core.c 14.3 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/slab.h>
M
Magnus Damm 已提交
28

29 30
#include "core.h"

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

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

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

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

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

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

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

	/* Fill them. */
78 79 80 81 82 83 84 85
	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 已提交
86
	}
87 88
	for (i = 0; i < num_irqs; i++)
		*irqs++ = platform_get_irq(pdev, i);
M
Magnus Damm 已提交
89 90 91 92

	return 0;
}

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

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

		if (address < window->phys)
			continue;

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

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

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

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

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

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

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

131
	return -EINVAL;
132 133
}

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

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

	return 1;
}

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

	BUG();
	return 0;
}

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

	BUG();
}

178
static void sh_pfc_config_reg_helper(struct sh_pfc *pfc,
L
Laurent Pinchart 已提交
179
				     const struct pinmux_cfg_reg *crp,
180
				     unsigned int in_pos,
181
				     void __iomem **mapped_regp, u32 *maskp,
182
				     unsigned int *posp)
M
Magnus Damm 已提交
183
{
184
	unsigned int k;
185

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

188 189 190 191 192 193 194 195 196
	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];
	}
197 198
}

199
static void sh_pfc_write_config_reg(struct sh_pfc *pfc,
L
Laurent Pinchart 已提交
200
				    const struct pinmux_cfg_reg *crp,
201
				    unsigned int field, u32 value)
M
Magnus Damm 已提交
202
{
203
	void __iomem *mapped_reg;
204
	unsigned int pos;
205
	u32 mask, data;
M
Magnus Damm 已提交
206

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

209
	dev_dbg(pfc->dev, "write_reg addr = %x, value = 0x%x, field = %u, "
210
		"r_width = %u, f_width = %u\n",
211
		crp->reg, value, field, crp->reg_width, crp->field_width);
M
Magnus Damm 已提交
212 213 214

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

216
	data = sh_pfc_read_raw_reg(mapped_reg, crp->reg_width);
M
Magnus Damm 已提交
217 218 219
	data &= mask;
	data |= value;

220
	if (pfc->info->unlock_reg)
221
		sh_pfc_write_raw_reg(
222
			sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32,
223
			~data);
M
Magnus Damm 已提交
224

225
	sh_pfc_write_raw_reg(mapped_reg, crp->reg_width, data);
M
Magnus Damm 已提交
226 227
}

228
static int sh_pfc_get_config_reg(struct sh_pfc *pfc, u16 enum_id,
229 230
				 const struct pinmux_cfg_reg **crp,
				 unsigned int *fieldp, u32 *valuep)
M
Magnus Damm 已提交
231
{
232
	unsigned int k = 0;
M
Magnus Damm 已提交
233 234

	while (1) {
235 236 237 238 239 240 241 242
		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 已提交
243 244 245

		if (!r_width)
			break;
246 247

		for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
248 249 250
			u32 ncomb;
			u32 n;

251 252 253 254 255 256 257 258 259 260 261 262 263
			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 已提交
264
			}
265 266
			pos += ncomb;
			m++;
M
Magnus Damm 已提交
267 268 269 270
		}
		k++;
	}

271
	return -EINVAL;
M
Magnus Damm 已提交
272 273
}

274 275
static int sh_pfc_mark_to_enum(struct sh_pfc *pfc, u16 mark, int pos,
			      u16 *enum_idp)
M
Magnus Damm 已提交
276
{
277
	const u16 *data = pfc->info->pinmux_data;
278
	unsigned int k;
M
Magnus Damm 已提交
279 280 281 282 283 284

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

285
	for (k = 0; k < pfc->info->pinmux_data_size; k++) {
286
		if (data[k] == mark) {
M
Magnus Damm 已提交
287 288 289 290 291
			*enum_idp = data[k + 1];
			return k + 1;
		}
	}

292 293
	dev_err(pfc->dev, "cannot locate data/mark enum_id for mark %d\n",
		mark);
294
	return -EINVAL;
M
Magnus Damm 已提交
295 296
}

