示例#1
0
static int cmd_i2c_common(struct vmm_chardev *cdev,
			  int argc,
			  char **argv,
			  struct i2c_adapter **adap,
			  unsigned int *funcs)
{
	int id = -1;

	if (argc < 3) {
		cmd_i2c_usage(cdev);
		return VMM_EFAIL;
	}

	id = atoi(argv[2]);
	if (id < 0) {
		cmd_i2c_usage(cdev);
		return VMM_EFAIL;
	}

	if (NULL == (*adap = i2c_get_adapter(id))) {
		vmm_cprintf(cdev, "Failed to get adapter %d\n", id);
		return VMM_ENODEV;
	}

	*funcs = i2c_get_functionality(*adap);
	return VMM_OK;
}
示例#2
0
int i2cdev_ioctl (struct inode *inode, struct file *file, unsigned int cmd, 
                  unsigned long arg)
{
	struct i2c_client *client = (struct i2c_client *)file->private_data;
	struct i2c_rdwr_ioctl_data rdwr_arg;
	struct i2c_smbus_ioctl_data data_arg;
	union i2c_smbus_data temp;
	struct i2c_msg *rdwr_pa;
	u8 **data_ptrs;
	int i,datasize,res;
	unsigned long funcs;

#ifdef DEBUG
	printk(KERN_DEBUG "i2c-dev.o: i2c-%d ioctl, cmd: 0x%x, arg: %lx.\n", 
	       MINOR(inode->i_rdev),cmd, arg);
#endif /* DEBUG */

	switch ( cmd ) {
	case I2C_SLAVE:
	case I2C_SLAVE_FORCE:
		if ((arg > 0x3ff) || 
		    (((client->flags & I2C_M_TEN) == 0) && arg > 0x7f))
			return -EINVAL;
		if ((cmd == I2C_SLAVE) && i2c_check_addr(client->adapter,arg))
			return -EBUSY;
		client->addr = arg;
		return 0;
	case I2C_TENBIT:
		if (arg)
			client->flags |= I2C_M_TEN;
		else
			client->flags &= ~I2C_M_TEN;
		return 0;
	case I2C_FUNCS:
		funcs = i2c_get_functionality(client->adapter);
		return (copy_to_user((unsigned long *)arg,&funcs,
		                     sizeof(unsigned long)))?-EFAULT:0;

	case I2C_RDWR:
		if (copy_from_user(&rdwr_arg, 
				   (struct i2c_rdwr_ioctl_data *)arg, 
				   sizeof(rdwr_arg)))
			return -EFAULT;

		/* Put an arbritrary limit on the number of messages that can
		 * be sent at once */
		if (rdwr_arg.nmsgs > 42)
			return -EINVAL;
		
		rdwr_pa = (struct i2c_msg *)
			kmalloc(rdwr_arg.nmsgs * sizeof(struct i2c_msg), 
			GFP_KERNEL);

		if (rdwr_pa == NULL) return -ENOMEM;

		if (copy_from_user(rdwr_pa, rdwr_arg.msgs,
				   rdwr_arg.nmsgs * sizeof(struct i2c_msg))) {
			kfree(rdwr_pa);
			return -EFAULT;
		}

		data_ptrs = (u8 **) kmalloc(rdwr_arg.nmsgs * sizeof(u8 *),
					    GFP_KERNEL);
		if (data_ptrs == NULL) {
			kfree(rdwr_pa);
			return -ENOMEM;
		}

		res = 0;
		for( i=0; i<rdwr_arg.nmsgs; i++ )
		{
			/* Limit the size of the message to a sane amount */
			if (rdwr_pa[i].len > 8192) {
				res = -EINVAL;
				break;
			}
			data_ptrs[i] = rdwr_pa[i].buf;
			rdwr_pa[i].buf = kmalloc(rdwr_pa[i].len, GFP_KERNEL);
			if(rdwr_pa[i].buf == NULL)
			{
				res = -ENOMEM;
				break;
			}
			if(copy_from_user(rdwr_pa[i].buf,
				data_ptrs[i],
				rdwr_pa[i].len))
			{
				++i; /* Needs to be kfreed too */
				res = -EFAULT;
				break;
			}
		}
		if (res < 0) {
			int j;
			for (j = 0; j < i; ++j)
				kfree(rdwr_pa[j].buf);
			kfree(data_ptrs);
			kfree(rdwr_pa);
			return res;
		}

		res = i2c_transfer(client->adapter,
			rdwr_pa,
			rdwr_arg.nmsgs);
		while(i-- > 0)
		{
			if( res>=0 && (rdwr_pa[i].flags & I2C_M_RD))
			{
				if(copy_to_user(
					data_ptrs[i],
					rdwr_pa[i].buf,
					rdwr_pa[i].len))
				{
					res = -EFAULT;
				}
			}
			kfree(rdwr_pa[i].buf);
		}
		kfree(data_ptrs);
		kfree(rdwr_pa);
		return res;

	case I2C_SMBUS:
		if (copy_from_user(&data_arg,
		                   (struct i2c_smbus_ioctl_data *) arg,
		                   sizeof(struct i2c_smbus_ioctl_data)))
			return -EFAULT;
		if ((data_arg.size != I2C_SMBUS_BYTE) && 
		    (data_arg.size != I2C_SMBUS_QUICK) &&
		    (data_arg.size != I2C_SMBUS_BYTE_DATA) && 
		    (data_arg.size != I2C_SMBUS_WORD_DATA) &&
		    (data_arg.size != I2C_SMBUS_PROC_CALL) &&
		    (data_arg.size != I2C_SMBUS_BLOCK_DATA) &&
		    (data_arg.size != I2C_SMBUS_I2C_BLOCK_DATA)) {
#ifdef DEBUG
			printk(KERN_DEBUG "i2c-dev.o: size out of range (%x) in ioctl I2C_SMBUS.\n",
			       data_arg.size);
#endif
			return -EINVAL;
		}
		/* Note that I2C_SMBUS_READ and I2C_SMBUS_WRITE are 0 and 1, 
		   so the check is valid if size==I2C_SMBUS_QUICK too. */
		if ((data_arg.read_write != I2C_SMBUS_READ) && 
		    (data_arg.read_write != I2C_SMBUS_WRITE)) {
#ifdef DEBUG
			printk(KERN_DEBUG "i2c-dev.o: read_write out of range (%x) in ioctl I2C_SMBUS.\n",
			       data_arg.read_write);
#endif
			return -EINVAL;
		}

		/* Note that command values are always valid! */

		if ((data_arg.size == I2C_SMBUS_QUICK) ||
		    ((data_arg.size == I2C_SMBUS_BYTE) && 
		    (data_arg.read_write == I2C_SMBUS_WRITE)))
			/* These are special: we do not use data */
			return i2c_smbus_xfer(client->adapter, client->addr,
			                      client->flags,
			                      data_arg.read_write,
			                      data_arg.command,
			                      data_arg.size, NULL);

		if (data_arg.data == NULL) {
#ifdef DEBUG
			printk(KERN_DEBUG "i2c-dev.o: data is NULL pointer in ioctl I2C_SMBUS.\n");
#endif
			return -EINVAL;
		}

		if ((data_arg.size == I2C_SMBUS_BYTE_DATA) ||
		    (data_arg.size == I2C_SMBUS_BYTE))
			datasize = sizeof(data_arg.data->byte);
		else if ((data_arg.size == I2C_SMBUS_WORD_DATA) || 
		         (data_arg.size == I2C_SMBUS_PROC_CALL))
			datasize = sizeof(data_arg.data->word);
		else /* size == I2C_SMBUS_BLOCK_DATA */
			datasize = sizeof(data_arg.data->block);

		if ((data_arg.size == I2C_SMBUS_PROC_CALL) || 
		    (data_arg.read_write == I2C_SMBUS_WRITE)) {
			if (copy_from_user(&temp, data_arg.data, datasize))
				return -EFAULT;
		}
		res = i2c_smbus_xfer(client->adapter,client->addr,client->flags,
		      data_arg.read_write,
		      data_arg.command,data_arg.size,&temp);
		if (! res && ((data_arg.size == I2C_SMBUS_PROC_CALL) || 
			      (data_arg.read_write == I2C_SMBUS_READ))) {
			if (copy_to_user(data_arg.data, &temp, datasize))
				return -EFAULT;
		}
		return res;

	default:
		return i2c_control(client,cmd,arg);
	}
	return 0;
}
static int s2mu003_mfd_probe(struct i2c_client *i2c,
			    const struct i2c_device_id *id)
{
	int ret = 0;
	u8 data = 0;
	struct device_node *of_node = i2c->dev.of_node;
	s2mu003_mfd_chip_t *chip;
	s2mu003_mfd_platform_data_t *pdata = i2c->dev.platform_data;

	pr_info("%s : S2MU003 MFD Driver start probe\n", __func__);
	if (of_node) {
		pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
		if (!pdata) {
			dev_err(&i2c->dev, "Failed to allocate memory\n");
			ret = -ENOMEM;
			goto err_dt_nomem;
		}
		ret = s2mu003mfd_parse_dt(&i2c->dev, pdata);
		if (ret < 0)
			goto err_parse_dt;
	} else {
		pdata = i2c->dev.platform_data;
	}

	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
	if (chip ==  NULL) {
		dev_err(&i2c->dev, "Memory is not enough.\n");
		ret = -ENOMEM;
		goto err_mfd_nomem;
	}
	chip->dev = &i2c->dev;

	ret = i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
			I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_I2C_BLOCK);
	if (!ret) {
		ret = i2c_get_functionality(i2c->adapter);
		dev_err(chip->dev, "I2C functionality is not supported.\n");
		ret = -ENOSYS;
		goto err_i2cfunc_not_support;
	}

	chip->i2c_client = i2c;
	chip->pdata = pdata;

	/* if board-init had already assigned irq_base (>=0) ,
	no need to allocate it;
	assign -1 to let this driver allocate resource by itself*/
	if (pdata->irq_base < 0)
		pdata->irq_base = irq_alloc_descs(-1, 0, S2MU003_IRQS_NR, 0);
	if (pdata->irq_base < 0) {
		pr_err("%s:%s irq_alloc_descs Fail! ret(%d)\n",
				"s2mu003-mfd", __func__, pdata->irq_base);
		ret = -EINVAL;
		goto irq_base_err;
	} else {
		chip->irq_base = pdata->irq_base;
		pr_info("%s:%s irq_base = %d\n",
				"s2mu003-mfd", __func__, chip->irq_base);
	irq_domain_add_legacy(of_node, S2MU003_IRQS_NR, chip->irq_base, 0,
				&irq_domain_simple_ops, NULL);
	}

	i2c_set_clientdata(i2c, chip);
	mutex_init(&chip->io_lock);

	wake_lock_init(&(chip->irq_wake_lock), WAKE_LOCK_SUSPEND,
			"s2mu003mfd_wakelock");

	/* To disable MRST function should be
	finished before set any reg init-value*/
	data = s2mu003_reg_read(i2c, 0x47);
	pr_info("%s : Manual Reset Data = 0x%x", __func__, data);
	s2mu003_clr_bits(i2c, 0x47, 1<<3); /*Disable Manual Reset*/

	ret = s2mu003_init_irq(chip);

	if (ret < 0) {
		dev_err(chip->dev,
				"Error : can't initialize S2MU003 MFD irq\n");
		goto err_init_irq;
	}

