palmz72.c 10.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Hardware definitions for Palm Zire72
 *
 * Authors:
 *	Vladimir "Farcaller" Pouzanov <farcaller@gmail.com>
 *	Sergey Lapin <slapin@ossfans.org>
 *	Alex Osborne <bobofdoom@gmail.com>
 *	Jan Herman <2hp@seznam.cz>
 *
 * Rewrite for mainline:
 *	Marek Vasut <marek.vasut@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * (find more info at www.hackndev.com)
 *
 */

#include <linux/platform_device.h>
22
#include <linux/syscore_ops.h>
23 24 25 26 27 28 29
#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/gpio_keys.h>
#include <linux/input.h>
#include <linux/pda_power.h>
#include <linux/pwm_backlight.h>
#include <linux/gpio.h>
30
#include <linux/wm97xx.h>
31
#include <linux/power_supply.h>
32
#include <linux/usb/gpio_vbus.h>
33
#include <linux/i2c-gpio.h>
34 35

#include <asm/mach-types.h>
36
#include <asm/suspend.h>
37 38 39
#include <asm/mach/arch.h>
#include <asm/mach/map.h>

40
#include <mach/pxa27x.h>
41 42
#include <mach/audio.h>
#include <mach/palmz72.h>
43 44 45 46
#include <linux/platform_data/mmc-pxamci.h>
#include <linux/platform_data/video-pxafb.h>
#include <linux/platform_data/irda-pxaficp.h>
#include <linux/platform_data/keypad-pxa27x.h>
47
#include <mach/udc.h>
48
#include <linux/platform_data/asoc-palm27x.h>
49
#include <mach/palm27x.h>
50

51
#include <mach/pm.h>
52
#include <linux/platform_data/media/camera-pxa.h>
53 54

#include <media/soc_camera.h>
55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78

#include "generic.h"
#include "devices.h"

/******************************************************************************
 * Pin configuration
 ******************************************************************************/
static unsigned long palmz72_pin_config[] __initdata = {
	/* MMC */
	GPIO32_MMC_CLK,
	GPIO92_MMC_DAT_0,
	GPIO109_MMC_DAT_1,
	GPIO110_MMC_DAT_2,
	GPIO111_MMC_DAT_3,
	GPIO112_MMC_CMD,
	GPIO14_GPIO,	/* SD detect */
	GPIO115_GPIO,	/* SD RO */
	GPIO98_GPIO,	/* SD power */

	/* AC97 */
	GPIO28_AC97_BITCLK,
	GPIO29_AC97_SDATA_IN_0,
	GPIO30_AC97_SDATA_OUT,
	GPIO31_AC97_SYNC,
79 80
	GPIO89_AC97_SYSCLK,
	GPIO113_AC97_nRESET,
81 82 83 84 85 86 87 88 89 90 91

	/* IrDA */
	GPIO49_GPIO,	/* ir disable */
	GPIO46_FICP_RXD,
	GPIO47_FICP_TXD,

	/* PWM */
	GPIO16_PWM0_OUT,

	/* USB */
	GPIO15_GPIO,	/* usb detect */
92
	GPIO95_GPIO,	/* usb pullup */
93 94 95 96 97 98 99 100 101 102 103

	/* Matrix keypad */
	GPIO100_KP_MKIN_0	| WAKEUP_ON_LEVEL_HIGH,
	GPIO101_KP_MKIN_1	| WAKEUP_ON_LEVEL_HIGH,
	GPIO102_KP_MKIN_2	| WAKEUP_ON_LEVEL_HIGH,
	GPIO97_KP_MKIN_3	| WAKEUP_ON_LEVEL_HIGH,
	GPIO103_KP_MKOUT_0,
	GPIO104_KP_MKOUT_1,
	GPIO105_KP_MKOUT_2,

	/* LCD */
104 105
	GPIOxx_LCD_TFT_16BPP,

106 107 108 109 110
	GPIO20_GPIO,	/* bl power */
	GPIO21_GPIO,	/* LCD border switch */
	GPIO22_GPIO,	/* LCD border color */
	GPIO96_GPIO,	/* lcd power */

111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
	/* PXA Camera */
	GPIO81_CIF_DD_0,
	GPIO48_CIF_DD_5,
	GPIO50_CIF_DD_3,
	GPIO51_CIF_DD_2,
	GPIO52_CIF_DD_4,
	GPIO53_CIF_MCLK,
	GPIO54_CIF_PCLK,
	GPIO55_CIF_DD_1,
	GPIO84_CIF_FV,
	GPIO85_CIF_LV,
	GPIO93_CIF_DD_6,
	GPIO108_CIF_DD_7,

	GPIO56_GPIO,	/* OV9640 Powerdown */
	GPIO57_GPIO,	/* OV9640 Reset */
	GPIO91_GPIO,	/* OV9640 Power */

	/* I2C */
	GPIO117_GPIO,	/* I2C_SCL */
	GPIO118_GPIO,	/* I2C_SDA */

133 134 135 136 137 138 139 140 141
	/* Misc. */
	GPIO0_GPIO	| WAKEUP_ON_LEVEL_HIGH,	/* power detect */
	GPIO88_GPIO,				/* green led */
	GPIO27_GPIO,				/* WM9712 IRQ */
};

