예제 #1
0
static int pm860x_charger_probe(struct platform_device *pdev)
{
	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
	struct pm860x_charger_info *info;
	int ret;
	int count;
	int i;
	int j;

	info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL);
	if (!info)
		return -ENOMEM;

	count = pdev->num_resources;
	for (i = 0, j = 0; i < count; i++) {
		info->irq[j] = platform_get_irq(pdev, i);
		if (info->irq[j] < 0)
			continue;
		j++;
	}
	info->irq_nums = j;

	info->chip = chip;
	info->i2c =
	    (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
	info->i2c_8606 =
	    (chip->id == CHIP_PM8607) ? chip->companion : chip->client;
	if (!info->i2c_8606) {
		dev_err(&pdev->dev, "Missed I2C address of 88PM8606!\n");
		ret = -EINVAL;
		goto out;
	}
	info->dev = &pdev->dev;

	/* set init value for the case we are not using battery */
	set_vchg_threshold(info, VCHG_NORMAL_LOW, VCHG_OVP_LOW);

	mutex_init(&info->lock);
	platform_set_drvdata(pdev, info);

	info->usb.name = "usb";
	info->usb.type = POWER_SUPPLY_TYPE_USB;
	info->usb.supplied_to = pm860x_supplied_to;
	info->usb.num_supplicants = ARRAY_SIZE(pm860x_supplied_to);
	info->usb.properties = pm860x_usb_props;
	info->usb.num_properties = ARRAY_SIZE(pm860x_usb_props);
	info->usb.get_property = pm860x_usb_get_prop;
	ret = power_supply_register(&pdev->dev, &info->usb);
	if (ret)
		goto out;

	pm860x_init_charger(info);

	for (i = 0; i < ARRAY_SIZE(info->irq); i++) {
		ret = request_threaded_irq(info->irq[i], NULL,
			pm860x_irq_descs[i].handler,
			IRQF_ONESHOT, pm860x_irq_descs[i].name, info);
		if (ret < 0) {
			dev_err(chip->dev, "Failed to request IRQ: #%d: %d\n",
				info->irq[i], ret);
			goto out_irq;
		}
	}
	return 0;

out_irq:
	power_supply_unregister(&info->usb);
	while (--i >= 0)
		free_irq(info->irq[i], info);
out:
	return ret;
}
static int __devinit SM5414_charger_probe(
						struct i2c_client *client,
						const struct i2c_device_id *id)
{
	struct i2c_adapter *adapter =
		to_i2c_adapter(client->dev.parent);
	struct sec_charger_info *charger;
	int ret = 0;

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

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

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

	charger->client = client;
	if (client->dev.of_node) {
		void * pdata = kzalloc(sizeof(sec_battery_platform_data_t), GFP_KERNEL);
		if (!pdata)
			goto err_free1;
		charger->pdata = pdata;
		if (SM5414_charger_parse_dt(charger))
			dev_err(&client->dev,
				"%s : Failed to get charger dt\n", __func__);
	} else
		charger->pdata = client->dev.platform_data;

	i2c_set_clientdata(client, charger);

	charger->siop_level = 100;
	charger->psy_chg.name		= "SM5414";
	charger->psy_chg.type		= POWER_SUPPLY_TYPE_UNKNOWN;
	charger->psy_chg.get_property	= SM5414_chg_get_property;
	charger->psy_chg.set_property	= SM5414_chg_set_property;
	charger->psy_chg.properties	= SM5414_charger_props;
	charger->psy_chg.num_properties	= ARRAY_SIZE(SM5414_charger_props);
	charger->is_slow_charging = false;

	if (charger->pdata->chg_gpio_init) {
		if (!charger->pdata->chg_gpio_init()) {
			dev_err(&client->dev,
					"%s: Failed to Initialize GPIO\n", __func__);
			goto err_free;
		}
	}

	if (!SM5414_hal_chg_init(charger->client)) {
		dev_err(&client->dev,
			"%s: Failed to Initialize Charger\n", __func__);
		goto err_free;
	}

	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_free;
	}

	if (charger->pdata->chg_irq) {
		INIT_DELAYED_WORK_DEFERRABLE(
			&charger->isr_work, SM5414_chg_isr_work);

		ret = request_threaded_irq(charger->pdata->chg_irq,
				NULL, SM5414_chg_irq_thread,
				charger->pdata->chg_irq_attr,
				"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->pdata->chg_irq);
		if (ret < 0)
			dev_err(&client->dev,
				"%s: Failed to Enable Wakeup Source(%d)\n",
				__func__, ret);
	}

	ret = SM5414_chg_create_attrs(charger->psy_chg.dev);
	if (ret) {
		dev_err(&client->dev,
			"%s : Failed to create_attrs\n", __func__);
		goto err_req_irq;
	}

	dev_dbg(&client->dev,
		"%s: SM5414 Charger Driver Loaded\n", __func__);
	return 0;

err_req_irq:
	if (charger->pdata->chg_irq)
		free_irq(charger->pdata->chg_irq, charger);
err_supply_unreg:
	power_supply_unregister(&charger->psy_chg);
err_free:
	kfree(charger->pdata);
err_free1:
	kfree(charger);

	return ret;
}
예제 #3
0
static __devinit int max8998_charger_probe(struct platform_device *pdev)
{
	struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
	struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
	struct chg_data *chg;
        struct i2c_client *i2c = iodev->i2c;
	int ret = 0;

	bat_info("%s : MAX8998 Charger Driver Loading\n", __func__);

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

	chg->iodev = iodev;
	chg->pdata = pdata->charger;

	if (!chg->pdata || !chg->pdata->adc_table) {
		pr_err("%s : No platform data & adc_table supplied\n", __func__);
		ret = -EINVAL;
		goto err_bat_table;
	}

	chg->psy_bat.name = "battery";
	chg->psy_bat.type = POWER_SUPPLY_TYPE_BATTERY;
	chg->psy_bat.properties = max8998_battery_props;
	chg->psy_bat.num_properties = ARRAY_SIZE(max8998_battery_props);
	chg->psy_bat.get_property = s3c_bat_get_property;

	chg->psy_usb.name = "usb";
	chg->psy_usb.type = POWER_SUPPLY_TYPE_USB;
	chg->psy_usb.supplied_to = supply_list;
	chg->psy_usb.num_supplicants = ARRAY_SIZE(supply_list);
	chg->psy_usb.properties = s3c_power_properties;
	chg->psy_usb.num_properties = ARRAY_SIZE(s3c_power_properties);
	chg->psy_usb.get_property = s3c_usb_get_property;

	chg->psy_ac.name = "ac";
	chg->psy_ac.type = POWER_SUPPLY_TYPE_MAINS;
	chg->psy_ac.supplied_to = supply_list;
	chg->psy_ac.num_supplicants = ARRAY_SIZE(supply_list);
	chg->psy_ac.properties = s3c_power_properties;
	chg->psy_ac.num_properties = ARRAY_SIZE(s3c_power_properties);
	chg->psy_ac.get_property = s3c_ac_get_property;

	chg->present = 1;
	chg->bat_info.batt_health = POWER_SUPPLY_HEALTH_GOOD;
	chg->bat_info.batt_is_full = false;
	chg->set_batt_full = false;
	chg->set_charge_timeout = false;

	chg->cable_status = CABLE_TYPE_NONE;
	chg->esafe = MAX8998_USB_VBUS_AP_ON;

	mutex_init(&chg->mutex);

	platform_set_drvdata(pdev, chg);

	ret = max8998_write_reg(i2c, MAX8998_REG_IRQM1,
		~(MAX8998_IRQ_DCINR_MASK | MAX8998_IRQ_DCINF_MASK));
	if (ret < 0)
		goto err_kfree;

	ret = max8998_write_reg(i2c, MAX8998_REG_IRQM2, 0xFF);
	if (ret < 0)
		goto err_kfree;

#ifdef TOPOFF_CURRENT_CHECK
	ret = max8998_write_reg(i2c, MAX8998_REG_IRQM3, 0xFF);
#else
	ret = max8998_write_reg(i2c, MAX8998_REG_IRQM3, ~MAX8998_IRQ_TOPOFFR_MASK);
#endif
	if (ret < 0)
		goto err_kfree;

	ret = max8998_write_reg(i2c, MAX8998_REG_IRQM4,
		~(MAX8998_IRQ_LOBAT2_MASK | MAX8998_IRQ_LOBAT1_MASK));
	if (ret < 0)
		goto err_kfree;

	ret = max8998_update_reg(i2c, MAX8998_REG_ONOFF3,
		(1 << MAX8998_SHIFT_ENBATTMON), MAX8998_MASK_ENBATTMON);
	if (ret < 0)
		goto err_kfree;

	ret = max8998_update_reg(i2c, MAX8998_REG_LBCNFG1, 0x7, 0x37); //3.57V
	if (ret < 0)
		goto err_kfree;

	ret = max8998_update_reg(i2c, MAX8998_REG_LBCNFG2, 0x5, 0x37); //3.4V
	if (ret < 0)
		goto err_kfree;

	max8998_lowbat_config(chg, 0);

	wake_lock_init(&chg->vbus_wake_lock, WAKE_LOCK_SUSPEND, "vbus_present");
	wake_lock_init(&chg->work_wake_lock, WAKE_LOCK_SUSPEND, "max8998-charger");
	wake_lock_init(&chg->lowbat_wake_lock, WAKE_LOCK_SUSPEND, "max8998-lowbat");

	INIT_WORK(&chg->bat_work, s3c_bat_work);
	setup_timer(&chg->bat_work_timer, s3c_bat_work_timer_func, (unsigned long)chg);

	chg->monitor_wqueue = create_freezeable_workqueue(dev_name(&pdev->dev));
	if (!chg->monitor_wqueue) {
		pr_err("%s : Failed to create freezeable workqueue\n", __func__);
		ret = -ENOMEM;
		goto err_wake_lock;
	}

	check_lpm_charging_mode(chg);

	/* init power supplier framework */
	ret = power_supply_register(&pdev->dev, &chg->psy_bat);
	if (ret) {
		pr_err("%s : Failed to register power supply psy_bat\n", __func__);
		goto err_wqueue;
	}

	ret = power_supply_register(&pdev->dev, &chg->psy_usb);
	if (ret) {
		pr_err("%s : Failed to register power supply psy_usb\n", __func__);
		goto err_supply_unreg_bat;
	}

	ret = power_supply_register(&pdev->dev, &chg->psy_ac);
	if (ret) {
		pr_err("%s : Failed to register power supply psy_ac\n", __func__);
		goto err_supply_unreg_usb;
	}

	ret = request_threaded_irq(iodev->i2c->irq, NULL, max8998_int_work_func,
				   IRQF_TRIGGER_FALLING, "max8998-charger", chg);
	if (ret) {
		pr_err("%s : Failed to request pmic irq\n", __func__);
		goto err_supply_unreg_ac;
	}

	ret = enable_irq_wake(iodev->i2c->irq);
	if (ret) {
		pr_err("%s : Failed to enable pmic irq wake\n", __func__);
		goto err_irq;
	}

	ret = s3c_bat_create_attrs(chg->psy_bat.dev);
	if (ret) {
		pr_err("%s : Failed to create_attrs\n", __func__);
		goto err_irq;
	}

	chg->callbacks.set_cable = max8998_set_cable;
	chg->callbacks.set_esafe = max8998_set_esafe;
	chg->callbacks.get_vdcin = max8998_get_vdcin;
	if (chg->pdata->register_callbacks)
		chg->pdata->register_callbacks(&chg->callbacks);

	wake_lock(&chg->work_wake_lock);
	queue_work(chg->monitor_wqueue, &chg->bat_work);

	return 0;

err_irq:
	free_irq(iodev->i2c->irq, NULL);
err_supply_unreg_ac:
	power_supply_unregister(&chg->psy_ac);
err_supply_unreg_usb:
	power_supply_unregister(&chg->psy_usb);
err_supply_unreg_bat:
	power_supply_unregister(&chg->psy_bat);
err_wqueue:
	destroy_workqueue(chg->monitor_wqueue);
	cancel_work_sync(&chg->bat_work);
err_wake_lock:
	wake_lock_destroy(&chg->work_wake_lock);
	wake_lock_destroy(&chg->vbus_wake_lock);
	wake_lock_destroy(&chg->lowbat_wake_lock);
err_kfree:
	mutex_destroy(&chg->mutex);
err_bat_table:
	kfree(chg);
	return ret;
}
예제 #4
0
static int aml1216_battery_probe(struct platform_device *pdev)
{
	struct  aml1216_supply    *supply;
	struct  aml_charger	  *c;
	struct  battery_curve     *curve;
	struct  power_supply_info *b;
	int	 ret;
	uint32_t i;

	AML1216_DBG("call %s in", __func__);

	g_aml1216_init = pdev->dev.platform_data;
	if (g_aml1216_init == NULL) {
		AML1216_ERR("%s, NO platform data\n", __func__);
		return -EINVAL;
	}
	aml1216_power_key = input_allocate_device();
	if (!aml1216_power_key) {
		kfree(aml1216_power_key);
		return -ENODEV;
	}

	aml1216_power_key->name	      = pdev->name;
	aml1216_power_key->phys	      = "m1kbd/input2";
	aml1216_power_key->id.bustype = BUS_HOST;
	aml1216_power_key->id.vendor  = 0x0001;
	aml1216_power_key->id.product = 0x0001;
	aml1216_power_key->id.version = 0x0100;
	aml1216_power_key->open	      = NULL;
	aml1216_power_key->close      = NULL;
	aml1216_power_key->dev.parent = &pdev->dev;

	set_bit(EV_KEY, aml1216_power_key->evbit);
	set_bit(EV_REL, aml1216_power_key->evbit);
	set_bit(KEY_POWER, aml1216_power_key->keybit);

	ret = input_register_device(aml1216_power_key);

	aml1216_battery = g_aml1216_init->board_battery;

	/*
	 * initialize parameters for supply
	 */
	supply = kzalloc(sizeof(*supply), GFP_KERNEL);
	if (supply == NULL)
		return -ENOMEM;
	supply->battery_info = kzalloc(sizeof(struct power_supply_info),
				       GFP_KERNEL);
	if (supply->battery_info == NULL) {
		kfree(supply);
		return -ENOMEM;
	}
	supply->master = pdev->dev.parent;

	g_aml1216_supply = supply;
	c     = &supply->aml_charger;
	curve = aml1216_battery->pmu_bat_curve;
	if (aml1216_battery) {
		for (i = 1; i < 16; i++) {
			if (!c->ocv_empty && curve[i].discharge_percent > 0)
				c->ocv_empty = curve[i-1].ocv;
			if (!c->ocv_full && curve[i].discharge_percent == 100)
				c->ocv_full = curve[i].ocv;
		}

		supply->irq	      = aml1216_battery->pmu_irq_id;
		b = supply->battery_info;
		b->technology	      = aml1216_battery->pmu_battery_technology;
		b->voltage_max_design = aml1216_battery->pmu_init_chgvol;
		b->energy_full_design = aml1216_battery->pmu_battery_cap;
		b->voltage_min_design = c->ocv_empty * 1000;
		b->use_for_apm	      = 1;
		b->name		      = aml1216_battery->pmu_battery_name;
	} else
		AML1216_ERR(" NO BATTERY_PARAMETERS FOUND\n");

	c->soft_limit_to99 = g_aml1216_init->soft_limit_to99;
	c->coulomb_type    = COULOMB_BOTH;
	supply->charge_timeout_retry = g_aml1216_init->charge_timeout_retry;
	aml1216_update_state(c);
#ifdef CONFIG_AMLOGIC_USB
	INIT_WORK(&aml1216_otg_work, aml1216_otg_work_fun);
	if (aml1216_charger_job.flag) {
		aml1216_usb_charger(NULL, aml1216_charger_job.value, NULL);
		aml1216_charger_job.flag = 0;
	}
	if (aml1216_otg_job.flag) {
		aml1216_otg_change(NULL, aml1216_otg_job.value, NULL);
		aml1216_otg_job.flag = 0;
	}
#endif

	if (supply->irq) {
		INIT_WORK(&supply->irq_work, aml1216_irq_work_func);
		ret = request_irq(supply->irq,
				  aml1216_irq_handler,
				  IRQF_DISABLED | IRQF_SHARED,
				  AML1216_IRQ_NAME,
				  supply);
		if (ret) {
			AML1216_DBG("request irq failed, ret:%d, irq:%d\n",
				    ret, supply->irq);
		}
	}

	ret = aml1216_first_init(supply);
	if (ret)
		goto err_charger_init;

	aml1216_battery_setup_psy(supply);
	ret = power_supply_register(&pdev->dev, &supply->batt);
	if (ret)
		goto err_ps_register;

	ret = power_supply_register(&pdev->dev, &supply->ac);
	if (ret) {
		power_supply_unregister(&supply->batt);
		goto err_ps_register;
	}
	ret = power_supply_register(&pdev->dev, &supply->usb);
	if (ret) {
		power_supply_unregister(&supply->ac);
		power_supply_unregister(&supply->batt);
		goto err_ps_register;
	}

	ret = aml1216_supply_create_attrs(&supply->batt);
	if (ret)
		return ret;

	platform_set_drvdata(pdev, supply);

	supply->interval = msecs_to_jiffies(AML1216_WORK_CYCLE);
	INIT_DELAYED_WORK(&supply->work, aml1216_charging_monitor);
	schedule_delayed_work(&supply->work, supply->interval);

#ifdef CONFIG_HAS_EARLYSUSPEND
	aml1216_early_suspend.suspend = aml1216_earlysuspend;
	aml1216_early_suspend.resume  = aml1216_lateresume;
	aml1216_early_suspend.level   = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 2;
	aml1216_early_suspend.param   = supply;
	register_early_suspend(&aml1216_early_suspend);
	wake_lock_init(&aml1216_lock, WAKE_LOCK_SUSPEND, "aml1216");
#endif
	if (aml1216_battery)
		power_supply_changed(&supply->batt); /* update battery status */

	aml1216_dump_all_register(NULL);
	AML1216_DBG("call %s exit, ret:%d", __func__, ret);
	return ret;

err_ps_register:
	free_irq(supply->irq, supply);
	cancel_delayed_work_sync(&supply->work);

err_charger_init:
	kfree(supply->battery_info);
	kfree(supply);
	input_unregister_device(aml1216_power_key);
	kfree(aml1216_power_key);
	AML1216_DBG("call %s exit, ret:%d", __func__, ret);
	return ret;
}
예제 #5
0
static int ulpmc_battery_probe(struct i2c_client *client,
				 const struct i2c_device_id *id)
{
	struct ulpmc_chip_info *chip;
	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
	int ret = 0;

	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) {
		dev_err(&client->dev,
				"SM bus doesn't support BYTE transactions\n");
		return -EIO;
	}
	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
		dev_err(&client->dev,
				"SM bus doesn't support WORD transactions\n");
		return -EIO;
	}

	/* check if the device is accessible */
	ret = ulpmc_read_reg16(client, ULPMC_FG_REG_CNTL);
	if (ret < 0) {
		dev_err(&client->dev,
			"I2C read error:%s error:%d\n", __func__, ret);
		return -EIO;
	} else {
		dev_err(&client->dev, "FG control reg:%x\n", ret);
	}

	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
	if (!chip) {
		dev_err(&client->dev, "failed to allocate memory\n");
		return -ENOMEM;
	}

	chip->client = client;
	chip->pdata = client->dev.platform_data;
	i2c_set_clientdata(client, chip);


	INIT_DELAYED_WORK(&chip->work, ulpmc_battery_monitor);
	mutex_init(&chip->lock);

	chip->bat.name = "byt-battery";
	chip->bat.type = POWER_SUPPLY_TYPE_BATTERY;
	chip->bat.properties = ulpmc_battery_props;
	chip->bat.num_properties = ARRAY_SIZE(ulpmc_battery_props);
	chip->bat.get_property = ulpmc_get_battery_property;
	ret = power_supply_register(&client->dev, &chip->bat);
	if (ret) {
		dev_err(&client->dev, "failed to register battery: %d\n", ret);
		goto probe_failed_1;
	}

	chip->chrg.name = "byt-charger";
	chip->chrg.type = POWER_SUPPLY_TYPE_MAINS;
	chip->chrg.properties = ulpmc_charger_properties;
	chip->chrg.num_properties = ARRAY_SIZE(ulpmc_charger_properties);
	chip->chrg.get_property = ulpmc_get_charger_property;
	ret = power_supply_register(&client->dev, &chip->chrg);
	if (ret) {
		dev_err(&client->dev, "failed to register charger: %d\n", ret);
		goto probe_failed_2;
	}

	/* get extcon device */
	chip->edev = extcon_get_extcon_dev(chip->pdata->extcon_devname);
	if (!chip->edev) {
		dev_err(&client->dev, "failed to get extcon device\n");
	} else {
		chip->nb.notifier_call = &ulpmc_extcon_callback;
		ret = extcon_register_notifier(chip->edev, &chip->nb);
		if (ret)
			dev_err(&client->dev,
				"failed to register extcon notifier:%d\n", ret);
	}

	/* get irq and register */
	ulpmc_init_irq(chip);
	/* schedule status monitoring worker */
	schedule_delayed_work(&chip->work, STATUS_MON_JIFFIES);
	return 0;