#ifdef CONFIG_REGULATOR_S2MU003
	ret = mfd_add_devices(chip->dev, 0, &s2mu003_regulator_devs[0],
			ARRAY_SIZE(s2mu003_regulator_devs),
			NULL, chip->irq_base, NULL);
	if (ret < 0) {
		dev_err(chip->dev,
				"Error : can't add regulator\n");
		goto err_add_regulator_devs;
	}
#endif /*CONFIG_REGULATOR_S2MU003*/

#ifdef CONFIG_LEDS_S2MU003
	ret = mfd_add_devices(chip->dev, 0, &s2mu003_fled_devs[0],
			ARRAY_SIZE(s2mu003_fled_devs),
			NULL, chip->irq_base, NULL);
	if (ret < 0) {
		dev_err(chip->dev, "Failed : add FlashLED devices");
		goto err_add_fled_devs;
	}
#endif /*CONFIG_LEDS_S2MU003*/


#ifdef CONFIG_CHARGER_S2MU003
	ret = mfd_add_devices(chip->dev, 0, &s2mu003_charger_devs[0],
			ARRAY_SIZE(s2mu003_charger_devs),
			NULL, chip->irq_base, NULL);
	if (ret < 0) {
		dev_err(chip->dev, "Failed : add charger devices\n");
		goto err_add_chg_devs;
	}
