root/i2c/trunk/kernel/i2c-adap-ibm_ocp.c @ 3753

Revision 3753, 11.2 KB (checked in by kmalkki, 10 years ago)

(Kyösti)

Drop support for kernels below 2.4.9.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/*
2   -------------------------------------------------------------------------
3   i2c-adap-ibm_ocp.c i2c-hw access for the IIC peripheral on the IBM PPC 405
4   -------------------------------------------------------------------------
5 
6   Ian DaSilva, MontaVista Software, Inc.
7   idasilva@mvista.com or source@mvista.com
8
9   Copyright 2000 MontaVista Software Inc.
10
11   Changes made to support the IIC peripheral on the IBM PPC 405
12
13
14   ----------------------------------------------------------------------------
15   This file was highly leveraged from i2c-elektor.c, which was created
16   by Simon G. Vogl and Hans Berglund:
17
18 
19     Copyright (C) 1995-97 Simon G. Vogl
20                   1998-99 Hans Berglund
21
22   With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
23   Frodo Looijaard <frodol@dds.nl>
24
25
26    This program is free software; you can redistribute it and/or modify
27    it under the terms of the GNU General Public License as published by
28    the Free Software Foundation; either version 2 of the License, or
29    (at your option) any later version.
30
31    This program is distributed in the hope that it will be useful,
32    but WITHOUT ANY WARRANTY; without even the implied warranty of
33    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
34    GNU General Public License for more details.
35
36    You should have received a copy of the GNU General Public License
37    along with this program; if not, write to the Free Software
38    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
39   ----------------------------------------------------------------------------
40
41   History: 01/20/12 - Armin
42        akuster@mvista.com
43        ported up to 2.4.16+   
44
45   Version 02/03/25 - Armin
46       converted to ocp format
47       removed commented out or #if 0 code
48
49   TODO: convert to ocp_register
50         add PM hooks
51
52*/
53
54
55#include <linux/kernel.h>
56#include <linux/ioport.h>
57#include <linux/module.h>
58#include <linux/delay.h>
59#include <linux/slab.h>
60#include <linux/version.h>
61#include <linux/init.h>
62#include <asm/irq.h>
63#include <asm/io.h>
64#include <linux/i2c.h>
65#include <linux/i2c-algo-ibm_ocp.h>
66#include <linux/i2c-id.h>
67#include <asm/ocp.h>
68
69MODULE_LICENSE("GPL");
70
71/*
72 * This next section is configurable, and it is used to set the number
73 * of i2c controllers in the system.  The default number of instances is 1,
74 * however, this should be changed to reflect your system's configuration.
75 */ 
76
77/*
78 * The STB03xxx, with a PPC405 core, has two i2c controllers.
79 */
80//(sizeof(IIC_ADDR)/sizeof(struct iic_regs))
81extern iic_t *IIC_ADDR[];
82static struct iic_ibm iic_ibmocp_adaps[IIC_NUMS][5];
83
84static struct i2c_algo_iic_data *iic_ibmocp_data[IIC_NUMS];
85static struct i2c_adapter *iic_ibmocp_ops[IIC_NUMS];
86
87static int i2c_debug=0;
88static wait_queue_head_t iic_wait[IIC_NUMS];
89static int iic_pending;
90static spinlock_t irq_driver_lock = SPIN_LOCK_UNLOCKED;
91
92
93/* ----- global defines ----------------------------------------------- */
94#define DEB(x)  if (i2c_debug>=1) x
95#define DEB2(x) if (i2c_debug>=2) x
96#define DEB3(x) if (i2c_debug>=3) x
97#define DEBE(x) x       /* error messages                               */
98
99/* ----- local functions ---------------------------------------------- */
100
101//
102// Description: Write a byte to IIC hardware
103//
104static void iic_ibmocp_setbyte(void *data, int ctl, int val)
105{
106   // writeb resolves to a write to the specified memory location
107   // plus a call to eieio.  eieio ensures that all instructions
108   // preceding it are completed before any further stores are
109   // completed.
110   // Delays at this level (to protect writes) are not needed here.
111   writeb(val, ctl);
112}
113
114
115//
116// Description: Read a byte from IIC hardware
117//
118static int iic_ibmocp_getbyte(void *data, int ctl)
119{
120   int val;
121
122   val = readb(ctl);
123   return (val);
124}
125
126
127//
128// Description: Return our slave address.  This is the address
129// put on the I2C bus when another master on the bus wants to address us
130// as a slave
131//
132static int iic_ibmocp_getown(void *data)
133{
134   return(((struct iic_ibm *)(data))->iic_own);
135}
136
137
138//
139// Description: Return the clock rate
140//
141static int iic_ibmocp_getclock(void *data)
142{
143   return(((struct iic_ibm *)(data))->iic_clock);
144}
145
146
147#if 0
148static void iic_ibmocp_sleep(unsigned long timeout)
149{
150   schedule_timeout( timeout * HZ);
151}
152#endif
153
154
155//
156// Description:  Put this process to sleep.  We will wake up when the
157// IIC controller interrupts.
158//
159static void iic_ibmocp_waitforpin(void *data) {
160
161   int timeout = 2;
162   struct iic_ibm *priv_data = data;
163
164   //
165   // If interrupts are enabled (which they are), then put the process to
166   // sleep.  This process will be awakened by two events -- either the
167   // the IIC peripheral interrupts or the timeout expires.
168   //
169   if (priv_data->iic_irq > 0) {
170      spin_lock_irq(&irq_driver_lock);
171      if (iic_pending == 0) {
172         interruptible_sleep_on_timeout(&(iic_wait[priv_data->index]), timeout*HZ );
173      } else
174         iic_pending = 0;
175      spin_unlock_irq(&irq_driver_lock);
176   } else {
177      //
178      // If interrupts are not enabled then delay for a reasonable amount
179      // of time and return.  We expect that by time we return to the calling
180      // function that the IIC has finished our requested transaction and
181      // the status bit reflects this.
182      //
183      // udelay is probably not the best choice for this since it is
184      // the equivalent of a busy wait
185      //
186      udelay(100);
187   }
188   //printk("iic_ibmocp_waitforpin: exitting\n");
189}
190
191
192//
193// Description: The registered interrupt handler
194//
195static void iic_ibmocp_handler(int this_irq, void *dev_id, struct pt_regs *regs) 
196{
197   int ret;
198   struct iic_regs *iic;
199   struct iic_ibm *priv_data = dev_id;
200   iic = (struct iic_regs *) priv_data->iic_base;
201   iic_pending = 1;
202   DEB2(printk("iic_ibmocp_handler: in interrupt handler\n"));
203   // Read status register
204   ret = readb((int) &(iic->sts));
205   DEB2(printk("iic_ibmocp_handler: status = %x\n", ret));
206   // Clear status register.  See IBM PPC 405 reference manual for details
207   writeb(0x0a, (int) &(iic->sts));
208   wake_up_interruptible(&(iic_wait[priv_data->index]));
209}
210
211
212//
213// Description: This function is very hardware dependent.  First, we lock
214// the region of memory where out registers exist.  Next, we request our
215// interrupt line and register its associated handler.  Our IIC peripheral
216// uses interrupt number 2, as specified by the 405 reference manual.
217//
218static int iic_hw_resrc_init(int instance)
219{
220
221   DEB(printk("iic_hw_resrc_init: Physical Base address: 0x%x\n", (u32) IIC_ADDR[instance] ));
222   iic_ibmocp_adaps[instance]->iic_base = (u32)ioremap((unsigned long)IIC_ADDR[instance],PAGE_SIZE);
223
224   DEB(printk("iic_hw_resrc_init: ioremapped base address: 0x%x\n", iic_ibmocp_adaps[instance]->iic_base));
225
226   if (iic_ibmocp_adaps[instance]->iic_irq > 0) {
227       
228      if (request_irq(iic_ibmocp_adaps[instance]->iic_irq, iic_ibmocp_handler,
229       0, "IBM OCP IIC", iic_ibmocp_adaps[instance]) < 0) {
230         printk(KERN_ERR "iic_hw_resrc_init: Request irq%d failed\n",
231          iic_ibmocp_adaps[instance]->iic_irq);
232         iic_ibmocp_adaps[instance]->iic_irq = 0;
233      } else {
234         DEB3(printk("iic_hw_resrc_init: Enabled interrupt\n"));
235      }
236   }
237   return 0;
238}
239
240
241//
242// Description: Release irq and memory
243//
244static void iic_ibmocp_release(void)
245{
246   int i;
247
248   for(i=0; i<IIC_NUMS; i++) {
249      struct iic_ibm *priv_data = (struct iic_ibm *)iic_ibmocp_data[i]->data;
250      if (priv_data->iic_irq > 0) {
251         disable_irq(priv_data->iic_irq);
252         free_irq(priv_data->iic_irq, 0);
253      }
254      kfree(iic_ibmocp_data[i]);
255      kfree(iic_ibmocp_ops[i]);
256   }
257}
258
259
260//
261// Description: Does nothing
262//
263static int iic_ibmocp_reg(struct i2c_client *client)
264{
265        return 0;
266}
267
268
269//
270// Description: Does nothing
271//
272static int iic_ibmocp_unreg(struct i2c_client *client)
273{
274        return 0;
275}
276
277
278//
279// Description: If this compiled as a module, then increment the count
280//
281static void iic_ibmocp_inc_use(struct i2c_adapter *adap)
282{
283#ifdef MODULE
284        MOD_INC_USE_COUNT;
285#endif
286}
287
288
289//
290// Description: If this is a module, then decrement the count
291//
292static void iic_ibmocp_dec_use(struct i2c_adapter *adap)
293{
294#ifdef MODULE
295        MOD_DEC_USE_COUNT;
296#endif
297}
298
299//
300// Description: Called when the module is loaded.  This function starts the
301// cascade of calls up through the heirarchy of i2c modules (i.e. up to the
302//  algorithm layer and into to the core layer)
303//
304int __init iic_ibmocp_init(void) 
305{
306   int i;
307
308   printk(KERN_INFO "iic_ibmocp_init: IBM on-chip iic adapter module\n");
309 
310   for(i=0; i<IIC_NUMS; i++) {
311      iic_ibmocp_data[i] = kmalloc(sizeof(struct i2c_algo_iic_data),GFP_KERNEL);
312      if(iic_ibmocp_data[i] == NULL) {
313         return -ENOMEM;
314      }
315      memset(iic_ibmocp_data[i], 0, sizeof(struct i2c_algo_iic_data));
316     
317      switch (i) {
318              case 0:
319               iic_ibmocp_adaps[i]->iic_irq = IIC_IRQ(0);
320              break;
321              case 1:
322               iic_ibmocp_adaps[i]->iic_irq = IIC_IRQ(1);
323              break;
324      }
325      iic_ibmocp_adaps[i]->iic_clock = IIC_CLOCK;
326      iic_ibmocp_adaps[i]->iic_own = IIC_OWN; 
327      iic_ibmocp_adaps[i]->index = i;
328 
329      DEB(printk("irq %x\n", iic_ibmocp_adaps[i]->iic_irq));
330      DEB(printk("clock %x\n", iic_ibmocp_adaps[i]->iic_clock));
331      DEB(printk("own %x\n", iic_ibmocp_adaps[i]->iic_own));
332      DEB(printk("index %x\n", iic_ibmocp_adaps[i]->index));
333
334
335      iic_ibmocp_data[i]->data = (struct iic_regs *)iic_ibmocp_adaps[i]; 
336      iic_ibmocp_data[i]->setiic = iic_ibmocp_setbyte;
337      iic_ibmocp_data[i]->getiic = iic_ibmocp_getbyte;
338      iic_ibmocp_data[i]->getown = iic_ibmocp_getown;
339      iic_ibmocp_data[i]->getclock = iic_ibmocp_getclock;
340      iic_ibmocp_data[i]->waitforpin = iic_ibmocp_waitforpin;
341      iic_ibmocp_data[i]->udelay = 80;
342      iic_ibmocp_data[i]->mdelay = 80;
343      iic_ibmocp_data[i]->timeout = 100;
344     
345            iic_ibmocp_ops[i] = kmalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
346      if(iic_ibmocp_ops[i] == NULL) {
347         return -ENOMEM;
348      }
349      memset(iic_ibmocp_ops[i], 0, sizeof(struct i2c_adapter));
350      strcpy(iic_ibmocp_ops[i]->name, "IBM OCP IIC adapter");
351      iic_ibmocp_ops[i]->id = I2C_HW_OCP;
352      iic_ibmocp_ops[i]->algo = NULL;
353      iic_ibmocp_ops[i]->algo_data = iic_ibmocp_data[i];
354      iic_ibmocp_ops[i]->inc_use = iic_ibmocp_inc_use;
355      iic_ibmocp_ops[i]->dec_use = iic_ibmocp_dec_use;
356      iic_ibmocp_ops[i]->client_register = iic_ibmocp_reg;
357      iic_ibmocp_ops[i]->client_unregister = iic_ibmocp_unreg;
358       
359     
360      init_waitqueue_head(&(iic_wait[i]));
361      if (iic_hw_resrc_init(i) == 0) {
362         if (i2c_ocp_add_bus(iic_ibmocp_ops[i]) < 0)
363         return -ENODEV;
364      } else {
365         return -ENODEV;
366      }
367      DEB(printk(KERN_INFO "iic_ibmocp_init: found device at %#x.\n\n", iic_ibmocp_adaps[i]->iic_base));
368   }
369   return 0;
370}
371
372
373static void iic_ibmocp_exit(void)
374{
375   int i;
376
377   for(i=0; i<IIC_NUMS; i++) {
378      i2c_ocp_del_bus(iic_ibmocp_ops[i]);
379   }
380   iic_ibmocp_release();
381}
382
383EXPORT_NO_SYMBOLS;
384
385//
386// If modules is NOT defined when this file is compiled, then the MODULE_*
387// macros will resolve to nothing
388//
389MODULE_AUTHOR("MontaVista Software <www.mvista.com>");
390MODULE_DESCRIPTION("I2C-Bus adapter routines for PPC 405 IIC bus adapter");
391MODULE_PARM(base, "i");
392MODULE_PARM(irq, "i");
393MODULE_PARM(clock, "i");
394MODULE_PARM(own, "i");
395MODULE_PARM(i2c_debug,"i");
396
397
398module_init(iic_ibmocp_init);
399module_exit(iic_ibmocp_exit); 
Note: See TracBrowser for help on using the browser.