194d53084SVikas Manocha #include <common.h>
294d53084SVikas Manocha #include <dm.h>
394d53084SVikas Manocha #include <dm/pinctrl.h>
477417102SVikas Manocha #include <asm/arch/gpio.h>
577417102SVikas Manocha #include <asm/gpio.h>
677417102SVikas Manocha #include <asm/io.h>
794d53084SVikas Manocha
894d53084SVikas Manocha DECLARE_GLOBAL_DATA_PTR;
994d53084SVikas Manocha
1058fb3c8dSVikas Manocha #define MAX_PINS_ONE_IP 70
1177417102SVikas Manocha #define MODE_BITS_MASK 3
1277417102SVikas Manocha #define OSPEED_MASK 3
1377417102SVikas Manocha #define PUPD_MASK 3
1477417102SVikas Manocha #define OTYPE_MSK 1
1577417102SVikas Manocha #define AFR_MASK 0xF
1677417102SVikas Manocha
stm32_gpio_config(struct gpio_desc * desc,const struct stm32_gpio_ctl * ctl)1777417102SVikas Manocha static int stm32_gpio_config(struct gpio_desc *desc,
1877417102SVikas Manocha const struct stm32_gpio_ctl *ctl)
1977417102SVikas Manocha {
2077417102SVikas Manocha struct stm32_gpio_priv *priv = dev_get_priv(desc->dev);
2177417102SVikas Manocha struct stm32_gpio_regs *regs = priv->regs;
2277417102SVikas Manocha u32 index;
2377417102SVikas Manocha
2477417102SVikas Manocha if (!ctl || ctl->af > 15 || ctl->mode > 3 || ctl->otype > 1 ||
2577417102SVikas Manocha ctl->pupd > 2 || ctl->speed > 3)
2677417102SVikas Manocha return -EINVAL;
2777417102SVikas Manocha
2877417102SVikas Manocha index = (desc->offset & 0x07) * 4;
2977417102SVikas Manocha clrsetbits_le32(®s->afr[desc->offset >> 3], AFR_MASK << index,
3077417102SVikas Manocha ctl->af << index);
3177417102SVikas Manocha
3277417102SVikas Manocha index = desc->offset * 2;
3377417102SVikas Manocha clrsetbits_le32(®s->moder, MODE_BITS_MASK << index,
3477417102SVikas Manocha ctl->mode << index);
3577417102SVikas Manocha clrsetbits_le32(®s->ospeedr, OSPEED_MASK << index,
3677417102SVikas Manocha ctl->speed << index);
3777417102SVikas Manocha clrsetbits_le32(®s->pupdr, PUPD_MASK << index, ctl->pupd << index);
3877417102SVikas Manocha
3977417102SVikas Manocha index = desc->offset;
4077417102SVikas Manocha clrsetbits_le32(®s->otyper, OTYPE_MSK << index, ctl->otype << index);
4177417102SVikas Manocha
4277417102SVikas Manocha return 0;
4377417102SVikas Manocha }
prep_gpio_dsc(struct stm32_gpio_dsc * gpio_dsc,u32 port_pin)4494d53084SVikas Manocha static int prep_gpio_dsc(struct stm32_gpio_dsc *gpio_dsc, u32 port_pin)
4594d53084SVikas Manocha {
4694d53084SVikas Manocha gpio_dsc->port = (port_pin & 0xF000) >> 12;
4794d53084SVikas Manocha gpio_dsc->pin = (port_pin & 0x0F00) >> 8;
4894d53084SVikas Manocha debug("%s: GPIO:port= %d, pin= %d\n", __func__, gpio_dsc->port,
4994d53084SVikas Manocha gpio_dsc->pin);
5094d53084SVikas Manocha
5194d53084SVikas Manocha return 0;
5294d53084SVikas Manocha }
5394d53084SVikas Manocha
prep_gpio_ctl(struct stm32_gpio_ctl * gpio_ctl,u32 gpio_fn,int node)5494d53084SVikas Manocha static int prep_gpio_ctl(struct stm32_gpio_ctl *gpio_ctl, u32 gpio_fn, int node)
5594d53084SVikas Manocha {
5694d53084SVikas Manocha gpio_fn &= 0x00FF;
5777417102SVikas Manocha gpio_ctl->af = 0;
5894d53084SVikas Manocha
5994d53084SVikas Manocha switch (gpio_fn) {
6094d53084SVikas Manocha case 0:
6194d53084SVikas Manocha gpio_ctl->mode = STM32_GPIO_MODE_IN;
6294d53084SVikas Manocha break;
6394d53084SVikas Manocha case 1 ... 16:
6494d53084SVikas Manocha gpio_ctl->mode = STM32_GPIO_MODE_AF;
6594d53084SVikas Manocha gpio_ctl->af = gpio_fn - 1;
6694d53084SVikas Manocha break;
6794d53084SVikas Manocha case 17:
6894d53084SVikas Manocha gpio_ctl->mode = STM32_GPIO_MODE_AN;
6994d53084SVikas Manocha break;
7094d53084SVikas Manocha default:
7194d53084SVikas Manocha gpio_ctl->mode = STM32_GPIO_MODE_OUT;
7294d53084SVikas Manocha break;
7394d53084SVikas Manocha }
7494d53084SVikas Manocha
7594d53084SVikas Manocha gpio_ctl->speed = fdtdec_get_int(gd->fdt_blob, node, "slew-rate", 0);
7694d53084SVikas Manocha
7794d53084SVikas Manocha if (fdtdec_get_bool(gd->fdt_blob, node, "drive-open-drain"))
7894d53084SVikas Manocha gpio_ctl->otype = STM32_GPIO_OTYPE_OD;
7994d53084SVikas Manocha else
8094d53084SVikas Manocha gpio_ctl->otype = STM32_GPIO_OTYPE_PP;
8194d53084SVikas Manocha
8294d53084SVikas Manocha if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-up"))
8394d53084SVikas Manocha gpio_ctl->pupd = STM32_GPIO_PUPD_UP;
8494d53084SVikas Manocha else if (fdtdec_get_bool(gd->fdt_blob, node, "bias-pull-down"))
8594d53084SVikas Manocha gpio_ctl->pupd = STM32_GPIO_PUPD_DOWN;
8694d53084SVikas Manocha else
8794d53084SVikas Manocha gpio_ctl->pupd = STM32_GPIO_PUPD_NO;
8894d53084SVikas Manocha
8994d53084SVikas Manocha debug("%s: gpio fn= %d, slew-rate= %x, op type= %x, pull-upd is = %x\n",
9094d53084SVikas Manocha __func__, gpio_fn, gpio_ctl->speed, gpio_ctl->otype,
9194d53084SVikas Manocha gpio_ctl->pupd);
9294d53084SVikas Manocha
9394d53084SVikas Manocha return 0;
9494d53084SVikas Manocha }
9594d53084SVikas Manocha
stm32_pinctrl_config(int offset)96ad0376e0SChristophe Kerello static int stm32_pinctrl_config(int offset)
9794d53084SVikas Manocha {
9858fb3c8dSVikas Manocha u32 pin_mux[MAX_PINS_ONE_IP];
9994d53084SVikas Manocha int rv, len;
10094d53084SVikas Manocha
10194d53084SVikas Manocha /*
10294d53084SVikas Manocha * check for "pinmux" property in each subnode (e.g. pins1 and pins2 for
10394d53084SVikas Manocha * usart1) of pin controller phandle "pinctrl-0"
10494d53084SVikas Manocha * */
105ad0376e0SChristophe Kerello fdt_for_each_subnode(offset, gd->fdt_blob, offset) {
10694d53084SVikas Manocha struct stm32_gpio_dsc gpio_dsc;
10794d53084SVikas Manocha struct stm32_gpio_ctl gpio_ctl;
10894d53084SVikas Manocha int i;
10994d53084SVikas Manocha
110ad0376e0SChristophe Kerello len = fdtdec_get_int_array_count(gd->fdt_blob, offset,
11194d53084SVikas Manocha "pinmux", pin_mux,
11294d53084SVikas Manocha ARRAY_SIZE(pin_mux));
113ad0376e0SChristophe Kerello debug("%s: no of pinmux entries= %d\n", __func__, len);
11494d53084SVikas Manocha if (len < 0)
11594d53084SVikas Manocha return -EINVAL;
11694d53084SVikas Manocha for (i = 0; i < len; i++) {
117280057bdSVikas Manocha struct gpio_desc desc;
11894d53084SVikas Manocha debug("%s: pinmux = %x\n", __func__, *(pin_mux + i));
11994d53084SVikas Manocha prep_gpio_dsc(&gpio_dsc, *(pin_mux + i));
120ad0376e0SChristophe Kerello prep_gpio_ctl(&gpio_ctl, *(pin_mux + i), offset);
121280057bdSVikas Manocha rv = uclass_get_device_by_seq(UCLASS_GPIO,
122280057bdSVikas Manocha gpio_dsc.port, &desc.dev);
123280057bdSVikas Manocha if (rv)
124280057bdSVikas Manocha return rv;
125280057bdSVikas Manocha desc.offset = gpio_dsc.pin;
126280057bdSVikas Manocha rv = stm32_gpio_config(&desc, &gpio_ctl);
12794d53084SVikas Manocha debug("%s: rv = %d\n\n", __func__, rv);
12894d53084SVikas Manocha if (rv)
12994d53084SVikas Manocha return rv;
13094d53084SVikas Manocha }
13194d53084SVikas Manocha }
13294d53084SVikas Manocha
13394d53084SVikas Manocha return 0;
13494d53084SVikas Manocha }
13594d53084SVikas Manocha
136bb44b968SChristophe Kerello #if CONFIG_IS_ENABLED(PINCTRL_FULL)
stm32_pinctrl_set_state(struct udevice * dev,struct udevice * config)137bb44b968SChristophe Kerello static int stm32_pinctrl_set_state(struct udevice *dev, struct udevice *config)
138bb44b968SChristophe Kerello {
139bb44b968SChristophe Kerello return stm32_pinctrl_config(dev_of_offset(config));
140bb44b968SChristophe Kerello }
141bb44b968SChristophe Kerello #else /* PINCTRL_FULL */
stm32_pinctrl_set_state_simple(struct udevice * dev,struct udevice * periph)142ad0376e0SChristophe Kerello static int stm32_pinctrl_set_state_simple(struct udevice *dev,
143ad0376e0SChristophe Kerello struct udevice *periph)
144ad0376e0SChristophe Kerello {
145ad0376e0SChristophe Kerello const void *fdt = gd->fdt_blob;
146ad0376e0SChristophe Kerello const fdt32_t *list;
147ad0376e0SChristophe Kerello uint32_t phandle;
148ad0376e0SChristophe Kerello int config_node;
149ad0376e0SChristophe Kerello int size, i, ret;
150ad0376e0SChristophe Kerello
151ad0376e0SChristophe Kerello list = fdt_getprop(fdt, dev_of_offset(periph), "pinctrl-0", &size);
152ad0376e0SChristophe Kerello if (!list)
153ad0376e0SChristophe Kerello return -EINVAL;
154ad0376e0SChristophe Kerello
155ad0376e0SChristophe Kerello debug("%s: periph->name = %s\n", __func__, periph->name);
156ad0376e0SChristophe Kerello
157ad0376e0SChristophe Kerello size /= sizeof(*list);
158ad0376e0SChristophe Kerello for (i = 0; i < size; i++) {
159ad0376e0SChristophe Kerello phandle = fdt32_to_cpu(*list++);
160ad0376e0SChristophe Kerello
161ad0376e0SChristophe Kerello config_node = fdt_node_offset_by_phandle(fdt, phandle);
162ad0376e0SChristophe Kerello if (config_node < 0) {
163*90aa625cSMasahiro Yamada pr_err("prop pinctrl-0 index %d invalid phandle\n", i);
164ad0376e0SChristophe Kerello return -EINVAL;
165ad0376e0SChristophe Kerello }
166ad0376e0SChristophe Kerello
167ad0376e0SChristophe Kerello ret = stm32_pinctrl_config(config_node);
168ad0376e0SChristophe Kerello if (ret)
169ad0376e0SChristophe Kerello return ret;
170ad0376e0SChristophe Kerello }
171ad0376e0SChristophe Kerello
172ad0376e0SChristophe Kerello return 0;
173ad0376e0SChristophe Kerello }
174bb44b968SChristophe Kerello #endif /* PINCTRL_FULL */
175ad0376e0SChristophe Kerello
17694d53084SVikas Manocha static struct pinctrl_ops stm32_pinctrl_ops = {
177bb44b968SChristophe Kerello #if CONFIG_IS_ENABLED(PINCTRL_FULL)
178bb44b968SChristophe Kerello .set_state = stm32_pinctrl_set_state,
179bb44b968SChristophe Kerello #else /* PINCTRL_FULL */
18094d53084SVikas Manocha .set_state_simple = stm32_pinctrl_set_state_simple,
181bb44b968SChristophe Kerello #endif /* PINCTRL_FULL */
18294d53084SVikas Manocha };
18394d53084SVikas Manocha
18494d53084SVikas Manocha static const struct udevice_id stm32_pinctrl_ids[] = {
18594d53084SVikas Manocha { .compatible = "st,stm32f746-pinctrl" },
18694d53084SVikas Manocha { }
18794d53084SVikas Manocha };
18894d53084SVikas Manocha
18994d53084SVikas Manocha U_BOOT_DRIVER(pinctrl_stm32) = {
19094d53084SVikas Manocha .name = "pinctrl_stm32",
19194d53084SVikas Manocha .id = UCLASS_PINCTRL,
19294d53084SVikas Manocha .of_match = stm32_pinctrl_ids,
19394d53084SVikas Manocha .ops = &stm32_pinctrl_ops,
19494d53084SVikas Manocha .bind = dm_scan_fdt_dev,
19594d53084SVikas Manocha };
196