Devicetree
 help / color / mirror / Atom feed
* Re: [PATCH v2 2/2] clocksource: sprd: Add timer driver for Spreadtrum SC9860 platform
From: Baolin Wang @ 2017-12-07 10:52 UTC (permalink / raw)
  To: Daniel Lezcano
  Cc: Baolin Wang, Thomas Gleixner, Rob Herring, Mark Rutland, DTML,
	LKML, Mark Brown
In-Reply-To: <ebc1606c-d3d4-e784-87ff-c8d8ba3a80df-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Hi Daniel,

On 7 December 2017 at 18:44, Daniel Lezcano <daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org> wrote:
> On 28/11/2017 03:45, Baolin Wang wrote:
>> The Spreadtrum SC9860 platform will use the architected timers as local
>> clock events, but we also need a broadcast timer device to wakeup the
>> cpus when the cpus are in sleep mode.
>>
>> Thus this patch registers the timer0 to be a broadcast timer supporting
>> periodic and oneshot events.
>
> This changelog is inadequate. It is pointless to explain why you submit
> this driver.
>
> It would be much more interesting to describe the timer internals.

Sure.

>
>> Signed-off-by: Baolin Wang <baolin.wang-lxIno14LUO0EEoCn2XhGlw@public.gmane.org>
>> ---
>> Changes since v1:
>>  - Change to 32bit counter to avoid build warning.
>> ---
>>  drivers/clocksource/Kconfig      |    8 ++
>>  drivers/clocksource/Makefile     |    1 +
>>  drivers/clocksource/sprd-timer.c |  211 ++++++++++++++++++++++++++++++++++++++
>>  3 files changed, 220 insertions(+)
>>  create mode 100644 drivers/clocksource/sprd-timer.c
>
> Even if it is not a general rule, can you rename this driver to
> timer-sprd.c ? I would like little by little to converge all the timer
> names to this pattern.

OK.

>
>> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
>> index c729a88..48c8702 100644
>> --- a/drivers/clocksource/Kconfig
>> +++ b/drivers/clocksource/Kconfig
>> @@ -441,6 +441,14 @@ config MTK_TIMER
>>       help
>>         Support for Mediatek timer driver.
>>
>> +config SPRD_TIMER
>> +     bool "Spreadtrum timer driver"
>> +     depends on GENERIC_CLOCKEVENTS
>
> Remove GENERIC_CLOCKEVENTS because of:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux-stable.git/tree/drivers/clocksource/Kconfig#n2

Yes, here GENERIC_CLOCKEVENTS is redundant.

>
>> +     depends on ARCH_SPRD || COMPILE_TEST
>
> Remove the dependency on ARCH_SPRD, the arch's Kconfig must select
> SPRD_TIMER.
>
> Move the COMPILE_TEST as the other drivers.

OK.

>
>         bool "Spreadtrum timer driver" if COMPILE_TEST
>
>> +     select TIMER_O> +       help
>> +       Enables the support for the Spreadtrum timer driver.
>> +
>>  config SYS_SUPPORTS_SH_MTU2
>>          bool
>>
>> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
>> index 72711f1..62bf264 100644
>> --- a/drivers/clocksource/Makefile
>> +++ b/drivers/clocksource/Makefile
>> @@ -54,6 +54,7 @@ obj-$(CONFIG_CLKSRC_TI_32K) += timer-ti-32k.o
>>  obj-$(CONFIG_CLKSRC_NPS)     += timer-nps.o
>>  obj-$(CONFIG_OXNAS_RPS_TIMER)        += timer-oxnas-rps.o
>>  obj-$(CONFIG_OWL_TIMER)              += owl-timer.o
>> +obj-$(CONFIG_SPRD_TIMER)     += sprd-timer.o
>>
>>  obj-$(CONFIG_ARC_TIMERS)             += arc_timer.o
>>  obj-$(CONFIG_ARM_ARCH_TIMER)         += arm_arch_timer.o
>> diff --git a/drivers/clocksource/sprd-timer.c b/drivers/clocksource/sprd-timer.c
>> new file mode 100644
>> index 0000000..e90f948
>> --- /dev/null
>> +++ b/drivers/clocksource/sprd-timer.c
>> @@ -0,0 +1,211 @@
>> +/*
>> + * Copyright (C) 2017 Spreadtrum Communications Inc.
>> + *
>> + * SPDX-License-Identifier: GPL-2.0
>> + */
>
> Please fix the above with proper format (one example in timer-of.c).

OK.

>
>> +#include <linux/clocksource.h>
>> +#include <linux/clockchips.h>
>> +#include <linux/init.h>
>> +#include <linux/interrupt.h>
>> +#include <linux/sched_clock.h>
>
> Are you sure you need sched_clock and clocksource ?

Sorry, I forgot to remove them.

>
>> +#include <linux/slab.h>
>> +#include <linux/of.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_irq.h>
>
> These headers won't be needed anymore when using the timer-of API (see
> the init function comment below).

OK.

>
>> +#define TIMER_NAME           "sprd_timer"
>> +
>> +#define TIMER_LOAD_LO                0x0
>> +#define TIMER_LOAD_HI                0x4
>> +#define TIMER_VALUE_LO               0x8
>> +#define TIMER_VALUE_HI               0xc
>> +
>> +#define TIMER_CTL            0x10
>> +#define TIMER_CTL_PERIOD_MODE        BIT(0)
>> +#define TIMER_CTL_ENABLE     BIT(1)
>> +#define TIMER_CTL_64BIT_WIDTH        BIT(16)
>> +
>> +#define TIMER_INT            0x14
>> +#define TIMER_INT_EN         BIT(0)
>> +#define TIMER_INT_RAW_STS    BIT(1)
>> +#define TIMER_INT_MASK_STS   BIT(2)
>> +#define TIMER_INT_CLR                BIT(3)
>> +
>> +#define TIMER_VALUE_SHDW_LO  0x18
>> +#define TIMER_VALUE_SHDW_HI  0x1c
>> +
>> +#define TIMER_VALUE_LO_MASK  GENMASK(31, 0)
>> +
>> +struct sprd_timer_device {
>> +     struct clock_event_device ce;
>> +     void __iomem *base;
>> +     u32 freq;
>> +     int irq;
>> +};
>> +
>> +static inline struct sprd_timer_device *
>> +to_sprd_timer(struct clock_event_device *c)
>> +{
>> +     return container_of(c, struct sprd_timer_device, ce);
>> +}
>> +
>> +static void sprd_timer_enable(struct sprd_timer_device *timer, u32 flag)
>> +{
>> +     u32 val = readl_relaxed(timer->base + TIMER_CTL);
>> +
>> +     val |= TIMER_CTL_ENABLE;
>> +     if (flag & TIMER_CTL_64BIT_WIDTH)
>> +             val |= TIMER_CTL_64BIT_WIDTH;
>> +     else
>> +             val &= ~TIMER_CTL_64BIT_WIDTH;
>> +
>> +     if (flag & TIMER_CTL_PERIOD_MODE)
>> +             val |= TIMER_CTL_PERIOD_MODE;
>> +     else
>> +             val &= ~TIMER_CTL_PERIOD_MODE;
>> +
>> +     writel_relaxed(val, timer->base + TIMER_CTL);
>> +}
>> +
>> +static void sprd_timer_disable(struct sprd_timer_device *timer)
>> +{
>> +     u32 val = readl_relaxed(timer->base + TIMER_CTL);
>> +
>> +     val &= ~TIMER_CTL_ENABLE;
>> +     writel_relaxed(val, timer->base + TIMER_CTL);
>> +}
>> +
>> +static void sprd_timer_update_counter(struct sprd_timer_device *timer,
>> +                                   unsigned long cycles)
>> +{
>> +     writel_relaxed(cycles & TIMER_VALUE_LO_MASK,
>> +                    timer->base + TIMER_LOAD_LO);
>> +     writel_relaxed(0, timer->base + TIMER_LOAD_HI);
>> +}
>> +
>> +static void sprd_timer_enable_interrupt(struct sprd_timer_device *timer)
>> +{
>> +     writel_relaxed(TIMER_INT_EN, timer->base + TIMER_INT);
>> +}
>> +
>> +static void sprd_timer_clear_interrupt(struct sprd_timer_device *timer)
>> +{
>> +     u32 val = readl_relaxed(timer->base + TIMER_INT);
>> +
>> +     val |= TIMER_INT_CLR;
>> +     writel_relaxed(val, timer->base + TIMER_INT);
>> +}
>> +
>> +static int sprd_timer_set_next_event(unsigned long cycles,
>> +                                  struct clock_event_device *ce)
>> +{
>> +     struct sprd_timer_device *timer = to_sprd_timer(ce);
>> +
>> +     sprd_timer_disable(timer);
>> +     sprd_timer_update_counter(timer, cycles);
>> +     sprd_timer_enable(timer, 0);
>> +
>> +     return 0;
>> +}
>> +
>> +static int sprd_timer_set_periodic(struct clock_event_device *ce)
>> +{
>> +     struct sprd_timer_device *timer = to_sprd_timer(ce);
>> +     unsigned long cycles = DIV_ROUND_UP(timer->freq, HZ);
>> +
>> +     sprd_timer_disable(timer);
>> +     sprd_timer_update_counter(timer, cycles);
>> +     sprd_timer_enable(timer, TIMER_CTL_PERIOD_MODE);
>> +
>> +     return 0;
>> +}
>> +
>> +static int sprd_timer_shutdown(struct clock_event_device *ce)
>> +{
>> +     struct sprd_timer_device *timer = to_sprd_timer(ce);
>> +
>> +     sprd_timer_disable(timer);
>> +     return 0;
>> +}
>> +
>> +static irqreturn_t sprd_timer_interrupt(int irq, void *dev_id)
>> +{
>> +     struct sprd_timer_device *timer = dev_id;
>> +
>> +     sprd_timer_clear_interrupt(timer);
>> +
>> +     if (clockevent_state_oneshot(&timer->ce))
>> +             sprd_timer_disable(timer);
>> +
>> +     timer->ce.event_handler(&timer->ce);
>> +     return IRQ_HANDLED;
>> +}
>> +
>> +static void __init sprd_timer_clkevt_init(struct sprd_timer_device *timer)
>> +{
>> +     timer->ce.features = CLOCK_EVT_FEAT_DYNIRQ | CLOCK_EVT_FEAT_PERIODIC |
>> +                             CLOCK_EVT_FEAT_ONESHOT;
>> +     timer->ce.set_next_event = sprd_timer_set_next_event;
>> +     timer->ce.set_state_periodic = sprd_timer_set_periodic;
>> +     timer->ce.set_state_shutdown = sprd_timer_shutdown;
>> +     timer->ce.name = TIMER_NAME;
>> +     timer->ce.rating = 300;
>> +     timer->ce.irq = timer->irq;
>> +     timer->ce.cpumask = cpu_possible_mask;
>> +
>> +     sprd_timer_enable_interrupt(timer);
>> +     clockevents_config_and_register(&timer->ce, timer->freq, 1, UINT_MAX);
>> +}
>> +
>> +static int __init sprd_timer_init(struct device_node *np)
>> +{
>> +     struct sprd_timer_device *timer;
>> +     int ret;
>> +
>> +     timer = kzalloc(sizeof(*timer), GFP_KERNEL);
>> +     if (!timer)
>> +             return -ENOMEM;
>> +
>> +     ret = of_property_read_u32(np, "clock-frequency", &timer->freq);
>> +     if (ret) {
>> +             pr_err("failed to get clock frequency\n");
>> +             goto err_freq;
>> +     }
>> +
>> +     timer->base = of_iomap(np, 0);
>> +     if (!timer->base) {
>> +             pr_err("%s: unable to map resource\n", np->name);
>> +             ret = -ENXIO;
>> +             goto err_freq;
>> +     }
>> +
>> +     timer->irq = irq_of_parse_and_map(np, 0);
>> +     if (timer->irq < 0) {
>> +             pr_crit("%s: unable to parse timer irq\n", np->name);
>> +             ret = timer->irq;
>> +             goto err_map_irq;
>> +     }
>> +
>> +     ret = request_irq(timer->irq, sprd_timer_interrupt, IRQF_TIMER,
>> +                       TIMER_NAME, timer);
>> +     if (ret) {
>> +             pr_err("failed to setup irq %d\n", timer->irq);
>> +             goto err_request_irq;
>> +     }
>> +     sprd_timer_clkevt_init(timer);
>
> Please use the timer-of API, that will save you all these operations and
> checks.
>
> One example at:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clocksource/sun4i_timer.c#n143
>
> And then use the function:
>
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clocksource/sun4i_timer.c#n174
>

I missed timer-of APIs, and I will check it and use timer-of APIs.
Really appreciated for your useful comments.

-- 
Baolin.wang
Best Regards
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v6 03/17] mfd: madera: Add common support for Cirrus Logic Madera codecs
From: Richard Fitzgerald @ 2017-12-07 10:52 UTC (permalink / raw)
  To: Linus Walleij
  Cc: Alexandre Courbot, alsa-devel, Jason Cooper,
	open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	open list:WOLFSON MICROELECTRONICS DRIVERS,
	linux-kernel@vger.kernel.org, Rob Herring, linux-gpio, Mark Brown,
	Thomas Gleixner, Lee Jones, Charles Keepax, Nikesh Oswal
In-Reply-To: <CACRpkdb_i4k3F0fmDbQciPYTBUCcfpFkqM=5e3gr75-X51TTkg@mail.gmail.com>

On 07/12/17 08:54, Linus Walleij wrote:
> On Mon, Dec 4, 2017 at 10:47 AM, Richard Fitzgerald
> <rf@opensource.wolfsonmicro.com> wrote:
>> On 02/12/17 12:10, Linus Walleij wrote:
>>> On Wed, Nov 29, 2017 at 12:36 PM, Richard Fitzgerald
>>> <rf@opensource.wolfsonmicro.com> wrote:
>>>> On 29/11/17 10:18, Linus Walleij wrote:
>>>>> On Thu, Nov 23, 2017 at 6:13 PM, Richard Fitzgerald
>>>>> <rf@opensource.wolfsonmicro.com> wrote:
>>>>>
>>>>>> +config MFD_MADERA_I2C
>>>>>> +       bool "Cirrus Logic Madera codecs with I2C"
>>>>>> +       select MFD_MADERA
>>>>>> +       select REGMAP_I2C
>>>>>> +       depends on I2C
>>>>>> +       depends on PINCTRL
>>>>>> +       help
>>>>>> +         Support for the Cirrus Logic Madera platform audio SoC
>>>>>> +         core functionality controlled via I2C.
>>>>>> +
>>>>>> +config MFD_MADERA_SPI
>>>>>> +       bool "Cirrus Logic Madera codecs with SPI"
>>>>>> +       select MFD_MADERA
>>>>>> +       select REGMAP_SPI
>>>>>> +       depends on SPI_MASTER
>>>>>> +       depends on PINCTRL
>>>>>> +       help
>>>>>> +         Support for the Cirrus Logic Madera platform audio SoC
>>>>>> +         core functionality controlled via SPI.
>>>>>
>>>>>
>>>>>
>>>>> Why do the I2C and SPI subdrivers depend on PINCTRL?
>>>>>
>>>>> They sure don't seem to be using any pinctrl-specific APIs.
>>>>>
>>>>
>>>> They require PINCTRL even if they don't call any functions on it because
>>>> the
>>>> chip won't work correctly if there isn't a PINCTRL driver to apply the
>>>> correct pinmux configuration.
>>>
>>>
>>> Apply the configuration to what? Sorry I don't get it.
>>>
>>> You can't be referring to the internal pin controller of the Madera, since
>>
>> Yes I am
> 
> You are saying that the I2C and SPI interface to the Madera codec
> depends on pin control.
> 
> It does not.
> 
> You can most certainly talk I2C and SPI to the coded without any
> pin control. Probably the MFD driver can come up without it.
> 
> If what you want is unconditional pin control enabled for this circuit,
> then have MFD_MADERA select PINCTRL.
> 
>>> that has to come up before its pin controller can even be communicated
>>> with.
>>
>>
>> So?
>>
>> The MFD driver powers up the chip before registering child drivers.
> 
> Including the pin controller. You just confirmed what I said: the
> I2C and SPI interfaces do not require pin control to talk to the
> chip.
> 
>> Also that's not entirely relevant, the pinctrl settings can still be written
>> with the chip off because they will go into the regmap cache and be applied
>> when the chip is next resumed.
> 
> You still have the dependencies wrong.
> 
> Yours,
> Linus Walleij
> 

So the short version of this email thread is that it should be "select 
PINCTRL" ?

^ permalink raw reply

* Re: [PATCH v5 08/16] arm64: Add vmap_stack header file
From: Mark Rutland @ 2017-12-07 10:54 UTC (permalink / raw)
  To: James Morse
  Cc: linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	kvmarm-FPEHb7Xf0XXUo1n7N8X6UoWGPAHP3yOg,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Will Deacon, Catalin Marinas,
	Rob Herring, Marc Zyngier, Christoffer Dall, Lorenzo Pieralisi,
	Loc Ho, Heyi Guo
In-Reply-To: <20171206190142.9246-9-james.morse-5wv7dgnIgG8@public.gmane.org>

Hi James,

On Wed, Dec 06, 2017 at 07:01:34PM +0000, James Morse wrote:
> Today the arm64 arch code allocates an extra IRQ stack per-cpu. If we
> also have SDEI and VMAP stacks we need two extra per-cpu VMAP stacks.
> 
> Move the VMAP stack allocation out to a helper in a new header file.
> This avoids missing THREADINFO_GFP, or getting the all-important alignment
> wrong.
> 
> Signed-off-by: James Morse <james.morse-5wv7dgnIgG8@public.gmane.org>
> Reviewed-by: Catalin Marinas <catalin.marinas-5wv7dgnIgG8@public.gmane.org>
> ---
> Changes since v4:
>  * Added gfp.h include
> 
> Changes since v3:
>  * Added BUILD_BUG() instead of a spooky link error
> 
>  arch/arm64/include/asm/vmap_stack.h | 26 ++++++++++++++++++++++++++
>  arch/arm64/kernel/irq.c             | 13 ++-----------
>  2 files changed, 28 insertions(+), 11 deletions(-)
>  create mode 100644 arch/arm64/include/asm/vmap_stack.h
> 
> diff --git a/arch/arm64/include/asm/vmap_stack.h b/arch/arm64/include/asm/vmap_stack.h
> new file mode 100644
> index 000000000000..5465e4e65987
> --- /dev/null
> +++ b/arch/arm64/include/asm/vmap_stack.h
> @@ -0,0 +1,26 @@
> +// SPDX-License-Identifier: GPL-2.0
> +// Copyright (C) 2017 Arm Ltd.
> +#ifndef __ASM_VMAP_STACK_H
> +#define __ASM_VMAP_STACK_H
> +
> +#include <linux/gfp.h>
> +#include <linux/vmalloc.h>
> +#include <asm/memory.h>
> +#include <asm/pgtable.h>
> +#include <asm/thread_info.h>

I think we also need:

#include <linux/bug.h>		// for BUILD_BUG_ON()
#incldue <linux/kconfig.h>	// for IS_ENABLED()

Otherwise, this looks good to me. With those includes folded in:

Reviewed-by: Mark Rutland <mark.rutland-5wv7dgnIgG8@public.gmane.org>

Thanks,
Mark.

> +
> +/*
> + * To ensure that VMAP'd stack overflow detection works correctly, all VMAP'd
> + * stacks need to have the same alignment.
> + */
> +static inline unsigned long *arch_alloc_vmap_stack(size_t stack_size, int node)
> +{
> +	BUILD_BUG_ON(!IS_ENABLED(CONFIG_VMAP_STACK));
> +
> +	return __vmalloc_node_range(stack_size, THREAD_ALIGN,
> +				    VMALLOC_START, VMALLOC_END,
> +				    THREADINFO_GFP, PAGE_KERNEL, 0, node,
> +				    __builtin_return_address(0));
> +}
> +
> +#endif /* __ASM_VMAP_STACK_H */
> diff --git a/arch/arm64/kernel/irq.c b/arch/arm64/kernel/irq.c
> index 713561e5bcab..60e5fc661f74 100644
> --- a/arch/arm64/kernel/irq.c
> +++ b/arch/arm64/kernel/irq.c
> @@ -29,6 +29,7 @@
>  #include <linux/irqchip.h>
>  #include <linux/seq_file.h>
>  #include <linux/vmalloc.h>
> +#include <asm/vmap_stack.h>
>  
>  unsigned long irq_err_count;
>  
> @@ -58,17 +59,7 @@ static void init_irq_stacks(void)
>  	unsigned long *p;
>  
>  	for_each_possible_cpu(cpu) {
> -		/*
> -		* To ensure that VMAP'd stack overflow detection works
> -		* correctly, the IRQ stacks need to have the same
> -		* alignment as other stacks.
> -		*/
> -		p = __vmalloc_node_range(IRQ_STACK_SIZE, THREAD_ALIGN,
> -					 VMALLOC_START, VMALLOC_END,
> -					 THREADINFO_GFP, PAGE_KERNEL,
> -					 0, cpu_to_node(cpu),
> -					 __builtin_return_address(0));
> -
> +		p = arch_alloc_vmap_stack(IRQ_STACK_SIZE, cpu_to_node(cpu));
>  		per_cpu(irq_stack_ptr, cpu) = p;
>  	}
>  }
> -- 
> 2.15.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe devicetree" in
> the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH v3 09/15] drm/sun4i: Add A83T support
From: Maxime Ripard @ 2017-12-07 10:55 UTC (permalink / raw)
  To: Jernej Škrabec
  Cc: Mark Rutland, Thomas Petazzoni, plaes, devicetree, David Airlie,
	linux-kernel, dri-devel, Chen-Yu Tsai, Rob Herring, Daniel Vetter,
	linux-arm-kernel, icenowy
In-Reply-To: <1729482.Mgh5nx8BIs@jernej-laptop>


[-- Attachment #1.1: Type: text/plain, Size: 3853 bytes --]

Hi,

On Wed, Dec 06, 2017 at 05:37:47PM +0100, Jernej Škrabec wrote:
> Hi,
> 
> Dne torek, 05. december 2017 ob 16:42:55 CET je Jernej Škrabec napisal(a):
> > Hi Maxime,
> > 
> > Dne torek, 05. december 2017 ob 16:10:21 CET je Maxime Ripard napisal(a):
> > > Add support for the A83T display pipeline.
> > > 
> > > Reviewed-by: Chen-Yu Tsai <wens@csie.org>
> > > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > ---
> > > 
> > >  drivers/gpu/drm/sun4i/sun4i_drv.c   |  1 +
> > >  drivers/gpu/drm/sun4i/sun4i_tcon.c  |  5 +++++
> > >  drivers/gpu/drm/sun4i/sun8i_mixer.c |  9 +++++++++
> > >  3 files changed, 15 insertions(+)
> > > 
> > > diff --git a/drivers/gpu/drm/sun4i/sun4i_drv.c
> > > b/drivers/gpu/drm/sun4i/sun4i_drv.c index 49215d91c853..6f5e721b545e
> > > 100644
> > > --- a/drivers/gpu/drm/sun4i/sun4i_drv.c
> > > +++ b/drivers/gpu/drm/sun4i/sun4i_drv.c
> > > @@ -347,6 +347,7 @@ static const struct of_device_id sun4i_drv_of_table[]
> > > =
> > > { { .compatible = "allwinner,sun6i-a31s-display-engine" },
> > > 
> > >  	{ .compatible = "allwinner,sun7i-a20-display-engine" },
> > >  	{ .compatible = "allwinner,sun8i-a33-display-engine" },
> > > 
> > > +	{ .compatible = "allwinner,sun8i-a83t-display-engine" },
> > > 
> > >  	{ .compatible = "allwinner,sun8i-v3s-display-engine" },
> > >  	{ }
> > >  
> > >  };
> > > 
> > > diff --git a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > b/drivers/gpu/drm/sun4i/sun4i_tcon.c index 92f4738101e6..9b757450555f
> > > 100644
> > > --- a/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > +++ b/drivers/gpu/drm/sun4i/sun4i_tcon.c
> > > @@ -1132,6 +1132,10 @@ static const struct sun4i_tcon_quirks
> > > sun8i_a33_quirks = { .has_lvds_pll		= true,
> > > 
> > >  };
> > > 
> > > +static const struct sun4i_tcon_quirks sun8i_a83t_lcd_quirks = {
> > > +	/* nothing is supported */
> > > +};
> > > +
> > > 
> > >  static const struct sun4i_tcon_quirks sun8i_v3s_quirks = {
> > >  
> > >  	/* nothing is supported */
> > >  
> > >  };
> > > 
> > > @@ -1144,6 +1148,7 @@ const struct of_device_id sun4i_tcon_of_table[] = {
> > > 
> > >  	{ .compatible = "allwinner,sun6i-a31s-tcon", .data = 
> &sun6i_a31s_quirks
> > >  	},
> > > 
> > > { .compatible = "allwinner,sun7i-a20-tcon", .data = &sun7i_a20_quirks }, {
> > > .compatible = "allwinner,sun8i-a33-tcon", .data = &sun8i_a33_quirks }, +	
> {
> > > .compatible = "allwinner,sun8i-a83t-tcon-lcd", .data =
> > > &sun8i_a83t_lcd_quirks }, { .compatible = "allwinner,sun8i-v3s-tcon",
> > > .data
> > > = &sun8i_v3s_quirks }, { }
> > > 
> > >  };
> > > 
> > > diff --git a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> > > b/drivers/gpu/drm/sun4i/sun8i_mixer.c index ff235e3228ce..6829bec4ba68
> > > 100644
> > > --- a/drivers/gpu/drm/sun4i/sun8i_mixer.c
> > > +++ b/drivers/gpu/drm/sun4i/sun8i_mixer.c
> > > @@ -477,6 +477,11 @@ static int sun8i_mixer_remove(struct platform_device
> > > *pdev) return 0;
> > > 
> > >  }
> > > 
> > > +static const struct sun8i_mixer_cfg sun8i_a83t_mixer_cfg = {
> > > +	.vi_num = 1,
> > > +	.ui_num = 3,
> > > +};
> > > +
> > 
> > I think you should expand that structure with:
> > .ccsc = 0,
> > .scaler_mask = 0xf,
> > .mod_rate = 150000000,
> 
> I guess you could set higher clock if CLK_SET_RATE_PARENT flag is set to de_clk 
> in A83T CCU driver. BSP sets it to 500 MHz, which is a bit high...

Actually, I didn't have to change the rate used by default, so it's
not clear what it should be on the A83T.

And yeah, I'd like to avoid setting it at 500MHz without any
particular reason. The A83T draws way to much power already without
making it worse.

I'll add the CCSC and scaler_mask fields.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* [PATCH] arm64: allwinner: a64: orangepi-zero-plus2: add usb otg
From: Jagan Teki @ 2017-12-07 11:05 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Chen-Yu Tsai, Icenowy Zheng, Rob Herring, Mark Rutland,
	Catalin Marinas, Will Deacon, Michael Trimarchi,
	linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	devicetree-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-sunxi-/JYPxA39Uh5TLH3MbocFFw, Jagan Teki

Add usb otg support for orangepi-zero-plus2 board:
- Add usb_otg node with dr_mode as 'otg'
- USB0-IDDET connected to PA21
- VBUS connected through DCIN which always on

Tested mass storage function.

Signed-off-by: Jagan Teki <jagan-dyjBcgdgk7Pe9wHmmfpqLFaTQe2KTcn/@public.gmane.org>
---
Note: Anyone please check vbus connection [1]
Since it is connected through DCIN of vcc-5v, I've added vcc-5v0
regulator for the same and attached to usb0_vbus-supply but it is
disabling during kernel boot.
[    1.887854] vcc5v0: disabling

[1] http://linux-sunxi.org/File:ORANGE_PI-ZERO-PLUS2_V1_0.pdf

 .../dts/allwinner/sun50i-h5-orangepi-zero-plus2.dts    | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus2.dts b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus2.dts
index d349399..7f298ee 100644
--- a/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus2.dts
+++ b/arch/arm64/boot/dts/allwinner/sun50i-h5-orangepi-zero-plus2.dts
@@ -73,6 +73,10 @@
 	};
 };
 
+&ehci0 {
+	status = "okay";
+};
+
 &mmc0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&mmc0_pins_a>;
@@ -111,6 +115,10 @@
 	status = "okay";
 };
 
+&ohci0 {
+	status = "okay";
+};
+
 &uart0 {
 	pinctrl-names = "default";
 	pinctrl-0 = <&uart0_pins_a>;
@@ -122,3 +130,13 @@
 	pinctrl-0 = <&uart1_pins>, <&uart1_rts_cts_pins>;
 	status = "okay";
 };
+
+&usb_otg {
+	dr_mode = "otg";
+	status = "okay";
+};
+
+&usbphy {
+	usb0_id_det-gpios = <&pio 0 21 GPIO_ACTIVE_HIGH>; /* PA21 */
+	status = "okay";
+};
-- 
2.7.4

^ permalink raw reply related

* Re: [PATCH v2 0/8] arm64: Add initial Actions Semi S700 and CubieBoard7 support
From: Andreas Färber @ 2017-12-07 11:30 UTC (permalink / raw)
  To: Daniel Lezcano, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r,
	Jeff Chen, Ahha Lee
  Cc: Thomas Liau, 张东风, 刘炜,
	张天益, 梅利,
	support-om/0PrzuAKC1Z/+hSey0Gg,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	devicetree-u79uwXL29TY76Z2rM5mHXA, Thomas Gleixner
In-Reply-To: <e43387f9-60a6-129b-d0e9-dff6d0df301a-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org>

Am 07.12.2017 um 10:20 schrieb Daniel Lezcano:
> On 14/11/2017 00:34, Andreas Färber wrote:
>> Hello,
>>
>> This series prepares the Actions Semi S700 SoC and Cubietech CubieBoard7.
>> It boots equally far as the S900 based Bubblegum-96 these patches are based on,
>> i.e. into an initrd with serial and all four cores up.
>>
>> v2 modifies the clocksource driver patches and adds SPS patches.
>>
>> Not having succeeded to replace the bootloader on eMMC or to try
>> booting from SD, the only working way I've found to boot mainline kernels
>> appears to be booting into Android, then issuing "reboot bootloader". U-Boot
>> is lacking the saveenv command, so it wasn't possible to change the bootdelay
>> to facilitate this.
> 
> Is it possible this change fixes your issue ?
> 
> http://git.denx.de/?p=u-boot.git;a=commit;h=c9e87ba66540cf72c164674a71af43853d087ba8

Actions is not yet supported in mainline U-Boot, and S500 boards did not
have a problem there. The saveenv command is simply not enabled in this
config deployed by Cubietech. Since I have not succeeded in getting a
self-built U-Boot booted from SD, I cannot test individual commits on
top either.

