|
@@ -45,7 +45,16 @@
|
|
/* If you trust current SCSI layer to handle different SCSI IRQs, enable this. I don't trust it... -jj */
|
|
/* If you trust current SCSI layer to handle different SCSI IRQs, enable this. I don't trust it... -jj */
|
|
/* #define DISTRIBUTE_IRQS */
|
|
/* #define DISTRIBUTE_IRQS */
|
|
|
|
|
|
-struct sun4d_timer_regs *sun4d_timers;
|
|
|
|
|
|
+struct sun4d_timer_regs {
|
|
|
|
+ u32 l10_timer_limit;
|
|
|
|
+ u32 l10_cur_countx;
|
|
|
|
+ u32 l10_limit_noclear;
|
|
|
|
+ u32 ctrl;
|
|
|
|
+ u32 l10_cur_count;
|
|
|
|
+};
|
|
|
|
+
|
|
|
|
+static struct sun4d_timer_regs __iomem *sun4d_timers;
|
|
|
|
+
|
|
#define TIMER_IRQ 10
|
|
#define TIMER_IRQ 10
|
|
|
|
|
|
#define MAX_STATIC_ALLOC 4
|
|
#define MAX_STATIC_ALLOC 4
|
|
@@ -446,8 +455,7 @@ void __init sun4d_distribute_irqs(void)
|
|
|
|
|
|
static void sun4d_clear_clock_irq(void)
|
|
static void sun4d_clear_clock_irq(void)
|
|
{
|
|
{
|
|
- volatile unsigned int clear_intr;
|
|
|
|
- clear_intr = sun4d_timers->l10_timer_limit;
|
|
|
|
|
|
+ sbus_readl(&sun4d_timers->l10_timer_limit);
|
|
}
|
|
}
|
|
|
|
|
|
static void sun4d_clear_profile_irq(int cpu)
|
|
static void sun4d_clear_profile_irq(int cpu)
|
|
@@ -460,71 +468,90 @@ static void sun4d_load_profile_irq(int cpu, unsigned int limit)
|
|
bw_set_prof_limit(cpu, limit);
|
|
bw_set_prof_limit(cpu, limit);
|
|
}
|
|
}
|
|
|
|
|
|
-static void __init sun4d_init_timers(irq_handler_t counter_fn)
|
|
|
|
|
|
+static void __init sun4d_load_profile_irqs(void)
|
|
{
|
|
{
|
|
- int irq;
|
|
|
|
- int cpu;
|
|
|
|
- struct resource r;
|
|
|
|
- int mid;
|
|
|
|
|
|
+ int cpu = 0, mid;
|
|
|
|
|
|
- /* Map the User Timer registers. */
|
|
|
|
- memset(&r, 0, sizeof(r));
|
|
|
|
|
|
+ while (!cpu_find_by_instance(cpu, NULL, &mid)) {
|
|
|
|
+ sun4d_load_profile_irq(mid >> 3, 0);
|
|
|
|
+ cpu++;
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void __init sun4d_fixup_trap_table(void)
|
|
|
|
+{
|
|
#ifdef CONFIG_SMP
|
|
#ifdef CONFIG_SMP
|
|
- r.start = CSR_BASE(boot_cpu_id)+BW_TIMER_LIMIT;
|
|
|
|
-#else
|
|
|
|
- r.start = CSR_BASE(0)+BW_TIMER_LIMIT;
|
|
|
|
|
|
+ unsigned long flags;
|
|
|
|
+ extern unsigned long lvl14_save[4];
|
|
|
|
+ struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
|
|
|
|
+ extern unsigned int real_irq_entry[], smp4d_ticker[];
|
|
|
|
+ extern unsigned int patchme_maybe_smp_msg[];
|
|
|
|
+
|
|
|
|
+ /* Adjust so that we jump directly to smp4d_ticker */
|
|
|
|
+ lvl14_save[2] += smp4d_ticker - real_irq_entry;
|
|
|
|
+
|
|
|
|
+ /* For SMP we use the level 14 ticker, however the bootup code
|
|
|
|
+ * has copied the firmware's level 14 vector into the boot cpu's
|
|
|
|
+ * trap table, we must fix this now or we get squashed.
|
|
|
|
+ */
|
|
|
|
+ local_irq_save(flags);
|
|
|
|
+ patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */
|
|
|
|
+ trap_table->inst_one = lvl14_save[0];
|
|
|
|
+ trap_table->inst_two = lvl14_save[1];
|
|
|
|
+ trap_table->inst_three = lvl14_save[2];
|
|
|
|
+ trap_table->inst_four = lvl14_save[3];
|
|
|
|
+ local_flush_cache_all();
|
|
|
|
+ local_irq_restore(flags);
|
|
#endif
|
|
#endif
|
|
- r.flags = 0xf;
|
|
|
|
- sun4d_timers = (struct sun4d_timer_regs *) of_ioremap(&r, 0,
|
|
|
|
- PAGE_SIZE, "user timer");
|
|
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+static void __init sun4d_init_timers(irq_handler_t counter_fn)
|
|
|
|
+{
|
|
|
|
+ struct device_node *dp;
|
|
|
|
+ struct resource res;
|
|
|
|
+ const u32 *reg;
|
|
|
|
+ int err;
|
|
|
|
+
|
|
|
|
+ dp = of_find_node_by_name(NULL, "cpu-unit");
|
|
|
|
+ if (!dp) {
|
|
|
|
+ prom_printf("sun4d_init_timers: Unable to find cpu-unit\n");
|
|
|
|
+ prom_halt();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /* Which cpu-unit we use is arbitrary, we can view the bootbus timer
|
|
|
|
+ * registers via any cpu's mapping. The first 'reg' property is the
|
|
|
|
+ * bootbus.
|
|
|
|
+ */
|
|
|
|
+ reg = of_get_property(dp, "reg", NULL);
|
|
|
|
+ if (!reg) {
|
|
|
|
+ prom_printf("sun4d_init_timers: No reg property\n");
|
|
|
|
+ prom_halt();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ res.start = reg[1];
|
|
|
|
+ res.end = reg[2] - 1;
|
|
|
|
+ res.flags = reg[0] & 0xff;
|
|
|
|
+ sun4d_timers = of_ioremap(&res, BW_TIMER_LIMIT,
|
|
|
|
+ sizeof(struct sun4d_timer_regs), "user timer");
|
|
|
|
+ if (!sun4d_timers) {
|
|
|
|
+ prom_printf("sun4d_init_timers: Can't map timer regs\n");
|
|
|
|
+ prom_halt();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ sbus_writel((((1000000/HZ) + 1) << 10), &sun4d_timers->l10_timer_limit);
|
|
|
|
|
|
- sun4d_timers->l10_timer_limit = (((1000000/HZ) + 1) << 10);
|
|
|
|
master_l10_counter = &sun4d_timers->l10_cur_count;
|
|
master_l10_counter = &sun4d_timers->l10_cur_count;
|
|
master_l10_limit = &sun4d_timers->l10_timer_limit;
|
|
master_l10_limit = &sun4d_timers->l10_timer_limit;
|
|
|
|
|
|
- irq = request_irq(TIMER_IRQ,
|
|
|
|
- counter_fn,
|
|
|
|
|
|
+ err = request_irq(TIMER_IRQ, counter_fn,
|
|
(IRQF_DISABLED | SA_STATIC_ALLOC),
|
|
(IRQF_DISABLED | SA_STATIC_ALLOC),
|
|
"timer", NULL);
|
|
"timer", NULL);
|
|
- if (irq) {
|
|
|
|
- prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ);
|
|
|
|
|
|
+ if (err) {
|
|
|
|
+ prom_printf("sun4d_init_timers: request_irq() failed with %d\n", err);
|
|
prom_halt();
|
|
prom_halt();
|
|
}
|
|
}
|
|
-
|
|
|
|
- /* Enable user timer free run for CPU 0 in BW */
|
|
|
|
- /* bw_set_ctrl(0, bw_get_ctrl(0) | BW_CTRL_USER_TIMER); */
|
|
|
|
-
|
|
|
|
- cpu = 0;
|
|
|
|
- while (!cpu_find_by_instance(cpu, NULL, &mid)) {
|
|
|
|
- sun4d_load_profile_irq(mid >> 3, 0);
|
|
|
|
- cpu++;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
-#ifdef CONFIG_SMP
|
|
|
|
- {
|
|
|
|
- unsigned long flags;
|
|
|
|
- extern unsigned long lvl14_save[4];
|
|
|
|
- struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
|
|
|
|
- extern unsigned int real_irq_entry[], smp4d_ticker[];
|
|
|
|
- extern unsigned int patchme_maybe_smp_msg[];
|
|
|
|
-
|
|
|
|
- /* Adjust so that we jump directly to smp4d_ticker */
|
|
|
|
- lvl14_save[2] += smp4d_ticker - real_irq_entry;
|
|
|
|
-
|
|
|
|
- /* For SMP we use the level 14 ticker, however the bootup code
|
|
|
|
- * has copied the firmware's level 14 vector into the boot cpu's
|
|
|
|
- * trap table, we must fix this now or we get squashed.
|
|
|
|
- */
|
|
|
|
- local_irq_save(flags);
|
|
|
|
- patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */
|
|
|
|
- trap_table->inst_one = lvl14_save[0];
|
|
|
|
- trap_table->inst_two = lvl14_save[1];
|
|
|
|
- trap_table->inst_three = lvl14_save[2];
|
|
|
|
- trap_table->inst_four = lvl14_save[3];
|
|
|
|
- local_flush_cache_all();
|
|
|
|
- local_irq_restore(flags);
|
|
|
|
- }
|
|
|
|
-#endif
|
|
|
|
|
|
+ sun4d_load_profile_irqs();
|
|
|
|
+ sun4d_fixup_trap_table();
|
|
}
|
|
}
|
|
|
|
|
|
void __init sun4d_init_sbi_irq(void)
|
|
void __init sun4d_init_sbi_irq(void)
|