patch-2.3.35 linux/arch/sparc64/kernel/central.c

Next file: linux/arch/sparc64/kernel/devices.c
Previous file: linux/arch/sparc64/kernel/auxio.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.34/linux/arch/sparc64/kernel/central.c linux/arch/sparc64/kernel/central.c
@@ -1,7 +1,7 @@
-/* $Id: central.c,v 1.11 1998/12/14 12:18:16 davem Exp $
+/* $Id: central.c,v 1.13 1999/12/01 10:44:43 davem Exp $
  * central.c: Central FHC driver for Sunfire/Starfire/Wildfire.
  *
- * Copyright (C) 1997 David S. Miller (davem@caip.rutgers.edu)
+ * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com)
  */
 
 #include <linux/kernel.h>
@@ -10,6 +10,8 @@
 #include <linux/timer.h>
 #include <linux/sched.h>
 #include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
 
 #include <asm/page.h>
 #include <asm/fhc.h>
@@ -25,10 +27,80 @@
 		~(sizeof(unsigned long) - 1));
 }
 
-extern void prom_central_ranges_init(int cnode, struct linux_central *central);
-extern void prom_fhc_ranges_init(int fnode, struct linux_fhc *fhc);
+static void central_ranges_init(int cnode, struct linux_central *central)
+{
+	int success;
+	
+	central->num_central_ranges = 0;
+	success = prom_getproperty(central->prom_node, "ranges",
+				   (char *) central->central_ranges,
+				   sizeof (central->central_ranges));
+	if (success != -1)
+		central->num_central_ranges = (success/sizeof(struct linux_prom_ranges));
+}
+
+static void fhc_ranges_init(int fnode, struct linux_fhc *fhc)
+{
+	int success;
+	
+	fhc->num_fhc_ranges = 0;
+	success = prom_getproperty(fhc->prom_node, "ranges",
+				   (char *) fhc->fhc_ranges,
+				   sizeof (fhc->fhc_ranges));
+	if (success != -1)
+		fhc->num_fhc_ranges = (success/sizeof(struct linux_prom_ranges));
+}
+
+/* Range application routines are exported to various drivers,
+ * so do not __init this.
+ */
+static void adjust_regs(struct linux_prom_registers *regp, int nregs,
+			struct linux_prom_ranges *rangep, int nranges)
+{
+	int regc, rngc;
+
+	for (regc = 0; regc < nregs; regc++) {
+		for (rngc = 0; rngc < nranges; rngc++)
+			if (regp[regc].which_io == rangep[rngc].ot_child_space)
+				break; /* Fount it */
+		if (rngc == nranges) /* oops */
+			prom_printf("adjust_regs: Could not find range with matching bus type...\n");
+		regp[regc].which_io = rangep[rngc].ot_parent_space;
+		regp[regc].phys_addr += rangep[rngc].ot_parent_base;
+	}
+}
+
+/* Apply probed fhc ranges to registers passed, if no ranges return. */
+void apply_fhc_ranges(struct linux_fhc *fhc,
+		      struct linux_prom_registers *regs,
+		      int nregs)
+{
+	if(fhc->num_fhc_ranges)
+		adjust_regs(regs, nregs, fhc->fhc_ranges,
+			    fhc->num_fhc_ranges);
+}
+
+/* Apply probed central ranges to registers passed, if no ranges return. */
+void apply_central_ranges(struct linux_central *central,
+			  struct linux_prom_registers *regs, int nregs)
+{
+	if(central->num_central_ranges)
+		adjust_regs(regs, nregs, central->central_ranges,
+			    central->num_central_ranges);
+}
 
