1*83d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
29319a756SWenyou Yang /*
39319a756SWenyou Yang  * Atmel PIO pinctrl driver
49319a756SWenyou Yang  *
59319a756SWenyou Yang  * Copyright (C) 2016 Atmel Corporation
69319a756SWenyou Yang  *               Wenyou.Yang <wenyou.yang@atmel.com>
79319a756SWenyou Yang  */
89319a756SWenyou Yang 
99319a756SWenyou Yang #include <common.h>
109d922450SSimon Glass #include <dm.h>
119319a756SWenyou Yang #include <dm/pinctrl.h>
12e61ed48fSWenyou Yang #include <asm/hardware.h>
139319a756SWenyou Yang #include <linux/io.h>
149319a756SWenyou Yang #include <linux/err.h>
159319a756SWenyou Yang #include <mach/at91_pio.h>
169319a756SWenyou Yang 
179319a756SWenyou Yang DECLARE_GLOBAL_DATA_PTR;
189319a756SWenyou Yang 
199319a756SWenyou Yang #define MAX_GPIO_BANKS		5
209319a756SWenyou Yang #define MAX_NB_GPIO_PER_BANK	32
219319a756SWenyou Yang 
229319a756SWenyou Yang #define MAX_PINMUX_ENTRIES	200
239319a756SWenyou Yang 
249319a756SWenyou Yang struct at91_pinctrl_priv {
259319a756SWenyou Yang 	struct at91_port *reg_base[MAX_GPIO_BANKS];
269319a756SWenyou Yang 	u32 nbanks;
279319a756SWenyou Yang };
289319a756SWenyou Yang 
299319a756SWenyou Yang #define PULL_UP			BIT(0)
309319a756SWenyou Yang #define MULTI_DRIVE		BIT(1)
319319a756SWenyou Yang #define DEGLITCH		BIT(2)
329319a756SWenyou Yang #define PULL_DOWN		BIT(3)
339319a756SWenyou Yang #define DIS_SCHMIT		BIT(4)
349319a756SWenyou Yang #define DRIVE_STRENGTH_SHIFT	5
359319a756SWenyou Yang #define DRIVE_STRENGTH_MASK	0x3
369319a756SWenyou Yang #define DRIVE_STRENGTH		(DRIVE_STRENGTH_MASK << DRIVE_STRENGTH_SHIFT)
379319a756SWenyou Yang #define OUTPUT			BIT(7)
389319a756SWenyou Yang #define OUTPUT_VAL_SHIFT	8
399319a756SWenyou Yang #define OUTPUT_VAL		(0x1 << OUTPUT_VAL_SHIFT)
409319a756SWenyou Yang #define DEBOUNCE		BIT(16)
419319a756SWenyou Yang #define DEBOUNCE_VAL_SHIFT	17
429319a756SWenyou Yang #define DEBOUNCE_VAL		(0x3fff << DEBOUNCE_VAL_SHIFT)
439319a756SWenyou Yang 
449319a756SWenyou Yang /**
459319a756SWenyou Yang  * These defines will translated the dt binding settings to our internal
469319a756SWenyou Yang  * settings. They are not necessarily the same value as the register setting.
479319a756SWenyou Yang  * The actual drive strength current of low, medium and high must be looked up
489319a756SWenyou Yang  * from the corresponding device datasheet. This value is different for pins
499319a756SWenyou Yang  * that are even in the same banks. It is also dependent on VCC.
509319a756SWenyou Yang  * DRIVE_STRENGTH_DEFAULT is just a placeholder to avoid changing the drive
519319a756SWenyou Yang  * strength when there is no dt config for it.
529319a756SWenyou Yang  */
539319a756SWenyou Yang #define DRIVE_STRENGTH_DEFAULT	(0 << DRIVE_STRENGTH_SHIFT)
549319a756SWenyou Yang #define DRIVE_STRENGTH_LOW	(1 << DRIVE_STRENGTH_SHIFT)
559319a756SWenyou Yang #define DRIVE_STRENGTH_MED	(2 << DRIVE_STRENGTH_SHIFT)
569319a756SWenyou Yang #define DRIVE_STRENGTH_HI	(3 << DRIVE_STRENGTH_SHIFT)
579319a756SWenyou Yang 
589319a756SWenyou Yang enum at91_mux {
599319a756SWenyou Yang 	AT91_MUX_GPIO = 0,
609319a756SWenyou Yang 	AT91_MUX_PERIPH_A = 1,
619319a756SWenyou Yang 	AT91_MUX_PERIPH_B = 2,
629319a756SWenyou Yang 	AT91_MUX_PERIPH_C = 3,
639319a756SWenyou Yang 	AT91_MUX_PERIPH_D = 4,
649319a756SWenyou Yang };
659319a756SWenyou Yang 
669319a756SWenyou Yang /**
679319a756SWenyou Yang  * struct at91_pinctrl_mux_ops - describes an AT91 mux ops group
689319a756SWenyou Yang  * on new IP with support for periph C and D the way to mux in
699319a756SWenyou Yang  * periph A and B has changed
709319a756SWenyou Yang  * So provide the right callbacks
719319a756SWenyou Yang  * if not present means the IP does not support it
729319a756SWenyou Yang  * @mux_A_periph: assign the corresponding pin to the peripheral A function.
739319a756SWenyou Yang  * @mux_B_periph: assign the corresponding pin to the peripheral B function.
749319a756SWenyou Yang  * @mux_C_periph: assign the corresponding pin to the peripheral C function.
759319a756SWenyou Yang  * @mux_D_periph: assign the corresponding pin to the peripheral D function.
769319a756SWenyou Yang  * @set_deglitch: enable/disable the deglitch feature.
779319a756SWenyou Yang  * @set_debounce: enable/disable the debounce feature.
789319a756SWenyou Yang  * @set_pulldown: enable/disable the pulldown feature.
799319a756SWenyou Yang  * @disable_schmitt_trig: disable schmitt trigger
809319a756SWenyou Yang  */
819319a756SWenyou Yang struct at91_pinctrl_mux_ops {
829319a756SWenyou Yang 	void (*mux_A_periph)(struct at91_port *pio, u32 mask);
839319a756SWenyou Yang 	void (*mux_B_periph)(struct at91_port *pio, u32 mask);
849319a756SWenyou Yang 	void (*mux_C_periph)(struct at91_port *pio, u32 mask);
859319a756SWenyou Yang 	void (*mux_D_periph)(struct at91_port *pio, u32 mask);
869319a756SWenyou Yang 	void (*set_deglitch)(struct at91_port *pio, u32 mask, bool is_on);
879319a756SWenyou Yang 	void (*set_debounce)(struct at91_port *pio, u32 mask, bool is_on,
889319a756SWenyou Yang 			     u32 div);
899319a756SWenyou Yang 	void (*set_pulldown)(struct at91_port *pio, u32 mask, bool is_on);
909319a756SWenyou Yang 	void (*disable_schmitt_trig)(struct at91_port *pio, u32 mask);
919319a756SWenyou Yang 	void (*set_drivestrength)(struct at91_port *pio, u32 pin,
929319a756SWenyou Yang 				  u32 strength);
939319a756SWenyou Yang };
949319a756SWenyou Yang 
two_bit_pin_value_shift_amount(u32 pin)959319a756SWenyou Yang static u32 two_bit_pin_value_shift_amount(u32 pin)
969319a756SWenyou Yang {
979319a756SWenyou Yang 	/* return the shift value for a pin for "two bit" per pin registers,
989319a756SWenyou Yang 	 * i.e. drive strength */
999319a756SWenyou Yang 	return 2 * ((pin >= MAX_NB_GPIO_PER_BANK/2)
1009319a756SWenyou Yang 			? pin - MAX_NB_GPIO_PER_BANK/2 : pin);
1019319a756SWenyou Yang }
1029319a756SWenyou Yang 
at91_mux_disable_interrupt(struct at91_port * pio,u32 mask)1039319a756SWenyou Yang static void at91_mux_disable_interrupt(struct at91_port *pio, u32 mask)
1049319a756SWenyou Yang {
1059319a756SWenyou Yang 	writel(mask, &pio->idr);
1069319a756SWenyou Yang }
1079319a756SWenyou Yang 
at91_mux_set_pullup(struct at91_port * pio,u32 mask,bool on)1089319a756SWenyou Yang static void at91_mux_set_pullup(struct at91_port *pio, u32 mask, bool on)
1099319a756SWenyou Yang {
1109319a756SWenyou Yang 	if (on)
1119319a756SWenyou Yang 		writel(mask, &pio->mux.pio3.ppddr);
1129319a756SWenyou Yang 
1139319a756SWenyou Yang 	writel(mask, (on ? &pio->puer : &pio->pudr));
1149319a756SWenyou Yang }
1159319a756SWenyou Yang 
at91_mux_set_output(struct at91_port * pio,unsigned mask,bool is_on,bool val)1169319a756SWenyou Yang static void at91_mux_set_output(struct at91_port *pio, unsigned mask,
1179319a756SWenyou Yang 				bool is_on, bool val)
1189319a756SWenyou Yang {
1199319a756SWenyou Yang 	writel(mask, (val ? &pio->sodr : &pio->codr));
1209319a756SWenyou Yang 	writel(mask, (is_on ? &pio->oer : &pio->odr));
1219319a756SWenyou Yang }
1229319a756SWenyou Yang 
at91_mux_set_multidrive(struct at91_port * pio,u32 mask,bool on)1239319a756SWenyou Yang static void at91_mux_set_multidrive(struct at91_port *pio, u32 mask, bool on)
1249319a756SWenyou Yang {
1259319a756SWenyou Yang 	writel(mask, (on ? &pio->mder : &pio->mddr));
1269319a756SWenyou Yang }
1279319a756SWenyou Yang 
at91_mux_set_A_periph(struct at91_port * pio,u32 mask)1289319a756SWenyou Yang static void at91_mux_set_A_periph(struct at91_port *pio, u32 mask)
1299319a756SWenyou Yang {
1309319a756SWenyou Yang 	writel(mask, &pio->mux.pio2.asr);
1319319a756SWenyou Yang }
1329319a756SWenyou Yang 
at91_mux_set_B_periph(struct at91_port * pio,u32 mask)1339319a756SWenyou Yang static void at91_mux_set_B_periph(struct at91_port *pio, u32 mask)
1349319a756SWenyou Yang {
1359319a756SWenyou Yang 	writel(mask, &pio->mux.pio2.bsr);
1369319a756SWenyou Yang }
1379319a756SWenyou Yang 
at91_mux_pio3_set_A_periph(struct at91_port * pio,u32 mask)1389319a756SWenyou Yang static void at91_mux_pio3_set_A_periph(struct at91_port *pio, u32 mask)
1399319a756SWenyou Yang {
1409319a756SWenyou Yang 	writel(readl(&pio->mux.pio3.abcdsr1) & ~mask, &pio->mux.pio3.abcdsr1);
1419319a756SWenyou Yang 	writel(readl(&pio->mux.pio3.abcdsr2) & ~mask, &pio->mux.pio3.abcdsr2);
1429319a756SWenyou Yang }
1439319a756SWenyou Yang 
at91_mux_pio3_set_B_periph(struct at91_port * pio,u32 mask)1449319a756SWenyou Yang static void at91_mux_pio3_set_B_periph(struct at91_port *pio, u32 mask)
1459319a756SWenyou Yang {
1469319a756SWenyou Yang 	writel(readl(&pio->mux.pio3.abcdsr1) | mask, &pio->mux.pio3.abcdsr1);
1479319a756SWenyou Yang 	writel(readl(&pio->mux.pio3.abcdsr2) & ~mask, &pio->mux.pio3.abcdsr2);
1489319a756SWenyou Yang }
1499319a756SWenyou Yang 
at91_mux_pio3_set_C_periph(struct at91_port * pio,u32 mask)1509319a756SWenyou Yang static void at91_mux_pio3_set_C_periph(struct at91_port *pio, u32 mask)
1519319a756SWenyou Yang {
1529319a756SWenyou Yang 	writel(readl(&pio->mux.pio3.abcdsr1) & ~mask, &pio->mux.pio3.abcdsr1);
1539319a756SWenyou Yang 	writel(readl(&pio->mux.pio3.abcdsr2) | mask, &pio->mux.pio3.abcdsr2);
1549319a756SWenyou Yang }
1559319a756SWenyou Yang 
at91_mux_pio3_set_D_periph(struct at91_port * pio,u32 mask)1569319a756SWenyou Yang static void at91_mux_pio3_set_D_periph(struct at91_port *pio, u32 mask)
1579319a756SWenyou Yang {
1589319a756SWenyou Yang 	writel(readl(&pio->mux.pio3.abcdsr1) | mask, &pio->mux.pio3.abcdsr1);
1599319a756SWenyou Yang 	writel(readl(&pio->mux.pio3.abcdsr2) | mask, &pio->mux.pio3.abcdsr2);
1609319a756SWenyou Yang }
1619319a756SWenyou Yang 
at91_mux_set_deglitch(struct at91_port * pio,u32 mask,bool is_on)1629319a756SWenyou Yang static void at91_mux_set_deglitch(struct at91_port *pio, u32 mask, bool is_on)
1639319a756SWenyou Yang {
1649319a756SWenyou Yang 	writel(mask, (is_on ? &pio->ifer : &pio->ifdr));
1659319a756SWenyou Yang }
1669319a756SWenyou Yang 
at91_mux_pio3_set_deglitch(struct at91_port * pio,u32 mask,bool is_on)1679319a756SWenyou Yang static void at91_mux_pio3_set_deglitch(struct at91_port *pio,
1689319a756SWenyou Yang 				       u32 mask, bool is_on)
1699319a756SWenyou Yang {
1709319a756SWenyou Yang 	if (is_on)
1719319a756SWenyou Yang 		writel(mask, &pio->mux.pio3.ifscdr);
1729319a756SWenyou Yang 	at91_mux_set_deglitch(pio, mask, is_on);
1739319a756SWenyou Yang }
1749319a756SWenyou Yang 
at91_mux_pio3_set_debounce(struct at91_port * pio,u32 mask,bool is_on,u32 div)1759319a756SWenyou Yang static void at91_mux_pio3_set_debounce(struct at91_port *pio, u32 mask,
1769319a756SWenyou Yang 				       bool is_on, u32 div)
1779319a756SWenyou Yang {
1789319a756SWenyou Yang 	if (is_on) {
1799319a756SWenyou Yang 		writel(mask, &pio->mux.pio3.ifscer);
1809319a756SWenyou Yang 		writel(div & PIO_SCDR_DIV, &pio->mux.pio3.scdr);
1819319a756SWenyou Yang 		writel(mask, &pio->ifer);
1829319a756SWenyou Yang 	} else {
1839319a756SWenyou Yang 		writel(mask, &pio->mux.pio3.ifscdr);
1849319a756SWenyou Yang 	}
1859319a756SWenyou Yang }
1869319a756SWenyou Yang 
at91_mux_pio3_set_pulldown(struct at91_port * pio,u32 mask,bool is_on)1879319a756SWenyou Yang static void at91_mux_pio3_set_pulldown(struct at91_port *pio,
1889319a756SWenyou Yang 				       u32 mask, bool is_on)
1899319a756SWenyou Yang {
1909319a756SWenyou Yang 	if (is_on)
1919319a756SWenyou Yang 		writel(mask, &pio->pudr);
1929319a756SWenyou Yang 
1939319a756SWenyou Yang 	writel(mask, (is_on ? &pio->mux.pio3.ppder : &pio->mux.pio3.ppddr));
1949319a756SWenyou Yang }
1959319a756SWenyou Yang 
at91_mux_pio3_disable_schmitt_trig(struct at91_port * pio,u32 mask)1969319a756SWenyou Yang static void at91_mux_pio3_disable_schmitt_trig(struct at91_port *pio,
1979319a756SWenyou Yang 					       u32 mask)
1989319a756SWenyou Yang {
1999319a756SWenyou Yang 	writel(readl(&pio->schmitt) | mask, &pio->schmitt);
2009319a756SWenyou Yang }
2019319a756SWenyou Yang 
set_drive_strength(void * reg,u32 pin,u32 strength)2029319a756SWenyou Yang static void set_drive_strength(void *reg, u32 pin, u32 strength)
2039319a756SWenyou Yang {
2049319a756SWenyou Yang 	u32 shift = two_bit_pin_value_shift_amount(pin);
2059319a756SWenyou Yang 
2069319a756SWenyou Yang 	clrsetbits_le32(reg, DRIVE_STRENGTH_MASK << shift, strength << shift);
2079319a756SWenyou Yang }
2089319a756SWenyou Yang 
at91_mux_sama5d3_set_drivestrength(struct at91_port * pio,u32 pin,u32 setting)2099319a756SWenyou Yang static void at91_mux_sama5d3_set_drivestrength(struct at91_port *pio,
2109319a756SWenyou Yang 					       u32 pin, u32 setting)
2119319a756SWenyou Yang {
2129319a756SWenyou Yang 	void *reg;
2139319a756SWenyou Yang 
2149319a756SWenyou Yang 	reg = &pio->driver12;
2159319a756SWenyou Yang 	if (pin >= MAX_NB_GPIO_PER_BANK / 2)
2169319a756SWenyou Yang 		reg = &pio->driver2;
2179319a756SWenyou Yang 
2189319a756SWenyou Yang 	/* do nothing if setting is zero */
2199319a756SWenyou Yang 	if (!setting)
2209319a756SWenyou Yang 		return;
2219319a756SWenyou Yang 
2229319a756SWenyou Yang 	/* strength is 1 to 1 with setting for SAMA5 */
2239319a756SWenyou Yang 	set_drive_strength(reg, pin, setting);
2249319a756SWenyou Yang }
2259319a756SWenyou Yang 
at91_mux_sam9x5_set_drivestrength(struct at91_port * pio,u32 pin,u32 setting)2269319a756SWenyou Yang static void at91_mux_sam9x5_set_drivestrength(struct at91_port *pio,
2279319a756SWenyou Yang 					      u32 pin, u32 setting)
2289319a756SWenyou Yang {
2299319a756SWenyou Yang 	void *reg;
2309319a756SWenyou Yang 
2319319a756SWenyou Yang 	reg = &pio->driver1;
2329319a756SWenyou Yang 	if (pin >= MAX_NB_GPIO_PER_BANK / 2)
2339319a756SWenyou Yang 		reg = &pio->driver12;
2349319a756SWenyou Yang 
2359319a756SWenyou Yang 	/* do nothing if setting is zero */
2369319a756SWenyou Yang 	if (!setting)
2379319a756SWenyou Yang 		return;
2389319a756SWenyou Yang 
2399319a756SWenyou Yang 	/* strength is inverse on SAM9x5s with our defines
2409319a756SWenyou Yang 	 * 0 = hi, 1 = med, 2 = low, 3 = rsvd */
2419319a756SWenyou Yang 	setting = DRIVE_STRENGTH_HI - setting;
2429319a756SWenyou Yang 
2439319a756SWenyou Yang 	set_drive_strength(reg, pin, setting);
2449319a756SWenyou Yang }
2459319a756SWenyou Yang 
2469319a756SWenyou Yang static struct at91_pinctrl_mux_ops at91rm9200_ops = {
2479319a756SWenyou Yang 	.mux_A_periph	= at91_mux_set_A_periph,
2489319a756SWenyou Yang 	.mux_B_periph	= at91_mux_set_B_periph,
2499319a756SWenyou Yang 	.set_deglitch	= at91_mux_set_deglitch,
2509319a756SWenyou Yang };
2519319a756SWenyou Yang 
2529319a756SWenyou Yang static struct at91_pinctrl_mux_ops at91sam9x5_ops = {
2539319a756SWenyou Yang 	.mux_A_periph	= at91_mux_pio3_set_A_periph,
2549319a756SWenyou Yang 	.mux_B_periph	= at91_mux_pio3_set_B_periph,
2559319a756SWenyou Yang 	.mux_C_periph	= at91_mux_pio3_set_C_periph,
2569319a756SWenyou Yang 	.mux_D_periph	= at91_mux_pio3_set_D_periph,
2579319a756SWenyou Yang 	.set_deglitch	= at91_mux_pio3_set_deglitch,
2589319a756SWenyou Yang 	.set_debounce	= at91_mux_pio3_set_debounce,
2599319a756SWenyou Yang 	.set_pulldown	= at91_mux_pio3_set_pulldown,
2609319a756SWenyou Yang 	.disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
2619319a756SWenyou Yang 	.set_drivestrength = at91_mux_sam9x5_set_drivestrength,
2629319a756SWenyou Yang };
2639319a756SWenyou Yang 
2649319a756SWenyou Yang static struct at91_pinctrl_mux_ops sama5d3_ops = {
2659319a756SWenyou Yang 	.mux_A_periph	= at91_mux_pio3_set_A_periph,
2669319a756SWenyou Yang 	.mux_B_periph	= at91_mux_pio3_set_B_periph,
2679319a756SWenyou Yang 	.mux_C_periph	= at91_mux_pio3_set_C_periph,
2689319a756SWenyou Yang 	.mux_D_periph	= at91_mux_pio3_set_D_periph,
2699319a756SWenyou Yang 	.set_deglitch	= at91_mux_pio3_set_deglitch,
2709319a756SWenyou Yang 	.set_debounce	= at91_mux_pio3_set_debounce,
2719319a756SWenyou Yang 	.set_pulldown	= at91_mux_pio3_set_pulldown,
2729319a756SWenyou Yang 	.disable_schmitt_trig = at91_mux_pio3_disable_schmitt_trig,
2739319a756SWenyou Yang 	.set_drivestrength = at91_mux_sama5d3_set_drivestrength,
2749319a756SWenyou Yang };
2759319a756SWenyou Yang 
at91_mux_gpio_disable(struct at91_port * pio,u32 mask)2769319a756SWenyou Yang static void at91_mux_gpio_disable(struct at91_port *pio, u32 mask)
2779319a756SWenyou Yang {
2789319a756SWenyou Yang 	writel(mask, &pio->pdr);
2799319a756SWenyou Yang }
2809319a756SWenyou Yang 
at91_mux_gpio_enable(struct at91_port * pio,u32 mask,bool input)2819319a756SWenyou Yang static void at91_mux_gpio_enable(struct at91_port *pio, u32 mask, bool input)
2829319a756SWenyou Yang {
2839319a756SWenyou Yang 	writel(mask, &pio->per);
2849319a756SWenyou Yang 	writel(mask, (input ? &pio->odr : &pio->oer));
2859319a756SWenyou Yang }
2869319a756SWenyou Yang 
at91_pmx_set(struct at91_pinctrl_mux_ops * ops,struct at91_port * pio,u32 mask,enum at91_mux mux)2879319a756SWenyou Yang static int at91_pmx_set(struct at91_pinctrl_mux_ops *ops,
2889319a756SWenyou Yang 			struct at91_port *pio, u32 mask, enum at91_mux mux)
2899319a756SWenyou Yang {
2909319a756SWenyou Yang 	at91_mux_disable_interrupt(pio, mask);
2919319a756SWenyou Yang 	switch (mux) {
2929319a756SWenyou Yang 	case AT91_MUX_GPIO:
2939319a756SWenyou Yang 		at91_mux_gpio_enable(pio, mask, 1);
2949319a756SWenyou Yang 		break;
2959319a756SWenyou Yang 	case AT91_MUX_PERIPH_A:
2969319a756SWenyou Yang 		ops->mux_A_periph(pio, mask);
2979319a756SWenyou Yang 		break;
2989319a756SWenyou Yang 	case AT91_MUX_PERIPH_B:
2999319a756SWenyou Yang 		ops->mux_B_periph(pio, mask);
3009319a756SWenyou Yang 		break;
3019319a756SWenyou Yang 	case AT91_MUX_PERIPH_C:
3029319a756SWenyou Yang 		if (!ops->mux_C_periph)
3039319a756SWenyou Yang 			return -EINVAL;
3049319a756SWenyou Yang 		ops->mux_C_periph(pio, mask);
3059319a756SWenyou Yang 		break;
3069319a756SWenyou Yang 	case AT91_MUX_PERIPH_D:
3079319a756SWenyou Yang 		if (!ops->mux_D_periph)
3089319a756SWenyou Yang 			return -EINVAL;
3099319a756SWenyou Yang 		ops->mux_D_periph(pio, mask);
3109319a756SWenyou Yang 		break;
3119319a756SWenyou Yang 	}
3129319a756SWenyou Yang 	if (mux)
3139319a756SWenyou Yang 		at91_mux_gpio_disable(pio, mask);
3149319a756SWenyou Yang 
3159319a756SWenyou Yang 	return 0;
3169319a756SWenyou Yang }
3179319a756SWenyou Yang 
at91_pinconf_set(struct at91_pinctrl_mux_ops * ops,struct at91_port * pio,u32 pin,u32 config)3189319a756SWenyou Yang static int at91_pinconf_set(struct at91_pinctrl_mux_ops *ops,
3199319a756SWenyou Yang 			    struct at91_port *pio, u32 pin, u32 config)
3209319a756SWenyou Yang {
3219319a756SWenyou Yang 	u32 mask = BIT(pin);
3229319a756SWenyou Yang 
3239319a756SWenyou Yang 	if ((config & PULL_UP) && (config & PULL_DOWN))
3249319a756SWenyou Yang 		return -EINVAL;
3259319a756SWenyou Yang 
3269319a756SWenyou Yang 	at91_mux_set_output(pio, mask, config & OUTPUT,
3279319a756SWenyou Yang 			    (config & OUTPUT_VAL) >> OUTPUT_VAL_SHIFT);
3289319a756SWenyou Yang 	at91_mux_set_pullup(pio, mask, config & PULL_UP);
3299319a756SWenyou Yang 	at91_mux_set_multidrive(pio, mask, config & MULTI_DRIVE);
3309319a756SWenyou Yang 	if (ops->set_deglitch)
3319319a756SWenyou Yang 		ops->set_deglitch(pio, mask, config & DEGLITCH);
3329319a756SWenyou Yang 	if (ops->set_debounce)
3339319a756SWenyou Yang 		ops->set_debounce(pio, mask, config & DEBOUNCE,
3349319a756SWenyou Yang 			(config & DEBOUNCE_VAL) >> DEBOUNCE_VAL_SHIFT);
3359319a756SWenyou Yang 	if (ops->set_pulldown)
3369319a756SWenyou Yang 		ops->set_pulldown(pio, mask, config & PULL_DOWN);
3379319a756SWenyou Yang 	if (ops->disable_schmitt_trig && config & DIS_SCHMIT)
3389319a756SWenyou Yang 		ops->disable_schmitt_trig(pio, mask);
3399319a756SWenyou Yang 	if (ops->set_drivestrength)
3409319a756SWenyou Yang 		ops->set_drivestrength(pio, pin,
3419319a756SWenyou Yang 			(config & DRIVE_STRENGTH) >> DRIVE_STRENGTH_SHIFT);
3429319a756SWenyou Yang 
3439319a756SWenyou Yang 	return 0;
3449319a756SWenyou Yang }
3459319a756SWenyou Yang 
at91_pin_check_config(struct udevice * dev,u32 bank,u32 pin)3469319a756SWenyou Yang static int at91_pin_check_config(struct udevice *dev, u32 bank, u32 pin)
3479319a756SWenyou Yang {
3489319a756SWenyou Yang 	struct at91_pinctrl_priv *priv = dev_get_priv(dev);
3499319a756SWenyou Yang 
3509319a756SWenyou Yang 	if (bank >= priv->nbanks) {
3519319a756SWenyou Yang 		debug("pin conf bank %d >= nbanks %d\n", bank, priv->nbanks);
3529319a756SWenyou Yang 		return -EINVAL;
3539319a756SWenyou Yang 	}
3549319a756SWenyou Yang 
3559319a756SWenyou Yang 	if (pin >= MAX_NB_GPIO_PER_BANK) {
3569319a756SWenyou Yang 		debug("pin conf pin %d >= %d\n", pin, MAX_NB_GPIO_PER_BANK);
3579319a756SWenyou Yang 		return -EINVAL;
3589319a756SWenyou Yang 	}
3599319a756SWenyou Yang 
3609319a756SWenyou Yang 	return 0;
3619319a756SWenyou Yang }
3629319a756SWenyou Yang 
at91_pinctrl_set_state(struct udevice * dev,struct udevice * config)3639319a756SWenyou Yang static int at91_pinctrl_set_state(struct udevice *dev, struct udevice *config)
3649319a756SWenyou Yang {
3659319a756SWenyou Yang 	struct at91_pinctrl_priv *priv = dev_get_priv(dev);
3669319a756SWenyou Yang 	const void *blob = gd->fdt_blob;
367da409cccSSimon Glass 	int node = dev_of_offset(config);
3689319a756SWenyou Yang 	u32 cells[MAX_PINMUX_ENTRIES];
3699319a756SWenyou Yang 	const u32 *list = cells;
3709319a756SWenyou Yang 	u32 bank, pin;
3719319a756SWenyou Yang 	u32 conf, mask, count, i;
3729319a756SWenyou Yang 	int size;
3739319a756SWenyou Yang 	int ret;
3749319a756SWenyou Yang 	enum at91_mux mux;
3759319a756SWenyou Yang 	struct at91_port *pio;
3769319a756SWenyou Yang 	struct at91_pinctrl_mux_ops *ops =
3779319a756SWenyou Yang 			(struct at91_pinctrl_mux_ops *)dev_get_driver_data(dev);
3789319a756SWenyou Yang 
3799319a756SWenyou Yang 	/*
3809319a756SWenyou Yang 	 * the binding format is atmel,pins = <bank pin mux CONFIG ...>,
3819319a756SWenyou Yang 	 * do sanity check and calculate pins number
3829319a756SWenyou Yang 	 */
3839319a756SWenyou Yang 	size = fdtdec_get_int_array_count(blob, node, "atmel,pins",
3849319a756SWenyou Yang 					  cells, ARRAY_SIZE(cells));
3859319a756SWenyou Yang 
3869319a756SWenyou Yang 	/* we do not check return since it's safe node passed down */
3879319a756SWenyou Yang 	count = size >> 2;
3889319a756SWenyou Yang 	if (!count)
3899319a756SWenyou Yang 		return -EINVAL;
3909319a756SWenyou Yang 
3919319a756SWenyou Yang 	for (i = 0; i < count; i++) {
3929319a756SWenyou Yang 		bank = *list++;
3939319a756SWenyou Yang 		pin = *list++;
3949319a756SWenyou Yang 		mux = *list++;
3959319a756SWenyou Yang 		conf = *list++;
3969319a756SWenyou Yang 
3979319a756SWenyou Yang 		ret = at91_pin_check_config(dev, bank, pin);
3989319a756SWenyou Yang 		if (ret)
3999319a756SWenyou Yang 			return ret;
4009319a756SWenyou Yang 
4019319a756SWenyou Yang 		pio = priv->reg_base[bank];
4029319a756SWenyou Yang 		mask = BIT(pin);
4039319a756SWenyou Yang 
4049319a756SWenyou Yang 		ret = at91_pmx_set(ops, pio, mask, mux);
4059319a756SWenyou Yang 		if (ret)
4069319a756SWenyou Yang 			return ret;
4079319a756SWenyou Yang 
4089319a756SWenyou Yang 		ret = at91_pinconf_set(ops, pio, pin, conf);
4099319a756SWenyou Yang 		if (ret)
4109319a756SWenyou Yang 			return ret;
4119319a756SWenyou Yang 	}
4129319a756SWenyou Yang 
4139319a756SWenyou Yang 	return 0;
4149319a756SWenyou Yang }
4159319a756SWenyou Yang 
4169319a756SWenyou Yang const struct pinctrl_ops at91_pinctrl_ops  = {
4179319a756SWenyou Yang 	.set_state = at91_pinctrl_set_state,
4189319a756SWenyou Yang };
4199319a756SWenyou Yang 
at91_pinctrl_probe(struct udevice * dev)4209319a756SWenyou Yang static int at91_pinctrl_probe(struct udevice *dev)
4219319a756SWenyou Yang {
4229319a756SWenyou Yang 	struct at91_pinctrl_priv *priv = dev_get_priv(dev);
4239319a756SWenyou Yang 	fdt_addr_t addr_base;
4249319a756SWenyou Yang 	int index;
4259319a756SWenyou Yang 
4269319a756SWenyou Yang 	for (index = 0; index < MAX_GPIO_BANKS; index++) {
427a821c4afSSimon Glass 		addr_base = devfdt_get_addr_index(dev, index);
4289319a756SWenyou Yang 		if (addr_base == FDT_ADDR_T_NONE)
4299319a756SWenyou Yang 			break;
4309319a756SWenyou Yang 
4319319a756SWenyou Yang 		priv->reg_base[index] = (struct at91_port *)addr_base;
4329319a756SWenyou Yang 	}
4339319a756SWenyou Yang 
4349319a756SWenyou Yang 	priv->nbanks = index;
4359319a756SWenyou Yang 
4369319a756SWenyou Yang 	return 0;
4379319a756SWenyou Yang }
4389319a756SWenyou Yang 
4399319a756SWenyou Yang static const struct udevice_id at91_pinctrl_match[] = {
4409319a756SWenyou Yang 	{ .compatible = "atmel,sama5d3-pinctrl", .data = (ulong)&sama5d3_ops },
4419319a756SWenyou Yang 	{ .compatible = "atmel,at91sam9x5-pinctrl", .data = (ulong)&at91sam9x5_ops },
4429319a756SWenyou Yang 	{ .compatible = "atmel,at91rm9200-pinctrl", .data = (ulong)&at91rm9200_ops },
4439319a756SWenyou Yang 	{}
4449319a756SWenyou Yang };
4459319a756SWenyou Yang 
4469319a756SWenyou Yang U_BOOT_DRIVER(at91_pinctrl) = {
4479319a756SWenyou Yang 	.name = "pinctrl_at91",
4489319a756SWenyou Yang 	.id = UCLASS_PINCTRL,
4499319a756SWenyou Yang 	.of_match = at91_pinctrl_match,
4509319a756SWenyou Yang 	.probe = at91_pinctrl_probe,
4519319a756SWenyou Yang 	.priv_auto_alloc_size = sizeof(struct at91_pinctrl_priv),
4529319a756SWenyou Yang 	.ops = &at91_pinctrl_ops,
4539319a756SWenyou Yang };
454