core.c 14.6 KB
Newer Older
Magnus Damm's avatar
Magnus Damm committed
1
/*
2
 * SuperH Pin Function Controller support.
Magnus Damm's avatar
Magnus Damm committed
3 4
 *
 * Copyright (C) 2008 Magnus Damm
5
 * Copyright (C) 2009 - 2012 Paul Mundt
Magnus Damm's avatar
Magnus Damm committed
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>
Magnus Damm's avatar
Magnus Damm committed
15
#include <linux/err.h>
16
#include <linux/errno.h>
Magnus Damm's avatar
Magnus Damm committed
17
#include <linux/io.h>
Magnus Damm's avatar
Magnus Damm committed
18
#include <linux/ioport.h>
19 20
#include <linux/kernel.h>
#include <linux/module.h>
Laurent Pinchart's avatar
Laurent Pinchart committed
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>
Magnus Damm's avatar
Magnus Damm committed
26

27 28
#include "core.h"

29 30
static int sh_pfc_map_resources(struct sh_pfc *pfc,
				struct platform_device *pdev)
Magnus Damm's avatar
Magnus Damm committed
31
{
32 33 34 35
	unsigned int num_windows = 0;
	unsigned int num_irqs = 0;
	struct sh_pfc_window *windows;
	unsigned int *irqs = NULL;
Magnus Damm's avatar
Magnus Damm committed
36
	struct resource *res;
37 38 39 40 41 42 43 44 45 46 47 48 49 50
	unsigned int i;

	/* Count the MEM and IRQ resources. */
	for (i = 0; i < pdev->num_resources; ++i) {
		switch (resource_type(&pdev->resource[i])) {
		case IORESOURCE_MEM:
			num_windows++;
			break;

		case IORESOURCE_IRQ:
			num_irqs++;
			break;
		}
	}
Magnus Damm's avatar
Magnus Damm committed
51

52
	if (num_windows == 0)
53
		return -EINVAL;
Magnus Damm's avatar
Magnus Damm committed
54

55 56 57 58
	/* Allocate memory windows and IRQs arrays. */
	windows = devm_kzalloc(pfc->dev, num_windows * sizeof(*windows),
			       GFP_KERNEL);
	if (windows == NULL)
59
		return -ENOMEM;
Magnus Damm's avatar
Magnus Damm committed
60

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

64 65 66 67
	if (num_irqs) {
		irqs = devm_kzalloc(pfc->dev, num_irqs * sizeof(*irqs),
				    GFP_KERNEL);
		if (irqs == NULL)
68
			return -ENOMEM;
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89

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

	/* Fill them. */
	for (i = 0, res = pdev->resource; i < pdev->num_resources; i++, res++) {
		switch (resource_type(res)) {
		case IORESOURCE_MEM:
			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++;
			break;

		case IORESOURCE_IRQ:
			*irqs++ = res->start;
			break;
		}
Magnus Damm's avatar
Magnus Damm committed
90 91 92 93 94
	}

	return 0;
}

95
static void __iomem *sh_pfc_phys_to_virt(struct sh_pfc *pfc, u32 reg)
Magnus Damm's avatar
Magnus Damm committed
96
{
97
	struct sh_pfc_window *window;
98
	phys_addr_t address = reg;
99
	unsigned int i;
Magnus Damm's avatar
Magnus Damm committed
100 101

	/* scan through physical windows and convert address */
102
	for (i = 0; i < pfc->num_windows; i++) {
103
		window = pfc->windows + i;
Magnus Damm's avatar
Magnus Damm committed
104 105 106 107 108 109 110 111 112 113

		if (address < window->phys)
			continue;

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

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

114
	BUG();
115
	return NULL;
Magnus Damm's avatar
Magnus Damm committed
116
}
Magnus Damm's avatar
Magnus Damm committed
117

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

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

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

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

133
	return -EINVAL;
134 135
}

136
static int sh_pfc_enum_in_range(u16 enum_id, const struct pinmux_range *r)
Magnus Damm's avatar
Magnus Damm committed
137 138 139 140 141 142 143 144 145 146
{
	if (enum_id < r->begin)
		return 0;

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

	return 1;
}

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

	BUG();
	return 0;
}

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

	BUG();
}

