aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/sbus/dvma.c
blob: ab0d2de3324c16f73318d01603ee4381a9fb2d86 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* dvma.c:  Routines that are used to access DMA on the Sparc SBus.
 *
 * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
 */

#include <linux/string.h>
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/delay.h>

#include <asm/oplib.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <asm/sbus.h>

struct sbus_dma *dma_chain;

static void __init init_one_dvma(struct sbus_dma *dma, int num_dma)
{
	printk("dma%d: ", num_dma);
	
	dma->next = NULL;
	dma->running = 0;      /* No transfers going on as of yet */
	dma->allocated = 0;    /* No one has allocated us yet */
	switch(sbus_readl(dma->regs + DMA_CSR)&DMA_DEVICE_ID) {
	case DMA_VERS0:
		dma->revision = dvmarev0;
		printk("Revision 0 ");
		break;
	case DMA_ESCV1:
		dma->revision = dvmaesc1;
		printk("ESC Revision 1 ");
		break;
	case DMA_VERS1:
		dma->revision = dvmarev1;
		printk("Revision 1 ");
		break;
	case DMA_VERS2:
		dma->revision = dvmarev2;
		printk("Revision 2 ");
		break;
	case DMA_VERHME:
		dma->revision = dvmahme;
		printk("HME DVMA gate array ");
		break;
	case DMA_VERSPLUS:
		dma->revision = dvmarevplus;
		printk("Revision 1 PLUS ");
		break;
	default:
		printk("unknown dma version %08x",
		       sbus_readl(dma->regs + DMA_CSR) & DMA_DEVICE_ID);
		dma->allocated = 1;
		break;
	}
	printk("\n");
}

/* Probe this SBus DMA module(s) */
void __init dvma_init(struct sbus_bus *sbus)
{
	struct sbus_dev *this_dev;
	struct sbus_dma *dma;
	struct sbus_dma *dchain;
	static int num_dma = 0;

	for_each_sbusdev(this_dev, sbus) {
		char *name = this_dev->prom_name;
		int hme = 0;

		if(!strcmp(name, "SUNW,fas"))
			hme = 1;
		else if(strcmp(name, "dma") &&
			strcmp(name, "ledma") &&
			strcmp(name, "espdma"))
			continue;

		/* Found one... */
		dma = kmalloc(sizeof(struct sbus_dma), GFP_ATOMIC);

		dma->sdev = this_dev;

		/* Put at end of dma chain */
		dchain = dma_chain;
		if(dchain) {
			while(dchain->next)
				dchain = dchain->next;
			dchain->next = dma;
		} else {
			/* We're the first in line */
			dma_chain = dma;
		}

		dma->regs = sbus_ioremap(&dma->sdev->resource[0], 0,
					 dma->sdev->resource[0].end - dma->sdev->resource[0].start + 1,
					 "dma");

		dma->node = dma->sdev->prom_node;
		
		init_one_dvma(dma, num_dma++);
	}
}

#ifdef CONFIG_SUN4

#include <asm/sun4paddr.h>

void __init sun4_dvma_init(void)
{
	struct sbus_dma *dma;
	struct resource r;

	if(sun4_dma_physaddr) {
		dma = kmalloc(sizeof(struct sbus_dma), GFP_ATOMIC);

		/* No SBUS */
		dma->sdev = NULL;

		/* Only one DMA device */
		dma_chain = dma;

		memset(&r, 0, sizeof(r));
		r.start = sun4_dma_physaddr;
		dma->regs = sbus_ioremap(&r, 0, PAGE_SIZE, "dma");

		/* No prom node */
		dma->node = 0x0;

		init_one_dvma(dma, 0);
	} else {
	  	dma_chain = NULL;
	}
}

#endif