#endif /*CONFIG_CHARGER_S2MU003*/

	device_init_wakeup(chip->dev, 1);
	enable_irq_wake(chip->irq);

	pr_info("%s : S2MU003 MFD Driver Fin probe\n", __func__);
	return ret;

#ifdef CONFIG_CHARGER_S2MU003
err_add_chg_devs:
#endif /*CONFIG_CHARGER_S2MU003*/

#ifdef CONFIG_LEDS_S2MU003
err_add_fled_devs:
#endif /*CONFIG_LEDS_S2MU003*/
	mfd_remove_devices(chip->dev);
#ifdef CONFIG_REGULATOR_S2MU003
err_add_regulator_devs:
#endif /*CONFIG_REGULATOR_S2MU003*/
err_init_irq:
	wake_lock_destroy(&(chip->irq_wake_lock));
	mutex_destroy(&chip->io_lock);
irq_base_err:
err_i2cfunc_not_support:
	kfree(chip);
err_mfd_nomem:
	if(pdata)
		kfree(pdata);
err_parse_dt:
err_dt_nomem:
	return ret;
}
static int sm5703_mfd_probe(struct i2c_client *i2c,
		const struct i2c_device_id *id)
{
	int ret = 0;
	struct device_node *of_node = i2c->dev.of_node;
	sm5703_mfd_chip_t *chip;
	sm5703_mfd_platform_data_t *pdata = i2c->dev.platform_data;

	pr_info("%s : SM5703 MFD Driver %s start probing\n",
			__func__, SM5703_DRV_VER);

	if (of_node) {
		pdata = devm_kzalloc(&i2c->dev, sizeof(*pdata), GFP_KERNEL);
		if (!pdata) {
			dev_err(&i2c->dev, "Failed to allocate memory\n");
			ret = -ENOMEM;
			goto err_dt_nomem;
		}
		ret = sm5703mfd_parse_dt(&i2c->dev, pdata);
		if (ret < 0)
			goto err_parse_dt;
	} else {
		pdata = i2c->dev.platform_data;
	}

	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
	if (chip == NULL) {
		dev_err(&i2c->dev, "Memory is not enough.\n");
		ret = -ENOMEM;
		goto err_mfd_nomem;
	}

	chip->dev = &i2c->dev;

	ret = i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
			I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_I2C_BLOCK);
	if (!ret) {
		ret = i2c_get_functionality(i2c->adapter);
		dev_err(chip->dev, "I2C functionality is not supported.\n");
		ret = -ENOSYS;
		goto err_i2cfunc_not_support;
	}

	chip->i2c_client = i2c;
	chip->pdata = pdata;

	pr_info("%s:%s pdata->irq_base = %d\n",
			"sm5703-mfd", __func__, pdata->irq_base);
	/* if board-init had already assigned irq_base (>=0) ,
	   no need to allocate it;
	   assign -1 to let this driver allocate resource by itself*/
	if (pdata->irq_base < 0)
		pdata->irq_base = irq_alloc_descs(-1, 0, SM5703_IRQS_NR, 0);
	if (pdata->irq_base < 0) {
		pr_err("%s:%s irq_alloc_descs Fail! ret(%d)\n",
				"sm5703-mfd", __func__, pdata->irq_base);
		ret = -EINVAL;
		goto irq_base_err;
	} else {
		chip->irq_base = pdata->irq_base;
		pr_info("%s:%s irq_base = %d\n",
				"sm5703-mfd", __func__, chip->irq_base);
	}

	i2c_set_clientdata(i2c, chip);
	mutex_init(&chip->io_lock);
	mutex_init(&chip->suspend_flag_lock);

	/* Set MRSTB GPIO pin to high level to indicate that
	 * system is alive (do NOT do reset) */
	ret = gpio_request(pdata->mrstb_gpio, "sm5703_mrstb");
	if (ret == 0) {
		ret = gpio_direction_output(pdata->mrstb_gpio, 1);
		if (ret < 0)
			pr_err("%s : cannot set GPIO%d output direction(%d)\n",
					__func__, pdata->mrstb_gpio, ret);

	} else
		pr_info("%s : Request GPIO %d failed\n",
				__func__, (int)pdata->mrstb_gpio);

	wake_lock_init(&(chip->irq_wake_lock), WAKE_LOCK_SUSPEND,
			"sm5703mfd_wakelock");

	ret = sm5703_init_irq(chip);

	if (ret < 0) {
		dev_err(chip->dev,
				"Error : can't initialize SM5703 MFD irq\n");
		goto err_init_irq;
	}

