Commit | Line | Data |
---|---|---|
19d95e1a | 1 | /* |
f5c42271 | 2 | * Platform support for LPC32xx SoC |
19d95e1a KW |
3 | * |
4 | * Author: Kevin Wells <kevin.wells@nxp.com> | |
5 | * | |
f5c42271 | 6 | * Copyright (C) 2012 Roland Stigge <stigge@antcom.de> |
19d95e1a KW |
7 | * Copyright (C) 2010 NXP Semiconductors |
8 | * | |
9 | * This program is free software; you can redistribute it and/or modify | |
10 | * it under the terms of the GNU General Public License as published by | |
11 | * the Free Software Foundation; either version 2 of the License, or | |
12 | * (at your option) any later version. | |
13 | * | |
14 | * This program is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
17 | * GNU General Public License for more details. | |
18 | */ | |
19 | ||
20 | #include <linux/init.h> | |
21 | #include <linux/platform_device.h> | |
edbaa603 | 22 | #include <linux/device.h> |
19d95e1a KW |
23 | #include <linux/interrupt.h> |
24 | #include <linux/irq.h> | |
25 | #include <linux/dma-mapping.h> | |
26 | #include <linux/device.h> | |
19d95e1a KW |
27 | #include <linux/gpio.h> |
28 | #include <linux/amba/bus.h> | |
29 | #include <linux/amba/clcd.h> | |
291dd71f RS |
30 | #include <linux/amba/pl08x.h> |
31 | #include <linux/amba/mmci.h> | |
f5c42271 RS |
32 | #include <linux/of.h> |
33 | #include <linux/of_address.h> | |
34 | #include <linux/of_irq.h> | |
35 | #include <linux/of_platform.h> | |
36 | #include <linux/clk.h> | |
5b941238 RS |
37 | #include <linux/mtd/lpc32xx_slc.h> |
38 | #include <linux/mtd/lpc32xx_mlc.h> | |
19d95e1a KW |
39 | |
40 | #include <asm/setup.h> | |
41 | #include <asm/mach-types.h> | |
42 | #include <asm/mach/arch.h> | |
43 | ||
44 | #include <mach/hardware.h> | |
45 | #include <mach/platform.h> | |
c20b909b | 46 | #include <mach/board.h> |
19d95e1a KW |
47 | #include "common.h" |
48 | ||
19d95e1a KW |
49 | /* |
50 | * AMBA LCD controller | |
51 | */ | |
52 | static struct clcd_panel conn_lcd_panel = { | |
53 | .mode = { | |
54 | .name = "QVGA portrait", | |
55 | .refresh = 60, | |
56 | .xres = 240, | |
57 | .yres = 320, | |
58 | .pixclock = 191828, | |
59 | .left_margin = 22, | |
60 | .right_margin = 11, | |
61 | .upper_margin = 2, | |
62 | .lower_margin = 1, | |
63 | .hsync_len = 5, | |
64 | .vsync_len = 2, | |
65 | .sync = 0, | |
66 | .vmode = FB_VMODE_NONINTERLACED, | |
67 | }, | |
68 | .width = -1, | |
69 | .height = -1, | |
70 | .tim2 = (TIM2_IVS | TIM2_IHS), | |
71 | .cntl = (CNTL_BGR | CNTL_LCDTFT | CNTL_LCDVCOMP(1) | | |
72 | CNTL_LCDBPP16_565), | |
73 | .bpp = 16, | |
74 | }; | |
75 | #define PANEL_SIZE (3 * SZ_64K) | |
76 | ||
77 | static int lpc32xx_clcd_setup(struct clcd_fb *fb) | |
78 | { | |
79 | dma_addr_t dma; | |
80 | ||
f6e45661 LR |
81 | fb->fb.screen_base = dma_alloc_wc(&fb->dev->dev, PANEL_SIZE, &dma, |
82 | GFP_KERNEL); | |
19d95e1a KW |
83 | if (!fb->fb.screen_base) { |
84 | printk(KERN_ERR "CLCD: unable to map framebuffer\n"); | |
85 | return -ENOMEM; | |
86 | } | |
87 | ||
88 | fb->fb.fix.smem_start = dma; | |
89 | fb->fb.fix.smem_len = PANEL_SIZE; | |
90 | fb->panel = &conn_lcd_panel; | |
91 | ||
19d95e1a KW |
92 | return 0; |
93 | } | |
94 | ||
95 | static int lpc32xx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) | |
96 | { | |
f6e45661 LR |
97 | return dma_mmap_wc(&fb->dev->dev, vma, fb->fb.screen_base, |
98 | fb->fb.fix.smem_start, fb->fb.fix.smem_len); | |
19d95e1a KW |
99 | } |
100 | ||
101 | static void lpc32xx_clcd_remove(struct clcd_fb *fb) | |
102 | { | |
f6e45661 LR |
103 | dma_free_wc(&fb->dev->dev, fb->fb.fix.smem_len, fb->fb.screen_base, |
104 | fb->fb.fix.smem_start); | |
19d95e1a KW |
105 | } |
106 | ||
19d95e1a KW |
107 | static struct clcd_board lpc32xx_clcd_data = { |
108 | .name = "Phytec LCD", | |
109 | .check = clcdfb_check, | |
110 | .decode = clcdfb_decode, | |
19d95e1a KW |
111 | .setup = lpc32xx_clcd_setup, |
112 | .mmap = lpc32xx_clcd_mmap, | |
113 | .remove = lpc32xx_clcd_remove, | |
114 | }; | |
115 | ||
d807af47 RS |
116 | static struct pl08x_channel_data pl08x_slave_channels[] = { |
117 | { | |
118 | .bus_id = "nand-slc", | |
119 | .min_signal = 1, /* SLC NAND Flash */ | |
120 | .max_signal = 1, | |
121 | .periph_buses = PL08X_AHB1, | |
122 | }, | |
123 | { | |
124 | .bus_id = "nand-mlc", | |
125 | .min_signal = 12, /* MLC NAND Flash */ | |
126 | .max_signal = 12, | |
127 | .periph_buses = PL08X_AHB1, | |
128 | }, | |
129 | }; | |
130 | ||
8ba85f8b | 131 | static int pl08x_get_signal(const struct pl08x_channel_data *cd) |
d807af47 | 132 | { |
8ba85f8b | 133 | return cd->min_signal; |
d807af47 RS |
134 | } |
135 | ||
8ba85f8b | 136 | static void pl08x_put_signal(const struct pl08x_channel_data *cd, int ch) |
d807af47 RS |
137 | { |
138 | } | |
139 | ||
f5c42271 | 140 | static struct pl08x_platform_data pl08x_pd = { |
d807af47 RS |
141 | .slave_channels = &pl08x_slave_channels[0], |
142 | .num_slave_channels = ARRAY_SIZE(pl08x_slave_channels), | |
d7cabeed MB |
143 | .get_xfer_signal = pl08x_get_signal, |
144 | .put_xfer_signal = pl08x_put_signal, | |
d807af47 RS |
145 | .lli_buses = PL08X_AHB1, |
146 | .mem_buses = PL08X_AHB1, | |
19d95e1a KW |
147 | }; |
148 | ||
291dd71f RS |
149 | static struct mmci_platform_data lpc32xx_mmci_data = { |
150 | .ocr_mask = MMC_VDD_30_31 | MMC_VDD_31_32 | | |
151 | MMC_VDD_32_33 | MMC_VDD_33_34, | |
291dd71f RS |
152 | }; |
153 | ||
5b941238 RS |
154 | static struct lpc32xx_slc_platform_data lpc32xx_slc_data = { |
155 | .dma_filter = pl08x_filter_id, | |
156 | }; | |
157 | ||
158 | static struct lpc32xx_mlc_platform_data lpc32xx_mlc_data = { | |
159 | .dma_filter = pl08x_filter_id, | |
160 | }; | |
161 | ||
71d42e9c | 162 | static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = { |
a4bc7878 RS |
163 | OF_DEV_AUXDATA("arm,pl022", 0x20084000, "dev:ssp0", NULL), |
164 | OF_DEV_AUXDATA("arm,pl022", 0x2008C000, "dev:ssp1", NULL), | |
f5c42271 RS |
165 | OF_DEV_AUXDATA("arm,pl110", 0x31040000, "dev:clcd", &lpc32xx_clcd_data), |
166 | OF_DEV_AUXDATA("arm,pl080", 0x31000000, "pl08xdmac", &pl08x_pd), | |
291dd71f RS |
167 | OF_DEV_AUXDATA("arm,pl18x", 0x20098000, "20098000.sd", |
168 | &lpc32xx_mmci_data), | |
5b941238 RS |
169 | OF_DEV_AUXDATA("nxp,lpc3220-slc", 0x20020000, "20020000.flash", |
170 | &lpc32xx_slc_data), | |
171 | OF_DEV_AUXDATA("nxp,lpc3220-mlc", 0x200a8000, "200a8000.flash", | |
172 | &lpc32xx_mlc_data), | |
f5c42271 | 173 | { } |
19d95e1a KW |
174 | }; |
175 | ||
f5c42271 | 176 | static void __init lpc3250_machine_init(void) |
19d95e1a KW |
177 | { |
178 | u32 tmp; | |
19d95e1a | 179 | |
19d95e1a KW |
180 | /* Setup LCD muxing to RGB565 */ |
181 | tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL) & | |
182 | ~(LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_MSK | | |
183 | LPC32XX_CLKPWR_LCDCTRL_PSCALE_MSK); | |
184 | tmp |= LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT16; | |
185 | __raw_writel(tmp, LPC32XX_CLKPWR_LCDCLK_CTRL); | |
186 | ||
19d95e1a KW |
187 | lpc32xx_serial_init(); |
188 | ||
19d95e1a KW |
189 | /* Test clock needed for UDA1380 initial init */ |
190 | __raw_writel(LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC | | |
191 | LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN, | |
192 | LPC32XX_CLKPWR_TEST_CLK_SEL); | |
193 | ||
f5c42271 RS |
194 | of_platform_populate(NULL, of_default_bus_match_table, |
195 | lpc32xx_auxdata_lookup, NULL); | |
19d95e1a KW |
196 | } |
197 | ||
19c233b7 | 198 | static const char *const lpc32xx_dt_compat[] __initconst = { |
f5c42271 RS |
199 | "nxp,lpc3220", |
200 | "nxp,lpc3230", | |
201 | "nxp,lpc3240", | |
202 | "nxp,lpc3250", | |
203 | NULL | |
204 | }; | |
205 | ||
206 | DT_MACHINE_START(LPC32XX_DT, "LPC32XX SoC (Flattened Device Tree)") | |
bdec5ddd | 207 | .atag_offset = 0x100, |
19d95e1a | 208 | .map_io = lpc32xx_map_io, |
f5c42271 RS |
209 | .init_machine = lpc3250_machine_init, |
210 | .dt_compat = lpc32xx_dt_compat, | |
19d95e1a | 211 | MACHINE_END |