gpio-aspeed.c 30.8 KB
Newer Older
Joel Stanley's avatar
Joel Stanley committed
1 2 3 4 5 6 7 8 9 10 11
/*
 * Copyright 2015 IBM Corp.
 *
 * Joel Stanley <joel@jms.id.au>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version
 * 2 of the License, or (at your option) any later version.
 */

12 13 14
#include <asm/div64.h>
#include <linux/clk.h>
#include <linux/gpio/driver.h>
15
#include <linux/gpio/aspeed.h>
16
#include <linux/hashtable.h>
Joel Stanley's avatar
Joel Stanley committed
17 18
#include <linux/init.h>
#include <linux/io.h>
19 20
#include <linux/kernel.h>
#include <linux/module.h>
Joel Stanley's avatar
Joel Stanley committed
21
#include <linux/pinctrl/consumer.h>
22 23 24
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/string.h>
Joel Stanley's avatar
Joel Stanley committed
25

26 27 28 29 30 31 32 33 34
/*
 * These two headers aren't meant to be used by GPIO drivers. We need
 * them in order to access gpio_chip_hwgpio() which we need to implement
 * the aspeed specific API which allows the coprocessor to request
 * access to some GPIOs and to arbitrate between coprocessor and ARM.
 */
#include <linux/gpio/consumer.h>
#include "gpiolib.h"

35 36 37 38 39 40 41 42 43 44 45
struct aspeed_bank_props {
	unsigned int bank;
	u32 input;
	u32 output;
};

struct aspeed_gpio_config {
	unsigned int nr_gpios;
	const struct aspeed_bank_props *props;
};

46 47 48 49 50 51 52 53 54 55 56
/*
 * @offset_timer: Maps an offset to an @timer_users index, or zero if disabled
 * @timer_users: Tracks the number of users for each timer
 *
 * The @timer_users has four elements but the first element is unused. This is
 * to simplify accounting and indexing, as a zero value in @offset_timer
 * represents disabled debouncing for the GPIO. Any other value for an element
 * of @offset_timer is used as an index into @timer_users. This behaviour of
 * the zero value aligns with the behaviour of zero built from the timer
 * configuration registers (i.e. debouncing is disabled).
 */
Joel Stanley's avatar
Joel Stanley committed
57 58 59 60 61
struct aspeed_gpio {
	struct gpio_chip chip;
	spinlock_t lock;
	void __iomem *base;
	int irq;
62
	const struct aspeed_gpio_config *config;
63 64 65 66

	u8 *offset_timer;
	unsigned int timer_users[4];
	struct clk *clk;
67 68

	u32 *dcache;
69
	u8 *cf_copro_bankmap;
Joel Stanley's avatar
Joel Stanley committed
70 71 72
};

struct aspeed_gpio_bank {
73 74 75 76
	uint16_t	val_regs;	/* +0: Rd: read input value, Wr: set write latch
					 * +4: Rd/Wr: Direction (0=in, 1=out)
					 */
	uint16_t	rdata_reg;	/*     Rd: read write latch, Wr: <none>  */
Joel Stanley's avatar
Joel Stanley committed
77
	uint16_t	irq_regs;
78
	uint16_t	debounce_regs;
79
	uint16_t	tolerance_regs;
80
	uint16_t	cmdsrc_regs;
81
	const char	names[4][3];
Joel Stanley's avatar
Joel Stanley committed
82 83
};

84 85 86 87 88 89 90 91 92 93 94
/*
 * Note: The "value" register returns the input value sampled on the
 *       line even when the GPIO is configured as an output. Since
 *       that input goes through synchronizers, writing, then reading
 *       back may not return the written value right away.
 *
 *       The "rdata" register returns the content of the write latch
 *       and thus can be used to read back what was last written
 *       reliably.
 */

95 96
static const int debounce_timers[4] = { 0x00, 0x50, 0x54, 0x58 };

97 98 99
static const struct aspeed_gpio_copro_ops *copro_ops;
static void *copro_data;

Joel Stanley's avatar
Joel Stanley committed
100 101 102
static const struct aspeed_gpio_bank aspeed_gpio_banks[] = {
	{
		.val_regs = 0x0000,
103
		.rdata_reg = 0x00c0,
Joel Stanley's avatar
Joel Stanley committed
104
		.irq_regs = 0x0008,
105
		.debounce_regs = 0x0040,
106
		.tolerance_regs = 0x001c,
107
		.cmdsrc_regs = 0x0060,
108
		.names = { "A", "B", "C", "D" },
Joel Stanley's avatar
Joel Stanley committed
109 110 111
	},
	{
		.val_regs = 0x0020,
112
		.rdata_reg = 0x00c4,
Joel Stanley's avatar
Joel Stanley committed
113
		.irq_regs = 0x0028,
114
		.debounce_regs = 0x0048,
115
		.tolerance_regs = 0x003c,
116
		.cmdsrc_regs = 0x0068,
117
		.names = { "E", "F", "G", "H" },
Joel Stanley's avatar
Joel Stanley committed
118 119 120
	},
	{
		.val_regs = 0x0070,
121
		.rdata_reg = 0x00c8,
Joel Stanley's avatar
Joel Stanley committed
122
		.irq_regs = 0x0098,
123
		.debounce_regs = 0x00b0,
124
		.tolerance_regs = 0x00ac,
125
		.cmdsrc_regs = 0x0090,
126
		.names = { "I", "J", "K", "L" },
Joel Stanley's avatar
Joel Stanley committed
127 128 129
	},
	{
		.val_regs = 0x0078,
130
		.rdata_reg = 0x00cc,
Joel Stanley's avatar
Joel Stanley committed
131
		.irq_regs = 0x00e8,
132
		.debounce_regs = 0x0100,
133
		.tolerance_regs = 0x00fc,
134
		.cmdsrc_regs = 0x00e0,
135
		.names = { "M", "N", "O", "P" },
Joel Stanley's avatar
Joel Stanley committed
136 137 138
	},
	{
		.val_regs = 0x0080,
139
		.rdata_reg = 0x00d0,
Joel Stanley's avatar
Joel Stanley committed
140
		.irq_regs = 0x0118,
141
		.debounce_regs = 0x0130,
142
		.tolerance_regs = 0x012c,
143
		.cmdsrc_regs = 0x0110,
144
		.names = { "Q", "R", "S", "T" },
Joel Stanley's avatar
Joel Stanley committed
145 146 147
	},
	{
		.val_regs = 0x0088,
148
		.rdata_reg = 0x00d4,
Joel Stanley's avatar
Joel Stanley committed
149
		.irq_regs = 0x0148,
150
		.debounce_regs = 0x0160,
151
		.tolerance_regs = 0x015c,
152
		.cmdsrc_regs = 0x0140,
153
		.names = { "U", "V", "W", "X" },
Joel Stanley's avatar
Joel Stanley committed
154
	},
155 156
	{
		.val_regs = 0x01E0,
157
		.rdata_reg = 0x00d8,
158
		.irq_regs = 0x0178,
159
		.debounce_regs = 0x0190,
160
		.tolerance_regs = 0x018c,
161
		.cmdsrc_regs = 0x0170,
162 163 164
		.names = { "Y", "Z", "AA", "AB" },
	},
	{
165
		.val_regs = 0x01e8,
166
		.rdata_reg = 0x00dc,
167
		.irq_regs = 0x01a8,
168
		.debounce_regs = 0x01c0,
169
		.tolerance_regs = 0x01bc,
170
		.cmdsrc_regs = 0x01a0,
171 172
		.names = { "AC", "", "", "" },
	},
Joel Stanley's avatar
Joel Stanley committed
173 174
};