Maybe Cubietech or Actions can comment?

Regards,
Andreas

>> Cf. https://en.opensuse.org/HCL:CubieBoard7

-- 
SUSE Linux GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Felix Imendörffer, Jane Smithard, Graham Norton
HRB 21284 (AG Nürnberg)
--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* [PATCH v2] dt-bindings: mfd: mc13xxx: Add the unit address to sysled
From: Fabio Estevam @ 2017-12-07 12:00 UTC (permalink / raw)
  To: lee.jones-QSEj5FYQhm4dnm+yROfE0A
  Cc: robh+dt-DgEjT+Ai2ygdnm+yROfE0A, devicetree-u79uwXL29TY76Z2rM5mHXA,
	Fabio Estevam

From: Fabio Estevam <fabio.estevam-3arQi8VN3Tc@public.gmane.org>

As the 'reg' property is mandatory in the subnodes, improve the
example by adding the unit address to the sysled node.

This prevents the following build warning with W=1:

Node /soc/aips@70000000/spba@70000000/ecspi@70010000/pmic@0/leds/sysled has a reg or ranges property, but no unit name

Signed-off-by: Fabio Estevam <fabio.estevam-3arQi8VN3Tc@public.gmane.org>
Reviewed-by: Rob Herring <robh-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org>
---
Changes since v1:
- Use the correct name (sysled_ in the warning message (Rob)

 Documentation/devicetree/bindings/mfd/mc13xxx.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Documentation/devicetree/bindings/mfd/mc13xxx.txt b/Documentation/devicetree/bindings/mfd/mc13xxx.txt
index ac235fe..8261ea7 100644
--- a/Documentation/devicetree/bindings/mfd/mc13xxx.txt
+++ b/Documentation/devicetree/bindings/mfd/mc13xxx.txt
@@ -130,7 +130,7 @@ ecspi@70010000 { /* ECSPI1 */
 			#size-cells = <0>;
 			led-control = <0x000 0x000 0x0e0 0x000>;
 
-			sysled {
+			sysled@3 {
 				reg = <3>;
 				label = "system:red:live";
 				linux,default-trigger = "heartbeat";
-- 
2.7.4

--
To unsubscribe from this list: send the line "unsubscribe devicetree" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply related

* Re: [RFC 2/2] drivers: dma-mapping: parse per device reserved mem at probe time
From: Marek Szyprowski @ 2017-12-07 12:01 UTC (permalink / raw)
  To: Peng Fan
  Cc: Peng Fan, hch, robin.murphy, gregkh, robh+dt, frowand.list, iommu,
	linux-kernel, devicetree
In-Reply-To: <20171127090409.posgikgumpoq4wdm@linux-u7w5.ap.freescale.net>

Hi Peng,

On 2017-11-27 10:04, Peng Fan wrote:
> On Mon, Nov 27, 2017 at 09:44:20AM +0100, Marek Szyprowski wrote:
>> On 2017-11-27 09:37, Peng Fan wrote:
>>> On Mon, Nov 27, 2017 at 09:31:00AM +0100, Marek Szyprowski wrote:
>>>> On 2017-11-26 14:13, Peng Fan wrote:
>>>>> Invoke of_reserved_mem_device_init at dma_configure, then
>>>>> there is no need to call of_reserved_mem_device_init in device
>>>>> specific probe function.
>>>>>
>>>>> Signed-off-by: Peng Fan <peng.fan@nxp.com>
>>>> This has been already tried long time ago, without success:
>>>> http://patches.linaro.org/patch/33558/
>>> Thanks for the info. I should first search mail list before
>>> sending out patches.
>> It doesn't mean that I'm against such idea. I just pointed that I've
>> already tried. That time, however there was no dma_configure() function
>> yet, which seems to be better place for of_rmem_device_init().
>>
>> I would however always call of_dma_configure(), even when reserved mem
>> node is there. IIRC on ARM64 that function configures dma_ops, without
>> which no dma is possible at all.
> So, you prefer this?
> 	if (dma_dev->of_node) {
> +		of_reserved_mem_device_init(dev);
> 		ret = of_dma_configure(dev, dma_dev->of_node);
>
> However in of_reserved_mem_device, there is also an call to
> of_dma_configure.
>
> "
> 	/* ensure that dma_ops is set for virtual devices
> 	 * using reserved memory
> 	 */
> 	 ret = of_dma_configure(dev, np);
> "
>
> If always call of_dma_configure, of_dma_configure maybe called twice.

Right, I forgot about this.

> I just checked more. of_reserved_mem_device_init only handle the first
> memory-region. To nodes which have multiple memory-region, seems 2nd and etc
> could not be handled, such as drivers/media/platform/s5p-mfc/s5p_mfc.c.

Well, maybe automatic assignment should be done only when there is only
one reserved region set? In case more than one region assigned to a device,
the driver has to create virtual child devices and configure DMA for them
to be able to let dma-mapping API to use those reserved regions. It looks
that the call to of_dma_configure(dev, np) can be moved back to the driver
(it was not possible at the time that code was merged due to missing
export symbols).

Configuring more than one reserved memory region for given device might
then moved to some helper function to have a common code for that across
the drivers.

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland

^ permalink raw reply

* Re: [PATCH v2 16/19] ASoC: tlv320aic31xx: Add short circuit detection support
From: Mark Brown @ 2017-12-07 12:03 UTC (permalink / raw)
  To: Andrew F. Davis
  Cc: Mark Rutland, devicetree, alsa-devel, Tony Lindgren,
	Liam Girdwood, linux-kernel, Rob Herring, Benoît Cousson
In-Reply-To: <fd362117-ae71-a6a2-eb43-70c2457c0a5d@ti.com>


[-- Attachment #1.1: Type: text/plain, Size: 992 bytes --]

On Wed, Dec 06, 2017 at 02:22:39PM -0600, Andrew F. Davis wrote:
> On 12/01/2017 09:32 AM, Andrew F. Davis wrote:

> >> This will report the interrupt as handled even if we didn't see an
> >> interrupt we understand which will break shared interrupt lines.  At the
> >> very least we should log other interrupt sources numerically.

> > Okay, I think I can make that work by checking if no bits are set in the
> > interrupt regs and returning early if not, IRQ_NONE.

> This turned out to be more difficult than I expected, plus if I do
> handle an interrupt it doesn't mean the other device did not right? So
> this wouldn't fix shared lines as far as I can tell, but I don't
> register it as shared so this should be fine.

It'll mean that we don't offer the interrupt to anything else sharing
the line.

> As for your other suggestion of "log other interrupt sources
> numerically", could you explain this or point to an example of what you
> mean?

Just print out the bits that were set.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 488 bytes --]

[-- Attachment #2: Type: text/plain, Size: 0 bytes --]



^ permalink raw reply

* Re: [PATCH v3 08/15] drm/sun4i: Add LVDS support
From: Maxime Ripard @ 2017-12-07 12:25 UTC (permalink / raw)
  To: Chen-Yu Tsai
  Cc: Mark Rutland, Thomas Petazzoni, Jernej Skrabec, Priit Laes,
	devicetree, David Airlie, linux-kernel, dri-devel, Rob Herring,
	Daniel Vetter, linux-arm-kernel, Icenowy Zheng
In-Reply-To: <CAGb2v65Voua-AjHDnCLgDOKqUeSG-yD4wuSO5-BJ230FCp4OuQ@mail.gmail.com>


[-- Attachment #1.1: Type: text/plain, Size: 6914 bytes --]

Hi,

On Thu, Dec 07, 2017 at 02:05:47PM +0800, Chen-Yu Tsai wrote:
> > +static void sun4i_tcon_lvds_set_status(struct sun4i_tcon *tcon,
> > +                                      const struct drm_encoder *encoder,
> > +                                      bool enabled)
> > +{
> > +       if (enabled) {
> > +               u8 val;
> > +
> > +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
> > +                                  SUN4I_TCON0_LVDS_IF_EN,
> > +                                  SUN4I_TCON0_LVDS_IF_EN);
> > +
> > +               regmap_write(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> > +                            SUN4I_TCON0_LVDS_ANA0_C(2) |
> > +                            SUN4I_TCON0_LVDS_ANA0_V(3) |
> > +                            SUN4I_TCON0_LVDS_ANA0_PD(2) |
> > +                            SUN4I_TCON0_LVDS_ANA0_EN_LDO);
> > +               udelay(2);
> > +
> > +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> > +                                  SUN4I_TCON0_LVDS_ANA0_EN_MB,
> > +                                  SUN4I_TCON0_LVDS_ANA0_EN_MB);
> > +               udelay(2);
> > +
> > +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> > +                                  SUN4I_TCON0_LVDS_ANA0_EN_DRVC,
> > +                                  SUN4I_TCON0_LVDS_ANA0_EN_DRVC);
> > +
> > +               if (sun4i_tcon_get_pixel_depth(encoder) == 18)
> > +                       val = 7;
> > +               else
> > +                       val = 0xf;
> > +
> > +               regmap_write_bits(tcon->regs, SUN4I_TCON0_LVDS_ANA0_REG,
> > +                                 SUN4I_TCON0_LVDS_ANA0_EN_DRVD(0xf),
> > +                                 SUN4I_TCON0_LVDS_ANA0_EN_DRVD(val));
> 
> I suggest changing the prefix of the macros of the analog bits to
> SUN6I_TCON0_*. The register definitions and sequence do not apply
> to the A10/A20. Furthermore you should add a comment saying this
> doesn't apply to the A10/A20. In the future we might want to move
> this part into a separate function, referenced by a function pointer
> from the quirks structure.

I'll change the bit field names and add a comment like you suggested.

> > +       } else {
> > +               regmap_update_bits(tcon->regs, SUN4I_TCON0_LVDS_IF_REG,
> > +                                  SUN4I_TCON0_LVDS_IF_EN, 0);
> > +       }
> > +}
> > +
> >  void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
> >                            const struct drm_encoder *encoder,
> >                            bool enabled)
> >  {
> > +       bool is_lvds = false;
> >         int channel;
> >
> >         switch (encoder->encoder_type) {
> > +       case DRM_MODE_ENCODER_LVDS:
> > +               is_lvds = true;
> > +               /* Fallthrough */
> >         case DRM_MODE_ENCODER_NONE:
> >                 channel = 0;
> >                 break;
> > @@ -84,10 +171,16 @@ void sun4i_tcon_set_status(struct sun4i_tcon *tcon,
> >                 return;
> >         }
> >
> > +       if (is_lvds && !enabled)
> > +               sun4i_tcon_lvds_set_status(tcon, encoder, false);
> > +
> >         regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
> >                            SUN4I_TCON_GCTL_TCON_ENABLE,
> >                            enabled ? SUN4I_TCON_GCTL_TCON_ENABLE : 0);
> >
> > +       if (is_lvds && enabled)
> > +               sun4i_tcon_lvds_set_status(tcon, encoder, true);
> > +
> >         sun4i_tcon_channel_set_status(tcon, channel, enabled);
> >  }
> >
> > @@ -170,6 +263,78 @@ static void sun4i_tcon0_mode_set_common(struct sun4i_tcon *tcon,
> >                      SUN4I_TCON0_BASIC0_Y(mode->crtc_vdisplay));
> >  }
> >
> > +static void sun4i_tcon0_mode_set_lvds(struct sun4i_tcon *tcon,
> > +                                     const struct drm_encoder *encoder,
> > +                                     const struct drm_display_mode *mode)
> > +{
> > +       unsigned int bp;
> > +       u8 clk_delay;
> > +       u32 reg, val = 0;
> > +
> > +       tcon->dclk_min_div = 7;
> > +       tcon->dclk_max_div = 7;
> > +       sun4i_tcon0_mode_set_common(tcon, mode);
> > +
> > +       /* Adjust clock delay */
> > +       clk_delay = sun4i_tcon_get_clk_delay(mode, 0);
> > +       regmap_update_bits(tcon->regs, SUN4I_TCON0_CTL_REG,
> > +                          SUN4I_TCON0_CTL_CLK_DELAY_MASK,
> > +                          SUN4I_TCON0_CTL_CLK_DELAY(clk_delay));
> > +
> > +       /*
> > +        * This is called a backporch in the register documentation,
> > +        * but it really is the back porch + hsync
> > +        */
> > +       bp = mode->crtc_htotal - mode->crtc_hsync_start;
> > +       DRM_DEBUG_DRIVER("Setting horizontal total %d, backporch %d\n",
> > +                        mode->crtc_htotal, bp);
> > +
> > +       /* Set horizontal display timings */
> > +       regmap_write(tcon->regs, SUN4I_TCON0_BASIC1_REG,
> > +                    SUN4I_TCON0_BASIC1_H_TOTAL(mode->htotal) |
> > +                    SUN4I_TCON0_BASIC1_H_BACKPORCH(bp));
> > +
> > +       /*
> > +        * This is called a backporch in the register documentation,
> > +        * but it really is the back porch + hsync
> > +        */
> > +       bp = mode->crtc_vtotal - mode->crtc_vsync_start;
> > +       DRM_DEBUG_DRIVER("Setting vertical total %d, backporch %d\n",
> > +                        mode->crtc_vtotal, bp);
> > +
> > +       /* Set vertical display timings */
> > +       regmap_write(tcon->regs, SUN4I_TCON0_BASIC2_REG,
> > +                    SUN4I_TCON0_BASIC2_V_TOTAL(mode->crtc_vtotal * 2) |
> > +                    SUN4I_TCON0_BASIC2_V_BACKPORCH(bp));
> 
> Can we move the above to a common function?

Until we have DSI support figured out I'd rather not do too much of
consolidation. We know already a few things are going to change there
(like the clk_delay), but it's not clear yet how much.

> > +       /* Map output pins to channel 0 */
> > +       regmap_update_bits(tcon->regs, SUN4I_TCON_GCTL_REG,
> > +                          SUN4I_TCON_GCTL_IOMAP_MASK,
> > +                          SUN4I_TCON_GCTL_IOMAP_TCON0);
> > +
> > +       /* Enable the output on the pins */
> > +       regmap_write(tcon->regs, SUN4I_TCON0_IO_TRI_REG, 0xe0000000);
> 
> Is this still needed? You are no longer using the TCON LCD pins
> with LVDS.

We do. It's a separate function of the pins, but it's the same pins.

> >  static const struct sun4i_tcon_quirks sun6i_a31s_quirks = {
> >         .has_channel_1          = true,
> > +       .has_lvds_pll           = true,
> 
> The A31s does not have MIPI.

I'll change that.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

[-- Attachment #2: Type: text/plain, Size: 160 bytes --]

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

^ permalink raw reply

* Re: [PATCH V6 3/7] device property: Introduce a common API to fetch device match data
From: Sakari Ailus @ 2017-12-07 12:29 UTC (permalink / raw)
  To: Sinan Kaya
  Cc: dmaengine, timur, devicetree, linux-acpi, linux-arm-msm,
	linux-arm-kernel, Greg Kroah-Hartman, Rafael J. Wysocki,
	Len Brown, Mika Westerberg, Sakari Ailus, Dmitry Torokhov,
	Rob Herring, Kieran Bingham, open list
In-Reply-To: <1512493493-6464-4-git-send-email-okaya@codeaurora.org>

Hi Sinan,

Thanks for the update.

Just one small comment below.

On Tue, Dec 05, 2017 at 12:04:48PM -0500, Sinan Kaya wrote:
> There is an OF/ACPI function to obtain the driver data. We want to hide
> OF/ACPI details from the device drivers and abstract following the device
> family of functions.
> 
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
>  drivers/base/property.c  | 6 ++++++
>  include/linux/fwnode.h   | 4 ++++
>  include/linux/property.h | 2 ++
>  3 files changed, 12 insertions(+)
> 
> diff --git a/drivers/base/property.c b/drivers/base/property.c
> index 7ed99c1..65bf6f2 100644
> --- a/drivers/base/property.c
> +++ b/drivers/base/property.c
> @@ -1335,3 +1335,9 @@ int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
>  	return fwnode_call_int_op(fwnode, graph_parse_endpoint, endpoint);
>  }
>  EXPORT_SYMBOL(fwnode_graph_parse_endpoint);
> +
> +void *device_get_match_data(struct device *dev)
> +{
> +	return fwnode_call_ptr_op(dev_fwnode(dev), get_match_data, dev);
> +}
> +EXPORT_SYMBOL_GPL(device_get_match_data);
> diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
> index 0c35b6c..ab9aab5 100644
> --- a/include/linux/fwnode.h
> +++ b/include/linux/fwnode.h
> @@ -15,6 +15,7 @@
>  #include <linux/types.h>
>  
>  struct fwnode_operations;
> +struct device;
>  
>  struct fwnode_handle {
>  	struct fwnode_handle *secondary;
> @@ -66,6 +67,7 @@ struct fwnode_reference_args {
>   *			       endpoint node.
>   * @graph_get_port_parent: Return the parent node of a port node.
>   * @graph_parse_endpoint: Parse endpoint for port and endpoint id.
> + * @get_match_data: Return the driver match data.

Could you arrange the new get_match_data op closer to the other ops that
don't deal with the graphs? Such as device_is_available. As the ops are
dealing generally with fwnodes, I might call this device_get_match_data to
explicitly mention it's for devices.

>   */
>  struct fwnode_operations {
>  	void (*get)(struct fwnode_handle *fwnode);
> @@ -101,6 +103,8 @@ struct fwnode_operations {
>  	(*graph_get_port_parent)(struct fwnode_handle *fwnode);
>  	int (*graph_parse_endpoint)(const struct fwnode_handle *fwnode,
>  				    struct fwnode_endpoint *endpoint);
> +	void *(*get_match_data)(const struct fwnode_handle *fwnode,
> +				struct device *dev);

Same comment about the order here.

>  };
>  
>  #define fwnode_has_op(fwnode, op)				\
> diff --git a/include/linux/property.h b/include/linux/property.h
> index 6bebee1..01fa55b 100644
> --- a/include/linux/property.h
> +++ b/include/linux/property.h
> @@ -275,6 +275,8 @@ int device_add_properties(struct device *dev,
>  
>  enum dev_dma_attr device_get_dma_attr(struct device *dev);
>  
> +void *device_get_match_data(struct device *dev);
> +
>  int device_get_phy_mode(struct device *dev);
>  
>  void *device_get_mac_address(struct device *dev, char *addr, int alen);

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi

^ permalink raw reply

* Re: [PATCH V6 4/7] OF: properties: Implement get_match_data() callback
From: Sakari Ailus @ 2017-12-07 12:38 UTC (permalink / raw)
  To: Sinan Kaya
  Cc: dmaengine, timur, devicetree, linux-acpi, linux-arm-msm,
	linux-arm-kernel, Rob Herring, Frank Rowand, open list
In-Reply-To: <1512493493-6464-5-git-send-email-okaya@codeaurora.org>

Hi Sinan,

On Tue, Dec 05, 2017 at 12:04:49PM -0500, Sinan Kaya wrote:
> Now that we have a get_match_data() callback as part of the firmware node,
> implement the OF specific piece for it.
> 
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
>  drivers/of/property.c | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/drivers/of/property.c b/drivers/of/property.c
> index 264c355..9964169 100644
> --- a/drivers/of/property.c
> +++ b/drivers/of/property.c
> @@ -981,6 +981,12 @@ static int of_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
>  	return 0;
>  }
>  
> +void *of_fwnode_get_match_data(const struct fwnode_handle *fwnode,
> +			       struct device *dev)

static, as Rob mentioned.

> +{
> +	return (void *)of_device_get_match_data(dev);
> +}
> +
>  const struct fwnode_operations of_fwnode_ops = {
>  	.get = of_fwnode_get,
>  	.put = of_fwnode_put,
> @@ -996,5 +1002,6 @@ static int of_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
>  	.graph_get_remote_endpoint = of_fwnode_graph_get_remote_endpoint,
>  	.graph_get_port_parent = of_fwnode_graph_get_port_parent,
>  	.graph_parse_endpoint = of_fwnode_graph_parse_endpoint,
> +	.get_match_data = of_fwnode_get_match_data,

Please arrange right after device_is_available, the same applies to the
ACPI equivalent (5th patch).

>  };
>  EXPORT_SYMBOL_GPL(of_fwnode_ops);

With the above changes plus the ones in my comments on 3rd patch, on
patches 3--5:

Acked-by: Sakari Ailus <sakari.ailus@linux.intel.com>

-- 
Kind regards,

Sakari Ailus
e-mail: sakari.ailus@iki.fi

^ permalink raw reply

* Re: [PATCH V6 3/7] device property: Introduce a common API to fetch device match data
From: Sakari Ailus @ 2017-12-07 12:40 UTC (permalink / raw)
  To: Sinan Kaya
  Cc: dmaengine, timur, devicetree, linux-acpi, linux-arm-msm,
	linux-arm-kernel, Greg Kroah-Hartman, Rafael J. Wysocki,
	Len Brown, Mika Westerberg, Sakari Ailus, Dmitry Torokhov,
	Rob Herring, Kieran Bingham, open list
In-Reply-To: <1512493493-6464-4-git-send-email-okaya@codeaurora.org>

On Tue, Dec 05, 2017 at 12:04:48PM -0500, Sinan Kaya wrote:
> @@ -101,6 +103,8 @@ struct fwnode_operations {
>  	(*graph_get_port_parent)(struct fwnode_handle *fwnode);
>  	int (*graph_parse_endpoint)(const struct fwnode_handle *fwnode,
>  				    struct fwnode_endpoint *endpoint);
> +	void *(*get_match_data)(const struct fwnode_handle *fwnode,
> +				struct device *dev);

You can make dev const, too.

-- 
Sakari Ailus
e-mail: sakari.ailus@iki.fi

^ permalink raw reply

* Re: [PATCH V6 0/7] dmaengine: qcom_hidma: add support for bugfixed HW
From: Sakari Ailus @ 2017-12-07 12:41 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Sinan Kaya, Sakari Ailus, dmaengine, Timur Tabi,
	devicetree@vger.kernel.org, ACPI Devel Maling List, linux-arm-msm,
	linux-arm-kernel@lists.infradead.org
In-Reply-To: <CAJZ5v0gq-Xv1V90GEcfxdnrADQn2Gern=LBnsbSzmrU9M0+FEQ@mail.gmail.com>

On Tue, Dec 05, 2017 at 11:05:52PM +0100, Rafael J. Wysocki wrote:
> On Tue, Dec 5, 2017 at 6:04 PM, Sinan Kaya <okaya@codeaurora.org> wrote:
> > Introduce new ACPI and OF device ids for thw HW along with the helper
> > functions.
> >
> > Changes from v5:
> > * use struct device as a calling parameter to get_match_data() callback
> > so that we can reuse the existing OF API.
> > * revert the change on acpi_get_match_data() to V4.
> >
> > Sinan Kaya (7):
> >   Documentation: DT: qcom_hidma: Bump HW revision for the bugfixed HW
> >   ACPI / bus: Introduce acpi_get_match_data() function
> >   device property: Introduce a common API to fetch device match data
> >   OF: properties: Implement get_match_data() callback
> >   ACPI: properties: Implement get_match_data() callback
> >   dmaengine: qcom_hidma: Add support for the new revision
> >   dmaengine: qcom_hidma: Add identity register support
> 
> Sakari, can you please have a look at this series?
> 
> I'm particularly interested in your opinion on patches [2-3/7] and [5/7].

Reviewed. Thanks for the heads up!

-- 
Sakari Ailus
e-mail: sakari.ailus@iki.fi

^ permalink raw reply

* [PATCH V7 00/12] add clock driver for Spreadtrum platforms
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
  To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
  Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
	linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
	Ben Li, Orson Zhai, Chunyan Zhang

From: Chunyan Zhang <zhang.chunyan@linaro.org>

This series adds Spreadtrum clock support together with its binding
documentation and devicetree data.

Any comments would be greatly appreciated.

Thanks,
Chunyan

Changes from V6: (https://lkml.org/lkml/2017/11/27/217)
* Changed to use "//" format for the file header
* Addressed Stephen's comments:
  - Put the common macros in clk-provider.h instead of clk_common.h, also removed
    the same macros from sunxi-ng/ccu_common.h and zte/clk.h;
  - Removed CLK_FIXED_RATE(), and moved the fixed rate clocks from driver to DT;
  - Use devm_of_clk_add_hw_provider() instead;
  - Removed sprd_regmap_{read|write}(), use regmap API directly;
  - Removed all full stop on error messages.
* Use IS_ERR_OR_NULL() instead of IS_ERR() for checking regmap pointers;

Changes from V5: (https://lkml.org/lkml/2017/11/20/21)
* Rebased the whole patch-set to 4.15-rc1;
* Fixed kbuild-test warnings;
* Switched to use devm_clk_hw_register() instead of clk_hw_register();
* Removed useless debug information from sc9860-clk.c.

Changes from V4: (https://lkml.org/lkml/2017/11/10/30)
* Added acked-by of Rob Herring;
* Removed spin lock from Spreadtrum's gate, mux, div drivers, since we have
  switched to use regmap.

Changes from V3: (https://lkml.org/lkml/2017/11/2/61)
* Addressed comments from Julien Thierry:
  - Clean the if branch of sprd_mux_helper_get_parent()
  - Have the Gate clock macros and ops for both mode (i.e. sc_gate and gate) separate;
  - Have the Mux clock macros with/without table separate, and same changes
    for the composite clock.
* Switched the function name from _endisable to _toggle;
* Fixed Kbuild test error:
  - Added exporting sprd_clk_regmap_init() which would be used in other module(s);
* Change the function sprd_clk_set_regmap() to the static one, and removed the
  declear from the include file;
* Addressed comments from Rob:
  - Separate the dt-binding include file from the driver patch;
  - Documented more for the property "clocks"
* Changed the syscon device names;
* Changed the name of 'sprd_mux_internal' to 'sprd_mux_ssel'
  

Changes from V2: (http://lkml.iu.edu/hypermail/linux/kernel/1707.1/01504.html)
* Switch to use regmap to access registers;
* Splited all clocks into 16 separated nodes, for each belongs to a single address area; 
* Rearranged the order of clock declaration in sc9860-clk.c, sorted them upon the address area;
* Added syscon device tree nodes which will be quoted by the node of clocks which are in
  the same address area with the syscon device;
* Revised the binding documentation according to the dt modification. 

Changes from V1: (https://lkml.org/lkml/2017/6/17/356)
* Address Stephen's comments:
  - Switch to use platform device driver instead of the DT probing mechanism.
  - Move the common clock macro out from vendor directory, but need to remove those
    overlap code from other vendors (such as sunxi-ng) once this get merged.
  - Add support to be built as a module.
  - Add 'sprd_' prefix for all spin locks used in these drivers.
  - Mark input parameter of sprd_x with const.
  - Remove unreasonable dependencies to CONFIG_64BIT.
  - Add readl() after writing the same register.
  - Remove CLK_IS_BASIC which is no longer used.
  - Remove unnecessery CLK_IGNORE_UNUSED when defining a clock.
  - Change to expose all clock index.
  - Use clk_ instead of ccu.
  - Add Kconfig for sprd clocks.
  - Move the fixed clocks out from the soc node.
  - Switch to use 64-bit math in pll driver instead of 32-bit math.
* Revise binding documentation according to dt modification.
* Rename sc9860.c to sc9860-clk.c


Chunyan Zhang (12):
  drivers: move clock common macros out from vendor directories
  clk: sprd: Add common infrastructure
  clk: sprd: add gate clock support
  clk: sprd: add mux clock support
  clk: sprd: add divider clock support
  clk: sprd: add composite clock support
  clk: sprd: add adjustable pll support
  dt-bindings: Add Spreadtrum clock binding documentation
  clk: sprd: Add dt-bindings include file for SC9860
  clk: sprd: add clocks support for SC9860
  arm64: dts: add syscon for whale2 platform
  arm64: dts: add clocks for SC9860

 Documentation/devicetree/bindings/clock/sprd.txt |   63 +
 arch/arm64/boot/dts/sprd/sc9860.dtsi             |  115 ++
 arch/arm64/boot/dts/sprd/whale2.dtsi             |   62 +-
 drivers/clk/Kconfig                              |    1 +
 drivers/clk/Makefile                             |    1 +
 drivers/clk/sprd/Kconfig                         |   14 +
 drivers/clk/sprd/Makefile                        |   11 +
 drivers/clk/sprd/common.c                        |   96 ++
 drivers/clk/sprd/common.h                        |   38 +
 drivers/clk/sprd/composite.c                     |   60 +
 drivers/clk/sprd/composite.h                     |   51 +
 drivers/clk/sprd/div.c                           |   90 +
 drivers/clk/sprd/div.h                           |   75 +
 drivers/clk/sprd/gate.c                          |  111 ++
 drivers/clk/sprd/gate.h                          |   59 +
 drivers/clk/sprd/mux.c                           |   76 +
 drivers/clk/sprd/mux.h                           |   74 +
 drivers/clk/sprd/pll.c                           |  266 +++
 drivers/clk/sprd/pll.h                           |  108 ++
 drivers/clk/sprd/sc9860-clk.c                    | 1974 ++++++++++++++++++++++
 drivers/clk/sunxi-ng/ccu_common.h                |   29 -
 drivers/clk/zte/clk.h                            |   18 -
 include/dt-bindings/clock/sprd,sc9860-clk.h      |  404 +++++
 include/linux/clk-provider.h                     |   38 +
 24 files changed, 3785 insertions(+), 49 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt
 create mode 100644 drivers/clk/sprd/Kconfig
 create mode 100644 drivers/clk/sprd/Makefile
 create mode 100644 drivers/clk/sprd/common.c
 create mode 100644 drivers/clk/sprd/common.h
 create mode 100644 drivers/clk/sprd/composite.c
 create mode 100644 drivers/clk/sprd/composite.h
 create mode 100644 drivers/clk/sprd/div.c
 create mode 100644 drivers/clk/sprd/div.h
 create mode 100644 drivers/clk/sprd/gate.c
 create mode 100644 drivers/clk/sprd/gate.h
 create mode 100644 drivers/clk/sprd/mux.c
 create mode 100644 drivers/clk/sprd/mux.h
 create mode 100644 drivers/clk/sprd/pll.c
 create mode 100644 drivers/clk/sprd/pll.h
 create mode 100644 drivers/clk/sprd/sc9860-clk.c
 create mode 100644 include/dt-bindings/clock/sprd,sc9860-clk.h

-- 
2.7.4

^ permalink raw reply

* [PATCH V7 01/12] drivers: move clock common macros out from vendor directories
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
  To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
  Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
	linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
	Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>

These macros are used by more than one SoC vendor platforms, avoid to
have many copies of these code, this patch moves them to the common
header file which every clock drivers can access to.

Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 drivers/clk/sunxi-ng/ccu_common.h | 29 -----------------------------
 drivers/clk/zte/clk.h             | 18 ------------------
 include/linux/clk-provider.h      | 38 ++++++++++++++++++++++++++++++++++++++
 3 files changed, 38 insertions(+), 47 deletions(-)

diff --git a/drivers/clk/sunxi-ng/ccu_common.h b/drivers/clk/sunxi-ng/ccu_common.h
index 5d684ce..568cfae 100644
--- a/drivers/clk/sunxi-ng/ccu_common.h
+++ b/drivers/clk/sunxi-ng/ccu_common.h
@@ -31,35 +31,6 @@
 
 struct device_node;
 
-#define CLK_HW_INIT(_name, _parent, _ops, _flags)			\
-	&(struct clk_init_data) {					\
-		.flags		= _flags,				\
-		.name		= _name,				\
-		.parent_names	= (const char *[]) { _parent },		\
-		.num_parents	= 1,					\
-		.ops 		= _ops,					\
-	}
-
-#define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags)		\
-	&(struct clk_init_data) {					\
-		.flags		= _flags,				\
-		.name		= _name,				\
-		.parent_names	= _parents,				\
-		.num_parents	= ARRAY_SIZE(_parents),			\
-		.ops 		= _ops,					\
-	}
-
-#define CLK_FIXED_FACTOR(_struct, _name, _parent,			\
-			_div, _mult, _flags)				\
-	struct clk_fixed_factor _struct = {				\
-		.div		= _div,					\
-		.mult		= _mult,				\
-		.hw.init	= CLK_HW_INIT(_name,			\
-					      _parent,			\
-					      &clk_fixed_factor_ops,	\
-					      _flags),			\
-	}
-
 struct ccu_common {
 	void __iomem	*base;
 	u16		reg;
diff --git a/drivers/clk/zte/clk.h b/drivers/clk/zte/clk.h
index 4df0f12..f1041e3 100644
--- a/drivers/clk/zte/clk.h
+++ b/drivers/clk/zte/clk.h
@@ -14,24 +14,6 @@
 
 #define PNAME(x) static const char *x[]
 
-#define CLK_HW_INIT(_name, _parent, _ops, _flags)			\
-	&(struct clk_init_data) {					\
-		.flags		= _flags,				\
-		.name		= _name,				\
-		.parent_names	= (const char *[]) { _parent },		\
-		.num_parents	= 1,					\
-		.ops		= _ops,					\
-	}
-
-#define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags)		\
-	&(struct clk_init_data) {					\
-		.flags		= _flags,				\
-		.name		= _name,				\
-		.parent_names	= _parents,				\
-		.num_parents	= ARRAY_SIZE(_parents),			\
-		.ops		= _ops,					\
-	}
-
 struct zx_pll_config {
 	unsigned long rate;
 	u32 cfg0;
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h
index 7c925e6..26ea037 100644
--- a/include/linux/clk-provider.h
+++ b/include/linux/clk-provider.h
@@ -806,6 +806,44 @@ extern struct of_device_id __clk_of_table;
 	}								\
 	OF_DECLARE_1(clk, name, compat, name##_of_clk_init_driver)
 
+#define CLK_HW_INIT(_name, _parent, _ops, _flags)		\
+	(&(struct clk_init_data) {				\
+		.flags		= _flags,			\
+		.name		= _name,			\
+		.parent_names	= (const char *[]) { _parent },	\
+		.num_parents	= 1,				\
+		.ops		= _ops,				\
+	})
+
+#define CLK_HW_INIT_PARENTS(_name, _parents, _ops, _flags)	\
+	(&(struct clk_init_data) {				\
+		.flags		= _flags,			\
+		.name		= _name,			\
+		.parent_names	= _parents,			\
+		.num_parents	= ARRAY_SIZE(_parents),		\
+		.ops		= _ops,				\
+	})
+
+#define CLK_HW_INIT_NO_PARENT(_name, _ops, _flags)	\
+	(&(struct clk_init_data) {			\
+		.flags          = _flags,		\
+		.name           = _name,		\
+		.parent_names   = NULL,			\
+		.num_parents    = 0,			\
+		.ops            = _ops,			\
+	})
+
+#define CLK_FIXED_FACTOR(_struct, _name, _parent,			\
+			_div, _mult, _flags)				\
+	struct clk_fixed_factor _struct = {				\
+		.div		= _div,					\
+		.mult		= _mult,				\
+		.hw.init	= CLK_HW_INIT(_name,			\
+					      _parent,			\
+					      &clk_fixed_factor_ops,	\
+					      _flags),			\
+	}
+
 #ifdef CONFIG_OF
 int of_clk_add_provider(struct device_node *np,
 			struct clk *(*clk_src_get)(struct of_phandle_args *args,
-- 
2.7.4

^ permalink raw reply related

* [PATCH V7 02/12] clk: sprd: Add common infrastructure
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
  To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
  Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
	linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
	Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>

Added Spreadtrum's clock driver framework together with common
structures and interface functions.

Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 drivers/clk/Kconfig       |  1 +
 drivers/clk/Makefile      |  1 +
 drivers/clk/sprd/Kconfig  |  4 ++
 drivers/clk/sprd/Makefile |  3 ++
 drivers/clk/sprd/common.c | 96 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sprd/common.h | 38 +++++++++++++++++++
 6 files changed, 143 insertions(+)
 create mode 100644 drivers/clk/sprd/Kconfig
 create mode 100644 drivers/clk/sprd/Makefile
 create mode 100644 drivers/clk/sprd/common.c
 create mode 100644 drivers/clk/sprd/common.h

diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig
index 1c4e1aa..ce1a32be 100644
--- a/drivers/clk/Kconfig
+++ b/drivers/clk/Kconfig
@@ -236,6 +236,7 @@ source "drivers/clk/mvebu/Kconfig"
 source "drivers/clk/qcom/Kconfig"
 source "drivers/clk/renesas/Kconfig"
 source "drivers/clk/samsung/Kconfig"
+source "drivers/clk/sprd/Kconfig"
 source "drivers/clk/sunxi-ng/Kconfig"
 source "drivers/clk/tegra/Kconfig"
 source "drivers/clk/ti/Kconfig"
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index f7f761b..d880d13 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -85,6 +85,7 @@ obj-$(CONFIG_COMMON_CLK_SAMSUNG)	+= samsung/
 obj-$(CONFIG_ARCH_SIRF)			+= sirf/
 obj-$(CONFIG_ARCH_SOCFPGA)		+= socfpga/
 obj-$(CONFIG_PLAT_SPEAR)		+= spear/
+obj-$(CONFIG_ARCH_SPRD)			+= sprd/
 obj-$(CONFIG_ARCH_STI)			+= st/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi/
 obj-$(CONFIG_ARCH_SUNXI)		+= sunxi-ng/
diff --git a/drivers/clk/sprd/Kconfig b/drivers/clk/sprd/Kconfig
new file mode 100644
index 0000000..67a3287
--- /dev/null
+++ b/drivers/clk/sprd/Kconfig
@@ -0,0 +1,4 @@
+config SPRD_COMMON_CLK
+	tristate "Clock support for Spreadtrum SoCs"
+	depends on ARCH_SPRD || COMPILE_TEST
+	default ARCH_SPRD
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
new file mode 100644
index 0000000..74f4b80
--- /dev/null
+++ b/drivers/clk/sprd/Makefile
@@ -0,0 +1,3 @@
+obj-$(CONFIG_SPRD_COMMON_CLK)	+= clk-sprd.o
+
+clk-sprd-y	+= common.o
diff --git a/drivers/clk/sprd/common.c b/drivers/clk/sprd/common.c
new file mode 100644
index 0000000..e038b044
--- /dev/null
+++ b/drivers/clk/sprd/common.c
@@ -0,0 +1,96 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum clock infrastructure
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#include <linux/mfd/syscon.h>
+#include <linux/module.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+
+#include "common.h"
+
+static const struct regmap_config sprdclk_regmap_config = {
+	.reg_bits	= 32,
+	.reg_stride	= 4,
+	.val_bits	= 32,
+	.max_register	= 0xffff,
+	.fast_io	= true,
+};
+
+static void sprd_clk_set_regmap(const struct sprd_clk_desc *desc,
+			 struct regmap *regmap)
+{
+	int i;
+	struct sprd_clk_common *cclk;
+
+	for (i = 0; i < desc->num_clk_clks; i++) {
+		cclk = desc->clk_clks[i];
+		if (!cclk)
+			continue;
+
+		cclk->regmap = regmap;
+	}
+}
+
+int sprd_clk_regmap_init(struct platform_device *pdev,
+			 const struct sprd_clk_desc *desc)
+{
+	void __iomem *base;
+	struct device_node *node = pdev->dev.of_node;
+	struct regmap *regmap;
+
+	if (of_find_property(node, "sprd,syscon", NULL)) {
+		regmap = syscon_regmap_lookup_by_phandle(node, "sprd,syscon");
+		if (IS_ERR_OR_NULL(regmap)) {
+			pr_err("%s: failed to get syscon regmap\n", __func__);
+			return PTR_ERR(regmap);
+		}
+	} else {
+		base = of_iomap(node, 0);
+		regmap = devm_regmap_init_mmio(&pdev->dev, base,
+					       &sprdclk_regmap_config);
+		if (IS_ERR_OR_NULL(regmap)) {
+			pr_err("failed to init regmap\n");
+			return PTR_ERR(regmap);
+		}
+	}
+
+	sprd_clk_set_regmap(desc, regmap);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(sprd_clk_regmap_init);
+
+int sprd_clk_probe(struct device *dev, struct clk_hw_onecell_data *clkhw)
+{
+	int i, ret;
+	struct clk_hw *hw;
+
+	for (i = 0; i < clkhw->num; i++) {
+
+		hw = clkhw->hws[i];
+
+		if (!hw)
+			continue;
+
+		ret = devm_clk_hw_register(dev, hw);
+		if (ret) {
+			dev_err(dev, "Couldn't register clock %d - %s\n",
+				i, hw->init->name);
+			return ret;
+		}
+	}
+
+	ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clkhw);
+	if (ret)
+		dev_err(dev, "Failed to add clock provider\n");
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(sprd_clk_probe);
+
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/sprd/common.h b/drivers/clk/sprd/common.h
new file mode 100644
index 0000000..abd9ff5
--- /dev/null
+++ b/drivers/clk/sprd/common.h
@@ -0,0 +1,38 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum clock infrastructure
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#ifndef _SPRD_CLK_COMMON_H_
+#define _SPRD_CLK_COMMON_H_
+
+#include <linux/clk-provider.h>
+#include <linux/of_platform.h>
+#include <linux/regmap.h>
+
+struct device_node;
+
+struct sprd_clk_common {
+	struct regmap	*regmap;
+	u32		reg;
+	struct clk_hw	hw;
+};
+
+struct sprd_clk_desc {
+	struct sprd_clk_common		**clk_clks;
+	unsigned long			num_clk_clks;
+	struct clk_hw_onecell_data      *hw_clks;
+};
+
+static inline struct sprd_clk_common *
+	hw_to_sprd_clk_common(const struct clk_hw *hw)
+{
+	return container_of(hw, struct sprd_clk_common, hw);
+}
+int sprd_clk_regmap_init(struct platform_device *pdev,
+			 const struct sprd_clk_desc *desc);
+int sprd_clk_probe(struct device *dev, struct clk_hw_onecell_data *clkhw);
+
+#endif /* _SPRD_CLK_COMMON_H_ */
-- 
2.7.4

^ permalink raw reply related

* [PATCH V7 03/12] clk: sprd: add gate clock support
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
  To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
  Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
	linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
	Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>

Some clocks on the Spreadtrum's SoCs are just simple gates. Add
support for those clocks.

Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 drivers/clk/sprd/Makefile |   1 +
 drivers/clk/sprd/gate.c   | 111 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sprd/gate.h   |  59 ++++++++++++++++++++++++
 3 files changed, 171 insertions(+)
 create mode 100644 drivers/clk/sprd/gate.c
 create mode 100644 drivers/clk/sprd/gate.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 74f4b80..8cd5592 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -1,3 +1,4 @@
 obj-$(CONFIG_SPRD_COMMON_CLK)	+= clk-sprd.o
 
 clk-sprd-y	+= common.o
+clk-sprd-y	+= gate.o
diff --git a/drivers/clk/sprd/gate.c b/drivers/clk/sprd/gate.c
new file mode 100644
index 0000000..f59d193
--- /dev/null
+++ b/drivers/clk/sprd/gate.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum gate clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+
+#include "gate.h"
+
+static void clk_gate_toggle(const struct sprd_gate *sg, bool en)
+{
+	const struct sprd_clk_common *common = &sg->common;
+	unsigned int reg;
+	bool set = sg->flags & CLK_GATE_SET_TO_DISABLE ? true : false;
+
+	set ^= en;
+
+	regmap_read(common->regmap, common->reg, &reg);
+
+	if (set)
+		reg |= sg->enable_mask;
+	else
+		reg &= ~sg->enable_mask;
+
+	regmap_write(common->regmap, common->reg, reg);
+}
+
+static void clk_sc_gate_toggle(const struct sprd_gate *sg, bool en)
+{
+	const struct sprd_clk_common *common = &sg->common;
+	bool set = sg->flags & CLK_GATE_SET_TO_DISABLE ? 1 : 0;
+	unsigned int offset;
+
+	set ^= en;
+
+	/*
+	 * Each set/clear gate clock has three registers:
+	 * common->reg			- base register
+	 * common->reg + offset		- set register
+	 * common->reg + 2 * offset	- clear register
+	 */
+	offset = set ? sg->sc_offset : sg->sc_offset * 2;
+
+	regmap_write(common->regmap, common->reg + offset,
+			  sg->enable_mask);
+}
+
+static void sprd_gate_disable(struct clk_hw *hw)
+{
+	struct sprd_gate *sg = hw_to_sprd_gate(hw);
+
+	clk_gate_toggle(sg, false);
+}
+
+static int sprd_gate_enable(struct clk_hw *hw)
+{
+	struct sprd_gate *sg = hw_to_sprd_gate(hw);
+
+	clk_gate_toggle(sg, true);
+
+	return 0;
+}
+
+static void sprd_sc_gate_disable(struct clk_hw *hw)
+{
+	struct sprd_gate *sg = hw_to_sprd_gate(hw);
+
+	clk_sc_gate_toggle(sg, false);
+}
+
+static int sprd_sc_gate_enable(struct clk_hw *hw)
+{
+	struct sprd_gate *sg = hw_to_sprd_gate(hw);
+
+	clk_sc_gate_toggle(sg, true);
+
+	return 0;
+}
+static int sprd_gate_is_enabled(struct clk_hw *hw)
+{
+	struct sprd_gate *sg = hw_to_sprd_gate(hw);
+	struct sprd_clk_common *common = &sg->common;
+	unsigned int reg;
+
+	regmap_read(common->regmap, common->reg, &reg);
+
+	if (sg->flags & CLK_GATE_SET_TO_DISABLE)
+		reg ^= sg->enable_mask;
+
+	reg &= sg->enable_mask;
+
+	return reg ? 1 : 0;
+}
+
+const struct clk_ops sprd_gate_ops = {
+	.disable	= sprd_gate_disable,
+	.enable		= sprd_gate_enable,
+	.is_enabled	= sprd_gate_is_enabled,
+};
+EXPORT_SYMBOL_GPL(sprd_gate_ops);
+
+const struct clk_ops sprd_sc_gate_ops = {
+	.disable	= sprd_sc_gate_disable,
+	.enable		= sprd_sc_gate_enable,
+	.is_enabled	= sprd_gate_is_enabled,
+};
+EXPORT_SYMBOL_GPL(sprd_sc_gate_ops);
+
diff --git a/drivers/clk/sprd/gate.h b/drivers/clk/sprd/gate.h
new file mode 100644
index 0000000..2e582c6
--- /dev/null
+++ b/drivers/clk/sprd/gate.h
@@ -0,0 +1,59 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum gate clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#ifndef _SPRD_GATE_H_
+#define _SPRD_GATE_H_
+
+#include "common.h"
+
+struct sprd_gate {
+	u32			enable_mask;
+	u16			flags;
+	u16			sc_offset;
+
+	struct sprd_clk_common	common;
+};
+
+#define SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, _sc_offset,	\
+			     _enable_mask, _flags, _gate_flags, _ops)	\
+	struct sprd_gate _struct = {					\
+		.enable_mask	= _enable_mask,				\
+		.sc_offset	= _sc_offset,				\
+		.flags		= _gate_flags,				\
+		.common	= {						\
+			.regmap		= NULL,				\
+			.reg		= _reg,				\
+			.hw.init	= CLK_HW_INIT(_name,		\
+						      _parent,		\
+						      _ops,		\
+						      _flags),		\
+		}							\
+	}
+
+#define SPRD_GATE_CLK(_struct, _name, _parent, _reg,			\
+		      _enable_mask, _flags, _gate_flags)		\
+	SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, 0,		\
+			     _enable_mask, _flags, _gate_flags,		\
+			     &sprd_gate_ops)
+
+#define SPRD_SC_GATE_CLK(_struct, _name, _parent, _reg, _sc_offset,	\
+			 _enable_mask, _flags, _gate_flags)		\
+	SPRD_SC_GATE_CLK_OPS(_struct, _name, _parent, _reg, _sc_offset,	\
+			     _enable_mask, _flags, _gate_flags,		\
+			     &sprd_sc_gate_ops)
+
+static inline struct sprd_gate *hw_to_sprd_gate(const struct clk_hw *hw)
+{
+	struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
+
+	return container_of(common, struct sprd_gate, common);
+}
+
+extern const struct clk_ops sprd_gate_ops;
+extern const struct clk_ops sprd_sc_gate_ops;
+
+#endif /* _SPRD_GATE_H_ */
-- 
2.7.4

^ permalink raw reply related

* [PATCH V7 04/12] clk: sprd: add mux clock support
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
  To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
  Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
	linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
	Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>

This patch adds clock multiplexor support for Spreadtrum platforms,
the mux clocks also can be found in sprd composite clocks, so
provides two helpers that can be reused later on.

Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 drivers/clk/sprd/Makefile |  1 +
 drivers/clk/sprd/mux.c    | 76 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sprd/mux.h    | 74 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 151 insertions(+)
 create mode 100644 drivers/clk/sprd/mux.c
 create mode 100644 drivers/clk/sprd/mux.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 8cd5592..cee36b5 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -2,3 +2,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK)	+= clk-sprd.o
 
 clk-sprd-y	+= common.o
 clk-sprd-y	+= gate.o
+clk-sprd-y	+= mux.o
diff --git a/drivers/clk/sprd/mux.c b/drivers/clk/sprd/mux.c
new file mode 100644
index 0000000..624041b
--- /dev/null
+++ b/drivers/clk/sprd/mux.c
@@ -0,0 +1,76 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum multiplexer clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+
+#include "mux.h"
+
+u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common,
+			      const struct sprd_mux_ssel *mux)
+{
+	unsigned int reg;
+	u8 parent;
+	int num_parents;
+	int i;
+
+	regmap_read(common->regmap, common->reg, &reg);
+	parent = reg >> mux->shift;
+	parent &= (1 << mux->width) - 1;
+
+	if (!mux->table)
+		return parent;
+
+	num_parents = clk_hw_get_num_parents(&common->hw);
+
+	for (i = 0; i < num_parents - 1; i++)
+		if (parent >= mux->table[i] && parent < mux->table[i + 1])
+			return i;
+
+	return num_parents - 1;
+}
+EXPORT_SYMBOL_GPL(sprd_mux_helper_get_parent);
+
+static u8 sprd_mux_get_parent(struct clk_hw *hw)
+{
+	struct sprd_mux *cm = hw_to_sprd_mux(hw);
+
+	return sprd_mux_helper_get_parent(&cm->common, &cm->mux);
+}
+
+int sprd_mux_helper_set_parent(const struct sprd_clk_common *common,
+			       const struct sprd_mux_ssel *mux,
+			       u8 index)
+{
+	unsigned int reg;
+
+	if (mux->table)
+		index = mux->table[index];
+
+	regmap_read(common->regmap, common->reg, &reg);
+	reg &= ~GENMASK(mux->width + mux->shift - 1, mux->shift);
+	regmap_write(common->regmap, common->reg,
+			  reg | (index << mux->shift));
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(sprd_mux_helper_set_parent);
+
+static int sprd_mux_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct sprd_mux *cm = hw_to_sprd_mux(hw);
+
+	return sprd_mux_helper_set_parent(&cm->common, &cm->mux, index);
+}
+
+const struct clk_ops sprd_mux_ops = {
+	.get_parent = sprd_mux_get_parent,
+	.set_parent = sprd_mux_set_parent,
+	.determine_rate = __clk_mux_determine_rate,
+};
+EXPORT_SYMBOL_GPL(sprd_mux_ops);
diff --git a/drivers/clk/sprd/mux.h b/drivers/clk/sprd/mux.h
new file mode 100644
index 0000000..548cfa0
--- /dev/null
+++ b/drivers/clk/sprd/mux.h
@@ -0,0 +1,74 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum multiplexer clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#ifndef _SPRD_MUX_H_
+#define _SPRD_MUX_H_
+
+#include "common.h"
+
+/**
+ * struct sprd_mux_ssel - Mux clock's source select bits in its register
+ * @shift: Bit offset of the divider in its register
+ * @width: Width of the divider field in its register
+ * @table: For some mux clocks, not all sources are used on some special
+ *	   chips, this matches the value of mux clock's register and the
+ *	   sources which are used for this mux clock
+ */
+struct sprd_mux_ssel {
+	u8		shift;
+	u8		width;
+	const u8	*table;
+};
+
+struct sprd_mux {
+	struct sprd_mux_ssel mux;
+	struct sprd_clk_common	common;
+};
+
+#define _SPRD_MUX_CLK(_shift, _width, _table)		\
+	{						\
+		.shift	= _shift,			\
+		.width	= _width,			\
+		.table	= _table,			\
+	}
+
+#define SPRD_MUX_CLK_TABLE(_struct, _name, _parents, _table,		\
+				     _reg, _shift, _width,		\
+				     _flags)				\
+	struct sprd_mux _struct = {					\
+		.mux	= _SPRD_MUX_CLK(_shift, _width, _table),	\
+		.common	= {						\
+			.regmap		= NULL,				\
+			.reg		= _reg,				\
+			.hw.init = CLK_HW_INIT_PARENTS(_name,		\
+						       _parents,	\
+						       &sprd_mux_ops,	\
+						       _flags),		\
+		}							\
+	}
+
+#define SPRD_MUX_CLK(_struct, _name, _parents, _reg,		\
+		     _shift, _width, _flags)			\
+	SPRD_MUX_CLK_TABLE(_struct, _name, _parents, NULL,	\
+			   _reg, _shift, _width, _flags)
+
+static inline struct sprd_mux *hw_to_sprd_mux(const struct clk_hw *hw)
+{
+	struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
+
+	return container_of(common, struct sprd_mux, common);
+}
+
+extern const struct clk_ops sprd_mux_ops;
+
+u8 sprd_mux_helper_get_parent(const struct sprd_clk_common *common,
+			      const struct sprd_mux_ssel *mux);
+int sprd_mux_helper_set_parent(const struct sprd_clk_common *common,
+			       const struct sprd_mux_ssel *mux,
+			       u8 index);
+
+#endif /* _SPRD_MUX_H_ */
-- 
2.7.4

^ permalink raw reply related

* [PATCH V7 05/12] clk: sprd: add divider clock support
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
  To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
  Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
	linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
	Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>

This is a feature that can also be found in sprd composite clocks,
provide a bunch of helpers that can be reused later on.

Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 drivers/clk/sprd/Makefile |  1 +
 drivers/clk/sprd/div.c    | 90 +++++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sprd/div.h    | 75 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 166 insertions(+)
 create mode 100644 drivers/clk/sprd/div.c
 create mode 100644 drivers/clk/sprd/div.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index cee36b5..80e6039 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_SPRD_COMMON_CLK)	+= clk-sprd.o
 clk-sprd-y	+= common.o
 clk-sprd-y	+= gate.o
 clk-sprd-y	+= mux.o
+clk-sprd-y	+= div.o
diff --git a/drivers/clk/sprd/div.c b/drivers/clk/sprd/div.c
new file mode 100644
index 0000000..887a863
--- /dev/null
+++ b/drivers/clk/sprd/div.c
@@ -0,0 +1,90 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum divider clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#include <linux/clk-provider.h>
+
+#include "div.h"
+
+long sprd_div_helper_round_rate(struct sprd_clk_common *common,
+				const struct sprd_div_internal *div,
+				unsigned long rate,
+				unsigned long *parent_rate)
+{
+	return divider_round_rate(&common->hw, rate, parent_rate,
+				  NULL, div->width, 0);
+}
+EXPORT_SYMBOL_GPL(sprd_div_helper_round_rate);
+
+static long sprd_div_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *parent_rate)
+{
+	struct sprd_div *cd = hw_to_sprd_div(hw);
+
+	return sprd_div_helper_round_rate(&cd->common, &cd->div,
+					  rate, parent_rate);
+}
+
+unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
+					  const struct sprd_div_internal *div,
+					  unsigned long parent_rate)
+{
+	unsigned long val;
+	unsigned int reg;
+
+	regmap_read(common->regmap, common->reg, &reg);
+	val = reg >> div->shift;
+	val &= (1 << div->width) - 1;
+
+	return divider_recalc_rate(&common->hw, parent_rate, val, NULL, 0);
+}
+EXPORT_SYMBOL_GPL(sprd_div_helper_recalc_rate);
+
+static unsigned long sprd_div_recalc_rate(struct clk_hw *hw,
+					  unsigned long parent_rate)
+{
+	struct sprd_div *cd = hw_to_sprd_div(hw);
+
+	return sprd_div_helper_recalc_rate(&cd->common, &cd->div, parent_rate);
+}
+
+int sprd_div_helper_set_rate(const struct sprd_clk_common *common,
+			     const struct sprd_div_internal *div,
+			     unsigned long rate,
+			     unsigned long parent_rate)
+{
+	unsigned long val;
+	unsigned int reg;
+
+	val = divider_get_val(rate, parent_rate, NULL,
+			      div->width, 0);
+
+	regmap_read(common->regmap, common->reg, &reg);
+	reg &= ~GENMASK(div->width + div->shift - 1, div->shift);
+
+	regmap_write(common->regmap, common->reg,
+			  reg | (val << div->shift));
+
+	return 0;
+
+}
+EXPORT_SYMBOL_GPL(sprd_div_helper_set_rate);
+
+static int sprd_div_set_rate(struct clk_hw *hw, unsigned long rate,
+			     unsigned long parent_rate)
+{
+	struct sprd_div *cd = hw_to_sprd_div(hw);
+
+	return sprd_div_helper_set_rate(&cd->common, &cd->div,
+					rate, parent_rate);
+}
+
+const struct clk_ops sprd_div_ops = {
+	.recalc_rate = sprd_div_recalc_rate,
+	.round_rate = sprd_div_round_rate,
+	.set_rate = sprd_div_set_rate,
+};
+EXPORT_SYMBOL_GPL(sprd_div_ops);
diff --git a/drivers/clk/sprd/div.h b/drivers/clk/sprd/div.h
new file mode 100644
index 0000000..b3033d2
--- /dev/null
+++ b/drivers/clk/sprd/div.h
@@ -0,0 +1,75 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum divider clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#ifndef _SPRD_DIV_H_
+#define _SPRD_DIV_H_
+
+#include "common.h"
+
+/**
+ * struct sprd_div_internal - Internal divider description
+ * @shift: Bit offset of the divider in its register
+ * @width: Width of the divider field in its register
+ *
+ * That structure represents a single divider, and is meant to be
+ * embedded in other structures representing the various clock
+ * classes.
+ */
+struct sprd_div_internal {
+	u8	shift;
+	u8	width;
+};
+
+#define _SPRD_DIV_CLK(_shift, _width)	\
+	{				\
+		.shift	= _shift,	\
+		.width	= _width,	\
+	}
+
+struct sprd_div {
+	struct sprd_div_internal	div;
+	struct sprd_clk_common	common;
+};
+
+#define SPRD_DIV_CLK(_struct, _name, _parent, _reg,			\
+			_shift, _width, _flags)				\
+	struct sprd_div _struct = {					\
+		.div	= _SPRD_DIV_CLK(_shift, _width),		\
+		.common	= {						\
+			.regmap		= NULL,				\
+			.reg		= _reg,				\
+			.hw.init	= CLK_HW_INIT(_name,		\
+						      _parent,		\
+						      &sprd_div_ops,	\
+						      _flags),		\
+		}							\
+	}
+
+static inline struct sprd_div *hw_to_sprd_div(const struct clk_hw *hw)
+{
+	struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
+
+	return container_of(common, struct sprd_div, common);
+}
+
+long sprd_div_helper_round_rate(struct sprd_clk_common *common,
+				const struct sprd_div_internal *div,
+				unsigned long rate,
+				unsigned long *parent_rate);
+
+unsigned long sprd_div_helper_recalc_rate(struct sprd_clk_common *common,
+					  const struct sprd_div_internal *div,
+					  unsigned long parent_rate);
+
+int sprd_div_helper_set_rate(const struct sprd_clk_common *common,
+			     const struct sprd_div_internal *div,
+			     unsigned long rate,
+			     unsigned long parent_rate);
+
+extern const struct clk_ops sprd_div_ops;
+
+#endif /* _SPRD_DIV_H_ */
-- 
2.7.4

^ permalink raw reply related

* [PATCH V7 06/12] clk: sprd: add composite clock support
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
  To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
  Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
	linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
	Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>

This patch introduced composite driver for Spreadtrum's SoCs. The
functions of this composite clock simply consist of divider and
mux clocks.

Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 drivers/clk/sprd/Makefile    |  1 +
 drivers/clk/sprd/composite.c | 60 ++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sprd/composite.h | 51 +++++++++++++++++++++++++++++++++++++
 3 files changed, 112 insertions(+)
 create mode 100644 drivers/clk/sprd/composite.c
 create mode 100644 drivers/clk/sprd/composite.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 80e6039..2262e76 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -4,3 +4,4 @@ clk-sprd-y	+= common.o
 clk-sprd-y	+= gate.o
 clk-sprd-y	+= mux.o
 clk-sprd-y	+= div.o
+clk-sprd-y	+= composite.o
diff --git a/drivers/clk/sprd/composite.c b/drivers/clk/sprd/composite.c
new file mode 100644
index 0000000..ebb6448
--- /dev/null
+++ b/drivers/clk/sprd/composite.c
@@ -0,0 +1,60 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum composite clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#include <linux/clk-provider.h>
+
+#include "composite.h"
+
+static long sprd_comp_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *parent_rate)
+{
+	struct sprd_comp *cc = hw_to_sprd_comp(hw);
+
+	return sprd_div_helper_round_rate(&cc->common, &cc->div,
+					 rate, parent_rate);
+}
+
+static unsigned long sprd_comp_recalc_rate(struct clk_hw *hw,
+					  unsigned long parent_rate)
+{
+	struct sprd_comp *cc = hw_to_sprd_comp(hw);
+
+	return sprd_div_helper_recalc_rate(&cc->common, &cc->div, parent_rate);
+}
+
+static int sprd_comp_set_rate(struct clk_hw *hw, unsigned long rate,
+			     unsigned long parent_rate)
+{
+	struct sprd_comp *cc = hw_to_sprd_comp(hw);
+
+	return sprd_div_helper_set_rate(&cc->common, &cc->div,
+				       rate, parent_rate);
+}
+
+static u8 sprd_comp_get_parent(struct clk_hw *hw)
+{
+	struct sprd_comp *cc = hw_to_sprd_comp(hw);
+
+	return sprd_mux_helper_get_parent(&cc->common, &cc->mux);
+}
+
+static int sprd_comp_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct sprd_comp *cc = hw_to_sprd_comp(hw);
+
+	return sprd_mux_helper_set_parent(&cc->common, &cc->mux, index);
+}
+
+const struct clk_ops sprd_comp_ops = {
+	.get_parent	= sprd_comp_get_parent,
+	.set_parent	= sprd_comp_set_parent,
+
+	.round_rate	= sprd_comp_round_rate,
+	.recalc_rate	= sprd_comp_recalc_rate,
+	.set_rate	= sprd_comp_set_rate,
+};
+EXPORT_SYMBOL_GPL(sprd_comp_ops);
diff --git a/drivers/clk/sprd/composite.h b/drivers/clk/sprd/composite.h
new file mode 100644
index 0000000..0984e9e
--- /dev/null
+++ b/drivers/clk/sprd/composite.h
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum composite clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#ifndef _SPRD_COMPOSITE_H_
+#define _SPRD_COMPOSITE_H_
+
+#include "common.h"
+#include "mux.h"
+#include "div.h"
+
+struct sprd_comp {
+	struct sprd_mux_ssel	mux;
+	struct sprd_div_internal	div;
+	struct sprd_clk_common	common;
+};
+
+#define SPRD_COMP_CLK_TABLE(_struct, _name, _parent, _reg, _table,	\
+			_mshift, _mwidth, _dshift, _dwidth, _flags)	\
+	struct sprd_comp _struct = {					\
+		.mux	= _SPRD_MUX_CLK(_mshift, _mwidth, _table),	\
+		.div	= _SPRD_DIV_CLK(_dshift, _dwidth),		\
+		.common = {						\
+			.regmap		= NULL,				\
+			.reg		= _reg,				\
+			.hw.init = CLK_HW_INIT_PARENTS(_name,		\
+						       _parent,		\
+						       &sprd_comp_ops,	\
+						       _flags),		\
+			 }						\
+	}
+
+#define SPRD_COMP_CLK(_struct, _name, _parent, _reg, _mshift,	\
+			_mwidth, _dshift, _dwidth, _flags)	\
+	SPRD_COMP_CLK_TABLE(_struct, _name, _parent, _reg,	\
+			    NULL, _mshift, _mwidth,		\
+			    _dshift, _dwidth, _flags)
+
+static inline struct sprd_comp *hw_to_sprd_comp(const struct clk_hw *hw)
+{
+	struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
+
+	return container_of(common, struct sprd_comp, common);
+}
+
+extern const struct clk_ops sprd_comp_ops;
+
+#endif /* _SPRD_COMPOSITE_H_ */
-- 
2.7.4

^ permalink raw reply related

* [PATCH V7 07/12] clk: sprd: add adjustable pll support
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
  To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
  Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
	linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
	Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>

Introduced a common adjustable pll clock driver for Spreadtrum SoCs.

Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 drivers/clk/sprd/Makefile |   1 +
 drivers/clk/sprd/pll.c    | 266 ++++++++++++++++++++++++++++++++++++++++++++++
 drivers/clk/sprd/pll.h    | 108 +++++++++++++++++++
 3 files changed, 375 insertions(+)
 create mode 100644 drivers/clk/sprd/pll.c
 create mode 100644 drivers/clk/sprd/pll.h

diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index 2262e76..d693969 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -5,3 +5,4 @@ clk-sprd-y	+= gate.o
 clk-sprd-y	+= mux.o
 clk-sprd-y	+= div.o
 clk-sprd-y	+= composite.o
+clk-sprd-y	+= pll.o
diff --git a/drivers/clk/sprd/pll.c b/drivers/clk/sprd/pll.c
new file mode 100644
index 0000000..36b4402
--- /dev/null
+++ b/drivers/clk/sprd/pll.c
@@ -0,0 +1,266 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum pll clock driver
+//
+// Copyright (C) 2015~2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+
+#include "pll.h"
+
+#define CLK_PLL_1M	1000000
+#define CLK_PLL_10M	(CLK_PLL_1M * 10)
+
+#define pindex(pll, member)		\
+	(pll->factors[member].shift / (8 * sizeof(pll->regs_num)))
+
+#define pshift(pll, member)		\
+	(pll->factors[member].shift % (8 * sizeof(pll->regs_num)))
+
+#define pwidth(pll, member)		\
+	pll->factors[member].width
+
+#define pmask(pll, member)					\
+	((pwidth(pll, member)) ?				\
+	GENMASK(pwidth(pll, member) + pshift(pll, member) - 1,	\
+	pshift(pll, member)) : 0)
+
+#define pinternal(pll, cfg, member)	\
+	(cfg[pindex(pll, member)] & pmask(pll, member))
+
+#define pinternal_val(pll, cfg, member)	\
+	(pinternal(pll, cfg, member) >> pshift(pll, member))
+
+static inline unsigned int
+sprd_pll_read(const struct sprd_pll *pll, u8 index)
+{
+	const struct sprd_clk_common *common = &pll->common;
+	unsigned int val = 0;
+
+	if (WARN_ON(index >= pll->regs_num))
+		return 0;
+
+	regmap_read(common->regmap, common->reg + index * 4, &val);
+
+	return val;
+}
+
+static inline void
+sprd_pll_write(const struct sprd_pll *pll, u8 index,
+				  u32 msk, u32 val)
+{
+	const struct sprd_clk_common *common = &pll->common;
+	unsigned int offset, reg;
+	int ret = 0;
+
+	if (WARN_ON(index >= pll->regs_num))
+		return;
+
+	offset = common->reg + index * 4;
+	ret = regmap_read(common->regmap, offset, &reg);
+	if (!ret)
+		regmap_write(common->regmap, offset, (reg & ~msk) | val);
+}
+
+static unsigned long pll_get_refin(const struct sprd_pll *pll)
+{
+	u32 shift, mask, index, refin_id = 3;
+	const unsigned long refin[4] = { 2, 4, 13, 26 };
+
+	if (pwidth(pll, PLL_REFIN)) {
+		index = pindex(pll, PLL_REFIN);
+		shift = pshift(pll, PLL_REFIN);
+		mask = pmask(pll, PLL_REFIN);
+		refin_id = (sprd_pll_read(pll, index) & mask) >> shift;
+		if (refin_id > 3)
+			refin_id = 3;
+	}
+
+	return refin[refin_id];
+}
+
+static u32 pll_get_ibias(u64 rate, const u64 *table)
+{
+	u32 i, num = table[0];
+
+	for (i = 1; i < num + 1; i++)
+		if (rate <= table[i])
+			break;
+
+	return (i == num + 1) ? num : i;
+}
+
+static unsigned long _sprd_pll_recalc_rate(const struct sprd_pll *pll,
+					   unsigned long parent_rate)
+{
+	u32 *cfg;
+	u32 i, mask, regs_num = pll->regs_num;
+	unsigned long rate, nint, kint = 0;
+	u64 refin;
+	u16 k1, k2;
+
+	cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL);
+	if (!cfg)
+		return -ENOMEM;
+
+	for (i = 0; i < regs_num; i++)
+		cfg[i] = sprd_pll_read(pll, i);
+
+	refin = pll_get_refin(pll);
+
+	if (pinternal(pll, cfg, PLL_PREDIV))
+		refin = refin * 2;
+
+	if (pwidth(pll, PLL_POSTDIV) &&
+	    ((pll->fflag == 1 && pinternal(pll, cfg, PLL_POSTDIV)) ||
+	     (!pll->fflag && !pinternal(pll, cfg, PLL_POSTDIV))))
+		refin = refin / 2;
+
+	if (!pinternal(pll, cfg, PLL_DIV_S)) {
+		rate = refin * pinternal_val(pll, cfg, PLL_N) * CLK_PLL_10M;
+	} else {
+		nint = pinternal_val(pll, cfg, PLL_NINT);
+		if (pinternal(pll, cfg, PLL_SDM_EN))
+			kint = pinternal_val(pll, cfg, PLL_KINT);
+
+		mask = pmask(pll, PLL_KINT);
+
+		k1 = pll->k1;
+		k2 = pll->k2;
+		rate = DIV_ROUND_CLOSEST_ULL(refin * kint * k1,
+					 ((mask >> __ffs(mask)) + 1)) *
+					 k2 + refin * nint * CLK_PLL_1M;
+	}
+
+	return rate;
+}
+
+#define SPRD_PLL_WRITE_CHECK(pll, i, mask, val)		\
+	(((sprd_pll_read(pll, i) & mask) == val) ? 0 : (-EFAULT))
+
+static int _sprd_pll_set_rate(const struct sprd_pll *pll,
+			      unsigned long rate,
+			      unsigned long parent_rate)
+{
+	struct reg_cfg *cfg;
+	int ret = 0;
+	u32 mask, shift, width, ibias_val, index;
+	u32 regs_num = pll->regs_num, i = 0;
+	unsigned long kint, nint;
+	u64 tmp, refin, fvco = rate;
+
+	cfg = kcalloc(regs_num, sizeof(*cfg), GFP_KERNEL);
+	if (!cfg)
+		return -ENOMEM;
+
+	refin = pll_get_refin(pll);
+
+	mask = pmask(pll, PLL_PREDIV);
+	index = pindex(pll, PLL_PREDIV);
+	width = pwidth(pll, PLL_PREDIV);
+	if (width && (sprd_pll_read(pll, index) & mask))
+		refin = refin * 2;
+
+	mask = pmask(pll, PLL_POSTDIV);
+	index = pindex(pll, PLL_POSTDIV);
+	width = pwidth(pll, PLL_POSTDIV);
+	cfg[index].msk = mask;
+	if (width && ((pll->fflag == 1 && fvco <= pll->fvco) ||
+		      (pll->fflag == 0 && fvco > pll->fvco)))
+		cfg[index].val |= mask;
+
+	if (width && fvco <= pll->fvco)
+		fvco = fvco * 2;
+
+	mask = pmask(pll, PLL_DIV_S);
+	index = pindex(pll, PLL_DIV_S);
+	cfg[index].val |= mask;
+	cfg[index].msk |= mask;
+
+	mask = pmask(pll, PLL_SDM_EN);
+	index = pindex(pll, PLL_SDM_EN);
+	cfg[index].val |= mask;
+	cfg[index].msk |= mask;
+
+	nint = do_div(fvco, refin * CLK_PLL_1M);
+	mask = pmask(pll, PLL_NINT);
+	index = pindex(pll, PLL_NINT);
+	shift = pshift(pll, PLL_NINT);
+	cfg[index].val |= (nint << shift) & mask;
+	cfg[index].msk |= mask;
+
+	mask = pmask(pll, PLL_KINT);
+	index = pindex(pll, PLL_KINT);
+	width = pwidth(pll, PLL_KINT);
+	shift = pshift(pll, PLL_KINT);
+	tmp = fvco - refin * nint * CLK_PLL_1M;
+	tmp = do_div(tmp, 10000) * ((mask >> shift) + 1);
+	kint = DIV_ROUND_CLOSEST_ULL(tmp, refin * 100);
+	cfg[index].val |= (kint << shift) & mask;
+	cfg[index].msk |= mask;
+
+	ibias_val = pll_get_ibias(fvco, pll->itable);
+
+	mask = pmask(pll, PLL_IBIAS);
+	index = pindex(pll, PLL_IBIAS);
+	shift = pshift(pll, PLL_IBIAS);
+	cfg[index].val |= ibias_val << shift & mask;
+	cfg[index].msk |= mask;
+
+	for (i = 0; i < regs_num; i++) {
+		if (cfg[i].msk) {
+			sprd_pll_write(pll, i, cfg[i].msk, cfg[i].val);
+			ret |= SPRD_PLL_WRITE_CHECK(pll, i, cfg[i].msk,
+						   cfg[i].val);
+		}
+	}
+
+	if (!ret)
+		udelay(pll->udelay);
+
+	return ret;
+}
+
+static unsigned long sprd_pll_recalc_rate(struct clk_hw *hw,
+					  unsigned long parent_rate)
+{
+	struct sprd_pll *pll = hw_to_sprd_pll(hw);
+
+	return _sprd_pll_recalc_rate(pll, parent_rate);
+}
+
+static int sprd_pll_set_rate(struct clk_hw *hw,
+			     unsigned long rate,
+			     unsigned long parent_rate)
+{
+	struct sprd_pll *pll = hw_to_sprd_pll(hw);
+
+	return _sprd_pll_set_rate(pll, rate, parent_rate);
+}
+
+static int sprd_pll_clk_prepare(struct clk_hw *hw)
+{
+	struct sprd_pll *pll = hw_to_sprd_pll(hw);
+
+	udelay(pll->udelay);
+
+	return 0;
+}
+
+static long sprd_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long *prate)
+{
+	return rate;
+}
+
+const struct clk_ops sprd_pll_ops = {
+	.prepare = sprd_pll_clk_prepare,
+	.recalc_rate = sprd_pll_recalc_rate,
+	.round_rate = sprd_pll_round_rate,
+	.set_rate = sprd_pll_set_rate,
+};
+EXPORT_SYMBOL_GPL(sprd_pll_ops);
diff --git a/drivers/clk/sprd/pll.h b/drivers/clk/sprd/pll.h
new file mode 100644
index 0000000..5141756
--- /dev/null
+++ b/drivers/clk/sprd/pll.h
@@ -0,0 +1,108 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreadtrum pll clock driver
+//
+// Copyright (C) 2015~2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#ifndef _SPRD_PLL_H_
+#define _SPRD_PLL_H_
+
+#include "common.h"
+
+struct reg_cfg {
+	u32 val;
+	u32 msk;
+};
+
+struct clk_bit_field {
+	u8 shift;
+	u8 width;
+};
+
+enum {
+	PLL_LOCK_DONE,
+	PLL_DIV_S,
+	PLL_MOD_EN,
+	PLL_SDM_EN,
+	PLL_REFIN,
+	PLL_IBIAS,
+	PLL_N,
+	PLL_NINT,
+	PLL_KINT,
+	PLL_PREDIV,
+	PLL_POSTDIV,
+
+	PLL_FACT_MAX
+};
+
+/*
+ * struct sprd_pll - definition of adjustable pll clock
+ *
+ * @reg:	registers used to set the configuration of pll clock,
+ *		reg[0] shows how many registers this pll clock uses.
+ * @itable:	pll ibias table, itable[0] means how many items this
+ *		table includes
+ * @udelay	delay time after setting rate
+ * @factors	used to calculate the pll clock rate
+ * @fvco:	fvco threshold rate
+ * @fflag:	fvco flag
+ */
+struct sprd_pll {
+	u32 regs_num;
+	const u64 *itable;
+	const struct clk_bit_field *factors;
+	u16 udelay;
+	u16 k1;
+	u16 k2;
+	u16 fflag;
+	u64 fvco;
+
+	struct sprd_clk_common	common;
+};
+
+#define SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg,	\
+				    _regs_num, _itable, _factors,	\
+				    _udelay, _k1, _k2, _fflag, _fvco)	\
+	struct sprd_pll _struct = {					\
+		.regs_num	= _regs_num,				\
+		.itable		= _itable,				\
+		.factors	= _factors,				\
+		.udelay		= _udelay,				\
+		.k1		= _k1,					\
+		.k2		= _k2,					\
+		.fflag		= _fflag,				\
+		.fvco		= _fvco,				\
+		.common		= {					\
+			.regmap		= NULL,				\
+			.reg		= _reg,				\
+			.hw.init	= CLK_HW_INIT(_name,		\
+						      _parent,		\
+						      &sprd_pll_ops,	\
+						      0),		\
+		},							\
+	}
+
+#define SPRD_PLL_WITH_ITABLE_K(_struct, _name, _parent, _reg,		\
+			       _regs_num, _itable, _factors,		\
+			       _udelay, _k1, _k2)			\
+	SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg,	\
+				    _regs_num, _itable, _factors,	\
+				    _udelay, _k1, _k2, 0, 0)
+
+#define SPRD_PLL_WITH_ITABLE_1K(_struct, _name, _parent, _reg,		\
+				_regs_num, _itable, _factors, _udelay)	\
+	SPRD_PLL_WITH_ITABLE_K_FVCO(_struct, _name, _parent, _reg,	\
+				    _regs_num, _itable, _factors,	\
+				    _udelay, 1000, 1000, 0, 0)
+
+static inline struct sprd_pll *hw_to_sprd_pll(struct clk_hw *hw)
+{
+	struct sprd_clk_common *common = hw_to_sprd_clk_common(hw);
+
+	return container_of(common, struct sprd_pll, common);
+}
+
+extern const struct clk_ops sprd_pll_ops;
+
+#endif /* _SPRD_PLL_H_ */
-- 
2.7.4

