linux/drivers/gpio/gpio-mcp23s08.c
<<
>>
Prefs
   1/*
   2 * MCP23S08 SPI/GPIO gpio expander driver
   3 */
   4
   5#include <linux/kernel.h>
   6#include <linux/device.h>
   7#include <linux/mutex.h>
   8#include <linux/module.h>
   9#include <linux/gpio.h>
  10#include <linux/i2c.h>
  11#include <linux/spi/spi.h>
  12#include <linux/spi/mcp23s08.h>
  13#include <linux/slab.h>
  14#include <asm/byteorder.h>
  15#include <linux/of.h>
  16#include <linux/of_device.h>
  17
  18/**
  19 * MCP types supported by driver
  20 */
  21#define MCP_TYPE_S08    0
  22#define MCP_TYPE_S17    1
  23#define MCP_TYPE_008    2
  24#define MCP_TYPE_017    3
  25
  26/* Registers are all 8 bits wide.
  27 *
  28 * The mcp23s17 has twice as many bits, and can be configured to work
  29 * with either 16 bit registers or with two adjacent 8 bit banks.
  30 */
  31#define MCP_IODIR       0x00            /* init/reset:  all ones */
  32#define MCP_IPOL        0x01
  33#define MCP_GPINTEN     0x02
  34#define MCP_DEFVAL      0x03
  35#define MCP_INTCON      0x04
  36#define MCP_IOCON       0x05
  37#       define IOCON_SEQOP      (1 << 5)
  38#       define IOCON_HAEN       (1 << 3)
  39#       define IOCON_ODR        (1 << 2)
  40#       define IOCON_INTPOL     (1 << 1)
  41#define MCP_GPPU        0x06
  42#define MCP_INTF        0x07
  43#define MCP_INTCAP      0x08
  44#define MCP_GPIO        0x09
  45#define MCP_OLAT        0x0a
  46
  47struct mcp23s08;
  48
  49struct mcp23s08_ops {
  50        int     (*read)(struct mcp23s08 *mcp, unsigned reg);
  51        int     (*write)(struct mcp23s08 *mcp, unsigned reg, unsigned val);
  52        int     (*read_regs)(struct mcp23s08 *mcp, unsigned reg,
  53                             u16 *vals, unsigned n);
  54};
  55
  56struct mcp23s08 {
  57        u8                      addr;
  58
  59        u16                     cache[11];
  60        /* lock protects the cached values */
  61        struct mutex            lock;
  62
  63        struct gpio_chip        chip;
  64
  65        const struct mcp23s08_ops       *ops;
  66        void                    *data; /* ops specific data */
  67};
  68
  69/* A given spi_device can represent up to eight mcp23sxx chips
  70 * sharing the same chipselect but using different addresses
  71 * (e.g. chips #0 and #3 might be populated, but not #1 or $2).
  72 * Driver data holds all the per-chip data.
  73 */
  74struct mcp23s08_driver_data {
  75        unsigned                ngpio;
  76        struct mcp23s08         *mcp[8];
  77        struct mcp23s08         chip[];
  78};
  79
  80/*----------------------------------------------------------------------*/
  81
  82#if IS_ENABLED(CONFIG_I2C)
  83
  84static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg)
  85{
  86        return i2c_smbus_read_byte_data(mcp->data, reg);
  87}
  88
  89static int mcp23008_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
  90{
  91        return i2c_smbus_write_byte_data(mcp->data, reg, val);
  92}
  93
  94static int
  95mcp23008_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
  96{
  97        while (n--) {
  98                int ret = mcp23008_read(mcp, reg++);
  99                if (ret < 0)
 100                        return ret;
 101                *vals++ = ret;
 102        }
 103
 104        return 0;
 105}
 106
 107static int mcp23017_read(struct mcp23s08 *mcp, unsigned reg)
 108{
 109        return i2c_smbus_read_word_data(mcp->data, reg << 1);
 110}
 111
 112static int mcp23017_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
 113{
 114        return i2c_smbus_write_word_data(mcp->data, reg << 1, val);
 115}
 116
 117static int
 118mcp23017_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
 119{
 120        while (n--) {
 121                int ret = mcp23017_read(mcp, reg++);
 122                if (ret < 0)
 123                        return ret;
 124                *vals++ = ret;
 125        }
 126
 127        return 0;
 128}
 129
 130static const struct mcp23s08_ops mcp23008_ops = {
 131        .read           = mcp23008_read,
 132        .write          = mcp23008_write,
 133        .read_regs      = mcp23008_read_regs,
 134};
 135
 136static const struct mcp23s08_ops mcp23017_ops = {
 137        .read           = mcp23017_read,
 138        .write          = mcp23017_write,
 139        .read_regs      = mcp23017_read_regs,
 140};
 141
 142#endif /* CONFIG_I2C */
 143
 144/*----------------------------------------------------------------------*/
 145
 146#ifdef CONFIG_SPI_MASTER
 147
 148static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
 149{
 150        u8      tx[2], rx[1];
 151        int     status;
 152
 153        tx[0] = mcp->addr | 0x01;
 154        tx[1] = reg;
 155        status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx);
 156        return (status < 0) ? status : rx[0];
 157}
 158
 159static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
 160{
 161        u8      tx[3];
 162
 163        tx[0] = mcp->addr;
 164        tx[1] = reg;
 165        tx[2] = val;
 166        return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0);
 167}
 168
 169static int
 170mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
 171{
 172        u8      tx[2], *tmp;
 173        int     status;
 174
 175        if ((n + reg) > sizeof mcp->cache)
 176                return -EINVAL;
 177        tx[0] = mcp->addr | 0x01;
 178        tx[1] = reg;
 179
 180        tmp = (u8 *)vals;
 181        status = spi_write_then_read(mcp->data, tx, sizeof tx, tmp, n);
 182        if (status >= 0) {
 183                while (n--)
 184                        vals[n] = tmp[n]; /* expand to 16bit */
 185        }
 186        return status;
 187}
 188
 189static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg)
 190{
 191        u8      tx[2], rx[2];
 192        int     status;
 193
 194        tx[0] = mcp->addr | 0x01;
 195        tx[1] = reg << 1;
 196        status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx);
 197        return (status < 0) ? status : (rx[0] | (rx[1] << 8));
 198}
 199
 200static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
 201{
 202        u8      tx[4];
 203
 204        tx[0] = mcp->addr;
 205        tx[1] = reg << 1;
 206        tx[2] = val;
 207        tx[3] = val >> 8;
 208        return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0);
 209}
 210
 211static int
 212mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
 213{
 214        u8      tx[2];
 215        int     status;
 216
 217        if ((n + reg) > sizeof mcp->cache)
 218                return -EINVAL;
 219        tx[0] = mcp->addr | 0x01;
 220        tx[1] = reg << 1;
 221
 222        status = spi_write_then_read(mcp->data, tx, sizeof tx,
 223                                     (u8 *)vals, n * 2);
 224        if (status >= 0) {
 225                while (n--)
 226                        vals[n] = __le16_to_cpu((__le16)vals[n]);
 227        }
 228
 229        return status;
 230}
 231
 232static const struct mcp23s08_ops mcp23s08_ops = {
 233        .read           = mcp23s08_read,
 234        .write          = mcp23s08_write,
 235        .read_regs      = mcp23s08_read_regs,
 236};
 237
 238static const struct mcp23s08_ops mcp23s17_ops = {
 239        .read           = mcp23s17_read,
 240        .write          = mcp23s17_write,
 241        .read_regs      = mcp23s17_read_regs,
 242};
 243
 244#endif /* CONFIG_SPI_MASTER */
 245
 246/*----------------------------------------------------------------------*/
 247
 248static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset)
 249{
 250        struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
 251        int status;
 252
 253        mutex_lock(&mcp->lock);
 254        mcp->cache[MCP_IODIR] |= (1 << offset);
 255        status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
 256        mutex_unlock(&mcp->lock);
 257        return status;
 258}
 259
 260static int mcp23s08_get(struct gpio_chip *chip, unsigned offset)
 261{
 262        struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
 263        int status;
 264
 265        mutex_lock(&mcp->lock);
 266
 267        /* REVISIT reading this clears any IRQ ... */
 268        status = mcp->ops->read(mcp, MCP_GPIO);
 269        if (status < 0)
 270                status = 0;
 271        else {
 272                mcp->cache[MCP_GPIO] = status;
 273                status = !!(status & (1 << offset));
 274        }
 275        mutex_unlock(&mcp->lock);
 276        return status;
 277}
 278
 279static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value)
 280{
 281        unsigned olat = mcp->cache[MCP_OLAT];
 282
 283        if (value)
 284                olat |= mask;
 285        else
 286                olat &= ~mask;
 287        mcp->cache[MCP_OLAT] = olat;
 288        return mcp->ops->write(mcp, MCP_OLAT, olat);
 289}
 290
 291static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value)
 292{
 293        struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
 294        unsigned mask = 1 << offset;
 295
 296        mutex_lock(&mcp->lock);
 297        __mcp23s08_set(mcp, mask, value);
 298        mutex_unlock(&mcp->lock);
 299}
 300
 301static int
 302mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
 303{
 304        struct mcp23s08 *mcp = container_of(chip, struct mcp23s08, chip);
 305        unsigned mask = 1 << offset;
 306        int status;
 307
 308        mutex_lock(&mcp->lock);
 309        status = __mcp23s08_set(mcp, mask, value);
 310        if (status == 0) {
 311                mcp->cache[MCP_IODIR] &= ~mask;
 312                status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
 313        }
 314        mutex_unlock(&mcp->lock);
 315        return status;
 316}
 317
 318/*----------------------------------------------------------------------*/
 319
 320#ifdef CONFIG_DEBUG_FS
 321
 322#include <linux/seq_file.h>
 323
 324/*
 325 * This shows more info than the generic gpio dump code:
 326 * pullups, deglitching, open drain drive.
 327 */
 328static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 329{
 330        struct mcp23s08 *mcp;
 331        char            bank;
 332        int             t;
 333        unsigned        mask;
 334
 335        mcp = container_of(chip, struct mcp23s08, chip);
 336
 337        /* NOTE: we only handle one bank for now ... */
 338        bank = '0' + ((mcp->addr >> 1) & 0x7);
 339
 340        mutex_lock(&mcp->lock);
 341        t = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
 342        if (t < 0) {
 343                seq_printf(s, " I/O ERROR %d\n", t);
 344                goto done;
 345        }
 346
 347        for (t = 0, mask = 1; t < chip->ngpio; t++, mask <<= 1) {
 348                const char      *label;
 349
 350                label = gpiochip_is_requested(chip, t);
 351                if (!label)
 352                        continue;
 353
 354                seq_printf(s, " gpio-%-3d P%c.%d (%-12s) %s %s %s",
 355                        chip->base + t, bank, t, label,
 356                        (mcp->cache[MCP_IODIR] & mask) ? "in " : "out",
 357                        (mcp->cache[MCP_GPIO] & mask) ? "hi" : "lo",
 358                        (mcp->cache[MCP_GPPU] & mask) ? "up" : "  ");
 359                /* NOTE:  ignoring the irq-related registers */
 360                seq_printf(s, "\n");
 361        }
 362done:
 363        mutex_unlock(&mcp->lock);
 364}
 365
 366#else
 367#define mcp23s08_dbg_show       NULL
 368#endif
 369
 370/*----------------------------------------------------------------------*/
 371
 372static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
 373                              void *data, unsigned addr,
 374                              unsigned type, unsigned base, unsigned pullups)
 375{
 376        int status;
 377
 378        mutex_init(&mcp->lock);
 379
 380        mcp->data = data;
 381        mcp->addr = addr;
 382
 383        mcp->chip.direction_input = mcp23s08_direction_input;
 384        mcp->chip.get = mcp23s08_get;
 385        mcp->chip.direction_output = mcp23s08_direction_output;
 386        mcp->chip.set = mcp23s08_set;
 387        mcp->chip.dbg_show = mcp23s08_dbg_show;
 388#ifdef CONFIG_OF
 389        mcp->chip.of_gpio_n_cells = 2;
 390        mcp->chip.of_node = dev->of_node;
 391#endif
 392
 393        switch (type) {
 394#ifdef CONFIG_SPI_MASTER
 395        case MCP_TYPE_S08:
 396                mcp->ops = &mcp23s08_ops;
 397                mcp->chip.ngpio = 8;
 398                mcp->chip.label = "mcp23s08";
 399                break;
 400
 401        case MCP_TYPE_S17:
 402                mcp->ops = &mcp23s17_ops;
 403                mcp->chip.ngpio = 16;
 404                mcp->chip.label = "mcp23s17";
 405                break;
 406#endif /* CONFIG_SPI_MASTER */
 407
 408#if IS_ENABLED(CONFIG_I2C)
 409        case MCP_TYPE_008:
 410                mcp->ops = &mcp23008_ops;
 411                mcp->chip.ngpio = 8;
 412                mcp->chip.label = "mcp23008";
 413                break;
 414
 415        case MCP_TYPE_017:
 416                mcp->ops = &mcp23017_ops;
 417                mcp->chip.ngpio = 16;
 418                mcp->chip.label = "mcp23017";
 419                break;
 420#endif /* CONFIG_I2C */
 421
 422        default:
 423                dev_err(dev, "invalid device type (%d)\n", type);
 424                return -EINVAL;
 425        }
 426
 427        mcp->chip.base = base;
 428        mcp->chip.can_sleep = 1;
 429        mcp->chip.dev = dev;
 430        mcp->chip.owner = THIS_MODULE;
 431
 432        /* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
 433         * and MCP_IOCON.HAEN = 1, so we work with all chips.
 434         */
 435        status = mcp->ops->read(mcp, MCP_IOCON);
 436        if (status < 0)
 437                goto fail;
 438        if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) {
 439                /* mcp23s17 has IOCON twice, make sure they are in sync */
 440                status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
 441                status |= IOCON_HAEN | (IOCON_HAEN << 8);
 442                status = mcp->ops->write(mcp, MCP_IOCON, status);
 443                if (status < 0)
 444                        goto fail;
 445        }
 446
 447        /* configure ~100K pullups */
 448        status = mcp->ops->write(mcp, MCP_GPPU, pullups);
 449        if (status < 0)
 450                goto fail;
 451
 452        status = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
 453        if (status < 0)
 454                goto fail;
 455
 456        /* disable inverter on input */
 457        if (mcp->cache[MCP_IPOL] != 0) {
 458                mcp->cache[MCP_IPOL] = 0;
 459                status = mcp->ops->write(mcp, MCP_IPOL, 0);
 460                if (status < 0)
 461                        goto fail;
 462        }
 463
 464        /* disable irqs */
 465        if (mcp->cache[MCP_GPINTEN] != 0) {
 466                mcp->cache[MCP_GPINTEN] = 0;
 467                status = mcp->ops->write(mcp, MCP_GPINTEN, 0);
 468                if (status < 0)
 469                        goto fail;
 470        }
 471
 472        status = gpiochip_add(&mcp->chip);
 473fail:
 474        if (status < 0)
 475                dev_dbg(dev, "can't setup chip %d, --> %d\n",
 476                        addr, status);
 477        return status;
 478}
 479
 480/*----------------------------------------------------------------------*/
 481
 482#ifdef CONFIG_OF
 483#ifdef CONFIG_SPI_MASTER
 484static struct of_device_id mcp23s08_spi_of_match[] = {
 485        {
 486                .compatible = "microchip,mcp23s08",
 487                .data = (void *) MCP_TYPE_S08,
 488        },
 489        {
 490                .compatible = "microchip,mcp23s17",
 491                .data = (void *) MCP_TYPE_S17,
 492        },
 493/* NOTE: The use of the mcp prefix is deprecated and will be removed. */
 494        {
 495                .compatible = "mcp,mcp23s08",
 496                .data = (void *) MCP_TYPE_S08,
 497        },
 498        {
 499                .compatible = "mcp,mcp23s17",
 500                .data = (void *) MCP_TYPE_S17,
 501        },
 502        { },
 503};
 504MODULE_DEVICE_TABLE(of, mcp23s08_spi_of_match);
 505#endif
 506
 507#if IS_ENABLED(CONFIG_I2C)
 508static struct of_device_id mcp23s08_i2c_of_match[] = {
 509        {
 510                .compatible = "microchip,mcp23008",
 511                .data = (void *) MCP_TYPE_008,
 512        },
 513        {
 514                .compatible = "microchip,mcp23017",
 515                .data = (void *) MCP_TYPE_017,
 516        },
 517/* NOTE: The use of the mcp prefix is deprecated and will be removed. */
 518        {
 519                .compatible = "mcp,mcp23008",
 520                .data = (void *) MCP_TYPE_008,
 521        },
 522        {
 523                .compatible = "mcp,mcp23017",
 524                .data = (void *) MCP_TYPE_017,
 525        },
 526        { },
 527};
 528MODULE_DEVICE_TABLE(of, mcp23s08_i2c_of_match);
 529#endif
 530#endif /* CONFIG_OF */
 531
 532
 533#if IS_ENABLED(CONFIG_I2C)
 534
 535static int mcp230xx_probe(struct i2c_client *client,
 536                                    const struct i2c_device_id *id)
 537{
 538        struct mcp23s08_platform_data *pdata;
 539        struct mcp23s08 *mcp;
 540        int status, base, pullups;
 541        const struct of_device_id *match;
 542
 543        match = of_match_device(of_match_ptr(mcp23s08_i2c_of_match),
 544                                        &client->dev);
 545        pdata = dev_get_platdata(&client->dev);
 546        if (match || !pdata) {
 547                base = -1;
 548                pullups = 0;
 549        } else {
 550                if (!gpio_is_valid(pdata->base)) {
 551                        dev_dbg(&client->dev, "invalid platform data\n");
 552                        return -EINVAL;
 553                }
 554                base = pdata->base;
 555                pullups = pdata->chip[0].pullups;
 556        }
 557
 558        mcp = kzalloc(sizeof *mcp, GFP_KERNEL);
 559        if (!mcp)
 560                return -ENOMEM;
 561
 562        status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr,
 563                                    id->driver_data, base, pullups);
 564        if (status)
 565                goto fail;
 566
 567        i2c_set_clientdata(client, mcp);
 568
 569        return 0;
 570
 571fail:
 572        kfree(mcp);
 573
 574        return status;
 575}
 576
 577static int mcp230xx_remove(struct i2c_client *client)
 578{
 579        struct mcp23s08 *mcp = i2c_get_clientdata(client);
 580        int status;
 581
 582        status = gpiochip_remove(&mcp->chip);
 583        if (status == 0)
 584                kfree(mcp);
 585
 586        return status;
 587}
 588
 589static const struct i2c_device_id mcp230xx_id[] = {
 590        { "mcp23008", MCP_TYPE_008 },
 591        { "mcp23017", MCP_TYPE_017 },
 592        { },
 593};
 594MODULE_DEVICE_TABLE(i2c, mcp230xx_id);
 595
 596static struct i2c_driver mcp230xx_driver = {
 597        .driver = {
 598                .name   = "mcp230xx",
 599                .owner  = THIS_MODULE,
 600                .of_match_table = of_match_ptr(mcp23s08_i2c_of_match),
 601        },
 602        .probe          = mcp230xx_probe,
 603        .remove         = mcp230xx_remove,
 604        .id_table       = mcp230xx_id,
 605};
 606
 607static int __init mcp23s08_i2c_init(void)
 608{
 609        return i2c_add_driver(&mcp230xx_driver);
 610}
 611
 612static void mcp23s08_i2c_exit(void)
 613{
 614        i2c_del_driver(&mcp230xx_driver);
 615}
 616
 617#else
 618
 619static int __init mcp23s08_i2c_init(void) { return 0; }
 620static void mcp23s08_i2c_exit(void) { }
 621
 622#endif /* CONFIG_I2C */
 623
 624/*----------------------------------------------------------------------*/
 625
 626#ifdef CONFIG_SPI_MASTER
 627
 628static int mcp23s08_probe(struct spi_device *spi)
 629{
 630        struct mcp23s08_platform_data   *pdata;
 631        unsigned                        addr;
 632        unsigned                        chips = 0;
 633        struct mcp23s08_driver_data     *data;
 634        int                             status, type;
 635        unsigned                        base = -1,
 636                                        ngpio = 0,
 637                                        pullups[ARRAY_SIZE(pdata->chip)];
 638        const struct                    of_device_id *match;
 639        u32                             spi_present_mask = 0;
 640
 641        match = of_match_device(of_match_ptr(mcp23s08_spi_of_match), &spi->dev);
 642        if (match) {
 643                type = (int)match->data;
 644                status = of_property_read_u32(spi->dev.of_node,
 645                            "microchip,spi-present-mask", &spi_present_mask);
 646                if (status) {
 647                        status = of_property_read_u32(spi->dev.of_node,
 648                                    "mcp,spi-present-mask", &spi_present_mask);
 649                        if (status) {
 650                                dev_err(&spi->dev,
 651                                        "DT has no spi-present-mask\n");
 652                                return -ENODEV;
 653                        }
 654                }
 655                if ((spi_present_mask <= 0) || (spi_present_mask >= 256)) {
 656                        dev_err(&spi->dev, "invalid spi-present-mask\n");
 657                        return -ENODEV;
 658                }
 659
 660                for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++)
 661                        pullups[addr] = 0;
 662        } else {
 663                type = spi_get_device_id(spi)->driver_data;
 664                pdata = dev_get_platdata(&spi->dev);
 665                if (!pdata || !gpio_is_valid(pdata->base)) {
 666                        dev_dbg(&spi->dev,
 667                                        "invalid or missing platform data\n");
 668                        return -EINVAL;
 669                }
 670
 671                for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
 672                        if (!pdata->chip[addr].is_present)
 673                                continue;
 674                        chips++;
 675                        if ((type == MCP_TYPE_S08) && (addr > 3)) {
 676                                dev_err(&spi->dev,
 677                                        "mcp23s08 only supports address 0..3\n");
 678                                return -EINVAL;
 679                        }
 680                        spi_present_mask |= 1 << addr;
 681                        pullups[addr] = pdata->chip[addr].pullups;
 682                }
 683
 684                if (!chips)
 685                        return -ENODEV;
 686
 687                base = pdata->base;
 688        }
 689
 690        data = kzalloc(sizeof *data + chips * sizeof(struct mcp23s08),
 691                        GFP_KERNEL);
 692        if (!data)
 693                return -ENOMEM;
 694        spi_set_drvdata(spi, data);
 695
 696        for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
 697                if (!(spi_present_mask & (1 << addr)))
 698                        continue;
 699                chips--;
 700                data->mcp[addr] = &data->chip[chips];
 701                status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi,
 702                                            0x40 | (addr << 1), type, base,
 703                                            pullups[addr]);
 704                if (status < 0)
 705                        goto fail;
 706
 707                if (base != -1)
 708                        base += (type == MCP_TYPE_S17) ? 16 : 8;
 709                ngpio += (type == MCP_TYPE_S17) ? 16 : 8;
 710        }
 711        data->ngpio = ngpio;
 712
 713        /* NOTE:  these chips have a relatively sane IRQ framework, with
 714         * per-signal masking and level/edge triggering.  It's not yet
 715         * handled here...
 716         */
 717
 718        return 0;
 719
 720fail:
 721        for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
 722                int tmp;
 723
 724                if (!data->mcp[addr])
 725                        continue;
 726                tmp = gpiochip_remove(&data->mcp[addr]->chip);
 727                if (tmp < 0)
 728                        dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
 729        }
 730        kfree(data);
 731        return status;
 732}
 733
 734static int mcp23s08_remove(struct spi_device *spi)
 735{
 736        struct mcp23s08_driver_data     *data = spi_get_drvdata(spi);
 737        unsigned                        addr;
 738        int                             status = 0;
 739
 740        for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
 741                int tmp;
 742
 743                if (!data->mcp[addr])
 744                        continue;
 745
 746                tmp = gpiochip_remove(&data->mcp[addr]->chip);
 747                if (tmp < 0) {
 748                        dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
 749                        status = tmp;
 750                }
 751        }
 752        if (status == 0)
 753                kfree(data);
 754        return status;
 755}
 756
 757static const struct spi_device_id mcp23s08_ids[] = {
 758        { "mcp23s08", MCP_TYPE_S08 },
 759        { "mcp23s17", MCP_TYPE_S17 },
 760        { },
 761};
 762MODULE_DEVICE_TABLE(spi, mcp23s08_ids);
 763
 764static struct spi_driver mcp23s08_driver = {
 765        .probe          = mcp23s08_probe,
 766        .remove         = mcp23s08_remove,
 767        .id_table       = mcp23s08_ids,
 768        .driver = {
 769                .name   = "mcp23s08",
 770                .owner  = THIS_MODULE,
 771                .of_match_table = of_match_ptr(mcp23s08_spi_of_match),
 772        },
 773};
 774
 775static int __init mcp23s08_spi_init(void)
 776{
 777        return spi_register_driver(&mcp23s08_driver);
 778}
 779
 780static void mcp23s08_spi_exit(void)
 781{
 782        spi_unregister_driver(&mcp23s08_driver);
 783}
 784
 785#else
 786
 787static int __init mcp23s08_spi_init(void) { return 0; }
 788static void mcp23s08_spi_exit(void) { }
 789
 790#endif /* CONFIG_SPI_MASTER */
 791
 792/*----------------------------------------------------------------------*/
 793
 794static int __init mcp23s08_init(void)
 795{
 796        int ret;
 797
 798        ret = mcp23s08_spi_init();
 799        if (ret)
 800                goto spi_fail;
 801
 802        ret = mcp23s08_i2c_init();
 803        if (ret)
 804                goto i2c_fail;
 805
 806        return 0;
 807
 808 i2c_fail:
 809        mcp23s08_spi_exit();
 810 spi_fail:
 811        return ret;
 812}
 813/* register after spi/i2c postcore initcall and before
 814 * subsys initcalls that may rely on these GPIOs
 815 */
 816subsys_initcall(mcp23s08_init);
 817
 818static void __exit mcp23s08_exit(void)
 819{
 820        mcp23s08_spi_exit();
 821        mcp23s08_i2c_exit();
 822}
 823module_exit(mcp23s08_exit);
 824
 825MODULE_LICENSE("GPL");
 826
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.