示例#1
0
static int smb347_shutdown(struct i2c_client *client)
{
	int ret;
	printk("smb347_shutdown+\n");

	cancel_delayed_work(&charger->curr_limit_work);
	smb347_set_InputCurrentlimit(charger->client, 1800);

	/* Disable OTG */
	ret = smb347_configure_otg(client, 0);
	if (ret < 0)
		dev_err(&client->dev, "%s() error in configuring"
			"otg..\n", __func__);

	/* configure charger */
	ret = smb347_configure_charger(client, 1);
	if (ret < 0)
		dev_err(&client->dev, "%s() error in configuring"
			"otg..\n", __func__);

	printk("smb347_shutdown-\n");
	return 0;
}
示例#2
0
static int __devinit smb347_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
	int ret, irq_num;
	uint8_t buf[15];

	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
		return -EIO;

	charger = kzalloc(sizeof(*charger), GFP_KERNEL);
	if (!charger)
		return -ENOMEM;

	charger->client = client;
	charger->dev = &client->dev;
	i2c_set_clientdata(client, charger);

	/* disable STAT pin IRQ */
	smb347_intr_sts(charger->client);

	ret = sysfs_create_group(&client->dev.kobj, &smb347_group);
	if (ret) {
		dev_err(&client->dev, "smb347_probe: unable to create the sysfs\n");
	}

	mutex_init(&charger->cable_lock);

	smb347_wq = create_singlethread_workqueue("smb347_wq");
	INIT_DELAYED_WORK_DEFERRABLE(&charger->inok_isr_work, inok_isr_work_function);

	INIT_DELAYED_WORK_DEFERRABLE(&charger->cable_det_work, cable_type_detect);

	wake_lock_init(&charger_wakelock, WAKE_LOCK_SUSPEND,
			"charger_configuration");
	wake_lock_init(&charger_ac_detec_wakelock, WAKE_LOCK_SUSPEND,
			"charger_ac_detec_wakelock");
	INIT_DELAYED_WORK(&charger->curr_limit_work,
			smb347_set_curr_limit_work_func);
	INIT_DELAYED_WORK(&charger->test_fail_clear_work,
			smb347_test_fail_clear_work_function);
	charger->curr_limit = UINT_MAX;
	smb347_set_InputCurrentlimit(charger->client, 900);
	charger->cur_cable_type = non_cable;
	charger->old_cable_type = non_cable;
	charger->test_1800mA_fail = 0;

	ret = smb347_inok_irq(charger);
	if (ret) {
		dev_err(&client->dev, "%s(): Failed in requesting ACOK# pin isr\n",
				__func__);
		goto error;
	}

	queue_delayed_work(smb347_wq, &charger->cable_det_work, 0.5*HZ);

	ret = register_otg_callback(smb347_otg_status, charger);
	if (ret < 0)
		goto error;

	smb347_charger_status = 1;

	return 0;
