^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * This file is subject to the terms and conditions of the GNU General Public
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * License. See the file "COPYING" in the main directory of this archive
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * for more details.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Copyright (C) 2004-2017 Cavium, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Copyright (C) 2008 Wind River Systems
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/etherdevice.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/of_platform.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) #include <linux/of_fdt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) #include <linux/libfdt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) #include <asm/octeon/octeon.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #include <asm/octeon/cvmx-helper-board.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #ifdef CONFIG_USB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/usb/ehci_def.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/usb/ehci_pdriver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/usb/ohci_pdriver.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <asm/octeon/cvmx-uctlx-defs.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define CVMX_UAHCX_EHCI_USBCMD (CVMX_ADD_IO_SEG(0x00016F0000000010ull))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #define CVMX_UAHCX_OHCI_USBCMD (CVMX_ADD_IO_SEG(0x00016F0000000408ull))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) static DEFINE_MUTEX(octeon2_usb_clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) static int octeon2_usb_clock_start_cnt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) static int __init octeon2_usb_reset(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) union cvmx_uctlx_clk_rst_ctl clk_rst_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) u32 ucmd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) if (!OCTEON_IS_OCTEON2())
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) if (clk_rst_ctl.s.hrst) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) ucmd = cvmx_read64_uint32(CVMX_UAHCX_EHCI_USBCMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) ucmd &= ~CMD_RUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) cvmx_write64_uint32(CVMX_UAHCX_EHCI_USBCMD, ucmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) mdelay(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) ucmd |= CMD_RESET;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) cvmx_write64_uint32(CVMX_UAHCX_EHCI_USBCMD, ucmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) ucmd = cvmx_read64_uint32(CVMX_UAHCX_OHCI_USBCMD);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) ucmd |= CMD_RUN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) cvmx_write64_uint32(CVMX_UAHCX_OHCI_USBCMD, ucmd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) arch_initcall(octeon2_usb_reset);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static void octeon2_usb_clocks_start(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) u64 div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) union cvmx_uctlx_if_ena if_ena;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) union cvmx_uctlx_clk_rst_ctl clk_rst_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) unsigned long io_clk_64_to_ns;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) u32 clock_rate = 12000000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) bool is_crystal_clock = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) mutex_lock(&octeon2_usb_clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) octeon2_usb_clock_start_cnt++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) if (octeon2_usb_clock_start_cnt != 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) io_clk_64_to_ns = 64000000000ull / octeon_get_io_clock_rate();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) if (dev->of_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) struct device_node *uctl_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) const char *clock_type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) uctl_node = of_get_parent(dev->of_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) if (!uctl_node) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) dev_err(dev, "No UCTL device node\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) i = of_property_read_u32(uctl_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) "refclk-frequency", &clock_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) if (i) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) dev_err(dev, "No UCTL \"refclk-frequency\"\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) goto exit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) i = of_property_read_string(uctl_node,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) "refclk-type", &clock_type);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) if (!i && strcmp("crystal", clock_type) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) is_crystal_clock = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) * Step 1: Wait for voltages stable. That surely happened
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) * before starting the kernel.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) * Step 2: Enable SCLK of UCTL by writing UCTL0_IF_ENA[EN] = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) if_ena.u64 = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) if_ena.s.en = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) cvmx_write_csr(CVMX_UCTLX_IF_ENA(0), if_ena.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) for (i = 0; i <= 1; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) port_ctl_status.u64 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) cvmx_read_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) /* Set txvreftune to 15 to obtain compliant 'eye' diagram. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) port_ctl_status.s.txvreftune = 15;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) port_ctl_status.s.txrisetune = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) port_ctl_status.s.txpreemphasistune = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) cvmx_write_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) port_ctl_status.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) /* Step 3: Configure the reference clock, PHY, and HCLK */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) * If the UCTL looks like it has already been started, skip
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) * the initialization, otherwise bus errors are obtained.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) if (clk_rst_ctl.s.hrst)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) goto end_clock;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) /* 3a */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) clk_rst_ctl.s.p_por = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) clk_rst_ctl.s.hrst = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) clk_rst_ctl.s.p_prst = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) clk_rst_ctl.s.h_clkdiv_rst = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) clk_rst_ctl.s.o_clkdiv_rst = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) clk_rst_ctl.s.h_clkdiv_en = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) clk_rst_ctl.s.o_clkdiv_en = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) /* 3b */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) clk_rst_ctl.s.p_refclk_sel = is_crystal_clock ? 0 : 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) switch (clock_rate) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) pr_err("Invalid UCTL clock rate of %u, using 12000000 instead\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) clock_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) case 12000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) clk_rst_ctl.s.p_refclk_div = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) case 24000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) clk_rst_ctl.s.p_refclk_div = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) case 48000000:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) clk_rst_ctl.s.p_refclk_div = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) /* 3c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) div = octeon_get_io_clock_rate() / 130000000ull;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) switch (div) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) case 0:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) div = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) case 1:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) case 2:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) case 3:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) case 4:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) case 5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) div = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) case 6:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) case 7:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) div = 6;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) case 8:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) case 9:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) case 10:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) case 11:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) div = 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) div = 12;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) clk_rst_ctl.s.h_div = div;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) /* Read it back, */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) clk_rst_ctl.s.h_clkdiv_en = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) /* 3d */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) clk_rst_ctl.s.h_clkdiv_rst = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) /* 3e: delay 64 io clocks */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) ndelay(io_clk_64_to_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) * Step 4: Program the power-on reset field in the UCTL
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) * clock-reset-control register.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) clk_rst_ctl.s.p_por = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) /* Step 5: Wait 3 ms for the PHY clock to start. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) mdelay(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) /* Steps 6..9 for ATE only, are skipped. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) /* Step 10: Configure the OHCI_CLK48 and OHCI_CLK12 clocks. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) /* 10a */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) clk_rst_ctl.s.o_clkdiv_rst = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) /* 10b */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) clk_rst_ctl.s.o_clkdiv_en = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) /* 10c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) ndelay(io_clk_64_to_ns);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) * Step 11: Program the PHY reset field:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) * UCTL0_CLK_RST_CTL[P_PRST] = 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) clk_rst_ctl.s.p_prst = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) /* Step 11b */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) /* Step 11c */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) clk_rst_ctl.s.p_prst = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) /* Step 11d */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) mdelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /* Step 11e */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) clk_rst_ctl.s.p_prst = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) /* Step 12: Wait 1 uS. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) udelay(1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) /* Step 13: Program the HRESET_N field: UCTL0_CLK_RST_CTL[HRST] = 1 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) clk_rst_ctl.s.hrst = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) end_clock:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) /* Set uSOF cycle period to 60,000 bits. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) cvmx_write_csr(CVMX_UCTLX_EHCI_FLA(0), 0x20ull);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) exit:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) mutex_unlock(&octeon2_usb_clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) static void octeon2_usb_clocks_stop(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) mutex_lock(&octeon2_usb_clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) octeon2_usb_clock_start_cnt--;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) mutex_unlock(&octeon2_usb_clocks_mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) static int octeon_ehci_power_on(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) octeon2_usb_clocks_start(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) static void octeon_ehci_power_off(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) octeon2_usb_clocks_stop();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) static struct usb_ehci_pdata octeon_ehci_pdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) /* Octeon EHCI matches CPU endianness. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) #ifdef __BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) .big_endian_mmio = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) * We can DMA from anywhere. But the descriptors must be in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) * the lower 4GB.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) .dma_mask_64 = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) .power_on = octeon_ehci_power_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) .power_off = octeon_ehci_power_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) static void __init octeon_ehci_hw_start(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) union cvmx_uctlx_ehci_ctl ehci_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) octeon2_usb_clocks_start(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) ehci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_EHCI_CTL(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) /* Use 64-bit addressing. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) ehci_ctl.s.ehci_64b_addr_en = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) ehci_ctl.s.l2c_addr_msb = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) #ifdef __BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) ehci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) ehci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) ehci_ctl.s.l2c_buff_emod = 0; /* not swapped. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) ehci_ctl.s.l2c_desc_emod = 0; /* not swapped. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) ehci_ctl.s.inv_reg_a2 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) cvmx_write_csr(CVMX_UCTLX_EHCI_CTL(0), ehci_ctl.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) octeon2_usb_clocks_stop();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) static int __init octeon_ehci_device_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) struct platform_device *pd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) struct device_node *ehci_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) ehci_node = of_find_node_by_name(NULL, "ehci");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) if (!ehci_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) pd = of_find_device_by_node(ehci_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) of_node_put(ehci_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) if (!pd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) pd->dev.platform_data = &octeon_ehci_pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) octeon_ehci_hw_start(&pd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) put_device(&pd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) device_initcall(octeon_ehci_device_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) static int octeon_ohci_power_on(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) octeon2_usb_clocks_start(&pdev->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) static void octeon_ohci_power_off(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) octeon2_usb_clocks_stop();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static struct usb_ohci_pdata octeon_ohci_pdata = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) /* Octeon OHCI matches CPU endianness. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) #ifdef __BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) .big_endian_mmio = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) .power_on = octeon_ohci_power_on,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) .power_off = octeon_ohci_power_off,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) static void __init octeon_ohci_hw_start(struct device *dev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) union cvmx_uctlx_ohci_ctl ohci_ctl;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) octeon2_usb_clocks_start(dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) ohci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_OHCI_CTL(0));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) ohci_ctl.s.l2c_addr_msb = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) #ifdef __BIG_ENDIAN
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) ohci_ctl.s.l2c_buff_emod = 1; /* Byte swapped. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) ohci_ctl.s.l2c_desc_emod = 1; /* Byte swapped. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) ohci_ctl.s.l2c_buff_emod = 0; /* not swapped. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) ohci_ctl.s.l2c_desc_emod = 0; /* not swapped. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) ohci_ctl.s.inv_reg_a2 = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) cvmx_write_csr(CVMX_UCTLX_OHCI_CTL(0), ohci_ctl.u64);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) octeon2_usb_clocks_stop();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) static int __init octeon_ohci_device_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) struct platform_device *pd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) struct device_node *ohci_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) ohci_node = of_find_node_by_name(NULL, "ohci");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) if (!ohci_node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) pd = of_find_device_by_node(ohci_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) of_node_put(ohci_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) if (!pd)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) pd->dev.platform_data = &octeon_ohci_pdata;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) octeon_ohci_hw_start(&pd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) put_device(&pd->dev);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) device_initcall(octeon_ohci_device_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 401) #endif /* CONFIG_USB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 402)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 403) /* Octeon Random Number Generator. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 404) static int __init octeon_rng_device_init(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 405) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 406) struct platform_device *pd;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 407) int ret = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 408)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 409) struct resource rng_resources[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 410) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 411) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 412) .start = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 413) .end = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS) + 0xf
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 414) }, {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 415) .flags = IORESOURCE_MEM,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 416) .start = cvmx_build_io_address(8, 0),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 417) .end = cvmx_build_io_address(8, 0) + 0x7
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 418) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 419) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 420)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 421) pd = platform_device_alloc("octeon_rng", -1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 422) if (!pd) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 423) ret = -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 424) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 425) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 426)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 427) ret = platform_device_add_resources(pd, rng_resources,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 428) ARRAY_SIZE(rng_resources));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 429) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 430) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 431)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 432) ret = platform_device_add(pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 433) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 434) goto fail;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 435)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 436) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 437) fail:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 438) platform_device_put(pd);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 439)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 440) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 441) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 442) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 443) device_initcall(octeon_rng_device_init);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 444)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 445) static const struct of_device_id octeon_ids[] __initconst = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 446) { .compatible = "simple-bus", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 447) { .compatible = "cavium,octeon-6335-uctl", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 448) { .compatible = "cavium,octeon-5750-usbn", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 449) { .compatible = "cavium,octeon-3860-bootbus", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 450) { .compatible = "cavium,mdio-mux", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 451) { .compatible = "gpio-leds", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 452) { .compatible = "cavium,octeon-7130-usb-uctl", },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 453) {},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 454) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 455)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 456) static bool __init octeon_has_88e1145(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 457) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 458) return !OCTEON_IS_MODEL(OCTEON_CN52XX) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 459) !OCTEON_IS_MODEL(OCTEON_CN6XXX) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 460) !OCTEON_IS_MODEL(OCTEON_CN56XX);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 461) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 462)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 463) static bool __init octeon_has_fixed_link(int ipd_port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 464) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 465) switch (cvmx_sysinfo_get()->board_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 466) case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 467) case CVMX_BOARD_TYPE_CN3010_EVB_HS5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 468) case CVMX_BOARD_TYPE_CN3020_EVB_HS5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 469) case CVMX_BOARD_TYPE_CUST_NB5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 470) case CVMX_BOARD_TYPE_EBH3100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 471) /* Port 1 on these boards is always gigabit. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 472) return ipd_port == 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 473) case CVMX_BOARD_TYPE_BBGW_REF:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 474) /* Ports 0 and 1 connect to the switch. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 475) return ipd_port == 0 || ipd_port == 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 476) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 477) return false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 478) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 479)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 480) static void __init octeon_fdt_set_phy(int eth, int phy_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 481) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 482) const __be32 *phy_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 483) const __be32 *alt_phy_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 484) const __be32 *reg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 485) u32 phandle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 486) int phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 487) int alt_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 488) const char *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 489) int current_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 490) char new_name[20];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 491)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 492) phy_handle = fdt_getprop(initial_boot_params, eth, "phy-handle", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 493) if (!phy_handle)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 494) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 495)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 496) phandle = be32_to_cpup(phy_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 497) phy = fdt_node_offset_by_phandle(initial_boot_params, phandle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 498)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 499) alt_phy_handle = fdt_getprop(initial_boot_params, eth, "cavium,alt-phy-handle", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 500) if (alt_phy_handle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 501) u32 alt_phandle = be32_to_cpup(alt_phy_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 502)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 503) alt_phy = fdt_node_offset_by_phandle(initial_boot_params, alt_phandle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 504) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 505) alt_phy = -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 506) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 507)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 508) if (phy_addr < 0 || phy < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 509) /* Delete the PHY things */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 510) fdt_nop_property(initial_boot_params, eth, "phy-handle");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 511) /* This one may fail */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 512) fdt_nop_property(initial_boot_params, eth, "cavium,alt-phy-handle");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 513) if (phy >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 514) fdt_nop_node(initial_boot_params, phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 515) if (alt_phy >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 516) fdt_nop_node(initial_boot_params, alt_phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 517) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 518) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 519)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 520) if (phy_addr >= 256 && alt_phy > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 521) const struct fdt_property *phy_prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 522) struct fdt_property *alt_prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 523) fdt32_t phy_handle_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 524)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 525) /* Use the alt phy node instead.*/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 526) phy_prop = fdt_get_property(initial_boot_params, eth, "phy-handle", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 527) phy_handle_name = phy_prop->nameoff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 528) fdt_nop_node(initial_boot_params, phy);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 529) fdt_nop_property(initial_boot_params, eth, "phy-handle");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 530) alt_prop = fdt_get_property_w(initial_boot_params, eth, "cavium,alt-phy-handle", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 531) alt_prop->nameoff = phy_handle_name;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 532) phy = alt_phy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 533) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 534)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 535) phy_addr &= 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 536)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 537) if (octeon_has_88e1145()) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 538) fdt_nop_property(initial_boot_params, phy, "marvell,reg-init");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 539) memset(new_name, 0, sizeof(new_name));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 540) strcpy(new_name, "marvell,88e1145");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 541) p = fdt_getprop(initial_boot_params, phy, "compatible",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 542) ¤t_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 543) if (p && current_len >= strlen(new_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 544) fdt_setprop_inplace(initial_boot_params, phy,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 545) "compatible", new_name, current_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 546) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 547)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 548) reg = fdt_getprop(initial_boot_params, phy, "reg", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 549) if (phy_addr == be32_to_cpup(reg))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 550) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 551)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 552) fdt_setprop_inplace_cell(initial_boot_params, phy, "reg", phy_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 553)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 554) snprintf(new_name, sizeof(new_name), "ethernet-phy@%x", phy_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 555)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 556) p = fdt_get_name(initial_boot_params, phy, ¤t_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 557) if (p && current_len == strlen(new_name))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 558) fdt_set_name(initial_boot_params, phy, new_name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 559) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 560) pr_err("Error: could not rename ethernet phy: <%s>", p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 561) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 562)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 563) static void __init octeon_fdt_set_mac_addr(int n, u64 *pmac)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 564) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 565) const u8 *old_mac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 566) int old_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 567) u8 new_mac[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 568) u64 mac = *pmac;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 569) int r;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 570)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 571) old_mac = fdt_getprop(initial_boot_params, n, "local-mac-address",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 572) &old_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 573) if (!old_mac || old_len != 6 || is_valid_ether_addr(old_mac))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 574) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 575)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 576) new_mac[0] = (mac >> 40) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 577) new_mac[1] = (mac >> 32) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 578) new_mac[2] = (mac >> 24) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 579) new_mac[3] = (mac >> 16) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 580) new_mac[4] = (mac >> 8) & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 581) new_mac[5] = mac & 0xff;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 582)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 583) r = fdt_setprop_inplace(initial_boot_params, n, "local-mac-address",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 584) new_mac, sizeof(new_mac));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 585)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 586) if (r) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 587) pr_err("Setting \"local-mac-address\" failed %d", r);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 588) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 589) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 590) *pmac = mac + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 591) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 592)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 593) static void __init octeon_fdt_rm_ethernet(int node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 594) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 595) const __be32 *phy_handle;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 596)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 597) phy_handle = fdt_getprop(initial_boot_params, node, "phy-handle", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 598) if (phy_handle) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 599) u32 ph = be32_to_cpup(phy_handle);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 600) int p = fdt_node_offset_by_phandle(initial_boot_params, ph);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 601)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 602) if (p >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 603) fdt_nop_node(initial_boot_params, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 604) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 605) fdt_nop_node(initial_boot_params, node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 606) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 607)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 608) static void __init _octeon_rx_tx_delay(int eth, int rx_delay, int tx_delay)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 609) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 610) fdt_setprop_inplace_cell(initial_boot_params, eth, "rx-delay",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 611) rx_delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 612) fdt_setprop_inplace_cell(initial_boot_params, eth, "tx-delay",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 613) tx_delay);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 614) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 615)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 616) static void __init octeon_rx_tx_delay(int eth, int iface, int port)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 617) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 618) switch (cvmx_sysinfo_get()->board_type) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 619) case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 620) if (iface == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 621) if (port == 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 622) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 623) * Boards with gigabit WAN ports need a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 624) * different setting that is compatible with
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 625) * 100 Mbit settings
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 626) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 627) _octeon_rx_tx_delay(eth, 0xc, 0x0c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 628) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 629) } else if (port == 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 630) /* Different config for switch port. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 631) _octeon_rx_tx_delay(eth, 0x0, 0x0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 632) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 633) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 634) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 635) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 636) case CVMX_BOARD_TYPE_UBNT_E100:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 637) if (iface == 0 && port <= 2) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 638) _octeon_rx_tx_delay(eth, 0x0, 0x10);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 639) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 640) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 641) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 642) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 643) fdt_nop_property(initial_boot_params, eth, "rx-delay");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 644) fdt_nop_property(initial_boot_params, eth, "tx-delay");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 645) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 646)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 647) static void __init octeon_fdt_pip_port(int iface, int i, int p, int max)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 648) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 649) char name_buffer[20];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 650) int eth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 651) int phy_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 652) int ipd_port;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 653) int fixed_link;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 654)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 655) snprintf(name_buffer, sizeof(name_buffer), "ethernet@%x", p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 656) eth = fdt_subnode_offset(initial_boot_params, iface, name_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 657) if (eth < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 658) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 659) if (p > max) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 660) pr_debug("Deleting port %x:%x\n", i, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 661) octeon_fdt_rm_ethernet(eth);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 662) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 663) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 664) if (OCTEON_IS_MODEL(OCTEON_CN68XX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 665) ipd_port = (0x100 * i) + (0x10 * p) + 0x800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 666) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 667) ipd_port = 16 * i + p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 668)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 669) phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 670) octeon_fdt_set_phy(eth, phy_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 671)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 672) fixed_link = fdt_subnode_offset(initial_boot_params, eth, "fixed-link");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 673) if (fixed_link < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 674) WARN_ON(octeon_has_fixed_link(ipd_port));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 675) else if (!octeon_has_fixed_link(ipd_port))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 676) fdt_nop_node(initial_boot_params, fixed_link);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 677) octeon_rx_tx_delay(eth, i, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 678) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 679)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 680) static void __init octeon_fdt_pip_iface(int pip, int idx)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 681) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 682) char name_buffer[20];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 683) int iface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 684) int p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 685) int count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 686)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 687) snprintf(name_buffer, sizeof(name_buffer), "interface@%d", idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 688) iface = fdt_subnode_offset(initial_boot_params, pip, name_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 689) if (iface < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 690) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 691)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 692) if (cvmx_helper_interface_enumerate(idx) == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 693) count = cvmx_helper_ports_on_interface(idx);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 694)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 695) for (p = 0; p < 16; p++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 696) octeon_fdt_pip_port(iface, idx, p, count - 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 697) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 698)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 699) void __init octeon_fill_mac_addresses(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 700) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 701) const char *alias_prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 702) char name_buffer[20];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 703) u64 mac_addr_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 704) int aliases;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 705) int pip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 706) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 707)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 708) aliases = fdt_path_offset(initial_boot_params, "/aliases");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 709) if (aliases < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 710) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 711)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 712) mac_addr_base =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 713) ((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 714) ((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 715) ((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 716) ((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 717) ((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 |
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 718) (octeon_bootinfo->mac_addr_base[5] & 0xffull);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 719)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 720) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 721) int mgmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 722)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 723) snprintf(name_buffer, sizeof(name_buffer), "mix%d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 724) alias_prop = fdt_getprop(initial_boot_params, aliases,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 725) name_buffer, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 726) if (!alias_prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 727) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 728) mgmt = fdt_path_offset(initial_boot_params, alias_prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 729) if (mgmt < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 730) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 731) octeon_fdt_set_mac_addr(mgmt, &mac_addr_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 732) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 733)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 734) alias_prop = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 735) if (!alias_prop)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 736) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 737)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 738) pip = fdt_path_offset(initial_boot_params, alias_prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 739) if (pip < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 740) return;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 741)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 742) for (i = 0; i <= 4; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 743) int iface;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 744) int p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 745)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 746) snprintf(name_buffer, sizeof(name_buffer), "interface@%d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 747) iface = fdt_subnode_offset(initial_boot_params, pip,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 748) name_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 749) if (iface < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 750) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 751) for (p = 0; p < 16; p++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 752) int eth;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 753)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 754) snprintf(name_buffer, sizeof(name_buffer),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 755) "ethernet@%x", p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 756) eth = fdt_subnode_offset(initial_boot_params, iface,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 757) name_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 758) if (eth < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 759) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 760) octeon_fdt_set_mac_addr(eth, &mac_addr_base);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 761) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 762) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 763) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 764)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 765) int __init octeon_prune_device_tree(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 766) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 767) int i, max_port, uart_mask;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 768) const char *pip_path;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 769) const char *alias_prop;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 770) char name_buffer[20];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 771) int aliases;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 772)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 773) if (fdt_check_header(initial_boot_params))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 774) panic("Corrupt Device Tree.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 775)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 776) WARN(octeon_bootinfo->board_type == CVMX_BOARD_TYPE_CUST_DSR1000N,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 777) "Built-in DTB booting is deprecated on %s. Please switch to use appended DTB.",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 778) cvmx_board_type_to_string(octeon_bootinfo->board_type));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 779)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 780) aliases = fdt_path_offset(initial_boot_params, "/aliases");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 781) if (aliases < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 782) pr_err("Error: No /aliases node in device tree.");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 783) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 784) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 785)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 786) if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 787) max_port = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 788) else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN68XX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 789) max_port = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 790) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 791) max_port = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 792)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 793) if (octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC10E)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 794) max_port = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 795)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 796) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 797) int mgmt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 798)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 799) snprintf(name_buffer, sizeof(name_buffer),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 800) "mix%d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 801) alias_prop = fdt_getprop(initial_boot_params, aliases,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 802) name_buffer, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 803) if (alias_prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 804) mgmt = fdt_path_offset(initial_boot_params, alias_prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 805) if (mgmt < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 806) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 807) if (i >= max_port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 808) pr_debug("Deleting mix%d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 809) octeon_fdt_rm_ethernet(mgmt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 810) fdt_nop_property(initial_boot_params, aliases,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 811) name_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 812) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 813) int phy_addr = cvmx_helper_board_get_mii_address(CVMX_HELPER_BOARD_MGMT_IPD_PORT + i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 814)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 815) octeon_fdt_set_phy(mgmt, phy_addr);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 816) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 817) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 818) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 819)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 820) pip_path = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 821) if (pip_path) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 822) int pip = fdt_path_offset(initial_boot_params, pip_path);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 823)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 824) if (pip >= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 825) for (i = 0; i <= 4; i++)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 826) octeon_fdt_pip_iface(pip, i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 827) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 828)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 829) /* I2C */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 830) if (OCTEON_IS_MODEL(OCTEON_CN52XX) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 831) OCTEON_IS_MODEL(OCTEON_CN63XX) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 832) OCTEON_IS_MODEL(OCTEON_CN68XX) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 833) OCTEON_IS_MODEL(OCTEON_CN56XX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 834) max_port = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 835) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 836) max_port = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 837)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 838) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 839) int i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 840)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 841) snprintf(name_buffer, sizeof(name_buffer),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 842) "twsi%d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 843) alias_prop = fdt_getprop(initial_boot_params, aliases,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 844) name_buffer, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 845)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 846) if (alias_prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 847) i2c = fdt_path_offset(initial_boot_params, alias_prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 848) if (i2c < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 849) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 850) if (i >= max_port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 851) pr_debug("Deleting twsi%d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 852) fdt_nop_node(initial_boot_params, i2c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 853) fdt_nop_property(initial_boot_params, aliases,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 854) name_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 855) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 856) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 857) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 858)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 859) /* SMI/MDIO */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 860) if (OCTEON_IS_MODEL(OCTEON_CN68XX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 861) max_port = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 862) else if (OCTEON_IS_MODEL(OCTEON_CN52XX) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 863) OCTEON_IS_MODEL(OCTEON_CN63XX) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 864) OCTEON_IS_MODEL(OCTEON_CN56XX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 865) max_port = 2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 866) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 867) max_port = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 868)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 869) for (i = 0; i < 2; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 870) int i2c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 871)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 872) snprintf(name_buffer, sizeof(name_buffer),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 873) "smi%d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 874) alias_prop = fdt_getprop(initial_boot_params, aliases,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 875) name_buffer, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 876) if (alias_prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 877) i2c = fdt_path_offset(initial_boot_params, alias_prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 878) if (i2c < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 879) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 880) if (i >= max_port) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 881) pr_debug("Deleting smi%d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 882) fdt_nop_node(initial_boot_params, i2c);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 883) fdt_nop_property(initial_boot_params, aliases,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 884) name_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 885) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 886) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 887) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 888)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 889) /* Serial */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 890) uart_mask = 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 891)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 892) /* Right now CN52XX is the only chip with a third uart */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 893) if (OCTEON_IS_MODEL(OCTEON_CN52XX))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 894) uart_mask |= 4; /* uart2 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 895)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 896) for (i = 0; i < 3; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 897) int uart;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 898)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 899) snprintf(name_buffer, sizeof(name_buffer),
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 900) "uart%d", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 901) alias_prop = fdt_getprop(initial_boot_params, aliases,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 902) name_buffer, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 903)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 904) if (alias_prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 905) uart = fdt_path_offset(initial_boot_params, alias_prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 906) if (uart_mask & (1 << i)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 907) __be32 f;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 908)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 909) f = cpu_to_be32(octeon_get_io_clock_rate());
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 910) fdt_setprop_inplace(initial_boot_params,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 911) uart, "clock-frequency",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 912) &f, sizeof(f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 913) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 914) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 915) pr_debug("Deleting uart%d\n", i);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 916) fdt_nop_node(initial_boot_params, uart);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 917) fdt_nop_property(initial_boot_params, aliases,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 918) name_buffer);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 919) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 920) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 921)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 922) /* Compact Flash */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 923) alias_prop = fdt_getprop(initial_boot_params, aliases,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 924) "cf0", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 925) if (alias_prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 926) union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 927) unsigned long base_ptr, region_base, region_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 928) unsigned long region1_base = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 929) unsigned long region1_size = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 930) int cs, bootbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 931) bool is_16bit = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 932) bool is_true_ide = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 933) __be32 new_reg[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 934) __be32 *ranges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 935) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 936)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 937) int cf = fdt_path_offset(initial_boot_params, alias_prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 938)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 939) base_ptr = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 940) if (octeon_bootinfo->major_version == 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 941) && octeon_bootinfo->minor_version >= 1) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 942) if (octeon_bootinfo->compact_flash_common_base_addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 943) base_ptr = octeon_bootinfo->compact_flash_common_base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 944) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 945) base_ptr = 0x1d000800;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 946) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 947)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 948) if (!base_ptr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 949) goto no_cf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 950)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 951) /* Find CS0 region. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 952) for (cs = 0; cs < 8; cs++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 953) mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 954) region_base = mio_boot_reg_cfg.s.base << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 955) region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 956) if (mio_boot_reg_cfg.s.en && base_ptr >= region_base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 957) && base_ptr < region_base + region_size) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 958) is_16bit = mio_boot_reg_cfg.s.width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 959) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 960) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 961) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 962) if (cs >= 7) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 963) /* cs and cs + 1 are CS0 and CS1, both must be less than 8. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 964) goto no_cf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 965) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 966)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 967) if (!(base_ptr & 0xfffful)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 968) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 969) * Boot loader signals availability of DMA (true_ide
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 970) * mode) by setting low order bits of base_ptr to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 971) * zero.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 972) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 973)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 974) /* Asume that CS1 immediately follows. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 975) mio_boot_reg_cfg.u64 =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 976) cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs + 1));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 977) region1_base = mio_boot_reg_cfg.s.base << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 978) region1_size = (mio_boot_reg_cfg.s.size + 1) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 979) if (!mio_boot_reg_cfg.s.en)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 980) goto no_cf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 981) is_true_ide = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 982)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 983) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 984) fdt_nop_property(initial_boot_params, cf, "cavium,true-ide");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 985) fdt_nop_property(initial_boot_params, cf, "cavium,dma-engine-handle");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 986) if (!is_16bit) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 987) __be32 width = cpu_to_be32(8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 988)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 989) fdt_setprop_inplace(initial_boot_params, cf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 990) "cavium,bus-width", &width, sizeof(width));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 991) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 992) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 993) new_reg[0] = cpu_to_be32(cs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 994) new_reg[1] = cpu_to_be32(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 995) new_reg[2] = cpu_to_be32(0x10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 996) new_reg[3] = cpu_to_be32(cs + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 997) new_reg[4] = cpu_to_be32(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 998) new_reg[5] = cpu_to_be32(0x10000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 999) fdt_setprop_inplace(initial_boot_params, cf,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1000) "reg", new_reg, sizeof(new_reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1001)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1002) bootbus = fdt_parent_offset(initial_boot_params, cf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1003) if (bootbus < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1004) goto no_cf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1005) ranges = fdt_getprop_w(initial_boot_params, bootbus, "ranges", &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1006) if (!ranges || len < (5 * 8 * sizeof(__be32)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1007) goto no_cf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1008)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1009) ranges[(cs * 5) + 2] = cpu_to_be32(region_base >> 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1010) ranges[(cs * 5) + 3] = cpu_to_be32(region_base & 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1011) ranges[(cs * 5) + 4] = cpu_to_be32(region_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1012) if (is_true_ide) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1013) cs++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1014) ranges[(cs * 5) + 2] = cpu_to_be32(region1_base >> 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1015) ranges[(cs * 5) + 3] = cpu_to_be32(region1_base & 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1016) ranges[(cs * 5) + 4] = cpu_to_be32(region1_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1017) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1018) goto end_cf;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1019) no_cf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1020) fdt_nop_node(initial_boot_params, cf);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1021)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1022) end_cf:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1023) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1024) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1025)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1026) /* 8 char LED */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1027) alias_prop = fdt_getprop(initial_boot_params, aliases,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1028) "led0", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1029) if (alias_prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1030) union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1031) unsigned long base_ptr, region_base, region_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1032) int cs, bootbus;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1033) __be32 new_reg[6];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1034) __be32 *ranges;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1035) int len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1036) int led = fdt_path_offset(initial_boot_params, alias_prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1037)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1038) base_ptr = octeon_bootinfo->led_display_base_addr;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1039) if (base_ptr == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1040) goto no_led;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1041) /* Find CS0 region. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1042) for (cs = 0; cs < 8; cs++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1043) mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1044) region_base = mio_boot_reg_cfg.s.base << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1045) region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1046) if (mio_boot_reg_cfg.s.en && base_ptr >= region_base
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1047) && base_ptr < region_base + region_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1048) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1049) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1050)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1051) if (cs > 7)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1052) goto no_led;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1053)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1054) new_reg[0] = cpu_to_be32(cs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1055) new_reg[1] = cpu_to_be32(0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1056) new_reg[2] = cpu_to_be32(0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1057) new_reg[3] = cpu_to_be32(cs);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1058) new_reg[4] = cpu_to_be32(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1059) new_reg[5] = cpu_to_be32(0x20);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1060) fdt_setprop_inplace(initial_boot_params, led,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1061) "reg", new_reg, sizeof(new_reg));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1062)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1063) bootbus = fdt_parent_offset(initial_boot_params, led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1064) if (bootbus < 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1065) goto no_led;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1066) ranges = fdt_getprop_w(initial_boot_params, bootbus, "ranges", &len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1067) if (!ranges || len < (5 * 8 * sizeof(__be32)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1068) goto no_led;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1069)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1070) ranges[(cs * 5) + 2] = cpu_to_be32(region_base >> 32);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1071) ranges[(cs * 5) + 3] = cpu_to_be32(region_base & 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1072) ranges[(cs * 5) + 4] = cpu_to_be32(region_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1073) goto end_led;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1074)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1075) no_led:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1076) fdt_nop_node(initial_boot_params, led);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1077) end_led:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1078) ;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1079) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1080)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1081) #ifdef CONFIG_USB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1082) /* OHCI/UHCI USB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1083) alias_prop = fdt_getprop(initial_boot_params, aliases,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1084) "uctl", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1085) if (alias_prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1086) int uctl = fdt_path_offset(initial_boot_params, alias_prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1087)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1088) if (uctl >= 0 && (!OCTEON_IS_MODEL(OCTEON_CN6XXX) ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1089) octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC2E)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1090) pr_debug("Deleting uctl\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1091) fdt_nop_node(initial_boot_params, uctl);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1092) fdt_nop_property(initial_boot_params, aliases, "uctl");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1093) } else if (octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC10E ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1094) octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC4E) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1095) /* Missing "refclk-type" defaults to crystal. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1096) fdt_nop_property(initial_boot_params, uctl, "refclk-type");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1097) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1098) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1099)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1100) /* DWC2 USB */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1101) alias_prop = fdt_getprop(initial_boot_params, aliases,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1102) "usbn", NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1103) if (alias_prop) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1104) int usbn = fdt_path_offset(initial_boot_params, alias_prop);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1106) if (usbn >= 0 && (current_cpu_type() == CPU_CAVIUM_OCTEON2 ||
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1107) !octeon_has_feature(OCTEON_FEATURE_USB))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1108) pr_debug("Deleting usbn\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1109) fdt_nop_node(initial_boot_params, usbn);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1110) fdt_nop_property(initial_boot_params, aliases, "usbn");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1111) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1112) __be32 new_f[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1113) enum cvmx_helper_board_usb_clock_types c;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1114)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1115) c = __cvmx_helper_board_usb_get_clock_type();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1116) switch (c) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1117) case USB_CLOCK_TYPE_REF_48:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1118) new_f[0] = cpu_to_be32(48000000);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1119) fdt_setprop_inplace(initial_boot_params, usbn,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1120) "refclk-frequency", new_f, sizeof(new_f));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1121) fallthrough;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1122) case USB_CLOCK_TYPE_REF_12:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1123) /* Missing "refclk-type" defaults to external. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1124) fdt_nop_property(initial_boot_params, usbn, "refclk-type");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1125) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1126) default:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1127) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1128) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1129) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1130) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1131) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1133) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1134) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1135)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1136) static int __init octeon_publish_devices(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1137) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1138) return of_platform_populate(NULL, octeon_ids, NULL, NULL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1139) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1140) arch_initcall(octeon_publish_devices);