diff options
author | Peter Korsgaard <jacmet@sunsite.dk> | 2011-07-15 10:25:31 +0200 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-07-15 13:54:18 -0600 |
commit | d62b98f305a6b0d32fbdc72ac6ba3d4f4768adeb (patch) | |
tree | 4d449ba816ce6ddc3df16822863b9c6132b93deb /drivers/gpio | |
parent | 1bb6f9b042eb1428ba927d2e851a00df6308877a (diff) | |
download | blackbird-op-linux-d62b98f305a6b0d32fbdc72ac6ba3d4f4768adeb.tar.gz blackbird-op-linux-d62b98f305a6b0d32fbdc72ac6ba3d4f4768adeb.zip |
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')
-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 { }; struct mcp23s08 { - struct spi_device *spi; u8 addr; u16 cache[11]; @@ -60,6 +59,7 @@ struct mcp23s08 { struct gpio_chip chip; const struct mcp23s08_ops *ops; + void *data; /* ops specific data */ }; /* A given spi_device can represent up to eight mcp23sxx chips @@ -73,6 +73,8 @@ struct mcp23s08_driver_data { struct mcp23s08 chip[]; }; +#ifdef CONFIG_SPI_MASTER + static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg) { u8 tx[2], rx[1]; @@ -80,7 +82,7 @@ static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg) tx[0] = mcp->addr | 0x01; tx[1] = reg; - status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx); + status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx); return (status < 0) ? status : rx[0]; } @@ -91,7 +93,7 @@ static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) tx[0] = mcp->addr; tx[1] = reg; tx[2] = val; - return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0); + return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0); } static int @@ -106,7 +108,7 @@ mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) tx[1] = reg; tmp = (u8 *)vals; - status = spi_write_then_read(mcp->spi, tx, sizeof tx, tmp, n); + status = spi_write_then_read(mcp->data, tx, sizeof tx, tmp, n); if (status >= 0) { while (n--) vals[n] = tmp[n]; /* expand to 16bit */ @@ -121,7 +123,7 @@ static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg) tx[0] = mcp->addr | 0x01; tx[1] = reg << 1; - status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx); + status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx); return (status < 0) ? status : (rx[0] | (rx[1] << 8)); } @@ -133,7 +135,7 @@ static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val) tx[1] = reg << 1; tx[2] = val; tx[3] = val >> 8; - return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0); + return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0); } static int @@ -147,7 +149,7 @@ mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n) tx[0] = mcp->addr | 0x01; tx[1] = reg << 1; - status = spi_write_then_read(mcp->spi, tx, sizeof tx, + status = spi_write_then_read(mcp->data, tx, sizeof tx, (u8 *)vals, n * 2); if (status >= 0) { while (n--) @@ -169,6 +171,7 @@ static const struct mcp23s08_ops mcp23s17_ops = { .read_regs = mcp23s17_read_regs, }; +#endif /* CONFIG_SPI_MASTER */ /*----------------------------------------------------------------------*/ @@ -296,17 +299,16 @@ done: /*----------------------------------------------------------------------*/ -static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr, +static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev, + void *data, unsigned addr, unsigned type, unsigned base, unsigned pullups) { - struct mcp23s08_driver_data *data = spi_get_drvdata(spi); - struct mcp23s08 *mcp = data->mcp[addr]; - int status; + int status; mutex_init(&mcp->lock); - mcp->spi = spi; - mcp->addr = 0x40 | (addr << 1); + mcp->data = data; + mcp->addr = addr; mcp->chip.direction_input = mcp23s08_direction_input; mcp->chip.get = mcp23s08_get; @@ -314,18 +316,29 @@ static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr, mcp->chip.set = mcp23s08_set; mcp->chip.dbg_show = mcp23s08_dbg_show; - if (type == MCP_TYPE_S17) { - mcp->ops = &mcp23s17_ops; - mcp->chip.ngpio = 16; - mcp->chip.label = "mcp23s17"; - } else { + switch (type) { +#ifdef CONFIG_SPI_MASTER + case MCP_TYPE_S08: mcp->ops = &mcp23s08_ops; mcp->chip.ngpio = 8; mcp->chip.label = "mcp23s08"; + break; + + case MCP_TYPE_S17: + mcp->ops = &mcp23s17_ops; + mcp->chip.ngpio = 16; + mcp->chip.label = "mcp23s17"; + break; +#endif /* CONFIG_SPI_MASTER */ + + default: + dev_err(dev, "invalid device type (%d)\n", type); + return -EINVAL; } + mcp->chip.base = base; mcp->chip.can_sleep = 1; - mcp->chip.dev = &spi->dev; + mcp->chip.dev = dev; mcp->chip.owner = THIS_MODULE; /* verify MCP_IOCON.SEQOP = 0, so sequential reads work, @@ -371,11 +384,13 @@ static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr, status = gpiochip_add(&mcp->chip); fail: if (status < 0) - dev_dbg(&spi->dev, "can't setup chip %d, --> %d\n", - addr, status); + dev_dbg(dev, "can't setup chip %d, --> %d\n", + addr, status); return status; } +#ifdef CONFIG_SPI_MASTER + static int mcp23s08_probe(struct spi_device *spi) { struct mcp23s08_platform_data *pdata; @@ -418,7 +433,8 @@ static int mcp23s08_probe(struct spi_device *spi) continue; chips--; data->mcp[addr] = &data->chip[chips]; - status = mcp23s08_probe_one(spi, addr, type, base, + status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi, + 0x40 | (addr << 1), type, base, pdata->chip[addr].pullups); if (status < 0) goto fail; @@ -488,11 +504,28 @@ static struct spi_driver mcp23s08_driver = { }, }; +static int __init mcp23s08_spi_init(void) +{ + return spi_register_driver(&mcp23s08_driver); +} + +static void mcp23s08_spi_exit(void) +{ + spi_unregister_driver(&mcp23s08_driver); +} + +#else + +static int __init mcp23s08_spi_init(void) { return 0; } +static void mcp23s08_spi_exit(void) { } + +#endif /* CONFIG_SPI_MASTER */ + /*----------------------------------------------------------------------*/ static int __init mcp23s08_init(void) { - return spi_register_driver(&mcp23s08_driver); + return mcp23s08_spi_init(); } /* register after spi postcore initcall and before * subsys initcalls that may rely on these GPIOs @@ -501,7 +534,7 @@ subsys_initcall(mcp23s08_init); static void __exit mcp23s08_exit(void) { - spi_unregister_driver(&mcp23s08_driver); + mcp23s08_spi_exit(); } module_exit(mcp23s08_exit); |