core.c 18.0 KB
Newer Older
M
Magnus Damm 已提交
1
/*
2 3 4
 * Pin Control and GPIO driver for SuperH Pin Function Controller.
 *
 * Authors: Magnus Damm, Paul Mundt, Laurent Pinchart
M
Magnus Damm 已提交
5 6
 *
 * Copyright (C) 2008 Magnus Damm
7
 * Copyright (C) 2009 - 2012 Paul Mundt
M
Magnus Damm 已提交
8 9 10 11 12
 *
 * This file is subject to the terms and conditions of the GNU General Public
 * License.  See the file "COPYING" in the main directory of this archive
 * for more details.
 */
13 14

#define DRV_NAME "sh-pfc"
15

16
#include <linux/bitops.h>
M
Magnus Damm 已提交
17
#include <linux/err.h>
18
#include <linux/errno.h>
M
Magnus Damm 已提交
19
#include <linux/io.h>
M
Magnus Damm 已提交
20
#include <linux/ioport.h>
21
#include <linux/kernel.h>
22
#include <linux/init.h>
L
Laurent Pinchart 已提交
23 24
#include <linux/of.h>
#include <linux/of_device.h>
25
#include <linux/pinctrl/machine.h>
26
#include <linux/platform_device.h>
27
#include <linux/psci.h>
28
#include <linux/slab.h>
M
Magnus Damm 已提交
29

30 31
#include "core.h"

32 33
static int sh_pfc_map_resources(struct sh_pfc *pfc,
				struct platform_device *pdev)
M
Magnus Damm 已提交
34
{
35
	unsigned int num_windows, num_irqs;
36 37
	struct sh_pfc_window *windows;
	unsigned int *irqs = NULL;
M
Magnus Damm 已提交
38
	struct resource *res;
39
	unsigned int i;
40
	int irq;
41 42

	/* Count the MEM and IRQ resources. */
43 44 45
	for (num_windows = 0;; num_windows++) {
		res = platform_get_resource(pdev, IORESOURCE_MEM, num_windows);
		if (!res)
46
			break;
47 48 49 50 51 52
	}
	for (num_irqs = 0;; num_irqs++) {
		irq = platform_get_irq(pdev, num_irqs);
		if (irq == -EPROBE_DEFER)
			return irq;
		if (irq < 0)
53 54
			break;
	}
M
Magnus Damm 已提交
55

56
	if (num_windows == 0)
57
		return -EINVAL;
M
Magnus Damm 已提交
58

59 60 61 62
	/* Allocate memory windows and IRQs arrays. */
	windows = devm_kzalloc(pfc->dev, num_windows * sizeof(*windows),
			       GFP_KERNEL);
	if (windows == NULL)
L
Laurent Pinchart 已提交
63
		return -ENOMEM;
M
Magnus Damm 已提交
64

65 66
	pfc->num_windows = num_windows;
	pfc->windows = windows;
67

68 69 70 71
	if (num_irqs) {
		irqs = devm_kzalloc(pfc->dev, num_irqs * sizeof(*irqs),
				    GFP_KERNEL);
		if (irqs == NULL)
L
Laurent Pinchart 已提交
72
			return -ENOMEM;
73 74 75 76 77 78

		pfc->num_irqs = num_irqs;
		pfc->irqs = irqs;
	}

	/* Fill them. */
79 80 81 82 83 84 85 86
	for (i = 0; i < num_windows; i++) {
		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
		windows->phys = res->start;
		windows->size = resource_size(res);
		windows->virt = devm_ioremap_resource(pfc->dev, res);
		if (IS_ERR(windows->virt))
			return -ENOMEM;
		windows++;
M
Magnus Damm 已提交
87
	}
88 89
	for (i = 0; i < num_irqs; i++)
		*irqs++ = platform_get_irq(pdev, i);
M
Magnus Damm 已提交
90 91 92 93

	return 0;
}

