mbox series

[v4,00/13] Add initial support for the i.MXRTxxxx SoC family starting from i.IMXRT1050 SoC.

Message ID 20211204061042.1248028-1-Mr.Bossman075@gmail.com
Headers show
Series Add initial support for the i.MXRTxxxx SoC family starting from i.IMXRT1050 SoC. | expand

Message

Jesse T Dec. 4, 2021, 6:10 a.m. UTC
This patchset contains:
- i.MXRT10xx family infrastructure
- i.MXRT1050 pinctrl driver adaption
- i.MXRT1050 clock driver adaption
- i.MXRT1050 sd-card driver adaption
- i.MXRT1050 uart driver adaption
- i.MXRT1050-evk basic support

The i.MXRTxxxx family that could have support by Linux actually spreads
from i.MXRT1020 to i.MXRT1170 with the first one supporting 1 USB OTG &
100M ethernet with a cortex-M7@500Mhz up to the latter with i.MXRT1170
with cortex-M7@1Ghz and cortex-M4@400Mhz, 2MB of internal SRAM, 2D GPU,
2x 1Gb and 1x 100Mb ENET. The i.MXRT family is NXP's answer to
STM32F7XX, as it uses only simple SDRAM, it gives the chance of a 4 or
less layer PCBs. Seeing that these chips are comparable to the
STM32F7XXs which have linux ported to them it seems reasonable to add
support for them.

Giving Linux support to this family should ease the development process,
instead of using a RTOS they could use Embedded Linux allowing for more
portability, ease of design and will broaden the scope of people using
embedded linux.

The EVK has very little SDRAM, generally 32MB starting from
i.MXRT1020(the lowest P/N), although the i.MXRT1160/70 provide instead
64MB of SDRAM for more functionality.

At the moment we do not support XIP for either u-boot or Linux but it
should be done in the future. XIP will also save SDRAM.

Another interesting fact is the amount of internal SRAM, as the P/N
increases the SRAM will reach up to 2MB(some could be for cache and
some would be for video).

Also, some parts have embed flash of 4MB that can be used for
u-boot/Linux, if both correctly sized it will leave the SDRAM free.

External flash can be Quad SPI and HyperFlash, so throughput would be
decent.

The i.MXRT11xx series supports MIPI interface too.

The family in general provide CAN bus, audio I/O, 1 or more
USB(otg/host), 1 or more 100Mb/1Gb ethernet, camera interface, sd-card.

All this can be used for simple GUIs, web-servers, point-of-sale
stations, etc.

Giulio Benetti (5):
  ARM: imx: add initial support for i.MXRT10xx family
  pinctrl: freescale: Add i.MXRT1050 pinctrl driver support
  dt-bindings: imx: Add clock binding for i.MXRT1050
  ARM: dts: imx: add i.MXRT1050-EVK support
  ARM: imxrt1050_defconfig: add i.MXRT1050 defconfig

Jesse Taube (8):
  dt-bindings: pinctrl: add i.MXRT1050 pinctrl binding doc
  ARM: dts: imxrt1050-pinfunc: Add pinctrl binding header
  dt-bindings: clock: imx: Add documentation for i.MXRT clock
  clk: imx: Add initial support for i.MXRT clock driver
  dt-bindings: serial: fsl-lpuart: add i.MXRT compatible
  tty: serial: fsl_lpuart: add i.MXRT support
  dt-bindings: mmc: fsl-imx-esdhc: add i.MXRT compatible string
  mmc: sdhci-esdhc-imx: Add sdhc support for i.MXRT series

 .../bindings/clock/imxrt-clock.yaml           |  67 ++
 .../bindings/mmc/fsl-imx-esdhc.yaml           |   1 +
 .../bindings/pinctrl/fsl,imxrt1050.yaml       |  79 ++
 .../bindings/serial/fsl-lpuart.yaml           |   1 +
 arch/arm/boot/dts/Makefile                    |   2 +
 arch/arm/boot/dts/imxrt1050-evk.dts           |  72 ++
 arch/arm/boot/dts/imxrt1050-pinfunc.h         | 993 ++++++++++++++++++
 arch/arm/boot/dts/imxrt1050.dtsi              | 154 +++
 arch/arm/configs/imxrt_defconfig              |  35 +
 arch/arm/mach-imx/Kconfig                     |   7 +
 arch/arm/mach-imx/Makefile                    |   2 +
 arch/arm/mach-imx/mach-imxrt.c                |  19 +
 drivers/clk/imx/Kconfig                       |   5 +
 drivers/clk/imx/Makefile                      |   1 +
 drivers/clk/imx/clk-imxrt1050.c               | 156 +++
 drivers/mmc/host/sdhci-esdhc-imx.c            |   4 +
 drivers/pinctrl/freescale/Kconfig             |   7 +
 drivers/pinctrl/freescale/Makefile            |   1 +
 drivers/pinctrl/freescale/pinctrl-imxrt1050.c | 349 ++++++
 drivers/tty/serial/fsl_lpuart.c               |   8 +
 include/dt-bindings/clock/imxrt1050-clock.h   |  73 ++
 21 files changed, 2036 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/imxrt-clock.yaml
 create mode 100644 Documentation/devicetree/bindings/pinctrl/fsl,imxrt1050.yaml
 create mode 100644 arch/arm/boot/dts/imxrt1050-evk.dts
 create mode 100644 arch/arm/boot/dts/imxrt1050-pinfunc.h
 create mode 100644 arch/arm/boot/dts/imxrt1050.dtsi
 create mode 100644 arch/arm/configs/imxrt_defconfig
 create mode 100644 arch/arm/mach-imx/mach-imxrt.c
 create mode 100644 drivers/clk/imx/clk-imxrt1050.c
 create mode 100644 drivers/pinctrl/freescale/pinctrl-imxrt1050.c
 create mode 100644 include/dt-bindings/clock/imxrt1050-clock.h

Comments

Fabio Estevam Dec. 4, 2021, 10:47 a.m. UTC | #1
Hi Jesse,

On Sat, Dec 4, 2021 at 3:10 AM Jesse Taube <mr.bossman075@gmail.com> wrote:

> Giulio Benetti (5):
>   ARM: imx: add initial support for i.MXRT10xx family
>   pinctrl: freescale: Add i.MXRT1050 pinctrl driver support
>   dt-bindings: imx: Add clock binding for i.MXRT1050
>   ARM: dts: imx: add i.MXRT1050-EVK support
>   ARM: imxrt1050_defconfig: add i.MXRT1050 defconfig
>
> Jesse Taube (8):
>   dt-bindings: pinctrl: add i.MXRT1050 pinctrl binding doc
>   ARM: dts: imxrt1050-pinfunc: Add pinctrl binding header
>   dt-bindings: clock: imx: Add documentation for i.MXRT clock
>   clk: imx: Add initial support for i.MXRT clock driver
>   dt-bindings: serial: fsl-lpuart: add i.MXRT compatible
>   tty: serial: fsl_lpuart: add i.MXRT support
>   dt-bindings: mmc: fsl-imx-esdhc: add i.MXRT compatible string
>   mmc: sdhci-esdhc-imx: Add sdhc support for i.MXRT series

The emmc and pinctrl patches have already been applied and they are available
in linux-next. No need to resend them.
Giulio Benetti Dec. 6, 2021, 8:16 p.m. UTC | #2
Hi Jesse,

On 04/12/21 07:10, Jesse Taube wrote:
> From: Giulio Benetti <giulio.benetti@benettiengineering.com>
> 
> Add i.MXRT1050 defconfig, that will be the basis for the i.MXRT family.

here we need a generic imxrt_defconfig file for i.MXRT1xxx family, like 
sunxi_defconfig, stm32_defconfig etc.

