diff --git a/drivers/i2c/busses/i2c-dev-rk29.c b/drivers/i2c/busses/i2c-dev-rk29.c deleted file mode 100755 index 1d9d922d1c60..000000000000 --- a/drivers/i2c/busses/i2c-dev-rk29.c +++ /dev/null @@ -1,398 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include - -#include "i2c-dev-rk29.h" -#include "../i2c-core.h" - - -#define I2C_DEV_SCL_RATE 100 * 1000 - -struct completion i2c_dev_complete = { - .done = -1, -}; -struct i2c_dump_info g_dump; - -static void i2c_dev_get_list(struct i2c_list_info *list) -{ - struct i2c_devinfo *devinfo; - struct i2c_adapter *adap = NULL; - int index; - - memset(list, 0, sizeof(struct i2c_list_info)); - - down_read(&__i2c_board_lock); - list_for_each_entry(devinfo, &__i2c_board_list, list) { - if(devinfo->busnum >= MAX_I2C_BUS) { - list->adap_nr = -1; - up_read(&__i2c_board_lock); - return; - } - adap = i2c_get_adapter(devinfo->busnum); - if(adap != NULL) { - list->adap[devinfo->busnum].id = adap->nr; - strcpy(list->adap[devinfo->busnum].name, adap->name); - - index = list->adap[devinfo->busnum].client_nr++; - if(index >= MAX_CLIENT_NUM || index == -1) - list->adap[devinfo->busnum].client_nr = -1; - else { - list->adap[devinfo->busnum].client[index].addr = devinfo->board_info.addr; - strcpy(list->adap[devinfo->busnum].client[index].name, - devinfo->board_info.type); - } - } - } - list->adap_nr = MAX_I2C_BUS; - up_read(&__i2c_board_lock); - return; -} -void i2c_dev_dump_start(struct i2c_adapter *adap, struct i2c_msg *msgs, int num) -{ - int i, j; - - memset(&g_dump, 0, sizeof(struct i2c_dump_info)); - g_dump.id = adap->nr; - g_dump.addr = msgs[0].addr; - - for(i = 0; i < num; i++) { - if(msgs[i].flags & I2C_M_RD) { - if(msgs[i].len >= MAX_VALUE_NUM) - g_dump.get_num = -1; - else - g_dump.get_num = msgs[i].len; - } - else { - if(msgs[i].len >= MAX_VALUE_NUM) - g_dump.set_num = -1; - else { - g_dump.set_num = msgs[i].len; - for(j = 0; j < msgs[i].len; j++) - g_dump.set_value[j] = msgs[i].buf[j]; - } - } - } - return; -} -EXPORT_SYMBOL(i2c_dev_dump_start); - -void i2c_dev_dump_stop(struct i2c_adapter *adap, struct i2c_msg *msgs, int num, int ret) -{ - int i, j; - - if(ret < 0) { - g_dump.get_num = 0; - g_dump.set_num = 0; - } - for(i = 0; i < num; i++) { - if((msgs[i].flags & I2C_M_RD) && (g_dump.get_num > 0)) { - for(j = 0; j < msgs[i].len; j++) - g_dump.get_value[j] = msgs[i].buf[j]; - } - } - if(i2c_dev_complete.done == 0) - complete(&i2c_dev_complete); - return; -} -EXPORT_SYMBOL(i2c_dev_dump_stop); - -static void i2c_dev_get_dump(struct i2c_dump_info *dump) -{ - init_completion(&i2c_dev_complete); - wait_for_completion_killable(&i2c_dev_complete); - *dump = g_dump; - return; -} -static int i2c_dev_get_normal(struct i2c_adapter *adap, struct i2c_get_info *get) -{ - struct i2c_msg msg; - char buf[MAX_VALUE_NUM]; - int ret, i; - - msg.addr = (__u16)get->addr; - msg.flags = I2C_M_RD; - msg.len = get->num; - msg.buf = buf; - msg.scl_rate = I2C_DEV_SCL_RATE; - - ret = i2c_transfer(adap, &msg, 1); - if(ret == 1) { - for(i = 0; i < get->num; i++) - get->value[i] = buf[i]; - return 0; - } - else - return -1; -} -static int i2c_dev_set_normal(struct i2c_adapter *adap, struct i2c_set_info *set) -{ - struct i2c_msg msg; - char buf[MAX_VALUE_NUM]; - int ret; - - msg.addr = (__u16)set->addr; - msg.flags = 0; - msg.len = set->num; - msg.buf = buf; - msg.scl_rate = I2C_DEV_SCL_RATE; - - ret = i2c_transfer(adap, &msg, 1); - return(ret == 1)? 0: -1; -} -static int i2c_dev_get_reg8(struct i2c_adapter *adap, struct i2c_get_info *get) -{ - int ret, i; - struct i2c_msg msgs[2]; - char reg = get->reg; - char buf[MAX_VALUE_NUM]; - - msgs[0].addr = (__u16)get->addr; - msgs[0].flags = 0; - msgs[0].len = 1; - msgs[0].buf = ® - msgs[0].scl_rate = I2C_DEV_SCL_RATE; - - msgs[1].addr = get->addr; - msgs[1].flags = I2C_M_RD; - msgs[1].len = get->num; - msgs[1].buf = buf; - msgs[1].scl_rate = I2C_DEV_SCL_RATE; - - ret = i2c_transfer(adap, msgs, 2); - if(ret == 2) { - for(i = 0; i < get->num; i++) - get->value[i] = buf[i]; - return 0; - } - else - return -1; - -} - -static int i2c_dev_set_reg8(struct i2c_adapter *adap, struct i2c_set_info *set) -{ - int ret, i; - struct i2c_msg msg; - char buf[MAX_VALUE_NUM + 1]; - - buf[0] = (char)set->reg; - for(i = 0; i < set->num; i++) - buf[i+1] = (char)set->value[i]; - - msg.addr = (__u16)set->addr; - msg.flags = 0; - msg.len = set->num + 1; - msg.buf = buf; - msg.scl_rate = I2C_DEV_SCL_RATE; - - - ret = i2c_transfer(adap, &msg, 1); - return (ret == 1)? 0: -1; -} - -static int i2c_dev_get_reg16(struct i2c_adapter *adap, struct i2c_get_info *get) -{ - int ret, i; - struct i2c_msg msgs[2]; - char reg[2]; - char buf[MAX_VALUE_NUM * 2]; - - reg[0] = (char)(get->reg & 0xff); - reg[1] = (char)((get->reg >>8) & 0xff); - - msgs[0].addr = (__u16)get->addr; - msgs[0].flags = 0; - msgs[0].len = 2; - msgs[0].buf = reg; - msgs[0].scl_rate = I2C_DEV_SCL_RATE; - - msgs[1].addr = get->addr; - msgs[1].flags = I2C_M_RD; - msgs[1].len = get->num * 2; - msgs[1].buf = buf; - msgs[1].scl_rate = I2C_DEV_SCL_RATE; - - ret = i2c_transfer(adap, msgs, 2); - if(ret == 2) { - for(i = 0; i < get->num; i++) - get->value[i] = buf[2*i] & (buf[2*i+1]<<8); - return 0; - } - else - return -1; - -} -static int i2c_dev_set_reg16(struct i2c_adapter *adap, struct i2c_set_info *set) -{ - struct i2c_msg msg; - int ret, i; - char buf[2 * (MAX_VALUE_NUM + 1)]; - - buf[0] = (char)(set->reg & 0xff); - buf[1] = (char)((set->reg >>8) & 0xff); - - for(i = 0; i < set->num; i++) { - buf[2 * (i + 1)] = (char)(set->value[i] & 0xff); - buf[2 * (i + 1) + 1] = (char)((set->value[i]>>8) & 0xff); - } - - msg.addr = set->addr; - msg.flags = 0; - msg.len = 2 * (set->num + 1); - msg.buf = buf; - msg.scl_rate = I2C_DEV_SCL_RATE; - - ret = i2c_transfer(adap, &msg, 1); - return (ret == 1)? 0: -1; -} - -static int i2c_dev_get_value(struct i2c_get_info *get) -{ - int ret = 0; - struct i2c_adapter *adap = NULL; - - if(get->num > MAX_VALUE_NUM) - return -1; - adap = i2c_get_adapter(get->id); - if(adap == NULL) - return -1; - switch(get->mode) { - case 'b': - ret = i2c_dev_get_reg8(adap, get); - break; - case 's': - ret = i2c_dev_get_reg16(adap, get); - break; - case 'o': - ret = -1; - break; - default: - ret = i2c_dev_get_normal(adap, get); - break; - } - return ret; -} - -static int i2c_dev_set_value(struct i2c_set_info *set) -{ - int ret = 0; - struct i2c_adapter *adap = NULL; - - printk("id=%d, addr=0x%x, mode = %c, num = %d, reg = 0x%x, value[0] = %d,",set->id, set->addr, set->mode, set->num, set->reg, set->value[0]); - if(set->num > MAX_VALUE_NUM) - return -1; - adap = i2c_get_adapter(set->id); - if(adap == NULL) - return -1; - switch(set->mode) { - case 'b': - ret = i2c_dev_set_reg8(adap, set); - break; - case 's': - ret = i2c_dev_set_reg16(adap, set); - break; - case 'o': - ret = -1; - break; - default: - ret = i2c_dev_set_normal(adap, set); - break; - } - return ret; -} - -static int i2c_dev_open(struct inode *inode, struct file *file) -{ - return 0; -} -static long i2c_dev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) -{ - int ret = 0; - struct i2c_list_info *list = NULL; - struct i2c_dump_info dump; - struct i2c_get_info get; - struct i2c_set_info set; - - switch(cmd) { - case I2C_LIST: - list = kzalloc(sizeof(struct i2c_list_info), GFP_KERNEL); - if(list == NULL) { - ret = -ENOMEM; - break; - } - i2c_dev_get_list(list); - if(copy_to_user((void __user *)arg, (void *)list, sizeof(struct i2c_list_info))) - ret = -EFAULT; - kfree(list); - break; - case I2C_DUMP: - i2c_dev_get_dump(&dump); - if(copy_to_user((void __user *)arg, (void *)&dump, sizeof(struct i2c_dump_info))) - ret = -EFAULT; - break; - case I2C_GET: - if(copy_from_user((void *)&get, (void __user *)arg, sizeof(struct i2c_get_info))) { - ret = -EFAULT; - break; - } - if(i2c_dev_get_value(&get) < 0) { - ret = -EFAULT; - break; - } - if(copy_to_user((void __user *)arg, (void *)&get, sizeof(struct i2c_get_info))) - ret = -EFAULT; - break; - case I2C_SET: - if(copy_from_user((void *)&set, (void __user *)arg, sizeof(struct i2c_set_info))) { - ret = -EFAULT; - break; - } - ret = i2c_dev_set_value(&set); - break; - default: - break; - } - return ret; -} -static int i2c_dev_release(struct inode *inode, struct file *file) -{ - return 0; -} - -static struct file_operations i2c_dev_fops = { - .owner = THIS_MODULE, - .open = i2c_dev_open, - .unlocked_ioctl = i2c_dev_ioctl, - .release = i2c_dev_release, -}; -static struct miscdevice i2c_misc_dev = { - .minor = MISC_DYNAMIC_MINOR, - .name = I2C_DEV_NAME, - .fops = &i2c_dev_fops, -}; -static int __init i2c_dev_init(void) -{ - return misc_register(&i2c_misc_dev); -} -static void __exit i2c_dev_exit(void) -{ - misc_deregister(&i2c_misc_dev); -} -module_init(i2c_dev_init); -module_exit(i2c_dev_exit); - -MODULE_DESCRIPTION("Driver for RK29 I2C Device"); -MODULE_AUTHOR("kfx, kfx@rock-chips.com"); -MODULE_LICENSE("GPL"); - diff --git a/drivers/i2c/busses/i2c-dev-rk29.h b/drivers/i2c/busses/i2c-dev-rk29.h deleted file mode 100755 index 086c937ffc4a..000000000000 --- a/drivers/i2c/busses/i2c-dev-rk29.h +++ /dev/null @@ -1,62 +0,0 @@ -#ifndef _I2C_DEV_H -#define _I2C_DEV_H - -#define I2C_DEV_NAME "i2c-dev" -#define I2C_DEV_PATH "/dev/"I2C_DEV_NAME - -#define MAX_ADAP_LENG 48 -#define MAX_CLIENT_LENG 20 -#define MAX_VALUE_NUM 16 -#define MAX_I2C_BUS 4 -#define MAX_CLIENT_NUM 32 - - - -#define I2C_LIST 0X7000 -#define I2C_DUMP 0x7010 -#define I2C_GET 0x7020 -#define I2C_SET 0x7030 - - -struct i2c_client_info { - int addr; - char name[MAX_CLIENT_LENG]; -}; -struct i2c_adap_info { - int id; - char name[MAX_ADAP_LENG]; - int client_nr; - struct i2c_client_info client[MAX_CLIENT_NUM]; -}; -struct i2c_list_info { - int adap_nr; - struct i2c_adap_info adap[MAX_I2C_BUS]; -}; - -struct i2c_dump_info { - int id; - int addr; - int get_num; - int get_value[MAX_VALUE_NUM]; - int set_num; - int set_value[MAX_VALUE_NUM]; -}; - -struct i2c_get_info { - char mode; - int id; - int addr; - int reg; - int num; - int value[MAX_VALUE_NUM]; -}; -struct i2c_set_info { - char mode; - int id; - int addr; - int reg; - int num; - int value[MAX_VALUE_NUM]; -}; - -#endif /* _I2CDEV_H */ diff --git a/drivers/i2c/busses/i2c-rk29-adapter.c b/drivers/i2c/busses/i2c-rk29-adapter.c deleted file mode 100755 index 726c8241d805..000000000000 --- a/drivers/i2c/busses/i2c-rk29-adapter.c +++ /dev/null @@ -1,598 +0,0 @@ -/* drivers/i2c/busses/i2c-rk29-adapter.c - * - * Copyright (C) 2012 ROCKCHIP, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ -#include "i2c-rk30.h" - -/* master transmit */ -#define I2C_MTXR (0x0000) -/* master receive */ -#define I2C_MRXR (0x0004) -/* slave address */ -#define I2C_SADDR (0x0010) -/* interrupt enable control */ -#define I2C_IER (0x0014) -#define I2C_IER_ARBITR_LOSE (1<<7) -#define I2C_IER_MRX_NEED_ACK (1<<1) -#define I2C_IER_MTX_RCVD_ACK (1<<0) - -#define IRQ_MST_ENABLE (I2C_IER_ARBITR_LOSE | \ - I2C_IER_MRX_NEED_ACK | \ - I2C_IER_MTX_RCVD_ACK) -#define IRQ_ALL_DISABLE (0x00) - -/* interrupt status, write 0 to clear */ -#define I2C_ISR (0x0018) -#define I2C_ISR_ARBITR_LOSE (1<<7) -#define I2C_ISR_MRX_NEED_ACK (1<<1) -#define I2C_ISR_MTX_RCVD_ACK (1<<0) - -/* stop/start/resume command, write 1 to set */ -#define I2C_LCMR (0x001c) -#define I2C_LCMR_RESUME (1<<2) -#define I2C_LCMR_STOP (1<<1) -#define I2C_LCMR_START (1<<0) - -/* i2c core status */ -#define I2C_LSR (0x0020) -#define I2C_LSR_RCV_NAK (1<<1) -#define I2C_LSR_RCV_ACK (~(1<<1)) -#define I2C_LSR_BUSY (1<<0) - -/* i2c config */ -#define I2C_CONR (0x0024) -#define I2C_CONR_NAK (1<<4) -#define I2C_CONR_ACK (~(1<<4)) -#define I2C_CONR_MTX_MODE (1<<3) -#define I2C_CONR_MRX_MODE (~(1<<3)) -#define I2C_CONR_MPORT_ENABLE (1<<2) -#define I2C_CONR_MPORT_DISABLE (~(1<<2)) - -/* i2c core config */ -#define I2C_OPR (0x0028) -#define I2C_OPR_RESET_STATUS (1<<7) -#define I2C_OPR_CORE_ENABLE (1<<6) - -#define I2CCDVR_REM_BITS (0x03) -#define I2CCDVR_REM_MAX (1<<(I2CCDVR_REM_BITS)) -#define I2CCDVR_EXP_BITS (0x03) -#define I2CCDVR_EXP_MAX (1<<(I2CCDVR_EXP_BITS)) - - -#define RK29_I2C_START_TMO_COUNT 100 // msleep 1 * 100 - -int i2c_suspended(struct i2c_adapter *adap) -{ - return 1; -} -EXPORT_SYMBOL(i2c_suspended); - -static inline void rk29_i2c_disable_ack(struct rk30_i2c *i2c) -{ - unsigned long conr = readl(i2c->regs + I2C_CONR); - - conr |= I2C_CONR_NAK; - writel(conr,i2c->regs + I2C_CONR); -} - -static inline void rk29_i2c_enable_ack(struct rk30_i2c *i2c) -{ - unsigned long conr = readl(i2c->regs + I2C_CONR); - - conr &= I2C_CONR_ACK; - writel(conr,i2c->regs + I2C_CONR); -} -static inline void rk29_i2c_disable_mport(struct rk30_i2c *i2c) -{ - unsigned long conr = readl(i2c->regs + I2C_CONR); - - conr &= I2C_CONR_MPORT_DISABLE; - writel(conr,i2c->regs + I2C_CONR); -} - -static inline void rk29_i2c_enable_mport(struct rk30_i2c *i2c) -{ - unsigned long conr = readl(i2c->regs + I2C_CONR); - - conr |= I2C_CONR_MPORT_ENABLE; - writel(conr,i2c->regs + I2C_CONR); -} - -static inline void rk29_i2c_disable_irq(struct rk30_i2c *i2c) -{ - writel(IRQ_ALL_DISABLE, i2c->regs + I2C_IER); -} - -static inline void rk29_i2c_enable_irq(struct rk30_i2c *i2c) -{ - writel(IRQ_MST_ENABLE, i2c->regs + I2C_IER); -} - -/* scl = pclk/(5 *(rem+1) * 2^(exp+1)) */ -static void rk29_i2c_calcdivisor(unsigned long pclk, - unsigned long scl_rate, - unsigned long *real_rate, - unsigned int *rem, unsigned int *exp) -{ - unsigned int calc_rem = 0; - unsigned int calc_exp = 0; - - for(calc_exp = 0; calc_exp < I2CCDVR_EXP_MAX; calc_exp++) - { - calc_rem = pclk / (5 * scl_rate * (1 <<(calc_exp +1))); - if(calc_rem < I2CCDVR_REM_MAX) - break; - } - if(calc_rem >= I2CCDVR_REM_MAX || calc_exp >= I2CCDVR_EXP_MAX) - { - calc_rem = I2CCDVR_REM_MAX - 1; - calc_exp = I2CCDVR_EXP_MAX - 1; - } - *rem = calc_rem; - *exp = calc_exp; - *real_rate = pclk/(5 * (calc_rem + 1) * (1 <<(calc_exp +1))); - return; -} -static void rk29_i2c_set_clk(struct rk30_i2c *i2c, unsigned long scl_rate) -{ - - unsigned int rem = 0, exp = 0; - unsigned long real_rate = 0, tmp; - - unsigned long i2c_rate = clk_get_rate(i2c->clk); - - if((scl_rate == i2c->scl_rate) && (i2c_rate == i2c->i2c_rate)) - return; - - i2c->i2c_rate = i2c_rate; - i2c->scl_rate = scl_rate; - - rk29_i2c_calcdivisor(i2c->i2c_rate, i2c->scl_rate, &real_rate, &rem, &exp); - - tmp = readl(i2c->regs + I2C_OPR); - tmp &= ~0x3f; - tmp |= exp; - tmp |= rem<regs + I2C_OPR); - return; -} - -static void rk29_i2c_init_hw(struct rk30_i2c *i2c, unsigned long scl_rate) -{ - unsigned long opr = readl(i2c->regs + I2C_OPR); - - opr |= I2C_OPR_RESET_STATUS; - writel(opr, i2c->regs + I2C_OPR); - - udelay(10); - opr = readl(i2c->regs + I2C_OPR); - opr &= ~I2C_OPR_RESET_STATUS; - writel(opr, i2c->regs + I2C_OPR); - - rk29_i2c_set_clk(i2c, scl_rate); - - rk29_i2c_disable_irq(i2c); - writel(0, i2c->regs + I2C_LCMR); - writel(0, i2c->regs + I2C_LCMR); - - opr = readl(i2c->regs + I2C_OPR); - opr |= I2C_OPR_CORE_ENABLE; - writel(opr, i2c->regs + I2C_OPR); - udelay(i2c->tx_setup); - - return; -} - -static inline void rk29_i2c_master_complete(struct rk30_i2c *i2c, int ret) -{ - i2c_dbg(i2c->dev, "master_complete %d\n", ret); - - i2c->msg_ptr = 0; - i2c->msg = NULL; - i2c->msg_idx++; - i2c->msg_num = 0; - if (ret) - i2c->msg_idx = ret; - - wake_up(&i2c->wait); -} - -static void rk29_i2c_message_start(struct rk30_i2c *i2c, - struct i2c_msg *msg) -{ - unsigned int addr = (msg->addr & 0x7f) << 1; - unsigned long stat, conr; - - stat = 0; - - i2c->addr = msg->addr & 0x7f; - - if (msg->flags & I2C_M_RD) - addr |= 1; - - if (msg->flags & I2C_M_REV_DIR_ADDR) - addr ^= 1; - - rk29_i2c_enable_ack(i2c); - i2c_dbg(i2c->dev, "START: set addr 0x%02x to DS\n", addr); - - conr = readl(i2c->regs + I2C_CONR); - conr |= I2C_CONR_MTX_MODE; - writel(conr, i2c->regs + I2C_CONR); - writel(addr, i2c->regs + I2C_MTXR); - - udelay(i2c->tx_setup); - writel(I2C_LCMR_START|I2C_LCMR_RESUME, i2c->regs + I2C_LCMR); - -} - -static inline void rk29_i2c_stop(struct rk30_i2c *i2c, int ret) -{ - i2c_dbg(i2c->dev, "STOP\n"); - udelay(i2c->tx_setup); - - writel(I2C_LCMR_STOP|I2C_LCMR_RESUME, i2c->regs + I2C_LCMR); - - i2c->state = STATE_STOP; - - rk29_i2c_master_complete(i2c, ret); - rk29_i2c_disable_irq(i2c); -} - -/* returns TRUE if the current message is the last in the set */ -static inline int is_lastmsg(struct rk30_i2c *i2c) -{ - return i2c->msg_idx >= (i2c->msg_num - 1); -} - -/* returns TRUE if we this is the last byte in the current message */ -static inline int is_msglast(struct rk30_i2c *i2c) -{ - return i2c->msg_ptr == i2c->msg->len-1; -} - -/* returns TRUE if we reached the end of the current message */ -static inline int is_msgend(struct rk30_i2c *i2c) -{ - return i2c->msg_ptr >= i2c->msg->len; -} - -static int rk29_i2c_irq_nextbyte(struct rk30_i2c *i2c, unsigned long isr) -{ - unsigned long lsr, conr; - unsigned char byte; - int ret = 0; - - lsr = readl(i2c->regs + I2C_LSR); - - switch (i2c->state) { - case STATE_IDLE: - dev_err(i2c->dev, "%s: called in STATE_IDLE\n", __func__); - goto out; - - case STATE_STOP: - dev_err(i2c->dev, "%s: called in STATE_STOP\n", __func__); - rk29_i2c_disable_irq(i2c); - goto out; - - case STATE_START: - if(!(isr & I2C_ISR_MTX_RCVD_ACK)){ - writel(isr & ~I2C_ISR_MTX_RCVD_ACK, i2c->regs + I2C_ISR); - rk29_i2c_stop(i2c, -ENXIO); - dev_err(i2c->dev, "START: addr[0x%02x] ack was not received(isr)\n", i2c->addr); - goto out; - } - if ((lsr & I2C_LSR_RCV_NAK) && - !(i2c->msg->flags & I2C_M_IGNORE_NAK)) { - writel(isr & ~I2C_ISR_MTX_RCVD_ACK, i2c->regs + I2C_ISR); - - rk29_i2c_stop(i2c, -EAGAIN); - dev_err(i2c->dev, "START: addr[0x%02x] ack was not received(lsr)\n", i2c->addr); - goto out; - } - if (i2c->msg->flags & I2C_M_RD) - i2c->state = STATE_READ; - else - i2c->state = STATE_WRITE; - - /* terminate the transfer if there is nothing to do - * as this is used by the i2c probe to find devices. */ - if (is_lastmsg(i2c) && i2c->msg->len == 0) { - writel(isr & ~I2C_ISR_MTX_RCVD_ACK, i2c->regs + I2C_ISR); - rk29_i2c_stop(i2c, 0); - goto out; - } - - if (i2c->state == STATE_READ){ - writel(isr & ~I2C_ISR_MTX_RCVD_ACK, i2c->regs + I2C_ISR); - goto prepare_read; - } - - case STATE_WRITE: - if (!(i2c->msg->flags & I2C_M_IGNORE_NAK)) { - if (!(isr & I2C_ISR_MTX_RCVD_ACK)){ - - rk29_i2c_stop(i2c, -ECONNREFUSED); - dev_err(i2c->dev, "WRITE: addr[0x%02x] No Ack\n", i2c->addr); - goto out; - } - } - writel(isr & ~I2C_ISR_MTX_RCVD_ACK, i2c->regs + I2C_ISR); - -retry_write: - - if (!is_msgend(i2c)) { - byte = i2c->msg->buf[i2c->msg_ptr++]; - conr = readl(i2c->regs + I2C_CONR); - conr |= I2C_CONR_MTX_MODE; - writel(conr, i2c->regs + I2C_CONR); - writel(byte, i2c->regs + I2C_MTXR); - - writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR); - - } else if (!is_lastmsg(i2c)) { - /* we need to go to the next i2c message */ - - i2c_dbg(i2c->dev, "WRITE: Next Message\n"); - - i2c->msg_ptr = 0; - i2c->msg_idx++; - i2c->msg++; - - /* check to see if we need to do another message */ - if (i2c->msg->flags & I2C_M_NOSTART) { - if (i2c->msg->flags & I2C_M_RD) { - /* cannot do this, the controller - * forces us to send a new START - * when we change direction */ - - rk29_i2c_stop(i2c, -EINVAL); - } - - goto retry_write; - } else { - /* send the new start */ - rk29_i2c_message_start(i2c, i2c->msg); - i2c->state = STATE_START; - } - - } else { - /* send stop */ - - rk29_i2c_stop(i2c, 0); - } - break; - - case STATE_READ: - if(!(isr & I2C_ISR_MRX_NEED_ACK)){ - rk29_i2c_stop(i2c, -ENXIO); - dev_err(i2c->dev, "READ: addr[0x%02x] not recv need ack interrupt\n", i2c->addr); - goto out; - } - writel(isr & ~I2C_ISR_MRX_NEED_ACK, i2c->regs + I2C_ISR); - byte = readl(i2c->regs + I2C_MRXR); - i2c_dbg(i2c->dev, "READ: byte = %d\n", byte); - i2c->msg->buf[i2c->msg_ptr++] = byte; - prepare_read: - if (is_msgend(i2c)) { - if (is_lastmsg(i2c)) { - /* last message, send stop and complete */ - rk29_i2c_disable_ack(i2c); - i2c_dbg(i2c->dev, "READ: Send Stop\n"); - - rk29_i2c_stop(i2c, 0); - } else { - /* go to the next transfer */ - i2c_dbg(i2c->dev, "READ: Next Transfer\n"); - - i2c->msg_ptr = 0; - i2c->msg_idx++; - i2c->msg++; - rk29_i2c_message_start(i2c, i2c->msg); - i2c->state = STATE_START; - } - }else{ - conr = readl(i2c->regs + I2C_CONR); - conr &= I2C_CONR_MRX_MODE; - writel(conr, i2c->regs + I2C_CONR); - - writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR); - } - break; - } - - out: - return ret; -} - -static irqreturn_t rk29_i2c_irq(int irqno, void *dev_id) -{ - struct rk30_i2c *i2c = dev_id; - unsigned long isr; - - spin_lock(&i2c->lock); - udelay(i2c->tx_setup); - - isr = readl(i2c->regs + I2C_ISR); - - if (isr & I2C_ISR_ARBITR_LOSE) { - writel(isr & ~I2C_ISR_ARBITR_LOSE, i2c->regs + I2C_ISR); - dev_err(i2c->dev, "deal with arbitration loss\n"); - } - - if (i2c->state == STATE_IDLE) { - i2c_dbg(i2c->dev, "IRQ: error i2c->state == IDLE\n"); - goto out; - } - - rk29_i2c_irq_nextbyte(i2c, isr); - - out: - spin_unlock(&i2c->lock); - - return IRQ_HANDLED; -} - - -/* rk29_i2c_set_master - * - * get the i2c bus for a master transaction -*/ - -static int rk29_i2c_set_master(struct rk30_i2c *i2c) -{ - int tmo = RK29_I2C_START_TMO_COUNT; - unsigned long lsr; - - while (tmo-- > 0) { - lsr = readl(i2c->regs + I2C_LSR); - if (!(lsr & I2C_LSR_BUSY)) - return 0; - writel(I2C_LCMR_STOP|I2C_LCMR_RESUME, i2c->regs + I2C_LCMR); - msleep(1); - } - return -ETIMEDOUT; -} - -/* rk29_i2c_doxfer - * - * this starts an i2c transfer -*/ - -static int rk29_i2c_doxfer(struct rk30_i2c *i2c, - struct i2c_msg *msgs, int num) -{ - unsigned long timeout; - int ret; - - if (i2c->suspended) - return -EIO; - - ret = rk29_i2c_set_master(i2c); - if (ret != 0) { - dev_err(i2c->dev, "addr[0x%02x] cannot get bus (error %d)\n", msgs[0].addr, ret); - ret = -EAGAIN; - goto out; - } - - spin_lock_irq(&i2c->lock); - - i2c->msg = msgs; - i2c->msg_num = num; - i2c->msg_ptr = 0; - i2c->msg_idx = 0; - i2c->state = STATE_START; - - rk29_i2c_enable_irq(i2c); - rk29_i2c_message_start(i2c, msgs); - spin_unlock_irq(&i2c->lock); - - timeout = wait_event_timeout(i2c->wait, i2c->msg_num == 0, msecs_to_jiffies(I2C_WAIT_TIMEOUT)); - - ret = i2c->msg_idx; - - if (timeout == 0) - i2c_dbg(i2c->dev, "addr[0x%02x] wait event timeout\n", msgs[0].addr); - else if (ret != num) - i2c_dbg(i2c->dev, "addr[0x%02x ]incomplete xfer (%d)\n", msgs[0].addr, ret); - if((readl(i2c->regs + I2C_LSR) & I2C_LSR_BUSY) || - readl(i2c->regs + I2C_LCMR) & I2C_LCMR_STOP ){ - msleep(1); - writel(I2C_LCMR_STOP|I2C_LCMR_RESUME, i2c->regs + I2C_LCMR); - if((readl(i2c->regs + I2C_LSR) & I2C_LSR_BUSY) || - readl(i2c->regs + I2C_LCMR) & I2C_LCMR_STOP ){ - dev_warn(i2c->dev, "WARNING: STOP abnormal, addr[0x%02x] isr = 0x%x, lsr = 0x%x, lcmr = 0x%x\n", - msgs[0].addr, - readl(i2c->regs + I2C_ISR), - readl(i2c->regs + I2C_LSR), - readl(i2c->regs + I2C_LCMR) - ); - } - } - out: - return ret; -} - -/* rk29_i2c_xfer - * - * first port of call from the i2c bus code when an message needs - * transferring across the i2c bus. -*/ - -static int rk29_i2c_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) -{ - struct rk30_i2c *i2c = (struct rk30_i2c *)adap->algo_data; - int ret = 0; - unsigned long scl_rate; - - clk_enable(i2c->clk); - - if(msgs[0].scl_rate <= 400000 && msgs[0].scl_rate >= 10000) - scl_rate = msgs[0].scl_rate; - else if(msgs[0].scl_rate > 400000){ - dev_warn(i2c->dev, "Warning: addr[0x%x] msg[0].scl_rate( = %dKhz) is too high!", - msgs[0].addr, msgs[0].scl_rate/1000); - scl_rate = 400000; - } - else{ - dev_warn(i2c->dev, "Warning: addr[0x%x] msg[0].scl_rate( = %dKhz) is too low!", - msgs[0].addr, msgs[0].scl_rate/1000); - scl_rate = 10000; - } - if(i2c->is_div_from_arm[i2c->adap.nr]) - wake_lock(&i2c->idlelock[i2c->adap.nr]); - - rk29_i2c_set_clk(i2c, scl_rate); - rk29_i2c_enable_mport(i2c); - udelay(i2c->tx_setup); - - ret = rk29_i2c_doxfer(i2c, msgs, num); - - rk29_i2c_disable_mport(i2c); - if(i2c->is_div_from_arm[i2c->adap.nr]) - wake_unlock(&i2c->idlelock[i2c->adap.nr]); - clk_disable(i2c->clk); - return ret; -} - -/* declare our i2c functionality */ -static u32 rk29_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING; -} - -/* i2c bus registration info */ - -static const struct i2c_algorithm rk29_i2c_algorithm = { - .master_xfer = rk29_i2c_xfer, - .functionality = rk29_i2c_func, -}; - -int i2c_add_rk29_adapter(struct i2c_adapter *adap) -{ - int ret = 0; - struct rk30_i2c *i2c = (struct rk30_i2c *)adap->algo_data; - - adap->algo = &rk29_i2c_algorithm; - - i2c->i2c_init_hw = &rk29_i2c_init_hw; - i2c->i2c_set_clk = &rk29_i2c_set_clk; - i2c->i2c_irq = &rk29_i2c_irq; - - ret = i2c_add_numbered_adapter(adap); - - return ret; -} - - diff --git a/drivers/i2c/busses/i2c-rk29.c b/drivers/i2c/busses/i2c-rk29.c deleted file mode 100755 index 4e5f1e136751..000000000000 --- a/drivers/i2c/busses/i2c-rk29.c +++ /dev/null @@ -1,912 +0,0 @@ -/* drivers/i2c/busses/i2c_rk29.c - * - * Copyright (C) 2010 ROCKCHIP, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "i2c-rk29.h" -#define DRV_NAME "rk29_i2c" -#define RETRY_NUM 1 - -#define RK29_UDELAY_TIME(scl_rate) ((400*1000)/(scl_rate)) -/*max ACK delay time = RK29_I2C_ACK_TIMEOUT_COUNT * RK29_UDELAY_TIME(scl_rate) us */ -#define RK29_I2C_ACK_TIMEOUT_COUNT (100 * 1000) -/*max STOP delay time = RK29_I2C_STOP_TIMEOUT_COUNT * RK29_UDELAY_TIME(scl_rate) us */ -#define RK29_I2C_STOP_TIMEOUT_COUNT 70//1000 -/*max START delay time = RK29_I2C_START_TIMEOUT_COUNT * RK29_UDELAY_TIME(scl_rate) us */ -#define RK29_I2C_START_TIMEOUT_COUNT 1000 - - - -#if 0 -#define i2c_dbg(dev, format, arg...) \ - dev_printk(KERN_INFO , dev , format , ## arg) -#define i2c_err(dev, format, arg...) \ - dev_printk(KERN_ERR , dev , format , ## arg) - -#else -#define i2c_dbg(dev, format, arg...) -#define i2c_err(dev, format, arg...) - -#endif - -enum rk29_error { - RK29_ERROR_NONE = 0, - RK29_ERROR_ARBITR_LOSE, - RK29_ERROR_UNKNOWN -}; - -enum rk29_event { - RK29_EVENT_NONE = 0, - /* master has received ack(MTX mode) - means that data has been sent to slave. - */ - RK29_EVENT_MTX_RCVD_ACK, - /* master needs to send ack to slave(MRX mode) - means that data has been received from slave. - */ - RK29_EVENT_MRX_NEED_ACK, - RK29_EVENT_MAX -}; - -struct rk29_i2c_data { - struct device *dev; - struct i2c_adapter adap; - void __iomem *regs; - struct resource *ioarea; - - unsigned int ack_timeout; //unit: us - unsigned int udelay_time; //unit: us - - unsigned int suspended:1; - unsigned long scl_rate; - unsigned long i2c_rate; - struct clk *clk; - - unsigned int mode; - int retry; - - int poll_status; - - unsigned int irq; - - spinlock_t cmd_lock; - struct completion cmd_complete; - enum rk29_event cmd_event; - enum rk29_error cmd_err; - - unsigned int msg_idx; - unsigned int msg_num; - int udelay; - int (*io_init)(void); -#ifdef CONFIG_CPU_FREQ - struct notifier_block freq_transition; -#endif -}; - -#if defined(CONFIG_ARCH_RK29) || defined(CONFIG_ARCH_RK30) -static struct wake_lock idlelock; /* only for i2c0 */ -#endif - -static void rk29_set_ack(struct rk29_i2c_data *i2c) -{ - unsigned long conr = readl(i2c->regs + I2C_CONR); - - conr &= I2C_CONR_ACK; - writel(conr,i2c->regs + I2C_CONR); - return; -} -static void rk29_set_nak(struct rk29_i2c_data *i2c) -{ - unsigned long conr = readl(i2c->regs + I2C_CONR); - - conr |= I2C_CONR_NAK; - writel(conr,i2c->regs + I2C_CONR); - return; -} - - -static inline void rk29_i2c_disable_irqs(struct rk29_i2c_data *i2c) -{ - unsigned long tmp; - - tmp = readl(i2c->regs + I2C_IER); - writel(tmp & IRQ_ALL_DISABLE, i2c->regs + I2C_IER); -} -static inline void rk29_i2c_enable_irqs(struct rk29_i2c_data *i2c) -{ - unsigned long tmp; - - tmp = readl(i2c->regs + I2C_IER); - writel(tmp | IRQ_MST_ENABLE, i2c->regs + I2C_IER); -} - -/* scl = pclk/(5 *(rem+1) * 2^(exp+1)) */ -static void rk29_i2c_calcdivisor(unsigned long pclk, - unsigned long scl_rate, - unsigned long *real_rate, - unsigned int *rem, unsigned int *exp) -{ - unsigned int calc_rem = 0; - unsigned int calc_exp = 0; - - for(calc_exp = 0; calc_exp < I2CCDVR_EXP_MAX; calc_exp++) - { - calc_rem = pclk / (5 * scl_rate * (1 <<(calc_exp +1))); - if(calc_rem < I2CCDVR_REM_MAX) - break; - } - if(calc_rem >= I2CCDVR_REM_MAX || calc_exp >= I2CCDVR_EXP_MAX) - { - calc_rem = I2CCDVR_REM_MAX - 1; - calc_exp = I2CCDVR_EXP_MAX - 1; - } - *rem = calc_rem; - *exp = calc_exp; - *real_rate = pclk/(5 * (calc_rem + 1) * (1 <<(calc_exp +1))); - return; -} -/* set i2c bus scl rate */ -static void rk29_i2c_clockrate(struct rk29_i2c_data *i2c) -{ - - struct rk29_i2c_platform_data *pdata = i2c->dev->platform_data; - unsigned int rem = 0, exp = 0; - unsigned long scl_rate, real_rate = 0, tmp; - - i2c->i2c_rate = clk_get_rate(i2c->clk); - - scl_rate = (i2c->scl_rate) ? i2c->scl_rate : ((pdata->scl_rate)? pdata->scl_rate:100000); - - rk29_i2c_calcdivisor(i2c->i2c_rate, scl_rate, &real_rate, &rem, &exp); - - tmp = readl(i2c->regs + I2C_OPR); - tmp &= ~0x3f; - tmp |= exp; - tmp |= rem<regs + I2C_OPR); - if(real_rate > 400000) - dev_warn(i2c->dev, "i2c_rate[%luKhz], scl_rate[%luKhz], real_rate[%luKhz] > 400Khz\n", - i2c->i2c_rate/1000, scl_rate/1000, real_rate/1000); - else - i2c_dbg(i2c->dev, "i2c_rate[%luKhz], scl_rate[%luKhz], real_rate[%luKhz]\n", - i2c->i2c_rate/1000, scl_rate/1000, real_rate/1000); - return; -} -static int rk29_event_occurred(struct rk29_i2c_data *i2c) -{ - unsigned long isr, lsr; - - isr = readl(i2c->regs + I2C_ISR); - lsr = readl(i2c->regs + I2C_LSR); - i2c_dbg(i2c->dev,"event occurred, isr = %lx, lsr = %lx\n", isr, lsr); - if(isr & I2C_ISR_ARBITR_LOSE) - { - writel(0, i2c->regs + I2C_ISR); - i2c->cmd_err = RK29_ERROR_ARBITR_LOSE; - i2c_err(i2c->dev, "arbitration loss\n"); - return 0; - } - - switch(i2c->cmd_event) - { - case RK29_EVENT_MTX_RCVD_ACK: - if(isr & I2C_ISR_MTX_RCVD_ACK) - { - isr &= ~I2C_ISR_MTX_RCVD_ACK; - writel(isr, i2c->regs + I2C_ISR); - return 1; - } - break; - case RK29_EVENT_MRX_NEED_ACK: - if(isr & I2C_ISR_MRX_NEED_ACK) - { - isr &= ~I2C_ISR_MRX_NEED_ACK; - writel(isr, i2c->regs + I2C_ISR); - return 1; - } - break; - default: - break; - } - writel(0, i2c->regs + I2C_ISR); - i2c->cmd_err = RK29_ERROR_UNKNOWN; - return 0; -} - -static irqreturn_t rk29_i2c_irq(int irq, void *data) -{ - struct rk29_i2c_data *i2c = (struct rk29_i2c_data *)data; - int res; - - rk29_i2c_disable_irqs(i2c); - spin_lock(&i2c->cmd_lock); - res = rk29_event_occurred(i2c); - if(res) - { - if(i2c->mode == I2C_MODE_IRQ) - complete(&i2c->cmd_complete); - else - i2c->poll_status = 1; - } - spin_unlock(&i2c->cmd_lock); - return IRQ_HANDLED; -} -static int wait_for_completion_poll_timeout(struct rk29_i2c_data *i2c) -{ - int tmo = RK29_I2C_ACK_TIMEOUT_COUNT; - - while(--tmo) - { - if(i2c->poll_status == 1) - return 1; - udelay(i2c->udelay_time); - } - return 0; -} -static int rk29_wait_event(struct rk29_i2c_data *i2c, - enum rk29_event mr_event) -{ - int ret = 0; - - if(unlikely(irqs_disabled())) - { - i2c_err(i2c->dev, "irqs are disabled on this system!\n"); - return -EIO; - } - i2c->cmd_err = RK29_ERROR_NONE; - i2c->cmd_event = mr_event; - rk29_i2c_enable_irqs(i2c); - if(i2c->mode == I2C_MODE_IRQ) - { - ret = wait_for_completion_interruptible_timeout(&i2c->cmd_complete, - usecs_to_jiffies(i2c->ack_timeout)); - } - else - { - i2c->poll_status = 0; - ret = wait_for_completion_poll_timeout(i2c); - } - if(ret < 0) - { - i2c_err(i2c->dev, "i2c wait for event %04x, retrun %d \n", mr_event, ret); - return ret; - } - if(ret == 0) - { - i2c_err(i2c->dev, "i2c wait for envent timeout, but not return -ETIMEDOUT\n"); - return 0; - //return -ETIMEDOUT; - } - return 0; -} - -static void rk29_i2c_stop(struct rk29_i2c_data *i2c) -{ - int tmo = RK29_I2C_STOP_TIMEOUT_COUNT; - - writel(I2C_LCMR_STOP|I2C_LCMR_RESUME, i2c->regs + I2C_LCMR); - while(--tmo && !(readl(i2c->regs + I2C_LCMR) & I2C_LCMR_STOP)) - { - udelay(i2c->udelay_time); - } - writel(0, i2c->regs + I2C_ISR); - rk29_i2c_disable_irqs(i2c); - - udelay(tmo); - return; -} -static void rk29_wait_while_busy(struct rk29_i2c_data *i2c) -{ - int tmo = RK29_I2C_START_TIMEOUT_COUNT; - - while(--tmo && (readl(i2c->regs + I2C_LSR) & I2C_LSR_BUSY)) - { - udelay(i2c->udelay_time); - } - return; -} - -static int rk29_send_2nd_addr(struct rk29_i2c_data *i2c, - struct i2c_msg *msg, int start) -{ - int ret = 0; - unsigned long lsr; - unsigned long addr_2nd = msg->addr & 0xff; - - i2c_dbg(i2c->dev, "i2c send addr_2nd: %lx\n", addr_2nd); - writel(addr_2nd, i2c->regs + I2C_MTXR); - if(i2c->mode == I2C_MODE_IRQ) - INIT_COMPLETION(i2c->cmd_complete); - writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR); - rk29_set_ack(i2c); - - if((ret = rk29_wait_event(i2c, RK29_EVENT_MTX_RCVD_ACK)) != 0) - { - i2c_err(i2c->dev, "after sent addr_2nd, i2c wait for ACK timeout\n"); - return ret; - } - lsr = readl(i2c->regs + I2C_LSR); - if((lsr & I2C_LSR_RCV_NAK) && !(msg->flags & I2C_M_IGNORE_NAK)) - return -EINVAL; - return ret; -} -static int rk29_send_address(struct rk29_i2c_data *i2c, - struct i2c_msg *msg, int start) -{ - unsigned long addr_1st; - unsigned long conr,lsr; - int ret = 0; - - if(msg->flags & I2C_M_TEN) - addr_1st = (0xf0 | (((unsigned long) msg->addr & 0x300) >> 7)) & 0xff; - else - addr_1st = ((msg->addr << 1) & 0xff); - - if (msg->flags & I2C_M_RD) - addr_1st |= 0x01; - else - addr_1st &= (~0x01); - - if(start) - rk29_wait_while_busy(i2c); - - writel(0, i2c->regs + I2C_ISR); - conr = readl(i2c->regs + I2C_CONR); - conr |= I2C_CONR_MTX_MODE; - conr |= I2C_CONR_MPORT_ENABLE; - writel(conr, i2c->regs + I2C_CONR); - - i2c_dbg(i2c->dev, "i2c send addr_1st: %lx\n", addr_1st); - writel(addr_1st, i2c->regs + I2C_MTXR); - rk29_set_ack(i2c); - if(i2c->mode == I2C_MODE_IRQ) - INIT_COMPLETION(i2c->cmd_complete); - writel(I2C_LCMR_START|I2C_LCMR_RESUME, i2c->regs + I2C_LCMR); - - if((ret = rk29_wait_event(i2c, RK29_EVENT_MTX_RCVD_ACK)) != 0) - { - i2c_err(i2c->dev, "after sent addr_1st, i2c wait for ACK timeout\n"); - return ret; - } - lsr = readl(i2c->regs + I2C_LSR); - if((lsr & I2C_LSR_RCV_NAK) && !(msg->flags & I2C_M_IGNORE_NAK)) - { - dev_info(i2c->dev, "addr: 0x%x receive no ack\n", msg->addr); - return -EAGAIN; - } - if(start && (msg->flags & I2C_M_TEN)) - ret = rk29_send_2nd_addr(i2c, msg, start); - return ret; -} - -static int rk29_i2c_send_msg(struct rk29_i2c_data *i2c, struct i2c_msg *msg) -{ - int i, ret = 0; - unsigned long conr, lsr; - - conr = readl(i2c->regs + I2C_CONR); - conr |= I2C_CONR_MTX_MODE; - //conr |= I2C_CONR_MPORT_ENABLE; - writel(conr, i2c->regs + I2C_CONR); - - for(i = 0; i < msg->len; i++) - { - i2c_dbg(i2c->dev, "i2c send buf[%d]: %x\n", i, msg->buf[i]); - writel(msg->buf[i], i2c->regs + I2C_MTXR); - rk29_set_ack(i2c); - if(i2c->mode == I2C_MODE_IRQ) - INIT_COMPLETION(i2c->cmd_complete); - writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR); - - if((ret = rk29_wait_event(i2c, RK29_EVENT_MTX_RCVD_ACK)) != 0) - return ret; - lsr = readl(i2c->regs + I2C_LSR); - if((lsr & I2C_LSR_RCV_NAK) && (i != msg->len -1) && !(msg->flags & I2C_M_IGNORE_NAK)) - return -EINVAL; - udelay(i2c->udelay); - - } - return ret; -} -static int rk29_i2c_recv_msg(struct rk29_i2c_data *i2c, struct i2c_msg *msg) -{ - int i, ret = 0; - unsigned long conr; - - conr = readl(i2c->regs + I2C_CONR); - conr &= I2C_CONR_MRX_MODE; - //conr |= I2C_CONR_MPORT_ENABLE; - writel(conr, i2c->regs + I2C_CONR); - - for(i = 0; i < msg->len; i++) - { - if(i2c->mode == I2C_MODE_IRQ) - INIT_COMPLETION(i2c->cmd_complete); - writel(I2C_LCMR_RESUME, i2c->regs + I2C_LCMR); - if((ret = rk29_wait_event(i2c, RK29_EVENT_MRX_NEED_ACK)) != 0) - return ret; - msg->buf[i] = (uint8_t)readl(i2c->regs + I2C_MRXR); - - if( i == msg->len -1) - rk29_set_nak(i2c); - else - rk29_set_ack(i2c); - udelay(i2c->udelay); - i2c_dbg(i2c->dev, "i2c recv >>>>>>>>>>>> buf[%d]: %x\n", i, msg->buf[i]); - } - return ret; -} -static int rk29_xfer_msg(struct i2c_adapter *adap, - struct i2c_msg *msg, int start, int stop) -{ - struct rk29_i2c_data *i2c = (struct rk29_i2c_data *)adap->algo_data; - int ret = 0; - - if(msg->len == 0) - { - ret = -EINVAL; - i2c_err(i2c->dev, "msg->len = %d\n", msg->len); - goto exit; - } - if(msg->flags & I2C_M_NEED_DELAY) - i2c->udelay = msg->udelay; - else - i2c->udelay = 0; - if((ret = rk29_send_address(i2c, msg, start))!= 0) - { - rk29_set_nak(i2c); - i2c_err(i2c->dev, "rk29_send_address timeout\n"); - goto exit; - } - if(msg->flags & I2C_M_RD) - { - if(msg->flags & I2C_M_REG8_DIRECT) - { - struct i2c_msg msg1 = *msg; - struct i2c_msg msg2 = *msg; - msg1.len = 1; - msg2.len = msg->len - 1; - msg2.buf = msg->buf + 1; - - if((ret = rk29_i2c_send_msg(i2c, &msg1)) != 0) - i2c_err(i2c->dev, "rk29_i2c_send_msg timeout\n"); - if((ret = rk29_i2c_recv_msg(i2c, &msg2)) != 0) - { - i2c_err(i2c->dev, "rk29_i2c_recv_msg timeout\n"); - goto exit; - } - - } - else if((ret = rk29_i2c_recv_msg(i2c, msg)) != 0) - { - i2c_err(i2c->dev, "rk29_i2c_recv_msg timeout\n"); - goto exit; - } - } - else - { - if((ret = rk29_i2c_send_msg(i2c, msg)) != 0) - { - rk29_set_nak(i2c); - i2c_err(i2c->dev, "rk29_i2c_send_msg timeout\n"); - goto exit; - } - } - -exit: - if(stop || ret < 0) - { - rk29_i2c_stop(i2c); - } - return ret; - -} - -static int rk29_i2c_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) -{ - int ret = -1; - int i; - struct rk29_i2c_data *i2c = (struct rk29_i2c_data *)adap->algo_data; - - //int retry = i2c->retry; - /* - if(i2c->suspended ==1) - return -EIO; - */ - // 400k > scl_rate > 10k - if(msgs[0].scl_rate <= 400000 && msgs[0].scl_rate >= 10000) - i2c->scl_rate = msgs[0].scl_rate; - else if(msgs[0].scl_rate > 400000){ - dev_info(i2c->dev, "Warning: msg[0].scl_rate( = %dKhz) is too high!", - msgs[0].scl_rate/1000); - i2c->scl_rate = 400000; - } - else{ - dev_info(i2c->dev, "Warning: msg[0].scl_rate( = %dKhz) is too low!", - msgs[0].scl_rate/1000); - i2c->scl_rate = 10000; - } - rk29_i2c_clockrate(i2c); - - i2c->udelay_time = RK29_UDELAY_TIME(i2c->scl_rate); - i2c->ack_timeout = RK29_I2C_ACK_TIMEOUT_COUNT * i2c->udelay_time; - -#if defined(CONFIG_ARCH_RK29) || defined(CONFIG_ARCH_RK30) - if (adap->nr == 0) - wake_lock(&idlelock); -#endif - - for (i = 0; i < num; i++) - { - ret = rk29_xfer_msg(adap, &msgs[i], (i == 0), (i == (num - 1))); - if (ret != 0) - { - num = ret; - i2c_err(i2c->dev, "rk29_xfer_msg error, ret = %d\n", ret); - break; - } - } - -#if defined(CONFIG_ARCH_RK29) || defined(CONFIG_ARCH_RK30) - if (adap->nr == 0) - wake_unlock(&idlelock); -#endif - - /* - if( --retry && num < 0) - { - udelay(10000 * 1000/i2c->scl_rate); - goto retry; - } - */ - if(num < 0) - dev_err(i2c->dev, "i2c transfer err, client address is 0x%x [20110106]\n", msgs[0].addr); - return num; -} - -static u32 rk29_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR; -} - -static const struct i2c_algorithm rk29_i2c_algorithm = { - .master_xfer = rk29_i2c_xfer, - .functionality = rk29_i2c_func, -}; - -int i2c_suspended(struct i2c_adapter *adap) -{ - struct rk29_i2c_data *i2c = (struct rk29_i2c_data *)adap->algo_data; - if(adap->nr > 1) - return 1; - if(i2c == NULL) - return 1; - return i2c->suspended; -} -EXPORT_SYMBOL(i2c_suspended); - -static void rk29_i2c_deinit_hw(struct rk29_i2c_data *i2c) -{ - unsigned long opr = readl(i2c->regs + I2C_OPR); - - opr &= ~I2C_OPR_RESET_STATUS; - writel(opr, i2c->regs); - return; -} -static void rk29_i2c_init_hw(struct rk29_i2c_data *i2c) -{ - unsigned long opr = readl(i2c->regs + I2C_OPR); - - opr |= I2C_OPR_RESET_STATUS; - writel(opr, i2c->regs + I2C_OPR); - - udelay(10); - opr = readl(i2c->regs + I2C_OPR); - opr &= ~I2C_OPR_RESET_STATUS; - writel(opr, i2c->regs + I2C_OPR); - - rk29_i2c_clockrate(i2c); - - rk29_i2c_disable_irqs(i2c); - writel(0, i2c->regs + I2C_LCMR); - writel(0, i2c->regs + I2C_LCMR); - - opr = readl(i2c->regs + I2C_OPR); - opr |= I2C_OPR_CORE_ENABLE; - writel(opr, i2c->regs + I2C_OPR); - - return; -} - -#ifdef CONFIG_CPU_FREQ - -#define freq_to_i2c(_n) container_of(_n, struct rk29_i2c_data, freq_transition) - -static int rk29_i2c_cpufreq_transition(struct notifier_block *nb, - unsigned long val, void *data) -{ - struct rk29_i2c_data *i2c = freq_to_i2c(nb); - unsigned long flags; - int delta_f; - delta_f = clk_get_rate(i2c->clk) - i2c->i2c_rate; - - if ((val == CPUFREQ_POSTCHANGE && delta_f < 0) || - (val == CPUFREQ_PRECHANGE && delta_f > 0)) - { - spin_lock_irqsave(&i2c->cmd_lock, flags); - rk29_i2c_clockrate(i2c); - spin_unlock_irqrestore(&i2c->cmd_lock, flags); - } - return 0; -} - -static inline int rk29_i2c_register_cpufreq(struct rk29_i2c_data *i2c) -{ - if (i2c->adap.nr != 0) - return 0; - i2c->freq_transition.notifier_call = rk29_i2c_cpufreq_transition; - - return cpufreq_register_notifier(&i2c->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -} - -static inline void rk29_i2c_unregister_cpufreq(struct rk29_i2c_data *i2c) -{ - if (i2c->adap.nr != 0) - return; - cpufreq_unregister_notifier(&i2c->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -} - -#else -static inline int rk29_i2c_register_cpufreq(struct rk29_i2c_data *i2c) -{ - return 0; -} - -static inline void rk29_i2c_unregister_cpufreq(struct rk29_i2c_data *i2c) -{ - return; -} -#endif - -static int rk29_i2c_probe(struct platform_device *pdev) -{ - struct rk29_i2c_data *i2c; - struct rk29_i2c_platform_data *pdata = NULL; - struct resource *res; - int ret; - - pdata = pdev->dev.platform_data; - if (!pdata) - { - i2c_err(&pdev->dev, "no platform data\n"); - return -EINVAL; - } - i2c = kzalloc(sizeof(struct rk29_i2c_data), GFP_KERNEL); - if (!i2c) - { - i2c_err(&pdev->dev, "no memory for state\n"); - return -ENOMEM; - } - init_completion(&i2c->cmd_complete); - i2c->retry = RETRY_NUM; - i2c->mode = pdata->mode; - i2c->scl_rate = (pdata->scl_rate) ? pdata->scl_rate : 100000; - - strlcpy(i2c->adap.name, DRV_NAME, sizeof(i2c->adap.name)); - i2c->adap.owner = THIS_MODULE; - i2c->adap.algo = &rk29_i2c_algorithm; - i2c->adap.class = I2C_CLASS_HWMON; - i2c->adap.nr = pdata->bus_num; - i2c->adap.retries = 3; - i2c->adap.timeout = msecs_to_jiffies(500); - - spin_lock_init(&i2c->cmd_lock); - - i2c->dev = &pdev->dev; - - i2c->clk = clk_get(&pdev->dev, "i2c"); - if (IS_ERR(i2c->clk)) { - i2c_err(&pdev->dev, "cannot get clock\n"); - ret = -ENOENT; - goto err_noclk; - } - - clk_enable(i2c->clk); - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - i2c_err(&pdev->dev, "cannot find IO resource\n"); - ret = -ENOENT; - goto err_clk; - } - - i2c->ioarea = request_mem_region(res->start, res->end - res->start + 1, - pdev->name); - - if (i2c->ioarea == NULL) { - i2c_err(&pdev->dev, "cannot request IO\n"); - ret = -ENXIO; - goto err_clk; - } - - i2c->regs = ioremap(res->start, res->end - res->start + 1); - - if (i2c->regs == NULL) { - i2c_err(&pdev->dev, "annot map IO\n"); - ret = -ENXIO; - goto err_ioarea; - } - i2c->adap.algo_data = i2c; - i2c->adap.dev.parent = &pdev->dev; - - if(pdata->io_init) - { - i2c->io_init = pdata->io_init; - pdata->io_init(); - } - - i2c->irq = ret = platform_get_irq(pdev, 0); - if (ret <= 0) { - i2c_err(&pdev->dev, "cannot find IRQ\n"); - goto err_iomap; - } - ret = request_irq(i2c->irq, rk29_i2c_irq, IRQF_DISABLED, - dev_name(&pdev->dev), i2c); - - if (ret != 0) { - i2c_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); - goto err_iomap; - } - ret = rk29_i2c_register_cpufreq(i2c); - if (ret < 0) { - i2c_err(&pdev->dev, "failed to register cpufreq notifier\n"); - goto err_irq; - } - - ret = i2c_add_numbered_adapter(&i2c->adap); - if (ret < 0) { - i2c_err(&pdev->dev, "failed to add bus to i2c core\n"); - goto err_cpufreq; - } - - platform_set_drvdata(pdev, i2c); - rk29_i2c_init_hw(i2c); - - dev_info(&pdev->dev, "%s: RK29 I2C adapter\n", dev_name(&i2c->adap.dev)); - return 0; - - err_cpufreq: - rk29_i2c_unregister_cpufreq(i2c); - - err_irq: - free_irq(i2c->irq, i2c); - - err_iomap: - iounmap(i2c->regs); - - err_ioarea: - release_resource(i2c->ioarea); - kfree(i2c->ioarea); - - err_clk: - clk_disable(i2c->clk); - clk_put(i2c->clk); - - err_noclk: - kfree(i2c); - return ret; -} - - -static int rk29_i2c_remove(struct platform_device *pdev) -{ - struct rk29_i2c_data *i2c = platform_get_drvdata(pdev); - - - rk29_i2c_deinit_hw(i2c); - rk29_i2c_unregister_cpufreq(i2c); - - i2c_del_adapter(&i2c->adap); - free_irq(i2c->irq, i2c); - - clk_disable(i2c->clk); - clk_put(i2c->clk); - - iounmap(i2c->regs); - - release_resource(i2c->ioarea); - kfree(i2c->ioarea); - kfree(i2c); - - return 0; -} - -#ifdef CONFIG_PM -static int rk29_i2c_suspend_noirq(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rk29_i2c_data *i2c = platform_get_drvdata(pdev); - - i2c->suspended = 1; - return 0; -} - -static int rk29_i2c_resume_noirq(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rk29_i2c_data *i2c = platform_get_drvdata(pdev); - - i2c->suspended = 0; - rk29_i2c_init_hw(i2c); - - return 0; -} - -static struct dev_pm_ops rk29_i2c_pm_ops = { - .suspend_noirq = rk29_i2c_suspend_noirq, - .resume_noirq = rk29_i2c_resume_noirq, -}; -#endif - -static struct platform_driver rk29_i2c_driver = { - .probe = rk29_i2c_probe, - .remove = rk29_i2c_remove, - .driver = { - .owner = THIS_MODULE, - .name = DRV_NAME, -#ifdef CONFIG_PM - .pm = &rk29_i2c_pm_ops, -#endif - }, -}; - -static int __init rk29_i2c_adap_init(void) -{ -#if defined(CONFIG_ARCH_RK29) || defined(CONFIG_ARCH_RK30) - wake_lock_init(&idlelock, WAKE_LOCK_IDLE, "i2c0"); -#endif - return platform_driver_register(&rk29_i2c_driver); -} - -static void __exit rk29_i2c_adap_exit(void) -{ - platform_driver_unregister(&rk29_i2c_driver); -} - -subsys_initcall(rk29_i2c_adap_init); -module_exit(rk29_i2c_adap_exit); - -MODULE_DESCRIPTION("Driver for RK29 I2C Bus"); -MODULE_AUTHOR("kfx, kfx@rock-chips.com"); -MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-rk29.h b/drivers/i2c/busses/i2c-rk29.h deleted file mode 100755 index 97bf03cd8fc2..000000000000 --- a/drivers/i2c/busses/i2c-rk29.h +++ /dev/null @@ -1,73 +0,0 @@ -/* drivers/i2c/busses/i2c_rk2818.h - * - * Copyright (C) 2010 ROCKCHIP, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#ifndef __RK2818_I2C_H -#define __RK2818_I2C_H - -/* master transmit */ -#define I2C_MTXR (0x0000) -/* master receive */ -#define I2C_MRXR (0x0004) -/* slave address */ -#define I2C_SADDR (0x0010) -/* interrupt enable control */ -#define I2C_IER (0x0014) -#define I2C_IER_ARBITR_LOSE (1<<7) -#define I2C_IER_MRX_NEED_ACK (1<<1) -#define I2C_IER_MTX_RCVD_ACK (1<<0) - -#define IRQ_MST_ENABLE (I2C_IER_ARBITR_LOSE | \ - I2C_IER_MRX_NEED_ACK | \ - I2C_IER_MTX_RCVD_ACK) -#define IRQ_ALL_DISABLE (0x00) - -/* interrupt status, write 0 to clear */ -#define I2C_ISR (0x0018) -#define I2C_ISR_ARBITR_LOSE (1<<7) -#define I2C_ISR_MRX_NEED_ACK (1<<1) -#define I2C_ISR_MTX_RCVD_ACK (1<<0) - -/* stop/start/resume command, write 1 to set */ -#define I2C_LCMR (0x001c) -#define I2C_LCMR_RESUME (1<<2) -#define I2C_LCMR_STOP (1<<1) -#define I2C_LCMR_START (1<<0) - -/* i2c core status */ -#define I2C_LSR (0x0020) -#define I2C_LSR_RCV_NAK (1<<1) -#define I2C_LSR_RCV_ACK (~(1<<1)) -#define I2C_LSR_BUSY (1<<0) - -/* i2c config */ -#define I2C_CONR (0x0024) -#define I2C_CONR_NAK (1<<4) -#define I2C_CONR_ACK (~(1<<4)) -#define I2C_CONR_MTX_MODE (1<<3) -#define I2C_CONR_MRX_MODE (~(1<<3)) -#define I2C_CONR_MPORT_ENABLE (1<<2) -#define I2C_CONR_MPORT_DISABLE (~(1<<2)) - -/* i2c core config */ -#define I2C_OPR (0x0028) -#define I2C_OPR_RESET_STATUS (1<<7) -#define I2C_OPR_CORE_ENABLE (1<<6) - -#define I2CCDVR_REM_BITS (0x03) -#define I2CCDVR_REM_MAX (1<<(I2CCDVR_REM_BITS)) -#define I2CCDVR_EXP_BITS (0x03) -#define I2CCDVR_EXP_MAX (1<<(I2CCDVR_EXP_BITS)) - -#endif diff --git a/drivers/i2c/busses/i2c-rk30-adapter.c b/drivers/i2c/busses/i2c-rk30-adapter.c deleted file mode 100644 index 44b2f3eca852..000000000000 --- a/drivers/i2c/busses/i2c-rk30-adapter.c +++ /dev/null @@ -1,708 +0,0 @@ -/* drivers/i2c/busses/i2c-rk30-adapter.c - * - * Copyright (C) 2012 ROCKCHIP, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ -#include "i2c-rk30.h" - -#define COMPLETE_READ (1<dev, "i2c->clk = %lu\n", clk_get_rate(i2c->clk)); - dev_info(i2c->dev, "i2c->start = %d\n", i2c->state); - dev_info(i2c->dev, "I2C_CON: 0x%08x\n", i2c_readl(i2c->regs + I2C_CON)); - dev_info(i2c->dev, "I2C_CLKDIV: 0x%08x\n", i2c_readl(i2c->regs + I2C_CLKDIV)); - dev_info(i2c->dev, "I2C_MRXADDR: 0x%08x\n", i2c_readl(i2c->regs + I2C_MRXADDR)); - dev_info(i2c->dev, "I2C_MRXRADDR: 0x%08x\n", i2c_readl(i2c->regs + I2C_MRXRADDR)); - dev_info(i2c->dev, "I2C_MTXCNT: 0x%08x\n", i2c_readl(i2c->regs + I2C_MTXCNT)); - dev_info(i2c->dev, "I2C_MRXCNT: 0x%08x\n", i2c_readl(i2c->regs + I2C_MRXCNT)); - dev_info(i2c->dev, "I2C_IEN: 0x%08x\n", i2c_readl(i2c->regs + I2C_IEN)); - dev_info(i2c->dev, "I2C_IPD: 0x%08x\n", i2c_readl(i2c->regs + I2C_IPD)); - dev_info(i2c->dev, "I2C_FCNT: 0x%08x\n", i2c_readl(i2c->regs + I2C_FCNT)); - for( i = 0; i < 8; i ++) - dev_info(i2c->dev, "I2C_TXDATA%d: 0x%08x\n", i, i2c_readl(i2c->regs + I2C_TXDATA_BASE + i * 4)); - for( i = 0; i < 8; i ++) - dev_info(i2c->dev, "I2C_RXDATA%d: 0x%08x\n", i, i2c_readl(i2c->regs + I2C_RXDATA_BASE + i * 4)); -} - -static int rk30_i2c_check_idle(struct rk30_i2c *i2c) -{ - int ret = 0; - int sda_io, scl_io; - int sda_lev, scl_lev; - - sda_io = iomux_mode_to_gpio(i2c->sda_mode); - scl_io = iomux_mode_to_gpio(i2c->scl_mode); - - ret = gpio_request(sda_io, NULL); - if(unlikely(ret < 0)){ - dev_err(i2c->dev, "Failed to request gpio: SDA_GPIO\n"); - return ret; - } - ret = gpio_request(scl_io, NULL); - if(unlikely(ret < 0)){ - dev_err(i2c->dev, "Failed to request gpio: SCL_GPIO\n"); - gpio_free(sda_io); - return ret; - } - gpio_direction_input(sda_io); - gpio_direction_input(scl_io); - - sda_lev = gpio_get_value(sda_io); - scl_lev = gpio_get_value(scl_io); - - gpio_free(sda_io); - gpio_free(scl_io); - - iomux_set(i2c->sda_mode); - iomux_set(i2c->scl_mode); - - if(sda_lev == 1 && scl_lev == 1) - return I2C_IDLE; - else if(sda_lev == 0 && scl_lev == 1) - return I2C_SDA_LOW; - else if(sda_lev == 1 && scl_lev == 0) - return I2C_SCL_LOW; - else - return BOTH_LOW; -} -static inline void rk30_i2c_enable(struct rk30_i2c *i2c, unsigned int lastnak) -{ - unsigned int con = 0; - - con |= I2C_CON_EN; - con |= I2C_CON_MOD(i2c->mode); - if(lastnak) - con |= I2C_CON_LASTACK; - con |= I2C_CON_START; - i2c_writel(con, i2c->regs + I2C_CON); -} -static inline void rk30_i2c_disable(struct rk30_i2c *i2c) -{ - i2c_writel( 0, i2c->regs + I2C_CON); -} - -static inline void rk30_i2c_clean_start(struct rk30_i2c *i2c) -{ - unsigned int con = i2c_readl(i2c->regs + I2C_CON); - - con &= ~I2C_CON_START; - i2c_writel(con, i2c->regs + I2C_CON); -} -static inline void rk30_i2c_send_start(struct rk30_i2c *i2c) -{ - unsigned int con = i2c_readl(i2c->regs + I2C_CON); - - con |= I2C_CON_START; - if(con & I2C_CON_STOP) - dev_warn(i2c->dev, "I2C_CON: stop bit is set\n"); - - i2c_writel(con, i2c->regs + I2C_CON); -} -static inline void rk30_i2c_send_stop(struct rk30_i2c *i2c) -{ - unsigned int con = i2c_readl(i2c->regs + I2C_CON); - - con |= I2C_CON_STOP; - if(con & I2C_CON_START) - dev_warn(i2c->dev, "I2C_CON: start bit is set\n"); - - i2c_writel(con, i2c->regs + I2C_CON); -} -static inline void rk30_i2c_clean_stop(struct rk30_i2c *i2c) -{ - unsigned int con = i2c_readl(i2c->regs + I2C_CON); - - con &= ~I2C_CON_STOP; - i2c_writel(con, i2c->regs + I2C_CON); -} - -static inline void rk30_i2c_disable_irq(struct rk30_i2c *i2c) -{ - i2c_writel(IRQ_ALL_DISABLE, i2c->regs + I2C_IEN); -} - -static inline void rk30_i2c_enable_irq(struct rk30_i2c *i2c) -{ - i2c_writel(IRQ_MST_ENABLE, i2c->regs + I2C_IEN); -} -static void rk30_get_div(int div, int *divh, int *divl) -{ - if(div % 2 == 0){ - *divh = div/2; - *divl = div/2; - }else{ - *divh = rk30_ceil(div, 2); - *divl = div/2; - } -} -/* SCL Divisor = 8 * (CLKDIVL+1 + CLKDIVH+1) - * SCL = i2c_rate/ SCLK Divisor -*/ -static void rk30_i2c_set_clk(struct rk30_i2c *i2c, unsigned long scl_rate) -{ - unsigned long i2c_rate = clk_get_rate(i2c->clk); - - int div, divl, divh; - - if((scl_rate == i2c->scl_rate) && (i2c_rate == i2c->i2c_rate)) - return; - i2c->i2c_rate = i2c_rate; - i2c->scl_rate = scl_rate; - div = rk30_ceil(i2c_rate, (scl_rate * 8)) - 2; - if(unlikely(div < 0)){ - dev_warn(i2c->dev, "Divisor(%d) is negative, set divl = divh = 0\n", div); - divh =divl = 0; - }else{ - rk30_get_div(div, &divh, &divl); - } - i2c_writel(I2C_CLKDIV_VAL(divl, divh), i2c->regs + I2C_CLKDIV); - i2c_dbg(i2c->dev, "set clk(I2C_CLKDIV: 0x%08x)\n", i2c_readl(i2c->regs + I2C_CLKDIV)); - return; -} -static void rk30_i2c_init_hw(struct rk30_i2c *i2c, unsigned long scl_rate) -{ - i2c->scl_rate = 0; - rk30_i2c_set_clk(i2c, scl_rate); - return; -} -/* returns TRUE if we this is the last byte in the current message */ -static inline int is_msglast(struct rk30_i2c *i2c) -{ - return i2c->msg_ptr == i2c->msg->len-1; -} - -/* returns TRUE if we reached the end of the current message */ -static inline int is_msgend(struct rk30_i2c *i2c) -{ - return i2c->msg_ptr >= i2c->msg->len; -} - -static void rk30_i2c_stop(struct rk30_i2c *i2c, int ret) -{ - - i2c->msg_ptr = 0; - i2c->msg = NULL; - if(ret == -EAGAIN){ - i2c->state = STATE_IDLE; - i2c->is_busy = 0; - wake_up(&i2c->wait); - return; - } - i2c->error = ret; - i2c_writel(I2C_STOPIEN, i2c->regs + I2C_IEN); - i2c->state = STATE_STOP; - rk30_i2c_send_stop(i2c); - return; -} -static inline void rk30_set_rx_mode(struct rk30_i2c *i2c, unsigned int lastnak) -{ - unsigned long con = i2c_readl(i2c->regs + I2C_CON); - - con &= (~I2C_CON_MASK); - con |= (I2C_CON_MOD_RX << 1); - if(lastnak) - con |= I2C_CON_LASTACK; - i2c_writel(con, i2c->regs + I2C_CON); -} -static void rk30_irq_read_prepare(struct rk30_i2c *i2c) -{ - unsigned int cnt, len = i2c->msg->len - i2c->msg_ptr; - - if(len <= 32 && i2c->msg_ptr != 0) - rk30_set_rx_mode(i2c, 1); - else if(i2c->msg_ptr != 0) - rk30_set_rx_mode(i2c, 0); - - if(is_msgend(i2c)) { - rk30_i2c_stop(i2c, i2c->error); - return; - } - if(len > 32) - cnt = 32; - else - cnt = len; - i2c_writel(cnt, i2c->regs + I2C_MRXCNT); -} -static void rk30_irq_read_get_data(struct rk30_i2c *i2c) -{ - unsigned int i, len = i2c->msg->len - i2c->msg_ptr; - unsigned int p = 0; - - len = (len >= 32)?32:len; - - for(i = 0; i < len; i++){ - if(i%4 == 0) - p = i2c_readl(i2c->regs + I2C_RXDATA_BASE + (i/4) * 4); - i2c->msg->buf[i2c->msg_ptr++] = (p >>((i%4) * 8)) & 0xff; - } - - return; -} -static void rk30_irq_write_prepare(struct rk30_i2c *i2c) -{ - unsigned int data = 0, cnt = 0, i, j; - unsigned char byte; - - if(is_msgend(i2c)) { - rk30_i2c_stop(i2c, i2c->error); - return; - } - for(i = 0; i < 8; i++){ - data = 0; - for(j = 0; j < 4; j++) { - if(is_msgend(i2c)) - break; - if((i2c->msg_ptr == 0) && (cnt == 0)) - byte = (i2c->addr_1st & 0x7f) << 1; - else if((i2c->msg_ptr == 0) && (cnt == 1) && (i2c->msg->flags & I2C_M_TEN)) - byte = i2c->addr_2nd; - else - byte = i2c->msg->buf[i2c->msg_ptr++]; - cnt++; - data |= (byte << (j * 8)); - } - i2c_writel(data, i2c->regs + I2C_TXDATA_BASE + 4 * i); - if(is_msgend(i2c)) - break; - } - i2c_writel(cnt, i2c->regs + I2C_MTXCNT); -} -static void rk30_i2c_irq_nextblock(struct rk30_i2c *i2c, unsigned int ipd) -{ - switch (i2c->state) { - case STATE_START: - if(!(ipd & I2C_STARTIPD)){ - rk30_i2c_stop(i2c, -ENXIO); - dev_err(i2c->dev, "Addr[0x%04x] no start irq in STATE_START\n", i2c->addr); - rk30_show_regs(i2c); - i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); - goto out; - } - i2c->complete_what |= 1<state; - i2c_writel(I2C_STARTIPD, i2c->regs + I2C_IPD); - rk30_i2c_clean_start(i2c); - if(i2c->mode == I2C_CON_MOD_TX){ - i2c_writel(I2C_MBTFIEN | I2C_NAKRCVIEN, i2c->regs + I2C_IEN); - i2c->state = STATE_WRITE; - goto prepare_write; - } else { - i2c_writel(I2C_MBRFIEN | I2C_NAKRCVIEN, i2c->regs + I2C_IEN); - i2c->state = STATE_READ; - goto prepare_read; - } - case STATE_WRITE: - if(!(ipd & I2C_MBTFIPD)){ - rk30_i2c_stop(i2c, -ENXIO); - dev_err(i2c->dev, "Addr[0x%04x] no mbtf irq in STATE_WRITE\n", i2c->addr); - rk30_show_regs(i2c); - i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); - goto out; - } - i2c->complete_what |= 1<state; - i2c_writel(I2C_MBTFIPD, i2c->regs + I2C_IPD); -prepare_write: - rk30_irq_write_prepare(i2c); - break; - case STATE_READ: - if(!(ipd & I2C_MBRFIPD)){ - rk30_i2c_stop(i2c, -ENXIO); - dev_err(i2c->dev, "Addr[0x%04x] no mbrf irq in STATE_READ, ipd = 0x%x\n", i2c->addr, ipd); - rk30_show_regs(i2c); - i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); - goto out; - } - i2c->complete_what |= 1<state; - i2c_writel(I2C_MBRFIPD, i2c->regs + I2C_IPD); - rk30_irq_read_get_data(i2c); -prepare_read: - rk30_irq_read_prepare(i2c); - break; - case STATE_STOP: - if(!(ipd & I2C_STOPIPD)){ - rk30_i2c_stop(i2c, -ENXIO); - dev_err(i2c->dev, "Addr[0x%04x] no stop irq in STATE_STOP\n", i2c->addr); - rk30_show_regs(i2c); - i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); - goto out; - } - rk30_i2c_clean_stop(i2c); - i2c_writel(I2C_STOPIPD, i2c->regs + I2C_IPD); - i2c->is_busy = 0; - i2c->complete_what |= 1<state; - i2c->state = STATE_IDLE; - wake_up(&i2c->wait); - break; - default: - break; - } -out: - return; -} -static irqreturn_t rk30_i2c_irq(int irq, void *dev_id) -{ - struct rk30_i2c *i2c = dev_id; - unsigned int ipd; - - spin_lock(&i2c->lock); - ipd = i2c_readl(i2c->regs + I2C_IPD); - if(i2c->state == STATE_IDLE){ - dev_info(i2c->dev, "Addr[0x%04x] irq in STATE_IDLE, ipd = 0x%x\n", i2c->addr, ipd); - i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); - goto out; - } - - if(ipd & I2C_NAKRCVIPD){ - i2c_writel(I2C_NAKRCVIPD, i2c->regs + I2C_IPD); - i2c->error = -EAGAIN; - goto out; - } - rk30_i2c_irq_nextblock(i2c, ipd); -out: - spin_unlock(&i2c->lock); - return IRQ_HANDLED; -} - - -static int rk30_i2c_set_master(struct rk30_i2c *i2c, struct i2c_msg *msgs, int num) -{ - unsigned int reg_valid_bits = 0; - unsigned int reg_addr = 0; - unsigned int addr = (i2c->addr_1st << 1) | 1; - - if(num == 1) { - i2c->count = msgs[0].len; - if(!(msgs[0].flags & I2C_M_RD)){ - i2c->msg = &msgs[0]; - i2c->mode = I2C_CON_MOD_TX; - } - else { - i2c->msg = &msgs[0]; - i2c_writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR); - i2c_writel(0, i2c->regs + I2C_MRXRADDR); - i2c->mode = I2C_CON_MOD_TRX; - //i2c->mode = I2C_CON_MOD_RX; - } - } - else if(num == 2) { - i2c->count = msgs[1].len; - - if(msgs[0].flags & I2C_M_TEN){ - switch(msgs[0].len){ - case 1: - reg_addr = i2c->addr_2nd | (msgs[0].buf[0] << 8); - reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID; - break; - case 2: - reg_addr = i2c->addr_2nd | (msgs[0].buf[0] << 8) | (msgs[0].buf[1] << 16); - reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID | I2C_MRXADDR_HIGH; - break; - default: - return -EIO; - } - }else{ - switch(msgs[0].len){ - case 1: - reg_addr = msgs[0].buf[0]; - reg_valid_bits |= I2C_MRXADDR_LOW; - break; - case 2: - reg_addr = msgs[0].buf[0] | (msgs[0].buf[1] << 8); - reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID; - break; - case 3: - reg_addr = msgs[0].buf[0] | (msgs[0].buf[1] << 8) | (msgs[0].buf[2] << 16); - reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID | I2C_MRXADDR_HIGH; - break; - default: - return -EIO; - } - } - if((msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) { - i2c->msg = &msgs[1]; - i2c_writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR); - i2c_writel(reg_addr | reg_valid_bits, i2c->regs + I2C_MRXRADDR); - i2c->mode = I2C_CON_MOD_RRX; - } - else if(!(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) { - i2c->msg = &msgs[1]; - i2c_writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR); - i2c_writel(reg_addr | reg_valid_bits, i2c->regs + I2C_MRXRADDR); - i2c->mode = I2C_CON_MOD_TRX; - } - else - return -EIO; - } - else { - dev_err(i2c->dev, "This case(num > 2) has not been support now\n"); - return -EIO; - } - - return 0; -} -/* rk30_i2c_doxfer - * - * this starts an i2c transfer -*/ -static int rk30_i2c_doxfer(struct rk30_i2c *i2c, - struct i2c_msg *msgs, int num) -{ - unsigned long timeout, flags; - int error = 0; - /* 32 -- max transfer bytes - * 2 -- addr bytes * 2 - * 3 -- max reg addr bytes - * 9 -- cycles per bytes - * max cycles: (32 + 2 + 3) * 9 --> 400 cycles - */ - int msleep_time = 400 * 1000/ i2c->scl_rate; // ms - - if (i2c->suspended){ - dev_err(i2c->dev, "i2c is suspended\n"); - return -EIO; - } - - spin_lock_irqsave(&i2c->lock, flags); - i2c->addr = msgs[0].addr; - if(msgs[0].flags & I2C_M_TEN){ - i2c->addr_1st = ((i2c->addr & 0x0300)>>8) | 0x78; - i2c->addr_2nd = i2c->addr & 0x00ff; - }else{ - i2c->addr_1st = i2c->addr & 0x007f; - i2c->addr_2nd = 0; - } - i2c_dbg(i2c->dev, "addr: 0x%04x, addr_1st: 0x%02x, addr_2nd: 0x%02x\n", - i2c->addr, i2c->addr_1st, i2c->addr_2nd); - - if(rk30_i2c_set_master(i2c, msgs, num) < 0){ - spin_unlock_irqrestore(&i2c->lock, flags); - dev_err(i2c->dev, "addr[0x%04x] set master error\n", msgs[0].addr); - return -EIO; - } - i2c->msg_ptr = 0; - i2c->error = 0; - i2c->is_busy = 1; - i2c->state = STATE_START; - i2c->complete_what = 0; - i2c_writel(I2C_STARTIEN, i2c->regs + I2C_IEN); - spin_unlock_irqrestore(&i2c->lock, flags); - - rk30_i2c_enable(i2c, (i2c->count > 32)?0:1); //if count > 32, byte(32) send ack - - if (in_atomic()){ - int tmo = I2C_WAIT_TIMEOUT * USEC_PER_MSEC; - while(tmo-- && i2c->is_busy != 0) - udelay(1); - timeout = (tmo <= 0)?0:1; - }else - timeout = wait_event_timeout(i2c->wait, (i2c->is_busy == 0), msecs_to_jiffies(I2C_WAIT_TIMEOUT)); - - spin_lock_irqsave(&i2c->lock, flags); - i2c->state = STATE_IDLE; - error = i2c->error; - spin_unlock_irqrestore(&i2c->lock, flags); - - if (timeout == 0){ - unsigned int ipd = i2c_readl(i2c->regs + I2C_IPD); - if(error < 0) - i2c_dbg(i2c->dev, "error = %d\n", error); - else if((i2c->complete_what !=COMPLETE_READ && i2c->complete_what != COMPLETE_WRITE)){ - if(ipd & I2C_HOLD_SCL) - dev_err(i2c->dev, "SCL was hold by slave\n"); - dev_err(i2c->dev, "Addr[0x%04x] wait event timeout, state: %d, is_busy: %d, error: %d, complete_what: 0x%x, ipd: 0x%x\n", - msgs[0].addr, i2c->state, i2c->is_busy, error, i2c->complete_what, ipd); - //rk30_show_regs(i2c); - error = -ETIMEDOUT; - if(in_atomic()) - mdelay(msleep_time); - else - msleep(msleep_time); - rk30_i2c_send_stop(i2c); - if(in_atomic()) - mdelay(1); - else - msleep(1); - } - else - i2c_dbg(i2c->dev, "Addr[0x%02x] wait event timeout, but transfer complete\n", i2c->addr); - } - i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); - rk30_i2c_disable_irq(i2c); - rk30_i2c_disable(i2c); - - if(error == -EAGAIN) - i2c_dbg(i2c->dev, "No ack(complete_what: 0x%x), Maybe slave(addr: 0x%04x) not exist or abnormal power-on\n", - i2c->complete_what, i2c->addr); - return error; -} - -/* rk30_i2c_xfer - * - * first port of call from the i2c bus code when an message needs - * transferring across the i2c bus. -*/ - -static int rk30_i2c_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) -{ - int ret = 0, state, retry = 10; - unsigned long scl_rate; - struct rk30_i2c *i2c = (struct rk30_i2c *)adap->algo_data; - - clk_enable(i2c->clk); -#ifdef I2C_CHECK_IDLE - while(retry-- && ((state = rk30_i2c_check_idle(i2c)) != I2C_IDLE)){ - if(in_atomic()) - mdelay(10); - else - msleep(10); - } - if(retry == 0){ - dev_err(i2c->dev, "i2c is not in idle(state = %d)\n", state); - return -EIO; - } -#endif - - if(msgs[0].scl_rate <= 400000 && msgs[0].scl_rate >= 10000) - scl_rate = msgs[0].scl_rate; - else if(msgs[0].scl_rate > 400000){ - dev_warn(i2c->dev, "Warning: addr[0x%04x] msg[0].scl_rate( = %dKhz) is too high!", - msgs[0].addr, msgs[0].scl_rate/1000); - scl_rate = 400000; - } - else{ - dev_warn(i2c->dev, "Warning: addr[0x%04x] msg[0].scl_rate( = %dKhz) is too low!", - msgs[0].addr, msgs[0].scl_rate/1000); - scl_rate = 10000; - } - if(i2c->is_div_from_arm[i2c->adap.nr]){ - mutex_lock(&i2c->m_lock); - } - - rk30_i2c_set_clk(i2c, scl_rate); - i2c_dbg(i2c->dev, "i2c transfer start: addr: 0x%04x, scl_reate: %ldKhz, len: %d\n", msgs[0].addr, scl_rate/1000, num); - ret = rk30_i2c_doxfer(i2c, msgs, num); - i2c_dbg(i2c->dev, "i2c transfer stop: addr: 0x%04x, state: %d, ret: %d\n", msgs[0].addr, ret, i2c->state); - - if(i2c->is_div_from_arm[i2c->adap.nr]){ - mutex_unlock(&i2c->m_lock); - } - - clk_disable(i2c->clk); - return (ret < 0)?ret:num; -} - -/* declare our i2c functionality */ -static u32 rk30_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING; -} - -/* i2c bus registration info */ - -static const struct i2c_algorithm rk30_i2c_algorithm = { - .master_xfer = rk30_i2c_xfer, - .functionality = rk30_i2c_func, -}; - -int i2c_add_rk30_adapter(struct i2c_adapter *adap) -{ - int ret = 0; - struct rk30_i2c *i2c = (struct rk30_i2c *)adap->algo_data; - - adap->algo = &rk30_i2c_algorithm; - - i2c->i2c_init_hw = &rk30_i2c_init_hw; - i2c->i2c_set_clk = &rk30_i2c_set_clk; - i2c->i2c_irq = &rk30_i2c_irq; - - ret = i2c_add_numbered_adapter(adap); - - return ret; -} - diff --git a/drivers/i2c/busses/i2c-rk30.c b/drivers/i2c/busses/i2c-rk30.c deleted file mode 100755 index 146b9cc21802..000000000000 --- a/drivers/i2c/busses/i2c-rk30.c +++ /dev/null @@ -1,407 +0,0 @@ -/* drivers/i2c/busses/i2c-rk30.c - * - * Copyright (C) 2012 ROCKCHIP, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ -#include "i2c-rk30.h" -#define TX_SETUP 1 - -static int i2c_max_adap = 0; -void i2c_adap_sel(struct rk30_i2c *i2c, int nr, int adap_type) -{ - i2c_writel((1 << I2C_ADAP_SEL_BIT(nr)) | (1 << I2C_ADAP_SEL_MASK(nr)) , - i2c->con_base); -} - -#ifdef CONFIG_CPU_FREQ - -#define freq_to_i2c(_n) container_of(_n, struct rk30_i2c, freq_transition) - -static int rk30_i2c_cpufreq_transition(struct notifier_block *nb, - unsigned long val, void *data) -{ - struct rk30_i2c *i2c = freq_to_i2c(nb); - struct cpufreq_freqs *freqs = data; - - if (freqs->cpu) - return 0; - - if(val == CPUFREQ_PRECHANGE) - mutex_lock(&i2c->m_lock); - else if(val == CPUFREQ_POSTCHANGE) - mutex_unlock(&i2c->m_lock); - - return 0; -} - -static inline int rk30_i2c_register_cpufreq(struct rk30_i2c *i2c) -{ - if(!i2c->is_div_from_arm[i2c->adap.nr]) - return 0; - i2c->freq_transition.notifier_call = rk30_i2c_cpufreq_transition; - - return cpufreq_register_notifier(&i2c->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -} - -static inline void rk30_i2c_deregister_cpufreq(struct rk30_i2c *i2c) -{ - if(!i2c->is_div_from_arm[i2c->adap.nr]) - return; - cpufreq_unregister_notifier(&i2c->freq_transition, - CPUFREQ_TRANSITION_NOTIFIER); -} - -#else -static inline int rk30_i2c_register_cpufreq(struct rk30_i2c *i2c) -{ - return 0; -} - -static inline void rk30_i2c_deregister_cpufreq(struct rk30_i2c *i2c) -{ -} -#endif - -/* rk30_i2c_probe - * - * called by the bus driver when a suitable device is found -*/ - -static int rk30_i2c_probe(struct platform_device *pdev) -{ - struct rk30_i2c *i2c = NULL; - struct rk30_i2c_platform_data *pdata = NULL; - struct resource *res; - int ret; - - pdata = pdev->dev.platform_data; - if (!pdata) { - dev_err(&pdev->dev, "no platform data\n"); - return -EINVAL; - } - - - i2c = kzalloc(sizeof(struct rk30_i2c), GFP_KERNEL); - if (!i2c) { - dev_err(&pdev->dev, "no memory for state\n"); - return -ENOMEM; - } - -#if !defined(CONFIG_ARCH_RK319X) - i2c->con_base = (void __iomem *)GRF_I2C_CON_BASE; - i2c_adap_sel(i2c, pdata->bus_num, pdata->adap_type); -#endif - - if(pdata->io_init) - pdata->io_init(); - - i2c->sda_mode = pdata->sda_mode; - i2c->scl_mode = pdata->scl_mode; - - strlcpy(i2c->adap.name, "rk30_i2c", sizeof(i2c->adap.name)); - i2c->adap.owner = THIS_MODULE; - i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - i2c->tx_setup = TX_SETUP; - i2c->adap.retries = 2; - i2c->adap.timeout = msecs_to_jiffies(100); - - spin_lock_init(&i2c->lock); - init_waitqueue_head(&i2c->wait); - mutex_init(&i2c->m_lock); - - /* find the clock and enable it */ - - i2c->dev = &pdev->dev; - i2c->clk = clk_get(&pdev->dev, "i2c"); - if (IS_ERR(i2c->clk)) { - dev_err(&pdev->dev, "cannot get clock\n"); - ret = -ENOENT; - goto err_noclk; - } - - i2c_dbg(&pdev->dev, "clock source %p\n", i2c->clk); - - clk_enable(i2c->clk); - - /* map the registers */ - - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - if (res == NULL) { - dev_err(&pdev->dev, "cannot find IO resource\n"); - ret = -ENOENT; - goto err_get_resource; - } - - i2c->ioarea = request_mem_region(res->start, resource_size(res), - pdev->name); - - if (i2c->ioarea == NULL) { - dev_err(&pdev->dev, "cannot request IO\n"); - ret = -ENXIO; - goto err_ioarea; - } - - i2c->regs = ioremap(res->start, resource_size(res)); - - if (i2c->regs == NULL) { - dev_err(&pdev->dev, "cannot map IO\n"); - ret = -ENXIO; - goto err_ioremap; - } - - i2c_dbg(&pdev->dev, "registers %p (%p, %p)\n", - i2c->regs, i2c->ioarea, res); - - /* setup info block for the i2c core */ - - i2c->adap.algo_data = i2c; - i2c->adap.dev.parent = &pdev->dev; - i2c->adap.nr = pdata->bus_num; - if(pdata->adap_type == I2C_RK29_ADAP) - ret = i2c_add_rk29_adapter(&i2c->adap); - else // I2C_RK30_ADAP - ret = i2c_add_rk30_adapter(&i2c->adap); - - if (ret < 0) { - dev_err(&pdev->dev, "failed to add adapter\n"); - goto err_add_adapter; - } - - /* find the IRQ for this unit (note, this relies on the init call to - * ensure no current IRQs pending - */ - - i2c->irq = ret = platform_get_irq(pdev, 0); - if (ret <= 0) { - dev_err(&pdev->dev, "cannot find IRQ\n"); - goto err_get_irq; - } - - ret = request_irq(i2c->irq, i2c->i2c_irq, IRQF_DISABLED, - dev_name(&pdev->dev), i2c); - - if (ret != 0) { - dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); - goto err_request_irq; - } - - ret = rk30_i2c_register_cpufreq(i2c); - if (ret < 0) { - dev_err(&pdev->dev, "failed to register cpufreq notifier\n"); - goto err_register_cpufreq; - } - - platform_set_drvdata(pdev, i2c); - - i2c->is_div_from_arm[i2c->adap.nr] = pdata->is_div_from_arm; - - i2c->i2c_init_hw(i2c, 100 * 1000); - i2c_max_adap++; - dev_info(&pdev->dev, "%s: RK30 I2C adapter\n", dev_name(&i2c->adap.dev)); - return 0; -//err_none: -// rk30_i2c_deregister_cpufreq(i2c); -err_register_cpufreq: - free_irq(i2c->irq, i2c); -err_request_irq: -err_get_irq: - i2c_del_adapter(&i2c->adap); -err_add_adapter: - iounmap(i2c->regs); -err_ioremap: - kfree(i2c->ioarea); -err_ioarea: - release_resource(i2c->ioarea); -err_get_resource: - clk_put(i2c->clk); -err_noclk: - kfree(i2c); - return ret; -} - -/* rk30_i2c_remove - * - * called when device is removed from the bus -*/ - -static int rk30_i2c_remove(struct platform_device *pdev) -{ - struct rk30_i2c *i2c = platform_get_drvdata(pdev); - - rk30_i2c_deregister_cpufreq(i2c); - free_irq(i2c->irq, i2c); - i2c_del_adapter(&i2c->adap); - iounmap(i2c->regs); - kfree(i2c->ioarea); - release_resource(i2c->ioarea); - clk_put(i2c->clk); - kfree(i2c); - return 0; -} - -#ifdef CONFIG_PM -static int rk30_i2c_suspend_noirq(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rk30_i2c *i2c = platform_get_drvdata(pdev); - - i2c->suspended = 1; - - return 0; -} - -static int rk30_i2c_resume_noirq(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rk30_i2c *i2c = platform_get_drvdata(pdev); - - i2c->suspended = 0; - i2c->i2c_init_hw(i2c, i2c->scl_rate); - - return 0; -} - -static const struct dev_pm_ops rk30_i2c_dev_pm_ops = { - .suspend_noirq = rk30_i2c_suspend_noirq, - .resume_noirq = rk30_i2c_resume_noirq, -}; - -#define rk30_DEV_PM_OPS (&rk30_i2c_dev_pm_ops) -#else -#define rk30_DEV_PM_OPS NULL -#endif - -MODULE_DEVICE_TABLE(platform, rk30_driver_ids); - -static struct platform_driver rk30_i2c_driver = { - .probe = rk30_i2c_probe, - .remove = rk30_i2c_remove, - .driver = { - .owner = THIS_MODULE, - .name = "rk30_i2c", - .pm = rk30_DEV_PM_OPS, - }, -}; - -static int __init i2c_adap_init(void) -{ - return platform_driver_register(&rk30_i2c_driver); -} -subsys_initcall(i2c_adap_init); - -static void __exit i2c_adap_exit(void) -{ - platform_driver_unregister(&rk30_i2c_driver); -} -module_exit(i2c_adap_exit); - -static int detect_read(struct i2c_client *client, char *buf, int len) -{ - struct i2c_msg msg; - - msg.addr = client->addr; - msg.flags = client->flags | I2C_M_RD; - msg.buf = buf; - msg.len = len; - msg.scl_rate = 100 * 1000; - - return i2c_transfer(client->adapter, &msg, 1); -} - -static void detect_set_client(struct i2c_client *client, __u16 addr, int nr) -{ - client->flags = 0; - client->addr = addr; - client->adapter = i2c_get_adapter(nr); -} -static void slave_detect(int nr) -{ - int ret = 0; - unsigned short addr; - char val[8]; - char buf[6 * 0x80 + 20]; - struct i2c_client client; - - memset(buf, 0, 6 * 0x80 + 20); - - sprintf(buf, "I2c%d slave list: ", nr); - do { - for(addr = 0x01; addr < 0x80; addr++){ - detect_set_client(&client, addr, nr); - ret = detect_read(&client, val, 1); - if(ret > 0) - sprintf(buf, "%s 0x%02x", buf, addr); - } - printk("%s\n", buf); - } - while(0); -} -static ssize_t i2c_detect_write(struct file *file, - const char __user *buf, size_t count, loff_t *offset) -{ - char nr_buf[8]; - int nr = 0, ret; - - if(count > 4) - return -EFAULT; - ret = copy_from_user(nr_buf, buf, count); - if(ret < 0) - return -EFAULT; - - sscanf(nr_buf, "%d", &nr); - if(nr >= 5 || nr < 0) - return -EFAULT; - - slave_detect(nr); - - return count; -} - - -static const struct file_operations i2c_detect_fops = { - .write = i2c_detect_write, -}; -static struct miscdevice i2c_detect_device = { - .minor = MISC_DYNAMIC_MINOR, - .name = "i2c_detect", - .fops = &i2c_detect_fops, -}; -static int __init i2c_detect_init(void) -{ - return misc_register(&i2c_detect_device); -} - -static void __exit i2c_detect_exit(void) -{ - misc_deregister(&i2c_detect_device); -} -module_init(i2c_detect_init); -module_exit(i2c_detect_exit); - -static int __init i2c_detect_rk610(void) -{ - int i; - - for(i = 0; i < i2c_max_adap; i++){ - i2c_check_rk610_ex(i); - } - return 0; -} -late_initcall(i2c_detect_rk610); - - - - -MODULE_DESCRIPTION("Driver for RK30 I2C Bus"); -MODULE_AUTHOR("kfx, kfx@rock-chips.com"); -MODULE_LICENSE("GPL"); diff --git a/drivers/i2c/busses/i2c-rk30.h b/drivers/i2c/busses/i2c-rk30.h deleted file mode 100755 index c1dd7a29f0df..000000000000 --- a/drivers/i2c/busses/i2c-rk30.h +++ /dev/null @@ -1,120 +0,0 @@ -#ifndef __RK30_I2C_H__ -#define __RK30_I2C_H__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if 0 -#define i2c_dbg(dev, format, arg...) \ - dev_printk(KERN_INFO , dev , format , ## arg) -#else -#define i2c_dbg(dev, format, arg...) -#endif - -#define I2C_CHECK_IDLE - -#define i2c_writel writel_relaxed -#define i2c_readl readl_relaxed - -#define I2C_WAIT_TIMEOUT 200 //200ms - -#define rk30_set_bit(p, v, b) (((p) & ~(1 << (b))) | ((v) << (b))) -#define rk30_get_bit(p, b) (((p) & (1 << (b))) >> (b)) - -#define rk30_set_bits(p, v, b, m) (((p) & ~(m)) | ((v) << (b))) -#define rk30_get_bits(p, b, m) (((p) & (m)) >> (b)) - -#define rk30_ceil(x, y) \ - ({ unsigned long __x = (x), __y = (y); (__x + __y - 1) / __y; }) -#if defined(CONFIG_ARCH_RK30) || defined(CONFIG_ARCH_RK3188) -#define GRF_I2C_CON_BASE (RK30_GRF_BASE + GRF_SOC_CON1) -#endif -#if defined(CONFIG_ARCH_RK2928) || defined(CONFIG_ARCH_RK3026) -#define GRF_I2C_CON_BASE (RK2928_GRF_BASE + GRF_SOC_CON1) -#endif -#define I2C_ADAP_SEL_BIT(nr) ((nr) + 11) -#define I2C_ADAP_SEL_MASK(nr) ((nr) + 27) -enum rk30_i2c_state { - STATE_IDLE, - STATE_START, - STATE_READ, - STATE_WRITE, - STATE_STOP -}; -struct rk30_i2c { - spinlock_t lock; - wait_queue_head_t wait; - struct mutex m_lock; - unsigned int suspended:1; - - struct i2c_msg *msg; - union { - unsigned int msg_num; - unsigned int is_busy; - }; - union { - unsigned int msg_idx; - int error; - }; - unsigned int msg_ptr; - - unsigned int tx_setup; - unsigned int irq; - - enum rk30_i2c_state state; - unsigned int complete_what; - unsigned long clkrate; - - void __iomem *regs; - void __iomem *con_base; - struct clk *clk; - struct device *dev; - struct resource *ioarea; - struct i2c_adapter adap; - - unsigned long scl_rate; - unsigned long i2c_rate; - unsigned int addr; - unsigned char addr_1st, addr_2nd; - unsigned int mode; - unsigned int count; - - int sda_mode, scl_mode; - - struct wake_lock idlelock[5]; - int is_div_from_arm[5]; - -#ifdef CONFIG_CPU_FREQ - struct notifier_block freq_transition; -#endif - - void (*i2c_init_hw)(struct rk30_i2c *, unsigned long scl_rate); - void (*i2c_set_clk)(struct rk30_i2c *, unsigned long); - int (*check_idle)(int); - irqreturn_t (*i2c_irq)(int, void *); -}; -void i2c_adap_sel(struct rk30_i2c *i2c, int nr, int adap_type); -int i2c_add_rk29_adapter(struct i2c_adapter *); -int i2c_add_rk30_adapter(struct i2c_adapter *); -#endif diff --git a/drivers/i2c/busses/i2c-rockchip.c b/drivers/i2c/busses/i2c-rockchip.c deleted file mode 100644 index 78bb407f1586..000000000000 --- a/drivers/i2c/busses/i2c-rockchip.c +++ /dev/null @@ -1,1132 +0,0 @@ -/* - * Copyright (C) 2012-2014 ROCKCHIP, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#if 0 -#define i2c_dbg(dev, format, arg...) \ - dev_printk(KERN_INFO , dev , format , ## arg) -#else -#define i2c_dbg(dev, format, arg...) -#endif - -enum { - I2C_IDLE = 0, - I2C_SDA_LOW, - I2C_SCL_LOW, - BOTH_LOW, -}; - -#define i2c_writel writel_relaxed -#define i2c_readl readl_relaxed - -#define I2C_WAIT_TIMEOUT 200 //200ms - -#define rockchip_set_bit(p, v, b) (((p) & ~(1 << (b))) | ((v) << (b))) -#define rockchip_get_bit(p, b) (((p) & (1 << (b))) >> (b)) - -#define rockchip_set_bits(p, v, b, m) (((p) & ~(m)) | ((v) << (b))) -#define rockchip_get_bits(p, b, m) (((p) & (m)) >> (b)) - -#define rockchip_ceil(x, y) \ - ({ unsigned long __x = (x), __y = (y); (__x + __y - 1) / __y; }) - -enum rockchip_i2c_state { - STATE_IDLE, - STATE_START, - STATE_READ, - STATE_WRITE, - STATE_STOP -}; - -struct rockchip_i2c { - spinlock_t lock; - wait_queue_head_t wait; - unsigned int suspended:1; - - struct i2c_msg *msg; - unsigned int is_busy; - int error; - unsigned int msg_ptr; - - unsigned int irq; - - enum rockchip_i2c_state state; - unsigned int complete_what; - unsigned long clkrate; - - void __iomem *regs; - struct clk *clk; - struct device *dev; - struct resource *ioarea; - struct i2c_adapter adap; - struct mutex suspend_lock; - - unsigned long scl_rate; - unsigned long i2c_rate; - unsigned int addr; - unsigned char addr_1st, addr_2nd; - unsigned int mode; - unsigned int count; - - unsigned int check_idle; - int sda_gpio, scl_gpio; - struct pinctrl_state *gpio_state; -}; - -#define COMPLETE_READ (1<dev, "i2c->clk = %lu\n", clk_get_rate(i2c->clk)); - dev_info(i2c->dev, "i2c->state = %d\n", i2c->state); - dev_info(i2c->dev, "I2C_CON: 0x%08x\n", i2c_readl(i2c->regs + I2C_CON)); - dev_info(i2c->dev, "I2C_CLKDIV: 0x%08x\n", i2c_readl(i2c->regs + I2C_CLKDIV)); - dev_info(i2c->dev, "I2C_MRXADDR: 0x%08x\n", i2c_readl(i2c->regs + I2C_MRXADDR)); - dev_info(i2c->dev, "I2C_MRXRADDR: 0x%08x\n", i2c_readl(i2c->regs + I2C_MRXRADDR)); - dev_info(i2c->dev, "I2C_MTXCNT: 0x%08x\n", i2c_readl(i2c->regs + I2C_MTXCNT)); - dev_info(i2c->dev, "I2C_MRXCNT: 0x%08x\n", i2c_readl(i2c->regs + I2C_MRXCNT)); - dev_info(i2c->dev, "I2C_IEN: 0x%08x\n", i2c_readl(i2c->regs + I2C_IEN)); - dev_info(i2c->dev, "I2C_IPD: 0x%08x\n", i2c_readl(i2c->regs + I2C_IPD)); - dev_info(i2c->dev, "I2C_FCNT: 0x%08x\n", i2c_readl(i2c->regs + I2C_FCNT)); - for (i = 0; i < 8; i++) - dev_info(i2c->dev, "I2C_TXDATA%d: 0x%08x\n", i, i2c_readl(i2c->regs + I2C_TXDATA_BASE + i * 4)); - for (i = 0; i < 8; i++) - dev_info(i2c->dev, "I2C_RXDATA%d: 0x%08x\n", i, i2c_readl(i2c->regs + I2C_RXDATA_BASE + i * 4)); -} - -static int rockchip_i2c_check_idle(struct rockchip_i2c *i2c) -{ - int ret = I2C_IDLE; - int sda_lev, scl_lev; - - if (!gpio_is_valid(i2c->sda_gpio)) - return ret; - - if (pinctrl_select_state(i2c->dev->pins->p, i2c->gpio_state)) - return ret; - - sda_lev = gpio_get_value(i2c->sda_gpio); - scl_lev = gpio_get_value(i2c->scl_gpio); - - pinctrl_select_state(i2c->dev->pins->p, i2c->dev->pins->default_state); - - if (sda_lev == 1 && scl_lev == 1) - return I2C_IDLE; - else if (sda_lev == 0 && scl_lev == 1) - return I2C_SDA_LOW; - else if (sda_lev == 1 && scl_lev == 0) - return I2C_SCL_LOW; - else - return BOTH_LOW; -} - -static inline void rockchip_i2c_enable(struct rockchip_i2c *i2c, unsigned int lastnak) -{ - unsigned int con = 0; - - con |= I2C_CON_EN; - con |= I2C_CON_MOD(i2c->mode); - if (lastnak) - con |= I2C_CON_LASTACK; - con |= I2C_CON_START; - i2c_writel(con, i2c->regs + I2C_CON); -} - -static inline void rockchip_i2c_disable(struct rockchip_i2c *i2c) -{ - i2c_writel(0, i2c->regs + I2C_CON); -} - -static inline void rockchip_i2c_clean_start(struct rockchip_i2c *i2c) -{ - unsigned int con = i2c_readl(i2c->regs + I2C_CON); - - con &= ~I2C_CON_START; - i2c_writel(con, i2c->regs + I2C_CON); -} - -static inline void rockchip_i2c_send_start(struct rockchip_i2c *i2c) -{ - unsigned int con = i2c_readl(i2c->regs + I2C_CON); - - con |= I2C_CON_START; - if (con & I2C_CON_STOP) - dev_warn(i2c->dev, "I2C_CON: stop bit is set\n"); - - i2c_writel(con, i2c->regs + I2C_CON); -} - -static inline void rockchip_i2c_send_stop(struct rockchip_i2c *i2c) -{ - unsigned int con = i2c_readl(i2c->regs + I2C_CON); - - con |= I2C_CON_STOP; - if (con & I2C_CON_START) - dev_warn(i2c->dev, "I2C_CON: start bit is set\n"); - - i2c_writel(con, i2c->regs + I2C_CON); -} - -static inline void rockchip_i2c_clean_stop(struct rockchip_i2c *i2c) -{ - unsigned int con = i2c_readl(i2c->regs + I2C_CON); - - con &= ~I2C_CON_STOP; - i2c_writel(con, i2c->regs + I2C_CON); -} - -static inline void rockchip_i2c_disable_irq(struct rockchip_i2c *i2c) -{ - i2c_writel(IRQ_ALL_DISABLE, i2c->regs + I2C_IEN); -} - -static inline void rockchip_i2c_enable_irq(struct rockchip_i2c *i2c) -{ - i2c_writel(IRQ_MST_ENABLE, i2c->regs + I2C_IEN); -} - -static void rockchip_get_div(int div, int *divh, int *divl) -{ - if (div % 2 == 0) { - *divh = div / 2; - *divl = div / 2; - } else { - *divh = rockchip_ceil(div, 2); - *divl = div / 2; - } -} - -/* SCL Divisor = 8 * (CLKDIVL+1 + CLKDIVH+1) - * SCL = i2c_rate/ SCLK Divisor -*/ -static void rockchip_i2c_set_clk(struct rockchip_i2c *i2c, unsigned long scl_rate) -{ - unsigned long i2c_rate = i2c->i2c_rate; - int div, divl, divh; - - if (scl_rate == i2c->scl_rate) - return; - i2c->scl_rate = scl_rate; - div = rockchip_ceil(i2c_rate, (scl_rate * 8)) - 2; - if (unlikely(div < 0)) { - dev_warn(i2c->dev, "Divisor(%d) is negative, set divl = divh = 0\n", div); - divh = divl = 0; - } else { - rockchip_get_div(div, &divh, &divl); - } - i2c_writel(I2C_CLKDIV_VAL(divl, divh), i2c->regs + I2C_CLKDIV); - i2c_dbg(i2c->dev, "set clk(I2C_CLKDIV: 0x%08x)\n", i2c_readl(i2c->regs + I2C_CLKDIV)); -} - -static void rockchip_i2c_init_hw(struct rockchip_i2c *i2c, unsigned long scl_rate) -{ - i2c->scl_rate = 0; - clk_enable(i2c->clk); - rockchip_i2c_set_clk(i2c, scl_rate); - clk_disable(i2c->clk); -} - -/* returns TRUE if we this is the last byte in the current message */ -static inline int is_msglast(struct rockchip_i2c *i2c) -{ - return i2c->msg_ptr == i2c->msg->len - 1; -} - -/* returns TRUE if we reached the end of the current message */ -static inline int is_msgend(struct rockchip_i2c *i2c) -{ - return i2c->msg_ptr >= i2c->msg->len; -} - -static void rockchip_i2c_stop(struct rockchip_i2c *i2c, int ret) -{ - - i2c->msg_ptr = 0; - i2c->msg = NULL; - if (ret == -EAGAIN) { - i2c->state = STATE_IDLE; - i2c->is_busy = 0; - wake_up(&i2c->wait); - return; - } - i2c->error = ret; - i2c_writel(I2C_STOPIEN, i2c->regs + I2C_IEN); - i2c->state = STATE_STOP; - rockchip_i2c_send_stop(i2c); -} - -static inline void rockchip_set_rx_mode(struct rockchip_i2c *i2c, unsigned int lastnak) -{ - unsigned long con = i2c_readl(i2c->regs + I2C_CON); - - con &= (~I2C_CON_MASK); - con |= (I2C_CON_MOD_RX << 1); - if (lastnak) - con |= I2C_CON_LASTACK; - i2c_writel(con, i2c->regs + I2C_CON); -} - -static void rockchip_irq_read_prepare(struct rockchip_i2c *i2c) -{ - unsigned int cnt, len = i2c->msg->len - i2c->msg_ptr; - - if (len <= 32 && i2c->msg_ptr != 0) - rockchip_set_rx_mode(i2c, 1); - else if (i2c->msg_ptr != 0) - rockchip_set_rx_mode(i2c, 0); - - if (is_msgend(i2c)) { - rockchip_i2c_stop(i2c, i2c->error); - return; - } - if (len > 32) - cnt = 32; - else - cnt = len; - i2c_writel(cnt, i2c->regs + I2C_MRXCNT); -} - -static void rockchip_irq_read_get_data(struct rockchip_i2c *i2c) -{ - unsigned int i, len = i2c->msg->len - i2c->msg_ptr; - unsigned int p = 0; - - len = (len >= 32) ? 32 : len; - - for (i = 0; i < len; i++) { - if (i % 4 == 0) - p = i2c_readl(i2c->regs + I2C_RXDATA_BASE + (i / 4) * 4); - i2c->msg->buf[i2c->msg_ptr++] = (p >> ((i % 4) * 8)) & 0xff; - } -} - -static void rockchip_irq_write_prepare(struct rockchip_i2c *i2c) -{ - unsigned int data = 0, cnt = 0, i, j; - unsigned char byte; - - if (is_msgend(i2c)) { - rockchip_i2c_stop(i2c, i2c->error); - return; - } - for (i = 0; i < 8; i++) { - data = 0; - for (j = 0; j < 4; j++) { - if (is_msgend(i2c)) - break; - if ((i2c->msg_ptr == 0) && (cnt == 0)) - byte = (i2c->addr_1st & 0x7f) << 1; - else if ((i2c->msg_ptr == 0) && (cnt == 1) && (i2c->msg->flags & I2C_M_TEN)) - byte = i2c->addr_2nd; - else - byte = i2c->msg->buf[i2c->msg_ptr++]; - cnt++; - data |= (byte << (j * 8)); - } - i2c_writel(data, i2c->regs + I2C_TXDATA_BASE + 4 * i); - if (is_msgend(i2c)) - break; - } - i2c_writel(cnt, i2c->regs + I2C_MTXCNT); -} - -static void rockchip_i2c_irq_nextblock(struct rockchip_i2c *i2c, unsigned int ipd) -{ - switch (i2c->state) { - case STATE_START: - if (!(ipd & I2C_STARTIPD)) { - rockchip_i2c_stop(i2c, -ENXIO); - dev_err(i2c->dev, "Addr[0x%04x] no start irq in STATE_START\n", i2c->addr); - rockchip_show_regs(i2c); - i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); - goto out; - } - i2c->complete_what |= 1 << i2c->state; - i2c_writel(I2C_STARTIPD, i2c->regs + I2C_IPD); - rockchip_i2c_clean_start(i2c); - if (i2c->mode == I2C_CON_MOD_TX) { - i2c_writel(I2C_MBTFIEN | I2C_NAKRCVIEN, i2c->regs + I2C_IEN); - i2c->state = STATE_WRITE; - goto prepare_write; - } else { - i2c_writel(I2C_MBRFIEN | I2C_NAKRCVIEN, i2c->regs + I2C_IEN); - i2c->state = STATE_READ; - goto prepare_read; - } - case STATE_WRITE: - if (!(ipd & I2C_MBTFIPD)) { - rockchip_i2c_stop(i2c, -ENXIO); - dev_err(i2c->dev, "Addr[0x%04x] no mbtf irq in STATE_WRITE\n", i2c->addr); - rockchip_show_regs(i2c); - i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); - goto out; - } - i2c->complete_what |= 1 << i2c->state; - i2c_writel(I2C_MBTFIPD, i2c->regs + I2C_IPD); -prepare_write: - rockchip_irq_write_prepare(i2c); - break; - case STATE_READ: - if (!(ipd & I2C_MBRFIPD)) { - rockchip_i2c_stop(i2c, -ENXIO); - dev_err(i2c->dev, "Addr[0x%04x] no mbrf irq in STATE_READ, ipd = 0x%x\n", i2c->addr, ipd); - rockchip_show_regs(i2c); - i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); - goto out; - } - i2c->complete_what |= 1 << i2c->state; - i2c_writel(I2C_MBRFIPD, i2c->regs + I2C_IPD); - rockchip_irq_read_get_data(i2c); -prepare_read: - rockchip_irq_read_prepare(i2c); - break; - case STATE_STOP: - if (!(ipd & I2C_STOPIPD)) { - rockchip_i2c_stop(i2c, -ENXIO); - dev_err(i2c->dev, "Addr[0x%04x] no stop irq in STATE_STOP\n", i2c->addr); - rockchip_show_regs(i2c); - i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); - goto out; - } - rockchip_i2c_clean_stop(i2c); - i2c_writel(I2C_STOPIPD, i2c->regs + I2C_IPD); - i2c->is_busy = 0; - i2c->complete_what |= 1 << i2c->state; - i2c->state = STATE_IDLE; - wake_up(&i2c->wait); - break; - default: - break; - } -out: - return; -} - -static irqreturn_t rockchip_i2c_irq(int irq, void *dev_id) -{ - struct rockchip_i2c *i2c = dev_id; - unsigned int ipd; - - spin_lock(&i2c->lock); - ipd = i2c_readl(i2c->regs + I2C_IPD); - if (i2c->state == STATE_IDLE) { - dev_info(i2c->dev, "Addr[0x%04x] irq in STATE_IDLE, ipd = 0x%x\n", i2c->addr, ipd); - i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); - goto out; - } - - if (ipd & I2C_NAKRCVIPD) { - i2c_writel(I2C_NAKRCVIPD, i2c->regs + I2C_IPD); - i2c->error = -EAGAIN; - goto out; - } - rockchip_i2c_irq_nextblock(i2c, ipd); -out: - spin_unlock(&i2c->lock); - return IRQ_HANDLED; -} - -static int rockchip_i2c_set_master(struct rockchip_i2c *i2c, struct i2c_msg *msgs, int num) -{ - unsigned int reg_valid_bits = 0; - unsigned int reg_addr = 0; - unsigned int addr = (i2c->addr_1st << 1) | 1; - - if (num == 1) { - i2c->count = msgs[0].len; - if (!(msgs[0].flags & I2C_M_RD)) { - i2c->msg = &msgs[0]; - i2c->mode = I2C_CON_MOD_TX; - } else { - i2c->msg = &msgs[0]; - i2c_writel(addr | I2C_MRXADDR_LOW, - i2c->regs + I2C_MRXADDR); - i2c_writel(0, i2c->regs + I2C_MRXRADDR); - i2c->mode = I2C_CON_MOD_TRX; - //i2c->mode = I2C_CON_MOD_RX; - } - } else if (num == 2) { - i2c->count = msgs[1].len; - - if (msgs[0].flags & I2C_M_TEN) { - switch (msgs[0].len) { - case 1: - reg_addr = i2c->addr_2nd | (msgs[0].buf[0] << 8); - reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID; - break; - case 2: - reg_addr = i2c->addr_2nd | (msgs[0].buf[0] << 8) | (msgs[0].buf[1] << 16); - reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID | I2C_MRXADDR_HIGH; - break; - default: - return -EIO; - } - } else { - switch (msgs[0].len) { - case 1: - reg_addr = msgs[0].buf[0]; - reg_valid_bits |= I2C_MRXADDR_LOW; - break; - case 2: - reg_addr = msgs[0].buf[0] | (msgs[0].buf[1] << 8); - reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID; - break; - case 3: - reg_addr = msgs[0].buf[0] | (msgs[0].buf[1] << 8) | (msgs[0].buf[2] << 16); - reg_valid_bits |= I2C_MRXADDR_LOW | I2C_MRXADDR_MID | I2C_MRXADDR_HIGH; - break; - default: - return -EIO; - } - } - if ((msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) { - i2c->msg = &msgs[1]; - i2c_writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR); - i2c_writel(reg_addr | reg_valid_bits, i2c->regs + I2C_MRXRADDR); - i2c->mode = I2C_CON_MOD_RRX; - } else if (!(msgs[0].flags & I2C_M_RD) && (msgs[1].flags & I2C_M_RD)) { - i2c->msg = &msgs[1]; - i2c_writel(addr | I2C_MRXADDR_LOW, i2c->regs + I2C_MRXADDR); - i2c_writel(reg_addr | reg_valid_bits, i2c->regs + I2C_MRXRADDR); - i2c->mode = I2C_CON_MOD_TRX; - } else - return -EIO; - } else { - dev_err(i2c->dev, "This case(num > 2) has not been support now\n"); - return -EIO; - } - - return 0; -} - -/* rockchip_i2c_doxfer - * - * this starts an i2c transfer -*/ -static int rockchip_i2c_doxfer(struct rockchip_i2c *i2c, - struct i2c_msg *msgs, int num) -{ - unsigned long timeout, flags; - int error = 0; - /* 32 -- max transfer bytes - * 2 -- addr bytes * 2 - * 3 -- max reg addr bytes - * 9 -- cycles per bytes - * max cycles: (32 + 2 + 3) * 9 --> 400 cycles - */ - int msleep_time = 400 * 1000 / i2c->scl_rate; // ms - int can_sleep = !(in_atomic() || irqs_disabled()); - - spin_lock_irqsave(&i2c->lock, flags); - i2c->addr = msgs[0].addr; - if (msgs[0].flags & I2C_M_TEN) { - i2c->addr_1st = ((i2c->addr & 0x0300) >> 8) | 0x78; - i2c->addr_2nd = i2c->addr & 0x00ff; - } else { - i2c->addr_1st = i2c->addr & 0x007f; - i2c->addr_2nd = 0; - } - i2c_dbg(i2c->dev, "addr: 0x%04x, addr_1st: 0x%02x, addr_2nd: 0x%02x\n", - i2c->addr, i2c->addr_1st, i2c->addr_2nd); - - if (rockchip_i2c_set_master(i2c, msgs, num) < 0) { - spin_unlock_irqrestore(&i2c->lock, flags); - dev_err(i2c->dev, "addr[0x%04x] set master error\n", msgs[0].addr); - return -EIO; - } - i2c->msg_ptr = 0; - i2c->error = 0; - i2c->is_busy = 1; - i2c->state = STATE_START; - i2c->complete_what = 0; - i2c_writel(I2C_STARTIEN, i2c->regs + I2C_IEN); - - rockchip_i2c_enable(i2c, (i2c->count > 32) ? 0 : 1); //if count > 32, byte(32) send ack - - if (can_sleep) { - long ret = msecs_to_jiffies(I2C_WAIT_TIMEOUT); - if (i2c->is_busy) { - DEFINE_WAIT(wait); - for (;;) { - prepare_to_wait(&i2c->wait, &wait, TASK_UNINTERRUPTIBLE); - if (i2c->is_busy == 0) - break; - spin_unlock_irqrestore(&i2c->lock, flags); - ret = schedule_timeout(ret); - spin_lock_irqsave(&i2c->lock, flags); - if (!ret) - break; - } - if (!ret && (i2c->is_busy == 0)) - ret = 1; - finish_wait(&i2c->wait, &wait); - } - timeout = ret; - } else { - int cpu = raw_smp_processor_id(); - int tmo = I2C_WAIT_TIMEOUT * USEC_PER_MSEC; - while (tmo-- && i2c->is_busy != 0) { - spin_unlock_irqrestore(&i2c->lock, flags); - udelay(1); - if (cpu == 0 && irqs_disabled() - && (i2c_readl(i2c->regs + I2C_IPD) - & i2c_readl(i2c->regs + I2C_IEN))) { - rockchip_i2c_irq(i2c->irq, i2c); - } - spin_lock_irqsave(&i2c->lock, flags); - } - timeout = (tmo <= 0) ? 0 : 1; - } - - error = i2c->error; - - if (timeout == 0) { - unsigned int ipd = i2c_readl(i2c->regs + I2C_IPD); - if (error < 0) - i2c_dbg(i2c->dev, "error = %d\n", error); - else if (i2c->complete_what != COMPLETE_READ && i2c->complete_what != COMPLETE_WRITE) { - if (ipd & I2C_HOLD_SCL) - dev_err(i2c->dev, "SCL was hold by slave\n"); - dev_err(i2c->dev, "Addr[0x%04x] wait event timeout, state: %d, is_busy: %d, error: %d, complete_what: 0x%x, ipd: 0x%x\n", - msgs[0].addr, i2c->state, i2c->is_busy, error, i2c->complete_what, ipd); - //rockchip_show_regs(i2c); - error = -ETIMEDOUT; - mdelay(msleep_time); - rockchip_i2c_send_stop(i2c); - mdelay(1); - } else - i2c_dbg(i2c->dev, "Addr[0x%02x] wait event timeout, but transfer complete\n", i2c->addr); - } - - i2c->state = STATE_IDLE; - - i2c_writel(I2C_IPD_ALL_CLEAN, i2c->regs + I2C_IPD); - rockchip_i2c_disable_irq(i2c); - rockchip_i2c_disable(i2c); - spin_unlock_irqrestore(&i2c->lock, flags); - - if (error == -EAGAIN) - i2c_dbg(i2c->dev, "No ack(complete_what: 0x%x), Maybe slave(addr: 0x%04x) not exist or abnormal power-on\n", - i2c->complete_what, i2c->addr); - - return error; -} - -/* rockchip_i2c_xfer - * - * first port of call from the i2c bus code when an message needs - * transferring across the i2c bus. -*/ - -static int rockchip_i2c_xfer(struct i2c_adapter *adap, - struct i2c_msg *msgs, int num) -{ - int ret; - struct rockchip_i2c *i2c = i2c_get_adapdata(adap); - unsigned long scl_rate = i2c->scl_rate; - int can_sleep = !(in_atomic() || irqs_disabled()); - - if (can_sleep) { - mutex_lock(&i2c->suspend_lock); - if (i2c->suspended) { - dev_err(i2c->dev, "i2c is suspended\n"); - mutex_unlock(&i2c->suspend_lock); - return -EIO; - } - } - - clk_enable(i2c->clk); - if (i2c->check_idle) { - int state, retry = 10; - while (retry) { - state = rockchip_i2c_check_idle(i2c); - if (state == I2C_IDLE) - break; - if (can_sleep) - msleep(10); - else - mdelay(10); - retry--; - } - if (retry == 0) { - dev_err(i2c->dev, "i2c is not in idle(state = %d)\n", state); - ret = -EIO; - goto out; - } - } - -#ifdef CONFIG_I2C_ROCKCHIP_COMPAT - if (msgs[0].scl_rate <= 400000 && msgs[0].scl_rate >= 10000) - scl_rate = msgs[0].scl_rate; - else if (msgs[0].scl_rate > 400000) { - dev_warn_ratelimited(i2c->dev, "Warning: addr[0x%04x] msg[0].scl_rate( = %dKhz) is too high!", - msgs[0].addr, msgs[0].scl_rate/1000); - scl_rate = 400000; - } else { - dev_warn_ratelimited(i2c->dev, "Warning: addr[0x%04x] msg[0].scl_rate( = %dKhz) is too low!", - msgs[0].addr, msgs[0].scl_rate/1000); - scl_rate = 100000; - } - - rockchip_i2c_set_clk(i2c, scl_rate); -#endif - - i2c_dbg(i2c->dev, "i2c transfer start: addr: 0x%04x, scl_reate: %ldKhz, len: %d\n", msgs[0].addr, scl_rate/1000, num); - ret = rockchip_i2c_doxfer(i2c, msgs, num); - i2c_dbg(i2c->dev, "i2c transfer stop: addr: 0x%04x, state: %d, ret: %d\n", msgs[0].addr, ret, i2c->state); - -out: - clk_disable(i2c->clk); - if (can_sleep) - mutex_unlock(&i2c->suspend_lock); - - return (ret < 0) ? ret : num; -} - -/* declare our i2c functionality */ -static u32 rockchip_i2c_func(struct i2c_adapter *adap) -{ - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_PROTOCOL_MANGLING; -} - -/* i2c bus registration info */ - -static const struct i2c_algorithm rockchip_i2c_algorithm = { - .master_xfer = rockchip_i2c_xfer, - .functionality = rockchip_i2c_func, -}; - -/* rockchip_i2c_probe - * - * called by the bus driver when a suitable device is found -*/ - -static int rockchip_i2c_probe(struct platform_device *pdev) -{ - struct rockchip_i2c *i2c = NULL; - struct resource *res; - struct device_node *np = pdev->dev.of_node; - int ret; - - if (!np) { - dev_err(&pdev->dev, "Missing device tree node.\n"); - return -EINVAL; - } - - i2c = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_i2c), GFP_KERNEL); - if (!i2c) { - dev_err(&pdev->dev, "no memory for state\n"); - return -ENOMEM; - } - - strlcpy(i2c->adap.name, "rockchip_i2c", sizeof(i2c->adap.name)); - i2c->dev = &pdev->dev; - i2c->adap.owner = THIS_MODULE; - i2c->adap.class = I2C_CLASS_HWMON | I2C_CLASS_SPD; - i2c->adap.retries = 2; - i2c->adap.timeout = msecs_to_jiffies(100); - i2c->adap.algo = &rockchip_i2c_algorithm; - i2c_set_adapdata(&i2c->adap, i2c); - i2c->adap.dev.parent = &pdev->dev; - i2c->adap.dev.of_node = np; - - spin_lock_init(&i2c->lock); - init_waitqueue_head(&i2c->wait); - - /* map the registers */ - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - i2c->regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(i2c->regs)) - return PTR_ERR(i2c->regs); - - i2c_dbg(&pdev->dev, "registers %p (%p, %p)\n", - i2c->regs, i2c->ioarea, res); - - i2c->check_idle = true; - of_property_read_u32(np, "rockchip,check-idle", &i2c->check_idle); - if (i2c->check_idle) { - i2c->sda_gpio = of_get_gpio(np, 0); - if (!gpio_is_valid(i2c->sda_gpio)) { - dev_err(&pdev->dev, "sda gpio is invalid\n"); - return -EINVAL; - } - ret = devm_gpio_request(&pdev->dev, i2c->sda_gpio, dev_name(&i2c->adap.dev)); - if (ret) { - dev_err(&pdev->dev, "failed to request sda gpio\n"); - return ret; - } - i2c->scl_gpio = of_get_gpio(np, 1); - if (!gpio_is_valid(i2c->scl_gpio)) { - dev_err(&pdev->dev, "scl gpio is invalid\n"); - return -EINVAL; - } - ret = devm_gpio_request(&pdev->dev, i2c->scl_gpio, dev_name(&i2c->adap.dev)); - if (ret) { - dev_err(&pdev->dev, "failed to request scl gpio\n"); - return ret; - } - i2c->gpio_state = pinctrl_lookup_state(i2c->dev->pins->p, "gpio"); - if (IS_ERR(i2c->gpio_state)) { - dev_err(&pdev->dev, "no gpio pinctrl state\n"); - return PTR_ERR(i2c->gpio_state); - } - pinctrl_select_state(i2c->dev->pins->p, i2c->gpio_state); - gpio_direction_input(i2c->sda_gpio); - gpio_direction_input(i2c->scl_gpio); - pinctrl_select_state(i2c->dev->pins->p, i2c->dev->pins->default_state); - } - - /* setup info block for the i2c core */ - ret = i2c_add_adapter(&i2c->adap); - if (ret < 0) { - dev_err(&pdev->dev, "failed to add adapter\n"); - return ret; - } - - platform_set_drvdata(pdev, i2c); - - /* find the clock and enable it */ - i2c->clk = devm_clk_get(&pdev->dev, NULL); - if (IS_ERR(i2c->clk)) { - dev_err(&pdev->dev, "cannot get clock\n"); - return PTR_ERR(i2c->clk); - } - - i2c_dbg(&pdev->dev, "clock source %p\n", i2c->clk); - - /* find the IRQ for this unit (note, this relies on the init call to - * ensure no current IRQs pending - */ - i2c->irq = ret = platform_get_irq(pdev, 0); - if (ret < 0) { - dev_err(&pdev->dev, "cannot find IRQ\n"); - return ret; - } - - ret = devm_request_irq(&pdev->dev, i2c->irq, rockchip_i2c_irq, 0, - dev_name(&i2c->adap.dev), i2c); - if (ret) { - dev_err(&pdev->dev, "cannot claim IRQ %d\n", i2c->irq); - return ret; - } - - ret = clk_prepare(i2c->clk); - if (ret < 0) { - dev_err(&pdev->dev, "Could not prepare clock\n"); - return ret; - } - - i2c->i2c_rate = clk_get_rate(i2c->clk); - - rockchip_i2c_init_hw(i2c, 100 * 1000); - dev_info(&pdev->dev, "%s: Rockchip I2C adapter\n", dev_name(&i2c->adap.dev)); - - of_i2c_register_devices(&i2c->adap); - mutex_init(&i2c->suspend_lock); - - return 0; -} - -/* rockchip_i2c_remove - * - * called when device is removed from the bus -*/ - -static int rockchip_i2c_remove(struct platform_device *pdev) -{ - struct rockchip_i2c *i2c = platform_get_drvdata(pdev); - - mutex_lock(&i2c->suspend_lock); - i2c->suspended = 1; - i2c_del_adapter(&i2c->adap); - clk_unprepare(i2c->clk); - mutex_unlock(&i2c->suspend_lock); - - return 0; -} - -/* rockchip_i2c_shutdown - * - * called when device is shutdown from the bus -*/ -static void rockchip_i2c_shutdown(struct platform_device *pdev) -{ - struct rockchip_i2c *i2c = platform_get_drvdata(pdev); - - mutex_lock(&i2c->suspend_lock); - i2c->suspended = 1; - mutex_unlock(&i2c->suspend_lock); -} - -#ifdef CONFIG_PM -static int rockchip_i2c_suspend_noirq(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rockchip_i2c *i2c = platform_get_drvdata(pdev); - - mutex_lock(&i2c->suspend_lock); - i2c->suspended = 1; - pinctrl_pm_select_sleep_state(dev); - mutex_unlock(&i2c->suspend_lock); - - return 0; -} - -static int rockchip_i2c_resume_noirq(struct device *dev) -{ - struct platform_device *pdev = to_platform_device(dev); - struct rockchip_i2c *i2c = platform_get_drvdata(pdev); - - mutex_lock(&i2c->suspend_lock); - pinctrl_pm_select_default_state(dev); - rockchip_i2c_init_hw(i2c, i2c->scl_rate); - i2c->suspended = 0; - mutex_unlock(&i2c->suspend_lock); - - return 0; -} - -static const struct dev_pm_ops rockchip_i2c_dev_pm_ops = { - .suspend_noirq = rockchip_i2c_suspend_noirq, - .resume_noirq = rockchip_i2c_resume_noirq, -}; - -#define ROCKCHIP_I2C_PM_OPS (&rockchip_i2c_dev_pm_ops) -#else -#define ROCKCHIP_I2C_PM_OPS NULL -#endif - -static const struct of_device_id rockchip_i2c_of_match[] = { - { .compatible = "rockchip,rk30-i2c", .data = NULL, }, - {}, -}; -MODULE_DEVICE_TABLE(of, rockchip_i2c_of_match); - -static struct platform_driver rockchip_i2c_driver = { - .probe = rockchip_i2c_probe, - .remove = rockchip_i2c_remove, - .shutdown = rockchip_i2c_shutdown, - .driver = { - .owner = THIS_MODULE, - .name = "rockchip_i2c", - .pm = ROCKCHIP_I2C_PM_OPS, - .of_match_table = of_match_ptr(rockchip_i2c_of_match), - }, -}; - -static int __init rockchip_i2c_init_driver(void) -{ - return platform_driver_register(&rockchip_i2c_driver); -} - -subsys_initcall(rockchip_i2c_init_driver); - -static void __exit rockchip_i2c_exit_driver(void) -{ - platform_driver_unregister(&rockchip_i2c_driver); -} - -module_exit(rockchip_i2c_exit_driver); - -static int detect_read(struct i2c_client *client, char *buf, int len) -{ - struct i2c_msg msg; - - msg.addr = client->addr; - msg.flags = client->flags | I2C_M_RD; - msg.buf = buf; - msg.len = len; -#ifdef CONFIG_I2C_ROCKCHIP_COMPAT - msg.scl_rate = 100 * 1000; -#endif - - return i2c_transfer(client->adapter, &msg, 1); -} - -static void detect_set_client(struct i2c_client *client, __u16 addr, int nr) -{ - client->flags = 0; - client->addr = addr; - client->adapter = i2c_get_adapter(nr); -} - -static void slave_detect(int nr) -{ - int ret = 0; - unsigned short addr; - char val[8]; - char buf[6 * 0x80 + 20]; - struct i2c_client client; - - memset(buf, 0, 6 * 0x80 + 20); - - sprintf(buf, "I2c%d slave list: ", nr); - do { - for (addr = 0x01; addr < 0x80; addr++) { - detect_set_client(&client, addr, nr); - ret = detect_read(&client, val, 1); - if (ret > 0) - sprintf(buf, "%s 0x%02x", buf, addr); - } - printk("%s\n", buf); - } - while (0); -} - -static ssize_t i2c_detect_write(struct file *file, - const char __user *buf, size_t count, loff_t *offset) -{ - char nr_buf[8]; - int nr = 0, ret; - - if (count > 4) - return -EFAULT; - ret = copy_from_user(nr_buf, buf, count); - if (ret < 0) - return -EFAULT; - - sscanf(nr_buf, "%d", &nr); - if (nr >= 5 || nr < 0) - return -EFAULT; - - slave_detect(nr); - - return count; -} - -static const struct file_operations i2c_detect_fops = { - .write = i2c_detect_write, -}; - -static struct miscdevice i2c_detect_device = { - .minor = MISC_DYNAMIC_MINOR, - .name = "i2c_detect", - .fops = &i2c_detect_fops, -}; - -static int __init i2c_detect_init(void) -{ - return misc_register(&i2c_detect_device); -} - -static void __exit i2c_detect_exit(void) -{ - misc_deregister(&i2c_detect_device); -} - -module_init(i2c_detect_init); -module_exit(i2c_detect_exit); - -MODULE_DESCRIPTION("Driver for Rockchip I2C Bus"); -MODULE_AUTHOR("kfx, kfx@rock-chips.com"); -MODULE_LICENSE("GPL");