94
static void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc, u32 reg)
M
Magnus Damm 已提交
95
{
96
	struct sh_pfc_window *window;
97
	phys_addr_t address = reg;
98
	unsigned int i;
M
Magnus Damm 已提交
99 100

	/* scan through physical windows and convert address */
101
	for (i = 0; i < pfc->num_windows; i++) {
102
		window = pfc->windows + i;
M
Magnus Damm 已提交
103 104 105 106 107 108 109 110 111 112

		if (address < window->phys)
			continue;

		if (address >= (window->phys + window->size))
			continue;

		return window->virt + (address - window->phys);
	}

113
	BUG();
114
	return NULL;
M
Magnus Damm 已提交
115
}
M
Magnus Damm 已提交
116

117
int sh_pfc_get_pin_index(struct sh_pfc *pfc, unsigned int pin)
118
{
119 120 121
	unsigned int offset;
	unsigned int i;

122 123
	for (i = 0, offset = 0; i < pfc->nr_ranges; ++i) {
		const struct sh_pfc_pin_range *range = &pfc->ranges[i];
124 125

		if (pin <= range->end)
126 127
			return pin >= range->start
			     ? offset + pin - range->start : -1;
128

129
		offset += range->end - range->start + 1;
130 131
	}

132
	return -EINVAL;
133 134
}

135
static int sh_pfc_enum_in_range(u16 enum_id, const struct pinmux_range *r)
M
Magnus Damm 已提交
136 137 138 139 140 141 142 143 144 145
{
	if (enum_id < r->begin)
		return 0;

	if (enum_id > r->end)
		return 0;

	return 1;
}

146
u32 sh_pfc_read_raw_reg(void __iomem *mapped_reg, unsigned int reg_width)
M
Magnus Damm 已提交
147 148 149
{
	switch (reg_width) {
	case 8:
M
Magnus Damm 已提交
150
		return ioread8(mapped_reg);
M
Magnus Damm 已提交
151
	case 16:
M
Magnus Damm 已提交
152
		return ioread16(mapped_reg);
M
Magnus Damm 已提交
153
	case 32:
M
Magnus Damm 已提交
154
		return ioread32(mapped_reg);
M
Magnus Damm 已提交
155 156 157 158 159 160
	}

	BUG();
	return 0;
}

161
void sh_pfc_write_raw_reg(void __iomem *mapped_reg, unsigned int reg_width,
162
			  u32 data)
M
Magnus Damm 已提交
163 164 165
{
	switch (reg_width) {
	case 8:
M
Magnus Damm 已提交
166
		iowrite8(data, mapped_reg);
M
Magnus Damm 已提交
167 168
		return;
	case 16:
M
Magnus Damm 已提交
169
		iowrite16(data, mapped_reg);
M
Magnus Damm 已提交
170 171
		return;
	case 32:
M
Magnus Damm 已提交
172
		iowrite32(data, mapped_reg);
M
Magnus Damm 已提交
173 174 175 176 177 178
		return;
	}

	BUG();
}

179
u32 sh_pfc_read(struct sh_pfc *pfc, u32 reg)
180
{
181
	return sh_pfc_read_raw_reg(sh_pfc_phys_to_virt(pfc, reg), 32);
182 183
}

184
void sh_pfc_write(struct sh_pfc *pfc, u32 reg, u32 data)
185 186 187 188 189 190
{
	if (pfc->info->unlock_reg)
		sh_pfc_write_raw_reg(
			sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32,
			~data);

191
	sh_pfc_write_raw_reg(sh_pfc_phys_to_virt(pfc, reg), 32, data);
192 193
}

194
static void sh_pfc_config_reg_helper(struct sh_pfc *pfc,
L
Laurent Pinchart 已提交
195
				     const struct pinmux_cfg_reg *crp,
196
				     unsigned int in_pos,
197
				     void __iomem **mapped_regp, u32 *maskp,
198
				     unsigned int *posp)
