Skip to contentSkip to conversation

Consolidate simple ARM MMIO clock sources

PATCH Superseded Russell King - ARM Linux 15 participants 52 messages May 10, 2011 – May 26, 2011

Subsystems (13)

v1 of 2 Superseded Latest is v2 →

lore
Share & tools
lore
#0 lore raw

cover Consolidate simple ARM MMIO clock sources

In a similar light to the i8253 series, this consolidates 17 ARM MMIO counter clocksources into a single common implementation. This common implementation caters for 32-bit and 16-bit register access sizes, up and down counters, and various bit sizes of those counters.

Patch 1 is already in John Stultz tree, but is included for completeness and to get rid of a build warning.

 arch/arm/Kconfig                         |   14 ++++++
 arch/arm/common/timer-sp.c               |   22 +--------
 arch/arm/mach-integrator/Kconfig         |    1 +
 arch/arm/mach-integrator/integrator_ap.c |   21 +-------
 arch/arm/mach-ixp4xx/common.c            |   16 +------
 arch/arm/mach-lpc32xx/timer.c            |   17 +------
 arch/arm/mach-mxs/timer.c                |   20 +++-----
 arch/arm/mach-netx/time.c                |   16 +------
 arch/arm/mach-omap1/time.c               |   69 +++++++++-------------------
 arch/arm/mach-pxa/time.c                 |   17 +------
 arch/arm/mach-sa1100/time.c              |   24 ++--------
 arch/arm/mach-tcc8k/time.c               |   16 +------
 arch/arm/mach-tegra/timer.c              |   16 +------
 arch/arm/mach-u300/timer.c               |   18 +------
 arch/arm/mach-w90x900/time.c             |   17 +------
 arch/arm/plat-mxc/epit.c                 |   18 +-------
 arch/arm/plat-mxc/time.c                 |   38 +++-------------
 arch/arm/plat-nomadik/Kconfig            |    1 +
 arch/arm/plat-nomadik/timer.c            |   31 +------------
 arch/arm/plat-omap/Kconfig               |    1 +
 arch/arm/plat-orion/time.c               |   21 +--------
 arch/arm/plat-s5p/s5p-time.c             |   58 +++++++-----------------
 arch/arm/plat-spear/time.c               |   16 +------
 drivers/Kconfig                          |    3 +
 drivers/clocksource/Kconfig              |    2 +
 drivers/clocksource/Makefile             |    1 +
 drivers/clocksource/mmio.c               |   72 ++++++++++++++++++++++++++++++
 include/linux/clocksource.h              |   10 ++++-
 28 files changed, 194 insertions(+), 382 deletions(-)
#1 lore raw

PATCH 1/13 Make clocksource name const

As nothing should be writing to the clocksource name string, make the clocksource name pointer const. Build-tested on ARM Versatile Express.

Cc Alessandro Rubini <[email protected]>
Cc Colin Cross <[email protected]>
Cc Eric Miao <[email protected]>
Cc Erik Gilling <[email protected]>
Cc "Hans J. Koch" <[email protected]>
Cc Imre Kaloz <[email protected]>
Cc Krzysztof Halasa <[email protected]>
Cc Kukjin Kim <[email protected]>
Cc Lennert Buytenhek <[email protected]>
Cc Linus Walleij <[email protected]>
Cc linux-omap at vger.kernel.org
Cc Nicolas Pitre <[email protected]>
Cc Olof Johansson <[email protected]>
Cc Sascha Hauer <[email protected]>
Cc Tony Lindgren <[email protected]>
Cc Viresh Kumar <[email protected]>
Cc Wan ZongShun <[email protected]>
---
 include/linux/clocksource.h |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)
include/linux/clocksource.h +1 -1
index c37b21a..94c1f38 100644
@@ -161,7 +161,7 @@ struct clocksource {
 	/*
 	 * First part of structure is read mostly
 	 */
-	char *name;
+	const char *name;
 	struct list_head list;
 	int rating;
 	cycle_t (*read)(struct clocksource *cs);
Signature · 1 line
1.7.4.4
#2 lore raw

PATCH 2/13 ARM: s5p: consolidate selection of timer register

In reply to Russell King - ARM Linux

s5p duplicates the runtime selection of the timer register three times. Move this out into a separate function.

FIXME: It is unclear whether this code needs to support true runtime selection of the timer register, or whether it can be selected once at init time.

---
 arch/arm/plat-s5p/s5p-time.c |   58 ++++++++++++-----------------------------
 1 files changed, 17 insertions(+), 41 deletions(-)
arch/arm/plat-s5p/s5p-time.c +17 -41
index 8090403..9052f2a 100644
@@ -290,7 +290,7 @@ static void __init s5p_clockevent_init(void)
 	setup_irq(irq_number, &s5p_clock_event_irq);
 }
 
-static cycle_t s5p_timer_read(struct clocksource *cs)
+static void __iomem *s5p_timer_reg(void)
 {
 	unsigned long offset = 0;
 
@@ -308,10 +308,17 @@ static cycle_t s5p_timer_read(struct clocksource *cs)
 
 	default:
 		printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
-		return 0;
+		return NULL;
 	}
 
-	return (cycle_t) ~__raw_readl(S3C_TIMERREG(offset));
+	return S3C_TIMERREG(offset);
+}
+
+static cycle_t s5p_timer_read(struct clocksource *cs)
+{
+	void __iomem *reg = s5p_timer_reg();
+
+	return (cycle_t) (reg ? ~__raw_readl(reg) : 0);
 }
 
 /*
@@ -325,53 +332,22 @@ static DEFINE_CLOCK_DATA(cd);
 
 unsigned long long notrace sched_clock(void)
 {
-	u32 cyc;
-	unsigned long offset = 0;
-
-	switch (timer_source.source_id) {
-	case S5P_PWM0:
-	case S5P_PWM1:
-	case S5P_PWM2:
-	case S5P_PWM3:
-		offset = (timer_source.source_id * 0x0c) + 0x14;
-		break;
-
-	case S5P_PWM4:
-		offset = 0x40;
-		break;
+	void __iomem *reg = s5p_timer_reg();
 
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
+	if (!reg)
 		return 0;
-	}
 
-	cyc = ~__raw_readl(S3C_TIMERREG(offset));
-	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+	return cyc_to_sched_clock(&cd, ~__raw_readl(reg), (u32)~0);
 }
 
 static void notrace s5p_update_sched_clock(void)
 {
-	u32 cyc;
-	unsigned long offset = 0;
-
-	switch (timer_source.source_id) {
-	case S5P_PWM0:
-	case S5P_PWM1:
-	case S5P_PWM2:
-	case S5P_PWM3:
-		offset = (timer_source.source_id * 0x0c) + 0x14;
-		break;
-
-	case S5P_PWM4:
-		offset = 0x40;
-		break;
+	void __iomem *reg = s5p_timer_reg();
 
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
-	}
+	if (!reg)
+		return 0;
 
-	cyc = ~__raw_readl(S3C_TIMERREG(offset));
-	update_sched_clock(&cd, cyc, (u32)~0);
+	update_sched_clock(&cd, ~__raw_readl(reg), (u32)~0);
 }
 
 struct clocksource time_clocksource = {
Signature · 1 line
1.7.4.4
#3 lore raw

PATCH 2/13 ARM: s5p: consolidate selection of timer register

Quoted 7 lines · Russell King - ARM Linux

s5p duplicates the runtime selection of the timer register three times. Move this out into a separate function.

FIXME: It is unclear whether this code needs to support true runtime selection of the timer register, or whether it can be selected once at init time.

Now, implementation is the latter :)

Quoted 2 lines
Cc Kukjin Kim <[email protected]>

It works fine on SMDKC110 and SMDK6440.
But there is small comment...

Quoted 3 lines
---
 arch/arm/plat-s5p/s5p-time.c |   58

++++++++++++----------------------------

arch/arm/plat-s5p/s5p-time.c static cycle_t s5p_timer_read(struct clocksource

Quoted 17 lines
(quoted diff) +0 -1
-
 1 files changed, 17 insertions(+), 41 deletions(-)
arch/arm/plat-s5p/s5p-time.c +1 -1
index 8090403..9052f2a 100644
@@ -290,7 +290,7 @@ static void __init s5p_clockevent_init(void)
 	setup_irq(irq_number, &s5p_clock_event_irq);
 }
 
-static cycle_t s5p_timer_read(struct clocksource *cs)
+static void __iomem *s5p_timer_reg(void)
 {
 	unsigned long offset = 0;
 
@@ -308,10 +308,17 @@ static cycle_t s5p_timer_read(struct clocksource

*cs)

arch/arm/plat-s5p/s5p-time.c static cycle_t s5p_timer_read(struct clocksource · line 309

Quoted 3 lines
arch/arm/plat-s5p/s5p-time.c +0 -0
 	default:
 		printk(KERN_ERR "Invalid Timer %d\n",

timer_source.source_id);

Quoted 28 lines
arch/arm/plat-s5p/s5p-time.c +9 -10
-		return 0;
+		return NULL;
 	}
 
-	return (cycle_t) ~__raw_readl(S3C_TIMERREG(offset));
+	return S3C_TIMERREG(offset);
+}
+
+static cycle_t s5p_timer_read(struct clocksource *cs)
+{
+	void __iomem *reg = s5p_timer_reg();
+
+	return (cycle_t) (reg ? ~__raw_readl(reg) : 0);
 }
 
 /*
@@ -325,53 +332,22 @@ static DEFINE_CLOCK_DATA(cd);
 
 unsigned long long notrace sched_clock(void)
 {
-	u32 cyc;
-	unsigned long offset = 0;
-
-	switch (timer_source.source_id) {
-	case S5P_PWM0:
-	case S5P_PWM1:
-	case S5P_PWM2:
-	case S5P_PWM3:

arch/arm/plat-s5p/s5p-time.c static DEFINE_CLOCK_DATA(cd); · line 344

Quoted 10 lines
arch/arm/plat-s5p/s5p-time.c +1 -8
-		offset = (timer_source.source_id * 0x0c) + 0x14;
-		break;
-
-	case S5P_PWM4:
-		offset = 0x40;
-		break;
+	void __iomem *reg = s5p_timer_reg();
 
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n",

timer_source.source_id);

Quoted 19 lines
arch/arm/plat-s5p/s5p-time.c +2 -11
+	if (!reg)
 		return 0;
-	}
 
-	cyc = ~__raw_readl(S3C_TIMERREG(offset));
-	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+	return cyc_to_sched_clock(&cd, ~__raw_readl(reg), (u32)~0);
 }
 
 static void notrace s5p_update_sched_clock(void)
 {
-	u32 cyc;
-	unsigned long offset = 0;
-
-	switch (timer_source.source_id) {
-	case S5P_PWM0:
-	case S5P_PWM1:
-	case S5P_PWM2:
-	case S5P_PWM3:

arch/arm/plat-s5p/s5p-time.c static DEFINE_CLOCK_DATA(cd);

Quoted 10 lines
arch/arm/plat-s5p/s5p-time.c +1 -8
-		offset = (timer_source.source_id * 0x0c) + 0x14;
-		break;
-
-	case S5P_PWM4:
-		offset = 0x40;
-		break;
+	void __iomem *reg = s5p_timer_reg();
 
-	default:
-		printk(KERN_ERR "Invalid Timer %d\n",

timer_source.source_id);

arch/arm/plat-s5p/s5p-time.c static DEFINE_CLOCK_DATA(cd); · line 348

Quoted 3 lines
arch/arm/plat-s5p/s5p-time.c +2 -1
-	}
+	if (!reg)
+		return 0;

Should be just 'return;' without a value?

Quoted 9 lines
arch/arm/plat-s5p/s5p-time.c +1 -3
-	cyc = ~__raw_readl(S3C_TIMERREG(offset));
-	update_sched_clock(&cd, cyc, (u32)~0);
+	update_sched_clock(&cd, ~__raw_readl(reg), (u32)~0);
 }
 
 struct clocksource time_clocksource = {
--

1.7.4.4

And will test with your 6th patch soon :)

Thanks.

Best regards,
Kgene.
--
Kukjin Kim <[email protected]>, Senior Engineer, SW Solution Development Team, Samsung Electronics Co., Ltd.

#4 lore raw

PATCH 3/13 ARM: omap1: delete useless interrupt handler

In reply to Russell King - ARM Linux

The OMAP1 clocksource interrupt handler just increments a variable which otherwise isn't used, so this seems to be unnecessary. Tony Lindgren confirms, so lets remove it.

Cc Tony Lindgren <[email protected]>
Cc linux-omap at vger.kernel.org
---
 arch/arm/mach-omap1/time.c |   15 ---------------
 1 files changed, 0 insertions(+), 15 deletions(-)
arch/arm/mach-omap1/time.c +0 -15
index 6885d2f..e2c29b4 100644
@@ -189,20 +189,6 @@ static __init void omap_init_mpu_timer(unsigned long rate)
  * ---------------------------------------------------------------------------
  */
 