^ permalink raw reply related

* [PATCH V7 08/12] dt-bindings: Add Spreadtrum clock binding documentation
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
  To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
  Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
	linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
	Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>

Introduce a new binding with its documentation for Spreadtrum clock
sub-framework.

Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
Acked-by: Rob Herring <robh@kernel.org>
---
 Documentation/devicetree/bindings/clock/sprd.txt | 63 ++++++++++++++++++++++++
 1 file changed, 63 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/clock/sprd.txt

diff --git a/Documentation/devicetree/bindings/clock/sprd.txt b/Documentation/devicetree/bindings/clock/sprd.txt
new file mode 100644
index 0000000..e9d179e
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/sprd.txt
@@ -0,0 +1,63 @@
+Spreadtrum Clock Binding
+------------------------
+
+Required properties:
+- compatible: should contain the following compatible strings:
+	- "sprd,sc9860-pmu-gate"
+	- "sprd,sc9860-pll"
+	- "sprd,sc9860-ap-clk"
+	- "sprd,sc9860-aon-prediv"
+	- "sprd,sc9860-apahb-gate"
+	- "sprd,sc9860-aon-gate"
+	- "sprd,sc9860-aonsecure-clk"
+	- "sprd,sc9860-agcp-gate"
+	- "sprd,sc9860-gpu-clk"
+	- "sprd,sc9860-vsp-clk"
+	- "sprd,sc9860-vsp-gate"
+	- "sprd,sc9860-cam-clk"
+	- "sprd,sc9860-cam-gate"
+	- "sprd,sc9860-disp-clk"
+	- "sprd,sc9860-disp-gate"
+	- "sprd,sc9860-apapb-gate"
+
+- #clock-cells: must be 1
+
+- clocks : Should be the input parent clock(s) phandle for the clock, this
+	   property here just simply shows which clock group the clocks'
+	   parents are in, since each clk node would represent many clocks
+	   which are defined in the driver.  The detailed dependency
+	   relationship (i.e. how many parents and which are the parents)
+	   are implemented in driver code.
+
+Optional properties:
+
+- reg:	Contain the registers base address and length. It must be configured
+	only if no 'sprd,syscon' under the node.
+
+- sprd,syscon: phandle to the syscon which is in the same address area with
+	       the clock, and so we can get regmap for the clocks from the
+	       syscon device.
+
+Example:
+
+	pmu_gate: pmu-gate {
+		compatible = "sprd,sc9860-pmu-gate";
+		sprd,syscon = <&pmu_regs>;
+		clocks = <&ext_26m>;
+		#clock-cells = <1>;
+	};
+
+	pll: pll {
+		compatible = "sprd,sc9860-pll";
+		sprd,syscon = <&ana_regs>;
+		clocks = <&pmu_gate 0>;
+		#clock-cells = <1>;
+	};
+
+	ap_clk: clock-controller@20000000 {
+		compatible = "sprd,sc9860-ap-clk";
+		reg = <0 0x20000000 0 0x400>;
+		clocks = <&ext_26m>, <&pll 0>,
+			 <&pmu_gate 0>;
+		#clock-cells = <1>;
+	};
-- 
2.7.4

