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
 271static void __init crystalfontz_init(void)
 272{
 273        update_fec_mac_prop(OUI_CRYSTALFONTZ);
 274}
 275
 276static void __init duckbill_init(void)
 277{
 278        update_fec_mac_prop(OUI_I2SE);
 279}
 280
 281static void __init m28cu3_init(void)
 282{
 283        update_fec_mac_prop(OUI_DENX);
 284}
 285
 286static const char __init *mxs_get_soc_id(void)
 287{
 288        struct device_node *np;
 289        void __iomem *digctl_base;
 290
 291        np = of_find_compatible_node(NULL, NULL, "fsl,imx23-digctl");
 292        digctl_base = of_iomap(np, 0);
 293        WARN_ON(!digctl_base);
 294
 295        chipid = readl(digctl_base + HW_DIGCTL_CHIPID);
 296        socid = chipid & HW_DIGCTL_CHIPID_MASK;
 297
 298        iounmap(digctl_base);
 299        of_node_put(np);
 300
 301        switch (socid) {
 302        case HW_DIGCTL_CHIPID_MX23:
 303                return "i.MX23";
 304        case HW_DIGCTL_CHIPID_MX28:
 305                return "i.MX28";
 306        default:
 307                return "Unknown";
 308        }
 309}
 310
 311static u32 __init mxs_get_cpu_rev(void)
 312{
 313        u32 rev = chipid & HW_DIGCTL_REV_MASK;
 314
 315        switch (socid) {
 316        case HW_DIGCTL_CHIPID_MX23:
 317                switch (rev) {
 318                case 0x0:
 319                        return MXS_CHIP_REVISION_1_0;
 320                case 0x1:
 321                        return MXS_CHIP_REVISION_1_1;
 322                case 0x2:
 323                        return MXS_CHIP_REVISION_1_2;
 324                case 0x3:
 325                        return MXS_CHIP_REVISION_1_3;
 326                case 0x4:
 327                        return MXS_CHIP_REVISION_1_4;
 328                default:
 329                        return MXS_CHIP_REV_UNKNOWN;
 330                }
 331        case HW_DIGCTL_CHIPID_MX28:
 332                switch (rev) {
 333                case 0x0:
 334                        return MXS_CHIP_REVISION_1_1;
 335                case 0x1:
 336                        return MXS_CHIP_REVISION_1_2;
 337                default:
 338                        return MXS_CHIP_REV_UNKNOWN;
 339                }
 340        default:
 341                return MXS_CHIP_REV_UNKNOWN;
 342        }
 343}
 344
 345static const char __init *mxs_get_revision(void)
 346{
 347        u32 rev = mxs_get_cpu_rev();
 348
 349        if (rev != MXS_CHIP_REV_UNKNOWN)
 350                return kasprintf(GFP_KERNEL, "%d.%d", (rev >> 4) & 0xf,
 351                                rev & 0xf);
 352        else
 353                return kasprintf(GFP_KERNEL, "%s", "Unknown");
 354}
 355
 356#define MX23_CLKCTRL_RESET_OFFSET       0x120
 357#define MX28_CLKCTRL_RESET_OFFSET       0x1e0
 358
 359static int __init mxs_restart_init(void)
 360{
 361        struct device_node *np;
 362
 363        np = of_find_compatible_node(NULL, NULL, "fsl,clkctrl");
 364        reset_addr = of_iomap(np, 0);
 365        if (!reset_addr)
 366                return -ENODEV;
 367
 368        if (of_device_is_compatible(np, "fsl,imx23-clkctrl"))
 369                reset_addr += MX23_CLKCTRL_RESET_OFFSET;
 370        else
 371                reset_addr += MX28_CLKCTRL_RESET_OFFSET;
 372        of_node_put(np);
 373
 374        return 0;
 375}
 376
 377static void __init eukrea_mbmx283lc_init(void)
 378{
 379        mxs_saif_clkmux_select(MXS_DIGCTL_SAIF_CLKMUX_EXTMSTR0);
 380}
 381
 382static void __init mxs_machine_init(void)
 383{
 384        struct device_node *root;
 385        struct device *parent;
 386        struct soc_device *soc_dev;
 387        struct soc_device_attribute *soc_dev_attr;
 388        int ret;
 389
 390        soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
 391        if (!soc_dev_attr)
 392                return;
 393
 394        root = of_find_node_by_path("/");
 395        ret = of_property_read_string(root, "model", &soc_dev_attr->machine);
 396        if (ret)
 397                return;
 398
 399        soc_dev_attr->family = "Freescale MXS Family";
 400        soc_dev_attr->soc_id = mxs_get_soc_id();
 401        soc_dev_attr->revision = mxs_get_revision();
 402
 403        soc_dev = soc_device_register(soc_dev_attr);
 404        if (IS_ERR(soc_dev)) {
 405                kfree(soc_dev_attr->revision);
 406                kfree(soc_dev_attr);
 407                return;
 408        }
 409
 410        parent = soc_device_to_device(soc_dev);
 411
 412        if (of_machine_is_compatible("fsl,imx28-evk"))
 413                imx28_evk_init();
 414        if (of_machine_is_compatible("armadeus,imx28-apf28"))
 415                imx28_apf28_init();
 416        else if (of_machine_is_compatible("bluegiga,apx4devkit"))
 417                apx4devkit_init();
 418        else if (of_machine_is_compatible("crystalfontz,cfa10036"))
 419                crystalfontz_init();
 420        else if (of_machine_is_compatible("eukrea,mbmx283lc"))
 421                eukrea_mbmx283lc_init();
 422        else if (of_machine_is_compatible("i2se,duckbill"))
 423                duckbill_init();
 424        else if (of_machine_is_compatible("msr,m28cu3"))
 425                m28cu3_init();
 426
 427        of_platform_default_populate(NULL, NULL, parent);
 428
 429        mxs_restart_init();
 430}
 431
 432#define MXS_CLKCTRL_RESET_CHIP          (1 << 1)
 433
 434/*
 435 * Reset the system. It is called by machine_restart().
 436 */
 437static void mxs_restart(enum reboot_mode mode, const char *cmd)
 438{
 439        if (reset_addr) {
 440                /* reset the chip */
 441                __mxs_setl(MXS_CLKCTRL_RESET_CHIP, reset_addr);
 442
 443                pr_err("Failed to assert the chip reset\n");
 444
 445                /* Delay to allow the serial port to show the message */
 446                mdelay(50);
 447        }
 448
 449        /* We'll take a jump through zero as a poor second */
 450        soft_restart(0);
 451}
 452
 453static const char *const mxs_dt_compat[] __initconst = {
 454        "fsl,imx28",
 455        "fsl,imx23",
 456        NULL,
 457};
 458
 459DT_MACHINE_START(MXS, "Freescale MXS (Device Tree)")
 460        .handle_irq     = icoll_handle_irq,
 461        .init_machine   = mxs_machine_init,
 462        .init_late      = mxs_pm_init,
 463        .dt_compat      = mxs_dt_compat,
 464        .restart        = mxs_restart,
 465MACHINE_END
 466