mach-imx6sx.c 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /*
  2. * Copyright 2014 Freescale Semiconductor, Inc.
  3. *
  4. * This program is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License version 2 as
  6. * published by the Free Software Foundation.
  7. */
  8. #include <linux/irqchip.h>
  9. #include <linux/of_platform.h>
  10. #include <linux/phy.h>
  11. #include <linux/regmap.h>
  12. #include <linux/mfd/syscon.h>
  13. #include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
  14. #include <linux/fec.h>
  15. #include <linux/netdevice.h>
  16. #include <asm/mach/arch.h>
  17. #include <asm/mach/map.h>
  18. #include "common.h"
  19. #include "cpuidle.h"
  20. static struct fec_platform_data fec_pdata[2];
  21. static void imx6sx_fec1_sleep_enable(int enabled)
  22. {
  23. struct regmap *gpr;
  24. gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sx-iomuxc-gpr");
  25. if (!IS_ERR(gpr)) {
  26. if (enabled)
  27. regmap_update_bits(gpr, IOMUXC_GPR4,
  28. IMX6SX_GPR4_FEC_ENET1_STOP_REQ,
  29. IMX6SX_GPR4_FEC_ENET1_STOP_REQ);
  30. else
  31. regmap_update_bits(gpr, IOMUXC_GPR4,
  32. IMX6SX_GPR4_FEC_ENET1_STOP_REQ, 0);
  33. } else
  34. pr_err("failed to find fsl,imx6sx-iomux-gpr regmap\n");
  35. }
  36. static void imx6sx_fec2_sleep_enable(int enabled)
  37. {
  38. struct regmap *gpr;
  39. gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sx-iomuxc-gpr");
  40. if (!IS_ERR(gpr)) {
  41. if (enabled)
  42. regmap_update_bits(gpr, IOMUXC_GPR4,
  43. IMX6SX_GPR4_FEC_ENET2_STOP_REQ,
  44. IMX6SX_GPR4_FEC_ENET2_STOP_REQ);
  45. else
  46. regmap_update_bits(gpr, IOMUXC_GPR4,
  47. IMX6SX_GPR4_FEC_ENET2_STOP_REQ, 0);
  48. } else
  49. pr_err("failed to find fsl,imx6sx-iomux-gpr regmap\n");
  50. }
  51. static void __init imx6sx_enet_plt_init(void)
  52. {
  53. struct device_node *np;
  54. np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000");
  55. if (np && of_get_property(np, "fsl,magic-packet", NULL))
  56. fec_pdata[0].sleep_mode_enable = imx6sx_fec1_sleep_enable;
  57. np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@021b4000");
  58. if (np && of_get_property(np, "fsl,magic-packet", NULL))
  59. fec_pdata[1].sleep_mode_enable = imx6sx_fec2_sleep_enable;
  60. }
  61. static int ar8031_phy_fixup(struct phy_device *dev)
  62. {
  63. u16 val;
  64. /* Set RGMII IO voltage to 1.8V */
  65. phy_write(dev, 0x1d, 0x1f);
  66. phy_write(dev, 0x1e, 0x8);
  67. /* introduce tx clock delay */
  68. phy_write(dev, 0x1d, 0x5);
  69. val = phy_read(dev, 0x1e);
  70. val |= 0x0100;
  71. phy_write(dev, 0x1e, val);
  72. return 0;
  73. }
  74. #define PHY_ID_AR8031 0x004dd074
  75. static void __init imx6sx_enet_phy_init(void)
  76. {
  77. if (IS_BUILTIN(CONFIG_PHYLIB))
  78. phy_register_fixup_for_uid(PHY_ID_AR8031, 0xffffffff,
  79. ar8031_phy_fixup);
  80. }
  81. static void __init imx6sx_enet_clk_sel(void)
  82. {
  83. struct regmap *gpr;
  84. gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sx-iomuxc-gpr");
  85. if (!IS_ERR(gpr)) {
  86. regmap_update_bits(gpr, IOMUXC_GPR1,
  87. IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_MASK, 0);
  88. regmap_update_bits(gpr, IOMUXC_GPR1,
  89. IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK, 0);
  90. } else {
  91. pr_err("failed to find fsl,imx6sx-iomux-gpr regmap\n");
  92. }
  93. }
  94. static inline void imx6sx_enet_init(void)
  95. {
  96. imx6sx_enet_phy_init();
  97. imx6sx_enet_clk_sel();
  98. }
  99. static void __init imx6sx_init_machine(void)
  100. {
  101. struct device *parent;
  102. parent = imx_soc_device_init();
  103. if (parent == NULL)
  104. pr_warn("failed to initialize soc device\n");
  105. of_platform_populate(NULL, of_default_bus_match_table, NULL, parent);
  106. imx6sx_enet_init();
  107. imx_anatop_init();
  108. imx6sx_pm_init();
  109. }
  110. static void __init imx6sx_init_irq(void)
  111. {
  112. imx_init_revision_from_anatop();
  113. imx_init_l2cache();
  114. imx_src_init();
  115. imx_gpc_init();
  116. irqchip_init();
  117. }
  118. static void __init imx6sx_init_late(void)
  119. {
  120. imx6q_cpuidle_init();
  121. if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ))
  122. platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0);
  123. }
  124. static const char * const imx6sx_dt_compat[] __initconst = {
  125. "fsl,imx6sx",
  126. NULL,
  127. };
  128. DT_MACHINE_START(IMX6SX, "Freescale i.MX6 SoloX (Device Tree)")
  129. .init_irq = imx6sx_init_irq,
  130. .init_machine = imx6sx_init_machine,
  131. .dt_compat = imx6sx_dt_compat,
  132. .init_late = imx6sx_init_late,
  133. MACHINE_END