Re: [PATCH v6 4/5] clocksource: add driver for i.MX EPIT timer

2018-06-11 Thread Vladimir Zapolskiy
On 06/07/2018 05:05 PM, Clément Péron wrote:
> From: Colin Didier 
> 
> Add driver for NXP's EPIT timer used in i.MX SoC.
> 
> Signed-off-by: Colin Didier 
> Signed-off-by: Clément Peron 

Reviewed-by: Vladimir Zapolskiy 
Tested-by: Vladimir Zapolskiy 

I tested the driver on i.MX31 only, and I didn't find any problems.

Please fix the indentation issue found by Stefan in v7.

Regarding utilization of timer-of.c it can be postponed IMHO,
but it's up to clocksource maintainers and you to decide, and if
you do such an update for v7, then please don't add my tags,
I'll review and test it again.

--
With best wishes,
Vladimir


Re: [PATCH v6 4/5] clocksource: add driver for i.MX EPIT timer

2018-06-11 Thread Vladimir Zapolskiy
On 06/07/2018 05:05 PM, Clément Péron wrote:
> From: Colin Didier 
> 
> Add driver for NXP's EPIT timer used in i.MX SoC.
> 
> Signed-off-by: Colin Didier 
> Signed-off-by: Clément Peron 

Reviewed-by: Vladimir Zapolskiy 
Tested-by: Vladimir Zapolskiy 

I tested the driver on i.MX31 only, and I didn't find any problems.

Please fix the indentation issue found by Stefan in v7.

Regarding utilization of timer-of.c it can be postponed IMHO,
but it's up to clocksource maintainers and you to decide, and if
you do such an update for v7, then please don't add my tags,
I'll review and test it again.

--
With best wishes,
Vladimir


Re: [PATCH v6 4/5] clocksource: add driver for i.MX EPIT timer

