diff --git a/arch/arm/mach-imx/imx8/lpcg.c b/arch/arm/mach-imx/imx8/lpcg.c index 7e91574..22cbc60 100644 --- a/arch/arm/mach-imx/imx8/lpcg.c +++ b/arch/arm/mach-imx/imx8/lpcg.c @@ -1,5 +1,5 @@ /* - * Copyright 2017-2018 NXP + * Copyright 2017-2019 NXP * * SPDX-License-Identifier: GPL-2.0+ */ @@ -20,6 +20,18 @@ #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_ClockOff(u32 lpcg_addr, u8 clk) { u32 lpcgVal; @@ -32,7 +44,7 @@ void LPCG_ClockOff(u32 lpcg_addr, u8 clk) lpcgVal |= ((u32)(LPCG_CLOCK_OFF) << (clk * 4U)); /* Write to LPCG */ - writel(lpcgVal, (ulong)lpcg_addr); + lpcg_write(lpcgVal, (ulong)lpcg_addr); } void LPCG_ClockOn(u32 lpcg_addr, u8 clk) @@ -47,7 +59,7 @@ void LPCG_ClockOn(u32 lpcg_addr, u8 clk) lpcgVal |= ((u32)(LPCG_CLOCK_ON) << (clk * 4U)); /* Write to LPCG */ - writel(lpcgVal, (ulong)lpcg_addr); + lpcg_write(lpcgVal, (ulong)lpcg_addr); } void LPCG_ClockAutoGate(u32 lpcg_addr, u8 clk) @@ -62,19 +74,19 @@ void LPCG_ClockAutoGate(u32 lpcg_addr, u8 clk) lpcgVal |= ((u32)(LPCG_CLOCK_AUTO) << (clk * 4U)); /* Write to LPCG */ - writel(lpcgVal, (ulong)lpcg_addr); + lpcg_write(lpcgVal, (ulong)lpcg_addr); } void LPCG_AllClockOff(u32 lpcg_addr) { /* Write to LPCG */ - writel(LPCG_ALL_CLOCK_OFF, (ulong)lpcg_addr); + lpcg_write(LPCG_ALL_CLOCK_OFF, (ulong)lpcg_addr); } void LPCG_AllClockOn(u32 lpcg_addr) { /* Write to LPCG */ - writel(LPCG_ALL_CLOCK_ON, (ulong)lpcg_addr); + lpcg_write(LPCG_ALL_CLOCK_ON, (ulong)lpcg_addr); /* Wait for clocks to start */ while ((readl((ulong)lpcg_addr) & LPCG_ALL_CLOCK_STOP) != 0U) @@ -85,5 +97,5 @@ void LPCG_AllClockOn(u32 lpcg_addr) void LPCG_AllClockAutoGate(u32 lpcg_addr) { /* Write to LPCG */ - writel(LPCG_ALL_CLOCK_AUTO, (ulong)lpcg_addr); + lpcg_write(LPCG_ALL_CLOCK_AUTO, (ulong)lpcg_addr); }