probe_failed_2:
	power_supply_unregister(&chip->bat);
probe_failed_1:
	kfree(chip);
	return ret;
}
static int __devinit max17047_fuelgauge_i2c_probe(struct i2c_client *client,
						  const struct i2c_device_id *id)
{
	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
	struct max17047_fuelgauge_data *fg_data;
	struct max17047_platform_data *pdata = client->dev.platform_data;
	int ret = -ENODEV;
	int rawsoc, firstsoc;
	pr_info("%s: fuelgauge init\n", __func__);

	if (!pdata) {
		pr_err("%s: no platform data\n", __func__);
		return -ENODEV;
	}

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

	fg_data = kzalloc(sizeof(struct max17047_fuelgauge_data), GFP_KERNEL);
	if (!fg_data)
		return -ENOMEM;

	fg_data->client = client;
	fg_data->pdata = pdata;

	i2c_set_clientdata(client, fg_data);

	mutex_init(&fg_data->irq_lock);

	wake_lock_init(&fg_data->update_wake_lock, WAKE_LOCK_SUSPEND,
							       "fuel-update");

#ifdef USE_TRIM_ERROR_DETECTION
	/* trim error detect */
	fg_data->trim_err = max17047_detect_trim_error(fg_data);
#endif

	/* Initialize full_soc, set this before fisrt SOC reading */
	fg_data->full_soc = FULL_SOC_DEFAULT;
	/* first full_soc update */
	rawsoc = max17047_get_rawsoc(fg_data->client);
	if (rawsoc > FULL_SOC_DEFAULT)
		max17047_adjust_fullsoc(client);
	firstsoc = max17047_get_soc(client);
	pr_info("%s: rsoc=%d, fsoc=%d, soc=%d\n", __func__,
			rawsoc, fg_data->full_soc, firstsoc);

	if (fg_data->pdata->psy_name)
		fg_data->fuelgauge.name =
			fg_data->pdata->psy_name;
	else
		fg_data->fuelgauge.name = "max17047-fuelgauge";

#if defined(CONFIG_MACH_GC1)
	fg_data->prev_status = POWER_SUPPLY_STATUS_DISCHARGING;
#endif
	fg_data->fuelgauge.type = POWER_SUPPLY_TYPE_UNKNOWN;
	fg_data->fuelgauge.properties = max17047_fuelgauge_props;
	fg_data->fuelgauge.num_properties =
				ARRAY_SIZE(max17047_fuelgauge_props);
	fg_data->fuelgauge.get_property = max17047_get_property;
	fg_data->fuelgauge.set_property = max17047_set_property;

	ret = power_supply_register(&client->dev, &fg_data->fuelgauge);
	if (ret) {
		pr_err("%s: failed power supply register\n", __func__);
		goto err_psy_reg_fg;
	}

	/* Initialize fuelgauge registers */
	max17047_reg_init(fg_data);

	/* Initialize fuelgauge alert */
	max17047_alert_init(fg_data);

	INIT_DELAYED_WORK_DEFERRABLE(&fg_data->update_work,
					max17047_update_work);

	/* Request IRQ */
	fg_data->irq = gpio_to_irq(fg_data->pdata->irq_gpio);
	ret = gpio_request(fg_data->pdata->irq_gpio, "fuelgauge-irq");
	if (ret) {
		pr_err("%s: failed requesting gpio %d\n", __func__,
				fg_data->pdata->irq_gpio);
		goto err_irq;
	}
	gpio_direction_input(fg_data->pdata->irq_gpio);
	gpio_free(fg_data->pdata->irq_gpio);

	ret = request_threaded_irq(fg_data->irq, NULL,
				max17047_fuelgauge_isr, IRQF_TRIGGER_FALLING,
				"max17047-alert", fg_data);
	if (ret < 0) {
		pr_err("%s: fail to request max17047 irq: %d: %d\n",
				__func__, fg_data->irq, ret);
		goto err_irq;
	}

	ret = enable_irq_wake(fg_data->irq);
	if (ret < 0) {
		pr_err("%s: failed enable irq wake %d\n", __func__,
						fg_data->irq);
		goto err_enable_irq;
	}

#ifdef DEBUG_FUELGAUGE_POLLING
	INIT_DELAYED_WORK_DEFERRABLE(&fg_data->polling_work,
					max17047_polling_work);
	schedule_delayed_work(&fg_data->polling_work, 0);
#else
	max17047_test_read(fg_data);
#endif

	pr_info("%s: probe complete\n", __func__);

#if defined(CONFIG_TARGET_LOCALE_KOR)
#ifdef CONFIG_DEBUG_FS
	fg_data->fg_debugfs_dir =
		debugfs_create_dir("fg_debug", NULL);
	if (fg_data->fg_debugfs_dir) {
		if (!debugfs_create_file("max17047_regs", 0644,
			fg_data->fg_debugfs_dir,
			fg_data, &max17047_debugfs_fops))
			pr_err("%s : debugfs_create_file, error\n", __func__);
		if (!debugfs_create_file("default_data", 0644,
			fg_data->fg_debugfs_dir,
			fg_data, &max17047_debugfs_fops2))
			pr_err("%s : debugfs_create_file2, error\n", __func__);
	} else
		pr_err("%s : debugfs_create_dir, error\n", __func__);
#endif
#endif

	return 0;

err_enable_irq:
	free_irq(fg_data->irq, fg_data);
err_irq:
	power_supply_unregister(&fg_data->fuelgauge);
err_psy_reg_fg:
	wake_lock_destroy(&fg_data->update_wake_lock);
	mutex_destroy(&fg_data->irq_lock);
	kfree(fg_data);
	return ret;
}
예제 #7
0
static int __devinit sec_fuelgauge_probe(struct i2c_client *client,
						const struct i2c_device_id *id)
{
	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
	struct sec_fuelgauge_info *fuelgauge;
	int ret = 0;
	union power_supply_propval raw_soc_val;

	dev_dbg(&client->dev,
		"%s: SEC Fuelgauge Driver Loading\n", __func__);

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

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

	mutex_init(&fuelgauge->fg_lock);

	fuelgauge->client = client;
	fuelgauge->pdata = client->dev.platform_data;

	i2c_set_clientdata(client, fuelgauge);

	fuelgauge->psy_fg.name		= "sec-fuelgauge";
	fuelgauge->psy_fg.type		= POWER_SUPPLY_TYPE_UNKNOWN;
	fuelgauge->psy_fg.get_property	= sec_fg_get_property;
	fuelgauge->psy_fg.set_property	= sec_fg_set_property;
	fuelgauge->psy_fg.properties	= sec_fuelgauge_props;
	fuelgauge->psy_fg.num_properties =
		ARRAY_SIZE(sec_fuelgauge_props);
	fuelgauge->capacity_max = fuelgauge->pdata->capacity_max;
	raw_soc_val.intval = SEC_FUELGAUGE_CAPACITY_TYPE_RAW;
	sec_hal_fg_get_property(fuelgauge->client,
			POWER_SUPPLY_PROP_CAPACITY, &raw_soc_val);
	raw_soc_val.intval /= 10;
	fuelgauge->is_reset = false;
	if(raw_soc_val.intval > fuelgauge->pdata->capacity_max)
		sec_fg_calculate_dynamic_scale(fuelgauge);

	if (!fuelgauge->pdata->fg_gpio_init()) {
		dev_err(&client->dev,
			"%s: Failed to Initialize GPIO\n", __func__);
		goto err_free;
	}

	if (!sec_hal_fg_init(fuelgauge->client)) {
		dev_err(&client->dev,
			"%s: Failed to Initialize Fuelgauge\n", __func__);
		goto err_free;
	}

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

	if (fuelgauge->pdata->fg_irq) {
		INIT_DELAYED_WORK_DEFERRABLE(
			&fuelgauge->isr_work, sec_fg_isr_work);

		ret = request_threaded_irq(fuelgauge->pdata->fg_irq,
				NULL, sec_fg_irq_thread,
				fuelgauge->pdata->fg_irq_attr,
				"fuelgauge-irq", fuelgauge);
		if (ret) {
			dev_err(&client->dev,
				"%s: Failed to Reqeust IRQ\n", __func__);
			goto err_supply_unreg;
		}

		ret = enable_irq_wake(fuelgauge->pdata->fg_irq);
		if (ret < 0)
			dev_err(&client->dev,
				"%s: Failed to Enable Wakeup Source(%d)\n",
				__func__, ret);
	}

	fuelgauge->is_fuel_alerted = false;
	if (fuelgauge->pdata->fuel_alert_soc >= 0) {
		if (sec_hal_fg_fuelalert_init(fuelgauge->client,
			fuelgauge->pdata->fuel_alert_soc))
			wake_lock_init(&fuelgauge->fuel_alert_wake_lock,
				WAKE_LOCK_SUSPEND, "fuel_alerted");
		else {
			dev_err(&client->dev,
				"%s: Failed to Initialize Fuel-alert\n",
				__func__);
			goto err_irq;
		}
	}

	fuelgauge->initial_update_of_soc = true;

	ret = sec_fg_create_attrs(fuelgauge->psy_fg.dev);
	if (ret) {
		dev_err(&client->dev,
			"%s : Failed to create_attrs\n", __func__);
		goto err_irq;
	}

	dev_dbg(&client->dev,
		"%s: SEC Fuelgauge Driver Loaded\n", __func__);
	return 0;

err_irq:
	if (fuelgauge->pdata->fg_irq)
		free_irq(fuelgauge->pdata->fg_irq, fuelgauge);
	wake_lock_destroy(&fuelgauge->fuel_alert_wake_lock);
err_supply_unreg:
	power_supply_unregister(&fuelgauge->psy_fg);
err_free:
	mutex_destroy(&fuelgauge->fg_lock);
	kfree(fuelgauge);

	return ret;
}
/*
 * imx6_usb_remove_charger - remove a USB charger
 * @charger: the charger to be removed
 *
 * Unregister the chargers power supply.
 */
