OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [parport/] [parport_ax88796.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/* 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 struct parport_operations parport_ax88796_ops = {
236
        .write_data     = parport_ax88796_write_data,
237
        .read_data      = parport_ax88796_read_data,
238
 
239
        .write_control  = parport_ax88796_write_control,
240
        .read_control   = parport_ax88796_read_control,
241
        .frob_control   = parport_ax88796_frob_control,
242
 
243
        .read_status    = parport_ax88796_read_status,
244
 
245
        .enable_irq     = parport_ax88796_enable_irq,
246
        .disable_irq    = parport_ax88796_disable_irq,
247
 
248
        .data_forward   = parport_ax88796_data_forward,
249
        .data_reverse   = parport_ax88796_data_reverse,
250
 
251
        .init_state     = parport_ax88796_init_state,
252
        .save_state     = parport_ax88796_save_state,
253
        .restore_state  = parport_ax88796_restore_state,
254
 
255
        .epp_write_data = parport_ieee1284_epp_write_data,
256
        .epp_read_data  = parport_ieee1284_epp_read_data,
257
        .epp_write_addr = parport_ieee1284_epp_write_addr,
258
        .epp_read_addr  = parport_ieee1284_epp_read_addr,
259
 
260
        .ecp_write_data = parport_ieee1284_ecp_write_data,
261
        .ecp_read_data  = parport_ieee1284_ecp_read_data,
262
        .ecp_write_addr = parport_ieee1284_ecp_write_addr,
263
 
264
        .compat_write_data      = parport_ieee1284_write_compat,
265
        .nibble_read_data       = parport_ieee1284_read_nibble,
266
        .byte_read_data         = parport_ieee1284_read_byte,
267
 
268
        .owner          = THIS_MODULE,
269
};
270
 
271
static int parport_ax88796_probe(struct platform_device *pdev)
272
{
273
        struct device *_dev = &pdev->dev;
274
        struct ax_drvdata *dd;
275
        struct parport *pp = NULL;
276
        struct resource *res;
277
        unsigned long size;
278
        int spacing;
279
        int irq;
280
        int ret;
281
 
282
        dd = kzalloc(sizeof(struct ax_drvdata), GFP_KERNEL);
283
        if (dd == NULL) {
284
                dev_err(_dev, "no memory for private data\n");
285
                return -ENOMEM;
286
        }
287
 
288
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
289
        if (res == NULL) {
290
                dev_err(_dev, "no MEM specified\n");
291
                ret = -ENXIO;
292
                goto exit_mem;
293
        }
294
 
295
        size = (res->end - res->start) + 1;
296
        spacing = size / 3;
297
 
298
        dd->io = request_mem_region(res->start, size, pdev->name);
299
        if (dd->io == NULL) {
300
                dev_err(_dev, "cannot reserve memory\n");
301
                ret = -ENXIO;
302
                goto exit_mem;
303
        }
304
 
305
        dd->base = ioremap(res->start, size);
306
        if (dd->base == NULL) {
307
                dev_err(_dev, "cannot ioremap region\n");
308
                ret = -ENXIO;
309
                goto exit_res;
310
        }
311
 
312
        irq = platform_get_irq(pdev, 0);
313
        if (irq <= 0)
314
                irq = PARPORT_IRQ_NONE;
315
 
316
        pp = parport_register_port((unsigned long)dd->base, irq,
317
                                   PARPORT_DMA_NONE,
318
                                   &parport_ax88796_ops);
319
 
320
        if (pp == NULL) {
321
                dev_err(_dev, "failed to register parallel port\n");
322
                ret = -ENOMEM;
323
                goto exit_unmap;
324
        }
325
 
326
        pp->private_data = dd;
327
        dd->parport = pp;
328
        dd->dev = _dev;
329
 
330
        dd->spp_data = dd->base;
331
        dd->spp_spr  = dd->base + (spacing * 1);
332
        dd->spp_cpr  = dd->base + (spacing * 2);
333
 
334
        /* initialise the port controls */
335
        writeb(AX_CPR_STRB, dd->spp_cpr);
336
 
337
        if (irq >= 0) {
338
                /* request irq */
339
                ret = request_irq(irq, parport_irq_handler,
340
                                  IRQF_TRIGGER_FALLING, pdev->name, pp);
341
 
342
                if (ret < 0)
343
                        goto exit_port;
344
 
345
                dd->irq_enabled = 1;
346
        }
347
 
348
        platform_set_drvdata(pdev, pp);
349
 
350
        dev_info(_dev, "attached parallel port driver\n");
351
        parport_announce_port(pp);
352
 
353
        return 0;
354
 
355
 exit_port:
356
        parport_remove_port(pp);
357
 exit_unmap:
358
        iounmap(dd->base);
359
 exit_res:
360
        release_resource(dd->io);
361
        kfree(dd->io);
362
 exit_mem:
363
        kfree(dd);
364
        return ret;
365
}
366
 
367
static int parport_ax88796_remove(struct platform_device *pdev)
368
{
369
        struct parport *p = platform_get_drvdata(pdev);
370
        struct ax_drvdata *dd = pp_to_drv(p);
371
 
372
        free_irq(p->irq, p);
373
        parport_remove_port(p);
374
        iounmap(dd->base);
375
        release_resource(dd->io);
376
        kfree(dd->io);
377
        kfree(dd);
378
 
379
        return 0;
380
}
381
 
382
#ifdef CONFIG_PM
383
 
384
static int parport_ax88796_suspend(struct platform_device *dev,
385
                                   pm_message_t state)
386
{
387
        struct parport *p = platform_get_drvdata(dev);
388
        struct ax_drvdata *dd = pp_to_drv(p);
389
 
390
        parport_ax88796_save_state(p, &dd->suspend);
391
        writeb(AX_CPR_nDOE | AX_CPR_STRB, dd->spp_cpr);
392
        return 0;
393
}
394
 
395
static int parport_ax88796_resume(struct platform_device *dev)
396
{
397
        struct parport *p = platform_get_drvdata(dev);
398
        struct ax_drvdata *dd = pp_to_drv(p);
399
 
400
        parport_ax88796_restore_state(p, &dd->suspend);
401
        return 0;
402
}
403
 
404
#else
405
#define parport_ax88796_suspend NULL
406
#define parport_ax88796_resume  NULL
407
#endif
408
 
409
static struct platform_driver axdrv = {
410
        .driver         = {
411
                .name   = "ax88796-pp",
412
                .owner  = THIS_MODULE,
413
        },
414
        .probe          = parport_ax88796_probe,
415
        .remove         = parport_ax88796_remove,
416
        .suspend        = parport_ax88796_suspend,
417
        .resume         = parport_ax88796_resume,
418
};
419
 
420
static int __init parport_ax88796_init(void)
421
{
422
        return platform_driver_register(&axdrv);
423
}
424
 
425
static void __exit parport_ax88796_exit(void)
426
{
427
        platform_driver_unregister(&axdrv);
428
}
429
 
430
module_init(parport_ax88796_init)
431
module_exit(parport_ax88796_exit)
432
 
433
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
434
MODULE_DESCRIPTION("AX88796 Parport parallel port driver");
435
MODULE_LICENSE("GPL");

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.