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

Configure Feed

Select the types of activity you want to include in your feed.

at v3.9-rc1 210 lines 5.3 kB view raw
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}