-static unsigned long probe_other_fhcs(unsigned long memory_start)
+void * __init central_alloc_bootmem(unsigned long size)
+{
+	void *ret;
+
+	ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL);
+	if (ret != NULL)
+		memset(ret, 0, size);
+
+	return ret;
+}
+
+static void probe_other_fhcs(void)
 {
 	struct linux_prom64_registers fpregs[6];
 	char namebuf[128];
@@ -45,9 +117,12 @@
 		int board;
 		u32 tmp;
 
-		fhc = (struct linux_fhc *)memory_start;
-		memory_start += sizeof(struct linux_fhc);
-		memory_start = long_align(memory_start);
+		fhc = (struct linux_fhc *)
+			central_alloc_bootmem(sizeof(struct linux_fhc));
+		if (fhc == NULL) {
+			prom_printf("probe_other_fhcs: Cannot alloc fhc.\n");
+			prom_halt();
+		}
 
 		/* Link it into the FHC chain. */
 		fhc->next = fhc_list;
@@ -59,7 +134,7 @@
 		fhc->prom_node = node;
 		prom_getstring(node, "name", namebuf, sizeof(namebuf));
 		strcpy(fhc->prom_name, namebuf);
-		prom_fhc_ranges_init(node, fhc);
+		fhc_ranges_init(node, fhc);
 
 		/* Non-central FHC's have 64-bit OBP format registers. */
 		if(prom_getproperty(node, "reg",
@@ -69,29 +144,23 @@
 		}
 
 		/* Only central FHC needs special ranges applied. */
-		fhc->fhc_regs.pregs = (struct fhc_internal_regs *)
-			__va(fpregs[0].phys_addr);
-		fhc->fhc_regs.ireg = (struct fhc_ign_reg *)
-			__va(fpregs[1].phys_addr);
-		fhc->fhc_regs.ffregs = (struct fhc_fanfail_regs *)
-			__va(fpregs[2].phys_addr);
-		fhc->fhc_regs.sregs = (struct fhc_system_regs *)
-			__va(fpregs[3].phys_addr);
-		fhc->fhc_regs.uregs = (struct fhc_uart_regs *)
-			__va(fpregs[4].phys_addr);
-		fhc->fhc_regs.tregs = (struct fhc_tod_regs *)
-			__va(fpregs[5].phys_addr);
+		fhc->fhc_regs.pregs = fpregs[0].phys_addr;
+		fhc->fhc_regs.ireg = fpregs[1].phys_addr;
+		fhc->fhc_regs.ffregs = fpregs[2].phys_addr;
+		fhc->fhc_regs.sregs = fpregs[3].phys_addr;
+		fhc->fhc_regs.uregs = fpregs[4].phys_addr;
+		fhc->fhc_regs.tregs = fpregs[5].phys_addr;
 
 		board = prom_getintdefault(node, "board#", -1);
 		fhc->board = board;
 
-		tmp = fhc->fhc_regs.pregs->fhc_jtag_ctrl;
+		tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_JCTRL);
 		if((tmp & FHC_JTAG_CTRL_MENAB) != 0)
 			fhc->jtag_master = 1;
 		else
 			fhc->jtag_master = 0;
 
-		tmp = fhc->fhc_regs.pregs->fhc_id;
+		tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID);
 		printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] %s\n",
 		       board,
 		       (tmp & FHC_ID_VERS) >> 28,
@@ -103,7 +172,9 @@
 		 * the system.  When it is clear, this identifies
 		 * the central board.
 		 */
-		fhc->fhc_regs.pregs->fhc_control |= FHC_CONTROL_IXIST;
+		tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
+		tmp |= FHC_CONTROL_IXIST;
+		upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
 
 		/* Look for the next FHC. */
 		node = prom_getsibling(node);
@@ -113,8 +184,6 @@
 		if(node == 0)
 			break;
 	}
-
-	return memory_start;
 }
 
 static void probe_clock_board(struct linux_central *central,
@@ -135,22 +204,20 @@
 		prom_halt();
 	}
 	nregs /= sizeof(struct linux_prom_registers);
-	prom_apply_fhc_ranges(fhc, &cregs[0], nregs);
-	prom_apply_central_ranges(central, &cregs[0], nregs);
-	central->cfreg = (volatile u8 *)
-		__va((((unsigned long)cregs[0].which_io) << 32) |
-		     (((unsigned long)cregs[0].phys_addr)+0x02));
-	central->clkregs = (struct clock_board_regs *)
-		__va((((unsigned long)cregs[1].which_io) << 32) |
-		     (((unsigned long)cregs[1].phys_addr)));
+	apply_fhc_ranges(fhc, &cregs[0], nregs);
+	apply_central_ranges(central, &cregs[0], nregs);
+	central->cfreg = ((((unsigned long)cregs[0].which_io) << 32UL) |
+			  ((unsigned long)cregs[0].phys_addr));
+	central->clkregs = ((((unsigned long)cregs[1].which_io) << 32UL) |
+			    ((unsigned long)cregs[1].phys_addr));
+
 	if(nregs == 2)
