[U-Boot] [PATCH v3 19/58] clk: sunxi: Implement direct MMC clocks
Jagan Teki
jagan at amarulasolutions.com
Mon Aug 27 10:04:20 UTC 2018
On Mon, Aug 20, 2018 at 5:03 PM, Maxime Ripard
<maxime.ripard at bootlin.com> wrote:
> On Sun, Aug 19, 2018 at 07:26:36PM +0530, Jagan Teki wrote:
>> Implement direct MMC clocks for all Allwinner SoC
>> clock drivers via clock map descriptor table.
>>
>> This includes adding ccu_clk_set_rate function pointer,
>> which indeed support CLK set_rate API, so update clock
>> handling in sunxi_mmc driver to support both no-dm and dm code.
>>
>> Cc: Jaehoon Chung <jh80.chung at samsung.com>
>> Signed-off-by: Jagan Teki <jagan at amarulasolutions.com>
>> ---
>> arch/arm/include/asm/arch-sunxi/ccu.h | 10 +++++
>> drivers/clk/sunxi/clk_a10.c | 5 +++
>> drivers/clk/sunxi/clk_a10s.c | 6 +++
>> drivers/clk/sunxi/clk_a23.c | 6 +++
>> drivers/clk/sunxi/clk_a31.c | 5 +++
>> drivers/clk/sunxi/clk_a64.c | 4 ++
>> drivers/clk/sunxi/clk_a83t.c | 4 ++
>> drivers/clk/sunxi/clk_h3.c | 4 ++
>> drivers/clk/sunxi/clk_r40.c | 4 ++
>> drivers/clk/sunxi/clk_sunxi.c | 19 +++++++++
>> drivers/clk/sunxi/clk_v3s.c | 4 ++
>> drivers/mmc/sunxi_mmc.c | 58 +++++++++++++++++----------
>> 12 files changed, 107 insertions(+), 22 deletions(-)
>>
>> diff --git a/arch/arm/include/asm/arch-sunxi/ccu.h b/arch/arm/include/asm/arch-sunxi/ccu.h
>> index bacd052ef3..4e30ab330c 100644
>> --- a/arch/arm/include/asm/arch-sunxi/ccu.h
>> +++ b/arch/arm/include/asm/arch-sunxi/ccu.h
>> @@ -60,6 +60,16 @@ struct sunxi_clk_priv {
>>
>> extern struct clk_ops sunxi_clk_ops;
>>
>> +/**
>> + * mmc_clk_set_rate - mmc clock set rate
>> + *
>> + * @base: clock register base address
>> + * @bit: clock bit value
>> + * @rate: clock input rate in Hz
>> + * @return 0, or -ve error code.
>> + */
>> +int mmc_clk_set_rate(void *base, u32 bit, ulong rate);
>> +
>> /**
>> * sunxi_reset_bind() - reset binding
>> *
>> diff --git a/drivers/clk/sunxi/clk_a10.c b/drivers/clk/sunxi/clk_a10.c
>> index fb11231dd1..55176bc174 100644
>> --- a/drivers/clk/sunxi/clk_a10.c
>> +++ b/drivers/clk/sunxi/clk_a10.c
>> @@ -23,6 +23,11 @@ static struct ccu_clk_map a10_clks[] = {
>> [CLK_AHB_MMC2] = { 0x060, BIT(10), NULL },
>> [CLK_AHB_MMC3] = { 0x060, BIT(11), NULL },
>>
>> + [CLK_MMC0] = { 0x088, BIT(31), &mmc_clk_set_rate },
>> + [CLK_MMC1] = { 0x08c, BIT(31), &mmc_clk_set_rate },
>> + [CLK_MMC2] = { 0x090, BIT(31), &mmc_clk_set_rate },
>> + [CLK_MMC3] = { 0x094, BIT(31), &mmc_clk_set_rate },
>> +
>> [CLK_USB_OHCI0] = { 0x0cc, BIT(6), NULL },
>> [CLK_USB_OHCI1] = { 0x0cc, BIT(7), NULL },
>> [CLK_USB_PHY] = { 0x0cc, BIT(8), NULL },
>> diff --git a/drivers/clk/sunxi/clk_a10s.c b/drivers/clk/sunxi/clk_a10s.c
>> index bc4ae7352b..fbac0ad751 100644
>> --- a/drivers/clk/sunxi/clk_a10s.c
>> +++ b/drivers/clk/sunxi/clk_a10s.c
>> @@ -20,6 +20,12 @@ static struct ccu_clk_map a10s_clks[] = {
>> [CLK_AHB_MMC1] = { 0x060, BIT(9), NULL },
>> [CLK_AHB_MMC2] = { 0x060, BIT(10), NULL },
>>
>> +#ifdef CONFIG_MMC
>> + [CLK_MMC0] = { 0x088, BIT(31), &mmc_clk_set_rate },
>> + [CLK_MMC1] = { 0x08c, BIT(31), &mmc_clk_set_rate },
>> + [CLK_MMC2] = { 0x090, BIT(31), &mmc_clk_set_rate },
>> +#endif
>> +
>
> I'm not too sure about the ifdef here. Or at least, we should be
> consistent, and if we do it for the MMC, we should do it for all the
> SoCs (including the A10), and for all the controllers (including USB,
> for example).
because few of sun5i boards not using MMC, example CHIP and CHIP_pro
otherwise we need to use intermediate wrapper to call
mmc_clk_set_rate.
>
>> diff --git a/drivers/mmc/sunxi_mmc.c b/drivers/mmc/sunxi_mmc.c
>> index 39f15eb423..bf82014a64 100644
>> --- a/drivers/mmc/sunxi_mmc.c
>> +++ b/drivers/mmc/sunxi_mmc.c
>> @@ -13,6 +13,7 @@
>> #include <malloc.h>
>> #include <mmc.h>
>> #include <asm/io.h>
>> +#include <asm/arch/ccu.h>
>> #include <asm/arch/clock.h>
>> #include <asm/arch/cpu.h>
>> #include <asm/arch/gpio.h>
>> @@ -34,6 +35,8 @@ struct sunxi_mmc_priv {
>> struct mmc_config cfg;
>> };
>>
>> +bool new_mode;
>> +
>> #if !CONFIG_IS_ENABLED(DM_MMC)
>> /* support 4 mmc hosts */
>> struct sunxi_mmc_priv mmc_host[4];
>> @@ -95,23 +98,19 @@ static int mmc_resource_init(int sdc_no)
>> }
>> #endif
>>
>> -static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz)
>> +int mmc_clk_set_rate(void *base, u32 bit, ulong rate)
>> {
>> unsigned int pll, pll_hz, div, n, oclk_dly, sclk_dly;
>> - bool new_mode = false;
>> u32 val = 0;
>>
>> - if (IS_ENABLED(CONFIG_MMC_SUNXI_HAS_NEW_MODE) && (priv->mmc_no == 2))
>> - new_mode = true;
>> -
>
> [..]
>
>> +static int mmc_set_mod_clk(struct sunxi_mmc_priv *priv, unsigned int hz)
>> +{
>> +#if CONFIG_IS_ENABLED(DM_MMC) && CONFIG_IS_ENABLED(CLK)
>> +#else
>> + if (IS_ENABLED(CONFIG_MMC_SUNXI_HAS_NEW_MODE) && (priv->mmc_no == 2))
>> + new_mode = true;
>> +
>
> I'm not sure why you need the global variable.
>
> The A83t emmc case you have below is caught in this condition, and
> therefore, the scope doesn't need to be global.
Since mmc_set_rate calling with base and reg bits, which doesn't have
any possibility know private data of driver we need a global to check
to update the same in dm and non-dm.
More information about the U-Boot
mailing list