#ifdef CONFIG_REGULATOR_SM5703
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
	ret = mfd_add_devices(chip->dev, 0, &sm5703_regulator_devs[0],
			ARRAY_SIZE(sm5703_regulator_devs),
			NULL, chip->irq_base, NULL);
#else
	ret = mfd_add_devices(chip->dev, 0, &sm5703_regulator_devs[0],
			ARRAY_SIZE(sm5703_regulator_devs),
			NULL, chip->irq_base);
#endif
	if (ret < 0) {
		dev_err(chip->dev,
				"Error : can't add regulator\n");
		goto err_add_regulator_devs;
	}
#endif /*CONFIG_REGULATOR_SM5703*/

#ifdef CONFIG_FLED_SM5703
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
	ret = mfd_add_devices(chip->dev, 0, &sm5703_fled_devs[0],
			ARRAY_SIZE(sm5703_fled_devs),
			NULL, chip->irq_base, NULL);
#else
	ret = mfd_add_devices(chip->dev, 0, &sm5703_fled_devs[0],
			ARRAY_SIZE(sm5703_fled_devs),
			NULL, chip->irq_base);
#endif
	if (ret < 0) {
		dev_err(chip->dev, "Failed : add FlashLED devices");
		goto err_add_fled_devs;
	}
#endif /*CONFIG_FLED_SM5703*/