M
Magnus Damm 已提交
199
{
200
	unsigned int k;
201

202
	*mapped_regp = sh_pfc_phys_to_virt(pfc, crp->reg);
M
Magnus Damm 已提交
203

204 205 206 207 208 209 210 211 212
	if (crp->field_width) {
		*maskp = (1 << crp->field_width) - 1;
		*posp = crp->reg_width - ((in_pos + 1) * crp->field_width);
	} else {
		*maskp = (1 << crp->var_field_width[in_pos]) - 1;
		*posp = crp->reg_width;
		for (k = 0; k <= in_pos; k++)
			*posp -= crp->var_field_width[k];
	}
213 214
}

215
static void sh_pfc_write_config_reg(struct sh_pfc *pfc,
L
Laurent Pinchart 已提交
216
				    const struct pinmux_cfg_reg *crp,
217
				    unsigned int field, u32 value)
M
Magnus Damm 已提交
218
{
219
	void __iomem *mapped_reg;
220
	unsigned int pos;
221
	u32 mask, data;
M
Magnus Damm 已提交
222

223
	sh_pfc_config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos);
M
Magnus Damm 已提交
224

225
	dev_dbg(pfc->dev, "write_reg addr = %x, value = 0x%x, field = %u, "
226
		"r_width = %u, f_width = %u\n",
227
		crp->reg, value, field, crp->reg_width, crp->field_width);
M
Magnus Damm 已提交
228 229 230

	mask = ~(mask << pos);
	value = value << pos;
M
Magnus Damm 已提交
231

232
	data = sh_pfc_read_raw_reg(mapped_reg, crp->reg_width);
M
Magnus Damm 已提交
233 234 235
	data &= mask;
	data |= value;

236
	if (pfc->info->unlock_reg)
237
		sh_pfc_write_raw_reg(
238
			sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32,
239
			~data);
M
Magnus Damm 已提交
240

241
	sh_pfc_write_raw_reg(mapped_reg, crp->reg_width, data);
M
Magnus Damm 已提交
242 243
}

244
static int sh_pfc_get_config_reg(struct sh_pfc *pfc, u16 enum_id,
245 246
				 const struct pinmux_cfg_reg **crp,
				 unsigned int *fieldp, u32 *valuep)
M
Magnus Damm 已提交
247
{
248
	unsigned int k = 0;
M
Magnus Damm 已提交
249 250

	while (1) {
251 252 253 254 255 256 257 258
		const struct pinmux_cfg_reg *config_reg =
			pfc->info->cfg_regs + k;
		unsigned int r_width = config_reg->reg_width;
		unsigned int f_width = config_reg->field_width;
		unsigned int curr_width;
		unsigned int bit_pos;
		unsigned int pos = 0;
		unsigned int m = 0;
M
Magnus Damm 已提交
259 260 261

		if (!r_width)
			break;
262 263

		for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
264 265 266
			u32 ncomb;
			u32 n;

267 268 269 270 271 272 273 274 275 276 277 278 279
			if (f_width)
				curr_width = f_width;
			else
				curr_width = config_reg->var_field_width[m];

			ncomb = 1 << curr_width;
			for (n = 0; n < ncomb; n++) {
				if (config_reg->enum_ids[pos + n] == enum_id) {
					*crp = config_reg;
					*fieldp = m;
					*valuep = n;
					return 0;
				}
M
Magnus Damm 已提交
280
			}
281 282
			pos += ncomb;
			m++;
M
Magnus Damm 已提交
283 284 285 286
		}
		k++;
	}

287
	return -EINVAL;
M
Magnus Damm 已提交
288 289
}

290 291
static int sh_pfc_mark_to_enum(struct sh_pfc *pfc, u16 mark, int pos,
			      u16 *enum_idp)
