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