fsl_soc.c 17.4 KB
Newer Older
1 2 3 4 5
/*
 * FSL SoC setup code
 *
 * Maintained by Kumar Gala (see MAINTAINERS for contact information)
 *
6 7 8
 * 2006 (c) MontaVista Software, Inc.
 * Vitaly Bordug <vbordug@ru.mvista.com>
 *
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 * 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.
 */

#include <linux/stddef.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/errno.h>
#include <linux/major.h>
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/device.h>
#include <linux/platform_device.h>
K
Kumar Gala 已提交
25
#include <linux/of_platform.h>
26
#include <linux/phy.h>
27
#include <linux/phy_fixed.h>
28
#include <linux/spi/spi.h>
29
#include <linux/fsl_devices.h>
30 31
#include <linux/fs_enet_pd.h>
#include <linux/fs_uart_pd.h>
32 33 34 35 36

#include <asm/system.h>
#include <asm/atomic.h>
#include <asm/io.h>
#include <asm/irq.h>
37
#include <asm/time.h>
38 39 40
#include <asm/prom.h>
#include <sysdev/fsl_soc.h>
#include <mm/mmu_decl.h>
41
#include <asm/cpm2.h>
42

43
extern void init_fcc_ioports(struct fs_platform_info*);
44 45
extern void init_fec_ioports(struct fs_platform_info*);
extern void init_smc_ioports(struct fs_uart_platform_info*);
46 47 48 49 50 51 52 53 54 55
static phys_addr_t immrbase = -1;

phys_addr_t get_immrbase(void)
{
	struct device_node *soc;

	if (immrbase != -1)
		return immrbase;

	soc = of_find_node_by_type(NULL, "soc");
56
	if (soc) {
S
Scott Wood 已提交
57
		int size;
58 59
		u32 naddr;
		const u32 *prop = of_get_property(soc, "#address-cells", &size);
60

61 62 63 64 65 66
		if (prop && size == 4)
			naddr = *prop;
		else
			naddr = 2;

		prop = of_get_property(soc, "ranges", &size);
67
		if (prop)
68 69
			immrbase = of_translate_address(soc, prop + naddr);

70
		of_node_put(soc);
S
Scott Wood 已提交
71
	}
72 73 74 75

	return immrbase;
}

76
EXPORT_SYMBOL(get_immrbase);
77

78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104
static u32 sysfreq = -1;

u32 fsl_get_sys_freq(void)
{
	struct device_node *soc;
	const u32 *prop;
	int size;

	if (sysfreq != -1)
		return sysfreq;

	soc = of_find_node_by_type(NULL, "soc");
	if (!soc)
		return -1;

	prop = of_get_property(soc, "clock-frequency", &size);
	if (!prop || size != sizeof(*prop) || *prop == 0)
		prop = of_get_property(soc, "bus-frequency", &size);

	if (prop && size == sizeof(*prop))
		sysfreq = *prop;

	of_node_put(soc);
	return sysfreq;
}
EXPORT_SYMBOL(fsl_get_sys_freq);

105
#if defined(CONFIG_CPM2) || defined(CONFIG_QUICC_ENGINE) || defined(CONFIG_8xx)
106 107 108 109 110 111

static u32 brgfreq = -1;

u32 get_brgfreq(void)
{
	struct device_node *node;
112 113
	const unsigned int *prop;
	int size;
114 115 116 117

	if (brgfreq != -1)
		return brgfreq;

118
	node = of_find_compatible_node(NULL, NULL, "fsl,cpm-brg");
119
	if (node) {
120 121 122 123 124 125 126
		prop = of_get_property(node, "clock-frequency", &size);
		if (prop && size == 4)
			brgfreq = *prop;

		of_node_put(node);
		return brgfreq;
	}
127

128 129
	/* Legacy device binding -- will go away when no users are left. */
	node = of_find_node_by_type(NULL, "cpm");
130 131 132 133 134
	if (!node)
		node = of_find_compatible_node(NULL, NULL, "fsl,qe");
	if (!node)
		node = of_find_node_by_type(NULL, "qe");

135 136
	if (node) {
		prop = of_get_property(node, "brg-frequency", &size);
S
Scott Wood 已提交
137
		if (prop && size == 4)
138
			brgfreq = *prop;
S
Scott Wood 已提交
139

140 141 142 143 144
		if (brgfreq == -1 || brgfreq == 0) {
			prop = of_get_property(node, "bus-frequency", &size);
			if (prop && size == 4)
				brgfreq = *prop / 2;
		}
145
		of_node_put(node);
S
Scott Wood 已提交
146
	}
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163

	return brgfreq;
}

