Skip to content
Snippets Groups Projects
Commit 9db651f4 authored by Sander Vanheule's avatar Sander Vanheule Committed by Daniel Golle
Browse files

realtek: use DT provided address for timers


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: default avatarSander Vanheule <sander@svanheule.net>
parent 71810eb0
No related branches found
No related tags found
No related merge requests found
......@@ -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>;
......
......@@ -24,11 +24,6 @@
#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
......@@ -38,37 +33,35 @@
#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);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment