sbus.c
上传用户:lgb322
上传日期:2013-02-24
资源大小:30529k
文件大小:14k
源码类别:

嵌入式Linux

开发平台:

Unix_Linux

  1. /* $Id: sbus.c,v 1.95.2.3 2002/01/05 01:12:31 davem Exp $
  2.  * sbus.c:  SBus support routines.
  3.  *
  4.  * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  5.  */
  6. #include <linux/kernel.h>
  7. #include <linux/slab.h>
  8. #include <linux/config.h>
  9. #include <linux/init.h>
  10. #include <linux/pci.h>
  11. #include <asm/system.h>
  12. #include <asm/sbus.h>
  13. #include <asm/dma.h>
  14. #include <asm/oplib.h>
  15. #include <asm/bpp.h>
  16. #include <asm/irq.h>
  17. struct sbus_bus *sbus_root = NULL;
  18. static struct linux_prom_irqs irqs[PROMINTR_MAX] __initdata = { { 0 } };
  19. /* Perhaps when I figure out more about the iommu we'll put a
  20.  * device registration routine here that probe_sbus() calls to
  21.  * setup the iommu for each Sbus.
  22.  */
  23. /* We call this for each SBus device, and fill the structure based
  24.  * upon the prom device tree.  We return the start of memory after
  25.  * the things we have allocated.
  26.  */
  27. /* #define DEBUG_FILL */
  28. static void __init fill_sbus_device(int prom_node, struct sbus_dev *sdev)
  29. {
  30. unsigned long address, base;
  31. int len;
  32. sdev->prom_node = prom_node;
  33. prom_getstring(prom_node, "name",
  34.        sdev->prom_name, sizeof(sdev->prom_name));
  35. address = prom_getint(prom_node, "address");
  36. len = prom_getproperty(prom_node, "reg",
  37.        (char *) sdev->reg_addrs,
  38.        sizeof(sdev->reg_addrs));
  39. if (len == -1) {
  40. sdev->num_registers = 0;
  41. goto no_regs;
  42. }
  43. if (len % sizeof(struct linux_prom_registers)) {
  44. prom_printf("fill_sbus_device: proplen for regs of %s "
  45.     " was %d, need multiple of %dn",
  46.     sdev->prom_name, len,
  47.     (int) sizeof(struct linux_prom_registers));
  48. prom_halt();
  49. }
  50. if (len > (sizeof(struct linux_prom_registers) * PROMREG_MAX)) {
  51. prom_printf("fill_sbus_device: Too many register properties "
  52.     "for device %s, len=%dn",
  53.     sdev->prom_name, len);
  54. prom_halt();
  55. }
  56. sdev->num_registers = len / sizeof(struct linux_prom_registers);
  57. sdev->ranges_applied = 0;
  58. base = (unsigned long) sdev->reg_addrs[0].phys_addr;
  59. /* Compute the slot number. */
  60. if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) {
  61. sdev->slot = sbus_dev_slot(base);
  62. } else {
  63. sdev->slot = sdev->reg_addrs[0].which_io;
  64. }
  65. no_regs:
  66. len = prom_getproperty(prom_node, "ranges",
  67.        (char *)sdev->device_ranges,
  68.        sizeof(sdev->device_ranges));
  69. if (len == -1) {
  70. sdev->num_device_ranges = 0;
  71. goto no_ranges;
  72. }
  73. if (len % sizeof(struct linux_prom_ranges)) {
  74. prom_printf("fill_sbus_device: proplen for ranges of %s "
  75.     " was %d, need multiple of %dn",
  76.     sdev->prom_name, len,
  77.     (int) sizeof(struct linux_prom_ranges));
  78. prom_halt();
  79. }
  80. if (len > (sizeof(struct linux_prom_ranges) * PROMREG_MAX)) {
  81. prom_printf("fill_sbus_device: Too many range properties "
  82.     "for device %s, len=%dn",
  83.     sdev->prom_name, len);
  84. prom_halt();
  85. }
  86. sdev->num_device_ranges =
  87. len / sizeof(struct linux_prom_ranges);
  88. no_ranges:
  89. /* XXX Unfortunately, IRQ issues are very arch specific.
  90.  * XXX Pull this crud out into an arch specific area
  91.  * XXX at some point. -DaveM
  92.  */
  93. #ifdef __sparc_v9__
  94. len = prom_getproperty(prom_node, "interrupts",
  95.        (char *) irqs, sizeof(irqs));
  96. if (len == -1 || len == 0) {
  97. sdev->irqs[0] = 0;
  98. sdev->num_irqs = 0;
  99. } else {
  100. unsigned int pri = irqs[0].pri;
  101. sdev->num_irqs = 1;
  102. if (pri < 0x20)
  103. pri += sdev->slot * 8;
  104. sdev->irqs[0] = sbus_build_irq(sdev->bus, pri);
  105. }
  106. #else
  107. len = prom_getproperty(prom_node, "intr",
  108.        (char *)irqs, sizeof(irqs));
  109. if (len == -1)
  110. len = 0;
  111. sdev->num_irqs = len / 8;
  112. if (sdev->num_irqs == 0) {
  113. sdev->irqs[0] = 0;
  114. } else if (sparc_cpu_model == sun4d) {
  115. extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);
  116. for (len = 0; len < sdev->num_irqs; len++)
  117. sdev->irqs[len] = sun4d_build_irq(sdev, irqs[len].pri);
  118. } else {
  119. for (len = 0; len < sdev->num_irqs; len++)
  120. sdev->irqs[len] = irqs[len].pri;
  121. }
  122. #endif /* !__sparc_v9__ */
  123. }
  124. /* This routine gets called from whoever needs the sbus first, to scan
  125.  * the SBus device tree.  Currently it just prints out the devices
  126.  * found on the bus and builds trees of SBUS structs and attached
  127.  * devices.
  128.  */
  129. extern void iommu_init(int iommu_node, struct sbus_bus *sbus);
  130. extern void iounit_init(int sbi_node, int iounit_node, struct sbus_bus *sbus);
  131. void sun4_init(void);
  132. #ifdef CONFIG_SUN_AUXIO
  133. extern void auxio_probe(void);
  134. #endif
  135. static void __init sbus_do_child_siblings(int start_node,
  136.   struct sbus_dev *child,
  137.   struct sbus_dev *parent,
  138.   struct sbus_bus *sbus)
  139. {
  140. struct sbus_dev *this_dev = child;
  141. int this_node = start_node;
  142. /* Child already filled in, just need to traverse siblings. */
  143. child->child = NULL;
  144. child->parent = parent;
  145. while((this_node = prom_getsibling(this_node)) != 0) {
  146. this_dev->next = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC);
  147. this_dev = this_dev->next;
  148. this_dev->next = 0;
  149. this_dev->parent = parent;
  150. this_dev->bus = sbus;
  151. fill_sbus_device(this_node, this_dev);
  152. if(prom_getchild(this_node)) {
  153. this_dev->child = kmalloc(sizeof(struct sbus_dev),
  154.   GFP_ATOMIC);
  155. this_dev->child->bus = sbus;
  156. this_dev->child->next = 0;
  157. fill_sbus_device(prom_getchild(this_node), this_dev->child);
  158. sbus_do_child_siblings(prom_getchild(this_node),
  159.        this_dev->child, this_dev, sbus);
  160. } else {
  161. this_dev->child = NULL;
  162. }
  163. }
  164. }
  165. /*
  166.  * XXX This functions appears to be a distorted version of
  167.  * prom_sbus_ranges_init(), with all sun4d stuff cut away.
  168.  * Ask DaveM what is going on here, how is sun4d supposed to work... XXX
  169.  */
  170. static void __init sbus_bus_ranges_init(int parent_node, struct sbus_bus *sbus)
  171. {
  172. int len;
  173. len = prom_getproperty(sbus->prom_node, "ranges",
  174.        (char *) sbus->sbus_ranges,
  175.        sizeof(sbus->sbus_ranges));
  176. if (len == -1 || len == 0) {
  177. sbus->num_sbus_ranges = 0;
  178. return;
  179. }
  180. sbus->num_sbus_ranges = len / sizeof(struct linux_prom_ranges);
  181. }
  182. static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges,
  183.   int num_ranges,
  184.   struct linux_prom_registers *regs,
  185.   int num_regs)
  186. {
  187. if (num_ranges) {
  188. int regnum;
  189. for (regnum = 0; regnum < num_regs; regnum++) {
  190. int rngnum;
  191. for (rngnum = 0; rngnum < num_ranges; rngnum++) {
  192. if (regs[regnum].which_io == ranges[rngnum].ot_child_space)
  193. break;
  194. }
  195. if (rngnum == num_ranges) {
  196. /* We used to flag this as an error.  Actually
  197.  * some devices do not report the regs as we expect.
  198.  * For example, see SUNW,pln device.  In that case
  199.  * the reg property is in a format internal to that
  200.  * node, ie. it is not in the SBUS register space
  201.  * per se. -DaveM
  202.  */
  203. return;
  204. }
  205. regs[regnum].which_io = ranges[rngnum].ot_parent_space;
  206. regs[regnum].phys_addr -= ranges[rngnum].ot_child_base;
  207. regs[regnum].phys_addr += ranges[rngnum].ot_parent_base;
  208. }
  209. }
  210. }
  211. static void __init __fixup_regs_sdev(struct sbus_dev *sdev)
  212. {
  213. if (sdev->num_registers != 0) {
  214. struct sbus_dev *parent = sdev->parent;
  215. int i;
  216. while (parent != NULL) {
  217. __apply_ranges_to_regs(parent->device_ranges,
  218.        parent->num_device_ranges,
  219.        sdev->reg_addrs,
  220.        sdev->num_registers);
  221. parent = parent->parent;
  222. }
  223. __apply_ranges_to_regs(sdev->bus->sbus_ranges,
  224.        sdev->bus->num_sbus_ranges,
  225.        sdev->reg_addrs,
  226.        sdev->num_registers);
  227. for (i = 0; i < sdev->num_registers; i++) {
  228. struct resource *res = &sdev->resource[i];
  229. res->start = sdev->reg_addrs[i].phys_addr;
  230. res->end = (res->start +
  231.     (unsigned long)sdev->reg_addrs[i].reg_size - 1UL);
  232. res->flags = IORESOURCE_IO |
  233. (sdev->reg_addrs[i].which_io & 0xff);
  234. }
  235. }
  236. }
  237. static void __init sbus_fixup_all_regs(struct sbus_dev *first_sdev)
  238. {
  239. struct sbus_dev *sdev;
  240. for (sdev = first_sdev; sdev; sdev = sdev->next) {
  241. if (sdev->child)
  242. sbus_fixup_all_regs(sdev->child);
  243. __fixup_regs_sdev(sdev);
  244. }
  245. }
  246. extern void register_proc_sparc_ioport(void);
  247. extern void firetruck_init(void);
  248. extern void rs_init(void);
  249. void __init sbus_init(void)
  250. {
  251. int nd, this_sbus, sbus_devs, topnd, iommund;
  252. unsigned int sbus_clock;
  253. struct sbus_bus *sbus;
  254. struct sbus_dev *this_dev;
  255. int num_sbus = 0;  /* How many did we find? */
  256. #ifndef __sparc_v9__
  257. register_proc_sparc_ioport();
  258. #endif
  259. #ifdef CONFIG_SUN4
  260. return sun4_dvma_init();
  261. #endif
  262. topnd = prom_getchild(prom_root_node);
  263. /* Finding the first sbus is a special case... */
  264. iommund = 0;
  265. if(sparc_cpu_model == sun4u) {
  266. nd = prom_searchsiblings(topnd, "sbus");
  267. if(nd == 0) {
  268. #ifdef CONFIG_PCI
  269. if (!pcibios_present()) {
  270. prom_printf("Neither SBUS nor PCI found.n");
  271. prom_halt();
  272. } else {
  273. #ifdef __sparc_v9__
  274. firetruck_init();
  275. #endif
  276. }
  277. return;
  278. #else
  279. prom_printf("YEEE, UltraSparc sbus not foundn");
  280. prom_halt();
  281. #endif
  282. }
  283. } else if(sparc_cpu_model == sun4d) {
  284. if((iommund = prom_searchsiblings(topnd, "io-unit")) == 0 ||
  285.    (nd = prom_getchild(iommund)) == 0 ||
  286.    (nd = prom_searchsiblings(nd, "sbi")) == 0) {
  287.     panic("sbi not found");
  288. }
  289. } else if((nd = prom_searchsiblings(topnd, "sbus")) == 0) {
  290. if((iommund = prom_searchsiblings(topnd, "iommu")) == 0 ||
  291.    (nd = prom_getchild(iommund)) == 0 ||
  292.    (nd = prom_searchsiblings(nd, "sbus")) == 0) {
  293. #ifdef CONFIG_PCI
  294.                         if (!pcibios_present()) {       
  295.                                 prom_printf("Neither SBUS nor PCI found.n");
  296.                                 prom_halt();
  297.                         }
  298.                         return;
  299. #else
  300. /* No reason to run further - the data access trap will occur. */
  301. panic("sbus not found");
  302. #endif
  303. }
  304. }
  305. /* Ok, we've found the first one, allocate first SBus struct
  306.  * and place in chain.
  307.  */
  308. sbus = sbus_root = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
  309. sbus->next = NULL;
  310. sbus->prom_node = nd;
  311. this_sbus = nd;
  312. if(iommund && sparc_cpu_model != sun4u && sparc_cpu_model != sun4d)
  313. iommu_init(iommund, sbus);
  314. /* Loop until we find no more SBUS's */
  315. while(this_sbus) {
  316. #ifdef __sparc_v9__   
  317. /* IOMMU hides inside SBUS/SYSIO prom node on Ultra. */
  318. if(sparc_cpu_model == sun4u) {
  319. extern void sbus_iommu_init(int prom_node, struct sbus_bus *sbus);
  320. sbus_iommu_init(this_sbus, sbus);
  321. }
  322. #endif
  323. #ifndef __sparc_v9__   
  324. if (sparc_cpu_model == sun4d)
  325. iounit_init(this_sbus, iommund, sbus);
  326. #endif    
  327. printk("sbus%d: ", num_sbus);
  328. sbus_clock = prom_getint(this_sbus, "clock-frequency");
  329. if(sbus_clock == -1)
  330. sbus_clock = (25*1000*1000);
  331. printk("Clock %d.%d MHzn", (int) ((sbus_clock/1000)/1000),
  332.        (int) (((sbus_clock/1000)%1000 != 0) ? 
  333.       (((sbus_clock/1000)%1000) + 1000) : 0));
  334. prom_getstring(this_sbus, "name",
  335.        sbus->prom_name, sizeof(sbus->prom_name));
  336. sbus->clock_freq = sbus_clock;
  337. #ifndef __sparc_v9__
  338. if (sparc_cpu_model == sun4d) {
  339. sbus->devid = prom_getint(iommund, "device-id");
  340. sbus->board = prom_getint(iommund, "board#");
  341. }
  342. #endif
  343. sbus_bus_ranges_init(iommund, sbus);
  344. sbus_devs = prom_getchild(this_sbus);
  345. sbus->devices = kmalloc(sizeof(struct sbus_dev), GFP_ATOMIC);
  346. this_dev = sbus->devices;
  347. this_dev->next = NULL;
  348. this_dev->bus = sbus;
  349. this_dev->parent = NULL;
  350. fill_sbus_device(sbus_devs, this_dev);
  351. /* Should we traverse for children? */
  352. if(prom_getchild(sbus_devs)) {
  353. /* Allocate device node */
  354. this_dev->child = kmalloc(sizeof(struct sbus_dev),
  355.   GFP_ATOMIC);
  356. /* Fill it */
  357. this_dev->child->bus = sbus;
  358. this_dev->child->next = 0;
  359. fill_sbus_device(prom_getchild(sbus_devs),
  360.  this_dev->child);
  361. sbus_do_child_siblings(prom_getchild(sbus_devs),
  362.        this_dev->child,
  363.        this_dev,
  364.        sbus);
  365. } else {
  366. this_dev->child = NULL;
  367. }
  368. while((sbus_devs = prom_getsibling(sbus_devs)) != 0) {
  369. /* Allocate device node */
  370. this_dev->next = kmalloc(sizeof(struct sbus_dev),
  371.  GFP_ATOMIC);
  372. this_dev = this_dev->next;
  373. this_dev->next = NULL;
  374. /* Fill it */
  375. this_dev->bus = sbus;
  376. this_dev->parent = NULL;
  377. fill_sbus_device(sbus_devs, this_dev);
  378. /* Is there a child node hanging off of us? */
  379. if(prom_getchild(sbus_devs)) {
  380. /* Get new device struct */
  381. this_dev->child = kmalloc(sizeof(struct sbus_dev),
  382.   GFP_ATOMIC);
  383. /* Fill it */
  384. this_dev->child->bus = sbus;
  385. this_dev->child->next = 0;
  386. fill_sbus_device(prom_getchild(sbus_devs),
  387.  this_dev->child);
  388. sbus_do_child_siblings(prom_getchild(sbus_devs),
  389.        this_dev->child,
  390.        this_dev,
  391.        sbus);
  392. } else {
  393. this_dev->child = NULL;
  394. }
  395. }
  396. /* Walk all devices and apply parent ranges. */
  397. sbus_fixup_all_regs(sbus->devices);
  398. dvma_init(sbus);
  399. num_sbus++;
  400. if(sparc_cpu_model == sun4u) {
  401. this_sbus = prom_getsibling(this_sbus);
  402. if(!this_sbus)
  403. break;
  404. this_sbus = prom_searchsiblings(this_sbus, "sbus");
  405. } else if(sparc_cpu_model == sun4d) {
  406. iommund = prom_getsibling(iommund);
  407. if(!iommund)
  408. break;
  409. iommund = prom_searchsiblings(iommund, "io-unit");
  410. if(!iommund)
  411. break;
  412. this_sbus = prom_searchsiblings(prom_getchild(iommund), "sbi");
  413. } else {
  414. this_sbus = prom_getsibling(this_sbus);
  415. if(!this_sbus)
  416. break;
  417. this_sbus = prom_searchsiblings(this_sbus, "sbus");
  418. }
  419. if(this_sbus) {
  420. sbus->next = kmalloc(sizeof(struct sbus_bus), GFP_ATOMIC);
  421. sbus = sbus->next;
  422. sbus->next = NULL;
  423. sbus->prom_node = this_sbus;
  424. } else {
  425. break;
  426. }
  427. } /* while(this_sbus) */
  428. if (sparc_cpu_model == sun4d) {
  429. extern void sun4d_init_sbi_irq(void);
  430. sun4d_init_sbi_irq();
  431. }
  432. rs_init();
  433. #ifdef __sparc_v9__
  434. if (sparc_cpu_model == sun4u) {
  435. firetruck_init();
  436. }
  437. #endif
  438. #ifdef CONFIG_SUN_AUXIO
  439. if (sparc_cpu_model == sun4u)
  440. auxio_probe ();
  441. #endif
  442. #ifdef __sparc_v9__
  443. if (sparc_cpu_model == sun4u) {
  444. extern void clock_probe(void);
  445. clock_probe();
  446. }
  447. #endif
  448. }