183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
277417102SVikas Manocha /*
33bc599c9SPatrice Chotard * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
43bc599c9SPatrice Chotard * Author(s): Vikas Manocha, <vikas.manocha@st.com> for STMicroelectronics.
577417102SVikas Manocha */
677417102SVikas Manocha
777417102SVikas Manocha #include <common.h>
877417102SVikas Manocha #include <clk.h>
977417102SVikas Manocha #include <dm.h>
1077417102SVikas Manocha #include <fdtdec.h>
1177417102SVikas Manocha #include <asm/arch/gpio.h>
1277417102SVikas Manocha #include <asm/arch/stm32.h>
1377417102SVikas Manocha #include <asm/gpio.h>
1477417102SVikas Manocha #include <asm/io.h>
1577417102SVikas Manocha #include <linux/errno.h>
1677417102SVikas Manocha #include <linux/io.h>
1777417102SVikas Manocha
1877417102SVikas Manocha #define MODE_BITS(gpio_pin) (gpio_pin * 2)
1977417102SVikas Manocha #define MODE_BITS_MASK 3
20798cd708SPatrice Chotard #define BSRR_BIT(gpio_pin, value) BIT(gpio_pin + (value ? 0 : 16))
2177417102SVikas Manocha
22*4fb22463SPatrice Chotard #ifndef CONFIG_SPL_BUILD
23dbf928ddSPatrice Chotard /*
24dbf928ddSPatrice Chotard * convert gpio offset to gpio index taking into account gpio holes
25dbf928ddSPatrice Chotard * into gpio bank
26dbf928ddSPatrice Chotard */
stm32_offset_to_index(struct udevice * dev,unsigned int offset)27dbf928ddSPatrice Chotard int stm32_offset_to_index(struct udevice *dev, unsigned int offset)
28dbf928ddSPatrice Chotard {
29dbf928ddSPatrice Chotard struct stm32_gpio_priv *priv = dev_get_priv(dev);
30dbf928ddSPatrice Chotard int idx = 0;
31dbf928ddSPatrice Chotard int i;
32dbf928ddSPatrice Chotard
33dbf928ddSPatrice Chotard for (i = 0; i < STM32_GPIOS_PER_BANK; i++) {
34dbf928ddSPatrice Chotard if (priv->gpio_range & BIT(i)) {
35dbf928ddSPatrice Chotard if (idx == offset)
36dbf928ddSPatrice Chotard return idx;
37dbf928ddSPatrice Chotard idx++;
38dbf928ddSPatrice Chotard }
39dbf928ddSPatrice Chotard }
40dbf928ddSPatrice Chotard /* shouldn't happen */
41dbf928ddSPatrice Chotard return -EINVAL;
42dbf928ddSPatrice Chotard }
43dbf928ddSPatrice Chotard
stm32_gpio_direction_input(struct udevice * dev,unsigned offset)4477417102SVikas Manocha static int stm32_gpio_direction_input(struct udevice *dev, unsigned offset)
4577417102SVikas Manocha {
4677417102SVikas Manocha struct stm32_gpio_priv *priv = dev_get_priv(dev);
4777417102SVikas Manocha struct stm32_gpio_regs *regs = priv->regs;
48dbf928ddSPatrice Chotard int bits_index;
49dbf928ddSPatrice Chotard int mask;
50dbf928ddSPatrice Chotard int idx;
51dbf928ddSPatrice Chotard
52dbf928ddSPatrice Chotard idx = stm32_offset_to_index(dev, offset);
53dbf928ddSPatrice Chotard if (idx < 0)
54dbf928ddSPatrice Chotard return idx;
55dbf928ddSPatrice Chotard
56dbf928ddSPatrice Chotard bits_index = MODE_BITS(idx);
57dbf928ddSPatrice Chotard mask = MODE_BITS_MASK << bits_index;
5877417102SVikas Manocha
5977417102SVikas Manocha clrsetbits_le32(®s->moder, mask, STM32_GPIO_MODE_IN << bits_index);
6077417102SVikas Manocha
6177417102SVikas Manocha return 0;
6277417102SVikas Manocha }
6377417102SVikas Manocha
stm32_gpio_direction_output(struct udevice * dev,unsigned offset,int value)6477417102SVikas Manocha static int stm32_gpio_direction_output(struct udevice *dev, unsigned offset,
6577417102SVikas Manocha int value)
6677417102SVikas Manocha {
6777417102SVikas Manocha struct stm32_gpio_priv *priv = dev_get_priv(dev);
6877417102SVikas Manocha struct stm32_gpio_regs *regs = priv->regs;
69dbf928ddSPatrice Chotard int bits_index;
70dbf928ddSPatrice Chotard int mask;
71dbf928ddSPatrice Chotard int idx;
72dbf928ddSPatrice Chotard
73dbf928ddSPatrice Chotard idx = stm32_offset_to_index(dev, offset);
74dbf928ddSPatrice Chotard if (idx < 0)
75dbf928ddSPatrice Chotard return idx;
76dbf928ddSPatrice Chotard
77dbf928ddSPatrice Chotard bits_index = MODE_BITS(idx);
78dbf928ddSPatrice Chotard mask = MODE_BITS_MASK << bits_index;
7977417102SVikas Manocha
8077417102SVikas Manocha clrsetbits_le32(®s->moder, mask, STM32_GPIO_MODE_OUT << bits_index);
81798cd708SPatrice Chotard
82dbf928ddSPatrice Chotard writel(BSRR_BIT(idx, value), ®s->bsrr);
8377417102SVikas Manocha
8477417102SVikas Manocha return 0;
8577417102SVikas Manocha }
8677417102SVikas Manocha
stm32_gpio_get_value(struct udevice * dev,unsigned offset)8777417102SVikas Manocha static int stm32_gpio_get_value(struct udevice *dev, unsigned offset)
8877417102SVikas Manocha {
8977417102SVikas Manocha struct stm32_gpio_priv *priv = dev_get_priv(dev);
9077417102SVikas Manocha struct stm32_gpio_regs *regs = priv->regs;
91dbf928ddSPatrice Chotard int idx;
9277417102SVikas Manocha
93dbf928ddSPatrice Chotard idx = stm32_offset_to_index(dev, offset);
94dbf928ddSPatrice Chotard if (idx < 0)
95dbf928ddSPatrice Chotard return idx;
96dbf928ddSPatrice Chotard
97dbf928ddSPatrice Chotard return readl(®s->idr) & BIT(idx) ? 1 : 0;
9877417102SVikas Manocha }
9977417102SVikas Manocha
stm32_gpio_set_value(struct udevice * dev,unsigned offset,int value)10077417102SVikas Manocha static int stm32_gpio_set_value(struct udevice *dev, unsigned offset, int value)
10177417102SVikas Manocha {
10277417102SVikas Manocha struct stm32_gpio_priv *priv = dev_get_priv(dev);
10377417102SVikas Manocha struct stm32_gpio_regs *regs = priv->regs;
104dbf928ddSPatrice Chotard int idx;
10577417102SVikas Manocha
106dbf928ddSPatrice Chotard idx = stm32_offset_to_index(dev, offset);
107dbf928ddSPatrice Chotard if (idx < 0)
108dbf928ddSPatrice Chotard return idx;
109dbf928ddSPatrice Chotard
110dbf928ddSPatrice Chotard writel(BSRR_BIT(idx, value), ®s->bsrr);
11177417102SVikas Manocha
11277417102SVikas Manocha return 0;
11377417102SVikas Manocha }
11477417102SVikas Manocha
stm32_gpio_get_function(struct udevice * dev,unsigned int offset)115cad73249SPatrice Chotard static int stm32_gpio_get_function(struct udevice *dev, unsigned int offset)
116cad73249SPatrice Chotard {
117cad73249SPatrice Chotard struct stm32_gpio_priv *priv = dev_get_priv(dev);
118cad73249SPatrice Chotard struct stm32_gpio_regs *regs = priv->regs;
119dbf928ddSPatrice Chotard int bits_index;
120dbf928ddSPatrice Chotard int mask;
121dbf928ddSPatrice Chotard int idx;
122cad73249SPatrice Chotard u32 mode;
123cad73249SPatrice Chotard
124dbf928ddSPatrice Chotard idx = stm32_offset_to_index(dev, offset);
125dbf928ddSPatrice Chotard if (idx < 0)
126dbf928ddSPatrice Chotard return idx;
127dbf928ddSPatrice Chotard
128dbf928ddSPatrice Chotard bits_index = MODE_BITS(idx);
129dbf928ddSPatrice Chotard mask = MODE_BITS_MASK << bits_index;
130dbf928ddSPatrice Chotard
131cad73249SPatrice Chotard mode = (readl(®s->moder) & mask) >> bits_index;
132cad73249SPatrice Chotard if (mode == STM32_GPIO_MODE_OUT)
133cad73249SPatrice Chotard return GPIOF_OUTPUT;
134cad73249SPatrice Chotard if (mode == STM32_GPIO_MODE_IN)
135cad73249SPatrice Chotard return GPIOF_INPUT;
136cad73249SPatrice Chotard if (mode == STM32_GPIO_MODE_AN)
137cad73249SPatrice Chotard return GPIOF_UNUSED;
138cad73249SPatrice Chotard
139cad73249SPatrice Chotard return GPIOF_FUNC;
140cad73249SPatrice Chotard }
141cad73249SPatrice Chotard
14277417102SVikas Manocha static const struct dm_gpio_ops gpio_stm32_ops = {
14377417102SVikas Manocha .direction_input = stm32_gpio_direction_input,
14477417102SVikas Manocha .direction_output = stm32_gpio_direction_output,
14577417102SVikas Manocha .get_value = stm32_gpio_get_value,
14677417102SVikas Manocha .set_value = stm32_gpio_set_value,
147cad73249SPatrice Chotard .get_function = stm32_gpio_get_function,
14877417102SVikas Manocha };
149*4fb22463SPatrice Chotard #endif
15077417102SVikas Manocha
gpio_stm32_probe(struct udevice * dev)15177417102SVikas Manocha static int gpio_stm32_probe(struct udevice *dev)
15277417102SVikas Manocha {
15377417102SVikas Manocha struct stm32_gpio_priv *priv = dev_get_priv(dev);
1548b6d45abSPatrice Chotard struct clk clk;
15577417102SVikas Manocha fdt_addr_t addr;
156dbf928ddSPatrice Chotard int ret;
15777417102SVikas Manocha
158d876eaf2SPatrick Delaunay addr = dev_read_addr(dev);
15977417102SVikas Manocha if (addr == FDT_ADDR_T_NONE)
16077417102SVikas Manocha return -EINVAL;
16177417102SVikas Manocha
16277417102SVikas Manocha priv->regs = (struct stm32_gpio_regs *)addr;
163*4fb22463SPatrice Chotard
164*4fb22463SPatrice Chotard #ifndef CONFIG_SPL_BUILD
165*4fb22463SPatrice Chotard struct gpio_dev_priv *uc_priv = dev_get_uclass_priv(dev);
166*4fb22463SPatrice Chotard struct ofnode_phandle_args args;
167*4fb22463SPatrice Chotard const char *name;
168*4fb22463SPatrice Chotard int i;
169*4fb22463SPatrice Chotard
170d876eaf2SPatrick Delaunay name = dev_read_string(dev, "st,bank-name");
17177417102SVikas Manocha if (!name)
17277417102SVikas Manocha return -EINVAL;
17377417102SVikas Manocha uc_priv->bank_name = name;
174dbf928ddSPatrice Chotard
175dbf928ddSPatrice Chotard i = 0;
176dbf928ddSPatrice Chotard ret = dev_read_phandle_with_args(dev, "gpio-ranges",
177dbf928ddSPatrice Chotard NULL, 3, i, &args);
178dbf928ddSPatrice Chotard
17939a8f0beSPatrice Chotard if (ret == -ENOENT) {
18039a8f0beSPatrice Chotard uc_priv->gpio_count = STM32_GPIOS_PER_BANK;
18139a8f0beSPatrice Chotard priv->gpio_range = GENMASK(STM32_GPIOS_PER_BANK - 1, 0);
18239a8f0beSPatrice Chotard }
18339a8f0beSPatrice Chotard
184dbf928ddSPatrice Chotard while (ret != -ENOENT) {
185dbf928ddSPatrice Chotard priv->gpio_range |= GENMASK(args.args[2] + args.args[0] - 1,
186dbf928ddSPatrice Chotard args.args[0]);
187dbf928ddSPatrice Chotard
188dbf928ddSPatrice Chotard uc_priv->gpio_count += args.args[2];
189dbf928ddSPatrice Chotard
190dbf928ddSPatrice Chotard ret = dev_read_phandle_with_args(dev, "gpio-ranges", NULL, 3,
191dbf928ddSPatrice Chotard ++i, &args);
192dbf928ddSPatrice Chotard }
193dbf928ddSPatrice Chotard
194dbf928ddSPatrice Chotard dev_dbg(dev, "addr = 0x%p bank_name = %s gpio_count = %d gpio_range = 0x%x\n",
195dbf928ddSPatrice Chotard (u32 *)priv->regs, uc_priv->bank_name, uc_priv->gpio_count,
196dbf928ddSPatrice Chotard priv->gpio_range);
197*4fb22463SPatrice Chotard #endif
19877417102SVikas Manocha ret = clk_get_by_index(dev, 0, &clk);
19977417102SVikas Manocha if (ret < 0)
20077417102SVikas Manocha return ret;
20177417102SVikas Manocha
20277417102SVikas Manocha ret = clk_enable(&clk);
20377417102SVikas Manocha
20477417102SVikas Manocha if (ret) {
20577417102SVikas Manocha dev_err(dev, "failed to enable clock\n");
20677417102SVikas Manocha return ret;
20777417102SVikas Manocha }
20877417102SVikas Manocha debug("clock enabled for device %s\n", dev->name);
20977417102SVikas Manocha
21077417102SVikas Manocha return 0;
21177417102SVikas Manocha }
21277417102SVikas Manocha
21377417102SVikas Manocha static const struct udevice_id stm32_gpio_ids[] = {
21477417102SVikas Manocha { .compatible = "st,stm32-gpio" },
21577417102SVikas Manocha { }
21677417102SVikas Manocha };
21777417102SVikas Manocha
21877417102SVikas Manocha U_BOOT_DRIVER(gpio_stm32) = {
21977417102SVikas Manocha .name = "gpio_stm32",
22077417102SVikas Manocha .id = UCLASS_GPIO,
22177417102SVikas Manocha .of_match = stm32_gpio_ids,
22277417102SVikas Manocha .probe = gpio_stm32_probe,
223*4fb22463SPatrice Chotard #ifndef CONFIG_SPL_BUILD
22477417102SVikas Manocha .ops = &gpio_stm32_ops,
225*4fb22463SPatrice Chotard #endif
226695c4994SBin Meng .flags = DM_UC_FLAG_SEQ_ALIAS,
22777417102SVikas Manocha .priv_auto_alloc_size = sizeof(struct stm32_gpio_priv),
22877417102SVikas Manocha };
229