175 176
enum aspeed_gpio_reg {
	reg_val,
177
	reg_rdata,
178 179 180 181 182 183 184 185 186
	reg_dir,
	reg_irq_enable,
	reg_irq_type0,
	reg_irq_type1,
	reg_irq_type2,
	reg_irq_status,
	reg_debounce_sel1,
	reg_debounce_sel2,
	reg_tolerance,
187 188
	reg_cmdsrc0,
	reg_cmdsrc1,
189
};
Joel Stanley's avatar
Joel Stanley committed
190

191 192
#define GPIO_VAL_VALUE	0x00
#define GPIO_VAL_DIR	0x04
Joel Stanley's avatar
Joel Stanley committed
193 194 195 196 197 198 199

#define GPIO_IRQ_ENABLE	0x00
#define GPIO_IRQ_TYPE0	0x04
#define GPIO_IRQ_TYPE1	0x08
#define GPIO_IRQ_TYPE2	0x0c
#define GPIO_IRQ_STATUS	0x10

200 201 202
#define GPIO_DEBOUNCE_SEL1 0x00
#define GPIO_DEBOUNCE_SEL2 0x04

203 204 205 206 207 208 209
#define GPIO_CMDSRC_0	0x00
#define GPIO_CMDSRC_1	0x04
#define  GPIO_CMDSRC_ARM		0
#define  GPIO_CMDSRC_LPC		1
#define  GPIO_CMDSRC_COLDFIRE		2
#define  GPIO_CMDSRC_RESERVED		3

210 211 212 213 214 215 216 217
/* This will be resolved at compile time */
static inline void __iomem *bank_reg(struct aspeed_gpio *gpio,
				     const struct aspeed_gpio_bank *bank,
				     const enum aspeed_gpio_reg reg)
{
	switch (reg) {
	case reg_val:
		return gpio->base + bank->val_regs + GPIO_VAL_VALUE;
218 219
	case reg_rdata:
		return gpio->base + bank->rdata_reg;
220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
	case reg_dir:
		return gpio->base + bank->val_regs + GPIO_VAL_DIR;
	case reg_irq_enable:
		return gpio->base + bank->irq_regs + GPIO_IRQ_ENABLE;
	case reg_irq_type0:
		return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE0;
	case reg_irq_type1:
		return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE1;
	case reg_irq_type2:
		return gpio->base + bank->irq_regs + GPIO_IRQ_TYPE2;
	case reg_irq_status:
		return gpio->base + bank->irq_regs + GPIO_IRQ_STATUS;
	case reg_debounce_sel1:
		return gpio->base + bank->debounce_regs + GPIO_DEBOUNCE_SEL1;
	case reg_debounce_sel2:
		return gpio->base + bank->debounce_regs + GPIO_DEBOUNCE_SEL2;
	case reg_tolerance:
		return gpio->base + bank->tolerance_regs;
238 239 240 241
	case reg_cmdsrc0:
		return gpio->base + bank->cmdsrc_regs + GPIO_CMDSRC_0;
	case reg_cmdsrc1:
		return gpio->base + bank->cmdsrc_regs + GPIO_CMDSRC_1;
242
	}
243
	BUG();
244 245 246 247 248 249
}

#define GPIO_BANK(x)	((x) >> 5)
#define GPIO_OFFSET(x)	((x) & 0x1f)
#define GPIO_BIT(x)	BIT(GPIO_OFFSET(x))

250 251 252 253
#define _GPIO_SET_DEBOUNCE(t, o, i) ((!!((t) & BIT(i))) << GPIO_OFFSET(o))
#define GPIO_SET_DEBOUNCE1(t, o) _GPIO_SET_DEBOUNCE(t, o, 1)
#define GPIO_SET_DEBOUNCE2(t, o) _GPIO_SET_DEBOUNCE(t, o, 0)

Joel Stanley's avatar
Joel Stanley committed
254 255 256 257
static const struct aspeed_gpio_bank *to_bank(unsigned int offset)
{
	unsigned int bank = GPIO_BANK(offset);

258
	WARN_ON(bank >= ARRAY_SIZE(aspeed_gpio_banks));
Joel Stanley's avatar
Joel Stanley committed
259 260 261
	return &aspeed_gpio_banks[bank];
}

262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
static inline bool is_bank_props_sentinel(const struct aspeed_bank_props *props)
{
	return !(props->input || props->output);
}

static inline const struct aspeed_bank_props *find_bank_props(
		struct aspeed_gpio *gpio, unsigned int offset)
{
	const struct aspeed_bank_props *props = gpio->config->props;

	while (!is_bank_props_sentinel(props)) {
		if (props->bank == GPIO_BANK(offset))
			return props;
		props++;
	}

	return NULL;
}

