Skip to contentSkip to conversation

ARM: davinci: modernize the timer support

PATCH Superseded Bartosz Golaszewski 3 participants 22 messages Mar 18, 2019 – Apr 16, 2019

Subsystems (4)

v4 of 8 Superseded Latest is v8 →

lore
Share & tools
lore
#0 lore raw

v4 cover ARM: davinci: modernize the timer support

From: Bartosz Golaszewski <[email protected]>

This series removes the legacy timer code from mach-davinci in favor of a new clocksource driver it introduces.

Patch 1 adds a new clocksource driver for davinci.

Patch 2 enables the new driver for device-tree based systems.

Patch 3 adds a WARN_ON() to the machine code of all davinci boards which is triggered if clk_get() for the timer clock fails. This is needed as the new driver expects the clock to be functional and doesn't check it.

Patches 4-5 and 7-10 switch the board files to using the new clocksource driver while patch 6 moves some necessary defines to a different place since we'll be removing the file that contains them.

Patch 11 removes legacy timer code.

v1 -> v2:

- changed the license to GPL-only
- dropped regmap usage due to the additional code paths making the code too slow
- minor code rearrangement
- fixed the da830 timer configuration
- correctly assign the timer halves to clocksource and clockevent
- sqashed the commits adding WARN() when clk_get() fails
- used WARN_ON() and added a return when clk_get() fails to avoid entering the timer driver without a valid clock
- request the register range before iomapping it
- simplified the configuration structure (dropped the additional cmp struct)

v2 -> v3:

- use readl/writel_relaxed() instead of __raw variants in the clocksource driver
- request the memory region before remapping it
- add explanatory comments
- fixed licensing
- used pr_fmt macro
- correctly assign the clocksource name
- use DEFINE_RES_x macros when defining resources to avoid off-by-one bugs in resource's size
- tweak the commit messages
- don't delete the comments describing the timer usage
- other minor improvements
- rebased on top of Sekhar's soc branch
- dropped patch fixing the clocksource interrupts in device tree (already upstream)

v3 -> v4:
- fixed formatting of error messages
- fixed comments all around the place
- rebased on top of v5.1-rc1

Bartosz Golaszewski (11):
clocksource: davinci-timer: new driver
ARM: davinci: enable the clocksource driver for DT mode
ARM: davinci: WARN_ON() if clk_get() fails
ARM: davinci: da850: switch to using the clocksource driver
ARM: davinci: da830: switch to using the clocksource driver
ARM: davinci: move timer definitions to davinci.h
ARM: davinci: dm355: switch to using the clocksource driver
ARM: davinci: dm365: switch to using the clocksource driver
ARM: davinci: dm644x: switch to using the clocksource driver
ARM: davinci: dm646x: switch to using the clocksource driver
ARM: davinci: remove legacy timer support

 arch/arm/Kconfig                            |   1 +
 arch/arm/mach-davinci/Makefile              |   3 +-
 arch/arm/mach-davinci/da830.c               |  45 +-
 arch/arm/mach-davinci/da850.c               |  50 +--
 arch/arm/mach-davinci/davinci.h             |   3 +
 arch/arm/mach-davinci/devices-da8xx.c       |   1 -
 arch/arm/mach-davinci/devices.c             |  19 -
 arch/arm/mach-davinci/dm355.c               |  28 +-
 arch/arm/mach-davinci/dm365.c               |  26 +-
 arch/arm/mach-davinci/dm644x.c              |  28 +-
 arch/arm/mach-davinci/dm646x.c              |  28 +-
 arch/arm/mach-davinci/include/mach/common.h |  17 -
 arch/arm/mach-davinci/include/mach/time.h   |  35 --
 arch/arm/mach-davinci/time.c                | 414 ------------------
 drivers/clocksource/Kconfig                 |   5 +
 drivers/clocksource/Makefile                |   1 +
 drivers/clocksource/timer-davinci.c         | 438 ++++++++++++++++++++
 include/clocksource/timer-davinci.h         |  44 ++
 18 files changed, 598 insertions(+), 588 deletions(-)
 delete mode 100644 arch/arm/mach-davinci/include/mach/time.h
 delete mode 100644 arch/arm/mach-davinci/time.c
 create mode 100644 drivers/clocksource/timer-davinci.c
 create mode 100644 include/clocksource/timer-davinci.h
Signature · 1 line
2.20.1
#1 lore raw

PATCH v4 1/11 clocksource: davinci-timer: new driver

From: Bartosz Golaszewski <[email protected]>

Currently the clocksource and clockevent support for davinci platforms lives in mach-davinci. It hard-codes many things, uses global variables, implements functionalities unused by any platform and has code fragments scattered across many (often unrelated) files.

Implement a new, modern and simplified timer driver and put it into drivers/clocksource. We still need to support legacy board files so export a config structure and a function that allows machine code to register the timer.

We don't bother freeing resources on errors in davinci_timer_register() as the system won't boot without a timer anyway.

---
 drivers/clocksource/Kconfig         |   5 +
 drivers/clocksource/Makefile        |   1 +
 drivers/clocksource/timer-davinci.c | 438 ++++++++++++++++++++++++++++
 include/clocksource/timer-davinci.h |  44 +++
 4 files changed, 488 insertions(+)
 create mode 100644 drivers/clocksource/timer-davinci.c
 create mode 100644 include/clocksource/timer-davinci.h
drivers/clocksource/Kconfig +5 -0
index 171502a356aa..08b1f539cfc4 100644
@@ -42,6 +42,11 @@ config BCM_KONA_TIMER
 	help
 	  Enables the support for the BCM Kona mobile timer driver.
 
+config DAVINCI_TIMER
+	bool "Texas Instruments DaVinci timer driver"
+	help
+	  Enables the support for the TI DaVinci timer driver.
+
 config DIGICOLOR_TIMER
 	bool "Digicolor timer driver" if COMPILE_TEST
 	select CLKSRC_MMIO
drivers/clocksource/Makefile +1 -0
index be6e0fbc7489..3c73d0e58b45 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_SH_TIMER_TMU)	+= sh_tmu.o
 obj-$(CONFIG_EM_TIMER_STI)	+= em_sti.o
 obj-$(CONFIG_CLKBLD_I8253)	+= i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)	+= mmio.o
+obj-$(CONFIG_DAVINCI_TIMER)	+= timer-davinci.o
 obj-$(CONFIG_DIGICOLOR_TIMER)	+= timer-digicolor.o
 obj-$(CONFIG_OMAP_DM_TIMER)	+= timer-ti-dm.o
 obj-$(CONFIG_DW_APB_TIMER)	+= dw_apb_timer.o
drivers/clocksource/timer-davinci.c new file +438 -0

438 lines not on this page · raw message

include/clocksource/timer-davinci.h new file +44 -0

44 lines not on this page · raw message

Signature · 7 lines
2.20.1


_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
#2 lore raw

Re: [PATCH v4 01/11] clocksource: davinci-timer: new driver

Quoted 31 lines · Bartosz Golaszewski

From: Bartosz Golaszewski <[email protected]>

Currently the clocksource and clockevent support for davinci platforms lives in mach-davinci. It hard-codes many things, uses global variables, implements functionalities unused by any platform and has code fragments scattered across many (often unrelated) files.

Implement a new, modern and simplified timer driver and put it into drivers/clocksource. We still need to support legacy board files so export a config structure and a function that allows machine code to register the timer.

We don't bother freeing resources on errors in davinci_timer_register() as the system won't boot without a timer anyway.

---
 drivers/clocksource/Kconfig         |   5 +
 drivers/clocksource/Makefile        |   1 +
 drivers/clocksource/timer-davinci.c | 438 ++++++++++++++++++++++++++++
 include/clocksource/timer-davinci.h |  44 +++
 4 files changed, 488 insertions(+)
 create mode 100644 drivers/clocksource/timer-davinci.c
 create mode 100644 include/clocksource/timer-davinci.h
drivers/clocksource/Kconfig +0 -0
index 171502a356aa..08b1f539cfc4 100644

drivers/clocksource/Kconfig config BCM_KONA_TIMER · line 49

Quoted 8 lines
drivers/clocksource/Kconfig +5 -0
@@ -42,6 +42,11 @@ config BCM_KONA_TIMER
 	help
 	  Enables the support for the BCM Kona mobile timer driver.
 
+config DAVINCI_TIMER
+	bool "Texas Instruments DaVinci timer driver"
+	help
+	  Enables the support for the TI DaVinci timer driver.
+

Please make it a silence option only visible with COMPILE_TEST or EXPERT, examples here:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clocksource/Kconfig#n45

or second format:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clocksource/Kconfig#n459

Quoted 100 lines
drivers/clocksource/Kconfig +0 -0
 config DIGICOLOR_TIMER
 	bool "Digicolor timer driver" if COMPILE_TEST
 	select CLKSRC_MMIO
drivers/clocksource/Makefile +1 -0
index be6e0fbc7489..3c73d0e58b45 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_SH_TIMER_TMU)	+= sh_tmu.o
 obj-$(CONFIG_EM_TIMER_STI)	+= em_sti.o
 obj-$(CONFIG_CLKBLD_I8253)	+= i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)	+= mmio.o
+obj-$(CONFIG_DAVINCI_TIMER)	+= timer-davinci.o
 obj-$(CONFIG_DIGICOLOR_TIMER)	+= timer-digicolor.o
 obj-$(CONFIG_OMAP_DM_TIMER)	+= timer-ti-dm.o
 obj-$(CONFIG_DW_APB_TIMER)	+= dw_apb_timer.o
drivers/clocksource/timer-davinci.c new file +79 -0
new file mode 100644
index 000000000000..46dfc4d457fc
@@ -0,0 +1,438 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// TI DaVinci clocksource driver
+//
+// Copyright (C) 2019 Texas Instruments
+// Author: Bartosz Golaszewski <[email protected]>
+// (with some parts adopted from code by Kevin Hilman <[email protected]>)
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+
+#include <clocksource/timer-davinci.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt "\n", __func__
+
+#define DAVINCI_TIMER_REG_TIM12			0x10
+#define DAVINCI_TIMER_REG_TIM34			0x14
+#define DAVINCI_TIMER_REG_PRD12			0x18
+#define DAVINCI_TIMER_REG_PRD34			0x1c
+#define DAVINCI_TIMER_REG_TCR			0x20
+#define DAVINCI_TIMER_REG_TGCR			0x24
+
+#define DAVINCI_TIMER_TIMMODE_MASK		GENMASK(3, 2)
+#define DAVINCI_TIMER_RESET_MASK		GENMASK(1, 0)
+#define DAVINCI_TIMER_TIMMODE_32BIT_UNCHAINED	BIT(2)
+#define DAVINCI_TIMER_UNRESET			GENMASK(1, 0)
+
+/* Shift depends on timer. */
+#define DAVINCI_TIMER_ENAMODE_MASK		GENMASK(1, 0)
+#define DAVINCI_TIMER_ENAMODE_DISABLED		0x00
+#define DAVINCI_TIMER_ENAMODE_ONESHOT		BIT(0)
+#define DAVINCI_TIMER_ENAMODE_PERIODIC		BIT(1)
+
+#define DAVINCI_TIMER_ENAMODE_SHIFT_TIM12	6
+#define DAVINCI_TIMER_ENAMODE_SHIFT_TIM34	22
+
+#define DAVINCI_TIMER_MIN_DELTA			0x01
+#define DAVINCI_TIMER_MAX_DELTA			0xfffffffe
+
+#define DAVINCI_TIMER_CLKSRC_BITS		32
+
+#define DAVINCI_TIMER_TGCR_DEFAULT \
+		(DAVINCI_TIMER_TIMMODE_32BIT_UNCHAINED | DAVINCI_TIMER_UNRESET)
+
+enum {
+	DAVINCI_TIMER_MODE_DISABLED = 0,
+	DAVINCI_TIMER_MODE_ONESHOT,
+	DAVINCI_TIMER_MODE_PERIODIC,
+};
+
+struct davinci_timer_data;
+
+typedef void (*davinci_timer_set_period_func)(struct davinci_timer_data *,
+					      unsigned int period);
+
+/**
+ * struct davinci_timer_regs - timer-specific register offsets
+ *
+ * @tim_off: timer counter register
+ * @prd_off: timer period register
+ * @enamode_shift: left bit-shift of the enable register associated
+ *                 with this timer in the TCR register
+ */
+struct davinci_timer_regs {
+	unsigned int tim_off;
+	unsigned int prd_off;
+	unsigned int enamode_shift;
+};
+
+struct davinci_timer_data {
+	void __iomem *base;
+	const struct davinci_timer_regs *regs;

drivers/clocksource/timer-davinci.c line 89

Quoted 10 lines
drivers/clocksource/timer-davinci.c new file +10 -0
+	unsigned int mode;
+	davinci_timer_set_period_func set_period;
+	unsigned int cmp_off;
+};
+
+struct davinci_timer_clockevent {
+	struct clock_event_device dev;
+	unsigned int tick_rate;
+	struct davinci_timer_data timer;
+};

The timer-of API provides the functions and the common structures for the usual operations. Please use them instead of redefining your own structures.

Signature · 5 lines
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
#3 lore raw

