[U-Boot] [PATCH 1/5] imx8: Add lpcg driver for iMX8QM/QXP

Peng Fan peng.fan at nxp.com
Wed Jul 3 06:02:13 UTC 2019


> Subject: [PATCH 1/5] imx8: Add lpcg driver for iMX8QM/QXP
> 
[...]
> 
> diff --git a/arch/arm/include/asm/arch-imx8/imx8qm_lpcg.h
> b/arch/arm/include/asm/arch-imx8/imx8qm_lpcg.h
> new file mode 100644
> index 0000000..692c27f
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-imx8/imx8qm_lpcg.h
> @@ -0,0 +1,200 @@
> +/*
> + * Copyright 2018 NXP
> + *
> + * SPDX-License-Identifier:     GPL-2.0+

Please fix license and time.

> + */
> +
> +#ifndef _SC_LPCG_H
> +#define _SC_LPCG_H
> +
[...]

> +#endif
> diff --git a/arch/arm/include/asm/arch-imx8/imx8qxp_lpcg.h
> b/arch/arm/include/asm/arch-imx8/imx8qxp_lpcg.h
> new file mode 100644
> index 0000000..5fed514
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-imx8/imx8qxp_lpcg.h
> @@ -0,0 +1,195 @@
> +/*
> + * Copyright 2018 NXP
> + *
> + * SPDX-License-Identifier:     GPL-2.0+

Ditto

> + */
> +
> +#ifndef _SC_LPCG_H
> +#define _SC_LPCG_H
> +
[...]
> +#define     AUD_EDMA_1_LPCG         0x59df0000
> +

Blank line.

> +
> +/* Connectivity SS */
> +#define     USDHC_0_LPCG        0x5B200000
> +#define     USDHC_1_LPCG        0x5B210000
> +#define     USDHC_2_LPCG        0x5B220000
> +#define     ENET_0_LPCG         0x5B230000
> +#define     ENET_1_LPCG         0x5B240000
> +#define     DTCP_LPCG           0x5B250000
> +#define     MLB_LPCG            0x5B260000
> +#define     USB_2_LPCG          0x5B270000
> +#define     USB_3_LPCG          0x5B280000
> +#define     NAND_LPCG           0x5B290000
> +#define     EDMA_LPCG           0x5B2A0000
> +
> +/* CM40 SS */
> +#define     CM40_I2C_LPCG       0x37630000
> +
> +

Ditto

