xref: /rk3399_rockchip-uboot/drivers/gpio/stm32_gpio.c (revision eaaa4f7e0e99b7bb1f5caefd96ade7c2ee891bf3)
1*eaaa4f7eSrev13@wp.pl /*
2*eaaa4f7eSrev13@wp.pl  * (C) Copyright 2011
3*eaaa4f7eSrev13@wp.pl  * Yuri Tikhonov, Emcraft Systems, yur@emcraft.com
4*eaaa4f7eSrev13@wp.pl  *
5*eaaa4f7eSrev13@wp.pl  * (C) Copyright 2015
6*eaaa4f7eSrev13@wp.pl  * Kamil Lulko, <rev13@wp.pl>
7*eaaa4f7eSrev13@wp.pl  *
8*eaaa4f7eSrev13@wp.pl  * SPDX-License-Identifier:	GPL-2.0+
9*eaaa4f7eSrev13@wp.pl  */
10*eaaa4f7eSrev13@wp.pl 
11*eaaa4f7eSrev13@wp.pl #include <common.h>
12*eaaa4f7eSrev13@wp.pl #include <asm/io.h>
13*eaaa4f7eSrev13@wp.pl #include <asm/errno.h>
14*eaaa4f7eSrev13@wp.pl #include <asm/arch/stm32.h>
15*eaaa4f7eSrev13@wp.pl #include <asm/arch/gpio.h>
16*eaaa4f7eSrev13@wp.pl 
17*eaaa4f7eSrev13@wp.pl DECLARE_GLOBAL_DATA_PTR;
18*eaaa4f7eSrev13@wp.pl 
19*eaaa4f7eSrev13@wp.pl #define STM32_GPIOA_BASE	(STM32_AHB1PERIPH_BASE + 0x0000)
20*eaaa4f7eSrev13@wp.pl #define STM32_GPIOB_BASE	(STM32_AHB1PERIPH_BASE + 0x0400)
21*eaaa4f7eSrev13@wp.pl #define STM32_GPIOC_BASE	(STM32_AHB1PERIPH_BASE + 0x0800)
22*eaaa4f7eSrev13@wp.pl #define STM32_GPIOD_BASE	(STM32_AHB1PERIPH_BASE + 0x0C00)
23*eaaa4f7eSrev13@wp.pl #define STM32_GPIOE_BASE	(STM32_AHB1PERIPH_BASE + 0x1000)
24*eaaa4f7eSrev13@wp.pl #define STM32_GPIOF_BASE	(STM32_AHB1PERIPH_BASE + 0x1400)
25*eaaa4f7eSrev13@wp.pl #define STM32_GPIOG_BASE	(STM32_AHB1PERIPH_BASE + 0x1800)
26*eaaa4f7eSrev13@wp.pl #define STM32_GPIOH_BASE	(STM32_AHB1PERIPH_BASE + 0x1C00)
27*eaaa4f7eSrev13@wp.pl #define STM32_GPIOI_BASE	(STM32_AHB1PERIPH_BASE + 0x2000)
28*eaaa4f7eSrev13@wp.pl 
29*eaaa4f7eSrev13@wp.pl static const unsigned long io_base[] = {
30*eaaa4f7eSrev13@wp.pl 	STM32_GPIOA_BASE, STM32_GPIOB_BASE, STM32_GPIOC_BASE,
31*eaaa4f7eSrev13@wp.pl 	STM32_GPIOD_BASE, STM32_GPIOE_BASE, STM32_GPIOF_BASE,
32*eaaa4f7eSrev13@wp.pl 	STM32_GPIOG_BASE, STM32_GPIOH_BASE, STM32_GPIOI_BASE
33*eaaa4f7eSrev13@wp.pl };
34*eaaa4f7eSrev13@wp.pl 
35*eaaa4f7eSrev13@wp.pl struct stm32_gpio_regs {
36*eaaa4f7eSrev13@wp.pl 	u32 moder;	/* GPIO port mode */
37*eaaa4f7eSrev13@wp.pl 	u32 otyper;	/* GPIO port output type */
38*eaaa4f7eSrev13@wp.pl 	u32 ospeedr;	/* GPIO port output speed */
39*eaaa4f7eSrev13@wp.pl 	u32 pupdr;	/* GPIO port pull-up/pull-down */
40*eaaa4f7eSrev13@wp.pl 	u32 idr;	/* GPIO port input data */
41*eaaa4f7eSrev13@wp.pl 	u32 odr;	/* GPIO port output data */
42*eaaa4f7eSrev13@wp.pl 	u32 bsrr;	/* GPIO port bit set/reset */
43*eaaa4f7eSrev13@wp.pl 	u32 lckr;	/* GPIO port configuration lock */
44*eaaa4f7eSrev13@wp.pl 	u32 afr[2];	/* GPIO alternate function */
45*eaaa4f7eSrev13@wp.pl };
46*eaaa4f7eSrev13@wp.pl 
47*eaaa4f7eSrev13@wp.pl #define CHECK_DSC(x)	(!x || x->port > 8 || x->pin > 15)
48*eaaa4f7eSrev13@wp.pl #define CHECK_CTL(x)	(!x || x->af > 15 || x->mode > 3 || x->otype > 1 || \
49*eaaa4f7eSrev13@wp.pl 			x->pupd > 2 || x->speed > 3)
50*eaaa4f7eSrev13@wp.pl 
51*eaaa4f7eSrev13@wp.pl int stm32_gpio_config(const struct stm32_gpio_dsc *dsc,
52*eaaa4f7eSrev13@wp.pl 		const struct stm32_gpio_ctl *ctl)
53*eaaa4f7eSrev13@wp.pl {
54*eaaa4f7eSrev13@wp.pl 	struct stm32_gpio_regs *gpio_regs;
55*eaaa4f7eSrev13@wp.pl 	u32 i;
56*eaaa4f7eSrev13@wp.pl 	int rv;
57*eaaa4f7eSrev13@wp.pl 
58*eaaa4f7eSrev13@wp.pl 	if (CHECK_DSC(dsc)) {
59*eaaa4f7eSrev13@wp.pl 		rv = -EINVAL;
60*eaaa4f7eSrev13@wp.pl 		goto out;
61*eaaa4f7eSrev13@wp.pl 	}
62*eaaa4f7eSrev13@wp.pl 	if (CHECK_CTL(ctl)) {
63*eaaa4f7eSrev13@wp.pl 		rv = -EINVAL;
64*eaaa4f7eSrev13@wp.pl 		goto out;
65*eaaa4f7eSrev13@wp.pl 	}
66*eaaa4f7eSrev13@wp.pl 
67*eaaa4f7eSrev13@wp.pl 	gpio_regs = (struct stm32_gpio_regs *)io_base[dsc->port];
68*eaaa4f7eSrev13@wp.pl 
69*eaaa4f7eSrev13@wp.pl 	setbits_le32(&STM32_RCC->ahb1enr, 1 << dsc->port);
70*eaaa4f7eSrev13@wp.pl 
71*eaaa4f7eSrev13@wp.pl 	i = (dsc->pin & 0x07) * 4;
72*eaaa4f7eSrev13@wp.pl 	clrbits_le32(&gpio_regs->afr[dsc->pin >> 3], (0xF << i));
73*eaaa4f7eSrev13@wp.pl 	setbits_le32(&gpio_regs->afr[dsc->pin >> 3], ctl->af << i);
74*eaaa4f7eSrev13@wp.pl 
75*eaaa4f7eSrev13@wp.pl 	i = dsc->pin * 2;
76*eaaa4f7eSrev13@wp.pl 
77*eaaa4f7eSrev13@wp.pl 	clrbits_le32(&gpio_regs->moder, (0x3 << i));
78*eaaa4f7eSrev13@wp.pl 	setbits_le32(&gpio_regs->moder, ctl->mode << i);
79*eaaa4f7eSrev13@wp.pl 
80*eaaa4f7eSrev13@wp.pl 	clrbits_le32(&gpio_regs->otyper, (0x3 << i));
81*eaaa4f7eSrev13@wp.pl 	setbits_le32(&gpio_regs->otyper, ctl->otype << i);
82*eaaa4f7eSrev13@wp.pl 
83*eaaa4f7eSrev13@wp.pl 	clrbits_le32(&gpio_regs->ospeedr, (0x3 << i));
84*eaaa4f7eSrev13@wp.pl 	setbits_le32(&gpio_regs->ospeedr, ctl->speed << i);
85*eaaa4f7eSrev13@wp.pl 
86*eaaa4f7eSrev13@wp.pl 	clrbits_le32(&gpio_regs->pupdr, (0x3 << i));
87*eaaa4f7eSrev13@wp.pl 	setbits_le32(&gpio_regs->pupdr, ctl->pupd << i);
88*eaaa4f7eSrev13@wp.pl 
89*eaaa4f7eSrev13@wp.pl 	rv = 0;
90*eaaa4f7eSrev13@wp.pl out:
91*eaaa4f7eSrev13@wp.pl 	return rv;
92*eaaa4f7eSrev13@wp.pl }
93*eaaa4f7eSrev13@wp.pl 
94*eaaa4f7eSrev13@wp.pl int stm32_gpout_set(const struct stm32_gpio_dsc *dsc, int state)
95*eaaa4f7eSrev13@wp.pl {
96*eaaa4f7eSrev13@wp.pl 	struct stm32_gpio_regs	*gpio_regs;
97*eaaa4f7eSrev13@wp.pl 	int rv;
98*eaaa4f7eSrev13@wp.pl 
99*eaaa4f7eSrev13@wp.pl 	if (CHECK_DSC(dsc)) {
100*eaaa4f7eSrev13@wp.pl 		rv = -EINVAL;
101*eaaa4f7eSrev13@wp.pl 		goto out;
102*eaaa4f7eSrev13@wp.pl 	}
103*eaaa4f7eSrev13@wp.pl 
104*eaaa4f7eSrev13@wp.pl 	gpio_regs = (struct stm32_gpio_regs *)io_base[dsc->port];
105*eaaa4f7eSrev13@wp.pl 
106*eaaa4f7eSrev13@wp.pl 	if (state)
107*eaaa4f7eSrev13@wp.pl 		writel(1 << dsc->pin, &gpio_regs->bsrr);
108*eaaa4f7eSrev13@wp.pl 	else
109*eaaa4f7eSrev13@wp.pl 		writel(1 << (dsc->pin + 16), &gpio_regs->bsrr);
110*eaaa4f7eSrev13@wp.pl 
111*eaaa4f7eSrev13@wp.pl 	rv = 0;
112*eaaa4f7eSrev13@wp.pl out:
113*eaaa4f7eSrev13@wp.pl 	return rv;
114*eaaa4f7eSrev13@wp.pl }
115*eaaa4f7eSrev13@wp.pl 
116*eaaa4f7eSrev13@wp.pl int stm32_gpin_get(const struct stm32_gpio_dsc *dsc)
117*eaaa4f7eSrev13@wp.pl {
118*eaaa4f7eSrev13@wp.pl 	struct stm32_gpio_regs	*gpio_regs;
119*eaaa4f7eSrev13@wp.pl 	int rv;
120*eaaa4f7eSrev13@wp.pl 
121*eaaa4f7eSrev13@wp.pl 	if (CHECK_DSC(dsc)) {
122*eaaa4f7eSrev13@wp.pl 		rv = -EINVAL;
123*eaaa4f7eSrev13@wp.pl 		goto out;
124*eaaa4f7eSrev13@wp.pl 	}
125*eaaa4f7eSrev13@wp.pl 
126*eaaa4f7eSrev13@wp.pl 	gpio_regs = (struct stm32_gpio_regs *)io_base[dsc->port];
127*eaaa4f7eSrev13@wp.pl 	rv = readl(&gpio_regs->idr) & (1 << dsc->pin);
128*eaaa4f7eSrev13@wp.pl out:
129*eaaa4f7eSrev13@wp.pl 	return rv;
130*eaaa4f7eSrev13@wp.pl }
131*eaaa4f7eSrev13@wp.pl 
132*eaaa4f7eSrev13@wp.pl /* Common GPIO API */
133*eaaa4f7eSrev13@wp.pl 
134*eaaa4f7eSrev13@wp.pl int gpio_request(unsigned gpio, const char *label)
135*eaaa4f7eSrev13@wp.pl {
136*eaaa4f7eSrev13@wp.pl 	return 0;
137*eaaa4f7eSrev13@wp.pl }
138*eaaa4f7eSrev13@wp.pl 
139*eaaa4f7eSrev13@wp.pl int gpio_free(unsigned gpio)
140*eaaa4f7eSrev13@wp.pl {
141*eaaa4f7eSrev13@wp.pl 	return 0;
142*eaaa4f7eSrev13@wp.pl }
143*eaaa4f7eSrev13@wp.pl 
144*eaaa4f7eSrev13@wp.pl int gpio_direction_input(unsigned gpio)
145*eaaa4f7eSrev13@wp.pl {
146*eaaa4f7eSrev13@wp.pl 	struct stm32_gpio_dsc dsc;
147*eaaa4f7eSrev13@wp.pl 	struct stm32_gpio_ctl ctl;
148*eaaa4f7eSrev13@wp.pl 
149*eaaa4f7eSrev13@wp.pl 	dsc.port = stm32_gpio_to_port(gpio);
150*eaaa4f7eSrev13@wp.pl 	dsc.pin = stm32_gpio_to_pin(gpio);
151*eaaa4f7eSrev13@wp.pl 	ctl.af = STM32_GPIO_AF0;
152*eaaa4f7eSrev13@wp.pl 	ctl.mode = STM32_GPIO_MODE_IN;
153*eaaa4f7eSrev13@wp.pl 	ctl.pupd = STM32_GPIO_PUPD_NO;
154*eaaa4f7eSrev13@wp.pl 	ctl.speed = STM32_GPIO_SPEED_50M;
155*eaaa4f7eSrev13@wp.pl 
156*eaaa4f7eSrev13@wp.pl 	return stm32_gpio_config(&dsc, &ctl);
157*eaaa4f7eSrev13@wp.pl }
158*eaaa4f7eSrev13@wp.pl 
159*eaaa4f7eSrev13@wp.pl int gpio_direction_output(unsigned gpio, int value)
160*eaaa4f7eSrev13@wp.pl {
161*eaaa4f7eSrev13@wp.pl 	struct stm32_gpio_dsc dsc;
162*eaaa4f7eSrev13@wp.pl 	struct stm32_gpio_ctl ctl;
163*eaaa4f7eSrev13@wp.pl 	int res;
164*eaaa4f7eSrev13@wp.pl 
165*eaaa4f7eSrev13@wp.pl 	dsc.port = stm32_gpio_to_port(gpio);
166*eaaa4f7eSrev13@wp.pl 	dsc.pin = stm32_gpio_to_pin(gpio);
167*eaaa4f7eSrev13@wp.pl 	ctl.af = STM32_GPIO_AF0;
168*eaaa4f7eSrev13@wp.pl 	ctl.mode = STM32_GPIO_MODE_OUT;
169*eaaa4f7eSrev13@wp.pl 	ctl.otype = STM32_GPIO_OTYPE_PP;
170*eaaa4f7eSrev13@wp.pl 	ctl.pupd = STM32_GPIO_PUPD_NO;
171*eaaa4f7eSrev13@wp.pl 	ctl.speed = STM32_GPIO_SPEED_50M;
172*eaaa4f7eSrev13@wp.pl 
173*eaaa4f7eSrev13@wp.pl 	res = stm32_gpio_config(&dsc, &ctl);
174*eaaa4f7eSrev13@wp.pl 	if (res < 0)
175*eaaa4f7eSrev13@wp.pl 		goto out;
176*eaaa4f7eSrev13@wp.pl 	res = stm32_gpout_set(&dsc, value);
177*eaaa4f7eSrev13@wp.pl out:
178*eaaa4f7eSrev13@wp.pl 	return res;
179*eaaa4f7eSrev13@wp.pl }
180*eaaa4f7eSrev13@wp.pl 
181*eaaa4f7eSrev13@wp.pl int gpio_get_value(unsigned gpio)
182*eaaa4f7eSrev13@wp.pl {
183*eaaa4f7eSrev13@wp.pl 	struct stm32_gpio_dsc dsc;
184*eaaa4f7eSrev13@wp.pl 
185*eaaa4f7eSrev13@wp.pl 	dsc.port = stm32_gpio_to_port(gpio);
186*eaaa4f7eSrev13@wp.pl 	dsc.pin = stm32_gpio_to_pin(gpio);
187*eaaa4f7eSrev13@wp.pl 
188*eaaa4f7eSrev13@wp.pl 	return stm32_gpin_get(&dsc);
189*eaaa4f7eSrev13@wp.pl }
190*eaaa4f7eSrev13@wp.pl 
191*eaaa4f7eSrev13@wp.pl int gpio_set_value(unsigned gpio, int value)
192*eaaa4f7eSrev13@wp.pl {
193*eaaa4f7eSrev13@wp.pl 	struct stm32_gpio_dsc dsc;
194*eaaa4f7eSrev13@wp.pl 
195*eaaa4f7eSrev13@wp.pl 	dsc.port = stm32_gpio_to_port(gpio);
196*eaaa4f7eSrev13@wp.pl 	dsc.pin = stm32_gpio_to_pin(gpio);
197*eaaa4f7eSrev13@wp.pl 
198*eaaa4f7eSrev13@wp.pl 	return stm32_gpout_set(&dsc, value);
199*eaaa4f7eSrev13@wp.pl }
200