^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) // SPDX-License-Identifier: GPL-2.0-or-later
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * Copyright 2012-2013 Freescale Semiconductor, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/interrupt.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include <linux/clockchips.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include <linux/clk.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include <linux/of_address.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) #include <linux/of_irq.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) #include <linux/sched_clock.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * Each pit takes 0x10 Bytes register space
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) #define PITMCR 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) #define PIT0_OFFSET 0x100
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) #define PITn_OFFSET(n) (PIT0_OFFSET + 0x10 * (n))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #define PITLDVAL 0x00
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #define PITCVAL 0x04
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #define PITTCTRL 0x08
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #define PITTFLG 0x0c
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #define PITMCR_MDIS (0x1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #define PITTCTRL_TEN (0x1 << 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) #define PITTCTRL_TIE (0x1 << 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) #define PITCTRL_CHN (0x1 << 2)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) #define PITTFLG_TIF 0x1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) static void __iomem *clksrc_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) static void __iomem *clkevt_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) static unsigned long cycle_per_jiffy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static inline void pit_timer_enable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) __raw_writel(PITTCTRL_TEN | PITTCTRL_TIE, clkevt_base + PITTCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) static inline void pit_timer_disable(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) __raw_writel(0, clkevt_base + PITTCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) static inline void pit_irq_acknowledge(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static u64 notrace pit_read_sched_clock(void)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) return ~__raw_readl(clksrc_base + PITCVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) static int __init pit_clocksource_init(unsigned long rate)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) /* set the max load value and start the clock source counter */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) __raw_writel(0, clksrc_base + PITTCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) __raw_writel(~0UL, clksrc_base + PITLDVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) __raw_writel(PITTCTRL_TEN, clksrc_base + PITTCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) sched_clock_register(pit_read_sched_clock, 32, rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return clocksource_mmio_init(clksrc_base + PITCVAL, "vf-pit", rate,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) 300, 32, clocksource_mmio_readl_down);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) static int pit_set_next_event(unsigned long delta,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) struct clock_event_device *unused)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) * set a new value to PITLDVAL register will not restart the timer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) * to abort the current cycle and start a timer period with the new
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) * value, the timer must be disabled and enabled again.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) * and the PITLAVAL should be set to delta minus one according to pit
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) * hardware requirement.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) pit_timer_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) __raw_writel(delta - 1, clkevt_base + PITLDVAL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) pit_timer_enable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) static int pit_shutdown(struct clock_event_device *evt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) pit_timer_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) static int pit_set_periodic(struct clock_event_device *evt)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) pit_set_next_event(cycle_per_jiffy, evt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) static irqreturn_t pit_timer_interrupt(int irq, void *dev_id)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) struct clock_event_device *evt = dev_id;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) pit_irq_acknowledge();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) * pit hardware doesn't support oneshot, it will generate an interrupt
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) * and reload the counter value from PITLDVAL when PITCVAL reach zero,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) * and start the counter again. So software need to disable the timer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) * to stop the counter loop in ONESHOT mode.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (likely(clockevent_state_oneshot(evt)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) pit_timer_disable();
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) evt->event_handler(evt);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) return IRQ_HANDLED;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) static struct clock_event_device clockevent_pit = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) .name = "VF pit timer",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) .set_state_shutdown = pit_shutdown,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) .set_state_periodic = pit_set_periodic,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) .set_next_event = pit_set_next_event,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) .rating = 300,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) static int __init pit_clockevent_init(unsigned long rate, int irq)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) __raw_writel(0, clkevt_base + PITTCTRL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) __raw_writel(PITTFLG_TIF, clkevt_base + PITTFLG);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) BUG_ON(request_irq(irq, pit_timer_interrupt, IRQF_TIMER | IRQF_IRQPOLL,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) "VF pit timer", &clockevent_pit));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) clockevent_pit.cpumask = cpumask_of(0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) clockevent_pit.irq = irq;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) * The value for the LDVAL register trigger is calculated as:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) * LDVAL trigger = (period / clock period) - 1
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) * The pit is a 32-bit down count timer, when the conter value
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) * reaches 0, it will generate an interrupt, thus the minimal
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) * LDVAL trigger value is 1. And then the min_delta is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) * minimal LDVAL trigger value + 1, and the max_delta is full 32-bit.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) clockevents_config_and_register(&clockevent_pit, rate, 2, 0xffffffff);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) static int __init pit_timer_init(struct device_node *np)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) struct clk *pit_clk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) void __iomem *timer_base;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) unsigned long clk_rate;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) int irq, ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) timer_base = of_iomap(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) if (!timer_base) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) pr_err("Failed to iomap\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return -ENXIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) * PIT0 and PIT1 can be chained to build a 64-bit timer,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) * so choose PIT2 as clocksource, PIT3 as clockevent device,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) * and leave PIT0 and PIT1 unused for anyone else who needs them.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) clksrc_base = timer_base + PITn_OFFSET(2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) clkevt_base = timer_base + PITn_OFFSET(3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) irq = irq_of_parse_and_map(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) if (irq <= 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) pit_clk = of_clk_get(np, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) if (IS_ERR(pit_clk))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) return PTR_ERR(pit_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) ret = clk_prepare_enable(pit_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) clk_rate = clk_get_rate(pit_clk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) cycle_per_jiffy = clk_rate / (HZ);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) /* enable the pit module */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) __raw_writel(~PITMCR_MDIS, timer_base + PITMCR);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) ret = pit_clocksource_init(clk_rate);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) return pit_clockevent_init(clk_rate, irq);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) TIMER_OF_DECLARE(vf610, "fsl,vf610-pit", pit_timer_init);