-		central->clkver = NULL;
+		central->clkver = 0UL;
 	else
-		central->clkver = (volatile u8 *)
-			__va((((unsigned long)cregs[2].which_io) << 32) |
-			     (((unsigned long)cregs[2].phys_addr)));
+		central->clkver = ((((unsigned long)cregs[2].which_io) << 32UL) |
+				   ((unsigned long)cregs[2].phys_addr));
 
-	tmp = central->clkregs->stat1;
+	tmp = upa_readb(central->clkregs + CLOCK_STAT1);
 	tmp &= 0xc0;
 	switch(tmp) {
 	case 0x40:
@@ -160,9 +227,9 @@
 		nslots = 8;
 		break;
 	case 0x80:
-		if(central->clkver != NULL &&
-		   *(central->clkver) != 0) {
-			if((*(central->clkver) & 0x80) != 0)
+		if(central->clkver != 0UL &&
+		   upa_readb(central->clkver) != 0) {
+			if((upa_readb(central->clkver) & 0x80) != 0)
 				nslots = 4;
 			else
 				nslots = 5;
@@ -174,11 +241,11 @@
 	};
 	central->slots = nslots;
 	printk("CENTRAL: Detected %d slot Enterprise system. cfreg[%02x] cver[%02x]\n",
-	       central->slots, *(central->cfreg),
-	       (central->clkver ? *(central->clkver) : 0x00));
+	       central->slots, upa_readb(central->cfreg),
+	       (central->clkver ? upa_readb(central->clkver) : 0x00));
 }
 
-unsigned long central_probe(unsigned long memory_start)
+void central_probe(void)
 {
 	struct linux_prom_registers fpregs[6];
 	struct linux_fhc *fhc;
@@ -190,18 +257,23 @@
 		extern void starfire_check(void);
 
 		starfire_check();
-		return memory_start;
+		return;
 	}
 
 	/* Ok we got one, grab some memory for software state. */
-	memory_start = long_align(memory_start);
-	central_bus = (struct linux_central *) (memory_start);
+	central_bus = (struct linux_central *)
+		central_alloc_bootmem(sizeof(struct linux_central));
+	if (central_bus == NULL) {
+		prom_printf("central_probe: Cannot alloc central_bus.\n");
+		prom_halt();
+	}
 
-	memory_start += sizeof(struct linux_central);
-	memory_start = long_align(memory_start);
-	fhc = (struct linux_fhc *)(memory_start);
-	memory_start += sizeof(struct linux_fhc);
-	memory_start = long_align(memory_start);
+	fhc = (struct linux_fhc *)
+		central_alloc_bootmem(sizeof(struct linux_fhc));
+	if (fhc == NULL) {
+		prom_printf("central_probe: Cannot alloc central fhc.\n");
+		prom_halt();
+	}
 
 	/* First init central. */
 	central_bus->child = fhc;
@@ -210,7 +282,7 @@
 	prom_getstring(cnode, "name", namebuf, sizeof(namebuf));
 	strcpy(central_bus->prom_name, namebuf);
 
-	prom_central_ranges_init(cnode, central_bus);
+	central_ranges_init(cnode, central_bus);
 
 	/* And then central's FHC. */
 	fhc->next = fhc_list;
@@ -226,38 +298,32 @@
 	prom_getstring(fnode, "name", namebuf, sizeof(namebuf));
 	strcpy(fhc->prom_name, namebuf);
 
-	prom_fhc_ranges_init(fnode, fhc);
+	fhc_ranges_init(fnode, fhc);
 
 	/* Now, map in FHC register set. */
 	if (prom_getproperty(fnode, "reg", (char *)&fpregs[0], sizeof(fpregs)) == -1) {
 		prom_printf("CENTRAL: Fatal error, cannot get fhc regs.\n");
 		prom_halt();
 	}
-	prom_apply_central_ranges(central_bus, &fpregs[0], 6);
+	apply_central_ranges(central_bus, &fpregs[0], 6);
 	
