Path: blob/master/drivers/clocksource/arm_arch_timer_mmio.c
29267 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* ARM Generic Memory Mapped Timer support3*4* Split from drivers/clocksource/arm_arch_timer.c5*6* Copyright (C) 2011 ARM Ltd.7* All Rights Reserved8*/910#define pr_fmt(fmt) "arch_timer_mmio: " fmt1112#include <linux/clockchips.h>13#include <linux/interrupt.h>14#include <linux/io-64-nonatomic-lo-hi.h>15#include <linux/of_irq.h>16#include <linux/of_address.h>17#include <linux/platform_device.h>1819#include <clocksource/arm_arch_timer.h>2021#define CNTTIDR 0x0822#define CNTTIDR_VIRT(n) (BIT(1) << ((n) * 4))2324#define CNTACR(n) (0x40 + ((n) * 4))25#define CNTACR_RPCT BIT(0)26#define CNTACR_RVCT BIT(1)27#define CNTACR_RFRQ BIT(2)28#define CNTACR_RVOFF BIT(3)29#define CNTACR_RWVT BIT(4)30#define CNTACR_RWPT BIT(5)3132#define CNTPCT_LO 0x0033#define CNTVCT_LO 0x0834#define CNTFRQ 0x1035#define CNTP_CVAL_LO 0x2036#define CNTP_CTL 0x2c37#define CNTV_CVAL_LO 0x3038#define CNTV_CTL 0x3c3940enum arch_timer_access {41PHYS_ACCESS,42VIRT_ACCESS,43};4445struct arch_timer {46struct clock_event_device evt;47struct clocksource cs;48struct arch_timer_mem *gt_block;49void __iomem *base;50enum arch_timer_access access;51u32 rate;52};5354#define evt_to_arch_timer(e) container_of(e, struct arch_timer, evt)55#define cs_to_arch_timer(c) container_of(c, struct arch_timer, cs)5657static void arch_timer_mmio_write(struct arch_timer *timer,58enum arch_timer_reg reg, u64 val)59{60switch (timer->access) {61case PHYS_ACCESS:62switch (reg) {63case ARCH_TIMER_REG_CTRL:64writel_relaxed((u32)val, timer->base + CNTP_CTL);65return;66case ARCH_TIMER_REG_CVAL:67/*68* Not guaranteed to be atomic, so the timer69* must be disabled at this point.70*/71writeq_relaxed(val, timer->base + CNTP_CVAL_LO);72return;73}74break;75case VIRT_ACCESS:76switch (reg) {77case ARCH_TIMER_REG_CTRL:78writel_relaxed((u32)val, timer->base + CNTV_CTL);79return;80case ARCH_TIMER_REG_CVAL:81/* Same restriction as above */82writeq_relaxed(val, timer->base + CNTV_CVAL_LO);83return;84}85break;86}8788/* Should never be here */89WARN_ON_ONCE(1);90}9192static u32 arch_timer_mmio_read(struct arch_timer *timer, enum arch_timer_reg reg)93{94switch (timer->access) {95case PHYS_ACCESS:96switch (reg) {97case ARCH_TIMER_REG_CTRL:98return readl_relaxed(timer->base + CNTP_CTL);99default:100break;101}102break;103case VIRT_ACCESS:104switch (reg) {105case ARCH_TIMER_REG_CTRL:106return readl_relaxed(timer->base + CNTV_CTL);107default:108break;109}110break;111}112113/* Should never be here */114WARN_ON_ONCE(1);115return 0;116}117118static noinstr u64 arch_counter_mmio_get_cnt(struct arch_timer *t)119{120int offset_lo = t->access == VIRT_ACCESS ? CNTVCT_LO : CNTPCT_LO;121u32 cnt_lo, cnt_hi, tmp_hi;122123do {124cnt_hi = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo + 4));125cnt_lo = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo));126tmp_hi = __le32_to_cpu((__le32 __force)__raw_readl(t->base + offset_lo + 4));127} while (cnt_hi != tmp_hi);128129return ((u64) cnt_hi << 32) | cnt_lo;130}131132static u64 arch_mmio_counter_read(struct clocksource *cs)133{134struct arch_timer *at = cs_to_arch_timer(cs);135136return arch_counter_mmio_get_cnt(at);137}138139static int arch_timer_mmio_shutdown(struct clock_event_device *clk)140{141struct arch_timer *at = evt_to_arch_timer(clk);142unsigned long ctrl;143144ctrl = arch_timer_mmio_read(at, ARCH_TIMER_REG_CTRL);145ctrl &= ~ARCH_TIMER_CTRL_ENABLE;146arch_timer_mmio_write(at, ARCH_TIMER_REG_CTRL, ctrl);147148return 0;149}150151static int arch_timer_mmio_set_next_event(unsigned long evt,152struct clock_event_device *clk)153{154struct arch_timer *timer = evt_to_arch_timer(clk);155unsigned long ctrl;156u64 cnt;157158ctrl = arch_timer_mmio_read(timer, ARCH_TIMER_REG_CTRL);159160/* Timer must be disabled before programming CVAL */161if (ctrl & ARCH_TIMER_CTRL_ENABLE) {162ctrl &= ~ARCH_TIMER_CTRL_ENABLE;163arch_timer_mmio_write(timer, ARCH_TIMER_REG_CTRL, ctrl);164}165166ctrl |= ARCH_TIMER_CTRL_ENABLE;167ctrl &= ~ARCH_TIMER_CTRL_IT_MASK;168169cnt = arch_counter_mmio_get_cnt(timer);170171arch_timer_mmio_write(timer, ARCH_TIMER_REG_CVAL, evt + cnt);172arch_timer_mmio_write(timer, ARCH_TIMER_REG_CTRL, ctrl);173return 0;174}175176static irqreturn_t arch_timer_mmio_handler(int irq, void *dev_id)177{178struct clock_event_device *evt = dev_id;179struct arch_timer *at = evt_to_arch_timer(evt);180unsigned long ctrl;181182ctrl = arch_timer_mmio_read(at, ARCH_TIMER_REG_CTRL);183if (ctrl & ARCH_TIMER_CTRL_IT_STAT) {184ctrl |= ARCH_TIMER_CTRL_IT_MASK;185arch_timer_mmio_write(at, ARCH_TIMER_REG_CTRL, ctrl);186evt->event_handler(evt);187return IRQ_HANDLED;188}189190return IRQ_NONE;191}192193static struct arch_timer_mem_frame *find_best_frame(struct platform_device *pdev)194{195struct arch_timer_mem_frame *frame, *best_frame = NULL;196struct arch_timer *at = platform_get_drvdata(pdev);197void __iomem *cntctlbase;198u32 cnttidr;199200cntctlbase = ioremap(at->gt_block->cntctlbase, at->gt_block->size);201if (!cntctlbase) {202dev_err(&pdev->dev, "Can't map CNTCTLBase @ %pa\n",203&at->gt_block->cntctlbase);204return NULL;205}206207cnttidr = readl_relaxed(cntctlbase + CNTTIDR);208209/*210* Try to find a virtual capable frame. Otherwise fall back to a211* physical capable frame.212*/213for (int i = 0; i < ARCH_TIMER_MEM_MAX_FRAMES; i++) {214u32 cntacr = CNTACR_RFRQ | CNTACR_RWPT | CNTACR_RPCT |215CNTACR_RWVT | CNTACR_RVOFF | CNTACR_RVCT;216217frame = &at->gt_block->frame[i];218if (!frame->valid)219continue;220221/* Try enabling everything, and see what sticks */222writel_relaxed(cntacr, cntctlbase + CNTACR(i));223cntacr = readl_relaxed(cntctlbase + CNTACR(i));224225/* Pick a suitable frame for which we have an IRQ */226if ((cnttidr & CNTTIDR_VIRT(i)) &&227!(~cntacr & (CNTACR_RWVT | CNTACR_RVCT)) &&228frame->virt_irq) {229best_frame = frame;230at->access = VIRT_ACCESS;231break;232}233234if ((~cntacr & (CNTACR_RWPT | CNTACR_RPCT)) ||235!frame->phys_irq)236continue;237238at->access = PHYS_ACCESS;239best_frame = frame;240}241242iounmap(cntctlbase);243244return best_frame;245}246247static void arch_timer_mmio_setup(struct arch_timer *at, int irq)248{249at->evt = (struct clock_event_device) {250.features = (CLOCK_EVT_FEAT_ONESHOT |251CLOCK_EVT_FEAT_DYNIRQ),252.name = "arch_mem_timer",253.rating = 400,254.cpumask = cpu_possible_mask,255.irq = irq,256.set_next_event = arch_timer_mmio_set_next_event,257.set_state_oneshot_stopped = arch_timer_mmio_shutdown,258.set_state_shutdown = arch_timer_mmio_shutdown,259};260261at->evt.set_state_shutdown(&at->evt);262263clockevents_config_and_register(&at->evt, at->rate, 0xf,264(unsigned long)CLOCKSOURCE_MASK(56));265266enable_irq(at->evt.irq);267268at->cs = (struct clocksource) {269.name = "arch_mmio_counter",270.rating = 300,271.read = arch_mmio_counter_read,272.mask = CLOCKSOURCE_MASK(56),273.flags = CLOCK_SOURCE_IS_CONTINUOUS,274};275276clocksource_register_hz(&at->cs, at->rate);277}278279static int arch_timer_mmio_frame_register(struct platform_device *pdev,280struct arch_timer_mem_frame *frame)281{282struct arch_timer *at = platform_get_drvdata(pdev);283struct device_node *np = pdev->dev.of_node;284int ret, irq;285u32 rate;286287if (!devm_request_mem_region(&pdev->dev, frame->cntbase, frame->size,288"arch_mem_timer"))289return -EBUSY;290291at->base = devm_ioremap(&pdev->dev, frame->cntbase, frame->size);292if (!at->base) {293dev_err(&pdev->dev, "Can't map frame's registers\n");294return -ENXIO;295}296297/*298* Allow "clock-frequency" to override the probed rate. If neither299* lead to something useful, use the CPU timer frequency as the300* fallback. The nice thing about that last point is that we woudn't301* made it here if we didn't have a valid frequency.302*/303rate = readl_relaxed(at->base + CNTFRQ);304305if (!np || of_property_read_u32(np, "clock-frequency", &at->rate))306at->rate = rate;307308if (!at->rate)309at->rate = arch_timer_get_rate();310311irq = at->access == VIRT_ACCESS ? frame->virt_irq : frame->phys_irq;312ret = devm_request_irq(&pdev->dev, irq, arch_timer_mmio_handler,313IRQF_TIMER | IRQF_NO_AUTOEN, "arch_mem_timer",314&at->evt);315if (ret) {316dev_err(&pdev->dev, "Failed to request mem timer irq\n");317return ret;318}319320/* Afer this point, we're not allowed to fail anymore */321arch_timer_mmio_setup(at, irq);322return 0;323}324325static int of_populate_gt_block(struct platform_device *pdev,326struct arch_timer *at)327{328struct resource res;329330if (of_address_to_resource(pdev->dev.of_node, 0, &res))331return -EINVAL;332333at->gt_block->cntctlbase = res.start;334at->gt_block->size = resource_size(&res);335336for_each_available_child_of_node_scoped(pdev->dev.of_node, frame_node) {337struct arch_timer_mem_frame *frame;338u32 n;339340if (of_property_read_u32(frame_node, "frame-number", &n)) {341dev_err(&pdev->dev, FW_BUG "Missing frame-number\n");342return -EINVAL;343}344if (n >= ARCH_TIMER_MEM_MAX_FRAMES) {345dev_err(&pdev->dev,346FW_BUG "Wrong frame-number, only 0-%u are permitted\n",347ARCH_TIMER_MEM_MAX_FRAMES - 1);348return -EINVAL;349}350351frame = &at->gt_block->frame[n];352353if (frame->valid) {354dev_err(&pdev->dev, FW_BUG "Duplicated frame-number\n");355return -EINVAL;356}357358if (of_address_to_resource(frame_node, 0, &res))359return -EINVAL;360361frame->cntbase = res.start;362frame->size = resource_size(&res);363364frame->phys_irq = irq_of_parse_and_map(frame_node, 0);365frame->virt_irq = irq_of_parse_and_map(frame_node, 1);366367frame->valid = true;368}369370return 0;371}372373static int arch_timer_mmio_probe(struct platform_device *pdev)374{375struct arch_timer_mem_frame *frame;376struct arch_timer *at;377struct device_node *np;378int ret;379380np = pdev->dev.of_node;381382at = devm_kmalloc(&pdev->dev, sizeof(*at), GFP_KERNEL | __GFP_ZERO);383if (!at)384return -ENOMEM;385386if (np) {387at->gt_block = devm_kmalloc(&pdev->dev, sizeof(*at->gt_block),388GFP_KERNEL | __GFP_ZERO);389if (!at->gt_block)390return -ENOMEM;391ret = of_populate_gt_block(pdev, at);392if (ret)393return ret;394} else {395at->gt_block = dev_get_platdata(&pdev->dev);396}397398platform_set_drvdata(pdev, at);399400frame = find_best_frame(pdev);401if (!frame) {402dev_err(&pdev->dev,403"Unable to find a suitable frame in timer @ %pa\n",404&at->gt_block->cntctlbase);405return -EINVAL;406}407408ret = arch_timer_mmio_frame_register(pdev, frame);409if (!ret)410dev_info(&pdev->dev,411"mmio timer running at %lu.%02luMHz (%s)\n",412(unsigned long)at->rate / 1000000,413(unsigned long)(at->rate / 10000) % 100,414at->access == VIRT_ACCESS ? "virt" : "phys");415416return ret;417}418419static const struct of_device_id arch_timer_mmio_of_table[] = {420{ .compatible = "arm,armv7-timer-mem", },421{}422};423424static struct platform_driver arch_timer_mmio_drv = {425.driver = {426.name = "arch-timer-mmio",427.of_match_table = arch_timer_mmio_of_table,428},429.probe = arch_timer_mmio_probe,430};431builtin_platform_driver(arch_timer_mmio_drv);432433static struct platform_driver arch_timer_mmio_acpi_drv = {434.driver = {435.name = "gtdt-arm-mmio-timer",436},437.probe = arch_timer_mmio_probe,438};439builtin_platform_driver(arch_timer_mmio_acpi_drv);440441442