From 57a4af9be7051302edc51c878ecfbd90466827ff Mon Sep 17 00:00:00 2001 From: Balaji Rao Date: Tue, 27 Jan 2009 14:38:49 +0000 Subject: Subject: pcf50606_rebase_changes,patch X-Git-Url: http://git.openmoko.org/?p=kernel.git;a=commitdiff_plain;h=445395c9fcfb78ea62ab5a69b84c2c12efe01cff pcf50606_rebase_changes,patch This patch brings into andy-tracking all changes related to pcf50606 from old balaji-tracking. --- arch/arm/plat-s3c24xx/neo1973_pm_bt.c | 188 +++++++++++++++++++++++++-------- arch/arm/plat-s3c24xx/neo1973_pm_gps.c | 4 + 2 files changed, 149 insertions(+), 43 deletions(-) (limited to 'arch/arm/plat-s3c24xx') diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_bt.c b/arch/arm/plat-s3c24xx/neo1973_pm_bt.c index 96af7c544d7..53d3c02b9d5 100644 --- a/arch/arm/plat-s3c24xx/neo1973_pm_bt.c +++ b/arch/arm/plat-s3c24xx/neo1973_pm_bt.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -27,24 +28,27 @@ /* For GTA02 */ #include -#include +#include +#include #define DRVMSG "FIC Neo1973 Bluetooth Power Management" +struct gta01_pm_bt_data { + struct regulator *regulator; + struct rfkill *rfkill; + int pre_resume_state; +}; + static ssize_t bt_read(struct device *dev, struct device_attribute *attr, char *buf) { int ret = 0; + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(dev); if (!strcmp(attr->attr.name, "power_on")) { - if (machine_is_neo1973_gta01()) { - if (pcf50606_onoff_get(pcf50606_global, - PCF50606_REGULATOR_D1REG) && - pcf50606_voltage_get(pcf50606_global, - PCF50606_REGULATOR_D1REG) == 3100) - ret = 1; + ret = regulator_is_enabled(bt_data->regulator); } else if (machine_is_neo1973_gta02()) { if (s3c2410_gpio_getpin(GTA02_GPIO_BT_EN)) ret = 1; @@ -66,37 +70,51 @@ static ssize_t bt_read(struct device *dev, struct device_attribute *attr, } } +static void __gta02_pm_bt_toggle_radio(struct device *dev, unsigned int on) +{ + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(dev); + + dev_info(dev, "__gta02_pm_bt_toggle_radio %d\n", on); + + if (machine_is_neo1973_gta02()) { + + bt_data = dev_get_drvdata(dev); + + neo1973_gpb_setpin(GTA02_GPIO_BT_EN, !on); + + if (on) { + if (!regulator_is_enabled(bt_data->regulator)) + regulator_enable(bt_data->regulator); + } else { + if (regulator_is_enabled(bt_data->regulator)) + regulator_disable(bt_data->regulator); + } + + neo1973_gpb_setpin(GTA02_GPIO_BT_EN, on); + } +} + + static int bt_rfkill_toggle_radio(void *data, enum rfkill_state state) { struct device *dev = data; unsigned long on = (state == RFKILL_STATE_ON); - unsigned int vol; + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(dev); if (machine_is_neo1973_gta01()) { /* if we are powering up, assert reset, then power, * then release reset */ if (on) { neo1973_gpb_setpin(GTA01_GPIO_BT_EN, 0); - pcf50606_voltage_set(pcf50606_global, - PCF50606_REGULATOR_D1REG, - 3100); + if (!regulator_is_enabled(bt_data->regulator)) + regulator_enable(bt_data->regulator); + } else { + if (regulator_is_enabled(bt_data->regulator)) + regulator_disable(bt_data->regulator); } - pcf50606_onoff_set(pcf50606_global, - PCF50606_REGULATOR_D1REG, on); neo1973_gpb_setpin(GTA01_GPIO_BT_EN, on); - } else if (machine_is_neo1973_gta02()) { - if (s3c2410_gpio_getpin(GTA02_GPIO_BT_EN) == on) - return 0; - neo1973_gpb_setpin(GTA02_GPIO_BT_EN, !on); - pcf50633_voltage_set(pcf50633_global, - PCF50633_REGULATOR_LDO4, on ? 3200 : 0); - pcf50633_onoff_set(pcf50633_global, - PCF50633_REGULATOR_LDO4, on); - vol = pcf50633_voltage_get(pcf50633_global, - PCF50633_REGULATOR_LDO4); - dev_info(dev, "GTA02 Set PCF50633 LDO4 = %d\n", vol); - neo1973_gpb_setpin(GTA02_GPIO_BT_EN, on); - } + } else if (machine_is_neo1973_gta02()) + __gta02_pm_bt_toggle_radio(dev, on); return 0; } @@ -105,12 +123,29 @@ static ssize_t bt_write(struct device *dev, struct device_attribute *attr, const char *buf, size_t count) { unsigned long on = simple_strtoul(buf, NULL, 10); + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(dev); if (!strcmp(attr->attr.name, "power_on")) { - struct rfkill *rfkill = dev_get_drvdata(dev); enum rfkill_state state = on ? RFKILL_STATE_ON : RFKILL_STATE_OFF; bt_rfkill_toggle_radio(dev, state); - rfkill->state = state; + bt_data->rfkill->state = state; + + if (machine_is_neo1973_gta01()) { + /* if we are powering up, assert reset, then power, + * then release reset */ + if (on) { + neo1973_gpb_setpin(GTA01_GPIO_BT_EN, 0); + if (!regulator_is_enabled(bt_data->regulator)) + regulator_enable(bt_data->regulator); + } else { + if (regulator_is_enabled(bt_data->regulator)) + regulator_disable(bt_data->regulator); + } + + neo1973_gpb_setpin(GTA01_GPIO_BT_EN, on); + } else if (machine_is_neo1973_gta02()) + __gta02_pm_bt_toggle_radio(dev, on); + } else if (!strcmp(attr->attr.name, "reset")) { /* reset is low-active, so we need to invert */ if (machine_is_neo1973_gta01()) { @@ -129,18 +164,32 @@ static DEVICE_ATTR(reset, 0644, bt_read, bt_write); #ifdef CONFIG_PM static int gta01_bt_suspend(struct platform_device *pdev, pm_message_t state) { + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(&pdev->dev); + dev_dbg(&pdev->dev, DRVMSG ": suspending\n"); - /* FIXME: The PMU should save the PMU status, and the GPIO code should - * preserve the GPIO level, so there shouldn't be anything left to do - * for us, should there? */ + + if (machine_is_neo1973_gta01()) { + if (regulator_is_enabled(bt_data->regulator)) + regulator_disable(bt_data->regulator); + } else if (machine_is_neo1973_gta02()) { + bt_data->pre_resume_state = + s3c2410_gpio_getpin(GTA02_GPIO_BT_EN); + __gta02_pm_bt_toggle_radio(&pdev->dev, 0); + } return 0; } static int gta01_bt_resume(struct platform_device *pdev) { + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(&pdev->dev); dev_dbg(&pdev->dev, DRVMSG ": resuming\n"); + if (machine_is_neo1973_gta02()) { + __gta02_pm_bt_toggle_radio(&pdev->dev, + bt_data->pre_resume_state); + } + return 0; } #else @@ -162,19 +211,55 @@ static struct attribute_group gta01_bt_attr_group = { static int __init gta01_bt_probe(struct platform_device *pdev) { struct rfkill *rfkill; + struct regulator *regulator; + struct gta01_pm_bt_data *bt_data; + int ret; + dev_info(&pdev->dev, DRVMSG ": starting\n"); + bt_data = kzalloc(sizeof(*bt_data), GFP_KERNEL); + dev_set_drvdata(&pdev->dev, bt_data); + if (machine_is_neo1973_gta01()) { /* we make sure that the voltage is off */ - pcf50606_onoff_set(pcf50606_global, - PCF50606_REGULATOR_D1REG, 0); + regulator = regulator_get(&pdev->dev, "BT_3V1"); + if (IS_ERR(regulator)) + return -ENODEV; + + bt_data->regulator = regulator; + + /* this tests the true physical state of the regulator... */ + if (regulator_is_enabled(regulator)) { + /* + * but these only operate on the logical state of the + * regulator... so we need to logicaly "adopt" it on + * to turn it off + */ + regulator_enable(regulator); + regulator_disable(regulator); + } + /* we pull reset to low to make sure that the chip doesn't * drain power through the reset line */ neo1973_gpb_setpin(GTA01_GPIO_BT_EN, 0); } else if (machine_is_neo1973_gta02()) { - /* we make sure that the voltage is off */ - pcf50633_onoff_set(pcf50633_global, - PCF50633_REGULATOR_LDO4, 0); + regulator = regulator_get(&pdev->dev, "BT_3V2"); + if (IS_ERR(regulator)) + return -ENODEV; + + bt_data->regulator = regulator; + + /* this tests the true physical state of the regulator... */ + if (regulator_is_enabled(regulator)) { + /* + * but these only operate on the logical state of the + * regulator... so we need to logicaly "adopt" it on + * to turn it off + */ + regulator_enable(regulator); + regulator_disable(regulator); + } + /* we pull reset to low to make sure that the chip doesn't * drain power through the reset line */ neo1973_gpb_setpin(GTA02_GPIO_BT_EN, 0); @@ -187,25 +272,42 @@ static int __init gta01_bt_probe(struct platform_device *pdev) rfkill->state = RFKILL_STATE_OFF; rfkill->toggle_radio = bt_rfkill_toggle_radio; - if (rfkill_register(rfkill) < 0) { - /* We can live if it fails to register, but report it. */ - dev_dbg(&pdev->dev, DRVMSG ": RFKILL registration failed\n"); + ret = rfkill_register(rfkill); + if (ret) { + dev_err(&pdev->dev, "Failed to register rfkill\n"); + return ret; } - platform_set_drvdata(pdev, rfkill); + bt_data->rfkill = rfkill; return sysfs_create_group(&pdev->dev.kobj, >a01_bt_attr_group); } static int gta01_bt_remove(struct platform_device *pdev) { - struct rfkill *rfkill = platform_get_drvdata(pdev); + struct gta01_pm_bt_data *bt_data = dev_get_drvdata(&pdev->dev); + struct regulator *regulator; sysfs_remove_group(&pdev->dev.kobj, >a01_bt_attr_group); - rfkill_unregister(rfkill); - rfkill_free(rfkill); + if (bt_data->rfkill) { + rfkill_unregister(bt_data->rfkill); + rfkill_free(bt_data->rfkill); + } + + if (!bt_data || !bt_data->regulator) + return 0; + + regulator = bt_data->regulator; + + /* Make sure regulator is disabled before calling regulator_put */ + if (regulator_is_enabled(regulator)) + regulator_disable(regulator); + + regulator_put(regulator); + kfree(bt_data); + return 0; } diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_gps.c b/arch/arm/plat-s3c24xx/neo1973_pm_gps.c index 26a49d4fbd4..84785dfa52a 100644 --- a/arch/arm/plat-s3c24xx/neo1973_pm_gps.c +++ b/arch/arm/plat-s3c24xx/neo1973_pm_gps.c @@ -422,6 +422,8 @@ static ssize_t power_gps_write(struct device *dev, /* This is the nRESET pin */ static void gps_rst_set(int on) { + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_2V5]; + switch (system_rev) { case GTA01v3_SYSTEM_REV: pcf50606_gpo_set_active(gta01_pcf, PCF50606_GPO1, on); @@ -437,6 +439,8 @@ static void gps_rst_set(int on) static int gps_rst_get(void) { + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_1V5]; + switch (system_rev) { case GTA01v3_SYSTEM_REV: return pcf50606_gpo_get_active(gta01_pcf, PCF50606_GPO1); -- cgit v1.2.3