Message ID | 20190221154458.23763-9-linus.walleij@linaro.org (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | ARM: ixp4xx: Modernize and DT support | expand |
On 21/02/2019 16:44, Linus Walleij wrote: > This augments the IXP4xx to select and use the new > timer driver in drivers/clocksource and removes the old > code in the machine. > > Cc: Daniel Lezcano <daniel.lezcano@linaro.org> > Cc: Thomas Gleixner <tglx@linutronix.de> > Signed-off-by: Linus Walleij <linus.walleij@linaro.org> > --- > Clocksource/timer maintainers: here you see how I activate > this new driver. Intended to be merged through ARM SoC. > --- Acked-by: Daniel Lezcano <daniel.lezcano@linaro.org> > arch/arm/Kconfig | 2 +- > arch/arm/mach-ixp4xx/common.c | 153 +--------------------------------- > 2 files changed, 5 insertions(+), 150 deletions(-) > > diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig > index f6345594cef0..9f70d7e032d6 100644 > --- a/arch/arm/Kconfig > +++ b/arch/arm/Kconfig > @@ -427,7 +427,6 @@ config ARCH_IXP4XX > depends on MMU > select ARCH_HAS_DMA_SET_COHERENT_MASK > select ARCH_SUPPORTS_BIG_ENDIAN > - select CLKSRC_MMIO > select CPU_XSCALE > select DMABOUNCE if PCI > select GENERIC_CLOCKEVENTS > @@ -436,6 +435,7 @@ config ARCH_IXP4XX > select GPIOLIB > select HAVE_PCI > select IXP4XX_IRQ > + select IXP4XX_TIMER > select NEED_MACH_IO_H > select USB_EHCI_BIG_ENDIAN_DESC > select USB_EHCI_BIG_ENDIAN_MMIO > diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c > index 71683dfc48f9..fc4c9b21ca96 100644 > --- a/arch/arm/mach-ixp4xx/common.c > +++ b/arch/arm/mach-ixp4xx/common.c > @@ -22,9 +22,6 @@ > #include <linux/serial_core.h> > #include <linux/interrupt.h> > #include <linux/bitops.h> > -#include <linux/time.h> > -#include <linux/clocksource.h> > -#include <linux/clockchips.h> > #include <linux/io.h> > #include <linux/export.h> > #include <linux/cpu.h> > @@ -32,6 +29,7 @@ > #include <linux/sched_clock.h> > #include <linux/bitops.h> > #include <linux/irqchip/irq-ixp4xx.h> > +#include <linux/platform_data/timer-ixp4xx.h> > #include <mach/udc.h> > #include <mach/hardware.h> > #include <mach/io.h> > @@ -49,19 +47,6 @@ > > #define IXP4XX_TIMER_FREQ 66666000 > > -/* > - * The timer register doesn't allow to specify the two least significant bits of > - * the timeout value and assumes them being zero. So make sure IXP4XX_LATCH is > - * the best value with the two least significant bits unset. > - */ > -#define IXP4XX_LATCH DIV_ROUND_CLOSEST(IXP4XX_TIMER_FREQ, \ > - (IXP4XX_OST_RELOAD_MASK + 1) * HZ) * \ > - (IXP4XX_OST_RELOAD_MASK + 1) > - > -static void __init ixp4xx_clocksource_init(void); > -static void __init ixp4xx_clockevent_init(void); > -static struct clock_event_device clockevent_ixp4xx; > - > /************************************************************************* > * IXP4xx chipset I/O mapping > *************************************************************************/ > @@ -106,37 +91,11 @@ void __init ixp4xx_init_irq(void) > (cpu_is_ixp46x() || cpu_is_ixp43x())); > } > > -/************************************************************************* > - * IXP4xx timer tick > - * We use OS timer1 on the CPU for the timer tick and the timestamp > - * counter as a source of real clock ticks to account for missed jiffies. > - *************************************************************************/ > - > -static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id) > -{ > - struct clock_event_device *evt = dev_id; > - > - /* Clear Pending Interrupt by writing '1' to it */ > - *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; > - > - evt->event_handler(evt); > - > - return IRQ_HANDLED; > -} > - > void __init ixp4xx_timer_init(void) > { > - /* Reset/disable counter */ > - *IXP4XX_OSRT1 = 0; > - > - /* Clear Pending Interrupt by writing '1' to it */ > - *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; > - > - /* Reset time-stamp counter */ > - *IXP4XX_OSTS = 0; > - > - ixp4xx_clocksource_init(); > - ixp4xx_clockevent_init(); > + return ixp4xx_timer_setup(IXP4XX_TIMER_BASE_PHYS, > + IRQ_IXP4XX_TIMER1, > + IXP4XX_TIMER_FREQ); > } > > static struct pxa2xx_udc_mach_info ixp4xx_udc_info; > @@ -251,112 +210,8 @@ void __init ixp4xx_sys_init(void) > ixp4xx_exp_bus_size >> 20); > } > > -/* > - * sched_clock() > - */ > -static u64 notrace ixp4xx_read_sched_clock(void) > -{ > - return *IXP4XX_OSTS; > -} > - > -/* > - * clocksource > - */ > - > -static u64 ixp4xx_clocksource_read(struct clocksource *c) > -{ > - return *IXP4XX_OSTS; > -} > - > unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ; > EXPORT_SYMBOL(ixp4xx_timer_freq); > -static void __init ixp4xx_clocksource_init(void) > -{ > - sched_clock_register(ixp4xx_read_sched_clock, 32, ixp4xx_timer_freq); > - > - clocksource_mmio_init(NULL, "OSTS", ixp4xx_timer_freq, 200, 32, > - ixp4xx_clocksource_read); > -} > - > -/* > - * clockevents > - */ > -static int ixp4xx_set_next_event(unsigned long evt, > - struct clock_event_device *unused) > -{ > - unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK; > - > - *IXP4XX_OSRT1 = (evt & ~IXP4XX_OST_RELOAD_MASK) | opts; > - > - return 0; > -} > - > -static int ixp4xx_shutdown(struct clock_event_device *evt) > -{ > - unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK; > - unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK; > - > - opts &= ~IXP4XX_OST_ENABLE; > - *IXP4XX_OSRT1 = osrt | opts; > - return 0; > -} > - > -static int ixp4xx_set_oneshot(struct clock_event_device *evt) > -{ > - unsigned long opts = IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT; > - unsigned long osrt = 0; > - > - /* period set by 'set next_event' */ > - *IXP4XX_OSRT1 = osrt | opts; > - return 0; > -} > - > -static int ixp4xx_set_periodic(struct clock_event_device *evt) > -{ > - unsigned long opts = IXP4XX_OST_ENABLE; > - unsigned long osrt = IXP4XX_LATCH & ~IXP4XX_OST_RELOAD_MASK; > - > - *IXP4XX_OSRT1 = osrt | opts; > - return 0; > -} > - > -static int ixp4xx_resume(struct clock_event_device *evt) > -{ > - unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK; > - unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK; > - > - opts |= IXP4XX_OST_ENABLE; > - *IXP4XX_OSRT1 = osrt | opts; > - return 0; > -} > - > -static struct clock_event_device clockevent_ixp4xx = { > - .name = "ixp4xx timer1", > - .features = CLOCK_EVT_FEAT_PERIODIC | > - CLOCK_EVT_FEAT_ONESHOT, > - .rating = 200, > - .set_state_shutdown = ixp4xx_shutdown, > - .set_state_periodic = ixp4xx_set_periodic, > - .set_state_oneshot = ixp4xx_set_oneshot, > - .tick_resume = ixp4xx_resume, > - .set_next_event = ixp4xx_set_next_event, > -}; > - > -static void __init ixp4xx_clockevent_init(void) > -{ > - int ret; > - > - clockevent_ixp4xx.cpumask = cpumask_of(0); > - clockevent_ixp4xx.irq = IRQ_IXP4XX_TIMER1; > - ret = request_irq(IRQ_IXP4XX_TIMER1, ixp4xx_timer_interrupt, > - IRQF_TIMER, "IXP4XX-TIMER1", &clockevent_ixp4xx); > - if (ret) { > - pr_crit("no timer IRQ\n"); > - return; > - } > - clockevents_config_and_register(&clockevent_ixp4xx, IXP4XX_TIMER_FREQ, > - 0xf, 0xfffffffe); > -} > > void ixp4xx_restart(enum reboot_mode mode, const char *cmd) > { >
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index f6345594cef0..9f70d7e032d6 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -427,7 +427,6 @@ config ARCH_IXP4XX depends on MMU select ARCH_HAS_DMA_SET_COHERENT_MASK select ARCH_SUPPORTS_BIG_ENDIAN - select CLKSRC_MMIO select CPU_XSCALE select DMABOUNCE if PCI select GENERIC_CLOCKEVENTS @@ -436,6 +435,7 @@ config ARCH_IXP4XX select GPIOLIB select HAVE_PCI select IXP4XX_IRQ + select IXP4XX_TIMER select NEED_MACH_IO_H select USB_EHCI_BIG_ENDIAN_DESC select USB_EHCI_BIG_ENDIAN_MMIO diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index 71683dfc48f9..fc4c9b21ca96 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -22,9 +22,6 @@ #include <linux/serial_core.h> #include <linux/interrupt.h> #include <linux/bitops.h> -#include <linux/time.h> -#include <linux/clocksource.h> -#include <linux/clockchips.h> #include <linux/io.h> #include <linux/export.h> #include <linux/cpu.h> @@ -32,6 +29,7 @@ #include <linux/sched_clock.h> #include <linux/bitops.h> #include <linux/irqchip/irq-ixp4xx.h> +#include <linux/platform_data/timer-ixp4xx.h> #include <mach/udc.h> #include <mach/hardware.h> #include <mach/io.h> @@ -49,19 +47,6 @@ #define IXP4XX_TIMER_FREQ 66666000 -/* - * The timer register doesn't allow to specify the two least significant bits of - * the timeout value and assumes them being zero. So make sure IXP4XX_LATCH is - * the best value with the two least significant bits unset. - */ -#define IXP4XX_LATCH DIV_ROUND_CLOSEST(IXP4XX_TIMER_FREQ, \ - (IXP4XX_OST_RELOAD_MASK + 1) * HZ) * \ - (IXP4XX_OST_RELOAD_MASK + 1) - -static void __init ixp4xx_clocksource_init(void); -static void __init ixp4xx_clockevent_init(void); -static struct clock_event_device clockevent_ixp4xx; - /************************************************************************* * IXP4xx chipset I/O mapping *************************************************************************/ @@ -106,37 +91,11 @@ void __init ixp4xx_init_irq(void) (cpu_is_ixp46x() || cpu_is_ixp43x())); } -/************************************************************************* - * IXP4xx timer tick - * We use OS timer1 on the CPU for the timer tick and the timestamp - * counter as a source of real clock ticks to account for missed jiffies. - *************************************************************************/ - -static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id) -{ - struct clock_event_device *evt = dev_id; - - /* Clear Pending Interrupt by writing '1' to it */ - *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; - - evt->event_handler(evt); - - return IRQ_HANDLED; -} - void __init ixp4xx_timer_init(void) { - /* Reset/disable counter */ - *IXP4XX_OSRT1 = 0; - - /* Clear Pending Interrupt by writing '1' to it */ - *IXP4XX_OSST = IXP4XX_OSST_TIMER_1_PEND; - - /* Reset time-stamp counter */ - *IXP4XX_OSTS = 0; - - ixp4xx_clocksource_init(); - ixp4xx_clockevent_init(); + return ixp4xx_timer_setup(IXP4XX_TIMER_BASE_PHYS, + IRQ_IXP4XX_TIMER1, + IXP4XX_TIMER_FREQ); } static struct pxa2xx_udc_mach_info ixp4xx_udc_info; @@ -251,112 +210,8 @@ void __init ixp4xx_sys_init(void) ixp4xx_exp_bus_size >> 20); } -/* - * sched_clock() - */ -static u64 notrace ixp4xx_read_sched_clock(void) -{ - return *IXP4XX_OSTS; -} - -/* - * clocksource - */ - -static u64 ixp4xx_clocksource_read(struct clocksource *c) -{ - return *IXP4XX_OSTS; -} - unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ; EXPORT_SYMBOL(ixp4xx_timer_freq); -static void __init ixp4xx_clocksource_init(void) -{ - sched_clock_register(ixp4xx_read_sched_clock, 32, ixp4xx_timer_freq); - - clocksource_mmio_init(NULL, "OSTS", ixp4xx_timer_freq, 200, 32, - ixp4xx_clocksource_read); -} - -/* - * clockevents - */ -static int ixp4xx_set_next_event(unsigned long evt, - struct clock_event_device *unused) -{ - unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK; - - *IXP4XX_OSRT1 = (evt & ~IXP4XX_OST_RELOAD_MASK) | opts; - - return 0; -} - -static int ixp4xx_shutdown(struct clock_event_device *evt) -{ - unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK; - unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK; - - opts &= ~IXP4XX_OST_ENABLE; - *IXP4XX_OSRT1 = osrt | opts; - return 0; -} - -static int ixp4xx_set_oneshot(struct clock_event_device *evt) -{ - unsigned long opts = IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT; - unsigned long osrt = 0; - - /* period set by 'set next_event' */ - *IXP4XX_OSRT1 = osrt | opts; - return 0; -} - -static int ixp4xx_set_periodic(struct clock_event_device *evt) -{ - unsigned long opts = IXP4XX_OST_ENABLE; - unsigned long osrt = IXP4XX_LATCH & ~IXP4XX_OST_RELOAD_MASK; - - *IXP4XX_OSRT1 = osrt | opts; - return 0; -} - -static int ixp4xx_resume(struct clock_event_device *evt) -{ - unsigned long opts = *IXP4XX_OSRT1 & IXP4XX_OST_RELOAD_MASK; - unsigned long osrt = *IXP4XX_OSRT1 & ~IXP4XX_OST_RELOAD_MASK; - - opts |= IXP4XX_OST_ENABLE; - *IXP4XX_OSRT1 = osrt | opts; - return 0; -} - -static struct clock_event_device clockevent_ixp4xx = { - .name = "ixp4xx timer1", - .features = CLOCK_EVT_FEAT_PERIODIC | - CLOCK_EVT_FEAT_ONESHOT, - .rating = 200, - .set_state_shutdown = ixp4xx_shutdown, - .set_state_periodic = ixp4xx_set_periodic, - .set_state_oneshot = ixp4xx_set_oneshot, - .tick_resume = ixp4xx_resume, - .set_next_event = ixp4xx_set_next_event, -}; - -static void __init ixp4xx_clockevent_init(void) -{ - int ret; - - clockevent_ixp4xx.cpumask = cpumask_of(0); - clockevent_ixp4xx.irq = IRQ_IXP4XX_TIMER1; - ret = request_irq(IRQ_IXP4XX_TIMER1, ixp4xx_timer_interrupt, - IRQF_TIMER, "IXP4XX-TIMER1", &clockevent_ixp4xx); - if (ret) { - pr_crit("no timer IRQ\n"); - return; - } - clockevents_config_and_register(&clockevent_ixp4xx, IXP4XX_TIMER_FREQ, - 0xf, 0xfffffffe); -} void ixp4xx_restart(enum reboot_mode mode, const char *cmd) {
This augments the IXP4xx to select and use the new timer driver in drivers/clocksource and removes the old code in the machine. Cc: Daniel Lezcano <daniel.lezcano@linaro.org> Cc: Thomas Gleixner <tglx@linutronix.de> Signed-off-by: Linus Walleij <linus.walleij@linaro.org> --- Clocksource/timer maintainers: here you see how I activate this new driver. Intended to be merged through ARM SoC. --- arch/arm/Kconfig | 2 +- arch/arm/mach-ixp4xx/common.c | 153 +--------------------------------- 2 files changed, 5 insertions(+), 150 deletions(-)