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>
This commit is contained in:
Peter Korsgaard 2011-07-15 10:25:31 +02:00 committed by Grant Likely
parent 1bb6f9b042
commit d62b98f305
1 changed files with 57 additions and 24 deletions

View File

@ -50,7 +50,6 @@ struct mcp23s08_ops {
}; };
struct mcp23s08 { struct mcp23s08 {
struct spi_device *spi;
u8 addr; u8 addr;
u16 cache[11]; u16 cache[11];
@ -60,6 +59,7 @@ struct mcp23s08 {
struct gpio_chip chip; struct gpio_chip chip;
const struct mcp23s08_ops *ops; const struct mcp23s08_ops *ops;
void *data; /* ops specific data */
}; };
/* A given spi_device can represent up to eight mcp23sxx chips /* A given spi_device can represent up to eight mcp23sxx chips
@ -73,6 +73,8 @@ struct mcp23s08_driver_data {
struct mcp23s08 chip[]; struct mcp23s08 chip[];
}; };
#ifdef CONFIG_SPI_MASTER
static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg) static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
{ {
u8 tx[2], rx[1]; u8 tx[2], rx[1];
@ -80,7 +82,7 @@ static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
tx[0] = mcp->addr | 0x01; tx[0] = mcp->addr | 0x01;
tx[1] = reg; 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]; 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[0] = mcp->addr;
tx[1] = reg; tx[1] = reg;
tx[2] = val; 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 static int
@ -106,7 +108,7 @@ mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
tx[1] = reg; tx[1] = reg;
tmp = (u8 *)vals; 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) { if (status >= 0) {
while (n--) while (n--)
vals[n] = tmp[n]; /* expand to 16bit */ 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[0] = mcp->addr | 0x01;
tx[1] = reg << 1; 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)); 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[1] = reg << 1;
tx[2] = val; tx[2] = val;
tx[3] = val >> 8; 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 static int
@ -147,7 +149,7 @@ mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
tx[0] = mcp->addr | 0x01; tx[0] = mcp->addr | 0x01;
tx[1] = reg << 1; 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); (u8 *)vals, n * 2);
if (status >= 0) { if (status >= 0) {
while (n--) while (n--)
@ -169,6 +171,7 @@ static const struct mcp23s08_ops mcp23s17_ops = {
.read_regs = mcp23s17_read_regs, .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) unsigned type, unsigned base, unsigned pullups)
{ {
struct mcp23s08_driver_data *data = spi_get_drvdata(spi); int status;
struct mcp23s08 *mcp = data->mcp[addr];
int status;
mutex_init(&mcp->lock); mutex_init(&mcp->lock);
mcp->spi = spi; mcp->data = data;
mcp->addr = 0x40 | (addr << 1); mcp->addr = addr;
mcp->chip.direction_input = mcp23s08_direction_input; mcp->chip.direction_input = mcp23s08_direction_input;
mcp->chip.get = mcp23s08_get; 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.set = mcp23s08_set;
mcp->chip.dbg_show = mcp23s08_dbg_show; mcp->chip.dbg_show = mcp23s08_dbg_show;
if (type == MCP_TYPE_S17) { switch (type) {
mcp->ops = &mcp23s17_ops; #ifdef CONFIG_SPI_MASTER
mcp->chip.ngpio = 16; case MCP_TYPE_S08:
mcp->chip.label = "mcp23s17";
} else {
mcp->ops = &mcp23s08_ops; mcp->ops = &mcp23s08_ops;
mcp->chip.ngpio = 8; mcp->chip.ngpio = 8;
mcp->chip.label = "mcp23s08"; 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.base = base;
mcp->chip.can_sleep = 1; mcp->chip.can_sleep = 1;
mcp->chip.dev = &spi->dev; mcp->chip.dev = dev;
mcp->chip.owner = THIS_MODULE; mcp->chip.owner = THIS_MODULE;
/* verify MCP_IOCON.SEQOP = 0, so sequential reads work, /* 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); status = gpiochip_add(&mcp->chip);
fail: fail:
if (status < 0) if (status < 0)
dev_dbg(&spi->dev, "can't setup chip %d, --> %d\n", dev_dbg(dev, "can't setup chip %d, --> %d\n",
addr, status); addr, status);
return status; return status;
} }
#ifdef CONFIG_SPI_MASTER
static int mcp23s08_probe(struct spi_device *spi) static int mcp23s08_probe(struct spi_device *spi)
{ {
struct mcp23s08_platform_data *pdata; struct mcp23s08_platform_data *pdata;
@ -418,7 +433,8 @@ static int mcp23s08_probe(struct spi_device *spi)
continue; continue;
chips--; chips--;
data->mcp[addr] = &data->chip[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); pdata->chip[addr].pullups);
if (status < 0) if (status < 0)
goto fail; 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) static int __init mcp23s08_init(void)
{ {
return spi_register_driver(&mcp23s08_driver); return mcp23s08_spi_init();
} }
/* register after spi postcore initcall and before /* register after spi postcore initcall and before
* subsys initcalls that may rely on these GPIOs * subsys initcalls that may rely on these GPIOs
@ -501,7 +534,7 @@ subsys_initcall(mcp23s08_init);
static void __exit mcp23s08_exit(void) static void __exit mcp23s08_exit(void)
{ {
spi_unregister_driver(&mcp23s08_driver); mcp23s08_spi_exit();
} }
module_exit(mcp23s08_exit); module_exit(mcp23s08_exit);