0001
0002
0003
0004
0005
0006
0007
0008
0009 #define pr_fmt(fmt) "clint: " fmt
0010 #include <linux/bitops.h>
0011 #include <linux/clocksource.h>
0012 #include <linux/clockchips.h>
0013 #include <linux/cpu.h>
0014 #include <linux/delay.h>
0015 #include <linux/module.h>
0016 #include <linux/of_address.h>
0017 #include <linux/sched_clock.h>
0018 #include <linux/io-64-nonatomic-lo-hi.h>
0019 #include <linux/interrupt.h>
0020 #include <linux/of_irq.h>
0021 #include <linux/smp.h>
0022 #include <linux/timex.h>
0023
0024 #ifndef CONFIG_RISCV_M_MODE
0025 #include <asm/clint.h>
0026 #endif
0027
0028 #define CLINT_IPI_OFF 0
0029 #define CLINT_TIMER_CMP_OFF 0x4000
0030 #define CLINT_TIMER_VAL_OFF 0xbff8
0031
0032
0033 static u32 __iomem *clint_ipi_base;
0034 static u64 __iomem *clint_timer_cmp;
0035 static u64 __iomem *clint_timer_val;
0036 static unsigned long clint_timer_freq;
0037 static unsigned int clint_timer_irq;
0038
0039 #ifdef CONFIG_RISCV_M_MODE
0040 u64 __iomem *clint_time_val;
0041 EXPORT_SYMBOL(clint_time_val);
0042 #endif
0043
0044 static void clint_send_ipi(const struct cpumask *target)
0045 {
0046 unsigned int cpu;
0047
0048 for_each_cpu(cpu, target)
0049 writel(1, clint_ipi_base + cpuid_to_hartid_map(cpu));
0050 }
0051
0052 static void clint_clear_ipi(void)
0053 {
0054 writel(0, clint_ipi_base + cpuid_to_hartid_map(smp_processor_id()));
0055 }
0056
0057 static struct riscv_ipi_ops clint_ipi_ops = {
0058 .ipi_inject = clint_send_ipi,
0059 .ipi_clear = clint_clear_ipi,
0060 };
0061
0062 #ifdef CONFIG_64BIT
0063 #define clint_get_cycles() readq_relaxed(clint_timer_val)
0064 #else
0065 #define clint_get_cycles() readl_relaxed(clint_timer_val)
0066 #define clint_get_cycles_hi() readl_relaxed(((u32 *)clint_timer_val) + 1)
0067 #endif
0068
0069 #ifdef CONFIG_64BIT
0070 static u64 notrace clint_get_cycles64(void)
0071 {
0072 return clint_get_cycles();
0073 }
0074 #else
0075 static u64 notrace clint_get_cycles64(void)
0076 {
0077 u32 hi, lo;
0078
0079 do {
0080 hi = clint_get_cycles_hi();
0081 lo = clint_get_cycles();
0082 } while (hi != clint_get_cycles_hi());
0083
0084 return ((u64)hi << 32) | lo;
0085 }
0086 #endif
0087
0088 static u64 clint_rdtime(struct clocksource *cs)
0089 {
0090 return clint_get_cycles64();
0091 }
0092
0093 static struct clocksource clint_clocksource = {
0094 .name = "clint_clocksource",
0095 .rating = 300,
0096 .mask = CLOCKSOURCE_MASK(64),
0097 .flags = CLOCK_SOURCE_IS_CONTINUOUS,
0098 .read = clint_rdtime,
0099 };
0100
0101 static int clint_clock_next_event(unsigned long delta,
0102 struct clock_event_device *ce)
0103 {
0104 void __iomem *r = clint_timer_cmp +
0105 cpuid_to_hartid_map(smp_processor_id());
0106
0107 csr_set(CSR_IE, IE_TIE);
0108 writeq_relaxed(clint_get_cycles64() + delta, r);
0109 return 0;
0110 }
0111
0112 static DEFINE_PER_CPU(struct clock_event_device, clint_clock_event) = {
0113 .name = "clint_clockevent",
0114 .features = CLOCK_EVT_FEAT_ONESHOT,
0115 .rating = 100,
0116 .set_next_event = clint_clock_next_event,
0117 };
0118
0119 static int clint_timer_starting_cpu(unsigned int cpu)
0120 {
0121 struct clock_event_device *ce = per_cpu_ptr(&clint_clock_event, cpu);
0122
0123 ce->cpumask = cpumask_of(cpu);
0124 clockevents_config_and_register(ce, clint_timer_freq, 100, 0x7fffffff);
0125
0126 enable_percpu_irq(clint_timer_irq,
0127 irq_get_trigger_type(clint_timer_irq));
0128 return 0;
0129 }
0130
0131 static int clint_timer_dying_cpu(unsigned int cpu)
0132 {
0133 disable_percpu_irq(clint_timer_irq);
0134 return 0;
0135 }
0136
0137 static irqreturn_t clint_timer_interrupt(int irq, void *dev_id)
0138 {
0139 struct clock_event_device *evdev = this_cpu_ptr(&clint_clock_event);
0140
0141 csr_clear(CSR_IE, IE_TIE);
0142 evdev->event_handler(evdev);
0143
0144 return IRQ_HANDLED;
0145 }
0146
0147 static int __init clint_timer_init_dt(struct device_node *np)
0148 {
0149 int rc;
0150 u32 i, nr_irqs;
0151 void __iomem *base;
0152 struct of_phandle_args oirq;
0153
0154
0155
0156
0157
0158 nr_irqs = of_irq_count(np);
0159 for (i = 0; i < nr_irqs; i++) {
0160 if (of_irq_parse_one(np, i, &oirq)) {
0161 pr_err("%pOFP: failed to parse irq %d.\n", np, i);
0162 continue;
0163 }
0164
0165 if ((oirq.args_count != 1) ||
0166 (oirq.args[0] != RV_IRQ_TIMER &&
0167 oirq.args[0] != RV_IRQ_SOFT)) {
0168 pr_err("%pOFP: invalid irq %d (hwirq %d)\n",
0169 np, i, oirq.args[0]);
0170 return -ENODEV;
0171 }
0172
0173
0174 if (!clint_timer_irq &&
0175 oirq.args[0] == RV_IRQ_TIMER &&
0176 irq_find_host(oirq.np))
0177 clint_timer_irq = irq_of_parse_and_map(np, i);
0178 }
0179
0180
0181 if (!clint_timer_irq) {
0182 pr_err("%pOFP: timer irq not found\n", np);
0183 return -ENODEV;
0184 }
0185
0186 base = of_iomap(np, 0);
0187 if (!base) {
0188 pr_err("%pOFP: could not map registers\n", np);
0189 return -ENODEV;
0190 }
0191
0192 clint_ipi_base = base + CLINT_IPI_OFF;
0193 clint_timer_cmp = base + CLINT_TIMER_CMP_OFF;
0194 clint_timer_val = base + CLINT_TIMER_VAL_OFF;
0195 clint_timer_freq = riscv_timebase;
0196
0197 #ifdef CONFIG_RISCV_M_MODE
0198
0199
0200
0201
0202 clint_time_val = clint_timer_val;
0203 #endif
0204
0205 pr_info("%pOFP: timer running at %ld Hz\n", np, clint_timer_freq);
0206
0207 rc = clocksource_register_hz(&clint_clocksource, clint_timer_freq);
0208 if (rc) {
0209 pr_err("%pOFP: clocksource register failed [%d]\n", np, rc);
0210 goto fail_iounmap;
0211 }
0212
0213 sched_clock_register(clint_get_cycles64, 64, clint_timer_freq);
0214
0215 rc = request_percpu_irq(clint_timer_irq, clint_timer_interrupt,
0216 "clint-timer", &clint_clock_event);
0217 if (rc) {
0218 pr_err("registering percpu irq failed [%d]\n", rc);
0219 goto fail_iounmap;
0220 }
0221
0222 rc = cpuhp_setup_state(CPUHP_AP_CLINT_TIMER_STARTING,
0223 "clockevents/clint/timer:starting",
0224 clint_timer_starting_cpu,
0225 clint_timer_dying_cpu);
0226 if (rc) {
0227 pr_err("%pOFP: cpuhp setup state failed [%d]\n", np, rc);
0228 goto fail_free_irq;
0229 }
0230
0231 riscv_set_ipi_ops(&clint_ipi_ops);
0232 clint_clear_ipi();
0233
0234 return 0;
0235
0236 fail_free_irq:
0237 free_irq(clint_timer_irq, &clint_clock_event);
0238 fail_iounmap:
0239 iounmap(base);
0240 return rc;
0241 }
0242
0243 TIMER_OF_DECLARE(clint_timer, "riscv,clint0", clint_timer_init_dt);
0244 TIMER_OF_DECLARE(clint_timer1, "sifive,clint0", clint_timer_init_dt);