Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

sparc64: Rewrite central driver.

This driver is now limited to just doing the basic clock board and FHC
chip initialization and registering the platform devices for the
per-board LEDs, which are driven by the new LEDS_STARFIRE driver.

The IRQ register handling is already confined purely to the device
tree code.

Signed-off-by: David S. Miller <davem@davemloft.net>

+221 -458
+1 -42
arch/sparc/include/asm/fhc.h
··· 1 - /* 2 - * fhc.h: Structures for central/fhc pseudo driver on Sunfire/Starfire/Wildfire. 1 + /* fhc.h: FHC and Clock board register definitions. 3 2 * 4 3 * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com) 5 4 */ 6 5 7 6 #ifndef _SPARC64_FHC_H 8 7 #define _SPARC64_FHC_H 9 - 10 - #include <linux/timer.h> 11 - 12 - #include <asm/oplib.h> 13 - #include <asm/prom.h> 14 - #include <asm/upa.h> 15 - 16 - struct linux_fhc; 17 8 18 9 /* Clock board register offsets. */ 19 10 #define CLOCK_CTRL 0x00UL /* Main control */ ··· 20 29 #define CLOCK_CTRL_MLED 0x02 /* Mid LED, 1 == on */ 21 30 #define CLOCK_CTRL_RLED 0x01 /* RIght LED, 1 == on */ 22 31 23 - struct linux_central { 24 - struct linux_fhc *child; 25 - unsigned long cfreg; 26 - unsigned long clkregs; 27 - unsigned long clkver; 28 - int slots; 29 - struct device_node *prom_node; 30 - 31 - struct linux_prom_ranges central_ranges[PROMREG_MAX]; 32 - int num_central_ranges; 33 - }; 34 - 35 32 /* Firehose controller register offsets */ 36 - struct fhc_regs { 37 - unsigned long pregs; /* FHC internal regs */ 38 33 #define FHC_PREGS_ID 0x00UL /* FHC ID */ 39 34 #define FHC_ID_VERS 0xf0000000 /* Version of this FHC */ 40 35 #define FHC_ID_PARTID 0x0ffff000 /* Part ID code (0x0f9f == FHC) */ ··· 67 90 #define FHC_JTAG_CTRL_MENAB 0x80000000 /* Indicates this is JTAG Master */ 68 91 #define FHC_JTAG_CTRL_MNONE 0x40000000 /* Indicates no JTAG Master present */ 69 92 #define FHC_PREGS_JCMD 0x100UL /* FHC JTAG Command Register */ 70 - unsigned long ireg; /* FHC IGN reg */ 71 93 #define FHC_IREG_IGN 0x00UL /* This FHC's IGN */ 72 - unsigned long ffregs; /* FHC fanfail regs */ 73 94 #define FHC_FFREGS_IMAP 0x00UL /* FHC Fanfail IMAP */ 74 95 #define FHC_FFREGS_ICLR 0x10UL /* FHC Fanfail ICLR */ 75 - unsigned long sregs; /* FHC system regs */ 76 96 #define FHC_SREGS_IMAP 0x00UL /* FHC System IMAP */ 77 97 #define FHC_SREGS_ICLR 0x10UL /* FHC System ICLR */ 78 - unsigned long uregs; /* FHC uart regs */ 79 98 #define FHC_UREGS_IMAP 0x00UL /* FHC Uart IMAP */ 80 99 #define FHC_UREGS_ICLR 0x10UL /* FHC Uart ICLR */ 81 - unsigned long tregs; /* FHC TOD regs */ 82 100 #define FHC_TREGS_IMAP 0x00UL /* FHC TOD IMAP */ 83 101 #define FHC_TREGS_ICLR 0x10UL /* FHC TOD ICLR */ 84 - }; 85 - 86 - struct linux_fhc { 87 - struct linux_fhc *next; 88 - struct linux_central *parent; /* NULL if not central FHC */ 89 - struct fhc_regs fhc_regs; 90 - int board; 91 - int jtag_master; 92 - struct device_node *prom_node; 93 - 94 - struct linux_prom_ranges fhc_ranges[PROMREG_MAX]; 95 - int num_fhc_ranges; 96 - }; 97 102 98 103 #endif /* !(_SPARC64_FHC_H) */
+220 -410
arch/sparc64/kernel/central.c
··· 1 1 /* central.c: Central FHC driver for Sunfire/Starfire/Wildfire. 2 2 * 3 - * Copyright (C) 1997, 1999 David S. Miller (davem@davemloft.net) 3 + * Copyright (C) 1997, 1999, 2008 David S. Miller (davem@davemloft.net) 4 4 */ 5 5 6 6 #include <linux/kernel.h> 7 7 #include <linux/types.h> 8 8 #include <linux/string.h> 9 - #include <linux/timer.h> 10 - #include <linux/sched.h> 11 - #include <linux/delay.h> 12 9 #include <linux/init.h> 13 - #include <linux/bootmem.h> 10 + #include <linux/of_device.h> 11 + #include <linux/platform_device.h> 14 12 15 - #include <asm/page.h> 16 13 #include <asm/fhc.h> 17 - #include <asm/starfire.h> 14 + #include <asm/upa.h> 18 15 19 - static struct linux_central *central_bus = NULL; 20 - static struct linux_fhc *fhc_list = NULL; 16 + struct clock_board { 17 + void __iomem *clock_freq_regs; 18 + void __iomem *clock_regs; 19 + void __iomem *clock_ver_reg; 20 + int num_slots; 21 + struct resource leds_resource; 22 + struct platform_device leds_pdev; 23 + }; 21 24 22 - #define IS_CENTRAL_FHC(__fhc) ((__fhc) == central_bus->child) 25 + struct fhc { 26 + void __iomem *pregs; 27 + bool central; 28 + bool jtag_master; 29 + int board_num; 30 + struct resource leds_resource; 31 + struct platform_device leds_pdev; 32 + }; 23 33 24 - static void central_probe_failure(int line) 34 + static int __devinit clock_board_calc_nslots(struct clock_board *p) 25 35 { 26 - prom_printf("CENTRAL: Critical device probe failure at central.c:%d\n", 27 - line); 28 - prom_halt(); 29 - } 36 + u8 reg = upa_readb(p->clock_regs + CLOCK_STAT1) & 0xc0; 30 37 31 - static void central_ranges_init(struct linux_central *central) 32 - { 33 - struct device_node *dp = central->prom_node; 34 - const void *pval; 35 - int len; 36 - 37 - central->num_central_ranges = 0; 38 - pval = of_get_property(dp, "ranges", &len); 39 - if (pval) { 40 - memcpy(central->central_ranges, pval, len); 41 - central->num_central_ranges = 42 - (len / sizeof(struct linux_prom_ranges)); 43 - } 44 - } 45 - 46 - static void fhc_ranges_init(struct linux_fhc *fhc) 47 - { 48 - struct device_node *dp = fhc->prom_node; 49 - const void *pval; 50 - int len; 51 - 52 - fhc->num_fhc_ranges = 0; 53 - pval = of_get_property(dp, "ranges", &len); 54 - if (pval) { 55 - memcpy(fhc->fhc_ranges, pval, len); 56 - fhc->num_fhc_ranges = 57 - (len / sizeof(struct linux_prom_ranges)); 58 - } 59 - } 60 - 61 - /* Range application routines are exported to various drivers, 62 - * so do not __init this. 63 - */ 64 - static void adjust_regs(struct linux_prom_registers *regp, int nregs, 65 - struct linux_prom_ranges *rangep, int nranges) 66 - { 67 - int regc, rngc; 68 - 69 - for (regc = 0; regc < nregs; regc++) { 70 - for (rngc = 0; rngc < nranges; rngc++) 71 - if (regp[regc].which_io == rangep[rngc].ot_child_space) 72 - break; /* Fount it */ 73 - if (rngc == nranges) /* oops */ 74 - central_probe_failure(__LINE__); 75 - regp[regc].which_io = rangep[rngc].ot_parent_space; 76 - regp[regc].phys_addr -= rangep[rngc].ot_child_base; 77 - regp[regc].phys_addr += rangep[rngc].ot_parent_base; 78 - } 79 - } 80 - 81 - /* Apply probed fhc ranges to registers passed, if no ranges return. */ 82 - static void apply_fhc_ranges(struct linux_fhc *fhc, 83 - struct linux_prom_registers *regs, 84 - int nregs) 85 - { 86 - if (fhc->num_fhc_ranges) 87 - adjust_regs(regs, nregs, fhc->fhc_ranges, 88 - fhc->num_fhc_ranges); 89 - } 90 - 91 - /* Apply probed central ranges to registers passed, if no ranges return. */ 92 - static void apply_central_ranges(struct linux_central *central, 93 - struct linux_prom_registers *regs, int nregs) 94 - { 95 - if (central->num_central_ranges) 96 - adjust_regs(regs, nregs, central->central_ranges, 97 - central->num_central_ranges); 98 - } 99 - 100 - static void * __init central_alloc_bootmem(unsigned long size) 101 - { 102 - void *ret; 103 - 104 - ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); 105 - if (ret != NULL) 106 - memset(ret, 0, size); 107 - 108 - return ret; 109 - } 110 - 111 - static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r) 112 - { 113 - unsigned long ret = ((unsigned long) r->which_io) << 32; 114 - 115 - return ret | (unsigned long) r->phys_addr; 116 - } 117 - 118 - static void __init probe_other_fhcs(void) 119 - { 120 - struct device_node *dp; 121 - const struct linux_prom64_registers *fpregs; 122 - 123 - for_each_node_by_name(dp, "fhc") { 124 - struct linux_fhc *fhc; 125 - int board; 126 - u32 tmp; 127 - 128 - if (dp->parent && 129 - dp->parent->parent != NULL) 130 - continue; 131 - 132 - fhc = (struct linux_fhc *) 133 - central_alloc_bootmem(sizeof(struct linux_fhc)); 134 - if (fhc == NULL) 135 - central_probe_failure(__LINE__); 136 - 137 - /* Link it into the FHC chain. */ 138 - fhc->next = fhc_list; 139 - fhc_list = fhc; 140 - 141 - /* Toplevel FHCs have no parent. */ 142 - fhc->parent = NULL; 143 - 144 - fhc->prom_node = dp; 145 - fhc_ranges_init(fhc); 146 - 147 - /* Non-central FHC's have 64-bit OBP format registers. */ 148 - fpregs = of_get_property(dp, "reg", NULL); 149 - if (!fpregs) 150 - central_probe_failure(__LINE__); 151 - 152 - /* Only central FHC needs special ranges applied. */ 153 - fhc->fhc_regs.pregs = fpregs[0].phys_addr; 154 - fhc->fhc_regs.ireg = fpregs[1].phys_addr; 155 - fhc->fhc_regs.ffregs = fpregs[2].phys_addr; 156 - fhc->fhc_regs.sregs = fpregs[3].phys_addr; 157 - fhc->fhc_regs.uregs = fpregs[4].phys_addr; 158 - fhc->fhc_regs.tregs = fpregs[5].phys_addr; 159 - 160 - board = of_getintprop_default(dp, "board#", -1); 161 - fhc->board = board; 162 - 163 - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_JCTRL); 164 - if ((tmp & FHC_JTAG_CTRL_MENAB) != 0) 165 - fhc->jtag_master = 1; 166 - else 167 - fhc->jtag_master = 0; 168 - 169 - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); 170 - printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] %s\n", 171 - board, 172 - (tmp & FHC_ID_VERS) >> 28, 173 - (tmp & FHC_ID_PARTID) >> 12, 174 - (tmp & FHC_ID_MANUF) >> 1, 175 - (fhc->jtag_master ? "(JTAG Master)" : "")); 176 - 177 - /* This bit must be set in all non-central FHC's in 178 - * the system. When it is clear, this identifies 179 - * the central board. 180 - */ 181 - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); 182 - tmp |= FHC_CONTROL_IXIST; 183 - upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); 184 - } 185 - } 186 - 187 - static void probe_clock_board(struct linux_central *central, 188 - struct linux_fhc *fhc, 189 - struct device_node *fp) 190 - { 191 - struct device_node *dp; 192 - struct linux_prom_registers cregs[3]; 193 - const struct linux_prom_registers *pr; 194 - int nslots, tmp, nregs; 195 - 196 - dp = fp->child; 197 - while (dp) { 198 - if (!strcmp(dp->name, "clock-board")) 199 - break; 200 - dp = dp->sibling; 201 - } 202 - if (!dp) 203 - central_probe_failure(__LINE__); 204 - 205 - pr = of_get_property(dp, "reg", &nregs); 206 - if (!pr) 207 - central_probe_failure(__LINE__); 208 - 209 - memcpy(cregs, pr, nregs); 210 - nregs /= sizeof(struct linux_prom_registers); 211 - 212 - apply_fhc_ranges(fhc, &cregs[0], nregs); 213 - apply_central_ranges(central, &cregs[0], nregs); 214 - central->cfreg = prom_reg_to_paddr(&cregs[0]); 215 - central->clkregs = prom_reg_to_paddr(&cregs[1]); 216 - 217 - if (nregs == 2) 218 - central->clkver = 0UL; 219 - else 220 - central->clkver = prom_reg_to_paddr(&cregs[2]); 221 - 222 - tmp = upa_readb(central->clkregs + CLOCK_STAT1); 223 - tmp &= 0xc0; 224 - switch(tmp) { 38 + switch (reg) { 225 39 case 0x40: 226 - nslots = 16; 227 - break; 40 + return 16; 41 + 228 42 case 0xc0: 229 - nslots = 8; 230 - break; 43 + return 8; 44 + 231 45 case 0x80: 232 - if (central->clkver != 0UL && 233 - upa_readb(central->clkver) != 0) { 234 - if ((upa_readb(central->clkver) & 0x80) != 0) 235 - nslots = 4; 46 + reg = 0; 47 + if (p->clock_ver_reg) 48 + reg = upa_readb(p->clock_ver_reg); 49 + if (reg) { 50 + if (reg & 0x80) 51 + return 4; 236 52 else 237 - nslots = 5; 238 - break; 53 + return 5; 239 54 } 55 + /* Fallthrough */ 240 56 default: 241 - nslots = 4; 242 - break; 243 - }; 244 - central->slots = nslots; 245 - printk("CENTRAL: Detected %d slot Enterprise system. cfreg[%02x] cver[%02x]\n", 246 - central->slots, upa_readb(central->cfreg), 247 - (central->clkver ? upa_readb(central->clkver) : 0x00)); 57 + return 4; 58 + } 248 59 } 249 60 250 - static void ZAP(unsigned long iclr, unsigned long imap) 61 + static int __devinit clock_board_probe(struct of_device *op, 62 + const struct of_device_id *match) 251 63 { 252 - u32 imap_tmp; 64 + struct clock_board *p = kzalloc(sizeof(*p), GFP_KERNEL); 65 + int err = -ENOMEM; 253 66 254 - upa_writel(0, iclr); 255 - upa_readl(iclr); 256 - imap_tmp = upa_readl(imap); 257 - imap_tmp &= ~(0x80000000); 258 - upa_writel(imap_tmp, imap); 259 - upa_readl(imap); 260 - } 261 - 262 - static void init_all_fhc_hw(void) 263 - { 264 - struct linux_fhc *fhc; 265 - 266 - for (fhc = fhc_list; fhc != NULL; fhc = fhc->next) { 267 - u32 tmp; 268 - 269 - /* Clear all of the interrupt mapping registers 270 - * just in case OBP left them in a foul state. 271 - */ 272 - ZAP(fhc->fhc_regs.ffregs + FHC_FFREGS_ICLR, 273 - fhc->fhc_regs.ffregs + FHC_FFREGS_IMAP); 274 - ZAP(fhc->fhc_regs.sregs + FHC_SREGS_ICLR, 275 - fhc->fhc_regs.sregs + FHC_SREGS_IMAP); 276 - ZAP(fhc->fhc_regs.uregs + FHC_UREGS_ICLR, 277 - fhc->fhc_regs.uregs + FHC_UREGS_IMAP); 278 - ZAP(fhc->fhc_regs.tregs + FHC_TREGS_ICLR, 279 - fhc->fhc_regs.tregs + FHC_TREGS_IMAP); 280 - 281 - /* Setup FHC control register. */ 282 - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); 283 - 284 - /* All non-central boards have this bit set. */ 285 - if (! IS_CENTRAL_FHC(fhc)) 286 - tmp |= FHC_CONTROL_IXIST; 287 - 288 - /* For all FHCs, clear the firmware synchronization 289 - * line and both low power mode enables. 290 - */ 291 - tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | 292 - FHC_CONTROL_SLINE); 293 - 294 - upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); 295 - upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); 67 + if (!p) { 68 + printk(KERN_ERR "clock_board: Cannot allocate struct clock_board\n"); 69 + goto out; 296 70 } 297 71 298 - } 299 - 300 - void __init central_probe(void) 301 - { 302 - struct linux_prom_registers fpregs[6]; 303 - const struct linux_prom_registers *pr; 304 - struct linux_fhc *fhc; 305 - struct device_node *dp, *fp; 306 - int err; 307 - 308 - dp = of_find_node_by_name(NULL, "central"); 309 - if (!dp) 310 - return; 311 - 312 - /* Ok we got one, grab some memory for software state. */ 313 - central_bus = (struct linux_central *) 314 - central_alloc_bootmem(sizeof(struct linux_central)); 315 - if (central_bus == NULL) 316 - central_probe_failure(__LINE__); 317 - 318 - fhc = (struct linux_fhc *) 319 - central_alloc_bootmem(sizeof(struct linux_fhc)); 320 - if (fhc == NULL) 321 - central_probe_failure(__LINE__); 322 - 323 - /* First init central. */ 324 - central_bus->child = fhc; 325 - central_bus->prom_node = dp; 326 - central_ranges_init(central_bus); 327 - 328 - /* And then central's FHC. */ 329 - fhc->next = fhc_list; 330 - fhc_list = fhc; 331 - 332 - fhc->parent = central_bus; 333 - fp = dp->child; 334 - while (fp) { 335 - if (!strcmp(fp->name, "fhc")) 336 - break; 337 - fp = fp->sibling; 72 + p->clock_freq_regs = of_ioremap(&op->resource[0], 0, 73 + resource_size(&op->resource[0]), 74 + "clock_board_freq"); 75 + if (!p->clock_freq_regs) { 76 + printk(KERN_ERR "clock_board: Cannot map clock_freq_regs\n"); 77 + goto out_free; 338 78 } 339 - if (!fp) 340 - central_probe_failure(__LINE__); 341 79 342 - fhc->prom_node = fp; 343 - fhc_ranges_init(fhc); 80 + p->clock_regs = of_ioremap(&op->resource[1], 0, 81 + resource_size(&op->resource[1]), 82 + "clock_board_regs"); 83 + if (!p->clock_regs) { 84 + printk(KERN_ERR "clock_board: Cannot map clock_regs\n"); 85 + goto out_unmap_clock_freq_regs; 86 + } 344 87 345 - /* Now, map in FHC register set. */ 346 - pr = of_get_property(fp, "reg", NULL); 347 - if (!pr) 348 - central_probe_failure(__LINE__); 349 - memcpy(fpregs, pr, sizeof(fpregs)); 88 + if (op->resource[2].flags) { 89 + p->clock_ver_reg = of_ioremap(&op->resource[2], 0, 90 + resource_size(&op->resource[2]), 91 + "clock_ver_reg"); 92 + if (!p->clock_ver_reg) { 93 + printk(KERN_ERR "clock_board: Cannot map clock_ver_reg\n"); 94 + goto out_unmap_clock_regs; 95 + } 96 + } 350 97 351 - apply_central_ranges(central_bus, &fpregs[0], 6); 352 - 353 - fhc->fhc_regs.pregs = prom_reg_to_paddr(&fpregs[0]); 354 - fhc->fhc_regs.ireg = prom_reg_to_paddr(&fpregs[1]); 355 - fhc->fhc_regs.ffregs = prom_reg_to_paddr(&fpregs[2]); 356 - fhc->fhc_regs.sregs = prom_reg_to_paddr(&fpregs[3]); 357 - fhc->fhc_regs.uregs = prom_reg_to_paddr(&fpregs[4]); 358 - fhc->fhc_regs.tregs = prom_reg_to_paddr(&fpregs[5]); 98 + p->num_slots = clock_board_calc_nslots(p); 359 99 360 - /* Obtain board number from board status register, Central's 361 - * FHC lacks "board#" property. 362 - */ 363 - err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_BSR); 364 - fhc->board = (((err >> 16) & 0x01) | 365 - ((err >> 12) & 0x0e)); 100 + p->leds_resource.start = (unsigned long) 101 + (p->clock_regs + CLOCK_CTRL); 102 + p->leds_resource.end = p->leds_resource.end; 103 + p->leds_resource.name = "leds"; 366 104 367 - fhc->jtag_master = 0; 105 + p->leds_pdev.name = "sunfire-clockboard-leds"; 106 + p->leds_pdev.resource = &p->leds_resource; 107 + p->leds_pdev.num_resources = 1; 108 + p->leds_pdev.dev.parent = &op->dev; 368 109 369 - /* Attach the clock board registers for CENTRAL. */ 370 - probe_clock_board(central_bus, fhc, fp); 110 + err = platform_device_register(&p->leds_pdev); 111 + if (err) { 112 + printk(KERN_ERR "clock_board: Could not register LEDS " 113 + "platform device\n"); 114 + goto out_unmap_clock_ver_reg; 115 + } 371 116 372 - err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); 373 - printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] (CENTRAL)\n", 374 - fhc->board, 375 - ((err & FHC_ID_VERS) >> 28), 376 - ((err & FHC_ID_PARTID) >> 12), 377 - ((err & FHC_ID_MANUF) >> 1)); 117 + printk(KERN_INFO "clock_board: Detected %d slot Enterprise system.\n", 118 + p->num_slots); 378 119 379 - probe_other_fhcs(); 120 + err = 0; 121 + out: 122 + return err; 380 123 381 - init_all_fhc_hw(); 124 + out_unmap_clock_ver_reg: 125 + if (p->clock_ver_reg) 126 + of_iounmap(&op->resource[2], p->clock_ver_reg, 127 + resource_size(&op->resource[2])); 128 + 129 + out_unmap_clock_regs: 130 + of_iounmap(&op->resource[1], p->clock_regs, 131 + resource_size(&op->resource[1])); 132 + 133 + out_unmap_clock_freq_regs: 134 + of_iounmap(&op->resource[0], p->clock_freq_regs, 135 + resource_size(&op->resource[0])); 136 + 137 + out_free: 138 + kfree(p); 139 + goto out; 382 140 } 383 141 384 - static inline void fhc_ledblink(struct linux_fhc *fhc, int on) 142 + static struct of_device_id __initdata clock_board_match[] = { 143 + { 144 + .name = "clock-board", 145 + }, 146 + {}, 147 + }; 148 + 149 + static struct of_platform_driver clock_board_driver = { 150 + .match_table = clock_board_match, 151 + .probe = clock_board_probe, 152 + .driver = { 153 + .name = "clock_board", 154 + }, 155 + }; 156 + 157 + static int __devinit fhc_probe(struct of_device *op, 158 + const struct of_device_id *match) 385 159 { 386 - u32 tmp; 160 + struct fhc *p = kzalloc(sizeof(*p), GFP_KERNEL); 161 + int err = -ENOMEM; 162 + u32 reg; 387 163 388 - tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); 164 + if (!p) { 165 + printk(KERN_ERR "fhc: Cannot allocate struct fhc\n"); 166 + goto out; 167 + } 389 168 390 - /* NOTE: reverse logic on this bit */ 391 - if (on) 392 - tmp &= ~(FHC_CONTROL_RLED); 393 - else 394 - tmp |= FHC_CONTROL_RLED; 395 - tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | FHC_CONTROL_SLINE); 169 + if (!strcmp(op->node->parent->name, "central")) 170 + p->central = true; 396 171 397 - upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); 398 - upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); 172 + p->pregs = of_ioremap(&op->resource[0], 0, 173 + resource_size(&op->resource[0]), 174 + "fhc_pregs"); 175 + if (!p->pregs) { 176 + printk(KERN_ERR "fhc: Cannot map pregs\n"); 177 + goto out_free; 178 + } 179 + 180 + if (p->central) { 181 + reg = upa_readl(p->pregs + FHC_PREGS_BSR); 182 + p->board_num = ((reg >> 16) & 1) | ((reg >> 12) & 0x0e); 183 + } else { 184 + p->board_num = of_getintprop_default(op->node, "board#", -1); 185 + if (p->board_num == -1) { 186 + printk(KERN_ERR "fhc: No board# property\n"); 187 + goto out_unmap_pregs; 188 + } 189 + if (upa_readl(p->pregs + FHC_PREGS_JCTRL) & FHC_JTAG_CTRL_MENAB) 190 + p->jtag_master = true; 191 + } 192 + 193 + if (!p->central) { 194 + p->leds_resource.start = (unsigned long) 195 + (p->pregs + FHC_PREGS_CTRL); 196 + p->leds_resource.end = p->leds_resource.end; 197 + p->leds_resource.name = "leds"; 198 + 199 + p->leds_pdev.name = "sunfire-fhc-leds"; 200 + p->leds_pdev.resource = &p->leds_resource; 201 + p->leds_pdev.num_resources = 1; 202 + p->leds_pdev.dev.parent = &op->dev; 203 + 204 + err = platform_device_register(&p->leds_pdev); 205 + if (err) { 206 + printk(KERN_ERR "fhc: Could not register LEDS " 207 + "platform device\n"); 208 + goto out_unmap_pregs; 209 + } 210 + } 211 + reg = upa_readl(p->pregs + FHC_PREGS_CTRL); 212 + 213 + if (!p->central) 214 + reg |= FHC_CONTROL_IXIST; 215 + 216 + reg &= ~(FHC_CONTROL_AOFF | 217 + FHC_CONTROL_BOFF | 218 + FHC_CONTROL_SLINE); 219 + 220 + upa_writel(reg, p->pregs + FHC_PREGS_CTRL); 221 + upa_readl(p->pregs + FHC_PREGS_CTRL); 222 + 223 + reg = upa_readl(p->pregs + FHC_PREGS_ID); 224 + printk(KERN_INFO "fhc: Board #%d, Version[%x] PartID[%x] Manuf[%x] %s\n", 225 + p->board_num, 226 + (reg & FHC_ID_VERS) >> 28, 227 + (reg & FHC_ID_PARTID) >> 12, 228 + (reg & FHC_ID_MANUF) >> 1, 229 + (p->jtag_master ? 230 + "(JTAG Master)" : 231 + (p->central ? "(Central)" : ""))); 232 + 233 + err = 0; 234 + 235 + out: 236 + return err; 237 + 238 + out_unmap_pregs: 239 + of_iounmap(&op->resource[0], p->pregs, resource_size(&op->resource[0])); 240 + 241 + out_free: 242 + kfree(p); 243 + goto out; 399 244 } 400 245 401 - static inline void central_ledblink(struct linux_central *central, int on) 246 + static struct of_device_id __initdata fhc_match[] = { 247 + { 248 + .name = "fhc", 249 + }, 250 + {}, 251 + }; 252 + 253 + static struct of_platform_driver fhc_driver = { 254 + .match_table = fhc_match, 255 + .probe = fhc_probe, 256 + .driver = { 257 + .name = "fhc", 258 + }, 259 + }; 260 + 261 + static int __init sunfire_init(void) 402 262 { 403 - u8 tmp; 404 - 405 - tmp = upa_readb(central->clkregs + CLOCK_CTRL); 406 - 407 - /* NOTE: reverse logic on this bit */ 408 - if (on) 409 - tmp &= ~(CLOCK_CTRL_RLED); 410 - else 411 - tmp |= CLOCK_CTRL_RLED; 412 - 413 - upa_writeb(tmp, central->clkregs + CLOCK_CTRL); 414 - upa_readb(central->clkregs + CLOCK_CTRL); 263 + (void) of_register_driver(&fhc_driver, &of_platform_bus_type); 264 + (void) of_register_driver(&clock_board_driver, &of_platform_bus_type); 265 + return 0; 415 266 } 416 267 417 - static struct timer_list sftimer; 418 - static int led_state; 419 - 420 - static void sunfire_timer(unsigned long __ignored) 421 - { 422 - struct linux_fhc *fhc; 423 - 424 - central_ledblink(central_bus, led_state); 425 - for (fhc = fhc_list; fhc != NULL; fhc = fhc->next) 426 - if (! IS_CENTRAL_FHC(fhc)) 427 - fhc_ledblink(fhc, led_state); 428 - led_state = ! led_state; 429 - sftimer.expires = jiffies + (HZ >> 1); 430 - add_timer(&sftimer); 431 - } 432 - 433 - /* After PCI/SBUS busses have been probed, this is called to perform 434 - * final initialization of all FireHose Controllers in the system. 435 - */ 436 - void firetruck_init(void) 437 - { 438 - struct linux_central *central = central_bus; 439 - u8 ctrl; 440 - 441 - /* No central bus, nothing to do. */ 442 - if (central == NULL) 443 - return; 444 - 445 - /* OBP leaves it on, turn it off so clock board timer LED 446 - * is in sync with FHC ones. 447 - */ 448 - ctrl = upa_readb(central->clkregs + CLOCK_CTRL); 449 - ctrl &= ~(CLOCK_CTRL_RLED); 450 - upa_writeb(ctrl, central->clkregs + CLOCK_CTRL); 451 - 452 - led_state = 0; 453 - init_timer(&sftimer); 454 - sftimer.data = 0; 455 - sftimer.function = &sunfire_timer; 456 - sftimer.expires = jiffies + (HZ >> 1); 457 - add_timer(&sftimer); 458 - } 268 + subsys_initcall(sunfire_init);
-3
arch/sparc64/kernel/sbus.c
··· 659 659 660 660 static int __init sbus_init(void) 661 661 { 662 - extern void firetruck_init(void); 663 662 struct device_node *dp; 664 663 665 664 for_each_node_by_name(dp, "sbus") { ··· 667 668 sbus_iommu_init(op); 668 669 of_propagate_archdata(op); 669 670 } 670 - 671 - firetruck_init(); 672 671 673 672 return 0; 674 673 }
-3
arch/sparc64/mm/init.c
··· 1673 1673 1674 1674 /* paging_init() sets up the page tables */ 1675 1675 1676 - extern void central_probe(void); 1677 - 1678 1676 static unsigned long last_valid_pfn; 1679 1677 pgd_t swapper_pg_dir[2048]; 1680 1678 ··· 1842 1844 1843 1845 printk("Booting Linux...\n"); 1844 1846 1845 - central_probe(); 1846 1847 cpu_probe(); 1847 1848 } 1848 1849