linux/arch/arm/mach-mxs/mach-mxs.c
<<
>>
Prefs
   1/*
   2 * Copyright 2012 Freescale Semiconductor, Inc.
   3 * Copyright 2012 Linaro Ltd.
   4 *
   5 * The code contained herein is licensed under the GNU General Public
   6 * License. You may obtain a copy of the GNU General Public License
   7 * Version 2 or later at the following locations:
   8 *
   9 * http://www.opensource.org/licenses/gpl-license.html
  10 * http://www.gnu.org/copyleft/gpl.html
  11 */
  12
  13#include <linux/clk.h>
  14#include <linux/clk/mxs.h>
  15#include <linux/clkdev.h>
  16#include <linux/delay.h>
  17#include <linux/err.h>
  18#include <linux/gpio.h>
  19#include <linux/init.h>
  20#include <linux/irqchip/mxs.h>
  21#include <linux/reboot.h>
  22#include <linux/micrel_phy.h>
  23#include <linux/of_address.h>
  24#include <linux/of_platform.h>
  25#include <linux/phy.h>
  26#include <linux/pinctrl/consumer.h>
  27#include <linux/sys_soc.h>
  28#include <asm/mach/arch.h>
  29#include <asm/mach/map.h>
  30#include <asm/mach/time.h>
  31#include <asm/system_misc.h>
  32
  33#include "pm.h"
  34
  35/* MXS DIGCTL SAIF CLKMUX */
  36#define MXS_DIGCTL_SAIF_CLKMUX_DIRECT           0x0
  37#define MXS_DIGCTL_SAIF_CLKMUX_CROSSINPUT       0x1
  38#define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0         0x2
  39#define MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR1         0x3
  40
  41#define HW_DIGCTL_CHIPID        0x310
  42#define HW_DIGCTL_CHIPID_MASK   (0xffff << 16)
  43#define HW_DIGCTL_REV_MASK      0xff
  44#define HW_DIGCTL_CHIPID_MX23   (0x3780 << 16)
  45#define HW_DIGCTL_CHIPID_MX28   (0x2800 << 16)
  46
  47#define MXS_CHIP_REVISION_1_0   0x10
  48#define MXS_CHIP_REVISION_1_1   0x11
  49#define MXS_CHIP_REVISION_1_2   0x12
  50#define MXS_CHIP_REVISION_1_3   0x13
  51#define MXS_CHIP_REVISION_1_4   0x14
  52#define MXS_CHIP_REV_UNKNOWN    0xff
  53
  54#define MXS_GPIO_NR(bank, nr)   ((bank) * 32 + (nr))
  55
  56#define MXS_SET_ADDR            0x4
  57#define MXS_CLR_ADDR            0x8
  58#define MXS_TOG_ADDR            0xc
  59
  60static u32 chipid;
  61static u32 socid;
  62
  63static void __iomem *reset_addr;
  64
  65static inline void __mxs_setl(u32 mask, void __iomem *reg)
  66{
  67        __raw_writel(mask, reg + MXS_SET_ADDR);
  68}
  69
  70static inline void __mxs_clrl(u32 mask, void __iomem *reg)
  71{
  72        __raw_writel(mask, reg + MXS_CLR_ADDR);
  73}
  74
  75static inline void __mxs_togl(u32 mask, void __iomem *reg)
  76{
  77        __raw_writel(mask, reg + MXS_TOG_ADDR);
  78}
  79
  80#define OCOTP_WORD_OFFSET               0x20
  81#define OCOTP_WORD_COUNT                0x20
  82
  83#define BM_OCOTP_CTRL_BUSY              (1 << 8)
  84#define BM_OCOTP_CTRL_ERROR             (1 << 9)
  85#define BM_OCOTP_CTRL_RD_BANK_OPEN      (1 << 12)
  86
  87static DEFINE_MUTEX(ocotp_mutex);
  88static u32 ocotp_words[OCOTP_WORD_COUNT];
  89
  90static const u32 *mxs_get_ocotp(void)
  91{
  92        struct device_node *np;
  93        void __iomem *ocotp_base;
  94        int timeout = 0x400;
  95        size_t i;
  96        static int once;
  97
  98        if (once)
  99                return ocotp_words;
 100
 101        np = of_find_compatible_node(NULL, NULL, "fsl,ocotp");
 102        ocotp_base = of_iomap(np, 0);
 103        WARN_ON(!ocotp_base);
 104
 105        mutex_lock(&ocotp_mutex);
 106
 107        /*
 108         * clk_enable(hbus_clk) for ocotp can be skipped
 109         * as it must be on when system is running.
 110         */
 111
 112        /* try to clear ERROR bit */
 113        __mxs_clrl(BM_OCOTP_CTRL_ERROR, ocotp_base);
 114
 115        /* check both BUSY and ERROR cleared */
 116        while ((__raw_readl(ocotp_base) &
 117                (BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR)) && --timeout)
 118                cpu_relax();
 119
 120        if (unlikely(!timeout))
 121                goto error_unlock;
 122
 123        /* open OCOTP banks for read */
 124        __mxs_setl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
 125
 126        /* approximately wait 32 hclk cycles */
 127        udelay(1);
 128
 129        /* poll BUSY bit becoming cleared */
 130        timeout = 0x400;
 131        while ((__raw_readl(ocotp_base) & BM_OCOTP_CTRL_BUSY) && --timeout)
 132                cpu_relax();
 133
 134        if (unlikely(!timeout))
 135                goto error_unlock;
 136
 137        for (i = 0; i < OCOTP_WORD_COUNT; i++)
 138                ocotp_words[i] = __raw_readl(ocotp_base + OCOTP_WORD_OFFSET +
 139                                                i * 0x10);
 140
 141        /* close banks for power saving */
 142        __mxs_clrl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
 143
 144        once = 1;
 145
 146        mutex_unlock(&ocotp_mutex);
 147
 148        return ocotp_words;
 149
 150error_unlock:
 151        mutex_unlock(&ocotp_mutex);
 152        pr_err("%s: timeout in reading OCOTP\n", __func__);
 153        return NULL;
 154}
 155
 156enum mac_oui {
 157        OUI_FSL,
 158        OUI_DENX,
 159        OUI_CRYSTALFONTZ,
 160        OUI_I2SE,
 161        OUI_ARMADEUS,
 162};
 163
 164static void __init update_fec_mac_prop(enum mac_oui oui)
 165{
 166        struct device_node *np, *from = NULL;
 167        struct property *newmac;
 168        const u32 *ocotp = mxs_get_ocotp();
 169        u8 *macaddr;
 170        u32 val;
 171        int i;
 172
 173        for (i = 0; i < 2; i++) {
 174                np = of_find_compatible_node(from, NULL, "fsl,imx28-fec");
 175                if (!np)
 176                        return;
 177
 178                from = np;
 179
 180                if (of_get_property(np, "local-mac-address", NULL))
 181                        continue;
 182
 183                newmac = kzalloc(sizeof(*newmac) + 6, GFP_KERNEL);
 184                if (!newmac)
 185                        return;
 186                newmac->value = newmac + 1;
 187                newmac->length = 6;
 188
 189                newmac->name = kstrdup("local-mac-address", GFP_KERNEL);
 190                if (!newmac->name) {
 191                        kfree(newmac);
 192                        return;
 193                }
 194
 195                /*
 196                 * OCOTP only stores the last 4 octets for each mac address,
 197                 * so hard-code OUI here.
 198                 */
 199                macaddr = newmac->value;
 200                switch (oui) {
 201                case OUI_FSL:
 202                        macaddr[0] = 0x00;
 203                        macaddr[1] = 0x04;
 204                        macaddr[2] = 0x9f;
 205                        break;
 206                case OUI_DENX:
 207                        macaddr[0] = 0xc0;
 208                        macaddr[1] = 0xe5;
 209                        macaddr[2] = 0x4e;
 210                        break;
 211                case OUI_CRYSTALFONTZ:
 212                        macaddr[0] = 0x58;
 213                        macaddr[1] = 0xb9;
 214                        macaddr[2] = 0xe1;
 215                        break;
 216                case OUI_I2SE:
 217                        macaddr[0] = 0x00;
 218                        macaddr[1] = 0x01;
 219                        macaddr[2] = 0x87;
 220                        break;
 221                case OUI_ARMADEUS:
 222                        macaddr[0] = 0x00;
 223                        macaddr[1] = 0x1e;
 224                        macaddr[2] = 0xac;
 225                        break;
 226                }
 227                val = ocotp[i];
 228                macaddr[3] = (val >> 16) & 0xff;
 229                macaddr[4] = (val >> 8) & 0xff;
 230                macaddr[5] = (val >> 0) & 0xff;
 231
 232                of_update_property(np, newmac);
 233        }
 234}
 235
 236static inline void enable_clk_enet_out(void)
 237{
 238        struct clk *clk = clk_get_sys("enet_out", NULL);
 239
 240        if (!IS_ERR(clk))
 241                clk_prepare_enable(clk);
 242}
 243
 244static void __init imx28_evk_init(void)
 245{
 246        update_fec_mac_prop(OUI_FSL);
 247
 248        mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0);
 249}
 250
 251static void __init imx28_apf28_init(void)
 252{
 253        update_fec_mac_prop(OUI_ARMADEUS);
 254}
 255
 256static int apx4devkit_phy_fixup(struct phy_device *phy)
 257{
 258        phy->dev_flags |= MICREL_PHY_50MHZ_CLK;
 259        return 0;
 260}
 261
 262static void __init apx4devkit_init(void)
 263{
 264        enable_clk_enet_out();
 265
 266        if (IS_BUILTIN(CONFIG_PHYLIB))
 267                phy_register_fixup_for_uid(PHY_ID_KSZ8051, MICREL_PHY_ID_MASK,
 268                                           apx4devkit_phy_fixup);
 269}
 270
 271#define ENET0_MDC__GPIO_4_0     MXS_GPIO_NR(4, 0)
 272#define ENET0_MDIO__GPIO_4_1    MXS_GPIO_NR(4, 1)
 273#define ENET0_RX_EN__GPIO_4_2   MXS_GPIO_NR(4, 2)
 274#define ENET0_RXD0__GPIO_4_3    MXS_GPIO_NR(4, 3)
 275#define ENET0_RXD1__GPIO_4_4    MXS_GPIO_NR(4, 4)
 276#define ENET0_TX_EN__GPIO_4_6   MXS_GPIO_NR(4, 6)
 277#define ENET0_TXD0__GPIO_4_7    MXS_GPIO_NR(4, 7)
 278#define ENET0_TXD1__GPIO_4_8    MXS_GPIO_NR(4, 8)
 279#define ENET_CLK__GPIO_4_16     MXS_GPIO_NR(4, 16)
 280
 281#define TX28_FEC_PHY_POWER      MXS_GPIO_NR(3, 29)
 282#define TX28_FEC_PHY_RESET      MXS_GPIO_NR(4, 13)
 283#define TX28_FEC_nINT           MXS_GPIO_NR(4, 5)
 284
 285static const struct gpio tx28_gpios[] __initconst = {
 286        { ENET0_MDC__GPIO_4_0, GPIOF_OUT_INIT_LOW, "GPIO_4_0" },
 287        { ENET0_MDIO__GPIO_4_1, GPIOF_OUT_INIT_LOW, "GPIO_4_1" },
 288        { ENET0_RX_EN__GPIO_4_2, GPIOF_OUT_INIT_LOW, "GPIO_4_2" },
 289        { ENET0_RXD0__GPIO_4_3, GPIOF_OUT_INIT_LOW, "GPIO_4_3" },
 290        { ENET0_RXD1__GPIO_4_4, GPIOF_OUT_INIT_LOW, "GPIO_4_4" },
 291        { ENET0_TX_EN__GPIO_4_6, GPIOF_OUT_INIT_LOW, "GPIO_4_6" },
 292        { ENET0_TXD0__GPIO_4_7, GPIOF_OUT_INIT_LOW, "GPIO_4_7" },
 293        { ENET0_TXD1__GPIO_4_8, GPIOF_OUT_INIT_LOW, "GPIO_4_8" },
 294        { ENET_CLK__GPIO_4_16, GPIOF_OUT_INIT_LOW, "GPIO_4_16" },
 295        { TX28_FEC_PHY_POWER, GPIOF_OUT_INIT_LOW, "fec-phy-power" },
 296        { TX28_FEC_PHY_RESET, GPIOF_OUT_INIT_LOW, "fec-phy-reset" },
 297        { TX28_FEC_nINT, GPIOF_DIR_IN, "fec-int" },
 298};
 299
 300static void __init tx28_post_init(void)
 301{
 302        struct device_node *np;
 303        struct platform_device *pdev;
 304        struct pinctrl *pctl;
 305        int ret;
 306
 307        enable_clk_enet_out();
 308
 309        np = of_find_compatible_node(NULL, NULL, "fsl,imx28-fec");
 310        pdev = of_find_device_by_node(np);
 311        if (!pdev) {
 312                pr_err("%s: failed to find fec device\n", __func__);
 313                return;
 314        }
 315
 316        pctl = pinctrl_get_select(&pdev->dev, "gpio_mode");
 317        if (IS_ERR(pctl)) {
 318                pr_err("%s: failed to get pinctrl state\n", __func__);
 319                return;
 320        }
 321
 322        ret = gpio_request_array(tx28_gpios, ARRAY_SIZE(tx28_gpios));
 323        if (ret) {
 324                pr_err("%s: failed to request gpios: %d\n", __func__, ret);
 325                return;
 326        }
 327
 328        /* Power up fec phy */
 329        gpio_set_value(TX28_FEC_PHY_POWER, 1);
 330        msleep(26); /* 25ms according to data sheet */
 331
 332        /* Mode strap pins */
 333        gpio_set_value(ENET0_RX_EN__GPIO_4_2, 1);
 334        gpio_set_value(ENET0_RXD0__GPIO_4_3, 1);
 335        gpio_set_value(ENET0_RXD1__GPIO_4_4, 1);
 336
 337        udelay(100); /* minimum assertion time for nRST */
 338
 339        /* Deasserting FEC PHY RESET */
 340        gpio_set_value(TX28_FEC_PHY_RESET, 1);
 341
 342        pinctrl_put(pctl);
 343}
 344
 345static void __init crystalfontz_init(void)
 346{
 347        update_fec_mac_prop(OUI_CRYSTALFONTZ);
 348}
 349
 350static void __init duckbill_init(void)
 351{
 352        update_fec_mac_prop(OUI_I2SE);
 353}
 354
 355static void __init m28cu3_init(void)
 356{
 357        update_fec_mac_prop(OUI_DENX);
 358}
 359
 360static const char __init *mxs_get_soc_id(void)
 361{
 362        struct device_node *np;
 363        void __iomem *digctl_base;
 364
 365        np = of_find_compatible_node(NULL, NULL, "fsl,imx23-digctl");
 366        digctl_base = of_iomap(np, 0);
 367        WARN_ON(!digctl_base);
 368
 369        chipid = readl(digctl_base + HW_DIGCTL_CHIPID);
 370        socid = chipid & HW_DIGCTL_CHIPID_MASK;
 371
 372        iounmap(digctl_base);
 373        of_node_put(np);
 374
 375        switch (socid) {
 376        case HW_DIGCTL_CHIPID_MX23:
 377                return "i.MX23";
 378        case HW_DIGCTL_CHIPID_MX28:
 379                return "i.MX28";
 380        default:
 381                return "Unknown";
 382        }
 383}
 384
 385static u32 __init mxs_get_cpu_rev(void)
 386{
 387        u32 rev = chipid & HW_DIGCTL_REV_MASK;
 388
 389        switch (socid) {
 390        case HW_DIGCTL_CHIPID_MX23:
 391                switch (rev) {
 392                case 0x0:
 393                        return MXS_CHIP_REVISION_1_0;
 394                case 0x1:
 395                        return MXS_CHIP_REVISION_1_1;
 396                case 0x2:
 397                        return MXS_CHIP_REVISION_1_2;
 398                case 0x3:
 399                        return MXS_CHIP_REVISION_1_3;
 400                case 0x4:
 401                        return MXS_CHIP_REVISION_1_4;
 402                default:
 403                        return MXS_CHIP_REV_UNKNOWN;
 404                }
 405        case HW_DIGCTL_CHIPID_MX28:
 406                switch (rev) {
 407                case 0x0:
 408                        return MXS_CHIP_REVISION_1_1;
 409                case 0x1:
 410                        return MXS_CHIP_REVISION_1_2;
 411                default:
 412                        return MXS_CHIP_REV_UNKNOWN;
 413                }
 414        default:
 415                return MXS_CHIP_REV_UNKNOWN;
 416        }
 417}
 418
 419static const char __init *mxs_get_revision(void)
 420{
 421        u32 rev = mxs_get_cpu_rev();
 422
 423        if (rev != MXS_CHIP_REV_UNKNOWN)
 424                return kasprintf(GFP_KERNEL, "%d.%d", (rev >> 4) & 0xf,
 425                                rev & 0xf);
 426        else
 427                return kasprintf(GFP_KERNEL, "%s", "Unknown");
 428}
 429
 430#define MX23_CLKCTRL_RESET_OFFSET       0x120
 431#define MX28_CLKCTRL_RESET_OFFSET       0x1e0
 432
 433static int __init mxs_restart_init(void)
 434{
 435        struct device_node *np;
 436
 437        np = of_find_compatible_node(NULL, NULL, "fsl,clkctrl");
 438        reset_addr = of_iomap(np, 0);
 439        if (!reset_addr)
 440                return -ENODEV;
 441
 442        if (of_device_is_compatible(np, "fsl,imx23-clkctrl"))
 443                reset_addr += MX23_CLKCTRL_RESET_OFFSET;
 444        else
 445                reset_addr += MX28_CLKCTRL_RESET_OFFSET;
 446        of_node_put(np);
 447
 448        return 0;
 449}
 450
 451static void __init eukrea_mbmx283lc_init(void)
 452{
 453        mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0);
 454}
 455
 456static void __init mxs_machine_init(void)
 457{
 458        struct device_node *root;
 459        struct device *parent;
 460        struct soc_device *soc_dev;
 461        struct soc_device_attribute *soc_dev_attr;
 462        int ret;
 463
 464        soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
 465        if (!soc_dev_attr)
 466                return;
 467
 468        root = of_find_node_by_path("/");
 469        ret = of_property_read_string(root, "model", &soc_dev_attr->machine);
 470        if (ret)
 471                return;
 472
 473        soc_dev_attr->family = "Freescale MXS Family";
 474        soc_dev_attr->soc_id = mxs_get_soc_id();
 475        soc_dev_attr->revision = mxs_get_revision();
 476
 477        soc_dev = soc_device_register(soc_dev_attr);
 478        if (IS_ERR(soc_dev)) {
 479                kfree(soc_dev_attr->revision);
 480                kfree(soc_dev_attr);
 481                return;
 482        }
 483
 484        parent = soc_device_to_device(soc_dev);
 485
 486        if (of_machine_is_compatible("fsl,imx28-evk"))
 487                imx28_evk_init();
 488        if (of_machine_is_compatible("armadeus,imx28-apf28"))
 489                imx28_apf28_init();
 490        else if (of_machine_is_compatible("bluegiga,apx4devkit"))
 491                apx4devkit_init();
 492        else if (of_machine_is_compatible("crystalfontz,cfa10036"))
 493                crystalfontz_init();
 494        else if (of_machine_is_compatible("eukrea,mbmx283lc"))
 495                eukrea_mbmx283lc_init();
 496        else if (of_machine_is_compatible("i2se,duckbill"))
 497                duckbill_init();
 498        else if (of_machine_is_compatible("msr,m28cu3"))
 499                m28cu3_init();
 500
 501        of_platform_populate(NULL, of_default_bus_match_table,
 502                             NULL, parent);
 503
 504        mxs_restart_init();
 505
 506        if (of_machine_is_compatible("karo,tx28"))
 507                tx28_post_init();
 508}
 509
 510#define MXS_CLKCTRL_RESET_CHIP          (1 << 1)
 511
 512/*
 513 * Reset the system. It is called by machine_restart().
 514 */
 515static void mxs_restart(enum reboot_mode mode, const char *cmd)
 516{
 517        if (reset_addr) {
 518                /* reset the chip */
 519                __mxs_setl(MXS_CLKCTRL_RESET_CHIP, reset_addr);
 520
 521                pr_err("Failed to assert the chip reset\n");
 522
 523                /* Delay to allow the serial port to show the message */
 524                mdelay(50);
 525        }
 526
 527        /* We'll take a jump through zero as a poor second */
 528        soft_restart(0);
 529}
 530
 531static const char *mxs_dt_compat[] __initdata = {
 532        "fsl,imx28",
 533        "fsl,imx23",
 534        NULL,
 535};
 536
 537DT_MACHINE_START(MXS, "Freescale MXS (Device Tree)")
 538        .handle_irq     = icoll_handle_irq,
 539        .init_machine   = mxs_machine_init,
 540        .init_late      = mxs_pm_init,
 541        .dt_compat      = mxs_dt_compat,
 542        .restart        = mxs_restart,
 543MACHINE_END
 544