Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-or-later
0002 /*
0003  * Copyright 2011-2013 Freescale Semiconductor, Inc.
0004  * Copyright 2011 Linaro Ltd.
0005  */
0006 
0007 #include <linux/clk.h>
0008 #include <linux/irqchip.h>
0009 #include <linux/of_platform.h>
0010 #include <linux/pci.h>
0011 #include <linux/phy.h>
0012 #include <linux/regmap.h>
0013 #include <linux/micrel_phy.h>
0014 #include <linux/mfd/syscon.h>
0015 #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
0016 #include <asm/mach/arch.h>
0017 #include <asm/mach/map.h>
0018 
0019 #include "common.h"
0020 #include "cpuidle.h"
0021 #include "hardware.h"
0022 
0023 /* For imx6q sabrelite board: set KSZ9021RN RGMII pad skew */
0024 static int ksz9021rn_phy_fixup(struct phy_device *phydev)
0025 {
0026     if (IS_BUILTIN(CONFIG_PHYLIB)) {
0027         /* min rx data delay */
0028         phy_write(phydev, MICREL_KSZ9021_EXTREG_CTRL,
0029             0x8000 | MICREL_KSZ9021_RGMII_RX_DATA_PAD_SCEW);
0030         phy_write(phydev, MICREL_KSZ9021_EXTREG_DATA_WRITE, 0x0000);
0031 
0032         /* max rx/tx clock delay, min rx/tx control delay */
0033         phy_write(phydev, MICREL_KSZ9021_EXTREG_CTRL,
0034             0x8000 | MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW);
0035         phy_write(phydev, MICREL_KSZ9021_EXTREG_DATA_WRITE, 0xf0f0);
0036         phy_write(phydev, MICREL_KSZ9021_EXTREG_CTRL,
0037             MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW);
0038     }
0039 
0040     return 0;
0041 }
0042 
0043 /*
0044  * fixup for PLX PEX8909 bridge to configure GPIO1-7 as output High
0045  * as they are used for slots1-7 PERST#
0046  */
0047 static void ventana_pciesw_early_fixup(struct pci_dev *dev)
0048 {
0049     u32 dw;
0050 
0051     if (!of_machine_is_compatible("gw,ventana"))
0052         return;
0053 
0054     if (dev->devfn != 0)
0055         return;
0056 
0057     pci_read_config_dword(dev, 0x62c, &dw);
0058     dw |= 0xaaa8; // GPIO1-7 outputs
0059     pci_write_config_dword(dev, 0x62c, dw);
0060 
0061     pci_read_config_dword(dev, 0x644, &dw);
0062     dw |= 0xfe;   // GPIO1-7 output high
0063     pci_write_config_dword(dev, 0x644, dw);
0064 
0065     msleep(100);
0066 }
0067 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8609, ventana_pciesw_early_fixup);
0068 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8606, ventana_pciesw_early_fixup);
0069 DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8604, ventana_pciesw_early_fixup);
0070 
0071 static void __init imx6q_enet_phy_init(void)
0072 {
0073     if (IS_BUILTIN(CONFIG_PHYLIB)) {
0074         phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
0075                 ksz9021rn_phy_fixup);
0076     }
0077 }
0078 
0079 static void __init imx6q_1588_init(void)
0080 {
0081     struct device_node *np;
0082     struct clk *ptp_clk;
0083     struct clk *enet_ref;
0084     struct regmap *gpr;
0085     u32 clksel;
0086 
0087     np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-fec");
0088     if (!np) {
0089         pr_warn("%s: failed to find fec node\n", __func__);
0090         return;
0091     }
0092 
0093     ptp_clk = of_clk_get(np, 2);
0094     if (IS_ERR(ptp_clk)) {
0095         pr_warn("%s: failed to get ptp clock\n", __func__);
0096         goto put_node;
0097     }
0098 
0099     enet_ref = clk_get_sys(NULL, "enet_ref");
0100     if (IS_ERR(enet_ref)) {
0101         pr_warn("%s: failed to get enet clock\n", __func__);
0102         goto put_ptp_clk;
0103     }
0104 
0105     /*
0106      * If enet_ref from ANATOP/CCM is the PTP clock source, we need to
0107      * set bit IOMUXC_GPR1[21].  Or the PTP clock must be from pad
0108      * (external OSC), and we need to clear the bit.
0109      */
0110     clksel = clk_is_match(ptp_clk, enet_ref) ?
0111                 IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
0112                 IMX6Q_GPR1_ENET_CLK_SEL_PAD;
0113     gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
0114     if (!IS_ERR(gpr))
0115         regmap_update_bits(gpr, IOMUXC_GPR1,
0116                 IMX6Q_GPR1_ENET_CLK_SEL_MASK,
0117                 clksel);
0118     else
0119         pr_err("failed to find fsl,imx6q-iomuxc-gpr regmap\n");
0120 
0121     clk_put(enet_ref);
0122 put_ptp_clk:
0123     clk_put(ptp_clk);
0124 put_node:
0125     of_node_put(np);
0126 }
0127 
0128 static void __init imx6q_axi_init(void)
0129 {
0130     struct regmap *gpr;
0131     unsigned int mask;
0132 
0133     gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
0134     if (!IS_ERR(gpr)) {
0135         /*
0136          * Enable the cacheable attribute of VPU and IPU
0137          * AXI transactions.
0138          */
0139         mask = IMX6Q_GPR4_VPU_WR_CACHE_SEL |
0140             IMX6Q_GPR4_VPU_RD_CACHE_SEL |
0141             IMX6Q_GPR4_VPU_P_WR_CACHE_VAL |
0142             IMX6Q_GPR4_VPU_P_RD_CACHE_VAL_MASK |
0143             IMX6Q_GPR4_IPU_WR_CACHE_CTL |
0144             IMX6Q_GPR4_IPU_RD_CACHE_CTL;
0145         regmap_update_bits(gpr, IOMUXC_GPR4, mask, mask);
0146 
0147         /* Increase IPU read QoS priority */
0148         regmap_update_bits(gpr, IOMUXC_GPR6,
0149                 IMX6Q_GPR6_IPU1_ID00_RD_QOS_MASK |
0150                 IMX6Q_GPR6_IPU1_ID01_RD_QOS_MASK,
0151                 (0xf << 16) | (0x7 << 20));
0152         regmap_update_bits(gpr, IOMUXC_GPR7,
0153                 IMX6Q_GPR7_IPU2_ID00_RD_QOS_MASK |
0154                 IMX6Q_GPR7_IPU2_ID01_RD_QOS_MASK,
0155                 (0xf << 16) | (0x7 << 20));
0156     } else {
0157         pr_warn("failed to find fsl,imx6q-iomuxc-gpr regmap\n");
0158     }
0159 }
0160 
0161 static void __init imx6q_init_machine(void)
0162 {
0163     if (cpu_is_imx6q() && imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0)
0164         /*
0165          * SoCs that identify as i.MX6Q >= rev 2.0 are really i.MX6QP.
0166          * Quirk: i.MX6QP revision = i.MX6Q revision - (1, 0),
0167          * e.g. i.MX6QP rev 1.1 identifies as i.MX6Q rev 2.1.
0168          */
0169         imx_print_silicon_rev("i.MX6QP", imx_get_soc_revision() - 0x10);
0170     else
0171         imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q",
0172                 imx_get_soc_revision());
0173 
0174     imx6q_enet_phy_init();
0175 
0176     of_platform_default_populate(NULL, NULL, NULL);
0177 
0178     imx_anatop_init();
0179     cpu_is_imx6q() ?  imx6q_pm_init() : imx6dl_pm_init();
0180     imx6q_1588_init();
0181     imx6q_axi_init();
0182 }
0183 
0184 static void __init imx6q_init_late(void)
0185 {
0186     /*
0187      * WAIT mode is broken on imx6 Dual/Quad revision 1.0 and 1.1 so
0188      * there is no point to run cpuidle on them.
0189      *
0190      * It does work on imx6 Solo/DualLite starting from 1.1
0191      */
0192     if ((cpu_is_imx6q() && imx_get_soc_revision() > IMX_CHIP_REVISION_1_1) ||
0193         (cpu_is_imx6dl() && imx_get_soc_revision() > IMX_CHIP_REVISION_1_0))
0194         imx6q_cpuidle_init();
0195 
0196     if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
0197         platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
0198 }
0199 
0200 static void __init imx6q_map_io(void)
0201 {
0202     debug_ll_io_init();
0203     imx_scu_map_io();
0204 }
0205 
0206 static void __init imx6q_init_irq(void)
0207 {
0208     imx_gpc_check_dt();
0209     imx_init_revision_from_anatop();
0210     imx_init_l2cache();
0211     imx_src_init();
0212     irqchip_init();
0213     imx6_pm_ccm_init("fsl,imx6q-ccm");
0214 }
0215 
0216 static const char * const imx6q_dt_compat[] __initconst = {
0217     "fsl,imx6dl",
0218     "fsl,imx6q",
0219     "fsl,imx6qp",
0220     NULL,
0221 };
0222 
0223 DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)")
0224     .l2c_aux_val    = 0,
0225     .l2c_aux_mask   = ~0,
0226     .smp        = smp_ops(imx_smp_ops),
0227     .map_io     = imx6q_map_io,
0228     .init_irq   = imx6q_init_irq,
0229     .init_machine   = imx6q_init_machine,
0230     .init_late      = imx6q_init_late,
0231     .dt_compat  = imx6q_dt_compat,
0232 MACHINE_END