Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
parport.h
Go to the documentation of this file.
1 /* parport.h: sparc64 specific parport initialization and dma.
2  *
3  * Copyright (C) 1999 Eddie C. Dost ([email protected])
4  */
5 
6 #ifndef _ASM_SPARC64_PARPORT_H
7 #define _ASM_SPARC64_PARPORT_H 1
8 
9 #include <linux/of_device.h>
10 
11 #include <asm/ebus_dma.h>
12 #include <asm/ns87303.h>
13 #include <asm/prom.h>
14 
15 #define PARPORT_PC_MAX_PORTS PARPORT_MAX
16 
17 /*
18  * While sparc64 doesn't have an ISA DMA API, we provide something that looks
19  * close enough to make parport_pc happy
20  */
21 #define HAS_DMA
22 
23 static DEFINE_SPINLOCK(dma_spin_lock);
24 
25 #define claim_dma_lock() \
26 ({ unsigned long flags; \
27  spin_lock_irqsave(&dma_spin_lock, flags); \
28  flags; \
29 })
30 
31 #define release_dma_lock(__flags) \
32  spin_unlock_irqrestore(&dma_spin_lock, __flags);
33 
34 static struct sparc_ebus_info {
35  struct ebus_dma_info info;
36  unsigned int addr;
37  unsigned int count;
38  int lock;
39 
40  struct parport *port;
41 } sparc_ebus_dmas[PARPORT_PC_MAX_PORTS];
42 
43 static DECLARE_BITMAP(dma_slot_map, PARPORT_PC_MAX_PORTS);
44 
45 static inline int request_dma(unsigned int dmanr, const char *device_id)
46 {
47  if (dmanr >= PARPORT_PC_MAX_PORTS)
48  return -EINVAL;
49  if (xchg(&sparc_ebus_dmas[dmanr].lock, 1) != 0)
50  return -EBUSY;
51  return 0;
52 }
53 
54 static inline void free_dma(unsigned int dmanr)
55 {
56  if (dmanr >= PARPORT_PC_MAX_PORTS) {
57  printk(KERN_WARNING "Trying to free DMA%d\n", dmanr);
58  return;
59  }
60  if (xchg(&sparc_ebus_dmas[dmanr].lock, 0) == 0) {
61  printk(KERN_WARNING "Trying to free free DMA%d\n", dmanr);
62  return;
63  }
64 }
65 
66 static inline void enable_dma(unsigned int dmanr)
67 {
68  ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 1);
69 
70  if (ebus_dma_request(&sparc_ebus_dmas[dmanr].info,
71  sparc_ebus_dmas[dmanr].addr,
72  sparc_ebus_dmas[dmanr].count))
73  BUG();
74 }
75 
76 static inline void disable_dma(unsigned int dmanr)
77 {
78  ebus_dma_enable(&sparc_ebus_dmas[dmanr].info, 0);
79 }
80 
81 static inline void clear_dma_ff(unsigned int dmanr)
82 {
83  /* nothing */
84 }
85 
86 static inline void set_dma_mode(unsigned int dmanr, char mode)
87 {
88  ebus_dma_prepare(&sparc_ebus_dmas[dmanr].info, (mode != DMA_MODE_WRITE));
89 }
90 
91 static inline void set_dma_addr(unsigned int dmanr, unsigned int addr)
92 {
93  sparc_ebus_dmas[dmanr].addr = addr;
94 }
95 
96 static inline void set_dma_count(unsigned int dmanr, unsigned int count)
97 {
98  sparc_ebus_dmas[dmanr].count = count;
99 }
100 
101 static inline unsigned int get_dma_residue(unsigned int dmanr)
102 {
103  return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
104 }
105 
106 static int __devinit ecpp_probe(struct platform_device *op)
107 {
108  unsigned long base = op->resource[0].start;
109  unsigned long config = op->resource[1].start;
110  unsigned long d_base = op->resource[2].start;
111  unsigned long d_len;
112  struct device_node *parent;
113  struct parport *p;
114  int slot, err;
115 
116  parent = op->dev.of_node->parent;
117  if (!strcmp(parent->name, "dma")) {
118  p = parport_pc_probe_port(base, base + 0x400,
119  op->archdata.irqs[0], PARPORT_DMA_NOFIFO,
120  op->dev.parent->parent, 0);
121  if (!p)
122  return -ENOMEM;
123  dev_set_drvdata(&op->dev, p);
124  return 0;
125  }
126 
127  for (slot = 0; slot < PARPORT_PC_MAX_PORTS; slot++) {
128  if (!test_and_set_bit(slot, dma_slot_map))
129  break;
130  }
131  err = -ENODEV;
132  if (slot >= PARPORT_PC_MAX_PORTS)
133  goto out_err;
134 
135  spin_lock_init(&sparc_ebus_dmas[slot].info.lock);
136 
137  d_len = (op->resource[2].end - d_base) + 1UL;
138  sparc_ebus_dmas[slot].info.regs =
139  of_ioremap(&op->resource[2], 0, d_len, "ECPP DMA");
140 
141  if (!sparc_ebus_dmas[slot].info.regs)
142  goto out_clear_map;
143 
144  sparc_ebus_dmas[slot].info.flags = 0;
145  sparc_ebus_dmas[slot].info.callback = NULL;
146  sparc_ebus_dmas[slot].info.client_cookie = NULL;
147  sparc_ebus_dmas[slot].info.irq = 0xdeadbeef;
148  strcpy(sparc_ebus_dmas[slot].info.name, "parport");
149  if (ebus_dma_register(&sparc_ebus_dmas[slot].info))
150  goto out_unmap_regs;
151 
152  ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 1);
153 
154  /* Configure IRQ to Push Pull, Level Low */
155  /* Enable ECP, set bit 2 of the CTR first */
156  outb(0x04, base + 0x02);
157  ns87303_modify(config, PCR,
162  PCR_IRQ_POLAR);
163 
164  /* CTR bit 5 controls direction of port */
165  ns87303_modify(config, PTR,
166  0, PTR_LPT_REG_DIR);
167 
168  p = parport_pc_probe_port(base, base + 0x400,
169  op->archdata.irqs[0],
170  slot,
171  op->dev.parent,
172  0);
173  err = -ENOMEM;
174  if (!p)
175  goto out_disable_irq;
176 
177  dev_set_drvdata(&op->dev, p);
178 
179  return 0;
180 
181 out_disable_irq:
182  ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
183  ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
184 
185 out_unmap_regs:
186  of_iounmap(&op->resource[2], sparc_ebus_dmas[slot].info.regs, d_len);
187 
188 out_clear_map:
189  clear_bit(slot, dma_slot_map);
190 
191 out_err:
192  return err;
193 }
194 
195 static int __devexit ecpp_remove(struct platform_device *op)
196 {
197  struct parport *p = dev_get_drvdata(&op->dev);
198  int slot = p->dma;
199 
201 
202  if (slot != PARPORT_DMA_NOFIFO) {
203  unsigned long d_base = op->resource[2].start;
204  unsigned long d_len;
205 
206  d_len = (op->resource[2].end - d_base) + 1UL;
207 
208  ebus_dma_irq_enable(&sparc_ebus_dmas[slot].info, 0);
209  ebus_dma_unregister(&sparc_ebus_dmas[slot].info);
210  of_iounmap(&op->resource[2],
211  sparc_ebus_dmas[slot].info.regs,
212  d_len);
213  clear_bit(slot, dma_slot_map);
214  }
215 
216  return 0;
217 }
218 
219 static const struct of_device_id ecpp_match[] = {
220  {
221  .name = "ecpp",
222  },
223  {
224  .name = "parallel",
225  .compatible = "ecpp",
226  },
227  {
228  .name = "parallel",
229  .compatible = "ns87317-ecpp",
230  },
231  {
232  .name = "parallel",
233  .compatible = "pnpALI,1533,3",
234  },
235  {},
236 };
237 
238 static struct platform_driver ecpp_driver = {
239  .driver = {
240  .name = "ecpp",
241  .owner = THIS_MODULE,
242  .of_match_table = ecpp_match,
243  },
244  .probe = ecpp_probe,
245  .remove = __devexit_p(ecpp_remove),
246 };
247 
248 static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
249 {
250  return platform_driver_register(&ecpp_driver);
251 }
252 
253 #endif /* !(_ASM_SPARC64_PARPORT_H */