mbox series

[v2,0/2] Add drivers for Intel Keem Bay SoC timer block

Message ID cover.1609306622.git.vijayakannan.ayyathurai@intel.com
Headers show
Series Add drivers for Intel Keem Bay SoC timer block | expand

Message

Ayyathurai, Vijayakannan Dec. 30, 2020, 6:25 a.m. UTC
From: Vijayakannan Ayyathurai <vijayakannan.ayyathurai@intel.com>

Hi,

This patch set adds the driver for Intel Keem Bay SoC timer block, which
contains 32-bit general purpose timers, a 64 bit free running counter.

Patch 1 holds the Device Tree binding documentation and
Patch 2 holds the Device Driver for clocksource and clockevent.

It was tested on the Keem Bay evaluation module board.

Thanks,
Vijay

Changes since v1:
 - Add support for KEEMBAY_TIMER to get selected through Kconfig.platforms.
 - Add CLOCK_EVT_FEAT_DYNIRQ as part of clockevent feature.
 - Avoid overlapping reg regions across 2 device nodes.
 - Simplify 2 device nodes as 1 because both are from same IP block.
 - Adapt the driver code according to the new simplified devicetree.

Vijayakannan Ayyathurai (2):
  dt-bindings: timer: Add bindings for Intel Keem Bay SoC timer
  clocksource: Add Intel Keem Bay Timer Support

 .../bindings/timer/intel,keembay-timer.yaml   |  52 ++++
 arch/arm64/Kconfig.platforms                  |   1 +
 drivers/clocksource/Kconfig                   |  10 +
 drivers/clocksource/Makefile                  |   1 +
 drivers/clocksource/timer-keembay.c           | 225 ++++++++++++++++++
 5 files changed, 289 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/timer/intel,keembay-timer.yaml
 create mode 100644 drivers/clocksource/timer-keembay.c


base-commit: 5c8fe583cce542aa0b84adc939ce85293de36e5e
prerequisite-patch-id: bbb340c3a34059ea6960e8b96f5ad3bf0b4ae7b0
prerequisite-patch-id: b71b548284a57a38ce96d9bb523eadfccabd6e02

Comments

Ayyathurai, Vijayakannan Jan. 13, 2021, 10:54 a.m. UTC | #1
Hi,

> From: Vijayakannan Ayyathurai <vijayakannan.ayyathurai@intel.com>
> 
> Changes since v1:
>  - Add support for KEEMBAY_TIMER to get selected through Kconfig.platforms.
>  - Add CLOCK_EVT_FEAT_DYNIRQ as part of clockevent feature.
>  - Avoid overlapping reg regions across 2 device nodes.
>  - Simplify 2 device nodes as 1 because both are from same IP block.
>  - Adapt the driver code according to the new simplified devicetree.
> 
> Vijayakannan Ayyathurai (2):
>   dt-bindings: timer: Add bindings for Intel Keem Bay SoC timer
>   clocksource: Add Intel Keem Bay Timer Support

Kindly help us to review this updated patch(v2) set.

Thanks,
Vijay
Daniel Lezcano Jan. 18, 2021, 3:34 p.m. UTC | #2
On 13/01/2021 11:54, Ayyathurai, Vijayakannan wrote:
> Hi,
> 
>> From: Vijayakannan Ayyathurai <vijayakannan.ayyathurai@intel.com>
>>
>> Changes since v1:
>>  - Add support for KEEMBAY_TIMER to get selected through Kconfig.platforms.
>>  - Add CLOCK_EVT_FEAT_DYNIRQ as part of clockevent feature.
>>  - Avoid overlapping reg regions across 2 device nodes.
>>  - Simplify 2 device nodes as 1 because both are from same IP block.
>>  - Adapt the driver code according to the new simplified devicetree.
>>
>> Vijayakannan Ayyathurai (2):
>>   dt-bindings: timer: Add bindings for Intel Keem Bay SoC timer
>>   clocksource: Add Intel Keem Bay Timer Support
> 
> Kindly help us to review this updated patch(v2) set.

Review in progress ... :)
Daniel Lezcano Jan. 18, 2021, 3:56 p.m. UTC | #3
On 30/12/2020 07:25, vijayakannan.ayyathurai@intel.com wrote:
> From: Vijayakannan Ayyathurai <vijayakannan.ayyathurai@intel.com>

[ ... ]