-static unsigned long omap_mpu_timer2_overflows;
-
-static irqreturn_t omap_mpu_timer2_interrupt(int irq, void *dev_id)
-{
-	omap_mpu_timer2_overflows++;
-	return IRQ_HANDLED;
-}
-
-static struct irqaction omap_mpu_timer2_irq = {
-	.name		= "mpu_timer2",
-	.flags		= IRQF_DISABLED,
-	.handler	= omap_mpu_timer2_interrupt,
-};
-
 static cycle_t mpu_read(struct clocksource *cs)
 {
 	return ~omap_mpu_timer_read(1);
@@ -247,7 +233,6 @@ static void __init omap_init_clocksource(unsigned long rate)
 	static char err[] __initdata = KERN_ERR
 			"%s: can't register clocksource!\n";
 
-	setup_irq(INT_TIMER2, &omap_mpu_timer2_irq);
 	omap_mpu_timer_start(1, ~0, 1);
 	init_sched_clock(&cd, mpu_update_sched_clock, 32, rate);
 
Signature · 1 line
1.7.4.4
#5 lore raw

PATCH 3/13 ARM: omap1: delete useless interrupt handler

Quoted 7 lines · Russell King - ARM Linux

The OMAP1 clocksource interrupt handler just increments a variable which otherwise isn't used, so this seems to be unnecessary. Tony Lindgren confirms, so lets remove it.

Cc Tony Lindgren <[email protected]>
Cc linux-omap at vger.kernel.org

Yes, this is left over legacy code from an earlier implementation.

reviewer
#6 lore raw

PATCH 3/13 ARM: omap1: delete useless interrupt handler

Quoted 6 lines · Kevin Hilman
Quoted 4 lines · Russell King - ARM Linux

The OMAP1 clocksource interrupt handler just increments a variable which otherwise isn't used, so this seems to be unnecessary. Tony Lindgren confirms, so lets remove it.

Quoted 7 lines
Quoted 3 lines
Cc Tony Lindgren <[email protected]>
Cc linux-omap at vger.kernel.org

Yes, this is left over legacy code from an earlier implementation.

#7 lore raw

PATCH 4/13 ARM: omap1: convert to using readl/writel instead of volatile struct

In reply to Russell King - ARM Linux
Cc Tony Lindgren <[email protected]>
Cc linux-omap at vger.kernel.org
---
 arch/arm/mach-omap1/time.c |   31 ++++++++++++++++---------------
 1 files changed, 16 insertions(+), 15 deletions(-)
arch/arm/mach-omap1/time.c +16 -15
index e2c29b4..e7ab616 100644
@@ -68,49 +68,50 @@ typedef struct {
 } omap_mpu_timer_regs_t;
 
 #define omap_mpu_timer_base(n)							\
-((volatile omap_mpu_timer_regs_t*)OMAP1_IO_ADDRESS(OMAP_MPU_TIMER_BASE +	\
+((omap_mpu_timer_regs_t __iomem *)OMAP1_IO_ADDRESS(OMAP_MPU_TIMER_BASE +	\
 				 (n)*OMAP_MPU_TIMER_OFFSET))
 
 static inline unsigned long notrace omap_mpu_timer_read(int nr)
 {
-	volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
-	return timer->read_tim;
+	omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(nr);
+	return readl(&timer->read_tim);
 }
 
 static inline void omap_mpu_set_autoreset(int nr)
 {
-	volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
+	omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(nr);
 
-	timer->cntl = timer->cntl | MPU_TIMER_AR;
+	writel(readl(&timer->cntl) | MPU_TIMER_AR, &timer->cntl);
 }
 
 static inline void omap_mpu_remove_autoreset(int nr)
 {
-	volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
+	omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(nr);
 
-	timer->cntl = timer->cntl & ~MPU_TIMER_AR;
+	writel(readl(&timer->cntl) & ~MPU_TIMER_AR, &timer->cntl);
 }
 
 static inline void omap_mpu_timer_start(int nr, unsigned long load_val,
 					int autoreset)
 {
-	volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
-	unsigned int timerflags = (MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_ST);
+	omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(nr);
+	unsigned int timerflags = MPU_TIMER_CLOCK_ENABLE | MPU_TIMER_ST;
 
-	if (autoreset) timerflags |= MPU_TIMER_AR;
+	if (autoreset)
+		timerflags |= MPU_TIMER_AR;
 
-	timer->cntl = MPU_TIMER_CLOCK_ENABLE;
+	writel(MPU_TIMER_CLOCK_ENABLE, &timer->cntl);
 	udelay(1);
-	timer->load_tim = load_val;
+	writel(load_val, &timer->load_tim);
         udelay(1);
-	timer->cntl = timerflags;
+	writel(timerflags, &timer->cntl);
 }
 
 static inline void omap_mpu_timer_stop(int nr)
 {
-	volatile omap_mpu_timer_regs_t* timer = omap_mpu_timer_base(nr);
+	omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(nr);
 
-	timer->cntl &= ~MPU_TIMER_ST;
+	writel(readl(&timer->cntl) & ~MPU_TIMER_ST, &timer->cntl);
 }
 
 /*
Signature · 1 line
1.7.4.4
#9 lore raw

PATCH 5/13 ARM: update sa1100 to reflect PXA updates

In reply to Russell King - ARM Linux

Update sa1100 clockevents code to reflect what its later derivative does with clockevents_calc_mult_shift(). Use OSSR_M* constants too.

---
 arch/arm/mach-sa1100/time.c |    8 +++-----
 1 files changed, 3 insertions(+), 5 deletions(-)
arch/arm/mach-sa1100/time.c +3 -5
index ae4f3d8..51c0529 100644
@@ -92,7 +92,6 @@ sa1100_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c)
 static struct clock_event_device ckevt_sa1100_osmr0 = {
 	.name		= "osmr0",
 	.features	= CLOCK_EVT_FEAT_ONESHOT,
-	.shift		= 32,
 	.rating		= 200,
 	.set_next_event	= sa1100_osmr0_set_next_event,
 	.set_mode	= sa1100_osmr0_set_mode,
@@ -120,14 +119,13 @@ static struct irqaction sa1100_timer_irq = {
 
 static void __init sa1100_timer_init(void)
 {
-	OIER = 0;		/* disable any timer interrupts */
-	OSSR = 0xf;		/* clear status on all timers */
+	OIER = 0;
+	OSSR = OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3;
 
 	init_fixed_sched_clock(&cd, sa1100_update_sched_clock, 32,
 			       3686400, SC_MULT, SC_SHIFT);
 
-	ckevt_sa1100_osmr0.mult =
-		div_sc(3686400, NSEC_PER_SEC, ckevt_sa1100_osmr0.shift);
+	clockevents_calc_mult_shift(&ckevt_sa1100_osmr0, 3686400, 4);
 	ckevt_sa1100_osmr0.max_delta_ns =
 		clockevent_delta2ns(0x7fffffff, &ckevt_sa1100_osmr0);
 	ckevt_sa1100_osmr0.min_delta_ns =
Signature · 1 line
1.7.4.4
#10 lore raw

PATCH 6/13 clocksource: add common mmio clocksource

In reply to Russell King - ARM Linux

Add a generic mmio clocksource, covering both 32-bit and 16-bit register access sizes, for up or down counters. This can be used to easily create clocksources for simple counter-based implementations.

Cc Alessandro Rubini <[email protected]>
Cc Colin Cross <[email protected]>
Cc Eric Miao <[email protected]>
Cc Erik Gilling <[email protected]>
Cc "Hans J. Koch" <[email protected]>
Cc Imre Kaloz <[email protected]>
Cc Krzysztof Halasa <[email protected]>
Cc Kukjin Kim <[email protected]>
Cc Lennert Buytenhek <[email protected]>
Cc Linus Walleij <[email protected]>
Cc linux-omap at vger.kernel.org
Cc Nicolas Pitre <[email protected]>
Cc Olof Johansson <[email protected]>
Cc Sascha Hauer <[email protected]>
Cc Tony Lindgren <[email protected]>
Cc Viresh Kumar <[email protected]>
Cc Wan ZongShun <[email protected]>
---
 drivers/Kconfig              |    3 ++
 drivers/clocksource/Kconfig  |    2 +
 drivers/clocksource/Makefile |    1 +
 drivers/clocksource/mmio.c   |   72 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/clocksource.h  |    8 +++++
 5 files changed, 86 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clocksource/Kconfig
 create mode 100644 drivers/clocksource/mmio.c
drivers/Kconfig +3 -0
index 177c7d1..557a469 100644
@@ -119,4 +119,7 @@ source "drivers/platform/Kconfig"
 source "drivers/clk/Kconfig"
 
 source "drivers/hwspinlock/Kconfig"
+
+source "drivers/clocksource/Kconfig"
+
 endmenu
drivers/clocksource/Kconfig new file +2 -0
new file mode 100644
index 0000000..47f37b1
@@ -0,0 +1,2 @@
+config CLKSRC_MMIO
+	bool
drivers/clocksource/Makefile +1 -0
index be61ece..9b2ba29 100644
@@ -6,3 +6,4 @@ obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC)	+= cs5535-clockevt.o
 obj-$(CONFIG_SH_TIMER_CMT)	+= sh_cmt.o
 obj-$(CONFIG_SH_TIMER_MTU2)	+= sh_mtu2.o
 obj-$(CONFIG_SH_TIMER_TMU)	+= sh_tmu.o
+obj-$(CONFIG_CLKSRC_MMIO)	+= mmio.o
drivers/clocksource/mmio.c new file +72 -0

72 lines not on this page · raw message

include/linux/clocksource.h +8 -0
index 94c1f38..a3558fd 100644
@@ -341,4 +341,12 @@ static inline void update_vsyscall_tz(void)
 
 extern void timekeeping_notify(struct clocksource *clock);
 
+extern cycle_t clocksource_mmio_readl_up(struct clocksource *);
+extern cycle_t clocksource_mmio_readl_down(struct clocksource *);
+extern cycle_t clocksource_mmio_readw_up(struct clocksource *);
+extern cycle_t clocksource_mmio_readw_down(struct clocksource *);
+
+extern int clocksource_mmio_init(void __iomem *, const char *,
+	unsigned long, int, unsigned, cycle_t (*)(struct clocksource *));
+
 #endif /* _LINUX_CLOCKSOURCE_H */
Signature · 1 line
1.7.4.4
maintainer
#11 lore raw

PATCH 6/13 clocksource: add common mmio clocksource

Quoted 126 lines · Russell King - ARM Linux

Add a generic mmio clocksource, covering both 32-bit and 16-bit register access sizes, for up or down counters. This can be used to easily create clocksources for simple counter-based implementations.

Cc Alessandro Rubini <[email protected]>
Cc Colin Cross <[email protected]>
Cc Eric Miao <[email protected]>
Cc Erik Gilling <[email protected]>
Cc "Hans J. Koch" <[email protected]>
Cc Imre Kaloz <[email protected]>
Cc Krzysztof Halasa <[email protected]>
Cc Kukjin Kim <[email protected]>
Cc Lennert Buytenhek <[email protected]>
Cc Linus Walleij <[email protected]>
Cc linux-omap at vger.kernel.org
Cc Nicolas Pitre <[email protected]>
Cc Olof Johansson <[email protected]>
Cc Sascha Hauer <[email protected]>
Cc Tony Lindgren <[email protected]>
Cc Viresh Kumar <[email protected]>
Cc Wan ZongShun <[email protected]>
---
 drivers/Kconfig              |    3 ++
 drivers/clocksource/Kconfig  |    2 +
 drivers/clocksource/Makefile |    1 +
 drivers/clocksource/mmio.c   |   72 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/clocksource.h  |    8 +++++
 5 files changed, 86 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clocksource/Kconfig
 create mode 100644 drivers/clocksource/mmio.c
drivers/Kconfig +3 -0
index 177c7d1..557a469 100644
@@ -119,4 +119,7 @@ source "drivers/platform/Kconfig"
 source "drivers/clk/Kconfig"
 
 source "drivers/hwspinlock/Kconfig"
+
+source "drivers/clocksource/Kconfig"
+
 endmenu
drivers/clocksource/Kconfig new file +2 -0
new file mode 100644
index 0000000..47f37b1
@@ -0,0 +1,2 @@
+config CLKSRC_MMIO
+	bool
drivers/clocksource/Makefile +1 -0
index be61ece..9b2ba29 100644
@@ -6,3 +6,4 @@ obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC)	+= cs5535-clockevt.o
 obj-$(CONFIG_SH_TIMER_CMT)	+= sh_cmt.o
 obj-$(CONFIG_SH_TIMER_MTU2)	+= sh_mtu2.o
 obj-$(CONFIG_SH_TIMER_TMU)	+= sh_tmu.o
+obj-$(CONFIG_CLKSRC_MMIO)	+= mmio.o
drivers/clocksource/mmio.c new file +59 -0
new file mode 100644
index 0000000..71ad3a3
@@ -0,0 +1,72 @@
+/*
+ * Generic MMIO clocksource support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/clocksource.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+
+struct clocksource_mmio {
+	void __iomem *reg;
+	struct clocksource clksrc;
+};
+
+static inline struct clocksource_mmio *to_mmio_clksrc(struct clocksource *c)
+{
+	return container_of(c, struct clocksource_mmio, clksrc);
+}
+
+cycle_t clocksource_mmio_readl_up(struct clocksource *c)
+{
+	return readl_relaxed(to_mmio_clksrc(c)->reg);
+}
+
+cycle_t clocksource_mmio_readl_down(struct clocksource *c)
+{
+	return ~readl_relaxed(to_mmio_clksrc(c)->reg);
+}
+
+cycle_t clocksource_mmio_readw_up(struct clocksource *c)
+{
+	return readw_relaxed(to_mmio_clksrc(c)->reg);
+}
+
+cycle_t clocksource_mmio_readw_down(struct clocksource *c)
+{
+	return ~(unsigned)readw_relaxed(to_mmio_clksrc(c)->reg);
+}
+
+/**
+ * clocksource_mmio_init - Initialize a simple mmio based clocksource
+ * @base:	Virtual address of the clock readout register
+ * @name:	Name of the clocksource
+ * @hz:		Frequency of the clocksource in Hz
+ * @rating:	Rating of the clocksource
+ * @bits:	Number of valid bits
+ * @read:	One of clocksource_mmio_read*() above
+ */
+int __init clocksource_mmio_init(void __iomem *base, const char *name,
+	unsigned long hz, int rating, unsigned bits,
+	cycle_t (*read)(struct clocksource *))
+{
+	struct clocksource_mmio *cs;
+
+	if (bits > 32 || bits < 16)
+		return -EINVAL;

drivers/clocksource/mmio.c line 69

Quoted 10 lines
drivers/clocksource/mmio.c new file +10 -0
+
+	cs = kzalloc(sizeof(struct clocksource_mmio), GFP_KERNEL);
+	if (!cs)
+		return -ENOMEM;
+
+	cs->clksrc.name = name;
+	cs->clksrc.rating = rating;
+	cs->clksrc.read = read;
+	cs->clksrc.mask = CLOCKSOURCE_MASK(bits);
+	cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;

You forgot to initialize cs->reg. With this:

(For the i.MX part)

Sascha

Signature · 4 lines
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |
#14 lore raw

PATCH 6/13 clocksource: add common mmio clocksource

In reply to Russell King - ARM Linux
Quoted 9 lines · Russell King - ARM Linux
drivers/clocksource/mmio.c new file +9 -0
+cycle_t clocksource_mmio_readl_up(struct clocksource *c)
+{
+	return readl_relaxed(to_mmio_clksrc(c)->reg);
+}
+
+cycle_t clocksource_mmio_readl_down(struct clocksource *c)
+{
+	return ~readl_relaxed(to_mmio_clksrc(c)->reg);
+}

drivers/clocksource/mmio.c line 41

Quoted 10 lines
drivers/clocksource/mmio.c new file +10 -0
+
+cycle_t clocksource_mmio_readw_up(struct clocksource *c)
+{
+	return readw_relaxed(to_mmio_clksrc(c)->reg);
+}
+
+cycle_t clocksource_mmio_readw_down(struct clocksource *c)
+{
+	return ~(unsigned)readw_relaxed(to_mmio_clksrc(c)->reg);
+}

I probably ought to point out why that cast is there: readw* returns an u16.

u16 will be promoted to 'int' by the compiler, then not'd, and then extended to cycle_t (64-bit). This extension is a signed extension which not only results in more code than required, but also results in a delay slot not being filled.

It's the u16 -> signed int -> cycle_t which causes the signed extension.

u16 -> cycle_t doesn't involve changing the signed-ness of the type, so doesn't suffer.

Neither does readl as it returns a u32 which doesn't need any promotion to an int type.

So, rather than allow the compiler to do automatic promotion to a signed int, the cast is there to ensure that it becomes an unsigned int instead.

#15 lore raw

PATCH 6/13 clocksource: add common mmio clocksource

In reply to Russell King - ARM Linux
Quoted 146 lines · Russell King - ARM Linux

Add a generic mmio clocksource, covering both 32-bit and 16-bit register access sizes, for up or down counters. This can be used to easily create clocksources for simple counter-based implementations.

Cc Alessandro Rubini <[email protected]>
Cc Colin Cross <[email protected]>
Cc Eric Miao <[email protected]>
Cc Erik Gilling <[email protected]>
Cc "Hans J. Koch" <[email protected]>
Cc Imre Kaloz <[email protected]>
Cc Krzysztof Halasa <[email protected]>
Cc Kukjin Kim <[email protected]>
Cc Lennert Buytenhek <[email protected]>
Cc Linus Walleij <[email protected]>
Cc linux-omap at vger.kernel.org
Cc Nicolas Pitre <[email protected]>
Cc Olof Johansson <[email protected]>
Cc Sascha Hauer <[email protected]>
Cc Tony Lindgren <[email protected]>
Cc Viresh Kumar <[email protected]>
Cc Wan ZongShun <[email protected]>
---
 drivers/Kconfig              |    3 ++
 drivers/clocksource/Kconfig  |    2 +
 drivers/clocksource/Makefile |    1 +
 drivers/clocksource/mmio.c   |   72 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/clocksource.h  |    8 +++++
 5 files changed, 86 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clocksource/Kconfig
 create mode 100644 drivers/clocksource/mmio.c
drivers/Kconfig +3 -0
index 177c7d1..557a469 100644
@@ -119,4 +119,7 @@ source "drivers/platform/Kconfig"
 source "drivers/clk/Kconfig"
 
 source "drivers/hwspinlock/Kconfig"
+
+source "drivers/clocksource/Kconfig"
+
 endmenu
drivers/clocksource/Kconfig new file +2 -0
new file mode 100644
index 0000000..47f37b1
@@ -0,0 +1,2 @@
+config CLKSRC_MMIO
+	bool
drivers/clocksource/Makefile +1 -0
index be61ece..9b2ba29 100644
@@ -6,3 +6,4 @@ obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC)	+= cs5535-clockevt.o
 obj-$(CONFIG_SH_TIMER_CMT)	+= sh_cmt.o
 obj-$(CONFIG_SH_TIMER_MTU2)	+= sh_mtu2.o
 obj-$(CONFIG_SH_TIMER_TMU)	+= sh_tmu.o
+obj-$(CONFIG_CLKSRC_MMIO)	+= mmio.o
drivers/clocksource/mmio.c new file +72 -0
new file mode 100644
index 0000000..71ad3a3
@@ -0,0 +1,72 @@
+/*
+ * Generic MMIO clocksource support
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+#include <linux/clocksource.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+
+struct clocksource_mmio {
+	void __iomem *reg;
+	struct clocksource clksrc;
+};
+
+static inline struct clocksource_mmio *to_mmio_clksrc(struct clocksource *c)
+{
+	return container_of(c, struct clocksource_mmio, clksrc);
+}
+
+cycle_t clocksource_mmio_readl_up(struct clocksource *c)
+{
+	return readl_relaxed(to_mmio_clksrc(c)->reg);
+}
+
+cycle_t clocksource_mmio_readl_down(struct clocksource *c)
+{
+	return ~readl_relaxed(to_mmio_clksrc(c)->reg);
+}
+
+cycle_t clocksource_mmio_readw_up(struct clocksource *c)
+{
+	return readw_relaxed(to_mmio_clksrc(c)->reg);
+}
+
+cycle_t clocksource_mmio_readw_down(struct clocksource *c)
+{
+	return ~(unsigned)readw_relaxed(to_mmio_clksrc(c)->reg);
+}
+
+/**
+ * clocksource_mmio_init - Initialize a simple mmio based clocksource
+ * @base:	Virtual address of the clock readout register
+ * @name:	Name of the clocksource
+ * @hz:		Frequency of the clocksource in Hz
+ * @rating:	Rating of the clocksource
+ * @bits:	Number of valid bits
+ * @read:	One of clocksource_mmio_read*() above
+ */
+int __init clocksource_mmio_init(void __iomem *base, const char *name,
+	unsigned long hz, int rating, unsigned bits,
+	cycle_t (*read)(struct clocksource *))
+{
+	struct clocksource_mmio *cs;
+
+	if (bits > 32 || bits < 16)
+		return -EINVAL;
+
+	cs = kzalloc(sizeof(struct clocksource_mmio), GFP_KERNEL);
+	if (!cs)
+		return -ENOMEM;
+
+	cs->clksrc.name = name;
+	cs->clksrc.rating = rating;
+	cs->clksrc.read = read;
+	cs->clksrc.mask = CLOCKSOURCE_MASK(bits);
+	cs->clksrc.flags = CLOCK_SOURCE_IS_CONTINUOUS;
+
+	return clocksource_register_hz(&cs->clksrc, hz);
+}
include/linux/clocksource.h +0 -0
index 94c1f38..a3558fd 100644
@@ -341,4 +341,12 @@ static inline void update_vsyscall_tz(void)
 
 extern void timekeeping_notify(struct clocksource *clock);

include/linux/clocksource.h static inline void update_vsyscall_tz(void) · line 352

Quoted 10 lines
include/linux/clocksource.h +8 -0
 
+extern cycle_t clocksource_mmio_readl_up(struct clocksource *);
+extern cycle_t clocksource_mmio_readl_down(struct clocksource *);
+extern cycle_t clocksource_mmio_readw_up(struct clocksource *);
+extern cycle_t clocksource_mmio_readw_down(struct clocksource *);
+
+extern int clocksource_mmio_init(void __iomem *, const char *,
+	unsigned long, int, unsigned, cycle_t (*)(struct clocksource *));
+
 #endif /* _LINUX_CLOCKSOURCE_H */

With cs->reg initialized,

Signature · 1 line
viresh
#16 lore raw

PATCH v2 6/13 clocksource: add common mmio clocksource

In reply to Russell King - ARM Linux

Add a generic mmio clocksource, covering both 32-bit and 16-bit register access sizes, for up or down counters. This can be used to easily create clocksources for simple counter-based implementations.

Cc Alessandro Rubini <[email protected]>
Cc Colin Cross <[email protected]>
Cc Eric Miao <[email protected]>
Cc Erik Gilling <[email protected]>
Cc Imre Kaloz <[email protected]>
Cc Krzysztof Halasa <[email protected]>
Cc Kukjin Kim <[email protected]>
Cc Lennert Buytenhek <[email protected]>
Cc Linus Walleij <[email protected]>
Cc linux-omap at vger.kernel.org
Cc Nicolas Pitre <[email protected]>
Cc Olof Johansson <[email protected]>
Cc Tony Lindgren <[email protected]>
Cc Wan ZongShun <[email protected]>

---

This is the version with cs->reg initialized.

 drivers/Kconfig              |    3 ++
 drivers/clocksource/Kconfig  |    2 +
 drivers/clocksource/Makefile |    1 +
 drivers/clocksource/mmio.c   |   73 ++++++++++++++++++++++++++++++++++++++++++
 include/linux/clocksource.h  |    8 ++++
 5 files changed, 87 insertions(+), 0 deletions(-)
 create mode 100644 drivers/clocksource/Kconfig
 create mode 100644 drivers/clocksource/mmio.c
drivers/Kconfig +3 -0
index 177c7d1..557a469 100644
@@ -119,4 +119,7 @@ source "drivers/platform/Kconfig"
 source "drivers/clk/Kconfig"
 
 source "drivers/hwspinlock/Kconfig"
+
+source "drivers/clocksource/Kconfig"
+
 endmenu
drivers/clocksource/Kconfig new file +2 -0
new file mode 100644
index 0000000..47f37b1
@@ -0,0 +1,2 @@
+config CLKSRC_MMIO
+	bool
drivers/clocksource/Makefile +1 -0
index be61ece..9b2ba29 100644
@@ -6,3 +6,4 @@ obj-$(CONFIG_CS5535_CLOCK_EVENT_SRC)	+= cs5535-clockevt.o
 obj-$(CONFIG_SH_TIMER_CMT)	+= sh_cmt.o
 obj-$(CONFIG_SH_TIMER_MTU2)	+= sh_mtu2.o
 obj-$(CONFIG_SH_TIMER_TMU)	+= sh_tmu.o
+obj-$(CONFIG_CLKSRC_MMIO)	+= mmio.o
drivers/clocksource/mmio.c new file +73 -0

73 lines not on this page · raw message

include/linux/clocksource.h +8 -0
index 94c1f38..a3558fd 100644
@@ -341,4 +341,12 @@ static inline void update_vsyscall_tz(void)
 
 extern void timekeeping_notify(struct clocksource *clock);
 
+extern cycle_t clocksource_mmio_readl_up(struct clocksource *);
+extern cycle_t clocksource_mmio_readl_down(struct clocksource *);
+extern cycle_t clocksource_mmio_readw_up(struct clocksource *);
+extern cycle_t clocksource_mmio_readw_down(struct clocksource *);
+
+extern int clocksource_mmio_init(void __iomem *, const char *,
+	unsigned long, int, unsigned, cycle_t (*)(struct clocksource *));
+
 #endif /* _LINUX_CLOCKSOURCE_H */
Signature · 1 line
1.7.4.4
#17 lore raw

PATCH 6/13 clocksource: add common mmio clocksource

In reply to Russell King - ARM Linux
Quoted 14 lines · Russell King - ARM Linux

Add a generic mmio clocksource, covering both 32-bit and 16-bit register access sizes, for up or down counters. This can be used to easily create clocksources for simple counter-based implementations.

Cc Alessandro Rubini <[email protected]>
Cc Colin Cross <[email protected]>
Cc Eric Miao <[email protected]>
Cc Erik Gilling <[email protected]>
Cc "Hans J. Koch" <[email protected]>
Cc Imre Kaloz <[email protected]>
Cc Krzysztof Halasa <[email protected]>
Cc Kukjin Kim <[email protected]>
Cc Lennert Buytenhek <[email protected]>
Cc Linus Walleij <[email protected]>
Quoted 8 lines
Cc linux-omap at vger.kernel.org
Cc Nicolas Pitre <[email protected]>
Cc Olof Johansson <[email protected]>
Cc Sascha Hauer <[email protected]>
Cc Tony Lindgren <[email protected]>
Cc Viresh Kumar <[email protected]>
Cc Wan ZongShun <[email protected]>

Please take this through the ARM tree. It's not conflicting with anything in my tree.

#18 lore raw

PATCH 7/13 clocksource: convert ARM 32-bit up counting clocksources

In reply to Russell King - ARM Linux

Convert ixp4xx, lpc32xx, mxc, netx, pxa, sa1100, tcc8k, tegra and u300 to use the generic mmio clocksource recently introduced.

Cc Imre Kaloz <[email protected]>
Cc Krzysztof Halasa <[email protected]>
Cc Eric Miao <[email protected]>
Cc "Hans J. Koch" <[email protected]>
Cc Colin Cross <[email protected]>
Cc Erik Gilling <[email protected]>
Cc Olof Johansson <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Sascha Hauer <[email protected]>
---
 arch/arm/Kconfig              |    9 +++++++++
 arch/arm/mach-ixp4xx/common.c |   16 ++--------------
 arch/arm/mach-lpc32xx/timer.c |   17 +++--------------
 arch/arm/mach-netx/time.c     |   16 ++--------------
 arch/arm/mach-pxa/time.c      |   17 ++---------------
 arch/arm/mach-sa1100/time.c   |   16 ++--------------
 arch/arm/mach-tcc8k/time.c    |   16 ++--------------
 arch/arm/mach-tegra/timer.c   |   16 ++--------------
 arch/arm/mach-u300/timer.c    |   18 +++---------------
 arch/arm/plat-mxc/time.c      |   38 +++++++-------------------------------
 10 files changed, 34 insertions(+), 145 deletions(-)
arch/arm/Kconfig +9 -0
index 377a7a5..9aa5514 100644
@@ -366,6 +366,7 @@ config ARCH_MXC
 	select GENERIC_CLOCKEVENTS
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
 	select HAVE_SCHED_CLOCK
 	help
 	  Support for Freescale MXC/iMX-based family of processors
@@ -390,6 +391,7 @@ config ARCH_STMP3XXX
 
 config ARCH_NETX
 	bool "Hilscher NetX based"
+	select CLKSRC_MMIO
 	select CPU_ARM926T
 	select ARM_VIC
 	select GENERIC_CLOCKEVENTS
@@ -457,6 +459,7 @@ config ARCH_IXP2000
 config ARCH_IXP4XX
 	bool "IXP4xx-based"
 	depends on MMU
+	select CLKSRC_MMIO
 	select CPU_XSCALE
 	select GENERIC_GPIO
 	select GENERIC_CLOCKEVENTS
@@ -497,6 +500,7 @@ config ARCH_LOKI
 
 config ARCH_LPC32XX
 	bool "NXP LPC32XX"
+	select CLKSRC_MMIO
 	select CPU_ARM926T
 	select ARCH_REQUIRE_GPIOLIB
 	select HAVE_IDE
@@ -592,6 +596,7 @@ config ARCH_NUC93X
 config ARCH_TEGRA
 	bool "NVIDIA Tegra"
 	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
 	select GENERIC_TIME
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_GPIO
@@ -617,6 +622,7 @@ config ARCH_PXA
 	select ARCH_MTD_XIP
 	select ARCH_HAS_CPUFREQ
 	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
 	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_CLOCKEVENTS
 	select HAVE_SCHED_CLOCK
@@ -667,6 +673,7 @@ config ARCH_RPC
 
 config ARCH_SA1100
 	bool "SA1100-based"
+	select CLKSRC_MMIO
 	select CPU_SA1100
 	select ISA
 	select ARCH_SPARSEMEM_ENABLE
@@ -803,6 +810,7 @@ config ARCH_SHARK
 
 config ARCH_TCC_926
 	bool "Telechips TCC ARM926-based systems"
+	select CLKSRC_MMIO
 	select CPU_ARM926T
 	select HAVE_CLK
 	select CLKDEV_LOOKUP
@@ -813,6 +821,7 @@ config ARCH_TCC_926
 config ARCH_U300
 	bool "ST-Ericsson U300 Series"
 	depends on MMU
+	select CLKSRC_MMIO
 	select CPU_ARM926T
 	select HAVE_SCHED_CLOCK
 	select HAVE_TCM
arch/arm/mach-ixp4xx/common.c +2 -14
index ed19bc3..74ed81a 100644
@@ -419,26 +419,14 @@ static void notrace ixp4xx_update_sched_clock(void)
 /*
  * clocksource
  */
-static cycle_t ixp4xx_get_cycles(struct clocksource *cs)
-{
-	return *IXP4XX_OSTS;
-}
-
-static struct clocksource clocksource_ixp4xx = {
-	.name 		= "OSTS",
-	.rating		= 200,
-	.read		= ixp4xx_get_cycles,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ;
 EXPORT_SYMBOL(ixp4xx_timer_freq);
 static void __init ixp4xx_clocksource_init(void)
 {
 	init_sched_clock(&cd, ixp4xx_update_sched_clock, 32, ixp4xx_timer_freq);
 
-	clocksource_register_hz(&clocksource_ixp4xx, ixp4xx_timer_freq);
+	clocksource_mmio_init(&IXP4XX_OSTS, "OSTS", ixp4xx_timer_freq, 200, 32,
+			clocksource_mmio_readl_up);
 }
 
 /*
arch/arm/mach-lpc32xx/timer.c +3 -14
index 6162ac3..b42c909 100644
@@ -31,19 +31,6 @@
 #include <mach/platform.h>
 #include "common.h"
 
-static cycle_t lpc32xx_clksrc_read(struct clocksource *cs)
-{
-	return (cycle_t)__raw_readl(LCP32XX_TIMER_TC(LPC32XX_TIMER1_BASE));
-}
-
-static struct clocksource lpc32xx_clksrc = {
-	.name	= "lpc32xx_clksrc",
-	.rating	= 300,
-	.read	= lpc32xx_clksrc_read,
-	.mask	= CLOCKSOURCE_MASK(32),
-	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 static int lpc32xx_clkevt_next_event(unsigned long delta,
     struct clock_event_device *dev)
 {
@@ -170,7 +157,9 @@ static void __init lpc32xx_timer_init(void)
 	__raw_writel(0, LCP32XX_TIMER_MCR(LPC32XX_TIMER1_BASE));
 	__raw_writel(LCP32XX_TIMER_CNTR_TCR_EN,
 		LCP32XX_TIMER_TCR(LPC32XX_TIMER1_BASE));
-	clocksource_register_hz(&lpc32xx_clksrc, clkrate);
+
+	clocksource_mmio_init(LCP32XX_TIMER_TC(LPC32XX_TIMER1_BASE),
+		"lpc32xx_clksrc", clkrate, 300, 32, clocksource_mmio_readl_up);
 }
 
 struct sys_timer lpc32xx_timer = {
arch/arm/mach-netx/time.c +2 -14
index f12f22d..e24c141 100644
@@ -104,19 +104,6 @@ static struct irqaction netx_timer_irq = {
 	.handler	= netx_timer_interrupt,
 };
 
-cycle_t netx_get_cycles(struct clocksource *cs)
-{
-	return readl(NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE));
-}
-
-static struct clocksource clocksource_netx = {
-	.name		= "netx_timer",
-	.rating		= 200,
-	.read		= netx_get_cycles,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 /*
  * Set up timer interrupt
  */
@@ -150,7 +137,8 @@ static void __init netx_timer_init(void)
 	writel(NETX_GPIO_COUNTER_CTRL_RUN,
 			NETX_GPIO_COUNTER_CTRL(TIMER_CLOCKSOURCE));
 
-	clocksource_register_hz(&clocksource_netx, CLOCK_TICK_RATE);
+	clocksource_mmio_init(NETX_GPIO_COUNTER_CURRENT(TIMER_CLOCKSOURCE),
+		"netx_timer", CLOCK_TICK_RATE, 200, 32, clocksource_mmio_readl_up);
 
 	netx_clockevent.mult = div_sc(CLOCK_TICK_RATE, NSEC_PER_SEC,
 			netx_clockevent.shift);
arch/arm/mach-pxa/time.c +2 -15
index 428da3f..de68470 100644
@@ -105,19 +105,6 @@ static struct clock_event_device ckevt_pxa_osmr0 = {
 	.set_mode	= pxa_osmr0_set_mode,
 };
 
-static cycle_t pxa_read_oscr(struct clocksource *cs)
-{
-	return OSCR;
-}
-
-static struct clocksource cksrc_pxa_oscr0 = {
-	.name           = "oscr0",
-	.rating         = 200,
-	.read           = pxa_read_oscr,
-	.mask           = CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 static struct irqaction pxa_ost0_irq = {
 	.name		= "ost0",
 	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
@@ -134,7 +121,6 @@ static void __init pxa_timer_init(void)
 
 	init_sched_clock(&cd, pxa_update_sched_clock, 32, clock_tick_rate);
 
-	clocksource_calc_mult_shift(&cksrc_pxa_oscr0, clock_tick_rate, 4);
 	clockevents_calc_mult_shift(&ckevt_pxa_osmr0, clock_tick_rate, 4);
 	ckevt_pxa_osmr0.max_delta_ns =
 		clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0);
@@ -144,7 +130,8 @@ static void __init pxa_timer_init(void)
 
 	setup_irq(IRQ_OST0, &pxa_ost0_irq);
 
-	clocksource_register_hz(&cksrc_pxa_oscr0, clock_tick_rate);
+	clocksource_mmio_init(&OSCR, "oscr0", clock_tick_rate, 200, 32,
+		clocksource_mmio_readl_up);
 	clockevents_register_device(&ckevt_pxa_osmr0);
 }
 
arch/arm/mach-sa1100/time.c +2 -14
index 51c0529..fa66024 100644
@@ -97,19 +97,6 @@ static struct clock_event_device ckevt_sa1100_osmr0 = {
 	.set_mode	= sa1100_osmr0_set_mode,
 };
 
-static cycle_t sa1100_read_oscr(struct clocksource *s)
-{
-	return OSCR;
-}
-
-static struct clocksource cksrc_sa1100_oscr = {
-	.name		= "oscr",
-	.rating		= 200,
-	.read		= sa1100_read_oscr,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 static struct irqaction sa1100_timer_irq = {
 	.name		= "ost0",
 	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
@@ -134,7 +121,8 @@ static void __init sa1100_timer_init(void)
 
 	setup_irq(IRQ_OST0, &sa1100_timer_irq);
 
-	clocksource_register_hz(&cksrc_sa1100_oscr, CLOCK_TICK_RATE);
+	clocksource_mmio_init(&OSCR, "oscr", CLOCK_TICK_RATE, 200, 32,
+		clocksource_mmio_readl_up);
 	clockevents_register_device(&ckevt_sa1100_osmr0);
 }
 
arch/arm/mach-tcc8k/time.c +2 -14
index e0a8d60..a96babe 100644
@@ -25,19 +25,6 @@
 
 static void __iomem *timer_base;
 
-static cycle_t tcc_get_cycles(struct clocksource *cs)
-{
-	return __raw_readl(timer_base + TC32MCNT_OFFS);
-}
-
-static struct clocksource clocksource_tcc = {
-	.name		= "tcc_tc32",
-	.rating		= 200,
-	.read		= tcc_get_cycles,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 static int tcc_set_next_event(unsigned long evt,
 			      struct clock_event_device *unused)
 {
@@ -102,7 +89,8 @@ static int __init tcc_clockevent_init(struct clk *clock)
 {
 	unsigned int c = clk_get_rate(clock);
 
-	clocksource_register_hz(&clocksource_tcc, c);
+	clocksource_mmio_init(timer_base + TC32MCNT_OFFS, "tcc_tc32", c,
+		200, 32, clocksource_mmio_readl_up);
 
 	clockevent_tcc.mult = div_sc(c, NSEC_PER_SEC,
 					clockevent_tcc.shift);
arch/arm/mach-tegra/timer.c +2 -14
index 0fcb1eb..9035042 100644
@@ -98,11 +98,6 @@ static void tegra_timer_set_mode(enum clock_event_mode mode,
 	}
 }
 
-static cycle_t tegra_clocksource_read(struct clocksource *cs)
-{
-	return timer_readl(TIMERUS_CNTR_1US);
-}
-
 static struct clock_event_device tegra_clockevent = {
 	.name		= "timer0",
 	.rating		= 300,
@@ -111,14 +106,6 @@ static struct clock_event_device tegra_clockevent = {
 	.set_mode	= tegra_timer_set_mode,
 };
 
-static struct clocksource tegra_clocksource = {
-	.name	= "timer_us",
-	.rating	= 300,
-	.read	= tegra_clocksource_read,
-	.mask	= CLOCKSOURCE_MASK(32),
-	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 static DEFINE_CLOCK_DATA(cd);
 
 /*
@@ -234,7 +221,8 @@ static void __init tegra_init_timer(void)
 	init_fixed_sched_clock(&cd, tegra_update_sched_clock, 32,
 			       1000000, SC_MULT, SC_SHIFT);
 
-	if (clocksource_register_hz(&tegra_clocksource, 1000000)) {
+	if (clocksource_mmio_init(timer_reg_base + TIMERUS_CNTR_1US,
+		"timer_us", 1000000, 300, 32, clocksource_mmio_readl_up)) {
 		printk(KERN_ERR "Failed to register clocksource\n");
 		BUG();
 	}
arch/arm/mach-u300/timer.c +3 -15
index 3ec58bd..891cf44 100644
@@ -333,20 +333,6 @@ static struct irqaction u300_timer_irq = {
 	.handler        = u300_timer_interrupt,
 };
 
-/* Use general purpose timer 2 as clock source */
-static cycle_t u300_get_cycles(struct clocksource *cs)
-{
-	return (cycles_t) readl(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC);
-}
-
-static struct clocksource clocksource_u300_1mhz = {
-	.name           = "GPT2",
-	.rating         = 300, /* Reasonably fast and accurate clock source */
-	.read           = u300_get_cycles,
-	.mask           = CLOCKSOURCE_MASK(32), /* 32 bits */
-	.flags          = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 /*
  * Override the global weak sched_clock symbol with this
  * local implementation which uses the clocksource to get some
@@ -422,7 +408,9 @@ static void __init u300_timer_init(void)
 	writel(U300_TIMER_APP_EGPT2_TIMER_ENABLE,
 		U300_TIMER_APP_VBASE + U300_TIMER_APP_EGPT2);
 
-	if (clocksource_register_hz(&clocksource_u300_1mhz, rate))
+	/* Use general purpose timer 2 as clock source */
+	if (clocksource_mmio_init(U300_TIMER_APP_VBASE + U300_TIMER_APP_GPT2CC,
+			"GPT2", rate, 300, 32, clocksource_mmio_readl_up))
 		printk(KERN_ERR "timer: failed to initialize clock "
 		       "source %s\n", clocksource_u300_1mhz.name);
 
arch/arm/plat-mxc/time.c +7 -31
index 2237ff8..e4ac94a 100644
@@ -106,56 +106,32 @@ static void gpt_irq_acknowledge(void)
 		__raw_writel(V2_TSTAT_OF1, timer_base + V2_TSTAT);
 }
 
-static cycle_t dummy_get_cycles(struct clocksource *cs)
-{
-	return 0;
-}
-
-static cycle_t mx1_2_get_cycles(struct clocksource *cs)
-{
-	return __raw_readl(timer_base + MX1_2_TCN);
-}
-
-static cycle_t v2_get_cycles(struct clocksource *cs)
-{
-	return __raw_readl(timer_base + V2_TCN);
-}
-
-static struct clocksource clocksource_mxc = {
-	.name 		= "mxc_timer1",
-	.rating		= 200,
-	.read		= dummy_get_cycles,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
+static void __iomem *sched_clock_reg;
 
 static DEFINE_CLOCK_DATA(cd);
 unsigned long long notrace sched_clock(void)
 {
-	cycle_t cyc = clocksource_mxc.read(&clocksource_mxc);
+	cycle_t cyc = sched_clock_reg ? __raw_readl(sched_clock_reg) : 0;
 
 	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
 }
 
 static void notrace mxc_update_sched_clock(void)
 {
-	cycle_t cyc = clocksource_mxc.read(&clocksource_mxc);
+	cycle_t cyc = sched_clock_reg ? __raw_readl(sched_clock_reg) : 0;
 	update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 static int __init mxc_clocksource_init(struct clk *timer_clk)
 {
 	unsigned int c = clk_get_rate(timer_clk);
+	void __iomem *reg = timer_base + (timer_is_v2() ? V2_TCN : MX1_2_TCN);
 
-	if (timer_is_v2())
-		clocksource_mxc.read = v2_get_cycles;
-	else
-		clocksource_mxc.read = mx1_2_get_cycles;
+	sched_clock_reg = reg;
 
 	init_sched_clock(&cd, mxc_update_sched_clock, 32, c);
-	clocksource_register_hz(&clocksource_mxc, c);
-
-	return 0;
+	return clocksource_mmio_init(reg, "mxc_timer1", c, 200, 32,
+			clocksource_mmio_readl_up);
 }
 
 /* clock event */
Signature · 1 line
1.7.4.4
#19 lore raw

PATCH 7/13 clocksource: convert ARM 32-bit up counting clocksources

2011/5/10 Russell King - ARM Linux <[email protected]>:

Quoted 13 lines

Convert ixp4xx, lpc32xx, mxc, netx, pxa, sa1100, tcc8k, tegra and u300 to use the generic mmio clocksource recently introduced.

Cc Imre Kaloz <[email protected]>
Cc Krzysztof Halasa <[email protected]>
Cc Eric Miao <[email protected]>
Cc "Hans J. Koch" <[email protected]>
Cc Colin Cross <[email protected]>
Cc Erik Gilling <[email protected]>
Cc Olof Johansson <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Sascha Hauer <[email protected]>

Thanks
Linus Walleij

#20 lore raw

PATCH 7/13 clocksource: convert ARM 32-bit up counting clocksources

Quoted 15 lines · Linus Walleij

2011/5/10 Russell King - ARM Linux <[email protected]>:

Quoted 13 lines

Convert ixp4xx, lpc32xx, mxc, netx, pxa, sa1100, tcc8k, tegra and u300 to use the generic mmio clocksource recently introduced.

Cc Imre Kaloz <[email protected]>
Cc Krzysztof Halasa <[email protected]>
Cc Eric Miao <[email protected]>
Cc "Hans J. Koch" <[email protected]>
Cc Colin Cross <[email protected]>
Cc Erik Gilling <[email protected]>
Cc Olof Johansson <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Sascha Hauer <[email protected]>
Quoted 1 line

Does that apply to patch 6 too?

#21 lore raw

PATCH 7/13 clocksource: convert ARM 32-bit up counting clocksources

In reply to Russell King - ARM Linux
Quoted 13 lines · Russell King - ARM Linux

Convert ixp4xx, lpc32xx, mxc, netx, pxa, sa1100, tcc8k, tegra and u300 to use the generic mmio clocksource recently introduced.

Cc Imre Kaloz <[email protected]>
Cc Krzysztof Halasa <[email protected]>
Cc Eric Miao <[email protected]>
Cc "Hans J. Koch" <[email protected]>
Cc Colin Cross <[email protected]>
Cc Erik Gilling <[email protected]>
Cc Olof Johansson <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Sascha Hauer <[email protected]>
#22 lore raw

PATCH 7/13 clocksource: convert ARM 32-bit up counting clocksources

Quoted 15 lines · Hans J. Koch
Quoted 13 lines · Russell King - ARM Linux

Convert ixp4xx, lpc32xx, mxc, netx, pxa, sa1100, tcc8k, tegra and u300 to use the generic mmio clocksource recently introduced.

Cc Imre Kaloz <[email protected]>
Cc Krzysztof Halasa <[email protected]>
Cc Eric Miao <[email protected]>
Cc "Hans J. Koch" <[email protected]>
Cc Colin Cross <[email protected]>
Cc Erik Gilling <[email protected]>
Cc Olof Johansson <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Sascha Hauer <[email protected]>
Quoted 1 line

Does that apply to patch 6 too?

#23 lore raw

PATCH 7/13 clocksource: convert ARM 32-bit up counting clocksources

Quoted 16 lines · Russell King - ARM Linux
Quoted 15 lines · Hans J. Koch
Quoted 13 lines · Russell King - ARM Linux

Convert ixp4xx, lpc32xx, mxc, netx, pxa, sa1100, tcc8k, tegra and u300 to use the generic mmio clocksource recently introduced.

Cc Imre Kaloz <[email protected]>
Cc Krzysztof Halasa <[email protected]>
Cc Eric Miao <[email protected]>
Cc "Hans J. Koch" <[email protected]>
Cc Colin Cross <[email protected]>
Cc Erik Gilling <[email protected]>
Cc Olof Johansson <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Sascha Hauer <[email protected]>
Quoted 3 lines
Quoted 1 line

Does that apply to patch 6 too?

Yes.

Quoted 1 line
#24 lore raw

PATCH 7/13 clocksource: convert ARM 32-bit up counting clocksources

In reply to Russell King - ARM Linux
Quoted 13 lines · Russell King - ARM Linux

Convert ixp4xx, lpc32xx, mxc, netx, pxa, sa1100, tcc8k, tegra and u300 to use the generic mmio clocksource recently introduced.

Cc Imre Kaloz <[email protected]>
Cc Krzysztof Halasa <[email protected]>
Cc Eric Miao <[email protected]>
Cc "Hans J. Koch" <[email protected]>
Cc Colin Cross <[email protected]>
Cc Erik Gilling <[email protected]>
Cc Olof Johansson <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Sascha Hauer <[email protected]>

Boot tested this patch and patch 6 on Tegra.

#25 lore raw

PATCH 7/13 clocksource: convert ARM 32-bit up counting clocksources

In reply to Russell King - ARM Linux

Russell,

Just noticed in the 2.6.40 (aka 3.0) merge window that this doesn't work for big endian ixp, see below.

Quoted 2 lines · Russell King - ARM Linux

Convert ixp4xx, lpc32xx, mxc, netx, pxa, sa1100, tcc8k, tegra and u300 to use the generic mmio clocksource recently introduced.

...

Quoted 21 lines
arch/arm/mach-ixp4xx/common.c +0 -13
index ed19bc3..74ed81a 100644
@@ -419,26 +419,14 @@ static void notrace ixp4xx_update_sched_clock(void)
 /*
  * clocksource
  */
-static cycle_t ixp4xx_get_cycles(struct clocksource *cs)
-{
-	return *IXP4XX_OSTS;
-}
-
-static struct clocksource clocksource_ixp4xx = {
-	.name 		= "OSTS",
-	.rating		= 200,
-	.read		= ixp4xx_get_cycles,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-

arch/arm/mach-ixp4xx/common.c static void notrace ixp4xx_update_sched_clock(void) · line 430

Quoted 10 lines
arch/arm/mach-ixp4xx/common.c +2 -1
 unsigned long ixp4xx_timer_freq = IXP4XX_TIMER_FREQ;
 EXPORT_SYMBOL(ixp4xx_timer_freq);
 static void __init ixp4xx_clocksource_init(void)
 {
 	init_sched_clock(&cd, ixp4xx_update_sched_clock, 32, ixp4xx_timer_freq);
 
-	clocksource_register_hz(&clocksource_ixp4xx, ixp4xx_timer_freq);
+	clocksource_mmio_init(&IXP4XX_OSTS, "OSTS", ixp4xx_timer_freq, 200, 32,
+			clocksource_mmio_readl_up);
 }

This does not compile. I think it should be:

    clocksource_mmio_init( /* delete me - & */ IXP4XX_OSTS, "OSTS", ...)

since IXP4XX_OSTS is

    #define IXP4XX_TIMER_REG(x) ((volatile u32 *)(IXP4XX_TIMER_BASE_VIRT+(x)))
    #define IXP4XX_OSTS         IXP4XX_TIMER_REG(IXP4XX_OSTS_OFFSET)

However, still it doesn't work at run time using a big endian kernel. The clocksource_mmio_readl_up() function uses readl_relaxed() which uses le32_to_cpu(), and mixes up the counter value.

How can I fix this for big endian IXP?

Thanks,

Richard

#26 lore raw

PATCH 8/13 clocksource: convert ARM 32-bit down counting clocksources

In reply to Russell King - ARM Linux

Convert MXC, Nomadik and Orion 32-bit down-counting clocksources to generic mmio clocksource infrastructure.

Cc Sascha Hauer <[email protected]>
Cc Alessandro Rubini <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Lennert Buytenhek <[email protected]>
Cc Nicolas Pitre <[email protected]>
---
 arch/arm/Kconfig              |    2 ++
 arch/arm/common/timer-sp.c    |   22 ++--------------------
 arch/arm/plat-mxc/epit.c      |   18 ++----------------
 arch/arm/plat-nomadik/Kconfig |    1 +
 arch/arm/plat-nomadik/timer.c |   31 +++----------------------------
 arch/arm/plat-orion/time.c    |   21 ++-------------------
 6 files changed, 12 insertions(+), 83 deletions(-)
arch/arm/Kconfig +2 -0
index 9aa5514..0a05a57 100644
@@ -1042,6 +1042,7 @@ config PLAT_IOP
 
 config PLAT_ORION
 	bool
+	select CLKSRC_MMIO
 	select HAVE_SCHED_CLOCK
 
 config PLAT_PXA
@@ -1052,6 +1053,7 @@ config PLAT_VERSATILE
 
 config ARM_TIMER_SP804
 	bool
+	select CLKSRC_MMIO
 
 source arch/arm/mm/Kconfig
 
arch/arm/common/timer-sp.c +2 -20
index 6ef3342..27f7c22 100644
@@ -32,27 +32,8 @@
 #define TIMER_FREQ_KHZ	(1000)
 #define TIMER_RELOAD	(TIMER_FREQ_KHZ * 1000 / HZ)
 
-static void __iomem *clksrc_base;
-
-static cycle_t sp804_read(struct clocksource *cs)
-{
-	return ~readl(clksrc_base + TIMER_VALUE);
-}
-
-static struct clocksource clocksource_sp804 = {
-	.name		= "timer3",
-	.rating		= 200,
-	.read		= sp804_read,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 void __init sp804_clocksource_init(void __iomem *base)
 {
-	struct clocksource *cs = &clocksource_sp804;
-
-	clksrc_base = base;
-
 	/* setup timer 0 as free-running clocksource */
 	writel(0, clksrc_base + TIMER_CTRL);
 	writel(0xffffffff, clksrc_base + TIMER_LOAD);
@@ -60,7 +41,8 @@ void __init sp804_clocksource_init(void __iomem *base)
 	writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
 		clksrc_base + TIMER_CTRL);
 
-	clocksource_register_khz(cs, TIMER_FREQ_KHZ);
+	clocksource_mmio_init(base + TIMER_VALUE, "timer3",
+		TIMER_FREQ_KHZ * 1000, 200, 32, clocksource_mmio_readl_down);
 }
 
 
arch/arm/plat-mxc/epit.c +2 -16
index d69d343..d3467f8 100644
@@ -83,26 +83,12 @@ static void epit_irq_acknowledge(void)
 	__raw_writel(EPITSR_OCIF, timer_base + EPITSR);
 }
 
-static cycle_t epit_read(struct clocksource *cs)
-{
-	return 0 - __raw_readl(timer_base + EPITCNR);
-}
-
-static struct clocksource clocksource_epit = {
-	.name		= "epit",
-	.rating		= 200,
-	.read		= epit_read,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 static int __init epit_clocksource_init(struct clk *timer_clk)
 {
 	unsigned int c = clk_get_rate(timer_clk);
 
-	clocksource_register_hz(&clocksource_epit, c);
-
-	return 0;
+	return clocksource_mmio_init(timer_base + EPITCNR, "epit", c, 200, 32,
+			clocksource_mmio_readl_down);
 }
 
 /* clock event */
arch/arm/plat-nomadik/Kconfig +1 -0
index 187f4e8..18296ee 100644
@@ -5,6 +5,7 @@
 config PLAT_NOMADIK
 	bool
 	depends on ARCH_NOMADIK || ARCH_U8500
+	select CLKSRC_MMIO
 	default y
 	help
 	  Common platform code for Nomadik and other ST-Ericsson
arch/arm/plat-nomadik/timer.c +3 -28
index 4172340..6ec1dea 100644
@@ -26,29 +26,6 @@
 void __iomem *mtu_base; /* Assigned by machine code */
 
 /*
- * Kernel assumes that sched_clock can be called early
- * but the MTU may not yet be initialized.
- */
-static cycle_t nmdk_read_timer_dummy(struct clocksource *cs)
-{
-	return 0;
-}
-
-/* clocksource: MTU decrements, so we negate the value being read. */
-static cycle_t nmdk_read_timer(struct clocksource *cs)
-{
-	return -readl(mtu_base + MTU_VAL(0));
-}
-
-static struct clocksource nmdk_clksrc = {
-	.name		= "mtu_0",
-	.rating		= 200,
-	.read		= nmdk_read_timer_dummy,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-/*
  * Override the global weak sched_clock symbol with this
  * local implementation which uses the clocksource to get some
  * better resolution when scheduling the kernel.
@@ -172,12 +149,10 @@ void __init nmdk_timer_init(void)
 	writel(0, mtu_base + MTU_BGLR(0));
 	writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
 
-	/* Now the clock source is ready */
-	nmdk_clksrc.read = nmdk_read_timer;
-
-	if (clocksource_register_hz(&nmdk_clksrc, rate))
+	if (clocksource_mmio_init(mti_base + MTU_VAL(0), "mtu_0",
+			rate, 200, 32, clocksource_mmio_readl_down))
 		pr_err("timer: failed to initialize clock source %s\n",
-		       nmdk_clksrc.name);
+		       "mtu_0");
 
 	init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate);
 
arch/arm/plat-orion/time.c +2 -19
index 742b032..69a6136 100644
@@ -81,24 +81,6 @@ static void __init setup_sched_clock(unsigned long tclk)
 }
 
 /*
- * Clocksource handling.
- */
-static cycle_t orion_clksrc_read(struct clocksource *cs)
-{
-	return 0xffffffff - readl(timer_base + TIMER0_VAL_OFF);
-}
-
-static struct clocksource orion_clksrc = {
-	.name		= "orion_clocksource",
-	.rating		= 300,
-	.read		= orion_clksrc_read,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-
-
-/*
  * Clockevent handling.
  */
 static int
@@ -247,7 +229,8 @@ orion_time_init(u32 _bridge_base, u32 _bridge_timer1_clr_mask,
 	writel(u & ~BRIDGE_INT_TIMER0, bridge_base + BRIDGE_MASK_OFF);
 	u = readl(timer_base + TIMER_CTRL_OFF);
 	writel(u | TIMER0_EN | TIMER0_RELOAD_EN, timer_base + TIMER_CTRL_OFF);
-	clocksource_register_hz(&orion_clksrc, tclk);
+	clocksource_mmio_init(timer_base + TIMER0_VAL_OFF, "orion_clocksource",
+		tclk, 300, 32, clocksource_mmio_readl_down);
 
 	/*
 	 * Setup clockevent timer (interrupt-driven).
Signature · 1 line
1.7.4.4
#27 lore raw

PATCH 8/13 clocksource: convert ARM 32-bit down counting clocksources

Quoted 2 lines

Convert MXC, Nomadik and Orion 32-bit down-counting clocksources to generic mmio clocksource infrastructure.

Ok, but I think Linusw should ack this as there is the issue of dummy-read used initially, that I really didn't understand.

arch/arm/plat-nomadik/timer.c void __init nmdk_timer_init(void) · line 152

Quoted 1 line
arch/arm/plat-nomadik/timer.c +1 -0
+	if (clocksource_mmio_init(mti_base + MTU_VAL(0), "mtu_0",

Typo. That's "mtu_base", not "mti".

/alessandro

#28 lore raw

PATCH 8/13 clocksource: convert ARM 32-bit down counting clocksources

Quoted 5 lines · Alessandro Rubini
Quoted 2 lines

Convert MXC, Nomadik and Orion 32-bit down-counting clocksources to generic mmio clocksource infrastructure.

Ok, but I think Linusw should ack this as there is the issue of dummy-read used initially, that I really didn't understand.

It was introduced for sched_clock() support - see 2a84751 (ARM: 6107/1:
plat-nomadik: use the MTU clocksrc for sched_clock). That has already been revised so it doesn't use nmdk_clksrc.read - see 8fbb97a (ARM:
6488/1: nomadik: prevent sched_clock() wraparound).

The clocksource isn't registered, and there are no users of nmdk_clksrc.read, so nothing is going to call the dummy read function.

Quoted 3 lines

arch/arm/plat-nomadik/timer.c void __init nmdk_timer_init(void) · line 152

Quoted 1 line
arch/arm/plat-nomadik/timer.c +1 -0
+	if (clocksource_mmio_init(mti_base + MTU_VAL(0), "mtu_0",

Typo. That's "mtu_base", not "mti".

Fixed.

#29 lore raw

PATCH 8/13 clocksource: convert ARM 32-bit down counting clocksources

In reply to Russell King - ARM Linux
Quoted 9 lines · Russell King - ARM Linux

Convert MXC, Nomadik and Orion 32-bit down-counting clocksources to generic mmio clocksource infrastructure.

Cc Sascha Hauer <[email protected]>
Cc Alessandro Rubini <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Lennert Buytenhek <[email protected]>
Cc Nicolas Pitre <[email protected]>
Quoted 208 lines
---
 arch/arm/Kconfig              |    2 ++
 arch/arm/common/timer-sp.c    |   22 ++--------------------
 arch/arm/plat-mxc/epit.c      |   18 ++----------------
 arch/arm/plat-nomadik/Kconfig |    1 +
 arch/arm/plat-nomadik/timer.c |   31 +++----------------------------
 arch/arm/plat-orion/time.c    |   21 ++-------------------
 6 files changed, 12 insertions(+), 83 deletions(-)
arch/arm/Kconfig +2 -0
index 9aa5514..0a05a57 100644
@@ -1042,6 +1042,7 @@ config PLAT_IOP
 
 config PLAT_ORION
 	bool
+	select CLKSRC_MMIO
 	select HAVE_SCHED_CLOCK
 
 config PLAT_PXA
@@ -1052,6 +1053,7 @@ config PLAT_VERSATILE
 
 config ARM_TIMER_SP804
 	bool
+	select CLKSRC_MMIO
 
 source arch/arm/mm/Kconfig
 
arch/arm/common/timer-sp.c +2 -20
index 6ef3342..27f7c22 100644
@@ -32,27 +32,8 @@
 #define TIMER_FREQ_KHZ	(1000)
 #define TIMER_RELOAD	(TIMER_FREQ_KHZ * 1000 / HZ)
 
-static void __iomem *clksrc_base;
-
-static cycle_t sp804_read(struct clocksource *cs)
-{
-	return ~readl(clksrc_base + TIMER_VALUE);
-}
-
-static struct clocksource clocksource_sp804 = {
-	.name		= "timer3",
-	.rating		= 200,
-	.read		= sp804_read,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 void __init sp804_clocksource_init(void __iomem *base)
 {
-	struct clocksource *cs = &clocksource_sp804;
-
-	clksrc_base = base;
-
 	/* setup timer 0 as free-running clocksource */
 	writel(0, clksrc_base + TIMER_CTRL);
 	writel(0xffffffff, clksrc_base + TIMER_LOAD);
@@ -60,7 +41,8 @@ void __init sp804_clocksource_init(void __iomem *base)
 	writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
 		clksrc_base + TIMER_CTRL);
 
-	clocksource_register_khz(cs, TIMER_FREQ_KHZ);
+	clocksource_mmio_init(base + TIMER_VALUE, "timer3",
+		TIMER_FREQ_KHZ * 1000, 200, 32, clocksource_mmio_readl_down);
 }
 
 
arch/arm/plat-mxc/epit.c +2 -16
index d69d343..d3467f8 100644
@@ -83,26 +83,12 @@ static void epit_irq_acknowledge(void)
 	__raw_writel(EPITSR_OCIF, timer_base + EPITSR);
 }
 
-static cycle_t epit_read(struct clocksource *cs)
-{
-	return 0 - __raw_readl(timer_base + EPITCNR);
-}
-
-static struct clocksource clocksource_epit = {
-	.name		= "epit",
-	.rating		= 200,
-	.read		= epit_read,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 static int __init epit_clocksource_init(struct clk *timer_clk)
 {
 	unsigned int c = clk_get_rate(timer_clk);
 
-	clocksource_register_hz(&clocksource_epit, c);
-
-	return 0;
+	return clocksource_mmio_init(timer_base + EPITCNR, "epit", c, 200, 32,
+			clocksource_mmio_readl_down);
 }
 
 /* clock event */
arch/arm/plat-nomadik/Kconfig +1 -0
index 187f4e8..18296ee 100644
@@ -5,6 +5,7 @@
 config PLAT_NOMADIK
 	bool
 	depends on ARCH_NOMADIK || ARCH_U8500
+	select CLKSRC_MMIO
 	default y
 	help
 	  Common platform code for Nomadik and other ST-Ericsson
arch/arm/plat-nomadik/timer.c +3 -28
index 4172340..6ec1dea 100644
@@ -26,29 +26,6 @@
 void __iomem *mtu_base; /* Assigned by machine code */
 
 /*
- * Kernel assumes that sched_clock can be called early
- * but the MTU may not yet be initialized.
- */
-static cycle_t nmdk_read_timer_dummy(struct clocksource *cs)
-{
-	return 0;
-}
-
-/* clocksource: MTU decrements, so we negate the value being read. */
-static cycle_t nmdk_read_timer(struct clocksource *cs)
-{
-	return -readl(mtu_base + MTU_VAL(0));
-}
-
-static struct clocksource nmdk_clksrc = {
-	.name		= "mtu_0",
-	.rating		= 200,
-	.read		= nmdk_read_timer_dummy,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-/*
  * Override the global weak sched_clock symbol with this
  * local implementation which uses the clocksource to get some
  * better resolution when scheduling the kernel.
@@ -172,12 +149,10 @@ void __init nmdk_timer_init(void)
 	writel(0, mtu_base + MTU_BGLR(0));
 	writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
 
-	/* Now the clock source is ready */
-	nmdk_clksrc.read = nmdk_read_timer;
-
-	if (clocksource_register_hz(&nmdk_clksrc, rate))
+	if (clocksource_mmio_init(mti_base + MTU_VAL(0), "mtu_0",
+			rate, 200, 32, clocksource_mmio_readl_down))
 		pr_err("timer: failed to initialize clock source %s\n",
-		       nmdk_clksrc.name);
+		       "mtu_0");
 
 	init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate);
 
arch/arm/plat-orion/time.c +2 -19
index 742b032..69a6136 100644
@@ -81,24 +81,6 @@ static void __init setup_sched_clock(unsigned long tclk)
 }
 
 /*
- * Clocksource handling.
- */
-static cycle_t orion_clksrc_read(struct clocksource *cs)
-{
-	return 0xffffffff - readl(timer_base + TIMER0_VAL_OFF);
-}
-
-static struct clocksource orion_clksrc = {
-	.name		= "orion_clocksource",
-	.rating		= 300,
-	.read		= orion_clksrc_read,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-
-
-/*
  * Clockevent handling.
  */
 static int
@@ -247,7 +229,8 @@ orion_time_init(u32 _bridge_base, u32 _bridge_timer1_clr_mask,
 	writel(u & ~BRIDGE_INT_TIMER0, bridge_base + BRIDGE_MASK_OFF);
 	u = readl(timer_base + TIMER_CTRL_OFF);
 	writel(u | TIMER0_EN | TIMER0_RELOAD_EN, timer_base + TIMER_CTRL_OFF);
-	clocksource_register_hz(&orion_clksrc, tclk);
+	clocksource_mmio_init(timer_base + TIMER0_VAL_OFF, "orion_clocksource",
+		tclk, 300, 32, clocksource_mmio_readl_down);
 
 	/*
 	 * Setup clockevent timer (interrupt-driven).
Signature · 1 line
1.7.4.4
#30 lore raw

PATCH 8/13 clocksource: convert ARM 32-bit down counting clocksources

Quoted 5 lines · Nicolas Pitre
Quoted 3 lines · Russell King - ARM Linux

Convert MXC, Nomadik and Orion 32-bit down-counting clocksources to generic mmio clocksource infrastructure.

Quoted 8 lines
Quoted 6 lines
Cc Sascha Hauer <[email protected]>
Cc Alessandro Rubini <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Lennert Buytenhek <[email protected]>
Cc Nicolas Pitre <[email protected]>

Does that apply to patch 6 too?

#31 lore raw

PATCH 8/13 clocksource: convert ARM 32-bit down counting clocksources

Quoted 13 lines · Russell King - ARM Linux
Quoted 12 lines · Nicolas Pitre
Quoted 9 lines · Russell King - ARM Linux

Convert MXC, Nomadik and Orion 32-bit down-counting clocksources to generic mmio clocksource infrastructure.

Cc Sascha Hauer <[email protected]>
Cc Alessandro Rubini <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Lennert Buytenhek <[email protected]>
Cc Nicolas Pitre <[email protected]>
Quoted 3 lines
Quoted 1 line

Does that apply to patch 6 too?

y
Yes, you can add my ACK to patch 6.

Nicolas

#32 lore raw

PATCH 8/13 clocksource: convert ARM 32-bit down counting clocksources

In reply to Russell King - ARM Linux

2011/5/10 Russell King - ARM Linux <[email protected]>:

Quoted 9 lines

Convert MXC, Nomadik and Orion 32-bit down-counting clocksources to generic mmio clocksource infrastructure.

Cc Sascha Hauer <[email protected]>
Cc Alessandro Rubini <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Lennert Buytenhek <[email protected]>
Cc Nicolas Pitre <[email protected]>

Thanks Russell, excellent.
Linus Walleij

#33 lore raw

PATCH 8/13 clocksource: convert ARM 32-bit down counting clocksources

Quoted 5 lines · Linus Walleij

2011/5/10 Russell King - ARM Linux <[email protected]>:

Quoted 3 lines

Convert MXC, Nomadik and Orion 32-bit down-counting clocksources to generic mmio clocksource infrastructure.

Quoted 8 lines
Quoted 6 lines
Cc Sascha Hauer <[email protected]>
Cc Alessandro Rubini <[email protected]>
Cc Linus Walleij <[email protected]>
Cc Lennert Buytenhek <[email protected]>
Cc Nicolas Pitre <[email protected]>

Does that apply to patch 6 too?

#34 lore raw

PATCH v2 8/13 clocksource: convert ARM 32-bit down counting clocksources

In reply to Russell King - ARM Linux

Convert SP804, MXC, Nomadik and Orion 32-bit down-counting clocksources to generic mmio clocksource infrastructure.

Cc Catalin Marinas <[email protected]>
Cc Sascha Hauer <[email protected]>
Cc Alessandro Rubini <[email protected]>
Cc Lennert Buytenhek <[email protected]>

---

This is v2 of this patch, which adds Catalin to the Cc for timer-sp.c as ARM platforms are impacted by this change, and fixes a build problem with timer-sp.c.

 arch/arm/Kconfig              |    2 ++
 arch/arm/common/timer-sp.c    |   30 ++++++------------------------
 arch/arm/plat-mxc/epit.c      |   18 ++----------------
 arch/arm/plat-nomadik/Kconfig |    1 +
 arch/arm/plat-nomadik/timer.c |   31 +++----------------------------
 arch/arm/plat-orion/time.c    |   21 ++-------------------
 6 files changed, 16 insertions(+), 87 deletions(-)
arch/arm/Kconfig +2 -0
index 9aa5514..0a05a57 100644
@@ -1042,6 +1042,7 @@ config PLAT_IOP
 
 config PLAT_ORION
 	bool
+	select CLKSRC_MMIO
 	select HAVE_SCHED_CLOCK
 
 config PLAT_PXA
@@ -1052,6 +1053,7 @@ config PLAT_VERSATILE
 
 config ARM_TIMER_SP804
 	bool
+	select CLKSRC_MMIO
 
 source arch/arm/mm/Kconfig
 
arch/arm/common/timer-sp.c +6 -24
index 6ef3342..445b05e 100644
@@ -32,35 +32,17 @@
 #define TIMER_FREQ_KHZ	(1000)
 #define TIMER_RELOAD	(TIMER_FREQ_KHZ * 1000 / HZ)
 
-static void __iomem *clksrc_base;
-
-static cycle_t sp804_read(struct clocksource *cs)
-{
-	return ~readl(clksrc_base + TIMER_VALUE);
-}
-
-static struct clocksource clocksource_sp804 = {
-	.name		= "timer3",
-	.rating		= 200,
-	.read		= sp804_read,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 void __init sp804_clocksource_init(void __iomem *base)
 {
-	struct clocksource *cs = &clocksource_sp804;
-
-	clksrc_base = base;
-
 	/* setup timer 0 as free-running clocksource */
-	writel(0, clksrc_base + TIMER_CTRL);
-	writel(0xffffffff, clksrc_base + TIMER_LOAD);
-	writel(0xffffffff, clksrc_base + TIMER_VALUE);
+	writel(0, base + TIMER_CTRL);
+	writel(0xffffffff, base + TIMER_LOAD);
+	writel(0xffffffff, base + TIMER_VALUE);
 	writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
-		clksrc_base + TIMER_CTRL);
+		base + TIMER_CTRL);
 
-	clocksource_register_khz(cs, TIMER_FREQ_KHZ);
+	clocksource_mmio_init(base + TIMER_VALUE, "timer3",
+		TIMER_FREQ_KHZ * 1000, 200, 32, clocksource_mmio_readl_down);
 }
 
 
arch/arm/plat-mxc/epit.c +2 -16
index d69d343..d3467f8 100644
@@ -83,26 +83,12 @@ static void epit_irq_acknowledge(void)
 	__raw_writel(EPITSR_OCIF, timer_base + EPITSR);
 }
 
-static cycle_t epit_read(struct clocksource *cs)
-{
-	return 0 - __raw_readl(timer_base + EPITCNR);
-}
-
-static struct clocksource clocksource_epit = {
-	.name		= "epit",
-	.rating		= 200,
-	.read		= epit_read,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 static int __init epit_clocksource_init(struct clk *timer_clk)
 {
 	unsigned int c = clk_get_rate(timer_clk);
 
-	clocksource_register_hz(&clocksource_epit, c);
-
-	return 0;
+	return clocksource_mmio_init(timer_base + EPITCNR, "epit", c, 200, 32,
+			clocksource_mmio_readl_down);
 }
 
 /* clock event */
arch/arm/plat-nomadik/Kconfig +1 -0
index 187f4e8..18296ee 100644
@@ -5,6 +5,7 @@
 config PLAT_NOMADIK
 	bool
 	depends on ARCH_NOMADIK || ARCH_U8500
+	select CLKSRC_MMIO
 	default y
 	help
 	  Common platform code for Nomadik and other ST-Ericsson
arch/arm/plat-nomadik/timer.c +3 -28
index 4172340..ef74e15 100644
@@ -26,29 +26,6 @@
 void __iomem *mtu_base; /* Assigned by machine code */
 
 /*
- * Kernel assumes that sched_clock can be called early
- * but the MTU may not yet be initialized.
- */
-static cycle_t nmdk_read_timer_dummy(struct clocksource *cs)
-{
-	return 0;
-}
-
-/* clocksource: MTU decrements, so we negate the value being read. */
-static cycle_t nmdk_read_timer(struct clocksource *cs)
-{
-	return -readl(mtu_base + MTU_VAL(0));
-}
-
-static struct clocksource nmdk_clksrc = {
-	.name		= "mtu_0",
-	.rating		= 200,
-	.read		= nmdk_read_timer_dummy,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-/*
  * Override the global weak sched_clock symbol with this
  * local implementation which uses the clocksource to get some
  * better resolution when scheduling the kernel.
@@ -172,12 +149,10 @@ void __init nmdk_timer_init(void)
 	writel(0, mtu_base + MTU_BGLR(0));
 	writel(cr | MTU_CRn_ENA, mtu_base + MTU_CR(0));
 
-	/* Now the clock source is ready */
-	nmdk_clksrc.read = nmdk_read_timer;
-
-	if (clocksource_register_hz(&nmdk_clksrc, rate))
+	if (clocksource_mmio_init(mtu_base + MTU_VAL(0), "mtu_0",
+			rate, 200, 32, clocksource_mmio_readl_down))
 		pr_err("timer: failed to initialize clock source %s\n",
-		       nmdk_clksrc.name);
+		       "mtu_0");
 
 	init_sched_clock(&cd, nomadik_update_sched_clock, 32, rate);
 
arch/arm/plat-orion/time.c +2 -19
index 742b032..69a6136 100644
@@ -81,24 +81,6 @@ static void __init setup_sched_clock(unsigned long tclk)
 }
 
 /*
- * Clocksource handling.
- */
-static cycle_t orion_clksrc_read(struct clocksource *cs)
-{
-	return 0xffffffff - readl(timer_base + TIMER0_VAL_OFF);
-}
-
-static struct clocksource orion_clksrc = {
-	.name		= "orion_clocksource",
-	.rating		= 300,
-	.read		= orion_clksrc_read,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-
-
-/*
  * Clockevent handling.
  */
 static int
@@ -247,7 +229,8 @@ orion_time_init(u32 _bridge_base, u32 _bridge_timer1_clr_mask,
 	writel(u & ~BRIDGE_INT_TIMER0, bridge_base + BRIDGE_MASK_OFF);
 	u = readl(timer_base + TIMER_CTRL_OFF);
 	writel(u | TIMER0_EN | TIMER0_RELOAD_EN, timer_base + TIMER_CTRL_OFF);
-	clocksource_register_hz(&orion_clksrc, tclk);
+	clocksource_mmio_init(timer_base + TIMER0_VAL_OFF, "orion_clocksource",
+		tclk, 300, 32, clocksource_mmio_readl_down);
 
 	/*
 	 * Setup clockevent timer (interrupt-driven).
Signature · 1 line
1.7.4.4
#35 lore raw

PATCH v2 8/13 clocksource: convert ARM 32-bit down counting clocksources

Quoted 10 lines · Russell King - ARM Linux

Convert SP804, MXC, Nomadik and Orion 32-bit down-counting clocksources to generic mmio clocksource infrastructure.

Cc Catalin Marinas <[email protected]>
Cc Sascha Hauer <[email protected]>
Cc Alessandro Rubini <[email protected]>
Cc Lennert Buytenhek <[email protected]>

...

arch/arm/common/timer-sp.c

Quoted 4 lines
arch/arm/common/timer-sp.c +0 -0
index 6ef3342..445b05e 100644
#36 lore raw

PATCH 9/13 clocksource: convert W90x900 24-bit down counting clocksource

In reply to Russell King - ARM Linux

Convert the W90x900 24-bit down-counting clocksource to the generic mmio clocksource infrastructure

---
 arch/arm/Kconfig             |    1 +
 arch/arm/mach-w90x900/time.c |   17 ++---------------
 2 files changed, 3 insertions(+), 15 deletions(-)
arch/arm/Kconfig +1 -0
index 0a05a57..bab25a0 100644
@@ -575,6 +575,7 @@ config ARCH_W90X900
 	select CPU_ARM926T
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
 	select GENERIC_CLOCKEVENTS
 	help
 	  Support for Nuvoton (Winbond logic dept.) ARM9 processor,
arch/arm/mach-w90x900/time.c +2 -15
index 4b089cb..a2c4e2d 100644
@@ -43,7 +43,6 @@
 #define PRESCALE	0x63 /* Divider = prescale + 1 */
 
 #define	TDR_SHIFT	24
-#define	TDR_MASK	((1 << TDR_SHIFT) - 1)
 
 static unsigned int timer0_load;
 
@@ -143,19 +142,6 @@ static void __init nuc900_clockevents_init(void)
 	clockevents_register_device(&nuc900_clockevent_device);
 }
 
-static cycle_t nuc900_get_cycles(struct clocksource *cs)
-{
-	return (~__raw_readl(REG_TDR1)) & TDR_MASK;
-}
-
-static struct clocksource clocksource_nuc900 = {
-	.name	= "nuc900-timer1",
-	.rating	= 200,
-	.read	= nuc900_get_cycles,
-	.mask	= CLOCKSOURCE_MASK(TDR_SHIFT),
-	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 static void __init nuc900_clocksource_init(void)
 {
 	unsigned int val;
@@ -175,7 +161,8 @@ static void __init nuc900_clocksource_init(void)
 	val |= (COUNTEN | PERIOD | PRESCALE);
 	__raw_writel(val, REG_TCSR1);
 
-	clocksource_register_hz(&clocksource_nuc900, rate);
+	clocksource_mmio_init(REG_TDR1, "nuc900-timer1", rate, 200,
+		TDR_SHIFT, clocksource_mmio_readl_down);
 }
 
 static void __init nuc900_timer_init(void)
Signature · 1 line
1.7.4.4
#37 lore raw

PATCH 10/13 clocksource: convert Integrator/AP 16-bit down counting clocksource

In reply to Russell King - ARM Linux

Convert the Integrator/AP 16-bit down-counting clocksource to the generic clocksource infrastructure.

---
 arch/arm/mach-integrator/Kconfig         |    1 +
 arch/arm/mach-integrator/integrator_ap.c |   21 +++------------------
 2 files changed, 4 insertions(+), 18 deletions(-)
arch/arm/mach-integrator/Kconfig +1 -0
index d701d32..dfd18f3 100644
@@ -4,6 +4,7 @@ menu "Integrator Options"
 
 config ARCH_INTEGRATOR_AP
 	bool "Support Integrator/AP and Integrator/PP2 platforms"
+	select CLKSRC_MMIO
 	select MIGHT_HAVE_PCI
 	help
 	  Include support for the ARM(R) Integrator/AP and
arch/arm/mach-integrator/integrator_ap.c +3 -18
index 980803f..9c61acf 100644
@@ -343,25 +343,9 @@ static void __init ap_init(void)
 
 static unsigned long timer_reload;
 
-static void __iomem * const clksrc_base = (void __iomem *)TIMER2_VA_BASE;
-
-static cycle_t timersp_read(struct clocksource *cs)
-{
-	return ~(readl(clksrc_base + TIMER_VALUE) & 0xffff);
-}
-
-static struct clocksource clocksource_timersp = {
-	.name		= "timer2",
-	.rating		= 200,
-	.read		= timersp_read,
-	.mask		= CLOCKSOURCE_MASK(16),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 static void integrator_clocksource_init(u32 khz)
 {
-	struct clocksource *cs = &clocksource_timersp;
-	void __iomem *base = clksrc_base;
+	void __iomem *base = (void __iomem *)TIMER2_VA_BASE;
 	u32 ctrl = TIMER_CTRL_ENABLE;
 
 	if (khz >= 1500) {
@@ -372,7 +356,8 @@ static void integrator_clocksource_init(u32 khz)
 	writel(ctrl, base + TIMER_CTRL);
 	writel(0xffff, base + TIMER_LOAD);
 
-	clocksource_register_khz(cs, khz);
+	clocksource_mmio_init(base + TIMER_VALUE, "timer2",
+		khz * 1000, 200, 16, clocksource_mmio_readl_down);
 }
 
 static void __iomem * const clkevt_base = (void __iomem *)TIMER1_VA_BASE;
Signature · 1 line
1.7.4.4
#38 lore raw

PATCH 11/13 clocksource: convert SPEAr platforms 16-bit up counting clocksource

In reply to Russell King - ARM Linux

Convert SPEAr platforms 16-bit up counting clocksource, which requires a 16-bit register access read rather than 32-bit.

---
 arch/arm/Kconfig           |    1 +
 arch/arm/plat-spear/time.c |   16 ++--------------
 2 files changed, 3 insertions(+), 14 deletions(-)
arch/arm/Kconfig +1 -0
index bab25a0..cbc27fb 100644
@@ -884,6 +884,7 @@ config PLAT_SPEAR
 	select ARM_AMBA
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
 	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
 	help
arch/arm/plat-spear/time.c +2 -14
index dbb6e4f..0c77e42 100644
@@ -70,19 +70,6 @@ static void clockevent_set_mode(enum clock_event_mode mode,
 static int clockevent_next_event(unsigned long evt,
 				 struct clock_event_device *clk_event_dev);
 
-static cycle_t clocksource_read_cycles(struct clocksource *cs)
-{
-	return (cycle_t) readw(gpt_base + COUNT(CLKSRC));
-}
-
-static struct clocksource clksrc = {
-	.name = "tmr1",
-	.rating = 200,		/* its a pretty decent clock */
-	.read = clocksource_read_cycles,
-	.mask = 0xFFFF,		/* 16 bits */
-	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 static void spear_clocksource_init(void)
 {
 	u32 tick_rate;
@@ -103,7 +90,8 @@ static void spear_clocksource_init(void)
 	writew(val, gpt_base + CR(CLKSRC));
 
 	/* register the clocksource */
-	clocksource_register_hz(&clksrc, tick_rate);
+	clocksource_mmio_init(gpt_base + COUNT(CLKSRC), "tmr1", tick_rate,
+		200, 16, clocksource_mmio_readw_up);
 }
 
 static struct clock_event_device clkevt = {
Signature · 1 line
1.7.4.4
#39 lore raw

PATCH 11/13 clocksource: convert SPEAr platforms 16-bit up counting clocksource

Quoted 47 lines · Russell King - ARM Linux

Convert SPEAr platforms 16-bit up counting clocksource, which requires a 16-bit register access read rather than 32-bit.

---
 arch/arm/Kconfig           |    1 +
 arch/arm/plat-spear/time.c |   16 ++--------------
 2 files changed, 3 insertions(+), 14 deletions(-)
arch/arm/Kconfig +1 -0
index bab25a0..cbc27fb 100644
@@ -884,6 +884,7 @@ config PLAT_SPEAR
 	select ARM_AMBA
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
 	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
 	help
arch/arm/plat-spear/time.c +0 -13
index dbb6e4f..0c77e42 100644
@@ -70,19 +70,6 @@ static void clockevent_set_mode(enum clock_event_mode mode,
 static int clockevent_next_event(unsigned long evt,
 				 struct clock_event_device *clk_event_dev);
 
-static cycle_t clocksource_read_cycles(struct clocksource *cs)
-{
-	return (cycle_t) readw(gpt_base + COUNT(CLKSRC));
-}
-
-static struct clocksource clksrc = {
-	.name = "tmr1",
-	.rating = 200,		/* its a pretty decent clock */
-	.read = clocksource_read_cycles,
-	.mask = 0xFFFF,		/* 16 bits */
-	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 static void spear_clocksource_init(void)
 {
 	u32 tick_rate;

arch/arm/plat-spear/time.c static void spear_clocksource_init(void) · line 97

Quoted 9 lines
arch/arm/plat-spear/time.c +2 -1
@@ -103,7 +90,8 @@ static void spear_clocksource_init(void)
 	writew(val, gpt_base + CR(CLKSRC));
 
 	/* register the clocksource */
-	clocksource_register_hz(&clksrc, tick_rate);
+	clocksource_mmio_init(gpt_base + COUNT(CLKSRC), "tmr1", tick_rate,
+		200, 16, clocksource_mmio_readw_up);
 }
 
 static struct clock_event_device clkevt = {
Signature · 1 line
viresh
#41 lore raw

PATCH 11/13 clocksource: convert SPEAr platforms 16-bit up counting clocksource

Quoted 4 lines · Russell King - ARM Linux
Quoted 1 line · viresh kumar

Does that apply to patch 6 too?

No. But i can send a reviewed-by separately.

Signature · 1 line
viresh
#42 lore raw

PATCH 12/13 clocksource: convert MXS timrotv2 to 32-bit down counting clocksource

In reply to Russell King - ARM Linux

Convert the MXS timrotv2 32-bit down counting clocksource to the generic clocksource infrastructure.

---
 arch/arm/Kconfig          |    1 +
 arch/arm/mach-mxs/timer.c |   20 +++++++-------------
 2 files changed, 8 insertions(+), 13 deletions(-)
arch/arm/Kconfig +1 -0
index cbc27fb..43f003a 100644
@@ -376,6 +376,7 @@ config ARCH_MXS
 	select GENERIC_CLOCKEVENTS
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
 	help
 	  Support for Freescale MXS-based family of processors
 
arch/arm/mach-mxs/timer.c +7 -13
index 13647f3..27bebf2 100644
@@ -101,11 +101,6 @@ static cycle_t timrotv1_get_cycles(struct clocksource *cs)
 			& 0xffff0000) >> 16);
 }
 
-static cycle_t timrotv2_get_cycles(struct clocksource *cs)
-{
-	return ~__raw_readl(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1));
-}
-
 static int timrotv1_set_next_event(unsigned long evt,
 					struct clock_event_device *dev)
 {
@@ -230,8 +225,8 @@ static int __init mxs_clockevent_init(struct clk *timer_clk)
 static struct clocksource clocksource_mxs = {
 	.name		= "mxs_timer",
 	.rating		= 200,
-	.read		= timrotv2_get_cycles,
-	.mask		= CLOCKSOURCE_MASK(32),
+	.read		= timrotv1_get_cycles,
+	.mask		= CLOCKSOURCE_MASK(16),
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -239,12 +234,11 @@ static int __init mxs_clocksource_init(struct clk *timer_clk)
 {
 	unsigned int c = clk_get_rate(timer_clk);
 
-	if (timrot_is_v1()) {
-		clocksource_mxs.read = timrotv1_get_cycles;
-		clocksource_mxs.mask = CLOCKSOURCE_MASK(16);
-	}
-
-	clocksource_register_hz(&clocksource_mxs, c);
+	if (timrot_is_v1())
+		clocksource_register_hz(&clocksource_mxs, c);
+	else
+		clocksource_mmio_init(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1)),
+			"mxs_timer", c, 200, 32, clocksource_mmio_readl_down);
 
 	return 0;
 }
Signature · 1 line
1.7.4.4
#43 lore raw

PATCH 12/13 clocksource: convert MXS timrotv2 to 32-bit down counting clocksource

Quoted 53 lines · Russell King - ARM Linux

Convert the MXS timrotv2 32-bit down counting clocksource to the generic clocksource infrastructure.

---
 arch/arm/Kconfig          |    1 +
 arch/arm/mach-mxs/timer.c |   20 +++++++-------------
 2 files changed, 8 insertions(+), 13 deletions(-)
arch/arm/Kconfig +1 -0
index cbc27fb..43f003a 100644
@@ -376,6 +376,7 @@ config ARCH_MXS
 	select GENERIC_CLOCKEVENTS
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
 	help
 	  Support for Freescale MXS-based family of processors
 
arch/arm/mach-mxs/timer.c +2 -7
index 13647f3..27bebf2 100644
@@ -101,11 +101,6 @@ static cycle_t timrotv1_get_cycles(struct clocksource *cs)
 			& 0xffff0000) >> 16);
 }
 
-static cycle_t timrotv2_get_cycles(struct clocksource *cs)
-{
-	return ~__raw_readl(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1));
-}
-
 static int timrotv1_set_next_event(unsigned long evt,
 					struct clock_event_device *dev)
 {
@@ -230,8 +225,8 @@ static int __init mxs_clockevent_init(struct clk *timer_clk)
 static struct clocksource clocksource_mxs = {
 	.name		= "mxs_timer",
 	.rating		= 200,
-	.read		= timrotv2_get_cycles,
-	.mask		= CLOCKSOURCE_MASK(32),
+	.read		= timrotv1_get_cycles,
+	.mask		= CLOCKSOURCE_MASK(16),
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -239,12 +234,11 @@ static int __init mxs_clocksource_init(struct clk *timer_clk)
 {
 	unsigned int c = clk_get_rate(timer_clk);
 

arch/arm/mach-mxs/timer.c static int __init mxs_clocksource_init(struct clk *timer_clk) · line 240

Quoted 10 lines
arch/arm/mach-mxs/timer.c +4 -6
-	if (timrot_is_v1()) {
-		clocksource_mxs.read = timrotv1_get_cycles;
-		clocksource_mxs.mask = CLOCKSOURCE_MASK(16);
-	}
-
-	clocksource_register_hz(&clocksource_mxs, c);
+	if (timrot_is_v1())
+		clocksource_register_hz(&clocksource_mxs, c);
+	else
+		clocksource_mmio_init(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1)),
                                                                                   ^

Mismatched parenthesis

Quoted 4 lines
arch/arm/mach-mxs/timer.c +1 -0
+			"mxs_timer", c, 200, 32, clocksource_mmio_readl_down);
 
 	return 0;
 }
Signature · 2 lines
Regards,
Shawn
#44 lore raw

PATCH 12/13 clocksource: convert MXS timrotv2 to 32-bit down counting clocksource

Quoted 65 lines · Shawn Guo
Quoted 53 lines · Russell King - ARM Linux

Convert the MXS timrotv2 32-bit down counting clocksource to the generic clocksource infrastructure.

---
 arch/arm/Kconfig          |    1 +
 arch/arm/mach-mxs/timer.c |   20 +++++++-------------
 2 files changed, 8 insertions(+), 13 deletions(-)
arch/arm/Kconfig +1 -0
index cbc27fb..43f003a 100644
@@ -376,6 +376,7 @@ config ARCH_MXS
 	select GENERIC_CLOCKEVENTS
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
 	help
 	  Support for Freescale MXS-based family of processors
 
arch/arm/mach-mxs/timer.c +2 -7
index 13647f3..27bebf2 100644
@@ -101,11 +101,6 @@ static cycle_t timrotv1_get_cycles(struct clocksource *cs)
 			& 0xffff0000) >> 16);
 }
 
-static cycle_t timrotv2_get_cycles(struct clocksource *cs)
-{
-	return ~__raw_readl(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1));
-}
-
 static int timrotv1_set_next_event(unsigned long evt,
 					struct clock_event_device *dev)
 {
@@ -230,8 +225,8 @@ static int __init mxs_clockevent_init(struct clk *timer_clk)
 static struct clocksource clocksource_mxs = {
 	.name		= "mxs_timer",
 	.rating		= 200,
-	.read		= timrotv2_get_cycles,
-	.mask		= CLOCKSOURCE_MASK(32),
+	.read		= timrotv1_get_cycles,
+	.mask		= CLOCKSOURCE_MASK(16),
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
@@ -239,12 +234,11 @@ static int __init mxs_clocksource_init(struct clk *timer_clk)
 {
 	unsigned int c = clk_get_rate(timer_clk);
 

arch/arm/mach-mxs/timer.c static int __init mxs_clocksource_init(struct clk *timer_clk) · line 240

Quoted 10 lines
arch/arm/mach-mxs/timer.c +4 -6
-	if (timrot_is_v1()) {
-		clocksource_mxs.read = timrotv1_get_cycles;
-		clocksource_mxs.mask = CLOCKSOURCE_MASK(16);
-	}
-
-	clocksource_register_hz(&clocksource_mxs, c);
+	if (timrot_is_v1())
+		clocksource_register_hz(&clocksource_mxs, c);
+	else
+		clocksource_mmio_init(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1)),
                                                                                   ^
Quoted 2 lines

Mismatched parenthesis

Other than that,

Tested on both i.MX23 and i.MX28.

Quoted 5 lines
Quoted 4 lines
arch/arm/mach-mxs/timer.c +1 -0
+			"mxs_timer", c, 200, 32, clocksource_mmio_readl_down);
 
 	return 0;
 }
Signature · 2 lines
Regards,
Shawn
#45 lore raw

PATCH 12/13 clocksource: convert MXS timrotv2 to 32-bit down counting clocksource

Quoted 3 lines · Shawn Guo
Quoted 3 lines

arch/arm/mach-mxs/timer.c static int __init mxs_clocksource_init(struct clk *timer_clk) · line 240

Quoted 1 line
arch/arm/mach-mxs/timer.c +1 -0
+		clocksource_mmio_init(mxs_timrot_base + HW_TIMROT_RUNNING_COUNTn(1)),
                                                                                   ^

Mismatched parenthesis

Fixed.

Quoted 5 lines

Other than that,

Tested on both i.MX23 and i.MX28.

Thanks.

#46 lore raw

PATCH 13/13 clocksource: convert OMAP1 to 32-bit down counting clocksource

In reply to Russell King - ARM Linux

Convert the OMAP1 32-bit down counting clocksource to the generic clocksource infrastructure.

Cc Tony Lindgren <[email protected]>
Cc linux-omap at vger.kernel.org
---
 arch/arm/mach-omap1/time.c |   23 ++++++-----------------
 arch/arm/plat-omap/Kconfig |    1 +
 2 files changed, 7 insertions(+), 17 deletions(-)
arch/arm/mach-omap1/time.c +6 -17
index e7ab616..03e1e10 100644
@@ -190,24 +190,11 @@ static __init void omap_init_mpu_timer(unsigned long rate)
  * ---------------------------------------------------------------------------
  */
 
-static cycle_t mpu_read(struct clocksource *cs)
-{
-	return ~omap_mpu_timer_read(1);
-}
-
-static struct clocksource clocksource_mpu = {
-	.name		= "mpu_timer2",
-	.rating		= 300,
-	.read		= mpu_read,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
 static DEFINE_CLOCK_DATA(cd);
 
 static inline unsigned long long notrace _omap_mpu_sched_clock(void)
 {
-	u32 cyc = mpu_read(&clocksource_mpu);
+	u32 cyc = ~omap_mpu_timer_read(1);
 	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
 }
 
@@ -225,20 +212,22 @@ static unsigned long long notrace omap_mpu_sched_clock(void)
 
 static void notrace mpu_update_sched_clock(void)
 {
-	u32 cyc = mpu_read(&clocksource_mpu);
+	u32 cyc = ~omap_mpu_timer_read(1);
 	update_sched_clock(&cd, cyc, (u32)~0);
 }
 
 static void __init omap_init_clocksource(unsigned long rate)
 {
+	omap_mpu_timer_regs_t __iomem *timer = omap_mpu_timer_base(1);
 	static char err[] __initdata = KERN_ERR
 			"%s: can't register clocksource!\n";
 
 	omap_mpu_timer_start(1, ~0, 1);
 	init_sched_clock(&cd, mpu_update_sched_clock, 32, rate);
 
-	if (clocksource_register_hz(&clocksource_mpu, rate))
-		printk(err, clocksource_mpu.name);
+	if (clocksource_mmio_init(&timer->read_tim, "mpu_timer2", rate,
+			300, 32, clocksource_mmio_readl_down))
+		printk(err, "mpu_timer2");
 }
 
 static void __init omap_mpu_timer_init(void)
arch/arm/plat-omap/Kconfig +1 -0
index cd5f993..e9c0efc 100644
@@ -12,6 +12,7 @@ choice
 config ARCH_OMAP1
 	bool "TI OMAP1"
 	select CLKDEV_LOOKUP
+	select CLKSRC_MMIO
 	help
 	  "Systems based on omap7xx, omap15xx or omap16xx"
 
Signature · 1 line
1.7.4.4
#48 lore raw

[PATCH 14/13] clocksource: ARM sp804: allow clocksource name to be specified

In reply to Russell King - ARM Linux

This allows platforms to specify the clocksource name upon registration, which is necessary should they wish to register more than one sp804 clocksource.

Cc Catalin Marinas <[email protected]>
---
 arch/arm/common/timer-sp.c               |    4 ++--
 arch/arm/include/asm/hardware/timer-sp.h |    2 +-
 arch/arm/mach-integrator/integrator_cp.c |    2 +-
 arch/arm/mach-realview/core.c            |    2 +-
 arch/arm/mach-versatile/core.c           |    2 +-
 arch/arm/mach-vexpress/ct-ca9x4.c        |    2 +-
 arch/arm/mach-vexpress/v2m.c             |    2 +-
 7 files changed, 8 insertions(+), 8 deletions(-)
arch/arm/common/timer-sp.c +2 -2
index 445b05e..f6b9011 100644
@@ -32,7 +32,7 @@
 #define TIMER_FREQ_KHZ	(1000)
 #define TIMER_RELOAD	(TIMER_FREQ_KHZ * 1000 / HZ)
 
-void __init sp804_clocksource_init(void __iomem *base)
+void __init sp804_clocksource_init(void __iomem *base, const char *name)
 {
 	/* setup timer 0 as free-running clocksource */
 	writel(0, base + TIMER_CTRL);
@@ -41,7 +41,7 @@ void __init sp804_clocksource_init(void __iomem *base)
 	writel(TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE | TIMER_CTRL_PERIODIC,
 		base + TIMER_CTRL);
 
-	clocksource_mmio_init(base + TIMER_VALUE, "timer3",
+	clocksource_mmio_init(base + TIMER_VALUE, name,
 		TIMER_FREQ_KHZ * 1000, 200, 32, clocksource_mmio_readl_down);
 }
 
arch/arm/include/asm/hardware/timer-sp.h +1 -1
index 21e75e3..11c386b 100644
@@ -1,2 +1,2 @@
-void sp804_clocksource_init(void __iomem *);
+void sp804_clocksource_init(void __iomem *, const char *);
 void sp804_clockevents_init(void __iomem *, unsigned int);
arch/arm/mach-integrator/integrator_cp.c +1 -1
index 9e3ce26..46fb7f5 100644
@@ -476,7 +476,7 @@ static void __init intcp_timer_init(void)
 	writel(0, TIMER1_VA_BASE + TIMER_CTRL);
 	writel(0, TIMER2_VA_BASE + TIMER_CTRL);
 
-	sp804_clocksource_init(TIMER2_VA_BASE);
+	sp804_clocksource_init(TIMER2_VA_BASE, "timer2");
 	sp804_clockevents_init(TIMER1_VA_BASE, IRQ_TIMERINT1);
 }
 
arch/arm/mach-realview/core.c +1 -1
index 75dbc87..6356b5e 100644
@@ -545,7 +545,7 @@ void __init realview_timer_init(unsigned int timer_irq)
 	writel(0, timer2_va_base + TIMER_CTRL);
 	writel(0, timer3_va_base + TIMER_CTRL);
 
-	sp804_clocksource_init(timer3_va_base);
+	sp804_clocksource_init(timer3_va_base, "timer3");
 	sp804_clockevents_init(timer0_va_base, timer_irq);
 }
 
arch/arm/mach-versatile/core.c +1 -1
index eb7ffa0..aad6d39 100644
@@ -764,7 +764,7 @@ static void __init versatile_timer_init(void)
 	writel(0, TIMER2_VA_BASE + TIMER_CTRL);
 	writel(0, TIMER3_VA_BASE + TIMER_CTRL);
 
-	sp804_clocksource_init(TIMER3_VA_BASE);
+	sp804_clocksource_init(TIMER3_VA_BASE, "timer3");
 	sp804_clockevents_init(TIMER0_VA_BASE, IRQ_TIMERINT0_1);
 }
 
arch/arm/mach-vexpress/ct-ca9x4.c +1 -1
index ebc22e7..c833fd9 100644
@@ -71,7 +71,7 @@ static void __init ct_ca9x4_timer_init(void)
 	writel(0, MMIO_P2V(CT_CA9X4_TIMER0) + TIMER_CTRL);
 	writel(0, MMIO_P2V(CT_CA9X4_TIMER1) + TIMER_CTRL);
 
-	sp804_clocksource_init(MMIO_P2V(CT_CA9X4_TIMER1));
+	sp804_clocksource_init(MMIO_P2V(CT_CA9X4_TIMER1), "ct-timer1");
 	sp804_clockevents_init(MMIO_P2V(CT_CA9X4_TIMER0), IRQ_CT_CA9X4_TIMER0);
 }
 
