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