static inline bool have_gpio(struct aspeed_gpio *gpio, unsigned int offset)
{
	const struct aspeed_bank_props *props = find_bank_props(gpio, offset);
	const struct aspeed_gpio_bank *bank = to_bank(offset);
	unsigned int group = GPIO_OFFSET(offset) / 8;

	return bank->names[group][0] != '\0' &&
		(!props || ((props->input | props->output) & GPIO_BIT(offset)));
}

static inline bool have_input(struct aspeed_gpio *gpio, unsigned int offset)
{
	const struct aspeed_bank_props *props = find_bank_props(gpio, offset);

	return !props || (props->input & GPIO_BIT(offset));
}

#define have_irq(g, o) have_input((g), (o))
299
#define have_debounce(g, o) have_input((g), (o))
300 301 302 303 304 305 306 307

static inline bool have_output(struct aspeed_gpio *gpio, unsigned int offset)
{
	const struct aspeed_bank_props *props = find_bank_props(gpio, offset);

	return !props || (props->output & GPIO_BIT(offset));
}

308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339
static void aspeed_gpio_change_cmd_source(struct aspeed_gpio *gpio,
					  const struct aspeed_gpio_bank *bank,
					  int bindex, int cmdsrc)
{
	void __iomem *c0 = bank_reg(gpio, bank, reg_cmdsrc0);
	void __iomem *c1 = bank_reg(gpio, bank, reg_cmdsrc1);
	u32 bit, reg;

	/*
	 * Each register controls 4 banks, so take the bottom 2
	 * bits of the bank index, and use them to select the
	 * right control bit (0, 8, 16 or 24).
	 */
	bit = BIT((bindex & 3) << 3);

	/* Source 1 first to avoid illegal 11 combination */
	reg = ioread32(c1);
	if (cmdsrc & 2)
		reg |= bit;
	else
		reg &= ~bit;
	iowrite32(reg, c1);

	/* Then Source 0 */
	reg = ioread32(c0);
	if (cmdsrc & 1)
		reg |= bit;
	else
		reg &= ~bit;
	iowrite32(reg, c0);
}

340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383
static bool aspeed_gpio_copro_request(struct aspeed_gpio *gpio,
				      unsigned int offset)
{
	const struct aspeed_gpio_bank *bank = to_bank(offset);

	if (!copro_ops || !gpio->cf_copro_bankmap)
		return false;
	if (!gpio->cf_copro_bankmap[offset >> 3])
		return false;
	if (!copro_ops->request_access)
		return false;

	/* Pause the coprocessor */
	copro_ops->request_access(copro_data);

	/* Change command source back to ARM */
	aspeed_gpio_change_cmd_source(gpio, bank, offset >> 3, GPIO_CMDSRC_ARM);

	/* Update cache */
	gpio->dcache[GPIO_BANK(offset)] = ioread32(bank_reg(gpio, bank, reg_rdata));

	return true;
}

static void aspeed_gpio_copro_release(struct aspeed_gpio *gpio,
				      unsigned int offset)
{
	const struct aspeed_gpio_bank *bank = to_bank(offset);

	if (!copro_ops || !gpio->cf_copro_bankmap)
		return;
	if (!gpio->cf_copro_bankmap[offset >> 3])
		return;
	if (!copro_ops->release_access)
		return;

	/* Change command source back to ColdFire */
	aspeed_gpio_change_cmd_source(gpio, bank, offset >> 3,
				      GPIO_CMDSRC_COLDFIRE);

	/* Restart the coprocessor */
	copro_ops->release_access(copro_data);
}

Joel Stanley's avatar
Joel Stanley committed
384 385 386 387 388
static int aspeed_gpio_get(struct gpio_chip *gc, unsigned int offset)
{
	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
	const struct aspeed_gpio_bank *bank = to_bank(offset);

389
	return !!(ioread32(bank_reg(gpio, bank, reg_val)) & GPIO_BIT(offset));
Joel Stanley's avatar
Joel Stanley committed
390 391 392 393 394 395 396 397 398 399
}

static void __aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
			      int val)
{
	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
	const struct aspeed_gpio_bank *bank = to_bank(offset);
	void __iomem *addr;
	u32 reg;

400
	addr = bank_reg(gpio, bank, reg_val);
401
	reg = gpio->dcache[GPIO_BANK(offset)];
Joel Stanley's avatar
Joel Stanley committed
402 403 404 405 406

	if (val)
		reg |= GPIO_BIT(offset);
	else
		reg &= ~GPIO_BIT(offset);
407
	gpio->dcache[GPIO_BANK(offset)] = reg;
Joel Stanley's avatar
Joel Stanley committed
408 409 410 411 412 413 414 415 416

	iowrite32(reg, addr);
}

static void aspeed_gpio_set(struct gpio_chip *gc, unsigned int offset,
			    int val)
{
	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
	unsigned long flags;
417
	bool copro;
Joel Stanley's avatar
Joel Stanley committed
418 419

	spin_lock_irqsave(&gpio->lock, flags);
420
	copro = aspeed_gpio_copro_request(gpio, offset);
Joel Stanley's avatar
Joel Stanley committed
421 422 423

	__aspeed_gpio_set(gc, offset, val);

424 425
	if (copro)
		aspeed_gpio_copro_release(gpio, offset);
Joel Stanley's avatar
Joel Stanley committed
426 427 428 429 430 431 432
	spin_unlock_irqrestore(&gpio->lock, flags);
}

static int aspeed_gpio_dir_in(struct gpio_chip *gc, unsigned int offset)
{
	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
	const struct aspeed_gpio_bank *bank = to_bank(offset);
433
	void __iomem *addr = bank_reg(gpio, bank, reg_dir);
Joel Stanley's avatar
Joel Stanley committed
434
	unsigned long flags;
435
	bool copro;
Joel Stanley's avatar
Joel Stanley committed
436 437
	u32 reg;

438 439 440
	if (!have_input(gpio, offset))
		return -ENOTSUPP;

Joel Stanley's avatar
Joel Stanley committed
441 442
	spin_lock_irqsave(&gpio->lock, flags);

443 444 445 446 447 448 449
	reg = ioread32(addr);
	reg &= ~GPIO_BIT(offset);

	copro = aspeed_gpio_copro_request(gpio, offset);
	iowrite32(reg, addr);
	if (copro)
		aspeed_gpio_copro_release(gpio, offset);
Joel Stanley's avatar
Joel Stanley committed
450 451 452 453 454 455 456 457 458 459 460

	spin_unlock_irqrestore(&gpio->lock, flags);

	return 0;
}