2018-06-11 Thread Stefan Agner
On 11.06.2018 14:42, Clément Péron wrote:
> Hi Stefan,
> 
> 
>> > +
>> > +#define EPITCR   0x00
>> > +#define EPITSR   0x04
>> > +#define EPITLR   0x08
>> > +#define EPITCMPR 0x0c
>> > +#define EPITCNR  0x10
>> > +
>> > +#define EPITCR_ENBIT(0)
>> > +#define EPITCR_ENMOD BIT(1)
>> > +#define EPITCR_OCIEN BIT(2)
>> > +#define EPITCR_RLD   BIT(3)
>> > +#define EPITCR_PRESC(x)  (((x) & 0xfff) << 4)
>> > +#define EPITCR_SWR   BIT(16)
>> > +#define EPITCR_IOVW  BIT(17)
>> > +#define EPITCR_DBGEN BIT(18)
>> > +#define EPITCR_WAITENBIT(19)
>> > +#define EPITCR_RES   BIT(20)
>> > +#define EPITCR_STOPENBIT(21)
>> > +#define EPITCR_OM_DISCON (0 << 22)
>> > +#define EPITCR_OM_TOGGLE (1 << 22)
>> > +#define EPITCR_OM_CLEAR  (2 << 22)
>> > +#define EPITCR_OM_SET(3 << 22)
>> > +#define EPITCR_CLKSRC_OFF(0 << 24)
>> > +#define EPITCR_CLKSRC_PERIPHERAL (1 << 24)
>> > +#define EPITCR_CLKSRC_REF_HIGH   (2 << 24)
>> > +#define EPITCR_CLKSRC_REF_LOW(3 << 24)
>> > +
>> > +#define EPITSR_OCIF  BIT(0)
>> > +
>> > +struct epit_timer {
>> > + void __iomem *base;
>> > + int irq;
>> > + struct clk *clk;
>> > + struct clock_event_device ced;
>> > + struct irqaction act;
>> > +};
>> > +
>> > +static void __iomem *sched_clock_reg;
>> > +
>> > +static inline struct epit_timer *to_epit_timer(struct clock_event_device 
>> > *ced)
>> > +{
>> > + return container_of(ced, struct epit_timer, ced);
>> > +}
>> > +
>> > +static inline void epit_irq_disable(struct epit_timer *epittm)
>> > +{
>> > + u32 val;
>> > +
>> > + val = readl_relaxed(epittm->base + EPITCR);
>> > + writel_relaxed(val & ~EPITCR_OCIEN, epittm->base + EPITCR);
>> > +}
>> > +
>> > +static inline void epit_irq_enable(struct epit_timer *epittm)
>> > +{
>> > + u32 val;
>> > +
>> > + val = readl_relaxed(epittm->base + EPITCR);
>> > + writel_relaxed(val | EPITCR_OCIEN, epittm->base + EPITCR);
>> > +}
>> > +
>> > +static void epit_irq_acknowledge(struct epit_timer *epittm)
>> > +{
>> > + writel_relaxed(EPITSR_OCIF, epittm->base + EPITSR);
>> > +}
>> > +
>> > +static u64 notrace epit_read_sched_clock(void)
>> > +{
>> > + return ~readl_relaxed(sched_clock_reg);
>> > +}
>> > +
>> > +static int epit_set_next_event(unsigned long cycles,
>> > +struct clock_event_device *ced)
>> > +{
>> > + struct epit_timer *epittm = to_epit_timer(ced);
>> > + unsigned long tcmp;
>> > +
>> > + tcmp = readl_relaxed(epittm->base + EPITCNR) - cycles;
>> > + writel_relaxed(tcmp, epittm->base + EPITCMPR);
>> > +
>> > + return 0;
>> > +}
>> > +
>> > +/* Left event sources disabled, no more interrupts appear */
>> > +static int epit_shutdown(struct clock_event_device *ced)
>> > +{
>> > + struct epit_timer *epittm = to_epit_timer(ced);
>> > + unsigned long flags;
>> > +
>> > + /*
>> > +  * The timer interrupt generation is disabled at least
>> > +  * for enough time to call epit_set_next_event()
>> > +  */
>> > + local_irq_save(flags);
>> > +
>> > + /* Disable interrupt in EPIT module */
>> > + epit_irq_disable(epittm);
>> > +
>> > + /* Clear pending interrupt */
>> > + epit_irq_acknowledge(epittm);
>> > +
>> > + local_irq_restore(flags);
>> > +
>> > + return 0;
>> > +}
>> > +
>> > +static int epit_set_oneshot(struct clock_event_device *ced)
>> > +{
>> > + struct epit_timer *epittm = to_epit_timer(ced);
>> > + unsigned long flags;
>> > +
>> > + /*
>> > +  * The timer interrupt generation is disabled at least
>> > +  * for enough time to call epit_set_next_event()
>> > +  */
>> > + local_irq_save(flags);
>> > +
>> > + /* Disable interrupt in EPIT module */
>> > + epit_irq_disable(epittm);
>> > +
>> > + /* Clear pending interrupt, only while switching mode */
>> > + if (!clockevent_state_oneshot(ced))
>> > + epit_irq_acknowledge(epittm);
>> > +
>> > + /*
>> > +  * Do not put overhead of interrupt enable/disable into
>> > +  * epit_set_next_event(), the core has about 4 minutes
>> > +  * to call epit_set_next_event() or shutdown clock after
>> > +  * mode switching
>> > +  */
>> > + epit_irq_enable(epittm);
>> > + local_irq_restore(flags);
>> > +
>> > + return 0;
>> > +}
>> > +
>> > +static irqreturn_t epit_timer_interrupt(int irq, void *dev_id)
>> > +{
>> > + struct clock_event_device *ced = dev_id;
>> > + struct epit_timer *epittm = to_epit_timer(ced);
>> > +
>> > + epit_irq_acknowledge(epittm);
>> > +
>> > 

Re: [PATCH v6 4/5] clocksource: add driver for i.MX EPIT timer

2018-06-11 Thread Stefan Agner
On 11.06.2018 14:42, Clément Péron wrote:
> Hi Stefan,
> 
> 
>> > +
>> > +#define EPITCR   0x00
>> > +#define EPITSR   0x04
>> > +#define EPITLR   0x08
>> > +#define EPITCMPR 0x0c
>> > +#define EPITCNR  0x10
>> > +
>> > +#define EPITCR_ENBIT(0)
>> > +#define EPITCR_ENMOD BIT(1)
>> > +#define EPITCR_OCIEN BIT(2)
>> > +#define EPITCR_RLD   BIT(3)
>> > +#define EPITCR_PRESC(x)  (((x) & 0xfff) << 4)
>> > +#define EPITCR_SWR   BIT(16)
>> > +#define EPITCR_IOVW  BIT(17)
>> > +#define EPITCR_DBGEN BIT(18)
>> > +#define EPITCR_WAITENBIT(19)
>> > +#define EPITCR_RES   BIT(20)
>> > +#define EPITCR_STOPENBIT(21)
>> > +#define EPITCR_OM_DISCON (0 << 22)
>> > +#define EPITCR_OM_TOGGLE (1 << 22)
>> > +#define EPITCR_OM_CLEAR  (2 << 22)
>> > +#define EPITCR_OM_SET(3 << 22)
>> > +#define EPITCR_CLKSRC_OFF(0 << 24)
>> > +#define EPITCR_CLKSRC_PERIPHERAL (1 << 24)
>> > +#define EPITCR_CLKSRC_REF_HIGH   (2 << 24)
>> > +#define EPITCR_CLKSRC_REF_LOW(3 << 24)
>> > +
>> > +#define EPITSR_OCIF  BIT(0)
>> > +
>> > +struct epit_timer {
>> > + void __iomem *base;
>> > + int irq;
>> > + struct clk *clk;
>> > + struct clock_event_device ced;
>> > + struct irqaction act;
>> > +};
>> > +
>> > +static void __iomem *sched_clock_reg;
>> > +
>> > +static inline struct epit_timer *to_epit_timer(struct clock_event_device 
>> > *ced)
>> > +{
>> > + return container_of(ced, struct epit_timer, ced);
>> > +}
>> > +
>> > +static inline void epit_irq_disable(struct epit_timer *epittm)
>> > +{
>> > + u32 val;
>> > +
>> > + val = readl_relaxed(epittm->base + EPITCR);
>> > + writel_relaxed(val & ~EPITCR_OCIEN, epittm->base + EPITCR);
>> > +}
>> > +
>> > +static inline void epit_irq_enable(struct epit_timer *epittm)
>> > +{
>> > + u32 val;
>> > +
>> > + val = readl_relaxed(epittm->base + EPITCR);
>> > + writel_relaxed(val | EPITCR_OCIEN, epittm->base + EPITCR);
>> > +}
>> > +
>> > +static void epit_irq_acknowledge(struct epit_timer *epittm)
>> > +{
>> > + writel_relaxed(EPITSR_OCIF, epittm->base + EPITSR);
>> > +}
>> > +
>> > +static u64 notrace epit_read_sched_clock(void)
>> > +{
>> > + return ~readl_relaxed(sched_clock_reg);
>> > +}
>> > +
>> > +static int epit_set_next_event(unsigned long cycles,
>> > +struct clock_event_device *ced)
>> > +{
>> > + struct epit_timer *epittm = to_epit_timer(ced);
>> > + unsigned long tcmp;
>> > +
>> > + tcmp = readl_relaxed(epittm->base + EPITCNR) - cycles;
>> > + writel_relaxed(tcmp, epittm->base + EPITCMPR);
>> > +
>> > + return 0;
>> > +}
>> > +
>> > +/* Left event sources disabled, no more interrupts appear */
>> > +static int epit_shutdown(struct clock_event_device *ced)
>> > +{
>> > + struct epit_timer *epittm = to_epit_timer(ced);
>> > + unsigned long flags;
>> > +
>> > + /*
>> > +  * The timer interrupt generation is disabled at least
>> > +  * for enough time to call epit_set_next_event()
>> > +  */
>> > + local_irq_save(flags);
>> > +
>> > + /* Disable interrupt in EPIT module */
>> > + epit_irq_disable(epittm);
>> > +
>> > + /* Clear pending interrupt */
>> > + epit_irq_acknowledge(epittm);
>> > +
>> > + local_irq_restore(flags);
>> > +
>> > + return 0;
>> > +}
>> > +
>> > +static int epit_set_oneshot(struct clock_event_device *ced)
>> > +{
>> > + struct epit_timer *epittm = to_epit_timer(ced);
>> > + unsigned long flags;
>> > +
>> > + /*
>> > +  * The timer interrupt generation is disabled at least
>> > +  * for enough time to call epit_set_next_event()
>> > +  */
>> > + local_irq_save(flags);
>> > +
>> > + /* Disable interrupt in EPIT module */
>> > + epit_irq_disable(epittm);
>> > +
>> > + /* Clear pending interrupt, only while switching mode */
>> > + if (!clockevent_state_oneshot(ced))
>> > + epit_irq_acknowledge(epittm);
>> > +
>> > + /*
>> > +  * Do not put overhead of interrupt enable/disable into
>> > +  * epit_set_next_event(), the core has about 4 minutes
>> > +  * to call epit_set_next_event() or shutdown clock after
>> > +  * mode switching
>> > +  */
>> > + epit_irq_enable(epittm);
>> > + local_irq_restore(flags);
>> > +
>> > + return 0;
>> > +}
>> > +
>> > +static irqreturn_t epit_timer_interrupt(int irq, void *dev_id)
>> > +{
>> > + struct clock_event_device *ced = dev_id;
>> > + struct epit_timer *epittm = to_epit_timer(ced);
>> > +
>> > + epit_irq_acknowledge(epittm);
>> > +
>> > 

Re: [PATCH v6 4/5] clocksource: add driver for i.MX EPIT timer

2018-06-11 Thread Clément Péron
Hi Stefan,


> > +
> > +#define EPITCR   0x00
> > +#define EPITSR   0x04
> > +#define EPITLR   0x08
> > +#define EPITCMPR 0x0c
> > +#define EPITCNR  0x10
> > +
> > +#define EPITCR_ENBIT(0)
> > +#define EPITCR_ENMOD BIT(1)
> > +#define EPITCR_OCIEN BIT(2)
> > +#define EPITCR_RLD   BIT(3)
> > +#define EPITCR_PRESC(x)  (((x) & 0xfff) << 4)
> > +#define EPITCR_SWR   BIT(16)
> > +#define EPITCR_IOVW  BIT(17)
> > +#define EPITCR_DBGEN BIT(18)
> > +#define EPITCR_WAITENBIT(19)
> > +#define EPITCR_RES   BIT(20)
> > +#define EPITCR_STOPENBIT(21)
> > +#define EPITCR_OM_DISCON (0 << 22)
> > +#define EPITCR_OM_TOGGLE (1 << 22)
> > +#define EPITCR_OM_CLEAR  (2 << 22)
> > +#define EPITCR_OM_SET(3 << 22)
> > +#define EPITCR_CLKSRC_OFF(0 << 24)
> > +#define EPITCR_CLKSRC_PERIPHERAL (1 << 24)
> > +#define EPITCR_CLKSRC_REF_HIGH   (2 << 24)
> > +#define EPITCR_CLKSRC_REF_LOW(3 << 24)
> > +
> > +#define EPITSR_OCIF  BIT(0)
> > +
> > +struct epit_timer {
> > + void __iomem *base;
> > + int irq;
> > + struct clk *clk;
> > + struct clock_event_device ced;
> > + struct irqaction act;
> > +};
> > +
> > +static void __iomem *sched_clock_reg;
> > +
> > +static inline struct epit_timer *to_epit_timer(struct clock_event_device 
> > *ced)
> > +{
> > + return container_of(ced, struct epit_timer, ced);
> > +}
> > +
> > +static inline void epit_irq_disable(struct epit_timer *epittm)
> > +{
> > + u32 val;
> > +
> > + val = readl_relaxed(epittm->base + EPITCR);
> > + writel_relaxed(val & ~EPITCR_OCIEN, epittm->base + EPITCR);
> > +}
> > +
> > +static inline void epit_irq_enable(struct epit_timer *epittm)
> > +{
> > + u32 val;
> > +
> > + val = readl_relaxed(epittm->base + EPITCR);
> > + writel_relaxed(val | EPITCR_OCIEN, epittm->base + EPITCR);
> > +}
> > +
> > +static void epit_irq_acknowledge(struct epit_timer *epittm)
> > +{
> > + writel_relaxed(EPITSR_OCIF, epittm->base + EPITSR);
> > +}
> > +
> > +static u64 notrace epit_read_sched_clock(void)
> > +{
> > + return ~readl_relaxed(sched_clock_reg);
> > +}
> > +
> > +static int epit_set_next_event(unsigned long cycles,
> > +struct clock_event_device *ced)
> > +{
> > + struct epit_timer *epittm = to_epit_timer(ced);
> > + unsigned long tcmp;
> > +
> > + tcmp = readl_relaxed(epittm->base + EPITCNR) - cycles;
> > + writel_relaxed(tcmp, epittm->base + EPITCMPR);
> > +
> > + return 0;
> > +}
> > +
> > +/* Left event sources disabled, no more interrupts appear */
> > +static int epit_shutdown(struct clock_event_device *ced)
> > +{
> > + struct epit_timer *epittm = to_epit_timer(ced);
> > + unsigned long flags;
> > +
> > + /*
> > +  * The timer interrupt generation is disabled at least
> > +  * for enough time to call epit_set_next_event()
> > +  */
> > + local_irq_save(flags);
> > +
> > + /* Disable interrupt in EPIT module */
> > + epit_irq_disable(epittm);
> > +
> > + /* Clear pending interrupt */
> > + epit_irq_acknowledge(epittm);
> > +
> > + local_irq_restore(flags);
> > +
> > + return 0;
> > +}
> > +
> > +static int epit_set_oneshot(struct clock_event_device *ced)
> > +{
> > + struct epit_timer *epittm = to_epit_timer(ced);
> > + unsigned long flags;
> > +
> > + /*
> > +  * The timer interrupt generation is disabled at least
> > +  * for enough time to call epit_set_next_event()
> > +  */
> > + local_irq_save(flags);
> > +
> > + /* Disable interrupt in EPIT module */
> > + epit_irq_disable(epittm);
> > +
> > + /* Clear pending interrupt, only while switching mode */
> > + if (!clockevent_state_oneshot(ced))
> > + epit_irq_acknowledge(epittm);
> > +
> > + /*
> > +  * Do not put overhead of interrupt enable/disable into
> > +  * epit_set_next_event(), the core has about 4 minutes
> > +  * to call epit_set_next_event() or shutdown clock after
> > +  * mode switching
> > +  */
> > + epit_irq_enable(epittm);
> > + local_irq_restore(flags);
> > +
> > + return 0;
> > +}
> > +
> > +static irqreturn_t epit_timer_interrupt(int irq, void *dev_id)
> > +{
> > + struct clock_event_device *ced = dev_id;
> > + struct epit_timer *epittm = to_epit_timer(ced);
> > +
> > + epit_irq_acknowledge(epittm);
> > +
> > + ced->event_handler(ced);
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static int __init epit_clocksource_init(struct epit_timer *epittm)
> > +{
> > + unsigned int c = 

Re: [PATCH v6 4/5] clocksource: add driver for i.MX EPIT timer

2018-06-11 Thread Clément Péron
Hi Stefan,


> > +
> > +#define EPITCR   0x00
> > +#define EPITSR   0x04
> > +#define EPITLR   0x08
> > +#define EPITCMPR 0x0c
> > +#define EPITCNR  0x10
> > +
> > +#define EPITCR_ENBIT(0)
> > +#define EPITCR_ENMOD BIT(1)
> > +#define EPITCR_OCIEN BIT(2)
> > +#define EPITCR_RLD   BIT(3)
> > +#define EPITCR_PRESC(x)  (((x) & 0xfff) << 4)
> > +#define EPITCR_SWR   BIT(16)
> > +#define EPITCR_IOVW  BIT(17)
> > +#define EPITCR_DBGEN BIT(18)
> > +#define EPITCR_WAITENBIT(19)
> > +#define EPITCR_RES   BIT(20)
> > +#define EPITCR_STOPENBIT(21)
> > +#define EPITCR_OM_DISCON (0 << 22)
> > +#define EPITCR_OM_TOGGLE (1 << 22)
> > +#define EPITCR_OM_CLEAR  (2 << 22)
> > +#define EPITCR_OM_SET(3 << 22)
> > +#define EPITCR_CLKSRC_OFF(0 << 24)
> > +#define EPITCR_CLKSRC_PERIPHERAL (1 << 24)
> > +#define EPITCR_CLKSRC_REF_HIGH   (2 << 24)
> > +#define EPITCR_CLKSRC_REF_LOW(3 << 24)
> > +
> > +#define EPITSR_OCIF  BIT(0)
> > +
> > +struct epit_timer {
> > + void __iomem *base;
> > + int irq;
> > + struct clk *clk;
> > + struct clock_event_device ced;
> > + struct irqaction act;
> > +};
> > +
> > +static void __iomem *sched_clock_reg;
> > +
> > +static inline struct epit_timer *to_epit_timer(struct clock_event_device 
> > *ced)
> > +{
> > + return container_of(ced, struct epit_timer, ced);
> > +}
> > +
> > +static inline void epit_irq_disable(struct epit_timer *epittm)
> > +{
> > + u32 val;
> > +
> > + val = readl_relaxed(epittm->base + EPITCR);
> > + writel_relaxed(val & ~EPITCR_OCIEN, epittm->base + EPITCR);
> > +}
> > +
> > +static inline void epit_irq_enable(struct epit_timer *epittm)
> > +{
> > + u32 val;
> > +
> > + val = readl_relaxed(epittm->base + EPITCR);
> > + writel_relaxed(val | EPITCR_OCIEN, epittm->base + EPITCR);
> > +}
> > +
> > +static void epit_irq_acknowledge(struct epit_timer *epittm)
> > +{
> > + writel_relaxed(EPITSR_OCIF, epittm->base + EPITSR);
> > +}
> > +
> > +static u64 notrace epit_read_sched_clock(void)
> > +{
> > + return ~readl_relaxed(sched_clock_reg);
> > +}
> > +
> > +static int epit_set_next_event(unsigned long cycles,
> > +struct clock_event_device *ced)
> > +{
> > + struct epit_timer *epittm = to_epit_timer(ced);
> > + unsigned long tcmp;
> > +
> > + tcmp = readl_relaxed(epittm->base + EPITCNR) - cycles;
> > + writel_relaxed(tcmp, epittm->base + EPITCMPR);
> > +
> > + return 0;
> > +}
> > +
> > +/* Left event sources disabled, no more interrupts appear */
> > +static int epit_shutdown(struct clock_event_device *ced)
> > +{
> > + struct epit_timer *epittm = to_epit_timer(ced);
> > + unsigned long flags;
> > +
> > + /*
> > +  * The timer interrupt generation is disabled at least
> > +  * for enough time to call epit_set_next_event()
> > +  */
> > + local_irq_save(flags);
> > +
> > + /* Disable interrupt in EPIT module */
> > + epit_irq_disable(epittm);
> > +
> > + /* Clear pending interrupt */
> > + epit_irq_acknowledge(epittm);
> > +
> > + local_irq_restore(flags);
> > +
> > + return 0;
> > +}
> > +
> > +static int epit_set_oneshot(struct clock_event_device *ced)
> > +{
> > + struct epit_timer *epittm = to_epit_timer(ced);
> > + unsigned long flags;
> > +
> > + /*
> > +  * The timer interrupt generation is disabled at least
> > +  * for enough time to call epit_set_next_event()
> > +  */
> > + local_irq_save(flags);
> > +
> > + /* Disable interrupt in EPIT module */
> > + epit_irq_disable(epittm);
> > +
> > + /* Clear pending interrupt, only while switching mode */
> > + if (!clockevent_state_oneshot(ced))
> > + epit_irq_acknowledge(epittm);
> > +
> > + /*
> > +  * Do not put overhead of interrupt enable/disable into
> > +  * epit_set_next_event(), the core has about 4 minutes
> > +  * to call epit_set_next_event() or shutdown clock after
> > +  * mode switching
> > +  */
> > + epit_irq_enable(epittm);
> > + local_irq_restore(flags);
> > +
> > + return 0;
> > +}
> > +
> > +static irqreturn_t epit_timer_interrupt(int irq, void *dev_id)
> > +{
> > + struct clock_event_device *ced = dev_id;
> > + struct epit_timer *epittm = to_epit_timer(ced);
> > +
> > + epit_irq_acknowledge(epittm);
> > +
> > + ced->event_handler(ced);
> > +
> > + return IRQ_HANDLED;
> > +}
> > +
> > +static int __init epit_clocksource_init(struct epit_timer *epittm)
> > +{
> > + unsigned int c = 

Re: [PATCH v6 4/5] clocksource: add driver for i.MX EPIT timer

2018-06-11 Thread Stefan Agner
On 07.06.2018 16:05, Clément Péron wrote:
> From: Colin Didier 
> 
> Add driver for NXP's EPIT timer used in i.MX SoC.
> 
> Signed-off-by: Colin Didier 
> Signed-off-by: Clément Peron 
> ---
>  drivers/clocksource/Kconfig  |  11 ++
>  drivers/clocksource/Makefile |   1 +
>  drivers/clocksource/timer-imx-epit.c | 265 +++
>  3 files changed, 277 insertions(+)
>  create mode 100644 drivers/clocksource/timer-imx-epit.c
> 
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index 8e8a09755d10..790478afd02c 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -576,6 +576,17 @@ config H8300_TPU
> This enables the clocksource for the H8300 platform with the
> H8S2678 cpu.
>  
> +config CLKSRC_IMX_EPIT
> + bool "Clocksource using i.MX EPIT"
> + depends on CLKDEV_LOOKUP && (ARCH_MXC || COMPILE_TEST)
> + select CLKSRC_MMIO
> + help
> +   This enables EPIT support available on some i.MX platforms.
> +   Normally you don't have a reason to do so as the EPIT has
> +   the same features and uses the same clocks as the GPT.
> +   Anyway, on some systems the GPT may be in use for other
> +   purposes.
> +
>  config CLKSRC_IMX_GPT
>   bool "Clocksource using i.MX GPT" if COMPILE_TEST
>   depends on ARM && CLKDEV_LOOKUP
> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index 00caf37e52f9..d9426f69ec69 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -69,6 +69,7 @@ obj-$(CONFIG_INTEGRATOR_AP_TIMER)   += timer-integrator-ap.o
>  obj-$(CONFIG_CLKSRC_VERSATILE)   += versatile.o
>  obj-$(CONFIG_CLKSRC_MIPS_GIC)+= mips-gic-timer.o
>  obj-$(CONFIG_CLKSRC_TANGO_XTAL)  += tango_xtal.o
> +obj-$(CONFIG_CLKSRC_IMX_EPIT)+= timer-imx-epit.o
>  obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o
>  obj-$(CONFIG_CLKSRC_IMX_TPM) += timer-imx-tpm.o
>  obj-$(CONFIG_ASM9260_TIMER)  += asm9260_timer.o
> diff --git a/drivers/clocksource/timer-imx-epit.c
> b/drivers/clocksource/timer-imx-epit.c
> new file mode 100644
> index ..15f70e210fad
> --- /dev/null
> +++ b/drivers/clocksource/timer-imx-epit.c
> @@ -0,0 +1,265 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * i.MX EPIT Timer
> + *
> + * Copyright (C) 2010 Sascha Hauer 
> + * Copyright (C) 2018 Colin Didier 
> + * Copyright (C) 2018 Clément Péron 
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#define EPITCR   0x00
> +#define EPITSR   0x04
> +#define EPITLR   0x08
> +#define EPITCMPR 0x0c
> +#define EPITCNR  0x10
> +
> +#define EPITCR_ENBIT(0)
> +#define EPITCR_ENMOD BIT(1)
> +#define EPITCR_OCIEN BIT(2)
> +#define EPITCR_RLD   BIT(3)
> +#define EPITCR_PRESC(x)  (((x) & 0xfff) << 4)
> +#define EPITCR_SWR   BIT(16)
> +#define EPITCR_IOVW  BIT(17)
> +#define EPITCR_DBGEN BIT(18)
> +#define EPITCR_WAITENBIT(19)
> +#define EPITCR_RES   BIT(20)
> +#define EPITCR_STOPENBIT(21)
> +#define EPITCR_OM_DISCON (0 << 22)
> +#define EPITCR_OM_TOGGLE (1 << 22)
> +#define EPITCR_OM_CLEAR  (2 << 22)
> +#define EPITCR_OM_SET(3 << 22)
> +#define EPITCR_CLKSRC_OFF(0 << 24)
> +#define EPITCR_CLKSRC_PERIPHERAL (1 << 24)
> +#define EPITCR_CLKSRC_REF_HIGH   (2 << 24)
> +#define EPITCR_CLKSRC_REF_LOW(3 << 24)
> +
> +#define EPITSR_OCIF  BIT(0)
> +
> +struct epit_timer {
> + void __iomem *base;
> + int irq;
> + struct clk *clk;
> + struct clock_event_device ced;
> + struct irqaction act;
> +};
> +
> +static void __iomem *sched_clock_reg;
> +
> +static inline struct epit_timer *to_epit_timer(struct clock_event_device 
> *ced)
> +{
> + return container_of(ced, struct epit_timer, ced);
> +}
> +
> +static inline void epit_irq_disable(struct epit_timer *epittm)
> +{
> + u32 val;
> +
> + val = readl_relaxed(epittm->base + EPITCR);
> + writel_relaxed(val & ~EPITCR_OCIEN, epittm->base + EPITCR);
> +}
> +
> +static inline void epit_irq_enable(struct epit_timer *epittm)
> +{
> + u32 val;
> +
> + val = readl_relaxed(epittm->base + EPITCR);
> + writel_relaxed(val | EPITCR_OCIEN, epittm->base + EPITCR);
> +}
> +
> +static void epit_irq_acknowledge(struct epit_timer *epittm)
> +{
> + writel_relaxed(EPITSR_OCIF, epittm->base + EPITSR);
> +}
> +
> +static u64 notrace epit_read_sched_clock(void)
> +{
> + return ~readl_relaxed(sched_clock_reg);
> +}
> +
> +static 

Re: [PATCH v6 4/5] clocksource: add driver for i.MX EPIT timer

2018-06-11 Thread Stefan Agner
On 07.06.2018 16:05, Clément Péron wrote:
> From: Colin Didier 
> 
> Add driver for NXP's EPIT timer used in i.MX SoC.
> 
> Signed-off-by: Colin Didier 
> Signed-off-by: Clément Peron 
> ---
>  drivers/clocksource/Kconfig  |  11 ++
>  drivers/clocksource/Makefile |   1 +
>  drivers/clocksource/timer-imx-epit.c | 265 +++
>  3 files changed, 277 insertions(+)
>  create mode 100644 drivers/clocksource/timer-imx-epit.c
> 
> diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
> index 8e8a09755d10..790478afd02c 100644
> --- a/drivers/clocksource/Kconfig
> +++ b/drivers/clocksource/Kconfig
> @@ -576,6 +576,17 @@ config H8300_TPU
> This enables the clocksource for the H8300 platform with the
> H8S2678 cpu.
>  
> +config CLKSRC_IMX_EPIT
> + bool "Clocksource using i.MX EPIT"
> + depends on CLKDEV_LOOKUP && (ARCH_MXC || COMPILE_TEST)
> + select CLKSRC_MMIO
> + help
> +   This enables EPIT support available on some i.MX platforms.
> +   Normally you don't have a reason to do so as the EPIT has
> +   the same features and uses the same clocks as the GPT.
> +   Anyway, on some systems the GPT may be in use for other
> +   purposes.
> +
>  config CLKSRC_IMX_GPT
>   bool "Clocksource using i.MX GPT" if COMPILE_TEST
>   depends on ARM && CLKDEV_LOOKUP
> diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
> index 00caf37e52f9..d9426f69ec69 100644
> --- a/drivers/clocksource/Makefile
> +++ b/drivers/clocksource/Makefile
> @@ -69,6 +69,7 @@ obj-$(CONFIG_INTEGRATOR_AP_TIMER)   += timer-integrator-ap.o
>  obj-$(CONFIG_CLKSRC_VERSATILE)   += versatile.o
>  obj-$(CONFIG_CLKSRC_MIPS_GIC)+= mips-gic-timer.o
>  obj-$(CONFIG_CLKSRC_TANGO_XTAL)  += tango_xtal.o
> +obj-$(CONFIG_CLKSRC_IMX_EPIT)+= timer-imx-epit.o
>  obj-$(CONFIG_CLKSRC_IMX_GPT) += timer-imx-gpt.o
>  obj-$(CONFIG_CLKSRC_IMX_TPM) += timer-imx-tpm.o
>  obj-$(CONFIG_ASM9260_TIMER)  += asm9260_timer.o
> diff --git a/drivers/clocksource/timer-imx-epit.c
> b/drivers/clocksource/timer-imx-epit.c
> new file mode 100644
> index ..15f70e210fad
> --- /dev/null
> +++ b/drivers/clocksource/timer-imx-epit.c
> @@ -0,0 +1,265 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/*
> + * i.MX EPIT Timer
> + *
> + * Copyright (C) 2010 Sascha Hauer 
> + * Copyright (C) 2018 Colin Didier 
> + * Copyright (C) 2018 Clément Péron 
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +#define EPITCR   0x00
> +#define EPITSR   0x04
> +#define EPITLR   0x08
> +#define EPITCMPR 0x0c
> +#define EPITCNR  0x10
> +
> +#define EPITCR_ENBIT(0)
> +#define EPITCR_ENMOD BIT(1)
> +#define EPITCR_OCIEN BIT(2)
> +#define EPITCR_RLD   BIT(3)
> +#define EPITCR_PRESC(x)  (((x) & 0xfff) << 4)
> +#define EPITCR_SWR   BIT(16)
> +#define EPITCR_IOVW  BIT(17)
> +#define EPITCR_DBGEN BIT(18)
> +#define EPITCR_WAITENBIT(19)
> +#define EPITCR_RES   BIT(20)
> +#define EPITCR_STOPENBIT(21)
> +#define EPITCR_OM_DISCON (0 << 22)
> +#define EPITCR_OM_TOGGLE (1 << 22)
> +#define EPITCR_OM_CLEAR  (2 << 22)
> +#define EPITCR_OM_SET(3 << 22)
> +#define EPITCR_CLKSRC_OFF(0 << 24)
> +#define EPITCR_CLKSRC_PERIPHERAL (1 << 24)
> +#define EPITCR_CLKSRC_REF_HIGH   (2 << 24)
> +#define EPITCR_CLKSRC_REF_LOW(3 << 24)
> +
> +#define EPITSR_OCIF  BIT(0)
> +
> +struct epit_timer {
> + void __iomem *base;
> + int irq;
> + struct clk *clk;
> + struct clock_event_device ced;
> + struct irqaction act;
> +};
> +
> +static void __iomem *sched_clock_reg;
> +
> +static inline struct epit_timer *to_epit_timer(struct clock_event_device 
> *ced)
> +{
> + return container_of(ced, struct epit_timer, ced);
> +}
> +
> +static inline void epit_irq_disable(struct epit_timer *epittm)
> +{
> + u32 val;
> +
> + val = readl_relaxed(epittm->base + EPITCR);
> + writel_relaxed(val & ~EPITCR_OCIEN, epittm->base + EPITCR);
> +}
> +
> +static inline void epit_irq_enable(struct epit_timer *epittm)
> +{
> + u32 val;
> +
> + val = readl_relaxed(epittm->base + EPITCR);
> + writel_relaxed(val | EPITCR_OCIEN, epittm->base + EPITCR);
> +}
> +
> +static void epit_irq_acknowledge(struct epit_timer *epittm)
> +{
> + writel_relaxed(EPITSR_OCIF, epittm->base + EPITSR);
> +}
> +
> +static u64 notrace epit_read_sched_clock(void)
> +{
> + return ~readl_relaxed(sched_clock_reg);
> +}
> +
> +static 

[PATCH v6 4/5] clocksource: add driver for i.MX EPIT timer

2018-06-07 Thread Clément Péron
From: Colin Didier 

Add driver for NXP's EPIT timer used in i.MX SoC.

Signed-off-by: Colin Didier 
Signed-off-by: Clément Peron 
---
 drivers/clocksource/Kconfig  |  11 ++
 drivers/clocksource/Makefile |   1 +
 drivers/clocksource/timer-imx-epit.c | 265 +++
 3 files changed, 277 insertions(+)
 create mode 100644 drivers/clocksource/timer-imx-epit.c

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 8e8a09755d10..790478afd02c 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -576,6 +576,17 @@ config H8300_TPU
  This enables the clocksource for the H8300 platform with the
  H8S2678 cpu.
 
+config CLKSRC_IMX_EPIT
+   bool "Clocksource using i.MX EPIT"
+   depends on CLKDEV_LOOKUP && (ARCH_MXC || COMPILE_TEST)
+   select CLKSRC_MMIO
+   help
+ This enables EPIT support available on some i.MX platforms.
+ Normally you don't have a reason to do so as the EPIT has
+ the same features and uses the same clocks as the GPT.
+ Anyway, on some systems the GPT may be in use for other
+ purposes.
+
 config CLKSRC_IMX_GPT
bool "Clocksource using i.MX GPT" if COMPILE_TEST
depends on ARM && CLKDEV_LOOKUP
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 00caf37e52f9..d9426f69ec69 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_INTEGRATOR_AP_TIMER) += timer-integrator-ap.o
 obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o
 obj-$(CONFIG_CLKSRC_MIPS_GIC)  += mips-gic-timer.o
 obj-$(CONFIG_CLKSRC_TANGO_XTAL)+= tango_xtal.o
+obj-$(CONFIG_CLKSRC_IMX_EPIT)  += timer-imx-epit.o
 obj-$(CONFIG_CLKSRC_IMX_GPT)   += timer-imx-gpt.o
 obj-$(CONFIG_CLKSRC_IMX_TPM)   += timer-imx-tpm.o
 obj-$(CONFIG_ASM9260_TIMER)+= asm9260_timer.o
diff --git a/drivers/clocksource/timer-imx-epit.c 
b/drivers/clocksource/timer-imx-epit.c
new file mode 100644
index ..15f70e210fad
--- /dev/null
+++ b/drivers/clocksource/timer-imx-epit.c
@@ -0,0 +1,265 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * i.MX EPIT Timer
+ *
+ * Copyright (C) 2010 Sascha Hauer 
+ * Copyright (C) 2018 Colin Didier 
+ * Copyright (C) 2018 Clément Péron 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define EPITCR 0x00
+#define EPITSR 0x04
+#define EPITLR 0x08
+#define EPITCMPR   0x0c
+#define EPITCNR0x10
+
+#define EPITCR_EN  BIT(0)
+#define EPITCR_ENMOD   BIT(1)
+#define EPITCR_OCIEN   BIT(2)
+#define EPITCR_RLD BIT(3)
+#define EPITCR_PRESC(x)(((x) & 0xfff) << 4)
+#define EPITCR_SWR BIT(16)
+#define EPITCR_IOVWBIT(17)
+#define EPITCR_DBGEN   BIT(18)
+#define EPITCR_WAITEN  BIT(19)
+#define EPITCR_RES BIT(20)
+#define EPITCR_STOPEN  BIT(21)
+#define EPITCR_OM_DISCON   (0 << 22)
+#define EPITCR_OM_TOGGLE   (1 << 22)
+#define EPITCR_OM_CLEAR(2 << 22)
+#define EPITCR_OM_SET  (3 << 22)
+#define EPITCR_CLKSRC_OFF  (0 << 24)
+#define EPITCR_CLKSRC_PERIPHERAL   (1 << 24)
+#define EPITCR_CLKSRC_REF_HIGH (2 << 24)
+#define EPITCR_CLKSRC_REF_LOW  (3 << 24)
+
+#define EPITSR_OCIFBIT(0)
+
+struct epit_timer {
+   void __iomem *base;
+   int irq;
+   struct clk *clk;
+   struct clock_event_device ced;
+   struct irqaction act;
+};
+
+static void __iomem *sched_clock_reg;
+
+static inline struct epit_timer *to_epit_timer(struct clock_event_device *ced)
+{
+   return container_of(ced, struct epit_timer, ced);
+}
+
+static inline void epit_irq_disable(struct epit_timer *epittm)
+{
+   u32 val;
+
+   val = readl_relaxed(epittm->base + EPITCR);
+   writel_relaxed(val & ~EPITCR_OCIEN, epittm->base + EPITCR);
+}
+
+static inline void epit_irq_enable(struct epit_timer *epittm)
+{
+   u32 val;
+
+   val = readl_relaxed(epittm->base + EPITCR);
+   writel_relaxed(val | EPITCR_OCIEN, epittm->base + EPITCR);
+}
+
+static void epit_irq_acknowledge(struct epit_timer *epittm)
+{
+   writel_relaxed(EPITSR_OCIF, epittm->base + EPITSR);
+}
+
+static u64 notrace epit_read_sched_clock(void)
+{
+   return ~readl_relaxed(sched_clock_reg);
+}
+
+static int epit_set_next_event(unsigned long cycles,
+  struct clock_event_device *ced)
+{
+   struct epit_timer *epittm = to_epit_timer(ced);
+   unsigned long tcmp;
+
+   tcmp = readl_relaxed(epittm->base + EPITCNR) - cycles;
+   writel_relaxed(tcmp, 

[PATCH v6 4/5] clocksource: add driver for i.MX EPIT timer

2018-06-07 Thread Clément Péron
From: Colin Didier 

Add driver for NXP's EPIT timer used in i.MX SoC.

Signed-off-by: Colin Didier 
Signed-off-by: Clément Peron 
---
 drivers/clocksource/Kconfig  |  11 ++
 drivers/clocksource/Makefile |   1 +
 drivers/clocksource/timer-imx-epit.c | 265 +++
 3 files changed, 277 insertions(+)
 create mode 100644 drivers/clocksource/timer-imx-epit.c

diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 8e8a09755d10..790478afd02c 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -576,6 +576,17 @@ config H8300_TPU
  This enables the clocksource for the H8300 platform with the
  H8S2678 cpu.
 
+config CLKSRC_IMX_EPIT
+   bool "Clocksource using i.MX EPIT"
+   depends on CLKDEV_LOOKUP && (ARCH_MXC || COMPILE_TEST)
+   select CLKSRC_MMIO
+   help
+ This enables EPIT support available on some i.MX platforms.
+ Normally you don't have a reason to do so as the EPIT has
+ the same features and uses the same clocks as the GPT.
+ Anyway, on some systems the GPT may be in use for other
+ purposes.
+
 config CLKSRC_IMX_GPT
bool "Clocksource using i.MX GPT" if COMPILE_TEST
depends on ARM && CLKDEV_LOOKUP
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index 00caf37e52f9..d9426f69ec69 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -69,6 +69,7 @@ obj-$(CONFIG_INTEGRATOR_AP_TIMER) += timer-integrator-ap.o
 obj-$(CONFIG_CLKSRC_VERSATILE) += versatile.o
 obj-$(CONFIG_CLKSRC_MIPS_GIC)  += mips-gic-timer.o
 obj-$(CONFIG_CLKSRC_TANGO_XTAL)+= tango_xtal.o
+obj-$(CONFIG_CLKSRC_IMX_EPIT)  += timer-imx-epit.o
 obj-$(CONFIG_CLKSRC_IMX_GPT)   += timer-imx-gpt.o
 obj-$(CONFIG_CLKSRC_IMX_TPM)   += timer-imx-tpm.o
 obj-$(CONFIG_ASM9260_TIMER)+= asm9260_timer.o
diff --git a/drivers/clocksource/timer-imx-epit.c 
b/drivers/clocksource/timer-imx-epit.c
new file mode 100644
index ..15f70e210fad
--- /dev/null
+++ b/drivers/clocksource/timer-imx-epit.c
@@ -0,0 +1,265 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * i.MX EPIT Timer
+ *
+ * Copyright (C) 2010 Sascha Hauer 
+ * Copyright (C) 2018 Colin Didier 
+ * Copyright (C) 2018 Clément Péron 
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define EPITCR 0x00
+#define EPITSR 0x04
+#define EPITLR 0x08
+#define EPITCMPR   0x0c
+#define EPITCNR0x10
+
+#define EPITCR_EN  BIT(0)
+#define EPITCR_ENMOD   BIT(1)
+#define EPITCR_OCIEN   BIT(2)
+#define EPITCR_RLD BIT(3)
+#define EPITCR_PRESC(x)(((x) & 0xfff) << 4)
+#define EPITCR_SWR BIT(16)
+#define EPITCR_IOVWBIT(17)
+#define EPITCR_DBGEN   BIT(18)
+#define EPITCR_WAITEN  BIT(19)
+#define EPITCR_RES BIT(20)
+#define EPITCR_STOPEN  BIT(21)
+#define EPITCR_OM_DISCON   (0 << 22)
+#define EPITCR_OM_TOGGLE   (1 << 22)
+#define EPITCR_OM_CLEAR(2 << 22)
+#define EPITCR_OM_SET  (3 << 22)
+#define EPITCR_CLKSRC_OFF  (0 << 24)
+#define EPITCR_CLKSRC_PERIPHERAL   (1 << 24)
+#define EPITCR_CLKSRC_REF_HIGH (2 << 24)
+#define EPITCR_CLKSRC_REF_LOW  (3 << 24)
+
+#define EPITSR_OCIFBIT(0)
+
+struct epit_timer {
+   void __iomem *base;
+   int irq;
+   struct clk *clk;
+   struct clock_event_device ced;
+   struct irqaction act;
+};
+
+static void __iomem *sched_clock_reg;
+
+static inline struct epit_timer *to_epit_timer(struct clock_event_device *ced)
+{
+   return container_of(ced, struct epit_timer, ced);
+}
+
+static inline void epit_irq_disable(struct epit_timer *epittm)
+{
+   u32 val;
+
+   val = readl_relaxed(epittm->base + EPITCR);
+   writel_relaxed(val & ~EPITCR_OCIEN, epittm->base + EPITCR);
+}
+
+static inline void epit_irq_enable(struct epit_timer *epittm)
+{
+   u32 val;
+
+   val = readl_relaxed(epittm->base + EPITCR);
+   writel_relaxed(val | EPITCR_OCIEN, epittm->base + EPITCR);
+}
+
+static void epit_irq_acknowledge(struct epit_timer *epittm)
+{
+   writel_relaxed(EPITSR_OCIF, epittm->base + EPITSR);
+}
+
+static u64 notrace epit_read_sched_clock(void)
+{
+   return ~readl_relaxed(sched_clock_reg);
+}
+
+static int epit_set_next_event(unsigned long cycles,
+  struct clock_event_device *ced)
+{
+   struct epit_timer *epittm = to_epit_timer(ced);
+   unsigned long tcmp;
+
+   tcmp = readl_relaxed(epittm->base + EPITCNR) - cycles;
+   writel_relaxed(tcmp,