gpio-mcp23s08.c 18.1 KB
Newer Older
1
/*
P
Peter Korsgaard 已提交
2
 * MCP23S08 SPI/GPIO gpio expander driver
3 4 5 6 7
 */

#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/mutex.h>
8
#include <linux/module.h>
9
#include <linux/gpio.h>
P
Peter Korsgaard 已提交
10
#include <linux/i2c.h>
11 12
#include <linux/spi/spi.h>
#include <linux/spi/mcp23s08.h>
13
#include <linux/slab.h>
14
#include <asm/byteorder.h>
15 16
#include <linux/of.h>
#include <linux/of_device.h>
17

18 19 20 21 22
/**
 * MCP types supported by driver
 */
#define MCP_TYPE_S08	0
#define MCP_TYPE_S17	1
P
Peter Korsgaard 已提交
23 24
#define MCP_TYPE_008	2
#define MCP_TYPE_017	3
25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46

/* Registers are all 8 bits wide.
 *
 * The mcp23s17 has twice as many bits, and can be configured to work
 * with either 16 bit registers or with two adjacent 8 bit banks.
 */
#define MCP_IODIR	0x00		/* init/reset:  all ones */
#define MCP_IPOL	0x01
#define MCP_GPINTEN	0x02
#define MCP_DEFVAL	0x03
#define MCP_INTCON	0x04
#define MCP_IOCON	0x05
#	define IOCON_SEQOP	(1 << 5)
#	define IOCON_HAEN	(1 << 3)
#	define IOCON_ODR	(1 << 2)
#	define IOCON_INTPOL	(1 << 1)
#define MCP_GPPU	0x06
#define MCP_INTF	0x07
#define MCP_INTCAP	0x08
#define MCP_GPIO	0x09
#define MCP_OLAT	0x0a

47 48 49 50 51 52 53 54 55
struct mcp23s08;

struct mcp23s08_ops {
	int	(*read)(struct mcp23s08 *mcp, unsigned reg);
	int	(*write)(struct mcp23s08 *mcp, unsigned reg, unsigned val);
	int	(*read_regs)(struct mcp23s08 *mcp, unsigned reg,
			     u16 *vals, unsigned n);
};

56 57 58
struct mcp23s08 {
	u8			addr;

59
	u16			cache[11];
60 61 62 63 64
	/* lock protects the cached values */
	struct mutex		lock;

	struct gpio_chip	chip;

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 71 72 73 74 75
 * 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;
76
	struct mcp23s08		*mcp[8];
77 78 79
	struct mcp23s08		chip[];
};

P
Peter Korsgaard 已提交
80 81
/*----------------------------------------------------------------------*/

82
#if IS_ENABLED(CONFIG_I2C)
P
Peter Korsgaard 已提交
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145

static int mcp23008_read(struct mcp23s08 *mcp, unsigned reg)
{
	return i2c_smbus_read_byte_data(mcp->data, reg);
}

static int mcp23008_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
{
	return i2c_smbus_write_byte_data(mcp->data, reg, val);
}

static int
mcp23008_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
{
	while (n--) {
		int ret = mcp23008_read(mcp, reg++);
		if (ret < 0)
			return ret;
		*vals++ = ret;
	}

	return 0;
}

static int mcp23017_read(struct mcp23s08 *mcp, unsigned reg)
{
	return i2c_smbus_read_word_data(mcp->data, reg << 1);
}

static int mcp23017_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
{
	return i2c_smbus_write_word_data(mcp->data, reg << 1, val);
}

static int
mcp23017_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
{
	while (n--) {
		int ret = mcp23017_read(mcp, reg++);
		if (ret < 0)
			return ret;
		*vals++ = ret;
	}

	return 0;
}

static const struct mcp23s08_ops mcp23008_ops = {
	.read		= mcp23008_read,
	.write		= mcp23008_write,
	.read_regs	= mcp23008_read_regs,
};

static const struct mcp23s08_ops mcp23017_ops = {
	.read		= mcp23017_read,
	.write		= mcp23017_write,
	.read_regs	= mcp23017_read_regs,
};

#endif /* CONFIG_I2C */

/*----------------------------------------------------------------------*/

146 147
#ifdef CONFIG_SPI_MASTER

