diff options
Diffstat (limited to 'drivers/parport')
-rw-r--r-- | drivers/parport/Kconfig | 19 | ||||
-rw-r--r-- | drivers/parport/Makefile | 3 | ||||
-rw-r--r-- | drivers/parport/daisy.c | 2 | ||||
-rw-r--r-- | drivers/parport/parport_arc.c | 139 | ||||
-rw-r--r-- | drivers/parport/parport_ax88796.c | 443 | ||||
-rw-r--r-- | drivers/parport/parport_sunbpp.c | 134 | ||||
-rw-r--r-- | drivers/parport/share.c | 2 |
7 files changed, 530 insertions, 212 deletions
diff --git a/drivers/parport/Kconfig b/drivers/parport/Kconfig index f63c387976cf..c7fa28a28b9f 100644 --- a/drivers/parport/Kconfig +++ b/drivers/parport/Kconfig | |||
@@ -48,7 +48,7 @@ config PARPORT_PC | |||
48 | 48 | ||
49 | config PARPORT_SERIAL | 49 | config PARPORT_SERIAL |
50 | tristate "Multi-IO cards (parallel and serial)" | 50 | tristate "Multi-IO cards (parallel and serial)" |
51 | depends on SERIAL_8250 && PARPORT_PC && PCI | 51 | depends on SERIAL_8250_PCI && PARPORT_PC && PCI |
52 | help | 52 | help |
53 | This adds support for multi-IO PCI cards that have parallel and | 53 | This adds support for multi-IO PCI cards that have parallel and |
54 | serial ports. You should say Y or M here. If you say M, the module | 54 | serial ports. You should say Y or M here. If you say M, the module |
@@ -85,11 +85,6 @@ config PARPORT_PC_PCMCIA | |||
85 | config PARPORT_NOT_PC | 85 | config PARPORT_NOT_PC |
86 | bool | 86 | bool |
87 | 87 | ||
88 | config PARPORT_ARC | ||
89 | tristate "Archimedes hardware" | ||
90 | depends on ARM && PARPORT | ||
91 | select PARPORT_NOT_PC | ||
92 | |||
93 | config PARPORT_IP32 | 88 | config PARPORT_IP32 |
94 | tristate "SGI IP32 builtin port (EXPERIMENTAL)" | 89 | tristate "SGI IP32 builtin port (EXPERIMENTAL)" |
95 | depends on SGI_IP32 && PARPORT && EXPERIMENTAL | 90 | depends on SGI_IP32 && PARPORT && EXPERIMENTAL |
@@ -141,6 +136,18 @@ config PARPORT_SUNBPP | |||
141 | found on many Sun machines. Note that many of the newer Ultras | 136 | found on many Sun machines. Note that many of the newer Ultras |
142 | actually have pc style hardware instead. | 137 | actually have pc style hardware instead. |
143 | 138 | ||
139 | config PARPORT_AX88796 | ||
140 | tristate "AX88796 Parallel Port" | ||
141 | depends on PARPORT | ||
142 | select PARPORT_NOT_PC | ||
143 | help | ||
144 | Say Y here if you need support for the parallel port hardware on | ||
145 | the AX88796 network controller chip. This code is also available | ||
146 | as a module (say M), called parport_ax88796. | ||
147 | |||
148 | The driver is not dependant on the AX88796 network driver, and | ||
149 | should not interfere with the networking functions of the chip. | ||
150 | |||
144 | config PARPORT_1284 | 151 | config PARPORT_1284 |
145 | bool "IEEE 1284 transfer modes" | 152 | bool "IEEE 1284 transfer modes" |
146 | depends on PARPORT | 153 | depends on PARPORT |
diff --git a/drivers/parport/Makefile b/drivers/parport/Makefile index a19de35f8de2..696b8d4ca887 100644 --- a/drivers/parport/Makefile +++ b/drivers/parport/Makefile | |||
@@ -17,4 +17,5 @@ obj-$(CONFIG_PARPORT_MFC3) += parport_mfc3.o | |||
17 | obj-$(CONFIG_PARPORT_ATARI) += parport_atari.o | 17 | obj-$(CONFIG_PARPORT_ATARI) += parport_atari.o |
18 | obj-$(CONFIG_PARPORT_SUNBPP) += parport_sunbpp.o | 18 | obj-$(CONFIG_PARPORT_SUNBPP) += parport_sunbpp.o |
19 | obj-$(CONFIG_PARPORT_GSC) += parport_gsc.o | 19 | obj-$(CONFIG_PARPORT_GSC) += parport_gsc.o |
20 | obj-$(CONFIG_PARPORT_IP32) += parport_ip32.o | 20 | obj-$(CONFIG_PARPORT_AX88796) += parport_ax88796.o |
21 | obj-$(CONFIG_PARPORT_IP32) += parport_ip32.o \ No newline at end of file | ||
diff --git a/drivers/parport/daisy.c b/drivers/parport/daisy.c index 9ee67321b630..fd41e28101ea 100644 --- a/drivers/parport/daisy.c +++ b/drivers/parport/daisy.c | |||
@@ -283,7 +283,7 @@ void parport_close (struct pardevice *dev) | |||
283 | * | 283 | * |
284 | * This tries to locate a device on the given parallel port, | 284 | * This tries to locate a device on the given parallel port, |
285 | * multiplexor port and daisy chain address, and returns its | 285 | * multiplexor port and daisy chain address, and returns its |
286 | * device number or -NXIO if no device with those coordinates | 286 | * device number or %-ENXIO if no device with those coordinates |
287 | * exists. | 287 | * exists. |
288 | **/ | 288 | **/ |
289 | 289 | ||
diff --git a/drivers/parport/parport_arc.c b/drivers/parport/parport_arc.c deleted file mode 100644 index b35bb4f48d62..000000000000 --- a/drivers/parport/parport_arc.c +++ /dev/null | |||
@@ -1,139 +0,0 @@ | |||
1 | /* Low-level parallel port routines for Archimedes onboard hardware | ||
2 | * | ||
3 | * Author: Phil Blundell <philb@gnu.org> | ||
4 | */ | ||
5 | |||
6 | /* This driver is for the parallel port hardware found on Acorn's old | ||
7 | * range of Archimedes machines. The A5000 and newer systems have PC-style | ||
8 | * I/O hardware and should use the parport_pc driver instead. | ||
9 | * | ||
10 | * The Acorn printer port hardware is very simple. There is a single 8-bit | ||
11 | * write-only latch for the data port and control/status bits are handled | ||
12 | * with various auxilliary input and output lines. The port is not | ||
13 | * bidirectional, does not support any modes other than SPP, and has only | ||
14 | * a subset of the standard printer control lines connected. | ||
15 | */ | ||
16 | |||
17 | #include <linux/threads.h> | ||
18 | #include <linux/delay.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/interrupt.h> | ||
21 | #include <linux/ioport.h> | ||
22 | #include <linux/kernel.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/parport.h> | ||
25 | |||
26 | #include <asm/ptrace.h> | ||
27 | #include <asm/io.h> | ||
28 | #include <asm/arch/oldlatches.h> | ||
29 | #include <asm/arch/irqs.h> | ||
30 | |||
31 | #define DATA_ADDRESS 0x3350010 | ||
32 | |||
33 | /* This is equivalent to the above and only used for request_region. */ | ||
34 | #define PORT_BASE 0x80000000 | ((DATA_ADDRESS - IO_BASE) >> 2) | ||
35 | |||
36 | /* The hardware can't read from the data latch, so we must use a soft | ||
37 | copy. */ | ||
38 | static unsigned char data_copy; | ||
39 | |||
40 | /* These are pretty simple. We know the irq is never shared and the | ||
41 | kernel does all the magic that's required. */ | ||
42 | static void arc_enable_irq(struct parport *p) | ||
43 | { | ||
44 | enable_irq(p->irq); | ||
45 | } | ||
46 | |||
47 | static void arc_disable_irq(struct parport *p) | ||
48 | { | ||
49 | disable_irq(p->irq); | ||
50 | } | ||
51 | |||
52 | static void arc_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
53 | { | ||
54 | parport_generic_irq(irq, (struct parport *) dev_id, regs); | ||
55 | } | ||
56 | |||
57 | static void arc_write_data(struct parport *p, unsigned char data) | ||
58 | { | ||
59 | data_copy = data; | ||
60 | outb_t(data, DATA_LATCH); | ||
61 | } | ||
62 | |||
63 | static unsigned char arc_read_data(struct parport *p) | ||
64 | { | ||
65 | return data_copy; | ||
66 | } | ||
67 | |||
68 | static struct parport_operations parport_arc_ops = | ||
69 | { | ||
70 | .write_data = arc_write_data, | ||
71 | .read_data = arc_read_data, | ||
72 | |||
73 | .write_control = arc_write_control, | ||
74 | .read_control = arc_read_control, | ||
75 | .frob_control = arc_frob_control, | ||
76 | |||
77 | .read_status = arc_read_status, | ||
78 | |||
79 | .enable_irq = arc_enable_irq, | ||
80 | .disable_irq = arc_disable_irq, | ||
81 | |||
82 | .data_forward = arc_data_forward, | ||
83 | .data_reverse = arc_data_reverse, | ||
84 | |||
85 | .init_state = arc_init_state, | ||
86 | .save_state = arc_save_state, | ||
87 | .restore_state = arc_restore_state, | ||
88 | |||
89 | .epp_write_data = parport_ieee1284_epp_write_data, | ||
90 | .epp_read_data = parport_ieee1284_epp_read_data, | ||
91 | .epp_write_addr = parport_ieee1284_epp_write_addr, | ||
92 | .epp_read_addr = parport_ieee1284_epp_read_addr, | ||
93 | |||
94 | .ecp_write_data = parport_ieee1284_ecp_write_data, | ||
95 | .ecp_read_data = parport_ieee1284_ecp_read_data, | ||
96 | .ecp_write_addr = parport_ieee1284_ecp_write_addr, | ||
97 | |||
98 | .compat_write_data = parport_ieee1284_write_compat, | ||
99 | .nibble_read_data = parport_ieee1284_read_nibble, | ||
100 | .byte_read_data = parport_ieee1284_read_byte, | ||
101 | |||
102 | .owner = THIS_MODULE, | ||
103 | }; | ||
104 | |||
105 | /* --- Initialisation code -------------------------------- */ | ||
106 | |||
107 | static int parport_arc_init(void) | ||
108 | { | ||
109 | /* Archimedes hardware provides only one port, at a fixed address */ | ||
110 | struct parport *p; | ||
111 | struct resource res; | ||
112 | char *fake_name = "parport probe"); | ||
113 | |||
114 | res = request_region(PORT_BASE, 1, fake_name); | ||
115 | if (res == NULL) | ||
116 | return 0; | ||
117 | |||
118 | p = parport_register_port (PORT_BASE, IRQ_PRINTERACK, | ||
119 | PARPORT_DMA_NONE, &parport_arc_ops); | ||
120 | |||
121 | if (!p) { | ||
122 | release_region(PORT_BASE, 1); | ||
123 | return 0; | ||
124 | } | ||
125 | |||
126 | p->modes = PARPORT_MODE_ARCSPP; | ||
127 | p->size = 1; | ||
128 | rename_region(res, p->name); | ||
129 | |||
130 | printk(KERN_INFO "%s: Archimedes on-board port, using irq %d\n", | ||
131 | p->irq); | ||
132 | |||
133 | /* Tell the high-level drivers about the port. */ | ||
134 | parport_announce_port (p); | ||
135 | |||
136 | return 1; | ||
137 | } | ||
138 | |||
139 | module_init(parport_arc_init) | ||
diff --git a/drivers/parport/parport_ax88796.c b/drivers/parport/parport_ax88796.c new file mode 100644 index 000000000000..4baa719439a2 --- /dev/null +++ b/drivers/parport/parport_ax88796.c | |||
@@ -0,0 +1,443 @@ | |||
1 | /* linux/drivers/parport/parport_ax88796.c | ||
2 | * | ||
3 | * (c) 2005,2006 Simtec Electronics | ||
4 | * Ben Dooks <ben@simtec.co.uk> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | * | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/parport.h> | ||
15 | #include <linux/interrupt.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/platform_device.h> | ||
18 | |||
19 | #include <asm/io.h> | ||
20 | #include <asm/irq.h> | ||
21 | |||
22 | #define AX_SPR_BUSY (1<<7) | ||
23 | #define AX_SPR_ACK (1<<6) | ||
24 | #define AX_SPR_PE (1<<5) | ||
25 | #define AX_SPR_SLCT (1<<4) | ||
26 | #define AX_SPR_ERR (1<<3) | ||
27 | |||
28 | #define AX_CPR_nDOE (1<<5) | ||
29 | #define AX_CPR_SLCTIN (1<<3) | ||
30 | #define AX_CPR_nINIT (1<<2) | ||
31 | #define AX_CPR_ATFD (1<<1) | ||
32 | #define AX_CPR_STRB (1<<0) | ||
33 | |||
34 | struct ax_drvdata { | ||
35 | struct parport *parport; | ||
36 | struct parport_state suspend; | ||
37 | |||
38 | struct device *dev; | ||
39 | struct resource *io; | ||
40 | |||
41 | unsigned char irq_enabled; | ||
42 | |||
43 | void __iomem *base; | ||
44 | void __iomem *spp_data; | ||
45 | void __iomem *spp_spr; | ||
46 | void __iomem *spp_cpr; | ||
47 | }; | ||
48 | |||
49 | static inline struct ax_drvdata *pp_to_drv(struct parport *p) | ||
50 | { | ||
51 | return p->private_data; | ||
52 | } | ||
53 | |||
54 | static unsigned char | ||
55 | parport_ax88796_read_data(struct parport *p) | ||
56 | { | ||
57 | struct ax_drvdata *dd = pp_to_drv(p); | ||
58 | |||
59 | return readb(dd->spp_data); | ||
60 | } | ||
61 | |||
62 | static void | ||
63 | parport_ax88796_write_data(struct parport *p, unsigned char data) | ||
64 | { | ||
65 | struct ax_drvdata *dd = pp_to_drv(p); | ||
66 | |||
67 | writeb(data, dd->spp_data); | ||
68 | } | ||
69 | |||
70 | static unsigned char | ||
71 | parport_ax88796_read_control(struct parport *p) | ||
72 | { | ||
73 | struct ax_drvdata *dd = pp_to_drv(p); | ||
74 | unsigned int cpr = readb(dd->spp_cpr); | ||
75 | unsigned int ret = 0; | ||
76 | |||
77 | if (!(cpr & AX_CPR_STRB)) | ||
78 | ret |= PARPORT_CONTROL_STROBE; | ||
79 | |||
80 | if (!(cpr & AX_CPR_ATFD)) | ||
81 | ret |= PARPORT_CONTROL_AUTOFD; | ||
82 | |||
83 | if (cpr & AX_CPR_nINIT) | ||
84 | ret |= PARPORT_CONTROL_INIT; | ||
85 | |||
86 | if (!(cpr & AX_CPR_SLCTIN)) | ||
87 | ret |= PARPORT_CONTROL_SELECT; | ||
88 | |||
89 | return ret; | ||
90 | } | ||
91 | |||
92 | static void | ||
93 | parport_ax88796_write_control(struct parport *p, unsigned char control) | ||
94 | { | ||
95 | struct ax_drvdata *dd = pp_to_drv(p); | ||
96 | unsigned int cpr = readb(dd->spp_cpr); | ||
97 | |||
98 | cpr &= AX_CPR_nDOE; | ||
99 | |||
100 | if (!(control & PARPORT_CONTROL_STROBE)) | ||
101 | cpr |= AX_CPR_STRB; | ||
102 | |||
103 | if (!(control & PARPORT_CONTROL_AUTOFD)) | ||
104 | cpr |= AX_CPR_ATFD; | ||
105 | |||
106 | if (control & PARPORT_CONTROL_INIT) | ||
107 | cpr |= AX_CPR_nINIT; | ||
108 | |||
109 | if (!(control & PARPORT_CONTROL_SELECT)) | ||
110 | cpr |= AX_CPR_SLCTIN; | ||
111 | |||
112 | dev_dbg(dd->dev, "write_control: ctrl=%02x, cpr=%02x\n", control, cpr); | ||
113 | writeb(cpr, dd->spp_cpr); | ||
114 | |||
115 | if (parport_ax88796_read_control(p) != control) { | ||
116 | dev_err(dd->dev, "write_control: read != set (%02x, %02x)\n", | ||
117 | parport_ax88796_read_control(p), control); | ||
118 | } | ||
119 | } | ||
120 | |||
121 | static unsigned char | ||
122 | parport_ax88796_read_status(struct parport *p) | ||
123 | { | ||
124 | struct ax_drvdata *dd = pp_to_drv(p); | ||
125 | unsigned int status = readb(dd->spp_spr); | ||
126 | unsigned int ret = 0; | ||
127 | |||
128 | if (status & AX_SPR_BUSY) | ||
129 | ret |= PARPORT_STATUS_BUSY; | ||
130 | |||
131 | if (status & AX_SPR_ACK) | ||
132 | ret |= PARPORT_STATUS_ACK; | ||
133 | |||
134 | if (status & AX_SPR_ERR) | ||
135 | ret |= PARPORT_STATUS_ERROR; | ||
136 | |||
137 | if (status & AX_SPR_SLCT) | ||
138 | ret |= PARPORT_STATUS_SELECT; | ||
139 | |||
140 | if (status & AX_SPR_PE) | ||
141 | ret |= PARPORT_STATUS_PAPEROUT; | ||
142 | |||
143 | return ret; | ||
144 | } | ||
145 | |||
146 | static unsigned char | ||
147 | parport_ax88796_frob_control(struct parport *p, unsigned char mask, | ||
148 | unsigned char val) | ||
149 | { | ||
150 | struct ax_drvdata *dd = pp_to_drv(p); | ||
151 | unsigned char old = parport_ax88796_read_control(p); | ||
152 | |||
153 | dev_dbg(dd->dev, "frob: mask=%02x, val=%02x, old=%02x\n", | ||
154 | mask, val, old); | ||
155 | |||
156 | parport_ax88796_write_control(p, (old & ~mask) | val); | ||
157 | return old; | ||
158 | } | ||
159 | |||
160 | static void | ||
161 | parport_ax88796_enable_irq(struct parport *p) | ||
162 | { | ||
163 | struct ax_drvdata *dd = pp_to_drv(p); | ||
164 | unsigned long flags; | ||
165 | |||
166 | local_irq_save(flags); | ||
167 | if (!dd->irq_enabled) { | ||
168 | enable_irq(p->irq); | ||
169 | dd->irq_enabled = 1; | ||
170 | } | ||
171 | local_irq_restore(flags); | ||
172 | } | ||
173 | |||
174 | static void | ||
175 | parport_ax88796_disable_irq(struct parport *p) | ||
176 | { | ||
177 | struct ax_drvdata *dd = pp_to_drv(p); | ||
178 | unsigned long flags; | ||
179 | |||
180 | local_irq_save(flags); | ||
181 | if (dd->irq_enabled) { | ||
182 | disable_irq(p->irq); | ||
183 | dd->irq_enabled = 0; | ||
184 | } | ||
185 | local_irq_restore(flags); | ||
186 | } | ||
187 | |||
188 | static void | ||
189 | parport_ax88796_data_forward(struct parport *p) | ||
190 | { | ||
191 | struct ax_drvdata *dd = pp_to_drv(p); | ||
192 | void __iomem *cpr = dd->spp_cpr; | ||
193 | |||
194 | writeb((readb(cpr) & ~AX_CPR_nDOE), cpr); | ||
195 | } | ||
196 | |||
197 | static void | ||
198 | parport_ax88796_data_reverse(struct parport *p) | ||
199 | { | ||
200 | struct ax_drvdata *dd = pp_to_drv(p); | ||
201 | void __iomem *cpr = dd->spp_cpr; | ||
202 | |||
203 | writeb(readb(cpr) | AX_CPR_nDOE, cpr); | ||
204 | } | ||
205 | |||
206 | static void | ||
207 | parport_ax88796_init_state(struct pardevice *d, struct parport_state *s) | ||
208 | { | ||
209 | struct ax_drvdata *dd = pp_to_drv(d->port); | ||
210 | |||
211 | memset(s, 0, sizeof(struct parport_state)); | ||
212 | |||
213 | dev_dbg(dd->dev, "init_state: %p: state=%p\n", d, s); | ||
214 | s->u.ax88796.cpr = readb(dd->spp_cpr); | ||
215 | } | ||
216 | |||
217 | static void | ||
218 | parport_ax88796_save_state(struct parport *p, struct parport_state *s) | ||
219 | { | ||
220 | struct ax_drvdata *dd = pp_to_drv(p); | ||
221 | |||
222 | dev_dbg(dd->dev, "save_state: %p: state=%p\n", p, s); | ||
223 | s->u.ax88796.cpr = readb(dd->spp_cpr); | ||
224 | } | ||
225 | |||
226 | static void | ||
227 | parport_ax88796_restore_state(struct parport *p, struct parport_state *s) | ||
228 | { | ||
229 | struct ax_drvdata *dd = pp_to_drv(p); | ||
230 | |||
231 | dev_dbg(dd->dev, "restore_state: %p: state=%p\n", p, s); | ||
232 | writeb(s->u.ax88796.cpr, dd->spp_cpr); | ||
233 | } | ||
234 | |||
235 | static irqreturn_t | ||
236 | parport_ax88796_interrupt(int irq, void *dev_id, struct pt_regs *regs) | ||
237 | { | ||
238 | parport_generic_irq(irq, dev_id, regs); | ||
239 | return IRQ_HANDLED; | ||
240 | } | ||
241 | |||
242 | |||
243 | static struct parport_operations parport_ax88796_ops = { | ||
244 | .write_data = parport_ax88796_write_data, | ||
245 | .read_data = parport_ax88796_read_data, | ||
246 | |||
247 | .write_control = parport_ax88796_write_control, | ||
248 | .read_control = parport_ax88796_read_control, | ||
249 | .frob_control = parport_ax88796_frob_control, | ||
250 | |||
251 | .read_status = parport_ax88796_read_status, | ||
252 | |||
253 | .enable_irq = parport_ax88796_enable_irq, | ||
254 | .disable_irq = parport_ax88796_disable_irq, | ||
255 | |||
256 | .data_forward = parport_ax88796_data_forward, | ||
257 | .data_reverse = parport_ax88796_data_reverse, | ||
258 | |||
259 | .init_state = parport_ax88796_init_state, | ||
260 | .save_state = parport_ax88796_save_state, | ||
261 | .restore_state = parport_ax88796_restore_state, | ||
262 | |||
263 | .epp_write_data = parport_ieee1284_epp_write_data, | ||
264 | .epp_read_data = parport_ieee1284_epp_read_data, | ||
265 | .epp_write_addr = parport_ieee1284_epp_write_addr, | ||
266 | .epp_read_addr = parport_ieee1284_epp_read_addr, | ||
267 | |||
268 | .ecp_write_data = parport_ieee1284_ecp_write_data, | ||
269 | .ecp_read_data = parport_ieee1284_ecp_read_data, | ||
270 | .ecp_write_addr = parport_ieee1284_ecp_write_addr, | ||
271 | |||
272 | .compat_write_data = parport_ieee1284_write_compat, | ||
273 | .nibble_read_data = parport_ieee1284_read_nibble, | ||
274 | .byte_read_data = parport_ieee1284_read_byte, | ||
275 | |||
276 | .owner = THIS_MODULE, | ||
277 | }; | ||
278 | |||
279 | static int parport_ax88796_probe(struct platform_device *pdev) | ||
280 | { | ||
281 | struct device *_dev = &pdev->dev; | ||
282 | struct ax_drvdata *dd; | ||
283 | struct parport *pp = NULL; | ||
284 | struct resource *res; | ||
285 | unsigned long size; | ||
286 | int spacing; | ||
287 | int irq; | ||
288 | int ret; | ||
289 | |||
290 | dd = kzalloc(sizeof(struct ax_drvdata), GFP_KERNEL); | ||
291 | if (dd == NULL) { | ||
292 | dev_err(_dev, "no memory for private data\n"); | ||
293 | return -ENOMEM; | ||
294 | } | ||
295 | |||
296 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
297 | if (res == NULL) { | ||
298 | dev_err(_dev, "no MEM specified\n"); | ||
299 | ret = -ENXIO; | ||
300 | goto exit_mem; | ||
301 | } | ||
302 | |||
303 | size = (res->end - res->start) + 1; | ||
304 | spacing = size / 3; | ||
305 | |||
306 | dd->io = request_mem_region(res->start, size, pdev->name); | ||
307 | if (dd->io == NULL) { | ||
308 | dev_err(_dev, "cannot reserve memory\n"); | ||
309 | ret = -ENXIO; | ||
310 | goto exit_mem; | ||
311 | } | ||
312 | |||
313 | dd->base = ioremap(res->start, size); | ||
314 | if (dd->base == NULL) { | ||
315 | dev_err(_dev, "cannot ioremap region\n"); | ||
316 | ret = -ENXIO; | ||
317 | goto exit_res; | ||
318 | } | ||
319 | |||
320 | irq = platform_get_irq(pdev, 0); | ||
321 | if (irq <= 0) | ||
322 | irq = PARPORT_IRQ_NONE; | ||
323 | |||
324 | pp = parport_register_port((unsigned long)dd->base, irq, | ||
325 | PARPORT_DMA_NONE, | ||
326 | &parport_ax88796_ops); | ||
327 | |||
328 | if (pp == NULL) { | ||
329 | dev_err(_dev, "failed to register parallel port\n"); | ||
330 | ret = -ENOMEM; | ||
331 | goto exit_unmap; | ||
332 | } | ||
333 | |||
334 | pp->private_data = dd; | ||
335 | dd->parport = pp; | ||
336 | dd->dev = _dev; | ||
337 | |||
338 | dd->spp_data = dd->base; | ||
339 | dd->spp_spr = dd->base + (spacing * 1); | ||
340 | dd->spp_cpr = dd->base + (spacing * 2); | ||
341 | |||
342 | /* initialise the port controls */ | ||
343 | writeb(AX_CPR_STRB, dd->spp_cpr); | ||
344 | |||
345 | if (irq >= 0) { | ||
346 | /* request irq */ | ||
347 | ret = request_irq(irq, parport_ax88796_interrupt, | ||
348 | SA_TRIGGER_FALLING, pdev->name, pp); | ||
349 | |||
350 | if (ret < 0) | ||
351 | goto exit_port; | ||
352 | |||
353 | dd->irq_enabled = 1; | ||
354 | } | ||
355 | |||
356 | platform_set_drvdata(pdev, pp); | ||
357 | |||
358 | dev_info(_dev, "attached parallel port driver\n"); | ||
359 | parport_announce_port(pp); | ||
360 | |||
361 | return 0; | ||
362 | |||
363 | exit_port: | ||
364 | parport_remove_port(pp); | ||
365 | exit_unmap: | ||
366 | iounmap(dd->base); | ||
367 | exit_res: | ||
368 | release_resource(dd->io); | ||
369 | kfree(dd->io); | ||
370 | exit_mem: | ||
371 | kfree(dd); | ||
372 | return ret; | ||
373 | } | ||
374 | |||
375 | static int parport_ax88796_remove(struct platform_device *pdev) | ||
376 | { | ||
377 | struct parport *p = platform_get_drvdata(pdev); | ||
378 | struct ax_drvdata *dd = pp_to_drv(p); | ||
379 | |||
380 | free_irq(p->irq, p); | ||
381 | parport_remove_port(p); | ||
382 | iounmap(dd->base); | ||
383 | release_resource(dd->io); | ||
384 | kfree(dd->io); | ||
385 | kfree(dd); | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | #ifdef CONFIG_PM | ||
391 | |||
392 | static int parport_ax88796_suspend(struct platform_device *dev, | ||
393 | pm_message_t state) | ||
394 | { | ||
395 | struct parport *p = platform_get_drvdata(dev); | ||
396 | struct ax_drvdata *dd = pp_to_drv(p); | ||
397 | |||
398 | parport_ax88796_save_state(p, &dd->suspend); | ||
399 | writeb(AX_CPR_nDOE | AX_CPR_STRB, dd->spp_cpr); | ||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static int parport_ax88796_resume(struct platform_device *dev) | ||
404 | { | ||
405 | struct parport *p = platform_get_drvdata(dev); | ||
406 | struct ax_drvdata *dd = pp_to_drv(p); | ||
407 | |||
408 | parport_ax88796_restore_state(p, &dd->suspend); | ||
409 | return 0; | ||
410 | } | ||
411 | |||
412 | #else | ||
413 | #define parport_ax88796_suspend NULL | ||
414 | #define parport_ax88796_resume NULL | ||
415 | #endif | ||
416 | |||
417 | static struct platform_driver axdrv = { | ||
418 | .driver = { | ||
419 | .name = "ax88796-pp", | ||
420 | .owner = THIS_MODULE, | ||
421 | }, | ||
422 | .probe = parport_ax88796_probe, | ||
423 | .remove = parport_ax88796_remove, | ||
424 | .suspend = parport_ax88796_suspend, | ||
425 | .resume = parport_ax88796_resume, | ||
426 | }; | ||
427 | |||
428 | static int __init parport_ax88796_init(void) | ||
429 | { | ||
430 | return platform_driver_register(&axdrv); | ||
431 | } | ||
432 | |||
433 | static void __exit parport_ax88796_exit(void) | ||
434 | { | ||
435 | platform_driver_unregister(&axdrv); | ||
436 | } | ||
437 | |||
438 | module_init(parport_ax88796_init) | ||
439 | module_exit(parport_ax88796_exit) | ||
440 | |||
441 | MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>"); | ||
442 | MODULE_DESCRIPTION("AX88796 Parport parallel port driver"); | ||
443 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c index 36a1556e64c7..69a4bbd4cbee 100644 --- a/drivers/parport/parport_sunbpp.c +++ b/drivers/parport/parport_sunbpp.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* $Id: parport_sunbpp.c,v 1.12 2001/05/26 03:01:42 davem Exp $ | 1 | /* parport_sunbpp.c: Parallel-port routines for SBUS |
2 | * Parallel-port routines for Sun architecture | ||
3 | * | 2 | * |
4 | * Author: Derrick J. Brashear <shadow@dementia.org> | 3 | * Author: Derrick J. Brashear <shadow@dementia.org> |
5 | * | 4 | * |
@@ -14,6 +13,9 @@ | |||
14 | * Gus Baldauf (gbaldauf@ix.netcom.com) | 13 | * Gus Baldauf (gbaldauf@ix.netcom.com) |
15 | * Peter Zaitcev | 14 | * Peter Zaitcev |
16 | * Tom Dyas | 15 | * Tom Dyas |
16 | * | ||
17 | * Updated to new SBUS device framework: David S. Miller <davem@davemloft.net> | ||
18 | * | ||
17 | */ | 19 | */ |
18 | 20 | ||
19 | #include <linux/string.h> | 21 | #include <linux/string.h> |
@@ -287,14 +289,7 @@ static struct parport_operations parport_sunbpp_ops = | |||
287 | .owner = THIS_MODULE, | 289 | .owner = THIS_MODULE, |
288 | }; | 290 | }; |
289 | 291 | ||
290 | typedef struct { | 292 | static int __devinit init_one_port(struct sbus_dev *sdev) |
291 | struct list_head list; | ||
292 | struct parport *port; | ||
293 | } Node; | ||
294 | /* no locks, everything's serialized */ | ||
295 | static LIST_HEAD(port_list); | ||
296 | |||
297 | static int __init init_one_port(struct sbus_dev *sdev) | ||
298 | { | 293 | { |
299 | struct parport *p; | 294 | struct parport *p; |
300 | /* at least in theory there may be a "we don't dma" case */ | 295 | /* at least in theory there may be a "we don't dma" case */ |
@@ -303,109 +298,120 @@ static int __init init_one_port(struct sbus_dev *sdev) | |||
303 | int irq, dma, err = 0, size; | 298 | int irq, dma, err = 0, size; |
304 | struct bpp_regs __iomem *regs; | 299 | struct bpp_regs __iomem *regs; |
305 | unsigned char value_tcr; | 300 | unsigned char value_tcr; |
306 | Node *node; | ||
307 | |||
308 | dprintk((KERN_DEBUG "init_one_port(%p): ranges, alloc_io, ", sdev)); | ||
309 | node = kmalloc(sizeof(Node), GFP_KERNEL); | ||
310 | if (!node) | ||
311 | goto out0; | ||
312 | 301 | ||
313 | irq = sdev->irqs[0]; | 302 | irq = sdev->irqs[0]; |
314 | base = sbus_ioremap(&sdev->resource[0], 0, | 303 | base = sbus_ioremap(&sdev->resource[0], 0, |
315 | sdev->reg_addrs[0].reg_size, | 304 | sdev->reg_addrs[0].reg_size, |
316 | "sunbpp"); | 305 | "sunbpp"); |
317 | if (!base) | 306 | if (!base) |
318 | goto out1; | 307 | return -ENODEV; |
319 | 308 | ||
320 | size = sdev->reg_addrs[0].reg_size; | 309 | size = sdev->reg_addrs[0].reg_size; |
321 | dma = PARPORT_DMA_NONE; | 310 | dma = PARPORT_DMA_NONE; |
322 | 311 | ||
323 | dprintk(("alloc(ppops), ")); | 312 | ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL); |
324 | ops = kmalloc (sizeof (struct parport_operations), GFP_KERNEL); | ||
325 | if (!ops) | 313 | if (!ops) |
326 | goto out2; | 314 | goto out_unmap; |
327 | 315 | ||
328 | memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations)); | 316 | memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations)); |
329 | 317 | ||
330 | dprintk(("register_port\n")); | 318 | dprintk(("register_port\n")); |
331 | if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) | 319 | if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) |
332 | goto out3; | 320 | goto out_free_ops; |
333 | 321 | ||
334 | p->size = size; | 322 | p->size = size; |
335 | 323 | ||
336 | dprintk((KERN_DEBUG "init_one_port: request_irq(%08x:%p:%x:%s:%p) ", | ||
337 | p->irq, parport_sunbpp_interrupt, SA_SHIRQ, p->name, p)); | ||
338 | if ((err = request_irq(p->irq, parport_sunbpp_interrupt, | 324 | if ((err = request_irq(p->irq, parport_sunbpp_interrupt, |
339 | SA_SHIRQ, p->name, p)) != 0) { | 325 | SA_SHIRQ, p->name, p)) != 0) { |
340 | dprintk(("ERROR %d\n", err)); | 326 | goto out_put_port; |
341 | goto out4; | ||
342 | } | 327 | } |
343 | dprintk(("OK\n")); | 328 | |
344 | parport_sunbpp_enable_irq(p); | 329 | parport_sunbpp_enable_irq(p); |
345 | 330 | ||
346 | regs = (struct bpp_regs __iomem *)p->base; | 331 | regs = (struct bpp_regs __iomem *)p->base; |
347 | dprintk((KERN_DEBUG "forward\n")); | 332 | |
348 | value_tcr = sbus_readb(®s->p_tcr); | 333 | value_tcr = sbus_readb(®s->p_tcr); |
349 | value_tcr &= ~P_TCR_DIR; | 334 | value_tcr &= ~P_TCR_DIR; |
350 | sbus_writeb(value_tcr, ®s->p_tcr); | 335 | sbus_writeb(value_tcr, ®s->p_tcr); |
351 | 336 | ||
352 | printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base); | 337 | printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base); |
353 | node->port = p; | ||
354 | list_add(&node->list, &port_list); | ||
355 | parport_announce_port (p); | ||
356 | 338 | ||
357 | return 1; | 339 | dev_set_drvdata(&sdev->ofdev.dev, p); |
340 | |||
341 | parport_announce_port(p); | ||
342 | |||
343 | return 0; | ||
358 | 344 | ||
359 | out4: | 345 | out_put_port: |
360 | parport_put_port(p); | 346 | parport_put_port(p); |
361 | out3: | 347 | |
348 | out_free_ops: | ||
362 | kfree(ops); | 349 | kfree(ops); |
363 | out2: | 350 | |
351 | out_unmap: | ||
364 | sbus_iounmap(base, size); | 352 | sbus_iounmap(base, size); |
365 | out1: | 353 | |
366 | kfree(node); | ||
367 | out0: | ||
368 | return err; | 354 | return err; |
369 | } | 355 | } |
370 | 356 | ||
371 | static int __init parport_sunbpp_init(void) | 357 | static int __devinit bpp_probe(struct of_device *dev, const struct of_device_id *match) |
372 | { | 358 | { |
373 | struct sbus_bus *sbus; | 359 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); |
374 | struct sbus_dev *sdev; | 360 | |
375 | int count = 0; | 361 | return init_one_port(sdev); |
376 | 362 | } | |
377 | for_each_sbus(sbus) { | 363 | |
378 | for_each_sbusdev(sdev, sbus) { | 364 | static int __devexit bpp_remove(struct of_device *dev) |
379 | if (!strcmp(sdev->prom_name, "SUNW,bpp")) | 365 | { |
380 | count += init_one_port(sdev); | 366 | struct parport *p = dev_get_drvdata(&dev->dev); |
381 | } | 367 | struct parport_operations *ops = p->ops; |
368 | |||
369 | parport_remove_port(p); | ||
370 | |||
371 | if (p->irq != PARPORT_IRQ_NONE) { | ||
372 | parport_sunbpp_disable_irq(p); | ||
373 | free_irq(p->irq, p); | ||
382 | } | 374 | } |
383 | return count ? 0 : -ENODEV; | 375 | |
376 | sbus_iounmap((void __iomem *) p->base, p->size); | ||
377 | parport_put_port(p); | ||
378 | kfree(ops); | ||
379 | |||
380 | dev_set_drvdata(&dev->dev, NULL); | ||
381 | |||
382 | return 0; | ||
383 | } | ||
384 | |||
385 | static struct of_device_id bpp_match[] = { | ||
386 | { | ||
387 | .name = "SUNW,bpp", | ||
388 | }, | ||
389 | {}, | ||
390 | }; | ||
391 | |||
392 | MODULE_DEVICE_TABLE(of, qec_sbus_match); | ||
393 | |||
394 | static struct of_platform_driver bpp_sbus_driver = { | ||
395 | .name = "bpp", | ||
396 | .match_table = bpp_match, | ||
397 | .probe = bpp_probe, | ||
398 | .remove = __devexit_p(bpp_remove), | ||
399 | }; | ||
400 | |||
401 | static int __init parport_sunbpp_init(void) | ||
402 | { | ||
403 | return of_register_driver(&bpp_sbus_driver, &sbus_bus_type); | ||
384 | } | 404 | } |
385 | 405 | ||
386 | static void __exit parport_sunbpp_exit(void) | 406 | static void __exit parport_sunbpp_exit(void) |
387 | { | 407 | { |
388 | while (!list_empty(&port_list)) { | 408 | of_unregister_driver(&bpp_sbus_driver); |
389 | Node *node = list_entry(port_list.next, Node, list); | ||
390 | struct parport *p = node->port; | ||
391 | struct parport_operations *ops = p->ops; | ||
392 | parport_remove_port(p); | ||
393 | |||
394 | if (p->irq != PARPORT_IRQ_NONE) { | ||
395 | parport_sunbpp_disable_irq(p); | ||
396 | free_irq(p->irq, p); | ||
397 | } | ||
398 | sbus_iounmap((void __iomem *)p->base, p->size); | ||
399 | parport_put_port(p); | ||
400 | kfree (ops); | ||
401 | list_del(&node->list); | ||
402 | kfree (node); | ||
403 | } | ||
404 | } | 409 | } |
405 | 410 | ||
406 | MODULE_AUTHOR("Derrick J Brashear"); | 411 | MODULE_AUTHOR("Derrick J Brashear"); |
407 | MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port"); | 412 | MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port"); |
408 | MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port"); | 413 | MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port"); |
414 | MODULE_VERSION("2.0"); | ||
409 | MODULE_LICENSE("GPL"); | 415 | MODULE_LICENSE("GPL"); |
410 | 416 | ||
411 | module_init(parport_sunbpp_init) | 417 | module_init(parport_sunbpp_init) |
diff --git a/drivers/parport/share.c b/drivers/parport/share.c index bbbfd79adbaf..2cb22c8d3357 100644 --- a/drivers/parport/share.c +++ b/drivers/parport/share.c | |||
@@ -218,7 +218,7 @@ static void free_port (struct parport *port) | |||
218 | * parport_get_port - increment a port's reference count | 218 | * parport_get_port - increment a port's reference count |
219 | * @port: the port | 219 | * @port: the port |
220 | * | 220 | * |
221 | * This ensure's that a struct parport pointer remains valid | 221 | * This ensures that a struct parport pointer remains valid |
222 | * until the matching parport_put_port() call. | 222 | * until the matching parport_put_port() call. |
223 | **/ | 223 | **/ |
224 | 224 | ||