xref: /openbmc/u-boot/drivers/pinctrl/pinctrl_stm32.c (revision 774171020beaf3af19dcc8056c9de38653bc121b)
1 #include <common.h>
2 #include <dm.h>
3 #include <dm/pinctrl.h>
4 #include <asm/arch/gpio.h>
5 #include <asm/gpio.h>
6 #include <asm/io.h>
7 
8 DECLARE_GLOBAL_DATA_PTR;
9 
10 #define MODE_BITS_MASK			3
11 #define OSPEED_MASK			3
12 #define PUPD_MASK			3
13 #define OTYPE_MSK			1
14 #define AFR_MASK			0xF
15 
16 static int stm32_gpio_config(struct gpio_desc *desc,
17 			     const struct stm32_gpio_ctl *ctl)
18 {
19 	struct stm32_gpio_priv *priv = dev_get_priv(desc->dev);
20 	struct stm32_gpio_regs *regs = priv->regs;
21 	u32 index;
22 
23 	if (!ctl || ctl->af > 15 || ctl->mode > 3 || ctl->otype > 1 ||
24 	    ctl->pupd > 2 || ctl->speed > 3)
25 		return -EINVAL;
26 
27 	index = (desc->offset & 0x07) * 4;
28 	clrsetbits_le32(&regs->afr[desc->offset >> 3], AFR_MASK << index,
29 			ctl->af << index);
30 
31 	index = desc->offset * 2;
32 	clrsetbits_le32(&regs->moder, MODE_BITS_MASK << index,
33 			ctl->mode << index);
34 	clrsetbits_le32(&regs->ospeedr, OSPEED_MASK << index,
35 			ctl->speed << index);
36 	clrsetbits_le32(&regs->pupdr, PUPD_MASK << index, ctl->pupd << index);
37 
38 	index = desc->offset;
39 	clrsetbits_le32(&regs->otyper, OTYPE_MSK << index, ctl->otype << index);
40 
41 	return 0;
42 }
43 static int prep_gpio_dsc(struct stm32_gpio_dsc *gpio_dsc, u32 port_pin)
44 {
45 	gpio_dsc->port = (port_pin & 0xF000) >> 12;
46 	gpio_dsc->pin = (port_pin & 0x0F00) >> 8;
47 	debug("%s: GPIO:port= %d, pin= %d\n", __func__, gpio_dsc->port,
48 	      gpio_dsc->pin);
49 
50 	return 0;
51 }
52 
53 static int prep_gpio_ctl(struct stm32_gpio_ctl *gpio_ctl, u32 gpio_fn, int node)
54 {
55 	gpio_fn &= 0x00FF;
56 	gpio_ctl->af = 0;
57 
58 	switch (gpio_fn) {
59 	case 0:
60 		gpio_ctl->mode = STM32_GPIO_MODE_IN;
61 		break;
62 	case 1 ... 16:
63 		gpio_ctl->mode = STM32_GPIO_MODE_AF;
64 		gpio_ctl->af = gpio_fn - 1;
65 		break;
66 	case 17:
67 		gpio_ctl->mode = STM32_GPIO_MODE_AN;
68 		break;
69 	default:
70 		gpio_ctl->mode = STM32_GPIO_MODE_OUT;
71 		break;
72 	}
73 
74 	gpio_ctl->speed = fdtdec_get_int(gd->fdt_blob, node, "slew-rate", 0);
75 
76 	if (fdtdec_get_bool(gd->fdt_blob, node, "drive-open-drain"))
77 		gpio_ctl->otype = STM32_GPIO_OTYPE_OD;
78 	else
79 		gpio_ctl->otype = STM32_GPIO_OTYPE_PP;
80 
81 	if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-up"))
82 		gpio_ctl->pupd = STM32_GPIO_PUPD_UP;
83 	else if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-down"))
84 		gpio_ctl->pupd = STM32_GPIO_PUPD_DOWN;
85 	else
86 		gpio_ctl->pupd = STM32_GPIO_PUPD_NO;
87 
88 	debug("%s: gpio fn= %d, slew-rate= %x, op type= %x, pull-upd is = %x\n",
89 	      __func__,  gpio_fn, gpio_ctl->speed, gpio_ctl->otype,
90 	     gpio_ctl->pupd);
91 
92 	return 0;
93 }
94 
95 static int stm32_pinctrl_set_state_simple(struct udevice *dev,
96 					  struct udevice *periph)
97 {
98 	u32 pin_mux[50];
99 	struct fdtdec_phandle_args args;
100 	int rv, len;
101 
102 	/* Get node pinctrl-0 */
103 	rv = fdtdec_parse_phandle_with_args(gd->fdt_blob, periph->of_offset,
104 					   "pinctrl-0", 0, 0, 0, &args);
105 	if (rv)
106 		return rv;
107 	/*
108 	 * check for "pinmux" property in each subnode (e.g. pins1 and pins2 for
109 	 * usart1) of pin controller phandle "pinctrl-0"
110 	 * */
111 	fdt_for_each_subnode(args.node, gd->fdt_blob, args.node) {
112 		struct stm32_gpio_dsc gpio_dsc;
113 		struct stm32_gpio_ctl gpio_ctl;
114 		int i;
115 
116 		len = fdtdec_get_int_array_count(gd->fdt_blob, args.node,
117 						 "pinmux", pin_mux,
118 						 ARRAY_SIZE(pin_mux));
119 		debug("%s: periph->name = %s, no of pinmux entries= %d\n",
120 		      __func__, periph->name, len);
121 		if (len < 0)
122 			return -EINVAL;
123 		for (i = 0; i < len; i++) {
124 			debug("%s: pinmux = %x\n", __func__, *(pin_mux + i));
125 			prep_gpio_dsc(&gpio_dsc, *(pin_mux + i));
126 			prep_gpio_ctl(&gpio_ctl, *(pin_mux + i), args.node);
127 
128 			rv = stm32_gpio_config(&gpio_dsc, &gpio_ctl);
129 			debug("%s: rv = %d\n\n", __func__, rv);
130 			if (rv)
131 				return rv;
132 		}
133 	}
134 
135 	return 0;
136 }
137 
138 static struct pinctrl_ops stm32_pinctrl_ops = {
139 	.set_state_simple	= stm32_pinctrl_set_state_simple,
140 };
141 
142 static const struct udevice_id stm32_pinctrl_ids[] = {
143 	{ .compatible = "st,stm32f746-pinctrl" },
144 	{ }
145 };
146 
147 U_BOOT_DRIVER(pinctrl_stm32) = {
148 	.name		= "pinctrl_stm32",
149 	.id		= UCLASS_PINCTRL,
150 	.of_match	= stm32_pinctrl_ids,
151 	.ops		= &stm32_pinctrl_ops,
152 	.bind		= dm_scan_fdt_dev,
153 };
154