1 /* 2 * Support for viafb GPIO ports. 3 * 4 * Copyright 2009 Jonathan Corbet <corbet@lwn.net> 5 * Distributable under version 2 of the GNU General Public License. 6 */ 7 8 #include <linux/spinlock.h> 9 #include <linux/gpio.h> 10 #include <linux/platform_device.h> 11 #include <linux/via-core.h> 12 #include <linux/via-gpio.h> 13 #include <linux/export.h> 14 15 /* 16 * The ports we know about. Note that the port-25 gpios are not 17 * mentioned in the datasheet. 18 */ 19 20 struct viafb_gpio { 21 char *vg_name; /* Data sheet name */ 22 u16 vg_io_port; 23 u8 vg_port_index; 24 int vg_mask_shift; 25 }; 26 27 static struct viafb_gpio viafb_all_gpios[] = { 28 { 29 .vg_name = "VGPIO0", /* Guess - not in datasheet */ 30 .vg_io_port = VIASR, 31 .vg_port_index = 0x25, 32 .vg_mask_shift = 1 33 }, 34 { 35 .vg_name = "VGPIO1", 36 .vg_io_port = VIASR, 37 .vg_port_index = 0x25, 38 .vg_mask_shift = 0 39 }, 40 { 41 .vg_name = "VGPIO2", /* aka DISPCLKI0 */ 42 .vg_io_port = VIASR, 43 .vg_port_index = 0x2c, 44 .vg_mask_shift = 1 45 }, 46 { 47 .vg_name = "VGPIO3", /* aka DISPCLKO0 */ 48 .vg_io_port = VIASR, 49 .vg_port_index = 0x2c, 50 .vg_mask_shift = 0 51 }, 52 { 53 .vg_name = "VGPIO4", /* DISPCLKI1 */ 54 .vg_io_port = VIASR, 55 .vg_port_index = 0x3d, 56 .vg_mask_shift = 1 57 }, 58 { 59 .vg_name = "VGPIO5", /* DISPCLKO1 */ 60 .vg_io_port = VIASR, 61 .vg_port_index = 0x3d, 62 .vg_mask_shift = 0 63 }, 64 }; 65 66 #define VIAFB_NUM_GPIOS ARRAY_SIZE(viafb_all_gpios) 67 68 /* 69 * This structure controls the active GPIOs, which may be a subset 70 * of those which are known. 71 */ 72 73 struct viafb_gpio_cfg { 74 struct gpio_chip gpio_chip; 75 struct viafb_dev *vdev; 76 struct viafb_gpio *active_gpios[VIAFB_NUM_GPIOS]; 77 const char *gpio_names[VIAFB_NUM_GPIOS]; 78 }; 79 80 /* 81 * GPIO access functions 82 */ 83 static void via_gpio_set(struct gpio_chip *chip, unsigned int nr, 84 int value) 85 { 86 struct viafb_gpio_cfg *cfg = container_of(chip, 87 struct viafb_gpio_cfg, 88 gpio_chip); 89 u8 reg; 90 struct viafb_gpio *gpio; 91 unsigned long flags; 92 93 spin_lock_irqsave(&cfg->vdev->reg_lock, flags); 94 gpio = cfg->active_gpios[nr]; 95 reg = via_read_reg(VIASR, gpio->vg_port_index); 96 reg |= 0x40 << gpio->vg_mask_shift; /* output enable */ 97 if (value) 98 reg |= 0x10 << gpio->vg_mask_shift; 99 else 100 reg &= ~(0x10 << gpio->vg_mask_shift); 101 via_write_reg(VIASR, gpio->vg_port_index, reg); 102 spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags); 103 } 104 105 static int via_gpio_dir_out(struct gpio_chip *chip, unsigned int nr, 106 int value) 107 { 108 via_gpio_set(chip, nr, value); 109 return 0; 110 } 111 112 /* 113 * Set the input direction. I'm not sure this is right; we should 114 * be able to do input without disabling output. 115 */ 116 static int via_gpio_dir_input(struct gpio_chip *chip, unsigned int nr) 117 { 118 struct viafb_gpio_cfg *cfg = container_of(chip, 119 struct viafb_gpio_cfg, 120 gpio_chip); 121 struct viafb_gpio *gpio; 122 unsigned long flags; 123 124 spin_lock_irqsave(&cfg->vdev->reg_lock, flags); 125 gpio = cfg->active_gpios[nr]; 126 via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 127 0x40 << gpio->vg_mask_shift); 128 spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags); 129 return 0; 130 } 131 132 static int via_gpio_get(struct gpio_chip *chip, unsigned int nr) 133 { 134 struct viafb_gpio_cfg *cfg = container_of(chip, 135 struct viafb_gpio_cfg, 136 gpio_chip); 137 u8 reg; 138 struct viafb_gpio *gpio; 139 unsigned long flags; 140 141 spin_lock_irqsave(&cfg->vdev->reg_lock, flags); 142 gpio = cfg->active_gpios[nr]; 143 reg = via_read_reg(VIASR, gpio->vg_port_index); 144 spin_unlock_irqrestore(&cfg->vdev->reg_lock, flags); 145 return reg & (0x04 << gpio->vg_mask_shift); 146 } 147 148 149 static struct viafb_gpio_cfg viafb_gpio_config = { 150 .gpio_chip = { 151 .label = "VIAFB onboard GPIO", 152 .owner = THIS_MODULE, 153 .direction_output = via_gpio_dir_out, 154 .set = via_gpio_set, 155 .direction_input = via_gpio_dir_input, 156 .get = via_gpio_get, 157 .base = -1, 158 .ngpio = 0, 159 .can_sleep = 0 160 } 161 }; 162 163 /* 164 * Manage the software enable bit. 165 */ 166 static void viafb_gpio_enable(struct viafb_gpio *gpio) 167 { 168 via_write_reg_mask(VIASR, gpio->vg_port_index, 0x02, 0x02); 169 } 170 171 static void viafb_gpio_disable(struct viafb_gpio *gpio) 172 { 173 via_write_reg_mask(VIASR, gpio->vg_port_index, 0, 0x02); 174 } 175 176 #ifdef CONFIG_PM 177 178 static int viafb_gpio_suspend(void *private) 179 { 180 return 0; 181 } 182 183 static int viafb_gpio_resume(void *private) 184 { 185 int i; 186 187 for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i += 2) 188 viafb_gpio_enable(viafb_gpio_config.active_gpios[i]); 189 return 0; 190 } 191 192 static struct viafb_pm_hooks viafb_gpio_pm_hooks = { 193 .suspend = viafb_gpio_suspend, 194 .resume = viafb_gpio_resume 195 }; 196 #endif /* CONFIG_PM */ 197 198 /* 199 * Look up a specific gpio and return the number it was assigned. 200 */ 201 int viafb_gpio_lookup(const char *name) 202 { 203 int i; 204 205 for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i++) 206 if (!strcmp(name, viafb_gpio_config.active_gpios[i]->vg_name)) 207 return viafb_gpio_config.gpio_chip.base + i; 208 return -1; 209 } 210 EXPORT_SYMBOL_GPL(viafb_gpio_lookup); 211 212 /* 213 * Platform device stuff. 214 */ 215 static int viafb_gpio_probe(struct platform_device *platdev) 216 { 217 struct viafb_dev *vdev = platdev->dev.platform_data; 218 struct via_port_cfg *port_cfg = vdev->port_cfg; 219 int i, ngpio = 0, ret; 220 struct viafb_gpio *gpio; 221 unsigned long flags; 222 223 /* 224 * Set up entries for all GPIOs which have been configured to 225 * operate as such (as opposed to as i2c ports). 226 */ 227 for (i = 0; i < VIAFB_NUM_PORTS; i++) { 228 if (port_cfg[i].mode != VIA_MODE_GPIO) 229 continue; 230 for (gpio = viafb_all_gpios; 231 gpio < viafb_all_gpios + VIAFB_NUM_GPIOS; gpio++) 232 if (gpio->vg_port_index == port_cfg[i].ioport_index) { 233 viafb_gpio_config.active_gpios[ngpio] = gpio; 234 viafb_gpio_config.gpio_names[ngpio] = 235 gpio->vg_name; 236 ngpio++; 237 } 238 } 239 viafb_gpio_config.gpio_chip.ngpio = ngpio; 240 viafb_gpio_config.gpio_chip.names = viafb_gpio_config.gpio_names; 241 viafb_gpio_config.vdev = vdev; 242 if (ngpio == 0) { 243 printk(KERN_INFO "viafb: no GPIOs configured\n"); 244 return 0; 245 } 246 /* 247 * Enable the ports. They come in pairs, with a single 248 * enable bit for both. 249 */ 250 spin_lock_irqsave(&viafb_gpio_config.vdev->reg_lock, flags); 251 for (i = 0; i < ngpio; i += 2) 252 viafb_gpio_enable(viafb_gpio_config.active_gpios[i]); 253 spin_unlock_irqrestore(&viafb_gpio_config.vdev->reg_lock, flags); 254 /* 255 * Get registered. 256 */ 257 viafb_gpio_config.gpio_chip.base = -1; /* Dynamic */ 258 ret = gpiochip_add(&viafb_gpio_config.gpio_chip); 259 if (ret) { 260 printk(KERN_ERR "viafb: failed to add gpios (%d)\n", ret); 261 viafb_gpio_config.gpio_chip.ngpio = 0; 262 } 263 #ifdef CONFIG_PM 264 viafb_pm_register(&viafb_gpio_pm_hooks); 265 #endif 266 return ret; 267 } 268 269 270 static int viafb_gpio_remove(struct platform_device *platdev) 271 { 272 unsigned long flags; 273 int i; 274 275 #ifdef CONFIG_PM 276 viafb_pm_unregister(&viafb_gpio_pm_hooks); 277 #endif 278 279 /* 280 * Get unregistered. 281 */ 282 if (viafb_gpio_config.gpio_chip.ngpio > 0) { 283 gpiochip_remove(&viafb_gpio_config.gpio_chip); 284 } 285 /* 286 * Disable the ports. 287 */ 288 spin_lock_irqsave(&viafb_gpio_config.vdev->reg_lock, flags); 289 for (i = 0; i < viafb_gpio_config.gpio_chip.ngpio; i += 2) 290 viafb_gpio_disable(viafb_gpio_config.active_gpios[i]); 291 viafb_gpio_config.gpio_chip.ngpio = 0; 292 spin_unlock_irqrestore(&viafb_gpio_config.vdev->reg_lock, flags); 293 return 0; 294 } 295 296 static struct platform_driver via_gpio_driver = { 297 .driver = { 298 .name = "viafb-gpio", 299 }, 300 .probe = viafb_gpio_probe, 301 .remove = viafb_gpio_remove, 302 }; 303 304 int viafb_gpio_init(void) 305 { 306 return platform_driver_register(&via_gpio_driver); 307 } 308 309 void viafb_gpio_exit(void) 310 { 311 platform_driver_unregister(&via_gpio_driver); 312 } 313