diff options
Diffstat (limited to 'arch/arm/mach-omap2')
| -rw-r--r-- | arch/arm/mach-omap2/Kconfig | 28 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/Makefile | 2 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-flash.c | 2 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-omap3h1-bluetooth.c | 387 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-omap3h1.c | 1267 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/board-omap3h1.h | 30 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/devices.c | 4 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/fb.c | 5 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/gpmc-nand.c | 4 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/gpmc.c | 130 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 4 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/opp.c | 2 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/opp3xxx_data.c | 4 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/pm-debug-regs.h | 2 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/pm.c | 2 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/pmu.c | 5 | ||||
| -rw-r--r-- | arch/arm/mach-omap2/sdram-micron-mt29c4g48.h | 63 |
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 |