1/* 2 * Board-specific setup code for Remote Media Terminal 1 (RMT1) 3 * add-on board for the ATNGW100 Network Gateway 4 * 5 * Copyright (C) 2008 Mediama Technologies 6 * Based on ATNGW100 Network Gateway (Copyright (C) Atmel) 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 version 2 as 10 * published by the Free Software Foundation. 11 */ 12#include <linux/gpio.h> 13#include <linux/init.h> 14#include <linux/irq.h> 15#include <linux/linkage.h> 16#include <linux/platform_device.h> 17#include <linux/types.h> 18#include <linux/fb.h> 19#include <linux/leds.h> 20#include <linux/pwm.h> 21#include <linux/leds_pwm.h> 22#include <linux/input.h> 23#include <linux/gpio_keys.h> 24#include <linux/atmel_serial.h> 25#include <linux/spi/spi.h> 26#include <linux/spi/ads7846.h> 27 28#include <video/atmel_lcdc.h> 29#include <sound/atmel-ac97c.h> 30 31#include <asm/delay.h> 32#include <asm/io.h> 33#include <asm/setup.h> 34 35#include <mach/at32ap700x.h> 36#include <mach/board.h> 37#include <mach/init.h> 38#include <mach/portmux.h> 39 40/* Define board-specifoic GPIO assignments */ 41#define PIN_LCD_BL GPIO_PIN_PA(28) 42#define PWM_CH_BL 0 /* Must match with GPIO pin definition */ 43#define PIN_LCD_DISP GPIO_PIN_PA(31) 44#define PIN_AC97_RST_N GPIO_PIN_PA(30) 45#define PB_EXTINT_BASE 25 46#define TS_IRQ 0 47#define PIN_TS_EXTINT GPIO_PIN_PB(PB_EXTINT_BASE+TS_IRQ) 48#define PIN_PB_LEFT GPIO_PIN_PB(11) 49#define PIN_PB_RIGHT GPIO_PIN_PB(12) 50#define PIN_PWR_SW_N GPIO_PIN_PB(14) 51#define PIN_PWR_ON GPIO_PIN_PB(13) 52#define PIN_ZB_RST_N GPIO_PIN_PA(21) 53#define PIN_BT_RST GPIO_PIN_PA(22) 54#define PIN_LED_SYS GPIO_PIN_PA(16) 55#define PIN_LED_A GPIO_PIN_PA(19) 56#define PIN_LED_B GPIO_PIN_PE(19) 57 58#ifdef CONFIG_BOARD_MRMT_LCD_LQ043T3DX0X 59/* Sharp LQ043T3DX0x (or compatible) panel */ 60static struct fb_videomode __initdata lcd_fb_modes[] = { 61 { 62 .name = "480x272 @ 59.94Hz", 63 .refresh = 59.94, 64 .xres = 480, .yres = 272, 65 .pixclock = KHZ2PICOS(9000), 66 67 .left_margin = 2, .right_margin = 2, 68 .upper_margin = 3, .lower_margin = 9, 69 .hsync_len = 41, .vsync_len = 1, 70 71 .sync = 0, 72 .vmode = FB_VMODE_NONINTERLACED, 73 }, 74}; 75 76static struct fb_monspecs __initdata lcd_fb_default_monspecs = { 77 .manufacturer = "SHA", 78 .monitor = "LQ043T3DX02", 79 .modedb = lcd_fb_modes, 80 .modedb_len = ARRAY_SIZE(lcd_fb_modes), 81 .hfmin = 14915, 82 .hfmax = 17638, 83 .vfmin = 53, 84 .vfmax = 61, 85 .dclkmax = 9260000, 86}; 87 88static struct atmel_lcdfb_pdata __initdata rmt_lcdc_data = { 89 .default_bpp = 24, 90 .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, 91 .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT 92 | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE 93 | ATMEL_LCDC_INVCLK_NORMAL 94 | ATMEL_LCDC_MEMOR_BIG), 95 .lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB, 96 .default_monspecs = &lcd_fb_default_monspecs, 97 .guard_time = 2, 98}; 99#endif 100 101#ifdef CONFIG_BOARD_MRMT_LCD_KWH043GM08 102/* Sharp KWH043GM08-Fxx (or compatible) panel */ 103static struct fb_videomode __initdata lcd_fb_modes[] = { 104 { 105 .name = "480x272 @ 59.94Hz", 106 .refresh = 59.94, 107 .xres = 480, .yres = 272, 108 .pixclock = KHZ2PICOS(9000), 109 110 .left_margin = 2, .right_margin = 2, 111 .upper_margin = 3, .lower_margin = 9, 112 .hsync_len = 41, .vsync_len = 1, 113 114 .sync = 0, 115 .vmode = FB_VMODE_NONINTERLACED, 116 }, 117}; 118 119static struct fb_monspecs __initdata lcd_fb_default_monspecs = { 120 .manufacturer = "FOR", 121 .monitor = "KWH043GM08", 122 .modedb = lcd_fb_modes, 123 .modedb_len = ARRAY_SIZE(lcd_fb_modes), 124 .hfmin = 14915, 125 .hfmax = 17638, 126 .vfmin = 53, 127 .vfmax = 61, 128 .dclkmax = 9260000, 129}; 130 131static struct atmel_lcdfb_pdata __initdata rmt_lcdc_data = { 132 .default_bpp = 24, 133 .default_dmacon = ATMEL_LCDC_DMAEN | ATMEL_LCDC_DMA2DEN, 134 .default_lcdcon2 = (ATMEL_LCDC_DISTYPE_TFT 135 | ATMEL_LCDC_CLKMOD_ALWAYSACTIVE 136 | ATMEL_LCDC_INVCLK_INVERTED 137 | ATMEL_LCDC_MEMOR_BIG), 138 .lcd_wiring_mode = ATMEL_LCDC_WIRING_RGB, 139 .default_monspecs = &lcd_fb_default_monspecs, 140 .guard_time = 2, 141}; 142#endif 143 144#ifdef CONFIG_BOARD_MRMT_AC97 145static struct ac97c_platform_data __initdata ac97c0_data = { 146 .reset_pin = PIN_AC97_RST_N, 147}; 148#endif 149 150#ifdef CONFIG_BOARD_MRMT_UCB1400_TS 151/* NOTE: IRQ assignment relies on kernel module parameter */ 152static struct platform_device rmt_ts_device = { 153 .name = "ucb1400_ts", 154 .id = -1, 155}; 156#endif 157 158#ifdef CONFIG_BOARD_MRMT_BL_PWM 159/* PWM LEDs: LCD Backlight, etc */ 160static struct pwm_lookup pwm_lookup[] = { 161 PWM_LOOKUP("at91sam9rl-pwm", PWM_CH_BL, "leds_pwm", "ds1", 162 5000, PWM_POLARITY_INVERSED), 163}; 164 165static struct led_pwm pwm_leds[] = { 166 { 167 .name = "backlight", 168 .max_brightness = 255, 169 }, 170}; 171 172static struct led_pwm_platform_data pwm_data = { 173 .num_leds = ARRAY_SIZE(pwm_leds), 174 .leds = pwm_leds, 175}; 176 177static struct platform_device leds_pwm = { 178 .name = "leds_pwm", 179 .id = -1, 180 .dev = { 181 .platform_data = &pwm_data, 182 }, 183}; 184#endif 185 186#ifdef CONFIG_BOARD_MRMT_ADS7846_TS 187static int ads7846_pendown_state(void) 188{ 189 return !gpio_get_value( PIN_TS_EXTINT ); /* PENIRQ.*/ 190} 191 192static struct ads7846_platform_data ads_info = { 193 .model = 7846, 194 .keep_vref_on = 0, /* Use external VREF pin */ 195 .vref_delay_usecs = 0, 196 .vref_mv = 3300, /* VREF = 3.3V */ 197 .settle_delay_usecs = 800, 198 .penirq_recheck_delay_usecs = 800, 199 .x_plate_ohms = 750, 200 .y_plate_ohms = 300, 201 .pressure_max = 4096, 202 .debounce_max = 1, 203 .debounce_rep = 0, 204 .debounce_tol = (~0), 205 .get_pendown_state = ads7846_pendown_state, 206 .filter = NULL, 207 .filter_init = NULL, 208}; 209 210static struct spi_board_info spi01_board_info[] __initdata = { 211 { 212 .modalias = "ads7846", 213 .max_speed_hz = 31250*26, 214 .bus_num = 0, 215 .chip_select = 1, 216 .platform_data = &ads_info, 217 .irq = AT32_EXTINT(TS_IRQ), 218 }, 219}; 220#endif 221 222/* GPIO Keys: left, right, power, etc */ 223static const struct gpio_keys_button rmt_gpio_keys_buttons[] = { 224 [0] = { 225 .type = EV_KEY, 226 .code = KEY_POWER, 227 .gpio = PIN_PWR_SW_N, 228 .active_low = 1, 229 .desc = "power button", 230 }, 231 [1] = { 232 .type = EV_KEY, 233 .code = KEY_LEFT, 234 .gpio = PIN_PB_LEFT, 235 .active_low = 1, 236 .desc = "left button", 237 }, 238 [2] = { 239 .type = EV_KEY, 240 .code = KEY_RIGHT, 241 .gpio = PIN_PB_RIGHT, 242 .active_low = 1, 243 .desc = "right button", 244 }, 245}; 246 247static const struct gpio_keys_platform_data rmt_gpio_keys_data = { 248 .nbuttons = ARRAY_SIZE(rmt_gpio_keys_buttons), 249 .buttons = (void *) rmt_gpio_keys_buttons, 250}; 251 252static struct platform_device rmt_gpio_keys = { 253 .name = "gpio-keys", 254 .id = -1, 255 .dev = { 256 .platform_data = (void *) &rmt_gpio_keys_data, 257 } 258}; 259 260#ifdef CONFIG_BOARD_MRMT_RTC_I2C 261static struct i2c_board_info __initdata mrmt1_i2c_rtc = { 262 I2C_BOARD_INFO("s35390a", 0x30), 263 .irq = 0, 264}; 265#endif 266 267static void mrmt_power_off(void) 268{ 269 /* PWR_ON=0 will force power off */ 270 gpio_set_value( PIN_PWR_ON, 0 ); 271} 272 273static int __init mrmt1_init(void) 274{ 275 gpio_set_value( PIN_PWR_ON, 1 ); /* Ensure PWR_ON is enabled */ 276 277 pm_power_off = mrmt_power_off; 278 279 /* Setup USARTS (other than console) */ 280 at32_map_usart(2, 1, 0); /* USART 2: /dev/ttyS1, RMT1:DB9M */ 281 at32_map_usart(3, 2, ATMEL_USART_RTS | ATMEL_USART_CTS); 282 /* USART 3: /dev/ttyS2, RMT1:Wireless, w/ RTS/CTS */ 283 at32_add_device_usart(1); 284 at32_add_device_usart(2); 285 286 /* Select GPIO Key pins */ 287 at32_select_gpio( PIN_PWR_SW_N, AT32_GPIOF_DEGLITCH); 288 at32_select_gpio( PIN_PB_LEFT, AT32_GPIOF_DEGLITCH); 289 at32_select_gpio( PIN_PB_RIGHT, AT32_GPIOF_DEGLITCH); 290 platform_device_register(&rmt_gpio_keys); 291 292#ifdef CONFIG_BOARD_MRMT_RTC_I2C 293 i2c_register_board_info(0, &mrmt1_i2c_rtc, 1); 294#endif 295 296#ifndef CONFIG_BOARD_MRMT_LCD_DISABLE 297 /* User "alternate" LCDC inferface on Port E & D */ 298 /* NB: exclude LCDC_CC pin, as NGW100 reserves it for other use */ 299 at32_add_device_lcdc(0, &rmt_lcdc_data, 300 fbmem_start, fbmem_size, 301 (ATMEL_LCDC_ALT_24BIT | ATMEL_LCDC_PE_DVAL ) ); 302#endif 303 304#ifdef CONFIG_BOARD_MRMT_AC97 305 at32_add_device_ac97c(0, &ac97c0_data, AC97C_BOTH); 306#endif 307 308#ifdef CONFIG_BOARD_MRMT_ADS7846_TS 309 /* Select the Touchscreen interrupt pin mode */ 310 at32_select_periph( GPIO_PIOB_BASE, 1 << (PB_EXTINT_BASE+TS_IRQ), 311 GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH); 312 irq_set_irq_type(AT32_EXTINT(TS_IRQ), IRQ_TYPE_EDGE_FALLING); 313 at32_spi_setup_slaves(0,spi01_board_info,ARRAY_SIZE(spi01_board_info)); 314 spi_register_board_info(spi01_board_info,ARRAY_SIZE(spi01_board_info)); 315#endif 316 317#ifdef CONFIG_BOARD_MRMT_UCB1400_TS 318 /* Select the Touchscreen interrupt pin mode */ 319 at32_select_periph( GPIO_PIOB_BASE, 1 << (PB_EXTINT_BASE+TS_IRQ), 320 GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH); 321 platform_device_register(&rmt_ts_device); 322#endif 323 324 at32_select_gpio( PIN_LCD_DISP, AT32_GPIOF_OUTPUT ); 325 gpio_request( PIN_LCD_DISP, "LCD_DISP" ); 326 gpio_direction_output( PIN_LCD_DISP, 0 ); /* LCD DISP */ 327#ifdef CONFIG_BOARD_MRMT_LCD_DISABLE 328 /* Keep Backlight and DISP off */ 329 at32_select_gpio( PIN_LCD_BL, AT32_GPIOF_OUTPUT ); 330 gpio_request( PIN_LCD_BL, "LCD_BL" ); 331 gpio_direction_output( PIN_LCD_BL, 0 ); /* Backlight */ 332#else 333 gpio_set_value( PIN_LCD_DISP, 1 ); /* DISP asserted first */ 334#ifdef CONFIG_BOARD_MRMT_BL_PWM 335 /* Use PWM for Backlight controls */ 336 at32_add_device_pwm(1 << PWM_CH_BL); 337 pwm_add_table(pwm_lookup, ARRAY_SIZE(pwm_lookup)); 338 platform_device_register(&leds_pwm); 339#else 340 /* Backlight always on */ 341 udelay( 1 ); 342 at32_select_gpio( PIN_LCD_BL, AT32_GPIOF_OUTPUT ); 343 gpio_request( PIN_LCD_BL, "LCD_BL" ); 344 gpio_direction_output( PIN_LCD_BL, 1 ); 345#endif 346#endif 347 348 /* Make sure BT and Zigbee modules in reset */ 349 at32_select_gpio( PIN_BT_RST, AT32_GPIOF_OUTPUT ); 350 gpio_request( PIN_BT_RST, "BT_RST" ); 351 gpio_direction_output( PIN_BT_RST, 1 ); 352 /* BT Module in Reset */ 353 354 at32_select_gpio( PIN_ZB_RST_N, AT32_GPIOF_OUTPUT ); 355 gpio_request( PIN_ZB_RST_N, "ZB_RST_N" ); 356 gpio_direction_output( PIN_ZB_RST_N, 0 ); 357 /* XBee Module in Reset */ 358 359#ifdef CONFIG_BOARD_MRMT_WIRELESS_ZB 360 udelay( 1000 ); 361 /* Unreset the XBee Module */ 362 gpio_set_value( PIN_ZB_RST_N, 1 ); 363#endif 364#ifdef CONFIG_BOARD_MRMT_WIRELESS_BT 365 udelay( 1000 ); 366 /* Unreset the BT Module */ 367 gpio_set_value( PIN_BT_RST, 0 ); 368#endif 369 370 return 0; 371} 372arch_initcall(mrmt1_init); 373 374static int __init mrmt1_early_init(void) 375{ 376 /* To maintain power-on signal in case boot loader did not already */ 377 at32_select_gpio( PIN_PWR_ON, AT32_GPIOF_OUTPUT ); 378 gpio_request( PIN_PWR_ON, "PIN_PWR_ON" ); 379 gpio_direction_output( PIN_PWR_ON, 1 ); 380 381 return 0; 382} 383core_initcall(mrmt1_early_init); 384