180
static void sh_pfc_config_reg_helper(struct sh_pfc *pfc,
181
				     const struct pinmux_cfg_reg *crp,
182
				     unsigned int in_pos,
183
				     void __iomem **mapped_regp, u32 *maskp,
184
				     unsigned int *posp)
Magnus Damm's avatar
Magnus Damm committed
185
{
186
	unsigned int k;
187

188
	*mapped_regp = sh_pfc_phys_to_virt(pfc, crp->reg);
Magnus Damm's avatar
Magnus Damm committed
189

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

201
static void sh_pfc_write_config_reg(struct sh_pfc *pfc,
202
				    const struct pinmux_cfg_reg *crp,
203
				    unsigned int field, u32 value)
Magnus Damm's avatar
Magnus Damm committed
204
{
205
	void __iomem *mapped_reg;
206
	unsigned int pos;
207
	u32 mask, data;
Magnus Damm's avatar
Magnus Damm committed
208

209
	sh_pfc_config_reg_helper(pfc, crp, field, &mapped_reg, &mask, &pos);
Magnus Damm's avatar
Magnus Damm committed
210

211
	dev_dbg(pfc->dev, "write_reg addr = %x, value = 0x%x, field = %u, "
212
		"r_width = %u, f_width = %u\n",
213
		crp->reg, value, field, crp->reg_width, crp->field_width);
Magnus Damm's avatar
Magnus Damm committed
214 215 216

	mask = ~(mask << pos);
	value = value << pos;
Magnus Damm's avatar
Magnus Damm committed
217

218
	data = sh_pfc_read_raw_reg(mapped_reg, crp->reg_width);
219 220 221
	data &= mask;
	data |= value;

222
	if (pfc->info->unlock_reg)
223
		sh_pfc_write_raw_reg(
224
			sh_pfc_phys_to_virt(pfc, pfc->info->unlock_reg), 32,
225
			~data);
226

227
	sh_pfc_write_raw_reg(mapped_reg, crp->reg_width, data);
Magnus Damm's avatar
Magnus Damm committed
228 229
}

230
static int sh_pfc_get_config_reg(struct sh_pfc *pfc, u16 enum_id,
231 232
				 const struct pinmux_cfg_reg **crp,
				 unsigned int *fieldp, u32 *valuep)
Magnus Damm's avatar
Magnus Damm committed
233
{
234
	unsigned int k = 0;
Magnus Damm's avatar
Magnus Damm committed
235 236

	while (1) {
237 238 239 240 241 242 243 244
		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;
Magnus Damm's avatar
Magnus Damm committed
245 246 247

		if (!r_width)
			break;
248 249

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

253 254 255 256 257 258 259 260 261 262 263 264 265
			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;
				}
Magnus Damm's avatar
Magnus Damm committed
266
			}
267 268
			pos += ncomb;
			m++;
Magnus Damm's avatar
Magnus Damm committed
269 270 271 272
		}
		k++;
	}

273
	return -EINVAL;
Magnus Damm's avatar
Magnus Damm committed
274 275
}

276 277
static int sh_pfc_mark_to_enum(struct sh_pfc *pfc, u16 mark, int pos,
			      u16 *enum_idp)
Magnus Damm's avatar
Magnus Damm committed
278
{
279
	const u16 *data = pfc->info->gpio_data;
280
	unsigned int k;
Magnus Damm's avatar
Magnus Damm committed
281 282 283 284 285 286

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

287
	for (k = 0; k < pfc->info->gpio_data_size; k++) {
288
		if (data[k] == mark) {
Magnus Damm's avatar
Magnus Damm committed
289 290 291 292 293
			*enum_idp = data[k + 1];
			return k + 1;
		}
	}

294 295
	dev_err(pfc->dev, "cannot locate data/mark enum_id for mark %d\n",
		mark);
296
	return -EINVAL;
Magnus Damm's avatar
Magnus Damm committed
297 298
}