arch/arm/mach-vexpress/v2m.c +1 -1
index ba46e8e..ccf1f89 100644
@@ -65,7 +65,7 @@ static void __init v2m_timer_init(void)
 	writel(0, MMIO_P2V(V2M_TIMER0) + TIMER_CTRL);
 	writel(0, MMIO_P2V(V2M_TIMER1) + TIMER_CTRL);
 
-	sp804_clocksource_init(MMIO_P2V(V2M_TIMER1));
+	sp804_clocksource_init(MMIO_P2V(V2M_TIMER1), "v2m-timer1");
 	sp804_clockevents_init(MMIO_P2V(V2M_TIMER0), IRQ_V2M_TIMER0);
 }
 
Signature · 1 line
1.7.4.4
#50 lore raw

[PATCH 15/13] clocksource: ARM sp804: obtain sp804 timer rate via clks

In reply to Russell King - ARM Linux

This allows platforms to specify the rate of the SP804 clocksource via the clk subsystem. While ARM boards clock these at 1MHz, BCMRing also has SP804 timers but are clocked at different rates.

Cc Catalin Marinas <[email protected]>
---
 arch/arm/common/timer-sp.c               |   24 +++++++++++++++++++++++-
 arch/arm/mach-integrator/integrator_cp.c |    7 +++++++
 arch/arm/mach-realview/core.c            |    9 ++++++++-
 arch/arm/mach-versatile/core.c           |    9 ++++++++-
 arch/arm/mach-vexpress/ct-ca9x4.c        |    8 ++++++++
 arch/arm/mach-vexpress/v2m.c             |    8 ++++++++
 6 files changed, 62 insertions(+), 3 deletions(-)