148 149 150 151 152 153 154
static int mcp23s08_read(struct mcp23s08 *mcp, unsigned reg)
{
	u8	tx[2], rx[1];
	int	status;

	tx[0] = mcp->addr | 0x01;
	tx[1] = reg;
155
	status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx);
156 157 158
	return (status < 0) ? status : rx[0];
}

159
static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
160 161 162 163 164 165
{
	u8	tx[3];

	tx[0] = mcp->addr;
	tx[1] = reg;
	tx[2] = val;
166
	return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0);
167 168 169
}

static int
170
mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
171
{
172 173
	u8	tx[2], *tmp;
	int	status;
174 175 176 177 178

	if ((n + reg) > sizeof mcp->cache)
		return -EINVAL;
	tx[0] = mcp->addr | 0x01;
	tx[1] = reg;
179 180

	tmp = (u8 *)vals;
181
	status = spi_write_then_read(mcp->data, tx, sizeof tx, tmp, n);
182 183 184 185 186 187 188 189 190 191 192 193 194 195
	if (status >= 0) {
		while (n--)
			vals[n] = tmp[n]; /* expand to 16bit */
	}
	return status;
}

static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg)
{
	u8	tx[2], rx[2];
	int	status;

	tx[0] = mcp->addr | 0x01;
	tx[1] = reg << 1;
196
	status = spi_write_then_read(mcp->data, tx, sizeof tx, rx, sizeof rx);
197 198 199 200 201 202 203 204 205 206 207
	return (status < 0) ? status : (rx[0] | (rx[1] << 8));
}

static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
{
	u8	tx[4];

	tx[0] = mcp->addr;
	tx[1] = reg << 1;
	tx[2] = val;
	tx[3] = val >> 8;
208
	return spi_write_then_read(mcp->data, tx, sizeof tx, NULL, 0);
209 210 211 212 213 214 215 216 217 218 219 220 221
}

static int
mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
{
	u8	tx[2];
	int	status;

	if ((n + reg) > sizeof mcp->cache)
		return -EINVAL;
	tx[0] = mcp->addr | 0x01;
	tx[1] = reg << 1;

222
	status = spi_write_then_read(mcp->data, tx, sizeof tx,
223 224 225 226 227 228 229
				     (u8 *)vals, n * 2);
	if (status >= 0) {
		while (n--)
			vals[n] = __le16_to_cpu((__le16)vals[n]);
	}

	return status;
230 231
}

232 233 234 235 236 237 238 239 240 241 242 243
static const struct mcp23s08_ops mcp23s08_ops = {
	.read		= mcp23s08_read,
	.write		= mcp23s08_write,
	.read_regs	= mcp23s08_read_regs,
};

static const struct mcp23s08_ops mcp23s17_ops = {
	.read		= mcp23s17_read,
	.write		= mcp23s17_write,
	.read_regs	= mcp23s17_read_regs,
};

244
#endif /* CONFIG_SPI_MASTER */
245

246 247 248 249 250 251 252 253 254
/*----------------------------------------------------------------------*/

static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset)
{
	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
	int status;

	mutex_lock(&mcp->lock);
	mcp->cache[MCP_IODIR] |= (1 << offset);
255
	status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
256 257 258 259 260 261 262 263 264 265 266 267
	mutex_unlock(&mcp->lock);
	return status;
}

static int mcp23s08_get(struct gpio_chip *chip, unsigned offset)
{
	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
	int status;

	mutex_lock(&mcp->lock);

	/* REVISIT reading this clears any IRQ ... */
268
	status = mcp->ops->read(mcp, MCP_GPIO);
269 270 271 272 273 274 275 276 277 278 279 280
	if (status < 0)
		status = 0;
	else {
		mcp->cache[MCP_GPIO] = status;
		status = !!(status & (1 << offset));
	}
	mutex_unlock(&mcp->lock);
	return status;
}

static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value)
{
281
	unsigned olat = mcp->cache[MCP_OLAT];
282 283 284 285 286 287

	if (value)
		olat |= mask;
	else
		olat &= ~mask;
	mcp->cache[MCP_OLAT] = olat;
288
	return mcp->ops->write(mcp, MCP_OLAT, olat);
289 290 291 292 293
}

static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value)
{
	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
294
	unsigned mask = 1 << offset;
295 296 297 298 299 300 301 302 303 304

	mutex_lock(&mcp->lock);
	__mcp23s08_set(mcp, mask, value);
	mutex_unlock(&mcp->lock);
}

