Messages in this thread Patch in this message | | | From | Anson Huang <> | Subject | [PATCH V2] clocksource/drivers/timer-imx-tpm: convert the driver to timer-of | Date | Fri, 23 Nov 2018 02:57:57 +0000 |
| |
Convert the driver to use the timer_of helpers. This allows to handle timer base, clock and irq using common timer_of driver and it simplifies the code.
Signed-off-by: Anson Huang <Anson.Huang@nxp.com> --- drivers/clocksource/timer-imx-tpm.c | 183 ++++++++++++++---------------------- 1 file changed, 73 insertions(+), 110 deletions(-)
diff --git a/drivers/clocksource/timer-imx-tpm.c b/drivers/clocksource/timer-imx-tpm.c index b7aa2b8..b9df46c 100644 --- a/drivers/clocksource/timer-imx-tpm.c +++ b/drivers/clocksource/timer-imx-tpm.c @@ -12,6 +12,8 @@ #include <linux/of_irq.h> #include <linux/sched_clock.h> +#include "timer-of.h" + #define TPM_PARAM 0x4 #define TPM_PARAM_WIDTH_SHIFT 16 #define TPM_PARAM_WIDTH_MASK (0xff << 16) @@ -33,35 +35,7 @@ #define TPM_C0V 0x24 static int counter_width; -static int rating; static void __iomem *timer_base; -static struct clock_event_device clockevent_tpm; - -static inline void tpm_timer_disable(void) -{ - unsigned int val; - - /* channel disable */ - val = readl(timer_base + TPM_C0SC); - val &= ~(TPM_C0SC_MODE_MASK | TPM_C0SC_CHIE); - writel(val, timer_base + TPM_C0SC); -} - -static inline void tpm_timer_enable(void) -{ - unsigned int val; - - /* channel enabled in sw compare mode */ - val = readl(timer_base + TPM_C0SC); - val |= (TPM_C0SC_MODE_SW_COMPARE << TPM_C0SC_MODE_SHIFT) | - TPM_C0SC_CHIE; - writel(val, timer_base + TPM_C0SC); -} - -static inline void tpm_irq_acknowledge(void) -{ - writel(TPM_STATUS_CH0F, timer_base + TPM_STATUS); -} static struct delay_timer tpm_delay_timer; @@ -80,19 +54,6 @@ static u64 notrace tpm_read_sched_clock(void) return tpm_read_counter(); } -static int __init tpm_clocksource_init(unsigned long rate) -{ - tpm_delay_timer.read_current_timer = &tpm_read_current_timer; - tpm_delay_timer.freq = rate; - register_current_timer_delay(&tpm_delay_timer); - - sched_clock_register(tpm_read_sched_clock, counter_width, rate); - - return clocksource_mmio_init(timer_base + TPM_CNT, "imx-tpm", - rate, rating, counter_width, - clocksource_mmio_readl_up); -} - static int tpm_set_next_event(unsigned long delta, struct clock_event_device *evt) { @@ -114,14 +75,27 @@ static int tpm_set_next_event(unsigned long delta, static int tpm_set_state_oneshot(struct clock_event_device *evt) { - tpm_timer_enable(); + struct timer_of *to_tpm = to_timer_of(evt); + unsigned int val; + + /* channel enabled in sw compare mode */ + val = readl(timer_of_base(to_tpm) + TPM_C0SC); + val |= (TPM_C0SC_MODE_SW_COMPARE << TPM_C0SC_MODE_SHIFT) | + TPM_C0SC_CHIE; + writel(val, timer_of_base(to_tpm) + TPM_C0SC); return 0; } static int tpm_set_state_shutdown(struct clock_event_device *evt) { - tpm_timer_disable(); + struct timer_of *to_tpm = to_timer_of(evt); + unsigned int val; + + /* channel disable */ + val = readl(timer_of_base(to_tpm) + TPM_C0SC); + val &= ~(TPM_C0SC_MODE_MASK | TPM_C0SC_CHIE); + writel(val, timer_of_base(to_tpm) + TPM_C0SC); return 0; } @@ -129,82 +103,87 @@ static int tpm_set_state_shutdown(struct clock_event_device *evt) static irqreturn_t tpm_timer_interrupt(int irq, void *dev_id) { struct clock_event_device *evt = dev_id; + struct timer_of *to_tpm = to_timer_of(evt); - tpm_irq_acknowledge(); + /* irq acknowledge */ + writel(TPM_STATUS_CH0F, timer_of_base(to_tpm) + TPM_STATUS); evt->event_handler(evt); return IRQ_HANDLED; } -static struct clock_event_device clockevent_tpm = { - .name = "i.MX7ULP TPM Timer", - .features = CLOCK_EVT_FEAT_ONESHOT, - .set_state_oneshot = tpm_set_state_oneshot, - .set_next_event = tpm_set_next_event, - .set_state_shutdown = tpm_set_state_shutdown, +static struct timer_of to_tpm = { + .flags = TIMER_OF_IRQ | TIMER_OF_BASE | TIMER_OF_CLOCK, + .clkevt = { + .name = "i.MX7ULP TPM Timer", + .rating = 200, + .features = CLOCK_EVT_FEAT_ONESHOT, + .set_state_shutdown = tpm_set_state_shutdown, + .set_state_oneshot = tpm_set_state_oneshot, + .set_next_event = tpm_set_next_event, + .cpumask = cpu_possible_mask, + }, + .of_irq = { + .handler = tpm_timer_interrupt, + .flags = IRQF_TIMER | IRQF_IRQPOLL, + }, }; -static int __init tpm_clockevent_init(unsigned long rate, int irq) +static int __init tpm_clocksource_init(void) { - int ret; + tpm_delay_timer.read_current_timer = &tpm_read_current_timer; + tpm_delay_timer.freq = timer_of_rate(&to_tpm) >> 3; + register_current_timer_delay(&tpm_delay_timer); - ret = request_irq(irq, tpm_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL, - "i.MX7ULP TPM Timer", &clockevent_tpm); + sched_clock_register(tpm_read_sched_clock, counter_width, + timer_of_rate(&to_tpm) >> 3); - clockevent_tpm.rating = rating; - clockevent_tpm.cpumask = cpumask_of(0); - clockevent_tpm.irq = irq; - clockevents_config_and_register(&clockevent_tpm, rate, 300, - GENMASK(counter_width - 1, 1)); + return clocksource_mmio_init(timer_base + TPM_CNT, + "imx-tpm", + timer_of_rate(&to_tpm) >> 3, + to_tpm.clkevt.rating, + counter_width, + clocksource_mmio_readl_up); +} - return ret; +static void __init tpm_clockevent_init(void) +{ + clockevents_config_and_register(&to_tpm.clkevt, + timer_of_rate(&to_tpm) >> 3, + 300, + GENMASK(counter_width - 1, + 1)); } static int __init tpm_timer_init(struct device_node *np) { - struct clk *ipg, *per; - int irq, ret; - u32 rate; - - timer_base = of_iomap(np, 0); - if (!timer_base) { - pr_err("tpm: failed to get base address\n"); - return -ENXIO; - } - - irq = irq_of_parse_and_map(np, 0); - if (!irq) { - pr_err("tpm: failed to get irq\n"); - ret = -ENOENT; - goto err_iomap; - } + struct clk *ipg; + int ret; ipg = of_clk_get_by_name(np, "ipg"); - per = of_clk_get_by_name(np, "per"); - if (IS_ERR(ipg) || IS_ERR(per)) { - pr_err("tpm: failed to get ipg or per clk\n"); - ret = -ENODEV; - goto err_clk_get; + if (IS_ERR(ipg)) { + pr_err("tpm: failed to get ipg clk\n"); + return -ENODEV; } - /* enable clk before accessing registers */ ret = clk_prepare_enable(ipg); if (ret) { pr_err("tpm: ipg clock enable failed (%d)\n", ret); - goto err_clk_get; + clk_put(ipg); + return ret; } - ret = clk_prepare_enable(per); - if (ret) { - pr_err("tpm: per clock enable failed (%d)\n", ret); - goto err_per_clk_enable; - } + ret = timer_of_init(np, &to_tpm); + if (ret) + return ret; + + timer_base = timer_of_base(&to_tpm); - counter_width = (readl(timer_base + TPM_PARAM) & TPM_PARAM_WIDTH_MASK) - >> TPM_PARAM_WIDTH_SHIFT; + counter_width = (readl(timer_base + TPM_PARAM) + & TPM_PARAM_WIDTH_MASK) >> TPM_PARAM_WIDTH_SHIFT; /* use rating 200 for 32-bit counter and 150 for 16-bit counter */ - rating = counter_width == 0x20 ? 200 : 150; + to_tpm.clkevt.rating = counter_width == 0x20 ? 200 : 150; /* * Initialize tpm module to a known state @@ -229,29 +208,13 @@ static int __init tpm_timer_init(struct device_node *np) writel(TPM_SC_CMOD_INC_PER_CNT | (counter_width == 0x20 ? TPM_SC_CMOD_DIV_DEFAULT : TPM_SC_CMOD_DIV_MAX), - timer_base + TPM_SC); + timer_base + TPM_SC); /* set MOD register to maximum for free running mode */ writel(GENMASK(counter_width - 1, 0), timer_base + TPM_MOD); - rate = clk_get_rate(per) >> 3; - ret = tpm_clocksource_init(rate); - if (ret) - goto err_per_clk_enable; - - ret = tpm_clockevent_init(rate, irq); - if (ret) - goto err_per_clk_enable; - - return 0; + tpm_clockevent_init(); -err_per_clk_enable: - clk_disable_unprepare(ipg); -err_clk_get: - clk_put(per); - clk_put(ipg); -err_iomap: - iounmap(timer_base); - return ret; + return tpm_clocksource_init(); } TIMER_OF_DECLARE(imx7ulp, "fsl,imx7ulp-tpm", tpm_timer_init); -- 2.7.4
| |