1 /* 2 * (C) Copyright 2011 3 * Yuri Tikhonov, Emcraft Systems, yur@emcraft.com 4 * 5 * (C) Copyright 2015 6 * Kamil Lulko, <kamil.lulko@gmail.com> 7 * 8 * Copyright 2015 ATS Advanced Telematics Systems GmbH 9 * Copyright 2015 Konsulko Group, Matt Porter <mporter@konsulko.com> 10 * 11 * SPDX-License-Identifier: GPL-2.0+ 12 */ 13 14 #include <common.h> 15 #include <asm/io.h> 16 #include <linux/errno.h> 17 #include <asm/arch/stm32.h> 18 #include <asm/arch/gpio.h> 19 20 DECLARE_GLOBAL_DATA_PTR; 21 22 static const unsigned long io_base[] = { 23 STM32_GPIOA_BASE, STM32_GPIOB_BASE, STM32_GPIOC_BASE, 24 STM32_GPIOD_BASE, STM32_GPIOE_BASE, STM32_GPIOF_BASE, 25 STM32_GPIOG_BASE, STM32_GPIOH_BASE, STM32_GPIOI_BASE 26 }; 27 28 struct stm32_gpio_regs { 29 u32 moder; /* GPIO port mode */ 30 u32 otyper; /* GPIO port output type */ 31 u32 ospeedr; /* GPIO port output speed */ 32 u32 pupdr; /* GPIO port pull-up/pull-down */ 33 u32 idr; /* GPIO port input data */ 34 u32 odr; /* GPIO port output data */ 35 u32 bsrr; /* GPIO port bit set/reset */ 36 u32 lckr; /* GPIO port configuration lock */ 37 u32 afr[2]; /* GPIO alternate function */ 38 }; 39 40 #define CHECK_DSC(x) (!x || x->port > 8 || x->pin > 15) 41 #define CHECK_CTL(x) (!x || x->af > 15 || x->mode > 3 || x->otype > 1 || \ 42 x->pupd > 2 || x->speed > 3) 43 44 int stm32_gpio_config(const struct stm32_gpio_dsc *dsc, 45 const struct stm32_gpio_ctl *ctl) 46 { 47 struct stm32_gpio_regs *gpio_regs; 48 u32 i; 49 int rv; 50 51 if (CHECK_DSC(dsc)) { 52 rv = -EINVAL; 53 goto out; 54 } 55 if (CHECK_CTL(ctl)) { 56 rv = -EINVAL; 57 goto out; 58 } 59 60 gpio_regs = (struct stm32_gpio_regs *)io_base[dsc->port]; 61 62 i = (dsc->pin & 0x07) * 4; 63 clrsetbits_le32(&gpio_regs->afr[dsc->pin >> 3], 0xF << i, ctl->af << i); 64 65 i = dsc->pin * 2; 66 67 clrsetbits_le32(&gpio_regs->moder, 0x3 << i, ctl->mode << i); 68 clrsetbits_le32(&gpio_regs->otyper, 0x3 << i, ctl->otype << i); 69 clrsetbits_le32(&gpio_regs->ospeedr, 0x3 << i, ctl->speed << i); 70 clrsetbits_le32(&gpio_regs->pupdr, 0x3 << i, ctl->pupd << i); 71 72 rv = 0; 73 out: 74 return rv; 75 } 76 77 int stm32_gpout_set(const struct stm32_gpio_dsc *dsc, int state) 78 { 79 struct stm32_gpio_regs *gpio_regs; 80 int rv; 81 82 if (CHECK_DSC(dsc)) { 83 rv = -EINVAL; 84 goto out; 85 } 86 87 gpio_regs = (struct stm32_gpio_regs *)io_base[dsc->port]; 88 89 if (state) 90 writel(1 << dsc->pin, &gpio_regs->bsrr); 91 else 92 writel(1 << (dsc->pin + 16), &gpio_regs->bsrr); 93 94 rv = 0; 95 out: 96 return rv; 97 } 98 99 int stm32_gpin_get(const struct stm32_gpio_dsc *dsc) 100 { 101 struct stm32_gpio_regs *gpio_regs; 102 int rv; 103 104 if (CHECK_DSC(dsc)) { 105 rv = -EINVAL; 106 goto out; 107 } 108 109 gpio_regs = (struct stm32_gpio_regs *)io_base[dsc->port]; 110 rv = readl(&gpio_regs->idr) & (1 << dsc->pin); 111 out: 112 return rv; 113 } 114 115 /* Common GPIO API */ 116 117 int gpio_request(unsigned gpio, const char *label) 118 { 119 return 0; 120 } 121 122 int gpio_free(unsigned gpio) 123 { 124 return 0; 125 } 126 127 int gpio_direction_input(unsigned gpio) 128 { 129 struct stm32_gpio_dsc dsc; 130 struct stm32_gpio_ctl ctl; 131 132 dsc.port = stm32_gpio_to_port(gpio); 133 dsc.pin = stm32_gpio_to_pin(gpio); 134 ctl.af = STM32_GPIO_AF0; 135 ctl.mode = STM32_GPIO_MODE_IN; 136 ctl.otype = STM32_GPIO_OTYPE_PP; 137 ctl.pupd = STM32_GPIO_PUPD_NO; 138 ctl.speed = STM32_GPIO_SPEED_50M; 139 140 return stm32_gpio_config(&dsc, &ctl); 141 } 142 143 int gpio_direction_output(unsigned gpio, int value) 144 { 145 struct stm32_gpio_dsc dsc; 146 struct stm32_gpio_ctl ctl; 147 int res; 148 149 dsc.port = stm32_gpio_to_port(gpio); 150 dsc.pin = stm32_gpio_to_pin(gpio); 151 ctl.af = STM32_GPIO_AF0; 152 ctl.mode = STM32_GPIO_MODE_OUT; 153 ctl.pupd = STM32_GPIO_PUPD_NO; 154 ctl.speed = STM32_GPIO_SPEED_50M; 155 156 res = stm32_gpio_config(&dsc, &ctl); 157 if (res < 0) 158 goto out; 159 res = stm32_gpout_set(&dsc, value); 160 out: 161 return res; 162 } 163 164 int gpio_get_value(unsigned gpio) 165 { 166 struct stm32_gpio_dsc dsc; 167 168 dsc.port = stm32_gpio_to_port(gpio); 169 dsc.pin = stm32_gpio_to_pin(gpio); 170 171 return stm32_gpin_get(&dsc); 172 } 173 174 int gpio_set_value(unsigned gpio, int value) 175 { 176 struct stm32_gpio_dsc dsc; 177 178 dsc.port = stm32_gpio_to_port(gpio); 179 dsc.pin = stm32_gpio_to_pin(gpio); 180 181 return stm32_gpout_set(&dsc, value); 182 } 183