diff options
author | Thomas White <taw@bitwiz.org.uk> | 2009-09-11 12:49:39 +0100 |
---|---|---|
committer | Thomas White <taw@bitwiz.org.uk> | 2009-09-11 12:49:39 +0100 |
commit | cd38bcdac64aec45575ed58de66db4a2fbf1914d (patch) | |
tree | 450333c7a1c67685db627edda3e1376a5bd46a2e /drivers | |
parent | 166226209d59b1210cadfdec6b31e7d633100d9d (diff) | |
parent | a3587e4ed77974adfb057af261aaeea4022018e8 (diff) |
Merge commit 'remotes/openmoko/andy-tracking' into drm-tracking
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/ar6000/ar6000/ar6000_drv.c | 150 | ||||
-rw-r--r-- | drivers/input/keyboard/neo1973kbd.c | 6 | ||||
-rw-r--r-- | drivers/mfd/glamo/glamo-fb.c | 4 | ||||
-rw-r--r-- | drivers/mfd/glamo/glamo-mci.c | 2 | ||||
-rw-r--r-- | drivers/mfd/pcf50606-core.c | 6 | ||||
-rw-r--r-- | drivers/mfd/pcf50633-adc.c | 32 | ||||
-rw-r--r-- | drivers/mfd/pcf50633-core.c | 9 | ||||
-rw-r--r-- | drivers/power/Kconfig | 1 | ||||
-rw-r--r-- | drivers/power/bq27000_battery.c | 3 | ||||
-rw-r--r-- | drivers/power/gta01_battery.c | 71 | ||||
-rw-r--r-- | drivers/power/pcf50633-charger.c | 101 | ||||
-rw-r--r-- | drivers/rtc/rtc-pcf50606.c | 9 | ||||
-rw-r--r-- | drivers/usb/gadget/rndis.c | 19 |
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, >a01_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; |