static int aspeed_gpio_dir_out(struct gpio_chip *gc,
			       unsigned int offset, int val)
{
	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
	const struct aspeed_gpio_bank *bank = to_bank(offset);
461
	void __iomem *addr = bank_reg(gpio, bank, reg_dir);
Joel Stanley's avatar
Joel Stanley committed
462
	unsigned long flags;
463
	bool copro;
Joel Stanley's avatar
Joel Stanley committed
464 465
	u32 reg;

466 467 468
	if (!have_output(gpio, offset))
		return -ENOTSUPP;

Joel Stanley's avatar
Joel Stanley committed
469 470
	spin_lock_irqsave(&gpio->lock, flags);

471 472 473 474
	reg = ioread32(addr);
	reg |= GPIO_BIT(offset);

	copro = aspeed_gpio_copro_request(gpio, offset);
475
	__aspeed_gpio_set(gc, offset, val);
476
	iowrite32(reg, addr);
Joel Stanley's avatar
Joel Stanley committed
477

478 479
	if (copro)
		aspeed_gpio_copro_release(gpio, offset);
Joel Stanley's avatar
Joel Stanley committed
480 481 482 483 484 485 486 487 488 489 490 491
	spin_unlock_irqrestore(&gpio->lock, flags);

	return 0;
}

static int aspeed_gpio_get_direction(struct gpio_chip *gc, unsigned int offset)
{
	struct aspeed_gpio *gpio = gpiochip_get_data(gc);
	const struct aspeed_gpio_bank *bank = to_bank(offset);
	unsigned long flags;
	u32 val;

492
	if (!have_input(gpio, offset))
493
		return 0;
494 495

	if (!have_output(gpio, offset))
496
		return 1;
497

Joel Stanley's avatar
Joel Stanley committed
498 499
	spin_lock_irqsave(&gpio->lock, flags);

500
	val = ioread32(bank_reg(gpio, bank, reg_dir)) & GPIO_BIT(offset);
Joel Stanley's avatar
Joel Stanley committed
501 502 503 504 505 506 507 508

	spin_unlock_irqrestore(&gpio->lock, flags);

	return !val;

}

static inline int irqd_to_aspeed_gpio_data(struct irq_data *d,
509 510 511
					   struct aspeed_gpio **gpio,
					   const struct aspeed_gpio_bank **bank,
					   u32 *bit, int *offset)
Joel Stanley's avatar
Joel Stanley committed
512
{
513
	struct aspeed_gpio *internal;
Joel Stanley's avatar
Joel Stanley committed
514

515
	*offset = irqd_to_hwirq(d);
Joel Stanley's avatar
Joel Stanley committed
516

517 518 519
	internal = irq_data_get_irq_chip_data(d);

	/* This might be a bit of a questionable place to check */
520
	if (!have_irq(internal, *offset))
521 522 523
		return -ENOTSUPP;

	*gpio = internal;
524 525
	*bank = to_bank(*offset);
	*bit = GPIO_BIT(*offset);
Joel Stanley's avatar
Joel Stanley committed
526 527 528 529 530 531 532 533 534 535

	return 0;
}

static void aspeed_gpio_irq_ack(struct irq_data *d)
{
	const struct aspeed_gpio_bank *bank;
	struct aspeed_gpio *gpio;
	unsigned long flags;
	void __iomem *status_addr;
536 537
	int rc, offset;
	bool copro;
Joel Stanley's avatar
Joel Stanley committed
538 539
	u32 bit;

540
	rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit, &offset);
Joel Stanley's avatar
Joel Stanley committed
541 542 543
	if (rc)
		return;

544
	status_addr = bank_reg(gpio, bank, reg_irq_status);
Joel Stanley's avatar
Joel Stanley committed
545 546

	spin_lock_irqsave(&gpio->lock, flags);
547 548
	copro = aspeed_gpio_copro_request(gpio, offset);

Joel Stanley's avatar
Joel Stanley committed
549
	iowrite32(bit, status_addr);
550 551 552

	if (copro)
		aspeed_gpio_copro_release(gpio, offset);
Joel Stanley's avatar
Joel Stanley committed
553 554 555 556 557 558 559 560 561 562
	spin_unlock_irqrestore(&gpio->lock, flags);
}

static void aspeed_gpio_irq_set_mask(struct irq_data *d, bool set)
{
	const struct aspeed_gpio_bank *bank;
	struct aspeed_gpio *gpio;
	unsigned long flags;
	u32 reg, bit;
	void __iomem *addr;
563 564
	int rc, offset;
	bool copro;
Joel Stanley's avatar
Joel Stanley committed
565

566
	rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit, &offset);
Joel Stanley's avatar
Joel Stanley committed
567 568 569
	if (rc)
		return;

570
	addr = bank_reg(gpio, bank, reg_irq_enable);
Joel Stanley's avatar
Joel Stanley committed
571 572

	spin_lock_irqsave(&gpio->lock, flags);
573
	copro = aspeed_gpio_copro_request(gpio, offset);
Joel Stanley's avatar
Joel Stanley committed
574 575 576 577 578

	reg = ioread32(addr);
	if (set)
		reg |= bit;
	else
579
		reg &= ~bit;
Joel Stanley's avatar
Joel Stanley committed
580 581
	iowrite32(reg, addr);

582 583
	if (copro)
		aspeed_gpio_copro_release(gpio, offset);
Joel Stanley's avatar
Joel Stanley committed
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607
	spin_unlock_irqrestore(&gpio->lock, flags);
}

static void aspeed_gpio_irq_mask(struct irq_data *d)
{
	aspeed_gpio_irq_set_mask(d, false);
}

static void aspeed_gpio_irq_unmask(struct irq_data *d)
{
	aspeed_gpio_irq_set_mask(d, true);
}