/******************************************************************************
 * GPIO keyboard
 ******************************************************************************/
142
#if defined(CONFIG_KEYBOARD_PXA27x) || defined(CONFIG_KEYBOARD_PXA27x_MODULE)
143
static const unsigned int palmz72_matrix_keys[] = {
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
	KEY(0, 0, KEY_POWER),
	KEY(0, 1, KEY_F1),
	KEY(0, 2, KEY_ENTER),

	KEY(1, 0, KEY_F2),
	KEY(1, 1, KEY_F3),
	KEY(1, 2, KEY_F4),

	KEY(2, 0, KEY_UP),
	KEY(2, 2, KEY_DOWN),

	KEY(3, 0, KEY_RIGHT),
	KEY(3, 2, KEY_LEFT),
};

159 160 161 162 163
static struct matrix_keymap_data almz72_matrix_keymap_data = {
	.keymap			= palmz72_matrix_keys,
	.keymap_size		= ARRAY_SIZE(palmz72_matrix_keys),
};

164 165 166
static struct pxa27x_keypad_platform_data palmz72_keypad_platform_data = {
	.matrix_key_rows	= 4,
	.matrix_key_cols	= 3,
167
	.matrix_keymap_data	= &almz72_matrix_keymap_data,
168 169 170 171

	.debounce_interval	= 30,
};

172
static void __init palmz72_kpc_init(void)
173
{
174
	pxa_set_keypad_info(&palmz72_keypad_platform_data);
175
}
176 177 178
#else
static inline void palmz72_kpc_init(void) {}
#endif
179 180 181 182

/******************************************************************************
 * LEDs
 ******************************************************************************/
183
#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204
static struct gpio_led gpio_leds[] = {
	{
		.name			= "palmz72:green:led",
		.default_trigger	= "none",
		.gpio			= GPIO_NR_PALMZ72_LED_GREEN,
	},
};

static struct gpio_led_platform_data gpio_led_info = {
	.leds		= gpio_leds,
	.num_leds	= ARRAY_SIZE(gpio_leds),
};

static struct platform_device palmz72_leds = {
	.name	= "leds-gpio",
	.id	= -1,
	.dev	= {
		.platform_data	= &gpio_led_info,
	}
};

205
static void __init palmz72_leds_init(void)
206
{
207
	platform_device_register(&palmz72_leds);
208
}
209 210 211
#else
static inline void palmz72_leds_init(void) {}
#endif
212

213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240
#ifdef CONFIG_PM

/* We have some black magic here
 * PalmOS ROM on recover expects special struct physical address
 * to be transferred via PSPR. Using this struct PalmOS restores
 * its state after sleep. As for Linux, we need to setup it the
 * same way. More than that, PalmOS ROM changes some values in memory.
 * For now only one location is found, which needs special treatment.
 * Thanks to Alex Osborne, Andrzej Zaborowski, and lots of other people
 * for reading backtraces for me :)
 */

#define PALMZ72_SAVE_DWORD ((unsigned long *)0xc0000050)

static struct palmz72_resume_info palmz72_resume_info = {
	.magic0 = 0xb4e6,
	.magic1 = 1,

	/* reset state, MMU off etc */
	.arm_control = 0,
	.aux_control = 0,
	.ttb = 0,
	.domain_access = 0,
	.process_id = 0,
};

static unsigned long store_ptr;

241
/* syscore_ops for Palm Zire 72 PM */
242

243
static int palmz72_pm_suspend(void)
244 245
{
	/* setup the resume_info struct for the original bootloader */
246
	palmz72_resume_info.resume_addr = (u32) cpu_resume;
247 248 249 250 251 252 253 254 255 256

	/* Storing memory touched by ROM */
	store_ptr = *PALMZ72_SAVE_DWORD;

	/* Setting PSPR to a proper value */
	PSPR = virt_to_phys(&palmz72_resume_info);

	return 0;
}

257
static void palmz72_pm_resume(void)
258 259 260 261
{
	*PALMZ72_SAVE_DWORD = store_ptr;
}

262
static struct syscore_ops palmz72_pm_syscore_ops = {
263 264 265 266 267 268 269
	.suspend = palmz72_pm_suspend,
	.resume = palmz72_pm_resume,
};

static int __init palmz72_pm_init(void)
{
	if (machine_is_palmz72()) {
270 271
		register_syscore_ops(&palmz72_pm_syscore_ops);
		return 0;
272
	}
273
	return -ENODEV;
274 275 276 277 278
}

device_initcall(palmz72_pm_init);
#endif

279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378
/******************************************************************************
 * SoC Camera
 ******************************************************************************/
#if defined(CONFIG_SOC_CAMERA_OV9640) || \
	defined(CONFIG_SOC_CAMERA_OV9640_MODULE)
static struct pxacamera_platform_data palmz72_pxacamera_platform_data = {
	.flags		= PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 |
			PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN,
	.mclk_10khz	= 2600,
};

