aboutsummaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authormerge <null@invalid>2008-12-08 22:50:52 +0000
committerAndy Green <agreen@pads.home.warmcat.com>2008-12-08 22:50:52 +0000
commitebb3f320edcc6c4665a71ea060ef2ce6a83402b0 (patch)
treebcc900f37c2f7ab72addce6555263bfe1dd85aca /drivers
parent31383993decd60a7cc783f402ad83ee8580008d3 (diff)
MERGE-via-pending-tracking-hist-MERGE-via-stable-tracking-fix-s3c2410_ts-fifo-allocation-1228776491
pending-tracking-hist top was MERGE-via-stable-tracking-fix-s3c2410_ts-fifo-allocation-1228776491 / a85a8a282939b4f6800081f67e1d568e0b97bd7a ... parent commitmessage: From: merge <null@invalid> MERGE-via-stable-tracking-hist-fix-s3c2410_ts-fifo-allocation stable-tracking-hist top was fix-s3c2410_ts-fifo-allocation / 56a57ba0d4c1d60869250d5f89fae61544f01012 ... parent commitmessage: From: Nelson Castillo <nelsoneci@gmail.com> Fix s3c2410_ts FIFO allocation When I added the FIFO improving the interrupts handlers I introduced a bug. The FIFO is allocated after the interrupts are requested. This makes the kernel crash if the touchscreen generates activity before the allocation takes place. This patch fixes the bug. I reproduced it and tested the fix in a GTA02. - Fix bug - Fix a typo Reported-by: Andy Green <andy@openmoko.com> Signed-off-by: Nelson Castillo <nelsoneci@gmail.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/input/touchscreen/s3c2410_ts.c19
-rw-r--r--drivers/mfd/pcf50633-core.c74
-rw-r--r--drivers/power/pcf50633-charger.c81
3 files changed, 134 insertions, 40 deletions
diff --git a/drivers/input/touchscreen/s3c2410_ts.c b/drivers/input/touchscreen/s3c2410_ts.c
index 8e6bc0a0371..4159adaec7c 100644
--- a/drivers/input/touchscreen/s3c2410_ts.c
+++ b/drivers/input/touchscreen/s3c2410_ts.c
@@ -427,6 +427,11 @@ static int __init s3c2410ts_probe(struct platform_device *pdev)
ts.dev->id.product = 0xBEEF;
ts.dev->id.version = S3C2410TSVERSION;
ts.state = TS_STATE_STANDBY;
+ ts.event_fifo = kfifo_alloc(TS_EVENT_FIFO_SIZE, GFP_KERNEL, NULL);
+ if (IS_ERR(ts.event_fifo)) {
+ ret = -EIO;
+ goto bail2;
+ }
/* create the filter chain set up for the 2 coordinates we produce */
ret = ts_filter_create_chain(
@@ -459,26 +464,17 @@ static int __init s3c2410ts_probe(struct platform_device *pdev)
goto bail4;
}
- ts.event_fifo = kfifo_alloc(TS_EVENT_FIFO_SIZE, GFP_KERNEL, NULL);
-
- if (IS_ERR(ts.event_fifo)) {
- ret = -EIO;
- goto bail5;
- }
-
dev_info(&pdev->dev, "successfully loaded\n");
/* All went ok, so register to the input system */
rc = input_register_device(ts.dev);
if (rc) {
ret = -EIO;
- goto bail6;
+ goto bail5;
}
return 0;
-bail6:
- kfifo_free(ts.event_fifo);
bail5:
free_irq(IRQ_TC, ts.dev);
free_irq(IRQ_ADC, ts.dev);
@@ -489,7 +485,8 @@ bail4:
disable_irq(IRQ_ADC);
bail3:
ts_filter_destroy_chain(ts.tsf);
-
+ kfifo_free(ts.event_fifo);
+bail2:
input_unregister_device(ts.dev);
bail1:
iounmap(base_addr);
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 6634558ea91..2079d303000 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -28,6 +28,7 @@
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/platform_device.h>
+#include <linux/delay.h>
#include <linux/mfd/pcf50633/core.h>
@@ -292,10 +293,11 @@ static void pcf50633_irq_worker(struct work_struct *work)
pcf_int[0] &= ~(1 << PCF50633_INT1_ADPINS);
}
+#if 0
dev_info(pcf->dev, "INT1=0x%02x INT2=0x%02x INT3=0x%02x "
"INT4=0x%02x INT5=0x%02x\n", pcf_int[0],
pcf_int[1], pcf_int[2], pcf_int[3], pcf_int[4]);
-
+#endif
/* Some revisions of the chip don't have a 8s standby mode on
* ONKEY1S press. We try to manually do it in such cases. */
@@ -377,8 +379,6 @@ static irqreturn_t pcf50633_irq(int irq, void *data)
{
struct pcf50633 *pcf = data;
- printk(KERN_ERR "pcf50633_irq\n");
-
get_device(pcf->dev);
disable_irq(pcf->irq);
@@ -474,15 +474,17 @@ static int pcf50633_resume(struct device *dev)
#define pcf50633_resume NULL
#endif
+
static int pcf50633_probe(struct i2c_client *client,
const struct i2c_device_id *ids)
{
struct pcf50633 *pcf;
struct pcf50633_platform_data *pdata;
- int i, ret = 0;
- u8 mbcs1;
+ int ret = 0;
int version;
int variant;
+ u8 mbcs1;
+ int i;
pdata = client->dev.platform_data;
@@ -518,7 +520,7 @@ static int pcf50633_probe(struct i2c_client *client,
dev_info(pcf->dev, "Probed device version %d variant %d\n",
version, variant);
- /* Enable all inteerupts except RTC SECOND */
+ /* Enable all interrupts except RTC SECOND */
pcf->mask_regs[0] = 0x80;
pcf50633_reg_write(pcf, PCF50633_REG_INT1M, 0x80);
@@ -535,22 +537,15 @@ static int pcf50633_probe(struct i2c_client *client,
&pcf->mbc.pdev);
pcf50633_client_dev_register(pcf, "pcf50633-adc",
&pcf->adc.pdev);
- for (i = 0; i < PCF50633_NUM_REGULATORS; i++) {
- struct platform_device *pdev;
- pdev = platform_device_alloc("pcf50633-regltr", i);
- if (!pdev) {
- dev_err(pcf->dev, "Cannot create regulator\n");
- continue;
- }
+ /* Cold Intialization */
+ mbcs1 = pcf50633_reg_read(pcf, PCF50633_REG_MBCS1);
- pdev->dev.parent = pcf->dev;
- pdev->dev.platform_data = &pdata->reg_init_data[i];
- pdev->dev.driver_data = pcf;
- pcf->pmic.pdev[i] = pdev;
+ if (mbcs1 & 0x01)
+ pcf50633_irq_call_handler(pcf, PCF50633_IRQ_USBINS);
+ if (mbcs1 & 0x04)
+ pcf50633_irq_call_handler(pcf, PCF50633_IRQ_ADPINS);
- platform_device_add(pdev);
- }
pcf->irq = client->irq;
@@ -571,20 +566,41 @@ static int pcf50633_probe(struct i2c_client *client,
dev_err(pcf->dev, "IRQ %u cannot be enabled as wake-up "
"source in this hardware revision\n", client->irq);
- /* Cold Intialization */
- mbcs1 = pcf50633_reg_read(pcf, PCF50633_REG_MBCS1);
-
- if (mbcs1 & 0x01)
- pcf50633_irq_call_handler(pcf, PCF50633_IRQ_USBINS);
- if (mbcs1 & 0x04)
- pcf50633_irq_call_handler(pcf, PCF50633_IRQ_ADPINS);
-
ret = sysfs_create_group(&client->dev.kobj, &pcf_attr_group);
if (ret)
dev_err(pcf->dev, "error creating sysfs entries\n");
- if (pdata->probe_done)
- pdata->probe_done(pcf);
+ /*
+ * give the system a chance to spin until power situation becomes
+ * good enough to continue boot. USB-based systems are only allowed to
+ * pull 100mA until enumerated when they can have up to 500mA for
+ * example
+ */
+
+ if (pcf->pdata->mbc_event_callback)
+ pcf->pdata->mbc_event_callback(pcf,
+ PCF50633_ABOUT_TO_INCREASE_POWER);
+
+ for (i = 0; i < PCF50633_NUM_REGULATORS; i++) {
+ struct platform_device *pdev;
+
+ pdev = platform_device_alloc("pcf50633-regltr", i);
+ if (!pdev) {
+ dev_err(pcf->dev, "Cannot create regulator\n");
+ continue;
+ }
+
+ pdev->dev.parent = pcf->dev;
+ pdev->dev.platform_data = &pcf->pdata->reg_init_data[i];
+ pdev->dev.driver_data = pcf;
+ pcf->pmic.pdev[i] = pdev;
+
+ platform_device_add(pdev);
+ }
+
+ if (pcf->pdata->probe_done)
+ pcf->pdata->probe_done(pcf);
+
return 0;
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
index 9bbfaac48a1..8e302c6c40e 100644
--- a/drivers/power/pcf50633-charger.c
+++ b/drivers/power/pcf50633-charger.c
@@ -23,9 +23,90 @@
* MA 02111-1307 USA
*/
+#include <linux/delay.h>
#include <linux/mfd/pcf50633/core.h>
#include <linux/mfd/pcf50633/mbc.h>
+/* this tells us the answer to "how am I set for power?" */
+
+enum pcf50633_power_avail pcf50633_check_power_available(struct pcf50633 *pcf)
+{
+ int ret;
+ int battery_ok;
+ int usb_present;
+
+ /* first look for adapter and USB power status */
+
+ ret = pcf50633_reg_read(pcf, PCF50633_REG_MBCS1);
+ if (ret < 0)
+ return ret;
+
+ if (ret & 8) /* adapter power present */
+ return PCF50633_PA_ADAPTER; /* don't care about anything else */
+
+ usb_present = ret & 2;
+
+ /* measure battery using PMU ADC */
+ /* disable charging momentarily so we can measure battery */
+
+ ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, 1, 0);
+ if (ret < 0)
+ return ret;
+
+ ret = pcf50633_adc_sync_read(pcf, PCF50633_ADCC1_MUX_BATSNS_RES,
+ PCF50633_ADCC1_AVERAGE_16);
+ if (ret < 0)
+ return ret;
+
+ battery_ok = (ret > pcf->pdata->good_main_battery_adc_threshold);
+
+ /* enable charging again */
+
+ ret = pcf50633_reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, 1, 1);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * now we know battery and USB situation
+ * make the decision now if possible
+ */
+
+ if (!usb_present && !battery_ok)
+ return PCF50633_PA_DEAD_BATTERY_ONLY;
+
+ if (!usb_present && battery_ok)
+ return PCF50633_PA_LIVE_BATTERY_ONLY;
+
+ /* So USB is present... what current limit? */
+
+ ret = pcf50633_reg_read(pcf, PCF50633_REG_MBCC7);
+ if (ret < 0)
+ return ret;
+
+ switch (ret & PCF50633_MBCC7_USB_MASK) {
+
+ case PCF50633_MBCC7_USB_100mA:
+ if (battery_ok)
+ return PCF50633_PA_USB_100mA_AND_LIVE_BATTERY;
+ else
+ return PCF50633_PA_USB_100mA_AND_DEAD_BATTERY;
+
+ case PCF50633_MBCC7_USB_500mA:
+ return PCF50633_PA_USB_500mA;
+
+ case PCF50633_MBCC7_USB_1000mA:
+ return PCF50633_PA_USB_1A;
+
+ default:
+ if (battery_ok)
+ return PCF50633_PA_LIVE_BATTERY_ONLY;
+ else
+ return PCF50633_PA_DEAD_BATTERY_ONLY;
+ }
+
+ return PCF50633_PA_DEAD_BATTERY_ONLY;
+}
+
void pcf50633_mbc_usb_curlim_set(struct pcf50633 *pcf, int ma)
{
int ret;