> +#endif
> diff --git a/arch/arm/include/asm/arch-imx8/lpcg.h
> b/arch/arm/include/asm/arch-imx8/lpcg.h
> new file mode 100644
> index 0000000..b3a4545
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-imx8/lpcg.h
> @@ -0,0 +1,26 @@
> +/*
> + * Copyright 2018 NXP
> + *
> + * SPDX-License-Identifier:	GPL-2.0+

Please fix copyright and license.

> + */
> +
> +#ifndef __ASM_ARCH_IMX8_LPCG_H__
> +#define __ASM_ARCH_IMX8_LPCG_H__
> +
> +#if defined(CONFIG_IMX8QM)
> +#include "imx8qm_lpcg.h"
> +#elif defined(CONFIG_IMX8QXP)
> +#include "imx8qxp_lpcg.h"
> +#else
> +#error "No lpcg header"
> +#endif
> +
> +void lpcg_clock_off(u32 lpcg_addr, u8 clk); void lpcg_clock_on(u32
> +lpcg_addr, u8 clk); void lpcg_clock_autogate(u32 lpcg_addr, u8 clk);
> +bool lpcg_is_clock_on(u32 lpcg_addr, u8 clk); void
> +lpcg_all_clock_off(u32 lpcg_addr); void lpcg_all_clock_on(u32
> +lpcg_addr); void lpcg_all_clock_autogate(u32 lpcg_addr);
> +
> +#endif	/* __ASM_ARCH_IMX8_LPCG_H__ */
> diff --git a/arch/arm/mach-imx/imx8/Makefile
> b/arch/arm/mach-imx/imx8/Makefile index 31ad169..e23f84f 100644
> --- a/arch/arm/mach-imx/imx8/Makefile
> +++ b/arch/arm/mach-imx/imx8/Makefile
> @@ -4,4 +4,4 @@
>  # SPDX-License-Identifier:	GPL-2.0+
>  #
> 
> -obj-y += cpu.o iomux.o
> +obj-y += cpu.o iomux.o lpcg.o
> diff --git a/arch/arm/mach-imx/imx8/lpcg.c
> b/arch/arm/mach-imx/imx8/lpcg.c new file mode 100644 index
> 0000000..5f5d770
> --- /dev/null
> +++ b/arch/arm/mach-imx/imx8/lpcg.c
> @@ -0,0 +1,115 @@
> +/*
> + * Copyright 2017-2019 NXP
> + *
> + * SPDX-License-Identifier:	GPL-2.0+

Ditto.

Regards,
Peng.

> + */
> +
> +#include <common.h>
> +#include <asm/io.h>
> +#include <linux/errno.h>
> +#include <asm/arch/lpcg.h>
> +
> +#define LPCG_CLOCK_MASK         0x3U
> +#define LPCG_CLOCK_OFF          0x0U
> +#define LPCG_CLOCK_ON           0x2U
> +#define LPCG_CLOCK_AUTO         0x3U
> +#define LPCG_CLOCK_STOP         0x8U
> +
> +#define LPCG_ALL_CLOCK_OFF      0x00000000U
> +#define LPCG_ALL_CLOCK_ON       0x22222222U
> +#define LPCG_ALL_CLOCK_AUTO     0x33333333U
> +#define LPCG_ALL_CLOCK_STOP     0x88888888U
> +
> +static inline void lpcg_write(u32 lpcgVal, ulong lpcg_addr) {
> +	/*
> +	* Write twice with 4x DSC clock cycles (40x IPS clock cycles) interval
> +	* to work around LPCG issue
> +	*/
> +	writel(lpcgVal, lpcg_addr);
> +	udelay(10); /* 10us is enough. Worst case is 40x IPS cycle (200Mhz) */
> +	writel(lpcgVal, lpcg_addr);
> +	udelay(10);
> +}
> +
> +void lpcg_clock_off(u32 lpcg_addr, u8 clk) {
> +	u32 lpcgVal;
> +
> +	/* Read from LPCG */
> +	lpcgVal = readl((ulong)lpcg_addr);
> +
> +	/* Modify */
> +	lpcgVal &= ~((u32)(LPCG_CLOCK_MASK) << (clk * 4U));
> +	lpcgVal |= ((u32)(LPCG_CLOCK_OFF) << (clk * 4U));
> +
> +	/* Write to LPCG */
> +	lpcg_write(lpcgVal, (ulong)lpcg_addr); }
> +
> +void lpcg_clock_on(u32 lpcg_addr, u8 clk) {
> +	u32 lpcgVal;
> +
> +	/* Read from LPCG */
> +	lpcgVal = readl((ulong)lpcg_addr);
> +
> +	/* Modify */
> +	lpcgVal &= ~((u32)(LPCG_CLOCK_MASK) << (clk * 4U));
> +	lpcgVal |= ((u32)(LPCG_CLOCK_ON) << (clk * 4U));
> +
> +	/* Write to LPCG */
> +	lpcg_write(lpcgVal, (ulong)lpcg_addr); }
> +
> +bool lpcg_is_clock_on(u32 lpcg_addr, u8 clk) {
> +	u32 lpcgVal;
> +
> +	/* Read from LPCG */
> +	lpcgVal = readl((ulong)lpcg_addr);
> +	lpcgVal = (lpcgVal >> (clk * 4U)) & (u32)(LPCG_CLOCK_MASK);
> +
> +	if (lpcgVal == LPCG_CLOCK_ON)
> +		return true;
> +
> +	return false;
> +}
> +
> +void lpcg_clock_autogate(u32 lpcg_addr, u8 clk) {
> +	u32 lpcgVal;
> +
> +	/* Read from LPCG */
> +	lpcgVal = readl((ulong)lpcg_addr);
> +
> +	/* Modify */
> +	lpcgVal &= ~((u32)(LPCG_CLOCK_MASK) << (clk * 4U));
> +	lpcgVal |= ((u32)(LPCG_CLOCK_AUTO) << (clk * 4U));
> +
> +	/* Write to LPCG */
> +	lpcg_write(lpcgVal, (ulong)lpcg_addr); }
> +
> +void lpcg_all_clock_off(u32 lpcg_addr)
> +{
> +	/* Write to LPCG */
> +	lpcg_write(LPCG_ALL_CLOCK_OFF, (ulong)lpcg_addr); }
> +
> +void lpcg_all_clock_on(u32 lpcg_addr)
> +{
> +	/* Write to LPCG */
> +	lpcg_write(LPCG_ALL_CLOCK_ON, (ulong)lpcg_addr);
> +
> +	/* Wait for clocks to start */
> +	while ((readl((ulong)lpcg_addr) & LPCG_ALL_CLOCK_STOP) != 0U)
> +	{
> +	}
> +}
> +
> +void lpcg_all_clock_autogate(u32 lpcg_addr) {
> +	/* Write to LPCG */
> +	lpcg_write(LPCG_ALL_CLOCK_AUTO, (ulong)lpcg_addr); }
> --
> 2.7.4



More information about the U-Boot mailing list