linux/drivers/parport/parport_ax88796.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/* linux/drivers/parport/parport_ax88796.c
   3 *
   4 * (c) 2005,2006 Simtec Electronics
   5 *      Ben Dooks <ben@simtec.co.uk>
   6*/
   7
   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>
  15
  16#include <asm/io.h>
  17#include <asm/irq.h>
  18
  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)
  24
  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)
  30
  31struct ax_drvdata {
  32        struct parport          *parport;
  33        struct parport_state     suspend;
  34
  35        struct device           *dev;
  36        struct resource         *io;
  37
  38        unsigned char            irq_enabled;
  39
  40        void __iomem            *base;
  41        void __iomem            *spp_data;
  42        void __iomem            *spp_spr;
  43        void __iomem            *spp_cpr;
  44};
  45
  46static inline struct ax_drvdata *pp_to_drv(struct parport *p)
  47{
  48        return p->private_data;
  49}
  50
  51static unsigned char
  52parport_ax88796_read_data(struct parport *p)
  53{
  54        struct ax_drvdata *dd = pp_to_drv(p);
  55
  56        return readb(dd->spp_data);
  57}
  58
  59static void
  60parport_ax88796_write_data(struct parport *p, unsigned char data)
  61{
  62        struct ax_drvdata *dd = pp_to_drv(p);
  63
  64        writeb(data, dd->spp_data);
  65}
  66
  67static unsigned char
  68parport_ax88796_read_control(struct parport *p)
  69{
  70        struct ax_drvdata *dd = pp_to_drv(p);
  71        unsigned int cpr = readb(dd->spp_cpr);
  72        unsigned int ret = 0;
  73
  74        if (!(cpr & AX_CPR_STRB))
  75                ret |= PARPORT_CONTROL_STROBE;
  76
  77        if (!(cpr & AX_CPR_ATFD))
  78                ret |= PARPORT_CONTROL_AUTOFD;
  79
  80        if (cpr & AX_CPR_nINIT)
  81                ret |= PARPORT_CONTROL_INIT;
  82
  83        if (!(cpr & AX_CPR_SLCTIN))
  84                ret |= PARPORT_CONTROL_SELECT;
  85
  86        return ret;
  87}
  88
  89static void
  90parport_ax88796_write_control(struct parport *p, unsigned char control)
  91{
  92        struct ax_drvdata *dd = pp_to_drv(p);
  93        unsigned int cpr = readb(dd->spp_cpr);
  94
  95        cpr &= AX_CPR_nDOE;
  96
  97        if (!(control & PARPORT_CONTROL_STROBE))
  98                cpr |= AX_CPR_STRB;
  99
 100        if (!(control & PARPORT_CONTROL_AUTOFD))
 101                cpr |= AX_CPR_ATFD;
 102
 103        if (control & PARPORT_CONTROL_INIT)
 104                cpr |= AX_CPR_nINIT;
 105
 106        if (!(control & PARPORT_CONTROL_SELECT))
 107                cpr |= AX_CPR_SLCTIN;
 108
 109        dev_dbg(dd->dev, "write_control: ctrl=%02x, cpr=%02x\n", control, cpr);
 110        writeb(cpr, dd->spp_cpr);
 111
 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);
 115        }
 116}
 117
 118static unsigned char
 119parport_ax88796_read_status(struct parport *p)
 120{
 121        struct ax_drvdata *dd = pp_to_drv(p);
 122        unsigned int status = readb(dd->spp_spr);
 123        unsigned int ret = 0;
 124
 125        if (status & AX_SPR_BUSY)
 126                ret |= PARPORT_STATUS_BUSY;
 127
 128        if (status & AX_SPR_ACK)
 129                ret |= PARPORT_STATUS_ACK;
 130
 131        if (status & AX_SPR_ERR)
 132                ret |= PARPORT_STATUS_ERROR;
 133
 134        if (status & AX_SPR_SLCT)
 135                ret |= PARPORT_STATUS_SELECT;
 136
 137        if (status & AX_SPR_PE)
 138                ret |= PARPORT_STATUS_PAPEROUT;
 139
 140        return ret;
 141}
 142
 143static unsigned char
 144parport_ax88796_frob_control(struct parport *p, unsigned char mask,
 145                             unsigned char val)
 146{
 147        struct ax_drvdata *dd = pp_to_drv(p);
 148        unsigned char old = parport_ax88796_read_control(p);
 149
 150        dev_dbg(dd->dev, "frob: mask=%02x, val=%02x, old=%02x\n",
 151                mask, val, old);
 152
 153        parport_ax88796_write_control(p, (old & ~mask) | val);
 154        return old;
 155}
 156
 157static void
 158parport_ax88796_enable_irq(struct parport *p)
 159{
 160        struct ax_drvdata *dd = pp_to_drv(p);
 161        unsigned long flags;
 162
 163        local_irq_save(flags);
 164        if (!dd->irq_enabled) {
 165                enable_irq(p->irq);
 166                dd->irq_enabled = 1;
 167        }
 168        local_irq_restore(flags);
 169}
 170
 171static void
 172parport_ax88796_disable_irq(struct parport *p)
 173{
 174        struct ax_drvdata *dd = pp_to_drv(p);
 175        unsigned long flags;
 176
 177        local_irq_save(flags);
 178        if (dd->irq_enabled) {
 179                disable_irq(p->irq);
 180                dd->irq_enabled = 0;
 181        }
 182        local_irq_restore(flags);
 183}
 184
 185static void
 186parport_ax88796_data_forward(struct parport *p)
 187{
 188        struct ax_drvdata *dd = pp_to_drv(p);
 189        void __iomem *cpr = dd->spp_cpr;
 190
 191        writeb((readb(cpr) & ~AX_CPR_nDOE), cpr);
 192}
 193
 194static void
 195parport_ax88796_data_reverse(struct parport *p)
 196{
 197        struct ax_drvdata *dd = pp_to_drv(p);
 198        void __iomem *cpr = dd->spp_cpr;
 199
 200        writeb(readb(cpr) | AX_CPR_nDOE, cpr);
 201}
 202
 203static void
 204parport_ax88796_init_state(struct pardevice *d, struct parport_state *s)
 205{
 206        struct ax_drvdata *dd = pp_to_drv(d->port);
 207
 208        memset(s, 0, sizeof(struct parport_state));
 209
 210        dev_dbg(dd->dev, "init_state: %p: state=%p\n", d, s);
 211        s->u.ax88796.cpr = readb(dd->spp_cpr);
 212}
 213
 214static void
 215parport_ax88796_save_state(struct parport *p, struct parport_state *s)
 216{
 217        struct ax_drvdata *dd = pp_to_drv(p);
 218
 219        dev_dbg(dd->dev, "save_state: %p: state=%p\n", p, s);
 220        s->u.ax88796.cpr = readb(dd->spp_cpr);
 221}
 222
 223static void
 224parport_ax88796_restore_state(struct parport *p, struct parport_state *s)
 225{
 226        struct ax_drvdata *dd = pp_to_drv(p);
 227
 228        dev_dbg(dd->dev, "restore_state: %p: state=%p\n", p, s);
 229        writeb(s->u.ax88796.cpr, dd->spp_cpr);
 230}
 231
 232static struct parport_operations parport_ax88796_ops = {
 233        .write_data     = parport_ax88796_write_data,
 234        .read_data      = parport_ax88796_read_data,
 235
 236        .write_control  = parport_ax88796_write_control,
 237        .read_control   = parport_ax88796_read_control,
 238        .frob_control   = parport_ax88796_frob_control,
 239
 240        .read_status    = parport_ax88796_read_status,
 241
 242        .enable_irq     = parport_ax88796_enable_irq,
 243        .disable_irq    = parport_ax88796_disable_irq,
 244
 245        .data_forward   = parport_ax88796_data_forward,
 246        .data_reverse   = parport_ax88796_data_reverse,
 247
 248        .init_state     = parport_ax88796_init_state,
 249        .save_state     = parport_ax88796_save_state,
 250        .restore_state  = parport_ax88796_restore_state,
 251
 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,
 256
 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,
 260
 261        .compat_write_data      = parport_ieee1284_write_compat,
 262        .nibble_read_data       = parport_ieee1284_read_nibble,
 263        .byte_read_data         = parport_ieee1284_read_byte,
 264
 265        .owner          = THIS_MODULE,
 266};
 267
 268static int parport_ax88796_probe(struct platform_device *pdev)
 269{
 270        struct device *_dev = &pdev->dev;
 271        struct ax_drvdata *dd;
 272        struct parport *pp;
 273        struct resource *res;
 274        unsigned long size;
 275        int spacing;
 276        int irq;
 277        int ret;
 278
 279        dd = kzalloc(sizeof(*dd), GFP_KERNEL);
 280        if (!dd)
 281                return -ENOMEM;
 282
 283        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 284        if (res == NULL) {
 285                dev_err(_dev, "no MEM specified\n");
 286                ret = -ENXIO;
 287                goto exit_mem;
 288        }
 289
 290        size = resource_size(res);
 291        spacing = size / 3;
 292
 293        dd->io = request_mem_region(res->start, size, pdev->name);
 294        if (dd->io == NULL) {
 295                dev_err(_dev, "cannot reserve memory\n");
 296                ret = -ENXIO;
 297                goto exit_mem;
 298        }
 299
 300        dd->base = ioremap(res->start, size);
 301        if (dd->base == NULL) {
 302                dev_err(_dev, "cannot ioremap region\n");
 303                ret = -ENXIO;
 304                goto exit_res;
 305        }
 306
 307        irq = platform_get_irq(pdev, 0);
 308        if (irq <= 0)
 309                irq = PARPORT_IRQ_NONE;
 310
 311        pp = parport_register_port((unsigned long)dd->base, irq,
 312                                   PARPORT_DMA_NONE,
 313                                   &parport_ax88796_ops);
 314
 315        if (pp == NULL) {
 316                dev_err(_dev, "failed to register parallel port\n");
 317                ret = -ENOMEM;
 318                goto exit_unmap;
 319        }
 320
 321        pp->private_data = dd;
 322        dd->parport = pp;
 323        dd->dev = _dev;
 324
 325        dd->spp_data = dd->base;
 326        dd->spp_spr  = dd->base + (spacing * 1);
 327        dd->spp_cpr  = dd->base + (spacing * 2);
 328
 329        /* initialise the port controls */
 330        writeb(AX_CPR_STRB, dd->spp_cpr);
 331
 332        if (irq >= 0) {
 333                /* request irq */
 334                ret = request_irq(irq, parport_irq_handler,
 335                                  IRQF_TRIGGER_FALLING, pdev->name, pp);
 336
 337                if (ret < 0)
 338                        goto exit_port;
 339
 340                dd->irq_enabled = 1;
 341        }
 342
 343        platform_set_drvdata(pdev, pp);
 344
 345        dev_info(_dev, "attached parallel port driver\n");
 346        parport_announce_port(pp);
 347
 348        return 0;
 349
 350 exit_port:
 351        parport_remove_port(pp);
 352 exit_unmap:
 353        iounmap(dd->base);
 354 exit_res:
 355        release_mem_region(dd->io->start, size);
 356 exit_mem:
 357        kfree(dd);
 358        return ret;
 359}
 360
 361static int parport_ax88796_remove(struct platform_device *pdev)
 362{
 363        struct parport *p = platform_get_drvdata(pdev);
 364        struct ax_drvdata *dd = pp_to_drv(p);
 365
 366        free_irq(p->irq, p);
 367        parport_remove_port(p);
 368        iounmap(dd->base);
 369        release_mem_region(dd->io->start, resource_size(dd->io));
 370        kfree(dd);
 371
 372        return 0;
 373}
 374
 375#ifdef CONFIG_PM
 376
 377static int parport_ax88796_suspend(struct platform_device *dev,
 378                                   pm_message_t state)
 379{
 380        struct parport *p = platform_get_drvdata(dev);
 381        struct ax_drvdata *dd = pp_to_drv(p);
 382
 383        parport_ax88796_save_state(p, &dd->suspend);
 384        writeb(AX_CPR_nDOE | AX_CPR_STRB, dd->spp_cpr);
 385        return 0;
 386}
 387
 388static int parport_ax88796_resume(struct platform_device *dev)
 389{
 390        struct parport *p = platform_get_drvdata(dev);
 391        struct ax_drvdata *dd = pp_to_drv(p);
 392
 393        parport_ax88796_restore_state(p, &dd->suspend);
 394        return 0;
 395}
 396
 397#else
 398#define parport_ax88796_suspend NULL
 399#define parport_ax88796_resume  NULL
 400#endif
 401
 402MODULE_ALIAS("platform:ax88796-pp");
 403
 404static struct platform_driver axdrv = {
 405        .driver         = {
 406                .name   = "ax88796-pp",
 407        },
 408        .probe          = parport_ax88796_probe,
 409        .remove         = parport_ax88796_remove,
 410        .suspend        = parport_ax88796_suspend,
 411        .resume         = parport_ax88796_resume,
 412};
 413
 414module_platform_driver(axdrv);
 415
 416MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
 417MODULE_DESCRIPTION("AX88796 Parport parallel port driver");
 418MODULE_LICENSE("GPL");
 419