xref: /openbmc/u-boot/drivers/gpio/stm32f7_gpio.c (revision 7f941868)
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(&regs->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(&regs->moder, mask, STM32_GPIO_MODE_OUT << bits_index);
81798cd708SPatrice Chotard 
82dbf928ddSPatrice Chotard 	writel(BSRR_BIT(idx, value), &regs->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(&regs->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), &regs->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(&regs->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