Re: [PATCH v4 01/11] clocksource: davinci-timer: new driver

wt., 2 kwi 2019 o 11:21 Daniel Lezcano <[email protected]> napisał(a):

Quoted 157 lines · Bartosz Golaszewski
Quoted 31 lines

From: Bartosz Golaszewski <[email protected]>

Currently the clocksource and clockevent support for davinci platforms lives in mach-davinci. It hard-codes many things, uses global variables, implements functionalities unused by any platform and has code fragments scattered across many (often unrelated) files.

Implement a new, modern and simplified timer driver and put it into drivers/clocksource. We still need to support legacy board files so export a config structure and a function that allows machine code to register the timer.

We don't bother freeing resources on errors in davinci_timer_register() as the system won't boot without a timer anyway.

---
 drivers/clocksource/Kconfig         |   5 +
 drivers/clocksource/Makefile        |   1 +
 drivers/clocksource/timer-davinci.c | 438 ++++++++++++++++++++++++++++
 include/clocksource/timer-davinci.h |  44 +++
 4 files changed, 488 insertions(+)
 create mode 100644 drivers/clocksource/timer-davinci.c
 create mode 100644 include/clocksource/timer-davinci.h
drivers/clocksource/Kconfig +0 -0
index 171502a356aa..08b1f539cfc4 100644

drivers/clocksource/Kconfig config BCM_KONA_TIMER · line 49

Quoted 8 lines
drivers/clocksource/Kconfig +5 -0
@@ -42,6 +42,11 @@ config BCM_KONA_TIMER
      help
        Enables the support for the BCM Kona mobile timer driver.
 
+config DAVINCI_TIMER
+     bool "Texas Instruments DaVinci timer driver"
+     help
+       Enables the support for the TI DaVinci timer driver.
+

Please make it a silence option only visible with COMPILE_TEST or EXPERT, examples here:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clocksource/Kconfig#n45

or second format:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clocksource/Kconfig#n459

Quoted 106 lines
drivers/clocksource/Kconfig +0 -0
 config DIGICOLOR_TIMER
      bool "Digicolor timer driver" if COMPILE_TEST
      select CLKSRC_MMIO
drivers/clocksource/Makefile +1 -0
index be6e0fbc7489..3c73d0e58b45 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_SH_TIMER_TMU)  += sh_tmu.o
 obj-$(CONFIG_EM_TIMER_STI)   += em_sti.o
 obj-$(CONFIG_CLKBLD_I8253)   += i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)    += mmio.o
+obj-$(CONFIG_DAVINCI_TIMER)  += timer-davinci.o
 obj-$(CONFIG_DIGICOLOR_TIMER)        += timer-digicolor.o
 obj-$(CONFIG_OMAP_DM_TIMER)  += timer-ti-dm.o
 obj-$(CONFIG_DW_APB_TIMER)   += dw_apb_timer.o
drivers/clocksource/timer-davinci.c new file +85 -0
new file mode 100644
index 000000000000..46dfc4d457fc
@@ -0,0 +1,438 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// TI DaVinci clocksource driver
+//
+// Copyright (C) 2019 Texas Instruments
+// Author: Bartosz Golaszewski <[email protected]>
+// (with some parts adopted from code by Kevin Hilman <[email protected]>)
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+
+#include <clocksource/timer-davinci.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt "\n", __func__
+
+#define DAVINCI_TIMER_REG_TIM12                      0x10
+#define DAVINCI_TIMER_REG_TIM34                      0x14
+#define DAVINCI_TIMER_REG_PRD12                      0x18
+#define DAVINCI_TIMER_REG_PRD34                      0x1c
+#define DAVINCI_TIMER_REG_TCR                        0x20
+#define DAVINCI_TIMER_REG_TGCR                       0x24
+
+#define DAVINCI_TIMER_TIMMODE_MASK           GENMASK(3, 2)
+#define DAVINCI_TIMER_RESET_MASK             GENMASK(1, 0)
+#define DAVINCI_TIMER_TIMMODE_32BIT_UNCHAINED        BIT(2)
+#define DAVINCI_TIMER_UNRESET                        GENMASK(1, 0)
+
+/* Shift depends on timer. */
+#define DAVINCI_TIMER_ENAMODE_MASK           GENMASK(1, 0)
+#define DAVINCI_TIMER_ENAMODE_DISABLED               0x00
+#define DAVINCI_TIMER_ENAMODE_ONESHOT                BIT(0)
+#define DAVINCI_TIMER_ENAMODE_PERIODIC               BIT(1)
+
+#define DAVINCI_TIMER_ENAMODE_SHIFT_TIM12    6
+#define DAVINCI_TIMER_ENAMODE_SHIFT_TIM34    22
+
+#define DAVINCI_TIMER_MIN_DELTA                      0x01
+#define DAVINCI_TIMER_MAX_DELTA                      0xfffffffe
+
+#define DAVINCI_TIMER_CLKSRC_BITS            32
+
+#define DAVINCI_TIMER_TGCR_DEFAULT \
+             (DAVINCI_TIMER_TIMMODE_32BIT_UNCHAINED | DAVINCI_TIMER_UNRESET)
+
+enum {
+     DAVINCI_TIMER_MODE_DISABLED = 0,
+     DAVINCI_TIMER_MODE_ONESHOT,
+     DAVINCI_TIMER_MODE_PERIODIC,
+};
+
+struct davinci_timer_data;
+
+typedef void (*davinci_timer_set_period_func)(struct davinci_timer_data *,
+                                           unsigned int period);
+
+/**
+ * struct davinci_timer_regs - timer-specific register offsets
+ *
+ * @tim_off: timer counter register
+ * @prd_off: timer period register
+ * @enamode_shift: left bit-shift of the enable register associated
+ *                 with this timer in the TCR register
+ */
+struct davinci_timer_regs {
+     unsigned int tim_off;
+     unsigned int prd_off;
+     unsigned int enamode_shift;
+};
+
+struct davinci_timer_data {
+     void __iomem *base;
+     const struct davinci_timer_regs *regs;
+     unsigned int mode;
+     davinci_timer_set_period_func set_period;
+     unsigned int cmp_off;
+};
+
+struct davinci_timer_clockevent {
Quoted 9 lines

drivers/clocksource/timer-davinci.c line 90

Quoted 4 lines
drivers/clocksource/timer-davinci.c new file +4 -0
+     struct clock_event_device dev;
+     unsigned int tick_rate;
+     struct davinci_timer_data timer;
+};

The timer-of API provides the functions and the common structures for the usual operations. Please use them instead of redefining your own structures.

Hi Daniel,

do you have any suggestion about where to put the information about register offsets I'm now storing in struct davinci_timer_regs? I thought about having specialized wrappers around all relevant functions that access the registers, but that seems like an overkill. For instance we'd have:

davinci_timer_set_period_std()

and two specialized variants:

davinci_timer_set_period_std_tim12() and davinci_timer_set_period_std_tim34()

The former would take struct davinci_timer_regs as argument while two latter routines would fit the callback format. We'd then need the same for three more routines.

Alternatively struct timer_of could be packed together with struct davinci_timer_regs in another structure and accessed in callbacks via container_of.

Do you have a preference or a different idea?

Bartosz

Quoted 9 lines

--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

#4 lore raw

Re: [PATCH v4 01/11] clocksource: davinci-timer: new driver

In reply to Daniel Lezcano

wt., 2 kwi 2019 o 11:21 Daniel Lezcano <[email protected]> napisał(a):

Quoted 157 lines · Bartosz Golaszewski
Quoted 31 lines

From: Bartosz Golaszewski <[email protected]>

Currently the clocksource and clockevent support for davinci platforms lives in mach-davinci. It hard-codes many things, uses global variables, implements functionalities unused by any platform and has code fragments scattered across many (often unrelated) files.

Implement a new, modern and simplified timer driver and put it into drivers/clocksource. We still need to support legacy board files so export a config structure and a function that allows machine code to register the timer.

We don't bother freeing resources on errors in davinci_timer_register() as the system won't boot without a timer anyway.

---
 drivers/clocksource/Kconfig         |   5 +
 drivers/clocksource/Makefile        |   1 +
 drivers/clocksource/timer-davinci.c | 438 ++++++++++++++++++++++++++++
 include/clocksource/timer-davinci.h |  44 +++
 4 files changed, 488 insertions(+)
 create mode 100644 drivers/clocksource/timer-davinci.c
 create mode 100644 include/clocksource/timer-davinci.h
drivers/clocksource/Kconfig +0 -0
index 171502a356aa..08b1f539cfc4 100644

drivers/clocksource/Kconfig config BCM_KONA_TIMER · line 49

Quoted 8 lines
drivers/clocksource/Kconfig +5 -0
@@ -42,6 +42,11 @@ config BCM_KONA_TIMER
      help
        Enables the support for the BCM Kona mobile timer driver.
 
+config DAVINCI_TIMER
+     bool "Texas Instruments DaVinci timer driver"
+     help
+       Enables the support for the TI DaVinci timer driver.
+

Please make it a silence option only visible with COMPILE_TEST or EXPERT, examples here:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clocksource/Kconfig#n45

or second format:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clocksource/Kconfig#n459

Quoted 106 lines
drivers/clocksource/Kconfig +0 -0
 config DIGICOLOR_TIMER
      bool "Digicolor timer driver" if COMPILE_TEST
      select CLKSRC_MMIO
drivers/clocksource/Makefile +1 -0
index be6e0fbc7489..3c73d0e58b45 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_SH_TIMER_TMU)  += sh_tmu.o
 obj-$(CONFIG_EM_TIMER_STI)   += em_sti.o
 obj-$(CONFIG_CLKBLD_I8253)   += i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)    += mmio.o
+obj-$(CONFIG_DAVINCI_TIMER)  += timer-davinci.o
 obj-$(CONFIG_DIGICOLOR_TIMER)        += timer-digicolor.o
 obj-$(CONFIG_OMAP_DM_TIMER)  += timer-ti-dm.o
 obj-$(CONFIG_DW_APB_TIMER)   += dw_apb_timer.o
drivers/clocksource/timer-davinci.c new file +85 -0
new file mode 100644
index 000000000000..46dfc4d457fc
@@ -0,0 +1,438 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// TI DaVinci clocksource driver
+//
+// Copyright (C) 2019 Texas Instruments
+// Author: Bartosz Golaszewski <[email protected]>
+// (with some parts adopted from code by Kevin Hilman <[email protected]>)
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+
+#include <clocksource/timer-davinci.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt "\n", __func__
+
+#define DAVINCI_TIMER_REG_TIM12                      0x10
+#define DAVINCI_TIMER_REG_TIM34                      0x14
+#define DAVINCI_TIMER_REG_PRD12                      0x18
+#define DAVINCI_TIMER_REG_PRD34                      0x1c
+#define DAVINCI_TIMER_REG_TCR                        0x20
+#define DAVINCI_TIMER_REG_TGCR                       0x24
+
+#define DAVINCI_TIMER_TIMMODE_MASK           GENMASK(3, 2)
+#define DAVINCI_TIMER_RESET_MASK             GENMASK(1, 0)
+#define DAVINCI_TIMER_TIMMODE_32BIT_UNCHAINED        BIT(2)
+#define DAVINCI_TIMER_UNRESET                        GENMASK(1, 0)
+
+/* Shift depends on timer. */
+#define DAVINCI_TIMER_ENAMODE_MASK           GENMASK(1, 0)
+#define DAVINCI_TIMER_ENAMODE_DISABLED               0x00
+#define DAVINCI_TIMER_ENAMODE_ONESHOT                BIT(0)
+#define DAVINCI_TIMER_ENAMODE_PERIODIC               BIT(1)
+
+#define DAVINCI_TIMER_ENAMODE_SHIFT_TIM12    6
+#define DAVINCI_TIMER_ENAMODE_SHIFT_TIM34    22
+
+#define DAVINCI_TIMER_MIN_DELTA                      0x01
+#define DAVINCI_TIMER_MAX_DELTA                      0xfffffffe
+
+#define DAVINCI_TIMER_CLKSRC_BITS            32
+
+#define DAVINCI_TIMER_TGCR_DEFAULT \
+             (DAVINCI_TIMER_TIMMODE_32BIT_UNCHAINED | DAVINCI_TIMER_UNRESET)
+
+enum {
+     DAVINCI_TIMER_MODE_DISABLED = 0,
+     DAVINCI_TIMER_MODE_ONESHOT,
+     DAVINCI_TIMER_MODE_PERIODIC,
+};
+
+struct davinci_timer_data;
+
+typedef void (*davinci_timer_set_period_func)(struct davinci_timer_data *,
+                                           unsigned int period);
+
+/**
+ * struct davinci_timer_regs - timer-specific register offsets
+ *
+ * @tim_off: timer counter register
+ * @prd_off: timer period register
+ * @enamode_shift: left bit-shift of the enable register associated
+ *                 with this timer in the TCR register
+ */
+struct davinci_timer_regs {
+     unsigned int tim_off;
+     unsigned int prd_off;
+     unsigned int enamode_shift;
+};
+
+struct davinci_timer_data {
+     void __iomem *base;
+     const struct davinci_timer_regs *regs;
+     unsigned int mode;
+     davinci_timer_set_period_func set_period;
+     unsigned int cmp_off;
+};
+
+struct davinci_timer_clockevent {
Quoted 9 lines

drivers/clocksource/timer-davinci.c line 90

Quoted 4 lines
drivers/clocksource/timer-davinci.c new file +4 -0
+     struct clock_event_device dev;
+     unsigned int tick_rate;
+     struct davinci_timer_data timer;
+};