arch/arm/common/timer-sp.c +23 -1
index f6b9011..e201941 100644
@@ -18,8 +18,10 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
+#include <linux/clk.h>
 #include <linux/clocksource.h>
 #include <linux/clockchips.h>
+#include <linux/err.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/io.h>
@@ -34,6 +36,26 @@
 
 void __init sp804_clocksource_init(void __iomem *base, const char *name)
 {
+	unsigned long rate;
+	struct clk *clk;
+	int err;
+
+	clk = clk_get_sys("sp804", name);
+	if (IS_ERR(clk)) {
+		pr_err("sp804: %s clock not found: %d\n", name,
+			(int)PTR_ERR(clk));
+		return;
+	}
+
+	err = clk_enable(clk);
+	if (err) {
+		pr_err("sp804: %s clock failed to enable: %d\n", name, err);
+		clk_put(clk);
+		return;
+	}
+
+	rate = clk_get_rate(clk);
+
 	/* setup timer 0 as free-running clocksource */
 	writel(0, base + TIMER_CTRL);
 	writel(0xffffffff, base + TIMER_LOAD);
@@ -42,7 +64,7 @@ void __init sp804_clocksource_init(void __iomem *base, const char *name)
 		base + TIMER_CTRL);
 
 	clocksource_mmio_init(base + TIMER_VALUE, name,
-		TIMER_FREQ_KHZ * 1000, 200, 32, clocksource_mmio_readl_down);
+		rate, 200, 32, clocksource_mmio_readl_down);
 }
 
 
