Home | History | Annotate | Download | only in stm32f4xx
      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/inc/gpio.h>
     18 #include <plat/inc/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