1/*
2 * Copyright (C) 2016 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <plat/gpio.h>
18#include <plat/pwr.h>
19#include <gpio.h>
20#include <cpu.h>
21
22struct StmGpio {
23    volatile uint32_t MODER;
24    volatile uint32_t OTYPER;
25    volatile uint32_t OSPEEDR;
26    volatile uint32_t PUPDR;
27    volatile uint32_t IDR;
28    volatile uint32_t ODR;
29    volatile uint32_t BSRR;
30    volatile uint32_t LCKR;
31    volatile uint32_t AFR[2];
32};
33
34static const uint32_t mGpioPeriphs[] = {
35    PERIPH_AHB1_GPIOA,
36    PERIPH_AHB1_GPIOB,
37    PERIPH_AHB1_GPIOC,
38    PERIPH_AHB1_GPIOD,
39    PERIPH_AHB1_GPIOE,
40    PERIPH_AHB1_GPIOF,
41    PERIPH_AHB1_GPIOG,
42    PERIPH_AHB1_GPIOH,
43    PERIPH_AHB1_GPIOI,
44};
45
46static const uint32_t mGpioBases[] = {
47    GPIOA_BASE,
48    GPIOB_BASE,
49    GPIOC_BASE,
50    GPIOD_BASE,
51    GPIOE_BASE,
52    GPIOF_BASE,
53    GPIOG_BASE,
54    GPIOH_BASE,
55    GPIOI_BASE,
56};
57
58static void gpioSetWithNum(uint32_t gpioNum, bool value);
59
60
61struct Gpio* gpioRequest(uint32_t number)
62{
63    return (struct Gpio*)(((uintptr_t)number) + GPIO_HANDLE_OFFSET);
64}
65
66void gpioRelease(struct Gpio* __restrict gpio)
67{
68    (void)gpio;
69}
70
71static enum StmGpioSpeed gpioSpeedFromRequestedSpeed(int32_t requestedSpeed)
72{
73    static const enum StmGpioSpeed mStandardSpeeds[] = {
74        [-1 - GPIO_SPEED_BEST_POWER  ] = GPIO_SPEED_LOW,
75        [-1 - GPIO_SPEED_BEST_SPEED  ] = GPIO_SPEED_HIGH,
76        [-1 - GPIO_SPEED_DEFAULT     ] = GPIO_SPEED_MEDIUM,
77        [-1 - GPIO_SPEED_1MHZ_PLUS   ] = GPIO_SPEED_LOW,
78        [-1 - GPIO_SPEED_3MHZ_PLUS   ] = GPIO_SPEED_LOW,
79        [-1 - GPIO_SPEED_5MHZ_PLUS   ] = GPIO_SPEED_MEDIUM,
80        [-1 - GPIO_SPEED_10MHZ_PLUS  ] = GPIO_SPEED_MEDIUM,
81        [-1 - GPIO_SPEED_15MHZ_PLUS  ] = GPIO_SPEED_MEDIUM,
82        [-1 - GPIO_SPEED_20MHZ_PLUS  ] = GPIO_SPEED_MEDIUM,
83        [-1 - GPIO_SPEED_30MHZ_PLUS  ] = GPIO_SPEED_FAST,
84        [-1 - GPIO_SPEED_50MHZ_PLUS  ] = GPIO_SPEED_FAST,
85        [-1 - GPIO_SPEED_100MHZ_PLUS ] = GPIO_SPEED_FAST,
86        [-1 - GPIO_SPEED_150MHZ_PLUS ] = GPIO_SPEED_FAST,  //this is not fast enough, but it is all we can do
87        [-1 - GPIO_SPEED_150MHZ_PLUS ] = GPIO_SPEED_FAST,  //this is not fast enough, but it is all we can do
88    };
89
90    if (requestedSpeed >= 0)
91        return requestedSpeed;
92    else
93        return mStandardSpeeds[-requestedSpeed - 1];
94}
95
96static void gpioConfigWithNum(uint32_t gpioNum, int32_t gpioSpeed, enum GpioPullMode pull, enum GpioOpenDrainMode output)
97{
98    struct StmGpio *block = (struct StmGpio*)mGpioBases[gpioNum >> GPIO_PORT_SHIFT];
99    const uint32_t shift_1b = gpioNum & GPIO_PIN_MASK;
100    const uint32_t shift_2b = (gpioNum & GPIO_PIN_MASK) * 2;
101    const uint32_t mask_1b = (1UL << shift_1b);
102    const uint32_t mask_2b = (3UL << shift_2b);
103
104    /* unit clock */
105    pwrUnitClock(PERIPH_BUS_AHB1, mGpioPeriphs[gpioNum >> GPIO_PORT_SHIFT], true);
106
107    /* speed */
108    block->OSPEEDR = (block->OSPEEDR & ~mask_2b) | (((uint32_t)gpioSpeedFromRequestedSpeed(gpioSpeed)) << shift_2b);
109
110    /* pull ups/downs */
111    block->PUPDR = (block->PUPDR & ~mask_2b) | (((uint32_t)pull) << shift_2b);
112    /* push/pull or open drain */
113    if (output == GPIO_OUT_PUSH_PULL)
114        block->OTYPER &= ~mask_1b;
115    else
116        block->OTYPER |= mask_1b;
117}
118
119static void gpioConfigInputWithNum(uint32_t gpioNum, int32_t gpioSpeed, enum GpioPullMode pull)
120{
121    struct StmGpio *block = (struct StmGpio*)mGpioBases[gpioNum >> GPIO_PORT_SHIFT];
122    const uint32_t shift_2b = (gpioNum & GPIO_PIN_MASK) * 2;
123    const uint32_t mask_2b = (3UL << shift_2b);
124
125    gpioConfigWithNum(gpioNum, gpioSpeed, pull, GPIO_OUT_PUSH_PULL);
126
127    /* direction */
128    block->MODER = (block->MODER & ~mask_2b) | (((uint32_t)GPIO_MODE_IN) << shift_2b);
129}
130
131void gpioConfigInput(const struct Gpio* __restrict gpioHandle, int32_t gpioSpeed, enum GpioPullMode pull)
132{
133    if (gpioHandle)
134        gpioConfigInputWithNum((uint32_t)gpioHandle - GPIO_HANDLE_OFFSET, gpioSpeed, pull);
135}
136
137static void gpioConfigOutputWithNum(uint32_t gpioNum, int32_t gpioSpeed, enum GpioPullMode pull, enum GpioOpenDrainMode output, bool value)
138{
139    struct StmGpio *block = (struct StmGpio*)mGpioBases[gpioNum >> GPIO_PORT_SHIFT];
140    const uint32_t shift_2b = (gpioNum & GPIO_PIN_MASK) * 2;
141    const uint32_t mask_2b = (3UL << shift_2b);
142
143    gpioConfigWithNum(gpioNum, gpioSpeed, pull, output);
144
145    /* set the initial output value */
146    gpioSetWithNum(gpioNum, value);
147
148    /* direction */
149    block->MODER = (block->MODER & ~mask_2b) | (((uint32_t)GPIO_MODE_OUT) << shift_2b);
150}
151
152void gpioConfigOutput(const struct Gpio* __restrict gpioHandle, int32_t gpioSpeed, enum GpioPullMode pull, enum GpioOpenDrainMode output, bool value)
153{
154    if (gpioHandle)
155        gpioConfigOutputWithNum((uint32_t)gpioHandle - GPIO_HANDLE_OFFSET, gpioSpeed, pull, output, value);
156}
157
158static void gpioConfigAltWithNum(uint32_t gpioNum, int32_t gpioSpeed, enum GpioPullMode pull, enum GpioOpenDrainMode output, uint32_t altFunc)
159{
160    struct StmGpio *block = (struct StmGpio*)mGpioBases[gpioNum >> GPIO_PORT_SHIFT];
161    const uint32_t pinNo = gpioNum & GPIO_PIN_MASK;
162    const uint32_t regNo = pinNo >> (GPIO_PORT_SHIFT - 1);
163    const uint32_t nibbleNo = pinNo & (GPIO_PIN_MASK >> 1);
164    const uint32_t shift_2b = pinNo * 2;
165    const uint32_t shift_4b = nibbleNo * 4;
166    const uint32_t mask_2b = (3UL << shift_2b);
167    const uint32_t mask_4b = (15UL << shift_4b);
168
169    gpioConfigWithNum(gpioNum, gpioSpeed, pull, output);
170
171    /* assign function */
172    block->AFR[regNo] = (block->AFR[regNo] & ~mask_4b) | (((uint32_t)altFunc) << shift_4b);
173
174    /* direction */
175    block->MODER = (block->MODER & ~mask_2b) | (((uint32_t)GPIO_MODE_ALTERNATE) << shift_2b);
176}
177
178void gpioConfigAlt(const struct Gpio* __restrict gpioHandle, int32_t gpioSpeed, enum GpioPullMode pull, enum GpioOpenDrainMode output, uint32_t altFunc)
179{
180    if (gpioHandle)
181        gpioConfigAltWithNum((uint32_t)gpioHandle - GPIO_HANDLE_OFFSET, gpioSpeed, pull, output, altFunc);
182}
183
184static void gpioConfigAnalogWithNum(uint32_t gpioNum)
185{
186    struct StmGpio *block = (struct StmGpio*)mGpioBases[gpioNum >> GPIO_PORT_SHIFT];
187    const uint32_t pinNo = gpioNum & GPIO_PIN_MASK;
188    const uint32_t shift_2b = pinNo * 2;
189    const uint32_t mask_2b = (3UL << shift_2b);
190
191    gpioConfigWithNum(gpioNum, GPIO_SPEED_LOW, GPIO_PULL_NONE, GPIO_OUT_OPEN_DRAIN);
192
193    /* I/O configuration */
194    block->MODER = (block->MODER & ~mask_2b) | (((uint32_t)GPIO_MODE_ANALOG) << shift_2b);
195}
196
197void gpioConfigAnalog(const struct Gpio* __restrict gpioHandle)
198{
199    if (gpioHandle)
200        gpioConfigAnalogWithNum((uint32_t)gpioHandle - GPIO_HANDLE_OFFSET);
201}
202
203static void gpioSetWithNum(uint32_t gpioNum, bool value)
204{
205    struct StmGpio *block = (struct StmGpio*)mGpioBases[gpioNum >> GPIO_PORT_SHIFT];
206    const uint32_t shift_1b = gpioNum & GPIO_PIN_MASK;
207    const uint32_t mask_set_1b = (1UL << (0  + shift_1b));
208    const uint32_t mask_clr_1b = (1UL << (16 + shift_1b));
209
210    block->BSRR = value ? mask_set_1b : mask_clr_1b;
211}
212
213void gpioSet(const struct Gpio* __restrict gpioHandle, bool value)
214{
215    if (gpioHandle)
216        gpioSetWithNum((uint32_t)gpioHandle - GPIO_HANDLE_OFFSET, value);
217}
218
219static bool gpioGetWithNum(uint32_t gpioNum)
220{
221    struct StmGpio *block = (struct StmGpio*)mGpioBases[gpioNum >> GPIO_PORT_SHIFT];
222    const uint32_t shift_1b = gpioNum & GPIO_PIN_MASK;
223    const uint32_t mask_1b = (1UL << shift_1b);
224
225    return !!(block->IDR & mask_1b);
226}
227
228bool gpioGet(const struct Gpio* __restrict gpioHandle)
229{
230    return gpioHandle ? gpioGetWithNum((uint32_t)gpioHandle - GPIO_HANDLE_OFFSET) : 0;
231}
232
233
234#ifdef DEBUG_UART_PIN
235
236//this function makes more assumptions than i'd care to list, sorry...
237void gpioBitbangedUartOut(uint32_t chr)
238{
239    static const uint32_t bsrrVals[] = {(1 << (DEBUG_UART_PIN & GPIO_PIN_MASK)) << 16, (1 << (DEBUG_UART_PIN & GPIO_PIN_MASK))};
240    struct StmGpio *block = (struct StmGpio*)mGpioBases[DEBUG_UART_PIN >> GPIO_PORT_SHIFT];
241    uint32_t bits[10], *bitsP = bits, base = (uint32_t)&block->BSRR;
242    static bool setup = 0;
243    uint64_t state;
244    uint32_t i;
245
246    if (!setup) {
247        struct Gpio *gpio = gpioRequest(DEBUG_UART_PIN);
248
249        if (!gpio)
250            return;
251
252        setup = true;
253        gpioConfigOutput(gpio, GPIO_SPEED_HIGH, GPIO_PULL_NONE, GPIO_OUT_PUSH_PULL, true);
254    }
255
256    bits[0] = bsrrVals[0];
257    for (i = 0; i < 8; i++, chr >>= 1)
258        bits[i + 1] = bsrrVals[chr & 1];
259    bits[9] = bsrrVals[1];
260
261    #define SENDBIT "ldr %0, [%1], #4   \n\t"   \
262   "str %0, [%2]   \n\t"   \
263   "nop    \n\t"   \
264   "nop    \n\t"   \
265   "nop    \n\t"   \
266   "nop    \n\t"   \
267   "nop    \n\t"   \
268   "nop    \n\t"
269
270   state = cpuIntsOff();
271   asm volatile(
272       SENDBIT
273       SENDBIT
274       SENDBIT
275       SENDBIT
276       SENDBIT
277       SENDBIT
278       SENDBIT
279       SENDBIT
280       SENDBIT
281       SENDBIT
282       :"=r"(i), "=r"(bitsP), "=r"(base)
283       :"0"(i), "1"(bitsP), "2"(base)
284       :"memory","cc"
285    );
286    cpuIntsRestore(state);
287}
288
289
290#endif
291
292
293
294
295