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>
11*e1a7566dSRob Herring #include <linux/of.h>
127ed18152SDavid Daney #include <linux/of_platform.h>
137ed18152SDavid Daney #include <linux/of_fdt.h>
14*e1a7566dSRob Herring #include <linux/platform_device.h>
157ed18152SDavid Daney #include <linux/libfdt.h>
16512254baSDavid Daney
17512254baSDavid Daney #include <asm/octeon/octeon.h>
187ed18152SDavid Daney #include <asm/octeon/cvmx-helper-board.h>
197fd57ab9SSteven J. Hill
207fd57ab9SSteven J. Hill #ifdef CONFIG_USB
217fd57ab9SSteven J. Hill #include <linux/usb/ehci_def.h>
227fd57ab9SSteven J. Hill #include <linux/usb/ehci_pdriver.h>
237fd57ab9SSteven J. Hill #include <linux/usb/ohci_pdriver.h>
242193dda5SAlan Stern #include <asm/octeon/cvmx-uctlx-defs.h>
25512254baSDavid Daney
267e78db99SSteven J. Hill #define CVMX_UAHCX_EHCI_USBCMD (CVMX_ADD_IO_SEG(0x00016F0000000010ull))
277e78db99SSteven J. Hill #define CVMX_UAHCX_OHCI_USBCMD (CVMX_ADD_IO_SEG(0x00016F0000000408ull))
287e78db99SSteven J. Hill
292193dda5SAlan Stern static DEFINE_MUTEX(octeon2_usb_clocks_mutex);
302193dda5SAlan Stern
312193dda5SAlan Stern static int octeon2_usb_clock_start_cnt;
322193dda5SAlan Stern
octeon2_usb_reset(void)337e78db99SSteven J. Hill static int __init octeon2_usb_reset(void)
347e78db99SSteven J. Hill {
357e78db99SSteven J. Hill union cvmx_uctlx_clk_rst_ctl clk_rst_ctl;
367e78db99SSteven J. Hill u32 ucmd;
377e78db99SSteven J. Hill
387e78db99SSteven J. Hill if (!OCTEON_IS_OCTEON2())
397e78db99SSteven J. Hill return 0;
407e78db99SSteven J. Hill
417e78db99SSteven J. Hill clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
427e78db99SSteven J. Hill if (clk_rst_ctl.s.hrst) {
437e78db99SSteven J. Hill ucmd = cvmx_read64_uint32(CVMX_UAHCX_EHCI_USBCMD);
447e78db99SSteven J. Hill ucmd &= ~CMD_RUN;
457e78db99SSteven J. Hill cvmx_write64_uint32(CVMX_UAHCX_EHCI_USBCMD, ucmd);
467e78db99SSteven J. Hill mdelay(2);
477e78db99SSteven J. Hill ucmd |= CMD_RESET;
487e78db99SSteven J. Hill cvmx_write64_uint32(CVMX_UAHCX_EHCI_USBCMD, ucmd);
497e78db99SSteven J. Hill ucmd = cvmx_read64_uint32(CVMX_UAHCX_OHCI_USBCMD);
507e78db99SSteven J. Hill ucmd |= CMD_RUN;
517e78db99SSteven J. Hill cvmx_write64_uint32(CVMX_UAHCX_OHCI_USBCMD, ucmd);
527e78db99SSteven J. Hill }
537e78db99SSteven J. Hill
547e78db99SSteven J. Hill return 0;
557e78db99SSteven J. Hill }
567e78db99SSteven J. Hill arch_initcall(octeon2_usb_reset);
577e78db99SSteven J. Hill
octeon2_usb_clocks_start(struct device * dev)58a95cfa6bSAndreas Herrmann static void octeon2_usb_clocks_start(struct device *dev)
592193dda5SAlan Stern {
602193dda5SAlan Stern u64 div;
612193dda5SAlan Stern union cvmx_uctlx_if_ena if_ena;
622193dda5SAlan Stern union cvmx_uctlx_clk_rst_ctl clk_rst_ctl;
632193dda5SAlan Stern union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status;
642193dda5SAlan Stern int i;
652193dda5SAlan Stern unsigned long io_clk_64_to_ns;
66a95cfa6bSAndreas Herrmann u32 clock_rate = 12000000;
67a95cfa6bSAndreas Herrmann bool is_crystal_clock = false;
682193dda5SAlan Stern
692193dda5SAlan Stern
702193dda5SAlan Stern mutex_lock(&octeon2_usb_clocks_mutex);
712193dda5SAlan Stern
722193dda5SAlan Stern octeon2_usb_clock_start_cnt++;
732193dda5SAlan Stern if (octeon2_usb_clock_start_cnt != 1)
742193dda5SAlan Stern goto exit;
752193dda5SAlan Stern
762193dda5SAlan Stern io_clk_64_to_ns = 64000000000ull / octeon_get_io_clock_rate();
772193dda5SAlan Stern
78a95cfa6bSAndreas Herrmann if (dev->of_node) {
79a95cfa6bSAndreas Herrmann struct device_node *uctl_node;
80a95cfa6bSAndreas Herrmann const char *clock_type;
81a95cfa6bSAndreas Herrmann
82a95cfa6bSAndreas Herrmann uctl_node = of_get_parent(dev->of_node);
83a95cfa6bSAndreas Herrmann if (!uctl_node) {
84a95cfa6bSAndreas Herrmann dev_err(dev, "No UCTL device node\n");
85a95cfa6bSAndreas Herrmann goto exit;
86a95cfa6bSAndreas Herrmann }
87a95cfa6bSAndreas Herrmann i = of_property_read_u32(uctl_node,
88a95cfa6bSAndreas Herrmann "refclk-frequency", &clock_rate);
89a95cfa6bSAndreas Herrmann if (i) {
90a95cfa6bSAndreas Herrmann dev_err(dev, "No UCTL \"refclk-frequency\"\n");
917a9f743cSLiang He of_node_put(uctl_node);
92a95cfa6bSAndreas Herrmann goto exit;
93a95cfa6bSAndreas Herrmann }
94a95cfa6bSAndreas Herrmann i = of_property_read_string(uctl_node,
95a95cfa6bSAndreas Herrmann "refclk-type", &clock_type);
967a9f743cSLiang He of_node_put(uctl_node);
97a95cfa6bSAndreas Herrmann if (!i && strcmp("crystal", clock_type) == 0)
98a95cfa6bSAndreas Herrmann is_crystal_clock = true;
99a95cfa6bSAndreas Herrmann }
100a95cfa6bSAndreas Herrmann
1012193dda5SAlan Stern /*
1022193dda5SAlan Stern * Step 1: Wait for voltages stable. That surely happened
1032193dda5SAlan Stern * before starting the kernel.
1042193dda5SAlan Stern *
1052193dda5SAlan Stern * Step 2: Enable SCLK of UCTL by writing UCTL0_IF_ENA[EN] = 1
1062193dda5SAlan Stern */
1072193dda5SAlan Stern if_ena.u64 = 0;
1082193dda5SAlan Stern if_ena.s.en = 1;
1092193dda5SAlan Stern cvmx_write_csr(CVMX_UCTLX_IF_ENA(0), if_ena.u64);
1102193dda5SAlan Stern
1117e78db99SSteven J. Hill for (i = 0; i <= 1; i++) {
1127e78db99SSteven J. Hill port_ctl_status.u64 =
1137e78db99SSteven J. Hill cvmx_read_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0));
1147e78db99SSteven J. Hill /* Set txvreftune to 15 to obtain compliant 'eye' diagram. */
1157e78db99SSteven J. Hill port_ctl_status.s.txvreftune = 15;
1167e78db99SSteven J. Hill port_ctl_status.s.txrisetune = 1;
1177e78db99SSteven J. Hill port_ctl_status.s.txpreemphasistune = 1;
1187e78db99SSteven J. Hill cvmx_write_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0),
1197e78db99SSteven J. Hill port_ctl_status.u64);
1207e78db99SSteven J. Hill }
1217e78db99SSteven J. Hill
1222193dda5SAlan Stern /* Step 3: Configure the reference clock, PHY, and HCLK */
1232193dda5SAlan Stern clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
1242193dda5SAlan Stern
1252193dda5SAlan Stern /*
1262193dda5SAlan Stern * If the UCTL looks like it has already been started, skip
1272193dda5SAlan Stern * the initialization, otherwise bus errors are obtained.
1282193dda5SAlan Stern */
1292193dda5SAlan Stern if (clk_rst_ctl.s.hrst)
1302193dda5SAlan Stern goto end_clock;
1312193dda5SAlan Stern /* 3a */
1322193dda5SAlan Stern clk_rst_ctl.s.p_por = 1;
1332193dda5SAlan Stern clk_rst_ctl.s.hrst = 0;
1342193dda5SAlan Stern clk_rst_ctl.s.p_prst = 0;
1352193dda5SAlan Stern clk_rst_ctl.s.h_clkdiv_rst = 0;
1362193dda5SAlan Stern clk_rst_ctl.s.o_clkdiv_rst = 0;
1372193dda5SAlan Stern clk_rst_ctl.s.h_clkdiv_en = 0;
1382193dda5SAlan Stern clk_rst_ctl.s.o_clkdiv_en = 0;
1392193dda5SAlan Stern cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
1402193dda5SAlan Stern
1412193dda5SAlan Stern /* 3b */
142a95cfa6bSAndreas Herrmann clk_rst_ctl.s.p_refclk_sel = is_crystal_clock ? 0 : 1;
143a95cfa6bSAndreas Herrmann switch (clock_rate) {
144a95cfa6bSAndreas Herrmann default:
145a95cfa6bSAndreas Herrmann pr_err("Invalid UCTL clock rate of %u, using 12000000 instead\n",
146a95cfa6bSAndreas Herrmann clock_rate);
147c9b02990SLiangliang Huang fallthrough;
148a95cfa6bSAndreas Herrmann case 12000000:
1492193dda5SAlan Stern clk_rst_ctl.s.p_refclk_div = 0;
150a95cfa6bSAndreas Herrmann break;
151a95cfa6bSAndreas Herrmann case 24000000:
152a95cfa6bSAndreas Herrmann clk_rst_ctl.s.p_refclk_div = 1;
153a95cfa6bSAndreas Herrmann break;
154a95cfa6bSAndreas Herrmann case 48000000:
155a95cfa6bSAndreas Herrmann clk_rst_ctl.s.p_refclk_div = 2;
156a95cfa6bSAndreas Herrmann break;
157a95cfa6bSAndreas Herrmann }
1582193dda5SAlan Stern cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
1592193dda5SAlan Stern
1602193dda5SAlan Stern /* 3c */
1612193dda5SAlan Stern div = octeon_get_io_clock_rate() / 130000000ull;
1622193dda5SAlan Stern
1632193dda5SAlan Stern switch (div) {
1642193dda5SAlan Stern case 0:
1652193dda5SAlan Stern div = 1;
1662193dda5SAlan Stern break;
1672193dda5SAlan Stern case 1:
1682193dda5SAlan Stern case 2:
1692193dda5SAlan Stern case 3:
1702193dda5SAlan Stern case 4:
1712193dda5SAlan Stern break;
1722193dda5SAlan Stern case 5:
1732193dda5SAlan Stern div = 4;
1742193dda5SAlan Stern break;
1752193dda5SAlan Stern case 6:
1762193dda5SAlan Stern case 7:
1772193dda5SAlan Stern div = 6;
1782193dda5SAlan Stern break;
1792193dda5SAlan Stern case 8:
1802193dda5SAlan Stern case 9:
1812193dda5SAlan Stern case 10:
1822193dda5SAlan Stern case 11:
1832193dda5SAlan Stern div = 8;
1842193dda5SAlan Stern break;
1852193dda5SAlan Stern default:
1862193dda5SAlan Stern div = 12;
1872193dda5SAlan Stern break;
1882193dda5SAlan Stern }
1892193dda5SAlan Stern clk_rst_ctl.s.h_div = div;
1902193dda5SAlan Stern cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
1912193dda5SAlan Stern /* Read it back, */
1922193dda5SAlan Stern clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
1932193dda5SAlan Stern clk_rst_ctl.s.h_clkdiv_en = 1;
1942193dda5SAlan Stern cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
1952193dda5SAlan Stern /* 3d */
1962193dda5SAlan Stern clk_rst_ctl.s.h_clkdiv_rst = 1;
1972193dda5SAlan Stern cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
1982193dda5SAlan Stern
1992193dda5SAlan Stern /* 3e: delay 64 io clocks */
2002193dda5SAlan Stern ndelay(io_clk_64_to_ns);
2012193dda5SAlan Stern
2022193dda5SAlan Stern /*
2032193dda5SAlan Stern * Step 4: Program the power-on reset field in the UCTL
2042193dda5SAlan Stern * clock-reset-control register.
2052193dda5SAlan Stern */
2062193dda5SAlan Stern clk_rst_ctl.s.p_por = 0;
2072193dda5SAlan Stern cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
2082193dda5SAlan Stern
2097e78db99SSteven J. Hill /* Step 5: Wait 3 ms for the PHY clock to start. */
2107e78db99SSteven J. Hill mdelay(3);
2112193dda5SAlan Stern
2127e78db99SSteven J. Hill /* Steps 6..9 for ATE only, are skipped. */
2132193dda5SAlan Stern
2142193dda5SAlan Stern /* Step 10: Configure the OHCI_CLK48 and OHCI_CLK12 clocks. */
2152193dda5SAlan Stern /* 10a */
2162193dda5SAlan Stern clk_rst_ctl.s.o_clkdiv_rst = 1;
2172193dda5SAlan Stern cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
2182193dda5SAlan Stern
2192193dda5SAlan Stern /* 10b */
2202193dda5SAlan Stern clk_rst_ctl.s.o_clkdiv_en = 1;
2212193dda5SAlan Stern cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
2222193dda5SAlan Stern
2232193dda5SAlan Stern /* 10c */
2242193dda5SAlan Stern ndelay(io_clk_64_to_ns);
2252193dda5SAlan Stern
2262193dda5SAlan Stern /*
2272193dda5SAlan Stern * Step 11: Program the PHY reset field:
2282193dda5SAlan Stern * UCTL0_CLK_RST_CTL[P_PRST] = 1
2292193dda5SAlan Stern */
2302193dda5SAlan Stern clk_rst_ctl.s.p_prst = 1;
2312193dda5SAlan Stern cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
2322193dda5SAlan Stern
2337e78db99SSteven J. Hill /* Step 11b */
2347e78db99SSteven J. Hill udelay(1);
2357e78db99SSteven J. Hill
2367e78db99SSteven J. Hill /* Step 11c */
2377e78db99SSteven J. Hill clk_rst_ctl.s.p_prst = 0;
2387e78db99SSteven J. Hill cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
2397e78db99SSteven J. Hill
2407e78db99SSteven J. Hill /* Step 11d */
2417e78db99SSteven J. Hill mdelay(1);
2427e78db99SSteven J. Hill
2437e78db99SSteven J. Hill /* Step 11e */
2447e78db99SSteven J. Hill clk_rst_ctl.s.p_prst = 1;
2457e78db99SSteven J. Hill cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
2467e78db99SSteven J. Hill
2472193dda5SAlan Stern /* Step 12: Wait 1 uS. */
2482193dda5SAlan Stern udelay(1);
2492193dda5SAlan Stern
2502193dda5SAlan Stern /* Step 13: Program the HRESET_N field: UCTL0_CLK_RST_CTL[HRST] = 1 */
2512193dda5SAlan Stern clk_rst_ctl.s.hrst = 1;
2522193dda5SAlan Stern cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
2532193dda5SAlan Stern
2542193dda5SAlan Stern end_clock:
2552193dda5SAlan Stern /* Set uSOF cycle period to 60,000 bits. */
2562193dda5SAlan Stern cvmx_write_csr(CVMX_UCTLX_EHCI_FLA(0), 0x20ull);
2577e78db99SSteven J. Hill
2582193dda5SAlan Stern exit:
2592193dda5SAlan Stern mutex_unlock(&octeon2_usb_clocks_mutex);
2602193dda5SAlan Stern }
2612193dda5SAlan Stern
octeon2_usb_clocks_stop(void)2622193dda5SAlan Stern static void octeon2_usb_clocks_stop(void)
2632193dda5SAlan Stern {
2642193dda5SAlan Stern mutex_lock(&octeon2_usb_clocks_mutex);
2652193dda5SAlan Stern octeon2_usb_clock_start_cnt--;
2662193dda5SAlan Stern mutex_unlock(&octeon2_usb_clocks_mutex);
2672193dda5SAlan Stern }
2682193dda5SAlan Stern
octeon_ehci_power_on(struct platform_device * pdev)2692193dda5SAlan Stern static int octeon_ehci_power_on(struct platform_device *pdev)
2702193dda5SAlan Stern {
271a95cfa6bSAndreas Herrmann octeon2_usb_clocks_start(&pdev->dev);
2722193dda5SAlan Stern return 0;
2732193dda5SAlan Stern }
2742193dda5SAlan Stern
octeon_ehci_power_off(struct platform_device * pdev)2752193dda5SAlan Stern static void octeon_ehci_power_off(struct platform_device *pdev)
2762193dda5SAlan Stern {
2772193dda5SAlan Stern octeon2_usb_clocks_stop();
2782193dda5SAlan Stern }
2792193dda5SAlan Stern
2802193dda5SAlan Stern static struct usb_ehci_pdata octeon_ehci_pdata = {
2812193dda5SAlan Stern /* Octeon EHCI matches CPU endianness. */
2822193dda5SAlan Stern #ifdef __BIG_ENDIAN
2832193dda5SAlan Stern .big_endian_mmio = 1,
2842193dda5SAlan Stern #endif
2858552b5b4SSteven J. Hill /*
2868552b5b4SSteven J. Hill * We can DMA from anywhere. But the descriptors must be in
2878552b5b4SSteven J. Hill * the lower 4GB.
2888552b5b4SSteven J. Hill */
2898552b5b4SSteven J. Hill .dma_mask_64 = 0,
2902193dda5SAlan Stern .power_on = octeon_ehci_power_on,
2912193dda5SAlan Stern .power_off = octeon_ehci_power_off,
2922193dda5SAlan Stern };
2932193dda5SAlan Stern
octeon_ehci_hw_start(struct device * dev)294a95cfa6bSAndreas Herrmann static void __init octeon_ehci_hw_start(struct device *dev)
2952193dda5SAlan Stern {
2962193dda5SAlan Stern union cvmx_uctlx_ehci_ctl ehci_ctl;
2972193dda5SAlan Stern
298a95cfa6bSAndreas Herrmann octeon2_usb_clocks_start(dev);
2992193dda5SAlan Stern
3002193dda5SAlan Stern ehci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_EHCI_CTL(0));
3012193dda5SAlan Stern /* Use 64-bit addressing. */
3022193dda5SAlan Stern ehci_ctl.s.ehci_64b_addr_en = 1;
3032193dda5SAlan Stern ehci_ctl.s.l2c_addr_msb = 0;
304b0abf36fSPaul Martin #ifdef __BIG_ENDIAN
3052193dda5SAlan Stern ehci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */
3062193dda5SAlan Stern ehci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */
307b0abf36fSPaul Martin #else
308b0abf36fSPaul Martin ehci_ctl.s.l2c_buff_emod = 0; /* not swapped. */
309b0abf36fSPaul Martin ehci_ctl.s.l2c_desc_emod = 0; /* not swapped. */
310b0abf36fSPaul Martin ehci_ctl.s.inv_reg_a2 = 1;
311b0abf36fSPaul Martin #endif
3122193dda5SAlan Stern cvmx_write_csr(CVMX_UCTLX_EHCI_CTL(0), ehci_ctl.u64);
3132193dda5SAlan Stern
3142193dda5SAlan Stern octeon2_usb_clocks_stop();
3152193dda5SAlan Stern }
3162193dda5SAlan Stern
octeon_ehci_device_init(void)317340fbb8bSDavid Daney static int __init octeon_ehci_device_init(void)
318340fbb8bSDavid Daney {
319340fbb8bSDavid Daney struct platform_device *pd;
320a95cfa6bSAndreas Herrmann struct device_node *ehci_node;
321340fbb8bSDavid Daney int ret = 0;
322340fbb8bSDavid Daney
323a95cfa6bSAndreas Herrmann ehci_node = of_find_node_by_name(NULL, "ehci");
324a95cfa6bSAndreas Herrmann if (!ehci_node)
325340fbb8bSDavid Daney return 0;
326340fbb8bSDavid Daney
327a95cfa6bSAndreas Herrmann pd = of_find_device_by_node(ehci_node);
328b1259519SNicholas Mc Guire of_node_put(ehci_node);
329a95cfa6bSAndreas Herrmann if (!pd)
330a95cfa6bSAndreas Herrmann return 0;
331340fbb8bSDavid Daney
3322193dda5SAlan Stern pd->dev.platform_data = &octeon_ehci_pdata;
333a95cfa6bSAndreas Herrmann octeon_ehci_hw_start(&pd->dev);
334858779dfSYe Guojin put_device(&pd->dev);
3352193dda5SAlan Stern
336340fbb8bSDavid Daney return ret;
337340fbb8bSDavid Daney }
338340fbb8bSDavid Daney device_initcall(octeon_ehci_device_init);
339340fbb8bSDavid Daney
octeon_ohci_power_on(struct platform_device * pdev)3402193dda5SAlan Stern static int octeon_ohci_power_on(struct platform_device *pdev)
3412193dda5SAlan Stern {
342a95cfa6bSAndreas Herrmann octeon2_usb_clocks_start(&pdev->dev);
3432193dda5SAlan Stern return 0;
3442193dda5SAlan Stern }
3452193dda5SAlan Stern
octeon_ohci_power_off(struct platform_device * pdev)3462193dda5SAlan Stern static void octeon_ohci_power_off(struct platform_device *pdev)
3472193dda5SAlan Stern {
3482193dda5SAlan Stern octeon2_usb_clocks_stop();
3492193dda5SAlan Stern }
3502193dda5SAlan Stern
3512193dda5SAlan Stern static struct usb_ohci_pdata octeon_ohci_pdata = {
3522193dda5SAlan Stern /* Octeon OHCI matches CPU endianness. */
3532193dda5SAlan Stern #ifdef __BIG_ENDIAN
3542193dda5SAlan Stern .big_endian_mmio = 1,
3552193dda5SAlan Stern #endif
3562193dda5SAlan Stern .power_on = octeon_ohci_power_on,
3572193dda5SAlan Stern .power_off = octeon_ohci_power_off,
3582193dda5SAlan Stern };
3592193dda5SAlan Stern
octeon_ohci_hw_start(struct device * dev)360a95cfa6bSAndreas Herrmann static void __init octeon_ohci_hw_start(struct device *dev)
3612193dda5SAlan Stern {
3622193dda5SAlan Stern union cvmx_uctlx_ohci_ctl ohci_ctl;
3632193dda5SAlan Stern
364a95cfa6bSAndreas Herrmann octeon2_usb_clocks_start(dev);
3652193dda5SAlan Stern
3662193dda5SAlan Stern ohci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_OHCI_CTL(0));
3672193dda5SAlan Stern ohci_ctl.s.l2c_addr_msb = 0;
368b0abf36fSPaul Martin #ifdef __BIG_ENDIAN
3692193dda5SAlan Stern ohci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */
3702193dda5SAlan Stern ohci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */
371b0abf36fSPaul Martin #else
372b0abf36fSPaul Martin ohci_ctl.s.l2c_buff_emod = 0; /* not swapped. */
373b0abf36fSPaul Martin ohci_ctl.s.l2c_desc_emod = 0; /* not swapped. */
374b0abf36fSPaul Martin ohci_ctl.s.inv_reg_a2 = 1;
375b0abf36fSPaul Martin #endif
3762193dda5SAlan Stern cvmx_write_csr(CVMX_UCTLX_OHCI_CTL(0), ohci_ctl.u64);
3772193dda5SAlan Stern
3782193dda5SAlan Stern octeon2_usb_clocks_stop();
3792193dda5SAlan Stern }
3802193dda5SAlan Stern
octeon_ohci_device_init(void)381340fbb8bSDavid Daney static int __init octeon_ohci_device_init(void)
382340fbb8bSDavid Daney {
383340fbb8bSDavid Daney struct platform_device *pd;
384a95cfa6bSAndreas Herrmann struct device_node *ohci_node;
385340fbb8bSDavid Daney int ret = 0;
386340fbb8bSDavid Daney
387a95cfa6bSAndreas Herrmann ohci_node = of_find_node_by_name(NULL, "ohci");
388a95cfa6bSAndreas Herrmann if (!ohci_node)
389340fbb8bSDavid Daney return 0;
390340fbb8bSDavid Daney
391a95cfa6bSAndreas Herrmann pd = of_find_device_by_node(ohci_node);
392b1259519SNicholas Mc Guire of_node_put(ohci_node);
393a95cfa6bSAndreas Herrmann if (!pd)
394a95cfa6bSAndreas Herrmann return 0;
395340fbb8bSDavid Daney
3962193dda5SAlan Stern pd->dev.platform_data = &octeon_ohci_pdata;
397a95cfa6bSAndreas Herrmann octeon_ohci_hw_start(&pd->dev);
398858779dfSYe Guojin put_device(&pd->dev);
3992193dda5SAlan Stern
400340fbb8bSDavid Daney return ret;
401340fbb8bSDavid Daney }
402340fbb8bSDavid Daney device_initcall(octeon_ohci_device_init);
403340fbb8bSDavid Daney
404340fbb8bSDavid Daney #endif /* CONFIG_USB */
405340fbb8bSDavid Daney
4067fd57ab9SSteven J. Hill /* Octeon Random Number Generator. */
octeon_rng_device_init(void)4077fd57ab9SSteven J. Hill static int __init octeon_rng_device_init(void)
4087fd57ab9SSteven J. Hill {
4097fd57ab9SSteven J. Hill struct platform_device *pd;
4107fd57ab9SSteven J. Hill int ret = 0;
4117fd57ab9SSteven J. Hill
4127fd57ab9SSteven J. Hill struct resource rng_resources[] = {
4137fd57ab9SSteven J. Hill {
4147fd57ab9SSteven J. Hill .flags = IORESOURCE_MEM,
4157fd57ab9SSteven J. Hill .start = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS),
4167fd57ab9SSteven J. Hill .end = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS) + 0xf
4177fd57ab9SSteven J. Hill }, {
4187fd57ab9SSteven J. Hill .flags = IORESOURCE_MEM,
4197fd57ab9SSteven J. Hill .start = cvmx_build_io_address(8, 0),
4207fd57ab9SSteven J. Hill .end = cvmx_build_io_address(8, 0) + 0x7
4217fd57ab9SSteven J. Hill }
4227fd57ab9SSteven J. Hill };
4237fd57ab9SSteven J. Hill
4247fd57ab9SSteven J. Hill pd = platform_device_alloc("octeon_rng", -1);
4257fd57ab9SSteven J. Hill if (!pd) {
4267fd57ab9SSteven J. Hill ret = -ENOMEM;
4277fd57ab9SSteven J. Hill goto out;
4287fd57ab9SSteven J. Hill }
4297fd57ab9SSteven J. Hill
4307fd57ab9SSteven J. Hill ret = platform_device_add_resources(pd, rng_resources,
4317fd57ab9SSteven J. Hill ARRAY_SIZE(rng_resources));
4327fd57ab9SSteven J. Hill if (ret)
4337fd57ab9SSteven J. Hill goto fail;
4347fd57ab9SSteven J. Hill
4357fd57ab9SSteven J. Hill ret = platform_device_add(pd);
4367fd57ab9SSteven J. Hill if (ret)
4377fd57ab9SSteven J. Hill goto fail;
4387fd57ab9SSteven J. Hill
4397fd57ab9SSteven J. Hill return ret;
4407fd57ab9SSteven J. Hill fail:
4417fd57ab9SSteven J. Hill platform_device_put(pd);
4427fd57ab9SSteven J. Hill
4437fd57ab9SSteven J. Hill out:
4447fd57ab9SSteven J. Hill return ret;
4457fd57ab9SSteven J. Hill }
4467fd57ab9SSteven J. Hill device_initcall(octeon_rng_device_init);
447a95cfa6bSAndreas Herrmann
448fa1d2e3fSAaro Koskinen static const struct of_device_id octeon_ids[] __initconst = {
4497ed18152SDavid Daney { .compatible = "simple-bus", },
4507ed18152SDavid Daney { .compatible = "cavium,octeon-6335-uctl", },
451d617f9e9SDavid Daney { .compatible = "cavium,octeon-5750-usbn", },
4527ed18152SDavid Daney { .compatible = "cavium,octeon-3860-bootbus", },
4537ed18152SDavid Daney { .compatible = "cavium,mdio-mux", },
4547ed18152SDavid Daney { .compatible = "gpio-leds", },
4557ed18152SDavid Daney {},
4567ed18152SDavid Daney };
4577ed18152SDavid Daney
octeon_has_88e1145(void)4587ed18152SDavid Daney static bool __init octeon_has_88e1145(void)
4597ed18152SDavid Daney {
4607ed18152SDavid Daney return !OCTEON_IS_MODEL(OCTEON_CN52XX) &&
4617ed18152SDavid Daney !OCTEON_IS_MODEL(OCTEON_CN6XXX) &&
4627ed18152SDavid Daney !OCTEON_IS_MODEL(OCTEON_CN56XX);
4637ed18152SDavid Daney }
4647ed18152SDavid Daney
octeon_has_fixed_link(int ipd_port)465565485b8SAaro Koskinen static bool __init octeon_has_fixed_link(int ipd_port)
466565485b8SAaro Koskinen {
467565485b8SAaro Koskinen switch (cvmx_sysinfo_get()->board_type) {
468565485b8SAaro Koskinen case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
469565485b8SAaro Koskinen case CVMX_BOARD_TYPE_CN3010_EVB_HS5:
470565485b8SAaro Koskinen case CVMX_BOARD_TYPE_CN3020_EVB_HS5:
471565485b8SAaro Koskinen case CVMX_BOARD_TYPE_CUST_NB5:
472565485b8SAaro Koskinen case CVMX_BOARD_TYPE_EBH3100:
473565485b8SAaro Koskinen /* Port 1 on these boards is always gigabit. */
474565485b8SAaro Koskinen return ipd_port == 1;
475565485b8SAaro Koskinen case CVMX_BOARD_TYPE_BBGW_REF:
476565485b8SAaro Koskinen /* Ports 0 and 1 connect to the switch. */
477565485b8SAaro Koskinen return ipd_port == 0 || ipd_port == 1;
478565485b8SAaro Koskinen }
479565485b8SAaro Koskinen return false;
480565485b8SAaro Koskinen }
481565485b8SAaro Koskinen
octeon_fdt_set_phy(int eth,int phy_addr)4827ed18152SDavid Daney static void __init octeon_fdt_set_phy(int eth, int phy_addr)
4837ed18152SDavid Daney {
4847ed18152SDavid Daney const __be32 *phy_handle;
4857ed18152SDavid Daney const __be32 *alt_phy_handle;
4867ed18152SDavid Daney const __be32 *reg;
4877ed18152SDavid Daney u32 phandle;
4887ed18152SDavid Daney int phy;
4897ed18152SDavid Daney int alt_phy;
4907ed18152SDavid Daney const char *p;
4917ed18152SDavid Daney int current_len;
4927ed18152SDavid Daney char new_name[20];
4937ed18152SDavid Daney
4947ed18152SDavid Daney phy_handle = fdt_getprop(initial_boot_params, eth, "phy-handle", NULL);
4957ed18152SDavid Daney if (!phy_handle)
4967ed18152SDavid Daney return;
4977ed18152SDavid Daney
4987ed18152SDavid Daney phandle = be32_to_cpup(phy_handle);
4997ed18152SDavid Daney phy = fdt_node_offset_by_phandle(initial_boot_params, phandle);
5007ed18152SDavid Daney
5017ed18152SDavid Daney alt_phy_handle = fdt_getprop(initial_boot_params, eth, "cavium,alt-phy-handle", NULL);
5027ed18152SDavid Daney if (alt_phy_handle) {
5037ed18152SDavid Daney u32 alt_phandle = be32_to_cpup(alt_phy_handle);
504e96b1b06SSteven J. Hill
5057ed18152SDavid Daney alt_phy = fdt_node_offset_by_phandle(initial_boot_params, alt_phandle);
5067ed18152SDavid Daney } else {
5077ed18152SDavid Daney alt_phy = -1;
5087ed18152SDavid Daney }
5097ed18152SDavid Daney
5107ed18152SDavid Daney if (phy_addr < 0 || phy < 0) {
5117ed18152SDavid Daney /* Delete the PHY things */
5127ed18152SDavid Daney fdt_nop_property(initial_boot_params, eth, "phy-handle");
5137ed18152SDavid Daney /* This one may fail */
5147ed18152SDavid Daney fdt_nop_property(initial_boot_params, eth, "cavium,alt-phy-handle");
5157ed18152SDavid Daney if (phy >= 0)
5167ed18152SDavid Daney fdt_nop_node(initial_boot_params, phy);
5177ed18152SDavid Daney if (alt_phy >= 0)
5187ed18152SDavid Daney fdt_nop_node(initial_boot_params, alt_phy);
5197ed18152SDavid Daney return;
5207ed18152SDavid Daney }
5217ed18152SDavid Daney
5227ed18152SDavid Daney if (phy_addr >= 256 && alt_phy > 0) {
5237ed18152SDavid Daney const struct fdt_property *phy_prop;
5247ed18152SDavid Daney struct fdt_property *alt_prop;
5252cf1c893SAaro Koskinen fdt32_t phy_handle_name;
5267ed18152SDavid Daney
5277ed18152SDavid Daney /* Use the alt phy node instead.*/
5287ed18152SDavid Daney phy_prop = fdt_get_property(initial_boot_params, eth, "phy-handle", NULL);
5297ed18152SDavid Daney phy_handle_name = phy_prop->nameoff;
5307ed18152SDavid Daney fdt_nop_node(initial_boot_params, phy);
5317ed18152SDavid Daney fdt_nop_property(initial_boot_params, eth, "phy-handle");
5327ed18152SDavid Daney alt_prop = fdt_get_property_w(initial_boot_params, eth, "cavium,alt-phy-handle", NULL);
5337ed18152SDavid Daney alt_prop->nameoff = phy_handle_name;
5347ed18152SDavid Daney phy = alt_phy;
5357ed18152SDavid Daney }
5367ed18152SDavid Daney
5377ed18152SDavid Daney phy_addr &= 0xff;
5387ed18152SDavid Daney
5397ed18152SDavid Daney if (octeon_has_88e1145()) {
5407ed18152SDavid Daney fdt_nop_property(initial_boot_params, phy, "marvell,reg-init");
5417ed18152SDavid Daney memset(new_name, 0, sizeof(new_name));
5427ed18152SDavid Daney strcpy(new_name, "marvell,88e1145");
5437ed18152SDavid Daney p = fdt_getprop(initial_boot_params, phy, "compatible",
5447ed18152SDavid Daney ¤t_len);
5457ed18152SDavid Daney if (p && current_len >= strlen(new_name))
5467ed18152SDavid Daney fdt_setprop_inplace(initial_boot_params, phy,
5477ed18152SDavid Daney "compatible", new_name, current_len);
5487ed18152SDavid Daney }
5497ed18152SDavid Daney
5507ed18152SDavid Daney reg = fdt_getprop(initial_boot_params, phy, "reg", NULL);
5517ed18152SDavid Daney if (phy_addr == be32_to_cpup(reg))
5527ed18152SDavid Daney return;
5537ed18152SDavid Daney
5547ed18152SDavid Daney fdt_setprop_inplace_cell(initial_boot_params, phy, "reg", phy_addr);
5557ed18152SDavid Daney
5567ed18152SDavid Daney snprintf(new_name, sizeof(new_name), "ethernet-phy@%x", phy_addr);
5577ed18152SDavid Daney
5587ed18152SDavid Daney p = fdt_get_name(initial_boot_params, phy, ¤t_len);
5597ed18152SDavid Daney if (p && current_len == strlen(new_name))
5607ed18152SDavid Daney fdt_set_name(initial_boot_params, phy, new_name);
5617ed18152SDavid Daney else
5627ed18152SDavid Daney pr_err("Error: could not rename ethernet phy: <%s>", p);
5637ed18152SDavid Daney }
5647ed18152SDavid Daney
octeon_fdt_set_mac_addr(int n,u64 * pmac)5657ed18152SDavid Daney static void __init octeon_fdt_set_mac_addr(int n, u64 *pmac)
5667ed18152SDavid Daney {
567377de399SAaro Koskinen const u8 *old_mac;
568377de399SAaro Koskinen int old_len;
5697ed18152SDavid Daney u8 new_mac[6];
5707ed18152SDavid Daney u64 mac = *pmac;
5717ed18152SDavid Daney int r;
5727ed18152SDavid Daney
573377de399SAaro Koskinen old_mac = fdt_getprop(initial_boot_params, n, "local-mac-address",
574377de399SAaro Koskinen &old_len);
575377de399SAaro Koskinen if (!old_mac || old_len != 6 || is_valid_ether_addr(old_mac))
576377de399SAaro Koskinen return;
577377de399SAaro Koskinen
5787ed18152SDavid Daney new_mac[0] = (mac >> 40) & 0xff;
5797ed18152SDavid Daney new_mac[1] = (mac >> 32) & 0xff;
5807ed18152SDavid Daney new_mac[2] = (mac >> 24) & 0xff;
5817ed18152SDavid Daney new_mac[3] = (mac >> 16) & 0xff;
5827ed18152SDavid Daney new_mac[4] = (mac >> 8) & 0xff;
5837ed18152SDavid Daney new_mac[5] = mac & 0xff;
5847ed18152SDavid Daney
5857ed18152SDavid Daney r = fdt_setprop_inplace(initial_boot_params, n, "local-mac-address",
5867ed18152SDavid Daney new_mac, sizeof(new_mac));
5877ed18152SDavid Daney
5887ed18152SDavid Daney if (r) {
5897ed18152SDavid Daney pr_err("Setting \"local-mac-address\" failed %d", r);
5907ed18152SDavid Daney return;
5917ed18152SDavid Daney }
5927ed18152SDavid Daney *pmac = mac + 1;
5937ed18152SDavid Daney }
5947ed18152SDavid Daney
octeon_fdt_rm_ethernet(int node)5957ed18152SDavid Daney static void __init octeon_fdt_rm_ethernet(int node)
5967ed18152SDavid Daney {
5977ed18152SDavid Daney const __be32 *phy_handle;
5987ed18152SDavid Daney
5997ed18152SDavid Daney phy_handle = fdt_getprop(initial_boot_params, node, "phy-handle", NULL);
6007ed18152SDavid Daney if (phy_handle) {
6017ed18152SDavid Daney u32 ph = be32_to_cpup(phy_handle);
6027ed18152SDavid Daney int p = fdt_node_offset_by_phandle(initial_boot_params, ph);
603e96b1b06SSteven J. Hill
6047ed18152SDavid Daney if (p >= 0)
6057ed18152SDavid Daney fdt_nop_node(initial_boot_params, p);
6067ed18152SDavid Daney }
6077ed18152SDavid Daney fdt_nop_node(initial_boot_params, node);
6087ed18152SDavid Daney }
6097ed18152SDavid Daney
_octeon_rx_tx_delay(int eth,int rx_delay,int tx_delay)6103d252181SAaro Koskinen static void __init _octeon_rx_tx_delay(int eth, int rx_delay, int tx_delay)
6113d252181SAaro Koskinen {
6123d252181SAaro Koskinen fdt_setprop_inplace_cell(initial_boot_params, eth, "rx-delay",
6133d252181SAaro Koskinen rx_delay);
6143d252181SAaro Koskinen fdt_setprop_inplace_cell(initial_boot_params, eth, "tx-delay",
6153d252181SAaro Koskinen tx_delay);
6163d252181SAaro Koskinen }
6173d252181SAaro Koskinen
octeon_rx_tx_delay(int eth,int iface,int port)6183d252181SAaro Koskinen static void __init octeon_rx_tx_delay(int eth, int iface, int port)
6193d252181SAaro Koskinen {
6203d252181SAaro Koskinen switch (cvmx_sysinfo_get()->board_type) {
6213d252181SAaro Koskinen case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
6223d252181SAaro Koskinen if (iface == 0) {
6233d252181SAaro Koskinen if (port == 0) {
6243d252181SAaro Koskinen /*
6253d252181SAaro Koskinen * Boards with gigabit WAN ports need a
6263d252181SAaro Koskinen * different setting that is compatible with
6273d252181SAaro Koskinen * 100 Mbit settings
6283d252181SAaro Koskinen */
6293d252181SAaro Koskinen _octeon_rx_tx_delay(eth, 0xc, 0x0c);
6303d252181SAaro Koskinen return;
6313d252181SAaro Koskinen } else if (port == 1) {
6323d252181SAaro Koskinen /* Different config for switch port. */
6333d252181SAaro Koskinen _octeon_rx_tx_delay(eth, 0x0, 0x0);
6343d252181SAaro Koskinen return;
6353d252181SAaro Koskinen }
6363d252181SAaro Koskinen }
6373d252181SAaro Koskinen break;
6383d252181SAaro Koskinen case CVMX_BOARD_TYPE_UBNT_E100:
6393d252181SAaro Koskinen if (iface == 0 && port <= 2) {
6403d252181SAaro Koskinen _octeon_rx_tx_delay(eth, 0x0, 0x10);
6413d252181SAaro Koskinen return;
6423d252181SAaro Koskinen }
6433d252181SAaro Koskinen break;
6443d252181SAaro Koskinen }
6453d252181SAaro Koskinen fdt_nop_property(initial_boot_params, eth, "rx-delay");
6463d252181SAaro Koskinen fdt_nop_property(initial_boot_params, eth, "tx-delay");
6473d252181SAaro Koskinen }
6483d252181SAaro Koskinen
octeon_fdt_pip_port(int iface,int i,int p,int max)64943349b9eSAaro Koskinen static void __init octeon_fdt_pip_port(int iface, int i, int p, int max)
6507ed18152SDavid Daney {
6517ed18152SDavid Daney char name_buffer[20];
6527ed18152SDavid Daney int eth;
6537ed18152SDavid Daney int phy_addr;
6547ed18152SDavid Daney int ipd_port;
655565485b8SAaro Koskinen int fixed_link;
6567ed18152SDavid Daney
6577ed18152SDavid Daney snprintf(name_buffer, sizeof(name_buffer), "ethernet@%x", p);
6587ed18152SDavid Daney eth = fdt_subnode_offset(initial_boot_params, iface, name_buffer);
6597ed18152SDavid Daney if (eth < 0)
6607ed18152SDavid Daney return;
6617ed18152SDavid Daney if (p > max) {
6627ed18152SDavid Daney pr_debug("Deleting port %x:%x\n", i, p);
6637ed18152SDavid Daney octeon_fdt_rm_ethernet(eth);
6647ed18152SDavid Daney return;
6657ed18152SDavid Daney }
6667ed18152SDavid Daney if (OCTEON_IS_MODEL(OCTEON_CN68XX))
6677ed18152SDavid Daney ipd_port = (0x100 * i) + (0x10 * p) + 0x800;
6687ed18152SDavid Daney else
6697ed18152SDavid Daney ipd_port = 16 * i + p;
6707ed18152SDavid Daney
6717ed18152SDavid Daney phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
6727ed18152SDavid Daney octeon_fdt_set_phy(eth, phy_addr);
673565485b8SAaro Koskinen
674565485b8SAaro Koskinen fixed_link = fdt_subnode_offset(initial_boot_params, eth, "fixed-link");
675565485b8SAaro Koskinen if (fixed_link < 0)
676565485b8SAaro Koskinen WARN_ON(octeon_has_fixed_link(ipd_port));
677565485b8SAaro Koskinen else if (!octeon_has_fixed_link(ipd_port))
678565485b8SAaro Koskinen fdt_nop_node(initial_boot_params, fixed_link);
6793d252181SAaro Koskinen octeon_rx_tx_delay(eth, i, p);
6807ed18152SDavid Daney }
6817ed18152SDavid Daney
octeon_fdt_pip_iface(int pip,int idx)68243349b9eSAaro Koskinen static void __init octeon_fdt_pip_iface(int pip, int idx)
6837ed18152SDavid Daney {
6847ed18152SDavid Daney char name_buffer[20];
6857ed18152SDavid Daney int iface;
6867ed18152SDavid Daney int p;
687ab2bb148SFaidon Liambotis int count = 0;
6887ed18152SDavid Daney
6897ed18152SDavid Daney snprintf(name_buffer, sizeof(name_buffer), "interface@%d", idx);
6907ed18152SDavid Daney iface = fdt_subnode_offset(initial_boot_params, pip, name_buffer);
6917ed18152SDavid Daney if (iface < 0)
6927ed18152SDavid Daney return;
6937ed18152SDavid Daney
694b2e4f156SAaro Koskinen if (cvmx_helper_interface_enumerate(idx) == 0)
695b2e4f156SAaro Koskinen count = cvmx_helper_ports_on_interface(idx);
696b2e4f156SAaro Koskinen
6977ed18152SDavid Daney for (p = 0; p < 16; p++)
69843349b9eSAaro Koskinen octeon_fdt_pip_port(iface, idx, p, count - 1);
69943349b9eSAaro Koskinen }
70043349b9eSAaro Koskinen
octeon_fill_mac_addresses(void)70143349b9eSAaro Koskinen void __init octeon_fill_mac_addresses(void)
70243349b9eSAaro Koskinen {
70343349b9eSAaro Koskinen const char *alias_prop;
70443349b9eSAaro Koskinen char name_buffer[20];
70543349b9eSAaro Koskinen u64 mac_addr_base;
70643349b9eSAaro Koskinen int aliases;
70743349b9eSAaro Koskinen int pip;
70843349b9eSAaro Koskinen int i;
70943349b9eSAaro Koskinen
71043349b9eSAaro Koskinen aliases = fdt_path_offset(initial_boot_params, "/aliases");
71143349b9eSAaro Koskinen if (aliases < 0)
71243349b9eSAaro Koskinen return;
71343349b9eSAaro Koskinen
71443349b9eSAaro Koskinen mac_addr_base =
71543349b9eSAaro Koskinen ((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 |
71643349b9eSAaro Koskinen ((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 |
71743349b9eSAaro Koskinen ((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 |
71843349b9eSAaro Koskinen ((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 |
71943349b9eSAaro Koskinen ((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 |
72043349b9eSAaro Koskinen (octeon_bootinfo->mac_addr_base[5] & 0xffull);
72143349b9eSAaro Koskinen
72243349b9eSAaro Koskinen for (i = 0; i < 2; i++) {
72343349b9eSAaro Koskinen int mgmt;
72443349b9eSAaro Koskinen
72543349b9eSAaro Koskinen snprintf(name_buffer, sizeof(name_buffer), "mix%d", i);
72643349b9eSAaro Koskinen alias_prop = fdt_getprop(initial_boot_params, aliases,
72743349b9eSAaro Koskinen name_buffer, NULL);
72843349b9eSAaro Koskinen if (!alias_prop)
72943349b9eSAaro Koskinen continue;
73043349b9eSAaro Koskinen mgmt = fdt_path_offset(initial_boot_params, alias_prop);
73143349b9eSAaro Koskinen if (mgmt < 0)
73243349b9eSAaro Koskinen continue;
73343349b9eSAaro Koskinen octeon_fdt_set_mac_addr(mgmt, &mac_addr_base);
73443349b9eSAaro Koskinen }
73543349b9eSAaro Koskinen
73643349b9eSAaro Koskinen alias_prop = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
73743349b9eSAaro Koskinen if (!alias_prop)
73843349b9eSAaro Koskinen return;
73943349b9eSAaro Koskinen
74043349b9eSAaro Koskinen pip = fdt_path_offset(initial_boot_params, alias_prop);
74143349b9eSAaro Koskinen if (pip < 0)
74243349b9eSAaro Koskinen return;
74343349b9eSAaro Koskinen
74443349b9eSAaro Koskinen for (i = 0; i <= 4; i++) {
74543349b9eSAaro Koskinen int iface;
74643349b9eSAaro Koskinen int p;
74743349b9eSAaro Koskinen
74843349b9eSAaro Koskinen snprintf(name_buffer, sizeof(name_buffer), "interface@%d", i);
74943349b9eSAaro Koskinen iface = fdt_subnode_offset(initial_boot_params, pip,
75043349b9eSAaro Koskinen name_buffer);
75143349b9eSAaro Koskinen if (iface < 0)
75243349b9eSAaro Koskinen continue;
75343349b9eSAaro Koskinen for (p = 0; p < 16; p++) {
75443349b9eSAaro Koskinen int eth;
75543349b9eSAaro Koskinen
75643349b9eSAaro Koskinen snprintf(name_buffer, sizeof(name_buffer),
75743349b9eSAaro Koskinen "ethernet@%x", p);
75843349b9eSAaro Koskinen eth = fdt_subnode_offset(initial_boot_params, iface,
75943349b9eSAaro Koskinen name_buffer);
76043349b9eSAaro Koskinen if (eth < 0)
76143349b9eSAaro Koskinen continue;
76243349b9eSAaro Koskinen octeon_fdt_set_mac_addr(eth, &mac_addr_base);
76343349b9eSAaro Koskinen }
76443349b9eSAaro Koskinen }
7657ed18152SDavid Daney }
7667ed18152SDavid Daney
octeon_prune_device_tree(void)7677ed18152SDavid Daney int __init octeon_prune_device_tree(void)
7687ed18152SDavid Daney {
7697ed18152SDavid Daney int i, max_port, uart_mask;
7707ed18152SDavid Daney const char *pip_path;
7717ed18152SDavid Daney const char *alias_prop;
7727ed18152SDavid Daney char name_buffer[20];
7737ed18152SDavid Daney int aliases;
7747ed18152SDavid Daney
7757ed18152SDavid Daney if (fdt_check_header(initial_boot_params))
7767ed18152SDavid Daney panic("Corrupt Device Tree.");
7777ed18152SDavid Daney
77886bee12fSAaro Koskinen WARN(octeon_bootinfo->board_type == CVMX_BOARD_TYPE_CUST_DSR1000N,
77986bee12fSAaro Koskinen "Built-in DTB booting is deprecated on %s. Please switch to use appended DTB.",
78086bee12fSAaro Koskinen cvmx_board_type_to_string(octeon_bootinfo->board_type));
78186bee12fSAaro Koskinen
7827ed18152SDavid Daney aliases = fdt_path_offset(initial_boot_params, "/aliases");
7837ed18152SDavid Daney if (aliases < 0) {
7847ed18152SDavid Daney pr_err("Error: No /aliases node in device tree.");
7857ed18152SDavid Daney return -EINVAL;
7867ed18152SDavid Daney }
7877ed18152SDavid Daney
7887ed18152SDavid Daney if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))
7897ed18152SDavid Daney max_port = 2;
7907ed18152SDavid Daney else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN68XX))
7917ed18152SDavid Daney max_port = 1;
7927ed18152SDavid Daney else
7937ed18152SDavid Daney max_port = 0;
7947ed18152SDavid Daney
7957ed18152SDavid Daney if (octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC10E)
7967ed18152SDavid Daney max_port = 0;
7977ed18152SDavid Daney
7987ed18152SDavid Daney for (i = 0; i < 2; i++) {
7997ed18152SDavid Daney int mgmt;
800e96b1b06SSteven J. Hill
8017ed18152SDavid Daney snprintf(name_buffer, sizeof(name_buffer),
8027ed18152SDavid Daney "mix%d", i);
8037ed18152SDavid Daney alias_prop = fdt_getprop(initial_boot_params, aliases,
8047ed18152SDavid Daney name_buffer, NULL);
8057ed18152SDavid Daney if (alias_prop) {
8067ed18152SDavid Daney mgmt = fdt_path_offset(initial_boot_params, alias_prop);
8077ed18152SDavid Daney if (mgmt < 0)
8087ed18152SDavid Daney continue;
8097ed18152SDavid Daney if (i >= max_port) {
8107ed18152SDavid Daney pr_debug("Deleting mix%d\n", i);
8117ed18152SDavid Daney octeon_fdt_rm_ethernet(mgmt);
8127ed18152SDavid Daney fdt_nop_property(initial_boot_params, aliases,
8137ed18152SDavid Daney name_buffer);
8147ed18152SDavid Daney } else {
8157ed18152SDavid Daney int phy_addr = cvmx_helper_board_get_mii_address(CVMX_HELPER_BOARD_MGMT_IPD_PORT + i);
816e96b1b06SSteven J. Hill
8177ed18152SDavid Daney octeon_fdt_set_phy(mgmt, phy_addr);
8187ed18152SDavid Daney }
8197ed18152SDavid Daney }
8207ed18152SDavid Daney }
8217ed18152SDavid Daney
8227ed18152SDavid Daney pip_path = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
8237ed18152SDavid Daney if (pip_path) {
8247ed18152SDavid Daney int pip = fdt_path_offset(initial_boot_params, pip_path);
825e96b1b06SSteven J. Hill
8267ed18152SDavid Daney if (pip >= 0)
8277ed18152SDavid Daney for (i = 0; i <= 4; i++)
82843349b9eSAaro Koskinen octeon_fdt_pip_iface(pip, i);
8297ed18152SDavid Daney }
8307ed18152SDavid Daney
8317ed18152SDavid Daney /* I2C */
8327ed18152SDavid Daney if (OCTEON_IS_MODEL(OCTEON_CN52XX) ||
8337ed18152SDavid Daney OCTEON_IS_MODEL(OCTEON_CN63XX) ||
8347ed18152SDavid Daney OCTEON_IS_MODEL(OCTEON_CN68XX) ||
8357ed18152SDavid Daney OCTEON_IS_MODEL(OCTEON_CN56XX))
8367ed18152SDavid Daney max_port = 2;
8377ed18152SDavid Daney else
8387ed18152SDavid Daney max_port = 1;
8397ed18152SDavid Daney
8407ed18152SDavid Daney for (i = 0; i < 2; i++) {
8417ed18152SDavid Daney int i2c;
842e96b1b06SSteven J. Hill
8437ed18152SDavid Daney snprintf(name_buffer, sizeof(name_buffer),
8447ed18152SDavid Daney "twsi%d", i);
8457ed18152SDavid Daney alias_prop = fdt_getprop(initial_boot_params, aliases,
8467ed18152SDavid Daney name_buffer, NULL);
8477ed18152SDavid Daney
8487ed18152SDavid Daney if (alias_prop) {
8497ed18152SDavid Daney i2c = fdt_path_offset(initial_boot_params, alias_prop);
8507ed18152SDavid Daney if (i2c < 0)
8517ed18152SDavid Daney continue;
8527ed18152SDavid Daney if (i >= max_port) {
8537ed18152SDavid Daney pr_debug("Deleting twsi%d\n", i);
8547ed18152SDavid Daney fdt_nop_node(initial_boot_params, i2c);
8557ed18152SDavid Daney fdt_nop_property(initial_boot_params, aliases,
8567ed18152SDavid Daney name_buffer);
8577ed18152SDavid Daney }
8587ed18152SDavid Daney }
8597ed18152SDavid Daney }
8607ed18152SDavid Daney
8617ed18152SDavid Daney /* SMI/MDIO */
8627ed18152SDavid Daney if (OCTEON_IS_MODEL(OCTEON_CN68XX))
8637ed18152SDavid Daney max_port = 4;
8647ed18152SDavid Daney else if (OCTEON_IS_MODEL(OCTEON_CN52XX) ||
8657ed18152SDavid Daney OCTEON_IS_MODEL(OCTEON_CN63XX) ||
8667ed18152SDavid Daney OCTEON_IS_MODEL(OCTEON_CN56XX))
8677ed18152SDavid Daney max_port = 2;
8687ed18152SDavid Daney else
8697ed18152SDavid Daney max_port = 1;
8707ed18152SDavid Daney
8717ed18152SDavid Daney for (i = 0; i < 2; i++) {
8727ed18152SDavid Daney int i2c;
873e96b1b06SSteven J. Hill
8747ed18152SDavid Daney snprintf(name_buffer, sizeof(name_buffer),
8757ed18152SDavid Daney "smi%d", i);
8767ed18152SDavid Daney alias_prop = fdt_getprop(initial_boot_params, aliases,
8777ed18152SDavid Daney name_buffer, NULL);
8787ed18152SDavid Daney if (alias_prop) {
8797ed18152SDavid Daney i2c = fdt_path_offset(initial_boot_params, alias_prop);
8807ed18152SDavid Daney if (i2c < 0)
8817ed18152SDavid Daney continue;
8827ed18152SDavid Daney if (i >= max_port) {
8837ed18152SDavid Daney pr_debug("Deleting smi%d\n", i);
8847ed18152SDavid Daney fdt_nop_node(initial_boot_params, i2c);
8857ed18152SDavid Daney fdt_nop_property(initial_boot_params, aliases,
8867ed18152SDavid Daney name_buffer);
8877ed18152SDavid Daney }
8887ed18152SDavid Daney }
8897ed18152SDavid Daney }
8907ed18152SDavid Daney
8917ed18152SDavid Daney /* Serial */
8927ed18152SDavid Daney uart_mask = 3;
8937ed18152SDavid Daney
8947ed18152SDavid Daney /* Right now CN52XX is the only chip with a third uart */
8957ed18152SDavid Daney if (OCTEON_IS_MODEL(OCTEON_CN52XX))
8967ed18152SDavid Daney uart_mask |= 4; /* uart2 */
8977ed18152SDavid Daney
8987ed18152SDavid Daney for (i = 0; i < 3; i++) {
8997ed18152SDavid Daney int uart;
900e96b1b06SSteven J. Hill
9017ed18152SDavid Daney snprintf(name_buffer, sizeof(name_buffer),
9027ed18152SDavid Daney "uart%d", i);
9037ed18152SDavid Daney alias_prop = fdt_getprop(initial_boot_params, aliases,
9047ed18152SDavid Daney name_buffer, NULL);
9057ed18152SDavid Daney
9067ed18152SDavid Daney if (alias_prop) {
9077ed18152SDavid Daney uart = fdt_path_offset(initial_boot_params, alias_prop);
9085219343fSDavid Daney if (uart_mask & (1 << i)) {
9095219343fSDavid Daney __be32 f;
9105219343fSDavid Daney
9115219343fSDavid Daney f = cpu_to_be32(octeon_get_io_clock_rate());
9125219343fSDavid Daney fdt_setprop_inplace(initial_boot_params,
9135219343fSDavid Daney uart, "clock-frequency",
9145219343fSDavid Daney &f, sizeof(f));
9157ed18152SDavid Daney continue;
9165219343fSDavid Daney }
9177ed18152SDavid Daney pr_debug("Deleting uart%d\n", i);
9187ed18152SDavid Daney fdt_nop_node(initial_boot_params, uart);
9197ed18152SDavid Daney fdt_nop_property(initial_boot_params, aliases,
9207ed18152SDavid Daney name_buffer);
9217ed18152SDavid Daney }
9227ed18152SDavid Daney }
9237ed18152SDavid Daney
9247ed18152SDavid Daney /* Compact Flash */
9257ed18152SDavid Daney alias_prop = fdt_getprop(initial_boot_params, aliases,
9267ed18152SDavid Daney "cf0", NULL);
9277ed18152SDavid Daney if (alias_prop) {
9287ed18152SDavid Daney union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg;
9297ed18152SDavid Daney unsigned long base_ptr, region_base, region_size;
9307ed18152SDavid Daney unsigned long region1_base = 0;
9317ed18152SDavid Daney unsigned long region1_size = 0;
9327ed18152SDavid Daney int cs, bootbus;
9337ed18152SDavid Daney bool is_16bit = false;
9347ed18152SDavid Daney bool is_true_ide = false;
9357ed18152SDavid Daney __be32 new_reg[6];
9367ed18152SDavid Daney __be32 *ranges;
9377ed18152SDavid Daney int len;
9387ed18152SDavid Daney
9397ed18152SDavid Daney int cf = fdt_path_offset(initial_boot_params, alias_prop);
940e96b1b06SSteven J. Hill
9417ed18152SDavid Daney base_ptr = 0;
9427ed18152SDavid Daney if (octeon_bootinfo->major_version == 1
9437ed18152SDavid Daney && octeon_bootinfo->minor_version >= 1) {
9447ed18152SDavid Daney if (octeon_bootinfo->compact_flash_common_base_addr)
9457ed18152SDavid Daney base_ptr = octeon_bootinfo->compact_flash_common_base_addr;
9467ed18152SDavid Daney } else {
9477ed18152SDavid Daney base_ptr = 0x1d000800;
9487ed18152SDavid Daney }
9497ed18152SDavid Daney
9507ed18152SDavid Daney if (!base_ptr)
9517ed18152SDavid Daney goto no_cf;
9527ed18152SDavid Daney
9537ed18152SDavid Daney /* Find CS0 region. */
9547ed18152SDavid Daney for (cs = 0; cs < 8; cs++) {
9557ed18152SDavid Daney mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
9567ed18152SDavid Daney region_base = mio_boot_reg_cfg.s.base << 16;
9577ed18152SDavid Daney region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
9587ed18152SDavid Daney if (mio_boot_reg_cfg.s.en && base_ptr >= region_base
9597ed18152SDavid Daney && base_ptr < region_base + region_size) {
9607ed18152SDavid Daney is_16bit = mio_boot_reg_cfg.s.width;
9617ed18152SDavid Daney break;
9627ed18152SDavid Daney }
9637ed18152SDavid Daney }
9647ed18152SDavid Daney if (cs >= 7) {
9657ed18152SDavid Daney /* cs and cs + 1 are CS0 and CS1, both must be less than 8. */
9667ed18152SDavid Daney goto no_cf;
9677ed18152SDavid Daney }
9687ed18152SDavid Daney
9697ed18152SDavid Daney if (!(base_ptr & 0xfffful)) {
9707ed18152SDavid Daney /*
9717ed18152SDavid Daney * Boot loader signals availability of DMA (true_ide
9727ed18152SDavid Daney * mode) by setting low order bits of base_ptr to
9737ed18152SDavid Daney * zero.
9747ed18152SDavid Daney */
9757ed18152SDavid Daney
9767ed18152SDavid Daney /* Asume that CS1 immediately follows. */
9777ed18152SDavid Daney mio_boot_reg_cfg.u64 =
9787ed18152SDavid Daney cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs + 1));
9797ed18152SDavid Daney region1_base = mio_boot_reg_cfg.s.base << 16;
9807ed18152SDavid Daney region1_size = (mio_boot_reg_cfg.s.size + 1) << 16;
9817ed18152SDavid Daney if (!mio_boot_reg_cfg.s.en)
9827ed18152SDavid Daney goto no_cf;
9837ed18152SDavid Daney is_true_ide = true;
9847ed18152SDavid Daney
9857ed18152SDavid Daney } else {
9867ed18152SDavid Daney fdt_nop_property(initial_boot_params, cf, "cavium,true-ide");
9877ed18152SDavid Daney fdt_nop_property(initial_boot_params, cf, "cavium,dma-engine-handle");
9887ed18152SDavid Daney if (!is_16bit) {
9897ed18152SDavid Daney __be32 width = cpu_to_be32(8);
990e96b1b06SSteven J. Hill
9917ed18152SDavid Daney fdt_setprop_inplace(initial_boot_params, cf,
9927ed18152SDavid Daney "cavium,bus-width", &width, sizeof(width));
9937ed18152SDavid Daney }
9947ed18152SDavid Daney }
9957ed18152SDavid Daney new_reg[0] = cpu_to_be32(cs);
9967ed18152SDavid Daney new_reg[1] = cpu_to_be32(0);
9977ed18152SDavid Daney new_reg[2] = cpu_to_be32(0x10000);
9987ed18152SDavid Daney new_reg[3] = cpu_to_be32(cs + 1);
9997ed18152SDavid Daney new_reg[4] = cpu_to_be32(0);
10007ed18152SDavid Daney new_reg[5] = cpu_to_be32(0x10000);
10017ed18152SDavid Daney fdt_setprop_inplace(initial_boot_params, cf,
10027ed18152SDavid Daney "reg", new_reg, sizeof(new_reg));
10037ed18152SDavid Daney
10047ed18152SDavid Daney bootbus = fdt_parent_offset(initial_boot_params, cf);
10057ed18152SDavid Daney if (bootbus < 0)
10067ed18152SDavid Daney goto no_cf;
10077ed18152SDavid Daney ranges = fdt_getprop_w(initial_boot_params, bootbus, "ranges", &len);
10087ed18152SDavid Daney if (!ranges || len < (5 * 8 * sizeof(__be32)))
10097ed18152SDavid Daney goto no_cf;
10107ed18152SDavid Daney
10117ed18152SDavid Daney ranges[(cs * 5) + 2] = cpu_to_be32(region_base >> 32);
10127ed18152SDavid Daney ranges[(cs * 5) + 3] = cpu_to_be32(region_base & 0xffffffff);
10137ed18152SDavid Daney ranges[(cs * 5) + 4] = cpu_to_be32(region_size);
10147ed18152SDavid Daney if (is_true_ide) {
10157ed18152SDavid Daney cs++;
10167ed18152SDavid Daney ranges[(cs * 5) + 2] = cpu_to_be32(region1_base >> 32);
10177ed18152SDavid Daney ranges[(cs * 5) + 3] = cpu_to_be32(region1_base & 0xffffffff);
10187ed18152SDavid Daney ranges[(cs * 5) + 4] = cpu_to_be32(region1_size);
10197ed18152SDavid Daney }
10207ed18152SDavid Daney goto end_cf;
10217ed18152SDavid Daney no_cf:
10227ed18152SDavid Daney fdt_nop_node(initial_boot_params, cf);
10237ed18152SDavid Daney
10247ed18152SDavid Daney end_cf:
10257ed18152SDavid Daney ;
10267ed18152SDavid Daney }
10277ed18152SDavid Daney
10287ed18152SDavid Daney /* 8 char LED */
10297ed18152SDavid Daney alias_prop = fdt_getprop(initial_boot_params, aliases,
10307ed18152SDavid Daney "led0", NULL);
10317ed18152SDavid Daney if (alias_prop) {
10327ed18152SDavid Daney union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg;
10337ed18152SDavid Daney unsigned long base_ptr, region_base, region_size;
10347ed18152SDavid Daney int cs, bootbus;
10357ed18152SDavid Daney __be32 new_reg[6];
10367ed18152SDavid Daney __be32 *ranges;
10377ed18152SDavid Daney int len;
10387ed18152SDavid Daney int led = fdt_path_offset(initial_boot_params, alias_prop);
10397ed18152SDavid Daney
10407ed18152SDavid Daney base_ptr = octeon_bootinfo->led_display_base_addr;
10417ed18152SDavid Daney if (base_ptr == 0)
10427ed18152SDavid Daney goto no_led;
10437ed18152SDavid Daney /* Find CS0 region. */
10447ed18152SDavid Daney for (cs = 0; cs < 8; cs++) {
10457ed18152SDavid Daney mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
10467ed18152SDavid Daney region_base = mio_boot_reg_cfg.s.base << 16;
10477ed18152SDavid Daney region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
10487ed18152SDavid Daney if (mio_boot_reg_cfg.s.en && base_ptr >= region_base
10497ed18152SDavid Daney && base_ptr < region_base + region_size)
10507ed18152SDavid Daney break;
10517ed18152SDavid Daney }
10527ed18152SDavid Daney
10537ed18152SDavid Daney if (cs > 7)
10547ed18152SDavid Daney goto no_led;
10557ed18152SDavid Daney
10567ed18152SDavid Daney new_reg[0] = cpu_to_be32(cs);
10577ed18152SDavid Daney new_reg[1] = cpu_to_be32(0x20);
10587ed18152SDavid Daney new_reg[2] = cpu_to_be32(0x20);
10597ed18152SDavid Daney new_reg[3] = cpu_to_be32(cs);
10607ed18152SDavid Daney new_reg[4] = cpu_to_be32(0);
10617ed18152SDavid Daney new_reg[5] = cpu_to_be32(0x20);
10627ed18152SDavid Daney fdt_setprop_inplace(initial_boot_params, led,
10637ed18152SDavid Daney "reg", new_reg, sizeof(new_reg));
10647ed18152SDavid Daney
10657ed18152SDavid Daney bootbus = fdt_parent_offset(initial_boot_params, led);
10667ed18152SDavid Daney if (bootbus < 0)
10677ed18152SDavid Daney goto no_led;
10687ed18152SDavid Daney ranges = fdt_getprop_w(initial_boot_params, bootbus, "ranges", &len);
10697ed18152SDavid Daney if (!ranges || len < (5 * 8 * sizeof(__be32)))
10707ed18152SDavid Daney goto no_led;
10717ed18152SDavid Daney
10727ed18152SDavid Daney ranges[(cs * 5) + 2] = cpu_to_be32(region_base >> 32);
10737ed18152SDavid Daney ranges[(cs * 5) + 3] = cpu_to_be32(region_base & 0xffffffff);
10747ed18152SDavid Daney ranges[(cs * 5) + 4] = cpu_to_be32(region_size);
10757ed18152SDavid Daney goto end_led;
10767ed18152SDavid Daney
10777ed18152SDavid Daney no_led:
10787ed18152SDavid Daney fdt_nop_node(initial_boot_params, led);
10797ed18152SDavid Daney end_led:
10807ed18152SDavid Daney ;
10817ed18152SDavid Daney }
10827ed18152SDavid Daney
10837fd57ab9SSteven J. Hill #ifdef CONFIG_USB
10847ed18152SDavid Daney /* OHCI/UHCI USB */
10857ed18152SDavid Daney alias_prop = fdt_getprop(initial_boot_params, aliases,
10867ed18152SDavid Daney "uctl", NULL);
10877ed18152SDavid Daney if (alias_prop) {
10887ed18152SDavid Daney int uctl = fdt_path_offset(initial_boot_params, alias_prop);
10897ed18152SDavid Daney
10907ed18152SDavid Daney if (uctl >= 0 && (!OCTEON_IS_MODEL(OCTEON_CN6XXX) ||
10917ed18152SDavid Daney octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC2E)) {
10927ed18152SDavid Daney pr_debug("Deleting uctl\n");
10937ed18152SDavid Daney fdt_nop_node(initial_boot_params, uctl);
10947ed18152SDavid Daney fdt_nop_property(initial_boot_params, aliases, "uctl");
10957ed18152SDavid Daney } else if (octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC10E ||
10967ed18152SDavid Daney octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC4E) {
10977ed18152SDavid Daney /* Missing "refclk-type" defaults to crystal. */
10987ed18152SDavid Daney fdt_nop_property(initial_boot_params, uctl, "refclk-type");
10997ed18152SDavid Daney }
11007ed18152SDavid Daney }
11017ed18152SDavid Daney
1102d617f9e9SDavid Daney /* DWC2 USB */
1103d617f9e9SDavid Daney alias_prop = fdt_getprop(initial_boot_params, aliases,
1104d617f9e9SDavid Daney "usbn", NULL);
1105d617f9e9SDavid Daney if (alias_prop) {
1106d617f9e9SDavid Daney int usbn = fdt_path_offset(initial_boot_params, alias_prop);
1107d617f9e9SDavid Daney
1108d617f9e9SDavid Daney if (usbn >= 0 && (current_cpu_type() == CPU_CAVIUM_OCTEON2 ||
1109d617f9e9SDavid Daney !octeon_has_feature(OCTEON_FEATURE_USB))) {
1110d617f9e9SDavid Daney pr_debug("Deleting usbn\n");
1111d617f9e9SDavid Daney fdt_nop_node(initial_boot_params, usbn);
1112d617f9e9SDavid Daney fdt_nop_property(initial_boot_params, aliases, "usbn");
1113d617f9e9SDavid Daney } else {
1114d617f9e9SDavid Daney __be32 new_f[1];
1115d617f9e9SDavid Daney enum cvmx_helper_board_usb_clock_types c;
1116e96b1b06SSteven J. Hill
1117d617f9e9SDavid Daney c = __cvmx_helper_board_usb_get_clock_type();
1118d617f9e9SDavid Daney switch (c) {
1119d617f9e9SDavid Daney case USB_CLOCK_TYPE_REF_48:
1120d617f9e9SDavid Daney new_f[0] = cpu_to_be32(48000000);
1121d617f9e9SDavid Daney fdt_setprop_inplace(initial_boot_params, usbn,
1122d617f9e9SDavid Daney "refclk-frequency", new_f, sizeof(new_f));
1123c9b02990SLiangliang Huang fallthrough;
1124d617f9e9SDavid Daney case USB_CLOCK_TYPE_REF_12:
1125d617f9e9SDavid Daney /* Missing "refclk-type" defaults to external. */
1126d617f9e9SDavid Daney fdt_nop_property(initial_boot_params, usbn, "refclk-type");
1127d617f9e9SDavid Daney break;
1128d617f9e9SDavid Daney default:
1129d617f9e9SDavid Daney break;
1130d617f9e9SDavid Daney }
1131d617f9e9SDavid Daney }
1132d617f9e9SDavid Daney }
11337fd57ab9SSteven J. Hill #endif
1134d617f9e9SDavid Daney
11357ed18152SDavid Daney return 0;
11367ed18152SDavid Daney }
11377ed18152SDavid Daney
octeon_publish_devices(void)11387ed18152SDavid Daney static int __init octeon_publish_devices(void)
11397ed18152SDavid Daney {
1140f072f9ceSRob Herring return of_platform_populate(NULL, octeon_ids, NULL, NULL);
11417ed18152SDavid Daney }
11428074d782SAaro Koskinen arch_initcall(octeon_publish_devices);
1143