void imx6_usb_remove_charger(struct usb_charger *charger)
{
	power_supply_unregister(&charger->psy);
}
예제 #9
0
static int __init twl4030_bci_probe(struct platform_device *pdev)
{
	struct twl4030_bci *bci;
	struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data;
	int ret;
	u32 reg;

	bci = kzalloc(sizeof(*bci), GFP_KERNEL);
	if (bci == NULL)
		return -ENOMEM;

	bci->dev = &pdev->dev;
	bci->irq_chg = platform_get_irq(pdev, 0);
	bci->irq_bci = platform_get_irq(pdev, 1);

	platform_set_drvdata(pdev, bci);

	bci->ac.name = "twl4030_ac";
	bci->ac.type = POWER_SUPPLY_TYPE_MAINS;
	bci->ac.properties = twl4030_charger_props;
	bci->ac.num_properties = ARRAY_SIZE(twl4030_charger_props);
	bci->ac.get_property = twl4030_bci_get_property;

	ret = power_supply_register(&pdev->dev, &bci->ac);
	if (ret) {
		dev_err(&pdev->dev, "failed to register ac: %d\n", ret);
		goto fail_register_ac;
	}

	bci->usb.name = "twl4030_usb";
	bci->usb.type = POWER_SUPPLY_TYPE_USB;
	bci->usb.properties = twl4030_charger_props;
	bci->usb.num_properties = ARRAY_SIZE(twl4030_charger_props);
	bci->usb.get_property = twl4030_bci_get_property;

	bci->usb_reg = regulator_get(bci->dev, "bci3v1");

	ret = power_supply_register(&pdev->dev, &bci->usb);
	if (ret) {
		dev_err(&pdev->dev, "failed to register usb: %d\n", ret);
		goto fail_register_usb;
	}

	ret = request_threaded_irq(bci->irq_chg, NULL,
			twl4030_charger_interrupt, IRQF_ONESHOT, pdev->name,
			bci);
	if (ret < 0) {
		dev_err(&pdev->dev, "could not request irq %d, status %d\n",
			bci->irq_chg, ret);
		goto fail_chg_irq;
	}

	ret = request_threaded_irq(bci->irq_bci, NULL,
			twl4030_bci_interrupt, IRQF_ONESHOT, pdev->name, bci);
	if (ret < 0) {
		dev_err(&pdev->dev, "could not request irq %d, status %d\n",
			bci->irq_bci, ret);
		goto fail_bci_irq;
	}

	INIT_WORK(&bci->work, twl4030_bci_usb_work);

	bci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
	if (!IS_ERR_OR_NULL(bci->transceiver)) {
		bci->usb_nb.notifier_call = twl4030_bci_usb_ncb;
		usb_register_notifier(bci->transceiver, &bci->usb_nb);
	}

	/* Enable interrupts now. */
	reg = ~(u32)(TWL4030_ICHGLOW | TWL4030_ICHGEOC | TWL4030_TBATOR2 |
		TWL4030_TBATOR1 | TWL4030_BATSTS);
	ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
			       TWL4030_INTERRUPTS_BCIIMR1A);
	if (ret < 0) {
		dev_err(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
		goto fail_unmask_interrupts;
	}

	reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
	ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
			       TWL4030_INTERRUPTS_BCIIMR2A);
	if (ret < 0)
		dev_warn(&pdev->dev, "failed to unmask interrupts: %d\n", ret);

	twl4030_charger_enable_ac(true);
	twl4030_charger_enable_usb(bci, true);
	twl4030_charger_enable_backup(pdata->bb_uvolt,
				      pdata->bb_uamp);

	return 0;

fail_unmask_interrupts:
	if (!IS_ERR_OR_NULL(bci->transceiver)) {
		usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
		usb_put_phy(bci->transceiver);
	}
	free_irq(bci->irq_bci, bci);
fail_bci_irq:
	free_irq(bci->irq_chg, bci);
fail_chg_irq:
	power_supply_unregister(&bci->usb);
fail_register_usb:
	power_supply_unregister(&bci->ac);
fail_register_ac:
	platform_set_drvdata(pdev, NULL);
	kfree(bci);

	return ret;
}
예제 #10
0
static int __init twl6030_bci_battery_probe(struct platform_device *pdev)
{
	struct twl6030_bci_platform_data *pdata = pdev->dev.platform_data;
	struct twl6030_bci_device_info *di;
	int irq;
	int ret;
	u8 rd_reg = 0, controller_stat = 0;

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

	if (!pdata) {
		dev_dbg(&pdev->dev, "platform_data not available\n");
		ret = -EINVAL;
		goto err_pdata;
	}

	di->dev = &pdev->dev;
	di->bat.name = "twl6030_bci_battery";
	di->bat.supplied_to = twl6030_bci_supplied_to;
	di->bat.num_supplicants = ARRAY_SIZE(twl6030_bci_supplied_to);
	di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
	di->bat.properties = twl6030_bci_battery_props;
	di->bat.num_properties = ARRAY_SIZE(twl6030_bci_battery_props);
	di->bat.get_property = twl6030_bci_battery_get_property;
	di->bat.external_power_changed =
			twl6030_bci_battery_external_power_changed;

	di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;

	di->bk_bat.name = "twl6030_bci_bk_battery";
	di->bk_bat.type = POWER_SUPPLY_TYPE_BATTERY;
	di->bk_bat.properties = twl6030_bk_bci_battery_props;
	di->bk_bat.num_properties = ARRAY_SIZE(twl6030_bk_bci_battery_props);
	di->bk_bat.get_property = twl6030_bk_bci_battery_get_property;
	di->bk_bat.external_power_changed = NULL;

	/*
	 * Android expects a battery type POWER_SUPPLY_TYPE_USB
	 * as a usb charger battery. This battery
	 * and its "online" property are used to determine if the
	 * usb cable is plugged in or not.
	 */
	di->usb_bat.name = "twl6030_bci_usb_battery";
	di->usb_bat.supplied_to = twl6030_bci_supplied_to;
	di->usb_bat.type = POWER_SUPPLY_TYPE_USB;
	di->usb_bat.properties = twl6030_usb_battery_props;
	di->usb_bat.num_properties = ARRAY_SIZE(twl6030_usb_battery_props);
	di->usb_bat.get_property = twl6030_usb_battery_get_property;
	di->usb_bat.external_power_changed = NULL;

	di->vac_priority = 1;
	platform_set_drvdata(pdev, di);

	/* settings for temperature sensing */
	ret = twl6030battery_temp_setup();
	if (ret)
		goto temp_setup_fail;

	/* request charger fault interruption */
	irq = platform_get_irq(pdev, 1);
	ret = request_irq(irq, twl6030charger_fault_interrupt,
		0, "twl_bci_fault", di);
	if (ret) {
		dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
			irq, ret);
		goto batt_irq_fail;
	}

	/* request charger ctrl interruption */
	irq = platform_get_irq(pdev, 0);
	ret = request_irq(irq, twl6030charger_ctrl_interrupt,
		0, "twl_bci_ctrl", di);

	if (ret) {
		dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
			irq, ret);
		goto chg_irq_fail;
	}

	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
						REG_INT_MSK_LINE_C);
	twl6030_interrupt_unmask(TWL6030_CHARGER_CTRL_INT_MASK,
						REG_INT_MSK_STS_C);
	twl6030_interrupt_unmask(TWL6030_CHARGER_FAULT_INT_MASK,
						REG_INT_MSK_LINE_C);
	twl6030_interrupt_unmask(TWL6030_CHARGER_FAULT_INT_MASK,
						REG_INT_MSK_STS_C);

	ret = power_supply_register(&pdev->dev, &di->bat);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to register main battery\n");
		goto batt_failed;
	}

	INIT_DELAYED_WORK_DEFERRABLE(&di->twl6030_bci_monitor_work,
				twl6030_bci_battery_work);
	schedule_delayed_work(&di->twl6030_bci_monitor_work, 0);

	ret = power_supply_register(&pdev->dev, &di->bk_bat);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to register backup battery\n");
		goto bk_batt_failed;
	}

	ret = power_supply_register(&pdev->dev, &di->usb_bat);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to register usb source\n");
		goto usb_batt_failed;
	}

	INIT_DELAYED_WORK_DEFERRABLE(&di->twl6030_bk_bci_monitor_work,
				twl6030_bk_bci_battery_work);
	schedule_delayed_work(&di->twl6030_bk_bci_monitor_work, 500);

	twl_i2c_read_u8(TWL6030_MODULE_ID0, &rd_reg, REG_MISC1);
	rd_reg = rd_reg | VAC_MEAS | VBAT_MEAS | BB_MEAS;
	twl_i2c_write_u8(TWL6030_MODULE_ID0, rd_reg, REG_MISC1);

	twl_i2c_read_u8(TWL6030_MODULE_ID1, &rd_reg, REG_TOGGLE1);
	rd_reg = rd_reg | ENABLE_FUELGUAGE;
	twl_i2c_write_u8(TWL6030_MODULE_ID1, rd_reg, REG_TOGGLE1);

	twl_i2c_read_u8(TWL_MODULE_MADC, &rd_reg, TWL6030_GPADC_CTRL);
	rd_reg = rd_reg | ENABLE_ISOURCE;
	twl_i2c_write_u8(TWL_MODULE_MADC, rd_reg, TWL6030_GPADC_CTRL);

	twl_i2c_read_u8(TWL_MODULE_USB, &rd_reg, REG_USB_VBUS_CTRL_SET);
	rd_reg = rd_reg | VBUS_MEAS;
	twl_i2c_write_u8(TWL_MODULE_USB, rd_reg, REG_USB_VBUS_CTRL_SET);

	twl_i2c_read_u8(TWL_MODULE_USB, &rd_reg, REG_USB_ID_CTRL_SET);
	rd_reg = rd_reg | ID_MEAS;
	twl_i2c_write_u8(TWL_MODULE_USB, rd_reg, REG_USB_ID_CTRL_SET);

	/* initialize for USB charging */
	twl_i2c_write_u8(TWL6030_MODULE_CHARGER, MBAT_TEMP,
						CONTROLLER_INT_MASK);
	twl_i2c_write_u8(TWL6030_MODULE_CHARGER, MASK_MCHARGERUSB_THMREG,
						CHARGERUSB_INT_MASK);
	twl_i2c_write_u8(TWL6030_MODULE_CHARGER, CHARGERUSB_VOREG_4P2,
						CHARGERUSB_VOREG);
	twl_i2c_write_u8(TWL6030_MODULE_CHARGER, CHARGERUSB_VICHRG_1500,
						CHARGERUSB_VICHRG);
	twl_i2c_write_u8(TWL6030_MODULE_CHARGER, CHARGERUSB_CTRL2_VITERM_100,
						CHARGERUSB_CTRL2);
	twl_i2c_write_u8(TWL6030_MODULE_CHARGER, CHARGERUSB_CIN_LIMIT_NONE,
						CHARGERUSB_CINLIMIT);
	twl_i2c_write_u8(TWL6030_MODULE_CHARGER, CHARGERUSB_CTRLLIMIT2_1500,
					CHARGERUSB_CTRLLIMIT2);

	twl_i2c_write_u8(TWL6030_MODULE_BQ, 0xa0, REG_SAFETY_LIMIT);

	twl_i2c_read_u8(TWL6030_MODULE_CHARGER, &controller_stat,
		CONTROLLER_STAT1);

	if (controller_stat & VBUS_DET)
		twl6030_start_usb_charger();

	if (controller_stat & VAC_DET)
		twl6030_start_ac_charger();

	return 0;

usb_batt_failed:
	power_supply_unregister(&di->bk_bat);
bk_batt_failed:
	power_supply_unregister(&di->bat);
batt_failed:
	free_irq(irq, di);
chg_irq_fail:
	irq = platform_get_irq(pdev, 1);
	free_irq(irq, NULL);
err_pdata:
batt_irq_fail:
temp_setup_fail:
	kfree(di);

	return ret;
}
예제 #11
0
static __devinit int max8903_probe(struct platform_device *pdev)
{
	struct max8903_platform_data *pdata = dev_get_platdata(&pdev->dev);
	struct max8903_info *info;
	int ret;

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

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

	platform_set_drvdata(pdev, info);

	info->dev = &pdev->dev;
	info->pdata = pdata;

	info->psy_bat.name = "max8903-charger",
		info->psy_bat.type = POWER_SUPPLY_TYPE_BATTERY,
		info->psy_bat.properties = max8903_battery_props,
		info->psy_bat.num_properties = ARRAY_SIZE(max8903_battery_props),
		info->psy_bat.get_property = max8903_get_property,
		info->psy_bat.set_property = max8903_set_property,
		ret = power_supply_register(&pdev->dev, &info->psy_bat);
	if (ret) {
		dev_err(info->dev, "Failed to register psy_bat\n");
		goto err_kfree;
	}

	if (pdata->cfg_gpio) {
		ret = pdata->cfg_gpio();
		if (ret) {
			dev_err(info->dev, "failed to configure GPIO\n");
			goto err_kfree;
		}
	}

	if (gpio_is_valid(pdata->gpio_curr_adj)) {
		if (!pdata->gpio_curr_adj) {
			dev_err(info->dev, "gpio_curr_adj defined as 0\n");
			WARN_ON(!pdata->gpio_curr_adj);
			ret = -EIO;
			goto err_kfree;
		}
		gpio_request(pdata->gpio_curr_adj, "MAX8903 gpio_curr_adj");
	}

	if (gpio_is_valid(pdata->gpio_ta_en)) {
		if (!pdata->gpio_ta_en) {
			dev_err(info->dev, "gpio_ta_en defined as 0\n");
			WARN_ON(!pdata->gpio_ta_en);
			ret = -EIO;
			goto err_kfree;
		}
		gpio_request(pdata->gpio_ta_en, "MAX8903 gpio_ta_en");
	}

	if (gpio_is_valid(pdata->gpio_ta_nconnected)) {
		if (!pdata->gpio_ta_nconnected) {
			dev_err(info->dev, "gpio_ta_nconnected defined as 0\n");
			WARN_ON(!pdata->gpio_ta_nconnected);
			ret = -EIO;
			goto err_kfree;
		}
		gpio_request(pdata->gpio_ta_nconnected,
			"MAX8903 TA_nCONNECTED");
	}

	if (gpio_is_valid(pdata->gpio_ta_nchg)) {
		if (!pdata->gpio_ta_nchg) {
			dev_err(info->dev, "gpio_ta_nchg defined as 0\n");
			WARN_ON(!pdata->gpio_ta_nchg);
			ret = -EIO;
			goto err_kfree;
		}
		gpio_request(pdata->gpio_ta_nchg,
			"MAX8903 gpio_ta_nchg");
	}
#if 0
	info->irq_chg_ing = gpio_to_irq(pdata->gpio_chg_ing);

	ret = request_threaded_irq(info->irq_chg_ing, NULL,
				max8922_chg_ing_irq,
				IRQF_TRIGGER_RISING | IRQF_ONESHOT,
				"chg_ing", info);
	if (ret)
		dev_err(&pdev->dev, "%s: fail to request chg_ing IRQ:"
			" %d: %d\n", __func__, info->irq_chg_ing, ret);
#endif

	return 0;
err_kfree:
	power_supply_unregister(&info->psy_bat);
	platform_set_drvdata(pdev, NULL);
	kfree(info);
	return ret;
}
예제 #12
0
static int __devinit tosa_bat_probe(struct platform_device *dev)
{
	int ret;
	int i;

	if (!machine_is_tosa())
		return -ENODEV;

	for (i = 0; i < ARRAY_SIZE(gpios); i++) {
		ret = gpio_request(gpios[i].gpio, gpios[i].name);
		if (ret) {
			i--;
			goto err_gpio;
		}

		if (gpios[i].output)
			ret = gpio_direction_output(gpios[i].gpio,
					gpios[i].value);
		else
			ret = gpio_direction_input(gpios[i].gpio);

		if (ret)
			goto err_gpio;
	}

	mutex_init(&tosa_bat_main.work_lock);
	mutex_init(&tosa_bat_jacket.work_lock);

	INIT_WORK(&bat_work, tosa_bat_work);

	ret = power_supply_register(&dev->dev, &tosa_bat_main.psy);
	if (ret)
		goto err_psy_reg_main;
	ret = power_supply_register(&dev->dev, &tosa_bat_jacket.psy);
	if (ret)
		goto err_psy_reg_jacket;
	ret = power_supply_register(&dev->dev, &tosa_bat_bu.psy);
	if (ret)
		goto err_psy_reg_bu;

	ret = request_irq(gpio_to_irq(TOSA_GPIO_BAT0_CRG),
				tosa_bat_gpio_isr,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
				"main full", &tosa_bat_main);
	if (ret)
		goto err_req_main;

	ret = request_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG),
				tosa_bat_gpio_isr,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
				"jacket full", &tosa_bat_jacket);
	if (ret)
		goto err_req_jacket;

	ret = request_irq(gpio_to_irq(TOSA_GPIO_JACKET_DETECT),
				tosa_bat_gpio_isr,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
				"jacket detect", &tosa_bat_jacket);
	if (!ret) {
		schedule_work(&bat_work);
		return 0;
	}

	free_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG), &tosa_bat_jacket);
