From 8f1cc3b10e6ee0c5c7c8ed27f8771c4f252b4862 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Fri, 25 Jul 2008 01:46:09 -0700 Subject: gpio: mcp23s08 handles multiple chips per chipselect Teach the mcp23s08 driver about a curious feature of these chips: up to four of them can share the same chipselect, with the SPI signals wired in parallel, by matching two bits in the first protocol byte against two address lines on the chip. This is handled by three software changes: * Platform data now holds an array of per-chip structs, not just one chip's address and pullup configuration. * Probe() and remove() now use another level of structure, wrapping an instance of the original structure for each mcp23s08 chip sharing that chipselect. * The HAEN bit is set, so that the hardware address bits can no longer be ignored (boot firmware may not have enabled them). The "one struct per chip" preserves the guts of the current code, but platform_data will need minor changes. OLD: /* incorrect "slave" ID may not have mattered */ .slave = 3, .pullups = BIT(3) | BIT(1) | BIT(0), NEW: /* slave address _must_ match chip's wiring */ .chip[3] = { .is_present = true, .pullups = BIT(3) | BIT(1) | BIT(0), }, There's no change in how things _behave_ for spi_device nodes with a single mcp23s08 chip. New multi-chip configurations assign GPIOs in sequence, without holes. The spi_device just resembles a bigger controller, but internally it has multiple gpio_chip instances. Signed-off-by: David Brownell Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- include/linux/spi/mcp23s08.h | 25 ++++++++++++++++--------- 1 file changed, 16 insertions(+), 9 deletions(-) (limited to 'include/linux/spi') diff --git a/include/linux/spi/mcp23s08.h b/include/linux/spi/mcp23s08.h index 835ddf47d45..22ef107d770 100644 --- a/include/linux/spi/mcp23s08.h +++ b/include/linux/spi/mcp23s08.h @@ -1,18 +1,25 @@ -/* FIXME driver should be able to handle all four slaves that - * can be hooked up to each chipselect, as well as IRQs... - */ +/* FIXME driver should be able to handle IRQs... */ + +struct mcp23s08_chip_info { + bool is_present; /* true iff populated */ + u8 pullups; /* BIT(x) means enable pullup x */ +}; struct mcp23s08_platform_data { - /* four slaves can share one SPI chipselect */ - u8 slave; + /* Four slaves (numbered 0..3) can share one SPI chipselect, and + * will provide 8..32 GPIOs using 1..4 gpio_chip instances. + */ + struct mcp23s08_chip_info chip[4]; - /* number assigned to the first GPIO */ + /* "base" is the number of the first GPIO. Dynamic assignment is + * not currently supported, and even if there are gaps in chip + * addressing the GPIO numbers are sequential .. so for example + * if only slaves 0 and 3 are present, their GPIOs range from + * base to base+15. + */ unsigned base; - /* pins with pullups */ - u8 pullups; - void *context; /* param to setup/teardown */ int (*setup)(struct spi_device *spi, -- cgit v1.2.3-70-g09d2