static int
mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
{
	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
305
	unsigned mask = 1 << offset;
306 307 308 309 310 311
	int status;

	mutex_lock(&mcp->lock);
	status = __mcp23s08_set(mcp, mask, value);
	if (status == 0) {
		mcp->cache[MCP_IODIR] &= ~mask;
312
		status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331
	}
	mutex_unlock(&mcp->lock);
	return status;
}

/*----------------------------------------------------------------------*/

#ifdef CONFIG_DEBUG_FS

#include <linux/seq_file.h>

/*
 * This shows more info than the generic gpio dump code:
 * pullups, deglitching, open drain drive.
 */
static void mcp23s08_dbg_show(struct seq_file *s, struct gpio_chip *chip)
{
	struct mcp23s08	*mcp;
	char		bank;
R
Roel Kluin 已提交
332
	int		t;
333 334 335 336 337
	unsigned	mask;

	mcp = container_of(chip, struct mcp23s08, chip);

	/* 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 343 344 345 346
	if (t < 0) {
		seq_printf(s, " I/O ERROR %d\n", t);
		goto done;
	}

347
	for (t = 0, mask = 1; t < chip->ngpio; t++, mask <<= 1) {
348 349 350 351 352 353 354 355 356 357
		const char	*label;

		label = gpiochip_is_requested(chip, t);
		if (!label)
			continue;

		seq_printf(s, " gpio-%-3d P%c.%d (%-12s) %s %s %s",
			chip->base + t, bank, t, label,
			(mcp->cache[MCP_IODIR] & mask) ? "in " : "out",
			(mcp->cache[MCP_GPIO] & mask) ? "hi" : "lo",
358
			(mcp->cache[MCP_GPPU] & mask) ? "up" : "  ");
359 360 361 362 363 364 365 366 367 368 369 370 371
		/* NOTE:  ignoring the irq-related registers */
		seq_printf(s, "\n");
	}
done:
	mutex_unlock(&mcp->lock);
}

#else
#define mcp23s08_dbg_show	NULL
#endif

/*----------------------------------------------------------------------*/

372 373
static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
			      void *data, unsigned addr,
374
			      unsigned type, unsigned base, unsigned pullups)
375
{
376
	int status;
377 378 379

	mutex_init(&mcp->lock);

380 381
	mcp->data = data;
	mcp->addr = addr;
382 383 384 385 386 387

	mcp->chip.direction_input = mcp23s08_direction_input;
	mcp->chip.get = mcp23s08_get;
	mcp->chip.direction_output = mcp23s08_direction_output;
	mcp->chip.set = mcp23s08_set;
	mcp->chip.dbg_show = mcp23s08_dbg_show;
388 389 390 391
#ifdef CONFIG_OF
	mcp->chip.of_gpio_n_cells = 2;
	mcp->chip.of_node = dev->of_node;
#endif
392

393 394 395
	switch (type) {
#ifdef CONFIG_SPI_MASTER
	case MCP_TYPE_S08:
396 397 398
		mcp->ops = &mcp23s08_ops;
		mcp->chip.ngpio = 8;
		mcp->chip.label = "mcp23s08";
399 400 401 402 403 404 405 406 407
		break;

	case MCP_TYPE_S17:
		mcp->ops = &mcp23s17_ops;
		mcp->chip.ngpio = 16;
		mcp->chip.label = "mcp23s17";
		break;
#endif /* CONFIG_SPI_MASTER */

408
#if IS_ENABLED(CONFIG_I2C)
P
Peter Korsgaard 已提交
409 410 411 412 413 414 415 416 417 418 419 420 421
	case MCP_TYPE_008:
		mcp->ops = &mcp23008_ops;
		mcp->chip.ngpio = 8;
		mcp->chip.label = "mcp23008";
		break;

	case MCP_TYPE_017:
		mcp->ops = &mcp23017_ops;
		mcp->chip.ngpio = 16;
		mcp->chip.label = "mcp23017";
		break;
#endif /* CONFIG_I2C */

422 423 424
	default:
		dev_err(dev, "invalid device type (%d)\n", type);
		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 433 434
	/* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
	 * and MCP_IOCON.HAEN = 1, so we work with all chips.
	 */
435
	status = mcp->ops->read(mcp, MCP_IOCON);
436 437
	if (status < 0)
		goto fail;
438
	if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) {
439 440 441 442
		/* mcp23s17 has IOCON twice, make sure they are in sync */
		status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
		status |= IOCON_HAEN | (IOCON_HAEN << 8);
		status = mcp->ops->write(mcp, MCP_IOCON, status);
443 444 445 446 447
		if (status < 0)
			goto fail;
	}

	/* configure ~100K pullups */
448
	status = mcp->ops->write(mcp, MCP_GPPU, pullups);
449 450 451
	if (status < 0)
		goto fail;

452
	status = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
453 454 455 456 457 458
	if (status < 0)
		goto fail;

	/* disable inverter on input */
	if (mcp->cache[MCP_IPOL] != 0) {
		mcp->cache[MCP_IPOL] = 0;
459 460 461
		status = mcp->ops->write(mcp, MCP_IPOL, 0);
		if (status < 0)
			goto fail;
462 463 464 465 466
	}

	/* disable irqs */
	if (mcp->cache[MCP_GPINTEN] != 0) {
		mcp->cache[MCP_GPINTEN] = 0;
467
		status = mcp->ops->write(mcp, MCP_GPINTEN, 0);
468 469
		if (status < 0)
			goto fail;
470 471 472
	}

	status = gpiochip_add(&mcp->chip);
473 474
fail:
	if (status < 0)
475 476
		dev_dbg(dev, "can't setup chip %d, --> %d\n",
			addr, status);
477 478 479
	return status;
}

