Root/
1 | /* Low-level parallel port routines for the Amiga built-in port |
2 | * |
3 | * Author: Joerg Dorchain <joerg@dorchain.net> |
4 | * |
5 | * This is a complete rewrite of the code, but based heaviy upon the old |
6 | * lp_intern. code. |
7 | * |
8 | * The built-in Amiga parallel port provides one port at a fixed address |
9 | * with 8 bidirectional data lines (D0 - D7) and 3 bidirectional status |
10 | * lines (BUSY, POUT, SEL), 1 output control line /STROBE (raised automatically |
11 | * in hardware when the data register is accessed), and 1 input control line |
12 | * /ACK, able to cause an interrupt, but both not directly settable by |
13 | * software. |
14 | */ |
15 | |
16 | #include <linux/module.h> |
17 | #include <linux/init.h> |
18 | #include <linux/parport.h> |
19 | #include <linux/ioport.h> |
20 | #include <linux/interrupt.h> |
21 | #include <linux/platform_device.h> |
22 | |
23 | #include <asm/setup.h> |
24 | #include <asm/amigahw.h> |
25 | #include <asm/irq.h> |
26 | #include <asm/io.h> |
27 | #include <asm/amigaints.h> |
28 | |
29 | #undef DEBUG |
30 | #ifdef DEBUG |
31 | #define DPRINTK printk |
32 | #else |
33 | #define DPRINTK(x...) do { } while (0) |
34 | #endif |
35 | |
36 | |
37 | static void amiga_write_data(struct parport *p, unsigned char data) |
38 | { |
39 | DPRINTK(KERN_DEBUG "write_data %c\n",data); |
40 | /* Triggers also /STROBE. This behavior cannot be changed */ |
41 | ciaa.prb = data; |
42 | mb(); |
43 | } |
44 | |
45 | static unsigned char amiga_read_data(struct parport *p) |
46 | { |
47 | /* Triggers also /STROBE. This behavior cannot be changed */ |
48 | return ciaa.prb; |
49 | } |
50 | |
51 | static unsigned char control_amiga_to_pc(unsigned char control) |
52 | { |
53 | return PARPORT_CONTROL_SELECT | |
54 | PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_STROBE; |
55 | /* fake value: interrupt enable, select in, no reset, |
56 | no autolf, no strobe - seems to be closest the wiring diagram */ |
57 | } |
58 | |
59 | static void amiga_write_control(struct parport *p, unsigned char control) |
60 | { |
61 | DPRINTK(KERN_DEBUG "write_control %02x\n",control); |
62 | /* No implementation possible */ |
63 | } |
64 | |
65 | static unsigned char amiga_read_control( struct parport *p) |
66 | { |
67 | DPRINTK(KERN_DEBUG "read_control \n"); |
68 | return control_amiga_to_pc(0); |
69 | } |
70 | |
71 | static unsigned char amiga_frob_control( struct parport *p, unsigned char mask, unsigned char val) |
72 | { |
73 | unsigned char old; |
74 | |
75 | DPRINTK(KERN_DEBUG "frob_control mask %02x, value %02x\n",mask,val); |
76 | old = amiga_read_control(p); |
77 | amiga_write_control(p, (old & ~mask) ^ val); |
78 | return old; |
79 | } |
80 | |
81 | static unsigned char status_amiga_to_pc(unsigned char status) |
82 | { |
83 | unsigned char ret = PARPORT_STATUS_BUSY | PARPORT_STATUS_ACK | PARPORT_STATUS_ERROR; |
84 | |
85 | if (status & 1) /* Busy */ |
86 | ret &= ~PARPORT_STATUS_BUSY; |
87 | if (status & 2) /* PaperOut */ |
88 | ret |= PARPORT_STATUS_PAPEROUT; |
89 | if (status & 4) /* Selected */ |
90 | ret |= PARPORT_STATUS_SELECT; |
91 | /* the rest is not connected or handled autonomously in hardware */ |
92 | |
93 | return ret; |
94 | } |
95 | |
96 | static unsigned char amiga_read_status(struct parport *p) |
97 | { |
98 | unsigned char status; |
99 | |
100 | status = status_amiga_to_pc(ciab.pra & 7); |
101 | DPRINTK(KERN_DEBUG "read_status %02x\n", status); |
102 | return status; |
103 | } |
104 | |
105 | static void amiga_enable_irq(struct parport *p) |
106 | { |
107 | enable_irq(IRQ_AMIGA_CIAA_FLG); |
108 | } |
109 | |
110 | static void amiga_disable_irq(struct parport *p) |
111 | { |
112 | disable_irq(IRQ_AMIGA_CIAA_FLG); |
113 | } |
114 | |
115 | static void amiga_data_forward(struct parport *p) |
116 | { |
117 | DPRINTK(KERN_DEBUG "forward\n"); |
118 | ciaa.ddrb = 0xff; /* all pins output */ |
119 | mb(); |
120 | } |
121 | |
122 | static void amiga_data_reverse(struct parport *p) |
123 | { |
124 | DPRINTK(KERN_DEBUG "reverse\n"); |
125 | ciaa.ddrb = 0; /* all pins input */ |
126 | mb(); |
127 | } |
128 | |
129 | static void amiga_init_state(struct pardevice *dev, struct parport_state *s) |
130 | { |
131 | s->u.amiga.data = 0; |
132 | s->u.amiga.datadir = 255; |
133 | s->u.amiga.status = 0; |
134 | s->u.amiga.statusdir = 0; |
135 | } |
136 | |
137 | static void amiga_save_state(struct parport *p, struct parport_state *s) |
138 | { |
139 | mb(); |
140 | s->u.amiga.data = ciaa.prb; |
141 | s->u.amiga.datadir = ciaa.ddrb; |
142 | s->u.amiga.status = ciab.pra & 7; |
143 | s->u.amiga.statusdir = ciab.ddra & 7; |
144 | mb(); |
145 | } |
146 | |
147 | static void amiga_restore_state(struct parport *p, struct parport_state *s) |
148 | { |
149 | mb(); |
150 | ciaa.prb = s->u.amiga.data; |
151 | ciaa.ddrb = s->u.amiga.datadir; |
152 | ciab.pra |= (ciab.pra & 0xf8) | s->u.amiga.status; |
153 | ciab.ddra |= (ciab.ddra & 0xf8) | s->u.amiga.statusdir; |
154 | mb(); |
155 | } |
156 | |
157 | static struct parport_operations pp_amiga_ops = { |
158 | .write_data = amiga_write_data, |
159 | .read_data = amiga_read_data, |
160 | |
161 | .write_control = amiga_write_control, |
162 | .read_control = amiga_read_control, |
163 | .frob_control = amiga_frob_control, |
164 | |
165 | .read_status = amiga_read_status, |
166 | |
167 | .enable_irq = amiga_enable_irq, |
168 | .disable_irq = amiga_disable_irq, |
169 | |
170 | .data_forward = amiga_data_forward, |
171 | .data_reverse = amiga_data_reverse, |
172 | |
173 | .init_state = amiga_init_state, |
174 | .save_state = amiga_save_state, |
175 | .restore_state = amiga_restore_state, |
176 | |
177 | .epp_write_data = parport_ieee1284_epp_write_data, |
178 | .epp_read_data = parport_ieee1284_epp_read_data, |
179 | .epp_write_addr = parport_ieee1284_epp_write_addr, |
180 | .epp_read_addr = parport_ieee1284_epp_read_addr, |
181 | |
182 | .ecp_write_data = parport_ieee1284_ecp_write_data, |
183 | .ecp_read_data = parport_ieee1284_ecp_read_data, |
184 | .ecp_write_addr = parport_ieee1284_ecp_write_addr, |
185 | |
186 | .compat_write_data = parport_ieee1284_write_compat, |
187 | .nibble_read_data = parport_ieee1284_read_nibble, |
188 | .byte_read_data = parport_ieee1284_read_byte, |
189 | |
190 | .owner = THIS_MODULE, |
191 | }; |
192 | |
193 | /* ----------- Initialisation code --------------------------------- */ |
194 | |
195 | static int __init amiga_parallel_probe(struct platform_device *pdev) |
196 | { |
197 | struct parport *p; |
198 | int err; |
199 | |
200 | ciaa.ddrb = 0xff; |
201 | ciab.ddra &= 0xf8; |
202 | mb(); |
203 | |
204 | p = parport_register_port((unsigned long)&ciaa.prb, IRQ_AMIGA_CIAA_FLG, |
205 | PARPORT_DMA_NONE, &pp_amiga_ops); |
206 | if (!p) |
207 | return -EBUSY; |
208 | |
209 | err = request_irq(IRQ_AMIGA_CIAA_FLG, parport_irq_handler, 0, p->name, |
210 | p); |
211 | if (err) |
212 | goto out_irq; |
213 | |
214 | printk(KERN_INFO "%s: Amiga built-in port using irq\n", p->name); |
215 | /* XXX: set operating mode */ |
216 | parport_announce_port(p); |
217 | |
218 | platform_set_drvdata(pdev, p); |
219 | |
220 | return 0; |
221 | |
222 | out_irq: |
223 | parport_put_port(p); |
224 | return err; |
225 | } |
226 | |
227 | static int __exit amiga_parallel_remove(struct platform_device *pdev) |
228 | { |
229 | struct parport *port = platform_get_drvdata(pdev); |
230 | |
231 | parport_remove_port(port); |
232 | if (port->irq != PARPORT_IRQ_NONE) |
233 | free_irq(IRQ_AMIGA_CIAA_FLG, port); |
234 | parport_put_port(port); |
235 | platform_set_drvdata(pdev, NULL); |
236 | return 0; |
237 | } |
238 | |
239 | static struct platform_driver amiga_parallel_driver = { |
240 | .remove = __exit_p(amiga_parallel_remove), |
241 | .driver = { |
242 | .name = "amiga-parallel", |
243 | .owner = THIS_MODULE, |
244 | }, |
245 | }; |
246 | |
247 | static int __init amiga_parallel_init(void) |
248 | { |
249 | return platform_driver_probe(&amiga_parallel_driver, |
250 | amiga_parallel_probe); |
251 | } |
252 | |
253 | module_init(amiga_parallel_init); |
254 | |
255 | static void __exit amiga_parallel_exit(void) |
256 | { |
257 | platform_driver_unregister(&amiga_parallel_driver); |
258 | } |
259 | |
260 | module_exit(amiga_parallel_exit); |
261 | |
262 | MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>"); |
263 | MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port"); |
264 | MODULE_SUPPORTED_DEVICE("Amiga builtin Parallel Port"); |
265 | MODULE_LICENSE("GPL"); |
266 | MODULE_ALIAS("platform:amiga-parallel"); |
267 |
Branches:
ben-wpan
ben-wpan-stefan
javiroman/ks7010
jz-2.6.34
jz-2.6.34-rc5
jz-2.6.34-rc6
jz-2.6.34-rc7
jz-2.6.35
jz-2.6.36
jz-2.6.37
jz-2.6.38
jz-2.6.39
jz-3.0
jz-3.1
jz-3.11
jz-3.12
jz-3.13
jz-3.15
jz-3.16
jz-3.18-dt
jz-3.2
jz-3.3
jz-3.4
jz-3.5
jz-3.6
jz-3.6-rc2-pwm
jz-3.9
jz-3.9-clk
jz-3.9-rc8
jz47xx
jz47xx-2.6.38
master
Tags:
od-2011-09-04
od-2011-09-18
v2.6.34-rc5
v2.6.34-rc6
v2.6.34-rc7
v3.9