aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorThomas White <taw@bitwiz.org.uk>2009-09-11 12:49:39 +0100
committerThomas White <taw@bitwiz.org.uk>2009-09-11 12:49:39 +0100
commitcd38bcdac64aec45575ed58de66db4a2fbf1914d (patch)
tree450333c7a1c67685db627edda3e1376a5bd46a2e /drivers
parent166226209d59b1210cadfdec6b31e7d633100d9d (diff)
parenta3587e4ed77974adfb057af261aaeea4022018e8 (diff)
Merge commit 'remotes/openmoko/andy-tracking' into drm-tracking
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ar6000/ar6000/ar6000_drv.c150
-rw-r--r--drivers/input/keyboard/neo1973kbd.c6
-rw-r--r--drivers/mfd/glamo/glamo-fb.c4
-rw-r--r--drivers/mfd/glamo/glamo-mci.c2
-rw-r--r--drivers/mfd/pcf50606-core.c6
-rw-r--r--drivers/mfd/pcf50633-adc.c32
-rw-r--r--drivers/mfd/pcf50633-core.c9
-rw-r--r--drivers/power/Kconfig1
-rw-r--r--drivers/power/bq27000_battery.c3
-rw-r--r--drivers/power/gta01_battery.c71
-rw-r--r--drivers/power/pcf50633-charger.c101
-rw-r--r--drivers/rtc/rtc-pcf50606.c9
-rw-r--r--drivers/usb/gadget/rndis.c19
13 files changed, 231 insertions, 182 deletions
diff --git a/drivers/ar6000/ar6000/ar6000_drv.c b/drivers/ar6000/ar6000/ar6000_drv.c
index b790670ece8..21504f221dd 100644
--- a/drivers/ar6000/ar6000/ar6000_drv.c
+++ b/drivers/ar6000/ar6000/ar6000_drv.c
@@ -974,17 +974,86 @@ ar6000_destroy(struct net_device *dev, unsigned int unregister)
return;
}
+ /* Stop the transmit queues */
+ netif_stop_queue(dev);
+
+ /* Disable the target and the interrupts associated with it */
+ if (ar->arWmiReady == TRUE)
+ {
+ if (!bypasswmi)
+ {
+ if (ar->arConnected == TRUE || ar->arConnectPending == TRUE)
+ {
+ AR_DEBUG_PRINTF("%s(): Disconnect\n", __func__);
+ AR6000_SPIN_LOCK(&ar->arLock, 0);
+ ar6000_init_profile_info(ar);
+ AR6000_SPIN_UNLOCK(&ar->arLock, 0);
+ wmi_disconnect_cmd(ar->arWmi);
+ }
+
+ ar6000_dbglog_get_debug_logs(ar);
+ ar->arWmiReady = FALSE;
+ ar->arConnected = FALSE;
+ ar->arConnectPending = FALSE;
+ wmi_shutdown(ar->arWmi);
+ ar->arWmiEnabled = FALSE;
+ ar->arWmi = NULL;
+ ar->arWlanState = WLAN_ENABLED;
+#ifdef USER_KEYS
+ ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
+ ar->user_key_ctrl = 0;
+#endif
+ }
+
+ AR_DEBUG_PRINTF("%s(): WMI stopped\n", __func__);
+ }
+ else
+ {
+ AR_DEBUG_PRINTF("%s(): WMI not ready 0x%08x 0x%08x\n",
+ __func__, (unsigned int) ar, (unsigned int) ar->arWmi);
+
+ /* Shut down WMI if we have started it */
+ if(ar->arWmiEnabled == TRUE)
+ {
+ AR_DEBUG_PRINTF("%s(): Shut down WMI\n", __func__);
+ wmi_shutdown(ar->arWmi);
+ ar->arWmiEnabled = FALSE;
+ ar->arWmi = NULL;
+ }
+ }
+
+ /* stop HTC */
+ HTCStop(ar->arHtcTarget);
+
+ /* set the instance to NULL so we do not get called back on remove incase we
+ * we're explicity destroyed by module unload */
+ HTCSetInstance(ar->arHtcTarget, NULL);
+
+ if (resetok) {
+ /* try to reset the device if we can
+ * The driver may have been configure NOT to reset the target during
+ * a debug session */
+ AR_DEBUG_PRINTF(" Attempting to reset target on instance destroy.... \n");
+ ar6000_reset_device(ar->arHifDevice, ar->arTargetType);
+ } else {
+ AR_DEBUG_PRINTF(" Host does not want target reset. \n");
+ }
+
+ /* Done with cookies */
+ ar6000_cookie_cleanup(ar);
+
+ /* Cleanup BMI */
+ BMIInit();
+
/* Clear the tx counters */
memset(tx_attempt, 0, sizeof(tx_attempt));
memset(tx_post, 0, sizeof(tx_post));
memset(tx_complete, 0, sizeof(tx_complete));
+
/* Free up the device data structure */
- if (unregister) {
- unregister_netdev(dev);
- } else {
- ar6000_close(dev);
- }
+ if (unregister)
+ unregister_netdev(dev);
free_raw_buffers(ar);
@@ -1090,79 +1159,8 @@ ar6000_open(struct net_device *dev)
static int
ar6000_close(struct net_device *dev)
{
- AR_SOFTC_T *ar = netdev_priv(dev);
-
- /* Stop the transmit queues */
netif_stop_queue(dev);
- /* Disable the target and the interrupts associated with it */
- if (ar->arWmiReady == TRUE)
- {
- if (!bypasswmi)
- {
- if (ar->arConnected == TRUE || ar->arConnectPending == TRUE)
- {
- AR_DEBUG_PRINTF("%s(): Disconnect\n", __func__);
- AR6000_SPIN_LOCK(&ar->arLock, 0);
- ar6000_init_profile_info(ar);
- AR6000_SPIN_UNLOCK(&ar->arLock, 0);
- wmi_disconnect_cmd(ar->arWmi);
- }
-
- ar6000_dbglog_get_debug_logs(ar);
- ar->arWmiReady = FALSE;
- ar->arConnected = FALSE;
- ar->arConnectPending = FALSE;
- wmi_shutdown(ar->arWmi);
- ar->arWmiEnabled = FALSE;
- ar->arWmi = NULL;
- ar->arWlanState = WLAN_ENABLED;
-#ifdef USER_KEYS
- ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
- ar->user_key_ctrl = 0;
-#endif
- }
-
- AR_DEBUG_PRINTF("%s(): WMI stopped\n", __func__);
- }
- else
- {
- AR_DEBUG_PRINTF("%s(): WMI not ready 0x%08x 0x%08x\n",
- __func__, (unsigned int) ar, (unsigned int) ar->arWmi);
-
- /* Shut down WMI if we have started it */
- if(ar->arWmiEnabled == TRUE)
- {
- AR_DEBUG_PRINTF("%s(): Shut down WMI\n", __func__);
- wmi_shutdown(ar->arWmi);
- ar->arWmiEnabled = FALSE;
- ar->arWmi = NULL;
- }
- }
-
- /* stop HTC */
- HTCStop(ar->arHtcTarget);
-
- /* set the instance to NULL so we do not get called back on remove incase we
- * we're explicity destroyed by module unload */
- HTCSetInstance(ar->arHtcTarget, NULL);
-
- if (resetok) {
- /* try to reset the device if we can
- * The driver may have been configure NOT to reset the target during
- * a debug session */
- AR_DEBUG_PRINTF(" Attempting to reset target on instance destroy.... \n");
- ar6000_reset_device(ar->arHifDevice, ar->arTargetType);
- } else {
- AR_DEBUG_PRINTF(" Host does not want target reset. \n");
- }
-
- /* Done with cookies */
- ar6000_cookie_cleanup(ar);
-
- /* Cleanup BMI */
- BMIInit();
-
return 0;
}
diff --git a/drivers/input/keyboard/neo1973kbd.c b/drivers/input/keyboard/neo1973kbd.c
index a95dd5806d2..8756ae60910 100644
--- a/drivers/input/keyboard/neo1973kbd.c
+++ b/drivers/input/keyboard/neo1973kbd.c
@@ -75,7 +75,7 @@ static struct neo1973kbd_key keys[] = {
[NEO1973_KEY_HOLD] = {
.name = "Neo1973 HOLD button",
.isr = neo1973kbd_default_key_irq,
- .input_key = KEY_PAUSE,
+ .input_key = KEY_PLAY,
},
[NEO1973_KEY_JACK] = {
.name = "Neo1973 Headphone jack",
@@ -161,7 +161,7 @@ static irqreturn_t neo1973kbd_default_key_irq(int irq, void *dev_id)
continue;
input_report_key(kbd->input, keys[n].input_key,
- gpio_get_value(kbd->pdev->resource[n].start));
+ !gpio_get_value(kbd->pdev->resource[n].start));
input_sync(kbd->input);
}
@@ -346,7 +346,7 @@ static int neo1973kbd_probe(struct platform_device *pdev)
input_dev->evbit[0] = BIT(EV_KEY) | BIT(EV_SW);
set_bit(SW_HEADPHONE_INSERT, input_dev->swbit);
set_bit(KEY_PHONE, input_dev->keybit);
- set_bit(KEY_PAUSE, input_dev->keybit);
+ set_bit(KEY_PLAY, input_dev->keybit);
rc = input_register_device(neo1973kbd->input);
if (rc)
diff --git a/drivers/mfd/glamo/glamo-fb.c b/drivers/mfd/glamo/glamo-fb.c
index 95d40d25cf7..06bbe8a505f 100644
--- a/drivers/mfd/glamo/glamo-fb.c
+++ b/drivers/mfd/glamo/glamo-fb.c
@@ -1067,7 +1067,7 @@ static int __init glamofb_probe(struct platform_device *pdev)
glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD);
glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD);
- dev_info(&pdev->dev, "spin_lock_init\n");
+ dev_dbg(&pdev->dev, "spin_lock_init\n");
spin_lock_init(&glamofb->lock_cmd);
glamofb_init_regs(glamofb);
#ifdef CONFIG_MFD_GLAMO_HWACCEL
@@ -1154,7 +1154,7 @@ static int glamofb_resume(struct platform_device *pdev)
glamo_engine_enable(mach_info->glamo, GLAMO_ENGINE_LCD);
glamo_engine_reset(mach_info->glamo, GLAMO_ENGINE_LCD);
- printk(KERN_ERR"spin_lock_init\n");
+ dev_dbg(&pdev->dev, "spin_lock_init\n");
spin_lock_init(&gfb->lock_cmd);
glamofb_init_regs(gfb);
#ifdef CONFIG_MFD_GLAMO_HWACCEL
diff --git a/drivers/mfd/glamo/glamo-mci.c b/drivers/mfd/glamo/glamo-mci.c
index 398f8634a9b..a3b4c5e4962 100644
--- a/drivers/mfd/glamo/glamo-mci.c
+++ b/drivers/mfd/glamo/glamo-mci.c
@@ -616,7 +616,7 @@ static void glamo_mci_send_request(struct mmc_host *mmc)
int insanity_timeout = 1000000;
if (host->suspending) {
- dev_err(&host->pdev->dev, "IGNORING glamo_mci_send_request while "
+ dev_dbg(&host->pdev->dev, "REFUSING glamo_mci_send_request while "
"suspended\n");
cmd->error = -EIO;
if (cmd->data)
diff --git a/drivers/mfd/pcf50606-core.c b/drivers/mfd/pcf50606-core.c
index 7c4fb42b460..09ce70b9b79 100644
--- a/drivers/mfd/pcf50606-core.c
+++ b/drivers/mfd/pcf50606-core.c
@@ -282,7 +282,7 @@ out:
int pcf50606_irq_mask(struct pcf50606 *pcf, int irq)
{
- dev_info(pcf->dev, "Masking IRQ %d\n", irq);
+ dev_dbg(pcf->dev, "Masking IRQ %d\n", irq);
return __pcf50606_irq_mask_set(pcf, irq, 1);
}
@@ -290,7 +290,7 @@ EXPORT_SYMBOL_GPL(pcf50606_irq_mask);
int pcf50606_irq_unmask(struct pcf50606 *pcf, int irq)
{
- dev_info(pcf->dev, "Unmasking IRQ %d\n", irq);
+ dev_dbg(pcf->dev, "Unmasking IRQ %d\n", irq);
return __pcf50606_irq_mask_set(pcf, irq, 0);
}
@@ -330,7 +330,7 @@ static void pcf50606_irq_worker(struct work_struct *work)
ret = pcf50606_read_block(pcf, PCF50606_REG_INT1,
ARRAY_SIZE(pcf_int), pcf_int);
if (ret != ARRAY_SIZE(pcf_int)) {
- dev_info(pcf->dev, "Error reading INT registers\n");
+ dev_err(pcf->dev, "Error reading INT registers\n");
/*
* If this doesn't ACK the interrupt to the chip, we'll be
diff --git a/drivers/mfd/pcf50633-adc.c b/drivers/mfd/pcf50633-adc.c
index c2d05becfa9..3d31e97d6a4 100644
--- a/drivers/mfd/pcf50633-adc.c
+++ b/drivers/mfd/pcf50633-adc.c
@@ -73,15 +73,10 @@ static void trigger_next_adc_job_if_any(struct pcf50633 *pcf)
struct pcf50633_adc *adc = __to_adc(pcf);
int head;
- mutex_lock(&adc->queue_mutex);
-
head = adc->queue_head;
- if (!adc->queue[head]) {
- mutex_unlock(&adc->queue_mutex);
+ if (!adc->queue[head])
return;
- }
- mutex_unlock(&adc->queue_mutex);
adc_setup(pcf, adc->queue[head]->mux, adc->queue[head]->avg);
}
@@ -99,16 +94,17 @@ adc_enqueue_request(struct pcf50633 *pcf, struct pcf50633_adc_request *req)
if (adc->queue[tail]) {
mutex_unlock(&adc->queue_mutex);
+ dev_err(pcf->dev, "ADC queue is full, dropping request\n");
return -EBUSY;
}
adc->queue[tail] = req;
+ if (head == tail)
+ trigger_next_adc_job_if_any(pcf);
adc->queue_tail = (tail + 1) & (PCF50633_MAX_ADC_FIFO_DEPTH - 1);
mutex_unlock(&adc->queue_mutex);
- trigger_next_adc_job_if_any(pcf);
-
return 0;
}
@@ -124,6 +120,7 @@ pcf50633_adc_sync_read_callback(struct pcf50633 *pcf, void *param, int result)
int pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg)
{
struct pcf50633_adc_request *req;
+ int err;
/* req is freed when the result is ready, in interrupt handler */
req = kzalloc(sizeof(*req), GFP_KERNEL);
@@ -136,9 +133,13 @@ int pcf50633_adc_sync_read(struct pcf50633 *pcf, int mux, int avg)
req->callback_param = req;
init_completion(&req->completion);
- adc_enqueue_request(pcf, req);
+ err = adc_enqueue_request(pcf, req);
+ if (err)
+ return err;
+
wait_for_completion(&req->completion);
+ /* FIXME by this time req might be already freed */
return req->result;
}
EXPORT_SYMBOL_GPL(pcf50633_adc_sync_read);
@@ -159,9 +160,7 @@ int pcf50633_adc_async_read(struct pcf50633 *pcf, int mux, int avg,
req->callback = callback;
req->callback_param = callback_param;
- adc_enqueue_request(pcf, req);
-
- return 0;
+ return adc_enqueue_request(pcf, req);
}
EXPORT_SYMBOL_GPL(pcf50633_adc_async_read);
@@ -184,7 +183,7 @@ static void pcf50633_adc_irq(int irq, void *data)
struct pcf50633_adc *adc = data;
struct pcf50633 *pcf = adc->pcf;
struct pcf50633_adc_request *req;
- int head;
+ int head, res;
mutex_lock(&adc->queue_mutex);
head = adc->queue_head;
@@ -199,12 +198,13 @@ static void pcf50633_adc_irq(int irq, void *data)
adc->queue_head = (head + 1) &
(PCF50633_MAX_ADC_FIFO_DEPTH - 1);
+ res = adc_result(pcf);
+ trigger_next_adc_job_if_any(pcf);
+
mutex_unlock(&adc->queue_mutex);
- req->callback(pcf, req->callback_param, adc_result(pcf));
+ req->callback(pcf, req->callback_param, res);
kfree(req);
-
- trigger_next_adc_job_if_any(pcf);
}
static int __devinit pcf50633_adc_probe(struct platform_device *pdev)
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 29c9395d65f..b3c96015600 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -291,7 +291,7 @@ out:
int pcf50633_irq_mask(struct pcf50633 *pcf, int irq)
{
- dev_info(pcf->dev, "Masking IRQ %d\n", irq);
+ dev_dbg(pcf->dev, "Masking IRQ %d\n", irq);
return __pcf50633_irq_mask_set(pcf, irq, 1);
}
@@ -299,7 +299,7 @@ EXPORT_SYMBOL_GPL(pcf50633_irq_mask);
int pcf50633_irq_unmask(struct pcf50633 *pcf, int irq)
{
- dev_info(pcf->dev, "Unmasking IRQ %d\n", irq);
+ dev_dbg(pcf->dev, "Unmasking IRQ %d\n", irq);
return __pcf50633_irq_mask_set(pcf, irq, 0);
}
@@ -448,7 +448,7 @@ static irqreturn_t pcf50633_irq(int irq, void *data)
get_device(pcf->dev);
disable_irq(pcf->irq);
- schedule_work(&pcf->irq_work);
+ queue_work(pcf->work_queue, &pcf->irq_work);
return IRQ_HANDLED;
}
@@ -579,6 +579,7 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
pcf->dev = &client->dev;
pcf->i2c_client = client;
pcf->irq = client->irq;
+ pcf->work_queue = create_singlethread_workqueue("pcf50633");
INIT_WORK(&pcf->irq_work, pcf50633_irq_worker);
@@ -656,6 +657,7 @@ static int __devinit pcf50633_probe(struct i2c_client *client,
return 0;
err:
+ destroy_workqueue(pcf->work_queue);
kfree(pcf);
return ret;
}
@@ -666,6 +668,7 @@ static int __devexit pcf50633_remove(struct i2c_client *client)
int i;
free_irq(pcf->irq, pcf);
+ destroy_workqueue(pcf->work_queue);
platform_device_unregister(pcf->input_pdev);
platform_device_unregister(pcf->rtc_pdev);
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index b5332f714cd..f88c5aab640 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -90,6 +90,7 @@ config CHARGER_PCF50633
config BATTERY_BQ27000_HDQ
tristate "BQ27000 HDQ battery monitor driver"
+ select HDQ_GPIO_BITBANG
help
Say Y to enable support for the battery on the Neo Freerunner
diff --git a/drivers/power/bq27000_battery.c b/drivers/power/bq27000_battery.c
index 593cbe6f752..f1dcda3297d 100644
--- a/drivers/power/bq27000_battery.c
+++ b/drivers/power/bq27000_battery.c
@@ -186,6 +186,9 @@ static int bq27000_battery_get_property(struct power_supply *psy,
int n;
struct bq27000_device_info *di = container_of(psy, struct bq27000_device_info, bat);
+ if (di->regs.rsoc < 0 && psp != POWER_SUPPLY_PROP_PRESENT)
+ return -ENODEV;
+
switch (psp) {
case POWER_SUPPLY_PROP_STATUS:
val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
diff --git a/drivers/power/gta01_battery.c b/drivers/power/gta01_battery.c
index 81a0fe7387e..2078b071b06 100644
--- a/drivers/power/gta01_battery.c
+++ b/drivers/power/gta01_battery.c
@@ -23,8 +23,40 @@ static enum power_supply_property gta01_bat_props[] = {
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CURRENT_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
};
+/* Capacity of typical BL-5C dumb battery */
+#define GTA01_BAT_CHARGE_FULL 850000
+
+static int gta01_bat_voltscale(int volt)
+{
+ /* This table is suggested by SpeedEvil based on analysis of
+ * experimental data */
+ static const int lut[][2] = {
+ { 4120, 100 },
+ { 3900, 60 },
+ { 3740, 25 },
+ { 3600, 5 },
+ { 3000, 0 } };
+ int i, res = 0;
+
+ if (volt > lut[0][0])
+ res = lut[0][1];
+ else
+ for (i = 0; lut[i][1]; i++) {
+ if (volt <= lut[i][0] && volt >= lut[i+1][0]) {
+ res = lut[i][1] - (lut[i][0]-volt)*
+ (lut[i][1]-lut[i+1][1])/
+ (lut[i][0]-lut[i+1][0]);
+ break;
+ }
+ }
+ return res;
+}
+
static int gta01_bat_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
@@ -33,20 +65,48 @@ static int gta01_bat_get_property(struct power_supply *psy,
switch(psp) {
case POWER_SUPPLY_PROP_STATUS:
- if (bat->pdata->get_charging_status())
- val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ if (bat->pdata->get_charging_status)
+ if (bat->pdata->get_charging_status())
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
else
- val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- val->intval = bat->pdata->get_voltage();
+ if (bat->pdata->get_voltage)
+ val->intval = bat->pdata->get_voltage();
+ else
+ val->intval = 0;
break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
- val->intval = bat->pdata->get_current();
+ if (bat->pdata->get_current)
+ val->intval = bat->pdata->get_current();
+ else
+ val->intval = 0;
break;
case POWER_SUPPLY_PROP_PRESENT:
val->intval = 1; /* You must never run GTA01 without battery. */
break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ if (bat->pdata->get_voltage) {
+ int perc = gta01_bat_voltscale(
+ bat->pdata->get_voltage()/1000);
+ val->intval = perc * GTA01_BAT_CHARGE_FULL / 100;
+ } else
+ val->intval = 0;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ if (bat->pdata->get_voltage)
+ val->intval = gta01_bat_voltscale(
+ bat->pdata->get_voltage()/1000);
+ else
+ val->intval = 0;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ val->intval = GTA01_BAT_CHARGE_FULL;
+ break;
+
default:
return -EINVAL;
}
@@ -76,6 +136,7 @@ static int gta01_battery_probe(struct platform_device *pdev)
gta01_bat->psy.external_power_changed = gta01_bat_ext_changed;
gta01_bat->pdata = pdev->dev.platform_data;
+ platform_set_drvdata(pdev, gta01_bat);
power_supply_register(&pdev->dev, &gta01_bat->psy);
return 0;
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
index 1bdb9906201..6fbe26eb756 100644
--- a/drivers/power/pcf50633-charger.c
+++ b/drivers/power/pcf50633-charger.c
@@ -29,16 +29,12 @@
struct pcf50633_mbc {
struct pcf50633 *pcf;
- int adapter_active;
int adapter_online;
- int usb_active;
int usb_online;
struct power_supply usb;
struct power_supply adapter;
struct power_supply ac;
-
- struct delayed_work charging_restart_work;
};
int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
@@ -92,17 +88,19 @@ int pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK);
/* If chgmod == BATFULL, setting chgena has no effect.
- * We need to set resume instead.
+ * Datasheet says we need to set resume instead but when autoresume is
+ * used resume doesn't work. Clear and set chgena instead.
*/
if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL)
pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1,
PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA);
- else
+ else {
+ pcf50633_reg_clear_bits(pcf, PCF50633_REG_MBCC1,
+ PCF50633_MBCC1_CHGENA);
pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1,
- PCF50633_MBCC1_RESUME, PCF50633_MBCC1_RESUME);
+ PCF50633_MBCC1_CHGENA, PCF50633_MBCC1_CHGENA);
+ }
- mbc->usb_active = charging_start;
-
power_supply_changed(&mbc->usb);
return ret;
@@ -113,23 +111,44 @@ int pcf50633_mbc_get_status(struct pcf50633 *pcf)
{
struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
int status = 0;
+ u8 chgmod;
if (!mbc)
return 0;
+ chgmod = pcf50633_reg_read(pcf, PCF50633_REG_MBCS2)
+ & PCF50633_MBCS2_MBC_MASK;
+
if (mbc->usb_online)
status |= PCF50633_MBC_USB_ONLINE;
- if (mbc->usb_active)
+ if (chgmod == PCF50633_MBCS2_MBC_USB_PRE ||
+ chgmod == PCF50633_MBCS2_MBC_USB_PRE_WAIT ||
+ chgmod == PCF50633_MBCS2_MBC_USB_FAST ||
+ chgmod == PCF50633_MBCS2_MBC_USB_FAST_WAIT)
status |= PCF50633_MBC_USB_ACTIVE;
if (mbc->adapter_online)
status |= PCF50633_MBC_ADAPTER_ONLINE;
- if (mbc->adapter_active)
+ if (chgmod == PCF50633_MBCS2_MBC_ADP_PRE ||
+ chgmod == PCF50633_MBCS2_MBC_ADP_PRE_WAIT ||
+ chgmod == PCF50633_MBCS2_MBC_ADP_FAST ||
+ chgmod == PCF50633_MBCS2_MBC_ADP_FAST_WAIT)
status |= PCF50633_MBC_ADAPTER_ACTIVE;
return status;
}
EXPORT_SYMBOL_GPL(pcf50633_mbc_get_status);
+int pcf50633_mbc_get_usb_online_status(struct pcf50633 *pcf)
+{
+ struct pcf50633_mbc *mbc = platform_get_drvdata(pcf->mbc_pdev);
+
+ if (!mbc)
+ return 0;
+
+ return mbc->usb_online;
+}
+EXPORT_SYMBOL_GPL(pcf50633_mbc_get_usb_online_status);
+
static ssize_t
show_chgmode(struct device *dev, struct device_attribute *attr, char *buf)
{
@@ -226,75 +245,24 @@ static struct attribute_group mbc_attr_group = {
.attrs = pcf50633_mbc_sysfs_entries,
};
-/* MBC state machine switches into charging mode when the battery voltage
- * falls below 96% of a battery float voltage. But the voltage drop in Li-ion
- * batteries is marginal(1~2 %) till about 80% of its capacity - which means,
- * after a BATFULL, charging won't be restarted until 80%.
- *
- * This work_struct function restarts charging every few seconds and makes
- * sure we don't discharge too much
- */
-
-static void pcf50633_mbc_charging_restart(struct work_struct *work)
-{
- struct pcf50633_mbc *mbc;
- u8 mbcs2, chgmod;
-
- mbc = container_of(work, struct pcf50633_mbc,
- charging_restart_work.work);
-
- mbcs2 = pcf50633_reg_read(mbc->pcf, PCF50633_REG_MBCS2);
- chgmod = (mbcs2 & PCF50633_MBCS2_MBC_MASK);
-
- if (chgmod != PCF50633_MBCS2_MBC_BAT_FULL)
- return;
-
- /* Restart charging */
- pcf50633_reg_set_bit_mask(mbc->pcf, PCF50633_REG_MBCC1,
- PCF50633_MBCC1_RESUME, PCF50633_MBCC1_RESUME);
- mbc->usb_active = 1;
- power_supply_changed(&mbc->usb);
-
- dev_info(mbc->pcf->dev, "Charging restarted\n");
-}
-
static void
pcf50633_mbc_irq_handler(int irq, void *data)
{
struct pcf50633_mbc *mbc = data;
- int chg_restart_interval =
- mbc->pcf->pdata->charging_restart_interval;
/* USB */
if (irq == PCF50633_IRQ_USBINS) {
mbc->usb_online = 1;
} else if (irq == PCF50633_IRQ_USBREM) {
mbc->usb_online = 0;
- mbc->usb_active = 0;
pcf50633_mbc_usb_curlim_set(mbc->pcf, 0);
- cancel_delayed_work_sync(&mbc->charging_restart_work);
}
/* Adapter */
- if (irq == PCF50633_IRQ_ADPINS) {
+ if (irq == PCF50633_IRQ_ADPINS)
mbc->adapter_online = 1;
- mbc->adapter_active = 1;
- } else if (irq == PCF50633_IRQ_ADPREM) {
+ else if (irq == PCF50633_IRQ_ADPREM)
mbc->adapter_online = 0;
- mbc->adapter_active = 0;
- }
-
- if (irq == PCF50633_IRQ_BATFULL) {
- mbc->usb_active = 0;
- mbc->adapter_active = 0;
-
- if (chg_restart_interval > 0)
- schedule_delayed_work(&mbc->charging_restart_work,
- chg_restart_interval);
- } else if (irq == PCF50633_IRQ_USBLIMON)
- mbc->usb_active = 0;
- else if (irq == PCF50633_IRQ_USBLIMOFF)
- mbc->usb_active = 1;
power_supply_changed(&mbc->usb);
power_supply_changed(&mbc->adapter);
@@ -428,9 +396,6 @@ static int __devinit pcf50633_mbc_probe(struct platform_device *pdev)
mbc->ac.supplied_to = mbc->pcf->pdata->batteries;
mbc->ac.num_supplicants = mbc->pcf->pdata->num_batteries;
- INIT_DELAYED_WORK(&mbc->charging_restart_work,
- pcf50633_mbc_charging_restart);
-
ret = power_supply_register(&pdev->dev, &mbc->adapter);
if (ret) {
dev_err(mbc->pcf->dev, "failed to register adapter\n");
@@ -480,8 +445,6 @@ static int __devexit pcf50633_mbc_remove(struct platform_device *pdev)
power_supply_unregister(&mbc->usb);
power_supply_unregister(&mbc->adapter);
- cancel_delayed_work_sync(&mbc->charging_restart_work);
-
kfree(mbc);
return 0;
diff --git a/drivers/rtc/rtc-pcf50606.c b/drivers/rtc/rtc-pcf50606.c
index 434cfc1dca4..6bd93b0b672 100644
--- a/drivers/rtc/rtc-pcf50606.c
+++ b/drivers/rtc/rtc-pcf50606.c
@@ -58,6 +58,7 @@ struct pcf50606_time {
struct pcf50606_rtc {
int alarm_enabled;
int second_enabled;
+ int alarm_pending;
struct pcf50606 *pcf;
struct rtc_device *rtc_dev;
@@ -198,6 +199,7 @@ static int pcf50606_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
rtc = dev_get_drvdata(dev);
alrm->enabled = rtc->alarm_enabled;
+ alrm->pending = rtc->alarm_pending;
ret = pcf50606_read_block(rtc->pcf, PCF50606_REG_RTCSCA,
PCF50606_TI_EXTENT, &pcf_tm.time[0]);
@@ -234,8 +236,12 @@ static int pcf50606_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm)
ret = pcf50606_write_block(rtc->pcf, PCF50606_REG_RTCSCA,
PCF50606_TI_EXTENT, &pcf_tm.time[0]);
- if (!alarm_masked)
+ if (!alrm->enabled)
+ rtc->alarm_pending = 0;
+
+ if (!alarm_masked || alrm->enabled)
pcf50606_irq_unmask(rtc->pcf, PCF50606_IRQ_ALARM);
+ rtc->alarm_enabled = alrm->enabled;
return ret;
}
@@ -255,6 +261,7 @@ static void pcf50606_rtc_irq(int irq, void *data)
switch (irq) {
case PCF50606_IRQ_ALARM:
rtc_update_irq(rtc->rtc_dev, 1, RTC_AF | RTC_IRQF);
+ rtc->alarm_pending = 1;
break;
case PCF50606_IRQ_SECOND:
rtc_update_irq(rtc->rtc_dev, 1, RTC_UF | RTC_IRQF);
diff --git a/drivers/usb/gadget/rndis.c b/drivers/usb/gadget/rndis.c
index 8c26f5ea2b8..c719b1efcbc 100644
--- a/drivers/usb/gadget/rndis.c
+++ b/drivers/usb/gadget/rndis.c
@@ -294,9 +294,22 @@ gen_ndis_query_resp (int configNr, u32 OID, u8 *buf, unsigned buf_len,
/* mandatory */
case OID_GEN_VENDOR_DESCRIPTION:
pr_debug("%s: OID_GEN_VENDOR_DESCRIPTION\n", __func__);
- length = strlen (rndis_per_dev_params [configNr].vendorDescr);
- memcpy (outbuf,
- rndis_per_dev_params [configNr].vendorDescr, length);
+
+ if (rndis_per_dev_params[configNr].vendorDescr) {
+ length = strlen(
+ rndis_per_dev_params[configNr].vendorDescr);
+ memcpy(outbuf,
+ rndis_per_dev_params[configNr].vendorDescr,
+ length);
+ } else {
+ /*
+ * FIXME: Openmoko hack by Paul Fertser to avoid
+ * panic with Win XP SP2 when vendorDescr is NULL
+ * (always ATM).
+ */
+ length = 5;
+ memcpy(outbuf, "dummy", length);
+ }
retval = 0;
break;