299
int sh_pfc_config_mux(struct sh_pfc *pfc, unsigned mark, int pinmux_type)
Magnus Damm's avatar
Magnus Damm committed
300
{
301
	const struct pinmux_range *range;
302
	int pos = 0;
Magnus Damm's avatar
Magnus Damm committed
303 304

	switch (pinmux_type) {
305
	case PINMUX_TYPE_GPIO:
Magnus Damm's avatar
Magnus Damm committed
306 307 308 309 310
	case PINMUX_TYPE_FUNCTION:
		range = NULL;
		break;

	case PINMUX_TYPE_OUTPUT:
311
		range = &pfc->info->output;
Magnus Damm's avatar
Magnus Damm committed
312 313 314
		break;

	case PINMUX_TYPE_INPUT:
315
		range = &pfc->info->input;
Magnus Damm's avatar
Magnus Damm committed
316 317 318
		break;

	default:
319
		return -EINVAL;
Magnus Damm's avatar
Magnus Damm committed
320 321
	}

322
	/* Iterate over all the configuration fields we need to update. */
Magnus Damm's avatar
Magnus Damm committed
323
	while (1) {
324 325 326 327 328 329 330
		const struct pinmux_cfg_reg *cr;
		unsigned int field;
		u16 enum_id;
		u32 value;
		int in_range;
		int ret;

331
		pos = sh_pfc_mark_to_enum(pfc, mark, pos, &enum_id);
332 333
		if (pos < 0)
			return pos;
Magnus Damm's avatar
Magnus Damm committed
334 335 336 337

		if (!enum_id)
			break;

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

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

Magnus Damm's avatar
Magnus Damm committed
366 367 368
		if (!in_range)
			continue;

369 370 371
		ret = sh_pfc_get_config_reg(pfc, enum_id, &cr, &field, &value);
		if (ret < 0)
			return ret;
Magnus Damm's avatar
Magnus Damm committed
372

373
		sh_pfc_write_config_reg(pfc, cr, field, value);
Magnus Damm's avatar
Magnus Damm committed
374 375 376 377 378
	}

	return 0;
}

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

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

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

	return 0;
}

Laurent Pinchart's avatar
Laurent Pinchart committed
440 441
#ifdef CONFIG_OF
static const struct of_device_id sh_pfc_of_table[] = {
442 443 444 445 446 447
#ifdef CONFIG_PINCTRL_PFC_EMEV2
	{
		.compatible = "renesas,pfc-emev2",
		.data = &emev2_pinmux_info,
	},
#endif
Laurent Pinchart's avatar
Laurent Pinchart committed
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 476 477
#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
478 479 480 481 482 483
#ifdef CONFIG_PINCTRL_PFC_R8A7791
	{
		.compatible = "renesas,pfc-r8a7791",
		.data = &r8a7791_pinmux_info,
	},
#endif
484 485 486 487 488 489
#ifdef CONFIG_PINCTRL_PFC_R8A7793
	{
		.compatible = "renesas,pfc-r8a7793",
		.data = &r8a7793_pinmux_info,
	},
#endif
Laurent Pinchart's avatar
Laurent Pinchart committed
490 491 492 493 494 495 496 497 498 499 500
#ifdef CONFIG_PINCTRL_PFC_SH73A0
	{
		.compatible = "renesas,pfc-sh73a0",
		.data = &sh73a0_pinmux_info,
	},
#endif
	{ },
};
MODULE_DEVICE_TABLE(of, sh_pfc_of_table);
#endif