#ifdef CONFIG_CHARGER_SM5703
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
	ret = mfd_add_devices(chip->dev, 0, &sm5703_charger_devs[0],
			ARRAY_SIZE(sm5703_charger_devs),
			NULL, chip->irq_base, NULL);
#else
	ret = mfd_add_devices(chip->dev, 0, &sm5703_charger_devs[0],
			ARRAY_SIZE(sm5703_charger_devs),
			NULL, chip->irq_base);
#endif
	if (ret<0) {
		dev_err(chip->dev, "Failed : add charger devices\n");
		goto err_add_chg_devs;
	}
#endif /*CONFIG_CHARGER_SM5703*/

	pr_info("%s : SM5703 MFD Driver Fin probe\n", __func__);
	return ret;

#ifdef CONFIG_CHARGER_SM5703
err_add_chg_devs:
#endif /*CONFIG_CHARGER_SM5703*/

#ifdef CONFIG_FLED_SM5703
err_add_fled_devs:
#endif /*CONFIG_FLED_SM5703*/
	mfd_remove_devices(chip->dev);
#ifdef CONFIG_REGULATOR_SM5703
err_add_regulator_devs:
#endif /*CONFIG_REGULATOR_SM5703*/
err_init_irq:
	wake_lock_destroy(&(chip->irq_wake_lock));
	mutex_destroy(&chip->io_lock);
	kfree(chip);
irq_base_err:
err_mfd_nomem:
err_i2cfunc_not_support:
err_parse_dt:
err_dt_nomem:
	return ret;
}
示例#5
0
static int bq51221_charger_probe(
						struct i2c_client *client,
						const struct i2c_device_id *id)
{
	struct device_node *of_node = client->dev.of_node;
	struct bq51221_charger_data *charger;
	bq51221_charger_platform_data_t *pdata = client->dev.platform_data;
	int ret = 0;

	dev_info(&client->dev,
		"%s: bq51221 Charger Driver Loading\n", __func__);

	if (of_node) {
		pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
		if (!pdata) {
			dev_err(&client->dev, "Failed to allocate memory\n");
			return -ENOMEM;
		}
		ret = bq51221_chg_parse_dt(&client->dev, pdata);
		if (ret < 0)
			goto err_parse_dt;
	} else {
		pdata = client->dev.platform_data;
	}

	charger = kzalloc(sizeof(*charger), GFP_KERNEL);
	if (charger == NULL) {
		dev_err(&client->dev, "Memory is not enough.\n");
		ret = -ENOMEM;
		goto err_wpc_nomem;
	}
	charger->dev = &client->dev;

	ret = i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
		I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_I2C_BLOCK);
	if (!ret) {
		ret = i2c_get_functionality(client->adapter);
		dev_err(charger->dev, "I2C functionality is not supported.\n");
		ret = -ENOSYS;
		goto err_i2cfunc_not_support;
	}

	charger->client = client;
	charger->pdata = pdata;

    pr_info("%s: %s\n", __func__, charger->pdata->wireless_charger_name );

	/* if board-init had already assigned irq_base (>=0) ,
	no need to allocate it;
	assign -1 to let this driver allocate resource by itself*/