M
Magnus Damm 已提交
292
{
293
	const u16 *data = pfc->info->pinmux_data;
294
	unsigned int k;
M
Magnus Damm 已提交
295 296 297 298 299 300

	if (pos) {
		*enum_idp = data[pos + 1];
		return pos + 1;
	}

301
	for (k = 0; k < pfc->info->pinmux_data_size; k++) {
302
		if (data[k] == mark) {
M
Magnus Damm 已提交
303 304 305 306 307
			*enum_idp = data[k + 1];
			return k + 1;
		}
	}

308 309
	dev_err(pfc->dev, "cannot locate data/mark enum_id for mark %d\n",
		mark);
310
	return -EINVAL;
M
Magnus Damm 已提交
311 312
}

313
int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
M
Magnus Damm 已提交
314
{
L
Laurent Pinchart 已提交
315
	const struct pinmux_range *range;
316
	int pos = 0;
M
Magnus Damm 已提交
317 318

	switch (pinmux_type) {
319
	case PINMUX_TYPE_GPIO:
M
Magnus Damm 已提交
320 321 322 323 324
	case PINMUX_TYPE_FUNCTION:
		range = NULL;
		break;

	case PINMUX_TYPE_OUTPUT:
325
		range = &pfc->info->output;
M
Magnus Damm 已提交
326 327 328
		break;

	case PINMUX_TYPE_INPUT:
329
		range = &pfc->info->input;
M
Magnus Damm 已提交
330 331 332
		break;

	default:
333
		return -EINVAL;
M
Magnus Damm 已提交
334 335
	}

336
	/* Iterate over all the configuration fields we need to update. */
M
Magnus Damm 已提交
337
	while (1) {
338 339 340 341 342 343 344
		const struct pinmux_cfg_reg *cr;
		unsigned int field;
		u16 enum_id;
		u32 value;
		int in_range;
		int ret;

345
		pos = sh_pfc_mark_to_enum(pfc, mark, pos, &enum_id);
346 347
		if (pos < 0)
			return pos;
M
Magnus Damm 已提交
348 349 350 351

		if (!enum_id)
			break;

352 353 354 355
		/* Check if the configuration field selects a function. If it
		 * doesn't, skip the field if it's not applicable to the
		 * requested pinmux type.
		 */
356
		in_range = sh_pfc_enum_in_range(enum_id, &pfc->info->function);
357
		if (!in_range) {
358 359 360 361 362 363 364 365
			if (pinmux_type == PINMUX_TYPE_FUNCTION) {
				/* Functions are allowed to modify all
				 * fields.
				 */
				in_range = 1;
			} else if (pinmux_type != PINMUX_TYPE_GPIO) {
				/* Input/output types can only modify fields
				 * that correspond to their respective ranges.
366
				 */
367
				in_range = sh_pfc_enum_in_range(enum_id, range);
368 369 370 371 372 373 374 375 376

				/*
				 * special case pass through for fixed
				 * input-only or output-only pins without
				 * function enum register association.
				 */
				if (in_range && enum_id == range->force)
					continue;
			}
377
			/* GPIOs are only allowed to modify function fields. */
378 379
		}

M
Magnus Damm 已提交
380 381 382
		if (!in_range)
			continue;

383 384 385
		ret = sh_pfc_get_config_reg(pfc, enum_id, &cr, &field, &value);
		if (ret < 0)
			return ret;
M
Magnus Damm 已提交
386

387
		sh_pfc_write_config_reg(pfc, cr, field, value);
M
Magnus Damm 已提交
388 389 390 391 392
	}

	return 0;
}

393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412
const struct pinmux_bias_reg *
sh_pfc_pin_to_bias_reg(const struct sh_pfc *pfc, unsigned int pin,
		       unsigned int *bit)
{
	unsigned int i, j;

	for (i = 0; pfc->info->bias_regs[i].puen; i++) {
		for (j = 0; j < ARRAY_SIZE(pfc->info->bias_regs[i].pins); j++) {
			if (pfc->info->bias_regs[i].pins[j] == pin) {
				*bit = j;
				return &pfc->info->bias_regs[i];
			}
		}
	}

	WARN_ONCE(1, "Pin %u is not in bias info list\n", pin);

	return NULL;
}