501
static int sh_pfc_probe(struct platform_device *pdev)
Magnus Damm's avatar
Magnus Damm committed
502
{
Laurent Pinchart's avatar
Laurent Pinchart committed
503 504 505 506
	const struct platform_device_id *platid = platform_get_device_id(pdev);
#ifdef CONFIG_OF
	struct device_node *np = pdev->dev.of_node;
#endif
507
	const struct sh_pfc_soc_info *info;
508
	struct sh_pfc *pfc;
Magnus Damm's avatar
Magnus Damm committed
509
	int ret;
Magnus Damm's avatar
Magnus Damm committed
510

Laurent Pinchart's avatar
Laurent Pinchart committed
511 512 513 514 515 516 517
#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;

518
	if (info == NULL)
519
		return -ENODEV;
Magnus Damm's avatar
Magnus Damm committed
520

521
	pfc = devm_kzalloc(&pdev->dev, sizeof(*pfc), GFP_KERNEL);
522 523
	if (pfc == NULL)
		return -ENOMEM;
524

525
	pfc->info = info;
526 527
	pfc->dev = &pdev->dev;

528
	ret = sh_pfc_map_resources(pfc, pdev);
529
	if (unlikely(ret < 0))
Magnus Damm's avatar
Magnus Damm committed
530 531
		return ret;

532
	spin_lock_init(&pfc->lock);
Magnus Damm's avatar
Magnus Damm committed
533

534 535 536 537 538 539
	if (info->ops && info->ops->init) {
		ret = info->ops->init(pfc);
		if (ret < 0)
			return ret;
	}

540
	pinctrl_provide_dummies();
Magnus Damm's avatar
Magnus Damm committed
541

542 543 544 545
	ret = sh_pfc_init_ranges(pfc);
	if (ret < 0)
		return ret;

546 547 548
	/*
	 * Initialize pinctrl bindings first
	 */
549
	ret = sh_pfc_register_pinctrl(pfc);
550
	if (unlikely(ret != 0))
551
		return ret;
552

553
#ifdef CONFIG_GPIO_SH_PFC
554 555 556
	/*
	 * Then the GPIO chip
	 */
557
	ret = sh_pfc_register_gpiochip(pfc);
558
	if (unlikely(ret != 0)) {
559 560 561 562 563
		/*
		 * 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.
		 */
564
		dev_notice(pfc->dev, "failed to init GPIO chip, ignoring...\n");
565
	}
566
#endif
567

568 569
	platform_set_drvdata(pdev, pfc);

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

572
	return 0;
573
}
574

575 576 577 578 579 580 581 582 583 584 585 586 587
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[] = {
588 589
#ifdef CONFIG_PINCTRL_PFC_R8A7740
	{ "pfc-r8a7740", (kernel_ulong_t)&r8a7740_pinmux_info },
590
#endif
591 592 593
#ifdef CONFIG_PINCTRL_PFC_R8A7778
	{ "pfc-r8a7778", (kernel_ulong_t)&r8a7778_pinmux_info },
#endif
594 595
#ifdef CONFIG_PINCTRL_PFC_R8A7779
	{ "pfc-r8a7779", (kernel_ulong_t)&r8a7779_pinmux_info },
596
#endif
597 598 599
#ifdef CONFIG_PINCTRL_PFC_SH7203
	{ "pfc-sh7203", (kernel_ulong_t)&sh7203_pinmux_info },
#endif
600 601 602
#ifdef CONFIG_PINCTRL_PFC_SH7264
	{ "pfc-sh7264", (kernel_ulong_t)&sh7264_pinmux_info },
#endif
603 604 605
#ifdef CONFIG_PINCTRL_PFC_SH7269
	{ "pfc-sh7269", (kernel_ulong_t)&sh7269_pinmux_info },
#endif
606 607
#ifdef CONFIG_PINCTRL_PFC_SH73A0
	{ "pfc-sh73a0", (kernel_ulong_t)&sh73a0_pinmux_info },
608 609 610
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7720
	{ "pfc-sh7720", (kernel_ulong_t)&sh7720_pinmux_info },
611 612 613
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7722
	{ "pfc-sh7722", (kernel_ulong_t)&sh7722_pinmux_info },
614 615 616
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7723
	{ "pfc-sh7723", (kernel_ulong_t)&sh7723_pinmux_info },
617 618 619
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7724
	{ "pfc-sh7724", (kernel_ulong_t)&sh7724_pinmux_info },
620 621 622
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7734
	{ "pfc-sh7734", (kernel_ulong_t)&sh7734_pinmux_info },
623 624 625
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7757
	{ "pfc-sh7757", (kernel_ulong_t)&sh7757_pinmux_info },
626 627 628
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7785
	{ "pfc-sh7785", (kernel_ulong_t)&sh7785_pinmux_info },
629 630 631
#endif
#ifdef CONFIG_PINCTRL_PFC_SH7786
	{ "pfc-sh7786", (kernel_ulong_t)&sh7786_pinmux_info },
632 633 634
#endif
#ifdef CONFIG_PINCTRL_PFC_SHX3
	{ "pfc-shx3", (kernel_ulong_t)&shx3_pinmux_info },
635
#endif
636 637 638 639 640 641 642 643 644 645 646
	{ "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,
Laurent Pinchart's avatar
Laurent Pinchart committed
647
		.of_match_table = of_match_ptr(sh_pfc_of_table),
648 649 650
	},
};

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

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

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