Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* Low-level parallel port routines for the Amiga built-in port
0003  *
0004  * Author: Joerg Dorchain <joerg@dorchain.net>
0005  *
0006  * This is a complete rewrite of the code, but based heaviy upon the old
0007  * lp_intern. code.
0008  *
0009  * The built-in Amiga parallel port provides one port at a fixed address
0010  * with 8 bidirectional data lines (D0 - D7) and 3 bidirectional status
0011  * lines (BUSY, POUT, SEL), 1 output control line /STROBE (raised automatically
0012  * in hardware when the data register is accessed), and 1 input control line
0013  * /ACK, able to cause an interrupt, but both not directly settable by
0014  * software.
0015  */
0016 
0017 #include <linux/module.h>
0018 #include <linux/init.h>
0019 #include <linux/parport.h>
0020 #include <linux/ioport.h>
0021 #include <linux/interrupt.h>
0022 #include <linux/platform_device.h>
0023 
0024 #include <asm/setup.h>
0025 #include <asm/amigahw.h>
0026 #include <asm/irq.h>
0027 #include <asm/io.h>
0028 #include <asm/amigaints.h>
0029 
0030 #undef DEBUG
0031 
0032 static void amiga_write_data(struct parport *p, unsigned char data)
0033 {
0034     pr_debug("write_data %c\n", data);
0035     /* Triggers also /STROBE. This behavior cannot be changed */
0036     ciaa.prb = data;
0037     mb();
0038 }
0039 
0040 static unsigned char amiga_read_data(struct parport *p)
0041 {
0042     /* Triggers also /STROBE. This behavior cannot be changed */
0043     return ciaa.prb;
0044 }
0045 
0046 static unsigned char control_amiga_to_pc(unsigned char control)
0047 {
0048     return PARPORT_CONTROL_SELECT |
0049           PARPORT_CONTROL_AUTOFD | PARPORT_CONTROL_STROBE;
0050     /* fake value: interrupt enable, select in, no reset,
0051     no autolf, no strobe - seems to be closest the wiring diagram */
0052 }
0053 
0054 static void amiga_write_control(struct parport *p, unsigned char control)
0055 {
0056     pr_debug("write_control %02x\n", control);
0057     /* No implementation possible */
0058 }
0059     
0060 static unsigned char amiga_read_control( struct parport *p)
0061 {
0062     pr_debug("read_control\n");
0063     return control_amiga_to_pc(0);
0064 }
0065 
0066 static unsigned char amiga_frob_control( struct parport *p, unsigned char mask, unsigned char val)
0067 {
0068     unsigned char old;
0069 
0070     pr_debug("frob_control mask %02x, value %02x\n", mask, val);
0071     old = amiga_read_control(p);
0072     amiga_write_control(p, (old & ~mask) ^ val);
0073     return old;
0074 }
0075 
0076 static unsigned char status_amiga_to_pc(unsigned char status)
0077 {
0078     unsigned char ret = PARPORT_STATUS_BUSY | PARPORT_STATUS_ACK | PARPORT_STATUS_ERROR;
0079 
0080     if (status & 1) /* Busy */
0081         ret &= ~PARPORT_STATUS_BUSY;
0082     if (status & 2) /* PaperOut */
0083         ret |= PARPORT_STATUS_PAPEROUT;
0084     if (status & 4) /* Selected */
0085         ret |= PARPORT_STATUS_SELECT;
0086     /* the rest is not connected or handled autonomously in hardware */
0087 
0088     return ret;
0089 }
0090 
0091 static unsigned char amiga_read_status(struct parport *p)
0092 {
0093     unsigned char status;
0094 
0095     status = status_amiga_to_pc(ciab.pra & 7);
0096     pr_debug("read_status %02x\n", status);
0097     return status;
0098 }
0099 
0100 static void amiga_enable_irq(struct parport *p)
0101 {
0102     enable_irq(IRQ_AMIGA_CIAA_FLG);
0103 }
0104 
0105 static void amiga_disable_irq(struct parport *p)
0106 {
0107     disable_irq(IRQ_AMIGA_CIAA_FLG);
0108 }
0109 
0110 static void amiga_data_forward(struct parport *p)
0111 {
0112     pr_debug("forward\n");
0113     ciaa.ddrb = 0xff; /* all pins output */
0114     mb();
0115 }
0116 
0117 static void amiga_data_reverse(struct parport *p)
0118 {
0119     pr_debug("reverse\n");
0120     ciaa.ddrb = 0; /* all pins input */
0121     mb();
0122 }
0123 
0124 static void amiga_init_state(struct pardevice *dev, struct parport_state *s)
0125 {
0126     s->u.amiga.data = 0;
0127     s->u.amiga.datadir = 255;
0128     s->u.amiga.status = 0;
0129     s->u.amiga.statusdir = 0;
0130 }
0131 
0132 static void amiga_save_state(struct parport *p, struct parport_state *s)
0133 {
0134     mb();
0135     s->u.amiga.data = ciaa.prb;
0136     s->u.amiga.datadir = ciaa.ddrb;
0137     s->u.amiga.status = ciab.pra & 7;
0138     s->u.amiga.statusdir = ciab.ddra & 7;
0139     mb();
0140 }
0141 
0142 static void amiga_restore_state(struct parport *p, struct parport_state *s)
0143 {
0144     mb();
0145     ciaa.prb = s->u.amiga.data;
0146     ciaa.ddrb = s->u.amiga.datadir;
0147     ciab.pra |= (ciab.pra & 0xf8) | s->u.amiga.status;
0148     ciab.ddra |= (ciab.ddra & 0xf8) | s->u.amiga.statusdir;
0149     mb();
0150 }
0151 
0152 static struct parport_operations pp_amiga_ops = {
0153     .write_data = amiga_write_data,
0154     .read_data  = amiga_read_data,
0155 
0156     .write_control  = amiga_write_control,
0157     .read_control   = amiga_read_control,
0158     .frob_control   = amiga_frob_control,
0159 
0160     .read_status    = amiga_read_status,
0161 
0162     .enable_irq = amiga_enable_irq,
0163     .disable_irq    = amiga_disable_irq,
0164 
0165     .data_forward   = amiga_data_forward,
0166     .data_reverse   = amiga_data_reverse,
0167 
0168     .init_state = amiga_init_state,
0169     .save_state = amiga_save_state,
0170     .restore_state  = amiga_restore_state,
0171 
0172     .epp_write_data = parport_ieee1284_epp_write_data,
0173     .epp_read_data  = parport_ieee1284_epp_read_data,
0174     .epp_write_addr = parport_ieee1284_epp_write_addr,
0175     .epp_read_addr  = parport_ieee1284_epp_read_addr,
0176 
0177     .ecp_write_data = parport_ieee1284_ecp_write_data,
0178     .ecp_read_data  = parport_ieee1284_ecp_read_data,
0179     .ecp_write_addr = parport_ieee1284_ecp_write_addr,
0180 
0181     .compat_write_data  = parport_ieee1284_write_compat,
0182     .nibble_read_data   = parport_ieee1284_read_nibble,
0183     .byte_read_data     = parport_ieee1284_read_byte,
0184 
0185     .owner      = THIS_MODULE,
0186 };
0187 
0188 /* ----------- Initialisation code --------------------------------- */
0189 
0190 static int __init amiga_parallel_probe(struct platform_device *pdev)
0191 {
0192     struct parport *p;
0193     int err;
0194 
0195     ciaa.ddrb = 0xff;
0196     ciab.ddra &= 0xf8;
0197     mb();
0198 
0199     p = parport_register_port((unsigned long)&ciaa.prb, IRQ_AMIGA_CIAA_FLG,
0200                    PARPORT_DMA_NONE, &pp_amiga_ops);
0201     if (!p)
0202         return -EBUSY;
0203 
0204     err = request_irq(IRQ_AMIGA_CIAA_FLG, parport_irq_handler, 0, p->name,
0205               p);
0206     if (err)
0207         goto out_irq;
0208 
0209     pr_info("%s: Amiga built-in port using irq\n", p->name);
0210     /* XXX: set operating mode */
0211     parport_announce_port(p);
0212 
0213     platform_set_drvdata(pdev, p);
0214 
0215     return 0;
0216 
0217 out_irq:
0218     parport_put_port(p);
0219     return err;
0220 }
0221 
0222 static int __exit amiga_parallel_remove(struct platform_device *pdev)
0223 {
0224     struct parport *port = platform_get_drvdata(pdev);
0225 
0226     parport_remove_port(port);
0227     if (port->irq != PARPORT_IRQ_NONE)
0228         free_irq(IRQ_AMIGA_CIAA_FLG, port);
0229     parport_put_port(port);
0230     return 0;
0231 }
0232 
0233 static struct platform_driver amiga_parallel_driver = {
0234     .remove = __exit_p(amiga_parallel_remove),
0235     .driver   = {
0236         .name   = "amiga-parallel",
0237     },
0238 };
0239 
0240 module_platform_driver_probe(amiga_parallel_driver, amiga_parallel_probe);
0241 
0242 MODULE_AUTHOR("Joerg Dorchain <joerg@dorchain.net>");
0243 MODULE_DESCRIPTION("Parport Driver for Amiga builtin Port");
0244 MODULE_LICENSE("GPL");
0245 MODULE_ALIAS("platform:amiga-parallel");