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