aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRyan Mallon <ryan@bluewatersys.com>2009-09-22 19:47:09 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2009-09-23 10:39:51 -0400
commitc6012189a40d33213ead5d15769fab615443206f (patch)
tree56682b59b54f18f0134d373e309121f87a907297
parentd63870db3c41086d7f13ec8b41def4331db32327 (diff)
ep93xx video driver platform support
Signed-off-by: Ryan Mallon <ryan@bluewatersys.com> Acked-by: H Hartley Sweeten <hsweeten@visionengravers.com> Cc: Daniele Venzano <linux@brownhat.org> Cc: Russell King <rmk@arm.linux.org.uk> Cc: Krzysztof Helt <krzysztof.h1@poczta.fm> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/arm/mach-ep93xx/clock.c88
-rw-r--r--arch/arm/mach-ep93xx/core.c32
-rw-r--r--arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h6
-rw-r--r--arch/arm/mach-ep93xx/include/mach/fb.h56
-rw-r--r--arch/arm/mach-ep93xx/include/mach/platform.h2
5 files changed, 183 insertions, 1 deletions
diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c
index 3dd0e2a23095..dda19cd76194 100644
--- a/arch/arm/mach-ep93xx/clock.c
+++ b/arch/arm/mach-ep93xx/clock.c
@@ -37,7 +37,7 @@ struct clk {
37static unsigned long get_uart_rate(struct clk *clk); 37static unsigned long get_uart_rate(struct clk *clk);
38 38
39static int set_keytchclk_rate(struct clk *clk, unsigned long rate); 39static int set_keytchclk_rate(struct clk *clk, unsigned long rate);
40 40static int set_div_rate(struct clk *clk, unsigned long rate);
41 41
42static struct clk clk_uart1 = { 42static struct clk clk_uart1 = {
43 .sw_locked = 1, 43 .sw_locked = 1,
@@ -76,6 +76,13 @@ static struct clk clk_pwm = {
76 .rate = EP93XX_EXT_CLK_RATE, 76 .rate = EP93XX_EXT_CLK_RATE,
77}; 77};
78 78
79static struct clk clk_video = {
80 .sw_locked = 1,
81 .enable_reg = EP93XX_SYSCON_VIDCLKDIV,
82 .enable_mask = EP93XX_SYSCON_CLKDIV_ENABLE,
83 .set_rate = set_div_rate,
84};
85
79/* DMA Clocks */ 86/* DMA Clocks */
80static struct clk clk_m2p0 = { 87static struct clk clk_m2p0 = {
81 .enable_reg = EP93XX_SYSCON_PWRCNT, 88 .enable_reg = EP93XX_SYSCON_PWRCNT,
@@ -140,6 +147,7 @@ static struct clk_lookup clocks[] = {
140 INIT_CK(NULL, "pll2", &clk_pll2), 147 INIT_CK(NULL, "pll2", &clk_pll2),
141 INIT_CK("ep93xx-ohci", NULL, &clk_usb_host), 148 INIT_CK("ep93xx-ohci", NULL, &clk_usb_host),
142 INIT_CK("ep93xx-keypad", NULL, &clk_keypad), 149 INIT_CK("ep93xx-keypad", NULL, &clk_keypad),
150 INIT_CK("ep93xx-fb", NULL, &clk_video),
143 INIT_CK(NULL, "pwm_clk", &clk_pwm), 151 INIT_CK(NULL, "pwm_clk", &clk_pwm),
144 INIT_CK(NULL, "m2p0", &clk_m2p0), 152 INIT_CK(NULL, "m2p0", &clk_m2p0),
145 INIT_CK(NULL, "m2p1", &clk_m2p1), 153 INIT_CK(NULL, "m2p1", &clk_m2p1),
@@ -236,6 +244,84 @@ static int set_keytchclk_rate(struct clk *clk, unsigned long rate)
236 return 0; 244 return 0;
237} 245}
238 246
247static unsigned long calc_clk_div(unsigned long rate, int *psel, int *esel,
248 int *pdiv, int *div)
249{
250 unsigned long max_rate, best_rate = 0,
251 actual_rate = 0, mclk_rate = 0, rate_err = -1;
252 int i, found = 0, __div = 0, __pdiv = 0;
253
254 /* Don't exceed the maximum rate */
255 max_rate = max(max(clk_pll1.rate / 4, clk_pll2.rate / 4),
256 (unsigned long)EP93XX_EXT_CLK_RATE / 4);
257 rate = min(rate, max_rate);
258
259 /*
260 * Try the two pll's and the external clock
261 * Because the valid predividers are 2, 2.5 and 3, we multiply
262 * all the clocks by 2 to avoid floating point math.
263 *
264 * This is based on the algorithm in the ep93xx raster guide:
265 * http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf
266 *
267 */
268 for (i = 0; i < 3; i++) {
269 if (i == 0)
270 mclk_rate = EP93XX_EXT_CLK_RATE * 2;
271 else if (i == 1)
272 mclk_rate = clk_pll1.rate * 2;
273 else if (i == 2)
274 mclk_rate = clk_pll2.rate * 2;
275
276 /* Try each predivider value */
277 for (__pdiv = 4; __pdiv <= 6; __pdiv++) {
278 __div = mclk_rate / (rate * __pdiv);
279 if (__div < 2 || __div > 127)
280 continue;
281
282 actual_rate = mclk_rate / (__pdiv * __div);
283
284 if (!found || abs(actual_rate - rate) < rate_err) {
285 *pdiv = __pdiv - 3;
286 *div = __div;
287 *psel = (i == 2);
288 *esel = (i != 0);
289 best_rate = actual_rate;
290 rate_err = abs(actual_rate - rate);
291 found = 1;
292 }
293 }
294 }
295
296 if (!found)
297 return 0;
298
299 return best_rate;
300}
301
302static int set_div_rate(struct clk *clk, unsigned long rate)
303{
304 unsigned long actual_rate;
305 int psel = 0, esel = 0, pdiv = 0, div = 0;
306 u32 val;
307
308 actual_rate = calc_clk_div(rate, &psel, &esel, &pdiv, &div);
309 if (actual_rate == 0)
310 return -EINVAL;
311 clk->rate = actual_rate;
312
313 /* Clear the esel, psel, pdiv and div bits */
314 val = __raw_readl(clk->enable_reg);
315 val &= ~0x7fff;
316
317 /* Set the new esel, psel, pdiv and div bits for the new clock rate */
318 val |= (esel ? EP93XX_SYSCON_CLKDIV_ESEL : 0) |
319 (psel ? EP93XX_SYSCON_CLKDIV_PSEL : 0) |
320 (pdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | div;
321 ep93xx_syscon_swlocked_write(val, clk->enable_reg);
322 return 0;
323}
324
239int clk_set_rate(struct clk *clk, unsigned long rate) 325int clk_set_rate(struct clk *clk, unsigned long rate)
240{ 326{
241 if (clk->set_rate) 327 if (clk->set_rate)
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index 16b92c37ec99..f7ebed942f66 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -30,6 +30,7 @@
30#include <linux/i2c-gpio.h> 30#include <linux/i2c-gpio.h>
31 31
32#include <mach/hardware.h> 32#include <mach/hardware.h>
33#include <mach/fb.h>
33 34
34#include <asm/mach/map.h> 35#include <asm/mach/map.h>
35#include <asm/mach/time.h> 36#include <asm/mach/time.h>
@@ -682,6 +683,37 @@ void ep93xx_pwm_release_gpio(struct platform_device *pdev)
682EXPORT_SYMBOL(ep93xx_pwm_release_gpio); 683EXPORT_SYMBOL(ep93xx_pwm_release_gpio);
683 684
684 685
686/*************************************************************************
687 * EP93xx video peripheral handling
688 *************************************************************************/
689static struct ep93xxfb_mach_info ep93xxfb_data;
690
691static struct resource ep93xx_fb_resource[] = {
692 {
693 .start = EP93XX_RASTER_PHYS_BASE,
694 .end = EP93XX_RASTER_PHYS_BASE + 0x800 - 1,
695 .flags = IORESOURCE_MEM,
696 },
697};
698
699static struct platform_device ep93xx_fb_device = {
700 .name = "ep93xx-fb",
701 .id = -1,
702 .dev = {
703 .platform_data = &ep93xxfb_data,
704 .coherent_dma_mask = DMA_BIT_MASK(32),
705 .dma_mask = &ep93xx_fb_device.dev.coherent_dma_mask,
706 },
707 .num_resources = ARRAY_SIZE(ep93xx_fb_resource),
708 .resource = ep93xx_fb_resource,
709};
710
711void __init ep93xx_register_fb(struct ep93xxfb_mach_info *data)
712{
713 ep93xxfb_data = *data;
714 platform_device_register(&ep93xx_fb_device);
715}
716
685extern void ep93xx_gpio_init(void); 717extern void ep93xx_gpio_init(void);
686 718
687void __init ep93xx_init_devices(void) 719void __init ep93xx_init_devices(void)
diff --git a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
index ea78e908fc82..0fbf87b16338 100644
--- a/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
+++ b/arch/arm/mach-ep93xx/include/mach/ep93xx-regs.h
@@ -70,6 +70,7 @@
70#define EP93XX_USB_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00020000) 70#define EP93XX_USB_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00020000)
71#define EP93XX_USB_BASE EP93XX_AHB_IOMEM(0x00020000) 71#define EP93XX_USB_BASE EP93XX_AHB_IOMEM(0x00020000)
72 72
73#define EP93XX_RASTER_PHYS_BASE (EP93XX_AHB_PHYS_BASE + 0x00030000)
73#define EP93XX_RASTER_BASE EP93XX_AHB_IOMEM(0x00030000) 74#define EP93XX_RASTER_BASE EP93XX_AHB_IOMEM(0x00030000)
74 75
75#define EP93XX_GRAPHICS_ACCEL_BASE EP93XX_AHB_IOMEM(0x00040000) 76#define EP93XX_GRAPHICS_ACCEL_BASE EP93XX_AHB_IOMEM(0x00040000)
@@ -207,6 +208,11 @@
207#define EP93XX_SYSCON_DEVCFG_ADCPD (1<<2) 208#define EP93XX_SYSCON_DEVCFG_ADCPD (1<<2)
208#define EP93XX_SYSCON_DEVCFG_KEYS (1<<1) 209#define EP93XX_SYSCON_DEVCFG_KEYS (1<<1)
209#define EP93XX_SYSCON_DEVCFG_SHENA (1<<0) 210#define EP93XX_SYSCON_DEVCFG_SHENA (1<<0)
211#define EP93XX_SYSCON_VIDCLKDIV EP93XX_SYSCON_REG(0x84)
212#define EP93XX_SYSCON_CLKDIV_ENABLE (1<<15)
213#define EP93XX_SYSCON_CLKDIV_ESEL (1<<14)
214#define EP93XX_SYSCON_CLKDIV_PSEL (1<<13)
215#define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8
210#define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90) 216#define EP93XX_SYSCON_KEYTCHCLKDIV EP93XX_SYSCON_REG(0x90)
211#define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN (1<<31) 217#define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN (1<<31)
212#define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV (1<<16) 218#define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV (1<<16)
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 @@
1/*
2 * arch/arm/mach-ep93xx/include/mach/fb.h
3 */
4
5#ifndef __ASM_ARCH_EP93XXFB_H
6#define __ASM_ARCH_EP93XXFB_H
7
8struct platform_device;
9struct fb_videomode;
10struct fb_info;
11
12#define EP93XXFB_USE_MODEDB 0
13
14/* VideoAttributes flags */
15#define EP93XXFB_STATE_MACHINE_ENABLE (1 << 0)
16#define EP93XXFB_PIXEL_CLOCK_ENABLE (1 << 1)
17#define EP93XXFB_VSYNC_ENABLE (1 << 2)
18#define EP93XXFB_PIXEL_DATA_ENABLE (1 << 3)
19#define EP93XXFB_COMPOSITE_SYNC (1 << 4)
20#define EP93XXFB_SYNC_VERT_HIGH (1 << 5)
21#define EP93XXFB_SYNC_HORIZ_HIGH (1 << 6)
22#define EP93XXFB_SYNC_BLANK_HIGH (1 << 7)
23#define EP93XXFB_PCLK_FALLING (1 << 8)
24#define EP93XXFB_ENABLE_AC (1 << 9)
25#define EP93XXFB_ENABLE_LCD (1 << 10)
26#define EP93XXFB_ENABLE_CCIR (1 << 12)
27#define EP93XXFB_USE_PARALLEL_INTERFACE (1 << 13)
28#define EP93XXFB_ENABLE_INTERRUPT (1 << 14)
29#define EP93XXFB_USB_INTERLACE (1 << 16)
30#define EP93XXFB_USE_EQUALIZATION (1 << 17)
31#define EP93XXFB_USE_DOUBLE_HORZ (1 << 18)
32#define EP93XXFB_USE_DOUBLE_VERT (1 << 19)
33#define EP93XXFB_USE_BLANK_PIXEL (1 << 20)
34#define EP93XXFB_USE_SDCSN0 (0 << 21)
35#define EP93XXFB_USE_SDCSN1 (1 << 21)
36#define EP93XXFB_USE_SDCSN2 (2 << 21)
37#define EP93XXFB_USE_SDCSN3 (3 << 21)
38
39#define EP93XXFB_ENABLE (EP93XXFB_STATE_MACHINE_ENABLE | \
40 EP93XXFB_PIXEL_CLOCK_ENABLE | \
41 EP93XXFB_VSYNC_ENABLE | \
42 EP93XXFB_PIXEL_DATA_ENABLE)
43
44struct ep93xxfb_mach_info {
45 unsigned int num_modes;
46 const struct fb_videomode *modes;
47 const struct fb_videomode *default_mode;
48 int bpp;
49 unsigned int flags;
50
51 int (*setup)(struct platform_device *pdev);
52 void (*teardown)(struct platform_device *pdev);
53 void (*blank)(int blank_mode, struct fb_info *info);
54};
55
56#endif /* __ASM_ARCH_EP93XXFB_H */
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
index 5f5fa6574d34..01a0f0838e5b 100644
--- a/arch/arm/mach-ep93xx/include/mach/platform.h
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -6,6 +6,7 @@
6 6
7struct i2c_board_info; 7struct i2c_board_info;
8struct platform_device; 8struct platform_device;
9struct ep93xxfb_mach_info;
9 10
10struct ep93xx_eth_data 11struct ep93xx_eth_data
11{ 12{
@@ -33,6 +34,7 @@ static inline void ep93xx_devcfg_clear_bits(unsigned int bits)
33 34
34void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr); 35void ep93xx_register_eth(struct ep93xx_eth_data *data, int copy_addr);
35void ep93xx_register_i2c(struct i2c_board_info *devices, int num); 36void ep93xx_register_i2c(struct i2c_board_info *devices, int num);
37void ep93xx_register_fb(struct ep93xxfb_mach_info *data);
36void ep93xx_register_pwm(int pwm0, int pwm1); 38void ep93xx_register_pwm(int pwm0, int pwm1);
37int ep93xx_pwm_acquire_gpio(struct platform_device *pdev); 39int ep93xx_pwm_acquire_gpio(struct platform_device *pdev);
38void ep93xx_pwm_release_gpio(struct platform_device *pdev); 40void ep93xx_pwm_release_gpio(struct platform_device *pdev);