413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436
static int sh_pfc_init_ranges(struct sh_pfc *pfc)
{
	struct sh_pfc_pin_range *range;
	unsigned int nr_ranges;
	unsigned int i;

	if (pfc->info->pins[0].pin == (u16)-1) {
		/* Pin number -1 denotes that the SoC doesn't report pin numbers
		 * in its pin arrays yet. Consider the pin numbers range as
		 * continuous and allocate a single range.
		 */
		pfc->nr_ranges = 1;
		pfc->ranges = devm_kzalloc(pfc->dev, sizeof(*pfc->ranges),
					   GFP_KERNEL);
		if (pfc->ranges == NULL)
			return -ENOMEM;

		pfc->ranges->start = 0;
		pfc->ranges->end = pfc->info->nr_pins - 1;
		pfc->nr_gpio_pins = pfc->info->nr_pins;

		return 0;
	}

437 438 439 440
	/* Count, allocate and fill the ranges. The PFC SoC data pins array must
	 * be sorted by pin numbers, and pins without a GPIO port must come
	 * last.
	 */
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455
	for (i = 1, nr_ranges = 1; i < pfc->info->nr_pins; ++i) {
		if (pfc->info->pins[i-1].pin != pfc->info->pins[i].pin - 1)
			nr_ranges++;
	}

	pfc->nr_ranges = nr_ranges;
	pfc->ranges = devm_kzalloc(pfc->dev, sizeof(*pfc->ranges) * nr_ranges,
				   GFP_KERNEL);
	if (pfc->ranges == NULL)
		return -ENOMEM;

	range = pfc->ranges;
	range->start = pfc->info->pins[0].pin;

	for (i = 1; i < pfc->info->nr_pins; ++i) {
456 457 458 459 460 461 462 463 464
		if (pfc->info->pins[i-1].pin == pfc->info->pins[i].pin - 1)
			continue;

		range->end = pfc->info->pins[i-1].pin;
		if (!(pfc->info->pins[i-1].configs & SH_PFC_PIN_CFG_NO_GPIO))
			pfc->nr_gpio_pins = range->end + 1;

		range++;
		range->start = pfc->info->pins[i].pin;
465 466 467
	}

	range->end = pfc->info->pins[i-1].pin;
468 469
	if (!(pfc->info->pins[i-1].configs & SH_PFC_PIN_CFG_NO_GPIO))
		pfc->nr_gpio_pins = range->end + 1;
470 471 472 473

	return 0;
}