static int aspeed_gpio_set_type(struct irq_data *d, unsigned int type)
{
	u32 type0 = 0;
	u32 type1 = 0;
	u32 type2 = 0;
	u32 bit, reg;
	const struct aspeed_gpio_bank *bank;
	irq_flow_handler_t handler;
	struct aspeed_gpio *gpio;
	unsigned long flags;
	void __iomem *addr;
608 609
	int rc, offset;
	bool copro;
Joel Stanley's avatar
Joel Stanley committed
610

611
	rc = irqd_to_aspeed_gpio_data(d, &gpio, &bank, &bit, &offset);
Joel Stanley's avatar
Joel Stanley committed
612 613 614 615 616 617
	if (rc)
		return -EINVAL;

	switch (type & IRQ_TYPE_SENSE_MASK) {
	case IRQ_TYPE_EDGE_BOTH:
		type2 |= bit;
618
		/* fall through */
Joel Stanley's avatar
Joel Stanley committed
619 620
	case IRQ_TYPE_EDGE_RISING:
		type0 |= bit;
621
		/* fall through */
Joel Stanley's avatar
Joel Stanley committed
622 623 624 625 626
	case IRQ_TYPE_EDGE_FALLING:
		handler = handle_edge_irq;
		break;
	case IRQ_TYPE_LEVEL_HIGH:
		type0 |= bit;
627
		/* fall through */
Joel Stanley's avatar
Joel Stanley committed
628 629 630 631 632 633 634 635 636
	case IRQ_TYPE_LEVEL_LOW:
		type1 |= bit;
		handler = handle_level_irq;
		break;
	default:
		return -EINVAL;
	}

	spin_lock_irqsave(&gpio->lock, flags);
637
	copro = aspeed_gpio_copro_request(gpio, offset);
Joel Stanley's avatar
Joel Stanley committed
638

639
	addr = bank_reg(gpio, bank, reg_irq_type0);
Joel Stanley's avatar
Joel Stanley committed
640 641 642 643
	reg = ioread32(addr);
	reg = (reg & ~bit) | type0;
	iowrite32(reg, addr);

644
	addr = bank_reg(gpio, bank, reg_irq_type1);
Joel Stanley's avatar
Joel Stanley committed
645 646 647 648
	reg = ioread32(addr);
	reg = (reg & ~bit) | type1;
	iowrite32(reg, addr);

649
	addr = bank_reg(gpio, bank, reg_irq_type2);
Joel Stanley's avatar
Joel Stanley committed
650 651 652 653
	reg = ioread32(addr);
	reg = (reg & ~bit) | type2;
	iowrite32(reg, addr);

654 655
	if (copro)
		aspeed_gpio_copro_release(gpio, offset);
Joel Stanley's avatar
Joel Stanley committed
656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675
	spin_unlock_irqrestore(&gpio->lock, flags);

	irq_set_handler_locked(d, handler);

	return 0;
}

static void aspeed_gpio_irq_handler(struct irq_desc *desc)
{
	struct gpio_chip *gc = irq_desc_get_handler_data(desc);
	struct irq_chip *ic = irq_desc_get_chip(desc);
	struct aspeed_gpio *data = gpiochip_get_data(gc);
	unsigned int i, p, girq;
	unsigned long reg;

	chained_irq_enter(ic, desc);

	for (i = 0; i < ARRAY_SIZE(aspeed_gpio_banks); i++) {
		const struct aspeed_gpio_bank *bank = &aspeed_gpio_banks[i];

676
		reg = ioread32(bank_reg(data, bank, reg_irq_status));
Joel Stanley's avatar
Joel Stanley committed
677 678

		for_each_set_bit(p, &reg, 32) {
679
			girq = irq_find_mapping(gc->irq.domain, i * 32 + p);
Joel Stanley's avatar
Joel Stanley committed
680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695
			generic_handle_irq(girq);
		}

	}

	chained_irq_exit(ic, desc);
}

static struct irq_chip aspeed_gpio_irqchip = {
	.name		= "aspeed-gpio",
	.irq_ack	= aspeed_gpio_irq_ack,
	.irq_mask	= aspeed_gpio_irq_mask,
	.irq_unmask	= aspeed_gpio_irq_unmask,
	.irq_set_type	= aspeed_gpio_set_type,
};

696 697 698 699 700 701 702 703 704 705 706 707 708 709 710
static void set_irq_valid_mask(struct aspeed_gpio *gpio)
{
	const struct aspeed_bank_props *props = gpio->config->props;

	while (!is_bank_props_sentinel(props)) {
		unsigned int offset;
		const unsigned long int input = props->input;

		/* Pretty crummy approach, but similar to GPIO core */
		for_each_clear_bit(offset, &input, 32) {
			unsigned int i = props->bank * 32 + offset;

			if (i >= gpio->config->nr_gpios)
				break;

711
			clear_bit(i, gpio->chip.irq.valid_mask);
712 713 714 715 716 717
		}

		props++;
	}
}

Joel Stanley's avatar
Joel Stanley committed
718 719 720 721 722 723 724 725 726 727 728
static int aspeed_gpio_setup_irqs(struct aspeed_gpio *gpio,
		struct platform_device *pdev)
{
	int rc;

	rc = platform_get_irq(pdev, 0);
	if (rc < 0)
		return rc;

	gpio->irq = rc;

729 730
	set_irq_valid_mask(gpio);

Joel Stanley's avatar
Joel Stanley committed
731 732 733 734 735 736 737 738 739 740 741 742 743
	rc = gpiochip_irqchip_add(&gpio->chip, &aspeed_gpio_irqchip,
			0, handle_bad_irq, IRQ_TYPE_NONE);
	if (rc) {
		dev_info(&pdev->dev, "Could not add irqchip\n");
		return rc;
	}

	gpiochip_set_chained_irqchip(&gpio->chip, &aspeed_gpio_irqchip,
				     gpio->irq, aspeed_gpio_irq_handler);

	return 0;
}

744 745 746 747 748
static int aspeed_gpio_reset_tolerance(struct gpio_chip *chip,
					unsigned int offset, bool enable)
{
	struct aspeed_gpio *gpio = gpiochip_get_data(chip);
	unsigned long flags;
749
	void __iomem *treg;
750
	bool copro;
751 752
	u32 val;

753
	treg = bank_reg(gpio, to_bank(offset), reg_tolerance);
754 755

	spin_lock_irqsave(&gpio->lock, flags);
756 757
	copro = aspeed_gpio_copro_request(gpio, offset);

758
	val = readl(treg);
759 760 761 762 763 764

	if (enable)
		val |= GPIO_BIT(offset);
	else
		val &= ~GPIO_BIT(offset);

765
	writel(val, treg);
766 767 768

	if (copro)
		aspeed_gpio_copro_release(gpio, offset);
769 770 771 772 773
	spin_unlock_irqrestore(&gpio->lock, flags);

	return 0;
}

