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 61 struct Gpio* gpioRequest(uint32_t number) 62 { 63 return (struct Gpio*)(((uintptr_t)number) + GPIO_HANDLE_OFFSET); 64 } 65 66 void gpioRelease(struct Gpio* __restrict gpio) 67 { 68 (void)gpio; 69 } 70 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 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 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 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 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 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 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 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 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 197 void gpioConfigAnalog(const struct Gpio* __restrict gpioHandle) 198 { 199 if (gpioHandle) 200 gpioConfigAnalogWithNum((uint32_t)gpioHandle - GPIO_HANDLE_OFFSET); 201 } 202 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 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 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 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... 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