diff options
author | Peter Korsgaard <jacmet@sunsite.dk> | 2011-07-15 04:25:31 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-07-15 15:54:18 -0400 |
commit | d62b98f305a6b0d32fbdc72ac6ba3d4f4768adeb (patch) | |
tree | 4d449ba816ce6ddc3df16822863b9c6132b93deb /drivers/gpio/gpio-mcp23s08.c | |
parent | 1bb6f9b042eb1428ba927d2e851a00df6308877a (diff) |
mcp23s08: isolate spi specific parts
Change spi member of struct mcp23s08 to be a ops-specific opaque data
pointer, and move spi specific knowledge out of mcp23s08_probe_one().
No functional change, but is needed to add i2c support.
Signed-off-by: Peter Korsgaard <jacmet@sunsite.dk>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/gpio/gpio-mcp23s08.c')
-rw-r--r-- | drivers/gpio/gpio-mcp23s08.c | 81 |
1 files changed, 57 insertions, 24 deletions
diff --git a/drivers/gpio/gpio-mcp23s08.c b/drivers/gpio/gpio-mcp23s08.c index ef61234c0e03..7b78f940868e 100644 --- a/drivers/gpio/gpio-mcp23s08.c +++ b/drivers/gpio/gpio-mcp23s08.c | |||
@@ -50,7 +50,6 @@ struct mcp23s08_ops { | |||
50 | }; | 50 | }; |
51 | 51 | ||
52 | struct mcp23s08 { | 52 | struct mcp23s08 { |
53 | struct spi_device *spi; | ||
54 | u8 addr; | 53 | u8 addr; |
55 | 54 | ||
56 | u16 cache[11]; | 55 | u16 cache[11]; |
@@ -60,6 +59,7 @@ struct mcp23s08 { | |||
60 | struct gpio_chip chip; | 59 | struct gpio_chip chip; |
61 | 60 | ||
62 | const struct mcp23s08_ops *ops; | 61 | const struct mcp23s08_ops *ops; |
62 | void *data; /* ops specific data */ | ||
63 | }; | 63 | }; |
64 | 64 | ||
65 | /* A given spi_device can represent up to eight mcp23sxx chips | 65 | /* A given spi_device can represent up to eight mcp23sxx chips |
@@ -73,6 +73,8 @@ struct mcp23s08_driver_data { | |||
73 | struct mcp23s08 chip[]; | 73 | struct mcp23s08 chip[]; |
74 | }; | 74 | }; |
75 | 75 | ||
76 | #ifdef CONFIG_SPI_MASTER | ||
77 | |||
76 | static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg) | 78 | static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg) |
77 | { | 79 | { |
78 | u8 tx[2], rx[1]; | 80 | u8 tx[2], rx[1]; |
@@ -80,7 +82,7 @@ static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg) | |||
80 | 82 | ||
81 | tx[0] = mcp->addr | 0x01; | 83 | tx[0] = mcp->addr | 0x01; |
82 | tx[1] = reg; | 84 | tx[1] = reg; |
83 | status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx); | 85 | status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx); |
84 | return (status < 0) ? status : rx[0]; | 86 | return (status < 0) ? status : rx[0]; |
85 | } | 87 | } |
86 | 88 | ||
@@ -91,7 +93,7 @@ static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) | |||
91 | tx[0] = mcp->addr; | 93 | tx[0] = mcp->addr; |
92 | tx[1] = reg; | 94 | tx[1] = reg; |
93 | tx[2] = val; | 95 | tx[2] = val; |
94 | return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0); | 96 | return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0); |
95 | } | 97 | } |
96 | 98 | ||
97 | static int | 99 | static int |
@@ -106,7 +108,7 @@ mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) | |||
106 | tx[1] = reg; | 108 | tx[1] = reg; |
107 | 109 | ||
108 | tmp = (u8 *)vals; | 110 | tmp = (u8 *)vals; |
109 | status = spi_write_then_read(mcp->spi, tx, sizeof tx, tmp, n); | 111 | status = spi_write_then_read(mcp->data, tx, sizeof tx, tmp, n); |
110 | if (status >= 0) { | 112 | if (status >= 0) { |
111 | while (n--) | 113 | while (n--) |
112 | vals[n] = tmp[n]; /* expand to 16bit */ | 114 | vals[n] = tmp[n]; /* expand to 16bit */ |
@@ -121,7 +123,7 @@ static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg) | |||
121 | 123 | ||
122 | tx[0] = mcp->addr | 0x01; | 124 | tx[0] = mcp->addr | 0x01; |
123 | tx[1] = reg << 1; | 125 | tx[1] = reg << 1; |
124 | status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx); | 126 | status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx); |
125 | return (status < 0) ? status : (rx[0] | (rx[1] << 8)); | 127 | return (status < 0) ? status : (rx[0] | (rx[1] << 8)); |
126 | } | 128 | } |
127 | 129 | ||
@@ -133,7 +135,7 @@ static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) | |||
133 | tx[1] = reg << 1; | 135 | tx[1] = reg << 1; |
134 | tx[2] = val; | 136 | tx[2] = val; |
135 | tx[3] = val >> 8; | 137 | tx[3] = val >> 8; |
136 | return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0); | 138 | return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0); |
137 | } | 139 | } |
138 | 140 | ||
139 | static int | 141 | static int |
@@ -147,7 +149,7 @@ mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) | |||
147 | tx[0] = mcp->addr | 0x01; | 149 | tx[0] = mcp->addr | 0x01; |
148 | tx[1] = reg << 1; | 150 | tx[1] = reg << 1; |
149 | 151 | ||
150 | status = spi_write_then_read(mcp->spi, tx, sizeof tx, | 152 | status = spi_write_then_read(mcp->data, tx, sizeof tx, |
151 | (u8 *)vals, n * 2); | 153 | (u8 *)vals, n * 2); |
152 | if (status >= 0) { | 154 | if (status >= 0) { |
153 | while (n--) | 155 | while (n--) |
@@ -169,6 +171,7 @@ static const struct mcp23s08_ops mcp23s17_ops = { | |||
169 | .read_regs = mcp23s17_read_regs, | 171 | .read_regs = mcp23s17_read_regs, |
170 | }; | 172 | }; |
171 | 173 | ||
174 | #endif /* CONFIG_SPI_MASTER */ | ||
172 | 175 | ||
173 | /*----------------------------------------------------------------------*/ | 176 | /*----------------------------------------------------------------------*/ |
174 | 177 | ||
@@ -296,17 +299,16 @@ done: | |||
296 | 299 | ||
297 | /*----------------------------------------------------------------------*/ | 300 | /*----------------------------------------------------------------------*/ |
298 | 301 | ||
299 | static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr, | 302 | static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, |
303 | void *data, unsigned addr, | ||
300 | unsigned type, unsigned base, unsigned pullups) | 304 | unsigned type, unsigned base, unsigned pullups) |
301 | { | 305 | { |
302 | struct mcp23s08_driver_data *data = spi_get_drvdata(spi); | 306 | int status; |
303 | struct mcp23s08 *mcp = data->mcp[addr]; | ||
304 | int status; | ||
305 | 307 | ||
306 | mutex_init(&mcp->lock); | 308 | mutex_init(&mcp->lock); |
307 | 309 | ||
308 | mcp->spi = spi; | 310 | mcp->data = data; |
309 | mcp->addr = 0x40 | (addr << 1); | 311 | mcp->addr = addr; |
310 | 312 | ||
311 | mcp->chip.direction_input = mcp23s08_direction_input; | 313 | mcp->chip.direction_input = mcp23s08_direction_input; |
312 | mcp->chip.get = mcp23s08_get; | 314 | mcp->chip.get = mcp23s08_get; |
@@ -314,18 +316,29 @@ static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr, | |||
314 | mcp->chip.set = mcp23s08_set; | 316 | mcp->chip.set = mcp23s08_set; |
315 | mcp->chip.dbg_show = mcp23s08_dbg_show; | 317 | mcp->chip.dbg_show = mcp23s08_dbg_show; |
316 | 318 | ||
317 | if (type == MCP_TYPE_S17) { | 319 | switch (type) { |
318 | mcp->ops = &mcp23s17_ops; | 320 | #ifdef CONFIG_SPI_MASTER |
319 | mcp->chip.ngpio = 16; | 321 | case MCP_TYPE_S08: |
320 | mcp->chip.label = "mcp23s17"; | ||
321 | } else { | ||
322 | mcp->ops = &mcp23s08_ops; | 322 | mcp->ops = &mcp23s08_ops; |
323 | mcp->chip.ngpio = 8; | 323 | mcp->chip.ngpio = 8; |
324 | mcp->chip.label = "mcp23s08"; | 324 | mcp->chip.label = "mcp23s08"; |
325 | break; | ||
326 | |||
327 | case MCP_TYPE_S17: | ||
328 | mcp->ops = &mcp23s17_ops; | ||
329 | mcp->chip.ngpio = 16; | ||
330 | mcp->chip.label = "mcp23s17"; | ||
331 | break; | ||
332 | #endif /* CONFIG_SPI_MASTER */ | ||
333 | |||
334 | default: | ||
335 | dev_err(dev, "invalid device type (%d)\n", type); | ||
336 | return -EINVAL; | ||
325 | } | 337 | } |
338 | |||
326 | mcp->chip.base = base; | 339 | mcp->chip.base = base; |
327 | mcp->chip.can_sleep = 1; | 340 | mcp->chip.can_sleep = 1; |
328 | mcp->chip.dev = &spi->dev; | 341 | mcp->chip.dev = dev; |
329 | mcp->chip.owner = THIS_MODULE; | 342 | mcp->chip.owner = THIS_MODULE; |
330 | 343 | ||
331 | /* verify MCP_IOCON.SEQOP = 0, so sequential reads work, | 344 | /* verify MCP_IOCON.SEQOP = 0, so sequential reads work, |
@@ -371,11 +384,13 @@ static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr, | |||
371 | status = gpiochip_add(&mcp->chip); | 384 | status = gpiochip_add(&mcp->chip); |
372 | fail: | 385 | fail: |
373 | if (status < 0) | 386 | if (status < 0) |
374 | dev_dbg(&spi->dev, "can't setup chip %d, --> %d\n", | 387 | dev_dbg(dev, "can't setup chip %d, --> %d\n", |
375 | addr, status); | 388 | addr, status); |
376 | return status; | 389 | return status; |
377 | } | 390 | } |
378 | 391 | ||
392 | #ifdef CONFIG_SPI_MASTER | ||
393 | |||
379 | static int mcp23s08_probe(struct spi_device *spi) | 394 | static int mcp23s08_probe(struct spi_device *spi) |
380 | { | 395 | { |
381 | struct mcp23s08_platform_data *pdata; | 396 | struct mcp23s08_platform_data *pdata; |
@@ -418,7 +433,8 @@ static int mcp23s08_probe(struct spi_device *spi) | |||
418 | continue; | 433 | continue; |
419 | chips--; | 434 | chips--; |
420 | data->mcp[addr] = &data->chip[chips]; | 435 | data->mcp[addr] = &data->chip[chips]; |
421 | status = mcp23s08_probe_one(spi, addr, type, base, | 436 | status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi, |
437 | 0x40 | (addr << 1), type, base, | ||
422 | pdata->chip[addr].pullups); | 438 | pdata->chip[addr].pullups); |
423 | if (status < 0) | 439 | if (status < 0) |
424 | goto fail; | 440 | goto fail; |
@@ -488,11 +504,28 @@ static struct spi_driver mcp23s08_driver = { | |||
488 | }, | 504 | }, |
489 | }; | 505 | }; |
490 | 506 | ||
507 | static int __init mcp23s08_spi_init(void) | ||
508 | { | ||
509 | return spi_register_driver(&mcp23s08_driver); | ||
510 | } | ||
511 | |||
512 | static void mcp23s08_spi_exit(void) | ||
513 | { | ||
514 | spi_unregister_driver(&mcp23s08_driver); | ||
515 | } | ||
516 | |||
517 | #else | ||
518 | |||
519 | static int __init mcp23s08_spi_init(void) { return 0; } | ||
520 | static void mcp23s08_spi_exit(void) { } | ||
521 | |||
522 | #endif /* CONFIG_SPI_MASTER */ | ||
523 | |||
491 | /*----------------------------------------------------------------------*/ | 524 | /*----------------------------------------------------------------------*/ |
492 | 525 | ||
493 | static int __init mcp23s08_init(void) | 526 | static int __init mcp23s08_init(void) |
494 | { | 527 | { |
495 | return spi_register_driver(&mcp23s08_driver); | 528 | return mcp23s08_spi_init(); |
496 | } | 529 | } |
497 | /* register after spi postcore initcall and before | 530 | /* register after spi postcore initcall and before |
498 | * subsys initcalls that may rely on these GPIOs | 531 | * subsys initcalls that may rely on these GPIOs |
@@ -501,7 +534,7 @@ subsys_initcall(mcp23s08_init); | |||
501 | 534 | ||
502 | static void __exit mcp23s08_exit(void) | 535 | static void __exit mcp23s08_exit(void) |
503 | { | 536 | { |
504 | spi_unregister_driver(&mcp23s08_driver); | 537 | mcp23s08_spi_exit(); |
505 | } | 538 | } |
506 | module_exit(mcp23s08_exit); | 539 | module_exit(mcp23s08_exit); |
507 | 540 | ||