err_req_jacket:
	free_irq(gpio_to_irq(TOSA_GPIO_BAT0_CRG), &tosa_bat_main);
err_req_main:
	power_supply_unregister(&tosa_bat_bu.psy);
err_psy_reg_bu:
	power_supply_unregister(&tosa_bat_jacket.psy);
err_psy_reg_jacket:
	power_supply_unregister(&tosa_bat_main.psy);
err_psy_reg_main:

	/* see comment in tosa_bat_remove */
	cancel_work_sync(&bat_work);

	i--;
err_gpio:
	for (; i >= 0; i--)
		gpio_free(gpios[i].gpio);

	return ret;
}
예제 #13
0
static int pmic_battery_probe(struct platform_device *pdev)
{
	int retval = 0;
	struct mc13892_dev_info *di;
	pmic_event_callback_t bat_event_callback;
	pmic_version_t pmic_version;

	/* Only apply battery driver for MC13892 V2.0 due to ENGR108085 */
	pmic_version = pmic_get_version();
	if (pmic_version.revision < 20) {
		pr_debug("Battery driver is only applied for MC13892 V2.0\n");
		return -1;
	}
	if (machine_is_mx50_arm2()) {
		pr_debug("mc13892 charger is not used for this platform\n");
		return -1;
	}

	di = kzalloc(sizeof(*di), GFP_KERNEL);
	if (!di) {
		retval = -ENOMEM;
		goto di_alloc_failed;
	}

	platform_set_drvdata(pdev, di);

	di->charger.name	= "mc13892_charger";
	di->charger.type = POWER_SUPPLY_TYPE_MAINS;
	di->charger.properties = mc13892_charger_props;
	di->charger.num_properties = ARRAY_SIZE(mc13892_charger_props);
	di->charger.get_property = mc13892_charger_get_property;
	retval = power_supply_register(&pdev->dev, &di->charger);
	if (retval) {
		dev_err(di->dev, "failed to register charger\n");
		goto charger_failed;
	}

	INIT_DELAYED_WORK(&chg_work, chg_thread);
	chg_wq = create_singlethread_workqueue("mxc_chg");
	if (!chg_wq) {
		retval = -ESRCH;
		goto workqueue_failed;
	}

	INIT_DELAYED_WORK(&di->monitor_work, mc13892_battery_work);
	di->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev));
	if (!di->monitor_wqueue) {
		retval = -ESRCH;
		goto workqueue_failed;
	}
	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 10);

	di->dev	= &pdev->dev;
	di->bat.name	= "mc13892_bat";
	di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
	di->bat.properties = mc13892_battery_props;
	di->bat.num_properties = ARRAY_SIZE(mc13892_battery_props);
	di->bat.get_property = mc13892_battery_get_property;
	di->bat.use_for_apm = 1;

	di->battery_status = POWER_SUPPLY_STATUS_UNKNOWN;

	retval = power_supply_register(&pdev->dev, &di->bat);
	if (retval) {
		dev_err(di->dev, "failed to register battery\n");
		goto batt_failed;
	}

	bat_event_callback.func = charger_online_event_callback;
	bat_event_callback.param = (void *) di;
	pmic_event_subscribe(EVENT_CHGDETI, bat_event_callback);
	retval = sysfs_create_file(&pdev->dev.kobj, &dev_attr_enable.attr);

	if (retval) {
		printk(KERN_ERR
		       "Battery: Unable to register sysdev entry for Battery");
		goto workqueue_failed;
	}
	chg_wa_is_active = 1;
	chg_wa_timer = 0;
	disable_chg_timer = 0;

	pmic_stop_coulomb_counter();
	pmic_calibrate_coulomb_counter();
	goto success;

workqueue_failed:
	power_supply_unregister(&di->charger);
charger_failed:
	power_supply_unregister(&di->bat);
batt_failed:
	kfree(di);
di_alloc_failed:
success:
	dev_dbg(di->dev, "%s battery probed!\n", __func__);
	return retval;


	return 0;
}
예제 #14
0
static int __init twl4030_bci_battery_probe(struct platform_device *pdev)
{
	struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data;
	struct twl4030_bci_device_info *di;
	int irq;
	int ret;

	therm_tbl = pdata->battery_tmp_tbl;
	bci_charging_current = pdata->twl4030_bci_charging_current;

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

	di->dev = &pdev->dev;
	di->bat.name = "twl4030_bci_battery";
	di->bat.supplied_to = twl4030_bci_supplied_to;
	di->bat.num_supplicants = ARRAY_SIZE(twl4030_bci_supplied_to);
	di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
	di->bat.properties = twl4030_bci_battery_props;
	di->bat.num_properties = ARRAY_SIZE(twl4030_bci_battery_props);
	di->bat.get_property = twl4030_bci_battery_get_property;
	di->bat.external_power_changed =
			twl4030_bci_battery_external_power_changed;

	di->charge_status = POWER_SUPPLY_STATUS_UNKNOWN;

	di->bk_bat.name = "twl4030_bci_bk_battery";
	di->bk_bat.type = POWER_SUPPLY_TYPE_BATTERY;
	di->bk_bat.properties = twl4030_bk_bci_battery_props;
	di->bk_bat.num_properties = ARRAY_SIZE(twl4030_bk_bci_battery_props);
	di->bk_bat.get_property = twl4030_bk_bci_battery_get_property;
	di->bk_bat.external_power_changed = NULL;

	/*
	 * Android expects a battery type POWER_SUPPLY_TYPE_USB
	 * as a usb charger battery. This battery
	 * and its "online" property are used to determine if the
	 * usb cable is plugged in or not.
	 */
	di->usb_bat.name = "twl4030_bci_usb_src";
	di->usb_bat.supplied_to = twl4030_bci_supplied_to;
	di->usb_bat.type = POWER_SUPPLY_TYPE_USB;
	di->usb_bat.properties = twl4030_usb_battery_props;
	di->usb_bat.num_properties = ARRAY_SIZE(twl4030_usb_battery_props);
	di->usb_bat.get_property = twl4030_usb_battery_get_property;
	di->usb_bat.external_power_changed = NULL;

	twl4030charger_ac_en(ENABLE);
	twl4030charger_usb_en(ENABLE);
	twl4030battery_hw_level_en(ENABLE);
	twl4030battery_hw_presence_en(ENABLE);

	platform_set_drvdata(pdev, di);

	/* settings for temperature sensing */
	ret = twl4030battery_temp_setup();
	if (ret)
		goto temp_setup_fail;

	/* enabling GPCH09 for read back battery voltage */
	ret = twl4030backupbatt_voltage_setup();
	if (ret)
		goto voltage_setup_fail;

	/* REVISIT do we need to request both IRQs ?? */

	/* request BCI interruption */
	irq = platform_get_irq(pdev, 1);
	ret = request_irq(irq, twl4030battery_interrupt,
		0, pdev->name, NULL);
	if (ret) {
		dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
			irq, ret);
		goto batt_irq_fail;
	}

	/* request Power interruption */
	irq = platform_get_irq(pdev, 0);
	ret = request_irq(irq, twl4030charger_interrupt,
		0, pdev->name, di);

	if (ret) {
		dev_dbg(&pdev->dev, "could not request irq %d, status %d\n",
			irq, ret);
		goto chg_irq_fail;
	}

	ret = power_supply_register(&pdev->dev, &di->bat);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to register main battery\n");
		goto batt_failed;
	}

	INIT_DELAYED_WORK_DEFERRABLE(&di->twl4030_bci_monitor_work,
				twl4030_bci_battery_work);
	schedule_delayed_work(&di->twl4030_bci_monitor_work, 0);

	ret = power_supply_register(&pdev->dev, &di->bk_bat);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to register backup battery\n");
		goto bk_batt_failed;
	}

	INIT_DELAYED_WORK_DEFERRABLE(&di->twl4030_bk_bci_monitor_work,
				twl4030_bk_bci_battery_work);
	schedule_delayed_work(&di->twl4030_bk_bci_monitor_work, 500);

	ret = power_supply_register(&pdev->dev, &di->usb_bat);
	if (ret) {
		dev_dbg(&pdev->dev, "failed to register usb battery\n");
		goto usb_batt_failed;
	}

	return 0;

usb_batt_failed:
	power_supply_unregister(&di->bk_bat);
bk_batt_failed:
	power_supply_unregister(&di->bat);
batt_failed:
	free_irq(irq, di);
chg_irq_fail:
	irq = platform_get_irq(pdev, 1);
	free_irq(irq, NULL);
batt_irq_fail:
voltage_setup_fail:
temp_setup_fail:
	twl4030charger_ac_en(DISABLE);
	twl4030charger_usb_en(DISABLE);
	twl4030battery_hw_level_en(DISABLE);
	twl4030battery_hw_presence_en(DISABLE);
	kfree(di);

	return ret;
}
예제 #15
0
static __devinit int max8971_probe(struct i2c_client *client, 
				   const struct i2c_device_id *id)
{

	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
	struct max8971_chip *chip;
	int ret;


	dev_info(&client->dev, "%s..\n", __func__);

	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE)) {
		dev_err(&client->dev, "%s i2c check failed..\n", __func__);
		return -EIO;
	}

	chip = kzalloc(sizeof(*chip), GFP_KERNEL);
	if (!chip) {
		dev_err(&client->dev, "Memory allocation failed\n");
		return -ENOMEM;
	}

	/*                                              */
	max8971_chg = chip;
	/*                                              */

#ifdef MAX8971_TOPOFF_WORKAROUND
	dev_info(&client->dev, "Starting delayed workd queue..\n");
	INIT_DELAYED_WORK(&chip->topoff_work, max8971_topoff_work);
	//printk(KERN_DEBUG "%s(%d)\n", __func__, __LINE__);
	chip->start_topoff_work = 0;
	chip->prev_chg_dtl = 0;
#endif
	chip->client	= client;
	chip->pdata	= client->dev.platform_data;

	i2c_set_clientdata(client, chip);

	if(chip->pdata->gpio_init)
		chip->pdata->gpio_init();
	else
		printk("max8971_probe : Failed to gpio init\n");
	
	chip->charger.name		= "charger";
	chip->charger.type		= POWER_SUPPLY_TYPE_BATTERY;
	chip->charger.properties	= max8971_charger_props;
	chip->charger.num_properties 	= ARRAY_SIZE(max8971_charger_props);
	chip->charger.get_property	= max8971_charger_get_property;
	chip->charger.set_property	= max8971_charger_set_property;

	ret = power_supply_register(&client->dev, &chip->charger);
	if (ret) {
		dev_err(&client->dev, 
				"power supply register failed : %d\n", ret);
		goto err_power_supply_register;
	}
	
	//INIT_WORK(&max8971_wq, max8971_charger_wq);

	//kkk_test
	INIT_DELAYED_WORK_DEFERRABLE(&chip->monitor_work, lge_charger_setting_work);
	//schedule_delayed_work(&chip->monitor_work, 0);

	if(is_tegra_batteryexistWhenBoot() == 1)
	{
	   	 ret = request_threaded_irq(client->irq, NULL, max8971_charger_wq,
	      		  IRQF_ONESHOT | IRQF_TRIGGER_LOW, client->name, chip);
		
		if (ret < 0) {
			printk(KERN_INFO "[max8971_probe] MAX8971_IRQB_GPIO set up failed!\n");
			free_irq(client->irq, &client->dev);
			return -ENOSYS;
		}
	}

/*
	chip->chg_online = 0;
	ret = max8971_read_reg(chip->client, MAX8971_REG_CHG_STAT);
	if (ret >= 0) {
		chip->chg_online = (ret & MAX8971_DCUVP_MASK) ? 0 : 1;

		if (chip->chg_online) {
			// Set IRQ MASK register
			max8971_write_reg(chip->client, MAX8971_REG_CHGINT_MASK, chip->pdata->int_mask);
			max8971_set_reg(chip, 1);
		}
	}
	else {
		dev_err(&client->dev, "i2c reading err : %d\n", ret);
		goto err;
	}
*/

	chip->chgcc_forced = 0;
	chip->dcilmt_forced = 60;

	ret = device_create_file(&client->dev, &dev_attr_chgcc_ta);
	if (ret < 0) {
		printk("device_create_file(chgcc_ta) error!\n");
		goto err;
	}

	ret = device_create_file(&client->dev, &dev_attr_chgcc_forced);
	if (ret < 0) {
		printk("device_create_file(chgcc_forced) error!\n");
		goto err_chgcc_forced;
	}

	ret = device_create_file(&client->dev, &dev_attr_dcilmt_forced);
	if (ret < 0) {
		printk("device_create_file(dcilmt_forced) error!\n");
		goto err_dcilmt_forced;
	}

	dev_info(&client->dev, "%s finish...\n", __func__);

	return 0;

err_dcilmt_forced:
	device_remove_file(&client->dev, &dev_attr_chgcc_forced);

err_chgcc_forced:
	device_remove_file(&client->dev, &dev_attr_chgcc_ta);

err:
	free_irq(client->irq, chip);

err_irq_request:
err_gpio_register_2:
	gpio_free(client->irq);

err_gpio_register_1:
	power_supply_unregister(&chip->charger);

err_power_supply_register:
	i2c_set_clientdata(client, NULL);
	kfree(chip);

	return ret;
}
static int __devinit tosa_bat_probe(struct platform_device *dev)
{
	int ret;

	if (!machine_is_tosa())
		return -ENODEV;

	ret = gpio_request_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios));
	if (ret)
		return ret;

	mutex_init(&tosa_bat_main.work_lock);
	mutex_init(&tosa_bat_jacket.work_lock);

	INIT_WORK(&bat_work, tosa_bat_work);

	ret = power_supply_register(&dev->dev, &tosa_bat_main.psy);
	if (ret)
		goto err_psy_reg_main;
	ret = power_supply_register(&dev->dev, &tosa_bat_jacket.psy);
	if (ret)
		goto err_psy_reg_jacket;
	ret = power_supply_register(&dev->dev, &tosa_bat_bu.psy);
	if (ret)
		goto err_psy_reg_bu;

	ret = request_irq(gpio_to_irq(TOSA_GPIO_BAT0_CRG),
				tosa_bat_gpio_isr,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
				"main full", &tosa_bat_main);
	if (ret)
		goto err_req_main;

	ret = request_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG),
				tosa_bat_gpio_isr,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
				"jacket full", &tosa_bat_jacket);
	if (ret)
		goto err_req_jacket;

	ret = request_irq(gpio_to_irq(TOSA_GPIO_JACKET_DETECT),
				tosa_bat_gpio_isr,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
				"jacket detect", &tosa_bat_jacket);
	if (!ret) {
		schedule_work(&bat_work);
		return 0;
	}

	free_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG), &tosa_bat_jacket);
err_req_jacket:
	free_irq(gpio_to_irq(TOSA_GPIO_BAT0_CRG), &tosa_bat_main);
err_req_main:
	power_supply_unregister(&tosa_bat_bu.psy);
