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 master 360 lines 9.2 kB view raw
1// SPDX-License-Identifier: GPL-2.0-only 2/* 3 * AMD CS5535/CS5536 GPIO driver 4 * Copyright (C) 2006 Advanced Micro Devices, Inc. 5 * Copyright (C) 2007-2009 Andres Salomon <dilinger@collabora.co.uk> 6 */ 7 8#include <linux/kernel.h> 9#include <linux/spinlock.h> 10#include <linux/module.h> 11#include <linux/platform_device.h> 12#include <linux/gpio/driver.h> 13#include <linux/io.h> 14#include <linux/cs5535.h> 15#include <asm/msr.h> 16 17#define DRV_NAME "cs5535-gpio" 18 19/* 20 * Some GPIO pins 21 * 31-29,23 : reserved (always mask out) 22 * 28 : Power Button 23 * 26 : PME# 24 * 22-16 : LPC 25 * 14,15 : SMBus 26 * 9,8 : UART1 27 * 7 : PCI INTB 28 * 3,4 : UART2/DDC 29 * 2 : IDE_IRQ0 30 * 1 : AC_BEEP 31 * 0 : PCI INTA 32 * 33 * If a mask was not specified, allow all except 34 * reserved and Power Button 35 */ 36#define GPIO_DEFAULT_MASK 0x0F7FFFFF 37 38static ulong mask = GPIO_DEFAULT_MASK; 39module_param_named(mask, mask, ulong, 0444); 40MODULE_PARM_DESC(mask, "GPIO channel mask."); 41 42static struct cs5535_gpio_chip { 43 struct gpio_chip chip; 44 resource_size_t base; 45 46 struct platform_device *pdev; 47 spinlock_t lock; 48} cs5535_gpio_chip; 49 50/* 51 * The CS5535/CS5536 GPIOs support a number of extra features not defined 52 * by the gpio_chip API, so these are exported. For a full list of the 53 * registers, see include/linux/cs5535.h. 54 */ 55 56static void errata_outl(struct cs5535_gpio_chip *chip, u32 val, 57 unsigned int reg) 58{ 59 unsigned long addr = chip->base + 0x80 + reg; 60 61 /* 62 * According to the CS5536 errata (#36), after suspend 63 * a write to the high bank GPIO register will clear all 64 * non-selected bits; the recommended workaround is a 65 * read-modify-write operation. 66 * 67 * Don't apply this errata to the edge status GPIOs, as writing 68 * to their lower bits will clear them. 69 */ 70 if (reg != GPIO_POSITIVE_EDGE_STS && reg != GPIO_NEGATIVE_EDGE_STS) { 71 if (val & 0xffff) 72 val |= (inl(addr) & 0xffff); /* ignore the high bits */ 73 else 74 val |= (inl(addr) ^ (val >> 16)); 75 } 76 outl(val, addr); 77} 78 79static void __cs5535_gpio_set(struct cs5535_gpio_chip *chip, unsigned offset, 80 unsigned int reg) 81{ 82 if (offset < 16) 83 /* low bank register */ 84 outl(1 << offset, chip->base + reg); 85 else 86 /* high bank register */ 87 errata_outl(chip, 1 << (offset - 16), reg); 88} 89 90void cs5535_gpio_set(unsigned offset, unsigned int reg) 91{ 92 struct cs5535_gpio_chip *chip = &cs5535_gpio_chip; 93 unsigned long flags; 94 95 spin_lock_irqsave(&chip->lock, flags); 96 __cs5535_gpio_set(chip, offset, reg); 97 spin_unlock_irqrestore(&chip->lock, flags); 98} 99EXPORT_SYMBOL_GPL(cs5535_gpio_set); 100 101static void __cs5535_gpio_clear(struct cs5535_gpio_chip *chip, unsigned offset, 102 unsigned int reg) 103{ 104 if (offset < 16) 105 /* low bank register */ 106 outl(1 << (offset + 16), chip->base + reg); 107 else 108 /* high bank register */ 109 errata_outl(chip, 1 << offset, reg); 110} 111 112void cs5535_gpio_clear(unsigned offset, unsigned int reg) 113{ 114 struct cs5535_gpio_chip *chip = &cs5535_gpio_chip; 115 unsigned long flags; 116 117 spin_lock_irqsave(&chip->lock, flags); 118 __cs5535_gpio_clear(chip, offset, reg); 119 spin_unlock_irqrestore(&chip->lock, flags); 120} 121EXPORT_SYMBOL_GPL(cs5535_gpio_clear); 122 123int cs5535_gpio_isset(unsigned offset, unsigned int reg) 124{ 125 struct cs5535_gpio_chip *chip = &cs5535_gpio_chip; 126 unsigned long flags; 127 long val; 128 129 spin_lock_irqsave(&chip->lock, flags); 130 if (offset < 16) 131 /* low bank register */ 132 val = inl(chip->base + reg); 133 else { 134 /* high bank register */ 135 val = inl(chip->base + 0x80 + reg); 136 offset -= 16; 137 } 138 spin_unlock_irqrestore(&chip->lock, flags); 139 140 return (val & (1 << offset)) ? 1 : 0; 141} 142EXPORT_SYMBOL_GPL(cs5535_gpio_isset); 143 144int cs5535_gpio_set_irq(unsigned group, unsigned irq) 145{ 146 uint32_t lo, hi; 147 148 if (group > 7 || irq > 15) 149 return -EINVAL; 150 151 rdmsr(MSR_PIC_ZSEL_HIGH, lo, hi); 152 153 lo &= ~(0xF << (group * 4)); 154 lo |= (irq & 0xF) << (group * 4); 155 156 wrmsr(MSR_PIC_ZSEL_HIGH, lo, hi); 157 return 0; 158} 159EXPORT_SYMBOL_GPL(cs5535_gpio_set_irq); 160 161void cs5535_gpio_setup_event(unsigned offset, int pair, int pme) 162{ 163 struct cs5535_gpio_chip *chip = &cs5535_gpio_chip; 164 uint32_t shift = (offset % 8) * 4; 165 unsigned long flags; 166 uint32_t val; 167 168 if (offset >= 24) 169 offset = GPIO_MAP_W; 170 else if (offset >= 16) 171 offset = GPIO_MAP_Z; 172 else if (offset >= 8) 173 offset = GPIO_MAP_Y; 174 else 175 offset = GPIO_MAP_X; 176 177 spin_lock_irqsave(&chip->lock, flags); 178 val = inl(chip->base + offset); 179 180 /* Clear whatever was there before */ 181 val &= ~(0xF << shift); 182 183 /* Set the new value */ 184 val |= ((pair & 7) << shift); 185 186 /* Set the PME bit if this is a PME event */ 187 if (pme) 188 val |= (1 << (shift + 3)); 189 190 outl(val, chip->base + offset); 191 spin_unlock_irqrestore(&chip->lock, flags); 192} 193EXPORT_SYMBOL_GPL(cs5535_gpio_setup_event); 194 195/* 196 * Generic gpio_chip API support. 197 */ 198 199static int chip_gpio_request(struct gpio_chip *c, unsigned offset) 200{ 201 struct cs5535_gpio_chip *chip = gpiochip_get_data(c); 202 unsigned long flags; 203 204 spin_lock_irqsave(&chip->lock, flags); 205 206 /* check if this pin is available */ 207 if ((mask & (1 << offset)) == 0) { 208 dev_info(&chip->pdev->dev, 209 "pin %u is not available (check mask)\n", offset); 210 spin_unlock_irqrestore(&chip->lock, flags); 211 return -EINVAL; 212 } 213 214 /* disable output aux 1 & 2 on this pin */ 215 __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX1); 216 __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_AUX2); 217 218 /* disable input aux 1 on this pin */ 219 __cs5535_gpio_clear(chip, offset, GPIO_INPUT_AUX1); 220 221 spin_unlock_irqrestore(&chip->lock, flags); 222 223 return 0; 224} 225 226static int chip_gpio_get(struct gpio_chip *chip, unsigned offset) 227{ 228 return cs5535_gpio_isset(offset, GPIO_READ_BACK); 229} 230 231static int chip_gpio_set(struct gpio_chip *chip, unsigned int offset, int val) 232{ 233 if (val) 234 cs5535_gpio_set(offset, GPIO_OUTPUT_VAL); 235 else 236 cs5535_gpio_clear(offset, GPIO_OUTPUT_VAL); 237 238 return 0; 239} 240 241static int chip_direction_input(struct gpio_chip *c, unsigned offset) 242{ 243 struct cs5535_gpio_chip *chip = gpiochip_get_data(c); 244 unsigned long flags; 245 246 spin_lock_irqsave(&chip->lock, flags); 247 __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE); 248 __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_ENABLE); 249 spin_unlock_irqrestore(&chip->lock, flags); 250 251 return 0; 252} 253 254static int chip_direction_output(struct gpio_chip *c, unsigned offset, int val) 255{ 256 struct cs5535_gpio_chip *chip = gpiochip_get_data(c); 257 unsigned long flags; 258 259 spin_lock_irqsave(&chip->lock, flags); 260 261 __cs5535_gpio_set(chip, offset, GPIO_INPUT_ENABLE); 262 __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_ENABLE); 263 if (val) 264 __cs5535_gpio_set(chip, offset, GPIO_OUTPUT_VAL); 265 else 266 __cs5535_gpio_clear(chip, offset, GPIO_OUTPUT_VAL); 267 268 spin_unlock_irqrestore(&chip->lock, flags); 269 270 return 0; 271} 272 273static const char * const cs5535_gpio_names[] = { 274 "GPIO0", "GPIO1", "GPIO2", "GPIO3", 275 "GPIO4", "GPIO5", "GPIO6", "GPIO7", 276 "GPIO8", "GPIO9", "GPIO10", "GPIO11", 277 "GPIO12", "GPIO13", "GPIO14", "GPIO15", 278 "GPIO16", "GPIO17", "GPIO18", "GPIO19", 279 "GPIO20", "GPIO21", "GPIO22", NULL, 280 "GPIO24", "GPIO25", "GPIO26", "GPIO27", 281 "GPIO28", NULL, NULL, NULL, 282}; 283 284static int cs5535_gpio_probe(struct platform_device *pdev) 285{ 286 struct cs5535_gpio_chip *priv; 287 struct gpio_chip *gc; 288 struct resource *res; 289 int err = -EIO; 290 ulong mask_orig = mask; 291 292 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 293 if (!priv) 294 return -ENOMEM; 295 296 gc = &priv->chip; 297 gc->owner = THIS_MODULE; 298 gc->label = DRV_NAME; 299 gc->ngpio = 32; 300 gc->names = cs5535_gpio_names; 301 gc->request = chip_gpio_request; 302 gc->get = chip_gpio_get; 303 gc->set = chip_gpio_set; 304 gc->direction_input = chip_direction_input; 305 gc->direction_output = chip_direction_output; 306 307 /* There are two ways to get the GPIO base address; one is by 308 * fetching it from MSR_LBAR_GPIO, the other is by reading the 309 * PCI BAR info. The latter method is easier (especially across 310 * different architectures), so we'll stick with that for now. If 311 * it turns out to be unreliable in the face of crappy BIOSes, we 312 * can always go back to using MSRs.. */ 313 314 res = platform_get_resource(pdev, IORESOURCE_IO, 0); 315 if (!res) { 316 dev_err(&pdev->dev, "can't fetch device resource info\n"); 317 return err; 318 } 319 320 if (!devm_request_region(&pdev->dev, res->start, resource_size(res), 321 pdev->name)) { 322 dev_err(&pdev->dev, "can't request region\n"); 323 return err; 324 } 325 326 /* set up the driver-specific struct */ 327 priv->base = res->start; 328 priv->pdev = pdev; 329 spin_lock_init(&priv->lock); 330 331 dev_info(&pdev->dev, "reserved resource region %pR\n", res); 332 333 /* mask out reserved pins */ 334 mask &= 0x1F7FFFFF; 335 336 /* do not allow pin 28, Power Button, as there's special handling 337 * in the PMC needed. (note 12, p. 48) */ 338 mask &= ~(1 << 28); 339 340 if (mask_orig != mask) 341 dev_info(&pdev->dev, "mask changed from 0x%08lX to 0x%08lX\n", 342 mask_orig, mask); 343 344 /* finally, register with the generic GPIO API */ 345 return devm_gpiochip_add_data(&pdev->dev, gc, priv); 346} 347 348static struct platform_driver cs5535_gpio_driver = { 349 .driver = { 350 .name = DRV_NAME, 351 }, 352 .probe = cs5535_gpio_probe, 353}; 354 355module_platform_driver(cs5535_gpio_driver); 356 357MODULE_AUTHOR("Andres Salomon <dilinger@queued.net>"); 358MODULE_DESCRIPTION("AMD CS5535/CS5536 GPIO driver"); 359MODULE_LICENSE("GPL"); 360MODULE_ALIAS("platform:" DRV_NAME);