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