diff options
Diffstat (limited to 'arch/arm')
-rw-r--r-- | arch/arm/mach-s3c2440/mach-gta02.c | 396 | ||||
-rw-r--r-- | arch/arm/plat-s3c24xx/neo1973_pm_gps.c | 173 |
2 files changed, 281 insertions, 288 deletions
diff --git a/arch/arm/mach-s3c2440/mach-gta02.c b/arch/arm/mach-s3c2440/mach-gta02.c index 5b537f70d56..b8811169743 100644 --- a/arch/arm/mach-s3c2440/mach-gta02.c +++ b/arch/arm/mach-s3c2440/mach-gta02.c @@ -45,6 +45,16 @@ #include <linux/mtd/partitions.h> #include <linux/mtd/physmap.h> +#include <linux/i2c.h> +#include <linux/backlight.h> +#include <linux/regulator/machine.h> + +#include <linux/mfd/pcf50633/core.h> +#include <linux/mfd/pcf50633/mbc.h> +#include <linux/mfd/pcf50633/adc.h> +#include <linux/mfd/pcf50633/gpio.h> +#include <linux/mfd/pcf50633/pmic.h> + #include <linux/lis302dl.h> #include <asm/mach/arch.h> @@ -98,17 +108,9 @@ #include <../drivers/input/touchscreen/ts_filter_median.h> #include <../drivers/input/touchscreen/ts_filter_group.h> -#include <linux/mfd/pcf50633/core.h> -#include <linux/mfd/pcf50633/gpio.h> -#include <linux/mfd/pcf50633/mbc.h> -#include <linux/pcf506xx.h> - /* arbitrates which sensor IRQ owns the shared SPI bus */ static spinlock_t motion_irq_lock; -static int gta02_charger_online_status; -static int gta02_charger_active_status; - /* define FIQ IPC struct */ /* * contains stuff FIQ ISR modifies and normal kernel code can see and use @@ -473,14 +475,20 @@ static struct s3c2410_uartcfg gta02_uartcfgs[] = { /* BQ27000 Battery */ +struct pcf50633 *gta02_pcf; + static int gta02_get_charger_online_status(void) { - return gta02_charger_online_status; + struct pcf50633 *pcf = gta02_pcf; + + return pcf50633_mbc_get_status(pcf) & PCF50633_MBC_USB_ONLINE; } static int gta02_get_charger_active_status(void) { - return gta02_charger_active_status; + struct pcf50633 *pcf = gta02_pcf; + + return pcf50633_mbc_get_status(pcf) & PCF50633_MBC_USB_ACTIVE; } @@ -522,10 +530,10 @@ gta02_configure_pmu_for_charger(struct pcf50633 *pcf, void *unused, int res) pcf50633_mbc_usb_curlim_set(pcf, ma); } -/* PMU driver info */ +static struct delayed_work gta02_charger_work; +static int gta02_usb_vbus_draw; -static int pmu_callback(struct device *dev, unsigned int feature, - enum pmu_event event) +static void gta02_charger_worker(struct work_struct *work) { struct pcf50633 *pcf = gta02_pcf; @@ -539,9 +547,19 @@ static int pmu_callback(struct device *dev, unsigned int feature, gta02_configure_pmu_for_charger, NULL); return; } +} - bq27000_charging_state_change(&bq27000_battery_device); - return 0; +#define GTA02_CHARGER_CONFIGURE_TIMEOUT ((3000 * HZ) / 1000) +static void gta02_pmu_event_callback(struct pcf50633 *pcf, int irq) +{ + if (irq == PCF50633_IRQ_USBINS) { + schedule_delayed_work(>a02_charger_work, + GTA02_CHARGER_CONFIGURE_TIMEOUT); + return; + } else if (irq == PCF50633_IRQ_USBREM) { + cancel_delayed_work_sync(>a02_charger_work); + gta02_usb_vbus_draw = 0; + } } static struct platform_device gta01_pm_gps_dev = { @@ -566,7 +584,8 @@ static struct platform_device gta02_pm_gsm_dev = { static struct platform_device gta02_glamo_dev; static void mangle_glamo_res_by_system_rev(void); -static void gta02_pcf50633_attach_child_devices(struct device *parent_device); +static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf); +static void gta02_pmu_regulator_registered(struct pcf50633 *pcf, int id); static struct platform_device gta02_pm_wlan_dev = { .name = "gta02-pm-wlan", @@ -606,22 +625,21 @@ static char *gta02_batteries[] = { struct pcf50633_platform_data gta02_pcf_pdata = { .resumers = { - [0] = PCF50633_INT1_USBINS | - PCF50633_INT1_USBREM | - PCF50633_INT1_ALARM, - [1] = PCF50633_INT2_ONKEYF, - [2] = PCF50633_INT3_ONKEY1S + [0] = PCF50633_INT1_USBINS | + PCF50633_INT1_USBREM | + PCF50633_INT1_ALARM, + [1] = PCF50633_INT2_ONKEYF, + [2] = PCF50633_INT3_ONKEY1S, + [3] = PCF50633_INT4_LOWSYS | + PCF50633_INT4_LOWBAT | + PCF50633_INT4_HIGHTMP, }, - /* warning: these get rewritten during machine init below - * depending on pcb variant - */ - .rails = { + + .batteries = gta02_batteries, + .num_batteries = ARRAY_SIZE(gta02_batteries), + + .reg_init_data = { [PCF50633_REGULATOR_AUTO] = { - .name = "io_3v3", - .flags = PMU_VRAIL_F_SUSPEND_ON, - .voltage = { - .init = 3300, - .max = 3300, .constraints = { .min_uV = 3300000, .max_uV = 3300000, @@ -632,17 +650,9 @@ struct pcf50633_platform_data gta02_pcf_pdata = { .enabled = 1, }, }, + .num_consumer_supplies = 0, }, [PCF50633_REGULATOR_DOWN1] = { - .name = "core_1v3", - /* Wow, when we are going into suspend, after pcf50633 - * runs its suspend (which happens real early since it - * is an i2c device) we are running out of the 22uF cap - * on core_1v3 rail !!!! - */ - .voltage = { - .init = 1300, - .max = 1600, .constraints = { .min_uV = 1300000, .max_uV = 1600000, @@ -650,13 +660,9 @@ struct pcf50633_platform_data gta02_pcf_pdata = { .boot_on = 1, .apply_uV = 1, }, + .num_consumer_supplies = 0, }, [PCF50633_REGULATOR_DOWN2] = { - .name = "core_1v8", - .flags = PMU_VRAIL_F_SUSPEND_ON, - .voltage = { - .init = 1800, - .max = 1800, .constraints = { .min_uV = 1800000, .max_uV = 1800000, @@ -667,12 +673,9 @@ struct pcf50633_platform_data gta02_pcf_pdata = { .enabled = 1, }, }, + .num_consumer_supplies = 0, }, [PCF50633_REGULATOR_HCLDO] = { - .name = "sd_3v3", - .voltage = { - .init = 2000, - .max = 3300, .constraints = { .min_uV = 2000000, .max_uV = 3300000, @@ -680,40 +683,47 @@ struct pcf50633_platform_data gta02_pcf_pdata = { .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE, .boot_on = 1, }, + .num_consumer_supplies = 1, + .consumer_supplies = hcldo_consumers, }, [PCF50633_REGULATOR_LDO1] = { - .name = "gsensor_3v3", - .voltage = { - .init = 1300, - .max = 1330, + .constraints = { + .min_uV = 1300000, + .max_uV = 1300000, + .valid_modes_mask = REGULATOR_MODE_NORMAL, + .apply_uV = 1, }, + .num_consumer_supplies = 0, }, [PCF50633_REGULATOR_LDO2] = { - .name = "codec_3v3", - .voltage = { - .init = 3300, - .max = 3300, + .constraints = { + .min_uV = 3300000, + .max_uV = 3300000, + .valid_modes_mask = REGULATOR_MODE_NORMAL, + .apply_uV = 1, }, + .num_consumer_supplies = 0, }, [PCF50633_REGULATOR_LDO3] = { - .name = "unused3", - .voltage = { - .init = 3000, - .max = 3000, + .constraints = { + .min_uV = 3000000, + .max_uV = 3000000, + .valid_modes_mask = REGULATOR_MODE_NORMAL, + .apply_uV = 1, }, + .num_consumer_supplies = 0, }, [PCF50633_REGULATOR_LDO4] = { - .name = "bt_3v2", - .voltage = { - .init = 2500, - .max = 3300, + .constraints = { + .min_uV = 3200000, + .max_uV = 3200000, + .valid_modes_mask = REGULATOR_MODE_NORMAL, + .apply_uV = 1, }, + .num_consumer_supplies = 1, + .consumer_supplies = ldo4_consumers, }, [PCF50633_REGULATOR_LDO5] = { - .name = "rf3v", - .voltage = { - .init = 1500, - .max = 1500, .constraints = { .min_uV = 1500000, .max_uV = 1500000, @@ -723,115 +733,76 @@ struct pcf50633_platform_data gta02_pcf_pdata = { .enabled = 1, }, }, + .num_consumer_supplies = 1, + .consumer_supplies = ldo5_consumers, }, [PCF50633_REGULATOR_LDO6] = { - .name = "lcm_3v", - .flags = PMU_VRAIL_F_SUSPEND_ON, - .voltage = { - .init = 0, - .max = 3300, .constraints = { .min_uV = 0, .max_uV = 3300000, .valid_modes_mask = REGULATOR_MODE_NORMAL, }, + .num_consumer_supplies = 0, }, [PCF50633_REGULATOR_MEMLDO] = { - .name = "memldo", - .flags = PMU_VRAIL_F_SUSPEND_ON, - .voltage = { - .init = 1800, - .max = 1800, + .constraints = { + .min_uV = 1800000, + .max_uV = 1800000, + .valid_modes_mask = REGULATOR_MODE_NORMAL, + .state_mem = { + .enabled = 1, + }, }, + .num_consumer_supplies = 0, }, - }, - .defer_resume_backlight = 1, - .resume_backlight_ramp_speed = 5, - .attach_child_devices = gta02_pcf50633_attach_child_devices + }, + .probe_done = gta02_pmu_attach_child_devices, + .regulator_registered = gta02_pmu_regulator_registered, + .mbc_event_callback = gta02_pmu_event_callback, }; -#if 0 /* currently unused */ -static void cfg_pmu_vrail(struct pmu_voltage_rail *vrail, char *name, - unsigned int flags, unsigned int init, - unsigned int max) -{ - vrail->name = name; - vrail->flags = flags; - vrail->voltage.init = init; - vrail->voltage.max = max; -} -#endif - static void mangle_pmu_pdata_by_system_rev(void) { + struct regulator_init_data *reg_init_data; + + reg_init_data = gta02_pcf_pdata.reg_init_data; + switch (system_rev) { case GTA02v1_SYSTEM_REV: /* FIXME: this is only in v1 due to wrong PMU variant */ - gta02_pcf_pdata.rails[PCF50633_REGULATOR_DOWN2].flags = - PMU_VRAIL_F_SUSPEND_ON; + reg_init_data[PCF50633_REGULATOR_DOWN2] + .constraints.state_mem.enabled = 1; break; case GTA02v2_SYSTEM_REV: case GTA02v3_SYSTEM_REV: case GTA02v4_SYSTEM_REV: case GTA02v5_SYSTEM_REV: case GTA02v6_SYSTEM_REV: - /* we need to keep the 1.8V going since this is the SDRAM - * self-refresh voltage */ - gta02_pcf_pdata.rails[PCF50633_REGULATOR_DOWN2].flags = - PMU_VRAIL_F_SUSPEND_ON; - gta02_pcf_pdata.rails[PCF50633_REGULATOR_DOWN2].name = - "io_1v8", - gta02_pcf_pdata.rails[PCF50633_REGULATOR_LDO1].name = - "gsensor_3v3", - gta02_pcf_pdata.rails[PCF50633_REGULATOR_LDO1].voltage.init = - 3300; - gta02_pcf_pdata.rails[PCF50633_REGULATOR_LDO1].voltage.max = - 3300; - gta02_pcf_pdata.rails[PCF50633_REGULATOR_LDO1].flags &= - ~PMU_VRAIL_F_SUSPEND_ON; - gta02_pcf_pdata.rails[PCF50633_REGULATOR_LDO3].flags = - PMU_VRAIL_F_UNUSED; - gta02_pcf_pdata.rails[PCF50633_REGULATOR_LDO5] = ((struct pmu_voltage_rail) { - .name = "rf_3v", - .voltage = { - .init = 0, - .max = 3000, - } - }); - gta02_pcf_pdata.rails[PCF50633_REGULATOR_LDO6] = - ((struct pmu_voltage_rail) { - .name = "lcm_3v", - .flags = PMU_VRAIL_F_SUSPEND_ON, - .voltage = { - .init = 3000, - .max = 3000, - } - }); + reg_init_data[PCF50633_REGULATOR_LDO1] + .constraints.min_uV = 3300000; + reg_init_data[PCF50633_REGULATOR_LDO1] + .constraints.min_uV = 3300000; + reg_init_data[PCF50633_REGULATOR_LDO1] + .constraints.state_mem.enabled = 0; + + reg_init_data[PCF50633_REGULATOR_LDO5] + .constraints.min_uV = 3000000; + reg_init_data[PCF50633_REGULATOR_LDO5] + .constraints.max_uV = 3000000; + + reg_init_data[PCF50633_REGULATOR_LDO6] + .constraints.min_uV = 3000000; + reg_init_data[PCF50633_REGULATOR_LDO6] + .constraints.max_uV = 3000000; + reg_init_data[PCF50633_REGULATOR_LDO6] + .constraints.apply_uV = 1; break; default: break; } } -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 */ @@ -956,6 +927,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", @@ -1078,10 +1057,11 @@ static struct s3c2410_ts_mach_info gta02_ts_cfg = { }, }; + static void gta02_bl_set_intensity(int intensity) { - struct pcf50633 *pcf = gta02_pcf_pdata.pcf; - int old_intensity; + struct pcf50633 *pcf = gta02_pcf; + int old_intensity = pcf50633_reg_read(pcf, PCF50633_REG_LEDOUT); int ret; intensity >>= 2; @@ -1149,19 +1129,25 @@ static struct platform_device gta02_bl_dev = { static void gta02_jbt6k74_reset(int devidx, int level) { glamo_lcm_reset(level); -} +} -/* finally bring up deferred backlight resume now LCM is resumed itself */ - -static void gta02_jbt6k74_resuming(int devidx) +static void gta02_jbt6k74_probe_completed(struct device *dev) { - pcf50633_backlight_resume(pcf50633_global); -} + struct pcf50633 *pcf = gta02_pcf; + /* Switch on backlight. Qi does not do it for us */ + pcf50633_reg_write(pcf, PCF50633_REG_LEDOUT, 0x01); + pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0x00); + pcf50633_reg_write(pcf, PCF50633_REG_LEDDIM, 0x01); + pcf50633_reg_write(pcf, PCF50633_REG_LEDENA, 0x01); + + gta02_bl_dev.dev.parent = dev; + platform_device_register(>a02_bl_dev); +} const struct jbt6k74_platform_data jbt6k74_pdata = { .reset = gta02_jbt6k74_reset, - .resuming = gta02_jbt6k74_resuming, + .probe_completed = gta02_jbt6k74_probe_completed, }; static struct spi_board_info gta02_spi_board_info[] = { @@ -1487,61 +1473,18 @@ static int glamo_irq_is_wired(void) return -ENODEV; } - -static void -gta02_glamo_mmc_set_power(unsigned char power_mode, unsigned short vdd) +static int gta02_glamo_can_set_mmc_power(void) { - int mv = 1650; - int timeout = 500; - - printk(KERN_DEBUG "mmc_set_power(power_mode=%u, vdd=%u)\n", - power_mode, vdd); - switch (system_rev) { - case GTA02v1_SYSTEM_REV: - case GTA02v2_SYSTEM_REV: - break; - case GTA02v3_SYSTEM_REV: - case GTA02v4_SYSTEM_REV: - case GTA02v5_SYSTEM_REV: - case GTA02v6_SYSTEM_REV: - switch (power_mode) { - case MMC_POWER_ON: - case MMC_POWER_UP: - /* depend on pcf50633 driver init + not suspended */ - while (pcf50633_ready(pcf50633_global) && (timeout--)) - msleep(5); - - if (timeout < 0) { - printk(KERN_ERR"gta02_glamo_mmc_set_power " - "BAILING on timeout\n"); - return; - } - /* select and set the voltage */ - if (vdd > 7) - mv += 350 + 100 * (vdd - 8); - printk(KERN_INFO "SD power -> %dmV\n", mv); - pcf50633_voltage_set(pcf50633_global, - PCF50633_REGULATOR_HCLDO, mv); - pcf50633_onoff_set(pcf50633_global, - PCF50633_REGULATOR_HCLDO, 1); - break; - case MMC_POWER_OFF: - /* power off happens during suspend, when pcf50633 can - * be already gone and not coming back... just forget - * the action then because pcf50633 suspend already - * dealt with it, otherwise we spin forever - */ - if (pcf50633_ready(pcf50633_global)) - return; - pcf50633_onoff_set(pcf50633_global, - PCF50633_REGULATOR_HCLDO, 0); - break; - } - break; + case GTA02v3_SYSTEM_REV: + case GTA02v4_SYSTEM_REV: + case GTA02v5_SYSTEM_REV: + case GTA02v6_SYSTEM_REV: + return 1; } -} + return 0; +} /* Smedia Glamo 3362 */ @@ -1591,7 +1534,8 @@ static struct glamofb_platform_data gta02_glamo_pdata = { .spigpio_info = &glamo_spigpio_cfg, /* glamo MMC function platform data */ - .glamo_set_mci_power = gta02_glamo_mmc_set_power, + .mmc_dev = >a02_mmc_dev, + .glamo_can_set_mci_power = gta02_glamo_can_set_mmc_power, .glamo_mci_use_slow = gta02_glamo_mci_use_slow, .glamo_irq_is_wired = glamo_irq_is_wired, .glamo_external_reset = gta02_glamo_external_reset @@ -1697,7 +1641,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, @@ -1706,10 +1649,7 @@ static struct platform_device *gta02_devices[] __initdata = { /* these guys DO need to be children of PMU */ static struct platform_device *gta02_devices_pmu_children[] = { - >a02_glamo_dev, /* glamo-mci power handling depends on PMU */ &s3c_device_ts, /* input 1 */ - >a01_pm_gps_dev, - >a01_pm_bt_dev, >a02_pm_gsm_dev, >a02_pm_usbhost_dev, &s3c_device_spi_acc1, /* input 2 */ @@ -1718,6 +1658,30 @@ static struct platform_device *gta02_devices_pmu_children[] = { >a02_resume_reason_device, }; +static void gta02_pmu_regulator_registered(struct pcf50633 *pcf, int id) +{ + struct platform_device *regulator, *pdev; + + regulator = pcf->regulator_pdev[id]; + + switch(id) { + case PCF50633_REGULATOR_LDO4: + pdev = >a01_pm_bt_dev; + break; + case PCF50633_REGULATOR_LDO5: + pdev = >a01_pm_gps_dev; + break; + case PCF50633_REGULATOR_HCLDO: + pdev = >a02_glamo_dev; + break; + default: + return; + } + + pdev->dev.parent = ®ulator->dev; + platform_device_register(pdev); +} + /* this is called when pc50633 is probed, unfortunately quite late in the * day since it is an I2C bus device. Here we can belatedly define some * platform devices with the advantage that we can mark the pcf50633 as the @@ -1725,18 +1689,14 @@ static struct platform_device *gta02_devices_pmu_children[] = { * the pcf50633 still around. */ -static void gta02_pcf50633_attach_child_devices(struct device *parent_device) +static void gta02_pmu_attach_child_devices(struct pcf50633 *pcf) { int n; gta02_pcf = pcf; - gta02_pcf = pcf; - - gta02_pcf = pcf; - for (n = 0; n < ARRAY_SIZE(gta02_devices_pmu_children); n++) - gta02_devices_pmu_children[n]->dev.parent = parent_device; + gta02_devices_pmu_children[n]->dev.parent = pcf->dev; mangle_glamo_res_by_system_rev(); platform_add_devices(gta02_devices_pmu_children, @@ -1792,6 +1752,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_gps.c b/arch/arm/plat-s3c24xx/neo1973_pm_gps.c index 3db733c86f4..9b455229e6d 100644 --- a/arch/arm/plat-s3c24xx/neo1973_pm_gps.c +++ b/arch/arm/plat-s3c24xx/neo1973_pm_gps.c @@ -25,22 +25,40 @@ /* For GTA01 */ #include <mach/gta01.h> -#include <linux/pcf50606.h> +#include <linux/mfd/pcf50606/core.h> +#include <linux/mfd/pcf50606/gpo.h> /* For GTA02 */ #include <mach/gta02.h> #include <linux/mfd/pcf50633/core.h> +#include <linux/mfd/pcf50633/pmic.h> #include <linux/regulator/consumer.h> - #include <linux/err.h> +enum gta01_pm_gps_supplies { + + /* GTA01 */ + GTA01_GPS_REG_2V8, + GTA01_GPS_REG_3V, + GTA01_GPS_REG_3V3, + GTA01_GPS_REG_1V5, + GTA01_GPS_REG_2V5, + + /* GTA02 */ + GTA02_GPS_REG_RF_3V, + + /* Always last */ + GTA01_GPS_NUM_REG +}; + struct neo1973_pm_gps_data { - int power_was_on; - struct regulator *regulator; #ifdef CONFIG_PM int keep_on_in_suspend; #endif + int power_was_on; /* For GTA02 only */ + int regulator_state[GTA01_GPS_NUM_REG]; + struct regulator *regulator[GTA01_GPS_NUM_REG]; }; static struct neo1973_pm_gps_data neo1973_gps; @@ -57,14 +75,16 @@ EXPORT_SYMBOL_GPL(neo1973_pm_gps_is_on); * the input to VDD_RF */ static void gps_power_2v8_set(int on) { + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_2V8]; + switch (system_rev) { case GTA01v3_SYSTEM_REV: case GTA01v4_SYSTEM_REV: if (on) - pcf50606_voltage_set(pcf50606_global, - PCF50606_REGULATOR_IOREG, 2800); - pcf50606_onoff_set(pcf50606_global, - PCF50606_REGULATOR_IOREG, on); + regulator_enable(regulator); + else + regulator_disable(regulator); + neo1973_gps.regulator_state[GTA01_GPS_REG_2V8] = on; break; case GTA01Bv2_SYSTEM_REV: s3c2410_gpio_setpin(GTA01_GPIO_GPS_EN_2V8, on); @@ -78,15 +98,12 @@ static void gps_power_2v8_set(int on) static int gps_power_2v8_get(void) { int ret = 0; + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_2V8]; switch (system_rev) { case GTA01v3_SYSTEM_REV: case GTA01v4_SYSTEM_REV: - if (pcf50606_onoff_get(pcf50606_global, - PCF50606_REGULATOR_IOREG) && - pcf50606_voltage_get(pcf50606_global, - PCF50606_REGULATOR_IOREG) == 2800) - ret = 1; + ret = regulator_is_enabled(regulator); break; case GTA01Bv2_SYSTEM_REV: if (s3c2410_gpio_getpin(GTA01_GPIO_GPS_EN_2V8)) @@ -103,14 +120,16 @@ static int gps_power_2v8_get(void) /* This is the 3V supply (AVDD) for the external RF frontend (LNA bias) */ static void gps_power_3v_set(int on) { + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_3V]; + switch (system_rev) { case GTA01v3_SYSTEM_REV: case GTA01v4_SYSTEM_REV: if (on) - pcf50606_voltage_set(pcf50606_global, - PCF50606_REGULATOR_D1REG, 3000); - pcf50606_onoff_set(pcf50606_global, - PCF50606_REGULATOR_D1REG, on); + regulator_enable(regulator); + else + regulator_disable(regulator); + neo1973_gps.regulator_state[GTA01_GPS_REG_3V3] = on; break; case GTA01Bv2_SYSTEM_REV: case GTA01Bv3_SYSTEM_REV: @@ -123,15 +142,12 @@ static void gps_power_3v_set(int on) static int gps_power_3v_get(void) { int ret = 0; + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_3V]; switch (system_rev) { case GTA01v3_SYSTEM_REV: case GTA01v4_SYSTEM_REV: - if (pcf50606_onoff_get(pcf50606_global, - PCF50606_REGULATOR_D1REG) && - pcf50606_voltage_get(pcf50606_global, - PCF50606_REGULATOR_D1REG) == 3000) - ret = 1; + ret = regulator_is_enabled(regulator); break; case GTA01Bv2_SYSTEM_REV: case GTA01Bv3_SYSTEM_REV: @@ -147,15 +163,17 @@ static int gps_power_3v_get(void) /* This is the 3.3V supply for VDD_IO and VDD_LPREG input */ static void gps_power_3v3_set(int on) { + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_3V3]; + switch (system_rev) { case GTA01v3_SYSTEM_REV: case GTA01v4_SYSTEM_REV: case GTA01Bv2_SYSTEM_REV: if (on) - pcf50606_voltage_set(pcf50606_global, - PCF50606_REGULATOR_DCD, 3300); - pcf50606_onoff_set(pcf50606_global, - PCF50606_REGULATOR_DCD, on); + regulator_enable(regulator); + else + regulator_disable(regulator); + neo1973_gps.regulator_state[GTA01_GPS_REG_3V3] = on; break; case GTA01Bv3_SYSTEM_REV: case GTA01Bv4_SYSTEM_REV: @@ -167,16 +185,13 @@ static void gps_power_3v3_set(int on) static int gps_power_3v3_get(void) { int ret = 0; + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_3V3]; switch (system_rev) { case GTA01v3_SYSTEM_REV: case GTA01v4_SYSTEM_REV: case GTA01Bv2_SYSTEM_REV: - if (pcf50606_onoff_get(pcf50606_global, - PCF50606_REGULATOR_DCD) && - pcf50606_voltage_get(pcf50606_global, - PCF50606_REGULATOR_DCD) == 3300) - ret = 1; + ret = regulator_is_enabled(regulator); break; case GTA01Bv3_SYSTEM_REV: case GTA01Bv4_SYSTEM_REV: @@ -191,6 +206,8 @@ static int gps_power_3v3_get(void) /* This is the 2.5V supply for VDD_PLLREG and VDD_COREREG input */ static void gps_power_2v5_set(int on) { + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_2V5]; + switch (system_rev) { case GTA01v3_SYSTEM_REV: /* This is CORE_1V8 and cannot be disabled */ @@ -200,10 +217,10 @@ static void gps_power_2v5_set(int on) case GTA01Bv3_SYSTEM_REV: case GTA01Bv4_SYSTEM_REV: if (on) - pcf50606_voltage_set(pcf50606_global, - PCF50606_REGULATOR_D2REG, 2500); - pcf50606_onoff_set(pcf50606_global, - PCF50606_REGULATOR_D2REG, on); + regulator_enable(regulator); + else + regulator_disable(regulator); + neo1973_gps.regulator_state[GTA01_GPS_REG_2V5] = on; break; } } @@ -211,6 +228,7 @@ static void gps_power_2v5_set(int on) static int gps_power_2v5_get(void) { int ret = 0; + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_2V5]; switch (system_rev) { case GTA01v3_SYSTEM_REV: @@ -221,11 +239,7 @@ static int gps_power_2v5_get(void) case GTA01Bv2_SYSTEM_REV: case GTA01Bv3_SYSTEM_REV: case GTA01Bv4_SYSTEM_REV: - if (pcf50606_onoff_get(pcf50606_global, - PCF50606_REGULATOR_D2REG) && - pcf50606_voltage_get(pcf50606_global, - PCF50606_REGULATOR_D2REG) == 2500) - ret = 1; + ret = regulator_is_enabled(regulator); break; } @@ -235,6 +249,8 @@ static int gps_power_2v5_get(void) /* This is the 1.5V supply for VDD_CORE */ static void gps_power_1v5_set(int on) { + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_1V5]; + switch (system_rev) { case GTA01v3_SYSTEM_REV: case GTA01v4_SYSTEM_REV: @@ -244,10 +260,10 @@ static void gps_power_1v5_set(int on) case GTA01Bv3_SYSTEM_REV: case GTA01Bv4_SYSTEM_REV: if (on) - pcf50606_voltage_set(pcf50606_global, - PCF50606_REGULATOR_DCD, 1500); - pcf50606_onoff_set(pcf50606_global, - PCF50606_REGULATOR_DCD, on); + regulator_enable(regulator); + else + regulator_disable(regulator); + neo1973_gps.regulator_state[GTA01_GPS_REG_1V5] = on; break; } } @@ -255,6 +271,7 @@ static void gps_power_1v5_set(int on) static int gps_power_1v5_get(void) { int ret = 0; + struct regulator *regulator = neo1973_gps.regulator[GTA01_GPS_REG_1V5]; switch (system_rev) { case GTA01v3_SYSTEM_REV: @@ -265,11 +282,7 @@ static int gps_power_1v5_get(void) break; case GTA01Bv3_SYSTEM_REV: case GTA01Bv4_SYSTEM_REV: - if (pcf50606_onoff_get(pcf50606_global, - PCF50606_REGULATOR_DCD) && - pcf50606_voltage_get(pcf50606_global, - PCF50606_REGULATOR_DCD) == 1500) - ret = 1; + ret = regulator_is_enabled(regulator); break; } @@ -286,8 +299,6 @@ static void gps_pwron_set(int on) if (machine_is_neo1973_gta02()) { if (on) { - pcf50633_voltage_set(pcf50633_global, - PCF50633_REGULATOR_LDO5, 3000); /* return UART pins to being UART pins */ s3c2410_gpio_cfgpin(S3C2410_GPH4, S3C2410_GPH4_TXD1); /* remove pulldown now it won't be floating any more */ @@ -302,11 +313,10 @@ static void gps_pwron_set(int on) /* don't let RX from unpowered GPS float */ s3c2410_gpio_pullup(S3C2410_GPH5, 1); } - if (on && !regulator_is_enabled(neo1973_gps.regulator)) - regulator_enable(neo1973_gps.regulator); - - if (!on && regulator_is_enabled(neo1973_gps.regulator)) - regulator_disable(neo1973_gps.regulator); + if (on && !neo1973_gps.power_was_on) + regulator_enable(neo1973_gps.regulator[GTA02_GPS_REG_RF_3V]); + else if (!on && neo1973_gps.power_was_on) + regulator_disable(neo1973_gps.regulator[GTA02_GPS_REG_RF_3V]); } } @@ -316,8 +326,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, - PCF50633_REGULATOR_LDO5); + return regulator_is_enabled(neo1973_gps.regulator[GTA02_GPS_REG_RF_3V]); return -1; } @@ -413,7 +422,7 @@ static void gps_rst_set(int on) { switch (system_rev) { case GTA01v3_SYSTEM_REV: - pcf50606_gpo0_set(pcf50606_global, on); + pcf50606_gpo_set_active(gta01_pcf, PCF50606_GPO1, on); break; case GTA01v4_SYSTEM_REV: case GTA01Bv2_SYSTEM_REV: @@ -428,8 +437,7 @@ static int gps_rst_get(void) { switch (system_rev) { case GTA01v3_SYSTEM_REV: - if (pcf50606_gpo0_get(pcf50606_global)) - return 1; + return pcf50606_gpo_get_active(gta01_pcf, PCF50606_GPO1); break; case GTA01v4_SYSTEM_REV: case GTA01Bv2_SYSTEM_REV: @@ -487,17 +495,22 @@ static void gps_power_sequence_down(void) /* Don't disable AVDD before PWRON is cleared, since * in GTA01Bv3, AVDD and RFREG_IN are shared */ - gps_power_3v_set(0); + if (neo1973_gps.regulator_state[GTA01_GPS_REG_3V]) + gps_power_3v_set(0); /* Remove VDD_COREREG_IN, VDD_PLLREG_IN and VDD_REFREG_IN */ - gps_power_1v5_set(0); - gps_power_2v5_set(0); - gps_power_2v8_set(0); + if (neo1973_gps.regulator_state[GTA01_GPS_REG_1V5]) + gps_power_1v5_set(0); + if (neo1973_gps.regulator_state[GTA01_GPS_REG_2V5]) + gps_power_2v5_set(0); + if (neo1973_gps.regulator_state[GTA01_GPS_REG_2V8]) + gps_power_2v8_set(0); /* Remove VDD_LPREG_IN and VDD_IO */ - gps_power_3v3_set(0); -} + if (neo1973_gps.regulator_state[GTA01_GPS_REG_3V3]) + gps_power_3v3_set(0); +} static ssize_t power_sequence_read(struct device *dev, struct device_attribute *attr, @@ -643,6 +656,18 @@ static int __init gta01_pm_gps_probe(struct platform_device *pdev) } #ifdef CONFIG_MACH_NEO1973_GTA01 + + neo1973_gps.regulator[GTA01_GPS_REG_2V8] = + regulator_get(&pdev->dev, "GPS_2V8"); + neo1973_gps.regulator[GTA01_GPS_REG_3V] = + regulator_get(&pdev->dev, "GPS_3V"); + neo1973_gps.regulator[GTA01_GPS_REG_3V3] = + regulator_get(&pdev->dev, "GPS_3V3"); + neo1973_gps.regulator[GTA01_GPS_REG_1V5] = + regulator_get(&pdev->dev, "GPS_1V5"); + neo1973_gps.regulator[GTA01_GPS_REG_2V5] = + regulator_get(&pdev->dev, "GPS_2V5"); + gps_power_sequence_down(); switch (system_rev) { @@ -673,7 +698,7 @@ static int __init gta01_pm_gps_probe(struct platform_device *pdev) case GTA02v4_SYSTEM_REV: case GTA02v5_SYSTEM_REV: case GTA02v6_SYSTEM_REV: - neo1973_gps.regulator = regulator_get( + neo1973_gps.regulator[GTA02_GPS_REG_RF_3V] = regulator_get( &pdev->dev, "RF_3V"); if (IS_ERR(neo1973_gps.regulator)) { dev_err(&pdev->dev, "probe failed %ld\n", @@ -681,7 +706,7 @@ static int __init gta01_pm_gps_probe(struct platform_device *pdev) return PTR_ERR(neo1973_gps.regulator); } - dev_info(&pdev->dev, "FIC Neo1973 GPS Power Management:" + dev_info(&pdev->dev, "FIC Neo1973 GPS Power Managerment:" "starting\n"); break; default: @@ -699,7 +724,7 @@ static int __init gta01_pm_gps_probe(struct platform_device *pdev) * to second-guess some of its internal logic and make it do * something that isn't really part of its design. */ - pcf50633_reg_write(gta02_pcf_pdata.pcf, + pcf50633_reg_write(gta02_pcf, PCF50633_REG_LDO5ENA, 0); return sysfs_create_group(&pdev->dev.kobj, @@ -712,13 +737,19 @@ static int gta01_pm_gps_remove(struct platform_device *pdev) { if (machine_is_neo1973_gta01()) { #ifdef CONFIG_MACH_NEO1973_GTA01 + int i; + gps_power_sequence_down(); + /* Now disable all regulators */ + for (i = 0; i < GTA01_GPS_NUM_REG; i++) { + regulator_put(neo1973_gps.regulator[i]); + } #endif sysfs_remove_group(&pdev->dev.kobj, >a01_gps_attr_group); } if (machine_is_neo1973_gta02()) { - pcf50633_onoff_set(pcf50633_global, PCF50633_REGULATOR_LDO5, 0); + regulator_put(neo1973_gps.regulator[GTA02_GPS_REG_RF_3V]); sysfs_remove_group(&pdev->dev.kobj, >a02_gps_attr_group); } return 0; |