^ permalink raw reply related

* [PATCH V7 09/12] clk: sprd: Add dt-bindings include file for SC9860
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
  To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
  Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
	linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
	Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>

This file defines all SC9860 clock indexes, it should be included in the
device tree in which there's device using the clocks.

Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
Acked-by: Rob Herring <robh@kernel.org>
---
 include/dt-bindings/clock/sprd,sc9860-clk.h | 404 ++++++++++++++++++++++++++++
 1 file changed, 404 insertions(+)
 create mode 100644 include/dt-bindings/clock/sprd,sc9860-clk.h

diff --git a/include/dt-bindings/clock/sprd,sc9860-clk.h b/include/dt-bindings/clock/sprd,sc9860-clk.h
new file mode 100644
index 0000000..4cb202f
--- /dev/null
+++ b/include/dt-bindings/clock/sprd,sc9860-clk.h
@@ -0,0 +1,404 @@
+// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
+//
+// Spreadtrum SC9860 platform clocks
+//
+// Copyright (C) 2017, Spreadtrum Communications Inc.
+
+#ifndef _DT_BINDINGS_CLK_SC9860_H_
+#define _DT_BINDINGS_CLK_SC9860_H_
+
+#define	CLK_FAC_4M		0
+#define	CLK_FAC_2M		1
+#define	CLK_FAC_1M		2
+#define	CLK_FAC_250K		3
+#define	CLK_FAC_RPLL0_26M	4
+#define	CLK_FAC_RPLL1_26M	5
+#define	CLK_FAC_RCO25M		6
+#define	CLK_FAC_RCO4M		7
+#define	CLK_FAC_RCO2M		8
+#define	CLK_FAC_3K2		9
+#define	CLK_FAC_1K		10
+#define	CLK_MPLL0_GATE		11
+#define	CLK_MPLL1_GATE		12
+#define	CLK_DPLL0_GATE		13
+#define	CLK_DPLL1_GATE		14
+#define	CLK_LTEPLL0_GATE	15
+#define	CLK_TWPLL_GATE		16
+#define	CLK_LTEPLL1_GATE	17
+#define	CLK_RPLL0_GATE		18
+#define	CLK_RPLL1_GATE		19
+#define	CLK_CPPLL_GATE		20
+#define	CLK_GPLL_GATE		21
+#define CLK_PMU_GATE_NUM	(CLK_GPLL_GATE + 1)
+
+#define	CLK_MPLL0		0
+#define	CLK_MPLL1		1
+#define	CLK_DPLL0		2
+#define	CLK_DPLL1		3
+#define	CLK_RPLL0		4
+#define	CLK_RPLL1		5
+#define	CLK_TWPLL		6
+#define	CLK_LTEPLL0		7
+#define	CLK_LTEPLL1		8
+#define	CLK_GPLL		9
+#define	CLK_CPPLL		10
+#define	CLK_GPLL_42M5		11
+#define	CLK_TWPLL_768M		12
+#define	CLK_TWPLL_384M		13
+#define	CLK_TWPLL_192M		14
+#define	CLK_TWPLL_96M		15
+#define	CLK_TWPLL_48M		16
+#define	CLK_TWPLL_24M		17
+#define	CLK_TWPLL_12M		18
+#define	CLK_TWPLL_512M		19
+#define	CLK_TWPLL_256M		20
+#define	CLK_TWPLL_128M		21
+#define	CLK_TWPLL_64M		22
+#define	CLK_TWPLL_307M2		23
+#define	CLK_TWPLL_153M6		24
+#define	CLK_TWPLL_76M8		25
+#define	CLK_TWPLL_51M2		26
+#define	CLK_TWPLL_38M4		27
+#define	CLK_TWPLL_19M2		28
+#define	CLK_L0_614M4		29
+#define	CLK_L0_409M6		30
+#define	CLK_L0_38M		31
+#define	CLK_L1_38M		32
+#define	CLK_RPLL0_192M		33
+#define	CLK_RPLL0_96M		34
+#define	CLK_RPLL0_48M		35
+#define	CLK_RPLL1_468M		36
+#define	CLK_RPLL1_192M		37
+#define	CLK_RPLL1_96M		38
+#define	CLK_RPLL1_64M		39
+#define	CLK_RPLL1_48M		40
+#define	CLK_DPLL0_50M		41
+#define	CLK_DPLL1_50M		42
+#define	CLK_CPPLL_50M		43
+#define	CLK_M0_39M		44
+#define	CLK_M1_63M		45
+#define CLK_PLL_NUM		(CLK_M1_63M + 1)
+
+
+#define	CLK_AP_APB		0
+#define	CLK_AP_USB3		1
+#define	CLK_UART0		2
+#define	CLK_UART1		3
+#define	CLK_UART2		4
+#define	CLK_UART3		5
+#define	CLK_UART4		6
+#define	CLK_I2C0		7
+#define	CLK_I2C1		8
+#define	CLK_I2C2		9
+#define	CLK_I2C3		10
+#define	CLK_I2C4		11
+#define	CLK_I2C5		12
+#define	CLK_SPI0		13
+#define	CLK_SPI1		14
+#define	CLK_SPI2		15
+#define	CLK_SPI3		16
+#define	CLK_IIS0		17
+#define	CLK_IIS1		18
+#define	CLK_IIS2		19
+#define	CLK_IIS3		20
+#define CLK_AP_CLK_NUM		(CLK_IIS3 + 1)
+
+#define	CLK_AON_APB		0
+#define	CLK_AUX0		1
+#define	CLK_AUX1		2
+#define	CLK_AUX2		3
+#define	CLK_PROBE		4
+#define	CLK_SP_AHB		5
+#define	CLK_CCI			6
+#define	CLK_GIC			7
+#define	CLK_CSSYS		8
+#define	CLK_SDIO0_2X		9
+#define	CLK_SDIO1_2X		10
+#define	CLK_SDIO2_2X		11
+#define	CLK_EMMC_2X		12
+#define	CLK_SDIO0_1X		13
+#define	CLK_SDIO1_1X		14
+#define	CLK_SDIO2_1X		15
+#define	CLK_EMMC_1X		16
+#define	CLK_ADI			17
+#define	CLK_PWM0		18
+#define	CLK_PWM1		19
+#define	CLK_PWM2		20
+#define	CLK_PWM3		21
+#define	CLK_EFUSE		22
+#define	CLK_CM3_UART0		23
+#define	CLK_CM3_UART1		24
+#define	CLK_THM			25
+#define	CLK_CM3_I2C0		26
+#define	CLK_CM3_I2C1		27
+#define	CLK_CM4_SPI		28
+#define	CLK_AON_I2C		29
+#define	CLK_AVS			30
+#define	CLK_CA53_DAP		31
+#define	CLK_CA53_TS		32
+#define	CLK_DJTAG_TCK		33
+#define	CLK_PMU			34
+#define	CLK_PMU_26M		35
+#define	CLK_DEBOUNCE		36
+#define	CLK_OTG2_REF		37
+#define	CLK_USB3_REF		38
+#define	CLK_AP_AXI		39
+#define CLK_AON_PREDIV_NUM	(CLK_AP_AXI + 1)
+
+#define	CLK_USB3_EB		0
+#define	CLK_USB3_SUSPEND_EB	1
+#define	CLK_USB3_REF_EB		2
+#define	CLK_DMA_EB		3
+#define	CLK_SDIO0_EB		4
+#define	CLK_SDIO1_EB		5
+#define	CLK_SDIO2_EB		6
+#define	CLK_EMMC_EB		7
+#define	CLK_ROM_EB		8
+#define	CLK_BUSMON_EB		9
+#define	CLK_CC63S_EB		10
+#define	CLK_CC63P_EB		11
+#define	CLK_CE0_EB		12
+#define	CLK_CE1_EB		13
+#define CLK_APAHB_GATE_NUM	(CLK_CE1_EB + 1)
+
+#define	CLK_AVS_LIT_EB		0
+#define	CLK_AVS_BIG_EB		1
+#define	CLK_AP_INTC5_EB		2
+#define	CLK_GPIO_EB		3
+#define	CLK_PWM0_EB		4
+#define	CLK_PWM1_EB		5
+#define	CLK_PWM2_EB		6
+#define	CLK_PWM3_EB		7
+#define	CLK_KPD_EB		8
+#define	CLK_AON_SYS_EB		9
+#define	CLK_AP_SYS_EB		10
+#define	CLK_AON_TMR_EB		11
+#define	CLK_AP_TMR0_EB		12
+#define	CLK_EFUSE_EB		13
+#define	CLK_EIC_EB		14
+#define	CLK_PUB1_REG_EB		15
+#define	CLK_ADI_EB		16
+#define	CLK_AP_INTC0_EB		17
+#define	CLK_AP_INTC1_EB		18
+#define	CLK_AP_INTC2_EB		19
+#define	CLK_AP_INTC3_EB		20
+#define	CLK_AP_INTC4_EB		21
+#define	CLK_SPLK_EB		22
+#define	CLK_MSPI_EB		23
+#define	CLK_PUB0_REG_EB		24
+#define	CLK_PIN_EB		25
+#define	CLK_AON_CKG_EB		26
+#define	CLK_GPU_EB		27
+#define	CLK_APCPU_TS0_EB	28
+#define	CLK_APCPU_TS1_EB	29
+#define	CLK_DAP_EB		30
+#define	CLK_I2C_EB		31
+#define	CLK_PMU_EB		32
+#define	CLK_THM_EB		33
+#define	CLK_AUX0_EB		34
+#define	CLK_AUX1_EB		35
+#define	CLK_AUX2_EB		36
+#define	CLK_PROBE_EB		37
+#define	CLK_GPU0_AVS_EB		38
+#define	CLK_GPU1_AVS_EB		39
+#define	CLK_APCPU_WDG_EB	40
+#define	CLK_AP_TMR1_EB		41
+#define	CLK_AP_TMR2_EB		42
+#define	CLK_DISP_EMC_EB		43
+#define	CLK_ZIP_EMC_EB		44
+#define	CLK_GSP_EMC_EB		45
+#define	CLK_OSC_AON_EB		46
+#define	CLK_LVDS_TRX_EB		47
+#define	CLK_LVDS_TCXO_EB	48
+#define	CLK_MDAR_EB		49
+#define	CLK_RTC4M0_CAL_EB	50
+#define	CLK_RCT100M_CAL_EB	51
+#define	CLK_DJTAG_EB		52
+#define	CLK_MBOX_EB		53
+#define	CLK_AON_DMA_EB		54
+#define	CLK_DBG_EMC_EB		55
+#define	CLK_LVDS_PLL_DIV_EN	56
+#define	CLK_DEF_EB		57
+#define	CLK_AON_APB_RSV0	58
+#define	CLK_ORP_JTAG_EB		59
+#define	CLK_VSP_EB		60
+#define	CLK_CAM_EB		61
+#define	CLK_DISP_EB		62
+#define	CLK_DBG_AXI_IF_EB	63
+#define	CLK_SDIO0_2X_EN		64
+#define	CLK_SDIO1_2X_EN		65
+#define	CLK_SDIO2_2X_EN		66
+#define	CLK_EMMC_2X_EN		67
+#define CLK_AON_GATE_NUM	(CLK_EMMC_2X_EN + 1)
+
+#define	CLK_LIT_MCU		0
+#define	CLK_BIG_MCU		1
+#define CLK_AONSECURE_NUM	(CLK_BIG_MCU + 1)
+
+#define	CLK_AGCP_IIS0_EB	0
+#define	CLK_AGCP_IIS1_EB	1
+#define	CLK_AGCP_IIS2_EB	2
+#define	CLK_AGCP_IIS3_EB	3
+#define	CLK_AGCP_UART_EB	4
+#define	CLK_AGCP_DMACP_EB	5
+#define	CLK_AGCP_DMAAP_EB	6
+#define	CLK_AGCP_ARC48K_EB	7
+#define	CLK_AGCP_SRC44P1K_EB	8
+#define	CLK_AGCP_MCDT_EB	9
+#define	CLK_AGCP_VBCIFD_EB	10
+#define	CLK_AGCP_VBC_EB		11
+#define	CLK_AGCP_SPINLOCK_EB	12
+#define	CLK_AGCP_ICU_EB		13
+#define	CLK_AGCP_AP_ASHB_EB	14
+#define	CLK_AGCP_CP_ASHB_EB	15
+#define	CLK_AGCP_AUD_EB		16
+#define	CLK_AGCP_AUDIF_EB	17
+#define CLK_AGCP_GATE_NUM	(CLK_AGCP_AUDIF_EB + 1)
+
+#define	CLK_GPU			0
+#define CLK_GPU_NUM		(CLK_GPU + 1)
+
+#define	CLK_AHB_VSP		0
+#define	CLK_VSP			1
+#define	CLK_VSP_ENC		2
+#define	CLK_VPP			3
+#define	CLK_VSP_26M		4
+#define CLK_VSP_NUM		(CLK_VSP_26M + 1)
+
+#define	CLK_VSP_DEC_EB		0
+#define	CLK_VSP_CKG_EB		1
+#define	CLK_VSP_MMU_EB		2
+#define	CLK_VSP_ENC_EB		3
+#define	CLK_VPP_EB		4
+#define	CLK_VSP_26M_EB		5
+#define	CLK_VSP_AXI_GATE	6
+#define	CLK_VSP_ENC_GATE	7
+#define	CLK_VPP_AXI_GATE	8
+#define	CLK_VSP_BM_GATE		9
+#define	CLK_VSP_ENC_BM_GATE	10
+#define	CLK_VPP_BM_GATE		11
+#define CLK_VSP_GATE_NUM	(CLK_VPP_BM_GATE + 1)
+
+#define	CLK_AHB_CAM		0
+#define	CLK_SENSOR0		1
+#define	CLK_SENSOR1		2
+#define	CLK_SENSOR2		3
+#define	CLK_MIPI_CSI0_EB	4
+#define	CLK_MIPI_CSI1_EB	5
+#define CLK_CAM_NUM		(CLK_MIPI_CSI1_EB + 1)
+
+#define	CLK_DCAM0_EB		0
+#define	CLK_DCAM1_EB		1
+#define	CLK_ISP0_EB		2
+#define	CLK_CSI0_EB		3
+#define	CLK_CSI1_EB		4
+#define	CLK_JPG0_EB		5
+#define	CLK_JPG1_EB		6
+#define	CLK_CAM_CKG_EB		7
+#define	CLK_CAM_MMU_EB		8
+#define	CLK_ISP1_EB		9
+#define	CLK_CPP_EB		10
+#define	CLK_MMU_PF_EB		11
+#define	CLK_ISP2_EB		12
+#define	CLK_DCAM2ISP_IF_EB	13
+#define	CLK_ISP2DCAM_IF_EB	14
+#define	CLK_ISP_LCLK_EB		15
+#define	CLK_ISP_ICLK_EB		16
+#define	CLK_ISP_MCLK_EB		17
+#define	CLK_ISP_PCLK_EB		18
+#define	CLK_ISP_ISP2DCAM_EB	19
+#define	CLK_DCAM0_IF_EB		20
+#define	CLK_CLK26M_IF_EB	21
+#define	CLK_CPHY0_GATE		22
+#define	CLK_MIPI_CSI0_GATE	23
+#define	CLK_CPHY1_GATE		24
+#define	CLK_MIPI_CSI1		25
+#define	CLK_DCAM0_AXI_GATE	26
+#define	CLK_DCAM1_AXI_GATE	27
+#define	CLK_SENSOR0_GATE	28
+#define	CLK_SENSOR1_GATE	29
+#define	CLK_JPG0_AXI_GATE	30
+#define	CLK_GPG1_AXI_GATE	31
+#define	CLK_ISP0_AXI_GATE	32
+#define	CLK_ISP1_AXI_GATE	33
+#define	CLK_ISP2_AXI_GATE	34
+#define	CLK_CPP_AXI_GATE	35
+#define	CLK_D0_IF_AXI_GATE	36
+#define	CLK_D2I_IF_AXI_GATE	37
+#define	CLK_I2D_IF_AXI_GATE	38
+#define	CLK_SPARE_AXI_GATE	39
+#define	CLK_SENSOR2_GATE	40
+#define	CLK_D0IF_IN_D_EN	41
+#define	CLK_D1IF_IN_D_EN	42
+#define	CLK_D0IF_IN_D2I_EN	43
+#define	CLK_D1IF_IN_D2I_EN	44
+#define	CLK_IA_IN_D2I_EN	45
+#define	CLK_IB_IN_D2I_EN	46
+#define	CLK_IC_IN_D2I_EN	47
+#define	CLK_IA_IN_I_EN		48
+#define	CLK_IB_IN_I_EN		49
+#define	CLK_IC_IN_I_EN		50
+#define CLK_CAM_GATE_NUM	(CLK_IC_IN_I_EN + 1)
+
+#define	CLK_AHB_DISP		0
+#define	CLK_DISPC0_DPI		1
+#define	CLK_DISPC1_DPI		2
+#define CLK_DISP_NUM		(CLK_DISPC1_DPI + 1)
+
+#define	CLK_DISPC0_EB		0
+#define	CLK_DISPC1_EB		1
+#define	CLK_DISPC_MMU_EB	2
+#define	CLK_GSP0_EB		3
+#define	CLK_GSP1_EB		4
+#define	CLK_GSP0_MMU_EB		5
+#define	CLK_GSP1_MMU_EB		6
+#define	CLK_DSI0_EB		7
+#define	CLK_DSI1_EB		8
+#define	CLK_DISP_CKG_EB		9
+#define	CLK_DISP_GPU_EB		10
+#define	CLK_GPU_MTX_EB		11
+#define	CLK_GSP_MTX_EB		12
+#define	CLK_TMC_MTX_EB		13
+#define	CLK_DISPC_MTX_EB	14
+#define	CLK_DPHY0_GATE		15
+#define	CLK_DPHY1_GATE		16
+#define	CLK_GSP0_A_GATE		17
+#define	CLK_GSP1_A_GATE		18
+#define	CLK_GSP0_F_GATE		19
+#define	CLK_GSP1_F_GATE		20
+#define	CLK_D_MTX_F_GATE	21
+#define	CLK_D_MTX_A_GATE	22
+#define	CLK_D_NOC_F_GATE	23
+#define	CLK_D_NOC_A_GATE	24
+#define	CLK_GSP_MTX_F_GATE	25
+#define	CLK_GSP_MTX_A_GATE	26
+#define	CLK_GSP_NOC_F_GATE	27
+#define	CLK_GSP_NOC_A_GATE	28
+#define	CLK_DISPM0IDLE_GATE	29
+#define	CLK_GSPM0IDLE_GATE	30
+#define CLK_DISP_GATE_NUM	(CLK_GSPM0IDLE_GATE + 1)
+
+#define	CLK_SIM0_EB		0
+#define	CLK_IIS0_EB		1
+#define	CLK_IIS1_EB		2
+#define	CLK_IIS2_EB		3
+#define	CLK_IIS3_EB		4
+#define	CLK_SPI0_EB		5
+#define	CLK_SPI1_EB		6
+#define	CLK_SPI2_EB		7
+#define	CLK_I2C0_EB		8
+#define	CLK_I2C1_EB		9
+#define	CLK_I2C2_EB		10
+#define	CLK_I2C3_EB		11
+#define	CLK_I2C4_EB		12
+#define	CLK_I2C5_EB		13
+#define	CLK_UART0_EB		14
+#define	CLK_UART1_EB		15
+#define	CLK_UART2_EB		16
+#define	CLK_UART3_EB		17
+#define	CLK_UART4_EB		18
+#define	CLK_AP_CKG_EB		19
+#define	CLK_SPI3_EB		20
+#define CLK_APAPB_GATE_NUM	(CLK_SPI3_EB + 1)
+
+#endif /* _DT_BINDINGS_CLK_SC9860_H_ */
-- 
2.7.4

