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
22 struct 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
34 static 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
46 static 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
58 static void gpioSetWithNum(uint32_t gpioNum, bool value);
59
60
gpioRequest(uint32_t number)61 struct Gpio* gpioRequest(uint32_t number)
62 {
63 return (struct Gpio*)(((uintptr_t)number) + GPIO_HANDLE_OFFSET);
64 }
65
gpioRelease(struct Gpio * __restrict gpio)66 void gpioRelease(struct Gpio* __restrict gpio)
67 {
68 (void)gpio;
69 }
70
gpioSpeedFromRequestedSpeed(int32_t requestedSpeed)71 static 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
gpioConfigWithNum(uint32_t gpioNum,int32_t gpioSpeed,enum GpioPullMode pull,enum GpioOpenDrainMode output)96 static 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
gpioConfigInputWithNum(uint32_t gpioNum,int32_t gpioSpeed,enum GpioPullMode pull)119 static 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
gpioConfigInput(const struct Gpio * __restrict gpioHandle,int32_t gpioSpeed,enum GpioPullMode pull)131 void 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
gpioConfigOutputWithNum(uint32_t gpioNum,int32_t gpioSpeed,enum GpioPullMode pull,enum GpioOpenDrainMode output,bool value)137 static 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
gpioConfigOutput(const struct Gpio * __restrict gpioHandle,int32_t gpioSpeed,enum GpioPullMode pull,enum GpioOpenDrainMode output,bool value)152 void 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
gpioConfigAltWithNum(uint32_t gpioNum,int32_t gpioSpeed,enum GpioPullMode pull,enum GpioOpenDrainMode output,uint32_t altFunc)158 static 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
gpioConfigAlt(const struct Gpio * __restrict gpioHandle,int32_t gpioSpeed,enum GpioPullMode pull,enum GpioOpenDrainMode output,uint32_t altFunc)178 void 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
gpioConfigAnalogWithNum(uint32_t gpioNum)184 static 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
gpioConfigAnalog(const struct Gpio * __restrict gpioHandle)197 void gpioConfigAnalog(const struct Gpio* __restrict gpioHandle)
198 {
199 if (gpioHandle)
200 gpioConfigAnalogWithNum((uint32_t)gpioHandle - GPIO_HANDLE_OFFSET);
201 }
202
gpioSetWithNum(uint32_t gpioNum,bool value)203 static 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
gpioSet(const struct Gpio * __restrict gpioHandle,bool value)213 void gpioSet(const struct Gpio* __restrict gpioHandle, bool value)
214 {
215 if (gpioHandle)
216 gpioSetWithNum((uint32_t)gpioHandle - GPIO_HANDLE_OFFSET, value);
217 }
218
gpioGetWithNum(uint32_t gpioNum)219 static 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
gpioGet(const struct Gpio * __restrict gpioHandle)228 bool 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...
gpioBitbangedUartOut(uint32_t chr)237 void 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