1
0
mirror of https://git.yoctoproject.org/meta-ti synced 2026-07-16 22:38:04 +00:00

move kernel recipes in to the proper dir

Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
This commit is contained in:
Koen Kooi
2011-05-21 08:54:21 +02:00
parent 2ee953b627
commit 07e8c30da9
407 changed files with 0 additions and 1 deletions
@@ -0,0 +1,44 @@
From 3d2f0e2f29320d9c6a6e4d8d5aeff9127a2106cb Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@beagleboard.org>
Date: Tue, 11 Jan 2011 17:13:35 +0000
Subject: [PATCH 01/28] omap3: beaglexm: fix EHCI power up GPIO dir
EHCI enable power pin is inverted (active high) in comparison
to vanilla beagle which is active low. Handle this case conditionally.
Without this fix, Beagle XM 4 port EHCI will not function and no
networking will be available
[nm@ti.com: split up, added descriptive changelogs]
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Koen Kooi <koen@beagleboard.org>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
arch/arm/mach-omap2/board-omap3beagle.c | 10 ++++++++--
1 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 6c12760..af1166b 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -297,9 +297,15 @@ static int beagle_twl_gpio_setup(struct device *dev,
gpio_request(gpio + 1, "EHCI_nOC");
gpio_direction_input(gpio + 1);
- /* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, active low) */
+ /*
+ * TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
+ * high / others active low)
+ */
gpio_request(gpio + TWL4030_GPIO_MAX, "nEN_USB_PWR");
- gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
+ if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM)
+ gpio_direction_output(gpio + TWL4030_GPIO_MAX, 1);
+ else
+ gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
--
1.6.6.1
@@ -0,0 +1,48 @@
From e1dd1afba99853083da545f632a1f7c6899ae379 Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@beagleboard.org>
Date: Tue, 11 Jan 2011 17:13:36 +0000
Subject: [PATCH 02/28] omap3: beaglexm: fix DVI reset GPIO
GPIO reset line for Beagle XM is different from vanilla beagle
so we populate it as part of gpio update routine.
This in part fixes the issue of display not functioning on beagle XM
platform.
[nm@ti.com: split up, added descriptive changelogs]
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Koen Kooi <koen@beagleboard.org>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
arch/arm/mach-omap2/board-omap3beagle.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index af1166b..673deb9 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -199,7 +199,7 @@ static struct omap_dss_device beagle_dvi_device = {
.name = "dvi",
.driver_name = "generic_panel",
.phy.dpi.data_lines = 24,
- .reset_gpio = 170,
+ .reset_gpio = -EINVAL,
.platform_enable = beagle_enable_dvi,
.platform_disable = beagle_disable_dvi,
};
@@ -307,6 +307,12 @@ static int beagle_twl_gpio_setup(struct device *dev,
else
gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
+ /* DVI reset GPIO is different between beagle revisions */
+ if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM)
+ beagle_dvi_device.reset_gpio = 129;
+ else
+ beagle_dvi_device.reset_gpio = 170;
+
/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
--
1.6.6.1
@@ -0,0 +1,94 @@
From 4004c3e68b973f4cb736048b1e90ee3b511f5865 Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@beagleboard.org>
Date: Wed, 12 Jan 2011 00:23:29 +0000
Subject: [PATCH 03/28] omap3: beaglexm: fix power on of DVI
TFP410 DVI chip is used to provide display out.
This chip is controlled by 2 lines:
LDO which supplies the power is controlled over gpio + 2
and the enable of the chip itself is done over gpio + 1
NOTE: the LDO is necessary for LED, serial blocks as well.
gpio + 1 was used to sense USB overcurrent in vanilla beagle.
Without this fix, the display would not function as the LDO
remains shut down.
[nm@ti.com: split up, added descriptive changelogs]
Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Koen Kooi <koen@beagleboard.org>
Signed-off-by: Tony Lindgren <tony@atomide.com>
---
arch/arm/mach-omap2/board-omap3beagle.c | 42 ++++++++++++++++++++++++++++--
1 files changed, 39 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 673deb9..2ed8040 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -273,6 +273,8 @@ static struct gpio_led gpio_leds[];
static int beagle_twl_gpio_setup(struct device *dev,
unsigned gpio, unsigned ngpio)
{
+ int r;
+
if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
mmc[0].gpio_wp = -EINVAL;
} else if ((omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C1_3) ||
@@ -293,9 +295,16 @@ static int beagle_twl_gpio_setup(struct device *dev,
/* REVISIT: need ehci-omap hooks for external VBUS
* power switch and overcurrent detect
*/
-
- gpio_request(gpio + 1, "EHCI_nOC");
- gpio_direction_input(gpio + 1);
+ if (omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XM) {
+ r = gpio_request(gpio + 1, "EHCI_nOC");
+ if (!r) {
+ r = gpio_direction_input(gpio + 1);
+ if (r)
+ gpio_free(gpio + 1);
+ }
+ if (r)
+ pr_err("%s: unable to configure EHCI_nOC\n", __func__);
+ }
/*
* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
@@ -316,6 +325,33 @@ static int beagle_twl_gpio_setup(struct device *dev,
/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
+ /*
+ * gpio + 1 on Xm controls the TFP410's enable line (active low)
+ * gpio + 2 control varies depending on the board rev as follows:
+ * P7/P8 revisions(prototype): Camera EN
+ * A2+ revisions (production): LDO (supplies DVI, serial, led blocks)
+ */
+ if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
+ r = gpio_request(gpio + 1, "nDVI_PWR_EN");
+ if (!r) {
+ r = gpio_direction_output(gpio + 1, 0);
+ if (r)
+ gpio_free(gpio + 1);
+ }
+ if (r)
+ pr_err("%s: unable to configure nDVI_PWR_EN\n",
+ __func__);
+ r = gpio_request(gpio + 2, "DVI_LDO_EN");
+ if (!r) {
+ r = gpio_direction_output(gpio + 2, 1);
+ if (r)
+ gpio_free(gpio + 2);
+ }
+ if (r)
+ pr_err("%s: unable to configure DVI_LDO_EN\n",
+ __func__);
+ }
+
return 0;
}
--
1.6.6.1
@@ -0,0 +1,43 @@
From 24b7a742b27ed2c05c6bc7800b0299a77af37a82 Mon Sep 17 00:00:00 2001
From: Robert Nelson <robertcnelson@gmail.com>
Date: Tue, 9 Nov 2010 08:34:55 -0600
Subject: [PATCH 04/28] omap: Beagle: detect new xM revision B
The xM B uses a DM3730 ES1.1 over the ES1.0 on xM A's, no other board changes.
Signed-off-by: Robert Nelson <robertcnelson@gmail.com>
Signed-off-by: Koen Kooi <koen@beagleboard.org>
---
arch/arm/mach-omap2/board-omap3beagle.c | 9 +++++++--
1 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 2ed8040..f9fb64b 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -58,7 +58,8 @@
* AXBX = GPIO173, GPIO172, GPIO171: 1 1 1
* C1_3 = GPIO173, GPIO172, GPIO171: 1 1 0
* C4 = GPIO173, GPIO172, GPIO171: 1 0 1
- * XM = GPIO173, GPIO172, GPIO171: 0 0 0
+ * XMA = GPIO173, GPIO172, GPIO171: 0 0 0
+ * XMB = GPIO173, GPIO172, GPIO171: 0 0 1
*/
enum {
OMAP3BEAGLE_BOARD_UNKN = 0,
@@ -117,7 +118,11 @@ static void __init omap3_beagle_init_rev(void)
omap3_beagle_version = OMAP3BEAGLE_BOARD_C4;
break;
case 0:
- printk(KERN_INFO "OMAP3 Beagle Rev: xM\n");
+ printk(KERN_INFO "OMAP3 Beagle Rev: xM A\n");
+ omap3_beagle_version = OMAP3BEAGLE_BOARD_XM;
+ break;
+ case 1:
+ printk(KERN_INFO "OMAP3 Beagle Rev: xM B\n");
omap3_beagle_version = OMAP3BEAGLE_BOARD_XM;
break;
default:
--
1.6.6.1
@@ -0,0 +1,219 @@
From a564ca287c115928a9e7febf7c99bbab582290e6 Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@dominion.thruhere.net>
Date: Wed, 6 Oct 2010 10:19:34 +0200
Subject: [PATCH 05/28] ARM: OMAP: beagleboard: Add infrastructure to do fixups based on expansionboard name passed by u-boot
Add support for Tincantools Zippy and Zippy2 expansionboards as well
Signed-off-by: Koen Kooi <koen@beagleboard.org>
---
arch/arm/mach-omap2/board-omap3beagle.c | 142 ++++++++++++++++++++++++++++++-
1 files changed, 139 insertions(+), 3 deletions(-)
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index f9fb64b..d777b3b 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -21,6 +21,7 @@
#include <linux/io.h>
#include <linux/leds.h>
#include <linux/gpio.h>
+#include <linux/irq.h>
#include <linux/input.h>
#include <linux/gpio_keys.h>
@@ -143,6 +144,92 @@ fail0:
return;
}
+char expansionboard_name[16];
+
+#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
+
+#include <plat/mcspi.h>
+#include <linux/spi/spi.h>
+
+#define OMAP3BEAGLE_GPIO_ENC28J60_IRQ 157
+
+static struct omap2_mcspi_device_config enc28j60_spi_chip_info = {
+ .turbo_mode = 0,
+ .single_channel = 1, /* 0: slave, 1: master */
+};
+
+static struct spi_board_info omap3beagle_zippy_spi_board_info[] __initdata = {
+ {
+ .modalias = "enc28j60",
+ .bus_num = 4,
+ .chip_select = 0,
+ .max_speed_hz = 20000000,
+ .controller_data = &enc28j60_spi_chip_info,
+ },
+};
+
+static void __init omap3beagle_enc28j60_init(void)
+{
+ if ((gpio_request(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, "ENC28J60_IRQ") == 0) &&
+ (gpio_direction_input(OMAP3BEAGLE_GPIO_ENC28J60_IRQ) == 0)) {
+ gpio_export(OMAP3BEAGLE_GPIO_ENC28J60_IRQ, 0);
+ omap3beagle_zippy_spi_board_info[0].irq = OMAP_GPIO_IRQ(OMAP3BEAGLE_GPIO_ENC28J60_IRQ);
+ set_irq_type(omap3beagle_zippy_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
+ } else {
+ printk(KERN_ERR "could not obtain gpio for ENC28J60_IRQ\n");
+ return;
+ }
+
+ spi_register_board_info(omap3beagle_zippy_spi_board_info,
+ ARRAY_SIZE(omap3beagle_zippy_spi_board_info));
+}
+
+#else
+static inline void __init omap3beagle_enc28j60_init(void) { return; }
+#endif
+
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
+
+#include <plat/mcspi.h>
+#include <linux/spi/spi.h>
+
+#define OMAP3BEAGLE_GPIO_KS8851_IRQ 157
+
+static struct omap2_mcspi_device_config ks8851_spi_chip_info = {
+ .turbo_mode = 0,
+ .single_channel = 1, /* 0: slave, 1: master */
+};
+
+static struct spi_board_info omap3beagle_zippy2_spi_board_info[] __initdata = {
+ {
+ .modalias = "ks8851",
+ .bus_num = 4,
+ .chip_select = 0,
+ .max_speed_hz = 36000000,
+ .controller_data = &ks8851_spi_chip_info,
+ },
+};
+
+static void __init omap3beagle_ks8851_init(void)
+{
+ if ((gpio_request(OMAP3BEAGLE_GPIO_KS8851_IRQ, "KS8851_IRQ") == 0) &&
+ (gpio_direction_input(OMAP3BEAGLE_GPIO_KS8851_IRQ) == 0)) {
+ gpio_export(OMAP3BEAGLE_GPIO_KS8851_IRQ, 0);
+ omap3beagle_zippy2_spi_board_info[0].irq = OMAP_GPIO_IRQ(OMAP3BEAGLE_GPIO_KS8851_IRQ);
+ set_irq_type(omap3beagle_zippy2_spi_board_info[0].irq, IRQ_TYPE_EDGE_FALLING);
+ } else {
+ printk(KERN_ERR "could not obtain gpio for KS8851_IRQ\n");
+ return;
+ }
+
+ spi_register_board_info(omap3beagle_zippy2_spi_board_info,
+ ARRAY_SIZE(omap3beagle_zippy2_spi_board_info));
+}
+
+#else
+static inline void __init omap3beagle_ks8851_init(void) { return; }
+#endif
+
static struct mtd_partition omap3beagle_nand_partitions[] = {
/* All the partition sizes are listed in terms of NAND block size */
{
@@ -262,6 +349,12 @@ static struct omap2_hsmmc_info mmc[] = {
.caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
.gpio_wp = 29,
},
+ {
+ .mmc = 2,
+ .caps = MMC_CAP_4_BIT_DATA,
+ .transceiver = true,
+ .ocr_mask = 0x00100000, /* 3.3V */
+ },
{} /* Terminator */
};
@@ -457,7 +550,7 @@ static struct twl4030_platform_data beagle_twldata = {
.vpll2 = &beagle_vpll2,
};
-static struct i2c_board_info __initdata beagle_i2c_boardinfo[] = {
+static struct i2c_board_info __initdata beagle_i2c1_boardinfo[] = {
{
I2C_BOARD_INFO("twl4030", 0x48),
.flags = I2C_CLIENT_WAKE,
@@ -472,10 +565,24 @@ static struct i2c_board_info __initdata beagle_i2c_eeprom[] = {
},
};
+#if defined(CONFIG_RTC_DRV_DS1307) || \
+ defined(CONFIG_RTC_DRV_DS1307_MODULE)
+
+static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = {
+ {
+ I2C_BOARD_INFO("ds1307", 0x68),
+ },
+};
+#else
+static struct i2c_board_info __initdata beagle_i2c2_boardinfo[] = {};
+#endif
+
static int __init omap3_beagle_i2c_init(void)
{
- omap_register_i2c_bus(1, 2600, beagle_i2c_boardinfo,
- ARRAY_SIZE(beagle_i2c_boardinfo));
+ omap_register_i2c_bus(1, 2600, beagle_i2c1_boardinfo,
+ ARRAY_SIZE(beagle_i2c1_boardinfo));
+ omap_register_i2c_bus(2, 400, beagle_i2c2_boardinfo,
+ ARRAY_SIZE(beagle_i2c2_boardinfo));
/* Bus 3 is attached to the DVI port where devices like the pico DLP
* projector don't work reliably with 400kHz */
omap_register_i2c_bus(3, 100, beagle_i2c_eeprom, ARRAY_SIZE(beagle_i2c_eeprom));
@@ -609,6 +716,15 @@ static struct omap_musb_board_data musb_board_data = {
.power = 100,
};
+static int __init expansionboard_setup(char *str)
+{
+ if (!str)
+ return -EINVAL;
+ strncpy(expansionboard_name, str, 16);
+ printk(KERN_INFO "Beagle expansionboard: %s\n", expansionboard_name);
+ return 0;
+}
+
static void __init omap3_beagle_init(void)
{
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
@@ -623,6 +739,24 @@ static void __init omap3_beagle_init(void)
/* REVISIT leave DVI powered down until it's needed ... */
gpio_direction_output(170, true);
+ if(!strcmp(expansionboard_name, "zippy"))
+ {
+ printk(KERN_INFO "Beagle expansionboard: initializing enc28j60\n");
+ omap3beagle_enc28j60_init();
+ printk(KERN_INFO "Beagle expansionboard: assigning GPIO 141 and 162 to MMC1\n");
+ mmc[1].gpio_wp = 141;
+ mmc[1].gpio_cd = 162;
+ }
+
+ if(!strcmp(expansionboard_name, "zippy2"))
+ {
+ printk(KERN_INFO "Beagle expansionboard: initializing ks_8851\n");
+ omap3beagle_ks8851_init();
+ printk(KERN_INFO "Beagle expansionboard: assigning GPIO 141 and 162 to MMC1\n");
+ mmc[1].gpio_wp = 141;
+ mmc[1].gpio_cd = 162;
+ }
+
usb_musb_init(&musb_board_data);
usb_ehci_init(&ehci_pdata);
omap3beagle_flash_init();
@@ -634,6 +768,8 @@ static void __init omap3_beagle_init(void)
beagle_display_init();
}
+early_param("buddy", expansionboard_setup);
+
MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
/* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
.boot_params = 0x80000100,
--
1.6.6.1
@@ -0,0 +1,57 @@
From 0c2c9a4d7fd299444b66e08aa34acc868261003f Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@dominion.thruhere.net>
Date: Sun, 5 Dec 2010 13:25:00 +0100
Subject: [PATCH 06/28] ARM: OMAP: beagleboard: pre-export GPIOs to userspace when using a Tincantools trainerboard
This really needs a for loop, patches welcome
Signed-off-by: Koen Kooi <koen@beagleboard.org>
---
arch/arm/mach-omap2/board-omap3beagle.c | 31 +++++++++++++++++++++++++++++++
1 files changed, 31 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index d777b3b..64a181e 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -757,6 +757,37 @@ static void __init omap3_beagle_init(void)
mmc[1].gpio_cd = 162;
}
+ if(!strcmp(expansionboard_name, "trainer"))
+ {
+ printk(KERN_INFO "Beagle expansionboard: exporting GPIOs 130-141,162 to userspace\n");
+ gpio_request(130, "sysfs");
+ gpio_export(130, 1);
+ gpio_request(131, "sysfs");
+ gpio_export(131, 1);
+ gpio_request(132, "sysfs");
+ gpio_export(132, 1);
+ gpio_request(133, "sysfs");
+ gpio_export(133, 1);
+ gpio_request(134, "sysfs");
+ gpio_export(134, 1);
+ gpio_request(135, "sysfs");
+ gpio_export(135, 1);
+ gpio_request(136, "sysfs");
+ gpio_export(136, 1);
+ gpio_request(137, "sysfs");
+ gpio_export(137, 1);
+ gpio_request(138, "sysfs");
+ gpio_export(138, 1);
+ gpio_request(139, "sysfs");
+ gpio_export(139, 1);
+ gpio_request(140, "sysfs");
+ gpio_export(140, 1);
+ gpio_request(141, "sysfs");
+ gpio_export(141, 1);
+ gpio_request(162, "sysfs");
+ gpio_export(162, 1);
+ }
+
usb_musb_init(&musb_board_data);
usb_ehci_init(&ehci_pdata);
omap3beagle_flash_init();
--
1.6.6.1
@@ -0,0 +1,28 @@
From ed12d865de851c5aed3ae7685337551b831bb045 Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@dominion.thruhere.net>
Date: Mon, 8 Mar 2010 14:38:31 +0100
Subject: [PATCH 07/28] modedb.c: add proper 720p60 mode
Signed-off-by: Koen Kooi <koen@beagleboard.org>
---
drivers/video/modedb.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)
diff --git a/drivers/video/modedb.c b/drivers/video/modedb.c
index de450c1..1cd8153 100644
--- a/drivers/video/modedb.c
+++ b/drivers/video/modedb.c
@@ -46,6 +46,10 @@ static const struct fb_videomode modedb[] = {
NULL, 60, 640, 480, 39721, 40, 24, 32, 11, 96, 2,
0, FB_VMODE_NONINTERLACED
}, {
+ /* 1280x720 @ 60 Hz, 45 kHz hsync, CEA 681-E Format 4 */
+ "hd720", 60, 1280, 720, 13468, 220, 110, 20, 5, 40, 5,
+ 0, FB_VMODE_NONINTERLACED
+ }, {
/* 800x600 @ 56 Hz, 35.15 kHz hsync */
NULL, 56, 800, 600, 27777, 128, 24, 22, 1, 72, 2,
0, FB_VMODE_NONINTERLACED
--
1.6.6.1
@@ -0,0 +1,28 @@
From 13235700be3729d183143bdb75ee58742372d6aa Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Mon, 4 Jan 2010 19:20:25 -0800
Subject: [PATCH 08/28] mmc: don't display single block read console messages
mmc: don't display single block read console messages
---
drivers/mmc/card/block.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index 217f820..b0b68cc 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -434,8 +434,8 @@ static int mmc_blk_issue_rw_rq(struct mmc_queue *mq, struct request *req)
if (brq.cmd.error || brq.data.error || brq.stop.error) {
if (brq.data.blocks > 1 && rq_data_dir(req) == READ) {
/* Redo read one sector at a time */
- printk(KERN_WARNING "%s: retrying using single "
- "block read\n", req->rq_disk->disk_name);
+ /* printk(KERN_WARNING "%s: retrying using single "
+ "block read\n", req->rq_disk->disk_name); */
disable_multi = 1;
continue;
}
--
1.6.6.1
@@ -0,0 +1,63 @@
From 8b0c56b910811acd23c15bed273b3dbd959ef96a Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Mon, 26 Apr 2010 11:17:26 -0700
Subject: [PATCH 09/28] MTD: silence ecc errors on mtdblock0
mtdblock0 is the x-load partition, which uses hw ecc
this confuses linux, which uses sw ecc
this patch silences ecc error messages when linux peeks into mtdblock0
* not for upstream submission *
---
block/blk-core.c | 7 ++++---
drivers/mtd/nand/nand_ecc.c | 2 +-
fs/buffer.c | 3 ++-
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/block/blk-core.c b/block/blk-core.c
index 4ce953f..1ef9a01 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -2028,9 +2028,10 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
if (error && req->cmd_type == REQ_TYPE_FS &&
!(req->cmd_flags & REQ_QUIET)) {
- printk(KERN_ERR "end_request: I/O error, dev %s, sector %llu\n",
- req->rq_disk ? req->rq_disk->disk_name : "?",
- (unsigned long long)blk_rq_pos(req));
+ if (req->rq_disk && (strcmp(req->rq_disk->disk_name, "mtdblock0") != 0))
+ printk(KERN_ERR "end_request: I/O error, dev %s, sector %llu\n",
+ req->rq_disk ? req->rq_disk->disk_name : "?",
+ (unsigned long long)blk_rq_pos(req));
}
blk_account_io_completion(req, nr_bytes);
diff --git a/drivers/mtd/nand/nand_ecc.c b/drivers/mtd/nand/nand_ecc.c
index 271b8e7..5924ba7 100644
--- a/drivers/mtd/nand/nand_ecc.c
+++ b/drivers/mtd/nand/nand_ecc.c
@@ -507,7 +507,7 @@ int __nand_correct_data(unsigned char *buf,
if ((bitsperbyte[b0] + bitsperbyte[b1] + bitsperbyte[b2]) == 1)
return 1; /* error in ecc data; no action needed */
- printk(KERN_ERR "uncorrectable error : ");
+// printk(KERN_ERR "uncorrectable error : ");
return -1;
}
EXPORT_SYMBOL(__nand_correct_data);
diff --git a/fs/buffer.c b/fs/buffer.c
index 5930e38..06a00d5 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -114,7 +114,8 @@ static int quiet_error(struct buffer_head *bh)
static void buffer_io_error(struct buffer_head *bh)
{
char b[BDEVNAME_SIZE];
- printk(KERN_ERR "Buffer I/O error on device %s, logical block %Lu\n",
+ if (strcmp(bdevname(bh->b_bdev, b), "mtdblock0") != 0)
+ printk(KERN_ERR "Buffer I/O error on device %s, logical block %Lu\n",
bdevname(bh->b_bdev, b),
(unsigned long long)bh->b_blocknr);
}
--
1.6.6.1
@@ -0,0 +1,504 @@
From ce4f1f734efd638af01f1849ffffdc2746ad4a55 Mon Sep 17 00:00:00 2001
From: Mike Galbraith <efault@gmx.de>
Date: Fri, 19 Nov 2010 12:52:42 +0100
Subject: [PATCH 10/28] Miracle patch
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
On Sun, 2010-11-14 at 16:26 -0800, Linus Torvalds wrote:
> On Sun, Nov 14, 2010 at 4:15 PM, Linus Torvalds
> <torvalds@linux-foundation.org> wrote:
> >
> > THAT is why I think it's so silly to try to be so strict and walk over
> > all processes while holding a couple of spinlocks.
>
> Btw, let me say that I think the patch is great even with that thing
> in. It looks clean, the thing I'm complaining about is not a big deal,
> and it seems to perform very much as advertized. The difference with
> autogroup scheduling is very noticeable with a simple "make -j64"
> kernel compile.
>
> So I really don't think it's a big deal. The sysctl handler isn't even
> complicated. But boy does it hurt my eyes to see a spinlock held
> around a "do_each_thread()". And I do get the feeling that the
> simplest way to fix it would be to just remove the code entirely, and
> just say that "enabling/disabling may be delayed for old processes
> with existing autogroups".
Which is what I just did. If the oddball case isn't a big deal, the
patch shrinks, which is a good thing. I just wanted to cover all bases.
Patchlet with handler whacked:
A recurring complaint from CFS users is that parallel kbuild has a negative
impact on desktop interactivity. This patch implements an idea from Linus,
to automatically create task groups. This patch only implements Linus' per
tty task group suggestion, and only for fair class tasks, but leaves the way
open for enhancement.
Implementation: each task's signal struct contains an inherited pointer to a
refcounted autogroup struct containing a task group pointer, the default for
all tasks pointing to the init_task_group. When a task calls __proc_set_tty(),
the process wide reference to the default group is dropped, a new task group is
created, and the process is moved into the new task group. Children thereafter
inherit this task group, and increase it's refcount. On exit, a reference to the
current task group is dropped when the last reference to each signal struct is
dropped. The task group is destroyed when the last signal struct referencing
it is freed. At runqueue selection time, IFF a task has no cgroup assignment,
it's current autogroup is used.
The feature is enabled from boot by default if CONFIG_SCHED_AUTOGROUP is
selected, but can be disabled via the boot option noautogroup, and can be
also be turned on/off on the fly via..
echo [01] > /proc/sys/kernel/sched_autogroup_enabled.
..which will automatically move tasks to/from the root task group.
Some numbers.
A 100% hog overhead measurement proggy pinned to the same CPU as a make -j10
About measurement proggy:
pert/sec = perturbations/sec
min/max/avg = scheduler service latencies in usecs
sum/s = time accrued by the competition per sample period (1 sec here)
overhead = %CPU received by the competition per sample period
pert/s: 31 >40475.37us: 3 min: 0.37 max:48103.60 avg:29573.74 sum/s:916786us overhead:90.24%
pert/s: 23 >41237.70us: 12 min: 0.36 max:56010.39 avg:40187.01 sum/s:924301us overhead:91.99%
pert/s: 24 >42150.22us: 12 min: 8.86 max:61265.91 avg:39459.91 sum/s:947038us overhead:92.20%
pert/s: 26 >42344.91us: 11 min: 3.83 max:52029.60 avg:36164.70 sum/s:940282us overhead:91.12%
pert/s: 24 >44262.90us: 14 min: 5.05 max:82735.15 avg:40314.33 sum/s:967544us overhead:92.22%
Same load with this patch applied.
pert/s: 229 >5484.43us: 41 min: 0.15 max:12069.42 avg:2193.81 sum/s:502382us overhead:50.24%
pert/s: 222 >5652.28us: 43 min: 0.46 max:12077.31 avg:2248.56 sum/s:499181us overhead:49.92%
pert/s: 211 >5809.38us: 43 min: 0.16 max:12064.78 avg:2381.70 sum/s:502538us overhead:50.25%
pert/s: 223 >6147.92us: 43 min: 0.15 max:16107.46 avg:2282.17 sum/s:508925us overhead:50.49%
pert/s: 218 >6252.64us: 43 min: 0.16 max:12066.13 avg:2324.11 sum/s:506656us overhead:50.27%
Average service latency is an order of magnitude better with autogroup.
(Imagine that pert were Xorg or whatnot instead)
Using Mathieu Desnoyers' wakeup-latency testcase:
With taskset -c 3 make -j 10 running..
taskset -c 3 ./wakeup-latency& sleep 30;killall wakeup-latency
without:
maximum latency: 42963.2 µs
average latency: 9077.0 µs
missed timer events: 0
with:
maximum latency: 4160.7 µs
average latency: 149.4 µs
missed timer events: 0
Signed-off-by: Mike Galbraith <efault@gmx.de>
---
Documentation/kernel-parameters.txt | 2 +
drivers/tty/tty_io.c | 1 +
include/linux/sched.h | 19 +++++
init/Kconfig | 12 +++
kernel/fork.c | 5 +-
kernel/sched.c | 25 ++++--
kernel/sched_autogroup.c | 140 +++++++++++++++++++++++++++++++++++
kernel/sched_autogroup.h | 18 +++++
kernel/sysctl.c | 11 +++
9 files changed, 224 insertions(+), 9 deletions(-)
create mode 100644 kernel/sched_autogroup.c
create mode 100644 kernel/sched_autogroup.h
diff --git a/Documentation/kernel-parameters.txt b/Documentation/kernel-parameters.txt
index 01ece1b..1031923 100644
--- a/Documentation/kernel-parameters.txt
+++ b/Documentation/kernel-parameters.txt
@@ -1622,6 +1622,8 @@ and is between 256 and 4096 characters. It is defined in the file
noapic [SMP,APIC] Tells the kernel to not make use of any
IOAPICs that may be present in the system.
+ noautogroup Disable scheduler automatic task group creation.
+
nobats [PPC] Do not use BATs for mapping kernel lowmem
on "Classic" PPC cores.
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 35480dd..1849f4a 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3169,6 +3169,7 @@ static void __proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
put_pid(tsk->signal->tty_old_pgrp);
tsk->signal->tty = tty_kref_get(tty);
tsk->signal->tty_old_pgrp = NULL;
+ sched_autogroup_create_attach(tsk);
}
static void proc_set_tty(struct task_struct *tsk, struct tty_struct *tty)
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2238745..3a775e3 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -509,6 +509,8 @@ struct thread_group_cputimer {
spinlock_t lock;
};
+struct autogroup;
+
/*
* NOTE! "signal_struct" does not have it's own
* locking, because a shared signal_struct always
@@ -576,6 +578,9 @@ struct signal_struct {
struct tty_struct *tty; /* NULL if no tty */
+#ifdef CONFIG_SCHED_AUTOGROUP
+ struct autogroup *autogroup;
+#endif
/*
* Cumulative resource counters for dead threads in the group,
* and for reaped dead child processes forked by this group.
@@ -1931,6 +1936,20 @@ int sched_rt_handler(struct ctl_table *table, int write,
extern unsigned int sysctl_sched_compat_yield;
+#ifdef CONFIG_SCHED_AUTOGROUP
+extern unsigned int sysctl_sched_autogroup_enabled;
+
+extern void sched_autogroup_create_attach(struct task_struct *p);
+extern void sched_autogroup_detach(struct task_struct *p);
+extern void sched_autogroup_fork(struct signal_struct *sig);
+extern void sched_autogroup_exit(struct signal_struct *sig);
+#else
+static inline void sched_autogroup_create_attach(struct task_struct *p) { }
+static inline void sched_autogroup_detach(struct task_struct *p) { }
+static inline void sched_autogroup_fork(struct signal_struct *sig) { }
+static inline void sched_autogroup_exit(struct signal_struct *sig) { }
+#endif
+
#ifdef CONFIG_RT_MUTEXES
extern int rt_mutex_getprio(struct task_struct *p);
extern void rt_mutex_setprio(struct task_struct *p, int prio);
diff --git a/init/Kconfig b/init/Kconfig
index c972899..a4985d9 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -741,6 +741,18 @@ config NET_NS
endif # NAMESPACES
+config SCHED_AUTOGROUP
+ bool "Automatic process group scheduling"
+ select CGROUPS
+ select CGROUP_SCHED
+ select FAIR_GROUP_SCHED
+ help
+ This option optimizes the scheduler for common desktop workloads by
+ automatically creating and populating task groups. This separation
+ of workloads isolates aggressive CPU burners (like build jobs) from
+ desktop applications. Task group autogeneration is currently based
+ upon task tty association.
+
config MM_OWNER
bool
diff --git a/kernel/fork.c b/kernel/fork.c
index 5447dc7..70ea75f 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -174,8 +174,10 @@ static inline void free_signal_struct(struct signal_struct *sig)
static inline void put_signal_struct(struct signal_struct *sig)
{
- if (atomic_dec_and_test(&sig->sigcnt))
+ if (atomic_dec_and_test(&sig->sigcnt)) {
+ sched_autogroup_exit(sig);
free_signal_struct(sig);
+ }
}
void __put_task_struct(struct task_struct *tsk)
@@ -905,6 +907,7 @@ static int copy_signal(unsigned long clone_flags, struct task_struct *tsk)
posix_cpu_timers_init_group(sig);
tty_audit_fork(sig);
+ sched_autogroup_fork(sig);
sig->oom_adj = current->signal->oom_adj;
sig->oom_score_adj = current->signal->oom_score_adj;
diff --git a/kernel/sched.c b/kernel/sched.c
index 297d1a0..53ff9a1 100644
--- a/kernel/sched.c
+++ b/kernel/sched.c
@@ -78,6 +78,7 @@
#include "sched_cpupri.h"
#include "workqueue_sched.h"
+#include "sched_autogroup.h"
#define CREATE_TRACE_POINTS
#include <trace/events/sched.h>
@@ -605,11 +606,14 @@ static inline int cpu_of(struct rq *rq)
*/
static inline struct task_group *task_group(struct task_struct *p)
{
+ struct task_group *tg;
struct cgroup_subsys_state *css;
css = task_subsys_state_check(p, cpu_cgroup_subsys_id,
lockdep_is_held(&task_rq(p)->lock));
- return container_of(css, struct task_group, css);
+ tg = container_of(css, struct task_group, css);
+
+ return autogroup_task_group(p, tg);
}
/* Change a task's cfs_rq and parent entity if it moves across CPUs/groups */
@@ -2063,6 +2067,7 @@ static void update_rq_clock_task(struct rq *rq, s64 delta)
#include "sched_idletask.c"
#include "sched_fair.c"
#include "sched_rt.c"
+#include "sched_autogroup.c"
#include "sched_stoptask.c"
#ifdef CONFIG_SCHED_DEBUG
# include "sched_debug.c"
@@ -8164,7 +8169,7 @@ void __init sched_init(void)
#ifdef CONFIG_CGROUP_SCHED
list_add(&init_task_group.list, &task_groups);
INIT_LIST_HEAD(&init_task_group.children);
-
+ autogroup_init(&init_task);
#endif /* CONFIG_CGROUP_SCHED */
#if defined CONFIG_FAIR_GROUP_SCHED && defined CONFIG_SMP
@@ -8694,15 +8699,11 @@ void sched_destroy_group(struct task_group *tg)
/* change task's runqueue when it moves between groups.
* The caller of this function should have put the task in its new group
* by now. This function just updates tsk->se.cfs_rq and tsk->se.parent to
- * reflect its new group.
+ * reflect its new group. Called with the runqueue lock held.
*/
-void sched_move_task(struct task_struct *tsk)
+void __sched_move_task(struct task_struct *tsk, struct rq *rq)
{
int on_rq, running;
- unsigned long flags;
- struct rq *rq;
-
- rq = task_rq_lock(tsk, &flags);
running = task_current(rq, tsk);
on_rq = tsk->se.on_rq;
@@ -8723,7 +8724,15 @@ void sched_move_task(struct task_struct *tsk)
tsk->sched_class->set_curr_task(rq);
if (on_rq)
enqueue_task(rq, tsk, 0);
+}
+void sched_move_task(struct task_struct *tsk)
+{
+ struct rq *rq;
+ unsigned long flags;
+
+ rq = task_rq_lock(tsk, &flags);
+ __sched_move_task(tsk, rq);
task_rq_unlock(rq, &flags);
}
#endif /* CONFIG_CGROUP_SCHED */
diff --git a/kernel/sched_autogroup.c b/kernel/sched_autogroup.c
new file mode 100644
index 0000000..62f1d0e
--- /dev/null
+++ b/kernel/sched_autogroup.c
@@ -0,0 +1,140 @@
+#ifdef CONFIG_SCHED_AUTOGROUP
+
+unsigned int __read_mostly sysctl_sched_autogroup_enabled = 1;
+
+struct autogroup {
+ struct kref kref;
+ struct task_group *tg;
+};
+
+static struct autogroup autogroup_default;
+
+static void autogroup_init(struct task_struct *init_task)
+{
+ autogroup_default.tg = &init_task_group;
+ kref_init(&autogroup_default.kref);
+ init_task->signal->autogroup = &autogroup_default;
+}
+
+static inline void autogroup_destroy(struct kref *kref)
+{
+ struct autogroup *ag = container_of(kref, struct autogroup, kref);
+ struct task_group *tg = ag->tg;
+
+ kfree(ag);
+ sched_destroy_group(tg);
+}
+
+static inline void autogroup_kref_put(struct autogroup *ag)
+{
+ kref_put(&ag->kref, autogroup_destroy);
+}
+
+static inline struct autogroup *autogroup_kref_get(struct autogroup *ag)
+{
+ kref_get(&ag->kref);
+ return ag;
+}
+
+static inline struct autogroup *autogroup_create(void)
+{
+ struct autogroup *ag = kmalloc(sizeof(*ag), GFP_KERNEL);
+
+ if (!ag)
+ goto out_fail;
+
+ ag->tg = sched_create_group(&init_task_group);
+ kref_init(&ag->kref);
+
+ if (!(IS_ERR(ag->tg)))
+ return ag;
+
+out_fail:
+ if (ag) {
+ kfree(ag);
+ WARN_ON(1);
+ } else
+ WARN_ON(1);
+
+ return autogroup_kref_get(&autogroup_default);
+}
+
+static inline struct task_group *
+autogroup_task_group(struct task_struct *p, struct task_group *tg)
+{
+ int enabled = ACCESS_ONCE(sysctl_sched_autogroup_enabled);
+
+ enabled &= (tg == &root_task_group);
+ enabled &= (p->sched_class == &fair_sched_class);
+ enabled &= (!(p->flags & PF_EXITING));
+
+ if (enabled)
+ return p->signal->autogroup->tg;
+
+ return tg;
+}
+
+static void
+autogroup_move_group(struct task_struct *p, struct autogroup *ag)
+{
+ struct autogroup *prev;
+ struct task_struct *t;
+ struct rq *rq;
+ unsigned long flags;
+
+ rq = task_rq_lock(p, &flags);
+ prev = p->signal->autogroup;
+ if (prev == ag) {
+ task_rq_unlock(rq, &flags);
+ return;
+ }
+
+ p->signal->autogroup = autogroup_kref_get(ag);
+ __sched_move_task(p, rq);
+ task_rq_unlock(rq, &flags);
+
+ rcu_read_lock();
+ list_for_each_entry_rcu(t, &p->thread_group, thread_group) {
+ sched_move_task(t);
+ }
+ rcu_read_unlock();
+
+ autogroup_kref_put(prev);
+}
+
+void sched_autogroup_create_attach(struct task_struct *p)
+{
+ struct autogroup *ag = autogroup_create();
+
+ autogroup_move_group(p, ag);
+ /* drop extra refrence added by autogroup_create() */
+ autogroup_kref_put(ag);
+}
+EXPORT_SYMBOL(sched_autogroup_create_attach);
+
+/* currently has no users */
+void sched_autogroup_detach(struct task_struct *p)
+{
+ autogroup_move_group(p, &autogroup_default);
+}
+EXPORT_SYMBOL(sched_autogroup_detach);
+
+void sched_autogroup_fork(struct signal_struct *sig)
+{
+ sig->autogroup = autogroup_kref_get(current->signal->autogroup);
+}
+
+void sched_autogroup_exit(struct signal_struct *sig)
+{
+ autogroup_kref_put(sig->autogroup);
+}
+
+static int __init setup_autogroup(char *str)
+{
+ sysctl_sched_autogroup_enabled = 0;
+
+ return 1;
+}
+
+__setup("noautogroup", setup_autogroup);
+#endif
diff --git a/kernel/sched_autogroup.h b/kernel/sched_autogroup.h
new file mode 100644
index 0000000..6048f5d
--- /dev/null
+++ b/kernel/sched_autogroup.h
@@ -0,0 +1,18 @@
+#ifdef CONFIG_SCHED_AUTOGROUP
+
+static void __sched_move_task(struct task_struct *tsk, struct rq *rq);
+
+static inline struct task_group *
+autogroup_task_group(struct task_struct *p, struct task_group *tg);
+
+#else /* !CONFIG_SCHED_AUTOGROUP */
+
+static inline void autogroup_init(struct task_struct *init_task) { }
+
+static inline struct task_group *
+autogroup_task_group(struct task_struct *p, struct task_group *tg)
+{
+ return tg;
+}
+
+#endif /* CONFIG_SCHED_AUTOGROUP */
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index 5abfa15..b162f65 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -382,6 +382,17 @@ static struct ctl_table kern_table[] = {
.mode = 0644,
.proc_handler = proc_dointvec,
},
+#ifdef CONFIG_SCHED_AUTOGROUP
+ {
+ .procname = "sched_autogroup_enabled",
+ .data = &sysctl_sched_autogroup_enabled,
+ .maxlen = sizeof(unsigned int),
+ .mode = 0644,
+ .proc_handler = proc_dointvec,
+ .extra1 = &zero,
+ .extra2 = &one,
+ },
+#endif
#ifdef CONFIG_PROVE_LOCKING
{
.procname = "prove_locking",
--
1.6.6.1
@@ -0,0 +1,81 @@
From 8b34449d7eb89e1ae1c1c84f90ef5ea1e397787e Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@dominion.thruhere.net>
Date: Tue, 23 Nov 2010 11:40:20 +0100
Subject: [PATCH 11/28] ARM: OMAP: add omap_rev_* macros
This is just to make the SGX modules build that depend on omap_rev_lt_3_0
Signed-off-by: Koen Kooi <koen@beagleboard.org>
---
arch/arm/plat-omap/include/plat/cpu.h | 55 +++++++++++++++++++++++++++++++++
1 files changed, 55 insertions(+), 0 deletions(-)
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index 3fd8b40..1a8c347 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -394,6 +394,61 @@ IS_OMAP_TYPE(3517, 0x3517)
#define OMAP4430_REV_ES2_0 0x44301044
/*
+ * Silicon revisions
+ */
+#define OMAP_ES_1_0 0x00
+#define OMAP_ES_2_0 0x10
+#define OMAP_ES_2_1 0x20
+#define OMAP_ES_3_0 0x30
+#define OMAP_ES_3_1 0x40
+
+#define OMAP_REV_MASK 0x0000ff00
+#define OMAP_REV_BITS ((omap_rev() & OMAP_REV_MASK) >> 8)
+
+#define OMAP_REV_IS(revid) \
+static inline u8 omap_rev_is_ ##revid (void) \
+{ \
+ return (OMAP_REV_BITS == OMAP_ES_ ##revid) ? 1 : 0; \
+}
+
+#define OMAP_REV_LT(revid) \
+static inline u8 omap_rev_lt_ ##revid (void) \
+{ \
+ return (OMAP_REV_BITS < OMAP_ES_ ##revid) ? 1 : 0; \
+}
+
+#define OMAP_REV_LE(revid) \
+static inline u8 omap_rev_le_ ##revid (void) \
+{ \
+ return (OMAP_REV_BITS <= OMAP_ES_ ##revid) ? 1 : 0; \
+}
+
+#define OMAP_REV_GT(revid) \
+static inline u8 omap_rev_gt_ ##revid (void) \
+{ \
+ return (OMAP_REV_BITS > OMAP_ES_ ##revid) ? 1 : 0; \
+}
+
+#define OMAP_REV_GE(revid) \
+static inline u8 omap_rev_ge_ ##revid (void) \
+{ \
+ return (OMAP_REV_BITS >= OMAP_ES_ ##revid) ? 1 : 0; \
+}
+
+#define OMAP_REV_FUNCTIONS(revid) \
+ OMAP_REV_IS(revid) \
+ OMAP_REV_LT(revid) \
+ OMAP_REV_LE(revid) \
+ OMAP_REV_GT(revid) \
+ OMAP_REV_GE(revid)
+
+OMAP_REV_FUNCTIONS(1_0)
+OMAP_REV_FUNCTIONS(2_0)
+OMAP_REV_FUNCTIONS(2_1)
+OMAP_REV_FUNCTIONS(3_0)
+OMAP_REV_FUNCTIONS(3_1)
+
+/*
* omap_chip bits
*
* CHIP_IS_OMAP{2420,2430,3430} indicate that a particular structure is
--
1.6.6.1
@@ -0,0 +1,31 @@
From cd8a01e55dc674bba0030b99bff4f58d587aaecd Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Mon, 10 May 2010 20:44:09 -0700
Subject: [PATCH 12/28] OMAP: DSS2: enable hsclk in dsi_pll_init for OMAP36XX
Signed-off-by: Koen Kooi <koen@beagleboard.org>
---
drivers/video/omap2/dss/dpi.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)
diff --git a/drivers/video/omap2/dss/dpi.c b/drivers/video/omap2/dss/dpi.c
index 960e977..23047b6 100644
--- a/drivers/video/omap2/dss/dpi.c
+++ b/drivers/video/omap2/dss/dpi.c
@@ -177,7 +177,12 @@ int omapdss_dpi_display_enable(struct omap_dss_device *dssdev)
#ifdef CONFIG_OMAP2_DSS_USE_DSI_PLL
dss_clk_enable(DSS_CLK_FCK2);
- r = dsi_pll_init(dssdev, 0, 1);
+
+ if (cpu_is_omap3630())
+ r = dsi_pll_init(dssdev, 1, 1);
+ else
+ r = dsi_pll_init(dssdev, 0, 1);
+
if (r)
goto err3;
#endif
--
1.6.6.1
@@ -0,0 +1,128 @@
From f7d71be36165002251727019b1a03a19938bfa64 Mon Sep 17 00:00:00 2001
From: Koen Kooi <koen@beagleboard.org>
Date: Mon, 20 Dec 2010 11:57:56 +0100
Subject: [PATCH 13/28] omap3: beagleboard: add WIP support for beagleboardtoys WL12xx board
Based on a patch by Luciano Coelho <luciano.coelho@nokia.com>
Signed-off-by: Koen Kooi <koen@beagleboard.org>
---
arch/arm/mach-omap2/board-omap3beagle.c | 84 ++++++++++++++++++++++++++++++-
1 files changed, 83 insertions(+), 1 deletions(-)
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 64a181e..59b26da 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -146,6 +146,67 @@ fail0:
char expansionboard_name[16];
+#if defined(CONFIG_WL1271) || defined(CONFIG_WL1271_MODULE)
+#include <linux/regulator/fixed.h>
+#include <linux/wl12xx.h>
+
+#define OMAP_BEAGLE_WLAN_EN_GPIO (139)
+#define OMAP_BEAGLE_WLAN_IRQ_GPIO (137)
+
+struct wl12xx_platform_data omap_beagle_wlan_data __initdata = {
+ .irq = OMAP_GPIO_IRQ(OMAP_BEAGLE_WLAN_IRQ_GPIO),
+ .board_ref_clock = 2, /* 38.4 MHz */
+};
+
+ static struct omap2_hsmmc_info mmcbbt[] = {
+ {
+ .mmc = 1,
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+ .gpio_wp = 29,
+ },
+ {
+ .name = "wl1271",
+ .mmc = 2,
+ .caps = MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
+ .gpio_wp = -EINVAL,
+ .gpio_cd = -EINVAL,
+ .nonremovable = true,
+ },
+ {} /* Terminator */
+ };
+
+static struct regulator_consumer_supply beagle_vmmc2_supply = {
+ .supply = "vmmc",
+ .dev_name = "mmci-omap-hs.1",
+};
+
+static struct regulator_init_data beagle_vmmc2 = {
+ .constraints = {
+ .valid_ops_mask = REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &beagle_vmmc2_supply,
+};
+
+static struct fixed_voltage_config beagle_vwlan = {
+ .supply_name = "vwl1271",
+ .microvolts = 1800000, /* 1.8V */
+ .gpio = OMAP_BEAGLE_WLAN_EN_GPIO,
+ .startup_delay = 70000, /* 70ms */
+ .enable_high = 1,
+ .enabled_at_boot = 0,
+ .init_data = &beagle_vmmc2,
+};
+
+static struct platform_device omap_vwlan_device = {
+ .name = "reg-fixed-voltage",
+ .id = 1,
+ .dev = {
+ .platform_data = &beagle_vwlan,
+ },
+};
+#endif
+
#if defined(CONFIG_ENC28J60) || defined(CONFIG_ENC28J60_MODULE)
#include <plat/mcspi.h>
@@ -384,11 +445,24 @@ static int beagle_twl_gpio_setup(struct device *dev,
}
/* gpio + 0 is "mmc0_cd" (input/IRQ) */
mmc[0].gpio_cd = gpio + 0;
+#if defined(CONFIG_WL1271) || defined(CONFIG_WL1271_MODULE)
+ if(!strcmp(expansionboard_name, "bbtoys-wifi")) {
+ omap2_hsmmc_init(mmcbbt);
+ /* link regulators to MMC adapters */
+ beagle_vmmc1_supply.dev = mmcbbt[0].dev;
+ beagle_vsim_supply.dev = mmcbbt[0].dev;
+ } else {
+ omap2_hsmmc_init(mmc);
+ /* link regulators to MMC adapters */
+ beagle_vmmc1_supply.dev = mmc[0].dev;
+ beagle_vsim_supply.dev = mmc[0].dev;
+ }
+#else
omap2_hsmmc_init(mmc);
-
/* link regulators to MMC adapters */
beagle_vmmc1_supply.dev = mmc[0].dev;
beagle_vsim_supply.dev = mmc[0].dev;
+#endif
/* REVISIT: need ehci-omap hooks for external VBUS
* power switch and overcurrent detect
@@ -788,6 +862,14 @@ static void __init omap3_beagle_init(void)
gpio_export(162, 1);
}
+ if(!strcmp(expansionboard_name, "bbtoys-wifi"))
+ {
+ if (wl12xx_set_platform_data(&omap_beagle_wlan_data))
+ pr_err("error setting wl12xx data\n");
+ printk(KERN_INFO "Beagle expansionboard: registering wl12xx platform device\n");
+ platform_device_register(&omap_vwlan_device);
+ }
+
usb_musb_init(&musb_board_data);
usb_ehci_init(&ehci_pdata);
omap3beagle_flash_init();
--
1.6.6.1
@@ -0,0 +1,29 @@
From a47bbc5c9742e4ce250ee3bfba62732f3fea40b7 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <sakoman@gmail.com>
Date: Tue, 15 Dec 2009 15:17:44 -0800
Subject: [PATCH 14/28] drivers: net: smsc911x: return ENODEV if device is not found
Signed-off-by: Steve Sakoman <sakoman@gmail.com>
---
drivers/net/smsc911x.c | 4 +++-
1 files changed, 3 insertions(+), 1 deletions(-)
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index 64bfdae..ba2a00e 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -2019,8 +2019,10 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
}
retval = smsc911x_init(dev);
- if (retval < 0)
+ if (retval < 0) {
+ retval = -ENODEV;
goto out_unmap_io_3;
+ }
/* configure irq polarity and type before connecting isr */
if (pdata->config.irq_polarity == SMSC911X_IRQ_POLARITY_ACTIVE_HIGH)
--
1.6.6.1
@@ -0,0 +1,47 @@
From 713eb96dd137e1436198aa07094049ae0e0f9f1f Mon Sep 17 00:00:00 2001
From: Steve Sakoman <sakoman@gmail.com>
Date: Tue, 15 Dec 2009 15:24:10 -0800
Subject: [PATCH 15/28] drivers: input: touchscreen: ads7846: return ENODEV if device is not found
Signed-off-by: Steve Sakoman <sakoman@gmail.com>
---
drivers/input/touchscreen/ads7846.c | 13 ++++++++++---
1 files changed, 10 insertions(+), 3 deletions(-)
diff --git a/drivers/input/touchscreen/ads7846.c b/drivers/input/touchscreen/ads7846.c
index 14ea54b..c775e38 100644
--- a/drivers/input/touchscreen/ads7846.c
+++ b/drivers/input/touchscreen/ads7846.c
@@ -1325,11 +1325,18 @@ static int __devinit ads7846_probe(struct spi_device *spi)
* the touchscreen, in case it's not connected.
*/
if (ts->model == 7845)
- ads7845_read12_ser(&spi->dev, PWRDOWN);
+ err = ads7845_read12_ser(&spi->dev, PWRDOWN);
else
- (void) ads7846_read12_ser(&spi->dev,
+ err = ads7846_read12_ser(&spi->dev,
READ_12BIT_SER(vaux) | ADS_PD10_ALL_ON);
+ /* if sample is all 0's or all 1's then there is no device on spi */
+ if ( (err == 0x000) || (err == 0xfff)) {
+ dev_info(&spi->dev, "no device detected, test read result was 0x%08X\n", err);
+ err = -ENODEV;
+ goto err_free_irq;
+ }
+
err = sysfs_create_group(&spi->dev.kobj, &ads784x_attr_group);
if (err)
goto err_remove_hwmon;
@@ -1353,7 +1360,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
err_put_regulator:
regulator_put(ts->reg);
err_free_gpio:
- if (ts->gpio_pendown != -1)
+ if (!ts->get_pendown_state && ts->gpio_pendown != -1)
gpio_free(ts->gpio_pendown);
err_cleanup_filter:
if (ts->filter_cleanup)
--
1.6.6.1
@@ -0,0 +1,27 @@
From de63bf4fdf6c64e543c207792cb2d8ebcd089342 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Thu, 17 Dec 2009 12:45:20 -0800
Subject: [PATCH 16/28] ASoC: enable audio capture by default for twl4030
---
sound/soc/codecs/twl4030.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index cbebec6..430cd10 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -56,8 +56,8 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
0x00, /* REG_OPTION (0x2) */
0x00, /* REG_UNKNOWN (0x3) */
0x00, /* REG_MICBIAS_CTL (0x4) */
- 0x00, /* REG_ANAMICL (0x5) */
- 0x00, /* REG_ANAMICR (0x6) */
+ 0x34, /* REG_ANAMICL (0x5) */
+ 0x14, /* REG_ANAMICR (0x6) */
0x00, /* REG_AVADC_CTL (0x7) */
0x00, /* REG_ADCMICSEL (0x8) */
0x00, /* REG_DIGMIXING (0x9) */
--
1.6.6.1
@@ -0,0 +1,51 @@
From 18934b05f81025c1254d64c1774832e95187cbd9 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Sat, 23 Jan 2010 06:26:54 -0800
Subject: [PATCH 17/28] MFD: enable madc clock
---
drivers/mfd/twl-core.c | 8 ++++++++
include/linux/i2c/twl.h | 1 +
2 files changed, 9 insertions(+), 0 deletions(-)
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 35275ba..5aa7358 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -208,6 +208,11 @@
/* Few power values */
#define R_CFG_BOOT 0x05
+#define R_GPBR1 0x0C
+
+/* MADC clock values for R_GPBR1 */
+#define MADC_HFCLK_EN 0x80
+#define DEFAULT_MADC_CLK_EN 0x10
/* some fields in R_CFG_BOOT */
#define HFCLK_FREQ_19p2_MHZ (1 << 0)
@@ -929,6 +934,9 @@ static void clocks_init(struct device *dev,
e |= unprotect_pm_master();
/* effect->MADC+USB ck en */
+ if (twl_has_madc())
+ e |= twl_i2c_write_u8(TWL_MODULE_INTBR,
+ MADC_HFCLK_EN | DEFAULT_MADC_CLK_EN, R_GPBR1);
e |= twl_i2c_write_u8(TWL_MODULE_PM_MASTER, ctrl, R_CFG_BOOT);
e |= protect_pm_master();
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
index c760991..cfdfdd3 100644
--- a/include/linux/i2c/twl.h
+++ b/include/linux/i2c/twl.h
@@ -74,6 +74,7 @@
#define TWL_MODULE_USB TWL4030_MODULE_USB
#define TWL_MODULE_AUDIO_VOICE TWL4030_MODULE_AUDIO_VOICE
+#define TWL_MODULE_INTBR TWL4030_MODULE_INTBR
#define TWL_MODULE_PIH TWL4030_MODULE_PIH
#define TWL_MODULE_MADC TWL4030_MODULE_MADC
#define TWL_MODULE_MAIN_CHARGE TWL4030_MODULE_MAIN_CHARGE
--
1.6.6.1
@@ -0,0 +1,740 @@
From 562dc52ebe3df1e5d23416e78306db7c568dc427 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Thu, 17 Dec 2009 14:19:34 -0800
Subject: [PATCH 18/28] MFD: add twl4030 madc driver
---
drivers/mfd/Kconfig | 21 ++
drivers/mfd/Makefile | 1 +
drivers/mfd/twl4030-madc.c | 537 ++++++++++++++++++++++++++++++++++++++
include/linux/i2c/twl4030-madc.h | 130 +++++++++
4 files changed, 689 insertions(+), 0 deletions(-)
create mode 100644 drivers/mfd/twl4030-madc.c
create mode 100644 include/linux/i2c/twl4030-madc.h
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 3a1493b..26ca160 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -186,6 +186,27 @@ config TWL4030_CODEC
select MFD_CORE
default n
+config TWL4030_MADC
+ tristate "TWL4030 MADC Driver"
+ depends on TWL4030_CORE
+ help
+ The TWL4030 Monitoring ADC driver enables the host
+ processor to monitor analog signals using analog-to-digital
+ conversions on the input source. TWL4030 MADC provides the
+ following features:
+ - Single 10-bit ADC with successive approximation register (SAR) conversion;
+ - Analog multiplexer for 16 inputs;
+ - Seven (of the 16) inputs are freely available;
+ - Battery voltage monitoring;
+ - Concurrent conversion request management;
+ - Interrupt signal to Primary Interrupt Handler;
+ - Averaging feature;
+ - Selective enable/disable of the averaging feature.
+
+ Say 'y' here to statically link this module into the kernel or 'm'
+ to build it as a dinamically loadable module. The module will be
+ called twl4030-madc.ko
+
config TWL6030_PWM
tristate "TWL6030 PWM (Pulse Width Modulator) Support"
depends on TWL4030_CORE
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index f54b365..8c4ccb2 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -39,6 +39,7 @@ obj-$(CONFIG_MENELAUS) += menelaus.o
obj-$(CONFIG_TWL4030_CORE) += twl-core.o twl4030-irq.o twl6030-irq.o
obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o
obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o
+obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o
obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
diff --git a/drivers/mfd/twl4030-madc.c b/drivers/mfd/twl4030-madc.c
new file mode 100644
index 0000000..4adf880
--- /dev/null
+++ b/drivers/mfd/twl4030-madc.c
@@ -0,0 +1,537 @@
+/*
+ * TWL4030 MADC module driver
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Mikko Ylinen <mikko.k.ylinen@nokia.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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/fs.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/i2c/twl.h>
+#include <linux/i2c/twl4030-madc.h>
+
+#include <asm/uaccess.h>
+
+#define TWL4030_MADC_PFX "twl4030-madc: "
+
+struct twl4030_madc_data {
+ struct device *dev;
+ struct mutex lock;
+ struct work_struct ws;
+ struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
+ int imr;
+ int isr;
+};
+
+static struct twl4030_madc_data *the_madc;
+
+static
+const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = {
+ [TWL4030_MADC_RT] = {
+ .sel = TWL4030_MADC_RTSELECT_LSB,
+ .avg = TWL4030_MADC_RTAVERAGE_LSB,
+ .rbase = TWL4030_MADC_RTCH0_LSB,
+ },
+ [TWL4030_MADC_SW1] = {
+ .sel = TWL4030_MADC_SW1SELECT_LSB,
+ .avg = TWL4030_MADC_SW1AVERAGE_LSB,
+ .rbase = TWL4030_MADC_GPCH0_LSB,
+ .ctrl = TWL4030_MADC_CTRL_SW1,
+ },
+ [TWL4030_MADC_SW2] = {
+ .sel = TWL4030_MADC_SW2SELECT_LSB,
+ .avg = TWL4030_MADC_SW2AVERAGE_LSB,
+ .rbase = TWL4030_MADC_GPCH0_LSB,
+ .ctrl = TWL4030_MADC_CTRL_SW2,
+ },
+};
+
+static int twl4030_madc_read(struct twl4030_madc_data *madc, u8 reg)
+{
+ int ret;
+ u8 val;
+
+ ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, reg);
+ if (ret) {
+ dev_dbg(madc->dev, "unable to read register 0x%X\n", reg);
+ return ret;
+ }
+
+ return val;
+}
+
+static void twl4030_madc_write(struct twl4030_madc_data *madc, u8 reg, u8 val)
+{
+ int ret;
+
+ ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, reg);
+ if (ret)
+ dev_err(madc->dev, "unable to write register 0x%X\n", reg);
+}
+
+static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg)
+{
+ u8 msb, lsb;
+
+ /* For each ADC channel, we have MSB and LSB register pair. MSB address
+ * is always LSB address+1. reg parameter is the addr of LSB register */
+ msb = twl4030_madc_read(madc, reg + 1);
+ lsb = twl4030_madc_read(madc, reg);
+
+ return (int)(((msb << 8) | lsb) >> 6);
+}
+
+static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
+ u8 reg_base, u16 channels, int *buf)
+{
+ int count = 0;
+ u8 reg, i;
+
+ if (unlikely(!buf))
+ return 0;
+
+ for (i = 0; i < TWL4030_MADC_MAX_CHANNELS; i++) {
+ if (channels & (1<<i)) {
+ reg = reg_base + 2*i;
+ buf[i] = twl4030_madc_channel_raw_read(madc, reg);
+ count++;
+ }
+ }
+ return count;
+}
+
+static void twl4030_madc_enable_irq(struct twl4030_madc_data *madc, int id)
+{
+ u8 val;
+
+ val = twl4030_madc_read(madc, madc->imr);
+ val &= ~(1 << id);
+ twl4030_madc_write(madc, madc->imr, val);
+}
+
+static void twl4030_madc_disable_irq(struct twl4030_madc_data *madc, int id)
+{
+ u8 val;
+
+ val = twl4030_madc_read(madc, madc->imr);
+ val |= (1 << id);
+ twl4030_madc_write(madc, madc->imr, val);
+}
+
+static irqreturn_t twl4030_madc_irq_handler(int irq, void *_madc)
+{
+ struct twl4030_madc_data *madc = _madc;
+ u8 isr_val, imr_val;
+ int i;
+
+#ifdef CONFIG_LOCKDEP
+ /* WORKAROUND for lockdep forcing IRQF_DISABLED on us, which
+ * we don't want and can't tolerate. Although it might be
+ * friendlier not to borrow this thread context...
+ */
+ local_irq_enable();
+#endif
+
+ /* Use COR to ack interrupts since we have no shared IRQs in ISRx */
+ isr_val = twl4030_madc_read(madc, madc->isr);
+ imr_val = twl4030_madc_read(madc, madc->imr);
+
+ isr_val &= ~imr_val;
+
+ for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
+
+ if (!(isr_val & (1<<i)))
+ continue;
+
+ twl4030_madc_disable_irq(madc, i);
+ madc->requests[i].result_pending = 1;
+ }
+
+ schedule_work(&madc->ws);
+
+ return IRQ_HANDLED;
+}
+
+static void twl4030_madc_work(struct work_struct *ws)
+{
+ const struct twl4030_madc_conversion_method *method;
+ struct twl4030_madc_data *madc;
+ struct twl4030_madc_request *r;
+ int len, i;
+
+ madc = container_of(ws, struct twl4030_madc_data, ws);
+ mutex_lock(&madc->lock);
+
+ for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
+
+ r = &madc->requests[i];
+
+ /* No pending results for this method, move to next one */
+ if (!r->result_pending)
+ continue;
+
+ method = &twl4030_conversion_methods[r->method];
+
+ /* Read results */
+ len = twl4030_madc_read_channels(madc, method->rbase,
+ r->channels, r->rbuf);
+
+ /* Return results to caller */
+ if (r->func_cb != NULL) {
+ r->func_cb(len, r->channels, r->rbuf);
+ r->func_cb = NULL;
+ }
+
+ /* Free request */
+ r->result_pending = 0;
+ r->active = 0;
+ }
+
+ mutex_unlock(&madc->lock);
+}
+
+static int twl4030_madc_set_irq(struct twl4030_madc_data *madc,
+ struct twl4030_madc_request *req)
+{
+ struct twl4030_madc_request *p;
+
+ p = &madc->requests[req->method];
+
+ memcpy(p, req, sizeof *req);
+
+ twl4030_madc_enable_irq(madc, req->method);
+
+ return 0;
+}
+
+static inline void twl4030_madc_start_conversion(struct twl4030_madc_data *madc,
+ int conv_method)
+{
+ const struct twl4030_madc_conversion_method *method;
+
+ method = &twl4030_conversion_methods[conv_method];
+
+ switch (conv_method) {
+ case TWL4030_MADC_SW1:
+ case TWL4030_MADC_SW2:
+ twl4030_madc_write(madc, method->ctrl, TWL4030_MADC_SW_START);
+ break;
+ case TWL4030_MADC_RT:
+ default:
+ break;
+ }
+}
+
+static int twl4030_madc_wait_conversion_ready(
+ struct twl4030_madc_data *madc,
+ unsigned int timeout_ms, u8 status_reg)
+{
+ unsigned long timeout;
+
+ timeout = jiffies + msecs_to_jiffies(timeout_ms);
+ do {
+ u8 reg;
+
+ reg = twl4030_madc_read(madc, status_reg);
+ if (!(reg & TWL4030_MADC_BUSY) && (reg & TWL4030_MADC_EOC_SW))
+ return 0;
+ } while (!time_after(jiffies, timeout));
+
+ return -EAGAIN;
+}
+
+int twl4030_madc_conversion(struct twl4030_madc_request *req)
+{
+ const struct twl4030_madc_conversion_method *method;
+ u8 ch_msb, ch_lsb;
+ int ret;
+
+ if (unlikely(!req))
+ return -EINVAL;
+
+ mutex_lock(&the_madc->lock);
+
+ /* Do we have a conversion request ongoing */
+ if (the_madc->requests[req->method].active) {
+ ret = -EBUSY;
+ goto out;
+ }
+
+ ch_msb = (req->channels >> 8) & 0xff;
+ ch_lsb = req->channels & 0xff;
+
+ method = &twl4030_conversion_methods[req->method];
+
+ /* Select channels to be converted */
+ twl4030_madc_write(the_madc, method->sel + 1, ch_msb);
+ twl4030_madc_write(the_madc, method->sel, ch_lsb);
+
+ /* Select averaging for all channels if do_avg is set */
+ if (req->do_avg) {
+ twl4030_madc_write(the_madc, method->avg + 1, ch_msb);
+ twl4030_madc_write(the_madc, method->avg, ch_lsb);
+ }
+
+ if ((req->type == TWL4030_MADC_IRQ_ONESHOT) && (req->func_cb != NULL)) {
+ twl4030_madc_set_irq(the_madc, req);
+ twl4030_madc_start_conversion(the_madc, req->method);
+ the_madc->requests[req->method].active = 1;
+ ret = 0;
+ goto out;
+ }
+
+ /* With RT method we should not be here anymore */
+ if (req->method == TWL4030_MADC_RT) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ twl4030_madc_start_conversion(the_madc, req->method);
+ the_madc->requests[req->method].active = 1;
+
+ /* Wait until conversion is ready (ctrl register returns EOC) */
+ ret = twl4030_madc_wait_conversion_ready(the_madc, 5, method->ctrl);
+ if (ret) {
+ dev_dbg(the_madc->dev, "conversion timeout!\n");
+ the_madc->requests[req->method].active = 0;
+ goto out;
+ }
+
+ ret = twl4030_madc_read_channels(the_madc, method->rbase, req->channels,
+ req->rbuf);
+
+ the_madc->requests[req->method].active = 0;
+
+out:
+ mutex_unlock(&the_madc->lock);
+
+ return ret;
+}
+EXPORT_SYMBOL(twl4030_madc_conversion);
+
+static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
+ int chan, int on)
+{
+ int ret;
+ u8 regval;
+
+ /* Current generator is only available for ADCIN0 and ADCIN1. NB:
+ * ADCIN1 current generator only works when AC or VBUS is present */
+ if (chan > 1)
+ return EINVAL;
+
+ ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
+ &regval, TWL4030_BCI_BCICTL1);
+ if (on)
+ regval |= (chan) ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
+ else
+ regval &= (chan) ? ~TWL4030_BCI_ITHEN : ~TWL4030_BCI_TYPEN;
+ ret = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
+ regval, TWL4030_BCI_BCICTL1);
+
+ return ret;
+}
+
+static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
+{
+ u8 regval;
+
+ regval = twl4030_madc_read(madc, TWL4030_MADC_CTRL1);
+ if (on)
+ regval |= TWL4030_MADC_MADCON;
+ else
+ regval &= ~TWL4030_MADC_MADCON;
+ twl4030_madc_write(madc, TWL4030_MADC_CTRL1, regval);
+
+ return 0;
+}
+
+static long twl4030_madc_ioctl(struct file *filp, unsigned int cmd,
+ unsigned long arg)
+{
+ struct twl4030_madc_user_parms par;
+ int val, ret;
+
+ ret = copy_from_user(&par, (void __user *) arg, sizeof(par));
+ if (ret) {
+ dev_dbg(the_madc->dev, "copy_from_user: %d\n", ret);
+ return -EACCES;
+ }
+
+ switch (cmd) {
+ case TWL4030_MADC_IOCX_ADC_RAW_READ: {
+ struct twl4030_madc_request req;
+ if (par.channel >= TWL4030_MADC_MAX_CHANNELS)
+ return -EINVAL;
+
+ req.channels = (1 << par.channel);
+ req.do_avg = par.average;
+ req.method = TWL4030_MADC_SW1;
+ req.func_cb = NULL;
+
+ val = twl4030_madc_conversion(&req);
+ if (val <= 0) {
+ par.status = -1;
+ } else {
+ par.status = 0;
+ par.result = (u16)req.rbuf[par.channel];
+ }
+ break;
+ }
+ default:
+ return -EINVAL;
+ }
+
+ ret = copy_to_user((void __user *) arg, &par, sizeof(par));
+ if (ret) {
+ dev_dbg(the_madc->dev, "copy_to_user: %d\n", ret);
+ return -EACCES;
+ }
+
+ return 0;
+}
+
+static struct file_operations twl4030_madc_fileops = {
+ .owner = THIS_MODULE,
+ .unlocked_ioctl = twl4030_madc_ioctl
+};
+
+static struct miscdevice twl4030_madc_device = {
+ .minor = MISC_DYNAMIC_MINOR,
+ .name = "twl4030-madc",
+ .fops = &twl4030_madc_fileops
+};
+
+static int __init twl4030_madc_probe(struct platform_device *pdev)
+{
+ struct twl4030_madc_data *madc;
+ struct twl4030_madc_platform_data *pdata = pdev->dev.platform_data;
+ int ret;
+ u8 regval;
+
+ madc = kzalloc(sizeof *madc, GFP_KERNEL);
+ if (!madc)
+ return -ENOMEM;
+
+ if (!pdata) {
+ dev_dbg(&pdev->dev, "platform_data not available\n");
+ ret = -EINVAL;
+ goto err_pdata;
+ }
+
+ madc->imr = (pdata->irq_line == 1) ? TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2;
+ madc->isr = (pdata->irq_line == 1) ? TWL4030_MADC_ISR1 : TWL4030_MADC_ISR2;
+
+ ret = misc_register(&twl4030_madc_device);
+ if (ret) {
+ dev_dbg(&pdev->dev, "could not register misc_device\n");
+ goto err_misc;
+ }
+ twl4030_madc_set_power(madc, 1);
+ twl4030_madc_set_current_generator(madc, 0, 1);
+
+ /* Enable ADCIN3 through 6 */
+ ret = twl_i2c_read_u8(TWL4030_MODULE_USB,
+ &regval, TWL4030_USB_CARKIT_ANA_CTRL);
+
+ regval |= TWL4030_USB_SEL_MADC_MCPC;
+
+ ret = twl_i2c_write_u8(TWL4030_MODULE_USB,
+ regval, TWL4030_USB_CARKIT_ANA_CTRL);
+
+
+ ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
+ &regval, TWL4030_BCI_BCICTL1);
+
+ regval |= TWL4030_BCI_MESBAT;
+
+ ret = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
+ regval, TWL4030_BCI_BCICTL1);
+
+ ret = request_irq(platform_get_irq(pdev, 0), twl4030_madc_irq_handler,
+ 0, "twl4030_madc", madc);
+ if (ret) {
+ dev_dbg(&pdev->dev, "could not request irq\n");
+ goto err_irq;
+ }
+
+ platform_set_drvdata(pdev, madc);
+ mutex_init(&madc->lock);
+ INIT_WORK(&madc->ws, twl4030_madc_work);
+
+ the_madc = madc;
+
+ return 0;
+
+err_irq:
+ misc_deregister(&twl4030_madc_device);
+
+err_misc:
+err_pdata:
+ kfree(madc);
+
+ return ret;
+}
+
+static int __exit twl4030_madc_remove(struct platform_device *pdev)
+{
+ struct twl4030_madc_data *madc = platform_get_drvdata(pdev);
+
+ twl4030_madc_set_power(madc, 0);
+ twl4030_madc_set_current_generator(madc, 0, 0);
+ free_irq(platform_get_irq(pdev, 0), madc);
+ cancel_work_sync(&madc->ws);
+ misc_deregister(&twl4030_madc_device);
+
+ return 0;
+}
+
+static struct platform_driver twl4030_madc_driver = {
+ .probe = twl4030_madc_probe,
+ .remove = __exit_p(twl4030_madc_remove),
+ .driver = {
+ .name = "twl4030_madc",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init twl4030_madc_init(void)
+{
+ return platform_driver_register(&twl4030_madc_driver);
+}
+module_init(twl4030_madc_init);
+
+static void __exit twl4030_madc_exit(void)
+{
+ platform_driver_unregister(&twl4030_madc_driver);
+}
+module_exit(twl4030_madc_exit);
+
+MODULE_ALIAS("platform:twl4030-madc");
+MODULE_AUTHOR("Nokia Corporation");
+MODULE_DESCRIPTION("twl4030 ADC driver");
+MODULE_LICENSE("GPL");
+
diff --git a/include/linux/i2c/twl4030-madc.h b/include/linux/i2c/twl4030-madc.h
new file mode 100644
index 0000000..341a665
--- /dev/null
+++ b/include/linux/i2c/twl4030-madc.h
@@ -0,0 +1,130 @@
+/*
+ * include/linux/i2c/twl4030-madc.h
+ *
+ * TWL4030 MADC module driver header
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Mikko Ylinen <mikko.k.ylinen@nokia.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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef _TWL4030_MADC_H
+#define _TWL4030_MADC_H
+
+struct twl4030_madc_conversion_method {
+ u8 sel;
+ u8 avg;
+ u8 rbase;
+ u8 ctrl;
+};
+
+#define TWL4030_MADC_MAX_CHANNELS 16
+
+struct twl4030_madc_request {
+ u16 channels;
+ u16 do_avg;
+ u16 method;
+ u16 type;
+ int active;
+ int result_pending;
+ int rbuf[TWL4030_MADC_MAX_CHANNELS];
+ void (*func_cb)(int len, int channels, int *buf);
+};
+
+enum conversion_methods {
+ TWL4030_MADC_RT,
+ TWL4030_MADC_SW1,
+ TWL4030_MADC_SW2,
+ TWL4030_MADC_NUM_METHODS
+};
+
+enum sample_type {
+ TWL4030_MADC_WAIT,
+ TWL4030_MADC_IRQ_ONESHOT,
+ TWL4030_MADC_IRQ_REARM
+};
+
+#define TWL4030_MADC_CTRL1 0x00
+#define TWL4030_MADC_CTRL2 0x01
+
+#define TWL4030_MADC_RTSELECT_LSB 0x02
+#define TWL4030_MADC_SW1SELECT_LSB 0x06
+#define TWL4030_MADC_SW2SELECT_LSB 0x0A
+
+#define TWL4030_MADC_RTAVERAGE_LSB 0x04
+#define TWL4030_MADC_SW1AVERAGE_LSB 0x08
+#define TWL4030_MADC_SW2AVERAGE_LSB 0x0C
+
+#define TWL4030_MADC_CTRL_SW1 0x12
+#define TWL4030_MADC_CTRL_SW2 0x13
+
+#define TWL4030_MADC_RTCH0_LSB 0x17
+#define TWL4030_MADC_GPCH0_LSB 0x37
+
+#define TWL4030_MADC_MADCON (1<<0) /* MADC power on */
+#define TWL4030_MADC_BUSY (1<<0) /* MADC busy */
+#define TWL4030_MADC_EOC_SW (1<<1) /* MADC conversion completion */
+#define TWL4030_MADC_SW_START (1<<5) /* MADC SWx start conversion */
+
+#define TWL4030_MADC_ADCIN0 (1<<0)
+#define TWL4030_MADC_ADCIN1 (1<<1)
+#define TWL4030_MADC_ADCIN2 (1<<2)
+#define TWL4030_MADC_ADCIN3 (1<<3)
+#define TWL4030_MADC_ADCIN4 (1<<4)
+#define TWL4030_MADC_ADCIN5 (1<<5)
+#define TWL4030_MADC_ADCIN6 (1<<6)
+#define TWL4030_MADC_ADCIN7 (1<<7)
+#define TWL4030_MADC_ADCIN8 (1<<8)
+#define TWL4030_MADC_ADCIN9 (1<<9)
+#define TWL4030_MADC_ADCIN10 (1<<10)
+#define TWL4030_MADC_ADCIN11 (1<<11)
+#define TWL4030_MADC_ADCIN12 (1<<12)
+#define TWL4030_MADC_ADCIN13 (1<<13)
+#define TWL4030_MADC_ADCIN14 (1<<14)
+#define TWL4030_MADC_ADCIN15 (1<<15)
+
+/* Fixed channels */
+#define TWL4030_MADC_BTEMP TWL4030_MADC_ADCIN1
+#define TWL4030_MADC_VBUS TWL4030_MADC_ADCIN8
+#define TWL4030_MADC_VBKB TWL4030_MADC_ADCIN9
+#define TWL4030_MADC_ICHG TWL4030_MADC_ADCIN10
+#define TWL4030_MADC_VCHG TWL4030_MADC_ADCIN11
+#define TWL4030_MADC_VBAT TWL4030_MADC_ADCIN12
+
+/* BCI related - XXX To be moved elsewhere */
+#define TWL4030_BCI_BCICTL1 0x23
+#define TWL4030_BCI_MESBAT (1<<1)
+#define TWL4030_BCI_TYPEN (1<<4)
+#define TWL4030_BCI_ITHEN (1<<3)
+
+/* USB related - XXX To be moved elsewhere */
+#define TWL4030_USB_CARKIT_ANA_CTRL 0xBB
+#define TWL4030_USB_SEL_MADC_MCPC (1<<3)
+
+#define TWL4030_MADC_IOC_MAGIC '`'
+#define TWL4030_MADC_IOCX_ADC_RAW_READ _IO(TWL4030_MADC_IOC_MAGIC, 0)
+
+struct twl4030_madc_user_parms {
+ int channel;
+ int average;
+ int status;
+ u16 result;
+};
+
+int twl4030_madc_conversion(struct twl4030_madc_request *conv);
+
+#endif
--
1.6.6.1
@@ -0,0 +1,32 @@
From a33c4e0fb917ca059e900c2851849ba604758ff9 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Thu, 17 Dec 2009 14:27:15 -0800
Subject: [PATCH 19/28] ARM: OMAP: Add twl4030 madc support to Overo
---
arch/arm/mach-omap2/board-overo.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index cb26e5d..17f066a 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -369,10 +369,15 @@ static struct twl4030_codec_data overo_codec_data = {
/* mmc2 (WLAN) and Bluetooth don't use twl4030 regulators */
+static struct twl4030_madc_platform_data overo_madc_data = {
+ .irq_line = 1,
+};
+
static struct twl4030_platform_data overo_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
.gpio = &overo_gpio_data,
+ .madc = &overo_madc_data,
.usb = &overo_usb_data,
.codec = &overo_codec_data,
.vmmc1 = &overo_vmmc1,
--
1.6.6.1
@@ -0,0 +1,35 @@
From fe51c97f26f8d6798909b1f22a5fb4ca84684f36 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Thu, 17 Dec 2009 14:32:36 -0800
Subject: [PATCH 20/28] ARM: OMAP: Add twl4030 madc support to Beagle
---
arch/arm/mach-omap2/board-omap3beagle.c | 5 +++++
1 files changed, 5 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index f699701..9259780 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -604,6 +604,10 @@ static struct twl4030_codec_data beagle_codec_data = {
.audio = &beagle_audio_data,
};
+static struct twl4030_madc_platform_data beagle_madc_data = {
+ .irq_line = 1,
+};
+
static struct twl4030_platform_data beagle_twldata = {
.irq_base = TWL4030_IRQ_BASE,
.irq_end = TWL4030_IRQ_END,
@@ -612,6 +616,7 @@ static struct twl4030_platform_data beagle_twldata = {
.usb = &beagle_usb_data,
.gpio = &beagle_gpio_data,
.codec = &beagle_codec_data,
+ .madc = &beagle_madc_data,
.vmmc1 = &beagle_vmmc1,
.vsim = &beagle_vsim,
.vdac = &beagle_vdac,
--
1.6.6.1
@@ -0,0 +1,173 @@
From f8049ce6302904c1d08d8813f8a60b10b8a476e7 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Tue, 23 Feb 2010 14:40:27 -0800
Subject: [PATCH 21/28] OMAP: DSS2: Add support for Samsung LTE430WQ-F0C panel
---
.../omap2/displays/panel-samsung-lte430wq-f0c.c | 154 ++++++++++++++++++++
1 files changed, 154 insertions(+), 0 deletions(-)
create mode 100644 drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
diff --git a/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
new file mode 100644
index 0000000..6a29f9c
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-samsung-lte430wq-f0c.c
@@ -0,0 +1,154 @@
+/*
+ * LCD panel driver for Samsung LTE430WQ-F0C
+ *
+ * Author: Steve Sakoman <steve@sakoman.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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+
+#include <plat/display.h>
+
+static struct omap_video_timings samsung_lte_timings = {
+ .x_res = 480,
+ .y_res = 272,
+
+ .pixel_clock = 9200,
+
+ .hsw = 41,
+ .hfp = 8,
+ .hbp = 45-41,
+
+ .vsw = 10,
+ .vfp = 4,
+ .vbp = 12-10,
+};
+
+static int samsung_lte_panel_power_on(struct omap_dss_device *dssdev)
+{
+ int r;
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+ return 0;
+
+ r = omapdss_dpi_display_enable(dssdev);
+ if (r)
+ goto err0;
+
+ if (dssdev->platform_enable) {
+ r = dssdev->platform_enable(dssdev);
+ if (r)
+ goto err1;
+ }
+
+ return 0;
+err1:
+ omapdss_dpi_display_disable(dssdev);
+err0:
+ return r;
+}
+
+static void samsung_lte_panel_power_off(struct omap_dss_device *dssdev)
+{
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return;
+
+ if (dssdev->platform_disable)
+ dssdev->platform_disable(dssdev);
+
+ omapdss_dpi_display_disable(dssdev);
+}
+
+static int samsung_lte_panel_probe(struct omap_dss_device *dssdev)
+{
+ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS;
+ dssdev->panel.timings = samsung_lte_timings;
+
+ return 0;
+}
+
+static void samsung_lte_panel_remove(struct omap_dss_device *dssdev)
+{
+}
+
+static int samsung_lte_panel_enable(struct omap_dss_device *dssdev)
+{
+ int r = 0;
+
+ r = samsung_lte_panel_power_on(dssdev);
+ if (r)
+ return r;
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ return 0;
+}
+
+static void samsung_lte_panel_disable(struct omap_dss_device *dssdev)
+{
+ samsung_lte_panel_power_off(dssdev);
+
+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static int samsung_lte_panel_suspend(struct omap_dss_device *dssdev)
+{
+ samsung_lte_panel_disable(dssdev);
+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+ return 0;
+}
+
+static int samsung_lte_panel_resume(struct omap_dss_device *dssdev)
+{
+ int r;
+
+ r = samsung_lte_panel_enable(dssdev);
+ if (r)
+ return r;
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ return 0;
+}
+
+static struct omap_dss_driver samsung_lte_driver = {
+ .probe = samsung_lte_panel_probe,
+ .remove = samsung_lte_panel_remove,
+
+ .enable = samsung_lte_panel_enable,
+ .disable = samsung_lte_panel_disable,
+ .suspend = samsung_lte_panel_suspend,
+ .resume = samsung_lte_panel_resume,
+
+ .driver = {
+ .name = "samsung_lte_panel",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init samsung_lte_panel_drv_init(void)
+{
+ return omap_dss_register_driver(&samsung_lte_driver);
+}
+
+static void __exit samsung_lte_panel_drv_exit(void)
+{
+ omap_dss_unregister_driver(&samsung_lte_driver);
+}
+
+module_init(samsung_lte_panel_drv_init);
+module_exit(samsung_lte_panel_drv_exit);
+MODULE_LICENSE("GPL");
--
1.6.6.1
@@ -0,0 +1,299 @@
From 93032782a4803072d7ab1e22da029325f8f3cf44 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Thu, 17 Dec 2009 15:05:30 -0800
Subject: [PATCH 22/28] OMAP: DSS2: Add support for LG Philips LB035Q02 panel
---
drivers/video/omap2/displays/Kconfig | 12 +
drivers/video/omap2/displays/Makefile | 2 +
.../omap2/displays/panel-lgphilips-lb035q02.c | 244 ++++++++++++++++++++
3 files changed, 258 insertions(+), 0 deletions(-)
create mode 100644 drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
index 12327bb..48e872f 100644
--- a/drivers/video/omap2/displays/Kconfig
+++ b/drivers/video/omap2/displays/Kconfig
@@ -7,6 +7,18 @@ config PANEL_GENERIC
Generic panel driver.
Used for DVI output for Beagle and OMAP3 SDP.
+config PANEL_LGPHILIPS_LB035Q02
+ tristate "LG.Philips LB035Q02 LCD Panel"
+ depends on OMAP2_DSS
+ help
+ LCD Panel used on Overo Palo35
+
+config PANEL_SAMSUNG_LTE430WQ_F0C
+ tristate "Samsung LTE430WQ-F0C LCD Panel"
+ depends on OMAP2_DSS
+ help
+ LCD Panel used on Overo Palo43
+
config PANEL_SHARP_LS037V7DW01
tristate "Sharp LS037V7DW01 LCD Panel"
depends on OMAP2_DSS
diff --git a/drivers/video/omap2/displays/Makefile b/drivers/video/omap2/displays/Makefile
index aa38609..2fb1a57 100644
--- a/drivers/video/omap2/displays/Makefile
+++ b/drivers/video/omap2/displays/Makefile
@@ -1,4 +1,6 @@
obj-$(CONFIG_PANEL_GENERIC) += panel-generic.o
+obj-$(CONFIG_PANEL_LGPHILIPS_LB035Q02) += panel-lgphilips-lb035q02.o
+obj-$(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) += panel-samsung-lte430wq-f0c.o
obj-$(CONFIG_PANEL_SHARP_LS037V7DW01) += panel-sharp-ls037v7dw01.o
obj-$(CONFIG_PANEL_SHARP_LQ043T1DG01) += panel-sharp-lq043t1dg01.o
diff --git a/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
new file mode 100644
index 0000000..4ad709d
--- /dev/null
+++ b/drivers/video/omap2/displays/panel-lgphilips-lb035q02.c
@@ -0,0 +1,244 @@
+/*
+ * LCD panel driver for LG.Philips LB035Q02
+ *
+ * Author: Steve Sakoman <steve@sakoman.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.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/spi/spi.h>
+
+#include <plat/display.h>
+
+static struct spi_device *spidev;
+
+static struct omap_video_timings lb035q02_timings = {
+ .x_res = 320,
+ .y_res = 240,
+
+ .pixel_clock = 6500,
+
+ .hsw = 2,
+ .hfp = 20,
+ .hbp = 68,
+
+ .vsw = 2,
+ .vfp = 4,
+ .vbp = 18,
+};
+
+static int lb035q02_write_reg(u8 reg, u16 val)
+{
+ struct spi_message msg;
+ struct spi_transfer index_xfer = {
+ .len = 3,
+ .cs_change = 1,
+ };
+ struct spi_transfer value_xfer = {
+ .len = 3,
+ };
+ u8 buffer[16];
+
+ spi_message_init(&msg);
+
+ /* register index */
+ buffer[0] = 0x70;
+ buffer[1] = 0x00;
+ buffer[2] = reg & 0x7f;
+ index_xfer.tx_buf = buffer;
+ spi_message_add_tail(&index_xfer, &msg);
+
+ /* register value */
+ buffer[4] = 0x72;
+ buffer[5] = val >> 8;
+ buffer[6] = val;
+ value_xfer.tx_buf = buffer + 4;
+ spi_message_add_tail(&value_xfer, &msg);
+
+ return spi_sync(spidev, &msg);
+}
+
+static int lb035q02_panel_power_on(struct omap_dss_device *dssdev)
+{
+ int r;
+
+ if (dssdev->state == OMAP_DSS_DISPLAY_ACTIVE)
+ return 0;
+
+ r = omapdss_dpi_display_enable(dssdev);
+ if (r)
+ goto err0;
+
+ if (dssdev->platform_enable) {
+ r = dssdev->platform_enable(dssdev);
+ if (r)
+ goto err1;
+ }
+
+ /* Panel init sequence from page 28 of the spec */
+ lb035q02_write_reg(0x01, 0x6300);
+ lb035q02_write_reg(0x02, 0x0200);
+ lb035q02_write_reg(0x03, 0x0177);
+ lb035q02_write_reg(0x04, 0x04c7);
+ lb035q02_write_reg(0x05, 0xffc0);
+ lb035q02_write_reg(0x06, 0xe806);
+ lb035q02_write_reg(0x0a, 0x4008);
+ lb035q02_write_reg(0x0b, 0x0000);
+ lb035q02_write_reg(0x0d, 0x0030);
+ lb035q02_write_reg(0x0e, 0x2800);
+ lb035q02_write_reg(0x0f, 0x0000);
+ lb035q02_write_reg(0x16, 0x9f80);
+ lb035q02_write_reg(0x17, 0x0a0f);
+ lb035q02_write_reg(0x1e, 0x00c1);
+ lb035q02_write_reg(0x30, 0x0300);
+ lb035q02_write_reg(0x31, 0x0007);
+ lb035q02_write_reg(0x32, 0x0000);
+ lb035q02_write_reg(0x33, 0x0000);
+ lb035q02_write_reg(0x34, 0x0707);
+ lb035q02_write_reg(0x35, 0x0004);
+ lb035q02_write_reg(0x36, 0x0302);
+ lb035q02_write_reg(0x37, 0x0202);
+ lb035q02_write_reg(0x3a, 0x0a0d);
+ lb035q02_write_reg(0x3b, 0x0806);
+
+ return 0;
+err1:
+ omapdss_dpi_display_disable(dssdev);
+err0:
+ return r;
+}
+
+static void lb035q02_panel_power_off(struct omap_dss_device *dssdev)
+{
+ if (dssdev->state != OMAP_DSS_DISPLAY_ACTIVE)
+ return;
+
+ if (dssdev->platform_disable)
+ dssdev->platform_disable(dssdev);
+
+ omapdss_dpi_display_disable(dssdev);
+}
+
+static int lb035q02_panel_probe(struct omap_dss_device *dssdev)
+{
+ dssdev->panel.config = OMAP_DSS_LCD_TFT | OMAP_DSS_LCD_IVS |
+ OMAP_DSS_LCD_IHS;
+ dssdev->panel.timings = lb035q02_timings;
+
+ return 0;
+}
+
+static void lb035q02_panel_remove(struct omap_dss_device *dssdev)
+{
+}
+
+static int lb035q02_panel_enable(struct omap_dss_device *dssdev)
+{
+ int r = 0;
+
+ r = lb035q02_panel_power_on(dssdev);
+ if (r)
+ return r;
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ return 0;
+}
+
+static void lb035q02_panel_disable(struct omap_dss_device *dssdev)
+{
+ lb035q02_panel_power_off(dssdev);
+
+ dssdev->state = OMAP_DSS_DISPLAY_DISABLED;
+}
+
+static int lb035q02_panel_suspend(struct omap_dss_device *dssdev)
+{
+ lb035q02_panel_disable(dssdev);
+ dssdev->state = OMAP_DSS_DISPLAY_SUSPENDED;
+ return 0;
+}
+
+static int lb035q02_panel_resume(struct omap_dss_device *dssdev)
+{
+ int r;
+
+ r = lb035q02_panel_power_on(dssdev);
+ if (r)
+ return r;
+
+ dssdev->state = OMAP_DSS_DISPLAY_ACTIVE;
+
+ return 0;
+}
+
+static struct omap_dss_driver lb035q02_driver = {
+ .probe = lb035q02_panel_probe,
+ .remove = lb035q02_panel_remove,
+
+ .enable = lb035q02_panel_enable,
+ .disable = lb035q02_panel_disable,
+ .suspend = lb035q02_panel_suspend,
+ .resume = lb035q02_panel_resume,
+
+ .driver = {
+ .name = "lgphilips_lb035q02_panel",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __devinit lb035q02_panel_spi_probe(struct spi_device *spi)
+{
+ spidev = spi;
+ return 0;
+}
+
+static int __devexit lb035q02_panel_spi_remove(struct spi_device *spi)
+{
+ return 0;
+}
+
+static struct spi_driver lb035q02_spi_driver = {
+ .driver = {
+ .name = "lgphilips_lb035q02_panel-spi",
+ .owner = THIS_MODULE,
+ },
+ .probe = lb035q02_panel_spi_probe,
+ .remove = __devexit_p (lb035q02_panel_spi_remove),
+};
+
+static int __init lb035q02_panel_drv_init(void)
+{
+ int r;
+ r = spi_register_driver(&lb035q02_spi_driver);
+ if (r != 0)
+ pr_err("lgphilips_lb035q02: Unable to register SPI driver: %d\n", r);
+
+ r = omap_dss_register_driver(&lb035q02_driver);
+ if (r != 0)
+ pr_err("lgphilips_lb035q02: Unable to register panel driver: %d\n", r);
+
+ return r;
+}
+
+static void __exit lb035q02_panel_drv_exit(void)
+{
+ spi_unregister_driver(&lb035q02_spi_driver);
+ omap_dss_unregister_driver(&lb035q02_driver);
+}
+
+module_init(lb035q02_panel_drv_init);
+module_exit(lb035q02_panel_drv_exit);
+MODULE_LICENSE("GPL");
--
1.6.6.1
@@ -0,0 +1,75 @@
From f046a207183e3e338c7e851085265f0df95f4cc2 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Tue, 19 Jan 2010 21:19:15 -0800
Subject: [PATCH 23/28] OMAP: DSS2: add bootarg for selecting svideo or composite for tv output
also add pal-16 and ntsc-16 omapfb.mode settings for 16bpp
---
drivers/video/omap2/dss/venc.c | 22 ++++++++++++++++++++++
drivers/video/omap2/omapfb/omapfb-main.c | 10 +++++++++-
2 files changed, 31 insertions(+), 1 deletions(-)
diff --git a/drivers/video/omap2/dss/venc.c b/drivers/video/omap2/dss/venc.c
index eff3505..e1f4aab 100644
--- a/drivers/video/omap2/dss/venc.c
+++ b/drivers/video/omap2/dss/venc.c
@@ -87,6 +87,11 @@
#define VENC_OUTPUT_TEST 0xC8
#define VENC_DAC_B__DAC_C 0xC8
+static char *tv_connection;
+
+module_param_named(tvcable, tv_connection, charp, 0);
+MODULE_PARM_DESC(tvcable, "TV connection type (svideo, composite)");
+
struct venc_config {
u32 f_control;
u32 vidout_ctrl;
@@ -459,6 +464,23 @@ static int venc_panel_probe(struct omap_dss_device *dssdev)
{
dssdev->panel.timings = omap_dss_pal_timings;
+ /* Allow the TV output to be overriden */
+ if (tv_connection) {
+ if (strcmp(tv_connection, "svideo") == 0) {
+ printk(KERN_INFO
+ "omapdss: tv output is svideo.\n");
+ dssdev->phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO;
+ } else if (strcmp(tv_connection, "composite") == 0) {
+ printk(KERN_INFO
+ "omapdss: tv output is composite.\n");
+ dssdev->phy.venc.type = OMAP_DSS_VENC_TYPE_COMPOSITE;
+ } else {
+ printk(KERN_INFO
+ "omapdss: unsupported output type'%s'.\n",
+ tv_connection);
+ }
+ }
+
return 0;
}
diff --git a/drivers/video/omap2/omapfb/omapfb-main.c b/drivers/video/omap2/omapfb/omapfb-main.c
index 6a704f1..7ee833f 100644
--- a/drivers/video/omap2/omapfb/omapfb-main.c
+++ b/drivers/video/omap2/omapfb/omapfb-main.c
@@ -2036,7 +2036,15 @@ static int omapfb_mode_to_timings(const char *mode_str,
int r;
#ifdef CONFIG_OMAP2_DSS_VENC
- if (strcmp(mode_str, "pal") == 0) {
+ if (strcmp(mode_str, "pal-16") == 0) {
+ *timings = omap_dss_pal_timings;
+ *bpp = 16;
+ return 0;
+ } else if (strcmp(mode_str, "ntsc-16") == 0) {
+ *timings = omap_dss_ntsc_timings;
+ *bpp = 16;
+ return 0;
+ } else if (strcmp(mode_str, "pal") == 0) {
*timings = omap_dss_pal_timings;
*bpp = 24;
return 0;
--
1.6.6.1
@@ -0,0 +1,39 @@
From 66bba5baf225a1420c734aa0268e7dd37fc3f73b Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Sun, 24 Jan 2010 09:33:56 -0800
Subject: [PATCH 24/28] ARM: OMAP2: mmc-twl4030: move clock input selection prior to vcc test
otherwise it is not executed on systems that use non-twl regulators
---
arch/arm/mach-omap2/hsmmc.c | 14 ++++++--------
1 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 34272e4..a74631d 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -186,15 +186,13 @@ static void hsmmc23_before_set_reg(struct device *dev, int slot,
if (mmc->slots[0].remux)
mmc->slots[0].remux(dev, slot, power_on);
- if (power_on) {
- /* Only MMC2 supports a CLKIN */
- if (mmc->slots[0].internal_clock) {
- u32 reg;
+ /* Only MMC2 supports a CLKIN */
+ if (mmc->slots[0].internal_clock) {
+ u32 reg;
- reg = omap_ctrl_readl(control_devconf1_offset);
- reg |= OMAP2_MMCSDIO2ADPCLKISEL;
- omap_ctrl_writel(reg, control_devconf1_offset);
- }
+ reg = omap_ctrl_readl(control_devconf1_offset);
+ reg |= OMAP2_MMCSDIO2ADPCLKISEL;
+ omap_ctrl_writel(reg, control_devconf1_offset);
}
}
--
1.6.6.1
@@ -0,0 +1,55 @@
From ae08111e55d17183382dd06d161066adf9f80f3c Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Thu, 4 Feb 2010 12:26:22 -0800
Subject: [PATCH 25/28] RTC: add support for backup battery recharge
---
drivers/rtc/rtc-twl.c | 25 +++++++++++++++++++++++++
1 files changed, 25 insertions(+), 0 deletions(-)
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index ed1b868..33a8598 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -30,6 +30,23 @@
#include <linux/i2c/twl.h>
+/*
+ * PM_RECEIVER block register offsets (use TWL4030_MODULE_PM_RECEIVER)
+ */
+#define REG_BB_CFG 0x12
+
+/* PM_RECEIVER BB_CFG bitfields */
+#define BIT_PM_RECEIVER_BB_CFG_BBCHEN 0x10
+#define BIT_PM_RECEIVER_BB_CFG_BBSEL 0x0C
+#define BIT_PM_RECEIVER_BB_CFG_BBSEL_2V5 0x00
+#define BIT_PM_RECEIVER_BB_CFG_BBSEL_3V0 0x04
+#define BIT_PM_RECEIVER_BB_CFG_BBSEL_3V1 0x08
+#define BIT_PM_RECEIVER_BB_CFG_BBSEL_3v2 0x0c
+#define BIT_PM_RECEIVER_BB_CFG_BBISEL 0x03
+#define BIT_PM_RECEIVER_BB_CFG_BBISEL_25UA 0x00
+#define BIT_PM_RECEIVER_BB_CFG_BBISEL_150UA 0x01
+#define BIT_PM_RECEIVER_BB_CFG_BBISEL_500UA 0x02
+#define BIT_PM_RECEIVER_BB_CFG_BBISEL_1MA 0x03
/*
* RTC block register offsets (use TWL_MODULE_RTC)
@@ -508,6 +525,14 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
if (ret < 0)
goto out2;
+ /* enable backup battery charging */
+ /* use a conservative 25uA @ 3.1V */
+ ret = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
+ BIT_PM_RECEIVER_BB_CFG_BBCHEN |
+ BIT_PM_RECEIVER_BB_CFG_BBSEL_3V1 |
+ BIT_PM_RECEIVER_BB_CFG_BBISEL_25UA,
+ REG_BB_CFG);
+
return ret;
out2:
--
1.6.6.1
@@ -0,0 +1,49 @@
From dd53a7c1ab8addfd2a943ea44b5ccc5700648323 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Wed, 24 Feb 2010 10:37:22 -0800
Subject: [PATCH 26/28] ARM: OMAP: automatically set musb mode in platform data based on CONFIG options
---
arch/arm/mach-omap2/board-omap3beagle.c | 6 ++++++
arch/arm/mach-omap2/board-overo.c | 6 ++++++
2 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 9259780..ad0c1d8 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -785,7 +785,13 @@ static struct omap_board_mux board_mux[] __initdata = {
static struct omap_musb_board_data musb_board_data = {
.interface_type = MUSB_INTERFACE_ULPI,
+#if defined(CONFIG_USB_MUSB_OTG)
.mode = MUSB_OTG,
+#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
+ .mode = MUSB_PERIPHERAL,
+#else
+ .mode = MUSB_HOST,
+#endif
.power = 100,
};
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index 17f066a..b28a9d5 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -447,7 +447,13 @@ static struct omap_board_mux board_mux[] __initdata = {
static struct omap_musb_board_data musb_board_data = {
.interface_type = MUSB_INTERFACE_ULPI,
+#if defined(CONFIG_USB_MUSB_OTG)
.mode = MUSB_OTG,
+#elif defined(CONFIG_USB_GADGET_MUSB_HDRC)
+ .mode = MUSB_PERIPHERAL,
+#else
+ .mode = MUSB_HOST,
+#endif
.power = 100,
};
--
1.6.6.1
@@ -0,0 +1,34 @@
From ec3e66ef2e222feb0408f16a3498be1ea9b6a9c0 Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Mon, 10 May 2010 13:59:14 -0700
Subject: [PATCH 27/28] OMAP: DSS2: check for both cpu type and revision, rather than just revision
---
drivers/video/omap2/dss/dispc.c | 4 ++--
1 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/video/omap2/dss/dispc.c b/drivers/video/omap2/dss/dispc.c
index fa40fa5..133916a 100644
--- a/drivers/video/omap2/dss/dispc.c
+++ b/drivers/video/omap2/dss/dispc.c
@@ -2101,7 +2101,7 @@ void dispc_set_parallel_interface_mode(enum omap_parallel_interface_mode mode)
static bool _dispc_lcd_timings_ok(int hsw, int hfp, int hbp,
int vsw, int vfp, int vbp)
{
- if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
+ if (cpu_is_omap24xx() || (cpu_is_omap34xx() && omap_rev_lt_3_0())) {
if (hsw < 1 || hsw > 64 ||
hfp < 1 || hfp > 256 ||
hbp < 1 || hbp > 256 ||
@@ -2134,7 +2134,7 @@ static void _dispc_set_lcd_timings(int hsw, int hfp, int hbp,
{
u32 timing_h, timing_v;
- if (cpu_is_omap24xx() || omap_rev() < OMAP3430_REV_ES3_0) {
+ if (cpu_is_omap24xx() || (cpu_is_omap34xx() && omap_rev_lt_3_0())) {
timing_h = FLD_VAL(hsw-1, 5, 0) | FLD_VAL(hfp-1, 15, 8) |
FLD_VAL(hbp-1, 27, 20);
--
1.6.6.1
@@ -0,0 +1,355 @@
From 9b2bfa418f2e1b7ed3e210cb7cba3cdd67f9925f Mon Sep 17 00:00:00 2001
From: Steve Sakoman <steve@sakoman.com>
Date: Fri, 18 Dec 2009 06:39:24 -0800
Subject: [PATCH 28/28] OMAP: DSS2: Add DSS2 support for Overo
---
arch/arm/mach-omap2/board-overo.c | 238 +++++++++++++++++++++++++++++++------
1 files changed, 204 insertions(+), 34 deletions(-)
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index b28a9d5..8a44c17 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -28,6 +28,7 @@
#include <linux/platform_device.h>
#include <linux/i2c/twl.h>
#include <linux/regulator/machine.h>
+#include <linux/spi/spi.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/nand.h>
@@ -41,10 +42,13 @@
#include <plat/board.h>
#include <plat/common.h>
+#include <plat/display.h>
#include <mach/gpio.h>
#include <plat/gpmc.h>
#include <mach/hardware.h>
#include <plat/nand.h>
+#include <plat/mcspi.h>
+#include <plat/mux.h>
#include <plat/usb.h>
#include "mux.h"
@@ -68,8 +72,6 @@
#if defined(CONFIG_TOUCHSCREEN_ADS7846) || \
defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
-#include <plat/mcspi.h>
-#include <linux/spi/spi.h>
#include <linux/spi/ads7846.h>
static struct omap2_mcspi_device_config ads7846_mcspi_config = {
@@ -94,18 +96,6 @@ static struct ads7846_platform_data ads7846_config = {
.keep_vref_on = 1,
};
-static struct spi_board_info overo_spi_board_info[] __initdata = {
- {
- .modalias = "ads7846",
- .bus_num = 1,
- .chip_select = 0,
- .max_speed_hz = 1500000,
- .controller_data = &ads7846_mcspi_config,
- .irq = OMAP_GPIO_IRQ(OVERO_GPIO_PENDOWN),
- .platform_data = &ads7846_config,
- }
-};
-
static void __init overo_ads7846_init(void)
{
if ((gpio_request(OVERO_GPIO_PENDOWN, "ADS7846_PENDOWN") == 0) &&
@@ -115,9 +105,6 @@ static void __init overo_ads7846_init(void)
printk(KERN_ERR "could not obtain gpio for ADS7846_PENDOWN\n");
return;
}
-
- spi_register_board_info(overo_spi_board_info,
- ARRAY_SIZE(overo_spi_board_info));
}
#else
@@ -233,6 +220,139 @@ static inline void __init overo_init_smsc911x(void)
static inline void __init overo_init_smsc911x(void) { return; }
#endif
+/* DSS */
+static int lcd_enabled;
+static int dvi_enabled;
+
+#define OVERO_GPIO_LCD_EN 144
+#define OVERO_GPIO_LCD_BL 145
+
+static void __init overo_display_init(void)
+{
+ if ((gpio_request(OVERO_GPIO_LCD_EN, "OVERO_GPIO_LCD_EN") == 0) &&
+ (gpio_direction_output(OVERO_GPIO_LCD_EN, 1) == 0))
+ gpio_export(OVERO_GPIO_LCD_EN, 0);
+ else
+ printk(KERN_ERR "could not obtain gpio for "
+ "OVERO_GPIO_LCD_EN\n");
+
+ if ((gpio_request(OVERO_GPIO_LCD_BL, "OVERO_GPIO_LCD_BL") == 0) &&
+ (gpio_direction_output(OVERO_GPIO_LCD_BL, 1) == 0))
+ gpio_export(OVERO_GPIO_LCD_BL, 0);
+ else
+ printk(KERN_ERR "could not obtain gpio for "
+ "OVERO_GPIO_LCD_BL\n");
+}
+
+static int overo_panel_enable_dvi(struct omap_dss_device *dssdev)
+{
+ if (lcd_enabled) {
+ printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
+ return -EINVAL;
+ }
+ dvi_enabled = 1;
+
+ return 0;
+}
+
+static void overo_panel_disable_dvi(struct omap_dss_device *dssdev)
+{
+ dvi_enabled = 0;
+}
+
+static struct omap_dss_device overo_dvi_device = {
+ .type = OMAP_DISPLAY_TYPE_DPI,
+ .name = "dvi",
+ .driver_name = "generic_panel",
+ .phy.dpi.data_lines = 24,
+ .platform_enable = overo_panel_enable_dvi,
+ .platform_disable = overo_panel_disable_dvi,
+};
+
+static struct omap_dss_device overo_tv_device = {
+ .name = "tv",
+ .driver_name = "venc",
+ .type = OMAP_DISPLAY_TYPE_VENC,
+ .phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
+};
+
+static int overo_panel_enable_lcd(struct omap_dss_device *dssdev)
+{
+ if (dvi_enabled) {
+ printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
+ return -EINVAL;
+ }
+
+ gpio_set_value(OVERO_GPIO_LCD_EN, 1);
+ gpio_set_value(OVERO_GPIO_LCD_BL, 1);
+ lcd_enabled = 1;
+ return 0;
+}
+
+static void overo_panel_disable_lcd(struct omap_dss_device *dssdev)
+{
+ gpio_set_value(OVERO_GPIO_LCD_EN, 0);
+ gpio_set_value(OVERO_GPIO_LCD_BL, 0);
+ lcd_enabled = 0;
+}
+
+#if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \
+ defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE)
+static struct omap_dss_device overo_lcd35_device = {
+ .type = OMAP_DISPLAY_TYPE_DPI,
+ .name = "lcd35",
+ .driver_name = "lgphilips_lb035q02_panel",
+ .phy.dpi.data_lines = 24,
+ .platform_enable = overo_panel_enable_lcd,
+ .platform_disable = overo_panel_disable_lcd,
+};
+#endif
+
+#if defined(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) || \
+ defined(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C_MODULE)
+static struct omap_dss_device overo_lcd43_device = {
+ .type = OMAP_DISPLAY_TYPE_DPI,
+ .name = "lcd43",
+ .driver_name = "samsung_lte_panel",
+ .phy.dpi.data_lines = 24,
+ .platform_enable = overo_panel_enable_lcd,
+ .platform_disable = overo_panel_disable_lcd,
+};
+#endif
+
+static struct omap_dss_device *overo_dss_devices[] = {
+ &overo_dvi_device,
+ &overo_tv_device,
+#if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \
+ defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE)
+ &overo_lcd35_device,
+#endif
+#if defined(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C) || \
+ defined(CONFIG_PANEL_SAMSUNG_LTE430WQ_F0C_MODULE)
+ &overo_lcd43_device,
+#endif
+};
+
+static struct omap_dss_board_info overo_dss_data = {
+ .num_devices = ARRAY_SIZE(overo_dss_devices),
+ .devices = overo_dss_devices,
+ .default_device = &overo_dvi_device,
+};
+
+static struct platform_device overo_dss_device = {
+ .name = "omapdss",
+ .id = -1,
+ .dev = {
+ .platform_data = &overo_dss_data,
+ },
+};
+
+static struct regulator_consumer_supply overo_vdda_dac_supply =
+ REGULATOR_SUPPLY("vdda_dac", "omapdss");
+
+static struct regulator_consumer_supply overo_vdds_dsi_supply =
+ REGULATOR_SUPPLY("vdds_dsi", "omapdss");
+
static struct mtd_partition overo_nand_partitions[] = {
{
.name = "xloader",
@@ -358,6 +478,37 @@ static struct regulator_init_data overo_vmmc1 = {
.consumer_supplies = &overo_vmmc1_supply,
};
+/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
+static struct regulator_init_data overo_vdac = {
+ .constraints = {
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &overo_vdda_dac_supply,
+};
+
+/* VPLL2 for digital video outputs */
+static struct regulator_init_data overo_vpll2 = {
+ .constraints = {
+ .name = "VDVI",
+ .min_uV = 1800000,
+ .max_uV = 1800000,
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
+ | REGULATOR_MODE_STANDBY,
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
+ | REGULATOR_CHANGE_STATUS,
+ },
+ .num_consumer_supplies = 1,
+ .consumer_supplies = &overo_vdds_dsi_supply,
+};
+
+/* mmc2 (WLAN) and Bluetooth don't use twl4030 regulators */
+
static struct twl4030_codec_audio_data overo_audio_data = {
.audio_mclk = 26000000,
};
@@ -367,8 +518,6 @@ static struct twl4030_codec_data overo_codec_data = {
.audio = &overo_audio_data,
};
-/* mmc2 (WLAN) and Bluetooth don't use twl4030 regulators */
-
static struct twl4030_madc_platform_data overo_madc_data = {
.irq_line = 1,
};
@@ -381,6 +530,8 @@ static struct twl4030_platform_data overo_twldata = {
.usb = &overo_usb_data,
.codec = &overo_codec_data,
.vmmc1 = &overo_vmmc1,
+ .vdac = &overo_vdac,
+ .vpll2 = &overo_vpll2,
};
static struct i2c_board_info __initdata overo_i2c_boardinfo[] = {
@@ -401,23 +552,41 @@ static int __init overo_i2c_init(void)
return 0;
}
-static struct platform_device overo_lcd_device = {
- .name = "overo_lcd",
- .id = -1,
-};
-
-static struct omap_lcd_config overo_lcd_config __initdata = {
- .ctrl_name = "internal",
+static struct spi_board_info overo_spi_board_info[] __initdata = {
+#if defined(CONFIG_TOUCHSCREEN_ADS7846) || \
+ defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
+ {
+ .modalias = "ads7846",
+ .bus_num = 1,
+ .chip_select = 0,
+ .max_speed_hz = 1500000,
+ .controller_data = &ads7846_mcspi_config,
+ .irq = OMAP_GPIO_IRQ(OVERO_GPIO_PENDOWN),
+ .platform_data = &ads7846_config,
+ },
+#endif
+#if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \
+ defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE)
+ {
+ .modalias = "lgphilips_lb035q02_panel-spi",
+ .bus_num = 1,
+ .chip_select = 1,
+ .max_speed_hz = 500000,
+ .mode = SPI_MODE_3,
+ },
+#endif
};
-static struct omap_board_config_kernel overo_config[] __initdata = {
- { OMAP_TAG_LCD, &overo_lcd_config },
-};
+static int __init overo_spi_init(void)
+{
+ overo_ads7846_init();
+ spi_register_board_info(overo_spi_board_info,
+ ARRAY_SIZE(overo_spi_board_info));
+ return 0;
+}
static void __init overo_init_irq(void)
{
- omap_board_config = overo_config;
- omap_board_config_size = ARRAY_SIZE(overo_config);
omap2_init_common_infrastructure();
omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
mt46h32m32lf6_sdrc_params);
@@ -425,7 +594,7 @@ static void __init overo_init_irq(void)
}
static struct platform_device *overo_devices[] __initdata = {
- &overo_lcd_device,
+ &overo_dss_device,
};
static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
@@ -466,8 +635,9 @@ static void __init overo_init(void)
overo_flash_init();
usb_musb_init(&musb_board_data);
usb_ehci_init(&ehci_pdata);
- overo_ads7846_init();
+ overo_spi_init();
overo_init_smsc911x();
+ overo_display_init();
/* Ensure SDRC pins are mux'd for self-refresh */
omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
@@ -510,7 +680,7 @@ static void __init overo_init(void)
"OVERO_GPIO_USBH_CPEN\n");
}
-MACHINE_START(OVERO, "Gumstix Overo")
+MACHINE_START(OVERO, "Gumstsix Overo")
.boot_params = 0x80000100,
.map_io = omap3_map_io,
.reserve = omap_reserve,
--
1.6.6.1