diff options
Diffstat (limited to 'target')
3 files changed, 187 insertions, 8 deletions
| diff --git a/target/linux/mx2/files/arch/arm/mach-mx2/mach-vp6500.c b/target/linux/mx2/files/arch/arm/mach-mx2/mach-vp6500.c index 4ca5c0fd9..fb4464eb8 100644 --- a/target/linux/mx2/files/arch/arm/mach-mx2/mach-vp6500.c +++ b/target/linux/mx2/files/arch/arm/mach-mx2/mach-vp6500.c @@ -20,9 +20,9 @@  #include <linux/input.h>  #include <linux/input/matrix_keypad.h>  #include <linux/gpio_keys.h> +#include <linux/pwm_backlight.h>  static unsigned int vp6500_pins[] = { -  	/* UART1 */  	PE12_PF_UART1_TXD,  	PE13_PF_UART1_RXD, @@ -52,8 +52,14 @@ static unsigned int vp6500_pins[] = {  	PA30_PF_CONTRAST,  	PA31_PF_OE_ACD,  #endif + +	/* LCD Backlight */ +	PE5_PF_PWMO, +	VP6500_GPIO_BACKLIGHT_EN | GPIO_GPIO | GPIO_OUT,  }; +/* Flash */ +  static struct physmap_flash_data vp6500_flash_data = {  	.width = 2,  }; @@ -74,6 +80,8 @@ static struct platform_device vp6500_nor_mtd_device = {  	.resource = &vp6500_flash_resource,  }; +/* LEDs */ +  static struct gpio_led vp6500_leds[] = {  	{  		.name = "vp6500:orange:keypad", @@ -108,6 +116,8 @@ static struct platform_device vp6500_leds_device = {  	},  }; +/* Keypad */ +  static const uint32_t vp6500_keypad_keys[] = {  	KEY(0, 3, KEY_F2),  	KEY(0, 4, KEY_RIGHT), @@ -180,11 +190,38 @@ static struct platform_device vp6500_key_device = {  	},  }; +/* LCD backlight */ + +static int vp6500_backlight_notify(struct device *dev, int brightness) +{ +	gpio_set_value(VP6500_GPIO_BACKLIGHT_EN, !!brightness); + +	return brightness; +} + +static struct platform_pwm_backlight_data vp6500_backlight_data = { +	.max_brightness = 255, +	.dft_brightness = 100, +	.pwm_period_ns = 15000000, +	.notify = vp6500_backlight_notify, +}; + +static struct platform_device vp6500_backlight_device = { +	.name = "pwm-backlight", +	.id = -1, +	.dev = { +		.parent = &mxc_pwm_device.dev, +		.platform_data = &vp6500_backlight_data, +	}, +}; + +  static struct platform_device *platform_devices[] __initdata = {  	&vp6500_nor_mtd_device,  	&vp6500_leds_device,  	&vp6500_keypad_device,  	&vp6500_key_device, +	&vp6500_backlight_device,  };  static void __init vp6500_board_init(void) @@ -193,6 +230,7 @@ static void __init vp6500_board_init(void)  			"vp6500");  	mxc_register_device(&mxc_uart_device0, NULL); +	mxc_register_device(&mxc_pwm_device, NULL);  	platform_add_devices(platform_devices, ARRAY_SIZE(platform_devices));  } diff --git a/target/linux/mx2/files/arch/arm/plat-mxc/include/mach/board-vp6500.h b/target/linux/mx2/files/arch/arm/plat-mxc/include/mach/board-vp6500.h index 700f9c101..c11d053a5 100644 --- a/target/linux/mx2/files/arch/arm/plat-mxc/include/mach/board-vp6500.h +++ b/target/linux/mx2/files/arch/arm/plat-mxc/include/mach/board-vp6500.h @@ -2,12 +2,16 @@  #ifndef __BOARD_VP6500__  #define __BOARD_VP6500__ -#define VP6500_GPIO_POWER_KEY		39 -#define VP6500_GPIO_CAMERA_DIRECTION	45 -#define VP6500_GPIO_LED_KEYPAD		82 -#define VP6500_GPIO_AMP_ENABLE		89 -#define VP6500_GPIO_LED_RED		91 -#define VP6500_GPIO_LED_GREEN		92 -#define VP6500_GPIO_LED_CAMERA		93 +#define VP6500_GPIO_POWER_KEY		GPIO_PORTB | 5 +#define VP6500_GPIO_CAMERA_DIRECTION	GPIO_PORTB | 13 +#define VP6500_GPIO_LED_KEYPAD		GPIO_PORTC | 18 +#define VP6500_GPIO_AMP_ENABLE		GPIO_PORTC | 25 +#define VP6500_GPIO_LED_RED		GPIO_PORTC | 27 +#define VP6500_GPIO_LED_GREEN		GPIO_PORTC | 28 +#define VP6500_GPIO_LED_CAMERA		GPIO_PORTC | 29 +#define VP6500_GPIO_BACKLIGHT_EN	GPIO_PORTE | 10 + +#define VP6500_GPIO_TLV_RESET		GPIO_PORTB | 27 +#define VP6500_GPIO_TLV_ENABLE		GPIO_PORTC | 25  #endif diff --git a/target/linux/mx2/patches-2.6.34/040-pwm.patch b/target/linux/mx2/patches-2.6.34/040-pwm.patch new file mode 100644 index 000000000..55e846ec1 --- /dev/null +++ b/target/linux/mx2/patches-2.6.34/040-pwm.patch @@ -0,0 +1,137 @@ +diff --git a/arch/arm/plat-mxc/pwm.c b/arch/arm/plat-mxc/pwm.c +index c36f263..acc5dc1 100644 +--- a/arch/arm/plat-mxc/pwm.c ++++ b/arch/arm/plat-mxc/pwm.c +@@ -25,6 +25,11 @@ + #define MX1_PWMS    0x04   /* PWM Sample Register */ + #define MX1_PWMP    0x08   /* PWM Period Register */ +  ++#define MX1_PWMC_EN (1 << 4) ++#define MX1_PWMC_PRESCALER_MASK (0x7f << 8) ++#define MX1_PWMC_PRESCALER(x) ((x & 0x7f) << 8) ++#define MX1_PWMC_CLKSEL_MASK 0x3 ++#define MX1_PWMC_CLKSEL(x) ((x & 0x3)) +  + /* i.MX27, i.MX31, i.MX35 share the same PWM function block: */ +  +@@ -54,25 +59,32 @@ struct pwm_device { +  + int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) + { ++	unsigned long long c; ++	unsigned long period_cycles, duty_cycles, prescale; ++ + 	if (pwm == NULL || period_ns == 0 || duty_ns > period_ns) + 		return -EINVAL; +  +-	if (cpu_is_mx27() || cpu_is_mx3() || cpu_is_mx25()) { +-		unsigned long long c; +-		unsigned long period_cycles, duty_cycles, prescale; +-		u32 cr; ++	c = clk_get_rate(pwm->clk); ++ ++	c = c * period_ns; ++ ++	if (cpu_is_mx1() || cpu_is_mx2()) ++		c >>= 1; +  +-		c = clk_get_rate(pwm->clk); +-		c = c * period_ns; +-		do_div(c, 1000000000); +-		period_cycles = c; ++	do_div(c, 1000000000); ++	period_cycles = c; +  +-		prescale = period_cycles / 0x10000 + 1; ++	prescale = period_cycles / 0x10000 + 1; +  +-		period_cycles /= prescale; +-		c = (unsigned long long)period_cycles * duty_ns; +-		do_div(c, period_ns); +-		duty_cycles = c; ++	period_cycles /= prescale; ++	c = (unsigned long long)period_cycles * duty_ns; ++	do_div(c, period_ns); ++	duty_cycles = c; ++ ++ ++	if (cpu_is_mx27() || cpu_is_mx3() || cpu_is_mx25()) { ++		u32 cr; +  + 		writel(duty_cycles, pwm->mmio_base + MX3_PWMSAR); + 		writel(period_cycles, pwm->mmio_base + MX3_PWMPR); +@@ -86,25 +98,28 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns) +  + 		writel(cr, pwm->mmio_base + MX3_PWMCR); + 	} else if (cpu_is_mx1() || cpu_is_mx21()) { +-		/* The PWM subsystem allows for exact frequencies. However, +-		 * I cannot connect a scope on my device to the PWM line and +-		 * thus cannot provide the program the PWM controller +-		 * exactly. Instead, I'm relying on the fact that the +-		 * Bootloader (u-boot or WinCE+haret) has programmed the PWM +-		 * function group already. So I'll just modify the PWM sample +-		 * register to follow the ratio of duty_ns vs. period_ns +-		 * accordingly. +-		 * +-		 * This is good enough for programming the brightness of +-		 * the LCD backlight. +-		 * +-		 * The real implementation would divide PERCLK[0] first by +-		 * both the prescaler (/1 .. /128) and then by CLKSEL +-		 * (/2 .. /16). +-		 */ +-		u32 max = readl(pwm->mmio_base + MX1_PWMP); +-		u32 p = max * duty_ns / period_ns; +-		writel(max - p, pwm->mmio_base + MX1_PWMS); ++		unsigned long clksel = 0; ++		u32 ctrl; ++ ++		while (prescale >= 0x80 && clksel < 4) { ++			prescale >>= 1; ++			++clksel; ++		} ++ ++		if (clksel > 3) ++			return -EINVAL; ++ ++		ctrl = readl(pwm->mmio_base + MX1_PWMC); ++		writel(ctrl & ~MX1_PWMC_EN, pwm->mmio_base + MX1_PWMC); ++ ++		writel(duty_cycles, pwm->mmio_base + MX1_PWMS); ++		writel(period_cycles, pwm->mmio_base + MX1_PWMP); ++ ++		ctrl &= ~(MX1_PWMC_PRESCALER_MASK | MX1_PWMC_CLKSEL_MASK); ++		ctrl |= MX1_PWMC_PRESCALER(prescale); ++		ctrl |= MX1_PWMC_CLKSEL(clksel); ++		writel(ctrl, pwm->mmio_base + MX1_PWMC); ++ + 	} else { + 		BUG(); + 	} +@@ -116,6 +130,11 @@ EXPORT_SYMBOL(pwm_config); + int pwm_enable(struct pwm_device *pwm) + { + 	int rc = 0; ++	if (cpu_is_mx1() || cpu_is_mx2()) { ++		u32 ctrl; ++		ctrl = readl(pwm->mmio_base + MX1_PWMC); ++		writel(ctrl | MX1_PWMC_EN, pwm->mmio_base + MX1_PWMC); ++	} +  + 	if (!pwm->clk_enabled) { + 		rc = clk_enable(pwm->clk); +@@ -128,7 +147,13 @@ EXPORT_SYMBOL(pwm_enable); +  + void pwm_disable(struct pwm_device *pwm) + { +-	writel(0, pwm->mmio_base + MX3_PWMCR); ++	if (cpu_is_mx27() || cpu_is_mx3() || cpu_is_mx25()) { ++		writel(0, pwm->mmio_base + MX3_PWMCR); ++	} else if (cpu_is_mx1() || cpu_is_mx2()) { ++		u32 ctrl; ++		ctrl = readl(pwm->mmio_base + MX1_PWMC); ++		writel(ctrl & ~MX1_PWMC_EN, pwm->mmio_base + MX1_PWMC); ++	} +  + 	if (pwm->clk_enabled) { + 		clk_disable(pwm->clk); | 
