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