root/i2c/trunk/kernel/i2c-pcf-epp.c @ 3560

Revision 3560, 6.6 KB (checked in by mds, 13 years ago)

Belatedly sync with kernel 2.4.2 (malloc.h -> slab.h)

Should be ok for 2.2 kernels also.
Thanks J . A . Magallon <jamagallon@…>

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* ------------------------------------------------------------------------- */
2/* i2c-pcf-epp.c i2c-hw access for PCF8584 style EPP parallel port adapters  */
3/* ------------------------------------------------------------------------- */
4
5#include <linux/kernel.h>
6#include <linux/ioport.h>
7#include <linux/module.h>
8#include <linux/delay.h>
9#include <linux/slab.h>
10#include <linux/version.h>
11#include <linux/init.h>
12#include <asm/irq.h>
13#include <asm/io.h>
14
15#include "i2c.h"
16#include "i2c-algo-pcf.h"
17#include "i2c-pcf8584.h"
18#include "i2c-pcf-epp.h"
19
20#define DEFAULT_BASE 0x378
21#define DEFAULT_IRQ      7
22#define DEFAULT_CLOCK 0x1c
23#define DEFAULT_OWN   0x55
24
25static int base  = 0;
26static int irq   = 0;
27static int clock = 0;
28static int own   = 0;
29static int i2c_debug=0;
30static struct i2c_pcf_epp gpe;
31#if (LINUX_VERSION_CODE < 0x020301)
32static struct wait_queue *pcf_wait = NULL;
33#else
34static wait_queue_head_t pcf_wait;
35#endif
36static int pcf_pending;
37
38/* ----- global defines ----------------------------------------------- */
39#define DEB(x)  if (i2c_debug>=1) x
40#define DEB2(x) if (i2c_debug>=2) x
41#define DEB3(x) if (i2c_debug>=3) x
42#define DEBE(x) x       /* error messages                               */
43
44/* --- Convenience defines for the EPP/SPP port:                        */
45#define BASE    ((struct i2c_pcf_epp *)(data))->pe_base
46#define DATA    BASE                    /* SPP data port */
47#define STAT    (BASE+1)                /* SPP status port */
48#define CTRL    (BASE+2)                /* SPP control port */
49#define EADD    (BASE+3)                /* EPP address port */
50#define EDAT    (BASE+4)                /* EPP data port */
51
52/* ----- local functions ---------------------------------------------- */
53
54static void pcf_epp_setbyte(void *data, int ctl, int val)
55{
56  if (ctl) {
57    if (gpe.pe_irq > 0) {
58      DEB3(printk("i2c-pcf-epp.o: Write control 0x%x\n",
59                  val|I2C_PCF_ENI));
60      // set A0 pin HIGH
61      outb(inb(CTRL) | PARPORT_CONTROL_INIT, CTRL);
62      // DEB3(printk("i2c-pcf-epp.o: CTRL port = 0x%x\n", inb(CTRL)));
63      // DEB3(printk("i2c-pcf-epp.o: STAT port = 0x%x\n", inb(STAT)));
64     
65      // EPP write data cycle
66      outb(val | I2C_PCF_ENI, EDAT);
67    } else {
68      DEB3(printk("i2c-pcf-epp.o: Write control 0x%x\n", val));
69      // set A0 pin HIGH
70      outb(inb(CTRL) | PARPORT_CONTROL_INIT, CTRL);
71      outb(val, CTRL);
72    }
73  } else {
74    DEB3(printk("i2c-pcf-epp.o: Write data 0x%x\n", val));
75    // set A0 pin LO
76    outb(inb(CTRL) & ~PARPORT_CONTROL_INIT, CTRL);
77    // DEB3(printk("i2c-pcf-epp.o: CTRL port = 0x%x\n", inb(CTRL)));
78    // DEB3(printk("i2c-pcf-epp.o: STAT port = 0x%x\n", inb(STAT)));
79    outb(val, EDAT);
80  }
81}
82
83static int pcf_epp_getbyte(void *data, int ctl)
84{
85  int val;
86
87  if (ctl) {
88    // set A0 pin HIGH
89    outb(inb(CTRL) | PARPORT_CONTROL_INIT, CTRL);
90    val = inb(EDAT);
91    DEB3(printk("i2c-pcf-epp.o: Read control 0x%x\n", val));
92  } else {
93    // set A0 pin LOW
94    outb(inb(CTRL) & ~PARPORT_CONTROL_INIT, CTRL);
95    val = inb(EDAT);
96    DEB3(printk("i2c-pcf-epp.o: Read data 0x%x\n", val));
97  }
98  return (val);
99}
100
101static int pcf_epp_getown(void *data)
102{
103  return (gpe.pe_own);
104}
105
106
107static int pcf_epp_getclock(void *data)
108{
109  return (gpe.pe_clock);
110}
111
112#if 0
113static void pcf_epp_sleep(unsigned long timeout)
114{
115  schedule_timeout( timeout * HZ);
116}
117#endif
118
119static void pcf_epp_waitforpin(void) {
120  int timeout = 10;
121
122  if (gpe.pe_irq > 0) {
123    cli();
124    if (pcf_pending == 0) {
125      interruptible_sleep_on_timeout(&pcf_wait, timeout*HZ);
126      //udelay(100);
127    } else {
128      pcf_pending = 0;
129    }
130    sti();
131  } else {
132    udelay(100);
133  }
134}
135
136static void pcf_epp_handler(int this_irq, void *dev_id, struct pt_regs *regs) {
137  pcf_pending = 1;
138  wake_up_interruptible(&pcf_wait);
139  DEB3(printk("i2c-pcf-epp.o: in interrupt handler.\n"));
140}
141
142
143static int pcf_epp_init(void *data)
144{
145  if (check_region(gpe.pe_base, 5) < 0 ) {
146    return -ENODEV;
147  } else {
148    request_region(gpe.pe_base, 5, "i2c (EPP parallel port adapter)");
149  }
150
151  DEB3(printk("i2c-pcf-epp.o: init status port = 0x%x\n", inb(0x379)));
152 
153  if (gpe.pe_irq > 0) {
154    if (request_irq(gpe.pe_irq, pcf_epp_handler, 0, "PCF8584", 0) < 0) {
155      printk("i2c-pcf-epp.o: Request irq%d failed\n", gpe.pe_irq);
156      gpe.pe_irq = 0;
157    } else
158      disable_irq(gpe.pe_irq);
159      enable_irq(gpe.pe_irq);
160  }
161  // EPP mode initialize
162  // enable interrupt from nINTR pin
163  outb(inb(CTRL)|0x14, CTRL);
164  // clear ERROR bit of STAT
165  outb(inb(STAT)|0x01, STAT);
166  outb(inb(STAT)&~0x01,STAT);
167 
168  return 0;
169}
170
171
172static void pcf_epp_exit(void)
173{
174  if (gpe.pe_irq > 0) {
175    disable_irq(gpe.pe_irq);
176    free_irq(gpe.pe_irq, 0);
177  }
178  release_region(gpe.pe_base , 5);
179}
180
181
182static int pcf_epp_reg(struct i2c_client *client)
183{
184  return 0;
185}
186
187
188static int pcf_epp_unreg(struct i2c_client *client)
189{
190  return 0;
191}
192
193static void pcf_epp_inc_use(struct i2c_adapter *adap)
194{
195#ifdef MODULE
196  MOD_INC_USE_COUNT;
197#endif
198}
199
200static void pcf_epp_dec_use(struct i2c_adapter *adap)
201{
202#ifdef MODULE
203  MOD_DEC_USE_COUNT;
204#endif
205}
206
207
208/* ------------------------------------------------------------------------
209 * Encapsulate the above functions in the correct operations structure.
210 * This is only done when more than one hardware adapter is supported.
211 */
212static struct i2c_algo_pcf_data pcf_epp_data = {
213  NULL,
214  pcf_epp_setbyte,
215  pcf_epp_getbyte,
216  pcf_epp_getown,
217  pcf_epp_getclock,
218  pcf_epp_waitforpin,
219  80, 80, 100,          /*      waits, timeout */
220};
221
222static struct i2c_adapter pcf_epp_ops = {
223  "PCF8584 EPP adapter",
224  I2C_HW_P_LP,
225  NULL,
226  &pcf_epp_data,
227  pcf_epp_inc_use,
228  pcf_epp_dec_use,
229  pcf_epp_reg,
230  pcf_epp_unreg,
231};
232
233int __init i2c_pcfepp_init(void) 
234{
235  struct i2c_pcf_epp *pepp = &gpe;
236
237  printk("i2c-pcf-epp.o: i2c pcf8584-epp adapter module\n");
238  if (base == 0)
239    pepp->pe_base = DEFAULT_BASE;
240  else
241    pepp->pe_base = base;
242
243  if (irq == 0)
244    pepp->pe_irq = DEFAULT_IRQ;
245  else
246    pepp->pe_irq = irq;
247
248  if (clock == 0)
249    pepp->pe_clock = DEFAULT_CLOCK;
250  else
251    pepp->pe_clock = clock;
252
253  if (own == 0)
254    pepp->pe_own = DEFAULT_OWN;
255  else
256    pepp->pe_own = own;
257
258  pcf_epp_data.data = (void *)pepp;
259#if (LINUX_VERSION_CODE >= 0x020301)
260  init_waitqueue_head(&pcf_wait);
261#endif
262  if (pcf_epp_init(pepp) == 0) {
263    if (i2c_pcf_add_bus(&pcf_epp_ops) < 0)
264      return -ENODEV;
265  } else {
266    return -ENODEV;
267  }
268  printk("i2c-pcf-epp.o: found device at %#x.\n", pepp->pe_base);
269  return 0;
270}
271
272
273EXPORT_NO_SYMBOLS;
274
275#ifdef MODULE
276MODULE_AUTHOR("Hans Berglund <hb@spacetec.no> \n modified by Ryosuke Tajima <rosk@jsk.t.u-tokyo.ac.jp>");
277MODULE_DESCRIPTION("I2C-Bus adapter routines for PCF8584 EPP parallel port adapter");
278
279MODULE_PARM(base, "i");
280MODULE_PARM(irq, "i");
281MODULE_PARM(clock, "i");
282MODULE_PARM(own, "i");
283
284int init_module(void) 
285{
286  return i2c_pcfepp_init();
287}
288
289void cleanup_module(void) 
290{
291  i2c_pcf_del_bus(&pcf_epp_ops);
292  pcf_epp_exit();
293}
294
295#endif
296
297
Note: See TracBrowser for help on using the browser.