diff options
Diffstat (limited to 'arch/arm/mach-ep93xx')
-rw-r--r-- | arch/arm/mach-ep93xx/Kconfig | 44 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/Makefile.boot | 9 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/clock.c | 216 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/core.c | 64 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/edb93xx.c | 31 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h | 46 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/include/mach/fb.h | 56 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/include/mach/gpio.h | 16 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/include/mach/memory.h | 6 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/include/mach/platform.h | 7 | ||||
-rw-r--r-- | arch/arm/mach-ep93xx/micro9.c | 133 |
11 files changed, 486 insertions, 142 deletions
diff --git a/arch/arm/mach-ep93xx/Kconfig b/arch/arm/mach-ep93xx/Kconfig index d7291c682a64..9167c3d2a5ed 100644 --- a/arch/arm/mach-ep93xx/Kconfig +++ b/arch/arm/mach-ep93xx/Kconfig @@ -17,13 +17,31 @@ config EP93XX_SDCE3_SYNC_PHYS_OFFSET bool "0x00000000 - SDCE3/SyncBoot" help Select this option if you want support for EP93xx boards with the - first SDRAM bank at 0x00000000 + first SDRAM bank at 0x00000000. config EP93XX_SDCE0_PHYS_OFFSET bool "0xc0000000 - SDCEO" help Select this option if you want support for EP93xx boards with the - first SDRAM bank at 0xc0000000 + first SDRAM bank at 0xc0000000. + +config EP93XX_SDCE1_PHYS_OFFSET + bool "0xd0000000 - SDCE1" + help + Select this option if you want support for EP93xx boards with the + first SDRAM bank at 0xd0000000. + +config EP93XX_SDCE2_PHYS_OFFSET + bool "0xe0000000 - SDCE2" + help + Select this option if you want support for EP93xx boards with the + first SDRAM bank at 0xe0000000. + +config EP93XX_SDCE3_ASYNC_PHYS_OFFSET + bool "0xf0000000 - SDCE3/AsyncBoot" + help + Select this option if you want support for EP93xx boards with the + first SDRAM bank at 0xf0000000. endchoice @@ -112,28 +130,36 @@ config MACH_MICRO9 bool config MACH_MICRO9H - bool "Support Contec Hypercontrol Micro9-H" + bool "Support Contec Micro9-High" depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET select MACH_MICRO9 help Say 'Y' here if you want your kernel to support the - Contec Hypercontrol Micro9-H board. + Contec Micro9-High board. config MACH_MICRO9M - bool "Support Contec Hypercontrol Micro9-M" - depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET + bool "Support Contec Micro9-Mid" + depends on EP93XX_SDCE3_ASYNC_PHYS_OFFSET select MACH_MICRO9 help Say 'Y' here if you want your kernel to support the - Contec Hypercontrol Micro9-M board. + Contec Micro9-Mid board. config MACH_MICRO9L - bool "Support Contec Hypercontrol Micro9-L" + bool "Support Contec Micro9-Lite" depends on EP93XX_SDCE3_SYNC_PHYS_OFFSET select MACH_MICRO9 help Say 'Y' here if you want your kernel to support the - Contec Hypercontrol Micro9-L board. + Contec Micro9-Lite board. + +config MACH_MICRO9S + bool "Support Contec Micro9-Slim" + depends on EP93XX_SDCE3_ASYNC_PHYS_OFFSET + select MACH_MICRO9 + help + Say 'Y' here if you want your kernel to support the + Contec Micro9-Slim board. config MACH_TS72XX bool "Support Technologic Systems TS-72xx SBC" diff --git a/arch/arm/mach-ep93xx/Makefile.boot b/arch/arm/mach-ep93xx/Makefile.boot index 27a085a8f12a..0ad33f15c622 100644 --- a/arch/arm/mach-ep93xx/Makefile.boot +++ b/arch/arm/mach-ep93xx/Makefile.boot @@ -3,3 +3,12 @@ params_phys-$(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET) := 0x00000100 zreladdr-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) := 0xc0008000 params_phys-$(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) := 0xc0000100 + + zreladdr-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) := 0xd0008000 +params_phys-$(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) := 0xd0000100 + + zreladdr-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) := 0xe0008000 +params_phys-$(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) := 0xe0000100 + + zreladdr-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) := 0xf0008000 +params_phys-$(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) := 0xf0000100 diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index 3dd0e2a23095..1d0f9d8aff2e 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -16,13 +16,16 @@ #include <linux/module.h> #include <linux/string.h> #include <linux/io.h> +#include <linux/spinlock.h> + +#include <mach/hardware.h> #include <asm/clkdev.h> #include <asm/div64.h> -#include <mach/hardware.h> struct clk { + struct clk *parent; unsigned long rate; int users; int sw_locked; @@ -37,91 +40,130 @@ struct clk { static unsigned long get_uart_rate(struct clk *clk); static int set_keytchclk_rate(struct clk *clk, unsigned long rate); +static int set_div_rate(struct clk *clk, unsigned long rate); +static struct clk clk_xtali = { + .rate = EP93XX_EXT_CLK_RATE, +}; static struct clk clk_uart1 = { + .parent = &clk_xtali, .sw_locked = 1, .enable_reg = EP93XX_SYSCON_DEVCFG, .enable_mask = EP93XX_SYSCON_DEVCFG_U1EN, .get_rate = get_uart_rate, }; static struct clk clk_uart2 = { + .parent = &clk_xtali, .sw_locked = 1, .enable_reg = EP93XX_SYSCON_DEVCFG, .enable_mask = EP93XX_SYSCON_DEVCFG_U2EN, .get_rate = get_uart_rate, }; static struct clk clk_uart3 = { + .parent = &clk_xtali, .sw_locked = 1, .enable_reg = EP93XX_SYSCON_DEVCFG, .enable_mask = EP93XX_SYSCON_DEVCFG_U3EN, .get_rate = get_uart_rate, }; -static struct clk clk_pll1; -static struct clk clk_f; -static struct clk clk_h; -static struct clk clk_p; -static struct clk clk_pll2; +static struct clk clk_pll1 = { + .parent = &clk_xtali, +}; +static struct clk clk_f = { + .parent = &clk_pll1, +}; +static struct clk clk_h = { + .parent = &clk_pll1, +}; +static struct clk clk_p = { + .parent = &clk_pll1, +}; +static struct clk clk_pll2 = { + .parent = &clk_xtali, +}; static struct clk clk_usb_host = { + .parent = &clk_pll2, .enable_reg = EP93XX_SYSCON_PWRCNT, .enable_mask = EP93XX_SYSCON_PWRCNT_USH_EN, }; static struct clk clk_keypad = { + .parent = &clk_xtali, .sw_locked = 1, .enable_reg = EP93XX_SYSCON_KEYTCHCLKDIV, .enable_mask = EP93XX_SYSCON_KEYTCHCLKDIV_KEN, .set_rate = set_keytchclk_rate, }; static struct clk clk_pwm = { + .parent = &clk_xtali, .rate = EP93XX_EXT_CLK_RATE, }; +static struct clk clk_video = { + .sw_locked = 1, + .enable_reg = EP93XX_SYSCON_VIDCLKDIV, + .enable_mask = EP93XX_SYSCON_CLKDIV_ENABLE, + .set_rate = set_div_rate, +}; + /* DMA Clocks */ static struct clk clk_m2p0 = { + .parent = &clk_h, .enable_reg = EP93XX_SYSCON_PWRCNT, .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P0, }; static struct clk clk_m2p1 = { + .parent = &clk_h, .enable_reg = EP93XX_SYSCON_PWRCNT, .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P1, }; static struct clk clk_m2p2 = { + .parent = &clk_h, .enable_reg = EP93XX_SYSCON_PWRCNT, .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P2, }; static struct clk clk_m2p3 = { + .parent = &clk_h, .enable_reg = EP93XX_SYSCON_PWRCNT, .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P3, }; static struct clk clk_m2p4 = { + .parent = &clk_h, .enable_reg = EP93XX_SYSCON_PWRCNT, .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P4, }; static struct clk clk_m2p5 = { + .parent = &clk_h, .enable_reg = EP93XX_SYSCON_PWRCNT, .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P5, }; static struct clk clk_m2p6 = { + .parent = &clk_h, .enable_reg = EP93XX_SYSCON_PWRCNT, .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P6, }; static struct clk clk_m2p7 = { + .parent = &clk_h, .enable_reg = EP93XX_SYSCON_PWRCNT, .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P7, }; static struct clk clk_m2p8 = { + .parent = &clk_h, .enable_reg = EP93XX_SYSCON_PWRCNT, .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P8, }; static struct clk clk_m2p9 = { + .parent = &clk_h, .enable_reg = EP93XX_SYSCON_PWRCNT, .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2P9, }; static struct clk clk_m2m0 = { + .parent = &clk_h, .enable_reg = EP93XX_SYSCON_PWRCNT, .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2M0, }; static struct clk clk_m2m1 = { + .parent = &clk_h, .enable_reg = EP93XX_SYSCON_PWRCNT, .enable_mask = EP93XX_SYSCON_PWRCNT_DMA_M2M1, }; @@ -130,6 +172,7 @@ static struct clk clk_m2m1 = { { .dev_id = dev, .con_id = con, .clk = ck } static struct clk_lookup clocks[] = { + INIT_CK(NULL, "xtali", &clk_xtali), INIT_CK("apb:uart1", NULL, &clk_uart1), INIT_CK("apb:uart2", NULL, &clk_uart2), INIT_CK("apb:uart3", NULL, &clk_uart3), @@ -140,6 +183,7 @@ static struct clk_lookup clocks[] = { INIT_CK(NULL, "pll2", &clk_pll2), INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), INIT_CK("ep93xx-keypad", NULL, &clk_keypad), + INIT_CK("ep93xx-fb", NULL, &clk_video), INIT_CK(NULL, "pwm_clk", &clk_pwm), INIT_CK(NULL, "m2p0", &clk_m2p0), INIT_CK(NULL, "m2p1", &clk_m2p1), @@ -155,48 +199,84 @@ static struct clk_lookup clocks[] = { INIT_CK(NULL, "m2m1", &clk_m2m1), }; +static DEFINE_SPINLOCK(clk_lock); + +static void __clk_enable(struct clk *clk) +{ + if (!clk->users++) { + if (clk->parent) + __clk_enable(clk->parent); + + if (clk->enable_reg) { + u32 v; + + v = __raw_readl(clk->enable_reg); + v |= clk->enable_mask; + if (clk->sw_locked) + ep93xx_syscon_swlocked_write(v, clk->enable_reg); + else + __raw_writel(v, clk->enable_reg); + } + } +} int clk_enable(struct clk *clk) { - if (!clk->users++ && clk->enable_reg) { - u32 value; + unsigned long flags; - value = __raw_readl(clk->enable_reg); - value |= clk->enable_mask; - if (clk->sw_locked) - ep93xx_syscon_swlocked_write(value, clk->enable_reg); - else - __raw_writel(value, clk->enable_reg); - } + if (!clk) + return -EINVAL; + + spin_lock_irqsave(&clk_lock, flags); + __clk_enable(clk); + spin_unlock_irqrestore(&clk_lock, flags); return 0; } EXPORT_SYMBOL(clk_enable); +static void __clk_disable(struct clk *clk) +{ + if (!--clk->users) { + if (clk->enable_reg) { + u32 v; + + v = __raw_readl(clk->enable_reg); + v &= ~clk->enable_mask; + if (clk->sw_locked) + ep93xx_syscon_swlocked_write(v, clk->enable_reg); + else + __raw_writel(v, clk->enable_reg); + } + + if (clk->parent) + __clk_disable(clk->parent); + } +} + void clk_disable(struct clk *clk) { - if (!--clk->users && clk->enable_reg) { - u32 value; + unsigned long flags; - value = __raw_readl(clk->enable_reg); - value &= ~clk->enable_mask; - if (clk->sw_locked) - ep93xx_syscon_swlocked_write(value, clk->enable_reg); - else - __raw_writel(value, clk->enable_reg); - } + if (!clk) + return; + + spin_lock_irqsave(&clk_lock, flags); + __clk_disable(clk); + spin_unlock_irqrestore(&clk_lock, flags); } EXPORT_SYMBOL(clk_disable); static unsigned long get_uart_rate(struct clk *clk) { + unsigned long rate = clk_get_rate(clk->parent); u32 value; value = __raw_readl(EP93XX_SYSCON_PWRCNT); if (value & EP93XX_SYSCON_PWRCNT_UARTBAUD) - return EP93XX_EXT_CLK_RATE; + return rate; else - return EP93XX_EXT_CLK_RATE / 2; + return rate / 2; } unsigned long clk_get_rate(struct clk *clk) @@ -236,6 +316,84 @@ static int set_keytchclk_rate(struct clk *clk, unsigned long rate) return 0; } +static int calc_clk_div(struct clk *clk, unsigned long rate, + int *psel, int *esel, int *pdiv, int *div) +{ + struct clk *mclk; + unsigned long max_rate, actual_rate, mclk_rate, rate_err = -1; + int i, found = 0, __div = 0, __pdiv = 0; + + /* Don't exceed the maximum rate */ + max_rate = max(max(clk_pll1.rate / 4, clk_pll2.rate / 4), + clk_xtali.rate / 4); + rate = min(rate, max_rate); + + /* + * Try the two pll's and the external clock + * Because the valid predividers are 2, 2.5 and 3, we multiply + * all the clocks by 2 to avoid floating point math. + * + * This is based on the algorithm in the ep93xx raster guide: + * http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf + * + */ + for (i = 0; i < 3; i++) { + if (i == 0) + mclk = &clk_xtali; + else if (i == 1) + mclk = &clk_pll1; + else + mclk = &clk_pll2; + mclk_rate = mclk->rate * 2; + + /* Try each predivider value */ + for (__pdiv = 4; __pdiv <= 6; __pdiv++) { + __div = mclk_rate / (rate * __pdiv); + if (__div < 2 || __div > 127) + continue; + + actual_rate = mclk_rate / (__pdiv * __div); + + if (!found || abs(actual_rate - rate) < rate_err) { + *pdiv = __pdiv - 3; + *div = __div; + *psel = (i == 2); + *esel = (i != 0); + clk->parent = mclk; + clk->rate = actual_rate; + rate_err = abs(actual_rate - rate); + found = 1; + } + } + } + + if (!found) + return -EINVAL; + + return 0; +} + +static int set_div_rate(struct clk *clk, unsigned long rate) +{ + int err, psel = 0, esel = 0, pdiv = 0, div = 0; + u32 val; + + err = calc_clk_div(clk, rate, &psel, &esel, &pdiv, &div); + if (err) + return err; + + /* Clear the esel, psel, pdiv and div bits */ + val = __raw_readl(clk->enable_reg); + val &= ~0x7fff; + + /* Set the new esel, psel, pdiv and div bits for the new clock rate */ + val |= (esel ? EP93XX_SYSCON_CLKDIV_ESEL : 0) | + (psel ? EP93XX_SYSCON_CLKDIV_PSEL : 0) | + (pdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | div; + ep93xx_syscon_swlocked_write(val, clk->enable_reg); + return 0; +} + int clk_set_rate(struct clk *clk, unsigned long rate) { if (clk->set_rate) @@ -258,7 +416,7 @@ static unsigned long calc_pll_rate(u32 config_word) unsigned long long rate; int i; - rate = EP93XX_EXT_CLK_RATE; + rate = clk_xtali.rate; rate *= ((config_word >> 11) & 0x1f) + 1; /* X1FBD */ rate *= ((config_word >> 5) & 0x3f) + 1; /* X2FBD */ do_div(rate, (config_word & 0x1f) + 1); /* X2IPD */ @@ -291,7 +449,7 @@ static int __init ep93xx_clock_init(void) value = __raw_readl(EP93XX_SYSCON_CLOCK_SET1); if (!(value & 0x00800000)) { /* PLL1 bypassed? */ - clk_pll1.rate = EP93XX_EXT_CLK_RATE; + clk_pll1.rate = clk_xtali.rate; } else { clk_pll1.rate = calc_pll_rate(value); } @@ -302,7 +460,7 @@ static int __init ep93xx_clock_init(void) value = __raw_readl(EP93XX_SYSCON_CLOCK_SET2); if (!(value & 0x00080000)) { /* PLL2 bypassed? */ - clk_pll2.rate = EP93XX_EXT_CLK_RATE; + clk_pll2.rate = clk_xtali.rate; } else if (value & 0x00040000) { /* PLL2 enabled? */ clk_pll2.rate = calc_pll_rate(value); } else { diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 16b92c37ec99..b4357c388d2e 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -30,6 +30,7 @@ #include <linux/i2c-gpio.h> #include <mach/hardware.h> +#include <mach/fb.h> #include <asm/mach/map.h> #include <asm/mach/time.h> @@ -205,7 +206,6 @@ static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc) for (i = 0; i < 8; i++) { if (status & (1 << i)) { int gpio_irq = gpio_to_irq(EP93XX_GPIO_LINE_B(0)) + i; - desc = irq_desc + gpio_irq; generic_handle_irq(gpio_irq); } } @@ -549,13 +549,11 @@ void __init ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr) platform_device_register(&ep93xx_eth_device); } -static struct i2c_gpio_platform_data ep93xx_i2c_data = { - .sda_pin = EP93XX_GPIO_LINE_EEDAT, - .sda_is_open_drain = 0, - .scl_pin = EP93XX_GPIO_LINE_EECLK, - .scl_is_open_drain = 0, - .udelay = 2, -}; + +/************************************************************************* + * EP93xx i2c peripheral handling + *************************************************************************/ +static struct i2c_gpio_platform_data ep93xx_i2c_data; static struct platform_device ep93xx_i2c_device = { .name = "i2c-gpio", @@ -563,8 +561,25 @@ static struct platform_device ep93xx_i2c_device = { .dev.platform_data = &ep93xx_i2c_data, }; -void __init ep93xx_register_i2c(struct i2c_board_info *devices, int num) +void __init ep93xx_register_i2c(struct i2c_gpio_platform_data *data, + struct i2c_board_info *devices, int num) { + /* + * Set the EEPROM interface pin drive type control. + * Defines the driver type for the EECLK and EEDAT pins as either + * open drain, which will require an external pull-up, or a normal + * CMOS driver. + */ + if (data->sda_is_open_drain && data->sda_pin != EP93XX_GPIO_LINE_EEDAT) + pr_warning("ep93xx: sda != EEDAT, open drain has no effect\n"); + if (data->scl_is_open_drain && data->scl_pin != EP93XX_GPIO_LINE_EECLK) + pr_warning("ep93xx: scl != EECLK, open drain has no effect\n"); + + __raw_writel((data->sda_is_open_drain << 1) | + (data->scl_is_open_drain << 0), + EP93XX_GPIO_EEDRIVE); + + ep93xx_i2c_data = *data; i2c_register_board_info(0, devices, num); platform_device_register(&ep93xx_i2c_device); } @@ -682,6 +697,37 @@ void ep93xx_pwm_release_gpio(struct platform_device *pdev) EXPORT_SYMBOL(ep93xx_pwm_release_gpio); +/************************************************************************* + * EP93xx video peripheral handling + *************************************************************************/ +static struct ep93xxfb_mach_info ep93xxfb_data; + +static struct resource ep93xx_fb_resource[] = { + { + .start = EP93XX_RASTER_PHYS_BASE, + .end = EP93XX_RASTER_PHYS_BASE + 0x800 - 1, + .flags = IORESOURCE_MEM, + }, +}; + +static struct platform_device ep93xx_fb_device = { + .name = "ep93xx-fb", + .id = -1, + .dev = { + .platform_data = &ep93xxfb_data, + .coherent_dma_mask = DMA_BIT_MASK(32), + .dma_mask = &ep93xx_fb_device.dev.coherent_dma_mask, + }, + .num_resources = ARRAY_SIZE(ep93xx_fb_resource), + .resource = ep93xx_fb_resource, +}; + +void __init ep93xx_register_fb(struct ep93xxfb_mach_info *data) +{ + ep93xxfb_data = *data; + platform_device_register(&ep93xx_fb_device); +} + extern void ep93xx_gpio_init(void); void __init ep93xx_init_devices(void) diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c index 73145ae5d3fa..a4a7be308000 100644 --- a/arch/arm/mach-ep93xx/edb93xx.c +++ b/arch/arm/mach-ep93xx/edb93xx.c @@ -27,8 +27,10 @@ #include <linux/kernel.h> #include <linux/init.h> #include <linux/platform_device.h> -#include <linux/i2c.h> #include <linux/mtd/physmap.h> +#include <linux/gpio.h> +#include <linux/i2c.h> +#include <linux/i2c-gpio.h> #include <mach/hardware.h> @@ -76,13 +78,26 @@ static struct ep93xx_eth_data edb93xx_eth_data = { .phy_id = 1, }; -static struct i2c_board_info __initdata edb93xxa_i2c_data[] = { + +/************************************************************************* + * EDB93xx i2c peripheral handling + *************************************************************************/ +static struct i2c_gpio_platform_data edb93xx_i2c_gpio_data = { + .sda_pin = EP93XX_GPIO_LINE_EEDAT, + .sda_is_open_drain = 0, + .scl_pin = EP93XX_GPIO_LINE_EECLK, + .scl_is_open_drain = 0, + .udelay = 0, /* default to 100 kHz */ + .timeout = 0, /* default to 100 ms */ +}; + +static struct i2c_board_info __initdata edb93xxa_i2c_board_info[] = { { I2C_BOARD_INFO("isl1208", 0x6f), }, }; -static struct i2c_board_info __initdata edb93xx_i2c_data[] = { +static struct i2c_board_info __initdata edb93xx_i2c_board_info[] = { { I2C_BOARD_INFO("ds1337", 0x68), }, @@ -92,12 +107,14 @@ static void __init edb93xx_register_i2c(void) { if (machine_is_edb9302a() || machine_is_edb9307a() || machine_is_edb9315a()) { - ep93xx_register_i2c(edb93xxa_i2c_data, - ARRAY_SIZE(edb93xxa_i2c_data)); + ep93xx_register_i2c(&edb93xx_i2c_gpio_data, + edb93xxa_i2c_board_info, + ARRAY_SIZE(edb93xxa_i2c_board_info)); } else if (machine_is_edb9307() || machine_is_edb9312() || machine_is_edb9315()) { - ep93xx_register_i2c(edb93xx_i2c_data, - ARRAY_SIZE(edb93xx_i2c_data)); + ep93xx_register_i2c(&edb93xx_i2c_gpio_data, + edb93xx_i2c_board_info, + ARRAY_SIZE(edb93xx_i2c_board_info)); } } diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h index ea78e908fc82..b1f937eda29c 100644 --- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h +++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h @@ -52,24 +52,27 @@ #define EP93XX_AHB_VIRT_BASE 0xfef00000 #define EP93XX_AHB_SIZE 0x00100000 +#define EP93XX_AHB_PHYS(x) (EP93XX_AHB_PHYS_BASE + (x)) #define EP93XX_AHB_IOMEM(x) IOMEM(EP93XX_AHB_VIRT_BASE + (x)) #define EP93XX_APB_PHYS_BASE 0x80800000 #define EP93XX_APB_VIRT_BASE 0xfed00000 #define EP93XX_APB_SIZE 0x00200000 +#define EP93XX_APB_PHYS(x) (EP93XX_APB_PHYS_BASE + (x)) #define EP93XX_APB_IOMEM(x) IOMEM(EP93XX_APB_VIRT_BASE + (x)) /* AHB peripherals */ #define EP93XX_DMA_BASE EP93XX_AHB_IOMEM(0x00000000) -#define EP93XX_ETHERNET_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00010000) +#define EP93XX_ETHERNET_PHYS_BASE EP93XX_AHB_PHYS(0x00010000) #define EP93XX_ETHERNET_BASE EP93XX_AHB_IOMEM(0x00010000) -#define EP93XX_USB_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00020000) +#define EP93XX_USB_PHYS_BASE EP93XX_AHB_PHYS(0x00020000) #define EP93XX_USB_BASE EP93XX_AHB_IOMEM(0x00020000) +#define EP93XX_RASTER_PHYS_BASE EP93XX_AHB_PHYS(0x00030000) #define EP93XX_RASTER_BASE EP93XX_AHB_IOMEM(0x00030000) #define EP93XX_GRAPHICS_ACCEL_BASE EP93XX_AHB_IOMEM(0x00040000) @@ -111,21 +114,10 @@ #define EP93XX_GPIO_BASE EP93XX_APB_IOMEM(0x00040000) #define EP93XX_GPIO_REG(x) (EP93XX_GPIO_BASE + (x)) -#define EP93XX_GPIO_F_INT_TYPE1 EP93XX_GPIO_REG(0x4c) -#define EP93XX_GPIO_F_INT_TYPE2 EP93XX_GPIO_REG(0x50) -#define EP93XX_GPIO_F_INT_ACK EP93XX_GPIO_REG(0x54) -#define EP93XX_GPIO_F_INT_ENABLE EP93XX_GPIO_REG(0x58) #define EP93XX_GPIO_F_INT_STATUS EP93XX_GPIO_REG(0x5c) -#define EP93XX_GPIO_A_INT_TYPE1 EP93XX_GPIO_REG(0x90) -#define EP93XX_GPIO_A_INT_TYPE2 EP93XX_GPIO_REG(0x94) -#define EP93XX_GPIO_A_INT_ACK EP93XX_GPIO_REG(0x98) -#define EP93XX_GPIO_A_INT_ENABLE EP93XX_GPIO_REG(0x9c) #define EP93XX_GPIO_A_INT_STATUS EP93XX_GPIO_REG(0xa0) -#define EP93XX_GPIO_B_INT_TYPE1 EP93XX_GPIO_REG(0xac) -#define EP93XX_GPIO_B_INT_TYPE2 EP93XX_GPIO_REG(0xb0) -#define EP93XX_GPIO_B_INT_ACK EP93XX_GPIO_REG(0xb4) -#define EP93XX_GPIO_B_INT_ENABLE EP93XX_GPIO_REG(0xb8) #define EP93XX_GPIO_B_INT_STATUS EP93XX_GPIO_REG(0xbc) +#define EP93XX_GPIO_EEDRIVE EP93XX_GPIO_REG(0xc8) #define EP93XX_AAC_BASE EP93XX_APB_IOMEM(0x00080000) @@ -133,13 +125,13 @@ #define EP93XX_IRDA_BASE EP93XX_APB_IOMEM(0x000b0000) -#define EP93XX_UART1_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x000c0000) +#define EP93XX_UART1_PHYS_BASE EP93XX_APB_PHYS(0x000c0000) #define EP93XX_UART1_BASE EP93XX_APB_IOMEM(0x000c0000) -#define EP93XX_UART2_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x000d0000) +#define EP93XX_UART2_PHYS_BASE EP93XX_APB_PHYS(0x000d0000) #define EP93XX_UART2_BASE EP93XX_APB_IOMEM(0x000d0000) -#define EP93XX_UART3_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x000e0000) +#define EP93XX_UART3_PHYS_BASE EP93XX_APB_PHYS(0x000e0000) #define EP93XX_UART3_BASE EP93XX_APB_IOMEM(0x000e0000) #define EP93XX_KEY_MATRIX_BASE EP93XX_APB_IOMEM(0x000f0000) @@ -147,10 +139,10 @@ #define EP93XX_ADC_BASE EP93XX_APB_IOMEM(0x00100000) #define EP93XX_TOUCHSCREEN_BASE EP93XX_APB_IOMEM(0x00100000) -#define EP93XX_PWM_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x00110000) +#define EP93XX_PWM_PHYS_BASE EP93XX_APB_PHYS(0x00110000) #define EP93XX_PWM_BASE EP93XX_APB_IOMEM(0x00110000) -#define EP93XX_RTC_PHYS_BASE (EP93XX_APB_PHYS_BASE + 0x00120000) +#define EP93XX_RTC_PHYS_BASE EP93XX_APB_PHYS(0x00120000) #define EP93XX_RTC_BASE EP93XX_APB_IOMEM(0x00120000) #define EP93XX_SYSCON_BASE EP93XX_APB_IOMEM(0x00130000) @@ -207,11 +199,27 @@ #define EP93XX_SYSCON_DEVCFG_ADCPD (1<<2) #define EP93XX_SYSCON_DEVCFG_KEYS (1<<1) #define EP93XX_SYSCON_DEVCFG_SHENA (1<<0) +#define EP93XX_SYSCON_VIDCLKDIV EP93XX_SYSCON_REG(0x84) +#define EP93XX_SYSCON_CLKDIV_ENABLE (1<<15) +#define EP93XX_SYSCON_CLKDIV_ESEL (1<<14) +#define EP93XX_SYSCON_CLKDIV_PSEL (1<<13) +#define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8 #define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90) #define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN (1<<31) #define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV (1<<16) #define EP93XX_SYSCON_KEYTCHCLKDIV_KEN (1<<15) #define EP93XX_SYSCON_KEYTCHCLKDIV_KDIV (1<<0) +#define EP93XX_SYSCON_SYSCFG EP93XX_SYSCON_REG(0x9c) +#define EP93XX_SYSCON_SYSCFG_REV_MASK (0xf0000000) +#define EP93XX_SYSCON_SYSCFG_REV_SHIFT (28) +#define EP93XX_SYSCON_SYSCFG_SBOOT (1<<8) +#define EP93XX_SYSCON_SYSCFG_LCSN7 (1<<7) +#define EP93XX_SYSCON_SYSCFG_LCSN6 (1<<6) +#define EP93XX_SYSCON_SYSCFG_LASDO (1<<5) +#define EP93XX_SYSCON_SYSCFG_LEEDA (1<<4) +#define EP93XX_SYSCON_SYSCFG_LEECLK (1<<3) +#define EP93XX_SYSCON_SYSCFG_LCSN2 (1<<1) +#define EP93XX_SYSCON_SYSCFG_LCSN1 (1<<0) #define EP93XX_SYSCON_SWLOCK EP93XX_SYSCON_REG(0xc0) #define EP93XX_WATCHDOG_BASE EP93XX_APB_IOMEM(0x00140000) diff --git a/arch/arm/mach-ep93xx/include/mach/fb.h b/arch/arm/mach-ep93xx/include/mach/fb.h new file mode 100644 index 000000000000..d5ae11d7c453 --- /dev/null +++ b/arch/arm/mach-ep93xx/include/mach/fb.h @@ -0,0 +1,56 @@ +/* + * arch/arm/mach-ep93xx/include/mach/fb.h + */ + +#ifndef __ASM_ARCH_EP93XXFB_H +#define __ASM_ARCH_EP93XXFB_H + +struct platform_device; +struct fb_videomode; +struct fb_info; + +#define EP93XXFB_USE_MODEDB 0 + +/* VideoAttributes flags */ +#define EP93XXFB_STATE_MACHINE_ENABLE (1 << 0) +#define EP93XXFB_PIXEL_CLOCK_ENABLE (1 << 1) +#define EP93XXFB_VSYNC_ENABLE (1 << 2) +#define EP93XXFB_PIXEL_DATA_ENABLE (1 << 3) +#define EP93XXFB_COMPOSITE_SYNC (1 << 4) +#define EP93XXFB_SYNC_VERT_HIGH (1 << 5) +#define EP93XXFB_SYNC_HORIZ_HIGH (1 << 6) +#define EP93XXFB_SYNC_BLANK_HIGH (1 << 7) +#define EP93XXFB_PCLK_FALLING (1 << 8) +#define EP93XXFB_ENABLE_AC (1 << 9) +#define EP93XXFB_ENABLE_LCD (1 << 10) +#define EP93XXFB_ENABLE_CCIR (1 << 12) +#define EP93XXFB_USE_PARALLEL_INTERFACE (1 << 13) +#define EP93XXFB_ENABLE_INTERRUPT (1 << 14) +#define EP93XXFB_USB_INTERLACE (1 << 16) +#define EP93XXFB_USE_EQUALIZATION (1 << 17) +#define EP93XXFB_USE_DOUBLE_HORZ (1 << 18) +#define EP93XXFB_USE_DOUBLE_VERT (1 << 19) +#define EP93XXFB_USE_BLANK_PIXEL (1 << 20) +#define EP93XXFB_USE_SDCSN0 (0 << 21) +#define EP93XXFB_USE_SDCSN1 (1 << 21) +#define EP93XXFB_USE_SDCSN2 (2 << 21) +#define EP93XXFB_USE_SDCSN3 (3 << 21) + +#define EP93XXFB_ENABLE (EP93XXFB_STATE_MACHINE_ENABLE | \ + EP93XXFB_PIXEL_CLOCK_ENABLE | \ + EP93XXFB_VSYNC_ENABLE | \ + EP93XXFB_PIXEL_DATA_ENABLE) + +struct ep93xxfb_mach_info { + unsigned int num_modes; + const struct fb_videomode *modes; + const struct fb_videomode *default_mode; + int bpp; + unsigned int flags; + + int (*setup)(struct platform_device *pdev); + void (*teardown)(struct platform_device *pdev); + void (*blank)(int blank_mode, struct fb_info *info); +}; + +#endif /* __ASM_ARCH_EP93XXFB_H */ diff --git a/arch/arm/mach-ep93xx/include/mach/gpio.h b/arch/arm/mach-ep93xx/include/mach/gpio.h index 0a1498ae899a..c991b149bdf2 100644 --- a/arch/arm/mach-ep93xx/include/mach/gpio.h +++ b/arch/arm/mach-ep93xx/include/mach/gpio.h @@ -114,17 +114,9 @@ extern void ep93xx_gpio_int_debounce(unsigned int irq, int enable); * B0..B7 (7..15) to irq 72..79, and * F0..F7 (16..24) to irq 80..87. */ -static inline int gpio_to_irq(unsigned gpio) -{ - if (gpio <= EP93XX_GPIO_LINE_MAX_IRQ) - return 64 + gpio; - - return -EINVAL; -} - -static inline int irq_to_gpio(unsigned irq) -{ - return irq - gpio_to_irq(0); -} +#define gpio_to_irq(gpio) \ + (((gpio) <= EP93XX_GPIO_LINE_MAX_IRQ) ? (64 + (gpio)) : -EINVAL) + +#define irq_to_gpio(irq) ((irq) - gpio_to_irq(0)) #endif diff --git a/arch/arm/mach-ep93xx/include/mach/memory.h b/arch/arm/mach-ep93xx/include/mach/memory.h index 925b12ea0990..554064e90307 100644 --- a/arch/arm/mach-ep93xx/include/mach/memory.h +++ b/arch/arm/mach-ep93xx/include/mach/memory.h @@ -9,6 +9,12 @@ #define PHYS_OFFSET UL(0x00000000) #elif defined(CONFIG_EP93XX_SDCE0_PHYS_OFFSET) #define PHYS_OFFSET UL(0xc0000000) +#elif defined(CONFIG_EP93XX_SDCE1_PHYS_OFFSET) +#define PHYS_OFFSET UL(0xd0000000) +#elif defined(CONFIG_EP93XX_SDCE2_PHYS_OFFSET) +#define PHYS_OFFSET UL(0xe0000000) +#elif defined(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET) +#define PHYS_OFFSET UL(0xf0000000) #else #error "Kconfig bug: No EP93xx PHYS_OFFSET set" #endif diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h index 5f5fa6574d34..469fd968d517 100644 --- a/arch/arm/mach-ep93xx/include/mach/platform.h +++ b/arch/arm/mach-ep93xx/include/mach/platform.h @@ -4,8 +4,10 @@ #ifndef __ASSEMBLY__ +struct i2c_gpio_platform_data; struct i2c_board_info; struct platform_device; +struct ep93xxfb_mach_info; struct ep93xx_eth_data { @@ -15,7 +17,6 @@ struct ep93xx_eth_data void ep93xx_map_io(void); void ep93xx_init_irq(void); -void ep93xx_init_time(unsigned long); /* EP93xx System Controller software locked register write */ void ep93xx_syscon_swlocked_write(unsigned int val, void __iomem *reg); @@ -32,7 +33,9 @@ static inline void ep93xx_devcfg_clear_bits(unsigned int bits) } void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr); -void ep93xx_register_i2c(struct i2c_board_info *devices, int num); +void ep93xx_register_i2c(struct i2c_gpio_platform_data *data, + struct i2c_board_info *devices, int num); +void ep93xx_register_fb(struct ep93xxfb_mach_info *data); void ep93xx_register_pwm(int pwm0, int pwm1); int ep93xx_pwm_acquire_gpio(struct platform_device *pdev); void ep93xx_pwm_release_gpio(struct platform_device *pdev); diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c index 0a313e82fb74..f3757a1c5a10 100644 --- a/arch/arm/mach-ep93xx/micro9.c +++ b/arch/arm/mach-ep93xx/micro9.c @@ -2,7 +2,9 @@ * linux/arch/arm/mach-ep93xx/micro9.c * * Copyright (C) 2006 Contec Steuerungstechnik & Automation GmbH - * Manfred Gruber <manfred.gruber@contec.at> + * Manfred Gruber <m.gruber@tirol.com> + * Copyright (C) 2009 Contec Steuerungstechnik & Automation GmbH + * Hubert Feurstein <hubert.feurstein@contec.at> * * 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 @@ -13,6 +15,7 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/mtd/physmap.h> +#include <linux/io.h> #include <mach/hardware.h> @@ -20,104 +23,124 @@ #include <asm/mach/arch.h> -static struct ep93xx_eth_data micro9_eth_data = { - .phy_id = 0x1f, -}; - -static void __init micro9_init(void) -{ - ep93xx_register_eth(µ9_eth_data, 1); -} - -/* - * Micro9-H - */ -#ifdef CONFIG_MACH_MICRO9H -static struct physmap_flash_data micro9h_flash_data = { - .width = 4, -}; - -static struct resource micro9h_flash_resource = { +/************************************************************************* + * Micro9 NOR Flash + * + * Micro9-High has up to 64MB of 32-bit flash on CS1 + * Micro9-Mid has up to 64MB of either 32-bit or 16-bit flash on CS1 + * Micro9-Lite uses a seperate MTD map driver for flash support + * Micro9-Slim has up to 64MB of either 32-bit or 16-bit flash on CS1 + *************************************************************************/ +static struct physmap_flash_data micro9_flash_data; + +static struct resource micro9_flash_resource = { .start = EP93XX_CS1_PHYS_BASE, .end = EP93XX_CS1_PHYS_BASE + SZ_64M - 1, .flags = IORESOURCE_MEM, }; -static struct platform_device micro9h_flash = { +static struct platform_device micro9_flash = { .name = "physmap-flash", .id = 0, .dev = { - .platform_data = µ9h_flash_data, + .platform_data = µ9_flash_data, }, .num_resources = 1, - .resource = µ9h_flash_resource, + .resource = µ9_flash_resource, }; -static void __init micro9h_init(void) +static void __init __micro9_register_flash(unsigned int width) +{ + micro9_flash_data.width = width; + + platform_device_register(µ9_flash); +} + +static unsigned int __init micro9_detect_bootwidth(void) +{ + u32 v; + + /* Detect the bus width of the external flash memory */ + v = __raw_readl(EP93XX_SYSCON_SYSCFG); + if (v & EP93XX_SYSCON_SYSCFG_LCSN7) + return 4; /* 32-bit */ + else + return 2; /* 16-bit */ +} + +static void __init micro9_register_flash(void) { - platform_device_register(µ9h_flash); + if (machine_is_micro9()) + __micro9_register_flash(4); + else if (machine_is_micro9m() || machine_is_micro9s()) + __micro9_register_flash(micro9_detect_bootwidth()); } -static void __init micro9h_init_machine(void) + +/************************************************************************* + * Micro9 Ethernet + *************************************************************************/ +static struct ep93xx_eth_data micro9_eth_data = { + .phy_id = 0x1f, +}; + + +static void __init micro9_init_machine(void) { ep93xx_init_devices(); - micro9_init(); - micro9h_init(); + ep93xx_register_eth(µ9_eth_data, 1); + micro9_register_flash(); } -MACHINE_START(MICRO9, "Contec Hypercontrol Micro9-H") - /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */ + +#ifdef CONFIG_MACH_MICRO9H +MACHINE_START(MICRO9, "Contec Micro9-High") + /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */ .phys_io = EP93XX_APB_PHYS_BASE, .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, .timer = &ep93xx_timer, - .init_machine = micro9h_init_machine, + .init_machine = micro9_init_machine, MACHINE_END #endif -/* - * Micro9-M - */ #ifdef CONFIG_MACH_MICRO9M -static void __init micro9m_init_machine(void) -{ - ep93xx_init_devices(); - micro9_init(); -} - -MACHINE_START(MICRO9M, "Contec Hypercontrol Micro9-M") - /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */ +MACHINE_START(MICRO9M, "Contec Micro9-Mid") + /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */ .phys_io = EP93XX_APB_PHYS_BASE, .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, - .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, + .boot_params = EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, .timer = &ep93xx_timer, - .init_machine = micro9m_init_machine, + .init_machine = micro9_init_machine, MACHINE_END #endif -/* - * Micro9-L - */ #ifdef CONFIG_MACH_MICRO9L -static void __init micro9l_init_machine(void) -{ - ep93xx_init_devices(); - micro9_init(); -} - -MACHINE_START(MICRO9L, "Contec Hypercontrol Micro9-L") - /* Maintainer: Manfred Gruber <manfred.gruber@contec.at> */ +MACHINE_START(MICRO9L, "Contec Micro9-Lite") + /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */ .phys_io = EP93XX_APB_PHYS_BASE, .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, .boot_params = EP93XX_SDCE3_PHYS_BASE_SYNC + 0x100, .map_io = ep93xx_map_io, .init_irq = ep93xx_init_irq, .timer = &ep93xx_timer, - .init_machine = micro9l_init_machine, + .init_machine = micro9_init_machine, MACHINE_END #endif +#ifdef CONFIG_MACH_MICRO9S +MACHINE_START(MICRO9S, "Contec Micro9-Slim") + /* Maintainer: Hubert Feurstein <hubert.feurstein@contec.at> */ + .phys_io = EP93XX_APB_PHYS_BASE, + .io_pg_offst = ((EP93XX_APB_VIRT_BASE) >> 18) & 0xfffc, + .boot_params = EP93XX_SDCE3_PHYS_BASE_ASYNC + 0x100, + .map_io = ep93xx_map_io, + .init_irq = ep93xx_init_irq, + .timer = &ep93xx_timer, + .init_machine = micro9_init_machine, +MACHINE_END +#endif |