EXPORT_SYMBOL(get_brgfreq);

static u32 fs_baudrate = -1;

u32 get_baudrate(void)
{
	struct device_node *node;

	if (fs_baudrate != -1)
		return fs_baudrate;

	node = of_find_node_by_type(NULL, "serial");
	if (node) {
S
Scott Wood 已提交
164
		int size;
165 166
		const unsigned int *prop = of_get_property(node,
				"current-speed", &size);
167 168 169 170

		if (prop)
			fs_baudrate = *prop;
		of_node_put(node);
S
Scott Wood 已提交
171
	}
172 173 174 175 176 177 178

	return fs_baudrate;
}

EXPORT_SYMBOL(get_baudrate);
#endif /* CONFIG_CPM2 */

179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
#ifdef CONFIG_FIXED_PHY
static int __init of_add_fixed_phys(void)
{
	int ret;
	struct device_node *np;
	u32 *fixed_link;
	struct fixed_phy_status status = {};

	for_each_node_by_name(np, "ethernet") {
		fixed_link  = (u32 *)of_get_property(np, "fixed-link", NULL);
		if (!fixed_link)
			continue;

		status.link = 1;
		status.duplex = fixed_link[1];
		status.speed = fixed_link[2];
		status.pause = fixed_link[3];
		status.asym_pause = fixed_link[4];

		ret = fixed_phy_add(PHY_POLL, fixed_link[0], &status);
		if (ret) {
			of_node_put(np);
			return ret;
		}
	}

	return 0;
}
arch_initcall(of_add_fixed_phys);
#endif /* CONFIG_FIXED_PHY */

210
static int gfar_mdio_of_init_one(struct device_node *np)
211
{
212 213 214
	int k;
	struct device_node *child = NULL;
	struct gianfar_mdio_data mdio_data;
215
	struct platform_device *mdio_dev;
216 217 218
	struct resource res;
	int ret;

219 220
	memset(&res, 0, sizeof(res));
	memset(&mdio_data, 0, sizeof(mdio_data));
221

222 223 224
	ret = of_address_to_resource(np, 0, &res);
	if (ret)
		return ret;
225

226 227
	/* The gianfar device will try to use the same ID created below to find
	 * this bus, to coordinate register access (since they share).  */
228 229 230 231
	mdio_dev = platform_device_register_simple("fsl-gianfar_mdio",
			res.start&0xfffff, &res, 1);
	if (IS_ERR(mdio_dev))
		return PTR_ERR(mdio_dev);
232

233 234
	for (k = 0; k < 32; k++)
		mdio_data.irq[k] = PHY_POLL;
235

236 237 238 239 240
	while ((child = of_get_next_child(np, child)) != NULL) {
		int irq = irq_of_parse_and_map(child, 0);
		if (irq != NO_IRQ) {
			const u32 *id = of_get_property(child, "reg", NULL);
			mdio_data.irq[*id] = irq;
241
		}
242
	}
243

244 245 246 247
	ret = platform_device_add_data(mdio_dev, &mdio_data,
				sizeof(struct gianfar_mdio_data));
	if (ret)
		platform_device_unregister(mdio_dev);
248

249 250
	return ret;
}
251

252 253 254
static int __init gfar_mdio_of_init(void)
{
	struct device_node *np = NULL;
255

256 257
	for_each_compatible_node(np, NULL, "fsl,gianfar-mdio")
		gfar_mdio_of_init_one(np);
258

259 260 261 262 263
	/* try the deprecated version */
	for_each_compatible_node(np, "mdio", "gianfar");
		gfar_mdio_of_init_one(np);

	return 0;
264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282
}

arch_initcall(gfar_mdio_of_init);

static const char *gfar_tx_intr = "tx";
static const char *gfar_rx_intr = "rx";
static const char *gfar_err_intr = "error";

