blob: 03ee3491b7cf084822c20e0ede93b80ecb595b81 [file] [log] [blame]
Kevin Wells19d95e12010-07-27 08:44:37 -07001/*
Roland Stiggef5c42272012-04-22 12:01:19 +02002 * Platform support for LPC32xx SoC
Kevin Wells19d95e12010-07-27 08:44:37 -07003 *
4 * Author: Kevin Wells <kevin.wells@nxp.com>
5 *
Roland Stiggef5c42272012-04-22 12:01:19 +02006 * Copyright (C) 2012 Roland Stigge <stigge@antcom.de>
Kevin Wells19d95e12010-07-27 08:44:37 -07007 * 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>
Kay Sieversedbaa602011-12-21 16:26:03 -080022#include <linux/device.h>
Kevin Wells19d95e12010-07-27 08:44:37 -070023#include <linux/interrupt.h>
24#include <linux/irq.h>
25#include <linux/dma-mapping.h>
26#include <linux/device.h>
27#include <linux/spi/spi.h>
28#include <linux/spi/eeprom.h>
Kevin Wells19d95e12010-07-27 08:44:37 -070029#include <linux/gpio.h>
30#include <linux/amba/bus.h>
31#include <linux/amba/clcd.h>
32#include <linux/amba/pl022.h>
Roland Stigge291dd712012-06-14 16:16:17 +020033#include <linux/amba/pl08x.h>
34#include <linux/amba/mmci.h>
Roland Stiggef5c42272012-04-22 12:01:19 +020035#include <linux/of.h>
36#include <linux/of_address.h>
37#include <linux/of_irq.h>
38#include <linux/of_platform.h>
39#include <linux/clk.h>
Kevin Wells19d95e12010-07-27 08:44:37 -070040
41#include <asm/setup.h>
42#include <asm/mach-types.h>
43#include <asm/mach/arch.h>
44
45#include <mach/hardware.h>
46#include <mach/platform.h>
Roland Stiggec20b9092012-03-12 22:27:28 +010047#include <mach/board.h>
Linus Walleij9c587c02011-08-22 08:45:15 +010048#include <mach/gpio-lpc32xx.h>
Kevin Wells19d95e12010-07-27 08:44:37 -070049#include "common.h"
50
51/*
52 * Mapped GPIOLIB GPIOs
53 */
Roland Stigge291dd712012-06-14 16:16:17 +020054#define SPI0_CS_GPIO LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5)
55#define LCD_POWER_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 0)
56#define BKL_POWER_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 4)
57#define MMC_PWR_ENABLE_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 5)
58#define MMC_CD_GPIO LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 1)
59#define MMC_WP_GPIO LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 0)
Kevin Wells19d95e12010-07-27 08:44:37 -070060
61/*
62 * AMBA LCD controller
63 */
64static struct clcd_panel conn_lcd_panel = {
65 .mode = {
66 .name = "QVGA portrait",
67 .refresh = 60,
68 .xres = 240,
69 .yres = 320,
70 .pixclock = 191828,
71 .left_margin = 22,
72 .right_margin = 11,
73 .upper_margin = 2,
74 .lower_margin = 1,
75 .hsync_len = 5,
76 .vsync_len = 2,
77 .sync = 0,
78 .vmode = FB_VMODE_NONINTERLACED,
79 },
80 .width = -1,
81 .height = -1,
82 .tim2 = (TIM2_IVS | TIM2_IHS),
83 .cntl = (CNTL_BGR | CNTL_LCDTFT | CNTL_LCDVCOMP(1) |
84 CNTL_LCDBPP16_565),
85 .bpp = 16,
86};
87#define PANEL_SIZE (3 * SZ_64K)
88
89static int lpc32xx_clcd_setup(struct clcd_fb *fb)
90{
91 dma_addr_t dma;
92
93 fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev,
94 PANEL_SIZE, &dma, GFP_KERNEL);
95 if (!fb->fb.screen_base) {
96 printk(KERN_ERR "CLCD: unable to map framebuffer\n");
97 return -ENOMEM;
98 }
99
100 fb->fb.fix.smem_start = dma;
101 fb->fb.fix.smem_len = PANEL_SIZE;
102 fb->panel = &conn_lcd_panel;
103
104 if (gpio_request(LCD_POWER_GPIO, "LCD power"))
105 printk(KERN_ERR "Error requesting gpio %u",
106 LCD_POWER_GPIO);
107 else if (gpio_direction_output(LCD_POWER_GPIO, 1))
108 printk(KERN_ERR "Error setting gpio %u to output",
109 LCD_POWER_GPIO);
110
111 if (gpio_request(BKL_POWER_GPIO, "LCD backlight power"))
112 printk(KERN_ERR "Error requesting gpio %u",
113 BKL_POWER_GPIO);
114 else if (gpio_direction_output(BKL_POWER_GPIO, 1))
115 printk(KERN_ERR "Error setting gpio %u to output",
116 BKL_POWER_GPIO);
117
118 return 0;
119}
120
121static int lpc32xx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
122{
123 return dma_mmap_writecombine(&fb->dev->dev, vma,
124 fb->fb.screen_base, fb->fb.fix.smem_start,
125 fb->fb.fix.smem_len);
126}
127
128static void lpc32xx_clcd_remove(struct clcd_fb *fb)
129{
130 dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
131 fb->fb.screen_base, fb->fb.fix.smem_start);
132}
133
134/*
135 * On some early LCD modules (1307.0), the backlight logic is inverted.
136 * For those board variants, swap the disable and enable states for
137 * BKL_POWER_GPIO.
138*/
139static void clcd_disable(struct clcd_fb *fb)
140{
141 gpio_set_value(BKL_POWER_GPIO, 0);
142 gpio_set_value(LCD_POWER_GPIO, 0);
143}
144
145static void clcd_enable(struct clcd_fb *fb)
146{
147 gpio_set_value(BKL_POWER_GPIO, 1);
148 gpio_set_value(LCD_POWER_GPIO, 1);
149}
150
151static struct clcd_board lpc32xx_clcd_data = {
152 .name = "Phytec LCD",
153 .check = clcdfb_check,
154 .decode = clcdfb_decode,
155 .disable = clcd_disable,
156 .enable = clcd_enable,
157 .setup = lpc32xx_clcd_setup,
158 .mmap = lpc32xx_clcd_mmap,
159 .remove = lpc32xx_clcd_remove,
160};
161
Kevin Wells19d95e12010-07-27 08:44:37 -0700162/*
163 * AMBA SSP (SPI)
164 */
165static void phy3250_spi_cs_set(u32 control)
166{
167 gpio_set_value(SPI0_CS_GPIO, (int) control);
168}
169
170static struct pl022_config_chip spi0_chip_info = {
Kevin Wells19d95e12010-07-27 08:44:37 -0700171 .com_mode = INTERRUPT_TRANSFER,
172 .iface = SSP_INTERFACE_MOTOROLA_SPI,
173 .hierarchy = SSP_MASTER,
174 .slave_tx_disable = 0,
Kevin Wells19d95e12010-07-27 08:44:37 -0700175 .rx_lev_trig = SSP_RX_4_OR_MORE_ELEM,
176 .tx_lev_trig = SSP_TX_4_OR_MORE_EMPTY_LOC,
Kevin Wells19d95e12010-07-27 08:44:37 -0700177 .ctrl_len = SSP_BITS_8,
178 .wait_state = SSP_MWIRE_WAIT_ZERO,
179 .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX,
180 .cs_control = phy3250_spi_cs_set,
181};
182
183static struct pl022_ssp_controller lpc32xx_ssp0_data = {
184 .bus_id = 0,
185 .num_chipselect = 1,
186 .enable_dma = 0,
187};
188
Roland Stiggef5c42272012-04-22 12:01:19 +0200189static struct pl022_ssp_controller lpc32xx_ssp1_data = {
190 .bus_id = 1,
191 .num_chipselect = 1,
192 .enable_dma = 0,
193};
Kevin Wells19d95e12010-07-27 08:44:37 -0700194
195/* AT25 driver registration */
196static int __init phy3250_spi_board_register(void)
197{
198#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
199 static struct spi_board_info info[] = {
200 {
201 .modalias = "spidev",
202 .max_speed_hz = 5000000,
203 .bus_num = 0,
204 .chip_select = 0,
205 .controller_data = &spi0_chip_info,
206 },
207 };
208
209#else
210 static struct spi_eeprom eeprom = {
211 .name = "at25256a",
212 .byte_len = 0x8000,
213 .page_size = 64,
214 .flags = EE_ADDR2,
215 };
216
217 static struct spi_board_info info[] = {
218 {
219 .modalias = "at25",
220 .max_speed_hz = 5000000,
221 .bus_num = 0,
222 .chip_select = 0,
Kevin Wellsbde435a2010-09-16 06:18:50 -0700223 .mode = SPI_MODE_0,
Kevin Wells19d95e12010-07-27 08:44:37 -0700224 .platform_data = &eeprom,
225 .controller_data = &spi0_chip_info,
226 },
227 };
228#endif
229 return spi_register_board_info(info, ARRAY_SIZE(info));
230}
231arch_initcall(phy3250_spi_board_register);
232
Roland Stigged807af42012-06-14 16:16:17 +0200233static struct pl08x_channel_data pl08x_slave_channels[] = {
234 {
235 .bus_id = "nand-slc",
236 .min_signal = 1, /* SLC NAND Flash */
237 .max_signal = 1,
238 .periph_buses = PL08X_AHB1,
239 },
240 {
241 .bus_id = "nand-mlc",
242 .min_signal = 12, /* MLC NAND Flash */
243 .max_signal = 12,
244 .periph_buses = PL08X_AHB1,
245 },
246};
247
248/* NOTE: These will change, according to RMK */
249static int pl08x_get_signal(struct pl08x_dma_chan *ch)
250{
251 return ch->cd->min_signal;
252}
253
254static void pl08x_put_signal(struct pl08x_dma_chan *ch)
255{
256}
257
Roland Stiggef5c42272012-04-22 12:01:19 +0200258static struct pl08x_platform_data pl08x_pd = {
Roland Stigged807af42012-06-14 16:16:17 +0200259 .slave_channels = &pl08x_slave_channels[0],
260 .num_slave_channels = ARRAY_SIZE(pl08x_slave_channels),
261 .get_signal = pl08x_get_signal,
262 .put_signal = pl08x_put_signal,
263 .lli_buses = PL08X_AHB1,
264 .mem_buses = PL08X_AHB1,
Kevin Wells19d95e12010-07-27 08:44:37 -0700265};
266
Roland Stigge291dd712012-06-14 16:16:17 +0200267static int mmc_handle_ios(struct device *dev, struct mmc_ios *ios)
268{
269 /* Only on and off are supported */
270 if (ios->power_mode == MMC_POWER_OFF)
271 gpio_set_value(MMC_PWR_ENABLE_GPIO, 0);
272 else
273 gpio_set_value(MMC_PWR_ENABLE_GPIO, 1);
274 return 0;
275}
276
277static struct mmci_platform_data lpc32xx_mmci_data = {
278 .ocr_mask = MMC_VDD_30_31 | MMC_VDD_31_32 |
279 MMC_VDD_32_33 | MMC_VDD_33_34,
280 .ios_handler = mmc_handle_ios,
281 .dma_filter = NULL,
282 /* No DMA for now since AMBA PL080 dmaengine driver only does scatter
283 * gather, and the MMCI driver doesn't do it this way */
284};
285
Roland Stiggef5c42272012-04-22 12:01:19 +0200286static const struct of_dev_auxdata lpc32xx_auxdata_lookup[] __initconst = {
287 OF_DEV_AUXDATA("arm,pl022", 0x20084000, "dev:ssp0", &lpc32xx_ssp0_data),
288 OF_DEV_AUXDATA("arm,pl022", 0x2008C000, "dev:ssp1", &lpc32xx_ssp1_data),
289 OF_DEV_AUXDATA("arm,pl110", 0x31040000, "dev:clcd", &lpc32xx_clcd_data),
290 OF_DEV_AUXDATA("arm,pl080", 0x31000000, "pl08xdmac", &pl08x_pd),
Roland Stigge291dd712012-06-14 16:16:17 +0200291 OF_DEV_AUXDATA("arm,pl18x", 0x20098000, "20098000.sd",
292 &lpc32xx_mmci_data),
Roland Stiggef5c42272012-04-22 12:01:19 +0200293 { }
Kevin Wells19d95e12010-07-27 08:44:37 -0700294};
295
Roland Stiggef5c42272012-04-22 12:01:19 +0200296static void __init lpc3250_machine_init(void)
Kevin Wells19d95e12010-07-27 08:44:37 -0700297{
298 u32 tmp;
Kevin Wells19d95e12010-07-27 08:44:37 -0700299
Kevin Wells19d95e12010-07-27 08:44:37 -0700300 /* Setup LCD muxing to RGB565 */
301 tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL) &
302 ~(LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_MSK |
303 LPC32XX_CLKPWR_LCDCTRL_PSCALE_MSK);
304 tmp |= LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT16;
305 __raw_writel(tmp, LPC32XX_CLKPWR_LCDCLK_CTRL);
306
Roland Stiggef5c42272012-04-22 12:01:19 +0200307 /* Set up USB power */
308 tmp = __raw_readl(LPC32XX_CLKPWR_USB_CTRL);
309 tmp |= LPC32XX_CLKPWR_USBCTRL_HCLK_EN |
310 LPC32XX_CLKPWR_USBCTRL_USBI2C_EN;
311 __raw_writel(tmp, LPC32XX_CLKPWR_USB_CTRL);
312
Kevin Wells19d95e12010-07-27 08:44:37 -0700313 /* Set up I2C pull levels */
314 tmp = __raw_readl(LPC32XX_CLKPWR_I2C_CLK_CTRL);
315 tmp |= LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE |
316 LPC32XX_CLKPWR_I2CCLK_I2C2HI_DRIVE;
317 __raw_writel(tmp, LPC32XX_CLKPWR_I2C_CLK_CTRL);
318
319 /* Disable IrDA pulsing support on UART6 */
320 tmp = __raw_readl(LPC32XX_UARTCTL_CTRL);
321 tmp |= LPC32XX_UART_UART6_IRDAMOD_BYPASS;
322 __raw_writel(tmp, LPC32XX_UARTCTL_CTRL);
323
324 /* Enable DMA for I2S1 channel */
325 tmp = __raw_readl(LPC32XX_CLKPWR_I2S_CLK_CTRL);
326 tmp = LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA;
327 __raw_writel(tmp, LPC32XX_CLKPWR_I2S_CLK_CTRL);
328
329 lpc32xx_serial_init();
330
331 /*
332 * AMBA peripheral clocks need to be enabled prior to AMBA device
333 * detection or a data fault will occur, so enable the clocks
Roland Stiggef5c42272012-04-22 12:01:19 +0200334 * here.
Kevin Wells19d95e12010-07-27 08:44:37 -0700335 */
Roland Stigge291dd712012-06-14 16:16:17 +0200336 tmp = __raw_readl(LPC32XX_CLKPWR_MS_CTRL);
337 tmp |= LPC32XX_CLKPWR_MSCARD_SDCARD_EN |
338 LPC32XX_CLKPWR_MSCARD_MSDIO_PU_EN;
339 __raw_writel(tmp, LPC32XX_CLKPWR_MS_CTRL);
340
Kevin Wells19d95e12010-07-27 08:44:37 -0700341 tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL);
342 __raw_writel((tmp | LPC32XX_CLKPWR_LCDCTRL_CLK_EN),
343 LPC32XX_CLKPWR_LCDCLK_CTRL);
Roland Stiggef5c42272012-04-22 12:01:19 +0200344
Kevin Wells19d95e12010-07-27 08:44:37 -0700345 tmp = __raw_readl(LPC32XX_CLKPWR_SSP_CLK_CTRL);
346 __raw_writel((tmp | LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN),
347 LPC32XX_CLKPWR_SSP_CLK_CTRL);
Kevin Wells19d95e12010-07-27 08:44:37 -0700348
Roland Stiggef5c42272012-04-22 12:01:19 +0200349 tmp = __raw_readl(LPC32XX_CLKPWR_DMA_CLK_CTRL);
350 __raw_writel((tmp | LPC32XX_CLKPWR_DMACLKCTRL_CLK_EN),
351 LPC32XX_CLKPWR_DMA_CLK_CTRL);
Kevin Wells19d95e12010-07-27 08:44:37 -0700352
353 /* Test clock needed for UDA1380 initial init */
354 __raw_writel(LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC |
355 LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN,
356 LPC32XX_CLKPWR_TEST_CLK_SEL);
357
Roland Stiggef5c42272012-04-22 12:01:19 +0200358 of_platform_populate(NULL, of_default_bus_match_table,
359 lpc32xx_auxdata_lookup, NULL);
360
361 /* Register GPIOs used on this board */
362 if (gpio_request(SPI0_CS_GPIO, "spi0 cs"))
363 printk(KERN_ERR "Error requesting gpio %u",
364 SPI0_CS_GPIO);
365 else if (gpio_direction_output(SPI0_CS_GPIO, 1))
366 printk(KERN_ERR "Error setting gpio %u to output",
367 SPI0_CS_GPIO);
Roland Stigge291dd712012-06-14 16:16:17 +0200368
369 if (gpio_request(MMC_PWR_ENABLE_GPIO, "mmc_power_en"))
370 pr_err("Error requesting gpio %u", MMC_PWR_ENABLE_GPIO);
371 else if (gpio_direction_output(MMC_PWR_ENABLE_GPIO, 1))
372 pr_err("Error setting gpio %u to output", MMC_PWR_ENABLE_GPIO);
Kevin Wells19d95e12010-07-27 08:44:37 -0700373}
374
Roland Stiggef5c42272012-04-22 12:01:19 +0200375static char const *lpc32xx_dt_compat[] __initdata = {
376 "nxp,lpc3220",
377 "nxp,lpc3230",
378 "nxp,lpc3240",
379 "nxp,lpc3250",
380 NULL
381};
382
383DT_MACHINE_START(LPC32XX_DT, "LPC32XX SoC (Flattened Device Tree)")
Nicolas Pitrebdec5dd2011-07-05 22:38:14 -0400384 .atag_offset = 0x100,
Kevin Wells19d95e12010-07-27 08:44:37 -0700385 .map_io = lpc32xx_map_io,
386 .init_irq = lpc32xx_init_irq,
387 .timer = &lpc32xx_timer,
Roland Stiggef5c42272012-04-22 12:01:19 +0200388 .init_machine = lpc3250_machine_init,
389 .dt_compat = lpc32xx_dt_compat,
Russell Kingb23fcd92011-11-05 12:17:40 +0000390 .restart = lpc23xx_restart,
Kevin Wells19d95e12010-07-27 08:44:37 -0700391MACHINE_END