err_psy_reg_bu:
	power_supply_unregister(&tosa_bat_jacket.psy);
err_psy_reg_jacket:
	power_supply_unregister(&tosa_bat_main.psy);
err_psy_reg_main:

	/* see comment in tosa_bat_remove */
	cancel_work_sync(&bat_work);

	gpio_free_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios));
	return ret;
}
예제 #17
0
static int pda_power_probe(struct platform_device *pdev)
{
	int ret = 0;

	dev = &pdev->dev;

	if (pdev->id != -1) {
		dev_err(dev, "it's meaningless to register several "
			"pda_powers; use id = -1\n");
		ret = -EINVAL;
		goto wrongid;
	}

	pdata = pdev->dev.platform_data;

	if (pdata->init) {
		ret = pdata->init(dev);
		if (ret < 0)
			goto init_failed;
	}

	update_status();
	update_charger();

	if (!pdata->wait_for_status)
		pdata->wait_for_status = 500;

	if (!pdata->wait_for_charger)
		pdata->wait_for_charger = 500;

	if (!pdata->polling_interval)
		pdata->polling_interval = 2000;

	if (!pdata->ac_max_uA)
		pdata->ac_max_uA = 500000;

	setup_timer(&charger_timer, charger_timer_func, 0);
	setup_timer(&supply_timer, supply_timer_func, 0);

	ac_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ac");
	usb_irq = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "usb");

	if (pdata->supplied_to) {
		pda_psy_ac.supplied_to = pdata->supplied_to;
		pda_psy_ac.num_supplicants = pdata->num_supplicants;
		pda_psy_usb.supplied_to = pdata->supplied_to;
		pda_psy_usb.num_supplicants = pdata->num_supplicants;
	}

	ac_draw = regulator_get(dev, "ac_draw");
	if (IS_ERR(ac_draw)) {
		dev_dbg(dev, "couldn't get ac_draw regulator\n");
		ac_draw = NULL;
		ret = PTR_ERR(ac_draw);
	}

#ifdef CONFIG_USB_OTG_UTILS
	transceiver = usb_get_transceiver();
	if (transceiver && !pdata->is_usb_online) {
		pdata->is_usb_online = otg_is_usb_online;
	}
	if (transceiver && !pdata->is_ac_online) {
		pdata->is_ac_online = otg_is_ac_online;
	}
#endif

	if (pdata->is_ac_online) {
		ret = power_supply_register(&pdev->dev, &pda_psy_ac);
		if (ret) {
			dev_err(dev, "failed to register %s power supply\n",
				pda_psy_ac.name);
			goto ac_supply_failed;
		}

		if (ac_irq) {
			ret = request_irq(ac_irq->start, power_changed_isr,
					  get_irq_flags(ac_irq), ac_irq->name,
					  &pda_psy_ac);
			if (ret) {
				dev_err(dev, "request ac irq failed\n");
				goto ac_irq_failed;
			}
		} else {
			polling = 1;
		}
	}

	if (pdata->is_usb_online) {
		ret = power_supply_register(&pdev->dev, &pda_psy_usb);
		if (ret) {
			dev_err(dev, "failed to register %s power supply\n",
				pda_psy_usb.name);
			goto usb_supply_failed;
		}

		if (usb_irq) {
			ret = request_irq(usb_irq->start, power_changed_isr,
					  get_irq_flags(usb_irq),
					  usb_irq->name, &pda_psy_usb);
			if (ret) {
				dev_err(dev, "request usb irq failed\n");
				goto usb_irq_failed;
			}
		} else {
			polling = 1;
		}
	}

#ifdef CONFIG_USB_OTG_UTILS
	if (transceiver && pdata->use_otg_notifier) {
		otg_nb.notifier_call = otg_handle_notification;
		ret = usb_register_notifier(transceiver, &otg_nb);
		if (ret) {
			dev_err(dev, "failure to register otg notifier\n");
			goto otg_reg_notifier_failed;
		}
		polling = 0;
	}
#endif

	if (polling) {
		dev_dbg(dev, "will poll for status\n");
		setup_timer(&polling_timer, polling_timer_func, 0);
		mod_timer(&polling_timer,
			  jiffies + msecs_to_jiffies(pdata->polling_interval));
	}

	if (ac_irq || usb_irq)
		device_init_wakeup(&pdev->dev, 1);

	return 0;

#ifdef CONFIG_USB_OTG_UTILS
otg_reg_notifier_failed:
	if (pdata->is_usb_online && usb_irq)
		free_irq(usb_irq->start, &pda_psy_usb);
#endif
usb_irq_failed:
	if (pdata->is_usb_online)
		power_supply_unregister(&pda_psy_usb);
usb_supply_failed:
	if (pdata->is_ac_online && ac_irq)
		free_irq(ac_irq->start, &pda_psy_ac);
#ifdef CONFIG_USB_OTG_UTILS
	if (transceiver)
		usb_put_transceiver(transceiver);
#endif
ac_irq_failed:
	if (pdata->is_ac_online)
		power_supply_unregister(&pda_psy_ac);
ac_supply_failed:
	if (ac_draw) {
		regulator_put(ac_draw);
		ac_draw = NULL;
	}
	if (pdata->exit)
		pdata->exit(dev);
init_failed:
wrongid:
	return ret;
}
예제 #18
0
static int olpc_battery_probe(struct platform_device *pdev)
{
	int ret;
	uint8_t status;

	/*
	 * We've seen a number of EC protocol changes; this driver requires
	 * the latest EC protocol, supported by 0x44 and above.
	 */
	if (olpc_platform_info.ecver < 0x44) {
		printk(KERN_NOTICE "OLPC EC version 0x%02x too old for "
			"battery driver.\n", olpc_platform_info.ecver);
		return -ENXIO;
	}

	ret = olpc_ec_cmd(EC_BAT_STATUS, NULL, 0, &status, 1);
	if (ret)
		return ret;

	/* Ignore the status. It doesn't actually matter */

	olpc_ac = power_supply_register(&pdev->dev, &olpc_ac_desc, NULL);
	if (IS_ERR(olpc_ac))
		return PTR_ERR(olpc_ac);

	if (olpc_board_at_least(olpc_board_pre(0xd0))) { /* XO-1.5 */
		olpc_bat_desc.properties = olpc_xo15_bat_props;
		olpc_bat_desc.num_properties = ARRAY_SIZE(olpc_xo15_bat_props);
	} else { /* XO-1 */
		olpc_bat_desc.properties = olpc_xo1_bat_props;
		olpc_bat_desc.num_properties = ARRAY_SIZE(olpc_xo1_bat_props);
	}

	olpc_bat = power_supply_register(&pdev->dev, &olpc_bat_desc, NULL);
	if (IS_ERR(olpc_bat)) {
		ret = PTR_ERR(olpc_bat);
		goto battery_failed;
	}

	ret = device_create_bin_file(&olpc_bat->dev, &olpc_bat_eeprom);
	if (ret)
		goto eeprom_failed;

	ret = device_create_file(&olpc_bat->dev, &olpc_bat_error);
	if (ret)
		goto error_failed;

	if (olpc_ec_wakeup_available()) {
		device_set_wakeup_capable(&olpc_ac->dev, true);
		device_set_wakeup_capable(&olpc_bat->dev, true);
	}

	return 0;

error_failed:
	device_remove_bin_file(&olpc_bat->dev, &olpc_bat_eeprom);
eeprom_failed:
	power_supply_unregister(olpc_bat);
battery_failed:
	power_supply_unregister(olpc_ac);
	return ret;
}
예제 #19
0
static int __devinit sec_battery_probe(struct platform_device *pdev)
{
	sec_battery_platform_data_t *pdata = dev_get_platdata(&pdev->dev);
	struct sec_battery_info *battery;
	int irq = 0;
	int ret = 0;

	pr_debug("%s: SEC Battery Driver Loading\n", __func__);

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

	platform_set_drvdata(pdev, battery);

	battery->dev = &pdev->dev;
	battery->pdata = pdata;

	mutex_init(&battery->adclock);
	pr_debug("%s: ADC init\n", __func__);
	adc_init(pdev, pdata, pdata->cable_check_adc_channel);
	adc_init(pdev, pdata, pdata->check_adc_channel);
	adc_init(pdev, pdata, pdata->temp_adc_channel);
	adc_init(pdev, pdata, pdata->temp_amb_adc_channel);
	adc_init(pdev, pdata, pdata->full_check_adc_channel);

	wake_lock_init(&battery->monitor_wake_lock, WAKE_LOCK_SUSPEND,
		       "sec-battery-monitor");
	wake_lock_init(&battery->cable_wake_lock, WAKE_LOCK_SUSPEND,
		       "sec-battery-cable");
	wake_lock_init(&battery->vbus_wake_lock, WAKE_LOCK_SUSPEND,
		       "sec-battery-vbus");

	/* initialization of battery info */
	battery->status = POWER_SUPPLY_STATUS_DISCHARGING;
	battery->health = POWER_SUPPLY_HEALTH_GOOD;
	battery->present = false;

	battery->long_polling_activated = false;
	battery->polling_count = 0;
	battery->polling_time = pdata->short_polling_time;

	battery->check_count = 0;
	battery->check_adc_count = 0;
	battery->check_adc_value = 0;

	battery->charging_start_time = 0;
	battery->charging_passed_time = 0;
	battery->charging_next_time = 0;

	setup_timer(&battery->event_expired_timer,
		sec_bat_event_expired_timer_func, (unsigned long)battery);

	battery->temp_high_threshold =
		pdata->temp_high_threshold_normal;
	battery->temp_high_recovery =
		pdata->temp_high_recovery_normal;
	battery->temp_low_recovery =
		pdata->temp_low_recovery_normal;
	battery->temp_low_threshold =
		pdata->temp_low_threshold_normal;

	battery->charging_mode = SEC_BATTERY_CHARGING_NONE;
	battery->cable_type = POWER_SUPPLY_TYPE_BATTERY;
	battery->test_activated = false;

	battery->psy_bat.name = "battery",
	battery->psy_bat.type = POWER_SUPPLY_TYPE_BATTERY,
	battery->psy_bat.properties = sec_battery_props,
	battery->psy_bat.num_properties = ARRAY_SIZE(sec_battery_props),
	battery->psy_bat.get_property = sec_bat_get_property,
	battery->psy_bat.set_property = sec_bat_set_property,
	battery->psy_usb.name = "usb",
	battery->psy_usb.type = POWER_SUPPLY_TYPE_USB,
	battery->psy_usb.supplied_to = supply_list,
	battery->psy_usb.num_supplicants = ARRAY_SIZE(supply_list),
	battery->psy_usb.properties = sec_power_props,
	battery->psy_usb.num_properties = ARRAY_SIZE(sec_power_props),
	battery->psy_usb.get_property = sec_usb_get_property,
	battery->psy_ac.name = "ac",
	battery->psy_ac.type = POWER_SUPPLY_TYPE_MAINS,
	battery->psy_ac.supplied_to = supply_list,
	battery->psy_ac.num_supplicants = ARRAY_SIZE(supply_list),
	battery->psy_ac.properties = sec_power_props,
	battery->psy_ac.num_properties = ARRAY_SIZE(sec_power_props),
	battery->psy_ac.get_property = sec_ac_get_property;

	/* init power supplier framework */
	ret = power_supply_register(&pdev->dev, &battery->psy_bat);
	if (ret) {
		pr_err("%s: Failed to Register psy_bat\n",
			__func__);
		goto err_wake_lock;
	}

	ret = power_supply_register(&pdev->dev, &battery->psy_usb);
	if (ret) {
		pr_err("%s: Failed to Register psy_usb\n",
			__func__);
		goto err_supply_unreg_bat;
	}

	ret = power_supply_register(&pdev->dev, &battery->psy_ac);
	if (ret) {
		pr_err("%s: Failed to Register psy_ac\n", __func__);
		goto err_supply_unreg_usb;
	}

	/* create work queue */
	battery->monitor_wqueue =
	    create_singlethread_workqueue(dev_name(&pdev->dev));
	if (!battery->monitor_wqueue) {
		pr_err("%s: Fail to Create Workqueue\n", __func__);
		goto err_supply_unreg_ac;
	}
	INIT_WORK(&battery->monitor_work, sec_bat_monitor_work);
	INIT_WORK(&battery->cable_work, sec_bat_cable_work);

	if (battery->pdata->bat_gpio_irq) {
		irq = gpio_to_irq(battery->pdata->bat_gpio_irq);
		ret = request_threaded_irq(irq, NULL,
				sec_bat_irq_thread,
				battery->pdata->bat_irq_attr,
				"battery-irq", battery);
		if (ret) {
			pr_err("%s: Failed to Reqeust IRQ\n", __func__);
			return ret;
		}

		ret = enable_irq_wake(irq);
		if (ret < 0)
			pr_err("%s: Failed to Enable Wakeup Source(%d)\n"
				, __func__, ret);
	}

	ret = sec_bat_create_attrs(battery->psy_bat.dev);
	if (ret) {
		pr_err("%s : Failed to create_attrs\n", __func__);
		goto err_supply_unreg_ac;
	}

	switch (pdata->polling_type) {
	case SEC_BATTERY_MONITOR_WORKQUEUE:
		INIT_DELAYED_WORK_DEFERRABLE(&battery->polling_work,
			sec_bat_polling_work);
		break;
	case SEC_BATTERY_MONITOR_ALARM:
		battery->last_poll_time = alarm_get_elapsed_realtime();
		alarm_init(&battery->polling_alarm,
			ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
			sec_bat_alarm);
		break;
	default:
		break;
	}

	wake_lock(&battery->monitor_wake_lock);
	queue_work(battery->monitor_wqueue, &battery->monitor_work);

	pdata->initial_check();

	pr_debug("%s: SEC Battery Driver Loaded\n", __func__);
	return 0;

err_supply_unreg_ac:
	power_supply_unregister(&battery->psy_ac);
err_supply_unreg_usb:
	power_supply_unregister(&battery->psy_usb);
err_supply_unreg_bat:
	power_supply_unregister(&battery->psy_bat);
err_wake_lock:
	wake_lock_destroy(&battery->monitor_wake_lock);
	wake_lock_destroy(&battery->cable_wake_lock);
	wake_lock_destroy(&battery->vbus_wake_lock);
	mutex_destroy(&battery->adclock);
	kfree(battery);

	return ret;
}
예제 #20
0
static int max8925_power_probe(struct platform_device *pdev)
{
	struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
	struct max8925_power_pdata *pdata = NULL;
	struct max8925_power_info *info;
	int ret;

	pdata = max8925_power_dt_init(pdev);
	if (!pdata) {
		dev_err(&pdev->dev, "platform data isn't assigned to "
			"power supply\n");
		return -EINVAL;
	}

	info = kzalloc(sizeof(struct max8925_power_info), GFP_KERNEL);
	if (!info)
		return -ENOMEM;
	info->chip = chip;
	info->gpm = chip->i2c;
	info->adc = chip->adc;
	platform_set_drvdata(pdev, info);

	info->ac.name = "max8925-ac";
	info->ac.type = POWER_SUPPLY_TYPE_MAINS;
	info->ac.properties = max8925_ac_props;
	info->ac.num_properties = ARRAY_SIZE(max8925_ac_props);
	info->ac.get_property = max8925_ac_get_prop;
	info->ac.supplied_to = pdata->supplied_to;
	info->ac.num_supplicants = pdata->num_supplicants;
	ret = power_supply_register(&pdev->dev, &info->ac);
	if (ret)
		goto out;
	info->ac.dev->parent = &pdev->dev;

	info->usb.name = "max8925-usb";
	info->usb.type = POWER_SUPPLY_TYPE_USB;
	info->usb.properties = max8925_usb_props;
	info->usb.num_properties = ARRAY_SIZE(max8925_usb_props);
	info->usb.get_property = max8925_usb_get_prop;
	info->usb.supplied_to = pdata->supplied_to;
	info->usb.num_supplicants = pdata->num_supplicants;

	ret = power_supply_register(&pdev->dev, &info->usb);
	if (ret)
		goto out_usb;
	info->usb.dev->parent = &pdev->dev;

	info->battery.name = "max8925-battery";
	info->battery.type = POWER_SUPPLY_TYPE_BATTERY;
	info->battery.properties = max8925_battery_props;
	info->battery.num_properties = ARRAY_SIZE(max8925_battery_props);
	info->battery.get_property = max8925_bat_get_prop;
	ret = power_supply_register(&pdev->dev, &info->battery);
	if (ret)
		goto out_battery;
	info->battery.dev->parent = &pdev->dev;

	info->batt_detect = pdata->batt_detect;
	info->topoff_threshold = pdata->topoff_threshold;
	info->fast_charge = pdata->fast_charge;
	info->set_charger = pdata->set_charger;
	info->no_temp_support = pdata->no_temp_support;
	info->no_insert_detect = pdata->no_insert_detect;

	max8925_init_charger(chip, info);
	return 0;
out_battery:
	power_supply_unregister(&info->battery);
out_usb:
	power_supply_unregister(&info->ac);
out:
	kfree(info);
	return ret;
}
static int ftt_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct ftt_charger_pdata *pdata = pdev->dev.platform_data;
	struct ftt_charger_device *ftt_pdev;
	int err;
	int retval = 0;

