14891f015SMarc Zyngier // SPDX-License-Identifier: GPL-2.0-only
24891f015SMarc Zyngier /*
34891f015SMarc Zyngier * ARM Generic Memory Mapped Timer support
44891f015SMarc Zyngier *
54891f015SMarc Zyngier * Split from drivers/clocksource/arm_arch_timer.c
64891f015SMarc Zyngier *
74891f015SMarc Zyngier * Copyright (C) 2011 ARM Ltd.
84891f015SMarc Zyngier * All Rights Reserved
94891f015SMarc Zyngier */
104891f015SMarc Zyngier
114891f015SMarc Zyngier #define pr_fmt(fmt) "arch_timer_mmio: " fmt
124891f015SMarc Zyngier
134891f015SMarc Zyngier #include <linux/clockchips.h>
144891f015SMarc Zyngier #include <linux/interrupt.h>
154891f015SMarc Zyngier #include <linux/io-64-nonatomic-lo-hi.h>
164891f015SMarc Zyngier #include <linux/of_irq.h>
174891f015SMarc Zyngier #include <linux/of_address.h>
184891f015SMarc Zyngier #include <linux/platform_device.h>
194891f015SMarc Zyngier
204891f015SMarc Zyngier #include <clocksource/arm_arch_timer.h>
214891f015SMarc Zyngier
224891f015SMarc Zyngier #define CNTTIDR 0x08
234891f015SMarc Zyngier #define CNTTIDR_VIRT(n) (BIT(1) << ((n) * 4))
244891f015SMarc Zyngier
254891f015SMarc Zyngier #define CNTACR(n) (0x40 + ((n) * 4))
264891f015SMarc Zyngier #define CNTACR_RPCT BIT(0)
274891f015SMarc Zyngier #define CNTACR_RVCT BIT(1)
284891f015SMarc Zyngier #define CNTACR_RFRQ BIT(2)
294891f015SMarc Zyngier #define CNTACR_RVOFF BIT(3)
304891f015SMarc Zyngier #define CNTACR_RWVT BIT(4)
314891f015SMarc Zyngier #define CNTACR_RWPT BIT(5)
324891f015SMarc Zyngier
334891f015SMarc Zyngier #define CNTPCT_LO 0x00
344891f015SMarc Zyngier #define CNTVCT_LO 0x08
354891f015SMarc Zyngier #define CNTFRQ 0x10
364891f015SMarc Zyngier #define CNTP_CVAL_LO 0x20
374891f015SMarc Zyngier #define CNTP_CTL 0x2c
384891f015SMarc Zyngier #define CNTV_CVAL_LO 0x30
394891f015SMarc Zyngier #define CNTV_CTL 0x3c
404891f015SMarc Zyngier
414891f015SMarc Zyngier enum arch_timer_access {
424891f015SMarc Zyngier PHYS_ACCESS,
434891f015SMarc Zyngier VIRT_ACCESS,
444891f015SMarc Zyngier };
454891f015SMarc Zyngier
464891f015SMarc Zyngier struct arch_timer {
474891f015SMarc Zyngier struct clock_event_device evt;
48*4e9bfe69SMarc Zyngier struct clocksource cs;
494891f015SMarc Zyngier struct arch_timer_mem *gt_block;
504891f015SMarc Zyngier void __iomem *base;
514891f015SMarc Zyngier enum arch_timer_access access;
524891f015SMarc Zyngier u32 rate;
534891f015SMarc Zyngier };
544891f015SMarc Zyngier
554891f015SMarc Zyngier #define evt_to_arch_timer(e) container_of(e, struct arch_timer, evt)
56*4e9bfe69SMarc Zyngier #define cs_to_arch_timer(c) container_of(c, struct arch_timer, cs)
574891f015SMarc Zyngier
arch_timer_mmio_write(struct arch_timer * timer,enum arch_timer_reg reg,u64 val)584891f015SMarc Zyngier static void arch_timer_mmio_write(struct arch_timer *timer,
594891f015SMarc Zyngier enum arch_timer_reg reg, u64 val)
604891f015SMarc Zyngier {
614891f015SMarc Zyngier switch (timer->access) {
624891f015SMarc Zyngier case PHYS_ACCESS:
634891f015SMarc Zyngier switch (reg) {
644891f015SMarc Zyngier case ARCH_TIMER_REG_CTRL:
654891f015SMarc Zyngier writel_relaxed((u32)val, timer->base + CNTP_CTL);
664891f015SMarc Zyngier return;
674891f015SMarc Zyngier case ARCH_TIMER_REG_CVAL:
684891f015SMarc Zyngier /*
694891f015SMarc Zyngier * Not guaranteed to be atomic, so the timer
704891f015SMarc Zyngier * must be disabled at this point.
714891f015SMarc Zyngier */
724891f015SMarc Zyngier writeq_relaxed(val, timer->base + CNTP_CVAL_LO);
734891f015SMarc Zyngier return;
744891f015SMarc Zyngier }
754891f015SMarc Zyngier break;
764891f015SMarc Zyngier case VIRT_ACCESS:
774891f015SMarc Zyngier switch (reg) {
784891f015SMarc Zyngier case ARCH_TIMER_REG_CTRL:
794891f015SMarc Zyngier writel_relaxed((u32)val, timer->base + CNTV_CTL);
804891f015SMarc Zyngier return;
814891f015SMarc Zyngier case ARCH_TIMER_REG_CVAL:
824891f015SMarc Zyngier /* Same restriction as above */
834891f015SMarc Zyngier writeq_relaxed(val, timer->base + CNTV_CVAL_LO);
844891f015SMarc Zyngier return;
854891f015SMarc Zyngier }
864891f015SMarc Zyngier break;
874891f015SMarc Zyngier }
884891f015SMarc Zyngier
894891f015SMarc Zyngier /* Should never be here */
904891f015SMarc Zyngier WARN_ON_ONCE(1);
914891f015SMarc Zyngier }
924891f015SMarc Zyngier
arch_timer_mmio_read(struct arch_timer * timer,enum arch_timer_reg reg)934891f015SMarc Zyngier static u32 arch_timer_mmio_read(struct arch_timer *timer, enum arch_timer_reg reg)
944891f015SMarc Zyngier {
954891f015SMarc Zyngier switch (timer->access) {
964891f015SMarc Zyngier case PHYS_ACCESS:
974891f015SMarc Zyngier switch (reg) {
984891f015SMarc Zyngier case ARCH_TIMER_REG_CTRL:
994891f015SMarc Zyngier return readl_relaxed(timer->base + CNTP_CTL);
1004891f015SMarc Zyngier default:
1014891f015SMarc Zyngier break;
1024891f015SMarc Zyngier }
1034891f015SMarc Zyngier break;
1044891f015SMarc Zyngier case VIRT_ACCESS:
1054891f015SMarc Zyngier switch (reg) {
1064891f015SMarc Zyngier case ARCH_TIMER_REG_CTRL:
1074891f015SMarc Zyngier return readl_relaxed(timer->base + CNTV_CTL);
1084891f015SMarc Zyngier default:
1094891f015SMarc Zyngier break;
1104891f015SMarc Zyngier }
1114891f015SMarc Zyngier break;
1124891f015SMarc Zyngier }
1134891f015SMarc Zyngier
1144891f015SMarc Zyngier /* Should never be here */
1154891f015SMarc Zyngier WARN_ON_ONCE(1);
1164891f015SMarc Zyngier return 0;
1174891f015SMarc Zyngier }
1184891f015SMarc Zyngier
arch_counter_mmio_get_cnt(struct arch_timer * t)1194891f015SMarc Zyngier static noinstr u64 arch_counter_mmio_get_cnt(struct arch_timer *t)
1204891f015SMarc Zyngier {
1214891f015SMarc Zyngier int offset_lo = t->access == VIRT_ACCESS ? CNTVCT_LO : CNTPCT_LO;
1224891f015SMarc Zyngier u32 cnt_lo, cnt_hi, tmp_hi;
1234891f015SMarc Zyngier
1244891f015SMarc Zyngier do {
1254891f015SMarc Zyngier cnt_hi = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo + 4));
1264891f015SMarc Zyngier cnt_lo = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo));
1274891f015SMarc Zyngier tmp_hi = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo + 4));
1284891f015SMarc Zyngier } while (cnt_hi != tmp_hi);
1294891f015SMarc Zyngier
1304891f015SMarc Zyngier return ((u64) cnt_hi << 32) | cnt_lo;
1314891f015SMarc Zyngier }
1324891f015SMarc Zyngier
arch_mmio_counter_read(struct clocksource * cs)133*4e9bfe69SMarc Zyngier static u64 arch_mmio_counter_read(struct clocksource *cs)
134*4e9bfe69SMarc Zyngier {
135*4e9bfe69SMarc Zyngier struct arch_timer *at = cs_to_arch_timer(cs);
136*4e9bfe69SMarc Zyngier
137*4e9bfe69SMarc Zyngier return arch_counter_mmio_get_cnt(at);
138*4e9bfe69SMarc Zyngier }
139*4e9bfe69SMarc Zyngier
arch_timer_mmio_shutdown(struct clock_event_device * clk)1404891f015SMarc Zyngier static int arch_timer_mmio_shutdown(struct clock_event_device *clk)
1414891f015SMarc Zyngier {
1424891f015SMarc Zyngier struct arch_timer *at = evt_to_arch_timer(clk);
1434891f015SMarc Zyngier unsigned long ctrl;
1444891f015SMarc Zyngier
1454891f015SMarc Zyngier ctrl = arch_timer_mmio_read(at, ARCH_TIMER_REG_CTRL);
1464891f015SMarc Zyngier ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
1474891f015SMarc Zyngier arch_timer_mmio_write(at, ARCH_TIMER_REG_CTRL, ctrl);
1484891f015SMarc Zyngier
1494891f015SMarc Zyngier return 0;
1504891f015SMarc Zyngier }
1514891f015SMarc Zyngier
arch_timer_mmio_set_next_event(unsigned long evt,struct clock_event_device * clk)1524891f015SMarc Zyngier static int arch_timer_mmio_set_next_event(unsigned long evt,
1534891f015SMarc Zyngier struct clock_event_device *clk)
1544891f015SMarc Zyngier {
1554891f015SMarc Zyngier struct arch_timer *timer = evt_to_arch_timer(clk);
1564891f015SMarc Zyngier unsigned long ctrl;
1574891f015SMarc Zyngier u64 cnt;
1584891f015SMarc Zyngier
1594891f015SMarc Zyngier ctrl = arch_timer_mmio_read(timer, ARCH_TIMER_REG_CTRL);
1604891f015SMarc Zyngier
1614891f015SMarc Zyngier /* Timer must be disabled before programming CVAL */
1624891f015SMarc Zyngier if (ctrl & ARCH_TIMER_CTRL_ENABLE) {
1634891f015SMarc Zyngier ctrl &= ~ARCH_TIMER_CTRL_ENABLE;
1644891f015SMarc Zyngier arch_timer_mmio_write(timer, ARCH_TIMER_REG_CTRL, ctrl);
1654891f015SMarc Zyngier }
1664891f015SMarc Zyngier
1674891f015SMarc Zyngier ctrl |= ARCH_TIMER_CTRL_ENABLE;
1684891f015SMarc Zyngier ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;
1694891f015SMarc Zyngier
1704891f015SMarc Zyngier cnt = arch_counter_mmio_get_cnt(timer);
1714891f015SMarc Zyngier
1724891f015SMarc Zyngier arch_timer_mmio_write(timer, ARCH_TIMER_REG_CVAL, evt + cnt);
1734891f015SMarc Zyngier arch_timer_mmio_write(timer, ARCH_TIMER_REG_CTRL, ctrl);
1744891f015SMarc Zyngier return 0;
1754891f015SMarc Zyngier }
1764891f015SMarc Zyngier
arch_timer_mmio_handler(int irq,void * dev_id)1774891f015SMarc Zyngier static irqreturn_t arch_timer_mmio_handler(int irq, void *dev_id)
1784891f015SMarc Zyngier {
1794891f015SMarc Zyngier struct clock_event_device *evt = dev_id;
1804891f015SMarc Zyngier struct arch_timer *at = evt_to_arch_timer(evt);
1814891f015SMarc Zyngier unsigned long ctrl;
1824891f015SMarc Zyngier
1834891f015SMarc Zyngier ctrl = arch_timer_mmio_read(at, ARCH_TIMER_REG_CTRL);
1844891f015SMarc Zyngier if (ctrl & ARCH_TIMER_CTRL_IT_STAT) {
1854891f015SMarc Zyngier ctrl |= ARCH_TIMER_CTRL_IT_MASK;
1864891f015SMarc Zyngier arch_timer_mmio_write(at, ARCH_TIMER_REG_CTRL, ctrl);
1874891f015SMarc Zyngier evt->event_handler(evt);
1884891f015SMarc Zyngier return IRQ_HANDLED;
1894891f015SMarc Zyngier }
1904891f015SMarc Zyngier
1914891f015SMarc Zyngier return IRQ_NONE;
1924891f015SMarc Zyngier }
1934891f015SMarc Zyngier
find_best_frame(struct platform_device * pdev)1944891f015SMarc Zyngier static struct arch_timer_mem_frame *find_best_frame(struct platform_device *pdev)
1954891f015SMarc Zyngier {
1964891f015SMarc Zyngier struct arch_timer_mem_frame *frame, *best_frame = NULL;
1974891f015SMarc Zyngier struct arch_timer *at = platform_get_drvdata(pdev);
1984891f015SMarc Zyngier void __iomem *cntctlbase;
1994891f015SMarc Zyngier u32 cnttidr;
2004891f015SMarc Zyngier
2014891f015SMarc Zyngier cntctlbase = ioremap(at->gt_block->cntctlbase, at->gt_block->size);
2024891f015SMarc Zyngier if (!cntctlbase) {
2034891f015SMarc Zyngier dev_err(&pdev->dev, "Can't map CNTCTLBase @ %pa\n",
2044891f015SMarc Zyngier &at->gt_block->cntctlbase);
2054891f015SMarc Zyngier return NULL;
2064891f015SMarc Zyngier }
2074891f015SMarc Zyngier
2084891f015SMarc Zyngier cnttidr = readl_relaxed(cntctlbase + CNTTIDR);
2094891f015SMarc Zyngier
2104891f015SMarc Zyngier /*
2114891f015SMarc Zyngier * Try to find a virtual capable frame. Otherwise fall back to a
2124891f015SMarc Zyngier * physical capable frame.
2134891f015SMarc Zyngier */
2144891f015SMarc Zyngier for (int i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {
2154891f015SMarc Zyngier u32 cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT |
2164891f015SMarc Zyngier CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT;
2174891f015SMarc Zyngier
2184891f015SMarc Zyngier frame = &at->gt_block->frame[i];
2194891f015SMarc Zyngier if (!frame->valid)
2204891f015SMarc Zyngier continue;
2214891f015SMarc Zyngier
2224891f015SMarc Zyngier /* Try enabling everything, and see what sticks */
2234891f015SMarc Zyngier writel_relaxed(cntacr, cntctlbase + CNTACR(i));
2244891f015SMarc Zyngier cntacr = readl_relaxed(cntctlbase + CNTACR(i));
2254891f015SMarc Zyngier
2264891f015SMarc Zyngier /* Pick a suitable frame for which we have an IRQ */
2274891f015SMarc Zyngier if ((cnttidr & CNTTIDR_VIRT(i)) &&
2284891f015SMarc Zyngier !(~cntacr & (CNTACR_RWVT | CNTACR_RVCT)) &&
2294891f015SMarc Zyngier frame->virt_irq) {
2304891f015SMarc Zyngier best_frame = frame;
2314891f015SMarc Zyngier at->access = VIRT_ACCESS;
2324891f015SMarc Zyngier break;
2334891f015SMarc Zyngier }
2344891f015SMarc Zyngier
2354891f015SMarc Zyngier if ((~cntacr & (CNTACR_RWPT | CNTACR_RPCT)) ||
2364891f015SMarc Zyngier !frame->phys_irq)
2374891f015SMarc Zyngier continue;
2384891f015SMarc Zyngier
2394891f015SMarc Zyngier at->access = PHYS_ACCESS;
2404891f015SMarc Zyngier best_frame = frame;
2414891f015SMarc Zyngier }
2424891f015SMarc Zyngier
2434891f015SMarc Zyngier iounmap(cntctlbase);
2444891f015SMarc Zyngier
2454891f015SMarc Zyngier return best_frame;
2464891f015SMarc Zyngier }
2474891f015SMarc Zyngier
arch_timer_mmio_setup(struct arch_timer * at,int irq)2484891f015SMarc Zyngier static void arch_timer_mmio_setup(struct arch_timer *at, int irq)
2494891f015SMarc Zyngier {
2504891f015SMarc Zyngier at->evt = (struct clock_event_device) {
2514891f015SMarc Zyngier .features = (CLOCK_EVT_FEAT_ONESHOT |
2524891f015SMarc Zyngier CLOCK_EVT_FEAT_DYNIRQ),
2534891f015SMarc Zyngier .name = "arch_mem_timer",
2544891f015SMarc Zyngier .rating = 400,
2554891f015SMarc Zyngier .cpumask = cpu_possible_mask,
2564891f015SMarc Zyngier .irq = irq,
2574891f015SMarc Zyngier .set_next_event = arch_timer_mmio_set_next_event,
2584891f015SMarc Zyngier .set_state_oneshot_stopped = arch_timer_mmio_shutdown,
2594891f015SMarc Zyngier .set_state_shutdown = arch_timer_mmio_shutdown,
2604891f015SMarc Zyngier };
2614891f015SMarc Zyngier
2624891f015SMarc Zyngier at->evt.set_state_shutdown(&at->evt);
2634891f015SMarc Zyngier
2644891f015SMarc Zyngier clockevents_config_and_register(&at->evt, at->rate, 0xf,
2654891f015SMarc Zyngier (unsigned long)CLOCKSOURCE_MASK(56));
2664891f015SMarc Zyngier
2674891f015SMarc Zyngier enable_irq(at->evt.irq);
268*4e9bfe69SMarc Zyngier
269*4e9bfe69SMarc Zyngier at->cs = (struct clocksource) {
270*4e9bfe69SMarc Zyngier .name = "arch_mmio_counter",
271*4e9bfe69SMarc Zyngier .rating = 300,
272*4e9bfe69SMarc Zyngier .read = arch_mmio_counter_read,
273*4e9bfe69SMarc Zyngier .mask = CLOCKSOURCE_MASK(56),
274*4e9bfe69SMarc Zyngier .flags = CLOCK_SOURCE_IS_CONTINUOUS,
275*4e9bfe69SMarc Zyngier };
276*4e9bfe69SMarc Zyngier
277*4e9bfe69SMarc Zyngier clocksource_register_hz(&at->cs, at->rate);
2784891f015SMarc Zyngier }
2794891f015SMarc Zyngier
arch_timer_mmio_frame_register(struct platform_device * pdev,struct arch_timer_mem_frame * frame)2804891f015SMarc Zyngier static int arch_timer_mmio_frame_register(struct platform_device *pdev,
2814891f015SMarc Zyngier struct arch_timer_mem_frame *frame)
2824891f015SMarc Zyngier {
2834891f015SMarc Zyngier struct arch_timer *at = platform_get_drvdata(pdev);
2844891f015SMarc Zyngier struct device_node *np = pdev->dev.of_node;
2854891f015SMarc Zyngier int ret, irq;
2864891f015SMarc Zyngier u32 rate;
2874891f015SMarc Zyngier
2884891f015SMarc Zyngier if (!devm_request_mem_region(&pdev->dev, frame->cntbase, frame->size,
2894891f015SMarc Zyngier "arch_mem_timer"))
2904891f015SMarc Zyngier return -EBUSY;
2914891f015SMarc Zyngier
2924891f015SMarc Zyngier at->base = devm_ioremap(&pdev->dev, frame->cntbase, frame->size);
2934891f015SMarc Zyngier if (!at->base) {
2944891f015SMarc Zyngier dev_err(&pdev->dev, "Can't map frame's registers\n");
2954891f015SMarc Zyngier return -ENXIO;
2964891f015SMarc Zyngier }
2974891f015SMarc Zyngier
2984891f015SMarc Zyngier /*
2994891f015SMarc Zyngier * Allow "clock-frequency" to override the probed rate. If neither
3004891f015SMarc Zyngier * lead to something useful, use the CPU timer frequency as the
3014891f015SMarc Zyngier * fallback. The nice thing about that last point is that we woudn't
3024891f015SMarc Zyngier * made it here if we didn't have a valid frequency.
3034891f015SMarc Zyngier */
3044891f015SMarc Zyngier rate = readl_relaxed(at->base + CNTFRQ);
3054891f015SMarc Zyngier
3064891f015SMarc Zyngier if (!np || of_property_read_u32(np, "clock-frequency", &at->rate))
3074891f015SMarc Zyngier at->rate = rate;
3084891f015SMarc Zyngier
3094891f015SMarc Zyngier if (!at->rate)
3104891f015SMarc Zyngier at->rate = arch_timer_get_rate();
3114891f015SMarc Zyngier
3124891f015SMarc Zyngier irq = at->access == VIRT_ACCESS ? frame->virt_irq : frame->phys_irq;
3134891f015SMarc Zyngier ret = devm_request_irq(&pdev->dev, irq, arch_timer_mmio_handler,
3144891f015SMarc Zyngier IRQF_TIMER | IRQF_NO_AUTOEN, "arch_mem_timer",
3154891f015SMarc Zyngier &at->evt);
3164891f015SMarc Zyngier if (ret) {
3174891f015SMarc Zyngier dev_err(&pdev->dev, "Failed to request mem timer irq\n");
3184891f015SMarc Zyngier return ret;
3194891f015SMarc Zyngier }
3204891f015SMarc Zyngier
3214891f015SMarc Zyngier /* Afer this point, we're not allowed to fail anymore */
3224891f015SMarc Zyngier arch_timer_mmio_setup(at, irq);
3234891f015SMarc Zyngier return 0;
3244891f015SMarc Zyngier }
3254891f015SMarc Zyngier
of_populate_gt_block(struct platform_device * pdev,struct arch_timer * at)3264891f015SMarc Zyngier static int of_populate_gt_block(struct platform_device *pdev,
3274891f015SMarc Zyngier struct arch_timer *at)
3284891f015SMarc Zyngier {
3294891f015SMarc Zyngier struct resource res;
3304891f015SMarc Zyngier
3314891f015SMarc Zyngier if (of_address_to_resource(pdev->dev.of_node, 0, &res))
3324891f015SMarc Zyngier return -EINVAL;
3334891f015SMarc Zyngier
3344891f015SMarc Zyngier at->gt_block->cntctlbase = res.start;
3354891f015SMarc Zyngier at->gt_block->size = resource_size(&res);
3364891f015SMarc Zyngier
3374891f015SMarc Zyngier for_each_available_child_of_node_scoped(pdev->dev.of_node, frame_node) {
3384891f015SMarc Zyngier struct arch_timer_mem_frame *frame;
3394891f015SMarc Zyngier u32 n;
3404891f015SMarc Zyngier
3414891f015SMarc Zyngier if (of_property_read_u32(frame_node, "frame-number", &n)) {
3424891f015SMarc Zyngier dev_err(&pdev->dev, FW_BUG "Missing frame-number\n");
3434891f015SMarc Zyngier return -EINVAL;
3444891f015SMarc Zyngier }
3454891f015SMarc Zyngier if (n >= ARCH_TIMER_MEM_MAX_FRAMES) {
3464891f015SMarc Zyngier dev_err(&pdev->dev,
3474891f015SMarc Zyngier FW_BUG "Wrong frame-number, only 0-%u are permitted\n",
3484891f015SMarc Zyngier ARCH_TIMER_MEM_MAX_FRAMES - 1);
3494891f015SMarc Zyngier return -EINVAL;
3504891f015SMarc Zyngier }
3514891f015SMarc Zyngier
3524891f015SMarc Zyngier frame = &at->gt_block->frame[n];
3534891f015SMarc Zyngier
3544891f015SMarc Zyngier if (frame->valid) {
3554891f015SMarc Zyngier dev_err(&pdev->dev, FW_BUG "Duplicated frame-number\n");
3564891f015SMarc Zyngier return -EINVAL;
3574891f015SMarc Zyngier }
3584891f015SMarc Zyngier
3594891f015SMarc Zyngier if (of_address_to_resource(frame_node, 0, &res))
3604891f015SMarc Zyngier return -EINVAL;
3614891f015SMarc Zyngier
3624891f015SMarc Zyngier frame->cntbase = res.start;
3634891f015SMarc Zyngier frame->size = resource_size(&res);
3644891f015SMarc Zyngier
3654891f015SMarc Zyngier frame->phys_irq = irq_of_parse_and_map(frame_node, 0);
3664891f015SMarc Zyngier frame->virt_irq = irq_of_parse_and_map(frame_node, 1);
3674891f015SMarc Zyngier
3684891f015SMarc Zyngier frame->valid = true;
3694891f015SMarc Zyngier }
3704891f015SMarc Zyngier
3714891f015SMarc Zyngier return 0;
3724891f015SMarc Zyngier }
3734891f015SMarc Zyngier
arch_timer_mmio_probe(struct platform_device * pdev)3744891f015SMarc Zyngier static int arch_timer_mmio_probe(struct platform_device *pdev)
3754891f015SMarc Zyngier {
3764891f015SMarc Zyngier struct arch_timer_mem_frame *frame;
3774891f015SMarc Zyngier struct arch_timer *at;
3784891f015SMarc Zyngier struct device_node *np;
3794891f015SMarc Zyngier int ret;
3804891f015SMarc Zyngier
3814891f015SMarc Zyngier np = pdev->dev.of_node;
3824891f015SMarc Zyngier
3834891f015SMarc Zyngier at = devm_kmalloc(&pdev->dev, sizeof(*at), GFP_KERNEL | __GFP_ZERO);
3844891f015SMarc Zyngier if (!at)
3854891f015SMarc Zyngier return -ENOMEM;
3864891f015SMarc Zyngier
3874891f015SMarc Zyngier if (np) {
3884891f015SMarc Zyngier at->gt_block = devm_kmalloc(&pdev->dev, sizeof(*at->gt_block),
3894891f015SMarc Zyngier GFP_KERNEL | __GFP_ZERO);
3904891f015SMarc Zyngier if (!at->gt_block)
3914891f015SMarc Zyngier return -ENOMEM;
3924891f015SMarc Zyngier ret = of_populate_gt_block(pdev, at);
3934891f015SMarc Zyngier if (ret)
3944891f015SMarc Zyngier return ret;
3954891f015SMarc Zyngier } else {
3964891f015SMarc Zyngier at->gt_block = dev_get_platdata(&pdev->dev);
3974891f015SMarc Zyngier }
3984891f015SMarc Zyngier
3994891f015SMarc Zyngier platform_set_drvdata(pdev, at);
4004891f015SMarc Zyngier
4014891f015SMarc Zyngier frame = find_best_frame(pdev);
4024891f015SMarc Zyngier if (!frame) {
4034891f015SMarc Zyngier dev_err(&pdev->dev,
4044891f015SMarc Zyngier "Unable to find a suitable frame in timer @ %pa\n",
4054891f015SMarc Zyngier &at->gt_block->cntctlbase);
4064891f015SMarc Zyngier return -EINVAL;
4074891f015SMarc Zyngier }
4084891f015SMarc Zyngier
4094891f015SMarc Zyngier ret = arch_timer_mmio_frame_register(pdev, frame);
4104891f015SMarc Zyngier if (!ret)
4114891f015SMarc Zyngier dev_info(&pdev->dev,
4124891f015SMarc Zyngier "mmio timer running at %lu.%02luMHz (%s)\n",
4134891f015SMarc Zyngier (unsigned long)at->rate / 1000000,
4144891f015SMarc Zyngier (unsigned long)(at->rate / 10000) % 100,
4154891f015SMarc Zyngier at->access == VIRT_ACCESS ? "virt" : "phys");
4164891f015SMarc Zyngier
4174891f015SMarc Zyngier return ret;
4184891f015SMarc Zyngier }
4194891f015SMarc Zyngier
4204891f015SMarc Zyngier static const struct of_device_id arch_timer_mmio_of_table[] = {
4214891f015SMarc Zyngier { .compatible = "arm,armv7-timer-mem", },
4224891f015SMarc Zyngier {}
4234891f015SMarc Zyngier };
4244891f015SMarc Zyngier
4254891f015SMarc Zyngier static struct platform_driver arch_timer_mmio_drv = {
4264891f015SMarc Zyngier .driver = {
4274891f015SMarc Zyngier .name = "arch-timer-mmio",
4284891f015SMarc Zyngier .of_match_table = arch_timer_mmio_of_table,
4294891f015SMarc Zyngier },
4304891f015SMarc Zyngier .probe = arch_timer_mmio_probe,
4314891f015SMarc Zyngier };
4324891f015SMarc Zyngier builtin_platform_driver(arch_timer_mmio_drv);
4334891f015SMarc Zyngier
4344891f015SMarc Zyngier static struct platform_driver arch_timer_mmio_acpi_drv = {
4354891f015SMarc Zyngier .driver = {
4364891f015SMarc Zyngier .name = "gtdt-arm-mmio-timer",
4374891f015SMarc Zyngier },
4384891f015SMarc Zyngier .probe = arch_timer_mmio_probe,
4394891f015SMarc Zyngier };
4404891f015SMarc Zyngier builtin_platform_driver(arch_timer_mmio_acpi_drv);
441