> +static struct timer_of keembay_ce_to = {
> +	.flags	= TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
> +	.clkevt = {
> +		.name			= "keembay_sys_clkevt",
> +		.features		= CLOCK_EVT_FEAT_PERIODIC |
> +					  CLOCK_EVT_FEAT_ONESHOT  |
> +					  CLOCK_EVT_FEAT_DYNIRQ,
> +		.rating			= TIM_RATING,
> +		.set_next_event		= keembay_timer_set_next_event,
> +		.set_state_periodic	= keembay_timer_periodic,
> +		.set_state_shutdown	= keembay_timer_shutdown,
> +	},
> +	.of_base = {
> +		.index = 0,
> +	},
> +	.of_irq = {
> +		.handler = keembay_timer_isr,
> +		.flags = IRQF_TIMER | IRQF_IRQPOLL,

Is the IRQPOLL flag really needed here ?

> +	},
> +};
> +
> +static int __init keembay_clockevent_init(struct device_node *np,
> +					  struct keembay_init_data *data)
> +{
> +	u32 val;
> +	int ret;
> +
> +	data->mask = TIM_CONFIG_PRESCALER_ENABLE;
> +	data->cfg = &keembay_ce_to;
> +	ret = keembay_timer_setup(np, data);
> +	if (ret)
> +		return ret;
> +
> +	val = readl(data->base + TIM_RELOAD_VAL_OFFSET);
> +
> +	keembay_ce_to.clkevt.cpumask = cpumask_of(0);
> +	keembay_ce_to.of_clk.rate = keembay_ce_to.of_clk.rate / (val + 1);
> +
> +	keembay_timer_disable(timer_of_base(&keembay_ce_to));
> +
> +	clockevents_config_and_register(&keembay_ce_to.clkevt,
> +					timer_of_rate(&keembay_ce_to), 1, U32_MAX);
> +	return 0;
> +}
> +
> +static struct timer_of keembay_cs_to = {
> +	.flags	= TIMER_OF_BASE | TIMER_OF_CLOCK,
> +	.of_base = {
> +		.index = 1,
> +	},
> +};
> +
> +static u64 notrace keembay_clocksource_read(struct clocksource *cs)
> +{
> +	return lo_hi_readq(timer_of_base(&keembay_cs_to));
> +}
> +
> +static struct clocksource keembay_counter = {
> +	.name			= "keembay_sys_counter",
> +	.rating			= TIM_RATING,
> +	.read			= keembay_clocksource_read,
> +	.mask			= CLOCKSOURCE_MASK(TIM_CLKSRC_BITS),
> +	.flags			= CLOCK_SOURCE_IS_CONTINUOUS |
> +				  CLOCK_SOURCE_SUSPEND_NONSTOP,
> +};
> +
> +static int __init keembay_clocksource_init(struct device_node *np,
> +					   struct keembay_init_data *data)
> +{
> +	int ret;
> +
> +	data->mask = TIM_CONFIG_ENABLE;
> +	data->cfg = &keembay_cs_to;
> +	ret = keembay_timer_setup(np, data);
> +	if (ret)
> +		return ret;
> +
> +	return clocksource_register_hz(&keembay_counter, timer_of_rate(&keembay_cs_to));
> +}
> +
> +static int __init keembay_timer_init(struct device_node *np)
> +{
> +	struct keembay_init_data data;
> +	int ret;
> +
> +	data.base = of_iomap(np, 2);
> +	if (!data.base)
> +		return -ENXIO;
> +
> +	ret = keembay_clocksource_init(np, &data);
> +	if (ret)
> +		goto exit;
> +
> +	ret = keembay_clockevent_init(np, &data);

Is this missing ?

	if (ret)
		goto exit;

	return 0;

> +
> +exit:
> +	keembay_timer_cleanup(np, &data);
> +
> +	return ret;
> +}
> +
> +TIMER_OF_DECLARE(keembay_timer, "intel,keembay-timer", keembay_timer_init);
>
Ayyathurai, Vijayakannan Jan. 19, 2021, 1:55 a.m. UTC | #4
Hi Daniel,

> From: Daniel Lezcano <daniel.lezcano@linaro.org>
> >> From: Vijayakannan Ayyathurai <vijayakannan.ayyathurai@intel.com>
> >>
> >> Changes since v1:
> >>  - Add support for KEEMBAY_TIMER to get selected through
> Kconfig.platforms.
> >>  - Add CLOCK_EVT_FEAT_DYNIRQ as part of clockevent feature.
> >>  - Avoid overlapping reg regions across 2 device nodes.
> >>  - Simplify 2 device nodes as 1 because both are from same IP block.
> >>  - Adapt the driver code according to the new simplified devicetree.
> >>
> >> Vijayakannan Ayyathurai (2):
> >>   dt-bindings: timer: Add bindings for Intel Keem Bay SoC timer
> >>   clocksource: Add Intel Keem Bay Timer Support
> >
> > Kindly help us to review this updated patch(v2) set.
> 
> Review in progress ... :)
> 

