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

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