The timer-of API provides the functions and the common structures for the usual operations. Please use them instead of redefining your own structures.

After giving it another thought, I don't think we can use timer-of in this driver easily.

It's meant to work both for board files and device-tree. The solution with the least code duplication is to take the device_node on DT systems and put all relevant properties into the custom structure used by board files users. Timer-of maps the memory, enables the clock and requests interrupts directly from the device_node. I'd have to do the same for board files manually anyway. I think it's better to have a single point of entry for the initialization code.

Even if I were just to reuse the timer-of structures without reusing the actual code - they are still missing certain fields. We're using 32-bit "halves" of timers that are actually 64 bits - the 32-bit control register deals with both by using the same layout of bit fields but shifted. This is what the struct davinci_timer_regs is for. Reusing those structures would also be confusing because of the of_ prefix in the naming.

I'd prefer to leave it as it is. Let me know what you think.

Bart

#5 lore raw

Re: [PATCH v4 01/11] clocksource: davinci-timer: new driver

Quoted 187 lines · Bartosz Golaszewski

wt., 2 kwi 2019 o 11:21 Daniel Lezcano <[email protected]> napisał(a):

Quoted 157 lines · Bartosz Golaszewski
Quoted 31 lines

From: Bartosz Golaszewski <[email protected]>

Currently the clocksource and clockevent support for davinci platforms lives in mach-davinci. It hard-codes many things, uses global variables, implements functionalities unused by any platform and has code fragments scattered across many (often unrelated) files.

Implement a new, modern and simplified timer driver and put it into drivers/clocksource. We still need to support legacy board files so export a config structure and a function that allows machine code to register the timer.

We don't bother freeing resources on errors in davinci_timer_register() as the system won't boot without a timer anyway.

---
 drivers/clocksource/Kconfig         |   5 +
 drivers/clocksource/Makefile        |   1 +
 drivers/clocksource/timer-davinci.c | 438 ++++++++++++++++++++++++++++
 include/clocksource/timer-davinci.h |  44 +++
 4 files changed, 488 insertions(+)
 create mode 100644 drivers/clocksource/timer-davinci.c
 create mode 100644 include/clocksource/timer-davinci.h
drivers/clocksource/Kconfig +0 -0
index 171502a356aa..08b1f539cfc4 100644

drivers/clocksource/Kconfig config BCM_KONA_TIMER · line 49

Quoted 8 lines
drivers/clocksource/Kconfig +5 -0
@@ -42,6 +42,11 @@ config BCM_KONA_TIMER
      help
        Enables the support for the BCM Kona mobile timer driver.
 
+config DAVINCI_TIMER
+     bool "Texas Instruments DaVinci timer driver"
+     help
+       Enables the support for the TI DaVinci timer driver.
+

Please make it a silence option only visible with COMPILE_TEST or EXPERT, examples here:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clocksource/Kconfig#n45

or second format:

https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/clocksource/Kconfig#n459

Quoted 106 lines
drivers/clocksource/Kconfig +0 -0
 config DIGICOLOR_TIMER
      bool "Digicolor timer driver" if COMPILE_TEST
      select CLKSRC_MMIO
drivers/clocksource/Makefile +1 -0
index be6e0fbc7489..3c73d0e58b45 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_SH_TIMER_TMU)  += sh_tmu.o
 obj-$(CONFIG_EM_TIMER_STI)   += em_sti.o
 obj-$(CONFIG_CLKBLD_I8253)   += i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)    += mmio.o
+obj-$(CONFIG_DAVINCI_TIMER)  += timer-davinci.o
 obj-$(CONFIG_DIGICOLOR_TIMER)        += timer-digicolor.o
 obj-$(CONFIG_OMAP_DM_TIMER)  += timer-ti-dm.o
 obj-$(CONFIG_DW_APB_TIMER)   += dw_apb_timer.o
drivers/clocksource/timer-davinci.c new file +85 -0
new file mode 100644
index 000000000000..46dfc4d457fc
@@ -0,0 +1,438 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// TI DaVinci clocksource driver
+//
+// Copyright (C) 2019 Texas Instruments
+// Author: Bartosz Golaszewski <[email protected]>
+// (with some parts adopted from code by Kevin Hilman <[email protected]>)
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+
+#include <clocksource/timer-davinci.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt "\n", __func__
+
+#define DAVINCI_TIMER_REG_TIM12                      0x10
+#define DAVINCI_TIMER_REG_TIM34                      0x14
+#define DAVINCI_TIMER_REG_PRD12                      0x18
+#define DAVINCI_TIMER_REG_PRD34                      0x1c
+#define DAVINCI_TIMER_REG_TCR                        0x20
+#define DAVINCI_TIMER_REG_TGCR                       0x24
+
+#define DAVINCI_TIMER_TIMMODE_MASK           GENMASK(3, 2)
+#define DAVINCI_TIMER_RESET_MASK             GENMASK(1, 0)
+#define DAVINCI_TIMER_TIMMODE_32BIT_UNCHAINED        BIT(2)
+#define DAVINCI_TIMER_UNRESET                        GENMASK(1, 0)
+
+/* Shift depends on timer. */
+#define DAVINCI_TIMER_ENAMODE_MASK           GENMASK(1, 0)
+#define DAVINCI_TIMER_ENAMODE_DISABLED               0x00
+#define DAVINCI_TIMER_ENAMODE_ONESHOT                BIT(0)
+#define DAVINCI_TIMER_ENAMODE_PERIODIC               BIT(1)
+
+#define DAVINCI_TIMER_ENAMODE_SHIFT_TIM12    6
+#define DAVINCI_TIMER_ENAMODE_SHIFT_TIM34    22
+
+#define DAVINCI_TIMER_MIN_DELTA                      0x01
+#define DAVINCI_TIMER_MAX_DELTA                      0xfffffffe
+
+#define DAVINCI_TIMER_CLKSRC_BITS            32
+
+#define DAVINCI_TIMER_TGCR_DEFAULT \
+             (DAVINCI_TIMER_TIMMODE_32BIT_UNCHAINED | DAVINCI_TIMER_UNRESET)
+
+enum {
+     DAVINCI_TIMER_MODE_DISABLED = 0,
+     DAVINCI_TIMER_MODE_ONESHOT,
+     DAVINCI_TIMER_MODE_PERIODIC,
+};
+
+struct davinci_timer_data;
+
+typedef void (*davinci_timer_set_period_func)(struct davinci_timer_data *,
+                                           unsigned int period);
+
+/**
+ * struct davinci_timer_regs - timer-specific register offsets
+ *
+ * @tim_off: timer counter register
+ * @prd_off: timer period register
+ * @enamode_shift: left bit-shift of the enable register associated
+ *                 with this timer in the TCR register
+ */
+struct davinci_timer_regs {
+     unsigned int tim_off;
+     unsigned int prd_off;
+     unsigned int enamode_shift;
+};
+
+struct davinci_timer_data {
+     void __iomem *base;
+     const struct davinci_timer_regs *regs;
+     unsigned int mode;
+     davinci_timer_set_period_func set_period;
+     unsigned int cmp_off;
+};
+
+struct davinci_timer_clockevent {
Quoted 9 lines

drivers/clocksource/timer-davinci.c line 90

Quoted 4 lines
drivers/clocksource/timer-davinci.c new file +4 -0
+     struct clock_event_device dev;
+     unsigned int tick_rate;
+     struct davinci_timer_data timer;
+};

The timer-of API provides the functions and the common structures for the usual operations. Please use them instead of redefining your own structures.

After giving it another thought, I don't think we can use timer-of in this driver easily.

It's meant to work both for board files and device-tree. The solution with the least code duplication is to take the device_node on DT systems and put all relevant properties into the custom structure used by board files users. Timer-of maps the memory, enables the clock and requests interrupts directly from the device_node. I'd have to do the same for board files manually anyway. I think it's better to have a single point of entry for the initialization code.

Even if I were just to reuse the timer-of structures without reusing the actual code - they are still missing certain fields. We're using 32-bit "halves" of timers that are actually 64 bits - the 32-bit control register deals with both by using the same layout of bit fields but shifted. This is what the struct davinci_timer_regs is for. Reusing those structures would also be confusing because of the of_ prefix in the naming.

Quoted 1 line

I'd prefer to leave it as it is. Let me know what you think.

Sorry for not being responsive, I've been OoO last week. Give me some days to digest the emails stack I have in my mailbox and I'll tell you after reviewing how works this timer.

Signature · 5 lines
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
#6 lore raw

Re: [PATCH v4 01/11] clocksource: davinci-timer: new driver

In reply to Bartosz Golaszewski
Quoted 7 lines · Bartosz Golaszewski

From: Bartosz Golaszewski <[email protected]>

Currently the clocksource and clockevent support for davinci platforms lives in mach-davinci. It hard-codes many things, uses global variables, implements functionalities unused by any platform and has code fragments scattered across many (often unrelated) files.

Quoted 7 lines

Implement a new, modern and simplified timer driver and put it into drivers/clocksource. We still need to support legacy board files so export a config structure and a function that allows machine code to register the timer.

We don't bother freeing resources on errors in davinci_timer_register() as the system won't boot without a timer anyway.

Can you give a quick description of the timer hardware and how it works?

Quoted 16 lines
---
 drivers/clocksource/Kconfig         |   5 +
 drivers/clocksource/Makefile        |   1 +
 drivers/clocksource/timer-davinci.c | 438 ++++++++++++++++++++++++++++
 include/clocksource/timer-davinci.h |  44 +++
 4 files changed, 488 insertions(+)
 create mode 100644 drivers/clocksource/timer-davinci.c
 create mode 100644 include/clocksource/timer-davinci.h
drivers/clocksource/Kconfig +0 -0
index 171502a356aa..08b1f539cfc4 100644

drivers/clocksource/Kconfig config BCM_KONA_TIMER · line 46

Quoted 5 lines
drivers/clocksource/Kconfig +2 -0
@@ -42,6 +42,11 @@ config BCM_KONA_TIMER
 	help
 	  Enables the support for the BCM Kona mobile timer driver.
 
+config DAVINCI_TIMER
+	bool "Texas Instruments DaVinci timer driver"

Make the option silent (eg. if COMPILE_TEST)

Quoted 71 lines
drivers/clocksource/Kconfig +3 -0
+	help
+	  Enables the support for the TI DaVinci timer driver.
+
 config DIGICOLOR_TIMER
 	bool "Digicolor timer driver" if COMPILE_TEST
 	select CLKSRC_MMIO
drivers/clocksource/Makefile +1 -0
index be6e0fbc7489..3c73d0e58b45 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_SH_TIMER_TMU)	+= sh_tmu.o
 obj-$(CONFIG_EM_TIMER_STI)	+= em_sti.o
 obj-$(CONFIG_CLKBLD_I8253)	+= i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)	+= mmio.o
+obj-$(CONFIG_DAVINCI_TIMER)	+= timer-davinci.o
 obj-$(CONFIG_DIGICOLOR_TIMER)	+= timer-digicolor.o
 obj-$(CONFIG_OMAP_DM_TIMER)	+= timer-ti-dm.o
 obj-$(CONFIG_DW_APB_TIMER)	+= dw_apb_timer.o
drivers/clocksource/timer-davinci.c new file +47 -0
new file mode 100644
index 000000000000..46dfc4d457fc
@@ -0,0 +1,438 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// TI DaVinci clocksource driver
+//
+// Copyright (C) 2019 Texas Instruments
+// Author: Bartosz Golaszewski <[email protected]>
+// (with some parts adopted from code by Kevin Hilman <[email protected]>)
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+
+#include <clocksource/timer-davinci.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt "\n", __func__
+
+#define DAVINCI_TIMER_REG_TIM12			0x10
+#define DAVINCI_TIMER_REG_TIM34			0x14
+#define DAVINCI_TIMER_REG_PRD12			0x18
+#define DAVINCI_TIMER_REG_PRD34			0x1c
+#define DAVINCI_TIMER_REG_TCR			0x20
+#define DAVINCI_TIMER_REG_TGCR			0x24
+
+#define DAVINCI_TIMER_TIMMODE_MASK		GENMASK(3, 2)
+#define DAVINCI_TIMER_RESET_MASK		GENMASK(1, 0)
+#define DAVINCI_TIMER_TIMMODE_32BIT_UNCHAINED	BIT(2)
+#define DAVINCI_TIMER_UNRESET			GENMASK(1, 0)
+
+/* Shift depends on timer. */
+#define DAVINCI_TIMER_ENAMODE_MASK		GENMASK(1, 0)
+#define DAVINCI_TIMER_ENAMODE_DISABLED		0x00
+#define DAVINCI_TIMER_ENAMODE_ONESHOT		BIT(0)
+#define DAVINCI_TIMER_ENAMODE_PERIODIC		BIT(1)
+
+#define DAVINCI_TIMER_ENAMODE_SHIFT_TIM12	6
+#define DAVINCI_TIMER_ENAMODE_SHIFT_TIM34	22
+
+#define DAVINCI_TIMER_MIN_DELTA			0x01
+#define DAVINCI_TIMER_MAX_DELTA			0xfffffffe
+

