summaryrefslogtreecommitdiff
path: root/arch
diff options
context:
space:
mode:
Diffstat (limited to 'arch')
-rw-r--r--arch/arm/configs/omap3_h1_defconfig25
-rw-r--r--arch/arm/mach-omap2/board-omap3h1.c263
2 files changed, 269 insertions, 19 deletions
diff --git a/arch/arm/configs/omap3_h1_defconfig b/arch/arm/configs/omap3_h1_defconfig
index f4eaa295e0e..94035e8bef3 100644
--- a/arch/arm/configs/omap3_h1_defconfig
+++ b/arch/arm/configs/omap3_h1_defconfig
@@ -399,12 +399,12 @@ CONFIG_ARM_ERRATA_430973=y
#
# Kernel Features
#
-# CONFIG_HAVE_ARM_ARCH_TIMER is not set
+CONFIG_HAVE_ARM_ARCH_TIMER=y
CONFIG_VMSPLIT_3G=y
# CONFIG_VMSPLIT_2G is not set
# CONFIG_VMSPLIT_1G is not set
CONFIG_PAGE_OFFSET=0xC0000000
-# CONFIG_ARM_PSCI is not set
+CONFIG_ARM_PSCI=y
CONFIG_ARCH_NR_GPIO=256
# CONFIG_PREEMPT_NONE is not set
# CONFIG_PREEMPT_VOLUNTARY is not set
@@ -493,7 +493,10 @@ CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
# CONFIG_ARM_EXYNOS5440_CPUFREQ is not set
# CONFIG_ARM_KIRKWOOD_CPUFREQ is not set
CONFIG_ARM_OMAP2PLUS_CPUFREQ=y
-# CONFIG_CPU_IDLE is not set
+CONFIG_CPU_IDLE=y
+# CONFIG_CPU_IDLE_MULTIPLE_DRIVERS is not set
+CONFIG_CPU_IDLE_GOV_LADDER=y
+CONFIG_CPU_IDLE_GOV_MENU=y
# CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED is not set
#
@@ -528,10 +531,15 @@ CONFIG_HAS_WAKELOCK=y
CONFIG_WAKELOCK=y
CONFIG_PM_SLEEP=y
CONFIG_PM_AUTOSLEEP=y
-# CONFIG_PM_WAKELOCKS is not set
+CONFIG_PM_WAKELOCKS=y
+CONFIG_PM_WAKELOCKS_LIMIT=100
+CONFIG_PM_WAKELOCKS_GC=y
CONFIG_PM_RUNTIME=y
CONFIG_PM=y
-# CONFIG_PM_DEBUG is not set
+CONFIG_PM_DEBUG=y
+CONFIG_PM_ADVANCED_DEBUG=y
+CONFIG_PM_TEST_SUSPEND=y
+CONFIG_PM_SLEEP_DEBUG=y
# CONFIG_APM_EMULATION is not set
CONFIG_ARCH_HAS_OPP=y
CONFIG_PM_OPP=y
@@ -1841,7 +1849,7 @@ CONFIG_SND_SOC_DMAENGINE_PCM=y
# CONFIG_SND_DESIGNWARE_I2S is not set
CONFIG_SND_OMAP_SOC=y
# CONFIG_SND_OMAP_SOC_C55 is not set
-#CONFIG_SND_OMAP_SOC_OMAP3_H1 is not set
+# CONFIG_SND_OMAP_SOC_OMAP3_H1 is not set
CONFIG_SND_SOC_I2C_AND_SPI=y
# CONFIG_SND_SOC_ALL_CODECS is not set
# CONFIG_SND_SIMPLE_CARD is not set
@@ -2027,6 +2035,7 @@ CONFIG_MUSB_PIO_ONLY=y
# CONFIG_USB_EZUSB_FX2 is not set
# CONFIG_USB_HSIC_USB3503 is not set
CONFIG_USB_PHY=y
+# CONFIG_USB_OTG_WAKELOCK is not set
CONFIG_NOP_USB_XCEIV=y
# CONFIG_OMAP_CONTROL_USB is not set
# CONFIG_OMAP_USB2 is not set
@@ -2386,7 +2395,9 @@ CONFIG_COMMON_CLK=y
#
# Hardware Spinlock drivers
#
+CONFIG_CLKSRC_OF=y
CONFIG_CLKSRC_MMIO=y
+CONFIG_ARM_ARCH_TIMER=y
# CONFIG_MAILBOX is not set
# CONFIG_IOMMU_SUPPORT is not set
@@ -2727,7 +2738,7 @@ CONFIG_TRACING_SUPPORT=y
# CONFIG_FTRACE is not set
# CONFIG_RBTREE_TEST is not set
# CONFIG_INTERVAL_TREE_TEST is not set
-# CONFIG_DYNAMIC_DEBUG is not set
+CONFIG_DYNAMIC_DEBUG=y
# CONFIG_DMA_API_DEBUG is not set
# CONFIG_ATOMIC64_SELFTEST is not set
# CONFIG_SAMPLES is not set
diff --git a/arch/arm/mach-omap2/board-omap3h1.c b/arch/arm/mach-omap2/board-omap3h1.c
index 57672948fdb..ef85cf0722f 100644
--- a/arch/arm/mach-omap2/board-omap3h1.c
+++ b/arch/arm/mach-omap2/board-omap3h1.c
@@ -33,11 +33,16 @@
#include <linux/i2c/atmel_mxt_ts.h>
#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/fixed.h>
#include <linux/mfd/tps65910.h>
+#include <linux/kmod.h> /* for call_usermodehelper - not used, remove? */
+#include <linux/wakelock.h> /* used in interrupt, waking up. */
+#include <linux/debugfs.h>
+
#include <linux/led-lm3530.h>
#include <asm/mach-types.h>
@@ -62,6 +67,7 @@
#define NAND_CS 0
#define MPUIRQ_GPIO 31
+#define ON_OFF_BUTTON_GPIO 30
#define ATMEL_MXT_GPIO 105
#define USB_IRQ 124
#define USB_ON_ETK_D7 21
@@ -72,7 +78,12 @@
#define LCD_RESET_GPIO 122
#endif
-
+static struct accelerometer_wake {
+ int awake;
+ struct wake_lock lock;
+ char lock_name[100];
+ int user_pid;
+} acc_wake;
static struct mtd_partition omap3h1_nand_partitions[] = {
/* All the partition sizes are listed in terms of NAND block size */
@@ -156,12 +167,20 @@ static int __init omap3h1_spi_init(void) {
}
+/*
+ * int_config is interrupt config, INT_ENABLE register. To enable _all_
+ * interrupts, set to 0x59. I think. --mfj
+ *
+ * Level shifter seems to set power rail between two options - 1 means VDD.
+ * (0 means VLogic, which I'm not sure what it is).
+ */
+
static struct mpu_platform_data mpu_data = {
.int_config = 0x00,
- .level_shifter = 0,
- .orientation = { -1, 0, 0,
+ .level_shifter = 1,
+ .orientation = { -1, 0, 0,
0, 1, 0,
- 0, 0, -1 },
+ 0, 0, -1 },
};
static struct lm3530_platform_data omap3h1_backlight_platform_data = {
@@ -197,6 +216,33 @@ static struct platform_device omap3h1_dmic_codec = {
};
/* --------------------------------------------------------------------------- */
+/* Keys / buttons settings
+ */
+
+static struct gpio_keys_button gpio_buttons[] = {
+ {
+ .code = KEY_POWER, /* 26 */
+ .gpio = ON_OFF_BUTTON_GPIO,
+ .desc = "accelerometer",
+ .wakeup = 1,
+ },
+};
+
+static struct gpio_keys_platform_data gpio_key_info = {
+ .buttons = gpio_buttons,
+ .nbuttons = ARRAY_SIZE(gpio_buttons),
+};
+
+static struct platform_device omap3h1_keys = {
+ .name = "gpio-keys",
+ .id = -1,
+ .dev = {
+ .platform_data = &gpio_key_info,
+ },
+};
+
+
+/* --------------------------------------------------------------------------- */
/* USB settings
*/
@@ -515,10 +561,177 @@ static struct i2c_board_info __initdata omap3h1_i2c3_board_info[] = {
},
};
+/* --------------------------------------------------------------------------- */
+/* Create debugfs entry
+ *
+ * We need to have this so that our wake-up thread can tell us it's PID.
+ * That PID will then be used when waking the system up.
+ */
+
+
+struct dentry * pidfile;
+
+#define SIG_OLIO_WAKE 44 // we choose 44 as our signal number (real-time signals are in the range of 33 to 64)
+
+static ssize_t write_pid(struct file *file,
+ const char __user *buf,
+ size_t count,
+ loff_t *ppos)
+{
+ char mybuf[10];
+ int pid = 0;
+
+ /* read the value from user space */
+
+ if(count > 10)
+ return -EINVAL;
+ if (copy_from_user(mybuf, buf, count) != 0) {
+ /* nothing read?? */
+ printk ("OLIO: write_pid: Error??\n");
+ return 0;
+ }
+
+ sscanf(mybuf, "%d", &pid);
+
+ printk("pid read = %d\n", pid);
+
+ acc_wake.user_pid = pid;
+
+ return count;
+}
+
+static ssize_t send_wake_signal (void) {
+ int ret;
+ struct siginfo info;
+ struct task_struct *t;
+
+ /* send the signal */
+
+ printk ("Now sending signal!\n");
+
+ memset(&info, 0, sizeof(struct siginfo));
+
+ /* this is bit of a trickery: SI_QUEUE is normally used by sigqueue from user space,
+ * and kernel space should use SI_KERNEL. But if SI_KERNEL is used the real_time data
+ * is not delivered to the user space signal handler function.
+ */
+
+ info.si_signo = SIG_OLIO_WAKE;
+ info.si_code = SI_QUEUE;
+
+ /* real time signals may have 32 bits of data. */
+
+ info.si_int = 1234;
+
+ rcu_read_lock();
+
+ t = pid_task(find_pid_ns(acc_wake.user_pid, &init_pid_ns), PIDTYPE_PID);
+
+ if(t == NULL){
+ rcu_read_unlock();
+ printk("no such pid\n");
+ return -ENODEV;
+ }
+
+ rcu_read_unlock();
+
+ /* send the signal */
+
+ ret = send_sig_info(SIG_OLIO_WAKE, &info, t);
+
+ if (ret < 0) {
+ printk("error sending signal\n");
+ }
+ return ret;
+}
+
+static const struct file_operations h1_fops = {
+ .write = write_pid,
+};
+
+
+
+/***************************************************************************
+ * acc_irq_handler - handle interrupt from accelerometer
+ *
+ * This routine gets called when an interrupt from the accelerometer
+ * happens. Time out is in milliseconds.
+ *
+ * TODO: BREAK this all out, place it in it's own kernel driver together
+ * with the configuration stuff for the accelerometer (the low power sleep
+ * mode stuff).
+ */
+
+#define OLIO_DOUBLE_TAP 800
+#define OLIO_ONE_SECOND 1000
+
+static unsigned long previous;
+
+static irqreturn_t acc_irq_handler_thr(int irq, void * omap3h1_d) {
+ /* struct platform_device** omap3h1_devs = (struct platform_device **) omap3h1_d; */
+
+ int ret = 99;
+ unsigned long now;
+
+ printk (KERN_DEBUG "acc_irq_handler_thr: Entered!\n");
+
+ now = jiffies;
+
+ if (jiffies_to_msecs(now - previous) < OLIO_DOUBLE_TAP) {
+ printk (KERN_DEBUG "Double tap detected!\n");
+ /* We want to wake up. Take wake lock (and send signal to user space?)
+ * BT driver only takes wake lock, then lets higher levels handle
+ * everything ... but what if there's nothing there to take the lock?
+ */
+
+ send_wake_signal();
+ wake_lock_timeout (&acc_wake.lock, msecs_to_jiffies (2 * OLIO_ONE_SECOND));
+
+ previous = 0;
+ } else {
+ previous = now;
+ }
+
+ printk (KERN_DEBUG "acc_irq_handler_thr: Leaving! (ret = %d)\n", ret);
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t acc_irq_handler(int irq, void * omap3h1_d) {
+ printk (KERN_DEBUG "acc_irq_handler: Entered!\n");
+
+ /* nothing to do, other than wake the main thread */
+
+ printk (KERN_DEBUG "acc_irq_handler: Leaving!\n");
+ return IRQ_WAKE_THREAD;
+}
+
+static int __init omap3_acc_irq_init (int irq, void * dev_id) {
+ irq_set_irq_wake(irq, 1);
+
+ if (request_threaded_irq (irq, acc_irq_handler,
+ acc_irq_handler_thr, 0x81, "acc_wake",
+ dev_id)) {
+ printk (KERN_DEBUG "Couldn't register handler for accelerometer IRQ\n");
+ }
+
+ /* Should check the return value ... but if it fails, what do we do? */
+
+ return 0;
+}
+
+
+
+/***************************************************************************
+ * omap3_h1_i2c_init - init the i2c buses
+ *
+ */
static int __init omap3_h1_i2c_init(void)
{
- /* Ugly hack: In Linux 3.10 we need to request an IRQ through
+ int acc_irq;
+
+ /* In Linux 3.10 we need to request an IRQ through
* gpio_to_irq. This means it can't be set at compile time, and
* must be done at runtime. In other words, here.
*/
@@ -526,15 +739,20 @@ static int __init omap3_h1_i2c_init(void)
gpio_request_one(ATMEL_MXT_GPIO, GPIOF_IN, "atmel_mxt_ts CHG");
gpio_request_one(MPUIRQ_GPIO, GPIOF_IN, "mpu6515 IRQ pin");
+ gpio_request_one(ON_OFF_BUTTON_GPIO, GPIOF_OUT_INIT_LOW, "on-off button");
+
+ acc_irq = gpio_to_irq(MPUIRQ_GPIO);
+
#ifdef CONFIG_MACH_OMAP3_H1_DVT2
omap3h1_i2c2_board_info[2].irq = gpio_to_irq(ATMEL_MXT_GPIO);
- omap3h1_i2c2_board_info[0].irq = gpio_to_irq(MPUIRQ_GPIO);
+ omap3h1_i2c2_board_info[0].irq = acc_irq;
#else
omap3h1_i2c1_board_info[3].irq = gpio_to_irq(ATMEL_MXT_GPIO);
- omap3h1_i2c1_board_info[1].irq = gpio_to_irq(MPUIRQ_GPIO);
+ omap3h1_i2c1_board_info[1].irq = acc_irq;
#endif
- gpio_request_one(USB_ON_ETK_D7, GPIOF_OUT_INIT_HIGH, "USB on");
+ gpio_request_one(USB_ON_ETK_D7, GPIOF_OUT_INIT_HIGH, "USB on");
+
/* Register buses */
omap_register_i2c_bus(1, 400, omap3h1_i2c1_board_info, ARRAY_SIZE(omap3h1_i2c1_board_info));
@@ -556,6 +774,7 @@ static struct platform_device *omap3h1_devices[] __initdata = {
&bcm20702_bluetooth_device,
&nop_phy_device,
&omap3h1_dmic_codec,
+ &omap3h1_keys,
};
#ifdef CONFIG_OMAP_MUX
@@ -615,8 +834,9 @@ static struct omap_board_mux board_mux[] __initdata = {
#endif /* CONFIG_MACH_OMAP3_H1_DVT */
/* accelerometer */
-
- OMAP3_MUX(JTAG_EMU1, (OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT)),
+
+ OMAP3_MUX(JTAG_EMU1, (OMAP_MUX_MODE4 | OMAP_PIN_INPUT
+ | OMAP_PIN_OFF_WAKEUPENABLE)),
/* USB on */
@@ -626,6 +846,18 @@ static struct omap_board_mux board_mux[] __initdata = {
};
#endif
+static int __init omap3_wake_init (void) {
+ pidfile = debugfs_create_file("wake_signal_pid", 0200, NULL, NULL, &h1_fops);
+ acc_wake.user_pid = 0; /* No user thread yet */
+
+ snprintf(acc_wake.lock_name, sizeof(acc_wake.lock_name),
+ "Accelerometer");
+ wake_lock_init(&acc_wake.lock, WAKE_LOCK_SUSPEND,
+ acc_wake.lock_name);
+ return 0;
+}
+
+
static void __init omap3_h1_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
@@ -646,9 +878,16 @@ static void __init omap3_h1_init(void)
usb_bind_phy("musb-hdrc.0.auto", 0, "nop_usb_xceiv"); /* "tusb-usb-h1" */
usb_musb_init(&musb_board_data);
- /* usbhs_init(&usbhs_bdata); */ /* We don't need this */
- /* h1_opp_init(); */
+ /* For handling interrupts from the accelerometer */
+
+ previous = jiffies;
+
+ /* Init the code that handles wake ups */
+
+ omap3_wake_init();
+
+ omap3_acc_irq_init(omap3h1_i2c2_board_info[0].irq, (void *) &omap3h1_devices);
}
MACHINE_START(OMAP3_H1, "Olio OMAP3 H1 Board")