1*84dee301SMathieu J. Poirier /* 2*84dee301SMathieu J. Poirier * Code ported from Nomadik GPIO driver in ST-Ericsson Linux kernel code. 3*84dee301SMathieu J. Poirier * The purpose is that GPIO config found in kernel should work by simply 4*84dee301SMathieu J. Poirier * copy-paste it to U-boot. 5*84dee301SMathieu J. Poirier * 6*84dee301SMathieu J. Poirier * Original Linux authors: 7*84dee301SMathieu J. Poirier * Copyright (C) 2008,2009 STMicroelectronics 8*84dee301SMathieu J. Poirier * Copyright (C) 2009 Alessandro Rubini <rubini@unipv.it> 9*84dee301SMathieu J. Poirier * Rewritten based on work by Prafulla WADASKAR <prafulla.wadaskar@st.com> 10*84dee301SMathieu J. Poirier * 11*84dee301SMathieu J. Poirier * Ported to U-boot by: 12*84dee301SMathieu J. Poirier * Copyright (C) 2010 Joakim Axelsson <joakim.axelsson AT stericsson.com> 13*84dee301SMathieu J. Poirier * 14*84dee301SMathieu J. Poirier * This program is free software; you can redistribute it and/or modify 15*84dee301SMathieu J. Poirier * it under the terms of the GNU General Public License version 2 as 16*84dee301SMathieu J. Poirier * published by the Free Software Foundation. 17*84dee301SMathieu J. Poirier */ 18*84dee301SMathieu J. Poirier 19*84dee301SMathieu J. Poirier #include <common.h> 20*84dee301SMathieu J. Poirier #include <asm/io.h> 21*84dee301SMathieu J. Poirier 22*84dee301SMathieu J. Poirier #include <asm/arch/db8500_gpio.h> 23*84dee301SMathieu J. Poirier #include <asm/arch/db8500_pincfg.h> 24*84dee301SMathieu J. Poirier #include <linux/compiler.h> 25*84dee301SMathieu J. Poirier 26*84dee301SMathieu J. Poirier #define IO_ADDR(x) (void *) (x) 27*84dee301SMathieu J. Poirier 28*84dee301SMathieu J. Poirier /* 29*84dee301SMathieu J. Poirier * The GPIO module in the db8500 Systems-on-Chip is an 30*84dee301SMathieu J. Poirier * AMBA device, managing 32 pins and alternate functions. The logic block 31*84dee301SMathieu J. Poirier * is currently only used in the db8500. 32*84dee301SMathieu J. Poirier */ 33*84dee301SMathieu J. Poirier 34*84dee301SMathieu J. Poirier #define GPIO_TOTAL_PINS 268 35*84dee301SMathieu J. Poirier #define GPIO_PINS_PER_BLOCK 32 36*84dee301SMathieu J. Poirier #define GPIO_BLOCKS_COUNT (GPIO_TOTAL_PINS/GPIO_PINS_PER_BLOCK + 1) 37*84dee301SMathieu J. Poirier #define GPIO_BLOCK(pin) (((pin + GPIO_PINS_PER_BLOCK) >> 5) - 1) 38*84dee301SMathieu J. Poirier #define GPIO_PIN_WITHIN_BLOCK(pin) ((pin)%(GPIO_PINS_PER_BLOCK)) 39*84dee301SMathieu J. Poirier 40*84dee301SMathieu J. Poirier /* Register in the logic block */ 41*84dee301SMathieu J. Poirier #define DB8500_GPIO_DAT 0x00 42*84dee301SMathieu J. Poirier #define DB8500_GPIO_DATS 0x04 43*84dee301SMathieu J. Poirier #define DB8500_GPIO_DATC 0x08 44*84dee301SMathieu J. Poirier #define DB8500_GPIO_PDIS 0x0c 45*84dee301SMathieu J. Poirier #define DB8500_GPIO_DIR 0x10 46*84dee301SMathieu J. Poirier #define DB8500_GPIO_DIRS 0x14 47*84dee301SMathieu J. Poirier #define DB8500_GPIO_DIRC 0x18 48*84dee301SMathieu J. Poirier #define DB8500_GPIO_SLPC 0x1c 49*84dee301SMathieu J. Poirier #define DB8500_GPIO_AFSLA 0x20 50*84dee301SMathieu J. Poirier #define DB8500_GPIO_AFSLB 0x24 51*84dee301SMathieu J. Poirier 52*84dee301SMathieu J. Poirier #define DB8500_GPIO_RIMSC 0x40 53*84dee301SMathieu J. Poirier #define DB8500_GPIO_FIMSC 0x44 54*84dee301SMathieu J. Poirier #define DB8500_GPIO_IS 0x48 55*84dee301SMathieu J. Poirier #define DB8500_GPIO_IC 0x4c 56*84dee301SMathieu J. Poirier #define DB8500_GPIO_RWIMSC 0x50 57*84dee301SMathieu J. Poirier #define DB8500_GPIO_FWIMSC 0x54 58*84dee301SMathieu J. Poirier #define DB8500_GPIO_WKS 0x58 59*84dee301SMathieu J. Poirier 60*84dee301SMathieu J. Poirier static void __iomem *get_gpio_addr(unsigned gpio) 61*84dee301SMathieu J. Poirier { 62*84dee301SMathieu J. Poirier /* Our list of GPIO chips */ 63*84dee301SMathieu J. Poirier static void __iomem *gpio_addrs[GPIO_BLOCKS_COUNT] = { 64*84dee301SMathieu J. Poirier IO_ADDR(CFG_GPIO_0_BASE), 65*84dee301SMathieu J. Poirier IO_ADDR(CFG_GPIO_1_BASE), 66*84dee301SMathieu J. Poirier IO_ADDR(CFG_GPIO_2_BASE), 67*84dee301SMathieu J. Poirier IO_ADDR(CFG_GPIO_3_BASE), 68*84dee301SMathieu J. Poirier IO_ADDR(CFG_GPIO_4_BASE), 69*84dee301SMathieu J. Poirier IO_ADDR(CFG_GPIO_5_BASE), 70*84dee301SMathieu J. Poirier IO_ADDR(CFG_GPIO_6_BASE), 71*84dee301SMathieu J. Poirier IO_ADDR(CFG_GPIO_7_BASE), 72*84dee301SMathieu J. Poirier IO_ADDR(CFG_GPIO_8_BASE) 73*84dee301SMathieu J. Poirier }; 74*84dee301SMathieu J. Poirier 75*84dee301SMathieu J. Poirier return gpio_addrs[GPIO_BLOCK(gpio)]; 76*84dee301SMathieu J. Poirier } 77*84dee301SMathieu J. Poirier 78*84dee301SMathieu J. Poirier static unsigned get_gpio_offset(unsigned gpio) 79*84dee301SMathieu J. Poirier { 80*84dee301SMathieu J. Poirier return GPIO_PIN_WITHIN_BLOCK(gpio); 81*84dee301SMathieu J. Poirier } 82*84dee301SMathieu J. Poirier 83*84dee301SMathieu J. Poirier /* Can only be called from config_pin. Don't configure alt-mode directly */ 84*84dee301SMathieu J. Poirier static void gpio_set_mode(unsigned gpio, enum db8500_gpio_alt mode) 85*84dee301SMathieu J. Poirier { 86*84dee301SMathieu J. Poirier void __iomem *addr = get_gpio_addr(gpio); 87*84dee301SMathieu J. Poirier unsigned offset = get_gpio_offset(gpio); 88*84dee301SMathieu J. Poirier u32 bit = 1 << offset; 89*84dee301SMathieu J. Poirier u32 afunc, bfunc; 90*84dee301SMathieu J. Poirier 91*84dee301SMathieu J. Poirier afunc = readl(addr + DB8500_GPIO_AFSLA) & ~bit; 92*84dee301SMathieu J. Poirier bfunc = readl(addr + DB8500_GPIO_AFSLB) & ~bit; 93*84dee301SMathieu J. Poirier if (mode & DB8500_GPIO_ALT_A) 94*84dee301SMathieu J. Poirier afunc |= bit; 95*84dee301SMathieu J. Poirier if (mode & DB8500_GPIO_ALT_B) 96*84dee301SMathieu J. Poirier bfunc |= bit; 97*84dee301SMathieu J. Poirier writel(afunc, addr + DB8500_GPIO_AFSLA); 98*84dee301SMathieu J. Poirier writel(bfunc, addr + DB8500_GPIO_AFSLB); 99*84dee301SMathieu J. Poirier } 100*84dee301SMathieu J. Poirier 101*84dee301SMathieu J. Poirier /** 102*84dee301SMathieu J. Poirier * db8500_gpio_set_pull() - enable/disable pull up/down on a gpio 103*84dee301SMathieu J. Poirier * @gpio: pin number 104*84dee301SMathieu J. Poirier * @pull: one of DB8500_GPIO_PULL_DOWN, DB8500_GPIO_PULL_UP, 105*84dee301SMathieu J. Poirier * and DB8500_GPIO_PULL_NONE 106*84dee301SMathieu J. Poirier * 107*84dee301SMathieu J. Poirier * Enables/disables pull up/down on a specified pin. This only takes effect if 108*84dee301SMathieu J. Poirier * the pin is configured as an input (either explicitly or by the alternate 109*84dee301SMathieu J. Poirier * function). 110*84dee301SMathieu J. Poirier * 111*84dee301SMathieu J. Poirier * NOTE: If enabling the pull up/down, the caller must ensure that the GPIO is 112*84dee301SMathieu J. Poirier * configured as an input. Otherwise, due to the way the controller registers 113*84dee301SMathieu J. Poirier * work, this function will change the value output on the pin. 114*84dee301SMathieu J. Poirier */ 115*84dee301SMathieu J. Poirier void db8500_gpio_set_pull(unsigned gpio, enum db8500_gpio_pull pull) 116*84dee301SMathieu J. Poirier { 117*84dee301SMathieu J. Poirier void __iomem *addr = get_gpio_addr(gpio); 118*84dee301SMathieu J. Poirier unsigned offset = get_gpio_offset(gpio); 119*84dee301SMathieu J. Poirier u32 bit = 1 << offset; 120*84dee301SMathieu J. Poirier u32 pdis; 121*84dee301SMathieu J. Poirier 122*84dee301SMathieu J. Poirier pdis = readl(addr + DB8500_GPIO_PDIS); 123*84dee301SMathieu J. Poirier if (pull == DB8500_GPIO_PULL_NONE) 124*84dee301SMathieu J. Poirier pdis |= bit; 125*84dee301SMathieu J. Poirier else 126*84dee301SMathieu J. Poirier pdis &= ~bit; 127*84dee301SMathieu J. Poirier writel(pdis, addr + DB8500_GPIO_PDIS); 128*84dee301SMathieu J. Poirier 129*84dee301SMathieu J. Poirier if (pull == DB8500_GPIO_PULL_UP) 130*84dee301SMathieu J. Poirier writel(bit, addr + DB8500_GPIO_DATS); 131*84dee301SMathieu J. Poirier else if (pull == DB8500_GPIO_PULL_DOWN) 132*84dee301SMathieu J. Poirier writel(bit, addr + DB8500_GPIO_DATC); 133*84dee301SMathieu J. Poirier } 134*84dee301SMathieu J. Poirier 135*84dee301SMathieu J. Poirier void db8500_gpio_make_input(unsigned gpio) 136*84dee301SMathieu J. Poirier { 137*84dee301SMathieu J. Poirier void __iomem *addr = get_gpio_addr(gpio); 138*84dee301SMathieu J. Poirier unsigned offset = get_gpio_offset(gpio); 139*84dee301SMathieu J. Poirier 140*84dee301SMathieu J. Poirier writel(1 << offset, addr + DB8500_GPIO_DIRC); 141*84dee301SMathieu J. Poirier } 142*84dee301SMathieu J. Poirier 143*84dee301SMathieu J. Poirier int db8500_gpio_get_input(unsigned gpio) 144*84dee301SMathieu J. Poirier { 145*84dee301SMathieu J. Poirier void __iomem *addr = get_gpio_addr(gpio); 146*84dee301SMathieu J. Poirier unsigned offset = get_gpio_offset(gpio); 147*84dee301SMathieu J. Poirier u32 bit = 1 << offset; 148*84dee301SMathieu J. Poirier 149*84dee301SMathieu J. Poirier printf("db8500_gpio_get_input gpio=%u addr=%p offset=%u bit=%#x\n", 150*84dee301SMathieu J. Poirier gpio, addr, offset, bit); 151*84dee301SMathieu J. Poirier 152*84dee301SMathieu J. Poirier return (readl(addr + DB8500_GPIO_DAT) & bit) != 0; 153*84dee301SMathieu J. Poirier } 154*84dee301SMathieu J. Poirier 155*84dee301SMathieu J. Poirier void db8500_gpio_make_output(unsigned gpio, int val) 156*84dee301SMathieu J. Poirier { 157*84dee301SMathieu J. Poirier void __iomem *addr = get_gpio_addr(gpio); 158*84dee301SMathieu J. Poirier unsigned offset = get_gpio_offset(gpio); 159*84dee301SMathieu J. Poirier 160*84dee301SMathieu J. Poirier writel(1 << offset, addr + DB8500_GPIO_DIRS); 161*84dee301SMathieu J. Poirier db8500_gpio_set_output(gpio, val); 162*84dee301SMathieu J. Poirier } 163*84dee301SMathieu J. Poirier 164*84dee301SMathieu J. Poirier void db8500_gpio_set_output(unsigned gpio, int val) 165*84dee301SMathieu J. Poirier { 166*84dee301SMathieu J. Poirier void __iomem *addr = get_gpio_addr(gpio); 167*84dee301SMathieu J. Poirier unsigned offset = get_gpio_offset(gpio); 168*84dee301SMathieu J. Poirier 169*84dee301SMathieu J. Poirier if (val) 170*84dee301SMathieu J. Poirier writel(1 << offset, addr + DB8500_GPIO_DATS); 171*84dee301SMathieu J. Poirier else 172*84dee301SMathieu J. Poirier writel(1 << offset, addr + DB8500_GPIO_DATC); 173*84dee301SMathieu J. Poirier } 174*84dee301SMathieu J. Poirier 175*84dee301SMathieu J. Poirier /** 176*84dee301SMathieu J. Poirier * config_pin - configure a pin's mux attributes 177*84dee301SMathieu J. Poirier * @cfg: pin confguration 178*84dee301SMathieu J. Poirier * 179*84dee301SMathieu J. Poirier * Configures a pin's mode (alternate function or GPIO), its pull up status, 180*84dee301SMathieu J. Poirier * and its sleep mode based on the specified configuration. The @cfg is 181*84dee301SMathieu J. Poirier * usually one of the SoC specific macros defined in mach/<soc>-pins.h. These 182*84dee301SMathieu J. Poirier * are constructed using, and can be further enhanced with, the macros in 183*84dee301SMathieu J. Poirier * plat/pincfg.h. 184*84dee301SMathieu J. Poirier * 185*84dee301SMathieu J. Poirier * If a pin's mode is set to GPIO, it is configured as an input to avoid 186*84dee301SMathieu J. Poirier * side-effects. The gpio can be manipulated later using standard GPIO API 187*84dee301SMathieu J. Poirier * calls. 188*84dee301SMathieu J. Poirier */ 189*84dee301SMathieu J. Poirier static void config_pin(unsigned long cfg) 190*84dee301SMathieu J. Poirier { 191*84dee301SMathieu J. Poirier int pin = PIN_NUM(cfg); 192*84dee301SMathieu J. Poirier int pull = PIN_PULL(cfg); 193*84dee301SMathieu J. Poirier int af = PIN_ALT(cfg); 194*84dee301SMathieu J. Poirier int output = PIN_DIR(cfg); 195*84dee301SMathieu J. Poirier int val = PIN_VAL(cfg); 196*84dee301SMathieu J. Poirier 197*84dee301SMathieu J. Poirier if (output) 198*84dee301SMathieu J. Poirier db8500_gpio_make_output(pin, val); 199*84dee301SMathieu J. Poirier else { 200*84dee301SMathieu J. Poirier db8500_gpio_make_input(pin); 201*84dee301SMathieu J. Poirier db8500_gpio_set_pull(pin, pull); 202*84dee301SMathieu J. Poirier } 203*84dee301SMathieu J. Poirier 204*84dee301SMathieu J. Poirier gpio_set_mode(pin, af); 205*84dee301SMathieu J. Poirier } 206*84dee301SMathieu J. Poirier 207*84dee301SMathieu J. Poirier /** 208*84dee301SMathieu J. Poirier * db8500_config_pins - configure several pins at once 209*84dee301SMathieu J. Poirier * @cfgs: array of pin configurations 210*84dee301SMathieu J. Poirier * @num: number of elments in the array 211*84dee301SMathieu J. Poirier * 212*84dee301SMathieu J. Poirier * Configures several pins using config_pin(). Refer to that function for 213*84dee301SMathieu J. Poirier * further information. 214*84dee301SMathieu J. Poirier */ 215*84dee301SMathieu J. Poirier void db8500_gpio_config_pins(unsigned long *cfgs, size_t num) 216*84dee301SMathieu J. Poirier { 217*84dee301SMathieu J. Poirier size_t i; 218*84dee301SMathieu J. Poirier 219*84dee301SMathieu J. Poirier for (i = 0; i < num; i++) 220*84dee301SMathieu J. Poirier config_pin(cfgs[i]); 221*84dee301SMathieu J. Poirier } 222