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_init(struct ssb_bus *bus)
  78{
  79        struct gpio_chip *chip = &bus->gpio;
  80
  81        chip->label             = "ssb_chipco_gpio";
  82        chip->owner             = THIS_MODULE;
  83        chip->request           = ssb_gpio_chipco_request;
  84        chip->free              = ssb_gpio_chipco_free;
  85        chip->get               = ssb_gpio_chipco_get_value;
  86        chip->set               = ssb_gpio_chipco_set_value;
  87        chip->direction_input   = ssb_gpio_chipco_direction_input;
  88        chip->direction_output  = ssb_gpio_chipco_direction_output;
  89        chip->ngpio             = 16;
  90        /* There is just one SoC in one device and its GPIO addresses should be
  91         * deterministic to address them more easily. The other buses could get
  92         * a random base number. */
  93        if (bus->bustype == SSB_BUSTYPE_SSB)
  94                chip->base              = 0;
  95        else
  96                chip->base              = -1;
  97
  98        return gpiochip_add(chip);
  99}
 100
 101#ifdef CONFIG_SSB_DRIVER_EXTIF
 102
 103static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio)
 104{
 105        struct ssb_bus *bus = ssb_gpio_get_bus(chip);
 106
 107        return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio);
 108}
 109
 110static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio,
 111                                     int value)
 112{
 113        struct ssb_bus *bus = ssb_gpio_get_bus(chip);
 114
 115        ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
 116}
 117
 118static int ssb_gpio_extif_direction_input(struct gpio_chip *chip,
 119                                          unsigned gpio)
 120{
 121        struct ssb_bus *bus = ssb_gpio_get_bus(chip);
 122
 123        ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0);
 124        return 0;
 125}
 126
 127static int ssb_gpio_extif_direction_output(struct gpio_chip *chip,
 128                                           unsigned gpio, int value)
 129{
 130        struct ssb_bus *bus = ssb_gpio_get_bus(chip);
 131
 132        ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio);
 133        ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
 134        return 0;
 135}
 136
 137static int ssb_gpio_extif_init(struct ssb_bus *bus)
 138{
 139        struct gpio_chip *chip = &bus->gpio;
 140
 141        chip->label             = "ssb_extif_gpio";
 142        chip->owner             = THIS_MODULE;
 143        chip->get               = ssb_gpio_extif_get_value;
 144        chip->set               = ssb_gpio_extif_set_value;
 145        chip->direction_input   = ssb_gpio_extif_direction_input;
 146        chip->direction_output  = ssb_gpio_extif_direction_output;
 147        chip->ngpio             = 5;
 148        /* There is just one SoC in one device and its GPIO addresses should be
 149         * deterministic to address them more easily. The other buses could get
 150         * a random base number. */
 151        if (bus->bustype == SSB_BUSTYPE_SSB)
 152                chip->base              = 0;
 153        else
 154                chip->base              = -1;
 155
 156        return gpiochip_add(chip);
 157}
 158
 159#else
 160static int ssb_gpio_extif_init(struct ssb_bus *bus)
 161{
 162        return -ENOTSUPP;
 163}
 164#endif
 165
 166int ssb_gpio_init(struct ssb_bus *bus)
 167{
 168        if (ssb_chipco_available(&bus->chipco))
 169                return ssb_gpio_chipco_init(bus);
 170        else if (ssb_extif_available(&bus->extif))
 171                return ssb_gpio_extif_init(bus);
 172        else
 173                SSB_WARN_ON(1);
 174
 175        return -1;
 176}
 177
 178int ssb_gpio_unregister(struct ssb_bus *bus)
 179{
 180        if (ssb_chipco_available(&bus->chipco) ||
 181            ssb_extif_available(&bus->extif)) {
 182                return gpiochip_remove(&bus->gpio);
 183        } else {
 184                SSB_WARN_ON(1);
 185        }
 186
 187        return -1;
 188}
 189
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.