1 /* $Id: parport_sunbpp.c,v 1.12 2001/05/26 03:01:42 davem Exp $
2 * Parallel-port routines for Sun architecture
4 * Author: Derrick J. Brashear <shadow@dementia.org>
7 * Phil Blundell <philb@gnu.org>
8 * Tim Waugh <tim@cyberelk.demon.co.uk>
9 * Jose Renau <renau@acm.org>
10 * David Campbell <campbell@tirian.che.curtin.edu.au>
11 * Grant Guenther <grant@torque.net>
12 * Eddie C. Dost <ecd@skynet.be>
13 * Stephen Williams (steve@icarus.com)
14 * Gus Baldauf (gbaldauf@ix.netcom.com)
19 #include <linux/string.h>
20 #include <linux/module.h>
21 #include <linux/delay.h>
22 #include <linux/errno.h>
23 #include <linux/ioport.h>
24 #include <linux/kernel.h>
25 #include <linux/slab.h>
26 #include <linux/init.h>
28 #include <linux/parport.h>
30 #include <asm/ptrace.h>
31 #include <linux/interrupt.h>
34 #include <asm/oplib.h> /* OpenProm Library */
36 #include <asm/dma.h> /* BPP uses LSI 64854 for DMA */
38 #include <asm/sunbpp.h>
42 #define dprintk(x) printk x
47 static irqreturn_t
parport_sunbpp_interrupt(int irq
, void *dev_id
, struct pt_regs
*regs
)
49 parport_generic_irq(irq
, (struct parport
*) dev_id
, regs
);
53 static void parport_sunbpp_disable_irq(struct parport
*p
)
55 struct bpp_regs __iomem
*regs
= (struct bpp_regs __iomem
*)p
->base
;
58 tmp
= sbus_readl(®s
->p_csr
);
60 sbus_writel(tmp
, ®s
->p_csr
);
63 static void parport_sunbpp_enable_irq(struct parport
*p
)
65 struct bpp_regs __iomem
*regs
= (struct bpp_regs __iomem
*)p
->base
;
68 tmp
= sbus_readl(®s
->p_csr
);
70 sbus_writel(tmp
, ®s
->p_csr
);
73 static void parport_sunbpp_write_data(struct parport
*p
, unsigned char d
)
75 struct bpp_regs __iomem
*regs
= (struct bpp_regs __iomem
*)p
->base
;
77 sbus_writeb(d
, ®s
->p_dr
);
78 dprintk((KERN_DEBUG
"wrote 0x%x\n", d
));
81 static unsigned char parport_sunbpp_read_data(struct parport
*p
)
83 struct bpp_regs __iomem
*regs
= (struct bpp_regs __iomem
*)p
->base
;
85 return sbus_readb(®s
->p_dr
);
89 static void control_pc_to_sunbpp(struct parport
*p
, unsigned char status
)
91 struct bpp_regs __iomem
*regs
= (struct bpp_regs __iomem
*)p
->base
;
92 unsigned char value_tcr
= sbus_readb(®s
->p_tcr
);
93 unsigned char value_or
= sbus_readb(®s
->p_or
);
95 if (status
& PARPORT_CONTROL_STROBE
)
96 value_tcr
|= P_TCR_DS
;
97 if (status
& PARPORT_CONTROL_AUTOFD
)
98 value_or
|= P_OR_AFXN
;
99 if (status
& PARPORT_CONTROL_INIT
)
100 value_or
|= P_OR_INIT
;
101 if (status
& PARPORT_CONTROL_SELECT
)
102 value_or
|= P_OR_SLCT_IN
;
104 sbus_writeb(value_or
, ®s
->p_or
);
105 sbus_writeb(value_tcr
, ®s
->p_tcr
);
109 static unsigned char status_sunbpp_to_pc(struct parport
*p
)
111 struct bpp_regs __iomem
*regs
= (struct bpp_regs __iomem
*)p
->base
;
112 unsigned char bits
= 0;
113 unsigned char value_tcr
= sbus_readb(®s
->p_tcr
);
114 unsigned char value_ir
= sbus_readb(®s
->p_ir
);
116 if (!(value_ir
& P_IR_ERR
))
117 bits
|= PARPORT_STATUS_ERROR
;
118 if (!(value_ir
& P_IR_SLCT
))
119 bits
|= PARPORT_STATUS_SELECT
;
120 if (!(value_ir
& P_IR_PE
))
121 bits
|= PARPORT_STATUS_PAPEROUT
;
122 if (value_tcr
& P_TCR_ACK
)
123 bits
|= PARPORT_STATUS_ACK
;
124 if (!(value_tcr
& P_TCR_BUSY
))
125 bits
|= PARPORT_STATUS_BUSY
;
127 dprintk((KERN_DEBUG
"tcr 0x%x ir 0x%x\n", regs
->p_tcr
, regs
->p_ir
));
128 dprintk((KERN_DEBUG
"read status 0x%x\n", bits
));
132 static unsigned char control_sunbpp_to_pc(struct parport
*p
)
134 struct bpp_regs __iomem
*regs
= (struct bpp_regs __iomem
*)p
->base
;
135 unsigned char bits
= 0;
136 unsigned char value_tcr
= sbus_readb(®s
->p_tcr
);
137 unsigned char value_or
= sbus_readb(®s
->p_or
);
139 if (!(value_tcr
& P_TCR_DS
))
140 bits
|= PARPORT_CONTROL_STROBE
;
141 if (!(value_or
& P_OR_AFXN
))
142 bits
|= PARPORT_CONTROL_AUTOFD
;
143 if (!(value_or
& P_OR_INIT
))
144 bits
|= PARPORT_CONTROL_INIT
;
145 if (value_or
& P_OR_SLCT_IN
)
146 bits
|= PARPORT_CONTROL_SELECT
;
148 dprintk((KERN_DEBUG
"tcr 0x%x or 0x%x\n", regs
->p_tcr
, regs
->p_or
));
149 dprintk((KERN_DEBUG
"read control 0x%x\n", bits
));
153 static unsigned char parport_sunbpp_read_control(struct parport
*p
)
155 return control_sunbpp_to_pc(p
);
158 static unsigned char parport_sunbpp_frob_control(struct parport
*p
,
162 struct bpp_regs __iomem
*regs
= (struct bpp_regs __iomem
*)p
->base
;
163 unsigned char value_tcr
= sbus_readb(®s
->p_tcr
);
164 unsigned char value_or
= sbus_readb(®s
->p_or
);
166 dprintk((KERN_DEBUG
"frob1: tcr 0x%x or 0x%x\n", regs
->p_tcr
, regs
->p_or
));
167 if (mask
& PARPORT_CONTROL_STROBE
) {
168 if (val
& PARPORT_CONTROL_STROBE
) {
169 value_tcr
&= ~P_TCR_DS
;
171 value_tcr
|= P_TCR_DS
;
174 if (mask
& PARPORT_CONTROL_AUTOFD
) {
175 if (val
& PARPORT_CONTROL_AUTOFD
) {
176 value_or
&= ~P_OR_AFXN
;
178 value_or
|= P_OR_AFXN
;
181 if (mask
& PARPORT_CONTROL_INIT
) {
182 if (val
& PARPORT_CONTROL_INIT
) {
183 value_or
&= ~P_OR_INIT
;
185 value_or
|= P_OR_INIT
;
188 if (mask
& PARPORT_CONTROL_SELECT
) {
189 if (val
& PARPORT_CONTROL_SELECT
) {
190 value_or
|= P_OR_SLCT_IN
;
192 value_or
&= ~P_OR_SLCT_IN
;
196 sbus_writeb(value_or
, ®s
->p_or
);
197 sbus_writeb(value_tcr
, ®s
->p_tcr
);
198 dprintk((KERN_DEBUG
"frob2: tcr 0x%x or 0x%x\n", regs
->p_tcr
, regs
->p_or
));
199 return parport_sunbpp_read_control(p
);
202 static void parport_sunbpp_write_control(struct parport
*p
, unsigned char d
)
204 const unsigned char wm
= (PARPORT_CONTROL_STROBE
|
205 PARPORT_CONTROL_AUTOFD
|
206 PARPORT_CONTROL_INIT
|
207 PARPORT_CONTROL_SELECT
);
209 parport_sunbpp_frob_control (p
, wm
, d
& wm
);
212 static unsigned char parport_sunbpp_read_status(struct parport
*p
)
214 return status_sunbpp_to_pc(p
);
217 static void parport_sunbpp_data_forward (struct parport
*p
)
219 struct bpp_regs __iomem
*regs
= (struct bpp_regs __iomem
*)p
->base
;
220 unsigned char value_tcr
= sbus_readb(®s
->p_tcr
);
222 dprintk((KERN_DEBUG
"forward\n"));
223 value_tcr
&= ~P_TCR_DIR
;
224 sbus_writeb(value_tcr
, ®s
->p_tcr
);
227 static void parport_sunbpp_data_reverse (struct parport
*p
)
229 struct bpp_regs __iomem
*regs
= (struct bpp_regs __iomem
*)p
->base
;
230 u8 val
= sbus_readb(®s
->p_tcr
);
232 dprintk((KERN_DEBUG
"reverse\n"));
234 sbus_writeb(val
, ®s
->p_tcr
);
237 static void parport_sunbpp_init_state(struct pardevice
*dev
, struct parport_state
*s
)
243 static void parport_sunbpp_save_state(struct parport
*p
, struct parport_state
*s
)
245 s
->u
.pc
.ctr
= parport_sunbpp_read_control(p
);
248 static void parport_sunbpp_restore_state(struct parport
*p
, struct parport_state
*s
)
250 parport_sunbpp_write_control(p
, s
->u
.pc
.ctr
);
253 static struct parport_operations parport_sunbpp_ops
=
255 .write_data
= parport_sunbpp_write_data
,
256 .read_data
= parport_sunbpp_read_data
,
258 .write_control
= parport_sunbpp_write_control
,
259 .read_control
= parport_sunbpp_read_control
,
260 .frob_control
= parport_sunbpp_frob_control
,
262 .read_status
= parport_sunbpp_read_status
,
264 .enable_irq
= parport_sunbpp_enable_irq
,
265 .disable_irq
= parport_sunbpp_disable_irq
,
267 .data_forward
= parport_sunbpp_data_forward
,
268 .data_reverse
= parport_sunbpp_data_reverse
,
270 .init_state
= parport_sunbpp_init_state
,
271 .save_state
= parport_sunbpp_save_state
,
272 .restore_state
= parport_sunbpp_restore_state
,
274 .epp_write_data
= parport_ieee1284_epp_write_data
,
275 .epp_read_data
= parport_ieee1284_epp_read_data
,
276 .epp_write_addr
= parport_ieee1284_epp_write_addr
,
277 .epp_read_addr
= parport_ieee1284_epp_read_addr
,
279 .ecp_write_data
= parport_ieee1284_ecp_write_data
,
280 .ecp_read_data
= parport_ieee1284_ecp_read_data
,
281 .ecp_write_addr
= parport_ieee1284_ecp_write_addr
,
283 .compat_write_data
= parport_ieee1284_write_compat
,
284 .nibble_read_data
= parport_ieee1284_read_nibble
,
285 .byte_read_data
= parport_ieee1284_read_byte
,
287 .owner
= THIS_MODULE
,
291 struct list_head list
;
292 struct parport
*port
;
294 /* no locks, everything's serialized */
295 static LIST_HEAD(port_list
);
297 static int __init
init_one_port(struct sbus_dev
*sdev
)
300 /* at least in theory there may be a "we don't dma" case */
301 struct parport_operations
*ops
;
303 int irq
, dma
, err
= 0, size
;
304 struct bpp_regs __iomem
*regs
;
305 unsigned char value_tcr
;
308 dprintk((KERN_DEBUG
"init_one_port(%p): ranges, alloc_io, ", sdev
));
309 node
= kmalloc(sizeof(Node
), GFP_KERNEL
);
314 base
= sbus_ioremap(&sdev
->resource
[0], 0,
315 sdev
->reg_addrs
[0].reg_size
,
320 size
= sdev
->reg_addrs
[0].reg_size
;
321 dma
= PARPORT_DMA_NONE
;
323 dprintk(("alloc(ppops), "));
324 ops
= kmalloc (sizeof (struct parport_operations
), GFP_KERNEL
);
328 memcpy (ops
, &parport_sunbpp_ops
, sizeof (struct parport_operations
));
330 dprintk(("register_port\n"));
331 if (!(p
= parport_register_port((unsigned long)base
, irq
, dma
, ops
)))
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
,
339 SA_SHIRQ
, p
->name
, p
)) != 0) {
340 dprintk(("ERROR %d\n", err
));
344 parport_sunbpp_enable_irq(p
);
346 regs
= (struct bpp_regs __iomem
*)p
->base
;
347 dprintk((KERN_DEBUG
"forward\n"));
348 value_tcr
= sbus_readb(®s
->p_tcr
);
349 value_tcr
&= ~P_TCR_DIR
;
350 sbus_writeb(value_tcr
, ®s
->p_tcr
);
352 printk(KERN_INFO
"%s: sunbpp at 0x%lx\n", p
->name
, p
->base
);
354 list_add(&node
->list
, &port_list
);
355 parport_announce_port (p
);
364 sbus_iounmap(base
, size
);
371 static int __init
parport_sunbpp_init(void)
373 struct sbus_bus
*sbus
;
374 struct sbus_dev
*sdev
;
377 for_each_sbus(sbus
) {
378 for_each_sbusdev(sdev
, sbus
) {
379 if (!strcmp(sdev
->prom_name
, "SUNW,bpp"))
380 count
+= init_one_port(sdev
);
383 return count
? 0 : -ENODEV
;
386 static void __exit
parport_sunbpp_exit(void)
388 while (!list_empty(&port_list
)) {
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
);
394 if (p
->irq
!= PARPORT_IRQ_NONE
) {
395 parport_sunbpp_disable_irq(p
);
398 sbus_iounmap((void __iomem
*)p
->base
, p
->size
);
401 list_del(&node
->list
);
406 MODULE_AUTHOR("Derrick J Brashear");
407 MODULE_DESCRIPTION("Parport Driver for Sparc bidirectional Port");
408 MODULE_SUPPORTED_DEVICE("Sparc Bidirectional Parallel Port");
409 MODULE_LICENSE("GPL");
411 module_init(parport_sunbpp_init
)
412 module_exit(parport_sunbpp_exit
)