Thank you for the Review. 

Thanks,
Vijay
Ayyathurai, Vijayakannan Jan. 19, 2021, 2:56 a.m. UTC | #5
Hi Daniel,

> From: Daniel Lezcano <daniel.lezcano@linaro.org>
> > From: Vijayakannan Ayyathurai <vijayakannan.ayyathurai@intel.com>
> 
> [ ... ]
> 
> > +static struct timer_of keembay_ce_to = {
> > +	.flags	= TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK,
> > +	.clkevt = {
> > +		.name			= "keembay_sys_clkevt",
> > +		.features		= CLOCK_EVT_FEAT_PERIODIC |
> > +					  CLOCK_EVT_FEAT_ONESHOT  |
> > +					  CLOCK_EVT_FEAT_DYNIRQ,
> > +		.rating			= TIM_RATING,
> > +		.set_next_event		=
> keembay_timer_set_next_event,
> > +		.set_state_periodic	= keembay_timer_periodic,
> > +		.set_state_shutdown	= keembay_timer_shutdown,
> > +	},
> > +	.of_base = {
> > +		.index = 0,
> > +	},
> > +	.of_irq = {
> > +		.handler = keembay_timer_isr,
> > +		.flags = IRQF_TIMER | IRQF_IRQPOLL,
> 
> Is the IRQPOLL flag really needed here ?
> 

Not really needed. I will remove this redundant Flag in my next version.

> > +static int __init keembay_timer_init(struct device_node *np)
> > +{
> > +	struct keembay_init_data data;
> > +	int ret;
> > +
> > +	data.base = of_iomap(np, 2);
> > +	if (!data.base)
> > +		return -ENXIO;
> > +
> > +	ret = keembay_clocksource_init(np, &data);
> > +	if (ret)
> > +		goto exit;
> > +
> > +	ret = keembay_clockevent_init(np, &data);
> 
> Is this missing ?
> 

Yes. Either case it goes to the exit path. So I thought of avoiding this error handling code.

> 	if (ret)
> 		goto exit;
> 
> 	return 0;
> 
> > +
> > +exit:
> > +	keembay_timer_cleanup(np, &data);
> > +
> > +	return ret;
> > +}
> > +
> > +TIMER_OF_DECLARE(keembay_timer, "intel,keembay-timer",
> keembay_timer_init);
> >
> 

Thanks,
Vijay
Andy Shevchenko Jan. 19, 2021, 8:50 a.m. UTC | #6
On Tue, Jan 19, 2021 at 02:56:36AM +0000, Ayyathurai, Vijayakannan wrote:

...

> > > +	data.base = of_iomap(np, 2);
> > > +	if (!data.base)
> > > +		return -ENXIO;
> > > +
> > > +	ret = keembay_clocksource_init(np, &data);
> > > +	if (ret)
> > > +		goto exit;
> > > +
> > > +	ret = keembay_clockevent_init(np, &data);
> > 
> > Is this missing ?
> > 
> 
> Yes. Either case it goes to the exit path. So I thought of avoiding this error handling code.

The point is that in success you probably won't call keembay_timer_cleanup().

> > 	if (ret)
> > 		goto exit;
> > 
> > 	return 0;
> > 
> > > +exit:
> > > +	keembay_timer_cleanup(np, &data);
> > > +
> > > +	return ret;
> > > +}
Ayyathurai, Vijayakannan Jan. 20, 2021, 7:18 p.m. UTC | #7
Hi Andy,

> From: andriy.shevchenko@linux.intel.com
> 
> > > > +	data.base = of_iomap(np, 2);
> > > > +	if (!data.base)
> > > > +		return -ENXIO;
> > > > +
> > > > +	ret = keembay_clocksource_init(np, &data);
> > > > +	if (ret)
> > > > +		goto exit;
> > > > +
> > > > +	ret = keembay_clockevent_init(np, &data);
> > >
> > > Is this missing ?
> > >
> >
> > Yes. Either case it goes to the exit path. So I thought of avoiding this error
> handling code.
> 
> The point is that in success you probably won't call keembay_timer_cleanup().
> 

Yes. You are right, if I use this error handling code.

> > > 	if (ret)
> > > 		goto exit;
> > >
> > > 	return 0;
> > >
> > > > +exit:
> > > > +	keembay_timer_cleanup(np, &data);
> > > > +
> > > > +	return ret;
> > > > +}
> 
Thanks,
Vijay