Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 344167
b: refs/heads/master
c: ec43b08
h: refs/heads/master
i:
  344165: 0894834
  344163: 1112633
  344159: 528b8fd
v: v3
  • Loading branch information
Hauke Mehrtens authored and John Crispin committed Nov 21, 2012
1 parent b35ee7d commit 2f4bdfa
Show file tree
Hide file tree
Showing 7 changed files with 206 additions and 1 deletion.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 394bc7e38be79987ed15de203920c3cddb724cc1
refs/heads/master: ec43b08b5733494ad88aa618ecdf534320dd8207
9 changes: 9 additions & 0 deletions trunk/drivers/ssb/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -160,4 +160,13 @@ config SSB_DRIVER_GIGE

If unsure, say N

config SSB_DRIVER_GPIO
bool "SSB GPIO driver"
depends on SSB
select GPIOLIB
help
Driver to provide access to the GPIO pins on the bus.

If unsure, say N

endmenu
1 change: 1 addition & 0 deletions trunk/drivers/ssb/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ ssb-$(CONFIG_SSB_DRIVER_MIPS) += driver_mipscore.o
ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o
ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o
ssb-$(CONFIG_SSB_DRIVER_GIGE) += driver_gige.o
ssb-$(CONFIG_SSB_DRIVER_GPIO) += driver_gpio.o

# b43 pci-ssb-bridge driver
# Not strictly a part of SSB, but kept here for convenience
Expand Down
176 changes: 176 additions & 0 deletions trunk/drivers/ssb/driver_gpio.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
/*
* Sonics Silicon Backplane
* GPIO driver
*
* Copyright 2011, Broadcom Corporation
* Copyright 2012, Hauke Mehrtens <hauke@hauke-m.de>
*
* Licensed under the GNU/GPL. See COPYING for details.
*/

#include <linux/gpio.h>
#include <linux/export.h>
#include <linux/ssb/ssb.h>

#include "ssb_private.h"

static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip)
{
return container_of(chip, struct ssb_bus, gpio);
}

static int ssb_gpio_chipco_get_value(struct gpio_chip *chip, unsigned gpio)
{
struct ssb_bus *bus = ssb_gpio_get_bus(chip);

return !!ssb_chipco_gpio_in(&bus->chipco, 1 << gpio);
}

static void ssb_gpio_chipco_set_value(struct gpio_chip *chip, unsigned gpio,
int value)
{
struct ssb_bus *bus = ssb_gpio_get_bus(chip);

ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
}

static int ssb_gpio_chipco_direction_input(struct gpio_chip *chip,
unsigned gpio)
{
struct ssb_bus *bus = ssb_gpio_get_bus(chip);

ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 0);
return 0;
}

static int ssb_gpio_chipco_direction_output(struct gpio_chip *chip,
unsigned gpio, int value)
{
struct ssb_bus *bus = ssb_gpio_get_bus(chip);

ssb_chipco_gpio_outen(&bus->chipco, 1 << gpio, 1 << gpio);
ssb_chipco_gpio_out(&bus->chipco, 1 << gpio, value ? 1 << gpio : 0);
return 0;
}

static int ssb_gpio_chipco_request(struct gpio_chip *chip, unsigned gpio)
{
struct ssb_bus *bus = ssb_gpio_get_bus(chip);

ssb_chipco_gpio_control(&bus->chipco, 1 << gpio, 0);
/* clear pulldown */
ssb_chipco_gpio_pulldown(&bus->chipco, 1 << gpio, 0);
/* Set pullup */
ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 1 << gpio);

return 0;
}

static void ssb_gpio_chipco_free(struct gpio_chip *chip, unsigned gpio)
{
struct ssb_bus *bus = ssb_gpio_get_bus(chip);

/* clear pullup */
ssb_chipco_gpio_pullup(&bus->chipco, 1 << gpio, 0);
}

static int ssb_gpio_chipco_init(struct ssb_bus *bus)
{
struct gpio_chip *chip = &bus->gpio;

chip->label = "ssb_chipco_gpio";
chip->owner = THIS_MODULE;
chip->request = ssb_gpio_chipco_request;
chip->free = ssb_gpio_chipco_free;
chip->get = ssb_gpio_chipco_get_value;
chip->set = ssb_gpio_chipco_set_value;
chip->direction_input = ssb_gpio_chipco_direction_input;
chip->direction_output = ssb_gpio_chipco_direction_output;
chip->ngpio = 16;
/* There is just one SoC in one device and its GPIO addresses should be
* deterministic to address them more easily. The other buses could get
* a random base number. */
if (bus->bustype == SSB_BUSTYPE_SSB)
chip->base = 0;
else
chip->base = -1;

return gpiochip_add(chip);
}

