diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-ite.c')
-rw-r--r-- | drivers/i2c/busses/i2c-ite.c | 282 |
1 files changed, 282 insertions, 0 deletions
diff --git a/drivers/i2c/busses/i2c-ite.c b/drivers/i2c/busses/i2c-ite.c new file mode 100644 index 000000000000..702e3def1b81 --- /dev/null +++ b/drivers/i2c/busses/i2c-ite.c | |||
@@ -0,0 +1,282 @@ | |||
1 | /* | ||
2 | ------------------------------------------------------------------------- | ||
3 | i2c-adap-ite.c i2c-hw access for the IIC peripheral on the ITE MIPS system | ||
4 | ------------------------------------------------------------------------- | ||
5 | Hai-Pao Fan, MontaVista Software, Inc. | ||
6 | hpfan@mvista.com or source@mvista.com | ||
7 | |||
8 | Copyright 2001 MontaVista Software Inc. | ||
9 | |||
10 | ---------------------------------------------------------------------------- | ||
11 | This file was highly leveraged from i2c-elektor.c, which was created | ||
12 | by Simon G. Vogl and Hans Berglund: | ||
13 | |||
14 | |||
15 | Copyright (C) 1995-97 Simon G. Vogl | ||
16 | 1998-99 Hans Berglund | ||
17 | |||
18 | This program is free software; you can redistribute it and/or modify | ||
19 | it under the terms of the GNU General Public License as published by | ||
20 | the Free Software Foundation; either version 2 of the License, or | ||
21 | (at your option) any later version. | ||
22 | |||
23 | This program is distributed in the hope that it will be useful, | ||
24 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
25 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
26 | GNU General Public License for more details. | ||
27 | |||
28 | You should have received a copy of the GNU General Public License | ||
29 | along with this program; if not, write to the Free Software | ||
30 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ | ||
31 | /* ------------------------------------------------------------------------- */ | ||
32 | |||
33 | /* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even | ||
34 | Frodo Looijaard <frodol@dds.nl> */ | ||
35 | |||
36 | #include <linux/config.h> | ||
37 | #include <linux/kernel.h> | ||
38 | #include <linux/ioport.h> | ||
39 | #include <linux/module.h> | ||
40 | #include <linux/delay.h> | ||
41 | #include <linux/slab.h> | ||
42 | #include <linux/init.h> | ||
43 | #include <linux/wait.h> | ||
44 | #include <asm/irq.h> | ||
45 | #include <asm/io.h> | ||
46 | |||
47 | #include <linux/i2c.h> | ||
48 | #include <linux/i2c-algo-ite.h> | ||
49 | #include <linux/i2c-adap-ite.h> | ||
50 | #include "../i2c-ite.h" | ||
51 | |||
52 | #define DEFAULT_BASE 0x14014030 | ||
53 | #define ITE_IIC_IO_SIZE 0x40 | ||
54 | #define DEFAULT_IRQ 0 | ||
55 | #define DEFAULT_CLOCK 0x1b0e /* default 16MHz/(27+14) = 400KHz */ | ||
56 | #define DEFAULT_OWN 0x55 | ||
57 | |||
58 | static int base; | ||
59 | static int irq; | ||
60 | static int clock; | ||
61 | static int own; | ||
62 | |||
63 | static struct iic_ite gpi; | ||
64 | static wait_queue_head_t iic_wait; | ||
65 | static int iic_pending; | ||
66 | static spinlock_t lock; | ||
67 | |||
68 | /* ----- local functions ---------------------------------------------- */ | ||
69 | |||
70 | static void iic_ite_setiic(void *data, int ctl, short val) | ||
71 | { | ||
72 | unsigned long j = jiffies + 10; | ||
73 | |||
74 | pr_debug(" Write 0x%02x to 0x%x\n",(unsigned short)val, ctl&0xff); | ||
75 | #ifdef DEBUG | ||
76 | while (time_before(jiffies, j)) | ||
77 | schedule(); | ||
78 | #endif | ||
79 | outw(val,ctl); | ||
80 | } | ||
81 | |||
82 | static short iic_ite_getiic(void *data, int ctl) | ||
83 | { | ||
84 | short val; | ||
85 | |||
86 | val = inw(ctl); | ||
87 | pr_debug("Read 0x%02x from 0x%x\n",(unsigned short)val, ctl&0xff); | ||
88 | return (val); | ||
89 | } | ||
90 | |||
91 | /* Return our slave address. This is the address | ||
92 | * put on the I2C bus when another master on the bus wants to address us | ||
93 | * as a slave | ||
94 | */ | ||
95 | static int iic_ite_getown(void *data) | ||
96 | { | ||
97 | return (gpi.iic_own); | ||
98 | } | ||
99 | |||
100 | |||
101 | static int iic_ite_getclock(void *data) | ||
102 | { | ||
103 | return (gpi.iic_clock); | ||
104 | } | ||
105 | |||
106 | |||
107 | /* Put this process to sleep. We will wake up when the | ||
108 | * IIC controller interrupts. | ||
109 | */ | ||
110 | static void iic_ite_waitforpin(void) { | ||
111 | DEFINE_WAIT(wait); | ||
112 | int timeout = 2; | ||
113 | long flags; | ||
114 | |||
115 | /* If interrupts are enabled (which they are), then put the process to | ||
116 | * sleep. This process will be awakened by two events -- either the | ||
117 | * the IIC peripheral interrupts or the timeout expires. | ||
118 | * If interrupts are not enabled then delay for a reasonable amount | ||
119 | * of time and return. | ||
120 | */ | ||
121 | if (gpi.iic_irq > 0) { | ||
122 | spin_lock_irqsave(&lock, flags); | ||
123 | if (iic_pending == 0) { | ||
124 | spin_unlock_irqrestore(&lock, flags); | ||
125 | prepare_to_wait(&iic_wait, &wait, TASK_INTERRUPTIBLE); | ||
126 | if (schedule_timeout(timeout*HZ)) { | ||
127 | spin_lock_irqsave(&lock, flags); | ||
128 | if (iic_pending == 1) { | ||
129 | iic_pending = 0; | ||
130 | } | ||
131 | spin_unlock_irqrestore(&lock, flags); | ||
132 | } | ||
133 | finish_wait(&iic_wait, &wait); | ||
134 | } else { | ||
135 | iic_pending = 0; | ||
136 | spin_unlock_irqrestore(&lock, flags); | ||
137 | } | ||
138 | } else { | ||
139 | udelay(100); | ||
140 | } | ||
141 | } | ||
142 | |||
143 | |||
144 | static irqreturn_t iic_ite_handler(int this_irq, void *dev_id, | ||
145 | struct pt_regs *regs) | ||
146 | { | ||
147 | spin_lock(&lock); | ||
148 | iic_pending = 1; | ||
149 | spin_unlock(&lock); | ||
150 | |||
151 | wake_up_interruptible(&iic_wait); | ||
152 | |||
153 | return IRQ_HANDLED; | ||
154 | } | ||
155 | |||
156 | |||
157 | /* Lock the region of memory where I/O registers exist. Request our | ||
158 | * interrupt line and register its associated handler. | ||
159 | */ | ||
160 | static int iic_hw_resrc_init(void) | ||
161 | { | ||
162 | if (!request_region(gpi.iic_base, ITE_IIC_IO_SIZE, "i2c")) | ||
163 | return -ENODEV; | ||
164 | |||
165 | if (gpi.iic_irq <= 0) | ||
166 | return 0; | ||
167 | |||
168 | if (request_irq(gpi.iic_irq, iic_ite_handler, 0, "ITE IIC", 0) < 0) | ||
169 | gpi.iic_irq = 0; | ||
170 | else | ||
171 | enable_irq(gpi.iic_irq); | ||
172 | |||
173 | return 0; | ||
174 | } | ||
175 | |||
176 | |||
177 | static void iic_ite_release(void) | ||
178 | { | ||
179 | if (gpi.iic_irq > 0) { | ||
180 | disable_irq(gpi.iic_irq); | ||
181 | free_irq(gpi.iic_irq, 0); | ||
182 | } | ||
183 | release_region(gpi.iic_base , 2); | ||
184 | } | ||
185 | |||
186 | /* ------------------------------------------------------------------------ | ||
187 | * Encapsulate the above functions in the correct operations structure. | ||
188 | * This is only done when more than one hardware adapter is supported. | ||
189 | */ | ||
190 | static struct i2c_algo_iic_data iic_ite_data = { | ||
191 | NULL, | ||
192 | iic_ite_setiic, | ||
193 | iic_ite_getiic, | ||
194 | iic_ite_getown, | ||
195 | iic_ite_getclock, | ||
196 | iic_ite_waitforpin, | ||
197 | 80, 80, 100, /* waits, timeout */ | ||
198 | }; | ||
199 | |||
200 | static struct i2c_adapter iic_ite_ops = { | ||
201 | .owner = THIS_MODULE, | ||
202 | .id = I2C_HW_I_IIC, | ||
203 | .algo_data = &iic_ite_data, | ||
204 | .dev = { | ||
205 | .name = "ITE IIC adapter", | ||
206 | }, | ||
207 | }; | ||
208 | |||
209 | /* Called when the module is loaded. This function starts the | ||
210 | * cascade of calls up through the hierarchy of i2c modules (i.e. up to the | ||
211 | * algorithm layer and into to the core layer) | ||
212 | */ | ||
213 | static int __init iic_ite_init(void) | ||
214 | { | ||
215 | |||
216 | struct iic_ite *piic = &gpi; | ||
217 | |||
218 | printk(KERN_INFO "Initialize ITE IIC adapter module\n"); | ||
219 | if (base == 0) | ||
220 | piic->iic_base = DEFAULT_BASE; | ||
221 | else | ||
222 | piic->iic_base = base; | ||
223 | |||
224 | if (irq == 0) | ||
225 | piic->iic_irq = DEFAULT_IRQ; | ||
226 | else | ||
227 | piic->iic_irq = irq; | ||
228 | |||
229 | if (clock == 0) | ||
230 | piic->iic_clock = DEFAULT_CLOCK; | ||
231 | else | ||
232 | piic->iic_clock = clock; | ||
233 | |||
234 | if (own == 0) | ||
235 | piic->iic_own = DEFAULT_OWN; | ||
236 | else | ||
237 | piic->iic_own = own; | ||
238 | |||
239 | iic_ite_data.data = (void *)piic; | ||
240 | init_waitqueue_head(&iic_wait); | ||
241 | spin_lock_init(&lock); | ||
242 | if (iic_hw_resrc_init() == 0) { | ||
243 | if (i2c_iic_add_bus(&iic_ite_ops) < 0) | ||
244 | return -ENODEV; | ||
245 | } else { | ||
246 | return -ENODEV; | ||
247 | } | ||
248 | printk(KERN_INFO " found device at %#x irq %d.\n", | ||
249 | piic->iic_base, piic->iic_irq); | ||
250 | return 0; | ||
251 | } | ||
252 | |||
253 | |||
254 | static void iic_ite_exit(void) | ||
255 | { | ||
256 | i2c_iic_del_bus(&iic_ite_ops); | ||
257 | iic_ite_release(); | ||
258 | } | ||
259 | |||
260 | /* If modules is NOT defined when this file is compiled, then the MODULE_* | ||
261 | * macros will resolve to nothing | ||
262 | */ | ||
263 | MODULE_AUTHOR("MontaVista Software <www.mvista.com>"); | ||
264 | MODULE_DESCRIPTION("I2C-Bus adapter routines for ITE IIC bus adapter"); | ||
265 | MODULE_LICENSE("GPL"); | ||
266 | |||
267 | module_param(base, int, 0); | ||
268 | module_param(irq, int, 0); | ||
269 | module_param(clock, int, 0); | ||
270 | module_param(own, int, 0); | ||
271 | |||
272 | |||
273 | /* Called when module is loaded or when kernel is initialized. | ||
274 | * If MODULES is defined when this file is compiled, then this function will | ||
275 | * resolve to init_module (the function called when insmod is invoked for a | ||
276 | * module). Otherwise, this function is called early in the boot, when the | ||
277 | * kernel is intialized. Check out /include/init.h to see how this works. | ||
278 | */ | ||
279 | module_init(iic_ite_init); | ||
280 | |||
281 | /* Resolves to module_cleanup when MODULES is defined. */ | ||
282 | module_exit(iic_ite_exit); | ||