Joel Stanley's avatar
Joel Stanley committed
774 775
static int aspeed_gpio_request(struct gpio_chip *chip, unsigned int offset)
{
776 777 778
	if (!have_gpio(gpiochip_get_data(chip), offset))
		return -ENODEV;

779
	return pinctrl_gpio_request(chip->base + offset);
Joel Stanley's avatar
Joel Stanley committed
780 781 782 783
}

static void aspeed_gpio_free(struct gpio_chip *chip, unsigned int offset)
{
784
	pinctrl_gpio_free(chip->base + offset);
Joel Stanley's avatar
Joel Stanley committed
785 786
}

787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863
static int usecs_to_cycles(struct aspeed_gpio *gpio, unsigned long usecs,
		u32 *cycles)
{
	u64 rate;
	u64 n;
	u32 r;

	rate = clk_get_rate(gpio->clk);
	if (!rate)
		return -ENOTSUPP;

	n = rate * usecs;
	r = do_div(n, 1000000);

	if (n >= U32_MAX)
		return -ERANGE;

	/* At least as long as the requested time */
	*cycles = n + (!!r);

	return 0;
}

/* Call under gpio->lock */
static int register_allocated_timer(struct aspeed_gpio *gpio,
		unsigned int offset, unsigned int timer)
{
	if (WARN(gpio->offset_timer[offset] != 0,
				"Offset %d already allocated timer %d\n",
				offset, gpio->offset_timer[offset]))
		return -EINVAL;

	if (WARN(gpio->timer_users[timer] == UINT_MAX,
				"Timer user count would overflow\n"))
		return -EPERM;

	gpio->offset_timer[offset] = timer;
	gpio->timer_users[timer]++;

	return 0;
}

/* Call under gpio->lock */
static int unregister_allocated_timer(struct aspeed_gpio *gpio,
		unsigned int offset)
{
	if (WARN(gpio->offset_timer[offset] == 0,
				"No timer allocated to offset %d\n", offset))
		return -EINVAL;

	if (WARN(gpio->timer_users[gpio->offset_timer[offset]] == 0,
				"No users recorded for timer %d\n",
				gpio->offset_timer[offset]))
		return -EINVAL;

	gpio->timer_users[gpio->offset_timer[offset]]--;
	gpio->offset_timer[offset] = 0;

	return 0;
}

/* Call under gpio->lock */
static inline bool timer_allocation_registered(struct aspeed_gpio *gpio,
		unsigned int offset)
{
	return gpio->offset_timer[offset] > 0;
}

/* Call under gpio->lock */
static void configure_timer(struct aspeed_gpio *gpio, unsigned int offset,
		unsigned int timer)
{
	const struct aspeed_gpio_bank *bank = to_bank(offset);
	const u32 mask = GPIO_BIT(offset);
	void __iomem *addr;
	u32 val;

864 865 866
	/* Note: Debounce timer isn't under control of the command
	 * source registers, so no need to sync with the coprocessor
	 */
867
	addr = bank_reg(gpio, bank, reg_debounce_sel1);
868 869 870
	val = ioread32(addr);
	iowrite32((val & ~mask) | GPIO_SET_DEBOUNCE1(timer, offset), addr);

871
	addr = bank_reg(gpio, bank, reg_debounce_sel2);
872 873 874 875 876 877 878 879 880 881 882 883 884
	val = ioread32(addr);
	iowrite32((val & ~mask) | GPIO_SET_DEBOUNCE2(timer, offset), addr);
}

static int enable_debounce(struct gpio_chip *chip, unsigned int offset,
				    unsigned long usecs)
{
	struct aspeed_gpio *gpio = gpiochip_get_data(chip);
	u32 requested_cycles;
	unsigned long flags;
	int rc;
	int i;

885 886 887
	if (!gpio->clk)
		return -EINVAL;

888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002
	rc = usecs_to_cycles(gpio, usecs, &requested_cycles);
	if (rc < 0) {
		dev_warn(chip->parent, "Failed to convert %luus to cycles at %luHz: %d\n",
				usecs, clk_get_rate(gpio->clk), rc);
		return rc;
	}

	spin_lock_irqsave(&gpio->lock, flags);

	if (timer_allocation_registered(gpio, offset)) {
		rc = unregister_allocated_timer(gpio, offset);
		if (rc < 0)
			goto out;
	}

	/* Try to find a timer already configured for the debounce period */
	for (i = 1; i < ARRAY_SIZE(debounce_timers); i++) {
		u32 cycles;

		cycles = ioread32(gpio->base + debounce_timers[i]);
		if (requested_cycles == cycles)
			break;
	}

	if (i == ARRAY_SIZE(debounce_timers)) {
		int j;

		/*
		 * As there are no timers configured for the requested debounce
		 * period, find an unused timer instead
		 */
		for (j = 1; j < ARRAY_SIZE(gpio->timer_users); j++) {
			if (gpio->timer_users[j] == 0)
				break;
		}

		if (j == ARRAY_SIZE(gpio->timer_users)) {
			dev_warn(chip->parent,
					"Debounce timers exhausted, cannot debounce for period %luus\n",
					usecs);

			rc = -EPERM;

			/*
			 * We already adjusted the accounting to remove @offset
			 * as a user of its previous timer, so also configure
			 * the hardware so @offset has timers disabled for
			 * consistency.
			 */
			configure_timer(gpio, offset, 0);
			goto out;
		}

		i = j;

		iowrite32(requested_cycles, gpio->base + debounce_timers[i]);
	}

	if (WARN(i == 0, "Cannot register index of disabled timer\n")) {
		rc = -EINVAL;
		goto out;
	}

	register_allocated_timer(gpio, offset, i);
	configure_timer(gpio, offset, i);

out:
	spin_unlock_irqrestore(&gpio->lock, flags);

	return rc;
}