drivers/clocksource/timer-davinci.c line 57

Quoted 10 lines
drivers/clocksource/timer-davinci.c new file +10 -0
+#define DAVINCI_TIMER_CLKSRC_BITS		32
+
+#define DAVINCI_TIMER_TGCR_DEFAULT \
+		(DAVINCI_TIMER_TIMMODE_32BIT_UNCHAINED | DAVINCI_TIMER_UNRESET)
+
+enum {
+	DAVINCI_TIMER_MODE_DISABLED = 0,
+	DAVINCI_TIMER_MODE_ONESHOT,
+	DAVINCI_TIMER_MODE_PERIODIC,
+};

This is replicating what is already available. Right after set_periodic or set_oneshot are called, the timer state is changed to respectively CLOCK_EVT_STATE_PERIODIC and CLOCK_EVT_STATE_ONESHOT. So it is useless to define those enum again as what you want is to check the timer mode.

[ ... ]

Quoted 14 lines
drivers/clocksource/timer-davinci.c new file +11 -0
+
+	clocksource = kzalloc(sizeof(*clocksource), GFP_KERNEL);
+	if (!clocksource) {
+		pr_err("Error allocating memory for clocksource data");
+		return -ENOMEM;
+	}
+
+	clocksource->dev.rating = 300;
+	clocksource->dev.read = davinci_timer_clksrc_read;
+	clocksource->dev.mask = CLOCKSOURCE_MASK(DAVINCI_TIMER_CLKSRC_BITS);
+	clocksource->dev.flags = CLOCK_SOURCE_IS_CONTINUOUS;
Quoted 2 lines
Quoted 2 lines

drivers/clocksource/timer-davinci.c line 370

Quoted 3 lines
drivers/clocksource/timer-davinci.c new file +3 -0
+	clocksource->timer.set_period = davinci_timer_set_period_std;
+	clocksource->timer.mode = DAVINCI_TIMER_MODE_PERIODIC;
+	clocksource->timer.base = base;

What for?

<<<

Quoted 5 lines
drivers/clocksource/timer-davinci.c new file +5 -0
+	if (timer_cfg->cmp_off) {
+		clocksource->timer.regs = &davinci_timer_tim12_regs;
+		clocksource->dev.name = "tim12";
+	} else {
+		clocksource->timer.regs = &davinci_timer_tim34_regs;

drivers/clocksource/timer-davinci.c line 386

Quoted 10 lines
drivers/clocksource/timer-davinci.c new file +10 -0
+		clocksource->dev.name = "tim34";
+	}
+
+	rv = request_irq(timer_cfg->irq[DAVINCI_TIMER_CLOCKSOURCE_IRQ].start,
+			 davinci_timer_irq_freerun, IRQF_TIMER,
+			 "free-run counter", clocksource);
+	if (rv) {
+		pr_err("Unable to request the clocksource interrupt");
+		return rv;
+	}

Why do you have to request an interrupt to do nothing? Isn't possible to let the timer run and wrap without generating interrupts?

[ ... ]

Signature · 5 lines
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
#7 lore raw

Re: [PATCH v4 01/11] clocksource: davinci-timer: new driver

pon., 15 kwi 2019 o 14:36 Daniel Lezcano <[email protected]> napisał(a):

Quoted 14 lines · Bartosz Golaszewski
Quoted 12 lines

From: Bartosz Golaszewski <[email protected]>

Currently the clocksource and clockevent support for davinci platforms lives in mach-davinci. It hard-codes many things, uses global variables, implements functionalities unused by any platform and has code fragments scattered across many (often unrelated) files.

Implement a new, modern and simplified timer driver and put it into drivers/clocksource. We still need to support legacy board files so export a config structure and a function that allows machine code to register the timer.

Quoted 5 lines
Quoted 2 lines

We don't bother freeing resources on errors in davinci_timer_register() as the system won't boot without a timer anyway.

Can you give a quick description of the timer hardware and how it works?

Will do.

Quoted 19 lines
Quoted 19 lines
---
 drivers/clocksource/Kconfig         |   5 +
 drivers/clocksource/Makefile        |   1 +
 drivers/clocksource/timer-davinci.c | 438 ++++++++++++++++++++++++++++
 include/clocksource/timer-davinci.h |  44 +++
 4 files changed, 488 insertions(+)
 create mode 100644 drivers/clocksource/timer-davinci.c
 create mode 100644 include/clocksource/timer-davinci.h
drivers/clocksource/Kconfig +0 -0
index 171502a356aa..08b1f539cfc4 100644
@@ -42,6 +42,11 @@ config BCM_KONA_TIMER
      help
        Enables the support for the BCM Kona mobile timer driver.
 
Quoted 5 lines

drivers/clocksource/Kconfig config BCM_KONA_TIMER · line 46

Quoted 2 lines
drivers/clocksource/Kconfig +2 -0
+config DAVINCI_TIMER
+     bool "Texas Instruments DaVinci timer driver"

Make the option silent (eg. if COMPILE_TEST)

Sure, I already did it locally after your last review.

Quoted 78 lines
Quoted 78 lines
drivers/clocksource/Kconfig +3 -0
+     help
+       Enables the support for the TI DaVinci timer driver.
+
 config DIGICOLOR_TIMER
      bool "Digicolor timer driver" if COMPILE_TEST
      select CLKSRC_MMIO
drivers/clocksource/Makefile +1 -0
index be6e0fbc7489..3c73d0e58b45 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_SH_TIMER_TMU)  += sh_tmu.o
 obj-$(CONFIG_EM_TIMER_STI)   += em_sti.o
 obj-$(CONFIG_CLKBLD_I8253)   += i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)    += mmio.o
+obj-$(CONFIG_DAVINCI_TIMER)  += timer-davinci.o
 obj-$(CONFIG_DIGICOLOR_TIMER)        += timer-digicolor.o
 obj-$(CONFIG_OMAP_DM_TIMER)  += timer-ti-dm.o
 obj-$(CONFIG_DW_APB_TIMER)   += dw_apb_timer.o
drivers/clocksource/timer-davinci.c new file +54 -0
new file mode 100644
index 000000000000..46dfc4d457fc
@@ -0,0 +1,438 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// TI DaVinci clocksource driver
+//
+// Copyright (C) 2019 Texas Instruments
+// Author: Bartosz Golaszewski <[email protected]>
+// (with some parts adopted from code by Kevin Hilman <[email protected]>)
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+
+#include <clocksource/timer-davinci.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt "\n", __func__
+
+#define DAVINCI_TIMER_REG_TIM12                      0x10
+#define DAVINCI_TIMER_REG_TIM34                      0x14
+#define DAVINCI_TIMER_REG_PRD12                      0x18
+#define DAVINCI_TIMER_REG_PRD34                      0x1c
+#define DAVINCI_TIMER_REG_TCR                        0x20
+#define DAVINCI_TIMER_REG_TGCR                       0x24
+
+#define DAVINCI_TIMER_TIMMODE_MASK           GENMASK(3, 2)
+#define DAVINCI_TIMER_RESET_MASK             GENMASK(1, 0)
+#define DAVINCI_TIMER_TIMMODE_32BIT_UNCHAINED        BIT(2)
+#define DAVINCI_TIMER_UNRESET                        GENMASK(1, 0)
+
+/* Shift depends on timer. */
+#define DAVINCI_TIMER_ENAMODE_MASK           GENMASK(1, 0)
+#define DAVINCI_TIMER_ENAMODE_DISABLED               0x00
+#define DAVINCI_TIMER_ENAMODE_ONESHOT                BIT(0)
+#define DAVINCI_TIMER_ENAMODE_PERIODIC               BIT(1)
+
+#define DAVINCI_TIMER_ENAMODE_SHIFT_TIM12    6
+#define DAVINCI_TIMER_ENAMODE_SHIFT_TIM34    22
+
+#define DAVINCI_TIMER_MIN_DELTA                      0x01
+#define DAVINCI_TIMER_MAX_DELTA                      0xfffffffe
+
+#define DAVINCI_TIMER_CLKSRC_BITS            32
+
+#define DAVINCI_TIMER_TGCR_DEFAULT \
+             (DAVINCI_TIMER_TIMMODE_32BIT_UNCHAINED | DAVINCI_TIMER_UNRESET)
+
+enum {
+     DAVINCI_TIMER_MODE_DISABLED = 0,
Quoted 9 lines

drivers/clocksource/timer-davinci.c line 57

Quoted 3 lines
drivers/clocksource/timer-davinci.c new file +3 -0
+     DAVINCI_TIMER_MODE_ONESHOT,
+     DAVINCI_TIMER_MODE_PERIODIC,
+};

This is replicating what is already available. Right after set_periodic or set_oneshot are called, the timer state is changed to respectively CLOCK_EVT_STATE_PERIODIC and CLOCK_EVT_STATE_ONESHOT. So it is useless to define those enum again as what you want is to check the timer mode.

I did it like this because I'm reusing the code in davinci_timer_set_period_std() for both clocksource and clockevent timers. If you prefer it be split to reuse the clockevent accessors, I can do this (see below).

Quoted 17 lines

[ ... ]

Quoted 13 lines
drivers/clocksource/timer-davinci.c new file +11 -0
+
+     clocksource = kzalloc(sizeof(*clocksource), GFP_KERNEL);
+     if (!clocksource) {
+             pr_err("Error allocating memory for clocksource data");
+             return -ENOMEM;
+     }
+
+     clocksource->dev.rating = 300;
+     clocksource->dev.read = davinci_timer_clksrc_read;
+     clocksource->dev.mask = CLOCKSOURCE_MASK(DAVINCI_TIMER_CLKSRC_BITS);
+     clocksource->dev.flags = CLOCK_SOURCE_IS_CONTINUOUS;
Quoted 2 lines
Quoted 2 lines
Quoted 6 lines

drivers/clocksource/timer-davinci.c line 370

Quoted 3 lines
drivers/clocksource/timer-davinci.c new file +3 -0
+     clocksource->timer.set_period = davinci_timer_set_period_std;
+     clocksource->timer.mode = DAVINCI_TIMER_MODE_PERIODIC;
+     clocksource->timer.base = base;

What for?

What am I assigning the timer for? In order to call davinci_timer_set_period() on it at the bottom of the init function. I'm not sure if it is a problem you're pointing out, but as I said above - I can configure the clocksource timer by hand in the init function, drop the davinci_timer_clocksource structure and use the clockevent accessors for checking the clock mode if you prefer it that way. Would that be fine?

Quoted 18 lines

<<<

Quoted 5 lines
drivers/clocksource/timer-davinci.c new file +5 -0
+     if (timer_cfg->cmp_off) {
+             clocksource->timer.regs = &davinci_timer_tim12_regs;
+             clocksource->dev.name = "tim12";
+     } else {
+             clocksource->timer.regs = &davinci_timer_tim34_regs;

drivers/clocksource/timer-davinci.c line 386

Quoted 10 lines
drivers/clocksource/timer-davinci.c new file +10 -0
+             clocksource->dev.name = "tim34";
+     }
+
+     rv = request_irq(timer_cfg->irq[DAVINCI_TIMER_CLOCKSOURCE_IRQ].start,
+                      davinci_timer_irq_freerun, IRQF_TIMER,
+                      "free-run counter", clocksource);
+     if (rv) {
+             pr_err("Unable to request the clocksource interrupt");
+             return rv;
+     }
Quoted 3 lines

Why do you have to request an interrupt to do nothing? Isn't possible to let the timer run and wrap without generating interrupts?

Yes it is, but the already existing DT bindings define two interrupts. It's true that nobody uses it, but I thought I'd stick with what was done before. If you prefer that, I can use a single interrupt - and just ignore the second one defined in DT (and also remove it from the config structure for board files).

Thanks,
Bartosz

Quoted 12 lines

[ ... ]

--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

#8 lore raw

Re: [PATCH v4 01/11] clocksource: davinci-timer: new driver

wt., 16 kwi 2019 o 15:44 Bartosz Golaszewski <[email protected]> napisał(a):

Quoted 168 lines

pon., 15 kwi 2019 o 14:36 Daniel Lezcano <[email protected]> napisał(a):

Quoted 14 lines · Bartosz Golaszewski
Quoted 12 lines

From: Bartosz Golaszewski <[email protected]>

Currently the clocksource and clockevent support for davinci platforms lives in mach-davinci. It hard-codes many things, uses global variables, implements functionalities unused by any platform and has code fragments scattered across many (often unrelated) files.

Implement a new, modern and simplified timer driver and put it into drivers/clocksource. We still need to support legacy board files so export a config structure and a function that allows machine code to register the timer.

Quoted 5 lines
Quoted 2 lines

We don't bother freeing resources on errors in davinci_timer_register() as the system won't boot without a timer anyway.

Can you give a quick description of the timer hardware and how it works?

Will do.

