* [PATCH 0/7] ARM: OMAP: Board updates and additions for OMAP2 @ 2007-04-09 21:33 Tony Lindgren 2007-04-09 21:33 ` [PATCH 1/7] ARM: OMAP: USB peripheral support on H4 Tony Lindgren 0 siblings, 1 reply; 9+ messages in thread From: Tony Lindgren @ 2007-04-09 21:33 UTC (permalink / raw) To: linux-kernel; +Cc: Tony Lindgren Hi, The following patch series contains updates board updates and additions for OMAP2 code. This is take #2 of the earlier 90 patch mountain, which has been split into six smaller series. Regards, Tony ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/7] ARM: OMAP: USB peripheral support on H4 2007-04-09 21:33 [PATCH 0/7] ARM: OMAP: Board updates and additions for OMAP2 Tony Lindgren @ 2007-04-09 21:33 ` Tony Lindgren 2007-04-09 21:33 ` [PATCH 2/7] ARM: OMAP: Fix typo in board-h4.h Tony Lindgren 0 siblings, 1 reply; 9+ messages in thread From: Tony Lindgren @ 2007-04-09 21:33 UTC (permalink / raw) To: linux-kernel; +Cc: David Brownell, Tony Lindgren From: David Brownell <dbrownell@users.sourceforge.net> H4 has two peripheral ports, one for "download" and one for OTG. The one to use is selected through Kconfig. Signed-off-by: David Brownell <dbrownell@users.sourceforge.net> Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/mach-omap2/Kconfig | 21 ++++++++++++++++++ arch/arm/mach-omap2/board-h4.c | 46 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+), 0 deletions(-) Index: linux-2.6/arch/arm/mach-omap2/Kconfig =================================================================== --- linux-2.6.orig/arch/arm/mach-omap2/Kconfig 2007-04-09 15:34:44.000000000 -0400 +++ linux-2.6/arch/arm/mach-omap2/Kconfig 2007-04-09 15:35:08.000000000 -0400 @@ -27,6 +27,27 @@ config MACH_OMAP_H4 depends on ARCH_OMAP2 && ARCH_OMAP24XX select OMAP_DEBUG_DEVICES +config MACH_OMAP_H4_OTG + bool "Use USB OTG connector, not device connector (S1.10)" + depends on MACH_OMAP_H4 + help + Set this if you've set S1.10 (on the mainboard) to use the + Mini-AB (OTG) connector and OTG transceiver with the USB0 + port, instead of the Mini-B ("download") connector with its + non-OTG transceiver. + + Note that the "download" connector can be used to bootstrap + the system from the OMAP mask ROM. Also, since this is a + development platform, you can also force the OTG port into + a non-OTG operational mode. + +config MACH_OMAP2_H4_USB1 + bool "Use USB1 port, not UART2 (S3.3)" + depends on MACH_OMAP_H4 + help + Set this if you've set SW3.3 (on the CPU card) so that the + expansion connectors receive USB1 signals instead of UART2. + config MACH_OMAP_APOLLON bool "OMAP 2420 Apollon board" depends on ARCH_OMAP2 && ARCH_OMAP24XX Index: linux-2.6/arch/arm/mach-omap2/board-h4.c =================================================================== --- linux-2.6.orig/arch/arm/mach-omap2/board-h4.c 2007-04-09 15:33:31.000000000 -0400 +++ linux-2.6/arch/arm/mach-omap2/board-h4.c 2007-04-09 15:35:08.000000000 -0400 @@ -278,7 +278,11 @@ static void __init omap_h4_init_irq(void } static struct omap_uart_config h4_uart_config __initdata = { +#ifdef CONFIG_MACH_OMAP2_H4_USB1 + .enabled_uarts = ((1 << 0) | (1 << 1)), +#else .enabled_uarts = ((1 << 0) | (1 << 1) | (1 << 2)), +#endif }; static struct omap_mmc_config h4_mmc_config __initdata = { @@ -295,10 +299,44 @@ static struct omap_lcd_config h4_lcd_con .ctrl_name = "internal", }; +static struct omap_usb_config h4_usb_config __initdata = { +#ifdef CONFIG_MACH_OMAP2_H4_USB1 + /* NOTE: usb1 could also be used with 3 wire signaling */ + .pins[1] = 4, +#endif + +#ifdef CONFIG_MACH_OMAP_H4_OTG + /* S1.10 ON -- USB OTG port + * usb0 switched to Mini-AB port and isp1301 transceiver; + * S2.POS3 = OFF, S2.POS4 = ON ... to allow battery charging + */ + .otg = 1, + .pins[0] = 4, +#ifdef CONFIG_USB_GADGET_OMAP + /* use OTG cable, or standard A-to-MiniB */ + .hmc_mode = 0x14, /* 0:dev/otg 1:host 2:disable */ +#elif defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE) + /* use OTG cable, or NONSTANDARD (B-to-MiniB) */ + .hmc_mode = 0x11, /* 0:host 1:host 2:disable */ +#endif /* XX */ + +#else + /* S1.10 OFF -- usb "download port" + * usb0 switched to Mini-B port and isp1105 transceiver; + * S2.POS3 = ON, S2.POS4 = OFF ... to enable battery charging + */ + .register_dev = 1, + .pins[0] = 3, +// .hmc_mode = 0x14, /* 0:dev 1:host 2:disable */ + .hmc_mode = 0x00, /* 0:dev|otg 1:disable 2:disable */ +#endif +}; + static struct omap_board_config_kernel h4_config[] = { { OMAP_TAG_UART, &h4_uart_config }, { OMAP_TAG_MMC, &h4_mmc_config }, { OMAP_TAG_LCD, &h4_lcd_config }, + { OMAP_TAG_USB, &h4_usb_config }, }; static void __init omap_h4_init(void) @@ -321,6 +359,14 @@ static void __init omap_h4_init(void) } #endif +#ifdef CONFIG_MACH_OMAP2_H4_USB1 + /* S3.3 controls whether these pins are for UART2 or USB1 */ + omap_cfg_reg(N14_24XX_USB1_SE0); + omap_cfg_reg(P15_24XX_USB1_DAT); + omap_cfg_reg(W20_24XX_USB1_TXEN); + omap_cfg_reg(V19_24XX_USB1_RCV); +#endif + platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices)); omap_board_config = h4_config; omap_board_config_size = ARRAY_SIZE(h4_config); ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 2/7] ARM: OMAP: Fix typo in board-h4.h 2007-04-09 21:33 ` [PATCH 1/7] ARM: OMAP: USB peripheral support on H4 Tony Lindgren @ 2007-04-09 21:33 ` Tony Lindgren 2007-04-09 21:33 ` [PATCH 3/7] ARM: OMAP: Sync H4 board init with linux-omap Tony Lindgren 0 siblings, 1 reply; 9+ messages in thread From: Tony Lindgren @ 2007-04-09 21:33 UTC (permalink / raw) To: linux-kernel; +Cc: Komal Shah, Tony Lindgren From: Komal Shah <komal_shah802003@yahoo.com> Replace OMAP1610 with OMAP2420. Signed-off-by: Komal Shah <komal_shah802003@yahoo.com> Signed-off-by: Tony Lindgren <tony@atomide.com> --- include/asm-arm/arch-omap/board-h4.h | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-) --- a/include/asm-arm/arch-omap/board-h4.h +++ b/include/asm-arm/arch-omap/board-h4.h @@ -1,7 +1,7 @@ /* * linux/include/asm-arm/arch-omap/board-h4.h * - * Hardware definitions for TI OMAP1610 H4 board. + * Hardware definitions for TI OMAP2420 H4 board. * * Initial creation by Dirk Behme <dirk.behme@de.bosch.com> * -- 1.4.4.2 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 3/7] ARM: OMAP: Sync H4 board init with linux-omap 2007-04-09 21:33 ` [PATCH 2/7] ARM: OMAP: Fix typo in board-h4.h Tony Lindgren @ 2007-04-09 21:33 ` Tony Lindgren 2007-04-09 21:33 ` [PATCH 4/7] ARM: OMAP: cleanup apollon board Tony Lindgren 0 siblings, 1 reply; 9+ messages in thread From: Tony Lindgren @ 2007-04-09 21:33 UTC (permalink / raw) To: linux-kernel; +Cc: Tony Lindgren This patch syncs H4 board init with linux-omap tree. Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/mach-omap2/board-h4.c | 180 +++++++++++++++++++++++++++++++-- 10 files changed, 380 insertions(+), 176 deletions(-) --- a/arch/arm/mach-omap2/board-h4.c +++ b/arch/arm/mach-omap2/board-h4.c @@ -19,6 +19,8 @@ #include <linux/delay.h> #include <linux/workqueue.h> #include <linux/input.h> +#include <linux/err.h> +#include <linux/clk.h> #include <asm/hardware.h> #include <asm/mach-types.h> @@ -36,10 +38,14 @@ #include <asm/arch/keypad.h> #include <asm/arch/menelaus.h> #include <asm/arch/dma.h> +#include <asm/arch/gpmc.h> #include "prcm-regs.h" #include <asm/io.h> +#define H4_FLASH_CS 0 +#define H4_SMC91X_CS 1 + static unsigned int row_gpios[6] = { 88, 89, 124, 11, 6, 96 }; static unsigned int col_gpios[7] = { 90, 91, 100, 36, 12, 97, 98 }; @@ -116,8 +122,6 @@ static struct flash_platform_data h4_flash_data = { }; static struct resource h4_flash_resource = { - .start = H4_CS0_BASE, - .end = H4_CS0_BASE + SZ_64M - 1, .flags = IORESOURCE_MEM, }; @@ -133,6 +137,7 @@ static struct platform_device h4_flash_device = { /* Select between the IrDA and aGPS module */ +#if defined(CONFIG_OMAP_IR) || defined(CONFIG_OMAP_IR_MODULE) static int h4_select_irda(struct device *dev, int state) { unsigned char expa; @@ -192,6 +197,10 @@ static int h4_transceiver_mode(struct device *dev, int mode) return 0; } +#else +static int h4_select_irda(struct device *dev, int state) { return 0; } +static int h4_transceiver_mode(struct device *dev, int mode) { return 0; } +#endif static struct omap_irda_config h4_irda_data = { .transceiver_cap = IR_SIRMODE | IR_MIRMODE | IR_FIRMODE, @@ -253,16 +262,80 @@ static struct platform_device *h4_devices[] __initdata = { &h4_lcd_device, }; +/* 2420 Sysboot setup (2430 is different) */ +static u32 get_sysboot_value(void) +{ + return (omap_readl(OMAP242X_CONTROL_STATUS) & 0xFFF); +} + +/* FIXME: This function should be moved to some other file, gpmc.c? */ + +/* H4-2420's always used muxed mode, H4-2422's always use non-muxed + * + * Note: OMAP-GIT doesn't correctly do is_cpu_omap2422 and is_cpu_omap2423 + * correctly. The macro needs to look at production_id not just hawkeye. + */ +static u32 is_gpmc_muxed(void) +{ + u32 mux; + mux = get_sysboot_value(); + if ((mux & 0xF) == 0xd) + return 1; /* NAND config (could be either) */ + if (mux & 0x2) /* if mux'ed */ + return 1; + else + return 0; +} + static inline void __init h4_init_debug(void) { + int eth_cs; + unsigned long cs_mem_base; + unsigned int muxed, rate; + struct clk *l3ck; + + eth_cs = H4_SMC91X_CS; + + l3ck = clk_get(NULL, "core_l3_ck"); + if (IS_ERR(l3ck)) + rate = 100000000; + else + rate = clk_get_rate(l3ck); + + if (is_gpmc_muxed()) + muxed = 0x200; + else + muxed = 0; + /* Make sure CS1 timings are correct */ - GPMC_CONFIG1_1 = 0x00011200; - GPMC_CONFIG2_1 = 0x001f1f01; - GPMC_CONFIG3_1 = 0x00080803; - GPMC_CONFIG4_1 = 0x1c091c09; - GPMC_CONFIG5_1 = 0x041f1f1f; - GPMC_CONFIG6_1 = 0x000004c4; - GPMC_CONFIG7_1 = 0x00000f40 | (0x08000000 >> 24); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, + 0x00011000 | muxed); + + if (rate >= 160000000) { + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4); + } else if (rate >= 130000000) { + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4); + } else {/* rate = 100000000 */ + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2); + } + + if (gpmc_cs_request(eth_cs, SZ_16M, &cs_mem_base) < 0) { + printk(KERN_ERR "Failed to request GPMC mem for smc91x\n"); + return; + } + udelay(100); omap_cfg_reg(M15_24XX_GPIO92); @@ -270,11 +343,24 @@ static inline void __init h4_init_debug(void) gpmc_cs_free(eth_cs); } +static void __init h4_init_flash(void) +{ + unsigned long base; + + if (gpmc_cs_request(H4_FLASH_CS, SZ_64M, &base) < 0) { + printk("Can't request GPMC CS for flash\n"); + return; + } + h4_flash_resource.start = base; + h4_flash_resource.end = base + SZ_64M - 1; +} + static void __init omap_h4_init_irq(void) { omap2_init_common_hw(); omap_init_irq(); omap_gpio_init(); + h4_init_flash(); } static struct omap_uart_config h4_uart_config __initdata = { @@ -336,9 +422,75 @@ static struct omap_board_config_kernel h4_config[] = { { OMAP_TAG_UART, &h4_uart_config }, { OMAP_TAG_MMC, &h4_mmc_config }, { OMAP_TAG_LCD, &h4_lcd_config }, - { OMAP_TAG_USB, &h4_usb_config }, + { OMAP_TAG_USB, &h4_usb_config }, }; +#ifdef CONFIG_MACH_OMAP_H4_TUSB + +#include <linux/usb/musb.h> + +static struct musb_hdrc_platform_data tusb_data = { + .mode = MUSB_OTG, + .min_power = 25, /* x2 = 50 mA drawn from VBUS as peripheral */ + + /* 1.8V supplied by Menelaus, other voltages supplied by VBAT; + * so no switching. + */ +}; + +static void __init tusb_evm_setup(void) +{ + static char announce[] __initdata = + KERN_INFO "TUSB 6010 EVM\n"; + int irq; + unsigned dmachan = 0; + + /* There are at least 32 different combinations of boards that + * are loosely called "H4", with a 2420 ... different OMAP chip + * revisions (with pin mux changes for DMAREQ, GPMC errata, etc), + * modifications of the CPU board, mainboard, EVM, TUSB etc. + * Plus omap2422, omap2423, etc. + * + * So you might need to tweak this setup to make the TUSB EVM + * behave on your particular setup ... + */ + + /* Already set up: GPMC AD[0..15], CLK, nOE, nWE, nADV_ALE */ + omap_cfg_reg(E2_GPMC_NCS2); + omap_cfg_reg(L2_GPMC_NCS7); + omap_cfg_reg(M1_GPMC_WAIT2); + + switch ((system_rev >> 8) & 0x0f) { + case 0: /* ES 1.0 */ + case 1: /* ES 2.0 */ + /* Assume early board revision without optional ES2.0 + * rework to swap J15 & AA10 so DMAREQ0 works + */ + omap_cfg_reg(AA10_242X_GPIO13); + irq = 13; + // omap_cfg_reg(J15_24XX_DMAREQ0); + break; + default: + /* Later Menelaus boards can support all 6 DMA request + * lines, at the price of boot flash A23-A26. + */ + omap_cfg_reg(J15_24XX_GPIO99); + irq = 99; + omap_cfg_reg(AA10_242X_DMAREQ0); + omap_cfg_reg(AA6_242X_DMAREQ1); + dmachan = (1 << 1) | (1 << 0); + break; + } + + if (tusb6010_setup_interface(&tusb_data, + TUSB6010_REFCLK_24, /* waitpin */ 2, + /* async cs */ 2, /* sync cs */ 7, + irq, dmachan) == 0) + printk(announce); +} + +#endif + static void __init omap_h4_init(void) { /* @@ -371,6 +523,14 @@ static void __init omap_h4_init(void) omap_board_config = h4_config; omap_board_config_size = ARRAY_SIZE(h4_config); omap_serial_init(); + + /* smc91x, debug leds, ps/2, extra uarts */ + h4_init_debug(); + +#ifdef CONFIG_MACH_OMAP_H4_TUSB + tusb_evm_setup(); +#endif + } static void __init omap_h4_map_io(void) -- 1.4.4.2 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/7] ARM: OMAP: cleanup apollon board 2007-04-09 21:33 ` [PATCH 3/7] ARM: OMAP: Sync H4 board init with linux-omap Tony Lindgren @ 2007-04-09 21:33 ` Tony Lindgren 2007-04-09 21:34 ` [PATCH 5/7] ARM: OMAP: Merge board specific files from N800 tree Tony Lindgren 0 siblings, 1 reply; 9+ messages in thread From: Tony Lindgren @ 2007-04-09 21:33 UTC (permalink / raw) To: linux-kernel; +Cc: Kyungmin Park, Tony Lindgren From: Kyungmin Park <kyungmin.park@samsung.com> - Add etherent gpmc handling - Remove unused mux setting - Add MMC switch pin comments Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/mach-omap2/board-apollon.c | 50 ++++++++++++++++++++++++++-------- 1 files changed, 38 insertions(+), 12 deletions(-) --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -27,6 +27,8 @@ #include <linux/delay.h> #include <linux/leds.h> #include <linux/irq.h> +#include <linux/err.h> +#include <linux/clk.h> #include <asm/hardware.h> #include <asm/mach-types.h> @@ -187,16 +189,42 @@ static struct platform_device *apollon_devices[] __initdata = { static inline void __init apollon_init_smc91x(void) { unsigned long base; + unsigned int rate; + struct clk *l3ck; + int eth_cs; + + l3ck = clk_get(NULL, "core_l3_ck"); + if (IS_ERR(l3ck)) + rate = 100000000; + else + rate = clk_get_rate(l3ck); + + eth_cs = APOLLON_ETH_CS; /* Make sure CS1 timings are correct */ - GPMC_CONFIG1_1 = 0x00011203; - GPMC_CONFIG2_1 = 0x001f1f01; - GPMC_CONFIG3_1 = 0x00080803; - GPMC_CONFIG4_1 = 0x1c091c09; - GPMC_CONFIG5_1 = 0x041f1f1f; - GPMC_CONFIG6_1 = 0x000004c4; - - if (gpmc_cs_request(APOLLON_ETH_CS, SZ_16M, &base) < 0) { + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG1, 0x00011200); + + if (rate >= 160000000) { + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f01); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080803); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1c0b1c0a); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4); + } else if (rate >= 130000000) { + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x041f1F1F); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000004C4); + } else {/* rate = 100000000 */ + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG2, 0x001f1f00); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG3, 0x00080802); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG4, 0x1C091C09); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG5, 0x031A1F1F); + gpmc_cs_write_reg(eth_cs, GPMC_CS_CONFIG6, 0x000003C2); + } + + if (gpmc_cs_request(eth_cs, SZ_16M, &base) < 0) { printk(KERN_ERR "Failed to request GPMC CS for smc91x\n"); return; } @@ -208,7 +236,7 @@ static inline void __init apollon_init_smc91x(void) if (omap_request_gpio(APOLLON_ETHR_GPIO_IRQ) < 0) { printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n", APOLLON_ETHR_GPIO_IRQ); - gpmc_cs_free(APOLLON_ETH_CS); + gpmc_cs_free(eth_cs); return; } omap_set_gpio_direction(APOLLON_ETHR_GPIO_IRQ, 1); @@ -232,6 +260,7 @@ static struct omap_mmc_config apollon_mmc_config __initdata = { .wire4 = 1, .wp_pin = -1, .power_pin = -1, + /* Note: If you want to detect card feature, please assign 37 */ .switch_pin = -1, }, }; @@ -336,9 +365,6 @@ static void __init omap_apollon_init(void) apollon_flash_init(); apollon_usb_init(); - /* REVISIT: where's the correct place */ - omap_cfg_reg(W19_24XX_SYS_NIRQ); - /* Use Interal loop-back in MMC/SDIO Module Input Clock selection */ CONTROL_DEVCONF |= (1 << 24); -- 1.4.4.2 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 5/7] ARM: OMAP: Merge board specific files from N800 tree 2007-04-09 21:33 ` [PATCH 4/7] ARM: OMAP: cleanup apollon board Tony Lindgren @ 2007-04-09 21:34 ` Tony Lindgren 2007-04-09 21:34 ` [PATCH 6/7] ARM: OMAP: Replace mach-omap/omap2 with mach-omap2 Tony Lindgren 2007-04-16 21:41 ` [PATCH 5/7] ARM: OMAP: Merge board specific files from N800 tree Tony Lindgren 0 siblings, 2 replies; 9+ messages in thread From: Tony Lindgren @ 2007-04-09 21:34 UTC (permalink / raw) To: linux-kernel; +Cc: Kai Svahn, Tony Lindgren From: Kai Svahn <kai.svahn@nokia.com> This patch merges board specific files from N800 tree. Nokia has published the files at: http://repository.maemo.org/pool/maemo3.0/free/source/ kernel-source-rx-34_2.6.18.orig.tar.gz kernel-source-rx-34_2.6.18-osso29.diff.gz Signed-off-by: Kai Svahn <kai.svahn@nokia.com> Signed-off-by: Tony Lindgren <tony@atomide.com> Index: linux-2.6/arch/arm/mach-omap2/Kconfig =================================================================== --- linux-2.6.orig/arch/arm/mach-omap2/Kconfig 2007-04-09 16:21:18.000000000 -0400 +++ linux-2.6/arch/arm/mach-omap2/Kconfig 2007-04-09 16:21:18.000000000 -0400 @@ -54,4 +54,13 @@ config MACH_OMAP_APOLLON config MACH_OMAP_2430SDP bool "OMAP 2430 SDP board" - depends on ARCH_OMAP2 && ARCH_OMAP24XX \ No newline at end of file + depends on ARCH_OMAP2 && ARCH_OMAP24XX + +config MACH_NOKIA_N800 + bool "Nokia N800" + depends on ARCH_OMAP24XX + +config MACH_OMAP2_TUSB6010 + bool + depends on ARCH_OMAP2 && ARCH_OMAP2420 + default y if MACH_NOKIA_N800 \ No newline at end of file Index: linux-2.6/arch/arm/mach-omap2/Makefile =================================================================== --- linux-2.6.orig/arch/arm/mach-omap2/Makefile 2007-04-09 16:21:17.000000000 -0400 +++ linux-2.6/arch/arm/mach-omap2/Makefile 2007-04-09 16:21:18.000000000 -0400 @@ -16,4 +16,8 @@ obj-$(CONFIG_MACH_OMAP_GENERIC) += boar obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o +obj-$(CONFIG_MACH_NOKIA_N800) += board-n800.o board-n800-flash.o \ + board-n800-mmc.o board-n800-bt.o \ + board-n800-audio.o board-n800-usb.o \ + board-n800-dsp.o board-n800-pm.o Index: linux-2.6/arch/arm/mach-omap2/board-n800-audio.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-n800-audio.c 2007-04-09 16:21:18.000000000 -0400 @@ -0,0 +1,366 @@ +/* + * linux/arch/arm/mach-omap2/board-n800-audio.c + * + * Copyright (C) 2006 Nokia Corporation + * Contact: Juha Yrjola + * Jarkko Nikula <jarkko.nikula@nokia.com> + * + * 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. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/spi/tsc2301.h> + +#include <asm/io.h> +#include <asm/arch/eac.h> + +#include "../plat-omap/dsp/dsp_common.h" + +#if defined(CONFIG_SPI_TSC2301_AUDIO) && defined(CONFIG_SND_OMAP24XX_EAC) +#define AUDIO_ENABLED + +static struct clk *sys_clkout2; +static struct clk *func96m_clk; +static struct device *eac_device; +static struct device *tsc2301_device; + +static int enable_audio; +static int audio_ok; +static spinlock_t audio_lock; + +/* + * Leaving EAC and sys_clkout2 pins multiplexed to those subsystems results + * in about 2 mA extra current leak when audios are powered down. The + * workaround is to multiplex them to protected mode (with pull-ups enabled) + * whenever audio is not being used. + */ +static int eac_mux_disabled = 0; +static int clkout2_mux_disabled = 0; +static u32 saved_mux[2]; + +static void n800_enable_eac_mux(void) +{ + if (!eac_mux_disabled) + return; + __raw_writel(saved_mux[1], IO_ADDRESS(0x48000124)); + eac_mux_disabled = 0; +} + +static void n800_disable_eac_mux(void) +{ + if (eac_mux_disabled) { + WARN_ON(eac_mux_disabled); + return; + } + saved_mux[1] = __raw_readl(IO_ADDRESS(0x48000124)); + __raw_writel(0x1f1f1f1f, IO_ADDRESS(0x48000124)); + eac_mux_disabled = 1; +} + +static void n800_enable_clkout2_mux(void) +{ + if (!clkout2_mux_disabled) + return; + __raw_writel(saved_mux[0], IO_ADDRESS(0x480000e8)); + clkout2_mux_disabled = 0; +} + +static void n800_disable_clkout2_mux(void) +{ + u32 l; + + if (clkout2_mux_disabled) { + WARN_ON(clkout2_mux_disabled); + return; + } + saved_mux[0] = __raw_readl(IO_ADDRESS(0x480000e8)); + l = saved_mux[0] & ~0xff; + l |= 0x1f; + __raw_writel(l, IO_ADDRESS(0x480000e8)); + clkout2_mux_disabled = 1; +} + +static int n800_eac_enable_ext_clocks(struct device *dev) +{ + BUG_ON(tsc2301_device == NULL); + n800_enable_eac_mux(); + tsc2301_mixer_enable_mclk(tsc2301_device); + + return 0; +} + +static void n800_eac_disable_ext_clocks(struct device *dev) +{ + BUG_ON(tsc2301_device == NULL); + tsc2301_mixer_disable_mclk(tsc2301_device); + n800_disable_eac_mux(); +} + +static int n800_audio_set_power(void *pdata, int dac, int adc) +{ + BUG_ON(pdata != tsc2301_device); + tsc2301_mixer_set_power(tsc2301_device, dac, adc); + + return 0; +} + +static int n800_audio_register_controls(void *pdata, struct snd_card *card) +{ + BUG_ON(pdata != tsc2301_device); + return tsc2301_mixer_register_controls(tsc2301_device, card); +} + +static struct eac_codec n800_eac_codec = { + .mclk_src = EAC_MCLK_EXT_2x12288000, + .codec_mode = EAC_CODEC_I2S, + .codec_conf.i2s.polarity_changed_mode = 0, + .codec_conf.i2s.sync_delay_enable = 0, + .default_rate = 48000, + .set_power = n800_audio_set_power, + .register_controls = n800_audio_register_controls, + .short_name = "TSC2301", +}; + +static int n800_register_codec(void) +{ + int r, do_enable = 0; + unsigned long flags; + + n800_eac_codec.private_data = tsc2301_device; + r = eac_register_codec(eac_device, &n800_eac_codec); + if (r < 0) + return r; + spin_lock_irqsave(&audio_lock, flags); + audio_ok = 1; + if (enable_audio) + do_enable = 1; + spin_unlock_irqrestore(&audio_lock, flags); + if (do_enable) + eac_set_mode(eac_device, 1, 1); + return 0; +} + +static void n800_unregister_codec(void) +{ + audio_ok = 0; + eac_unregister_codec(eac_device); + eac_set_mode(eac_device, 0, 0); +} + +static int n800_eac_init(struct device *dev) +{ + int r; + + BUG_ON(eac_device != NULL); + eac_device = dev; + if (tsc2301_device != NULL) { + r = n800_register_codec(); + if (r < 0) + return r; + } + + return 0; +} + +static void n800_eac_cleanup(struct device *dev) +{ + eac_device = NULL; + if (tsc2301_device != NULL) + n800_unregister_codec(); +} + +static int n800_codec_get_clocks(struct device *dev) +{ + sys_clkout2 = clk_get(dev, "sys_clkout2"); + if (IS_ERR(sys_clkout2)) { + dev_err(dev, "Could not get sys_clkout2\n"); + return -ENODEV; + } + /* configure 12 MHz output on SYS_CLKOUT2. Therefore we must use + * 96 MHz as its parent in order to get 12 MHz */ + func96m_clk = clk_get(dev, "func_96m_ck"); + if (IS_ERR(func96m_clk)) { + dev_err(dev, "Could not get func 96M clock\n"); + clk_put(sys_clkout2); + return -ENODEV; + } + + clk_set_parent(sys_clkout2, func96m_clk); + clk_set_rate(sys_clkout2, 12000000); + + return 0; +} + +static void n800_codec_put_clocks(struct device *dev) +{ + clk_put(func96m_clk); + clk_put(sys_clkout2); +} + +static int n800_codec_enable_clock(struct device *dev) +{ + n800_enable_clkout2_mux(); + return clk_enable(sys_clkout2); +} + +static void n800_codec_disable_clock(struct device *dev) +{ + clk_disable(sys_clkout2); + n800_disable_clkout2_mux(); +} + +static int n800_codec_init(struct device *dev) +{ + int r; + + BUG_ON(tsc2301_device != NULL); + tsc2301_device = dev; + if ((r = n800_codec_get_clocks(dev)) < 0) + return r; + if (eac_device != NULL) { + r = n800_register_codec(); + if (r < 0) { + n800_codec_put_clocks(dev); + return r; + } + } + return 0; +} + +static void n800_codec_cleanup(struct device *dev) +{ + tsc2301_device = NULL; + if (eac_device != NULL) + n800_unregister_codec(); + n800_codec_put_clocks(dev); +} + +static struct eac_platform_data n800_eac_data = { + .init = n800_eac_init, + .cleanup = n800_eac_cleanup, + .enable_ext_clocks = n800_eac_enable_ext_clocks, + .disable_ext_clocks = n800_eac_disable_ext_clocks, +}; + +static const struct tsc2301_mixer_gpio n800_mixer_gpios[] = { + { + .name = "Headset Amplifier", + .gpio = 1, + .deactivate_on_pd = 1, + }, { + .name = "Speaker Amplifier", + .gpio = 2, + .def_enable = 1, + .deactivate_on_pd = 1, + }, { + .name = "Headset Mic Select", + .gpio = 3, + } +}; + +static struct platform_device retu_headset_device = { + .name = "retu-headset", + .id = -1, + .dev = { + .release = NULL, + }, +}; + +void __init n800_audio_init(struct tsc2301_platform_data *tc) +{ + spin_lock_init(&audio_lock); + + if (platform_device_register(&retu_headset_device) < 0) + return; + omap_init_eac(&n800_eac_data); + + tc->pll_pdc = 7; + tc->pll_a = 7; + tc->pll_n = 9; + tc->pll_output = 1; + tc->mclk_ratio = TSC2301_MCLK_256xFS; + tc->i2s_sample_rate = TSC2301_I2S_SR_48000; + tc->i2s_format = TSC2301_I2S_FORMAT0; + tc->power_down_blocks = TSC2301_REG_PD_MISC_MOPD; + tc->mixer_gpios = n800_mixer_gpios; + tc->n_mixer_gpios = ARRAY_SIZE(n800_mixer_gpios); + tc->codec_init = n800_codec_init; + tc->codec_cleanup = n800_codec_cleanup; + tc->enable_clock = n800_codec_enable_clock; + tc->disable_clock = n800_codec_disable_clock; +} + +#else + +void __init n800_audio_init(void) +{ +} + +#endif + +#ifdef CONFIG_OMAP_DSP + +int n800_audio_enable(struct dsp_kfunc_device *kdev, int stage) +{ +#ifdef AUDIO_ENABLED + unsigned long flags; + int do_enable = 0; + + spin_lock_irqsave(&audio_lock, flags); + + pr_debug("DSP power up request (audio codec %sinitialized)\n", + audio_ok ? "" : "not "); + + if (enable_audio) + goto out; + enable_audio = 1; + if (audio_ok) + do_enable = 1; +out: + spin_unlock_irqrestore(&audio_lock, flags); + if (do_enable) + eac_set_mode(eac_device, 1, 1); +#endif + return 0; +} + +int n800_audio_disable(struct dsp_kfunc_device *kdev, int stage) +{ +#ifdef AUDIO_ENABLED + unsigned long flags; + int do_disable = 0; + + spin_lock_irqsave(&audio_lock, flags); + + pr_debug("DSP power down request (audio codec %sinitialized)\n", + audio_ok ? "" : "not "); + + if (!enable_audio) + goto out; + enable_audio = 0; + if (audio_ok) + do_disable = 1; +out: + spin_unlock_irqrestore(&audio_lock, flags); + if (do_disable) + eac_set_mode(eac_device, 0, 0); +#endif + return 0; +} + +#endif /* CONFIG_OMAP_DSP */ Index: linux-2.6/arch/arm/mach-omap2/board-n800-bt.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-n800-bt.c 2007-04-09 16:21:18.000000000 -0400 @@ -0,0 +1,42 @@ +/* + * Nokia N800 platform-specific data for Bluetooth + * + * Copyright (C) 2005, 2006 Nokia Corporation + * Contact: Ville Tervo <ville.tervo@nokia.com> + * + * 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. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <asm/arch/board.h> + +static struct platform_device n800_bt_device = { + .name = "hci_h4p", + .id = -1, + .num_resources = 0, +}; + +void __init n800_bt_init(void) +{ + const struct omap_bluetooth_config *bt_config; + + bt_config = (void *) omap_get_config(OMAP_TAG_NOKIA_BT, + struct omap_bluetooth_config); + n800_bt_device.dev.platform_data = (void *) bt_config; + if (platform_device_register(&n800_bt_device) < 0) + BUG(); +} + Index: linux-2.6/arch/arm/mach-omap2/board-n800-dsp.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-n800-dsp.c 2007-04-09 16:21:18.000000000 -0400 @@ -0,0 +1,156 @@ +/* + * linux/arch/arm/mach-omap2/board-n800-dsp.c + * + * Copyright (C) 2006 Nokia Corporation. + * + * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> + * + * 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. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/list.h> +#include <linux/err.h> +#include <linux/clk.h> + +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/board.h> + +#include "../plat-omap/dsp/dsp_common.h" + +#if defined(CONFIG_OMAP_DSP) + +/* + * dsp peripheral device: AUDIO + */ +static struct dsp_kfunc_device n800_audio_device = { + .name = "audio", + .type = DSP_KFUNC_DEV_TYPE_AUDIO, + .enable = n800_audio_enable, + .disable = n800_audio_disable, +}; + +/* + * dsp peripheral device: TIMER + */ +static int dsp_timer_probe(struct dsp_kfunc_device *kdev) +{ + char clockname[20]; + + strcpy(clockname, kdev->name); + strcat(clockname, "_fck"); + + kdev->fck = clk_get(NULL, clockname); + if (IS_ERR(kdev->fck)) { + printk(KERN_ERR "couldn't acquire %s\n", clockname); + return PTR_ERR(kdev->fck); + } + pr_debug("%s probed successfully\n", clockname); + + strcpy(clockname, kdev->name); + strcat(clockname, "_ick"); + kdev->ick = clk_get(NULL, clockname); + if (IS_ERR(kdev->ick)) { + printk(KERN_ERR "couldn't acquire %s\n", clockname); + goto fail; + } + pr_debug("%s probed successfully\n", clockname); + + return 0; + fail: + clk_put(kdev->fck); + + return PTR_ERR(kdev->ick); +} + +static int dsp_timer_remove(struct dsp_kfunc_device *kdev) +{ + clk_put(kdev->ick); + clk_put(kdev->fck); + pr_debug("%s removed successfully\n", kdev->name); + return 0; +} + +static int dsp_timer_enable(struct dsp_kfunc_device *kdev, int stage) +{ + pr_debug("%s enabled(%d)\n", kdev->name, stage); + + mutex_lock(&kdev->lock); + + if (kdev->enabled) + goto out; + kdev->enabled = 1; + + clk_enable(kdev->fck); + clk_enable(kdev->ick); + out: + mutex_unlock(&kdev->lock); + + return 0; +} + +static int dsp_timer_disable(struct dsp_kfunc_device *kdev, int stage) +{ + pr_debug("%s disabled(%d)\n", kdev->name, stage); + + mutex_lock(&kdev->lock); + + if (kdev->enabled == 0) + goto out; + kdev->enabled = 0; + + clk_disable(kdev->ick); + clk_disable(kdev->fck); + out: + mutex_unlock(&kdev->lock); + + return 0; +} + +static struct dsp_kfunc_device n800_timer_device = { + .name = "gpt5", + .type = DSP_KFUNC_DEV_TYPE_COMMON, + .probe = dsp_timer_probe, + .remove = dsp_timer_remove, + .enable = dsp_timer_enable, + .disable = dsp_timer_disable, +}; + +static struct dsp_kfunc_device *n800_kfunc_dev[] = { + &n800_audio_device, + &n800_timer_device, +}; + +void __init n800_dsp_init(void) +{ + int i, ret; + struct dsp_kfunc_device **p = n800_kfunc_dev; + + for (i = 0; i < ARRAY_SIZE(n800_kfunc_dev); i++) { + ret = dsp_kfunc_device_register(p[i]); + if (ret) { + printk(KERN_ERR + "KFUNC device registration failed: %s\n", + p[i]->name); + } + } +} + +#else +void __init n800_dsp_init(void) { } +#endif /* CONFIG_OMAP_DSP */ Index: linux-2.6/arch/arm/mach-omap2/board-n800-flash.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-n800-flash.c 2007-04-09 16:21:18.000000000 -0400 @@ -0,0 +1,156 @@ +/* + * linux/arch/arm/mach-omap2/board-n800-flash.c + * + * Copyright (C) 2006 Nokia Corporation + * Author: Juha Yrjola + * + * 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/platform_device.h> +#include <asm/mach/flash.h> +#include <linux/mtd/onenand_regs.h> + +#include <asm/io.h> +#include <asm/arch/onenand.h> +#include <asm/arch/board.h> +#include <asm/arch/gpmc.h> + +static struct mtd_partition n800_partitions[8]; + +static int n800_onenand_setup(void __iomem *); + +static struct omap_onenand_platform_data n800_onenand_data = { + .cs = 0, + .gpio_irq = 26, + .parts = n800_partitions, + .nr_parts = 0, /* filled later */ + .onenand_setup = n800_onenand_setup, +}; + +static struct platform_device n800_onenand_device = { + .name = "omap2-onenand", + .id = -1, + .dev = { + .platform_data = &n800_onenand_data, + }, +}; + +static unsigned short omap2_onenand_readw(void __iomem *addr) +{ + return readw(addr); +} + +static void omap2_onenand_writew(unsigned short value, void __iomem *addr) +{ + writew(value, addr); +} + +static int omap2_onenand_set_sync_mode(int cs, void __iomem *onenand_base) +{ + const int min_gpmc_clk_period = 18; + struct gpmc_timings t; + int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency; + u32 reg; + + tick_ns = gpmc_round_ns_to_ticks(1); + div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period); + gpmc_clk_ns = div * tick_ns; + if (gpmc_clk_ns >= 24) + latency = 3; + else + latency = 4; + + /* Configure OneNAND for sync read */ + reg = omap2_onenand_readw(onenand_base + ONENAND_REG_SYS_CFG1); + reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9)); + reg |= (latency << ONENAND_SYS_CFG1_BRL_SHIFT) | + ONENAND_SYS_CFG1_SYNC_READ | + ONENAND_SYS_CFG1_BL_16; + omap2_onenand_writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); + + /* FIXME: Get timings from platform data */ + /* Set syncronous read timings */ + memset(&t, 0, sizeof(t)); + t.sync_clk = min_gpmc_clk_period; + t.cs_on = 0; + t.adv_on = gpmc_round_ns_to_ticks(7); + fclk_offset_ns = t.adv_on + gpmc_round_ns_to_ticks(7); + fclk_offset = fclk_offset_ns / gpmc_round_ns_to_ticks(1); + t.page_burst_access = gpmc_clk_ns; + + /* Read */ + t.adv_rd_off = fclk_offset_ns + gpmc_round_ns_to_ticks(7); + t.oe_on = t.adv_rd_off; + t.access = fclk_offset_ns + (latency + 1) * gpmc_clk_ns; + t.oe_off = t.access + gpmc_round_ns_to_ticks(1); + t.cs_rd_off = t.oe_off; + t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(17); + + /* Write */ + t.adv_wr_off = t.adv_on + gpmc_round_ns_to_ticks(12); + t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(1); + t.we_off = t.we_on + gpmc_round_ns_to_ticks(40); + t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(1); + t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(1); + + /* Configure GPMC for synchronous read */ + fclk_offset %= div; + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, + GPMC_CONFIG1_WRAPBURST_SUPP | + GPMC_CONFIG1_READMULTIPLE_SUPP | + GPMC_CONFIG1_READTYPE_SYNC | + GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) | + GPMC_CONFIG1_PAGE_LEN(2) | + GPMC_CONFIG1_WAIT_READ_MON | + GPMC_CONFIG1_WAIT_PIN_SEL(0) | + GPMC_CONFIG1_DEVICESIZE_16 | + GPMC_CONFIG1_DEVICETYPE_NOR | + GPMC_CONFIG1_MUXADDDATA); + + return gpmc_cs_set_timings(cs, &t); +} + +static int n800_onenand_setup(void __iomem *onenand_base) +{ + struct omap_onenand_platform_data *datap = &n800_onenand_data; + struct device *dev = &n800_onenand_device.dev; + + /* Set sync timings in GPMC */ + if (omap2_onenand_set_sync_mode(datap->cs, onenand_base) < 0) { + dev_err(dev, "Unable to set synchronous mode\n"); + return -EINVAL; + } + + return 0; +} + +void __init n800_flash_init(void) +{ + const struct omap_partition_config *part; + int i = 0; + + while ((part = omap_get_nr_config(OMAP_TAG_PARTITION, + struct omap_partition_config, i)) != NULL) { + struct mtd_partition *mpart; + + mpart = n800_partitions + i; + mpart->name = (char *) part->name; + mpart->size = part->size; + mpart->offset = part->offset; + mpart->mask_flags = part->mask_flags; + i++; + if (i == ARRAY_SIZE(n800_partitions)) { + printk(KERN_ERR "Too many partitions supplied\n"); + return; + } + } + n800_onenand_data.nr_parts = i; + if (platform_device_register(&n800_onenand_device) < 0) { + printk(KERN_ERR "Unable to register OneNAND device\n"); + return; + } +} Index: linux-2.6/arch/arm/mach-omap2/board-n800-mmc.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-n800-mmc.c 2007-04-09 16:21:18.000000000 -0400 @@ -0,0 +1,282 @@ +/* + * linux/arch/arm/mach-omap2/board-n800-mmc.c + * + * Copyright (C) 2006 Nokia Corporation + * Author: Juha Yrjola + * + * 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 <asm/arch/mmc.h> +#include <asm/arch/menelaus.h> +#include <asm/arch/gpio.h> + +#ifdef CONFIG_MMC_OMAP + +static const int slot_switch_gpio = 96; +static const int slot1_wp_gpio = 23; +static const int slot2_wp_gpio = 8; +static int slot1_cover_closed; +static int slot2_cover_closed; +static struct device *mmc_device; + +/* + * VMMC --> slot 1 + * VDCDC3_APE, VMCS2_APE --> slot 2 + * GPIO96 --> Menelaus GPIO2 + */ + +static int n800_mmc_switch_slot(struct device *dev, int slot) +{ +#ifdef CONFIG_MMC_DEBUG + dev_dbg(dev, "Choose slot %d\n", slot + 1); +#endif + if (slot == 0) + omap_set_gpio_dataout(slot_switch_gpio, 0); + else + omap_set_gpio_dataout(slot_switch_gpio, 1); + return 0; +} + +static int n800_mmc_set_power(struct device *dev, int slot, int power_on, + int vdd) +{ + int mV; + +#ifdef CONFIG_MMC_DEBUG + dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1, + power_on ? "on" : "off", vdd); +#endif + if (slot == 0) { + if (!power_on) + return menelaus_set_vmmc(0); + switch (1 << vdd) { + case MMC_VDD_33_34: + case MMC_VDD_32_33: + case MMC_VDD_31_32: + mV = 3100; + break; + case MMC_VDD_30_31: + mV = 3000; + break; + case MMC_VDD_28_29: + mV = 2800; + break; + case MMC_VDD_18_19: + mV = 1850; + break; + default: + BUG(); + } + return menelaus_set_vmmc(mV); + } else { + if (!power_on) + return menelaus_set_vdcdc(3, 0); + switch (1 << vdd) { + case MMC_VDD_33_34: + case MMC_VDD_32_33: + mV = 3300; + break; + case MMC_VDD_30_31: + case MMC_VDD_29_30: + mV = 3000; + break; + case MMC_VDD_28_29: + case MMC_VDD_27_28: + mV = 2800; + break; + case MMC_VDD_24_25: + case MMC_VDD_23_24: + mV = 2400; + break; + case MMC_VDD_22_23: + case MMC_VDD_21_22: + mV = 2200; + break; + case MMC_VDD_20_21: + case MMC_VDD_19_20: + mV = 2000; + break; + case MMC_VDD_18_19: + case MMC_VDD_17_18: + mV = 1800; + break; + case MMC_VDD_150_155: + case MMC_VDD_145_150: + mV = 1500; + break; + default: + BUG(); + } + return menelaus_set_vdcdc(3, mV); + } + return 0; +} + +static int n800_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode) +{ + int r; + +#ifdef CONFIG_MMC_DEBUG + dev_dbg(dev, "Set slot %d bus mode %s\n", slot + 1, + bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull"); +#endif + BUG_ON(slot != 0 && slot != 1); + slot++; + switch (bus_mode) { + case MMC_BUSMODE_OPENDRAIN: + r = menelaus_set_mmc_opendrain(slot, 1); + break; + case MMC_BUSMODE_PUSHPULL: + r = menelaus_set_mmc_opendrain(slot, 0); + break; + default: + BUG(); + } + if (r != 0 && printk_ratelimit()) + dev_err(dev, "MMC: unable to set bus mode for slot %d\n", + slot); + return r; +} + +#if 0 +static int n800_mmc_get_ro(struct device *dev, int slot) +{ + int ro; + + slot++; + if (slot == 1) + ro = omap_get_gpio_datain(slot1_wp_gpio); + else + ro = omap_get_gpio_datain(slot2_wp_gpio); +#ifdef CONFIG_MMC_DEBUG + dev_dbg(dev, "Get RO slot %d: %s\n", + slot, ro ? "read-only" : "read-write"); +#endif + return ro; +} +#endif + +static int n800_mmc_get_cover_state(struct device *dev, int slot) +{ + slot++; + BUG_ON(slot != 1 && slot != 2); + if (slot == 1) + return slot1_cover_closed; + else + return slot2_cover_closed; +} + +static void n800_mmc_callback(void *data, u8 card_mask) +{ + if (card_mask & (1 << 1)) + slot2_cover_closed = 0; + else + slot2_cover_closed = 1; + omap_mmc_notify_cover_event(mmc_device, 1, slot2_cover_closed); +} + +void n800_mmc_slot1_cover_handler(void *arg, int state) +{ + if (mmc_device == NULL) + return; + + slot1_cover_closed = state; + omap_mmc_notify_cover_event(mmc_device, 0, state); +} + +static int n800_mmc_late_init(struct device *dev) +{ + int r; + + mmc_device = dev; + + r = menelaus_set_slot_sel(1); + if (r < 0) + return r; + + r = menelaus_set_mmc_slot(1, 1, 0, 1); + if (r < 0) + return r; + r = menelaus_set_mmc_slot(2, 1, 0, 1); + if (r < 0) + return r; + + r = menelaus_get_slot_pin_states(); + if (r < 0) + return r; + + if (r & (1 << 1)) + slot2_cover_closed = 1; + else + slot2_cover_closed = 0; + + r = menelaus_register_mmc_callback(n800_mmc_callback, NULL); + + return r; +} + +static void n800_mmc_cleanup(struct device *dev) +{ + menelaus_unregister_mmc_callback(); +} + +static struct omap_mmc_platform_data n800_mmc_data = { + .enabled = 1, + .nr_slots = 2, + .wire4 = 1, + .switch_slot = n800_mmc_switch_slot, + .init = n800_mmc_late_init, + .cleanup = n800_mmc_cleanup, + .slots[0] = { + .set_power = n800_mmc_set_power, + .set_bus_mode = n800_mmc_set_bus_mode, + .get_ro = NULL, + .get_cover_state= n800_mmc_get_cover_state, + .ocr_mask = MMC_VDD_18_19 | MMC_VDD_28_29 | MMC_VDD_30_31 | + MMC_VDD_32_33 | MMC_VDD_33_34, + .name = "internal", + }, + .slots[1] = { + .set_power = n800_mmc_set_power, + .set_bus_mode = n800_mmc_set_bus_mode, + .get_ro = NULL, + .get_cover_state= n800_mmc_get_cover_state, + .ocr_mask = MMC_VDD_150_155 | MMC_VDD_145_150 | MMC_VDD_17_18 | + MMC_VDD_18_19 | MMC_VDD_19_20 | MMC_VDD_20_21 | + MMC_VDD_21_22 | MMC_VDD_22_23 | MMC_VDD_23_24 | + MMC_VDD_24_25 | MMC_VDD_27_28 | MMC_VDD_28_29 | + MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_32_33 | + MMC_VDD_33_34, + .name = "external", + }, +}; + +void __init n800_mmc_init(void) +{ + omap_set_mmc_info(1, &n800_mmc_data); + if (omap_request_gpio(slot_switch_gpio) < 0) + BUG(); + omap_set_gpio_dataout(slot_switch_gpio, 0); + omap_set_gpio_direction(slot_switch_gpio, 0); + if (omap_request_gpio(slot1_wp_gpio) < 0) + BUG(); + if (omap_request_gpio(slot2_wp_gpio) < 0) + BUG(); + omap_set_gpio_direction(slot1_wp_gpio, 1); + omap_set_gpio_direction(slot2_wp_gpio, 1); +} + +#else + +void __init n800_mmc_init(void) +{ +} + +void n800_mmc_slot1_cover_handler(void *arg, int state) +{ +} + +#endif Index: linux-2.6/arch/arm/mach-omap2/board-n800-pm.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-n800-pm.c 2007-04-09 16:21:18.000000000 -0400 @@ -0,0 +1,79 @@ +/* + * Nokia N800 PM code + * + * Copyright (C) 2006 Nokia Corporation + * Author: Amit Kucheria <amit.kucheria@nokia.com> + * + * 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/module.h> +#include <asm/arch/menelaus.h> + +#ifdef CONFIG_MENELAUS + +static int n800_auto_sleep_regulators(void) +{ + u32 val; + int ret; + + val = EN_VPLL_SLEEP | EN_VMMC_SLEEP \ + | EN_VAUX_SLEEP | EN_VIO_SLEEP \ + | EN_VMEM_SLEEP | EN_DC3_SLEEP \ + | EN_VC_SLEEP | EN_DC2_SLEEP; + + ret = menelaus_set_regulator_sleep(1, val); + if (ret < 0) { + printk(KERN_ERR "Could not set regulators to sleep on " + "menelaus: %u\n", ret); + return ret; + } + return 0; +} + +static int n800_auto_voltage_scale(void) +{ + int ret; + + ret = menelaus_set_vcore_hw(1400, 1050); + if (ret < 0) { + printk(KERN_ERR "Could not set VCORE voltage on " + "menelaus: %u\n", ret); + return ret; + } + return 0; +} + +static int n800_menelaus_init(struct device *dev) +{ + int ret; + + ret = n800_auto_voltage_scale(); + if (ret < 0) + return ret; + ret = n800_auto_sleep_regulators(); + if (ret < 0) + return ret; + return 0; +} + +static struct menelaus_platform_data n800_menelaus_platform_data = { + .late_init = n800_menelaus_init, +}; + +void __init n800_pm_init(void) +{ + menelaus_set_platform_data(&n800_menelaus_platform_data); +} + +#else + +void __init n800_pm_init(void) +{ +} + +#endif + Index: linux-2.6/arch/arm/mach-omap2/board-n800-usb.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-n800-usb.c 2007-04-09 16:21:18.000000000 -0400 @@ -0,0 +1,102 @@ +/* + * linux/arch/arm/mach-omap2/board-n800-usb.c + * + * Copyright (C) 2006 Nokia Corporation + * Author: Juha Yrjola + * + * 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/types.h> +#include <linux/errno.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/usb/musb.h> +#include <asm/arch/gpmc.h> +#include <asm/arch/gpio.h> + +#define TUSB_ASYNC_CS 1 +#define TUSB_SYNC_CS 4 +#define GPIO_TUSB_INT 58 +#define GPIO_TUSB_ENABLE 0 + +static int tusb_set_power(int state); + +#if defined(CONFIG_USB_MUSB_OTG) +# define BOARD_MODE MUSB_OTG +#elif defined(CONFIG_USB_MUSB_PERIPHERAL) +# define BOARD_MODE MUSB_PERIPHERAL +#else /* defined(CONFIG_USB_MUSB_HOST) */ +# define BOARD_MODE MUSB_HOST +#endif + +static struct musb_hdrc_platform_data tusb_data = { + .mode = BOARD_MODE, + .multipoint = 1, + .set_power = tusb_set_power, + .min_power = 25, /* x2 = 50 mA drawn from VBUS as peripheral */ +}; + +/* + * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and + * 1.5 V voltage regulators of PM companion chip. Companion chip will then + * provide then PGOOD signal to TUSB6010 which will release it from reset. + */ +static int tusb_set_power(int state) +{ + int i, retval = 0; + + if (state) { + omap_set_gpio_dataout(GPIO_TUSB_ENABLE, 1); + msleep(1); + + /* Wait until TUSB6010 pulls INT pin down */ + i = 100; + while (i && omap_get_gpio_datain(GPIO_TUSB_INT)) { + msleep(1); + i--; + } + + if (!i) { + printk(KERN_ERR "tusb: powerup failed\n"); + retval = -ENODEV; + } + } else { + omap_set_gpio_dataout(GPIO_TUSB_ENABLE, 0); + msleep(10); + } + + return retval; +} + +void __init n800_usb_init(void) +{ + int ret = 0; + static char announce[] __initdata = KERN_INFO "TUSB 6010\n"; + + /* PM companion chip power control pin */ + ret = omap_request_gpio(GPIO_TUSB_ENABLE); + if (ret != 0) { + printk(KERN_ERR "Could not get TUSB power GPIO%i\n", + GPIO_TUSB_ENABLE); + return; + } + omap_set_gpio_direction(GPIO_TUSB_ENABLE, 0); + + tusb_set_power(0); + + ret = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2, + TUSB_ASYNC_CS, TUSB_SYNC_CS, + GPIO_TUSB_INT, 0x3f); + if (ret != 0) + goto err; + + printk(announce); + + return; + +err: + omap_free_gpio(GPIO_TUSB_ENABLE); +} Index: linux-2.6/arch/arm/mach-omap2/board-n800.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-n800.c 2007-04-09 16:21:18.000000000 -0400 @@ -0,0 +1,515 @@ +/* + * linux/arch/arm/mach-omap2/board-n800.c + * + * Copyright (C) 2005 Nokia Corporation + * Author: Juha Yrjola <juha.yrjola@nokia.com> + * + * Modified from mach-omap2/board-generic.c + * + * 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/clk.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/spi/spi.h> +#include <linux/spi/tsc2301.h> +#include <linux/input.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <asm/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/arch/gpio.h> +#include <asm/arch/usb.h> +#include <asm/arch/board.h> +#include <asm/arch/common.h> +#include <asm/arch/mcspi.h> +#include <asm/arch/menelaus.h> +#include <asm/arch/lcd_mipid.h> +#include <asm/arch/clock.h> +#include <asm/arch/gpio-switch.h> +#include <asm/arch/omapfb.h> +#include <asm/arch/blizzard.h> + +#include <../drivers/cbus/tahvo.h> + +#define N800_BLIZZARD_POWERDOWN_GPIO 15 +#define N800_STI_GPIO 62 +#define N800_CAM_SENSOR_RESET_GPIO 53 +#define N800_KEYB_IRQ_GPIO 109 + +static void __init nokia_n800_init_irq(void) +{ + omap2_init_common_hw(); + omap_init_irq(); + omap_gpio_init(); + +#ifdef CONFIG_OMAP_STI + if (omap_request_gpio(N800_STI_GPIO) < 0) { + printk(KERN_ERR "Failed to request GPIO %d for STI\n", + N800_STI_GPIO); + return; + } + + omap_set_gpio_direction(N800_STI_GPIO, 0); + omap_set_gpio_dataout(N800_STI_GPIO, 0); +#endif +} + +#if defined(CONFIG_MENELAUS) && defined(CONFIG_SENSORS_TMP105) + +static int n800_tmp105_set_power(int enable) +{ + return menelaus_set_vaux(enable ? 2800 : 0); +} + +#else + +#define n800_tmp105_set_power NULL + +#endif + +static struct omap_uart_config n800_uart_config __initdata = { + .enabled_uarts = (1 << 0) | (1 << 2), +}; + +#include "../../../drivers/cbus/retu.h" + +static struct omap_fbmem_config n800_fbmem0_config __initdata = { + .size = 752 * 1024, +}; + +static struct omap_fbmem_config n800_fbmem1_config __initdata = { + .size = 752 * 1024, +}; + +static struct omap_fbmem_config n800_fbmem2_config __initdata = { + .size = 752 * 1024, +}; + +static struct omap_tmp105_config n800_tmp105_config __initdata = { + .tmp105_irq_pin = 125, + .set_power = n800_tmp105_set_power, +}; + +static void mipid_shutdown(struct mipid_platform_data *pdata) +{ + if (pdata->nreset_gpio != -1) { + pr_info("shutdown LCD\n"); + omap_set_gpio_dataout(pdata->nreset_gpio, 0); + msleep(120); + } +} + +static struct mipid_platform_data n800_mipid_platform_data = { + .shutdown = mipid_shutdown, +}; + +static void __init mipid_dev_init(void) +{ + const struct omap_lcd_config *conf; + + conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); + if (conf != NULL) { + n800_mipid_platform_data.nreset_gpio = conf->nreset_gpio; + n800_mipid_platform_data.data_lines = conf->data_lines; + } +} + +static struct { + struct clk *sys_ck; +} blizzard; + +static int blizzard_get_clocks(void) +{ + blizzard.sys_ck = clk_get(0, "osc_ck"); + if (IS_ERR(blizzard.sys_ck)) { + printk(KERN_ERR "can't get Blizzard clock\n"); + return PTR_ERR(blizzard.sys_ck); + } + return 0; +} + +static unsigned long blizzard_get_clock_rate(struct device *dev) +{ + return clk_get_rate(blizzard.sys_ck); +} + +static void blizzard_enable_clocks(int enable) +{ + if (enable) + clk_enable(blizzard.sys_ck); + else + clk_disable(blizzard.sys_ck); +} + +static void blizzard_power_up(struct device *dev) +{ + /* Vcore to 1.475V */ + tahvo_set_clear_reg_bits(0x07, 0, 0xf); + msleep(10); + + blizzard_enable_clocks(1); + omap_set_gpio_dataout(N800_BLIZZARD_POWERDOWN_GPIO, 1); +} + +static void blizzard_power_down(struct device *dev) +{ + omap_set_gpio_dataout(N800_BLIZZARD_POWERDOWN_GPIO, 0); + blizzard_enable_clocks(0); + + /* Vcore to 1.005V */ + tahvo_set_clear_reg_bits(0x07, 0xf, 0); +} + +static struct blizzard_platform_data n800_blizzard_data = { + .power_up = blizzard_power_up, + .power_down = blizzard_power_down, + .get_clock_rate = blizzard_get_clock_rate, + .te_connected = 1, +}; + +static void __init blizzard_dev_init(void) +{ + int r; + + r = omap_request_gpio(N800_BLIZZARD_POWERDOWN_GPIO); + if (r < 0) + return; + omap_set_gpio_direction(N800_BLIZZARD_POWERDOWN_GPIO, 0); + omap_set_gpio_dataout(N800_BLIZZARD_POWERDOWN_GPIO, 1); + + blizzard_get_clocks(); + omapfb_set_ctrl_platform_data(&n800_blizzard_data); +} + +#if defined(CONFIG_CBUS_RETU) && defined(CONFIG_VIDEO_CAMERA_SENSOR_TCM825X) && \ + defined(CONFIG_MENELAUS) +#define SUPPORT_SENSOR +#endif + +#ifdef SUPPORT_SENSOR + +static int sensor_okay; + +/* + * VSIM1 --> CAM_IOVDD --> IOVDD (1.8 V) + */ +static int tcm825x_sensor_power_on(void *data) +{ + int ret; + + if (!sensor_okay) + return -ENODEV; + + /* Set VMEM to 1.5V and VIO to 2.5V */ + ret = menelaus_set_vmem(1500); + if (ret < 0) { + /* Try once more, it seems the sensor power up causes + * some problems on the I2C bus. */ + ret = menelaus_set_vmem(1500); + if (ret < 0) + return ret; + } + msleep(1); + + ret = menelaus_set_vio(2500); + if (ret < 0) + return ret; + + /* Set VSim1 on */ + retu_write_reg(RETU_REG_CTRL_SET, 0x0080); + msleep(100); + + omap_set_gpio_dataout(N800_CAM_SENSOR_RESET_GPIO, 1); + msleep(1); + + return 0; +} + +static int tcm825x_sensor_power_off(void * data) +{ + int ret; + + omap_set_gpio_dataout(N800_CAM_SENSOR_RESET_GPIO, 0); + msleep(1); + + /* Set VSim1 off */ + retu_write_reg(RETU_REG_CTRL_CLR, 0x0080); + msleep(1); + + /* Set VIO_MODE to off */ + ret = menelaus_set_vio(0); + if (ret < 0) + return ret; + msleep(1); + + /* Set VMEM_MODE to off */ + ret = menelaus_set_vmem(0); + if (ret < 0) + return ret; + msleep(1); + + return 0; +} + +static struct omap_camera_sensor_config n800_sensor_config = { + .power_on = tcm825x_sensor_power_on, + .power_off = tcm825x_sensor_power_off, +}; + +static void __init n800_cam_init(void) +{ + int r; + + r = omap_request_gpio(N800_CAM_SENSOR_RESET_GPIO); + if (r < 0) + return; + + omap_set_gpio_dataout(N800_CAM_SENSOR_RESET_GPIO, 0); + omap_set_gpio_direction(N800_CAM_SENSOR_RESET_GPIO, 0); + + sensor_okay = 1; +} + +#else + +static inline void n800_cam_init(void) {} + +#endif + +static struct omap_board_config_kernel n800_config[] = { + { OMAP_TAG_UART, &n800_uart_config }, +#ifdef SUPPORT_SENSOR + { OMAP_TAG_CAMERA_SENSOR, &n800_sensor_config }, +#endif + { OMAP_TAG_FBMEM, &n800_fbmem0_config }, + { OMAP_TAG_FBMEM, &n800_fbmem1_config }, + { OMAP_TAG_FBMEM, &n800_fbmem2_config }, + { OMAP_TAG_TMP105, &n800_tmp105_config }, +}; + + +static int n800_get_keyb_irq_state(struct device *dev) +{ + return !omap_get_gpio_datain(N800_KEYB_IRQ_GPIO); +} + +static struct tsc2301_platform_data tsc2301_config = { + .reset_gpio = 118, + .dav_gpio = 103, + .pen_int_gpio = 106, + .keymap = { + -1, /* Event for bit 0 */ + KEY_UP, /* Event for bit 1 (up) */ + KEY_F5, /* Event for bit 2 (home) */ + -1, /* Event for bit 3 */ + KEY_LEFT, /* Event for bit 4 (left) */ + KEY_ENTER, /* Event for bit 5 (enter) */ + KEY_RIGHT, /* Event for bit 6 (right) */ + -1, /* Event for bit 7 */ + KEY_ESC, /* Event for bit 8 (cycle) */ + KEY_DOWN, /* Event for bit 9 (down) */ + KEY_F4, /* Event for bit 10 (menu) */ + -1, /* Event for bit 11 */ + KEY_F8, /* Event for bit 12 (Zoom-) */ + KEY_F6, /* Event for bit 13 (FS) */ + KEY_F7, /* Event for bit 14 (Zoom+) */ + -1, /* Event for bit 15 */ + }, + .kp_rep = 0, + .get_keyb_irq_state = n800_get_keyb_irq_state, +}; + +static void tsc2301_dev_init(void) +{ + int gpio = N800_KEYB_IRQ_GPIO; + + if (omap_request_gpio(gpio) < 0) { + printk(KERN_ERR "can't get KBIRQ GPIO\n"); + return; + } + omap_set_gpio_direction(gpio, 1); + tsc2301_config.keyb_int = OMAP_GPIO_IRQ(gpio); +} + +static struct omap2_mcspi_device_config tsc2301_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, +}; + +static struct omap2_mcspi_device_config mipid_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, +}; + +static struct omap2_mcspi_device_config cx3110x_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, +}; + +static struct spi_board_info n800_spi_board_info[] __initdata = { + [0] = { + .modalias = "lcd_mipid", + .bus_num = 1, + .chip_select = 1, + .max_speed_hz = 4000000, + .controller_data= &mipid_mcspi_config, + .platform_data = &n800_mipid_platform_data, + }, [1] = { + .modalias = "cx3110x", + .bus_num = 2, + .chip_select = 0, + .max_speed_hz = 48000000, + .controller_data= &cx3110x_mcspi_config, + }, [2] = { + .modalias = "tsc2301", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 6000000, + .controller_data= &tsc2301_mcspi_config, + .platform_data = &tsc2301_config, + }, +}; + +#if defined(CONFIG_CBUS_RETU) && defined(CONFIG_LEDS_OMAP_PWM) + +void retu_keypad_led_set_power(struct omap_pwm_led_platform_data *self, + int on_off) +{ + if (on_off) { + retu_write_reg(RETU_REG_CTRL_SET, 1 << 6); + msleep(2); + retu_write_reg(RETU_REG_CTRL_SET, 1 << 3); + } else { + retu_write_reg(RETU_REG_CTRL_CLR, (1 << 6) | (1 << 3)); + } +} + +static struct omap_pwm_led_platform_data n800_keypad_led_data = { + .name = "keypad", + .intensity_timer = 10, + .blink_timer = 9, + .set_power = retu_keypad_led_set_power, +}; + +static struct platform_device n800_keypad_led_device = { + .name = "omap_pwm_led", + .id = -1, + .dev = { + .platform_data = &n800_keypad_led_data, + }, +}; +#endif + +#if defined(CONFIG_TOUCHSCREEN_TSC2301) +static void __init n800_ts_set_config(void) +{ + const struct omap_lcd_config *conf; + + conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); + if (conf != NULL) { + if (strcmp(conf->panel_name, "lph8923") == 0) { + tsc2301_config.ts_x_plate_ohm = 180; + tsc2301_config.ts_hw_avg = 4; + tsc2301_config.ts_ignore_last = 1; + tsc2301_config.ts_max_pressure = 255; + tsc2301_config.ts_stab_time = 100; + } else if (strcmp(conf->panel_name, "ls041y3") == 0) { + tsc2301_config.ts_x_plate_ohm = 280; + tsc2301_config.ts_hw_avg = 16; + tsc2301_config.ts_touch_pressure= 215; + tsc2301_config.ts_max_pressure = 255; + tsc2301_config.ts_ignore_last = 1; + } else { + printk(KERN_ERR "Unknown panel type, set default " + "touchscreen configuration\n"); + tsc2301_config.ts_x_plate_ohm = 200; + tsc2301_config.ts_stab_time = 100; + } + } +} +#else +static inline void n800_ts_set_config(void) +{ +} +#endif + +static struct omap_gpio_switch n800_gpio_switches[] __initdata = { + { + .name = "bat_cover", + .gpio = -1, + .debounce_rising = 100, + .debounce_falling = 0, + .notify = n800_mmc_slot1_cover_handler, + .notify_data = NULL, + }, { + .name = "headphone", + .gpio = -1, + .debounce_rising = 200, + .debounce_falling = 200, + }, { + .name = "cam_act", + .gpio = -1, + .debounce_rising = 200, + .debounce_falling = 200, + }, { + .name = "cam_turn", + .gpio = -1, + .debounce_rising = 100, + .debounce_falling = 100, + }, +}; + +static struct platform_device *n800_devices[] __initdata = { +#if defined(CONFIG_CBUS_RETU) && defined(CONFIG_LEDS_OMAP_PWM) + &n800_keypad_led_device, +#endif +}; + +static void __init nokia_n800_init(void) +{ + platform_add_devices(n800_devices, ARRAY_SIZE(n800_devices)); + n800_flash_init(); + n800_mmc_init(); + n800_bt_init(); + n800_audio_init(&tsc2301_config); + n800_dsp_init(); + n800_usb_init(); + n800_cam_init(); + n800_ts_set_config(); + spi_register_board_info(n800_spi_board_info, + ARRAY_SIZE(n800_spi_board_info)); + omap_serial_init(); + mipid_dev_init(); + blizzard_dev_init(); + tsc2301_dev_init(); + omap_register_gpio_switches(n800_gpio_switches, + ARRAY_SIZE(n800_gpio_switches)); + n800_pm_init(); +} + +static void __init nokia_n800_map_io(void) +{ + omap_board_config = n800_config; + omap_board_config_size = ARRAY_SIZE(n800_config); + + omap2_map_common_io(); +} + +MACHINE_START(NOKIA_N800, "Nokia N800") + .phys_io = 0x48000000, + .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = nokia_n800_map_io, + .init_irq = nokia_n800_init_irq, + .init_machine = nokia_n800_init, + .timer = &omap_timer, +MACHINE_END Index: linux-2.6/include/asm-arm/arch-omap/board.h =================================================================== --- linux-2.6.orig/include/asm-arm/arch-omap/board.h 2007-04-09 16:21:17.000000000 -0400 +++ linux-2.6/include/asm-arm/arch-omap/board.h 2007-04-09 16:21:18.000000000 -0400 @@ -25,9 +25,12 @@ #define OMAP_TAG_FBMEM 0x4f08 #define OMAP_TAG_STI_CONSOLE 0x4f09 #define OMAP_TAG_CAMERA_SENSOR 0x4f0a +#define OMAP_TAG_PARTITION 0x4f0b +#define OMAP_TAG_TEA5761 0x4f10 +#define OMAP_TAG_TMP105 0x4f11 #define OMAP_TAG_BOOT_REASON 0x4f80 -#define OMAP_TAG_FLASH_PART 0x4f81 +#define OMAP_TAG_FLASH_PART_STR 0x4f81 #define OMAP_TAG_VERSION_STR 0x4f82 struct omap_clock_config { @@ -139,8 +142,25 @@ struct omap_uart_config { unsigned int enabled_uarts; }; +struct omap_tea5761_config { + u16 enable_gpio; +}; + +/* This cannot be passed from the bootloader */ +struct omap_tmp105_config { + u16 tmp105_irq_pin; + int (* set_power)(int enable); +}; + +struct omap_partition_config { + char name[16]; + unsigned int size; + unsigned int offset; + /* same as in include/linux/mtd/partitions.h */ + unsigned int mask_flags; +}; -struct omap_flash_part_config { +struct omap_flash_part_str_config { char part_table[0]; }; Index: linux-2.6/include/asm-arm/arch-omap/board-nokia.h =================================================================== --- linux-2.6.orig/include/asm-arm/arch-omap/board-nokia.h 2007-04-09 16:21:09.000000000 -0400 +++ linux-2.6/include/asm-arm/arch-omap/board-nokia.h 2007-04-09 16:21:18.000000000 -0400 @@ -11,6 +11,17 @@ #include <linux/types.h> +extern void __init n800_flash_init(void); +extern void __init n800_mmc_init(void); +extern void __init n800_bt_init(void); +extern void __init n800_audio_init(struct tsc2301_platform_data *); +extern void __init n800_dsp_init(void); +extern void __init n800_usb_init(void); +extern void __init n800_pm_init(void); +extern int n800_audio_enable(struct dsp_kfunc_device *kdev, int stage); +extern int n800_audio_disable(struct dsp_kfunc_device *kdev, int stage); +extern void n800_mmc_slot1_cover_handler(void *arg, int state); + #define OMAP_TAG_NOKIA_BT 0x4e01 #define OMAP_TAG_WLAN_CX3110X 0x4e02 #define OMAP_TAG_CBUS 0x4e03 Index: linux-2.6/include/asm-arm/arch-omap/onenand.h =================================================================== --- linux-2.6.orig/include/asm-arm/arch-omap/onenand.h 2007-04-09 16:21:17.000000000 -0400 +++ linux-2.6/include/asm-arm/arch-omap/onenand.h 2007-04-09 16:21:18.000000000 -0400 @@ -16,4 +16,5 @@ struct omap_onenand_platform_data { int gpio_irq; struct mtd_partition *parts; int nr_parts; + int (*onenand_setup)(void __iomem *); }; ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 6/7] ARM: OMAP: Replace mach-omap/omap2 with mach-omap2 2007-04-09 21:34 ` [PATCH 5/7] ARM: OMAP: Merge board specific files from N800 tree Tony Lindgren @ 2007-04-09 21:34 ` Tony Lindgren 2007-04-09 21:34 ` [PATCH 7/7] ARM: OMAP: Add apollon gpio keys using gpio-keys input Tony Lindgren 2007-04-16 21:41 ` [PATCH 5/7] ARM: OMAP: Merge board specific files from N800 tree Tony Lindgren 1 sibling, 1 reply; 9+ messages in thread From: Tony Lindgren @ 2007-04-09 21:34 UTC (permalink / raw) To: linux-kernel; +Cc: Trilok Soni, Tony Lindgren From: Trilok Soni <soni.trilok@gmail.com> Update board Apollon with correct file path. Signed-off-by: Trilok Soni <soni.trilok@gmail.com> Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/mach-omap2/board-apollon.c | 2 +- arch/arm/mach-omap2/usb-tusb6010.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) --- a/arch/arm/mach-omap2/board-apollon.c +++ b/arch/arm/mach-omap2/board-apollon.c @@ -4,7 +4,7 @@ * Copyright (C) 2005,2006 Samsung Electronics * Author: Kyungmin Park <kyungmin.park@samsung.com> * - * Modified from mach-omap/omap2/board-h4.c + * Modified from mach-omap2/board-h4.c * * Code for apollon OMAP2 board. Should work on many OMAP2 systems where * the bootloader passes the board-specific data to the kernel. ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 7/7] ARM: OMAP: Add apollon gpio keys using gpio-keys input 2007-04-09 21:34 ` [PATCH 6/7] ARM: OMAP: Replace mach-omap/omap2 with mach-omap2 Tony Lindgren @ 2007-04-09 21:34 ` Tony Lindgren 0 siblings, 0 replies; 9+ messages in thread From: Tony Lindgren @ 2007-04-09 21:34 UTC (permalink / raw) To: linux-kernel; +Cc: Kyungmin Park, Tony Lindgren From: Kyungmin Park <kyungmin.park@samsung.com> Add apollon gpio keys using gpio-keys input Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Tony Lindgren <tony@atomide.com> --- arch/arm/mach-omap2/Makefile | 3 +- arch/arm/mach-omap2/board-apollon-keys.c | 79 ++++++++++++++++++++++++++++++ arch/arm/mach-omap2/board-apollon.c | 53 -------------------- 3 files changed, 81 insertions(+), 54 deletions(-) Index: linux-2.6/arch/arm/mach-omap2/Makefile =================================================================== --- linux-2.6.orig/arch/arm/mach-omap2/Makefile 2007-04-09 16:21:18.000000000 -0400 +++ linux-2.6/arch/arm/mach-omap2/Makefile 2007-04-09 16:21:52.000000000 -0400 @@ -15,7 +15,8 @@ obj-$(CONFIG_PM) += pm.o sleep.o 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_OMAP_APOLLON) += board-apollon.o +obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o \ + board-apollon-keys.o obj-$(CONFIG_MACH_NOKIA_N800) += board-n800.o board-n800-flash.o \ board-n800-mmc.o board-n800-bt.o \ board-n800-audio.o board-n800-usb.o \ Index: linux-2.6/arch/arm/mach-omap2/board-apollon-keys.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-apollon-keys.c 2007-04-09 16:21:52.000000000 -0400 @@ -0,0 +1,79 @@ +/* + * linux/arch/arm/mach-omap2/board-apollon-keys.c + * + * Copyright (C) 2007 Samsung Electronics + * Author: Kyungmin Park <kyungmin.park@samsung.com> + * + * 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/input.h> +#include <linux/gpio_keys.h> + +#include <asm/arch/gpio.h> +#include <asm/arch/mux.h> + +#define SW_ENTER_GPIO16 16 +#define SW_UP_GPIO17 17 +#define SW_DOWN_GPIO58 58 + +static struct gpio_keys_button apollon_gpio_keys_buttons[] = { + [0] = { + .keycode = KEY_ENTER, + .gpio = SW_ENTER_GPIO16, + .desc = "enter sw", + }, + [1] = { + .keycode = KEY_UP, + .gpio = SW_UP_GPIO17, + .desc = "up sw", + }, + [2] = { + .keycode = KEY_DOWN, + .gpio = SW_DOWN_GPIO58, + .desc = "down sw", + }, +}; + +static struct gpio_keys_platform_data apollon_gpio_keys = { + .buttons = apollon_gpio_keys_buttons, + .nbuttons = ARRAY_SIZE(apollon_gpio_keys_buttons), +}; + +static struct platform_device apollon_gpio_keys_device = { + .name = "gpio-keys", + .id = -1, + .dev = { + .platform_data = &apollon_gpio_keys, + }, +}; + +static void __init apollon_sw_init(void) +{ + /* Enter SW - Y11 */ + omap_cfg_reg(Y11_242X_GPIO16); + omap_request_gpio(SW_ENTER_GPIO16); + omap_set_gpio_direction(SW_ENTER_GPIO16, 1); + /* Up SW - AA12 */ + omap_cfg_reg(AA12_242X_GPIO17); + omap_request_gpio(SW_UP_GPIO17); + omap_set_gpio_direction(SW_UP_GPIO17, 1); + /* Down SW - AA8 */ + omap_cfg_reg(AA8_242X_GPIO58); + omap_request_gpio(SW_DOWN_GPIO58); + omap_set_gpio_direction(SW_DOWN_GPIO58, 1); +} + +static int __init omap_apollon_keys_init(void) +{ + apollon_sw_init(); + + return platform_device_register(&apollon_gpio_keys_device); +} + +arch_initcall(omap_apollon_keys_init); Index: linux-2.6/arch/arm/mach-omap2/board-apollon.c =================================================================== --- linux-2.6.orig/arch/arm/mach-omap2/board-apollon.c 2007-04-09 16:21:41.000000000 -0400 +++ linux-2.6/arch/arm/mach-omap2/board-apollon.c 2007-04-09 16:21:52.000000000 -0400 @@ -22,11 +22,8 @@ #include <linux/mtd/mtd.h> #include <linux/mtd/partitions.h> #include <linux/mtd/onenand.h> -#include <linux/irq.h> -#include <linux/interrupt.h> #include <linux/delay.h> #include <linux/leds.h> -#include <linux/irq.h> #include <linux/err.h> #include <linux/clk.h> @@ -48,9 +45,6 @@ #define LED0_GPIO13 13 #define LED1_GPIO14 14 #define LED2_GPIO15 15 -#define SW_ENTER_GPIO16 16 -#define SW_UP_GPIO17 17 -#define SW_DOWN_GPIO58 58 #define APOLLON_FLASH_CS 0 #define APOLLON_ETH_CS 1 @@ -302,52 +296,6 @@ static void __init apollon_led_init(void omap_set_gpio_dataout(LED2_GPIO15, 0); } -static irqreturn_t apollon_sw_interrupt(int irq, void *ignored) -{ - static unsigned int led0, led1, led2; - - if (irq == OMAP_GPIO_IRQ(SW_ENTER_GPIO16)) - omap_set_gpio_dataout(LED0_GPIO13, led0 ^= 1); - else if (irq == OMAP_GPIO_IRQ(SW_UP_GPIO17)) - omap_set_gpio_dataout(LED1_GPIO14, led1 ^= 1); - else if (irq == OMAP_GPIO_IRQ(SW_DOWN_GPIO58)) - omap_set_gpio_dataout(LED2_GPIO15, led2 ^= 1); - - return IRQ_HANDLED; -} - -static void __init apollon_sw_init(void) -{ - /* Enter SW - Y11 */ - omap_cfg_reg(Y11_242X_GPIO16); - omap_request_gpio(SW_ENTER_GPIO16); - omap_set_gpio_direction(SW_ENTER_GPIO16, 1); - /* Up SW - AA12 */ - omap_cfg_reg(AA12_242X_GPIO17); - omap_request_gpio(SW_UP_GPIO17); - omap_set_gpio_direction(SW_UP_GPIO17, 1); - /* Down SW - AA8 */ - omap_cfg_reg(AA8_242X_GPIO58); - omap_request_gpio(SW_DOWN_GPIO58); - omap_set_gpio_direction(SW_DOWN_GPIO58, 1); - - set_irq_type(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), IRQT_RISING); - if (request_irq(OMAP_GPIO_IRQ(SW_ENTER_GPIO16), &apollon_sw_interrupt, - IRQF_SHARED, "enter sw", - &apollon_sw_interrupt)) - return; - set_irq_type(OMAP_GPIO_IRQ(SW_UP_GPIO17), IRQT_RISING); - if (request_irq(OMAP_GPIO_IRQ(SW_UP_GPIO17), &apollon_sw_interrupt, - IRQF_SHARED, "up sw", - &apollon_sw_interrupt)) - return; - set_irq_type(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), IRQT_RISING); - if (request_irq(OMAP_GPIO_IRQ(SW_DOWN_GPIO58), &apollon_sw_interrupt, - IRQF_SHARED, "down sw", - &apollon_sw_interrupt)) - return; -} - static void __init apollon_usb_init(void) { /* USB device */ @@ -361,7 +309,6 @@ static void __init apollon_usb_init(void static void __init omap_apollon_init(void) { apollon_led_init(); - apollon_sw_init(); apollon_flash_init(); apollon_usb_init(); ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH 5/7] ARM: OMAP: Merge board specific files from N800 tree 2007-04-09 21:34 ` [PATCH 5/7] ARM: OMAP: Merge board specific files from N800 tree Tony Lindgren 2007-04-09 21:34 ` [PATCH 6/7] ARM: OMAP: Replace mach-omap/omap2 with mach-omap2 Tony Lindgren @ 2007-04-16 21:41 ` Tony Lindgren 1 sibling, 0 replies; 9+ messages in thread From: Tony Lindgren @ 2007-04-16 21:41 UTC (permalink / raw) To: linux-kernel; +Cc: Kai Svahn [-- Attachment #1: Type: text/plain, Size: 446 bytes --] * Tony Lindgren <tony@atomide.com> [070409 21:34]: > From: Kai Svahn <kai.svahn@nokia.com> > > This patch merges board specific files from N800 tree. > Nokia has published the files at: > > http://repository.maemo.org/pool/maemo3.0/free/source/ > kernel-source-rx-34_2.6.18.orig.tar.gz > kernel-source-rx-34_2.6.18-osso29.diff.gz Here's an updated version that fixes compile after my last fix to move externs to board-nokia.h. Regards, Tony [-- Attachment #2: 0062-ARM-OMAP-Merge-board-specific-files-from-N800-tree.txt --] [-- Type: text/plain, Size: 47729 bytes --] >From fd345ea126336a514baf808170f1231999ba2c1d Mon Sep 17 00:00:00 2001 From: Kai Svahn <kai.svahn@nokia.com> Date: Fri, 26 Jan 2007 12:39:48 -0800 Subject: [PATCH 5/7] ARM: OMAP: Merge board specific files from N800 tree This patch merges board specific files from N800 tree. Nokia has published the files at: http://repository.maemo.org/pool/maemo3.0/free/source/ kernel-source-rx-34_2.6.18.orig.tar.gz kernel-source-rx-34_2.6.18-osso29.diff.gz Signed-off-by: Kai Svahn <kai.svahn@nokia.com> Signed-off-by: Tony Lindgren <tony@atomide.com> Index: linux-2.6/arch/arm/mach-omap2/Kconfig =================================================================== --- linux-2.6.orig/arch/arm/mach-omap2/Kconfig 2007-04-16 20:50:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/Kconfig 2007-04-16 20:50:00.000000000 +0000 @@ -54,4 +54,13 @@ config MACH_OMAP_APOLLON config MACH_OMAP_2430SDP bool "OMAP 2430 SDP board" - depends on ARCH_OMAP2 && ARCH_OMAP24XX \ No newline at end of file + depends on ARCH_OMAP2 && ARCH_OMAP24XX + +config MACH_NOKIA_N800 + bool "Nokia N800" + depends on ARCH_OMAP24XX + +config MACH_OMAP2_TUSB6010 + bool + depends on ARCH_OMAP2 && ARCH_OMAP2420 + default y if MACH_NOKIA_N800 \ No newline at end of file Index: linux-2.6/arch/arm/mach-omap2/Makefile =================================================================== --- linux-2.6.orig/arch/arm/mach-omap2/Makefile 2007-04-16 20:50:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/Makefile 2007-04-16 20:50:00.000000000 +0000 @@ -16,4 +16,8 @@ obj-$(CONFIG_MACH_OMAP_GENERIC) += boar obj-$(CONFIG_MACH_OMAP_H4) += board-h4.o obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o +obj-$(CONFIG_MACH_NOKIA_N800) += board-n800.o board-n800-flash.o \ + board-n800-mmc.o board-n800-bt.o \ + board-n800-audio.o board-n800-usb.o \ + board-n800-dsp.o board-n800-pm.o Index: linux-2.6/arch/arm/mach-omap2/board-n800-audio.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-n800-audio.c 2007-04-16 20:50:00.000000000 +0000 @@ -0,0 +1,366 @@ +/* + * linux/arch/arm/mach-omap2/board-n800-audio.c + * + * Copyright (C) 2006 Nokia Corporation + * Contact: Juha Yrjola + * Jarkko Nikula <jarkko.nikula@nokia.com> + * + * 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. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/err.h> +#include <linux/clk.h> +#include <linux/platform_device.h> +#include <linux/spi/tsc2301.h> + +#include <asm/io.h> +#include <asm/arch/eac.h> + +#include "../plat-omap/dsp/dsp_common.h" + +#if defined(CONFIG_SPI_TSC2301_AUDIO) && defined(CONFIG_SND_OMAP24XX_EAC) +#define AUDIO_ENABLED + +static struct clk *sys_clkout2; +static struct clk *func96m_clk; +static struct device *eac_device; +static struct device *tsc2301_device; + +static int enable_audio; +static int audio_ok; +static spinlock_t audio_lock; + +/* + * Leaving EAC and sys_clkout2 pins multiplexed to those subsystems results + * in about 2 mA extra current leak when audios are powered down. The + * workaround is to multiplex them to protected mode (with pull-ups enabled) + * whenever audio is not being used. + */ +static int eac_mux_disabled = 0; +static int clkout2_mux_disabled = 0; +static u32 saved_mux[2]; + +static void n800_enable_eac_mux(void) +{ + if (!eac_mux_disabled) + return; + __raw_writel(saved_mux[1], IO_ADDRESS(0x48000124)); + eac_mux_disabled = 0; +} + +static void n800_disable_eac_mux(void) +{ + if (eac_mux_disabled) { + WARN_ON(eac_mux_disabled); + return; + } + saved_mux[1] = __raw_readl(IO_ADDRESS(0x48000124)); + __raw_writel(0x1f1f1f1f, IO_ADDRESS(0x48000124)); + eac_mux_disabled = 1; +} + +static void n800_enable_clkout2_mux(void) +{ + if (!clkout2_mux_disabled) + return; + __raw_writel(saved_mux[0], IO_ADDRESS(0x480000e8)); + clkout2_mux_disabled = 0; +} + +static void n800_disable_clkout2_mux(void) +{ + u32 l; + + if (clkout2_mux_disabled) { + WARN_ON(clkout2_mux_disabled); + return; + } + saved_mux[0] = __raw_readl(IO_ADDRESS(0x480000e8)); + l = saved_mux[0] & ~0xff; + l |= 0x1f; + __raw_writel(l, IO_ADDRESS(0x480000e8)); + clkout2_mux_disabled = 1; +} + +static int n800_eac_enable_ext_clocks(struct device *dev) +{ + BUG_ON(tsc2301_device == NULL); + n800_enable_eac_mux(); + tsc2301_mixer_enable_mclk(tsc2301_device); + + return 0; +} + +static void n800_eac_disable_ext_clocks(struct device *dev) +{ + BUG_ON(tsc2301_device == NULL); + tsc2301_mixer_disable_mclk(tsc2301_device); + n800_disable_eac_mux(); +} + +static int n800_audio_set_power(void *pdata, int dac, int adc) +{ + BUG_ON(pdata != tsc2301_device); + tsc2301_mixer_set_power(tsc2301_device, dac, adc); + + return 0; +} + +static int n800_audio_register_controls(void *pdata, struct snd_card *card) +{ + BUG_ON(pdata != tsc2301_device); + return tsc2301_mixer_register_controls(tsc2301_device, card); +} + +static struct eac_codec n800_eac_codec = { + .mclk_src = EAC_MCLK_EXT_2x12288000, + .codec_mode = EAC_CODEC_I2S, + .codec_conf.i2s.polarity_changed_mode = 0, + .codec_conf.i2s.sync_delay_enable = 0, + .default_rate = 48000, + .set_power = n800_audio_set_power, + .register_controls = n800_audio_register_controls, + .short_name = "TSC2301", +}; + +static int n800_register_codec(void) +{ + int r, do_enable = 0; + unsigned long flags; + + n800_eac_codec.private_data = tsc2301_device; + r = eac_register_codec(eac_device, &n800_eac_codec); + if (r < 0) + return r; + spin_lock_irqsave(&audio_lock, flags); + audio_ok = 1; + if (enable_audio) + do_enable = 1; + spin_unlock_irqrestore(&audio_lock, flags); + if (do_enable) + eac_set_mode(eac_device, 1, 1); + return 0; +} + +static void n800_unregister_codec(void) +{ + audio_ok = 0; + eac_unregister_codec(eac_device); + eac_set_mode(eac_device, 0, 0); +} + +static int n800_eac_init(struct device *dev) +{ + int r; + + BUG_ON(eac_device != NULL); + eac_device = dev; + if (tsc2301_device != NULL) { + r = n800_register_codec(); + if (r < 0) + return r; + } + + return 0; +} + +static void n800_eac_cleanup(struct device *dev) +{ + eac_device = NULL; + if (tsc2301_device != NULL) + n800_unregister_codec(); +} + +static int n800_codec_get_clocks(struct device *dev) +{ + sys_clkout2 = clk_get(dev, "sys_clkout2"); + if (IS_ERR(sys_clkout2)) { + dev_err(dev, "Could not get sys_clkout2\n"); + return -ENODEV; + } + /* configure 12 MHz output on SYS_CLKOUT2. Therefore we must use + * 96 MHz as its parent in order to get 12 MHz */ + func96m_clk = clk_get(dev, "func_96m_ck"); + if (IS_ERR(func96m_clk)) { + dev_err(dev, "Could not get func 96M clock\n"); + clk_put(sys_clkout2); + return -ENODEV; + } + + clk_set_parent(sys_clkout2, func96m_clk); + clk_set_rate(sys_clkout2, 12000000); + + return 0; +} + +static void n800_codec_put_clocks(struct device *dev) +{ + clk_put(func96m_clk); + clk_put(sys_clkout2); +} + +static int n800_codec_enable_clock(struct device *dev) +{ + n800_enable_clkout2_mux(); + return clk_enable(sys_clkout2); +} + +static void n800_codec_disable_clock(struct device *dev) +{ + clk_disable(sys_clkout2); + n800_disable_clkout2_mux(); +} + +static int n800_codec_init(struct device *dev) +{ + int r; + + BUG_ON(tsc2301_device != NULL); + tsc2301_device = dev; + if ((r = n800_codec_get_clocks(dev)) < 0) + return r; + if (eac_device != NULL) { + r = n800_register_codec(); + if (r < 0) { + n800_codec_put_clocks(dev); + return r; + } + } + return 0; +} + +static void n800_codec_cleanup(struct device *dev) +{ + tsc2301_device = NULL; + if (eac_device != NULL) + n800_unregister_codec(); + n800_codec_put_clocks(dev); +} + +static struct eac_platform_data n800_eac_data = { + .init = n800_eac_init, + .cleanup = n800_eac_cleanup, + .enable_ext_clocks = n800_eac_enable_ext_clocks, + .disable_ext_clocks = n800_eac_disable_ext_clocks, +}; + +static const struct tsc2301_mixer_gpio n800_mixer_gpios[] = { + { + .name = "Headset Amplifier", + .gpio = 1, + .deactivate_on_pd = 1, + }, { + .name = "Speaker Amplifier", + .gpio = 2, + .def_enable = 1, + .deactivate_on_pd = 1, + }, { + .name = "Headset Mic Select", + .gpio = 3, + } +}; + +static struct platform_device retu_headset_device = { + .name = "retu-headset", + .id = -1, + .dev = { + .release = NULL, + }, +}; + +void __init n800_audio_init(struct tsc2301_platform_data *tc) +{ + spin_lock_init(&audio_lock); + + if (platform_device_register(&retu_headset_device) < 0) + return; + omap_init_eac(&n800_eac_data); + + tc->pll_pdc = 7; + tc->pll_a = 7; + tc->pll_n = 9; + tc->pll_output = 1; + tc->mclk_ratio = TSC2301_MCLK_256xFS; + tc->i2s_sample_rate = TSC2301_I2S_SR_48000; + tc->i2s_format = TSC2301_I2S_FORMAT0; + tc->power_down_blocks = TSC2301_REG_PD_MISC_MOPD; + tc->mixer_gpios = n800_mixer_gpios; + tc->n_mixer_gpios = ARRAY_SIZE(n800_mixer_gpios); + tc->codec_init = n800_codec_init; + tc->codec_cleanup = n800_codec_cleanup; + tc->enable_clock = n800_codec_enable_clock; + tc->disable_clock = n800_codec_disable_clock; +} + +#else + +void __init n800_audio_init(void) +{ +} + +#endif + +#ifdef CONFIG_OMAP_DSP + +int n800_audio_enable(struct dsp_kfunc_device *kdev, int stage) +{ +#ifdef AUDIO_ENABLED + unsigned long flags; + int do_enable = 0; + + spin_lock_irqsave(&audio_lock, flags); + + pr_debug("DSP power up request (audio codec %sinitialized)\n", + audio_ok ? "" : "not "); + + if (enable_audio) + goto out; + enable_audio = 1; + if (audio_ok) + do_enable = 1; +out: + spin_unlock_irqrestore(&audio_lock, flags); + if (do_enable) + eac_set_mode(eac_device, 1, 1); +#endif + return 0; +} + +int n800_audio_disable(struct dsp_kfunc_device *kdev, int stage) +{ +#ifdef AUDIO_ENABLED + unsigned long flags; + int do_disable = 0; + + spin_lock_irqsave(&audio_lock, flags); + + pr_debug("DSP power down request (audio codec %sinitialized)\n", + audio_ok ? "" : "not "); + + if (!enable_audio) + goto out; + enable_audio = 0; + if (audio_ok) + do_disable = 1; +out: + spin_unlock_irqrestore(&audio_lock, flags); + if (do_disable) + eac_set_mode(eac_device, 0, 0); +#endif + return 0; +} + +#endif /* CONFIG_OMAP_DSP */ Index: linux-2.6/arch/arm/mach-omap2/board-n800-bt.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-n800-bt.c 2007-04-16 20:50:00.000000000 +0000 @@ -0,0 +1,42 @@ +/* + * Nokia N800 platform-specific data for Bluetooth + * + * Copyright (C) 2005, 2006 Nokia Corporation + * Contact: Ville Tervo <ville.tervo@nokia.com> + * + * 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. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + */ + +#include <linux/kernel.h> +#include <linux/platform_device.h> +#include <asm/arch/board.h> + +static struct platform_device n800_bt_device = { + .name = "hci_h4p", + .id = -1, + .num_resources = 0, +}; + +void __init n800_bt_init(void) +{ + const struct omap_bluetooth_config *bt_config; + + bt_config = (void *) omap_get_config(OMAP_TAG_NOKIA_BT, + struct omap_bluetooth_config); + n800_bt_device.dev.platform_data = (void *) bt_config; + if (platform_device_register(&n800_bt_device) < 0) + BUG(); +} + Index: linux-2.6/arch/arm/mach-omap2/board-n800-dsp.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-n800-dsp.c 2007-04-16 20:50:00.000000000 +0000 @@ -0,0 +1,156 @@ +/* + * linux/arch/arm/mach-omap2/board-n800-dsp.c + * + * Copyright (C) 2006 Nokia Corporation. + * + * Contact: Hiroshi DOYU <Hiroshi.DOYU@nokia.com> + * + * 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. + * + * 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., 51 Franklin St, Fifth Floor, Boston, MA + * 02110-1301 USA + * + */ + +#include <linux/kernel.h> +#include <linux/device.h> +#include <linux/list.h> +#include <linux/err.h> +#include <linux/clk.h> + +#include <asm/io.h> +#include <asm/arch/clock.h> +#include <asm/arch/board.h> + +#include "../plat-omap/dsp/dsp_common.h" + +#if defined(CONFIG_OMAP_DSP) + +/* + * dsp peripheral device: AUDIO + */ +static struct dsp_kfunc_device n800_audio_device = { + .name = "audio", + .type = DSP_KFUNC_DEV_TYPE_AUDIO, + .enable = n800_audio_enable, + .disable = n800_audio_disable, +}; + +/* + * dsp peripheral device: TIMER + */ +static int dsp_timer_probe(struct dsp_kfunc_device *kdev) +{ + char clockname[20]; + + strcpy(clockname, kdev->name); + strcat(clockname, "_fck"); + + kdev->fck = clk_get(NULL, clockname); + if (IS_ERR(kdev->fck)) { + printk(KERN_ERR "couldn't acquire %s\n", clockname); + return PTR_ERR(kdev->fck); + } + pr_debug("%s probed successfully\n", clockname); + + strcpy(clockname, kdev->name); + strcat(clockname, "_ick"); + kdev->ick = clk_get(NULL, clockname); + if (IS_ERR(kdev->ick)) { + printk(KERN_ERR "couldn't acquire %s\n", clockname); + goto fail; + } + pr_debug("%s probed successfully\n", clockname); + + return 0; + fail: + clk_put(kdev->fck); + + return PTR_ERR(kdev->ick); +} + +static int dsp_timer_remove(struct dsp_kfunc_device *kdev) +{ + clk_put(kdev->ick); + clk_put(kdev->fck); + pr_debug("%s removed successfully\n", kdev->name); + return 0; +} + +static int dsp_timer_enable(struct dsp_kfunc_device *kdev, int stage) +{ + pr_debug("%s enabled(%d)\n", kdev->name, stage); + + mutex_lock(&kdev->lock); + + if (kdev->enabled) + goto out; + kdev->enabled = 1; + + clk_enable(kdev->fck); + clk_enable(kdev->ick); + out: + mutex_unlock(&kdev->lock); + + return 0; +} + +static int dsp_timer_disable(struct dsp_kfunc_device *kdev, int stage) +{ + pr_debug("%s disabled(%d)\n", kdev->name, stage); + + mutex_lock(&kdev->lock); + + if (kdev->enabled == 0) + goto out; + kdev->enabled = 0; + + clk_disable(kdev->ick); + clk_disable(kdev->fck); + out: + mutex_unlock(&kdev->lock); + + return 0; +} + +static struct dsp_kfunc_device n800_timer_device = { + .name = "gpt5", + .type = DSP_KFUNC_DEV_TYPE_COMMON, + .probe = dsp_timer_probe, + .remove = dsp_timer_remove, + .enable = dsp_timer_enable, + .disable = dsp_timer_disable, +}; + +static struct dsp_kfunc_device *n800_kfunc_dev[] = { + &n800_audio_device, + &n800_timer_device, +}; + +void __init n800_dsp_init(void) +{ + int i, ret; + struct dsp_kfunc_device **p = n800_kfunc_dev; + + for (i = 0; i < ARRAY_SIZE(n800_kfunc_dev); i++) { + ret = dsp_kfunc_device_register(p[i]); + if (ret) { + printk(KERN_ERR + "KFUNC device registration failed: %s\n", + p[i]->name); + } + } +} + +#else +void __init n800_dsp_init(void) { } +#endif /* CONFIG_OMAP_DSP */ Index: linux-2.6/arch/arm/mach-omap2/board-n800-flash.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-n800-flash.c 2007-04-16 20:50:00.000000000 +0000 @@ -0,0 +1,156 @@ +/* + * linux/arch/arm/mach-omap2/board-n800-flash.c + * + * Copyright (C) 2006 Nokia Corporation + * Author: Juha Yrjola + * + * 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/platform_device.h> +#include <asm/mach/flash.h> +#include <linux/mtd/onenand_regs.h> + +#include <asm/io.h> +#include <asm/arch/onenand.h> +#include <asm/arch/board.h> +#include <asm/arch/gpmc.h> + +static struct mtd_partition n800_partitions[8]; + +static int n800_onenand_setup(void __iomem *); + +static struct omap_onenand_platform_data n800_onenand_data = { + .cs = 0, + .gpio_irq = 26, + .parts = n800_partitions, + .nr_parts = 0, /* filled later */ + .onenand_setup = n800_onenand_setup, +}; + +static struct platform_device n800_onenand_device = { + .name = "omap2-onenand", + .id = -1, + .dev = { + .platform_data = &n800_onenand_data, + }, +}; + +static unsigned short omap2_onenand_readw(void __iomem *addr) +{ + return readw(addr); +} + +static void omap2_onenand_writew(unsigned short value, void __iomem *addr) +{ + writew(value, addr); +} + +static int omap2_onenand_set_sync_mode(int cs, void __iomem *onenand_base) +{ + const int min_gpmc_clk_period = 18; + struct gpmc_timings t; + int tick_ns, div, fclk_offset_ns, fclk_offset, gpmc_clk_ns, latency; + u32 reg; + + tick_ns = gpmc_round_ns_to_ticks(1); + div = gpmc_cs_calc_divider(cs, min_gpmc_clk_period); + gpmc_clk_ns = div * tick_ns; + if (gpmc_clk_ns >= 24) + latency = 3; + else + latency = 4; + + /* Configure OneNAND for sync read */ + reg = omap2_onenand_readw(onenand_base + ONENAND_REG_SYS_CFG1); + reg &= ~((0x7 << ONENAND_SYS_CFG1_BRL_SHIFT) | (0x7 << 9)); + reg |= (latency << ONENAND_SYS_CFG1_BRL_SHIFT) | + ONENAND_SYS_CFG1_SYNC_READ | + ONENAND_SYS_CFG1_BL_16; + omap2_onenand_writew(reg, onenand_base + ONENAND_REG_SYS_CFG1); + + /* FIXME: Get timings from platform data */ + /* Set syncronous read timings */ + memset(&t, 0, sizeof(t)); + t.sync_clk = min_gpmc_clk_period; + t.cs_on = 0; + t.adv_on = gpmc_round_ns_to_ticks(7); + fclk_offset_ns = t.adv_on + gpmc_round_ns_to_ticks(7); + fclk_offset = fclk_offset_ns / gpmc_round_ns_to_ticks(1); + t.page_burst_access = gpmc_clk_ns; + + /* Read */ + t.adv_rd_off = fclk_offset_ns + gpmc_round_ns_to_ticks(7); + t.oe_on = t.adv_rd_off; + t.access = fclk_offset_ns + (latency + 1) * gpmc_clk_ns; + t.oe_off = t.access + gpmc_round_ns_to_ticks(1); + t.cs_rd_off = t.oe_off; + t.rd_cycle = t.cs_rd_off + gpmc_round_ns_to_ticks(17); + + /* Write */ + t.adv_wr_off = t.adv_on + gpmc_round_ns_to_ticks(12); + t.we_on = t.adv_wr_off + gpmc_round_ns_to_ticks(1); + t.we_off = t.we_on + gpmc_round_ns_to_ticks(40); + t.cs_wr_off = t.we_off + gpmc_round_ns_to_ticks(1); + t.wr_cycle = t.cs_wr_off + gpmc_round_ns_to_ticks(1); + + /* Configure GPMC for synchronous read */ + fclk_offset %= div; + gpmc_cs_write_reg(cs, GPMC_CS_CONFIG1, + GPMC_CONFIG1_WRAPBURST_SUPP | + GPMC_CONFIG1_READMULTIPLE_SUPP | + GPMC_CONFIG1_READTYPE_SYNC | + GPMC_CONFIG1_CLKACTIVATIONTIME(fclk_offset) | + GPMC_CONFIG1_PAGE_LEN(2) | + GPMC_CONFIG1_WAIT_READ_MON | + GPMC_CONFIG1_WAIT_PIN_SEL(0) | + GPMC_CONFIG1_DEVICESIZE_16 | + GPMC_CONFIG1_DEVICETYPE_NOR | + GPMC_CONFIG1_MUXADDDATA); + + return gpmc_cs_set_timings(cs, &t); +} + +static int n800_onenand_setup(void __iomem *onenand_base) +{ + struct omap_onenand_platform_data *datap = &n800_onenand_data; + struct device *dev = &n800_onenand_device.dev; + + /* Set sync timings in GPMC */ + if (omap2_onenand_set_sync_mode(datap->cs, onenand_base) < 0) { + dev_err(dev, "Unable to set synchronous mode\n"); + return -EINVAL; + } + + return 0; +} + +void __init n800_flash_init(void) +{ + const struct omap_partition_config *part; + int i = 0; + + while ((part = omap_get_nr_config(OMAP_TAG_PARTITION, + struct omap_partition_config, i)) != NULL) { + struct mtd_partition *mpart; + + mpart = n800_partitions + i; + mpart->name = (char *) part->name; + mpart->size = part->size; + mpart->offset = part->offset; + mpart->mask_flags = part->mask_flags; + i++; + if (i == ARRAY_SIZE(n800_partitions)) { + printk(KERN_ERR "Too many partitions supplied\n"); + return; + } + } + n800_onenand_data.nr_parts = i; + if (platform_device_register(&n800_onenand_device) < 0) { + printk(KERN_ERR "Unable to register OneNAND device\n"); + return; + } +} Index: linux-2.6/arch/arm/mach-omap2/board-n800-mmc.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-n800-mmc.c 2007-04-16 20:50:00.000000000 +0000 @@ -0,0 +1,282 @@ +/* + * linux/arch/arm/mach-omap2/board-n800-mmc.c + * + * Copyright (C) 2006 Nokia Corporation + * Author: Juha Yrjola + * + * 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 <asm/arch/mmc.h> +#include <asm/arch/menelaus.h> +#include <asm/arch/gpio.h> + +#ifdef CONFIG_MMC_OMAP + +static const int slot_switch_gpio = 96; +static const int slot1_wp_gpio = 23; +static const int slot2_wp_gpio = 8; +static int slot1_cover_closed; +static int slot2_cover_closed; +static struct device *mmc_device; + +/* + * VMMC --> slot 1 + * VDCDC3_APE, VMCS2_APE --> slot 2 + * GPIO96 --> Menelaus GPIO2 + */ + +static int n800_mmc_switch_slot(struct device *dev, int slot) +{ +#ifdef CONFIG_MMC_DEBUG + dev_dbg(dev, "Choose slot %d\n", slot + 1); +#endif + if (slot == 0) + omap_set_gpio_dataout(slot_switch_gpio, 0); + else + omap_set_gpio_dataout(slot_switch_gpio, 1); + return 0; +} + +static int n800_mmc_set_power(struct device *dev, int slot, int power_on, + int vdd) +{ + int mV; + +#ifdef CONFIG_MMC_DEBUG + dev_dbg(dev, "Set slot %d power: %s (vdd %d)\n", slot + 1, + power_on ? "on" : "off", vdd); +#endif + if (slot == 0) { + if (!power_on) + return menelaus_set_vmmc(0); + switch (1 << vdd) { + case MMC_VDD_33_34: + case MMC_VDD_32_33: + case MMC_VDD_31_32: + mV = 3100; + break; + case MMC_VDD_30_31: + mV = 3000; + break; + case MMC_VDD_28_29: + mV = 2800; + break; + case MMC_VDD_18_19: + mV = 1850; + break; + default: + BUG(); + } + return menelaus_set_vmmc(mV); + } else { + if (!power_on) + return menelaus_set_vdcdc(3, 0); + switch (1 << vdd) { + case MMC_VDD_33_34: + case MMC_VDD_32_33: + mV = 3300; + break; + case MMC_VDD_30_31: + case MMC_VDD_29_30: + mV = 3000; + break; + case MMC_VDD_28_29: + case MMC_VDD_27_28: + mV = 2800; + break; + case MMC_VDD_24_25: + case MMC_VDD_23_24: + mV = 2400; + break; + case MMC_VDD_22_23: + case MMC_VDD_21_22: + mV = 2200; + break; + case MMC_VDD_20_21: + case MMC_VDD_19_20: + mV = 2000; + break; + case MMC_VDD_18_19: + case MMC_VDD_17_18: + mV = 1800; + break; + case MMC_VDD_150_155: + case MMC_VDD_145_150: + mV = 1500; + break; + default: + BUG(); + } + return menelaus_set_vdcdc(3, mV); + } + return 0; +} + +static int n800_mmc_set_bus_mode(struct device *dev, int slot, int bus_mode) +{ + int r; + +#ifdef CONFIG_MMC_DEBUG + dev_dbg(dev, "Set slot %d bus mode %s\n", slot + 1, + bus_mode == MMC_BUSMODE_OPENDRAIN ? "open-drain" : "push-pull"); +#endif + BUG_ON(slot != 0 && slot != 1); + slot++; + switch (bus_mode) { + case MMC_BUSMODE_OPENDRAIN: + r = menelaus_set_mmc_opendrain(slot, 1); + break; + case MMC_BUSMODE_PUSHPULL: + r = menelaus_set_mmc_opendrain(slot, 0); + break; + default: + BUG(); + } + if (r != 0 && printk_ratelimit()) + dev_err(dev, "MMC: unable to set bus mode for slot %d\n", + slot); + return r; +} + +#if 0 +static int n800_mmc_get_ro(struct device *dev, int slot) +{ + int ro; + + slot++; + if (slot == 1) + ro = omap_get_gpio_datain(slot1_wp_gpio); + else + ro = omap_get_gpio_datain(slot2_wp_gpio); +#ifdef CONFIG_MMC_DEBUG + dev_dbg(dev, "Get RO slot %d: %s\n", + slot, ro ? "read-only" : "read-write"); +#endif + return ro; +} +#endif + +static int n800_mmc_get_cover_state(struct device *dev, int slot) +{ + slot++; + BUG_ON(slot != 1 && slot != 2); + if (slot == 1) + return slot1_cover_closed; + else + return slot2_cover_closed; +} + +static void n800_mmc_callback(void *data, u8 card_mask) +{ + if (card_mask & (1 << 1)) + slot2_cover_closed = 0; + else + slot2_cover_closed = 1; + omap_mmc_notify_cover_event(mmc_device, 1, slot2_cover_closed); +} + +void n800_mmc_slot1_cover_handler(void *arg, int state) +{ + if (mmc_device == NULL) + return; + + slot1_cover_closed = state; + omap_mmc_notify_cover_event(mmc_device, 0, state); +} + +static int n800_mmc_late_init(struct device *dev) +{ + int r; + + mmc_device = dev; + + r = menelaus_set_slot_sel(1); + if (r < 0) + return r; + + r = menelaus_set_mmc_slot(1, 1, 0, 1); + if (r < 0) + return r; + r = menelaus_set_mmc_slot(2, 1, 0, 1); + if (r < 0) + return r; + + r = menelaus_get_slot_pin_states(); + if (r < 0) + return r; + + if (r & (1 << 1)) + slot2_cover_closed = 1; + else + slot2_cover_closed = 0; + + r = menelaus_register_mmc_callback(n800_mmc_callback, NULL); + + return r; +} + +static void n800_mmc_cleanup(struct device *dev) +{ + menelaus_unregister_mmc_callback(); +} + +static struct omap_mmc_platform_data n800_mmc_data = { + .enabled = 1, + .nr_slots = 2, + .wire4 = 1, + .switch_slot = n800_mmc_switch_slot, + .init = n800_mmc_late_init, + .cleanup = n800_mmc_cleanup, + .slots[0] = { + .set_power = n800_mmc_set_power, + .set_bus_mode = n800_mmc_set_bus_mode, + .get_ro = NULL, + .get_cover_state= n800_mmc_get_cover_state, + .ocr_mask = MMC_VDD_18_19 | MMC_VDD_28_29 | MMC_VDD_30_31 | + MMC_VDD_32_33 | MMC_VDD_33_34, + .name = "internal", + }, + .slots[1] = { + .set_power = n800_mmc_set_power, + .set_bus_mode = n800_mmc_set_bus_mode, + .get_ro = NULL, + .get_cover_state= n800_mmc_get_cover_state, + .ocr_mask = MMC_VDD_150_155 | MMC_VDD_145_150 | MMC_VDD_17_18 | + MMC_VDD_18_19 | MMC_VDD_19_20 | MMC_VDD_20_21 | + MMC_VDD_21_22 | MMC_VDD_22_23 | MMC_VDD_23_24 | + MMC_VDD_24_25 | MMC_VDD_27_28 | MMC_VDD_28_29 | + MMC_VDD_29_30 | MMC_VDD_30_31 | MMC_VDD_32_33 | + MMC_VDD_33_34, + .name = "external", + }, +}; + +void __init n800_mmc_init(void) +{ + omap_set_mmc_info(1, &n800_mmc_data); + if (omap_request_gpio(slot_switch_gpio) < 0) + BUG(); + omap_set_gpio_dataout(slot_switch_gpio, 0); + omap_set_gpio_direction(slot_switch_gpio, 0); + if (omap_request_gpio(slot1_wp_gpio) < 0) + BUG(); + if (omap_request_gpio(slot2_wp_gpio) < 0) + BUG(); + omap_set_gpio_direction(slot1_wp_gpio, 1); + omap_set_gpio_direction(slot2_wp_gpio, 1); +} + +#else + +void __init n800_mmc_init(void) +{ +} + +void n800_mmc_slot1_cover_handler(void *arg, int state) +{ +} + +#endif Index: linux-2.6/arch/arm/mach-omap2/board-n800-pm.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-n800-pm.c 2007-04-16 20:50:00.000000000 +0000 @@ -0,0 +1,79 @@ +/* + * Nokia N800 PM code + * + * Copyright (C) 2006 Nokia Corporation + * Author: Amit Kucheria <amit.kucheria@nokia.com> + * + * 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/module.h> +#include <asm/arch/menelaus.h> + +#ifdef CONFIG_MENELAUS + +static int n800_auto_sleep_regulators(void) +{ + u32 val; + int ret; + + val = EN_VPLL_SLEEP | EN_VMMC_SLEEP \ + | EN_VAUX_SLEEP | EN_VIO_SLEEP \ + | EN_VMEM_SLEEP | EN_DC3_SLEEP \ + | EN_VC_SLEEP | EN_DC2_SLEEP; + + ret = menelaus_set_regulator_sleep(1, val); + if (ret < 0) { + printk(KERN_ERR "Could not set regulators to sleep on " + "menelaus: %u\n", ret); + return ret; + } + return 0; +} + +static int n800_auto_voltage_scale(void) +{ + int ret; + + ret = menelaus_set_vcore_hw(1400, 1050); + if (ret < 0) { + printk(KERN_ERR "Could not set VCORE voltage on " + "menelaus: %u\n", ret); + return ret; + } + return 0; +} + +static int n800_menelaus_init(struct device *dev) +{ + int ret; + + ret = n800_auto_voltage_scale(); + if (ret < 0) + return ret; + ret = n800_auto_sleep_regulators(); + if (ret < 0) + return ret; + return 0; +} + +static struct menelaus_platform_data n800_menelaus_platform_data = { + .late_init = n800_menelaus_init, +}; + +void __init n800_pm_init(void) +{ + menelaus_set_platform_data(&n800_menelaus_platform_data); +} + +#else + +void __init n800_pm_init(void) +{ +} + +#endif + Index: linux-2.6/arch/arm/mach-omap2/board-n800-usb.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-n800-usb.c 2007-04-16 20:50:00.000000000 +0000 @@ -0,0 +1,102 @@ +/* + * linux/arch/arm/mach-omap2/board-n800-usb.c + * + * Copyright (C) 2006 Nokia Corporation + * Author: Juha Yrjola + * + * 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/types.h> +#include <linux/errno.h> +#include <linux/delay.h> +#include <linux/platform_device.h> +#include <linux/usb/musb.h> +#include <asm/arch/gpmc.h> +#include <asm/arch/gpio.h> + +#define TUSB_ASYNC_CS 1 +#define TUSB_SYNC_CS 4 +#define GPIO_TUSB_INT 58 +#define GPIO_TUSB_ENABLE 0 + +static int tusb_set_power(int state); + +#if defined(CONFIG_USB_MUSB_OTG) +# define BOARD_MODE MUSB_OTG +#elif defined(CONFIG_USB_MUSB_PERIPHERAL) +# define BOARD_MODE MUSB_PERIPHERAL +#else /* defined(CONFIG_USB_MUSB_HOST) */ +# define BOARD_MODE MUSB_HOST +#endif + +static struct musb_hdrc_platform_data tusb_data = { + .mode = BOARD_MODE, + .multipoint = 1, + .set_power = tusb_set_power, + .min_power = 25, /* x2 = 50 mA drawn from VBUS as peripheral */ +}; + +/* + * Enable or disable power to TUSB6010. When enabling, turn on 3.3 V and + * 1.5 V voltage regulators of PM companion chip. Companion chip will then + * provide then PGOOD signal to TUSB6010 which will release it from reset. + */ +static int tusb_set_power(int state) +{ + int i, retval = 0; + + if (state) { + omap_set_gpio_dataout(GPIO_TUSB_ENABLE, 1); + msleep(1); + + /* Wait until TUSB6010 pulls INT pin down */ + i = 100; + while (i && omap_get_gpio_datain(GPIO_TUSB_INT)) { + msleep(1); + i--; + } + + if (!i) { + printk(KERN_ERR "tusb: powerup failed\n"); + retval = -ENODEV; + } + } else { + omap_set_gpio_dataout(GPIO_TUSB_ENABLE, 0); + msleep(10); + } + + return retval; +} + +void __init n800_usb_init(void) +{ + int ret = 0; + static char announce[] __initdata = KERN_INFO "TUSB 6010\n"; + + /* PM companion chip power control pin */ + ret = omap_request_gpio(GPIO_TUSB_ENABLE); + if (ret != 0) { + printk(KERN_ERR "Could not get TUSB power GPIO%i\n", + GPIO_TUSB_ENABLE); + return; + } + omap_set_gpio_direction(GPIO_TUSB_ENABLE, 0); + + tusb_set_power(0); + + ret = tusb6010_setup_interface(&tusb_data, TUSB6010_REFCLK_19, 2, + TUSB_ASYNC_CS, TUSB_SYNC_CS, + GPIO_TUSB_INT, 0x3f); + if (ret != 0) + goto err; + + printk(announce); + + return; + +err: + omap_free_gpio(GPIO_TUSB_ENABLE); +} Index: linux-2.6/arch/arm/mach-omap2/board-n800.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-2.6/arch/arm/mach-omap2/board-n800.c 2007-04-16 20:50:00.000000000 +0000 @@ -0,0 +1,515 @@ +/* + * linux/arch/arm/mach-omap2/board-n800.c + * + * Copyright (C) 2005 Nokia Corporation + * Author: Juha Yrjola <juha.yrjola@nokia.com> + * + * Modified from mach-omap2/board-generic.c + * + * 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/clk.h> +#include <linux/device.h> +#include <linux/platform_device.h> +#include <linux/spi/spi.h> +#include <linux/spi/tsc2301.h> +#include <linux/input.h> +#include <linux/delay.h> +#include <linux/interrupt.h> +#include <linux/irq.h> +#include <asm/hardware.h> +#include <asm/mach-types.h> +#include <asm/mach/arch.h> +#include <asm/mach/map.h> +#include <asm/arch/gpio.h> +#include <asm/arch/usb.h> +#include <asm/arch/board.h> +#include <asm/arch/common.h> +#include <asm/arch/mcspi.h> +#include <asm/arch/menelaus.h> +#include <asm/arch/lcd_mipid.h> +#include <asm/arch/clock.h> +#include <asm/arch/gpio-switch.h> +#include <asm/arch/omapfb.h> +#include <asm/arch/blizzard.h> + +#include <../drivers/cbus/tahvo.h> + +#define N800_BLIZZARD_POWERDOWN_GPIO 15 +#define N800_STI_GPIO 62 +#define N800_CAM_SENSOR_RESET_GPIO 53 +#define N800_KEYB_IRQ_GPIO 109 + +static void __init nokia_n800_init_irq(void) +{ + omap2_init_common_hw(); + omap_init_irq(); + omap_gpio_init(); + +#ifdef CONFIG_OMAP_STI + if (omap_request_gpio(N800_STI_GPIO) < 0) { + printk(KERN_ERR "Failed to request GPIO %d for STI\n", + N800_STI_GPIO); + return; + } + + omap_set_gpio_direction(N800_STI_GPIO, 0); + omap_set_gpio_dataout(N800_STI_GPIO, 0); +#endif +} + +#if defined(CONFIG_MENELAUS) && defined(CONFIG_SENSORS_TMP105) + +static int n800_tmp105_set_power(int enable) +{ + return menelaus_set_vaux(enable ? 2800 : 0); +} + +#else + +#define n800_tmp105_set_power NULL + +#endif + +static struct omap_uart_config n800_uart_config __initdata = { + .enabled_uarts = (1 << 0) | (1 << 2), +}; + +#include "../../../drivers/cbus/retu.h" + +static struct omap_fbmem_config n800_fbmem0_config __initdata = { + .size = 752 * 1024, +}; + +static struct omap_fbmem_config n800_fbmem1_config __initdata = { + .size = 752 * 1024, +}; + +static struct omap_fbmem_config n800_fbmem2_config __initdata = { + .size = 752 * 1024, +}; + +static struct omap_tmp105_config n800_tmp105_config __initdata = { + .tmp105_irq_pin = 125, + .set_power = n800_tmp105_set_power, +}; + +static void mipid_shutdown(struct mipid_platform_data *pdata) +{ + if (pdata->nreset_gpio != -1) { + pr_info("shutdown LCD\n"); + omap_set_gpio_dataout(pdata->nreset_gpio, 0); + msleep(120); + } +} + +static struct mipid_platform_data n800_mipid_platform_data = { + .shutdown = mipid_shutdown, +}; + +static void __init mipid_dev_init(void) +{ + const struct omap_lcd_config *conf; + + conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); + if (conf != NULL) { + n800_mipid_platform_data.nreset_gpio = conf->nreset_gpio; + n800_mipid_platform_data.data_lines = conf->data_lines; + } +} + +static struct { + struct clk *sys_ck; +} blizzard; + +static int blizzard_get_clocks(void) +{ + blizzard.sys_ck = clk_get(0, "osc_ck"); + if (IS_ERR(blizzard.sys_ck)) { + printk(KERN_ERR "can't get Blizzard clock\n"); + return PTR_ERR(blizzard.sys_ck); + } + return 0; +} + +static unsigned long blizzard_get_clock_rate(struct device *dev) +{ + return clk_get_rate(blizzard.sys_ck); +} + +static void blizzard_enable_clocks(int enable) +{ + if (enable) + clk_enable(blizzard.sys_ck); + else + clk_disable(blizzard.sys_ck); +} + +static void blizzard_power_up(struct device *dev) +{ + /* Vcore to 1.475V */ + tahvo_set_clear_reg_bits(0x07, 0, 0xf); + msleep(10); + + blizzard_enable_clocks(1); + omap_set_gpio_dataout(N800_BLIZZARD_POWERDOWN_GPIO, 1); +} + +static void blizzard_power_down(struct device *dev) +{ + omap_set_gpio_dataout(N800_BLIZZARD_POWERDOWN_GPIO, 0); + blizzard_enable_clocks(0); + + /* Vcore to 1.005V */ + tahvo_set_clear_reg_bits(0x07, 0xf, 0); +} + +static struct blizzard_platform_data n800_blizzard_data = { + .power_up = blizzard_power_up, + .power_down = blizzard_power_down, + .get_clock_rate = blizzard_get_clock_rate, + .te_connected = 1, +}; + +static void __init blizzard_dev_init(void) +{ + int r; + + r = omap_request_gpio(N800_BLIZZARD_POWERDOWN_GPIO); + if (r < 0) + return; + omap_set_gpio_direction(N800_BLIZZARD_POWERDOWN_GPIO, 0); + omap_set_gpio_dataout(N800_BLIZZARD_POWERDOWN_GPIO, 1); + + blizzard_get_clocks(); + omapfb_set_ctrl_platform_data(&n800_blizzard_data); +} + +#if defined(CONFIG_CBUS_RETU) && defined(CONFIG_VIDEO_CAMERA_SENSOR_TCM825X) && \ + defined(CONFIG_MENELAUS) +#define SUPPORT_SENSOR +#endif + +#ifdef SUPPORT_SENSOR + +static int sensor_okay; + +/* + * VSIM1 --> CAM_IOVDD --> IOVDD (1.8 V) + */ +static int tcm825x_sensor_power_on(void *data) +{ + int ret; + + if (!sensor_okay) + return -ENODEV; + + /* Set VMEM to 1.5V and VIO to 2.5V */ + ret = menelaus_set_vmem(1500); + if (ret < 0) { + /* Try once more, it seems the sensor power up causes + * some problems on the I2C bus. */ + ret = menelaus_set_vmem(1500); + if (ret < 0) + return ret; + } + msleep(1); + + ret = menelaus_set_vio(2500); + if (ret < 0) + return ret; + + /* Set VSim1 on */ + retu_write_reg(RETU_REG_CTRL_SET, 0x0080); + msleep(100); + + omap_set_gpio_dataout(N800_CAM_SENSOR_RESET_GPIO, 1); + msleep(1); + + return 0; +} + +static int tcm825x_sensor_power_off(void * data) +{ + int ret; + + omap_set_gpio_dataout(N800_CAM_SENSOR_RESET_GPIO, 0); + msleep(1); + + /* Set VSim1 off */ + retu_write_reg(RETU_REG_CTRL_CLR, 0x0080); + msleep(1); + + /* Set VIO_MODE to off */ + ret = menelaus_set_vio(0); + if (ret < 0) + return ret; + msleep(1); + + /* Set VMEM_MODE to off */ + ret = menelaus_set_vmem(0); + if (ret < 0) + return ret; + msleep(1); + + return 0; +} + +static struct omap_camera_sensor_config n800_sensor_config = { + .power_on = tcm825x_sensor_power_on, + .power_off = tcm825x_sensor_power_off, +}; + +static void __init n800_cam_init(void) +{ + int r; + + r = omap_request_gpio(N800_CAM_SENSOR_RESET_GPIO); + if (r < 0) + return; + + omap_set_gpio_dataout(N800_CAM_SENSOR_RESET_GPIO, 0); + omap_set_gpio_direction(N800_CAM_SENSOR_RESET_GPIO, 0); + + sensor_okay = 1; +} + +#else + +static inline void n800_cam_init(void) {} + +#endif + +static struct omap_board_config_kernel n800_config[] = { + { OMAP_TAG_UART, &n800_uart_config }, +#ifdef SUPPORT_SENSOR + { OMAP_TAG_CAMERA_SENSOR, &n800_sensor_config }, +#endif + { OMAP_TAG_FBMEM, &n800_fbmem0_config }, + { OMAP_TAG_FBMEM, &n800_fbmem1_config }, + { OMAP_TAG_FBMEM, &n800_fbmem2_config }, + { OMAP_TAG_TMP105, &n800_tmp105_config }, +}; + + +static int n800_get_keyb_irq_state(struct device *dev) +{ + return !omap_get_gpio_datain(N800_KEYB_IRQ_GPIO); +} + +static struct tsc2301_platform_data tsc2301_config = { + .reset_gpio = 118, + .dav_gpio = 103, + .pen_int_gpio = 106, + .keymap = { + -1, /* Event for bit 0 */ + KEY_UP, /* Event for bit 1 (up) */ + KEY_F5, /* Event for bit 2 (home) */ + -1, /* Event for bit 3 */ + KEY_LEFT, /* Event for bit 4 (left) */ + KEY_ENTER, /* Event for bit 5 (enter) */ + KEY_RIGHT, /* Event for bit 6 (right) */ + -1, /* Event for bit 7 */ + KEY_ESC, /* Event for bit 8 (cycle) */ + KEY_DOWN, /* Event for bit 9 (down) */ + KEY_F4, /* Event for bit 10 (menu) */ + -1, /* Event for bit 11 */ + KEY_F8, /* Event for bit 12 (Zoom-) */ + KEY_F6, /* Event for bit 13 (FS) */ + KEY_F7, /* Event for bit 14 (Zoom+) */ + -1, /* Event for bit 15 */ + }, + .kp_rep = 0, + .get_keyb_irq_state = n800_get_keyb_irq_state, +}; + +static void tsc2301_dev_init(void) +{ + int gpio = N800_KEYB_IRQ_GPIO; + + if (omap_request_gpio(gpio) < 0) { + printk(KERN_ERR "can't get KBIRQ GPIO\n"); + return; + } + omap_set_gpio_direction(gpio, 1); + tsc2301_config.keyb_int = OMAP_GPIO_IRQ(gpio); +} + +static struct omap2_mcspi_device_config tsc2301_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, +}; + +static struct omap2_mcspi_device_config mipid_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, +}; + +static struct omap2_mcspi_device_config cx3110x_mcspi_config = { + .turbo_mode = 0, + .single_channel = 1, +}; + +static struct spi_board_info n800_spi_board_info[] __initdata = { + [0] = { + .modalias = "lcd_mipid", + .bus_num = 1, + .chip_select = 1, + .max_speed_hz = 4000000, + .controller_data= &mipid_mcspi_config, + .platform_data = &n800_mipid_platform_data, + }, [1] = { + .modalias = "cx3110x", + .bus_num = 2, + .chip_select = 0, + .max_speed_hz = 48000000, + .controller_data= &cx3110x_mcspi_config, + }, [2] = { + .modalias = "tsc2301", + .bus_num = 1, + .chip_select = 0, + .max_speed_hz = 6000000, + .controller_data= &tsc2301_mcspi_config, + .platform_data = &tsc2301_config, + }, +}; + +#if defined(CONFIG_CBUS_RETU) && defined(CONFIG_LEDS_OMAP_PWM) + +void retu_keypad_led_set_power(struct omap_pwm_led_platform_data *self, + int on_off) +{ + if (on_off) { + retu_write_reg(RETU_REG_CTRL_SET, 1 << 6); + msleep(2); + retu_write_reg(RETU_REG_CTRL_SET, 1 << 3); + } else { + retu_write_reg(RETU_REG_CTRL_CLR, (1 << 6) | (1 << 3)); + } +} + +static struct omap_pwm_led_platform_data n800_keypad_led_data = { + .name = "keypad", + .intensity_timer = 10, + .blink_timer = 9, + .set_power = retu_keypad_led_set_power, +}; + +static struct platform_device n800_keypad_led_device = { + .name = "omap_pwm_led", + .id = -1, + .dev = { + .platform_data = &n800_keypad_led_data, + }, +}; +#endif + +#if defined(CONFIG_TOUCHSCREEN_TSC2301) +static void __init n800_ts_set_config(void) +{ + const struct omap_lcd_config *conf; + + conf = omap_get_config(OMAP_TAG_LCD, struct omap_lcd_config); + if (conf != NULL) { + if (strcmp(conf->panel_name, "lph8923") == 0) { + tsc2301_config.ts_x_plate_ohm = 180; + tsc2301_config.ts_hw_avg = 4; + tsc2301_config.ts_ignore_last = 1; + tsc2301_config.ts_max_pressure = 255; + tsc2301_config.ts_stab_time = 100; + } else if (strcmp(conf->panel_name, "ls041y3") == 0) { + tsc2301_config.ts_x_plate_ohm = 280; + tsc2301_config.ts_hw_avg = 16; + tsc2301_config.ts_touch_pressure= 215; + tsc2301_config.ts_max_pressure = 255; + tsc2301_config.ts_ignore_last = 1; + } else { + printk(KERN_ERR "Unknown panel type, set default " + "touchscreen configuration\n"); + tsc2301_config.ts_x_plate_ohm = 200; + tsc2301_config.ts_stab_time = 100; + } + } +} +#else +static inline void n800_ts_set_config(void) +{ +} +#endif + +static struct omap_gpio_switch n800_gpio_switches[] __initdata = { + { + .name = "bat_cover", + .gpio = -1, + .debounce_rising = 100, + .debounce_falling = 0, + .notify = n800_mmc_slot1_cover_handler, + .notify_data = NULL, + }, { + .name = "headphone", + .gpio = -1, + .debounce_rising = 200, + .debounce_falling = 200, + }, { + .name = "cam_act", + .gpio = -1, + .debounce_rising = 200, + .debounce_falling = 200, + }, { + .name = "cam_turn", + .gpio = -1, + .debounce_rising = 100, + .debounce_falling = 100, + }, +}; + +static struct platform_device *n800_devices[] __initdata = { +#if defined(CONFIG_CBUS_RETU) && defined(CONFIG_LEDS_OMAP_PWM) + &n800_keypad_led_device, +#endif +}; + +static void __init nokia_n800_init(void) +{ + platform_add_devices(n800_devices, ARRAY_SIZE(n800_devices)); + n800_flash_init(); + n800_mmc_init(); + n800_bt_init(); + n800_audio_init(&tsc2301_config); + n800_dsp_init(); + n800_usb_init(); + n800_cam_init(); + n800_ts_set_config(); + spi_register_board_info(n800_spi_board_info, + ARRAY_SIZE(n800_spi_board_info)); + omap_serial_init(); + mipid_dev_init(); + blizzard_dev_init(); + tsc2301_dev_init(); + omap_register_gpio_switches(n800_gpio_switches, + ARRAY_SIZE(n800_gpio_switches)); + n800_pm_init(); +} + +static void __init nokia_n800_map_io(void) +{ + omap_board_config = n800_config; + omap_board_config_size = ARRAY_SIZE(n800_config); + + omap2_map_common_io(); +} + +MACHINE_START(NOKIA_N800, "Nokia N800") + .phys_io = 0x48000000, + .io_pg_offst = ((0xd8000000) >> 18) & 0xfffc, + .boot_params = 0x80000100, + .map_io = nokia_n800_map_io, + .init_irq = nokia_n800_init_irq, + .init_machine = nokia_n800_init, + .timer = &omap_timer, +MACHINE_END Index: linux-2.6/include/asm-arm/arch-omap/board.h =================================================================== --- linux-2.6.orig/include/asm-arm/arch-omap/board.h 2007-04-16 20:50:00.000000000 +0000 +++ linux-2.6/include/asm-arm/arch-omap/board.h 2007-04-16 20:50:00.000000000 +0000 @@ -25,9 +25,12 @@ #define OMAP_TAG_FBMEM 0x4f08 #define OMAP_TAG_STI_CONSOLE 0x4f09 #define OMAP_TAG_CAMERA_SENSOR 0x4f0a +#define OMAP_TAG_PARTITION 0x4f0b +#define OMAP_TAG_TEA5761 0x4f10 +#define OMAP_TAG_TMP105 0x4f11 #define OMAP_TAG_BOOT_REASON 0x4f80 -#define OMAP_TAG_FLASH_PART 0x4f81 +#define OMAP_TAG_FLASH_PART_STR 0x4f81 #define OMAP_TAG_VERSION_STR 0x4f82 struct omap_clock_config { @@ -139,8 +142,25 @@ struct omap_uart_config { unsigned int enabled_uarts; }; +struct omap_tea5761_config { + u16 enable_gpio; +}; + +/* This cannot be passed from the bootloader */ +struct omap_tmp105_config { + u16 tmp105_irq_pin; + int (* set_power)(int enable); +}; + +struct omap_partition_config { + char name[16]; + unsigned int size; + unsigned int offset; + /* same as in include/linux/mtd/partitions.h */ + unsigned int mask_flags; +}; -struct omap_flash_part_config { +struct omap_flash_part_str_config { char part_table[0]; }; Index: linux-2.6/include/asm-arm/arch-omap/board-nokia.h =================================================================== --- linux-2.6.orig/include/asm-arm/arch-omap/board-nokia.h 2007-04-16 18:37:50.000000000 +0000 +++ linux-2.6/include/asm-arm/arch-omap/board-nokia.h 2007-04-16 20:50:29.000000000 +0000 @@ -11,12 +11,24 @@ #include <linux/types.h> +struct tsc2301_platform_data; +struct dsp_kfunc_device; +extern void n800_bt_init(void); +extern void n800_dsp_init(void); +extern void n800_flash_init(void); +extern void n800_mmc_init(void); +extern void n800_pm_init(void); +extern void n800_usb_init(void); +extern void n800_audio_init(struct tsc2301_platform_data *); +extern int n800_audio_enable(struct dsp_kfunc_device *kdev, int stage); +extern int n800_audio_disable(struct dsp_kfunc_device *kdev, int stage); +extern void n800_mmc_slot1_cover_handler(void *arg, int state); + #define OMAP_TAG_NOKIA_BT 0x4e01 #define OMAP_TAG_WLAN_CX3110X 0x4e02 #define OMAP_TAG_CBUS 0x4e03 #define OMAP_TAG_EM_ASIC_BB5 0x4e04 - #define BT_CHIP_CSR 1 #define BT_CHIP_TI 2 Index: linux-2.6/include/asm-arm/arch-omap/onenand.h =================================================================== --- linux-2.6.orig/include/asm-arm/arch-omap/onenand.h 2007-04-16 20:50:00.000000000 +0000 +++ linux-2.6/include/asm-arm/arch-omap/onenand.h 2007-04-16 20:50:00.000000000 +0000 @@ -16,4 +16,5 @@ struct omap_onenand_platform_data { int gpio_irq; struct mtd_partition *parts; int nr_parts; + int (*onenand_setup)(void __iomem *); }; ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2007-04-16 22:16 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2007-04-09 21:33 [PATCH 0/7] ARM: OMAP: Board updates and additions for OMAP2 Tony Lindgren 2007-04-09 21:33 ` [PATCH 1/7] ARM: OMAP: USB peripheral support on H4 Tony Lindgren 2007-04-09 21:33 ` [PATCH 2/7] ARM: OMAP: Fix typo in board-h4.h Tony Lindgren 2007-04-09 21:33 ` [PATCH 3/7] ARM: OMAP: Sync H4 board init with linux-omap Tony Lindgren 2007-04-09 21:33 ` [PATCH 4/7] ARM: OMAP: cleanup apollon board Tony Lindgren 2007-04-09 21:34 ` [PATCH 5/7] ARM: OMAP: Merge board specific files from N800 tree Tony Lindgren 2007-04-09 21:34 ` [PATCH 6/7] ARM: OMAP: Replace mach-omap/omap2 with mach-omap2 Tony Lindgren 2007-04-09 21:34 ` [PATCH 7/7] ARM: OMAP: Add apollon gpio keys using gpio-keys input Tony Lindgren 2007-04-16 21:41 ` [PATCH 5/7] ARM: OMAP: Merge board specific files from N800 tree Tony Lindgren
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox