Pull osi-now into release branch
[linux-2.6] / include / asm-sparc64 / parport.h
1 /* $Id: parport.h,v 1.11 2001/05/11 07:54:24 davem Exp $
2  * parport.h: sparc64 specific parport initialization and dma.
3  *
4  * Copyright (C) 1999  Eddie C. Dost  (ecd@skynet.be)
5  */
6
7 #ifndef _ASM_SPARC64_PARPORT_H
8 #define _ASM_SPARC64_PARPORT_H 1
9
10 #include <asm/ebus.h>
11 #include <asm/isa.h>
12 #include <asm/ns87303.h>
13
14 #define PARPORT_PC_MAX_PORTS    PARPORT_MAX
15
16 /*
17  * While sparc64 doesn't have an ISA DMA API, we provide something that looks
18  * close enough to make parport_pc happy
19  */
20 #define HAS_DMA
21
22 static DEFINE_SPINLOCK(dma_spin_lock);
23
24 #define claim_dma_lock() \
25 ({      unsigned long flags; \
26         spin_lock_irqsave(&dma_spin_lock, flags); \
27         flags; \
28 })
29
30 #define release_dma_lock(__flags) \
31         spin_unlock_irqrestore(&dma_spin_lock, __flags);
32
33 static struct sparc_ebus_info {
34         struct ebus_dma_info info;
35         unsigned int addr;
36         unsigned int count;
37         int lock;
38 } sparc_ebus_dmas[PARPORT_PC_MAX_PORTS];
39
40 static __inline__ int request_dma(unsigned int dmanr, const char *device_id)
41 {
42         if (dmanr >= PARPORT_PC_MAX_PORTS)
43                 return -EINVAL;
44         if (xchg(&sparc_ebus_dmas[dmanr].lock, 1) != 0)
45                 return -EBUSY;
46         return 0;
47 }
48
49 static __inline__ void free_dma(unsigned int dmanr)
50 {
51         if (dmanr >= PARPORT_PC_MAX_PORTS) {
52                 printk(KERN_WARNING "Trying to free DMA%d\n", dmanr);
53                 return;
54         }
55         if (xchg(&sparc_ebus_dmas[dmanr].lock, 0) == 0) {
56                 printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr);
57                 return;
58         }       
59 }
60
61 static __inline__ void enable_dma(unsigned int dmanr)
62 {
63         ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 1);
64
65         if (ebus_dma_request(&sparc_ebus_dmas[dmanr].info,
66                              sparc_ebus_dmas[dmanr].addr,
67                              sparc_ebus_dmas[dmanr].count))
68                 BUG();
69 }
70
71 static __inline__ void disable_dma(unsigned int dmanr)
72 {
73         ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 0);
74 }
75
76 static __inline__ void clear_dma_ff(unsigned int dmanr)
77 {
78         /* nothing */
79 }
80
81 static __inline__ void set_dma_mode(unsigned int dmanr, char mode)
82 {
83         ebus_dma_prepare(&sparc_ebus_dmas[dmanr].info, (mode != DMA_MODE_WRITE));
84 }
85
86 static __inline__ void set_dma_addr(unsigned int dmanr, unsigned int addr)
87 {
88         sparc_ebus_dmas[dmanr].addr = addr;
89 }
90
91 static __inline__ void set_dma_count(unsigned int dmanr, unsigned int count)
92 {
93         sparc_ebus_dmas[dmanr].count = count;
94 }
95
96 static __inline__ unsigned int get_dma_residue(unsigned int dmanr)
97 {
98         return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
99 }
100
101 static int ebus_ecpp_p(struct linux_ebus_device *edev)
102 {
103         if (!strcmp(edev->prom_node->name, "ecpp"))
104                 return 1;
105         if (!strcmp(edev->prom_node->name, "parallel")) {
106                 const char *compat;
107
108                 compat = of_get_property(edev->prom_node,
109                                          "compatible", NULL);
110                 if (compat &&
111                     (!strcmp(compat, "ecpp") ||
112                      !strcmp(compat, "ns87317-ecpp") ||
113                      !strcmp(compat + 13, "ecpp")))
114                         return 1;
115         }
116         return 0;
117 }
118
119 static int parport_isa_probe(int count)
120 {
121         struct sparc_isa_bridge *isa_br;
122         struct sparc_isa_device *isa_dev;
123
124         for_each_isa(isa_br) {
125                 for_each_isadev(isa_dev, isa_br) {
126                         struct sparc_isa_device *child;
127                         unsigned long base;
128
129                         if (strcmp(isa_dev->prom_node->name, "dma"))
130                                 continue;
131
132                         child = isa_dev->child;
133                         while (child) {
134                                 if (!strcmp(child->prom_node->name, "parallel"))
135                                         break;
136                                 child = child->next;
137                         }
138                         if (!child)
139                                 continue;
140
141                         base = child->resource.start;
142
143                         /* No DMA, see commentary in
144                          * asm-sparc64/floppy.h:isa_floppy_init()
145                          */
146                         if (parport_pc_probe_port(base, base + 0x400,
147                                                   child->irq, PARPORT_DMA_NOFIFO,
148                                                   child->bus->self))
149                                 count++;
150                 }
151         }
152
153         return count;
154 }
155
156 static int parport_pc_find_nonpci_ports (int autoirq, int autodma)
157 {
158         struct linux_ebus *ebus;
159         struct linux_ebus_device *edev;
160         int count = 0;
161
162         for_each_ebus(ebus) {
163                 for_each_ebusdev(edev, ebus) {
164                         if (ebus_ecpp_p(edev)) {
165                                 unsigned long base = edev->resource[0].start;
166                                 unsigned long config = edev->resource[1].start;
167                                 unsigned long d_base = edev->resource[2].start;
168                                 unsigned long d_len;
169
170                                 spin_lock_init(&sparc_ebus_dmas[count].info.lock);
171                                 d_len = (edev->resource[2].end -
172                                          d_base) + 1;
173                                 sparc_ebus_dmas[count].info.regs =
174                                         ioremap(d_base, d_len);
175                                 if (!sparc_ebus_dmas[count].info.regs)
176                                         continue;
177                                 sparc_ebus_dmas[count].info.flags = 0;
178                                 sparc_ebus_dmas[count].info.callback = NULL;
179                                 sparc_ebus_dmas[count].info.client_cookie = NULL;
180                                 sparc_ebus_dmas[count].info.irq = 0xdeadbeef;
181                                 strcpy(sparc_ebus_dmas[count].info.name, "parport");
182                                 if (ebus_dma_register(&sparc_ebus_dmas[count].info))
183                                         continue;
184                                 ebus_dma_irq_enable(&sparc_ebus_dmas[count].info, 1);
185
186                                 /* Configure IRQ to Push Pull, Level Low */
187                                 /* Enable ECP, set bit 2 of the CTR first */
188                                 outb(0x04, base + 0x02);
189                                 ns87303_modify(config, PCR,
190                                                PCR_EPP_ENABLE |
191                                                PCR_IRQ_ODRAIN,
192                                                PCR_ECP_ENABLE |
193                                                PCR_ECP_CLK_ENA |
194                                                PCR_IRQ_POLAR);
195
196                                 /* CTR bit 5 controls direction of port */
197                                 ns87303_modify(config, PTR,
198                                                0, PTR_LPT_REG_DIR);
199
200                                 if (parport_pc_probe_port(base, base + 0x400,
201                                                           edev->irqs[0],
202                                                           count, ebus->self))
203                                         count++;
204                         }
205                 }
206         }
207
208         count = parport_isa_probe(count);
209
210         return count;
211 }
212
213 #endif /* !(_ASM_SPARC64_PARPORT_H */