static int __init tegra_sleep_info_init(void)
{
	/* Register callback from idle for all cpus */
	rq_wq = create_singlethread_workqueue("rq_stats");
	BUG_ON(!rq_wq);
	INIT_DELAYED_WORK_DEFERRABLE(&rq_info.rq_work, rq_work_fn);
	INIT_DELAYED_WORK_DEFERRABLE(&rq_info.def_timer_work, def_work_fn);
	init_rq_attribs();

	return 0;
}
static int __init msm_sleep_info_init(void)
{
	int err = 0;
	int cpu;
	struct sleep_data *sleep_info = NULL;

	/* Register callback from idle for all cpus */
	msm_idle_register_cb(idle_enter, idle_exit);
	rq_wq = create_singlethread_workqueue("rq_stats");
	BUG_ON(!rq_wq);
	INIT_DELAYED_WORK_DEFERRABLE(&rq_info.rq_work, rq_work_fn);
	INIT_DELAYED_WORK_DEFERRABLE(&rq_info.def_timer_work, def_work_fn);
	init_rq_attribs();

	for_each_possible_cpu(cpu) {
		printk(KERN_INFO "msm_sleep_stats: Initializing sleep stats "
				"for CPU[%d]\n", cpu);
		sleep_info = &per_cpu(core_sleep_info, cpu);
		sleep_info->cpu = cpu;
		INIT_WORK(&sleep_info->work, notify_uspace_work_fn);

		/* Initialize high resolution timer */
		hrtimer_init(&sleep_info->timer, CLOCK_MONOTONIC,
				HRTIMER_MODE_REL);
		sleep_info->timer.function = timer_func;

		/* Register for cpufreq policy changes */
		sleep_info->nb.notifier_call = policy_change_notifier;
		err = cpufreq_register_notifier(&sleep_info->nb,
					CPUFREQ_POLICY_NOTIFIER);
		if (err)
			goto cleanup;

		/* Create sysfs object */
		err = add_sysfs_objects(sleep_info);
		if (err)
			goto cleanup;

		continue;
cleanup:
		printk(KERN_INFO "msm_sleep_stats: Failed to initialize sleep "
				"stats for CPU[%d]\n", cpu);
		sleep_info->cpu = -1;
		cpufreq_unregister_notifier(&sleep_info->nb,
				CPUFREQ_POLICY_NOTIFIER);
		remove_sysfs_objects(sleep_info);
	}

	return 0;
}
/**
 * sr_class1p5_start() - class 1p5 init
 * @voltdm:		sr voltage domain
 * @class_priv_data:	private data for the class
 *
 * we do class specific initialization like creating sysfs/debugfs entries
 * needed, spawning of a kthread if needed etc.
 */
static int sr_class1p5_start(struct voltagedomain *voltdm,
			     void *class_priv_data)
{
	struct sr_class1p5_work_data *work_data;
	int idx;

	if (IS_ERR_OR_NULL(voltdm) || IS_ERR_OR_NULL(class_priv_data)) {
		pr_err("%s: bad parameters!\n", __func__);
		return -EINVAL;
	}

	/* setup our work params */
	work_data = get_sr1p5_work(voltdm);
	if (!IS_ERR_OR_NULL(work_data)) {
		pr_err("%s: ooopps.. class already initialized for %s! bug??\n",
		       __func__, voltdm->name);
		return -EINVAL;
	}
	work_data = NULL;
	/* get the next spare work_data */
	for (idx = 0; idx < MAX_VDDS; idx++) {
		if (!class_1p5_data.work_data[idx].voltdm) {
			work_data = &class_1p5_data.work_data[idx];
			break;
		}
	}
	if (!work_data) {
		pr_err("%s: no more space for work data for domains!\n",
			__func__);
		return -ENOMEM;
	}
	work_data->voltdm = voltdm;
	INIT_DELAYED_WORK_DEFERRABLE(&work_data->work, do_calibrate);
	return 0;
}
Пример #4
0
/**
 * sr_class1p5_driver_init() - register class 1p5 as default
 *
 * board files call this function to use class 1p5, we register with the
 * smartreflex subsystem
 */
static int __init sr_class1p5_driver_init(void)
{
	int r;

	/* Enable this class only for OMAP3630 and OMAP4 */
	if (!(cpu_is_omap3630() || cpu_is_omap44xx()))
		return -EINVAL;

	r = sr_register_class(&class1p5_data);
	if (r) {
		pr_err("SmartReflex class 1.5 driver: "
		       "failed to register with %d\n", r);
	} else {
#if CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY
		INIT_DELAYED_WORK_DEFERRABLE(&recal_work,
					     sr_class1p5_recal_work);
		schedule_delayed_work(&recal_work,
			      msecs_to_jiffies
			      (CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY));
#endif
		pr_info("SmartReflex class 1.5 driver: initialized (%dms)\n",
			CONFIG_OMAP_SR_CLASS1P5_RECALIBRATION_DELAY);
	}
	return r;
}
Пример #5
0
/**
 * sr_class1p5_init() - class 1p5 init
 * @voltdm:		sr voltage domain
 * @voltdm_cdata:	voltage domain specific private class data
 *			allocated by class init with work item data
 *			freed by deinit.
 * @class_priv_data:	private data for the class (unused)
 *
 * we do class specific initialization like creating sysfs/debugfs entries
 * needed, spawning of a kthread if needed etc.
 */
