linux/arch/arm/mach-imx/mach-imx6q.c
<<
>>
Prefs
   1/*
   2 * Copyright 2011-2013 Freescale Semiconductor, Inc.
   3 * Copyright 2011 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/clkdev.h>
  15#include <linux/cpu.h>
  16#include <linux/delay.h>
  17#include <linux/export.h>
  18#include <linux/init.h>
  19#include <linux/io.h>
  20#include <linux/irq.h>
  21#include <linux/irqchip.h>
  22#include <linux/of.h>
  23#include <linux/of_address.h>
  24#include <linux/of_irq.h>
  25#include <linux/of_platform.h>
  26#include <linux/pm_opp.h>
  27#include <linux/pci.h>
  28#include <linux/phy.h>
  29#include <linux/reboot.h>
  30#include <linux/regmap.h>
  31#include <linux/micrel_phy.h>
  32#include <linux/mfd/syscon.h>
  33#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
  34#include <asm/mach/arch.h>
  35#include <asm/mach/map.h>
  36#include <asm/system_misc.h>
  37
  38#include "common.h"
  39#include "cpuidle.h"
  40#include "hardware.h"
  41
  42/* For imx6q sabrelite board: set KSZ9021RN RGMII pad skew */
  43static int ksz9021rn_phy_fixup(struct phy_device *phydev)
  44{
  45        if (IS_BUILTIN(CONFIG_PHYLIB)) {
  46                /* min rx data delay */
  47                phy_write(phydev, MICREL_KSZ9021_EXTREG_CTRL,
  48                        0x8000 | MICREL_KSZ9021_RGMII_RX_DATA_PAD_SCEW);
  49                phy_write(phydev, MICREL_KSZ9021_EXTREG_DATA_WRITE, 0x0000);
  50
  51                /* max rx/tx clock delay, min rx/tx control delay */
  52                phy_write(phydev, MICREL_KSZ9021_EXTREG_CTRL,
  53                        0x8000 | MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW);
  54                phy_write(phydev, MICREL_KSZ9021_EXTREG_DATA_WRITE, 0xf0f0);
  55                phy_write(phydev, MICREL_KSZ9021_EXTREG_CTRL,
  56                        MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW);
  57        }
  58
  59        return 0;
  60}
  61
  62static void mmd_write_reg(struct phy_device *dev, int device, int reg, int val)
  63{
  64        phy_write(dev, 0x0d, device);
  65        phy_write(dev, 0x0e, reg);
  66        phy_write(dev, 0x0d, (1 << 14) | device);
  67        phy_write(dev, 0x0e, val);
  68}
  69
  70static int ksz9031rn_phy_fixup(struct phy_device *dev)
  71{
  72        /*
  73         * min rx data delay, max rx/tx clock delay,
  74         * min rx/tx control delay
  75         */
  76        mmd_write_reg(dev, 2, 4, 0);
  77        mmd_write_reg(dev, 2, 5, 0);
  78        mmd_write_reg(dev, 2, 8, 0x003ff);
  79
  80        return 0;
  81}
  82
  83/*
  84 * fixup for PLX PEX8909 bridge to configure GPIO1-7 as output High
  85 * as they are used for slots1-7 PERST#
  86 */
  87static void ventana_pciesw_early_fixup(struct pci_dev *dev)
  88{
  89        u32 dw;
  90
  91        if (!of_machine_is_compatible("gw,ventana"))
  92                return;
  93
  94        if (dev->devfn != 0)
  95                return;
  96
  97        pci_read_config_dword(dev, 0x62c, &dw);
  98        dw |= 0xaaa8; // GPIO1-7 outputs
  99        pci_write_config_dword(dev, 0x62c, dw);
 100
 101        pci_read_config_dword(dev, 0x644, &dw);
 102        dw |= 0xfe;   // GPIO1-7 output high
 103        pci_write_config_dword(dev, 0x644, dw);
 104
 105        msleep(100);
 106}
 107DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8609, ventana_pciesw_early_fixup);
 108DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8606, ventana_pciesw_early_fixup);
 109DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8604, ventana_pciesw_early_fixup);
 110
 111static int ar8031_phy_fixup(struct phy_device *dev)
 112{
 113        u16 val;
 114
 115        /* To enable AR8031 output a 125MHz clk from CLK_25M */
 116        phy_write(dev, 0xd, 0x7);
 117        phy_write(dev, 0xe, 0x8016);
 118        phy_write(dev, 0xd, 0x4007);
 119
 120        val = phy_read(dev, 0xe);
 121        val &= 0xffe3;
 122        val |= 0x18;
 123        phy_write(dev, 0xe, val);
 124
 125        /* introduce tx clock delay */
 126        phy_write(dev, 0x1d, 0x5);
 127        val = phy_read(dev, 0x1e);
 128        val |= 0x0100;
 129        phy_write(dev, 0x1e, val);
 130
 131        return 0;
 132}
 133
 134#define PHY_ID_AR8031   0x004dd074
 135
 136static int ar8035_phy_fixup(struct phy_device *dev)
 137{
 138        u16 val;
 139
 140        /* Ar803x phy SmartEEE feature cause link status generates glitch,
 141         * which cause ethernet link down/up issue, so disable SmartEEE
 142         */
 143        phy_write(dev, 0xd, 0x3);
 144        phy_write(dev, 0xe, 0x805d);
 145        phy_write(dev, 0xd, 0x4003);
 146
 147        val = phy_read(dev, 0xe);
 148        phy_write(dev, 0xe, val & ~(1 << 8));
 149
 150        /*
 151         * Enable 125MHz clock from CLK_25M on the AR8031.  This
 152         * is fed in to the IMX6 on the ENET_REF_CLK (V22) pad.
 153         * Also, introduce a tx clock delay.
 154         *
 155         * This is the same as is the AR8031 fixup.
 156         */
 157        ar8031_phy_fixup(dev);
 158
 159        /*check phy power*/
 160        val = phy_read(dev, 0x0);
 161        if (val & BMCR_PDOWN)
 162                phy_write(dev, 0x0, val & ~BMCR_PDOWN);
 163
 164        return 0;
 165}
 166
 167#define PHY_ID_AR8035 0x004dd072
 168
 169static void __init imx6q_enet_phy_init(void)
 170{
 171        if (IS_BUILTIN(CONFIG_PHYLIB)) {
 172                phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
 173                                ksz9021rn_phy_fixup);
 174                phy_register_fixup_for_uid(PHY_ID_KSZ9031, MICREL_PHY_ID_MASK,
 175                                ksz9031rn_phy_fixup);
 176                phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffef,
 177                                ar8031_phy_fixup);
 178                phy_register_fixup_for_uid(PHY_ID_AR8035, 0xffffffef,
 179                                ar8035_phy_fixup);
 180        }
 181}
 182
 183static void __init imx6q_1588_init(void)
 184{
 185        struct device_node *np;
 186        struct clk *ptp_clk;
 187        struct clk *enet_ref;
 188        struct regmap *gpr;
 189        u32 clksel;
 190
 191        np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-fec");
 192        if (!np) {
 193                pr_warn("%s: failed to find fec node\n", __func__);
 194                return;
 195        }
 196
 197        ptp_clk = of_clk_get(np, 2);
 198        if (IS_ERR(ptp_clk)) {
 199                pr_warn("%s: failed to get ptp clock\n", __func__);
 200                goto put_node;
 201        }
 202
 203        enet_ref = clk_get_sys(NULL, "enet_ref");
 204        if (IS_ERR(enet_ref)) {
 205                pr_warn("%s: failed to get enet clock\n", __func__);
 206                goto put_ptp_clk;
 207        }
 208
 209        /*
 210         * If enet_ref from ANATOP/CCM is the PTP clock source, we need to
 211         * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
 212         * (external OSC), and we need to clear the bit.
 213         */
 214        clksel = clk_is_match(ptp_clk, enet_ref) ?
 215                                IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
 216                                IMX6Q_GPR1_ENET_CLK_SEL_PAD;
 217        gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
 218        if (!IS_ERR(gpr))
 219                regmap_update_bits(gpr, IOMUXC_GPR1,
 220                                IMX6Q_GPR1_ENET_CLK_SEL_MASK,
 221                                clksel);
 222        else
 223                pr_err("failed to find fsl,imx6q-iomuxc-gpr regmap\n");
 224
 225        clk_put(enet_ref);
 226put_ptp_clk:
 227        clk_put(ptp_clk);
 228put_node:
 229        of_node_put(np);
 230}
 231
 232static void __init imx6q_axi_init(void)
 233{
 234        struct regmap *gpr;
 235        unsigned int mask;
 236
 237        gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
 238        if (!IS_ERR(gpr)) {
 239                /*
 240                 * Enable the cacheable attribute of VPU and IPU
 241                 * AXI transactions.
 242                 */
 243                mask = IMX6Q_GPR4_VPU_WR_CACHE_SEL |
 244                        IMX6Q_GPR4_VPU_RD_CACHE_SEL |
 245                        IMX6Q_GPR4_VPU_P_WR_CACHE_VAL |
 246                        IMX6Q_GPR4_VPU_P_RD_CACHE_VAL_MASK |
 247                        IMX6Q_GPR4_IPU_WR_CACHE_CTL |
 248                        IMX6Q_GPR4_IPU_RD_CACHE_CTL;
 249                regmap_update_bits(gpr, IOMUXC_GPR4, mask, mask);
 250
 251                /* Increase IPU read QoS priority */
 252                regmap_update_bits(gpr, IOMUXC_GPR6,
 253                                IMX6Q_GPR6_IPU1_ID00_RD_QOS_MASK |
 254                                IMX6Q_GPR6_IPU1_ID01_RD_QOS_MASK,
 255                                (0xf << 16) | (0x7 << 20));
 256                regmap_update_bits(gpr, IOMUXC_GPR7,
 257                                IMX6Q_GPR7_IPU2_ID00_RD_QOS_MASK |
 258                                IMX6Q_GPR7_IPU2_ID01_RD_QOS_MASK,
 259                                (0xf << 16) | (0x7 << 20));
 260        } else {
 261                pr_warn("failed to find fsl,imx6q-iomuxc-gpr regmap\n");
 262        }
 263}
 264
 265static void __init imx6q_init_machine(void)
 266{
 267        struct device *parent;
 268
 269        if (cpu_is_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_2_0)
 270                imx_print_silicon_rev("i.MX6QP", IMX_CHIP_REVISION_1_0);
 271        else
 272                imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q",
 273                                imx_get_soc_revision());
 274
 275        parent = imx_soc_device_init();
 276        if (parent == NULL)
 277                pr_warn("failed to initialize soc device\n");
 278
 279        imx6q_enet_phy_init();
 280
 281        of_platform_default_populate(NULL, NULL, parent);
 282
 283        imx_anatop_init();
 284        cpu_is_imx6q() ?  imx6q_pm_init() : imx6dl_pm_init();
 285        imx6q_1588_init();
 286        imx6q_axi_init();
 287}
 288
 289#define OCOTP_CFG3                      0x440
 290#define OCOTP_CFG3_SPEED_SHIFT          16
 291#define OCOTP_CFG3_SPEED_1P2GHZ         0x3
 292#define OCOTP_CFG3_SPEED_996MHZ         0x2
 293#define OCOTP_CFG3_SPEED_852MHZ         0x1
 294
 295static void __init imx6q_opp_check_speed_grading(struct device *cpu_dev)
 296{
 297        struct device_node *np;
 298        void __iomem *base;
 299        u32 val;
 300
 301        np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ocotp");
 302        if (!np) {
 303                pr_warn("failed to find ocotp node\n");
 304                return;
 305        }
 306
 307        base = of_iomap(np, 0);
 308        if (!base) {
 309                pr_warn("failed to map ocotp\n");
 310                goto put_node;
 311        }
 312
 313        /*
 314         * SPEED_GRADING[1:0] defines the max speed of ARM:
 315         * 2b'11: 1200000000Hz;
 316         * 2b'10: 996000000Hz;
 317         * 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz.
 318         * 2b'00: 792000000Hz;
 319         * We need to set the max speed of ARM according to fuse map.
 320         */
 321        val = readl_relaxed(base + OCOTP_CFG3);
 322        val >>= OCOTP_CFG3_SPEED_SHIFT;
 323        val &= 0x3;
 324
 325        if ((val != OCOTP_CFG3_SPEED_1P2GHZ) && cpu_is_imx6q())
 326                if (dev_pm_opp_disable(cpu_dev, 1200000000))
 327                        pr_warn("failed to disable 1.2 GHz OPP\n");
 328        if (val < OCOTP_CFG3_SPEED_996MHZ)
 329                if (dev_pm_opp_disable(cpu_dev, 996000000))
 330                        pr_warn("failed to disable 996 MHz OPP\n");
 331        if (cpu_is_imx6q()) {
 332                if (val != OCOTP_CFG3_SPEED_852MHZ)
 333                        if (dev_pm_opp_disable(cpu_dev, 852000000))
 334                                pr_warn("failed to disable 852 MHz OPP\n");
 335        }
 336        iounmap(base);
 337put_node:
 338        of_node_put(np);
 339}
 340
 341static void __init imx6q_opp_init(void)
 342{
 343        struct device_node *np;
 344        struct device *cpu_dev = get_cpu_device(0);
 345
 346        if (!cpu_dev) {
 347                pr_warn("failed to get cpu0 device\n");
 348                return;
 349        }
 350        np = of_node_get(cpu_dev->of_node);
 351        if (!np) {
 352                pr_warn("failed to find cpu0 node\n");
 353                return;
 354        }
 355
 356        if (dev_pm_opp_of_add_table(cpu_dev)) {
 357                pr_warn("failed to init OPP table\n");
 358                goto put_node;
 359        }
 360
 361        imx6q_opp_check_speed_grading(cpu_dev);
 362
 363put_node:
 364        of_node_put(np);
 365}
 366
 367static struct platform_device imx6q_cpufreq_pdev = {
 368        .name = "imx6q-cpufreq",
 369};
 370
 371static void __init imx6q_init_late(void)
 372{
 373        /*
 374         * WAIT mode is broken on TO 1.0 and 1.1, so there is no point
 375         * to run cpuidle on them.
 376         */
 377        if (imx_get_soc_revision() > IMX_CHIP_REVISION_1_1)
 378                imx6q_cpuidle_init();
 379
 380        if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) {
 381                imx6q_opp_init();
 382                platform_device_register(&imx6q_cpufreq_pdev);
 383        }
 384}
 385
 386static void __init imx6q_map_io(void)
 387{
 388        debug_ll_io_init();
 389        imx_scu_map_io();
 390}
 391
 392static void __init imx6q_init_irq(void)
 393{
 394        imx_gpc_check_dt();
 395        imx_init_revision_from_anatop();
 396        imx_init_l2cache();
 397        imx_src_init();
 398        irqchip_init();
 399        imx6_pm_ccm_init("fsl,imx6q-ccm");
 400}
 401
 402static const char * const imx6q_dt_compat[] __initconst = {
 403        "fsl,imx6dl",
 404        "fsl,imx6q",
 405        "fsl,imx6qp",
 406        NULL,
 407};
 408
 409DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)")
 410        .l2c_aux_val    = 0,
 411        .l2c_aux_mask   = ~0,
 412        .smp            = smp_ops(imx_smp_ops),
 413        .map_io         = imx6q_map_io,
 414        .init_irq       = imx6q_init_irq,
 415        .init_machine   = imx6q_init_machine,
 416        .init_late      = imx6q_init_late,
 417        .dt_compat      = imx6q_dt_compat,
 418MACHINE_END
 419