#ifdef CONFIG_OF
	struct device_node *np = pdev->dev.of_node;
#endif

#ifdef CONFIG_OF
	printk("[FTT] +ftt_probe()\n");
	if (pdev->dev.of_node) {

		pdata = devm_kzalloc(&pdev->dev,
						sizeof(struct ftt_charger_pdata),
						GFP_KERNEL);
		if (!pdata) {
			printk("ftt : cannot allocate\n");
			return -ENOMEM;
		}
		pdev->dev.platform_data = pdata;

		pdata->chg_ctrl_gpio = of_get_named_gpio(np, "chg_ctrl_gpio", 0);
		pdata->half_chg_ctrl_gpio = of_get_named_gpio(np, "half_chg_ctrl_gpio", 0);
		pdata->active_n_gpio = of_get_named_gpio(np, "active_n_gpio", 0);
		pdata->otg_ctrl_gpio= of_get_named_gpio(np, "otg_ctrl_gpio", 0);
		pdata->wlc_ts_mpp = of_get_named_gpio(np, "wlc_ts_mpp", 0);
		pdata->ftt_gpio = of_get_named_gpio(np, "track_gpio", 0);

		pdata->get_ftt_gpio = get_ftt_gpio;
		pdata->online_fn = wireless_online;
		pdata->on_change_level_fn = on_change_level;
	}
#endif

	ftt_pdev = kzalloc(sizeof(struct ftt_charger_device), GFP_KERNEL);
	if (!ftt_pdev) {
		dev_dbg(&pdev->dev, "out of memory\n");
		retval = -ENOMEM;
		goto err_out;
	}

	ftt_pdev->pdev = pdev;
	pdata = ftt_pdev->pdev->dev.platform_data;

#ifdef CONFIG_OF
	ftt_pdev->chg_ctrl_gpio = pdata->chg_ctrl_gpio;
	printk("[FTT] - chg_ctrl_gpio : %d\n", ftt_pdev->chg_ctrl_gpio);
	ftt_pdev->half_chg_ctrl_gpio = pdata->half_chg_ctrl_gpio;
	printk("[FTT] - half_chg_ctrl_gpio : %d\n", ftt_pdev->half_chg_ctrl_gpio);
	ftt_pdev->active_n_gpio = pdata->active_n_gpio;
	printk("[FTT] - active_n_gpio : %d\n", ftt_pdev->active_n_gpio);
	ftt_pdev->otg_ctrl_gpio = pdata->otg_ctrl_gpio;
	printk("[FTT] - otg_ctrl_gpio : %d\n", ftt_pdev->otg_ctrl_gpio);
	ftt_pdev->wlc_ts_mpp = pdata->wlc_ts_mpp;
	printk("[FTT] - wlc_ts_mpp : %d\n", ftt_pdev->wlc_ts_mpp);
	ftt_pdev->ftt_gpio = pdata->ftt_gpio;
	printk("[FTT] - track_gpio : %d\n", ftt_pdev->ftt_gpio);

	ftt_hw_init(ftt_pdev);
#endif

/* initalize member start */
	set_ftt_charger_init_data(ftt_pdev);
	set_ftt_charger_reset_status(ftt_pdev);
	set_ftt_charger_reset_data(ftt_pdev);
/* initalize member end */

	if (!pdata)
	{
		dev_err(dev, "Cannot find platform data.\n");
		retval = -ENXIO;
		goto err_kzalloc;
	}

	DPRINT(FTT_INFO, "%s\n", __FUNCTION__);

#if (FTT_CHIP_ENABLE_PIN_USE == 1)
	err = gpio_request(pdata->en1, "FTT_CHIP_ENABLE");
	if (err)
		printk(KERN_ERR "#### failed to request FTT_CHIP_ENABLE ####\n");
	gpio_direction_output(pdata->en1, ftt_chip_enable_flag);
#endif

	if (pdata->get_ftt_gpio == NULL) {
		retval = -ENXIO;
		goto err_kzalloc;
	}

	err = gpio_request(ftt_pdev->ftt_gpio, "FTT_FREQUANCY");
	if (err) {
		printk(KERN_ERR "#### failed to request FTT_FREQUANCY ####\n");
		retval = ENODEV;
		goto err_kzalloc;
	}

	gpio_direction_input(ftt_pdev->ftt_gpio);

	ftt_pdev->ftt_irq = gpio_to_irq(ftt_pdev->ftt_gpio);

	ftt_pdev->ftt_charger_status_timer.function = ftt_charger_status_timer_handler;
	ftt_pdev->ftt_charger_status_timer.data = (unsigned long)ftt_pdev;
	init_timer(&ftt_pdev->ftt_charger_status_timer);

	err = request_irq(ftt_pdev->ftt_irq, ftt_interrupt_pin_cb,
			IRQF_TRIGGER_RISING,
			DEVICE_NAME, (void *)ftt_pdev);
	if (err)
	{
		printk(KERN_ERR "gpio-ftt-charger: Unable to claim irq %d; error %d\n", ftt_pdev->ftt_irq, err);
		retval = err;
		goto err_gpio;
	}

	ftt_interrupt_disable(ftt_pdev);
	ftt_pdev->ftt_interrupt_booting_enable_flag = true;
	set_ftt_charger_reset_status(ftt_pdev);
#ifndef FTT_FILE_OPEN_ENABLE
	ftt_enable(ftt_pdev);
#endif /* FTT_FILE_OPEN_ENABLE */

#if defined(CONFIG_HAS_EARLYSUSPEND)
	/**************************************************************
	EARLYSUSPEND/LATERESUME
	**************************************************************/
	ftt_pdev->power.suspend	= ftt_suspend;
	ftt_pdev->power.resume	= ftt_resume;

	ftt_pdev->power.level	= EARLY_SUSPEND_LEVEL_DISABLE_FB-1;

	register_early_suspend(&ftt_pdev->power);
#endif

#if FTT_UEVENT
	ftt_uevent_init(ftt_pdev);
	if ((err = power_supply_register(dev, &ftt_pdev->ftt_supply))) {
		dev_err(dev, "failed: power supply ftt wireless register.\n");
		retval = err;
		goto err_suspend;
	}
	else	{
		dev_info(dev, "power supply ftt wireless registerd.\n");
	}
#endif

#if FTT_CHARACTER_DEVICE
	ftt_pdev->ftt_misc.fops = &ftt_fops;
	ftt_pdev->ftt_misc.name	= FTT_CHAR_DEVICE_NAME;
	ftt_pdev->ftt_misc.minor	= MISC_DYNAMIC_MINOR;//FTT_MINOR;
	if ((err = misc_register(&ftt_pdev->ftt_misc))) {
		retval = err;
		goto err_power_supply;
	}
	else	{
		dev_info(dev, "misc device ftt wireless registerd.\n");
	}
#endif /* FTT_CHARACTER_DEVICE */

	init_waitqueue_head(&ftt_pdev->wait);
	INIT_LIST_HEAD(&ftt_pdev->read_cmd_queue);

#ifdef CONFIG_FTT_SYSFS
	err = sysfs_create_group(&pdev->dev.kobj, &ftt_sysfs_attr_group);
	if (err) {
		printk(KERN_ERR "#### failed to sysfs_create_group ####\n");
		retval = err;
		goto err_character_device;
	}
#endif /* CONFIG_FTT_SYSFS */

	platform_set_drvdata(pdev, ftt_pdev);

	printk(DEVICE_NAME " Initialized\n");
	return 0;

/*******************************************************************************************
	ERROR
*******************************************************************************************/
	err_character_device:
#if FTT_CHARACTER_DEVICE
    misc_deregister(&ftt_pdev->ftt_misc);
#endif /* FTT_CHARACTER_DEVICE */

	err_power_supply:
#if FTT_UEVENT
	power_supply_unregister(&ftt_pdev->ftt_supply);
#endif

	err_suspend:
#if defined(CONFIG_HAS_EARLYSUSPEND)
	unregister_early_suspend(&ftt_pdev->power);
#endif
	free_irq(ftt_pdev->ftt_irq, ftt_pdev);
#if FTT_CHARGER_STATUS_TIMER
	del_timer(&ftt_pdev->ftt_charger_status_timer);
#endif

	err_gpio:
	gpio_free(ftt_pdev->ftt_gpio);

	err_kzalloc:
	kfree(ftt_pdev);

	err_out:
	return retval;
}
예제 #22
0
static int __devinit isp1704_charger_probe(struct platform_device *pdev)
{
	struct isp1704_charger	*isp;
	int			ret = -ENODEV;

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

	isp->phy = usb_get_phy();
	if (!isp->phy)
		goto fail0;

	isp->dev = &pdev->dev;
	platform_set_drvdata(pdev, isp);

	isp1704_charger_set_power(isp, 1);

	ret = isp1704_test_ulpi(isp);
	if (ret < 0)
		goto fail1;

	isp->psy.name		= "isp1704";
	isp->psy.type		= POWER_SUPPLY_TYPE_USB;
	isp->psy.properties	= power_props;
	isp->psy.num_properties	= ARRAY_SIZE(power_props);
	isp->psy.get_property	= isp1704_charger_get_property;

	ret = power_supply_register(isp->dev, &isp->psy);
	if (ret)
		goto fail1;

	/*
	 * REVISIT: using work in order to allow the usb notifications to be
	 * made atomically in the future.
	 */
	INIT_WORK(&isp->work, isp1704_charger_work);

	isp->nb.notifier_call = isp1704_notifier_call;

	ret = usb_register_notifier(isp->phy, &isp->nb);
	if (ret)
		goto fail2;

	dev_info(isp->dev, "registered with product id %s\n", isp->model);

	/*
	 * Taking over the D+ pullup.
	 *
	 * FIXME: The device will be disconnected if it was already
	 * enumerated. The charger driver should be always loaded before any
	 * gadget is loaded.
	 */
	if (isp->phy->otg->gadget)
		usb_gadget_disconnect(isp->phy->otg->gadget);

	/* Detect charger if VBUS is valid (the cable was already plugged). */
	ret = isp1704_read(isp, ULPI_USB_INT_STS);
	isp1704_charger_set_power(isp, 0);
	if ((ret & ULPI_INT_VBUS_VALID) && !isp->phy->otg->default_a) {
		isp->event = USB_EVENT_VBUS;
		schedule_work(&isp->work);
	}

	return 0;
fail2:
	power_supply_unregister(&isp->psy);
fail1:
	usb_put_phy(isp->phy);
fail0:
	kfree(isp);

	dev_err(&pdev->dev, "failed to register isp1704 with error %d\n", ret);

	isp1704_charger_set_power(isp, 0);
	return ret;
}
예제 #23
0
static int __init twl4030_bci_probe(struct platform_device *pdev)
{
	struct twl4030_bci *bci;
	const struct twl4030_bci_platform_data *pdata = pdev->dev.platform_data;
	int ret;
	u32 reg;

	bci = kzalloc(sizeof(*bci), GFP_KERNEL);
	if (bci == NULL)
		return -ENOMEM;

	if (!pdata)
		pdata = twl4030_bci_parse_dt(&pdev->dev);

	bci->dev = &pdev->dev;
	bci->irq_chg = platform_get_irq(pdev, 0);
	bci->irq_bci = platform_get_irq(pdev, 1);

	/* Only proceed further *IF* battery is physically present */
	ret = twl4030_is_battery_present(bci);
	if  (ret) {
		dev_crit(&pdev->dev, "Battery was not detected:%d\n", ret);
		goto fail_no_battery;
	}

	platform_set_drvdata(pdev, bci);

	bci->ac = power_supply_register(&pdev->dev, &twl4030_bci_ac_desc,
					NULL);
	if (IS_ERR(bci->ac)) {
		ret = PTR_ERR(bci->ac);
		dev_err(&pdev->dev, "failed to register ac: %d\n", ret);
		goto fail_register_ac;
	}

	bci->usb_reg = regulator_get(bci->dev, "bci3v1");

	bci->usb = power_supply_register(&pdev->dev, &twl4030_bci_usb_desc,
					 NULL);
	if (IS_ERR(bci->usb)) {
		ret = PTR_ERR(bci->usb);
		dev_err(&pdev->dev, "failed to register usb: %d\n", ret);
		goto fail_register_usb;
	}

	ret = request_threaded_irq(bci->irq_chg, NULL,
			twl4030_charger_interrupt, IRQF_ONESHOT, pdev->name,
			bci);
	if (ret < 0) {
		dev_err(&pdev->dev, "could not request irq %d, status %d\n",
			bci->irq_chg, ret);
		goto fail_chg_irq;
	}

	ret = request_threaded_irq(bci->irq_bci, NULL,
			twl4030_bci_interrupt, IRQF_ONESHOT, pdev->name, bci);
	if (ret < 0) {
		dev_err(&pdev->dev, "could not request irq %d, status %d\n",
			bci->irq_bci, ret);
		goto fail_bci_irq;
	}

	INIT_WORK(&bci->work, twl4030_bci_usb_work);

	bci->transceiver = usb_get_phy(USB_PHY_TYPE_USB2);
	if (!IS_ERR_OR_NULL(bci->transceiver)) {
		bci->usb_nb.notifier_call = twl4030_bci_usb_ncb;
		usb_register_notifier(bci->transceiver, &bci->usb_nb);
	}

	/* Enable interrupts now. */
	reg = ~(u32)(TWL4030_ICHGLOW | TWL4030_ICHGEOC | TWL4030_TBATOR2 |
		TWL4030_TBATOR1 | TWL4030_BATSTS);
	ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
			       TWL4030_INTERRUPTS_BCIIMR1A);
	if (ret < 0) {
		dev_err(&pdev->dev, "failed to unmask interrupts: %d\n", ret);
		goto fail_unmask_interrupts;
	}

	reg = ~(u32)(TWL4030_VBATOV | TWL4030_VBUSOV | TWL4030_ACCHGOV);
	ret = twl_i2c_write_u8(TWL4030_MODULE_INTERRUPTS, reg,
			       TWL4030_INTERRUPTS_BCIIMR2A);
	if (ret < 0)
		dev_warn(&pdev->dev, "failed to unmask interrupts: %d\n", ret);

	twl4030_charger_enable_ac(true);
	twl4030_charger_enable_usb(bci, true);
	if (pdata)
		twl4030_charger_enable_backup(pdata->bb_uvolt,
					      pdata->bb_uamp);
	else
		twl4030_charger_enable_backup(0, 0);

	return 0;