static int sr_class1p5_init(struct voltagedomain *voltdm,
			    void **voltdm_cdata, void *class_priv_data)
{
	struct sr_class1p5_work_data *work_data;

	if (IS_ERR_OR_NULL(voltdm) || IS_ERR_OR_NULL(voltdm_cdata)) {
		pr_err("%s: bad parameters!\n", __func__);
		return -EINVAL;
	}

	if (!IS_ERR_OR_NULL(*voltdm_cdata)) {
		pr_err("%s: ooopps.. class already initialized for %s! bug??\n",
		       __func__, voltdm->name);
		return -EINVAL;
	}
	/* setup our work params */
	work_data = kzalloc(sizeof(struct sr_class1p5_work_data), GFP_KERNEL);
	if (!work_data) {
		pr_err("%s: no memory to allocate work data on domain %s\n",
			__func__, voltdm->name);
		return -ENOMEM;
	}

	work_data->voltdm = voltdm;
	INIT_DELAYED_WORK_DEFERRABLE(&work_data->work, sr_class1p5_calib_work);
	*voltdm_cdata = (void *)work_data;

	return 0;
}
Пример #6
0
static __devinit int sec_therm_probe(struct platform_device *pdev)
{
	struct sec_therm_platform_data *pdata = dev_get_platdata(&pdev->dev);
	struct sec_therm_info *info;
	int ret = 0;

	dev_info(&pdev->dev, "%s: SEC Thermistor 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->padc = s3c_adc_register(pdev, NULL, NULL, 0);

	ret = sysfs_create_group(&info->dev->kobj, &sec_therm_group);

	if (ret) {
		dev_err(info->dev,
			"failed to create sysfs attribute group\n");
	}

	INIT_DELAYED_WORK_DEFERRABLE(&info->polling_work,
			sec_therm_polling_work);
	schedule_delayed_work(&info->polling_work,
			msecs_to_jiffies(info->pdata->polling_interval));

	return ret;
}
int __init init_display_devices(void)
{
	int ret;

	ret = fb_register_client(&framebuffer_nb);
	if (ret)
		pr_warning("Failed to register framebuffer notifier\n");

	ret = mcde_dss_register_notifier(&display_nb);
	if (ret)
		pr_warning("Failed to register dss notifier\n");

#ifdef CONFIG_DISPLAY_GENERIC_PRIMARY
	if (display_initialized_during_boot)
		generic_display0.power_mode = MCDE_DISPLAY_PM_STANDBY;
	ret = mcde_display_device_register(&generic_display0);
	if (ret)
		pr_warning("Failed to register generic display device 0\n");
#endif

#ifdef CONFIG_DISPLAY_AV8100_TERTIARY
	INIT_DELAYED_WORK_DEFERRABLE(&work_dispreg_hdmi,
			delayed_work_dispreg_hdmi);

	schedule_delayed_work(&work_dispreg_hdmi,
			msecs_to_jiffies(DISPREG_HDMI_DELAY));
#endif

	return ret;
}
Пример #8
0
/**
 * sr_classp5_init() - class p5 init
 * @sr:			SR to init
 * @class_priv_data:	private data for the class (unused)
 *
 * we do class specific initialization like creating sysfs/debugfs entries
 * needed, spawning of a kthread if needed etc.
 */
static int sr_classp5_init(struct omap_sr *sr, void *class_priv_data)
{
	void **voltdm_cdata = NULL;
	struct sr_classp5_calib_data *work_data = NULL;

	if (IS_ERR_OR_NULL(sr) || IS_ERR_OR_NULL(sr->voltdm)) {
		pr_err("%s: bad parameters!\n", __func__);
		return -EINVAL;
	}

	voltdm_cdata = &sr->voltdm_cdata;
	if (*voltdm_cdata) {
		pr_err("%s: ooopps.. class already initialized for %s! bug??\n",
		       __func__, sr->name);
		return -EINVAL;
	}

	/* setup our work params */
	work_data = kzalloc(sizeof(struct sr_classp5_calib_data), GFP_KERNEL);
	if (!work_data) {
		pr_err("%s: no memory to allocate work data on domain %s\n",
		       __func__, sr->name);
		return -ENOMEM;
	}

	work_data->sr = sr;

	INIT_DELAYED_WORK_DEFERRABLE(&work_data->work, sr_classp5_calib_work);
	*voltdm_cdata = (void *)work_data;
	pm_qos_add_request(&work_data->qos, PM_QOS_CPU_DMA_LATENCY,
			   PM_QOS_DEFAULT_VALUE);

	return 0;
}
int omap4_dpll_low_power_cascade_check_entry()
{
	int delay = usecs_to_jiffies(LP_DELAY);

	INIT_DELAYED_WORK_DEFERRABLE(&lpmode_work,
			omap4_dpll_low_power_cascade_check_timer);

	return schedule_delayed_work_on(0, &lpmode_work, delay);
}
/***********************************************************
*调频任务初始化
***********************************************************/
static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
{
    /* We want all CPUs to do sampling nearly on same jiffy */
    unsigned long delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
    if (NULL == dbs_info) {
        cpufreq_err("!!!!!!dbs_timer_init!!!!!!error\n");
        return;
    }

    INIT_DELAYED_WORK_DEFERRABLE(&(dbs_info->work), balong_do_dbs_timer);/*lint !e613*/
    schedule_delayed_work_on(dbs_info->cpu, &(dbs_info->work), delay);/*lint !e613*/
}
Пример #11
0
bool sec_hal_fg_init(struct i2c_client *client)
{
	struct sec_fuelgauge_info *fuelgauge =
			i2c_get_clientdata(client);

	mutex_init(&fuelgauge->info.adclock);
	INIT_DELAYED_WORK_DEFERRABLE(&fuelgauge->info.monitor_work,
		adc_monitor_work);

	schedule_delayed_work(&fuelgauge->info.monitor_work, HZ);
	return true;
}
Пример #12
0
void  mlx4_sense_init(struct mlx4_dev *dev)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_sense *sense = &priv->sense;
	int port;

	sense->dev = dev;
	for (port = 1; port <= dev->caps.num_ports; port++)
		sense->do_sense_port[port] = 1;

	INIT_DELAYED_WORK_DEFERRABLE(&sense->sense_poll, mlx4_sense_port);
}
Пример #13
0
static int __devinit smb347_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
	int ret, irq_num, i;
	uint8_t val, buf[15];

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

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

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

	/* Restore default setting: APSD Enable & 5/1/HC mode Pin control */
	smb347_default_setback();

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

	mutex_init(&charger->cable_lock);

	smb347_wq = create_singlethread_workqueue("smb347_wq");
	INIT_DELAYED_WORK_DEFERRABLE(&charger->inok_isr_work, inok_isr_work_function);
	//INIT_DELAYED_WORK(&charger->regs_dump_work, regs_dump_work_func);

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

	//queue_delayed_work(smb347_wq, &charger->regs_dump_work, 30*HZ);

	cable_type_detect();

	ret = register_otg_callback( (callback_t)smb347_otg_status, charger);

	if (ret < 0)
		goto error;

	return 0;
