void initialize_temphumidity_factorytest(struct ssp_data *data)
{
	int ret;

	/* alloc platform device for adc client */
	data->pdev_pam_temp = platform_device_alloc("pam-temp-adc", -1);
	if (!data->pdev_pam_temp)
		pr_err("%s: could not allocation pam-temp-adc\n", __func__);

	data->adc_client = s3c_adc_register(data->pdev_pam_temp, NULL, NULL, 0);
	if (IS_ERR(data->adc_client))
		pr_err("%s, fail to register pam-temp-adc(%ld)\n",
			__func__, IS_ERR(data->adc_client));

	sensors_register(data->temphumidity_device,
		data, temphumidity_attrs, "temphumidity_sensor");

	data->shtc1_device.minor = MISC_DYNAMIC_MINOR;
	data->shtc1_device.name = "shtc1_sensor";
	data->shtc1_device.fops = &ssp_temphumidity_fops;

	ret = misc_register(&data->shtc1_device);
	if (ret < 0) {
		pr_err("register temphumidity misc device err(%d)", ret);
	}
}
void __init exynos5_manta_battery_init(void)
{
	int hw_rev = exynos5_manta_get_revision();

	charger_gpio_init();
	INIT_DELAYED_WORK(&redetect_work, redetect_work_proc);
	wake_lock_init(&manta_bat_chgdetect_wakelock, WAKE_LOCK_SUSPEND,
		       "manta-chgdetect");
	wake_lock_init(&manta_bat_redetect_wl, WAKE_LOCK_SUSPEND,
		       "manta-chgredetect");

	if (hw_rev >= MANTA_REV_DOGFOOD02) {
		s3c_gpio_cfgpin(GPIO_1WIRE_SLEEP, S3C_GPIO_OUTPUT);
		s3c_gpio_setpull(GPIO_1WIRE_SLEEP, S3C_GPIO_PULL_NONE);
		s5p_gpio_set_pd_cfg(GPIO_1WIRE_SLEEP, S5P_GPIO_PD_INPUT);
		s5p_gpio_set_pd_pull(GPIO_1WIRE_SLEEP,
				     S5P_GPIO_PD_UPDOWN_DISABLE);
		ds2483_pdata.slpz_gpio = GPIO_1WIRE_SLEEP;
	}

	i2c_register_board_info(2, i2c_devs2, ARRAY_SIZE(i2c_devs2));

	ta_adc_client =
		s3c_adc_register(&manta_bat_s3c_client_dev, NULL, NULL, 0);

	if (IS_ERR_OR_NULL(debugfs_create_file("manta-power", S_IRUGO, NULL,
					       NULL, &manta_power_debug_fops)))
		pr_err("failed to create manta-power debugfs entry\n");

	if (IS_ERR_OR_NULL(debugfs_create_file("manta-power-adc", S_IRUGO, NULL,
					       NULL,
					       &manta_power_adc_debug_fops)))
		pr_err("failed to create manta-power-adc debugfs entry\n");
}
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;
}
static bool sec_bat_adc_ap_init(struct platform_device *pdev)
{
	if (!adc_client) {
		adc_client = s3c_adc_register(pdev, NULL, NULL, 0);
		if (IS_ERR(adc_client))
			pr_err("ADC READ ERROR");
		else
			pr_info("%s: sec_bat_adc_ap_init succeed\n", __func__);
	}
	return true;
}
static int __devinit mixtile_adc_bat_probe(struct platform_device *pdev)
{
  int i;
  int ret = 0;
  struct s3c_adc_client	*client;

  dev = &pdev->dev;
  dev_info(dev, "%s\n", __func__);

  client = s3c_adc_register(pdev, NULL, NULL, 0);
	if (IS_ERR(client)) {
		dev_err(&pdev->dev, "cannot register adc\n");
		return PTR_ERR(client);
	}
  platform_set_drvdata(pdev, client);
  
  mixtile_adc_bat_info.client = client;
  mixtile_adc_bat_info.present = 1;

  mixtile_adc_bat_info.bat_info.batt_id = 0;
  mixtile_adc_bat_info.bat_info.batt_vol = 0;
  mixtile_adc_bat_info.bat_info.batt_vol_adc = 0;
  mixtile_adc_bat_info.bat_info.batt_vol_adc_cal = 0;
  mixtile_adc_bat_info.bat_info.batt_temp = 0;
  mixtile_adc_bat_info.bat_info.batt_temp_adc = 0;
  mixtile_adc_bat_info.bat_info.batt_temp_adc_cal = 0;
  mixtile_adc_bat_info.bat_info.batt_current = 0;
  mixtile_adc_bat_info.bat_info.level = 0;
  mixtile_adc_bat_info.bat_info.charging_source = CHARGER_BATTERY;
  mixtile_adc_bat_info.bat_info.charging_enabled = 0;
  mixtile_adc_bat_info.bat_info.batt_health = POWER_SUPPLY_HEALTH_GOOD;

  /* init power supplier framework */
  for (i = 0; i < ARRAY_SIZE(samsung_power_supplies); i++) {
    ret = power_supply_register(&pdev->dev, &samsung_power_supplies[i]);
    if (ret) {
      dev_err(dev, "Failed to register power supply %d,%d\n", i, ret);
      goto __end__;
    }
  }

  mixtile_adc_bat_create_attrs(samsung_power_supplies[CHARGER_BATTERY].dev);

  for(i=0; i<10; i++)
    adc_value[i] = 0;

  INIT_DELAYED_WORK(&bat_work, s3c_adc_bat_work);
  monitor_wqueue = create_singlethread_workqueue(dev_name(&pdev->dev));
  queue_delayed_work(monitor_wqueue, &bat_work, POLL_MSTIME);

__end__:
  return ret;
}
void __init exynos_slim8_charger_init(void)
{
	pr_info("%s: tab3 charger init\n", __func__);
	charger_gpio_init();

	platform_add_devices(sec_battery_devices,
		ARRAY_SIZE(sec_battery_devices));

	i2c_register_board_info(SEC_CHARGER_I2C_ID,
			sec_brdinfo_charger,
			ARRAY_SIZE(sec_brdinfo_charger));

	i2c_register_board_info(SEC_FUELGAUGE_I2C_ID,
                        sec_brdinfo_fuelgauge,
                        ARRAY_SIZE(sec_brdinfo_fuelgauge));

	temp_adc_client = s3c_adc_register(&sec_device_battery, NULL, NULL, 0);
}
static int __devinit exynos_adc_probe(struct platform_device *dev)
{
	int ret;

	mutex_init(&adcdev.lock);

	/* Register with the core ADC driver. */
	adcdev.client = s3c_adc_register(dev, NULL, NULL, 0);
	if (IS_ERR(adcdev.client)) {
		printk("tiny4412_adc: cannot register adc\n");
		ret = PTR_ERR(adcdev.client);
		goto err_mem;
	}

	ret = misc_register(&misc);

	printk(DEVICE_NAME"\tinitialized\n");

err_mem:
	return ret;
}
Beispiel #8
0
static int fl2440adc_open (struct inode * inodp, struct file * filp)
{
    unsigned int channel;
    struct s3c_adc_client * client;
    
    DPRINTK("File operations open...\n");

    if (filp->f_flags & O_NONBLOCK) // S3C_ADC 驱动中读取时有睡眠的可能, 所以不接受非阻塞的访问
        return -EINVAL;

    channel = MINOR(inodp->i_rdev);


    mutex_lock(&adc_dev.mutex);

    if (adc_dev.client[channel])
    {
        mutex_unlock(&adc_dev.mutex);
        return 0; // 用户空间有可能同一时间段有数个进程都在打开着这个设备
    }
    else
    {
        filp->private_data = (void *)channel;
    }

    client = s3c_adc_register(adc_dev.pltdev[channel], NULL, NULL, 0);
    if (IS_ERR(client))
    {
        DPRINTK("Get S3C ADC clietn failed...\n");
        adc_dev.client[channel] = NULL;
        mutex_unlock(&adc_dev.mutex);
        return PTR_ERR(client);
    }
    adc_dev.client[channel] = client;
    atomic_inc(&adc_dev.client_ref[channel]);
    mutex_unlock(&adc_dev.mutex);

    return 0;
}
Beispiel #9
0
static int instinctq_battery_probe(struct platform_device *pdev)
{
	struct s3c_adc_client	*client;
	struct instinctq_battery_pdata *pdata = pdev->dev.platform_data;
	struct instinctq_battery *bat;
	int ret, i, irq;

	/* Platform data is required */
	if (!pdata) {
		dev_err(&pdev->dev, "no platform data supplied\n");
		return -ENODEV;
	}

	/* Check GPIOs */
	if (!gpio_is_valid(pdata->gpio_pok)) {
		dev_err(&pdev->dev, "Invalid gpio pin for POK line\n");
		return -EINVAL;
	}

	if (!gpio_is_valid(pdata->gpio_chg)) {
		dev_err(&pdev->dev, "Invalid gpio pin for CHG line\n");
		return -EINVAL;
	}

	if (!gpio_is_valid(pdata->gpio_en)) {
		dev_err(&pdev->dev, "Invalid gpio pin for EN line\n");
		return -EINVAL;
	}

	if (!pdata->supply_detect_init) {
		dev_err(&pdev->dev, "Supply detection is required\n");
		return -EINVAL;
	}

	/* Register ADC client */
	client = s3c_adc_register(pdev, NULL, NULL, 0);
	if (IS_ERR(client)) {
		dev_err(&pdev->dev, "could not register adc\n");
		return PTR_ERR(client);
	}

	/* Allocate driver data */
	bat = kzalloc(sizeof(struct instinctq_battery), GFP_KERNEL);
	if (!bat) {
		dev_err(&pdev->dev, "could not allocate driver data\n");
		ret = -ENOMEM;
		goto err_free_adc;
	}

	/* Claim and setup GPIOs */
	ret = gpio_request(pdata->gpio_pok, dev_name(&pdev->dev));
	if (ret) {
		dev_err(&pdev->dev, "Failed to request POK pin: %d\n", ret);
		goto err_free;
	}

	ret = gpio_direction_input(pdata->gpio_pok);
	if (ret) {
		dev_err(&pdev->dev, "Failed to set POK to input: %d\n", ret);
		goto err_gpio_pok_free;
	}

	ret = gpio_request(pdata->gpio_chg, dev_name(&pdev->dev));
	if (ret) {
		dev_err(&pdev->dev, "Failed to request CHG pin: %d\n", ret);
		goto err_gpio_pok_free;
	}

	ret = gpio_direction_input(pdata->gpio_chg);
	if (ret) {
		dev_err(&pdev->dev, "Failed to set CHG to input: %d\n", ret);
		goto err_gpio_chg_free;
	}

	ret = gpio_request(pdata->gpio_en, dev_name(&pdev->dev));
	if (ret) {
		dev_err(&pdev->dev, "Failed to request EN pin: %d\n", ret);
		goto err_gpio_chg_free;
	}

	ret = gpio_direction_output(pdata->gpio_en, pdata->gpio_en_inverted);
	if (ret) {
		dev_err(&pdev->dev, "Failed to set EN to output: %d\n", ret);
		goto err_gpio_en_free;
	}

	platform_set_drvdata(pdev, bat);

	bat->dev = &pdev->dev;
	bat->client = client;
	bat->pdata = pdata;
	bat->status = POWER_SUPPLY_STATUS_DISCHARGING;
	bat->health = POWER_SUPPLY_HEALTH_GOOD;
	bat->supply = instinctq_BATTERY_NONE;
	bat->interval = BAT_POLL_INTERVAL;
	bat->calibration = pdata->calibration;

	ret = create_lookup_table(pdata->percent_lut,
				pdata->percent_lut_cnt, &bat->percent_lookup);
	if (ret) {
		dev_err(&pdev->dev, "could not get create percentage lookup table");
		goto err_gpio_en_free;
	}

	ret = create_lookup_table(pdata->volt_lut,
				pdata->volt_lut_cnt, &bat->volt_lookup);
	if (ret) {
		dev_err(&pdev->dev, "could not get create voltage lookup table");
		goto err_percent_free;
	}

	ret = create_lookup_table(pdata->temp_lut,
				pdata->temp_lut_cnt, &bat->temp_lookup);
	if (ret) {
		dev_err(&pdev->dev, "could not get create temperature lookup table");
		goto err_volt_free;
	}

	INIT_WORK(&bat->work, instinctq_battery_work);
	INIT_DELAYED_WORK(&bat->poll_work, instinctq_battery_poll);
	mutex_init(&bat->mutex);
#ifdef CONFIG_HAS_WAKELOCK
	wake_lock_init(&bat->wakelock, WAKE_LOCK_SUSPEND, "battery");
	wake_lock_init(&bat->chg_wakelock, WAKE_LOCK_SUSPEND, "charger");
	wake_lock_init(&bat->fault_wakelock,
					WAKE_LOCK_SUSPEND, "battery fault");
	wake_lock_init(&bat->suspend_lock, WAKE_LOCK_SUSPEND, "suspend_lock");
#endif
#ifdef CONFIG_RTC_INTF_ALARM
	alarm_init(&bat->alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
							instinctq_battery_alarm);
#endif
	/* Get some initial data for averaging */
	for (i = 0; i < NUM_SAMPLES; ++i) {
		int sample;
		/* Get a voltage sample from the ADC */
		sample = instinctq_battery_adc_read(bat->client, bat->pdata->volt_channel);
		if (sample < 0) {
			dev_warn(&pdev->dev, "Failed to get ADC sample.\n");
			continue;
		}
		sample += bat->compensation;
		bat->vol_adc = sample;
		/* Put the sample and get the new average */
		bat->volt_value = put_sample_get_avg(&bat->volt_avg, sample);
		/* Get a temperature sample from the ADC */
		sample = instinctq_battery_adc_read(bat->client, bat->pdata->temp_channel);
		if (sample < 0) {
			dev_warn(&pdev->dev, "Failed to get ADC sample.\n");
			continue;
		}
		bat->temp_adc = sample;
		/* Put the sample and get the new average */
		bat->temp_value = put_sample_get_avg(&bat->temp_avg, sample);
	}

	bat->percent_value = lookup_value(&bat->percent_lookup, bat->volt_value);
	bat->volt_value = lookup_value(&bat->volt_lookup, bat->volt_value);
	bat->temp_value = lookup_value(&bat->temp_lookup, bat->temp_value);
	bat->last_sample = ktime_get_boottime();

	/* Register the power supplies */
	for (i = 0; i < instinctq_BATTERY_NUM; ++i) {
		bat->psy[i] = instinctq_chg_templates[i];
		ret = power_supply_register(&pdev->dev, &bat->psy[i]);
		if (ret < 0) {
			dev_err(&pdev->dev,
				"Failed to register power supply %s (%d)\n",
							bat->psy[i].name, ret);
			break;
		}
	}

	/* Undo the loop on error */
	if (i-- != instinctq_BATTERY_NUM) {
		for (; i >= 0; --i)
			power_supply_unregister(&bat->psy[i]);
		goto err_temp_free;
	}
#ifdef CONFIG_HAS_WAKELOCK
	ret = device_create_file(bat->psy[instinctq_BATTERY_AC].dev,
							&dev_attr_suspend_lock);
	if (ret < 0) {
		dev_err(&pdev->dev,
			"Failed to register device attribute.\n");
		goto err_psy_unreg;
	}
#endif
	/* Register the battery */
	bat->bat = instinctq_bat_template;
	ret = power_supply_register(&pdev->dev, &bat->bat);
	if (ret < 0) {
		dev_err(&pdev->dev,
			"Failed to register battery power supply: %d\n", ret);
		goto err_attr_unreg;
	}

	for (i = 0; i < ARRAY_SIZE(battery_attrs); ++i) {
		ret = device_create_file(bat->bat.dev, battery_attrs[i]);
		if (ret < 0)
			break;
	}

	if (ret < 0) {
		for (; i >= 0; --i)
			device_remove_file(bat->bat.dev, battery_attrs[i]);
		goto err_bat_unreg;
	}

	bat->workqueue = create_freezable_workqueue(dev_name(&pdev->dev));
	if (!bat->workqueue) {
		dev_err(&pdev->dev, "Failed to create freezeable workqueue\n");
		ret = -ENOMEM;
		goto err_remove_bat_attr;
	}

	/* Claim IRQs */
	irq = gpio_to_irq(pdata->gpio_pok);
	if (irq <= 0) {
		dev_err(&pdev->dev, "POK irq invalid.\n");
		goto err_destroy_workqueue;
	}
	bat->irq_pok = irq;

	ret = request_irq(irq, instinctq_charger_irq,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
				dev_name(&pdev->dev), bat);
	if (ret) {
		dev_err(&pdev->dev, "Failed to request POK irq (%d)\n", ret);
		goto err_destroy_workqueue;
	}

	ret = request_irq(IRQ_BATF, instinctq_battery_fault_irq,
						0, dev_name(&pdev->dev), bat);
	if (ret) {
		dev_err(&pdev->dev,
			"Failed to request battery fault irq (%d)\n", ret);
		goto err_pok_irq_free;
	}

	enable_irq_wake(bat->irq_pok);

	instinctq_battery_set_fault_enable(1);

	/* Finish */
	dev_info(&pdev->dev, "successfully loaded\n");
	device_init_wakeup(&pdev->dev, 1);

	pdata->supply_detect_init(instinctq_battery_supply_notify);

	/* Schedule work to check current status */
#ifdef CONFIG_HAS_WAKELOCK
	wake_lock(&bat->wakelock);
#endif
	queue_work(bat->workqueue, &bat->work);

	return 0;

err_pok_irq_free:
	free_irq(bat->irq_pok, bat);
err_destroy_workqueue:
	destroy_workqueue(bat->workqueue);
err_remove_bat_attr:
	for (i = 0; i < ARRAY_SIZE(battery_attrs); ++i)
		device_remove_file(bat->bat.dev, battery_attrs[i]);
err_bat_unreg:
	power_supply_unregister(&bat->bat);
err_attr_unreg:
#ifdef CONFIG_HAS_WAKELOCK
	device_remove_file(bat->psy[instinctq_BATTERY_AC].dev,
							&dev_attr_suspend_lock);
err_psy_unreg:
#endif
	for (i = 0; i < instinctq_BATTERY_NUM; ++i)
		power_supply_unregister(&bat->psy[i]);
err_temp_free:
#ifdef CONFIG_HAS_WAKELOCK
	wake_lock_destroy(&bat->wakelock);
	wake_lock_destroy(&bat->chg_wakelock);
	wake_lock_destroy(&bat->fault_wakelock);
	wake_lock_destroy(&bat->suspend_lock);
#endif
	kfree(bat->temp_lookup.table);
err_volt_free:
	kfree(bat->volt_lookup.table);
err_percent_free:
	kfree(bat->percent_lookup.table);
err_gpio_en_free:
	gpio_free(pdata->gpio_en);
err_gpio_chg_free:
	gpio_free(pdata->gpio_chg);
err_gpio_pok_free:
	gpio_free(pdata->gpio_pok);
err_free:
	kfree(bat);
err_free_adc:
	s3c_adc_release(client);
	return ret;
}
Beispiel #10
0
/**
 * s3c_hwmon_probe - device probe entry.
 * @dev: The device being probed.
*/
static int __devinit s3c_hwmon_probe(struct platform_device *dev)
{
    struct s3c_hwmon_pdata *pdata = dev->dev.platform_data;
    struct s3c_hwmon *hwmon;
    int ret = 0;
    int i;

    if (!pdata) {
        dev_err(&dev->dev, "no platform data supplied\n");
        return -EINVAL;
    }

    shwmon = hwmon = kzalloc(sizeof(struct s3c_hwmon), GFP_KERNEL);
    if (hwmon == NULL) {
        dev_err(&dev->dev, "no memory\n");
        return -ENOMEM;
    }

    platform_set_drvdata(dev, hwmon);

    mutex_init(&hwmon->lock);

    /* Register with the core ADC driver. */

    hwmon->client = s3c_adc_register(dev, NULL, NULL, 0);
    if (IS_ERR(hwmon->client)) {
        dev_err(&dev->dev, "cannot register adc\n");
        ret = PTR_ERR(hwmon->client);
        goto err_mem;
    }

    /* add attributes for our adc devices. */

    ret = s3c_hwmon_add_raw(&dev->dev);
    if (ret)
        goto err_registered;

    /* register with the hwmon core */

    hwmon->hwmon_dev = hwmon_device_register(&dev->dev);
    if (IS_ERR(hwmon->hwmon_dev)) {
        dev_err(&dev->dev, "error registering with hwmon\n");
        ret = PTR_ERR(hwmon->hwmon_dev);
        goto err_raw_attribute;
    }

    for (i = 0; i < ARRAY_SIZE(pdata->in); i++) {
        struct s3c_hwmon_chcfg *cfg = pdata->in[i];

        if (!cfg)
            continue;

        if (cfg->mult >= 0x10000)
            dev_warn(&dev->dev,
                     "channel %d multiplier too large\n",
                     i);

        if (cfg->div == 0) {
            dev_err(&dev->dev, "channel %d divider zero\n", i);
            continue;
        }

        ret = s3c_hwmon_create_attr(&dev->dev, pdata->in[i],
                                    &hwmon->attrs[i], i);
        if (ret) {
            dev_err(&dev->dev,
                    "error creating channel %d\n", i);

            for (i--; i >= 0; i--)
                s3c_hwmon_remove_attr(&dev->dev,
                                      &hwmon->attrs[i]);

            goto err_hwmon_register;
        }
    }

    return 0;

err_hwmon_register:
    hwmon_device_unregister(hwmon->hwmon_dev);

err_raw_attribute:
    s3c_hwmon_remove_raw(&dev->dev);

err_registered:
    s3c_adc_release(hwmon->client);

err_mem:
    kfree(hwmon);
    return ret;
}
void __init exynos4_smdk4270_charger_init(void)
{
	pr_info("%s: harrison charger init\n", __func__);


	platform_add_devices(sec_battery_devices,
		ARRAY_SIZE(sec_battery_devices));

	if (system_rev < 8) {
		i2c_register_board_info(CHG_ID, sec_brdinfo_charger,
				ARRAY_SIZE(sec_brdinfo_charger));
		sec_battery_pdata.chg_float_voltage = 4350;
	} else {
		i2c_register_board_info(CHG_ID, sec_brdinfo_charger_smb328,
				ARRAY_SIZE(sec_brdinfo_charger_smb328));
		sec_battery_pdata.chg_float_voltage = 4340;
	}

	if (system_rev > 9) {
#if defined(CONFIG_MACH_DELOSLTE_KOR_SKT) || defined(CONFIG_MACH_DELOSLTE_KOR_KT) || \
	defined(CONFIG_MACH_DELOSLTE_KOR_LGT)
	sec_battery_pdata.temp_high_threshold_event = 660;
	sec_battery_pdata.temp_high_recovery_event = 415;
	sec_battery_pdata.temp_low_threshold_event = -45;
	sec_battery_pdata.temp_low_recovery_event = 0;
	sec_battery_pdata.temp_high_threshold_normal = 660;
	sec_battery_pdata.temp_high_recovery_normal = 415;
	sec_battery_pdata.temp_low_threshold_normal = -45;
	sec_battery_pdata.temp_low_recovery_normal = 0;
	sec_battery_pdata.temp_high_threshold_lpm = 660;
	sec_battery_pdata.temp_high_recovery_lpm = 415;
	sec_battery_pdata.temp_low_threshold_lpm = -45;
	sec_battery_pdata.temp_low_recovery_lpm = 0;
#else
	sec_battery_pdata.temp_high_threshold_event = 610;
	sec_battery_pdata.temp_high_recovery_event = 430;
	sec_battery_pdata.temp_low_threshold_event = -40;
	sec_battery_pdata.temp_low_recovery_event = 20;
	sec_battery_pdata.temp_high_threshold_normal = 480;
	sec_battery_pdata.temp_high_recovery_normal = 430;
	sec_battery_pdata.temp_low_threshold_normal = -40;
	sec_battery_pdata.temp_low_recovery_normal = 20;
	sec_battery_pdata.temp_high_threshold_lpm = 480;
	sec_battery_pdata.temp_high_recovery_lpm = 450;
	sec_battery_pdata.temp_low_threshold_lpm = -30;
	sec_battery_pdata.temp_low_recovery_lpm = 0;
#endif
	}

#if defined(CONFIG_MACH_DELOSLTE_KOR_SKT) || defined(CONFIG_MACH_DELOSLTE_KOR_KT) || \
	defined(CONFIG_MACH_DELOSLTE_KOR_LGT)
	if (system_rev == 11 || system_rev == 12) {
		stc3115_battery_data[0].CC_cnf = 960;
		stc3115_battery_data[0].Rsense = 24;
		pr_info("%s: temp CC_cnf(%d), Rsense(%d)", __func__,
			stc3115_battery_data[0].CC_cnf, stc3115_battery_data[0].Rsense);
	} else if (system_rev == 13 || system_rev == 14 || system_rev == 15) {
		stc3115_battery_data[0].CC_cnf = 448;
		stc3115_battery_data[0].VM_cnf = 413;
		stc3115_battery_data[0].Rsense = 11;
		pr_info("%s: temp CC_cnf(%d), VM_cnf(%d), Rsense(%d)", __func__,
			stc3115_battery_data[0].CC_cnf, stc3115_battery_data[0].VM_cnf,
			stc3115_battery_data[0].Rsense);
	}

	sec_battery_pdata.recharge_condition_type =
		SEC_BATTERY_RECHARGE_CONDITION_AVGVCELL;
#endif

	i2c_register_board_info(FG_ID, sec_brdinfo_fuelgauge,
			ARRAY_SIZE(sec_brdinfo_fuelgauge));

	temp_adc_client = s3c_adc_register(&sec_device_battery, NULL, NULL, 0);
}
Beispiel #12
0
static int gp2a_i2c_probe(struct i2c_client *client,
			const struct i2c_device_id *id)
{
	int ret = -ENODEV;
	struct input_dev *input_dev;
	struct gp2a_data *gp2a;
	struct gp2a_platform_data *pdata = client->dev.platform_data;

	pr_info("==============================\n");
	pr_info("=========     GP2A     =======\n");
	pr_info("==============================\n");

	if (!pdata) {
		pr_err("%s: missing pdata!\n", __func__);
		return ret;
	}
	/*
	if (!pdata->power || !pdata->light_adc_value) {
		pr_err("%s: incomplete pdata!\n", __func__);
		return ret;
	}
	*/
	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
		pr_err("%s: i2c functionality check failed!\n", __func__);
		return ret;
	}

	gp2a = kzalloc(sizeof(struct gp2a_data), GFP_KERNEL);
	if (!gp2a) {
		pr_err("%s: failed to alloc memory for module data\n",
			__func__);
		return -ENOMEM;
	}

