1*ec43b08bSHauke Mehrtens /* 2*ec43b08bSHauke Mehrtens * Sonics Silicon Backplane 3*ec43b08bSHauke Mehrtens * GPIO driver 4*ec43b08bSHauke Mehrtens * 5*ec43b08bSHauke Mehrtens * Copyright 2011, Broadcom Corporation 6*ec43b08bSHauke Mehrtens * Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de> 7*ec43b08bSHauke Mehrtens * 8*ec43b08bSHauke Mehrtens * Licensed under the GNU/GPL. See COPYING for details. 9*ec43b08bSHauke Mehrtens */ 10*ec43b08bSHauke Mehrtens 11*ec43b08bSHauke Mehrtens #include <linux/gpio.h> 12*ec43b08bSHauke Mehrtens #include <linux/export.h> 13*ec43b08bSHauke Mehrtens #include <linux/ssb/ssb.h> 14*ec43b08bSHauke Mehrtens 15*ec43b08bSHauke Mehrtens #include "ssb_private.h" 16*ec43b08bSHauke Mehrtens 17*ec43b08bSHauke Mehrtens static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip) 18*ec43b08bSHauke Mehrtens { 19*ec43b08bSHauke Mehrtens return container_of(chip, struct ssb_bus, gpio); 20*ec43b08bSHauke Mehrtens } 21*ec43b08bSHauke Mehrtens 22*ec43b08bSHauke Mehrtens static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio) 23*ec43b08bSHauke Mehrtens { 24*ec43b08bSHauke Mehrtens struct ssb_bus *bus = ssb_gpio_get_bus(chip); 25*ec43b08bSHauke Mehrtens 26*ec43b08bSHauke Mehrtens return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio); 27*ec43b08bSHauke Mehrtens } 28*ec43b08bSHauke Mehrtens 29*ec43b08bSHauke Mehrtens static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio, 30*ec43b08bSHauke Mehrtens int value) 31*ec43b08bSHauke Mehrtens { 32*ec43b08bSHauke Mehrtens struct ssb_bus *bus = ssb_gpio_get_bus(chip); 33*ec43b08bSHauke Mehrtens 34*ec43b08bSHauke Mehrtens ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0); 35*ec43b08bSHauke Mehrtens } 36*ec43b08bSHauke Mehrtens 37*ec43b08bSHauke Mehrtens static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip, 38*ec43b08bSHauke Mehrtens unsigned gpio) 39*ec43b08bSHauke Mehrtens { 40*ec43b08bSHauke Mehrtens struct ssb_bus *bus = ssb_gpio_get_bus(chip); 41*ec43b08bSHauke Mehrtens 42*ec43b08bSHauke Mehrtens ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0); 43*ec43b08bSHauke Mehrtens return 0; 44*ec43b08bSHauke Mehrtens } 45*ec43b08bSHauke Mehrtens 46*ec43b08bSHauke Mehrtens static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip, 47*ec43b08bSHauke Mehrtens unsigned gpio, int value) 48*ec43b08bSHauke Mehrtens { 49*ec43b08bSHauke Mehrtens struct ssb_bus *bus = ssb_gpio_get_bus(chip); 50*ec43b08bSHauke Mehrtens 51*ec43b08bSHauke Mehrtens ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio); 52*ec43b08bSHauke Mehrtens ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0); 53*ec43b08bSHauke Mehrtens return 0; 54*ec43b08bSHauke Mehrtens } 55*ec43b08bSHauke Mehrtens 56*ec43b08bSHauke Mehrtens static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio) 57*ec43b08bSHauke Mehrtens { 58*ec43b08bSHauke Mehrtens struct ssb_bus *bus = ssb_gpio_get_bus(chip); 59*ec43b08bSHauke Mehrtens 60*ec43b08bSHauke Mehrtens ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0); 61*ec43b08bSHauke Mehrtens /* clear pulldown */ 62*ec43b08bSHauke Mehrtens ssb_chipco_gpio_pulldown(&bus->chipco, 1 << gpio, 0); 63*ec43b08bSHauke Mehrtens /* Set pullup */ 64*ec43b08bSHauke Mehrtens ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 1 << gpio); 65*ec43b08bSHauke Mehrtens 66*ec43b08bSHauke Mehrtens return 0; 67*ec43b08bSHauke Mehrtens } 68*ec43b08bSHauke Mehrtens 69*ec43b08bSHauke Mehrtens static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio) 70*ec43b08bSHauke Mehrtens { 71*ec43b08bSHauke Mehrtens struct ssb_bus *bus = ssb_gpio_get_bus(chip); 72*ec43b08bSHauke Mehrtens 73*ec43b08bSHauke Mehrtens /* clear pullup */ 74*ec43b08bSHauke Mehrtens ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0); 75*ec43b08bSHauke Mehrtens } 76*ec43b08bSHauke Mehrtens 77*ec43b08bSHauke Mehrtens static int ssb_gpio_chipco_init(struct ssb_bus *bus) 78*ec43b08bSHauke Mehrtens { 79*ec43b08bSHauke Mehrtens struct gpio_chip *chip = &bus->gpio; 80*ec43b08bSHauke Mehrtens 81*ec43b08bSHauke Mehrtens chip->label = "ssb_chipco_gpio"; 82*ec43b08bSHauke Mehrtens chip->owner = THIS_MODULE; 83*ec43b08bSHauke Mehrtens chip->request = ssb_gpio_chipco_request; 84*ec43b08bSHauke Mehrtens chip->free = ssb_gpio_chipco_free; 85*ec43b08bSHauke Mehrtens chip->get = ssb_gpio_chipco_get_value; 86*ec43b08bSHauke Mehrtens chip->set = ssb_gpio_chipco_set_value; 87*ec43b08bSHauke Mehrtens chip->direction_input = ssb_gpio_chipco_direction_input; 88*ec43b08bSHauke Mehrtens chip->direction_output = ssb_gpio_chipco_direction_output; 89*ec43b08bSHauke Mehrtens chip->ngpio = 16; 90*ec43b08bSHauke Mehrtens /* There is just one SoC in one device and its GPIO addresses should be 91*ec43b08bSHauke Mehrtens * deterministic to address them more easily. The other buses could get 92*ec43b08bSHauke Mehrtens * a random base number. */ 93*ec43b08bSHauke Mehrtens if (bus->bustype == SSB_BUSTYPE_SSB) 94*ec43b08bSHauke Mehrtens chip->base = 0; 95*ec43b08bSHauke Mehrtens else 96*ec43b08bSHauke Mehrtens chip->base = -1; 97*ec43b08bSHauke Mehrtens 98*ec43b08bSHauke Mehrtens return gpiochip_add(chip); 99*ec43b08bSHauke Mehrtens } 100*ec43b08bSHauke Mehrtens 101*ec43b08bSHauke Mehrtens #ifdef CONFIG_SSB_DRIVER_EXTIF 102*ec43b08bSHauke Mehrtens 103*ec43b08bSHauke Mehrtens static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio) 104*ec43b08bSHauke Mehrtens { 105*ec43b08bSHauke Mehrtens struct ssb_bus *bus = ssb_gpio_get_bus(chip); 106*ec43b08bSHauke Mehrtens 107*ec43b08bSHauke Mehrtens return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio); 108*ec43b08bSHauke Mehrtens } 109*ec43b08bSHauke Mehrtens 110*ec43b08bSHauke Mehrtens static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio, 111*ec43b08bSHauke Mehrtens int value) 112*ec43b08bSHauke Mehrtens { 113*ec43b08bSHauke Mehrtens struct ssb_bus *bus = ssb_gpio_get_bus(chip); 114*ec43b08bSHauke Mehrtens 115*ec43b08bSHauke Mehrtens ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0); 116*ec43b08bSHauke Mehrtens } 117*ec43b08bSHauke Mehrtens 118*ec43b08bSHauke Mehrtens static int ssb_gpio_extif_direction_input(struct gpio_chip *chip, 119*ec43b08bSHauke Mehrtens unsigned gpio) 120*ec43b08bSHauke Mehrtens { 121*ec43b08bSHauke Mehrtens struct ssb_bus *bus = ssb_gpio_get_bus(chip); 122*ec43b08bSHauke Mehrtens 123*ec43b08bSHauke Mehrtens ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0); 124*ec43b08bSHauke Mehrtens return 0; 125*ec43b08bSHauke Mehrtens } 126*ec43b08bSHauke Mehrtens 127*ec43b08bSHauke Mehrtens static int ssb_gpio_extif_direction_output(struct gpio_chip *chip, 128*ec43b08bSHauke Mehrtens unsigned gpio, int value) 129*ec43b08bSHauke Mehrtens { 130*ec43b08bSHauke Mehrtens struct ssb_bus *bus = ssb_gpio_get_bus(chip); 131*ec43b08bSHauke Mehrtens 132*ec43b08bSHauke Mehrtens ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio); 133*ec43b08bSHauke Mehrtens ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0); 134*ec43b08bSHauke Mehrtens return 0; 135*ec43b08bSHauke Mehrtens } 136*ec43b08bSHauke Mehrtens 137*ec43b08bSHauke Mehrtens static int ssb_gpio_extif_init(struct ssb_bus *bus) 138*ec43b08bSHauke Mehrtens { 139*ec43b08bSHauke Mehrtens struct gpio_chip *chip = &bus->gpio; 140*ec43b08bSHauke Mehrtens 141*ec43b08bSHauke Mehrtens chip->label = "ssb_extif_gpio"; 142*ec43b08bSHauke Mehrtens chip->owner = THIS_MODULE; 143*ec43b08bSHauke Mehrtens chip->get = ssb_gpio_extif_get_value; 144*ec43b08bSHauke Mehrtens chip->set = ssb_gpio_extif_set_value; 145*ec43b08bSHauke Mehrtens chip->direction_input = ssb_gpio_extif_direction_input; 146*ec43b08bSHauke Mehrtens chip->direction_output = ssb_gpio_extif_direction_output; 147*ec43b08bSHauke Mehrtens chip->ngpio = 5; 148*ec43b08bSHauke Mehrtens /* There is just one SoC in one device and its GPIO addresses should be 149*ec43b08bSHauke Mehrtens * deterministic to address them more easily. The other buses could get 150*ec43b08bSHauke Mehrtens * a random base number. */ 151*ec43b08bSHauke Mehrtens if (bus->bustype == SSB_BUSTYPE_SSB) 152*ec43b08bSHauke Mehrtens chip->base = 0; 153*ec43b08bSHauke Mehrtens else 154*ec43b08bSHauke Mehrtens chip->base = -1; 155*ec43b08bSHauke Mehrtens 156*ec43b08bSHauke Mehrtens return gpiochip_add(chip); 157*ec43b08bSHauke Mehrtens } 158*ec43b08bSHauke Mehrtens 159*ec43b08bSHauke Mehrtens #else 160*ec43b08bSHauke Mehrtens static int ssb_gpio_extif_init(struct ssb_bus *bus) 161*ec43b08bSHauke Mehrtens { 162*ec43b08bSHauke Mehrtens return -ENOTSUPP; 163*ec43b08bSHauke Mehrtens } 164*ec43b08bSHauke Mehrtens #endif 165*ec43b08bSHauke Mehrtens 166*ec43b08bSHauke Mehrtens int ssb_gpio_init(struct ssb_bus *bus) 167*ec43b08bSHauke Mehrtens { 168*ec43b08bSHauke Mehrtens if (ssb_chipco_available(&bus->chipco)) 169*ec43b08bSHauke Mehrtens return ssb_gpio_chipco_init(bus); 170*ec43b08bSHauke Mehrtens else if (ssb_extif_available(&bus->extif)) 171*ec43b08bSHauke Mehrtens return ssb_gpio_extif_init(bus); 172*ec43b08bSHauke Mehrtens else 173*ec43b08bSHauke Mehrtens SSB_WARN_ON(1); 174*ec43b08bSHauke Mehrtens 175*ec43b08bSHauke Mehrtens return -1; 176*ec43b08bSHauke Mehrtens } 177