From d62b98f305a6b0d32fbdc72ac6ba3d4f4768adeb Mon Sep 17 00:00:00 2001
From: Peter Korsgaard <jacmet@sunsite.dk>
Date: Fri, 15 Jul 2011 10:25:31 +0200
Subject: 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>
---
 drivers/gpio/gpio-mcp23s08.c | 81 +++++++++++++++++++++++++++++++-------------
 1 file changed, 57 insertions(+), 24 deletions(-)

(limited to 'drivers')

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);
 
-- 
cgit v1.2.3