Quoted 19 lines
Quoted 19 lines
---
 drivers/clocksource/Kconfig         |   5 +
 drivers/clocksource/Makefile        |   1 +
 drivers/clocksource/timer-davinci.c | 438 ++++++++++++++++++++++++++++
 include/clocksource/timer-davinci.h |  44 +++
 4 files changed, 488 insertions(+)
 create mode 100644 drivers/clocksource/timer-davinci.c
 create mode 100644 include/clocksource/timer-davinci.h
drivers/clocksource/Kconfig +0 -0
index 171502a356aa..08b1f539cfc4 100644
@@ -42,6 +42,11 @@ config BCM_KONA_TIMER
      help
        Enables the support for the BCM Kona mobile timer driver.
 
Quoted 5 lines

drivers/clocksource/Kconfig config BCM_KONA_TIMER · line 46

Quoted 2 lines
drivers/clocksource/Kconfig +2 -0
+config DAVINCI_TIMER
+     bool "Texas Instruments DaVinci timer driver"

Make the option silent (eg. if COMPILE_TEST)

Sure, I already did it locally after your last review.

Quoted 78 lines
Quoted 78 lines
drivers/clocksource/Kconfig +3 -0
+     help
+       Enables the support for the TI DaVinci timer driver.
+
 config DIGICOLOR_TIMER
      bool "Digicolor timer driver" if COMPILE_TEST
      select CLKSRC_MMIO
drivers/clocksource/Makefile +1 -0
index be6e0fbc7489..3c73d0e58b45 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_SH_TIMER_TMU)  += sh_tmu.o
 obj-$(CONFIG_EM_TIMER_STI)   += em_sti.o
 obj-$(CONFIG_CLKBLD_I8253)   += i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)    += mmio.o
+obj-$(CONFIG_DAVINCI_TIMER)  += timer-davinci.o
 obj-$(CONFIG_DIGICOLOR_TIMER)        += timer-digicolor.o
 obj-$(CONFIG_OMAP_DM_TIMER)  += timer-ti-dm.o
 obj-$(CONFIG_DW_APB_TIMER)   += dw_apb_timer.o
drivers/clocksource/timer-davinci.c new file +54 -0
new file mode 100644
index 000000000000..46dfc4d457fc
@@ -0,0 +1,438 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// TI DaVinci clocksource driver
+//
+// Copyright (C) 2019 Texas Instruments
+// Author: Bartosz Golaszewski <[email protected]>
+// (with some parts adopted from code by Kevin Hilman <[email protected]>)
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+
+#include <clocksource/timer-davinci.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt "\n", __func__
+
+#define DAVINCI_TIMER_REG_TIM12                      0x10
+#define DAVINCI_TIMER_REG_TIM34                      0x14
+#define DAVINCI_TIMER_REG_PRD12                      0x18
+#define DAVINCI_TIMER_REG_PRD34                      0x1c
+#define DAVINCI_TIMER_REG_TCR                        0x20
+#define DAVINCI_TIMER_REG_TGCR                       0x24
+
+#define DAVINCI_TIMER_TIMMODE_MASK           GENMASK(3, 2)
+#define DAVINCI_TIMER_RESET_MASK             GENMASK(1, 0)
+#define DAVINCI_TIMER_TIMMODE_32BIT_UNCHAINED        BIT(2)
+#define DAVINCI_TIMER_UNRESET                        GENMASK(1, 0)
+
+/* Shift depends on timer. */
+#define DAVINCI_TIMER_ENAMODE_MASK           GENMASK(1, 0)
+#define DAVINCI_TIMER_ENAMODE_DISABLED               0x00
+#define DAVINCI_TIMER_ENAMODE_ONESHOT                BIT(0)
+#define DAVINCI_TIMER_ENAMODE_PERIODIC               BIT(1)
+
+#define DAVINCI_TIMER_ENAMODE_SHIFT_TIM12    6
+#define DAVINCI_TIMER_ENAMODE_SHIFT_TIM34    22
+
+#define DAVINCI_TIMER_MIN_DELTA                      0x01
+#define DAVINCI_TIMER_MAX_DELTA                      0xfffffffe
+
+#define DAVINCI_TIMER_CLKSRC_BITS            32
+
+#define DAVINCI_TIMER_TGCR_DEFAULT \
+             (DAVINCI_TIMER_TIMMODE_32BIT_UNCHAINED | DAVINCI_TIMER_UNRESET)
+
+enum {
+     DAVINCI_TIMER_MODE_DISABLED = 0,
Quoted 9 lines

drivers/clocksource/timer-davinci.c line 57

Quoted 3 lines
drivers/clocksource/timer-davinci.c new file +3 -0
+     DAVINCI_TIMER_MODE_ONESHOT,
+     DAVINCI_TIMER_MODE_PERIODIC,
+};

This is replicating what is already available. Right after set_periodic or set_oneshot are called, the timer state is changed to respectively CLOCK_EVT_STATE_PERIODIC and CLOCK_EVT_STATE_ONESHOT. So it is useless to define those enum again as what you want is to check the timer mode.

I did it like this because I'm reusing the code in davinci_timer_set_period_std() for both clocksource and clockevent timers. If you prefer it be split to reuse the clockevent accessors, I can do this (see below).

Quoted 17 lines

[ ... ]

Quoted 13 lines
drivers/clocksource/timer-davinci.c new file +11 -0
+
+     clocksource = kzalloc(sizeof(*clocksource), GFP_KERNEL);
+     if (!clocksource) {
+             pr_err("Error allocating memory for clocksource data");
+             return -ENOMEM;
+     }
+
+     clocksource->dev.rating = 300;
+     clocksource->dev.read = davinci_timer_clksrc_read;
+     clocksource->dev.mask = CLOCKSOURCE_MASK(DAVINCI_TIMER_CLKSRC_BITS);
+     clocksource->dev.flags = CLOCK_SOURCE_IS_CONTINUOUS;
Quoted 2 lines
Quoted 2 lines
Quoted 6 lines

drivers/clocksource/timer-davinci.c line 370

Quoted 3 lines
drivers/clocksource/timer-davinci.c new file +3 -0
+     clocksource->timer.set_period = davinci_timer_set_period_std;
+     clocksource->timer.mode = DAVINCI_TIMER_MODE_PERIODIC;
+     clocksource->timer.base = base;

What for?

Quoted 18 lines

What am I assigning the timer for? In order to call davinci_timer_set_period() on it at the bottom of the init function. I'm not sure if it is a problem you're pointing out, but as I said above - I can configure the clocksource timer by hand in the init function, drop the davinci_timer_clocksource structure and use the clockevent accessors for checking the clock mode if you prefer it that way. Would that be fine?

Quoted 10 lines

<<<

Quoted 8 lines
drivers/clocksource/timer-davinci.c new file +8 -0
+     if (timer_cfg->cmp_off) {
+             clocksource->timer.regs = &davinci_timer_tim12_regs;
+             clocksource->dev.name = "tim12";
+     } else {
+             clocksource->timer.regs = &davinci_timer_tim34_regs;
+             clocksource->dev.name = "tim34";
+     }
+

Just to clarify for the above: I'll still need to account for these lines here if I go that way. This again leads to code duplication IMO.

Bart

Quoted 33 lines
Quoted 11 lines

drivers/clocksource/timer-davinci.c line 386

Quoted 7 lines
drivers/clocksource/timer-davinci.c new file +7 -0
+     rv = request_irq(timer_cfg->irq[DAVINCI_TIMER_CLOCKSOURCE_IRQ].start,
+                      davinci_timer_irq_freerun, IRQF_TIMER,
+                      "free-run counter", clocksource);
+     if (rv) {
+             pr_err("Unable to request the clocksource interrupt");
+             return rv;
+     }

Why do you have to request an interrupt to do nothing? Isn't possible to let the timer run and wrap without generating interrupts?

Yes it is, but the already existing DT bindings define two interrupts. It's true that nobody uses it, but I thought I'd stick with what was done before. If you prefer that, I can use a single interrupt - and just ignore the second one defined in DT (and also remove it from the config structure for board files).

Thanks,
Bartosz

Quoted 12 lines

[ ... ]

--
<http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro: <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog

#9 lore raw

Re: [PATCH v4 01/11] clocksource: davinci-timer: new driver

In reply to Bartosz Golaszewski

Hi Bartosz,

Quoted 138 lines · Bartosz Golaszewski

pon., 15 kwi 2019 o 14:36 Daniel Lezcano <[email protected]> napisał(a):

Quoted 14 lines · Bartosz Golaszewski
Quoted 12 lines

From: Bartosz Golaszewski <[email protected]>

Currently the clocksource and clockevent support for davinci platforms lives in mach-davinci. It hard-codes many things, uses global variables, implements functionalities unused by any platform and has code fragments scattered across many (often unrelated) files.

Implement a new, modern and simplified timer driver and put it into drivers/clocksource. We still need to support legacy board files so export a config structure and a function that allows machine code to register the timer.

Quoted 5 lines
Quoted 2 lines

We don't bother freeing resources on errors in davinci_timer_register() as the system won't boot without a timer anyway.

Can you give a quick description of the timer hardware and how it works?

Will do.

Quoted 19 lines
Quoted 19 lines
---
 drivers/clocksource/Kconfig         |   5 +
 drivers/clocksource/Makefile        |   1 +
 drivers/clocksource/timer-davinci.c | 438 ++++++++++++++++++++++++++++
 include/clocksource/timer-davinci.h |  44 +++
 4 files changed, 488 insertions(+)
 create mode 100644 drivers/clocksource/timer-davinci.c
 create mode 100644 include/clocksource/timer-davinci.h
drivers/clocksource/Kconfig +0 -0
index 171502a356aa..08b1f539cfc4 100644
@@ -42,6 +42,11 @@ config BCM_KONA_TIMER
      help
        Enables the support for the BCM Kona mobile timer driver.
 
Quoted 5 lines

drivers/clocksource/Kconfig config BCM_KONA_TIMER · line 46

Quoted 2 lines
drivers/clocksource/Kconfig +2 -0
+config DAVINCI_TIMER
+     bool "Texas Instruments DaVinci timer driver"

Make the option silent (eg. if COMPILE_TEST)

Sure, I already did it locally after your last review.

Quoted 78 lines
Quoted 78 lines
drivers/clocksource/Kconfig +3 -0
+     help
+       Enables the support for the TI DaVinci timer driver.
+
 config DIGICOLOR_TIMER
      bool "Digicolor timer driver" if COMPILE_TEST
      select CLKSRC_MMIO
drivers/clocksource/Makefile +1 -0
index be6e0fbc7489..3c73d0e58b45 100644
@@ -15,6 +15,7 @@ obj-$(CONFIG_SH_TIMER_TMU)  += sh_tmu.o
 obj-$(CONFIG_EM_TIMER_STI)   += em_sti.o
 obj-$(CONFIG_CLKBLD_I8253)   += i8253.o
 obj-$(CONFIG_CLKSRC_MMIO)    += mmio.o
+obj-$(CONFIG_DAVINCI_TIMER)  += timer-davinci.o
 obj-$(CONFIG_DIGICOLOR_TIMER)        += timer-digicolor.o
 obj-$(CONFIG_OMAP_DM_TIMER)  += timer-ti-dm.o
 obj-$(CONFIG_DW_APB_TIMER)   += dw_apb_timer.o
drivers/clocksource/timer-davinci.c new file +54 -0
new file mode 100644
index 000000000000..46dfc4d457fc
@@ -0,0 +1,438 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// TI DaVinci clocksource driver
+//
+// Copyright (C) 2019 Texas Instruments
+// Author: Bartosz Golaszewski <[email protected]>
+// (with some parts adopted from code by Kevin Hilman <[email protected]>)
+
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/of_address.h>
+#include <linux/of_irq.h>
+#include <linux/sched_clock.h>
+
+#include <clocksource/timer-davinci.h>
+
+#undef pr_fmt
+#define pr_fmt(fmt) "%s: " fmt "\n", __func__
+
+#define DAVINCI_TIMER_REG_TIM12                      0x10
+#define DAVINCI_TIMER_REG_TIM34                      0x14
+#define DAVINCI_TIMER_REG_PRD12                      0x18
+#define DAVINCI_TIMER_REG_PRD34                      0x1c
+#define DAVINCI_TIMER_REG_TCR                        0x20
+#define DAVINCI_TIMER_REG_TGCR                       0x24
+
+#define DAVINCI_TIMER_TIMMODE_MASK           GENMASK(3, 2)
+#define DAVINCI_TIMER_RESET_MASK             GENMASK(1, 0)
+#define DAVINCI_TIMER_TIMMODE_32BIT_UNCHAINED        BIT(2)
+#define DAVINCI_TIMER_UNRESET                        GENMASK(1, 0)
+
+/* Shift depends on timer. */
+#define DAVINCI_TIMER_ENAMODE_MASK           GENMASK(1, 0)
+#define DAVINCI_TIMER_ENAMODE_DISABLED               0x00
+#define DAVINCI_TIMER_ENAMODE_ONESHOT                BIT(0)
+#define DAVINCI_TIMER_ENAMODE_PERIODIC               BIT(1)
+
+#define DAVINCI_TIMER_ENAMODE_SHIFT_TIM12    6
+#define DAVINCI_TIMER_ENAMODE_SHIFT_TIM34    22
+
+#define DAVINCI_TIMER_MIN_DELTA                      0x01
+#define DAVINCI_TIMER_MAX_DELTA                      0xfffffffe
+
+#define DAVINCI_TIMER_CLKSRC_BITS            32
+
+#define DAVINCI_TIMER_TGCR_DEFAULT \
+             (DAVINCI_TIMER_TIMMODE_32BIT_UNCHAINED | DAVINCI_TIMER_UNRESET)
+
+enum {
+     DAVINCI_TIMER_MODE_DISABLED = 0,
Quoted 9 lines

drivers/clocksource/timer-davinci.c line 57

Quoted 3 lines
drivers/clocksource/timer-davinci.c new file +3 -0
+     DAVINCI_TIMER_MODE_ONESHOT,
+     DAVINCI_TIMER_MODE_PERIODIC,
+};