fail_unmask_interrupts:
	if (!IS_ERR_OR_NULL(bci->transceiver)) {
		usb_unregister_notifier(bci->transceiver, &bci->usb_nb);
		usb_put_phy(bci->transceiver);
	}
	free_irq(bci->irq_bci, bci);
fail_bci_irq:
	free_irq(bci->irq_chg, bci);
fail_chg_irq:
	power_supply_unregister(bci->usb);
fail_register_usb:
	power_supply_unregister(bci->ac);
fail_register_ac:
fail_no_battery:
	kfree(bci);

	return ret;
}
예제 #24
0
static __devinit int max8903_probe(struct platform_device *pdev)
{
	struct max8903_data *data;
	struct device *dev = &pdev->dev;
	struct max8903_pdata *pdata = pdev->dev.platform_data;
	int ret = 0;
	int gpio = 0;
	int ta_in = 0;
	int usb_in = 0;
	int retval;
	cpu_type_flag = 0;
	
	//-> [J.Chiang], debug
	printk("sabresd_battery: max8903_probe is called......\n");
	// <- End.
	if (cpu_is_mx6q())
		cpu_type_flag = 1;
	if (cpu_is_mx6dl())
		cpu_type_flag = 0;
	data = kzalloc(sizeof(struct max8903_data), GFP_KERNEL);
	if (data == NULL) {
		dev_err(dev, "Cannot allocate memory.\n");
		return -ENOMEM;
	}
	data->first_delay_count = 0;
	data->pdata = pdata;
	data->dev = dev;
	platform_set_drvdata(pdev, data);
	data->usb_in = 0;
	data->ta_in = 0;
#ifndef	CONFIG_DSA2L
	if (pdata->dc_valid == false && pdata->usb_valid == false) {
		dev_err(dev, "No valid power sources.\n");
		printk(KERN_INFO "No valid power sources.\n");
		ret = -EINVAL;
		goto err;
	}
	if (pdata->dc_valid) {
		if (pdata->dok && gpio_is_valid(pdata->dok)) {
			gpio = pdata->dok; /* PULL_UPed Interrupt */
			/* set DOK gpio input */
			ret = gpio_request(gpio, "max8903-DOK");
			if (ret) {
				printk(KERN_ERR"request max8903-DOK error!!\n");
				goto err;
			} else {
				gpio_direction_input(gpio);
			}
			ta_in = gpio_get_value(gpio) ? 0 : 1;
		} else if (pdata->dok && gpio_is_valid(pdata->dok) && pdata->dcm_always_high) {
			ta_in = pdata->dok; /* PULL_UPed Interrupt */
			ta_in = gpio_get_value(gpio) ? 0 : 1;
		} else {
			dev_err(dev, "When DC is wired, DOK and DCM should"
					" be wired as well."
					" or set dcm always high\n");
			ret = -EINVAL;
			goto err;
		}
	}
	if (pdata->usb_valid) {
		if (pdata->uok && gpio_is_valid(pdata->uok)) {
			gpio = pdata->uok;
			/* set UOK gpio input */
			ret = gpio_request(gpio, "max8903-UOK");
			if (ret) {
				printk(KERN_ERR"request max8903-UOK error!!\n");
				goto err;
			} else {
				gpio_direction_input(gpio);
			}
			usb_in = gpio_get_value(gpio) ? 0 : 1;
		} else {
			dev_err(dev, "When USB is wired, UOK should be wired."
					"as well.\n");
			ret = -EINVAL;
			goto err;
		}
	}
	if (pdata->chg) {
		if (!gpio_is_valid(pdata->chg)) {
			dev_err(dev, "Invalid pin: chg.\n");
			ret = -EINVAL;
			goto err;
		}
		/* set CHG gpio input */
		ret = gpio_request(pdata->chg, "max8903-CHG");
		if (ret) {
			printk(KERN_ERR"request max8903-CHG error!!\n");
			goto err;
		} else {
			gpio_direction_input(pdata->chg);
		}
	}
	if (pdata->flt) {
		if (!gpio_is_valid(pdata->flt)) {
			dev_err(dev, "Invalid pin: flt.\n");
			ret = -EINVAL;
			goto err;
		}
		/* set FLT gpio input */
		ret = gpio_request(pdata->flt, "max8903-FLT");
		if (ret) {
			printk(KERN_ERR"request max8903-FLT error!!\n");
			goto err;
		} else {
			gpio_direction_input(pdata->flt);
		}
	}
	if (pdata->usus) {
		if (!gpio_is_valid(pdata->usus)) {
			dev_err(dev, "Invalid pin: usus.\n");
			ret = -EINVAL;
			goto err;
		}
	}
#endif	// CONFIG_DSA2L
	mutex_init(&data->work_lock);
	//-> [J.Chiang], debug
	printk("sabresd_battery: register max8903-ac......\n");
	// <- End.
	data->fault = false;
	data->ta_in = ta_in;
	data->usb_in = usb_in;
	data->psy.name = "max8903-ac";
	data->psy.type = POWER_SUPPLY_TYPE_MAINS;
	data->psy.get_property = max8903_get_property;
	data->psy.properties = max8903_charger_props;
	data->psy.num_properties = ARRAY_SIZE(max8903_charger_props);
	ret = power_supply_register(dev, &data->psy);
	if (ret) {
		dev_err(dev, "failed: power supply register.\n");
		goto err_psy;
	}
#ifndef	CONFIG_DSA2L
	data->usb.name = "max8903-usb";
	data->usb.type = POWER_SUPPLY_TYPE_USB;
	data->usb.get_property = max8903_get_usb_property;
	data->usb.properties = max8903_charger_props;
	data->usb.num_properties = ARRAY_SIZE(max8903_charger_props);
	ret = power_supply_register(dev, &data->usb);
	if (ret) {
		dev_err(dev, "failed: power supply register.\n");
		goto err_psy;
	}
#endif	// CONFIG_DSA2L
	//-> [J.Chiang], debug
	printk("sabresd_battery: register max8903-charger......\n");
	// <- End.
	data->bat.name = "max8903-charger";
	data->bat.type = POWER_SUPPLY_TYPE_BATTERY;
	data->bat.properties = max8903_battery_props;
	data->bat.num_properties = ARRAY_SIZE(max8903_battery_props);
	data->bat.get_property = max8903_battery_get_property;
	data->bat.use_for_apm = 1;
	retval = power_supply_register(&pdev->dev, &data->bat);
	if (retval) {
		dev_err(data->dev, "failed to register battery\n");
		goto battery_failed;
	}
	INIT_DELAYED_WORK(&data->work, max8903_battery_work);
	schedule_delayed_work(&data->work, data->interval);
#ifndef	CONFIG_DSA2L
	if (pdata->dc_valid) {
		ret = request_threaded_irq(gpio_to_irq(pdata->dok),
				NULL, max8903_dcin,
				IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
				"MAX8903 DC IN", data);
		if (ret) {
			dev_err(dev, "Cannot request irq %d for DC (%d)\n",
					gpio_to_irq(pdata->dok), ret);
			goto err_usb_irq;
		}
	}

	if (pdata->usb_valid) {
		ret = request_threaded_irq(gpio_to_irq(pdata->uok),
				NULL, max8903_usbin,
				IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
				"MAX8903 USB IN", data);
		if (ret) {
			dev_err(dev, "Cannot request irq %d for USB (%d)\n",
					gpio_to_irq(pdata->uok), ret);
			goto err_dc_irq;
		}
	}

	if (pdata->flt) {
		ret = request_threaded_irq(gpio_to_irq(pdata->flt),
				NULL, max8903_fault,
				IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
				"MAX8903 Fault", data);
		if (ret) {
			dev_err(dev, "Cannot request irq %d for Fault (%d)\n",
					gpio_to_irq(pdata->flt), ret);
			goto err_flt_irq;
		}
	}

	if (pdata->chg) {
		ret = request_threaded_irq(gpio_to_irq(pdata->chg),
				NULL, max8903_chg,
				IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
				"MAX8903 Status", data);
		if (ret) {
			dev_err(dev, "Cannot request irq %d for Status (%d)\n",
					gpio_to_irq(pdata->flt), ret);
			goto err_chg_irq;
		}
	}
#endif	// CONFIG_DSA2L
	ret = device_create_file(&pdev->dev, &max8903_discharger_dev_attr);
	if (ret)
		dev_err(&pdev->dev, "create device file failed!\n");
	ret = device_create_file(&pdev->dev, &max8903_charger_dev_attr);
	if (ret)
		dev_err(&pdev->dev, "create device file failed!\n");
#ifndef	CONFIG_DSA2L
	ret = device_create_file(&pdev->dev, &max8903_usb_charger_dev_attr);
	if (ret)
		dev_err(&pdev->dev, "create device file failed!\n");
#endif	// CONFIG_DSA2L
	if (cpu_type_flag == 1) {
			offset_discharger = 1694;
			offset_charger = 1900;
			offset_usb_charger = 1685;
	}
	if (cpu_type_flag == 0) {
			offset_discharger = 1464;
			offset_charger = 1485;
			offset_usb_charger = 1285;
	}
	max8903_charger_update_status(data);
	max8903_battery_update_status(data);
	return 0;
err_psy:
	power_supply_unregister(&data->psy);
battery_failed:
	power_supply_unregister(&data->bat);
err_usb_irq:
	if (pdata->usb_valid)
		free_irq(gpio_to_irq(pdata->uok), data);
	cancel_delayed_work(&data->work);
err_dc_irq:
	if (pdata->dc_valid)
		free_irq(gpio_to_irq(pdata->dok), data);
	cancel_delayed_work(&data->work);
err_flt_irq:
	if (pdata->usb_valid)
		free_irq(gpio_to_irq(pdata->uok), data);
	cancel_delayed_work(&data->work);
err_chg_irq:
	if (pdata->dc_valid)
		free_irq(gpio_to_irq(pdata->dok), data);
	cancel_delayed_work(&data->work);
err:
	if (pdata->uok)
		gpio_free(pdata->uok);
	if (pdata->dok)
		gpio_free(pdata->dok);
	if (pdata->flt)
		gpio_free(pdata->flt);
	if (pdata->chg)
		gpio_free(pdata->chg);
	kfree(data);
	return ret;
}
예제 #25
0
static void lp8788_psy_unregister(struct lp8788_charger *pchg)
{
	power_supply_unregister(pchg->battery);
	power_supply_unregister(pchg->charger);
}
예제 #26
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;
}
예제 #27
0
static int pmic_battery_probe(struct platform_device *pdev)
{
	int retval = 0;
	struct mc13892_dev_info *di;
	pmic_event_callback_t bat_event_callback;
	pmic_version_t pmic_version;

	//printk("%s %s %d   \n",__FILE__,__func__,__LINE__); 

	/* Only apply battery driver for MC13892 V2.0 due to ENGR108085 */
	pmic_version = pmic_get_version();
	if (pmic_version.revision < 20) {
		pr_debug("Battery driver is only applied for MC13892 V2.0\n");
		return -1;
	}
	if (machine_is_mx50_arm2()) {
		pr_debug("mc13892 charger is not used for this platform\n");
		return -1;
	}

	di = kzalloc(sizeof(*di), GFP_KERNEL);
	if (!di) {
		retval = -ENOMEM;
		goto di_alloc_failed;
	}

	di->init_charge = -1;

	platform_set_drvdata(pdev, di);
   
	di->charger.name	= "mc13892_charger";
	di->charger.type = POWER_SUPPLY_TYPE_MAINS;
	di->charger.properties = mc13892_charger_props;
	di->charger.num_properties = ARRAY_SIZE(mc13892_charger_props);
	di->charger.get_property = mc13892_charger_get_property;
	retval = power_supply_register(&pdev->dev, &di->charger);
	if (retval) {
		dev_err(di->dev, "failed to register charger\n");
		goto charger_failed;
	}

	INIT_DELAYED_WORK(&di->monitor_work, mc13892_battery_work);
	
	di->monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev));
	if (!di->monitor_wqueue) {
		retval = -ESRCH;
		goto workqueue_failed;
	}
	queue_delayed_work(di->monitor_wqueue, &di->monitor_work, HZ * 10);
	//queue_delayed_work(di->monitor_wqueue, &di->monitor_work, msecs_to_jiffies(10000));

	pmic_stop_coulomb_counter();
	pmic_calibrate_coulomb_counter();

	//for get correct voltage on the battery when booting with external power.
	//chg_thread will change it, when next work (chg_work) is start.
	pmic_set_chg_current(0);
	INIT_DELAYED_WORK(&di->calc_capacity,mc13892_compute_battery_capacity_from_CC);
	queue_delayed_work(di->monitor_wqueue, &di->calc_capacity, 0);

	INIT_DELAYED_WORK(&chg_work, chg_thread);
	chg_wq = create_singlethread_workqueue("mxc_chg");
	if (!chg_wq) {
		retval = -ESRCH;
		goto workqueue_failed;
	}
	queue_delayed_work(chg_wq, &chg_work, HZ);

	di->dev	= &pdev->dev;
	di->bat.name	= "mc13892_bat";
	di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
	di->bat.properties = mc13892_battery_props;
	di->bat.num_properties = ARRAY_SIZE(mc13892_battery_props);
	di->bat.get_property = mc13892_battery_get_property;
	di->bat.use_for_apm = 1;

	di->battery_status = POWER_SUPPLY_STATUS_UNKNOWN;
	//di->battery_status = POWER_SUPPLY_STATUS_DISCHARGING; 


	retval = power_supply_register(&pdev->dev, &di->bat);
	if (retval) {
		dev_err(di->dev, "failed to register battery\n");
		goto batt_failed;
	}

   


	bat_event_callback.func = charger_online_event_callback;
	bat_event_callback.param = (void *) di;
	pmic_event_subscribe(EVENT_CHGDETI, bat_event_callback);

	retval = sysfs_create_file(&pdev->dev.kobj, &dev_attr_enable.attr);
	if (retval) {
		printk(KERN_ERR
		       "Battery: Unable to register sysdev entry for Battery");
		goto workqueue_failed;
	}
	
	chg_wa_is_active = 1;
	chg_wa_timer = 0;
	disable_chg_timer = 0;

#if defined(PMIC_MC13892_BATTERY_WORK)
      work_init();
#endif
	
	goto success;

workqueue_failed:
	power_supply_unregister(&di->charger);
charger_failed:
	power_supply_unregister(&di->bat);
batt_failed:
	kfree(di);
