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

Revision 3758, 10.8 KB (checked in by kmalkki, 10 years ago)

(Kyösti)

Check in changes from 2.5.53 to 2.5.54).
Apply respective changes to other drivers in CVS.

  • 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//
280// Description: Called when the module is loaded.  This function starts the
281// cascade of calls up through the heirarchy of i2c modules (i.e. up to the
282//  algorithm layer and into to the core layer)
283//
284int __init iic_ibmocp_init(void) 
285{
286   int i;
287
288   printk(KERN_INFO "iic_ibmocp_init: IBM on-chip iic adapter module\n");
289 
290   for(i=0; i<IIC_NUMS; i++) {
291      iic_ibmocp_data[i] = kmalloc(sizeof(struct i2c_algo_iic_data),GFP_KERNEL);
292      if(iic_ibmocp_data[i] == NULL) {
293         return -ENOMEM;
294      }
295      memset(iic_ibmocp_data[i], 0, sizeof(struct i2c_algo_iic_data));
296     
297      switch (i) {
298              case 0:
299               iic_ibmocp_adaps[i]->iic_irq = IIC_IRQ(0);
300              break;
301              case 1:
302               iic_ibmocp_adaps[i]->iic_irq = IIC_IRQ(1);
303              break;
304      }
305      iic_ibmocp_adaps[i]->iic_clock = IIC_CLOCK;
306      iic_ibmocp_adaps[i]->iic_own = IIC_OWN; 
307      iic_ibmocp_adaps[i]->index = i;
308 
309      DEB(printk("irq %x\n", iic_ibmocp_adaps[i]->iic_irq));
310      DEB(printk("clock %x\n", iic_ibmocp_adaps[i]->iic_clock));
311      DEB(printk("own %x\n", iic_ibmocp_adaps[i]->iic_own));
312      DEB(printk("index %x\n", iic_ibmocp_adaps[i]->index));
313
314
315      iic_ibmocp_data[i]->data = (struct iic_regs *)iic_ibmocp_adaps[i]; 
316      iic_ibmocp_data[i]->setiic = iic_ibmocp_setbyte;
317      iic_ibmocp_data[i]->getiic = iic_ibmocp_getbyte;
318      iic_ibmocp_data[i]->getown = iic_ibmocp_getown;
319      iic_ibmocp_data[i]->getclock = iic_ibmocp_getclock;
320      iic_ibmocp_data[i]->waitforpin = iic_ibmocp_waitforpin;
321      iic_ibmocp_data[i]->udelay = 80;
322      iic_ibmocp_data[i]->mdelay = 80;
323      iic_ibmocp_data[i]->timeout = 100;
324     
325            iic_ibmocp_ops[i] = kmalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
326      if(iic_ibmocp_ops[i] == NULL) {
327         return -ENOMEM;
328      }
329      memset(iic_ibmocp_ops[i], 0, sizeof(struct i2c_adapter));
330      strcpy(iic_ibmocp_ops[i]->name, "IBM OCP IIC adapter");
331      iic_ibmocp_ops[i]->id = I2C_HW_OCP;
332      iic_ibmocp_ops[i]->algo = NULL;
333      iic_ibmocp_ops[i]->algo_data = iic_ibmocp_data[i];
334      iic_ibmocp_ops[i]->inc_use = iic_ibmocp_inc_use;
335      iic_ibmocp_ops[i]->dec_use = iic_ibmocp_dec_use;
336      iic_ibmocp_ops[i]->client_register = iic_ibmocp_reg;
337      iic_ibmocp_ops[i]->client_unregister = iic_ibmocp_unreg;
338       
339     
340      init_waitqueue_head(&(iic_wait[i]));
341      if (iic_hw_resrc_init(i) == 0) {
342         if (i2c_ocp_add_bus(iic_ibmocp_ops[i]) < 0)
343         return -ENODEV;
344      } else {
345         return -ENODEV;
346      }
347      DEB(printk(KERN_INFO "iic_ibmocp_init: found device at %#x.\n\n", iic_ibmocp_adaps[i]->iic_base));
348   }
349   return 0;
350}
351
352
353static void iic_ibmocp_exit(void)
354{
355   int i;
356
357   for(i=0; i<IIC_NUMS; i++) {
358      i2c_ocp_del_bus(iic_ibmocp_ops[i]);
359   }
360   iic_ibmocp_release();
361}
362
363EXPORT_NO_SYMBOLS;
364
365//
366// If modules is NOT defined when this file is compiled, then the MODULE_*
367// macros will resolve to nothing
368//
369MODULE_AUTHOR("MontaVista Software <www.mvista.com>");
370MODULE_DESCRIPTION("I2C-Bus adapter routines for PPC 405 IIC bus adapter");
371MODULE_PARM(base, "i");
372MODULE_PARM(irq, "i");
373MODULE_PARM(clock, "i");
374MODULE_PARM(own, "i");
375MODULE_PARM(i2c_debug,"i");
376
377
378module_init(iic_ibmocp_init);
379module_exit(iic_ibmocp_exit); 
Note: See TracBrowser for help on using the browser.