#if defined(CONFIG_OPTICAL_WAKE_ENABLE)
	if (system_rev >= 0x03) {
		pr_info("GP2A Reset GPIO = GPX0(1) (rev%02d)\n", system_rev);
		gp2a->enable_wakeup = true;
	} else {
		pr_info("GP2A Reset GPIO = GPL0(6) (rev%02d)\n", system_rev);
		gp2a->enable_wakeup = false;
	}
#else
	gp2a->enable_wakeup = false;
#endif

	gp2a->pdata = pdata;
	gp2a->i2c_client = client;
	i2c_set_clientdata(client, gp2a);

	/* wake lock init */
	wake_lock_init(&gp2a->prx_wake_lock, WAKE_LOCK_SUSPEND,
			"prx_wake_lock");
	mutex_init(&gp2a->power_mutex);
	mutex_init(&gp2a->adc_mutex);

	ret = gp2a_setup_irq(gp2a);
	if (ret) {
		pr_err("%s: could not setup irq\n", __func__);
		goto err_setup_irq;
	}

	/* allocate proximity input_device */
	input_dev = input_allocate_device();
	if (!input_dev) {
		pr_err("%s: could not allocate input device\n", __func__);
		goto err_input_allocate_device_proximity;
	}

	gp2a->proximity_input_dev = input_dev;
	input_set_drvdata(input_dev, gp2a);
	input_dev->name = "proximity_sensor";
	input_set_capability(input_dev, EV_ABS, ABS_DISTANCE);
	input_set_abs_params(input_dev, ABS_DISTANCE, 0, 1, 0, 0);

	gp2a_dbgmsg("registering proximity input device\n");
	ret = input_register_device(input_dev);
	if (ret < 0) {
		pr_err("%s: could not register input device\n", __func__);
		input_free_device(input_dev);
		goto err_input_register_device_proximity;
	}

	ret = sysfs_create_group(&input_dev->dev.kobj,
				 &proximity_attribute_group);
	if (ret) {
		pr_err("%s: could not create sysfs group\n", __func__);
		goto err_sysfs_create_group_proximity;
	}

	/* hrtimer settings.  we poll for light values using a timer. */
	hrtimer_init(&gp2a->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
	gp2a->light_poll_delay =
			ns_to_ktime(LIGHT_TIMER_PERIOD_MS * NSEC_PER_MSEC);
	gp2a->timer.function = gp2a_timer_func;

	/* the timer just fires off a work queue request.  we need a thread
	   to read the i2c (can be slow and blocking). */
	gp2a->wq = create_singlethread_workqueue("gp2a_wq");
	if (!gp2a->wq) {
		ret = -ENOMEM;
		pr_err("%s: could not create workqueue\n", __func__);
		goto err_create_workqueue;
	}

	/* this is the thread function we run on the work queue */
	INIT_WORK(&gp2a->work_light, gp2a_work_func_light);

#ifdef GP2A_MODE_B
	/* this is the thread function we run on the work queue */
	INIT_WORK(&gp2a->work_proximity, gp2a_work_func_proximity);
#endif

	/* allocate lightsensor-level input_device */
	input_dev = input_allocate_device();
	if (!input_dev) {
		pr_err("%s: could not allocate input device\n", __func__);
		ret = -ENOMEM;
		goto err_input_allocate_device_light;
	}

	input_set_drvdata(input_dev, gp2a);
	input_dev->name = "light_sensor";
	input_set_capability(input_dev, EV_ABS, ABS_MISC);
	input_set_abs_params(input_dev, ABS_MISC, 0, 1, 0, 0);

	gp2a_dbgmsg("registering lightsensor-level input device\n");
	ret = input_register_device(input_dev);
	if (ret < 0) {
		pr_err("%s: could not register input device\n", __func__);
		input_free_device(input_dev);
		goto err_input_register_device_light;
	}

	gp2a->light_input_dev = input_dev;
	ret = sysfs_create_group(&input_dev->dev.kobj,
				&light_attribute_group);
	if (ret) {
		pr_err("%s: could not create sysfs group\n", __func__);
		goto err_sysfs_create_group_light;
	}

	/* alloc platform device for adc client */
	pdev_gp2a_adc = platform_device_alloc("gp2a-adc", -1);
	if (!pdev_gp2a_adc) {
		pr_err("%s: could not allocation pdev_gp2a_adc.\n", __func__);
		ret = -ENOMEM;
		goto err_platform_allocate_device_adc;
	}

	/* Register adc client */
	gp2a->padc = s3c_adc_register(pdev_gp2a_adc, NULL, NULL, 0);

	if (IS_ERR(gp2a->padc)) {
		dev_err(&pdev_gp2a_adc->dev, "cannot register adc\n");
		ret = PTR_ERR(gp2a->padc);
		goto err_platform_register_device_adc;
	}

	/* set sysfs for light sensor */

	ret = misc_register(&light_device);
	if (ret)
		pr_err(KERN_ERR "misc_register failed - light\n");

	gp2a->lightsensor_class = class_create(THIS_MODULE, "lightsensor");
	if (IS_ERR(gp2a->lightsensor_class))
		pr_err("Failed to create class(lightsensor)!\n");

	gp2a->switch_cmd_dev = device_create(gp2a->lightsensor_class,
		NULL, 0, NULL, "switch_cmd");
	if (IS_ERR(gp2a->switch_cmd_dev))
		pr_err("Failed to create device(switch_cmd_dev)!\n");

	if (device_create_file(gp2a->switch_cmd_dev,
		&dev_attr_lightsensor_file_illuminance) < 0)
		pr_err("Failed to create device file(%s)!\n",
			dev_attr_lightsensor_file_illuminance.attr.name);

	dev_set_drvdata(gp2a->switch_cmd_dev, gp2a);

	/* set initial proximity value as 1 */
	input_report_abs(gp2a->proximity_input_dev, ABS_DISTANCE, 1);
	input_sync(gp2a->proximity_input_dev);

	gp2a->adc_total = 0;

	goto done;

	/* error, unwind it all */
err_sysfs_create_group_light:
	input_unregister_device(gp2a->light_input_dev);
err_input_register_device_light:
err_input_allocate_device_light:
	destroy_workqueue(gp2a->wq);
err_platform_allocate_device_adc:
	platform_device_unregister(pdev_gp2a_adc);
err_platform_register_device_adc:
	s3c_adc_release(gp2a->padc);
err_create_workqueue:
	sysfs_remove_group(&gp2a->proximity_input_dev->dev.kobj,
			&proximity_attribute_group);
err_sysfs_create_group_proximity:
	input_unregister_device(gp2a->proximity_input_dev);
err_input_register_device_proximity:
err_input_allocate_device_proximity:
	free_irq(gp2a->irq, 0);
	gpio_free(gp2a->pdata->p_out);
err_setup_irq:
	mutex_destroy(&gp2a->adc_mutex);
	mutex_destroy(&gp2a->power_mutex);

	wake_lock_destroy(&gp2a->prx_wake_lock);
	kfree(gp2a);
done:
	return ret;
}
static __devinit int samsung_battery_probe(struct platform_device *pdev)
{
	struct battery_info *info;
	int ret = 0;
	char *temper_src_name[] = { "fuelgauge", "ap adc",
		"ext adc", "unknown"
	};
	pr_info("%s: SAMSUNG Battery 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 = pdev->dev.platform_data;

	/* Check charger name and fuelgauge name. */
	if (!info->pdata->charger_name || !info->pdata->fuelgauge_name) {
		pr_err("%s: no charger or fuel gauge name\n", __func__);
		goto err_kfree;
	}
	info->charger_name = info->pdata->charger_name;
	info->fuelgauge_name = info->pdata->fuelgauge_name;
#if defined(CONFIG_CHARGER_MAX8922_U1)
	if (system_rev >= 2)
		info->sub_charger_name = info->pdata->sub_charger_name;
#endif
	pr_info("%s: Charger name: %s\n", __func__, info->charger_name);
	pr_info("%s: Fuelgauge name: %s\n", __func__, info->fuelgauge_name);
#if defined(CONFIG_CHARGER_MAX8922_U1)
	if (system_rev >= 2)
		pr_info("%s: SubCharger name: %s\n", __func__,
			info->sub_charger_name);
#endif

	info->psy_charger = power_supply_get_by_name(info->charger_name);
	info->psy_fuelgauge = power_supply_get_by_name(info->fuelgauge_name);
#if defined(CONFIG_CHARGER_MAX8922_U1)
	if (system_rev >= 2)
		info->psy_sub_charger =
		    power_supply_get_by_name(info->sub_charger_name);
#endif
	if (!info->psy_charger || !info->psy_fuelgauge) {
		pr_err("%s: fail to get power supply\n", __func__);
		goto err_kfree;
	}

	/* WORKAROUND: set battery pdata in driver */
	if (system_rev == 3) {
		info->pdata->temper_src = TEMPER_EXT_ADC;
		info->pdata->temper_ch = 7;
	}
	pr_info("%s: Temperature source: %s\n", __func__,
		temper_src_name[info->pdata->temper_src]);

	/* recalculate recharge voltage, it depends on max voltage value */
	info->pdata->recharge_voltage = info->pdata->voltage_max - 50;
	pr_info("%s: Recharge voltage: %d\n", __func__,
				info->pdata->recharge_voltage);
#if defined(CONFIG_S3C_ADC)
#if defined(CONFIG_MACH_S2PLUS)
	if (system_rev >= 2)
#endif
		/* adc register */
		info->adc_client = s3c_adc_register(pdev, NULL, NULL, 0);
#endif

	/* init battery info */
	info->full_charged_state = false;
	info->abstimer_state = false;
	info->recharge_phase = false;
	info->siop_charge_current = CHARGER_USB_CURRENT;
	info->monitor_mode = MONITOR_NORM;
	info->led_state = BATT_LED_DISCHARGING;

	/* LPM charging state */
	info->lpm_state = lpcharge;

	wake_lock_init(&info->monitor_wake_lock, WAKE_LOCK_SUSPEND,
		       "battery-monitor");
	wake_lock_init(&info->emer_wake_lock, WAKE_LOCK_SUSPEND,
		       "battery-emergency");
	if (!info->pdata->suspend_chging)
		wake_lock_init(&info->charge_wake_lock,
			       WAKE_LOCK_SUSPEND, "battery-charging");

	/* Init wq for battery */
	INIT_WORK(&info->error_work, battery_error_work);
	INIT_WORK(&info->monitor_work, battery_monitor_work);

	/* Init Power supply class */
	info->psy_bat.name = "battery";
	info->psy_bat.type = POWER_SUPPLY_TYPE_BATTERY;
	info->psy_bat.properties = samsung_battery_props;
	info->psy_bat.num_properties = ARRAY_SIZE(samsung_battery_props);
	info->psy_bat.get_property = samsung_battery_get_property;
	info->psy_bat.set_property = samsung_battery_set_property;

	info->psy_usb.name = "usb";
	info->psy_usb.type = POWER_SUPPLY_TYPE_USB;
	info->psy_usb.supplied_to = supply_list;
	info->psy_usb.num_supplicants = ARRAY_SIZE(supply_list);
	info->psy_usb.properties = samsung_power_props;
	info->psy_usb.num_properties = ARRAY_SIZE(samsung_power_props);
	info->psy_usb.get_property = samsung_usb_get_property;

	info->psy_ac.name = "ac";
	info->psy_ac.type = POWER_SUPPLY_TYPE_MAINS;
	info->psy_ac.supplied_to = supply_list;
	info->psy_ac.num_supplicants = ARRAY_SIZE(supply_list);
	info->psy_ac.properties = samsung_power_props;
	info->psy_ac.num_properties = ARRAY_SIZE(samsung_power_props);
	info->psy_ac.get_property = samsung_ac_get_property;

	ret = power_supply_register(&pdev->dev, &info->psy_bat);
	if (ret) {
		pr_err("%s: failed to register psy_bat\n", __func__);
		goto err_psy_reg_bat;
	}

	ret = power_supply_register(&pdev->dev, &info->psy_usb);
	if (ret) {
		pr_err("%s: failed to register psy_usb\n", __func__);
		goto err_psy_reg_usb;
	}

	ret = power_supply_register(&pdev->dev, &info->psy_ac);
	if (ret) {
		pr_err("%s: failed to register psy_ac\n", __func__);
		goto err_psy_reg_ac;
	}

	/* Using android alarm for gauging instead of workqueue */
	info->last_poll = alarm_get_elapsed_realtime();
	alarm_init(&info->alarm, ANDROID_ALARM_ELAPSED_REALTIME_WAKEUP,
		   samsung_battery_alarm_start);

	/* update battery init status */
	schedule_work(&info->monitor_work);

	/* Create samsung detail attributes */
	battery_create_attrs(info->psy_bat.dev);

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

 err_psy_reg_ac:
	power_supply_unregister(&info->psy_usb);
 err_psy_reg_usb:
	power_supply_unregister(&info->psy_bat);
 err_psy_reg_bat:
	wake_lock_destroy(&info->monitor_wake_lock);
	wake_lock_destroy(&info->emer_wake_lock);
	if (!info->pdata->suspend_chging)
		wake_lock_destroy(&info->charge_wake_lock);
 err_kfree:
	kfree(info);

	return ret;
}
static bool sec_bat_adc_ap_init(struct platform_device *pdev)
{
	adc_client = s3c_adc_register(pdev, NULL, NULL, 0);
	return true;

}
static int __devinit s3c_adc_bat_probe(struct platform_device *pdev)
{
	struct s3c_adc_client	*client;
	struct s3c_adc_bat_pdata *pdata = pdev->dev.platform_data;
	int ret;

	client = s3c_adc_register(pdev, NULL, NULL, 0);
	if (IS_ERR(client)) {
		dev_err(&pdev->dev, "cannot register adc\n");
		return PTR_ERR(client);
	}

	platform_set_drvdata(pdev, client);

	main_bat.client = client;
	main_bat.pdata = pdata;
	main_bat.volt_value = -1;
	main_bat.cur_value = -1;
	main_bat.cable_plugged = 0;
	main_bat.status = POWER_SUPPLY_STATUS_DISCHARGING;

	ret = power_supply_register(&pdev->dev, &main_bat.psy);
	if (ret)
		goto err_reg_main;
	if (pdata->backup_volt_mult) {
		backup_bat.client = client;
		backup_bat.pdata = pdev->dev.platform_data;
		backup_bat.volt_value = -1;
		ret = power_supply_register(&pdev->dev, &backup_bat.psy);
		if (ret)
			goto err_reg_backup;
	}

	INIT_DELAYED_WORK(&bat_work, s3c_adc_bat_work);

	if (pdata->gpio_charge_finished >= 0) {
		ret = gpio_request(pdata->gpio_charge_finished, "charged");
		if (ret)
			goto err_gpio;

		ret = request_irq(gpio_to_irq(pdata->gpio_charge_finished),
				s3c_adc_bat_charged,
				IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
				"battery charged", NULL);
		if (ret)
			goto err_irq;
	}

	if (pdata->init) {
		ret = pdata->init();
		if (ret)
			goto err_platform;
	}

	dev_info(&pdev->dev, "successfully loaded\n");
	device_init_wakeup(&pdev->dev, 1);

	
	schedule_delayed_work(&bat_work,
		msecs_to_jiffies(JITTER_DELAY));

	return 0;

err_platform:
	if (pdata->gpio_charge_finished >= 0)
		free_irq(gpio_to_irq(pdata->gpio_charge_finished), NULL);
err_irq:
	if (pdata->gpio_charge_finished >= 0)
		gpio_free(pdata->gpio_charge_finished);
err_gpio:
	if (pdata->backup_volt_mult)
		power_supply_unregister(&backup_bat.psy);
err_reg_backup:
	power_supply_unregister(&main_bat.psy);
err_reg_main:
	return ret;
}
Beispiel #16
0
static int __devinit gpio_switch_probe(struct platform_device *pdev)
{
	struct gpio_switch_platform_data *pdata = pdev->dev.platform_data;
	int ret = 0;

	if (!pdata)
		return -EBUSY;

	switch_data = kzalloc(sizeof(struct gpio_switch_data), GFP_KERNEL);
	if (!switch_data)
		return -ENOMEM;

	platform_set_drvdata(pdev, switch_data);
	switch_data->sdev.name = pdata->name;
	switch_data->gpio = pdata->gpio;
	switch_data->name_on = pdata->name_on;
	switch_data->name_off = pdata->name_off;
	switch_data->state_on = pdata->state_on;
	switch_data->state_off = pdata->state_off;
	switch_data->sdev.print_state = switch_gpio_print_state;
	
	switch_data->active_level = pdata->active_level;
	switch_data->adc_channel = pdata->adc_channel;
	
	ret = switch_dev_register(&switch_data->sdev);
	if (ret < 0)
		goto err_switch_dev_register;

	ret = gpio_request(switch_data->gpio, pdev->name);
	if (ret < 0)
		goto err_request_gpio;

	ret = gpio_direction_input(switch_data->gpio);
	if (ret < 0)
		goto err_set_gpio_input;

	INIT_DELAYED_WORK(&switch_data->del_work, gpio_switch_work);
	INIT_WORK(&mic_adc_work, mic_adc_work_func);

	mic_input_dev = input_allocate_device();
	mic_input_dev->name = "mx-mic-input";
	mic_input_dev->phys = "mx-mic-input/input0";
	if (input_register_device(mic_input_dev) != 0) {
		input_free_device(mic_input_dev);
		goto err_request_irq;
	}

	set_bit(EV_KEY, mic_input_dev->evbit);
	set_bit(KEY_FORWARDMAIL, mic_input_dev->keybit);

	switch_data->client = s3c_adc_register(pdev, NULL, NULL, 0);
	if (IS_ERR(switch_data->client)) {
		dev_err(&pdev->dev, "cannot register adc\n");
		ret = PTR_ERR(switch_data->client);
		goto err_request_adc;
	}

	setup_timer(&detect_mic_adc_timer, mic_adc_detect_timer_func, 0);
	
	s3c_gpio_setpull(switch_data->gpio, S3C_GPIO_PULL_UP);

	switch_data->irq = gpio_to_irq(switch_data->gpio);
	if (switch_data->irq < 0) {
		ret = switch_data->irq;
		goto err_detect_irq_num_failed;
	}

	ret = request_threaded_irq(switch_data->irq, NULL, gpio_irq_handler,
			IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_ONESHOT, pdev->name, switch_data);
	
	if (ret < 0)
		goto err_request_irq;

#ifdef CONFIG_EARLYSUSPEND
	switch_data->early_suspends.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN;
	switch_data->early_suspends.suspend = gpio_switch_early_suspend;
	switch_data->early_suspends.resume= gpio_switch_late_resume;
	register_early_suspend(&switch_data->early_suspends);
#endif
	schedule_delayed_work(&switch_data->del_work, msecs_to_jiffies(10));

	return 0;

err_request_irq:
	s3c_adc_release(switch_data->client);
err_request_adc:
err_detect_irq_num_failed:
err_set_gpio_input:
	gpio_free(switch_data->gpio);
err_request_gpio:
	switch_dev_unregister(&switch_data->sdev);
err_switch_dev_register:
	kfree(switch_data);

	return ret;
}
static int acc_con_probe(struct platform_device *pdev)
{
    struct acc_con_info *acc;
    struct acc_con_platform_data *pdata = pdev->dev.platform_data;
    struct regulator *vadc_regulator;

    int	retval;

    ACC_CONDEV_DBG("");

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

#ifdef CONFIG_REGULATOR
    /* LDO1 regulator ON */
    vadc_regulator = regulator_get(&pdev->dev, "vadc_3.3v");
    if (IS_ERR(vadc_regulator)) {
        printk(KERN_ERR "failed to get resource %s\n",
               "vadc_3.3v");
        return PTR_ERR(vadc_regulator);
    }
    regulator_enable(vadc_regulator);
#endif

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

    acc->pdata = pdata;
    acc->current_dock = DOCK_NONE;
    acc->current_accessory = ACCESSORY_NONE;
#ifdef CONFIG_MHL_SII9234
    acc->mhl_irq = gpio_to_irq(pdata->mhl_irq_gpio);
    acc->mhl_pwr_state = false;
#endif

    mutex_init(&acc->lock);
    dev_set_drvdata(&pdev->dev, acc);

    acc->acc_dev = &pdev->dev;

    /* Register adc client */
    acc->padc = s3c_adc_register(pdev, NULL, NULL, 0);

#ifdef CONFIG_MHL_SII9234
    retval = i2c_add_driver(&SII9234A_i2c_driver);
    if (retval) {
        pr_err("[MHL SII9234A] can't add i2c driver\n");
        goto err_i2c_a;
    } else {
        pr_info("[MHL SII9234A] add i2c driver\n");
    }

    retval = i2c_add_driver(&SII9234B_i2c_driver);
    if (retval) {
        pr_err("[MHL SII9234B] can't add i2c driver\n");
        goto err_i2c_b;
    } else {
        pr_info("[MHL SII9234B] add i2c driver\n");
    }

    retval = i2c_add_driver(&SII9234C_i2c_driver);
    if (retval) {
        pr_err("[MHL SII9234C] can't add i2c driver\n");
        goto err_i2c_c;
    } else {
        pr_info("[MHL SII9234C] add i2c driver\n");
    }

    retval = i2c_add_driver(&SII9234_i2c_driver);
    if (retval) {
        pr_err("[MHL SII9234] can't add i2c driver\n");
        goto err_i2c;
    } else {
        pr_info("[MHL SII9234] add i2c driver\n");
    }
#endif
    acc->dock_switch.name = "dock";
    retval = switch_dev_register(&acc->dock_switch);
    if (retval < 0)
        goto err_sw_dock;

    acc->ear_jack_switch.name = "usb_audio";
    retval = switch_dev_register(&acc->ear_jack_switch);
    if (retval < 0)
        goto err_sw_jack;

    wake_lock_init(&acc->wake_lock, WAKE_LOCK_SUSPEND, "30pin_con");

    INIT_DELAYED_WORK(&acc->acc_dwork, acc_dwork_int_init);
    schedule_delayed_work(&acc->acc_dwork, msecs_to_jiffies(10000));
    INIT_DELAYED_WORK(&acc->acc_id_dwork, acc_dwork_accessory_detect);
#ifdef CONFIG_MHL_SII9234
    if (device_create_file(acc->acc_dev, &dev_attr_MHD_file) < 0)
        pr_err("Failed to create device file(%s)!\n",
               dev_attr_MHD_file.attr.name);
#endif
    return 0;

#ifndef CONFIG_SEC_KEYBOARD_DOCK
err_irq_acc:
    free_irq(acc->accessory_irq, acc);
err_irq_dock:
    switch_dev_unregister(&acc->ear_jack_switch);
#endif
err_sw_jack:
    switch_dev_unregister(&acc->dock_switch);
err_sw_dock:
#ifdef CONFIG_MHL_SII9234
    i2c_del_driver(&SII9234_i2c_driver);
err_i2c:
    i2c_del_driver(&SII9234C_i2c_driver);
err_i2c_c:
    i2c_del_driver(&SII9234B_i2c_driver);
err_i2c_b:
    i2c_del_driver(&SII9234A_i2c_driver);
err_i2c_a:
#endif

    kfree(acc);

    return retval;
}