297
int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
M
Magnus Damm 已提交
298
{
L
Laurent Pinchart 已提交
299
	const struct pinmux_range *range;
300
	int pos = 0;
M
Magnus Damm 已提交
301 302

	switch (pinmux_type) {
303
	case PINMUX_TYPE_GPIO:
M
Magnus Damm 已提交
304 305 306 307 308
	case PINMUX_TYPE_FUNCTION:
		range = NULL;
		break;

	case PINMUX_TYPE_OUTPUT:
309
		range = &pfc->info->output;
M
Magnus Damm 已提交
310 311 312
		break;

	case PINMUX_TYPE_INPUT:
313
		range = &pfc->info->input;
M
Magnus Damm 已提交
314 315 316
		break;

	default:
317
		return -EINVAL;
M
Magnus Damm 已提交
318 319
	}

320
	/* Iterate over all the configuration fields we need to update. */
M
Magnus Damm 已提交
321
	while (1) {
322 323 324 325 326 327 328
		const struct pinmux_cfg_reg *cr;
		unsigned int field;
		u16 enum_id;
		u32 value;
		int in_range;
		int ret;

329
		pos = sh_pfc_mark_to_enum(pfc, mark, pos, &enum_id);
330 331
		if (pos < 0)
			return pos;
M
Magnus Damm 已提交
332 333 334 335

		if (!enum_id)
			break;

336 337 338 339
		/* 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.
		 */
340
		in_range = sh_pfc_enum_in_range(enum_id, &pfc->info->function);
341
		if (!in_range) {
342 343 344 345 346 347 348 349
			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.
350
				 */
351
				in_range = sh_pfc_enum_in_range(enum_id, range);
352 353 354 355 356 357 358 359 360

				/*
				 * 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;
			}
361
			/* GPIOs are only allowed to modify function fields. */
362 363
		}

M
Magnus Damm 已提交
364 365 366
		if (!in_range)
			continue;

367 368 369
		ret = sh_pfc_get_config_reg(pfc, enum_id, &cr, &field, &value);
		if (ret < 0)
			return ret;
M
Magnus Damm 已提交
370

371
		sh_pfc_write_config_reg(pfc, cr, field, value);
M
Magnus Damm 已提交
372 373 374 375 376
	}

	return 0;
}

377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
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;
	}

401 402 403 404
	/* 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.
	 */
405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
	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) {
420 421 422 423 424 425 426 427 428
		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;
429 430 431
	}

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

	return 0;
}

L
Laurent Pinchart 已提交
438 439
#ifdef CONFIG_OF
static const struct of_device_id sh_pfc_of_table[] = {
440 441 442 443 444 445
#ifdef CONFIG_PINCTRL_PFC_EMEV2
	{
		.compatible = "renesas,pfc-emev2",
		.data = &emev2_pinmux_info,
	},
#endif
L
Laurent Pinchart 已提交
446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
#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
#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
476 477 478 479 480 481
#ifdef CONFIG_PINCTRL_PFC_R8A7791
	{
		.compatible = "renesas,pfc-r8a7791",
		.data = &r8a7791_pinmux_info,
	},
#endif
482 483 484 485 486 487
#ifdef CONFIG_PINCTRL_PFC_R8A7793
	{
		.compatible = "renesas,pfc-r8a7793",
		.data = &r8a7793_pinmux_info,
	},
#endif
488 489 490 491 492 493
#ifdef CONFIG_PINCTRL_PFC_R8A7794
	{
		.compatible = "renesas,pfc-r8a7794",
		.data = &r8a7794_pinmux_info,
	},
#endif
494 495 496 497 498 499
#ifdef CONFIG_PINCTRL_PFC_R8A7795
	{
		.compatible = "renesas,pfc-r8a7795",
		.data = &r8a7795_pinmux_info,
	},
#endif
L
Laurent Pinchart 已提交
500 501 502 503 504 505 506 507 508 509
#ifdef CONFIG_PINCTRL_PFC_SH73A0
	{
		.compatible = "renesas,pfc-sh73a0",
		.data = &sh73a0_pinmux_info,
	},
#endif
	{ },
};
#endif