This is replicating what is already available. Right after set_periodic or set_oneshot are called, the timer state is changed to respectively CLOCK_EVT_STATE_PERIODIC and CLOCK_EVT_STATE_ONESHOT. So it is useless to define those enum again as what you want is to check the timer mode.

Quoted 4 lines

I did it like this because I'm reusing the code in davinci_timer_set_period_std() for both clocksource and clockevent timers. If you prefer it be split to reuse the clockevent accessors, I can do this (see below).

I see. It is too much complicated for the purpose. The values are computed around every time with this flag. At the first glance, the driver can be simpler.

Please do the following rework:

1. One patch providing the clockevents code only

2. One patch providing the clocksource code only and taking account the comments below.

In order to not review the entire series every time, just send those two patches until we agree on it and then the rest of the series.

The computation in the function davinci_timer_set_period_std() can be replaced with constant put in the field instead of bit shifting everytime.

Quoted 23 lines
Quoted 16 lines

[ ... ]

Quoted 13 lines
drivers/clocksource/timer-davinci.c new file +11 -0
+
+     clocksource = kzalloc(sizeof(*clocksource), GFP_KERNEL);
+     if (!clocksource) {
+             pr_err("Error allocating memory for clocksource data");
+             return -ENOMEM;
+     }
+
+     clocksource->dev.rating = 300;
+     clocksource->dev.read = davinci_timer_clksrc_read;
+     clocksource->dev.mask = CLOCKSOURCE_MASK(DAVINCI_TIMER_CLKSRC_BITS);
+     clocksource->dev.flags = CLOCK_SOURCE_IS_CONTINUOUS;
Quoted 2 lines
Quoted 2 lines
Quoted 6 lines

drivers/clocksource/timer-davinci.c line 370

Quoted 3 lines
drivers/clocksource/timer-davinci.c new file +3 -0
+     clocksource->timer.set_period = davinci_timer_set_period_std;
+     clocksource->timer.mode = DAVINCI_TIMER_MODE_PERIODIC;
+     clocksource->timer.base = base;

What for?

Quoted 7 lines

What am I assigning the timer for? In order to call davinci_timer_set_period() on it at the bottom of the init function. I'm not sure if it is a problem you're pointing out, but as I said above - I can configure the clocksource timer by hand in the init function, drop the davinci_timer_clocksource structure and use the clockevent accessors for checking the clock mode if you prefer it that way. Would that be fine?

Yes but without checking the clock mode.

Quoted 20 lines
Quoted 16 lines
Quoted 5 lines
drivers/clocksource/timer-davinci.c new file +5 -0
+     if (timer_cfg->cmp_off) {
+             clocksource->timer.regs = &davinci_timer_tim12_regs;
+             clocksource->dev.name = "tim12";
+     } else {
+             clocksource->timer.regs = &davinci_timer_tim34_regs;

drivers/clocksource/timer-davinci.c line 386

Quoted 10 lines
drivers/clocksource/timer-davinci.c new file +10 -0
+             clocksource->dev.name = "tim34";
+     }
+
+     rv = request_irq(timer_cfg->irq[DAVINCI_TIMER_CLOCKSOURCE_IRQ].start,
+                      davinci_timer_irq_freerun, IRQF_TIMER,
+                      "free-run counter", clocksource);
+     if (rv) {
+             pr_err("Unable to request the clocksource interrupt");
+             return rv;
+     }
Quoted 3 lines

Why do you have to request an interrupt to do nothing? Isn't possible to let the timer run and wrap without generating interrupts?

Quoted 5 lines

Yes it is, but the already existing DT bindings define two interrupts. It's true that nobody uses it, but I thought I'd stick with what was done before. If you prefer that, I can use a single interrupt - and just ignore the second one defined in DT (and also remove it from the config structure for board files).

Yes please, remove the interrupt handling for the clocksource but keep in the config structure the interrupt in case we want in the future swap the clocksource and the clockevent.

Signature · 5 lines
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog
#10 lore raw

PATCH v4 2/11 ARM: davinci: enable the clocksource driver for DT mode

In reply to Bartosz Golaszewski

From: Bartosz Golaszewski <[email protected]>

Switch all davinci boards supporting device tree to using the new clocksource driver: remove the previous OF_TIMER_DECLARE() from mach-davinci and select davinci-timer for ARCH_DAVINCI.

---
 arch/arm/Kconfig             |  1 +
 arch/arm/mach-davinci/time.c | 14 --------------
 2 files changed, 1 insertion(+), 14 deletions(-)
arch/arm/Kconfig +1 -0
index 054ead960f98..f893798e13d3 100644
@@ -588,6 +588,7 @@ config ARCH_DAVINCI
 	select ARCH_HAS_HOLES_MEMORYMODEL
 	select COMMON_CLK
 	select CPU_ARM926T
+	select DAVINCI_TIMER
 	select GENERIC_ALLOCATOR
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_IRQ_CHIP
arch/arm/mach-davinci/time.c +0 -14
index 5a6de5368ab0..740410a3bb6a 100644
@@ -398,17 +398,3 @@ void __init davinci_timer_init(struct clk *timer_clk)
 	for (i=0; i< ARRAY_SIZE(timers); i++)
 		timer32_config(&timers[i]);
 }
-
-static int __init of_davinci_timer_init(struct device_node *np)
-{
-	struct clk *clk;
-
-	clk = of_clk_get(np, 0);
-	if (IS_ERR(clk))
-		return PTR_ERR(clk);
-
-	davinci_timer_init(clk);
-
-	return 0;
-}
-TIMER_OF_DECLARE(davinci_timer, "ti,da830-timer", of_davinci_timer_init);
Signature · 1 line
2.20.1
#11 lore raw

PATCH v4 3/11 ARM: davinci: WARN_ON() if clk_get() fails

In reply to Bartosz Golaszewski

From: Bartosz Golaszewski <[email protected]>

Currently the timer code checks if the clock pointer passed to it is good (!IS_ERR(clk)). The new clocksource driver expects the clock to be functional and doesn't perform any checks so emit a warning if clk_get() fails. Apply this to all davinci platforms.

---
 arch/arm/mach-davinci/da830.c  | 4 ++++
 arch/arm/mach-davinci/da850.c  | 4 ++++
 arch/arm/mach-davinci/dm355.c  | 4 ++++
 arch/arm/mach-davinci/dm365.c  | 4 ++++
 arch/arm/mach-davinci/dm644x.c | 4 ++++
 arch/arm/mach-davinci/dm646x.c | 4 ++++
 6 files changed, 24 insertions(+)
arch/arm/mach-davinci/da830.c +4 -0
index 63511f638ce4..d242ce06f7e5 100644
@@ -750,6 +750,10 @@ void __init da830_init_time(void)
 	da830_pll_init(NULL, pll, NULL);
 
 	clk = clk_get(NULL, "timer0");
+	if (WARN_ON(IS_ERR(clk))) {
+		pr_err("Unable to get the timer clock\n");
+		return;
+	}
 
 	davinci_timer_init(clk);
 }
arch/arm/mach-davinci/da850.c +4 -0
index 67ab71ba3ad3..72d64d39d42a 100644
@@ -680,6 +680,10 @@ void __init da850_init_time(void)
 	da850_pll0_init(NULL, pll0, cfgchip);
 
 	clk = clk_get(NULL, "timer0");
+	if (WARN_ON(IS_ERR(clk))) {
+		pr_err("Unable to get the timer clock\n");
+		return;
+	}
 
 	davinci_timer_init(clk);
 }
arch/arm/mach-davinci/dm355.c +4 -0
index 4a482445b9a2..57c5a660758e 100644
@@ -742,6 +742,10 @@ void __init dm355_init_time(void)
 	dm355_psc_init(NULL, psc);
 
 	clk = clk_get(NULL, "timer0");
+	if (WARN_ON(IS_ERR(clk))) {
+		pr_err("Unable to get the timer clock\n");
+		return;
+	}
 
 	davinci_timer_init(clk);
 }
arch/arm/mach-davinci/dm365.c +4 -0
index 8e0a77315add..1d82bb630d11 100644
@@ -783,6 +783,10 @@ void __init dm365_init_time(void)
 	dm365_psc_init(NULL, psc);
 
 	clk = clk_get(NULL, "timer0");
+	if (WARN_ON(IS_ERR(clk))) {
+		pr_err("Unable to get the timer clock\n");
+		return;
+	}
 
 	davinci_timer_init(clk);
 }
arch/arm/mach-davinci/dm644x.c +4 -0
index cecc7ceb8d34..2b0e921aa755 100644
@@ -678,6 +678,10 @@ void __init dm644x_init_time(void)
 	dm644x_psc_init(NULL, psc);
 
 	clk = clk_get(NULL, "timer0");
+	if (WARN_ON(IS_ERR(clk))) {
+		pr_err("Unable to get the timer clock\n");
+		return;
+	}
 
 	davinci_timer_init(clk);
 }
arch/arm/mach-davinci/dm646x.c +4 -0
index f33392f77a03..7e5af984ed9f 100644
@@ -662,6 +662,10 @@ void __init dm646x_init_time(unsigned long ref_clk_rate,
 	dm646x_psc_init(NULL, psc);
 
 	clk = clk_get(NULL, "timer0");
+	if (WARN_ON(IS_ERR(clk))) {
+		pr_err("Unable to get the timer clock\n");
+		return;
+	}
 
 	davinci_timer_init(clk);
 }
Signature · 7 lines
2.20.1


_______________________________________________
linux-arm-kernel mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
#12 lore raw

PATCH v4 4/11 ARM: davinci: da850: switch to using the clocksource driver

In reply to Bartosz Golaszewski

From: Bartosz Golaszewski <[email protected]>

We now have a proper clocksource driver for davinci. Switch the da850 platform to using it.

---
 arch/arm/mach-davinci/da850.c | 46 ++++++++++-------------------------
 1 file changed, 13 insertions(+), 33 deletions(-)
arch/arm/mach-davinci/da850.c +13 -33
index 72d64d39d42a..4e18bdf05ac4 100644
@@ -34,7 +34,8 @@
 #include <mach/cputype.h>
 #include <mach/da8xx.h>
 #include <mach/pm.h>
-#include <mach/time.h>
+
+#include <clocksource/timer-davinci.h>
 
 #include "irqs.h"
 #include "mux.h"
@@ -332,38 +333,16 @@ static struct davinci_id da850_ids[] = {
 	},
 };
 
-static struct davinci_timer_instance da850_timer_instance[4] = {
-	{
-		.base		= DA8XX_TIMER64P0_BASE,
-		.bottom_irq	= DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_0),
-		.top_irq	= DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_0),
-	},
-	{
-		.base		= DA8XX_TIMER64P1_BASE,
-		.bottom_irq	= DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_1),
-		.top_irq	= DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_1),
-	},
-	{
-		.base		= DA850_TIMER64P2_BASE,
-		.bottom_irq	= DAVINCI_INTC_IRQ(IRQ_DA850_TINT12_2),
-		.top_irq	= DAVINCI_INTC_IRQ(IRQ_DA850_TINT34_2),
-	},
-	{
-		.base		= DA850_TIMER64P3_BASE,
-		.bottom_irq	= DAVINCI_INTC_IRQ(IRQ_DA850_TINT12_3),
-		.top_irq	= DAVINCI_INTC_IRQ(IRQ_DA850_TINT34_3),
-	},
-};
-
 /*
- * T0_BOT: Timer 0, bottom		: Used for clock_event
- * T0_TOP: Timer 0, top			: Used for clocksource
- * T1_BOT, T1_TOP: Timer 1, bottom & top: Used for watchdog timer
+ * Bottom half of timer 0 is used for clock_event, top half for
+ * clocksource.
  */
-static struct davinci_timer_info da850_timer_info = {
-	.timers		= da850_timer_instance,
-	.clockevent_id	= T0_BOT,
-	.clocksource_id	= T0_TOP,
+static const struct davinci_timer_cfg da850_timer_cfg = {
+	.reg = DEFINE_RES_IO(DA8XX_TIMER64P0_BASE, SZ_4K),
+	.irq = {
+		DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_0)),
+		DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_0)),
+	},
 };
 
 #ifdef CONFIG_CPU_FREQ
