r1577 - trunk/src/target/kernel/patches

laforge at sita.openmoko.org laforge at sita.openmoko.org
Fri Mar 30 21:27:12 CEST 2007


Author: laforge
Date: 2007-03-30 21:27:11 +0200 (Fri, 30 Mar 2007)
New Revision: 1577

Modified:
   trunk/src/target/kernel/patches/gta01-pcf50606.patch
Log:
* introduce platform_data usage for pcf50606 driver
* this makes it less GTA01 specific and rather a more generic pcf50606 driver


Modified: trunk/src/target/kernel/patches/gta01-pcf50606.patch
===================================================================
--- trunk/src/target/kernel/patches/gta01-pcf50606.patch	2007-03-30 19:23:34 UTC (rev 1576)
+++ trunk/src/target/kernel/patches/gta01-pcf50606.patch	2007-03-30 19:27:11 UTC (rev 1577)
@@ -3,8 +3,8 @@
 Index: linux-2.6.20.4/drivers/i2c/chips/pcf50606.c
 ===================================================================
 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.4/drivers/i2c/chips/pcf50606.c	2007-03-27 16:24:25.000000000 +0200
-@@ -0,0 +1,1633 @@
++++ linux-2.6.20.4/drivers/i2c/chips/pcf50606.c	2007-03-30 20:52:22.000000000 +0200
+@@ -0,0 +1,1710 @@
 +/* Philips PCF50606 Power Management Unit (PMU) driver
 + *
 + * (C) 2006 by OpenMoko, Inc.
@@ -64,10 +64,6 @@
 +#define DEBUGPC(x, args ...)
 +#endif
 +
-+/* Five seconds of power key press required to shut down */
-+
-+#define PCF50606_ONKEY_SECONDS_REQUIRED 5
-+
 +/***********************************************************************
 + * Static data / structures
 + ***********************************************************************/
