mach-imx6q.c 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Copyright 2011-2013 Freescale Semiconductor, Inc.
  4. * Copyright 2011 Linaro Ltd.
  5. */
  6. #include <linux/clk.h>
  7. #include <linux/irqchip.h>
  8. #include <linux/of_platform.h>
  9. #include <linux/pci.h>
  10. #include <linux/phy.h>
  11. #include <linux/regmap.h>
  12. #include <linux/micrel_phy.h>
  13. #include <linux/mfd/syscon.h>
  14. #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
  15. #include <asm/mach/arch.h>
  16. #include <asm/mach/map.h>
  17. #include "common.h"
  18. #include "cpuidle.h"
  19. #include "hardware.h"
  20. /* For imx6q sabrelite board: set KSZ9021RN RGMII pad skew */
  21. static int ksz9021rn_phy_fixup(struct phy_device *phydev)
  22. {
  23. if (IS_BUILTIN(CONFIG_PHYLIB)) {
  24. /* min rx data delay */
  25. phy_write(phydev, MICREL_KSZ9021_EXTREG_CTRL,
  26. 0x8000 | MICREL_KSZ9021_RGMII_RX_DATA_PAD_SCEW);
  27. phy_write(phydev, MICREL_KSZ9021_EXTREG_DATA_WRITE, 0x0000);
  28. /* max rx/tx clock delay, min rx/tx control delay */
  29. phy_write(phydev, MICREL_KSZ9021_EXTREG_CTRL,
  30. 0x8000 | MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW);
  31. phy_write(phydev, MICREL_KSZ9021_EXTREG_DATA_WRITE, 0xf0f0);
  32. phy_write(phydev, MICREL_KSZ9021_EXTREG_CTRL,
  33. MICREL_KSZ9021_RGMII_CLK_CTRL_PAD_SCEW);
  34. }
  35. return 0;
  36. }
  37. /*
  38. * fixup for PLX PEX8909 bridge to configure GPIO1-7 as output High
  39. * as they are used for slots1-7 PERST#
  40. */
  41. static void ventana_pciesw_early_fixup(struct pci_dev *dev)
  42. {
  43. u32 dw;
  44. if (!of_machine_is_compatible("gw,ventana"))
  45. return;
  46. if (dev->devfn != 0)
  47. return;
  48. pci_read_config_dword(dev, 0x62c, &dw);
  49. dw |= 0xaaa8; // GPIO1-7 outputs
  50. pci_write_config_dword(dev, 0x62c, dw);
  51. pci_read_config_dword(dev, 0x644, &dw);
  52. dw |= 0xfe; // GPIO1-7 output high
  53. pci_write_config_dword(dev, 0x644, dw);
  54. msleep(100);
  55. }
  56. DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8609, ventana_pciesw_early_fixup);
  57. DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8606, ventana_pciesw_early_fixup);
  58. DECLARE_PCI_FIXUP_EARLY(PCI_VENDOR_ID_PLX, 0x8604, ventana_pciesw_early_fixup);
  59. static void __init imx6q_enet_phy_init(void)
  60. {
  61. if (IS_BUILTIN(CONFIG_PHYLIB)) {
  62. phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
  63. ksz9021rn_phy_fixup);
  64. }
  65. }
  66. static void __init imx6q_1588_init(void)
  67. {
  68. struct device_node *np;
  69. struct clk *ptp_clk;
  70. struct clk *enet_ref;
  71. struct regmap *gpr;
  72. u32 clksel;
  73. np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-fec");
  74. if (!np) {
  75. pr_warn("%s: failed to find fec node\n", __func__);
  76. return;
  77. }
  78. ptp_clk = of_clk_get(np, 2);
  79. if (IS_ERR(ptp_clk)) {
  80. pr_warn("%s: failed to get ptp clock\n", __func__);
  81. goto put_node;
  82. }
  83. enet_ref = clk_get_sys(NULL, "enet_ref");
  84. if (IS_ERR(enet_ref)) {
  85. pr_warn("%s: failed to get enet clock\n", __func__);
  86. goto put_ptp_clk;
  87. }
  88. /*
  89. * If enet_ref from ANATOP/CCM is the PTP clock source, we need to
  90. * set bit IOMUXC_GPR1[21]. Or the PTP clock must be from pad
  91. * (external OSC), and we need to clear the bit.
  92. */
  93. clksel = clk_is_match(ptp_clk, enet_ref) ?
  94. IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
  95. IMX6Q_GPR1_ENET_CLK_SEL_PAD;
  96. gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
  97. if (!IS_ERR(gpr))
  98. regmap_update_bits(gpr, IOMUXC_GPR1,
  99. IMX6Q_GPR1_ENET_CLK_SEL_MASK,
  100. clksel);
  101. else
  102. pr_err("failed to find fsl,imx6q-iomuxc-gpr regmap\n");
  103. clk_put(enet_ref);
  104. put_ptp_clk:
  105. clk_put(ptp_clk);
  106. put_node:
  107. of_node_put(np);
  108. }
  109. static void __init imx6q_axi_init(void)
  110. {
  111. struct regmap *gpr;
  112. unsigned int mask;
  113. gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
  114. if (!IS_ERR(gpr)) {
  115. /*
  116. * Enable the cacheable attribute of VPU and IPU
  117. * AXI transactions.
  118. */
  119. mask = IMX6Q_GPR4_VPU_WR_CACHE_SEL |
  120. IMX6Q_GPR4_VPU_RD_CACHE_SEL |
  121. IMX6Q_GPR4_VPU_P_WR_CACHE_VAL |
  122. IMX6Q_GPR4_VPU_P_RD_CACHE_VAL_MASK |
  123. IMX6Q_GPR4_IPU_WR_CACHE_CTL |
  124. IMX6Q_GPR4_IPU_RD_CACHE_CTL;
  125. regmap_update_bits(gpr, IOMUXC_GPR4, mask, mask);
  126. /* Increase IPU read QoS priority */
  127. regmap_update_bits(gpr, IOMUXC_GPR6,
  128. IMX6Q_GPR6_IPU1_ID00_RD_QOS_MASK |
  129. IMX6Q_GPR6_IPU1_ID01_RD_QOS_MASK,
  130. (0xf << 16) | (0x7 << 20));
  131. regmap_update_bits(gpr, IOMUXC_GPR7,
  132. IMX6Q_GPR7_IPU2_ID00_RD_QOS_MASK |
  133. IMX6Q_GPR7_IPU2_ID01_RD_QOS_MASK,
  134. (0xf << 16) | (0x7 << 20));
  135. } else {
  136. pr_warn("failed to find fsl,imx6q-iomuxc-gpr regmap\n");
  137. }
  138. }
  139. static void __init imx6q_init_machine(void)
  140. {
  141. if (cpu_is_imx6q() && imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0)
  142. /*
  143. * SoCs that identify as i.MX6Q >= rev 2.0 are really i.MX6QP.
  144. * Quirk: i.MX6QP revision = i.MX6Q revision - (1, 0),
  145. * e.g. i.MX6QP rev 1.1 identifies as i.MX6Q rev 2.1.
  146. */
  147. imx_print_silicon_rev("i.MX6QP", imx_get_soc_revision() - 0x10);
  148. else
  149. imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q",
  150. imx_get_soc_revision());
  151. imx6q_enet_phy_init();
  152. of_platform_default_populate(NULL, NULL, NULL);
  153. imx_anatop_init();
  154. cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init();
  155. imx6q_1588_init();
  156. imx6q_axi_init();
  157. }
  158. static void __init imx6q_init_late(void)
  159. {
  160. /*
  161. * WAIT mode is broken on imx6 Dual/Quad revision 1.0 and 1.1 so
  162. * there is no point to run cpuidle on them.
  163. *
  164. * It does work on imx6 Solo/DualLite starting from 1.1
  165. */
  166. if ((cpu_is_imx6q() && imx_get_soc_revision() > IMX_CHIP_REVISION_1_1) ||
  167. (cpu_is_imx6dl() && imx_get_soc_revision() > IMX_CHIP_REVISION_1_0))
  168. imx6q_cpuidle_init();
  169. if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
  170. platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
  171. }
  172. static void __init imx6q_map_io(void)
  173. {
  174. debug_ll_io_init();
  175. imx_scu_map_io();
  176. }
  177. static void __init imx6q_init_irq(void)
  178. {
  179. imx_gpc_check_dt();
  180. imx_init_revision_from_anatop();
  181. imx_init_l2cache();
  182. imx_src_init();
  183. irqchip_init();
  184. imx6_pm_ccm_init("fsl,imx6q-ccm");
  185. }
  186. static const char * const imx6q_dt_compat[] __initconst = {
  187. "fsl,imx6dl",
  188. "fsl,imx6q",
  189. "fsl,imx6qp",
  190. NULL,
  191. };
  192. DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)")
  193. .l2c_aux_val = 0,
  194. .l2c_aux_mask = ~0,
  195. .smp = smp_ops(imx_smp_ops),
  196. .map_io = imx6q_map_io,
  197. .init_irq = imx6q_init_irq,
  198. .init_machine = imx6q_init_machine,
  199. .init_late = imx6q_init_late,
  200. .dt_compat = imx6q_dt_compat,
  201. MACHINE_END