0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <linux/bitfield.h>
0011 #include <linux/bitops.h>
0012 #include <linux/clk.h>
0013 #include <linux/clockchips.h>
0014 #include <linux/interrupt.h>
0015 #include <linux/irq.h>
0016 #include <linux/irqreturn.h>
0017 #include <linux/sched_clock.h>
0018 #include <linux/of.h>
0019 #include <linux/of_address.h>
0020 #include <linux/of_irq.h>
0021
0022 #ifdef CONFIG_ARM
0023 #include <linux/delay.h>
0024 #endif
0025
0026 #define MESON_ISA_TIMER_MUX 0x00
0027 #define MESON_ISA_TIMER_MUX_TIMERD_EN BIT(19)
0028 #define MESON_ISA_TIMER_MUX_TIMERC_EN BIT(18)
0029 #define MESON_ISA_TIMER_MUX_TIMERB_EN BIT(17)
0030 #define MESON_ISA_TIMER_MUX_TIMERA_EN BIT(16)
0031 #define MESON_ISA_TIMER_MUX_TIMERD_MODE BIT(15)
0032 #define MESON_ISA_TIMER_MUX_TIMERC_MODE BIT(14)
0033 #define MESON_ISA_TIMER_MUX_TIMERB_MODE BIT(13)
0034 #define MESON_ISA_TIMER_MUX_TIMERA_MODE BIT(12)
0035 #define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_MASK GENMASK(10, 8)
0036 #define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_SYSTEM_CLOCK 0x0
0037 #define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_1US 0x1
0038 #define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_10US 0x2
0039 #define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_100US 0x3
0040 #define MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_1MS 0x4
0041 #define MESON_ISA_TIMER_MUX_TIMERD_INPUT_CLOCK_MASK GENMASK(7, 6)
0042 #define MESON_ISA_TIMER_MUX_TIMERC_INPUT_CLOCK_MASK GENMASK(5, 4)
0043 #define MESON_ISA_TIMER_MUX_TIMERB_INPUT_CLOCK_MASK GENMASK(3, 2)
0044 #define MESON_ISA_TIMER_MUX_TIMERA_INPUT_CLOCK_MASK GENMASK(1, 0)
0045 #define MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_1US 0x0
0046 #define MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_10US 0x1
0047 #define MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_100US 0x0
0048 #define MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_1MS 0x3
0049
0050 #define MESON_ISA_TIMERA 0x04
0051 #define MESON_ISA_TIMERB 0x08
0052 #define MESON_ISA_TIMERC 0x0c
0053 #define MESON_ISA_TIMERD 0x10
0054 #define MESON_ISA_TIMERE 0x14
0055
0056 static void __iomem *timer_base;
0057
0058 #ifdef CONFIG_ARM
0059 static unsigned long meson6_read_current_timer(void)
0060 {
0061 return readl_relaxed(timer_base + MESON_ISA_TIMERE);
0062 }
0063
0064 static struct delay_timer meson6_delay_timer = {
0065 .read_current_timer = meson6_read_current_timer,
0066 .freq = 1000 * 1000,
0067 };
0068 #endif
0069
0070 static u64 notrace meson6_timer_sched_read(void)
0071 {
0072 return (u64)readl(timer_base + MESON_ISA_TIMERE);
0073 }
0074
0075 static void meson6_clkevt_time_stop(void)
0076 {
0077 u32 val = readl(timer_base + MESON_ISA_TIMER_MUX);
0078
0079 writel(val & ~MESON_ISA_TIMER_MUX_TIMERA_EN,
0080 timer_base + MESON_ISA_TIMER_MUX);
0081 }
0082
0083 static void meson6_clkevt_time_setup(unsigned long delay)
0084 {
0085 writel(delay, timer_base + MESON_ISA_TIMERA);
0086 }
0087
0088 static void meson6_clkevt_time_start(bool periodic)
0089 {
0090 u32 val = readl(timer_base + MESON_ISA_TIMER_MUX);
0091
0092 if (periodic)
0093 val |= MESON_ISA_TIMER_MUX_TIMERA_MODE;
0094 else
0095 val &= ~MESON_ISA_TIMER_MUX_TIMERA_MODE;
0096
0097 writel(val | MESON_ISA_TIMER_MUX_TIMERA_EN,
0098 timer_base + MESON_ISA_TIMER_MUX);
0099 }
0100
0101 static int meson6_shutdown(struct clock_event_device *evt)
0102 {
0103 meson6_clkevt_time_stop();
0104 return 0;
0105 }
0106
0107 static int meson6_set_oneshot(struct clock_event_device *evt)
0108 {
0109 meson6_clkevt_time_stop();
0110 meson6_clkevt_time_start(false);
0111 return 0;
0112 }
0113
0114 static int meson6_set_periodic(struct clock_event_device *evt)
0115 {
0116 meson6_clkevt_time_stop();
0117 meson6_clkevt_time_setup(USEC_PER_SEC / HZ - 1);
0118 meson6_clkevt_time_start(true);
0119 return 0;
0120 }
0121
0122 static int meson6_clkevt_next_event(unsigned long evt,
0123 struct clock_event_device *unused)
0124 {
0125 meson6_clkevt_time_stop();
0126 meson6_clkevt_time_setup(evt);
0127 meson6_clkevt_time_start(false);
0128
0129 return 0;
0130 }
0131
0132 static struct clock_event_device meson6_clockevent = {
0133 .name = "meson6_tick",
0134 .rating = 400,
0135 .features = CLOCK_EVT_FEAT_PERIODIC |
0136 CLOCK_EVT_FEAT_ONESHOT,
0137 .set_state_shutdown = meson6_shutdown,
0138 .set_state_periodic = meson6_set_periodic,
0139 .set_state_oneshot = meson6_set_oneshot,
0140 .tick_resume = meson6_shutdown,
0141 .set_next_event = meson6_clkevt_next_event,
0142 };
0143
0144 static irqreturn_t meson6_timer_interrupt(int irq, void *dev_id)
0145 {
0146 struct clock_event_device *evt = (struct clock_event_device *)dev_id;
0147
0148 evt->event_handler(evt);
0149
0150 return IRQ_HANDLED;
0151 }
0152
0153 static int __init meson6_timer_init(struct device_node *node)
0154 {
0155 u32 val;
0156 int ret, irq;
0157
0158 timer_base = of_io_request_and_map(node, 0, "meson6-timer");
0159 if (IS_ERR(timer_base)) {
0160 pr_err("Can't map registers\n");
0161 return -ENXIO;
0162 }
0163
0164 irq = irq_of_parse_and_map(node, 0);
0165 if (irq <= 0) {
0166 pr_err("Can't parse IRQ\n");
0167 return -EINVAL;
0168 }
0169
0170
0171 val = readl(timer_base + MESON_ISA_TIMER_MUX);
0172 val &= ~MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_MASK;
0173 val |= FIELD_PREP(MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_MASK,
0174 MESON_ISA_TIMER_MUX_TIMERE_INPUT_CLOCK_1US);
0175 writel(val, timer_base + MESON_ISA_TIMER_MUX);
0176
0177 sched_clock_register(meson6_timer_sched_read, 32, USEC_PER_SEC);
0178 clocksource_mmio_init(timer_base + MESON_ISA_TIMERE, node->name,
0179 1000 * 1000, 300, 32, clocksource_mmio_readl_up);
0180
0181
0182 val &= ~MESON_ISA_TIMER_MUX_TIMERA_INPUT_CLOCK_MASK;
0183 val |= FIELD_PREP(MESON_ISA_TIMER_MUX_TIMERA_INPUT_CLOCK_MASK,
0184 MESON_ISA_TIMER_MUX_TIMERABCD_INPUT_CLOCK_1US);
0185 writel(val, timer_base + MESON_ISA_TIMER_MUX);
0186
0187
0188 meson6_clkevt_time_stop();
0189
0190 ret = request_irq(irq, meson6_timer_interrupt,
0191 IRQF_TIMER | IRQF_IRQPOLL, "meson6_timer",
0192 &meson6_clockevent);
0193 if (ret) {
0194 pr_warn("failed to setup irq %d\n", irq);
0195 return ret;
0196 }
0197
0198 meson6_clockevent.cpumask = cpu_possible_mask;
0199 meson6_clockevent.irq = irq;
0200
0201 clockevents_config_and_register(&meson6_clockevent, USEC_PER_SEC,
0202 1, 0xfffe);
0203
0204 #ifdef CONFIG_ARM
0205
0206 register_current_timer_delay(&meson6_delay_timer);
0207 #endif
0208
0209 return 0;
0210 }
0211 TIMER_OF_DECLARE(meson6, "amlogic,meson6-timer",
0212 meson6_timer_init);