summaryrefslogtreecommitdiff
path: root/arch/arm/mach-omap2
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mach-omap2')
-rw-r--r--arch/arm/mach-omap2/Kconfig28
-rw-r--r--arch/arm/mach-omap2/Makefile2
-rw-r--r--arch/arm/mach-omap2/board-flash.c2
-rw-r--r--arch/arm/mach-omap2/board-omap3h1-bluetooth.c387
-rw-r--r--arch/arm/mach-omap2/board-omap3h1.c1267
-rw-r--r--arch/arm/mach-omap2/board-omap3h1.h30
-rw-r--r--arch/arm/mach-omap2/devices.c4
-rw-r--r--arch/arm/mach-omap2/fb.c5
-rw-r--r--arch/arm/mach-omap2/gpmc-nand.c4
-rw-r--r--arch/arm/mach-omap2/gpmc.c130
-rw-r--r--arch/arm/mach-omap2/omap_hwmod_3xxx_data.c4
-rw-r--r--arch/arm/mach-omap2/opp.c2
-rw-r--r--arch/arm/mach-omap2/opp3xxx_data.c4
-rw-r--r--arch/arm/mach-omap2/pm-debug-regs.h2
-rw-r--r--arch/arm/mach-omap2/pm.c2
-rw-r--r--arch/arm/mach-omap2/pmu.c5
-rw-r--r--arch/arm/mach-omap2/sdram-micron-mt29c4g48.h63
17 files changed, 1896 insertions, 45 deletions
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index 0168b07ce0c..c3fdbc0f08a 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -207,6 +207,34 @@ config MACH_OMAP3_BEAGLE
depends on ARCH_OMAP3
default y
select OMAP_PACKAGE_CBB
+
+config MACH_OMAP3_H1
+ bool "OMAP3 H1 board"
+ depends on ARCH_OMAP3
+ default y
+ select OMAP_PACKAGE_CBP
+
+choice
+ prompt "Olio H1B build version"
+ default MACH_OMAP3_H1_EVT2
+
+config MACH_OMAP3_H1_EVT1
+ bool "EVT1 Build of the H1 board"
+ depends on MACH_OMAP3_H1
+
+config MACH_OMAP3_H1_EVT2
+ bool "EVT2 Build of the H1 board"
+ depends on MACH_OMAP3_H1
+
+config MACH_OMAP3_H1_DVT1
+ bool "DVT1 Build of the H1 board"
+ depends on MACH_OMAP3_H1
+
+config MACH_OMAP3_H1_DVT2
+ bool "DVT2 Build of the H1 board"
+ depends on MACH_OMAP3_H1
+
+endchoice
config MACH_DEVKIT8000
bool "DEVKIT8000 board"
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
index ff5c4457325..9245b2356df 100644
--- a/arch/arm/mach-omap2/Makefile
+++ b/arch/arm/mach-omap2/Makefile
@@ -225,6 +225,8 @@ obj-$(CONFIG_MACH_OMAP_GENERIC) += board-generic.o
obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o
obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o
obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o
+obj-$(CONFIG_MACH_OMAP3_H1) += board-omap3h1.o
+obj-$(CONFIG_MACH_OMAP3_H1) += board-omap3h1-bluetooth.o
obj-$(CONFIG_MACH_DEVKIT8000) += board-devkit8000.o
obj-$(CONFIG_MACH_OMAP_LDP) += board-ldp.o
obj-$(CONFIG_MACH_OMAP3530_LV_SOM) += board-omap3logic.o
diff --git a/arch/arm/mach-omap2/board-flash.c b/arch/arm/mach-omap2/board-flash.c
index c33adea0247..bb25fff9ee6 100644
--- a/arch/arm/mach-omap2/board-flash.c
+++ b/arch/arm/mach-omap2/board-flash.c
@@ -139,7 +139,7 @@ __init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs,
board_nand_data.nr_parts = nr_parts;
board_nand_data.devsize = nand_type;
- board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT;
+ board_nand_data.ecc_opt = OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
gpmc_nand_init(&board_nand_data, gpmc_t);
}
#endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
diff --git a/arch/arm/mach-omap2/board-omap3h1-bluetooth.c b/arch/arm/mach-omap2/board-omap3h1-bluetooth.c
new file mode 100644
index 00000000000..52bf419b549
--- /dev/null
+++ b/arch/arm/mach-omap2/board-omap3h1-bluetooth.c
@@ -0,0 +1,387 @@
+/*
+ * Bluetooth Broadcomm and low power control via GPIO
+ *
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+ /*
+ * Adapted from board-tuna-bluetooth.c by Evan Wilson <evan@oliodevices.com
+ *
+ */
+
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+#include <linux/hrtimer.h>
+#include <linux/irq.h>
+#include <linux/rfkill.h>
+#include <linux/platform_device.h>
+#include <linux/wakelock.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <asm/mach-types.h>
+#include "serial.h"
+#include "board-omap3h1.h"
+#include <linux/regulator/driver.h>
+
+static void update_host_wake_locked(int);
+
+#define BT_REG_GPIO 180
+
+#define BT_WAKE_GPIO 93
+#define BT_HOST_WAKE_GPIO 11
+
+static struct rfkill *bt_rfkill;
+static struct regulator *clk32ksys_reg;
+static bool bt_enabled;
+static bool host_wake_uart_enabled;
+static bool wake_uart_enabled;
+static struct dentry *btdebugdent;
+
+struct bcm_bt_lpm {
+ int wake;
+ int host_wake;
+
+ struct hrtimer enter_lpm_timer;
+ ktime_t enter_lpm_delay;
+
+ struct uart_port *uport;
+
+ struct wake_lock wake_lock;
+ char wake_lock_name[100];
+} bt_lpm;
+
+static int bcm20702_bt_rfkill_set_power(void *data, bool blocked)
+{
+ // rfkill_ops callback. Turn transmitter on when blocked is false
+ if (!blocked) {
+ if (clk32ksys_reg && !bt_enabled)
+ regulator_enable(clk32ksys_reg);
+
+ gpio_set_value(BT_REG_GPIO, 1);
+
+ } else {
+ // Chip won't toggle host_wake after reset. Make sure
+ // we don't hold the wake_lock until chip wakes up again.
+ update_host_wake_locked(0);
+
+ gpio_set_value(BT_REG_GPIO, 0);
+ if (clk32ksys_reg && bt_enabled)
+ regulator_disable(clk32ksys_reg);
+ }
+
+ bt_enabled = !blocked;
+
+ return 0;
+}
+
+static const struct rfkill_ops bcm20702_bt_rfkill_ops = {
+ .set_block = bcm20702_bt_rfkill_set_power,
+};
+
+static void set_wake_locked(int wake)
+{
+ bt_lpm.wake = wake;
+
+ if (!wake)
+ wake_unlock(&bt_lpm.wake_lock);
+
+ if (!wake_uart_enabled && wake)
+ //omap_uart_enable(2);
+
+ gpio_set_value(BT_WAKE_GPIO, wake);
+
+ if (wake_uart_enabled && !wake)
+ //omap_uart_disable(2);
+
+ wake_uart_enabled = wake;
+}
+
+static enum hrtimer_restart enter_lpm(struct hrtimer *timer) {
+ unsigned long flags;
+ spin_lock_irqsave(&bt_lpm.uport->lock, flags);
+ set_wake_locked(0);
+ spin_unlock_irqrestore(&bt_lpm.uport->lock, flags);
+
+ return HRTIMER_NORESTART;
+}
+
+void bcm_bt_lpm_exit_lpm_locked(struct uart_port *uport) {
+ bt_lpm.uport = uport;
+
+ hrtimer_try_to_cancel(&bt_lpm.enter_lpm_timer);
+
+ set_wake_locked(1);
+
+ hrtimer_start(&bt_lpm.enter_lpm_timer, bt_lpm.enter_lpm_delay,
+ HRTIMER_MODE_REL);
+}
+EXPORT_SYMBOL(bcm_bt_lpm_exit_lpm_locked);
+
+static void update_host_wake_locked(int host_wake)
+{
+ if (host_wake == bt_lpm.host_wake)
+ return;
+
+ bt_lpm.host_wake = host_wake;
+
+ if (host_wake) {
+ wake_lock(&bt_lpm.wake_lock);
+ if (!host_wake_uart_enabled) {
+ //omap_uart_enable(2);
+ }
+ } else {
+ if (host_wake_uart_enabled) {
+ //omap_uart_disable(2);
+ }
+ // Take a timed wakelock, so that upper layers can take it.
+ // The chipset deasserts the hostwake lock, when there is no
+ // more data to send.
+ wake_lock_timeout(&bt_lpm.wake_lock, HZ/2);
+ }
+
+ host_wake_uart_enabled = host_wake;
+
+}
+
+static irqreturn_t host_wake_isr(int irq, void *dev)
+{
+ int host_wake;
+ unsigned long flags;
+
+ host_wake = gpio_get_value(BT_HOST_WAKE_GPIO);
+ irq_set_irq_type(irq, host_wake ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH);
+
+ if (!bt_lpm.uport) {
+ bt_lpm.host_wake = host_wake;
+ return IRQ_HANDLED;
+ }
+
+ spin_lock_irqsave(&bt_lpm.uport->lock, flags);
+ update_host_wake_locked(host_wake);
+ spin_unlock_irqrestore(&bt_lpm.uport->lock, flags);
+
+ return IRQ_HANDLED;
+}
+
+static int bcm_bt_lpm_init(struct platform_device *pdev)
+{
+ int irq;
+ int ret;
+ int rc;
+
+ rc = gpio_request(BT_WAKE_GPIO, "bcm20702_wake_gpio");
+ if (unlikely(rc)) {
+ return rc;
+ }
+
+ rc = gpio_request(BT_HOST_WAKE_GPIO, "bcm20702_host_wake_gpio");
+ if (unlikely(rc)) {
+ gpio_free(BT_WAKE_GPIO);
+ return rc;
+ }
+
+ hrtimer_init(&bt_lpm.enter_lpm_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+ bt_lpm.enter_lpm_delay = ktime_set(1, 0); /* 1 sec */
+ bt_lpm.enter_lpm_timer.function = enter_lpm;
+
+ bt_lpm.host_wake = 0;
+
+ irq = gpio_to_irq(BT_HOST_WAKE_GPIO);
+ ret = request_irq(irq, host_wake_isr, IRQF_TRIGGER_HIGH,
+ "bt host_wake", NULL);
+ if (ret) {
+ gpio_free(BT_WAKE_GPIO);
+ gpio_free(BT_HOST_WAKE_GPIO);
+ return ret;
+ }
+
+ ret = irq_set_irq_wake(irq, 1);
+ if (ret) {
+ gpio_free(BT_WAKE_GPIO);
+ gpio_free(BT_HOST_WAKE_GPIO);
+ return ret;
+ }
+
+ gpio_direction_output(BT_WAKE_GPIO, 0);
+ gpio_direction_input(BT_HOST_WAKE_GPIO);
+
+ snprintf(bt_lpm.wake_lock_name, sizeof(bt_lpm.wake_lock_name),
+ "BTLowPower");
+ wake_lock_init(&bt_lpm.wake_lock, WAKE_LOCK_SUSPEND,
+ bt_lpm.wake_lock_name);
+ return 0;
+}
+
+static int btdebug_dump(struct seq_file *sf, void *private)
+{
+ seq_printf(sf, "en=%d bt_wake=%d lpm.w=%d w_uart_en=%d\n",
+ bt_enabled, gpio_get_value(BT_WAKE_GPIO),
+ bt_lpm.wake, wake_uart_enabled);
+ seq_printf(sf, "bt_host_wake=%d lpm.hw=%d hw_uart_en=%d\n",
+ gpio_get_value(BT_HOST_WAKE_GPIO), bt_lpm.host_wake,
+ host_wake_uart_enabled);
+ return 0;
+}
+
+static int btdebug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, btdebug_dump, NULL);
+}
+
+static const struct file_operations btdebug_fops = {
+ .open = btdebug_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static int bcm20702_bluetooth_probe(struct platform_device *pdev)
+{
+ int rc = 0;
+ int ret = 0;
+
+// rc = gpio_request(BT_RESET_GPIO, "bcm20702_nreset_gpip");
+// if (unlikely(rc)) {
+// return rc;
+// }
+
+ rc = gpio_request(BT_REG_GPIO, "bcm20702_nshutdown_gpio");
+ if (unlikely(rc)) {
+ //gpio_free(BT_RESET_GPIO);
+ return rc;
+ }
+
+ clk32ksys_reg = regulator_get(0, "clk32ksys");
+ if (IS_ERR(clk32ksys_reg)) {
+ pr_err("clk32ksys reg not found!\n");
+ clk32ksys_reg = NULL;
+ }
+
+ gpio_direction_output(BT_REG_GPIO, 1);
+ //gpio_direction_output(BT_RESET_GPIO, 1);
+
+ bt_rfkill = rfkill_alloc("bcm20702 Bluetooth", &pdev->dev,
+ RFKILL_TYPE_BLUETOOTH, &bcm20702_bt_rfkill_ops,
+ NULL);
+
+ if (unlikely(!bt_rfkill)) {
+ //gpio_free(BT_RESET_GPIO);
+ gpio_free(BT_REG_GPIO);
+ return -ENOMEM;
+ }
+
+ rfkill_set_states(bt_rfkill, true, false);
+ rc = rfkill_register(bt_rfkill);
+
+ if (unlikely(rc)) {
+ rfkill_destroy(bt_rfkill);
+ //gpio_free(BT_RESET_GPIO);
+ gpio_free(BT_REG_GPIO);
+ return -1;
+ }
+
+ ret = bcm_bt_lpm_init(pdev);
+ if (ret) {
+ rfkill_unregister(bt_rfkill);
+ rfkill_destroy(bt_rfkill);
+
+ //gpio_free(BT_RESET_GPIO);
+ gpio_free(BT_REG_GPIO);
+ }
+
+ btdebugdent = debugfs_create_file("bt", S_IRUGO, NULL, NULL,
+ &btdebug_fops);
+ if (IS_ERR_OR_NULL(btdebugdent))
+ pr_err("%s: failed to create debugfs file\n", __func__);
+
+ return ret;
+}
+
+static int bcm20702_bluetooth_remove(struct platform_device *pdev)
+{
+ rfkill_unregister(bt_rfkill);
+ rfkill_destroy(bt_rfkill);
+
+ if (!IS_ERR_OR_NULL(btdebugdent))
+ debugfs_remove(btdebugdent);
+
+ gpio_free(BT_REG_GPIO);
+ //gpio_free(BT_RESET_GPIO);
+ gpio_free(BT_WAKE_GPIO);
+ gpio_free(BT_HOST_WAKE_GPIO);
+ regulator_put(clk32ksys_reg);
+
+ wake_lock_destroy(&bt_lpm.wake_lock);
+ return 0;
+}
+
+int bcm4430_bluetooth_suspend(struct platform_device *pdev, pm_message_t state)
+{
+ int irq = gpio_to_irq(BT_HOST_WAKE_GPIO);
+ int host_wake;
+
+ disable_irq(irq);
+ host_wake = gpio_get_value(BT_HOST_WAKE_GPIO);
+
+ if (host_wake) {
+ enable_irq(irq);
+ return -EBUSY;
+ }
+
+ return 0;
+}
+
+int bcm4430_bluetooth_resume(struct platform_device *pdev)
+{
+ int irq = gpio_to_irq(BT_HOST_WAKE_GPIO);
+ enable_irq(irq);
+ return 0;
+}
+
+static struct platform_driver bcm20702_bluetooth_platform_driver = {
+ .probe = bcm20702_bluetooth_probe,
+ .remove = bcm20702_bluetooth_remove,
+ .suspend = bcm4430_bluetooth_suspend,
+ .resume = bcm4430_bluetooth_resume,
+ .driver = {
+ .name = "bcm20702_bluetooth",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init bcm20702_bluetooth_init(void)
+{
+ bt_enabled = false;
+ return platform_driver_register(&bcm20702_bluetooth_platform_driver);
+}
+
+static void __exit bcm20702_bluetooth_exit(void)
+{
+ platform_driver_unregister(&bcm20702_bluetooth_platform_driver);
+}
+
+
+module_init(bcm20702_bluetooth_init);
+module_exit(bcm20702_bluetooth_exit);
+
+MODULE_ALIAS("platform:bcm20702");
+MODULE_DESCRIPTION("bcm20702_bluetooth");
+MODULE_AUTHOR("Jaikumar Ganesh <jaikumar@google.com>");
+MODULE_LICENSE("GPL");
diff --git a/arch/arm/mach-omap2/board-omap3h1.c b/arch/arm/mach-omap2/board-omap3h1.c
new file mode 100644
index 00000000000..61c01c90a8f
--- /dev/null
+++ b/arch/arm/mach-omap2/board-omap3h1.c
@@ -0,0 +1,1267 @@
+/*
+ * Copyright (C) 2014 Olio Devices, Inc.
+ * Authors: Evan Wilson <evan@oliodevices.com>
+ * Mattis Fjallstrom <mattis@oliodevices.com>
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ *
+ * Modified from the original mach-omap/omap2/board-generic.c did by Paul
+ * to support the OMAP2+ device tree boards with an unique board file.
+ *
+ * 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/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/opp.h>
+#include <linux/cpu.h>
+#include <linux/mpu.h>
+#include <linux/spi/spi.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/nand.h>
+
+#include <linux/usb/musb.h>
+#include <linux/usb/phy.h>
+#include <linux/usb/nop-usb-xceiv.h>
+
+#include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/gpio.h>
+
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mfd/tps65910.h>
+
+#include <linux/wakelock.h> /* used in interrupt, waking up. */
+#include <linux/debugfs.h>
+
+#include <linux/led-lm3530.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/mach/flash.h>
+
+#include <video/omapdss.h>
+#include <video/omap-panel-data.h>
+#include <linux/platform_data/mtd-nand-omap2.h>
+#include <linux/platform_data/serial-omap.h>
+#include <linux/interrupt.h>
+
+#include <linux/of_irq.h>
+#include <linux/of_platform.h>
+
+
+#include "common.h"
+#include "omap_device.h"
+#include "gpmc.h"
+#include "soc.h"
+#include "mux.h"
+#include "pm.h"
+#include "board-flash.h"
+#include "common-board-devices.h"
+#include "board-omap3h1.h"
+
+#include "sdram-micron-mt29c4g48.h"
+
+#define NAND_CS 0
+
+#define MPUIRQ_GPIO 31
+#define ATMEL_MXT_GPIO 105
+#define TPS_SYS_NIRQ 0
+#define USB_IRQ 124
+#define USB_ON_ETK_D7 21
+
+#define DEFAULT_RXDMA_POLLRATE 1 /* RX DMA polling rate (us) */
+#define DEFAULT_RXDMA_BUFSIZE 4096 /* RX DMA buffer size */
+#define DEFAULT_RXDMA_TIMEOUT (3 * HZ)/* RX DMA timeout (jiffies) */
+
+#if defined(CONFIG_MACH_OMAP3_H1_DVT1) || defined(CONFIG_MACH_OMAP3_H1_DVT2)
+#define LCD_RESET_GPIO 94
+#else
+#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 */
+ {
+ .name = "X-Loader",
+ .offset = 0,
+ .size = 4 * NAND_BLOCK_SIZE,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "U-Boot",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x80000 */
+ .size = 15 * NAND_BLOCK_SIZE,
+ .mask_flags = MTD_WRITEABLE, /* force read-only */
+ },
+ {
+ .name = "U-Boot Env",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x260000 */
+ .size = 1 * NAND_BLOCK_SIZE,
+ },
+ {
+ .name = "kernel",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x280000 */
+ .size = 40 * NAND_BLOCK_SIZE,
+ },
+ {
+ .name = "initramfs",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0xC80000 */
+ .size = 80 * NAND_BLOCK_SIZE,
+ },
+ {
+ .name = "ramdisk",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1180000 */
+ .size = 40 * NAND_BLOCK_SIZE,
+ },
+ {
+ .name = "system",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x1680000 */
+ .size = 2000 * NAND_BLOCK_SIZE,
+ },
+ {
+ .name = "userdata",
+ .offset = MTDPART_OFS_APPEND, /* Offset = 0x11180000 */
+ .size = MTDPART_SIZ_FULL,
+ },
+};
+
+static struct omap_dss_device omap3h1_lcd_device = {
+ .type = OMAP_DISPLAY_TYPE_DPI,
+ .name = "olio_h1_panel",
+ .driver_name = "ili9342_panel",
+ .phy.dpi.data_lines = 18,
+ .reset_gpio = LCD_RESET_GPIO,
+};
+
+static struct omap_dss_device *omap3h1_dss_devices[] = {
+ &omap3h1_lcd_device,
+};
+
+static struct omap_dss_board_info omap3h1_dss_data = {
+ .num_devices = 1,
+ .devices = omap3h1_dss_devices,
+ .default_device = &omap3h1_lcd_device,
+};
+
+static struct spi_board_info omap3h1_spi_board_info[] __initdata = {
+ {
+ .modalias = "ili9342-spi",
+ .bus_num = 1,
+ .chip_select = 1,
+ .max_speed_hz = 375000,
+ .platform_data = &omap3h1_lcd_device,
+ .mode = SPI_MODE_0,
+ }
+};
+
+static int __init omap3h1_spi_init(void) {
+ spi_register_board_info(omap3h1_spi_board_info,
+ ARRAY_SIZE(omap3h1_spi_board_info));
+ return 0;
+}
+
+
+/*
+ * 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 = 1,
+ .orientation = { 0, -1, 0,
+ -1, 0, 0,
+ 0, 0, 1 },
+};
+
+static struct lm3530_platform_data omap3h1_backlight_platform_data = {
+ .mode = LM3530_BL_MODE_MANUAL,
+ //.als_input_mode = LM3530_INPUT_ALS1,
+ .max_current = LM3530_FS_CURR_29mA,
+ //.pwm_pol_hi = true,
+ //.als_avrg_time = LM3530_ALS_AVRG_TIME_512ms,
+ .brt_ramp_law = 0,
+ .brt_ramp_fall = LM3530_RAMP_TIME_1s, /* LM3530_RAMP_TIME_1s, */
+ .brt_ramp_rise = LM3530_RAMP_TIME_1s, /* LM3530_RAMP_TIME_1s, */
+ //.als1_resistor_sel = LM3530_ALS_IMPD_13_53kOhm,
+ //.als2_resistor_sel = LM3530_ALS_IMPD_Z,
+ //.als_vmin = 730, /* mV */
+ //.als_vmax = 10a20, /* mV */
+ .brt_val = 0x64, /* initial brightness */
+};
+
+
+
+static struct mxt_platform_data mxt_data = {
+ .irqflags = IRQF_TRIGGER_FALLING,
+};
+
+/*
+static struct platform_device bcm20702_bluetooth_device = {
+ .name = "bcm20702_bluetooth",
+ .id = -1,
+ };
+*/
+
+static struct platform_device omap3h1_dmic_codec = {
+ .name = "dmic-codec",
+ .id = -1,
+};
+
+/* --------------------------------------------------------------------------- */
+/* USB settings
+ */
+
+
+
+static struct omap_musb_board_data musb_board_data = {
+ .interface_type = MUSB_INTERFACE_ULPI,
+ .mode = MUSB_OTG,
+ .power = 100,
+};
+
+static struct nop_usb_xceiv_platform_data nop_plat_data = {
+ .type = USB_PHY_TYPE_USB2,
+ .clk_rate = 60000000, /* 60 MHz */
+ .needs_vcc = 1,
+ .needs_reset = 0,
+};
+
+static struct platform_device nop_phy_device = {
+ .name = "nop_usb_xceiv",
+ .id = -1,
+ .dev = {
+ .platform_data = &nop_plat_data,
+ },
+};
+
+
+/* static struct usbhs_omap_platform_data usbhs_bdata __initdata = { */
+/* .port_mode[0] = OMAP_EHCI_PORT_MODE_PHY, */
+/* }; */
+
+
+/* --------------------------------------------------------------------------- */
+/* REGULATOR - Fixed first
+ */
+
+static struct regulator_init_data omap3h1_vbat_data = {
+ .constraints.always_on = true,
+ .constraints.valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .constraints.valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
+};
+
+static struct fixed_voltage_config omap3h1_vbat_pdata = {
+ .supply_name = "VBAT",
+ .microvolts = 3800000,
+ .init_data = &omap3h1_vbat_data,
+ .gpio = -EINVAL,
+};
+
+static struct platform_device omap3h1_vbat = {
+ .name = "reg-fixed-voltage",
+ .id = -1,
+ .dev = {
+ .platform_data = &omap3h1_vbat_pdata,
+ },
+};
+
+
+/* --------------------------------------------------------------------------- */
+
+static struct regulator_init_data tps65910_dummy = {
+ .supply_regulator = "VBAT",
+ .constraints.always_on = false,
+ .constraints.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+};
+
+/* --------------------------------------------------------------------------- */
+/* This one is required for the display to work.
+ */
+
+static struct regulator_consumer_supply tps65910_touch3_supply[] = {
+ REGULATOR_SUPPLY("avdd", "2-004a"),
+ REGULATOR_SUPPLY("vdd", "spi1.1"),
+};
+
+static struct regulator_init_data tps65910_touch3 = {
+ .supply_regulator = "VBAT",
+ .constraints = {
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE,
+ .always_on = false,
+ .apply_uV = true,
+
+ .state_mem = {
+ .uV = 0,
+ .mode = REGULATOR_MODE_STANDBY,
+ .disabled = 1,
+ },
+ .state_disk = {
+ .uV = 0,
+ .mode = REGULATOR_MODE_STANDBY,
+ .disabled = 1,
+ },
+ .state_standby = {
+ .uV = 0,
+ .mode = REGULATOR_MODE_STANDBY,
+ .disabled = 1,
+ },
+ },
+
+ .num_consumer_supplies = ARRAY_SIZE(tps65910_touch3_supply),
+ .consumer_supplies = tps65910_touch3_supply,
+};
+
+/* --------------------------------------------------------------------------- */
+/* This regulator is for the vibrator. We currently lack a way of enabling /
+ * disabling this since we lack a driver for the vibrator (we're just accessing
+ * it's registers through the i2c bus).
+ *
+ * Hence, it's always on.
+ */
+
+static struct regulator_consumer_supply tps65910_vibrator_supply[] = {
+ REGULATOR_SUPPLY("vaux2", "drv2605"),
+};
+
+static struct regulator_init_data tps65910_vibrator = {
+ .supply_regulator = "VBAT",
+ .constraints = {
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE,
+ .always_on = false,
+ .apply_uV = true,
+
+ .state_mem = {
+ .disabled = 1,
+ },
+ .state_disk = {
+ .disabled = 1,
+ },
+ .state_standby = {
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(tps65910_vibrator_supply),
+ .consumer_supplies = tps65910_vibrator_supply,
+};
+
+
+
+/* --------------------------------------------------------------------------- */
+/* Seems like this one has to be on. It doesn't have any "official" consumers
+ * ... but it's definitely needed. Bluetooth relies on it.
+ */
+
+/*
+static struct regulator_consumer_supply tps65910_bluetooth_3v3[] = {
+ REGULATOR_SUPPLY("clk32ksys", 0),
+};
+*/
+
+static struct regulator_init_data tps65910_3v3 = {
+ .supply_regulator = "VBAT",
+ .constraints = {
+ .min_uV = 3300000,
+ .max_uV = 3300000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE |
+ REGULATOR_CHANGE_STATUS,
+ .always_on = false,
+ .apply_uV = true,
+
+ .state_mem = {
+ .disabled = 1,
+ },
+ .state_disk = {
+ .disabled = 1,
+ },
+ .state_standby = {
+ .disabled = 1,
+ },
+ },
+
+};
+
+
+/* --------------------------------------------------------------------------- */
+/* This is the OMAP display subsystem. Part of the OMAP processor OCP stuff.
+ * USB also depends on this, so if you want to transfer files it has to be
+ * always on.
+ * NAND flash and UART3 (which we don't use) requires it
+ * as well. And the i2c bus, and lots of other stuff.
+ *
+ * Setting always_on to "false" resulted in almost no power savings, at
+ * least in the current setting.
+ */
+
+static struct regulator_consumer_supply tps65910_1v8_supply[] = {
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+};
+
+static struct regulator_init_data tps65910_1v8 = {
+ .supply_regulator = "VBAT",
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE,
+ .always_on = false,
+ .apply_uV = true,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(tps65910_1v8_supply),
+ .consumer_supplies = tps65910_1v8_supply,
+};
+
+/* --------------------------------------------------------------------------- */
+/* There's no driver explicitly using this one, but it goes to VDDA_DPLL_PER
+ * on the OMAP chip. So it's used internally by the DPLL devices in PER, I think.
+ */
+
+static struct regulator_consumer_supply tps65910_vpll_supply[] = {
+
+};
+
+static struct regulator_init_data tps65910_vpll = {
+ .supply_regulator = "VBAT",
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
+ .always_on = true,
+ .apply_uV = true,
+ },
+ .num_consumer_supplies = ARRAY_SIZE(tps65910_vpll_supply),
+ .consumer_supplies = tps65910_vpll_supply,
+};
+
+
+/* --------------------------------------------------------------------------- */
+/* Touch power supply part 2.
+ */
+
+static struct regulator_consumer_supply tps65910_touch_supply[] = {
+ REGULATOR_SUPPLY("vdd", "2-004a" ),
+};
+
+static struct regulator_init_data tps65910_touch = {
+ .supply_regulator = "VBAT",
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
+ .always_on = false,
+ .apply_uV = true,
+
+ .state_mem = {
+ .uV = 1,
+ .mode = REGULATOR_MODE_STANDBY,
+ .disabled = 1,
+ },
+ .state_disk = {
+ .uV = 1,
+ .mode = REGULATOR_MODE_STANDBY,
+ .disabled = 1,
+ },
+ .state_standby = {
+ .uV = 1,
+ .mode = REGULATOR_MODE_STANDBY,
+ .disabled = 1,
+ },
+
+ },
+ .num_consumer_supplies = ARRAY_SIZE(tps65910_touch_supply),
+ .consumer_supplies = tps65910_touch_supply,
+};
+
+/* =========================================================================== */
+
+/* --------------------------------------------------------------------------- */
+
+/* This one only works if 'always_on' is set to true. Do I need to do something
+ * special otherwise to turn it on? Maybe the driver doesn't enable it.
+ *
+ * The accelerometer driver isn't using regulators properly, hence this needs to
+ * be always on.
+ */
+
+static struct regulator_consumer_supply tps65910_accel_supply[] = {
+ REGULATOR_SUPPLY("vdd", "mpu6515"),
+};
+
+static struct regulator_init_data tps65910_accel = {
+ .supply_regulator = "VBAT",
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL | REGULATOR_MODE_IDLE | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
+ .always_on = true,
+ .apply_uV = true,
+
+ .state_mem = {
+ .uV = 1,
+ .mode = REGULATOR_MODE_STANDBY,
+ .disabled = 1,
+ },
+ .state_disk = {
+ .uV = 1,
+ .mode = REGULATOR_MODE_STANDBY,
+ .disabled = 1,
+ },
+ .state_standby = {
+ .uV = 1,
+ .mode = REGULATOR_MODE_STANDBY,
+ .disabled = 1,
+ },
+ },
+ .num_consumer_supplies = ARRAY_SIZE(tps65910_accel_supply),
+ .consumer_supplies = tps65910_accel_supply,
+};
+
+/* --------------------------------------------------------------------------- */
+/* Supplies the MPU PD and friends.
+ */
+
+static struct regulator_consumer_supply tps65910_vdd1_supply[] = {
+ REGULATOR_SUPPLY("vcc", "cpu0"),
+};
+
+static struct regulator_init_data tps65910_vdd1 = {
+ .supply_regulator = "VBAT",
+ .constraints = {
+ .name = "vdd_mpu_iva",
+ .min_uV = 900000,
+ .max_uV = 1350000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = false,
+
+ .state_mem = {
+ .uV = 1,
+ .mode = REGULATOR_MODE_STANDBY,
+ .disabled = 1,
+ },
+ .state_disk = {
+ .uV = 1,
+ .mode = REGULATOR_MODE_STANDBY,
+ .disabled = 1,
+ },
+ .state_standby = {
+ .uV = 1,
+ .mode = REGULATOR_MODE_STANDBY,
+ .disabled = 1,
+ },
+ },
+
+ .num_consumer_supplies = ARRAY_SIZE(tps65910_vdd1_supply),
+ .consumer_supplies = tps65910_vdd1_supply,
+};
+
+/* --------------------------------------------------------------------------- */
+/* I seem to need always on, but the TWL code gets by without it. So...
+ */
+
+static struct regulator_consumer_supply tps65910_vdd2_supply[] = {
+ REGULATOR_SUPPLY("vdd_core", "l3_main.0"),
+};
+
+static struct regulator_init_data tps65910_vdd2 = {
+ .supply_regulator = "VBAT",
+ .constraints = {
+ .name = "vdd_core",
+ .min_uV = 900000,
+ .max_uV = 1200000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL,
+ .valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+ .always_on = false,
+
+ .state_mem = {
+ .uV = 1,
+ .mode = REGULATOR_MODE_STANDBY,
+ .disabled = 1,
+ },
+ .state_disk = {
+ .uV = 1,
+ .mode = REGULATOR_MODE_STANDBY,
+ .disabled = 1,
+ },
+ .state_standby = {
+ .uV = 1,
+ .mode = REGULATOR_MODE_STANDBY,
+ .disabled = 1,
+ },
+ },
+
+ .num_consumer_supplies = ARRAY_SIZE(tps65910_vdd2_supply),
+ .consumer_supplies = tps65910_vdd2_supply,
+};
+
+/* --------------------------------------------------------------------------- */
+
+/* The clock has to be ON, probably because we're not enabling it properly. */
+/* If I set i2chs_keepon to 6, UBIfs fails to mount (!?). Again, probably
+ * not enabling it properly.
+ *
+ * And even with therm set, the screen acts weird (looking really dark during
+ * boot, touch not working when up).
+ */
+
+/*
+static struct tps65910_sleep_keepon_data olio_slp_keepon = {
+ .therm_keepon = 0,
+ .clkout32k_keepon = 0,
+ .i2chs_keepon = 1,
+ };*/
+
+
+
+static struct tps65910_board omap3h1_tps65910_pdata = {
+ /* .irq = 7 + OMAP_INTC_START, */ /* Getting this at runtime instead. */
+ .en_ck32k_xtal = true,
+ /* .en_dev_slp = true, */
+
+ /* .slp_keepon = &olio_slp_keepon, */
+
+ .tps65910_pmic_init_data[TPS65910_REG_VIO] = &tps65910_1v8,
+ .tps65910_pmic_init_data[TPS65910_REG_VDD1] = &tps65910_vdd1,
+ .tps65910_pmic_init_data[TPS65910_REG_VDD2] = &tps65910_vdd2,
+ .tps65910_pmic_init_data[TPS65910_REG_VDIG1] = &tps65910_accel,
+ .tps65910_pmic_init_data[TPS65910_REG_VDIG2] = &tps65910_touch,
+ .tps65910_pmic_init_data[TPS65910_REG_VPLL] = &tps65910_vpll,
+
+ .tps65910_pmic_init_data[TPS65910_REG_VMMC] = &tps65910_touch3,
+ .tps65910_pmic_init_data[TPS65910_REG_VAUX2] = &tps65910_vibrator,
+
+ /* This one is connected to BT ... maybe more? */
+
+ .tps65910_pmic_init_data[TPS65910_REG_VAUX33] = &tps65910_3v3,
+
+ /* not actually used */
+
+ .tps65910_pmic_init_data[TPS65910_REG_VRTC] = &tps65910_dummy,
+ .tps65910_pmic_init_data[TPS65910_REG_VDAC] = &tps65910_dummy,
+ .tps65910_pmic_init_data[TPS65910_REG_VAUX1] = &tps65910_dummy, /* 2v85 */
+ .tps65910_pmic_init_data[TPS65910_REG_VDD3] = &tps65910_dummy,
+
+ .pm_off = true,
+};
+
+
+/* ====================================================================== */
+/* Voltage domain settings */
+
+
+#define OMAP3_SRI2C_SLAVE_ADDR 0x12
+#define OMAP3_VDD_MPU_SR_CONTROL_REG 0x00
+#define OMAP3_VDD_CORE_SR_CONTROL_REG 0x01
+#define OMAP3_VP_CONFIG_ERROROFFSET 0x00
+#define OMAP3_VP_VSTEPMIN_VSTEPMIN 0x1
+#define OMAP3_VP_VSTEPMAX_VSTEPMAX 0x04
+#define OMAP3_VP_VLIMITTO_TIMEOUT_US 200
+
+
+static unsigned long olio_vsel_to_uv(const u8 vsel)
+{
+ return (((vsel * 125) + 6000)) * 100;
+}
+
+static u8 olio_uv_to_vsel(unsigned long uv)
+{
+ return DIV_ROUND_UP(uv - 600000, 12500);
+}
+
+
+static struct omap_voltdm_pmic omap3_mpu_pmic = {
+ .slew_rate = 12500,
+ .step_size = 12500,
+ .vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET,
+ .vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN,
+ .vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX,
+ .vddmin = 900000,
+ .vddmax = 1350000,
+ .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
+ .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
+ .volt_reg_addr = OMAP3_VDD_MPU_SR_CONTROL_REG,
+ .i2c_high_speed = true,
+ .vsel_to_uv = olio_vsel_to_uv,
+ .uv_to_vsel = olio_uv_to_vsel,
+};
+
+static struct omap_voltdm_pmic omap3_core_pmic = {
+ .slew_rate = 12500,
+ .step_size = 12500,
+ .vp_erroroffset = OMAP3_VP_CONFIG_ERROROFFSET,
+ .vp_vstepmin = OMAP3_VP_VSTEPMIN_VSTEPMIN,
+ .vp_vstepmax = OMAP3_VP_VSTEPMAX_VSTEPMAX,
+ .vddmin = 900000,
+ .vddmax = 1200000,
+ .vp_timeout_us = OMAP3_VP_VLIMITTO_TIMEOUT_US,
+ .i2c_slave_addr = OMAP3_SRI2C_SLAVE_ADDR,
+ .volt_reg_addr = OMAP3_VDD_CORE_SR_CONTROL_REG,
+ .i2c_high_speed = true,
+ .vsel_to_uv = olio_vsel_to_uv,
+ .uv_to_vsel = olio_uv_to_vsel,
+};
+
+int __init omap3_voltdm_init(void)
+{
+ struct voltagedomain *voltdm;
+
+ if (!cpu_is_omap34xx())
+ return -ENODEV;
+
+ voltdm = voltdm_lookup("mpu_iva");
+ omap_voltage_register_pmic(voltdm, &omap3_mpu_pmic);
+
+ voltdm = voltdm_lookup("core");
+ omap_voltage_register_pmic(voltdm, &omap3_core_pmic);
+
+ return 0;
+}
+
+
+
+/* ====================================================================== */
+
+
+static struct i2c_board_info __initdata omap3h1_i2c1_board_info[] = {
+ {
+ I2C_BOARD_INFO("tps65910", 0x2d),
+ .platform_data = &omap3h1_tps65910_pdata,
+ },
+#ifdef CONFIG_MACH_OMAP3_H1_DVT2
+};
+static struct i2c_board_info __initdata omap3h1_i2c2_board_info[] = {
+#endif
+ {
+ I2C_BOARD_INFO("mpu6515", 0x68),
+ // This is needed for the interrupt wake. IH_GPIO_BASE changed in 3.10
+ // .irq = (IH_GPIO_BASE + MPUIRQ_GPIO),
+ .platform_data = &mpu_data,
+ },
+ {
+ /* Backlight */
+ I2C_BOARD_INFO("lm3530-led", 0x38),
+ .platform_data = &omap3h1_backlight_platform_data,
+ },
+ {
+ I2C_BOARD_INFO("mXT224", 0x4a),
+ .platform_data = &mxt_data,
+ },
+ {
+ I2C_BOARD_INFO("cm3391", 0x10),
+ },
+#ifdef CONFIG_MACH_OMAP3_H1_EVT1
+};
+static struct i2c_board_info __initdata omap3h1_i2c3_board_info[] = {
+#endif
+ {
+ I2C_BOARD_INFO("bq274xx", 0x55),
+ },
+};
+
+#ifdef ONLY_KEEPING_THIS_STUFF_FOR_NOSTALGIC_REASONS
+
+/* --------------------------------------------------------------------------- */
+/* 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 500
+#define OLIO_ONE_SECOND 1000
+#define OLIO_DT_WAIT 3000
+
+static unsigned long previous;
+static unsigned long previous_double;
+
+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) {
+
+ /* ignore double clicks that happens too soon from the previous one */
+ if (jiffies_to_msecs (now - previous_double) < OLIO_DT_WAIT)
+ {
+ previous = 0;
+ return IRQ_HANDLED;
+ }
+
+ 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 (20 * OLIO_ONE_SECOND));
+
+ previous_double = now;
+ 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,
+ IRQF_SHARED | IRQF_TRIGGER_RISING,
+ "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;
+}
+
+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;
+}
+
+
+#endif /* ONLY_KEEPING_THIS_STUFF_FOR_NOSTALGIC_REASONS */
+
+
+/***************************************************************************
+ * omap_uart data
+ */
+
+/* Some notes:
+ .dma_enabled = false,
+ .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,
+ .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ .autosuspend_timeout = DEFAULT_AUTOSUSPEND_DELAY, ( -1 or X ms. )
+
+ .wakelock_timeout - for minnow, this is 150 (BT) or 50 (M4 debug).
+ Can be left out.
+
+ .DTR_* -> can be left out. I can't find anyone using it.
+
+ int DTR_gpio;
+ int DTR_inverted;
+ int DTR_present;
+ bool wakeup_capable;
+
+ bool open_close_pm; - Minnow uses this for c55 only
+ unsigned int rx_trig; Minnow, BT & debug only
+*/
+
+static struct omap_uart_port_info omap_uart_ports[] = {
+ {
+ .dma_enabled = false, /* To specify DMA Mode */
+ .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,
+ .autosuspend_timeout = 5000,
+ .wakeup_capable = false,
+ },
+ {
+ .dma_enabled = false, /* To specify DMA Mode */
+ .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,
+ .autosuspend_timeout = 5000,
+ .wakeup_capable = false,
+ },
+ {
+ .dma_enabled = false, /* To specify DMA Mode */
+ .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,
+ .autosuspend_timeout = -1,
+ .wakelock_timeout = -1,
+ .wakeup_capable = true,
+ },
+ {
+ .dma_enabled = false, /* To specify DMA Mode */
+ .dma_rx_buf_size = DEFAULT_RXDMA_BUFSIZE,
+ .dma_rx_timeout = DEFAULT_RXDMA_TIMEOUT,
+ .dma_rx_poll_rate = DEFAULT_RXDMA_POLLRATE,
+ .autosuspend_timeout = 5000,
+ .wakeup_capable = false,
+ },
+};
+
+
+/***************************************************************************
+ * DEVICE TREE STUFF
+ *
+ * Trying to include some DT stuff with our board file. Not sure how this
+ * will work out...
+ */
+
+static struct of_device_id omap_dt_match_table[] __initdata = {
+ { .compatible = "olio,omap3-h1", },
+ { .compatible = "simple-bus", },
+ { .compatible = "ti,omap-infra", },
+ { }
+};
+
+
+/***************************************************************************
+ * omap3_h1_i2c_init - init the i2c buses
+ *
+ */
+
+static int __init omap3_h1_i2c_init(void)
+{
+ 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.
+ */
+
+ gpio_request_one(ATMEL_MXT_GPIO, GPIOF_IN, "atmel_mxt_ts CHG");
+ gpio_request_one(MPUIRQ_GPIO, GPIOF_IN, "mpu6515 IRQ pin");
+
+ 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 = acc_irq;
+
+ ((struct tps65910_board *) (omap3h1_i2c1_board_info[0].platform_data))->irq =
+ gpio_to_irq (TPS_SYS_NIRQ);
+#else
+ omap3h1_i2c1_board_info[3].irq = gpio_to_irq(ATMEL_MXT_GPIO);
+ omap3h1_i2c1_board_info[1].irq = acc_irq;
+#endif
+
+ 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));
+#ifdef CONFIG_MACH_OMAP3_H1_DVT2
+ omap_register_i2c_bus(2, 400, omap3h1_i2c2_board_info, ARRAY_SIZE(omap3h1_i2c2_board_info));
+#else
+ omap_register_i2c_bus(2, 400, NULL, 0);
+#endif
+#ifdef CONFIG_MACH_OMAP3_H1_EVT1
+ omap_register_i2c_bus(3, 400, omap3h1_i2c3_board_info, ARRAY_SIZE(omap3h1_i2c3_board_info));
+#else
+ omap_register_i2c_bus(3, 400, NULL, 0);
+#endif
+ return 0;
+}
+
+
+static struct platform_device *omap3h1_devices[] __initdata = {
+ &omap3h1_vbat,
+ // &bcm20702_bluetooth_device,
+ &nop_phy_device,
+ &omap3h1_dmic_codec,
+};
+
+#ifdef CONFIG_OMAP_MUX
+static struct omap_board_mux board_mux[] __initdata = {
+
+#if defined(CONFIG_MACH_OMAP3_H1_DVT1) || defined(CONFIG_MACH_OMAP3_H1_DVT2)
+ OMAP3_MUX(CAM_HS, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+#else
+ OMAP3_MUX(HSUSB0_DIR, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+#endif
+ OMAP3_MUX(DSS_PCLK, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_HSYNC, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_VSYNC, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA0, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA1, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA2, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA3, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA4, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA5, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA6, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA7, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA8, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA9, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA10, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA11, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA12, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA13, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA14, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA15, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA16, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(DSS_DATA17, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+
+ OMAP3_MUX(MCSPI1_CLK, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(MCSPI1_SIMO, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+ OMAP3_MUX(MCSPI1_SOMI, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+ OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT),
+
+ /* TOUCH_RESET */
+
+ OMAP3_MUX(CAM_D6, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP),
+
+#if defined(CONFIG_MACH_OMAP3_H1_DVT1) || defined(CONFIG_MACH_OMAP3_H1_DVT2)
+ /* USB pin settings (mUSB) */
+
+ OMAP3_MUX(HSUSB0_CLK, (OMAP_MUX_MODE0 | OMAP_PIN_INPUT)),
+ OMAP3_MUX(HSUSB0_DATA0, (OMAP_MUX_MODE0 | OMAP_PIN_INPUT)),
+ OMAP3_MUX(HSUSB0_DATA1, (OMAP_MUX_MODE0 | OMAP_PIN_INPUT)),
+ OMAP3_MUX(HSUSB0_DATA2, (OMAP_MUX_MODE0 | OMAP_PIN_INPUT)),
+ OMAP3_MUX(HSUSB0_DATA3, (OMAP_MUX_MODE0 | OMAP_PIN_INPUT)),
+ OMAP3_MUX(HSUSB0_DATA4, (OMAP_MUX_MODE0 | OMAP_PIN_INPUT)),
+ OMAP3_MUX(HSUSB0_DATA5, (OMAP_MUX_MODE0 | OMAP_PIN_INPUT)),
+ OMAP3_MUX(HSUSB0_DATA6, (OMAP_MUX_MODE0 | OMAP_PIN_INPUT)),
+ OMAP3_MUX(HSUSB0_DATA7, (OMAP_MUX_MODE0 | OMAP_PIN_INPUT)),
+ OMAP3_MUX(HSUSB0_DIR, (OMAP_MUX_MODE0 | OMAP_PIN_INPUT)),
+ OMAP3_MUX(HSUSB0_NXT, (OMAP_MUX_MODE0 | OMAP_PIN_INPUT)),
+ OMAP3_MUX(HSUSB0_STP, (OMAP_MUX_MODE0 | OMAP_PIN_OUTPUT)),
+#endif /* CONFIG_MACH_OMAP3_H1_DVT */
+
+ /* accelerometer */
+
+ OMAP3_MUX(JTAG_EMU1, (OMAP_MUX_MODE4 | OMAP_PIN_INPUT
+ | OMAP_PIN_OFF_WAKEUPENABLE)),
+
+ /* USB on */
+
+ OMAP3_MUX(ETK_D7, (OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT)),
+
+ OMAP3_MUX(SYS_NIRQ, (OMAP_MUX_MODE0 | OMAP_PIN_INPUT)),
+
+ { .reg_offset = OMAP_MUX_TERMINATOR },
+};
+#endif
+
+static void __init omap3_h1_init(void)
+{
+ /* Read what we can from the device tree */
+
+ of_platform_populate(NULL, omap_dt_match_table, NULL, NULL);
+
+ board_nand_init(omap3h1_nand_partitions,
+ ARRAY_SIZE(omap3h1_nand_partitions), NAND_CS,
+ NAND_BUSWIDTH_16, NULL);
+
+ omap_sdrc_init(mt29c4g48_sdrc_params, mt29c4g48_sdrc_params);
+
+ omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
+
+ omap3_h1_i2c_init();
+
+ /* Set up the voltage domains */
+ omap3_voltdm_init();
+
+ platform_add_devices(omap3h1_devices, ARRAY_SIZE(omap3h1_devices));
+
+ omap3h1_spi_init();
+
+ omap_serial_board_init(omap_uart_ports);
+
+ omap_display_init(&omap3h1_dss_data);
+
+ usb_bind_phy("musb-hdrc.0.auto", 0, "nop_usb_xceiv"); /* "tusb-usb-h1" */
+
+ usb_musb_init(&musb_board_data);
+
+ /* #ifdef ONLY_KEEPING_THIS_STUFF_FOR_NOSTALGIC_REASONS */
+
+ /* 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);
+ */
+
+ /* #endif ONLY_KEEPING_THIS_STUFF_FOR_NOSTALGIC_REASONS*/
+
+}
+
+static const char *omap3_h1_boards_compat[] __initdata = {
+ "olio,omap3-h1",
+ NULL,
+};
+
+DT_MACHINE_START(OMAP3_H1, "Olio OMAP3 H1 (Flattened Device Tree)")
+ .atag_offset = 0x100,
+ .reserve = omap_reserve,
+ .map_io = omap3_map_io,
+ .init_early = omap3630_init_early,
+ /* .init_irq = omap3_init_irq, */
+ .init_irq = omap_intc_of_init,
+ .handle_irq = omap3_intc_handle_irq,
+ .init_machine = omap3_h1_init,
+ .init_late = omap3630_init_late,
+ .init_time = omap3_sync32k_timer_init,
+ /* .init_time = omap3_secure_sync32k_timer_init, */
+ .dt_compat = omap3_h1_boards_compat,
+ .restart = omap3xxx_restart,
+MACHINE_END
+
+#if 0 /* removing ... for now */
+MACHINE_START(OMAP3_H1, "Olio OMAP3 H1 Board")
+ .atag_offset = 0x100,
+ .reserve = omap_reserve,
+ .map_io = omap3_map_io,
+ .init_early = omap3630_init_early,
+ .init_irq = omap3_init_irq,
+ .handle_irq = omap3_intc_handle_irq,
+ .init_machine = omap3_h1_init,
+ .init_late = omap3630_init_late,
+ .init_time = omap3_sync32k_timer_init,
+ /* .init_time = omap3_secure_sync32k_timer_init, */
+ /* .dt_compat = omap3_h1_boards_compat, */
+ .restart = omap3xxx_restart,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-omap2/board-omap3h1.h b/arch/arm/mach-omap2/board-omap3h1.h
new file mode 100644
index 00000000000..343eaeaaf86
--- /dev/null
+++ b/arch/arm/mach-omap2/board-omap3h1.h
@@ -0,0 +1,30 @@
+/*
+ * Bluetooth Broadcomm and low power control via GPIO
+ *
+ * Copyright (C) 2011 Samsung, Inc.
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#ifndef __BOARD_OMAP3H1__H__
+#define __BOARD_OMAP3H1__H__
+
+#include <linux/serial_core.h>
+
+extern void bcm_bt_lpm_exit_lpm_locked(struct uart_port *uport);
+
+#endif /* __BOARD_OMAP3H1_H__ */
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 9017d5ea9f3..81a30ac94a8 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -66,7 +66,7 @@ static int __init omap3_l3_init(void)
WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
- return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
+ return PTR_RET(pdev);
}
omap_postcore_initcall(omap3_l3_init);
@@ -100,7 +100,7 @@ static int __init omap4_l3_init(void)
WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
- return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
+ return PTR_RET(pdev);
}
omap_postcore_initcall(omap4_l3_init);
diff --git a/arch/arm/mach-omap2/fb.c b/arch/arm/mach-omap2/fb.c
index 190ae493c6e..2ca33cc0c48 100644
--- a/arch/arm/mach-omap2/fb.c
+++ b/arch/arm/mach-omap2/fb.c
@@ -83,10 +83,7 @@ static int __init omap_init_vrfb(void)
pdev = platform_device_register_resndata(NULL, "omapvrfb", -1,
res, num_res, NULL, 0);
- if (IS_ERR(pdev))
- return PTR_ERR(pdev);
- else
- return 0;
+ return PTR_RET(pdev);
}
omap_arch_initcall(omap_init_vrfb);
diff --git a/arch/arm/mach-omap2/gpmc-nand.c b/arch/arm/mach-omap2/gpmc-nand.c
index d9c27195caf..aeca5507820 100644
--- a/arch/arm/mach-omap2/gpmc-nand.c
+++ b/arch/arm/mach-omap2/gpmc-nand.c
@@ -140,8 +140,6 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
if (gpmc_nand_data->of_node) {
gpmc_read_settings_dt(gpmc_nand_data->of_node, &s);
} else {
- s.device_nand = true;
-
/* Enable RD PIN Monitoring Reg */
if (gpmc_nand_data->dev_ready) {
s.wait_on_read = true;
@@ -149,6 +147,8 @@ int gpmc_nand_init(struct omap_nand_platform_data *gpmc_nand_data,
}
}
+ s.device_nand = true;
+
if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
s.device_width = GPMC_DEVWIDTH_16BIT;
else
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 6c4da1254f5..c877129142b 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -30,6 +30,7 @@
#include <linux/of_mtd.h>
#include <linux/of_device.h>
#include <linux/mtd/nand.h>
+#include <linux/pm_runtime.h>
#include <linux/platform_data/mtd-nand-omap2.h>
@@ -148,13 +149,14 @@ struct omap3_gpmc_regs {
static struct gpmc_client_irq gpmc_client_irq[GPMC_NR_IRQ];
static struct irq_chip gpmc_irq_chip;
-static unsigned gpmc_irq_start;
+static int gpmc_irq_start;
static struct resource gpmc_mem_root;
static struct resource gpmc_cs_mem[GPMC_CS_NUM];
static DEFINE_SPINLOCK(gpmc_mem_lock);
/* Define chip-selects as reserved by default until probe completes */
static unsigned int gpmc_cs_map = ((1 << GPMC_CS_NUM) - 1);
+static unsigned int gpmc_cs_num = GPMC_CS_NUM;
static unsigned int gpmc_nr_waitpins;
static struct device *gpmc_dev;
static int gpmc_irq;
@@ -521,8 +523,10 @@ static int gpmc_cs_remap(int cs, u32 base)
int ret;
u32 old_base, size;
- if (cs > GPMC_CS_NUM)
+ if (cs > gpmc_cs_num) {
+ pr_err("%s: requested chip-select is disabled\n", __func__);
return -ENODEV;
+ }
gpmc_cs_get_memconf(cs, &old_base, &size);
if (base == old_base)
return 0;
@@ -545,9 +549,10 @@ int gpmc_cs_request(int cs, unsigned long size, unsigned long *base)
struct resource *res = &gpmc_cs_mem[cs];
int r = -1;
- if (cs > GPMC_CS_NUM)
+ if (cs > gpmc_cs_num) {
+ pr_err("%s: requested chip-select is disabled\n", __func__);
return -ENODEV;
-
+ }
size = gpmc_mem_align(size);
if (size > (1 << GPMC_SECTION_SHIFT))
return -ENOMEM;
@@ -582,7 +587,7 @@ EXPORT_SYMBOL(gpmc_cs_request);
void gpmc_cs_free(int cs)
{
spin_lock(&gpmc_mem_lock);
- if (cs >= GPMC_CS_NUM || cs < 0 || !gpmc_cs_reserved(cs)) {
+ if (cs >= gpmc_cs_num || cs < 0 || !gpmc_cs_reserved(cs)) {
printk(KERN_ERR "Trying to free non-reserved GPMC CS%d\n", cs);
BUG();
spin_unlock(&gpmc_mem_lock);
@@ -777,7 +782,7 @@ static void gpmc_mem_exit(void)
{
int cs;
- for (cs = 0; cs < GPMC_CS_NUM; cs++) {
+ for (cs = 0; cs < gpmc_cs_num; cs++) {
if (!gpmc_cs_mem_enabled(cs))
continue;
gpmc_cs_delete_mem(cs);
@@ -798,7 +803,7 @@ static void gpmc_mem_init(void)
gpmc_mem_root.end = GPMC_MEM_END;
/* Reserve all regions that has been set up by bootloader */
- for (cs = 0; cs < GPMC_CS_NUM; cs++) {
+ for (cs = 0; cs < gpmc_cs_num; cs++) {
u32 base, size;
if (!gpmc_cs_mem_enabled(cs))
@@ -1245,7 +1250,6 @@ void gpmc_read_settings_dt(struct device_node *np, struct gpmc_settings *p)
p->sync_read = of_property_read_bool(np, "gpmc,sync-read");
p->sync_write = of_property_read_bool(np, "gpmc,sync-write");
- p->device_nand = of_property_read_bool(np, "gpmc,device-nand");
of_property_read_u32(np, "gpmc,device-width", &p->device_width);
of_property_read_u32(np, "gpmc,mux-add-data", &p->mux_add_data);
@@ -1337,12 +1341,11 @@ static void __maybe_unused gpmc_read_timings_dt(struct device_node *np,
#ifdef CONFIG_MTD_NAND
-static const char * const nand_ecc_opts[] = {
- [OMAP_ECC_HAMMING_CODE_DEFAULT] = "sw",
- [OMAP_ECC_HAMMING_CODE_HW] = "hw",
- [OMAP_ECC_HAMMING_CODE_HW_ROMCODE] = "hw-romcode",
- [OMAP_ECC_BCH4_CODE_HW] = "bch4",
- [OMAP_ECC_BCH8_CODE_HW] = "bch8",
+static const char * const nand_xfer_types[] = {
+ [NAND_OMAP_PREFETCH_POLLED] = "prefetch-polled",
+ [NAND_OMAP_POLLED] = "polled",
+ [NAND_OMAP_PREFETCH_DMA] = "prefetch-dma",
+ [NAND_OMAP_PREFETCH_IRQ] = "prefetch-irq",
};
static int gpmc_probe_nand_child(struct platform_device *pdev,
@@ -1367,10 +1370,45 @@ static int gpmc_probe_nand_child(struct platform_device *pdev,
gpmc_nand_data->cs = val;
gpmc_nand_data->of_node = child;
- if (!of_property_read_string(child, "ti,nand-ecc-opt", &s))
- for (val = 0; val < ARRAY_SIZE(nand_ecc_opts); val++)
- if (!strcasecmp(s, nand_ecc_opts[val])) {
- gpmc_nand_data->ecc_opt = val;
+ /* Detect availability of ELM module */
+ gpmc_nand_data->elm_of_node = of_parse_phandle(child, "ti,elm-id", 0);
+ if (gpmc_nand_data->elm_of_node == NULL)
+ gpmc_nand_data->elm_of_node =
+ of_parse_phandle(child, "elm_id", 0);
+ if (gpmc_nand_data->elm_of_node == NULL)
+ pr_warn("%s: ti,elm-id property not found\n", __func__);
+
+ /* select ecc-scheme for NAND */
+ if (of_property_read_string(child, "ti,nand-ecc-opt", &s)) {
+ pr_err("%s: ti,nand-ecc-opt not found\n", __func__);
+ return -ENODEV;
+ }
+ if (!strcmp(s, "ham1") || !strcmp(s, "sw") ||
+ !strcmp(s, "hw") || !strcmp(s, "hw-romcode"))
+ gpmc_nand_data->ecc_opt =
+ OMAP_ECC_HAM1_CODE_HW;
+ else if (!strcmp(s, "bch4"))
+ if (gpmc_nand_data->elm_of_node)
+ gpmc_nand_data->ecc_opt =
+ OMAP_ECC_BCH4_CODE_HW;
+ else
+ gpmc_nand_data->ecc_opt =
+ OMAP_ECC_BCH4_CODE_HW_DETECTION_SW;
+ else if (!strcmp(s, "bch8"))
+ if (gpmc_nand_data->elm_of_node)
+ gpmc_nand_data->ecc_opt =
+ OMAP_ECC_BCH8_CODE_HW;
+ else
+ gpmc_nand_data->ecc_opt =
+ OMAP_ECC_BCH8_CODE_HW_DETECTION_SW;
+ else
+ pr_err("%s: ti,nand-ecc-opt invalid value\n", __func__);
+
+ /* select data transfer mode for NAND controller */
+ if (!of_property_read_string(child, "ti,nand-xfer-type", &s))
+ for (val = 0; val < ARRAY_SIZE(nand_xfer_types); val++)
+ if (!strcasecmp(s, nand_xfer_types[val])) {
+ gpmc_nand_data->xfer_type = val;
break;
}
@@ -1473,8 +1511,8 @@ static int gpmc_probe_generic_child(struct platform_device *pdev,
*/
ret = gpmc_cs_remap(cs, res.start);
if (ret < 0) {
- dev_err(&pdev->dev, "cannot remap GPMC CS %d to 0x%x\n",
- cs, res.start);
+ dev_err(&pdev->dev, "cannot remap GPMC CS %d to %pa\n",
+ cs, &res.start);
goto err;
}
@@ -1513,6 +1551,20 @@ static int gpmc_probe_dt(struct platform_device *pdev)
if (!of_id)
return 0;
+ ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-cs",
+ &gpmc_cs_num);
+ if (ret < 0) {
+ pr_err("%s: number of chip-selects not defined\n", __func__);
+ return ret;
+ } else if (gpmc_cs_num < 1) {
+ pr_err("%s: all chip-selects are disabled\n", __func__);
+ return -EINVAL;
+ } else if (gpmc_cs_num > GPMC_CS_NUM) {
+ pr_err("%s: number of supported chip-selects cannot be > %d\n",
+ __func__, GPMC_CS_NUM);
+ return -EINVAL;
+ }
+
ret = of_property_read_u32(pdev->dev.of_node, "gpmc,num-waitpins",
&gpmc_nr_waitpins);
if (ret < 0) {
@@ -1577,7 +1629,8 @@ static int gpmc_probe(struct platform_device *pdev)
return PTR_ERR(gpmc_l3_clk);
}
- clk_prepare_enable(gpmc_l3_clk);
+ pm_runtime_enable(&pdev->dev);
+ pm_runtime_get_sync(&pdev->dev);
gpmc_dev = &pdev->dev;
@@ -1610,12 +1663,14 @@ static int gpmc_probe(struct platform_device *pdev)
/* Now the GPMC is initialised, unreserve the chip-selects */
gpmc_cs_map = 0;
- if (!pdev->dev.of_node)
+ if (!pdev->dev.of_node) {
+ gpmc_cs_num = GPMC_CS_NUM;
gpmc_nr_waitpins = GPMC_NR_WAITPINS;
+ }
rc = gpmc_probe_dt(pdev);
if (rc < 0) {
- clk_disable_unprepare(gpmc_l3_clk);
+ pm_runtime_put_sync(&pdev->dev);
clk_put(gpmc_l3_clk);
dev_err(gpmc_dev, "failed to probe DT parameters\n");
return rc;
@@ -1628,10 +1683,30 @@ static int gpmc_remove(struct platform_device *pdev)
{
gpmc_free_irq();
gpmc_mem_exit();
+ pm_runtime_put_sync(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
gpmc_dev = NULL;
return 0;
}
+#ifdef CONFIG_PM_SLEEP
+static int gpmc_suspend(struct device *dev)
+{
+ omap3_gpmc_save_context();
+ pm_runtime_put_sync(dev);
+ return 0;
+}
+
+static int gpmc_resume(struct device *dev)
+{
+ pm_runtime_get_sync(dev);
+ omap3_gpmc_restore_context();
+ return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(gpmc_pm_ops, gpmc_suspend, gpmc_resume);
+
static struct platform_driver gpmc_driver = {
.probe = gpmc_probe,
.remove = gpmc_remove,
@@ -1639,6 +1714,7 @@ static struct platform_driver gpmc_driver = {
.name = DEVICE_NAME,
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(gpmc_dt_ids),
+ .pm = &gpmc_pm_ops,
},
};
@@ -1678,7 +1754,7 @@ static int __init omap_gpmc_init(void)
pdev = omap_device_build(DEVICE_NAME, -1, oh, NULL, 0);
WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
- return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
+ return PTR_RET(pdev);
}
omap_postcore_initcall(omap_gpmc_init);
@@ -1701,7 +1777,6 @@ static irqreturn_t gpmc_handle_irq(int irq, void *dev)
return IRQ_HANDLED;
}
-#ifdef CONFIG_ARCH_OMAP3
static struct omap3_gpmc_regs gpmc_context;
void omap3_gpmc_save_context(void)
@@ -1715,7 +1790,7 @@ void omap3_gpmc_save_context(void)
gpmc_context.prefetch_config1 = gpmc_read_reg(GPMC_PREFETCH_CONFIG1);
gpmc_context.prefetch_config2 = gpmc_read_reg(GPMC_PREFETCH_CONFIG2);
gpmc_context.prefetch_control = gpmc_read_reg(GPMC_PREFETCH_CONTROL);
- for (i = 0; i < GPMC_CS_NUM; i++) {
+ for (i = 0; i < gpmc_cs_num; i++) {
gpmc_context.cs_context[i].is_valid = gpmc_cs_mem_enabled(i);
if (gpmc_context.cs_context[i].is_valid) {
gpmc_context.cs_context[i].config1 =
@@ -1747,7 +1822,7 @@ void omap3_gpmc_restore_context(void)
gpmc_write_reg(GPMC_PREFETCH_CONFIG1, gpmc_context.prefetch_config1);
gpmc_write_reg(GPMC_PREFETCH_CONFIG2, gpmc_context.prefetch_config2);
gpmc_write_reg(GPMC_PREFETCH_CONTROL, gpmc_context.prefetch_control);
- for (i = 0; i < GPMC_CS_NUM; i++) {
+ for (i = 0; i < gpmc_cs_num; i++) {
if (gpmc_context.cs_context[i].is_valid) {
gpmc_cs_write_reg(i, GPMC_CS_CONFIG1,
gpmc_context.cs_context[i].config1);
@@ -1766,4 +1841,3 @@ void omap3_gpmc_restore_context(void)
}
}
}
-#endif /* CONFIG_ARCH_OMAP3 */
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
index 7c5a6b81875..f9b8a4c965a 100644
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
@@ -3818,6 +3818,7 @@ static struct omap_hwmod_ocp_if *omap34xx_gp_hwmod_ocp_ifs[] __initdata = {
NULL
};
+
static struct omap_hwmod_ocp_if *omap36xx_gp_hwmod_ocp_ifs[] __initdata = {
&omap3xxx_l4_sec__timer12,
&omap3xxx_l4_core__sham,
@@ -3975,7 +3976,8 @@ int __init omap3xxx_hwmod_init(void)
} else if (rev == OMAP3630_REV_ES1_0 || rev == OMAP3630_REV_ES1_1 ||
rev == OMAP3630_REV_ES1_2) {
h = omap36xx_hwmod_ocp_ifs;
- h_gp = omap36xx_gp_hwmod_ocp_ifs;
+ /* OLIO: We don't want these clocks running */
+ /* h_gp = omap36xx_gp_hwmod_ocp_ifs; */
} else {
WARN(1, "OMAP3 hwmod family init: unknown chip type\n");
return -EINVAL;
diff --git a/arch/arm/mach-omap2/opp.c b/arch/arm/mach-omap2/opp.c
index 82fd8c72f75..7149f838be4 100644
--- a/arch/arm/mach-omap2/opp.c
+++ b/arch/arm/mach-omap2/opp.c
@@ -41,8 +41,10 @@ int __init omap_init_opp_table(struct omap_opp_def *opp_def,
{
int i, r;
+ /* OLIO HACK
if (of_have_populated_dt())
return -EINVAL;
+ */
if (!opp_def || !opp_def_size) {
pr_err("%s: invalid params!\n", __func__);
diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c
index fc67add7644..0f5af3377af 100644
--- a/arch/arm/mach-omap2/opp3xxx_data.c
+++ b/arch/arm/mach-omap2/opp3xxx_data.c
@@ -130,9 +130,9 @@ static struct omap_opp_def __initdata omap36xx_opp_def_list[] = {
/* MPU OPP2 - OPP100 */
OPP_INITIALIZER("mpu", true, 600000000, OMAP3630_VDD_MPU_OPP100_UV),
/* MPU OPP3 - OPP-Turbo */
- OPP_INITIALIZER("mpu", false, 800000000, OMAP3630_VDD_MPU_OPP120_UV),
+ OPP_INITIALIZER("mpu", true, 800000000, OMAP3630_VDD_MPU_OPP120_UV),
/* MPU OPP4 - OPP-SB */
- OPP_INITIALIZER("mpu", false, 1000000000, OMAP3630_VDD_MPU_OPP1G_UV),
+ OPP_INITIALIZER("mpu", true, 1000000000, OMAP3630_VDD_MPU_OPP1G_UV),
/* L3 OPP1 - OPP50 */
OPP_INITIALIZER("l3_main", true, 100000000, OMAP3630_VDD_CORE_OPP50_UV),
diff --git a/arch/arm/mach-omap2/pm-debug-regs.h b/arch/arm/mach-omap2/pm-debug-regs.h
index f70bbe5c6a8..65da3221b13 100644
--- a/arch/arm/mach-omap2/pm-debug-regs.h
+++ b/arch/arm/mach-omap2/pm-debug-regs.h
@@ -27,7 +27,7 @@ extern void pm_dbg_regs_copy(int tgt, int src);
static inline int pm_dbg_regs_init(struct dentry *d) { return 0; }
static inline void pm_dbg_regs_save(int reg_set) {};
static inline void pm_dbg_regs_dump(int reg_set) {};
-static inline void pm_dbg_regs_dump_delta(int current, int ref) {}
+static inline void pm_dbg_regs_dump_delta(int curr, int ref) {};
static inline void pm_dbg_show_wakeup_source(void) {};
static inline void pm_dbg_regs_copy(int tgt, int src) {};
#endif
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index dd7931c2d54..b2dc18a6b82 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -276,6 +276,8 @@ static inline void omap_init_cpufreq(void)
devinfo.name = "omap-cpufreq";
else
devinfo.name = "cpufreq-cpu0";
+
+ devinfo.name = "omap-cpufreq"; /* OLIO HACK */
platform_device_register_full(&devinfo);
}
diff --git a/arch/arm/mach-omap2/pmu.c b/arch/arm/mach-omap2/pmu.c
index 9ace8eae7ee..33c8846b419 100644
--- a/arch/arm/mach-omap2/pmu.c
+++ b/arch/arm/mach-omap2/pmu.c
@@ -54,10 +54,7 @@ static int __init omap2_init_pmu(unsigned oh_num, char *oh_names[])
WARN(IS_ERR(omap_pmu_dev), "Can't build omap_device for %s.\n",
dev_name);
- if (IS_ERR(omap_pmu_dev))
- return PTR_ERR(omap_pmu_dev);
-
- return 0;
+ return PTR_RET(omap_pmu_dev);
}
static int __init omap_init_pmu(void)
diff --git a/arch/arm/mach-omap2/sdram-micron-mt29c4g48.h b/arch/arm/mach-omap2/sdram-micron-mt29c4g48.h
new file mode 100644
index 00000000000..aa012b090f9
--- /dev/null
+++ b/arch/arm/mach-omap2/sdram-micron-mt29c4g48.h
@@ -0,0 +1,63 @@
+/*
+ * SDRC register values for the Micron MT29C4G48MAYAPAKQ-5
+ *
+ * Copyright (C) 2015 Olio Devices
+ * Copyright (C) 2008 Texas Instruments, Inc.
+ * Copyright (C) 2008-2009 Nokia Corporation
+ *
+ * Mattis Fjallstrom (mattis at oliodevices.com)
+ * Paul Walmsley
+ *
+ * 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.
+ */
+
+#ifndef ARCH_ARM_MACH_OMAP2_SDRAM_MICRON_MT29C4G48
+#define ARCH_ARM_MACH_OMAP2_SDRAM_MICRON_MT29C4G48
+
+#include "sdrc.h"
+
+/* Micron MT29C4G48MAYAPAKQ-5 */
+/* 5ns -> 200MHz */
+
+
+/* 5.4ns -> 185.185185185185 MHz */
+/* 6ns -> 166.666667 MHz */
+/* 7.5ns -> 133.33333333333 */
+
+static struct omap_sdrc_params mt29c4g48_sdrc_params[] = {
+ [0] = {
+ .rate = 200000000,
+ .actim_ctrla = 0x7AE1B4C6,
+ .actim_ctrlb = 0x00021217,
+ .rfr_ctrl = 0x0005E601,
+ .mr = 0x00000034,
+ },
+ [1] = {
+ .rate = 185185185,
+ .actim_ctrla = 0x72E1B4C6,
+ .actim_ctrlb = 0x00021215,
+ .rfr_ctrl = 0x00057201,
+ .mr = 0x00000034,
+ },
+ [2] = {
+ .rate = 166000000,
+ .actim_ctrla = 0x629DB4C6,
+ .actim_ctrlb = 0x00011113,
+ .rfr_ctrl = 0x0004E201,
+ .mr = 0x00000034,
+ },
+ [3] = {
+ .rate = 133333333,
+ .actim_ctrla = 0x5259B485,
+ .actim_ctrlb = 0x0001110F,
+ .rfr_ctrl = 0x0003DE01,
+ .mr = 0x00000034,
+ },
+ [4] = {
+ .rate = 0,
+ },
+};
+
+#endif