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