root/arch/arm/mach-imx/mach-imx6q.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ksz9021rn_phy_fixup
  2. mmd_write_reg
  3. ksz9031rn_phy_fixup
  4. ventana_pciesw_early_fixup
  5. ar8031_phy_fixup
  6. ar8035_phy_fixup
  7. imx6q_enet_phy_init
  8. imx6q_1588_init
  9. imx6q_axi_init
  10. imx6q_init_machine
  11. imx6q_init_late
  12. imx6q_map_io
  13. imx6q_init_irq

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

/* [<][>][^][v][top][bottom][index][help] */