Commit 64e21add authored by Claudiu Beznea's avatar Claudiu Beznea Committed by Linus Walleij
Browse files

pinctrl: at91: add slewrate support for SAM9X60



Add slew rate support for SAM9X60 pin controller.

Signed-off-by: default avatarClaudiu Beznea <claudiu.beznea@microchip.com>
Acked-by: default avatarLudovic Desroches <ludovic.desroches@microchip.com>
Signed-off-by: default avatarLinus Walleij <linus.walleij@linaro.org>
parent fde84f19
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -59,6 +59,9 @@ static int gpio_banks;
#define OUTPUT		(1 << 7)
#define OUTPUT_VAL_SHIFT	8
#define OUTPUT_VAL	(0x1 << OUTPUT_VAL_SHIFT)
#define SLEWRATE_SHIFT	9
#define SLEWRATE_MASK	0x1
#define SLEWRATE	(SLEWRATE_MASK << SLEWRATE_SHIFT)
#define DEBOUNCE	(1 << 16)
#define DEBOUNCE_VAL_SHIFT	17
#define DEBOUNCE_VAL	(0x3fff << DEBOUNCE_VAL_SHIFT)
@@ -82,6 +85,13 @@ enum drive_strength_bit {
#define DRIVE_STRENGTH_BIT_MSK(name)	(DRIVE_STRENGTH_BIT_##name << \
					 DRIVE_STRENGTH_SHIFT)

enum slewrate_bit {
	SLEWRATE_BIT_DIS,
	SLEWRATE_BIT_ENA,
};

#define SLEWRATE_BIT_MSK(name)		(SLEWRATE_BIT_##name << SLEWRATE_SHIFT)

/**
 * struct at91_pmx_func - describes AT91 pinmux functions
 * @name: the name of this specific function
@@ -171,6 +181,8 @@ struct at91_pinctrl_mux_ops {
	unsigned (*get_drivestrength)(void __iomem *pio, unsigned pin);
	void (*set_drivestrength)(void __iomem *pio, unsigned pin,
					u32 strength);
	unsigned (*get_slewrate)(void __iomem *pio, unsigned pin);
	void (*set_slewrate)(void __iomem *pio, unsigned pin, u32 slewrate);
	/* irq */
	int (*irq_type)(struct irq_data *d, unsigned type);
};
@@ -585,6 +597,16 @@ static unsigned at91_mux_sam9x60_get_drivestrength(void __iomem *pio,
	return DRIVE_STRENGTH_BIT_LOW;
}

static unsigned at91_mux_sam9x60_get_slewrate(void __iomem *pio, unsigned pin)
{
	unsigned tmp = readl_relaxed(pio + SAM9X60_PIO_SLEWR);

	if ((tmp & BIT(pin)))
		return SLEWRATE_BIT_ENA;

	return SLEWRATE_BIT_DIS;
}

static void set_drive_strength(void __iomem *reg, unsigned pin, u32 strength)
{
	unsigned tmp = readl_relaxed(reg);
@@ -643,6 +665,24 @@ static void at91_mux_sam9x60_set_drivestrength(void __iomem *pio, unsigned pin,
	writel_relaxed(tmp, pio + SAM9X60_PIO_DRIVER1);
}

static void at91_mux_sam9x60_set_slewrate(void __iomem *pio, unsigned pin,
					  u32 setting)
{
	unsigned int tmp;

	if (setting < SLEWRATE_BIT_DIS || setting > SLEWRATE_BIT_ENA)
		return;

	tmp = readl_relaxed(pio + SAM9X60_PIO_SLEWR);

	if (setting == SLEWRATE_BIT_DIS)
		tmp &= ~BIT(pin);
	else
		tmp |= BIT(pin);

	writel_relaxed(tmp, pio + SAM9X60_PIO_SLEWR);
}

static struct at91_pinctrl_mux_ops at91rm9200_ops = {
	.get_periph	= at91_mux_get_periph,
	.mux_A_periph	= at91_mux_set_A_periph,
@@ -687,6 +727,8 @@ static const struct at91_pinctrl_mux_ops sam9x60_ops = {
	.disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
	.get_drivestrength = at91_mux_sam9x60_get_drivestrength,
	.set_drivestrength = at91_mux_sam9x60_set_drivestrength,
	.get_slewrate   = at91_mux_sam9x60_get_slewrate,
	.set_slewrate   = at91_mux_sam9x60_set_slewrate,
	.irq_type	= alt_gpio_irq_type,

};
@@ -950,6 +992,8 @@ static int at91_pinconf_get(struct pinctrl_dev *pctldev,
	if (info->ops->get_drivestrength)
		*config |= (info->ops->get_drivestrength(pio, pin)
				<< DRIVE_STRENGTH_SHIFT);
	if (info->ops->get_slewrate)
		*config |= (info->ops->get_slewrate(pio, pin) << SLEWRATE_SHIFT);
	if (at91_mux_get_output(pio, pin, &out))
		*config |= OUTPUT | (out << OUTPUT_VAL_SHIFT);

@@ -1001,6 +1045,9 @@ static int at91_pinconf_set(struct pinctrl_dev *pctldev,
			info->ops->set_drivestrength(pio, pin,
				(config & DRIVE_STRENGTH)
					>> DRIVE_STRENGTH_SHIFT);
		if (info->ops->set_slewrate)
			info->ops->set_slewrate(pio, pin,
				(config & SLEWRATE) >> SLEWRATE_SHIFT);

	} /* for each config */

@@ -1044,6 +1091,7 @@ static void at91_pinconf_dbg_show(struct pinctrl_dev *pctldev,
			     DRIVE_STRENGTH_MED);
	DBG_SHOW_FLAG_MASKED(DRIVE_STRENGTH, DRIVE_STRENGTH_BIT_MSK(HI),
			     DRIVE_STRENGTH_HI);
	DBG_SHOW_FLAG(SLEWRATE);
	DBG_SHOW_FLAG(DEBOUNCE);
	if (config & DEBOUNCE) {
		val = config >> DEBOUNCE_VAL_SHIFT;
+1 −0
Original line number Diff line number Diff line
@@ -69,6 +69,7 @@
#define AT91SAM9X5_PIO_DRIVER1	0x114  /*PIO Driver 1 register offset*/
#define AT91SAM9X5_PIO_DRIVER2	0x118  /*PIO Driver 2 register offset*/

#define SAM9X60_PIO_SLEWR	0x110	/* PIO Slew Rate Control Register */
#define SAM9X60_PIO_DRIVER1	0x118	/* PIO Driver 1 register offset */

#endif
+4 −0
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
#define AT91_PINCTRL_DIS_SCHMIT		(1 << 4)
#define AT91_PINCTRL_OUTPUT		(1 << 7)
#define AT91_PINCTRL_OUTPUT_VAL(x)	((x & 0x1) << 8)
#define AT91_PINCTRL_SLEWRATE		(1 << 9)
#define AT91_PINCTRL_DEBOUNCE		(1 << 16)
#define AT91_PINCTRL_DEBOUNCE_VAL(x)	(x << 17)

@@ -27,6 +28,9 @@
#define AT91_PINCTRL_DRIVE_STRENGTH_MED			(0x2 << 5)
#define AT91_PINCTRL_DRIVE_STRENGTH_HI			(0x3 << 5)

#define AT91_PINCTRL_SLEWRATE_DIS	(0x0 << 9)
#define AT91_PINCTRL_SLEWRATE_ENA	(0x1 << 9)

#define AT91_PIOA	0
#define AT91_PIOB	1
#define AT91_PIOC	2