@@ -94,6 +90,7 @@
 +
 +struct pcf50606_data {
 +	struct i2c_client client;
++	struct pcf50606_platform_data *pdata;
 +	struct mutex lock;
 +	unsigned int flags;
 +	unsigned int working;
@@ -122,6 +119,8 @@
 +struct pcf50606_data *pcf50606_global;
 +EXPORT_SYMBOL(pcf50606_global);
 +
++static struct platform_device *pcf50606_pdev;
++
 +/* This is a mitsubishi TN11-3H103J T,B NTC Thermistor -10..79 centigrade */
 +static const u_int16_t ntc_table_tn11_3h103j[] = {
 +	/* -10 */
@@ -601,7 +600,7 @@
 +				pcf->onkey_seconds, reg_read(pcf, PCF50606_REG_OOCC1));
 +			pcf->onkey_seconds++;
 +			if (pcf->onkey_seconds >=
-+			    PCF50606_ONKEY_SECONDS_REQUIRED) {
++			    pcf->pdata->onkey_seconds_required) {
 +				/* Ask init to do 'ctrlaltdel' */
 +				DEBUGPC("SIGINT(init) ");
 +				kill_proc(1, SIGINT, 1);
@@ -611,7 +610,9 @@
 +	}
 +	if (int1 & PCF50606_INT1_ALARM) {
 +		DEBUGPC("ALARM ");
-+		rtc_update_irq(&pcf->rtc->class_dev, 1, RTC_AF | RTC_IRQF);
++		if (pcf->pdata->used_features & PCF50606_FEAT_RTC)
++			rtc_update_irq(&pcf->rtc->class_dev, 1,
++				       RTC_AF | RTC_IRQF);
 +	}
 +
 +	if (int2 & PCF50606_INT2_CHGINS) {
@@ -850,6 +851,9 @@
 +/* Enable/disable fast charging (500mA in the GTA01) */
 +void pcf50606_charge_fast(struct pcf50606_data *pcf, int on)
 +{
++	if (!(pcf->pdata->used_features & PCF50606_FEAT_MBC))
++		return;
++
 +	if (on) {
 +		/* We can allow PCF to automatically charge
 +		 * using Ifast */
@@ -871,16 +875,14 @@
 +}
 +EXPORT_SYMBOL(pcf50606_charge_fast);
 +
-+#define PCF50606_R_FIXBATT	10000	/* 10 kOhms */
-+#define PCF50606_R_FIXBATT_PAR	10000	/* 10 kOhms */
 +#define ONE			1000000
-+static inline u_int16_t adc_to_rntc(u_int16_t adc)
++static inline u_int16_t adc_to_rntc(struct pcf50606_data *pcf, u_int16_t adc)
 +{
-+	u_int32_t r_batt = (adc * PCF50606_R_FIXBATT) / (1023 - adc);
++	u_int32_t r_batt = (adc * pcf->pdata->r_fix_batt) / (1023 - adc);
 +	u_int16_t r_ntc;
 +
 +	/* The battery NTC has a parallell 10kOhms resistor */
-+	r_ntc = ONE / ((ONE/r_batt) - (ONE/PCF50606_R_FIXBATT_PAR));
++	r_ntc = ONE / ((ONE/r_batt) - (ONE/pcf->pdata->r_fix_batt_par));
 +
 +	return r_ntc;
 +}
@@ -905,16 +907,16 @@
 +
 +	adc = adc_read(pcf, PCF50606_ADCMUX_BATTEMP, NULL);
 +
-+	return sprintf(buf, "%d\n", rntc_to_temp(adc_to_rntc(adc)));
++	return sprintf(buf, "%d\n", rntc_to_temp(adc_to_rntc(pcf, adc)));
 +}
 +static DEVICE_ATTR(battemp, S_IRUGO | S_IWUSR, show_battemp, NULL);
 +
-+#define MULT_R_SENSE_1024 225	/* 0.22 Ohms * 1024 */
-+static inline u_int16_t adc_to_chg_milliamps(u_int16_t adc_adcin1,
++static inline u_int16_t adc_to_chg_milliamps(struct pcf50606_data *pcf,
++					     u_int16_t adc_adcin1,
 +					     u_int16_t adc_batvolt)
 +{
 +	u_int32_t res = ((adc_adcin1 - adc_batvolt) * 6000);
-+	return res / MULT_R_SENSE_1024;
++	return res / (pcf->pdata->r_sense_milli * 1024 / 1000);
 +}
 +
 +static ssize_t show_chgcur(struct device *dev, struct device_attribute *attr,
@@ -927,7 +929,7 @@
 +
 +	adc_batvolt = adc_read(pcf, PCF50606_ADCMUX_BATVOLT_ADCIN1,
 +			       &adc_adcin1);
-+	ma = adc_to_chg_milliamps(adc_adcin1, adc_batvolt);
++	ma = adc_to_chg_milliamps(pcf, adc_adcin1, adc_batvolt);
 +
 +	return sprintf(buf, "%u\n", ma);
 +}
@@ -1357,12 +1359,7 @@
 +};
 +#endif
 +
-+static struct attribute *pcf_sysfs_entries[] = {
-+	&dev_attr_battvolt.attr,
-+	&dev_attr_battemp.attr,
-+	&dev_attr_chgcur.attr,
-+	&dev_attr_chgstate.attr,
-+	&dev_attr_chgmode.attr,
++static struct attribute *pcf_sysfs_entries[15] = {
 +	&dev_attr_voltage_dcd.attr,
 +	&dev_attr_voltage_dcde.attr,
 +	&dev_attr_voltage_dcud.attr,
@@ -1379,15 +1376,49 @@
 +	.attrs	= pcf_sysfs_entries,
 +};
 +
++static void populate_sysfs_group(struct pcf50606_data *pcf)
++{
++	int i = 0;
++	struct attribute *attr;
++
++	for (attr = pcf_sysfs_entries[0]; attr; attr++)
++		i++;
++
++	if (pcf->pdata->used_features & PCF50606_FEAT_MBC) {
++		pcf_sysfs_entries[i++] = &dev_attr_chgstate.attr;
++		pcf_sysfs_entries[i++] = &dev_attr_chgmode.attr;
++	}
++
++	if (pcf->pdata->used_features & PCF50606_FEAT_CHGCUR)
++		pcf_sysfs_entries[i++] = &dev_attr_chgcur.attr;
++
++	if (pcf->pdata->used_features & PCF50606_FEAT_BATVOLT)
++		pcf_sysfs_entries[i++] = &dev_attr_battvolt.attr;
++
++	if (pcf->pdata->used_features & PCF50606_FEAT_BATTEMP)
++		pcf_sysfs_entries[i++] = &dev_attr_battemp.attr;
++}
++
 +static int pcf50606_detect(struct i2c_adapter *adapter, int address, int kind)
 +{
 +	struct i2c_client *new_client;
-+	struct pcf50606_platform_data *pdata;
 +	struct pcf50606_data *data;
 +	int err = 0;
++	int irq;
 +
 +	DEBUGP("entering\n");
++	if (!pcf50606_pdev) {
++		printk(KERN_ERR
++		       "pcf50606: this driver needs a platform_device!\n");
++		return -EIO;
++	}
 +
++	irq = platform_get_irq(pcf50606_pdev, 0);
++	if (irq < 0) {
++		dev_err(&pcf50606_pdev->dev, "no irq in platform resources!\n");
++		return -EIO;
++	}
++
 +	/* At the moment, we only support one PCF50606 in a system */
 +	if (pcf50606_global) {
 +		printk(KERN_ERR
@@ -1402,6 +1433,8 @@
 +	INIT_WORK(&data->work, pcf50606_work);
 +	data->working = 0;
 +	data->onkey_seconds = -1;
++	data->pdata = pcf50606_pdev->dev.platform_data;
++
 +	new_client = &data->client;
 +	i2c_set_clientdata(new_client, data);
 +	new_client->addr = address;
@@ -1420,6 +1453,8 @@
 +
 +	pcf50606_global = data;
 +
++	populate_sysfs_group(data);
++
 +	err = sysfs_create_group(&new_client->dev.kobj, &pcf_attr_group);
 +	if (err) {
 +		dev_err(&new_client->dev, "error creating sysfs group\n");
@@ -1436,29 +1471,33 @@
 +	reg_write(data, PCF50606_REG_INT2M, 0x00);
 +	reg_write(data, PCF50606_REG_INT3M, PCF50606_INT3_TSCPRES);
 +
-+	/* FIXME: make this IRQ a resource */
-+	set_irq_type(GTA01_IRQ_PCF50606, IRQT_FALLING);
-+	err = request_irq(GTA01_IRQ_PCF50606, pcf50606_irq, SA_INTERRUPT,
++	err = request_irq(irq, pcf50606_irq, SA_INTERRUPT,
 +			  "pcf50606", data);
 +	if (err < 0)
 +		goto exit_sysfs;
 +
-+	if (enable_irq_wake(GTA01_IRQ_PCF50606) < 0)
++	set_irq_type(irq, IRQT_FALLING);
++
++	if (enable_irq_wake(irq) < 0)
 +		printk(KERN_ERR "PCF50606: IRQ %u cannot be enabled as wake-up"
-+		       "source in this hardware revision!");
++		       "source in this hardware revision!", irq);
 +
-+	data->rtc = rtc_device_register("pcf50606", &new_client->dev,
-+					&pcf50606_rtc_ops, THIS_MODULE);
-+	if (IS_ERR(data->rtc)) {
-+		err = PTR_ERR(data->rtc);
-+		goto exit_irq;
++	if (data->pdata->used_features & PCF50606_FEAT_RTC) {
++		data->rtc = rtc_device_register("pcf50606", &new_client->dev,
++						&pcf50606_rtc_ops, THIS_MODULE);
++		if (IS_ERR(data->rtc)) {
++			err = PTR_ERR(data->rtc);
++			goto exit_irq;
++		}
 +	}
 +
-+	err = misc_register(&pcf50606_wdt_miscdev);
-+	if (err) {
-+		printk(KERN_ERR "cannot register miscdev on minor=%d (%d)\n",
-+			WATCHDOG_MINOR, err);
-+		goto exit_rtc;
++	if (data->pdata->used_features & PCF50606_FEAT_WDT) {
++		err = misc_register(&pcf50606_wdt_miscdev);
++		if (err) {
++			printk(KERN_ERR "cannot register miscdev on \n"
++			       "minor=%d (%d)\n", WATCHDOG_MINOR, err);
++			goto exit_rtc;
++		}
 +	}
 +
 +	data->input_dev = input_allocate_device();
@@ -1491,9 +1530,11 @@
 +
 +	return 0;
 +exit_misc:
-+	misc_deregister(&pcf50606_wdt_miscdev);
++	if (data->pdata->used_features & PCF50606_FEAT_WDT)
++		misc_deregister(&pcf50606_wdt_miscdev);
 +exit_rtc:
-+	rtc_device_unregister(pcf50606_global->rtc);
++	if (data->pdata->used_features & PCF50606_FEAT_RTC)
++		rtc_device_unregister(pcf50606_global->rtc);
 +exit_irq:
 +	free_irq(GTA01_IRQ_PCF50606, pcf50606_global);
 +exit_sysfs:
@@ -1520,9 +1561,14 @@
 +
 +	apm_get_power_status = NULL;
 +	input_unregister_device(pcf->input_dev);
-+	misc_deregister(&pcf50606_wdt_miscdev);
++
++	if (pcf->pdata->used_features & PCF50606_FEAT_WDT)
++		misc_deregister(&pcf50606_wdt_miscdev);
++
 +	free_irq(GTA01_IRQ_PCF50606, pcf);
-+	rtc_device_unregister(pcf->rtc);
++
++	if (pcf->pdata->used_features & PCF50606_FEAT_RTC)
++		rtc_device_unregister(pcf->rtc);
 +	pm_power_off = NULL;
 +
 +	sysfs_remove_group(&client->dev.kobj, &pcf_attr_group);
@@ -1621,18 +1667,49 @@
 +	.detach_client	= &pcf50606_detach_client,
 +};
 +
++/* platform driver, since i2c devices don't have platform_data */
++static int __init pcf50606_plat_probe(struct platform_device *pdev)
++{
++	struct pcf50606_platform_data *pdata = pdev->dev.platform_data;
++
++	if (!pdata)
++		return -ENODEV;
++
++	pcf50606_pdev = pdev;
++
++	return 0;
++}
++
++static int pcf50606_plat_remove(struct platform_device *pdev)
++{
++	return 0;
++}
++
++static struct platform_driver pcf50606_plat_driver = {
++	.probe	= pcf50606_plat_probe,
++	.remove	= pcf50606_plat_remove,
++	.driver = {
++		.owner	= THIS_MODULE,
++		.name 	= "pcf50606",
++	},
++};
++
 +static int __init pcf50606_init(void)
 +{
-+	DEBUGP("entering, calling i2c_add_driver\n");
-+	return i2c_add_driver(&pcf50606_driver);
++	int rc;
++
++	if (!(rc = platform_driver_register(&pcf50606_plat_driver)))
++		rc = i2c_add_driver(&pcf50606_driver);
++
++	return rc;
 +}
 +
-+static void __exit pcf50606_exit(void)
++static void pcf50606_exit(void)
 +{
 +	i2c_del_driver(&pcf50606_driver);
++	platform_driver_unregister(&pcf50606_plat_driver);
 +}
 +
-+
 +MODULE_AUTHOR("Harald Welte <laforge at openmoko.org>");
 +MODULE_LICENSE("GPL");
 +
@@ -1951,8 +2028,8 @@
 Index: linux-2.6.20.4/include/linux/pcf50606.h
 ===================================================================
 --- /dev/null	1970-01-01 00:00:00.000000000 +0000
-+++ linux-2.6.20.4/include/linux/pcf50606.h	2007-03-26 19:01:17.000000000 +0200
-@@ -0,0 +1,56 @@
++++ linux-2.6.20.4/include/linux/pcf50606.h	2007-03-30 20:51:20.000000000 +0200
+@@ -0,0 +1,86 @@
 +#ifndef _LINUX_PCF50606_H
 +#define _LINUX_PCF50606_H
 +
@@ -1999,10 +2076,40 @@
 +extern void
 +pcf50606_charge_fast(struct pcf50606_data *pcf, int on);
 +
++struct pmu_voltage_rail {
++	char *name;
++	struct {
++		unsigned int init;
++		unsigned int max;
++	} voltage;
++};
++
++#define PCF50606_FEAT_EXTON	0x00000001	/* not yet supported */
++#define PCF50606_FEAT_MBC	0x00000002
++#define PCF50606_FEAT_BBC	0x00000004	/* not yet supported */
++#define PCF50606_FEAT_TSC	0x00000008	/* not yet supported */
++#define PCF50606_FEAT_WDT	0x00000010
++#define PCF50606_FEAT_ACD	0x00000020
++#define PCF50606_FEAT_RTC	0x00000040
++#define PCF50606_FEAT_PWM	0x00000080
++#define PCF50606_FEAT_CHGCUR	0x00000100
++#define PCF50606_FEAT_BATVOLT	0x00000200
++#define PCF50606_FEAT_BATTEMP	0x00000400
++
 +struct pcf50606_platform_data {
-+	unsigned int irq;
-+	unsigned int initial_voltage[__NUM_PCF50606_REGULATORS];
++	/* general */
++	unsigned int used_features;
++	unsigned int onkey_seconds_required;
 +
++	/* voltage regulator related */
++	struct pmu_voltage_rail rails[__NUM_PCF50606_REGULATORS];
++	unsigned int used_regulators;
++
++	/* charger related */
++	unsigned int r_fix_batt;
++	unsigned int r_fix_batt_par;
++	unsigned int r_sense_milli;
++
 +	struct {
 +		u_int8_t mbcc3; /* charger voltage / current */
 +	} charger;





More information about the commitlog mailing list