Re: [PATCH] mcp23s08: support mcp23s17 variant

From: Grant Likely
Date: Mon Feb 14 2011 - 12:13:28 EST


On Mon, Feb 14, 2011 at 9:12 AM, Peter Korsgaard <jacmet@xxxxxxxxxx> wrote:
> mpc23s17 is very similar to the mcp23s08, except that registers are 16bit
> wide, so extend the interface to work with both variants.
>
> The s17 variant also has an additional address pin, so adjust platform
> data structure to support up to 8 devices per SPI chipselect.
>
> Signed-off-by: Peter Korsgaard <jacmet@xxxxxxxxxx>
> ---
>  drivers/gpio/Kconfig         |    6 +-
>  drivers/gpio/mcp23s08.c      |  147 +++++++++++++++++++++++++++++-------------
>  include/linux/spi/mcp23s08.h |   15 +++--
>  3 files changed, 113 insertions(+), 55 deletions(-)
>
> diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig
> index 664660e..9573b33 100644
> --- a/drivers/gpio/Kconfig
> +++ b/drivers/gpio/Kconfig
> @@ -368,11 +368,11 @@ config GPIO_MAX7301
>          GPIO driver for Maxim MAX7301 SPI-based GPIO expander.
>
>  config GPIO_MCP23S08
> -       tristate "Microchip MCP23S08 I/O expander"
> +       tristate "Microchip MCP23Sxx I/O expander"
>        depends on SPI_MASTER
>        help
> -         SPI driver for Microchip MCP23S08 I/O expander.  This provides
> -         a GPIO interface supporting inputs and outputs.
> +         SPI driver for Microchip MCP23S08/MPC23S17 I/O expanders.
> +         This provides a GPIO interface supporting inputs and outputs.
>
>  config GPIO_MC33880
>        tristate "Freescale MC33880 high-side/low-side switch"
> diff --git a/drivers/gpio/mcp23s08.c b/drivers/gpio/mcp23s08.c
> index 69f6f19..497e527 100644
> --- a/drivers/gpio/mcp23s08.c
> +++ b/drivers/gpio/mcp23s08.c
> @@ -10,7 +10,13 @@
>  #include <linux/spi/spi.h>
>  #include <linux/spi/mcp23s08.h>
>  #include <linux/slab.h>
> +#include <asm/byteorder.h>
>
> +/**
> + * MCP types supported by driver
> + */
> +#define MCP_TYPE_S08   0
> +#define MCP_TYPE_S17   1
>
>  /* Registers are all 8 bits wide.
>  *
> @@ -38,8 +44,9 @@
>  struct mcp23s08 {
>        struct spi_device       *spi;
>        u8                      addr;
> +       u8                      type;
>
> -       u8                      cache[11];
> +       u16                     cache[11];
>        /* lock protects the cached values */
>        struct mutex            lock;
>
> @@ -48,48 +55,83 @@ struct mcp23s08 {
>        struct work_struct      work;
>  };
>
> -/* A given spi_device can represent up to four mcp23s08 chips
> +/* A given spi_device can represent up to eight mcp23sxx chips
>  * sharing the same chipselect but using different addresses
>  * (e.g. chips #0 and #3 might be populated, but not #1 or $2).
>  * Driver data holds all the per-chip data.
>  */
>  struct mcp23s08_driver_data {
>        unsigned                ngpio;
> -       struct mcp23s08         *mcp[4];
> +       struct mcp23s08         *mcp[8];
>        struct mcp23s08         chip[];
>  };
>
>  static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
>  {
> -       u8      tx[2], rx[1];
> +       u8      tx[2], rx[2];
>        int     status;
>
>        tx[0] = mcp->addr | 0x01;
>        tx[1] = reg;
> -       status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx);
> -       return (status < 0) ? status : rx[0];
> +
> +       if (mcp->type == MCP_TYPE_S17) {
> +               tx[1] <<= 1;
> +
> +               status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, 2);
> +               return (status < 0) ? status : (rx[0] | (rx[1] << 8));
> +       } else {
> +               status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, 1);
> +               return (status < 0) ? status : rx[0];
> +       }

Rather than checking ->type for every transaction, would a set of
callbacks for each type be better? It would probably have lower
overhead and be simpler to maintain.

[...]
> diff --git a/include/linux/spi/mcp23s08.h b/include/linux/spi/mcp23s08.h
> index 22ef107..c42cff8 100644
> --- a/include/linux/spi/mcp23s08.h
> +++ b/include/linux/spi/mcp23s08.h
> @@ -2,21 +2,24 @@
>  /* 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 */
> +       bool            is_present;     /* true if populated */
> +       unsigned        pullups;        /* BIT(x) means enable pullup x */
>  };

Unrelated whitespace changes.
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/