realtek: use DT provided address for timers
authorSander Vanheule <sander@svanheule.net>
Sun, 20 Feb 2022 16:17:17 +0000 (17:17 +0100)
committerDaniel Golle <daniel@makrotopia.org>
Sun, 20 Feb 2022 16:23:58 +0000 (16:23 +0000)
The I/O base address for the timers was hardcoded into the driver,
or derived from the HW IRQ number as an even more horrible hack. All
supported SoC families have these timers, but with hardcoded addresses
the code cannot be reused right now.

Request the timer's base address from the DT specification, and store it
in a private struct for future reference.

Matching the second interrupt specifier, the address range for the
second timer is added to the DT specification.

Signed-off-by: Sander Vanheule <sander@svanheule.net>
target/linux/realtek/dts-5.10/rtl930x.dtsi
target/linux/realtek/files-5.10/arch/mips/kernel/cevt-rtl9300.c

index 0ac613454f58932ad96b5b6187f50dec99b75418..bfde5e6ff6ae82d55f67ee82de762ed8d88eb42f 100644 (file)
@@ -59,7 +59,7 @@
 
                rtl9300clock: rtl9300clock@3200 {
                        compatible = "realtek,rtl9300clock";
-                       reg = <0x3200 0x10>;
+                       reg = <0x3200 0x10>, <0x3210 0x10>;
 
                        interrupt-parent = <&intc>;
                        interrupts = <7 5>, <8 5>;
index cf3a4fe437d81f55ea9ca25ffbb0f4d8ec59ee11..cbbea7d68605c235b6d1f8cb4fafea6ee2a06a59 100644 (file)
 #define RTL9300_TC_INT_IP      BIT(16)
 #define RTL9300_TC_INT_IE      BIT(20)
 
-// Clocksource is using timer 0, clock event uses timer 1
-#define TIMER_CLK_SRC          0
-#define TIMER_CLK_EVT          0
-#define TIMER_BLK_EVT          (TIMER_CLK_EVT << 4)
-
 // Timer modes
 #define TIMER_MODE_REPEAT      1
 #define TIMER_MODE_ONCE                0
 
 #define N_BITS                 28
 
-#define RTL9300_TC1_IRQ                8
 #define RTL9300_CLOCK_RATE     87500000
-#define RTL9300_TC0_BASE       (void *)0xb8003200
 
-int irq_tc0 = 7;
+struct rtl9300_clk_dev {
+       struct clock_event_device clkdev;
+       void __iomem *base;
+};
 
 static void __iomem *rtl9300_tc_base(struct clock_event_device *clk)
 {
-       struct irq_desc *desc = irq_to_desc(clk->irq);
-       int tc = desc->irq_data.hwirq - irq_tc0;
+       struct rtl9300_clk_dev *rtl_clk = container_of(clk, struct rtl9300_clk_dev, clkdev);
 
-       return RTL9300_TC0_BASE + (tc << 4);
+       return rtl_clk->base;
 }
 
 static irqreturn_t rtl9300_timer_interrupt(int irq, void *dev_id)
 {
-       struct clock_event_device *clk = dev_id;
+       struct rtl9300_clk_dev *rtl_clk = dev_id;
+       struct clock_event_device *clk = &rtl_clk->clkdev;
 //     int cpu = smp_processor_id();
-       struct irq_desc *desc = irq_to_desc(irq);
-       int tc = desc->irq_data.hwirq - irq_tc0;
-       void __iomem *base = RTL9300_TC0_BASE + (tc << 4);
        static atomic_t count = ATOMIC_INIT(0);
        unsigned int c;
-       u32 v = readl(base + RTL9300_TC_INT);
+       u32 v = readl(rtl_clk->base + RTL9300_TC_INT);
 
        c = (unsigned int)atomic_inc_return(&count);
 
        // Acknowledge the IRQ
        v |= RTL9300_TC_INT_IP;
-       writel(v, base + RTL9300_TC_INT);
-       if (readl(base + RTL9300_TC_INT) & RTL9300_TC_INT_IP)
+       writel(v, rtl_clk->base + RTL9300_TC_INT);
+       if (readl(rtl_clk->base + RTL9300_TC_INT) & RTL9300_TC_INT_IP)
                dump_stack();
 
        clk->event_handler(clk);
@@ -158,14 +151,15 @@ static void rtl9300_clock_setup(void __iomem *base)
        writel(0x0fffffff, base + RTL9300_TC_DATA);
 }
 
-static DEFINE_PER_CPU(struct clock_event_device, rtl9300_clockevent);
+static DEFINE_PER_CPU(struct rtl9300_clk_dev, rtl9300_clockevent);
 static DEFINE_PER_CPU(char [18], rtl9300_clock_name);
 
 void rtl9300_clockevent_init(void)
 {
        int cpu = smp_processor_id();
        int irq;
-       struct clock_event_device *cd = &per_cpu(rtl9300_clockevent, cpu);
+       struct rtl9300_clk_dev *rtl_clk = &per_cpu(rtl9300_clockevent, cpu);
+       struct clock_event_device *cd = &rtl_clk->clkdev;
        unsigned char *name = per_cpu(rtl9300_clock_name, cpu);
        unsigned long flags =  IRQF_PERCPU | IRQF_TIMER;
        struct device_node *node;
@@ -182,7 +176,13 @@ void rtl9300_clockevent_init(void)
        irq = irq_of_parse_and_map(node, cpu);
        pr_info("%s using IRQ %d\n", __func__, irq);
 
-       rtl9300_clock_setup(RTL9300_TC0_BASE + TIMER_BLK_EVT + (cpu << 4));
+       rtl_clk->base = of_iomap(node, cpu);
+       if (!rtl_clk->base) {
+               pr_err("cannot map timer for cpu %d", cpu);
+               return;
+       }
+
+       rtl9300_clock_setup(rtl_clk->base);
 
        sprintf(name, "rtl9300-counter-%d", cpu);
        cd->name                = name;
@@ -205,8 +205,8 @@ void rtl9300_clockevent_init(void)
 
        irq_set_affinity(irq, cd->cpumask);
 
-       if (request_irq(irq, rtl9300_timer_interrupt, flags, name, cd))
+       if (request_irq(irq, rtl9300_timer_interrupt, flags, name, rtl_clk))
                pr_err("Failed to request irq %d (%s)\n", irq, name);
 
-       writel(RTL9300_TC_INT_IE, RTL9300_TC0_BASE + TIMER_BLK_EVT + (cpu << 4) + RTL9300_TC_INT);
+       writel(RTL9300_TC_INT_IE, rtl_clk->base + RTL9300_TC_INT);
 }