static int disable_debounce(struct gpio_chip *chip, unsigned int offset)
{
	struct aspeed_gpio *gpio = gpiochip_get_data(chip);
	unsigned long flags;
	int rc;

	spin_lock_irqsave(&gpio->lock, flags);

	rc = unregister_allocated_timer(gpio, offset);
	if (!rc)
		configure_timer(gpio, offset, 0);

	spin_unlock_irqrestore(&gpio->lock, flags);

	return rc;
}

static int set_debounce(struct gpio_chip *chip, unsigned int offset,
				    unsigned long usecs)
{
	struct aspeed_gpio *gpio = gpiochip_get_data(chip);

	if (!have_debounce(gpio, offset))
		return -ENOTSUPP;

	if (usecs)
		return enable_debounce(chip, offset, usecs);

	return disable_debounce(chip, offset);
}

static int aspeed_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
				  unsigned long config)
{
	unsigned long param = pinconf_to_config_param(config);
	u32 arg = pinconf_to_config_argument(config);

	if (param == PIN_CONFIG_INPUT_DEBOUNCE)
		return set_debounce(chip, offset, arg);
	else if (param == PIN_CONFIG_BIAS_DISABLE ||
			param == PIN_CONFIG_BIAS_PULL_DOWN ||
			param == PIN_CONFIG_DRIVE_STRENGTH)
		return pinctrl_gpio_set_config(offset, config);
1003 1004 1005 1006
	else if (param == PIN_CONFIG_DRIVE_OPEN_DRAIN ||
			param == PIN_CONFIG_DRIVE_OPEN_SOURCE)
		/* Return -ENOTSUPP to trigger emulation, as per datasheet */
		return -ENOTSUPP;
1007 1008
	else if (param == PIN_CONFIG_PERSIST_STATE)
		return aspeed_gpio_reset_tolerance(chip, offset, arg);
1009 1010 1011 1012

	return -ENOTSUPP;
}

1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117
/**
 * aspeed_gpio_copro_set_ops - Sets the callbacks used for handhsaking with
 *                             the coprocessor for shared GPIO banks
 * @ops: The callbacks
 * @data: Pointer passed back to the callbacks
 */
int aspeed_gpio_copro_set_ops(const struct aspeed_gpio_copro_ops *ops, void *data)
{
	copro_data = data;
	copro_ops = ops;

	return 0;
}
EXPORT_SYMBOL_GPL(aspeed_gpio_copro_set_ops);

/**
 * aspeed_gpio_copro_grab_gpio - Mark a GPIO used by the coprocessor. The entire
 *                               bank gets marked and any access from the ARM will
 *                               result in handshaking via callbacks.
 * @desc: The GPIO to be marked
 * @vreg_offset: If non-NULL, returns the value register offset in the GPIO space
 * @dreg_offset: If non-NULL, returns the data latch register offset in the GPIO space
 * @bit: If non-NULL, returns the bit number of the GPIO in the registers
 */
int aspeed_gpio_copro_grab_gpio(struct gpio_desc *desc,
				u16 *vreg_offset, u16 *dreg_offset, u8 *bit)
{
	struct gpio_chip *chip = gpiod_to_chip(desc);
	struct aspeed_gpio *gpio = gpiochip_get_data(chip);
	int rc = 0, bindex, offset = gpio_chip_hwgpio(desc);
	const struct aspeed_gpio_bank *bank = to_bank(offset);
	unsigned long flags;

	if (!gpio->cf_copro_bankmap)
		gpio->cf_copro_bankmap = kzalloc(gpio->config->nr_gpios >> 3, GFP_KERNEL);
	if (!gpio->cf_copro_bankmap)
		return -ENOMEM;
	if (offset < 0 || offset > gpio->config->nr_gpios)
		return -EINVAL;
	bindex = offset >> 3;

	spin_lock_irqsave(&gpio->lock, flags);

	/* Sanity check, this shouldn't happen */
	if (gpio->cf_copro_bankmap[bindex] == 0xff) {
		rc = -EIO;
		goto bail;
	}
	gpio->cf_copro_bankmap[bindex]++;

	/* Switch command source */
	if (gpio->cf_copro_bankmap[bindex] == 1)
		aspeed_gpio_change_cmd_source(gpio, bank, bindex,
					      GPIO_CMDSRC_COLDFIRE);

	if (vreg_offset)
		*vreg_offset = bank->val_regs;
	if (dreg_offset)
		*dreg_offset = bank->rdata_reg;
	if (bit)
		*bit = GPIO_OFFSET(offset);
 bail:
	spin_unlock_irqrestore(&gpio->lock, flags);
	return rc;
}
EXPORT_SYMBOL_GPL(aspeed_gpio_copro_grab_gpio);

/**
 * aspeed_gpio_copro_release_gpio - Unmark a GPIO used by the coprocessor.
 * @desc: The GPIO to be marked
 */
int aspeed_gpio_copro_release_gpio(struct gpio_desc *desc)
{
	struct gpio_chip *chip = gpiod_to_chip(desc);
	struct aspeed_gpio *gpio = gpiochip_get_data(chip);
	int rc = 0, bindex, offset = gpio_chip_hwgpio(desc);
	const struct aspeed_gpio_bank *bank = to_bank(offset);
	unsigned long flags;

	if (!gpio->cf_copro_bankmap)
		return -ENXIO;

	if (offset < 0 || offset > gpio->config->nr_gpios)
		return -EINVAL;
	bindex = offset >> 3;

	spin_lock_irqsave(&gpio->lock, flags);

	/* Sanity check, this shouldn't happen */
	if (gpio->cf_copro_bankmap[bindex] == 0) {
		rc = -EIO;
		goto bail;
	}
	gpio->cf_copro_bankmap[bindex]--;

	/* Switch command source */
	if (gpio->cf_copro_bankmap[bindex] == 0)
		aspeed_gpio_change_cmd_source(gpio, bank, bindex,
					      GPIO_CMDSRC_ARM);
 bail:
	spin_unlock_irqrestore(&gpio->lock, flags);
	return rc;
}
EXPORT_SYMBOL_GPL(aspeed_gpio_copro_release_gpio);

1118 1119 1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154
/*
 * Any banks not specified in a struct aspeed_bank_props array are assumed to
 * have the properties:
 *
 *     { .input = 0xffffffff, .output = 0xffffffff }
 */

