@@ -15,6 +15,8 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <soc/imx/revision.h>
+#include <linux/mfd/syscon.h>
+#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
#include <dt-bindings/clock/imx6qdl-clock.h>
#include "clk.h"
@@ -87,6 +89,8 @@ static const char *pll4_bypass_sels[] = { "pll4", "pll4_bypass_src", };
static const char *pll5_bypass_sels[] = { "pll5", "pll5_bypass_src", };
static const char *pll6_bypass_sels[] = { "pll6", "pll6_bypass_src", };
static const char *pll7_bypass_sels[] = { "pll7", "pll7_bypass_src", };
+static const char * const enet_pad_sels[] = { "anaclk3", "enet_ref", };
+static const char * const enet_ptp_sels[] = { "enet_pad", "enet_ref", };
static struct clk_hw **hws;
static struct clk_hw_onecell_data *clk_hw_data;
@@ -436,6 +440,7 @@ static struct clk_hw * __init imx6q_obtain_fixed_clk_hw(struct device_node *np,
static void __init imx6q_clocks_init(struct device_node *ccm_node)
{
+ struct regmap *gpr;
struct device_node *np;
void __iomem *anatop_base, *base;
int ret;
@@ -464,6 +469,9 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
WARN_ON(!base);
of_node_put(np);
+ gpr = syscon_regmap_lookup_by_compatible("fsl,imx6q-iomuxc-gpr");
+ WARN_ON(IS_ERR_OR_NULL(gpr));
+
/* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */
if (clk_on_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) {
post_div_table[1].div = 1;
@@ -959,6 +967,44 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
/* Audio-related clocks configuration */
clk_set_parent(hws[IMX6QDL_CLK_SPDIF_SEL]->clk, hws[IMX6QDL_CLK_PLL3_PFD3_454M]->clk);
+ /*
+ * The QuadPlus has improved enet clocking:
+ * _
+ * anaclk3---------| \
+ * | | _
+ * |M |--enet_pad-->| \
+ * | | | |
+ * enet_ref---o--->|_/ |M |----enet_ptp
+ * | | |
+ * o---------------------|_/
+ *
+ * On the plus, three options to generate the enet ptp clock:
+ *
+ * a) route enet_ref externally from pad to pad (the default):
+ * enet_ptp from enet_pad
+ * enet_pad from enet_ref
+ * b) route internally on SoC from enet_ref:
+ * enet_ptp from enet_ref
+ * c) route external clock (from PHY or oscillator) via pad:
+ * enet_ptp from enet_pad
+ * enet_pad from anaclk3
+ * anaclk3 from PHY or oscillator, add devicetree node
+ */
+ if (clk_on_imx6qp()) {
+ /*
+ * anaclk3: clock source from external clock via:
+ * - RGMII_TX_CTL PAD (mux mode ENET_REF_CLK), or
+ * - GPIO_16 PAD (mux mode ENET_REF_CLK)
+ */
+ hws[IMX6QDL_CLK_ANACLK3] = imx6q_obtain_fixed_clk_hw(ccm_node, "anaclk3", 0);
+ hws[IMX6QDL_CLK_ENET_PAD] = imx_clk_hw_mux_regmap("enet_pad", gpr, IOMUXC_GPR1, ffs(IMX6Q_GPR1_ENET_CLK_SEL_MASK) - 1,
+ 1, enet_pad_sels, ARRAY_SIZE(enet_pad_sels));
+ hws[IMX6QDL_CLK_ENET_PTP] = imx_clk_hw_mux_regmap("enet_ptp", gpr, IOMUXC_GPR5, ffs(IMX6Q_GPR5_ENET_TXCLK_SEL_MASK) - 1,
+ 1, enet_ptp_sels, ARRAY_SIZE(enet_ptp_sels));
+ clk_set_parent(hws[IMX6QDL_CLK_ENET_PAD]->clk, hws[IMX6QDL_CLK_ENET_REF]->clk);
+ clk_set_parent(hws[IMX6QDL_CLK_ENET_PTP]->clk, hws[IMX6QDL_CLK_ENET_PAD]->clk);
+ }
+
/* All existing boards with PCIe use LVDS1 */
if (IS_ENABLED(CONFIG_PCI_IMX6))
clk_set_parent(hws[IMX6QDL_CLK_LVDS1_SEL]->clk, hws[IMX6QDL_CLK_SATA_REF_100M]->clk);
@@ -240,6 +240,7 @@
#define IMX6Q_GPR4_IPU_RD_CACHE_CTL BIT(0)
#define IMX6Q_GPR5_L2_CLK_STOP BIT(8)
+#define IMX6Q_GPR5_ENET_TXCLK_SEL_MASK BIT(9)
#define IMX6Q_GPR5_SATA_SW_PD BIT(10)
#define IMX6Q_GPR5_SATA_SW_RST BIT(11)
On the imx6q QuadPlus, hardware designers have improved the enet clocking: _ anaclk3---------| \ | | _ |M |--enet_pad-->| \ | | | | enet_ref---o--->|_/ |M |----enet_ptp | | | o---------------------|_/ Where anaclk3 is an external clock fed into the imx6q via a pad, typically RGMII_TX_CTL or GPIO_16, when these are configured in mux mode ENET_REF_CLK. Board designers can now change the clock tree (via the devicetree) to choose between all three supported enet clocking methods. See follow-up devicetree patch for details. Signed-off-by: Sven Van Asbroeck <TheSven73@gmail.com> --- Tree: v5.8-rc4 To: Shawn Guo <shawnguo@kernel.org> To: Sascha Hauer <s.hauer@pengutronix.de> Cc: Pengutronix Kernel Team <kernel@pengutronix.de> Cc: Fabio Estevam <festevam@gmail.com> Cc: NXP Linux Team <linux-imx@nxp.com> Cc: linux-kernel@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-clk@vger.kernel.org drivers/clk/imx/clk-imx6q.c | 46 +++++++++++++++++++++ include/linux/mfd/syscon/imx6q-iomuxc-gpr.h | 1 + 2 files changed, 47 insertions(+)