static int __init gfar_of_init(void)
{
	struct device_node *np;
	unsigned int i;
	struct platform_device *gfar_dev;
	struct resource res;
	int ret;

	for (np = NULL, i = 0;
	     (np = of_find_compatible_node(np, "network", "gianfar")) != NULL;
	     i++) {
283 284 285
		struct resource r[4];
		struct device_node *phy, *mdio;
		struct gianfar_platform_data gfar_data;
286 287
		const unsigned int *id;
		const char *model;
A
Andy Fleming 已提交
288
		const char *ctype;
289 290
		const void *mac_addr;
		const phandle *ph;
291
		int n_res = 2;
292

293 294 295
		if (!of_device_is_available(np))
			continue;

296 297 298 299 300
		memset(r, 0, sizeof(r));
		memset(&gfar_data, 0, sizeof(gfar_data));

		ret = of_address_to_resource(np, 0, &r[0]);
		if (ret)
301
			goto err;
302

303
		of_irq_to_resource(np, 0, &r[1]);
304

305
		model = of_get_property(np, "model", NULL);
306 307 308 309 310 311

		/* If we aren't the FEC we have multiple interrupts */
		if (model && strcasecmp(model, "FEC")) {
			r[1].name = gfar_tx_intr;

			r[2].name = gfar_rx_intr;
312
			of_irq_to_resource(np, 1, &r[2]);
313 314

			r[3].name = gfar_err_intr;
315
			of_irq_to_resource(np, 2, &r[3]);
316 317

			n_res += 2;
318 319
		}

320 321
		gfar_dev =
		    platform_device_register_simple("fsl-gianfar", i, &r[0],
322
						    n_res);
323 324 325

		if (IS_ERR(gfar_dev)) {
			ret = PTR_ERR(gfar_dev);
326
			goto err;
327 328
		}

329
		mac_addr = of_get_mac_address(np);
330 331
		if (mac_addr)
			memcpy(gfar_data.mac_addr, mac_addr, 6);
332 333 334

		if (model && !strcasecmp(model, "TSEC"))
			gfar_data.device_flags =
335 336 337 338
			    FSL_GIANFAR_DEV_HAS_GIGABIT |
			    FSL_GIANFAR_DEV_HAS_COALESCE |
			    FSL_GIANFAR_DEV_HAS_RMON |
			    FSL_GIANFAR_DEV_HAS_MULTI_INTR;
339 340
		if (model && !strcasecmp(model, "eTSEC"))
			gfar_data.device_flags =
341 342 343 344 345 346 347
			    FSL_GIANFAR_DEV_HAS_GIGABIT |
			    FSL_GIANFAR_DEV_HAS_COALESCE |
			    FSL_GIANFAR_DEV_HAS_RMON |
			    FSL_GIANFAR_DEV_HAS_MULTI_INTR |
			    FSL_GIANFAR_DEV_HAS_CSUM |
			    FSL_GIANFAR_DEV_HAS_VLAN |
			    FSL_GIANFAR_DEV_HAS_EXTENDED_HASH;
348

A
Andy Fleming 已提交
349 350 351 352 353 354 355 356
		ctype = of_get_property(np, "phy-connection-type", NULL);

		/* We only care about rgmii-id.  The rest are autodetected */
		if (ctype && !strcmp(ctype, "rgmii-id"))
			gfar_data.interface = PHY_INTERFACE_MODE_RGMII_ID;
		else
			gfar_data.interface = PHY_INTERFACE_MODE_MII;

357 358 359
		if (of_get_property(np, "fsl,magic-packet", NULL))
			gfar_data.device_flags |= FSL_GIANFAR_DEV_HAS_MAGIC_PACKET;

360
		ph = of_get_property(np, "phy-handle", NULL);
361 362 363 364 365 366 367 368 369
		if (ph == NULL) {
			u32 *fixed_link;

			fixed_link = (u32 *)of_get_property(np, "fixed-link",
							   NULL);
			if (!fixed_link) {
				ret = -ENODEV;
				goto unreg;
			}
370

371
			snprintf(gfar_data.bus_id, MII_BUS_ID_SIZE, "0");
372 373 374
			gfar_data.phy_id = fixed_link[0];
		} else {
			phy = of_find_node_by_phandle(*ph);
375

376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
			if (phy == NULL) {
				ret = -ENODEV;
				goto unreg;
			}

			mdio = of_get_parent(phy);

			id = of_get_property(phy, "reg", NULL);
			ret = of_address_to_resource(mdio, 0, &res);
			if (ret) {
				of_node_put(phy);
				of_node_put(mdio);
				goto unreg;
			}

			gfar_data.phy_id = *id;
392
			snprintf(gfar_data.bus_id, MII_BUS_ID_SIZE, "%llx",
393
				 (unsigned long long)res.start&0xfffff);
394 395 396 397 398

			of_node_put(phy);
			of_node_put(mdio);
		}

399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422
		/* Get MDIO bus controlled by this eTSEC, if any.  Normally only
		 * eTSEC 1 will control an MDIO bus, not necessarily the same
		 * bus that its PHY is on ('mdio' above), so we can't just use
		 * that.  What we do is look for a gianfar mdio device that has
		 * overlapping registers with this device.  That's really the
		 * whole point, to find the device sharing our registers to
		 * coordinate access with it.
		 */
		for_each_compatible_node(mdio, NULL, "fsl,gianfar-mdio") {
			if (of_address_to_resource(mdio, 0, &res))
				continue;

			if (res.start >= r[0].start && res.end <= r[0].end) {
				/* Get the ID the mdio bus platform device was
				 * registered with.  gfar_data.bus_id is
				 * different because it's for finding a PHY,
				 * while this is for finding a MII bus.
				 */
				gfar_data.mdio_bus = res.start&0xfffff;
				of_node_put(mdio);
				break;
			}
		}

423 424 425 426
		ret =
		    platform_device_add_data(gfar_dev, &gfar_data,
					     sizeof(struct
						    gianfar_platform_data));
427
		if (ret)
428
			goto unreg;
429 430 431 432
	}

	return 0;

433
unreg:
434
	platform_device_unregister(gfar_dev);
435
err:
436 437
	return ret;
}
438

