Add andestech atcpit100 timer
Subsystems (2)
v4 cover Add andestech atcpit100 timer
Changelog v4:
- Patch 1/3: Changes
- Patch 2/3: No changes
- Patch 3/3: Changes
Patch 1/3
1 Pre-compute some definetions
2 Remove PWM relative
3 Refine coding style
4 Wrap some calls into functions
4 Use timer-of API
5 Correct commit content
use channel1 timer0 as clock source
use channel0 timer0 as clock event
Patch 3/3
Remove description about clock-frequency
Add clocks description for timer-of API
Rick Chen (3):
clocksource/drivers/atcpit100: Add andestech atcpit100 timer clocksource/drivers/Kconfig: Support andestech atcpit100 timer
dt-bindings: timer: Add andestech atcpit100 timer binding doc
.../bindings/timer/andestech,atcpit100-timer.txt | 33 +++ drivers/clocksource/Kconfig | 6 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-atcpit100.c | 248 +++++++++++++++++++++ 4 files changed, 288 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/andestech,atcpit100-timer.txt create mode 100644 drivers/clocksource/timer-atcpit100.c
--
Changelog v3:
Patch 1/3
Fix warning from kbuild test robot when make ARCH=x86_64
Patch 3/3
--
Changelog v2:
Patch 3/3
1 Add commit msg
2 Change rick to full name Rick Chen
3 MOdify S-o-b
2.7.4
PATCH v4 1/3 clocksource/drivers/atcpit100: Add andestech atcpit100 timer
ATCPIT100 is often used on the Andes architecture, This timer provide 4 PIT channels. Each PIT channel is a multi-function timer, can be configured as 32,16,8 bit timers or PWM as well.
For system timer it will set channel 1 32-bit timer0 as clock source and count downwards until underflow and restart again.
It also set channel 0 32-bit timer0 as clock event and count downwards until condition match. It will generate an interrupt for handling periodically.
--- drivers/clocksource/timer-atcpit100.c | 248 ++++++++++++++++++++++++++++++++++ 1 file changed, 248 insertions(+) create mode 100644 drivers/clocksource/timer-atcpit100.c
drivers/clocksource/timer-atcpit100.c new file +248 -0
@@ -0,0 +1,248 @@ +/* +* Andestech ATCPIT100 Timer Device Driver Implementation +* +* Copyright (C) 2017 Andes Technology Corporation +* Rick Chen, Andes Technology Corporation <[email protected]> + +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* +*/ + +#include <linux/irq.h> +#include <linux/clocksource.h> +#include <linux/clockchips.h> +#include <linux/interrupt.h> +#include <linux/ioport.h> +#include <linux/cpufreq.h> +#include <linux/sched.h> +#include <linux/sched_clock.h> +#include <linux/of_address.h> +#include <linux/of_irq.h> +#include <linux/of_platform.h> +#include "timer-of.h" + +/* +* Definition of register offsets +*/ + +/* ID and Revision Register */ +#define ID_REV 0x0 + +/* Configuration Register */ +#define CFG 0x10 + +/* Interrupt Enable Register */ +#define INT_EN 0x14 +#define CH_INT_EN (c, i) ((1<<i)<<(4*c)) +#define CH0INT0EN 0x01 + +/* Interrupt Status Register */ +#define INT_STA 0x18 +#define CH0INT0 0x01 + +/* Channel Enable Register */ +#define CH_EN 0x1C +#define CH0TMR0EN 0x1 +#define CH1TMR0EN 0x10 + +/* Channel 0 , 1 Control Register */ +#define CH0_CTL (0x20) +#define CH1_CTL (0x20 + 0x10) + +/* Channel clock source , bit 3 , 0:External clock , 1:APB clock */ +#define APB_CLK BIT(3) + +/* Channel mode , bit 0~2 */ +#define TMR_32 0x1 +#define TMR_16 0x2 +#define TMR_8 0x3 + +/* Channel 0 , 1 Reload Register */ +#define CH0_REL (0x24) +#define CH1_REL (0x24 + 0x10) + +/* Channel 0 , 1 Counter Register */ +#define CH0_CNT (0x28) +#define CH1_CNT (0x28 + 0x10) + +#define TIMER_SYNC_TICKS 3 + +static void atcpit100_ch1_tmr0_en (void __iomem *base) +{ +writel (~0 , base +CH1_REL ); +writel (APB_CLK |TMR_32 , base +CH1_CTL ); +} + +static void atcpit100_ch0_tmr0_en (void __iomem *base) +{ +writel (APB_CLK |TMR_32 , base +CH0_CTL ); +} + +static void atcpit100_clkevt_time_setup (void __iomem *base,unsigned long delay) +{ +writel (delay, base +CH0_CNT ); +writel (delay, base +CH0_REL ); +} + +static void atcpit100_timer_clear_interrupt (void __iomem *base) +{ +u32 val; + + val =readl (base +INT_STA ); +writel (val |CH0INT0 , base +INT_STA ); +} + +static void atcpit100_clocksource_start (void __iomem *base) +{ +u32 val; + + val =readl (base +CH_EN ); +writel (val |CH1TMR0EN , base +CH_EN ); +} + +static void atcpit100_clkevt_time_start (void __iomem *base) +{ +u32 val; + + val =readl (base +CH_EN ); +writel (val |CH0TMR0EN , base +CH_EN ); +} + +static void atcpit100_clkevt_time_stop (void __iomem *base) +{ +u32 val; + +atcpit100_timer_clear_interrupt (base); + val =readl (base +CH_EN ); +writel (val & ~CH0TMR0EN , base +CH_EN ); +} + +static int atcpit100_clkevt_next_event (unsigned long evt, +struct clock_event_device *clkevt) +{ +struct timer_of *to =to_timer_of (clkevt); + +writel (evt,timer_of_base (to) +CH0_REL ); + +return 0 ; +} + +static int atcpit100_clkevt_set_periodic (struct clock_event_device *evt) +{ +struct timer_of *to =to_timer_of (evt); + +atcpit100_clkevt_time_setup (timer_of_base (to),timer_of_period (to)); +atcpit100_clkevt_time_start (timer_of_base (to)); + +return 0 ; +} +static int atcpit100_clkevt_shutdown (struct clock_event_device *evt) +{ +struct timer_of *to =to_timer_of (evt); + +atcpit100_clkevt_time_stop (timer_of_base (to)); + +return 0 ; +} +static int atcpit100_clkevt_set_oneshot (struct clock_event_device *evt) +{ +struct timer_of *to =to_timer_of (evt); +u32 val; + +writel (~0x0 ,timer_of_base (to) +CH0_REL ); + val =readl (timer_of_base (to) +CH_EN ); +writel (val |CH0TMR0EN ,timer_of_base (to) +CH_EN ); + +return 0 ; +} + +static irqreturn_t atcpit100_timer_interrupt (int irq,void *dev_id) +{ +struct clock_event_device *evt = (struct clock_event_device *)dev_id; +struct timer_of *to =to_timer_of (evt); + +atcpit100_timer_clear_interrupt (timer_of_base (to)); + + evt->event_handler (evt); + +return IRQ_HANDLED ; +} + +static struct timer_of to = { + .flags =TIMER_OF_IRQ |TIMER_OF_CLOCK |TIMER_OF_BASE , + + .clkevt = { + .name ="atcpit100_tick" , + .rating =300 , + .features =CLOCK_EVT_FEAT_PERIODIC |CLOCK_EVT_FEAT_ONESHOT , + .set_state_shutdown = atcpit100_clkevt_shutdown, + .set_state_periodic = atcpit100_clkevt_set_periodic, + .set_state_oneshot = atcpit100_clkevt_set_oneshot, + .tick_resume = atcpit100_clkevt_shutdown, + .set_next_event = atcpit100_clkevt_next_event, + .cpumask = cpu_all_mask, + }, + + .of_irq = { + .handler = atcpit100_timer_interrupt, + .flags =IRQF_TIMER |IRQF_IRQPOLL , + }, +}; + +static u64 notrace atcpit100_timer_sched_read(void) +{ +return ~readl (timer_of_base (&to) +CH1_CNT ); +} + +static int __init atcpit100_timer_init (struct device_node *node) +{ +int ret; +u32 val; +void __iomem *base; + + ret =timer_of_init (node, &to); +if (ret) +return ret; + + base =timer_of_base (&to); + +sched_clock_register (atcpit100_timer_sched_read,32 , +timer_of_rate (&to)); + + ret =clocksource_mmio_init (base +CH1_CNT , + node->name,timer_of_rate (&to),300 ,32 , + clocksource_mmio_readl_down); + +if (ret) { +pr_err ("Failed to register clocksource\n" ); +return ret; + } + +/* clear channel 0 timer0 interrupt */ +atcpit100_timer_clear_interrupt (base); + +clockevents_config_and_register (&to.clkevt,timer_of_rate (&to), +TIMER_SYNC_TICKS ,0xffffffff ); +atcpit100_ch0_tmr0_en (base); +atcpit100_ch1_tmr0_en (base); +atcpit100_clocksource_start (base); +atcpit100_clkevt_time_start (base); + +/* Enable channel 0 timer0 interrupt */ + val =readl (base +INT_EN ); +writel (val |CH0INT0EN , base +INT_EN ); + +return ret; +} + +TIMER_OF_DECLARE (atcpit100,"andestech,atcpit100" , atcpit100_timer_init);
Signature · 1 line
2.7.4
PATCH v4 2/3 clocksource/drivers/Kconfig: Support andestech atcpit100 timer
In reply to Rick ChenAdd CLKSRC_ATCPIT100 for Andestech atcpit100 timer selection. It often be used in Andestech AE3XX platform.
--- drivers/clocksource/Kconfig | 6 ++++++ drivers/clocksource/Makefile | 1 + 2 files changed, 7 insertions(+)
drivers/clocksource/Kconfig +6 -0
@@ -615,4 +615,10 @@ config CLKSRC_ST_LPC Enable this option to use the Low Power controller timer as clocksource. +config CLKSRC_ATCPIT100 + bool "Clocksource for AE3XX platform" if COMPILE_TEST + depends on GENERIC_CLOCKEVENTS && HAS_IOMEM + help + This option enables support for the Andestech AE3XX platform timers. + endmenu
drivers/clocksource/Makefile +1 -0
@@ -74,3 +74,4 @@ obj-$(CONFIG_H8300_TMR16) += h8300_timer16.o obj-$(CONFIG_H8300_TPU) += h8300_tpu.o obj-$(CONFIG_CLKSRC_ST_LPC) += clksrc_st_lpc.o obj-$(CONFIG_X86_NUMACHIP) += numachip.o +obj-$(CONFIG_CLKSRC_ATCPIT100) += timer-atcpit100.o
Signature · 6 lines
2.7.4 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to [email protected] More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH v4 3/3 dt-bindings: timer: Add andestech atcpit100 timer binding doc
In reply to Rick ChenAdd a document to describe Andestech atcpit100 timer and binding information.
--- .../bindings/timer/andestech,atcpit100-timer.txt | 33 ++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 Documentation/devicetree/bindings/timer/andestech,atcpit100-timer.txt
Documentation/devicetree/bindings/timer/andestech,atcpit100-timer.txt new file +33 -0
@@ -0,0 +1,33 @@ +Andestech ATCPIT100 timer +------------------------------------------------------------------ +ATCPIT100 is a generic IP block from Andes Technology, embedded in +Andestech AE3XX platforms and other designs. + +This timer is a set of compact multi-function timers, which can be +used as pulse width modulators (PWM) as well as simple timers. + +It supports up to 4 PIT channels. Each PIT channel is a +multi-function timer and provide the following usage scenarios: +One 32-bit timer +Two 16-bit timers +Four 8-bit timers +One 16-bit PWM +One 16-bit timer and one 8-bit PWM +Two 8-bit timer and one 8-bit PWM + +Required properties: +- compatible : Should be "andestech,atcpit100" +- reg : Address and length of the register set +- interrupts : Reference to the timer interrupt +- clocks : a clock to provide the tick rate for "andestech,atcpit100" +- clock-names : should be "PCLK" for the external tick timer. + +Examples: + +timer0: timer@f0400000 { + compatible = "andestech,atcpit100"; + reg = <0xf0400000 0x1000>; + interrupts = <2 4>; + clocks = <&clk_pll>; + clock-names = "PCLK"; +};
Signature · 1 line
2.7.4