mach-imx6q.c 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  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, *fec_enet_ref;
  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. /*
  79. * If enet_clk_ref configured, we assume DT did it properly and .
  80. * clk-imx6q.c will do needed configuration.
  81. */
  82. fec_enet_ref = of_clk_get_by_name(np, "enet_clk_ref");
  83. if (!IS_ERR(fec_enet_ref))
  84. goto put_node;
  85. ptp_clk = of_clk_get(np, 2);
  86. if (IS_ERR(ptp_clk)) {
  87. pr_warn("%s: failed to get ptp clock\n", __func__);
  88. goto put_node;
  89. }
  90. enet_ref = clk_get_sys(NULL, "enet_ref");
  91. if (IS_ERR(enet_ref)) {
  92. pr_warn("%s: failed to get enet clock\n", __func__);
  93. goto put_ptp_clk;
  94. }
  95. /*
  96. * If enet_ref from ANATOP/CCM is the PTP clock source, we need to
  97. * set bit IOMUXC_GPR1[21]. Or the PTP clock must be from pad
  98. * (external OSC), and we need to clear the bit.
  99. */
  100. clksel = clk_is_match(ptp_clk, enet_ref) ?
  101. IMX6Q_GPR1_ENET_CLK_SEL_ANATOP :
  102. IMX6Q_GPR1_ENET_CLK_SEL_PAD;
  103. gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
  104. if (!IS_ERR(gpr))
  105. regmap_update_bits(gpr, IOMUXC_GPR1,
  106. IMX6Q_GPR1_ENET_CLK_SEL_MASK,
  107. clksel);
  108. else
  109. pr_err("failed to find fsl,imx6q-iomuxc-gpr regmap\n");
  110. clk_put(enet_ref);
  111. put_ptp_clk:
  112. clk_put(ptp_clk);
  113. put_node:
  114. of_node_put(np);
  115. }
  116. static void __init imx6q_axi_init(void)
  117. {
  118. struct regmap *gpr;
  119. unsigned int mask;
  120. gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
  121. if (!IS_ERR(gpr)) {
  122. /*
  123. * Enable the cacheable attribute of VPU and IPU
  124. * AXI transactions.
  125. */
  126. mask = IMX6Q_GPR4_VPU_WR_CACHE_SEL |
  127. IMX6Q_GPR4_VPU_RD_CACHE_SEL |
  128. IMX6Q_GPR4_VPU_P_WR_CACHE_VAL |
  129. IMX6Q_GPR4_VPU_P_RD_CACHE_VAL_MASK |
  130. IMX6Q_GPR4_IPU_WR_CACHE_CTL |
  131. IMX6Q_GPR4_IPU_RD_CACHE_CTL;
  132. regmap_update_bits(gpr, IOMUXC_GPR4, mask, mask);
  133. /* Increase IPU read QoS priority */
  134. regmap_update_bits(gpr, IOMUXC_GPR6,
  135. IMX6Q_GPR6_IPU1_ID00_RD_QOS_MASK |
  136. IMX6Q_GPR6_IPU1_ID01_RD_QOS_MASK,
  137. (0xf << 16) | (0x7 << 20));
  138. regmap_update_bits(gpr, IOMUXC_GPR7,
  139. IMX6Q_GPR7_IPU2_ID00_RD_QOS_MASK |
  140. IMX6Q_GPR7_IPU2_ID01_RD_QOS_MASK,
  141. (0xf << 16) | (0x7 << 20));
  142. } else {
  143. pr_warn("failed to find fsl,imx6q-iomuxc-gpr regmap\n");
  144. }
  145. }
  146. static void __init imx6q_init_machine(void)
  147. {
  148. if (cpu_is_imx6q() && imx_get_soc_revision() >= IMX_CHIP_REVISION_2_0)
  149. /*
  150. * SoCs that identify as i.MX6Q >= rev 2.0 are really i.MX6QP.
  151. * Quirk: i.MX6QP revision = i.MX6Q revision - (1, 0),
  152. * e.g. i.MX6QP rev 1.1 identifies as i.MX6Q rev 2.1.
  153. */
  154. imx_print_silicon_rev("i.MX6QP", imx_get_soc_revision() - 0x10);
  155. else
  156. imx_print_silicon_rev(cpu_is_imx6dl() ? "i.MX6DL" : "i.MX6Q",
  157. imx_get_soc_revision());
  158. imx6q_enet_phy_init();
  159. of_platform_default_populate(NULL, NULL, NULL);
  160. imx_anatop_init();
  161. cpu_is_imx6q() ? imx6q_pm_init() : imx6dl_pm_init();
  162. imx6q_1588_init();
  163. imx6q_axi_init();
  164. }
  165. static void __init imx6q_init_late(void)
  166. {
  167. /*
  168. * WAIT mode is broken on imx6 Dual/Quad revision 1.0 and 1.1 so
  169. * there is no point to run cpuidle on them.
  170. *
  171. * It does work on imx6 Solo/DualLite starting from 1.1
  172. */
  173. if ((cpu_is_imx6q() && imx_get_soc_revision() > IMX_CHIP_REVISION_1_1) ||
  174. (cpu_is_imx6dl() && imx_get_soc_revision() > IMX_CHIP_REVISION_1_0))
  175. imx6q_cpuidle_init();
  176. if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
  177. platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
  178. }
  179. static void __init imx6q_map_io(void)
  180. {
  181. debug_ll_io_init();
  182. imx_scu_map_io();
  183. }
  184. static void __init imx6q_init_irq(void)
  185. {
  186. imx_gpc_check_dt();
  187. imx_init_revision_from_anatop();
  188. imx_init_l2cache();
  189. imx_src_init();
  190. irqchip_init();
  191. imx6_pm_ccm_init("fsl,imx6q-ccm");
  192. }
  193. static const char * const imx6q_dt_compat[] __initconst = {
  194. "fsl,imx6dl",
  195. "fsl,imx6q",
  196. "fsl,imx6qp",
  197. NULL,
  198. };
  199. DT_MACHINE_START(IMX6Q, "Freescale i.MX6 Quad/DualLite (Device Tree)")
  200. .l2c_aux_val = 0,
  201. .l2c_aux_mask = ~0,
  202. .smp = smp_ops(imx_smp_ops),
  203. .map_io = imx6q_map_io,
  204. .init_irq = imx6q_init_irq,
  205. .init_machine = imx6q_init_machine,
  206. .init_late = imx6q_init_late,
  207. .dt_compat = imx6q_dt_compat,
  208. MACHINE_END