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