Skip to content

Commit

Permalink
realtek: latest IRQ and timer code for RTL9300
Browse files Browse the repository at this point in the history
  • Loading branch information
bkoblitz committed Nov 29, 2021
1 parent 1257626 commit 61860e0
Show file tree
Hide file tree
Showing 8 changed files with 115 additions and 86 deletions.
77 changes: 39 additions & 38 deletions target/linux/realtek/dts-5.10/rtl930x.dtsi
Expand Up @@ -87,35 +87,35 @@
clock-output-names = "osc";
};

soc: soc {
/* soc: soc {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0x18000000 0x10000>;

*/
intc: rtlintc@3000 {
compatible = "realtek,rtl-intc";
reg = <0x3000 0x18>;
reg = <0xb8003000 0x18>;
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
interrupt-map =
<31 &cpuintc 1>, /* UART1 */
<31 &cpuintc 4>, /* UART1 */
<30 &cpuintc 5>, /* UART0 */
<28 &cpuintc 1>, /* USB_H2 */
<28 &cpuintc 4>, /* USB_H2 */
<24 &cpuintc 4>, /* NIC */
<23 &cpuintc 3>, /* SWCORE */
<13 &cpuintc 4>, /* GPIO_ABCD */
<11 &cpuintc 5>, /* TC4 */
<10 &cpuintc 5>, /* TC3 */
<9 &cpuintc 1>, /* TC2 */
<8 &cpuintc 2>, /* TC1 */
<7 &cpuintc 1>; /* TC0 */
<9 &cpuintc 3>, /* TC2 */
<8 &cpuintc 3>, /* TC1 */
<7 &cpuintc 2>; /* TC0 */
};
/*
intc1: rtlintc@3018 {
compatible = "realtek,rtl-intc";
reg = <0x3018 0x18>;
reg = <0xb8003018 0x18>;
#address-cells = <0>;
#interrupt-cells = <1>;
interrupt-controller;
Expand All @@ -125,7 +125,7 @@
*/
rtl9300clock: rtl9300clock@3200 {
compatible = "realtek,rtl9300clock";
reg = <0x3200 0x10>;
reg = <0xb8003200 0x10>;
#address-cells = <0>;
#interrupt-cells = <1>;

Expand All @@ -135,15 +135,15 @@

spi0: spi@1200 {
compatible = "realtek,rtl8380-spi";
reg = <0x1200 0x100>;
reg = <0xb8001200 0x100>;

#address-cells = <1>;
#size-cells = <0>;
};

uart0: uart@2000 {
compatible = "ns16550a";
reg = <0x2000 0x100>;
reg = <0xb8002000 0x100>;

clock-frequency = <175000000>;

Expand All @@ -158,7 +158,7 @@

uart1: uart@2100 {
compatible = "ns16550a";
reg = <0x2100 0x100>;
reg = <0xb8002100 0x100>;

clock-frequency = <175000000>;

Expand All @@ -173,35 +173,36 @@
status = "disabled";
};

};
gpio0: gpio-controller@b8003500 {
compatible = "realtek,rtl838x-gpio";
reg = <0xb8003500 0x20>;
gpio-controller;
#gpio-cells = <2>;
interrupt-parent = <&intc>;
interrupts = <13>;
};

gpio0: gpio-controller@b8003500 {
compatible = "realtek,rtl838x-gpio";
reg = <0xb8003500 0x20>;
gpio-controller;
#gpio-cells = <2>;
interrupt-parent = <&intc>;
interrupts = <13>;
};
ethernet0: ethernet@1b00a300 {
compatible = "realtek,rtl838x-eth";
reg = <0xbb00a300 0x100>;
interrupt-parent = <&intc>;
interrupts = <24>;
#interrupt-cells = <1>;
phy-mode = "internal";

ethernet0: ethernet@1b00a300 {
compatible = "realtek,rtl838x-eth";
reg = <0x1b00a300 0x100>;
interrupt-parent = <&intc>;
interrupts = <24>;
#interrupt-cells = <1>;
phy-mode = "internal";
fixed-link {
speed = <1000>;
full-duplex;
};

fixed-link {
speed = <1000>;
full-duplex;
};
};

switch0: switch@1b000000 {
compatible = "realtek,rtl83xx-switch";
switch0: switch@1b000000 {
compatible = "realtek,rtl83xx-switch";

interrupt-parent = <&intc>;
interrupts = <20>;
};
// };

interrupt-parent = <&intc>;
interrupts = <20>;
};
};
43 changes: 27 additions & 16 deletions target/linux/realtek/files-5.10/arch/mips/kernel/cevt-rtl9300.c
Expand Up @@ -55,19 +55,27 @@ static void __iomem *rtl9300_tc_base(struct clock_event_device *clk)
static irqreturn_t rtl9300_timer_interrupt(int irq, void *dev_id)
{
struct clock_event_device *clk = dev_id;
int cpu = smp_processor_id();
// 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);

if ((desc->irq_data.hwirq == 7 && cpu) || (desc->irq_data.hwirq == 8 && !cpu))
pr_info("--------------- Timer-IRQ: %lu cpu%d base %08x\n",
desc->irq_data.hwirq, cpu, (u32)base);
c = (unsigned int)atomic_inc_return(&count);

// if ((desc->irq_data.hwirq == 7 && cpu) || (desc->irq_data.hwirq == 8 && !cpu))
/* if (c > 600)
pr_info("--------------- Timer-IRQ: %lu cpu%d base %08x, count %d\n",
desc->irq_data.hwirq, cpu, (u32)base, c);
if (c > 800)
dump_stack();*/
// Acknowledge the IRQ
v |= RTL9300_TC_INT_IP;
writel(v, base + RTL9300_TC_INT);
if (readl(base + RTL9300_TC_INT) & RTL9300_TC_INT_IP)
dump_stack();

clk->event_handler(clk);
return IRQ_HANDLED;
Expand All @@ -81,16 +89,18 @@ static void rtl9300_clock_stop(void __iomem *base)

// Acknowledge possibly pending IRQ
v = readl(base + RTL9300_TC_INT);
if (v & RTL9300_TC_INT_IP)
writel(v, base + RTL9300_TC_INT);
// if (v & RTL9300_TC_INT_IP)
writel(v | RTL9300_TC_INT_IP, base + RTL9300_TC_INT);
if (readl(base + RTL9300_TC_INT) & RTL9300_TC_INT_IP)
dump_stack();
}

static void rtl9300_timer_start(void __iomem *base, bool periodic)
{
u32 v = (periodic ? RTL9300_TC_CTRL_MODE : 0) | RTL9300_TC_CTRL_EN | DIVISOR_RTL9300;

writel(0, base + RTL9300_TC_CNT);
pr_info("------------- starting timer base %08x\n", (u32)base);
pr_debug("------------- starting timer base %08x\n", (u32)base);
writel(v, base + RTL9300_TC_CTRL);
}

Expand All @@ -101,14 +111,15 @@ static int rtl9300_next_event(unsigned long delta, struct clock_event_device *cl
rtl9300_clock_stop(base);
writel(delta, base + RTL9300_TC_DATA);
rtl9300_timer_start(base, TIMER_MODE_ONCE);

return 0;
}

static int rtl9300_state_periodic(struct clock_event_device *clk)
{
void __iomem *base = rtl9300_tc_base(clk);

pr_info("------------- rtl9300_state_periodic %08x\n", (u32)base);
pr_debug("------------- rtl9300_state_periodic %08x\n", (u32)base);
rtl9300_clock_stop(base);
writel(RTL9300_CLOCK_RATE / HZ, base + RTL9300_TC_DATA);
rtl9300_timer_start(base, TIMER_MODE_REPEAT);
Expand All @@ -119,7 +130,7 @@ static int rtl9300_state_oneshot(struct clock_event_device *clk)
{
void __iomem *base = rtl9300_tc_base(clk);

pr_info("------------- rtl9300_state_oneshot %08x\n", (u32)base);
pr_debug("------------- rtl9300_state_oneshot %08x\n", (u32)base);
rtl9300_clock_stop(base);
writel(RTL9300_CLOCK_RATE / HZ, base + RTL9300_TC_DATA);
rtl9300_timer_start(base, TIMER_MODE_ONCE);
Expand All @@ -130,9 +141,8 @@ static int rtl9300_shutdown(struct clock_event_device *clk)
{
void __iomem *base = rtl9300_tc_base(clk);

pr_info("------------- rtl9300_shutdown %08x\n", (u32)base);
pr_debug("------------- rtl9300_shutdown %08x\n", (u32)base);
rtl9300_clock_stop(base);

return 0;
}

Expand All @@ -145,8 +155,10 @@ static void rtl9300_clock_setup(void __iomem *base)

// Acknowledge possibly pending IRQ
v = readl(base + RTL9300_TC_INT);
if (v & RTL9300_TC_INT_IP)
writel(v, base + RTL9300_TC_INT);
// if (v & RTL9300_TC_INT_IP)
writel(v | RTL9300_TC_INT_IP, base + RTL9300_TC_INT);
if (readl(base + RTL9300_TC_INT) & RTL9300_TC_INT_IP)
dump_stack();

// Setup maximum period (for use as clock-source)
writel(0x0fffffff, base + RTL9300_TC_DATA);
Expand All @@ -161,7 +173,7 @@ void rtl9300_clockevent_init(void)
int irq;
struct clock_event_device *cd = &per_cpu(rtl9300_clockevent, cpu);
unsigned char *name = per_cpu(rtl9300_clock_name, cpu);
unsigned long flags = IRQF_PERCPU | IRQF_TIMER | IRQF_SHARED;
unsigned long flags = IRQF_PERCPU | IRQF_TIMER;
struct device_node *node;
int i;
void *b = RTL9300_TC0_BASE;
Expand Down Expand Up @@ -209,5 +221,4 @@ void rtl9300_clockevent_init(void)
for (i = 0; i < 5; i++)
pr_info("%d %08x %08x %08x %08x\n", i, readl(b + i * 16 + 0x0), readl(b + i * 16 + 0x4),
readl(b + i * 16 + 0x8), readl(b + i * 16 + 0xc));

}
4 changes: 4 additions & 0 deletions target/linux/realtek/files-5.10/arch/mips/kernel/smp-mt.c
Expand Up @@ -110,6 +110,10 @@ static void vsmp_init_secondary(void)
pr_info("%s ++++++++++++++\n", __func__);

/* This is Malta specific: IPI,performance and timer interrupts */

/* RTL9300 Clear internal timer interrupt */
write_c0_compare(0);

if (mips_gic_present())
change_c0_status(ST0_IM, STATUSF_IP2 | STATUSF_IP3 |
STATUSF_IP4 | STATUSF_IP5 |
Expand Down
49 changes: 27 additions & 22 deletions target/linux/realtek/files-5.10/drivers/irqchip/irq-realtek-rtl.c
Expand Up @@ -22,7 +22,7 @@
#define RTL_ICTL_IRR3 0x14

#define N_CPU_IRQ 2

#define RTL_ICTL_SIZE 0x18
#define REG(x) (base[cpu] + x)

void __iomem *base[2];
Expand Down Expand Up @@ -60,6 +60,8 @@ static void realtek_ictl_mask_irq(struct irq_data *i)

raw_spin_lock_irqsave(&realtek_ictl_lock, flags);
for (cpu = 0; cpu < NR_CPUS; cpu++) {
if (cpu_map[i->hwirq] >= 0 && cpu != cpu_map[i->hwirq])
continue;
value = readl(REG(RTL_ICTL_GIMR));
value &= ~BIT(i->hwirq);
writel(value, REG(RTL_ICTL_GIMR));
Expand Down Expand Up @@ -163,26 +165,26 @@ static void realtek_irq_dispatch(struct irq_desc *desc)
struct irq_chip *chip = irq_desc_get_chip(desc);
struct irq_domain *domain = irq_desc_get_handler_data(desc);
struct realtek_intc_chip_data *cd = domain->host_data;
unsigned int pending[N_CPU_IRQ];
unsigned int all_pending = 0;
int cpu;
unsigned long pending;
int irqn;
int cpu = smp_processor_id();

chained_irq_enter(chip, desc);
for (cpu = 0; cpu < N_CPU_IRQ; cpu++) {
pending[cpu] = readl(REG(RTL_ICTL_GIMR)) & readl(REG(RTL_ICTL_GISR));
all_pending |= pending[cpu];
}
// if (pending[1])
pending = readl(REG(RTL_ICTL_GIMR)) & readl(REG(RTL_ICTL_GISR));

// if (pending)
// pr_info("%s: with base %08x pending0 %08x pending1 %08x all pending %08x cpu%d\n",
// __func__, (u32)cd->base[0], pending[0], pending[1], all_pending, smp_processor_id());
if (unlikely(!all_pending)) {
if (unlikely(!pending)) {
spurious_interrupt();
goto out;
}

for (cpu = 0; cpu < N_CPU_IRQ; cpu++)
generic_handle_irq(irq_find_mapping(domain, __ffs(pending[cpu])));

// generic_handle_irq(irq_find_mapping(domain, __ffs(pending)));
// if (__sw_hweight32(pending) > 1)
// pr_info("%s: more than one pending: %llu\n", __func__, pending);
for_each_set_bit(irqn, &pending, BITS_PER_LONG)
generic_handle_irq(irq_find_mapping(domain, irqn));
out:
chained_irq_exit(chip, desc);
}
Expand All @@ -206,7 +208,7 @@ static int __init map_interrupts(struct device_node *node, struct irq_domain *do
RTL_ICTL_IRR0,
};
u8 mips_irqs_set;
int cpu;
int cpu = 0;

pr_info("%s, chip data %08x\n", __func__, (u32)cd);
ret = of_property_read_u32(node, "#address-cells", &tmp);
Expand Down Expand Up @@ -246,13 +248,13 @@ static int __init map_interrupts(struct device_node *node, struct irq_domain *do
imap += 3;
}

for (cpu = 0; cpu < NR_CPUS; cpu++) {
// for (cpu = 0; cpu < NR_CPUS; cpu++) {
for (i = 0; i < 4; i++) {
pr_info("%s: %d writing %08x to %08x\n",
__func__, i, regs[i], (u32)REG(irr_regs[i % 4]));
writel(regs[i], REG(irr_regs[i]));
}
}
// }
for (i = 0; i < 2; i++)
pr_info("%d %08x %08x %08x %08x %08x %08x\n", i,
readl(0xb8003000 + i * 24), readl(0xb8003004 + i * 24),
Expand All @@ -273,14 +275,17 @@ static int __init realtek_rtl_of_init(struct device_node *node, struct device_no
if (!base[0])
return -ENXIO;

base[1] = base[0] + 0x18;
if (NR_CPUS > N_CPU_IRQ)
return -ENXIO;

for (i = 0; i < 32; i++)
cpu_map[i] = -1;

/* Disable all cascaded interrupts */
for (cpu = 0; cpu < N_CPU_IRQ; cpu++)
/* Set per CPU base, disable all cascaded interrupts */
for (cpu = 0; cpu < NR_CPUS; cpu++) {
base[cpu] = base[0] + RTL_ICTL_SIZE * cpu;
writel(0, REG(RTL_ICTL_GIMR));
}

for (i = 0; i < 32; i++)
cpu_map[i] = 0;

pr_info("%s: new handler with base 0 %08x and base 1 %08x\n",
__func__, (u32)(base[0]), (u32)(base[1]));
Expand Down
4 changes: 1 addition & 3 deletions target/linux/realtek/files-5.10/net/dsa/tag_rtl83xx.c
Expand Up @@ -58,8 +58,6 @@ static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev,
{
struct dsa_port *cpu_dp = dev->dsa_ptr;
struct dsa_switch *ds = cpu_dp->ds;
int i;
struct rtl838x_switch_priv *priv = ds->priv;
u8 *trailer;
bool trunk = false;
int source_port;
Expand All @@ -75,9 +73,9 @@ static struct sk_buff *trailer_rcv(struct sk_buff *skb, struct net_device *dev,
return NULL;

if (trailer[1] & 0x40) { // forward
skb->offload_fwd_mark = 1;
struct dsa_switch *ds = cpu_dp->ds;
struct rtl838x_switch_priv *priv = ds->priv;

skb->offload_fwd_mark = 1;
if (priv->lagmembers & (1ULL << source_port)) {
pr_info("lag member %d found\n", source_port);
Expand Down

0 comments on commit 61860e0

Please sign in to comment.