@@ -634,7 +613,6 @@ static const struct davinci_soc_info davinci_soc_info_da850 = {
 	.pinmux_base		= DA8XX_SYSCFG0_BASE + 0x120,
 	.pinmux_pins		= da850_pins,
 	.pinmux_pins_num	= ARRAY_SIZE(da850_pins),
-	.timer_info		= &da850_timer_info,
 	.emac_pdata		= &da8xx_emac_pdata,
 	.sram_dma		= DA8XX_SHARED_RAM_BASE,
 	.sram_len		= SZ_128K,
@@ -671,6 +649,7 @@ void __init da850_init_time(void)
 	void __iomem *pll0;
 	struct regmap *cfgchip;
 	struct clk *clk;
+	int rv;
 
 	clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DA850_REF_FREQ);
 
@@ -685,7 +664,8 @@ void __init da850_init_time(void)
 		return;
 	}
 
-	davinci_timer_init(clk);
+	rv = davinci_timer_register(clk, &da850_timer_cfg);
+	WARN(rv, "Unable to register the timer: %d\n", rv);
 }
 
 static struct resource da850_pll1_resources[] = {
Signature · 1 line
2.20.1
#13 lore raw

PATCH v4 5/11 ARM: davinci: da830: switch to using the clocksource driver

In reply to Bartosz Golaszewski

From: Bartosz Golaszewski <[email protected]>

We now have a proper clocksource driver for davinci. Switch the da830 platform to using it.

---
 arch/arm/mach-davinci/da830.c | 41 ++++++++++++-----------------------
 1 file changed, 14 insertions(+), 27 deletions(-)
arch/arm/mach-davinci/da830.c +14 -27
index d242ce06f7e5..3b2c9454828c 100644
@@ -20,7 +20,8 @@
 #include <mach/common.h>
 #include <mach/cputype.h>
 #include <mach/da8xx.h>
-#include <mach/time.h>
+
+#include <clocksource/timer-davinci.h>
 
 #include "irqs.h"
 #include "mux.h"
@@ -675,32 +676,17 @@ int __init da830_register_gpio(void)
 	return da8xx_register_gpio(&da830_gpio_platform_data);
 }
 
-static struct davinci_timer_instance da830_timer_instance[2] = {
-	{
-		.base		= DA8XX_TIMER64P0_BASE,
-		.bottom_irq	= DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_0),
-		.top_irq	= DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_0),
-		.cmp_off	= DA830_CMP12_0,
-		.cmp_irq	= DAVINCI_INTC_IRQ(IRQ_DA830_T12CMPINT0_0),
-	},
-	{
-		.base		= DA8XX_TIMER64P1_BASE,
-		.bottom_irq	= DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_1),
-		.top_irq	= DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT34_1),
-		.cmp_off	= DA830_CMP12_0,
-		.cmp_irq	= DAVINCI_INTC_IRQ(IRQ_DA830_T12CMPINT0_1),
-	},
-};
-
 /*
- * T0_BOT: Timer 0, bottom		: Used for clock_event & clocksource
- * T0_TOP: Timer 0, top			: Used by DSP
- * T1_BOT, T1_TOP: Timer 1, bottom & top: Used for watchdog timer
+ * Bottom half of timer0 is used both for clock even and clocksource.
+ * Top half is used by DSP.
  */
-static struct davinci_timer_info da830_timer_info = {
-	.timers		= da830_timer_instance,
-	.clockevent_id	= T0_BOT,
-	.clocksource_id	= T0_BOT,
+static const struct davinci_timer_cfg da830_timer_cfg = {
+	.reg = DEFINE_RES_IO(DA8XX_TIMER64P0_BASE, SZ_4K),
+	.irq = {
+		DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_DA830_T12CMPINT0_0)),
+		DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_DA8XX_TINT12_0)),
+	},
+	.cmp_off = DA830_CMP12_0,
 };
 
 static const struct davinci_soc_info davinci_soc_info_da830 = {
@@ -712,7 +698,6 @@ static const struct davinci_soc_info davinci_soc_info_da830 = {
 	.pinmux_base		= DA8XX_SYSCFG0_BASE + 0x120,
 	.pinmux_pins		= da830_pins,
 	.pinmux_pins_num	= ARRAY_SIZE(da830_pins),
-	.timer_info		= &da830_timer_info,
 	.emac_pdata		= &da8xx_emac_pdata,
 };
 
@@ -742,6 +727,7 @@ void __init da830_init_time(void)
 {
 	void __iomem *pll;
 	struct clk *clk;
+	int rv;
 
 	clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DA830_REF_FREQ);
 
@@ -755,7 +741,8 @@ void __init da830_init_time(void)
 		return;
 	}
 
-	davinci_timer_init(clk);
+	rv = davinci_timer_register(clk, &da830_timer_cfg);
+	WARN(rv, "Unable to register the timer: %d\n", rv);
 }
 
 static struct resource da830_psc0_resources[] = {
Signature · 1 line
2.20.1
#14 lore raw

PATCH v4 6/11 ARM: davinci: move timer definitions to davinci.h

In reply to Bartosz Golaszewski

From: Bartosz Golaszewski <[email protected]>

Boards from the dm* family rely on register offset definitions from arch/arm/mach-davinci/include/mach/time.h. We'll be removing this file soon, so move the required defines to davinci.h where the rest of such constants live.

---
 arch/arm/mach-davinci/davinci.h           | 3 +++
 arch/arm/mach-davinci/include/mach/time.h | 2 --
 2 files changed, 3 insertions(+), 2 deletions(-)
arch/arm/mach-davinci/davinci.h +3 -0
index 56c1835c42e5..208d7a4d3597 100644
@@ -60,6 +60,9 @@ void davinci_map_sysmod(void);
 #define DAVINCI_GPIO_BASE 0x01C67000
 int davinci_gpio_register(struct resource *res, int size, void *pdata);
 
+#define DAVINCI_TIMER0_BASE		(IO_PHYS + 0x21400)
+#define DAVINCI_WDOG_BASE		(IO_PHYS + 0x21C00)
+
 /* DM355 base addresses */
 #define DM355_ASYNC_EMIF_CONTROL_BASE	0x01e10000
 #define DM355_ASYNC_EMIF_DATA_CE0_BASE	0x02000000
arch/arm/mach-davinci/include/mach/time.h +0 -2
index 1c971d8d8ba8..ba913736990f 100644
@@ -11,9 +11,7 @@
 #ifndef __ARCH_ARM_MACH_DAVINCI_TIME_H
 #define __ARCH_ARM_MACH_DAVINCI_TIME_H
 
-#define DAVINCI_TIMER0_BASE		(IO_PHYS + 0x21400)
 #define DAVINCI_TIMER1_BASE		(IO_PHYS + 0x21800)
-#define DAVINCI_WDOG_BASE		(IO_PHYS + 0x21C00)
 
 enum {
 	T0_BOT,
Signature · 1 line
2.20.1
#15 lore raw

PATCH v4 7/11 ARM: davinci: dm355: switch to using the clocksource driver

In reply to Bartosz Golaszewski

From: Bartosz Golaszewski <[email protected]>

We now have a proper clocksource driver for davinci. Switch the dm355 platform to using it.

---
 arch/arm/mach-davinci/dm355.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)
arch/arm/mach-davinci/dm355.c +13 -11
index 57c5a660758e..d871172f74c2 100644
@@ -29,7 +29,8 @@
 #include <mach/cputype.h>
 #include <mach/mux.h>
 #include <mach/serial.h>
-#include <mach/time.h>
+
+#include <clocksource/timer-davinci.h>
 
 #include "asp.h"
 #include "davinci.h"
@@ -619,15 +620,15 @@ static struct davinci_id dm355_ids[] = {
 };
 
 /*
- * T0_BOT: Timer 0, bottom:  clockevent source for hrtimers
- * T0_TOP: Timer 0, top   :  clocksource for generic timekeeping
- * T1_BOT: Timer 1, bottom:  (used by DSP in TI DSPLink code)
- * T1_TOP: Timer 1, top   :  <unused>
+ * Bottom half of timer0 is used for clockevent, top half is used for
+ * clocksource.
  */
-static struct davinci_timer_info dm355_timer_info = {
-	.timers		= davinci_timer_instance,
-	.clockevent_id	= T0_BOT,
-	.clocksource_id	= T0_TOP,
+static const struct davinci_timer_cfg dm355_timer_cfg = {
+	.reg = DEFINE_RES_IO(DAVINCI_TIMER0_BASE, SZ_4K),
+	.irq = {
+		DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT12)),
+		DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT34)),
+	},
 };
 
 static struct plat_serial8250_port dm355_serial0_platform_data[] = {
@@ -705,7 +706,6 @@ static const struct davinci_soc_info davinci_soc_info_dm355 = {
 	.pinmux_base		= DAVINCI_SYSTEM_MODULE_BASE,
 	.pinmux_pins		= dm355_pins,
 	.pinmux_pins_num	= ARRAY_SIZE(dm355_pins),
-	.timer_info		= &dm355_timer_info,
 	.sram_dma		= 0x00010000,
 	.sram_len		= SZ_32K,
 };
@@ -732,6 +732,7 @@ void __init dm355_init_time(void)
 {
 	void __iomem *pll1, *psc;
 	struct clk *clk;
+	int rv;
 
 	clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DM355_REF_FREQ);
 
@@ -747,7 +748,8 @@ void __init dm355_init_time(void)
 		return;
 	}
 
-	davinci_timer_init(clk);
+	rv = davinci_timer_register(clk, &dm355_timer_cfg);
+	WARN(rv, "Unable to register the timer: %d\n", rv);
 }
 
 static struct resource dm355_pll2_resources[] = {
Signature · 1 line
2.20.1
#16 lore raw

PATCH v4 8/11 ARM: davinci: dm365: switch to using the clocksource driver

In reply to Bartosz Golaszewski

From: Bartosz Golaszewski <[email protected]>

We now have a proper clocksource driver for davinci. Switch the dm365 platform to using it.

---
 arch/arm/mach-davinci/dm365.c | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)
arch/arm/mach-davinci/dm365.c +15 -7
index 1d82bb630d11..5e93e0b6410b 100644
@@ -34,7 +34,8 @@
 #include <mach/cputype.h>
 #include <mach/mux.h>
 #include <mach/serial.h>
-#include <mach/time.h>
+
+#include <clocksource/timer-davinci.h>
 
 #include "asp.h"
 #include "davinci.h"
@@ -659,10 +660,16 @@ static struct davinci_id dm365_ids[] = {
 	},
 };
 
-static struct davinci_timer_info dm365_timer_info = {
-	.timers		= davinci_timer_instance,
-	.clockevent_id	= T0_BOT,
-	.clocksource_id	= T0_TOP,
+/*
+ * Bottom half of timer0 is used for clockevent, top half is used for
+ * clocksource.
+ */
+static const struct davinci_timer_cfg dm365_timer_cfg = {
+	.reg = DEFINE_RES_IO(DAVINCI_TIMER0_BASE, SZ_4K),
+	.irq = {
+		DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT12)),
+		DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT34)),
+	},
 };
 
 #define DM365_UART1_BASE	(IO_PHYS + 0x106000)
@@ -722,7 +729,6 @@ static const struct davinci_soc_info davinci_soc_info_dm365 = {
 	.pinmux_base		= DAVINCI_SYSTEM_MODULE_BASE,
 	.pinmux_pins		= dm365_pins,
 	.pinmux_pins_num	= ARRAY_SIZE(dm365_pins),
-	.timer_info		= &dm365_timer_info,
 	.emac_pdata		= &dm365_emac_pdata,
 	.sram_dma		= 0x00010000,
 	.sram_len		= SZ_32K,
@@ -770,6 +776,7 @@ void __init dm365_init_time(void)
 {
 	void __iomem *pll1, *pll2, *psc;
 	struct clk *clk;
+	int rv;
 
 	clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DM365_REF_FREQ);
 
@@ -788,7 +795,8 @@ void __init dm365_init_time(void)
 		return;
 	}
 
-	davinci_timer_init(clk);
+	rv = davinci_timer_register(clk, &dm365_timer_cfg);
+	WARN(rv, "Unable to register the timer: %d\n", rv);
 }
 
 void __init dm365_register_clocks(void)
Signature · 1 line
2.20.1
#17 lore raw

PATCH v4 9/11 ARM: davinci: dm644x: switch to using the clocksource driver

In reply to Bartosz Golaszewski

From: Bartosz Golaszewski <[email protected]>

We now have a proper clocksource driver for davinci. Switch the dm644x platform to using it.

---
 arch/arm/mach-davinci/dm644x.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)
arch/arm/mach-davinci/dm644x.c +13 -11
index 2b0e921aa755..9f7c348d8efe 100644
@@ -26,7 +26,8 @@
 #include <mach/cputype.h>
 #include <mach/mux.h>
 #include <mach/serial.h>
-#include <mach/time.h>
+
+#include <clocksource/timer-davinci.h>
 
 #include "asp.h"
 #include "davinci.h"