^ permalink raw reply related

* [PATCH V7 10/12] clk: sprd: add clocks support for SC9860
From: Chunyan Zhang @ 2017-12-07 12:57 UTC (permalink / raw)
  To: Stephen Boyd, Michael Turquette, Rob Herring, Mark Rutland
  Cc: Catalin Marinas, Will Deacon, linux-clk, linux-kernel, devicetree,
	linux-arm-kernel, Arnd Bergmann, Mark Brown, Xiaolong Zhang,
	Ben Li, Orson Zhai, Chunyan Zhang
In-Reply-To: <20171207125715.16160-1-chunyan.zhang@spreadtrum.com>

This patch added the list of clocks for Spreadtrum's SC9860 SoC,
together with clock initialization code.

Signed-off-by: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
---
 drivers/clk/sprd/Kconfig      |   10 +
 drivers/clk/sprd/Makefile     |    3 +
 drivers/clk/sprd/sc9860-clk.c | 1974 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 1987 insertions(+)
 create mode 100644 drivers/clk/sprd/sc9860-clk.c

diff --git a/drivers/clk/sprd/Kconfig b/drivers/clk/sprd/Kconfig
index 67a3287..8789247 100644
--- a/drivers/clk/sprd/Kconfig
+++ b/drivers/clk/sprd/Kconfig
@@ -2,3 +2,13 @@ config SPRD_COMMON_CLK
 	tristate "Clock support for Spreadtrum SoCs"
 	depends on ARCH_SPRD || COMPILE_TEST
 	default ARCH_SPRD
+
+if SPRD_COMMON_CLK
+
+# SoC Drivers
+
+config SPRD_SC9860_CLK
+	tristate "Support for the Spreadtrum SC9860 clocks"
+	depends on (ARM64 && ARCH_SPRD) || COMPILE_TEST
+	default ARM64 && ARCH_SPRD
+endif
diff --git a/drivers/clk/sprd/Makefile b/drivers/clk/sprd/Makefile
index d693969..b0d81e5 100644
--- a/drivers/clk/sprd/Makefile
+++ b/drivers/clk/sprd/Makefile
@@ -6,3 +6,6 @@ clk-sprd-y	+= mux.o
 clk-sprd-y	+= div.o
 clk-sprd-y	+= composite.o
 clk-sprd-y	+= pll.o