error:
	kfree(charger);
	return ret;
}
示例#3
0
static void smb347_set_curr_limit_work_func(struct work_struct *work)
{
	smb347_set_InputCurrentlimit(charger->client, 1800);
}
示例#4
0
/* workqueue function */
static int cable_type_detect(void)
{
	struct i2c_client *client = charger->client;
	u8 retval;
	int  success = 0;
	int ac_ok = GPIO_AC_OK;

	/*
	printk("cable_type_detect %d %lu %d %x jiffies=%lu %lu+\n",
	charger->old_cable_type,
	charger->time_of_1800mA_limit,
	gpio_get_value(gpio),
	time_after(charger->time_of_1800mA_limit+(4*HZ), jiffies ),
	jiffies,
	charger->time_of_1800mA_limit+(ADAPTER_PROTECT_DELAY*HZ));
	*/

	mutex_lock(&charger->cable_lock);

	if ((charger->old_cable_type == ac_cable) &&
	charger->time_of_1800mA_limit && gpio_get_value(ac_ok) &&
	time_after(charger->time_of_1800mA_limit+
					ADAPTER_PROTECT_DELAY, jiffies)) {
		smb347_set_InputCurrentlimit(client, 900);
		charger->test_1800mA_fail = 1;
		queue_delayed_work(smb347_wq,
				&charger->test_fail_clear_work, 1*HZ);
	}

	if (gpio_get_value(ac_ok)) {
		printk(KERN_INFO "INOK=H\n");
		charger->cur_cable_type = non_cable;
		smb347_set_InputCurrentlimit(client, 900);
		success = bq27541_battery_callback(non_cable);
#ifdef TOUCH_CALLBACK_ENABLED
               touch_callback(non_cable);
#endif
		wake_unlock(&charger_wakelock);
	} else {
		printk(KERN_INFO "INOK=L\n");

		/* cable type dection */
		retval = smb347_read(client, smb347_STS_REG_E);
		SMB_NOTICE("Reg3F : 0x%02x\n", retval);
		if (retval & USBIN) {
			retval = smb347_read(client, smb347_STS_REG_D);
			SMB_NOTICE("Reg3E : 0x%02x\n", retval);
			if (retval & APSD_OK) {
					retval &= APSD_RESULT;
				if (retval == APSD_CDP) {
					printk(KERN_INFO "Cable: CDP\n");
					charger->cur_cable_type = ac_cable;
					success = bq27541_battery_callback(ac_cable);
#ifdef TOUCH_CALLBACK_ENABLED
                                    touch_callback(ac_cable);
#endif
				} else if (retval == APSD_DCP) {
					printk(KERN_INFO "Cable: DCP\n");
					charger->cur_cable_type = ac_cable;
					success = bq27541_battery_callback(ac_cable);
#ifdef TOUCH_CALLBACK_ENABLED
                                    touch_callback(ac_cable);
#endif
				} else if (retval == APSD_OTHER) {
					charger->cur_cable_type = ac_cable;
					success = bq27541_battery_callback(ac_cable);
#ifdef TOUCH_CALLBACK_ENABLED
                                   touch_callback(ac_cable);
#endif
					printk(KERN_INFO "Cable: OTHER\n");
				} else if (retval == APSD_SDP) {
					printk(KERN_INFO "Cable: SDP\n");
					charger->cur_cable_type = usb_cable;
					success = bq27541_battery_callback(usb_cable);
#ifdef TOUCH_CALLBACK_ENABLED
                                    touch_callback(usb_cable);
#endif
				} else {
					charger->cur_cable_type = unknow_cable;
					printk(KERN_INFO "Unkown Plug In Cable type !\n");

					if(ac_cable == cable_state_detect)
					{
						charger->cur_cable_type = ac_cable;
						success = bq27541_battery_callback(ac_cable);
#ifdef TOUCH_CALLBACK_ENABLED
						touch_callback(ac_cable);
#endif
						printk(KERN_INFO "Change unknow type to ac\n");
					}
					else if(usb_cable == cable_state_detect)
					{
						charger->cur_cable_type = usb_cable;
						success = bq27541_battery_callback(usb_cable);
#ifdef TOUCH_CALLBACK_ENABLED
						touch_callback(usb_cable);
#endif
						printk(KERN_INFO "Change unknow type to usb\n");
					}
				}
			} else {
				charger->cur_cable_type = unknow_cable;
				printk(KERN_INFO "APSD not completed\n");
			}
		} else {
			charger->cur_cable_type = unknow_cable;
			printk(KERN_INFO "USBIN=0\n");
		}
	}

	if (charger->cur_cable_type == ac_cable &&
		charger->old_cable_type != ac_cable &&
		charger->test_1800mA_fail == 0) {
		wake_lock(&charger_wakelock);
		queue_delayed_work(smb347_wq, &charger->curr_limit_work,
					DELAY_FOR_CURR_LIMIT_RECONF*HZ);
	}
	charger->old_cable_type = charger->cur_cable_type;

	mutex_unlock(&charger->cable_lock);
	return success;
}
示例#5
0
/* workqueue function */
static int cable_type_detect(void)
{
	struct i2c_client *client = charger->client;
	u8 retval;
	int  success = 0;
	int ac_ok = GPIO_AC_OK;
	int dock_in = gpio_dock_in;

	/*
	printk("cable_type_detect %d %lu %d %x jiffies=%lu %lu+\n",
	charger->old_cable_type,
	charger->time_of_1800mA_limit,
	gpio_get_value(gpio),
	time_after(charger->time_of_1800mA_limit+(4*HZ), jiffies ),
	jiffies,
	charger->time_of_1800mA_limit+(ADAPTER_PROTECT_DELAY*HZ));
	*/

	if((pcba_ver <= GROUPER_PCBA_ER2) && (project_id == GROUPER_PROJECT_NAKASI))
		return 0;

	mutex_lock(&charger->cable_lock);

	if ((charger->old_cable_type == ac_cable) &&
	charger->time_of_1800mA_limit && gpio_get_value(ac_ok) &&
	time_after(charger->time_of_1800mA_limit+
					ADAPTER_PROTECT_DELAY, jiffies)) {
		smb347_set_InputCurrentlimit(client, 900);
		charger->test_1800mA_fail = 1;
		queue_delayed_work(smb347_wq,
				&charger->test_fail_clear_work, 1*HZ);
	}

	if (gpio_get_value(ac_ok)) {
		printk(KERN_INFO "INOK=H\n");
		charger->cur_cable_type = non_cable;
		smb347_set_InputCurrentlimit(client, 900);
		success = battery_callback(non_cable);
#ifdef TOUCH_CALLBACK_ENABLED
               touch_callback(non_cable);
#endif
		wake_unlock(&charger_wakelock);
	} else {
		printk(KERN_INFO "INOK=L\n");
		retval = smb347_read(client, smb347_INTR_STS_E);
		SMB_NOTICE("Reg39 : 0x%02x\n", retval);
		if (!(retval & DCIN_OV_UV_STS) && !gpio_get_value(dock_in)) {
			SMB_NOTICE("DC_IN\n");
			success = battery_callback(ac_cable);
		} else {

			/* cable type dection */
			retval = smb347_read(client, smb347_STS_REG_E);
			SMB_NOTICE("Reg3F : 0x%02x\n", retval);
			if (retval & USBIN) {
				SMB_NOTICE("USB_IN\n");
				retval = smb347_read(client, smb347_STS_REG_D);
				SMB_NOTICE("Reg3E : 0x%02x\n", retval);
				if (retval & APSD_OK) {
						retval &= APSD_RESULT;
					if (retval == APSD_CDP) {
						printk(KERN_INFO "Cable: CDP\n");
						charger->cur_cable_type = ac_cable;
						success = battery_callback(ac_cable);
#ifdef TOUCH_CALLBACK_ENABLED
	                                    touch_callback(ac_cable);
#endif
					} else if (retval == APSD_DCP) {
						printk(KERN_INFO "Cable: DCP\n");
						charger->cur_cable_type = ac_cable;
						success = battery_callback(ac_cable);
#ifdef TOUCH_CALLBACK_ENABLED
	                                    touch_callback(ac_cable);
#endif
					} else if (retval == APSD_OTHER) {
						charger->cur_cable_type = ac_cable;
						success = battery_callback(ac_cable);
#ifdef TOUCH_CALLBACK_ENABLED
	                                   touch_callback(ac_cable);
#endif
						printk(KERN_INFO "Cable: OTHER\n");
					} else if (retval == APSD_SDP) {
						printk(KERN_INFO "Cable: SDP\n");
						charger->cur_cable_type = usb_cable;
						success = battery_callback(usb_cable);
#ifdef TOUCH_CALLBACK_ENABLED
	                                    touch_callback(usb_cable);
#endif
					} else {
						charger->cur_cable_type = unknow_cable;
						printk(KERN_INFO "Unkown Plug In Cable type !\n");

						if(usb_det_cable_type) {
							printk(KERN_INFO "Use usb det %s cable to report\n",
								(usb_det_cable_type == ac_cable) ? "ac" : "usb");
							charger->cur_cable_type = usb_det_cable_type;
							success = battery_callback(usb_det_cable_type);
						}
					}
				} else {
					charger->cur_cable_type = unknow_cable;
					printk(KERN_INFO "APSD not completed\n");
				}
			} else {
				charger->cur_cable_type = unknow_cable;
				printk(KERN_INFO "USBIN=0\n");
			}
		}
	}

	if (charger->cur_cable_type == ac_cable &&
		charger->old_cable_type != ac_cable &&
		charger->test_1800mA_fail == 0) {
		wake_lock(&charger_wakelock);
		queue_delayed_work(smb347_wq, &charger->curr_limit_work,
					DELAY_FOR_CURR_LIMIT_RECONF*HZ);
	}
	charger->old_cable_type = charger->cur_cable_type;

	mutex_unlock(&charger->cable_lock);
	return success;
}