diff options
Diffstat (limited to 'arch')
| -rw-r--r-- | arch/arm/configs/omap3_h1_defconfig | 25 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-omap3h1.c | 263 | 
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..ff4de235e20 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 (10 * 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")  |