#ifdef CONFIG_SSB_DRIVER_EXTIF

static int ssb_gpio_extif_get_value(struct gpio_chip *chip, unsigned gpio)
{
struct ssb_bus *bus = ssb_gpio_get_bus(chip);

return !!ssb_extif_gpio_in(&bus->extif, 1 << gpio);
}

static void ssb_gpio_extif_set_value(struct gpio_chip *chip, unsigned gpio,
int value)
{
struct ssb_bus *bus = ssb_gpio_get_bus(chip);

ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
}

static int ssb_gpio_extif_direction_input(struct gpio_chip *chip,
unsigned gpio)
{
struct ssb_bus *bus = ssb_gpio_get_bus(chip);

ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 0);
return 0;
}

static int ssb_gpio_extif_direction_output(struct gpio_chip *chip,
unsigned gpio, int value)
{
struct ssb_bus *bus = ssb_gpio_get_bus(chip);

ssb_extif_gpio_outen(&bus->extif, 1 << gpio, 1 << gpio);
ssb_extif_gpio_out(&bus->extif, 1 << gpio, value ? 1 << gpio : 0);
return 0;
}

static int ssb_gpio_extif_init(struct ssb_bus *bus)
{
struct gpio_chip *chip = &bus->gpio;

chip->label = "ssb_extif_gpio";
chip->owner = THIS_MODULE;
chip->get = ssb_gpio_extif_get_value;
chip->set = ssb_gpio_extif_set_value;
chip->direction_input = ssb_gpio_extif_direction_input;
chip->direction_output = ssb_gpio_extif_direction_output;
chip->ngpio = 5;
/* There is just one SoC in one device and its GPIO addresses should be
* deterministic to address them more easily. The other buses could get
* a random base number. */
if (bus->bustype == SSB_BUSTYPE_SSB)
chip->base = 0;
else
chip->base = -1;

return gpiochip_add(chip);
}

#else
static int ssb_gpio_extif_init(struct ssb_bus *bus)
{
return -ENOTSUPP;
}
#endif

int ssb_gpio_init(struct ssb_bus *bus)
{
if (ssb_chipco_available(&bus->chipco))
return ssb_gpio_chipco_init(bus);
else if (ssb_extif_available(&bus->extif))
return ssb_gpio_extif_init(bus);
else
SSB_WARN_ON(1);

return -1;
}
6 changes: 6 additions & 0 deletions trunk/drivers/ssb/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,12 @@ static int __devinit ssb_bus_register(struct ssb_bus *bus,
ssb_chipcommon_init(&bus->chipco);
ssb_extif_init(&bus->extif);
ssb_mipscore_init(&bus->mipscore);
err = ssb_gpio_init(bus);
if (err == -ENOTSUPP)
ssb_dprintk(KERN_DEBUG PFX "GPIO driver not activated\n");
else if (err)
ssb_dprintk(KERN_ERR PFX
"Error registering GPIO driver: %i\n", err);
err = ssb_fetch_invariants(bus, get_invariants);
if (err) {
ssb_bus_may_powerdown(bus);
Expand Down
9 changes: 9 additions & 0 deletions trunk/drivers/ssb/ssb_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -219,4 +219,13 @@ static inline void ssb_extif_init(struct ssb_extif *extif)
}
#endif

#ifdef CONFIG_SSB_DRIVER_GPIO
extern int ssb_gpio_init(struct ssb_bus *bus);
#else /* CONFIG_SSB_DRIVER_GPIO */
static inline int ssb_gpio_init(struct ssb_bus *bus)
{
return -ENOTSUPP;
}
#endif /* CONFIG_SSB_DRIVER_GPIO */

#endif /* LINUX_SSB_PRIVATE_H_ */
4 changes: 4 additions & 0 deletions trunk/include/linux/ssb/ssb.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include <linux/types.h>
#include <linux/spinlock.h>
#include <linux/pci.h>
#include <linux/gpio.h>
#include <linux/mod_devicetable.h>
#include <linux/dma-mapping.h>

Expand Down Expand Up @@ -433,6 +434,9 @@ struct ssb_bus {
/* Lock for GPIO register access. */
spinlock_t gpio_lock;
#endif /* EMBEDDED */
#ifdef CONFIG_SSB_DRIVER_GPIO
struct gpio_chip gpio;
#endif /* DRIVER_GPIO */

/* Internal-only stuff follows. Do not touch. */
struct list_head list;
Expand Down

0 comments on commit 2f4bdfa

Please sign in to comment.