diff options
-rw-r--r-- | arch/arm/mach-s3c2410/include/mach/gta02.h | 3 | ||||
-rw-r--r-- | arch/arm/mach-s3c2440/mach-gta02.c | 48 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/neo1973_pm_bt.c | 8 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/neo1973_pm_gps.c | 12 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/neo1973_pm_gsm.c | 4 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/neo1973_pm_host.c | 4 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/neo1973_pm_resume_reason.c | 2 | ||||
-rw-r--r-- | drivers/i2c/chips/pcf50633.c | 307 | ||||
-rw-r--r-- | include/linux/pcf50633.h | 6 |
9 files changed, 132 insertions, 262 deletions
diff --git a/arch/arm/mach-s3c2410/include/mach/gta02.h b/arch/arm/mach-s3c2410/include/mach/gta02.h index 68f853ec2ac..7f103bd2912 100644 --- a/arch/arm/mach-s3c2410/include/mach/gta02.h +++ b/arch/arm/mach-s3c2410/include/mach/gta02.h @@ -3,6 +3,7 @@ #include <mach/regs-gpio.h> #include <mach/irqs.h> +#include <linux/pcf50633.h> /* Different hardware revisions, passed in ATAG_REVISION by u-boot */ #define GTA02v1_SYSTEM_REV 0x00000310 @@ -106,4 +107,6 @@ int gta02_get_pcb_revision(void); +extern struct pcf50633_platform_data gta02_pcf_pdata; + #endif /* _GTA02_H */ diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c index ac2e5b615ef..f0ecc641790 100644 --- a/arch/arm/mach-s3c2440/mach-gta02.c +++ b/arch/arm/mach-s3c2440/mach-gta02.c @@ -45,6 +45,8 @@ #include <linux/mtd/partitions.h> #include <linux/mtd/physmap.h> +#include <linux/i2c.h> + #include <linux/pcf50633.h> #include <linux/lis302dl.h> @@ -558,7 +560,7 @@ static struct platform_device gta02_pm_wlan_dev = { .name = "gta02-pm-wlan", }; -static struct pcf50633_platform_data gta02_pcf_pdata = { +struct pcf50633_platform_data gta02_pcf_pdata = { .used_features = PCF50633_FEAT_MBC | PCF50633_FEAT_BBC | PCF50633_FEAT_RTC | @@ -740,23 +742,6 @@ static void mangle_pmu_pdata_by_system_rev(void) } } -static struct resource gta02_pmu_resources[] = { - [0] = { - .flags = IORESOURCE_IRQ, - .start = GTA02_IRQ_PCF50633, - .end = GTA02_IRQ_PCF50633, - }, -}; - -struct platform_device gta02_pmu_dev = { - .name = "pcf50633", - .num_resources = ARRAY_SIZE(gta02_pmu_resources), - .resource = gta02_pmu_resources, - .dev = { - .platform_data = >a02_pcf_pdata, - }, -}; - #ifdef CONFIG_GTA02_HDQ /* HDQ */ @@ -882,6 +867,14 @@ struct platform_device s3c24xx_pwm_device = { .num_resources = 0, }; +static struct i2c_board_info gta02_i2c_devs[] __initdata = { + { + I2C_BOARD_INFO("pcf50633", 0x73), + .irq = GTA02_IRQ_PCF50633, + .platform_data = >a02_pcf_pdata, + }, +}; + static struct s3c2410_nand_set gta02_nand_sets[] = { [0] = { .name = "neo1973-nand", @@ -926,10 +919,10 @@ static void gta02_udc_command(enum s3c2410_udc_cmd_e cmd) static void gta02_udc_vbus_draw(unsigned int ma) { - if (!pcf50633_global) + if (!gta02_pcf_pdata.pcf) return; - pcf50633_notify_usb_current_limit_change(pcf50633_global, ma); + pcf50633_notify_usb_current_limit_change(gta02_pcf_pdata.pcf, ma); } static struct s3c2410_udc_mach_info gta02_udc_cfg = { @@ -977,7 +970,7 @@ static void gta02_jbt6k74_reset(int devidx, int level) static void gta02_jbt6k74_resuming(int devidx) { - pcf50633_backlight_resume(pcf50633_global); + pcf50633_backlight_resume(gta02_pcf_pdata.pcf); } @@ -1323,7 +1316,7 @@ gta02_glamo_mmc_set_power(unsigned char power_mode, unsigned short vdd) case MMC_POWER_ON: case MMC_POWER_UP: /* depend on pcf50633 driver init + not suspended */ - while (pcf50633_ready(pcf50633_global) && (timeout--)) + while (pcf50633_ready(gta02_pcf_pdata.pcf) && (timeout--)) msleep(5); if (timeout < 0) { @@ -1335,9 +1328,9 @@ gta02_glamo_mmc_set_power(unsigned char power_mode, unsigned short vdd) if (vdd > 7) mv += 350 + 100 * (vdd - 8); printk(KERN_INFO "SD power -> %dmV\n", mv); - pcf50633_voltage_set(pcf50633_global, + pcf50633_voltage_set(gta02_pcf_pdata.pcf, PCF50633_REGULATOR_HCLDO, mv); - pcf50633_onoff_set(pcf50633_global, + pcf50633_onoff_set(gta02_pcf_pdata.pcf, PCF50633_REGULATOR_HCLDO, 1); break; case MMC_POWER_OFF: @@ -1346,9 +1339,9 @@ gta02_glamo_mmc_set_power(unsigned char power_mode, unsigned short vdd) * the action then because pcf50633 suspend already * dealt with it, otherwise we spin forever */ - if (pcf50633_ready(pcf50633_global)) + if (pcf50633_ready(gta02_pcf_pdata.pcf)) return; - pcf50633_onoff_set(pcf50633_global, + pcf50633_onoff_set(gta02_pcf_pdata.pcf, PCF50633_REGULATOR_HCLDO, 0); break; } @@ -1511,7 +1504,6 @@ static struct platform_device *gta02_devices[] __initdata = { &s3c24xx_pwm_device, >a02_led_dev, >a02_pm_wlan_dev, /* not dependent on PMU */ - >a02_pmu_dev, &s3c_device_iis, &s3c_device_i2c0, @@ -1593,6 +1585,8 @@ static void __init gta02_machine_init(void) mangle_glamo_res_by_system_rev(); + i2c_register_board_info(0, gta02_i2c_devs, ARRAY_SIZE(gta02_i2c_devs)); + mangle_pmu_pdata_by_system_rev(); platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices)); diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_bt.c b/arch/arm/plat-s3c24xx/neo1973_pm_bt.c index 8be584c9f82..dc149ac6d02 100644 --- a/arch/arm/plat-s3c24xx/neo1973_pm_bt.c +++ b/arch/arm/plat-s3c24xx/neo1973_pm_bt.c @@ -88,11 +88,11 @@ static ssize_t bt_write(struct device *dev, struct device_attribute *attr, if (s3c2410_gpio_getpin(GTA02_GPIO_BT_EN) == on) return count; neo1973_gpb_setpin(GTA02_GPIO_BT_EN, !on); - pcf50633_voltage_set(pcf50633_global, + pcf50633_voltage_set(gta02_pcf_pdata.pcf, PCF50633_REGULATOR_LDO4, on ? 3200 : 0); - pcf50633_onoff_set(pcf50633_global, + pcf50633_onoff_set(gta02_pcf_pdata.pcf, PCF50633_REGULATOR_LDO4, on); - vol = pcf50633_voltage_get(pcf50633_global, + vol = pcf50633_voltage_get(gta02_pcf_pdata.pcf, PCF50633_REGULATOR_LDO4); dev_info(dev, "GTA02 Set PCF50633 LDO4 = %d\n", vol); neo1973_gpb_setpin(GTA02_GPIO_BT_EN, on); @@ -158,7 +158,7 @@ static int __init gta01_bt_probe(struct platform_device *pdev) neo1973_gpb_setpin(GTA01_GPIO_BT_EN, 0); } else if (machine_is_neo1973_gta02()) { /* we make sure that the voltage is off */ - pcf50633_onoff_set(pcf50633_global, + pcf50633_onoff_set(gta02_pcf_pdata.pcf, PCF50633_REGULATOR_LDO4, 0); /* we pull reset to low to make sure that the chip doesn't * drain power through the reset line */ diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_gps.c b/arch/arm/plat-s3c24xx/neo1973_pm_gps.c index 6fabf19d0da..a3a6ad3b53f 100644 --- a/arch/arm/plat-s3c24xx/neo1973_pm_gps.c +++ b/arch/arm/plat-s3c24xx/neo1973_pm_gps.c @@ -280,7 +280,7 @@ static void gps_pwron_set(int on) if (machine_is_neo1973_gta02()) { if (on) { - pcf50633_voltage_set(pcf50633_global, + pcf50633_voltage_set(gta02_pcf_pdata.pcf, PCF50633_REGULATOR_LDO5, 3000); /* return UART pins to being UART pins */ s3c2410_gpio_cfgpin(S3C2410_GPH4, S3C2410_GPH4_TXD1); @@ -296,7 +296,7 @@ static void gps_pwron_set(int on) /* don't let RX from unpowered GPS float */ s3c2410_gpio_pullup(S3C2410_GPH5, 1); } - pcf50633_onoff_set(pcf50633_global, + pcf50633_onoff_set(gta02_pcf_pdata.pcf, PCF50633_REGULATOR_LDO5, on); } } @@ -307,7 +307,7 @@ static int gps_pwron_get(void) return !!s3c2410_gpio_getpin(GTA01_GPIO_GPS_PWRON); if (machine_is_neo1973_gta02()) - return !!pcf50633_onoff_get(pcf50633_global, + return !!pcf50633_onoff_get(gta02_pcf_pdata.pcf, PCF50633_REGULATOR_LDO5); return -1; } @@ -630,9 +630,9 @@ static int __init gta01_pm_gps_probe(struct platform_device *pdev) case GTA02v4_SYSTEM_REV: case GTA02v5_SYSTEM_REV: case GTA02v6_SYSTEM_REV: - pcf50633_voltage_set(pcf50633_global, + pcf50633_voltage_set(gta02_pcf_pdata.pcf, PCF50633_REGULATOR_LDO5, 3000); - pcf50633_onoff_set(pcf50633_global, + pcf50633_onoff_set(gta02_pcf_pdata.pcf, PCF50633_REGULATOR_LDO5, 0); dev_info(&pdev->dev, "FIC Neo1973 GPS Power Managerment:" "starting\n"); @@ -659,7 +659,7 @@ static int gta01_pm_gps_remove(struct platform_device *pdev) } if (machine_is_neo1973_gta02()) { - pcf50633_onoff_set(pcf50633_global, PCF50633_REGULATOR_LDO5, 0); + pcf50633_onoff_set(gta02_pcf_pdata.pcf, PCF50633_REGULATOR_LDO5, 0); sysfs_remove_group(&pdev->dev.kobj, >a02_gps_attr_group); } return 0; diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c b/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c index 7dd28911904..ebed33558a7 100644 --- a/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c +++ b/arch/arm/plat-s3c24xx/neo1973_pm_gsm.c @@ -117,7 +117,7 @@ static ssize_t gsm_write(struct device *dev, struct device_attribute *attr, case GTA02v4_SYSTEM_REV: case GTA02v5_SYSTEM_REV: case GTA02v6_SYSTEM_REV: - pcf50633_gpio_set(pcf50633_global, + pcf50633_gpio_set(gta02_pcf_pdata.pcf, PCF50633_GPIO2, 1); break; } @@ -134,7 +134,7 @@ static ssize_t gsm_write(struct device *dev, struct device_attribute *attr, case GTA02v4_SYSTEM_REV: case GTA02v5_SYSTEM_REV: case GTA02v6_SYSTEM_REV: - pcf50633_gpio_set(pcf50633_global, + pcf50633_gpio_set(gta02_pcf_pdata.pcf, PCF50633_GPIO2, 0); break; } diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_host.c b/arch/arm/plat-s3c24xx/neo1973_pm_host.c index bb25acdb7d2..8ab589b3ad8 100644 --- a/arch/arm/plat-s3c24xx/neo1973_pm_host.c +++ b/arch/arm/plat-s3c24xx/neo1973_pm_host.c @@ -27,7 +27,7 @@ static ssize_t pm_host_read(struct device *dev, struct device_attribute *attr, char *buf) { return sprintf(buf, "%d\n", - pcf50633_gpio_get(pcf50633_global, PCF50633_GPO)); + pcf50633_gpio_get(gta02_pcf_pdata.pcf, PCF50633_GPO)); } static ssize_t pm_host_write(struct device *dev, struct device_attribute *attr, @@ -35,7 +35,7 @@ static ssize_t pm_host_write(struct device *dev, struct device_attribute *attr, { unsigned long on = simple_strtoul(buf, NULL, 10); - pcf50633_gpio_set(pcf50633_global, PCF50633_GPO, on); + pcf50633_gpio_set(gta02_pcf_pdata.pcf, PCF50633_GPO, on); return count; } diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_resume_reason.c b/arch/arm/plat-s3c24xx/neo1973_pm_resume_reason.c index c7730b60da9..a04466c8960 100644 --- a/arch/arm/plat-s3c24xx/neo1973_pm_resume_reason.c +++ b/arch/arm/plat-s3c24xx/neo1973_pm_resume_reason.c @@ -80,7 +80,7 @@ static ssize_t resume_reason_read(struct device *dev, #ifdef CONFIG_MACH_NEO1973_GTA02 if ((gta) && (bit == 9)) /* PMU */ - end += pcf50633_report_resumers(pcf50633_global, end); + end += pcf50633_report_resumers(gta02_pcf_pdata.pcf, end); #endif } diff --git a/drivers/i2c/chips/pcf50633.c b/drivers/i2c/chips/pcf50633.c index 11a5f5a5b3a..8acb9a2a487 100644 --- a/drivers/i2c/chips/pcf50633.c +++ b/drivers/i2c/chips/pcf50633.c @@ -118,7 +118,7 @@ enum pcf50633_suspend_states { struct pcf50633_data { - struct i2c_client client; + struct i2c_client *client; struct pcf50633_platform_data *pdata; struct backlight_device *backlight; struct mutex lock; @@ -188,11 +188,6 @@ struct pcf50633_data { static struct i2c_driver pcf50633_driver; -struct pcf50633_data *pcf50633_global; -EXPORT_SYMBOL_GPL(pcf50633_global); - -static struct platform_device *pcf50633_pdev; - static void pcf50633_usb_curlim_set(struct pcf50633_data *pcf, int ma); static void pcf50633_charge_enable(struct pcf50633_data *pcf, int on); @@ -204,10 +199,10 @@ static void pcf50633_charge_enable(struct pcf50633_data *pcf, int on); static int __reg_write(struct pcf50633_data *pcf, u_int8_t reg, u_int8_t val) { if (pcf->suspend_state == PCF50633_SS_COMPLETED_SUSPEND) { - dev_err(&pcf->client.dev, "__reg_write while suspended\n"); + dev_err(&pcf->client->dev, "__reg_write while suspended\n"); dump_stack(); } - return i2c_smbus_write_byte_data(&pcf->client, reg, val); + return i2c_smbus_write_byte_data(pcf->client, reg, val); } static int reg_write(struct pcf50633_data *pcf, u_int8_t reg, u_int8_t val) @@ -226,10 +221,10 @@ static int32_t __reg_read(struct pcf50633_data *pcf, u_int8_t reg) int32_t ret; if (pcf->suspend_state == PCF50633_SS_COMPLETED_SUSPEND) { - dev_err(&pcf->client.dev, "__reg_read while suspended\n"); + dev_err(&pcf->client->dev, "__reg_read while suspended\n"); dump_stack(); } - ret = i2c_smbus_read_byte_data(&pcf->client, reg); + ret = i2c_smbus_read_byte_data(pcf->client, reg); return ret; } @@ -503,9 +498,9 @@ unsigned int pcf50633_voltage_get(struct pcf50633_data *pcf, EXPORT_SYMBOL_GPL(pcf50633_voltage_get); /* go into 'STANDBY' mode, i.e. power off the main CPU and peripherals */ -void pcf50633_go_standby(void) +void pcf50633_go_standby(struct pcf50633_data *pcf) { - reg_set_bit_mask(pcf50633_global, PCF50633_REG_OOCSHDWN, + reg_set_bit_mask(pcf, PCF50633_REG_OOCSHDWN, PCF50633_OOCSHDWN_GOSTDBY, PCF50633_OOCSHDWN_GOSTDBY); } EXPORT_SYMBOL_GPL(pcf50633_go_standby); @@ -583,7 +578,7 @@ static void configure_pmu_for_charger(struct pcf50633_data *pcf, * stop GPO / EN_HOSTUSB power driving out on the same * USB power pins we have a 1A charger on right now! */ - dev_dbg(&pcf->client.dev, "Charger -> CHARGER_TYPE_1A\n"); + dev_dbg(&pcf->client->dev, "Charger -> CHARGER_TYPE_1A\n"); __reg_write(pcf, PCF50633_GPO - PCF50633_GPIO1 + PCF50633_REG_GPIO1CFG, __reg_read(pcf, PCF50633_GPO - PCF50633_GPIO1 + @@ -639,7 +634,7 @@ static void pcf50633_work_usbcurlim(struct work_struct *work) (pcf->suspend_state == PCF50633_SS_COMPLETED_SUSPEND)) goto bail; - dev_dbg(&pcf->client.dev, "pcf50633_work_usbcurlim\n"); + dev_dbg(&pcf->client->dev, "pcf50633_work_usbcurlim\n"); if (!pcf->probe_completed) goto reschedule; @@ -659,7 +654,7 @@ static void pcf50633_work_usbcurlim(struct work_struct *work) /* OK let's set the requested limit and finish */ - dev_dbg(&pcf->client.dev, "pcf50633_work_usbcurlim setting %dmA\n", + dev_dbg(&pcf->client->dev, "pcf50633_work_usbcurlim setting %dmA\n", pcf->pending_curlimit); pcf50633_usb_curlim_set(pcf, pcf->pending_curlimit); @@ -668,9 +663,9 @@ bail: return; reschedule: - dev_dbg(&pcf->client.dev, "pcf50633_work_usbcurlim rescheduling\n"); + dev_dbg(&pcf->client->dev, "pcf50633_work_usbcurlim rescheduling\n"); if (!schedule_work(&pcf->work_usb_curlimit)) - dev_err(&pcf->client.dev, "curlim reschedule work " + dev_err(&pcf->client->dev, "curlim reschedule work " "already queued\n"); mutex_unlock(&pcf->working_lock_usb_curlimit); @@ -697,7 +692,7 @@ int pcf50633_notify_usb_current_limit_change(struct pcf50633_data *pcf, return -EBUSY; } - dev_dbg(&pcf->client.dev, + dev_dbg(&pcf->client->dev, "pcf50633_notify_usb_current_limit_change %dmA\n", ma); /* prepare to detect USB power removal before we complete */ @@ -706,7 +701,7 @@ int pcf50633_notify_usb_current_limit_change(struct pcf50633_data *pcf, pcf->pending_curlimit = ma; if (!schedule_work(&pcf->work_usb_curlimit)) - dev_err(&pcf->client.dev, "curlim work item already queued\n"); + dev_err(&pcf->client->dev, "curlim work item already queued\n"); return 0; } @@ -771,7 +766,7 @@ static void pcf50633_work(struct work_struct *work) pcf->working = 1; /* sanity */ - if (!&pcf->client.dev) + if (!&pcf->client->dev) goto bail; /* @@ -808,19 +803,19 @@ static void pcf50633_work(struct work_struct *work) goto reschedule; /* this is the case early in resume! Sanity check! */ - if (i2c_get_clientdata(&pcf->client) == NULL) + if (i2c_get_clientdata(pcf->client) == NULL) goto reschedule; /* * datasheet says we have to read the five IRQ * status regs in one transaction */ - ret = i2c_smbus_read_i2c_block_data(&pcf->client, + ret = i2c_smbus_read_i2c_block_data(pcf->client, PCF50633_REG_INT1, sizeof(pcfirq), pcfirq); if (ret != sizeof(pcfirq)) { - dev_info(&pcf->client.dev, + dev_info(&pcf->client->dev, "Oh crap PMU IRQ register read failed -- " "retrying later %d\n", ret); /* @@ -876,7 +871,7 @@ static void pcf50633_work(struct work_struct *work) apm_queue_event(APM_POWER_STATUS_CHANGE); pcf->flags |= PCF50633_F_USB_PRESENT; if (pcf->pdata->cb) - pcf->pdata->cb(&pcf->client.dev, + pcf->pdata->cb(&pcf->client->dev, PCF50633_FEAT_MBC, PMU_EVT_USB_INSERT); } @@ -897,7 +892,7 @@ static void pcf50633_work(struct work_struct *work) apm_queue_event(APM_POWER_STATUS_CHANGE); pcf->flags |= PCF50633_F_CHG_PRESENT; if (pcf->pdata->cb) - pcf->pdata->cb(&pcf->client.dev, + pcf->pdata->cb(&pcf->client->dev, PCF50633_FEAT_MBC, PMU_EVT_INSERT); } if (pcfirq[0] & PCF50633_INT1_ADPREM) { @@ -907,7 +902,7 @@ static void pcf50633_work(struct work_struct *work) apm_queue_event(APM_POWER_STATUS_CHANGE); pcf->flags &= ~PCF50633_F_CHG_PRESENT; if (pcf->pdata->cb) - pcf->pdata->cb(&pcf->client.dev, + pcf->pdata->cb(&pcf->client->dev, PCF50633_FEAT_MBC, PMU_EVT_REMOVE); } if (pcfirq[0] & PCF50633_INT1_USBINS) { @@ -916,7 +911,7 @@ static void pcf50633_work(struct work_struct *work) apm_queue_event(APM_POWER_STATUS_CHANGE); pcf->flags |= PCF50633_F_USB_PRESENT; if (pcf->pdata->cb) - pcf->pdata->cb(&pcf->client.dev, + pcf->pdata->cb(&pcf->client->dev, PCF50633_FEAT_MBC, PMU_EVT_USB_INSERT); msleep(500); /* debounce, allow to see any ID resistor */ /* completion irq will figure out our charging stance */ @@ -939,7 +934,7 @@ static void pcf50633_work(struct work_struct *work) pcf->flags &= ~PCF50633_F_USB_PRESENT; if (pcf->pdata->cb) - pcf->pdata->cb(&pcf->client.dev, + pcf->pdata->cb(&pcf->client->dev, PCF50633_FEAT_MBC, PMU_EVT_USB_REMOVE); /* destroy any memory of grant of power from host */ @@ -989,7 +984,7 @@ static void pcf50633_work(struct work_struct *work) if (pcf->onkey_seconds >= pcf->pdata->onkey_seconds_shutdown) { DEBUGPC("Power Off "); - pcf50633_go_standby(); + pcf50633_go_standby(pcf); } } } @@ -1050,7 +1045,7 @@ static void pcf50633_work(struct work_struct *work) ret); } else { if (pcf->pdata->cb) - pcf->pdata->cb(&pcf->client.dev, + pcf->pdata->cb(&pcf->client->dev, PCF50633_FEAT_MBC, PMU_EVT_CHARGER_IDLE); } @@ -1063,33 +1058,33 @@ static void pcf50633_work(struct work_struct *work) * appear with no battery attached */ if (pcf->pdata->cb) - pcf->pdata->cb(&pcf->client.dev, + pcf->pdata->cb(&pcf->client->dev, PCF50633_FEAT_MBC, PMU_EVT_CHARGER_CHANGE); } if (pcfirq[2] & PCF50633_INT3_THLIMON) { DEBUGPC("THLIMON "); pcf->flags |= PCF50633_F_CHG_PROT; if (pcf->pdata->cb) - pcf->pdata->cb(&pcf->client.dev, + pcf->pdata->cb(&pcf->client->dev, PCF50633_FEAT_MBC, PMU_EVT_CHARGER_CHANGE); } if (pcfirq[2] & PCF50633_INT3_THLIMOFF) { DEBUGPC("THLIMOFF "); pcf->flags &= ~PCF50633_F_CHG_PROT; if (pcf->pdata->cb) - pcf->pdata->cb(&pcf->client.dev, + pcf->pdata->cb(&pcf->client->dev, PCF50633_FEAT_MBC, PMU_EVT_CHARGER_CHANGE); } if (pcfirq[2] & PCF50633_INT3_USBLIMON) { DEBUGPC("USBLIMON "); if (pcf->pdata->cb) - pcf->pdata->cb(&pcf->client.dev, + pcf->pdata->cb(&pcf->client->dev, PCF50633_FEAT_MBC, PMU_EVT_CHARGER_CHANGE); } if (pcfirq[2] & PCF50633_INT3_USBLIMOFF) { DEBUGPC("USBLIMOFF "); if (pcf->pdata->cb) - pcf->pdata->cb(&pcf->client.dev, + pcf->pdata->cb(&pcf->client->dev, PCF50633_FEAT_MBC, PMU_EVT_CHARGER_CHANGE); } if (pcfirq[2] & PCF50633_INT3_ADCRDY) { @@ -1137,7 +1132,7 @@ static void pcf50633_work(struct work_struct *work) * we are not actually charging anything */ if (pcf->pdata->cb) - pcf->pdata->cb(&pcf->client.dev, + pcf->pdata->cb(&pcf->client->dev, PCF50633_FEAT_MBC, PMU_EVT_CHARGER_IDLE); reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, @@ -1229,7 +1224,7 @@ static void pcf50633_work(struct work_struct *work) bail: pcf->working = 0; input_sync(pcf->input_dev); - put_device(&pcf->client.dev); + put_device(&pcf->client->dev); mutex_unlock(&pcf->working_lock); return; @@ -1242,10 +1237,10 @@ reschedule: if ((pcf->suspend_state != PCF50633_SS_STARTING_SUSPEND) && (pcf->suspend_state != PCF50633_SS_COMPLETED_SUSPEND)) { msleep(10); - dev_dbg(&pcf->client.dev, "rescheduling interrupt service\n"); + dev_dbg(&pcf->client->dev, "rescheduling interrupt service\n"); } if (!schedule_work(&pcf->work)) - dev_err(&pcf->client.dev, "int service reschedule failed\n"); + dev_err(&pcf->client->dev, "int service reschedule failed\n"); /* we don't put the device here, hold it for next time */ mutex_unlock(&pcf->working_lock); @@ -1256,11 +1251,11 @@ static irqreturn_t pcf50633_irq(int irq, void *_pcf) struct pcf50633_data *pcf = _pcf; DEBUGP("entering(irq=%u, pcf=%p): scheduling work\n", irq, _pcf); - dev_dbg(&pcf->client.dev, "pcf50633_irq scheduling work\n"); + dev_dbg(&pcf->client->dev, "pcf50633_irq scheduling work\n"); - get_device(&pcf->client.dev); + get_device(&pcf->client->dev); if (!schedule_work(&pcf->work) && !pcf->working) - dev_err(&pcf->client.dev, "pcf irq work already queued\n"); + dev_err(&pcf->client->dev, "pcf irq work already queued\n"); return IRQ_HANDLED; } @@ -1420,7 +1415,7 @@ static void pcf50633_usb_curlim_set(struct pcf50633_data *pcf, int ma) pcf->last_curlim_set = ma; - dev_dbg(&pcf->client.dev, "setting usb current limit to %d ma", ma); + dev_dbg(&pcf->client->dev, "setting usb current limit to %d ma", ma); if (ma >= 1000) { bits = PCF50633_MBCC7_USB_1000mA; @@ -1445,7 +1440,7 @@ static void pcf50633_usb_curlim_set(struct pcf50633_data *pcf, int ma) break; default: /* right charging context that if there is power, we charge */ if (pcf->flags & PCF50633_F_USB_PRESENT) - pcf->pdata->cb(&pcf->client.dev, + pcf->pdata->cb(&pcf->client->dev, PCF50633_FEAT_MBC, PMU_EVT_CHARGER_ACTIVE); break; } @@ -1453,7 +1448,7 @@ static void pcf50633_usb_curlim_set(struct pcf50633_data *pcf, int ma) * enable or disable charging according to current limit -- this will * also throw a platform notification callback about it */ - pcf50633_charge_enable(pcf50633_global, active); + pcf50633_charge_enable(pcf, active); /* clear batfull */ reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, @@ -1511,7 +1506,7 @@ static void pcf50633_charge_enable(struct pcf50633_data *pcf, int on) case PCF50633_MBCC7_USB_500mA: if (pcf->flags & PCF50633_F_USB_PRESENT) if (pcf->pdata->cb) - pcf->pdata->cb(&pcf->client.dev, + pcf->pdata->cb(&pcf->client->dev, PCF50633_FEAT_MBC, PMU_EVT_CHARGER_ACTIVE); break; @@ -1522,7 +1517,7 @@ static void pcf50633_charge_enable(struct pcf50633_data *pcf, int on) pcf->flags &= ~PCF50633_F_CHG_ENABLED; bits = 0; if (pcf->pdata->cb) - pcf->pdata->cb(&pcf->client.dev, + pcf->pdata->cb(&pcf->client->dev, PCF50633_FEAT_MBC, PMU_EVT_CHARGER_IDLE); } reg_set_bit_mask(pcf, PCF50633_REG_MBCC1, PCF50633_MBCC1_CHGENA, @@ -1637,47 +1632,6 @@ static ssize_t show_chgstate(struct device *dev, struct device_attribute *attr, static DEVICE_ATTR(chgstate, S_IRUGO | S_IWUSR, show_chgstate, NULL); /*********************************************************************** - * APM emulation - ***********************************************************************/ - -extern void (*apm_get_power_status)(struct apm_power_info *); - -static void pcf50633_get_power_status(struct apm_power_info *info) -{ - struct pcf50633_data *pcf = pcf50633_global; - u_int8_t chgmod = reg_read(pcf, PCF50633_REG_MBCS2) & - PCF50633_MBCS2_MBC_MASK; - - u_int16_t battvolt = pcf50633_battvolt(pcf); - - if (reg_read(pcf, PCF50633_REG_MBCS1) & - (PCF50633_MBCS1_USBPRES|PCF50633_MBCS1_ADAPTPRES)) - info->ac_line_status = APM_AC_ONLINE; - else - info->ac_line_status = APM_AC_OFFLINE; - - switch (chgmod) { - case PCF50633_MBCS2_MBC_PLAY: - case PCF50633_MBCS2_MBC_USB_PRE: - case PCF50633_MBCS2_MBC_USB_PRE_WAIT: - case PCF50633_MBCS2_MBC_USB_FAST_WAIT: - case PCF50633_MBCS2_MBC_ADP_PRE: - case PCF50633_MBCS2_MBC_ADP_PRE_WAIT: - case PCF50633_MBCS2_MBC_ADP_FAST_WAIT: - case PCF50633_MBCS2_MBC_BAT_FULL: - case PCF50633_MBCS2_MBC_HALT: - info->battery_life = battvolt_scale(battvolt); - break; - case PCF50633_MBCS2_MBC_USB_FAST: - case PCF50633_MBCS2_MBC_ADP_FAST: - info->battery_status = APM_BATTERY_STATUS_CHARGING; - info->battery_flag = APM_BATTERY_FLAG_CHARGING; - default: - break; - } -} - -/*********************************************************************** * RTC ***********************************************************************/ enum pcf50633_time_indexes { @@ -1758,7 +1712,7 @@ static int pcf50633_rtc_read_time(struct device *dev, struct rtc_time *tm) mutex_lock(&pcf->lock); - ret = i2c_smbus_read_i2c_block_data(&pcf->client, + ret = i2c_smbus_read_i2c_block_data(pcf->client, PCF50633_REG_RTCSC, PCF50633_TI_EXTENT, &pcf_tm.time[0]); @@ -1806,7 +1760,7 @@ static int pcf50633_rtc_set_time(struct device *dev, struct rtc_time *tm) mutex_lock(&pcf->lock); /* FIXME: disable second interrupt */ - ret = i2c_smbus_write_i2c_block_data(&pcf->client, + ret = i2c_smbus_write_i2c_block_data(pcf->client, PCF50633_REG_RTCSC, PCF50633_TI_EXTENT, &pcf_tm.time[0]); @@ -1831,7 +1785,7 @@ static int pcf50633_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alrm) alrm->enabled = __reg_read(pcf, PCF50633_REG_INT1M) & PCF50633_INT1_ALARM ? 0 : 1; - ret = i2c_smbus_read_i2c_block_data(&pcf->client, + ret = i2c_smbus_read_i2c_block_data(pcf->client, PCF50633_REG_RTCSCA, PCF50633_TI_EXTENT, &pcf_tm.time[0]); @@ -1862,7 +1816,7 @@ static int pcf50633_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alrm) irqmask |= PCF50633_INT1_ALARM; __reg_write(pcf, PCF50633_REG_INT1M, irqmask); - ret = i2c_smbus_write_i2c_block_data(&pcf->client, + ret = i2c_smbus_write_i2c_block_data(pcf->client, PCF50633_REG_RTCSCA, PCF50633_TI_EXTENT, &pcf_tm.time[0]); @@ -2113,38 +2067,23 @@ static void populate_sysfs_group(struct pcf50633_data *pcf) } -static int pcf50633_detect(struct i2c_adapter *adapter, int address, int kind) +static int pcf50633_probe(struct i2c_client *client, const struct i2c_device_id *ids) { - struct i2c_client *new_client; struct pcf50633_data *pcf; + struct pcf50633_platform_data *pdata; int err = 0; int irq; - printk(KERN_INFO "************ pcf50633_detect\n"); + DEBUGP("entering probe\n"); - DEBUGP("entering\n"); - if (!pcf50633_pdev) { - printk(KERN_ERR "pcf50633: driver needs a platform_device!\n"); - return -EIO; - } - - irq = platform_get_irq(pcf50633_pdev, 0); - if (irq < 0) { - dev_err(&pcf50633_pdev->dev, "no irq in platform resources!\n"); - return -EIO; - } - - /* At the moment, we only support one PCF50633 in a system */ - if (pcf50633_global) { - dev_err(&pcf50633_pdev->dev, - "currently only one chip supported\n"); - return -EBUSY; - } + pdata = client->dev.platform_data; pcf = kzalloc(sizeof(*pcf), GFP_KERNEL); if (!pcf) - return -ENOMEM; + return -ENOMEM; + i2c_set_clientdata(client, pcf); + irq = client->irq; mutex_init(&pcf->lock); mutex_init(&pcf->working_lock); mutex_init(&pcf->working_lock_nobat); @@ -2152,41 +2091,28 @@ static int pcf50633_detect(struct i2c_adapter *adapter, int address, int kind) INIT_WORK(&pcf->work, pcf50633_work); INIT_WORK(&pcf->work_nobat, pcf50633_work_nobat); INIT_WORK(&pcf->work_usb_curlimit, pcf50633_work_usbcurlim); + + pcf->client = client; pcf->irq = irq; pcf->working = 0; pcf->suppress_onkey_events = 0; pcf->onkey_seconds = -1; - pcf->pdata = pcf50633_pdev->dev.platform_data; - - new_client = &pcf->client; - i2c_set_clientdata(new_client, pcf); - new_client->addr = address; - new_client->adapter = adapter; - new_client->driver = &pcf50633_driver; - new_client->flags = 0; - strlcpy(new_client->name, "pcf50633", I2C_NAME_SIZE); - - /* now we try to detect the chip */ - - /* register with i2c core */ - if ((err = i2c_attach_client(new_client))) { - dev_err(&new_client->dev, - "error during i2c_attach_client()\n"); - goto exit_free; - } + pcf->pdata = pdata; + + /* FIXME: now we try to detect the chip */ populate_sysfs_group(pcf); - err = sysfs_create_group(&new_client->dev.kobj, &pcf_attr_group); + err = sysfs_create_group(&client->dev.kobj, &pcf_attr_group); if (err) { - dev_err(&new_client->dev, "error creating sysfs group\n"); - goto exit_detach; + dev_err(&client->dev, "error creating sysfs group\n"); + goto exit_free; } /* create virtual charger 'device' */ /* register power off handler with core power management */ - pm_power_off = &pcf50633_go_standby; + /* FIXME : pm_power_off = &pcf50633_go_standby; */ pcf->input_dev = input_allocate_device(); if (!pcf->input_dev) @@ -2234,11 +2160,11 @@ static int pcf50633_detect(struct i2c_adapter *adapter, int address, int kind) goto exit_input; if (enable_irq_wake(irq) < 0) - dev_err(&new_client->dev, "IRQ %u cannot be enabled as wake-up" + dev_err(&client->dev, "IRQ %u cannot be enabled as wake-up" "source in this hardware revision!", irq); if (pcf->pdata->used_features & PCF50633_FEAT_RTC) { - pcf->rtc = rtc_device_register("pcf50633", &new_client->dev, + pcf->rtc = rtc_device_register("pcf50633", &client->dev, &pcf50633_rtc_ops, THIS_MODULE); if (IS_ERR(pcf->rtc)) { err = PTR_ERR(pcf->rtc); @@ -2248,7 +2174,7 @@ static int pcf50633_detect(struct i2c_adapter *adapter, int address, int kind) if (pcf->pdata->used_features & PCF50633_FEAT_PWM_BL) { pcf->backlight = backlight_device_register("pcf50633-bl", - &new_client->dev, + &client->dev, pcf, &pcf50633bl_ops); if (!pcf->backlight) @@ -2263,45 +2189,36 @@ static int pcf50633_detect(struct i2c_adapter *adapter, int address, int kind) } if (pcf->pdata->flag_use_apm_emulation) - apm_get_power_status = pcf50633_get_power_status; + apm_get_power_status = NULL; + pdata->pcf = pcf; pcf->probe_completed = 1; - pcf50633_global = pcf; - dev_info(&new_client->dev, "probe completed\n"); + dev_info(&client->dev, "probe completed\n"); /* if platform was interested, give him a chance to register * platform devices that switch power with us as the parent * at registration time -- ensures suspend / resume ordering */ if (pcf->pdata->attach_child_devices) - (pcf->pdata->attach_child_devices)(&new_client->dev); + (pcf->pdata->attach_child_devices)(&client->dev); return 0; exit_rtc: if (pcf->pdata->used_features & PCF50633_FEAT_RTC) - rtc_device_unregister(pcf50633_global->rtc); + rtc_device_unregister(pcf->rtc); exit_irq: - free_irq(pcf50633_global->irq, pcf50633_global); + free_irq(pcf->irq, pcf); exit_input: input_unregister_device(pcf->input_dev); exit_sysfs: pm_power_off = NULL; - sysfs_remove_group(&new_client->dev.kobj, &pcf_attr_group); -exit_detach: - i2c_detach_client(new_client); + sysfs_remove_group(&client->dev.kobj, &pcf_attr_group); exit_free: kfree(pcf); - pcf50633_global = NULL; return err; } -static int pcf50633_attach_adapter(struct i2c_adapter *adapter) -{ - printk(KERN_ERR "**** entering pcf50633_attach_adapter, calling i2c_probe\n"); - return i2c_probe(adapter, &addr_data, &pcf50633_detect); -} - -static int pcf50633_detach_client(struct i2c_client *client) +static int pcf50633_remove(struct i2c_client *client) { struct pcf50633_data *pcf = i2c_get_clientdata(client); @@ -2430,7 +2347,7 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state) /* Save all registers that don't "survive" standby state */ pcf->standby_regs.ooctim2 = __reg_read(pcf, PCF50633_REG_OOCTIM2); - ret = i2c_smbus_read_i2c_block_data(&pcf->client, + ret = i2c_smbus_read_i2c_block_data(pcf->client, PCF50633_REG_AUTOOUT, sizeof(pcf->standby_regs.misc), &pcf->standby_regs.misc[0]); @@ -2438,7 +2355,7 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state) dev_err(dev, "Failed to save misc levels and enables :-(\n"); /* regulator voltages and enable states */ - ret = i2c_smbus_read_i2c_block_data(&pcf->client, + ret = i2c_smbus_read_i2c_block_data(pcf->client, PCF50633_REG_LDO1OUT, sizeof(pcf->standby_regs.ldo), &pcf->standby_regs.ldo[0]); @@ -2477,7 +2394,7 @@ static int pcf50633_suspend(struct device *dev, pm_message_t state) for (i = 0; i < 5; i++) res[i] = ~pcf->pdata->resumers[i]; - ret = i2c_smbus_write_i2c_block_data(&pcf->client, + ret = i2c_smbus_write_i2c_block_data(pcf->client, PCF50633_REG_INT1M, 5, &res[0]); if (ret) @@ -2537,8 +2454,7 @@ EXPORT_SYMBOL_GPL(pcf50633_wait_for_ready); void pcf50633_backlight_resume(struct pcf50633_data *pcf) { - dev_err(&pcf->client.dev, "pcf50633_backlight_resume\n"); - + dev_err(&pcf->client->dev, "pcf50633_backlight_resume\n"); reg_write(pcf, PCF50633_REG_LEDENA, 0x00); reg_write(pcf, PCF50633_REG_LEDDIM, 0x01); reg_write(pcf, PCF50633_REG_LEDENA, 0x01); @@ -2581,7 +2497,7 @@ static int pcf50633_resume(struct device *dev) } /* regulator voltages and enable states */ - ret = i2c_smbus_write_i2c_block_data(&pcf->client, + ret = i2c_smbus_write_i2c_block_data(pcf->client, PCF50633_REG_AUTOOUT, sizeof(misc), &misc[0]); @@ -2593,7 +2509,7 @@ static int pcf50633_resume(struct device *dev) pcf50633_backlight_resume(pcf); /* regulator voltages and enable states */ - ret = i2c_smbus_write_i2c_block_data(&pcf->client, + ret = i2c_smbus_write_i2c_block_data(pcf->client, PCF50633_REG_LDO1OUT, sizeof(pcf->standby_regs.ldo), &pcf->standby_regs.ldo[0]); @@ -2603,7 +2519,7 @@ static int pcf50633_resume(struct device *dev) memset(res, 0, sizeof(res)); /* not interested in second on resume */ res[0] = PCF50633_INT1_SECOND; - ret = i2c_smbus_write_i2c_block_data(&pcf->client, + ret = i2c_smbus_write_i2c_block_data(pcf->client, PCF50633_REG_INT1M, 5, &res[0]); if (ret) @@ -2621,7 +2537,7 @@ static int pcf50633_resume(struct device *dev) * case nothing is waiting for service, no harm done. */ - get_device(&pcf->client.dev); + get_device(&pcf->client->dev); pcf50633_work(&pcf->work); return 0; @@ -2631,74 +2547,29 @@ static int pcf50633_resume(struct device *dev) #define pcf50633_resume NULL #endif +static struct i2c_device_id pcf50633_id_table[] = { + {"pcf50633", 0x73}, +}; + static struct i2c_driver pcf50633_driver = { .driver = { .name = "pcf50633", .suspend= pcf50633_suspend, .resume = pcf50633_resume, }, - .id = I2C_DRIVERID_PCF50633, - .attach_adapter = pcf50633_attach_adapter, - .detach_client = pcf50633_detach_client, -}; - -/* we have this purely to capture an early indication that we are coming out - * of suspend, before our device resume got called; async interrupt service is - * interested in this - */ - -static int pcf50633_plat_resume(struct platform_device *pdev) -{ - /* i2c_get_clientdata(to_i2c_client(&pdev->dev)) returns NULL at this - * early resume time so we have to use pcf50633_global - */ - pcf50633_global->suspend_state = PCF50633_SS_RESUMING_BUT_NOT_US_YET; - - return 0; -} - -/* platform driver, since i2c devices don't have platform_data */ -static int __init pcf50633_plat_probe(struct platform_device *pdev) -{ - struct pcf50633_platform_data *pdata = pdev->dev.platform_data; - - if (!pdata) - return -ENODEV; - - pcf50633_pdev = pdev; - - return 0; -} - -static int pcf50633_plat_remove(struct platform_device *pdev) -{ - return 0; -} - -static struct platform_driver pcf50633_plat_driver = { - .probe = pcf50633_plat_probe, - .remove = pcf50633_plat_remove, - .resume_early = pcf50633_plat_resume, - .driver = { - .owner = THIS_MODULE, - .name = "pcf50633", - }, + .id_table = pcf50633_id_table, + .probe = pcf50633_probe, + .remove = pcf50633_remove, }; static int __init pcf50633_init(void) { - int rc; - - if (!(rc = platform_driver_register(&pcf50633_plat_driver))) - rc = i2c_add_driver(&pcf50633_driver); - - return rc; + return i2c_add_driver(&pcf50633_driver); } static void pcf50633_exit(void) { i2c_del_driver(&pcf50633_driver); - platform_driver_unregister(&pcf50633_plat_driver); } MODULE_DESCRIPTION("I2C chip driver for NXP PCF50633 power management unit"); diff --git a/include/linux/pcf50633.h b/include/linux/pcf50633.h index c11a637c2ac..1d44ebf10b7 100644 --- a/include/linux/pcf50633.h +++ b/include/linux/pcf50633.h @@ -76,10 +76,9 @@ enum pcf50633_reg_int5 { }; struct pcf50633_data; -extern struct pcf50633_data *pcf50633_global; extern void -pcf50633_go_standby(void); +pcf50633_go_standby(struct pcf50633_data *pcf); enum pcf50633_gpio { PCF50633_GPIO1 = 1, @@ -175,6 +174,9 @@ struct pcf50633_platform_data { /* post-resume backlight bringup */ int defer_resume_backlight; u8 resume_backlight_ramp_speed; + + /* Runtime data */ + struct pcf50633_data *pcf; }; #endif /* _PCF50633_H */ |