• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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