1*4e779ad2SMichal Simek /* 2*4e779ad2SMichal Simek * Copyright (c) 2013 Xilinx, Michal Simek 3*4e779ad2SMichal Simek * 4*4e779ad2SMichal Simek * See file CREDITS for list of people who contributed to this 5*4e779ad2SMichal Simek * project. 6*4e779ad2SMichal Simek * 7*4e779ad2SMichal Simek * This program is free software; you can redistribute it and/or 8*4e779ad2SMichal Simek * modify it under the terms of the GNU General Public License as 9*4e779ad2SMichal Simek * published by the Free Software Foundation; either version 2 of 10*4e779ad2SMichal Simek * the License, or (at your option) any later version. 11*4e779ad2SMichal Simek * 12*4e779ad2SMichal Simek * This program is distributed in the hope that it will be useful, 13*4e779ad2SMichal Simek * but WITHOUT ANY WARRANTY; without even the implied warranty of 14*4e779ad2SMichal Simek * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15*4e779ad2SMichal Simek * GNU General Public License for more details. 16*4e779ad2SMichal Simek * 17*4e779ad2SMichal Simek * You should have received a copy of the GNU General Public License 18*4e779ad2SMichal Simek * along with this program; if not, write to the Free Software 19*4e779ad2SMichal Simek * Foundation, Inc., 59 Temple Place, Suite 330, Boston, 20*4e779ad2SMichal Simek * MA 02111-1307 USA 21*4e779ad2SMichal Simek */ 22*4e779ad2SMichal Simek 23*4e779ad2SMichal Simek #include <common.h> 24*4e779ad2SMichal Simek #include <errno.h> 25*4e779ad2SMichal Simek #include <malloc.h> 26*4e779ad2SMichal Simek #include <linux/list.h> 27*4e779ad2SMichal Simek #include <asm/io.h> 28*4e779ad2SMichal Simek #include <asm/gpio.h> 29*4e779ad2SMichal Simek 30*4e779ad2SMichal Simek static LIST_HEAD(gpio_list); 31*4e779ad2SMichal Simek 32*4e779ad2SMichal Simek enum gpio_direction { 33*4e779ad2SMichal Simek GPIO_DIRECTION_OUT = 0, 34*4e779ad2SMichal Simek GPIO_DIRECTION_IN = 1, 35*4e779ad2SMichal Simek }; 36*4e779ad2SMichal Simek 37*4e779ad2SMichal Simek /* Gpio simple map */ 38*4e779ad2SMichal Simek struct gpio_regs { 39*4e779ad2SMichal Simek u32 gpiodata; 40*4e779ad2SMichal Simek u32 gpiodir; 41*4e779ad2SMichal Simek }; 42*4e779ad2SMichal Simek 43*4e779ad2SMichal Simek #define GPIO_NAME_SIZE 10 44*4e779ad2SMichal Simek 45*4e779ad2SMichal Simek struct gpio_names { 46*4e779ad2SMichal Simek char name[GPIO_NAME_SIZE]; 47*4e779ad2SMichal Simek }; 48*4e779ad2SMichal Simek 49*4e779ad2SMichal Simek /* Initialized, rxbd_current, rx_first_buf must be 0 after init */ 50*4e779ad2SMichal Simek struct xilinx_gpio_priv { 51*4e779ad2SMichal Simek struct gpio_regs *regs; 52*4e779ad2SMichal Simek u32 gpio_min; 53*4e779ad2SMichal Simek u32 gpio_max; 54*4e779ad2SMichal Simek u32 gpiodata_store; 55*4e779ad2SMichal Simek char name[GPIO_NAME_SIZE]; 56*4e779ad2SMichal Simek struct list_head list; 57*4e779ad2SMichal Simek struct gpio_names *gpio_name; 58*4e779ad2SMichal Simek }; 59*4e779ad2SMichal Simek 60*4e779ad2SMichal Simek /* Store number of allocated gpio pins */ 61*4e779ad2SMichal Simek static u32 xilinx_gpio_max; 62*4e779ad2SMichal Simek 63*4e779ad2SMichal Simek /* Get associated gpio controller */ 64*4e779ad2SMichal Simek static struct xilinx_gpio_priv *gpio_get_controller(unsigned gpio) 65*4e779ad2SMichal Simek { 66*4e779ad2SMichal Simek struct list_head *entry; 67*4e779ad2SMichal Simek struct xilinx_gpio_priv *priv = NULL; 68*4e779ad2SMichal Simek 69*4e779ad2SMichal Simek list_for_each(entry, &gpio_list) { 70*4e779ad2SMichal Simek priv = list_entry(entry, struct xilinx_gpio_priv, list); 71*4e779ad2SMichal Simek if (gpio >= priv->gpio_min && gpio <= priv->gpio_max) { 72*4e779ad2SMichal Simek debug("%s: reg: %x, min-max: %d-%d\n", __func__, 73*4e779ad2SMichal Simek (u32)priv->regs, priv->gpio_min, priv->gpio_max); 74*4e779ad2SMichal Simek return priv; 75*4e779ad2SMichal Simek } 76*4e779ad2SMichal Simek } 77*4e779ad2SMichal Simek puts("!!!Can't get gpio controller!!!\n"); 78*4e779ad2SMichal Simek return NULL; 79*4e779ad2SMichal Simek } 80*4e779ad2SMichal Simek 81*4e779ad2SMichal Simek /* Get gpio pin name if used/setup */ 82*4e779ad2SMichal Simek static char *get_name(unsigned gpio) 83*4e779ad2SMichal Simek { 84*4e779ad2SMichal Simek u32 gpio_priv; 85*4e779ad2SMichal Simek struct xilinx_gpio_priv *priv; 86*4e779ad2SMichal Simek 87*4e779ad2SMichal Simek debug("%s\n", __func__); 88*4e779ad2SMichal Simek 89*4e779ad2SMichal Simek priv = gpio_get_controller(gpio); 90*4e779ad2SMichal Simek if (priv) { 91*4e779ad2SMichal Simek gpio_priv = gpio - priv->gpio_min; 92*4e779ad2SMichal Simek 93*4e779ad2SMichal Simek return *priv->gpio_name[gpio_priv].name ? 94*4e779ad2SMichal Simek priv->gpio_name[gpio_priv].name : "UNKNOWN"; 95*4e779ad2SMichal Simek } 96*4e779ad2SMichal Simek return "UNKNOWN"; 97*4e779ad2SMichal Simek } 98*4e779ad2SMichal Simek 99*4e779ad2SMichal Simek /* Get output value */ 100*4e779ad2SMichal Simek static int gpio_get_output_value(unsigned gpio) 101*4e779ad2SMichal Simek { 102*4e779ad2SMichal Simek u32 val, gpio_priv; 103*4e779ad2SMichal Simek struct xilinx_gpio_priv *priv = gpio_get_controller(gpio); 104*4e779ad2SMichal Simek 105*4e779ad2SMichal Simek if (priv) { 106*4e779ad2SMichal Simek gpio_priv = gpio - priv->gpio_min; 107*4e779ad2SMichal Simek val = !!(priv->gpiodata_store & (1 << gpio_priv)); 108*4e779ad2SMichal Simek debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__, 109*4e779ad2SMichal Simek (u32)priv->regs, gpio_priv, val); 110*4e779ad2SMichal Simek 111*4e779ad2SMichal Simek return val; 112*4e779ad2SMichal Simek } 113*4e779ad2SMichal Simek return -1; 114*4e779ad2SMichal Simek } 115*4e779ad2SMichal Simek 116*4e779ad2SMichal Simek /* Get input value */ 117*4e779ad2SMichal Simek static int gpio_get_input_value(unsigned gpio) 118*4e779ad2SMichal Simek { 119*4e779ad2SMichal Simek u32 val, gpio_priv; 120*4e779ad2SMichal Simek struct gpio_regs *regs; 121*4e779ad2SMichal Simek struct xilinx_gpio_priv *priv = gpio_get_controller(gpio); 122*4e779ad2SMichal Simek 123*4e779ad2SMichal Simek if (priv) { 124*4e779ad2SMichal Simek regs = priv->regs; 125*4e779ad2SMichal Simek gpio_priv = gpio - priv->gpio_min; 126*4e779ad2SMichal Simek val = readl(®s->gpiodata); 127*4e779ad2SMichal Simek val = !!(val & (1 << gpio_priv)); 128*4e779ad2SMichal Simek debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__, 129*4e779ad2SMichal Simek (u32)priv->regs, gpio_priv, val); 130*4e779ad2SMichal Simek 131*4e779ad2SMichal Simek return val; 132*4e779ad2SMichal Simek } 133*4e779ad2SMichal Simek return -1; 134*4e779ad2SMichal Simek } 135*4e779ad2SMichal Simek 136*4e779ad2SMichal Simek /* Set gpio direction */ 137*4e779ad2SMichal Simek static int gpio_set_direction(unsigned gpio, enum gpio_direction direction) 138*4e779ad2SMichal Simek { 139*4e779ad2SMichal Simek u32 val, gpio_priv; 140*4e779ad2SMichal Simek struct gpio_regs *regs; 141*4e779ad2SMichal Simek struct xilinx_gpio_priv *priv = gpio_get_controller(gpio); 142*4e779ad2SMichal Simek 143*4e779ad2SMichal Simek if (priv) { 144*4e779ad2SMichal Simek regs = priv->regs; 145*4e779ad2SMichal Simek val = readl(®s->gpiodir); 146*4e779ad2SMichal Simek 147*4e779ad2SMichal Simek gpio_priv = gpio - priv->gpio_min; 148*4e779ad2SMichal Simek if (direction == GPIO_DIRECTION_OUT) 149*4e779ad2SMichal Simek val &= ~(1 << gpio_priv); 150*4e779ad2SMichal Simek else 151*4e779ad2SMichal Simek val |= 1 << gpio_priv; 152*4e779ad2SMichal Simek 153*4e779ad2SMichal Simek writel(val, ®s->gpiodir); 154*4e779ad2SMichal Simek debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__, 155*4e779ad2SMichal Simek (u32)priv->regs, gpio_priv, val); 156*4e779ad2SMichal Simek 157*4e779ad2SMichal Simek return 0; 158*4e779ad2SMichal Simek } 159*4e779ad2SMichal Simek 160*4e779ad2SMichal Simek return -1; 161*4e779ad2SMichal Simek } 162*4e779ad2SMichal Simek 163*4e779ad2SMichal Simek /* Get gpio direction */ 164*4e779ad2SMichal Simek static int gpio_get_direction(unsigned gpio) 165*4e779ad2SMichal Simek { 166*4e779ad2SMichal Simek u32 val, gpio_priv; 167*4e779ad2SMichal Simek struct gpio_regs *regs; 168*4e779ad2SMichal Simek struct xilinx_gpio_priv *priv = gpio_get_controller(gpio); 169*4e779ad2SMichal Simek 170*4e779ad2SMichal Simek if (priv) { 171*4e779ad2SMichal Simek regs = priv->regs; 172*4e779ad2SMichal Simek gpio_priv = gpio - priv->gpio_min; 173*4e779ad2SMichal Simek val = readl(®s->gpiodir); 174*4e779ad2SMichal Simek val = !!(val & (1 << gpio_priv)); 175*4e779ad2SMichal Simek debug("%s: reg: %x, gpio_no: %d, dir: %d\n", __func__, 176*4e779ad2SMichal Simek (u32)priv->regs, gpio_priv, val); 177*4e779ad2SMichal Simek 178*4e779ad2SMichal Simek return val; 179*4e779ad2SMichal Simek } 180*4e779ad2SMichal Simek 181*4e779ad2SMichal Simek return -1; 182*4e779ad2SMichal Simek } 183*4e779ad2SMichal Simek 184*4e779ad2SMichal Simek /* 185*4e779ad2SMichal Simek * Get input value 186*4e779ad2SMichal Simek * for example gpio setup to output only can't get input value 187*4e779ad2SMichal Simek * which is breaking gpio toggle command 188*4e779ad2SMichal Simek */ 189*4e779ad2SMichal Simek int gpio_get_value(unsigned gpio) 190*4e779ad2SMichal Simek { 191*4e779ad2SMichal Simek u32 val; 192*4e779ad2SMichal Simek 193*4e779ad2SMichal Simek if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT) 194*4e779ad2SMichal Simek val = gpio_get_output_value(gpio); 195*4e779ad2SMichal Simek else 196*4e779ad2SMichal Simek val = gpio_get_input_value(gpio); 197*4e779ad2SMichal Simek 198*4e779ad2SMichal Simek return val; 199*4e779ad2SMichal Simek } 200*4e779ad2SMichal Simek 201*4e779ad2SMichal Simek /* Set output value */ 202*4e779ad2SMichal Simek static int gpio_set_output_value(unsigned gpio, int value) 203*4e779ad2SMichal Simek { 204*4e779ad2SMichal Simek u32 val, gpio_priv; 205*4e779ad2SMichal Simek struct gpio_regs *regs; 206*4e779ad2SMichal Simek struct xilinx_gpio_priv *priv = gpio_get_controller(gpio); 207*4e779ad2SMichal Simek 208*4e779ad2SMichal Simek if (priv) { 209*4e779ad2SMichal Simek regs = priv->regs; 210*4e779ad2SMichal Simek gpio_priv = gpio - priv->gpio_min; 211*4e779ad2SMichal Simek val = priv->gpiodata_store; 212*4e779ad2SMichal Simek if (value) 213*4e779ad2SMichal Simek val |= 1 << gpio_priv; 214*4e779ad2SMichal Simek else 215*4e779ad2SMichal Simek val &= ~(1 << gpio_priv); 216*4e779ad2SMichal Simek 217*4e779ad2SMichal Simek writel(val, ®s->gpiodata); 218*4e779ad2SMichal Simek debug("%s: reg: %x, gpio_no: %d, output_val: %d\n", __func__, 219*4e779ad2SMichal Simek (u32)priv->regs, gpio_priv, val); 220*4e779ad2SMichal Simek priv->gpiodata_store = val; 221*4e779ad2SMichal Simek 222*4e779ad2SMichal Simek return 0; 223*4e779ad2SMichal Simek } 224*4e779ad2SMichal Simek 225*4e779ad2SMichal Simek return -1; 226*4e779ad2SMichal Simek } 227*4e779ad2SMichal Simek 228*4e779ad2SMichal Simek int gpio_set_value(unsigned gpio, int value) 229*4e779ad2SMichal Simek { 230*4e779ad2SMichal Simek if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT) 231*4e779ad2SMichal Simek return gpio_set_output_value(gpio, value); 232*4e779ad2SMichal Simek 233*4e779ad2SMichal Simek return -1; 234*4e779ad2SMichal Simek } 235*4e779ad2SMichal Simek 236*4e779ad2SMichal Simek /* Set GPIO as input */ 237*4e779ad2SMichal Simek int gpio_direction_input(unsigned gpio) 238*4e779ad2SMichal Simek { 239*4e779ad2SMichal Simek debug("%s\n", __func__); 240*4e779ad2SMichal Simek return gpio_set_direction(gpio, GPIO_DIRECTION_IN); 241*4e779ad2SMichal Simek } 242*4e779ad2SMichal Simek 243*4e779ad2SMichal Simek /* Setup GPIO as output and set output value */ 244*4e779ad2SMichal Simek int gpio_direction_output(unsigned gpio, int value) 245*4e779ad2SMichal Simek { 246*4e779ad2SMichal Simek int ret = gpio_set_direction(gpio, GPIO_DIRECTION_OUT); 247*4e779ad2SMichal Simek 248*4e779ad2SMichal Simek debug("%s\n", __func__); 249*4e779ad2SMichal Simek 250*4e779ad2SMichal Simek if (ret < 0) 251*4e779ad2SMichal Simek return ret; 252*4e779ad2SMichal Simek 253*4e779ad2SMichal Simek return gpio_set_output_value(gpio, value); 254*4e779ad2SMichal Simek } 255*4e779ad2SMichal Simek 256*4e779ad2SMichal Simek /* Show gpio status */ 257*4e779ad2SMichal Simek void gpio_info(void) 258*4e779ad2SMichal Simek { 259*4e779ad2SMichal Simek unsigned gpio; 260*4e779ad2SMichal Simek 261*4e779ad2SMichal Simek struct list_head *entry; 262*4e779ad2SMichal Simek struct xilinx_gpio_priv *priv = NULL; 263*4e779ad2SMichal Simek 264*4e779ad2SMichal Simek list_for_each(entry, &gpio_list) { 265*4e779ad2SMichal Simek priv = list_entry(entry, struct xilinx_gpio_priv, list); 266*4e779ad2SMichal Simek printf("\n%s: %s/%x (%d-%d)\n", __func__, priv->name, 267*4e779ad2SMichal Simek (u32)priv->regs, priv->gpio_min, priv->gpio_max); 268*4e779ad2SMichal Simek 269*4e779ad2SMichal Simek for (gpio = priv->gpio_min; gpio <= priv->gpio_max; gpio++) { 270*4e779ad2SMichal Simek printf("GPIO_%d:\t%s is an ", gpio, get_name(gpio)); 271*4e779ad2SMichal Simek if (gpio_get_direction(gpio) == GPIO_DIRECTION_OUT) 272*4e779ad2SMichal Simek printf("OUTPUT value = %d\n", 273*4e779ad2SMichal Simek gpio_get_output_value(gpio)); 274*4e779ad2SMichal Simek else 275*4e779ad2SMichal Simek printf("INPUT value = %d\n", 276*4e779ad2SMichal Simek gpio_get_input_value(gpio)); 277*4e779ad2SMichal Simek } 278*4e779ad2SMichal Simek } 279*4e779ad2SMichal Simek } 280*4e779ad2SMichal Simek 281*4e779ad2SMichal Simek int gpio_request(unsigned gpio, const char *label) 282*4e779ad2SMichal Simek { 283*4e779ad2SMichal Simek u32 gpio_priv; 284*4e779ad2SMichal Simek struct xilinx_gpio_priv *priv; 285*4e779ad2SMichal Simek 286*4e779ad2SMichal Simek if (gpio >= xilinx_gpio_max) 287*4e779ad2SMichal Simek return -EINVAL; 288*4e779ad2SMichal Simek 289*4e779ad2SMichal Simek priv = gpio_get_controller(gpio); 290*4e779ad2SMichal Simek if (priv) { 291*4e779ad2SMichal Simek gpio_priv = gpio - priv->gpio_min; 292*4e779ad2SMichal Simek 293*4e779ad2SMichal Simek if (label != NULL) { 294*4e779ad2SMichal Simek strncpy(priv->gpio_name[gpio_priv].name, label, 295*4e779ad2SMichal Simek GPIO_NAME_SIZE); 296*4e779ad2SMichal Simek priv->gpio_name[gpio_priv].name[GPIO_NAME_SIZE - 1] = 297*4e779ad2SMichal Simek '\0'; 298*4e779ad2SMichal Simek } 299*4e779ad2SMichal Simek return 0; 300*4e779ad2SMichal Simek } 301*4e779ad2SMichal Simek 302*4e779ad2SMichal Simek return -1; 303*4e779ad2SMichal Simek } 304*4e779ad2SMichal Simek 305*4e779ad2SMichal Simek int gpio_free(unsigned gpio) 306*4e779ad2SMichal Simek { 307*4e779ad2SMichal Simek u32 gpio_priv; 308*4e779ad2SMichal Simek struct xilinx_gpio_priv *priv; 309*4e779ad2SMichal Simek 310*4e779ad2SMichal Simek if (gpio >= xilinx_gpio_max) 311*4e779ad2SMichal Simek return -EINVAL; 312*4e779ad2SMichal Simek 313*4e779ad2SMichal Simek priv = gpio_get_controller(gpio); 314*4e779ad2SMichal Simek if (priv) { 315*4e779ad2SMichal Simek gpio_priv = gpio - priv->gpio_min; 316*4e779ad2SMichal Simek priv->gpio_name[gpio_priv].name[0] = '\0'; 317*4e779ad2SMichal Simek 318*4e779ad2SMichal Simek /* Do nothing here */ 319*4e779ad2SMichal Simek return 0; 320*4e779ad2SMichal Simek } 321*4e779ad2SMichal Simek 322*4e779ad2SMichal Simek return -1; 323*4e779ad2SMichal Simek } 324*4e779ad2SMichal Simek 325*4e779ad2SMichal Simek int gpio_alloc(u32 baseaddr, const char *name, u32 gpio_no) 326*4e779ad2SMichal Simek { 327*4e779ad2SMichal Simek struct xilinx_gpio_priv *priv; 328*4e779ad2SMichal Simek 329*4e779ad2SMichal Simek priv = calloc(1, sizeof(struct xilinx_gpio_priv)); 330*4e779ad2SMichal Simek 331*4e779ad2SMichal Simek /* Setup gpio name */ 332*4e779ad2SMichal Simek if (name != NULL) { 333*4e779ad2SMichal Simek strncpy(priv->name, name, GPIO_NAME_SIZE); 334*4e779ad2SMichal Simek priv->name[GPIO_NAME_SIZE - 1] = '\0'; 335*4e779ad2SMichal Simek } 336*4e779ad2SMichal Simek priv->regs = (struct gpio_regs *)baseaddr; 337*4e779ad2SMichal Simek 338*4e779ad2SMichal Simek priv->gpio_min = xilinx_gpio_max; 339*4e779ad2SMichal Simek xilinx_gpio_max = priv->gpio_min + gpio_no; 340*4e779ad2SMichal Simek priv->gpio_max = xilinx_gpio_max - 1; 341*4e779ad2SMichal Simek 342*4e779ad2SMichal Simek priv->gpio_name = calloc(gpio_no, sizeof(struct gpio_names)); 343*4e779ad2SMichal Simek 344*4e779ad2SMichal Simek INIT_LIST_HEAD(&priv->list); 345*4e779ad2SMichal Simek list_add_tail(&priv->list, &gpio_list); 346*4e779ad2SMichal Simek 347*4e779ad2SMichal Simek printf("%s: Add %s (%d-%d)\n", __func__, name, 348*4e779ad2SMichal Simek priv->gpio_min, priv->gpio_max); 349*4e779ad2SMichal Simek 350*4e779ad2SMichal Simek /* Return the first gpio allocated for this device */ 351*4e779ad2SMichal Simek return priv->gpio_min; 352*4e779ad2SMichal Simek } 353*4e779ad2SMichal Simek 354*4e779ad2SMichal Simek /* Dual channel gpio is one IP with two independent channels */ 355*4e779ad2SMichal Simek int gpio_alloc_dual(u32 baseaddr, const char *name, u32 gpio_no0, u32 gpio_no1) 356*4e779ad2SMichal Simek { 357*4e779ad2SMichal Simek int ret; 358*4e779ad2SMichal Simek 359*4e779ad2SMichal Simek ret = gpio_alloc(baseaddr, name, gpio_no0); 360*4e779ad2SMichal Simek gpio_alloc(baseaddr + 8, strcat((char *)name, "_1"), gpio_no1); 361*4e779ad2SMichal Simek 362*4e779ad2SMichal Simek /* Return the first gpio allocated for this device */ 363*4e779ad2SMichal Simek return ret; 364*4e779ad2SMichal Simek } 365