aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Green <andy@openmoko.com>2008-12-01 01:26:31 +0000
committerAndy Green <agreen@pads.home.warmcat.com>2008-12-01 01:26:31 +0000
commit9ef786eed3c30516b7bfbf730d78824e30bc2e28 (patch)
treedcb465adedffa7fe0b83ab7798f6066e51f6cc82
parent3f5adf94526e33a9da8193d26a7d511820eb7f4d (diff)
fix-rfkill-on-bt-platform-drvdata-vs-drvdata.patch
Hum seems the rfkill stuff was broken somewhere along the line, some of it thinks the rfkill pointer is in the pdev private data and some gets confused about the bt_data pointer being in dev private data... this patch cleans it out so the rfkill pointer is held in the bt_data struct, which is created for gta01 or 02 now. Before these changes it will blow up on resume due to dereferencing the wrong pointer to the wrong thing. Signed-off-by: Andy Green <andy@openmoko.com>
-rw-r--r--arch/arm/plat-s3c24xx/neo1973_pm_bt.c115
1 files changed, 57 insertions, 58 deletions
diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_bt.c b/arch/arm/plat-s3c24xx/neo1973_pm_bt.c
index 894651afc12..217fcf05953 100644
--- a/arch/arm/plat-s3c24xx/neo1973_pm_bt.c
+++ b/arch/arm/plat-s3c24xx/neo1973_pm_bt.c
@@ -36,6 +36,8 @@
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,
@@ -72,11 +74,35 @@ 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);
- struct gta01_pm_bt_data *bt_data;
if (machine_is_neo1973_gta01()) {
/* if we are powering up, assert reset, then power,
@@ -90,25 +116,8 @@ static int bt_rfkill_toggle_radio(void *data, enum rfkill_state state)
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;
-
- bt_data = dev_get_drvdata(dev);
- BUG_ON(!bt_data || !bt_data->regulator);
-
- 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);
- }
+ } else if (machine_is_neo1973_gta02())
+ __gta02_pm_bt_toggle_radio(dev, on);
return 0;
}
@@ -117,15 +126,12 @@ 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);
- unsigned int vol;
- struct gta01_pm_bt_data *bt_data;
- struct regulator *regulator;
+ 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,
@@ -139,29 +145,9 @@ static ssize_t bt_write(struct device *dev, struct device_attribute *attr,
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 count;
-
- bt_data = dev_get_drvdata(dev);
- BUG_ON(!bt_data || !bt_data->regulator);
- regulator = bt_data->regulator;
-
- neo1973_gpb_setpin(GTA02_GPIO_BT_EN, !on);
-
- if (on) {
- if (!regulator_is_enabled(regulator))
- regulator_enable(regulator);
- } else {
- if (regulator_is_enabled(regulator))
- regulator_disable(regulator);
- }
-
- vol = regulator_get_voltage(regulator);
+ } else if (machine_is_neo1973_gta02())
+ __gta02_pm_bt_toggle_radio(dev, on);
- dev_info(dev, "GTA02 Set PCF50633 LDO4 = %d\n", vol);
- neo1973_gpb_setpin(GTA02_GPIO_BT_EN, on);
- }
} else if (!strcmp(attr->attr.name, "reset")) {
/* reset is low-active, so we need to invert */
if (machine_is_neo1973_gta01()) {
@@ -180,18 +166,29 @@ 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_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
@@ -219,6 +216,8 @@ static int __init gta01_bt_probe(struct platform_device *pdev)
dev_info(&pdev->dev, DRVMSG ": starting\n");
+ bt_data = kzalloc(sizeof(*bt_data), GFP_KERNEL);
+
if (machine_is_neo1973_gta01()) {
/* we make sure that the voltage is off */
pcf50606_onoff_set(pcf50606_global,
@@ -231,7 +230,6 @@ static int __init gta01_bt_probe(struct platform_device *pdev)
if (IS_ERR(regulator))
return -ENODEV;
- bt_data = kmalloc(sizeof(*bt_data), GFP_KERNEL);
bt_data->regulator = regulator;
dev_set_drvdata(&pdev->dev, bt_data);
@@ -264,24 +262,23 @@ static int __init gta01_bt_probe(struct platform_device *pdev)
return ret;
}
- platform_set_drvdata(pdev, rfkill);
+ bt_data->rfkill = rfkill;
return sysfs_create_group(&pdev->dev.kobj, &gta01_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;
+ struct gta01_pm_bt_data *bt_data = dev_get_drvdata(&pdev->dev);
struct regulator *regulator;
sysfs_remove_group(&pdev->dev.kobj, &gta01_bt_attr_group);
- rfkill_unregister(rfkill);
- rfkill_free(rfkill);
+ if (bt_data->rfkill) {
+ rfkill_unregister(bt_data->rfkill);
+ rfkill_free(bt_data->rfkill);
+ }
- bt_data = dev_get_drvdata(&pdev->dev);
if (!bt_data || !bt_data->regulator)
return 0;
@@ -292,6 +289,8 @@ static int gta01_bt_remove(struct platform_device *pdev)
regulator_disable(regulator);
regulator_put(regulator);
+
+ kfree(bt_data);
return 0;
}