root/arch/sparc/kernel/probe.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. probe_cpu
  2. probe_vac
  3. probe_mmu
  4. probe_clock
  5. probe_esp
  6. probe_sbus
  7. probe_devices

   1 /* probe.c: Preliminary device tree probing routines...
   2 
   3    Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
   4 */
   5 
   6 #include <linux/kernel.h>
   7 #include <asm/vac-ops.h>
   8 #include <asm/io.h>
   9 #include <asm/vaddrs.h>
  10 #include <asm/param.h>
  11 #include <asm/clock.h>
  12 
  13 /* #define DEBUG_PROBING */
  14 
  15 char promstr_buf[64];         /* overkill */
  16 unsigned int promint_buf[1];
  17 
  18 extern int prom_node_root;
  19 extern int num_segmaps, num_contexts;
  20 
  21 extern int node_get_sibling(int node);
  22 extern int node_get_child(int node);
  23 extern char* get_str_from_prom(int node, char* name, char* value);
  24 extern unsigned int* get_int_from_prom(int node, char* name, unsigned int *value);
  25 
  26 /* Cpu-type information and manufacturer strings */
  27 
  28 
  29 struct cpu_iu_info {
  30   int psr_impl;
  31   int psr_vers;
  32   char* cpu_name;   /* should be enough I hope... */
  33 };
  34 
  35 struct cpu_fp_info {
  36   int psr_impl;
  37   int fp_vers;
  38   char* fp_name;
  39 };
  40 
  41 struct cpu_fp_info linux_sparc_fpu[] = {
  42   { 0, 0, "Fujitsu MB86910 or Weitek WTL1164/5"},
  43   { 0, 1, "Fujitsu MB86911 or Weitek WTL1164/5"},
  44   { 0, 2, "LSI Logic L64802 or Texas Instruments ACT8847"},
  45   { 0, 3, "Weitek WTL3170/2"},
  46   { 0, 4, "Lsi Logic/Meiko L64804"},
  47   { 0, 5, "reserved"},
  48   { 0, 6, "reserved"},
  49   { 0, 7, "No FPU"},
  50   { 1, 0, "Lsi Logic L64812 or Texas Instruments ACT8847"},
  51   { 1, 1, "Lsi Logic L64814"},
  52   { 1, 2, "Texas Instruments TMS390-C602A"},
  53   { 1, 3, "Weitek WTL3171"},
  54   { 1, 4, "reserved"},
  55   { 1, 5, "reserved"},
  56   { 1, 6, "reserved"},
  57   { 1, 7, "No FPU"},
  58   { 2, 0, "BIT B5010 or B5110/20 or B5210"},
  59   { 2, 1, "reserved"},
  60   { 2, 2, "reserved"},
  61   { 2, 3, "reserved"},
  62   { 2, 4,  "reserved"},
  63   { 2, 5, "reserved"},
  64   { 2, 6, "reserved"},
  65   { 2, 7, "No FPU"},
  66   { 5, 0, "Matsushita MN10501"},
  67   { 5, 1, "reserved"},
  68   { 5, 2, "reserved"},
  69   { 5, 3, "reserved"},
  70   { 5, 4, "reserved"},
  71   { 5, 5, "reserved"},
  72   { 5, 6, "reserved"},
  73   { 5, 7, "No FPU"},
  74 };
  75 
  76 struct cpu_iu_info linux_sparc_chips[] = {
  77   { 0, 0, "Fujitsu Microelectronics, Inc. - MB86900/1A"},
  78   { 1, 0, "Cypress CY7C601"},
  79   { 1, 1, "LSI Logic Corporation - L64811"},
  80   { 1, 3, "Cypress CY7C611"},
  81   { 2, 0, "Bipolar Integrated Technology - B5010"},
  82   { 3, 0, "LSI Logic Corporation - unknown-type"},
  83   { 4, 0, "Texas Instruments, Inc. - unknown"},
  84   { 4, 1, "Texas Instruments, Inc. - unknown"},
  85   { 4, 2, "Texas Instruments, Inc. - unknown"},
  86   { 4, 3, "Texas Instruments, Inc. - unknown"},
  87   { 4, 4, "Texas Instruments, Inc. - unknown"},
  88   { 4, 5, "Texas Instruments, Inc. - unknown"},
  89   { 5, 0, "Matsushita - MN10501"},
  90   { 6, 0, "Philips Corporation - unknown"},
  91   { 7, 0, "Harvest VLSI Design Center, Inc. - unknown"},
  92   { 8, 0, "Systems and Processes Engineering Corporation (SPEC)"},
  93   { 9, 0, "UNKNOWN CPU-VENDOR/TYPE"},
  94   { 0xa, 0, "UNKNOWN CPU-VENDOR/TYPE"},
  95   { 0xb, 0, "UNKNOWN CPU-VENDOR/TYPE"},
  96   { 0xc, 0, "UNKNOWN CPU-VENDOR/TYPE"},
  97   { 0xd, 0, "UNKNOWN CPU-VENDOR/TYPE"},
  98   { 0xe, 0, "UNKNOWN CPU-VENDOR/TYPE"},
  99   { 0xf, 0, "UNKNOWN CPU-VENDOR/TYPE"},
 100 };
 101 
 102 char *sparc_cpu_type = "cpu-oops";
 103 char *sparc_fpu_type = "fpu-oops";
 104 
 105 /* various Virtual Address Cache parameters we find at boot time... */
 106 
 107 extern int vac_size, vac_linesize, vac_do_hw_vac_flushes;
 108 extern int vac_entries_per_context, vac_entries_per_segment;
 109 extern int vac_entries_per_page;
 110 
 111 extern int find_vac_size(void);
 112 extern int find_vac_linesize(void);
 113 extern int find_vac_hwflushes(void);
 114 extern void find_mmu_num_segmaps(void);
 115 extern void find_mmu_num_contexts(void);
 116 
 117 void
 118 probe_cpu(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 119 {
 120   register int psr_impl, psr_vers, fpu_vers, i;
 121   unsigned int tmp_fsr;
 122 
 123   &tmp_fsr;   /* GCC grrr... */
 124 
 125   __asm__("rd %%psr, %0\n\t"
 126           "mov %0, %1\n\t"
 127           "srl %0, 28, %0\n\t"
 128           "srl %1, 24, %1\n\t"
 129           "and %0, 0xf, %0\n\t"
 130           "and %1, 0xf, %1\n\t" :
 131           "=r" (psr_impl),
 132           "=r" (psr_vers) :
 133           "0" (psr_impl),
 134           "1" (psr_vers));
 135 
 136 
 137   __asm__("st %%fsr, %1\n\t"
 138           "ld %1, %0\n\t"
 139           "srl %0, 17, %0\n\t"
 140           "and %0, 0x7, %0\n\t" :
 141           "=r" (fpu_vers),
 142           "=m" (tmp_fsr) :
 143           "0" (fpu_vers),
 144           "1" (tmp_fsr));
 145 
 146   printk("fpu_vers: %d ", fpu_vers);
 147   printk("psr_impl: %d ", psr_impl);
 148   printk("psr_vers: %d \n\n", psr_vers);
 149 
 150   for(i = 0; i<23; i++)
 151     {
 152       if(linux_sparc_chips[i].psr_impl == psr_impl)
 153         if(linux_sparc_chips[i].psr_vers == psr_vers)
 154           {
 155             sparc_cpu_type = linux_sparc_chips[i].cpu_name;
 156             break;
 157           }
 158     }
 159 
 160   if(i==23)
 161     {
 162       printk("No CPU type! You lose\n");
 163       printk("DEBUG: psr.impl = 0x%x   psr.vers = 0x%x\n", psr_impl, 
 164              psr_vers);
 165       return;
 166     }
 167 
 168   for(i = 0; i<32; i++)
 169     {
 170       if(linux_sparc_fpu[i].psr_impl == psr_impl)
 171         if(linux_sparc_fpu[i].fp_vers == fpu_vers)
 172           {
 173             sparc_fpu_type = linux_sparc_fpu[i].fp_name;
 174             break;
 175           }
 176     }
 177 
 178   if(i == 32)
 179     {
 180       printk("No FPU type! You don't completely lose though...\n");
 181       printk("DEBUG: psr.impl = 0x%x  fsr.vers = 0x%x\n", psr_impl, fpu_vers);
 182       sparc_fpu_type = linux_sparc_fpu[31].fp_name;
 183     }
 184 
 185   printk("CPU: %s \n", sparc_cpu_type);
 186   printk("FPU: %s \n", sparc_fpu_type);
 187 
 188   return;
 189 }
 190 
 191 void
 192 probe_vac(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 193 {
 194   register unsigned int x,y;
 195 
 196   vac_size = find_vac_size();
 197   vac_linesize = find_vac_linesize();
 198   vac_do_hw_vac_flushes = find_vac_hwflushes();
 199 
 200   /* Calculate various constants that make the cache-flushing code
 201    * mode speedy.
 202    */
 203 
 204   vac_entries_per_segment = vac_entries_per_context = vac_size >> 12;
 205 
 206   for(x=0,y=vac_linesize; ((1<<x)<y); x++);
 207   if((1<<x) != vac_linesize) printk("Warning BOGUS VAC linesize 0x%x",
 208                                     vac_size);
 209 
 210   vac_entries_per_page = x;
 211 
 212   printk("Sparc VAC cache: Size=%d bytes  Line-Size=%d bytes ... ", vac_size,
 213          vac_linesize);
 214 
 215   /* Here we want to 'invalidate' all the software VAC "tags"
 216    * just in case there is garbage in there. Then we enable it.
 217    */
 218 
 219   for(x=0x80000000, y=(x+vac_size); x<y; x+=vac_linesize)
 220     __asm__("sta %0, [%1] %2" : : "r" (0), "r" (x), "n" (0x2));
 221 
 222   x=enable_vac();
 223   printk("ENABLED\n");
 224 
 225   return;
 226 }
 227 
 228 void
 229 probe_mmu(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 230 {
 231   find_mmu_num_segmaps();
 232   find_mmu_num_contexts();
 233 
 234   printk("\nMMU segmaps: %d     MMU contexts: %d\n", num_segmaps, 
 235          num_contexts);
 236 
 237   return;
 238 }
 239 
 240 void
 241 probe_clock(int fchild)
     /* [previous][next][first][last][top][bottom][index][help] */
 242 {
 243   register int node, type;
 244   register char *node_str;
 245 
 246   /* This will basically traverse the node-tree of the prom to see
 247    * which timer chip is on this machine.
 248    */
 249 
 250   printk("Probing timer chip... ");
 251 
 252   type = 0;
 253   for(node = fchild ; ; )
 254     {
 255       node_str = get_str_from_prom(node, "model", promstr_buf);
 256       if(strcmp(node_str, "mk48t02") == 0)
 257         {
 258           type = 2;
 259           break;
 260         }
 261 
 262       if(strcmp(node_str, "mk48t08") == 0)
 263         {
 264           type = 8;
 265           break;
 266         }
 267 
 268       node = node_get_sibling(node);
 269       if(node == fchild)
 270         {
 271           printk("Aieee, could not find timer chip type\n");
 272           return;
 273         }
 274     }
 275 
 276   printk("%s\n", node_str);
 277   printk("At OBIO address: 0x%x Virtual address: 0x%x\n",
 278          (unsigned int) 0xf3000000, (unsigned int) TIMER_STRUCT);
 279 
 280   mapioaddr((unsigned long) 0xf3000000,
 281             (unsigned long) TIMER_STRUCT);
 282 
 283   TIMER_STRUCT->timer_limit14=(((10000) << 10) | 0x80000000);
 284   TIMER_STRUCT->timer_limit10=(((10000) << 10) | 0x80000000);
 285 
 286   return;
 287 }
 288 
 289 
 290 void
 291 probe_esp(register int esp_node)
     /* [previous][next][first][last][top][bottom][index][help] */
 292 {
 293   register int nd;
 294   register char* lbuf;
 295 
 296   nd = node_get_child(esp_node);
 297 
 298   printk("\nProbing ESP:\n");
 299   lbuf = get_str_from_prom(nd, "name", promstr_buf);
 300 
 301   printk("\nProperty length for %s: 0x%x\n", "name", 
 302          *get_int_from_prom(nd, "name", promint_buf));
 303 
 304   if(*get_int_from_prom(nd, "name", promint_buf) != 0)
 305   printk("Node: 0x%x Name: %s", nd, lbuf);
 306 
 307   lbuf = get_str_from_prom(nd, "device-type", promstr_buf);
 308 
 309   printk("\nProperty length for %s: 0x%x\n", "device_type", 
 310          *get_int_from_prom(nd, "device_type", promint_buf));
 311 
 312   if(*get_int_from_prom(nd, "device-type", promint_buf) != 0)
 313     printk("Device-Type: %s ", lbuf);
 314   
 315   lbuf = get_str_from_prom(nd, "model", promstr_buf);
 316 
 317   printk("\nProperty length for %s: 0x%x\n", "model", 
 318          *get_int_from_prom(nd, "model", promint_buf));
 319 
 320   if(*get_int_from_prom(nd, "model", promint_buf) != 0)
 321     printk("Model: %s", lbuf);
 322 
 323   printk("\n");
 324 
 325   while((nd = node_get_sibling(nd)) != 0)
 326     {
 327       lbuf = get_str_from_prom(nd, "name", promstr_buf);
 328 
 329       if(*get_int_from_prom(nd, "name", promint_buf) != 0)
 330       printk("Node: 0x%x Name: %s ", nd, lbuf);
 331 
 332       lbuf = get_str_from_prom(nd, "device-type", promstr_buf);
 333 
 334       if(*get_int_from_prom(nd, "device-type", promint_buf) != 0)
 335       printk("Device-Type: %s ", lbuf);
 336 
 337       lbuf = get_str_from_prom(nd, "model", promstr_buf);
 338 
 339       if(*get_int_from_prom(nd, "model", promint_buf) != 0)
 340       printk("Model: %s", lbuf);
 341 
 342       printk("\n");
 343     }
 344 
 345   printk("\n");
 346 
 347   return;
 348 }
 349 
 350 void
 351 probe_sbus(register int cpu_child_node)
     /* [previous][next][first][last][top][bottom][index][help] */
 352 {
 353   register int nd, savend;
 354   register char* lbuf;
 355 
 356   nd = cpu_child_node;
 357 
 358   lbuf = (char *) 0;
 359 
 360   while((nd = node_get_sibling(nd)) != 0)
 361     {
 362       lbuf = get_str_from_prom(nd, "name", promstr_buf);
 363       if(lbuf[0]=='s' && lbuf[1]=='b' && lbuf[2]=='u' && lbuf[3]=='s')
 364         break;
 365     }
 366   nd = node_get_child(nd);
 367 
 368   printk("Node: 0x%x Name: %s\n", nd,
 369          get_str_from_prom(nd, "name", promstr_buf));
 370 
 371   if(lbuf[0]=='e' && lbuf[1]=='s' && lbuf[2]=='p')
 372     probe_esp(nd);
 373 
 374   while((nd = node_get_sibling(nd)) != 0)
 375     {
 376       printk("Node: 0x%x Name: %s\n", nd,
 377              get_str_from_prom(nd, "name", promstr_buf));
 378 
 379           if(lbuf[0]=='e' && lbuf[1]=='s' && lbuf[2]=='p')
 380             {
 381               savend = nd;
 382               probe_esp(nd);
 383               nd = savend;
 384             }
 385     }
 386 
 387   return;
 388 }
 389 
 390 void
 391 probe_devices(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 392 {
 393   register int nd, first_descent;
 394   register char* str;
 395 
 396   nd = prom_node_root;
 397 
 398   printk("PROBING DEVICES:\n");
 399 
 400   str = get_str_from_prom(nd, "device_type", promstr_buf);
 401   printk("Root Node: 0x%x ", nd);
 402 
 403 #ifdef DEBUG_PROBING
 404   printk("String address for d_type: 0x%x\n", (unsigned int) str);
 405   printk("str[0] = %c  str[1] = %c  str[2] = %c \n", str[0], str[1], str[2]);
 406 #endif
 407 
 408   printk("Device Type: %s ", str);
 409 
 410   str = get_str_from_prom(nd, "name", promstr_buf);
 411 
 412 #ifdef DEBUG_PROBING
 413   printk("String address for name: 0x%x\n", (unsigned int) str);
 414   printk("str[0] = %c  str[1] = %c  str[2] = %c \n", str[0], str[1], str[2]);
 415 #endif
 416 
 417   printk("Name: %s \n", str);
 418 
 419   first_descent = nd = node_get_child(nd);
 420 
 421 
 422 /* Ok, here will go a call to each specific device probe. We can
 423    call these now that we have the 'root' node and the child of
 424    this node to send to the routines. ORDER IS IMPORTANT!
 425 */
 426 
 427   probe_cpu();
 428   probe_vac();
 429   probe_mmu();
 430   probe_clock(first_descent);
 431 
 432 /*
 433   printk("PROM Root Child Node: 0x%x Name: %s \n", nd,
 434          get_str_from_prom(nd, "name", promstr_buf));
 435 
 436   while((nd = node_get_sibling(nd)) != 0)
 437     {
 438 
 439       printk("Node: 0x%x Name: %s\n", nd,
 440              get_str_from_prom(nd, "name", promstr_buf));
 441 
 442     }
 443 
 444   printk("\nProbing SBUS:\n");
 445   probe_sbus(first_descent);
 446 */
 447 
 448   return;
 449 }

/* [previous][next][first][last][top][bottom][index][help] */