/* Board I2C devices. */
static struct i2c_board_info palmz72_i2c_device[] = {
	{
		I2C_BOARD_INFO("ov9640", 0x30),
	}
};

static int palmz72_camera_power(struct device *dev, int power)
{
	gpio_set_value(GPIO_NR_PALMZ72_CAM_PWDN, !power);
	mdelay(50);
	return 0;
}

static int palmz72_camera_reset(struct device *dev)
{
	gpio_set_value(GPIO_NR_PALMZ72_CAM_RESET, 1);
	mdelay(50);
	gpio_set_value(GPIO_NR_PALMZ72_CAM_RESET, 0);
	mdelay(50);
	return 0;
}

static struct soc_camera_link palmz72_iclink = {
	.bus_id		= 0, /* Match id in pxa27x_device_camera in device.c */
	.board_info	= &palmz72_i2c_device[0],
	.i2c_adapter_id	= 0,
	.module_name	= "ov96xx",
	.power		= &palmz72_camera_power,
	.reset		= &palmz72_camera_reset,
	.flags		= SOCAM_DATAWIDTH_8,
};

static struct i2c_gpio_platform_data palmz72_i2c_bus_data = {
	.sda_pin	= 118,
	.scl_pin	= 117,
	.udelay		= 10,
	.timeout	= 100,
};

static struct platform_device palmz72_i2c_bus_device = {
	.name		= "i2c-gpio",
	.id		= 0, /* we use this as a replacement for i2c-pxa */
	.dev		= {
		.platform_data	= &palmz72_i2c_bus_data,
	}
};

static struct platform_device palmz72_camera = {
	.name	= "soc-camera-pdrv",
	.id	= -1,
	.dev	= {
		.platform_data	= &palmz72_iclink,
	},
};

/* Here we request the camera GPIOs and configure them. We power up the camera
 * module, deassert the reset pin, but put it into powerdown (low to no power
 * consumption) mode. This allows us to later bring the module up fast. */
static struct gpio palmz72_camera_gpios[] = {
	{ GPIO_NR_PALMZ72_CAM_POWER,	GPIOF_INIT_HIGH,"Camera DVDD" },
	{ GPIO_NR_PALMZ72_CAM_RESET,	GPIOF_INIT_LOW,	"Camera RESET" },
	{ GPIO_NR_PALMZ72_CAM_PWDN,	GPIOF_INIT_LOW,	"Camera PWDN" },
};

static inline void __init palmz72_cam_gpio_init(void)
{
	int ret;

	ret = gpio_request_array(ARRAY_AND_SIZE(palmz72_camera_gpios));
	if (!ret)
		gpio_free_array(ARRAY_AND_SIZE(palmz72_camera_gpios));
	else
		printk(KERN_ERR "Camera GPIO init failed!\n");

	return;
}

static void __init palmz72_camera_init(void)
{
	palmz72_cam_gpio_init();
	pxa_set_camera_info(&palmz72_pxacamera_platform_data);
	platform_device_register(&palmz72_i2c_bus_device);
	platform_device_register(&palmz72_camera);
}
#else
static inline void palmz72_camera_init(void) {}
#endif

379 380 381 382 383 384
/******************************************************************************
 * Machine init
 ******************************************************************************/
static void __init palmz72_init(void)
{
	pxa2xx_mfp_config(ARRAY_AND_SIZE(palmz72_pin_config));
385 386 387 388
	pxa_set_ffuart_info(NULL);
	pxa_set_btuart_info(NULL);
	pxa_set_stuart_info(NULL);

389 390 391 392 393 394 395 396 397 398 399 400 401
	palm27x_mmc_init(GPIO_NR_PALMZ72_SD_DETECT_N, GPIO_NR_PALMZ72_SD_RO,
			GPIO_NR_PALMZ72_SD_POWER_N, 1);
	palm27x_lcd_init(-1, &palm_320x320_lcd_mode);
	palm27x_udc_init(GPIO_NR_PALMZ72_USB_DETECT_N,
			GPIO_NR_PALMZ72_USB_PULLUP, 0);
	palm27x_irda_init(GPIO_NR_PALMZ72_IR_DISABLE);
	palm27x_ac97_init(PALMZ72_BAT_MIN_VOLTAGE, PALMZ72_BAT_MAX_VOLTAGE,
			-1, 113);
	palm27x_pwm_init(-1, -1);
	palm27x_power_init(-1, -1);
	palm27x_pmic_init();
	palmz72_kpc_init();
	palmz72_leds_init();
402
	palmz72_camera_init();
403 404 405
}

MACHINE_START(PALMZ72, "Palm Zire72")
406
	.atag_offset	= 0x100,
407
	.map_io		= pxa27x_map_io,
Rob Herring's avatar
Rob Herring committed
408
	.nr_irqs	= PXA_NR_IRQS,
409
	.init_irq	= pxa27x_init_irq,
410
	.handle_irq	= pxa27x_handle_irq,
411
	.init_time	= pxa_timer_init,
412 413
	.init_machine	= palmz72_init,
	.restart	= pxa_restart,
414
MACHINE_END