summaryrefslogtreecommitdiff
path: root/drivers/i2c/busses/wmt-i2c-slave-bus-1.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/busses/wmt-i2c-slave-bus-1.c')
-rwxr-xr-xdrivers/i2c/busses/wmt-i2c-slave-bus-1.c661
1 files changed, 661 insertions, 0 deletions
diff --git a/drivers/i2c/busses/wmt-i2c-slave-bus-1.c b/drivers/i2c/busses/wmt-i2c-slave-bus-1.c
new file mode 100755
index 00000000..90b49ea8
--- /dev/null
+++ b/drivers/i2c/busses/wmt-i2c-slave-bus-1.c
@@ -0,0 +1,661 @@
+/*++
+ drivers/i2c/busses/wmt-i2c-slave-bus-1.c
+
+ Copyright (c) 2008 WonderMedia Technologies, Inc.
+
+ This program is free software: you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software Foundation,
+ either version 2 of the License, or (at your option) any later version.
+
+ 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.
+ You should have received a copy of the GNU General Public License along with
+ this program. If not, see <http://www.gnu.org/licenses/>.
+
+ WonderMedia Technologies, Inc.
+ 10F, 529, Chung-Cheng Road, Hsin-Tien, Taipei 231, R.O.C.
+
+ History:
+ 2010/03/15 First Version
+--*/
+
+#include <linux/config.h>
+#define WMT_I2C1_SLAVE_C
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/errno.h>
+#include <asm/uaccess.h>
+#include <linux/kdev_t.h>
+#include <linux/cdev.h>
+#include <asm/semaphore.h>
+#include <linux/proc_fs.h>
+
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <mach/hardware.h>
+#include "./wmt-i2c-slave-bus.h"
+/*#define DEBUG*/
+#ifdef DEBUG
+#define DPRINTK(fmt, args...) printk(KERN_DEBUG "%s: " fmt, __func__ , ## args)
+#else
+#define DPRINTK(fmt, args...)
+#endif
+
+
+#define DEVICE_NAME "WMT_I2C_SLAVE-1"
+#define PMC_ClOCK_ENABLE_LOWER 0xd8130250
+#define CTRL_GPIO21 0xD8110055
+#define PU_EN_GPIO21 0xD8110495
+#define PU_CTRL_GPIO21 0xD81104D5
+
+#define DISABLE_I2C_SLAVE BIT15
+
+struct i2c_slave_msg {
+ __u16 addr; /* slave address */
+ __u16 flags;
+#define I2C_M_RD 0x01
+ __u16 len; /* data length */
+ __u8 *buf; /* pointer to data */
+};
+
+struct slave_i2c_dev_s {
+ /* module parameters */
+ char *buf;
+
+ /* char dev struct */
+ struct cdev cdev;
+ struct class *class_slave_i2c;
+};
+
+
+struct wmt_slave_i2c_s {
+ struct i2c_regs_s *regs;
+ int irq_no ;
+ enum i2c_mode_e i2c_mode ;
+ int isr_nack ;
+ int isr_byte_end ;
+ int isr_timeout ;
+ int isr_int_pending ;
+ struct compat_semaphore tx_sem;
+ struct compat_semaphore rx_sem;
+};
+
+static struct i2c_regs_s regs_backup;
+extern int wmt_getsyspara(char *varname, unsigned char *varval, int *varlen);
+static unsigned int is_master = 1;/*master:1, slave:0*/
+
+static DEFINE_SPINLOCK(slave_i2c_lock);
+
+static int slave_i2c_dev_major = SLAVE_I2C_MAJOR;
+static int slave_i2c_dev_minor = 1;
+static int slave_i2c_dev_nr = 1;
+static struct slave_i2c_dev_s slave_i2c_dev;
+
+static struct wmt_slave_i2c_s slave_i2c_port;
+
+static unsigned char slave_i2c_addr = 0x31;
+
+#ifdef CONFIG_PROC_FS
+static struct proc_dir_entry *slave_i2c_proc;
+
+static int slave_i2c_reg_read(char *buf, char **start, off_t offset, int len)
+{
+ char *p = buf;
+ p += sprintf(p, "reg : value\n");
+ p += sprintf(p, "cr : 0x%.4x\n", slave_i2c_port.regs->cr_reg);
+ p += sprintf(p, "tcr : 0x%.4x\n", slave_i2c_port.regs->tcr_reg);
+ p += sprintf(p, "csr : 0x%.4x\n", slave_i2c_port.regs->csr_reg);
+ p += sprintf(p, "isr : 0x%.4x\n", slave_i2c_port.regs->isr_reg);
+ p += sprintf(p, "imr : 0x%.4x\n", slave_i2c_port.regs->imr_reg);
+ p += sprintf(p, "cdr : 0x%.4x\n", slave_i2c_port.regs->cdr_reg);
+ p += sprintf(p, "tr : 0x%.4x\n", slave_i2c_port.regs->tr_reg);
+ p += sprintf(p, "scr : 0x%.4x\n", slave_i2c_port.regs->scr_reg);
+ p += sprintf(p, "cssr : 0x%.4x\n", slave_i2c_port.regs->cssr_reg);
+ p += sprintf(p, "simr : 0x%.4x\n", slave_i2c_port.regs->simr_reg);
+ p += sprintf(p, "sisr : 0x%.4x\n", slave_i2c_port.regs->sisr_reg);
+ p += sprintf(p, "csdr : 0x%.4x\n", slave_i2c_port.regs->csdr_reg);
+ p += sprintf(p, "str : 0x%.4x\n", slave_i2c_port.regs->str_reg);
+ return p - buf;
+}
+
+static int slave_i2c_addr_read(char *buf, char **start, off_t offset, int len)
+{
+ char *p = buf;
+ p += sprintf(p, "i2c-slave address : 0x%.2x\n", slave_i2c_addr);
+ return p - buf;
+}
+
+#endif
+
+static irqreturn_t slave_i2c_isr(
+ int irq, /*!<; // IRQ number */
+ void *dev, /*!<; // Private paramater(i.e. pointer of spi port) */
+ struct pt_regs *regs /*!<; // interrupt register */
+)
+{
+ unsigned short isr_status = slave_i2c_port.regs->sisr_reg;
+ unsigned short ssr_status = slave_i2c_port.regs->cssr_reg;
+ DPRINTK("slave_i2c isr sisr = %x\n", isr_status);
+ DPRINTK("slave_i2c isr cssr = %x\n", ssr_status);
+ if (isr_status & I2C_SISR_DAT_REQ) {
+ slave_i2c_port.regs->sisr_reg |= I2C_SISR_DAT_REQ_WRITE_CLEAR;
+ slave_i2c_port.isr_nack = ssr_status & I2C_SRCV_NACK_MASK;
+ compat_up(&slave_i2c_port.tx_sem);
+ } else if (isr_status & I2C_SISR_BYTE_END) {
+ slave_i2c_port.regs->sisr_reg |= I2C_SISR_BYTE_END_WRITE_CLEAR;
+ slave_i2c_port.isr_byte_end = 1;
+ slave_i2c_port.isr_nack = ssr_status & I2C_SRCV_NACK_MASK;
+ compat_up(&slave_i2c_port.rx_sem);
+ } else if (isr_status & I2C_SISR_SCL_TIME_OUT) {
+ slave_i2c_port.regs->sisr_reg |= I2C_SISR_SCL_TIME_OUT_WRITE_CLEAR;
+ slave_i2c_port.isr_timeout = 1 ;
+ }
+ return IRQ_HANDLED;
+}
+
+static int wmt_slave_i2c_read_data(unsigned short addr , unsigned char *buf, int size, int flags)
+{
+ int ret = 0;
+ int xfer_len = 0;
+ int sleep_count = 1;
+ DPRINTK("ssr = %x, isr = %x\n", slave_i2c_port.regs->cssr_reg, slave_i2c_port.regs->sisr_reg);
+ while (xfer_len < size) {
+ compat_down_interruptible(&slave_i2c_port.rx_sem);
+ buf[xfer_len] = ((slave_i2c_port.regs->csdr_reg & I2C_SLAVE_READ_DATA_MASK) >> I2C_SLAVE_READ_DATA_SHIFT);
+ DPRINTK("data = %x\n", buf[xfer_len]);
+ xfer_len++;
+ }
+ ret = xfer_len;
+ while (slave_i2c_port.regs->cssr_reg & I2C_SLAVE_ACTIVE) {
+ if (compat_sema_count(&slave_i2c_port.rx_sem) > 0) {/*receive data was longer than request*/
+ ret = -1;
+ break;
+ }
+ msleep(sleep_count);
+ if (sleep_count < 16)
+ sleep_count *= 2;
+ }
+ DPRINTK("ssr = %x, isr = %x\n", slave_i2c_port.regs->cssr_reg, slave_i2c_port.regs->sisr_reg);
+
+ return ret;
+}
+
+static int wmt_slave_i2c_write_data(unsigned short addr, unsigned char *buf, int size, int flags)
+{
+ int ret = 0;
+ int xfer_len = 0;
+ int sleep_count = 1;
+ DPRINTK("tx ssr = %x, isr = %x\n", slave_i2c_port.regs->cssr_reg, slave_i2c_port.regs->sisr_reg);
+ while (xfer_len < size) {
+ compat_down_interruptible(&slave_i2c_port.tx_sem);
+ slave_i2c_port.regs->csdr_reg = buf[xfer_len];
+ DPRINTK("data = %x\n", buf[xfer_len]);
+ ++xfer_len;
+ }
+ ret = xfer_len;
+ while (slave_i2c_port.regs->cssr_reg & I2C_SLAVE_ACTIVE) {
+ msleep(sleep_count);
+ if (sleep_count < 16)
+ sleep_count *= 2;
+ }
+ DPRINTK("2.tx ssr = %x, isr = %x\n", slave_i2c_port.regs->cssr_reg, slave_i2c_port.regs->sisr_reg);
+ return ret;
+}
+
+static int slave_i2c_do_xfer(unsigned short addr, unsigned char *buf, int size, int flags)
+{
+ int ret;
+ if (flags & I2C_M_RD)
+ ret = wmt_slave_i2c_read_data(addr , buf, size, flags);
+ else
+ ret = wmt_slave_i2c_write_data(addr , buf, size, flags);
+ return ret;
+}
+
+int wmt_i2cslave_transfer1(struct i2c_slave_msg slave_msg)
+{
+ int flags = slave_msg.flags;
+ unsigned char *buf = slave_msg.buf;
+ unsigned short addr = slave_msg.addr;
+ int size = slave_msg.len;
+ int xfer_len;
+ if (is_master == 1)
+ return 0;
+ spin_lock(&slave_i2c_lock);
+ xfer_len = slave_i2c_do_xfer(addr, buf, size, flags);
+ spin_unlock(&slave_i2c_lock);
+ return xfer_len;
+}
+EXPORT_SYMBOL(wmt_i2cslave_transfer1);
+
+void wmt_i2cslave_setaddr1(struct i2c_slave_msg msg)
+{
+ if (is_master == 1)
+ return;
+ spin_lock(&slave_i2c_lock);
+
+ slave_i2c_addr = msg.addr;
+
+ if (msg.addr & DISABLE_I2C_SLAVE)
+ slave_i2c_port.regs->cr_reg &= ~I2C_CR_ENABLE;
+ else {
+ slave_i2c_port.regs->cr_reg = 0;
+ slave_i2c_port.regs->scr_reg = 0;
+ slave_i2c_port.regs->cr_reg = (I2C_SLAV_MODE_SEL|I2C_CR_ENABLE);
+ slave_i2c_port.regs->sisr_reg = I2C_SISR_ALL_WRITE_CLEAR;
+
+ if (slave_i2c_port.i2c_mode == I2C_STANDARD_MODE)
+ slave_i2c_port.regs->scr_reg = slave_i2c_addr;
+ else if (slave_i2c_port.i2c_mode == I2C_FAST_MODE)
+ slave_i2c_port.regs->scr_reg = slave_i2c_addr;
+ else
+ slave_i2c_port.regs->scr_reg = (slave_i2c_addr|I2C_SLAVE_HS_MODE);
+
+ slave_i2c_port.regs->simr_reg = I2C_SIMR_ALL_ENABLE;
+ }
+ spin_unlock(&slave_i2c_lock);
+}
+EXPORT_SYMBOL(wmt_i2cslave_setaddr1);
+
+static ssize_t slave_i2c_read(
+ struct file *filp,
+ char __user *buf,
+ size_t count,
+ loff_t *f_pos
+)
+{
+ int ret = 0;
+ struct i2c_slave_msg slave_msg;
+ if (is_master == 1)
+ return ret;
+ slave_msg.buf = (char *)kmalloc(count * sizeof(unsigned char), GFP_KERNEL);
+ slave_msg.flags = 0;
+ slave_msg.flags |= I2C_M_RD;
+ slave_msg.len = count;
+ slave_msg.addr = slave_i2c_addr;
+ ret = wmt_i2cslave_transfer1(slave_msg);
+ if (copy_to_user(buf, slave_msg.buf, count)) {
+ kfree(slave_msg.buf);
+ return -EFAULT;
+ }
+ return ret;
+}
+
+static ssize_t slave_i2c_write(
+ struct file *filp,
+ const char __user *buf,
+ size_t count,
+ loff_t *f_pos
+)
+{
+ int ret = 0;
+ struct i2c_slave_msg slave_msg;
+ if (is_master == 1)
+ return ret;
+ slave_msg.buf = (char *)kmalloc(count * sizeof(unsigned char), GFP_KERNEL);
+ slave_msg.flags = 0;
+ slave_msg.flags &= ~I2C_M_RD;
+ slave_msg.len = count;
+ slave_msg.addr = slave_i2c_addr;
+ if (copy_from_user(slave_msg.buf, buf, count)) {
+ kfree(slave_msg.buf);
+ return -EFAULT;
+ }
+ ret = wmt_i2cslave_transfer1(slave_msg);
+ return ret; /* return Write out data size*/
+}
+
+static int slave_i2c_open(
+ struct inode *inode,
+ struct file *filp
+)
+{
+ struct slave_i2c_dev_s *dev;
+ char name[40];
+ int minor_no;
+
+ dev = container_of(inode->i_cdev, struct slave_i2c_dev_s, cdev);
+ filp->private_data = dev;
+ minor_no = iminor(inode); /* get */
+
+ /* Create user name*/
+ memset(name, 0x0, 8);
+ sprintf(name, "slave-i2c%d", minor_no);
+ return 0;
+}
+
+static int slave_i2c_release(
+ struct inode *inode,
+ struct file *filp
+)
+{
+ struct slave_i2c_dev_s *dev;
+ int minor_no;
+
+ dev = container_of(inode->i_cdev, struct slave_i2c_dev_s, cdev);
+ minor_no = iminor(inode);
+
+ return 0;
+}
+
+static int slave_i2c_ioctl(
+ struct inode *inode,
+ struct file *filp,
+ unsigned int cmd,
+ unsigned long arg
+)
+{
+ int ret = 0;
+ struct i2c_slave_msg slave_msg[1];
+ unsigned char *data_ptr;
+ unsigned char __user *usr_ptr;
+ switch (cmd) {
+ case IOCTL_DO_TRANSFER:
+ if (copy_from_user(slave_msg, (struct i2c_slave_msg *)arg,
+ sizeof(struct i2c_slave_msg)))
+ return -EFAULT;
+
+ data_ptr = (unsigned char *)kmalloc(slave_msg->len*sizeof(unsigned char), GFP_KERNEL);
+ usr_ptr = (unsigned char __user *)slave_msg->buf;
+
+ if (copy_from_user(data_ptr, (unsigned char *)slave_msg->buf,
+ slave_msg->len*sizeof(unsigned char))) {
+ kfree(data_ptr);
+ return -EFAULT;
+ }
+ slave_msg->buf = data_ptr;
+
+ ret = wmt_i2cslave_transfer1((struct i2c_slave_msg)*slave_msg);
+
+ if (slave_msg->flags & I2C_M_RD) {
+ if (copy_to_user(
+ usr_ptr,
+ data_ptr,
+ slave_msg->len))
+ ret = -EFAULT;
+ }
+
+ kfree(data_ptr);
+ break;
+ case IOCTL_SET_ADDR:
+ if (copy_from_user(slave_msg, (struct i2c_slave_msg *)arg,
+ sizeof(struct i2c_slave_msg)))
+ return -EFAULT;
+ wmt_i2cslave_setaddr1((struct i2c_slave_msg) *slave_msg);
+ break;
+ case IOCTL_QUERY_DATA:
+ break;
+ case IOCTL_SET_SPEED_MODE:
+ break;
+ default:
+ break;
+ }
+ return ret;
+}
+
+/*!*************************************************************************
+ driver file operations struct define
+****************************************************************************/
+static struct file_operations i2c_slave_fops = {
+ .owner = THIS_MODULE,
+ .open = slave_i2c_open,
+ .read = slave_i2c_read,
+ .write = slave_i2c_write,
+ .ioctl = slave_i2c_ioctl,
+ .release = slave_i2c_release,
+};
+
+static int slave_i2c_probe(
+ struct device *dev
+)
+{
+ int ret = 0;
+ dev_t dev_no;
+ struct cdev *cdev;
+ char name[40];
+ char buf[80];
+ unsigned int port_num;
+ int idx = 0;
+ char varname1[] = "wmt.bus.i2c.slave_port";
+ int ret_val = 0;
+ int varlen = 80;
+ memset(name, 0, 40);
+
+ dev_no = MKDEV(slave_i2c_dev_major, slave_i2c_dev_minor);
+
+ sprintf(name, "wmt_i2cslave%d",slave_i2c_dev_minor);
+ cdev = &slave_i2c_dev.cdev;
+ cdev_init(cdev, &i2c_slave_fops);
+ ret = cdev_add(cdev, dev_no, 8);
+ slave_i2c_dev.class_slave_i2c = class_create(THIS_MODULE, "wmt_i2cslave1");
+ device_create(slave_i2c_dev.class_slave_i2c, NULL ,
+ MKDEV(slave_i2c_dev_major,slave_i2c_dev_minor),
+ NULL, name);
+ if (ret) {
+ printk(KERN_ALERT "*E* register char dev \n");
+ return ret;
+ }
+
+#ifdef CONFIG_PROC_FS
+ struct proc_dir_entry *res;
+
+ slave_i2c_proc = proc_mkdir("driver/wmt_i2cslave1", NULL);
+ /*
+ slave_i2c_proc->owner = THIS_MODULE;
+ */
+ res = create_proc_entry("registers", 0, slave_i2c_proc);
+ if (res) {
+ res->read_proc = slave_i2c_reg_read;
+ }
+
+ res = create_proc_entry("address", 0, slave_i2c_proc);
+ if (res) {
+ res->read_proc = slave_i2c_addr_read;
+ }
+#endif
+ slave_i2c_port.regs = (struct i2c_regs_s *)I2C1_BASE_ADDR;
+ slave_i2c_port.irq_no = IRQ_I2C1;
+ slave_i2c_port.i2c_mode = I2C_STANDARD_MODE;
+ slave_i2c_port.isr_nack = 0;
+ slave_i2c_port.isr_byte_end = 0;
+ slave_i2c_port.isr_timeout = 0;
+ slave_i2c_port.isr_int_pending = 0;
+ compat_sema_init(&slave_i2c_port.tx_sem, 0);
+ compat_sema_init(&slave_i2c_port.rx_sem, 0);
+ ret_val = wmt_getsyspara(varname1, buf, &varlen);
+ is_master = 1;
+ if (ret_val == 0) {
+ ret_val = sscanf(buf, "%x", &port_num);
+ while (ret_val) {
+ if (port_num != 1)
+ is_master = 1;
+ else {
+ is_master = 0;
+ break;
+ }
+ idx += ret_val;
+ ret_val = sscanf(buf + idx, ",%x", &port_num);
+ }
+ } else
+ is_master = 1;
+ /**/
+ /* hardware initial*/
+ /**/
+ if (is_master == 0) {
+ *(volatile unsigned int *)PMC_ClOCK_ENABLE_LOWER |= (BIT0);
+ *(volatile unsigned int *)CTRL_GPIO21 &= ~(BIT2 | BIT3);
+ *(volatile unsigned int *)PU_EN_GPIO21 |= (BIT2 | BIT3);
+ *(volatile unsigned int *)PU_CTRL_GPIO21 |= (BIT2 | BIT3);
+
+ /*set i2c slave register*/
+ slave_i2c_port.regs->cr_reg = 0;
+ slave_i2c_port.regs->scr_reg = 0;
+ slave_i2c_port.regs->cr_reg = (I2C_SLAV_MODE_SEL|I2C_CR_ENABLE);
+ slave_i2c_port.regs->sisr_reg = I2C_SISR_ALL_WRITE_CLEAR;
+
+ if (slave_i2c_port.i2c_mode == I2C_STANDARD_MODE)
+ slave_i2c_port.regs->scr_reg = slave_i2c_addr;
+ else if (slave_i2c_port.i2c_mode == I2C_FAST_MODE)
+ slave_i2c_port.regs->scr_reg = slave_i2c_addr;
+ else
+ slave_i2c_port.regs->scr_reg = (slave_i2c_addr|I2C_SLAVE_HS_MODE);
+
+ slave_i2c_port.regs->simr_reg = I2C_SIMR_ALL_ENABLE;
+
+ slave_i2c_port.regs->cr_reg &= ~I2C_CR_ENABLE;
+
+ if (request_irq(slave_i2c_port.irq_no , &slave_i2c_isr, IRQF_DISABLED, "i2c-slave", 0) < 0) {
+ DPRINTK(KERN_INFO "I2C-SLAVE: Failed to register I2C-SLAVE irq %i\n", slave_i2c_port.irq_no);
+ return -ENODEV;
+ }
+ }
+
+ return ret;
+}
+
+static int slave_i2c_remove(
+ struct device *dev /*!<; // please add parameters description her*/
+)
+{
+ struct cdev *cdev;
+
+ cdev = &slave_i2c_dev.cdev;
+ cdev_del(cdev);
+
+ return 0;
+} /* End of spi_remove() */
+
+static void slave_i2c_backup(void)
+{
+ regs_backup.cr_reg = slave_i2c_port.regs->cr_reg;
+ regs_backup.tcr_reg = slave_i2c_port.regs->tcr_reg;
+ regs_backup.scr_reg = slave_i2c_port.regs->scr_reg;
+ regs_backup.simr_reg = slave_i2c_port.regs->simr_reg;
+ regs_backup.str_reg = slave_i2c_port.regs->str_reg;
+
+}
+
+static void slave_i2c_restore(void)
+{
+ slave_i2c_port.regs->cr_reg = 0;
+ slave_i2c_port.regs->cr_reg = regs_backup.cr_reg;
+ slave_i2c_port.regs->tcr_reg = regs_backup.tcr_reg;
+ slave_i2c_port.regs->scr_reg = regs_backup.scr_reg;
+ slave_i2c_port.regs->simr_reg = regs_backup.simr_reg;
+ slave_i2c_port.regs->str_reg = regs_backup.str_reg;
+}
+
+static int slave_i2c_suspend(
+ struct device *dev, /*!<; // please add parameters description her*/
+ pm_message_t state /*!<; // please add parameters description her*/
+)
+{
+ if (is_master == 1)
+ return 0;
+ slave_i2c_backup();
+ compat_sema_init(&slave_i2c_port.tx_sem, 0);
+ compat_sema_init(&slave_i2c_port.rx_sem, 0);
+ return 0;
+}
+
+
+static int slave_i2c_resume(
+ struct device *dev
+)
+{
+ if (is_master == 1)
+ return 0;
+ *(volatile unsigned int *)PMC_ClOCK_ENABLE_LOWER |= (BIT0);
+ *(volatile unsigned int *)CTRL_GPIO21 &= ~(BIT2 | BIT3);
+ *(volatile unsigned int *)PU_EN_GPIO21 |= (BIT2 | BIT3);
+ *(volatile unsigned int *)PU_CTRL_GPIO21 |= (BIT2 | BIT3);
+ slave_i2c_restore();
+ return 0;
+}
+
+/*!*************************************************************************
+ device driver struct define
+****************************************************************************/
+static struct device_driver slave_i2c_driver = {
+ .name = "wmt_i2c_slave_1", /* This name should equal to platform device name.*/
+ .bus = &platform_bus_type,
+ .probe = slave_i2c_probe,
+ .remove = slave_i2c_remove,
+ .suspend = slave_i2c_suspend,
+ .resume = slave_i2c_resume
+};
+
+static void slave_i2c_platform_release(
+ struct device *device
+)
+{
+}
+
+/*!*************************************************************************
+ platform device struct define
+****************************************************************************/
+
+static struct platform_device slave_i2c_device = {
+ .name = "wmt_i2c_slave_1",
+ .id = 1,
+ .dev = { .release = slave_i2c_platform_release,
+ },
+ .num_resources = 0,
+ .resource = NULL,
+};
+
+static int slave_i2c_init(void)
+{
+ int ret;
+ dev_t dev_no;
+ char dev_name[40];
+ memset(dev_name, 0, 40);
+ sprintf(dev_name, "wmt_i2c_slave%d", slave_i2c_device.id);
+
+ if (slave_i2c_dev_major) {
+ dev_no = MKDEV(slave_i2c_dev_major, slave_i2c_dev_minor);
+ ret = register_chrdev_region(dev_no, slave_i2c_dev_nr, dev_name);
+ } else {
+ ret = alloc_chrdev_region(&dev_no, slave_i2c_dev_minor, slave_i2c_dev_nr, dev_name);
+ slave_i2c_dev_major = MAJOR(dev_no);
+ }
+
+ if (ret < 0) {
+ printk(KERN_ALERT "*E* can't get major %d\n", slave_i2c_dev_major);
+ return ret;
+ }
+
+ platform_device_register(&slave_i2c_device);
+ ret = driver_register(&slave_i2c_driver);
+
+ return ret;
+}
+
+module_init(slave_i2c_init);
+
+static void slave_i2c_exit(void)
+{
+ dev_t dev_no;
+
+ driver_unregister(&slave_i2c_driver);
+ platform_device_unregister(&slave_i2c_device);
+ dev_no = MKDEV(slave_i2c_dev_major, slave_i2c_dev_minor);
+ unregister_chrdev_region(dev_no, slave_i2c_dev_nr);
+
+ return;
+}
+
+module_exit(slave_i2c_exit);
+
+MODULE_AUTHOR("WMT SW Team");
+MODULE_DESCRIPTION("WMT_slave_i2c device driver");
+MODULE_LICENSE("GPL");
+#undef WMT_I2C_SLAVE_C