Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0+ 2 : : /* 3 : : * Copyright 2012 Simon Arlott 4 : : */ 5 : : 6 : : #include <linux/bitops.h> 7 : : #include <linux/clockchips.h> 8 : : #include <linux/clocksource.h> 9 : : #include <linux/interrupt.h> 10 : : #include <linux/irqreturn.h> 11 : : #include <linux/kernel.h> 12 : : #include <linux/module.h> 13 : : #include <linux/of_address.h> 14 : : #include <linux/of_irq.h> 15 : : #include <linux/of_platform.h> 16 : : #include <linux/slab.h> 17 : : #include <linux/string.h> 18 : : #include <linux/sched_clock.h> 19 : : 20 : : #include <asm/irq.h> 21 : : 22 : : #define REG_CONTROL 0x00 23 : : #define REG_COUNTER_LO 0x04 24 : : #define REG_COUNTER_HI 0x08 25 : : #define REG_COMPARE(n) (0x0c + (n) * 4) 26 : : #define MAX_TIMER 3 27 : : #define DEFAULT_TIMER 3 28 : : 29 : : struct bcm2835_timer { 30 : : void __iomem *control; 31 : : void __iomem *compare; 32 : : int match_mask; 33 : : struct clock_event_device evt; 34 : : struct irqaction act; 35 : : }; 36 : : 37 : : static void __iomem *system_clock __read_mostly; 38 : : 39 : 0 : static u64 notrace bcm2835_sched_read(void) 40 : : { 41 : 0 : return readl_relaxed(system_clock); 42 : : } 43 : : 44 : 0 : static int bcm2835_time_set_next_event(unsigned long event, 45 : : struct clock_event_device *evt_dev) 46 : : { 47 : : struct bcm2835_timer *timer = container_of(evt_dev, 48 : : struct bcm2835_timer, evt); 49 : 0 : writel_relaxed(readl_relaxed(system_clock) + event, 50 : : timer->compare); 51 : 0 : return 0; 52 : : } 53 : : 54 : 0 : static irqreturn_t bcm2835_time_interrupt(int irq, void *dev_id) 55 : : { 56 : : struct bcm2835_timer *timer = dev_id; 57 : : void (*event_handler)(struct clock_event_device *); 58 : 0 : if (readl_relaxed(timer->control) & timer->match_mask) { 59 : : writel_relaxed(timer->match_mask, timer->control); 60 : : 61 : 0 : event_handler = READ_ONCE(timer->evt.event_handler); 62 : 0 : if (event_handler) 63 : 0 : event_handler(&timer->evt); 64 : : return IRQ_HANDLED; 65 : : } else { 66 : : return IRQ_NONE; 67 : : } 68 : : } 69 : : 70 : 0 : static int __init bcm2835_timer_init(struct device_node *node) 71 : : { 72 : : void __iomem *base; 73 : : u32 freq; 74 : : int irq, ret; 75 : : struct bcm2835_timer *timer; 76 : : 77 : 0 : base = of_iomap(node, 0); 78 : 0 : if (!base) { 79 : 0 : pr_err("Can't remap registers\n"); 80 : 0 : return -ENXIO; 81 : : } 82 : : 83 : : ret = of_property_read_u32(node, "clock-frequency", &freq); 84 : 0 : if (ret) { 85 : 0 : pr_err("Can't read clock-frequency\n"); 86 : 0 : goto err_iounmap; 87 : : } 88 : : 89 : 0 : system_clock = base + REG_COUNTER_LO; 90 : 0 : sched_clock_register(bcm2835_sched_read, 32, freq); 91 : : 92 : 0 : clocksource_mmio_init(base + REG_COUNTER_LO, node->name, 93 : : freq, 300, 32, clocksource_mmio_readl_up); 94 : : 95 : 0 : irq = irq_of_parse_and_map(node, DEFAULT_TIMER); 96 : 0 : if (irq <= 0) { 97 : 0 : pr_err("Can't parse IRQ\n"); 98 : : ret = -EINVAL; 99 : 0 : goto err_iounmap; 100 : : } 101 : : 102 : 0 : timer = kzalloc(sizeof(*timer), GFP_KERNEL); 103 : 0 : if (!timer) { 104 : : ret = -ENOMEM; 105 : : goto err_iounmap; 106 : : } 107 : : 108 : 0 : timer->control = base + REG_CONTROL; 109 : 0 : timer->compare = base + REG_COMPARE(DEFAULT_TIMER); 110 : 0 : timer->match_mask = BIT(DEFAULT_TIMER); 111 : 0 : timer->evt.name = node->name; 112 : 0 : timer->evt.rating = 300; 113 : 0 : timer->evt.features = CLOCK_EVT_FEAT_ONESHOT; 114 : 0 : timer->evt.set_next_event = bcm2835_time_set_next_event; 115 : 0 : timer->evt.cpumask = cpumask_of(0); 116 : 0 : timer->act.name = node->name; 117 : 0 : timer->act.flags = IRQF_TIMER | IRQF_SHARED; 118 : 0 : timer->act.dev_id = timer; 119 : 0 : timer->act.handler = bcm2835_time_interrupt; 120 : : 121 : 0 : ret = setup_irq(irq, &timer->act); 122 : 0 : if (ret) { 123 : 0 : pr_err("Can't set up timer IRQ\n"); 124 : : goto err_timer_free; 125 : : } 126 : : 127 : 0 : clockevents_config_and_register(&timer->evt, freq, 0xf, 0xffffffff); 128 : : 129 : 0 : pr_info("bcm2835: system timer (irq = %d)\n", irq); 130 : : 131 : 0 : return 0; 132 : : 133 : : err_timer_free: 134 : 0 : kfree(timer); 135 : : 136 : : err_iounmap: 137 : 0 : iounmap(base); 138 : 0 : return ret; 139 : : } 140 : : TIMER_OF_DECLARE(bcm2835, "brcm,bcm2835-system-timer", 141 : : bcm2835_timer_init);