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 */ 53 static 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 78 static 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 110 static 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 117 static 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 */ 128 static 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 134 static 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 140 static 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 151 static 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 */ 169 static void phy3250_spi_cs_set(u32 control) 170 { 171 gpio_set_value(SPI0_CS_GPIO, (int) control); 172 } 173 174 static struct pl022_config_chip spi0_chip_info = { 175 .com_mode = INTERRUPT_TRANSFER, 176 .iface = SSP_INTERFACE_MOTOROLA_SPI, 177 .hierarchy = SSP_MASTER, 178 .slave_tx_disable = 0, 179 .rx_lev_trig = SSP_RX_4_OR_MORE_ELEM, 180 .tx_lev_trig = SSP_TX_4_OR_MORE_EMPTY_LOC, 181 .ctrl_len = SSP_BITS_8, 182 .wait_state = SSP_MWIRE_WAIT_ZERO, 183 .duplex = SSP_MICROWIRE_CHANNEL_FULL_DUPLEX, 184 .cs_control = phy3250_spi_cs_set, 185 }; 186 187 static struct pl022_ssp_controller lpc32xx_ssp0_data = { 188 .bus_id = 0, 189 .num_chipselect = 1, 190 .enable_dma = 0, 191 }; 192 193 static struct amba_device lpc32xx_ssp0_device = { 194 .dev = { 195 .coherent_dma_mask = ~0, 196 .init_name = "dev:ssp0", 197 .platform_data = &lpc32xx_ssp0_data, 198 }, 199 .res = { 200 .start = LPC32XX_SSP0_BASE, 201 .end = (LPC32XX_SSP0_BASE + SZ_4K - 1), 202 .flags = IORESOURCE_MEM, 203 }, 204 .dma_mask = ~0, 205 .irq = {IRQ_LPC32XX_SSP0, NO_IRQ}, 206 }; 207 208 /* AT25 driver registration */ 209 static int __init phy3250_spi_board_register(void) 210 { 211 #if defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE) 212 static struct spi_board_info info[] = { 213 { 214 .modalias = "spidev", 215 .max_speed_hz = 5000000, 216 .bus_num = 0, 217 .chip_select = 0, 218 .controller_data = &spi0_chip_info, 219 }, 220 }; 221 222 #else 223 static struct spi_eeprom eeprom = { 224 .name = "at25256a", 225 .byte_len = 0x8000, 226 .page_size = 64, 227 .flags = EE_ADDR2, 228 }; 229 230 static struct spi_board_info info[] = { 231 { 232 .modalias = "at25", 233 .max_speed_hz = 5000000, 234 .bus_num = 0, 235 .chip_select = 0, 236 .mode = SPI_MODE_0, 237 .platform_data = &eeprom, 238 .controller_data = &spi0_chip_info, 239 }, 240 }; 241 #endif 242 return spi_register_board_info(info, ARRAY_SIZE(info)); 243 } 244 arch_initcall(phy3250_spi_board_register); 245 246 static struct i2c_board_info __initdata phy3250_i2c_board_info[] = { 247 { 248 I2C_BOARD_INFO("pcf8563", 0x51), 249 }, 250 }; 251 252 static struct gpio_led phy_leds[] = { 253 { 254 .name = "led0", 255 .gpio = LED_GPIO, 256 .active_low = 1, 257 .default_trigger = "heartbeat", 258 }, 259 }; 260 261 static struct gpio_led_platform_data led_data = { 262 .leds = phy_leds, 263 .num_leds = ARRAY_SIZE(phy_leds), 264 }; 265 266 static struct platform_device lpc32xx_gpio_led_device = { 267 .name = "leds-gpio", 268 .id = -1, 269 .dev.platform_data = &led_data, 270 }; 271 272 static struct platform_device *phy3250_devs[] __initdata = { 273 &lpc32xx_i2c0_device, 274 &lpc32xx_i2c1_device, 275 &lpc32xx_i2c2_device, 276 &lpc32xx_watchdog_device, 277 &lpc32xx_gpio_led_device, 278 }; 279 280 static struct amba_device *amba_devs[] __initdata = { 281 &lpc32xx_clcd_device, 282 &lpc32xx_ssp0_device, 283 }; 284 285 /* 286 * Board specific functions 287 */ 288 static void __init phy3250_board_init(void) 289 { 290 u32 tmp; 291 int i; 292 293 lpc32xx_gpio_init(); 294 295 /* Register GPIOs used on this board */ 296 if (gpio_request(SPI0_CS_GPIO, "spi0 cs")) 297 printk(KERN_ERR "Error requesting gpio %u", 298 SPI0_CS_GPIO); 299 else if (gpio_direction_output(SPI0_CS_GPIO, 1)) 300 printk(KERN_ERR "Error setting gpio %u to output", 301 SPI0_CS_GPIO); 302 303 /* Setup network interface for RMII mode */ 304 tmp = __raw_readl(LPC32XX_CLKPWR_MACCLK_CTRL); 305 tmp &= ~LPC32XX_CLKPWR_MACCTRL_PINS_MSK; 306 tmp |= LPC32XX_CLKPWR_MACCTRL_USE_RMII_PINS; 307 __raw_writel(tmp, LPC32XX_CLKPWR_MACCLK_CTRL); 308 309 /* Setup SLC NAND controller muxing */ 310 __raw_writel(LPC32XX_CLKPWR_NANDCLK_SEL_SLC, 311 LPC32XX_CLKPWR_NAND_CLK_CTRL); 312 313 /* Setup LCD muxing to RGB565 */ 314 tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL) & 315 ~(LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_MSK | 316 LPC32XX_CLKPWR_LCDCTRL_PSCALE_MSK); 317 tmp |= LPC32XX_CLKPWR_LCDCTRL_LCDTYPE_TFT16; 318 __raw_writel(tmp, LPC32XX_CLKPWR_LCDCLK_CTRL); 319 320 /* Set up I2C pull levels */ 321 tmp = __raw_readl(LPC32XX_CLKPWR_I2C_CLK_CTRL); 322 tmp |= LPC32XX_CLKPWR_I2CCLK_USBI2CHI_DRIVE | 323 LPC32XX_CLKPWR_I2CCLK_I2C2HI_DRIVE; 324 __raw_writel(tmp, LPC32XX_CLKPWR_I2C_CLK_CTRL); 325 326 /* Disable IrDA pulsing support on UART6 */ 327 tmp = __raw_readl(LPC32XX_UARTCTL_CTRL); 328 tmp |= LPC32XX_UART_UART6_IRDAMOD_BYPASS; 329 __raw_writel(tmp, LPC32XX_UARTCTL_CTRL); 330 331 /* Enable DMA for I2S1 channel */ 332 tmp = __raw_readl(LPC32XX_CLKPWR_I2S_CLK_CTRL); 333 tmp = LPC32XX_CLKPWR_I2SCTRL_I2S1_USE_DMA; 334 __raw_writel(tmp, LPC32XX_CLKPWR_I2S_CLK_CTRL); 335 336 lpc32xx_serial_init(); 337 338 /* 339 * AMBA peripheral clocks need to be enabled prior to AMBA device 340 * detection or a data fault will occur, so enable the clocks 341 * here. However, we don't want to enable them if the peripheral 342 * isn't included in the image 343 */ 344 #ifdef CONFIG_FB_ARMCLCD 345 tmp = __raw_readl(LPC32XX_CLKPWR_LCDCLK_CTRL); 346 __raw_writel((tmp | LPC32XX_CLKPWR_LCDCTRL_CLK_EN), 347 LPC32XX_CLKPWR_LCDCLK_CTRL); 348 #endif 349 #ifdef CONFIG_SPI_PL022 350 tmp = __raw_readl(LPC32XX_CLKPWR_SSP_CLK_CTRL); 351 __raw_writel((tmp | LPC32XX_CLKPWR_SSPCTRL_SSPCLK0_EN), 352 LPC32XX_CLKPWR_SSP_CLK_CTRL); 353 #endif 354 355 platform_add_devices(phy3250_devs, ARRAY_SIZE(phy3250_devs)); 356 for (i = 0; i < ARRAY_SIZE(amba_devs); i++) { 357 struct amba_device *d = amba_devs[i]; 358 amba_device_register(d, &iomem_resource); 359 } 360 361 /* Test clock needed for UDA1380 initial init */ 362 __raw_writel(LPC32XX_CLKPWR_TESTCLK2_SEL_MOSC | 363 LPC32XX_CLKPWR_TESTCLK_TESTCLK2_EN, 364 LPC32XX_CLKPWR_TEST_CLK_SEL); 365 366 i2c_register_board_info(0, phy3250_i2c_board_info, 367 ARRAY_SIZE(phy3250_i2c_board_info)); 368 } 369 370 static int __init lpc32xx_display_uid(void) 371 { 372 u32 uid[4]; 373 374 lpc32xx_get_uid(uid); 375 376 printk(KERN_INFO "LPC32XX unique ID: %08x%08x%08x%08x\n", 377 uid[3], uid[2], uid[1], uid[0]); 378 379 return 1; 380 } 381 arch_initcall(lpc32xx_display_uid); 382 383 MACHINE_START(PHY3250, "Phytec 3250 board with the LPC3250 Microcontroller") 384 /* Maintainer: Kevin Wells, NXP Semiconductors */ 385 .boot_params = 0x80000100, 386 .map_io = lpc32xx_map_io, 387 .init_irq = lpc32xx_init_irq, 388 .timer = &lpc32xx_timer, 389 .init_machine = phy3250_board_init, 390 MACHINE_END 391