diff options
Diffstat (limited to 'arch/arm/mach-pxa/magician.c')
| -rw-r--r-- | arch/arm/mach-pxa/magician.c | 680 | 
1 files changed, 422 insertions, 258 deletions
| diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c index a9761c293028..896b268c3ab7 100644 --- a/arch/arm/mach-pxa/magician.c +++ b/arch/arm/mach-pxa/magician.c @@ -24,8 +24,10 @@  #include <linux/mfd/htc-pasic3.h>  #include <linux/mtd/physmap.h>  #include <linux/pda_power.h> +#include <linux/pwm.h>  #include <linux/pwm_backlight.h>  #include <linux/regulator/driver.h> +#include <linux/regulator/fixed.h>  #include <linux/regulator/gpio-regulator.h>  #include <linux/regulator/machine.h>  #include <linux/usb/gpio_vbus.h> @@ -43,6 +45,12 @@  #include <linux/platform_data/irda-pxaficp.h>  #include <linux/platform_data/usb-ohci-pxa27x.h> +#include <linux/regulator/max1586.h> + +#include <linux/platform_data/pxa2xx_udc.h> +#include <mach/udc.h> +#include <mach/pxa27x-udc.h> +  #include "devices.h"  #include "generic.h" @@ -52,36 +60,36 @@ static unsigned long magician_pin_config[] __initdata = {  	GPIO20_nSDCS_2,  	GPIO21_nSDCS_3,  	GPIO15_nCS_1, -	GPIO78_nCS_2,   /* PASIC3 */ -	GPIO79_nCS_3,   /* EGPIO CPLD */ +	GPIO78_nCS_2,	/* PASIC3 */ +	GPIO79_nCS_3,	/* EGPIO CPLD */  	GPIO80_nCS_4,  	GPIO33_nCS_5, -	/* I2C */ +	/* I2C UDA1380 + OV9640 */  	GPIO117_I2C_SCL,  	GPIO118_I2C_SDA, -	/* PWM 0 */ +	/* PWM 0 - LCD backlight */  	GPIO16_PWM0_OUT, -	/* I2S */ +	/* I2S UDA1380 capture */  	GPIO28_I2S_BITCLK_OUT,  	GPIO29_I2S_SDATA_IN,  	GPIO31_I2S_SYNC,  	GPIO113_I2S_SYSCLK, -	/* SSP 1 */ +	/* SSP 1 UDA1380 playback */  	GPIO23_SSP1_SCLK,  	GPIO24_SSP1_SFRM,  	GPIO25_SSP1_TXD, -	/* SSP 2 */ +	/* SSP 2 TSC2046 touchscreen */  	GPIO19_SSP2_SCLK,  	GPIO14_SSP2_SFRM,  	GPIO89_SSP2_TXD,  	GPIO88_SSP2_RXD, -	/* MMC */ +	/* MMC/SD/SDHC slot */  	GPIO32_MMC_CLK,  	GPIO92_MMC_DAT_0,  	GPIO109_MMC_DAT_1, @@ -92,7 +100,7 @@ static unsigned long magician_pin_config[] __initdata = {  	/* LCD */  	GPIOxx_LCD_TFT_16BPP, -	/* QCI */ +	/* QCI camera interface */  	GPIO12_CIF_DD_7,  	GPIO17_CIF_DD_6,  	GPIO50_CIF_DD_3, @@ -120,12 +128,13 @@ static unsigned long magician_pin_config[] __initdata = {  };  /* - * IRDA + * IrDA   */  static struct pxaficp_platform_data magician_ficp_info = {  	.gpio_pwdown		= GPIO83_MAGICIAN_nIR_EN,  	.transceiver_cap	= IR_SIRMODE | IR_OFF, +	.gpio_pwdown_inverted	= 0,  };  /* @@ -134,11 +143,11 @@ static struct pxaficp_platform_data magician_ficp_info = {  #define INIT_KEY(_code, _gpio, _desc)	\  	{				\ -		.code   = KEY_##_code,	\ -		.gpio   = _gpio,	\ -		.desc   = _desc,	\ -		.type   = EV_KEY,	\ -		.wakeup = 1,		\ +		.code	= KEY_##_code,	\ +		.gpio	= _gpio,	\ +		.desc	= _desc,	\ +		.type	= EV_KEY,	\ +		.wakeup	= 1,		\  	}  static struct gpio_keys_button magician_button_table[] = { @@ -160,164 +169,162 @@ static struct gpio_keys_button magician_button_table[] = {  };  static struct gpio_keys_platform_data gpio_keys_data = { -	.buttons  = magician_button_table, -	.nbuttons = ARRAY_SIZE(magician_button_table), +	.buttons	= magician_button_table, +	.nbuttons	= ARRAY_SIZE(magician_button_table),  };  static struct platform_device gpio_keys = { -	.name = "gpio-keys", -	.dev  = { +	.name	= "gpio-keys", +	.dev	= {  		.platform_data = &gpio_keys_data,  	}, -	.id   = -1, +	.id	= -1,  }; -  /*   * EGPIO (Xilinx CPLD)   * - * 7 32-bit aligned 8-bit registers: 3x output, 1x irq, 3x input + * 32-bit aligned 8-bit registers + * 16 possible registers (reg windows size), only 7 used: + * 3x output, 1x irq, 3x input   */  static struct resource egpio_resources[] = {  	[0] = { -		.start = PXA_CS3_PHYS, -		.end   = PXA_CS3_PHYS + 0x20 - 1, -		.flags = IORESOURCE_MEM, +		.start	= PXA_CS3_PHYS, +		.end	= PXA_CS3_PHYS + 0x20 - 1, +		.flags	= IORESOURCE_MEM,  	},  	[1] = { -		.start = PXA_GPIO_TO_IRQ(GPIO13_MAGICIAN_CPLD_IRQ), -		.end   = PXA_GPIO_TO_IRQ(GPIO13_MAGICIAN_CPLD_IRQ), -		.flags = IORESOURCE_IRQ, +		.start	= PXA_GPIO_TO_IRQ(GPIO13_MAGICIAN_CPLD_IRQ), +		.end	= PXA_GPIO_TO_IRQ(GPIO13_MAGICIAN_CPLD_IRQ), +		.flags	= IORESOURCE_IRQ,  	},  };  static struct htc_egpio_chip egpio_chips[] = {  	[0] = { -		.reg_start = 0, -		.gpio_base = MAGICIAN_EGPIO(0, 0), -		.num_gpios = 24, -		.direction = HTC_EGPIO_OUTPUT, -		.initial_values = 0x40, /* EGPIO_MAGICIAN_GSM_RESET */ +		.reg_start	= 0, +		.gpio_base	= MAGICIAN_EGPIO(0, 0), +		.num_gpios	= 24, +		.direction	= HTC_EGPIO_OUTPUT, +		/* +		 * Depends on modules configuration +		 */ +		.initial_values	= 0x40, /* EGPIO_MAGICIAN_GSM_RESET */  	},  	[1] = { -		.reg_start = 4, -		.gpio_base = MAGICIAN_EGPIO(4, 0), -		.num_gpios = 24, -		.direction = HTC_EGPIO_INPUT, +		.reg_start	= 4, +		.gpio_base	= MAGICIAN_EGPIO(4, 0), +		.num_gpios	= 24, +		.direction	= HTC_EGPIO_INPUT,  	},  };  static struct htc_egpio_platform_data egpio_info = { -	.reg_width    = 8, -	.bus_width    = 32, -	.irq_base     = IRQ_BOARD_START, -	.num_irqs     = 4, -	.ack_register = 3, -	.chip         = egpio_chips, -	.num_chips    = ARRAY_SIZE(egpio_chips), +	.reg_width	= 8, +	.bus_width	= 32, +	.irq_base	= IRQ_BOARD_START, +	.num_irqs	= 4, +	.ack_register	= 3, +	.chip		= egpio_chips, +	.num_chips	= ARRAY_SIZE(egpio_chips),  };  static struct platform_device egpio = { -	.name          = "htc-egpio", -	.id            = -1, -	.resource      = egpio_resources, -	.num_resources = ARRAY_SIZE(egpio_resources), +	.name		= "htc-egpio", +	.id		= -1, +	.resource	= egpio_resources, +	.num_resources	= ARRAY_SIZE(egpio_resources),  	.dev = {  		.platform_data = &egpio_info,  	},  };  /* - * LCD - Toppoly TD028STEB1 or Samsung LTP280QV + * PXAFB LCD - Toppoly TD028STEB1 or Samsung LTP280QV   */  static struct pxafb_mode_info toppoly_modes[] = {  	{ -		.pixclock     = 96153, -		.bpp          = 16, -		.xres         = 240, -		.yres         = 320, -		.hsync_len    = 11, -		.vsync_len    = 3, -		.left_margin  = 19, -		.upper_margin = 2, -		.right_margin = 10, -		.lower_margin = 2, -		.sync         = 0, +		.pixclock	= 96153, +		.bpp		= 16, +		.xres		= 240, +		.yres		= 320, +		.hsync_len	= 11, +		.vsync_len	= 3, +		.left_margin	= 19, +		.upper_margin	= 2, +		.right_margin	= 10, +		.lower_margin	= 2, +		.sync		= 0,  	},  };  static struct pxafb_mode_info samsung_modes[] = {  	{ -		.pixclock     = 96153, -		.bpp          = 16, -		.xres         = 240, -		.yres         = 320, -		.hsync_len    = 8, -		.vsync_len    = 4, -		.left_margin  = 9, -		.upper_margin = 4, -		.right_margin = 9, -		.lower_margin = 4, -		.sync         = FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, +		.pixclock	= 226469, +		.bpp		= 16, +		.xres		= 240, +		.yres		= 320, +		.hsync_len	= 8, +		.vsync_len	= 4, +		.left_margin	= 9, +		.upper_margin	= 4, +		.right_margin	= 9, +		.lower_margin	= 4, +		.sync	= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,  	},  };  static void toppoly_lcd_power(int on, struct fb_var_screeninfo *si)  { -	pr_debug("Toppoly LCD power\n"); +	pr_debug("Toppoly LCD power: %s\n", on ? "on" : "off");  	if (on) { -		pr_debug("on\n");  		gpio_set_value(EGPIO_MAGICIAN_TOPPOLY_POWER, 1); -		gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 1); +		gpio_set_value(GPIO106_MAGICIAN_LCD_DCDC_NRESET, 1);  		udelay(2000);  		gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 1);  		udelay(2000);  		/* FIXME: enable LCDC here */  		udelay(2000); -		gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 1); +		gpio_set_value(GPIO104_MAGICIAN_LCD_VOFF_EN, 1);  		udelay(2000); -		gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 1); +		gpio_set_value(GPIO105_MAGICIAN_LCD_VON_EN, 1);  	} else { -		pr_debug("off\n");  		msleep(15); -		gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 0); +		gpio_set_value(GPIO105_MAGICIAN_LCD_VON_EN, 0);  		udelay(500); -		gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 0); +		gpio_set_value(GPIO104_MAGICIAN_LCD_VOFF_EN, 0);  		udelay(1000); -		gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 0); +		gpio_set_value(GPIO106_MAGICIAN_LCD_DCDC_NRESET, 0);  		gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 0);  	}  }  static void samsung_lcd_power(int on, struct fb_var_screeninfo *si)  { -	pr_debug("Samsung LCD power\n"); +	pr_debug("Samsung LCD power: %s\n", on ? "on" : "off");  	if (on) { -		pr_debug("on\n");  		if (system_rev < 3)  			gpio_set_value(GPIO75_MAGICIAN_SAMSUNG_POWER, 1);  		else  			gpio_set_value(EGPIO_MAGICIAN_LCD_POWER, 1); -		mdelay(10); -		gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 1); -		mdelay(10); -		gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 1); -		mdelay(30); -		gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 1); -		mdelay(10); +		mdelay(6); +		gpio_set_value(GPIO106_MAGICIAN_LCD_DCDC_NRESET, 1); +		mdelay(6);	/* Avdd -> Voff >5ms */ +		gpio_set_value(GPIO104_MAGICIAN_LCD_VOFF_EN, 1); +		mdelay(16);	/* Voff -> Von >(5+10)ms */ +		gpio_set_value(GPIO105_MAGICIAN_LCD_VON_EN, 1);  	} else { -		pr_debug("off\n"); -		mdelay(10); -		gpio_set_value(GPIO105_MAGICIAN_LCD_POWER_2, 0); -		mdelay(30); -		gpio_set_value(GPIO104_MAGICIAN_LCD_POWER_1, 0); -		mdelay(10); -		gpio_set_value(GPIO106_MAGICIAN_LCD_POWER_3, 0); -		mdelay(10); +		gpio_set_value(GPIO105_MAGICIAN_LCD_VON_EN, 0); +		mdelay(16); +		gpio_set_value(GPIO104_MAGICIAN_LCD_VOFF_EN, 0); +		mdelay(6); +		gpio_set_value(GPIO106_MAGICIAN_LCD_DCDC_NRESET, 0); +		mdelay(6);  		if (system_rev < 3)  			gpio_set_value(GPIO75_MAGICIAN_SAMSUNG_POWER, 0);  		else @@ -326,29 +333,43 @@ static void samsung_lcd_power(int on, struct fb_var_screeninfo *si)  }  static struct pxafb_mach_info toppoly_info = { -	.modes           = toppoly_modes, -	.num_modes       = 1, -	.fixed_modes     = 1, -	.lcd_conn	= LCD_COLOR_TFT_16BPP, -	.pxafb_lcd_power = toppoly_lcd_power, +	.modes			= toppoly_modes, +	.num_modes		= 1, +	.fixed_modes		= 1, +	.lcd_conn		= LCD_COLOR_TFT_16BPP, +	.pxafb_lcd_power	= toppoly_lcd_power,  };  static struct pxafb_mach_info samsung_info = { -	.modes           = samsung_modes, -	.num_modes       = 1, -	.fixed_modes     = 1, -	.lcd_conn	 = LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL |\ -			   LCD_ALTERNATE_MAPPING, -	.pxafb_lcd_power = samsung_lcd_power, +	.modes			= samsung_modes, +	.num_modes		= 1, +	.fixed_modes		= 1, +	.lcd_conn		= LCD_COLOR_TFT_16BPP | LCD_PCLK_EDGE_FALL | +		LCD_ALTERNATE_MAPPING, +	.pxafb_lcd_power	= samsung_lcd_power,  };  /*   * Backlight   */ +static struct pwm_lookup magician_pwm_lookup[] = { +	PWM_LOOKUP("pxa27x-pwm.0", 0, "pwm-backlight", NULL, 30923, +		   PWM_POLARITY_NORMAL), +}; + + /* + * fixed regulator for pwm_backlight + */ + +static struct regulator_consumer_supply pwm_backlight_supply[] = { +	REGULATOR_SUPPLY("power", "pwm_backlight"), +}; + +  static struct gpio magician_bl_gpios[] = { -	{ EGPIO_MAGICIAN_BL_POWER,  GPIOF_DIR_OUT, "Backlight power" }, -	{ EGPIO_MAGICIAN_BL_POWER2, GPIOF_DIR_OUT, "Backlight power 2" }, +	{ EGPIO_MAGICIAN_BL_POWER,	GPIOF_DIR_OUT, "Backlight power" }, +	{ EGPIO_MAGICIAN_BL_POWER2,	GPIOF_DIR_OUT, "Backlight power 2" },  };  static int magician_backlight_init(struct device *dev) @@ -358,6 +379,7 @@ static int magician_backlight_init(struct device *dev)  static int magician_backlight_notify(struct device *dev, int brightness)  { +	pr_debug("Brightness = %i\n", brightness);  	gpio_set_value(EGPIO_MAGICIAN_BL_POWER, brightness);  	if (brightness >= 200) {  		gpio_set_value(EGPIO_MAGICIAN_BL_POWER2, 1); @@ -373,28 +395,33 @@ static void magician_backlight_exit(struct device *dev)  	gpio_free_array(ARRAY_AND_SIZE(magician_bl_gpios));  } +/* + * LCD PWM backlight (main) + * + * MP1521 frequency should be: + *	100-400 Hz = 2 .5*10^6 - 10 *10^6 ns + */ +  static struct platform_pwm_backlight_data backlight_data = { -	.pwm_id         = 0, -	.max_brightness = 272, -	.dft_brightness = 100, -	.pwm_period_ns  = 30923, -	.enable_gpio    = -1, -	.init           = magician_backlight_init, -	.notify         = magician_backlight_notify, -	.exit           = magician_backlight_exit, +	.max_brightness	= 272, +	.dft_brightness	= 100, +	.enable_gpio	= -1, +	.init		= magician_backlight_init, +	.notify		= magician_backlight_notify, +	.exit		= magician_backlight_exit,  };  static struct platform_device backlight = { -	.name = "pwm-backlight", -	.id   = -1, -	.dev  = { -		.parent        = &pxa27x_device_pwm0.dev, -		.platform_data = &backlight_data, +	.name	= "pwm-backlight", +	.id	= -1, +	.dev	= { +		.parent		= &pxa27x_device_pwm0.dev, +		.platform_data	= &backlight_data,  	},  };  /* - * LEDs + * GPIO LEDs, Phone keys backlight, vibra   */  static struct gpio_led gpio_leds[] = { @@ -416,69 +443,32 @@ static struct gpio_led_platform_data gpio_led_info = {  };  static struct platform_device leds_gpio = { -	.name = "leds-gpio", -	.id   = -1, -	.dev  = { +	.name	= "leds-gpio", +	.id	= -1, +	.dev	= {  		.platform_data = &gpio_led_info,  	},  }; -static struct pasic3_led pasic3_leds[] = { -	{ -		.led = { -			.name            = "magician:red", -			.default_trigger = "ds2760-battery.0-charging", -		}, -		.hw_num = 0, -		.bit2   = PASIC3_BIT2_LED0, -		.mask   = PASIC3_MASK_LED0, -	}, -	{ -		.led = { -			.name            = "magician:green", -			.default_trigger = "ds2760-battery.0-charging-or-full", -		}, -		.hw_num = 1, -		.bit2   = PASIC3_BIT2_LED1, -		.mask   = PASIC3_MASK_LED1, -	}, -	{ -		.led = { -			.name            = "magician:blue", -			.default_trigger = "bluetooth", -		}, -		.hw_num = 2, -		.bit2   = PASIC3_BIT2_LED2, -		.mask   = PASIC3_MASK_LED2, -	}, -}; - -static struct pasic3_leds_machinfo pasic3_leds_info = { -	.num_leds   = ARRAY_SIZE(pasic3_leds), -	.power_gpio = EGPIO_MAGICIAN_LED_POWER, -	.leds       = pasic3_leds, -}; -  /*   * PASIC3 with DS1WM   */  static struct resource pasic3_resources[] = {  	[0] = { -		.start  = PXA_CS2_PHYS, +		.start	= PXA_CS2_PHYS,  		.end	= PXA_CS2_PHYS + 0x1b, -		.flags  = IORESOURCE_MEM, +		.flags	= IORESOURCE_MEM,  	},  	/* No IRQ handler in the PASIC3, DS1WM needs an external IRQ */  	[1] = { -		.start  = PXA_GPIO_TO_IRQ(GPIO107_MAGICIAN_DS1WM_IRQ), -		.end    = PXA_GPIO_TO_IRQ(GPIO107_MAGICIAN_DS1WM_IRQ), -		.flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE, +		.start	= PXA_GPIO_TO_IRQ(GPIO107_MAGICIAN_DS1WM_IRQ), +		.end	= PXA_GPIO_TO_IRQ(GPIO107_MAGICIAN_DS1WM_IRQ), +		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE,  	}  };  static struct pasic3_platform_data pasic3_platform_data = { -	.led_pdata  = &pasic3_leds_info,  	.clock_rate = 4000000,  }; @@ -493,25 +483,42 @@ static struct platform_device pasic3 = {  };  /* - * USB "Transceiver" + * PXA UDC + */ + +static void magician_udc_command(int cmd) +{ +	if (cmd == PXA2XX_UDC_CMD_CONNECT) +		UP2OCR |= UP2OCR_DPPUE | UP2OCR_DPPUBE; +	else if (cmd == PXA2XX_UDC_CMD_DISCONNECT) +		UP2OCR &= ~(UP2OCR_DPPUE | UP2OCR_DPPUBE); +} + +static struct pxa2xx_udc_mach_info magician_udc_info __initdata = { +	.udc_command	= magician_udc_command, +	.gpio_pullup	= GPIO27_MAGICIAN_USBC_PUEN, +}; + +/* + * USB device VBus detection   */  static struct resource gpio_vbus_resource = { -	.flags = IORESOURCE_IRQ, -	.start = IRQ_MAGICIAN_VBUS, -	.end   = IRQ_MAGICIAN_VBUS, +	.flags	= IORESOURCE_IRQ, +	.start	= IRQ_MAGICIAN_VBUS, +	.end	= IRQ_MAGICIAN_VBUS,  };  static struct gpio_vbus_mach_info gpio_vbus_info = { -	.gpio_pullup = GPIO27_MAGICIAN_USBC_PUEN, -	.gpio_vbus   = EGPIO_MAGICIAN_CABLE_STATE_USB, +	.gpio_pullup	= GPIO27_MAGICIAN_USBC_PUEN, +	.gpio_vbus	= EGPIO_MAGICIAN_CABLE_VBUS,  };  static struct platform_device gpio_vbus = { -	.name          = "gpio-vbus", -	.id            = -1, -	.num_resources = 1, -	.resource      = &gpio_vbus_resource, +	.name		= "gpio-vbus", +	.id		= -1, +	.num_resources	= 1, +	.resource	= &gpio_vbus_resource,  	.dev = {  		.platform_data = &gpio_vbus_info,  	}, @@ -521,19 +528,60 @@ static struct platform_device gpio_vbus = {   * External power   */ -static int power_supply_init(struct device *dev) +static int magician_supply_init(struct device *dev) +{ +	int ret = -1; + +	ret = gpio_request(EGPIO_MAGICIAN_CABLE_TYPE, "Cable is AC charger"); +	if (ret) { +		pr_err("Cannot request AC/USB charger GPIO (%i)\n", ret); +		goto err_ac; +	} + +	ret = gpio_request(EGPIO_MAGICIAN_CABLE_INSERTED, "Cable inserted"); +	if (ret) { +		pr_err("Cannot request cable detection GPIO (%i)\n", ret); +		goto err_usb; +	} + +	return 0; + +err_usb: +	gpio_free(EGPIO_MAGICIAN_CABLE_TYPE); +err_ac: +	return ret; +} + +static void magician_set_charge(int flags)  { -	return gpio_request(EGPIO_MAGICIAN_CABLE_STATE_AC, "CABLE_STATE_AC"); +	if (flags & PDA_POWER_CHARGE_AC) { +		pr_debug("Charging from AC\n"); +		gpio_set_value(EGPIO_MAGICIAN_NICD_CHARGE, 1); +	} else if (flags & PDA_POWER_CHARGE_USB) { +		pr_debug("Charging from USB\n"); +		gpio_set_value(EGPIO_MAGICIAN_NICD_CHARGE, 1); +	} else { +		pr_debug("Charging disabled\n"); +		gpio_set_value(EGPIO_MAGICIAN_NICD_CHARGE, 0); +	}  }  static int magician_is_ac_online(void)  { -	return gpio_get_value(EGPIO_MAGICIAN_CABLE_STATE_AC); +	return gpio_get_value(EGPIO_MAGICIAN_CABLE_INSERTED) && +		gpio_get_value(EGPIO_MAGICIAN_CABLE_TYPE); /* AC=1 */  } -static void power_supply_exit(struct device *dev) +static int magician_is_usb_online(void)  { -	gpio_free(EGPIO_MAGICIAN_CABLE_STATE_AC); +	return gpio_get_value(EGPIO_MAGICIAN_CABLE_INSERTED) && +		(!gpio_get_value(EGPIO_MAGICIAN_CABLE_TYPE)); /* USB=0 */ +} + +static void magician_supply_exit(struct device *dev) +{ +	gpio_free(EGPIO_MAGICIAN_CABLE_INSERTED); +	gpio_free(EGPIO_MAGICIAN_CABLE_TYPE);  }  static char *magician_supplicants[] = { @@ -541,38 +589,40 @@ static char *magician_supplicants[] = {  };  static struct pda_power_pdata power_supply_info = { -	.init            = power_supply_init, -	.is_ac_online    = magician_is_ac_online, -	.exit            = power_supply_exit, -	.supplied_to     = magician_supplicants, -	.num_supplicants = ARRAY_SIZE(magician_supplicants), +	.init			= magician_supply_init, +	.exit			= magician_supply_exit, +	.is_ac_online		= magician_is_ac_online, +	.is_usb_online		= magician_is_usb_online, +	.set_charge		= magician_set_charge, +	.supplied_to		= magician_supplicants, +	.num_supplicants	= ARRAY_SIZE(magician_supplicants),  };  static struct resource power_supply_resources[] = {  	[0] = { -		.name  = "ac", -		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | -		         IORESOURCE_IRQ_LOWEDGE, -		.start = IRQ_MAGICIAN_VBUS, -		.end   = IRQ_MAGICIAN_VBUS, +		.name	= "ac", +		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | +			IORESOURCE_IRQ_LOWEDGE, +		.start	= IRQ_MAGICIAN_VBUS, +		.end	= IRQ_MAGICIAN_VBUS,  	},  	[1] = { -		.name  = "usb", -		.flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | -		         IORESOURCE_IRQ_LOWEDGE, -		.start = IRQ_MAGICIAN_VBUS, -		.end   = IRQ_MAGICIAN_VBUS, +		.name	= "usb", +		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | +			IORESOURCE_IRQ_LOWEDGE, +		.start	= IRQ_MAGICIAN_VBUS, +		.end	= IRQ_MAGICIAN_VBUS,  	},  };  static struct platform_device power_supply = { -	.name = "pda-power", -	.id   = -1, -	.dev  = { +	.name	= "pda-power", +	.id	= -1, +	.dev = {  		.platform_data = &power_supply_info,  	}, -	.resource      = power_supply_resources, -	.num_resources = ARRAY_SIZE(power_supply_resources), +	.resource	= power_supply_resources, +	.num_resources	= ARRAY_SIZE(power_supply_resources),  };  /* @@ -586,11 +636,12 @@ static struct regulator_consumer_supply bq24022_consumers[] = {  static struct regulator_init_data bq24022_init_data = {  	.constraints = { -		.max_uA         = 500000, -		.valid_ops_mask = REGULATOR_CHANGE_CURRENT | REGULATOR_CHANGE_STATUS, +		.max_uA		= 500000, +		.valid_ops_mask	= REGULATOR_CHANGE_CURRENT | +			REGULATOR_CHANGE_STATUS,  	}, -	.num_consumer_supplies  = ARRAY_SIZE(bq24022_consumers), -	.consumer_supplies      = bq24022_consumers, +	.num_consumer_supplies	= ARRAY_SIZE(bq24022_consumers), +	.consumer_supplies	= bq24022_consumers,  };  static struct gpio bq24022_gpios[] = { @@ -603,39 +654,85 @@ static struct gpio_regulator_state bq24022_states[] = {  };  static struct gpio_regulator_config bq24022_info = { -	.supply_name = "bq24022", +	.supply_name		= "bq24022", -	.enable_gpio = GPIO30_MAGICIAN_BQ24022_nCHARGE_EN, -	.enable_high = 0, -	.enabled_at_boot = 0, +	.enable_gpio		= GPIO30_MAGICIAN_BQ24022_nCHARGE_EN, +	.enable_high		= 0, +	.enabled_at_boot	= 1, -	.gpios = bq24022_gpios, -	.nr_gpios = ARRAY_SIZE(bq24022_gpios), +	.gpios			= bq24022_gpios, +	.nr_gpios		= ARRAY_SIZE(bq24022_gpios), -	.states = bq24022_states, -	.nr_states = ARRAY_SIZE(bq24022_states), +	.states			= bq24022_states, +	.nr_states		= ARRAY_SIZE(bq24022_states), -	.type = REGULATOR_CURRENT, -	.init_data = &bq24022_init_data, +	.type			= REGULATOR_CURRENT, +	.init_data		= &bq24022_init_data,  };  static struct platform_device bq24022 = { -	.name = "gpio-regulator", -	.id   = -1, -	.dev  = { +	.name	= "gpio-regulator", +	.id	= -1, +	.dev	= {  		.platform_data = &bq24022_info,  	},  };  /* + * Vcore regulator MAX1587A + */ + +static struct regulator_consumer_supply magician_max1587a_consumers[] = { +	REGULATOR_SUPPLY("vcc_core", NULL), +}; + +static struct regulator_init_data magician_max1587a_v3_info = { +	.constraints = { +		.name		= "vcc_core range", +		.min_uV		= 700000, +		.max_uV		= 1475000, +		.always_on	= 1, +		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE, +	}, +	.consumer_supplies	= magician_max1587a_consumers, +	.num_consumer_supplies	= ARRAY_SIZE(magician_max1587a_consumers), +}; + +static struct max1586_subdev_data magician_max1587a_subdevs[] = { +	{ +		.name		= "vcc_core", +		.id		= MAX1586_V3, +		.platform_data	= &magician_max1587a_v3_info, +	} +}; + +static struct max1586_platform_data magician_max1587a_info = { +	.subdevs     = magician_max1587a_subdevs, +	.num_subdevs = ARRAY_SIZE(magician_max1587a_subdevs), +	/* +	 * NOTICE measured directly on the PCB (board_id == 0x3a), but +	 * if R24 is present, it will boost the voltage +	 * (write 1.475V, get 1.645V and smoke) +	 */ +	.v3_gain     = MAX1586_GAIN_NO_R24, +}; + +static struct i2c_board_info magician_pwr_i2c_board_info[] __initdata = { +	{ +		I2C_BOARD_INFO("max1586", 0x14), +		.platform_data	= &magician_max1587a_info, +	}, +}; + +/*   * MMC/SD   */  static int magician_mci_init(struct device *dev, -				irq_handler_t detect_irq, void *data) +	irq_handler_t detect_irq, void *data)  {  	return request_irq(IRQ_MAGICIAN_SD, detect_irq, 0, -			   "mmc card detect", data); +		"mmc card detect", data);  }  static void magician_mci_exit(struct device *dev, void *data) @@ -644,9 +741,9 @@ static void magician_mci_exit(struct device *dev, void *data)  }  static struct pxamci_platform_data magician_mci_info = { -	.ocr_mask 		= MMC_VDD_32_33|MMC_VDD_33_34, -	.init     		= magician_mci_init, -	.exit     		= magician_mci_exit, +	.ocr_mask		= MMC_VDD_32_33|MMC_VDD_33_34, +	.init			= magician_mci_init, +	.exit			= magician_mci_exit,  	.gpio_card_detect	= -1,  	.gpio_card_ro		= EGPIO_MAGICIAN_nSD_READONLY,  	.gpio_card_ro_invert	= 1, @@ -660,47 +757,102 @@ static struct pxamci_platform_data magician_mci_info = {  static struct pxaohci_platform_data magician_ohci_info = {  	.port_mode	= PMM_PERPORT_MODE, -	.flags		= ENABLE_PORT1 | ENABLE_PORT3 | POWER_CONTROL_LOW, +	/* port1: CSR Bluetooth, port2: OTG with UDC */ +	.flags		= ENABLE_PORT1 | ENABLE_PORT2 | POWER_CONTROL_LOW,  	.power_budget	= 0, +	.power_on_delay = 100,  }; -  /*   * StrataFlash   */ +static int magician_flash_init(struct platform_device *pdev) +{ +	int ret = gpio_request(EGPIO_MAGICIAN_FLASH_VPP, "flash Vpp enable"); + +	if (ret) { +		pr_err("Cannot request flash enable GPIO (%i)\n", ret); +		return ret; +	} + +	ret = gpio_direction_output(EGPIO_MAGICIAN_FLASH_VPP, 1); +	if (ret) { +		pr_err("Cannot set direction for flash enable (%i)\n", ret); +		gpio_free(EGPIO_MAGICIAN_FLASH_VPP); +	} + +	return ret; +} +  static void magician_set_vpp(struct platform_device *pdev, int vpp)  {  	gpio_set_value(EGPIO_MAGICIAN_FLASH_VPP, vpp);  } +static void magician_flash_exit(struct platform_device *pdev) +{ +	gpio_free(EGPIO_MAGICIAN_FLASH_VPP); +} +  static struct resource strataflash_resource = { -	.start = PXA_CS0_PHYS, -	.end   = PXA_CS0_PHYS + SZ_64M - 1, -	.flags = IORESOURCE_MEM, +	.start	= PXA_CS0_PHYS, +	.end	= PXA_CS0_PHYS + SZ_64M - 1, +	.flags	= IORESOURCE_MEM,  }; +static struct mtd_partition magician_flash_parts[] = { +	{ +		.name		= "Bootloader", +		.offset		= 0x0, +		.size		= 0x40000, +		.mask_flags	= MTD_WRITEABLE, /* EXPERIMENTAL */ +	}, +	{ +		.name		= "Linux Kernel", +		.offset		= 0x40000, +		.size		= MTDPART_SIZ_FULL, +	}, +}; + +/* + * physmap-flash driver + */ +  static struct physmap_flash_data strataflash_data = { -	.width = 4, -	.set_vpp = magician_set_vpp, +	.width		= 4, +	.init		= magician_flash_init, +	.set_vpp	= magician_set_vpp, +	.exit		= magician_flash_exit, +	.parts		= magician_flash_parts, +	.nr_parts	= ARRAY_SIZE(magician_flash_parts),  };  static struct platform_device strataflash = { -	.name          = "physmap-flash", -	.id            = -1, -	.resource      = &strataflash_resource, -	.num_resources = 1, +	.name		= "physmap-flash", +	.id		= -1, +	.resource	= &strataflash_resource, +	.num_resources	= 1,  	.dev = {  		.platform_data = &strataflash_data,  	},  };  /* - * I2C + * PXA I2C main controller   */  static struct i2c_pxa_platform_data i2c_info = { -	.fast_mode = 1, +	/* OV9640 I2C device doesn't support fast mode */ +	.fast_mode	= 0, +}; + +/* + * PXA I2C power controller + */ + +static struct i2c_pxa_platform_data magician_i2c_power_info = { +	.fast_mode	= 1,  };  /* @@ -720,12 +872,13 @@ static struct platform_device *devices[] __initdata = {  };  static struct gpio magician_global_gpios[] = { -	{ GPIO13_MAGICIAN_CPLD_IRQ,   GPIOF_IN, "CPLD_IRQ" }, +	{ GPIO13_MAGICIAN_CPLD_IRQ, GPIOF_IN, "CPLD_IRQ" },  	{ GPIO107_MAGICIAN_DS1WM_IRQ, GPIOF_IN, "DS1WM_IRQ" }, -	{ GPIO104_MAGICIAN_LCD_POWER_1, GPIOF_OUT_INIT_LOW, "LCD power 1" }, -	{ GPIO105_MAGICIAN_LCD_POWER_2, GPIOF_OUT_INIT_LOW, "LCD power 2" }, -	{ GPIO106_MAGICIAN_LCD_POWER_3, GPIOF_OUT_INIT_LOW, "LCD power 3" }, -	{ GPIO83_MAGICIAN_nIR_EN, GPIOF_OUT_INIT_HIGH, "nIR_EN" }, + +	/* NOTICE valid LCD init sequence */ +	{ GPIO106_MAGICIAN_LCD_DCDC_NRESET, GPIOF_OUT_INIT_LOW, "LCD DCDC nreset" }, +	{ GPIO104_MAGICIAN_LCD_VOFF_EN, GPIOF_OUT_INIT_LOW, "LCD VOFF enable" }, +	{ GPIO105_MAGICIAN_LCD_VON_EN, GPIOF_OUT_INIT_LOW, "LCD VON enable" },  };  static void __init magician_init(void) @@ -737,44 +890,55 @@ static void __init magician_init(void)  	pxa2xx_mfp_config(ARRAY_AND_SIZE(magician_pin_config));  	err = gpio_request_array(ARRAY_AND_SIZE(magician_global_gpios));  	if (err) -		pr_err("magician: Failed to request GPIOs: %d\n", err); +		pr_err("magician: Failed to request global GPIOs: %d\n", err);  	pxa_set_ffuart_info(NULL);  	pxa_set_btuart_info(NULL); -	pxa_set_stuart_info(NULL); -	platform_add_devices(ARRAY_AND_SIZE(devices)); +	pwm_add_table(magician_pwm_lookup, ARRAY_SIZE(magician_pwm_lookup));  	pxa_set_ficp_info(&magician_ficp_info); -	pxa27x_set_i2c_power_info(NULL); +	pxa27x_set_i2c_power_info(&magician_i2c_power_info);  	pxa_set_i2c_info(&i2c_info); + +	i2c_register_board_info(1, +		ARRAY_AND_SIZE(magician_pwr_i2c_board_info)); +  	pxa_set_mci_info(&magician_mci_info);  	pxa_set_ohci_info(&magician_ohci_info); +	pxa_set_udc_info(&magician_udc_info);  	/* Check LCD type we have */  	cpld = ioremap_nocache(PXA_CS3_PHYS, 0x1000);  	if (cpld) { -		u8 board_id = __raw_readb(cpld+0x14); +		u8 board_id = __raw_readb(cpld + 0x14); +  		iounmap(cpld);  		system_rev = board_id & 0x7;  		lcd_select = board_id & 0x8;  		pr_info("LCD type: %s\n", lcd_select ? "Samsung" : "Toppoly");  		if (lcd_select && (system_rev < 3)) +			/* NOTICE valid LCD init sequence */  			gpio_request_one(GPIO75_MAGICIAN_SAMSUNG_POWER, -			                 GPIOF_OUT_INIT_LOW, "SAMSUNG_POWER"); -		pxa_set_fb_info(NULL, lcd_select ? &samsung_info : &toppoly_info); +				GPIOF_OUT_INIT_LOW, "Samsung LCD Power"); +		pxa_set_fb_info(NULL, +			lcd_select ? &samsung_info : &toppoly_info);  	} else  		pr_err("LCD detection: CPLD mapping failed\n"); -} +	regulator_register_always_on(0, "power", pwm_backlight_supply, +		ARRAY_SIZE(pwm_backlight_supply), 5000000); + +	platform_add_devices(ARRAY_AND_SIZE(devices)); +}  MACHINE_START(MAGICIAN, "HTC Magician") -	.atag_offset = 0x100, -	.map_io = pxa27x_map_io, -	.nr_irqs = MAGICIAN_NR_IRQS, -	.init_irq = pxa27x_init_irq, -	.handle_irq = pxa27x_handle_irq, -	.init_machine = magician_init, +	.atag_offset	= 0x100, +	.map_io		= pxa27x_map_io, +	.nr_irqs	= MAGICIAN_NR_IRQS, +	.init_irq	= pxa27x_init_irq, +	.handle_irq	= pxa27x_handle_irq, +	.init_machine	= magician_init,  	.init_time	= pxa_timer_init,  	.restart	= pxa_restart,  MACHINE_END |