#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>
#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>
#include <asm/delay.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 };
};
static struct resource h4_flash_resource = {
- .start = H4_CS0_BASE,
- .end = H4_CS0_BASE + SZ_64M - 1,
.flags = IORESOURCE_MEM,
};
.resource = &h4_flash_resource,
};
-static struct resource h4_smc91x_resources[] = {
- [0] = {
- .start = OMAP24XX_ETHR_START, /* Physical */
- .end = OMAP24XX_ETHR_START + 0xf,
- .flags = IORESOURCE_MEM,
- },
- [1] = {
- .start = OMAP_GPIO_IRQ(OMAP24XX_ETHR_GPIO_IRQ),
- .end = OMAP_GPIO_IRQ(OMAP24XX_ETHR_GPIO_IRQ),
- .flags = IORESOURCE_IRQ,
- },
-};
-
-static struct platform_device h4_smc91x_device = {
- .name = "smc91x",
- .id = -1,
- .num_resources = ARRAY_SIZE(h4_smc91x_resources),
- .resource = h4_smc91x_resources,
-};
-
/* 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;
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,
};
static struct platform_device *h4_devices[] __initdata = {
- &h4_smc91x_device,
&h4_flash_device,
&h4_irda_device,
&h4_kp_device,
&h4_lcd_device,
};
-static inline void __init h4_init_smc91x(void)
+/* 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);
- if (omap_request_gpio(OMAP24XX_ETHR_GPIO_IRQ) < 0) {
- printk(KERN_ERR "Failed to request GPIO%d for smc91x IRQ\n",
- OMAP24XX_ETHR_GPIO_IRQ);
+ if (debug_card_init(cs_mem_base, OMAP24XX_ETHR_GPIO_IRQ) < 0)
+ 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;
}
- omap_set_gpio_direction(OMAP24XX_ETHR_GPIO_IRQ, 1);
+ 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_smc91x();
+ h4_init_flash();
}
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 = {
.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 },
+};
+
+#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;
+ dmachan = (1 << 1) | (1 << 0);
+#if !(defined(CONFIG_MTD_OMAP_NOR) || defined(CONFIG_MTD_OMAP_NOR_MODULE))
+ dmachan |= (1 << 5) | (1 << 4) (1 << 3) | (1 << 2);
+#endif
+ 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)
{
/*
}
#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);
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)