Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ssb: add GPIO driver

Register a GPIO driver to access the GPIOs provided by the chip.
The GPIOs of the SoC should always start at 0 and the other GPIOs could
start at a random position. There is just one SoC in a system and when
they start at 0 the number is predictable.

Signed-off-by: Hauke Mehrtens <hauke@hauke-m.de>
Patchwork: http://patchwork.linux-mips.org/patch/4591
Acked-by: Florian Fainelli <florian@openwrt.org>

authored by

Hauke Mehrtens and committed by
John Crispin
ec43b08b 394bc7e3

+205
+9
drivers/ssb/Kconfig
··· 160 160 161 161 If unsure, say N 162 162 163 + config SSB_DRIVER_GPIO 164 + bool "SSB GPIO driver" 165 + depends on SSB 166 + select GPIOLIB 167 + help 168 + Driver to provide access to the GPIO pins on the bus. 169 + 170 + If unsure, say N 171 + 163 172 endmenu
+1
drivers/ssb/Makefile
··· 15 15 ssb-$(CONFIG_SSB_DRIVER_EXTIF) += driver_extif.o 16 16 ssb-$(CONFIG_SSB_DRIVER_PCICORE) += driver_pcicore.o 17 17 ssb-$(CONFIG_SSB_DRIVER_GIGE) += driver_gige.o 18 + ssb-$(CONFIG_SSB_DRIVER_GPIO) += driver_gpio.o 18 19 19 20 # b43 pci-ssb-bridge driver 20 21 # Not strictly a part of SSB, but kept here for convenience
+176
drivers/ssb/driver_gpio.c
··· 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 + 17 + static struct ssb_bus *ssb_gpio_get_bus(struct gpio_chip *chip) 18 + { 19 + return container_of(chip, struct ssb_bus, gpio); 20 + } 21 + 22 + static 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 + 29 + static 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 + 37 + static 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 + 46 + static 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 + 56 + static 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 + 69 + static 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 + 77 + static 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 + 103 + static 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 + 110 + static 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 + 118 + static 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 + 127 + static 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 + 137 + static 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 160 + static int ssb_gpio_extif_init(struct ssb_bus *bus) 161 + { 162 + return -ENOTSUPP; 163 + } 164 + #endif 165 + 166 + int 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 + }
+6
drivers/ssb/main.c
··· 798 798 ssb_chipcommon_init(&bus->chipco); 799 799 ssb_extif_init(&bus->extif); 800 800 ssb_mipscore_init(&bus->mipscore); 801 + err = ssb_gpio_init(bus); 802 + if (err == -ENOTSUPP) 803 + ssb_dprintk(KERN_DEBUG PFX "GPIO driver not activated\n"); 804 + else if (err) 805 + ssb_dprintk(KERN_ERR PFX 806 + "Error registering GPIO driver: %i\n", err); 801 807 err = ssb_fetch_invariants(bus, get_invariants); 802 808 if (err) { 803 809 ssb_bus_may_powerdown(bus);
+9
drivers/ssb/ssb_private.h
··· 219 219 } 220 220 #endif 221 221 222 + #ifdef CONFIG_SSB_DRIVER_GPIO 223 + extern int ssb_gpio_init(struct ssb_bus *bus); 224 + #else /* CONFIG_SSB_DRIVER_GPIO */ 225 + static inline int ssb_gpio_init(struct ssb_bus *bus) 226 + { 227 + return -ENOTSUPP; 228 + } 229 + #endif /* CONFIG_SSB_DRIVER_GPIO */ 230 + 222 231 #endif /* LINUX_SSB_PRIVATE_H_ */
+4
include/linux/ssb/ssb.h
··· 6 6 #include <linux/types.h> 7 7 #include <linux/spinlock.h> 8 8 #include <linux/pci.h> 9 + #include <linux/gpio.h> 9 10 #include <linux/mod_devicetable.h> 10 11 #include <linux/dma-mapping.h> 11 12 ··· 434 433 /* Lock for GPIO register access. */ 435 434 spinlock_t gpio_lock; 436 435 #endif /* EMBEDDED */ 436 + #ifdef CONFIG_SSB_DRIVER_GPIO 437 + struct gpio_chip gpio; 438 + #endif /* DRIVER_GPIO */ 437 439 438 440 /* Internal-only stuff follows. Do not touch. */ 439 441 struct list_head list;