P
Peter Korsgaard 已提交
480 481
/*----------------------------------------------------------------------*/

482 483 484 485
#ifdef CONFIG_OF
#ifdef CONFIG_SPI_MASTER
static struct of_device_id mcp23s08_spi_of_match[] = {
	{
486 487
		.compatible = "microchip,mcp23s08",
		.data = (void *) MCP_TYPE_S08,
488 489
	},
	{
490 491 492 493 494 495 496 497 498 499 500
		.compatible = "microchip,mcp23s17",
		.data = (void *) MCP_TYPE_S17,
	},
/* NOTE: The use of the mcp prefix is deprecated and will be removed. */
	{
		.compatible = "mcp,mcp23s08",
		.data = (void *) MCP_TYPE_S08,
	},
	{
		.compatible = "mcp,mcp23s17",
		.data = (void *) MCP_TYPE_S17,
501 502 503 504 505 506 507 508 509
	},
	{ },
};
MODULE_DEVICE_TABLE(of, mcp23s08_spi_of_match);
#endif

#if IS_ENABLED(CONFIG_I2C)
static struct of_device_id mcp23s08_i2c_of_match[] = {
	{
510 511
		.compatible = "microchip,mcp23008",
		.data = (void *) MCP_TYPE_008,
512 513
	},
	{
514 515 516 517 518 519 520 521 522 523 524
		.compatible = "microchip,mcp23017",
		.data = (void *) MCP_TYPE_017,
	},
/* NOTE: The use of the mcp prefix is deprecated and will be removed. */
	{
		.compatible = "mcp,mcp23008",
		.data = (void *) MCP_TYPE_008,
	},
	{
		.compatible = "mcp,mcp23017",
		.data = (void *) MCP_TYPE_017,
525 526 527 528 529 530 531 532
	},
	{ },
};
MODULE_DEVICE_TABLE(of, mcp23s08_i2c_of_match);
#endif
#endif /* CONFIG_OF */


533
#if IS_ENABLED(CONFIG_I2C)
P
Peter Korsgaard 已提交
534

