diff options
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 ef61234c0e0..7b78f940868 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);  |