-	fhc->fhc_regs.pregs = (struct fhc_internal_regs *)
-		__va((((unsigned long)fpregs[0].which_io)<<32) |
-		     (((unsigned long)fpregs[0].phys_addr)));
-	fhc->fhc_regs.ireg = (struct fhc_ign_reg *)
-		__va((((unsigned long)fpregs[1].which_io)<<32) |
-		     (((unsigned long)fpregs[1].phys_addr)));
-	fhc->fhc_regs.ffregs = (struct fhc_fanfail_regs *)
-		__va((((unsigned long)fpregs[2].which_io)<<32) |
-		     (((unsigned long)fpregs[2].phys_addr)));
-	fhc->fhc_regs.sregs = (struct fhc_system_regs *)
-		__va((((unsigned long)fpregs[3].which_io)<<32) |
-		     (((unsigned long)fpregs[3].phys_addr)));
-	fhc->fhc_regs.uregs = (struct fhc_uart_regs *)
-		__va((((unsigned long)fpregs[4].which_io)<<32) |
-		     (((unsigned long)fpregs[4].phys_addr)));
-	fhc->fhc_regs.tregs = (struct fhc_tod_regs *)
-		__va((((unsigned long)fpregs[5].which_io)<<32) |
-		     (((unsigned long)fpregs[5].phys_addr)));
+	fhc->fhc_regs.pregs = ((((unsigned long)fpregs[0].which_io)<<32UL) |
+			       ((unsigned long)fpregs[0].phys_addr));
+	fhc->fhc_regs.ireg = ((((unsigned long)fpregs[1].which_io)<<32UL) |
+			      ((unsigned long)fpregs[1].phys_addr));
+	fhc->fhc_regs.ffregs = ((((unsigned long)fpregs[2].which_io)<<32UL) |
+				((unsigned long)fpregs[2].phys_addr));
+	fhc->fhc_regs.sregs = ((((unsigned long)fpregs[3].which_io)<<32UL) |
+			       ((unsigned long)fpregs[3].phys_addr));
+	fhc->fhc_regs.uregs = ((((unsigned long)fpregs[4].which_io)<<32UL) |
+			       ((unsigned long)fpregs[4].phys_addr));
+	fhc->fhc_regs.tregs = ((((unsigned long)fpregs[5].which_io)<<32UL) |
+			       ((unsigned long)fpregs[5].phys_addr));
 
 	/* Obtain board number from board status register, Central's
 	 * FHC lacks "board#" property.
 	 */
-	err = fhc->fhc_regs.pregs->fhc_bsr;
+	err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_BSR);
 	fhc->board = (((err >> 16) & 0x01) |
 		      ((err >> 12) & 0x0e));
 
@@ -266,23 +332,21 @@
 	/* Attach the clock board registers for CENTRAL. */
 	probe_clock_board(central_bus, fhc, cnode, fnode);
 
-	err = fhc->fhc_regs.pregs->fhc_id;
+	err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID);
 	printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] (CENTRAL)\n",
 	       fhc->board,
 	       ((err & FHC_ID_VERS) >> 28),
 	       ((err & FHC_ID_PARTID) >> 12),
 	       ((err & FHC_ID_MANUF) >> 1));
 
-	return probe_other_fhcs(memory_start);
+	probe_other_fhcs();
 }
 
 static __inline__ void fhc_ledblink(struct linux_fhc *fhc, int on)
 {
-	volatile u32 *ctrl = (volatile u32 *)
-		&fhc->fhc_regs.pregs->fhc_control;
 	u32 tmp;
 
-	tmp = *ctrl;
+	tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
 
 	/* NOTE: reverse logic on this bit */
 	if (on)
@@ -291,16 +355,15 @@
 		tmp |= FHC_CONTROL_RLED;
 	tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | FHC_CONTROL_SLINE);
 
