1 // SPDX-License-Identifier: GPL-2.0-only
2 /* linux/drivers/parport/parport_ax88796.c
4 * (c) 2005,2006 Simtec Electronics
5 * Ben Dooks <ben@simtec.co.uk>
8 #include <linux/module.h>
9 #include <linux/kernel.h>
10 #include <linux/parport.h>
11 #include <linux/interrupt.h>
12 #include <linux/errno.h>
13 #include <linux/platform_device.h>
14 #include <linux/slab.h>
19 #define AX_SPR_BUSY (1<<7)
20 #define AX_SPR_ACK (1<<6)
21 #define AX_SPR_PE (1<<5)
22 #define AX_SPR_SLCT (1<<4)
23 #define AX_SPR_ERR (1<<3)
25 #define AX_CPR_nDOE (1<<5)
26 #define AX_CPR_SLCTIN (1<<3)
27 #define AX_CPR_nINIT (1<<2)
28 #define AX_CPR_ATFD (1<<1)
29 #define AX_CPR_STRB (1<<0)
32 struct parport
*parport
;
33 struct parport_state suspend
;
38 unsigned char irq_enabled
;
41 void __iomem
*spp_data
;
42 void __iomem
*spp_spr
;
43 void __iomem
*spp_cpr
;
46 static inline struct ax_drvdata
*pp_to_drv(struct parport
*p
)
48 return p
->private_data
;
52 parport_ax88796_read_data(struct parport
*p
)
54 struct ax_drvdata
*dd
= pp_to_drv(p
);
56 return readb(dd
->spp_data
);
60 parport_ax88796_write_data(struct parport
*p
, unsigned char data
)
62 struct ax_drvdata
*dd
= pp_to_drv(p
);
64 writeb(data
, dd
->spp_data
);
68 parport_ax88796_read_control(struct parport
*p
)
70 struct ax_drvdata
*dd
= pp_to_drv(p
);
71 unsigned int cpr
= readb(dd
->spp_cpr
);
74 if (!(cpr
& AX_CPR_STRB
))
75 ret
|= PARPORT_CONTROL_STROBE
;
77 if (!(cpr
& AX_CPR_ATFD
))
78 ret
|= PARPORT_CONTROL_AUTOFD
;
80 if (cpr
& AX_CPR_nINIT
)
81 ret
|= PARPORT_CONTROL_INIT
;
83 if (!(cpr
& AX_CPR_SLCTIN
))
84 ret
|= PARPORT_CONTROL_SELECT
;
90 parport_ax88796_write_control(struct parport
*p
, unsigned char control
)
92 struct ax_drvdata
*dd
= pp_to_drv(p
);
93 unsigned int cpr
= readb(dd
->spp_cpr
);
97 if (!(control
& PARPORT_CONTROL_STROBE
))
100 if (!(control
& PARPORT_CONTROL_AUTOFD
))
103 if (control
& PARPORT_CONTROL_INIT
)
106 if (!(control
& PARPORT_CONTROL_SELECT
))
107 cpr
|= AX_CPR_SLCTIN
;
109 dev_dbg(dd
->dev
, "write_control: ctrl=%02x, cpr=%02x\n", control
, cpr
);
110 writeb(cpr
, dd
->spp_cpr
);
112 if (parport_ax88796_read_control(p
) != control
) {
113 dev_err(dd
->dev
, "write_control: read != set (%02x, %02x)\n",
114 parport_ax88796_read_control(p
), control
);
119 parport_ax88796_read_status(struct parport
*p
)
121 struct ax_drvdata
*dd
= pp_to_drv(p
);
122 unsigned int status
= readb(dd
->spp_spr
);
123 unsigned int ret
= 0;
125 if (status
& AX_SPR_BUSY
)
126 ret
|= PARPORT_STATUS_BUSY
;
128 if (status
& AX_SPR_ACK
)
129 ret
|= PARPORT_STATUS_ACK
;
131 if (status
& AX_SPR_ERR
)
132 ret
|= PARPORT_STATUS_ERROR
;
134 if (status
& AX_SPR_SLCT
)
135 ret
|= PARPORT_STATUS_SELECT
;
137 if (status
& AX_SPR_PE
)
138 ret
|= PARPORT_STATUS_PAPEROUT
;
144 parport_ax88796_frob_control(struct parport
*p
, unsigned char mask
,
147 struct ax_drvdata
*dd
= pp_to_drv(p
);
148 unsigned char old
= parport_ax88796_read_control(p
);
150 dev_dbg(dd
->dev
, "frob: mask=%02x, val=%02x, old=%02x\n",
153 parport_ax88796_write_control(p
, (old
& ~mask
) | val
);
158 parport_ax88796_enable_irq(struct parport
*p
)
160 struct ax_drvdata
*dd
= pp_to_drv(p
);
163 local_irq_save(flags
);
164 if (!dd
->irq_enabled
) {
168 local_irq_restore(flags
);
172 parport_ax88796_disable_irq(struct parport
*p
)
174 struct ax_drvdata
*dd
= pp_to_drv(p
);
177 local_irq_save(flags
);
178 if (dd
->irq_enabled
) {
182 local_irq_restore(flags
);
186 parport_ax88796_data_forward(struct parport
*p
)
188 struct ax_drvdata
*dd
= pp_to_drv(p
);
189 void __iomem
*cpr
= dd
->spp_cpr
;
191 writeb((readb(cpr
) & ~AX_CPR_nDOE
), cpr
);
195 parport_ax88796_data_reverse(struct parport
*p
)
197 struct ax_drvdata
*dd
= pp_to_drv(p
);
198 void __iomem
*cpr
= dd
->spp_cpr
;
200 writeb(readb(cpr
) | AX_CPR_nDOE
, cpr
);
204 parport_ax88796_init_state(struct pardevice
*d
, struct parport_state
*s
)
206 struct ax_drvdata
*dd
= pp_to_drv(d
->port
);
208 memset(s
, 0, sizeof(struct parport_state
));
210 dev_dbg(dd
->dev
, "init_state: %p: state=%p\n", d
, s
);
211 s
->u
.ax88796
.cpr
= readb(dd
->spp_cpr
);
215 parport_ax88796_save_state(struct parport
*p
, struct parport_state
*s
)
217 struct ax_drvdata
*dd
= pp_to_drv(p
);
219 dev_dbg(dd
->dev
, "save_state: %p: state=%p\n", p
, s
);
220 s
->u
.ax88796
.cpr
= readb(dd
->spp_cpr
);
224 parport_ax88796_restore_state(struct parport
*p
, struct parport_state
*s
)
226 struct ax_drvdata
*dd
= pp_to_drv(p
);
228 dev_dbg(dd
->dev
, "restore_state: %p: state=%p\n", p
, s
);
229 writeb(s
->u
.ax88796
.cpr
, dd
->spp_cpr
);
232 static struct parport_operations parport_ax88796_ops
= {
233 .write_data
= parport_ax88796_write_data
,
234 .read_data
= parport_ax88796_read_data
,
236 .write_control
= parport_ax88796_write_control
,
237 .read_control
= parport_ax88796_read_control
,
238 .frob_control
= parport_ax88796_frob_control
,
240 .read_status
= parport_ax88796_read_status
,
242 .enable_irq
= parport_ax88796_enable_irq
,
243 .disable_irq
= parport_ax88796_disable_irq
,
245 .data_forward
= parport_ax88796_data_forward
,
246 .data_reverse
= parport_ax88796_data_reverse
,
248 .init_state
= parport_ax88796_init_state
,
249 .save_state
= parport_ax88796_save_state
,
250 .restore_state
= parport_ax88796_restore_state
,
252 .epp_write_data
= parport_ieee1284_epp_write_data
,
253 .epp_read_data
= parport_ieee1284_epp_read_data
,
254 .epp_write_addr
= parport_ieee1284_epp_write_addr
,
255 .epp_read_addr
= parport_ieee1284_epp_read_addr
,
257 .ecp_write_data
= parport_ieee1284_ecp_write_data
,
258 .ecp_read_data
= parport_ieee1284_ecp_read_data
,
259 .ecp_write_addr
= parport_ieee1284_ecp_write_addr
,
261 .compat_write_data
= parport_ieee1284_write_compat
,
262 .nibble_read_data
= parport_ieee1284_read_nibble
,
263 .byte_read_data
= parport_ieee1284_read_byte
,
265 .owner
= THIS_MODULE
,
268 static int parport_ax88796_probe(struct platform_device
*pdev
)
270 struct device
*_dev
= &pdev
->dev
;
271 struct ax_drvdata
*dd
;
273 struct resource
*res
;
279 dd
= kzalloc(sizeof(*dd
), GFP_KERNEL
);
283 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
285 dev_err(_dev
, "no MEM specified\n");
290 size
= resource_size(res
);
293 dd
->io
= request_mem_region(res
->start
, size
, pdev
->name
);
294 if (dd
->io
== NULL
) {
295 dev_err(_dev
, "cannot reserve memory\n");
300 dd
->base
= ioremap(res
->start
, size
);
301 if (dd
->base
== NULL
) {
302 dev_err(_dev
, "cannot ioremap region\n");
307 irq
= platform_get_irq(pdev
, 0);
309 irq
= PARPORT_IRQ_NONE
;
311 pp
= parport_register_port((unsigned long)dd
->base
, irq
,
313 &parport_ax88796_ops
);
316 dev_err(_dev
, "failed to register parallel port\n");
321 pp
->private_data
= dd
;
325 dd
->spp_data
= dd
->base
;
326 dd
->spp_spr
= dd
->base
+ (spacing
* 1);
327 dd
->spp_cpr
= dd
->base
+ (spacing
* 2);
329 /* initialise the port controls */
330 writeb(AX_CPR_STRB
, dd
->spp_cpr
);
334 ret
= request_irq(irq
, parport_irq_handler
,
335 IRQF_TRIGGER_FALLING
, pdev
->name
, pp
);
343 platform_set_drvdata(pdev
, pp
);
345 dev_info(_dev
, "attached parallel port driver\n");
346 parport_announce_port(pp
);
351 parport_remove_port(pp
);
355 release_mem_region(dd
->io
->start
, size
);
361 static int parport_ax88796_remove(struct platform_device
*pdev
)
363 struct parport
*p
= platform_get_drvdata(pdev
);
364 struct ax_drvdata
*dd
= pp_to_drv(p
);
367 parport_remove_port(p
);
369 release_mem_region(dd
->io
->start
, resource_size(dd
->io
));
377 static int parport_ax88796_suspend(struct platform_device
*dev
,
380 struct parport
*p
= platform_get_drvdata(dev
);
381 struct ax_drvdata
*dd
= pp_to_drv(p
);
383 parport_ax88796_save_state(p
, &dd
->suspend
);
384 writeb(AX_CPR_nDOE
| AX_CPR_STRB
, dd
->spp_cpr
);
388 static int parport_ax88796_resume(struct platform_device
*dev
)
390 struct parport
*p
= platform_get_drvdata(dev
);
391 struct ax_drvdata
*dd
= pp_to_drv(p
);
393 parport_ax88796_restore_state(p
, &dd
->suspend
);
398 #define parport_ax88796_suspend NULL
399 #define parport_ax88796_resume NULL
402 MODULE_ALIAS("platform:ax88796-pp");
404 static struct platform_driver axdrv
= {
406 .name
= "ax88796-pp",
408 .probe
= parport_ax88796_probe
,
409 .remove
= parport_ax88796_remove
,
410 .suspend
= parport_ax88796_suspend
,
411 .resume
= parport_ax88796_resume
,
414 module_platform_driver(axdrv
);
416 MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
417 MODULE_DESCRIPTION("AX88796 Parport parallel port driver");
418 MODULE_LICENSE("GPL");