aboutsummaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
authorAndy Green <andy@openmoko.com>2008-11-21 11:56:57 +0000
committerAndy Green <agreen@pads.home.warmcat.com>2008-11-21 11:56:57 +0000
commit51f82d8be7acb8594e82d913d1b4577462703032 (patch)
tree411fdd1f9b6efbd850b49a7b393b396d3cf3b5e7 /arch
parent3afa93d57719fd9b1bf837f5609095237a4187c7 (diff)
introduce-om-gta03-features.patch
This patch adds a single file that is intended to do the job of the several neo1973_pm_* drivers used in GTA02. It exposes the /sys nodes /sys/bus/platform/devices/om-gta03.0/gps_power /sys/bus/platform/devices/om-gta03.0/gsm_power /sys/bus/platform/devices/om-gta03.0/usbhost_power /sys/bus/platform/devices/om-gta03.0/wlan_bt_power at the moment which allow power control of these subsystems. Signed-off-by: Andy Green <andy@openmoko.com>
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/mach-s3c6410/Makefile3
-rw-r--r--arch/arm/mach-s3c6410/include/mach/om-gta03.h8
-rw-r--r--arch/arm/mach-s3c6410/mach-om-gta03.c28
-rw-r--r--arch/arm/mach-s3c6410/om-gta03-features.c304
-rw-r--r--arch/arm/plat-s3c24xx/neo1973_pm_gps.c10
5 files changed, 334 insertions, 19 deletions
diff --git a/arch/arm/mach-s3c6410/Makefile b/arch/arm/mach-s3c6410/Makefile
index 0159ea208ed..e9f30d4a26c 100644
--- a/arch/arm/mach-s3c6410/Makefile
+++ b/arch/arm/mach-s3c6410/Makefile
@@ -21,5 +21,6 @@ obj-$(CONFIG_S3C6410_SETUP_SDHCI) += setup-sdhci.o
# machine support
obj-$(CONFIG_MACH_SMDK6410) += mach-smdk6410.o
-obj-$(CONFIG_MACH_OPENMOKO_GTA03) += mach-om-gta03.o
+obj-$(CONFIG_MACH_OPENMOKO_GTA03) += mach-om-gta03.o \
+ om-gta03-features.o
diff --git a/arch/arm/mach-s3c6410/include/mach/om-gta03.h b/arch/arm/mach-s3c6410/include/mach/om-gta03.h
index c05e014015f..17a07dd4c6f 100644
--- a/arch/arm/mach-s3c6410/include/mach/om-gta03.h
+++ b/arch/arm/mach-s3c6410/include/mach/om-gta03.h
@@ -16,6 +16,9 @@
#include <mach/gpio.h>
#include <mach/irqs.h>
+#include <linux/mfd/pcf50633/core.h>
+
+extern struct pcf50633_platform_data om_gta03_pcf_pdata;
/* ATAG_REVISION from bootloader */
#define GTA03v1_SYSTEM_REV 0x00000001
@@ -41,11 +44,10 @@
#define GTA03_GPIO_WLAN_RESET S3C64XX_GPH(6)
#define GTA03_GPIO_HDQ S3C64XX_GPH(7)
#define GTA03_GPIO_WLAN_PWRDN S3C64XX_GPH(8)
-#define GTA03_GPIO_WLAN_OSC S3C64XX_GPH(9)
-#define GTA03_GPIO_VERSION0 S3C64XX_GPI(0)
+#define GTA03_GPIO_VERSION2 S3C64XX_GPI(0)
#define GTA03_GPIO_VERSION1 S3C64XX_GPI(1)
-#define GTA03_GPIO_VERSION2 S3C64XX_GPI(8)
+#define GTA03_GPIO_VERSION0 S3C64XX_GPI(8)
#define GTA03_GPIO_NWLAN_POWER S3C64XX_GPK(0)
#define GTA03_GPIO_MODEN_ON S3C64XX_GPK(2)
diff --git a/arch/arm/mach-s3c6410/mach-om-gta03.c b/arch/arm/mach-s3c6410/mach-om-gta03.c
index 8ff50822d7f..80543d3cc8e 100644
--- a/arch/arm/mach-s3c6410/mach-om-gta03.c
+++ b/arch/arm/mach-s3c6410/mach-om-gta03.c
@@ -224,14 +224,18 @@ static struct regulator_consumer_supply ldo4_consumers[] = {
.supply = "SD_3V",
},
};
-#if 0
+
+static struct platform_device om_gta03_features_dev = {
+ .name = "om-gta03",
+};
+
static struct regulator_consumer_supply ldo5_consumers[] = {
{
- .dev = &gta01_pm_gps_dev.dev,
+ .dev = &om_gta03_features_dev.dev,
.supply = "RF_3V",
},
};
-#endif
+
static void om_gta03_pmu_event_callback(struct pcf50633 *pcf, int irq)
{
@@ -361,8 +365,8 @@ struct pcf50633_platform_data om_gta03_pcf_pdata = {
.valid_modes_mask = REGULATOR_MODE_NORMAL,
.apply_uV = 1,
},
- .num_consumer_supplies = 0,
-/* .consumer_supplies = ldo5_consumers, */
+ .num_consumer_supplies = 1,
+ .consumer_supplies = ldo5_consumers,
},
/* GTA03: LCM 3V */
[PCF50633_REGULATOR_LDO6] = {
@@ -411,6 +415,7 @@ static struct platform_device *om_gta03_devices[] __initdata = {
&s3c_device_hsmmc1, /* SDIO to WLAN */
};
+
static void om_gta03_pmu_regulator_registered(struct pcf50633 *pcf, int id)
{
struct platform_device *regulator, *pdev;
@@ -434,6 +439,7 @@ static void om_gta03_pmu_regulator_registered(struct pcf50633 *pcf, int id)
static struct platform_device *om_gta03_devices_pmu_children[] = {
&om_gta03_button_dev,
+ &om_gta03_features_dev,
};
/* this is called when pc50633 is probed, unfortunately quite late in the
@@ -504,12 +510,12 @@ static void __init om_gta03_machine_init(void)
s3c_gpio_setpull(S3C64XX_GPJ(8), S3C_GPIO_PULL_NONE);
s3c_gpio_cfgpin(S3C64XX_GPJ(8), S3C_GPIO_SFN(2));
- s3c_gpio_setpull(S3C64XX_GPK(9), S3C_GPIO_PULL_NONE);
- s3c_gpio_cfgpin(S3C64XX_GPK(9), S3C_GPIO_SFN(1));
- s3c_gpio_setpull(S3C64XX_GPK(10), S3C_GPIO_PULL_NONE);
- s3c_gpio_cfgpin(S3C64XX_GPK(10), S3C_GPIO_SFN(1));
- s3c_gpio_setpull(S3C64XX_GPK(11), S3C_GPIO_PULL_NONE);
- s3c_gpio_cfgpin(S3C64XX_GPK(11), S3C_GPIO_SFN(1));
+ s3c_gpio_setpull(S3C64XX_GPJ(9), S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(S3C64XX_GPJ(9), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S3C64XX_GPJ(10), S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(S3C64XX_GPJ(10), S3C_GPIO_SFN(2));
+ s3c_gpio_setpull(S3C64XX_GPJ(11), S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(S3C64XX_GPJ(11), S3C_GPIO_SFN(2));
i2c_register_board_info(0, om_gta03_i2c_devs,
diff --git a/arch/arm/mach-s3c6410/om-gta03-features.c b/arch/arm/mach-s3c6410/om-gta03-features.c
new file mode 100644
index 00000000000..612d705f259
--- /dev/null
+++ b/arch/arm/mach-s3c6410/om-gta03-features.c
@@ -0,0 +1,304 @@
+/*
+ * Support for features of Openmoko GTA03
+ *
+ * (C) 2008 by Openmoko Inc.
+ * Author: Andy Green <andy@openmoko.com>
+ * All rights reserved.
+ *
+ * Somewhat based on the GTA01 / 02 neo1973_pm_ stuff mainly by Harald Welte
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+
+#include <mach/hardware.h>
+#include <mach/om-gta03.h>
+#include <asm/mach-types.h>
+
+#include <linux/regulator/consumer.h>
+#include <linux/mfd/pcf50633/core.h>
+
+#include <plat/gpio-cfg.h>
+
+struct om_gta03_features_data {
+ int gps_power_was_on;
+ struct regulator *gps_regulator;
+
+ int wlan_bt_power_was_on;
+
+ int gsm_power_was_on;
+
+ int usbhost_power_was_on;
+
+};
+
+static struct om_gta03_features_data om_gta03_features;
+
+/* GPS power */
+
+static void om_gta03_gps_pwron_set(int on)
+{
+ if ((on) && (!om_gta03_features.gps_power_was_on)) {
+ regulator_enable(om_gta03_features.gps_regulator);
+ /* enable LNA */
+ gpio_direction_output(GTA03_GPIO_GPS_LNA_EN, 1);
+ }
+
+ if ((!on) && (om_gta03_features.gps_power_was_on)) {
+ /* disable LNA */
+ gpio_direction_output(GTA03_GPIO_GPS_LNA_EN, 0);
+ regulator_disable(om_gta03_features.gps_regulator);
+ }
+}
+
+static ssize_t om_gta03_gps_power_read(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (regulator_is_enabled(om_gta03_features.gps_regulator))
+ return strlcpy(buf, "1\n", 3);
+ else
+ return strlcpy(buf, "0\n", 3);
+}
+
+static ssize_t om_gta03_gps_power_write(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int on = !!simple_strtoul(buf, NULL, 10);
+
+ om_gta03_gps_pwron_set(on);
+ om_gta03_features.gps_power_was_on = on;
+
+ return count;
+}
+
+static DEVICE_ATTR(gps_power, 0644, om_gta03_gps_power_read,
+ om_gta03_gps_power_write);
+
+/* WLAN / BT power */
+
+static void om_gta03_wlan_bt_pwron_set(int on)
+{
+ if (!on) {
+ /* remove power from WLAN / BT module */
+ gpio_direction_output(GTA03_GPIO_NWLAN_POWER, 1);
+ s3c_gpio_setpull(GTA03_GPIO_NWLAN_POWER, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GTA03_GPIO_NWLAN_POWER, S3C_GPIO_SFN(1));
+
+ return;
+ }
+
+ /* give power to WLAN / BT module */
+ s3c_gpio_setpull(GTA03_GPIO_WLAN_RESET, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GTA03_GPIO_WLAN_RESET, S3C_GPIO_SFN(1));
+ gpio_direction_output(GTA03_GPIO_WLAN_RESET, 0);
+
+ gpio_direction_output(GTA03_GPIO_NWLAN_POWER, 0);
+ s3c_gpio_setpull(GTA03_GPIO_NWLAN_POWER, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GTA03_GPIO_NWLAN_POWER, S3C_GPIO_SFN(1));
+ msleep(1);
+ gpio_direction_output(GTA03_GPIO_WLAN_RESET, 1);
+}
+
+static ssize_t om_gta03_wlan_bt_power_read(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (om_gta03_features.wlan_bt_power_was_on)
+ return strlcpy(buf, "1\n", 3);
+ else
+ return strlcpy(buf, "0\n", 3);
+}
+
+static ssize_t om_gta03_wlan_bt_power_write(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ om_gta03_wlan_bt_pwron_set(simple_strtoul(buf, NULL, 10));
+
+ return count;
+}
+
+static DEVICE_ATTR(wlan_bt_power, 0644, om_gta03_wlan_bt_power_read,
+ om_gta03_wlan_bt_power_write);
+
+
+/* GSM Module on / off */
+
+static void om_gta03_gsm_pwron_set(int on)
+{
+ if (!on) {
+ /* remove power from WLAN / BT module */
+ gpio_direction_output(GTA03_GPIO_MODEN_ON, 0);
+ s3c_gpio_setpull(GTA03_GPIO_MODEN_ON, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GTA03_GPIO_MODEN_ON, S3C_GPIO_SFN(1));
+
+ return;
+ }
+
+ /* give power to GSM module */
+ s3c_gpio_setpull(GTA03_GPIO_N_MODEM_RESET, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GTA03_GPIO_N_MODEM_RESET, S3C_GPIO_SFN(1));
+ gpio_direction_output(GTA03_GPIO_N_MODEM_RESET, 0);
+
+ gpio_direction_output(GTA03_GPIO_MODEN_ON, 1);
+ s3c_gpio_setpull(GTA03_GPIO_MODEN_ON, S3C_GPIO_PULL_NONE);
+ s3c_gpio_cfgpin(GTA03_GPIO_MODEN_ON, S3C_GPIO_SFN(1));
+ msleep(1);
+ gpio_direction_output(GTA03_GPIO_N_MODEM_RESET, 1);
+}
+
+static ssize_t om_gta03_gsm_power_read(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (om_gta03_features.gsm_power_was_on)
+ return strlcpy(buf, "1\n", 3);
+ else
+ return strlcpy(buf, "0\n", 3);
+}
+
+static ssize_t om_gta03_gsm_power_write(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int on = !!simple_strtoul(buf, NULL, 10);
+
+ om_gta03_gsm_pwron_set(on);
+ om_gta03_features.gsm_power_was_on = on;
+
+ return count;
+}
+
+static DEVICE_ATTR(gsm_power, 0644, om_gta03_gsm_power_read,
+ om_gta03_gsm_power_write);
+
+
+/* USB host power on / off */
+
+static void om_gta03_usbhost_pwron_set(int on)
+{
+ pcf50633_gpio_set(om_gta03_pcf_pdata.pcf, PCF50633_GPO, on);
+}
+
+static ssize_t om_gta03_usbhost_power_read(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ if (pcf50633_gpio_get(om_gta03_pcf_pdata.pcf, PCF50633_GPO))
+ return strlcpy(buf, "1\n", 3);
+ else
+ return strlcpy(buf, "0\n", 3);
+}
+
+static ssize_t om_gta03_usbhost_power_write(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ int on = !!simple_strtoul(buf, NULL, 10);
+
+ om_gta03_usbhost_pwron_set(on);
+ om_gta03_features.usbhost_power_was_on = on;
+
+ return count;
+}
+
+static DEVICE_ATTR(usbhost_power, 0644, om_gta03_usbhost_power_read,
+ om_gta03_usbhost_power_write);
+
+
+
+
+static struct attribute *om_gta03_features_sysfs_entries[] = {
+ &dev_attr_gps_power.attr,
+ &dev_attr_wlan_bt_power.attr,
+ &dev_attr_gsm_power.attr,
+ &dev_attr_usbhost_power.attr,
+ NULL
+};
+
+static struct attribute_group om_gta03_features_attr_group = {
+ .name = NULL,
+ .attrs = om_gta03_features_sysfs_entries,
+};
+
+static int __init om_gta03_features_probe(struct platform_device *pdev)
+{
+ om_gta03_features.gps_regulator = regulator_get(&pdev->dev, "RF_3V");
+ dev_info(&pdev->dev, "starting\n");
+
+ om_gta03_features.wlan_bt_power_was_on = 1; /* defaults to on */
+
+ return sysfs_create_group(&pdev->dev.kobj, &om_gta03_features_attr_group);
+}
+
+static int om_gta03_features_remove(struct platform_device *pdev)
+{
+
+ regulator_put(om_gta03_features.gps_regulator);
+ sysfs_remove_group(&pdev->dev.kobj, &om_gta03_features_attr_group);
+
+ return 0;
+}
+
+
+#ifdef CONFIG_PM
+static int om_gta03_features_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ om_gta03_gps_pwron_set(0);
+ om_gta03_wlan_bt_pwron_set(0);
+ om_gta03_usbhost_pwron_set(0);
+
+ return 0;
+}
+
+static int om_gta03_features_resume(struct platform_device *pdev)
+{
+ if (om_gta03_features.gps_power_was_on)
+ om_gta03_gps_pwron_set(1);
+
+ if (om_gta03_features.wlan_bt_power_was_on)
+ om_gta03_wlan_bt_pwron_set(1);
+
+ if (om_gta03_features.usbhost_power_was_on)
+ om_gta03_usbhost_pwron_set(1);
+
+ return 0;
+}
+#else
+#define om_gta03_features_suspend NULL
+#define om_gta03_features_resume NULL
+#endif
+
+static struct platform_driver om_gta03_features_driver = {
+ .probe = om_gta03_features_probe,
+ .remove = om_gta03_features_remove,
+ .suspend = om_gta03_features_suspend,
+ .resume = om_gta03_features_resume,
+ .driver = {
+ .name = "om-gta03",
+ },
+};
+
+static int __devinit om_gta03_features_init(void)
+{
+ return platform_driver_register(&om_gta03_features_driver);
+}
+
+static void om_gta03_features_exit(void)
+{
+ platform_driver_unregister(&om_gta03_features_driver);
+}
+
+module_init(om_gta03_features_init);
+module_exit(om_gta03_features_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Andy Green <andy@openmoko.com>");
+MODULE_DESCRIPTION("Openmoko GTA03 Feature Driver");
diff --git a/arch/arm/plat-s3c24xx/neo1973_pm_gps.c b/arch/arm/plat-s3c24xx/neo1973_pm_gps.c
index 89075693b9f..8f0a6291db4 100644
--- a/arch/arm/plat-s3c24xx/neo1973_pm_gps.c
+++ b/arch/arm/plat-s3c24xx/neo1973_pm_gps.c
@@ -29,6 +29,7 @@
/* For GTA02 */
#include <mach/gta02.h>
+#include <linux/pcf50633.h>
#include <linux/regulator/consumer.h>
@@ -275,6 +276,8 @@ static int gps_power_1v5_get(void)
static void gps_pwron_set(int on)
{
+ neo1973_gps.power_was_on = !!on;
+
if (machine_is_neo1973_gta01())
neo1973_gpb_setpin(GTA01_GPIO_GPS_PWRON, on);
@@ -294,13 +297,12 @@ static void gps_pwron_set(int on)
/* don't let RX from unpowered GPS float */
s3c2410_gpio_pullup(S3C2410_GPH5, 1);
}
- if (on && !neo1973_gps.power_was_on)
+ if ((on) && (!neo1973_gps.power_was_on))
regulator_enable(neo1973_gps.regulator);
- else if (!on && neo1973_gps.power_was_on)
+
+ if ((!on) && (neo1973_gps.power_was_on))
regulator_disable(neo1973_gps.regulator);
}
-
- neo1973_gps.power_was_on = !!on;
}
static int gps_pwron_get(void)