L
Laurent Pinchart 已提交
474 475
#ifdef CONFIG_OF
static const struct of_device_id sh_pfc_of_table[] = {
476 477 478 479 480 481
#ifdef CONFIG_PINCTRL_PFC_EMEV2
	{
		.compatible = "renesas,pfc-emev2",
		.data = &emev2_pinmux_info,
	},
#endif
L
Laurent Pinchart 已提交
482 483 484 485 486 487 488 489 490 491 492 493
#ifdef CONFIG_PINCTRL_PFC_R8A73A4
	{
		.compatible = "renesas,pfc-r8a73a4",
		.data = &r8a73a4_pinmux_info,
	},
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A7740
	{
		.compatible = "renesas,pfc-r8a7740",
		.data = &r8a7740_pinmux_info,
	},
#endif
494 495 496 497 498 499
#ifdef CONFIG_PINCTRL_PFC_R8A7743
	{
		.compatible = "renesas,pfc-r8a7743",
		.data = &r8a7743_pinmux_info,
	},
#endif
500 501 502 503 504 505
#ifdef CONFIG_PINCTRL_PFC_R8A7745
	{
		.compatible = "renesas,pfc-r8a7745",
		.data = &r8a7745_pinmux_info,
	},
#endif
L
Laurent Pinchart 已提交
506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523
#ifdef CONFIG_PINCTRL_PFC_R8A7778
	{
		.compatible = "renesas,pfc-r8a7778",
		.data = &r8a7778_pinmux_info,
	},
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A7779
	{
		.compatible = "renesas,pfc-r8a7779",
		.data = &r8a7779_pinmux_info,
	},
#endif
#ifdef CONFIG_PINCTRL_PFC_R8A7790
	{
		.compatible = "renesas,pfc-r8a7790",
		.data = &r8a7790_pinmux_info,
	},
#endif
524 525 526 527 528 529
#ifdef CONFIG_PINCTRL_PFC_R8A7791
	{
		.compatible = "renesas,pfc-r8a7791",
		.data = &r8a7791_pinmux_info,
	},
#endif
530 531 532 533 534 535
#ifdef CONFIG_PINCTRL_PFC_R8A7792
	{
		.compatible = "renesas,pfc-r8a7792",
		.data = &r8a7792_pinmux_info,
	},
#endif
536 537 538 539 540 541
#ifdef CONFIG_PINCTRL_PFC_R8A7793
	{
		.compatible = "renesas,pfc-r8a7793",
		.data = &r8a7793_pinmux_info,
	},
#endif
542 543 544 545 546 547
#ifdef CONFIG_PINCTRL_PFC_R8A7794
	{
		.compatible = "renesas,pfc-r8a7794",
		.data = &r8a7794_pinmux_info,
	},
#endif
548 549 550 551 552 553
#ifdef CONFIG_PINCTRL_PFC_R8A7795
	{
		.compatible = "renesas,pfc-r8a7795",
		.data = &r8a7795_pinmux_info,
	},
#endif
554 555 556 557 558 559
#ifdef CONFIG_PINCTRL_PFC_R8A7796
	{
		.compatible = "renesas,pfc-r8a7796",
		.data = &r8a7796_pinmux_info,
	},
#endif
560 561 562 563 564 565
#ifdef CONFIG_PINCTRL_PFC_R8A77965
	{
		.compatible = "renesas,pfc-r8a77965",
		.data = &r8a77965_pinmux_info,
	},
#endif
566 567 568 569 570 571
#ifdef CONFIG_PINCTRL_PFC_R8A77970
	{
		.compatible = "renesas,pfc-r8a77970",
		.data = &r8a77970_pinmux_info,
	},
#endif
572 573 574 575 576 577
#ifdef CONFIG_PINCTRL_PFC_R8A77980
	{
		.compatible = "renesas,pfc-r8a77980",
		.data = &r8a77980_pinmux_info,
	},
#endif
578 579 580 581 582 583
#ifdef CONFIG_PINCTRL_PFC_R8A77995
	{
		.compatible = "renesas,pfc-r8a77995",
		.data = &r8a77995_pinmux_info,
	},
#endif
L
Laurent Pinchart 已提交
584 585 586 587 588 589 590 591 592 593
#ifdef CONFIG_PINCTRL_PFC_SH73A0
	{
		.compatible = "renesas,pfc-sh73a0",
		.data = &sh73a0_pinmux_info,
	},
#endif
	{ },
};
#endif

594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684
#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_ARM_PSCI_FW)
static void sh_pfc_nop_reg(struct sh_pfc *pfc, u32 reg, unsigned int idx)
{
}

static void sh_pfc_save_reg(struct sh_pfc *pfc, u32 reg, unsigned int idx)
{
	pfc->saved_regs[idx] = sh_pfc_read(pfc, reg);
}

static void sh_pfc_restore_reg(struct sh_pfc *pfc, u32 reg, unsigned int idx)
{
	sh_pfc_write(pfc, reg, pfc->saved_regs[idx]);
}