error:
	kfree(charger);
	return ret;
}
static int __init init_rq_avg(void)
{
	rq_data = kzalloc(sizeof(struct runqueue_data), GFP_KERNEL);
	if (rq_data == NULL) {
		pr_err("%s cannot allocate memory\n", __func__);
		return -ENOMEM;
	}
	spin_lock_init(&rq_data->lock);
	rq_data->update_rate = RQ_AVG_TIMER_RATE;
	INIT_DELAYED_WORK_DEFERRABLE(&rq_data->work, rq_work_fn);

	return 0;
}
Пример #15
0
static __devinit int wm831x_backup_probe(struct platform_device *pdev)
{
	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
	struct wm831x_backup *devdata;
	struct power_supply *backup;
	int ret;
	int irq = gpio_to_irq(MX53_SMD_DC_DET);

	devdata = kzalloc(sizeof(struct wm831x_backup), GFP_KERNEL);
	if (devdata == NULL)
		return -ENOMEM;

	devdata->wm831x = wm831x;
	platform_set_drvdata(pdev, devdata);

	backup = &devdata->backup;

	/* We ignore configuration failures since we can still read
	 * back the status without enabling the charger (which may
	 * already be enabled anyway).
	 */
	wm831x_config_backup(wm831x);

	backup->name = "wm831x-backup";
	backup->type = POWER_SUPPLY_TYPE_BATTERY;
	backup->properties = wm831x_backup_props;
	backup->num_properties = ARRAY_SIZE(wm831x_backup_props);
	backup->get_property = wm831x_backup_get_prop;
	ret = power_supply_register(&pdev->dev, backup);
	if (ret)
		goto err_kmalloc;

	wm831x_update_status(irq, devdata);
	wm831x_get_cap(devdata);

	INIT_DELAYED_WORK_DEFERRABLE(&devdata->work, wm831x_work);
	schedule_delayed_work(&devdata->work, WM831X_DELAY);

	ret = request_irq(irq, wm831x_update_status, IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, backup->name, devdata);
	if (ret != 0) {
		free_irq(irq, devdata);
		printk("request irq fail\n");
	}

	return ret;

err_kmalloc:
	kfree(devdata);
	return ret;
}
Пример #16
0
static void sr_classp5_recal_init(void)
{
	unsigned long delay;
	INIT_DELAYED_WORK_DEFERRABLE(&recal_work, sr_classp5_recal_work);
	pm_qos_add_request(&recal_qos, PM_QOS_CPU_DMA_LATENCY,
			   PM_QOS_DEFAULT_VALUE);
	delay = msecs_to_jiffies(CONFIG_OMAP_SR_CLASS1_P5_RECALIBRATION_DELAY);
	schedule_delayed_work(&recal_work, delay);
	next_recal_time = jiffies + delay;
	sr_classp5_recal_register_sleep_pm_notifier();
	recal_scheduled = true;
	pr_info("SmartReflex Recalibration delay = %dms\n",
		CONFIG_OMAP_SR_CLASS1_P5_RECALIBRATION_DELAY);
}
Пример #17
0
int user_init_device(struct fb_info *fb_info)
{
	int i, error = 0;
	struct omap3epfb_par *par = fb_info->par;

	fb_info->class_flag |= FB_SYSFS_FLAG_ATTR;

	mutex_init(&par->area_mutex);

	for (i = 0; i < ARRAY_SIZE(device_attrs); i++) {
		error = device_create_file(fb_info->dev, &device_attrs[i]);

		if (error)
			break;
	}

	if (error) {
		while (--i >= 0)
			device_remove_file(fb_info->dev, &device_attrs[i]);
		fb_info->class_flag &= ~FB_SYSFS_FLAG_ATTR;
	}
	INIT_DELAYED_WORK_DEFERRABLE(&par->lost_update, omap3epfb_lost_update);
	INIT_DELAYED_WORK_DEFERRABLE(&par->clear_work, omap3epfb_clear_work);
	INIT_DELAYED_WORK_DEFERRABLE(&par->disable_work, omap3epfb_disable_work);

	// Start with page flip mode active.
	par->pgflip_refresh = 1;

	// Disabled as default.
	par->clear_delay = 0;

	par->effect_active = 0;
	strncpy(par->effect_active_debug, "--------", EFFECT_ARRAY_SIZE);
	par->effect_active_debug[EFFECT_ARRAY_SIZE] = 0;

	return 0;
}
Пример #18
0
static int __init auto_hotplug_init(void)
{
        pr_info("auto_hotplug: v0.220 by _thalamus\n");
        pr_info("auto_hotplug: %d CPUs detected\n", CPUS_AVAILABLE);

        INIT_DELAYED_WORK(&hotplug_decision_work, hotplug_decision_work_fn);
        INIT_DELAYED_WORK_DEFERRABLE(&hotplug_unpause_work, hotplug_unpause_work_fn);
        INIT_WORK(&hotplug_online_all_work, hotplug_online_all_work_fn);
        INIT_WORK(&hotplug_online_single_work, hotplug_online_single_work_fn);
        INIT_WORK(&hotplug_offline_all_work, hotplug_offline_all_work_fn);
        INIT_DELAYED_WORK_DEFERRABLE(&hotplug_offline_work, hotplug_offline_work_fn);

        /*
         * Give the system time to boot before fiddling with hotplugging.
         */
        flags |= HOTPLUG_PAUSED;
        schedule_delayed_work_on(0, &hotplug_decision_work, HZ * 5);
        schedule_delayed_work(&hotplug_unpause_work, HZ * 10);

#ifdef CONFIG_HAS_EARLYSUSPEND
        register_early_suspend(&auto_hotplug_suspend);
#endif
        return 0;
}
Пример #19
0
bool sec_hal_fg_init(struct i2c_client *client)
{
	struct sec_fuelgauge_info *fuelgauge =
			i2c_get_clientdata(client);

	fuelgauge->info.last_vcell_check_time.tv_sec = 0;
	fuelgauge->info.is_init = 2;
	adc_get_reset_percentage(fuelgauge);

	mutex_init(&fuelgauge->info.adclock);
	INIT_DELAYED_WORK_DEFERRABLE(&fuelgauge->info.monitor_work,
		adc_monitor_work);

	schedule_delayed_work(&fuelgauge->info.monitor_work, HZ);
	return true;
}
Пример #20
0
int hardlimit_init(void)
{
#ifdef CPUFREQ_HARDLIMIT_LEGACY_INTERFACE
	int legacy_hardlimit_retval;
#endif
	int hardlimit_retval;

	/* Enable the legacy sysfs interface */
#ifdef CPUFREQ_HARDLIMIT_LEGACY_INTERFACE
        legacy_hardlimit_kobj = kobject_create_and_add("cpufreq", kernel_kobj);
        if (!legacy_hardlimit_kobj) {
                return -ENOMEM;
        }
        legacy_hardlimit_retval = sysfs_create_group(legacy_hardlimit_kobj, &legacy_hardlimit_attr_group);
        if (legacy_hardlimit_retval)
                kobject_put(legacy_hardlimit_kobj);
#endif

	/* Enable the new sysfs interface */

        hardlimit_kobj = kobject_create_and_add("cpufreq_hardlimit", kernel_kobj);
        if (!hardlimit_kobj) {
                return -ENOMEM;
        }
        hardlimit_retval = sysfs_create_group(hardlimit_kobj, &hardlimit_attr_group);
        if (hardlimit_retval)
                kobject_put(hardlimit_kobj);

#ifdef CPUFREQ_HARDLIMIT_LEGACY_INTERFACE
        if (!hardlimit_retval && !legacy_hardlimit_retval) {
#else
        if (!hardlimit_retval) {
#endif
		/* Only register to powersuspend and delayed work if we were able to create the sysfs interface */
		register_power_suspend(&cpufreq_hardlimit_suspend_data);
		INIT_DELAYED_WORK_DEFERRABLE(&stop_wakeup_kick_work, stop_wakeup_kick);
	}

        return (hardlimit_retval);
}
/* end sysfs interface */

void hardlimit_exit(void)
{
	unregister_power_suspend(&cpufreq_hardlimit_suspend_data);
	kobject_put(hardlimit_kobj);
}
static __devinit int sec_therm_probe(struct platform_device *pdev)
{
	int ret = 0;
	struct sec_therm_platform_data *pdata = fill_therm_pdata(pdev);
	struct sec_therm_info *info;

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

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

	info->dev = &pdev->dev;
	info->pdata = pdata;
	info->vadc_dev = qpnp_get_vadc(info->dev, "therm");
	therm_vadc_dev = info->vadc_dev;
	if (IS_ERR(info->vadc_dev)) {
		ret = PTR_ERR(info->vadc_dev);
		pr_err("%s:ret=%d\n",__func__,ret);
			if (ret != -EPROBE_DEFER)
				pr_err("vadc property missing\n");
			else
				goto err_therm;
	}

	dev_set_drvdata(&pdev->dev, info);

	ret = sysfs_create_group(&info->dev->kobj, &sec_therm_group);
	if (ret) {
		dev_err(info->dev,
			"failed to create sysfs attribute group\n");
	}

	if (!(pdata->no_polling)) {
		INIT_DELAYED_WORK_DEFERRABLE(&info->polling_work,
			sec_therm_polling_work);
		schedule_delayed_work(&info->polling_work,
			msecs_to_jiffies(info->pdata->polling_interval));
	}

	return ret;

err_therm:
	kfree(info);
	return ret;
}
Пример #22
0
int mlx4_sense_init(struct mlx4_dev *dev)
{
	struct mlx4_priv *priv = mlx4_priv(dev);
	struct mlx4_sense *sense = &priv->sense;
	int port;

	sense->dev = dev;
	sense->sense_wq = create_singlethread_workqueue("mlx4_sense");
	if (!sense->sense_wq)
		return -ENOMEM;

	for (port = 1; port <= dev->caps.num_ports; port++)
		sense->do_sense_port[port] = 1;

	INIT_DELAYED_WORK_DEFERRABLE(&sense->sense_poll, mlx4_sense_port);
	return 0;
}
Пример #23
0
static int __init pantech_debug_opt_init(void)
{
	int	rc;

	printk(KERN_ERR "%s is called\n", __func__);

	rc = platform_driver_register(&pantech_debug_opt_driver);
	if (rc < 0) {
		printk(KERN_ERR "%s: platform_driver_register rc = %d\n",
			__func__, rc);
	}

	INIT_DELAYED_WORK_DEFERRABLE(&pantech_debug_work, pantech_debug_work_init);
	schedule_delayed_work(&pantech_debug_work, 700);

	return	rc;
}
Пример #24
0
/*
	To create a bunch of /sys entries for DFMS application. We need a dummy power supply so we can have an entry /sys/class/power_supply 
	without breaking all the for_each_class calls in the rest of the charging.
	We also attach a dummy device to the sec device class device can be part of the /sys/devices/virtual/sec path 

*/
int make_dfms_battery_device (void)
{
	charger_extra_sysfs.polling_queue = create_singlethread_workqueue("ab8500_charging_monitor");
	INIT_DELAYED_WORK_DEFERRABLE(&charger_extra_sysfs.polling_work,ab8500_charger_polling_periodic_work);
	charger_extra_sysfs.btemp_psy.name = "battery";
	charger_extra_sysfs.btemp_psy.type = POWER_SUPPLY_TYPE_BATTERY;
	charger_extra_sysfs.btemp_psy.properties = ab8500_battery_props;
	charger_extra_sysfs.btemp_psy.num_properties = ARRAY_SIZE(ab8500_battery_props);
	charger_extra_sysfs.btemp_psy.get_property = battery_get_property;
	charger_extra_sysfs.btemp_psy.supplied_to = ab8500_battery_supplied_to;
	charger_extra_sysfs.btemp_psy.num_supplicants = ARRAY_SIZE(ab8500_battery_supplied_to);
	charger_extra_sysfs.btemp_psy.external_power_changed =battery_power_changed;
	power_supply_register( NULL, &charger_extra_sysfs.btemp_psy) ;
	add_adc_attributes(charger_extra_sysfs.btemp_psy.dev ) ;
	add_average_attributes(charger_extra_sysfs.btemp_psy.dev ) ;
	add_misc_attributes(charger_extra_sysfs.btemp_psy.dev);
	add_callback_attributes(charger_extra_sysfs.btemp_psy.dev);
	add_power_supply_attributes(charger_extra_sysfs.btemp_psy.dev );
	return 0 ;
}
/*******************************
* kernel module init function
********************************/
static int __init mt_hotplug_mechanism_init(void)
{
    struct proc_dir_entry *entry = NULL;
    struct proc_dir_entry *mt_hotplug_dir = NULL;
    
    HOTPLUG_INFO("mt_hotplug_mechanism_init");
    
    mt_hotplug_dir = proc_mkdir("mt_hotplug", NULL);
    if (!mt_hotplug_dir)
    {
        HOTPLUG_INFO("mkdir /proc/mt_hotplug failed");
    }
    else
    {
        entry = create_proc_entry("test0", S_IRUGO | S_IWUSR, mt_hotplug_dir);
        if (entry)
        {
            entry->read_proc = mt_hotplug_mechanism_read_test0;
            entry->write_proc = mt_hotplug_mechanism_write_test0;
        }
        entry = create_proc_entry("test1", S_IRUGO | S_IWUSR, mt_hotplug_dir);
        if (entry)
        {
            entry->read_proc = mt_hotplug_mechanism_read_test1;
            entry->write_proc = mt_hotplug_mechanism_write_test1;
        }
    }
    
#ifdef CONFIG_HAS_EARLYSUSPEND
    mt_hotplug_mechanism_early_suspend_handler.suspend = mt_hotplug_mechanism_early_suspend;
    mt_hotplug_mechanism_early_suspend_handler.resume = mt_hotplug_mechanism_late_resume;
    register_early_suspend(&mt_hotplug_mechanism_early_suspend_handler);
    INIT_DELAYED_WORK_DEFERRABLE(&hotplug_delayed_work, hotplug_delayed_work_handler);
    wake_lock_init(&hotplug_wake_lock, WAKE_LOCK_SUSPEND, "hotplug");
#endif //#ifdef CONFIG_HAS_EARLYSUSPEND

    return 0;
}
Пример #26
0
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;
	int ret;
	u8 i2c_data[2];
	int rawsoc, firstsoc;
	pr_info("%s: max17047 Fuel gauge Driver Loading\n", __func__);

	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 = client->dev.platform_data;

	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");

	/* 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";

	fg_data->fuelgauge.type = POWER_SUPPLY_TYPE_BATTERY;
	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);

	/* 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;
	}

	INIT_DELAYED_WORK_DEFERRABLE(&fg_data->update_work,
					max17047_update_work);
#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

	max17047_i2c_read(client, MAX17047_REG_VERSION, i2c_data);
	pr_info("max17047 fuelgauge(rev.%d%d) initialized.\n", i2c_data[0], i2c_data[1]);

#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;
}
Пример #27
0
static int __init rmnet_init(void)
{
	int ret;
	struct device *d;
	struct net_device *dev;
	struct rmnet_private *p;
	unsigned n;

#ifdef CONFIG_MSM_RMNET_DEBUG
	timeout_us = 0;
#ifdef CONFIG_HAS_EARLYSUSPEND
	timeout_suspend_us = 0;
#endif
#endif

#ifdef CONFIG_MSM_RMNET_DEBUG
	rmnet_wq = create_workqueue("rmnet");
#endif

	for (n = 0; n < 3; n++) {
		dev = alloc_netdev(sizeof(struct rmnet_private),
				   "rmnet%d", rmnet_setup);

		if (!dev)
			return -ENOMEM;

		d = &(dev->dev);
		p = netdev_priv(dev);
		p->chname = ch_name[n];
		wake_lock_init(&p->wake_lock, WAKE_LOCK_SUSPEND, ch_name[n]);
#ifdef CONFIG_MSM_RMNET_DEBUG
		p->timeout_us = timeout_us;
		p->awake_time_ms = p->wakeups_xmit = p->wakeups_rcv = 0;
		p->active_countdown = p->restart_count = 0;
		INIT_DELAYED_WORK_DEFERRABLE(&p->work, do_check_active);
#endif

		ret = register_netdev(dev);
		if (ret) {
			free_netdev(dev);
			return ret;
		}

#ifdef CONFIG_MSM_RMNET_DEBUG
		if (device_create_file(d, &dev_attr_timeout))
			continue;
		if (device_create_file(d, &dev_attr_wakeups_xmit))
			continue;
		if (device_create_file(d, &dev_attr_wakeups_rcv))
			continue;
		if (device_create_file(d, &dev_attr_awake_time_ms))
			continue;
#ifdef CONFIG_HAS_EARLYSUSPEND
		if (device_create_file(d, &dev_attr_timeout_suspend))
			continue;

		/* Only care about rmnet0 for suspend/resume tiemout hooks. */
		if (n == 0)
			rmnet0 = d;
#endif
#endif
	}
	return 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;
	bool fuelalert_init_ret = false;
	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;
	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) {
		fuelalert_init_ret =
			sec_hal_fg_fuelalert_init(fuelgauge->client,
					fuelgauge->pdata->fuel_alert_soc);
		if (fuelalert_init_ret)
			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);
	if (fuelalert_init_ret)
	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;
}
static irqreturn_t tmu_irq(int irq, void *id)
{
	struct tmu_info *info = id;
	unsigned int status;

	disable_irq_nosync(irq);

	status = __raw_readl(info->tmu_base + INTSTAT);

	/* To handle multiple interrupt pending,
	* interrupt by high temperature are serviced with priority.
	*/

#if defined(CONFIG_TC_VOLTAGE)
	if (status & INTSTAT_FALL0) {
		pr_info("TC interrupt occured..!\n");
		__raw_writel(INTCLEAR_FALL0, info->tmu_base + INTCLEAR);
		info->tmu_state = TMU_STATUS_TC;
	} else if (status & INTSTAT_RISE2) {
#else
	if (status & INTSTAT_RISE2) {
#endif
		pr_info("Tripping interrupt occured..!\n");
		info->tmu_state = TMU_STATUS_TRIPPED;
		__raw_writel(INTCLEAR_RISE2, info->tmu_base + INTCLEAR);
	} else if (status & INTSTAT_RISE1) {
		pr_info("Warning interrupt occured..!\n");
		__raw_writel(INTCLEAR_RISE1, info->tmu_base + INTCLEAR);
		info->tmu_state = TMU_STATUS_WARNING;
	} else if (status & INTSTAT_RISE0) {
		pr_info("Throttling interrupt occured..!\n");
		__raw_writel(INTCLEAR_RISE0, info->tmu_base + INTCLEAR);
		info->tmu_state = TMU_STATUS_THROTTLED;
	} else {
		pr_err("%s: TMU interrupt error\n", __func__);
		return -ENODEV;
	}

	queue_delayed_work_on(0, tmu_monitor_wq,
			&info->polling, usecs_to_jiffies(1 * 1000));
	return IRQ_HANDLED;
}

static irqreturn_t exynos4210_tmu_irq(int irq, void *id)
{
	struct tmu_info *info = id;
	unsigned int status;

	disable_irq_nosync(irq);

	status = __raw_readl(info->tmu_base + INTSTAT);

	if (status & INTSTAT2) {
		pr_info("Tripping interrupt occured..!\n");
		info->tmu_state = TMU_STATUS_TRIPPED;
		__raw_writel(INTCLEAR2, info->tmu_base + INTCLEAR);
	} else if (status & INTSTAT1) {
		pr_info("Warning interrupt occured..!\n");
		__raw_writel(INTCLEAR1, info->tmu_base + INTCLEAR);
		info->tmu_state = TMU_STATUS_WARNING;
	} else if (status & INTSTAT0) {
		pr_info("Throttling interrupt occured..!\n");
		__raw_writel(INTCLEAR0, info->tmu_base + INTCLEAR);
		info->tmu_state = TMU_STATUS_THROTTLED;
	} else {
		pr_err("%s: TMU interrupt error\n", __func__);
		return -ENODEV;
	}

	queue_delayed_work_on(0, tmu_monitor_wq,
			&info->polling, usecs_to_jiffies(1000));
	return IRQ_HANDLED;
}

static int __devinit tmu_probe(struct platform_device *pdev)
{
	struct tmu_info *info;
	struct resource *res;
	int	ret = 0;

	pr_debug("%s: probe=%p\n", __func__, pdev);

	info = kzalloc(sizeof(struct tmu_info), GFP_KERNEL);
	if (!info) {
		dev_err(&pdev->dev, "failed to alloc memory!\n");
		ret = -ENOMEM;
		goto err_nomem;
	}
	pr_emerg("TMU: Memory Allocation Sucessful\n");
	
	platform_set_drvdata(pdev, info);
	pr_emerg("TMU: Platform data set\n");
	
	info->dev = &pdev->dev;
	pr_emerg("TMU: Copied the Dev access Information \n");
	
	info->irq = platform_get_irq(pdev, 0);
	if (info->irq < 0) {
		dev_err(&pdev->dev, "no irq for thermal\n");
		ret = -ENOENT;
		goto err_noirq;
	}
	if (soc_is_exynos4210())
		ret = request_irq(info->irq, exynos4210_tmu_irq,
				IRQF_DISABLED,  "tmu interrupt", info);
	else
		ret = request_irq(info->irq, tmu_irq,
				IRQF_DISABLED,  "tmu interrupt", info);
	if (ret) {
		dev_err(&pdev->dev, "IRQ%d error %d\n", info->irq, ret);
		goto err_noirq;
	}
	pr_emerg("TMU: IRQ Granted!\n");
	
	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	if (res == NULL) {
		dev_err(&pdev->dev, "failed to get memory region resource\n");
		ret = -ENODEV;
		goto err_nores;
	}
	pr_emerg("TMU: IO Resource alloced on Memory\n");
	
	info->ioarea = request_mem_region(res->start,
			res->end-res->start+1, pdev->name);
	if (!(info->ioarea)) {
		dev_err(&pdev->dev, "failed to reserve memory region\n");
		ret = -EBUSY;
		goto err_nores;
	}
	pr_emerg("TMU: Memory area resersed\n");
	
	info->tmu_base = ioremap(res->start, (res->end - res->start) + 1);
	if (!(info->tmu_base)) {
		dev_err(&pdev->dev, "failed ioremap()\n");
		ret = -EINVAL;
		goto err_nomap;
	}
	pr_emerg("TMU: IO Memory Remapped\n");
	
	if (thermal_create_sysfs_file(&pdev->dev))
		goto err_sysfs;

	pr_emerg("TMU: Created Sysfs\n");
	
	tmu_monitor_wq = create_freezable_workqueue("tmu");
	if (!tmu_monitor_wq) {
		dev_err(&pdev->dev, "Creation of tmu_monitor_wq failed\n");
		ret = -EFAULT;
		goto err_wq;
	}
	pr_emerg("TMU: Workqueue Created\n");
	
	INIT_DELAYED_WORK_DEFERRABLE(&info->polling, tmu_monitor);
	pr_emerg("TMU: Work Created\n");
#ifdef CONFIG_TMU_DEBUG
	INIT_DELAYED_WORK_DEFERRABLE(&info->monitor, cur_temp_monitor);
#endif

	print_temperature_params(info);
	pr_emerg("TMU: Printed Parameters\n");
	
	ret = tmu_initialize(pdev);
	if (ret < 0)
		goto err_noinit;

#ifdef CONFIG_TMU_DEBUG
	queue_delayed_work_on(0, tmu_monitor_wq,
			&info->monitor, info->sampling_rate);
#endif
	pr_info("Tmu Initialization is sucessful...!\n");
	return ret;

err_noinit:
	destroy_workqueue(tmu_monitor_wq);
err_wq:
	thermal_remove_sysfs_file(&pdev->dev);
err_sysfs:
	iounmap(info->tmu_base);
err_nomap:
	release_resource(info->ioarea);
err_nores:
	free_irq(info->irq, info);
err_noirq:
	kfree(info);
	info = NULL;
err_nomem:
	dev_err(&pdev->dev, "initialization failed.\n");
	return ret;
}

static int __devinit tmu_remove(struct platform_device *pdev)
{
	struct tmu_info *info = platform_get_drvdata(pdev);

	cancel_delayed_work(&info->polling);
	destroy_workqueue(tmu_monitor_wq);

	thermal_remove_sysfs_file(&pdev->dev);

	iounmap(info->tmu_base);
	release_resource(info->ioarea);

	free_irq(info->irq, (void *)pdev);

	kfree(info);
	info = NULL;

	pr_info("%s is removed\n", dev_name(&pdev->dev));
	return 0;
}

#ifdef CONFIG_PM
static int tmu_suspend(struct platform_device *pdev, pm_message_t state)
{
	struct tmu_info *info = platform_get_drvdata(pdev);
	pm_tmu_save(info);

	return 0;
}

static int tmu_resume(struct platform_device *pdev)
{
	struct tmu_info *info = platform_get_drvdata(pdev);
#if defined(CONFIG_TC_VOLTAGE)
	struct tmu_data *data = info->dev->platform_data;
#endif
	pm_tmu_restore(info);

#if defined(CONFIG_TC_VOLTAGE)
	/* s/w workaround for fast service when interrupt is not occured,
	* such as current temp is lower than tc interrupt temperature
	* or current temp is continuosly increased.
	*/
	mdelay(1);
	if (get_cur_temp(info) <= data->ts.start_tc) {
		disable_irq_nosync(info->irq);
		if (exynos_tc_volt(info, 1) < 0)
			pr_err("%s\n", __func__);

		info->tmu_state = TMU_STATUS_TC;
		already_limit = 1;
		queue_delayed_work_on(0, tmu_monitor_wq,
				&info->polling, usecs_to_jiffies(1 * 1000));
	}
#endif
	return 0;
}

#else
#define tmu_suspend	NULL
#define tmu_resume	NULL
#endif

static struct platform_driver tmu_driver = {
	.probe		= tmu_probe,
	.remove		= tmu_remove,
	.suspend	= tmu_suspend,
	.resume		= tmu_resume,
	.driver		= {
		.name	=	"tmu",
		.owner	=	THIS_MODULE,
		},
};

static int __init tmu_driver_init(void)
{
	return platform_driver_register(&tmu_driver);
}

late_initcall(tmu_driver_init);
Пример #30
0
static __devinit int max8903_probe(struct platform_device *pdev)
{
	struct max8903_data *data;
	struct max8903_data *ac_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 error;

	data = kzalloc(sizeof(struct max8903_data), GFP_KERNEL);
	if (data == NULL) {
		dev_err(dev, "Cannot allocate memory.\n");
		return -ENOMEM;
	}
	data->pdata = pdata;
	data->dev = dev;
	platform_set_drvdata(pdev, data);

	if (pdata->dc_valid == false && pdata->usb_valid == false) {
		dev_err(dev, "No valid power sources.\n");
		ret = -EINVAL;
		goto err;
	}

	if (pdata->dc_valid) {
		if (pdata->dok && gpio_is_valid(pdata->dok) &&
				pdata->dcm && gpio_is_valid(pdata->dcm)) {
			gpio = pdata->dok; /* PULL_UPed Interrupt */
			ta_in = gpio_get_value(gpio) ? 0 : 1;

			gpio = pdata->dcm; /* Output */
			gpio_set_value(gpio, ta_in);
		} else if (pdata->dok && gpio_is_valid(pdata->dok) &&
			   pdata->dcm_always_high) {
			gpio = pdata->dok; /* PULL_UPed Interrupt */

			error = gpio_request(gpio, "chg_dc");
			if (error < 0) {
				dev_err(dev, "failed to configure"
					" request/direction for GPIO %d, error %d\n",
					gpio, error);
				goto err;
			}
			gpio_direction_input(gpio);

			ta_in = gpio_get_value(gpio) ? 0 : 1;

			if (ta_in)
				data->ta_in = true;
			else
				data->ta_in = false;
		} 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;
		}
	} else {
		if (pdata->dcm) {
			if (gpio_is_valid(pdata->dcm))
				gpio_set_value(pdata->dcm, 0);
			else {
				dev_err(dev, "Invalid pin: dcm.\n");
				ret = -EINVAL;
				goto err;
			}
		}
	}

	if (pdata->usb_valid) {
		if (pdata->uok && gpio_is_valid(pdata->uok)) {
			gpio = pdata->uok;
			error = gpio_request(gpio, "chg_usb");
			if (error < 0) {
				dev_err(dev, "failed to configure"
					" request/direction for GPIO %d, error %d\n",
					gpio, error);
				goto err;
			}

			gpio_direction_input(gpio);
			usb_in = gpio_get_value(gpio) ? 0 : 1;
			if (usb_in)
				data->usb_in = true;
			else
				data->usb_in = false;
		} else {
			dev_err(dev, "When USB is wired, UOK should be wired."
					"as well.\n");
			ret = -EINVAL;
			goto err;
		}
	}

	if (pdata->cen) {
		if (gpio_is_valid(pdata->cen)) {
			gpio_set_value(pdata->cen, (ta_in || usb_in) ? 0 : 1);
		} else {
			dev_err(dev, "Invalid pin: cen.\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;
		}
		error = gpio_request(pdata->chg, "chg_status");
		if (error < 0) {
			dev_err(dev, "failed to configure"
				" request/direction for GPIO %d, error %d\n",
				pdata->chg, error);
			goto err;
		}
		error = 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;
		}
		error = gpio_request(pdata->flt, "chg_fault");
		if (error < 0) {
			dev_err(dev, "failed to configure"
				" request/direction for GPIO %d, error %d\n",
				pdata->flt, error);
			goto err;
		}
		error = 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;
		}
	}

	data->fault = false;
	data->ta_in = ta_in;
	data->usb_in = usb_in;

	data->acpsy.name = "max8903-ac";
	data->acpsy.type = POWER_SUPPLY_TYPE_MAINS;
	data->acpsy.get_property = max8903_get_ac_property;
	data->acpsy.properties = max8903_ac_props;
	data->acpsy.num_properties = ARRAY_SIZE(max8903_ac_props);

	ret = power_supply_register(dev, &data->acpsy);
	if (ret) {
		dev_err(dev, "failed: power supply register.\n");
		goto err;
	}

	data->psy.name = "max8903-charger";
	data->psy.type = POWER_SUPPLY_TYPE_BATTERY;
	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;
	}

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

	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_usb_irq;
		}
	}
	/* should remove this if capacity is supported */
	data->cap = 90;

	INIT_DELAYED_WORK_DEFERRABLE(&data->work, max8903_work);

	power_supply_changed(&data->psy);
	power_supply_changed(&data->acpsy);
	schedule_delayed_work(&data->work, MAX8903_DELAY);

	return 0;

err_usb_irq:
	if (pdata->usb_valid)
		free_irq(gpio_to_irq(pdata->uok), data);
err_dc_irq:
	if (pdata->dc_valid)
		free_irq(gpio_to_irq(pdata->dok), data);
err_psy:
	power_supply_unregister(&data->psy);
	power_supply_unregister(&data->acpsy);
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;
}