Blame view
drivers/gpio/gpio-ich.c
12 KB
7ed0cf0af
|
1 |
// SPDX-License-Identifier: GPL-2.0+ |
6ed9f9c40
|
2 |
/* |
3b9231893
|
3 |
* Intel ICH6-10, Series 5 and 6, Atom C2000 (Avoton/Rangeley) GPIO driver |
6ed9f9c40
|
4 5 |
* * Copyright (C) 2010 Extreme Engineering Solutions. |
6ed9f9c40
|
6 |
*/ |
6ed9f9c40
|
7 |
|
488f270ca
|
8 9 |
#include <linux/bitops.h> #include <linux/gpio/driver.h> |
8a06b08ec
|
10 |
#include <linux/ioport.h> |
488f270ca
|
11 |
#include <linux/mfd/lpc_ich.h> |
6ed9f9c40
|
12 13 |
#include <linux/module.h> #include <linux/pci.h> |
6ed9f9c40
|
14 |
#include <linux/platform_device.h> |
6ed9f9c40
|
15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
#define DRV_NAME "gpio_ich" /* * GPIO register offsets in GPIO I/O space. * Each chunk of 32 GPIOs is manipulated via its own USE_SELx, IO_SELx, and * LVLx registers. Logic in the read/write functions takes a register and * an absolute bit number and determines the proper register offset and bit * number in that register. For example, to read the value of GPIO bit 50 * the code would access offset ichx_regs[2(=GPIO_LVL)][1(=50/32)], * bit 18 (50%32). */ enum GPIO_REG { GPIO_USE_SEL = 0, GPIO_IO_SEL, GPIO_LVL, |
7f6569f54
|
31 |
GPO_BLINK |
6ed9f9c40
|
32 |
}; |
7f6569f54
|
33 |
static const u8 ichx_regs[4][3] = { |
6ed9f9c40
|
34 35 36 |
{0x00, 0x30, 0x40}, /* USE_SEL[1-3] offsets */ {0x04, 0x34, 0x44}, /* IO_SEL[1-3] offsets */ {0x0c, 0x38, 0x48}, /* LVL[1-3] offsets */ |
7f6569f54
|
37 |
{0x18, 0x18, 0x18}, /* BLINK offset */ |
6ed9f9c40
|
38 |
}; |
4f600ada7
|
39 40 41 |
static const u8 ichx_reglen[3] = { 0x30, 0x10, 0x10, }; |
3b9231893
|
42 43 44 45 46 47 48 49 50 |
static const u8 avoton_regs[4][3] = { {0x00, 0x80, 0x00}, {0x04, 0x84, 0x00}, {0x08, 0x88, 0x00}, }; static const u8 avoton_reglen[3] = { 0x10, 0x10, 0x00, }; |
6ed9f9c40
|
51 52 53 54 55 56 |
#define ICHX_WRITE(val, reg, base_res) outl(val, (reg) + (base_res)->start) #define ICHX_READ(reg, base_res) inl((reg) + (base_res)->start) struct ichx_desc { /* Max GPIO pins the chipset can have */ uint ngpio; |
bb62a35bd
|
57 58 59 |
/* chipset registers */ const u8 (*regs)[3]; const u8 *reglen; |
ba7f74fe2
|
60 61 |
/* GPO_BLINK is available on this chipset */ bool have_blink; |
6ed9f9c40
|
62 63 64 65 66 67 68 69 70 |
/* Whether the chipset has GPIO in GPE0_STS in the PM IO region */ bool uses_gpe0; /* USE_SEL is bogus on some chipsets, eg 3100 */ u32 use_sel_ignore[3]; /* Some chipsets have quirks, let these use their own request/get */ int (*request)(struct gpio_chip *chip, unsigned offset); int (*get)(struct gpio_chip *chip, unsigned offset); |
e6540f332
|
71 72 73 74 75 76 |
/* * Some chipsets don't let reading output values on GPIO_LVL register * this option allows driver caching written output values */ bool use_outlvl_cache; |
6ed9f9c40
|
77 78 79 80 |
}; static struct { spinlock_t lock; |
ff4709b44
|
81 |
struct device *dev; |
6ed9f9c40
|
82 83 84 85 86 |
struct gpio_chip chip; struct resource *gpio_base; /* GPIO IO base */ struct resource *pm_base; /* Power Mangagment IO base */ struct ichx_desc *desc; /* Pointer to chipset-specific description */ u32 orig_gpio_ctrl; /* Orig CTRL value, used to restore on exit */ |
4f600ada7
|
87 |
u8 use_gpio; /* Which GPIO groups are usable */ |
e6540f332
|
88 |
int outlvl_cache[3]; /* cached output values */ |
6ed9f9c40
|
89 90 91 92 |
} ichx_priv; static int modparam_gpiobase = -1; /* dynamic */ module_param_named(gpiobase, modparam_gpiobase, int, 0444); |
5f6f2b9f6
|
93 |
MODULE_PARM_DESC(gpiobase, "The GPIO number base. -1 means dynamic, which is the default."); |
6ed9f9c40
|
94 95 96 97 98 99 100 |
static int ichx_write_bit(int reg, unsigned nr, int val, int verify) { unsigned long flags; u32 data, tmp; int reg_nr = nr / 32; int bit = nr & 0x1f; |
6ed9f9c40
|
101 102 |
spin_lock_irqsave(&ichx_priv.lock, flags); |
e6540f332
|
103 104 105 106 107 |
if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) data = ichx_priv.outlvl_cache[reg_nr]; else data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], ichx_priv.gpio_base); |
6ed9f9c40
|
108 |
if (val) |
7a8fd1f5c
|
109 |
data |= BIT(bit); |
6ed9f9c40
|
110 |
else |
7a8fd1f5c
|
111 |
data &= ~BIT(bit); |
bb62a35bd
|
112 113 |
ICHX_WRITE(data, ichx_priv.desc->regs[reg][reg_nr], ichx_priv.gpio_base); |
e6540f332
|
114 115 |
if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) ichx_priv.outlvl_cache[reg_nr] = data; |
bb62a35bd
|
116 117 |
tmp = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], ichx_priv.gpio_base); |
6ed9f9c40
|
118 119 |
spin_unlock_irqrestore(&ichx_priv.lock, flags); |
c5aaa3168
|
120 |
return (verify && data != tmp) ? -EPERM : 0; |
6ed9f9c40
|
121 122 123 124 125 126 127 128 129 130 |
} static int ichx_read_bit(int reg, unsigned nr) { unsigned long flags; u32 data; int reg_nr = nr / 32; int bit = nr & 0x1f; spin_lock_irqsave(&ichx_priv.lock, flags); |
bb62a35bd
|
131 132 |
data = ICHX_READ(ichx_priv.desc->regs[reg][reg_nr], ichx_priv.gpio_base); |
6ed9f9c40
|
133 |
|
e6540f332
|
134 135 |
if (reg == GPIO_LVL && ichx_priv.desc->use_outlvl_cache) data = ichx_priv.outlvl_cache[reg_nr] | data; |
6ed9f9c40
|
136 |
spin_unlock_irqrestore(&ichx_priv.lock, flags); |
7a8fd1f5c
|
137 |
return !!(data & BIT(bit)); |
6ed9f9c40
|
138 |
} |
e97f9b527
|
139 |
static bool ichx_gpio_check_available(struct gpio_chip *gpio, unsigned nr) |
4f600ada7
|
140 |
{ |
7a8fd1f5c
|
141 |
return !!(ichx_priv.use_gpio & BIT(nr / 32)); |
4f600ada7
|
142 |
} |
62e08f25b
|
143 144 |
static int ichx_gpio_get_direction(struct gpio_chip *gpio, unsigned nr) { |
3f4290d4d
|
145 |
return ichx_read_bit(GPIO_IO_SEL, nr); |
62e08f25b
|
146 |
} |
6ed9f9c40
|
147 148 149 150 151 152 |
static int ichx_gpio_direction_input(struct gpio_chip *gpio, unsigned nr) { /* * Try setting pin as an input and verify it worked since many pins * are output-only. */ |
c5aaa3168
|
153 |
return ichx_write_bit(GPIO_IO_SEL, nr, 1, 1); |
6ed9f9c40
|
154 155 156 157 158 |
} static int ichx_gpio_direction_output(struct gpio_chip *gpio, unsigned nr, int val) { |
7f6569f54
|
159 |
/* Disable blink hardware which is available for GPIOs from 0 to 31. */ |
ba7f74fe2
|
160 |
if (nr < 32 && ichx_priv.desc->have_blink) |
7f6569f54
|
161 |
ichx_write_bit(GPO_BLINK, nr, 0, 0); |
6ed9f9c40
|
162 163 164 165 166 167 168 |
/* Set GPIO output value. */ ichx_write_bit(GPIO_LVL, nr, val, 0); /* * Try setting pin as an output and verify it worked since many pins * are input-only. */ |
c5aaa3168
|
169 |
return ichx_write_bit(GPIO_IO_SEL, nr, 0, 1); |
6ed9f9c40
|
170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 |
} static int ichx_gpio_get(struct gpio_chip *chip, unsigned nr) { return ichx_read_bit(GPIO_LVL, nr); } static int ich6_gpio_get(struct gpio_chip *chip, unsigned nr) { unsigned long flags; u32 data; /* * GPI 0 - 15 need to be read from the power management registers on * a ICH6/3100 bridge. */ if (nr < 16) { if (!ichx_priv.pm_base) return -ENXIO; spin_lock_irqsave(&ichx_priv.lock, flags); /* GPI 0 - 15 are latched, write 1 to clear*/ |
7a8fd1f5c
|
193 |
ICHX_WRITE(BIT(16 + nr), 0, ichx_priv.pm_base); |
6ed9f9c40
|
194 195 196 |
data = ICHX_READ(0, ichx_priv.pm_base); spin_unlock_irqrestore(&ichx_priv.lock, flags); |
7a8fd1f5c
|
197 |
return !!((data >> 16) & BIT(nr)); |
6ed9f9c40
|
198 199 200 201 202 203 204 |
} else { return ichx_gpio_get(chip, nr); } } static int ichx_gpio_request(struct gpio_chip *chip, unsigned nr) { |
25f27db48
|
205 206 |
if (!ichx_gpio_check_available(chip, nr)) return -ENXIO; |
6ed9f9c40
|
207 208 209 210 211 212 |
/* * Note we assume the BIOS properly set a bridge's USE value. Some * chips (eg Intel 3100) have bogus USE values though, so first see if * the chipset's USE value can be trusted for this specific bit. * If it can't be trusted, assume that the pin can be used as a GPIO. */ |
7a8fd1f5c
|
213 |
if (ichx_priv.desc->use_sel_ignore[nr / 32] & BIT(nr & 0x1f)) |
2ab3a749e
|
214 |
return 0; |
6ed9f9c40
|
215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 |
return ichx_read_bit(GPIO_USE_SEL, nr) ? 0 : -ENODEV; } static int ich6_gpio_request(struct gpio_chip *chip, unsigned nr) { /* * Fixups for bits 16 and 17 are necessary on the Intel ICH6/3100 * bridge as they are controlled by USE register bits 0 and 1. See * "Table 704 GPIO_USE_SEL1 register" in the i3100 datasheet for * additional info. */ if (nr == 16 || nr == 17) nr -= 16; return ichx_gpio_request(chip, nr); } static void ichx_gpio_set(struct gpio_chip *chip, unsigned nr, int val) { ichx_write_bit(GPIO_LVL, nr, val, 0); } |
3836309d9
|
237 |
static void ichx_gpiolib_setup(struct gpio_chip *chip) |
6ed9f9c40
|
238 239 240 |
{ chip->owner = THIS_MODULE; chip->label = DRV_NAME; |
ff4709b44
|
241 |
chip->parent = ichx_priv.dev; |
6ed9f9c40
|
242 243 244 245 246 247 248 249 |
/* Allow chip-specific overrides of request()/get() */ chip->request = ichx_priv.desc->request ? ichx_priv.desc->request : ichx_gpio_request; chip->get = ichx_priv.desc->get ? ichx_priv.desc->get : ichx_gpio_get; chip->set = ichx_gpio_set; |
62e08f25b
|
250 |
chip->get_direction = ichx_gpio_get_direction; |
6ed9f9c40
|
251 252 253 254 |
chip->direction_input = ichx_gpio_direction_input; chip->direction_output = ichx_gpio_direction_output; chip->base = modparam_gpiobase; chip->ngpio = ichx_priv.desc->ngpio; |
9fb1f39eb
|
255 |
chip->can_sleep = false; |
6ed9f9c40
|
256 257 258 259 260 261 262 263 264 265 266 267 268 |
chip->dbg_show = NULL; } /* ICH6-based, 631xesb-based */ static struct ichx_desc ich6_desc = { /* Bridges using the ICH6 controller need fixups for GPIO 0 - 17 */ .request = ich6_gpio_request, .get = ich6_gpio_get, /* GPIO 0-15 are read in the GPE0_STS PM register */ .uses_gpe0 = true, .ngpio = 50, |
ba7f74fe2
|
269 |
.have_blink = true, |
a7008ee1a
|
270 271 |
.regs = ichx_regs, .reglen = ichx_reglen, |
6ed9f9c40
|
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 |
}; /* Intel 3100 */ static struct ichx_desc i3100_desc = { /* * Bits 16,17, 20 of USE_SEL and bit 16 of USE_SEL2 always read 0 on * the Intel 3100. See "Table 712. GPIO Summary Table" of 3100 * Datasheet for more info. */ .use_sel_ignore = {0x00130000, 0x00010000, 0x0}, /* The 3100 needs fixups for GPIO 0 - 17 */ .request = ich6_gpio_request, .get = ich6_gpio_get, /* GPIO 0-15 are read in the GPE0_STS PM register */ .uses_gpe0 = true, .ngpio = 50, |
a7008ee1a
|
291 292 |
.regs = ichx_regs, .reglen = ichx_reglen, |
6ed9f9c40
|
293 294 295 296 297 |
}; /* ICH7 and ICH8-based */ static struct ichx_desc ich7_desc = { .ngpio = 50, |
ba7f74fe2
|
298 |
.have_blink = true, |
bb62a35bd
|
299 300 |
.regs = ichx_regs, .reglen = ichx_reglen, |
6ed9f9c40
|
301 302 303 304 305 |
}; /* ICH9-based */ static struct ichx_desc ich9_desc = { .ngpio = 61, |
ba7f74fe2
|
306 |
.have_blink = true, |
bb62a35bd
|
307 308 |
.regs = ichx_regs, .reglen = ichx_reglen, |
6ed9f9c40
|
309 310 311 312 313 |
}; /* ICH10-based - Consumer/corporate versions have different amount of GPIO */ static struct ichx_desc ich10_cons_desc = { .ngpio = 61, |
ba7f74fe2
|
314 |
.have_blink = true, |
bb62a35bd
|
315 316 |
.regs = ichx_regs, .reglen = ichx_reglen, |
6ed9f9c40
|
317 318 319 |
}; static struct ichx_desc ich10_corp_desc = { .ngpio = 72, |
ba7f74fe2
|
320 |
.have_blink = true, |
bb62a35bd
|
321 322 |
.regs = ichx_regs, .reglen = ichx_reglen, |
6ed9f9c40
|
323 324 325 326 327 |
}; /* Intel 5 series, 6 series, 3400 series, and C200 series */ static struct ichx_desc intel5_desc = { .ngpio = 76, |
bb62a35bd
|
328 329 |
.regs = ichx_regs, .reglen = ichx_reglen, |
6ed9f9c40
|
330 |
}; |
3b9231893
|
331 332 333 334 335 336 337 338 339 340 |
/* Avoton */ static struct ichx_desc avoton_desc = { /* Avoton has only 59 GPIOs, but we assume the first set of register * (Core) has 32 instead of 31 to keep gpio-ich compliance */ .ngpio = 60, .regs = avoton_regs, .reglen = avoton_reglen, .use_outlvl_cache = true, }; |
8a06b08ec
|
341 342 |
static int ichx_gpio_request_regions(struct device *dev, struct resource *res_base, const char *name, u8 use_gpio) |
4f600ada7
|
343 344 345 346 347 |
{ int i; if (!res_base || !res_base->start || !res_base->end) return -ENODEV; |
bb62a35bd
|
348 |
for (i = 0; i < ARRAY_SIZE(ichx_priv.desc->regs[0]); i++) { |
7a8fd1f5c
|
349 |
if (!(use_gpio & BIT(i))) |
4f600ada7
|
350 |
continue; |
8a06b08ec
|
351 |
if (!devm_request_region(dev, |
bb62a35bd
|
352 353 |
res_base->start + ichx_priv.desc->regs[0][i], ichx_priv.desc->reglen[i], name)) |
8a06b08ec
|
354 |
return -EBUSY; |
4f600ada7
|
355 356 |
} return 0; |
4f600ada7
|
357 |
} |
3836309d9
|
358 |
static int ichx_gpio_probe(struct platform_device *pdev) |
6ed9f9c40
|
359 |
{ |
ff4709b44
|
360 361 |
struct device *dev = &pdev->dev; struct lpc_ich_info *ich_info = dev_get_platdata(dev); |
6ed9f9c40
|
362 363 |
struct resource *res_base, *res_pm; int err; |
6ed9f9c40
|
364 365 366 |
if (!ich_info) return -ENODEV; |
6ed9f9c40
|
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 |
switch (ich_info->gpio_version) { case ICH_I3100_GPIO: ichx_priv.desc = &i3100_desc; break; case ICH_V5_GPIO: ichx_priv.desc = &intel5_desc; break; case ICH_V6_GPIO: ichx_priv.desc = &ich6_desc; break; case ICH_V7_GPIO: ichx_priv.desc = &ich7_desc; break; case ICH_V9_GPIO: ichx_priv.desc = &ich9_desc; break; case ICH_V10CORP_GPIO: ichx_priv.desc = &ich10_corp_desc; break; case ICH_V10CONS_GPIO: ichx_priv.desc = &ich10_cons_desc; break; |
3b9231893
|
389 390 391 |
case AVOTON_GPIO: ichx_priv.desc = &avoton_desc; break; |
6ed9f9c40
|
392 393 394 |
default: return -ENODEV; } |
ff4709b44
|
395 |
ichx_priv.dev = dev; |
d39a948fe
|
396 |
spin_lock_init(&ichx_priv.lock); |
ff4709b44
|
397 |
|
6ed9f9c40
|
398 |
res_base = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPIO); |
ff4709b44
|
399 400 |
err = ichx_gpio_request_regions(dev, res_base, pdev->name, ich_info->use_gpio); |
4f600ada7
|
401 402 |
if (err) return err; |
6ed9f9c40
|
403 404 |
ichx_priv.gpio_base = res_base; |
ff4709b44
|
405 |
ichx_priv.use_gpio = ich_info->use_gpio; |
6ed9f9c40
|
406 407 408 |
/* * If necessary, determine the I/O address of ACPI/power management |
5f6f2b9f6
|
409 |
* registers which are needed to read the GPE0 register for GPI pins |
6ed9f9c40
|
410 411 412 413 414 415 416 |
* 0 - 15 on some chipsets. */ if (!ichx_priv.desc->uses_gpe0) goto init; res_pm = platform_get_resource(pdev, IORESOURCE_IO, ICH_RES_GPE0); if (!res_pm) { |
c086bea54
|
417 418 |
dev_warn(dev, "ACPI BAR is unavailable, GPI 0 - 15 unavailable "); |
6ed9f9c40
|
419 420 |
goto init; } |
ff4709b44
|
421 422 |
if (!devm_request_region(dev, res_pm->start, resource_size(res_pm), pdev->name)) { |
c086bea54
|
423 424 |
dev_warn(dev, "ACPI BAR is busy, GPI 0 - 15 unavailable "); |
6ed9f9c40
|
425 426 427 428 429 430 431 |
goto init; } ichx_priv.pm_base = res_pm; init: ichx_gpiolib_setup(&ichx_priv.chip); |
4eab22e74
|
432 |
err = gpiochip_add_data(&ichx_priv.chip, NULL); |
6ed9f9c40
|
433 |
if (err) { |
c086bea54
|
434 435 |
dev_err(dev, "Failed to register GPIOs "); |
8a06b08ec
|
436 |
return err; |
6ed9f9c40
|
437 |
} |
c086bea54
|
438 439 440 |
dev_info(dev, "GPIO from %d to %d ", ichx_priv.chip.base, ichx_priv.chip.base + ichx_priv.chip.ngpio - 1); |
6ed9f9c40
|
441 442 |
return 0; |
6ed9f9c40
|
443 |
} |
206210ce6
|
444 |
static int ichx_gpio_remove(struct platform_device *pdev) |
6ed9f9c40
|
445 |
{ |
9f5132ae8
|
446 |
gpiochip_remove(&ichx_priv.chip); |
6ed9f9c40
|
447 |
|
6ed9f9c40
|
448 449 450 451 452 |
return 0; } static struct platform_driver ichx_gpio_driver = { .driver = { |
6ed9f9c40
|
453 454 455 |
.name = DRV_NAME, }, .probe = ichx_gpio_probe, |
8283c4ff5
|
456 |
.remove = ichx_gpio_remove, |
6ed9f9c40
|
457 458 459 460 461 462 463 464 |
}; module_platform_driver(ichx_gpio_driver); MODULE_AUTHOR("Peter Tyser <ptyser@xes-inc.com>"); MODULE_DESCRIPTION("GPIO interface for Intel ICH series"); MODULE_LICENSE("GPL"); MODULE_ALIAS("platform:"DRV_NAME); |