Thread (42 messages) 42 messages, 3 authors, 2018-10-18

[PATCH V4 11/11] clk: imx: add imx8qxp clk driver

From: sboyd@kernel.org (Stephen Boyd)
Date: 2018-10-16 21:39:02
Also in: linux-clk

Quoting A.s. Dong (2018-10-14 01:08:16)
quoted hunk ↗ jump to hunk
diff --git a/drivers/clk/imx/scu/clk-imx8qxp.c b/drivers/clk/imx/scu/clk-imx8qxp.c
new file mode 100644
index 0000000..958c26d
--- /dev/null
+++ b/drivers/clk/imx/scu/clk-imx8qxp.c
@@ -0,0 +1,425 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017~2018 NXP
+ *     Dong Aisheng <aisheng.dong@nxp.com>
+ */
+
+#include <dt-bindings/clock/imx8qxp-clock.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <soc/imx/imx8qxp/lpcg.h>
+
+#include "clk-scu.h"
+
+static struct clk_hw_onecell_data *clk_data;
Please give this static global variable a more unique name as opposed to
'clk_data'.

+
+static const char * const enet_sels[] = { "enet_25MHz", "enet_125MHz", };
+static const char * const enet0_rmii_tx_sels[] = { "enet0_ref_div", "dummy", };
+static const char * const enet1_rmii_tx_sels[] = { "enet1_ref_div", "dummy", };
+
+static int imx8qxp_clk_probe(struct platform_device *pdev)
+{
+       struct device_node *ccm_node = pdev->dev.of_node;
+       struct clk_hw **clks;
+       int ret;
+
+       ret = imx_clk_scu_init();
+       if (ret)
+               return ret;
+
+       clk_data = devm_kzalloc(&pdev->dev, sizeof(*clk_data) +
+                               sizeof(*clk_data->hws) * IMX8QXP_CLK_END,
+                               GFP_KERNEL);
+       if (!clk_data)
+               return -ENOMEM;
+
+       clk_data->num = IMX8QXP_CLK_END;
+       clks = clk_data->hws;
+
+       /* Fixed clocks */
+       clks[IMX8QXP_CLK_DUMMY]         = imx_clk_hw_fixed("dummy", 0);
+       clks[IMX8QXP_24MHZ]             = imx_clk_hw_fixed("xtal_24MHz", 24000000);
+       clks[IMX8QXP_GPT_3M]            = imx_clk_hw_fixed("gpt_3m", 3000000);
+       clks[IMX8QXP_32KHZ]             = imx_clk_hw_fixed("xtal_32KHz", 32768);
+
+       /* ARM core */
+       clks[IMX8QXP_A35_DIV]           = imx_clk_divider_scu("a35_div", IMX_SC_R_A35, IMX_SC_PM_CLK_CPU);
+
+       clks[IMX8QXP_IPG_DMA_CLK_ROOT]  = imx_clk_hw_fixed("ipg_dma_clk_root", 120000000);
+       clks[IMX8QXP_AXI_CONN_CLK_ROOT] = imx_clk_hw_fixed("axi_conn_clk_root", 333333333);
+       clks[IMX8QXP_AHB_CONN_CLK_ROOT] = imx_clk_hw_fixed("ahb_conn_clk_root", 166666666);
+       clks[IMX8QXP_IPG_CONN_CLK_ROOT] = imx_clk_hw_fixed("ipg_conn_clk_root", 83333333);
+       clks[IMX8QXP_DC_AXI_EXT_CLK]    = imx_clk_hw_fixed("axi_ext_dc_clk_root", 800000000);
+       clks[IMX8QXP_DC_AXI_INT_CLK]    = imx_clk_hw_fixed("axi_int_dc_clk_root", 400000000);
+       clks[IMX8QXP_DC_CFG_CLK]        = imx_clk_hw_fixed("cfg_dc_clk_root", 100000000);
+       clks[IMX8QXP_MIPI_IPG_CLK]      = imx_clk_hw_fixed("ipg_mipi_clk_root", 120000000);
+       clks[IMX8QXP_IMG_AXI_CLK]       = imx_clk_hw_fixed("axi_img_clk_root", 400000000);
+       clks[IMX8QXP_IMG_IPG_CLK]       = imx_clk_hw_fixed("ipg_img_clk_root", 200000000);
+       clks[IMX8QXP_IMG_PXL_CLK]       = imx_clk_hw_fixed("pxl_img_clk_root", 600000000);
+       clks[IMX8QXP_HSIO_AXI_CLK]      = imx_clk_hw_fixed("axi_hsio_clk_root", 400000000);
+       clks[IMX8QXP_HSIO_PER_CLK]      = imx_clk_hw_fixed("per_hsio_clk_root", 133333333);
Can these fixed rate clks come from DT? Or what's going on here?
+
+       clks[IMX8QXP_UART0_DIV]         = imx_clk_divider_scu("uart0_div", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER);
+       clks[IMX8QXP_UART0_IPG_CLK]     = imx_clk_gate2_scu("uart0_ipg_clk", "ipg_dma_clk_root", (void __iomem *)(LPUART_0_LPCG), 16, 0);
+       clks[IMX8QXP_UART0_CLK]         = imx_clk_gate_scu("uart0_clk", "uart0_div", IMX_SC_R_UART_0, IMX_SC_PM_CLK_PER, (void __iomem *)(LPUART_0_LPCG), 0, 0);
+
[...]
+       clks[IMX8QXP_IMG_PDMA_2_CLK]            = imx_clk_gate2_scu("img_pdma2_clk", "pxl_img_clk_root", (void __iomem *)(IMG_PDMA_2_LPCG), 0, 0);
+       clks[IMX8QXP_IMG_PDMA_3_CLK]            = imx_clk_gate2_scu("img_pdma3_clk", "pxl_img_clk_root", (void __iomem *)(IMG_PDMA_3_LPCG), 0, 0);
+       clks[IMX8QXP_IMG_PDMA_4_CLK]            = imx_clk_gate2_scu("img_pdma4_clk", "pxl_img_clk_root", (void __iomem *)(IMG_PDMA_4_LPCG), 0, 0);
+       clks[IMX8QXP_IMG_PDMA_5_CLK]            = imx_clk_gate2_scu("img_pdma5_clk", "pxl_img_clk_root", (void __iomem *)(IMG_PDMA_5_LPCG), 0, 0);
+       clks[IMX8QXP_IMG_PDMA_6_CLK]            = imx_clk_gate2_scu("img_pdma6_clk", "pxl_img_clk_root", (void __iomem *)(IMG_PDMA_6_LPCG), 0, 0);
+       clks[IMX8QXP_IMG_PDMA_7_CLK]            = imx_clk_gate2_scu("img_pdma7_clk", "pxl_img_clk_root", (void __iomem *)(IMG_PDMA_7_LPCG), 0, 0);
All the casts in here shouldn't be necessary, see below.
+
+       /* MIPI CSI SS */
+       clks[IMX8QXP_CSI0_I2C0_DIV]     = imx_clk_divider_scu("mipi_csi0_i2c0_div", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER);
+       clks[IMX8QXP_CSI0_PWM0_DIV]     = imx_clk_divider_scu("mipi_csi0_pwm0_div", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER);
+       clks[IMX8QXP_CSI0_CORE_DIV]     = imx_clk_divider_scu("mipi_csi0_core_div", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER);
+       clks[IMX8QXP_CSI0_ESC_DIV]      = imx_clk_divider_scu("mipi_csi0_esc_div", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC);
+       clks[IMX8QXP_CSI0_IPG_CLK_S]    = imx_clk_gate2_scu("mipi_csi0_ipg_s", "ipg_mipi_csi_clk_root", (void __iomem *)(MIPI_CSI_0_LPCG + 0x8), 16, 0);
+       clks[IMX8QXP_CSI0_IPG_CLK]      = imx_clk_gate2_scu("mipi_csi0_ipg", "mipi_csi0_ipg_s", (void __iomem *)(MIPI_CSI_0_LPCG), 16, 0);
+       clks[IMX8QXP_CSI0_APB_CLK]      = imx_clk_gate2_scu("mipi_csi0_apb_clk", "ipg_mipi_csi_clk_root", (void __iomem *)(MIPI_CSI_0_LPCG + 0x4), 16,  0);
+       clks[IMX8QXP_CSI0_I2C0_IPG_CLK] = imx_clk_gate2_scu("mipi_csi0_i2c0_ipg_s", "ipg_mipi_csi_clk_root", (void __iomem *)(MIPI_CSI_0_LPCG + 0x14), 16, 0);
+       clks[IMX8QXP_CSI0_I2C0_CLK]     = imx_clk_gate_scu("mipi_csi0_i2c0_clk", "mipi_csi0_i2c0_div", IMX_SC_R_CSI_0_I2C_0, IMX_SC_PM_CLK_PER, (void __iomem *)(MIPI_CSI_0_LPCG + 0x14), 0, 0);
+       clks[IMX8QXP_CSI0_PWM0_IPG_CLK] = imx_clk_gate2_scu("mipi_csi0_pwm0_ipg_s", "ipg_mipi_csi_clk_root", (void __iomem *)(MIPI_CSI_0_LPCG + 0x10), 16, 0);
+       clks[IMX8QXP_CSI0_PWM0_CLK]     = imx_clk_gate_scu("mipi_csi0_pwm0_clk", "mipi_csi0_pwm0_div", IMX_SC_R_CSI_0_PWM_0, IMX_SC_PM_CLK_PER, (void __iomem *)(MIPI_CSI_0_LPCG + 0x10), 0, 0);
+       clks[IMX8QXP_CSI0_CORE_CLK]     = imx_clk_gate_scu("mipi_csi0_core_clk", "mipi_csi0_core_div", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_PER, (void __iomem *)(MIPI_CSI_0_LPCG + 0x18), 16, 0);
+       clks[IMX8QXP_CSI0_ESC_CLK]      = imx_clk_gate_scu("mipi_csi0_esc_clk", "mipi_csi0_esc_div", IMX_SC_R_CSI_0, IMX_SC_PM_CLK_MISC, (void __iomem *)(MIPI_CSI_0_LPCG + 0x1C), 16, 0);
+
+       /* HSIO SS */
+       clks[IMX8QXP_HSIO_PCIE_MSTR_AXI_CLK]    = imx_clk_gate2_scu("hsio_pcie_mstr_axi_clk", "axi_hsio_clk_root", (void __iomem *)(HSIO_PCIE_X1_LPCG), 16, 0);
+       clks[IMX8QXP_HSIO_PCIE_SLV_AXI_CLK]     = imx_clk_gate2_scu("hsio_pcie_slv_axi_clk", "axi_hsio_clk_root", (void __iomem *)(HSIO_PCIE_X1_LPCG), 20, 0);
+       clks[IMX8QXP_HSIO_PCIE_DBI_AXI_CLK]     = imx_clk_gate2_scu("hsio_pcie_dbi_axi_clk", "axi_hsio_clk_root", (void __iomem *)(HSIO_PCIE_X1_LPCG), 24, 0);
+       clks[IMX8QXP_HSIO_PCIE_X1_PER_CLK]      = imx_clk_gate2_scu("hsio_pcie_x1_per_clk", "per_hsio_clk_root", (void __iomem *)(HSIO_PCIE_X1_CRR3_LPCG), 16, 0);
+       clks[IMX8QXP_HSIO_PHY_X1_PER_CLK]       = imx_clk_gate2_scu("hsio_phy_x1_per_clk", "per_hsio_clk_root", (void __iomem *)(HSIO_PHY_X1_CRR1_LPCG), 16, 0);
+       clks[IMX8QXP_HSIO_MISC_PER_CLK]         = imx_clk_gate2_scu("hsio_misc_per_clk", "per_hsio_clk_root", (void __iomem *)(HSIO_MISC_LPCG), 16, 0);
+       clks[IMX8QXP_HSIO_PHY_X1_APB_CLK]       = imx_clk_gate2_scu("hsio_phy_x1_apb_clk", "per_hsio_clk_root", (void __iomem *)(HSIO_PHY_X1_LPCG), 16, 0);
+       clks[IMX8QXP_HSIO_GPIO_CLK]             = imx_clk_gate2_scu("hsio_gpio_clk", "per_hsio_clk_root", (void __iomem *)(HSIO_GPIO_LPCG), 16, 0);
+       clks[IMX8QXP_HSIO_PHY_X1_PCLK]          = imx_clk_gate2_scu("hsio_phy_x1_pclk", "dummy", (void __iomem *)(HSIO_PHY_X1_LPCG), 0, 0);
+
+       imx_check_clk_hws(clks, clk_data->num);
+
+       of_clk_add_hw_provider(ccm_node, of_clk_hw_onecell_get, clk_data);
+
+       pr_info("i.MX8QXP clock tree init done.\n");
Please no "I'm alive!" messages.
quoted hunk ↗ jump to hunk
+
+       return 0;
+}
+
+static const struct of_device_id imx8qxp_match[] = {
+       { .compatible = "fsl,imx8qxp-clk", },
+       { /* sentinel */ }
+};
+
+static struct platform_driver imx8qxp_clk_driver = {
+       .driver = {
+               .name = "imx8qxp-clk",
+               .of_match_table = imx8qxp_match,
+       },
+       .probe = imx8qxp_clk_probe,
+};
+
+static int __init imx8qxp_clk_init(void)
+{
+       return platform_driver_register(&imx8qxp_clk_driver);
+}
+core_initcall(imx8qxp_clk_init);
diff --git a/include/soc/imx/imx8qxp/lpcg.h b/include/soc/imx/imx8qxp/lpcg.h
new file mode 100644
index 0000000..afbb5da
--- /dev/null
+++ b/include/soc/imx/imx8qxp/lpcg.h
@@ -0,0 +1,186 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (C) 2016 Freescale Semiconductor, Inc.
+ * Copyright 2017~2018 NXP
+ *
+ */
+
+#ifndef _SC_LPCG_H
+#define _SC_LPCG_H
+
+/*LSIO SS */
+#define                PWM_0_LPCG              0x5D400000
Are these virtual or physical addresses? Because up above they're casted
right into void __iomem pointers, which makes me thing they're virtual
addresses, but then that would mean there's some sort of static iomap
being used, but I'm not aware of anything like that.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help