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 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 } 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 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 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 136*bb44b968SChristophe Kerello #if CONFIG_IS_ENABLED(PINCTRL_FULL) 137*bb44b968SChristophe Kerello static int stm32_pinctrl_set_state(struct udevice *dev, struct udevice *config) 138*bb44b968SChristophe Kerello { 139*bb44b968SChristophe Kerello return stm32_pinctrl_config(dev_of_offset(config)); 140*bb44b968SChristophe Kerello } 141*bb44b968SChristophe Kerello #else /* PINCTRL_FULL */ 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) { 163ad0376e0SChristophe Kerello error("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 } 174*bb44b968SChristophe Kerello #endif /* PINCTRL_FULL */ 175ad0376e0SChristophe Kerello 17694d53084SVikas Manocha static struct pinctrl_ops stm32_pinctrl_ops = { 177*bb44b968SChristophe Kerello #if CONFIG_IS_ENABLED(PINCTRL_FULL) 178*bb44b968SChristophe Kerello .set_state = stm32_pinctrl_set_state, 179*bb44b968SChristophe Kerello #else /* PINCTRL_FULL */ 18094d53084SVikas Manocha .set_state_simple = stm32_pinctrl_set_state_simple, 181*bb44b968SChristophe 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