@@ -560,15 +561,15 @@ static struct davinci_id dm644x_ids[] = {
 };
 
 /*
- * T0_BOT: Timer 0, bottom:  clockevent source for hrtimers
- * T0_TOP: Timer 0, top   :  clocksource for generic timekeeping
- * T1_BOT: Timer 1, bottom:  (used by DSP in TI DSPLink code)
- * T1_TOP: Timer 1, top   :  <unused>
+ * Bottom half of timer0 is used for clockevent, top half is used for
+ * clocksource.
  */
-static struct davinci_timer_info dm644x_timer_info = {
-	.timers		= davinci_timer_instance,
-	.clockevent_id	= T0_BOT,
-	.clocksource_id	= T0_TOP,
+static const struct davinci_timer_cfg dm644x_timer_cfg = {
+	.reg = DEFINE_RES_IO(DAVINCI_TIMER0_BASE, SZ_4K),
+	.irq = {
+		DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT12)),
+		DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT34)),
+	},
 };
 
 static struct plat_serial8250_port dm644x_serial0_platform_data[] = {
@@ -646,7 +647,6 @@ static const struct davinci_soc_info davinci_soc_info_dm644x = {
 	.pinmux_base		= DAVINCI_SYSTEM_MODULE_BASE,
 	.pinmux_pins		= dm644x_pins,
 	.pinmux_pins_num	= ARRAY_SIZE(dm644x_pins),
-	.timer_info		= &dm644x_timer_info,
 	.emac_pdata		= &dm644x_emac_pdata,
 	.sram_dma		= 0x00008000,
 	.sram_len		= SZ_16K,
@@ -668,6 +668,7 @@ void __init dm644x_init_time(void)
 {
 	void __iomem *pll1, *psc;
 	struct clk *clk;
+	int rv;
 
 	clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, DM644X_REF_FREQ);
 
@@ -683,7 +684,8 @@ void __init dm644x_init_time(void)
 		return;
 	}
 
-	davinci_timer_init(clk);
+	rv = davinci_timer_register(clk, &dm644x_timer_cfg);
+	WARN(rv, "Unable to register the timer: %d\n", rv);
 }
 
 static struct resource dm644x_pll2_resources[] = {
Signature · 1 line
2.20.1
#18 lore raw

PATCH v4 10/11 ARM: davinci: dm646x: switch to using the clocksource driver

In reply to Bartosz Golaszewski

From: Bartosz Golaszewski <[email protected]>

We now have a proper clocksource driver for davinci. Switch the dm646x platform to using it.

---
 arch/arm/mach-davinci/dm646x.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)
arch/arm/mach-davinci/dm646x.c +13 -11
index 7e5af984ed9f..281e778ba19e 100644
@@ -27,7 +27,8 @@
 #include <mach/cputype.h>
 #include <mach/mux.h>
 #include <mach/serial.h>
-#include <mach/time.h>
+
+#include <clocksource/timer-davinci.h>
 
 #include "asp.h"
 #include "davinci.h"
@@ -500,15 +501,15 @@ static struct davinci_id dm646x_ids[] = {
 };
 
 /*
- * T0_BOT: Timer 0, bottom:  clockevent source for hrtimers
- * T0_TOP: Timer 0, top   :  clocksource for generic timekeeping
- * T1_BOT: Timer 1, bottom:  (used by DSP in TI DSPLink code)
- * T1_TOP: Timer 1, top   :  <unused>
+ * Bottom half of timer0 is used for clockevent, top half is used for
+ * clocksource.
  */
-static struct davinci_timer_info dm646x_timer_info = {
-	.timers		= davinci_timer_instance,
-	.clockevent_id	= T0_BOT,
-	.clocksource_id	= T0_TOP,
+static const struct davinci_timer_cfg dm646x_timer_cfg = {
+	.reg = DEFINE_RES_IO(DAVINCI_TIMER0_BASE, SZ_4K),
+	.irq = {
+		DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT12)),
+		DEFINE_RES_IRQ(DAVINCI_INTC_IRQ(IRQ_TINT0_TINT34)),
+	},
 };
 
 static struct plat_serial8250_port dm646x_serial0_platform_data[] = {
@@ -586,7 +587,6 @@ static const struct davinci_soc_info davinci_soc_info_dm646x = {
 	.pinmux_base		= DAVINCI_SYSTEM_MODULE_BASE,
 	.pinmux_pins		= dm646x_pins,
 	.pinmux_pins_num	= ARRAY_SIZE(dm646x_pins),
-	.timer_info		= &dm646x_timer_info,
 	.emac_pdata		= &dm646x_emac_pdata,
 	.sram_dma		= 0x10010000,
 	.sram_len		= SZ_32K,
@@ -651,6 +651,7 @@ void __init dm646x_init_time(unsigned long ref_clk_rate,
 {
 	void __iomem *pll1, *psc;
 	struct clk *clk;
+	int rv;
 
 	clk_register_fixed_rate(NULL, "ref_clk", NULL, 0, ref_clk_rate);
 	clk_register_fixed_rate(NULL, "aux_clkin", NULL, 0, aux_clkin_rate);
@@ -667,7 +668,8 @@ void __init dm646x_init_time(unsigned long ref_clk_rate,
 		return;
 	}
 
-	davinci_timer_init(clk);
+	rv = davinci_timer_register(clk, &dm646x_timer_cfg);
+	WARN(rv, "Unable to register the timer: %d\n", rv);
 }
 
 static struct resource dm646x_pll2_resources[] = {
Signature · 1 line
2.20.1
#19 lore raw

PATCH v4 11/11 ARM: davinci: remove legacy timer support

In reply to Bartosz Golaszewski

From: Bartosz Golaszewski <[email protected]>

All platforms have now been switched to the new clocksource driver. Remove the old code and various no longer needed bits and pieces.

---
 arch/arm/mach-davinci/Makefile              |   3 +-
 arch/arm/mach-davinci/devices-da8xx.c       |   1 -
 arch/arm/mach-davinci/devices.c             |  19 -
 arch/arm/mach-davinci/include/mach/common.h |  17 -
 arch/arm/mach-davinci/include/mach/time.h   |  33 --
 arch/arm/mach-davinci/time.c                | 400 --------------------
 6 files changed, 1 insertion(+), 472 deletions(-)
 delete mode 100644 arch/arm/mach-davinci/include/mach/time.h
 delete mode 100644 arch/arm/mach-davinci/time.c
arch/arm/mach-davinci/Makefile +1 -2
index f76a8482784f..d9af8c0c0b87 100644
@@ -5,8 +5,7 @@
 #
 
 # Common objects
-obj-y 					:= time.o serial.o usb.o \
-					   common.o sram.o
+obj-y 					:= serial.o usb.o common.o sram.o
 
 obj-$(CONFIG_DAVINCI_MUX)		+= mux.o
 
arch/arm/mach-davinci/devices-da8xx.c +0 -1
index b8dc674e06bc..5c6508821de4 100644
@@ -24,7 +24,6 @@
 #include <mach/common.h>
 #include <mach/cputype.h>
 #include <mach/da8xx.h>
-#include <mach/time.h>
 
 #include "asp.h"
 #include "cpuidle.h"
arch/arm/mach-davinci/devices.c +0 -19
index 40bd8029e457..3844433c9deb 100644
@@ -21,7 +21,6 @@
 #include <mach/hardware.h>
 #include <mach/cputype.h>
 #include <mach/mux.h>
-#include <mach/time.h>
 
 #include "davinci.h"
 #include "irqs.h"
@@ -307,21 +306,3 @@ int davinci_gpio_register(struct resource *res, int size, void *pdata)
 	davinci_gpio_device.dev.platform_data = pdata;
 	return platform_device_register(&davinci_gpio_device);
 }
-
-/*-------------------------------------------------------------------------*/
-
-/*-------------------------------------------------------------------------*/
-
-struct davinci_timer_instance davinci_timer_instance[2] = {
-	{
-		.base		= DAVINCI_TIMER0_BASE,
-		.bottom_irq	= DAVINCI_INTC_IRQ(IRQ_TINT0_TINT12),
-		.top_irq	= DAVINCI_INTC_IRQ(IRQ_TINT0_TINT34),
-	},
-	{
-		.base		= DAVINCI_TIMER1_BASE,
-		.bottom_irq	= DAVINCI_INTC_IRQ(IRQ_TINT1_TINT12),
-		.top_irq	= DAVINCI_INTC_IRQ(IRQ_TINT1_TINT34),
-	},
-};
-
arch/arm/mach-davinci/include/mach/common.h +0 -17
index 9526e5da0d33..139b83de011d 100644
@@ -22,22 +22,6 @@
 #define DAVINCI_INTC_START		NR_IRQS
 #define DAVINCI_INTC_IRQ(_irqnum)	(DAVINCI_INTC_START + (_irqnum))
 
-void davinci_timer_init(struct clk *clk);
-
-struct davinci_timer_instance {
-	u32		base;
-	u32		bottom_irq;
-	u32		top_irq;
-	unsigned long	cmp_off;
-	unsigned int	cmp_irq;
-};
-
-struct davinci_timer_info {
-	struct davinci_timer_instance	*timers;
-	unsigned int			clockevent_id;
-	unsigned int			clocksource_id;
-};
-
 struct davinci_gpio_controller;
 
 /*
@@ -58,7 +42,6 @@ struct davinci_soc_info {
 	u32				pinmux_base;
 	const struct mux_config		*pinmux_pins;
 	unsigned long			pinmux_pins_num;
-	struct davinci_timer_info	*timer_info;
 	int				gpio_type;
 	u32				gpio_base;
 	unsigned			gpio_num;
arch/arm/mach-davinci/include/mach/time.h deleted +0 -33
deleted file mode 100644
index ba913736990f..000000000000
@@ -1,33 +0,0 @@
-/*
- * Local header file for DaVinci time code.
- *
- * Author: Kevin Hilman, MontaVista Software, Inc. <[email protected]>
- *
- * 2007 (c) MontaVista Software, Inc. This file is licensed under
- * the terms of the GNU General Public License version 2. This program
- * is licensed "as is" without any warranty of any kind, whether express
- * or implied.
- */
-#ifndef __ARCH_ARM_MACH_DAVINCI_TIME_H
-#define __ARCH_ARM_MACH_DAVINCI_TIME_H
-
-#define DAVINCI_TIMER1_BASE		(IO_PHYS + 0x21800)
-
-enum {
-	T0_BOT,
-	T0_TOP,
-	T1_BOT,
-	T1_TOP,
-	NUM_TIMERS
-};
-
-#define IS_TIMER1(id)		(id & 0x2)
-#define IS_TIMER0(id)		(!IS_TIMER1(id))
-#define IS_TIMER_TOP(id)	((id & 0x1))
-#define IS_TIMER_BOT(id)	(!IS_TIMER_TOP(id))
-
-#define ID_TO_TIMER(id)		(IS_TIMER1(id) != 0)
-
-extern struct davinci_timer_instance davinci_timer_instance[];
-
-#endif /* __ARCH_ARM_MACH_DAVINCI_TIME_H */
arch/arm/mach-davinci/time.c deleted +0 -400

400 lines not on this page · raw message

Signature · 1 line
2.20.1
#20 lore raw
In reply to Bartosz Golaszewski

Hi Daniel, Thomas,

Quoted 13 lines · Bartosz Golaszewski

From: Bartosz Golaszewski <[email protected]>

This series removes the legacy timer code from mach-davinci in favor of a new clocksource driver it introduces.

Patch 1 adds a new clocksource driver for davinci.

Patch 2 enables the new driver for device-tree based systems.

Patch 3 adds a WARN_ON() to the machine code of all davinci boards which is triggered if clk_get() for the timer clock fails. This is needed as the new driver expects the clock to be functional and doesn't check it.

Quoted 5 lines

Patches 4-5 and 7-10 switch the board files to using the new clocksource driver while patch 6 moves some necessary defines to a different place since we'll be removing the file that contains them.

Patch 11 removes legacy timer code.

The series looks good to me. With your ack on 1/11, I would like to merge the series through ARM SoC tree.

Thanks,
Sekhar

#21 lore raw

Hi Sekhar,

Quoted 16 lines · Sekhar Nori

Hi Daniel, Thomas,

Quoted 13 lines · Bartosz Golaszewski

From: Bartosz Golaszewski <[email protected]>

This series removes the legacy timer code from mach-davinci in favor of a new clocksource driver it introduces.

Patch 1 adds a new clocksource driver for davinci.

Patch 2 enables the new driver for device-tree based systems.

Patch 3 adds a WARN_ON() to the machine code of all davinci boards which is triggered if clk_get() for the timer clock fails. This is needed as the new driver expects the clock to be functional and doesn't check it.

Quoted 8 lines
Quoted 5 lines

Patches 4-5 and 7-10 switch the board files to using the new clocksource driver while patch 6 moves some necessary defines to a different place since we'll be removing the file that contains them.

Patch 11 removes legacy timer code.

The series looks good to me. With your ack on 1/11, I would like to merge the series through ARM SoC tree.

ok, will do the review asap.

-- Daniel

Signature · 5 lines
 <http://www.linaro.org/> Linaro.org │ Open source software for ARM SoCs

Follow Linaro:  <http://www.facebook.com/pages/Linaro> Facebook |
<http://twitter.com/#!/linaroorg> Twitter |
<http://www.linaro.org/linaro-blog/> Blog