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