aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpio/gpio-mcp23s08.c
diff options
context:
space:
mode:
authorPeter Korsgaard <jacmet@sunsite.dk>2011-07-15 04:25:31 -0400
committerGrant Likely <grant.likely@secretlab.ca>2011-07-15 15:54:18 -0400
commitd62b98f305a6b0d32fbdc72ac6ba3d4f4768adeb (patch)
tree4d449ba816ce6ddc3df16822863b9c6132b93deb /drivers/gpio/gpio-mcp23s08.c
parent1bb6f9b042eb1428ba927d2e851a00df6308877a (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.c81
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
52struct mcp23s08 { 52struct 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
76static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg) 78static 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
97static int 99static 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
139static int 141static 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
299static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr, 302static 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);
372fail: 385fail:
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
379static int mcp23s08_probe(struct spi_device *spi) 394static 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
507static int __init mcp23s08_spi_init(void)
508{
509 return spi_register_driver(&mcp23s08_driver);
510}
511
512static void mcp23s08_spi_exit(void)
513{
514 spi_unregister_driver(&mcp23s08_driver);
515}
516
517#else
518
519static int __init mcp23s08_spi_init(void) { return 0; }
520static void mcp23s08_spi_exit(void) { }
521
522#endif /* CONFIG_SPI_MASTER */
523
491/*----------------------------------------------------------------------*/ 524/*----------------------------------------------------------------------*/
492 525
493static int __init mcp23s08_init(void) 526static 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
502static void __exit mcp23s08_exit(void) 535static void __exit mcp23s08_exit(void)
503{ 536{
504 spi_unregister_driver(&mcp23s08_driver); 537 mcp23s08_spi_exit();
505} 538}
506module_exit(mcp23s08_exit); 539module_exit(mcp23s08_exit);
507 540