#if 0 /* this part is for bq51221s */
    if (pdata->irq_base < 0)
        pdata->irq_base = irq_alloc_descs(-1, 0, BQ51221_EVENT_IRQ, 0);
	if (pdata->irq_base < 0) {
		pr_err("%s: irq_alloc_descs Fail! ret(%d)\n",
				__func__, pdata->irq_base);
		ret = -EINVAL;
		goto irq_base_err;
	} else {
		charger->irq_base = pdata->irq_base;
		pr_info("%s: irq_base = %d\n",
			 __func__, charger->irq_base);

#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,4,0))
		irq_domain_add_legacy(of_node, BQ51221_EVENT_IRQ, charger->irq_base, 0,
				      &irq_domain_simple_ops, NULL);
#endif /*(LINUX_VERSION_CODE>=KERNEL_VERSION(3,4,0))*/
	}
#endif
	i2c_set_clientdata(client, charger);

	charger->psy_chg.name		= pdata->wireless_charger_name;
	charger->psy_chg.type		= POWER_SUPPLY_TYPE_UNKNOWN;
	charger->psy_chg.get_property	= bq51221_chg_get_property;
	charger->psy_chg.set_property	= bq51221_chg_set_property;
	charger->psy_chg.properties	= sec_charger_props;
	charger->psy_chg.num_properties	= ARRAY_SIZE(sec_charger_props);

	mutex_init(&charger->io_lock);

#if 0 /* this part is for bq51221s */

	if (charger->chg_irq) {
		INIT_DELAYED_WORK(
			&charger->isr_work, bq51221_chg_isr_work);

		ret = request_threaded_irq(charger->chg_irq,
				NULL, bq51221_chg_irq_thread,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
				"charger-irq", charger);
		if (ret) {
			dev_err(&client->dev,
				"%s: Failed to Reqeust IRQ\n", __func__);
			goto err_supply_unreg;
		}

		ret = enable_irq_wake(charger->chg_irq);
		if (ret < 0)
			dev_err(&client->dev,
				"%s: Failed to Enable Wakeup Source(%d)\n",
				__func__, ret);
	}
#endif
	charger->pdata->cs100_status = 0;
	charger->pdata->pad_mode = BQ51221_PAD_MODE_NONE;

	ret = power_supply_register(&client->dev, &charger->psy_chg);
	if (ret) {
		dev_err(&client->dev,
			"%s: Failed to Register psy_chg\n", __func__);
		goto err_supply_unreg;
	}

	charger->wqueue = create_workqueue("bq51221_workqueue");
	if (!charger->wqueue) {
		pr_err("%s: Fail to Create Workqueue\n", __func__);
		goto err_pdata_free;
	}

	wake_lock_init(&(charger->wpc_wake_lock), WAKE_LOCK_SUSPEND,
			"wpc_wakelock");
	INIT_DELAYED_WORK(&charger->wpc_work, bq51221_detect_work);

	dev_info(&client->dev,
		"%s: bq51221 Charger Driver Loaded\n", __func__);

	return 0;

err_pdata_free:
	power_supply_unregister(&charger->psy_chg);
err_supply_unreg:
	mutex_destroy(&charger->io_lock);
err_i2cfunc_not_support:
	kfree(charger);