+
+## SoC support
+obj-$(CONFIG_SPRD_SC9860_CLK)	+= sc9860-clk.o
diff --git a/drivers/clk/sprd/sc9860-clk.c b/drivers/clk/sprd/sc9860-clk.c
new file mode 100644
index 0000000..ed5c027
--- /dev/null
+++ b/drivers/clk/sprd/sc9860-clk.c
@@ -0,0 +1,1974 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// Spreatrum SC9860 clock driver
+//
+// Copyright (C) 2017 Spreadtrum, Inc.
+// Author: Chunyan Zhang <chunyan.zhang@spreadtrum.com>
+
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include <dt-bindings/clock/sprd,sc9860-clk.h>
+
+#include "common.h"
+#include "composite.h"
+#include "div.h"
+#include "gate.h"
+#include "mux.h"
+#include "pll.h"
+
+static CLK_FIXED_FACTOR(fac_4m,		"fac-4m",	"ext-26m",
+			6, 1, 0);
+static CLK_FIXED_FACTOR(fac_2m,		"fac-2m",	"ext-26m",
+			13, 1, 0);
+static CLK_FIXED_FACTOR(fac_1m,		"fac-1m",	"ext-26m",
+			26, 1, 0);
+static CLK_FIXED_FACTOR(fac_250k,	"fac-250k",	"ext-26m",
+			104, 1, 0);
+static CLK_FIXED_FACTOR(fac_rpll0_26m,	"rpll0-26m",	"ext-26m",
+			1, 1, 0);
+static CLK_FIXED_FACTOR(fac_rpll1_26m,	"rpll1-26m",	"ext-26m",
+			1, 1, 0);
+static CLK_FIXED_FACTOR(fac_rco_25m,	"rco-25m",	"ext-rc0-100m",
+			4, 1, 0);
+static CLK_FIXED_FACTOR(fac_rco_4m,	"rco-4m",	"ext-rc0-100m",
+			25, 1, 0);
+static CLK_FIXED_FACTOR(fac_rco_2m,	"rco-2m",	"ext-rc0-100m",
+			50, 1, 0);
+static CLK_FIXED_FACTOR(fac_3k2,	"fac-3k2",	"ext-32k",
+			10, 1, 0);
+static CLK_FIXED_FACTOR(fac_1k,		"fac-1k",	"ext-32k",
+			32, 1, 0);
+
+static SPRD_SC_GATE_CLK(mpll0_gate,	"mpll0-gate",	"ext-26m", 0xb0,
+		     0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(mpll1_gate,	"mpll1-gate",	"ext-26m", 0xb0,
+		     0x1000, BIT(18), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(dpll0_gate,	"dpll0-gate",	"ext-26m", 0xb4,
+		     0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(dpll1_gate,	"dpll1-gate",	"ext-26m", 0xb4,
+		     0x1000, BIT(18), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ltepll0_gate,	"ltepll0-gate",	"ext-26m", 0xb8,
+		     0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(twpll_gate,	"twpll-gate",	"ext-26m", 0xbc,
+		     0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ltepll1_gate,	"ltepll1-gate",	"ext-26m", 0x10c,
+		     0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(rpll0_gate,	"rpll0-gate",	"ext-26m", 0x16c,
+		     0x1000, BIT(2), 0, 0);
+static SPRD_SC_GATE_CLK(rpll1_gate,	"rpll1-gate",	"ext-26m", 0x16c,
+		     0x1000, BIT(18), 0, 0);
+static SPRD_SC_GATE_CLK(cppll_gate,	"cppll-gate",	"ext-26m", 0x2b4,
+		     0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(gpll_gate,	"gpll-gate",	"ext-26m", 0x32c,
+		0x1000, BIT(0), CLK_IGNORE_UNUSED, CLK_GATE_SET_TO_DISABLE);
+
+static struct sprd_clk_common *sc9860_pmu_gate_clks[] = {
+	/* address base is 0x402b0000 */
+	&mpll0_gate.common,
+	&mpll1_gate.common,
+	&dpll0_gate.common,
+	&dpll1_gate.common,
+	&ltepll0_gate.common,
+	&twpll_gate.common,
+	&ltepll1_gate.common,
+	&rpll0_gate.common,
+	&rpll1_gate.common,
+	&cppll_gate.common,
+	&gpll_gate.common,
+};
+
+static struct clk_hw_onecell_data sc9860_pmu_gate_hws = {
+	.hws	= {
+		[CLK_FAC_4M]		= &fac_4m.hw,
+		[CLK_FAC_2M]		= &fac_2m.hw,
+		[CLK_FAC_1M]		= &fac_1m.hw,
+		[CLK_FAC_250K]		= &fac_250k.hw,
+		[CLK_FAC_RPLL0_26M]	= &fac_rpll0_26m.hw,
+		[CLK_FAC_RPLL1_26M]	= &fac_rpll1_26m.hw,
+		[CLK_FAC_RCO25M]	= &fac_rco_25m.hw,
+		[CLK_FAC_RCO4M]		= &fac_rco_4m.hw,
+		[CLK_FAC_RCO2M]		= &fac_rco_2m.hw,
+		[CLK_FAC_3K2]		= &fac_3k2.hw,
+		[CLK_FAC_1K]		= &fac_1k.hw,
+		[CLK_MPLL0_GATE]	= &mpll0_gate.common.hw,
+		[CLK_MPLL1_GATE]	= &mpll1_gate.common.hw,
+		[CLK_DPLL0_GATE]	= &dpll0_gate.common.hw,
+		[CLK_DPLL1_GATE]	= &dpll1_gate.common.hw,
+		[CLK_LTEPLL0_GATE]	= &ltepll0_gate.common.hw,
+		[CLK_TWPLL_GATE]	= &twpll_gate.common.hw,
+		[CLK_LTEPLL1_GATE]	= &ltepll1_gate.common.hw,
+		[CLK_RPLL0_GATE]	= &rpll0_gate.common.hw,
+		[CLK_RPLL1_GATE]	= &rpll1_gate.common.hw,
+		[CLK_CPPLL_GATE]	= &cppll_gate.common.hw,
+		[CLK_GPLL_GATE]		= &gpll_gate.common.hw,
+	},
+	.num	= CLK_PMU_GATE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_pmu_gate_desc = {
+	.clk_clks	= sc9860_pmu_gate_clks,
+	.num_clk_clks	= ARRAY_SIZE(sc9860_pmu_gate_clks),
+	.hw_clks        = &sc9860_pmu_gate_hws,
+};
+
+/* GPLL/LPLL/DPLL/RPLL/CPLL */
+static const u64 itable1[4] = {3, 780000000, 988000000, 1196000000};
+
+/* TWPLL/MPLL0/MPLL1 */
+static const u64 itable2[4] = {3, 1638000000, 2080000000, 2600000000UL};
+
+static const struct clk_bit_field f_mpll0[PLL_FACT_MAX] = {
+	{ .shift = 20,	.width = 1 },	/* lock_done	*/
+	{ .shift = 19,	.width = 1 },	/* div_s	*/
+	{ .shift = 18,	.width = 1 },	/* mod_en	*/
+	{ .shift = 17,	.width = 1 },	/* sdm_en	*/
+	{ .shift = 0,	.width = 0 },	/* refin	*/
+	{ .shift = 11,	.width = 2 },	/* ibias	*/
+	{ .shift = 0,	.width = 7 },	/* n		*/
+	{ .shift = 57,	.width = 7 },	/* nint		*/
+	{ .shift = 32,	.width = 23},	/* kint		*/
+	{ .shift = 0,	.width = 0 },	/* prediv	*/
+	{ .shift = 56,	.width = 1 },	/* postdiv	*/
+};
+static SPRD_PLL_WITH_ITABLE_K_FVCO(mpll0_clk, "mpll0", "mpll0-gate", 0x24,
+				   2, itable2, f_mpll0, 200,
+				   1000, 1000, 1, 1300000000);
+
+static const struct clk_bit_field f_mpll1[PLL_FACT_MAX] = {
+	{ .shift = 20,	.width = 1 },	/* lock_done	*/
+	{ .shift = 19,	.width = 1 },	/* div_s	*/
+	{ .shift = 18,	.width = 1 },	/* mod_en	*/
+	{ .shift = 17,	.width = 1 },	/* sdm_en	*/
+	{ .shift = 0,	.width = 0 },	/* refin	*/
+	{ .shift = 11,	.width = 2 },	/* ibias	*/
+	{ .shift = 0,	.width = 7 },	/* n		*/
+	{ .shift = 57,	.width = 7 },	/* nint		*/
+	{ .shift = 32,	.width = 23},	/* kint		*/
+	{ .shift = 56,	.width = 1 },	/* prediv	*/
+	{ .shift = 0,	.width = 0 },	/* postdiv	*/
+};
+static SPRD_PLL_WITH_ITABLE_1K(mpll1_clk, "mpll1", "mpll1-gate", 0x2c,
+			       2, itable2, f_mpll1, 200);
+
+static const struct clk_bit_field f_dpll[PLL_FACT_MAX] = {
+	{ .shift = 16,	.width = 1 },	/* lock_done	*/
+	{ .shift = 15,	.width = 1 },	/* div_s	*/
+	{ .shift = 14,	.width = 1 },	/* mod_en	*/
+	{ .shift = 13,	.width = 1 },	/* sdm_en	*/
+	{ .shift = 0,	.width = 0 },	/* refin	*/
+	{ .shift = 8,	.width = 2 },	/* ibias	*/
+	{ .shift = 0,	.width = 7 },	/* n		*/
+	{ .shift = 57,	.width = 7 },	/* nint		*/
+	{ .shift = 32,	.width = 23},	/* kint		*/
+	{ .shift = 0,	.width = 0 },	/* prediv	*/
+	{ .shift = 0,	.width = 0 },	/* postdiv	*/
+};
+static SPRD_PLL_WITH_ITABLE_1K(dpll0_clk, "dpll0", "dpll0-gate", 0x34,
+			       2, itable1, f_dpll, 200);
+
+static SPRD_PLL_WITH_ITABLE_1K(dpll1_clk, "dpll1", "dpll1-gate", 0x3c,
+			       2, itable1, f_dpll, 200);
+
+static const struct clk_bit_field f_rpll[PLL_FACT_MAX] = {
+	{ .shift = 0,	.width = 1 },	/* lock_done	*/
+	{ .shift = 3,	.width = 1 },	/* div_s	*/
+	{ .shift = 80,	.width = 1 },	/* mod_en	*/
+	{ .shift = 81,	.width = 1 },	/* sdm_en	*/
+	{ .shift = 0,	.width = 0 },	/* refin	*/
+	{ .shift = 14,	.width = 2 },	/* ibias	*/
+	{ .shift = 16,	.width = 7 },	/* n		*/
+	{ .shift = 4,	.width = 7 },	/* nint		*/
+	{ .shift = 32,	.width = 23},	/* kint		*/
+	{ .shift = 0,	.width = 0 },	/* prediv	*/
+	{ .shift = 0,	.width = 0 },	/* postdiv	*/
+};
+static SPRD_PLL_WITH_ITABLE_1K(rpll0_clk, "rpll0", "rpll0-gate", 0x44,
+			       3, itable1, f_rpll, 200);
+
+static SPRD_PLL_WITH_ITABLE_1K(rpll1_clk, "rpll1", "rpll1-gate", 0x50,
+			       3, itable1, f_rpll, 200);
+
+static const struct clk_bit_field f_twpll[PLL_FACT_MAX] = {
+	{ .shift = 21,	.width = 1 },	/* lock_done	*/
+	{ .shift = 20,	.width = 1 },	/* div_s	*/
+	{ .shift = 19,	.width = 1 },	/* mod_en	*/
+	{ .shift = 18,	.width = 1 },	/* sdm_en	*/
+	{ .shift = 0,	.width = 0 },	/* refin	*/
+	{ .shift = 13,	.width = 2 },	/* ibias	*/
+	{ .shift = 0,	.width = 7 },	/* n		*/
+	{ .shift = 57,	.width = 7 },	/* nint		*/
+	{ .shift = 32,	.width = 23},	/* kint		*/
+	{ .shift = 0,	.width = 0 },	/* prediv	*/
+	{ .shift = 0,	.width = 0 },	/* postdiv	*/
+};
+static SPRD_PLL_WITH_ITABLE_1K(twpll_clk, "twpll", "twpll-gate", 0x5c,
+			       2, itable2, f_twpll, 200);
+
+static const struct clk_bit_field f_ltepll[PLL_FACT_MAX] = {
+	{ .shift = 31,	.width = 1 },	/* lock_done	*/
+	{ .shift = 27,	.width = 1 },	/* div_s	*/
+	{ .shift = 26,	.width = 1 },	/* mod_en	*/
+	{ .shift = 25,	.width = 1 },	/* sdm_en	*/
+	{ .shift = 0,	.width = 0 },	/* refin	*/
+	{ .shift = 20,	.width = 2 },	/* ibias	*/
+	{ .shift = 0,	.width = 7 },	/* n		*/
+	{ .shift = 57,	.width = 7 },	/* nint		*/
+	{ .shift = 32,	.width = 23},	/* kint		*/
+	{ .shift = 0,	.width = 0 },	/* prediv	*/
+	{ .shift = 0,	.width = 0 },	/* postdiv	*/
+};
+static SPRD_PLL_WITH_ITABLE_1K(ltepll0_clk, "ltepll0", "ltepll0-gate",
+			       0x64, 2, itable1,
+			       f_ltepll, 200);
+static SPRD_PLL_WITH_ITABLE_1K(ltepll1_clk, "ltepll1", "ltepll1-gate",
+			       0x6c, 2, itable1,
+			       f_ltepll, 200);
+
+static const struct clk_bit_field f_gpll[PLL_FACT_MAX] = {
+	{ .shift = 18,	.width = 1 },	/* lock_done	*/
+	{ .shift = 15,	.width = 1 },	/* div_s	*/
+	{ .shift = 14,	.width = 1 },	/* mod_en	*/
+	{ .shift = 13,	.width = 1 },	/* sdm_en	*/
+	{ .shift = 0,	.width = 0 },	/* refin	*/
+	{ .shift = 8,	.width = 2 },	/* ibias	*/
+	{ .shift = 0,	.width = 7 },	/* n		*/
+	{ .shift = 57,	.width = 7 },	/* nint		*/
+	{ .shift = 32,	.width = 23},	/* kint		*/
+	{ .shift = 0,	.width = 0 },	/* prediv	*/
+	{ .shift = 17,	.width = 1 },	/* postdiv	*/
+};
+static SPRD_PLL_WITH_ITABLE_K_FVCO(gpll_clk, "gpll", "gpll-gate", 0x9c,
+				   2, itable1, f_gpll, 200,
+				   1000, 1000, 1, 600000000);
+
+static const struct clk_bit_field f_cppll[PLL_FACT_MAX] = {
+	{ .shift = 17,	.width = 1 },	/* lock_done	*/
+	{ .shift = 15,	.width = 1 },	/* div_s	*/
+	{ .shift = 14,	.width = 1 },	/* mod_en	*/
+	{ .shift = 13,	.width = 1 },	/* sdm_en	*/
+	{ .shift = 0,	.width = 0 },	/* refin	*/
+	{ .shift = 8,	.width = 2 },	/* ibias	*/
+	{ .shift = 0,	.width = 7 },	/* n		*/
+	{ .shift = 57,	.width = 7 },	/* nint		*/
+	{ .shift = 32,	.width = 23},	/* kint		*/
+	{ .shift = 0,	.width = 0 },	/* prediv	*/
+	{ .shift = 0,	.width = 0 },	/* postdiv	*/
+};
+static SPRD_PLL_WITH_ITABLE_1K(cppll_clk, "cppll", "cppll-gate", 0xc4,
+			       2, itable1, f_cppll, 200);
+
+static CLK_FIXED_FACTOR(gpll_42m5, "gpll-42m5", "gpll", 20, 1, 0);
+static CLK_FIXED_FACTOR(twpll_768m, "twpll-768m", "twpll", 2, 1, 0);
+static CLK_FIXED_FACTOR(twpll_384m, "twpll-384m", "twpll", 4, 1, 0);
+static CLK_FIXED_FACTOR(twpll_192m, "twpll-192m", "twpll", 8, 1, 0);
+static CLK_FIXED_FACTOR(twpll_96m, "twpll-96m", "twpll", 16, 1, 0);
+static CLK_FIXED_FACTOR(twpll_48m, "twpll-48m", "twpll", 32, 1, 0);
+static CLK_FIXED_FACTOR(twpll_24m, "twpll-24m", "twpll", 64, 1, 0);
+static CLK_FIXED_FACTOR(twpll_12m, "twpll-12m", "twpll", 128, 1, 0);
+static CLK_FIXED_FACTOR(twpll_512m, "twpll-512m", "twpll", 3, 1, 0);
+static CLK_FIXED_FACTOR(twpll_256m, "twpll-256m", "twpll", 6, 1, 0);
+static CLK_FIXED_FACTOR(twpll_128m, "twpll-128m", "twpll", 12, 1, 0);
+static CLK_FIXED_FACTOR(twpll_64m, "twpll-64m", "twpll", 24, 1, 0);
+static CLK_FIXED_FACTOR(twpll_307m2, "twpll-307m2", "twpll", 5, 1, 0);
+static CLK_FIXED_FACTOR(twpll_153m6, "twpll-153m6", "twpll", 10, 1, 0);
+static CLK_FIXED_FACTOR(twpll_76m8, "twpll-76m8", "twpll", 20, 1, 0);
+static CLK_FIXED_FACTOR(twpll_51m2, "twpll-51m2", "twpll", 30, 1, 0);
+static CLK_FIXED_FACTOR(twpll_38m4, "twpll-38m4", "twpll", 40, 1, 0);
+static CLK_FIXED_FACTOR(twpll_19m2, "twpll-19m2", "twpll", 80, 1, 0);
+static CLK_FIXED_FACTOR(l0_614m4, "l0-614m4", "ltepll0", 2, 1, 0);
+static CLK_FIXED_FACTOR(l0_409m6, "l0-409m6", "ltepll0", 3, 1, 0);
+static CLK_FIXED_FACTOR(l0_38m, "l0-38m", "ltepll0", 32, 1, 0);
+static CLK_FIXED_FACTOR(l1_38m, "l1-38m", "ltepll1", 32, 1, 0);
+static CLK_FIXED_FACTOR(rpll0_192m, "rpll0-192m", "rpll0", 6, 1, 0);
+static CLK_FIXED_FACTOR(rpll0_96m, "rpll0-96m", "rpll0", 12, 1, 0);
+static CLK_FIXED_FACTOR(rpll0_48m, "rpll0-48m", "rpll0", 24, 1, 0);
+static CLK_FIXED_FACTOR(rpll1_468m, "rpll1-468m", "rpll1", 2, 1, 0);
+static CLK_FIXED_FACTOR(rpll1_192m, "rpll1-192m", "rpll1", 6, 1, 0);
+static CLK_FIXED_FACTOR(rpll1_96m, "rpll1-96m", "rpll1", 12, 1, 0);
+static CLK_FIXED_FACTOR(rpll1_64m, "rpll1-64m", "rpll1", 18, 1, 0);
+static CLK_FIXED_FACTOR(rpll1_48m, "rpll1-48m", "rpll1", 24, 1, 0);
+static CLK_FIXED_FACTOR(dpll0_50m, "dpll0-50m", "dpll0", 16, 1, 0);
+static CLK_FIXED_FACTOR(dpll1_50m, "dpll1-50m", "dpll1", 16, 1, 0);
+static CLK_FIXED_FACTOR(cppll_50m, "cppll-50m", "cppll", 18, 1, 0);
+static CLK_FIXED_FACTOR(m0_39m, "m0-39m", "mpll0", 32, 1, 0);
+static CLK_FIXED_FACTOR(m1_63m, "m1-63m", "mpll1", 32, 1, 0);
+
+static struct sprd_clk_common *sc9860_pll_clks[] = {
+	/* address base is 0x40400000 */
+	&mpll0_clk.common,
+	&mpll1_clk.common,
+	&dpll0_clk.common,
+	&dpll1_clk.common,
+	&rpll0_clk.common,
+	&rpll1_clk.common,
+	&twpll_clk.common,
+	&ltepll0_clk.common,
+	&ltepll1_clk.common,
+	&gpll_clk.common,
+	&cppll_clk.common,
+};
+
+static struct clk_hw_onecell_data sc9860_pll_hws = {
+	.hws	= {
+		[CLK_MPLL0]		= &mpll0_clk.common.hw,
+		[CLK_MPLL1]		= &mpll1_clk.common.hw,
+		[CLK_DPLL0]		= &dpll0_clk.common.hw,
+		[CLK_DPLL1]		= &dpll1_clk.common.hw,
+		[CLK_RPLL0]		= &rpll0_clk.common.hw,
+		[CLK_RPLL1]		= &rpll1_clk.common.hw,
+		[CLK_TWPLL]		= &twpll_clk.common.hw,
+		[CLK_LTEPLL0]		= &ltepll0_clk.common.hw,
+		[CLK_LTEPLL1]		= &ltepll1_clk.common.hw,
+		[CLK_GPLL]		= &gpll_clk.common.hw,
+		[CLK_CPPLL]		= &cppll_clk.common.hw,
+		[CLK_GPLL_42M5]		= &gpll_42m5.hw,
+		[CLK_TWPLL_768M]	= &twpll_768m.hw,
+		[CLK_TWPLL_384M]	= &twpll_384m.hw,
+		[CLK_TWPLL_192M]	= &twpll_192m.hw,
+		[CLK_TWPLL_96M]		= &twpll_96m.hw,
+		[CLK_TWPLL_48M]		= &twpll_48m.hw,
+		[CLK_TWPLL_24M]		= &twpll_24m.hw,
+		[CLK_TWPLL_12M]		= &twpll_12m.hw,
+		[CLK_TWPLL_512M]	= &twpll_512m.hw,
+		[CLK_TWPLL_256M]	= &twpll_256m.hw,
+		[CLK_TWPLL_128M]	= &twpll_128m.hw,
+		[CLK_TWPLL_64M]		= &twpll_64m.hw,
+		[CLK_TWPLL_307M2]	= &twpll_307m2.hw,
+		[CLK_TWPLL_153M6]	= &twpll_153m6.hw,
+		[CLK_TWPLL_76M8]	= &twpll_76m8.hw,
+		[CLK_TWPLL_51M2]	= &twpll_51m2.hw,
+		[CLK_TWPLL_38M4]	= &twpll_38m4.hw,
+		[CLK_TWPLL_19M2]	= &twpll_19m2.hw,
+		[CLK_L0_614M4]		= &l0_614m4.hw,
+		[CLK_L0_409M6]		= &l0_409m6.hw,
+		[CLK_L0_38M]		= &l0_38m.hw,
+		[CLK_L1_38M]		= &l1_38m.hw,
+		[CLK_RPLL0_192M]	= &rpll0_192m.hw,
+		[CLK_RPLL0_96M]		= &rpll0_96m.hw,
+		[CLK_RPLL0_48M]		= &rpll0_48m.hw,
+		[CLK_RPLL1_468M]	= &rpll1_468m.hw,
+		[CLK_RPLL1_192M]	= &rpll1_192m.hw,
+		[CLK_RPLL1_96M]		= &rpll1_96m.hw,
+		[CLK_RPLL1_64M]		= &rpll1_64m.hw,
+		[CLK_RPLL1_48M]		= &rpll1_48m.hw,
+		[CLK_DPLL0_50M]		= &dpll0_50m.hw,
+		[CLK_DPLL1_50M]		= &dpll1_50m.hw,
+		[CLK_CPPLL_50M]		= &cppll_50m.hw,
+		[CLK_M0_39M]		= &m0_39m.hw,
+		[CLK_M1_63M]		= &m1_63m.hw,
+	},
+	.num	= CLK_PLL_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_pll_desc = {
+	.clk_clks	= sc9860_pll_clks,
+	.num_clk_clks	= ARRAY_SIZE(sc9860_pll_clks),
+	.hw_clks	= &sc9860_pll_hws,
+};
+
+#define SC9860_MUX_FLAG	\
+	(CLK_GET_RATE_NOCACHE | CLK_SET_RATE_NO_REPARENT)
+
+static const char * const ap_apb_parents[] = { "ext-26m", "twpll-64m",
+					       "twpll-96m", "twpll-128m" };
+static SPRD_MUX_CLK(ap_apb, "ap-apb", ap_apb_parents,
+		    0x20, 0, 1, SC9860_MUX_FLAG);
+
+static const char * const ap_apb_usb3[] = { "ext-32k", "twpll-24m" };
+static SPRD_MUX_CLK(ap_usb3, "ap-usb3", ap_apb_usb3,
+		    0x2c, 0, 1, SC9860_MUX_FLAG);
+
+static const char * const uart_parents[] = {	"ext-26m",	"twpll-48m",
+						"twpll-51m2",	"twpll-96m" };
+static SPRD_COMP_CLK(uart0_clk,	"uart0",	uart_parents, 0x30,
+		     0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(uart1_clk,	"uart1",	uart_parents, 0x34,
+		     0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(uart2_clk,	"uart2",	uart_parents, 0x38,
+		     0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(uart3_clk,	"uart3",	uart_parents, 0x3c,
+		     0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(uart4_clk,	"uart4",	uart_parents, 0x40,
+		     0, 2, 8, 3, 0);
+
+static const char * const i2c_parents[] = { "ext-26m", "twpll-48m",
+					    "twpll-51m2", "twpll-153m6" };
+static SPRD_COMP_CLK(i2c0_clk,	"i2c0", i2c_parents, 0x44,
+		     0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(i2c1_clk,	"i2c1", i2c_parents, 0x48,
+		     0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(i2c2_clk,	"i2c2", i2c_parents, 0x4c,
+		     0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(i2c3_clk,	"i2c3", i2c_parents, 0x50,
+		     0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(i2c4_clk,	"i2c4", i2c_parents, 0x54,
+		     0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(i2c5_clk,	"i2c5", i2c_parents, 0x58,
+		     0, 2, 8, 3, 0);
+
+static const char * const spi_parents[] = {	"ext-26m",	"twpll-128m",
+						"twpll-153m6",	"twpll-192m" };
+static SPRD_COMP_CLK(spi0_clk,	"spi0",	spi_parents, 0x5c,
+		     0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(spi1_clk,	"spi1",	spi_parents, 0x60,
+		     0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(spi2_clk,	"spi2",	spi_parents, 0x64,
+		     0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(spi3_clk,	"spi3",	spi_parents, 0x68,
+		     0, 2, 8, 3, 0);
+
+static const char * const iis_parents[] = { "ext-26m",
+					    "twpll-128m",
+					    "twpll-153m6" };
+static SPRD_COMP_CLK(iis0_clk,	"iis0",	iis_parents, 0x6c,
+		     0, 2, 8, 6, 0);
+static SPRD_COMP_CLK(iis1_clk,	"iis1",	iis_parents, 0x70,
+		     0, 2, 8, 6, 0);
+static SPRD_COMP_CLK(iis2_clk,	"iis2",	iis_parents, 0x74,
+		     0, 2, 8, 6, 0);
+static SPRD_COMP_CLK(iis3_clk,	"iis3",	iis_parents, 0x78,
+		     0, 2, 8, 6, 0);
+
+static struct sprd_clk_common *sc9860_ap_clks[] = {
+	/* address base is 0x20000000 */
+	&ap_apb.common,
+	&ap_usb3.common,
+	&uart0_clk.common,
+	&uart1_clk.common,
+	&uart2_clk.common,
+	&uart3_clk.common,
+	&uart4_clk.common,
+	&i2c0_clk.common,
+	&i2c1_clk.common,
+	&i2c2_clk.common,
+	&i2c3_clk.common,
+	&i2c4_clk.common,
+	&i2c5_clk.common,
+	&spi0_clk.common,
+	&spi1_clk.common,
+	&spi2_clk.common,
+	&spi3_clk.common,
+	&iis0_clk.common,
+	&iis1_clk.common,
+	&iis2_clk.common,
+	&iis3_clk.common,
+};
+
+static struct clk_hw_onecell_data sc9860_ap_clk_hws = {
+	.hws	= {
+		[CLK_AP_APB]	= &ap_apb.common.hw,
+		[CLK_AP_USB3]	= &ap_usb3.common.hw,
+		[CLK_UART0]	= &uart0_clk.common.hw,
+		[CLK_UART1]	= &uart1_clk.common.hw,
+		[CLK_UART2]	= &uart2_clk.common.hw,
+		[CLK_UART3]	= &uart3_clk.common.hw,
+		[CLK_UART4]	= &uart4_clk.common.hw,
+		[CLK_I2C0]	= &i2c0_clk.common.hw,
+		[CLK_I2C1]	= &i2c1_clk.common.hw,
+		[CLK_I2C2]	= &i2c2_clk.common.hw,
+		[CLK_I2C3]	= &i2c3_clk.common.hw,
+		[CLK_I2C4]	= &i2c4_clk.common.hw,
+		[CLK_I2C5]	= &i2c5_clk.common.hw,
+		[CLK_SPI0]	= &spi0_clk.common.hw,
+		[CLK_SPI1]	= &spi1_clk.common.hw,
+		[CLK_SPI2]	= &spi2_clk.common.hw,
+		[CLK_SPI3]	= &spi3_clk.common.hw,
+		[CLK_IIS0]	= &iis0_clk.common.hw,
+		[CLK_IIS1]	= &iis1_clk.common.hw,
+		[CLK_IIS2]	= &iis2_clk.common.hw,
+		[CLK_IIS3]	= &iis3_clk.common.hw,
+	},
+	.num	= CLK_AP_CLK_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_ap_clk_desc = {
+	.clk_clks	= sc9860_ap_clks,
+	.num_clk_clks	= ARRAY_SIZE(sc9860_ap_clks),
+	.hw_clks	= &sc9860_ap_clk_hws,
+};
+
+static const char * const aon_apb_parents[] = { "rco-25m",	"ext-26m",
+						"ext-rco-100m",	"twpll-96m",
+						"twpll-128m",
+						"twpll-153m6" };
+static SPRD_COMP_CLK(aon_apb, "aon-apb", aon_apb_parents, 0x230,
+		     0, 3, 8, 2, 0);
+
+static const char * const aux_parents[] = { "ext-32k",		"rpll0-26m",
+					    "rpll1-26m",	"ext-26m",
+					    "cppll-50m",	"rco-25m",
+					    "dpll0-50m",	"dpll1-50m",
+					    "gpll-42m5",	"twpll-48m",
+					    "m0-39m",		"m1-63m",
+					    "l0-38m",		"l1-38m" };
+
+static SPRD_COMP_CLK(aux0_clk,	"aux0",		aux_parents, 0x238,
+		     0, 5, 8, 4, 0);
+static SPRD_COMP_CLK(aux1_clk,	"aux1",		aux_parents, 0x23c,
+		     0, 5, 8, 4, 0);
+static SPRD_COMP_CLK(aux2_clk,	"aux2",		aux_parents, 0x240,
+		     0, 5, 8, 4, 0);
+static SPRD_COMP_CLK(probe_clk,	"probe",	aux_parents, 0x244,
+		     0, 5, 8, 4, 0);
+
+static const char * const sp_ahb_parents[] = {	"rco-4m",	"ext-26m",
+						"ext-rco-100m",	"twpll-96m",
+						"twpll-128m",
+						"twpll-153m6" };
+static SPRD_COMP_CLK(sp_ahb,	"sp-ahb",	sp_ahb_parents, 0x2d0,
+		     0, 3, 8, 2, 0);
+
+static const char * const cci_parents[] = {	"ext-26m",	"twpll-384m",
+						"l0-614m4",	"twpll-768m" };
+static SPRD_COMP_CLK(cci_clk,	"cci",		cci_parents, 0x300,
+		     0, 2, 8, 2, 0);
+static SPRD_COMP_CLK(gic_clk,	"gic",		cci_parents, 0x304,
+		     0, 2, 8, 2, 0);
+static SPRD_COMP_CLK(cssys_clk,	"cssys",	cci_parents, 0x310,
+		     0, 2, 8, 2, 0);
+
+static const char * const sdio_2x_parents[] = {	"fac-1m",	"ext-26m",
+						"twpll-307m2",	"twpll-384m",
+						"l0-409m6" };
+static SPRD_COMP_CLK(sdio0_2x,	"sdio0-2x",	sdio_2x_parents, 0x328,
+		     0, 3, 8, 4, 0);
+static SPRD_COMP_CLK(sdio1_2x,	"sdio1-2x",	sdio_2x_parents, 0x330,
+		     0, 3, 8, 4, 0);
+static SPRD_COMP_CLK(sdio2_2x,	"sdio2-2x",	sdio_2x_parents, 0x338,
+		     0, 3, 8, 4, 0);
+static SPRD_COMP_CLK(emmc_2x,	"emmc-2x",	sdio_2x_parents, 0x340,
+		     0, 3, 8, 4, 0);
+
+static SPRD_DIV_CLK(sdio0_1x,	"sdio0-1x",	"sdio0-2x",	0x32c,
+		    8, 1, 0);
+static SPRD_DIV_CLK(sdio1_1x,	"sdio1-1x",	"sdio1-2x",	0x334,
+		    8, 1, 0);
+static SPRD_DIV_CLK(sdio2_1x,	"sdio2-1x",	"sdio2-2x",	0x33c,
+		    8, 1, 0);
+static SPRD_DIV_CLK(emmc_1x,	"emmc-1x",	"emmc-2x",	0x344,
+		    8, 1, 0);
+
+static const char * const adi_parents[] = {	"rco-4m",	"ext-26m",
+						"rco-25m",	"twpll-38m4",
+						"twpll-51m2" };
+static SPRD_MUX_CLK(adi_clk,	"adi",	adi_parents, 0x234,
+		    0, 3, SC9860_MUX_FLAG);
+
+static const char * const pwm_parents[] = {	"ext-32k",	"ext-26m",
+						"rco-4m",	"rco-25m",
+						"twpll-48m" };
+static SPRD_MUX_CLK(pwm0_clk,	"pwm0",	pwm_parents, 0x248,
+		    0, 3, SC9860_MUX_FLAG);
+static SPRD_MUX_CLK(pwm1_clk,	"pwm1",	pwm_parents, 0x24c,
+		    0, 3, SC9860_MUX_FLAG);
+static SPRD_MUX_CLK(pwm2_clk,	"pwm2",	pwm_parents, 0x250,
+		    0, 3, SC9860_MUX_FLAG);
+static SPRD_MUX_CLK(pwm3_clk,	"pwm3",	pwm_parents, 0x254,
+		    0, 3, SC9860_MUX_FLAG);
+
+static const char * const efuse_parents[] = { "rco-25m", "ext-26m" };
+static SPRD_MUX_CLK(efuse_clk, "efuse", efuse_parents, 0x258,
+		    0, 1, SC9860_MUX_FLAG);
+
+static const char * const cm3_uart_parents[] = { "rco-4m",	"ext-26m",
+						 "rco-100m",	"twpll-48m",
+						 "twpll-51m2",	"twpll-96m",
+						 "twpll-128m" };
+static SPRD_MUX_CLK(cm3_uart0, "cm3-uart0", cm3_uart_parents, 0x25c,
+		    0, 3, SC9860_MUX_FLAG);
+static SPRD_MUX_CLK(cm3_uart1, "cm3-uart1", cm3_uart_parents, 0x260,
+		    0, 3, SC9860_MUX_FLAG);
+
+static const char * const thm_parents[] = { "ext-32k", "fac-250k" };
+static SPRD_MUX_CLK(thm_clk,	"thm",	thm_parents, 0x270,
+		    0, 1, SC9860_MUX_FLAG);
+
+static const char * const cm3_i2c_parents[] = {	"rco-4m",
+						"ext-26m",
+						"rco-100m",
+						"twpll-48m",
+						"twpll-51m2",
+						"twpll-153m6" };
+static SPRD_MUX_CLK(cm3_i2c0, "cm3-i2c0", cm3_i2c_parents, 0x274,
+		    0, 3, SC9860_MUX_FLAG);
+static SPRD_MUX_CLK(cm3_i2c1, "cm3-i2c1", cm3_i2c_parents, 0x278,
+		    0, 3, SC9860_MUX_FLAG);
+static SPRD_MUX_CLK(aon_i2c, "aon-i2c",	cm3_i2c_parents, 0x280,
+		    0, 3, SC9860_MUX_FLAG);
+
+static const char * const cm4_spi_parents[] = {	"ext-26m",	"twpll-96m",
+						"rco-100m",	"twpll-128m",
+						"twpll-153m6",	"twpll-192m" };
+static SPRD_MUX_CLK(cm4_spi, "cm4-spi", cm4_spi_parents, 0x27c,
+		    0, 3, SC9860_MUX_FLAG);
+
+static SPRD_MUX_CLK(avs_clk, "avs", uart_parents, 0x284,
+		    0, 2, SC9860_MUX_FLAG);
+
+static const char * const ca53_dap_parents[] = { "ext-26m",	"rco-4m",
+						 "rco-100m",	"twpll-76m8",
+						 "twpll-128m",	"twpll-153m6" };
+static SPRD_MUX_CLK(ca53_dap, "ca53-dap", ca53_dap_parents, 0x288,
+		    0, 3, SC9860_MUX_FLAG);
+
+static const char * const ca53_ts_parents[] = {	"ext-32k", "ext-26m",
+						"clk-twpll-128m",
+						"clk-twpll-153m6" };
+static SPRD_MUX_CLK(ca53_ts, "ca53-ts", ca53_ts_parents, 0x290,
+		    0, 2, SC9860_MUX_FLAG);
+
+static const char * const djtag_tck_parents[] = { "rco-4m", "ext-26m" };
+static SPRD_MUX_CLK(djtag_tck, "djtag-tck", djtag_tck_parents, 0x2c8,
+		    0, 1, SC9860_MUX_FLAG);
+
+static const char * const pmu_parents[] = { "ext-32k", "rco-4m", "clk-4m" };
+static SPRD_MUX_CLK(pmu_clk, "pmu", pmu_parents, 0x2e0,
+		    0, 2, SC9860_MUX_FLAG);
+
+static const char * const pmu_26m_parents[] = { "rco-25m", "ext-26m" };
+static SPRD_MUX_CLK(pmu_26m, "pmu-26m", pmu_26m_parents, 0x2e4,
+		    0, 1, SC9860_MUX_FLAG);
+
+static const char * const debounce_parents[] = { "ext-32k", "rco-4m",
+						 "rco-25m", "ext-26m" };
+static SPRD_MUX_CLK(debounce_clk, "debounce", debounce_parents, 0x2e8,
+		    0, 2, SC9860_MUX_FLAG);
+
+static const char * const otg2_ref_parents[] = { "twpll-12m", "twpll-24m" };
+static SPRD_MUX_CLK(otg2_ref, "otg2-ref", otg2_ref_parents, 0x2f4,
+		    0, 1, SC9860_MUX_FLAG);
+
+static const char * const usb3_ref_parents[] = { "twpll-24m", "twpll-19m2",
+						 "twpll-48m" };
+static SPRD_MUX_CLK(usb3_ref, "usb3-ref", usb3_ref_parents, 0x2f8,
+		    0, 2, SC9860_MUX_FLAG);
+
+static const char * const ap_axi_parents[] = { "ext-26m", "twpll-76m8",
+					       "twpll-128m", "twpll-256m" };
+static SPRD_MUX_CLK(ap_axi, "ap-axi", ap_axi_parents, 0x324,
+		    0, 2, SC9860_MUX_FLAG);
+
+static struct sprd_clk_common *sc9860_aon_prediv[] = {
+	/* address base is 0x402d0000 */
+	&aon_apb.common,
+	&aux0_clk.common,
+	&aux1_clk.common,
+	&aux2_clk.common,
+	&probe_clk.common,
+	&sp_ahb.common,
+	&cci_clk.common,
+	&gic_clk.common,
+	&cssys_clk.common,
+	&sdio0_2x.common,
+	&sdio1_2x.common,
+	&sdio2_2x.common,
+	&emmc_2x.common,
+	&sdio0_1x.common,
+	&sdio1_1x.common,
+	&sdio2_1x.common,
+	&emmc_1x.common,
+	&adi_clk.common,
+	&pwm0_clk.common,
+	&pwm1_clk.common,
+	&pwm2_clk.common,
+	&pwm3_clk.common,
+	&efuse_clk.common,
+	&cm3_uart0.common,
+	&cm3_uart1.common,
+	&thm_clk.common,
+	&cm3_i2c0.common,
+	&cm3_i2c1.common,
+	&cm4_spi.common,
+	&aon_i2c.common,
+	&avs_clk.common,
+	&ca53_dap.common,
+	&ca53_ts.common,
+	&djtag_tck.common,
+	&pmu_clk.common,
+	&pmu_26m.common,
+	&debounce_clk.common,
+	&otg2_ref.common,
+	&usb3_ref.common,
+	&ap_axi.common,
+};
+
+static struct clk_hw_onecell_data sc9860_aon_prediv_hws = {
+	.hws	= {
+		[CLK_AON_APB]		= &aon_apb.common.hw,
+		[CLK_AUX0]		= &aux0_clk.common.hw,
+		[CLK_AUX1]		= &aux1_clk.common.hw,
+		[CLK_AUX2]		= &aux2_clk.common.hw,
+		[CLK_PROBE]		= &probe_clk.common.hw,
+		[CLK_SP_AHB]		= &sp_ahb.common.hw,
+		[CLK_CCI]		= &cci_clk.common.hw,
+		[CLK_GIC]		= &gic_clk.common.hw,
+		[CLK_CSSYS]		= &cssys_clk.common.hw,
+		[CLK_SDIO0_2X]		= &sdio0_2x.common.hw,
+		[CLK_SDIO1_2X]		= &sdio1_2x.common.hw,
+		[CLK_SDIO2_2X]		= &sdio2_2x.common.hw,
+		[CLK_EMMC_2X]		= &emmc_2x.common.hw,
+		[CLK_SDIO0_1X]		= &sdio0_1x.common.hw,
+		[CLK_SDIO1_1X]		= &sdio1_1x.common.hw,
+		[CLK_SDIO2_1X]		= &sdio2_1x.common.hw,
+		[CLK_EMMC_1X]		= &emmc_1x.common.hw,
+		[CLK_ADI]		= &adi_clk.common.hw,
+		[CLK_PWM0]		= &pwm0_clk.common.hw,
+		[CLK_PWM1]		= &pwm1_clk.common.hw,
+		[CLK_PWM2]		= &pwm2_clk.common.hw,
+		[CLK_PWM3]		= &pwm3_clk.common.hw,
+		[CLK_EFUSE]		= &efuse_clk.common.hw,
+		[CLK_CM3_UART0]		= &cm3_uart0.common.hw,
+		[CLK_CM3_UART1]		= &cm3_uart1.common.hw,
+		[CLK_THM]		= &thm_clk.common.hw,
+		[CLK_CM3_I2C0]		= &cm3_i2c0.common.hw,
+		[CLK_CM3_I2C1]		= &cm3_i2c1.common.hw,
+		[CLK_CM4_SPI]		= &cm4_spi.common.hw,
+		[CLK_AON_I2C]		= &aon_i2c.common.hw,
+		[CLK_AVS]		= &avs_clk.common.hw,
+		[CLK_CA53_DAP]		= &ca53_dap.common.hw,
+		[CLK_CA53_TS]		= &ca53_ts.common.hw,
+		[CLK_DJTAG_TCK]		= &djtag_tck.common.hw,
+		[CLK_PMU]		= &pmu_clk.common.hw,
+		[CLK_PMU_26M]		= &pmu_26m.common.hw,
+		[CLK_DEBOUNCE]		= &debounce_clk.common.hw,
+		[CLK_OTG2_REF]		= &otg2_ref.common.hw,
+		[CLK_USB3_REF]		= &usb3_ref.common.hw,
+		[CLK_AP_AXI]		= &ap_axi.common.hw,
+	},
+	.num	= CLK_AON_PREDIV_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_aon_prediv_desc = {
+	.clk_clks	= sc9860_aon_prediv,
+	.num_clk_clks	= ARRAY_SIZE(sc9860_aon_prediv),
+	.hw_clks	= &sc9860_aon_prediv_hws,
+};
+
+static SPRD_SC_GATE_CLK(usb3_eb,		"usb3-eb",	"ap-axi", 0x0,
+		     0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(usb3_suspend,	"usb3-suspend", "ap-axi", 0x0,
+		     0x1000, BIT(3), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(usb3_ref_eb,	"usb3-ref-eb",	"ap-axi", 0x0,
+		     0x1000, BIT(4), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(dma_eb,		"dma-eb",	"ap-axi", 0x0,
+		     0x1000, BIT(5), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(sdio0_eb,		"sdio0-eb",	"ap-axi", 0x0,
+		     0x1000, BIT(7), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(sdio1_eb,		"sdio1-eb",	"ap-axi", 0x0,
+		     0x1000, BIT(8), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(sdio2_eb,		"sdio2-eb",	"ap-axi", 0x0,
+		     0x1000, BIT(9), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(emmc_eb,		"emmc-eb",	"ap-axi", 0x0,
+		     0x1000, BIT(10), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(rom_eb,		"rom-eb",	"ap-axi", 0x0,
+		     0x1000, BIT(12), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(busmon_eb,		"busmon-eb",	"ap-axi", 0x0,
+		     0x1000, BIT(13), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(cc63s_eb,		"cc63s-eb",	"ap-axi", 0x0,
+		     0x1000, BIT(22), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(cc63p_eb,		"cc63p-eb",	"ap-axi", 0x0,
+		     0x1000, BIT(23), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ce0_eb,		"ce0-eb",	"ap-axi", 0x0,
+		     0x1000, BIT(24), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ce1_eb,		"ce1-eb",	"ap-axi", 0x0,
+		     0x1000, BIT(25), CLK_IGNORE_UNUSED, 0);
+
+static struct sprd_clk_common *sc9860_apahb_gate[] = {
+	/* address base is 0x20210000 */
+	&usb3_eb.common,
+	&usb3_suspend.common,
+	&usb3_ref_eb.common,
+	&dma_eb.common,
+	&sdio0_eb.common,
+	&sdio1_eb.common,
+	&sdio2_eb.common,
+	&emmc_eb.common,
+	&rom_eb.common,
+	&busmon_eb.common,
+	&cc63s_eb.common,
+	&cc63p_eb.common,
+	&ce0_eb.common,
+	&ce1_eb.common,
+};
+
+static struct clk_hw_onecell_data sc9860_apahb_gate_hws = {
+	.hws	= {
+		[CLK_USB3_EB]		= &usb3_eb.common.hw,
+		[CLK_USB3_SUSPEND_EB]	= &usb3_suspend.common.hw,
+		[CLK_USB3_REF_EB]	= &usb3_ref_eb.common.hw,
+		[CLK_DMA_EB]		= &dma_eb.common.hw,
+		[CLK_SDIO0_EB]		= &sdio0_eb.common.hw,
+		[CLK_SDIO1_EB]		= &sdio1_eb.common.hw,
+		[CLK_SDIO2_EB]		= &sdio2_eb.common.hw,
+		[CLK_EMMC_EB]		= &emmc_eb.common.hw,
+		[CLK_ROM_EB]		= &rom_eb.common.hw,
+		[CLK_BUSMON_EB]		= &busmon_eb.common.hw,
+		[CLK_CC63S_EB]		= &cc63s_eb.common.hw,
+		[CLK_CC63P_EB]		= &cc63p_eb.common.hw,
+		[CLK_CE0_EB]		= &ce0_eb.common.hw,
+		[CLK_CE1_EB]		= &ce1_eb.common.hw,
+	},
+	.num	= CLK_APAHB_GATE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_apahb_gate_desc = {
+	.clk_clks	= sc9860_apahb_gate,
+	.num_clk_clks	= ARRAY_SIZE(sc9860_apahb_gate),
+	.hw_clks	= &sc9860_apahb_gate_hws,
+};
+
+static SPRD_SC_GATE_CLK(avs_lit_eb,	"avs-lit-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(0), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(avs_big_eb,	"avs-big-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(1), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_intc5_eb,	"ap-intc5-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(gpio_eb,		"gpio-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(3), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(pwm0_eb,		"pwm0-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(4), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(pwm1_eb,		"pwm1-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(5), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(pwm2_eb,		"pwm2-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(6), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(pwm3_eb,		"pwm3-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(7), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(kpd_eb,		"kpd-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(8), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aon_sys_eb,	"aon-sys-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(9), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_sys_eb,	"ap-sys-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(10), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aon_tmr_eb,	"aon-tmr-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(11), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_tmr0_eb,	"ap-tmr0-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(12), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(efuse_eb,	"efuse-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(13), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(eic_eb,		"eic-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(14), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(pub1_reg_eb,	"pub1-reg-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(15), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(adi_eb,		"adi-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(16), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_intc0_eb,	"ap-intc0-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(17), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_intc1_eb,	"ap-intc1-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(18), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_intc2_eb,	"ap-intc2-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(19), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_intc3_eb,	"ap-intc3-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(20), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_intc4_eb,	"ap-intc4-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(21), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(splk_eb,		"splk-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(22), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(mspi_eb,		"mspi-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(23), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(pub0_reg_eb,	"pub0-reg-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(24), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(pin_eb,		"pin-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(25), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aon_ckg_eb,	"aon-ckg-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(26), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(gpu_eb,		"gpu-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(27), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(apcpu_ts0_eb,	"apcpu-ts0-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(28), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(apcpu_ts1_eb,	"apcpu-ts1-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(29), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(dap_eb,		"dap-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(30), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(i2c_eb,		"i2c-eb",	"aon-apb", 0x0,
+		     0x1000, BIT(31), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(pmu_eb,		"pmu-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(0), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(thm_eb,		"thm-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(1), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aux0_eb,		"aux0-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aux1_eb,		"aux1-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(3), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aux2_eb,		"aux2-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(4), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(probe_eb,		"probe-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(5), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(gpu0_avs_eb,	"gpu0-avs-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(6), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(gpu1_avs_eb,	"gpu1-avs-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(7), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(apcpu_wdg_eb,	"apcpu-wdg-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(8), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_tmr1_eb,	"ap-tmr1-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(9), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_tmr2_eb,	"ap-tmr2-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(10), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(disp_emc_eb,	"disp-emc-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(11), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(zip_emc_eb,	"zip-emc-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(12), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(gsp_emc_eb,	"gsp-emc-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(13), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(osc_aon_eb,	"osc-aon-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(14), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(lvds_trx_eb,	"lvds-trx-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(15), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(lvds_tcxo_eb,	"lvds-tcxo-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(16), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(mdar_eb,		"mdar-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(17), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(rtc4m0_cal_eb, "rtc4m0-cal-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(18), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(rct100m_cal_eb, "rct100m-cal-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(19), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(djtag_eb,		"djtag-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(20), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(mbox_eb,		"mbox-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(21), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aon_dma_eb,	"aon-dma-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(22), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(dbg_emc_eb,	"dbg-emc-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(23), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(lvds_pll_div_en, "lvds-pll-div-en", "aon-apb", 0x4,
+		     0x1000, BIT(24), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(def_eb,		"def-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(25), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(aon_apb_rsv0,	"aon-apb-rsv0",	"aon-apb", 0x4,
+		     0x1000, BIT(26), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(orp_jtag_eb,	"orp-jtag-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(27), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(vsp_eb,		"vsp-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(28), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(cam_eb,		"cam-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(29), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(disp_eb,		"disp-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(30), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(dbg_axi_if_eb, "dbg-axi-if-eb",	"aon-apb", 0x4,
+		     0x1000, BIT(31), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(sdio0_2x_en,	"sdio0-2x-en",	"aon-apb", 0x13c,
+			       0x1000, BIT(2), 0, 0);
+static SPRD_SC_GATE_CLK(sdio1_2x_en,	"sdio1-2x-en",	"aon-apb", 0x13c,
+			       0x1000, BIT(4), 0, 0);
+static SPRD_SC_GATE_CLK(sdio2_2x_en,	"sdio2-2x-en",	"aon-apb", 0x13c,
+			       0x1000, BIT(6), 0, 0);
+static SPRD_SC_GATE_CLK(emmc_2x_en,	"emmc-2x-en",	"aon-apb", 0x13c,
+			       0x1000, BIT(9), 0, 0);
+
+static struct sprd_clk_common *sc9860_aon_gate[] = {
+	/* address base is 0x402e0000 */
+	&avs_lit_eb.common,
+	&avs_big_eb.common,
+	&ap_intc5_eb.common,
+	&gpio_eb.common,
+	&pwm0_eb.common,
+	&pwm1_eb.common,
+	&pwm2_eb.common,
+	&pwm3_eb.common,
+	&kpd_eb.common,
+	&aon_sys_eb.common,
+	&ap_sys_eb.common,
+	&aon_tmr_eb.common,
+	&ap_tmr0_eb.common,
+	&efuse_eb.common,
+	&eic_eb.common,
+	&pub1_reg_eb.common,
+	&adi_eb.common,
+	&ap_intc0_eb.common,
+	&ap_intc1_eb.common,
+	&ap_intc2_eb.common,
+	&ap_intc3_eb.common,
+	&ap_intc4_eb.common,
+	&splk_eb.common,
+	&mspi_eb.common,
+	&pub0_reg_eb.common,
+	&pin_eb.common,
+	&aon_ckg_eb.common,
+	&gpu_eb.common,
+	&apcpu_ts0_eb.common,
+	&apcpu_ts1_eb.common,
+	&dap_eb.common,
+	&i2c_eb.common,
+	&pmu_eb.common,
+	&thm_eb.common,
+	&aux0_eb.common,
+	&aux1_eb.common,
+	&aux2_eb.common,
+	&probe_eb.common,
+	&gpu0_avs_eb.common,
+	&gpu1_avs_eb.common,
+	&apcpu_wdg_eb.common,
+	&ap_tmr1_eb.common,
+	&ap_tmr2_eb.common,
+	&disp_emc_eb.common,
+	&zip_emc_eb.common,
+	&gsp_emc_eb.common,
+	&osc_aon_eb.common,
+	&lvds_trx_eb.common,
+	&lvds_tcxo_eb.common,
+	&mdar_eb.common,
+	&rtc4m0_cal_eb.common,
+	&rct100m_cal_eb.common,
+	&djtag_eb.common,
+	&mbox_eb.common,
+	&aon_dma_eb.common,
+	&dbg_emc_eb.common,
+	&lvds_pll_div_en.common,
+	&def_eb.common,
+	&aon_apb_rsv0.common,
+	&orp_jtag_eb.common,
+	&vsp_eb.common,
+	&cam_eb.common,
+	&disp_eb.common,
+	&dbg_axi_if_eb.common,
+	&sdio0_2x_en.common,
+	&sdio1_2x_en.common,
+	&sdio2_2x_en.common,
+	&emmc_2x_en.common,
+};
+
+static struct clk_hw_onecell_data sc9860_aon_gate_hws = {
+	.hws	= {
+		[CLK_AVS_LIT_EB]	= &avs_lit_eb.common.hw,
+		[CLK_AVS_BIG_EB]	= &avs_big_eb.common.hw,
+		[CLK_AP_INTC5_EB]	= &ap_intc5_eb.common.hw,
+		[CLK_GPIO_EB]		= &gpio_eb.common.hw,
+		[CLK_PWM0_EB]		= &pwm0_eb.common.hw,
+		[CLK_PWM1_EB]		= &pwm1_eb.common.hw,
+		[CLK_PWM2_EB]		= &pwm2_eb.common.hw,
+		[CLK_PWM3_EB]		= &pwm3_eb.common.hw,
+		[CLK_KPD_EB]		= &kpd_eb.common.hw,
+		[CLK_AON_SYS_EB]	= &aon_sys_eb.common.hw,
+		[CLK_AP_SYS_EB]		= &ap_sys_eb.common.hw,
+		[CLK_AON_TMR_EB]	= &aon_tmr_eb.common.hw,
+		[CLK_AP_TMR0_EB]	= &ap_tmr0_eb.common.hw,
+		[CLK_EFUSE_EB]		= &efuse_eb.common.hw,
+		[CLK_EIC_EB]		= &eic_eb.common.hw,
+		[CLK_PUB1_REG_EB]	= &pub1_reg_eb.common.hw,
+		[CLK_ADI_EB]		= &adi_eb.common.hw,
+		[CLK_AP_INTC0_EB]	= &ap_intc0_eb.common.hw,
+		[CLK_AP_INTC1_EB]	= &ap_intc1_eb.common.hw,
+		[CLK_AP_INTC2_EB]	= &ap_intc2_eb.common.hw,
+		[CLK_AP_INTC3_EB]	= &ap_intc3_eb.common.hw,
+		[CLK_AP_INTC4_EB]	= &ap_intc4_eb.common.hw,
+		[CLK_SPLK_EB]		= &splk_eb.common.hw,
+		[CLK_MSPI_EB]		= &mspi_eb.common.hw,
+		[CLK_PUB0_REG_EB]	= &pub0_reg_eb.common.hw,
+		[CLK_PIN_EB]		= &pin_eb.common.hw,
+		[CLK_AON_CKG_EB]	= &aon_ckg_eb.common.hw,
+		[CLK_GPU_EB]		= &gpu_eb.common.hw,
+		[CLK_APCPU_TS0_EB]	= &apcpu_ts0_eb.common.hw,
+		[CLK_APCPU_TS1_EB]	= &apcpu_ts1_eb.common.hw,
+		[CLK_DAP_EB]		= &dap_eb.common.hw,
+		[CLK_I2C_EB]		= &i2c_eb.common.hw,
+		[CLK_PMU_EB]		= &pmu_eb.common.hw,
+		[CLK_THM_EB]		= &thm_eb.common.hw,
+		[CLK_AUX0_EB]		= &aux0_eb.common.hw,
+		[CLK_AUX1_EB]		= &aux1_eb.common.hw,
+		[CLK_AUX2_EB]		= &aux2_eb.common.hw,
+		[CLK_PROBE_EB]		= &probe_eb.common.hw,
+		[CLK_GPU0_AVS_EB]	= &gpu0_avs_eb.common.hw,
+		[CLK_GPU1_AVS_EB]	= &gpu1_avs_eb.common.hw,
+		[CLK_APCPU_WDG_EB]	= &apcpu_wdg_eb.common.hw,
+		[CLK_AP_TMR1_EB]	= &ap_tmr1_eb.common.hw,
+		[CLK_AP_TMR2_EB]	= &ap_tmr2_eb.common.hw,
+		[CLK_DISP_EMC_EB]	= &disp_emc_eb.common.hw,
+		[CLK_ZIP_EMC_EB]	= &zip_emc_eb.common.hw,
+		[CLK_GSP_EMC_EB]	= &gsp_emc_eb.common.hw,
+		[CLK_OSC_AON_EB]	= &osc_aon_eb.common.hw,
+		[CLK_LVDS_TRX_EB]	= &lvds_trx_eb.common.hw,
+		[CLK_LVDS_TCXO_EB]	= &lvds_tcxo_eb.common.hw,
+		[CLK_MDAR_EB]		= &mdar_eb.common.hw,
+		[CLK_RTC4M0_CAL_EB]	= &rtc4m0_cal_eb.common.hw,
+		[CLK_RCT100M_CAL_EB]	= &rct100m_cal_eb.common.hw,
+		[CLK_DJTAG_EB]		= &djtag_eb.common.hw,
+		[CLK_MBOX_EB]		= &mbox_eb.common.hw,
+		[CLK_AON_DMA_EB]	= &aon_dma_eb.common.hw,
+		[CLK_DBG_EMC_EB]	= &dbg_emc_eb.common.hw,
+		[CLK_LVDS_PLL_DIV_EN]	= &lvds_pll_div_en.common.hw,
+		[CLK_DEF_EB]		= &def_eb.common.hw,
+		[CLK_AON_APB_RSV0]	= &aon_apb_rsv0.common.hw,
+		[CLK_ORP_JTAG_EB]	= &orp_jtag_eb.common.hw,
+		[CLK_VSP_EB]		= &vsp_eb.common.hw,
+		[CLK_CAM_EB]		= &cam_eb.common.hw,
+		[CLK_DISP_EB]		= &disp_eb.common.hw,
+		[CLK_DBG_AXI_IF_EB]	= &dbg_axi_if_eb.common.hw,
+		[CLK_SDIO0_2X_EN]	= &sdio0_2x_en.common.hw,
+		[CLK_SDIO1_2X_EN]	= &sdio1_2x_en.common.hw,
+		[CLK_SDIO2_2X_EN]	= &sdio2_2x_en.common.hw,
+		[CLK_EMMC_2X_EN]	= &emmc_2x_en.common.hw,
+	},
+	.num	= CLK_AON_GATE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_aon_gate_desc = {
+	.clk_clks	= sc9860_aon_gate,
+	.num_clk_clks	= ARRAY_SIZE(sc9860_aon_gate),
+	.hw_clks	= &sc9860_aon_gate_hws,
+};
+
+static const u8 mcu_table[] = { 0, 1, 2, 3, 4, 8 };
+static const char * const lit_mcu_parents[] = {	"ext-26m",	"twpll-512m",
+						"twpll-768m",	"ltepll0",
+						"twpll",	"mpll0" };
+static SPRD_COMP_CLK_TABLE(lit_mcu, "lit-mcu", lit_mcu_parents, 0x20,
+			   mcu_table, 0, 4, 4, 3, 0);
+
+static const char * const big_mcu_parents[] = {	"ext-26m",	"twpll-512m",
+						"twpll-768m",	"ltepll0",
+						"twpll",	"mpll1" };
+static SPRD_COMP_CLK_TABLE(big_mcu, "big-mcu", big_mcu_parents, 0x24,
+			   mcu_table, 0, 4, 4, 3, 0);
+
+static struct sprd_clk_common *sc9860_aonsecure_clk[] = {
+	/* address base is 0x40880000 */
+	&lit_mcu.common,
+	&big_mcu.common,
+};
+
+static struct clk_hw_onecell_data sc9860_aonsecure_clk_hws = {
+	.hws	= {
+		[CLK_LIT_MCU]		= &lit_mcu.common.hw,
+		[CLK_BIG_MCU]		= &big_mcu.common.hw,
+	},
+	.num	= CLK_AONSECURE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_aonsecure_clk_desc = {
+	.clk_clks	= sc9860_aonsecure_clk,
+	.num_clk_clks	= ARRAY_SIZE(sc9860_aonsecure_clk),
+	.hw_clks	= &sc9860_aonsecure_clk_hws,
+};
+
+static SPRD_SC_GATE_CLK(agcp_iis0_eb,	"agcp-iis0-eb",		"aon-apb",
+		     0x0, 0x100, BIT(0), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_iis1_eb,	"agcp-iis1-eb",		"aon-apb",
+		     0x0, 0x100, BIT(1), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_iis2_eb,	"agcp-iis2-eb",		"aon-apb",
+		     0x0, 0x100, BIT(2), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_iis3_eb,	"agcp-iis3-eb",		"aon-apb",
+		     0x0, 0x100, BIT(3), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_uart_eb,	"agcp-uart-eb",		"aon-apb",
+		     0x0, 0x100, BIT(4), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_dmacp_eb,	"agcp-dmacp-eb",	"aon-apb",
+		     0x0, 0x100, BIT(5), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_dmaap_eb,	"agcp-dmaap-eb",	"aon-apb",
+		     0x0, 0x100, BIT(6), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_arc48k_eb,	"agcp-arc48k-eb",	"aon-apb",
+		     0x0, 0x100, BIT(10), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_src44p1k_eb, "agcp-src44p1k-eb",	"aon-apb",
+		     0x0, 0x100, BIT(11), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_mcdt_eb,	"agcp-mcdt-eb",		"aon-apb",
+		     0x0, 0x100, BIT(12), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_vbcifd_eb,	"agcp-vbcifd-eb",	"aon-apb",
+		     0x0, 0x100, BIT(13), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_vbc_eb,	"agcp-vbc-eb",		"aon-apb",
+		     0x0, 0x100, BIT(14), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_spinlock_eb, "agcp-spinlock-eb",	"aon-apb",
+		     0x0, 0x100, BIT(15), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_icu_eb,	"agcp-icu-eb",		"aon-apb",
+		     0x0, 0x100, BIT(16), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(agcp_ap_ashb_eb, "agcp-ap-ashb-eb",	"aon-apb",
+		     0x0, 0x100, BIT(17), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_cp_ashb_eb, "agcp-cp-ashb-eb",	"aon-apb",
+		     0x0, 0x100, BIT(18), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_aud_eb,	"agcp-aud-eb",		"aon-apb",
+		     0x0, 0x100, BIT(19), 0, 0);
+static SPRD_SC_GATE_CLK(agcp_audif_eb,	"agcp-audif-eb",	"aon-apb",
+		     0x0, 0x100, BIT(20), 0, 0);
+
+static struct sprd_clk_common *sc9860_agcp_gate[] = {
+	/* address base is 0x415e0000 */
+	&agcp_iis0_eb.common,
+	&agcp_iis1_eb.common,
+	&agcp_iis2_eb.common,
+	&agcp_iis3_eb.common,
+	&agcp_uart_eb.common,
+	&agcp_dmacp_eb.common,
+	&agcp_dmaap_eb.common,
+	&agcp_arc48k_eb.common,
+	&agcp_src44p1k_eb.common,
+	&agcp_mcdt_eb.common,
+	&agcp_vbcifd_eb.common,
+	&agcp_vbc_eb.common,
+	&agcp_spinlock_eb.common,
+	&agcp_icu_eb.common,
+	&agcp_ap_ashb_eb.common,
+	&agcp_cp_ashb_eb.common,
+	&agcp_aud_eb.common,
+	&agcp_audif_eb.common,
+};
+
+static struct clk_hw_onecell_data sc9860_agcp_gate_hws = {
+	.hws	= {
+		[CLK_AGCP_IIS0_EB]	= &agcp_iis0_eb.common.hw,
+		[CLK_AGCP_IIS1_EB]	= &agcp_iis1_eb.common.hw,
+		[CLK_AGCP_IIS2_EB]	= &agcp_iis2_eb.common.hw,
+		[CLK_AGCP_IIS3_EB]	= &agcp_iis3_eb.common.hw,
+		[CLK_AGCP_UART_EB]	= &agcp_uart_eb.common.hw,
+		[CLK_AGCP_DMACP_EB]	= &agcp_dmacp_eb.common.hw,
+		[CLK_AGCP_DMAAP_EB]	= &agcp_dmaap_eb.common.hw,
+		[CLK_AGCP_ARC48K_EB]	= &agcp_arc48k_eb.common.hw,
+		[CLK_AGCP_SRC44P1K_EB]	= &agcp_src44p1k_eb.common.hw,
+		[CLK_AGCP_MCDT_EB]	= &agcp_mcdt_eb.common.hw,
+		[CLK_AGCP_VBCIFD_EB]	= &agcp_vbcifd_eb.common.hw,
+		[CLK_AGCP_VBC_EB]	= &agcp_vbc_eb.common.hw,
+		[CLK_AGCP_SPINLOCK_EB]	= &agcp_spinlock_eb.common.hw,
+		[CLK_AGCP_ICU_EB]	= &agcp_icu_eb.common.hw,
+		[CLK_AGCP_AP_ASHB_EB]	= &agcp_ap_ashb_eb.common.hw,
+		[CLK_AGCP_CP_ASHB_EB]	= &agcp_cp_ashb_eb.common.hw,
+		[CLK_AGCP_AUD_EB]	= &agcp_aud_eb.common.hw,
+		[CLK_AGCP_AUDIF_EB]	= &agcp_audif_eb.common.hw,
+	},
+	.num	= CLK_AGCP_GATE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_agcp_gate_desc = {
+	.clk_clks	= sc9860_agcp_gate,
+	.num_clk_clks	= ARRAY_SIZE(sc9860_agcp_gate),
+	.hw_clks	= &sc9860_agcp_gate_hws,
+};
+
+static const char * const gpu_parents[] = { "twpll-512m",
+					    "twpll-768m",
+					    "gpll" };
+static SPRD_COMP_CLK(gpu_clk,	"gpu",	gpu_parents, 0x20,
+		     0, 2, 8, 4, 0);
+
+static struct sprd_clk_common *sc9860_gpu_clk[] = {
+	/* address base is 0x60200000 */
+	&gpu_clk.common,
+};
+
+static struct clk_hw_onecell_data sc9860_gpu_clk_hws = {
+	.hws	= {
+		[CLK_GPU]	= &gpu_clk.common.hw,
+	},
+	.num	= CLK_GPU_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_gpu_clk_desc = {
+	.clk_clks	= sc9860_gpu_clk,
+	.num_clk_clks	= ARRAY_SIZE(sc9860_gpu_clk),
+	.hw_clks	= &sc9860_gpu_clk_hws,
+};
+
+static const char * const ahb_parents[] = { "ext-26m", "twpll-96m",
+					    "twpll-128m", "twpll-153m6" };
+static SPRD_MUX_CLK(ahb_vsp, "ahb-vsp", ahb_parents, 0x20,
+		    0, 2, SC9860_MUX_FLAG);
+
+static const char * const vsp_parents[] = {	"twpll-76m8",	"twpll-128m",
+						"twpll-256m",	"twpll-307m2",
+						"twpll-384m" };
+static SPRD_COMP_CLK(vsp_clk, "vsp", vsp_parents, 0x24, 0, 3, 8, 2, 0);
+
+static const char * const dispc_parents[] = {	"twpll-76m8",	"twpll-128m",
+						"twpll-256m",	"twpll-307m2" };
+static SPRD_COMP_CLK(vsp_enc, "vsp-enc", dispc_parents, 0x28, 0, 2, 8, 2, 0);
+
+static const char * const vpp_parents[] = { "twpll-96m", "twpll-153m6",
+					    "twpll-192m", "twpll-256m" };
+static SPRD_MUX_CLK(vpp_clk, "vpp", vpp_parents, 0x2c,
+		    0, 2, SC9860_MUX_FLAG);
+static const char * const vsp_26m_parents[] = { "ext-26m" };
+static SPRD_MUX_CLK(vsp_26m, "vsp-26m", vsp_26m_parents, 0x30,
+		    0, 1, SC9860_MUX_FLAG);
+
+static struct sprd_clk_common *sc9860_vsp_clk[] = {
+	/* address base is 0x61000000 */
+	&ahb_vsp.common,
+	&vsp_clk.common,
+	&vsp_enc.common,
+	&vpp_clk.common,
+	&vsp_26m.common,
+};
+
+static struct clk_hw_onecell_data sc9860_vsp_clk_hws = {
+	.hws	= {
+		[CLK_AHB_VSP]	= &ahb_vsp.common.hw,
+		[CLK_VSP]	= &vsp_clk.common.hw,
+		[CLK_VSP_ENC]	= &vsp_enc.common.hw,
+		[CLK_VPP]	= &vpp_clk.common.hw,
+		[CLK_VSP_26M]	= &vsp_26m.common.hw,
+	},
+	.num	= CLK_VSP_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_vsp_clk_desc = {
+	.clk_clks	= sc9860_vsp_clk,
+	.num_clk_clks	= ARRAY_SIZE(sc9860_vsp_clk),
+	.hw_clks	= &sc9860_vsp_clk_hws,
+};
+
+static SPRD_SC_GATE_CLK(vsp_dec_eb,	"vsp-dec-eb",	"ahb-vsp", 0x0,
+		     0x1000, BIT(0), 0, 0);
+static SPRD_SC_GATE_CLK(vsp_ckg_eb,	"vsp-ckg-eb",	"ahb-vsp", 0x0,
+		     0x1000, BIT(1), 0, 0);
+static SPRD_SC_GATE_CLK(vsp_mmu_eb,	"vsp-mmu-eb",	"ahb-vsp", 0x0,
+		     0x1000, BIT(2), 0, 0);
+static SPRD_SC_GATE_CLK(vsp_enc_eb,	"vsp-enc-eb",	"ahb-vsp", 0x0,
+		     0x1000, BIT(3), 0, 0);
+static SPRD_SC_GATE_CLK(vpp_eb,		"vpp-eb",	"ahb-vsp", 0x0,
+		     0x1000, BIT(4), 0, 0);
+static SPRD_SC_GATE_CLK(vsp_26m_eb,	"vsp-26m-eb",	"ahb-vsp", 0x0,
+		     0x1000, BIT(5), 0, 0);
+static SPRD_GATE_CLK(vsp_axi_gate,	"vsp-axi-gate",	"ahb-vsp", 0x8,
+		     BIT(0), 0, 0);
+static SPRD_GATE_CLK(vsp_enc_gate,	"vsp-enc-gate",	"ahb-vsp", 0x8,
+		     BIT(1), 0, 0);
+static SPRD_GATE_CLK(vpp_axi_gate,	"vpp-axi-gate",	"ahb-vsp", 0x8,
+		     BIT(2), 0, 0);
+static SPRD_GATE_CLK(vsp_bm_gate,	"vsp-bm-gate",	"ahb-vsp", 0x8,
+		     BIT(8), 0, 0);
+static SPRD_GATE_CLK(vsp_enc_bm_gate, "vsp-enc-bm-gate", "ahb-vsp", 0x8,
+		     BIT(9), 0, 0);
+static SPRD_GATE_CLK(vpp_bm_gate,	"vpp-bm-gate",	"ahb-vsp", 0x8,
+		     BIT(10), 0, 0);
+
+static struct sprd_clk_common *sc9860_vsp_gate[] = {
+	/* address base is 0x61100000 */
+	&vsp_dec_eb.common,
+	&vsp_ckg_eb.common,
+	&vsp_mmu_eb.common,
+	&vsp_enc_eb.common,
+	&vpp_eb.common,
+	&vsp_26m_eb.common,
+	&vsp_axi_gate.common,
+	&vsp_enc_gate.common,
+	&vpp_axi_gate.common,
+	&vsp_bm_gate.common,
+	&vsp_enc_bm_gate.common,
+	&vpp_bm_gate.common,
+};
+
+static struct clk_hw_onecell_data sc9860_vsp_gate_hws = {
+	.hws	= {
+		[CLK_VSP_DEC_EB]	= &vsp_dec_eb.common.hw,
+		[CLK_VSP_CKG_EB]	= &vsp_ckg_eb.common.hw,
+		[CLK_VSP_MMU_EB]	= &vsp_mmu_eb.common.hw,
+		[CLK_VSP_ENC_EB]	= &vsp_enc_eb.common.hw,
+		[CLK_VPP_EB]		= &vpp_eb.common.hw,
+		[CLK_VSP_26M_EB]	= &vsp_26m_eb.common.hw,
+		[CLK_VSP_AXI_GATE]	= &vsp_axi_gate.common.hw,
+		[CLK_VSP_ENC_GATE]	= &vsp_enc_gate.common.hw,
+		[CLK_VPP_AXI_GATE]	= &vpp_axi_gate.common.hw,
+		[CLK_VSP_BM_GATE]	= &vsp_bm_gate.common.hw,
+		[CLK_VSP_ENC_BM_GATE]	= &vsp_enc_bm_gate.common.hw,
+		[CLK_VPP_BM_GATE]	= &vpp_bm_gate.common.hw,
+	},
+	.num	= CLK_VSP_GATE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_vsp_gate_desc = {
+	.clk_clks	= sc9860_vsp_gate,
+	.num_clk_clks	= ARRAY_SIZE(sc9860_vsp_gate),
+	.hw_clks	= &sc9860_vsp_gate_hws,
+};
+
+static SPRD_MUX_CLK(ahb_cam, "ahb-cam", ahb_parents, 0x20,
+		    0, 2, SC9860_MUX_FLAG);
+static const char * const sensor_parents[] = {	"ext-26m",	"twpll-48m",
+						"twpll-76m8",	"twpll-96m" };
+static SPRD_COMP_CLK(sensor0_clk, "sensor0", sensor_parents, 0x24,
+		     0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(sensor1_clk, "sensor1", sensor_parents, 0x28,
+		     0, 2, 8, 3, 0);
+static SPRD_COMP_CLK(sensor2_clk, "sensor2", sensor_parents, 0x2c,
+		     0, 2, 8, 3, 0);
+static SPRD_GATE_CLK(mipi_csi0_eb, "mipi-csi0-eb", "ahb-cam", 0x4c,
+		     BIT(16), 0, 0);
+static SPRD_GATE_CLK(mipi_csi1_eb, "mipi-csi1-eb", "ahb-cam", 0x50,
+		     BIT(16), 0, 0);
+
+static struct sprd_clk_common *sc9860_cam_clk[] = {
+	/* address base is 0x62000000 */
+	&ahb_cam.common,
+	&sensor0_clk.common,
+	&sensor1_clk.common,
+	&sensor2_clk.common,
+	&mipi_csi0_eb.common,
+	&mipi_csi1_eb.common,
+};
+
+static struct clk_hw_onecell_data sc9860_cam_clk_hws = {
+	.hws	= {
+		[CLK_AHB_CAM]		= &ahb_cam.common.hw,
+		[CLK_SENSOR0]		= &sensor0_clk.common.hw,
+		[CLK_SENSOR1]		= &sensor1_clk.common.hw,
+		[CLK_SENSOR2]		= &sensor2_clk.common.hw,
+		[CLK_MIPI_CSI0_EB]	= &mipi_csi0_eb.common.hw,
+		[CLK_MIPI_CSI1_EB]	= &mipi_csi1_eb.common.hw,
+	},
+	.num	= CLK_CAM_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_cam_clk_desc = {
+	.clk_clks	= sc9860_cam_clk,
+	.num_clk_clks	= ARRAY_SIZE(sc9860_cam_clk),
+	.hw_clks	= &sc9860_cam_clk_hws,
+};
+
+static SPRD_SC_GATE_CLK(dcam0_eb,		"dcam0-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(0), 0, 0);
+static SPRD_SC_GATE_CLK(dcam1_eb,		"dcam1-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(1), 0, 0);
+static SPRD_SC_GATE_CLK(isp0_eb,		"isp0-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(2), 0, 0);
+static SPRD_SC_GATE_CLK(csi0_eb,		"csi0-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(3), 0, 0);
+static SPRD_SC_GATE_CLK(csi1_eb,		"csi1-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(4), 0, 0);
+static SPRD_SC_GATE_CLK(jpg0_eb,		"jpg0-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(5), 0, 0);
+static SPRD_SC_GATE_CLK(jpg1_eb,		"jpg1-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(6), 0, 0);
+static SPRD_SC_GATE_CLK(cam_ckg_eb,	"cam-ckg-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(7), 0, 0);
+static SPRD_SC_GATE_CLK(cam_mmu_eb,	"cam-mmu-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(8), 0, 0);
+static SPRD_SC_GATE_CLK(isp1_eb,		"isp1-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(9), 0, 0);
+static SPRD_SC_GATE_CLK(cpp_eb,		"cpp-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(10), 0, 0);
+static SPRD_SC_GATE_CLK(mmu_pf_eb,		"mmu-pf-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(11), 0, 0);
+static SPRD_SC_GATE_CLK(isp2_eb,		"isp2-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(12), 0, 0);
+static SPRD_SC_GATE_CLK(dcam2isp_if_eb, "dcam2isp-if-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(13), 0, 0);
+static SPRD_SC_GATE_CLK(isp2dcam_if_eb, "isp2dcam-if-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(14), 0, 0);
+static SPRD_SC_GATE_CLK(isp_lclk_eb,	"isp-lclk-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(15), 0, 0);
+static SPRD_SC_GATE_CLK(isp_iclk_eb,	"isp-iclk-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(16), 0, 0);
+static SPRD_SC_GATE_CLK(isp_mclk_eb,	"isp-mclk-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(17), 0, 0);
+static SPRD_SC_GATE_CLK(isp_pclk_eb,	"isp-pclk-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(18), 0, 0);
+static SPRD_SC_GATE_CLK(isp_isp2dcam_eb, "isp-isp2dcam-eb", "ahb-cam", 0x0,
+		     0x1000, BIT(19), 0, 0);
+static SPRD_SC_GATE_CLK(dcam0_if_eb,	"dcam0-if-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(20), 0, 0);
+static SPRD_SC_GATE_CLK(clk26m_if_eb,	"clk26m-if-eb",	"ahb-cam", 0x0,
+		     0x1000, BIT(21), 0, 0);
+static SPRD_GATE_CLK(cphy0_gate, "cphy0-gate", "ahb-cam", 0x8,
+		     BIT(0), 0, 0);
+static SPRD_GATE_CLK(mipi_csi0_gate, "mipi-csi0-gate", "ahb-cam", 0x8,
+		     BIT(1), 0, 0);
+static SPRD_GATE_CLK(cphy1_gate,	"cphy1-gate",	"ahb-cam", 0x8,
+		     BIT(2), 0, 0);
+static SPRD_GATE_CLK(mipi_csi1,		"mipi-csi1",	"ahb-cam", 0x8,
+		     BIT(3), 0, 0);
+static SPRD_GATE_CLK(dcam0_axi_gate,	"dcam0-axi-gate", "ahb-cam", 0x8,
+		     BIT(4), 0, 0);
+static SPRD_GATE_CLK(dcam1_axi_gate,	"dcam1-axi-gate", "ahb-cam", 0x8,
+		     BIT(5), 0, 0);
+static SPRD_GATE_CLK(sensor0_gate,	"sensor0-gate",	"ahb-cam", 0x8,
+		     BIT(6), 0, 0);
+static SPRD_GATE_CLK(sensor1_gate,	"sensor1-gate",	"ahb-cam", 0x8,
+		     BIT(7), 0, 0);
+static SPRD_GATE_CLK(jpg0_axi_gate,	"jpg0-axi-gate", "ahb-cam", 0x8,
+		     BIT(8), 0, 0);
+static SPRD_GATE_CLK(gpg1_axi_gate,	"gpg1-axi-gate", "ahb-cam", 0x8,
+		     BIT(9), 0, 0);
+static SPRD_GATE_CLK(isp0_axi_gate,	"isp0-axi-gate", "ahb-cam", 0x8,
+		     BIT(10), 0, 0);
+static SPRD_GATE_CLK(isp1_axi_gate,	"isp1-axi-gate", "ahb-cam", 0x8,
+		     BIT(11), 0, 0);
+static SPRD_GATE_CLK(isp2_axi_gate,	"isp2-axi-gate", "ahb-cam", 0x8,
+		     BIT(12), 0, 0);
+static SPRD_GATE_CLK(cpp_axi_gate,	"cpp-axi-gate",	"ahb-cam", 0x8,
+		     BIT(13), 0, 0);
+static SPRD_GATE_CLK(d0_if_axi_gate,	"d0-if-axi-gate", "ahb-cam", 0x8,
+		     BIT(14), 0, 0);
+static SPRD_GATE_CLK(d2i_if_axi_gate, "d2i-if-axi-gate", "ahb-cam", 0x8,
+		     BIT(15), 0, 0);
+static SPRD_GATE_CLK(i2d_if_axi_gate, "i2d-if-axi-gate", "ahb-cam", 0x8,
+		     BIT(16), 0, 0);
+static SPRD_GATE_CLK(spare_axi_gate, "spare-axi-gate",	"ahb-cam", 0x8,
+		     BIT(17), 0, 0);
+static SPRD_GATE_CLK(sensor2_gate, "sensor2-gate",	"ahb-cam", 0x8,
+		     BIT(18), 0, 0);
+static SPRD_SC_GATE_CLK(d0if_in_d_en, "d0if-in-d-en", "ahb-cam", 0x28,
+		     0x1000, BIT(0), 0, 0);
+static SPRD_SC_GATE_CLK(d1if_in_d_en, "d1if-in-d-en", "ahb-cam", 0x28,
+		     0x1000, BIT(1), 0, 0);
+static SPRD_SC_GATE_CLK(d0if_in_d2i_en, "d0if-in-d2i-en", "ahb-cam", 0x28,
+		     0x1000, BIT(2), 0, 0);
+static SPRD_SC_GATE_CLK(d1if_in_d2i_en, "d1if-in-d2i-en",	"ahb-cam", 0x28,
+		     0x1000, BIT(3), 0, 0);
+static SPRD_SC_GATE_CLK(ia_in_d2i_en, "ia-in-d2i-en",	"ahb-cam", 0x28,
+		     0x1000, BIT(4), 0, 0);
+static SPRD_SC_GATE_CLK(ib_in_d2i_en,	"ib-in-d2i-en",	"ahb-cam", 0x28,
+		     0x1000, BIT(5), 0, 0);
+static SPRD_SC_GATE_CLK(ic_in_d2i_en,	"ic-in-d2i-en",	"ahb-cam", 0x28,
+		     0x1000, BIT(6), 0, 0);
+static SPRD_SC_GATE_CLK(ia_in_i_en,	"ia-in-i-en",	"ahb-cam", 0x28,
+		     0x1000, BIT(7), 0, 0);
+static SPRD_SC_GATE_CLK(ib_in_i_en,	"ib-in-i-en",	"ahb-cam", 0x28,
+		     0x1000, BIT(8), 0, 0);
+static SPRD_SC_GATE_CLK(ic_in_i_en,	"ic-in-i-en",	"ahb-cam", 0x28,
+		     0x1000, BIT(9), 0, 0);
+
+static struct sprd_clk_common *sc9860_cam_gate[] = {
+	/* address base is 0x62100000 */
+	&dcam0_eb.common,
+	&dcam1_eb.common,
+	&isp0_eb.common,
+	&csi0_eb.common,
+	&csi1_eb.common,
+	&jpg0_eb.common,
+	&jpg1_eb.common,
+	&cam_ckg_eb.common,
+	&cam_mmu_eb.common,
+	&isp1_eb.common,
+	&cpp_eb.common,
+	&mmu_pf_eb.common,
+	&isp2_eb.common,
+	&dcam2isp_if_eb.common,
+	&isp2dcam_if_eb.common,
+	&isp_lclk_eb.common,
+	&isp_iclk_eb.common,
+	&isp_mclk_eb.common,
+	&isp_pclk_eb.common,
+	&isp_isp2dcam_eb.common,
+	&dcam0_if_eb.common,
+	&clk26m_if_eb.common,
+	&cphy0_gate.common,
+	&mipi_csi0_gate.common,
+	&cphy1_gate.common,
+	&mipi_csi1.common,
+	&dcam0_axi_gate.common,
+	&dcam1_axi_gate.common,
+	&sensor0_gate.common,
+	&sensor1_gate.common,
+	&jpg0_axi_gate.common,
+	&gpg1_axi_gate.common,
+	&isp0_axi_gate.common,
+	&isp1_axi_gate.common,
+	&isp2_axi_gate.common,
+	&cpp_axi_gate.common,
+	&d0_if_axi_gate.common,
+	&d2i_if_axi_gate.common,
+	&i2d_if_axi_gate.common,
+	&spare_axi_gate.common,
+	&sensor2_gate.common,
+	&d0if_in_d_en.common,
+	&d1if_in_d_en.common,
+	&d0if_in_d2i_en.common,
+	&d1if_in_d2i_en.common,
+	&ia_in_d2i_en.common,
+	&ib_in_d2i_en.common,
+	&ic_in_d2i_en.common,
+	&ia_in_i_en.common,
+	&ib_in_i_en.common,
+	&ic_in_i_en.common,
+};
+
+static struct clk_hw_onecell_data sc9860_cam_gate_hws = {
+	.hws	= {
+		[CLK_DCAM0_EB]		= &dcam0_eb.common.hw,
+		[CLK_DCAM1_EB]		= &dcam1_eb.common.hw,
+		[CLK_ISP0_EB]		= &isp0_eb.common.hw,
+		[CLK_CSI0_EB]		= &csi0_eb.common.hw,
+		[CLK_CSI1_EB]		= &csi1_eb.common.hw,
+		[CLK_JPG0_EB]		= &jpg0_eb.common.hw,
+		[CLK_JPG1_EB]		= &jpg1_eb.common.hw,
+		[CLK_CAM_CKG_EB]	= &cam_ckg_eb.common.hw,
+		[CLK_CAM_MMU_EB]	= &cam_mmu_eb.common.hw,
+		[CLK_ISP1_EB]		= &isp1_eb.common.hw,
+		[CLK_CPP_EB]		= &cpp_eb.common.hw,
+		[CLK_MMU_PF_EB]		= &mmu_pf_eb.common.hw,
+		[CLK_ISP2_EB]		= &isp2_eb.common.hw,
+		[CLK_DCAM2ISP_IF_EB]	= &dcam2isp_if_eb.common.hw,
+		[CLK_ISP2DCAM_IF_EB]	= &isp2dcam_if_eb.common.hw,
+		[CLK_ISP_LCLK_EB]	= &isp_lclk_eb.common.hw,
+		[CLK_ISP_ICLK_EB]	= &isp_iclk_eb.common.hw,
+		[CLK_ISP_MCLK_EB]	= &isp_mclk_eb.common.hw,
+		[CLK_ISP_PCLK_EB]	= &isp_pclk_eb.common.hw,
+		[CLK_ISP_ISP2DCAM_EB]	= &isp_isp2dcam_eb.common.hw,
+		[CLK_DCAM0_IF_EB]	= &dcam0_if_eb.common.hw,
+		[CLK_CLK26M_IF_EB]	= &clk26m_if_eb.common.hw,
+		[CLK_CPHY0_GATE]	= &cphy0_gate.common.hw,
+		[CLK_MIPI_CSI0_GATE]	= &mipi_csi0_gate.common.hw,
+		[CLK_CPHY1_GATE]	= &cphy1_gate.common.hw,
+		[CLK_MIPI_CSI1]		= &mipi_csi1.common.hw,
+		[CLK_DCAM0_AXI_GATE]	= &dcam0_axi_gate.common.hw,
+		[CLK_DCAM1_AXI_GATE]	= &dcam1_axi_gate.common.hw,
+		[CLK_SENSOR0_GATE]	= &sensor0_gate.common.hw,
+		[CLK_SENSOR1_GATE]	= &sensor1_gate.common.hw,
+		[CLK_JPG0_AXI_GATE]	= &jpg0_axi_gate.common.hw,
+		[CLK_GPG1_AXI_GATE]	= &gpg1_axi_gate.common.hw,
+		[CLK_ISP0_AXI_GATE]	= &isp0_axi_gate.common.hw,
+		[CLK_ISP1_AXI_GATE]	= &isp1_axi_gate.common.hw,
+		[CLK_ISP2_AXI_GATE]	= &isp2_axi_gate.common.hw,
+		[CLK_CPP_AXI_GATE]	= &cpp_axi_gate.common.hw,
+		[CLK_D0_IF_AXI_GATE]	= &d0_if_axi_gate.common.hw,
+		[CLK_D2I_IF_AXI_GATE]	= &d2i_if_axi_gate.common.hw,
+		[CLK_I2D_IF_AXI_GATE]	= &i2d_if_axi_gate.common.hw,
+		[CLK_SPARE_AXI_GATE]	= &spare_axi_gate.common.hw,
+		[CLK_SENSOR2_GATE]	= &sensor2_gate.common.hw,
+		[CLK_D0IF_IN_D_EN]	= &d0if_in_d_en.common.hw,
+		[CLK_D1IF_IN_D_EN]	= &d1if_in_d_en.common.hw,
+		[CLK_D0IF_IN_D2I_EN]	= &d0if_in_d2i_en.common.hw,
+		[CLK_D1IF_IN_D2I_EN]	= &d1if_in_d2i_en.common.hw,
+		[CLK_IA_IN_D2I_EN]	= &ia_in_d2i_en.common.hw,
+		[CLK_IB_IN_D2I_EN]	= &ib_in_d2i_en.common.hw,
+		[CLK_IC_IN_D2I_EN]	= &ic_in_d2i_en.common.hw,
+		[CLK_IA_IN_I_EN]	= &ia_in_i_en.common.hw,
+		[CLK_IB_IN_I_EN]	= &ib_in_i_en.common.hw,
+		[CLK_IC_IN_I_EN]	= &ic_in_i_en.common.hw,
+	},
+	.num	= CLK_CAM_GATE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_cam_gate_desc = {
+	.clk_clks	= sc9860_cam_gate,
+	.num_clk_clks	= ARRAY_SIZE(sc9860_cam_gate),
+	.hw_clks	= &sc9860_cam_gate_hws,
+};
+
+static SPRD_MUX_CLK(ahb_disp, "ahb-disp", ahb_parents, 0x20,
+		    0, 2, SC9860_MUX_FLAG);
+static SPRD_COMP_CLK(dispc0_dpi, "dispc0-dpi", dispc_parents,	0x34,
+		     0, 2, 8, 2, 0);
+static SPRD_COMP_CLK(dispc1_dpi, "dispc1-dpi", dispc_parents,	0x40,
+		     0, 2, 8, 2, 0);
+
+static struct sprd_clk_common *sc9860_disp_clk[] = {
+	/* address base is 0x63000000 */
+	&ahb_disp.common,
+	&dispc0_dpi.common,
+	&dispc1_dpi.common,
+};
+
+static struct clk_hw_onecell_data sc9860_disp_clk_hws = {
+	.hws	= {
+		[CLK_AHB_DISP]		= &ahb_disp.common.hw,
+		[CLK_DISPC0_DPI]	= &dispc0_dpi.common.hw,
+		[CLK_DISPC1_DPI]	= &dispc1_dpi.common.hw,
+	},
+	.num	= CLK_DISP_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_disp_clk_desc = {
+	.clk_clks	= sc9860_disp_clk,
+	.num_clk_clks	= ARRAY_SIZE(sc9860_disp_clk),
+	.hw_clks	= &sc9860_disp_clk_hws,
+};
+
+static SPRD_SC_GATE_CLK(dispc0_eb,	"dispc0-eb",	"ahb-disp", 0x0,
+		     0x1000, BIT(0), 0, 0);
+static SPRD_SC_GATE_CLK(dispc1_eb,	"dispc1-eb",	"ahb-disp", 0x0,
+		     0x1000, BIT(1), 0, 0);
+static SPRD_SC_GATE_CLK(dispc_mmu_eb,	"dispc-mmu-eb",	"ahb-disp", 0x0,
+		     0x1000, BIT(2), 0, 0);
+static SPRD_SC_GATE_CLK(gsp0_eb,		"gsp0-eb",	"ahb-disp", 0x0,
+		     0x1000, BIT(3), 0, 0);
+static SPRD_SC_GATE_CLK(gsp1_eb,		"gsp1-eb",	"ahb-disp", 0x0,
+		     0x1000, BIT(4), 0, 0);
+static SPRD_SC_GATE_CLK(gsp0_mmu_eb,	"gsp0-mmu-eb",	"ahb-disp", 0x0,
+		     0x1000, BIT(5), 0, 0);
+static SPRD_SC_GATE_CLK(gsp1_mmu_eb,	"gsp1-mmu-eb",	"ahb-disp", 0x0,
+		     0x1000, BIT(6), 0, 0);
+static SPRD_SC_GATE_CLK(dsi0_eb,		"dsi0-eb",	"ahb-disp", 0x0,
+		     0x1000, BIT(7), 0, 0);
+static SPRD_SC_GATE_CLK(dsi1_eb,		"dsi1-eb",	"ahb-disp", 0x0,
+		     0x1000, BIT(8), 0, 0);
+static SPRD_SC_GATE_CLK(disp_ckg_eb,	"disp-ckg-eb",	"ahb-disp", 0x0,
+		     0x1000, BIT(9), 0, 0);
+static SPRD_SC_GATE_CLK(disp_gpu_eb,	"disp-gpu-eb",	"ahb-disp", 0x0,
+		     0x1000, BIT(10), 0, 0);
+static SPRD_SC_GATE_CLK(gpu_mtx_eb,	"gpu-mtx-eb",	"ahb-disp", 0x0,
+		     0x1000, BIT(13), 0, 0);
+static SPRD_SC_GATE_CLK(gsp_mtx_eb,	"gsp-mtx-eb",	"ahb-disp", 0x0,
+		     0x1000, BIT(14), 0, 0);
+static SPRD_SC_GATE_CLK(tmc_mtx_eb,	"tmc-mtx-eb",	"ahb-disp", 0x0,
+		     0x1000, BIT(15), 0, 0);
+static SPRD_SC_GATE_CLK(dispc_mtx_eb,	"dispc-mtx-eb",	"ahb-disp", 0x0,
+		     0x1000, BIT(16), 0, 0);
+static SPRD_GATE_CLK(dphy0_gate,	"dphy0-gate",	"ahb-disp", 0x8,
+		     BIT(0), 0, 0);
+static SPRD_GATE_CLK(dphy1_gate,	"dphy1-gate",	"ahb-disp", 0x8,
+		     BIT(1), 0, 0);
+static SPRD_GATE_CLK(gsp0_a_gate,	"gsp0-a-gate",	"ahb-disp", 0x8,
+		     BIT(2), 0, 0);
+static SPRD_GATE_CLK(gsp1_a_gate,	"gsp1-a-gate",	"ahb-disp", 0x8,
+		     BIT(3), 0, 0);
+static SPRD_GATE_CLK(gsp0_f_gate,	"gsp0-f-gate",	"ahb-disp", 0x8,
+		     BIT(4), 0, 0);
+static SPRD_GATE_CLK(gsp1_f_gate,	"gsp1-f-gate",	"ahb-disp", 0x8,
+		     BIT(5), 0, 0);
+static SPRD_GATE_CLK(d_mtx_f_gate,	"d-mtx-f-gate",	"ahb-disp", 0x8,
+		     BIT(6), 0, 0);
+static SPRD_GATE_CLK(d_mtx_a_gate,	"d-mtx-a-gate",	"ahb-disp", 0x8,
+		     BIT(7), 0, 0);
+static SPRD_GATE_CLK(d_noc_f_gate,	"d-noc-f-gate",	"ahb-disp", 0x8,
+		     BIT(8), 0, 0);
+static SPRD_GATE_CLK(d_noc_a_gate,	"d-noc-a-gate",	"ahb-disp", 0x8,
+		     BIT(9), 0, 0);
+static SPRD_GATE_CLK(gsp_mtx_f_gate, "gsp-mtx-f-gate", "ahb-disp",  0x8,
+		     BIT(10), 0, 0);
+static SPRD_GATE_CLK(gsp_mtx_a_gate, "gsp-mtx-a-gate", "ahb-disp",  0x8,
+		     BIT(11), 0, 0);
+static SPRD_GATE_CLK(gsp_noc_f_gate, "gsp-noc-f-gate", "ahb-disp",  0x8,
+		     BIT(12), 0, 0);
+static SPRD_GATE_CLK(gsp_noc_a_gate, "gsp-noc-a-gate", "ahb-disp",  0x8,
+		     BIT(13), 0, 0);
+static SPRD_GATE_CLK(dispm0idle_gate, "dispm0idle-gate", "ahb-disp", 0x8,
+		     BIT(14), 0, 0);
+static SPRD_GATE_CLK(gspm0idle_gate, "gspm0idle-gate", "ahb-disp",  0x8,
+		     BIT(15), 0, 0);
+
+static struct sprd_clk_common *sc9860_disp_gate[] = {
+	/* address base is 0x63100000 */
+	&dispc0_eb.common,
+	&dispc1_eb.common,
+	&dispc_mmu_eb.common,
+	&gsp0_eb.common,
+	&gsp1_eb.common,
+	&gsp0_mmu_eb.common,
+	&gsp1_mmu_eb.common,
+	&dsi0_eb.common,
+	&dsi1_eb.common,
+	&disp_ckg_eb.common,
+	&disp_gpu_eb.common,
+	&gpu_mtx_eb.common,
+	&gsp_mtx_eb.common,
+	&tmc_mtx_eb.common,
+	&dispc_mtx_eb.common,
+	&dphy0_gate.common,
+	&dphy1_gate.common,
+	&gsp0_a_gate.common,
+	&gsp1_a_gate.common,
+	&gsp0_f_gate.common,
+	&gsp1_f_gate.common,
+	&d_mtx_f_gate.common,
+	&d_mtx_a_gate.common,
+	&d_noc_f_gate.common,
+	&d_noc_a_gate.common,
+	&gsp_mtx_f_gate.common,
+	&gsp_mtx_a_gate.common,
+	&gsp_noc_f_gate.common,
+	&gsp_noc_a_gate.common,
+	&dispm0idle_gate.common,
+	&gspm0idle_gate.common,
+};
+
+static struct clk_hw_onecell_data sc9860_disp_gate_hws = {
+	.hws	= {
+		[CLK_DISPC0_EB]		= &dispc0_eb.common.hw,
+		[CLK_DISPC1_EB]		= &dispc1_eb.common.hw,
+		[CLK_DISPC_MMU_EB]	= &dispc_mmu_eb.common.hw,
+		[CLK_GSP0_EB]		= &gsp0_eb.common.hw,
+		[CLK_GSP1_EB]		= &gsp1_eb.common.hw,
+		[CLK_GSP0_MMU_EB]	= &gsp0_mmu_eb.common.hw,
+		[CLK_GSP1_MMU_EB]	= &gsp1_mmu_eb.common.hw,
+		[CLK_DSI0_EB]		= &dsi0_eb.common.hw,
+		[CLK_DSI1_EB]		= &dsi1_eb.common.hw,
+		[CLK_DISP_CKG_EB]	= &disp_ckg_eb.common.hw,
+		[CLK_DISP_GPU_EB]	= &disp_gpu_eb.common.hw,
+		[CLK_GPU_MTX_EB]	= &gpu_mtx_eb.common.hw,
+		[CLK_GSP_MTX_EB]	= &gsp_mtx_eb.common.hw,
+		[CLK_TMC_MTX_EB]	= &tmc_mtx_eb.common.hw,
+		[CLK_DISPC_MTX_EB]	= &dispc_mtx_eb.common.hw,
+		[CLK_DPHY0_GATE]	= &dphy0_gate.common.hw,
+		[CLK_DPHY1_GATE]	= &dphy1_gate.common.hw,
+		[CLK_GSP0_A_GATE]	= &gsp0_a_gate.common.hw,
+		[CLK_GSP1_A_GATE]	= &gsp1_a_gate.common.hw,
+		[CLK_GSP0_F_GATE]	= &gsp0_f_gate.common.hw,
+		[CLK_GSP1_F_GATE]	= &gsp1_f_gate.common.hw,
+		[CLK_D_MTX_F_GATE]	= &d_mtx_f_gate.common.hw,
+		[CLK_D_MTX_A_GATE]	= &d_mtx_a_gate.common.hw,
+		[CLK_D_NOC_F_GATE]	= &d_noc_f_gate.common.hw,
+		[CLK_D_NOC_A_GATE]	= &d_noc_a_gate.common.hw,
+		[CLK_GSP_MTX_F_GATE]	= &gsp_mtx_f_gate.common.hw,
+		[CLK_GSP_MTX_A_GATE]	= &gsp_mtx_a_gate.common.hw,
+		[CLK_GSP_NOC_F_GATE]	= &gsp_noc_f_gate.common.hw,
+		[CLK_GSP_NOC_A_GATE]	= &gsp_noc_a_gate.common.hw,
+		[CLK_DISPM0IDLE_GATE]	= &dispm0idle_gate.common.hw,
+		[CLK_GSPM0IDLE_GATE]	= &gspm0idle_gate.common.hw,
+	},
+	.num	= CLK_DISP_GATE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_disp_gate_desc = {
+	.clk_clks	= sc9860_disp_gate,
+	.num_clk_clks	= ARRAY_SIZE(sc9860_disp_gate),
+	.hw_clks	= &sc9860_disp_gate_hws,
+};
+
+static SPRD_SC_GATE_CLK(sim0_eb,	"sim0-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(0), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(iis0_eb,	"iis0-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(1), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(iis1_eb,	"iis1-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(2), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(iis2_eb,	"iis2-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(3), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(iis3_eb,	"iis3-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(4), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(spi0_eb,	"spi0-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(5), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(spi1_eb,	"spi1-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(6), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(spi2_eb,	"spi2-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(7), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(i2c0_eb,	"i2c0-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(8), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(i2c1_eb,	"i2c1-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(9), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(i2c2_eb,	"i2c2-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(10), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(i2c3_eb,	"i2c3-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(11), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(i2c4_eb,	"i2c4-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(12), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(i2c5_eb,	"i2c5-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(13), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(uart0_eb,	"uart0-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(14), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(uart1_eb,	"uart1-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(15), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(uart2_eb,	"uart2-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(16), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(uart3_eb,	"uart3-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(17), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(uart4_eb,	"uart4-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(18), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(ap_ckg_eb,	"ap-ckg-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(19), CLK_IGNORE_UNUSED, 0);
+static SPRD_SC_GATE_CLK(spi3_eb,	"spi3-eb",	"ap-apb", 0x0,
+		     0x1000, BIT(20), CLK_IGNORE_UNUSED, 0);
+
+static struct sprd_clk_common *sc9860_apapb_gate[] = {
+	/* address base is 0x70b00000 */
+	&sim0_eb.common,
+	&iis0_eb.common,
+	&iis1_eb.common,
+	&iis2_eb.common,
+	&iis3_eb.common,
+	&spi0_eb.common,
+	&spi1_eb.common,
+	&spi2_eb.common,
+	&i2c0_eb.common,
+	&i2c1_eb.common,
+	&i2c2_eb.common,
+	&i2c3_eb.common,
+	&i2c4_eb.common,
+	&i2c5_eb.common,
+	&uart0_eb.common,
+	&uart1_eb.common,
+	&uart2_eb.common,
+	&uart3_eb.common,
+	&uart4_eb.common,
+	&ap_ckg_eb.common,
+	&spi3_eb.common,
+};
+
+static struct clk_hw_onecell_data sc9860_apapb_gate_hws = {
+	.hws	= {
+		[CLK_SIM0_EB]		= &sim0_eb.common.hw,
+		[CLK_IIS0_EB]		= &iis0_eb.common.hw,
+		[CLK_IIS1_EB]		= &iis1_eb.common.hw,
+		[CLK_IIS2_EB]		= &iis2_eb.common.hw,
+		[CLK_IIS3_EB]		= &iis3_eb.common.hw,
+		[CLK_SPI0_EB]		= &spi0_eb.common.hw,
+		[CLK_SPI1_EB]		= &spi1_eb.common.hw,
+		[CLK_SPI2_EB]		= &spi2_eb.common.hw,
+		[CLK_I2C0_EB]		= &i2c0_eb.common.hw,
+		[CLK_I2C1_EB]		= &i2c1_eb.common.hw,
+		[CLK_I2C2_EB]		= &i2c2_eb.common.hw,
+		[CLK_I2C3_EB]		= &i2c3_eb.common.hw,
+		[CLK_I2C4_EB]		= &i2c4_eb.common.hw,
+		[CLK_I2C5_EB]		= &i2c5_eb.common.hw,
+		[CLK_UART0_EB]		= &uart0_eb.common.hw,
+		[CLK_UART1_EB]		= &uart1_eb.common.hw,
+		[CLK_UART2_EB]		= &uart2_eb.common.hw,
+		[CLK_UART3_EB]		= &uart3_eb.common.hw,
+		[CLK_UART4_EB]		= &uart4_eb.common.hw,
+		[CLK_AP_CKG_EB]		= &ap_ckg_eb.common.hw,
+		[CLK_SPI3_EB]		= &spi3_eb.common.hw,
+	},
+	.num	= CLK_APAPB_GATE_NUM,
+};
+
+static const struct sprd_clk_desc sc9860_apapb_gate_desc = {
+	.clk_clks	= sc9860_apapb_gate,
+	.num_clk_clks	= ARRAY_SIZE(sc9860_apapb_gate),
+	.hw_clks	= &sc9860_apapb_gate_hws,
+};
+
+static const struct of_device_id sprd_sc9860_clk_ids[] = {
+	{ .compatible = "sprd,sc9860-pmu-gate",		/* 0x402b */
+	  .data = &sc9860_pmu_gate_desc },
+	{ .compatible = "sprd,sc9860-pll",		/* 0x4040 */
+	  .data = &sc9860_pll_desc },
+	{ .compatible = "sprd,sc9860-ap-clk",		/* 0x2000 */
+	  .data = &sc9860_ap_clk_desc },
+	{ .compatible = "sprd,sc9860-aon-prediv",	/* 0x402d */
+	  .data = &sc9860_aon_prediv_desc },
+	{ .compatible = "sprd,sc9860-apahb-gate",	/* 0x2021 */
+	  .data = &sc9860_apahb_gate_desc },
+	{ .compatible = "sprd,sc9860-aon-gate",		/* 0x402e */
+	  .data = &sc9860_aon_gate_desc },
+	{ .compatible = "sprd,sc9860-aonsecure-clk",	/* 0x4088 */
+	  .data = &sc9860_aonsecure_clk_desc },
+	{ .compatible = "sprd,sc9860-agcp-gate",	/* 0x415e */
+	  .data = &sc9860_agcp_gate_desc },
+	{ .compatible = "sprd,sc9860-gpu-clk",		/* 0x6020 */
+	  .data = &sc9860_gpu_clk_desc },
+	{ .compatible = "sprd,sc9860-vsp-clk",		/* 0x6100 */
+	  .data = &sc9860_vsp_clk_desc },
+	{ .compatible = "sprd,sc9860-vsp-gate",		/* 0x6110 */
+	  .data = &sc9860_vsp_gate_desc },
+	{ .compatible = "sprd,sc9860-cam-clk",		/* 0x6200 */
+	  .data = &sc9860_cam_clk_desc },
+	{ .compatible = "sprd,sc9860-cam-gate",		/* 0x6210 */
+	  .data = &sc9860_cam_gate_desc },
+	{ .compatible = "sprd,sc9860-disp-clk",		/* 0x6300 */
+	  .data = &sc9860_disp_clk_desc },
+	{ .compatible = "sprd,sc9860-disp-gate",	/* 0x6310 */
+	  .data = &sc9860_disp_gate_desc },
+	{ .compatible = "sprd,sc9860-apapb-gate",	/* 0x70b0 */
+	  .data = &sc9860_apapb_gate_desc },
+	{ }
+};
+MODULE_DEVICE_TABLE(of, sprd_sc9860_clk_ids);
+
+static int sc9860_clk_probe(struct platform_device *pdev)
+{
+	const struct of_device_id *match;
+	const struct sprd_clk_desc *desc;
+
+	match = of_match_node(sprd_sc9860_clk_ids, pdev->dev.of_node);
+	if (!match) {
+		pr_err("%s: of_match_node() failed", __func__);
+		return -ENODEV;
+	}
+
+	desc = match->data;
+	sprd_clk_regmap_init(pdev, desc);
+
+	return sprd_clk_probe(&pdev->dev, desc->hw_clks);
+}
+
+static struct platform_driver sc9860_clk_driver = {
+	.probe	= sc9860_clk_probe,
+	.driver	= {
+		.name	= "sc9860-clk",
+		.of_match_table	= sprd_sc9860_clk_ids,
+	},
+};
+module_platform_driver(sc9860_clk_driver);
+
+MODULE_DESCRIPTION("Spreadtrum SC9860 Clock Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:sc9860-clk");
-- 
2.7.4

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox