/* * drivers/i2c/chips/gpio_expander_davinci.c * * Author: Vladimir Barinov, MontaVista Software, Inc. <source@mvista.com> * * Copyright (C) 2006 Texas Instruments Inc * * 2007 (c) MontaVista Software, Inc. This file is licensed under * the terms of the GNU General Public License version 2. This program * is licensed "as is" without any warranty of any kind, whether express * or implied. */ #include <linux/types.h> #include <linux/i2c.h> #include <linux/errno.h> #include <linux/mutex.h> #include <asm/arch/i2c-client.h> static DEFINE_MUTEX(expander_lock); static int davinci_i2c_expander_read(u8 size, u8 * val, u16 addr) { struct i2c_adapter *adap; int err; struct i2c_msg msg[1]; adap = i2c_get_adapter(0); if (!adap) return -ENODEV; msg->addr = addr; msg->flags = I2C_M_RD; msg->len = size; msg->buf = val; err = i2c_transfer(adap, msg, 1); if (err >= 0) return 0; return err; } static int davinci_i2c_expander_write(u8 size, u8 * val, u16 addr) { struct i2c_adapter *adap; int err; struct i2c_msg msg[1]; adap = i2c_get_adapter(0); if (!adap) return -ENODEV; msg->addr = addr; msg->flags = 0; msg->len = size; msg->buf = val; err = i2c_transfer(adap, msg, 1); if (err >= 0) return 0; return err; } int davinci_i2c_expander_op(u16 client_addr, u35_expander_ops pin, u8 val) { int err = 0; char cmd[4] = { 4, 6, 0x00, 0x09 }; u8 data_to_u35 = 0; if (val > 1) return -1; mutex_lock(&expander_lock); err = davinci_i2c_expander_read(1, &data_to_u35, 0x3A); if (err < 0) return err; if (client_addr == 0x3A) { switch (pin) { case USB_DRVVBUS: if (val) data_to_u35 |= val; else data_to_u35 &= (val | 0xFE); break; case VDDIMX_EN: if (val) data_to_u35 |= (val << 1); else data_to_u35 &= (val | 0xFD); break; case VLYNQ_ON: if (val) data_to_u35 |= (val << 2); else data_to_u35 &= (val | 0xFB); break; case CF_RESET: if (val) data_to_u35 |= (val << 3); else data_to_u35 &= (val | 0xF7); break; case WLAN_RESET: if (val) data_to_u35 |= (val << 5); else data_to_u35 &= (val | 0xDF); break; case ATA_SEL: if (val) data_to_u35 |= (val << 6); else data_to_u35 &= (val | 0xBF); break; case CF_SEL: davinci_i2c_expander_write(4, cmd, 0x23); if (val) data_to_u35 |= (val << 7); else data_to_u35 &= (val | 0x7F); break; default: break; } } else { printk("Only IO Expander at address 0x3A is suuported\n"); mutex_unlock(&expander_lock); return -EINVAL; } err = davinci_i2c_expander_write(1, &data_to_u35, 0x3A); mutex_unlock(&expander_lock); return err; } EXPORT_SYMBOL(davinci_i2c_expander_op);