-	*ctrl = tmp;
-	tmp = *ctrl;
+	upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
+	upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
 }
 
 static __inline__ void central_ledblink(struct linux_central *central, int on)
 {
-	volatile u8 *ctrl = (volatile u8 *) &central->clkregs->control;
-	int tmp;
+	u8 tmp;
 
-	tmp = *ctrl;
+	tmp = upa_readb(central->clkregs + CLOCK_CTRL);
 
 	/* NOTE: reverse logic on this bit */
 	if(on)
@@ -308,8 +371,8 @@
 	else
 		tmp |= CLOCK_CTRL_RLED;
 
-	*ctrl = tmp;
-	tmp = *ctrl;
+	upa_writeb(tmp, central->clkregs + CLOCK_CTRL);
+	upa_readb(central->clkregs + CLOCK_CTRL);
 }
 
 static struct timer_list sftimer;
@@ -335,41 +398,41 @@
 {
 	struct linux_central *central = central_bus;
 	struct linux_fhc *fhc;
+	u8 ctrl;
 
 	/* No central bus, nothing to do. */
 	if (central == NULL)
 		return;
 
 	for(fhc = fhc_list; fhc != NULL; fhc = fhc->next) {
-		volatile u32 *ctrl = (volatile u32 *)
-			&fhc->fhc_regs.pregs->fhc_control;
 		u32 tmp;
 
 		/* Clear all of the interrupt mapping registers
 		 * just in case OBP left them in a foul state.
 		 */
-#define ZAP(REG1, REG2) \
-do {	volatile u32 *__iclr = (volatile u32 *)(&(REG1)); \
-	volatile u32 *__imap = (volatile u32 *)(&(REG2)); \
-	*(__iclr) = 0; \
-	(void) *(__iclr); \
-	*(__imap) &= ~(0x80000000); \
-	(void) *(__imap); \
-} while(0)
-
-		ZAP(fhc->fhc_regs.ffregs->fhc_ff_iclr,
-		    fhc->fhc_regs.ffregs->fhc_ff_imap);
-		ZAP(fhc->fhc_regs.sregs->fhc_sys_iclr,
-		    fhc->fhc_regs.sregs->fhc_sys_imap);
-		ZAP(fhc->fhc_regs.uregs->fhc_uart_iclr,
-		    fhc->fhc_regs.uregs->fhc_uart_imap);
-		ZAP(fhc->fhc_regs.tregs->fhc_tod_iclr,
-		    fhc->fhc_regs.tregs->fhc_tod_imap);
+#define ZAP(ICLR, IMAP) \
+do {	u32 imap_tmp; \
+	upa_writel(0, (ICLR)); \
+	upa_readl(ICLR); \
+	imap_tmp = upa_readl(IMAP); \
+	imap_tmp &= ~(0x80000000); \
+	upa_writel(imap_tmp, (IMAP)); \
+	upa_readl(IMAP); \
+} while (0)
+
+		ZAP(fhc->fhc_regs.ffregs + FHC_FFREGS_ICLR,
+		    fhc->fhc_regs.ffregs + FHC_FFREGS_IMAP);
+		ZAP(fhc->fhc_regs.sregs + FHC_SREGS_ICLR,
+		    fhc->fhc_regs.sregs + FHC_SREGS_IMAP);
+		ZAP(fhc->fhc_regs.uregs + FHC_UREGS_ICLR,
+		    fhc->fhc_regs.uregs + FHC_UREGS_IMAP);
+		ZAP(fhc->fhc_regs.tregs + FHC_TREGS_ICLR,
+		    fhc->fhc_regs.tregs + FHC_TREGS_IMAP);
 
 #undef ZAP
 
 		/* Setup FHC control register. */
-		tmp = *ctrl;
+		tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
 
 		/* All non-central boards have this bit set. */
 		if(! IS_CENTRAL_FHC(fhc))
@@ -379,14 +442,17 @@
 		 * line and both low power mode enables.
 		 */
 		tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | FHC_CONTROL_SLINE);
-		*ctrl = tmp;
-		tmp = *ctrl; /* Ensure completion */
+
+		upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
+		upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL);
 	}
 
 	/* OBP leaves it on, turn it off so clock board timer LED
 	 * is in sync with FHC ones.
 	 */
-	central->clkregs->control &= ~(CLOCK_CTRL_RLED);
+	ctrl = upa_readb(central->clkregs + CLOCK_CTRL);
+	ctrl &= ~(CLOCK_CTRL_RLED);
+	upa_writeb(ctrl, central->clkregs + CLOCK_CTRL);
 
 	led_state = 0;
 	init_timer(&sftimer);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)