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