static unsigned int sh_pfc_walk_regs(struct sh_pfc *pfc,
	void (*do_reg)(struct sh_pfc *pfc, u32 reg, unsigned int idx))
{
	unsigned int i, n = 0;

	if (pfc->info->cfg_regs)
		for (i = 0; pfc->info->cfg_regs[i].reg; i++)
			do_reg(pfc, pfc->info->cfg_regs[i].reg, n++);

	if (pfc->info->drive_regs)
		for (i = 0; pfc->info->drive_regs[i].reg; i++)
			do_reg(pfc, pfc->info->drive_regs[i].reg, n++);

	if (pfc->info->bias_regs)
		for (i = 0; pfc->info->bias_regs[i].puen; i++) {
			do_reg(pfc, pfc->info->bias_regs[i].puen, n++);
			if (pfc->info->bias_regs[i].pud)
				do_reg(pfc, pfc->info->bias_regs[i].pud, n++);
		}

	if (pfc->info->ioctrl_regs)
		for (i = 0; pfc->info->ioctrl_regs[i].reg; i++)
			do_reg(pfc, pfc->info->ioctrl_regs[i].reg, n++);

	return n;
}

static int sh_pfc_suspend_init(struct sh_pfc *pfc)
{
	unsigned int n;

	/* This is the best we can do to check for the presence of PSCI */
	if (!psci_ops.cpu_suspend)
		return 0;

	n = sh_pfc_walk_regs(pfc, sh_pfc_nop_reg);
	if (!n)
		return 0;

	pfc->saved_regs = devm_kmalloc_array(pfc->dev, n,
					     sizeof(*pfc->saved_regs),
					     GFP_KERNEL);
	if (!pfc->saved_regs)
		return -ENOMEM;

	dev_dbg(pfc->dev, "Allocated space to save %u regs\n", n);
	return 0;
}

static int sh_pfc_suspend_noirq(struct device *dev)
{
	struct sh_pfc *pfc = dev_get_drvdata(dev);

	if (pfc->saved_regs)
		sh_pfc_walk_regs(pfc, sh_pfc_save_reg);
	return 0;
}

static int sh_pfc_resume_noirq(struct device *dev)
{
	struct sh_pfc *pfc = dev_get_drvdata(dev);

	if (pfc->saved_regs)
		sh_pfc_walk_regs(pfc, sh_pfc_restore_reg);
	return 0;
}

static const struct dev_pm_ops sh_pfc_pm  = {
	SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(sh_pfc_suspend_noirq, sh_pfc_resume_noirq)
};
#define DEV_PM_OPS	&sh_pfc_pm
#else
static int sh_pfc_suspend_init(struct sh_pfc *pfc) { return 0; }
#define DEV_PM_OPS	NULL
#endif /* CONFIG_PM_SLEEP && CONFIG_ARM_PSCI_FW */

685
static int sh_pfc_probe(struct platform_device *pdev)
M
Magnus Damm 已提交
686
{
L
Laurent Pinchart 已提交
687 688 689
#ifdef CONFIG_OF
	struct device_node *np = pdev->dev.of_node;
#endif
L
Laurent Pinchart 已提交
690
	const struct sh_pfc_soc_info *info;
691
	struct sh_pfc *pfc;
M
Magnus Damm 已提交
692
	int ret;
M
Magnus Damm 已提交
693

L
Laurent Pinchart 已提交
694 695
#ifdef CONFIG_OF
	if (np)
696
		info = of_device_get_match_data(&pdev->dev);
L
Laurent Pinchart 已提交
697 698
	else
#endif
699
		info = (const void *)platform_get_device_id(pdev)->driver_data;
M
Magnus Damm 已提交
700

701
	pfc = devm_kzalloc(&pdev->dev, sizeof(*pfc), GFP_KERNEL);
702 703
	if (pfc == NULL)
		return -ENOMEM;
704

705
	pfc->info = info;
706 707
	pfc->dev = &pdev->dev;

708
	ret = sh_pfc_map_resources(pfc, pdev);
709
	if (unlikely(ret < 0))
M
Magnus Damm 已提交
710 711
		return ret;

712
	spin_lock_init(&pfc->lock);
M
Magnus Damm 已提交
713

714 715 716 717
	if (info->ops && info->ops->init) {
		ret = info->ops->init(pfc);
		if (ret < 0)
			return ret;
718 719 720

		/* .init() may have overridden pfc->info */
		info = pfc->info;
721 722
	}

723 724 725 726
	ret = sh_pfc_suspend_init(pfc);
	if (ret)
		return ret;

727 728 729
	/* Enable dummy states for those platforms without pinctrl support */
	if (!of_have_populated_dt())
		pinctrl_provide_dummies();
M
Magnus Damm 已提交
730

731 732 733 734
	ret = sh_pfc_init_ranges(pfc);
	if (ret < 0)
		return ret;

735 736 737
	/*
	 * Initialize pinctrl bindings first
	 */
738
	ret = sh_pfc_register_pinctrl(pfc);
739
	if (unlikely(ret != 0))
740
		return ret;
741

742
#ifdef CONFIG_PINCTRL_SH_PFC_GPIO
743 744 745
	/*
	 * Then the GPIO chip
	 */
746
	ret = sh_pfc_register_gpiochip(pfc);
747
	if (unlikely(ret != 0)) {
748 749 750 751 752
		/*
		 * If the GPIO chip fails to come up we still leave the
		 * PFC state as it is, given that there are already
		 * extant users of it that have succeeded by this point.
		 */
753
		dev_notice(pfc->dev, "failed to init GPIO chip, ignoring...\n");
754
	}
755
#endif
756

757 758
	platform_set_drvdata(pdev, pfc);

759
	dev_info(pfc->dev, "%s support registered\n", info->name);
760

761
	return 0;
762
}
763

