| 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 | |
|---|
| 69 | MODULE_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)) |
|---|
| 81 | extern iic_t *IIC_ADDR[]; |
|---|
| 82 | static struct iic_ibm iic_ibmocp_adaps[IIC_NUMS][5]; |
|---|
| 83 | |
|---|
| 84 | static struct i2c_algo_iic_data *iic_ibmocp_data[IIC_NUMS]; |
|---|
| 85 | static struct i2c_adapter *iic_ibmocp_ops[IIC_NUMS]; |
|---|
| 86 | |
|---|
| 87 | static int i2c_debug=0; |
|---|
| 88 | static wait_queue_head_t iic_wait[IIC_NUMS]; |
|---|
| 89 | static int iic_pending; |
|---|
| 90 | static 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 | // |
|---|
| 104 | static 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 | // |
|---|
| 118 | static 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 | // |
|---|
| 132 | static 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 | // |
|---|
| 141 | static int iic_ibmocp_getclock(void *data) |
|---|
| 142 | { |
|---|
| 143 | return(((struct iic_ibm *)(data))->iic_clock); |
|---|
| 144 | } |
|---|
| 145 | |
|---|
| 146 | |
|---|
| 147 | #if 0 |
|---|
| 148 | static 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 | // |
|---|
| 159 | static 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 | // |
|---|
| 195 | static 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 | // |
|---|
| 218 | static 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 | // |
|---|
| 244 | static 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 | // |
|---|
| 263 | static int iic_ibmocp_reg(struct i2c_client *client) |
|---|
| 264 | { |
|---|
| 265 | return 0; |
|---|
| 266 | } |
|---|
| 267 | |
|---|
| 268 | |
|---|
| 269 | // |
|---|
| 270 | // Description: Does nothing |
|---|
| 271 | // |
|---|
| 272 | static 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 | // |
|---|
| 281 | static 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 | // |
|---|
| 292 | static 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 | // |
|---|
| 304 | int __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 | |
|---|
| 373 | static 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 | |
|---|
| 383 | EXPORT_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 | // |
|---|
| 389 | MODULE_AUTHOR("MontaVista Software <www.mvista.com>"); |
|---|
| 390 | MODULE_DESCRIPTION("I2C-Bus adapter routines for PPC 405 IIC bus adapter"); |
|---|
| 391 | MODULE_PARM(base, "i"); |
|---|
| 392 | MODULE_PARM(irq, "i"); |
|---|
| 393 | MODULE_PARM(clock, "i"); |
|---|
| 394 | MODULE_PARM(own, "i"); |
|---|
| 395 | MODULE_PARM(i2c_debug,"i"); |
|---|
| 396 | |
|---|
| 397 | |
|---|
| 398 | module_init(iic_ibmocp_init); |
|---|
| 399 | module_exit(iic_ibmocp_exit); |
|---|