439 440
arch_initcall(gfar_of_init);

441
static enum fsl_usb2_phy_modes determine_usb_phy(const char *phy_type)
442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459
{
	if (!phy_type)
		return FSL_USB2_PHY_NONE;
	if (!strcasecmp(phy_type, "ulpi"))
		return FSL_USB2_PHY_ULPI;
	if (!strcasecmp(phy_type, "utmi"))
		return FSL_USB2_PHY_UTMI;
	if (!strcasecmp(phy_type, "utmi_wide"))
		return FSL_USB2_PHY_UTMI_WIDE;
	if (!strcasecmp(phy_type, "serial"))
		return FSL_USB2_PHY_SERIAL;

	return FSL_USB2_PHY_NONE;
}

static int __init fsl_usb_of_init(void)
{
	struct device_node *np;
460
	unsigned int i = 0;
461 462
	struct platform_device *usb_dev_mph = NULL, *usb_dev_dr_host = NULL,
		*usb_dev_dr_client = NULL;
463 464
	int ret;

465
	for_each_compatible_node(np, NULL, "fsl-usb2-mph") {
466 467
		struct resource r[2];
		struct fsl_usb2_platform_data usb_data;
468
		const unsigned char *prop = NULL;
469 470 471 472 473 474 475 476

		memset(&r, 0, sizeof(r));
		memset(&usb_data, 0, sizeof(usb_data));

		ret = of_address_to_resource(np, 0, &r[0]);
		if (ret)
			goto err;

477
		of_irq_to_resource(np, 0, &r[1]);
478

479 480 481 482
		usb_dev_mph =
		    platform_device_register_simple("fsl-ehci", i, r, 2);
		if (IS_ERR(usb_dev_mph)) {
			ret = PTR_ERR(usb_dev_mph);
483 484 485
			goto err;
		}

486 487
		usb_dev_mph->dev.coherent_dma_mask = 0xffffffffUL;
		usb_dev_mph->dev.dma_mask = &usb_dev_mph->dev.coherent_dma_mask;
488 489 490

		usb_data.operating_mode = FSL_USB2_MPH_HOST;

491
		prop = of_get_property(np, "port0", NULL);
492 493 494
		if (prop)
			usb_data.port_enables |= FSL_USB2_PORT0_ENABLED;

495
		prop = of_get_property(np, "port1", NULL);
496 497 498
		if (prop)
			usb_data.port_enables |= FSL_USB2_PORT1_ENABLED;

499
		prop = of_get_property(np, "phy_type", NULL);
500 501 502
		usb_data.phy_mode = determine_usb_phy(prop);

		ret =
503
		    platform_device_add_data(usb_dev_mph, &usb_data,
504 505 506
					     sizeof(struct
						    fsl_usb2_platform_data));
		if (ret)
507
			goto unreg_mph;
508
		i++;
509 510
	}

511
	for_each_compatible_node(np, NULL, "fsl-usb2-dr") {
512 513
		struct resource r[2];
		struct fsl_usb2_platform_data usb_data;
514
		const unsigned char *prop = NULL;
515 516 517 518 519 520

		memset(&r, 0, sizeof(r));
		memset(&usb_data, 0, sizeof(usb_data));

		ret = of_address_to_resource(np, 0, &r[0]);
		if (ret)
521
			goto unreg_mph;
522

523
		of_irq_to_resource(np, 0, &r[1]);
524

525
		prop = of_get_property(np, "dr_mode", NULL);
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558

		if (!prop || !strcmp(prop, "host")) {
			usb_data.operating_mode = FSL_USB2_DR_HOST;
			usb_dev_dr_host = platform_device_register_simple(
					"fsl-ehci", i, r, 2);
			if (IS_ERR(usb_dev_dr_host)) {
				ret = PTR_ERR(usb_dev_dr_host);
				goto err;
			}
		} else if (prop && !strcmp(prop, "peripheral")) {
			usb_data.operating_mode = FSL_USB2_DR_DEVICE;
			usb_dev_dr_client = platform_device_register_simple(
					"fsl-usb2-udc", i, r, 2);
			if (IS_ERR(usb_dev_dr_client)) {
				ret = PTR_ERR(usb_dev_dr_client);
				goto err;
			}
		} else if (prop && !strcmp(prop, "otg")) {
			usb_data.operating_mode = FSL_USB2_DR_OTG;
			usb_dev_dr_host = platform_device_register_simple(
					"fsl-ehci", i, r, 2);
			if (IS_ERR(usb_dev_dr_host)) {
				ret = PTR_ERR(usb_dev_dr_host);
				goto err;
			}
			usb_dev_dr_client = platform_device_register_simple(
					"fsl-usb2-udc", i, r, 2);
			if (IS_ERR(usb_dev_dr_client)) {
				ret = PTR_ERR(usb_dev_dr_client);
				goto err;
			}
		} else {
			ret = -EINVAL;
559 560 561
			goto err;
		}

562
		prop = of_get_property(np, "phy_type", NULL);
563 564
		usb_data.phy_mode = determine_usb_phy(prop);

565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
		if (usb_dev_dr_host) {
			usb_dev_dr_host->dev.coherent_dma_mask = 0xffffffffUL;
			usb_dev_dr_host->dev.dma_mask = &usb_dev_dr_host->
				dev.coherent_dma_mask;
			if ((ret = platform_device_add_data(usb_dev_dr_host,
						&usb_data, sizeof(struct
						fsl_usb2_platform_data))))
				goto unreg_dr;
		}
		if (usb_dev_dr_client) {
			usb_dev_dr_client->dev.coherent_dma_mask = 0xffffffffUL;
			usb_dev_dr_client->dev.dma_mask = &usb_dev_dr_client->
				dev.coherent_dma_mask;
			if ((ret = platform_device_add_data(usb_dev_dr_client,
						&usb_data, sizeof(struct
						fsl_usb2_platform_data))))
				goto unreg_dr;
		}
583
		i++;
584 585 586
	}
	return 0;

587
unreg_dr:
588 589 590 591
	if (usb_dev_dr_host)
		platform_device_unregister(usb_dev_dr_host);
	if (usb_dev_dr_client)
		platform_device_unregister(usb_dev_dr_client);
592 593 594
unreg_mph:
	if (usb_dev_mph)
		platform_device_unregister(usb_dev_mph);
595 596 597 598
err:
	return ret;
}