B
Bill Pemberton 已提交
535
static int mcp230xx_probe(struct i2c_client *client,
P
Peter Korsgaard 已提交
536 537 538 539
				    const struct i2c_device_id *id)
{
	struct mcp23s08_platform_data *pdata;
	struct mcp23s08 *mcp;
540 541 542 543 544
	int status, base, pullups;
	const struct of_device_id *match;

	match = of_match_device(of_match_ptr(mcp23s08_i2c_of_match),
					&client->dev);
J
Jingoo Han 已提交
545
	pdata = dev_get_platdata(&client->dev);
546
	if (match || !pdata) {
547 548 549
		base = -1;
		pullups = 0;
	} else {
550 551
		if (!gpio_is_valid(pdata->base)) {
			dev_dbg(&client->dev, "invalid platform data\n");
552 553 554 555
			return -EINVAL;
		}
		base = pdata->base;
		pullups = pdata->chip[0].pullups;
P
Peter Korsgaard 已提交
556 557 558 559 560 561 562
	}

	mcp = kzalloc(sizeof *mcp, GFP_KERNEL);
	if (!mcp)
		return -ENOMEM;

	status = mcp23s08_probe_one(mcp, &client->dev, client, client->addr,
563
				    id->driver_data, base, pullups);
P
Peter Korsgaard 已提交
564 565 566 567 568 569 570 571 572 573 574 575 576
	if (status)
		goto fail;

	i2c_set_clientdata(client, mcp);

	return 0;

fail:
	kfree(mcp);

	return status;
}

B
Bill Pemberton 已提交
577
static int mcp230xx_remove(struct i2c_client *client)
P
Peter Korsgaard 已提交
578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599
{
	struct mcp23s08 *mcp = i2c_get_clientdata(client);
	int status;

	status = gpiochip_remove(&mcp->chip);
	if (status == 0)
		kfree(mcp);

	return status;
}

static const struct i2c_device_id mcp230xx_id[] = {
	{ "mcp23008", MCP_TYPE_008 },
	{ "mcp23017", MCP_TYPE_017 },
	{ },
};
MODULE_DEVICE_TABLE(i2c, mcp230xx_id);

static struct i2c_driver mcp230xx_driver = {
	.driver = {
		.name	= "mcp230xx",
		.owner	= THIS_MODULE,
600
		.of_match_table = of_match_ptr(mcp23s08_i2c_of_match),
P
Peter Korsgaard 已提交
601 602
	},
	.probe		= mcp230xx_probe,
B
Bill Pemberton 已提交
603
	.remove		= mcp230xx_remove,
P
Peter Korsgaard 已提交
604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625
	.id_table	= mcp230xx_id,
};

static int __init mcp23s08_i2c_init(void)
{
	return i2c_add_driver(&mcp230xx_driver);
}

static void mcp23s08_i2c_exit(void)
{
	i2c_del_driver(&mcp230xx_driver);
}

#else

static int __init mcp23s08_i2c_init(void) { return 0; }
static void mcp23s08_i2c_exit(void) { }

#endif /* CONFIG_I2C */

/*----------------------------------------------------------------------*/

626 627
#ifdef CONFIG_SPI_MASTER

628 629 630 631 632 633
static int mcp23s08_probe(struct spi_device *spi)
{
	struct mcp23s08_platform_data	*pdata;
	unsigned			addr;
	unsigned			chips = 0;
	struct mcp23s08_driver_data	*data;
634
	int				status, type;
635 636 637 638 639 640 641 642 643 644
	unsigned			base = -1,
					ngpio = 0,
					pullups[ARRAY_SIZE(pdata->chip)];
	const struct			of_device_id *match;
	u32				spi_present_mask = 0;

	match = of_match_device(of_match_ptr(mcp23s08_spi_of_match), &spi->dev);
	if (match) {
		type = (int)match->data;
		status = of_property_read_u32(spi->dev.of_node,
645
			    "microchip,spi-present-mask", &spi_present_mask);
646
		if (status) {
647 648 649 650 651 652 653
			status = of_property_read_u32(spi->dev.of_node,
				    "mcp,spi-present-mask", &spi_present_mask);
			if (status) {
				dev_err(&spi->dev,
					"DT has no spi-present-mask\n");
				return -ENODEV;
			}
654 655 656 657 658
		}
		if ((spi_present_mask <= 0) || (spi_present_mask >= 256)) {
			dev_err(&spi->dev, "invalid spi-present-mask\n");
			return -ENODEV;
		}
659

660 661 662 663
		for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++)
			pullups[addr] = 0;
	} else {
		type = spi_get_device_id(spi)->driver_data;
J
Jingoo Han 已提交
664
		pdata = dev_get_platdata(&spi->dev);
665 666 667
		if (!pdata || !gpio_is_valid(pdata->base)) {
			dev_dbg(&spi->dev,
					"invalid or missing platform data\n");
668 669
			return -EINVAL;
		}
670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687

		for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
			if (!pdata->chip[addr].is_present)
				continue;
			chips++;
			if ((type == MCP_TYPE_S08) && (addr > 3)) {
				dev_err(&spi->dev,
					"mcp23s08 only supports address 0..3\n");
				return -EINVAL;
			}
			spi_present_mask |= 1 << addr;
			pullups[addr] = pdata->chip[addr].pullups;
		}

		if (!chips)
			return -ENODEV;

		base = pdata->base;
