uboot/board/gdsys/mpc8308/strider.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2014
   4 * Dirk Eibach,  Guntermann & Drunck GmbH, dirk.eibach@gdsys.cc
   5 */
   6
   7#include <common.h>
   8#include <hwconfig.h>
   9#include <i2c.h>
  10#include <spi.h>
  11#include <linux/libfdt.h>
  12#include <fdt_support.h>
  13#include <pci.h>
  14#include <mpc83xx.h>
  15#include <fsl_esdhc.h>
  16#include <asm/io.h>
  17#include <asm/fsl_serdes.h>
  18#include <asm/fsl_mpc83xx_serdes.h>
  19
  20#include "mpc8308.h"
  21
  22#include <gdsys_fpga.h>
  23
  24#include "../common/adv7611.h"
  25#include "../common/ch7301.h"
  26#include "../common/dp501.h"
  27#include "../common/ioep-fpga.h"
  28#include "../common/mclink.h"
  29#include "../common/osd.h"
  30#include "../common/phy.h"
  31#include "../common/fanctrl.h"
  32
  33#include <pca953x.h>
  34#include <pca9698.h>
  35
  36#include <miiphy.h>
  37
  38#define MAX_MUX_CHANNELS 2
  39
  40enum {
  41        MCFPGA_DONE = 1 << 0,
  42        MCFPGA_INIT_N = 1 << 1,
  43        MCFPGA_PROGRAM_N = 1 << 2,
  44        MCFPGA_UPDATE_ENABLE_N = 1 << 3,
  45        MCFPGA_RESET_N = 1 << 4,
  46};
  47
  48enum {
  49        GPIO_MDC = 1 << 14,
  50        GPIO_MDIO = 1 << 15,
  51};
  52
  53uint mclink_fpgacount;
  54struct ihs_fpga *fpga_ptr[] = CONFIG_SYS_FPGA_PTR;
  55
  56struct {
  57        u8 bus;
  58        u8 addr;
  59} strider_fans[] = CONFIG_STRIDER_FANS;
  60
  61int fpga_set_reg(u32 fpga, u16 *reg, off_t regoff, u16 data)
  62{
  63        int res;
  64
  65        switch (fpga) {
  66        case 0:
  67                out_le16(reg, data);
  68                break;
  69        default:
  70                res = mclink_send(fpga - 1, regoff, data);
  71                if (res < 0) {
  72                        printf("mclink_send reg %02lx data %04x returned %d\n",
  73                               regoff, data, res);
  74                        return res;
  75                }
  76                break;
  77        }
  78
  79        return 0;
  80}
  81
  82int fpga_get_reg(u32 fpga, u16 *reg, off_t regoff, u16 *data)
  83{
  84        int res;
  85
  86        switch (fpga) {
  87        case 0:
  88                *data = in_le16(reg);
  89                break;
  90        default:
  91                if (fpga > mclink_fpgacount)
  92                        return -EINVAL;
  93                res = mclink_receive(fpga - 1, regoff, data);
  94                if (res < 0) {
  95                        printf("mclink_receive reg %02lx returned %d\n",
  96                               regoff, res);
  97                        return res;
  98                }
  99        }
 100
 101        return 0;
 102}
 103
 104int checkboard(void)
 105{
 106        char *s = env_get("serial#");
 107        bool hw_type_cat = pca9698_get_value(0x20, 18);
 108
 109        puts("Board: ");
 110
 111        printf("Strider %s", hw_type_cat ? "CAT" : "Fiber");
 112
 113        if (s) {
 114                puts(", serial# ");
 115                puts(s);
 116        }
 117
 118        puts("\n");
 119
 120        return 0;
 121}
 122
 123int last_stage_init(void)
 124{
 125        int slaves;
 126        uint k;
 127        uint mux_ch;
 128        uchar mclink_controllers_dvi[] = { 0x3c, 0x3d, 0x3e };
 129#ifdef CONFIG_STRIDER_CPU
 130        uchar mclink_controllers_dp[] = { 0x24, 0x25, 0x26 };
 131#endif
 132        bool hw_type_cat = pca9698_get_value(0x20, 18);
 133#ifdef CONFIG_STRIDER_CON_DP
 134        bool is_dh = pca9698_get_value(0x20, 25);
 135#endif
 136        bool ch0_sgmii2_present;
 137
 138        /* Turn on Analog Devices ADV7611 */
 139        pca9698_direction_output(0x20, 8, 0);
 140
 141        /* Turn on Parade DP501 */
 142        pca9698_direction_output(0x20, 10, 1);
 143        pca9698_direction_output(0x20, 11, 1);
 144
 145        ch0_sgmii2_present = !pca9698_get_value(0x20, 37);
 146
 147        /* wait for FPGA done, then reset FPGA */
 148        for (k = 0; k < ARRAY_SIZE(mclink_controllers_dvi); ++k) {
 149                uint ctr = 0;
 150                uchar *mclink_controllers = mclink_controllers_dvi;
 151
 152#ifdef CONFIG_STRIDER_CPU
 153                if (i2c_probe(mclink_controllers[k])) {
 154                        mclink_controllers = mclink_controllers_dp;
 155                        if (i2c_probe(mclink_controllers[k]))
 156                                continue;
 157                }
 158#else
 159                if (i2c_probe(mclink_controllers[k]))
 160                        continue;
 161#endif
 162                while (!(pca953x_get_val(mclink_controllers[k])
 163                       & MCFPGA_DONE)) {
 164                        mdelay(100);
 165                        if (ctr++ > 5) {
 166                                printf("no done for mclink_controller %d\n", k);
 167                                break;
 168                        }
 169                }
 170
 171                pca953x_set_dir(mclink_controllers[k], MCFPGA_RESET_N, 0);
 172                pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N, 0);
 173                udelay(10);
 174                pca953x_set_val(mclink_controllers[k], MCFPGA_RESET_N,
 175                                MCFPGA_RESET_N);
 176        }
 177
 178        if (hw_type_cat) {
 179                int retval;
 180                struct mii_dev *mdiodev = mdio_alloc();
 181
 182                if (!mdiodev)
 183                        return -ENOMEM;
 184                strncpy(mdiodev->name, bb_miiphy_buses[0].name, MDIO_NAME_LEN);
 185                mdiodev->read = bb_miiphy_read;
 186                mdiodev->write = bb_miiphy_write;
 187
 188                retval = mdio_register(mdiodev);
 189                if (retval < 0)
 190                        return retval;
 191                for (mux_ch = 0; mux_ch < MAX_MUX_CHANNELS; ++mux_ch) {
 192                        if ((mux_ch == 1) && !ch0_sgmii2_present)
 193                                continue;
 194
 195                        setup_88e1514(bb_miiphy_buses[0].name, mux_ch);
 196                }
 197        }
 198
 199        /* give slave-PLLs and Parade DP501 some time to be up and running */
 200        mdelay(500);
 201
 202        mclink_fpgacount = CONFIG_SYS_MCLINK_MAX;
 203        slaves = mclink_probe();
 204        mclink_fpgacount = 0;
 205
 206        ioep_fpga_print_info(0);
 207
 208        if (!adv7611_probe(0))
 209                printf("       Advantiv ADV7611 HDMI Receiver\n");
 210
 211#ifdef CONFIG_STRIDER_CON
 212        if (ioep_fpga_has_osd(0))
 213                osd_probe(0);
 214#endif
 215
 216#ifdef CONFIG_STRIDER_CON_DP
 217        if (ioep_fpga_has_osd(0)) {
 218                osd_probe(0);
 219                if (is_dh)
 220                        osd_probe(4);
 221        }
 222#endif
 223
 224#ifdef CONFIG_STRIDER_CPU
 225        ch7301_probe(0, false);
 226        dp501_probe(0, false);
 227#endif
 228
 229        if (slaves <= 0)
 230                return 0;
 231
 232        mclink_fpgacount = slaves;
 233
 234#ifdef CONFIG_STRIDER_CPU
 235        /* get ADV7611 out of reset, power up DP501, give some time to wakeup */
 236        for (k = 1; k <= slaves; ++k)
 237                FPGA_SET_REG(k, extended_control, 0x10); /* enable video */
 238
 239        mdelay(500);
 240#endif
 241
 242        for (k = 1; k <= slaves; ++k) {
 243                ioep_fpga_print_info(k);
 244#ifdef CONFIG_STRIDER_CON
 245                if (ioep_fpga_has_osd(k))
 246                        osd_probe(k);
 247#endif
 248#ifdef CONFIG_STRIDER_CON_DP
 249                if (ioep_fpga_has_osd(k)) {
 250                        osd_probe(k);
 251                        if (is_dh)
 252                                osd_probe(k + 4);
 253                }
 254#endif
 255#ifdef CONFIG_STRIDER_CPU
 256                if (!adv7611_probe(k))
 257                        printf("       Advantiv ADV7611 HDMI Receiver\n");
 258                ch7301_probe(k, false);
 259                dp501_probe(k, false);
 260#endif
 261                if (hw_type_cat) {
 262                        int retval;
 263                        struct mii_dev *mdiodev = mdio_alloc();
 264
 265                        if (!mdiodev)
 266                                return -ENOMEM;
 267                        strncpy(mdiodev->name, bb_miiphy_buses[k].name,
 268                                MDIO_NAME_LEN);
 269                        mdiodev->read = bb_miiphy_read;
 270                        mdiodev->write = bb_miiphy_write;
 271
 272                        retval = mdio_register(mdiodev);
 273                        if (retval < 0)
 274                                return retval;
 275                        setup_88e1514(bb_miiphy_buses[k].name, 0);
 276                }
 277        }
 278
 279        for (k = 0; k < ARRAY_SIZE(strider_fans); ++k) {
 280                i2c_set_bus_num(strider_fans[k].bus);
 281                init_fan_controller(strider_fans[k].addr);
 282        }
 283
 284        return 0;
 285}
 286
 287/*
 288 * provide access to fpga gpios (for I2C bitbang)
 289 * (these may look all too simple but make iocon.h much more readable)
 290 */
 291void fpga_gpio_set(uint bus, int pin)
 292{
 293        FPGA_SET_REG(bus, gpio.set, pin);
 294}
 295
 296void fpga_gpio_clear(uint bus, int pin)
 297{
 298        FPGA_SET_REG(bus, gpio.clear, pin);
 299}
 300
 301int fpga_gpio_get(uint bus, int pin)
 302{
 303        u16 val;
 304
 305        FPGA_GET_REG(bus, gpio.read, &val);
 306
 307        return val & pin;
 308}
 309
 310#ifdef CONFIG_STRIDER_CON_DP
 311void fpga_control_set(uint bus, int pin)
 312{
 313        u16 val;
 314
 315        FPGA_GET_REG(bus, control, &val);
 316        FPGA_SET_REG(bus, control, val | pin);
 317}
 318
 319void fpga_control_clear(uint bus, int pin)
 320{
 321        u16 val;
 322
 323        FPGA_GET_REG(bus, control, &val);
 324        FPGA_SET_REG(bus, control, val & ~pin);
 325}
 326#endif
 327
 328void mpc8308_init(void)
 329{
 330        pca9698_direction_output(0x20, 26, 1);
 331}
 332
 333void mpc8308_set_fpga_reset(uint state)
 334{
 335        pca9698_set_value(0x20, 26, state ? 0 : 1);
 336}
 337
 338void mpc8308_setup_hw(void)
 339{
 340        immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
 341
 342        /*
 343         * set "startup-finished"-gpios
 344         */
 345        setbits_be32(&immr->gpio[0].dir, BIT(31 - 11) | BIT(31 - 12));
 346        setbits_gpio0_out(BIT(31 - 12));
 347}
 348
 349int mpc8308_get_fpga_done(uint fpga)
 350{
 351        return pca9698_get_value(0x20, 20);
 352}
 353
 354#ifdef CONFIG_FSL_ESDHC
 355int board_mmc_init(bd_t *bd)
 356{
 357        immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
 358        sysconf83xx_t *sysconf = &immr->sysconf;
 359
 360        /* Enable cache snooping in eSDHC system configuration register */
 361        out_be32(&sysconf->sdhccr, 0x02000000);
 362
 363        return fsl_esdhc_mmc_init(bd);
 364}
 365#endif
 366
 367static struct pci_region pcie_regions_0[] = {
 368        {
 369                .bus_start = CONFIG_SYS_PCIE1_MEM_BASE,
 370                .phys_start = CONFIG_SYS_PCIE1_MEM_PHYS,
 371                .size = CONFIG_SYS_PCIE1_MEM_SIZE,
 372                .flags = PCI_REGION_MEM,
 373        },
 374        {
 375                .bus_start = CONFIG_SYS_PCIE1_IO_BASE,
 376                .phys_start = CONFIG_SYS_PCIE1_IO_PHYS,
 377                .size = CONFIG_SYS_PCIE1_IO_SIZE,
 378                .flags = PCI_REGION_IO,
 379        },
 380};
 381
 382void pci_init_board(void)
 383{
 384        immap_t *immr = (immap_t *)CONFIG_SYS_IMMR;
 385        sysconf83xx_t *sysconf = &immr->sysconf;
 386        law83xx_t *pcie_law = sysconf->pcielaw;
 387        struct pci_region *pcie_reg[] = { pcie_regions_0 };
 388
 389        fsl_setup_serdes(CONFIG_FSL_SERDES1, FSL_SERDES_PROTO_PEX,
 390                         FSL_SERDES_CLK_100, FSL_SERDES_VDD_1V);
 391
 392        /* Deassert the resets in the control register */
 393        out_be32(&sysconf->pecr1, 0xE0008000);
 394        udelay(2000);
 395
 396        /* Configure PCI Express Local Access Windows */
 397        out_be32(&pcie_law[0].bar, CONFIG_SYS_PCIE1_BASE & LAWBAR_BAR);
 398        out_be32(&pcie_law[0].ar, LBLAWAR_EN | LBLAWAR_512MB);
 399
 400        mpc83xx_pcie_init(1, pcie_reg);
 401}
 402
 403ulong board_flash_get_legacy(ulong base, int banknum, flash_info_t *info)
 404{
 405        info->portwidth = FLASH_CFI_16BIT;
 406        info->chipwidth = FLASH_CFI_BY16;
 407        info->interface = FLASH_CFI_X16;
 408        return 1;
 409}
 410
 411#if defined(CONFIG_OF_BOARD_SETUP)
 412int ft_board_setup(void *blob, bd_t *bd)
 413{
 414        ft_cpu_setup(blob, bd);
 415        fsl_fdt_fixup_dr_usb(blob, bd);
 416        fdt_fixup_esdhc(blob, bd);
 417
 418        return 0;
 419}
 420#endif
 421
 422/*
 423 * FPGA MII bitbang implementation
 424 */
 425
 426struct fpga_mii {
 427        uint fpga;
 428        int mdio;
 429} fpga_mii[] = {
 430        { 0, 1},
 431        { 1, 1},
 432        { 2, 1},
 433        { 3, 1},
 434};
 435
 436static int mii_dummy_init(struct bb_miiphy_bus *bus)
 437{
 438        return 0;
 439}
 440
 441static int mii_mdio_active(struct bb_miiphy_bus *bus)
 442{
 443        struct fpga_mii *fpga_mii = bus->priv;
 444
 445        if (fpga_mii->mdio)
 446                FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
 447        else
 448                FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
 449
 450        return 0;
 451}
 452
 453static int mii_mdio_tristate(struct bb_miiphy_bus *bus)
 454{
 455        struct fpga_mii *fpga_mii = bus->priv;
 456
 457        FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
 458
 459        return 0;
 460}
 461
 462static int mii_set_mdio(struct bb_miiphy_bus *bus, int v)
 463{
 464        struct fpga_mii *fpga_mii = bus->priv;
 465
 466        if (v)
 467                FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDIO);
 468        else
 469                FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDIO);
 470
 471        fpga_mii->mdio = v;
 472
 473        return 0;
 474}
 475
 476static int mii_get_mdio(struct bb_miiphy_bus *bus, int *v)
 477{
 478        u16 gpio;
 479        struct fpga_mii *fpga_mii = bus->priv;
 480
 481        FPGA_GET_REG(fpga_mii->fpga, gpio.read, &gpio);
 482
 483        *v = ((gpio & GPIO_MDIO) != 0);
 484
 485        return 0;
 486}
 487
 488static int mii_set_mdc(struct bb_miiphy_bus *bus, int v)
 489{
 490        struct fpga_mii *fpga_mii = bus->priv;
 491
 492        if (v)
 493                FPGA_SET_REG(fpga_mii->fpga, gpio.set, GPIO_MDC);
 494        else
 495                FPGA_SET_REG(fpga_mii->fpga, gpio.clear, GPIO_MDC);
 496
 497        return 0;
 498}
 499
 500static int mii_delay(struct bb_miiphy_bus *bus)
 501{
 502        udelay(1);
 503
 504        return 0;
 505}
 506
 507struct bb_miiphy_bus bb_miiphy_buses[] = {
 508        {
 509                .name = "board0",
 510                .init = mii_dummy_init,
 511                .mdio_active = mii_mdio_active,
 512                .mdio_tristate = mii_mdio_tristate,
 513                .set_mdio = mii_set_mdio,
 514                .get_mdio = mii_get_mdio,
 515                .set_mdc = mii_set_mdc,
 516                .delay = mii_delay,
 517                .priv = &fpga_mii[0],
 518        },
 519        {
 520                .name = "board1",
 521                .init = mii_dummy_init,
 522                .mdio_active = mii_mdio_active,
 523                .mdio_tristate = mii_mdio_tristate,
 524                .set_mdio = mii_set_mdio,
 525                .get_mdio = mii_get_mdio,
 526                .set_mdc = mii_set_mdc,
 527                .delay = mii_delay,
 528                .priv = &fpga_mii[1],
 529        },
 530        {
 531                .name = "board2",
 532                .init = mii_dummy_init,
 533                .mdio_active = mii_mdio_active,
 534                .mdio_tristate = mii_mdio_tristate,
 535                .set_mdio = mii_set_mdio,
 536                .get_mdio = mii_get_mdio,
 537                .set_mdc = mii_set_mdc,
 538                .delay = mii_delay,
 539                .priv = &fpga_mii[2],
 540        },
 541        {
 542                .name = "board3",
 543                .init = mii_dummy_init,
 544                .mdio_active = mii_mdio_active,
 545                .mdio_tristate = mii_mdio_tristate,
 546                .set_mdio = mii_set_mdio,
 547                .get_mdio = mii_get_mdio,
 548                .set_mdc = mii_set_mdc,
 549                .delay = mii_delay,
 550                .priv = &fpga_mii[3],
 551        },
 552};
 553
 554int bb_miiphy_buses_num = ARRAY_SIZE(bb_miiphy_buses);
 555