xref: /openbmc/linux/arch/mips/cavium-octeon/octeon-platform.c (revision b1259519e618d479ede8a0db5474b3aff99f5056)
1512254baSDavid Daney /*
2512254baSDavid Daney  * This file is subject to the terms and conditions of the GNU General Public
3512254baSDavid Daney  * License.  See the file "COPYING" in the main directory of this archive
4512254baSDavid Daney  * for more details.
5512254baSDavid Daney  *
67fd57ab9SSteven J. Hill  * Copyright (C) 2004-2017 Cavium, Inc.
7512254baSDavid Daney  * Copyright (C) 2008 Wind River Systems
8512254baSDavid Daney  */
9512254baSDavid Daney 
10377de399SAaro Koskinen #include <linux/etherdevice.h>
117ed18152SDavid Daney #include <linux/of_platform.h>
127ed18152SDavid Daney #include <linux/of_fdt.h>
137ed18152SDavid Daney #include <linux/libfdt.h>
14512254baSDavid Daney 
15512254baSDavid Daney #include <asm/octeon/octeon.h>
167ed18152SDavid Daney #include <asm/octeon/cvmx-helper-board.h>
177fd57ab9SSteven J. Hill 
187fd57ab9SSteven J. Hill #ifdef CONFIG_USB
197fd57ab9SSteven J. Hill #include <linux/usb/ehci_def.h>
207fd57ab9SSteven J. Hill #include <linux/usb/ehci_pdriver.h>
217fd57ab9SSteven J. Hill #include <linux/usb/ohci_pdriver.h>
222193dda5SAlan Stern #include <asm/octeon/cvmx-uctlx-defs.h>
23512254baSDavid Daney 
247e78db99SSteven J. Hill #define CVMX_UAHCX_EHCI_USBCMD	(CVMX_ADD_IO_SEG(0x00016F0000000010ull))
257e78db99SSteven J. Hill #define CVMX_UAHCX_OHCI_USBCMD	(CVMX_ADD_IO_SEG(0x00016F0000000408ull))
267e78db99SSteven J. Hill 
272193dda5SAlan Stern static DEFINE_MUTEX(octeon2_usb_clocks_mutex);
282193dda5SAlan Stern 
292193dda5SAlan Stern static int octeon2_usb_clock_start_cnt;
302193dda5SAlan Stern 
317e78db99SSteven J. Hill static int __init octeon2_usb_reset(void)
327e78db99SSteven J. Hill {
337e78db99SSteven J. Hill 	union cvmx_uctlx_clk_rst_ctl clk_rst_ctl;
347e78db99SSteven J. Hill 	u32 ucmd;
357e78db99SSteven J. Hill 
367e78db99SSteven J. Hill 	if (!OCTEON_IS_OCTEON2())
377e78db99SSteven J. Hill 		return 0;
387e78db99SSteven J. Hill 
397e78db99SSteven J. Hill 	clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
407e78db99SSteven J. Hill 	if (clk_rst_ctl.s.hrst) {
417e78db99SSteven J. Hill 		ucmd = cvmx_read64_uint32(CVMX_UAHCX_EHCI_USBCMD);
427e78db99SSteven J. Hill 		ucmd &= ~CMD_RUN;
437e78db99SSteven J. Hill 		cvmx_write64_uint32(CVMX_UAHCX_EHCI_USBCMD, ucmd);
447e78db99SSteven J. Hill 		mdelay(2);
457e78db99SSteven J. Hill 		ucmd |= CMD_RESET;
467e78db99SSteven J. Hill 		cvmx_write64_uint32(CVMX_UAHCX_EHCI_USBCMD, ucmd);
477e78db99SSteven J. Hill 		ucmd = cvmx_read64_uint32(CVMX_UAHCX_OHCI_USBCMD);
487e78db99SSteven J. Hill 		ucmd |= CMD_RUN;
497e78db99SSteven J. Hill 		cvmx_write64_uint32(CVMX_UAHCX_OHCI_USBCMD, ucmd);
507e78db99SSteven J. Hill 	}
517e78db99SSteven J. Hill 
527e78db99SSteven J. Hill 	return 0;
537e78db99SSteven J. Hill }
547e78db99SSteven J. Hill arch_initcall(octeon2_usb_reset);
557e78db99SSteven J. Hill 
56a95cfa6bSAndreas Herrmann static void octeon2_usb_clocks_start(struct device *dev)
572193dda5SAlan Stern {
582193dda5SAlan Stern 	u64 div;
592193dda5SAlan Stern 	union cvmx_uctlx_if_ena if_ena;
602193dda5SAlan Stern 	union cvmx_uctlx_clk_rst_ctl clk_rst_ctl;
612193dda5SAlan Stern 	union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status;
622193dda5SAlan Stern 	int i;
632193dda5SAlan Stern 	unsigned long io_clk_64_to_ns;
64a95cfa6bSAndreas Herrmann 	u32 clock_rate = 12000000;
65a95cfa6bSAndreas Herrmann 	bool is_crystal_clock = false;
662193dda5SAlan Stern 
672193dda5SAlan Stern 
682193dda5SAlan Stern 	mutex_lock(&octeon2_usb_clocks_mutex);
692193dda5SAlan Stern 
702193dda5SAlan Stern 	octeon2_usb_clock_start_cnt++;
712193dda5SAlan Stern 	if (octeon2_usb_clock_start_cnt != 1)
722193dda5SAlan Stern 		goto exit;
732193dda5SAlan Stern 
742193dda5SAlan Stern 	io_clk_64_to_ns = 64000000000ull / octeon_get_io_clock_rate();
752193dda5SAlan Stern 
76a95cfa6bSAndreas Herrmann 	if (dev->of_node) {
77a95cfa6bSAndreas Herrmann 		struct device_node *uctl_node;
78a95cfa6bSAndreas Herrmann 		const char *clock_type;
79a95cfa6bSAndreas Herrmann 
80a95cfa6bSAndreas Herrmann 		uctl_node = of_get_parent(dev->of_node);
81a95cfa6bSAndreas Herrmann 		if (!uctl_node) {
82a95cfa6bSAndreas Herrmann 			dev_err(dev, "No UCTL device node\n");
83a95cfa6bSAndreas Herrmann 			goto exit;
84a95cfa6bSAndreas Herrmann 		}
85a95cfa6bSAndreas Herrmann 		i = of_property_read_u32(uctl_node,
86a95cfa6bSAndreas Herrmann 					 "refclk-frequency", &clock_rate);
87a95cfa6bSAndreas Herrmann 		if (i) {
88a95cfa6bSAndreas Herrmann 			dev_err(dev, "No UCTL \"refclk-frequency\"\n");
89a95cfa6bSAndreas Herrmann 			goto exit;
90a95cfa6bSAndreas Herrmann 		}
91a95cfa6bSAndreas Herrmann 		i = of_property_read_string(uctl_node,
92a95cfa6bSAndreas Herrmann 					    "refclk-type", &clock_type);
93a95cfa6bSAndreas Herrmann 
94a95cfa6bSAndreas Herrmann 		if (!i && strcmp("crystal", clock_type) == 0)
95a95cfa6bSAndreas Herrmann 			is_crystal_clock = true;
96a95cfa6bSAndreas Herrmann 	}
97a95cfa6bSAndreas Herrmann 
982193dda5SAlan Stern 	/*
992193dda5SAlan Stern 	 * Step 1: Wait for voltages stable.  That surely happened
1002193dda5SAlan Stern 	 * before starting the kernel.
1012193dda5SAlan Stern 	 *
1022193dda5SAlan Stern 	 * Step 2: Enable  SCLK of UCTL by writing UCTL0_IF_ENA[EN] = 1
1032193dda5SAlan Stern 	 */
1042193dda5SAlan Stern 	if_ena.u64 = 0;
1052193dda5SAlan Stern 	if_ena.s.en = 1;
1062193dda5SAlan Stern 	cvmx_write_csr(CVMX_UCTLX_IF_ENA(0), if_ena.u64);
1072193dda5SAlan Stern 
1087e78db99SSteven J. Hill 	for (i = 0; i <= 1; i++) {
1097e78db99SSteven J. Hill 		port_ctl_status.u64 =
1107e78db99SSteven J. Hill 			cvmx_read_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0));
1117e78db99SSteven J. Hill 		/* Set txvreftune to 15 to obtain compliant 'eye' diagram. */
1127e78db99SSteven J. Hill 		port_ctl_status.s.txvreftune = 15;
1137e78db99SSteven J. Hill 		port_ctl_status.s.txrisetune = 1;
1147e78db99SSteven J. Hill 		port_ctl_status.s.txpreemphasistune = 1;
1157e78db99SSteven J. Hill 		cvmx_write_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0),
1167e78db99SSteven J. Hill 			       port_ctl_status.u64);
1177e78db99SSteven J. Hill 	}
1187e78db99SSteven J. Hill 
1192193dda5SAlan Stern 	/* Step 3: Configure the reference clock, PHY, and HCLK */
1202193dda5SAlan Stern 	clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
1212193dda5SAlan Stern 
1222193dda5SAlan Stern 	/*
1232193dda5SAlan Stern 	 * If the UCTL looks like it has already been started, skip
1242193dda5SAlan Stern 	 * the initialization, otherwise bus errors are obtained.
1252193dda5SAlan Stern 	 */
1262193dda5SAlan Stern 	if (clk_rst_ctl.s.hrst)
1272193dda5SAlan Stern 		goto end_clock;
1282193dda5SAlan Stern 	/* 3a */
1292193dda5SAlan Stern 	clk_rst_ctl.s.p_por = 1;
1302193dda5SAlan Stern 	clk_rst_ctl.s.hrst = 0;
1312193dda5SAlan Stern 	clk_rst_ctl.s.p_prst = 0;
1322193dda5SAlan Stern 	clk_rst_ctl.s.h_clkdiv_rst = 0;
1332193dda5SAlan Stern 	clk_rst_ctl.s.o_clkdiv_rst = 0;
1342193dda5SAlan Stern 	clk_rst_ctl.s.h_clkdiv_en = 0;
1352193dda5SAlan Stern 	clk_rst_ctl.s.o_clkdiv_en = 0;
1362193dda5SAlan Stern 	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
1372193dda5SAlan Stern 
1382193dda5SAlan Stern 	/* 3b */
139a95cfa6bSAndreas Herrmann 	clk_rst_ctl.s.p_refclk_sel = is_crystal_clock ? 0 : 1;
140a95cfa6bSAndreas Herrmann 	switch (clock_rate) {
141a95cfa6bSAndreas Herrmann 	default:
142a95cfa6bSAndreas Herrmann 		pr_err("Invalid UCTL clock rate of %u, using 12000000 instead\n",
143a95cfa6bSAndreas Herrmann 			clock_rate);
144a95cfa6bSAndreas Herrmann 		/* Fall through */
145a95cfa6bSAndreas Herrmann 	case 12000000:
1462193dda5SAlan Stern 		clk_rst_ctl.s.p_refclk_div = 0;
147a95cfa6bSAndreas Herrmann 		break;
148a95cfa6bSAndreas Herrmann 	case 24000000:
149a95cfa6bSAndreas Herrmann 		clk_rst_ctl.s.p_refclk_div = 1;
150a95cfa6bSAndreas Herrmann 		break;
151a95cfa6bSAndreas Herrmann 	case 48000000:
152a95cfa6bSAndreas Herrmann 		clk_rst_ctl.s.p_refclk_div = 2;
153a95cfa6bSAndreas Herrmann 		break;
154a95cfa6bSAndreas Herrmann 	}
1552193dda5SAlan Stern 	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
1562193dda5SAlan Stern 
1572193dda5SAlan Stern 	/* 3c */
1582193dda5SAlan Stern 	div = octeon_get_io_clock_rate() / 130000000ull;
1592193dda5SAlan Stern 
1602193dda5SAlan Stern 	switch (div) {
1612193dda5SAlan Stern 	case 0:
1622193dda5SAlan Stern 		div = 1;
1632193dda5SAlan Stern 		break;
1642193dda5SAlan Stern 	case 1:
1652193dda5SAlan Stern 	case 2:
1662193dda5SAlan Stern 	case 3:
1672193dda5SAlan Stern 	case 4:
1682193dda5SAlan Stern 		break;
1692193dda5SAlan Stern 	case 5:
1702193dda5SAlan Stern 		div = 4;
1712193dda5SAlan Stern 		break;
1722193dda5SAlan Stern 	case 6:
1732193dda5SAlan Stern 	case 7:
1742193dda5SAlan Stern 		div = 6;
1752193dda5SAlan Stern 		break;
1762193dda5SAlan Stern 	case 8:
1772193dda5SAlan Stern 	case 9:
1782193dda5SAlan Stern 	case 10:
1792193dda5SAlan Stern 	case 11:
1802193dda5SAlan Stern 		div = 8;
1812193dda5SAlan Stern 		break;
1822193dda5SAlan Stern 	default:
1832193dda5SAlan Stern 		div = 12;
1842193dda5SAlan Stern 		break;
1852193dda5SAlan Stern 	}
1862193dda5SAlan Stern 	clk_rst_ctl.s.h_div = div;
1872193dda5SAlan Stern 	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
1882193dda5SAlan Stern 	/* Read it back, */
1892193dda5SAlan Stern 	clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
1902193dda5SAlan Stern 	clk_rst_ctl.s.h_clkdiv_en = 1;
1912193dda5SAlan Stern 	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
1922193dda5SAlan Stern 	/* 3d */
1932193dda5SAlan Stern 	clk_rst_ctl.s.h_clkdiv_rst = 1;
1942193dda5SAlan Stern 	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
1952193dda5SAlan Stern 
1962193dda5SAlan Stern 	/* 3e: delay 64 io clocks */
1972193dda5SAlan Stern 	ndelay(io_clk_64_to_ns);
1982193dda5SAlan Stern 
1992193dda5SAlan Stern 	/*
2002193dda5SAlan Stern 	 * Step 4: Program the power-on reset field in the UCTL
2012193dda5SAlan Stern 	 * clock-reset-control register.
2022193dda5SAlan Stern 	 */
2032193dda5SAlan Stern 	clk_rst_ctl.s.p_por = 0;
2042193dda5SAlan Stern 	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
2052193dda5SAlan Stern 
2067e78db99SSteven J. Hill 	/* Step 5:    Wait 3 ms for the PHY clock to start. */
2077e78db99SSteven J. Hill 	mdelay(3);
2082193dda5SAlan Stern 
2097e78db99SSteven J. Hill 	/* Steps 6..9 for ATE only, are skipped. */
2102193dda5SAlan Stern 
2112193dda5SAlan Stern 	/* Step 10: Configure the OHCI_CLK48 and OHCI_CLK12 clocks. */
2122193dda5SAlan Stern 	/* 10a */
2132193dda5SAlan Stern 	clk_rst_ctl.s.o_clkdiv_rst = 1;
2142193dda5SAlan Stern 	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
2152193dda5SAlan Stern 
2162193dda5SAlan Stern 	/* 10b */
2172193dda5SAlan Stern 	clk_rst_ctl.s.o_clkdiv_en = 1;
2182193dda5SAlan Stern 	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
2192193dda5SAlan Stern 
2202193dda5SAlan Stern 	/* 10c */
2212193dda5SAlan Stern 	ndelay(io_clk_64_to_ns);
2222193dda5SAlan Stern 
2232193dda5SAlan Stern 	/*
2242193dda5SAlan Stern 	 * Step 11: Program the PHY reset field:
2252193dda5SAlan Stern 	 * UCTL0_CLK_RST_CTL[P_PRST] = 1
2262193dda5SAlan Stern 	 */
2272193dda5SAlan Stern 	clk_rst_ctl.s.p_prst = 1;
2282193dda5SAlan Stern 	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
2292193dda5SAlan Stern 
2307e78db99SSteven J. Hill 	/* Step 11b */
2317e78db99SSteven J. Hill 	udelay(1);
2327e78db99SSteven J. Hill 
2337e78db99SSteven J. Hill 	/* Step 11c */
2347e78db99SSteven J. Hill 	clk_rst_ctl.s.p_prst = 0;
2357e78db99SSteven J. Hill 	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
2367e78db99SSteven J. Hill 
2377e78db99SSteven J. Hill 	/* Step 11d */
2387e78db99SSteven J. Hill 	mdelay(1);
2397e78db99SSteven J. Hill 
2407e78db99SSteven J. Hill 	/* Step 11e */
2417e78db99SSteven J. Hill 	clk_rst_ctl.s.p_prst = 1;
2427e78db99SSteven J. Hill 	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
2437e78db99SSteven J. Hill 
2442193dda5SAlan Stern 	/* Step 12: Wait 1 uS. */
2452193dda5SAlan Stern 	udelay(1);
2462193dda5SAlan Stern 
2472193dda5SAlan Stern 	/* Step 13: Program the HRESET_N field: UCTL0_CLK_RST_CTL[HRST] = 1 */
2482193dda5SAlan Stern 	clk_rst_ctl.s.hrst = 1;
2492193dda5SAlan Stern 	cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
2502193dda5SAlan Stern 
2512193dda5SAlan Stern end_clock:
2522193dda5SAlan Stern 	/* Set uSOF cycle period to 60,000 bits. */
2532193dda5SAlan Stern 	cvmx_write_csr(CVMX_UCTLX_EHCI_FLA(0), 0x20ull);
2547e78db99SSteven J. Hill 
2552193dda5SAlan Stern exit:
2562193dda5SAlan Stern 	mutex_unlock(&octeon2_usb_clocks_mutex);
2572193dda5SAlan Stern }
2582193dda5SAlan Stern 
2592193dda5SAlan Stern static void octeon2_usb_clocks_stop(void)
2602193dda5SAlan Stern {
2612193dda5SAlan Stern 	mutex_lock(&octeon2_usb_clocks_mutex);
2622193dda5SAlan Stern 	octeon2_usb_clock_start_cnt--;
2632193dda5SAlan Stern 	mutex_unlock(&octeon2_usb_clocks_mutex);
2642193dda5SAlan Stern }
2652193dda5SAlan Stern 
2662193dda5SAlan Stern static int octeon_ehci_power_on(struct platform_device *pdev)
2672193dda5SAlan Stern {
268a95cfa6bSAndreas Herrmann 	octeon2_usb_clocks_start(&pdev->dev);
2692193dda5SAlan Stern 	return 0;
2702193dda5SAlan Stern }
2712193dda5SAlan Stern 
2722193dda5SAlan Stern static void octeon_ehci_power_off(struct platform_device *pdev)
2732193dda5SAlan Stern {
2742193dda5SAlan Stern 	octeon2_usb_clocks_stop();
2752193dda5SAlan Stern }
2762193dda5SAlan Stern 
2772193dda5SAlan Stern static struct usb_ehci_pdata octeon_ehci_pdata = {
2782193dda5SAlan Stern 	/* Octeon EHCI matches CPU endianness. */
2792193dda5SAlan Stern #ifdef __BIG_ENDIAN
2802193dda5SAlan Stern 	.big_endian_mmio	= 1,
2812193dda5SAlan Stern #endif
2828552b5b4SSteven J. Hill 	/*
2838552b5b4SSteven J. Hill 	 * We can DMA from anywhere. But the descriptors must be in
2848552b5b4SSteven J. Hill 	 * the lower 4GB.
2858552b5b4SSteven J. Hill 	 */
2868552b5b4SSteven J. Hill 	.dma_mask_64	= 0,
2872193dda5SAlan Stern 	.power_on	= octeon_ehci_power_on,
2882193dda5SAlan Stern 	.power_off	= octeon_ehci_power_off,
2892193dda5SAlan Stern };
2902193dda5SAlan Stern 
291a95cfa6bSAndreas Herrmann static void __init octeon_ehci_hw_start(struct device *dev)
2922193dda5SAlan Stern {
2932193dda5SAlan Stern 	union cvmx_uctlx_ehci_ctl ehci_ctl;
2942193dda5SAlan Stern 
295a95cfa6bSAndreas Herrmann 	octeon2_usb_clocks_start(dev);
2962193dda5SAlan Stern 
2972193dda5SAlan Stern 	ehci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_EHCI_CTL(0));
2982193dda5SAlan Stern 	/* Use 64-bit addressing. */
2992193dda5SAlan Stern 	ehci_ctl.s.ehci_64b_addr_en = 1;
3002193dda5SAlan Stern 	ehci_ctl.s.l2c_addr_msb = 0;
301b0abf36fSPaul Martin #ifdef __BIG_ENDIAN
3022193dda5SAlan Stern 	ehci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */
3032193dda5SAlan Stern 	ehci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */
304b0abf36fSPaul Martin #else
305b0abf36fSPaul Martin 	ehci_ctl.s.l2c_buff_emod = 0; /* not swapped. */
306b0abf36fSPaul Martin 	ehci_ctl.s.l2c_desc_emod = 0; /* not swapped. */
307b0abf36fSPaul Martin 	ehci_ctl.s.inv_reg_a2 = 1;
308b0abf36fSPaul Martin #endif
3092193dda5SAlan Stern 	cvmx_write_csr(CVMX_UCTLX_EHCI_CTL(0), ehci_ctl.u64);
3102193dda5SAlan Stern 
3112193dda5SAlan Stern 	octeon2_usb_clocks_stop();
3122193dda5SAlan Stern }
3132193dda5SAlan Stern 
314340fbb8bSDavid Daney static int __init octeon_ehci_device_init(void)
315340fbb8bSDavid Daney {
316340fbb8bSDavid Daney 	struct platform_device *pd;
317a95cfa6bSAndreas Herrmann 	struct device_node *ehci_node;
318340fbb8bSDavid Daney 	int ret = 0;
319340fbb8bSDavid Daney 
320a95cfa6bSAndreas Herrmann 	ehci_node = of_find_node_by_name(NULL, "ehci");
321a95cfa6bSAndreas Herrmann 	if (!ehci_node)
322340fbb8bSDavid Daney 		return 0;
323340fbb8bSDavid Daney 
324a95cfa6bSAndreas Herrmann 	pd = of_find_device_by_node(ehci_node);
325*b1259519SNicholas Mc Guire 	of_node_put(ehci_node);
326a95cfa6bSAndreas Herrmann 	if (!pd)
327a95cfa6bSAndreas Herrmann 		return 0;
328340fbb8bSDavid Daney 
3292193dda5SAlan Stern 	pd->dev.platform_data = &octeon_ehci_pdata;
330a95cfa6bSAndreas Herrmann 	octeon_ehci_hw_start(&pd->dev);
3312193dda5SAlan Stern 
332340fbb8bSDavid Daney 	return ret;
333340fbb8bSDavid Daney }
334340fbb8bSDavid Daney device_initcall(octeon_ehci_device_init);
335340fbb8bSDavid Daney 
3362193dda5SAlan Stern static int octeon_ohci_power_on(struct platform_device *pdev)
3372193dda5SAlan Stern {
338a95cfa6bSAndreas Herrmann 	octeon2_usb_clocks_start(&pdev->dev);
3392193dda5SAlan Stern 	return 0;
3402193dda5SAlan Stern }
3412193dda5SAlan Stern 
3422193dda5SAlan Stern static void octeon_ohci_power_off(struct platform_device *pdev)
3432193dda5SAlan Stern {
3442193dda5SAlan Stern 	octeon2_usb_clocks_stop();
3452193dda5SAlan Stern }
3462193dda5SAlan Stern 
3472193dda5SAlan Stern static struct usb_ohci_pdata octeon_ohci_pdata = {
3482193dda5SAlan Stern 	/* Octeon OHCI matches CPU endianness. */
3492193dda5SAlan Stern #ifdef __BIG_ENDIAN
3502193dda5SAlan Stern 	.big_endian_mmio	= 1,
3512193dda5SAlan Stern #endif
3522193dda5SAlan Stern 	.power_on	= octeon_ohci_power_on,
3532193dda5SAlan Stern 	.power_off	= octeon_ohci_power_off,
3542193dda5SAlan Stern };
3552193dda5SAlan Stern 
356a95cfa6bSAndreas Herrmann static void __init octeon_ohci_hw_start(struct device *dev)
3572193dda5SAlan Stern {
3582193dda5SAlan Stern 	union cvmx_uctlx_ohci_ctl ohci_ctl;
3592193dda5SAlan Stern 
360a95cfa6bSAndreas Herrmann 	octeon2_usb_clocks_start(dev);
3612193dda5SAlan Stern 
3622193dda5SAlan Stern 	ohci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_OHCI_CTL(0));
3632193dda5SAlan Stern 	ohci_ctl.s.l2c_addr_msb = 0;
364b0abf36fSPaul Martin #ifdef __BIG_ENDIAN
3652193dda5SAlan Stern 	ohci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */
3662193dda5SAlan Stern 	ohci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */
367b0abf36fSPaul Martin #else
368b0abf36fSPaul Martin 	ohci_ctl.s.l2c_buff_emod = 0; /* not swapped. */
369b0abf36fSPaul Martin 	ohci_ctl.s.l2c_desc_emod = 0; /* not swapped. */
370b0abf36fSPaul Martin 	ohci_ctl.s.inv_reg_a2 = 1;
371b0abf36fSPaul Martin #endif
3722193dda5SAlan Stern 	cvmx_write_csr(CVMX_UCTLX_OHCI_CTL(0), ohci_ctl.u64);
3732193dda5SAlan Stern 
3742193dda5SAlan Stern 	octeon2_usb_clocks_stop();
3752193dda5SAlan Stern }
3762193dda5SAlan Stern 
377340fbb8bSDavid Daney static int __init octeon_ohci_device_init(void)
378340fbb8bSDavid Daney {
379340fbb8bSDavid Daney 	struct platform_device *pd;
380a95cfa6bSAndreas Herrmann 	struct device_node *ohci_node;
381340fbb8bSDavid Daney 	int ret = 0;
382340fbb8bSDavid Daney 
383a95cfa6bSAndreas Herrmann 	ohci_node = of_find_node_by_name(NULL, "ohci");
384a95cfa6bSAndreas Herrmann 	if (!ohci_node)
385340fbb8bSDavid Daney 		return 0;
386340fbb8bSDavid Daney 
387a95cfa6bSAndreas Herrmann 	pd = of_find_device_by_node(ohci_node);
388*b1259519SNicholas Mc Guire 	of_node_put(ohci_node);
389a95cfa6bSAndreas Herrmann 	if (!pd)
390a95cfa6bSAndreas Herrmann 		return 0;
391340fbb8bSDavid Daney 
3922193dda5SAlan Stern 	pd->dev.platform_data = &octeon_ohci_pdata;
393a95cfa6bSAndreas Herrmann 	octeon_ohci_hw_start(&pd->dev);
3942193dda5SAlan Stern 
395340fbb8bSDavid Daney 	return ret;
396340fbb8bSDavid Daney }
397340fbb8bSDavid Daney device_initcall(octeon_ohci_device_init);
398340fbb8bSDavid Daney 
399340fbb8bSDavid Daney #endif /* CONFIG_USB */
400340fbb8bSDavid Daney 
4017fd57ab9SSteven J. Hill /* Octeon Random Number Generator.  */
4027fd57ab9SSteven J. Hill static int __init octeon_rng_device_init(void)
4037fd57ab9SSteven J. Hill {
4047fd57ab9SSteven J. Hill 	struct platform_device *pd;
4057fd57ab9SSteven J. Hill 	int ret = 0;
4067fd57ab9SSteven J. Hill 
4077fd57ab9SSteven J. Hill 	struct resource rng_resources[] = {
4087fd57ab9SSteven J. Hill 		{
4097fd57ab9SSteven J. Hill 			.flags	= IORESOURCE_MEM,
4107fd57ab9SSteven J. Hill 			.start	= XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS),
4117fd57ab9SSteven J. Hill 			.end	= XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS) + 0xf
4127fd57ab9SSteven J. Hill 		}, {
4137fd57ab9SSteven J. Hill 			.flags	= IORESOURCE_MEM,
4147fd57ab9SSteven J. Hill 			.start	= cvmx_build_io_address(8, 0),
4157fd57ab9SSteven J. Hill 			.end	= cvmx_build_io_address(8, 0) + 0x7
4167fd57ab9SSteven J. Hill 		}
4177fd57ab9SSteven J. Hill 	};
4187fd57ab9SSteven J. Hill 
4197fd57ab9SSteven J. Hill 	pd = platform_device_alloc("octeon_rng", -1);
4207fd57ab9SSteven J. Hill 	if (!pd) {
4217fd57ab9SSteven J. Hill 		ret = -ENOMEM;
4227fd57ab9SSteven J. Hill 		goto out;
4237fd57ab9SSteven J. Hill 	}
4247fd57ab9SSteven J. Hill 
4257fd57ab9SSteven J. Hill 	ret = platform_device_add_resources(pd, rng_resources,
4267fd57ab9SSteven J. Hill 					    ARRAY_SIZE(rng_resources));
4277fd57ab9SSteven J. Hill 	if (ret)
4287fd57ab9SSteven J. Hill 		goto fail;
4297fd57ab9SSteven J. Hill 
4307fd57ab9SSteven J. Hill 	ret = platform_device_add(pd);
4317fd57ab9SSteven J. Hill 	if (ret)
4327fd57ab9SSteven J. Hill 		goto fail;
4337fd57ab9SSteven J. Hill 
4347fd57ab9SSteven J. Hill 	return ret;
4357fd57ab9SSteven J. Hill fail:
4367fd57ab9SSteven J. Hill 	platform_device_put(pd);
4377fd57ab9SSteven J. Hill 
4387fd57ab9SSteven J. Hill out:
4397fd57ab9SSteven J. Hill 	return ret;
4407fd57ab9SSteven J. Hill }
4417fd57ab9SSteven J. Hill device_initcall(octeon_rng_device_init);
442a95cfa6bSAndreas Herrmann 
443e96b1b06SSteven J. Hill const struct of_device_id octeon_ids[] __initconst = {
4447ed18152SDavid Daney 	{ .compatible = "simple-bus", },
4457ed18152SDavid Daney 	{ .compatible = "cavium,octeon-6335-uctl", },
446d617f9e9SDavid Daney 	{ .compatible = "cavium,octeon-5750-usbn", },
4477ed18152SDavid Daney 	{ .compatible = "cavium,octeon-3860-bootbus", },
4487ed18152SDavid Daney 	{ .compatible = "cavium,mdio-mux", },
4497ed18152SDavid Daney 	{ .compatible = "gpio-leds", },
45093e502b3SSteven J. Hill 	{ .compatible = "cavium,octeon-7130-usb-uctl", },
4517ed18152SDavid Daney 	{},
4527ed18152SDavid Daney };
4537ed18152SDavid Daney 
4547ed18152SDavid Daney static bool __init octeon_has_88e1145(void)
4557ed18152SDavid Daney {
4567ed18152SDavid Daney 	return !OCTEON_IS_MODEL(OCTEON_CN52XX) &&
4577ed18152SDavid Daney 	       !OCTEON_IS_MODEL(OCTEON_CN6XXX) &&
4587ed18152SDavid Daney 	       !OCTEON_IS_MODEL(OCTEON_CN56XX);
4597ed18152SDavid Daney }
4607ed18152SDavid Daney 
4617ed18152SDavid Daney static void __init octeon_fdt_set_phy(int eth, int phy_addr)
4627ed18152SDavid Daney {
4637ed18152SDavid Daney 	const __be32 *phy_handle;
4647ed18152SDavid Daney 	const __be32 *alt_phy_handle;
4657ed18152SDavid Daney 	const __be32 *reg;
4667ed18152SDavid Daney 	u32 phandle;
4677ed18152SDavid Daney 	int phy;
4687ed18152SDavid Daney 	int alt_phy;
4697ed18152SDavid Daney 	const char *p;
4707ed18152SDavid Daney 	int current_len;
4717ed18152SDavid Daney 	char new_name[20];
4727ed18152SDavid Daney 
4737ed18152SDavid Daney 	phy_handle = fdt_getprop(initial_boot_params, eth, "phy-handle", NULL);
4747ed18152SDavid Daney 	if (!phy_handle)
4757ed18152SDavid Daney 		return;
4767ed18152SDavid Daney 
4777ed18152SDavid Daney 	phandle = be32_to_cpup(phy_handle);
4787ed18152SDavid Daney 	phy = fdt_node_offset_by_phandle(initial_boot_params, phandle);
4797ed18152SDavid Daney 
4807ed18152SDavid Daney 	alt_phy_handle = fdt_getprop(initial_boot_params, eth, "cavium,alt-phy-handle", NULL);
4817ed18152SDavid Daney 	if (alt_phy_handle) {
4827ed18152SDavid Daney 		u32 alt_phandle = be32_to_cpup(alt_phy_handle);
483e96b1b06SSteven J. Hill 
4847ed18152SDavid Daney 		alt_phy = fdt_node_offset_by_phandle(initial_boot_params, alt_phandle);
4857ed18152SDavid Daney 	} else {
4867ed18152SDavid Daney 		alt_phy = -1;
4877ed18152SDavid Daney 	}
4887ed18152SDavid Daney 
4897ed18152SDavid Daney 	if (phy_addr < 0 || phy < 0) {
4907ed18152SDavid Daney 		/* Delete the PHY things */
4917ed18152SDavid Daney 		fdt_nop_property(initial_boot_params, eth, "phy-handle");
4927ed18152SDavid Daney 		/* This one may fail */
4937ed18152SDavid Daney 		fdt_nop_property(initial_boot_params, eth, "cavium,alt-phy-handle");
4947ed18152SDavid Daney 		if (phy >= 0)
4957ed18152SDavid Daney 			fdt_nop_node(initial_boot_params, phy);
4967ed18152SDavid Daney 		if (alt_phy >= 0)
4977ed18152SDavid Daney 			fdt_nop_node(initial_boot_params, alt_phy);
4987ed18152SDavid Daney 		return;
4997ed18152SDavid Daney 	}
5007ed18152SDavid Daney 
5017ed18152SDavid Daney 	if (phy_addr >= 256 && alt_phy > 0) {
5027ed18152SDavid Daney 		const struct fdt_property *phy_prop;
5037ed18152SDavid Daney 		struct fdt_property *alt_prop;
5047ed18152SDavid Daney 		u32 phy_handle_name;
5057ed18152SDavid Daney 
5067ed18152SDavid Daney 		/* Use the alt phy node instead.*/
5077ed18152SDavid Daney 		phy_prop = fdt_get_property(initial_boot_params, eth, "phy-handle", NULL);
5087ed18152SDavid Daney 		phy_handle_name = phy_prop->nameoff;
5097ed18152SDavid Daney 		fdt_nop_node(initial_boot_params, phy);
5107ed18152SDavid Daney 		fdt_nop_property(initial_boot_params, eth, "phy-handle");
5117ed18152SDavid Daney 		alt_prop = fdt_get_property_w(initial_boot_params, eth, "cavium,alt-phy-handle", NULL);
5127ed18152SDavid Daney 		alt_prop->nameoff = phy_handle_name;
5137ed18152SDavid Daney 		phy = alt_phy;
5147ed18152SDavid Daney 	}
5157ed18152SDavid Daney 
5167ed18152SDavid Daney 	phy_addr &= 0xff;
5177ed18152SDavid Daney 
5187ed18152SDavid Daney 	if (octeon_has_88e1145()) {
5197ed18152SDavid Daney 		fdt_nop_property(initial_boot_params, phy, "marvell,reg-init");
5207ed18152SDavid Daney 		memset(new_name, 0, sizeof(new_name));
5217ed18152SDavid Daney 		strcpy(new_name, "marvell,88e1145");
5227ed18152SDavid Daney 		p = fdt_getprop(initial_boot_params, phy, "compatible",
5237ed18152SDavid Daney 				&current_len);
5247ed18152SDavid Daney 		if (p && current_len >= strlen(new_name))
5257ed18152SDavid Daney 			fdt_setprop_inplace(initial_boot_params, phy,
5267ed18152SDavid Daney 					"compatible", new_name, current_len);
5277ed18152SDavid Daney 	}
5287ed18152SDavid Daney 
5297ed18152SDavid Daney 	reg = fdt_getprop(initial_boot_params, phy, "reg", NULL);
5307ed18152SDavid Daney 	if (phy_addr == be32_to_cpup(reg))
5317ed18152SDavid Daney 		return;
5327ed18152SDavid Daney 
5337ed18152SDavid Daney 	fdt_setprop_inplace_cell(initial_boot_params, phy, "reg", phy_addr);
5347ed18152SDavid Daney 
5357ed18152SDavid Daney 	snprintf(new_name, sizeof(new_name), "ethernet-phy@%x", phy_addr);
5367ed18152SDavid Daney 
5377ed18152SDavid Daney 	p = fdt_get_name(initial_boot_params, phy, &current_len);
5387ed18152SDavid Daney 	if (p && current_len == strlen(new_name))
5397ed18152SDavid Daney 		fdt_set_name(initial_boot_params, phy, new_name);
5407ed18152SDavid Daney 	else
5417ed18152SDavid Daney 		pr_err("Error: could not rename ethernet phy: <%s>", p);
5427ed18152SDavid Daney }
5437ed18152SDavid Daney 
5447ed18152SDavid Daney static void __init octeon_fdt_set_mac_addr(int n, u64 *pmac)
5457ed18152SDavid Daney {
546377de399SAaro Koskinen 	const u8 *old_mac;
547377de399SAaro Koskinen 	int old_len;
5487ed18152SDavid Daney 	u8 new_mac[6];
5497ed18152SDavid Daney 	u64 mac = *pmac;
5507ed18152SDavid Daney 	int r;
5517ed18152SDavid Daney 
552377de399SAaro Koskinen 	old_mac = fdt_getprop(initial_boot_params, n, "local-mac-address",
553377de399SAaro Koskinen 			      &old_len);
554377de399SAaro Koskinen 	if (!old_mac || old_len != 6 || is_valid_ether_addr(old_mac))
555377de399SAaro Koskinen 		return;
556377de399SAaro Koskinen 
5577ed18152SDavid Daney 	new_mac[0] = (mac >> 40) & 0xff;
5587ed18152SDavid Daney 	new_mac[1] = (mac >> 32) & 0xff;
5597ed18152SDavid Daney 	new_mac[2] = (mac >> 24) & 0xff;
5607ed18152SDavid Daney 	new_mac[3] = (mac >> 16) & 0xff;
5617ed18152SDavid Daney 	new_mac[4] = (mac >> 8) & 0xff;
5627ed18152SDavid Daney 	new_mac[5] = mac & 0xff;
5637ed18152SDavid Daney 
5647ed18152SDavid Daney 	r = fdt_setprop_inplace(initial_boot_params, n, "local-mac-address",
5657ed18152SDavid Daney 				new_mac, sizeof(new_mac));
5667ed18152SDavid Daney 
5677ed18152SDavid Daney 	if (r) {
5687ed18152SDavid Daney 		pr_err("Setting \"local-mac-address\" failed %d", r);
5697ed18152SDavid Daney 		return;
5707ed18152SDavid Daney 	}
5717ed18152SDavid Daney 	*pmac = mac + 1;
5727ed18152SDavid Daney }
5737ed18152SDavid Daney 
5747ed18152SDavid Daney static void __init octeon_fdt_rm_ethernet(int node)
5757ed18152SDavid Daney {
5767ed18152SDavid Daney 	const __be32 *phy_handle;
5777ed18152SDavid Daney 
5787ed18152SDavid Daney 	phy_handle = fdt_getprop(initial_boot_params, node, "phy-handle", NULL);
5797ed18152SDavid Daney 	if (phy_handle) {
5807ed18152SDavid Daney 		u32 ph = be32_to_cpup(phy_handle);
5817ed18152SDavid Daney 		int p = fdt_node_offset_by_phandle(initial_boot_params, ph);
582e96b1b06SSteven J. Hill 
5837ed18152SDavid Daney 		if (p >= 0)
5847ed18152SDavid Daney 			fdt_nop_node(initial_boot_params, p);
5857ed18152SDavid Daney 	}
5867ed18152SDavid Daney 	fdt_nop_node(initial_boot_params, node);
5877ed18152SDavid Daney }
5887ed18152SDavid Daney 
58943349b9eSAaro Koskinen static void __init octeon_fdt_pip_port(int iface, int i, int p, int max)
5907ed18152SDavid Daney {
5917ed18152SDavid Daney 	char name_buffer[20];
5927ed18152SDavid Daney 	int eth;
5937ed18152SDavid Daney 	int phy_addr;
5947ed18152SDavid Daney 	int ipd_port;
5957ed18152SDavid Daney 
5967ed18152SDavid Daney 	snprintf(name_buffer, sizeof(name_buffer), "ethernet@%x", p);
5977ed18152SDavid Daney 	eth = fdt_subnode_offset(initial_boot_params, iface, name_buffer);
5987ed18152SDavid Daney 	if (eth < 0)
5997ed18152SDavid Daney 		return;
6007ed18152SDavid Daney 	if (p > max) {
6017ed18152SDavid Daney 		pr_debug("Deleting port %x:%x\n", i, p);
6027ed18152SDavid Daney 		octeon_fdt_rm_ethernet(eth);
6037ed18152SDavid Daney 		return;
6047ed18152SDavid Daney 	}
6057ed18152SDavid Daney 	if (OCTEON_IS_MODEL(OCTEON_CN68XX))
6067ed18152SDavid Daney 		ipd_port = (0x100 * i) + (0x10 * p) + 0x800;
6077ed18152SDavid Daney 	else
6087ed18152SDavid Daney 		ipd_port = 16 * i + p;
6097ed18152SDavid Daney 
6107ed18152SDavid Daney 	phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
6117ed18152SDavid Daney 	octeon_fdt_set_phy(eth, phy_addr);
6127ed18152SDavid Daney }
6137ed18152SDavid Daney 
61443349b9eSAaro Koskinen static void __init octeon_fdt_pip_iface(int pip, int idx)
6157ed18152SDavid Daney {
6167ed18152SDavid Daney 	char name_buffer[20];
6177ed18152SDavid Daney 	int iface;
6187ed18152SDavid Daney 	int p;
619ab2bb148SFaidon Liambotis 	int count = 0;
6207ed18152SDavid Daney 
6217ed18152SDavid Daney 	snprintf(name_buffer, sizeof(name_buffer), "interface@%d", idx);
6227ed18152SDavid Daney 	iface = fdt_subnode_offset(initial_boot_params, pip, name_buffer);
6237ed18152SDavid Daney 	if (iface < 0)
6247ed18152SDavid Daney 		return;
6257ed18152SDavid Daney 
626b2e4f156SAaro Koskinen 	if (cvmx_helper_interface_enumerate(idx) == 0)
627b2e4f156SAaro Koskinen 		count = cvmx_helper_ports_on_interface(idx);
628b2e4f156SAaro Koskinen 
6297ed18152SDavid Daney 	for (p = 0; p < 16; p++)
63043349b9eSAaro Koskinen 		octeon_fdt_pip_port(iface, idx, p, count - 1);
63143349b9eSAaro Koskinen }
63243349b9eSAaro Koskinen 
63343349b9eSAaro Koskinen void __init octeon_fill_mac_addresses(void)
63443349b9eSAaro Koskinen {
63543349b9eSAaro Koskinen 	const char *alias_prop;
63643349b9eSAaro Koskinen 	char name_buffer[20];
63743349b9eSAaro Koskinen 	u64 mac_addr_base;
63843349b9eSAaro Koskinen 	int aliases;
63943349b9eSAaro Koskinen 	int pip;
64043349b9eSAaro Koskinen 	int i;
64143349b9eSAaro Koskinen 
64243349b9eSAaro Koskinen 	aliases = fdt_path_offset(initial_boot_params, "/aliases");
64343349b9eSAaro Koskinen 	if (aliases < 0)
64443349b9eSAaro Koskinen 		return;
64543349b9eSAaro Koskinen 
64643349b9eSAaro Koskinen 	mac_addr_base =
64743349b9eSAaro Koskinen 		((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 |
64843349b9eSAaro Koskinen 		((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 |
64943349b9eSAaro Koskinen 		((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 |
65043349b9eSAaro Koskinen 		((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 |
65143349b9eSAaro Koskinen 		((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 |
65243349b9eSAaro Koskinen 		 (octeon_bootinfo->mac_addr_base[5] & 0xffull);
65343349b9eSAaro Koskinen 
65443349b9eSAaro Koskinen 	for (i = 0; i < 2; i++) {
65543349b9eSAaro Koskinen 		int mgmt;
65643349b9eSAaro Koskinen 
65743349b9eSAaro Koskinen 		snprintf(name_buffer, sizeof(name_buffer), "mix%d", i);
65843349b9eSAaro Koskinen 		alias_prop = fdt_getprop(initial_boot_params, aliases,
65943349b9eSAaro Koskinen 					 name_buffer, NULL);
66043349b9eSAaro Koskinen 		if (!alias_prop)
66143349b9eSAaro Koskinen 			continue;
66243349b9eSAaro Koskinen 		mgmt = fdt_path_offset(initial_boot_params, alias_prop);
66343349b9eSAaro Koskinen 		if (mgmt < 0)
66443349b9eSAaro Koskinen 			continue;
66543349b9eSAaro Koskinen 		octeon_fdt_set_mac_addr(mgmt, &mac_addr_base);
66643349b9eSAaro Koskinen 	}
66743349b9eSAaro Koskinen 
66843349b9eSAaro Koskinen 	alias_prop = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
66943349b9eSAaro Koskinen 	if (!alias_prop)
67043349b9eSAaro Koskinen 		return;
67143349b9eSAaro Koskinen 
67243349b9eSAaro Koskinen 	pip = fdt_path_offset(initial_boot_params, alias_prop);
67343349b9eSAaro Koskinen 	if (pip < 0)
67443349b9eSAaro Koskinen 		return;
67543349b9eSAaro Koskinen 
67643349b9eSAaro Koskinen 	for (i = 0; i <= 4; i++) {
67743349b9eSAaro Koskinen 		int iface;
67843349b9eSAaro Koskinen 		int p;
67943349b9eSAaro Koskinen 
68043349b9eSAaro Koskinen 		snprintf(name_buffer, sizeof(name_buffer), "interface@%d", i);
68143349b9eSAaro Koskinen 		iface = fdt_subnode_offset(initial_boot_params, pip,
68243349b9eSAaro Koskinen 					   name_buffer);
68343349b9eSAaro Koskinen 		if (iface < 0)
68443349b9eSAaro Koskinen 			continue;
68543349b9eSAaro Koskinen 		for (p = 0; p < 16; p++) {
68643349b9eSAaro Koskinen 			int eth;
68743349b9eSAaro Koskinen 
68843349b9eSAaro Koskinen 			snprintf(name_buffer, sizeof(name_buffer),
68943349b9eSAaro Koskinen 				 "ethernet@%x", p);
69043349b9eSAaro Koskinen 			eth = fdt_subnode_offset(initial_boot_params, iface,
69143349b9eSAaro Koskinen 						 name_buffer);
69243349b9eSAaro Koskinen 			if (eth < 0)
69343349b9eSAaro Koskinen 				continue;
69443349b9eSAaro Koskinen 			octeon_fdt_set_mac_addr(eth, &mac_addr_base);
69543349b9eSAaro Koskinen 		}
69643349b9eSAaro Koskinen 	}
6977ed18152SDavid Daney }
6987ed18152SDavid Daney 
6997ed18152SDavid Daney int __init octeon_prune_device_tree(void)
7007ed18152SDavid Daney {
7017ed18152SDavid Daney 	int i, max_port, uart_mask;
7027ed18152SDavid Daney 	const char *pip_path;
7037ed18152SDavid Daney 	const char *alias_prop;
7047ed18152SDavid Daney 	char name_buffer[20];
7057ed18152SDavid Daney 	int aliases;
7067ed18152SDavid Daney 
7077ed18152SDavid Daney 	if (fdt_check_header(initial_boot_params))
7087ed18152SDavid Daney 		panic("Corrupt Device Tree.");
7097ed18152SDavid Daney 
71086bee12fSAaro Koskinen 	WARN(octeon_bootinfo->board_type == CVMX_BOARD_TYPE_CUST_DSR1000N,
71186bee12fSAaro Koskinen 	     "Built-in DTB booting is deprecated on %s. Please switch to use appended DTB.",
71286bee12fSAaro Koskinen 	     cvmx_board_type_to_string(octeon_bootinfo->board_type));
71386bee12fSAaro Koskinen 
7147ed18152SDavid Daney 	aliases = fdt_path_offset(initial_boot_params, "/aliases");
7157ed18152SDavid Daney 	if (aliases < 0) {
7167ed18152SDavid Daney 		pr_err("Error: No /aliases node in device tree.");
7177ed18152SDavid Daney 		return -EINVAL;
7187ed18152SDavid Daney 	}
7197ed18152SDavid Daney 
7207ed18152SDavid Daney 	if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))
7217ed18152SDavid Daney 		max_port = 2;
7227ed18152SDavid Daney 	else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN68XX))
7237ed18152SDavid Daney 		max_port = 1;
7247ed18152SDavid Daney 	else
7257ed18152SDavid Daney 		max_port = 0;
7267ed18152SDavid Daney 
7277ed18152SDavid Daney 	if (octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC10E)
7287ed18152SDavid Daney 		max_port = 0;
7297ed18152SDavid Daney 
7307ed18152SDavid Daney 	for (i = 0; i < 2; i++) {
7317ed18152SDavid Daney 		int mgmt;
732e96b1b06SSteven J. Hill 
7337ed18152SDavid Daney 		snprintf(name_buffer, sizeof(name_buffer),
7347ed18152SDavid Daney 			 "mix%d", i);
7357ed18152SDavid Daney 		alias_prop = fdt_getprop(initial_boot_params, aliases,
7367ed18152SDavid Daney 					name_buffer, NULL);
7377ed18152SDavid Daney 		if (alias_prop) {
7387ed18152SDavid Daney 			mgmt = fdt_path_offset(initial_boot_params, alias_prop);
7397ed18152SDavid Daney 			if (mgmt < 0)
7407ed18152SDavid Daney 				continue;
7417ed18152SDavid Daney 			if (i >= max_port) {
7427ed18152SDavid Daney 				pr_debug("Deleting mix%d\n", i);
7437ed18152SDavid Daney 				octeon_fdt_rm_ethernet(mgmt);
7447ed18152SDavid Daney 				fdt_nop_property(initial_boot_params, aliases,
7457ed18152SDavid Daney 						 name_buffer);
7467ed18152SDavid Daney 			} else {
7477ed18152SDavid Daney 				int phy_addr = cvmx_helper_board_get_mii_address(CVMX_HELPER_BOARD_MGMT_IPD_PORT + i);
748e96b1b06SSteven J. Hill 
7497ed18152SDavid Daney 				octeon_fdt_set_phy(mgmt, phy_addr);
7507ed18152SDavid Daney 			}
7517ed18152SDavid Daney 		}
7527ed18152SDavid Daney 	}
7537ed18152SDavid Daney 
7547ed18152SDavid Daney 	pip_path = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
7557ed18152SDavid Daney 	if (pip_path) {
7567ed18152SDavid Daney 		int pip = fdt_path_offset(initial_boot_params, pip_path);
757e96b1b06SSteven J. Hill 
7587ed18152SDavid Daney 		if (pip	 >= 0)
7597ed18152SDavid Daney 			for (i = 0; i <= 4; i++)
76043349b9eSAaro Koskinen 				octeon_fdt_pip_iface(pip, i);
7617ed18152SDavid Daney 	}
7627ed18152SDavid Daney 
7637ed18152SDavid Daney 	/* I2C */
7647ed18152SDavid Daney 	if (OCTEON_IS_MODEL(OCTEON_CN52XX) ||
7657ed18152SDavid Daney 	    OCTEON_IS_MODEL(OCTEON_CN63XX) ||
7667ed18152SDavid Daney 	    OCTEON_IS_MODEL(OCTEON_CN68XX) ||
7677ed18152SDavid Daney 	    OCTEON_IS_MODEL(OCTEON_CN56XX))
7687ed18152SDavid Daney 		max_port = 2;
7697ed18152SDavid Daney 	else
7707ed18152SDavid Daney 		max_port = 1;
7717ed18152SDavid Daney 
7727ed18152SDavid Daney 	for (i = 0; i < 2; i++) {
7737ed18152SDavid Daney 		int i2c;
774e96b1b06SSteven J. Hill 
7757ed18152SDavid Daney 		snprintf(name_buffer, sizeof(name_buffer),
7767ed18152SDavid Daney 			 "twsi%d", i);
7777ed18152SDavid Daney 		alias_prop = fdt_getprop(initial_boot_params, aliases,
7787ed18152SDavid Daney 					name_buffer, NULL);
7797ed18152SDavid Daney 
7807ed18152SDavid Daney 		if (alias_prop) {
7817ed18152SDavid Daney 			i2c = fdt_path_offset(initial_boot_params, alias_prop);
7827ed18152SDavid Daney 			if (i2c < 0)
7837ed18152SDavid Daney 				continue;
7847ed18152SDavid Daney 			if (i >= max_port) {
7857ed18152SDavid Daney 				pr_debug("Deleting twsi%d\n", i);
7867ed18152SDavid Daney 				fdt_nop_node(initial_boot_params, i2c);
7877ed18152SDavid Daney 				fdt_nop_property(initial_boot_params, aliases,
7887ed18152SDavid Daney 						 name_buffer);
7897ed18152SDavid Daney 			}
7907ed18152SDavid Daney 		}
7917ed18152SDavid Daney 	}
7927ed18152SDavid Daney 
7937ed18152SDavid Daney 	/* SMI/MDIO */
7947ed18152SDavid Daney 	if (OCTEON_IS_MODEL(OCTEON_CN68XX))
7957ed18152SDavid Daney 		max_port = 4;
7967ed18152SDavid Daney 	else if (OCTEON_IS_MODEL(OCTEON_CN52XX) ||
7977ed18152SDavid Daney 		 OCTEON_IS_MODEL(OCTEON_CN63XX) ||
7987ed18152SDavid Daney 		 OCTEON_IS_MODEL(OCTEON_CN56XX))
7997ed18152SDavid Daney 		max_port = 2;
8007ed18152SDavid Daney 	else
8017ed18152SDavid Daney 		max_port = 1;
8027ed18152SDavid Daney 
8037ed18152SDavid Daney 	for (i = 0; i < 2; i++) {
8047ed18152SDavid Daney 		int i2c;
805e96b1b06SSteven J. Hill 
8067ed18152SDavid Daney 		snprintf(name_buffer, sizeof(name_buffer),
8077ed18152SDavid Daney 			 "smi%d", i);
8087ed18152SDavid Daney 		alias_prop = fdt_getprop(initial_boot_params, aliases,
8097ed18152SDavid Daney 					name_buffer, NULL);
8107ed18152SDavid Daney 		if (alias_prop) {
8117ed18152SDavid Daney 			i2c = fdt_path_offset(initial_boot_params, alias_prop);
8127ed18152SDavid Daney 			if (i2c < 0)
8137ed18152SDavid Daney 				continue;
8147ed18152SDavid Daney 			if (i >= max_port) {
8157ed18152SDavid Daney 				pr_debug("Deleting smi%d\n", i);
8167ed18152SDavid Daney 				fdt_nop_node(initial_boot_params, i2c);
8177ed18152SDavid Daney 				fdt_nop_property(initial_boot_params, aliases,
8187ed18152SDavid Daney 						 name_buffer);
8197ed18152SDavid Daney 			}
8207ed18152SDavid Daney 		}
8217ed18152SDavid Daney 	}
8227ed18152SDavid Daney 
8237ed18152SDavid Daney 	/* Serial */
8247ed18152SDavid Daney 	uart_mask = 3;
8257ed18152SDavid Daney 
8267ed18152SDavid Daney 	/* Right now CN52XX is the only chip with a third uart */
8277ed18152SDavid Daney 	if (OCTEON_IS_MODEL(OCTEON_CN52XX))
8287ed18152SDavid Daney 		uart_mask |= 4; /* uart2 */
8297ed18152SDavid Daney 
8307ed18152SDavid Daney 	for (i = 0; i < 3; i++) {
8317ed18152SDavid Daney 		int uart;
832e96b1b06SSteven J. Hill 
8337ed18152SDavid Daney 		snprintf(name_buffer, sizeof(name_buffer),
8347ed18152SDavid Daney 			 "uart%d", i);
8357ed18152SDavid Daney 		alias_prop = fdt_getprop(initial_boot_params, aliases,
8367ed18152SDavid Daney 					name_buffer, NULL);
8377ed18152SDavid Daney 
8387ed18152SDavid Daney 		if (alias_prop) {
8397ed18152SDavid Daney 			uart = fdt_path_offset(initial_boot_params, alias_prop);
8405219343fSDavid Daney 			if (uart_mask & (1 << i)) {
8415219343fSDavid Daney 				__be32 f;
8425219343fSDavid Daney 
8435219343fSDavid Daney 				f = cpu_to_be32(octeon_get_io_clock_rate());
8445219343fSDavid Daney 				fdt_setprop_inplace(initial_boot_params,
8455219343fSDavid Daney 						    uart, "clock-frequency",
8465219343fSDavid Daney 						    &f, sizeof(f));
8477ed18152SDavid Daney 				continue;
8485219343fSDavid Daney 			}
8497ed18152SDavid Daney 			pr_debug("Deleting uart%d\n", i);
8507ed18152SDavid Daney 			fdt_nop_node(initial_boot_params, uart);
8517ed18152SDavid Daney 			fdt_nop_property(initial_boot_params, aliases,
8527ed18152SDavid Daney 					 name_buffer);
8537ed18152SDavid Daney 		}
8547ed18152SDavid Daney 	}
8557ed18152SDavid Daney 
8567ed18152SDavid Daney 	/* Compact Flash */
8577ed18152SDavid Daney 	alias_prop = fdt_getprop(initial_boot_params, aliases,
8587ed18152SDavid Daney 				 "cf0", NULL);
8597ed18152SDavid Daney 	if (alias_prop) {
8607ed18152SDavid Daney 		union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg;
8617ed18152SDavid Daney 		unsigned long base_ptr, region_base, region_size;
8627ed18152SDavid Daney 		unsigned long region1_base = 0;
8637ed18152SDavid Daney 		unsigned long region1_size = 0;
8647ed18152SDavid Daney 		int cs, bootbus;
8657ed18152SDavid Daney 		bool is_16bit = false;
8667ed18152SDavid Daney 		bool is_true_ide = false;
8677ed18152SDavid Daney 		__be32 new_reg[6];
8687ed18152SDavid Daney 		__be32 *ranges;
8697ed18152SDavid Daney 		int len;
8707ed18152SDavid Daney 
8717ed18152SDavid Daney 		int cf = fdt_path_offset(initial_boot_params, alias_prop);
872e96b1b06SSteven J. Hill 
8737ed18152SDavid Daney 		base_ptr = 0;
8747ed18152SDavid Daney 		if (octeon_bootinfo->major_version == 1
8757ed18152SDavid Daney 			&& octeon_bootinfo->minor_version >= 1) {
8767ed18152SDavid Daney 			if (octeon_bootinfo->compact_flash_common_base_addr)
8777ed18152SDavid Daney 				base_ptr = octeon_bootinfo->compact_flash_common_base_addr;
8787ed18152SDavid Daney 		} else {
8797ed18152SDavid Daney 			base_ptr = 0x1d000800;
8807ed18152SDavid Daney 		}
8817ed18152SDavid Daney 
8827ed18152SDavid Daney 		if (!base_ptr)
8837ed18152SDavid Daney 			goto no_cf;
8847ed18152SDavid Daney 
8857ed18152SDavid Daney 		/* Find CS0 region. */
8867ed18152SDavid Daney 		for (cs = 0; cs < 8; cs++) {
8877ed18152SDavid Daney 			mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
8887ed18152SDavid Daney 			region_base = mio_boot_reg_cfg.s.base << 16;
8897ed18152SDavid Daney 			region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
8907ed18152SDavid Daney 			if (mio_boot_reg_cfg.s.en && base_ptr >= region_base
8917ed18152SDavid Daney 				&& base_ptr < region_base + region_size) {
8927ed18152SDavid Daney 				is_16bit = mio_boot_reg_cfg.s.width;
8937ed18152SDavid Daney 				break;
8947ed18152SDavid Daney 			}
8957ed18152SDavid Daney 		}
8967ed18152SDavid Daney 		if (cs >= 7) {
8977ed18152SDavid Daney 			/* cs and cs + 1 are CS0 and CS1, both must be less than 8. */
8987ed18152SDavid Daney 			goto no_cf;
8997ed18152SDavid Daney 		}
9007ed18152SDavid Daney 
9017ed18152SDavid Daney 		if (!(base_ptr & 0xfffful)) {
9027ed18152SDavid Daney 			/*
9037ed18152SDavid Daney 			 * Boot loader signals availability of DMA (true_ide
9047ed18152SDavid Daney 			 * mode) by setting low order bits of base_ptr to
9057ed18152SDavid Daney 			 * zero.
9067ed18152SDavid Daney 			 */
9077ed18152SDavid Daney 
9087ed18152SDavid Daney 			/* Asume that CS1 immediately follows. */
9097ed18152SDavid Daney 			mio_boot_reg_cfg.u64 =
9107ed18152SDavid Daney 				cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs + 1));
9117ed18152SDavid Daney 			region1_base = mio_boot_reg_cfg.s.base << 16;
9127ed18152SDavid Daney 			region1_size = (mio_boot_reg_cfg.s.size + 1) << 16;
9137ed18152SDavid Daney 			if (!mio_boot_reg_cfg.s.en)
9147ed18152SDavid Daney 				goto no_cf;
9157ed18152SDavid Daney 			is_true_ide = true;
9167ed18152SDavid Daney 
9177ed18152SDavid Daney 		} else {
9187ed18152SDavid Daney 			fdt_nop_property(initial_boot_params, cf, "cavium,true-ide");
9197ed18152SDavid Daney 			fdt_nop_property(initial_boot_params, cf, "cavium,dma-engine-handle");
9207ed18152SDavid Daney 			if (!is_16bit) {
9217ed18152SDavid Daney 				__be32 width = cpu_to_be32(8);
922e96b1b06SSteven J. Hill 
9237ed18152SDavid Daney 				fdt_setprop_inplace(initial_boot_params, cf,
9247ed18152SDavid Daney 						"cavium,bus-width", &width, sizeof(width));
9257ed18152SDavid Daney 			}
9267ed18152SDavid Daney 		}
9277ed18152SDavid Daney 		new_reg[0] = cpu_to_be32(cs);
9287ed18152SDavid Daney 		new_reg[1] = cpu_to_be32(0);
9297ed18152SDavid Daney 		new_reg[2] = cpu_to_be32(0x10000);
9307ed18152SDavid Daney 		new_reg[3] = cpu_to_be32(cs + 1);
9317ed18152SDavid Daney 		new_reg[4] = cpu_to_be32(0);
9327ed18152SDavid Daney 		new_reg[5] = cpu_to_be32(0x10000);
9337ed18152SDavid Daney 		fdt_setprop_inplace(initial_boot_params, cf,
9347ed18152SDavid Daney 				    "reg",  new_reg, sizeof(new_reg));
9357ed18152SDavid Daney 
9367ed18152SDavid Daney 		bootbus = fdt_parent_offset(initial_boot_params, cf);
9377ed18152SDavid Daney 		if (bootbus < 0)
9387ed18152SDavid Daney 			goto no_cf;
9397ed18152SDavid Daney 		ranges = fdt_getprop_w(initial_boot_params, bootbus, "ranges", &len);
9407ed18152SDavid Daney 		if (!ranges || len < (5 * 8 * sizeof(__be32)))
9417ed18152SDavid Daney 			goto no_cf;
9427ed18152SDavid Daney 
9437ed18152SDavid Daney 		ranges[(cs * 5) + 2] = cpu_to_be32(region_base >> 32);
9447ed18152SDavid Daney 		ranges[(cs * 5) + 3] = cpu_to_be32(region_base & 0xffffffff);
9457ed18152SDavid Daney 		ranges[(cs * 5) + 4] = cpu_to_be32(region_size);
9467ed18152SDavid Daney 		if (is_true_ide) {
9477ed18152SDavid Daney 			cs++;
9487ed18152SDavid Daney 			ranges[(cs * 5) + 2] = cpu_to_be32(region1_base >> 32);
9497ed18152SDavid Daney 			ranges[(cs * 5) + 3] = cpu_to_be32(region1_base & 0xffffffff);
9507ed18152SDavid Daney 			ranges[(cs * 5) + 4] = cpu_to_be32(region1_size);
9517ed18152SDavid Daney 		}
9527ed18152SDavid Daney 		goto end_cf;
9537ed18152SDavid Daney no_cf:
9547ed18152SDavid Daney 		fdt_nop_node(initial_boot_params, cf);
9557ed18152SDavid Daney 
9567ed18152SDavid Daney end_cf:
9577ed18152SDavid Daney 		;
9587ed18152SDavid Daney 	}
9597ed18152SDavid Daney 
9607ed18152SDavid Daney 	/* 8 char LED */
9617ed18152SDavid Daney 	alias_prop = fdt_getprop(initial_boot_params, aliases,
9627ed18152SDavid Daney 				 "led0", NULL);
9637ed18152SDavid Daney 	if (alias_prop) {
9647ed18152SDavid Daney 		union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg;
9657ed18152SDavid Daney 		unsigned long base_ptr, region_base, region_size;
9667ed18152SDavid Daney 		int cs, bootbus;
9677ed18152SDavid Daney 		__be32 new_reg[6];
9687ed18152SDavid Daney 		__be32 *ranges;
9697ed18152SDavid Daney 		int len;
9707ed18152SDavid Daney 		int led = fdt_path_offset(initial_boot_params, alias_prop);
9717ed18152SDavid Daney 
9727ed18152SDavid Daney 		base_ptr = octeon_bootinfo->led_display_base_addr;
9737ed18152SDavid Daney 		if (base_ptr == 0)
9747ed18152SDavid Daney 			goto no_led;
9757ed18152SDavid Daney 		/* Find CS0 region. */
9767ed18152SDavid Daney 		for (cs = 0; cs < 8; cs++) {
9777ed18152SDavid Daney 			mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
9787ed18152SDavid Daney 			region_base = mio_boot_reg_cfg.s.base << 16;
9797ed18152SDavid Daney 			region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
9807ed18152SDavid Daney 			if (mio_boot_reg_cfg.s.en && base_ptr >= region_base
9817ed18152SDavid Daney 				&& base_ptr < region_base + region_size)
9827ed18152SDavid Daney 				break;
9837ed18152SDavid Daney 		}
9847ed18152SDavid Daney 
9857ed18152SDavid Daney 		if (cs > 7)
9867ed18152SDavid Daney 			goto no_led;
9877ed18152SDavid Daney 
9887ed18152SDavid Daney 		new_reg[0] = cpu_to_be32(cs);
9897ed18152SDavid Daney 		new_reg[1] = cpu_to_be32(0x20);
9907ed18152SDavid Daney 		new_reg[2] = cpu_to_be32(0x20);
9917ed18152SDavid Daney 		new_reg[3] = cpu_to_be32(cs);
9927ed18152SDavid Daney 		new_reg[4] = cpu_to_be32(0);
9937ed18152SDavid Daney 		new_reg[5] = cpu_to_be32(0x20);
9947ed18152SDavid Daney 		fdt_setprop_inplace(initial_boot_params, led,
9957ed18152SDavid Daney 				    "reg",  new_reg, sizeof(new_reg));
9967ed18152SDavid Daney 
9977ed18152SDavid Daney 		bootbus = fdt_parent_offset(initial_boot_params, led);
9987ed18152SDavid Daney 		if (bootbus < 0)
9997ed18152SDavid Daney 			goto no_led;
10007ed18152SDavid Daney 		ranges = fdt_getprop_w(initial_boot_params, bootbus, "ranges", &len);
10017ed18152SDavid Daney 		if (!ranges || len < (5 * 8 * sizeof(__be32)))
10027ed18152SDavid Daney 			goto no_led;
10037ed18152SDavid Daney 
10047ed18152SDavid Daney 		ranges[(cs * 5) + 2] = cpu_to_be32(region_base >> 32);
10057ed18152SDavid Daney 		ranges[(cs * 5) + 3] = cpu_to_be32(region_base & 0xffffffff);
10067ed18152SDavid Daney 		ranges[(cs * 5) + 4] = cpu_to_be32(region_size);
10077ed18152SDavid Daney 		goto end_led;
10087ed18152SDavid Daney 
10097ed18152SDavid Daney no_led:
10107ed18152SDavid Daney 		fdt_nop_node(initial_boot_params, led);
10117ed18152SDavid Daney end_led:
10127ed18152SDavid Daney 		;
10137ed18152SDavid Daney 	}
10147ed18152SDavid Daney 
10157fd57ab9SSteven J. Hill #ifdef CONFIG_USB
10167ed18152SDavid Daney 	/* OHCI/UHCI USB */
10177ed18152SDavid Daney 	alias_prop = fdt_getprop(initial_boot_params, aliases,
10187ed18152SDavid Daney 				 "uctl", NULL);
10197ed18152SDavid Daney 	if (alias_prop) {
10207ed18152SDavid Daney 		int uctl = fdt_path_offset(initial_boot_params, alias_prop);
10217ed18152SDavid Daney 
10227ed18152SDavid Daney 		if (uctl >= 0 && (!OCTEON_IS_MODEL(OCTEON_CN6XXX) ||
10237ed18152SDavid Daney 				  octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC2E)) {
10247ed18152SDavid Daney 			pr_debug("Deleting uctl\n");
10257ed18152SDavid Daney 			fdt_nop_node(initial_boot_params, uctl);
10267ed18152SDavid Daney 			fdt_nop_property(initial_boot_params, aliases, "uctl");
10277ed18152SDavid Daney 		} else if (octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC10E ||
10287ed18152SDavid Daney 			   octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC4E) {
10297ed18152SDavid Daney 			/* Missing "refclk-type" defaults to crystal. */
10307ed18152SDavid Daney 			fdt_nop_property(initial_boot_params, uctl, "refclk-type");
10317ed18152SDavid Daney 		}
10327ed18152SDavid Daney 	}
10337ed18152SDavid Daney 
1034d617f9e9SDavid Daney 	/* DWC2 USB */
1035d617f9e9SDavid Daney 	alias_prop = fdt_getprop(initial_boot_params, aliases,
1036d617f9e9SDavid Daney 				 "usbn", NULL);
1037d617f9e9SDavid Daney 	if (alias_prop) {
1038d617f9e9SDavid Daney 		int usbn = fdt_path_offset(initial_boot_params, alias_prop);
1039d617f9e9SDavid Daney 
1040d617f9e9SDavid Daney 		if (usbn >= 0 && (current_cpu_type() == CPU_CAVIUM_OCTEON2 ||
1041d617f9e9SDavid Daney 				  !octeon_has_feature(OCTEON_FEATURE_USB))) {
1042d617f9e9SDavid Daney 			pr_debug("Deleting usbn\n");
1043d617f9e9SDavid Daney 			fdt_nop_node(initial_boot_params, usbn);
1044d617f9e9SDavid Daney 			fdt_nop_property(initial_boot_params, aliases, "usbn");
1045d617f9e9SDavid Daney 		} else  {
1046d617f9e9SDavid Daney 			__be32 new_f[1];
1047d617f9e9SDavid Daney 			enum cvmx_helper_board_usb_clock_types c;
1048e96b1b06SSteven J. Hill 
1049d617f9e9SDavid Daney 			c = __cvmx_helper_board_usb_get_clock_type();
1050d617f9e9SDavid Daney 			switch (c) {
1051d617f9e9SDavid Daney 			case USB_CLOCK_TYPE_REF_48:
1052d617f9e9SDavid Daney 				new_f[0] = cpu_to_be32(48000000);
1053d617f9e9SDavid Daney 				fdt_setprop_inplace(initial_boot_params, usbn,
1054d617f9e9SDavid Daney 						    "refclk-frequency",  new_f, sizeof(new_f));
1055d617f9e9SDavid Daney 				/* Fall through ...*/
1056d617f9e9SDavid Daney 			case USB_CLOCK_TYPE_REF_12:
1057d617f9e9SDavid Daney 				/* Missing "refclk-type" defaults to external. */
1058d617f9e9SDavid Daney 				fdt_nop_property(initial_boot_params, usbn, "refclk-type");
1059d617f9e9SDavid Daney 				break;
1060d617f9e9SDavid Daney 			default:
1061d617f9e9SDavid Daney 				break;
1062d617f9e9SDavid Daney 			}
1063d617f9e9SDavid Daney 		}
1064d617f9e9SDavid Daney 	}
10657fd57ab9SSteven J. Hill #endif
1066d617f9e9SDavid Daney 
10677ed18152SDavid Daney 	return 0;
10687ed18152SDavid Daney }
10697ed18152SDavid Daney 
10707ed18152SDavid Daney static int __init octeon_publish_devices(void)
10717ed18152SDavid Daney {
1072f072f9ceSRob Herring 	return of_platform_populate(NULL, octeon_ids, NULL, NULL);
10737ed18152SDavid Daney }
10748074d782SAaro Koskinen arch_initcall(octeon_publish_devices);
1075