Kind regards
Ulf Hansson Dec. 8, 2021, 10:47 a.m. UTC | #3
On Sat, 4 Dec 2021 at 07:11, Jesse Taube <mr.bossman075@gmail.com> wrote:
>
> From: Jesse Taube <mr.bossman075@gmail.com>
>
> Add support for i.MXRT1050's sdhc.
>
> Cc: Giulio Benetti <giulio.benetti@benettiengineering.com>
> Signed-off-by: Jesse Taube <Mr.Bossman075@gmail.com>
> Reviewed-by: Fabio Estevam <festevam@gmail.com>

No need to resend this, it's already been applied.

Kind regards
Uffe



> ---
> V1->V2:
> * Nothing done
> V2->V3:
> * Rename imxrt to imxrt1050
> * Remove BROKEN_AUTO_CMD23 and MAN_TUNING flags
> V3->V4:
> * Nothing done
> ---
>  drivers/mmc/host/sdhci-esdhc-imx.c | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
> index 764ee1b761d9..55981b0f0b10 100644
> --- a/drivers/mmc/host/sdhci-esdhc-imx.c
> +++ b/drivers/mmc/host/sdhci-esdhc-imx.c
> @@ -305,6 +305,9 @@ static struct esdhc_soc_data usdhc_imx7ulp_data = {
>                         | ESDHC_FLAG_PMQOS | ESDHC_FLAG_HS400
>                         | ESDHC_FLAG_STATE_LOST_IN_LPMODE,
>  };
> +static struct esdhc_soc_data usdhc_imxrt1050_data = {
> +       .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_HS200 | ESDHC_FLAG_ERR004536,
> +};
>
>  static struct esdhc_soc_data usdhc_imx8qxp_data = {
>         .flags = ESDHC_FLAG_USDHC | ESDHC_FLAG_STD_TUNING
> @@ -355,6 +358,7 @@ static const struct of_device_id imx_esdhc_dt_ids[] = {
>         { .compatible = "fsl,imx7ulp-usdhc", .data = &usdhc_imx7ulp_data, },
>         { .compatible = "fsl,imx8qxp-usdhc", .data = &usdhc_imx8qxp_data, },
>         { .compatible = "fsl,imx8mm-usdhc", .data = &usdhc_imx8mm_data, },
> +       { .compatible = "fsl,imxrt1050-usdhc", .data = &usdhc_imxrt1050_data, },
>         { .compatible = "nxp,s32g2-usdhc", .data = &usdhc_s32g2_data, },
>         { /* sentinel */ }
>  };
> --
> 2.34.0
>
Abel Vesa Dec. 13, 2021, 11:30 a.m. UTC | #4
On 21-12-04 01:10:36, Jesse Taube wrote:
> Add clock driver support for i.MXRT1***s starting with the i.MXRT1050.
> 
> Signed-off-by: Jesse Taube <Mr.Bossman075@gmail.com>
> Suggested-by: Giulio Benetti <giulio.benetti@benettiengineering.com>
> ---
> V1->V2:
> * Kconfig: Add new line
> * clk-imxrt.c: Remove unused const
> * clk-imxrt.c: Remove set parents
> * clk-imxrt.c: Use fsl,imxrt-anatop for anatop base address
> V2->V3:
> * Remove unused ANATOP_BASE_ADDR
> * Move to hw API
> * Add GPT's own clock
> * Add SEMC clocks to set muxing to CRITICAL
> V3->V4:
> * Rename clk-imxrt.c to clk-imxrt1050.c
> * Rename CONFIG_CLK_IMXRT to CONFIG_CLK_IMXRT1050
> * Make CONFIG_CLK_IMXRT1050 selectable
> ---
>  drivers/clk/imx/Kconfig         |   5 +
>  drivers/clk/imx/Makefile        |   1 +
>  drivers/clk/imx/clk-imxrt1050.c | 156 ++++++++++++++++++++++++++++++++
>  3 files changed, 162 insertions(+)
>  create mode 100644 drivers/clk/imx/clk-imxrt1050.c
> 
> diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig
> index c08edbd04d22..f697652ab19c 100644
> --- a/drivers/clk/imx/Kconfig
> +++ b/drivers/clk/imx/Kconfig
> @@ -105,3 +105,8 @@ config CLK_IMX8ULP
>  	select MXC_CLK
>  	help
>  	    Build the driver for i.MX8ULP CCM Clock Driver
> +
> +config CLK_IMXRT1050
> +	bool "IMXRT1050 CCM Clock Driver"
> +	depends on SOC_IMXRT
> +	select MXC_CLK
> diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
> index b5e040026dfb..3d9a1e3b5fc6 100644
> --- a/drivers/clk/imx/Makefile
> +++ b/drivers/clk/imx/Makefile
> @@ -47,3 +47,4 @@ obj-$(CONFIG_CLK_IMX6UL) += clk-imx6ul.o
>  obj-$(CONFIG_CLK_IMX7D)  += clk-imx7d.o
>  obj-$(CONFIG_CLK_IMX7ULP) += clk-imx7ulp.o
>  obj-$(CONFIG_CLK_VF610)  += clk-vf610.o
> +obj-$(CONFIG_CLK_IMXRT1050)  += clk-imxrt1050.o
> diff --git a/drivers/clk/imx/clk-imxrt1050.c b/drivers/clk/imx/clk-imxrt1050.c
> new file mode 100644
> index 000000000000..85ba1a240335
> --- /dev/null
> +++ b/drivers/clk/imx/clk-imxrt1050.c
> @@ -0,0 +1,156 @@
> +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
> +/*
> + * Copyright (C) 2021
> + * Author(s):
> + * Jesse Taube <Mr.Bossman075@gmail.com>
> + * Giulio Benetti <giulio.benetti@benettiengineering.com>
> + */
> +#include <linux/mm.h>
> +#include <linux/delay.h>
> +#include <linux/clk.h>
> +#include <linux/io.h>
> +#include <linux/clkdev.h>
> +#include <linux/clk-provider.h>
> +#include <linux/err.h>
> +#include <linux/of.h>
> +#include <linux/of_address.h>
> +#include <linux/of_irq.h>
> +#include <linux/sizes.h>
> +#include <soc/imx/revision.h>
> +#include <dt-bindings/clock/imxrt1050-clock.h>
> +
> +#include "clk.h"
> +
> +static const char * const pll_ref_sels[] = {"osc", "dummy", };
> +static const char * const per_sels[] = {"ipg_pdof", "osc", };
> +static const char * const pll1_bypass_sels[] = {"pll1_arm", "pll1_arm_ref_sel", };
> +static const char * const pll2_bypass_sels[] = {"pll2_sys", "pll2_sys_ref_sel", };
> +static const char * const pll3_bypass_sels[] = {"pll3_usb_otg", "pll3_usb_otg_ref_sel", };
> +static const char * const pll5_bypass_sels[] = {"pll5_video", "pll5_video_ref_sel", };
> +static const char *const pre_periph_sels[] = {
> +	"pll2_sys", "pll2_pfd2_396m", "pll2_pfd0_352m", "arm_podf", };
> +static const char *const periph_sels[] = { "pre_periph_sel", "todo", };
> +static const char *const usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
> +static const char *const lpuart_sels[] = { "pll3_80m", "osc", };
> +static const char *const lcdif_sels[] = {
> +	"pll2_sys", "pll3_pfd3_454_74m", "pll5_video", "pll2_pfd0_352m",
> +	"pll2_pfd1_594m", "pll3_pfd1_664_62m", };
> +static const char *const semc_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_664_62m", };
> +static const char *const semc_sels[] = { "periph_sel", "semc_alt_sel", };
> +
> +static struct clk_hw **hws;
> +static struct clk_hw_onecell_data *clk_hw_data;
> +
> +static void __init imxrt_clocks_common_init(void __iomem *base)
> +{
> +	/* Anatop clocks */
> +	hws[IMXRT1050_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0UL);
> +
> +	hws[IMXRT1050_CLK_PLL1_REF_SEL] = imx_clk_hw_mux("pll1_arm_ref_sel",
> +		base + 0x0, 14, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
> +	hws[IMXRT1050_CLK_PLL2_REF_SEL] = imx_clk_hw_mux("pll2_sys_ref_sel",
> +		base + 0x30, 14, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
> +	hws[IMXRT1050_CLK_PLL3_REF_SEL] = imx_clk_hw_mux("pll3_usb_otg_ref_sel",
> +		base + 0x10, 14, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
> +	hws[IMXRT1050_CLK_PLL5_REF_SEL] = imx_clk_hw_mux("pll5_video_ref_sel",
> +		base + 0xa0, 14, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
> +
> +	hws[IMXRT1050_CLK_PLL1_ARM] = imx_clk_hw_pllv3(IMX_PLLV3_SYS, "pll1_arm",
> +		"pll1_arm_ref_sel", base + 0x0, 0x7f);
> +	hws[IMXRT1050_CLK_PLL2_SYS] = imx_clk_hw_pllv3(IMX_PLLV3_GENERIC, "pll2_sys",
> +		"pll2_sys_ref_sel", base + 0x30, 0x1);
> +	hws[IMXRT1050_CLK_PLL3_USB_OTG] = imx_clk_hw_pllv3(IMX_PLLV3_USB, "pll3_usb_otg",
> +		"pll3_usb_otg_ref_sel", base + 0x10, 0x1);
> +	hws[IMXRT1050_CLK_PLL5_VIDEO] = imx_clk_hw_pllv3(IMX_PLLV3_AV, "pll5_video",
> +		"pll5_video_ref_sel", base + 0xa0, 0x7f);
> +
> +	/* PLL bypass out */
> +	hws[IMXRT1050_CLK_PLL1_BYPASS] = imx_clk_hw_mux_flags("pll1_bypass", base + 0x0, 16, 1,
> +		pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
> +	hws[IMXRT1050_CLK_PLL2_BYPASS] = imx_clk_hw_mux_flags("pll2_bypass", base + 0x30, 16, 1,
> +		pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
> +	hws[IMXRT1050_CLK_PLL3_BYPASS] = imx_clk_hw_mux_flags("pll3_bypass", base + 0x10, 16, 1,
> +		pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
> +	hws[IMXRT1050_CLK_PLL5_BYPASS] = imx_clk_hw_mux_flags("pll5_bypass", base + 0xa0, 16, 1,
> +		pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
> +
> +	hws[IMXRT1050_CLK_VIDEO_POST_DIV_SEL] = imx_clk_hw_divider("video_post_div_sel",
> +		"pll5_video", base + 0xa0, 19, 2);
> +	hws[IMXRT1050_CLK_VIDEO_DIV] = imx_clk_hw_divider("video_div",
> +		"video_post_div_sel", base + 0x170, 30, 2);
> +
> +	hws[IMXRT1050_CLK_PLL3_80M] = imx_clk_hw_fixed_factor("pll3_80m",  "pll3_usb_otg", 1, 6);
> +
> +	hws[IMXRT1050_CLK_PLL2_PFD0_352M] = imx_clk_hw_pfd("pll2_pfd0_352m", "pll2_sys", base + 0x100, 0);
> +	hws[IMXRT1050_CLK_PLL2_PFD1_594M] = imx_clk_hw_pfd("pll2_pfd1_594m", "pll2_sys", base + 0x100, 1);
> +	hws[IMXRT1050_CLK_PLL2_PFD2_396M] = imx_clk_hw_pfd("pll2_pfd2_396m", "pll2_sys", base + 0x100, 2);
> +	hws[IMXRT1050_CLK_PLL3_PFD1_664_62M] = imx_clk_hw_pfd("pll3_pfd1_664_62m", "pll3_usb_otg", base + 0xf0, 1);
> +	hws[IMXRT1050_CLK_PLL3_PFD3_454_74M] = imx_clk_hw_pfd("pll3_pfd3_454_74m", "pll3_usb_otg", base + 0xf0, 3);
> +}
> +
> +static void __init imxrt1050_clocks_init(struct device_node *np)
> +{
> +	void __iomem *ccm_base;
> +	void __iomem *pll_base;
> +	struct device_node *anp;
> +
> +	clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
> +					  IMXRT1050_CLK_END), GFP_KERNEL);
> +	if (WARN_ON(!clk_hw_data))
> +		return;
> +
> +	clk_hw_data->num = IMXRT1050_CLK_END;
> +	hws = clk_hw_data->hws;
> +
> +	hws[IMXRT1050_CLK_OSC] = __clk_get_hw(of_clk_get_by_name(np, "osc"));
> +
> +	anp = of_find_compatible_node(NULL, NULL, "fsl,imxrt-anatop");
> +	pll_base = of_iomap(anp, 0);
> +	WARN_ON(!pll_base);
> +	imxrt_clocks_common_init(pll_base);
> +	/* CCM clocks */
> +	ccm_base = of_iomap(np, 0);
> +	WARN_ON(!ccm_base);
> +
> +	hws[IMXRT1050_CLK_ARM_PODF] = imx_clk_hw_divider("arm_podf", "pll1_arm", ccm_base + 0x10, 0, 3);
> +	hws[IMXRT1050_CLK_PRE_PERIPH_SEL] = imx_clk_hw_mux("pre_periph_sel", ccm_base + 0x18, 18, 2,
> +		pre_periph_sels, ARRAY_SIZE(pre_periph_sels));
> +	hws[IMXRT1050_CLK_PERIPH_SEL] = imx_clk_hw_mux("periph_sel", ccm_base + 0x14, 25, 1,
> +		periph_sels, ARRAY_SIZE(periph_sels));
> +	hws[IMXRT1050_CLK_USDHC1_SEL] = imx_clk_hw_mux("usdhc1_sel", ccm_base + 0x1c, 16, 1,
> +		usdhc_sels, ARRAY_SIZE(usdhc_sels));
> +	hws[IMXRT1050_CLK_USDHC2_SEL] = imx_clk_hw_mux("usdhc2_sel", ccm_base + 0x1c, 17, 1,
> +		usdhc_sels, ARRAY_SIZE(usdhc_sels));
> +	hws[IMXRT1050_CLK_LPUART_SEL] = imx_clk_hw_mux("lpuart_sel", ccm_base + 0x24, 6, 1,
> +		lpuart_sels, ARRAY_SIZE(lpuart_sels));
> +	hws[IMXRT1050_CLK_LCDIF_SEL] = imx_clk_hw_mux("lcdif_sel", ccm_base + 0x38, 15, 3,
> +		lcdif_sels, ARRAY_SIZE(lcdif_sels));
> +	hws[IMXRT1050_CLK_PER_CLK_SEL] = imx_clk_hw_mux("per_sel", ccm_base + 0x1C, 6, 1,
> +		per_sels, ARRAY_SIZE(per_sels));
> +	hws[IMXRT1050_CLK_SEMC_ALT_SEL] = imx_clk_hw_mux("semc_alt_sel", ccm_base + 0x14, 7, 1,
> +		semc_alt_sels, ARRAY_SIZE(semc_alt_sels));
> +	hws[IMXRT1050_CLK_SEMC_SEL] = imx_clk_hw_mux_flags("semc_sel", ccm_base + 0x14, 6, 1,
> +		semc_sels, ARRAY_SIZE(semc_sels), CLK_IS_CRITICAL);
> +
> +	hws[IMXRT1050_CLK_AHB_PODF] = imx_clk_hw_divider("ahb", "periph_sel", ccm_base + 0x14, 10, 3);
> +	hws[IMXRT1050_CLK_IPG_PDOF] = imx_clk_hw_divider("ipg", "ahb", ccm_base + 0x14, 8, 2);
> +	hws[IMXRT1050_CLK_PER_PDOF] = imx_clk_hw_divider("per", "per_sel", ccm_base + 0x1C, 0, 5);
> +
> +	hws[IMXRT1050_CLK_USDHC1_PODF] = imx_clk_hw_divider("usdhc1_podf", "usdhc1_sel", ccm_base + 0x24, 11, 3);
> +	hws[IMXRT1050_CLK_USDHC2_PODF] = imx_clk_hw_divider("usdhc2_podf", "usdhc2_sel", ccm_base + 0x24, 16, 3);
> +	hws[IMXRT1050_CLK_LPUART_PODF] = imx_clk_hw_divider("lpuart_podf", "lpuart_sel", ccm_base + 0x24, 0, 6);
> +	hws[IMXRT1050_CLK_LCDIF_PRED] = imx_clk_hw_divider("lcdif_pred", "lcdif_sel", ccm_base + 0x38, 12, 3);
> +	hws[IMXRT1050_CLK_LCDIF_PODF] = imx_clk_hw_divider("lcdif_podf", "lcdif_pred", ccm_base + 0x18, 23, 3);
> +
> +	hws[IMXRT1050_CLK_USDHC1] = imx_clk_hw_gate2("usdhc1", "usdhc1_podf", ccm_base + 0x80, 2);
> +	hws[IMXRT1050_CLK_USDHC2] = imx_clk_hw_gate2("usdhc2", "usdhc2_podf", ccm_base + 0x80, 4);
> +	hws[IMXRT1050_CLK_LPUART1] = imx_clk_hw_gate2("lpuart1", "lpuart_podf", ccm_base + 0x7c, 24);
> +	hws[IMXRT1050_CLK_LCDIF_APB] = imx_clk_hw_gate2("lcdif", "lcdif_podf", ccm_base + 0x74, 10);
> +	hws[IMXRT1050_CLK_DMA] = imx_clk_hw_gate("dma", "ipg", ccm_base + 0x7C, 6);
> +	hws[IMXRT1050_CLK_DMA_MUX] = imx_clk_hw_gate("dmamux0", "ipg", ccm_base + 0x7C, 7);
> +	hws[IMXRT1050_CLK_GPT] = imx_clk_hw_fixed_factor("gpt", "osc", 1, 8);
> +	imx_check_clk_hws(hws, IMXRT1050_CLK_END);
> +
> +	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
> +}
> +CLK_OF_DECLARE(imxrt_ccm, "fsl,imxrt1050-ccm", imxrt1050_clocks_init);

I would suggest module platform driver instead.

Sorry for the late review.

> -- 
> 2.34.0
>
Giulio Benetti Dec. 13, 2021, 12:05 p.m. UTC | #5
Hi Abel,

On 13/12/21 12:30, Abel Vesa wrote:
> On 21-12-04 01:10:36, Jesse Taube wrote:
>> Add clock driver support for i.MXRT1***s starting with the i.MXRT1050.
>>
>> Signed-off-by: Jesse Taube <Mr.Bossman075@gmail.com>
>> Suggested-by: Giulio Benetti <giulio.benetti@benettiengineering.com>
>> ---
>> V1->V2:
>> * Kconfig: Add new line
>> * clk-imxrt.c: Remove unused const
>> * clk-imxrt.c: Remove set parents
>> * clk-imxrt.c: Use fsl,imxrt-anatop for anatop base address
>> V2->V3:
>> * Remove unused ANATOP_BASE_ADDR
>> * Move to hw API
>> * Add GPT's own clock
>> * Add SEMC clocks to set muxing to CRITICAL
>> V3->V4:
>> * Rename clk-imxrt.c to clk-imxrt1050.c
>> * Rename CONFIG_CLK_IMXRT to CONFIG_CLK_IMXRT1050
>> * Make CONFIG_CLK_IMXRT1050 selectable
>> ---
>>   drivers/clk/imx/Kconfig         |   5 +
>>   drivers/clk/imx/Makefile        |   1 +
>>   drivers/clk/imx/clk-imxrt1050.c | 156 ++++++++++++++++++++++++++++++++
>>   3 files changed, 162 insertions(+)
>>   create mode 100644 drivers/clk/imx/clk-imxrt1050.c
>>
>> diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig
>> index c08edbd04d22..f697652ab19c 100644
>> --- a/drivers/clk/imx/Kconfig
>> +++ b/drivers/clk/imx/Kconfig
>> @@ -105,3 +105,8 @@ config CLK_IMX8ULP
>>   	select MXC_CLK
>>   	help
>>   	    Build the driver for i.MX8ULP CCM Clock Driver
>> +
>> +config CLK_IMXRT1050
>> +	bool "IMXRT1050 CCM Clock Driver"
>> +	depends on SOC_IMXRT
>> +	select MXC_CLK
>> diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
>> index b5e040026dfb..3d9a1e3b5fc6 100644
>> --- a/drivers/clk/imx/Makefile
>> +++ b/drivers/clk/imx/Makefile
>> @@ -47,3 +47,4 @@ obj-$(CONFIG_CLK_IMX6UL) += clk-imx6ul.o
>>   obj-$(CONFIG_CLK_IMX7D)  += clk-imx7d.o
>>   obj-$(CONFIG_CLK_IMX7ULP) += clk-imx7ulp.o
>>   obj-$(CONFIG_CLK_VF610)  += clk-vf610.o
>> +obj-$(CONFIG_CLK_IMXRT1050)  += clk-imxrt1050.o
>> diff --git a/drivers/clk/imx/clk-imxrt1050.c b/drivers/clk/imx/clk-imxrt1050.c
>> new file mode 100644
>> index 000000000000..85ba1a240335
>> --- /dev/null
>> +++ b/drivers/clk/imx/clk-imxrt1050.c
>> @@ -0,0 +1,156 @@
>> +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
>> +/*
>> + * Copyright (C) 2021
>> + * Author(s):
>> + * Jesse Taube <Mr.Bossman075@gmail.com>
>> + * Giulio Benetti <giulio.benetti@benettiengineering.com>
>> + */
>> +#include <linux/mm.h>
>> +#include <linux/delay.h>
>> +#include <linux/clk.h>
>> +#include <linux/io.h>
>> +#include <linux/clkdev.h>
>> +#include <linux/clk-provider.h>
>> +#include <linux/err.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_irq.h>
>> +#include <linux/sizes.h>
>> +#include <soc/imx/revision.h>
>> +#include <dt-bindings/clock/imxrt1050-clock.h>
>> +
>> +#include "clk.h"
>> +
>> +static const char * const pll_ref_sels[] = {"osc", "dummy", };
>> +static const char * const per_sels[] = {"ipg_pdof", "osc", };
>> +static const char * const pll1_bypass_sels[] = {"pll1_arm", "pll1_arm_ref_sel", };
>> +static const char * const pll2_bypass_sels[] = {"pll2_sys", "pll2_sys_ref_sel", };
>> +static const char * const pll3_bypass_sels[] = {"pll3_usb_otg", "pll3_usb_otg_ref_sel", };
>> +static const char * const pll5_bypass_sels[] = {"pll5_video", "pll5_video_ref_sel", };
>> +static const char *const pre_periph_sels[] = {
>> +	"pll2_sys", "pll2_pfd2_396m", "pll2_pfd0_352m", "arm_podf", };
>> +static const char *const periph_sels[] = { "pre_periph_sel", "todo", };
>> +static const char *const usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
>> +static const char *const lpuart_sels[] = { "pll3_80m", "osc", };
>> +static const char *const lcdif_sels[] = {
>> +	"pll2_sys", "pll3_pfd3_454_74m", "pll5_video", "pll2_pfd0_352m",
>> +	"pll2_pfd1_594m", "pll3_pfd1_664_62m", };
>> +static const char *const semc_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_664_62m", };
>> +static const char *const semc_sels[] = { "periph_sel", "semc_alt_sel", };
>> +
>> +static struct clk_hw **hws;
>> +static struct clk_hw_onecell_data *clk_hw_data;
>> +
>> +static void __init imxrt_clocks_common_init(void __iomem *base)
>> +{
>> +	/* Anatop clocks */
>> +	hws[IMXRT1050_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0UL);
>> +
>> +	hws[IMXRT1050_CLK_PLL1_REF_SEL] = imx_clk_hw_mux("pll1_arm_ref_sel",
>> +		base + 0x0, 14, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
>> +	hws[IMXRT1050_CLK_PLL2_REF_SEL] = imx_clk_hw_mux("pll2_sys_ref_sel",
>> +		base + 0x30, 14, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
>> +	hws[IMXRT1050_CLK_PLL3_REF_SEL] = imx_clk_hw_mux("pll3_usb_otg_ref_sel",
>> +		base + 0x10, 14, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
>> +	hws[IMXRT1050_CLK_PLL5_REF_SEL] = imx_clk_hw_mux("pll5_video_ref_sel",
>> +		base + 0xa0, 14, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
>> +
>> +	hws[IMXRT1050_CLK_PLL1_ARM] = imx_clk_hw_pllv3(IMX_PLLV3_SYS, "pll1_arm",
>> +		"pll1_arm_ref_sel", base + 0x0, 0x7f);
>> +	hws[IMXRT1050_CLK_PLL2_SYS] = imx_clk_hw_pllv3(IMX_PLLV3_GENERIC, "pll2_sys",
>> +		"pll2_sys_ref_sel", base + 0x30, 0x1);
>> +	hws[IMXRT1050_CLK_PLL3_USB_OTG] = imx_clk_hw_pllv3(IMX_PLLV3_USB, "pll3_usb_otg",
>> +		"pll3_usb_otg_ref_sel", base + 0x10, 0x1);
>> +	hws[IMXRT1050_CLK_PLL5_VIDEO] = imx_clk_hw_pllv3(IMX_PLLV3_AV, "pll5_video",
>> +		"pll5_video_ref_sel", base + 0xa0, 0x7f);
>> +
>> +	/* PLL bypass out */
>> +	hws[IMXRT1050_CLK_PLL1_BYPASS] = imx_clk_hw_mux_flags("pll1_bypass", base + 0x0, 16, 1,
>> +		pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
>> +	hws[IMXRT1050_CLK_PLL2_BYPASS] = imx_clk_hw_mux_flags("pll2_bypass", base + 0x30, 16, 1,
>> +		pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
>> +	hws[IMXRT1050_CLK_PLL3_BYPASS] = imx_clk_hw_mux_flags("pll3_bypass", base + 0x10, 16, 1,
>> +		pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
>> +	hws[IMXRT1050_CLK_PLL5_BYPASS] = imx_clk_hw_mux_flags("pll5_bypass", base + 0xa0, 16, 1,
>> +		pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
>> +
>> +	hws[IMXRT1050_CLK_VIDEO_POST_DIV_SEL] = imx_clk_hw_divider("video_post_div_sel",
>> +		"pll5_video", base + 0xa0, 19, 2);
>> +	hws[IMXRT1050_CLK_VIDEO_DIV] = imx_clk_hw_divider("video_div",
>> +		"video_post_div_sel", base + 0x170, 30, 2);
>> +
>> +	hws[IMXRT1050_CLK_PLL3_80M] = imx_clk_hw_fixed_factor("pll3_80m",  "pll3_usb_otg", 1, 6);
>> +
>> +	hws[IMXRT1050_CLK_PLL2_PFD0_352M] = imx_clk_hw_pfd("pll2_pfd0_352m", "pll2_sys", base + 0x100, 0);
>> +	hws[IMXRT1050_CLK_PLL2_PFD1_594M] = imx_clk_hw_pfd("pll2_pfd1_594m", "pll2_sys", base + 0x100, 1);
>> +	hws[IMXRT1050_CLK_PLL2_PFD2_396M] = imx_clk_hw_pfd("pll2_pfd2_396m", "pll2_sys", base + 0x100, 2);
>> +	hws[IMXRT1050_CLK_PLL3_PFD1_664_62M] = imx_clk_hw_pfd("pll3_pfd1_664_62m", "pll3_usb_otg", base + 0xf0, 1);
>> +	hws[IMXRT1050_CLK_PLL3_PFD3_454_74M] = imx_clk_hw_pfd("pll3_pfd3_454_74m", "pll3_usb_otg", base + 0xf0, 3);
>> +}
>> +
>> +static void __init imxrt1050_clocks_init(struct device_node *np)
>> +{
>> +	void __iomem *ccm_base;
>> +	void __iomem *pll_base;
>> +	struct device_node *anp;
>> +
>> +	clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
>> +					  IMXRT1050_CLK_END), GFP_KERNEL);
>> +	if (WARN_ON(!clk_hw_data))
>> +		return;
>> +
>> +	clk_hw_data->num = IMXRT1050_CLK_END;
>> +	hws = clk_hw_data->hws;
>> +
>> +	hws[IMXRT1050_CLK_OSC] = __clk_get_hw(of_clk_get_by_name(np, "osc"));
>> +
>> +	anp = of_find_compatible_node(NULL, NULL, "fsl,imxrt-anatop");
>> +	pll_base = of_iomap(anp, 0);
>> +	WARN_ON(!pll_base);
>> +	imxrt_clocks_common_init(pll_base);
>> +	/* CCM clocks */
>> +	ccm_base = of_iomap(np, 0);
>> +	WARN_ON(!ccm_base);
>> +
>> +	hws[IMXRT1050_CLK_ARM_PODF] = imx_clk_hw_divider("arm_podf", "pll1_arm", ccm_base + 0x10, 0, 3);
>> +	hws[IMXRT1050_CLK_PRE_PERIPH_SEL] = imx_clk_hw_mux("pre_periph_sel", ccm_base + 0x18, 18, 2,
>> +		pre_periph_sels, ARRAY_SIZE(pre_periph_sels));
>> +	hws[IMXRT1050_CLK_PERIPH_SEL] = imx_clk_hw_mux("periph_sel", ccm_base + 0x14, 25, 1,
>> +		periph_sels, ARRAY_SIZE(periph_sels));
>> +	hws[IMXRT1050_CLK_USDHC1_SEL] = imx_clk_hw_mux("usdhc1_sel", ccm_base + 0x1c, 16, 1,
>> +		usdhc_sels, ARRAY_SIZE(usdhc_sels));
>> +	hws[IMXRT1050_CLK_USDHC2_SEL] = imx_clk_hw_mux("usdhc2_sel", ccm_base + 0x1c, 17, 1,
>> +		usdhc_sels, ARRAY_SIZE(usdhc_sels));
>> +	hws[IMXRT1050_CLK_LPUART_SEL] = imx_clk_hw_mux("lpuart_sel", ccm_base + 0x24, 6, 1,
>> +		lpuart_sels, ARRAY_SIZE(lpuart_sels));
>> +	hws[IMXRT1050_CLK_LCDIF_SEL] = imx_clk_hw_mux("lcdif_sel", ccm_base + 0x38, 15, 3,
>> +		lcdif_sels, ARRAY_SIZE(lcdif_sels));
>> +	hws[IMXRT1050_CLK_PER_CLK_SEL] = imx_clk_hw_mux("per_sel", ccm_base + 0x1C, 6, 1,
>> +		per_sels, ARRAY_SIZE(per_sels));
>> +	hws[IMXRT1050_CLK_SEMC_ALT_SEL] = imx_clk_hw_mux("semc_alt_sel", ccm_base + 0x14, 7, 1,
>> +		semc_alt_sels, ARRAY_SIZE(semc_alt_sels));
>> +	hws[IMXRT1050_CLK_SEMC_SEL] = imx_clk_hw_mux_flags("semc_sel", ccm_base + 0x14, 6, 1,
>> +		semc_sels, ARRAY_SIZE(semc_sels), CLK_IS_CRITICAL);
>> +
>> +	hws[IMXRT1050_CLK_AHB_PODF] = imx_clk_hw_divider("ahb", "periph_sel", ccm_base + 0x14, 10, 3);
>> +	hws[IMXRT1050_CLK_IPG_PDOF] = imx_clk_hw_divider("ipg", "ahb", ccm_base + 0x14, 8, 2);
>> +	hws[IMXRT1050_CLK_PER_PDOF] = imx_clk_hw_divider("per", "per_sel", ccm_base + 0x1C, 0, 5);
>> +
>> +	hws[IMXRT1050_CLK_USDHC1_PODF] = imx_clk_hw_divider("usdhc1_podf", "usdhc1_sel", ccm_base + 0x24, 11, 3);
>> +	hws[IMXRT1050_CLK_USDHC2_PODF] = imx_clk_hw_divider("usdhc2_podf", "usdhc2_sel", ccm_base + 0x24, 16, 3);
>> +	hws[IMXRT1050_CLK_LPUART_PODF] = imx_clk_hw_divider("lpuart_podf", "lpuart_sel", ccm_base + 0x24, 0, 6);
>> +	hws[IMXRT1050_CLK_LCDIF_PRED] = imx_clk_hw_divider("lcdif_pred", "lcdif_sel", ccm_base + 0x38, 12, 3);
>> +	hws[IMXRT1050_CLK_LCDIF_PODF] = imx_clk_hw_divider("lcdif_podf", "lcdif_pred", ccm_base + 0x18, 23, 3);
>> +
>> +	hws[IMXRT1050_CLK_USDHC1] = imx_clk_hw_gate2("usdhc1", "usdhc1_podf", ccm_base + 0x80, 2);
>> +	hws[IMXRT1050_CLK_USDHC2] = imx_clk_hw_gate2("usdhc2", "usdhc2_podf", ccm_base + 0x80, 4);
>> +	hws[IMXRT1050_CLK_LPUART1] = imx_clk_hw_gate2("lpuart1", "lpuart_podf", ccm_base + 0x7c, 24);
>> +	hws[IMXRT1050_CLK_LCDIF_APB] = imx_clk_hw_gate2("lcdif", "lcdif_podf", ccm_base + 0x74, 10);
>> +	hws[IMXRT1050_CLK_DMA] = imx_clk_hw_gate("dma", "ipg", ccm_base + 0x7C, 6);
>> +	hws[IMXRT1050_CLK_DMA_MUX] = imx_clk_hw_gate("dmamux0", "ipg", ccm_base + 0x7C, 7);
>> +	hws[IMXRT1050_CLK_GPT] = imx_clk_hw_fixed_factor("gpt", "osc", 1, 8);
>> +	imx_check_clk_hws(hws, IMXRT1050_CLK_END);
>> +
>> +	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
>> +}
>> +CLK_OF_DECLARE(imxrt_ccm, "fsl,imxrt1050-ccm", imxrt1050_clocks_init);
> 
> I would suggest module platform driver instead.

Can you please point us an example?

> Sorry for the late review.

No problem

Thank you
Best regards
Giulio Benetti Dec. 13, 2021, 12:11 p.m. UTC | #6
Hi Abel, Jesse,

On 13/12/21 13:05, Giulio Benetti wrote:
> Hi Abel,
> 
> On 13/12/21 12:30, Abel Vesa wrote:
>> On 21-12-04 01:10:36, Jesse Taube wrote:
>>> Add clock driver support for i.MXRT1***s starting with the i.MXRT1050.
>>>
>>> Signed-off-by: Jesse Taube <Mr.Bossman075@gmail.com>
>>> Suggested-by: Giulio Benetti <giulio.benetti@benettiengineering.com>
>>> ---
>>> V1->V2:
>>> * Kconfig: Add new line
>>> * clk-imxrt.c: Remove unused const
>>> * clk-imxrt.c: Remove set parents
>>> * clk-imxrt.c: Use fsl,imxrt-anatop for anatop base address
>>> V2->V3:
>>> * Remove unused ANATOP_BASE_ADDR
>>> * Move to hw API
>>> * Add GPT's own clock
>>> * Add SEMC clocks to set muxing to CRITICAL
>>> V3->V4:
>>> * Rename clk-imxrt.c to clk-imxrt1050.c
>>> * Rename CONFIG_CLK_IMXRT to CONFIG_CLK_IMXRT1050
>>> * Make CONFIG_CLK_IMXRT1050 selectable
>>> ---
>>>    drivers/clk/imx/Kconfig         |   5 +
>>>    drivers/clk/imx/Makefile        |   1 +
>>>    drivers/clk/imx/clk-imxrt1050.c | 156 ++++++++++++++++++++++++++++++++
>>>    3 files changed, 162 insertions(+)
>>>    create mode 100644 drivers/clk/imx/clk-imxrt1050.c
>>>
>>> diff --git a/drivers/clk/imx/Kconfig b/drivers/clk/imx/Kconfig
>>> index c08edbd04d22..f697652ab19c 100644
>>> --- a/drivers/clk/imx/Kconfig
>>> +++ b/drivers/clk/imx/Kconfig
>>> @@ -105,3 +105,8 @@ config CLK_IMX8ULP
>>>    	select MXC_CLK
>>>    	help
>>>    	    Build the driver for i.MX8ULP CCM Clock Driver
>>> +
>>> +config CLK_IMXRT1050
>>> +	bool "IMXRT1050 CCM Clock Driver"
>>> +	depends on SOC_IMXRT
>>> +	select MXC_CLK
>>> diff --git a/drivers/clk/imx/Makefile b/drivers/clk/imx/Makefile
>>> index b5e040026dfb..3d9a1e3b5fc6 100644
>>> --- a/drivers/clk/imx/Makefile
>>> +++ b/drivers/clk/imx/Makefile
>>> @@ -47,3 +47,4 @@ obj-$(CONFIG_CLK_IMX6UL) += clk-imx6ul.o
>>>    obj-$(CONFIG_CLK_IMX7D)  += clk-imx7d.o
>>>    obj-$(CONFIG_CLK_IMX7ULP) += clk-imx7ulp.o
>>>    obj-$(CONFIG_CLK_VF610)  += clk-vf610.o
>>> +obj-$(CONFIG_CLK_IMXRT1050)  += clk-imxrt1050.o
>>> diff --git a/drivers/clk/imx/clk-imxrt1050.c b/drivers/clk/imx/clk-imxrt1050.c
>>> new file mode 100644
>>> index 000000000000..85ba1a240335
>>> --- /dev/null
>>> +++ b/drivers/clk/imx/clk-imxrt1050.c
>>> @@ -0,0 +1,156 @@
>>> +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
>>> +/*
>>> + * Copyright (C) 2021
>>> + * Author(s):
>>> + * Jesse Taube <Mr.Bossman075@gmail.com>
>>> + * Giulio Benetti <giulio.benetti@benettiengineering.com>
>>> + */
>>> +#include <linux/mm.h>
>>> +#include <linux/delay.h>
>>> +#include <linux/clk.h>
>>> +#include <linux/io.h>
>>> +#include <linux/clkdev.h>
>>> +#include <linux/clk-provider.h>
>>> +#include <linux/err.h>
>>> +#include <linux/of.h>
>>> +#include <linux/of_address.h>
>>> +#include <linux/of_irq.h>
>>> +#include <linux/sizes.h>
>>> +#include <soc/imx/revision.h>
>>> +#include <dt-bindings/clock/imxrt1050-clock.h>
>>> +
>>> +#include "clk.h"
>>> +
>>> +static const char * const pll_ref_sels[] = {"osc", "dummy", };
>>> +static const char * const per_sels[] = {"ipg_pdof", "osc", };
>>> +static const char * const pll1_bypass_sels[] = {"pll1_arm", "pll1_arm_ref_sel", };
>>> +static const char * const pll2_bypass_sels[] = {"pll2_sys", "pll2_sys_ref_sel", };
>>> +static const char * const pll3_bypass_sels[] = {"pll3_usb_otg", "pll3_usb_otg_ref_sel", };
>>> +static const char * const pll5_bypass_sels[] = {"pll5_video", "pll5_video_ref_sel", };
>>> +static const char *const pre_periph_sels[] = {
>>> +	"pll2_sys", "pll2_pfd2_396m", "pll2_pfd0_352m", "arm_podf", };
>>> +static const char *const periph_sels[] = { "pre_periph_sel", "todo", };
>>> +static const char *const usdhc_sels[] = { "pll2_pfd2_396m", "pll2_pfd0_352m", };
>>> +static const char *const lpuart_sels[] = { "pll3_80m", "osc", };
>>> +static const char *const lcdif_sels[] = {
>>> +	"pll2_sys", "pll3_pfd3_454_74m", "pll5_video", "pll2_pfd0_352m",
>>> +	"pll2_pfd1_594m", "pll3_pfd1_664_62m", };
>>> +static const char *const semc_alt_sels[] = { "pll2_pfd2_396m", "pll3_pfd1_664_62m", };
>>> +static const char *const semc_sels[] = { "periph_sel", "semc_alt_sel", };
>>> +
>>> +static struct clk_hw **hws;
>>> +static struct clk_hw_onecell_data *clk_hw_data;
>>> +
>>> +static void __init imxrt_clocks_common_init(void __iomem *base)
>>> +{
>>> +	/* Anatop clocks */
>>> +	hws[IMXRT1050_CLK_DUMMY] = imx_clk_hw_fixed("dummy", 0UL);
>>> +
>>> +	hws[IMXRT1050_CLK_PLL1_REF_SEL] = imx_clk_hw_mux("pll1_arm_ref_sel",
>>> +		base + 0x0, 14, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
>>> +	hws[IMXRT1050_CLK_PLL2_REF_SEL] = imx_clk_hw_mux("pll2_sys_ref_sel",
>>> +		base + 0x30, 14, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
>>> +	hws[IMXRT1050_CLK_PLL3_REF_SEL] = imx_clk_hw_mux("pll3_usb_otg_ref_sel",
>>> +		base + 0x10, 14, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
>>> +	hws[IMXRT1050_CLK_PLL5_REF_SEL] = imx_clk_hw_mux("pll5_video_ref_sel",
>>> +		base + 0xa0, 14, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
>>> +
>>> +	hws[IMXRT1050_CLK_PLL1_ARM] = imx_clk_hw_pllv3(IMX_PLLV3_SYS, "pll1_arm",
>>> +		"pll1_arm_ref_sel", base + 0x0, 0x7f);
>>> +	hws[IMXRT1050_CLK_PLL2_SYS] = imx_clk_hw_pllv3(IMX_PLLV3_GENERIC, "pll2_sys",
>>> +		"pll2_sys_ref_sel", base + 0x30, 0x1);
>>> +	hws[IMXRT1050_CLK_PLL3_USB_OTG] = imx_clk_hw_pllv3(IMX_PLLV3_USB, "pll3_usb_otg",
>>> +		"pll3_usb_otg_ref_sel", base + 0x10, 0x1);
>>> +	hws[IMXRT1050_CLK_PLL5_VIDEO] = imx_clk_hw_pllv3(IMX_PLLV3_AV, "pll5_video",
>>> +		"pll5_video_ref_sel", base + 0xa0, 0x7f);
>>> +
>>> +	/* PLL bypass out */
>>> +	hws[IMXRT1050_CLK_PLL1_BYPASS] = imx_clk_hw_mux_flags("pll1_bypass", base + 0x0, 16, 1,
>>> +		pll1_bypass_sels, ARRAY_SIZE(pll1_bypass_sels), CLK_SET_RATE_PARENT);
>>> +	hws[IMXRT1050_CLK_PLL2_BYPASS] = imx_clk_hw_mux_flags("pll2_bypass", base + 0x30, 16, 1,
>>> +		pll2_bypass_sels, ARRAY_SIZE(pll2_bypass_sels), CLK_SET_RATE_PARENT);
>>> +	hws[IMXRT1050_CLK_PLL3_BYPASS] = imx_clk_hw_mux_flags("pll3_bypass", base + 0x10, 16, 1,
>>> +		pll3_bypass_sels, ARRAY_SIZE(pll3_bypass_sels), CLK_SET_RATE_PARENT);
>>> +	hws[IMXRT1050_CLK_PLL5_BYPASS] = imx_clk_hw_mux_flags("pll5_bypass", base + 0xa0, 16, 1,
>>> +		pll5_bypass_sels, ARRAY_SIZE(pll5_bypass_sels), CLK_SET_RATE_PARENT);
>>> +
>>> +	hws[IMXRT1050_CLK_VIDEO_POST_DIV_SEL] = imx_clk_hw_divider("video_post_div_sel",
>>> +		"pll5_video", base + 0xa0, 19, 2);
>>> +	hws[IMXRT1050_CLK_VIDEO_DIV] = imx_clk_hw_divider("video_div",
>>> +		"video_post_div_sel", base + 0x170, 30, 2);
>>> +
>>> +	hws[IMXRT1050_CLK_PLL3_80M] = imx_clk_hw_fixed_factor("pll3_80m",  "pll3_usb_otg", 1, 6);
>>> +
>>> +	hws[IMXRT1050_CLK_PLL2_PFD0_352M] = imx_clk_hw_pfd("pll2_pfd0_352m", "pll2_sys", base + 0x100, 0);
>>> +	hws[IMXRT1050_CLK_PLL2_PFD1_594M] = imx_clk_hw_pfd("pll2_pfd1_594m", "pll2_sys", base + 0x100, 1);
>>> +	hws[IMXRT1050_CLK_PLL2_PFD2_396M] = imx_clk_hw_pfd("pll2_pfd2_396m", "pll2_sys", base + 0x100, 2);
>>> +	hws[IMXRT1050_CLK_PLL3_PFD1_664_62M] = imx_clk_hw_pfd("pll3_pfd1_664_62m", "pll3_usb_otg", base + 0xf0, 1);
>>> +	hws[IMXRT1050_CLK_PLL3_PFD3_454_74M] = imx_clk_hw_pfd("pll3_pfd3_454_74m", "pll3_usb_otg", base + 0xf0, 3);
>>> +}
>>> +
>>> +static void __init imxrt1050_clocks_init(struct device_node *np)
>>> +{
>>> +	void __iomem *ccm_base;
>>> +	void __iomem *pll_base;
>>> +	struct device_node *anp;
>>> +
>>> +	clk_hw_data = kzalloc(struct_size(clk_hw_data, hws,
>>> +					  IMXRT1050_CLK_END), GFP_KERNEL);
>>> +	if (WARN_ON(!clk_hw_data))
>>> +		return;
>>> +
>>> +	clk_hw_data->num = IMXRT1050_CLK_END;
>>> +	hws = clk_hw_data->hws;
>>> +
>>> +	hws[IMXRT1050_CLK_OSC] = __clk_get_hw(of_clk_get_by_name(np, "osc"));
>>> +
>>> +	anp = of_find_compatible_node(NULL, NULL, "fsl,imxrt-anatop");
>>> +	pll_base = of_iomap(anp, 0);
>>> +	WARN_ON(!pll_base);
>>> +	imxrt_clocks_common_init(pll_base);
>>> +	/* CCM clocks */
>>> +	ccm_base = of_iomap(np, 0);
>>> +	WARN_ON(!ccm_base);
>>> +
>>> +	hws[IMXRT1050_CLK_ARM_PODF] = imx_clk_hw_divider("arm_podf", "pll1_arm", ccm_base + 0x10, 0, 3);
>>> +	hws[IMXRT1050_CLK_PRE_PERIPH_SEL] = imx_clk_hw_mux("pre_periph_sel", ccm_base + 0x18, 18, 2,
>>> +		pre_periph_sels, ARRAY_SIZE(pre_periph_sels));
>>> +	hws[IMXRT1050_CLK_PERIPH_SEL] = imx_clk_hw_mux("periph_sel", ccm_base + 0x14, 25, 1,
>>> +		periph_sels, ARRAY_SIZE(periph_sels));
>>> +	hws[IMXRT1050_CLK_USDHC1_SEL] = imx_clk_hw_mux("usdhc1_sel", ccm_base + 0x1c, 16, 1,
>>> +		usdhc_sels, ARRAY_SIZE(usdhc_sels));
>>> +	hws[IMXRT1050_CLK_USDHC2_SEL] = imx_clk_hw_mux("usdhc2_sel", ccm_base + 0x1c, 17, 1,
>>> +		usdhc_sels, ARRAY_SIZE(usdhc_sels));
>>> +	hws[IMXRT1050_CLK_LPUART_SEL] = imx_clk_hw_mux("lpuart_sel", ccm_base + 0x24, 6, 1,
>>> +		lpuart_sels, ARRAY_SIZE(lpuart_sels));
>>> +	hws[IMXRT1050_CLK_LCDIF_SEL] = imx_clk_hw_mux("lcdif_sel", ccm_base + 0x38, 15, 3,
>>> +		lcdif_sels, ARRAY_SIZE(lcdif_sels));
>>> +	hws[IMXRT1050_CLK_PER_CLK_SEL] = imx_clk_hw_mux("per_sel", ccm_base + 0x1C, 6, 1,
>>> +		per_sels, ARRAY_SIZE(per_sels));
>>> +	hws[IMXRT1050_CLK_SEMC_ALT_SEL] = imx_clk_hw_mux("semc_alt_sel", ccm_base + 0x14, 7, 1,
>>> +		semc_alt_sels, ARRAY_SIZE(semc_alt_sels));
>>> +	hws[IMXRT1050_CLK_SEMC_SEL] = imx_clk_hw_mux_flags("semc_sel", ccm_base + 0x14, 6, 1,
>>> +		semc_sels, ARRAY_SIZE(semc_sels), CLK_IS_CRITICAL);
>>> +
>>> +	hws[IMXRT1050_CLK_AHB_PODF] = imx_clk_hw_divider("ahb", "periph_sel", ccm_base + 0x14, 10, 3);
>>> +	hws[IMXRT1050_CLK_IPG_PDOF] = imx_clk_hw_divider("ipg", "ahb", ccm_base + 0x14, 8, 2);
>>> +	hws[IMXRT1050_CLK_PER_PDOF] = imx_clk_hw_divider("per", "per_sel", ccm_base + 0x1C, 0, 5);
>>> +
>>> +	hws[IMXRT1050_CLK_USDHC1_PODF] = imx_clk_hw_divider("usdhc1_podf", "usdhc1_sel", ccm_base + 0x24, 11, 3);
>>> +	hws[IMXRT1050_CLK_USDHC2_PODF] = imx_clk_hw_divider("usdhc2_podf", "usdhc2_sel", ccm_base + 0x24, 16, 3);
>>> +	hws[IMXRT1050_CLK_LPUART_PODF] = imx_clk_hw_divider("lpuart_podf", "lpuart_sel", ccm_base + 0x24, 0, 6);
>>> +	hws[IMXRT1050_CLK_LCDIF_PRED] = imx_clk_hw_divider("lcdif_pred", "lcdif_sel", ccm_base + 0x38, 12, 3);
>>> +	hws[IMXRT1050_CLK_LCDIF_PODF] = imx_clk_hw_divider("lcdif_podf", "lcdif_pred", ccm_base + 0x18, 23, 3);
>>> +
>>> +	hws[IMXRT1050_CLK_USDHC1] = imx_clk_hw_gate2("usdhc1", "usdhc1_podf", ccm_base + 0x80, 2);
>>> +	hws[IMXRT1050_CLK_USDHC2] = imx_clk_hw_gate2("usdhc2", "usdhc2_podf", ccm_base + 0x80, 4);
>>> +	hws[IMXRT1050_CLK_LPUART1] = imx_clk_hw_gate2("lpuart1", "lpuart_podf", ccm_base + 0x7c, 24);
>>> +	hws[IMXRT1050_CLK_LCDIF_APB] = imx_clk_hw_gate2("lcdif", "lcdif_podf", ccm_base + 0x74, 10);
>>> +	hws[IMXRT1050_CLK_DMA] = imx_clk_hw_gate("dma", "ipg", ccm_base + 0x7C, 6);
>>> +	hws[IMXRT1050_CLK_DMA_MUX] = imx_clk_hw_gate("dmamux0", "ipg", ccm_base + 0x7C, 7);
>>> +	hws[IMXRT1050_CLK_GPT] = imx_clk_hw_fixed_factor("gpt", "osc", 1, 8);
>>> +	imx_check_clk_hws(hws, IMXRT1050_CLK_END);
>>> +
>>> +	of_clk_add_hw_provider(np, of_clk_hw_onecell_get, clk_hw_data);
>>> +}
>>> +CLK_OF_DECLARE(imxrt_ccm, "fsl,imxrt1050-ccm", imxrt1050_clocks_init);
>>
>> I would suggest module platform driver instead.
> 
> Can you please point us an example?

Sorry, I've found already the clk-imx8mq.c as an example.

@Jesse, if you want here is a change to do on this driver or let me know 
if I have to make it.

Thank you all
Best regards
Fabio Estevam Dec. 13, 2021, 12:14 p.m. UTC | #7
Hi Giulio,

On Mon, Dec 13, 2021 at 9:06 AM Giulio Benetti
<giulio.benetti@benettiengineering.com> wrote:

> > I would suggest module platform driver instead.
>
> Can you please point us an example?

Here is an example of a commit that converts the imx8mm clk driver to
platform driver:
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v5.15.7&id=af7e7ee0e4280c29c41b6ec64b892bb53987a997
Giulio Benetti Dec. 13, 2021, 12:42 p.m. UTC | #8
Hi Fabio,

> Il giorno 13 dic 2021, alle ore 13:15, Fabio Estevam <festevam@gmail.com> ha scritto:
> 
> Hi Giulio,
> 
> On Mon, Dec 13, 2021 at 9:06 AM Giulio Benetti
> <giulio.benetti@benettiengineering.com> wrote:
> 
>>> I would suggest module platform driver instead.
>> 
>> Can you please point us an example?
> 
> Here is an example of a commit that converts the imx8mm clk driver to
> platform driver:
> https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?h=v5.15.7&id=af7e7ee0e4280c29c41b6ec64b892bb53987a997

Thanks a lot, this ease us

Best regards
Giulio