err_wpc_nomem:
err_parse_dt:
	kfree(pdata);
	return ret;
}
static int __devinit rt5033_mfd_probe(struct i2c_client *i2c,
		const struct i2c_device_id *id)
{
	int ret = 0;
	u8 data = 0;

	rt5033_mfd_chip_t *chip;
	rt5033_mfd_platform_data_t *pdata = i2c->dev.platform_data;

	pr_info("%s : RT5033 MFD Driver start probe\n", __func__);

	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
	if (chip ==  NULL) {
		dev_err(chip->dev, "Memory is not enough.\n");
		ret = -ENOMEM;
		goto err_mfd_nomem;
	}

	ret = i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA |
			I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_I2C_BLOCK);
	if (!ret) {
		ret = i2c_get_functionality(i2c->adapter);
		dev_err(chip->dev, "I2C functionality is not supported.\n");
		ret = -ENOSYS;
		goto err_i2cfunc_not_support;
	}

	chip->dev = &i2c->dev;
	chip->i2c_client = i2c;
	chip->pdata = pdata;

	pdata->irq_base = irq_alloc_descs(-1, 0, RT5033_IRQS_NR, -1);
	if (pdata->irq_base < 0) {
		pr_err("%s:%s irq_alloc_descs Fail! ret(%d)\n",
				"rt5033-mfd", __func__, pdata->irq_base);
		ret = -EINVAL;
		goto irq_base_err;
	} else {
		chip->irq_base = pdata->irq_base;
	}

	i2c_set_clientdata(i2c, chip);
	mutex_init(&chip->io_lock);

	wake_lock_init(&(chip->irq_wake_lock), WAKE_LOCK_SUSPEND,
			"rt5033mfd_wakelock");

	ret = rt5033_clr_bits(i2c, 0x47, 1<<3);
	pr_info("Diable MANUAL RESET (%d)\n", ret);

	ret = rt5033_init_irq(chip);

	if (ret < 0) {
		dev_err(chip->dev,
				"Error : can't initialize RT5033 MFD irq\n");
		goto err_init_irq;
	}

#ifdef CONFIG_REGULATOR_RT5033
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
	ret = mfd_add_devices(chip->dev, 0, &rt5033_regulator_devs[0],
			ARRAY_SIZE(rt5033_regulator_devs),
			NULL, chip->irq_base, NULL);
#else
	ret = mfd_add_devices(chip->dev, 0, &rt5033_regulator_devs[0],
			ARRAY_SIZE(rt5033_regulator_devs),
			NULL, chip->irq_base);
#endif
	if (ret < 0) {
		dev_err(chip->dev,
				"Error : can't add regulator\n");
		goto err_add_regulator_devs;
	}
#endif /*CONFIG_REGULATOR_RT5033*/

#ifdef CONFIG_FLED_RT5033
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
	ret = mfd_add_devices(chip->dev, 0, &rt5033_fled_devs[0],
			ARRAY_SIZE(rt5033_fled_devs),
			NULL, chip->irq_base, NULL);
#else
	ret = mfd_add_devices(chip->dev, 0, &rt5033_fled_devs[0],
			ARRAY_SIZE(rt5033_fled_devs),
			NULL, chip->irq_base);
#endif
	if (ret < 0)
	{
		dev_err(chip->dev,"Failed : add FlashLED devices");
		goto err_add_fled_devs;
	}
#endif /*CONFIG_FLED_RT5033*/


#ifdef CONFIG_CHARGER_RT5033
#if (LINUX_VERSION_CODE>=KERNEL_VERSION(3,6,0))
	ret = mfd_add_devices(chip->dev, 0, &rt5033_charger_devs[0],
			ARRAY_SIZE(rt5033_charger_devs),
			NULL, chip->irq_base, NULL);
#else
	ret = mfd_add_devices(chip->dev, 0, &rt5033_charger_devs[0],
			ARRAY_SIZE(rt5033_charger_devs),
			NULL, chip->irq_base);
#endif
	if (ret<0) {
		dev_err(chip->dev, "Failed : add charger devices\n");
		goto err_add_chg_devs;
	}
#endif /*CONFIG_CHARGER_RT5033*/

	pr_info("%s : RT5033 MFD Driver Fin probe\n", __func__);
	return ret;

#ifdef CONFIG_CHARGER_RT5033
err_add_chg_devs:
#endif /*CONFIG_CHARGER_RT5033*/

#ifdef CONFIG_FLED_RT5033
err_add_fled_devs:
#endif /*CONFIG_FLED_RT5033*/
	mfd_remove_devices(chip->dev);
#ifdef CONFIG_REGULATOR_RT5033
err_add_regulator_devs:
#endif /*CONFIG_REGULATOR_RT5033*/
err_init_irq:
	wake_lock_destroy(&(chip->irq_wake_lock));
	mutex_destroy(&chip->io_lock);
	kfree(chip);
irq_base_err:
err_mfd_nomem:
err_i2cfunc_not_support:
	return ret;
}