Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f5f10857 authored by David S. Miller's avatar David S. Miller
Browse files

sparc32: Use PROM infrastructure for probing and mapping sun4d timers.

parent 69c010b2
Loading
Loading
Loading
Loading
+0 −13
Original line number Original line Diff line number Diff line
@@ -35,19 +35,6 @@ struct sun4c_timer_info {


#define SUN_TIMER_PHYSADDR   0xf3000000
#define SUN_TIMER_PHYSADDR   0xf3000000


#define SUN4D_PRM_CNT_L       0x80000000
#define SUN4D_PRM_CNT_LVALUE  0x7FFFFC00

struct sun4d_timer_regs {
	volatile unsigned int l10_timer_limit;
	volatile unsigned int l10_cur_countx;
	volatile unsigned int l10_limit_noclear;
	volatile unsigned int ctrl;
	volatile unsigned int l10_cur_count;
};

extern struct sun4d_timer_regs *sun4d_timers;

extern __volatile__ unsigned int *master_l10_counter;
extern __volatile__ unsigned int *master_l10_counter;
extern __volatile__ unsigned int *master_l10_limit;
extern __volatile__ unsigned int *master_l10_limit;


+83 −56
Original line number Original line Diff line number Diff line
@@ -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;
	sbus_readl(&sun4d_timers->l10_timer_limit);
	clear_intr = sun4d_timers->l10_timer_limit;
}
}


static void sun4d_clear_profile_irq(int cpu)
static void sun4d_clear_profile_irq(int cpu)
@@ -460,48 +468,19 @@ 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 = 0, mid;
	int cpu;
	struct resource r;
	int mid;

	/* Map the User Timer registers. */
	memset(&r, 0, sizeof(r));
#ifdef CONFIG_SMP
	r.start = CSR_BASE(boot_cpu_id)+BW_TIMER_LIMIT;
#else
	r.start = CSR_BASE(0)+BW_TIMER_LIMIT;
#endif
	r.flags = 0xf;
	sun4d_timers = (struct sun4d_timer_regs *) of_ioremap(&r, 0,
	    PAGE_SIZE, "user timer");

	sun4d_timers->l10_timer_limit =  (((1000000/HZ) + 1) << 10);
	master_l10_counter = &sun4d_timers->l10_cur_count;
	master_l10_limit = &sun4d_timers->l10_timer_limit;


	irq = request_irq(TIMER_IRQ,
			  counter_fn,
			  (IRQF_DISABLED | SA_STATIC_ALLOC),
			  "timer", NULL);
	if (irq) {
		prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ);
		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)) {
	while (!cpu_find_by_instance(cpu, NULL, &mid)) {
		sun4d_load_profile_irq(mid >> 3, 0);
		sun4d_load_profile_irq(mid >> 3, 0);
		cpu++;
		cpu++;
	}
	}
}


#ifdef CONFIG_SMP
static void __init sun4d_fixup_trap_table(void)
{
{
#ifdef CONFIG_SMP
	unsigned long flags;
	unsigned long flags;
	extern unsigned long lvl14_save[4];
	extern unsigned long lvl14_save[4];
	struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
	struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
@@ -523,10 +502,58 @@ static void __init sun4d_init_timers(irq_handler_t counter_fn)
	trap_table->inst_four = lvl14_save[3];
	trap_table->inst_four = lvl14_save[3];
	local_flush_cache_all();
	local_flush_cache_all();
	local_irq_restore(flags);
	local_irq_restore(flags);
	}
#endif
#endif
}
}


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);

	master_l10_counter = &sun4d_timers->l10_cur_count;
	master_l10_limit = &sun4d_timers->l10_timer_limit;

	err = request_irq(TIMER_IRQ, counter_fn,
			  (IRQF_DISABLED | SA_STATIC_ALLOC),
			  "timer", NULL);
	if (err) {
		prom_printf("sun4d_init_timers: request_irq() failed with %d\n", err);
		prom_halt();
	}
	sun4d_load_profile_irqs();
	sun4d_fixup_trap_table();
}

void __init sun4d_init_sbi_irq(void)
void __init sun4d_init_sbi_irq(void)
{
{
	struct device_node *dp;
	struct device_node *dp;