di_alloc_failed:
success:
	dev_dbg(di->dev, "%s battery probed!\n", __func__);
	return retval;


	return 0;
}
예제 #28
0
static __devinit int max8998_charger_probe(struct platform_device *pdev)
{
	struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
	struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
	struct chg_data *chg;
	int ret = 0;

	pr_info("%s : MAX8998 Charger Driver Loading\n", __func__);

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

	chg->iodev = iodev;
	chg->pdata = pdata->charger;

	if (!chg->pdata || !chg->pdata->adc_table) {
		pr_err("%s : No platform data & adc_table supplied\n", __func__);
		ret = -EINVAL;
		goto err_bat_table;
	}

	chg->psy_bat.name = "battery",
	chg->psy_bat.type = POWER_SUPPLY_TYPE_BATTERY,
	chg->psy_bat.properties = max8998_battery_props,
	chg->psy_bat.num_properties = ARRAY_SIZE(max8998_battery_props),
	chg->psy_bat.get_property = s3c_bat_get_property,

	chg->psy_usb.name = "usb",
	chg->psy_usb.type = POWER_SUPPLY_TYPE_USB,
	chg->psy_usb.supplied_to = supply_list,
	chg->psy_usb.num_supplicants = ARRAY_SIZE(supply_list),
	chg->psy_usb.properties = s3c_power_properties,
	chg->psy_usb.num_properties = ARRAY_SIZE(s3c_power_properties),
	chg->psy_usb.get_property = s3c_usb_get_property,

	chg->psy_ac.name = "ac",
	chg->psy_ac.type = POWER_SUPPLY_TYPE_MAINS,
	chg->psy_ac.supplied_to = supply_list,
	chg->psy_ac.num_supplicants = ARRAY_SIZE(supply_list),
	chg->psy_ac.properties = s3c_power_properties,
	chg->psy_ac.num_properties = ARRAY_SIZE(s3c_power_properties),
	chg->psy_ac.get_property = s3c_ac_get_property,

	chg->present = 1;
	chg->polling_interval = POLLING_INTERVAL;
	chg->bat_info.batt_health = POWER_SUPPLY_HEALTH_GOOD;
	chg->bat_info.batt_is_full = false;
	chg->bat_info.batt_max_soc = 0;
	chg->set_charge_timeout = false;

	chg->cable_status = CABLE_TYPE_NONE;

	mutex_init(&chg->mutex);

	platform_set_drvdata(pdev, chg);

	ret = max8998_update_reg(iodev, MAX8998_REG_CHGR1, /* disable */
		(0x3 << MAX8998_SHIFT_RSTR), MAX8998_MASK_RSTR);
	if (ret < 0)
		goto err_kfree;

	ret = max8998_update_reg(iodev, MAX8998_REG_CHGR2, /* 6 Hr */
		(0x2 << MAX8998_SHIFT_FT), MAX8998_MASK_FT);
	if (ret < 0)
		goto err_kfree;

	ret = max8998_update_reg(iodev, MAX8998_REG_CHGR2, /* 4.2V */
		(0x0 << MAX8998_SHIFT_BATTSL), MAX8998_MASK_BATTSL);
	if (ret < 0)
		goto err_kfree;

	ret = max8998_update_reg(iodev, MAX8998_REG_CHGR2, /* 105c */
		(0x0 << MAX8998_SHIFT_TMP), MAX8998_MASK_TMP);
	if (ret < 0)
		goto err_kfree;

	pr_info("%s : pmic interrupt registered\n", __func__);
	ret = max8998_write_reg(iodev, MAX8998_REG_IRQM1,
		~(MAX8998_MASK_DCINR | MAX8998_MASK_DCINF));
	if (ret < 0)
		goto err_kfree;

	ret = max8998_write_reg(iodev, MAX8998_REG_IRQM2, 0xFF);
	if (ret < 0)
		goto err_kfree;

	ret = max8998_write_reg(iodev, MAX8998_REG_IRQM3, ~0x4);
	if (ret < 0)
		goto err_kfree;

	ret = max8998_write_reg(iodev, MAX8998_REG_IRQM4, 0xFF);
	if (ret < 0)
		goto err_kfree;

	wake_lock_init(&chg->vbus_wake_lock, WAKE_LOCK_SUSPEND,
		"vbus_present");
	wake_lock_init(&chg->work_wake_lock, WAKE_LOCK_SUSPEND,
		"max8998-charger");

	INIT_WORK(&chg->bat_work, s3c_bat_work);

	chg->monitor_wqueue =
		create_freezeable_workqueue(dev_name(&pdev->dev));
	if (!chg->monitor_wqueue) {
		pr_err("Failed to create freezeable workqueue\n");
		ret = -ENOMEM;
		goto err_wake_lock;
	}

	chg->last_poll = alarm_get_elapsed_realtime();
	alarm_init(&chg->alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
		s3c_battery_alarm);

	check_lpm_charging_mode(chg);

	/* init power supplier framework */
	ret = power_supply_register(&pdev->dev, &chg->psy_bat);
	if (ret) {
		pr_err("Failed to register power supply psy_bat\n");
		goto err_wqueue;
	}

	ret = power_supply_register(&pdev->dev, &chg->psy_usb);
	if (ret) {
		pr_err("Failed to register power supply psy_usb\n");
		goto err_supply_unreg_bat;
	}

	ret = power_supply_register(&pdev->dev, &chg->psy_ac);
	if (ret) {
		pr_err("Failed to register power supply psy_ac\n");
		goto err_supply_unreg_usb;
	}

	ret = request_threaded_irq(iodev->i2c_client->irq, NULL,
			max8998_int_work_func,
			IRQF_TRIGGER_FALLING, "max8998-charger", chg);
	if (ret) {
		pr_err("%s : Failed to request pmic irq\n", __func__);
		goto err_supply_unreg_ac;
	}

	ret = enable_irq_wake(iodev->i2c_client->irq);
	if (ret) {
		pr_err("Failed to enable pmic irq wake\n");
		goto err_irq;
	}

	ret = s3c_bat_create_attrs(chg->psy_bat.dev);
	if (ret) {
		pr_err("%s : Failed to create_attrs\n", __func__);
		goto err_irq;
	}

	chg->callbacks.set_cable = max8998_set_cable;
	if (chg->pdata->register_callbacks)
		chg->pdata->register_callbacks(&chg->callbacks);

	wake_lock(&chg->work_wake_lock);
	queue_work(chg->monitor_wqueue, &chg->bat_work);

	return 0;

err_irq:
	free_irq(iodev->i2c_client->irq, NULL);
err_supply_unreg_ac:
	power_supply_unregister(&chg->psy_ac);
err_supply_unreg_usb:
	power_supply_unregister(&chg->psy_usb);
err_supply_unreg_bat:
	power_supply_unregister(&chg->psy_bat);
err_wqueue:
	destroy_workqueue(chg->monitor_wqueue);
	cancel_work_sync(&chg->bat_work);
	alarm_cancel(&chg->alarm);
err_wake_lock:
	wake_lock_destroy(&chg->work_wake_lock);
	wake_lock_destroy(&chg->vbus_wake_lock);
err_kfree:
	mutex_destroy(&chg->mutex);
err_bat_table:
	kfree(chg);
	return ret;
}
static int __devinit bcmpmu_spa_pb_probe(struct platform_device *pdev)
{
	int ret = 0;
	struct bcmpmu_spa_pb *bcmpmu_spa_pb;
	struct bcmpmu59xxx *bcmpmu = dev_get_drvdata(pdev->dev.parent);
	struct bcmpmu59xxx_spa_pb_pdata *pdata;
	pdata = (struct  bcmpmu59xxx_spa_pb_pdata *)pdev->dev.platform_data;
	pr_pb(INIT, "%s\n", __func__);
	BUG_ON(!(bcmpmu->flags & BCMPMU_SPA_EN) || !pdata);
	bcmpmu_spa_pb = kzalloc(sizeof(struct bcmpmu_spa_pb), GFP_KERNEL);
	if (bcmpmu_spa_pb == NULL) {
		dev_err(&pdev->dev, "failed to alloc mem: %d\n", ret);
		return -ENOMEM;
	}
	bcmpmu_spa_pb->bcmpmu = bcmpmu;
	bcmpmu->spa_pb_info = (void *)bcmpmu_spa_pb;

	mutex_init(&bcmpmu_spa_pb->lock);

	INIT_DELAYED_WORK(&bcmpmu_spa_pb->spa_work, bcmpmu_spa_pb_work);

	bcmpmu_spa_pb->chrgr.properties = bcmpmu_spa_pb_chrgr_props;
	bcmpmu_spa_pb->chrgr.num_properties =
			ARRAY_SIZE(bcmpmu_spa_pb_chrgr_props);
	bcmpmu_spa_pb->chrgr.get_property = bcmpmu_spa_pb_chrgr_get_property;
	bcmpmu_spa_pb->chrgr.set_property = bcmpmu_spa_pb_chrgr_set_property;
	bcmpmu_spa_pb->chrgr.name = pdata->chrgr_name;

	ret = power_supply_register(&pdev->dev, &bcmpmu_spa_pb->chrgr);
	if (ret)
		goto cghr_err;

	bcmpmu->register_irq(bcmpmu, PMU_IRQ_MBTEMPLOW,
		bcmpmu_spa_pb_isr, bcmpmu_spa_pb);
	bcmpmu->register_irq(bcmpmu, PMU_IRQ_MBTEMPHIGH,
		bcmpmu_spa_pb_isr, bcmpmu_spa_pb);
	bcmpmu->register_irq(bcmpmu, PMU_IRQ_CHGERRDIS,
		bcmpmu_spa_pb_isr, bcmpmu_spa_pb);
	bcmpmu->register_irq(bcmpmu, PMU_IRQ_MBOV,
		bcmpmu_spa_pb_isr, bcmpmu_spa_pb);
	bcmpmu->register_irq(bcmpmu, PMU_IRQ_MBOV_DIS,
		bcmpmu_spa_pb_isr, bcmpmu_spa_pb);
	bcmpmu->unmask_irq(bcmpmu, PMU_IRQ_MBTEMPLOW);
	bcmpmu->unmask_irq(bcmpmu, PMU_IRQ_MBTEMPHIGH);
	bcmpmu->unmask_irq(bcmpmu, PMU_IRQ_CHGERRDIS);
	bcmpmu->unmask_irq(bcmpmu, PMU_IRQ_MBOV);
	bcmpmu->unmask_irq(bcmpmu, PMU_IRQ_MBOV_DIS);

	bcmpmu_spa_pb->nb_chgr_det.notifier_call = bcmpmu_spa_pb_event_hndlr;
	ret = bcmpmu_add_notifier(PMU_ACCY_EVT_OUT_CHRGR_TYPE,
		&bcmpmu_spa_pb->nb_chgr_det);
	if (ret) {
		pr_pb(ERROR, "%s, failed to register chrgr det notifier\n",
			__func__);
		goto err;
	}
	bcmpmu_spa_pb->nb_usbin.notifier_call = bcmpmu_spa_pb_event_hndlr;
	ret = bcmpmu_add_notifier(PMU_ACCY_EVT_OUT_USB_IN,
		&bcmpmu_spa_pb->nb_usbin);
	if (ret) {
		pr_pb(ERROR, "%s, failed to register chrgr det notifier\n",
			__func__);
		goto err;
	}

#ifdef CONFIG_DEBUG_FS
	bcmpmu_spa_pb_dbg_init(bcmpmu_spa_pb);
#endif

	return 0;

err:
	bcmpmu_remove_notifier(PMU_ACCY_EVT_OUT_CHRGR_TYPE,
			&bcmpmu_spa_pb->nb_chgr_det);
	bcmpmu_remove_notifier(PMU_ACCY_EVT_OUT_USB_IN,
			&bcmpmu_spa_pb->nb_usbin);
	power_supply_unregister(&bcmpmu_spa_pb->chrgr);
cghr_err:
	kfree(bcmpmu_spa_pb);
	return ret;
}
예제 #30
0
static int cw_bat_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
        struct cw_battery *cw_bat;
        int ret;
        int irq;
        int irq_flags;
        int loop = 0;

        cw_bat = devm_kzalloc(&client->dev, sizeof(*cw_bat), GFP_KERNEL);
        if (!cw_bat) {
                dev_err(&cw_bat->client->dev, "fail to allocate memory\n");
                return -ENOMEM;
        }

        i2c_set_clientdata(client, cw_bat);
        cw_bat->plat_data = client->dev.platform_data;
        ret = cw_bat_gpio_init(cw_bat);
        if (ret) {
                dev_err(&cw_bat->client->dev, "cw_bat_gpio_init error\n");
                return ret;
        }
        
        cw_bat->client = client;

        ret = cw_init(cw_bat);
        while ((loop++ < 200) && (ret != 0)) {
                ret = cw_init(cw_bat);
        }

        if (ret) 
                return ret;
        
        cw_bat->rk_bat.name = "rk-bat";
        cw_bat->rk_bat.type = POWER_SUPPLY_TYPE_BATTERY;
        cw_bat->rk_bat.properties = rk_battery_properties;
        cw_bat->rk_bat.num_properties = ARRAY_SIZE(rk_battery_properties);
        cw_bat->rk_bat.get_property = rk_battery_get_property;
        ret = power_supply_register(&client->dev, &cw_bat->rk_bat);
        if(ret < 0) {
                dev_err(&cw_bat->client->dev, "power supply register rk_bat error\n");
                goto rk_bat_register_fail;
        }

        cw_bat->rk_ac.name = "rk-ac";
        cw_bat->rk_ac.type = POWER_SUPPLY_TYPE_MAINS;
        cw_bat->rk_ac.properties = rk_ac_properties;
        cw_bat->rk_ac.num_properties = ARRAY_SIZE(rk_ac_properties);
        cw_bat->rk_ac.get_property = rk_ac_get_property;
        ret = power_supply_register(&client->dev, &cw_bat->rk_ac);
        if(ret < 0) {
                dev_err(&cw_bat->client->dev, "power supply register rk_ac error\n");
                goto rk_ac_register_fail;
        }

        cw_bat->rk_usb.name = "rk-usb";
        cw_bat->rk_usb.type = POWER_SUPPLY_TYPE_USB;
        cw_bat->rk_usb.properties = rk_usb_properties;
        cw_bat->rk_usb.num_properties = ARRAY_SIZE(rk_usb_properties);
        cw_bat->rk_usb.get_property = rk_usb_get_property;
        ret = power_supply_register(&client->dev, &cw_bat->rk_usb);
        if(ret < 0) {
                dev_err(&cw_bat->client->dev, "power supply register rk_ac error\n");
                goto rk_usb_register_fail;
        }

        cw_bat->charger_init_mode = dwc_otg_check_dpdm();

        cw_bat->dc_online = 0;
        cw_bat->usb_online = 0;
        cw_bat->charger_mode = 0;
        cw_bat->capacity = 2;
        cw_bat->voltage = 0;
        cw_bat->status = 0;
        cw_bat->time_to_empty = 0;
        cw_bat->bat_change = 0;

        cw_update_time_member_capacity_change(cw_bat);
        cw_update_time_member_charge_start(cw_bat);

        cw_bat->battery_workqueue = create_singlethread_workqueue("rk_battery");
        INIT_DELAYED_WORK(&cw_bat->battery_delay_work, cw_bat_work);
        INIT_DELAYED_WORK(&cw_bat->dc_wakeup_work, dc_detect_do_wakeup);
        queue_delayed_work(cw_bat->battery_workqueue, &cw_bat->battery_delay_work, msecs_to_jiffies(10));
        
        if (cw_bat->plat_data->dc_det_pin != INVALID_GPIO) {
                irq = gpio_to_irq(cw_bat->plat_data->dc_det_pin);
                irq_flags = gpio_get_value(cw_bat->plat_data->dc_det_pin) ? IRQF_TRIGGER_FALLING : IRQF_TRIGGER_RISING;
                ret = request_irq(irq, dc_detect_irq_handler, irq_flags, "usb_detect", cw_bat);
                if (ret < 0) {
                        pr_err("%s: request_irq(%d) failed\n", __func__, irq);
                }
                enable_irq_wake(irq);
        }

#ifdef BAT_LOW_INTERRUPT
        INIT_DELAYED_WORK(&cw_bat->bat_low_wakeup_work, bat_low_detect_do_wakeup);
        wake_lock_init(&bat_low_wakelock, WAKE_LOCK_SUSPEND, "bat_low_detect");
        if (cw_bat->plat_data->bat_low_pin != INVALID_GPIO) {
                irq = gpio_to_irq(cw_bat->plat_data->bat_low_pin);
                ret = request_irq(irq, bat_low_detect_irq_handler, IRQF_TRIGGER_RISING, "bat_low_detect", cw_bat);
                if (ret < 0) {
                        gpio_free(cw_bat->plat_data->bat_low_pin);
                }
                enable_irq_wake(irq);
        }
#endif

        dev_info(&cw_bat->client->dev, "cw2015/cw2013 driver v1.2 probe sucess\n");
        return 0;

rk_usb_register_fail:
        power_supply_unregister(&cw_bat->rk_bat);
rk_ac_register_fail:
        power_supply_unregister(&cw_bat->rk_ac);
rk_bat_register_fail:
        dev_info(&cw_bat->client->dev, "cw2015/cw2013 driver v1.2 probe error!!!!\n");
        return ret;
}