arch/arm/mach-integrator/integrator_cp.c +7 -0
index 46fb7f5..8fb8afb 100644
@@ -229,10 +229,17 @@ static struct clk cp_auxclk = {
 	.vcoreg	= CM_AUXOSC,
 };
 
+static struct clk sp804_clk = {
+	.rate	= 1000000,
+};
+
 static struct clk_lookup cp_lookups[] = {
 	{	/* CLCD */
 		.dev_id		= "mb:c0",
 		.clk		= &cp_auxclk,
+	}, {	/* SP804 timers */
+		.dev_id		= "sp804",
+		.clk		= &sp804_clk,
 	},
 };
 
arch/arm/mach-realview/core.c +8 -1
index 6356b5e..6a9cd1e 100644
@@ -315,6 +315,10 @@ static struct clk ref24_clk = {
 	.rate	= 24000000,
 };
 
+static struct clk sp804_clk = {
+	.rate	= 1000000,
+};
+
 static struct clk dummy_apb_pclk;
 
 static struct clk_lookup lookups[] = {
@@ -357,7 +361,10 @@ static struct clk_lookup lookups[] = {
 	}, {	/* SSP */
 		.dev_id		= "dev:ssp0",
 		.clk		= &ref24_clk,
-	}
+	}, {	/* SP804 timers */
+		.dev_id		= "sp804",
+		.clk		= &sp804_clk,
+	},
 };
 
 void __init realview_init_early(void)
