aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc/kernel/ioport.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/ioport.c')
-rw-r--r--arch/sparc/kernel/ioport.c227
1 files changed, 25 insertions, 202 deletions
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c
index 2a8a847764d8..4f025b36934b 100644
--- a/arch/sparc/kernel/ioport.c
+++ b/arch/sparc/kernel/ioport.c
@@ -42,10 +42,13 @@
42#include <asm/vaddrs.h> 42#include <asm/vaddrs.h>
43#include <asm/oplib.h> 43#include <asm/oplib.h>
44#include <asm/prom.h> 44#include <asm/prom.h>
45#include <asm/sbus.h>
46#include <asm/page.h> 45#include <asm/page.h>
47#include <asm/pgalloc.h> 46#include <asm/pgalloc.h>
48#include <asm/dma.h> 47#include <asm/dma.h>
48#include <asm/iommu.h>
49#include <asm/io-unit.h>
50
51#include "dma.h"
49 52
50#define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */ 53#define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */
51 54
@@ -139,15 +142,6 @@ void iounmap(volatile void __iomem *virtual)
139 } 142 }
140} 143}
141 144
142/*
143 */
144void __iomem *sbus_ioremap(struct resource *phyres, unsigned long offset,
145 unsigned long size, char *name)
146{
147 return _sparc_alloc_io(phyres->flags & 0xF,
148 phyres->start + offset, size, name);
149}
150
151void __iomem *of_ioremap(struct resource *res, unsigned long offset, 145void __iomem *of_ioremap(struct resource *res, unsigned long offset,
152 unsigned long size, char *name) 146 unsigned long size, char *name)
153{ 147{
@@ -164,13 +158,6 @@ void of_iounmap(struct resource *res, void __iomem *base, unsigned long size)
164EXPORT_SYMBOL(of_iounmap); 158EXPORT_SYMBOL(of_iounmap);
165 159
166/* 160/*
167 */
168void sbus_iounmap(volatile void __iomem *addr, unsigned long size)
169{
170 iounmap(addr);
171}
172
173/*
174 * Meat of mapping 161 * Meat of mapping
175 */ 162 */
176static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys, 163static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys,
@@ -246,63 +233,19 @@ static void _sparc_free_io(struct resource *res)
246 233
247#ifdef CONFIG_SBUS 234#ifdef CONFIG_SBUS
248 235
249void sbus_set_sbus64(struct sbus_dev *sdev, int x) 236void sbus_set_sbus64(struct device *dev, int x)
250{ 237{
251 printk("sbus_set_sbus64: unsupported\n"); 238 printk("sbus_set_sbus64: unsupported\n");
252} 239}
253 240
254extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq);
255void __init sbus_fill_device_irq(struct sbus_dev *sdev)
256{
257 struct linux_prom_irqs irqs[PROMINTR_MAX];
258 int len;
259
260 len = prom_getproperty(sdev->prom_node, "intr",
261 (char *)irqs, sizeof(irqs));
262 if (len != -1) {
263 sdev->num_irqs = len / 8;
264 if (sdev->num_irqs == 0) {
265 sdev->irqs[0] = 0;
266 } else if (sparc_cpu_model == sun4d) {
267 for (len = 0; len < sdev->num_irqs; len++)
268 sdev->irqs[len] =
269 sun4d_build_irq(sdev, irqs[len].pri);
270 } else {
271 for (len = 0; len < sdev->num_irqs; len++)
272 sdev->irqs[len] = irqs[len].pri;
273 }
274 } else {
275 int interrupts[PROMINTR_MAX];
276
277 /* No "intr" node found-- check for "interrupts" node.
278 * This node contains SBus interrupt levels, not IPLs
279 * as in "intr", and no vector values. We convert
280 * SBus interrupt levels to PILs (platform specific).
281 */
282 len = prom_getproperty(sdev->prom_node, "interrupts",
283 (char *)interrupts, sizeof(interrupts));
284 if (len == -1) {
285 sdev->irqs[0] = 0;
286 sdev->num_irqs = 0;
287 } else {
288 sdev->num_irqs = len / sizeof(int);
289 for (len = 0; len < sdev->num_irqs; len++) {
290 sdev->irqs[len] =
291 sbint_to_irq(sdev, interrupts[len]);
292 }
293 }
294 }
295}
296
297/* 241/*
298 * Allocate a chunk of memory suitable for DMA. 242 * Allocate a chunk of memory suitable for DMA.
299 * Typically devices use them for control blocks. 243 * Typically devices use them for control blocks.
300 * CPU may access them without any explicit flushing. 244 * CPU may access them without any explicit flushing.
301 *
302 * XXX Some clever people know that sdev is not used and supply NULL. Watch.
303 */ 245 */
304void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp) 246void *sbus_alloc_consistent(struct device *dev, long len, u32 *dma_addrp)
305{ 247{
248 struct of_device *op = to_of_device(dev);
306 unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK; 249 unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK;
307 unsigned long va; 250 unsigned long va;
308 struct resource *res; 251 struct resource *res;
@@ -336,13 +279,10 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp)
336 * XXX That's where sdev would be used. Currently we load 279 * XXX That's where sdev would be used. Currently we load
337 * all iommu tables with the same translations. 280 * all iommu tables with the same translations.
338 */ 281 */
339 if (mmu_map_dma_area(dma_addrp, va, res->start, len_total) != 0) 282 if (mmu_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0)
340 goto err_noiommu; 283 goto err_noiommu;
341 284
342 /* Set the resource name, if known. */ 285 res->name = op->node->name;
343 if (sdev) {
344 res->name = sdev->prom_name;
345 }
346 286
347 return (void *)(unsigned long)res->start; 287 return (void *)(unsigned long)res->start;
348 288
@@ -356,7 +296,7 @@ err_nopages:
356 return NULL; 296 return NULL;
357} 297}
358 298
359void sbus_free_consistent(struct sbus_dev *sdev, long n, void *p, u32 ba) 299void sbus_free_consistent(struct device *dev, long n, void *p, u32 ba)
360{ 300{
361 struct resource *res; 301 struct resource *res;
362 struct page *pgv; 302 struct page *pgv;
@@ -383,8 +323,8 @@ void sbus_free_consistent(struct sbus_dev *sdev, long n, void *p, u32 ba)
383 kfree(res); 323 kfree(res);
384 324
385 /* mmu_inval_dma_area(va, n); */ /* it's consistent, isn't it */ 325 /* mmu_inval_dma_area(va, n); */ /* it's consistent, isn't it */
386 pgv = mmu_translate_dvma(ba); 326 pgv = virt_to_page(p);
387 mmu_unmap_dma_area(ba, n); 327 mmu_unmap_dma_area(dev, ba, n);
388 328
389 __free_pages(pgv, get_order(n)); 329 __free_pages(pgv, get_order(n));
390} 330}
@@ -394,7 +334,7 @@ void sbus_free_consistent(struct sbus_dev *sdev, long n, void *p, u32 ba)
394 * CPU view of this memory may be inconsistent with 334 * CPU view of this memory may be inconsistent with
395 * a device view and explicit flushing is necessary. 335 * a device view and explicit flushing is necessary.
396 */ 336 */
397dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *va, size_t len, int direction) 337dma_addr_t sbus_map_single(struct device *dev, void *va, size_t len, int direction)
398{ 338{
399 /* XXX why are some lengths signed, others unsigned? */ 339 /* XXX why are some lengths signed, others unsigned? */
400 if (len <= 0) { 340 if (len <= 0) {
@@ -404,17 +344,17 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *va, size_t len, int dire
404 if (len > 256*1024) { /* __get_free_pages() limit */ 344 if (len > 256*1024) { /* __get_free_pages() limit */
405 return 0; 345 return 0;
406 } 346 }
407 return mmu_get_scsi_one(va, len, sdev->bus); 347 return mmu_get_scsi_one(dev, va, len);
408} 348}
409 349
410void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t ba, size_t n, int direction) 350void sbus_unmap_single(struct device *dev, dma_addr_t ba, size_t n, int direction)
411{ 351{
412 mmu_release_scsi_one(ba, n, sdev->bus); 352 mmu_release_scsi_one(dev, ba, n);
413} 353}
414 354
415int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) 355int sbus_map_sg(struct device *dev, struct scatterlist *sg, int n, int direction)
416{ 356{
417 mmu_get_scsi_sgl(sg, n, sdev->bus); 357 mmu_get_scsi_sgl(dev, sg, n);
418 358
419 /* 359 /*
420 * XXX sparc64 can return a partial length here. sun4c should do this 360 * XXX sparc64 can return a partial length here. sun4c should do this
@@ -423,145 +363,28 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direct
423 return n; 363 return n;
424} 364}
425 365
426void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) 366void sbus_unmap_sg(struct device *dev, struct scatterlist *sg, int n, int direction)
427{
428 mmu_release_scsi_sgl(sg, n, sdev->bus);
429}
430
431/*
432 */
433void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t ba, size_t size, int direction)
434{
435#if 0
436 unsigned long va;
437 struct resource *res;
438
439 /* We do not need the resource, just print a message if invalid. */
440 res = _sparc_find_resource(&_sparc_dvma, ba);
441 if (res == NULL)
442 panic("sbus_dma_sync_single: 0x%x\n", ba);
443
444 va = page_address(mmu_translate_dvma(ba)); /* XXX higmem */
445 /*
446 * XXX This bogosity will be fixed with the iommu rewrite coming soon
447 * to a kernel near you. - Anton
448 */
449 /* mmu_inval_dma_area(va, (size + PAGE_SIZE-1) & PAGE_MASK); */
450#endif
451}
452
453void sbus_dma_sync_single_for_device(struct sbus_dev *sdev, dma_addr_t ba, size_t size, int direction)
454{ 367{
455#if 0 368 mmu_release_scsi_sgl(dev, sg, n);
456 unsigned long va;
457 struct resource *res;
458
459 /* We do not need the resource, just print a message if invalid. */
460 res = _sparc_find_resource(&_sparc_dvma, ba);
461 if (res == NULL)
462 panic("sbus_dma_sync_single: 0x%x\n", ba);
463
464 va = page_address(mmu_translate_dvma(ba)); /* XXX higmem */
465 /*
466 * XXX This bogosity will be fixed with the iommu rewrite coming soon
467 * to a kernel near you. - Anton
468 */
469 /* mmu_inval_dma_area(va, (size + PAGE_SIZE-1) & PAGE_MASK); */
470#endif
471} 369}
472 370
473void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) 371void sbus_dma_sync_single_for_cpu(struct device *dev, dma_addr_t ba, size_t size, int direction)
474{ 372{
475 printk("sbus_dma_sync_sg_for_cpu: not implemented yet\n");
476} 373}
477 374
478void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) 375void sbus_dma_sync_single_for_device(struct device *dev, dma_addr_t ba, size_t size, int direction)
479{ 376{
480 printk("sbus_dma_sync_sg_for_device: not implemented yet\n");
481}
482
483/* Support code for sbus_init(). */
484/*
485 * XXX This functions appears to be a distorted version of
486 * prom_sbus_ranges_init(), with all sun4d stuff cut away.
487 * Ask DaveM what is going on here, how is sun4d supposed to work... XXX
488 */
489/* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */
490void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus)
491{
492 int parent_node = pn->node;
493
494 if (sparc_cpu_model == sun4d) {
495 struct linux_prom_ranges iounit_ranges[PROMREG_MAX];
496 int num_iounit_ranges, len;
497
498 len = prom_getproperty(parent_node, "ranges",
499 (char *) iounit_ranges,
500 sizeof (iounit_ranges));
501 if (len != -1) {
502 num_iounit_ranges =
503 (len / sizeof(struct linux_prom_ranges));
504 prom_adjust_ranges(sbus->sbus_ranges,
505 sbus->num_sbus_ranges,
506 iounit_ranges, num_iounit_ranges);
507 }
508 }
509} 377}
510 378
511void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) 379static int __init sparc_register_ioport(void)
512{
513#ifndef CONFIG_SUN4
514 struct device_node *parent = dp->parent;
515
516 if (sparc_cpu_model != sun4d &&
517 parent != NULL &&
518 !strcmp(parent->name, "iommu")) {
519 extern void iommu_init(int iommu_node, struct sbus_bus *sbus);
520
521 iommu_init(parent->node, sbus);
522 }
523
524 if (sparc_cpu_model == sun4d) {
525 extern void iounit_init(int sbi_node, int iounit_node,
526 struct sbus_bus *sbus);
527
528 iounit_init(dp->node, parent->node, sbus);
529 }
530#endif
531}
532
533void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp)
534{
535 if (sparc_cpu_model == sun4d) {
536 struct device_node *parent = dp->parent;
537
538 sbus->devid = of_getintprop_default(parent, "device-id", 0);
539 sbus->board = of_getintprop_default(parent, "board#", 0);
540 }
541}
542
543int __init sbus_arch_preinit(void)
544{ 380{
545 register_proc_sparc_ioport(); 381 register_proc_sparc_ioport();
546 382
547#ifdef CONFIG_SUN4
548 {
549 extern void sun4_dvma_init(void);
550 sun4_dvma_init();
551 }
552 return 1;
553#else
554 return 0; 383 return 0;
555#endif
556} 384}
557 385
558void __init sbus_arch_postinit(void) 386arch_initcall(sparc_register_ioport);
559{ 387
560 if (sparc_cpu_model == sun4d) {
561 extern void sun4d_init_sbi_irq(void);
562 sun4d_init_sbi_irq();
563 }
564}
565#endif /* CONFIG_SBUS */ 388#endif /* CONFIG_SBUS */
566 389
567#ifdef CONFIG_PCI 390#ifdef CONFIG_PCI