510
static int sh_pfc_probe(struct platform_device *pdev)
M
Magnus Damm 已提交
511
{
L
Laurent Pinchart 已提交
512 513 514 515
	const struct platform_device_id *platid = platform_get_device_id(pdev);
#ifdef CONFIG_OF
	struct device_node *np = pdev->dev.of_node;
#endif
L
Laurent Pinchart 已提交
516
	const struct sh_pfc_soc_info *info;
517
	struct sh_pfc *pfc;
M
Magnus Damm 已提交
518
	int ret;
M
Magnus Damm 已提交
519

L
Laurent Pinchart 已提交
520 521
#ifdef CONFIG_OF
	if (np)
522
		info = of_device_get_match_data(&pdev->dev);
L
Laurent Pinchart 已提交
523 524 525 526
	else
#endif
		info = platid ? (const void *)platid->driver_data : NULL;

527
	if (info == NULL)
528
		return -ENODEV;
M
Magnus Damm 已提交
529

530
	pfc = devm_kzalloc(&pdev->dev, sizeof(*pfc), GFP_KERNEL);
531 532
	if (pfc == NULL)
		return -ENOMEM;
533

534
	pfc->info = info;
535 536
	pfc->dev = &pdev->dev;

537
	ret = sh_pfc_map_resources(pfc, pdev);
538
	if (unlikely(ret < 0))
M
Magnus Damm 已提交
539 540
		return ret;

541
	spin_lock_init(&pfc->lock);
M
Magnus Damm 已提交
542

543 544 545 546 547 548
	if (info->ops && info->ops->init) {
		ret = info->ops->init(pfc);
		if (ret < 0)
			return ret;
	}

549 550 551
	/* Enable dummy states for those platforms without pinctrl support */
	if (!of_have_populated_dt())
		pinctrl_provide_dummies();
M
Magnus Damm 已提交
552

553 554 555 556
	ret = sh_pfc_init_ranges(pfc);
	if (ret < 0)
		return ret;

557 558 559
	/*
	 * Initialize pinctrl bindings first
	 */
560
	ret = sh_pfc_register_pinctrl(pfc);
561
	if (unlikely(ret != 0))
562
		return ret;
563

564
#ifdef CONFIG_PINCTRL_SH_PFC_GPIO
565 566 567
	/*
	 * Then the GPIO chip
	 */
568
	ret = sh_pfc_register_gpiochip(pfc);
569
	if (unlikely(ret != 0)) {
570 571 572 573 574
		/*
		 * 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.
		 */
575
		dev_notice(pfc->dev, "failed to init GPIO chip, ignoring...\n");
576
	}
577
#endif
578

579 580
	platform_set_drvdata(pdev, pfc);

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

583
	return 0;
584
}
585

586 587 588 589
static int sh_pfc_remove(struct platform_device *pdev)
{
	struct sh_pfc *pfc = platform_get_drvdata(pdev);

590
#ifdef CONFIG_PINCTRL_SH_PFC_GPIO
591 592 593 594 595 596 597 598
	sh_pfc_unregister_gpiochip(pfc);
#endif
	sh_pfc_unregister_pinctrl(pfc);

	return 0;
}

static const struct platform_device_id sh_pfc_id_table[] = {
599 600 601
#ifdef CONFIG_PINCTRL_PFC_SH7203
	{ "pfc-sh7203", (kernel_ulong_t)&sh7203_pinmux_info },
#endif
602 603 604
#ifdef CONFIG_PINCTRL_PFC_SH7264
	{ "pfc-sh7264", (kernel_ulong_t)&sh7264_pinmux_info },
#endif
605 606 607
#ifdef CONFIG_PINCTRL_PFC_SH7269
	{ "pfc-sh7269", (kernel_ulong_t)&sh7269_pinmux_info },
#endif
608 609
#ifdef CONFIG_PINCTRL_PFC_SH7720
	{ "pfc-sh7720", (kernel_ulong_t)&sh7720_pinmux_info },
610 611 612
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7722
	{ "pfc-sh7722", (kernel_ulong_t)&sh7722_pinmux_info },
613 614 615
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7723
	{ "pfc-sh7723", (kernel_ulong_t)&sh7723_pinmux_info },
616 617 618
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7724
	{ "pfc-sh7724", (kernel_ulong_t)&sh7724_pinmux_info },
619 620 621
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7734
	{ "pfc-sh7734", (kernel_ulong_t)&sh7734_pinmux_info },
622 623 624
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7757
	{ "pfc-sh7757", (kernel_ulong_t)&sh7757_pinmux_info },
625 626 627
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7785
	{ "pfc-sh7785", (kernel_ulong_t)&sh7785_pinmux_info },
628 629 630
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7786
	{ "pfc-sh7786", (kernel_ulong_t)&sh7786_pinmux_info },
631 632 633
#endif
#ifdef CONFIG_PINCTRL_PFC_SHX3
	{ "pfc-shx3", (kernel_ulong_t)&shx3_pinmux_info },
634
#endif
635 636 637 638 639 640 641 642 643 644
	{ "sh-pfc", 0 },
	{ },
};

static struct platform_driver sh_pfc_driver = {
	.probe		= sh_pfc_probe,
	.remove		= sh_pfc_remove,
	.id_table	= sh_pfc_id_table,
	.driver		= {
		.name	= DRV_NAME,
L
Laurent Pinchart 已提交
645
		.of_match_table = of_match_ptr(sh_pfc_of_table),
646 647 648
	},
};

649 650 651
static int __init sh_pfc_init(void)
{
	return platform_driver_register(&sh_pfc_driver);
652
}
653
postcore_initcall(sh_pfc_init);