core.c 14.6 KB
Newer Older
M
Magnus Damm 已提交
1
/*
2
 * SuperH Pin Function Controller support.
M
Magnus Damm 已提交
3 4
 *
 * Copyright (C) 2008 Magnus Damm
5
 * Copyright (C) 2009 - 2012 Paul Mundt
M
Magnus Damm 已提交
6 7 8 9 10
 *
 * 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.
 */
11 12

#define DRV_NAME "sh-pfc"
13

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

27 28
#include "core.h"

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

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

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

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

62 63
	pfc->num_windows = num_windows;
	pfc->windows = windows;
64

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

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

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

	return 0;
}

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

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

		if (address < window->phys)
			continue;

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

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

110
	BUG();
111
	return NULL;
M
Magnus Damm 已提交
112
}
M
Magnus Damm 已提交
113

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

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

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

126
		offset += range->end - range->start + 1;
127 128
	}

129
	return -EINVAL;
130 131
}

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

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

	return 1;
}

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

	BUG();
	return 0;
}

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

	BUG();
}

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

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

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

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

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

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

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

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

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

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

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

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

		if (!r_width)
			break;
244 245

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

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

269
	return -EINVAL;
M
Magnus Damm 已提交
270 271
}

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

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

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

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

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

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

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

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

	default:
315
		return -EINVAL;
M
Magnus Damm 已提交
316 317
	}

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

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

		if (!enum_id)
			break;

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

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

M
Magnus Damm 已提交
362 363 364
		if (!in_range)
			continue;

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

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

	return 0;
}

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

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

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

	return 0;
}

L
Laurent Pinchart 已提交
436 437
#ifdef CONFIG_OF
static const struct of_device_id sh_pfc_of_table[] = {
438 439 440 441 442 443
#ifdef CONFIG_PINCTRL_PFC_EMEV2
	{
		.compatible = "renesas,pfc-emev2",
		.data = &emev2_pinmux_info,
	},
#endif
L
Laurent Pinchart 已提交
444 445 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
#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
474 475 476 477 478 479
#ifdef CONFIG_PINCTRL_PFC_R8A7791
	{
		.compatible = "renesas,pfc-r8a7791",
		.data = &r8a7791_pinmux_info,
	},
#endif
480 481 482 483 484 485
#ifdef CONFIG_PINCTRL_PFC_R8A7793
	{
		.compatible = "renesas,pfc-r8a7793",
		.data = &r8a7793_pinmux_info,
	},
#endif
486 487 488 489 490 491
#ifdef CONFIG_PINCTRL_PFC_R8A7794
	{
		.compatible = "renesas,pfc-r8a7794",
		.data = &r8a7794_pinmux_info,
	},
#endif
492 493 494 495 496 497
#ifdef CONFIG_PINCTRL_PFC_R8A7795
	{
		.compatible = "renesas,pfc-r8a7795",
		.data = &r8a7795_pinmux_info,
	},
#endif
L
Laurent Pinchart 已提交
498 499 500 501 502 503 504 505 506 507 508
#ifdef CONFIG_PINCTRL_PFC_SH73A0
	{
		.compatible = "renesas,pfc-sh73a0",
		.data = &sh73a0_pinmux_info,
	},
#endif
	{ },
};
MODULE_DEVICE_TABLE(of, sh_pfc_of_table);
#endif

509
static int sh_pfc_probe(struct platform_device *pdev)
M
Magnus Damm 已提交
510
{
L
Laurent Pinchart 已提交
511 512 513 514
	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 已提交
515
	const struct sh_pfc_soc_info *info;
516
	struct sh_pfc *pfc;
M
Magnus Damm 已提交
517
	int ret;
M
Magnus Damm 已提交
518

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

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

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

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

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

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

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

548
	pinctrl_provide_dummies();
M
Magnus Damm 已提交
549

550 551 552 553
	ret = sh_pfc_init_ranges(pfc);
	if (ret < 0)
		return ret;

554 555 556
	/*
	 * Initialize pinctrl bindings first
	 */
557
	ret = sh_pfc_register_pinctrl(pfc);
558
	if (unlikely(ret != 0))
559
		return ret;
560

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

576 577
	platform_set_drvdata(pdev, pfc);

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

580
	return 0;
581
}
582

583 584 585 586 587 588 589 590 591 592 593 594 595
static int sh_pfc_remove(struct platform_device *pdev)
{
	struct sh_pfc *pfc = platform_get_drvdata(pdev);

#ifdef CONFIG_GPIO_SH_PFC
	sh_pfc_unregister_gpiochip(pfc);
#endif
	sh_pfc_unregister_pinctrl(pfc);

	return 0;
}

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

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 已提交
649
		.of_match_table = of_match_ptr(sh_pfc_of_table),
650 651 652
	},
};

653 654 655
static int __init sh_pfc_init(void)
{
	return platform_driver_register(&sh_pfc_driver);
656
}
657
postcore_initcall(sh_pfc_init);
658 659 660 661 662 663 664

static void __exit sh_pfc_exit(void)
{
	platform_driver_unregister(&sh_pfc_driver);
}
module_exit(sh_pfc_exit);

665 666 667
MODULE_AUTHOR("Magnus Damm, Paul Mundt, Laurent Pinchart");
MODULE_DESCRIPTION("Pin Control and GPIO driver for SuperH pin function controller");
MODULE_LICENSE("GPL v2");