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_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 87 static 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 114 static 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 121 static 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 129 static 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 138 static 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 148 static 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 158 static 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 182 static int ssb_gpio_extif_init(struct ssb_bus *bus) 183 { 184 return -ENOTSUPP; 185 } 186 #endif 187 188 int 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 200 int 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