599
arch_initcall(fsl_usb_of_init);
600

601 602 603 604 605
static int __init of_fsl_spi_probe(char *type, char *compatible, u32 sysclk,
				   struct spi_board_info *board_infos,
				   unsigned int num_board_infos,
				   void (*activate_cs)(u8 cs, u8 polarity),
				   void (*deactivate_cs)(u8 cs, u8 polarity))
606 607
{
	struct device_node *np;
608
	unsigned int i = 0;
609

610 611
	for_each_compatible_node(np, type, compatible) {
		int ret;
612 613 614 615 616 617 618 619 620 621 622
		unsigned int j;
		const void *prop;
		struct resource res[2];
		struct platform_device *pdev;
		struct fsl_spi_platform_data pdata = {
			.activate_cs = activate_cs,
			.deactivate_cs = deactivate_cs,
		};

		memset(res, 0, sizeof(res));

623
		pdata.sysclk = sysclk;
624 625 626 627 628 629

		prop = of_get_property(np, "reg", NULL);
		if (!prop)
			goto err;
		pdata.bus_num = *(u32 *)prop;

630 631 632 633
		prop = of_get_property(np, "cell-index", NULL);
		if (prop)
			i = *(u32 *)prop;

634 635 636 637 638 639 640 641 642 643
		prop = of_get_property(np, "mode", NULL);
		if (prop && !strcmp(prop, "cpu-qe"))
			pdata.qe_mode = 1;

		for (j = 0; j < num_board_infos; j++) {
			if (board_infos[j].bus_num == pdata.bus_num)
				pdata.max_chipselect++;
		}

		if (!pdata.max_chipselect)
644
			continue;
645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666

		ret = of_address_to_resource(np, 0, &res[0]);
		if (ret)
			goto err;

		ret = of_irq_to_resource(np, 0, &res[1]);
		if (ret == NO_IRQ)
			goto err;

		pdev = platform_device_alloc("mpc83xx_spi", i);
		if (!pdev)
			goto err;

		ret = platform_device_add_data(pdev, &pdata, sizeof(pdata));
		if (ret)
			goto unreg;

		ret = platform_device_add_resources(pdev, res,
						    ARRAY_SIZE(res));
		if (ret)
			goto unreg;

667
		ret = platform_device_add(pdev);
668 669 670
		if (ret)
			goto unreg;

671
		goto next;
672 673 674
unreg:
		platform_device_del(pdev);
err:
675 676 677
		pr_err("%s: registration failed\n", np->full_name);
next:
		i++;
678 679
	}

680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695
	return i;
}

