0001
0002
0003
0004
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
0024 static int ksz9021rn_phy_fixup(struct phy_device *phydev)
0025 {
0026 if (IS_BUILTIN(CONFIG_PHYLIB)) {
0027
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
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
0045
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;
0059 pci_write_config_dword(dev, 0x62c, dw);
0060
0061 pci_read_config_dword(dev, 0x644, &dw);
0062 dw |= 0xfe;
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
0107
0108
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
0137
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
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
0166
0167
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
0188
0189
0190
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