arch/arm/mach-versatile/core.c +8 -1
index aad6d39..b0b7de6 100644
@@ -375,6 +375,10 @@ static struct clk ref24_clk = {
 	.rate	= 24000000,
 };
 
+static struct clk sp804_clk = {
+	.rate	= 1000000,
+};
+
 static struct clk dummy_apb_pclk;
 
 static struct clk_lookup lookups[] = {
@@ -411,7 +415,10 @@ static struct clk_lookup lookups[] = {
 	}, {	/* CLCD */
 		.dev_id		= "dev:20",
 		.clk		= &osc4_clk,
-	}
+	}, {	/* SP804 timers */
+		.dev_id		= "sp804",
+		.clk		= &sp804_clk,
+	},
 };
 
 /*
arch/arm/mach-vexpress/ct-ca9x4.c +8 -0
index c833fd9..6004f06 100644
@@ -141,10 +141,18 @@ static struct clk osc1_clk = {
 	.rate	= 24000000,
 };
 
+static struct clk ct_sp804_clk = {
+	.rate	= 1000000,
+};
+
 static struct clk_lookup lookups[] = {
 	{	/* CLCD */
 		.dev_id		= "ct:clcd",
 		.clk		= &osc1_clk,
+	}, {	/* SP804 timers */
+		.dev_id		= "sp804",
+		.con_id		= "ct-timer1",
+		.clk		= &ct_sp804_clk,
 	},
 };
 
arch/arm/mach-vexpress/v2m.c +8 -0
index ccf1f89..77d5db3 100644
@@ -333,6 +333,10 @@ static struct clk osc2_clk = {
 	.rate	= 24000000,
 };
 
+static struct clk v2m_sp804_clk = {
+	.rate	= 1000000,
+};
+
 static struct clk dummy_apb_pclk;
 
 static struct clk_lookup v2m_lookups[] = {
@@ -363,6 +367,10 @@ static struct clk_lookup v2m_lookups[] = {
 	}, {	/* CLCD */
 		.dev_id		= "mb:clcd",
 		.clk		= &osc1_clk,
+	}, {	/* SP804 timers */
+		.dev_id		= "sp804",
+		.con_id		= "v2m-timer1",
+		.clk		= &v2m_sp804_clk,
 	},
 };
 
Signature · 1 line
1.7.4.4