int __init fsl_spi_init(struct spi_board_info *board_infos,
			unsigned int num_board_infos,
			void (*activate_cs)(u8 cs, u8 polarity),
			void (*deactivate_cs)(u8 cs, u8 polarity))
{
	u32 sysclk = -1;
	int ret;

#ifdef CONFIG_QUICC_ENGINE
	/* SPI controller is either clocked from QE or SoC clock */
	sysclk = get_brgfreq();
#endif
	if (sysclk == -1) {
696 697
		sysclk = fsl_get_sys_freq();
		if (sysclk == -1)
698 699 700 701 702 703 704 705 706
			return -ENODEV;
	}

	ret = of_fsl_spi_probe(NULL, "fsl,spi", sysclk, board_infos,
			       num_board_infos, activate_cs, deactivate_cs);
	if (!ret)
		of_fsl_spi_probe("spi", "fsl_spi", sysclk, board_infos,
				 num_board_infos, activate_cs, deactivate_cs);

707 708
	return spi_register_board_info(board_infos, num_board_infos);
}
709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746

#if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx)
static __be32 __iomem *rstcr;

static int __init setup_rstcr(void)
{
	struct device_node *np;
	np = of_find_node_by_name(NULL, "global-utilities");
	if ((np && of_get_property(np, "fsl,has-rstcr", NULL))) {
		const u32 *prop = of_get_property(np, "reg", NULL);
		if (prop) {
			/* map reset control register
			 * 0xE00B0 is offset of reset control register
			 */
			rstcr = ioremap(get_immrbase() + *prop + 0xB0, 0xff);
			if (!rstcr)
				printk (KERN_EMERG "Error: reset control "
						"register not mapped!\n");
		}
	} else
		printk (KERN_INFO "rstcr compatible register does not exist!\n");
	if (np)
		of_node_put(np);
	return 0;
}

arch_initcall(setup_rstcr);

void fsl_rstcr_restart(char *cmd)
{
	local_irq_disable();
	if (rstcr)
		/* set reset control register */
		out_be32(rstcr, 0x2);	/* HRESET_REQ */

	while (1) ;
}
#endif
747 748

#if defined(CONFIG_FB_FSL_DIU) || defined(CONFIG_FB_FSL_DIU_MODULE)
749
struct platform_diu_data_ops diu_ops;
750 751
EXPORT_SYMBOL(diu_ops);
#endif