static const struct aspeed_bank_props ast2400_bank_props[] = {
	/*     input	  output   */
	{ 5, 0xffffffff, 0x0000ffff }, /* U/V/W/X */
	{ 6, 0x0000000f, 0x0fffff0f }, /* Y/Z/AA/AB, two 4-GPIO holes */
	{ },
};

static const struct aspeed_gpio_config ast2400_config =
	/* 220 for simplicity, really 216 with two 4-GPIO holes, four at end */
	{ .nr_gpios = 220, .props = ast2400_bank_props, };

static const struct aspeed_bank_props ast2500_bank_props[] = {
	/*     input	  output   */
	{ 5, 0xffffffff, 0x0000ffff }, /* U/V/W/X */
	{ 6, 0x0fffffff, 0x0fffffff }, /* Y/Z/AA/AB, 4-GPIO hole */
	{ 7, 0x000000ff, 0x000000ff }, /* AC */
	{ },
};

static const struct aspeed_gpio_config ast2500_config =
	/* 232 for simplicity, actual number is 228 (4-GPIO hole in GPIOAB) */
	{ .nr_gpios = 232, .props = ast2500_bank_props, };

static const struct of_device_id aspeed_gpio_of_table[] = {
	{ .compatible = "aspeed,ast2400-gpio", .data = &ast2400_config, },
	{ .compatible = "aspeed,ast2500-gpio", .data = &ast2500_config, },
	{}
};
MODULE_DEVICE_TABLE(of, aspeed_gpio_of_table);

Joel Stanley's avatar
Joel Stanley committed
1155 1156
static int __init aspeed_gpio_probe(struct platform_device *pdev)
{
1157
	const struct of_device_id *gpio_id;
Joel Stanley's avatar
Joel Stanley committed
1158 1159
	struct aspeed_gpio *gpio;
	struct resource *res;
1160
	int rc, i, banks;
Joel Stanley's avatar
Joel Stanley committed
1161 1162 1163 1164 1165 1166 1167

	gpio = devm_kzalloc(&pdev->dev, sizeof(*gpio), GFP_KERNEL);
	if (!gpio)
		return -ENOMEM;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	gpio->base = devm_ioremap_resource(&pdev->dev, res);
1168 1169
	if (IS_ERR(gpio->base))
		return PTR_ERR(gpio->base);
Joel Stanley's avatar
Joel Stanley committed
1170 1171 1172

	spin_lock_init(&gpio->lock);

1173 1174 1175 1176
	gpio_id = of_match_node(aspeed_gpio_of_table, pdev->dev.of_node);
	if (!gpio_id)
		return -EINVAL;

1177 1178 1179
	gpio->clk = of_clk_get(pdev->dev.of_node, 0);
	if (IS_ERR(gpio->clk)) {
		dev_warn(&pdev->dev,
1180
				"Failed to get clock from devicetree, debouncing disabled\n");
1181 1182 1183
		gpio->clk = NULL;
	}

1184
	gpio->config = gpio_id->data;
Joel Stanley's avatar
Joel Stanley committed
1185

1186
	gpio->chip.parent = &pdev->dev;
1187
	gpio->chip.ngpio = gpio->config->nr_gpios;
Joel Stanley's avatar
Joel Stanley committed
1188 1189 1190 1191 1192 1193 1194 1195
	gpio->chip.parent = &pdev->dev;
	gpio->chip.direction_input = aspeed_gpio_dir_in;
	gpio->chip.direction_output = aspeed_gpio_dir_out;
	gpio->chip.get_direction = aspeed_gpio_get_direction;
	gpio->chip.request = aspeed_gpio_request;
	gpio->chip.free = aspeed_gpio_free;
	gpio->chip.get = aspeed_gpio_get;
	gpio->chip.set = aspeed_gpio_set;
1196
	gpio->chip.set_config = aspeed_gpio_set_config;
Joel Stanley's avatar
Joel Stanley committed
1197 1198
	gpio->chip.label = dev_name(&pdev->dev);
	gpio->chip.base = -1;
1199
	gpio->chip.irq.need_valid_mask = true;
Joel Stanley's avatar
Joel Stanley committed
1200

1201 1202
	/* Allocate a cache of the output registers */
	banks = gpio->config->nr_gpios >> 5;
1203 1204
	gpio->dcache = devm_kcalloc(&pdev->dev,
				    banks, sizeof(u32), GFP_KERNEL);
1205 1206 1207
	if (!gpio->dcache)
		return -ENOMEM;

1208 1209 1210 1211
	/*
	 * Populate it with initial values read from the HW and switch
	 * all command sources to the ARM by default
	 */
1212
	for (i = 0; i < banks; i++) {
1213 1214
		const struct aspeed_gpio_bank *bank = &aspeed_gpio_banks[i];
		void __iomem *addr = bank_reg(gpio, bank, reg_rdata);
1215
		gpio->dcache[i] = ioread32(addr);
1216 1217 1218 1219
		aspeed_gpio_change_cmd_source(gpio, bank, 0, GPIO_CMDSRC_ARM);
		aspeed_gpio_change_cmd_source(gpio, bank, 1, GPIO_CMDSRC_ARM);
		aspeed_gpio_change_cmd_source(gpio, bank, 2, GPIO_CMDSRC_ARM);
		aspeed_gpio_change_cmd_source(gpio, bank, 3, GPIO_CMDSRC_ARM);
1220 1221
	}

Joel Stanley's avatar
Joel Stanley committed
1222 1223 1224 1225
	rc = devm_gpiochip_add_data(&pdev->dev, &gpio->chip, gpio);
	if (rc < 0)
		return rc;

1226 1227 1228
	gpio->offset_timer =
		devm_kzalloc(&pdev->dev, gpio->chip.ngpio, GFP_KERNEL);

Joel Stanley's avatar
Joel Stanley committed
1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241
	return aspeed_gpio_setup_irqs(gpio, pdev);
}

static struct platform_driver aspeed_gpio_driver = {
	.driver = {
		.name = KBUILD_MODNAME,
		.of_match_table = aspeed_gpio_of_table,
	},
};

module_platform_driver_probe(aspeed_gpio_driver, aspeed_gpio_probe);

MODULE_DESCRIPTION("Aspeed GPIO Driver");
1242
MODULE_LICENSE("GPL");