688 689 690 691 692 693 694 695
	}

	data = kzalloc(sizeof *data + chips * sizeof(struct mcp23s08),
			GFP_KERNEL);
	if (!data)
		return -ENOMEM;
	spi_set_drvdata(spi, data);

696
	for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
697
		if (!(spi_present_mask & (1 << addr)))
698 699 700
			continue;
		chips--;
		data->mcp[addr] = &data->chip[chips];
701 702
		status = mcp23s08_probe_one(data->mcp[addr], &spi->dev, spi,
					    0x40 | (addr << 1), type, base,
703
					    pullups[addr]);
704 705
		if (status < 0)
			goto fail;
706

707 708 709
		if (base != -1)
			base += (type == MCP_TYPE_S17) ? 16 : 8;
		ngpio += (type == MCP_TYPE_S17) ? 16 : 8;
710
	}
711
	data->ngpio = ngpio;
712 713 714 715 716 717 718 719 720

	/* NOTE:  these chips have a relatively sane IRQ framework, with
	 * per-signal masking and level/edge triggering.  It's not yet
	 * handled here...
	 */

	return 0;

fail:
721
	for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
722 723 724 725 726 727 728 729 730
		int tmp;

		if (!data->mcp[addr])
			continue;
		tmp = gpiochip_remove(&data->mcp[addr]->chip);
		if (tmp < 0)
			dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
	}
	kfree(data);
731 732 733 734 735
	return status;
}

static int mcp23s08_remove(struct spi_device *spi)
{
736 737
	struct mcp23s08_driver_data	*data = spi_get_drvdata(spi);
	unsigned			addr;
738 739
	int				status = 0;

740
	for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
741 742 743 744 745 746 747 748 749 750 751
		int tmp;

		if (!data->mcp[addr])
			continue;

		tmp = gpiochip_remove(&data->mcp[addr]->chip);
		if (tmp < 0) {
			dev_err(&spi->dev, "%s --> %d\n", "remove", tmp);
			status = tmp;
		}
	}
752
	if (status == 0)
753
		kfree(data);
754 755 756
	return status;
}

757 758 759 760 761 762 763
static const struct spi_device_id mcp23s08_ids[] = {
	{ "mcp23s08", MCP_TYPE_S08 },
	{ "mcp23s17", MCP_TYPE_S17 },
	{ },
};
MODULE_DEVICE_TABLE(spi, mcp23s08_ids);

764 765 766
static struct spi_driver mcp23s08_driver = {
	.probe		= mcp23s08_probe,
	.remove		= mcp23s08_remove,
767
	.id_table	= mcp23s08_ids,
768 769 770
	.driver = {
		.name	= "mcp23s08",
		.owner	= THIS_MODULE,
771
		.of_match_table = of_match_ptr(mcp23s08_spi_of_match),
772 773 774
	},
};

775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
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 */

792 793 794 795
/*----------------------------------------------------------------------*/

static int __init mcp23s08_init(void)
{
P
Peter Korsgaard 已提交
796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811
	int ret;

	ret = mcp23s08_spi_init();
	if (ret)
		goto spi_fail;

	ret = mcp23s08_i2c_init();
	if (ret)
		goto i2c_fail;

	return 0;

 i2c_fail:
	mcp23s08_spi_exit();
 spi_fail:
	return ret;
812
}
P
Peter Korsgaard 已提交
813
/* register after spi/i2c postcore initcall and before
814 815 816
 * subsys initcalls that may rely on these GPIOs
 */
subsys_initcall(mcp23s08_init);
817 818 819

static void __exit mcp23s08_exit(void)
{
820
	mcp23s08_spi_exit();
P
Peter Korsgaard 已提交
821
	mcp23s08_i2c_exit();
822 823 824 825
}
module_exit(mcp23s08_exit);

MODULE_LICENSE("GPL");