764
static const struct platform_device_id sh_pfc_id_table[] = {
765 766 767
#ifdef CONFIG_PINCTRL_PFC_SH7203
	{ "pfc-sh7203", (kernel_ulong_t)&sh7203_pinmux_info },
#endif
768 769 770
#ifdef CONFIG_PINCTRL_PFC_SH7264
	{ "pfc-sh7264", (kernel_ulong_t)&sh7264_pinmux_info },
#endif
771 772 773
#ifdef CONFIG_PINCTRL_PFC_SH7269
	{ "pfc-sh7269", (kernel_ulong_t)&sh7269_pinmux_info },
#endif
774 775
#ifdef CONFIG_PINCTRL_PFC_SH7720
	{ "pfc-sh7720", (kernel_ulong_t)&sh7720_pinmux_info },
776 777 778
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7722
	{ "pfc-sh7722", (kernel_ulong_t)&sh7722_pinmux_info },
779 780 781
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7723
	{ "pfc-sh7723", (kernel_ulong_t)&sh7723_pinmux_info },
782 783 784
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7724
	{ "pfc-sh7724", (kernel_ulong_t)&sh7724_pinmux_info },
785 786 787
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7734
	{ "pfc-sh7734", (kernel_ulong_t)&sh7734_pinmux_info },
788 789 790
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7757
	{ "pfc-sh7757", (kernel_ulong_t)&sh7757_pinmux_info },
791 792 793
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7785
	{ "pfc-sh7785", (kernel_ulong_t)&sh7785_pinmux_info },
794 795 796
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7786
	{ "pfc-sh7786", (kernel_ulong_t)&sh7786_pinmux_info },
797 798 799
#endif
#ifdef CONFIG_PINCTRL_PFC_SHX3
	{ "pfc-shx3", (kernel_ulong_t)&shx3_pinmux_info },
800
#endif
801 802 803 804 805 806 807 808
	{ },
};

static struct platform_driver sh_pfc_driver = {
	.probe		= sh_pfc_probe,
	.id_table	= sh_pfc_id_table,
	.driver		= {
		.name	= DRV_NAME,
L
Laurent Pinchart 已提交
809
		.of_match_table = of_match_ptr(sh_pfc_of_table),
810
		.pm     = DEV_PM_OPS,
811 812 813
	},
};

814 815 816
static int __init sh_pfc_init(void)
{
	return platform_driver_register(&sh_pfc_driver);
817
}
818
postcore_initcall(sh_pfc_init);