1/* 2 * arch/arm/mach-lpc32xx/phy3250.c 3 * 4 * Author: Kevin Wells <kevin.wells@nxp.com> 5 * 6 * Copyright (C) 2010 NXP Semiconductors 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License as published by 10 * the Free Software Foundation; either version 2 of the License, or 11 * (at your option) any later version. 12 * 13 * This program is distributed in the hope that it will be useful, 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 * GNU General Public License for more details. 17 */ 18 19#include <linux/init.h> 20#include <linux/platform_device.h> 21#include <linux/sysdev.h> 22#include <linux/interrupt.h> 23#include <linux/irq.h> 24#include <linux/dma-mapping.h> 25#include <linux/device.h> 26#include <linux/spi/spi.h> 27#include <linux/spi/eeprom.h> 28#include <linux/leds.h> 29#include <linux/gpio.h> 30#include <linux/amba/bus.h> 31#include <linux/amba/clcd.h> 32#include <linux/amba/pl022.h> 33 34#include <asm/setup.h> 35#include <asm/mach-types.h> 36#include <asm/mach/arch.h> 37 38#include <mach/hardware.h> 39#include <mach/platform.h> 40#include "common.h" 41 42/* 43 * Mapped GPIOLIB GPIOs 44 */ 45#define SPI0_CS_GPIO LPC32XX_GPIO(LPC32XX_GPIO_P3_GRP, 5) 46#define LCD_POWER_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 0) 47#define BKL_POWER_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 4) 48#define LED_GPIO LPC32XX_GPIO(LPC32XX_GPO_P3_GRP, 1) 49 50/* 51 * AMBA LCD controller 52 */ 53static struct clcd_panel conn_lcd_panel = { 54 .mode = { 55 .name = "QVGA portrait", 56 .refresh = 60, 57 .xres = 240, 58 .yres = 320, 59 .pixclock = 191828, 60 .left_margin = 22, 61 .right_margin = 11, 62 .upper_margin = 2, 63 .lower_margin = 1, 64 .hsync_len = 5, 65 .vsync_len = 2, 66 .sync = 0, 67 .vmode = FB_VMODE_NONINTERLACED, 68 }, 69 .width = -1, 70 .height = -1, 71 .tim2 = (TIM2_IVS | TIM2_IHS), 72 .cntl = (CNTL_BGR | CNTL_LCDTFT | CNTL_LCDVCOMP(1) | 73 CNTL_LCDBPP16_565), 74 .bpp = 16, 75}; 76#define PANEL_SIZE (3 * SZ_64K) 77 78static int lpc32xx_clcd_setup(struct clcd_fb *fb) 79{ 80 dma_addr_t dma; 81 82 fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, 83 PANEL_SIZE, &dma, GFP_KERNEL); 84 if (!fb->fb.screen_base) { 85 printk(KERN_ERR "CLCD: unable to map framebuffer\n"); 86 return -ENOMEM; 87 } 88 89 fb->fb.fix.smem_start = dma; 90 fb->fb.fix.smem_len = PANEL_SIZE; 91 fb->panel = &conn_lcd_panel; 92 93 if (gpio_request(LCD_POWER_GPIO, "LCD power")) 94 printk(KERN_ERR "Error requesting gpio %u", 95 LCD_POWER_GPIO); 96 else if (gpio_direction_output(LCD_POWER_GPIO, 1)) 97 printk(KERN_ERR "Error setting gpio %u to output", 98 LCD_POWER_GPIO); 99 100 if (gpio_request(BKL_POWER_GPIO, "LCD backlight power")) 101 printk(KERN_ERR "Error requesting gpio %u", 102 BKL_POWER_GPIO); 103 else if (gpio_direction_output(BKL_POWER_GPIO, 1)) 104 printk(KERN_ERR "Error setting gpio %u to output", 105 BKL_POWER_GPIO); 106 107 return 0; 108} 109 110static int lpc32xx_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma) 111{ 112 return dma_mmap_writecombine(&fb->dev->dev, vma, 113 fb->fb.screen_base, fb->fb.fix.smem_start, 114 fb->fb.fix.smem_len); 115} 116 117static void lpc32xx_clcd_remove(struct clcd_fb *fb) 118{ 119 dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len, 120 fb->fb.screen_base, fb->fb.fix.smem_start); 121} 122 123/* 124 * On some early LCD modules (1307.0), the backlight logic is inverted. 125 * For those board variants, swap the disable and enable states for 126 * BKL_POWER_GPIO. 127*/ 128static void clcd_disable(struct clcd_fb *fb) 129{ 130 gpio_set_value(BKL_POWER_GPIO, 0); 131 gpio_set_value(LCD_POWER_GPIO, 0); 132} 133 134static void clcd_enable(struct clcd_fb *fb) 135{ 136 gpio_set_value(BKL_POWER_GPIO, 1); 137 gpio_set_value(LCD_POWER_GPIO, 1); 138} 139 140static struct clcd_board lpc32xx_clcd_data = { 141 .name = "Phytec LCD", 142 .check = clcdfb_check, 143 .decode = clcdfb_decode, 144 .disable = clcd_disable, 145 .enable = clcd_enable, 146 .setup = lpc32xx_clcd_setup, 147 .mmap = lpc32xx_clcd_mmap, 148 .remove = lpc32xx_clcd_remove, 149}; 150 151static struct amba_device lpc32xx_clcd_device = { 152 .dev = { 153 .coherent_dma_mask = ~0, 154 .init_name = "dev:clcd", 155 .platform_data = &lpc32xx_clcd_data, 156 }, 157 .res = { 158 .start = LPC32XX_LCD_BASE, 159 .end = (LPC32XX_LCD_BASE + SZ_4K - 1), 160 .flags = IORESOURCE_MEM, 161 }, 162 .dma_mask = ~0, 163 .irq = {IRQ_LPC32XX_LCD, NO_IRQ}, 164}; 165 166/* 167 * AMBA SSP (SPI) 168 */ 169static void phy3250_spi_cs_set(u32 control) 170{ 171 gpio_set_value(SPI0_CS_GPIO, (int) control); 172} 173 174static struct pl022_config_chip spi0_chip_info = { 175 .lbm = LOOPBACK_DISABLED, 176 .com_mode = INTERRUPT_TRANSFER, 177 .iface = SSP_INTERFACE_MOTOROLA_SPI, 178 .hierarchy = SSP_MASTER, 179 .slave_tx_disable = 0, 180 .endian_tx = SSP_TX_LSB, 181 .endian_rx = SSP_RX_LSB, 182 .data_size = SSP_DATA_BITS_8, 183 .rx_lev_trig = SSP_RX_4_OR_MORE_ELEM, 184 .tx_lev_trig = SSP_TX_4_OR_MORE_EMPTY_LOC, 185 .clk_phase = SSP_CLK_FIRST_EDGE, 186 .clk_pol = SSP_CLK_POL_IDLE_LOW, 187 .ctrl_len = SSP_BITS_8, 188 .wait_state = SSP_MWIRE_WAIT_ZERO, 189 .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, 190 .cs_control = phy3250_spi_cs_set, 191}; 192 193static struct pl022_ssp_controller lpc32xx_ssp0_data = { 194 .bus_id = 0, 195 .num_chipselect = 1, 196 .enable_dma = 0, 197}; 198 199static struct amba_device lpc32xx_ssp0_device = { 200 .dev = { 201 .coherent_dma_mask = ~0, 202 .init_name = "dev:ssp0", 203 .platform_data = &lpc32xx_ssp0_data, 204 }, 205 .res = { 206 .start = LPC32XX_SSP0_BASE, 207 .end = (LPC32XX_SSP0_BASE + SZ_4K - 1), 208 .flags = IORESOURCE_MEM, 209 }, 210 .dma_mask = ~0, 211 .irq = {IRQ_LPC32XX_SSP0, NO_IRQ}, 212}; 213 214/* AT25 driver registration */ 215static int __init phy3250_spi_board_register(void) 216{ 217#if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE) 218 static struct spi_board_info info[] = { 219 { 220 .modalias = "spidev", 221 .max_speed_hz = 5000000, 222 .bus_num = 0, 223 .chip_select = 0, 224 .controller_data = &spi0_chip_info, 225 }, 226 }; 227 228#else 229 static struct spi_eeprom eeprom = { 230 .name = "at25256a", 231 .byte_len = 0x8000, 232 .page_size = 64, 233 .flags = EE_ADDR2, 234 }; 235 236 static struct spi_board_info info[] = { 237 { 238 .modalias = "at25", 239 .max_speed_hz = 5000000, 240 .bus_num = 0, 241 .chip_select = 0, 242 .platform_data = &eeprom, 243 .controller_data = &spi0_chip_info, 244 }, 245 }; 246#endif 247 return spi_register_board_info(info, ARRAY_SIZE(info)); 248} 249arch_initcall(phy3250_spi_board_register); 250 251static struct i2c_board_info __initdata phy3250_i2c_board_info[] = { 252 { 253 I2C_BOARD_INFO("pcf8563", 0x51), 254 }, 255}; 256 257static struct gpio_led phy_leds[] = { 258 { 259 .name = "led0", 260 .gpio = LED_GPIO, 261 .active_low = 1, 262 .default_trigger = "heartbeat", 263 }, 264}; 265 266static struct gpio_led_platform_data led_data = { 267 .leds = phy_leds, 268 .num_leds = ARRAY_SIZE(phy_leds), 269}; 270 271static struct platform_device lpc32xx_gpio_led_device = { 272 .name = "leds-gpio", 273 .id = -1, 274 .dev.platform_data = &led_data, 275}; 276 277static struct platform_device *phy3250_devs[] __initdata = { 278 &lpc32xx_i2c0_device, 279 &lpc32xx_i2c1_device, 280 &lpc32xx_i2c2_device, 281 &lpc32xx_watchdog_device, 282 &lpc32xx_gpio_led_device, 283}; 284 285static struct amba_device *amba_devs[] __initdata = { 286 &lpc32xx_clcd_device, 287 &lpc32xx_ssp0_device, 288}; 289 290/* 291 * Board specific functions 292 */ 293static void __init phy3250_board_init(void) 294{ 295 u32 tmp; 296 int i; 297 298 lpc32xx_gpio_init(); 299 300 /* Register GPIOs used on this board */ 301 if (gpio_request(SPI0_CS_GPIO, "spi0 cs")) 302 printk(KERN_ERR "Error requesting gpio %u", 303 SPI0_CS_GPIO); 304 else if (gpio_direction_output(SPI0_CS_GPIO, 1)) 305 printk(KERN_ERR "Error setting gpio %u to output", 306 SPI0_CS_GPIO); 307 308 /* Setup network interface for RMII mode */ 309 tmp = __raw_readl(LPC32XX_CLKPWR_MACCLK_CTRL); 310 tmp &= ~LPC32XX_CLKPWR_MACCTRL_PINS_MSK; 311 tmp |= LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS; 312 __raw_writel(tmp, LPC32XX_CLKPWR_MACCLK_CTRL); 313 314 /* Setup SLC NAND controller muxing */ 315 __raw_writel(LPC32XX_CLKPWR_NANDCLK_SEL_SLC, 316 LPC32XX_CLKPWR_NAND_CLK_CTRL); 317 318 /* Setup LCD muxing to RGB565 */ 319 tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL) & 320 ~(LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_MSK | 321 LPC32XX_CLKPWR_LCDCTRL_PSCALE_MSK); 322 tmp |= LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT16; 323 __raw_writel(tmp, LPC32XX_CLKPWR_LCDCLK_CTRL); 324 325 /* Set up I2C pull levels */ 326 tmp = __raw_readl(LPC32XX_CLKPWR_I2C_CLK_CTRL); 327 tmp |= LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE | 328 LPC32XX_CLKPWR_I2CCLK_I2C2HI_DRIVE; 329 __raw_writel(tmp, LPC32XX_CLKPWR_I2C_CLK_CTRL); 330 331 /* Disable IrDA pulsing support on UART6 */ 332 tmp = __raw_readl(LPC32XX_UARTCTL_CTRL); 333 tmp |= LPC32XX_UART_UART6_IRDAMOD_BYPASS; 334 __raw_writel(tmp, LPC32XX_UARTCTL_CTRL); 335 336 /* Enable DMA for I2S1 channel */ 337 tmp = __raw_readl(LPC32XX_CLKPWR_I2S_CLK_CTRL); 338 tmp = LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA; 339 __raw_writel(tmp, LPC32XX_CLKPWR_I2S_CLK_CTRL); 340 341 lpc32xx_serial_init(); 342 343 /* 344 * AMBA peripheral clocks need to be enabled prior to AMBA device 345 * detection or a data fault will occur, so enable the clocks 346 * here. However, we don't want to enable them if the peripheral 347 * isn't included in the image 348 */ 349#ifdef CONFIG_FB_ARMCLCD 350 tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL); 351 __raw_writel((tmp | LPC32XX_CLKPWR_LCDCTRL_CLK_EN), 352 LPC32XX_CLKPWR_LCDCLK_CTRL); 353#endif 354#ifdef CONFIG_SPI_PL022 355 tmp = __raw_readl(LPC32XX_CLKPWR_SSP_CLK_CTRL); 356 __raw_writel((tmp | LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN), 357 LPC32XX_CLKPWR_SSP_CLK_CTRL); 358#endif 359 360 platform_add_devices(phy3250_devs, ARRAY_SIZE(phy3250_devs)); 361 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { 362 struct amba_device *d = amba_devs[i]; 363 amba_device_register(d, &iomem_resource); 364 } 365 366 /* Test clock needed for UDA1380 initial init */ 367 __raw_writel(LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC | 368 LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN, 369 LPC32XX_CLKPWR_TEST_CLK_SEL); 370 371 i2c_register_board_info(0, phy3250_i2c_board_info, 372 ARRAY_SIZE(phy3250_i2c_board_info)); 373} 374 375static int __init lpc32xx_display_uid(void) 376{ 377 u32 uid[4]; 378 379 lpc32xx_get_uid(uid); 380 381 printk(KERN_INFO "LPC32XX unique ID: %08x%08x%08x%08x\n", 382 uid[3], uid[2], uid[1], uid[0]); 383 384 return 1; 385} 386arch_initcall(lpc32xx_display_uid); 387 388MACHINE_START(PHY3250, "Phytec 3250 board with the LPC3250 Microcontroller") 389 /* Maintainer: Kevin Wells, NXP Semiconductors */ 390 .phys_io = LPC32XX_UART5_BASE, 391 .io_pg_offst = ((IO_ADDRESS(LPC32XX_UART5_BASE))>>18) & 0xfffc, 392 .boot_params = 0x80000100, 393 .map_io = lpc32xx_map_io, 394 .init_irq = lpc32xx_init_irq, 395 .timer = &lpc32xx_timer, 396 .init_machine = phy3250_board_init, 397MACHINE_END 398