0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/etherdevice.h>
0011 #include <linux/of_platform.h>
0012 #include <linux/of_fdt.h>
0013 #include <linux/libfdt.h>
0014
0015 #include <asm/octeon/octeon.h>
0016 #include <asm/octeon/cvmx-helper-board.h>
0017
0018 #ifdef CONFIG_USB
0019 #include <linux/usb/ehci_def.h>
0020 #include <linux/usb/ehci_pdriver.h>
0021 #include <linux/usb/ohci_pdriver.h>
0022 #include <asm/octeon/cvmx-uctlx-defs.h>
0023
0024 #define CVMX_UAHCX_EHCI_USBCMD (CVMX_ADD_IO_SEG(0x00016F0000000010ull))
0025 #define CVMX_UAHCX_OHCI_USBCMD (CVMX_ADD_IO_SEG(0x00016F0000000408ull))
0026
0027 static DEFINE_MUTEX(octeon2_usb_clocks_mutex);
0028
0029 static int octeon2_usb_clock_start_cnt;
0030
0031 static int __init octeon2_usb_reset(void)
0032 {
0033 union cvmx_uctlx_clk_rst_ctl clk_rst_ctl;
0034 u32 ucmd;
0035
0036 if (!OCTEON_IS_OCTEON2())
0037 return 0;
0038
0039 clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
0040 if (clk_rst_ctl.s.hrst) {
0041 ucmd = cvmx_read64_uint32(CVMX_UAHCX_EHCI_USBCMD);
0042 ucmd &= ~CMD_RUN;
0043 cvmx_write64_uint32(CVMX_UAHCX_EHCI_USBCMD, ucmd);
0044 mdelay(2);
0045 ucmd |= CMD_RESET;
0046 cvmx_write64_uint32(CVMX_UAHCX_EHCI_USBCMD, ucmd);
0047 ucmd = cvmx_read64_uint32(CVMX_UAHCX_OHCI_USBCMD);
0048 ucmd |= CMD_RUN;
0049 cvmx_write64_uint32(CVMX_UAHCX_OHCI_USBCMD, ucmd);
0050 }
0051
0052 return 0;
0053 }
0054 arch_initcall(octeon2_usb_reset);
0055
0056 static void octeon2_usb_clocks_start(struct device *dev)
0057 {
0058 u64 div;
0059 union cvmx_uctlx_if_ena if_ena;
0060 union cvmx_uctlx_clk_rst_ctl clk_rst_ctl;
0061 union cvmx_uctlx_uphy_portx_ctl_status port_ctl_status;
0062 int i;
0063 unsigned long io_clk_64_to_ns;
0064 u32 clock_rate = 12000000;
0065 bool is_crystal_clock = false;
0066
0067
0068 mutex_lock(&octeon2_usb_clocks_mutex);
0069
0070 octeon2_usb_clock_start_cnt++;
0071 if (octeon2_usb_clock_start_cnt != 1)
0072 goto exit;
0073
0074 io_clk_64_to_ns = 64000000000ull / octeon_get_io_clock_rate();
0075
0076 if (dev->of_node) {
0077 struct device_node *uctl_node;
0078 const char *clock_type;
0079
0080 uctl_node = of_get_parent(dev->of_node);
0081 if (!uctl_node) {
0082 dev_err(dev, "No UCTL device node\n");
0083 goto exit;
0084 }
0085 i = of_property_read_u32(uctl_node,
0086 "refclk-frequency", &clock_rate);
0087 if (i) {
0088 dev_err(dev, "No UCTL \"refclk-frequency\"\n");
0089 of_node_put(uctl_node);
0090 goto exit;
0091 }
0092 i = of_property_read_string(uctl_node,
0093 "refclk-type", &clock_type);
0094 of_node_put(uctl_node);
0095 if (!i && strcmp("crystal", clock_type) == 0)
0096 is_crystal_clock = true;
0097 }
0098
0099
0100
0101
0102
0103
0104
0105 if_ena.u64 = 0;
0106 if_ena.s.en = 1;
0107 cvmx_write_csr(CVMX_UCTLX_IF_ENA(0), if_ena.u64);
0108
0109 for (i = 0; i <= 1; i++) {
0110 port_ctl_status.u64 =
0111 cvmx_read_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0));
0112
0113 port_ctl_status.s.txvreftune = 15;
0114 port_ctl_status.s.txrisetune = 1;
0115 port_ctl_status.s.txpreemphasistune = 1;
0116 cvmx_write_csr(CVMX_UCTLX_UPHY_PORTX_CTL_STATUS(i, 0),
0117 port_ctl_status.u64);
0118 }
0119
0120
0121 clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
0122
0123
0124
0125
0126
0127 if (clk_rst_ctl.s.hrst)
0128 goto end_clock;
0129
0130 clk_rst_ctl.s.p_por = 1;
0131 clk_rst_ctl.s.hrst = 0;
0132 clk_rst_ctl.s.p_prst = 0;
0133 clk_rst_ctl.s.h_clkdiv_rst = 0;
0134 clk_rst_ctl.s.o_clkdiv_rst = 0;
0135 clk_rst_ctl.s.h_clkdiv_en = 0;
0136 clk_rst_ctl.s.o_clkdiv_en = 0;
0137 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
0138
0139
0140 clk_rst_ctl.s.p_refclk_sel = is_crystal_clock ? 0 : 1;
0141 switch (clock_rate) {
0142 default:
0143 pr_err("Invalid UCTL clock rate of %u, using 12000000 instead\n",
0144 clock_rate);
0145 fallthrough;
0146 case 12000000:
0147 clk_rst_ctl.s.p_refclk_div = 0;
0148 break;
0149 case 24000000:
0150 clk_rst_ctl.s.p_refclk_div = 1;
0151 break;
0152 case 48000000:
0153 clk_rst_ctl.s.p_refclk_div = 2;
0154 break;
0155 }
0156 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
0157
0158
0159 div = octeon_get_io_clock_rate() / 130000000ull;
0160
0161 switch (div) {
0162 case 0:
0163 div = 1;
0164 break;
0165 case 1:
0166 case 2:
0167 case 3:
0168 case 4:
0169 break;
0170 case 5:
0171 div = 4;
0172 break;
0173 case 6:
0174 case 7:
0175 div = 6;
0176 break;
0177 case 8:
0178 case 9:
0179 case 10:
0180 case 11:
0181 div = 8;
0182 break;
0183 default:
0184 div = 12;
0185 break;
0186 }
0187 clk_rst_ctl.s.h_div = div;
0188 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
0189
0190 clk_rst_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_CLK_RST_CTL(0));
0191 clk_rst_ctl.s.h_clkdiv_en = 1;
0192 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
0193
0194 clk_rst_ctl.s.h_clkdiv_rst = 1;
0195 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
0196
0197
0198 ndelay(io_clk_64_to_ns);
0199
0200
0201
0202
0203
0204 clk_rst_ctl.s.p_por = 0;
0205 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
0206
0207
0208 mdelay(3);
0209
0210
0211
0212
0213
0214 clk_rst_ctl.s.o_clkdiv_rst = 1;
0215 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
0216
0217
0218 clk_rst_ctl.s.o_clkdiv_en = 1;
0219 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
0220
0221
0222 ndelay(io_clk_64_to_ns);
0223
0224
0225
0226
0227
0228 clk_rst_ctl.s.p_prst = 1;
0229 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
0230
0231
0232 udelay(1);
0233
0234
0235 clk_rst_ctl.s.p_prst = 0;
0236 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
0237
0238
0239 mdelay(1);
0240
0241
0242 clk_rst_ctl.s.p_prst = 1;
0243 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
0244
0245
0246 udelay(1);
0247
0248
0249 clk_rst_ctl.s.hrst = 1;
0250 cvmx_write_csr(CVMX_UCTLX_CLK_RST_CTL(0), clk_rst_ctl.u64);
0251
0252 end_clock:
0253
0254 cvmx_write_csr(CVMX_UCTLX_EHCI_FLA(0), 0x20ull);
0255
0256 exit:
0257 mutex_unlock(&octeon2_usb_clocks_mutex);
0258 }
0259
0260 static void octeon2_usb_clocks_stop(void)
0261 {
0262 mutex_lock(&octeon2_usb_clocks_mutex);
0263 octeon2_usb_clock_start_cnt--;
0264 mutex_unlock(&octeon2_usb_clocks_mutex);
0265 }
0266
0267 static int octeon_ehci_power_on(struct platform_device *pdev)
0268 {
0269 octeon2_usb_clocks_start(&pdev->dev);
0270 return 0;
0271 }
0272
0273 static void octeon_ehci_power_off(struct platform_device *pdev)
0274 {
0275 octeon2_usb_clocks_stop();
0276 }
0277
0278 static struct usb_ehci_pdata octeon_ehci_pdata = {
0279
0280 #ifdef __BIG_ENDIAN
0281 .big_endian_mmio = 1,
0282 #endif
0283
0284
0285
0286
0287 .dma_mask_64 = 0,
0288 .power_on = octeon_ehci_power_on,
0289 .power_off = octeon_ehci_power_off,
0290 };
0291
0292 static void __init octeon_ehci_hw_start(struct device *dev)
0293 {
0294 union cvmx_uctlx_ehci_ctl ehci_ctl;
0295
0296 octeon2_usb_clocks_start(dev);
0297
0298 ehci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_EHCI_CTL(0));
0299
0300 ehci_ctl.s.ehci_64b_addr_en = 1;
0301 ehci_ctl.s.l2c_addr_msb = 0;
0302 #ifdef __BIG_ENDIAN
0303 ehci_ctl.s.l2c_buff_emod = 1;
0304 ehci_ctl.s.l2c_desc_emod = 1;
0305 #else
0306 ehci_ctl.s.l2c_buff_emod = 0;
0307 ehci_ctl.s.l2c_desc_emod = 0;
0308 ehci_ctl.s.inv_reg_a2 = 1;
0309 #endif
0310 cvmx_write_csr(CVMX_UCTLX_EHCI_CTL(0), ehci_ctl.u64);
0311
0312 octeon2_usb_clocks_stop();
0313 }
0314
0315 static int __init octeon_ehci_device_init(void)
0316 {
0317 struct platform_device *pd;
0318 struct device_node *ehci_node;
0319 int ret = 0;
0320
0321 ehci_node = of_find_node_by_name(NULL, "ehci");
0322 if (!ehci_node)
0323 return 0;
0324
0325 pd = of_find_device_by_node(ehci_node);
0326 of_node_put(ehci_node);
0327 if (!pd)
0328 return 0;
0329
0330 pd->dev.platform_data = &octeon_ehci_pdata;
0331 octeon_ehci_hw_start(&pd->dev);
0332 put_device(&pd->dev);
0333
0334 return ret;
0335 }
0336 device_initcall(octeon_ehci_device_init);
0337
0338 static int octeon_ohci_power_on(struct platform_device *pdev)
0339 {
0340 octeon2_usb_clocks_start(&pdev->dev);
0341 return 0;
0342 }
0343
0344 static void octeon_ohci_power_off(struct platform_device *pdev)
0345 {
0346 octeon2_usb_clocks_stop();
0347 }
0348
0349 static struct usb_ohci_pdata octeon_ohci_pdata = {
0350
0351 #ifdef __BIG_ENDIAN
0352 .big_endian_mmio = 1,
0353 #endif
0354 .power_on = octeon_ohci_power_on,
0355 .power_off = octeon_ohci_power_off,
0356 };
0357
0358 static void __init octeon_ohci_hw_start(struct device *dev)
0359 {
0360 union cvmx_uctlx_ohci_ctl ohci_ctl;
0361
0362 octeon2_usb_clocks_start(dev);
0363
0364 ohci_ctl.u64 = cvmx_read_csr(CVMX_UCTLX_OHCI_CTL(0));
0365 ohci_ctl.s.l2c_addr_msb = 0;
0366 #ifdef __BIG_ENDIAN
0367 ohci_ctl.s.l2c_buff_emod = 1;
0368 ohci_ctl.s.l2c_desc_emod = 1;
0369 #else
0370 ohci_ctl.s.l2c_buff_emod = 0;
0371 ohci_ctl.s.l2c_desc_emod = 0;
0372 ohci_ctl.s.inv_reg_a2 = 1;
0373 #endif
0374 cvmx_write_csr(CVMX_UCTLX_OHCI_CTL(0), ohci_ctl.u64);
0375
0376 octeon2_usb_clocks_stop();
0377 }
0378
0379 static int __init octeon_ohci_device_init(void)
0380 {
0381 struct platform_device *pd;
0382 struct device_node *ohci_node;
0383 int ret = 0;
0384
0385 ohci_node = of_find_node_by_name(NULL, "ohci");
0386 if (!ohci_node)
0387 return 0;
0388
0389 pd = of_find_device_by_node(ohci_node);
0390 of_node_put(ohci_node);
0391 if (!pd)
0392 return 0;
0393
0394 pd->dev.platform_data = &octeon_ohci_pdata;
0395 octeon_ohci_hw_start(&pd->dev);
0396 put_device(&pd->dev);
0397
0398 return ret;
0399 }
0400 device_initcall(octeon_ohci_device_init);
0401
0402 #endif
0403
0404
0405 static int __init octeon_rng_device_init(void)
0406 {
0407 struct platform_device *pd;
0408 int ret = 0;
0409
0410 struct resource rng_resources[] = {
0411 {
0412 .flags = IORESOURCE_MEM,
0413 .start = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS),
0414 .end = XKPHYS_TO_PHYS(CVMX_RNM_CTL_STATUS) + 0xf
0415 }, {
0416 .flags = IORESOURCE_MEM,
0417 .start = cvmx_build_io_address(8, 0),
0418 .end = cvmx_build_io_address(8, 0) + 0x7
0419 }
0420 };
0421
0422 pd = platform_device_alloc("octeon_rng", -1);
0423 if (!pd) {
0424 ret = -ENOMEM;
0425 goto out;
0426 }
0427
0428 ret = platform_device_add_resources(pd, rng_resources,
0429 ARRAY_SIZE(rng_resources));
0430 if (ret)
0431 goto fail;
0432
0433 ret = platform_device_add(pd);
0434 if (ret)
0435 goto fail;
0436
0437 return ret;
0438 fail:
0439 platform_device_put(pd);
0440
0441 out:
0442 return ret;
0443 }
0444 device_initcall(octeon_rng_device_init);
0445
0446 static const struct of_device_id octeon_ids[] __initconst = {
0447 { .compatible = "simple-bus", },
0448 { .compatible = "cavium,octeon-6335-uctl", },
0449 { .compatible = "cavium,octeon-5750-usbn", },
0450 { .compatible = "cavium,octeon-3860-bootbus", },
0451 { .compatible = "cavium,mdio-mux", },
0452 { .compatible = "gpio-leds", },
0453 { .compatible = "cavium,octeon-7130-usb-uctl", },
0454 {},
0455 };
0456
0457 static bool __init octeon_has_88e1145(void)
0458 {
0459 return !OCTEON_IS_MODEL(OCTEON_CN52XX) &&
0460 !OCTEON_IS_MODEL(OCTEON_CN6XXX) &&
0461 !OCTEON_IS_MODEL(OCTEON_CN56XX);
0462 }
0463
0464 static bool __init octeon_has_fixed_link(int ipd_port)
0465 {
0466 switch (cvmx_sysinfo_get()->board_type) {
0467 case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
0468 case CVMX_BOARD_TYPE_CN3010_EVB_HS5:
0469 case CVMX_BOARD_TYPE_CN3020_EVB_HS5:
0470 case CVMX_BOARD_TYPE_CUST_NB5:
0471 case CVMX_BOARD_TYPE_EBH3100:
0472
0473 return ipd_port == 1;
0474 case CVMX_BOARD_TYPE_BBGW_REF:
0475
0476 return ipd_port == 0 || ipd_port == 1;
0477 }
0478 return false;
0479 }
0480
0481 static void __init octeon_fdt_set_phy(int eth, int phy_addr)
0482 {
0483 const __be32 *phy_handle;
0484 const __be32 *alt_phy_handle;
0485 const __be32 *reg;
0486 u32 phandle;
0487 int phy;
0488 int alt_phy;
0489 const char *p;
0490 int current_len;
0491 char new_name[20];
0492
0493 phy_handle = fdt_getprop(initial_boot_params, eth, "phy-handle", NULL);
0494 if (!phy_handle)
0495 return;
0496
0497 phandle = be32_to_cpup(phy_handle);
0498 phy = fdt_node_offset_by_phandle(initial_boot_params, phandle);
0499
0500 alt_phy_handle = fdt_getprop(initial_boot_params, eth, "cavium,alt-phy-handle", NULL);
0501 if (alt_phy_handle) {
0502 u32 alt_phandle = be32_to_cpup(alt_phy_handle);
0503
0504 alt_phy = fdt_node_offset_by_phandle(initial_boot_params, alt_phandle);
0505 } else {
0506 alt_phy = -1;
0507 }
0508
0509 if (phy_addr < 0 || phy < 0) {
0510
0511 fdt_nop_property(initial_boot_params, eth, "phy-handle");
0512
0513 fdt_nop_property(initial_boot_params, eth, "cavium,alt-phy-handle");
0514 if (phy >= 0)
0515 fdt_nop_node(initial_boot_params, phy);
0516 if (alt_phy >= 0)
0517 fdt_nop_node(initial_boot_params, alt_phy);
0518 return;
0519 }
0520
0521 if (phy_addr >= 256 && alt_phy > 0) {
0522 const struct fdt_property *phy_prop;
0523 struct fdt_property *alt_prop;
0524 fdt32_t phy_handle_name;
0525
0526
0527 phy_prop = fdt_get_property(initial_boot_params, eth, "phy-handle", NULL);
0528 phy_handle_name = phy_prop->nameoff;
0529 fdt_nop_node(initial_boot_params, phy);
0530 fdt_nop_property(initial_boot_params, eth, "phy-handle");
0531 alt_prop = fdt_get_property_w(initial_boot_params, eth, "cavium,alt-phy-handle", NULL);
0532 alt_prop->nameoff = phy_handle_name;
0533 phy = alt_phy;
0534 }
0535
0536 phy_addr &= 0xff;
0537
0538 if (octeon_has_88e1145()) {
0539 fdt_nop_property(initial_boot_params, phy, "marvell,reg-init");
0540 memset(new_name, 0, sizeof(new_name));
0541 strcpy(new_name, "marvell,88e1145");
0542 p = fdt_getprop(initial_boot_params, phy, "compatible",
0543 ¤t_len);
0544 if (p && current_len >= strlen(new_name))
0545 fdt_setprop_inplace(initial_boot_params, phy,
0546 "compatible", new_name, current_len);
0547 }
0548
0549 reg = fdt_getprop(initial_boot_params, phy, "reg", NULL);
0550 if (phy_addr == be32_to_cpup(reg))
0551 return;
0552
0553 fdt_setprop_inplace_cell(initial_boot_params, phy, "reg", phy_addr);
0554
0555 snprintf(new_name, sizeof(new_name), "ethernet-phy@%x", phy_addr);
0556
0557 p = fdt_get_name(initial_boot_params, phy, ¤t_len);
0558 if (p && current_len == strlen(new_name))
0559 fdt_set_name(initial_boot_params, phy, new_name);
0560 else
0561 pr_err("Error: could not rename ethernet phy: <%s>", p);
0562 }
0563
0564 static void __init octeon_fdt_set_mac_addr(int n, u64 *pmac)
0565 {
0566 const u8 *old_mac;
0567 int old_len;
0568 u8 new_mac[6];
0569 u64 mac = *pmac;
0570 int r;
0571
0572 old_mac = fdt_getprop(initial_boot_params, n, "local-mac-address",
0573 &old_len);
0574 if (!old_mac || old_len != 6 || is_valid_ether_addr(old_mac))
0575 return;
0576
0577 new_mac[0] = (mac >> 40) & 0xff;
0578 new_mac[1] = (mac >> 32) & 0xff;
0579 new_mac[2] = (mac >> 24) & 0xff;
0580 new_mac[3] = (mac >> 16) & 0xff;
0581 new_mac[4] = (mac >> 8) & 0xff;
0582 new_mac[5] = mac & 0xff;
0583
0584 r = fdt_setprop_inplace(initial_boot_params, n, "local-mac-address",
0585 new_mac, sizeof(new_mac));
0586
0587 if (r) {
0588 pr_err("Setting \"local-mac-address\" failed %d", r);
0589 return;
0590 }
0591 *pmac = mac + 1;
0592 }
0593
0594 static void __init octeon_fdt_rm_ethernet(int node)
0595 {
0596 const __be32 *phy_handle;
0597
0598 phy_handle = fdt_getprop(initial_boot_params, node, "phy-handle", NULL);
0599 if (phy_handle) {
0600 u32 ph = be32_to_cpup(phy_handle);
0601 int p = fdt_node_offset_by_phandle(initial_boot_params, ph);
0602
0603 if (p >= 0)
0604 fdt_nop_node(initial_boot_params, p);
0605 }
0606 fdt_nop_node(initial_boot_params, node);
0607 }
0608
0609 static void __init _octeon_rx_tx_delay(int eth, int rx_delay, int tx_delay)
0610 {
0611 fdt_setprop_inplace_cell(initial_boot_params, eth, "rx-delay",
0612 rx_delay);
0613 fdt_setprop_inplace_cell(initial_boot_params, eth, "tx-delay",
0614 tx_delay);
0615 }
0616
0617 static void __init octeon_rx_tx_delay(int eth, int iface, int port)
0618 {
0619 switch (cvmx_sysinfo_get()->board_type) {
0620 case CVMX_BOARD_TYPE_CN3005_EVB_HS5:
0621 if (iface == 0) {
0622 if (port == 0) {
0623
0624
0625
0626
0627
0628 _octeon_rx_tx_delay(eth, 0xc, 0x0c);
0629 return;
0630 } else if (port == 1) {
0631
0632 _octeon_rx_tx_delay(eth, 0x0, 0x0);
0633 return;
0634 }
0635 }
0636 break;
0637 case CVMX_BOARD_TYPE_UBNT_E100:
0638 if (iface == 0 && port <= 2) {
0639 _octeon_rx_tx_delay(eth, 0x0, 0x10);
0640 return;
0641 }
0642 break;
0643 }
0644 fdt_nop_property(initial_boot_params, eth, "rx-delay");
0645 fdt_nop_property(initial_boot_params, eth, "tx-delay");
0646 }
0647
0648 static void __init octeon_fdt_pip_port(int iface, int i, int p, int max)
0649 {
0650 char name_buffer[20];
0651 int eth;
0652 int phy_addr;
0653 int ipd_port;
0654 int fixed_link;
0655
0656 snprintf(name_buffer, sizeof(name_buffer), "ethernet@%x", p);
0657 eth = fdt_subnode_offset(initial_boot_params, iface, name_buffer);
0658 if (eth < 0)
0659 return;
0660 if (p > max) {
0661 pr_debug("Deleting port %x:%x\n", i, p);
0662 octeon_fdt_rm_ethernet(eth);
0663 return;
0664 }
0665 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
0666 ipd_port = (0x100 * i) + (0x10 * p) + 0x800;
0667 else
0668 ipd_port = 16 * i + p;
0669
0670 phy_addr = cvmx_helper_board_get_mii_address(ipd_port);
0671 octeon_fdt_set_phy(eth, phy_addr);
0672
0673 fixed_link = fdt_subnode_offset(initial_boot_params, eth, "fixed-link");
0674 if (fixed_link < 0)
0675 WARN_ON(octeon_has_fixed_link(ipd_port));
0676 else if (!octeon_has_fixed_link(ipd_port))
0677 fdt_nop_node(initial_boot_params, fixed_link);
0678 octeon_rx_tx_delay(eth, i, p);
0679 }
0680
0681 static void __init octeon_fdt_pip_iface(int pip, int idx)
0682 {
0683 char name_buffer[20];
0684 int iface;
0685 int p;
0686 int count = 0;
0687
0688 snprintf(name_buffer, sizeof(name_buffer), "interface@%d", idx);
0689 iface = fdt_subnode_offset(initial_boot_params, pip, name_buffer);
0690 if (iface < 0)
0691 return;
0692
0693 if (cvmx_helper_interface_enumerate(idx) == 0)
0694 count = cvmx_helper_ports_on_interface(idx);
0695
0696 for (p = 0; p < 16; p++)
0697 octeon_fdt_pip_port(iface, idx, p, count - 1);
0698 }
0699
0700 void __init octeon_fill_mac_addresses(void)
0701 {
0702 const char *alias_prop;
0703 char name_buffer[20];
0704 u64 mac_addr_base;
0705 int aliases;
0706 int pip;
0707 int i;
0708
0709 aliases = fdt_path_offset(initial_boot_params, "/aliases");
0710 if (aliases < 0)
0711 return;
0712
0713 mac_addr_base =
0714 ((octeon_bootinfo->mac_addr_base[0] & 0xffull)) << 40 |
0715 ((octeon_bootinfo->mac_addr_base[1] & 0xffull)) << 32 |
0716 ((octeon_bootinfo->mac_addr_base[2] & 0xffull)) << 24 |
0717 ((octeon_bootinfo->mac_addr_base[3] & 0xffull)) << 16 |
0718 ((octeon_bootinfo->mac_addr_base[4] & 0xffull)) << 8 |
0719 (octeon_bootinfo->mac_addr_base[5] & 0xffull);
0720
0721 for (i = 0; i < 2; i++) {
0722 int mgmt;
0723
0724 snprintf(name_buffer, sizeof(name_buffer), "mix%d", i);
0725 alias_prop = fdt_getprop(initial_boot_params, aliases,
0726 name_buffer, NULL);
0727 if (!alias_prop)
0728 continue;
0729 mgmt = fdt_path_offset(initial_boot_params, alias_prop);
0730 if (mgmt < 0)
0731 continue;
0732 octeon_fdt_set_mac_addr(mgmt, &mac_addr_base);
0733 }
0734
0735 alias_prop = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
0736 if (!alias_prop)
0737 return;
0738
0739 pip = fdt_path_offset(initial_boot_params, alias_prop);
0740 if (pip < 0)
0741 return;
0742
0743 for (i = 0; i <= 4; i++) {
0744 int iface;
0745 int p;
0746
0747 snprintf(name_buffer, sizeof(name_buffer), "interface@%d", i);
0748 iface = fdt_subnode_offset(initial_boot_params, pip,
0749 name_buffer);
0750 if (iface < 0)
0751 continue;
0752 for (p = 0; p < 16; p++) {
0753 int eth;
0754
0755 snprintf(name_buffer, sizeof(name_buffer),
0756 "ethernet@%x", p);
0757 eth = fdt_subnode_offset(initial_boot_params, iface,
0758 name_buffer);
0759 if (eth < 0)
0760 continue;
0761 octeon_fdt_set_mac_addr(eth, &mac_addr_base);
0762 }
0763 }
0764 }
0765
0766 int __init octeon_prune_device_tree(void)
0767 {
0768 int i, max_port, uart_mask;
0769 const char *pip_path;
0770 const char *alias_prop;
0771 char name_buffer[20];
0772 int aliases;
0773
0774 if (fdt_check_header(initial_boot_params))
0775 panic("Corrupt Device Tree.");
0776
0777 WARN(octeon_bootinfo->board_type == CVMX_BOARD_TYPE_CUST_DSR1000N,
0778 "Built-in DTB booting is deprecated on %s. Please switch to use appended DTB.",
0779 cvmx_board_type_to_string(octeon_bootinfo->board_type));
0780
0781 aliases = fdt_path_offset(initial_boot_params, "/aliases");
0782 if (aliases < 0) {
0783 pr_err("Error: No /aliases node in device tree.");
0784 return -EINVAL;
0785 }
0786
0787 if (OCTEON_IS_MODEL(OCTEON_CN52XX) || OCTEON_IS_MODEL(OCTEON_CN63XX))
0788 max_port = 2;
0789 else if (OCTEON_IS_MODEL(OCTEON_CN56XX) || OCTEON_IS_MODEL(OCTEON_CN68XX))
0790 max_port = 1;
0791 else
0792 max_port = 0;
0793
0794 if (octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC10E)
0795 max_port = 0;
0796
0797 for (i = 0; i < 2; i++) {
0798 int mgmt;
0799
0800 snprintf(name_buffer, sizeof(name_buffer),
0801 "mix%d", i);
0802 alias_prop = fdt_getprop(initial_boot_params, aliases,
0803 name_buffer, NULL);
0804 if (alias_prop) {
0805 mgmt = fdt_path_offset(initial_boot_params, alias_prop);
0806 if (mgmt < 0)
0807 continue;
0808 if (i >= max_port) {
0809 pr_debug("Deleting mix%d\n", i);
0810 octeon_fdt_rm_ethernet(mgmt);
0811 fdt_nop_property(initial_boot_params, aliases,
0812 name_buffer);
0813 } else {
0814 int phy_addr = cvmx_helper_board_get_mii_address(CVMX_HELPER_BOARD_MGMT_IPD_PORT + i);
0815
0816 octeon_fdt_set_phy(mgmt, phy_addr);
0817 }
0818 }
0819 }
0820
0821 pip_path = fdt_getprop(initial_boot_params, aliases, "pip", NULL);
0822 if (pip_path) {
0823 int pip = fdt_path_offset(initial_boot_params, pip_path);
0824
0825 if (pip >= 0)
0826 for (i = 0; i <= 4; i++)
0827 octeon_fdt_pip_iface(pip, i);
0828 }
0829
0830
0831 if (OCTEON_IS_MODEL(OCTEON_CN52XX) ||
0832 OCTEON_IS_MODEL(OCTEON_CN63XX) ||
0833 OCTEON_IS_MODEL(OCTEON_CN68XX) ||
0834 OCTEON_IS_MODEL(OCTEON_CN56XX))
0835 max_port = 2;
0836 else
0837 max_port = 1;
0838
0839 for (i = 0; i < 2; i++) {
0840 int i2c;
0841
0842 snprintf(name_buffer, sizeof(name_buffer),
0843 "twsi%d", i);
0844 alias_prop = fdt_getprop(initial_boot_params, aliases,
0845 name_buffer, NULL);
0846
0847 if (alias_prop) {
0848 i2c = fdt_path_offset(initial_boot_params, alias_prop);
0849 if (i2c < 0)
0850 continue;
0851 if (i >= max_port) {
0852 pr_debug("Deleting twsi%d\n", i);
0853 fdt_nop_node(initial_boot_params, i2c);
0854 fdt_nop_property(initial_boot_params, aliases,
0855 name_buffer);
0856 }
0857 }
0858 }
0859
0860
0861 if (OCTEON_IS_MODEL(OCTEON_CN68XX))
0862 max_port = 4;
0863 else if (OCTEON_IS_MODEL(OCTEON_CN52XX) ||
0864 OCTEON_IS_MODEL(OCTEON_CN63XX) ||
0865 OCTEON_IS_MODEL(OCTEON_CN56XX))
0866 max_port = 2;
0867 else
0868 max_port = 1;
0869
0870 for (i = 0; i < 2; i++) {
0871 int i2c;
0872
0873 snprintf(name_buffer, sizeof(name_buffer),
0874 "smi%d", i);
0875 alias_prop = fdt_getprop(initial_boot_params, aliases,
0876 name_buffer, NULL);
0877 if (alias_prop) {
0878 i2c = fdt_path_offset(initial_boot_params, alias_prop);
0879 if (i2c < 0)
0880 continue;
0881 if (i >= max_port) {
0882 pr_debug("Deleting smi%d\n", i);
0883 fdt_nop_node(initial_boot_params, i2c);
0884 fdt_nop_property(initial_boot_params, aliases,
0885 name_buffer);
0886 }
0887 }
0888 }
0889
0890
0891 uart_mask = 3;
0892
0893
0894 if (OCTEON_IS_MODEL(OCTEON_CN52XX))
0895 uart_mask |= 4;
0896
0897 for (i = 0; i < 3; i++) {
0898 int uart;
0899
0900 snprintf(name_buffer, sizeof(name_buffer),
0901 "uart%d", i);
0902 alias_prop = fdt_getprop(initial_boot_params, aliases,
0903 name_buffer, NULL);
0904
0905 if (alias_prop) {
0906 uart = fdt_path_offset(initial_boot_params, alias_prop);
0907 if (uart_mask & (1 << i)) {
0908 __be32 f;
0909
0910 f = cpu_to_be32(octeon_get_io_clock_rate());
0911 fdt_setprop_inplace(initial_boot_params,
0912 uart, "clock-frequency",
0913 &f, sizeof(f));
0914 continue;
0915 }
0916 pr_debug("Deleting uart%d\n", i);
0917 fdt_nop_node(initial_boot_params, uart);
0918 fdt_nop_property(initial_boot_params, aliases,
0919 name_buffer);
0920 }
0921 }
0922
0923
0924 alias_prop = fdt_getprop(initial_boot_params, aliases,
0925 "cf0", NULL);
0926 if (alias_prop) {
0927 union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg;
0928 unsigned long base_ptr, region_base, region_size;
0929 unsigned long region1_base = 0;
0930 unsigned long region1_size = 0;
0931 int cs, bootbus;
0932 bool is_16bit = false;
0933 bool is_true_ide = false;
0934 __be32 new_reg[6];
0935 __be32 *ranges;
0936 int len;
0937
0938 int cf = fdt_path_offset(initial_boot_params, alias_prop);
0939
0940 base_ptr = 0;
0941 if (octeon_bootinfo->major_version == 1
0942 && octeon_bootinfo->minor_version >= 1) {
0943 if (octeon_bootinfo->compact_flash_common_base_addr)
0944 base_ptr = octeon_bootinfo->compact_flash_common_base_addr;
0945 } else {
0946 base_ptr = 0x1d000800;
0947 }
0948
0949 if (!base_ptr)
0950 goto no_cf;
0951
0952
0953 for (cs = 0; cs < 8; cs++) {
0954 mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
0955 region_base = mio_boot_reg_cfg.s.base << 16;
0956 region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
0957 if (mio_boot_reg_cfg.s.en && base_ptr >= region_base
0958 && base_ptr < region_base + region_size) {
0959 is_16bit = mio_boot_reg_cfg.s.width;
0960 break;
0961 }
0962 }
0963 if (cs >= 7) {
0964
0965 goto no_cf;
0966 }
0967
0968 if (!(base_ptr & 0xfffful)) {
0969
0970
0971
0972
0973
0974
0975
0976 mio_boot_reg_cfg.u64 =
0977 cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs + 1));
0978 region1_base = mio_boot_reg_cfg.s.base << 16;
0979 region1_size = (mio_boot_reg_cfg.s.size + 1) << 16;
0980 if (!mio_boot_reg_cfg.s.en)
0981 goto no_cf;
0982 is_true_ide = true;
0983
0984 } else {
0985 fdt_nop_property(initial_boot_params, cf, "cavium,true-ide");
0986 fdt_nop_property(initial_boot_params, cf, "cavium,dma-engine-handle");
0987 if (!is_16bit) {
0988 __be32 width = cpu_to_be32(8);
0989
0990 fdt_setprop_inplace(initial_boot_params, cf,
0991 "cavium,bus-width", &width, sizeof(width));
0992 }
0993 }
0994 new_reg[0] = cpu_to_be32(cs);
0995 new_reg[1] = cpu_to_be32(0);
0996 new_reg[2] = cpu_to_be32(0x10000);
0997 new_reg[3] = cpu_to_be32(cs + 1);
0998 new_reg[4] = cpu_to_be32(0);
0999 new_reg[5] = cpu_to_be32(0x10000);
1000 fdt_setprop_inplace(initial_boot_params, cf,
1001 "reg", new_reg, sizeof(new_reg));
1002
1003 bootbus = fdt_parent_offset(initial_boot_params, cf);
1004 if (bootbus < 0)
1005 goto no_cf;
1006 ranges = fdt_getprop_w(initial_boot_params, bootbus, "ranges", &len);
1007 if (!ranges || len < (5 * 8 * sizeof(__be32)))
1008 goto no_cf;
1009
1010 ranges[(cs * 5) + 2] = cpu_to_be32(region_base >> 32);
1011 ranges[(cs * 5) + 3] = cpu_to_be32(region_base & 0xffffffff);
1012 ranges[(cs * 5) + 4] = cpu_to_be32(region_size);
1013 if (is_true_ide) {
1014 cs++;
1015 ranges[(cs * 5) + 2] = cpu_to_be32(region1_base >> 32);
1016 ranges[(cs * 5) + 3] = cpu_to_be32(region1_base & 0xffffffff);
1017 ranges[(cs * 5) + 4] = cpu_to_be32(region1_size);
1018 }
1019 goto end_cf;
1020 no_cf:
1021 fdt_nop_node(initial_boot_params, cf);
1022
1023 end_cf:
1024 ;
1025 }
1026
1027
1028 alias_prop = fdt_getprop(initial_boot_params, aliases,
1029 "led0", NULL);
1030 if (alias_prop) {
1031 union cvmx_mio_boot_reg_cfgx mio_boot_reg_cfg;
1032 unsigned long base_ptr, region_base, region_size;
1033 int cs, bootbus;
1034 __be32 new_reg[6];
1035 __be32 *ranges;
1036 int len;
1037 int led = fdt_path_offset(initial_boot_params, alias_prop);
1038
1039 base_ptr = octeon_bootinfo->led_display_base_addr;
1040 if (base_ptr == 0)
1041 goto no_led;
1042
1043 for (cs = 0; cs < 8; cs++) {
1044 mio_boot_reg_cfg.u64 = cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(cs));
1045 region_base = mio_boot_reg_cfg.s.base << 16;
1046 region_size = (mio_boot_reg_cfg.s.size + 1) << 16;
1047 if (mio_boot_reg_cfg.s.en && base_ptr >= region_base
1048 && base_ptr < region_base + region_size)
1049 break;
1050 }
1051
1052 if (cs > 7)
1053 goto no_led;
1054
1055 new_reg[0] = cpu_to_be32(cs);
1056 new_reg[1] = cpu_to_be32(0x20);
1057 new_reg[2] = cpu_to_be32(0x20);
1058 new_reg[3] = cpu_to_be32(cs);
1059 new_reg[4] = cpu_to_be32(0);
1060 new_reg[5] = cpu_to_be32(0x20);
1061 fdt_setprop_inplace(initial_boot_params, led,
1062 "reg", new_reg, sizeof(new_reg));
1063
1064 bootbus = fdt_parent_offset(initial_boot_params, led);
1065 if (bootbus < 0)
1066 goto no_led;
1067 ranges = fdt_getprop_w(initial_boot_params, bootbus, "ranges", &len);
1068 if (!ranges || len < (5 * 8 * sizeof(__be32)))
1069 goto no_led;
1070
1071 ranges[(cs * 5) + 2] = cpu_to_be32(region_base >> 32);
1072 ranges[(cs * 5) + 3] = cpu_to_be32(region_base & 0xffffffff);
1073 ranges[(cs * 5) + 4] = cpu_to_be32(region_size);
1074 goto end_led;
1075
1076 no_led:
1077 fdt_nop_node(initial_boot_params, led);
1078 end_led:
1079 ;
1080 }
1081
1082 #ifdef CONFIG_USB
1083
1084 alias_prop = fdt_getprop(initial_boot_params, aliases,
1085 "uctl", NULL);
1086 if (alias_prop) {
1087 int uctl = fdt_path_offset(initial_boot_params, alias_prop);
1088
1089 if (uctl >= 0 && (!OCTEON_IS_MODEL(OCTEON_CN6XXX) ||
1090 octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC2E)) {
1091 pr_debug("Deleting uctl\n");
1092 fdt_nop_node(initial_boot_params, uctl);
1093 fdt_nop_property(initial_boot_params, aliases, "uctl");
1094 } else if (octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC10E ||
1095 octeon_bootinfo->board_type == CVMX_BOARD_TYPE_NIC4E) {
1096
1097 fdt_nop_property(initial_boot_params, uctl, "refclk-type");
1098 }
1099 }
1100
1101
1102 alias_prop = fdt_getprop(initial_boot_params, aliases,
1103 "usbn", NULL);
1104 if (alias_prop) {
1105 int usbn = fdt_path_offset(initial_boot_params, alias_prop);
1106
1107 if (usbn >= 0 && (current_cpu_type() == CPU_CAVIUM_OCTEON2 ||
1108 !octeon_has_feature(OCTEON_FEATURE_USB))) {
1109 pr_debug("Deleting usbn\n");
1110 fdt_nop_node(initial_boot_params, usbn);
1111 fdt_nop_property(initial_boot_params, aliases, "usbn");
1112 } else {
1113 __be32 new_f[1];
1114 enum cvmx_helper_board_usb_clock_types c;
1115
1116 c = __cvmx_helper_board_usb_get_clock_type();
1117 switch (c) {
1118 case USB_CLOCK_TYPE_REF_48:
1119 new_f[0] = cpu_to_be32(48000000);
1120 fdt_setprop_inplace(initial_boot_params, usbn,
1121 "refclk-frequency", new_f, sizeof(new_f));
1122 fallthrough;
1123 case USB_CLOCK_TYPE_REF_12:
1124
1125 fdt_nop_property(initial_boot_params, usbn, "refclk-type");
1126 break;
1127 default:
1128 break;
1129 }
1130 }
1131 }
1132 #endif
1133
1134 return 0;
1135 }
1136
1137 static int __init octeon_publish_devices(void)
1138 {
1139 return of_platform_populate(NULL, octeon_ids, NULL, NULL);
1140 }
1141 arch_initcall(octeon_publish_devices);