mirror of
https://git.yoctoproject.org/meta-ti
synced 2026-05-30 23:40:29 +00:00
linux-omap-2.6.39: remove old beagleboard-specific and not supported kernel
Beagleboard is supported by newer 3.x kernel recipes. Signed-off-by: Denys Dmytriyenko <denys@ti.com> Acked-by: Franklin Cooper Jr. <fcooper@ti.com>
This commit is contained in:
-117
@@ -1,117 +0,0 @@
|
||||
From 16c1bdb30f1bcd750b29dffd2ef3003be2d30610 Mon Sep 17 00:00:00 2001
|
||||
From: Koen Kooi <koen@dominion.thruhere.net>
|
||||
Date: Fri, 20 May 2011 12:48:37 +0200
|
||||
Subject: [PATCH 1/7] OMAP3: beagle: add support for beagleboard xM revision C
|
||||
|
||||
The USB enable GPIO has been inverted and the USER button moved.
|
||||
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/board-omap3beagle.c | 34 +++++++++++++++++++++++-------
|
||||
1 files changed, 26 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
index 2de4b02..77bafa8 100644
|
||||
--- a/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
@@ -62,7 +62,9 @@
|
||||
* 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
|
||||
+ * XMC = GPIO173, GPIO172, GPIO171: 0 1 0
|
||||
*/
|
||||
enum {
|
||||
OMAP3BEAGLE_BOARD_UNKN = 0,
|
||||
@@ -70,6 +72,7 @@ enum {
|
||||
OMAP3BEAGLE_BOARD_C1_3,
|
||||
OMAP3BEAGLE_BOARD_C4,
|
||||
OMAP3BEAGLE_BOARD_XM,
|
||||
+ OMAP3BEAGLE_BOARD_XMC,
|
||||
};
|
||||
|
||||
static u8 omap3_beagle_version;
|
||||
@@ -124,9 +127,18 @@ static void __init omap3_beagle_init_rev(void)
|
||||
printk(KERN_INFO "OMAP3 Beagle Rev: xM\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;
|
||||
+ case 2:
|
||||
+ printk(KERN_INFO "OMAP3 Beagle Rev: xM C\n");
|
||||
+ omap3_beagle_version = OMAP3BEAGLE_BOARD_XMC;
|
||||
+ break;
|
||||
default:
|
||||
- printk(KERN_INFO "OMAP3 Beagle Rev: unknown %hd\n", beagle_rev);
|
||||
- omap3_beagle_version = OMAP3BEAGLE_BOARD_UNKN;
|
||||
+ printk(KERN_INFO
|
||||
+ "OMAP3 Beagle Rev: unknown %hd, assuming xM C or newer\n", beagle_rev);
|
||||
+ omap3_beagle_version = OMAP3BEAGLE_BOARD_XMC;
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -278,7 +290,7 @@ static int beagle_twl_gpio_setup(struct device *dev,
|
||||
{
|
||||
int r;
|
||||
|
||||
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
|
||||
+ if (cpu_is_omap3630()) {
|
||||
mmc[0].gpio_wp = -EINVAL;
|
||||
} else if ((omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C1_3) ||
|
||||
(omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_C4)) {
|
||||
@@ -298,7 +310,8 @@ static int beagle_twl_gpio_setup(struct device *dev,
|
||||
/* REVISIT: need ehci-omap hooks for external VBUS
|
||||
* power switch and overcurrent detect
|
||||
*/
|
||||
- if (omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XM) {
|
||||
+ if (omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XM
|
||||
+ && omap3_beagle_get_rev() != OMAP3BEAGLE_BOARD_XMC) {
|
||||
r = gpio_request(gpio + 1, "EHCI_nOC");
|
||||
if (!r) {
|
||||
r = gpio_direction_input(gpio + 1);
|
||||
@@ -320,7 +333,7 @@ static int beagle_twl_gpio_setup(struct device *dev,
|
||||
gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
|
||||
|
||||
/* DVI reset GPIO is different between beagle revisions */
|
||||
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM)
|
||||
+ if (cpu_is_omap3630())
|
||||
beagle_dvi_device.reset_gpio = 129;
|
||||
else
|
||||
beagle_dvi_device.reset_gpio = 170;
|
||||
@@ -334,7 +347,7 @@ static int beagle_twl_gpio_setup(struct device *dev,
|
||||
* P7/P8 revisions(prototype): Camera EN
|
||||
* A2+ revisions (production): LDO (supplies DVI, serial, led blocks)
|
||||
*/
|
||||
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
|
||||
+ if (cpu_is_omap3630()) {
|
||||
r = gpio_request(gpio + 1, "nDVI_PWR_EN");
|
||||
if (!r) {
|
||||
r = gpio_direction_output(gpio + 1, 0);
|
||||
@@ -625,7 +638,7 @@ static void __init beagle_opp_init(void)
|
||||
}
|
||||
|
||||
/* Custom OPP enabled for XM */
|
||||
- if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
|
||||
+ if (cpu_is_omap3630()) {
|
||||
struct omap_hwmod *mh = omap_hwmod_lookup("mpu");
|
||||
struct omap_hwmod *dh = omap_hwmod_lookup("iva");
|
||||
struct device *dev;
|
||||
@@ -665,6 +678,11 @@ static void __init omap3_beagle_init(void)
|
||||
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
|
||||
omap3_beagle_init_rev();
|
||||
omap3_beagle_i2c_init();
|
||||
+
|
||||
+ if (cpu_is_omap3630()) {
|
||||
+ gpio_buttons[0].gpio = 4;
|
||||
+ }
|
||||
+
|
||||
platform_add_devices(omap3_beagle_devices,
|
||||
ARRAY_SIZE(omap3_beagle_devices));
|
||||
omap_display_init(&beagle_dss_data);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-359
@@ -1,359 +0,0 @@
|
||||
From 27494059a5d005b8cad4e0e8640ff031b86220dc Mon Sep 17 00:00:00 2001
|
||||
From: Koen Kooi <koen@dominion.thruhere.net>
|
||||
Date: Fri, 20 May 2011 13:06:24 +0200
|
||||
Subject: [PATCH 2/7] OMAP3: beagle: add support for expansionboards
|
||||
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/board-omap3beagle.c | 272 ++++++++++++++++++++++++++++++-
|
||||
1 files changed, 269 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
index 77bafa8..db285e1 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>
|
||||
#include <linux/opp.h>
|
||||
@@ -154,6 +155,167 @@ fail0:
|
||||
return;
|
||||
}
|
||||
|
||||
+char expansionboard_name[16];
|
||||
+
|
||||
+#if defined(CONFIG_WL12XX) || defined(CONFIG_WL12XX_MODULE)
|
||||
+#include <linux/regulator/fixed.h>
|
||||
+#include <linux/wl12xx.h>
|
||||
+
|
||||
+#define OMAP_BEAGLE_WLAN_EN_GPIO (139)
|
||||
+#define OMAP_BEAGLE_BT_EN_GPIO (138)
|
||||
+#define OMAP_BEAGLE_WLAN_IRQ_GPIO (137)
|
||||
+#define OMAP_BEAGLE_FM_EN_BT_WU (136)
|
||||
+
|
||||
+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 int gpios[] = {OMAP_BEAGLE_BT_EN_GPIO, OMAP_BEAGLE_FM_EN_BT_WU, -1};
|
||||
+static struct platform_device wl12xx_device = {
|
||||
+ .name = "kim",
|
||||
+ .id = -1,
|
||||
+ .dev.platform_data = &gpios,
|
||||
+};
|
||||
+
|
||||
+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,
|
||||
+ .ocr_mask = MMC_VDD_165_195,
|
||||
+ .nonremovable = true,
|
||||
+ },
|
||||
+ {} /* Terminator */
|
||||
+ };
|
||||
+
|
||||
+static struct regulator_consumer_supply beagle_vmmc2_supply =
|
||||
+ REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
|
||||
+
|
||||
+static struct regulator_init_data beagle_vmmc2 = {
|
||||
+ .constraints = {
|
||||
+ .min_uV = 1850000,
|
||||
+ .max_uV = 1850000,
|
||||
+ .apply_uV = true,
|
||||
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
|
||||
+ | REGULATOR_MODE_STANDBY,
|
||||
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
|
||||
+ | 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>
|
||||
+#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);
|
||||
+ 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);
|
||||
+ 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 */
|
||||
{
|
||||
@@ -272,6 +434,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 */
|
||||
};
|
||||
|
||||
@@ -301,11 +469,25 @@ 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_WL12XX) || defined(CONFIG_WL12XX_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
|
||||
@@ -466,7 +648,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,
|
||||
@@ -481,10 +663,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));
|
||||
@@ -627,6 +823,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 beagle_opp_init(void)
|
||||
{
|
||||
int r = 0;
|
||||
@@ -693,6 +898,65 @@ 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;
|
||||
+ }
|
||||
+
|
||||
+ 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);
|
||||
+ }
|
||||
+
|
||||
+ 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 bt platform device\n");
|
||||
+ platform_device_register(&wl12xx_device);
|
||||
+ printk(KERN_INFO "Beagle expansionboard: registering wl12xx wifi platform device\n");
|
||||
+ platform_device_register(&omap_vwlan_device);
|
||||
+ }
|
||||
+
|
||||
usb_musb_init(&musb_board_data);
|
||||
usbhs_init(&usbhs_bdata);
|
||||
omap3beagle_flash_init();
|
||||
@@ -705,6 +969,8 @@ static void __init omap3_beagle_init(void)
|
||||
beagle_opp_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
|
||||
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
From 91e701f3287923d11dd295b6a62186909e362503 Mon Sep 17 00:00:00 2001
|
||||
From: Koen Kooi <koen@dominion.thruhere.net>
|
||||
Date: Sat, 21 May 2011 16:18:30 +0200
|
||||
Subject: [PATCH 3/7] OMAP3: beagle: add MADC support
|
||||
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
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 db285e1..da4ba50 100644
|
||||
--- a/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
@@ -634,6 +634,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,
|
||||
@@ -642,6 +646,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
|
||||
|
||||
-88
@@ -1,88 +0,0 @@
|
||||
From 9d7f46abab88c74e674461a2f4e9ab35b524a6ef Mon Sep 17 00:00:00 2001
|
||||
From: Koen Kooi <koen@dominion.thruhere.net>
|
||||
Date: Wed, 25 May 2011 08:56:06 +0200
|
||||
Subject: [PATCH 4/7] OMAP3: beagle: add regulators for camera interface
|
||||
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/board-omap3beagle.c | 50 +++++++++++++++++++++++++++++++
|
||||
1 files changed, 50 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
index da4ba50..211cbdf 100644
|
||||
--- a/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
@@ -453,6 +453,44 @@ static struct regulator_consumer_supply beagle_vsim_supply = {
|
||||
|
||||
static struct gpio_led gpio_leds[];
|
||||
|
||||
+static struct regulator_consumer_supply beagle_vaux3_supply = {
|
||||
+ .supply = "cam_1v8",
|
||||
+};
|
||||
+
|
||||
+static struct regulator_consumer_supply beagle_vaux4_supply = {
|
||||
+ .supply = "cam_2v8",
|
||||
+};
|
||||
+
|
||||
+/* VAUX3 for CAM_1V8 */
|
||||
+static struct regulator_init_data beagle_vaux3 = {
|
||||
+ .constraints = {
|
||||
+ .min_uV = 1800000,
|
||||
+ .max_uV = 1800000,
|
||||
+ .apply_uV = true,
|
||||
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
|
||||
+ | REGULATOR_MODE_STANDBY,
|
||||
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
|
||||
+ | REGULATOR_CHANGE_STATUS,
|
||||
+ },
|
||||
+ .num_consumer_supplies = 1,
|
||||
+ .consumer_supplies = &beagle_vaux3_supply,
|
||||
+};
|
||||
+
|
||||
+/* VAUX4 for CAM_2V8 */
|
||||
+static struct regulator_init_data beagle_vaux4 = {
|
||||
+ .constraints = {
|
||||
+ .min_uV = 1800000,
|
||||
+ .max_uV = 1800000,
|
||||
+ .apply_uV = true,
|
||||
+ .valid_modes_mask = REGULATOR_MODE_NORMAL
|
||||
+ | REGULATOR_MODE_STANDBY,
|
||||
+ .valid_ops_mask = REGULATOR_CHANGE_MODE
|
||||
+ | REGULATOR_CHANGE_STATUS,
|
||||
+ },
|
||||
+ .num_consumer_supplies = 1,
|
||||
+ .consumer_supplies = &beagle_vaux4_supply,
|
||||
+};
|
||||
+
|
||||
static int beagle_twl_gpio_setup(struct device *dev,
|
||||
unsigned gpio, unsigned ngpio)
|
||||
{
|
||||
@@ -504,6 +542,16 @@ static int beagle_twl_gpio_setup(struct device *dev,
|
||||
pr_err("%s: unable to configure EHCI_nOC\n", __func__);
|
||||
}
|
||||
|
||||
+ if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
|
||||
+ /*
|
||||
+ * Power on camera interface - only on pre-production, not
|
||||
+ * needed on production boards
|
||||
+ */
|
||||
+ gpio_request(gpio + 2, "CAM_EN");
|
||||
+ gpio_direction_output(gpio + 2, 1);
|
||||
+ }
|
||||
+
|
||||
+
|
||||
/*
|
||||
* TWL4030_GPIO_MAX + 0 == ledA, EHCI nEN_USB_PWR (out, XM active
|
||||
* high / others active low)
|
||||
@@ -651,6 +699,8 @@ static struct twl4030_platform_data beagle_twldata = {
|
||||
.vsim = &beagle_vsim,
|
||||
.vdac = &beagle_vdac,
|
||||
.vpll2 = &beagle_vpll2,
|
||||
+ .vaux3 = &beagle_vaux3,
|
||||
+ .vaux4 = &beagle_vaux4,
|
||||
};
|
||||
|
||||
static struct i2c_board_info __initdata beagle_i2c1_boardinfo[] = {
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
From aa93263ed7827e33148396656b7e7ab4579509a5 Mon Sep 17 00:00:00 2001
|
||||
From: Koen Kooi <koen@dominion.thruhere.net>
|
||||
Date: Wed, 25 May 2011 08:57:40 +0200
|
||||
Subject: [PATCH 5/7] OMAP3: beagle: HACK! add in 1GHz OPP
|
||||
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/board-omap3beagle.c | 2 ++
|
||||
1 files changed, 2 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
index 211cbdf..221bfda 100644
|
||||
--- a/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
@@ -911,11 +911,13 @@ static void __init beagle_opp_init(void)
|
||||
/* Enable MPU 1GHz and lower opps */
|
||||
dev = &mh->od->pdev.dev;
|
||||
r = opp_enable(dev, 800000000);
|
||||
+ r |= opp_enable(dev, 1000000000);
|
||||
/* TODO: MPU 1GHz needs SR and ABB */
|
||||
|
||||
/* Enable IVA 800MHz and lower opps */
|
||||
dev = &dh->od->pdev.dev;
|
||||
r |= opp_enable(dev, 660000000);
|
||||
+ r |= opp_enable(dev, 800000000);
|
||||
/* TODO: DSP 800MHz needs SR and ABB */
|
||||
if (r) {
|
||||
pr_err("%s: failed to enable higher opp %d\n",
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
From dd2c7ba245ec1b17e3d323a6c4a1cad9697dbbbe Mon Sep 17 00:00:00 2001
|
||||
From: Koen Kooi <koen@dominion.thruhere.net>
|
||||
Date: Wed, 15 Jun 2011 16:25:50 +0200
|
||||
Subject: [PATCH 6/7] OMAP3: BEAGLE: fix RTC
|
||||
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/board-omap3beagle.c | 3 +++
|
||||
1 files changed, 3 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
index 221bfda..61564a4 100644
|
||||
--- a/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
@@ -941,6 +941,9 @@ static void __init omap3_beagle_init(void)
|
||||
omap3_beagle_init_rev();
|
||||
omap3_beagle_i2c_init();
|
||||
|
||||
+ /* Ensure msecure is mux'd to be able to set the RTC. */
|
||||
+ omap_mux_init_signal("sys_drm_msecure", OMAP_PIN_OFF_OUTPUT_HIGH);
|
||||
+
|
||||
if (cpu_is_omap3630()) {
|
||||
gpio_buttons[0].gpio = 4;
|
||||
}
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
From bd0b2f97c48aa6aac0c6a494f1c6ba5af5de486b Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <steve@sakoman.com>
|
||||
Date: Mon, 18 Jul 2011 23:13:41 -0500
|
||||
Subject: [PATCH] omap_hsmmc: Set dto to max value of 14 to avoid SD Card timeouts
|
||||
|
||||
This fixes MMC errors due to timeouts on certain SD Cards following suggestions
|
||||
to set dto to 14 by Jason Kridner and Steven Kipisz
|
||||
|
||||
Details of the issue:
|
||||
http://talk.maemo.org/showthread.php?p=1000707#post1000707
|
||||
|
||||
This fix was originally proposed by Sukumar Ghoral of TI.
|
||||
---
|
||||
drivers/mmc/host/omap_hsmmc.c | 3 +++
|
||||
1 files changed, 3 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
|
||||
index 9646a75..7443647 100644
|
||||
--- a/drivers/mmc/host/omap_hsmmc.c
|
||||
+++ b/drivers/mmc/host/omap_hsmmc.c
|
||||
@@ -1049,6 +1049,9 @@ static void set_data_timeout(struct omap_hsmmc_host *host,
|
||||
dto = 14;
|
||||
}
|
||||
|
||||
+ /* Set dto to max value of 14 to avoid SD Card timeouts */
|
||||
+ dto = 14;
|
||||
+
|
||||
reg &= ~DTO_MASK;
|
||||
reg |= dto << DTO_SHIFT;
|
||||
OMAP_HSMMC_WRITE(host->base, SYSCTL, reg);
|
||||
--
|
||||
1.7.0.4
|
||||
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
From 101b0aedf8152711847e2f9f347d267a3ac7f287 Mon Sep 17 00:00:00 2001
|
||||
From: Sanjeev Premi <premi@ti.com>
|
||||
Date: Fri, 24 Jun 2011 16:23:45 +0000
|
||||
Subject: [PATCH 7/7] omap3: beagle: Use GPTIMERi 1 for clockevents
|
||||
|
||||
The current selection of the GPTIMER on was result of
|
||||
a hardware issue in early versions of the Beagleboards
|
||||
(Ax and B1 thru B4). [1] [2]
|
||||
|
||||
Its been long since the hardware issue has been fixed.
|
||||
This patch uses GPTIMER 1 for all newer board revisions
|
||||
incl. Beagleboard XM.
|
||||
|
||||
[1] http://thread.gmane.org/gmane.comp.hardware.beagleboard.general/91
|
||||
[2] Errata #7 at http://elinux.org/BeagleBoard#Errata
|
||||
|
||||
Signed-off-by: Sanjeev Premi <premi@ti.com>
|
||||
Cc: Paul Walmsley <paul@pwsan.com>
|
||||
Reviewed-by: Paul Walmsley <paul@pwsan.com>
|
||||
---
|
||||
arch/arm/mach-omap2/board-omap3beagle.c | 5 ++++-
|
||||
1 files changed, 4 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
index 61564a4..20d5912 100644
|
||||
--- a/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
@@ -806,7 +806,10 @@ static void __init omap3_beagle_init_irq(void)
|
||||
{
|
||||
omap_init_irq();
|
||||
#ifdef CONFIG_OMAP_32K_TIMER
|
||||
- omap2_gp_clockevent_set_gptimer(12);
|
||||
+ if (omap3_beagle_version == OMAP3BEAGLE_BOARD_AXBX)
|
||||
+ omap2_gp_clockevent_set_gptimer(12);
|
||||
+ else
|
||||
+ omap2_gp_clockevent_set_gptimer(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
-859
@@ -1,859 +0,0 @@
|
||||
From e630a914bf14bf190feaf4a2cc57f6b27c4024e1 Mon Sep 17 00:00:00 2001
|
||||
From: Javier Martin <javier.martin@vista-silicon.com>
|
||||
Date: Wed, 1 Jun 2011 17:36:48 +0200
|
||||
Subject: [PATCH 1/3] Add driver for Aptina (Micron) mt9p031 sensor.
|
||||
|
||||
Clock frequency of 57MHz used in previous version was wrong since
|
||||
when VDD_IO is 1.8V it can only support 48MHz.
|
||||
|
||||
Two new platform flags have been added:
|
||||
|
||||
- vdd_io: indicates whether the chip is powered with 1.8 or 2.8 VDD_IO.
|
||||
So that it can use the maximum allowed frequency.
|
||||
- version: monochrome and color versions of the chip have exactly
|
||||
the same ID, so the only way to select one of them is through
|
||||
platform data.
|
||||
|
||||
Internal PLL is now used to generate PIXCLK depending on VDD_IO.
|
||||
|
||||
Signed-off-by: Javier Martin <javier.martin@vista-silicon.com>
|
||||
---
|
||||
drivers/media/video/Kconfig | 7 +
|
||||
drivers/media/video/Makefile | 1 +
|
||||
drivers/media/video/mt9p031.c | 763 +++++++++++++++++++++++++++++++++++++++++
|
||||
include/media/mt9p031.h | 23 ++
|
||||
4 files changed, 794 insertions(+), 0 deletions(-)
|
||||
create mode 100644 drivers/media/video/mt9p031.c
|
||||
create mode 100644 include/media/mt9p031.h
|
||||
|
||||
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
|
||||
index 00f51dd..cb87e35 100644
|
||||
--- a/drivers/media/video/Kconfig
|
||||
+++ b/drivers/media/video/Kconfig
|
||||
@@ -329,6 +329,13 @@ config VIDEO_OV7670
|
||||
OV7670 VGA camera. It currently only works with the M88ALP01
|
||||
controller.
|
||||
|
||||
+config VIDEO_MT9P031
|
||||
+ tristate "Aptina MT9P031 support"
|
||||
+ depends on I2C && VIDEO_V4L2
|
||||
+ ---help---
|
||||
+ This is a Video4Linux2 sensor-level driver for the Aptina
|
||||
+ (Micron) mt9p031 5 Mpixel camera.
|
||||
+
|
||||
config VIDEO_MT9V011
|
||||
tristate "Micron mt9v011 sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
|
||||
index ace5d8b..912b29b 100644
|
||||
--- a/drivers/media/video/Makefile
|
||||
+++ b/drivers/media/video/Makefile
|
||||
@@ -65,6 +65,7 @@ obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
|
||||
obj-$(CONFIG_VIDEO_OV7670) += ov7670.o
|
||||
obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
|
||||
obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
|
||||
+obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
|
||||
obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
|
||||
obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o
|
||||
obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o
|
||||
diff --git a/drivers/media/video/mt9p031.c b/drivers/media/video/mt9p031.c
|
||||
new file mode 100644
|
||||
index 0000000..cd830b1
|
||||
--- /dev/null
|
||||
+++ b/drivers/media/video/mt9p031.c
|
||||
@@ -0,0 +1,763 @@
|
||||
+/*
|
||||
+ * Driver for MT9P031 CMOS Image Sensor from Aptina
|
||||
+ *
|
||||
+ * Copyright (C) 2011, Javier Martin <javier.martin@vista-silicon.com>
|
||||
+ *
|
||||
+ * Copyright (C) 2011, Guennadi Liakhovetski <g.liakhovetski@gmx.de>
|
||||
+ *
|
||||
+ * Based on the MT9V032 driver and Bastian Hecht's code.
|
||||
+ *
|
||||
+ * 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.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/device.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/log2.h>
|
||||
+#include <linux/pm.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <media/v4l2-subdev.h>
|
||||
+#include <linux/videodev2.h>
|
||||
+
|
||||
+#include <media/mt9p031.h>
|
||||
+#include <media/v4l2-chip-ident.h>
|
||||
+#include <media/v4l2-subdev.h>
|
||||
+#include <media/v4l2-device.h>
|
||||
+
|
||||
+#define MT9P031_EXTCLK_FREQ 20000000
|
||||
+
|
||||
+#define MT9P031_CHIP_VERSION 0x00
|
||||
+#define MT9P031_CHIP_VERSION_VALUE 0x1801
|
||||
+#define MT9P031_ROW_START 0x01
|
||||
+#define MT9P031_ROW_START_MIN 1
|
||||
+#define MT9P031_ROW_START_MAX 2004
|
||||
+#define MT9P031_ROW_START_DEF 54
|
||||
+#define MT9P031_COLUMN_START 0x02
|
||||
+#define MT9P031_COLUMN_START_MIN 1
|
||||
+#define MT9P031_COLUMN_START_MAX 2750
|
||||
+#define MT9P031_COLUMN_START_DEF 16
|
||||
+#define MT9P031_WINDOW_HEIGHT 0x03
|
||||
+#define MT9P031_WINDOW_HEIGHT_MIN 2
|
||||
+#define MT9P031_WINDOW_HEIGHT_MAX 2003
|
||||
+#define MT9P031_WINDOW_HEIGHT_DEF 2003
|
||||
+#define MT9P031_WINDOW_WIDTH 0x04
|
||||
+#define MT9P031_WINDOW_WIDTH_MIN 18
|
||||
+#define MT9P031_WINDOW_WIDTH_MAX 2751
|
||||
+#define MT9P031_WINDOW_WIDTH_DEF 2751
|
||||
+#define MT9P031_H_BLANKING 0x05
|
||||
+#define MT9P031_H_BLANKING_VALUE 0
|
||||
+#define MT9P031_V_BLANKING 0x06
|
||||
+#define MT9P031_V_BLANKING_VALUE 25
|
||||
+#define MT9P031_OUTPUT_CONTROL 0x07
|
||||
+#define MT9P031_OUTPUT_CONTROL_CEN 2
|
||||
+#define MT9P031_OUTPUT_CONTROL_SYN 1
|
||||
+#define MT9P031_SHUTTER_WIDTH_UPPER 0x08
|
||||
+#define MT9P031_SHUTTER_WIDTH 0x09
|
||||
+#define MT9P031_PLL_CONTROL 0x10
|
||||
+#define MT9P031_PLL_CONTROL_PWROFF 0x0050
|
||||
+#define MT9P031_PLL_CONTROL_PWRON 0x0051
|
||||
+#define MT9P031_PLL_CONTROL_USEPLL 0x0052
|
||||
+#define MT9P031_PLL_CONFIG_1 0x11
|
||||
+#define MT9P031_PLL_CONFIG_1_M_48MHZ 0x5000
|
||||
+#define MT9P031_PLL_CONFIG_1_N_48MHZ 0x05
|
||||
+#define MT9P031_PLL_CONFIG_1_M_96MHZ 0x3600
|
||||
+#define MT9P031_PLL_CONFIG_1_N_96MHZ 0x05
|
||||
+#define MT9P031_PLL_CONFIG_2 0x12
|
||||
+#define MT9P031_PLL_CONFIG_2_P1_48MHZ 5
|
||||
+#define MT9P031_PLL_CONFIG_2_P1_96MHZ 2
|
||||
+#define MT9P031_PIXEL_CLOCK_CONTROL 0x0a
|
||||
+#define MT9P031_FRAME_RESTART 0x0b
|
||||
+#define MT9P031_SHUTTER_DELAY 0x0c
|
||||
+#define MT9P031_RST 0x0d
|
||||
+#define MT9P031_RST_ENABLE 1
|
||||
+#define MT9P031_RST_DISABLE 0
|
||||
+#define MT9P031_READ_MODE_1 0x1e
|
||||
+#define MT9P031_READ_MODE_2 0x20
|
||||
+#define MT9P031_READ_MODE_2_ROW_MIR 0x8000
|
||||
+#define MT9P031_READ_MODE_2_COL_MIR 0x4000
|
||||
+#define MT9P031_ROW_ADDRESS_MODE 0x22
|
||||
+#define MT9P031_COLUMN_ADDRESS_MODE 0x23
|
||||
+#define MT9P031_GLOBAL_GAIN 0x35
|
||||
+
|
||||
+struct mt9p031 {
|
||||
+ struct v4l2_subdev subdev;
|
||||
+ struct media_pad pad;
|
||||
+ struct v4l2_rect rect; /* Sensor window */
|
||||
+ struct v4l2_mbus_framefmt format;
|
||||
+ struct mt9p031_platform_data *pdata;
|
||||
+ struct mutex power_lock; /* lock to protect power_count */
|
||||
+ int power_count;
|
||||
+ u16 xskip;
|
||||
+ u16 yskip;
|
||||
+ /* cache register values */
|
||||
+ u16 output_control;
|
||||
+};
|
||||
+
|
||||
+static struct mt9p031 *to_mt9p031(const struct i2c_client *client)
|
||||
+{
|
||||
+ return container_of(i2c_get_clientdata(client), struct mt9p031, subdev);
|
||||
+}
|
||||
+
|
||||
+static int reg_read(struct i2c_client *client, const u8 reg)
|
||||
+{
|
||||
+ s32 data = i2c_smbus_read_word_data(client, reg);
|
||||
+ return data < 0 ? data : swab16(data);
|
||||
+}
|
||||
+
|
||||
+static int reg_write(struct i2c_client *client, const u8 reg,
|
||||
+ const u16 data)
|
||||
+{
|
||||
+ return i2c_smbus_write_word_data(client, reg, swab16(data));
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_set_output_control(struct mt9p031 *mt9p031, u16 clear,
|
||||
+ u16 set)
|
||||
+{
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
|
||||
+ u16 value = (mt9p031->output_control & ~clear) | set;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = reg_write(client, MT9P031_OUTPUT_CONTROL, value);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ mt9p031->output_control = value;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_reset(struct i2c_client *client)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = to_mt9p031(client);
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Disable chip output, synchronous option update */
|
||||
+ ret = reg_write(client, MT9P031_RST, MT9P031_RST_ENABLE);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = reg_write(client, MT9P031_RST, MT9P031_RST_DISABLE);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ return mt9p031_set_output_control(mt9p031,
|
||||
+ MT9P031_OUTPUT_CONTROL_CEN, 0);
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_power_on(struct mt9p031 *mt9p031)
|
||||
+{
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
|
||||
+ int ret;
|
||||
+
|
||||
+ /* Ensure RESET_BAR is low */
|
||||
+ if (mt9p031->pdata->reset) {
|
||||
+ mt9p031->pdata->reset(&mt9p031->subdev, 1);
|
||||
+ msleep(1);
|
||||
+ }
|
||||
+ /* Emable clock */
|
||||
+ if (mt9p031->pdata->set_xclk)
|
||||
+ mt9p031->pdata->set_xclk(&mt9p031->subdev, MT9P031_EXTCLK_FREQ);
|
||||
+ /* Now RESET_BAR must be high */
|
||||
+ if (mt9p031->pdata->reset) {
|
||||
+ mt9p031->pdata->reset(&mt9p031->subdev, 0);
|
||||
+ msleep(1);
|
||||
+ }
|
||||
+ /* soft reset */
|
||||
+ ret = mt9p031_reset(client);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(&client->dev, "Failed to reset the camera\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static void mt9p031_power_off(struct mt9p031 *mt9p031)
|
||||
+{
|
||||
+ if (mt9p031->pdata->reset) {
|
||||
+ mt9p031->pdata->reset(&mt9p031->subdev, 1);
|
||||
+ msleep(1);
|
||||
+ }
|
||||
+ if (mt9p031->pdata->set_xclk)
|
||||
+ mt9p031->pdata->set_xclk(&mt9p031->subdev, 0);
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_enum_mbus_code(struct v4l2_subdev *sd,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_mbus_code_enum *code)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+
|
||||
+ if (code->pad || code->index)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ code->code = mt9p031->format.code;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct v4l2_mbus_framefmt *mt9p031_get_pad_format(
|
||||
+ struct mt9p031 *mt9p031,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ unsigned int pad, u32 which)
|
||||
+{
|
||||
+ switch (which) {
|
||||
+ case V4L2_SUBDEV_FORMAT_TRY:
|
||||
+ return v4l2_subdev_get_try_format(fh, pad);
|
||||
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
|
||||
+ return &mt9p031->format;
|
||||
+ default:
|
||||
+ return NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static struct v4l2_rect *mt9p031_get_pad_crop(struct mt9p031 *mt9p031,
|
||||
+ struct v4l2_subdev_fh *fh, unsigned int pad, u32 which)
|
||||
+{
|
||||
+ switch (which) {
|
||||
+ case V4L2_SUBDEV_FORMAT_TRY:
|
||||
+ return v4l2_subdev_get_try_crop(fh, pad);
|
||||
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
|
||||
+ return &mt9p031->rect;
|
||||
+ default:
|
||||
+ return NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_get_crop(struct v4l2_subdev *sd,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_crop *crop)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+ struct v4l2_rect *rect = mt9p031_get_pad_crop(mt9p031, fh, crop->pad,
|
||||
+ crop->which);
|
||||
+ if (!rect)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ crop->rect = *rect;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static u16 mt9p031_skip_for_crop(s32 source, s32 *target, s32 max_skip)
|
||||
+{
|
||||
+ unsigned int skip;
|
||||
+
|
||||
+ if (source - source / 4 < *target) {
|
||||
+ *target = source;
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ skip = DIV_ROUND_CLOSEST(source, *target);
|
||||
+ if (skip > max_skip)
|
||||
+ skip = max_skip;
|
||||
+ *target = 2 * DIV_ROUND_UP(source, 2 * skip);
|
||||
+
|
||||
+ return skip;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_set_params(struct i2c_client *client,
|
||||
+ struct v4l2_rect *rect, u16 xskip, u16 yskip)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = to_mt9p031(client);
|
||||
+ int ret;
|
||||
+ u16 xbin, ybin;
|
||||
+ const u16 hblank = MT9P031_H_BLANKING_VALUE,
|
||||
+ vblank = MT9P031_V_BLANKING_VALUE;
|
||||
+ __s32 left;
|
||||
+
|
||||
+ /*
|
||||
+ * TODO: Attention! When implementing horizontal flipping, adjust
|
||||
+ * alignment according to R2 "Column Start" description in the datasheet
|
||||
+ */
|
||||
+ if (xskip & 1) {
|
||||
+ xbin = 1;
|
||||
+ left = rect->left & (~3);
|
||||
+ } else if (xskip & 2) {
|
||||
+ xbin = 2;
|
||||
+ left = rect->left & (~7);
|
||||
+ } else {
|
||||
+ xbin = 4;
|
||||
+ left = rect->left & (~15);
|
||||
+ }
|
||||
+ ybin = min(yskip, (u16)4);
|
||||
+
|
||||
+ /* Disable register update, reconfigure atomically */
|
||||
+ ret = mt9p031_set_output_control(mt9p031, 0,
|
||||
+ MT9P031_OUTPUT_CONTROL_SYN);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ dev_dbg(&client->dev, "skip %u:%u, rect %ux%u@%u:%u\n",
|
||||
+ xskip, yskip, rect->width, rect->height, rect->left, rect->top);
|
||||
+
|
||||
+ /* Blanking and start values - default... */
|
||||
+ ret = reg_write(client, MT9P031_H_BLANKING, hblank);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = reg_write(client, MT9P031_V_BLANKING, vblank);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = reg_write(client, MT9P031_COLUMN_ADDRESS_MODE,
|
||||
+ ((xbin - 1) << 4) | (xskip - 1));
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = reg_write(client, MT9P031_ROW_ADDRESS_MODE,
|
||||
+ ((ybin - 1) << 4) | (yskip - 1));
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ dev_dbg(&client->dev, "new physical left %u, top %u\n",
|
||||
+ rect->left, rect->top);
|
||||
+
|
||||
+ ret = reg_write(client, MT9P031_COLUMN_START,
|
||||
+ rect->left);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = reg_write(client, MT9P031_ROW_START,
|
||||
+ rect->top);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = reg_write(client, MT9P031_WINDOW_WIDTH,
|
||||
+ rect->width - 1);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = reg_write(client, MT9P031_WINDOW_HEIGHT,
|
||||
+ rect->height - 1);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Re-enable register update, commit all changes */
|
||||
+ ret = mt9p031_set_output_control(mt9p031,
|
||||
+ MT9P031_OUTPUT_CONTROL_SYN, 0);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ mt9p031->xskip = xskip;
|
||||
+ mt9p031->yskip = yskip;
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_set_crop(struct v4l2_subdev *sd,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_crop *crop)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+ struct v4l2_mbus_framefmt *f;
|
||||
+ struct v4l2_rect *c;
|
||||
+ struct v4l2_rect rect;
|
||||
+ u16 xskip, yskip;
|
||||
+ s32 width, height;
|
||||
+
|
||||
+ dev_dbg(mt9p031->subdev.v4l2_dev->dev, "%s(%ux%u@%u:%u : %u)\n",
|
||||
+ __func__, crop->rect.width, crop->rect.height,
|
||||
+ crop->rect.left, crop->rect.top, crop->which);
|
||||
+
|
||||
+ /*
|
||||
+ * Clamp the crop rectangle boundaries and align them to a multiple of 2
|
||||
+ * pixels.
|
||||
+ */
|
||||
+ rect.width = ALIGN(clamp(crop->rect.width,
|
||||
+ MT9P031_WINDOW_WIDTH_MIN,
|
||||
+ MT9P031_WINDOW_WIDTH_MAX), 2);
|
||||
+ rect.height = ALIGN(clamp(crop->rect.height,
|
||||
+ MT9P031_WINDOW_HEIGHT_MIN,
|
||||
+ MT9P031_WINDOW_HEIGHT_MAX), 2);
|
||||
+ rect.left = ALIGN(clamp(crop->rect.left,
|
||||
+ MT9P031_COLUMN_START_MIN,
|
||||
+ MT9P031_COLUMN_START_MAX), 2);
|
||||
+ rect.top = ALIGN(clamp(crop->rect.top,
|
||||
+ MT9P031_ROW_START_MIN,
|
||||
+ MT9P031_ROW_START_MAX), 2);
|
||||
+
|
||||
+ c = mt9p031_get_pad_crop(mt9p031, fh, crop->pad, crop->which);
|
||||
+
|
||||
+ if (rect.width != c->width || rect.height != c->height) {
|
||||
+ /*
|
||||
+ * Reset the output image size if the crop rectangle size has
|
||||
+ * been modified.
|
||||
+ */
|
||||
+ f = mt9p031_get_pad_format(mt9p031, fh, crop->pad,
|
||||
+ crop->which);
|
||||
+ width = f->width;
|
||||
+ height = f->height;
|
||||
+
|
||||
+ xskip = mt9p031_skip_for_crop(rect.width, &width, 7);
|
||||
+ yskip = mt9p031_skip_for_crop(rect.height, &height, 8);
|
||||
+ } else {
|
||||
+ xskip = mt9p031->xskip;
|
||||
+ yskip = mt9p031->yskip;
|
||||
+ f = NULL;
|
||||
+ }
|
||||
+ if (f) {
|
||||
+ f->width = width;
|
||||
+ f->height = height;
|
||||
+ }
|
||||
+
|
||||
+ *c = rect;
|
||||
+ crop->rect = rect;
|
||||
+
|
||||
+ mt9p031->xskip = xskip;
|
||||
+ mt9p031->yskip = yskip;
|
||||
+ mt9p031->rect = *c;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_get_format(struct v4l2_subdev *sd,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_format *fmt)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+
|
||||
+ fmt->format =
|
||||
+ *mt9p031_get_pad_format(mt9p031, fh, fmt->pad, fmt->which);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static u16 mt9p031_skip_for_scale(s32 *source, s32 target,
|
||||
+ s32 max_skip, s32 max)
|
||||
+{
|
||||
+ unsigned int skip;
|
||||
+
|
||||
+ if (*source - *source / 4 < target) {
|
||||
+ *source = target;
|
||||
+ return 1;
|
||||
+ }
|
||||
+
|
||||
+ skip = min(max, *source + target / 2) / target;
|
||||
+ if (skip > max_skip)
|
||||
+ skip = max_skip;
|
||||
+ *source = target * skip;
|
||||
+
|
||||
+ return skip;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_set_format(struct v4l2_subdev *sd,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_format *format)
|
||||
+{
|
||||
+ struct v4l2_mbus_framefmt *__format;
|
||||
+ struct v4l2_rect *__crop, rect;
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+ unsigned int width;
|
||||
+ unsigned int height;
|
||||
+ u16 xskip, yskip;
|
||||
+
|
||||
+ __crop = mt9p031_get_pad_crop(mt9p031, fh, format->pad, format->which);
|
||||
+
|
||||
+ width = clamp_t(int, ALIGN(format->format.width, 2), 2,
|
||||
+ MT9P031_WINDOW_WIDTH_MAX);
|
||||
+ height = clamp_t(int, ALIGN(format->format.height, 2), 2,
|
||||
+ MT9P031_WINDOW_HEIGHT_MAX);
|
||||
+
|
||||
+ rect.width = __crop->width;
|
||||
+ rect.height = __crop->height;
|
||||
+
|
||||
+ xskip = mt9p031_skip_for_scale(&rect.width, width, 7,
|
||||
+ MT9P031_WINDOW_WIDTH_MAX);
|
||||
+ if (rect.width + __crop->left > MT9P031_WINDOW_WIDTH_MAX)
|
||||
+ rect.left = (MT9P031_WINDOW_WIDTH_MAX - rect.width) / 2;
|
||||
+ else
|
||||
+ rect.left = __crop->left;
|
||||
+ yskip = mt9p031_skip_for_scale(&rect.height, height, 8,
|
||||
+ MT9P031_WINDOW_HEIGHT_MAX);
|
||||
+ if (rect.height + __crop->top > MT9P031_WINDOW_HEIGHT_MAX)
|
||||
+ rect.top = (MT9P031_WINDOW_HEIGHT_MAX - rect.height) / 2;
|
||||
+ else
|
||||
+ rect.top = __crop->top;
|
||||
+
|
||||
+ dev_dbg(mt9p031->subdev.v4l2_dev->dev, "%s(%ux%u : %u)\n", __func__,
|
||||
+ width, height, format->which);
|
||||
+ if (__crop)
|
||||
+ *__crop = rect;
|
||||
+
|
||||
+ __format = mt9p031_get_pad_format(mt9p031, fh, format->pad,
|
||||
+ format->which);
|
||||
+ __format->width = width;
|
||||
+ __format->height = height;
|
||||
+ format->format = *__format;
|
||||
+
|
||||
+ mt9p031->xskip = xskip;
|
||||
+ mt9p031->yskip = yskip;
|
||||
+ mt9p031->rect = *__crop;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_pll_enable(struct i2c_client *client)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = to_mt9p031(client);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = reg_write(client, MT9P031_PLL_CONTROL, MT9P031_PLL_CONTROL_PWRON);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Always set the maximum frequency allowed by VDD_IO */
|
||||
+ if (mt9p031->pdata->vdd_io == MT9P031_VDD_IO_2V8) {
|
||||
+ ret = reg_write(client, MT9P031_PLL_CONFIG_1,
|
||||
+ MT9P031_PLL_CONFIG_1_M_96MHZ |
|
||||
+ MT9P031_PLL_CONFIG_1_N_96MHZ);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = reg_write(client, MT9P031_PLL_CONFIG_2,
|
||||
+ MT9P031_PLL_CONFIG_2_P1_96MHZ);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ } else {
|
||||
+ ret = reg_write(client, MT9P031_PLL_CONFIG_1,
|
||||
+ MT9P031_PLL_CONFIG_1_M_48MHZ |
|
||||
+ MT9P031_PLL_CONFIG_1_N_48MHZ);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = reg_write(client, MT9P031_PLL_CONFIG_2,
|
||||
+ MT9P031_PLL_CONFIG_2_P1_48MHZ);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ }
|
||||
+ mdelay(1);
|
||||
+ ret = reg_write(client, MT9P031_PLL_CONTROL,
|
||||
+ MT9P031_PLL_CONTROL_PWRON |
|
||||
+ MT9P031_PLL_CONTROL_USEPLL);
|
||||
+ mdelay(1);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static inline int mt9p031_pll_disable(struct i2c_client *client)
|
||||
+{
|
||||
+ return reg_write(client, MT9P031_PLL_CONTROL,
|
||||
+ MT9P031_PLL_CONTROL_PWROFF);
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
|
||||
+ struct v4l2_rect rect = mt9p031->rect;
|
||||
+ u16 xskip = mt9p031->xskip;
|
||||
+ u16 yskip = mt9p031->yskip;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (enable) {
|
||||
+ ret = mt9p031_set_params(client, &rect, xskip, yskip);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ /* Switch to master "normal" mode */
|
||||
+ ret = mt9p031_set_output_control(mt9p031, 0,
|
||||
+ MT9P031_OUTPUT_CONTROL_CEN);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = mt9p031_pll_enable(client);
|
||||
+ } else {
|
||||
+ /* Stop sensor readout */
|
||||
+ ret = mt9p031_set_output_control(mt9p031,
|
||||
+ MT9P031_OUTPUT_CONTROL_CEN, 0);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ ret = mt9p031_pll_disable(client);
|
||||
+ }
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_video_probe(struct i2c_client *client)
|
||||
+{
|
||||
+ s32 data;
|
||||
+
|
||||
+ /* Read out the chip version register */
|
||||
+ data = reg_read(client, MT9P031_CHIP_VERSION);
|
||||
+ if (data != MT9P031_CHIP_VERSION_VALUE) {
|
||||
+ dev_err(&client->dev,
|
||||
+ "No MT9P031 chip detected, register read %x\n", data);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ dev_info(&client->dev, "Detected a MT9P031 chip ID %x\n", data);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_set_power(struct v4l2_subdev *sd, int on)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ mutex_lock(&mt9p031->power_lock);
|
||||
+
|
||||
+ /*
|
||||
+ * If the power count is modified from 0 to != 0 or from != 0 to 0,
|
||||
+ * update the power state.
|
||||
+ */
|
||||
+ if (mt9p031->power_count == !on) {
|
||||
+ if (on) {
|
||||
+ ret = mt9p031_power_on(mt9p031);
|
||||
+ if (ret) {
|
||||
+ dev_err(mt9p031->subdev.v4l2_dev->dev,
|
||||
+ "Failed to power on: %d\n", ret);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ } else {
|
||||
+ mt9p031_power_off(mt9p031);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ /* Update the power count. */
|
||||
+ mt9p031->power_count += on ? 1 : -1;
|
||||
+ WARN_ON(mt9p031->power_count < 0);
|
||||
+
|
||||
+out:
|
||||
+ mutex_unlock(&mt9p031->power_lock);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_registered(struct v4l2_subdev *sd)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9p031->subdev);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = mt9p031_set_power(&mt9p031->subdev, 1);
|
||||
+ if (ret) {
|
||||
+ dev_err(&client->dev,
|
||||
+ "Failed to power on device: %d\n", ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ ret = mt9p031_video_probe(client);
|
||||
+
|
||||
+ mt9p031_set_power(&mt9p031->subdev, 0);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
+{
|
||||
+ struct mt9p031 *mt9p031;
|
||||
+ mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+
|
||||
+ mt9p031->rect.width = MT9P031_WINDOW_WIDTH_DEF;
|
||||
+ mt9p031->rect.height = MT9P031_WINDOW_HEIGHT_DEF;
|
||||
+ mt9p031->rect.left = MT9P031_COLUMN_START_DEF;
|
||||
+ mt9p031->rect.top = MT9P031_ROW_START_DEF;
|
||||
+
|
||||
+ if (mt9p031->pdata->version == MT9P031_MONOCHROME_VERSION)
|
||||
+ mt9p031->format.code = V4L2_MBUS_FMT_Y12_1X12;
|
||||
+ else
|
||||
+ mt9p031->format.code = V4L2_MBUS_FMT_SGRBG12_1X12;
|
||||
+
|
||||
+ mt9p031->format.width = MT9P031_WINDOW_WIDTH_DEF;
|
||||
+ mt9p031->format.height = MT9P031_WINDOW_HEIGHT_DEF;
|
||||
+ mt9p031->format.field = V4L2_FIELD_NONE;
|
||||
+ mt9p031->format.colorspace = V4L2_COLORSPACE_SRGB;
|
||||
+
|
||||
+ mt9p031->xskip = 1;
|
||||
+ mt9p031->yskip = 1;
|
||||
+ return mt9p031_set_power(sd, 1);
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
|
||||
+{
|
||||
+ return mt9p031_set_power(sd, 0);
|
||||
+}
|
||||
+
|
||||
+static struct v4l2_subdev_core_ops mt9p031_subdev_core_ops = {
|
||||
+ .s_power = mt9p031_set_power,
|
||||
+};
|
||||
+
|
||||
+static struct v4l2_subdev_video_ops mt9p031_subdev_video_ops = {
|
||||
+ .s_stream = mt9p031_s_stream,
|
||||
+};
|
||||
+
|
||||
+static struct v4l2_subdev_pad_ops mt9p031_subdev_pad_ops = {
|
||||
+ .enum_mbus_code = mt9p031_enum_mbus_code,
|
||||
+ .get_fmt = mt9p031_get_format,
|
||||
+ .set_fmt = mt9p031_set_format,
|
||||
+ .get_crop = mt9p031_get_crop,
|
||||
+ .set_crop = mt9p031_set_crop,
|
||||
+};
|
||||
+
|
||||
+static struct v4l2_subdev_ops mt9p031_subdev_ops = {
|
||||
+ .core = &mt9p031_subdev_core_ops,
|
||||
+ .video = &mt9p031_subdev_video_ops,
|
||||
+ .pad = &mt9p031_subdev_pad_ops,
|
||||
+};
|
||||
+
|
||||
+static const struct v4l2_subdev_internal_ops mt9p031_subdev_internal_ops = {
|
||||
+ .registered = mt9p031_registered,
|
||||
+ .open = mt9p031_open,
|
||||
+ .close = mt9p031_close,
|
||||
+};
|
||||
+
|
||||
+static int mt9p031_probe(struct i2c_client *client,
|
||||
+ const struct i2c_device_id *did)
|
||||
+{
|
||||
+ int ret;
|
||||
+ struct mt9p031 *mt9p031;
|
||||
+ struct mt9p031_platform_data *pdata = client->dev.platform_data;
|
||||
+ struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
|
||||
+
|
||||
+ if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WORD_DATA)) {
|
||||
+ dev_warn(&adapter->dev,
|
||||
+ "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ mt9p031 = kzalloc(sizeof(struct mt9p031), GFP_KERNEL);
|
||||
+ if (!mt9p031)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ mutex_init(&mt9p031->power_lock);
|
||||
+ v4l2_i2c_subdev_init(&mt9p031->subdev, client, &mt9p031_subdev_ops);
|
||||
+ mt9p031->subdev.internal_ops = &mt9p031_subdev_internal_ops;
|
||||
+
|
||||
+ mt9p031->pdata = pdata;
|
||||
+
|
||||
+ mt9p031->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||
+ ret = media_entity_init(&mt9p031->subdev.entity, 1, &mt9p031->pad, 0);
|
||||
+ if (ret)
|
||||
+ return ret;
|
||||
+
|
||||
+ mt9p031->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9p031_remove(struct i2c_client *client)
|
||||
+{
|
||||
+ struct v4l2_subdev *sd = i2c_get_clientdata(client);
|
||||
+ struct mt9p031 *mt9p031 = container_of(sd, struct mt9p031, subdev);
|
||||
+
|
||||
+ v4l2_device_unregister_subdev(sd);
|
||||
+ media_entity_cleanup(&sd->entity);
|
||||
+ kfree(mt9p031);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct i2c_device_id mt9p031_id[] = {
|
||||
+ { "mt9p031", 0 },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(i2c, mt9p031_id);
|
||||
+
|
||||
+static struct i2c_driver mt9p031_i2c_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "mt9p031",
|
||||
+ },
|
||||
+ .probe = mt9p031_probe,
|
||||
+ .remove = mt9p031_remove,
|
||||
+ .id_table = mt9p031_id,
|
||||
+};
|
||||
+
|
||||
+static int __init mt9p031_mod_init(void)
|
||||
+{
|
||||
+ return i2c_add_driver(&mt9p031_i2c_driver);
|
||||
+}
|
||||
+
|
||||
+static void __exit mt9p031_mod_exit(void)
|
||||
+{
|
||||
+ i2c_del_driver(&mt9p031_i2c_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(mt9p031_mod_init);
|
||||
+module_exit(mt9p031_mod_exit);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Aptina MT9P031 Camera driver");
|
||||
+MODULE_AUTHOR("Bastian Hecht <hechtb@gmail.com>");
|
||||
+MODULE_LICENSE("GPL v2");
|
||||
diff --git a/include/media/mt9p031.h b/include/media/mt9p031.h
|
||||
new file mode 100644
|
||||
index 0000000..27b4c75
|
||||
--- /dev/null
|
||||
+++ b/include/media/mt9p031.h
|
||||
@@ -0,0 +1,23 @@
|
||||
+#ifndef MT9P031_H
|
||||
+#define MT9P031_H
|
||||
+
|
||||
+struct v4l2_subdev;
|
||||
+
|
||||
+enum {
|
||||
+ MT9P031_COLOR_VERSION = 0,
|
||||
+ MT9P031_MONOCHROME_VERSION = 1,
|
||||
+};
|
||||
+
|
||||
+enum {
|
||||
+ MT9P031_VDD_IO_1V8 = 0,
|
||||
+ MT9P031_VDD_IO_2V8 = 1,
|
||||
+};
|
||||
+
|
||||
+struct mt9p031_platform_data {
|
||||
+ int (*set_xclk)(struct v4l2_subdev *subdev, int hz);
|
||||
+ int (*reset)(struct v4l2_subdev *subdev, int active);
|
||||
+ int vdd_io; /* MT9P031_VDD_IO_1V8 or MT9P031_VDD_IO_2V8 */
|
||||
+ int version; /* MT9P031_COLOR_VERSION or MT9P031_MONOCHROME_VERSION */
|
||||
+};
|
||||
+
|
||||
+#endif
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-853
@@ -1,853 +0,0 @@
|
||||
From ba65e798c98e9c4d331deb2b51337964336d3f78 Mon Sep 17 00:00:00 2001
|
||||
From: Detlev Casanova <detlev.casanova@gmail.com>
|
||||
Date: Sun, 28 Nov 2010 19:07:20 +0100
|
||||
Subject: [PATCH 2/3] v4l: Add mt9v032 sensor driver
|
||||
|
||||
The MT9V032 is a parallel wide VGA sensor from Aptina (formerly Micron)
|
||||
controlled through I2C.
|
||||
|
||||
The driver creates a V4L2 subdevice. It currently supports binning and
|
||||
cropping, and the gain, auto gain, exposure, auto exposure and test
|
||||
pattern controls.
|
||||
|
||||
Signed-off-by: Detlev Casanova <detlev.casanova@gmail.com>
|
||||
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
---
|
||||
drivers/media/video/Kconfig | 7 +
|
||||
drivers/media/video/Makefile | 1 +
|
||||
drivers/media/video/mt9v032.c | 773 +++++++++++++++++++++++++++++++++++++++++
|
||||
include/media/mt9v032.h | 12 +
|
||||
4 files changed, 793 insertions(+), 0 deletions(-)
|
||||
create mode 100644 drivers/media/video/mt9v032.c
|
||||
create mode 100644 include/media/mt9v032.h
|
||||
|
||||
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
|
||||
index cb87e35..3a5bc57 100644
|
||||
--- a/drivers/media/video/Kconfig
|
||||
+++ b/drivers/media/video/Kconfig
|
||||
@@ -344,6 +344,13 @@ config VIDEO_MT9V011
|
||||
mt0v011 1.3 Mpixel camera. It currently only works with the
|
||||
em28xx driver.
|
||||
|
||||
+config VIDEO_MT9V032
|
||||
+ tristate "Micron MT9V032 sensor support"
|
||||
+ depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
+ ---help---
|
||||
+ This is a Video4Linux2 sensor-level driver for the Micron
|
||||
+ MT9V032 752x480 CMOS sensor.
|
||||
+
|
||||
config VIDEO_TCM825X
|
||||
tristate "TCM825x camera sensor support"
|
||||
depends on I2C && VIDEO_V4L2
|
||||
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
|
||||
index 912b29b..6679c6a 100644
|
||||
--- a/drivers/media/video/Makefile
|
||||
+++ b/drivers/media/video/Makefile
|
||||
@@ -67,6 +67,7 @@ obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
|
||||
obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
|
||||
obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
|
||||
obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
|
||||
+obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
|
||||
obj-$(CONFIG_VIDEO_SR030PC30) += sr030pc30.o
|
||||
obj-$(CONFIG_VIDEO_NOON010PC30) += noon010pc30.o
|
||||
|
||||
diff --git a/drivers/media/video/mt9v032.c b/drivers/media/video/mt9v032.c
|
||||
new file mode 100644
|
||||
index 0000000..c64e1dc
|
||||
--- /dev/null
|
||||
+++ b/drivers/media/video/mt9v032.c
|
||||
@@ -0,0 +1,773 @@
|
||||
+/*
|
||||
+ * Driver for MT9V032 CMOS Image Sensor from Micron
|
||||
+ *
|
||||
+ * Copyright (C) 2010, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
|
||||
+ *
|
||||
+ * Based on the MT9M001 driver,
|
||||
+ *
|
||||
+ * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
|
||||
+ *
|
||||
+ * 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.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/log2.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/slab.h>
|
||||
+#include <linux/videodev2.h>
|
||||
+#include <linux/v4l2-mediabus.h>
|
||||
+
|
||||
+#include <media/mt9v032.h>
|
||||
+#include <media/v4l2-ctrls.h>
|
||||
+#include <media/v4l2-device.h>
|
||||
+#include <media/v4l2-subdev.h>
|
||||
+
|
||||
+#define MT9V032_PIXEL_ARRAY_HEIGHT 492
|
||||
+#define MT9V032_PIXEL_ARRAY_WIDTH 782
|
||||
+
|
||||
+#define MT9V032_CHIP_VERSION 0x00
|
||||
+#define MT9V032_CHIP_ID_REV1 0x1311
|
||||
+#define MT9V032_CHIP_ID_REV3 0x1313
|
||||
+#define MT9V032_COLUMN_START 0x01
|
||||
+#define MT9V032_COLUMN_START_MIN 1
|
||||
+#define MT9V032_COLUMN_START_DEF 1
|
||||
+#define MT9V032_COLUMN_START_MAX 752
|
||||
+#define MT9V032_ROW_START 0x02
|
||||
+#define MT9V032_ROW_START_MIN 4
|
||||
+#define MT9V032_ROW_START_DEF 5
|
||||
+#define MT9V032_ROW_START_MAX 482
|
||||
+#define MT9V032_WINDOW_HEIGHT 0x03
|
||||
+#define MT9V032_WINDOW_HEIGHT_MIN 1
|
||||
+#define MT9V032_WINDOW_HEIGHT_DEF 480
|
||||
+#define MT9V032_WINDOW_HEIGHT_MAX 480
|
||||
+#define MT9V032_WINDOW_WIDTH 0x04
|
||||
+#define MT9V032_WINDOW_WIDTH_MIN 1
|
||||
+#define MT9V032_WINDOW_WIDTH_DEF 752
|
||||
+#define MT9V032_WINDOW_WIDTH_MAX 752
|
||||
+#define MT9V032_HORIZONTAL_BLANKING 0x05
|
||||
+#define MT9V032_HORIZONTAL_BLANKING_MIN 43
|
||||
+#define MT9V032_HORIZONTAL_BLANKING_MAX 1023
|
||||
+#define MT9V032_VERTICAL_BLANKING 0x06
|
||||
+#define MT9V032_VERTICAL_BLANKING_MIN 4
|
||||
+#define MT9V032_VERTICAL_BLANKING_MAX 3000
|
||||
+#define MT9V032_CHIP_CONTROL 0x07
|
||||
+#define MT9V032_CHIP_CONTROL_MASTER_MODE (1 << 3)
|
||||
+#define MT9V032_CHIP_CONTROL_DOUT_ENABLE (1 << 7)
|
||||
+#define MT9V032_CHIP_CONTROL_SEQUENTIAL (1 << 8)
|
||||
+#define MT9V032_SHUTTER_WIDTH1 0x08
|
||||
+#define MT9V032_SHUTTER_WIDTH2 0x09
|
||||
+#define MT9V032_SHUTTER_WIDTH_CONTROL 0x0a
|
||||
+#define MT9V032_TOTAL_SHUTTER_WIDTH 0x0b
|
||||
+#define MT9V032_TOTAL_SHUTTER_WIDTH_MIN 1
|
||||
+#define MT9V032_TOTAL_SHUTTER_WIDTH_DEF 480
|
||||
+#define MT9V032_TOTAL_SHUTTER_WIDTH_MAX 32767
|
||||
+#define MT9V032_RESET 0x0c
|
||||
+#define MT9V032_READ_MODE 0x0d
|
||||
+#define MT9V032_READ_MODE_ROW_BIN_MASK (3 << 0)
|
||||
+#define MT9V032_READ_MODE_ROW_BIN_SHIFT 0
|
||||
+#define MT9V032_READ_MODE_COLUMN_BIN_MASK (3 << 2)
|
||||
+#define MT9V032_READ_MODE_COLUMN_BIN_SHIFT 2
|
||||
+#define MT9V032_READ_MODE_ROW_FLIP (1 << 4)
|
||||
+#define MT9V032_READ_MODE_COLUMN_FLIP (1 << 5)
|
||||
+#define MT9V032_READ_MODE_DARK_COLUMNS (1 << 6)
|
||||
+#define MT9V032_READ_MODE_DARK_ROWS (1 << 7)
|
||||
+#define MT9V032_PIXEL_OPERATION_MODE 0x0f
|
||||
+#define MT9V032_PIXEL_OPERATION_MODE_COLOR (1 << 2)
|
||||
+#define MT9V032_PIXEL_OPERATION_MODE_HDR (1 << 6)
|
||||
+#define MT9V032_ANALOG_GAIN 0x35
|
||||
+#define MT9V032_ANALOG_GAIN_MIN 16
|
||||
+#define MT9V032_ANALOG_GAIN_DEF 16
|
||||
+#define MT9V032_ANALOG_GAIN_MAX 64
|
||||
+#define MT9V032_MAX_ANALOG_GAIN 0x36
|
||||
+#define MT9V032_MAX_ANALOG_GAIN_MAX 127
|
||||
+#define MT9V032_FRAME_DARK_AVERAGE 0x42
|
||||
+#define MT9V032_DARK_AVG_THRESH 0x46
|
||||
+#define MT9V032_DARK_AVG_LOW_THRESH_MASK (255 << 0)
|
||||
+#define MT9V032_DARK_AVG_LOW_THRESH_SHIFT 0
|
||||
+#define MT9V032_DARK_AVG_HIGH_THRESH_MASK (255 << 8)
|
||||
+#define MT9V032_DARK_AVG_HIGH_THRESH_SHIFT 8
|
||||
+#define MT9V032_ROW_NOISE_CORR_CONTROL 0x70
|
||||
+#define MT9V032_ROW_NOISE_CORR_ENABLE (1 << 5)
|
||||
+#define MT9V032_ROW_NOISE_CORR_USE_BLK_AVG (1 << 7)
|
||||
+#define MT9V032_PIXEL_CLOCK 0x74
|
||||
+#define MT9V032_PIXEL_CLOCK_INV_LINE (1 << 0)
|
||||
+#define MT9V032_PIXEL_CLOCK_INV_FRAME (1 << 1)
|
||||
+#define MT9V032_PIXEL_CLOCK_XOR_LINE (1 << 2)
|
||||
+#define MT9V032_PIXEL_CLOCK_CONT_LINE (1 << 3)
|
||||
+#define MT9V032_PIXEL_CLOCK_INV_PXL_CLK (1 << 4)
|
||||
+#define MT9V032_TEST_PATTERN 0x7f
|
||||
+#define MT9V032_TEST_PATTERN_DATA_MASK (1023 << 0)
|
||||
+#define MT9V032_TEST_PATTERN_DATA_SHIFT 0
|
||||
+#define MT9V032_TEST_PATTERN_USE_DATA (1 << 10)
|
||||
+#define MT9V032_TEST_PATTERN_GRAY_MASK (3 << 11)
|
||||
+#define MT9V032_TEST_PATTERN_GRAY_NONE (0 << 11)
|
||||
+#define MT9V032_TEST_PATTERN_GRAY_VERTICAL (1 << 11)
|
||||
+#define MT9V032_TEST_PATTERN_GRAY_HORIZONTAL (2 << 11)
|
||||
+#define MT9V032_TEST_PATTERN_GRAY_DIAGONAL (3 << 11)
|
||||
+#define MT9V032_TEST_PATTERN_ENABLE (1 << 13)
|
||||
+#define MT9V032_TEST_PATTERN_FLIP (1 << 14)
|
||||
+#define MT9V032_AEC_AGC_ENABLE 0xaf
|
||||
+#define MT9V032_AEC_ENABLE (1 << 0)
|
||||
+#define MT9V032_AGC_ENABLE (1 << 1)
|
||||
+#define MT9V032_THERMAL_INFO 0xc1
|
||||
+
|
||||
+struct mt9v032 {
|
||||
+ struct v4l2_subdev subdev;
|
||||
+ struct media_pad pad;
|
||||
+
|
||||
+ struct v4l2_mbus_framefmt format;
|
||||
+ struct v4l2_rect crop;
|
||||
+
|
||||
+ struct v4l2_ctrl_handler ctrls;
|
||||
+
|
||||
+ struct mutex power_lock;
|
||||
+ int power_count;
|
||||
+
|
||||
+ struct mt9v032_platform_data *pdata;
|
||||
+ u16 chip_control;
|
||||
+ u16 aec_agc;
|
||||
+};
|
||||
+
|
||||
+static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
|
||||
+{
|
||||
+ return container_of(sd, struct mt9v032, subdev);
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_read(struct i2c_client *client, const u8 reg)
|
||||
+{
|
||||
+ s32 data = i2c_smbus_read_word_data(client, reg);
|
||||
+ dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__,
|
||||
+ swab16(data), reg);
|
||||
+ return data < 0 ? data : swab16(data);
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_write(struct i2c_client *client, const u8 reg,
|
||||
+ const u16 data)
|
||||
+{
|
||||
+ dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__,
|
||||
+ data, reg);
|
||||
+ return i2c_smbus_write_word_data(client, reg, swab16(data));
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set)
|
||||
+{
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
+ u16 value = (mt9v032->chip_control & ~clear) | set;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_CHIP_CONTROL, value);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ mt9v032->chip_control = value;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int
|
||||
+mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
|
||||
+{
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
+ u16 value = mt9v032->aec_agc;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (enable)
|
||||
+ value |= which;
|
||||
+ else
|
||||
+ value &= ~which;
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_AEC_AGC_ENABLE, value);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ mt9v032->aec_agc = value;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_power_on(struct mt9v032 *mt9v032)
|
||||
+{
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
+ int ret;
|
||||
+
|
||||
+ if (mt9v032->pdata->set_clock) {
|
||||
+ mt9v032->pdata->set_clock(&mt9v032->subdev, 25000000);
|
||||
+ udelay(1);
|
||||
+ }
|
||||
+
|
||||
+ /* Reset the chip and stop data read out */
|
||||
+ ret = mt9v032_write(client, MT9V032_RESET, 1);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_RESET, 0);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ return mt9v032_write(client, MT9V032_CHIP_CONTROL, 0);
|
||||
+}
|
||||
+
|
||||
+static void mt9v032_power_off(struct mt9v032 *mt9v032)
|
||||
+{
|
||||
+ if (mt9v032->pdata->set_clock)
|
||||
+ mt9v032->pdata->set_clock(&mt9v032->subdev, 0);
|
||||
+}
|
||||
+
|
||||
+static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
|
||||
+{
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!on) {
|
||||
+ mt9v032_power_off(mt9v032);
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ ret = mt9v032_power_on(mt9v032);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Configure the pixel clock polarity */
|
||||
+ if (mt9v032->pdata && mt9v032->pdata->clk_pol) {
|
||||
+ ret = mt9v032_write(client, MT9V032_PIXEL_CLOCK,
|
||||
+ MT9V032_PIXEL_CLOCK_INV_PXL_CLK);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Disable the noise correction algorithm and restore the controls. */
|
||||
+ ret = mt9v032_write(client, MT9V032_ROW_NOISE_CORR_CONTROL, 0);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ return v4l2_ctrl_handler_setup(&mt9v032->ctrls);
|
||||
+}
|
||||
+
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * V4L2 subdev video operations
|
||||
+ */
|
||||
+
|
||||
+static struct v4l2_mbus_framefmt *
|
||||
+__mt9v032_get_pad_format(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh,
|
||||
+ unsigned int pad, enum v4l2_subdev_format_whence which)
|
||||
+{
|
||||
+ switch (which) {
|
||||
+ case V4L2_SUBDEV_FORMAT_TRY:
|
||||
+ return v4l2_subdev_get_try_format(fh, pad);
|
||||
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
|
||||
+ return &mt9v032->format;
|
||||
+ default:
|
||||
+ return NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static struct v4l2_rect *
|
||||
+__mt9v032_get_pad_crop(struct mt9v032 *mt9v032, struct v4l2_subdev_fh *fh,
|
||||
+ unsigned int pad, enum v4l2_subdev_format_whence which)
|
||||
+{
|
||||
+ switch (which) {
|
||||
+ case V4L2_SUBDEV_FORMAT_TRY:
|
||||
+ return v4l2_subdev_get_try_crop(fh, pad);
|
||||
+ case V4L2_SUBDEV_FORMAT_ACTIVE:
|
||||
+ return &mt9v032->crop;
|
||||
+ default:
|
||||
+ return NULL;
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
|
||||
+{
|
||||
+ const u16 mode = MT9V032_CHIP_CONTROL_MASTER_MODE
|
||||
+ | MT9V032_CHIP_CONTROL_DOUT_ENABLE
|
||||
+ | MT9V032_CHIP_CONTROL_SEQUENTIAL;
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(subdev);
|
||||
+ struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
+ struct v4l2_mbus_framefmt *format = &mt9v032->format;
|
||||
+ struct v4l2_rect *crop = &mt9v032->crop;
|
||||
+ unsigned int hratio;
|
||||
+ unsigned int vratio;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!enable)
|
||||
+ return mt9v032_set_chip_control(mt9v032, mode, 0);
|
||||
+
|
||||
+ /* Configure the window size and row/column bin */
|
||||
+ hratio = DIV_ROUND_CLOSEST(crop->width, format->width);
|
||||
+ vratio = DIV_ROUND_CLOSEST(crop->height, format->height);
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_READ_MODE,
|
||||
+ (hratio - 1) << MT9V032_READ_MODE_ROW_BIN_SHIFT |
|
||||
+ (vratio - 1) << MT9V032_READ_MODE_COLUMN_BIN_SHIFT);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_COLUMN_START, crop->left);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_ROW_START, crop->top);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_WINDOW_WIDTH, crop->width);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_WINDOW_HEIGHT, crop->height);
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ ret = mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING,
|
||||
+ max(43, 660 - crop->width));
|
||||
+ if (ret < 0)
|
||||
+ return ret;
|
||||
+
|
||||
+ /* Switch to master "normal" mode */
|
||||
+ return mt9v032_set_chip_control(mt9v032, 0, mode);
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_mbus_code_enum *code)
|
||||
+{
|
||||
+ if (code->index > 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ code->code = V4L2_MBUS_FMT_SGRBG10_1X10;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_enum_frame_size(struct v4l2_subdev *subdev,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_frame_size_enum *fse)
|
||||
+{
|
||||
+ if (fse->index >= 8 || fse->code != V4L2_MBUS_FMT_SGRBG10_1X10)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ fse->min_width = MT9V032_WINDOW_WIDTH_DEF / fse->index;
|
||||
+ fse->max_width = fse->min_width;
|
||||
+ fse->min_height = MT9V032_WINDOW_HEIGHT_DEF / fse->index;
|
||||
+ fse->max_height = fse->min_height;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_get_format(struct v4l2_subdev *subdev,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_format *format)
|
||||
+{
|
||||
+ struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
+
|
||||
+ format->format = *__mt9v032_get_pad_format(mt9v032, fh, format->pad,
|
||||
+ format->which);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_set_format(struct v4l2_subdev *subdev,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_format *format)
|
||||
+{
|
||||
+ struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
+ struct v4l2_mbus_framefmt *__format;
|
||||
+ struct v4l2_rect *__crop;
|
||||
+ unsigned int width;
|
||||
+ unsigned int height;
|
||||
+ unsigned int hratio;
|
||||
+ unsigned int vratio;
|
||||
+
|
||||
+ __crop = __mt9v032_get_pad_crop(mt9v032, fh, format->pad,
|
||||
+ format->which);
|
||||
+
|
||||
+ /* Clamp the width and height to avoid dividing by zero. */
|
||||
+ width = clamp_t(unsigned int, ALIGN(format->format.width, 2),
|
||||
+ max(__crop->width / 8, MT9V032_WINDOW_WIDTH_MIN),
|
||||
+ __crop->width);
|
||||
+ height = clamp_t(unsigned int, ALIGN(format->format.height, 2),
|
||||
+ max(__crop->height / 8, MT9V032_WINDOW_HEIGHT_MIN),
|
||||
+ __crop->height);
|
||||
+
|
||||
+ hratio = DIV_ROUND_CLOSEST(__crop->width, width);
|
||||
+ vratio = DIV_ROUND_CLOSEST(__crop->height, height);
|
||||
+
|
||||
+ __format = __mt9v032_get_pad_format(mt9v032, fh, format->pad,
|
||||
+ format->which);
|
||||
+ __format->width = __crop->width / hratio;
|
||||
+ __format->height = __crop->height / vratio;
|
||||
+
|
||||
+ format->format = *__format;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_get_crop(struct v4l2_subdev *subdev,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_crop *crop)
|
||||
+{
|
||||
+ struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
+
|
||||
+ crop->rect = *__mt9v032_get_pad_crop(mt9v032, fh, crop->pad,
|
||||
+ crop->which);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_set_crop(struct v4l2_subdev *subdev,
|
||||
+ struct v4l2_subdev_fh *fh,
|
||||
+ struct v4l2_subdev_crop *crop)
|
||||
+{
|
||||
+ struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
+ struct v4l2_mbus_framefmt *__format;
|
||||
+ struct v4l2_rect *__crop;
|
||||
+ struct v4l2_rect rect;
|
||||
+
|
||||
+ /* Clamp the crop rectangle boundaries and align them to a non multiple
|
||||
+ * of 2 pixels to ensure a GRBG Bayer pattern.
|
||||
+ */
|
||||
+ rect.left = clamp(ALIGN(crop->rect.left + 1, 2) - 1,
|
||||
+ MT9V032_COLUMN_START_MIN,
|
||||
+ MT9V032_COLUMN_START_MAX);
|
||||
+ rect.top = clamp(ALIGN(crop->rect.top + 1, 2) - 1,
|
||||
+ MT9V032_ROW_START_MIN,
|
||||
+ MT9V032_ROW_START_MAX);
|
||||
+ rect.width = clamp(ALIGN(crop->rect.width, 2),
|
||||
+ MT9V032_WINDOW_WIDTH_MIN,
|
||||
+ MT9V032_WINDOW_WIDTH_MAX);
|
||||
+ rect.height = clamp(ALIGN(crop->rect.height, 2),
|
||||
+ MT9V032_WINDOW_HEIGHT_MIN,
|
||||
+ MT9V032_WINDOW_HEIGHT_MAX);
|
||||
+
|
||||
+ rect.width = min(rect.width, MT9V032_PIXEL_ARRAY_WIDTH - rect.left);
|
||||
+ rect.height = min(rect.height, MT9V032_PIXEL_ARRAY_HEIGHT - rect.top);
|
||||
+
|
||||
+ __crop = __mt9v032_get_pad_crop(mt9v032, fh, crop->pad, crop->which);
|
||||
+
|
||||
+ if (rect.width != __crop->width || rect.height != __crop->height) {
|
||||
+ /* Reset the output image size if the crop rectangle size has
|
||||
+ * been modified.
|
||||
+ */
|
||||
+ __format = __mt9v032_get_pad_format(mt9v032, fh, crop->pad,
|
||||
+ crop->which);
|
||||
+ __format->width = rect.width;
|
||||
+ __format->height = rect.height;
|
||||
+ }
|
||||
+
|
||||
+ *__crop = rect;
|
||||
+ crop->rect = rect;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * V4L2 subdev control operations
|
||||
+ */
|
||||
+
|
||||
+#define V4L2_CID_TEST_PATTERN (V4L2_CID_USER_BASE | 0x1001)
|
||||
+
|
||||
+static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
+{
|
||||
+ struct mt9v032 *mt9v032 =
|
||||
+ container_of(ctrl->handler, struct mt9v032, ctrls);
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
|
||||
+ u16 data;
|
||||
+
|
||||
+ switch (ctrl->id) {
|
||||
+ case V4L2_CID_AUTOGAIN:
|
||||
+ return mt9v032_update_aec_agc(mt9v032, MT9V032_AGC_ENABLE,
|
||||
+ ctrl->val);
|
||||
+
|
||||
+ case V4L2_CID_GAIN:
|
||||
+ return mt9v032_write(client, MT9V032_ANALOG_GAIN, ctrl->val);
|
||||
+
|
||||
+ case V4L2_CID_EXPOSURE_AUTO:
|
||||
+ return mt9v032_update_aec_agc(mt9v032, MT9V032_AEC_ENABLE,
|
||||
+ ctrl->val);
|
||||
+
|
||||
+ case V4L2_CID_EXPOSURE:
|
||||
+ return mt9v032_write(client, MT9V032_TOTAL_SHUTTER_WIDTH,
|
||||
+ ctrl->val);
|
||||
+
|
||||
+ case V4L2_CID_TEST_PATTERN:
|
||||
+ switch (ctrl->val) {
|
||||
+ case 0:
|
||||
+ data = 0;
|
||||
+ break;
|
||||
+ case 1:
|
||||
+ data = MT9V032_TEST_PATTERN_GRAY_VERTICAL
|
||||
+ | MT9V032_TEST_PATTERN_ENABLE;
|
||||
+ break;
|
||||
+ case 2:
|
||||
+ data = MT9V032_TEST_PATTERN_GRAY_HORIZONTAL
|
||||
+ | MT9V032_TEST_PATTERN_ENABLE;
|
||||
+ break;
|
||||
+ case 3:
|
||||
+ data = MT9V032_TEST_PATTERN_GRAY_DIAGONAL
|
||||
+ | MT9V032_TEST_PATTERN_ENABLE;
|
||||
+ break;
|
||||
+ default:
|
||||
+ data = (ctrl->val << MT9V032_TEST_PATTERN_DATA_SHIFT)
|
||||
+ | MT9V032_TEST_PATTERN_USE_DATA
|
||||
+ | MT9V032_TEST_PATTERN_ENABLE
|
||||
+ | MT9V032_TEST_PATTERN_FLIP;
|
||||
+ break;
|
||||
+ }
|
||||
+
|
||||
+ return mt9v032_write(client, MT9V032_TEST_PATTERN, data);
|
||||
+ }
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct v4l2_ctrl_ops mt9v032_ctrl_ops = {
|
||||
+ .s_ctrl = mt9v032_s_ctrl,
|
||||
+};
|
||||
+
|
||||
+static const struct v4l2_ctrl_config mt9v032_ctrls[] = {
|
||||
+ {
|
||||
+ .ops = &mt9v032_ctrl_ops,
|
||||
+ .id = V4L2_CID_TEST_PATTERN,
|
||||
+ .type = V4L2_CTRL_TYPE_INTEGER,
|
||||
+ .name = "Test pattern",
|
||||
+ .min = 0,
|
||||
+ .max = 1023,
|
||||
+ .step = 1,
|
||||
+ .def = 0,
|
||||
+ .flags = 0,
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * V4L2 subdev core operations
|
||||
+ */
|
||||
+
|
||||
+static int mt9v032_set_power(struct v4l2_subdev *subdev, int on)
|
||||
+{
|
||||
+ struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ mutex_lock(&mt9v032->power_lock);
|
||||
+
|
||||
+ /* If the power count is modified from 0 to != 0 or from != 0 to 0,
|
||||
+ * update the power state.
|
||||
+ */
|
||||
+ if (mt9v032->power_count == !on) {
|
||||
+ ret = __mt9v032_set_power(mt9v032, !!on);
|
||||
+ if (ret < 0)
|
||||
+ goto done;
|
||||
+ }
|
||||
+
|
||||
+ /* Update the power count. */
|
||||
+ mt9v032->power_count += on ? 1 : -1;
|
||||
+ WARN_ON(mt9v032->power_count < 0);
|
||||
+
|
||||
+done:
|
||||
+ mutex_unlock(&mt9v032->power_lock);
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * V4L2 subdev internal operations
|
||||
+ */
|
||||
+
|
||||
+static int mt9v032_registered(struct v4l2_subdev *subdev)
|
||||
+{
|
||||
+ struct i2c_client *client = v4l2_get_subdevdata(subdev);
|
||||
+ struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
+ s32 data;
|
||||
+ int ret;
|
||||
+
|
||||
+ dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n",
|
||||
+ client->addr);
|
||||
+
|
||||
+ ret = mt9v032_power_on(mt9v032);
|
||||
+ if (ret < 0) {
|
||||
+ dev_err(&client->dev, "MT9V032 power up failed\n");
|
||||
+ return ret;
|
||||
+ }
|
||||
+
|
||||
+ /* Read and check the sensor version */
|
||||
+ data = mt9v032_read(client, MT9V032_CHIP_VERSION);
|
||||
+ if (data != MT9V032_CHIP_ID_REV1 && data != MT9V032_CHIP_ID_REV3) {
|
||||
+ dev_err(&client->dev, "MT9V032 not detected, wrong version "
|
||||
+ "0x%04x\n", data);
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ mt9v032_power_off(mt9v032);
|
||||
+
|
||||
+ dev_info(&client->dev, "MT9V032 detected at address 0x%02x\n",
|
||||
+ client->addr);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_open(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
|
||||
+{
|
||||
+ struct v4l2_mbus_framefmt *format;
|
||||
+ struct v4l2_rect *crop;
|
||||
+
|
||||
+ crop = v4l2_subdev_get_try_crop(fh, 0);
|
||||
+ crop->left = MT9V032_COLUMN_START_DEF;
|
||||
+ crop->top = MT9V032_ROW_START_DEF;
|
||||
+ crop->width = MT9V032_WINDOW_WIDTH_DEF;
|
||||
+ crop->height = MT9V032_WINDOW_HEIGHT_DEF;
|
||||
+
|
||||
+ format = v4l2_subdev_get_try_format(fh, 0);
|
||||
+ format->code = V4L2_MBUS_FMT_SGRBG10_1X10;
|
||||
+ format->width = MT9V032_WINDOW_WIDTH_DEF;
|
||||
+ format->height = MT9V032_WINDOW_HEIGHT_DEF;
|
||||
+ format->field = V4L2_FIELD_NONE;
|
||||
+ format->colorspace = V4L2_COLORSPACE_SRGB;
|
||||
+
|
||||
+ return mt9v032_set_power(subdev, 1);
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_close(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh)
|
||||
+{
|
||||
+ return mt9v032_set_power(subdev, 0);
|
||||
+}
|
||||
+
|
||||
+static struct v4l2_subdev_core_ops mt9v032_subdev_core_ops = {
|
||||
+ .s_power = mt9v032_set_power,
|
||||
+};
|
||||
+
|
||||
+static struct v4l2_subdev_video_ops mt9v032_subdev_video_ops = {
|
||||
+ .s_stream = mt9v032_s_stream,
|
||||
+};
|
||||
+
|
||||
+static struct v4l2_subdev_pad_ops mt9v032_subdev_pad_ops = {
|
||||
+ .enum_mbus_code = mt9v032_enum_mbus_code,
|
||||
+ .enum_frame_size = mt9v032_enum_frame_size,
|
||||
+ .get_fmt = mt9v032_get_format,
|
||||
+ .set_fmt = mt9v032_set_format,
|
||||
+ .get_crop = mt9v032_get_crop,
|
||||
+ .set_crop = mt9v032_set_crop,
|
||||
+};
|
||||
+
|
||||
+static struct v4l2_subdev_ops mt9v032_subdev_ops = {
|
||||
+ .core = &mt9v032_subdev_core_ops,
|
||||
+ .video = &mt9v032_subdev_video_ops,
|
||||
+ .pad = &mt9v032_subdev_pad_ops,
|
||||
+};
|
||||
+
|
||||
+static const struct v4l2_subdev_internal_ops mt9v032_subdev_internal_ops = {
|
||||
+ .registered = mt9v032_registered,
|
||||
+ .open = mt9v032_open,
|
||||
+ .close = mt9v032_close,
|
||||
+};
|
||||
+
|
||||
+/* -----------------------------------------------------------------------------
|
||||
+ * Driver initialization and probing
|
||||
+ */
|
||||
+
|
||||
+static int mt9v032_probe(struct i2c_client *client,
|
||||
+ const struct i2c_device_id *did)
|
||||
+{
|
||||
+ struct mt9v032 *mt9v032;
|
||||
+ unsigned int i;
|
||||
+ int ret;
|
||||
+
|
||||
+ if (!i2c_check_functionality(client->adapter,
|
||||
+ I2C_FUNC_SMBUS_WORD_DATA)) {
|
||||
+ dev_warn(&client->adapter->dev,
|
||||
+ "I2C-Adapter doesn't support I2C_FUNC_SMBUS_WORD\n");
|
||||
+ return -EIO;
|
||||
+ }
|
||||
+
|
||||
+ mt9v032 = kzalloc(sizeof(*mt9v032), GFP_KERNEL);
|
||||
+ if (!mt9v032)
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ mutex_init(&mt9v032->power_lock);
|
||||
+ mt9v032->pdata = client->dev.platform_data;
|
||||
+
|
||||
+ v4l2_ctrl_handler_init(&mt9v032->ctrls, ARRAY_SIZE(mt9v032_ctrls) + 4);
|
||||
+
|
||||
+ v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
|
||||
+ V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
|
||||
+ v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
|
||||
+ V4L2_CID_GAIN, MT9V032_ANALOG_GAIN_MIN,
|
||||
+ MT9V032_ANALOG_GAIN_MAX, 1, MT9V032_ANALOG_GAIN_DEF);
|
||||
+ v4l2_ctrl_new_std_menu(&mt9v032->ctrls, &mt9v032_ctrl_ops,
|
||||
+ V4L2_CID_EXPOSURE_AUTO, V4L2_EXPOSURE_MANUAL, 0,
|
||||
+ V4L2_EXPOSURE_AUTO);
|
||||
+ v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
|
||||
+ V4L2_CID_EXPOSURE, MT9V032_TOTAL_SHUTTER_WIDTH_MIN,
|
||||
+ MT9V032_TOTAL_SHUTTER_WIDTH_MAX, 1,
|
||||
+ MT9V032_TOTAL_SHUTTER_WIDTH_DEF);
|
||||
+
|
||||
+ for (i = 0; i < ARRAY_SIZE(mt9v032_ctrls); ++i)
|
||||
+ v4l2_ctrl_new_custom(&mt9v032->ctrls, &mt9v032_ctrls[i], NULL);
|
||||
+
|
||||
+ mt9v032->subdev.ctrl_handler = &mt9v032->ctrls;
|
||||
+
|
||||
+ if (mt9v032->ctrls.error)
|
||||
+ printk(KERN_INFO "%s: control initialization error %d\n",
|
||||
+ __func__, mt9v032->ctrls.error);
|
||||
+
|
||||
+ mt9v032->crop.left = MT9V032_COLUMN_START_DEF;
|
||||
+ mt9v032->crop.top = MT9V032_ROW_START_DEF;
|
||||
+ mt9v032->crop.width = MT9V032_WINDOW_WIDTH_DEF;
|
||||
+ mt9v032->crop.height = MT9V032_WINDOW_HEIGHT_DEF;
|
||||
+
|
||||
+ mt9v032->format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
|
||||
+ mt9v032->format.width = MT9V032_WINDOW_WIDTH_DEF;
|
||||
+ mt9v032->format.height = MT9V032_WINDOW_HEIGHT_DEF;
|
||||
+ mt9v032->format.field = V4L2_FIELD_NONE;
|
||||
+ mt9v032->format.colorspace = V4L2_COLORSPACE_SRGB;
|
||||
+
|
||||
+ mt9v032->aec_agc = MT9V032_AEC_ENABLE | MT9V032_AGC_ENABLE;
|
||||
+
|
||||
+ v4l2_i2c_subdev_init(&mt9v032->subdev, client, &mt9v032_subdev_ops);
|
||||
+ mt9v032->subdev.internal_ops = &mt9v032_subdev_internal_ops;
|
||||
+ mt9v032->subdev.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
|
||||
+
|
||||
+ mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE;
|
||||
+ ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0);
|
||||
+ if (ret < 0)
|
||||
+ kfree(mt9v032);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int mt9v032_remove(struct i2c_client *client)
|
||||
+{
|
||||
+ struct v4l2_subdev *subdev = i2c_get_clientdata(client);
|
||||
+ struct mt9v032 *mt9v032 = to_mt9v032(subdev);
|
||||
+
|
||||
+ v4l2_device_unregister_subdev(subdev);
|
||||
+ media_entity_cleanup(&subdev->entity);
|
||||
+ kfree(mt9v032);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static const struct i2c_device_id mt9v032_id[] = {
|
||||
+ { "mt9v032", 0 },
|
||||
+ { }
|
||||
+};
|
||||
+MODULE_DEVICE_TABLE(i2c, mt9v032_id);
|
||||
+
|
||||
+static struct i2c_driver mt9v032_driver = {
|
||||
+ .driver = {
|
||||
+ .name = "mt9v032",
|
||||
+ },
|
||||
+ .probe = mt9v032_probe,
|
||||
+ .remove = mt9v032_remove,
|
||||
+ .id_table = mt9v032_id,
|
||||
+};
|
||||
+
|
||||
+static int __init mt9v032_init(void)
|
||||
+{
|
||||
+ return i2c_add_driver(&mt9v032_driver);
|
||||
+}
|
||||
+
|
||||
+static void __exit mt9v032_exit(void)
|
||||
+{
|
||||
+ i2c_del_driver(&mt9v032_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(mt9v032_init);
|
||||
+module_exit(mt9v032_exit);
|
||||
+
|
||||
+MODULE_DESCRIPTION("Aptina MT9V032 Camera driver");
|
||||
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
|
||||
+MODULE_LICENSE("GPL");
|
||||
diff --git a/include/media/mt9v032.h b/include/media/mt9v032.h
|
||||
new file mode 100644
|
||||
index 0000000..5e27f9b
|
||||
--- /dev/null
|
||||
+++ b/include/media/mt9v032.h
|
||||
@@ -0,0 +1,12 @@
|
||||
+#ifndef _MEDIA_MT9V032_H
|
||||
+#define _MEDIA_MT9V032_H
|
||||
+
|
||||
+struct v4l2_subdev;
|
||||
+
|
||||
+struct mt9v032_platform_data {
|
||||
+ unsigned int clk_pol:1;
|
||||
+
|
||||
+ void (*set_clock)(struct v4l2_subdev *subdev, unsigned int rate);
|
||||
+};
|
||||
+
|
||||
+#endif
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-162
@@ -1,162 +0,0 @@
|
||||
From f662a8a2b9794121568903f5cc969e50eb151892 Mon Sep 17 00:00:00 2001
|
||||
From: Javier Martin <javier.martin@vista-silicon.com>
|
||||
Date: Mon, 30 May 2011 10:37:17 +0200
|
||||
Subject: [PATCH 3/3] Add support for mt9p031 (LI-5M03 module) in Beagleboard xM.
|
||||
|
||||
Since isp clocks have not been exposed yet, this patch
|
||||
includes a temporal solution for testing mt9p031 driver
|
||||
in Beagleboard xM.
|
||||
|
||||
Signed-off-by: Javier Martin <javier.martin@vista-silicon.com>
|
||||
---
|
||||
arch/arm/mach-omap2/Makefile | 1 +
|
||||
arch/arm/mach-omap2/board-omap3beagle-camera.c | 95 ++++++++++++++++++++++++
|
||||
arch/arm/mach-omap2/board-omap3beagle.c | 5 +
|
||||
3 files changed, 101 insertions(+), 0 deletions(-)
|
||||
create mode 100644 arch/arm/mach-omap2/board-omap3beagle-camera.c
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
|
||||
index 512b152..05cd983 100644
|
||||
--- a/arch/arm/mach-omap2/Makefile
|
||||
+++ b/arch/arm/mach-omap2/Makefile
|
||||
@@ -179,6 +179,7 @@ obj-$(CONFIG_MACH_OMAP_2430SDP) += board-2430sdp.o \
|
||||
hsmmc.o
|
||||
obj-$(CONFIG_MACH_OMAP_APOLLON) += board-apollon.o
|
||||
obj-$(CONFIG_MACH_OMAP3_BEAGLE) += board-omap3beagle.o \
|
||||
+ board-omap3beagle-camera.o \
|
||||
hsmmc.o
|
||||
obj-$(CONFIG_MACH_DEVKIT8000) += board-devkit8000.o \
|
||||
hsmmc.o
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle-camera.c b/arch/arm/mach-omap2/board-omap3beagle-camera.c
|
||||
new file mode 100644
|
||||
index 0000000..2632557
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle-camera.c
|
||||
@@ -0,0 +1,95 @@
|
||||
+#include <linux/gpio.h>
|
||||
+#include <linux/regulator/machine.h>
|
||||
+
|
||||
+#include <plat/i2c.h>
|
||||
+
|
||||
+#include <media/mt9p031.h>
|
||||
+#include <asm/mach-types.h>
|
||||
+#include "devices.h"
|
||||
+#include "../../../drivers/media/video/omap3isp/isp.h"
|
||||
+
|
||||
+#define MT9P031_RESET_GPIO 98
|
||||
+#define MT9P031_XCLK ISP_XCLK_A
|
||||
+
|
||||
+static struct regulator *reg_1v8, *reg_2v8;
|
||||
+
|
||||
+static int beagle_cam_set_xclk(struct v4l2_subdev *subdev, int hz)
|
||||
+{
|
||||
+ struct isp_device *isp = v4l2_dev_to_isp_device(subdev->v4l2_dev);
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = isp->platform_cb.set_xclk(isp, hz, MT9P031_XCLK);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int beagle_cam_reset(struct v4l2_subdev *subdev, int active)
|
||||
+{
|
||||
+ /* Set RESET_BAR to !active */
|
||||
+ gpio_set_value(MT9P031_RESET_GPIO, !active);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct mt9p031_platform_data beagle_mt9p031_platform_data = {
|
||||
+ .set_xclk = beagle_cam_set_xclk,
|
||||
+ .reset = beagle_cam_reset,
|
||||
+ .vdd_io = MT9P031_VDD_IO_1V8,
|
||||
+ .version = MT9P031_COLOR_VERSION,
|
||||
+};
|
||||
+
|
||||
+static struct i2c_board_info mt9p031_camera_i2c_device = {
|
||||
+ I2C_BOARD_INFO("mt9p031", 0x48),
|
||||
+ .platform_data = &beagle_mt9p031_platform_data,
|
||||
+};
|
||||
+
|
||||
+static struct isp_subdev_i2c_board_info mt9p031_camera_subdevs[] = {
|
||||
+ {
|
||||
+ .board_info = &mt9p031_camera_i2c_device,
|
||||
+ .i2c_adapter_id = 2,
|
||||
+ },
|
||||
+ { NULL, 0, },
|
||||
+};
|
||||
+
|
||||
+static struct isp_v4l2_subdevs_group beagle_camera_subdevs[] = {
|
||||
+ {
|
||||
+ .subdevs = mt9p031_camera_subdevs,
|
||||
+ .interface = ISP_INTERFACE_PARALLEL,
|
||||
+ .bus = {
|
||||
+ .parallel = {
|
||||
+ .data_lane_shift = 0,
|
||||
+ .clk_pol = 1,
|
||||
+ .bridge = ISPCTRL_PAR_BRIDGE_DISABLE,
|
||||
+ }
|
||||
+ },
|
||||
+ },
|
||||
+ { },
|
||||
+};
|
||||
+
|
||||
+static struct isp_platform_data beagle_isp_platform_data = {
|
||||
+ .subdevs = beagle_camera_subdevs,
|
||||
+};
|
||||
+
|
||||
+static int __init beagle_camera_init(void)
|
||||
+{
|
||||
+ if (!machine_is_omap3_beagle() || !cpu_is_omap3630())
|
||||
+ return 0;
|
||||
+
|
||||
+ reg_1v8 = regulator_get(NULL, "cam_1v8");
|
||||
+ if (IS_ERR(reg_1v8))
|
||||
+ pr_err("%s: cannot get cam_1v8 regulator\n", __func__);
|
||||
+ else
|
||||
+ regulator_enable(reg_1v8);
|
||||
+
|
||||
+ reg_2v8 = regulator_get(NULL, "cam_2v8");
|
||||
+ if (IS_ERR(reg_2v8))
|
||||
+ pr_err("%s: cannot get cam_2v8 regulator\n", __func__);
|
||||
+ else
|
||||
+ regulator_enable(reg_2v8);
|
||||
+
|
||||
+ omap_register_i2c_bus(2, 100, NULL, 0);
|
||||
+ gpio_request(MT9P031_RESET_GPIO, "cam_rst");
|
||||
+ gpio_direction_output(MT9P031_RESET_GPIO, 0);
|
||||
+ omap3_init_camera(&beagle_isp_platform_data);
|
||||
+ return 0;
|
||||
+}
|
||||
+late_initcall(beagle_camera_init);
|
||||
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
index 221bfda..dd6e31f 100644
|
||||
--- a/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
@@ -25,12 +25,16 @@
|
||||
#include <linux/input.h>
|
||||
#include <linux/gpio_keys.h>
|
||||
#include <linux/opp.h>
|
||||
+#include <linux/i2c.h>
|
||||
+#include <linux/mm.h>
|
||||
+#include <linux/videodev2.h>
|
||||
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/mtd/partitions.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/mmc/host.h>
|
||||
|
||||
+#include <linux/gpio.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
|
||||
@@ -48,6 +52,7 @@
|
||||
#include <plat/nand.h>
|
||||
#include <plat/usb.h>
|
||||
#include <plat/omap_device.h>
|
||||
+#include <plat/i2c.h>
|
||||
|
||||
#include "mux.h"
|
||||
#include "hsmmc.h"
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-67
@@ -1,67 +0,0 @@
|
||||
From 46be90d202c36db19e27c2991cbff401c6c3ee81 Mon Sep 17 00:00:00 2001
|
||||
From: Keshava Munegowda <Keshava_mgowda@ti.com>
|
||||
Date: Mon, 16 May 2011 14:24:58 +0530
|
||||
Subject: [PATCH 01/13] mfd: Fix omap usbhs crash when rmmoding ehci or ohci
|
||||
|
||||
The disabling of clocks and freeing GPIO are changed
|
||||
to fix the occurrence of the crash of rmmod of ehci and ohci
|
||||
drivers. The GPIOs should be freed after the spin locks are
|
||||
unlocked.
|
||||
|
||||
Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
|
||||
Acked-by: Felipe Balbi <balbi@ti.com>
|
||||
Cc: stable@kernel.org
|
||||
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
drivers/mfd/omap-usb-host.c | 27 +++++++++++++++++++--------
|
||||
1 files changed, 19 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
|
||||
index 3ab9ffa..55c5d47 100644
|
||||
--- a/drivers/mfd/omap-usb-host.c
|
||||
+++ b/drivers/mfd/omap-usb-host.c
|
||||
@@ -994,22 +994,33 @@ static void usbhs_disable(struct device *dev)
|
||||
dev_dbg(dev, "operation timed out\n");
|
||||
}
|
||||
|
||||
- if (pdata->ehci_data->phy_reset) {
|
||||
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
|
||||
- gpio_free(pdata->ehci_data->reset_gpio_port[0]);
|
||||
-
|
||||
- if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
|
||||
- gpio_free(pdata->ehci_data->reset_gpio_port[1]);
|
||||
+ if (is_omap_usbhs_rev2(omap)) {
|
||||
+ if (is_ehci_tll_mode(pdata->port_mode[0]))
|
||||
+ clk_enable(omap->usbtll_p1_fck);
|
||||
+ if (is_ehci_tll_mode(pdata->port_mode[1]))
|
||||
+ clk_enable(omap->usbtll_p2_fck);
|
||||
+ clk_disable(omap->utmi_p2_fck);
|
||||
+ clk_disable(omap->utmi_p1_fck);
|
||||
}
|
||||
|
||||
- clk_disable(omap->utmi_p2_fck);
|
||||
- clk_disable(omap->utmi_p1_fck);
|
||||
clk_disable(omap->usbtll_ick);
|
||||
clk_disable(omap->usbtll_fck);
|
||||
clk_disable(omap->usbhost_fs_fck);
|
||||
clk_disable(omap->usbhost_hs_fck);
|
||||
clk_disable(omap->usbhost_ick);
|
||||
|
||||
+ /* The gpio_free migh sleep; so unlock the spinlock */
|
||||
+ spin_unlock_irqrestore(&omap->lock, flags);
|
||||
+
|
||||
+ if (pdata->ehci_data->phy_reset) {
|
||||
+ if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
|
||||
+ gpio_free(pdata->ehci_data->reset_gpio_port[0]);
|
||||
+
|
||||
+ if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
|
||||
+ gpio_free(pdata->ehci_data->reset_gpio_port[1]);
|
||||
+ }
|
||||
+ return;
|
||||
+
|
||||
end_disble:
|
||||
spin_unlock_irqrestore(&omap->lock, flags);
|
||||
}
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
From 89a903aca8fda3dcf1a6f9a424247e772afdd44e Mon Sep 17 00:00:00 2001
|
||||
From: Axel Lin <axel.lin@gmail.com>
|
||||
Date: Sat, 14 May 2011 14:15:36 +0800
|
||||
Subject: [PATCH 02/13] mfd: Fix omap_usbhs_alloc_children error handling
|
||||
|
||||
1. Return proper error if omap_usbhs_alloc_child fails
|
||||
2. In the case of goto err_ehci, we should call platform_device_unregister(ehci)
|
||||
instead of platform_device_put(ehci) because we have already added the
|
||||
platform device to device hierarchy.
|
||||
|
||||
Signed-off-by: Axel Lin <axel.lin@gmail.com>
|
||||
Signed-off-by: Axel Lin <axel.lin@gmail.com>
|
||||
Tested-by: Keshava Munegowda <keshava_mgowda@ti.com>
|
||||
Acked-by: Felipe Balbi <balbi@ti.com>
|
||||
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
drivers/mfd/omap-usb-host.c | 4 +++-
|
||||
1 files changed, 3 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
|
||||
index 55c5d47..1717144 100644
|
||||
--- a/drivers/mfd/omap-usb-host.c
|
||||
+++ b/drivers/mfd/omap-usb-host.c
|
||||
@@ -281,6 +281,7 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
|
||||
|
||||
if (!ehci) {
|
||||
dev_err(dev, "omap_usbhs_alloc_child failed\n");
|
||||
+ ret = -ENOMEM;
|
||||
goto err_end;
|
||||
}
|
||||
|
||||
@@ -304,13 +305,14 @@ static int omap_usbhs_alloc_children(struct platform_device *pdev)
|
||||
sizeof(*ohci_data), dev);
|
||||
if (!ohci) {
|
||||
dev_err(dev, "omap_usbhs_alloc_child failed\n");
|
||||
+ ret = -ENOMEM;
|
||||
goto err_ehci;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_ehci:
|
||||
- platform_device_put(ehci);
|
||||
+ platform_device_unregister(ehci);
|
||||
|
||||
err_end:
|
||||
return ret;
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-245
@@ -1,245 +0,0 @@
|
||||
From edc881f9c4897fab11542cd5c36a33b288f702be Mon Sep 17 00:00:00 2001
|
||||
From: Keshava Munegowda <Keshava_mgowda@ti.com>
|
||||
Date: Sun, 22 May 2011 22:51:26 +0200
|
||||
Subject: [PATCH 03/13] mfd: Add omap-usbhs runtime PM support
|
||||
|
||||
The usbhs core driver does not enable/disable the interface and
|
||||
functional clocks; These clocks are handled by hwmod and runtime pm,
|
||||
hence insted of the clock enable/disable, the runtime pm APIS are
|
||||
used. however,the port clocks and tll clocks are handled
|
||||
by the usbhs core.
|
||||
|
||||
Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
|
||||
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
drivers/mfd/omap-usb-host.c | 131 +++----------------------------------------
|
||||
1 files changed, 9 insertions(+), 122 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
|
||||
index 1717144..8552195 100644
|
||||
--- a/drivers/mfd/omap-usb-host.c
|
||||
+++ b/drivers/mfd/omap-usb-host.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <linux/spinlock.h>
|
||||
#include <linux/gpio.h>
|
||||
#include <plat/usb.h>
|
||||
+#include <linux/pm_runtime.h>
|
||||
|
||||
#define USBHS_DRIVER_NAME "usbhs-omap"
|
||||
#define OMAP_EHCI_DEVICE "ehci-omap"
|
||||
@@ -146,9 +147,6 @@
|
||||
|
||||
|
||||
struct usbhs_hcd_omap {
|
||||
- struct clk *usbhost_ick;
|
||||
- struct clk *usbhost_hs_fck;
|
||||
- struct clk *usbhost_fs_fck;
|
||||
struct clk *xclk60mhsp1_ck;
|
||||
struct clk *xclk60mhsp2_ck;
|
||||
struct clk *utmi_p1_fck;
|
||||
@@ -158,8 +156,6 @@ struct usbhs_hcd_omap {
|
||||
struct clk *usbhost_p2_fck;
|
||||
struct clk *usbtll_p2_fck;
|
||||
struct clk *init_60m_fclk;
|
||||
- struct clk *usbtll_fck;
|
||||
- struct clk *usbtll_ick;
|
||||
|
||||
void __iomem *uhh_base;
|
||||
void __iomem *tll_base;
|
||||
@@ -353,46 +349,13 @@ static int __devinit usbhs_omap_probe(struct platform_device *pdev)
|
||||
omap->platdata.ehci_data = pdata->ehci_data;
|
||||
omap->platdata.ohci_data = pdata->ohci_data;
|
||||
|
||||
- omap->usbhost_ick = clk_get(dev, "usbhost_ick");
|
||||
- if (IS_ERR(omap->usbhost_ick)) {
|
||||
- ret = PTR_ERR(omap->usbhost_ick);
|
||||
- dev_err(dev, "usbhost_ick failed error:%d\n", ret);
|
||||
- goto err_end;
|
||||
- }
|
||||
-
|
||||
- omap->usbhost_hs_fck = clk_get(dev, "hs_fck");
|
||||
- if (IS_ERR(omap->usbhost_hs_fck)) {
|
||||
- ret = PTR_ERR(omap->usbhost_hs_fck);
|
||||
- dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret);
|
||||
- goto err_usbhost_ick;
|
||||
- }
|
||||
-
|
||||
- omap->usbhost_fs_fck = clk_get(dev, "fs_fck");
|
||||
- if (IS_ERR(omap->usbhost_fs_fck)) {
|
||||
- ret = PTR_ERR(omap->usbhost_fs_fck);
|
||||
- dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret);
|
||||
- goto err_usbhost_hs_fck;
|
||||
- }
|
||||
-
|
||||
- omap->usbtll_fck = clk_get(dev, "usbtll_fck");
|
||||
- if (IS_ERR(omap->usbtll_fck)) {
|
||||
- ret = PTR_ERR(omap->usbtll_fck);
|
||||
- dev_err(dev, "usbtll_fck failed error:%d\n", ret);
|
||||
- goto err_usbhost_fs_fck;
|
||||
- }
|
||||
-
|
||||
- omap->usbtll_ick = clk_get(dev, "usbtll_ick");
|
||||
- if (IS_ERR(omap->usbtll_ick)) {
|
||||
- ret = PTR_ERR(omap->usbtll_ick);
|
||||
- dev_err(dev, "usbtll_ick failed error:%d\n", ret);
|
||||
- goto err_usbtll_fck;
|
||||
- }
|
||||
+ pm_runtime_enable(&pdev->dev);
|
||||
|
||||
omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
|
||||
if (IS_ERR(omap->utmi_p1_fck)) {
|
||||
ret = PTR_ERR(omap->utmi_p1_fck);
|
||||
dev_err(dev, "utmi_p1_gfclk failed error:%d\n", ret);
|
||||
- goto err_usbtll_ick;
|
||||
+ goto err_end;
|
||||
}
|
||||
|
||||
omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
|
||||
@@ -522,22 +485,8 @@ err_xclk60mhsp1_ck:
|
||||
err_utmi_p1_fck:
|
||||
clk_put(omap->utmi_p1_fck);
|
||||
|
||||
-err_usbtll_ick:
|
||||
- clk_put(omap->usbtll_ick);
|
||||
-
|
||||
-err_usbtll_fck:
|
||||
- clk_put(omap->usbtll_fck);
|
||||
-
|
||||
-err_usbhost_fs_fck:
|
||||
- clk_put(omap->usbhost_fs_fck);
|
||||
-
|
||||
-err_usbhost_hs_fck:
|
||||
- clk_put(omap->usbhost_hs_fck);
|
||||
-
|
||||
-err_usbhost_ick:
|
||||
- clk_put(omap->usbhost_ick);
|
||||
-
|
||||
err_end:
|
||||
+ pm_runtime_disable(&pdev->dev);
|
||||
kfree(omap);
|
||||
|
||||
end_probe:
|
||||
@@ -571,11 +520,7 @@ static int __devexit usbhs_omap_remove(struct platform_device *pdev)
|
||||
clk_put(omap->utmi_p2_fck);
|
||||
clk_put(omap->xclk60mhsp1_ck);
|
||||
clk_put(omap->utmi_p1_fck);
|
||||
- clk_put(omap->usbtll_ick);
|
||||
- clk_put(omap->usbtll_fck);
|
||||
- clk_put(omap->usbhost_fs_fck);
|
||||
- clk_put(omap->usbhost_hs_fck);
|
||||
- clk_put(omap->usbhost_ick);
|
||||
+ pm_runtime_disable(&pdev->dev);
|
||||
kfree(omap);
|
||||
|
||||
return 0;
|
||||
@@ -695,7 +640,6 @@ static int usbhs_enable(struct device *dev)
|
||||
struct usbhs_omap_platform_data *pdata = &omap->platdata;
|
||||
unsigned long flags = 0;
|
||||
int ret = 0;
|
||||
- unsigned long timeout;
|
||||
unsigned reg;
|
||||
|
||||
dev_dbg(dev, "starting TI HSUSB Controller\n");
|
||||
@@ -708,11 +652,7 @@ static int usbhs_enable(struct device *dev)
|
||||
if (omap->count > 0)
|
||||
goto end_count;
|
||||
|
||||
- clk_enable(omap->usbhost_ick);
|
||||
- clk_enable(omap->usbhost_hs_fck);
|
||||
- clk_enable(omap->usbhost_fs_fck);
|
||||
- clk_enable(omap->usbtll_fck);
|
||||
- clk_enable(omap->usbtll_ick);
|
||||
+ pm_runtime_get_sync(dev);
|
||||
|
||||
if (pdata->ehci_data->phy_reset) {
|
||||
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) {
|
||||
@@ -736,50 +676,6 @@ static int usbhs_enable(struct device *dev)
|
||||
omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
|
||||
dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
|
||||
|
||||
- /* perform TLL soft reset, and wait until reset is complete */
|
||||
- usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
|
||||
- OMAP_USBTLL_SYSCONFIG_SOFTRESET);
|
||||
-
|
||||
- /* Wait for TLL reset to complete */
|
||||
- timeout = jiffies + msecs_to_jiffies(1000);
|
||||
- while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
|
||||
- & OMAP_USBTLL_SYSSTATUS_RESETDONE)) {
|
||||
- cpu_relax();
|
||||
-
|
||||
- if (time_after(jiffies, timeout)) {
|
||||
- dev_dbg(dev, "operation timed out\n");
|
||||
- ret = -EINVAL;
|
||||
- goto err_tll;
|
||||
- }
|
||||
- }
|
||||
-
|
||||
- dev_dbg(dev, "TLL RESET DONE\n");
|
||||
-
|
||||
- /* (1<<3) = no idle mode only for initial debugging */
|
||||
- usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
|
||||
- OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
|
||||
- OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
|
||||
- OMAP_USBTLL_SYSCONFIG_AUTOIDLE);
|
||||
-
|
||||
- /* Put UHH in NoIdle/NoStandby mode */
|
||||
- reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG);
|
||||
- if (is_omap_usbhs_rev1(omap)) {
|
||||
- reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
|
||||
- | OMAP_UHH_SYSCONFIG_SIDLEMODE
|
||||
- | OMAP_UHH_SYSCONFIG_CACTIVITY
|
||||
- | OMAP_UHH_SYSCONFIG_MIDLEMODE);
|
||||
- reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
|
||||
-
|
||||
-
|
||||
- } else if (is_omap_usbhs_rev2(omap)) {
|
||||
- reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR;
|
||||
- reg |= OMAP4_UHH_SYSCONFIG_NOIDLE;
|
||||
- reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR;
|
||||
- reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY;
|
||||
- }
|
||||
-
|
||||
- usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
|
||||
-
|
||||
reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
|
||||
/* setup ULPI bypass and burst configurations */
|
||||
reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
|
||||
@@ -919,6 +815,8 @@ end_count:
|
||||
return 0;
|
||||
|
||||
err_tll:
|
||||
+ pm_runtime_put_sync(dev);
|
||||
+ spin_unlock_irqrestore(&omap->lock, flags);
|
||||
if (pdata->ehci_data->phy_reset) {
|
||||
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
|
||||
gpio_free(pdata->ehci_data->reset_gpio_port[0]);
|
||||
@@ -926,13 +824,6 @@ err_tll:
|
||||
if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
|
||||
gpio_free(pdata->ehci_data->reset_gpio_port[1]);
|
||||
}
|
||||
-
|
||||
- clk_disable(omap->usbtll_ick);
|
||||
- clk_disable(omap->usbtll_fck);
|
||||
- clk_disable(omap->usbhost_fs_fck);
|
||||
- clk_disable(omap->usbhost_hs_fck);
|
||||
- clk_disable(omap->usbhost_ick);
|
||||
- spin_unlock_irqrestore(&omap->lock, flags);
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1005,11 +896,7 @@ static void usbhs_disable(struct device *dev)
|
||||
clk_disable(omap->utmi_p1_fck);
|
||||
}
|
||||
|
||||
- clk_disable(omap->usbtll_ick);
|
||||
- clk_disable(omap->usbtll_fck);
|
||||
- clk_disable(omap->usbhost_fs_fck);
|
||||
- clk_disable(omap->usbhost_hs_fck);
|
||||
- clk_disable(omap->usbhost_ick);
|
||||
+ pm_runtime_put_sync(dev);
|
||||
|
||||
/* The gpio_free migh sleep; so unlock the spinlock */
|
||||
spin_unlock_irqrestore(&omap->lock, flags);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-406
@@ -1,406 +0,0 @@
|
||||
From 339b167f6f76707a2d6ae3a7c0b921b8278564af Mon Sep 17 00:00:00 2001
|
||||
From: Keshava Munegowda <Keshava_mgowda@ti.com>
|
||||
Date: Wed, 1 Jun 2011 11:02:49 -0700
|
||||
Subject: [PATCH 04/13] arm: omap: usb: ehci and ohci hwmod structures for omap3 and omap4
|
||||
|
||||
Following 2 hwmod strcuture are added:
|
||||
UHH hwmod of usbhs with uhh base address and
|
||||
EHCI , OHCI irq and base addresses.
|
||||
TLL hwmod of usbhs with the TLL base address and irq.
|
||||
|
||||
Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c | 184 ++++++++++++++++++++++++++++
|
||||
arch/arm/mach-omap2/omap_hwmod_44xx_data.c | 153 +++++++++++++++++++++++
|
||||
2 files changed, 337 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
|
||||
index 909a84d..fe9a176 100644
|
||||
--- a/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
|
||||
+++ b/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
|
||||
@@ -84,6 +84,8 @@ static struct omap_hwmod omap3xxx_mcbsp4_hwmod;
|
||||
static struct omap_hwmod omap3xxx_mcbsp5_hwmod;
|
||||
static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod;
|
||||
static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod;
|
||||
+static struct omap_hwmod omap34xx_usb_host_hs_hwmod;
|
||||
+static struct omap_hwmod omap34xx_usb_tll_hs_hwmod;
|
||||
|
||||
/* L3 -> L4_CORE interface */
|
||||
static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {
|
||||
@@ -3574,6 +3576,185 @@ static struct omap_hwmod omap3xxx_mmc3_hwmod = {
|
||||
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * 'usb_host_hs' class
|
||||
+ * high-speed multi-port usb host controller
|
||||
+ */
|
||||
+static struct omap_hwmod_ocp_if omap34xx_usb_host_hs__l3_main_2 = {
|
||||
+ .master = &omap34xx_usb_host_hs_hwmod,
|
||||
+ .slave = &omap3xxx_l3_main_hwmod,
|
||||
+ .clk = "core_l3_ick",
|
||||
+ .user = OCP_USER_MPU,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_class_sysconfig omap34xx_usb_host_hs_sysc = {
|
||||
+ .rev_offs = 0x0000,
|
||||
+ .sysc_offs = 0x0010,
|
||||
+ .syss_offs = 0x0014,
|
||||
+ .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE),
|
||||
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
|
||||
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
|
||||
+ .sysc_fields = &omap_hwmod_sysc_type1,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_class omap34xx_usb_host_hs_hwmod_class = {
|
||||
+ .name = "usbhs_uhh",
|
||||
+ .sysc = &omap34xx_usb_host_hs_sysc,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if *omap34xx_usb_host_hs_masters[] = {
|
||||
+ &omap34xx_usb_host_hs__l3_main_2,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_irq_info omap34xx_usb_host_hs_irqs[] = {
|
||||
+ { .name = "ohci-irq", .irq = 76 },
|
||||
+ { .name = "ehci-irq", .irq = 77 },
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_addr_space omap34xx_usb_host_hs_addrs[] = {
|
||||
+ {
|
||||
+ .name = "uhh",
|
||||
+ .pa_start = 0x48064000,
|
||||
+ .pa_end = 0x480643ff,
|
||||
+ .flags = ADDR_TYPE_RT
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "ohci",
|
||||
+ .pa_start = 0x48064400,
|
||||
+ .pa_end = 0x480647FF,
|
||||
+ .flags = ADDR_MAP_ON_INIT
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "ehci",
|
||||
+ .pa_start = 0x48064800,
|
||||
+ .pa_end = 0x48064CFF,
|
||||
+ .flags = ADDR_MAP_ON_INIT
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if omap34xx_l4_cfg__usb_host_hs = {
|
||||
+ .master = &omap3xxx_l4_core_hwmod,
|
||||
+ .slave = &omap34xx_usb_host_hs_hwmod,
|
||||
+ .clk = "l4_ick",
|
||||
+ .addr = omap34xx_usb_host_hs_addrs,
|
||||
+ .addr_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_addrs),
|
||||
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if omap34xx_f128m_cfg__usb_host_hs = {
|
||||
+ .clk = "usbhost_120m_fck",
|
||||
+ .user = OCP_USER_MPU,
|
||||
+ .flags = OCPIF_SWSUP_IDLE,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if omap34xx_f48m_cfg__usb_host_hs = {
|
||||
+ .clk = "usbhost_48m_fck",
|
||||
+ .user = OCP_USER_MPU,
|
||||
+ .flags = OCPIF_SWSUP_IDLE,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if *omap34xx_usb_host_hs_slaves[] = {
|
||||
+ &omap34xx_l4_cfg__usb_host_hs,
|
||||
+ &omap34xx_f128m_cfg__usb_host_hs,
|
||||
+ &omap34xx_f48m_cfg__usb_host_hs,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod omap34xx_usb_host_hs_hwmod = {
|
||||
+ .name = "usbhs_uhh",
|
||||
+ .class = &omap34xx_usb_host_hs_hwmod_class,
|
||||
+ .mpu_irqs = omap34xx_usb_host_hs_irqs,
|
||||
+ .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_irqs),
|
||||
+ .main_clk = "usbhost_ick",
|
||||
+ .prcm = {
|
||||
+ .omap2 = {
|
||||
+ .module_offs = OMAP3430ES2_USBHOST_MOD,
|
||||
+ .prcm_reg_id = 1,
|
||||
+ .module_bit = 0,
|
||||
+ .idlest_reg_id = 1,
|
||||
+ .idlest_idle_bit = 1,
|
||||
+ .idlest_stdby_bit = 0,
|
||||
+ },
|
||||
+ },
|
||||
+ .slaves = omap34xx_usb_host_hs_slaves,
|
||||
+ .slaves_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_slaves),
|
||||
+ .masters = omap34xx_usb_host_hs_masters,
|
||||
+ .masters_cnt = ARRAY_SIZE(omap34xx_usb_host_hs_masters),
|
||||
+ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
|
||||
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * 'usb_tll_hs' class
|
||||
+ * usb_tll_hs module is the adapter on the usb_host_hs ports
|
||||
+ */
|
||||
+static struct omap_hwmod_class_sysconfig omap34xx_usb_tll_hs_sysc = {
|
||||
+ .rev_offs = 0x0000,
|
||||
+ .sysc_offs = 0x0010,
|
||||
+ .syss_offs = 0x0014,
|
||||
+ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE),
|
||||
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
|
||||
+ .sysc_fields = &omap_hwmod_sysc_type1,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_class omap34xx_usb_tll_hs_hwmod_class = {
|
||||
+ .name = "usbhs_tll",
|
||||
+ .sysc = &omap34xx_usb_tll_hs_sysc,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_irq_info omap34xx_usb_tll_hs_irqs[] = {
|
||||
+ { .name = "tll-irq", .irq = 78 },
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_addr_space omap34xx_usb_tll_hs_addrs[] = {
|
||||
+ {
|
||||
+ .name = "tll",
|
||||
+ .pa_start = 0x48062000,
|
||||
+ .pa_end = 0x48062fff,
|
||||
+ .flags = ADDR_TYPE_RT
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if omap34xx_f_cfg__usb_tll_hs = {
|
||||
+ .clk = "usbtll_fck",
|
||||
+ .user = OCP_USER_MPU,
|
||||
+ .flags = OCPIF_SWSUP_IDLE,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if omap34xx_l4_cfg__usb_tll_hs = {
|
||||
+ .master = &omap3xxx_l4_core_hwmod,
|
||||
+ .slave = &omap34xx_usb_tll_hs_hwmod,
|
||||
+ .clk = "l4_ick",
|
||||
+ .addr = omap34xx_usb_tll_hs_addrs,
|
||||
+ .addr_cnt = ARRAY_SIZE(omap34xx_usb_tll_hs_addrs),
|
||||
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if *omap34xx_usb_tll_hs_slaves[] = {
|
||||
+ &omap34xx_l4_cfg__usb_tll_hs,
|
||||
+ &omap34xx_f_cfg__usb_tll_hs,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod omap34xx_usb_tll_hs_hwmod = {
|
||||
+ .name = "usbhs_tll",
|
||||
+ .class = &omap34xx_usb_tll_hs_hwmod_class,
|
||||
+ .mpu_irqs = omap34xx_usb_tll_hs_irqs,
|
||||
+ .mpu_irqs_cnt = ARRAY_SIZE(omap34xx_usb_tll_hs_irqs),
|
||||
+ .main_clk = "usbtll_ick",
|
||||
+ .prcm = {
|
||||
+ .omap2 = {
|
||||
+ .module_offs = CORE_MOD,
|
||||
+ .prcm_reg_id = 3,
|
||||
+ .module_bit = 2,
|
||||
+ .idlest_reg_id = 3,
|
||||
+ .idlest_idle_bit = 2,
|
||||
+ },
|
||||
+ },
|
||||
+ .slaves = omap34xx_usb_tll_hs_slaves,
|
||||
+ .slaves_cnt = ARRAY_SIZE(omap34xx_usb_tll_hs_slaves),
|
||||
+ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
|
||||
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
|
||||
+};
|
||||
+
|
||||
static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
|
||||
&omap3xxx_l3_main_hwmod,
|
||||
&omap3xxx_l4_core_hwmod,
|
||||
@@ -3656,6 +3837,9 @@ static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
|
||||
/* usbotg for am35x */
|
||||
&am35xx_usbhsotg_hwmod,
|
||||
|
||||
+ &omap34xx_usb_host_hs_hwmod,
|
||||
+ &omap34xx_usb_tll_hs_hwmod,
|
||||
+
|
||||
NULL,
|
||||
};
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
|
||||
index abc548a..d7112b0 100644
|
||||
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
|
||||
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
|
||||
@@ -66,6 +66,8 @@ static struct omap_hwmod omap44xx_mmc2_hwmod;
|
||||
static struct omap_hwmod omap44xx_mpu_hwmod;
|
||||
static struct omap_hwmod omap44xx_mpu_private_hwmod;
|
||||
static struct omap_hwmod omap44xx_usb_otg_hs_hwmod;
|
||||
+static struct omap_hwmod omap44xx_usb_host_hs_hwmod;
|
||||
+static struct omap_hwmod omap44xx_usb_tll_hs_hwmod;
|
||||
|
||||
/*
|
||||
* Interconnects omap_hwmod structures
|
||||
@@ -5027,6 +5029,155 @@ static struct omap_hwmod omap44xx_wd_timer3_hwmod = {
|
||||
.omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * 'usb_host_hs' class
|
||||
+ * high-speed multi-port usb host controller
|
||||
+ */
|
||||
+static struct omap_hwmod_ocp_if omap44xx_usb_host_hs__l3_main_2 = {
|
||||
+ .master = &omap44xx_usb_host_hs_hwmod,
|
||||
+ .slave = &omap44xx_l3_main_2_hwmod,
|
||||
+ .clk = "l3_div_ck",
|
||||
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_class_sysconfig omap44xx_usb_host_hs_sysc = {
|
||||
+ .rev_offs = 0x0000,
|
||||
+ .sysc_offs = 0x0010,
|
||||
+ .syss_offs = 0x0014,
|
||||
+ .sysc_flags = (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE),
|
||||
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
|
||||
+ MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
|
||||
+ .sysc_fields = &omap_hwmod_sysc_type2,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_class omap44xx_usb_host_hs_hwmod_class = {
|
||||
+ .name = "usbhs_uhh",
|
||||
+ .sysc = &omap44xx_usb_host_hs_sysc,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if *omap44xx_usb_host_hs_masters[] = {
|
||||
+ &omap44xx_usb_host_hs__l3_main_2,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_irq_info omap44xx_usb_host_hs_irqs[] = {
|
||||
+ { .name = "ohci-irq", .irq = 76 + OMAP44XX_IRQ_GIC_START },
|
||||
+ { .name = "ehci-irq", .irq = 77 + OMAP44XX_IRQ_GIC_START },
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_addr_space omap44xx_usb_host_hs_addrs[] = {
|
||||
+ {
|
||||
+ .name = "uhh",
|
||||
+ .pa_start = 0x4a064000,
|
||||
+ .pa_end = 0x4a0647ff,
|
||||
+ .flags = ADDR_TYPE_RT
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "ohci",
|
||||
+ .pa_start = 0x4A064800,
|
||||
+ .pa_end = 0x4A064BFF,
|
||||
+ .flags = ADDR_MAP_ON_INIT
|
||||
+ },
|
||||
+ {
|
||||
+ .name = "ehci",
|
||||
+ .pa_start = 0x4A064C00,
|
||||
+ .pa_end = 0x4A064FFF,
|
||||
+ .flags = ADDR_MAP_ON_INIT
|
||||
+ }
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_host_hs = {
|
||||
+ .master = &omap44xx_l4_cfg_hwmod,
|
||||
+ .slave = &omap44xx_usb_host_hs_hwmod,
|
||||
+ .clk = "l4_div_ck",
|
||||
+ .addr = omap44xx_usb_host_hs_addrs,
|
||||
+ .addr_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_addrs),
|
||||
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if *omap44xx_usb_host_hs_slaves[] = {
|
||||
+ &omap44xx_l4_cfg__usb_host_hs,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod omap44xx_usb_host_hs_hwmod = {
|
||||
+ .name = "usbhs_uhh",
|
||||
+ .class = &omap44xx_usb_host_hs_hwmod_class,
|
||||
+ .mpu_irqs = omap44xx_usb_host_hs_irqs,
|
||||
+ .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_irqs),
|
||||
+ .main_clk = "usb_host_hs_fck",
|
||||
+ .prcm = {
|
||||
+ .omap4 = {
|
||||
+ .clkctrl_reg = OMAP4430_CM_L3INIT_USB_HOST_CLKCTRL,
|
||||
+ },
|
||||
+ },
|
||||
+ .slaves = omap44xx_usb_host_hs_slaves,
|
||||
+ .slaves_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_slaves),
|
||||
+ .masters = omap44xx_usb_host_hs_masters,
|
||||
+ .masters_cnt = ARRAY_SIZE(omap44xx_usb_host_hs_masters),
|
||||
+ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
|
||||
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * 'usb_tll_hs' class
|
||||
+ * usb_tll_hs module is the adapter on the usb_host_hs ports
|
||||
+ */
|
||||
+static struct omap_hwmod_class_sysconfig omap44xx_usb_tll_hs_sysc = {
|
||||
+ .rev_offs = 0x0000,
|
||||
+ .sysc_offs = 0x0010,
|
||||
+ .syss_offs = 0x0014,
|
||||
+ .sysc_flags = (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE),
|
||||
+ .idlemodes = (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
|
||||
+ .sysc_fields = &omap_hwmod_sysc_type1,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_class omap44xx_usb_tll_hs_hwmod_class = {
|
||||
+ .name = "usbhs_tll",
|
||||
+ .sysc = &omap44xx_usb_tll_hs_sysc,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_irq_info omap44xx_usb_tll_hs_irqs[] = {
|
||||
+ { .name = "tll-irq", .irq = 78 + OMAP44XX_IRQ_GIC_START },
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_addr_space omap44xx_usb_tll_hs_addrs[] = {
|
||||
+ {
|
||||
+ .name = "tll",
|
||||
+ .pa_start = 0x4a062000,
|
||||
+ .pa_end = 0x4a063fff,
|
||||
+ .flags = ADDR_TYPE_RT
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_tll_hs = {
|
||||
+ .master = &omap44xx_l4_cfg_hwmod,
|
||||
+ .slave = &omap44xx_usb_tll_hs_hwmod,
|
||||
+ .clk = "l4_div_ck",
|
||||
+ .addr = omap44xx_usb_tll_hs_addrs,
|
||||
+ .addr_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_addrs),
|
||||
+ .user = OCP_USER_MPU | OCP_USER_SDMA,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod_ocp_if *omap44xx_usb_tll_hs_slaves[] = {
|
||||
+ &omap44xx_l4_cfg__usb_tll_hs,
|
||||
+};
|
||||
+
|
||||
+static struct omap_hwmod omap44xx_usb_tll_hs_hwmod = {
|
||||
+ .name = "usbhs_tll",
|
||||
+ .class = &omap44xx_usb_tll_hs_hwmod_class,
|
||||
+ .mpu_irqs = omap44xx_usb_tll_hs_irqs,
|
||||
+ .mpu_irqs_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_irqs),
|
||||
+ .main_clk = "usb_tll_hs_ick",
|
||||
+ .prcm = {
|
||||
+ .omap4 = {
|
||||
+ .clkctrl_reg = OMAP4430_CM_L3INIT_USB_TLL_CLKCTRL,
|
||||
+ },
|
||||
+ },
|
||||
+ .slaves = omap44xx_usb_tll_hs_slaves,
|
||||
+ .slaves_cnt = ARRAY_SIZE(omap44xx_usb_tll_hs_slaves),
|
||||
+ .flags = HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
|
||||
+ .omap_chip = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
|
||||
+};
|
||||
+
|
||||
static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
|
||||
|
||||
/* dmm class */
|
||||
@@ -5173,6 +5324,8 @@ static __initdata struct omap_hwmod *omap44xx_hwmods[] = {
|
||||
&omap44xx_wd_timer2_hwmod,
|
||||
&omap44xx_wd_timer3_hwmod,
|
||||
|
||||
+ &omap44xx_usb_host_hs_hwmod,
|
||||
+ &omap44xx_usb_tll_hs_hwmod,
|
||||
NULL,
|
||||
};
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-160
@@ -1,160 +0,0 @@
|
||||
From 70f5e1a0e6639710503a9ffb9008ddcd2bb3f06e Mon Sep 17 00:00:00 2001
|
||||
From: Keshava Munegowda <Keshava_mgowda@ti.com>
|
||||
Date: Wed, 1 Jun 2011 11:02:54 -0700
|
||||
Subject: [PATCH 05/13] arm: omap: usb: register hwmods of usbhs
|
||||
|
||||
The hwmod structure of uhh and tll are retrived
|
||||
and registered with omap device
|
||||
|
||||
Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/usb-host.c | 99 ++++++++++++++--------------------------
|
||||
1 files changed, 35 insertions(+), 64 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c
|
||||
index 89ae298..9d762c4 100644
|
||||
--- a/arch/arm/mach-omap2/usb-host.c
|
||||
+++ b/arch/arm/mach-omap2/usb-host.c
|
||||
@@ -28,51 +28,28 @@
|
||||
#include <mach/hardware.h>
|
||||
#include <mach/irqs.h>
|
||||
#include <plat/usb.h>
|
||||
+#include <plat/omap_device.h>
|
||||
|
||||
#include "mux.h"
|
||||
|
||||
#ifdef CONFIG_MFD_OMAP_USB_HOST
|
||||
|
||||
-#define OMAP_USBHS_DEVICE "usbhs-omap"
|
||||
-
|
||||
-static struct resource usbhs_resources[] = {
|
||||
- {
|
||||
- .name = "uhh",
|
||||
- .flags = IORESOURCE_MEM,
|
||||
- },
|
||||
- {
|
||||
- .name = "tll",
|
||||
- .flags = IORESOURCE_MEM,
|
||||
- },
|
||||
- {
|
||||
- .name = "ehci",
|
||||
- .flags = IORESOURCE_MEM,
|
||||
- },
|
||||
- {
|
||||
- .name = "ehci-irq",
|
||||
- .flags = IORESOURCE_IRQ,
|
||||
- },
|
||||
- {
|
||||
- .name = "ohci",
|
||||
- .flags = IORESOURCE_MEM,
|
||||
- },
|
||||
- {
|
||||
- .name = "ohci-irq",
|
||||
- .flags = IORESOURCE_IRQ,
|
||||
- }
|
||||
-};
|
||||
-
|
||||
-static struct platform_device usbhs_device = {
|
||||
- .name = OMAP_USBHS_DEVICE,
|
||||
- .id = 0,
|
||||
- .num_resources = ARRAY_SIZE(usbhs_resources),
|
||||
- .resource = usbhs_resources,
|
||||
-};
|
||||
+#define OMAP_USBHS_DEVICE "usbhs_omap"
|
||||
+#define USBHS_UHH_HWMODNAME "usbhs_uhh"
|
||||
+#define USBHS_TLL_HWMODNAME "usbhs_tll"
|
||||
|
||||
static struct usbhs_omap_platform_data usbhs_data;
|
||||
static struct ehci_hcd_omap_platform_data ehci_data;
|
||||
static struct ohci_hcd_omap_platform_data ohci_data;
|
||||
|
||||
+static struct omap_device_pm_latency omap_uhhtll_latency[] = {
|
||||
+ {
|
||||
+ .deactivate_func = omap_device_idle_hwmods,
|
||||
+ .activate_func = omap_device_enable_hwmods,
|
||||
+ .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
/* MUX settings for EHCI pins */
|
||||
/*
|
||||
* setup_ehci_io_mux - initialize IO pad mux for USBHOST
|
||||
@@ -508,7 +485,10 @@ static void setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
|
||||
|
||||
void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
|
||||
{
|
||||
- int i;
|
||||
+ struct omap_hwmod *oh[2];
|
||||
+ struct omap_device *od;
|
||||
+ int bus_id = -1;
|
||||
+ int i;
|
||||
|
||||
for (i = 0; i < OMAP3_HS_USB_PORTS; i++) {
|
||||
usbhs_data.port_mode[i] = pdata->port_mode[i];
|
||||
@@ -523,44 +503,35 @@ void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
|
||||
usbhs_data.ohci_data = &ohci_data;
|
||||
|
||||
if (cpu_is_omap34xx()) {
|
||||
- usbhs_resources[0].start = OMAP34XX_UHH_CONFIG_BASE;
|
||||
- usbhs_resources[0].end = OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1;
|
||||
- usbhs_resources[1].start = OMAP34XX_USBTLL_BASE;
|
||||
- usbhs_resources[1].end = OMAP34XX_USBTLL_BASE + SZ_4K - 1;
|
||||
- usbhs_resources[2].start = OMAP34XX_EHCI_BASE;
|
||||
- usbhs_resources[2].end = OMAP34XX_EHCI_BASE + SZ_1K - 1;
|
||||
- usbhs_resources[3].start = INT_34XX_EHCI_IRQ;
|
||||
- usbhs_resources[4].start = OMAP34XX_OHCI_BASE;
|
||||
- usbhs_resources[4].end = OMAP34XX_OHCI_BASE + SZ_1K - 1;
|
||||
- usbhs_resources[5].start = INT_34XX_OHCI_IRQ;
|
||||
setup_ehci_io_mux(pdata->port_mode);
|
||||
setup_ohci_io_mux(pdata->port_mode);
|
||||
} else if (cpu_is_omap44xx()) {
|
||||
- usbhs_resources[0].start = OMAP44XX_UHH_CONFIG_BASE;
|
||||
- usbhs_resources[0].end = OMAP44XX_UHH_CONFIG_BASE + SZ_1K - 1;
|
||||
- usbhs_resources[1].start = OMAP44XX_USBTLL_BASE;
|
||||
- usbhs_resources[1].end = OMAP44XX_USBTLL_BASE + SZ_4K - 1;
|
||||
- usbhs_resources[2].start = OMAP44XX_HSUSB_EHCI_BASE;
|
||||
- usbhs_resources[2].end = OMAP44XX_HSUSB_EHCI_BASE + SZ_1K - 1;
|
||||
- usbhs_resources[3].start = OMAP44XX_IRQ_EHCI;
|
||||
- usbhs_resources[4].start = OMAP44XX_HSUSB_OHCI_BASE;
|
||||
- usbhs_resources[4].end = OMAP44XX_HSUSB_OHCI_BASE + SZ_1K - 1;
|
||||
- usbhs_resources[5].start = OMAP44XX_IRQ_OHCI;
|
||||
setup_4430ehci_io_mux(pdata->port_mode);
|
||||
setup_4430ohci_io_mux(pdata->port_mode);
|
||||
}
|
||||
|
||||
- if (platform_device_add_data(&usbhs_device,
|
||||
- &usbhs_data, sizeof(usbhs_data)) < 0) {
|
||||
- printk(KERN_ERR "USBHS platform_device_add_data failed\n");
|
||||
- goto init_end;
|
||||
+ oh[0] = omap_hwmod_lookup(USBHS_UHH_HWMODNAME);
|
||||
+ if (!oh[0]) {
|
||||
+ pr_err("Could not look up %s\n", USBHS_UHH_HWMODNAME);
|
||||
+ return;
|
||||
}
|
||||
|
||||
- if (platform_device_register(&usbhs_device) < 0)
|
||||
- printk(KERN_ERR "USBHS platform_device_register failed\n");
|
||||
+ oh[1] = omap_hwmod_lookup(USBHS_TLL_HWMODNAME);
|
||||
+ if (!oh[1]) {
|
||||
+ pr_err("Could not look up %s\n", USBHS_TLL_HWMODNAME);
|
||||
+ return;
|
||||
+ }
|
||||
|
||||
-init_end:
|
||||
- return;
|
||||
+ od = omap_device_build_ss(OMAP_USBHS_DEVICE, bus_id, oh, 2,
|
||||
+ (void *)&usbhs_data, sizeof(usbhs_data),
|
||||
+ omap_uhhtll_latency,
|
||||
+ ARRAY_SIZE(omap_uhhtll_latency), false);
|
||||
+
|
||||
+ if (IS_ERR(od)) {
|
||||
+ pr_err("Could not build hwmod devices %s, %s\n",
|
||||
+ USBHS_UHH_HWMODNAME, USBHS_TLL_HWMODNAME);
|
||||
+ return;
|
||||
+ }
|
||||
}
|
||||
|
||||
#else
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-123
@@ -1,123 +0,0 @@
|
||||
From 64bc651bb56435e4cd86d2ebfa4f301abdbac6e5 Mon Sep 17 00:00:00 2001
|
||||
From: Keshava Munegowda <Keshava_mgowda@ti.com>
|
||||
Date: Wed, 1 Jun 2011 11:02:58 -0700
|
||||
Subject: [PATCH 06/13] arm: omap: usb: device name change for the clk names of usbhs
|
||||
|
||||
device name usbhs clocks are changed from
|
||||
usbhs-omap.0 to usbhs_omap; this is because
|
||||
in the hwmod registration the device name is set
|
||||
as usbhs_omap
|
||||
|
||||
Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/clock3xxx_data.c | 28 ++++++++++++++--------------
|
||||
arch/arm/mach-omap2/clock44xx_data.c | 10 +++++-----
|
||||
drivers/mfd/omap-usb-host.c | 2 +-
|
||||
3 files changed, 20 insertions(+), 20 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/clock3xxx_data.c b/arch/arm/mach-omap2/clock3xxx_data.c
|
||||
index 75b119b..fabe482 100644
|
||||
--- a/arch/arm/mach-omap2/clock3xxx_data.c
|
||||
+++ b/arch/arm/mach-omap2/clock3xxx_data.c
|
||||
@@ -3285,7 +3285,7 @@ static struct omap_clk omap3xxx_clks[] = {
|
||||
CLK(NULL, "cpefuse_fck", &cpefuse_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK(NULL, "ts_fck", &ts_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK(NULL, "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
- CLK("usbhs-omap.0", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
+ CLK("usbhs_omap", "usbtll_fck", &usbtll_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK("omap-mcbsp.1", "prcm_fck", &core_96m_fck, CK_3XXX),
|
||||
CLK("omap-mcbsp.5", "prcm_fck", &core_96m_fck, CK_3XXX),
|
||||
CLK(NULL, "core_96m_fck", &core_96m_fck, CK_3XXX),
|
||||
@@ -3321,7 +3321,7 @@ static struct omap_clk omap3xxx_clks[] = {
|
||||
CLK(NULL, "pka_ick", &pka_ick, CK_34XX | CK_36XX),
|
||||
CLK(NULL, "core_l4_ick", &core_l4_ick, CK_3XXX),
|
||||
CLK(NULL, "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
- CLK("usbhs-omap.0", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
+ CLK("usbhs_omap", "usbtll_ick", &usbtll_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK("omap_hsmmc.2", "ick", &mmchs3_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK(NULL, "icr_ick", &icr_ick, CK_34XX | CK_36XX),
|
||||
CLK("omap-aes", "ick", &aes2_ick, CK_34XX | CK_36XX),
|
||||
@@ -3367,20 +3367,20 @@ static struct omap_clk omap3xxx_clks[] = {
|
||||
CLK(NULL, "cam_ick", &cam_ick, CK_34XX | CK_36XX),
|
||||
CLK(NULL, "csi2_96m_fck", &csi2_96m_fck, CK_34XX | CK_36XX),
|
||||
CLK(NULL, "usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
- CLK("usbhs-omap.0", "hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
+ CLK("usbhs_omap", "hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK(NULL, "usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
- CLK("usbhs-omap.0", "fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
+ CLK("usbhs_omap", "fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
CLK(NULL, "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
- CLK("usbhs-omap.0", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
- CLK("usbhs-omap.0", "utmi_p1_gfclk", &dummy_ck, CK_3XXX),
|
||||
- CLK("usbhs-omap.0", "utmi_p2_gfclk", &dummy_ck, CK_3XXX),
|
||||
- CLK("usbhs-omap.0", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX),
|
||||
- CLK("usbhs-omap.0", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX),
|
||||
- CLK("usbhs-omap.0", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX),
|
||||
- CLK("usbhs-omap.0", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX),
|
||||
- CLK("usbhs-omap.0", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX),
|
||||
- CLK("usbhs-omap.0", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX),
|
||||
- CLK("usbhs-omap.0", "init_60m_fclk", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "usbhost_ick", &usbhost_ick, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
|
||||
+ CLK("usbhs_omap", "utmi_p1_gfclk", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "utmi_p2_gfclk", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "xclk60mhsp1_ck", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "xclk60mhsp2_ck", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "usb_host_hs_utmi_p1_clk", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "usb_host_hs_utmi_p2_clk", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "usb_tll_hs_usb_ch0_clk", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "usb_tll_hs_usb_ch1_clk", &dummy_ck, CK_3XXX),
|
||||
+ CLK("usbhs_omap", "init_60m_fclk", &dummy_ck, CK_3XXX),
|
||||
CLK(NULL, "usim_fck", &usim_fck, CK_3430ES2PLUS | CK_36XX),
|
||||
CLK(NULL, "gpt1_fck", &gpt1_fck, CK_3XXX),
|
||||
CLK(NULL, "wkup_32k_fck", &wkup_32k_fck, CK_3XXX),
|
||||
diff --git a/arch/arm/mach-omap2/clock44xx_data.c b/arch/arm/mach-omap2/clock44xx_data.c
|
||||
index 8c96567..34e91eb 100644
|
||||
--- a/arch/arm/mach-omap2/clock44xx_data.c
|
||||
+++ b/arch/arm/mach-omap2/clock44xx_data.c
|
||||
@@ -3205,7 +3205,7 @@ static struct omap_clk omap44xx_clks[] = {
|
||||
CLK(NULL, "uart3_fck", &uart3_fck, CK_443X),
|
||||
CLK(NULL, "uart4_fck", &uart4_fck, CK_443X),
|
||||
CLK(NULL, "usb_host_fs_fck", &usb_host_fs_fck, CK_443X),
|
||||
- CLK("usbhs-omap.0", "fs_fck", &usb_host_fs_fck, CK_443X),
|
||||
+ CLK("usbhs_omap", "fs_fck", &usb_host_fs_fck, CK_443X),
|
||||
CLK(NULL, "utmi_p1_gfclk", &utmi_p1_gfclk, CK_443X),
|
||||
CLK(NULL, "usb_host_hs_utmi_p1_clk", &usb_host_hs_utmi_p1_clk, CK_443X),
|
||||
CLK(NULL, "utmi_p2_gfclk", &utmi_p2_gfclk, CK_443X),
|
||||
@@ -3217,8 +3217,8 @@ static struct omap_clk omap44xx_clks[] = {
|
||||
CLK(NULL, "usb_host_hs_hsic480m_p2_clk", &usb_host_hs_hsic480m_p2_clk, CK_443X),
|
||||
CLK(NULL, "usb_host_hs_func48mclk", &usb_host_hs_func48mclk, CK_443X),
|
||||
CLK(NULL, "usb_host_hs_fck", &usb_host_hs_fck, CK_443X),
|
||||
- CLK("usbhs-omap.0", "hs_fck", &usb_host_hs_fck, CK_443X),
|
||||
- CLK("usbhs-omap.0", "usbhost_ick", &dummy_ck, CK_443X),
|
||||
+ CLK("usbhs_omap", "hs_fck", &usb_host_hs_fck, CK_443X),
|
||||
+ CLK("usbhs_omap", "usbhost_ick", &dummy_ck, CK_443X),
|
||||
CLK(NULL, "otg_60m_gfclk", &otg_60m_gfclk, CK_443X),
|
||||
CLK(NULL, "usb_otg_hs_xclk", &usb_otg_hs_xclk, CK_443X),
|
||||
CLK("musb-omap2430", "ick", &usb_otg_hs_ick, CK_443X),
|
||||
@@ -3227,8 +3227,8 @@ static struct omap_clk omap44xx_clks[] = {
|
||||
CLK(NULL, "usb_tll_hs_usb_ch0_clk", &usb_tll_hs_usb_ch0_clk, CK_443X),
|
||||
CLK(NULL, "usb_tll_hs_usb_ch1_clk", &usb_tll_hs_usb_ch1_clk, CK_443X),
|
||||
CLK(NULL, "usb_tll_hs_ick", &usb_tll_hs_ick, CK_443X),
|
||||
- CLK("usbhs-omap.0", "usbtll_ick", &usb_tll_hs_ick, CK_443X),
|
||||
- CLK("usbhs-omap.0", "usbtll_fck", &dummy_ck, CK_443X),
|
||||
+ CLK("usbhs_omap", "usbtll_ick", &usb_tll_hs_ick, CK_443X),
|
||||
+ CLK("usbhs_omap", "usbtll_fck", &dummy_ck, CK_443X),
|
||||
CLK(NULL, "usim_ck", &usim_ck, CK_443X),
|
||||
CLK(NULL, "usim_fclk", &usim_fclk, CK_443X),
|
||||
CLK(NULL, "usim_fck", &usim_fck, CK_443X),
|
||||
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
|
||||
index 8552195..43de12a 100644
|
||||
--- a/drivers/mfd/omap-usb-host.c
|
||||
+++ b/drivers/mfd/omap-usb-host.c
|
||||
@@ -28,7 +28,7 @@
|
||||
#include <plat/usb.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
-#define USBHS_DRIVER_NAME "usbhs-omap"
|
||||
+#define USBHS_DRIVER_NAME "usbhs_omap"
|
||||
#define OMAP_EHCI_DEVICE "ehci-omap"
|
||||
#define OMAP_OHCI_DEVICE "ohci-omap3"
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-165
@@ -1,165 +0,0 @@
|
||||
From bf583f2924fd9b2f0356cbd0bbfd58c48d98ef15 Mon Sep 17 00:00:00 2001
|
||||
From: Keshava Munegowda <Keshava_mgowda@ti.com>
|
||||
Date: Wed, 1 Jun 2011 11:03:03 -0700
|
||||
Subject: [PATCH 07/13] mfd: global Suspend and resume support of ehci and ohci
|
||||
|
||||
The global suspend and resume functions for usbhs core driver
|
||||
are implemented.These routine are called when the global suspend
|
||||
and resume occurs. Before calling these functions, the
|
||||
bus suspend and resume of ehci and ohci drivers are called
|
||||
from runtime pm.
|
||||
|
||||
Signed-off-by: Keshava Munegowda <keshava_mgowda@ti.com>
|
||||
---
|
||||
drivers/mfd/omap-usb-host.c | 103 +++++++++++++++++++++++++++++++++++++++++++
|
||||
1 files changed, 103 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
|
||||
index 43de12a..32d19e2 100644
|
||||
--- a/drivers/mfd/omap-usb-host.c
|
||||
+++ b/drivers/mfd/omap-usb-host.c
|
||||
@@ -146,6 +146,10 @@
|
||||
#define is_ehci_hsic_mode(x) (x == OMAP_EHCI_PORT_MODE_HSIC)
|
||||
|
||||
|
||||
+/* USBHS state bits */
|
||||
+#define OMAP_USBHS_INIT 0
|
||||
+#define OMAP_USBHS_SUSPEND 4
|
||||
+
|
||||
struct usbhs_hcd_omap {
|
||||
struct clk *xclk60mhsp1_ck;
|
||||
struct clk *xclk60mhsp2_ck;
|
||||
@@ -165,6 +169,7 @@ struct usbhs_hcd_omap {
|
||||
u32 usbhs_rev;
|
||||
spinlock_t lock;
|
||||
int count;
|
||||
+ unsigned long state;
|
||||
};
|
||||
/*-------------------------------------------------------------------------*/
|
||||
|
||||
@@ -809,6 +814,8 @@ static int usbhs_enable(struct device *dev)
|
||||
(pdata->ehci_data->reset_gpio_port[1], 1);
|
||||
}
|
||||
|
||||
+ set_bit(OMAP_USBHS_INIT, &omap->state);
|
||||
+
|
||||
end_count:
|
||||
omap->count++;
|
||||
spin_unlock_irqrestore(&omap->lock, flags);
|
||||
@@ -897,6 +904,7 @@ static void usbhs_disable(struct device *dev)
|
||||
}
|
||||
|
||||
pm_runtime_put_sync(dev);
|
||||
+ clear_bit(OMAP_USBHS_INIT, &omap->state);
|
||||
|
||||
/* The gpio_free migh sleep; so unlock the spinlock */
|
||||
spin_unlock_irqrestore(&omap->lock, flags);
|
||||
@@ -926,10 +934,105 @@ void omap_usbhs_disable(struct device *dev)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(omap_usbhs_disable);
|
||||
|
||||
+#ifdef CONFIG_PM
|
||||
+
|
||||
+static int usbhs_resume(struct device *dev)
|
||||
+{
|
||||
+ struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
|
||||
+ struct usbhs_omap_platform_data *pdata = &omap->platdata;
|
||||
+ unsigned long flags = 0;
|
||||
+
|
||||
+ dev_dbg(dev, "Resuming TI HSUSB Controller\n");
|
||||
+
|
||||
+ if (!pdata) {
|
||||
+ dev_dbg(dev, "missing platform_data\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ spin_lock_irqsave(&omap->lock, flags);
|
||||
+
|
||||
+ if (!test_bit(OMAP_USBHS_INIT, &omap->state) ||
|
||||
+ !test_bit(OMAP_USBHS_SUSPEND, &omap->state))
|
||||
+ goto end_resume;
|
||||
+
|
||||
+ pm_runtime_get_sync(dev);
|
||||
+
|
||||
+ if (is_omap_usbhs_rev2(omap)) {
|
||||
+ if (is_ehci_tll_mode(pdata->port_mode[0])) {
|
||||
+ clk_enable(omap->usbhost_p1_fck);
|
||||
+ clk_enable(omap->usbtll_p1_fck);
|
||||
+ }
|
||||
+ if (is_ehci_tll_mode(pdata->port_mode[1])) {
|
||||
+ clk_enable(omap->usbhost_p2_fck);
|
||||
+ clk_enable(omap->usbtll_p2_fck);
|
||||
+ }
|
||||
+ clk_enable(omap->utmi_p1_fck);
|
||||
+ clk_enable(omap->utmi_p2_fck);
|
||||
+ }
|
||||
+ clear_bit(OMAP_USBHS_SUSPEND, &omap->state);
|
||||
+
|
||||
+end_resume:
|
||||
+ spin_unlock_irqrestore(&omap->lock, flags);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static int usbhs_suspend(struct device *dev)
|
||||
+{
|
||||
+ struct usbhs_hcd_omap *omap = dev_get_drvdata(dev);
|
||||
+ struct usbhs_omap_platform_data *pdata = &omap->platdata;
|
||||
+ unsigned long flags = 0;
|
||||
+
|
||||
+ dev_dbg(dev, "Suspending TI HSUSB Controller\n");
|
||||
+
|
||||
+ if (!pdata) {
|
||||
+ dev_dbg(dev, "missing platform_data\n");
|
||||
+ return -ENODEV;
|
||||
+ }
|
||||
+
|
||||
+ spin_lock_irqsave(&omap->lock, flags);
|
||||
+
|
||||
+ if (!test_bit(OMAP_USBHS_INIT, &omap->state) ||
|
||||
+ test_bit(OMAP_USBHS_SUSPEND, &omap->state))
|
||||
+ goto end_suspend;
|
||||
+
|
||||
+ if (is_omap_usbhs_rev2(omap)) {
|
||||
+ if (is_ehci_tll_mode(pdata->port_mode[0])) {
|
||||
+ clk_disable(omap->usbhost_p1_fck);
|
||||
+ clk_disable(omap->usbtll_p1_fck);
|
||||
+ }
|
||||
+ if (is_ehci_tll_mode(pdata->port_mode[1])) {
|
||||
+ clk_disable(omap->usbhost_p2_fck);
|
||||
+ clk_disable(omap->usbtll_p2_fck);
|
||||
+ }
|
||||
+ clk_disable(omap->utmi_p2_fck);
|
||||
+ clk_disable(omap->utmi_p1_fck);
|
||||
+ }
|
||||
+
|
||||
+ set_bit(OMAP_USBHS_SUSPEND, &omap->state);
|
||||
+ pm_runtime_put_sync(dev);
|
||||
+
|
||||
+end_suspend:
|
||||
+ spin_unlock_irqrestore(&omap->lock, flags);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+
|
||||
+static const struct dev_pm_ops usbhsomap_dev_pm_ops = {
|
||||
+ .suspend = usbhs_suspend,
|
||||
+ .resume = usbhs_resume,
|
||||
+};
|
||||
+
|
||||
+#define USBHS_OMAP_DEV_PM_OPS (&usbhsomap_dev_pm_ops)
|
||||
+#else
|
||||
+#define USBHS_OMAP_DEV_PM_OPS NULL
|
||||
+#endif
|
||||
+
|
||||
static struct platform_driver usbhs_omap_driver = {
|
||||
.driver = {
|
||||
.name = (char *)usbhs_driver_name,
|
||||
.owner = THIS_MODULE,
|
||||
+ .pm = USBHS_OMAP_DEV_PM_OPS,
|
||||
},
|
||||
.remove = __exit_p(usbhs_omap_remove),
|
||||
};
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
From 1f2e639755b920398d6592775e0e31f7fb1ca955 Mon Sep 17 00:00:00 2001
|
||||
From: Lesly A M <leslyam@ti.com>
|
||||
Date: Wed, 1 Jun 2011 14:56:38 -0700
|
||||
Subject: [PATCH 08/13] MFD: TWL4030: Correct the warning print during script loading
|
||||
|
||||
Correcting the if condition check for printing the warning,
|
||||
if wakeup script is not updated before updating the sleep script.
|
||||
|
||||
Since the flag 'order' is set to '1' while updating the wakeup script for P1P2,
|
||||
the condition checking for printing the warning should be if(!order)
|
||||
(ie: print the warning if wakeup script is not updated before updating the sleep script)
|
||||
|
||||
Signed-off-by: Lesly A M <leslyam@ti.com>
|
||||
Cc: Nishanth Menon <nm@ti.com>
|
||||
Cc: David Derrick <dderrick@ti.com>
|
||||
Cc: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
drivers/mfd/twl4030-power.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
|
||||
index 2c0d4d1..8373d79 100644
|
||||
--- a/drivers/mfd/twl4030-power.c
|
||||
+++ b/drivers/mfd/twl4030-power.c
|
||||
@@ -448,7 +448,7 @@ static int __init load_twl4030_script(struct twl4030_script *tscript,
|
||||
goto out;
|
||||
}
|
||||
if (tscript->flags & TWL4030_SLEEP_SCRIPT) {
|
||||
- if (order)
|
||||
+ if (!order)
|
||||
pr_warning("TWL4030: Bad order of scripts (sleep "\
|
||||
"script before wakeup) Leads to boot"\
|
||||
"failure on some boards\n");
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
From ea9acebfe2d3ca8fb3969eaf327665632142b85d Mon Sep 17 00:00:00 2001
|
||||
From: Lesly A M <leslyam@ti.com>
|
||||
Date: Wed, 1 Jun 2011 14:56:45 -0700
|
||||
Subject: [PATCH 09/13] MFD: TWL4030: Modifying the macro name Main_Ref to all caps
|
||||
|
||||
Modifying the macro name Main_Ref to all caps(MAIN_REF).
|
||||
|
||||
Suggested by Nishanth Menon <nm@ti.com>
|
||||
|
||||
Signed-off-by: Lesly A M <leslyam@ti.com>
|
||||
Cc: Nishanth Menon <nm@ti.com>
|
||||
Cc: David Derrick <dderrick@ti.com>
|
||||
Cc: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
arch/arm/mach-omap2/board-rx51-peripherals.c | 2 +-
|
||||
drivers/mfd/twl4030-power.c | 2 +-
|
||||
include/linux/i2c/twl.h | 2 +-
|
||||
3 files changed, 3 insertions(+), 3 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-rx51-peripherals.c b/arch/arm/mach-omap2/board-rx51-peripherals.c
|
||||
index bbcb677..01ee0a1 100644
|
||||
--- a/arch/arm/mach-omap2/board-rx51-peripherals.c
|
||||
+++ b/arch/arm/mach-omap2/board-rx51-peripherals.c
|
||||
@@ -730,7 +730,7 @@ static struct twl4030_resconfig twl4030_rconfig[] __initdata = {
|
||||
{ .resource = RES_RESET, .devgroup = -1,
|
||||
.type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1
|
||||
},
|
||||
- { .resource = RES_Main_Ref, .devgroup = -1,
|
||||
+ { .resource = RES_MAIN_REF, .devgroup = -1,
|
||||
.type = 1, .type2 = -1, .remap_off = -1, .remap_sleep = -1
|
||||
},
|
||||
{ 0, 0},
|
||||
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
|
||||
index 8373d79..8162e43 100644
|
||||
--- a/drivers/mfd/twl4030-power.c
|
||||
+++ b/drivers/mfd/twl4030-power.c
|
||||
@@ -120,7 +120,7 @@ static u8 res_config_addrs[] = {
|
||||
[RES_HFCLKOUT] = 0x8b,
|
||||
[RES_32KCLKOUT] = 0x8e,
|
||||
[RES_RESET] = 0x91,
|
||||
- [RES_Main_Ref] = 0x94,
|
||||
+ [RES_MAIN_REF] = 0x94,
|
||||
};
|
||||
|
||||
static int __init twl4030_write_script_byte(u8 address, u8 byte)
|
||||
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
|
||||
index cbbf3b3..aee3a22 100644
|
||||
--- a/include/linux/i2c/twl.h
|
||||
+++ b/include/linux/i2c/twl.h
|
||||
@@ -502,7 +502,7 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
|
||||
#define RES_32KCLKOUT 26
|
||||
#define RES_RESET 27
|
||||
/* Power Reference */
|
||||
-#define RES_Main_Ref 28
|
||||
+#define RES_MAIN_REF 28
|
||||
|
||||
#define TOTAL_RESOURCES 28
|
||||
/*
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-705
@@ -1,705 +0,0 @@
|
||||
From 0b29e1f61b85dd2d04f035088b70dc287d15b9f0 Mon Sep 17 00:00:00 2001
|
||||
From: Lesly A M <leslyam@ti.com>
|
||||
Date: Wed, 1 Jun 2011 14:56:49 -0700
|
||||
Subject: [PATCH 10/13] MFD: TWL4030: power scripts for OMAP3 boards
|
||||
|
||||
Power bus message sequence for TWL4030 to enter sleep/wakeup/warm_reset.
|
||||
|
||||
TWL4030 power scripts which can be used by different OMAP3 boards
|
||||
with the power companion chip (TWL4030 series).
|
||||
|
||||
The twl4030 generic script can be used by any board file to update
|
||||
the power data in twl4030_platform_data.
|
||||
|
||||
Since the TWL4030 power script has dependency with APIs in twl4030-power.c
|
||||
removing the __init for these APIs.
|
||||
|
||||
For more information please see:
|
||||
http://omapedia.org/wiki/TWL4030_power_scripts
|
||||
|
||||
Signed-off-by: Lesly A M <leslyam@ti.com>
|
||||
Cc: Nishanth Menon <nm@ti.com>
|
||||
Cc: David Derrick <dderrick@ti.com>
|
||||
Cc: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
arch/arm/configs/omap2plus_defconfig | 1 +
|
||||
arch/arm/mach-omap2/devices.c | 15 ++
|
||||
drivers/mfd/Kconfig | 11 +
|
||||
drivers/mfd/Makefile | 1 +
|
||||
drivers/mfd/twl4030-power.c | 31 ++--
|
||||
drivers/mfd/twl4030-script-omap.c | 373 ++++++++++++++++++++++++++++++++++
|
||||
include/linux/i2c/twl.h | 41 ++++-
|
||||
7 files changed, 454 insertions(+), 19 deletions(-)
|
||||
create mode 100644 drivers/mfd/twl4030-script-omap.c
|
||||
|
||||
diff --git a/arch/arm/configs/omap2plus_defconfig b/arch/arm/configs/omap2plus_defconfig
|
||||
index 076db52..d9b9858 100644
|
||||
--- a/arch/arm/configs/omap2plus_defconfig
|
||||
+++ b/arch/arm/configs/omap2plus_defconfig
|
||||
@@ -184,6 +184,7 @@ CONFIG_TWL4030_WATCHDOG=y
|
||||
CONFIG_MENELAUS=y
|
||||
CONFIG_TWL4030_CORE=y
|
||||
CONFIG_TWL4030_POWER=y
|
||||
+CONFIG_TWL4030_SCRIPT=m
|
||||
CONFIG_REGULATOR=y
|
||||
CONFIG_REGULATOR_TWL4030=y
|
||||
CONFIG_REGULATOR_TPS65023=y
|
||||
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
|
||||
index 7b85585..7653329 100644
|
||||
--- a/arch/arm/mach-omap2/devices.c
|
||||
+++ b/arch/arm/mach-omap2/devices.c
|
||||
@@ -329,6 +329,20 @@ static void omap_init_audio(void)
|
||||
static inline void omap_init_audio(void) {}
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_ARCH_OMAP3
|
||||
+static struct platform_device omap_twl4030_script = {
|
||||
+ .name = "twl4030_script",
|
||||
+ .id = -1,
|
||||
+};
|
||||
+
|
||||
+static void omap_init_twl4030_script(void)
|
||||
+{
|
||||
+ platform_device_register(&omap_twl4030_script);
|
||||
+}
|
||||
+#else
|
||||
+static inline void omap_init_twl4030_script(void) {}
|
||||
+#endif
|
||||
+
|
||||
#if defined(CONFIG_SPI_OMAP24XX) || defined(CONFIG_SPI_OMAP24XX_MODULE)
|
||||
|
||||
#include <plat/mcspi.h>
|
||||
@@ -691,6 +705,7 @@ static int __init omap2_init_devices(void)
|
||||
omap_init_sham();
|
||||
omap_init_aes();
|
||||
omap_init_vout();
|
||||
+ omap_init_twl4030_script();
|
||||
|
||||
return 0;
|
||||
}
|
||||
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
|
||||
index fe2370a..ea25d93 100644
|
||||
--- a/drivers/mfd/Kconfig
|
||||
+++ b/drivers/mfd/Kconfig
|
||||
@@ -204,6 +204,17 @@ config TWL4030_POWER
|
||||
and load scripts controlling which resources are switched off/on
|
||||
or reset when a sleep, wakeup or warm reset event occurs.
|
||||
|
||||
+config TWL4030_SCRIPT
|
||||
+ tristate "Support TWL4030 script for OMAP3 boards"
|
||||
+ depends on TWL4030_CORE && TWL4030_POWER
|
||||
+ help
|
||||
+ Say yes here if you want to use the twl4030 power scripts
|
||||
+ for OMAP3 boards. Power bus message sequence for
|
||||
+ TWL4030 to enter sleep/wakeup/warm_reset.
|
||||
+
|
||||
+ TWL4030 power scripts which can be used by different
|
||||
+ OMAP3 boards with the power companion chip (TWL4030 series).
|
||||
+
|
||||
config TWL4030_CODEC
|
||||
bool
|
||||
depends on TWL4030_CORE
|
||||
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
|
||||
index 419caa9..53ada21 100644
|
||||
--- a/drivers/mfd/Makefile
|
||||
+++ b/drivers/mfd/Makefile
|
||||
@@ -42,6 +42,7 @@ obj-$(CONFIG_TWL4030_MADC) += twl4030-madc.o
|
||||
obj-$(CONFIG_TWL4030_POWER) += twl4030-power.o
|
||||
obj-$(CONFIG_TWL4030_CODEC) += twl4030-codec.o
|
||||
obj-$(CONFIG_TWL6030_PWM) += twl6030-pwm.o
|
||||
+obj-$(CONFIG_TWL4030_SCRIPT) += twl4030-script-omap.o
|
||||
|
||||
obj-$(CONFIG_MFD_MC13XXX) += mc13xxx-core.o
|
||||
|
||||
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
|
||||
index 8162e43..91d5bc8 100644
|
||||
--- a/drivers/mfd/twl4030-power.c
|
||||
+++ b/drivers/mfd/twl4030-power.c
|
||||
@@ -123,7 +123,7 @@ static u8 res_config_addrs[] = {
|
||||
[RES_MAIN_REF] = 0x94,
|
||||
};
|
||||
|
||||
-static int __init twl4030_write_script_byte(u8 address, u8 byte)
|
||||
+static int twl4030_write_script_byte(u8 address, u8 byte)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -137,7 +137,7 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int __init twl4030_write_script_ins(u8 address, u16 pmb_message,
|
||||
+static int twl4030_write_script_ins(u8 address, u16 pmb_message,
|
||||
u8 delay, u8 next)
|
||||
{
|
||||
int err;
|
||||
@@ -157,7 +157,7 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int __init twl4030_write_script(u8 address, struct twl4030_ins *script,
|
||||
+static int twl4030_write_script(u8 address, struct twl4030_ins *script,
|
||||
int len)
|
||||
{
|
||||
int err;
|
||||
@@ -182,7 +182,7 @@ static int __init twl4030_write_script(u8 address, struct twl4030_ins *script,
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int __init twl4030_config_wakeup3_sequence(u8 address)
|
||||
+static int twl4030_config_wakeup3_sequence(u8 address)
|
||||
{
|
||||
int err;
|
||||
u8 data;
|
||||
@@ -207,7 +207,7 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int __init twl4030_config_wakeup12_sequence(u8 address)
|
||||
+static int twl4030_config_wakeup12_sequence(u8 address)
|
||||
{
|
||||
int err = 0;
|
||||
u8 data;
|
||||
@@ -261,7 +261,7 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int __init twl4030_config_sleep_sequence(u8 address)
|
||||
+static int twl4030_config_sleep_sequence(u8 address)
|
||||
{
|
||||
int err;
|
||||
|
||||
@@ -275,7 +275,7 @@ static int __init twl4030_config_sleep_sequence(u8 address)
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int __init twl4030_config_warmreset_sequence(u8 address)
|
||||
+static int twl4030_config_warmreset_sequence(u8 address)
|
||||
{
|
||||
int err;
|
||||
u8 rd_data;
|
||||
@@ -323,7 +323,7 @@ out:
|
||||
return err;
|
||||
}
|
||||
|
||||
-static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig)
|
||||
+static int twl4030_configure_resource(struct twl4030_resconfig *rconfig)
|
||||
{
|
||||
int rconfig_addr;
|
||||
int err;
|
||||
@@ -415,7 +415,7 @@ static int __init twl4030_configure_resource(struct twl4030_resconfig *rconfig)
|
||||
return 0;
|
||||
}
|
||||
|
||||
-static int __init load_twl4030_script(struct twl4030_script *tscript,
|
||||
+static int load_twl4030_script(struct twl4030_script *tscript,
|
||||
u8 address)
|
||||
{
|
||||
int err;
|
||||
@@ -510,8 +510,9 @@ int twl4030_remove_script(u8 flags)
|
||||
|
||||
return err;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(twl4030_remove_script);
|
||||
|
||||
-void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
|
||||
+int twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
|
||||
{
|
||||
int err = 0;
|
||||
int i;
|
||||
@@ -529,7 +530,6 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
|
||||
TWL4030_PM_MASTER_PROTECT_KEY);
|
||||
if (err)
|
||||
goto unlock;
|
||||
-
|
||||
for (i = 0; i < twl4030_scripts->num; i++) {
|
||||
err = load_twl4030_script(twl4030_scripts->scripts[i], address);
|
||||
if (err)
|
||||
@@ -552,18 +552,19 @@ void __init twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
|
||||
TWL4030_PM_MASTER_PROTECT_KEY);
|
||||
if (err)
|
||||
pr_err("TWL4030 Unable to relock registers\n");
|
||||
- return;
|
||||
+ return err;
|
||||
|
||||
unlock:
|
||||
if (err)
|
||||
pr_err("TWL4030 Unable to unlock registers\n");
|
||||
- return;
|
||||
+ return err;
|
||||
load:
|
||||
if (err)
|
||||
pr_err("TWL4030 failed to load scripts\n");
|
||||
- return;
|
||||
+ return err;
|
||||
resource:
|
||||
if (err)
|
||||
pr_err("TWL4030 failed to configure resource\n");
|
||||
- return;
|
||||
+ return err;
|
||||
}
|
||||
+EXPORT_SYMBOL_GPL(twl4030_power_init);
|
||||
diff --git a/drivers/mfd/twl4030-script-omap.c b/drivers/mfd/twl4030-script-omap.c
|
||||
new file mode 100644
|
||||
index 0000000..867a442
|
||||
--- /dev/null
|
||||
+++ b/drivers/mfd/twl4030-script-omap.c
|
||||
@@ -0,0 +1,373 @@
|
||||
+/*
|
||||
+ * OMAP power script for PMIC TWL4030
|
||||
+ *
|
||||
+ * Author: Lesly A M <leslyam@ti.com>
|
||||
+ *
|
||||
+ * Copyright (C) 2010 Texas Instruments, Inc.
|
||||
+ * Lesly A M <leslyam@ti.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.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/platform_device.h>
|
||||
+
|
||||
+#include <linux/i2c/twl.h>
|
||||
+
|
||||
+/*
|
||||
+ * power management signal connections for OMAP3430 with TWL5030
|
||||
+ *
|
||||
+ * TWL5030 OMAP3430
|
||||
+ * ______________________ _____________________
|
||||
+ * | | | |
|
||||
+ * | (P1) NSLEEP1|<----------|SYS_OFFMODE |
|
||||
+ * | NRESWARM|<----------|NWARMRESET |
|
||||
+ * | (P2) NSLEEP2|---| | |
|
||||
+ * | | === | |
|
||||
+ * | | - | |
|
||||
+ * | | | |
|
||||
+ * | VDD1 |---------->| VDD1 |
|
||||
+ * | VDD2 |---------->| VDD2 |
|
||||
+ * | VIO |---------->| VDDS |
|
||||
+ * ________ | VAUX1 | | |
|
||||
+ * | | | ... | | |
|
||||
+ * | ENABLE|<--------|CLKEN CLKREQ|<----------|SYS_CLKREQ |
|
||||
+ * | CLKOUT|-------->|HFCLKIN (P3) HFCLKOUT|---------->|XTALIN |
|
||||
+ * |________| |______________________| |_____________________|
|
||||
+ *
|
||||
+ *
|
||||
+ * Signal descriptions:
|
||||
+ *
|
||||
+ * SYS_OFFMODE - OMAP drives this signal low only when the OMAP is in the
|
||||
+ * OFF idle mode. It is driven high when a wake up event is detected.
|
||||
+ * This signal should control the P1 device group in the PMIC.
|
||||
+ *
|
||||
+ * SYS_CLKREQ - OMAP should drive this signal low when the OMAP goes into
|
||||
+ * any idle mode. This signal should control the P3 device group
|
||||
+ * in the PMIC. It is used to notify PMIC when XTALIN is no longer needed.
|
||||
+ *
|
||||
+ * NSLEEP1(P1) - When this signal goes low the P1 sleep sequence is executed
|
||||
+ * in the PMIC turning off certain resources. When this signal goes high
|
||||
+ * the P1 active sequence is executed turning back on certain resources.
|
||||
+ *
|
||||
+ * NSLEEP2(P2) - This signal controls the P2 device group of the PMIC.
|
||||
+ * It is not used in this setup and should be tied to ground.
|
||||
+ * This can be used for connecting a different processor or MODEM chip.
|
||||
+ *
|
||||
+ * CLKREQ(P3) - When this signal goes low the P3 sleep sequence is executed
|
||||
+ * in the PMIC turning off HFCLKOUT. When this signal goes high
|
||||
+ * the P3 active sequence is executed turning back on HFCLKOUT and other
|
||||
+ * resources.
|
||||
+ *
|
||||
+ * CLKEN - Enable signal for oscillator. Should only go low when OMAP is
|
||||
+ * in the OFF idle mode due to long oscillator startup times.
|
||||
+ *
|
||||
+ * HFCLKIN - Oscillator output clock into PMIC.
|
||||
+ *
|
||||
+ * HFCLKOUT - System clock output from PMIC to OMAP.
|
||||
+ *
|
||||
+ * XTALIN - OMAP system clock input(HFCLKOUT).
|
||||
+ */
|
||||
+
|
||||
+/*
|
||||
+ * Recommended sleep and active sequences for TWL5030 when connected to OMAP3
|
||||
+ *
|
||||
+ * WARNING: If the board is using NSLEEP2(P2), should modify this script and
|
||||
+ * setuptime values accordingly.
|
||||
+ *
|
||||
+ * Chip Retention/Off (using i2c for scaling voltage):
|
||||
+ * When OMAP de-assert the SYS_CLKREQ signal, only HFCLKOUT is affected
|
||||
+ * since it is the only resource assigned to P3 only.
|
||||
+ *
|
||||
+ * Sysoff (using sys_off signal):
|
||||
+ * When OMAP de-assert the SYS_OFFMODE signal A2S(active to sleep sequence)
|
||||
+ * on the PMIC is executed. This will put resources of TYPE2=1 and TYPE2=2
|
||||
+ * into sleep. At this point only resources assigned to P1 only will be
|
||||
+ * affected (VDD1, VDD2 & VPLL1).
|
||||
+ *
|
||||
+ * Next the OMAP will lower SYS_CLKREQ which will allow the A2S sequence
|
||||
+ * in PMIC to execute again. This will put resources of TYPE2=1 and TYPE2=2
|
||||
+ * into sleep but will affect resources that are assigned to P3(HFCLKOUT)
|
||||
+ * only or assigned to P1 and P3.
|
||||
+ *
|
||||
+ * On wakeup event OMAP goes active and pulls the SYS_CLKREQ high,
|
||||
+ * which will execute the P3 S2A sequence on the PMIC. This will turn on
|
||||
+ * resources assigned to P3 or assigned to P1 and P3 and of TYPE2=2.
|
||||
+ *
|
||||
+ * Next the OMAP will wait the PRM_VOLTOFFSET time and then de-assert
|
||||
+ * the SYS_OFFMODE pin allowing the PMIC to execute the P1 S2A active
|
||||
+ * sequence. This will turn on resources assigned to P1 or assigned to
|
||||
+ * P1 and P3 and of TYPE2=1.
|
||||
+ *
|
||||
+ * Timing diagram for OMAP wakeup from OFFMODE using sys_off signal
|
||||
+ * _____________________________________________________________
|
||||
+ * OMAP active __/
|
||||
+ * |<--------------------PRM_CLKSETP-------------------->|
|
||||
+ * ______________________________________________________
|
||||
+ * SYS_CLKREQ _________/
|
||||
+ * ___________________________________________________
|
||||
+ * CLKEN ____________/
|
||||
+ *
|
||||
+ * HFCLKIN _______________________________________________/////////////////
|
||||
+ *
|
||||
+ * HFCLKOUT __________________________________________________//////////////
|
||||
+ * |<---PRM_VOLTOFFSET-->|
|
||||
+ * ________________________________
|
||||
+ * SYS_OFFMODE _______________________________/
|
||||
+ * |<--------PRM_VOLTSETUP2------->|
|
||||
+ * ___________
|
||||
+ * VPLL1 ____________________________________________________/
|
||||
+ * __
|
||||
+ * VDD1 _____________________________________________________________/
|
||||
+ * __
|
||||
+ * VDD2 _____________________________________________________________/
|
||||
+ *
|
||||
+ * Other resources which are not handled by this script should be
|
||||
+ * controlled by the respective drivers using them (VAUX1, VAUX2, VAUX3,
|
||||
+ * VAUX4, VMMC1, VMMC2, VPLL2, VSIM, VDAC, VUSB1V5, VUSB1V8 & VUSB3V1).
|
||||
+ *
|
||||
+ * More info:
|
||||
+ * http://omapedia.org/wiki/TWL4030_power_scripts
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * DOC: Sleep to active sequence for P1/P2
|
||||
+ *
|
||||
+ * Sequence to control the TWL4030 Power resources,
|
||||
+ * when the system wakeup from sleep.
|
||||
+ * Executed upon P1_P2 transition for wakeup
|
||||
+ * (sys_offmode signal de-asserted on OMAP).
|
||||
+ */
|
||||
+static struct twl4030_ins wakeup_p12_seq[] __initdata = {
|
||||
+ /*
|
||||
+ * Broadcast message to put resources to active
|
||||
+ *
|
||||
+ * Since we are not using TYPE, resources which have TYPE2 configured
|
||||
+ * as 1 will be targeted (VPLL1, VDD1, VDD2, REGEN, NRES_PWRON, SYSEN).
|
||||
+ */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1,
|
||||
+ RES_STATE_ACTIVE), 2},
|
||||
+};
|
||||
+
|
||||
+static struct twl4030_script wakeup_p12_script __initdata = {
|
||||
+ .script = wakeup_p12_seq,
|
||||
+ .size = ARRAY_SIZE(wakeup_p12_seq),
|
||||
+ .flags = TWL4030_WAKEUP12_SCRIPT,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * DOC: Sleep to active sequence for P3
|
||||
+ *
|
||||
+ * Sequence to control the TWL4030 Power resources,
|
||||
+ * when the system wakeup from sleep.
|
||||
+ * Executed upon P3 transition for wakeup
|
||||
+ * (clkreq signal asserted on OMAP).
|
||||
+ */
|
||||
+static struct twl4030_ins wakeup_p3_seq[] __initdata = {
|
||||
+ /*
|
||||
+ * Broadcast message to put resources to active
|
||||
+ *
|
||||
+ * Since we are not using TYPE, resources which have TYPE2 configured
|
||||
+ * as 2 will be targeted
|
||||
+ * (VINTANA1, VINTANA2, VINTDIG, VIO, CLKEN, HFCLKOUT).
|
||||
+ */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
|
||||
+ RES_STATE_ACTIVE), 2},
|
||||
+};
|
||||
+
|
||||
+static struct twl4030_script wakeup_p3_script __initdata = {
|
||||
+ .script = wakeup_p3_seq,
|
||||
+ .size = ARRAY_SIZE(wakeup_p3_seq),
|
||||
+ .flags = TWL4030_WAKEUP3_SCRIPT,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * DOC: Active to sleep sequence for P1/P2/P3
|
||||
+ *
|
||||
+ * Sequence to control the TWL4030 Power resources,
|
||||
+ * when the system goes into sleep.
|
||||
+ * Executed upon P1_P2/P3 transition for sleep.
|
||||
+ * (sys_offmode signal asserted/clkreq de-asserted on OMAP).
|
||||
+ */
|
||||
+static struct twl4030_ins sleep_on_seq[] __initdata = {
|
||||
+ /* Broadcast message to put res to sleep (TYPE2 = 1, 2) */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1,
|
||||
+ RES_STATE_SLEEP), 2},
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
|
||||
+ RES_STATE_SLEEP), 2},
|
||||
+};
|
||||
+
|
||||
+static struct twl4030_script sleep_on_script __initdata = {
|
||||
+ .script = sleep_on_seq,
|
||||
+ .size = ARRAY_SIZE(sleep_on_seq),
|
||||
+ .flags = TWL4030_SLEEP_SCRIPT,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * DOC: Warm reset sequence
|
||||
+ *
|
||||
+ * Sequence to reset the TWL4030 Power resources,
|
||||
+ * when the system gets warm reset.
|
||||
+ * Executed upon warm reset signal.
|
||||
+ *
|
||||
+ * First the device is put in reset, then the system clock is requested to
|
||||
+ * the external oscillator, and default ON power reference and power providers
|
||||
+ * are enabled. Next some additional resources which are software controlled
|
||||
+ * are enabled. Finally sequence is ended by the release of TWL5030 reset.
|
||||
+ */
|
||||
+static struct twl4030_ins wrst_seq[] __initdata = {
|
||||
+ /*
|
||||
+ * As a workaround for OMAP Erratum (ID: i537 - OMAP HS devices are
|
||||
+ * not recovering from warm reset while in OFF mode)
|
||||
+ * NRESPWRON is toggled to force a power on reset condition to OMAP
|
||||
+ */
|
||||
+ /* Trun OFF NRES_PWRON */
|
||||
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_NRES_PWRON, RES_STATE_OFF), 2},
|
||||
+ /* Reset twl4030 */
|
||||
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_OFF), 2},
|
||||
+ /* Reset MAIN_REF */
|
||||
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_MAIN_REF, RES_STATE_WRST), 2},
|
||||
+ /* Reset All type2_group2 */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
|
||||
+ RES_STATE_WRST), 2},
|
||||
+ /* Reset VUSB_3v1 */
|
||||
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_VUSB_3V1, RES_STATE_WRST), 2},
|
||||
+ /* Reset All type2_group1 */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1,
|
||||
+ RES_STATE_WRST), 2},
|
||||
+ /* Reset the Reset & Contorl_signals */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_RC, RES_TYPE_ALL, RES_TYPE2_R0,
|
||||
+ RES_STATE_WRST), 2},
|
||||
+ /* Re-enable twl4030 */
|
||||
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_RESET, RES_STATE_ACTIVE), 2},
|
||||
+ /* Trun ON NRES_PWRON */
|
||||
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_NRES_PWRON, RES_STATE_ACTIVE), 2},
|
||||
+};
|
||||
+
|
||||
+static struct twl4030_script wrst_script __initdata = {
|
||||
+ .script = wrst_seq,
|
||||
+ .size = ARRAY_SIZE(wrst_seq),
|
||||
+ .flags = TWL4030_WRST_SCRIPT,
|
||||
+};
|
||||
+
|
||||
+/* TWL4030 script for sleep, wakeup & warm_reset */
|
||||
+static struct twl4030_script *twl4030_scripts[] __initdata = {
|
||||
+ &wakeup_p12_script,
|
||||
+ &wakeup_p3_script,
|
||||
+ &sleep_on_script,
|
||||
+ &wrst_script,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * DOC: TWL4030 resource configuration
|
||||
+ *
|
||||
+ * Resource which are attached to P1 device group alone
|
||||
+ * will go to sleep state, when sys_off signal from OMAP is de-asserted.
|
||||
+ * (VPLL1, VDD1, VDD2)
|
||||
+ *
|
||||
+ * None of the resources are attached to P2 device group alone.
|
||||
+ * (WARNING: If MODEM or connectivity chip is connected to NSLEEP2 PIN on
|
||||
+ * TWL4030, should modify the resource configuration accordingly).
|
||||
+ *
|
||||
+ * Resource which are attached to P3 device group alone
|
||||
+ * will go to sleep state, when clk_req signal from OMAP is de-asserted.
|
||||
+ * (HFCLKOUT)
|
||||
+ *
|
||||
+ * Resource which are attached to more than one device group
|
||||
+ * will go to sleep state, when corresponding signals are de-asserted.
|
||||
+ * (VINTANA1, VINTANA2, VINTDIG, VIO, REGEN, NRESPWRON, CLKEN, SYSEN)
|
||||
+ *
|
||||
+ * REGEN is an output of the device which can be connected to slave power ICs
|
||||
+ * or external LDOs that power on before voltage for the IO interface (VIO).
|
||||
+ *
|
||||
+ * SYSEN is a bidirectional signal of the device that controls slave power ICs.
|
||||
+ * In master mode, the device sets SYSEN high to enable the slave power ICs.
|
||||
+ * In slave mode, when one of the power ICs drives the SYSEN signal low,
|
||||
+ * all devices of the platform stay in the wait-on state.
|
||||
+ *
|
||||
+ * Resource which are attached to none of the device group by default
|
||||
+ * will be in sleep state. These resource should be controlled by
|
||||
+ * the respective drivers using them.
|
||||
+ * Resource which are controlled by drivers are not modified here.
|
||||
+ * (VAUX1, VAUX2, VAUX3, VAUX4, VMMC1, VMMC2, VPLL2, VSIM, VDAC,
|
||||
+ * VUSB1V5, VUSB1V8, VUSB3V1)
|
||||
+ *
|
||||
+ * Resource using reset values.
|
||||
+ * (32KCLKOUT, TRITON_RESET, MAINREF)
|
||||
+ */
|
||||
+static struct twl4030_resconfig twl4030_rconfig[] __initdata = {
|
||||
+ { .resource = RES_VPLL1, .devgroup = DEV_GRP_P1, .type = 3,
|
||||
+ .type2 = 1, .remap_sleep = RES_STATE_OFF },
|
||||
+ { .resource = RES_VINTANA1, .devgroup = DEV_GRP_ALL, .type = 1,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_VINTANA2, .devgroup = DEV_GRP_ALL, .type = 0,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_VINTDIG, .devgroup = DEV_GRP_ALL, .type = 1,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_VIO, .devgroup = DEV_GRP_ALL, .type = 2,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_VDD1, .devgroup = DEV_GRP_P1,
|
||||
+ .type = 4, .type2 = 1, .remap_sleep = RES_STATE_OFF },
|
||||
+ { .resource = RES_VDD2, .devgroup = DEV_GRP_P1,
|
||||
+ .type = 3, .type2 = 1, .remap_sleep = RES_STATE_OFF },
|
||||
+ { .resource = RES_REGEN, .devgroup = DEV_GRP_ALL, .type = 2,
|
||||
+ .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_NRES_PWRON, .devgroup = DEV_GRP_ALL, .type = 0,
|
||||
+ .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_CLKEN, .devgroup = DEV_GRP_ALL, .type = 3,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_SYSEN, .devgroup = DEV_GRP_ALL, .type = 6,
|
||||
+ .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P3,
|
||||
+ .type = 0, .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { 0, 0},
|
||||
+};
|
||||
+
|
||||
+struct twl4030_power_data twl4030_generic_script __initdata = {
|
||||
+ .scripts = twl4030_scripts,
|
||||
+ .num = ARRAY_SIZE(twl4030_scripts),
|
||||
+ .resource_config = twl4030_rconfig,
|
||||
+};
|
||||
+
|
||||
+static int __init twl4030_script_probe(struct platform_device *pdev)
|
||||
+{
|
||||
+ return twl4030_power_init(&twl4030_generic_script);
|
||||
+}
|
||||
+
|
||||
+static int twl4030_script_remove(struct platform_device *pdev)
|
||||
+{
|
||||
+ return twl4030_remove_script(TWL4030_SLEEP_SCRIPT |
|
||||
+ TWL4030_WAKEUP12_SCRIPT | TWL4030_WAKEUP3_SCRIPT |
|
||||
+ TWL4030_WRST_SCRIPT);
|
||||
+}
|
||||
+
|
||||
+static struct platform_driver twl4030_script_driver = {
|
||||
+ .remove = twl4030_script_remove,
|
||||
+ .driver = {
|
||||
+ .name = "twl4030_script",
|
||||
+ .owner = THIS_MODULE,
|
||||
+ },
|
||||
+};
|
||||
+
|
||||
+static int __init twl4030_script_init(void)
|
||||
+{
|
||||
+ /* Register the TWL4030 script driver */
|
||||
+ return platform_driver_probe(&twl4030_script_driver,
|
||||
+ twl4030_script_probe);
|
||||
+}
|
||||
+
|
||||
+static void __exit twl4030_script_cleanup(void)
|
||||
+{
|
||||
+ /* Unregister TWL4030 script driver */
|
||||
+ platform_driver_unregister(&twl4030_script_driver);
|
||||
+}
|
||||
+
|
||||
+module_init(twl4030_script_init);
|
||||
+module_exit(twl4030_script_cleanup);
|
||||
+
|
||||
+MODULE_DESCRIPTION("OMAP TWL4030 script driver");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+MODULE_AUTHOR("Texas Instruments Inc");
|
||||
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
|
||||
index aee3a22..f343974 100644
|
||||
--- a/include/linux/i2c/twl.h
|
||||
+++ b/include/linux/i2c/twl.h
|
||||
@@ -205,6 +205,12 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
|
||||
return -EIO;
|
||||
}
|
||||
#endif
|
||||
+
|
||||
+#ifdef CONFIG_TWL4030_POWER
|
||||
+extern struct twl4030_power_data twl4030_generic_script;
|
||||
+#else
|
||||
+#define twl4030_generic_script NULL;
|
||||
+#endif
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
@@ -437,9 +443,23 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
|
||||
|
||||
/* Power bus message definitions */
|
||||
|
||||
-/* The TWL4030/5030 splits its power-management resources (the various
|
||||
- * regulators, clock and reset lines) into 3 processor groups - P1, P2 and
|
||||
- * P3. These groups can then be configured to transition between sleep, wait-on
|
||||
+/*
|
||||
+ * The TWL4030/5030 splits its power-management resources (the various
|
||||
+ * regulators, clock and reset lines) into 3 processor groups - P1, P2 and P3.
|
||||
+ *
|
||||
+ * Resources attached to device group P1 is managed depending on the state of
|
||||
+ * NSLEEP1 pin of TWL4030, which is connected to sys_off signal from OMAP
|
||||
+ *
|
||||
+ * Resources attached to device group P2 is managed depending on the state of
|
||||
+ * NSLEEP2 pin of TWL4030, which is can be connected to a modem or
|
||||
+ * connectivity chip
|
||||
+ *
|
||||
+ * Resources attached to device group P3 is managed depending on the state of
|
||||
+ * CLKREQ pin of TWL4030, which is connected to clk request signal from OMAP
|
||||
+ *
|
||||
+ * If required these resources can be attached to combination of P1/P2/P3.
|
||||
+ *
|
||||
+ * These groups can then be configured to transition between sleep, wait-on
|
||||
* and active states by sending messages to the power bus. See Section 5.4.2
|
||||
* Power Resources of TWL4030 TRM
|
||||
*/
|
||||
@@ -449,7 +469,17 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
|
||||
#define DEV_GRP_P1 0x1 /* P1: all OMAP devices */
|
||||
#define DEV_GRP_P2 0x2 /* P2: all Modem devices */
|
||||
#define DEV_GRP_P3 0x4 /* P3: all peripheral devices */
|
||||
+#define DEV_GRP_ALL 0x7 /* P1/P2/P3: all devices */
|
||||
|
||||
+/*
|
||||
+ * The 27 power resources in TWL4030 is again divided into
|
||||
+ * analog resources:
|
||||
+ * Power Providers - LDO regulators, dc-to-dc regulators
|
||||
+ * Power Reference - analog reference
|
||||
+ *
|
||||
+ * and digital resources:
|
||||
+ * Reset & Clock - reset and clock signals.
|
||||
+ */
|
||||
/* Resource groups */
|
||||
#define RES_GRP_RES 0x0 /* Reserved */
|
||||
#define RES_GRP_PP 0x1 /* Power providers */
|
||||
@@ -461,7 +491,10 @@ static inline int twl6030_mmc_card_detect(struct device *dev, int slot)
|
||||
#define RES_GRP_ALL 0x7 /* All resource groups */
|
||||
|
||||
#define RES_TYPE2_R0 0x0
|
||||
+#define RES_TYPE2_R1 0x1
|
||||
+#define RES_TYPE2_R2 0x2
|
||||
|
||||
+#define RES_TYPE_R0 0x0
|
||||
#define RES_TYPE_ALL 0x7
|
||||
|
||||
/* Resource states */
|
||||
@@ -636,7 +669,7 @@ struct twl4030_power_data {
|
||||
#define TWL4030_RESCONFIG_UNDEF ((u8)-1)
|
||||
};
|
||||
|
||||
-extern void twl4030_power_init(struct twl4030_power_data *triton2_scripts);
|
||||
+extern int twl4030_power_init(struct twl4030_power_data *triton2_scripts);
|
||||
extern int twl4030_remove_script(u8 flags);
|
||||
|
||||
struct twl4030_codec_audio_data {
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-164
@@ -1,164 +0,0 @@
|
||||
From 3ceb224732230934aba7d082f3e2ca96c14a9ca0 Mon Sep 17 00:00:00 2001
|
||||
From: Lesly A M <leslyam@ti.com>
|
||||
Date: Wed, 1 Jun 2011 14:56:56 -0700
|
||||
Subject: [PATCH 11/13] MFD: TWL4030: TWL version checking
|
||||
|
||||
Added API to get the TWL5030 Si version from the IDCODE register.
|
||||
It is used for enabling the workaround for TWL erratum 27.
|
||||
|
||||
Signed-off-by: Lesly A M <leslyam@ti.com>
|
||||
Cc: Nishanth Menon <nm@ti.com>
|
||||
Cc: David Derrick <dderrick@ti.com>
|
||||
Cc: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
drivers/mfd/twl-core.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/i2c/twl.h | 17 ++++++++++++-
|
||||
2 files changed, 78 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
|
||||
index 9096d7d..a60601d 100644
|
||||
--- a/drivers/mfd/twl-core.c
|
||||
+++ b/drivers/mfd/twl-core.c
|
||||
@@ -251,6 +251,9 @@
|
||||
/* is driver active, bound to a chip? */
|
||||
static bool inuse;
|
||||
|
||||
+/* TWL IDCODE Register value */
|
||||
+static u32 twl_idcode;
|
||||
+
|
||||
static unsigned int twl_id;
|
||||
unsigned int twl_rev(void)
|
||||
{
|
||||
@@ -509,6 +512,58 @@ EXPORT_SYMBOL(twl_i2c_read_u8);
|
||||
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
+/**
|
||||
+ * twl_read_idcode_register - API to read the IDCODE register.
|
||||
+ *
|
||||
+ * Unlocks the IDCODE register and read the 32 bit value.
|
||||
+ */
|
||||
+static int twl_read_idcode_register(void)
|
||||
+{
|
||||
+ int err;
|
||||
+
|
||||
+ err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, TWL_EEPROM_R_UNLOCK,
|
||||
+ REG_UNLOCK_TEST_REG);
|
||||
+ if (err) {
|
||||
+ pr_err("TWL4030 Unable to unlock IDCODE registers -%d\n", err);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ err = twl_i2c_read(TWL4030_MODULE_INTBR, (u8 *)(&twl_idcode),
|
||||
+ REG_IDCODE_7_0, 4);
|
||||
+ if (err) {
|
||||
+ pr_err("TWL4030: unable to read IDCODE -%d\n", err);
|
||||
+ goto fail;
|
||||
+ }
|
||||
+
|
||||
+ err = twl_i2c_write_u8(TWL4030_MODULE_INTBR, 0x0, REG_UNLOCK_TEST_REG);
|
||||
+ if (err)
|
||||
+ pr_err("TWL4030 Unable to relock IDCODE registers -%d\n", err);
|
||||
+fail:
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * twl_get_type - API to get TWL Si type.
|
||||
+ *
|
||||
+ * Api to get the TWL Si type from IDCODE value.
|
||||
+ */
|
||||
+int twl_get_type(void)
|
||||
+{
|
||||
+ return TWL_SIL_TYPE(twl_idcode);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(twl_get_type);
|
||||
+
|
||||
+/**
|
||||
+ * twl_get_version - API to get TWL Si version.
|
||||
+ *
|
||||
+ * Api to get the TWL Si version from IDCODE value.
|
||||
+ */
|
||||
+int twl_get_version(void)
|
||||
+{
|
||||
+ return TWL_SIL_REV(twl_idcode);
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(twl_get_version);
|
||||
+
|
||||
static struct device *
|
||||
add_numbered_child(unsigned chip, const char *name, int num,
|
||||
void *pdata, unsigned pdata_len,
|
||||
@@ -1071,6 +1126,7 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
unsigned i;
|
||||
struct twl4030_platform_data *pdata = client->dev.platform_data;
|
||||
u8 temp;
|
||||
+ int ret = 0;
|
||||
|
||||
if (!pdata) {
|
||||
dev_dbg(&client->dev, "no platform data?\n");
|
||||
@@ -1117,6 +1173,12 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
/* setup clock framework */
|
||||
clocks_init(&client->dev, pdata->clock);
|
||||
|
||||
+ /* read TWL IDCODE Register */
|
||||
+ if (twl_id == TWL4030_CLASS_ID) {
|
||||
+ ret = twl_read_idcode_register();
|
||||
+ WARN(ret < 0, "Error: reading twl_idcode register value\n");
|
||||
+ }
|
||||
+
|
||||
/* load power event scripts */
|
||||
if (twl_has_power() && pdata->power)
|
||||
twl4030_power_init(pdata->power);
|
||||
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
|
||||
index f343974..23ec058 100644
|
||||
--- a/include/linux/i2c/twl.h
|
||||
+++ b/include/linux/i2c/twl.h
|
||||
@@ -151,7 +151,12 @@
|
||||
#define MMC_PU (0x1 << 3)
|
||||
#define MMC_PD (0x1 << 2)
|
||||
|
||||
-
|
||||
+#define TWL_SIL_TYPE(rev) ((rev) & 0x00FFFFFF)
|
||||
+#define TWL_SIL_REV(rev) ((rev) >> 24)
|
||||
+#define TWL_SIL_5030 0x09002F
|
||||
+#define TWL5030_REV_1_0 0x00
|
||||
+#define TWL5030_REV_1_1 0x10
|
||||
+#define TWL5030_REV_1_2 0x30
|
||||
|
||||
#define TWL4030_CLASS_ID 0x4030
|
||||
#define TWL6030_CLASS_ID 0x6030
|
||||
@@ -181,6 +186,9 @@ int twl_i2c_read_u8(u8 mod_no, u8 *val, u8 reg);
|
||||
int twl_i2c_write(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
|
||||
int twl_i2c_read(u8 mod_no, u8 *value, u8 reg, unsigned num_bytes);
|
||||
|
||||
+int twl_get_type(void);
|
||||
+int twl_get_version(void);
|
||||
+
|
||||
int twl6030_interrupt_unmask(u8 bit_mask, u8 offset);
|
||||
int twl6030_interrupt_mask(u8 bit_mask, u8 offset);
|
||||
|
||||
@@ -286,7 +294,12 @@ extern struct twl4030_power_data twl4030_generic_script;
|
||||
*(Use TWL_4030_MODULE_INTBR)
|
||||
*/
|
||||
|
||||
+#define REG_IDCODE_7_0 0x00
|
||||
+#define REG_IDCODE_15_8 0x01
|
||||
+#define REG_IDCODE_16_23 0x02
|
||||
+#define REG_IDCODE_31_24 0x03
|
||||
#define REG_GPPUPDCTR1 0x0F
|
||||
+#define REG_UNLOCK_TEST_REG 0x12
|
||||
|
||||
/*I2C1 and I2C4(SR) SDA/SCL pull-up control bits */
|
||||
|
||||
@@ -295,6 +308,8 @@ extern struct twl4030_power_data twl4030_generic_script;
|
||||
#define SR_I2C_SCL_CTRL_PU BIT(4)
|
||||
#define SR_I2C_SDA_CTRL_PU BIT(6)
|
||||
|
||||
+#define TWL_EEPROM_R_UNLOCK 0x49
|
||||
+
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/*
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-341
@@ -1,341 +0,0 @@
|
||||
From 0bec9f7b20e7c61e0bab93195ec39cf94f1f8e25 Mon Sep 17 00:00:00 2001
|
||||
From: Lesly A M <leslyam@ti.com>
|
||||
Date: Wed, 1 Jun 2011 14:57:01 -0700
|
||||
Subject: [PATCH 12/13] MFD: TWL4030: workaround changes for Erratum 27
|
||||
|
||||
Workaround for TWL5030 Silicon Errata 27 & 28:
|
||||
27 - VDD1, VDD2, may have glitches when their output value is updated.
|
||||
28 - VDD1 and / or VDD2 DCDC clock may stop working when internal clock
|
||||
is switched from internal to external.
|
||||
|
||||
Erratum 27:
|
||||
If the DCDC regulators is running on their internal oscillator,
|
||||
negative glitches may occur on VDD1, VDD2 output when voltage is changed.
|
||||
The OMAP device may reboot if the VDD1 or VDD2 go below the
|
||||
core minimum operating voltage.
|
||||
|
||||
WORKAROUND
|
||||
Set up the TWL5030 DC-DC power supplies to use the HFCLKIN instead of
|
||||
the internal oscillator.
|
||||
|
||||
Erratum 28:
|
||||
VDD1/VDD2 clock system may hang during switching the clock source from
|
||||
internal oscillator to external. VDD1/VDD2 output voltages may collapse
|
||||
if clock stops.
|
||||
|
||||
WORKAROUND
|
||||
If HFCLK is disabled in OFFMODE, modify the sleep/wakeup sequence and
|
||||
setuptimes to make sure the switching will happen only when HFCLKIN is stable.
|
||||
Also use the TWL5030 watchdog to safeguard the first switching from
|
||||
internal oscillator to HFCLKIN during the TWL5030 init.
|
||||
|
||||
IMPACT
|
||||
power sequence is changed.
|
||||
sleep/wakeup time values will be changed.
|
||||
|
||||
The workaround changes are called from twl4030_power_init(), since we have to
|
||||
make some i2c_read calls to check the TWL4030 version & the i2c will not be
|
||||
initialized in the early stage.
|
||||
|
||||
This workaround is required for TWL5030 Silicon version less than ES1.2
|
||||
The power script & setup time changes are recommended by TI HW team.
|
||||
|
||||
For more information please see:
|
||||
http://omapedia.org/wiki/TWL4030_power_scripts
|
||||
|
||||
Changes taken from TWL4030 Erratum 27 workaround patch by Nishanth Menon.
|
||||
|
||||
Signed-off-by: Lesly A M <leslyam@ti.com>
|
||||
Cc: Nishanth Menon <nm@ti.com>
|
||||
Cc: David Derrick <dderrick@ti.com>
|
||||
Cc: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
drivers/mfd/twl4030-power.c | 79 +++++++++++++++++++
|
||||
drivers/mfd/twl4030-script-omap.c | 150 +++++++++++++++++++++++++++++++++++++
|
||||
include/linux/i2c/twl.h | 1 +
|
||||
3 files changed, 230 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
|
||||
index 91d5bc8..8af3fe3 100644
|
||||
--- a/drivers/mfd/twl4030-power.c
|
||||
+++ b/drivers/mfd/twl4030-power.c
|
||||
@@ -63,6 +63,14 @@ static u8 twl4030_start_script_address = 0x2b;
|
||||
#define R_MEMORY_ADDRESS PHY_TO_OFF_PM_MASTER(0x59)
|
||||
#define R_MEMORY_DATA PHY_TO_OFF_PM_MASTER(0x5a)
|
||||
|
||||
+#define R_VDD1_OSC 0x5C
|
||||
+#define R_VDD2_OSC 0x6A
|
||||
+#define R_VIO_OSC 0x52
|
||||
+#define EXT_FS_CLK_EN BIT(6)
|
||||
+
|
||||
+#define R_WDT_CFG 0x03
|
||||
+#define WDT_WRK_TIMEOUT 0x03
|
||||
+
|
||||
/* resource configuration registers
|
||||
<RESOURCE>_DEV_GRP at address 'n+0'
|
||||
<RESOURCE>_TYPE at address 'n+1'
|
||||
@@ -512,6 +520,67 @@ int twl4030_remove_script(u8 flags)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(twl4030_remove_script);
|
||||
|
||||
+/**
|
||||
+ * twl_dcdc_use_hfclk - API to use HFCLK for TWL DCDCs
|
||||
+ *
|
||||
+ * TWL DCDCs switching to HFCLK instead of using internal RC oscillator.
|
||||
+ */
|
||||
+static int twl_dcdc_use_hfclk(void)
|
||||
+{
|
||||
+ u8 val;
|
||||
+ u8 smps_osc_reg[] = {R_VDD1_OSC, R_VDD2_OSC, R_VIO_OSC};
|
||||
+ int i;
|
||||
+ int err;
|
||||
+
|
||||
+ for (i = 0; i < sizeof(smps_osc_reg); i++) {
|
||||
+ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &val,
|
||||
+ smps_osc_reg[i]);
|
||||
+ val |= EXT_FS_CLK_EN;
|
||||
+ err |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, val,
|
||||
+ smps_osc_reg[i]);
|
||||
+ }
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * twl_erratum27_workaround - Workaround for TWL5030 Silicon Erratum 27
|
||||
+ * 27 - VDD1, VDD2, may have glitches when their output value is updated.
|
||||
+ * 28 - VDD1 and / or VDD2 DCDC clock may stop working when internal clock is
|
||||
+ * switched from internal to external.
|
||||
+ *
|
||||
+ * Workaround requires the TWL DCDCs to use HFCLK instead of
|
||||
+ * internal oscillator. Also enable TWL watchdog before switching the osc
|
||||
+ * to recover if the VDD1/VDD2 stop working.
|
||||
+ */
|
||||
+static void twl_erratum27_workaround(void)
|
||||
+{
|
||||
+ u8 wdt_counter_val = 0;
|
||||
+ int err;
|
||||
+
|
||||
+ /* Setup the twl wdt to take care of borderline failure case */
|
||||
+ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &wdt_counter_val,
|
||||
+ R_WDT_CFG);
|
||||
+ err |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, WDT_WRK_TIMEOUT,
|
||||
+ R_WDT_CFG);
|
||||
+
|
||||
+ /* TWL DCDC switching to HFCLK */
|
||||
+ err |= twl_dcdc_use_hfclk();
|
||||
+
|
||||
+ /* restore the original value */
|
||||
+ err |= twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, wdt_counter_val,
|
||||
+ R_WDT_CFG);
|
||||
+ if (err)
|
||||
+ pr_warning("TWL4030: workaround setup failed!\n");
|
||||
+}
|
||||
+
|
||||
+static bool is_twl5030_erratum27wa_required(void)
|
||||
+{
|
||||
+ if (twl_get_type() == TWL_SIL_5030)
|
||||
+ return (twl_get_version() < TWL5030_REV_1_2);
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
int twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
|
||||
{
|
||||
int err = 0;
|
||||
@@ -530,6 +599,16 @@ int twl4030_power_init(struct twl4030_power_data *twl4030_scripts)
|
||||
TWL4030_PM_MASTER_PROTECT_KEY);
|
||||
if (err)
|
||||
goto unlock;
|
||||
+
|
||||
+ /* Applying TWL5030 Erratum 27 WA based on Si revision &
|
||||
+ * flag updated from board file*/
|
||||
+ if (is_twl5030_erratum27wa_required()) {
|
||||
+ pr_info("TWL5030: Enabling workaround for Si Erratum 27\n");
|
||||
+ twl_erratum27_workaround();
|
||||
+ if (twl4030_scripts->twl5030_erratum27wa_script)
|
||||
+ twl4030_scripts->twl5030_erratum27wa_script();
|
||||
+ }
|
||||
+
|
||||
for (i = 0; i < twl4030_scripts->num; i++) {
|
||||
err = load_twl4030_script(twl4030_scripts->scripts[i], address);
|
||||
if (err)
|
||||
diff --git a/drivers/mfd/twl4030-script-omap.c b/drivers/mfd/twl4030-script-omap.c
|
||||
index 867a442..ff93fd2 100644
|
||||
--- a/drivers/mfd/twl4030-script-omap.c
|
||||
+++ b/drivers/mfd/twl4030-script-omap.c
|
||||
@@ -326,10 +326,160 @@ static struct twl4030_resconfig twl4030_rconfig[] __initdata = {
|
||||
{ 0, 0},
|
||||
};
|
||||
|
||||
+/*
|
||||
+ * Sleep and active sequences with changes for TWL5030 Erratum 27 workaround
|
||||
+ *
|
||||
+ * Sysoff (using sys_off signal):
|
||||
+ * When SYS_CLKREQ goes low during retention no resources will be affected
|
||||
+ * since no resources are assigned to P3 only.
|
||||
+ *
|
||||
+ * Since all resources are assigned to P1 and P3 then all resources
|
||||
+ * will be affected on the falling edge of P3 (SYS_CLKREQ).
|
||||
+ * When OMAP lower the SYS_CLKREQ signal PMIC will execute the
|
||||
+ * A2S sequence in which HFCLKOUT is dissabled first and
|
||||
+ * after 488.32 usec(PRM_VOLTOFFSET) resources assigned to P1 and P3
|
||||
+ * and of TYPE2=1 are put to sleep
|
||||
+ * (VDD1, VDD2, VPLL1, REGEN, NRESPWRON & SYSEN).
|
||||
+ * Again after a 61.04 usec resources assigned to P1 and P3
|
||||
+ * and of TYPE2=2 are put to sleep
|
||||
+ * (VINTANA1, VINTANA2, VINTDIG, VIO & CLKEN).
|
||||
+ *
|
||||
+ * On wakeup event OMAP goes active and pulls the SYS_CLKREQ high,
|
||||
+ * and will execute the S2A sequence which is same for P1_P2 & P3.
|
||||
+ * This will turn on all resources of TYPE2=2 to go to the active state.
|
||||
+ * Three dummy broadcast messages are added to get a delay of ~10 ms
|
||||
+ * before enabling the HFCLKOUT resource. And after a 30.52 usec
|
||||
+ * all resources of TYPE2=1 are put to the active state.
|
||||
+ *
|
||||
+ * This 10ms delay can be reduced if the oscillator is having less
|
||||
+ * stabilization time. A should be taken care if it needs more time
|
||||
+ * for stabilization.
|
||||
+ *
|
||||
+ */
|
||||
+
|
||||
+/**
|
||||
+ * DOC: Sleep to Active sequence for P1/P2/P3
|
||||
+ *
|
||||
+ * The wakeup sequence is adjusted to do the VDD1/VDD2 voltage ramp-up
|
||||
+ * only after HFCLKIN is stabilized and the HFCLKOUT is enabled.
|
||||
+ */
|
||||
+static struct twl4030_ins wakeup_seq_erratum27[] __initdata = {
|
||||
+ /*
|
||||
+ * Broadcast message to put res(TYPE2 = 2) to active.
|
||||
+ * Wait for ~10 mS (ramp-up time for OSC on the board)
|
||||
+ * after HFCLKIN is enabled
|
||||
+ */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
|
||||
+ RES_STATE_ACTIVE), 55},
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
|
||||
+ RES_STATE_ACTIVE), 55},
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
|
||||
+ RES_STATE_ACTIVE), 54},
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
|
||||
+ RES_STATE_ACTIVE), 1},
|
||||
+ /* Singular message to enable HCLKOUT after HFCLKIN is stabilized */
|
||||
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_HFCLKOUT, RES_STATE_ACTIVE), 1},
|
||||
+ /*
|
||||
+ * Broadcast message to put res(TYPE2 = 1) to active.
|
||||
+ * VDD1/VDD2 ramp-up after HFCLKIN is stable and HFCLKOUT is enabled.
|
||||
+ */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1,
|
||||
+ RES_STATE_ACTIVE), 2},
|
||||
+};
|
||||
+
|
||||
+static struct twl4030_script wakeup_script_erratum27 __initdata = {
|
||||
+ .script = wakeup_seq_erratum27,
|
||||
+ .size = ARRAY_SIZE(wakeup_seq_erratum27),
|
||||
+ .flags = TWL4030_WAKEUP12_SCRIPT | TWL4030_WAKEUP3_SCRIPT,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * DOC: Active to Sleep sequence for P1/P2/P3
|
||||
+ *
|
||||
+ * The sleep sequence is adjusted to do the switching of VDD1/VDD2/VIO OSC from
|
||||
+ * HFCLKIN to internal oscillator when the HFCLKIN is stable.
|
||||
+ */
|
||||
+static struct twl4030_ins sleep_on_seq_erratum27[] __initdata = {
|
||||
+ /*
|
||||
+ * Singular message to disable HCLKOUT.
|
||||
+ * Wait for ~488.32 uS to do the switching of VDD1/VDD2/VIO OSC from
|
||||
+ * HFCLKIN to internal oscillator before disabling HFCLKIN.
|
||||
+ */
|
||||
+ {MSG_SINGULAR(DEV_GRP_NULL, RES_HFCLKOUT, RES_STATE_SLEEP), 20},
|
||||
+ /* Broadcast message to put res(TYPE2 = 1) to sleep */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R1,
|
||||
+ RES_STATE_SLEEP), 2},
|
||||
+ /* Broadcast message to put res(TYPE2 = 2) to sleep, disable HFCLKIN */
|
||||
+ {MSG_BROADCAST(DEV_GRP_NULL, RES_GRP_ALL, RES_TYPE_R0, RES_TYPE2_R2,
|
||||
+ RES_STATE_SLEEP), 2},
|
||||
+};
|
||||
+
|
||||
+static struct twl4030_script sleep_on_script_erratum27 __initdata = {
|
||||
+ .script = sleep_on_seq_erratum27,
|
||||
+ .size = ARRAY_SIZE(sleep_on_seq_erratum27),
|
||||
+ .flags = TWL4030_SLEEP_SCRIPT,
|
||||
+};
|
||||
+
|
||||
+/* TWL4030 script for sleep, wakeup & warm_reset */
|
||||
+static struct twl4030_script *twl4030_scripts_erratum27[] __initdata = {
|
||||
+ &wakeup_script_erratum27,
|
||||
+ &sleep_on_script_erratum27,
|
||||
+ &wrst_script,
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * DOC: TWL4030 resource configuration
|
||||
+ *
|
||||
+ * VDD1/VDD2/VPLL are assigned to P1 and P3, to have better control
|
||||
+ * during OFFMODE. HFCLKOUT is assigned to P1 and P3 (*p2) to turn off
|
||||
+ * only during OFFMODE.
|
||||
+ * (*P2 is included if the platform uses it for modem/some other processor)
|
||||
+ */
|
||||
+static struct twl4030_resconfig twl4030_rconfig_erratum27[] __initdata = {
|
||||
+ { .resource = RES_VPLL1, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
|
||||
+ .type = 3, .type2 = 1, .remap_sleep = RES_STATE_OFF },
|
||||
+ { .resource = RES_VINTANA1, .devgroup = DEV_GRP_ALL, .type = 1,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_VINTANA2, .devgroup = DEV_GRP_ALL, .type = 0,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_VINTDIG, .devgroup = DEV_GRP_ALL, .type = 1,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_VIO, .devgroup = DEV_GRP_ALL, .type = 2,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_VDD1, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
|
||||
+ .type = 4, .type2 = 1, .remap_sleep = RES_STATE_OFF },
|
||||
+ { .resource = RES_VDD2, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
|
||||
+ .type = 3, .type2 = 1, .remap_sleep = RES_STATE_OFF },
|
||||
+ { .resource = RES_REGEN, .devgroup = DEV_GRP_ALL, .type = 2,
|
||||
+ .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_NRES_PWRON, .devgroup = DEV_GRP_ALL, .type = 0,
|
||||
+ .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_CLKEN, .devgroup = DEV_GRP_ALL, .type = 3,
|
||||
+ .type2 = 2, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_SYSEN, .devgroup = DEV_GRP_ALL, .type = 6,
|
||||
+ .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { .resource = RES_HFCLKOUT, .devgroup = DEV_GRP_P1 | DEV_GRP_P3,
|
||||
+ .type = 0, .type2 = 1, .remap_sleep = RES_STATE_SLEEP },
|
||||
+ { 0, 0},
|
||||
+};
|
||||
+
|
||||
+/**
|
||||
+ * twl5030_script_erratum27() - API to modify TWL4030 script
|
||||
+ *
|
||||
+ * Updating the TWL4030 script & resource configuration
|
||||
+ */
|
||||
+static void __init twl5030_script_erratum27(void)
|
||||
+{
|
||||
+ twl4030_generic_script.scripts = twl4030_scripts_erratum27;
|
||||
+ twl4030_generic_script.num = ARRAY_SIZE(twl4030_scripts_erratum27);
|
||||
+ twl4030_generic_script.resource_config = twl4030_rconfig_erratum27;
|
||||
+}
|
||||
+
|
||||
struct twl4030_power_data twl4030_generic_script __initdata = {
|
||||
.scripts = twl4030_scripts,
|
||||
.num = ARRAY_SIZE(twl4030_scripts),
|
||||
.resource_config = twl4030_rconfig,
|
||||
+ .twl5030_erratum27wa_script = twl5030_script_erratum27,
|
||||
};
|
||||
|
||||
static int __init twl4030_script_probe(struct platform_device *pdev)
|
||||
diff --git a/include/linux/i2c/twl.h b/include/linux/i2c/twl.h
|
||||
index 23ec058..10cb6e2 100644
|
||||
--- a/include/linux/i2c/twl.h
|
||||
+++ b/include/linux/i2c/twl.h
|
||||
@@ -681,6 +681,7 @@ struct twl4030_power_data {
|
||||
struct twl4030_script **scripts;
|
||||
unsigned num;
|
||||
struct twl4030_resconfig *resource_config;
|
||||
+ void (*twl5030_erratum27wa_script)(void);
|
||||
#define TWL4030_RESCONFIG_UNDEF ((u8)-1)
|
||||
};
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-184
@@ -1,184 +0,0 @@
|
||||
From bf171753a162d07753208c6bcfae8ca1e5c94af3 Mon Sep 17 00:00:00 2001
|
||||
From: Lesly A M <leslyam@ti.com>
|
||||
Date: Wed, 1 Jun 2011 14:57:05 -0700
|
||||
Subject: [PATCH 13/13] MFD: TWL4030: optimizing resource configuration
|
||||
|
||||
Skip the i2c register writes in twl4030_configure_resource() if the new value
|
||||
is same as the old value, for devgrp/type/remap regs.
|
||||
|
||||
Suggested by David Derrick <dderrick@ti.com>
|
||||
|
||||
Signed-off-by: Lesly A M <leslyam@ti.com>
|
||||
Cc: Nishanth Menon <nm@ti.com>
|
||||
Cc: David Derrick <dderrick@ti.com>
|
||||
Cc: Samuel Ortiz <sameo@linux.intel.com>
|
||||
---
|
||||
drivers/mfd/twl4030-power.c | 126 ++++++++++++++++++++++++------------------
|
||||
1 files changed, 72 insertions(+), 54 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
|
||||
index 8af3fe3..d82632f 100644
|
||||
--- a/drivers/mfd/twl4030-power.c
|
||||
+++ b/drivers/mfd/twl4030-power.c
|
||||
@@ -335,9 +335,9 @@ static int twl4030_configure_resource(struct twl4030_resconfig *rconfig)
|
||||
{
|
||||
int rconfig_addr;
|
||||
int err;
|
||||
- u8 type;
|
||||
- u8 grp;
|
||||
- u8 remap;
|
||||
+ u8 type, type_value;
|
||||
+ u8 grp, grp_value;
|
||||
+ u8 remap, remap_value;
|
||||
|
||||
if (rconfig->resource > TOTAL_RESOURCES) {
|
||||
pr_err("TWL4030 Resource %d does not exist\n",
|
||||
@@ -348,76 +348,94 @@ static int twl4030_configure_resource(struct twl4030_resconfig *rconfig)
|
||||
rconfig_addr = res_config_addrs[rconfig->resource];
|
||||
|
||||
/* Set resource group */
|
||||
- err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp,
|
||||
+ if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) {
|
||||
+ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &grp,
|
||||
rconfig_addr + DEV_GRP_OFFSET);
|
||||
- if (err) {
|
||||
- pr_err("TWL4030 Resource %d group could not be read\n",
|
||||
- rconfig->resource);
|
||||
- return err;
|
||||
- }
|
||||
+ if (err) {
|
||||
+ pr_err("TWL4030 Resource %d group could not be read\n",
|
||||
+ rconfig->resource);
|
||||
+ return err;
|
||||
+ }
|
||||
|
||||
- if (rconfig->devgroup != TWL4030_RESCONFIG_UNDEF) {
|
||||
- grp &= ~DEV_GRP_MASK;
|
||||
- grp |= rconfig->devgroup << DEV_GRP_SHIFT;
|
||||
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
|
||||
+ grp_value = (grp & DEV_GRP_MASK) >> DEV_GRP_SHIFT;
|
||||
+
|
||||
+ if (rconfig->devgroup != grp_value) {
|
||||
+ grp &= ~DEV_GRP_MASK;
|
||||
+ grp |= rconfig->devgroup << DEV_GRP_SHIFT;
|
||||
+ err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
|
||||
grp, rconfig_addr + DEV_GRP_OFFSET);
|
||||
- if (err < 0) {
|
||||
- pr_err("TWL4030 failed to program devgroup\n");
|
||||
- return err;
|
||||
+ if (err < 0) {
|
||||
+ pr_err("TWL4030 failed to program devgroup\n");
|
||||
+ return err;
|
||||
+ }
|
||||
}
|
||||
}
|
||||
|
||||
/* Set resource types */
|
||||
- err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type,
|
||||
+ if ((rconfig->type != TWL4030_RESCONFIG_UNDEF) ||
|
||||
+ (rconfig->type2 != TWL4030_RESCONFIG_UNDEF)) {
|
||||
+
|
||||
+ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &type,
|
||||
rconfig_addr + TYPE_OFFSET);
|
||||
- if (err < 0) {
|
||||
- pr_err("TWL4030 Resource %d type could not be read\n",
|
||||
- rconfig->resource);
|
||||
- return err;
|
||||
- }
|
||||
+ if (err < 0) {
|
||||
+ pr_err("TWL4030 Resource %d type could not be read\n",
|
||||
+ rconfig->resource);
|
||||
+ return err;
|
||||
+ }
|
||||
|
||||
- if (rconfig->type != TWL4030_RESCONFIG_UNDEF) {
|
||||
- type &= ~TYPE_MASK;
|
||||
- type |= rconfig->type << TYPE_SHIFT;
|
||||
- }
|
||||
+ type_value = type;
|
||||
|
||||
- if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) {
|
||||
- type &= ~TYPE2_MASK;
|
||||
- type |= rconfig->type2 << TYPE2_SHIFT;
|
||||
- }
|
||||
+ if (rconfig->type != TWL4030_RESCONFIG_UNDEF) {
|
||||
+ type &= ~TYPE_MASK;
|
||||
+ type |= rconfig->type << TYPE_SHIFT;
|
||||
+ }
|
||||
|
||||
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
|
||||
+ if (rconfig->type2 != TWL4030_RESCONFIG_UNDEF) {
|
||||
+ type &= ~TYPE2_MASK;
|
||||
+ type |= rconfig->type2 << TYPE2_SHIFT;
|
||||
+ }
|
||||
+
|
||||
+ if (type != type_value) {
|
||||
+ err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
|
||||
type, rconfig_addr + TYPE_OFFSET);
|
||||
- if (err < 0) {
|
||||
- pr_err("TWL4030 failed to program resource type\n");
|
||||
- return err;
|
||||
+ if (err < 0) {
|
||||
+ pr_err("TWL4030 failed to program resource type\n");
|
||||
+ return err;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
/* Set remap states */
|
||||
- err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &remap,
|
||||
+ if ((rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) ||
|
||||
+ (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF)) {
|
||||
+ err = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &remap,
|
||||
rconfig_addr + REMAP_OFFSET);
|
||||
- if (err < 0) {
|
||||
- pr_err("TWL4030 Resource %d remap could not be read\n",
|
||||
- rconfig->resource);
|
||||
- return err;
|
||||
- }
|
||||
+ if (err < 0) {
|
||||
+ pr_err("TWL4030 Resource %d remap could not be read\n",
|
||||
+ rconfig->resource);
|
||||
+ return err;
|
||||
+ }
|
||||
|
||||
- if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) {
|
||||
- remap &= ~OFF_STATE_MASK;
|
||||
- remap |= rconfig->remap_off << OFF_STATE_SHIFT;
|
||||
- }
|
||||
+ remap_value = remap;
|
||||
|
||||
- if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) {
|
||||
- remap &= ~SLEEP_STATE_MASK;
|
||||
- remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT;
|
||||
- }
|
||||
+ if (rconfig->remap_off != TWL4030_RESCONFIG_UNDEF) {
|
||||
+ remap &= ~OFF_STATE_MASK;
|
||||
+ remap |= rconfig->remap_off << OFF_STATE_SHIFT;
|
||||
+ }
|
||||
|
||||
- err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
|
||||
- remap,
|
||||
- rconfig_addr + REMAP_OFFSET);
|
||||
- if (err < 0) {
|
||||
- pr_err("TWL4030 failed to program remap\n");
|
||||
- return err;
|
||||
+ if (rconfig->remap_sleep != TWL4030_RESCONFIG_UNDEF) {
|
||||
+ remap &= ~SLEEP_STATE_MASK;
|
||||
+ remap |= rconfig->remap_sleep << SLEEP_STATE_SHIFT;
|
||||
+ }
|
||||
+
|
||||
+ if (remap != remap_value) {
|
||||
+ err = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER,
|
||||
+ remap, rconfig_addr + REMAP_OFFSET);
|
||||
+ if (err < 0) {
|
||||
+ pr_err("TWL4030 failed to program remap\n");
|
||||
+ return err;
|
||||
+ }
|
||||
+ }
|
||||
}
|
||||
|
||||
return 0;
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-121
@@ -1,121 +0,0 @@
|
||||
From 2adb339e4988632379971febe5696f21d05c71f2 Mon Sep 17 00:00:00 2001
|
||||
From: Anand Gadiyar <gadiyar@ti.com>
|
||||
Date: Tue, 19 Jul 2011 01:52:14 -0700
|
||||
Subject: [PATCH] usb: musb: Enable DMA mode1 RX for USB-Mass-Storage
|
||||
|
||||
This patch enables the DMA mode1 RX support.
|
||||
This feature is enabled based on the short_not_ok flag passed from
|
||||
gadget drivers.
|
||||
|
||||
This will result in a thruput performance gain of around
|
||||
40% for USB mass-storage/mtp use cases.
|
||||
|
||||
Signed-off-by: Anand Gadiyar <gadiyar@ti.com>
|
||||
Signed-off-by: Moiz Sonasath <m-sonasath@ti.com>
|
||||
Tested-by: Vikram Pandita <vikram.pandita@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
drivers/usb/musb/musb_gadget.c | 68 ++++++++++++++++++++++++---------------
|
||||
1 files changed, 42 insertions(+), 26 deletions(-)
|
||||
|
||||
diff --git a/drivers/usb/musb/musb_gadget.c b/drivers/usb/musb/musb_gadget.c
|
||||
index f47c201..ca32c63 100644
|
||||
--- a/drivers/usb/musb/musb_gadget.c
|
||||
+++ b/drivers/usb/musb/musb_gadget.c
|
||||
@@ -630,6 +630,7 @@ static void rxstate(struct musb *musb, struct musb_request *req)
|
||||
u16 len;
|
||||
u16 csr = musb_readw(epio, MUSB_RXCSR);
|
||||
struct musb_hw_ep *hw_ep = &musb->endpoints[epnum];
|
||||
+ u8 use_mode_1;
|
||||
|
||||
if (hw_ep->is_shared_fifo)
|
||||
musb_ep = &hw_ep->ep_in;
|
||||
@@ -679,6 +680,18 @@ static void rxstate(struct musb *musb, struct musb_request *req)
|
||||
|
||||
if (csr & MUSB_RXCSR_RXPKTRDY) {
|
||||
len = musb_readw(epio, MUSB_RXCOUNT);
|
||||
+
|
||||
+ /*
|
||||
+ * Enable Mode 1 for RX transfers only for mass-storage
|
||||
+ * use-case, based on short_not_ok flag which is set only
|
||||
+ * from file_storage and f_mass_storage drivers
|
||||
+ */
|
||||
+
|
||||
+ if (request->short_not_ok && len == musb_ep->packet_sz)
|
||||
+ use_mode_1 = 1;
|
||||
+ else
|
||||
+ use_mode_1 = 0;
|
||||
+
|
||||
if (request->actual < request->length) {
|
||||
#ifdef CONFIG_USB_INVENTRA_DMA
|
||||
if (is_buffer_mapped(req)) {
|
||||
@@ -710,37 +723,40 @@ static void rxstate(struct musb *musb, struct musb_request *req)
|
||||
* then becomes usable as a runtime "use mode 1" hint...
|
||||
*/
|
||||
|
||||
- csr |= MUSB_RXCSR_DMAENAB;
|
||||
-#ifdef USE_MODE1
|
||||
- csr |= MUSB_RXCSR_AUTOCLEAR;
|
||||
- /* csr |= MUSB_RXCSR_DMAMODE; */
|
||||
-
|
||||
- /* this special sequence (enabling and then
|
||||
- * disabling MUSB_RXCSR_DMAMODE) is required
|
||||
- * to get DMAReq to activate
|
||||
- */
|
||||
- musb_writew(epio, MUSB_RXCSR,
|
||||
- csr | MUSB_RXCSR_DMAMODE);
|
||||
-#else
|
||||
- if (!musb_ep->hb_mult &&
|
||||
- musb_ep->hw_ep->rx_double_buffered)
|
||||
+ /* Experimental: Mode1 works with mass storage use cases */
|
||||
+ if (use_mode_1) {
|
||||
csr |= MUSB_RXCSR_AUTOCLEAR;
|
||||
-#endif
|
||||
- musb_writew(epio, MUSB_RXCSR, csr);
|
||||
+ musb_writew(epio, MUSB_RXCSR, csr);
|
||||
+ csr |= MUSB_RXCSR_DMAENAB;
|
||||
+ musb_writew(epio, MUSB_RXCSR, csr);
|
||||
+
|
||||
+ /* this special sequence (enabling and then
|
||||
+ * disabling MUSB_RXCSR_DMAMODE) is required
|
||||
+ * to get DMAReq to activate
|
||||
+ */
|
||||
+ musb_writew(epio, MUSB_RXCSR,
|
||||
+ csr | MUSB_RXCSR_DMAMODE);
|
||||
+ musb_writew(epio, MUSB_RXCSR, csr);
|
||||
+
|
||||
+ } else {
|
||||
+ if (!musb_ep->hb_mult &&
|
||||
+ musb_ep->hw_ep->rx_double_buffered)
|
||||
+ csr |= MUSB_RXCSR_AUTOCLEAR;
|
||||
+ csr |= MUSB_RXCSR_DMAENAB;
|
||||
+ musb_writew(epio, MUSB_RXCSR, csr);
|
||||
+ }
|
||||
|
||||
if (request->actual < request->length) {
|
||||
int transfer_size = 0;
|
||||
-#ifdef USE_MODE1
|
||||
- transfer_size = min(request->length - request->actual,
|
||||
- channel->max_len);
|
||||
-#else
|
||||
- transfer_size = min(request->length - request->actual,
|
||||
- (unsigned)len);
|
||||
-#endif
|
||||
- if (transfer_size <= musb_ep->packet_sz)
|
||||
- musb_ep->dma->desired_mode = 0;
|
||||
- else
|
||||
+ if (use_mode_1) {
|
||||
+ transfer_size = min(request->length - request->actual,
|
||||
+ channel->max_len);
|
||||
musb_ep->dma->desired_mode = 1;
|
||||
+ } else {
|
||||
+ transfer_size = min(request->length - request->actual,
|
||||
+ (unsigned)len);
|
||||
+ musb_ep->dma->desired_mode = 0;
|
||||
+ }
|
||||
|
||||
use_dma = c->channel_program(
|
||||
channel,
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
diff --git a/fs/nfs/nfsroot.c b/fs/nfs/nfsroot.c
|
||||
index c541093..c4744e1 100644
|
||||
--- a/fs/nfs/nfsroot.c
|
||||
+++ b/fs/nfs/nfsroot.c
|
||||
@@ -87,7 +87,7 @@
|
||||
#define NFS_ROOT "/tftpboot/%s"
|
||||
|
||||
/* Default NFSROOT mount options. */
|
||||
-#define NFS_DEF_OPTIONS "udp"
|
||||
+#define NFS_DEF_OPTIONS "vers=2,udp,rsize=4096,wsize=4096"
|
||||
|
||||
/* Parameters passed from the kernel command line */
|
||||
static char nfs_root_parms[256] __initdata = "";
|
||||
-38
@@ -1,38 +0,0 @@
|
||||
From 38dd5aadc86725f6018d23679e9daa60ca0a8319 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Thu, 12 May 2011 07:59:52 -0500
|
||||
Subject: [PATCH 1/6] OMAP2+: cpufreq: free up table on exit
|
||||
|
||||
freq_table allocated by opp_init_cpufreq_table in omap_cpu_init
|
||||
needs to be freed in omap_cpu_exit.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 3 +++
|
||||
1 files changed, 3 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index d53ce23..e38ebb8 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -26,6 +26,7 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/opp.h>
|
||||
+#include <linux/slab.h>
|
||||
#include <linux/cpu.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
@@ -216,6 +217,8 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
{
|
||||
clk_exit_cpufreq_table(&freq_table);
|
||||
+ kfree(freq_table);
|
||||
+ freq_table = NULL;
|
||||
clk_put(mpu_clk);
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-44
@@ -1,44 +0,0 @@
|
||||
From 5febdc0482e545c2a598f035c5e03931e0c3c808 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Thu, 12 May 2011 08:14:41 -0500
|
||||
Subject: [PATCH 2/6] OMAP2+: cpufreq: handle invalid cpufreq table
|
||||
|
||||
Handle the case when cpufreq_frequency_table_cpuinfo fails. freq_table
|
||||
that we passed failed the internal test of cpufreq generic driver,
|
||||
so we should'nt be using the freq_table as such. Instead, warn and
|
||||
fallback to clock functions for validation and operation.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 12 ++++++++++--
|
||||
1 files changed, 10 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index e38ebb8..6e3666a 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -182,10 +182,18 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
if (freq_table) {
|
||||
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
- if (!result)
|
||||
+ if (!result) {
|
||||
cpufreq_frequency_table_get_attr(freq_table,
|
||||
policy->cpu);
|
||||
- } else {
|
||||
+ } else {
|
||||
+ WARN(true, "%s: fallback to clk_round(freq_table=%d)\n",
|
||||
+ __func__, result);
|
||||
+ kfree(freq_table);
|
||||
+ freq_table = NULL;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (!freq_table) {
|
||||
policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
|
||||
policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
|
||||
VERY_HI_RATE) / 1000;
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
From aef7e862873e6125159a18d22a2e37b1fbab2153 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Thu, 12 May 2011 16:27:45 -0700
|
||||
Subject: [PATCH 3/6] OMAP2+: cpufreq: minor comment cleanup
|
||||
|
||||
this should probably get squashed in..
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 6 ++++--
|
||||
1 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index 6e3666a..45f1e9e 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -84,8 +84,10 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
if (is_smp() && (num_online_cpus() < NR_CPUS))
|
||||
return ret;
|
||||
|
||||
- /* Ensure desired rate is within allowed range. Some govenors
|
||||
- * (ondemand) will just pass target_freq=0 to get the minimum. */
|
||||
+ /*
|
||||
+ * Ensure desired rate is within allowed range. Some govenors
|
||||
+ * (ondemand) will just pass target_freq=0 to get the minimum.
|
||||
+ */
|
||||
if (target_freq < policy->min)
|
||||
target_freq = policy->min;
|
||||
if (target_freq > policy->max)
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
From f231980dbd0f05229f2020e59b7242872576416f Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Fri, 13 May 2011 05:34:35 -0700
|
||||
Subject: [PATCH 4/6] OMAP2: cpufreq: use clk_init_cpufreq_table if OPPs not available
|
||||
|
||||
OMAP2 does not use OPP tables at the moment for DVFS. Currently,
|
||||
we depend on opp table initialization to give us the freq_table,
|
||||
which makes sense for OMAP3+. for OMAP2, we should be using
|
||||
clk_init_cpufreq_table - so if the opp based frequency table
|
||||
initilization fails, fall back to clk_init_cpufreq_table to give
|
||||
us the table.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 9 ++++++++-
|
||||
1 files changed, 8 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index 45f1e9e..854f4b3 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -180,7 +180,13 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
pr_warning("%s: unable to get the mpu device\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
- opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
+
|
||||
+ /*
|
||||
+ * if we dont get cpufreq table using opp, use traditional omap2 lookup
|
||||
+ * as a fallback
|
||||
+ */
|
||||
+ if (opp_init_cpufreq_table(mpu_dev, &freq_table))
|
||||
+ clk_init_cpufreq_table(&freq_table);
|
||||
|
||||
if (freq_table) {
|
||||
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
@@ -188,6 +194,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
cpufreq_frequency_table_get_attr(freq_table,
|
||||
policy->cpu);
|
||||
} else {
|
||||
+ clk_exit_cpufreq_table(&freq_table);
|
||||
WARN(true, "%s: fallback to clk_round(freq_table=%d)\n",
|
||||
__func__, result);
|
||||
kfree(freq_table);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-78
@@ -1,78 +0,0 @@
|
||||
From 272d76bcb22b9509ccc1b59d3a62e3930d902d17 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Fri, 13 May 2011 05:43:49 -0700
|
||||
Subject: [PATCH 5/6] OMAP2+: cpufreq: use cpufreq_frequency_table_target
|
||||
|
||||
Use cpufreq_frequency_table_target for finding the proper target
|
||||
instead of seeing if the frequency requested is divisible alone.
|
||||
if we have a frequency table, we should restrict ourselves to
|
||||
selecting the "approved" frequencies alone and only in the case
|
||||
where the frequency table is not available should we attempt at
|
||||
closest roundable clock frequency.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 38 ++++++++++++++++++++++--------
|
||||
1 files changed, 28 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index 854f4b3..d0b4f97 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -77,24 +77,42 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
- int i, ret = 0;
|
||||
+ unsigned int i;
|
||||
+ int ret = 0;
|
||||
struct cpufreq_freqs freqs;
|
||||
|
||||
/* Changes not allowed until all CPUs are online */
|
||||
if (is_smp() && (num_online_cpus() < NR_CPUS))
|
||||
return ret;
|
||||
|
||||
- /*
|
||||
- * Ensure desired rate is within allowed range. Some govenors
|
||||
- * (ondemand) will just pass target_freq=0 to get the minimum.
|
||||
- */
|
||||
- if (target_freq < policy->min)
|
||||
- target_freq = policy->min;
|
||||
- if (target_freq > policy->max)
|
||||
- target_freq = policy->max;
|
||||
+ if (freq_table) {
|
||||
+ ret = cpufreq_frequency_table_target(policy, freq_table,
|
||||
+ target_freq, relation, &i);
|
||||
+ if (ret) {
|
||||
+ pr_debug("%s: cpu%d: no freq match for %d(ret=%d)\n",
|
||||
+ __func__, policy->cpu, target_freq, ret);
|
||||
+ return ret;
|
||||
+ }
|
||||
+ freqs.new = freq_table[i].frequency;
|
||||
+ } else {
|
||||
+ /*
|
||||
+ * Ensure desired rate is within allowed range. Some govenors
|
||||
+ * (ondemand) will just pass target_freq=0 to get the minimum.
|
||||
+ */
|
||||
+ if (target_freq < policy->min)
|
||||
+ target_freq = policy->min;
|
||||
+ if (target_freq > policy->max)
|
||||
+ target_freq = policy->max;
|
||||
+
|
||||
+ freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
+ }
|
||||
+ if (!freqs.new) {
|
||||
+ pr_err("%s: cpu%d: no match for freq %d\n", __func__,
|
||||
+ policy->cpu, target_freq);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
|
||||
freqs.old = omap_getspeed(policy->cpu);
|
||||
- freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
freqs.cpu = policy->cpu;
|
||||
|
||||
if (freqs.old == freqs.new)
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-100
@@ -1,100 +0,0 @@
|
||||
From 42a384af80e07534913d9002ec8d9caf5d4d305c Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Wed, 18 May 2011 01:48:23 -0500
|
||||
Subject: [PATCH 6/6] OMAP2+: cpufreq: fix freq_table leak
|
||||
|
||||
Since we have two cpus the cpuinit call for cpu1 causes
|
||||
freq_table of cpu0 to be overwritten. instead, we maintain
|
||||
a counter to keep track of cpus who use the cpufreq table
|
||||
allocate it once(one freq table for all CPUs) and free them
|
||||
once the last user is done with it.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 33 ++++++++++++++++++++++++------
|
||||
1 files changed, 26 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index d0b4f97..fc3d0fb 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -42,6 +42,9 @@
|
||||
#define VERY_HI_RATE 900000000
|
||||
|
||||
static struct cpufreq_frequency_table *freq_table;
|
||||
+static int freq_table_users;
|
||||
+static DEFINE_MUTEX(freq_table_lock);
|
||||
+
|
||||
static struct clk *mpu_clk;
|
||||
|
||||
static int omap_verify_speed(struct cpufreq_policy *policy)
|
||||
@@ -172,6 +175,18 @@ skip_lpj:
|
||||
return ret;
|
||||
}
|
||||
|
||||
+static void freq_table_free(void)
|
||||
+{
|
||||
+ if (!freq_table_users)
|
||||
+ return;
|
||||
+ freq_table_users--;
|
||||
+ if (freq_table_users)
|
||||
+ return;
|
||||
+ clk_exit_cpufreq_table(&freq_table);
|
||||
+ kfree(freq_table);
|
||||
+ freq_table = NULL;
|
||||
+}
|
||||
+
|
||||
static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
int result = 0;
|
||||
@@ -199,14 +214,18 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
+ mutex_lock(&freq_table_lock);
|
||||
/*
|
||||
* if we dont get cpufreq table using opp, use traditional omap2 lookup
|
||||
* as a fallback
|
||||
*/
|
||||
- if (opp_init_cpufreq_table(mpu_dev, &freq_table))
|
||||
- clk_init_cpufreq_table(&freq_table);
|
||||
+ if (!freq_table) {
|
||||
+ if (opp_init_cpufreq_table(mpu_dev, &freq_table))
|
||||
+ clk_init_cpufreq_table(&freq_table);
|
||||
+ }
|
||||
|
||||
if (freq_table) {
|
||||
+ freq_table_users++;
|
||||
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
if (!result) {
|
||||
cpufreq_frequency_table_get_attr(freq_table,
|
||||
@@ -215,10 +234,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
clk_exit_cpufreq_table(&freq_table);
|
||||
WARN(true, "%s: fallback to clk_round(freq_table=%d)\n",
|
||||
__func__, result);
|
||||
- kfree(freq_table);
|
||||
- freq_table = NULL;
|
||||
+ freq_table_free();
|
||||
}
|
||||
}
|
||||
+ mutex_unlock(&freq_table_lock);
|
||||
|
||||
if (!freq_table) {
|
||||
policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
|
||||
@@ -251,9 +270,9 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
{
|
||||
- clk_exit_cpufreq_table(&freq_table);
|
||||
- kfree(freq_table);
|
||||
- freq_table = NULL;
|
||||
+ mutex_lock(&freq_table_lock);
|
||||
+ freq_table_free();
|
||||
+ mutex_unlock(&freq_table_lock);
|
||||
clk_put(mpu_clk);
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-134
@@ -1,134 +0,0 @@
|
||||
From 8726f3a7218b72a1003904a24bb000b3e4f9b4d1 Mon Sep 17 00:00:00 2001
|
||||
From: Mike Turquette <mturquette@ti.com>
|
||||
Date: Tue, 17 May 2011 09:35:54 -0500
|
||||
Subject: [PATCH 1/2] cpufreq: helpers for walking the frequency table
|
||||
|
||||
Two new functions for getting the next higher and next lower frequencies
|
||||
in the cpufreq table, based upon a frequency supplied in kHz.
|
||||
|
||||
This is useful for cpufreq governors that do not target frequencies
|
||||
based upon a percentage or a pre-determined value, but instead access
|
||||
the cpufreq table directly.
|
||||
|
||||
Signed-off-by: Mike Turquette <mturquette@ti.com>
|
||||
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
drivers/cpufreq/freq_table.c | 73 ++++++++++++++++++++++++++++++++++++++++++
|
||||
include/linux/cpufreq.h | 9 +++++
|
||||
2 files changed, 82 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c
|
||||
index 0543221..11a307b 100644
|
||||
--- a/drivers/cpufreq/freq_table.c
|
||||
+++ b/drivers/cpufreq/freq_table.c
|
||||
@@ -13,6 +13,7 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/cpufreq.h>
|
||||
+#include <linux/err.h>
|
||||
|
||||
#define dprintk(msg...) \
|
||||
cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, "freq-table", msg)
|
||||
@@ -174,6 +175,78 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cpufreq_frequency_table_target);
|
||||
|
||||
+int cpufreq_frequency_table_next_lowest(struct cpufreq_policy *policy,
|
||||
+ struct cpufreq_frequency_table *table, int *index)
|
||||
+{
|
||||
+ unsigned int cur_freq;
|
||||
+ unsigned int next_lowest_freq;
|
||||
+ int optimal_index = -1;
|
||||
+ int i = 0;
|
||||
+
|
||||
+ if (!policy || IS_ERR(policy) || !table || IS_ERR(table) ||
|
||||
+ !index || IS_ERR(index))
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ cur_freq = policy->cur;
|
||||
+ next_lowest_freq = policy->min;
|
||||
+
|
||||
+ /* we're at the lowest frequency in the table already, bail out */
|
||||
+ if (cur_freq == policy->min)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* walk the list, find closest freq to cur_freq that is below it */
|
||||
+ while(table[i].frequency != CPUFREQ_TABLE_END) {
|
||||
+ if (table[i].frequency < cur_freq &&
|
||||
+ table[i].frequency >= next_lowest_freq) {
|
||||
+ next_lowest_freq = table[i].frequency;
|
||||
+ optimal_index = table[i].index;
|
||||
+ }
|
||||
+
|
||||
+ i++;
|
||||
+ }
|
||||
+
|
||||
+ *index = optimal_index;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_next_lowest);
|
||||
+
|
||||
+int cpufreq_frequency_table_next_highest(struct cpufreq_policy *policy,
|
||||
+ struct cpufreq_frequency_table *table, int *index)
|
||||
+{
|
||||
+ unsigned int cur_freq;
|
||||
+ unsigned int next_higher_freq;
|
||||
+ int optimal_index = -1;
|
||||
+ int i = 0;
|
||||
+
|
||||
+ if (!policy || IS_ERR(policy) || !table || IS_ERR(table) ||
|
||||
+ !index || IS_ERR(index))
|
||||
+ return -ENOMEM;
|
||||
+
|
||||
+ cur_freq = policy->cur;
|
||||
+ next_higher_freq = policy->max;
|
||||
+
|
||||
+ /* we're at the highest frequency in the table already, bail out */
|
||||
+ if (cur_freq == policy->max)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* walk the list, find closest freq to cur_freq that is above it */
|
||||
+ while(table[i].frequency != CPUFREQ_TABLE_END) {
|
||||
+ if (table[i].frequency > cur_freq &&
|
||||
+ table[i].frequency <= next_higher_freq) {
|
||||
+ next_higher_freq = table[i].frequency;
|
||||
+ optimal_index = table[i].index;
|
||||
+ }
|
||||
+
|
||||
+ i++;
|
||||
+ }
|
||||
+
|
||||
+ *index = optimal_index;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(cpufreq_frequency_table_next_highest);
|
||||
+
|
||||
static DEFINE_PER_CPU(struct cpufreq_frequency_table *, cpufreq_show_table);
|
||||
/**
|
||||
* show_available_freqs - show available frequencies for the specified CPU
|
||||
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
|
||||
index 9343dd3..a38fca8 100644
|
||||
--- a/include/linux/cpufreq.h
|
||||
+++ b/include/linux/cpufreq.h
|
||||
@@ -396,6 +396,15 @@ void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table,
|
||||
|
||||
void cpufreq_frequency_table_put_attr(unsigned int cpu);
|
||||
|
||||
+/* the following are for use in governors, or anywhere else */
|
||||
+extern int cpufreq_frequency_table_next_lowest(struct cpufreq_policy *policy,
|
||||
+ struct cpufreq_frequency_table *table,
|
||||
+ int *index);
|
||||
+
|
||||
+extern int cpufreq_frequency_table_next_highest(struct cpufreq_policy *policy,
|
||||
+ struct cpufreq_frequency_table *table,
|
||||
+ int *index);
|
||||
+
|
||||
|
||||
/*********************************************************************
|
||||
* UNIFIED DEBUG HELPERS *
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-879
@@ -1,879 +0,0 @@
|
||||
From e4c777d8314d7925e4895f00b3a7ebd64a4d830b Mon Sep 17 00:00:00 2001
|
||||
From: Mike Turquette <mturquette@ti.com>
|
||||
Date: Tue, 17 May 2011 09:43:09 -0500
|
||||
Subject: [PATCH 2/2] cpufreq: introduce hotplug governor
|
||||
|
||||
The "hotplug" governor scales CPU frequency based on load, similar to
|
||||
"ondemand". It scales up to the highest frequency when "up_threshold"
|
||||
is crossed and scales down one frequency at a time when "down_threshold"
|
||||
is crossed. Unlike those governors, target frequencies are determined
|
||||
by directly accessing the CPUfreq frequency table, instead of taking
|
||||
some percentage of maximum available frequency.
|
||||
|
||||
The key difference in the "hotplug" governor is that it will disable
|
||||
auxillary CPUs when the system is very idle, and enable them again once
|
||||
the system becomes busy. This is achieved by averaging load over
|
||||
multiple sampling periods; if CPUs were online or offlined based on a
|
||||
single sampling period then thrashing will occur.
|
||||
|
||||
Sysfs entries exist for "hotplug_in_sampling_periods" and for
|
||||
"hotplug_out_sampling_periods" which determine how many consecutive
|
||||
periods get averaged to determine if auxillery CPUs should be onlined or
|
||||
offlined. Defaults are 5 periods and 20 periods respectively.
|
||||
Otherwise the standard sysfs entries you might find for "ondemand" and
|
||||
"conservative" governors are there.
|
||||
|
||||
To use this governor it is assumed that your CPUfreq driver has
|
||||
populated the CPUfreq table, CONFIG_NO_HZ is enabled and
|
||||
CONFIG_HOTPLUG_CPU is enabled.
|
||||
|
||||
Changes in V2:
|
||||
Corrected default sampling periods
|
||||
Optimized load history array resizing
|
||||
Maintain load history when resizing array
|
||||
Add locking to dbs_check_cpu
|
||||
Switch from enable_nonboot_cpus to cpu_up
|
||||
Switch from disable_nonboot_cpus to down_cpu
|
||||
Fix some printks
|
||||
Coding style around for-loops
|
||||
|
||||
Signed-off-by: Mike Turquette <mturquette@ti.com>
|
||||
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
Documentation/cpu-freq/governors.txt | 28 ++
|
||||
drivers/cpufreq/Kconfig | 33 ++
|
||||
drivers/cpufreq/Makefile | 1 +
|
||||
drivers/cpufreq/cpufreq_hotplug.c | 705 ++++++++++++++++++++++++++++++++++
|
||||
include/linux/cpufreq.h | 3 +
|
||||
5 files changed, 770 insertions(+), 0 deletions(-)
|
||||
create mode 100644 drivers/cpufreq/cpufreq_hotplug.c
|
||||
|
||||
diff --git a/Documentation/cpu-freq/governors.txt b/Documentation/cpu-freq/governors.txt
|
||||
index e74d0a2..c2e3d3d 100644
|
||||
--- a/Documentation/cpu-freq/governors.txt
|
||||
+++ b/Documentation/cpu-freq/governors.txt
|
||||
@@ -193,6 +193,34 @@ governor but for the opposite direction. For example when set to its
|
||||
default value of '20' it means that if the CPU usage needs to be below
|
||||
20% between samples to have the frequency decreased.
|
||||
|
||||
+
|
||||
+2.6 Hotplug
|
||||
+-----------
|
||||
+
|
||||
+The CPUfreq governor "hotplug" operates similary to "ondemand" and
|
||||
+"conservative". It's decisions are based primarily on CPU load. Like
|
||||
+"ondemand" the "hotplug" governor will ramp up to the highest frequency
|
||||
+once the run-time tunable "up_threshold" parameter is crossed. Like
|
||||
+"conservative", the "hotplug" governor exports a "down_threshold"
|
||||
+parameter that is also tunable at run-time. When the "down_threshold"
|
||||
+is crossed the CPU transitions to the next lowest frequency in the
|
||||
+CPUfreq frequency table instead of decrementing the frequency based on a
|
||||
+percentage of maximum load.
|
||||
+
|
||||
+The main reason "hotplug" governor exists is for architectures requiring
|
||||
+that only the master CPU be online in order to hit low-power states
|
||||
+(C-states). OMAP4 is one such example of this. The "hotplug" governor
|
||||
+is also helpful in reducing thermal output in devices with tight thermal
|
||||
+constraints.
|
||||
+
|
||||
+Auxillary CPUs are onlined/offline based on CPU load, but the decision
|
||||
+to do so is made after averaging several sampling windows. This is to
|
||||
+reduce CPU hotplug "thrashing", which can be caused by normal system
|
||||
+entropy and leads to lots of spurious plug-in and plug-out transitions.
|
||||
+The number of sampling periods averaged together is tunable via the
|
||||
+"hotplug_in_sampling_periods" and "hotplug_out_sampling_periods"
|
||||
+run-time tunable parameters.
|
||||
+
|
||||
3. The Governor Interface in the CPUfreq Core
|
||||
=============================================
|
||||
|
||||
diff --git a/drivers/cpufreq/Kconfig b/drivers/cpufreq/Kconfig
|
||||
index ca8ee80..c716a0e 100644
|
||||
--- a/drivers/cpufreq/Kconfig
|
||||
+++ b/drivers/cpufreq/Kconfig
|
||||
@@ -110,6 +110,19 @@ config CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
|
||||
Be aware that not all cpufreq drivers support the conservative
|
||||
governor. If unsure have a look at the help section of the
|
||||
driver. Fallback governor will be the performance governor.
|
||||
+
|
||||
+config CPU_FREQ_DEFAULT_GOV_HOTPLUG
|
||||
+ bool "hotplug"
|
||||
+ select CPU_FREQ_GOV_HOTPLUG
|
||||
+ select CPU_FREQ_GOV_PERFORMANCE
|
||||
+ help
|
||||
+ Use the CPUFreq governor 'hotplug' as default. This allows you
|
||||
+ to get a full dynamic frequency capable system with CPU
|
||||
+ hotplug support by simply loading your cpufreq low-level
|
||||
+ hardware driver. Be aware that not all cpufreq drivers
|
||||
+ support the hotplug governor. If unsure have a look at
|
||||
+ the help section of the driver. Fallback governor will be the
|
||||
+ performance governor.
|
||||
endchoice
|
||||
|
||||
config CPU_FREQ_GOV_PERFORMANCE
|
||||
@@ -190,4 +203,24 @@ config CPU_FREQ_GOV_CONSERVATIVE
|
||||
|
||||
If in doubt, say N.
|
||||
|
||||
+config CPU_FREQ_GOV_HOTPLUG
|
||||
+ tristate "'hotplug' cpufreq governor"
|
||||
+ depends on CPU_FREQ && NO_HZ && HOTPLUG_CPU
|
||||
+ help
|
||||
+ 'hotplug' - this driver mimics the frequency scaling behavior
|
||||
+ in 'ondemand', but with several key differences. First is
|
||||
+ that frequency transitions use the CPUFreq table directly,
|
||||
+ instead of incrementing in a percentage of the maximum
|
||||
+ available frequency. Second 'hotplug' will offline auxillary
|
||||
+ CPUs when the system is idle, and online those CPUs once the
|
||||
+ system becomes busy again. This last feature is needed for
|
||||
+ architectures which transition to low power states when only
|
||||
+ the "master" CPU is online, or for thermally constrained
|
||||
+ devices.
|
||||
+
|
||||
+ If you don't have one of these architectures or devices, use
|
||||
+ 'ondemand' instead.
|
||||
+
|
||||
+ If in doubt, say N.
|
||||
+
|
||||
endif # CPU_FREQ
|
||||
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
|
||||
index 71fc3b4..05d564c 100644
|
||||
--- a/drivers/cpufreq/Makefile
|
||||
+++ b/drivers/cpufreq/Makefile
|
||||
@@ -9,6 +9,7 @@ obj-$(CONFIG_CPU_FREQ_GOV_POWERSAVE) += cpufreq_powersave.o
|
||||
obj-$(CONFIG_CPU_FREQ_GOV_USERSPACE) += cpufreq_userspace.o
|
||||
obj-$(CONFIG_CPU_FREQ_GOV_ONDEMAND) += cpufreq_ondemand.o
|
||||
obj-$(CONFIG_CPU_FREQ_GOV_CONSERVATIVE) += cpufreq_conservative.o
|
||||
+obj-$(CONFIG_CPU_FREQ_GOV_HOTPLUG) += cpufreq_hotplug.o
|
||||
|
||||
# CPUfreq cross-arch helpers
|
||||
obj-$(CONFIG_CPU_FREQ_TABLE) += freq_table.o
|
||||
diff --git a/drivers/cpufreq/cpufreq_hotplug.c b/drivers/cpufreq/cpufreq_hotplug.c
|
||||
new file mode 100644
|
||||
index 0000000..85aa6d2
|
||||
--- /dev/null
|
||||
+++ b/drivers/cpufreq/cpufreq_hotplug.c
|
||||
@@ -0,0 +1,705 @@
|
||||
+/*
|
||||
+ * CPUFreq hotplug governor
|
||||
+ *
|
||||
+ * Copyright (C) 2010 Texas Instruments, Inc.
|
||||
+ * Mike Turquette <mturquette@ti.com>
|
||||
+ * Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
+ *
|
||||
+ * Based on ondemand governor
|
||||
+ * Copyright (C) 2001 Russell King
|
||||
+ * (C) 2003 Venkatesh Pallipadi <venkatesh.pallipadi@intel.com>,
|
||||
+ * Jun Nakajima <jun.nakajima@intel.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.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/module.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/cpufreq.h>
|
||||
+#include <linux/cpu.h>
|
||||
+#include <linux/jiffies.h>
|
||||
+#include <linux/kernel_stat.h>
|
||||
+#include <linux/mutex.h>
|
||||
+#include <linux/hrtimer.h>
|
||||
+#include <linux/tick.h>
|
||||
+#include <linux/ktime.h>
|
||||
+#include <linux/sched.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/slab.h>
|
||||
+
|
||||
+/* greater than 80% avg load across online CPUs increases frequency */
|
||||
+#define DEFAULT_UP_FREQ_MIN_LOAD (80)
|
||||
+
|
||||
+/* less than 20% avg load across online CPUs decreases frequency */
|
||||
+#define DEFAULT_DOWN_FREQ_MAX_LOAD (20)
|
||||
+
|
||||
+/* default sampling period (uSec) is bogus; 10x ondemand's default for x86 */
|
||||
+#define DEFAULT_SAMPLING_PERIOD (100000)
|
||||
+
|
||||
+/* default number of sampling periods to average before hotplug-in decision */
|
||||
+#define DEFAULT_HOTPLUG_IN_SAMPLING_PERIODS (5)
|
||||
+
|
||||
+/* default number of sampling periods to average before hotplug-out decision */
|
||||
+#define DEFAULT_HOTPLUG_OUT_SAMPLING_PERIODS (20)
|
||||
+
|
||||
+static void do_dbs_timer(struct work_struct *work);
|
||||
+static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
|
||||
+ unsigned int event);
|
||||
+
|
||||
+#ifndef CONFIG_CPU_FREQ_DEFAULT_GOV_HOTPLUG
|
||||
+static
|
||||
+#endif
|
||||
+struct cpufreq_governor cpufreq_gov_hotplug = {
|
||||
+ .name = "hotplug",
|
||||
+ .governor = cpufreq_governor_dbs,
|
||||
+ .owner = THIS_MODULE,
|
||||
+};
|
||||
+
|
||||
+struct cpu_dbs_info_s {
|
||||
+ cputime64_t prev_cpu_idle;
|
||||
+ cputime64_t prev_cpu_wall;
|
||||
+ cputime64_t prev_cpu_nice;
|
||||
+ struct cpufreq_policy *cur_policy;
|
||||
+ struct delayed_work work;
|
||||
+ struct cpufreq_frequency_table *freq_table;
|
||||
+ int cpu;
|
||||
+ /*
|
||||
+ * percpu mutex that serializes governor limit change with
|
||||
+ * do_dbs_timer invocation. We do not want do_dbs_timer to run
|
||||
+ * when user is changing the governor or limits.
|
||||
+ */
|
||||
+ struct mutex timer_mutex;
|
||||
+};
|
||||
+static DEFINE_PER_CPU(struct cpu_dbs_info_s, hp_cpu_dbs_info);
|
||||
+
|
||||
+static unsigned int dbs_enable; /* number of CPUs using this policy */
|
||||
+
|
||||
+/*
|
||||
+ * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on
|
||||
+ * different CPUs. It protects dbs_enable in governor start/stop.
|
||||
+ */
|
||||
+static DEFINE_MUTEX(dbs_mutex);
|
||||
+
|
||||
+static struct workqueue_struct *khotplug_wq;
|
||||
+
|
||||
+static struct dbs_tuners {
|
||||
+ unsigned int sampling_rate;
|
||||
+ unsigned int up_threshold;
|
||||
+ unsigned int down_threshold;
|
||||
+ unsigned int hotplug_in_sampling_periods;
|
||||
+ unsigned int hotplug_out_sampling_periods;
|
||||
+ unsigned int hotplug_load_index;
|
||||
+ unsigned int *hotplug_load_history;
|
||||
+ unsigned int ignore_nice;
|
||||
+ unsigned int io_is_busy;
|
||||
+} dbs_tuners_ins = {
|
||||
+ .sampling_rate = DEFAULT_SAMPLING_PERIOD,
|
||||
+ .up_threshold = DEFAULT_UP_FREQ_MIN_LOAD,
|
||||
+ .down_threshold = DEFAULT_DOWN_FREQ_MAX_LOAD,
|
||||
+ .hotplug_in_sampling_periods = DEFAULT_HOTPLUG_IN_SAMPLING_PERIODS,
|
||||
+ .hotplug_out_sampling_periods = DEFAULT_HOTPLUG_OUT_SAMPLING_PERIODS,
|
||||
+ .hotplug_load_index = 0,
|
||||
+ .ignore_nice = 0,
|
||||
+ .io_is_busy = 0,
|
||||
+};
|
||||
+
|
||||
+/*
|
||||
+ * A corner case exists when switching io_is_busy at run-time: comparing idle
|
||||
+ * times from a non-io_is_busy period to an io_is_busy period (or vice-versa)
|
||||
+ * will misrepresent the actual change in system idleness. We ignore this
|
||||
+ * corner case: enabling io_is_busy might cause freq increase and disabling
|
||||
+ * might cause freq decrease, which probably matches the original intent.
|
||||
+ */
|
||||
+static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
|
||||
+{
|
||||
+ u64 idle_time;
|
||||
+ u64 iowait_time;
|
||||
+
|
||||
+ /* cpufreq-hotplug always assumes CONFIG_NO_HZ */
|
||||
+ idle_time = get_cpu_idle_time_us(cpu, wall);
|
||||
+
|
||||
+ /* add time spent doing I/O to idle time */
|
||||
+ if (dbs_tuners_ins.io_is_busy) {
|
||||
+ iowait_time = get_cpu_iowait_time_us(cpu, wall);
|
||||
+ /* cpufreq-hotplug always assumes CONFIG_NO_HZ */
|
||||
+ if (iowait_time != -1ULL && idle_time >= iowait_time)
|
||||
+ idle_time -= iowait_time;
|
||||
+ }
|
||||
+
|
||||
+ return idle_time;
|
||||
+}
|
||||
+
|
||||
+/************************** sysfs interface ************************/
|
||||
+
|
||||
+/* XXX look at global sysfs macros in cpufreq.h, can those be used here? */
|
||||
+
|
||||
+/* cpufreq_hotplug Governor Tunables */
|
||||
+#define show_one(file_name, object) \
|
||||
+static ssize_t show_##file_name \
|
||||
+(struct kobject *kobj, struct attribute *attr, char *buf) \
|
||||
+{ \
|
||||
+ return sprintf(buf, "%u\n", dbs_tuners_ins.object); \
|
||||
+}
|
||||
+show_one(sampling_rate, sampling_rate);
|
||||
+show_one(up_threshold, up_threshold);
|
||||
+show_one(down_threshold, down_threshold);
|
||||
+show_one(hotplug_in_sampling_periods, hotplug_in_sampling_periods);
|
||||
+show_one(hotplug_out_sampling_periods, hotplug_out_sampling_periods);
|
||||
+show_one(ignore_nice_load, ignore_nice);
|
||||
+show_one(io_is_busy, io_is_busy);
|
||||
+
|
||||
+static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
|
||||
+ const char *buf, size_t count)
|
||||
+{
|
||||
+ unsigned int input;
|
||||
+ int ret;
|
||||
+ ret = sscanf(buf, "%u", &input);
|
||||
+ if (ret != 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ dbs_tuners_ins.sampling_rate = input;
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_up_threshold(struct kobject *a, struct attribute *b,
|
||||
+ const char *buf, size_t count)
|
||||
+{
|
||||
+ unsigned int input;
|
||||
+ int ret;
|
||||
+ ret = sscanf(buf, "%u", &input);
|
||||
+
|
||||
+ if (ret != 1 || input <= dbs_tuners_ins.down_threshold) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ dbs_tuners_ins.up_threshold = input;
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_down_threshold(struct kobject *a, struct attribute *b,
|
||||
+ const char *buf, size_t count)
|
||||
+{
|
||||
+ unsigned int input;
|
||||
+ int ret;
|
||||
+ ret = sscanf(buf, "%u", &input);
|
||||
+
|
||||
+ if (ret != 1 || input >= dbs_tuners_ins.up_threshold) {
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ dbs_tuners_ins.down_threshold = input;
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_hotplug_in_sampling_periods(struct kobject *a,
|
||||
+ struct attribute *b, const char *buf, size_t count)
|
||||
+{
|
||||
+ unsigned int input;
|
||||
+ unsigned int *temp;
|
||||
+ unsigned int max_windows;
|
||||
+ int ret;
|
||||
+ ret = sscanf(buf, "%u", &input);
|
||||
+
|
||||
+ if (ret != 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* already using this value, bail out */
|
||||
+ if (input == dbs_tuners_ins.hotplug_in_sampling_periods)
|
||||
+ return count;
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ ret = count;
|
||||
+ max_windows = max(dbs_tuners_ins.hotplug_in_sampling_periods,
|
||||
+ dbs_tuners_ins.hotplug_out_sampling_periods);
|
||||
+
|
||||
+ /* no need to resize array */
|
||||
+ if (input <= max_windows) {
|
||||
+ dbs_tuners_ins.hotplug_in_sampling_periods = input;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* resize array */
|
||||
+ temp = kmalloc((sizeof(unsigned int) * input), GFP_KERNEL);
|
||||
+
|
||||
+ if (!temp || IS_ERR(temp)) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(temp, dbs_tuners_ins.hotplug_load_history,
|
||||
+ (max_windows * sizeof(unsigned int)));
|
||||
+ kfree(dbs_tuners_ins.hotplug_load_history);
|
||||
+
|
||||
+ /* replace old buffer, old number of sampling periods & old index */
|
||||
+ dbs_tuners_ins.hotplug_load_history = temp;
|
||||
+ dbs_tuners_ins.hotplug_in_sampling_periods = input;
|
||||
+ dbs_tuners_ins.hotplug_load_index = max_windows;
|
||||
+out:
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_hotplug_out_sampling_periods(struct kobject *a,
|
||||
+ struct attribute *b, const char *buf, size_t count)
|
||||
+{
|
||||
+ unsigned int input;
|
||||
+ unsigned int *temp;
|
||||
+ unsigned int max_windows;
|
||||
+ int ret;
|
||||
+ ret = sscanf(buf, "%u", &input);
|
||||
+
|
||||
+ if (ret != 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ /* already using this value, bail out */
|
||||
+ if (input == dbs_tuners_ins.hotplug_out_sampling_periods)
|
||||
+ return count;
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ ret = count;
|
||||
+ max_windows = max(dbs_tuners_ins.hotplug_in_sampling_periods,
|
||||
+ dbs_tuners_ins.hotplug_out_sampling_periods);
|
||||
+
|
||||
+ /* no need to resize array */
|
||||
+ if (input <= max_windows) {
|
||||
+ dbs_tuners_ins.hotplug_out_sampling_periods = input;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* resize array */
|
||||
+ temp = kmalloc((sizeof(unsigned int) * input), GFP_KERNEL);
|
||||
+
|
||||
+ if (!temp || IS_ERR(temp)) {
|
||||
+ ret = -ENOMEM;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ memcpy(temp, dbs_tuners_ins.hotplug_load_history,
|
||||
+ (max_windows * sizeof(unsigned int)));
|
||||
+ kfree(dbs_tuners_ins.hotplug_load_history);
|
||||
+
|
||||
+ /* replace old buffer, old number of sampling periods & old index */
|
||||
+ dbs_tuners_ins.hotplug_load_history = temp;
|
||||
+ dbs_tuners_ins.hotplug_out_sampling_periods = input;
|
||||
+ dbs_tuners_ins.hotplug_load_index = max_windows;
|
||||
+out:
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_ignore_nice_load(struct kobject *a, struct attribute *b,
|
||||
+ const char *buf, size_t count)
|
||||
+{
|
||||
+ unsigned int input;
|
||||
+ int ret;
|
||||
+
|
||||
+ unsigned int j;
|
||||
+
|
||||
+ ret = sscanf(buf, "%u", &input);
|
||||
+ if (ret != 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (input > 1)
|
||||
+ input = 1;
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+ return count;
|
||||
+ }
|
||||
+ dbs_tuners_ins.ignore_nice = input;
|
||||
+
|
||||
+ /* we need to re-evaluate prev_cpu_idle */
|
||||
+ for_each_online_cpu(j) {
|
||||
+ struct cpu_dbs_info_s *dbs_info;
|
||||
+ dbs_info = &per_cpu(hp_cpu_dbs_info, j);
|
||||
+ dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
|
||||
+ &dbs_info->prev_cpu_wall);
|
||||
+ if (dbs_tuners_ins.ignore_nice)
|
||||
+ dbs_info->prev_cpu_nice = kstat_cpu(j).cpustat.nice;
|
||||
+
|
||||
+ }
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+static ssize_t store_io_is_busy(struct kobject *a, struct attribute *b,
|
||||
+ const char *buf, size_t count)
|
||||
+{
|
||||
+ unsigned int input;
|
||||
+ int ret;
|
||||
+
|
||||
+ ret = sscanf(buf, "%u", &input);
|
||||
+ if (ret != 1)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ dbs_tuners_ins.io_is_busy = !!input;
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+
|
||||
+ return count;
|
||||
+}
|
||||
+
|
||||
+define_one_global_rw(sampling_rate);
|
||||
+define_one_global_rw(up_threshold);
|
||||
+define_one_global_rw(down_threshold);
|
||||
+define_one_global_rw(hotplug_in_sampling_periods);
|
||||
+define_one_global_rw(hotplug_out_sampling_periods);
|
||||
+define_one_global_rw(ignore_nice_load);
|
||||
+define_one_global_rw(io_is_busy);
|
||||
+
|
||||
+static struct attribute *dbs_attributes[] = {
|
||||
+ &sampling_rate.attr,
|
||||
+ &up_threshold.attr,
|
||||
+ &down_threshold.attr,
|
||||
+ &hotplug_in_sampling_periods.attr,
|
||||
+ &hotplug_out_sampling_periods.attr,
|
||||
+ &ignore_nice_load.attr,
|
||||
+ &io_is_busy.attr,
|
||||
+ NULL
|
||||
+};
|
||||
+
|
||||
+static struct attribute_group dbs_attr_group = {
|
||||
+ .attrs = dbs_attributes,
|
||||
+ .name = "hotplug",
|
||||
+};
|
||||
+
|
||||
+/************************** sysfs end ************************/
|
||||
+
|
||||
+static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
|
||||
+{
|
||||
+ /* combined load of all enabled CPUs */
|
||||
+ unsigned int total_load = 0;
|
||||
+ /* single largest CPU load */
|
||||
+ unsigned int max_load = 0;
|
||||
+ /* average load across all enabled CPUs */
|
||||
+ unsigned int avg_load = 0;
|
||||
+ /* average load across multiple sampling periods for hotplug events */
|
||||
+ unsigned int hotplug_in_avg_load = 0;
|
||||
+ unsigned int hotplug_out_avg_load = 0;
|
||||
+ /* number of sampling periods averaged for hotplug decisions */
|
||||
+ unsigned int periods;
|
||||
+
|
||||
+ struct cpufreq_policy *policy;
|
||||
+ unsigned int index = 0;
|
||||
+ unsigned int i, j;
|
||||
+
|
||||
+ policy = this_dbs_info->cur_policy;
|
||||
+
|
||||
+ /*
|
||||
+ * cpu load accounting
|
||||
+ * get highest load, total load and average load across all CPUs
|
||||
+ */
|
||||
+ for_each_cpu(j, policy->cpus) {
|
||||
+ unsigned int load;
|
||||
+ unsigned int idle_time, wall_time;
|
||||
+ cputime64_t cur_wall_time, cur_idle_time;
|
||||
+ struct cpu_dbs_info_s *j_dbs_info;
|
||||
+
|
||||
+ j_dbs_info = &per_cpu(hp_cpu_dbs_info, j);
|
||||
+
|
||||
+ /* update both cur_idle_time and cur_wall_time */
|
||||
+ cur_idle_time = get_cpu_idle_time(j, &cur_wall_time);
|
||||
+
|
||||
+ /* how much wall time has passed since last iteration? */
|
||||
+ wall_time = (unsigned int) cputime64_sub(cur_wall_time,
|
||||
+ j_dbs_info->prev_cpu_wall);
|
||||
+ j_dbs_info->prev_cpu_wall = cur_wall_time;
|
||||
+
|
||||
+ /* how much idle time has passed since last iteration? */
|
||||
+ idle_time = (unsigned int) cputime64_sub(cur_idle_time,
|
||||
+ j_dbs_info->prev_cpu_idle);
|
||||
+ j_dbs_info->prev_cpu_idle = cur_idle_time;
|
||||
+
|
||||
+ if (unlikely(!wall_time || wall_time < idle_time))
|
||||
+ continue;
|
||||
+
|
||||
+ /* load is the percentage of time not spent in idle */
|
||||
+ load = 100 * (wall_time - idle_time) / wall_time;
|
||||
+
|
||||
+ /* keep track of combined load across all CPUs */
|
||||
+ total_load += load;
|
||||
+
|
||||
+ /* keep track of highest single load across all CPUs */
|
||||
+ if (load > max_load)
|
||||
+ max_load = load;
|
||||
+ }
|
||||
+
|
||||
+ /* calculate the average load across all related CPUs */
|
||||
+ avg_load = total_load / num_online_cpus();
|
||||
+
|
||||
+
|
||||
+ /*
|
||||
+ * hotplug load accounting
|
||||
+ * average load over multiple sampling periods
|
||||
+ */
|
||||
+
|
||||
+ /* how many sampling periods do we use for hotplug decisions? */
|
||||
+ periods = max(dbs_tuners_ins.hotplug_in_sampling_periods,
|
||||
+ dbs_tuners_ins.hotplug_out_sampling_periods);
|
||||
+
|
||||
+ /* store avg_load in the circular buffer */
|
||||
+ dbs_tuners_ins.hotplug_load_history[dbs_tuners_ins.hotplug_load_index]
|
||||
+ = avg_load;
|
||||
+
|
||||
+ /* compute average load across in & out sampling periods */
|
||||
+ for (i = 0, j = dbs_tuners_ins.hotplug_load_index;
|
||||
+ i < periods; i++, j--) {
|
||||
+ if (i < dbs_tuners_ins.hotplug_in_sampling_periods)
|
||||
+ hotplug_in_avg_load +=
|
||||
+ dbs_tuners_ins.hotplug_load_history[j];
|
||||
+ if (i < dbs_tuners_ins.hotplug_out_sampling_periods)
|
||||
+ hotplug_out_avg_load +=
|
||||
+ dbs_tuners_ins.hotplug_load_history[j];
|
||||
+
|
||||
+ if (j == 0)
|
||||
+ j = periods;
|
||||
+ }
|
||||
+
|
||||
+ hotplug_in_avg_load = hotplug_in_avg_load /
|
||||
+ dbs_tuners_ins.hotplug_in_sampling_periods;
|
||||
+
|
||||
+ hotplug_out_avg_load = hotplug_out_avg_load /
|
||||
+ dbs_tuners_ins.hotplug_out_sampling_periods;
|
||||
+
|
||||
+ /* return to first element if we're at the circular buffer's end */
|
||||
+ if (++dbs_tuners_ins.hotplug_load_index == periods)
|
||||
+ dbs_tuners_ins.hotplug_load_index = 0;
|
||||
+
|
||||
+ /* check for frequency increase */
|
||||
+ if (avg_load > dbs_tuners_ins.up_threshold) {
|
||||
+ /* should we enable auxillary CPUs? */
|
||||
+ if (num_online_cpus() < 2 && hotplug_in_avg_load >
|
||||
+ dbs_tuners_ins.up_threshold) {
|
||||
+ /* hotplug with cpufreq is nasty
|
||||
+ * a call to cpufreq_governor_dbs may cause a lockup.
|
||||
+ * wq is not running here so its safe.
|
||||
+ */
|
||||
+ mutex_unlock(&this_dbs_info->timer_mutex);
|
||||
+ cpu_up(1);
|
||||
+ mutex_lock(&this_dbs_info->timer_mutex);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* increase to highest frequency supported */
|
||||
+ if (policy->cur < policy->max)
|
||||
+ __cpufreq_driver_target(policy, policy->max,
|
||||
+ CPUFREQ_RELATION_H);
|
||||
+
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* check for frequency decrease */
|
||||
+ if (avg_load < dbs_tuners_ins.down_threshold) {
|
||||
+ /* are we at the minimum frequency already? */
|
||||
+ if (policy->cur == policy->min) {
|
||||
+ /* should we disable auxillary CPUs? */
|
||||
+ if (num_online_cpus() > 1 && hotplug_out_avg_load <
|
||||
+ dbs_tuners_ins.down_threshold) {
|
||||
+ mutex_unlock(&this_dbs_info->timer_mutex);
|
||||
+ cpu_down(1);
|
||||
+ mutex_lock(&this_dbs_info->timer_mutex);
|
||||
+ }
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* bump down to the next lowest frequency in the table */
|
||||
+ if (cpufreq_frequency_table_next_lowest(policy,
|
||||
+ this_dbs_info->freq_table, &index)) {
|
||||
+ pr_err("%s: failed to get next lowest frequency\n",
|
||||
+ __func__);
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ __cpufreq_driver_target(policy,
|
||||
+ this_dbs_info->freq_table[index].frequency,
|
||||
+ CPUFREQ_RELATION_L);
|
||||
+ }
|
||||
+out:
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static void do_dbs_timer(struct work_struct *work)
|
||||
+{
|
||||
+ struct cpu_dbs_info_s *dbs_info =
|
||||
+ container_of(work, struct cpu_dbs_info_s, work.work);
|
||||
+ unsigned int cpu = dbs_info->cpu;
|
||||
+
|
||||
+ /* We want all related CPUs to do sampling nearly on same jiffy */
|
||||
+ int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
|
||||
+
|
||||
+ mutex_lock(&dbs_info->timer_mutex);
|
||||
+ dbs_check_cpu(dbs_info);
|
||||
+ queue_delayed_work_on(cpu, khotplug_wq, &dbs_info->work, delay);
|
||||
+ mutex_unlock(&dbs_info->timer_mutex);
|
||||
+}
|
||||
+
|
||||
+static inline void dbs_timer_init(struct cpu_dbs_info_s *dbs_info)
|
||||
+{
|
||||
+ /* We want all related CPUs to do sampling nearly on same jiffy */
|
||||
+ int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate);
|
||||
+ delay -= jiffies % delay;
|
||||
+
|
||||
+ INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer);
|
||||
+ queue_delayed_work_on(dbs_info->cpu, khotplug_wq, &dbs_info->work,
|
||||
+ delay);
|
||||
+}
|
||||
+
|
||||
+static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
|
||||
+{
|
||||
+ cancel_delayed_work_sync(&dbs_info->work);
|
||||
+}
|
||||
+
|
||||
+static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
|
||||
+ unsigned int event)
|
||||
+{
|
||||
+ unsigned int cpu = policy->cpu;
|
||||
+ struct cpu_dbs_info_s *this_dbs_info;
|
||||
+ unsigned int i, j, max_periods;
|
||||
+ int rc;
|
||||
+
|
||||
+ this_dbs_info = &per_cpu(hp_cpu_dbs_info, cpu);
|
||||
+
|
||||
+ switch (event) {
|
||||
+ case CPUFREQ_GOV_START:
|
||||
+ if ((!cpu_online(cpu)) || (!policy->cur))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ dbs_enable++;
|
||||
+ for_each_cpu(j, policy->cpus) {
|
||||
+ struct cpu_dbs_info_s *j_dbs_info;
|
||||
+ j_dbs_info = &per_cpu(hp_cpu_dbs_info, j);
|
||||
+ j_dbs_info->cur_policy = policy;
|
||||
+
|
||||
+ j_dbs_info->prev_cpu_idle = get_cpu_idle_time(j,
|
||||
+ &j_dbs_info->prev_cpu_wall);
|
||||
+ if (dbs_tuners_ins.ignore_nice) {
|
||||
+ j_dbs_info->prev_cpu_nice =
|
||||
+ kstat_cpu(j).cpustat.nice;
|
||||
+ }
|
||||
+
|
||||
+ max_periods = max(DEFAULT_HOTPLUG_IN_SAMPLING_PERIODS,
|
||||
+ DEFAULT_HOTPLUG_OUT_SAMPLING_PERIODS);
|
||||
+ dbs_tuners_ins.hotplug_load_history = kmalloc(
|
||||
+ (sizeof(unsigned int) * max_periods),
|
||||
+ GFP_KERNEL);
|
||||
+ if (!dbs_tuners_ins.hotplug_load_history) {
|
||||
+ WARN_ON(1);
|
||||
+ return -ENOMEM;
|
||||
+ }
|
||||
+ for (i = 0; i < max_periods; i++)
|
||||
+ dbs_tuners_ins.hotplug_load_history[i] = 50;
|
||||
+ }
|
||||
+ this_dbs_info->cpu = cpu;
|
||||
+ this_dbs_info->freq_table = cpufreq_frequency_get_table(cpu);
|
||||
+ /*
|
||||
+ * Start the timerschedule work, when this governor
|
||||
+ * is used for first time
|
||||
+ */
|
||||
+ if (dbs_enable == 1) {
|
||||
+ rc = sysfs_create_group(cpufreq_global_kobject,
|
||||
+ &dbs_attr_group);
|
||||
+ if (rc) {
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+ return rc;
|
||||
+ }
|
||||
+ }
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+
|
||||
+ mutex_init(&this_dbs_info->timer_mutex);
|
||||
+ dbs_timer_init(this_dbs_info);
|
||||
+ break;
|
||||
+
|
||||
+ case CPUFREQ_GOV_STOP:
|
||||
+ dbs_timer_exit(this_dbs_info);
|
||||
+
|
||||
+ mutex_lock(&dbs_mutex);
|
||||
+ mutex_destroy(&this_dbs_info->timer_mutex);
|
||||
+ dbs_enable--;
|
||||
+ mutex_unlock(&dbs_mutex);
|
||||
+ if (!dbs_enable)
|
||||
+ sysfs_remove_group(cpufreq_global_kobject,
|
||||
+ &dbs_attr_group);
|
||||
+ kfree(dbs_tuners_ins.hotplug_load_history);
|
||||
+ /*
|
||||
+ * XXX BIG CAVEAT: Stopping the governor with CPU1 offline
|
||||
+ * will result in it remaining offline until the user onlines
|
||||
+ * it again. It is up to the user to do this (for now).
|
||||
+ */
|
||||
+ break;
|
||||
+
|
||||
+ case CPUFREQ_GOV_LIMITS:
|
||||
+ mutex_lock(&this_dbs_info->timer_mutex);
|
||||
+ if (policy->max < this_dbs_info->cur_policy->cur)
|
||||
+ __cpufreq_driver_target(this_dbs_info->cur_policy,
|
||||
+ policy->max, CPUFREQ_RELATION_H);
|
||||
+ else if (policy->min > this_dbs_info->cur_policy->cur)
|
||||
+ __cpufreq_driver_target(this_dbs_info->cur_policy,
|
||||
+ policy->min, CPUFREQ_RELATION_L);
|
||||
+ mutex_unlock(&this_dbs_info->timer_mutex);
|
||||
+ break;
|
||||
+ }
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int __init cpufreq_gov_dbs_init(void)
|
||||
+{
|
||||
+ int err;
|
||||
+ cputime64_t wall;
|
||||
+ u64 idle_time;
|
||||
+ int cpu = get_cpu();
|
||||
+
|
||||
+ idle_time = get_cpu_idle_time_us(cpu, &wall);
|
||||
+ put_cpu();
|
||||
+ if (idle_time != -1ULL) {
|
||||
+ dbs_tuners_ins.up_threshold = DEFAULT_UP_FREQ_MIN_LOAD;
|
||||
+ } else {
|
||||
+ pr_err("cpufreq-hotplug: %s: assumes CONFIG_NO_HZ\n",
|
||||
+ __func__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+
|
||||
+ khotplug_wq = create_workqueue("khotplug");
|
||||
+ if (!khotplug_wq) {
|
||||
+ pr_err("Creation of khotplug failed\n");
|
||||
+ return -EFAULT;
|
||||
+ }
|
||||
+ err = cpufreq_register_governor(&cpufreq_gov_hotplug);
|
||||
+ if (err)
|
||||
+ destroy_workqueue(khotplug_wq);
|
||||
+
|
||||
+ return err;
|
||||
+}
|
||||
+
|
||||
+static void __exit cpufreq_gov_dbs_exit(void)
|
||||
+{
|
||||
+ cpufreq_unregister_governor(&cpufreq_gov_hotplug);
|
||||
+ destroy_workqueue(khotplug_wq);
|
||||
+}
|
||||
+
|
||||
+MODULE_AUTHOR("Mike Turquette <mturquette@ti.com>");
|
||||
+MODULE_DESCRIPTION("'cpufreq_hotplug' - cpufreq governor for dynamic frequency scaling and CPU hotplugging");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+
|
||||
+#ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_HOTPLUG
|
||||
+fs_initcall(cpufreq_gov_dbs_init);
|
||||
+#else
|
||||
+module_init(cpufreq_gov_dbs_init);
|
||||
+#endif
|
||||
+module_exit(cpufreq_gov_dbs_exit);
|
||||
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
|
||||
index a38fca8..6cbc3df 100644
|
||||
--- a/include/linux/cpufreq.h
|
||||
+++ b/include/linux/cpufreq.h
|
||||
@@ -355,6 +355,9 @@ extern struct cpufreq_governor cpufreq_gov_ondemand;
|
||||
#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE)
|
||||
extern struct cpufreq_governor cpufreq_gov_conservative;
|
||||
#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_conservative)
|
||||
+#elif defined(CONFIG_CPU_FREQ_DEFAULT_GOV_HOTPLUG)
|
||||
+extern struct cpufreq_governor cpufreq_gov_hotplug;
|
||||
+#define CPUFREQ_DEFAULT_GOVERNOR (&cpufreq_gov_hotplug)
|
||||
#endif
|
||||
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
From 33668b07abd5e66a263cc8b4b88587646f38bed0 Mon Sep 17 00:00:00 2001
|
||||
From: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
|
||||
Date: Wed, 11 Aug 2010 17:02:43 -0700
|
||||
Subject: [PATCH 1/8] OMAP: CPUfreq: ensure driver initializes after cpufreq framework and governors
|
||||
|
||||
Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
---
|
||||
arch/arm/plat-omap/cpu-omap.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
index da4f68d..cd09d4b 100644
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ b/arch/arm/plat-omap/cpu-omap.c
|
||||
@@ -160,7 +160,7 @@ static int __init omap_cpufreq_init(void)
|
||||
return cpufreq_register_driver(&omap_driver);
|
||||
}
|
||||
|
||||
-arch_initcall(omap_cpufreq_init);
|
||||
+late_initcall(omap_cpufreq_init);
|
||||
|
||||
/*
|
||||
* if ever we want to remove this, upon cleanup call:
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-31
@@ -1,31 +0,0 @@
|
||||
From e89b1544450fb8410a44004e48d6b330bc39f0ce Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
Date: Wed, 11 Aug 2010 17:05:38 -0700
|
||||
Subject: [PATCH 2/8] OMAP: CPUfreq: ensure policy is fully initialized
|
||||
|
||||
Ensure policy min/max/cur values are initialized when OMAP
|
||||
CPUfreq driver starts.
|
||||
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
---
|
||||
arch/arm/plat-omap/cpu-omap.c | 4 ++++
|
||||
1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
index cd09d4b..1b36664 100644
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ b/arch/arm/plat-omap/cpu-omap.c
|
||||
@@ -126,6 +126,10 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
VERY_HI_RATE) / 1000;
|
||||
}
|
||||
|
||||
+ policy->min = policy->cpuinfo.min_freq;
|
||||
+ policy->max = policy->cpuinfo.max_freq;
|
||||
+ policy->cur = omap_getspeed(0);
|
||||
+
|
||||
/* FIXME: what's the actual transition time? */
|
||||
policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-263
@@ -1,263 +0,0 @@
|
||||
From 948b868e4a83b054e8a58362238bc6cd61c0aeab Mon Sep 17 00:00:00 2001
|
||||
From: Rajendra Nayak <rnayak@ti.com>
|
||||
Date: Mon, 10 Nov 2008 17:00:25 +0530
|
||||
Subject: [PATCH 3/8] OMAP3 PM: CPUFreq driver for OMAP3
|
||||
|
||||
CPUFreq driver for OMAP3
|
||||
|
||||
With additional fixes and cleanups from Tero Kristo:
|
||||
- Fix rate calculation bug in omap3_select_table_rate
|
||||
- Refreshed DVFS VDD1 control against latest clock fw
|
||||
|
||||
Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
|
||||
OMAP3: PM: CPUFreq: Fix omap_getspeed.
|
||||
|
||||
Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
|
||||
|
||||
Make sure omap cpufreq driver initializes after cpufreq framework and governors
|
||||
|
||||
Signed-off-by: Peter 'p2' De Schrijver <peter.de-schrijver@nokia.com>
|
||||
|
||||
merge: CPUFreq: remove obsolete funcs
|
||||
|
||||
OMAP3 clock: Update cpufreq driver
|
||||
|
||||
This patch removes all refrences to virtual clock
|
||||
nodes in CPUFreq driver.
|
||||
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
Signed-off-by: Tero Kristo <tero.kristo@nokia.com>
|
||||
Signed-off-by: Jean Pihet <jpihet@mvista.com>
|
||||
|
||||
PM: Prevent direct cpufreq scaling during initialization
|
||||
|
||||
It is seen that the OMAP specific cpufreq initialization code tries to
|
||||
scale the MPU frequency to the highest possible without taking care of
|
||||
the voltage level. On power on reset the power IC does not provide the
|
||||
necessary voltage for the highest available MPU frequency (that would
|
||||
satisfy all Si families). This potentially is an window of opportunity
|
||||
for things to go wrong.
|
||||
|
||||
Signed-off-by: Romit Dasgupta <romit@ti.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
|
||||
OMAP3: PM: enable 600MHz (overdrive) OPP
|
||||
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
|
||||
omap3: introduce cpufreq
|
||||
|
||||
OMAP OPP layer functions now have dependencies of CONFIG_CPU_FREQ only.
|
||||
|
||||
With this patch, omap opp layer now has its compilation flags
|
||||
bound to CONFIG_CPU_FREQ. Also its code has been removed from pm34xx.c.
|
||||
|
||||
A new file has been created to contain cpu freq code related to
|
||||
OMAP3: cpufreq34xx.c
|
||||
|
||||
OMAP34xx and OMAP36xx family OPPs are made available
|
||||
|
||||
Signed-off-by: Eduardo Valentin <eduardo.valentin@nokia.com>
|
||||
Signed-off-by: Paul Walmsley <paul@pwsan.com>
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Vishwanath BS <vishwanath.bs@ti.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
Signed-off-by: Romit Dasgupta <romit@ti.com>
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
|
||||
omap3: cpufreq: allow default opp table init
|
||||
|
||||
For board files which choose to override the defaults, the existing
|
||||
mechanism will work, for boards that would like to work with defaults,
|
||||
allow init_common_hw to call init_opp_table to initialize if not
|
||||
already initialized. this will allow all omap boards which have opp
|
||||
tables predefined for a silicon to use the same.
|
||||
|
||||
Originally reported for overo:
|
||||
http://marc.info/?t=127265269400004&r=1&w=2
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Reported-by: Peter Tseng <tsenpet09@gmail.com>
|
||||
Cc: Cliff Brake <cliff.brake@gmail.com>
|
||||
Cc: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
|
||||
OMAP2: update OPP data to be device based
|
||||
|
||||
Cc: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
|
||||
OMAP3: CPUfreq: update to device-based OPP API
|
||||
|
||||
Update usage of OPP API to use new device-based API. This requires
|
||||
getting the 'struct device' for the MPU and using that with the OPP
|
||||
API.
|
||||
|
||||
Signed-off-by: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
|
||||
omap3: opp: make independent of cpufreq
|
||||
|
||||
Make opp3xx data which is registered with the opp layer
|
||||
dependent purely on CONFIG_PM as opp layer and pm.c users
|
||||
are CONFIG_PM dependent not cpufreq dependent.
|
||||
so we rename the data definition to opp3xxx_data.c (inline with what
|
||||
we have for omap2), also move the build definition to be under
|
||||
the existing CONFIG_PM build instead of CPUFREQ.
|
||||
|
||||
Cc: Eduardo Valentin <eduardo.valentin@nokia.com>
|
||||
Cc: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
Cc: Paul Walmsley <paul@pwsan.com>
|
||||
Cc: Rajendra Nayak <rnayak@ti.com>
|
||||
Cc: Sanjeev Premi <premi@ti.com>
|
||||
Cc: Thara Gopinath <thara@ti.com>
|
||||
Cc: Tony Lindgren <tony@atomide.com>
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/clock.h | 14 +++++++++++++-
|
||||
arch/arm/mach-omap2/clock34xx.c | 2 ++
|
||||
arch/arm/plat-omap/cpu-omap.c | 34 +++++++++++++++++++++++++++++++---
|
||||
3 files changed, 46 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/clock.h b/arch/arm/mach-omap2/clock.h
|
||||
index e10ff2b..0a07e50 100644
|
||||
--- a/arch/arm/mach-omap2/clock.h
|
||||
+++ b/arch/arm/mach-omap2/clock.h
|
||||
@@ -141,7 +141,9 @@ extern const struct clksel_rate gpt_sys_rates[];
|
||||
extern const struct clksel_rate gfx_l3_rates[];
|
||||
extern const struct clksel_rate dsp_ick_rates[];
|
||||
|
||||
-#if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ)
|
||||
+#ifdef CONFIG_CPU_FREQ
|
||||
+
|
||||
+#ifdef CONFIG_ARCH_OMAP2
|
||||
extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
|
||||
extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
|
||||
#else
|
||||
@@ -149,6 +151,16 @@ extern void omap2_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table)
|
||||
#define omap2_clk_exit_cpufreq_table 0
|
||||
#endif
|
||||
|
||||
+#ifdef CONFIG_ARCH_OMAP3
|
||||
+extern void omap3_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
|
||||
+extern void omap3_clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
|
||||
+#else
|
||||
+#define omap3_clk_init_cpufreq_table 0
|
||||
+#define omap3_clk_exit_cpufreq_table 0
|
||||
+#endif
|
||||
+
|
||||
+#endif /* CONFIG_CPU_FREQ */
|
||||
+
|
||||
extern const struct clkops clkops_omap2_iclk_dflt_wait;
|
||||
extern const struct clkops clkops_omap2_iclk_dflt;
|
||||
extern const struct clkops clkops_omap2_iclk_idle_only;
|
||||
diff --git a/arch/arm/mach-omap2/clock34xx.c b/arch/arm/mach-omap2/clock34xx.c
|
||||
index 1fc96b9..119e135 100644
|
||||
--- a/arch/arm/mach-omap2/clock34xx.c
|
||||
+++ b/arch/arm/mach-omap2/clock34xx.c
|
||||
@@ -20,6 +20,8 @@
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/cpufreq.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
index 1b36664..f0f9430 100644
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ b/arch/arm/plat-omap/cpu-omap.c
|
||||
@@ -8,6 +8,10 @@
|
||||
*
|
||||
* Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
|
||||
*
|
||||
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
|
||||
+ * Updated to support OMAP3
|
||||
+ * Rajendra Nayak <rnayak@ti.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.
|
||||
@@ -26,12 +30,19 @@
|
||||
#include <plat/clock.h>
|
||||
#include <asm/system.h>
|
||||
|
||||
+#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
+#include <plat/omap-pm.h>
|
||||
+#include <plat/opp.h>
|
||||
+#endif
|
||||
+
|
||||
#define VERY_HI_RATE 900000000
|
||||
|
||||
static struct cpufreq_frequency_table *freq_table;
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP1
|
||||
#define MPU_CLK "mpu"
|
||||
+#elif CONFIG_ARCH_OMAP3
|
||||
+#define MPU_CLK "arm_fck"
|
||||
#else
|
||||
#define MPU_CLK "virt_prcm_set"
|
||||
#endif
|
||||
@@ -73,7 +84,13 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
+#ifdef CONFIG_ARCH_OMAP1
|
||||
struct cpufreq_freqs freqs;
|
||||
+#endif
|
||||
+#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
+ unsigned long freq;
|
||||
+ struct device *mpu_dev = omap2_get_mpuss_device();
|
||||
+#endif
|
||||
int ret = 0;
|
||||
|
||||
/* Ensure desired rate is within allowed range. Some govenors
|
||||
@@ -83,13 +100,13 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
if (target_freq > policy->max)
|
||||
target_freq = policy->max;
|
||||
|
||||
+#ifdef CONFIG_ARCH_OMAP1
|
||||
freqs.old = omap_getspeed(0);
|
||||
freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
freqs.cpu = 0;
|
||||
|
||||
if (freqs.old == freqs.new)
|
||||
return ret;
|
||||
-
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
#ifdef CONFIG_CPU_FREQ_DEBUG
|
||||
printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n",
|
||||
@@ -97,7 +114,11 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
#endif
|
||||
ret = clk_set_rate(mpu_clk, freqs.new * 1000);
|
||||
cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
-
|
||||
+#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
+ freq = target_freq * 1000;
|
||||
+ if (opp_find_freq_ceil(mpu_dev, &freq))
|
||||
+ omap_pm_cpu_set_freq(freq);
|
||||
+#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -114,7 +135,14 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
policy->cur = policy->min = policy->max = omap_getspeed(0);
|
||||
|
||||
- clk_init_cpufreq_table(&freq_table);
|
||||
+ if (!cpu_is_omap34xx()) {
|
||||
+ clk_init_cpufreq_table(&freq_table);
|
||||
+ } else {
|
||||
+ struct device *mpu_dev = omap2_get_mpuss_device();
|
||||
+
|
||||
+ opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
+ }
|
||||
+
|
||||
if (freq_table) {
|
||||
result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
if (!result)
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
From 86227f1eb341e571163464cb0a412ed2179f2541 Mon Sep 17 00:00:00 2001
|
||||
From: Silesh C V <silesh@ti.com>
|
||||
Date: Wed, 29 Sep 2010 14:52:54 +0530
|
||||
Subject: [PATCH 4/8] OMAP: PM: CPUFREQ: Fix conditional compilation
|
||||
|
||||
Fix conditional compilation. A conditional expresiion
|
||||
should follow "#elif", in this case #elif clause should
|
||||
check whether CONFIG_ARCH_OMAP3 is defined or not
|
||||
(ie. defined(CONFIG_ARCH_OMAP3)) rather than checking for
|
||||
the value of the macro.
|
||||
|
||||
Signed-off-by: Silesh C V <silesh@ti.com>
|
||||
---
|
||||
arch/arm/plat-omap/cpu-omap.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
index f0f9430..c3ac065 100644
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ b/arch/arm/plat-omap/cpu-omap.c
|
||||
@@ -41,7 +41,7 @@ static struct cpufreq_frequency_table *freq_table;
|
||||
|
||||
#ifdef CONFIG_ARCH_OMAP1
|
||||
#define MPU_CLK "mpu"
|
||||
-#elif CONFIG_ARCH_OMAP3
|
||||
+#elif defined(CONFIG_ARCH_OMAP3)
|
||||
#define MPU_CLK "arm_fck"
|
||||
#else
|
||||
#define MPU_CLK "virt_prcm_set"
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
From 4764137dd613362656726a15cb8184724aeb99bb Mon Sep 17 00:00:00 2001
|
||||
From: Kevin Hilman <khilman@deeprootsystems.com>
|
||||
Date: Tue, 16 Nov 2010 11:48:41 -0800
|
||||
Subject: [PATCH 5/8] cpufreq: fixup after new OPP layer merged
|
||||
|
||||
---
|
||||
arch/arm/plat-omap/cpu-omap.c | 3 ++-
|
||||
1 files changed, 2 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
index c3ac065..9cd2709 100644
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ b/arch/arm/plat-omap/cpu-omap.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/err.h>
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
+#include <linux/opp.h>
|
||||
|
||||
#include <mach/hardware.h>
|
||||
#include <plat/clock.h>
|
||||
@@ -32,7 +33,7 @@
|
||||
|
||||
#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
#include <plat/omap-pm.h>
|
||||
-#include <plat/opp.h>
|
||||
+#include <plat/common.h>
|
||||
#endif
|
||||
|
||||
#define VERY_HI_RATE 900000000
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-669
@@ -1,669 +0,0 @@
|
||||
From e16548716c5cbc3c9885d05f1654d83d5411a3a7 Mon Sep 17 00:00:00 2001
|
||||
From: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Date: Mon, 14 Mar 2011 17:08:48 +0530
|
||||
Subject: [PATCH 6/8] OMAP: cpufreq: Split OMAP1 and OMAP2PLUS CPUfreq drivers.
|
||||
|
||||
This patch is an attempt to cleanup the #ifdeferry in the
|
||||
omap CPUfreq drivers.
|
||||
|
||||
The split betwenn OMAP1 and OMAP2PLUS is logical because
|
||||
- OMAP1 doesn't support opp layer.
|
||||
- OMAP1 build is seperate from omap2plus.
|
||||
|
||||
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Cc: Kevin Hilman <khilman@ti.com>
|
||||
Cc: Vishwanath BS <vishwanath.bs@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap1/Makefile | 3 +
|
||||
arch/arm/mach-omap1/omap1-cpufreq.c | 176 ++++++++++++++++++++++++++
|
||||
arch/arm/mach-omap2/Makefile | 3 +
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 201 ++++++++++++++++++++++++++++++
|
||||
arch/arm/plat-omap/Makefile | 1 -
|
||||
arch/arm/plat-omap/cpu-omap.c | 204 -------------------------------
|
||||
6 files changed, 383 insertions(+), 205 deletions(-)
|
||||
create mode 100644 arch/arm/mach-omap1/omap1-cpufreq.c
|
||||
create mode 100644 arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
delete mode 100644 arch/arm/plat-omap/cpu-omap.c
|
||||
|
||||
diff --git a/arch/arm/mach-omap1/Makefile b/arch/arm/mach-omap1/Makefile
|
||||
index af98117..e5082b0 100644
|
||||
--- a/arch/arm/mach-omap1/Makefile
|
||||
+++ b/arch/arm/mach-omap1/Makefile
|
||||
@@ -10,6 +10,9 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
|
||||
|
||||
obj-$(CONFIG_OMAP_32K_TIMER) += timer32k.o
|
||||
|
||||
+# CPUFREQ driver
|
||||
+obj-$(CONFIG_CPU_FREQ) += omap1-cpufreq.o
|
||||
+
|
||||
# Power Management
|
||||
obj-$(CONFIG_PM) += pm.o sleep.o pm_bus.o
|
||||
|
||||
diff --git a/arch/arm/mach-omap1/omap1-cpufreq.c b/arch/arm/mach-omap1/omap1-cpufreq.c
|
||||
new file mode 100644
|
||||
index 0000000..682cdc8
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-omap1/omap1-cpufreq.c
|
||||
@@ -0,0 +1,176 @@
|
||||
+/*
|
||||
+ * OMAP1 cpufreq driver
|
||||
+ *
|
||||
+ * CPU frequency scaling for OMAP
|
||||
+ *
|
||||
+ * Copyright (C) 2005 Nokia Corporation
|
||||
+ * Written by Tony Lindgren <tony@atomide.com>
|
||||
+ *
|
||||
+ * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
|
||||
+ *
|
||||
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
|
||||
+ * Updated to support OMAP3
|
||||
+ * Rajendra Nayak <rnayak@ti.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.
|
||||
+ */
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/sched.h>
|
||||
+#include <linux/cpufreq.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/opp.h>
|
||||
+
|
||||
+#include <asm/system.h>
|
||||
+
|
||||
+#include <plat/clock.h>
|
||||
+#include <plat/omap-pm.h>
|
||||
+
|
||||
+#include <mach/hardware.h>
|
||||
+
|
||||
+#define VERY_HI_RATE 900000000
|
||||
+
|
||||
+static struct cpufreq_frequency_table *freq_table;
|
||||
+static struct clk *mpu_clk;
|
||||
+
|
||||
+static int omap_verify_speed(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ if (freq_table)
|
||||
+ return cpufreq_frequency_table_verify(policy, freq_table);
|
||||
+
|
||||
+ if (policy->cpu)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
+ policy->cpuinfo.max_freq);
|
||||
+
|
||||
+ policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000;
|
||||
+ policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
|
||||
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
+ policy->cpuinfo.max_freq);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static unsigned int omap_getspeed(unsigned int cpu)
|
||||
+{
|
||||
+ unsigned long rate;
|
||||
+
|
||||
+ if (cpu)
|
||||
+ return 0;
|
||||
+
|
||||
+ rate = clk_get_rate(mpu_clk) / 1000;
|
||||
+ return rate;
|
||||
+}
|
||||
+
|
||||
+static int omap_target(struct cpufreq_policy *policy,
|
||||
+ unsigned int target_freq,
|
||||
+ unsigned int relation)
|
||||
+{
|
||||
+ struct cpufreq_freqs freqs;
|
||||
+ int ret = 0;
|
||||
+
|
||||
+ /* Ensure desired rate is within allowed range. Some govenors
|
||||
+ * (ondemand) will just pass target_freq=0 to get the minimum. */
|
||||
+ if (target_freq < policy->min)
|
||||
+ target_freq = policy->min;
|
||||
+ if (target_freq > policy->max)
|
||||
+ target_freq = policy->max;
|
||||
+
|
||||
+ freqs.old = omap_getspeed(0);
|
||||
+ freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
+ freqs.cpu = 0;
|
||||
+
|
||||
+ if (freqs.old == freqs.new)
|
||||
+ return ret;
|
||||
+
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
+
|
||||
+#ifdef CONFIG_CPU_FREQ_DEBUG
|
||||
+ pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
|
||||
+#endif
|
||||
+ ret = clk_set_rate(mpu_clk, freqs.new * 1000);
|
||||
+
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int __init omap_cpu_init(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ int result = 0;
|
||||
+
|
||||
+ mpu_clk = clk_get(NULL, "mpu");
|
||||
+ if (IS_ERR(mpu_clk))
|
||||
+ return PTR_ERR(mpu_clk);
|
||||
+
|
||||
+ if (policy->cpu != 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ policy->cur = policy->min = policy->max = omap_getspeed(0);
|
||||
+
|
||||
+ clk_init_cpufreq_table(&freq_table);
|
||||
+
|
||||
+ if (freq_table) {
|
||||
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
+ if (!result)
|
||||
+ cpufreq_frequency_table_get_attr(freq_table,
|
||||
+ policy->cpu);
|
||||
+ } else {
|
||||
+ policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
|
||||
+ policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
|
||||
+ VERY_HI_RATE) / 1000;
|
||||
+ }
|
||||
+
|
||||
+ policy->min = policy->cpuinfo.min_freq;
|
||||
+ policy->max = policy->cpuinfo.max_freq;
|
||||
+ policy->cur = omap_getspeed(0);
|
||||
+
|
||||
+ /* FIXME: what's the actual transition time? */
|
||||
+ policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ clk_exit_cpufreq_table(&freq_table);
|
||||
+ clk_put(mpu_clk);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct freq_attr *omap_cpufreq_attr[] = {
|
||||
+ &cpufreq_freq_attr_scaling_available_freqs,
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static struct cpufreq_driver omap_driver = {
|
||||
+ .flags = CPUFREQ_STICKY,
|
||||
+ .verify = omap_verify_speed,
|
||||
+ .target = omap_target,
|
||||
+ .get = omap_getspeed,
|
||||
+ .init = omap_cpu_init,
|
||||
+ .exit = omap_cpu_exit,
|
||||
+ .name = "omap1",
|
||||
+ .attr = omap_cpufreq_attr,
|
||||
+};
|
||||
+
|
||||
+static int __init omap_cpufreq_init(void)
|
||||
+{
|
||||
+ return cpufreq_register_driver(&omap_driver);
|
||||
+}
|
||||
+
|
||||
+static void __exit omap_cpufreq_exit(void)
|
||||
+{
|
||||
+ cpufreq_unregister_driver(&omap_driver);
|
||||
+}
|
||||
+
|
||||
+MODULE_DESCRIPTION("cpufreq driver for OMAP1 SOCs");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+module_init(omap_cpufreq_init);
|
||||
+module_exit(omap_cpufreq_exit);
|
||||
diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile
|
||||
index 05cd983..e9c2445 100644
|
||||
--- a/arch/arm/mach-omap2/Makefile
|
||||
+++ b/arch/arm/mach-omap2/Makefile
|
||||
@@ -56,6 +56,9 @@ obj-$(CONFIG_ARCH_OMAP3) += opp3xxx_data.o
|
||||
obj-$(CONFIG_ARCH_OMAP4) += opp4xxx_data.o
|
||||
endif
|
||||
|
||||
+# CPUFREQ driver
|
||||
+obj-$(CONFIG_CPU_FREQ) += omap2plus-cpufreq.o
|
||||
+
|
||||
# Power Management
|
||||
ifeq ($(CONFIG_PM),y)
|
||||
obj-$(CONFIG_ARCH_OMAP2) += pm24xx.o
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
new file mode 100644
|
||||
index 0000000..14f84cc
|
||||
--- /dev/null
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -0,0 +1,201 @@
|
||||
+/*
|
||||
+ * OMAP2PLUS cpufreq driver
|
||||
+ *
|
||||
+ * CPU frequency scaling for OMAP
|
||||
+ *
|
||||
+ * Copyright (C) 2005 Nokia Corporation
|
||||
+ * Written by Tony Lindgren <tony@atomide.com>
|
||||
+ *
|
||||
+ * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
|
||||
+ *
|
||||
+ * Copyright (C) 2007-2008 Texas Instruments, Inc.
|
||||
+ * Updated to support OMAP3
|
||||
+ * Rajendra Nayak <rnayak@ti.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.
|
||||
+ */
|
||||
+#include <linux/types.h>
|
||||
+#include <linux/kernel.h>
|
||||
+#include <linux/sched.h>
|
||||
+#include <linux/cpufreq.h>
|
||||
+#include <linux/delay.h>
|
||||
+#include <linux/init.h>
|
||||
+#include <linux/err.h>
|
||||
+#include <linux/clk.h>
|
||||
+#include <linux/io.h>
|
||||
+#include <linux/opp.h>
|
||||
+
|
||||
+#include <asm/system.h>
|
||||
+#include <asm/smp_plat.h>
|
||||
+
|
||||
+#include <plat/clock.h>
|
||||
+#include <plat/omap-pm.h>
|
||||
+#include <plat/common.h>
|
||||
+
|
||||
+#include <mach/hardware.h>
|
||||
+
|
||||
+#define VERY_HI_RATE 900000000
|
||||
+
|
||||
+static struct cpufreq_frequency_table *freq_table;
|
||||
+static struct clk *mpu_clk;
|
||||
+
|
||||
+static int omap_verify_speed(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ if (freq_table)
|
||||
+ return cpufreq_frequency_table_verify(policy, freq_table);
|
||||
+
|
||||
+ if (policy->cpu)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
+ policy->cpuinfo.max_freq);
|
||||
+
|
||||
+ policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000;
|
||||
+ policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
|
||||
+ cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
+ policy->cpuinfo.max_freq);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static unsigned int omap_getspeed(unsigned int cpu)
|
||||
+{
|
||||
+ unsigned long rate;
|
||||
+
|
||||
+ if (cpu)
|
||||
+ return 0;
|
||||
+
|
||||
+ rate = clk_get_rate(mpu_clk) / 1000;
|
||||
+ return rate;
|
||||
+}
|
||||
+
|
||||
+static int omap_target(struct cpufreq_policy *policy,
|
||||
+ unsigned int target_freq,
|
||||
+ unsigned int relation)
|
||||
+{
|
||||
+ int ret = 0;
|
||||
+ struct cpufreq_freqs freqs;
|
||||
+
|
||||
+ /* Ensure desired rate is within allowed range. Some govenors
|
||||
+ * (ondemand) will just pass target_freq=0 to get the minimum. */
|
||||
+ if (target_freq < policy->min)
|
||||
+ target_freq = policy->min;
|
||||
+ if (target_freq > policy->max)
|
||||
+ target_freq = policy->max;
|
||||
+
|
||||
+ freqs.old = omap_getspeed(0);
|
||||
+ freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
+ freqs.cpu = 0;
|
||||
+
|
||||
+ if (freqs.old == freqs.new)
|
||||
+ return ret;
|
||||
+
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
+
|
||||
+#ifdef CONFIG_CPU_FREQ_DEBUG
|
||||
+ pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
|
||||
+#endif
|
||||
+
|
||||
+ ret = clk_set_rate(mpu_clk, freqs.new * 1000);
|
||||
+
|
||||
+ /*
|
||||
+ * Generic CPUFREQ driver jiffy update is under !SMP. So jiffies
|
||||
+ * won't get updated when UP machine cpufreq build with
|
||||
+ * CONFIG_SMP enabled. Below code is added only to manage that
|
||||
+ * scenario
|
||||
+ */
|
||||
+ if (!is_smp())
|
||||
+ loops_per_jiffy =
|
||||
+ cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new);
|
||||
+
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+
|
||||
+ return ret;
|
||||
+}
|
||||
+
|
||||
+static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ int result = 0;
|
||||
+ struct device *mpu_dev;
|
||||
+
|
||||
+ if (cpu_is_omap24xx())
|
||||
+ mpu_clk = clk_get(NULL, "virt_prcm_set");
|
||||
+ else if (cpu_is_omap34xx())
|
||||
+ mpu_clk = clk_get(NULL, "dpll1_ck");
|
||||
+ else if (cpu_is_omap34xx())
|
||||
+ mpu_clk = clk_get(NULL, "dpll_mpu_ck");
|
||||
+
|
||||
+ if (IS_ERR(mpu_clk))
|
||||
+ return PTR_ERR(mpu_clk);
|
||||
+
|
||||
+ if (policy->cpu != 0)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ policy->cur = policy->min = policy->max = omap_getspeed(0);
|
||||
+
|
||||
+ mpu_dev = omap2_get_mpuss_device();
|
||||
+ if (!mpu_dev) {
|
||||
+ pr_warning("%s: unable to get the mpu device\n", __func__);
|
||||
+ return -EINVAL;
|
||||
+ }
|
||||
+ opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
+
|
||||
+ if (freq_table) {
|
||||
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
+ if (!result)
|
||||
+ cpufreq_frequency_table_get_attr(freq_table,
|
||||
+ policy->cpu);
|
||||
+ } else {
|
||||
+ policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
|
||||
+ policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
|
||||
+ VERY_HI_RATE) / 1000;
|
||||
+ }
|
||||
+
|
||||
+ policy->min = policy->cpuinfo.min_freq;
|
||||
+ policy->max = policy->cpuinfo.max_freq;
|
||||
+ policy->cur = omap_getspeed(0);
|
||||
+
|
||||
+ /* FIXME: what's the actual transition time? */
|
||||
+ policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
+
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
+{
|
||||
+ clk_exit_cpufreq_table(&freq_table);
|
||||
+ clk_put(mpu_clk);
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+static struct freq_attr *omap_cpufreq_attr[] = {
|
||||
+ &cpufreq_freq_attr_scaling_available_freqs,
|
||||
+ NULL,
|
||||
+};
|
||||
+
|
||||
+static struct cpufreq_driver omap_driver = {
|
||||
+ .flags = CPUFREQ_STICKY,
|
||||
+ .verify = omap_verify_speed,
|
||||
+ .target = omap_target,
|
||||
+ .get = omap_getspeed,
|
||||
+ .init = omap_cpu_init,
|
||||
+ .exit = omap_cpu_exit,
|
||||
+ .name = "omap2plus",
|
||||
+ .attr = omap_cpufreq_attr,
|
||||
+};
|
||||
+
|
||||
+static int __init omap_cpufreq_init(void)
|
||||
+{
|
||||
+ return cpufreq_register_driver(&omap_driver);
|
||||
+}
|
||||
+
|
||||
+static void __exit omap_cpufreq_exit(void)
|
||||
+{
|
||||
+ cpufreq_unregister_driver(&omap_driver);
|
||||
+}
|
||||
+
|
||||
+MODULE_DESCRIPTION("cpufreq driver for OMAP2PLUS SOCs");
|
||||
+MODULE_LICENSE("GPL");
|
||||
+module_init(omap_cpufreq_init);
|
||||
+module_exit(omap_cpufreq_exit);
|
||||
diff --git a/arch/arm/plat-omap/Makefile b/arch/arm/plat-omap/Makefile
|
||||
index a4a1285..ec7862e 100644
|
||||
--- a/arch/arm/plat-omap/Makefile
|
||||
+++ b/arch/arm/plat-omap/Makefile
|
||||
@@ -21,7 +21,6 @@ obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
|
||||
obj-$(CONFIG_OMAP_IOMMU) += iommu.o iovmm.o
|
||||
obj-$(CONFIG_OMAP_IOMMU_DEBUG) += iommu-debug.o
|
||||
|
||||
-obj-$(CONFIG_CPU_FREQ) += cpu-omap.o
|
||||
obj-$(CONFIG_OMAP_DM_TIMER) += dmtimer.o
|
||||
obj-$(CONFIG_OMAP_DEBUG_DEVICES) += debug-devices.o
|
||||
obj-$(CONFIG_OMAP_DEBUG_LEDS) += debug-leds.o
|
||||
diff --git a/arch/arm/plat-omap/cpu-omap.c b/arch/arm/plat-omap/cpu-omap.c
|
||||
deleted file mode 100644
|
||||
index 9cd2709..0000000
|
||||
--- a/arch/arm/plat-omap/cpu-omap.c
|
||||
+++ /dev/null
|
||||
@@ -1,204 +0,0 @@
|
||||
-/*
|
||||
- * linux/arch/arm/plat-omap/cpu-omap.c
|
||||
- *
|
||||
- * CPU frequency scaling for OMAP
|
||||
- *
|
||||
- * Copyright (C) 2005 Nokia Corporation
|
||||
- * Written by Tony Lindgren <tony@atomide.com>
|
||||
- *
|
||||
- * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
|
||||
- *
|
||||
- * Copyright (C) 2007-2008 Texas Instruments, Inc.
|
||||
- * Updated to support OMAP3
|
||||
- * Rajendra Nayak <rnayak@ti.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.
|
||||
- */
|
||||
-#include <linux/types.h>
|
||||
-#include <linux/kernel.h>
|
||||
-#include <linux/sched.h>
|
||||
-#include <linux/cpufreq.h>
|
||||
-#include <linux/delay.h>
|
||||
-#include <linux/init.h>
|
||||
-#include <linux/err.h>
|
||||
-#include <linux/clk.h>
|
||||
-#include <linux/io.h>
|
||||
-#include <linux/opp.h>
|
||||
-
|
||||
-#include <mach/hardware.h>
|
||||
-#include <plat/clock.h>
|
||||
-#include <asm/system.h>
|
||||
-
|
||||
-#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
-#include <plat/omap-pm.h>
|
||||
-#include <plat/common.h>
|
||||
-#endif
|
||||
-
|
||||
-#define VERY_HI_RATE 900000000
|
||||
-
|
||||
-static struct cpufreq_frequency_table *freq_table;
|
||||
-
|
||||
-#ifdef CONFIG_ARCH_OMAP1
|
||||
-#define MPU_CLK "mpu"
|
||||
-#elif defined(CONFIG_ARCH_OMAP3)
|
||||
-#define MPU_CLK "arm_fck"
|
||||
-#else
|
||||
-#define MPU_CLK "virt_prcm_set"
|
||||
-#endif
|
||||
-
|
||||
-static struct clk *mpu_clk;
|
||||
-
|
||||
-/* TODO: Add support for SDRAM timing changes */
|
||||
-
|
||||
-static int omap_verify_speed(struct cpufreq_policy *policy)
|
||||
-{
|
||||
- if (freq_table)
|
||||
- return cpufreq_frequency_table_verify(policy, freq_table);
|
||||
-
|
||||
- if (policy->cpu)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
- policy->cpuinfo.max_freq);
|
||||
-
|
||||
- policy->min = clk_round_rate(mpu_clk, policy->min * 1000) / 1000;
|
||||
- policy->max = clk_round_rate(mpu_clk, policy->max * 1000) / 1000;
|
||||
- cpufreq_verify_within_limits(policy, policy->cpuinfo.min_freq,
|
||||
- policy->cpuinfo.max_freq);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static unsigned int omap_getspeed(unsigned int cpu)
|
||||
-{
|
||||
- unsigned long rate;
|
||||
-
|
||||
- if (cpu)
|
||||
- return 0;
|
||||
-
|
||||
- rate = clk_get_rate(mpu_clk) / 1000;
|
||||
- return rate;
|
||||
-}
|
||||
-
|
||||
-static int omap_target(struct cpufreq_policy *policy,
|
||||
- unsigned int target_freq,
|
||||
- unsigned int relation)
|
||||
-{
|
||||
-#ifdef CONFIG_ARCH_OMAP1
|
||||
- struct cpufreq_freqs freqs;
|
||||
-#endif
|
||||
-#if defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
- unsigned long freq;
|
||||
- struct device *mpu_dev = omap2_get_mpuss_device();
|
||||
-#endif
|
||||
- int ret = 0;
|
||||
-
|
||||
- /* Ensure desired rate is within allowed range. Some govenors
|
||||
- * (ondemand) will just pass target_freq=0 to get the minimum. */
|
||||
- if (target_freq < policy->min)
|
||||
- target_freq = policy->min;
|
||||
- if (target_freq > policy->max)
|
||||
- target_freq = policy->max;
|
||||
-
|
||||
-#ifdef CONFIG_ARCH_OMAP1
|
||||
- freqs.old = omap_getspeed(0);
|
||||
- freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
- freqs.cpu = 0;
|
||||
-
|
||||
- if (freqs.old == freqs.new)
|
||||
- return ret;
|
||||
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
-#ifdef CONFIG_CPU_FREQ_DEBUG
|
||||
- printk(KERN_DEBUG "cpufreq-omap: transition: %u --> %u\n",
|
||||
- freqs.old, freqs.new);
|
||||
-#endif
|
||||
- ret = clk_set_rate(mpu_clk, freqs.new * 1000);
|
||||
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
-#elif defined(CONFIG_ARCH_OMAP3) && !defined(CONFIG_OMAP_PM_NONE)
|
||||
- freq = target_freq * 1000;
|
||||
- if (opp_find_freq_ceil(mpu_dev, &freq))
|
||||
- omap_pm_cpu_set_freq(freq);
|
||||
-#endif
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
-{
|
||||
- int result = 0;
|
||||
-
|
||||
- mpu_clk = clk_get(NULL, MPU_CLK);
|
||||
- if (IS_ERR(mpu_clk))
|
||||
- return PTR_ERR(mpu_clk);
|
||||
-
|
||||
- if (policy->cpu != 0)
|
||||
- return -EINVAL;
|
||||
-
|
||||
- policy->cur = policy->min = policy->max = omap_getspeed(0);
|
||||
-
|
||||
- if (!cpu_is_omap34xx()) {
|
||||
- clk_init_cpufreq_table(&freq_table);
|
||||
- } else {
|
||||
- struct device *mpu_dev = omap2_get_mpuss_device();
|
||||
-
|
||||
- opp_init_cpufreq_table(mpu_dev, &freq_table);
|
||||
- }
|
||||
-
|
||||
- if (freq_table) {
|
||||
- result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
|
||||
- if (!result)
|
||||
- cpufreq_frequency_table_get_attr(freq_table,
|
||||
- policy->cpu);
|
||||
- } else {
|
||||
- policy->cpuinfo.min_freq = clk_round_rate(mpu_clk, 0) / 1000;
|
||||
- policy->cpuinfo.max_freq = clk_round_rate(mpu_clk,
|
||||
- VERY_HI_RATE) / 1000;
|
||||
- }
|
||||
-
|
||||
- policy->min = policy->cpuinfo.min_freq;
|
||||
- policy->max = policy->cpuinfo.max_freq;
|
||||
- policy->cur = omap_getspeed(0);
|
||||
-
|
||||
- /* FIXME: what's the actual transition time? */
|
||||
- policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
-
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static int omap_cpu_exit(struct cpufreq_policy *policy)
|
||||
-{
|
||||
- clk_exit_cpufreq_table(&freq_table);
|
||||
- clk_put(mpu_clk);
|
||||
- return 0;
|
||||
-}
|
||||
-
|
||||
-static struct freq_attr *omap_cpufreq_attr[] = {
|
||||
- &cpufreq_freq_attr_scaling_available_freqs,
|
||||
- NULL,
|
||||
-};
|
||||
-
|
||||
-static struct cpufreq_driver omap_driver = {
|
||||
- .flags = CPUFREQ_STICKY,
|
||||
- .verify = omap_verify_speed,
|
||||
- .target = omap_target,
|
||||
- .get = omap_getspeed,
|
||||
- .init = omap_cpu_init,
|
||||
- .exit = omap_cpu_exit,
|
||||
- .name = "omap",
|
||||
- .attr = omap_cpufreq_attr,
|
||||
-};
|
||||
-
|
||||
-static int __init omap_cpufreq_init(void)
|
||||
-{
|
||||
- return cpufreq_register_driver(&omap_driver);
|
||||
-}
|
||||
-
|
||||
-late_initcall(omap_cpufreq_init);
|
||||
-
|
||||
-/*
|
||||
- * if ever we want to remove this, upon cleanup call:
|
||||
- *
|
||||
- * cpufreq_unregister_driver()
|
||||
- * cpufreq_frequency_table_put_attr()
|
||||
- */
|
||||
-
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-170
@@ -1,170 +0,0 @@
|
||||
From f375d3c39d2835929d34c2a046b8c43cea6d1467 Mon Sep 17 00:00:00 2001
|
||||
From: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Date: Mon, 14 Mar 2011 17:08:49 +0530
|
||||
Subject: [PATCH 7/8] OMAP2PLUS: cpufreq: Add SMP support to cater OMAP4430
|
||||
|
||||
On OMAP SMP configuartion, both processors share the voltage
|
||||
and clock. So both CPUs needs to be scaled together and hence
|
||||
needs software co-ordination.
|
||||
|
||||
Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
|
||||
Cc: Kevin Hilman <khilman@ti.com>
|
||||
cc: Vishwanath BS <vishwanath.bs@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 73 ++++++++++++++++++++++++++-----
|
||||
1 files changed, 62 insertions(+), 11 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index 14f84cc..8d472f6 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -26,9 +26,11 @@
|
||||
#include <linux/clk.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/opp.h>
|
||||
+#include <linux/cpu.h>
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <asm/smp_plat.h>
|
||||
+#include <asm/cpu.h>
|
||||
|
||||
#include <plat/clock.h>
|
||||
#include <plat/omap-pm.h>
|
||||
@@ -63,7 +65,7 @@ static unsigned int omap_getspeed(unsigned int cpu)
|
||||
{
|
||||
unsigned long rate;
|
||||
|
||||
- if (cpu)
|
||||
+ if (cpu >= NR_CPUS)
|
||||
return 0;
|
||||
|
||||
rate = clk_get_rate(mpu_clk) / 1000;
|
||||
@@ -74,9 +76,13 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
unsigned int target_freq,
|
||||
unsigned int relation)
|
||||
{
|
||||
- int ret = 0;
|
||||
+ int i, ret = 0;
|
||||
struct cpufreq_freqs freqs;
|
||||
|
||||
+ /* Changes not allowed until all CPUs are online */
|
||||
+ if (is_smp() && (num_online_cpus() < NR_CPUS))
|
||||
+ return ret;
|
||||
+
|
||||
/* Ensure desired rate is within allowed range. Some govenors
|
||||
* (ondemand) will just pass target_freq=0 to get the minimum. */
|
||||
if (target_freq < policy->min)
|
||||
@@ -84,15 +90,25 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
if (target_freq > policy->max)
|
||||
target_freq = policy->max;
|
||||
|
||||
- freqs.old = omap_getspeed(0);
|
||||
+ freqs.old = omap_getspeed(policy->cpu);
|
||||
freqs.new = clk_round_rate(mpu_clk, target_freq * 1000) / 1000;
|
||||
- freqs.cpu = 0;
|
||||
+ freqs.cpu = policy->cpu;
|
||||
|
||||
if (freqs.old == freqs.new)
|
||||
return ret;
|
||||
|
||||
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
+ if (!is_smp()) {
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
+ goto set_freq;
|
||||
+ }
|
||||
+
|
||||
+ /* notifiers */
|
||||
+ for_each_cpu(i, policy->cpus) {
|
||||
+ freqs.cpu = i;
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
|
||||
+ }
|
||||
|
||||
+set_freq:
|
||||
#ifdef CONFIG_CPU_FREQ_DEBUG
|
||||
pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
|
||||
#endif
|
||||
@@ -105,12 +121,33 @@ static int omap_target(struct cpufreq_policy *policy,
|
||||
* CONFIG_SMP enabled. Below code is added only to manage that
|
||||
* scenario
|
||||
*/
|
||||
- if (!is_smp())
|
||||
+ freqs.new = omap_getspeed(policy->cpu);
|
||||
+ if (!is_smp()) {
|
||||
loops_per_jiffy =
|
||||
cpufreq_scale(loops_per_jiffy, freqs.old, freqs.new);
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+ goto skip_lpj;
|
||||
+ }
|
||||
|
||||
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+#ifdef CONFIG_SMP
|
||||
+ /*
|
||||
+ * Note that loops_per_jiffy is not updated on SMP systems in
|
||||
+ * cpufreq driver. So, update the per-CPU loops_per_jiffy value
|
||||
+ * on frequency transition. We need to update all dependent CPUs.
|
||||
+ */
|
||||
+ for_each_cpu(i, policy->cpus)
|
||||
+ per_cpu(cpu_data, i).loops_per_jiffy =
|
||||
+ cpufreq_scale(per_cpu(cpu_data, i).loops_per_jiffy,
|
||||
+ freqs.old, freqs.new);
|
||||
+#endif
|
||||
|
||||
+ /* notifiers */
|
||||
+ for_each_cpu(i, policy->cpus) {
|
||||
+ freqs.cpu = i;
|
||||
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
|
||||
+ }
|
||||
+
|
||||
+skip_lpj:
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -118,6 +155,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
{
|
||||
int result = 0;
|
||||
struct device *mpu_dev;
|
||||
+ static cpumask_var_t cpumask;
|
||||
|
||||
if (cpu_is_omap24xx())
|
||||
mpu_clk = clk_get(NULL, "virt_prcm_set");
|
||||
@@ -129,12 +167,12 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
if (IS_ERR(mpu_clk))
|
||||
return PTR_ERR(mpu_clk);
|
||||
|
||||
- if (policy->cpu != 0)
|
||||
+ if (policy->cpu >= NR_CPUS)
|
||||
return -EINVAL;
|
||||
|
||||
- policy->cur = policy->min = policy->max = omap_getspeed(0);
|
||||
-
|
||||
+ policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
|
||||
mpu_dev = omap2_get_mpuss_device();
|
||||
+
|
||||
if (!mpu_dev) {
|
||||
pr_warning("%s: unable to get the mpu device\n", __func__);
|
||||
return -EINVAL;
|
||||
@@ -154,7 +192,20 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
|
||||
policy->min = policy->cpuinfo.min_freq;
|
||||
policy->max = policy->cpuinfo.max_freq;
|
||||
- policy->cur = omap_getspeed(0);
|
||||
+ policy->cur = omap_getspeed(policy->cpu);
|
||||
+
|
||||
+ /*
|
||||
+ * On OMAP SMP configuartion, both processors share the voltage
|
||||
+ * and clock. So both CPUs needs to be scaled together and hence
|
||||
+ * needs software co-ordination. Use cpufreq affected_cpus
|
||||
+ * interface to handle this scenario. Additional is_smp() check
|
||||
+ * is to keep SMP_ON_UP build working.
|
||||
+ */
|
||||
+ if (is_smp()) {
|
||||
+ policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
|
||||
+ cpumask_or(cpumask, cpumask_of(policy->cpu), cpumask);
|
||||
+ cpumask_copy(policy->cpus, cpumask);
|
||||
+ }
|
||||
|
||||
/* FIXME: what's the actual transition time? */
|
||||
policy->cpuinfo.transition_latency = 300 * 1000;
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
From 6e101764a47cb6975a555e2237843ad391a542a4 Mon Sep 17 00:00:00 2001
|
||||
From: Jarkko Nikula <jhnikula@gmail.com>
|
||||
Date: Thu, 14 Apr 2011 16:21:58 +0300
|
||||
Subject: [PATCH 8/8] OMAP2PLUS: cpufreq: Fix typo when attempting to set mpu_clk for OMAP4
|
||||
|
||||
Fix this typo as there is no dpll_mpu_ck for OMAP3 and code flow is clearly
|
||||
trying to set mpu_clk for OMAP4 for which this dpll_mpu_ck is available.
|
||||
|
||||
Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>
|
||||
---
|
||||
arch/arm/mach-omap2/omap2plus-cpufreq.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap2plus-cpufreq.c b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
index 8d472f6..d53ce23 100644
|
||||
--- a/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
+++ b/arch/arm/mach-omap2/omap2plus-cpufreq.c
|
||||
@@ -161,7 +161,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
|
||||
mpu_clk = clk_get(NULL, "virt_prcm_set");
|
||||
else if (cpu_is_omap34xx())
|
||||
mpu_clk = clk_get(NULL, "dpll1_ck");
|
||||
- else if (cpu_is_omap34xx())
|
||||
+ else if (cpu_is_omap44xx())
|
||||
mpu_clk = clk_get(NULL, "dpll_mpu_ck");
|
||||
|
||||
if (IS_ERR(mpu_clk))
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-77
@@ -1,77 +0,0 @@
|
||||
From 988f50cb51d18e81ed2f7673a09694d28c9d086a Mon Sep 17 00:00:00 2001
|
||||
From: Rajendra Nayak <rnayak@ti.com>
|
||||
Date: Tue, 5 Apr 2011 15:22:31 +0530
|
||||
Subject: [PATCH 1/6] OMAP2+: clockdomain: Add an api to read idle mode
|
||||
|
||||
Add a clockdomain api to check if hardware supervised
|
||||
idle transitions are enabled on a clockdomain.
|
||||
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/clockdomain.c | 21 +++++++++++++++++++++
|
||||
arch/arm/mach-omap2/clockdomain.h | 3 +++
|
||||
2 files changed, 24 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
|
||||
index 6cb6c03..2ab3686 100644
|
||||
--- a/arch/arm/mach-omap2/clockdomain.c
|
||||
+++ b/arch/arm/mach-omap2/clockdomain.c
|
||||
@@ -795,6 +795,27 @@ void clkdm_deny_idle(struct clockdomain *clkdm)
|
||||
arch_clkdm->clkdm_deny_idle(clkdm);
|
||||
}
|
||||
|
||||
+/**
|
||||
+ * clkdm_is_idle - Check if the clkdm hwsup/autoidle is enabled
|
||||
+ * @clkdm: struct clockdomain *
|
||||
+ *
|
||||
+ * Returns true if the clockdomain is in hardware-supervised
|
||||
+ * idle mode, or 0 otherwise.
|
||||
+ *
|
||||
+ */
|
||||
+int clkdm_is_idle(struct clockdomain *clkdm)
|
||||
+{
|
||||
+ if (!clkdm)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ if (!arch_clkdm || !arch_clkdm->clkdm_is_idle)
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ pr_debug("clockdomain: reading idle state for %s\n", clkdm->name);
|
||||
+
|
||||
+ return arch_clkdm->clkdm_is_idle(clkdm);
|
||||
+}
|
||||
+
|
||||
|
||||
/* Clockdomain-to-clock framework interface code */
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
|
||||
index 5823584..085ed82 100644
|
||||
--- a/arch/arm/mach-omap2/clockdomain.h
|
||||
+++ b/arch/arm/mach-omap2/clockdomain.h
|
||||
@@ -138,6 +138,7 @@ struct clockdomain {
|
||||
* @clkdm_wakeup: Force a clockdomain to wakeup
|
||||
* @clkdm_allow_idle: Enable hw supervised idle transitions for clock domain
|
||||
* @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain
|
||||
+ * @clkdm_is_idle: Check if hw supervised idle transitions are enabled
|
||||
* @clkdm_clk_enable: Put the clkdm in right state for a clock enable
|
||||
* @clkdm_clk_disable: Put the clkdm in right state for a clock disable
|
||||
*/
|
||||
@@ -154,6 +155,7 @@ struct clkdm_ops {
|
||||
int (*clkdm_wakeup)(struct clockdomain *clkdm);
|
||||
void (*clkdm_allow_idle)(struct clockdomain *clkdm);
|
||||
void (*clkdm_deny_idle)(struct clockdomain *clkdm);
|
||||
+ int (*clkdm_is_idle)(struct clockdomain *clkdm);
|
||||
int (*clkdm_clk_enable)(struct clockdomain *clkdm);
|
||||
int (*clkdm_clk_disable)(struct clockdomain *clkdm);
|
||||
};
|
||||
@@ -177,6 +179,7 @@ int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
|
||||
|
||||
void clkdm_allow_idle(struct clockdomain *clkdm);
|
||||
void clkdm_deny_idle(struct clockdomain *clkdm);
|
||||
+int clkdm_is_idle(struct clockdomain *clkdm);
|
||||
|
||||
int clkdm_wakeup(struct clockdomain *clkdm);
|
||||
int clkdm_sleep(struct clockdomain *clkdm);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-86
@@ -1,86 +0,0 @@
|
||||
From e3ba8d41bfafd782f3ee7f8930d9bf393986c662 Mon Sep 17 00:00:00 2001
|
||||
From: Rajendra Nayak <rnayak@ti.com>
|
||||
Date: Tue, 5 Apr 2011 15:22:36 +0530
|
||||
Subject: [PATCH 2/6] OMAP2+: clockdomain: Add SoC support for clkdm_is_idle
|
||||
|
||||
Add the SoC specific implemenation for clkdm_is_idle
|
||||
for OMAP2/3 and OMAP4.
|
||||
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/clockdomain2xxx_3xxx.c | 12 ++++++++++++
|
||||
arch/arm/mach-omap2/clockdomain44xx.c | 7 +++++++
|
||||
2 files changed, 19 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
|
||||
index 48d0db7..db49baa 100644
|
||||
--- a/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
|
||||
+++ b/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
|
||||
@@ -13,6 +13,7 @@
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
+#include <linux/errno.h>
|
||||
#include <plat/prcm.h>
|
||||
#include "prm.h"
|
||||
#include "prm2xxx_3xxx.h"
|
||||
@@ -146,6 +147,15 @@ static void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
|
||||
_clkdm_del_autodeps(clkdm);
|
||||
}
|
||||
|
||||
+static int omap2_clkdm_is_idle(struct clockdomain *clkdm)
|
||||
+{
|
||||
+ if (!clkdm->clktrctrl_mask)
|
||||
+ return -1;
|
||||
+
|
||||
+ return omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
|
||||
+ clkdm->clktrctrl_mask);
|
||||
+}
|
||||
+
|
||||
static void _enable_hwsup(struct clockdomain *clkdm)
|
||||
{
|
||||
if (cpu_is_omap24xx())
|
||||
@@ -252,6 +262,7 @@ struct clkdm_ops omap2_clkdm_operations = {
|
||||
.clkdm_wakeup = omap2_clkdm_wakeup,
|
||||
.clkdm_allow_idle = omap2_clkdm_allow_idle,
|
||||
.clkdm_deny_idle = omap2_clkdm_deny_idle,
|
||||
+ .clkdm_is_idle = omap2_clkdm_is_idle,
|
||||
.clkdm_clk_enable = omap2_clkdm_clk_enable,
|
||||
.clkdm_clk_disable = omap2_clkdm_clk_disable,
|
||||
};
|
||||
@@ -269,6 +280,7 @@ struct clkdm_ops omap3_clkdm_operations = {
|
||||
.clkdm_wakeup = omap3_clkdm_wakeup,
|
||||
.clkdm_allow_idle = omap3_clkdm_allow_idle,
|
||||
.clkdm_deny_idle = omap3_clkdm_deny_idle,
|
||||
+ .clkdm_is_idle = omap2_clkdm_is_idle,
|
||||
.clkdm_clk_enable = omap2_clkdm_clk_enable,
|
||||
.clkdm_clk_disable = omap2_clkdm_clk_disable,
|
||||
};
|
||||
diff --git a/arch/arm/mach-omap2/clockdomain44xx.c b/arch/arm/mach-omap2/clockdomain44xx.c
|
||||
index a1a4ecd..4b10727 100644
|
||||
--- a/arch/arm/mach-omap2/clockdomain44xx.c
|
||||
+++ b/arch/arm/mach-omap2/clockdomain44xx.c
|
||||
@@ -93,6 +93,12 @@ static void omap4_clkdm_deny_idle(struct clockdomain *clkdm)
|
||||
clkdm->cm_inst, clkdm->clkdm_offs);
|
||||
}
|
||||
|
||||
+static int omap4_clkdm_is_idle(struct clockdomain *clkdm)
|
||||
+{
|
||||
+ return omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
|
||||
+ clkdm->cm_inst, clkdm->clkdm_offs);
|
||||
+}
|
||||
+
|
||||
static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
|
||||
{
|
||||
bool hwsup = false;
|
||||
@@ -132,6 +138,7 @@ struct clkdm_ops omap4_clkdm_operations = {
|
||||
.clkdm_wakeup = omap4_clkdm_wakeup,
|
||||
.clkdm_allow_idle = omap4_clkdm_allow_idle,
|
||||
.clkdm_deny_idle = omap4_clkdm_deny_idle,
|
||||
+ .clkdm_is_idle = omap4_clkdm_is_idle,
|
||||
.clkdm_clk_enable = omap4_clkdm_clk_enable,
|
||||
.clkdm_clk_disable = omap4_clkdm_clk_disable,
|
||||
};
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
From 7cdc87071a4bb390ad5d7ddea210bd2b4d662114 Mon Sep 17 00:00:00 2001
|
||||
From: Rajendra Nayak <rnayak@ti.com>
|
||||
Date: Tue, 5 Apr 2011 15:22:41 +0530
|
||||
Subject: [PATCH 3/6] OMAP2+: PM: Initialise sleep_switch to a non-valid value
|
||||
|
||||
sleep_switch which is initialised to 0 in omap_set_pwrdm_state
|
||||
happens to be a valid sleep_switch type (FORCEWAKEUP_SWITCH)
|
||||
which are defined as
|
||||
#define FORCEWAKEUP_SWITCH 0
|
||||
#define LOWPOWERSTATE_SWITCH 1
|
||||
|
||||
This causes the function to wrongly program some clock domains
|
||||
even when the Powerdomain is in ON state.
|
||||
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/pm.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
|
||||
index 49486f5..d48813f 100644
|
||||
--- a/arch/arm/mach-omap2/pm.c
|
||||
+++ b/arch/arm/mach-omap2/pm.c
|
||||
@@ -106,7 +106,7 @@ static void omap2_init_processor_devices(void)
|
||||
int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
|
||||
{
|
||||
u32 cur_state;
|
||||
- int sleep_switch = 0;
|
||||
+ int sleep_switch = -1;
|
||||
int ret = 0;
|
||||
|
||||
if (pwrdm == NULL || IS_ERR(pwrdm))
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-50
@@ -1,50 +0,0 @@
|
||||
From cec133850aa42c03d912c764aaa441677e782eca Mon Sep 17 00:00:00 2001
|
||||
From: Rajendra Nayak <rnayak@ti.com>
|
||||
Date: Tue, 5 Apr 2011 15:22:48 +0530
|
||||
Subject: [PATCH 4/6] OMAP2+: PM: idle clkdms only if already in idle
|
||||
|
||||
The omap_set_pwrdm_state function forces clockdomains
|
||||
to idle, without checking the existing idle state
|
||||
programmed, instead based solely on the HW capability
|
||||
of the clockdomain to support idle.
|
||||
This is wrong and the clockdomains should be idled
|
||||
post a state_switch *only* if idle transitions on the
|
||||
clockdomain were already enabled.
|
||||
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/pm.c | 4 +++-
|
||||
1 files changed, 3 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
|
||||
index d48813f..840b0e1 100644
|
||||
--- a/arch/arm/mach-omap2/pm.c
|
||||
+++ b/arch/arm/mach-omap2/pm.c
|
||||
@@ -108,6 +108,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
|
||||
u32 cur_state;
|
||||
int sleep_switch = -1;
|
||||
int ret = 0;
|
||||
+ int hwsup = 0;
|
||||
|
||||
if (pwrdm == NULL || IS_ERR(pwrdm))
|
||||
return -EINVAL;
|
||||
@@ -127,6 +128,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
|
||||
(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
|
||||
sleep_switch = LOWPOWERSTATE_SWITCH;
|
||||
} else {
|
||||
+ hwsup = clkdm_is_idle(pwrdm->pwrdm_clkdms[0]);
|
||||
clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
|
||||
pwrdm_wait_transition(pwrdm);
|
||||
sleep_switch = FORCEWAKEUP_SWITCH;
|
||||
@@ -142,7 +144,7 @@ int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state)
|
||||
|
||||
switch (sleep_switch) {
|
||||
case FORCEWAKEUP_SWITCH:
|
||||
- if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO)
|
||||
+ if (hwsup)
|
||||
clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
|
||||
else
|
||||
clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
From 8fb6b7c488b31fbff5b81bdeea5dbb236342458b Mon Sep 17 00:00:00 2001
|
||||
From: Rajendra Nayak <rnayak@ti.com>
|
||||
Date: Tue, 29 Mar 2011 22:37:43 +0530
|
||||
Subject: [PATCH 5/6] OMAP2+: hwmod: Follow the recomended PRCM sequence
|
||||
|
||||
Follow the recomended PRCM sequence.
|
||||
This still does not take care of Optional clocks.
|
||||
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/omap_hwmod.c | 9 ++++++++-
|
||||
1 files changed, 8 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
|
||||
index e034294..fc0db0c 100644
|
||||
--- a/arch/arm/mach-omap2/omap_hwmod.c
|
||||
+++ b/arch/arm/mach-omap2/omap_hwmod.c
|
||||
@@ -1223,6 +1223,7 @@ static int _reset(struct omap_hwmod *oh)
|
||||
static int _enable(struct omap_hwmod *oh)
|
||||
{
|
||||
int r;
|
||||
+ int hwsup = 0;
|
||||
|
||||
if (oh->_state != _HWMOD_STATE_INITIALIZED &&
|
||||
oh->_state != _HWMOD_STATE_IDLE &&
|
||||
@@ -1250,10 +1251,16 @@ static int _enable(struct omap_hwmod *oh)
|
||||
omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
|
||||
|
||||
_add_initiator_dep(oh, mpu_oh);
|
||||
+ if (oh->_clk && oh->_clk->clkdm) {
|
||||
+ hwsup = clkdm_is_idle(oh->_clk->clkdm);
|
||||
+ clkdm_wakeup(oh->_clk->clkdm);
|
||||
+ }
|
||||
_enable_clocks(oh);
|
||||
-
|
||||
r = _wait_target_ready(oh);
|
||||
if (!r) {
|
||||
+ if (oh->_clk && oh->_clk->clkdm && hwsup)
|
||||
+ clkdm_allow_idle(oh->_clk->clkdm);
|
||||
+
|
||||
oh->_state = _HWMOD_STATE_ENABLED;
|
||||
|
||||
/* Access the sysconfig only if the target is ready */
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
From 7b74888d198c260992349fab214cad3adf853ef9 Mon Sep 17 00:00:00 2001
|
||||
From: Rajendra Nayak <rnayak@ti.com>
|
||||
Date: Tue, 2 Mar 2010 17:25:30 +0530
|
||||
Subject: [PATCH 6/6] OMAP: Serial: Check wk_st only if present
|
||||
|
||||
Uart on the resume path tries to read wk_st registers, even
|
||||
on architectures were its not present/populated.
|
||||
This patch fixes the issue.
|
||||
|
||||
Signed-off-by: Rajendra Nayak <rnayak@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/serial.c | 5 +++--
|
||||
1 files changed, 3 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
|
||||
index 1ac361b..a0046ce 100644
|
||||
--- a/arch/arm/mach-omap2/serial.c
|
||||
+++ b/arch/arm/mach-omap2/serial.c
|
||||
@@ -418,8 +418,9 @@ void omap_uart_resume_idle(int num)
|
||||
}
|
||||
|
||||
/* Check for normal UART wakeup */
|
||||
- if (__raw_readl(uart->wk_st) & uart->wk_mask)
|
||||
- omap_uart_block_sleep(uart);
|
||||
+ if (uart->wk_st && uart->wk_mask)
|
||||
+ if (__raw_readl(uart->wk_st) & uart->wk_mask)
|
||||
+ omap_uart_block_sleep(uart);
|
||||
return;
|
||||
}
|
||||
}
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
From 4af697edf9d1d85d2735e86e86e1203c3509dcba Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Sat, 12 Feb 2011 17:27:14 +0530
|
||||
Subject: [PATCH 01/12] OMAP3+: voltage: remove spurious pr_notice for debugfs
|
||||
|
||||
cat of debugfs entry for vp_volt provides voltage. The additional pr_notice
|
||||
is just spam on console and provides no additional information.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/voltage.c | 1 -
|
||||
1 files changed, 0 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/voltage.c b/arch/arm/mach-omap2/voltage.c
|
||||
index 0c1552d..9ef3789 100644
|
||||
--- a/arch/arm/mach-omap2/voltage.c
|
||||
+++ b/arch/arm/mach-omap2/voltage.c
|
||||
@@ -148,7 +148,6 @@ static int vp_volt_debug_get(void *data, u64 *val)
|
||||
}
|
||||
|
||||
vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
|
||||
- pr_notice("curr_vsel = %x\n", vsel);
|
||||
|
||||
if (!vdd->pmic_info->vsel_to_uv) {
|
||||
pr_warning("PMIC function to convert vsel to voltage"
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
From 37fb1c8eeecd39542716d3d0c7c5e3ca0eb198f8 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Sun, 13 Mar 2011 09:07:23 +0530
|
||||
Subject: [PATCH 02/12] OMAP4: PM: remove redundant #ifdef CONFIG_PM
|
||||
|
||||
pm44xx.c is built only when CONFIG_PM is setup,
|
||||
remove redundant CONFIG_PM check.
|
||||
|
||||
This also fixes:
|
||||
https://bugzilla.kernel.org/show_bug.cgi?id=25022
|
||||
|
||||
Reported-by: Martin Etti <ettl.martin@gmx.de>
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/pm44xx.c | 2 --
|
||||
1 files changed, 0 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/pm44xx.c b/arch/arm/mach-omap2/pm44xx.c
|
||||
index 76cfff2..59a870b 100644
|
||||
--- a/arch/arm/mach-omap2/pm44xx.c
|
||||
+++ b/arch/arm/mach-omap2/pm44xx.c
|
||||
@@ -105,13 +105,11 @@ static int __init omap4_pm_init(void)
|
||||
|
||||
pr_err("Power Management for TI OMAP4.\n");
|
||||
|
||||
-#ifdef CONFIG_PM
|
||||
ret = pwrdm_for_each(pwrdms_setup, NULL);
|
||||
if (ret) {
|
||||
pr_err("Failed to setup powerdomains\n");
|
||||
goto err2;
|
||||
}
|
||||
-#endif
|
||||
|
||||
#ifdef CONFIG_SUSPEND
|
||||
suspend_set_ops(&omap_pm_ops);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-30
@@ -1,30 +0,0 @@
|
||||
From a22a0dcefe99c8ee260e0c489bc44e6e14bb1ccb Mon Sep 17 00:00:00 2001
|
||||
From: Aaro Koskinen <aaro.koskinen@nokia.com>
|
||||
Date: Thu, 24 Mar 2011 18:35:31 +0200
|
||||
Subject: [PATCH 03/12] OMAP3+: smartreflex: fix sr_late_init() error path in probe
|
||||
|
||||
sr_late_init() will take care of freeing the resources.
|
||||
|
||||
Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/smartreflex.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
|
||||
index 13e24f9..dbc4b6f 100644
|
||||
--- a/arch/arm/mach-omap2/smartreflex.c
|
||||
+++ b/arch/arm/mach-omap2/smartreflex.c
|
||||
@@ -883,7 +883,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
||||
ret = sr_late_init(sr_info);
|
||||
if (ret) {
|
||||
pr_warning("%s: Error in SR late init\n", __func__);
|
||||
- goto err_release_region;
|
||||
+ return ret;
|
||||
}
|
||||
}
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-36
@@ -1,36 +0,0 @@
|
||||
From db9c7da6a78be8584c96c83a3a2d1c8aeb623da8 Mon Sep 17 00:00:00 2001
|
||||
From: Aaro Koskinen <aaro.koskinen@nokia.com>
|
||||
Date: Thu, 24 Mar 2011 18:35:32 +0200
|
||||
Subject: [PATCH 04/12] OMAP3+: smartreflex: request the memory region
|
||||
|
||||
We are releasing the memory region, but never actually request it.
|
||||
|
||||
Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/smartreflex.c | 8 ++++++++
|
||||
1 files changed, 8 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
|
||||
index dbc4b6f..703143a 100644
|
||||
--- a/arch/arm/mach-omap2/smartreflex.c
|
||||
+++ b/arch/arm/mach-omap2/smartreflex.c
|
||||
@@ -847,6 +847,14 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
||||
goto err_free_devinfo;
|
||||
}
|
||||
|
||||
+ mem = request_mem_region(mem->start, resource_size(mem),
|
||||
+ dev_name(&pdev->dev));
|
||||
+ if (!mem) {
|
||||
+ dev_err(&pdev->dev, "%s: no mem region\n", __func__);
|
||||
+ ret = -EBUSY;
|
||||
+ goto err_free_devinfo;
|
||||
+ }
|
||||
+
|
||||
irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-66
@@ -1,66 +0,0 @@
|
||||
From b3ca51ac09da7c260c28df396d4c830814697ff0 Mon Sep 17 00:00:00 2001
|
||||
From: Aaro Koskinen <aaro.koskinen@nokia.com>
|
||||
Date: Thu, 24 Mar 2011 18:35:33 +0200
|
||||
Subject: [PATCH 05/12] OMAP3+: smartreflex: fix ioremap leak on probe error
|
||||
|
||||
Add missing iounmap() to error paths.
|
||||
|
||||
Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/smartreflex.c | 10 ++++++----
|
||||
1 files changed, 6 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
|
||||
index 703143a..156807e 100644
|
||||
--- a/arch/arm/mach-omap2/smartreflex.c
|
||||
+++ b/arch/arm/mach-omap2/smartreflex.c
|
||||
@@ -904,7 +904,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
||||
vdd_dbg_dir = omap_voltage_get_dbgdir(sr_info->voltdm);
|
||||
if (!vdd_dbg_dir) {
|
||||
ret = -EINVAL;
|
||||
- goto err_release_region;
|
||||
+ goto err_iounmap;
|
||||
}
|
||||
|
||||
sr_info->dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir);
|
||||
@@ -912,7 +912,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
|
||||
__func__);
|
||||
ret = PTR_ERR(sr_info->dbg_dir);
|
||||
- goto err_release_region;
|
||||
+ goto err_iounmap;
|
||||
}
|
||||
|
||||
(void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR,
|
||||
@@ -929,7 +929,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "%s: Unable to create debugfs directory"
|
||||
"for n-values\n", __func__);
|
||||
ret = PTR_ERR(nvalue_dir);
|
||||
- goto err_release_region;
|
||||
+ goto err_iounmap;
|
||||
}
|
||||
|
||||
omap_voltage_get_volttable(sr_info->voltdm, &volt_data);
|
||||
@@ -939,7 +939,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
||||
"entries for n-values\n",
|
||||
__func__, sr_info->voltdm->name);
|
||||
ret = -ENODATA;
|
||||
- goto err_release_region;
|
||||
+ goto err_iounmap;
|
||||
}
|
||||
|
||||
for (i = 0; i < sr_info->nvalue_count; i++) {
|
||||
@@ -953,6 +953,8 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
||||
|
||||
return ret;
|
||||
|
||||
+err_iounmap:
|
||||
+ iounmap(sr_info->base);
|
||||
err_release_region:
|
||||
release_mem_region(mem->start, resource_size(mem));
|
||||
err_free_devinfo:
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
From 92e63a2f098ce344cfc51ec9a7420e1a5cf85c3e Mon Sep 17 00:00:00 2001
|
||||
From: Aaro Koskinen <aaro.koskinen@nokia.com>
|
||||
Date: Thu, 24 Mar 2011 18:35:34 +0200
|
||||
Subject: [PATCH 06/12] OMAP3+: smartreflex: delete instance from sr_list on probe error
|
||||
|
||||
If the probe fails, the node should be deleted from sr_list.
|
||||
|
||||
Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/smartreflex.c | 1 +
|
||||
1 files changed, 1 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
|
||||
index 156807e..f0a488a 100644
|
||||
--- a/arch/arm/mach-omap2/smartreflex.c
|
||||
+++ b/arch/arm/mach-omap2/smartreflex.c
|
||||
@@ -954,6 +954,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
|
||||
err_iounmap:
|
||||
+ list_del(&sr_info->node);
|
||||
iounmap(sr_info->base);
|
||||
err_release_region:
|
||||
release_mem_region(mem->start, resource_size(mem));
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
From c194377152df812bcb29fff8f217ffbde59089be Mon Sep 17 00:00:00 2001
|
||||
From: Aaro Koskinen <aaro.koskinen@nokia.com>
|
||||
Date: Thu, 24 Mar 2011 18:35:35 +0200
|
||||
Subject: [PATCH 07/12] OMAP3+: smartreflex: delete debugfs entries on probe error
|
||||
|
||||
Delete created debugfs entries if probe fails.
|
||||
|
||||
Signed-off-by: Aaro Koskinen <aaro.koskinen@nokia.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/smartreflex.c | 6 ++++--
|
||||
1 files changed, 4 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
|
||||
index f0a488a..fb7dc52 100644
|
||||
--- a/arch/arm/mach-omap2/smartreflex.c
|
||||
+++ b/arch/arm/mach-omap2/smartreflex.c
|
||||
@@ -929,7 +929,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
||||
dev_err(&pdev->dev, "%s: Unable to create debugfs directory"
|
||||
"for n-values\n", __func__);
|
||||
ret = PTR_ERR(nvalue_dir);
|
||||
- goto err_iounmap;
|
||||
+ goto err_debugfs;
|
||||
}
|
||||
|
||||
omap_voltage_get_volttable(sr_info->voltdm, &volt_data);
|
||||
@@ -939,7 +939,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
||||
"entries for n-values\n",
|
||||
__func__, sr_info->voltdm->name);
|
||||
ret = -ENODATA;
|
||||
- goto err_iounmap;
|
||||
+ goto err_debugfs;
|
||||
}
|
||||
|
||||
for (i = 0; i < sr_info->nvalue_count; i++) {
|
||||
@@ -953,6 +953,8 @@ static int __init omap_sr_probe(struct platform_device *pdev)
|
||||
|
||||
return ret;
|
||||
|
||||
+err_debugfs:
|
||||
+ debugfs_remove_recursive(sr_info->dbg_dir);
|
||||
err_iounmap:
|
||||
list_del(&sr_info->node);
|
||||
iounmap(sr_info->base);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-57
@@ -1,57 +0,0 @@
|
||||
From 2b9e07516cc3853340b5e06e9ae7244ca5681466 Mon Sep 17 00:00:00 2001
|
||||
From: Jean Pihet <j-pihet@ti.com>
|
||||
Date: Fri, 29 Apr 2011 11:26:22 +0200
|
||||
Subject: [PATCH 08/12] OMAP3 cpuidle: remove useless SDP specific timings
|
||||
|
||||
The cpuidle states settings can be overriden by some board-
|
||||
specific settings, by calling omap3_pm_init_cpuidle.
|
||||
Remove the 3430SDP specific states settings registration
|
||||
since the figures are identical to the default ones (in cpuidle34xx.c).
|
||||
|
||||
Signed-off-by: Jean Pihet <j-pihet@ti.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/board-3430sdp.c | 19 -------------------
|
||||
1 files changed, 0 insertions(+), 19 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
|
||||
index 9afd087..7ffad7b 100644
|
||||
--- a/arch/arm/mach-omap2/board-3430sdp.c
|
||||
+++ b/arch/arm/mach-omap2/board-3430sdp.c
|
||||
@@ -59,24 +59,6 @@
|
||||
|
||||
#define TWL4030_MSECURE_GPIO 22
|
||||
|
||||
-/* FIXME: These values need to be updated based on more profiling on 3430sdp*/
|
||||
-static struct cpuidle_params omap3_cpuidle_params_table[] = {
|
||||
- /* C1 */
|
||||
- {1, 2, 2, 5},
|
||||
- /* C2 */
|
||||
- {1, 10, 10, 30},
|
||||
- /* C3 */
|
||||
- {1, 50, 50, 300},
|
||||
- /* C4 */
|
||||
- {1, 1500, 1800, 4000},
|
||||
- /* C5 */
|
||||
- {1, 2500, 7500, 12000},
|
||||
- /* C6 */
|
||||
- {1, 3000, 8500, 15000},
|
||||
- /* C7 */
|
||||
- {1, 10000, 30000, 300000},
|
||||
-};
|
||||
-
|
||||
static uint32_t board_keymap[] = {
|
||||
KEY(0, 0, KEY_LEFT),
|
||||
KEY(0, 1, KEY_RIGHT),
|
||||
@@ -883,7 +865,6 @@ static void __init omap_3430sdp_init(void)
|
||||
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
|
||||
omap_board_config = sdp3430_config;
|
||||
omap_board_config_size = ARRAY_SIZE(sdp3430_config);
|
||||
- omap3_pm_init_cpuidle(omap3_cpuidle_params_table);
|
||||
omap3430_i2c_init();
|
||||
omap_display_init(&sdp3430_dss_data);
|
||||
if (omap_rev() > OMAP3430_REV_ES1_0)
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-48
@@ -1,48 +0,0 @@
|
||||
From a0f28097b944930e479998780863b9e5a39e30b3 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Mon, 14 Feb 2011 12:16:36 +0530
|
||||
Subject: [PATCH 09/12] OMAP3+: SR: make notify independent of class
|
||||
|
||||
Interrupt notification mechanism of SmartReflex can be used by the
|
||||
choice of implementation of the class driver. For example, Class 2 and
|
||||
Class 1.5 of SmartReflex can both use the interrupt notification to
|
||||
identify the transition of voltage or other events.
|
||||
|
||||
Hence, the actual class does not matter for notifier. Let the class
|
||||
driver's handling decide how it should be used. SmartReflex driver
|
||||
should provide just the primitives.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/smartreflex.c | 6 ++----
|
||||
1 files changed, 2 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
|
||||
index fb7dc52..3ee7261 100644
|
||||
--- a/arch/arm/mach-omap2/smartreflex.c
|
||||
+++ b/arch/arm/mach-omap2/smartreflex.c
|
||||
@@ -143,7 +143,7 @@ static irqreturn_t sr_interrupt(int irq, void *data)
|
||||
sr_write_reg(sr_info, IRQSTATUS, status);
|
||||
}
|
||||
|
||||
- if (sr_class->class_type == SR_CLASS2 && sr_class->notify)
|
||||
+ if (sr_class->notify)
|
||||
sr_class->notify(sr_info->voltdm, status);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@@ -258,9 +258,7 @@ static int sr_late_init(struct omap_sr *sr_info)
|
||||
struct resource *mem;
|
||||
int ret = 0;
|
||||
|
||||
- if (sr_class->class_type == SR_CLASS2 &&
|
||||
- sr_class->notify_flags && sr_info->irq) {
|
||||
-
|
||||
+ if (sr_class->notify && sr_class->notify_flags && sr_info->irq) {
|
||||
name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
|
||||
if (name == NULL) {
|
||||
ret = -ENOMEM;
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-37
@@ -1,37 +0,0 @@
|
||||
From ca5dc57538a566681731102e09a9d1865a4a7020 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Mon, 14 Feb 2011 12:41:10 +0530
|
||||
Subject: [PATCH 10/12] OMAP3+: SR: disable interrupt by default
|
||||
|
||||
We will enable and disable interrupt on a need basis in the class
|
||||
driver. We need to keep the IRQ disabled by default else the
|
||||
forceupdate or vcbypass events could trigger events that we don't
|
||||
need/expect to handle.
|
||||
|
||||
This is a preparation for SmartReflex AVS class drivers such as
|
||||
class 2 and class 1.5 which would need to use interrupts. Existing
|
||||
SmartReflex AVS class 3 driver does not require to use interrupts
|
||||
and is not impacted by this change.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/smartreflex.c | 1 +
|
||||
1 files changed, 1 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
|
||||
index 3ee7261..616ef62 100644
|
||||
--- a/arch/arm/mach-omap2/smartreflex.c
|
||||
+++ b/arch/arm/mach-omap2/smartreflex.c
|
||||
@@ -268,6 +268,7 @@ static int sr_late_init(struct omap_sr *sr_info)
|
||||
0, name, (void *)sr_info);
|
||||
if (ret)
|
||||
goto error;
|
||||
+ disable_irq(sr_info->irq);
|
||||
}
|
||||
|
||||
if (pdata && pdata->enable_on_init)
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-41
@@ -1,41 +0,0 @@
|
||||
From 4aa67e94d6b13905abcf3e95cb66ea7be9c2e8dd Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Mon, 14 Feb 2011 21:14:17 +0530
|
||||
Subject: [PATCH 11/12] OMAP3+: SR: enable/disable SR only on need
|
||||
|
||||
Since we already know the state of the autocomp enablement, we can
|
||||
see if the requested state is different from the current state and
|
||||
enable/disable SR only on the need basis.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/smartreflex.c | 11 +++++++----
|
||||
1 files changed, 7 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
|
||||
index 616ef62..3bd9fac 100644
|
||||
--- a/arch/arm/mach-omap2/smartreflex.c
|
||||
+++ b/arch/arm/mach-omap2/smartreflex.c
|
||||
@@ -807,10 +807,13 @@ static int omap_sr_autocomp_store(void *data, u64 val)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
- if (!val)
|
||||
- sr_stop_vddautocomp(sr_info);
|
||||
- else
|
||||
- sr_start_vddautocomp(sr_info);
|
||||
+ /* control enable/disable only if there is a delta in value */
|
||||
+ if (sr_info->autocomp_active != val) {
|
||||
+ if (!val)
|
||||
+ sr_stop_vddautocomp(sr_info);
|
||||
+ else
|
||||
+ sr_start_vddautocomp(sr_info);
|
||||
+ }
|
||||
|
||||
return 0;
|
||||
}
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
From 0c2089eecdfc3a85a376eddf9c77857f3d575be6 Mon Sep 17 00:00:00 2001
|
||||
From: Nishanth Menon <nm@ti.com>
|
||||
Date: Mon, 14 Feb 2011 12:33:13 +0530
|
||||
Subject: [PATCH 12/12] OMAP3+: SR: fix cosmetic indentation
|
||||
|
||||
Error label case seems to have a 2 tab indentation when just 1 is
|
||||
necessary.
|
||||
|
||||
Signed-off-by: Nishanth Menon <nm@ti.com>
|
||||
Signed-off-by: Kevin Hilman <khilman@ti.com>
|
||||
Signed-off-by: Koen Kooi <koen@dominion.thruhere.net>
|
||||
---
|
||||
arch/arm/mach-omap2/smartreflex.c | 20 ++++++++++----------
|
||||
1 files changed, 10 insertions(+), 10 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
|
||||
index 3bd9fac..2ce2fb7 100644
|
||||
--- a/arch/arm/mach-omap2/smartreflex.c
|
||||
+++ b/arch/arm/mach-omap2/smartreflex.c
|
||||
@@ -277,16 +277,16 @@ static int sr_late_init(struct omap_sr *sr_info)
|
||||
return ret;
|
||||
|
||||
error:
|
||||
- iounmap(sr_info->base);
|
||||
- mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0);
|
||||
- release_mem_region(mem->start, resource_size(mem));
|
||||
- list_del(&sr_info->node);
|
||||
- dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
|
||||
- "interrupt handler. Smartreflex will"
|
||||
- "not function as desired\n", __func__);
|
||||
- kfree(name);
|
||||
- kfree(sr_info);
|
||||
- return ret;
|
||||
+ iounmap(sr_info->base);
|
||||
+ mem = platform_get_resource(sr_info->pdev, IORESOURCE_MEM, 0);
|
||||
+ release_mem_region(mem->start, resource_size(mem));
|
||||
+ list_del(&sr_info->node);
|
||||
+ dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
|
||||
+ "interrupt handler. Smartreflex will"
|
||||
+ "not function as desired\n", __func__);
|
||||
+ kfree(name);
|
||||
+ kfree(sr_info);
|
||||
+ return ret;
|
||||
}
|
||||
|
||||
static void sr_v1_disable(struct omap_sr *sr)
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
From 6aae34d56ba8fef140b60631536272f6b39c1f61 Mon Sep 17 00:00:00 2001
|
||||
From: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
Date: Thu, 7 Apr 2011 15:28:47 +0300
|
||||
Subject: [PATCH 01/32] OMAP: DSS2: DSI: fix use_sys_clk & highfreq
|
||||
|
||||
use_sys_clk and highfreq fields in dsi.current_cinfo were never set.
|
||||
Luckily they weren't used anywhere so it didn't cause any problems.
|
||||
|
||||
This patch fixes those fields and they are now set at the same time as
|
||||
the rest of the fields.
|
||||
|
||||
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
---
|
||||
drivers/video/omap2/dss/dsi.c | 3 +++
|
||||
1 files changed, 3 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
|
||||
index 0a7f1a4..8604153 100644
|
||||
--- a/drivers/video/omap2/dss/dsi.c
|
||||
+++ b/drivers/video/omap2/dss/dsi.c
|
||||
@@ -1276,6 +1276,9 @@ int dsi_pll_set_clock_div(struct dsi_clock_info *cinfo)
|
||||
|
||||
DSSDBGF();
|
||||
|
||||
+ dsi.current_cinfo.use_sys_clk = cinfo->use_sys_clk;
|
||||
+ dsi.current_cinfo.highfreq = cinfo->highfreq;
|
||||
+
|
||||
dsi.current_cinfo.fint = cinfo->fint;
|
||||
dsi.current_cinfo.clkin4ddr = cinfo->clkin4ddr;
|
||||
dsi.current_cinfo.dsi_pll_hsdiv_dispc_clk =
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
From 5275654d2e873ca5bdbbd8be61dbb2d63c0e04cb Mon Sep 17 00:00:00 2001
|
||||
From: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
Date: Mon, 4 Apr 2011 10:02:53 +0300
|
||||
Subject: [PATCH 02/32] OMAP: DSS2: DSI: fix dsi_dump_clocks()
|
||||
|
||||
On OMAP4, reading DSI_PLL_CONFIGURATION2 register requires the L3 clock
|
||||
(CIO_CLK_ICG) to PLL. Currently dsi_dump_clocks() tries to read that
|
||||
register without enabling the L3 clock, leading to crash if DSI is not
|
||||
in use.
|
||||
|
||||
The status of the bit being read from DSI_PLL_CONFIGURATION2 is
|
||||
available from dsi_clock_info->use_sys_clk, so we can avoid the whole
|
||||
problem by just using that.
|
||||
|
||||
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
---
|
||||
drivers/video/omap2/dss/dsi.c | 6 +-----
|
||||
1 files changed, 1 insertions(+), 5 deletions(-)
|
||||
|
||||
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
|
||||
index 8604153..1464ac4 100644
|
||||
--- a/drivers/video/omap2/dss/dsi.c
|
||||
+++ b/drivers/video/omap2/dss/dsi.c
|
||||
@@ -1491,7 +1491,6 @@ void dsi_pll_uninit(void)
|
||||
|
||||
void dsi_dump_clocks(struct seq_file *s)
|
||||
{
|
||||
- int clksel;
|
||||
struct dsi_clock_info *cinfo = &dsi.current_cinfo;
|
||||
enum dss_clk_source dispc_clk_src, dsi_clk_src;
|
||||
|
||||
@@ -1500,13 +1499,10 @@ void dsi_dump_clocks(struct seq_file *s)
|
||||
|
||||
enable_clocks(1);
|
||||
|
||||
- clksel = REG_GET(DSI_PLL_CONFIGURATION2, 11, 11);
|
||||
-
|
||||
seq_printf(s, "- DSI PLL -\n");
|
||||
|
||||
seq_printf(s, "dsi pll source = %s\n",
|
||||
- clksel == 0 ?
|
||||
- "dss_sys_clk" : "pclkfree");
|
||||
+ cinfo->use_sys_clk ? "dss_sys_clk" : "pclkfree");
|
||||
|
||||
seq_printf(s, "Fint\t\t%-16luregn %u\n", cinfo->fint, cinfo->regn);
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-43
@@ -1,43 +0,0 @@
|
||||
From 9ddb3aafff5f7f6b7eaad32f9b1eea249c0dce8b Mon Sep 17 00:00:00 2001
|
||||
From: Archit Taneja <archit@ti.com>
|
||||
Date: Thu, 31 Mar 2011 13:23:35 +0530
|
||||
Subject: [PATCH 03/32] OMAP2PLUS: DSS2: Fix: Return correct lcd clock source for OMAP2/3
|
||||
|
||||
dss.lcd_clk_source is set to the default value DSS_CLK_SRC_FCK at dss_init.
|
||||
For OMAP2 and OMAP3, the dss.lcd_clk_source should always be the same as
|
||||
dss.dispc_clk_source. The function dss_get_lcd_clk_source() always returns the
|
||||
default value DSS_CLK_SRC_FCK for OMAP2/3. This leads to wrong clock dumps when
|
||||
dispc_clk_source is not DSS_CLK_SRC_FCK.
|
||||
|
||||
Correct this function to always return dss.dispc_clk_source for OMAP2/3.
|
||||
|
||||
Signed-off-by: Archit Taneja <archit@ti.com>
|
||||
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
---
|
||||
drivers/video/omap2/dss/dss.c | 10 ++++++++--
|
||||
1 files changed, 8 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/drivers/video/omap2/dss/dss.c b/drivers/video/omap2/dss/dss.c
|
||||
index 3f1fee6..c3b48a0 100644
|
||||
--- a/drivers/video/omap2/dss/dss.c
|
||||
+++ b/drivers/video/omap2/dss/dss.c
|
||||
@@ -385,8 +385,14 @@ enum dss_clk_source dss_get_dsi_clk_source(void)
|
||||
|
||||
enum dss_clk_source dss_get_lcd_clk_source(enum omap_channel channel)
|
||||
{
|
||||
- int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
|
||||
- return dss.lcd_clk_source[ix];
|
||||
+ if (dss_has_feature(FEAT_LCD_CLK_SRC)) {
|
||||
+ int ix = channel == OMAP_DSS_CHANNEL_LCD ? 0 : 1;
|
||||
+ return dss.lcd_clk_source[ix];
|
||||
+ } else {
|
||||
+ /* LCD_CLK source is the same as DISPC_FCLK source for
|
||||
+ * OMAP2 and OMAP3 */
|
||||
+ return dss.dispc_clk_source;
|
||||
+ }
|
||||
}
|
||||
|
||||
/* calculate clock rates using dividers in cinfo */
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-64
@@ -1,64 +0,0 @@
|
||||
From 4a56fbcabd128dbd07895e5167fd131299a1391c Mon Sep 17 00:00:00 2001
|
||||
From: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
Date: Fri, 15 Apr 2011 10:42:59 +0300
|
||||
Subject: [PATCH 04/32] OMAP: DSS: DSI: Fix DSI PLL power bug
|
||||
|
||||
OMAP3630 has a HW bug causing DSI PLL power command POWER_ON_DIV (0x3)
|
||||
to not work properly. The bug prevents us from enabling DSI PLL power
|
||||
only to HS divider block.
|
||||
|
||||
This patch adds a dss feature for the bug and converts POWER_ON_DIV
|
||||
requests to POWER_ON_ALL (0x2).
|
||||
|
||||
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
---
|
||||
drivers/video/omap2/dss/dsi.c | 5 +++++
|
||||
drivers/video/omap2/dss/dss_features.c | 2 +-
|
||||
drivers/video/omap2/dss/dss_features.h | 2 ++
|
||||
3 files changed, 8 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/drivers/video/omap2/dss/dsi.c b/drivers/video/omap2/dss/dsi.c
|
||||
index 1464ac4..cbd9ca4 100644
|
||||
--- a/drivers/video/omap2/dss/dsi.c
|
||||
+++ b/drivers/video/omap2/dss/dsi.c
|
||||
@@ -1059,6 +1059,11 @@ static int dsi_pll_power(enum dsi_pll_power_state state)
|
||||
{
|
||||
int t = 0;
|
||||
|
||||
+ /* DSI-PLL power command 0x3 is not working */
|
||||
+ if (dss_has_feature(FEAT_DSI_PLL_PWR_BUG) &&
|
||||
+ state == DSI_PLL_POWER_ON_DIV)
|
||||
+ state = DSI_PLL_POWER_ON_ALL;
|
||||
+
|
||||
REG_FLD_MOD(DSI_CLK_CTRL, state, 31, 30); /* PLL_PWR_CMD */
|
||||
|
||||
/* PLL_PWR_STATUS */
|
||||
diff --git a/drivers/video/omap2/dss/dss_features.c b/drivers/video/omap2/dss/dss_features.c
|
||||
index aa16222..8c50e18 100644
|
||||
--- a/drivers/video/omap2/dss/dss_features.c
|
||||
+++ b/drivers/video/omap2/dss/dss_features.c
|
||||
@@ -271,7 +271,7 @@ static struct omap_dss_features omap3630_dss_features = {
|
||||
FEAT_LCDENABLESIGNAL | FEAT_PCKFREEENABLE |
|
||||
FEAT_PRE_MULT_ALPHA | FEAT_FUNCGATED |
|
||||
FEAT_ROWREPEATENABLE | FEAT_LINEBUFFERSPLIT |
|
||||
- FEAT_RESIZECONF,
|
||||
+ FEAT_RESIZECONF | FEAT_DSI_PLL_PWR_BUG,
|
||||
|
||||
.num_mgrs = 2,
|
||||
.num_ovls = 3,
|
||||
diff --git a/drivers/video/omap2/dss/dss_features.h b/drivers/video/omap2/dss/dss_features.h
|
||||
index 12e9c4e..37922ce 100644
|
||||
--- a/drivers/video/omap2/dss/dss_features.h
|
||||
+++ b/drivers/video/omap2/dss/dss_features.h
|
||||
@@ -40,6 +40,8 @@ enum dss_feat_id {
|
||||
/* Independent core clk divider */
|
||||
FEAT_CORE_CLK_DIV = 1 << 11,
|
||||
FEAT_LCD_CLK_SRC = 1 << 12,
|
||||
+ /* DSI-PLL power command 0x3 is not working */
|
||||
+ FEAT_DSI_PLL_PWR_BUG = 1 << 13,
|
||||
};
|
||||
|
||||
/* DSS register field id */
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-61
@@ -1,61 +0,0 @@
|
||||
From fcb26a06fe1badfaaf7aaa68140c8b3370dd503e Mon Sep 17 00:00:00 2001
|
||||
From: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
Date: Fri, 8 Apr 2011 09:30:27 +0300
|
||||
Subject: [PATCH 05/32] OMAP: DSS2: fix panel Kconfig dependencies
|
||||
|
||||
All DPI panels were missing dependency to OMAP2_DSS_DPI. Add the
|
||||
dependency.
|
||||
|
||||
Signed-off-by: Tomi Valkeinen <tomi.valkeinen@ti.com>
|
||||
---
|
||||
drivers/video/omap2/displays/Kconfig | 9 +++++----
|
||||
1 files changed, 5 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/video/omap2/displays/Kconfig b/drivers/video/omap2/displays/Kconfig
|
||||
index d18ad6b..609a280 100644
|
||||
--- a/drivers/video/omap2/displays/Kconfig
|
||||
+++ b/drivers/video/omap2/displays/Kconfig
|
||||
@@ -3,6 +3,7 @@ menu "OMAP2/3 Display Device Drivers"
|
||||
|
||||
config PANEL_GENERIC_DPI
|
||||
tristate "Generic DPI Panel"
|
||||
+ depends on OMAP2_DSS_DPI
|
||||
help
|
||||
Generic DPI panel driver.
|
||||
Supports DVI output for Beagle and OMAP3 SDP.
|
||||
@@ -11,20 +12,20 @@ config PANEL_GENERIC_DPI
|
||||
|
||||
config PANEL_LGPHILIPS_LB035Q02
|
||||
tristate "LG.Philips LB035Q02 LCD Panel"
|
||||
- depends on OMAP2_DSS && SPI
|
||||
+ depends on OMAP2_DSS_DPI && SPI
|
||||
help
|
||||
LCD Panel used on the Gumstix Overo Palo35
|
||||
|
||||
config PANEL_SHARP_LS037V7DW01
|
||||
tristate "Sharp LS037V7DW01 LCD Panel"
|
||||
- depends on OMAP2_DSS
|
||||
+ depends on OMAP2_DSS_DPI
|
||||
select BACKLIGHT_CLASS_DEVICE
|
||||
help
|
||||
LCD Panel used in TI's SDP3430 and EVM boards
|
||||
|
||||
config PANEL_NEC_NL8048HL11_01B
|
||||
tristate "NEC NL8048HL11-01B Panel"
|
||||
- depends on OMAP2_DSS
|
||||
+ depends on OMAP2_DSS_DPI
|
||||
help
|
||||
This NEC NL8048HL11-01B panel is TFT LCD
|
||||
used in the Zoom2/3/3630 sdp boards.
|
||||
@@ -37,7 +38,7 @@ config PANEL_TAAL
|
||||
|
||||
config PANEL_TPO_TD043MTEA1
|
||||
tristate "TPO TD043MTEA1 LCD Panel"
|
||||
- depends on OMAP2_DSS && SPI
|
||||
+ depends on OMAP2_DSS_DPI && SPI
|
||||
help
|
||||
LCD Panel used in OMAP3 Pandora
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-75
@@ -1,75 +0,0 @@
|
||||
From 4bd1d52fff974f5a5d0582f4fa4eae6e03e36fc1 Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <steve@sakoman.com>
|
||||
Date: Tue, 19 Jan 2010 21:19:15 -0800
|
||||
Subject: [PATCH 06/32] 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 8e35a5b..827723f 100644
|
||||
--- a/drivers/video/omap2/dss/venc.c
|
||||
+++ b/drivers/video/omap2/dss/venc.c
|
||||
@@ -85,6 +85,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;
|
||||
@@ -458,6 +463,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 505ec66..eaeded5 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
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
From 6d87a3f85ac36205111b4fe71ad06976239cdbe7 Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <steve@sakoman.com>
|
||||
Date: Sat, 19 Dec 2009 06:52:43 -0800
|
||||
Subject: [PATCH 07/32] video: add timings for hd720
|
||||
|
||||
---
|
||||
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 48c3ea8..b320a30 100644
|
||||
--- a/drivers/video/modedb.c
|
||||
+++ b/drivers/video/modedb.c
|
||||
@@ -103,6 +103,10 @@ static const struct fb_videomode modedb[] = {
|
||||
{ NULL, 70, 1024, 768, 13333, 144, 24, 29, 3, 136, 6, 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 },
|
||||
+
|
||||
/* 1280x1024 @ 87 Hz interlaced, 51 kHz hsync */
|
||||
{ NULL, 87, 1280, 1024, 12500, 56, 16, 128, 1, 216, 12, 0,
|
||||
FB_VMODE_INTERLACED },
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-29
@@ -1,29 +0,0 @@
|
||||
From 1e3fcfd74686fa8b02f93bb592cca458942058e4 Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <sakoman@gmail.com>
|
||||
Date: Tue, 15 Dec 2009 15:17:44 -0800
|
||||
Subject: [PATCH 08/32] 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 4b42ecc..5c1202b 100644
|
||||
--- a/drivers/net/smsc911x.c
|
||||
+++ b/drivers/net/smsc911x.c
|
||||
@@ -2028,8 +2028,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
|
||||
|
||||
-47
@@ -1,47 +0,0 @@
|
||||
From 078005a9c8b5913ed5eb7a7a9508e4b0a5b18c30 Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <sakoman@gmail.com>
|
||||
Date: Tue, 15 Dec 2009 15:24:10 -0800
|
||||
Subject: [PATCH 09/32] 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 1de1c19..097db10 100644
|
||||
--- a/drivers/input/touchscreen/ads7846.c
|
||||
+++ b/drivers/input/touchscreen/ads7846.c
|
||||
@@ -1338,11 +1338,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;
|
||||
@@ -1366,7 +1373,7 @@ static int __devinit ads7846_probe(struct spi_device *spi)
|
||||
err_put_regulator:
|
||||
regulator_put(ts->reg);
|
||||
err_free_gpio:
|
||||
- if (!ts->get_pendown_state)
|
||||
+ 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
|
||||
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
From ae16b19238b8d0609612d0e1f1a419d293f17c80 Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <steve@sakoman.com>
|
||||
Date: Thu, 3 Mar 2011 13:29:30 -0800
|
||||
Subject: [PATCH 10/32] Revert "omap2_mcspi: Flush posted writes"
|
||||
|
||||
This reverts commit a330ce2001b290c59fe98c37e981683ef0a75fdf.
|
||||
---
|
||||
drivers/spi/omap2_mcspi.c | 1 -
|
||||
1 files changed, 0 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/drivers/spi/omap2_mcspi.c b/drivers/spi/omap2_mcspi.c
|
||||
index 6f86ba0..6094be7 100644
|
||||
--- a/drivers/spi/omap2_mcspi.c
|
||||
+++ b/drivers/spi/omap2_mcspi.c
|
||||
@@ -195,7 +195,6 @@ static inline void mcspi_write_chconf0(const struct spi_device *spi, u32 val)
|
||||
|
||||
cs->chconf0 = val;
|
||||
mcspi_write_cs_reg(spi, OMAP2_MCSPI_CHCONF0, val);
|
||||
- mcspi_read_cs_reg(spi, OMAP2_MCSPI_CHCONF0);
|
||||
}
|
||||
|
||||
static void omap2_mcspi_set_dma_req(const struct spi_device *spi,
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-482
@@ -1,482 +0,0 @@
|
||||
From 3a66cefdf60033381c623b0425345c41e8c078fe Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <steve@sakoman.com>
|
||||
Date: Fri, 19 Nov 2010 15:11:19 -0800
|
||||
Subject: [PATCH 11/32] Revert "omap_hsmmc: improve interrupt synchronisation"
|
||||
|
||||
This reverts commit b417577d3b9bbb06a4ddc9aa955af9bd503f7242.
|
||||
|
||||
Conflicts:
|
||||
|
||||
drivers/mmc/host/omap_hsmmc.c
|
||||
---
|
||||
drivers/mmc/host/omap_hsmmc.c | 267 ++++++++++++++++++++---------------------
|
||||
1 files changed, 128 insertions(+), 139 deletions(-)
|
||||
|
||||
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
|
||||
index 259ece0..15a023b 100644
|
||||
--- a/drivers/mmc/host/omap_hsmmc.c
|
||||
+++ b/drivers/mmc/host/omap_hsmmc.c
|
||||
@@ -159,10 +159,12 @@ struct omap_hsmmc_host {
|
||||
*/
|
||||
struct regulator *vcc;
|
||||
struct regulator *vcc_aux;
|
||||
+ struct semaphore sem;
|
||||
struct work_struct mmc_carddetect_work;
|
||||
void __iomem *base;
|
||||
resource_size_t mapbase;
|
||||
spinlock_t irq_lock; /* Prevent races with irq handler */
|
||||
+ unsigned long flags;
|
||||
unsigned int id;
|
||||
unsigned int dma_len;
|
||||
unsigned int dma_sg_idx;
|
||||
@@ -183,7 +185,6 @@ struct omap_hsmmc_host {
|
||||
int protect_card;
|
||||
int reqs_blocked;
|
||||
int use_reg;
|
||||
- int req_in_progress;
|
||||
|
||||
struct omap_mmc_platform_data *pdata;
|
||||
};
|
||||
@@ -556,32 +557,6 @@ static void omap_hsmmc_stop_clock(struct omap_hsmmc_host *host)
|
||||
dev_dbg(mmc_dev(host->mmc), "MMC Clock is not stoped\n");
|
||||
}
|
||||
|
||||
-static void omap_hsmmc_enable_irq(struct omap_hsmmc_host *host,
|
||||
- struct mmc_command *cmd)
|
||||
-{
|
||||
- unsigned int irq_mask;
|
||||
-
|
||||
- if (host->use_dma)
|
||||
- irq_mask = INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE);
|
||||
- else
|
||||
- irq_mask = INT_EN_MASK;
|
||||
-
|
||||
- /* Disable timeout for erases */
|
||||
- if (cmd->opcode == MMC_ERASE)
|
||||
- irq_mask &= ~DTO_ENABLE;
|
||||
-
|
||||
- OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
|
||||
- OMAP_HSMMC_WRITE(host->base, ISE, irq_mask);
|
||||
- OMAP_HSMMC_WRITE(host->base, IE, irq_mask);
|
||||
-}
|
||||
-
|
||||
-static void omap_hsmmc_disable_irq(struct omap_hsmmc_host *host)
|
||||
-{
|
||||
- OMAP_HSMMC_WRITE(host->base, ISE, 0);
|
||||
- OMAP_HSMMC_WRITE(host->base, IE, 0);
|
||||
- OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
|
||||
-}
|
||||
-
|
||||
#ifdef CONFIG_PM
|
||||
|
||||
/*
|
||||
@@ -650,7 +625,9 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
|
||||
&& time_before(jiffies, timeout))
|
||||
;
|
||||
|
||||
- omap_hsmmc_disable_irq(host);
|
||||
+ OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
|
||||
+ OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
|
||||
+ OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
|
||||
|
||||
/* Do not initialize card-specific things if the power is off */
|
||||
if (host->power_mode == MMC_POWER_OFF)
|
||||
@@ -753,8 +730,6 @@ static void send_init_stream(struct omap_hsmmc_host *host)
|
||||
return;
|
||||
|
||||
disable_irq(host->irq);
|
||||
-
|
||||
- OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
|
||||
OMAP_HSMMC_WRITE(host->base, CON,
|
||||
OMAP_HSMMC_READ(host->base, CON) | INIT_STREAM);
|
||||
OMAP_HSMMC_WRITE(host->base, CMD, INIT_STREAM_CMD);
|
||||
@@ -820,7 +795,17 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
|
||||
mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
|
||||
host->cmd = cmd;
|
||||
|
||||
- omap_hsmmc_enable_irq(host, cmd);
|
||||
+ /*
|
||||
+ * Clear status bits and enable interrupts
|
||||
+ */
|
||||
+ OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
|
||||
+ OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
|
||||
+
|
||||
+ if (host->use_dma)
|
||||
+ OMAP_HSMMC_WRITE(host->base, IE,
|
||||
+ INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE));
|
||||
+ else
|
||||
+ OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
|
||||
|
||||
host->response_busy = 0;
|
||||
if (cmd->flags & MMC_RSP_PRESENT) {
|
||||
@@ -854,7 +839,13 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
|
||||
if (host->use_dma)
|
||||
cmdreg |= DMA_EN;
|
||||
|
||||
- host->req_in_progress = 1;
|
||||
+ /*
|
||||
+ * In an interrupt context (i.e. STOP command), the spinlock is unlocked
|
||||
+ * by the interrupt handler, otherwise (i.e. for a new request) it is
|
||||
+ * unlocked here.
|
||||
+ */
|
||||
+ if (!in_interrupt())
|
||||
+ spin_unlock_irqrestore(&host->irq_lock, host->flags);
|
||||
|
||||
OMAP_HSMMC_WRITE(host->base, ARG, cmd->arg);
|
||||
OMAP_HSMMC_WRITE(host->base, CMD, cmdreg);
|
||||
@@ -869,23 +860,6 @@ omap_hsmmc_get_dma_dir(struct omap_hsmmc_host *host, struct mmc_data *data)
|
||||
return DMA_FROM_DEVICE;
|
||||
}
|
||||
|
||||
-static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_request *mrq)
|
||||
-{
|
||||
- int dma_ch;
|
||||
-
|
||||
- spin_lock(&host->irq_lock);
|
||||
- host->req_in_progress = 0;
|
||||
- dma_ch = host->dma_ch;
|
||||
- spin_unlock(&host->irq_lock);
|
||||
-
|
||||
- omap_hsmmc_disable_irq(host);
|
||||
- /* Do not complete the request if DMA is still in progress */
|
||||
- if (mrq->data && host->use_dma && dma_ch != -1)
|
||||
- return;
|
||||
- host->mrq = NULL;
|
||||
- mmc_request_done(host->mmc, mrq);
|
||||
-}
|
||||
-
|
||||
/*
|
||||
* Notify the transfer complete to MMC core
|
||||
*/
|
||||
@@ -902,19 +876,25 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data)
|
||||
return;
|
||||
}
|
||||
|
||||
- omap_hsmmc_request_done(host, mrq);
|
||||
+ host->mrq = NULL;
|
||||
+ mmc_request_done(host->mmc, mrq);
|
||||
return;
|
||||
}
|
||||
|
||||
host->data = NULL;
|
||||
|
||||
+ if (host->use_dma && host->dma_ch != -1)
|
||||
+ dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
|
||||
+ omap_hsmmc_get_dma_dir(host, data));
|
||||
+
|
||||
if (!data->error)
|
||||
data->bytes_xfered += data->blocks * (data->blksz);
|
||||
else
|
||||
data->bytes_xfered = 0;
|
||||
|
||||
if (!data->stop) {
|
||||
- omap_hsmmc_request_done(host, data->mrq);
|
||||
+ host->mrq = NULL;
|
||||
+ mmc_request_done(host->mmc, data->mrq);
|
||||
return;
|
||||
}
|
||||
omap_hsmmc_start_command(host, data->stop, NULL);
|
||||
@@ -940,8 +920,10 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd)
|
||||
cmd->resp[0] = OMAP_HSMMC_READ(host->base, RSP10);
|
||||
}
|
||||
}
|
||||
- if ((host->data == NULL && !host->response_busy) || cmd->error)
|
||||
- omap_hsmmc_request_done(host, cmd->mrq);
|
||||
+ if ((host->data == NULL && !host->response_busy) || cmd->error) {
|
||||
+ host->mrq = NULL;
|
||||
+ mmc_request_done(host->mmc, cmd->mrq);
|
||||
+ }
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -949,19 +931,14 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd)
|
||||
*/
|
||||
static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno)
|
||||
{
|
||||
- int dma_ch;
|
||||
-
|
||||
host->data->error = errno;
|
||||
|
||||
- spin_lock(&host->irq_lock);
|
||||
- dma_ch = host->dma_ch;
|
||||
- host->dma_ch = -1;
|
||||
- spin_unlock(&host->irq_lock);
|
||||
-
|
||||
- if (host->use_dma && dma_ch != -1) {
|
||||
+ if (host->use_dma && host->dma_ch != -1) {
|
||||
dma_unmap_sg(mmc_dev(host->mmc), host->data->sg, host->dma_len,
|
||||
omap_hsmmc_get_dma_dir(host, host->data));
|
||||
- omap_free_dma(dma_ch);
|
||||
+ omap_free_dma(host->dma_ch);
|
||||
+ host->dma_ch = -1;
|
||||
+ up(&host->sem);
|
||||
}
|
||||
host->data = NULL;
|
||||
}
|
||||
@@ -1034,21 +1011,28 @@ static inline void omap_hsmmc_reset_controller_fsm(struct omap_hsmmc_host *host,
|
||||
__func__);
|
||||
}
|
||||
|
||||
-static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
|
||||
+/*
|
||||
+ * MMC controller IRQ handler
|
||||
+ */
|
||||
+static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
|
||||
{
|
||||
+ struct omap_hsmmc_host *host = dev_id;
|
||||
struct mmc_data *data;
|
||||
- int end_cmd = 0, end_trans = 0;
|
||||
-
|
||||
- if (!host->req_in_progress) {
|
||||
- do {
|
||||
- OMAP_HSMMC_WRITE(host->base, STAT, status);
|
||||
- /* Flush posted write */
|
||||
- status = OMAP_HSMMC_READ(host->base, STAT);
|
||||
- } while (status & INT_EN_MASK);
|
||||
- return;
|
||||
+ int end_cmd = 0, end_trans = 0, status;
|
||||
+
|
||||
+ spin_lock(&host->irq_lock);
|
||||
+
|
||||
+ if (host->mrq == NULL) {
|
||||
+ OMAP_HSMMC_WRITE(host->base, STAT,
|
||||
+ OMAP_HSMMC_READ(host->base, STAT));
|
||||
+ /* Flush posted write */
|
||||
+ OMAP_HSMMC_READ(host->base, STAT);
|
||||
+ spin_unlock(&host->irq_lock);
|
||||
+ return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
data = host->data;
|
||||
+ status = OMAP_HSMMC_READ(host->base, STAT);
|
||||
dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
|
||||
|
||||
if (status & ERR) {
|
||||
@@ -1101,27 +1085,15 @@ static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status)
|
||||
}
|
||||
|
||||
OMAP_HSMMC_WRITE(host->base, STAT, status);
|
||||
+ /* Flush posted write */
|
||||
+ OMAP_HSMMC_READ(host->base, STAT);
|
||||
|
||||
if (end_cmd || ((status & CC) && host->cmd))
|
||||
omap_hsmmc_cmd_done(host, host->cmd);
|
||||
if ((end_trans || (status & TC)) && host->mrq)
|
||||
omap_hsmmc_xfer_done(host, data);
|
||||
-}
|
||||
-
|
||||
-/*
|
||||
- * MMC controller IRQ handler
|
||||
- */
|
||||
-static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
|
||||
-{
|
||||
- struct omap_hsmmc_host *host = dev_id;
|
||||
- int status;
|
||||
|
||||
- status = OMAP_HSMMC_READ(host->base, STAT);
|
||||
- do {
|
||||
- omap_hsmmc_do_irq(host, status);
|
||||
- /* Flush posted write */
|
||||
- status = OMAP_HSMMC_READ(host->base, STAT);
|
||||
- } while (status & INT_EN_MASK);
|
||||
+ spin_unlock(&host->irq_lock);
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
@@ -1316,11 +1288,9 @@ static void omap_hsmmc_config_dma_params(struct omap_hsmmc_host *host,
|
||||
/*
|
||||
* DMA call back function
|
||||
*/
|
||||
-static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
|
||||
+static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *data)
|
||||
{
|
||||
- struct omap_hsmmc_host *host = cb_data;
|
||||
- struct mmc_data *data = host->mrq->data;
|
||||
- int dma_ch, req_in_progress;
|
||||
+ struct omap_hsmmc_host *host = data;
|
||||
|
||||
if (!(ch_status & OMAP_DMA_BLOCK_IRQ)) {
|
||||
dev_warn(mmc_dev(host->mmc), "unexpected dma status %x\n",
|
||||
@@ -1328,38 +1298,24 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
|
||||
return;
|
||||
}
|
||||
|
||||
- spin_lock(&host->irq_lock);
|
||||
- if (host->dma_ch < 0) {
|
||||
- spin_unlock(&host->irq_lock);
|
||||
+ if (host->dma_ch < 0)
|
||||
return;
|
||||
- }
|
||||
|
||||
host->dma_sg_idx++;
|
||||
if (host->dma_sg_idx < host->dma_len) {
|
||||
/* Fire up the next transfer. */
|
||||
- omap_hsmmc_config_dma_params(host, data,
|
||||
- data->sg + host->dma_sg_idx);
|
||||
- spin_unlock(&host->irq_lock);
|
||||
+ omap_hsmmc_config_dma_params(host, host->data,
|
||||
+ host->data->sg + host->dma_sg_idx);
|
||||
return;
|
||||
}
|
||||
|
||||
- dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_len,
|
||||
- omap_hsmmc_get_dma_dir(host, data));
|
||||
-
|
||||
- req_in_progress = host->req_in_progress;
|
||||
- dma_ch = host->dma_ch;
|
||||
+ omap_free_dma(host->dma_ch);
|
||||
host->dma_ch = -1;
|
||||
- spin_unlock(&host->irq_lock);
|
||||
-
|
||||
- omap_free_dma(dma_ch);
|
||||
-
|
||||
- /* If DMA has finished after TC, complete the request */
|
||||
- if (!req_in_progress) {
|
||||
- struct mmc_request *mrq = host->mrq;
|
||||
-
|
||||
- host->mrq = NULL;
|
||||
- mmc_request_done(host->mmc, mrq);
|
||||
- }
|
||||
+ /*
|
||||
+ * DMA Callback: run in interrupt context.
|
||||
+ * mutex_unlock will throw a kernel warning if used.
|
||||
+ */
|
||||
+ up(&host->sem);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1368,7 +1324,7 @@ static void omap_hsmmc_dma_cb(int lch, u16 ch_status, void *cb_data)
|
||||
static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host,
|
||||
struct mmc_request *req)
|
||||
{
|
||||
- int dma_ch = 0, ret = 0, i;
|
||||
+ int dma_ch = 0, ret = 0, err = 1, i;
|
||||
struct mmc_data *data = req->data;
|
||||
|
||||
/* Sanity check: all the SG entries must be aligned by block size. */
|
||||
@@ -1385,7 +1341,23 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host,
|
||||
*/
|
||||
return -EINVAL;
|
||||
|
||||
- BUG_ON(host->dma_ch != -1);
|
||||
+ /*
|
||||
+ * If for some reason the DMA transfer is still active,
|
||||
+ * we wait for timeout period and free the dma
|
||||
+ */
|
||||
+ if (host->dma_ch != -1) {
|
||||
+ set_current_state(TASK_UNINTERRUPTIBLE);
|
||||
+ schedule_timeout(100);
|
||||
+ if (down_trylock(&host->sem)) {
|
||||
+ omap_free_dma(host->dma_ch);
|
||||
+ host->dma_ch = -1;
|
||||
+ up(&host->sem);
|
||||
+ return err;
|
||||
+ }
|
||||
+ } else {
|
||||
+ if (down_trylock(&host->sem))
|
||||
+ return err;
|
||||
+ }
|
||||
|
||||
ret = omap_request_dma(omap_hsmmc_get_dma_sync_dev(host, data),
|
||||
"MMC/SD", omap_hsmmc_dma_cb, host, &dma_ch);
|
||||
@@ -1485,27 +1457,37 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
|
||||
struct omap_hsmmc_host *host = mmc_priv(mmc);
|
||||
int err;
|
||||
|
||||
- BUG_ON(host->req_in_progress);
|
||||
- BUG_ON(host->dma_ch != -1);
|
||||
- if (host->protect_card) {
|
||||
- if (host->reqs_blocked < 3) {
|
||||
- /*
|
||||
- * Ensure the controller is left in a consistent
|
||||
- * state by resetting the command and data state
|
||||
- * machines.
|
||||
- */
|
||||
- omap_hsmmc_reset_controller_fsm(host, SRD);
|
||||
- omap_hsmmc_reset_controller_fsm(host, SRC);
|
||||
- host->reqs_blocked += 1;
|
||||
- }
|
||||
- req->cmd->error = -EBADF;
|
||||
- if (req->data)
|
||||
- req->data->error = -EBADF;
|
||||
- req->cmd->retries = 0;
|
||||
- mmc_request_done(mmc, req);
|
||||
- return;
|
||||
- } else if (host->reqs_blocked)
|
||||
- host->reqs_blocked = 0;
|
||||
+ /*
|
||||
+ * Prevent races with the interrupt handler because of unexpected
|
||||
+ * interrupts, but not if we are already in interrupt context i.e.
|
||||
+ * retries.
|
||||
+ */
|
||||
+ if (!in_interrupt()) {
|
||||
+ spin_lock_irqsave(&host->irq_lock, host->flags);
|
||||
+ /*
|
||||
+ * Protect the card from I/O if there is a possibility
|
||||
+ * it can be removed.
|
||||
+ */
|
||||
+ if (host->protect_card) {
|
||||
+ if (host->reqs_blocked < 3) {
|
||||
+ /*
|
||||
+ * Ensure the controller is left in a consistent
|
||||
+ * state by resetting the command and data state
|
||||
+ * machines.
|
||||
+ */
|
||||
+ omap_hsmmc_reset_controller_fsm(host, SRD);
|
||||
+ omap_hsmmc_reset_controller_fsm(host, SRC);
|
||||
+ host->reqs_blocked += 1;
|
||||
+ }
|
||||
+ req->cmd->error = -EBADF;
|
||||
+ if (req->data)
|
||||
+ req->data->error = -EBADF;
|
||||
+ spin_unlock_irqrestore(&host->irq_lock, host->flags);
|
||||
+ mmc_request_done(mmc, req);
|
||||
+ return;
|
||||
+ } else if (host->reqs_blocked)
|
||||
+ host->reqs_blocked = 0;
|
||||
+ }
|
||||
WARN_ON(host->mrq != NULL);
|
||||
host->mrq = req;
|
||||
err = omap_hsmmc_prepare_data(host, req);
|
||||
@@ -1514,6 +1496,8 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req)
|
||||
if (req->data)
|
||||
req->data->error = err;
|
||||
host->mrq = NULL;
|
||||
+ if (!in_interrupt())
|
||||
+ spin_unlock_irqrestore(&host->irq_lock, host->flags);
|
||||
mmc_request_done(mmc, req);
|
||||
return;
|
||||
}
|
||||
@@ -2093,6 +2077,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
|
||||
mmc->f_min = 400000;
|
||||
mmc->f_max = 52000000;
|
||||
|
||||
+ sema_init(&host->sem, 1);
|
||||
spin_lock_init(&host->irq_lock);
|
||||
|
||||
host->iclk = clk_get(&pdev->dev, "ick");
|
||||
@@ -2235,7 +2220,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
|
||||
pdata->resume = omap_hsmmc_resume_cdirq;
|
||||
}
|
||||
|
||||
- omap_hsmmc_disable_irq(host);
|
||||
+ OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
|
||||
+ OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
|
||||
|
||||
mmc_host_lazy_disable(host->mmc);
|
||||
|
||||
@@ -2356,7 +2342,10 @@ static int omap_hsmmc_suspend(struct device *dev)
|
||||
ret = mmc_suspend_host(host->mmc);
|
||||
mmc_host_enable(host->mmc);
|
||||
if (ret == 0) {
|
||||
- omap_hsmmc_disable_irq(host);
|
||||
+ OMAP_HSMMC_WRITE(host->base, ISE, 0);
|
||||
+ OMAP_HSMMC_WRITE(host->base, IE, 0);
|
||||
+
|
||||
+
|
||||
OMAP_HSMMC_WRITE(host->base, HCTL,
|
||||
OMAP_HSMMC_READ(host->base, HCTL) & ~SDBP);
|
||||
mmc_host_disable(host->mmc);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-51
@@ -1,51 +0,0 @@
|
||||
From 75d9413d575f724e1f7c006fdef374fb1c200346 Mon Sep 17 00:00:00 2001
|
||||
From: David Vrabel <david.vrabel@csr.com>
|
||||
Date: Fri, 2 Apr 2010 08:41:47 -0700
|
||||
Subject: [PATCH 12/32] Don't turn SDIO cards off to save power. Doing so will lose all internal state in the card.
|
||||
|
||||
Signed-off-by: David Vrabel <david.vrabel@csr.com>
|
||||
---
|
||||
drivers/mmc/host/omap_hsmmc.c | 12 ++++++++----
|
||||
1 files changed, 8 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
|
||||
index 15a023b..83f93ab 100644
|
||||
--- a/drivers/mmc/host/omap_hsmmc.c
|
||||
+++ b/drivers/mmc/host/omap_hsmmc.c
|
||||
@@ -29,6 +29,7 @@
|
||||
#include <linux/mmc/host.h>
|
||||
#include <linux/mmc/core.h>
|
||||
#include <linux/mmc/mmc.h>
|
||||
+#include <linux/mmc/card.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/semaphore.h>
|
||||
#include <linux/gpio.h>
|
||||
@@ -1760,8 +1761,12 @@ static int omap_hsmmc_sleep_to_off(struct omap_hsmmc_host *host)
|
||||
mmc_slot(host).card_detect ||
|
||||
(mmc_slot(host).get_cover_state &&
|
||||
mmc_slot(host).get_cover_state(host->dev, host->slot_id)))) {
|
||||
- mmc_release_host(host->mmc);
|
||||
- return 0;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /* Don't turn SDIO cards off. */
|
||||
+ if (host->mmc->card && mmc_card_sdio(host->mmc->card)) {
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
mmc_slot(host).set_power(host->dev, host->slot_id, 0, 0);
|
||||
@@ -1772,9 +1777,8 @@ static int omap_hsmmc_sleep_to_off(struct omap_hsmmc_host *host)
|
||||
host->dpm_state == CARDSLEEP ? "CARDSLEEP" : "REGSLEEP");
|
||||
|
||||
host->dpm_state = OFF;
|
||||
-
|
||||
+out:
|
||||
mmc_release_host(host->mmc);
|
||||
-
|
||||
return 0;
|
||||
}
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-288
@@ -1,288 +0,0 @@
|
||||
From 948eeb1f03da5fca0f6734c10efbc35ad63a1d08 Mon Sep 17 00:00:00 2001
|
||||
From: David Vrabel <david.vrabel@csr.com>
|
||||
Date: Fri, 2 Apr 2010 08:42:22 -0700
|
||||
Subject: [PATCH 13/32] Enable the use of SDIO card interrupts.
|
||||
|
||||
FCLK must be enabled while SDIO interrupts are enabled or the MMC
|
||||
module won't wake-up (even though ENAWAKEUP in SYSCONFIG and IWE in
|
||||
HTCL have been set). Enabling the MMC module to wake-up would require
|
||||
configuring the MMC module (and the mmci_dat[1] GPIO when the CORE
|
||||
power domain is OFF) as wake-up sources in the PRCM.
|
||||
|
||||
The writes to STAT and ISE when starting a command are unnecessary and
|
||||
have been removed.
|
||||
|
||||
Signed-off-by: David Vrabel <david.vrabel@csr.com>
|
||||
---
|
||||
drivers/mmc/host/omap_hsmmc.c | 118 +++++++++++++++++++++++++++++------------
|
||||
1 files changed, 83 insertions(+), 35 deletions(-)
|
||||
|
||||
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
|
||||
index 83f93ab..d57686c 100644
|
||||
--- a/drivers/mmc/host/omap_hsmmc.c
|
||||
+++ b/drivers/mmc/host/omap_hsmmc.c
|
||||
@@ -67,6 +67,7 @@
|
||||
#define SDVS_MASK 0x00000E00
|
||||
#define SDVSCLR 0xFFFFF1FF
|
||||
#define SDVSDET 0x00000400
|
||||
+#define ENAWAKEUP (1 << 2)
|
||||
#define AUTOIDLE 0x1
|
||||
#define SDBP (1 << 8)
|
||||
#define DTO 0xe
|
||||
@@ -77,10 +78,13 @@
|
||||
#define CLKD_SHIFT 6
|
||||
#define DTO_MASK 0x000F0000
|
||||
#define DTO_SHIFT 16
|
||||
+#define CIRQ_ENABLE (1 << 8)
|
||||
#define INT_EN_MASK 0x307F0033
|
||||
#define BWR_ENABLE (1 << 4)
|
||||
#define BRR_ENABLE (1 << 5)
|
||||
#define DTO_ENABLE (1 << 20)
|
||||
+#define CTPL (1 << 11)
|
||||
+#define CLKEXTFREE (1 << 16)
|
||||
#define INIT_STREAM (1 << 1)
|
||||
#define DP_SELECT (1 << 21)
|
||||
#define DDIR (1 << 4)
|
||||
@@ -88,10 +92,12 @@
|
||||
#define MSBS (1 << 5)
|
||||
#define BCE (1 << 1)
|
||||
#define FOUR_BIT (1 << 1)
|
||||
+#define IWE (1 << 24)
|
||||
#define DW8 (1 << 5)
|
||||
#define CC 0x1
|
||||
#define TC 0x02
|
||||
#define OD 0x1
|
||||
+#define CIRQ (1 << 8)
|
||||
#define ERR (1 << 15)
|
||||
#define CMD_TIMEOUT (1 << 16)
|
||||
#define DATA_TIMEOUT (1 << 20)
|
||||
@@ -186,6 +192,7 @@ struct omap_hsmmc_host {
|
||||
int protect_card;
|
||||
int reqs_blocked;
|
||||
int use_reg;
|
||||
+ int sdio_int;
|
||||
|
||||
struct omap_mmc_platform_data *pdata;
|
||||
};
|
||||
@@ -598,7 +605,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
|
||||
;
|
||||
|
||||
OMAP_HSMMC_WRITE(host->base, SYSCONFIG,
|
||||
- OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE);
|
||||
+ OMAP_HSMMC_READ(host->base, SYSCONFIG) | AUTOIDLE | ENAWAKEUP);
|
||||
|
||||
if (host->id == OMAP_MMC1_DEVID) {
|
||||
if (host->power_mode != MMC_POWER_OFF &&
|
||||
@@ -613,7 +620,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
|
||||
}
|
||||
|
||||
OMAP_HSMMC_WRITE(host->base, HCTL,
|
||||
- OMAP_HSMMC_READ(host->base, HCTL) | hctl);
|
||||
+ OMAP_HSMMC_READ(host->base, HCTL) | hctl | IWE);
|
||||
|
||||
OMAP_HSMMC_WRITE(host->base, CAPA,
|
||||
OMAP_HSMMC_READ(host->base, CAPA) | capa);
|
||||
@@ -627,7 +634,7 @@ static int omap_hsmmc_context_restore(struct omap_hsmmc_host *host)
|
||||
;
|
||||
|
||||
OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
|
||||
- OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
|
||||
+ OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK | CIRQ);
|
||||
OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
|
||||
|
||||
/* Do not initialize card-specific things if the power is off */
|
||||
@@ -791,22 +798,19 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd,
|
||||
struct mmc_data *data)
|
||||
{
|
||||
int cmdreg = 0, resptype = 0, cmdtype = 0;
|
||||
+ int int_en_mask = INT_EN_MASK;
|
||||
|
||||
dev_dbg(mmc_dev(host->mmc), "%s: CMD%d, argument 0x%08x\n",
|
||||
mmc_hostname(host->mmc), cmd->opcode, cmd->arg);
|
||||
host->cmd = cmd;
|
||||
|
||||
- /*
|
||||
- * Clear status bits and enable interrupts
|
||||
- */
|
||||
- OMAP_HSMMC_WRITE(host->base, STAT, STAT_CLEAR);
|
||||
- OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
|
||||
-
|
||||
if (host->use_dma)
|
||||
- OMAP_HSMMC_WRITE(host->base, IE,
|
||||
- INT_EN_MASK & ~(BRR_ENABLE | BWR_ENABLE));
|
||||
- else
|
||||
- OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
|
||||
+ int_en_mask &= ~(BRR_ENABLE | BWR_ENABLE);
|
||||
+
|
||||
+ if (host->sdio_int)
|
||||
+ int_en_mask |= CIRQ;
|
||||
+
|
||||
+ OMAP_HSMMC_WRITE(host->base, IE, int_en_mask);
|
||||
|
||||
host->response_busy = 0;
|
||||
if (cmd->flags & MMC_RSP_PRESENT) {
|
||||
@@ -1019,23 +1023,26 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
|
||||
{
|
||||
struct omap_hsmmc_host *host = dev_id;
|
||||
struct mmc_data *data;
|
||||
- int end_cmd = 0, end_trans = 0, status;
|
||||
+ u32 status;
|
||||
+ int end_cmd = 0, end_trans = 0;
|
||||
+ bool card_irq = false;
|
||||
|
||||
spin_lock(&host->irq_lock);
|
||||
|
||||
- if (host->mrq == NULL) {
|
||||
- OMAP_HSMMC_WRITE(host->base, STAT,
|
||||
- OMAP_HSMMC_READ(host->base, STAT));
|
||||
- /* Flush posted write */
|
||||
- OMAP_HSMMC_READ(host->base, STAT);
|
||||
- spin_unlock(&host->irq_lock);
|
||||
- return IRQ_HANDLED;
|
||||
- }
|
||||
-
|
||||
- data = host->data;
|
||||
status = OMAP_HSMMC_READ(host->base, STAT);
|
||||
+ OMAP_HSMMC_WRITE(host->base, STAT, status);
|
||||
+ OMAP_HSMMC_READ(host->base, STAT); /* Flush posted write. */
|
||||
+
|
||||
dev_dbg(mmc_dev(host->mmc), "IRQ Status is %x\n", status);
|
||||
|
||||
+ if (status & CIRQ)
|
||||
+ card_irq = true;
|
||||
+
|
||||
+ if (host->mrq == NULL)
|
||||
+ goto out;
|
||||
+
|
||||
+ data = host->data;
|
||||
+
|
||||
if (status & ERR) {
|
||||
#ifdef CONFIG_MMC_DEBUG
|
||||
omap_hsmmc_report_irq(host, status);
|
||||
@@ -1085,17 +1092,16 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id)
|
||||
}
|
||||
}
|
||||
|
||||
- OMAP_HSMMC_WRITE(host->base, STAT, status);
|
||||
- /* Flush posted write */
|
||||
- OMAP_HSMMC_READ(host->base, STAT);
|
||||
-
|
||||
if (end_cmd || ((status & CC) && host->cmd))
|
||||
omap_hsmmc_cmd_done(host, host->cmd);
|
||||
if ((end_trans || (status & TC)) && host->mrq)
|
||||
omap_hsmmc_xfer_done(host, data);
|
||||
-
|
||||
+out:
|
||||
spin_unlock(&host->irq_lock);
|
||||
|
||||
+ if (card_irq)
|
||||
+ mmc_signal_sdio_irq(host->mmc);
|
||||
+
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -1643,6 +1649,47 @@ static void omap_hsmmc_init_card(struct mmc_host *mmc, struct mmc_card *card)
|
||||
mmc_slot(host).init_card(card);
|
||||
}
|
||||
|
||||
+static void omap_hsmmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
|
||||
+{
|
||||
+ struct omap_hsmmc_host *host = mmc_priv(mmc);
|
||||
+ u32 ie, con;
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ spin_lock_irqsave(&host->irq_lock, flags);
|
||||
+
|
||||
+ /*
|
||||
+ * When interrupts are enabled, CTPL must be set to enable
|
||||
+ * DAT1 input buffer (or the card interrupt is always
|
||||
+ * asserted) and FCLK must be enabled as wake-up does not
|
||||
+ * work. Take care to disable FCLK after all the register
|
||||
+ * accesses as they might not complete if FCLK is off.
|
||||
+ *
|
||||
+ * FIXME: if the MMC module (and the mmci_dat[1] GPIO when the
|
||||
+ * CORE power domain is OFF) are configured as a wake-up
|
||||
+ * sources in the PRCM, then FCLK could be switched off. This
|
||||
+ * might add too much latency.
|
||||
+ */
|
||||
+ con = OMAP_HSMMC_READ(host->base, CON);
|
||||
+ ie = OMAP_HSMMC_READ(host->base, IE);
|
||||
+ if (enable) {
|
||||
+ clk_enable(host->fclk);
|
||||
+ ie |= CIRQ_ENABLE;
|
||||
+ con |= CTPL | CLKEXTFREE;
|
||||
+ host->sdio_int = 1;
|
||||
+ } else {
|
||||
+ ie &= ~CIRQ_ENABLE;
|
||||
+ con &= ~(CTPL | CLKEXTFREE);
|
||||
+ host->sdio_int = 0;
|
||||
+ }
|
||||
+ OMAP_HSMMC_WRITE(host->base, CON, con);
|
||||
+ OMAP_HSMMC_WRITE(host->base, IE, ie);
|
||||
+ OMAP_HSMMC_READ(host->base, IE); /* flush posted write */
|
||||
+ if (!enable)
|
||||
+ clk_disable(host->fclk);
|
||||
+
|
||||
+ spin_unlock_irqrestore(&host->irq_lock, flags);
|
||||
+}
|
||||
+
|
||||
static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
|
||||
{
|
||||
u32 hctl, capa, value;
|
||||
@@ -1657,14 +1704,14 @@ static void omap_hsmmc_conf_bus_power(struct omap_hsmmc_host *host)
|
||||
}
|
||||
|
||||
value = OMAP_HSMMC_READ(host->base, HCTL) & ~SDVS_MASK;
|
||||
- OMAP_HSMMC_WRITE(host->base, HCTL, value | hctl);
|
||||
+ OMAP_HSMMC_WRITE(host->base, HCTL, value | hctl | IWE);
|
||||
|
||||
value = OMAP_HSMMC_READ(host->base, CAPA);
|
||||
OMAP_HSMMC_WRITE(host->base, CAPA, value | capa);
|
||||
|
||||
/* Set the controller to AUTO IDLE mode */
|
||||
value = OMAP_HSMMC_READ(host->base, SYSCONFIG);
|
||||
- OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE);
|
||||
+ OMAP_HSMMC_WRITE(host->base, SYSCONFIG, value | AUTOIDLE | ENAWAKEUP);
|
||||
|
||||
/* Set SD bus power bit */
|
||||
set_sd_bus_power(host);
|
||||
@@ -1918,7 +1965,7 @@ static const struct mmc_host_ops omap_hsmmc_ops = {
|
||||
.get_cd = omap_hsmmc_get_cd,
|
||||
.get_ro = omap_hsmmc_get_ro,
|
||||
.init_card = omap_hsmmc_init_card,
|
||||
- /* NYET -- enable_sdio_irq */
|
||||
+ .enable_sdio_irq = omap_hsmmc_enable_sdio_irq,
|
||||
};
|
||||
|
||||
static const struct mmc_host_ops omap_hsmmc_ps_ops = {
|
||||
@@ -1929,7 +1976,7 @@ static const struct mmc_host_ops omap_hsmmc_ps_ops = {
|
||||
.get_cd = omap_hsmmc_get_cd,
|
||||
.get_ro = omap_hsmmc_get_ro,
|
||||
.init_card = omap_hsmmc_init_card,
|
||||
- /* NYET -- enable_sdio_irq */
|
||||
+ .enable_sdio_irq = omap_hsmmc_enable_sdio_irq,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_DEBUG_FS
|
||||
@@ -2145,7 +2192,8 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
|
||||
mmc->max_seg_size = mmc->max_req_size;
|
||||
|
||||
mmc->caps |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
|
||||
- MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE;
|
||||
+ MMC_CAP_WAIT_WHILE_BUSY | MMC_CAP_ERASE |
|
||||
+ MMC_CAP_SDIO_IRQ;
|
||||
|
||||
mmc->caps |= mmc_slot(host).caps;
|
||||
if (mmc->caps & MMC_CAP_8_BIT_DATA)
|
||||
@@ -2224,7 +2272,7 @@ static int __init omap_hsmmc_probe(struct platform_device *pdev)
|
||||
pdata->resume = omap_hsmmc_resume_cdirq;
|
||||
}
|
||||
|
||||
- OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK);
|
||||
+ OMAP_HSMMC_WRITE(host->base, ISE, INT_EN_MASK | CIRQ);
|
||||
OMAP_HSMMC_WRITE(host->base, IE, INT_EN_MASK);
|
||||
|
||||
mmc_host_lazy_disable(host->mmc);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-27
@@ -1,27 +0,0 @@
|
||||
From f646d3df7a7160fd80f20416c4a0fce55946f527 Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <steve@sakoman.com>
|
||||
Date: Thu, 17 Dec 2009 12:45:20 -0800
|
||||
Subject: [PATCH 14/32] soc: codecs: 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 575238d..bd51f72 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
|
||||
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
From 00adf70cb5f8706ac5e7b1ec6f5a94f7e490b606 Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <steve@sakoman.com>
|
||||
Date: Wed, 29 Dec 2010 11:39:16 -0800
|
||||
Subject: [PATCH 15/32] soc: codecs: twl4030: Turn on mic bias by default
|
||||
|
||||
---
|
||||
sound/soc/codecs/twl4030.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
|
||||
index bd51f72..8949773 100644
|
||||
--- a/sound/soc/codecs/twl4030.c
|
||||
+++ b/sound/soc/codecs/twl4030.c
|
||||
@@ -55,7 +55,7 @@ static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
|
||||
0x00, /* REG_CODEC_MODE (0x1) */
|
||||
0x00, /* REG_OPTION (0x2) */
|
||||
0x00, /* REG_UNKNOWN (0x3) */
|
||||
- 0x00, /* REG_MICBIAS_CTL (0x4) */
|
||||
+ 0x03, /* REG_MICBIAS_CTL (0x4) */
|
||||
0x34, /* REG_ANAMICL (0x5) */
|
||||
0x14, /* REG_ANAMICR (0x6) */
|
||||
0x00, /* REG_AVADC_CTL (0x7) */
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-55
@@ -1,55 +0,0 @@
|
||||
From 6f432e1e39f276a41d600d1cc9cd17fc088877d8 Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <steve@sakoman.com>
|
||||
Date: Thu, 4 Feb 2010 12:26:22 -0800
|
||||
Subject: [PATCH 16/32] 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 f9a2799..713b8ea 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)
|
||||
@@ -495,6 +512,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
|
||||
|
||||
-39
@@ -1,39 +0,0 @@
|
||||
From 56dc96df8ff5e3db6afde96d64d74200f85e59c2 Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <steve@sakoman.com>
|
||||
Date: Sun, 24 Jan 2010 09:33:56 -0800
|
||||
Subject: [PATCH 17/32] 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 b2f30be..84d5ef6 100644
|
||||
--- a/arch/arm/mach-omap2/hsmmc.c
|
||||
+++ b/arch/arm/mach-omap2/hsmmc.c
|
||||
@@ -185,15 +185,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
|
||||
|
||||
-103
@@ -1,103 +0,0 @@
|
||||
From 8c257a6e7460ceb8c899980f7dad701ceb619adc Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Bernhard=20W=C3=B6rndl-Aichriedler?= <bwa@xdevelop.at>
|
||||
Date: Sat, 15 May 2010 16:34:05 +0200
|
||||
Subject: [PATCH 18/32] Add power-off support for the TWL4030 companion
|
||||
|
||||
This patch adds support for the power-off on shutdown feature of the TWL4030
|
||||
---
|
||||
drivers/mfd/Kconfig | 6 ++++++
|
||||
drivers/mfd/twl-core.c | 40 ++++++++++++++++++++++++++++++++++++++++
|
||||
2 files changed, 46 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
|
||||
index 3ed3ff0..fe2370a 100644
|
||||
--- a/drivers/mfd/Kconfig
|
||||
+++ b/drivers/mfd/Kconfig
|
||||
@@ -210,6 +210,12 @@ config TWL4030_CODEC
|
||||
select MFD_CORE
|
||||
default n
|
||||
|
||||
+config TWL4030_POWEROFF
|
||||
+ bool "TWL4030 Allow power-off on shutdown"
|
||||
+ depends on TWL4030_CORE
|
||||
+ help
|
||||
+ Enables the CPU to power-off the system on shutdown
|
||||
+
|
||||
config TWL6030_PWM
|
||||
tristate "TWL6030 PWM (Pulse Width Modulator) Support"
|
||||
depends on TWL4030_CORE
|
||||
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
|
||||
index 960b5be..8804550 100644
|
||||
--- a/drivers/mfd/twl-core.c
|
||||
+++ b/drivers/mfd/twl-core.c
|
||||
@@ -122,6 +122,12 @@
|
||||
#define twl_has_bci() false
|
||||
#endif
|
||||
|
||||
+#if defined (CONFIG_TWL4030_POWEROFF)
|
||||
+#define twl_has_poweroff() true
|
||||
+#else
|
||||
+#define twl_has_poweroff() false
|
||||
+#endif
|
||||
+
|
||||
/* Triton Core internal information (BEGIN) */
|
||||
|
||||
/* Last - for index max*/
|
||||
@@ -224,6 +230,10 @@
|
||||
#define TWL5031 BIT(2) /* twl5031 has different registers */
|
||||
#define TWL6030_CLASS BIT(3) /* TWL6030 class */
|
||||
|
||||
+/* for pm_power_off */
|
||||
+#define PWR_P1_SW_EVENTS 0x10
|
||||
+#define PWR_DEVOFF (1 << 0)
|
||||
+
|
||||
/*----------------------------------------------------------------------*/
|
||||
|
||||
/* is driver active, bound to a chip? */
|
||||
@@ -1006,6 +1016,30 @@ static int twl_remove(struct i2c_client *client)
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void twl_poweroff(void)
|
||||
+{
|
||||
+ int err;
|
||||
+ u8 val;
|
||||
+
|
||||
+ err = twl_i2c_read_u8(TWL4030_MODULE_PM_MASTER, &val,
|
||||
+ PWR_P1_SW_EVENTS);
|
||||
+ if (err) {
|
||||
+ pr_err("%s: i2c error %d while reading TWL4030"
|
||||
+ "PM_MASTER P1_SW_EVENTS\n",
|
||||
+ DRIVER_NAME, err);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ val |= PWR_DEVOFF;
|
||||
+
|
||||
+ err = twl_i2c_write_u8(TWL4030_MODULE_PM_MASTER, val,
|
||||
+ PWR_P1_SW_EVENTS);
|
||||
+ if (err)
|
||||
+ pr_err("%s: i2c error %d while writing TWL4030"
|
||||
+ "PM_MASTER P1_SW_EVENTS\n",
|
||||
+ DRIVER_NAME, err);
|
||||
+}
|
||||
+
|
||||
/* NOTE: this driver only handles a single twl4030/tps659x0 chip */
|
||||
static int __devinit
|
||||
twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
@@ -1093,6 +1127,12 @@ twl_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||
twl_i2c_write_u8(TWL4030_MODULE_INTBR, temp, REG_GPPUPDCTR1);
|
||||
}
|
||||
|
||||
+ if(twl_has_poweroff())
|
||||
+ {
|
||||
+ /* initialize pm_power_off routine */
|
||||
+ pm_power_off = twl_poweroff;
|
||||
+ }
|
||||
+
|
||||
status = add_children(pdata, id->driver_data);
|
||||
fail:
|
||||
if (status < 0)
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-33
@@ -1,33 +0,0 @@
|
||||
From 46ea520a3c80914ae5ad3e35be7b8650706da3e6 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/32] ARM: OMAP: Add twl4030 madc support to Overo
|
||||
|
||||
Signed-off-by: Steve Sakoman <steve@sakoman.com>
|
||||
---
|
||||
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 59ca333..86f76e9 100644
|
||||
--- a/arch/arm/mach-omap2/board-overo.c
|
||||
+++ b/arch/arm/mach-omap2/board-overo.c
|
||||
@@ -637,10 +637,15 @@ static struct twl4030_codec_data overo_codec_data = {
|
||||
.audio = &overo_audio_data,
|
||||
};
|
||||
|
||||
+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
|
||||
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
From 931bd787effbd6f1f00468c89c647c66c0bbc164 Mon Sep 17 00:00:00 2001
|
||||
From: Keerthy <j-keerthy@ti.com>
|
||||
Date: Wed, 4 May 2011 01:14:50 +0530
|
||||
Subject: [PATCH 20/32] Enabling Hwmon driver for twl4030-madc
|
||||
|
||||
Signed-off-by: Keerthy <j-keerthy@ti.com>
|
||||
---
|
||||
drivers/mfd/twl-core.c | 15 +++++++++++++++
|
||||
1 files changed, 15 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
|
||||
index 8804550..d9435e4 100644
|
||||
--- a/drivers/mfd/twl-core.c
|
||||
+++ b/drivers/mfd/twl-core.c
|
||||
@@ -83,6 +83,13 @@
|
||||
#define twl_has_madc() false
|
||||
#endif
|
||||
|
||||
+#if defined(CONFIG_SENSORS_TWL4030_MADC) ||\
|
||||
+ defined(CONFIG_SENSORS_TWL4030_MADC_MODULE)
|
||||
+#define twl_has_madc_hwmon() true
|
||||
+#else
|
||||
+#define twl_has_madc_hwmon() false
|
||||
+#endif
|
||||
+
|
||||
#ifdef CONFIG_TWL4030_POWER
|
||||
#define twl_has_power() true
|
||||
#else
|
||||
@@ -619,6 +626,14 @@ add_children(struct twl4030_platform_data *pdata, unsigned long features)
|
||||
return PTR_ERR(child);
|
||||
}
|
||||
|
||||
+if (twl_has_madc_hwmon()) {
|
||||
+ child = add_child(2, "twl4030_madc_hwmon",
|
||||
+ NULL, 0,
|
||||
+ true, pdata->irq_base + MADC_INTR_OFFSET, 0);
|
||||
+ if (IS_ERR(child))
|
||||
+ return PTR_ERR(child);
|
||||
+ }
|
||||
+
|
||||
if (twl_has_rtc()) {
|
||||
/*
|
||||
* REVISIT platform_data here currently might expose the
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-54
@@ -1,54 +0,0 @@
|
||||
From aee147073ad84a7c81fba36dd475c6d2d17ed728 Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <steve@sakoman.com>
|
||||
Date: Sat, 23 Jan 2010 06:26:54 -0800
|
||||
Subject: [PATCH 21/32] mfd: twl-core: enable madc clock
|
||||
|
||||
Now that the madc driver has been merged it is also necessary to enable the clock to the madc block
|
||||
|
||||
Signed-off-by: Steve Sakoman <steve@sakoman.com>
|
||||
---
|
||||
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 d9435e4..9096d7d 100644
|
||||
--- a/drivers/mfd/twl-core.c
|
||||
+++ b/drivers/mfd/twl-core.c
|
||||
@@ -222,6 +222,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)
|
||||
@@ -992,6 +997,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 0c0d1ae..cbbf3b3 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
|
||||
|
||||
-25
@@ -1,25 +0,0 @@
|
||||
From 29dd1b5655f60f97a9cee2f4ff1d27d7da1329a1 Mon Sep 17 00:00:00 2001
|
||||
From: Ilkka Koskinen <ilkka.koskinen@nokia.com>
|
||||
Date: Wed, 16 Mar 2011 16:07:14 +0000
|
||||
Subject: [PATCH 22/32] rtc-twl: Switch to using threaded irq
|
||||
|
||||
---
|
||||
drivers/rtc/rtc-twl.c | 2 +-
|
||||
1 files changed, 1 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
|
||||
index 713b8ea..1fe1bc9 100644
|
||||
--- a/drivers/rtc/rtc-twl.c
|
||||
+++ b/drivers/rtc/rtc-twl.c
|
||||
@@ -479,7 +479,7 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
|
||||
if (ret < 0)
|
||||
goto out1;
|
||||
|
||||
- ret = request_irq(irq, twl_rtc_interrupt,
|
||||
+ ret = request_threaded_irq(irq, NULL, twl_rtc_interrupt,
|
||||
IRQF_TRIGGER_RISING,
|
||||
dev_name(&rtc->dev), rtc);
|
||||
if (ret < 0) {
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-49
@@ -1,49 +0,0 @@
|
||||
From 92c06791d4d6b537a9a83b27d71d7d3dd348f93f Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <steve@sakoman.com>
|
||||
Date: Wed, 24 Feb 2010 10:37:22 -0800
|
||||
Subject: [PATCH 23/32] 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 33007fd..2de4b02 100644
|
||||
--- a/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
|
||||
@@ -604,7 +604,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 86f76e9..61c59fc 100644
|
||||
--- a/arch/arm/mach-omap2/board-overo.c
|
||||
+++ b/arch/arm/mach-omap2/board-overo.c
|
||||
@@ -729,7 +729,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
|
||||
|
||||
-28
@@ -1,28 +0,0 @@
|
||||
From a442a2b9b2f9f51375f8a796ee88784d3754be00 Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <steve@sakoman.com>
|
||||
Date: Wed, 12 Jan 2011 05:54:55 -0800
|
||||
Subject: [PATCH 24/32] omap: mmc: Adjust dto to eliminate timeout errors
|
||||
|
||||
A number of SD card types were experiencing timeout errors. This
|
||||
could also lead to data corruption in some cases.
|
||||
|
||||
This fix proposed by Sukumar Ghoral of TI.
|
||||
---
|
||||
drivers/mmc/host/omap_hsmmc.c | 1 +
|
||||
1 files changed, 1 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
|
||||
index d57686c..7fb03e8 100644
|
||||
--- a/drivers/mmc/host/omap_hsmmc.c
|
||||
+++ b/drivers/mmc/host/omap_hsmmc.c
|
||||
@@ -1400,6 +1400,7 @@ static void set_data_timeout(struct omap_hsmmc_host *host,
|
||||
cycle_ns = 1000000000 / (clk_get_rate(host->fclk) / clkd);
|
||||
timeout = timeout_ns / cycle_ns;
|
||||
timeout += timeout_clks;
|
||||
+ timeout *= 2;
|
||||
if (timeout) {
|
||||
while ((timeout & 0x80000000) == 0) {
|
||||
dto += 1;
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-95
@@ -1,95 +0,0 @@
|
||||
From acf75c8b4d0f6775527636bf9d41bb1f74fc2f97 Mon Sep 17 00:00:00 2001
|
||||
From: Charles Manning <cdhmanning@gmail.com>
|
||||
Date: Tue, 18 Jan 2011 11:25:25 +1300
|
||||
Subject: [PATCH 25/32] omap: Fix mtd subpage read alignment
|
||||
|
||||
This allows the omap2 prefetch engine to work properly for subpage
|
||||
reads. Without this ECC errors will stop UBIFS from working.
|
||||
|
||||
Signed-off-by: Charles Manning <cdhmanning@gmail.com>
|
||||
---
|
||||
drivers/mtd/nand/nand_base.c | 19 +++++++++++++++++++
|
||||
drivers/mtd/nand/omap2.c | 1 +
|
||||
include/linux/mtd/nand.h | 3 +++
|
||||
3 files changed, 23 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
|
||||
index c54a4cb..6ca7098 100644
|
||||
--- a/drivers/mtd/nand/nand_base.c
|
||||
+++ b/drivers/mtd/nand/nand_base.c
|
||||
@@ -1157,6 +1157,22 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
}
|
||||
|
||||
/**
|
||||
+ * nand_align_subpage32 - function to align subpage read to 32-bits
|
||||
+ * @mtd: mtd info structure
|
||||
+ * @buf: pointer to offset that needs to be aligned
|
||||
+ * @len: pointer to length that needs to be aligned.
|
||||
+ */
|
||||
+
|
||||
+void nand_align_subpage32(int *offs, int *len)
|
||||
+{
|
||||
+ int diff = *offs & 3;
|
||||
+
|
||||
+ *offs = *offs - diff;
|
||||
+ *len = (*len + diff + 3) & ~3;
|
||||
+}
|
||||
+EXPORT_SYMBOL(nand_align_subpage32);
|
||||
+
|
||||
+/**
|
||||
* nand_read_subpage - [REPLACABLE] software ecc based sub-page read function
|
||||
* @mtd: mtd info structure
|
||||
* @chip: nand chip info structure
|
||||
@@ -1221,6 +1237,9 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
if (eccpos[index + (num_steps * chip->ecc.bytes)] & (busw - 1))
|
||||
aligned_len++;
|
||||
|
||||
+ if(chip->align_subpage)
|
||||
+ chip->align_subpage(&aligned_pos, &aligned_len);
|
||||
+
|
||||
chip->cmdfunc(mtd, NAND_CMD_RNDOUT,
|
||||
mtd->writesize + aligned_pos, -1);
|
||||
chip->read_buf(mtd, &chip->oob_poi[aligned_pos], aligned_len);
|
||||
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
|
||||
index da9a351..bb89c65 100644
|
||||
--- a/drivers/mtd/nand/omap2.c
|
||||
+++ b/drivers/mtd/nand/omap2.c
|
||||
@@ -1069,6 +1069,7 @@ static int __devinit omap_nand_probe(struct platform_device *pdev)
|
||||
info->nand.ecc.correct = omap_correct_data;
|
||||
info->nand.ecc.mode = NAND_ECC_HW;
|
||||
}
|
||||
+ info->nand.align_subpage = nand_align_subpage32;
|
||||
|
||||
/* DIP switches on some boards change between 8 and 16 bit
|
||||
* bus widths for flash. Try the other width if the first try fails.
|
||||
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
|
||||
index d441927..311f211 100644
|
||||
--- a/include/linux/mtd/nand.h
|
||||
+++ b/include/linux/mtd/nand.h
|
||||
@@ -479,6 +479,7 @@ struct nand_buffers {
|
||||
* additional error status checks (determine if errors are
|
||||
* correctable).
|
||||
* @write_page: [REPLACEABLE] High-level page write function
|
||||
+ * @align_subpage: [OPTIONAL] Aligns subpage read buffer.
|
||||
*/
|
||||
|
||||
struct nand_chip {
|
||||
@@ -507,6 +508,7 @@ struct nand_chip {
|
||||
int (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
|
||||
const uint8_t *buf, int page, int cached, int raw);
|
||||
|
||||
+ void (*align_subpage)(int *offs, int *len);
|
||||
int chip_delay;
|
||||
unsigned int options;
|
||||
|
||||
@@ -602,6 +604,7 @@ extern int nand_erase_nand(struct mtd_info *mtd, struct erase_info *instr,
|
||||
int allowbbt);
|
||||
extern int nand_do_read(struct mtd_info *mtd, loff_t from, size_t len,
|
||||
size_t *retlen, uint8_t *buf);
|
||||
+extern void nand_align_subpage32(int *offs, int *len);
|
||||
|
||||
/**
|
||||
* struct platform_nand_chip - chip level device structure
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-35
@@ -1,35 +0,0 @@
|
||||
From 048c2b85c12ac4aa8cd82201e1ade332557e4380 Mon Sep 17 00:00:00 2001
|
||||
From: Charles Manning <manningc2@actrix.gen.nz>
|
||||
Date: Thu, 16 Dec 2010 20:35:56 -0800
|
||||
Subject: [PATCH 26/32] mtd: nand: omap2: Force all buffer reads to u32 alignment
|
||||
|
||||
---
|
||||
drivers/mtd/nand/omap2.c | 12 ++++++++++++
|
||||
1 files changed, 12 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
|
||||
index bb89c65..832f111 100644
|
||||
--- a/drivers/mtd/nand/omap2.c
|
||||
+++ b/drivers/mtd/nand/omap2.c
|
||||
@@ -247,6 +247,18 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
|
||||
int ret = 0;
|
||||
u32 *p = (u32 *)buf;
|
||||
|
||||
+ /* u32 align the buffer and read */
|
||||
+ /* NB: This assumes the buf ptr can be aligned *down* which is a valid.
|
||||
+ * Assumption when dealing with ecc buffers etc.
|
||||
+ */
|
||||
+ u32 addr = (u32)p;
|
||||
+
|
||||
+ int diff = addr & 3;
|
||||
+ addr -= diff;
|
||||
+ len += diff;
|
||||
+ len = (len + 3) & ~3;
|
||||
+ p = (u32 *)addr;
|
||||
+
|
||||
/* take care of subpage reads */
|
||||
if (len % 4) {
|
||||
if (info->nand.options & NAND_BUSWIDTH_16)
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-63
@@ -1,63 +0,0 @@
|
||||
From fb4dfff6a6e107e0e526801e7add4a9aaeab1eab Mon Sep 17 00:00:00 2001
|
||||
From: kishore kadiyala <kishore.kadiyala@ti.com>
|
||||
Date: Mon, 2 May 2011 11:10:38 +0000
|
||||
Subject: [PATCH 27/32] omap : nand : fix subpage ecc issue with prefetch
|
||||
|
||||
For prefetch engine, read and write got broken in commit '2c01946c'.
|
||||
We never hit a scenario of not getting 'gpmc_prefetch_enable'
|
||||
call success.
|
||||
When reading/writing a subpage with a non divisible by 4 ecc number
|
||||
of bytes, the mis-aligned bytes gets handled first before enabling
|
||||
the Prefetch engine, then it reads/writes rest of the bytes.
|
||||
|
||||
Signed-off-by: Kishore Kadiyala <kishore.kadiyala@ti.com>
|
||||
Signed-off-by: Vimal Singh <vimal.newwork@gmail.com>
|
||||
Reported-by: Bryan DE FARIA <bdefaria@adeneo-embedded.com>
|
||||
---
|
||||
drivers/mtd/nand/omap2.c | 12 +++++-------
|
||||
1 files changed, 5 insertions(+), 7 deletions(-)
|
||||
|
||||
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
|
||||
index 832f111..471a39b 100644
|
||||
--- a/drivers/mtd/nand/omap2.c
|
||||
+++ b/drivers/mtd/nand/omap2.c
|
||||
@@ -275,11 +275,10 @@ static void omap_read_buf_pref(struct mtd_info *mtd, u_char *buf, int len)
|
||||
if (ret) {
|
||||
/* PFPW engine is busy, use cpu copy method */
|
||||
if (info->nand.options & NAND_BUSWIDTH_16)
|
||||
- omap_read_buf16(mtd, buf, len);
|
||||
+ omap_read_buf16(mtd, (u_char *)p, len);
|
||||
else
|
||||
- omap_read_buf8(mtd, buf, len);
|
||||
+ omap_read_buf8(mtd, (u_char *)p, len);
|
||||
} else {
|
||||
- p = (u32 *) buf;
|
||||
do {
|
||||
r_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
|
||||
r_count = r_count >> 2;
|
||||
@@ -305,7 +304,7 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
|
||||
struct omap_nand_info, mtd);
|
||||
uint32_t w_count = 0;
|
||||
int i = 0, ret = 0;
|
||||
- u16 *p;
|
||||
+ u16 *p = (u16 *)buf;
|
||||
unsigned long tim, limit;
|
||||
|
||||
/* take care of subpage writes */
|
||||
@@ -321,11 +320,10 @@ static void omap_write_buf_pref(struct mtd_info *mtd,
|
||||
if (ret) {
|
||||
/* PFPW engine is busy, use cpu copy method */
|
||||
if (info->nand.options & NAND_BUSWIDTH_16)
|
||||
- omap_write_buf16(mtd, buf, len);
|
||||
+ omap_write_buf16(mtd, (u_char *)p, len);
|
||||
else
|
||||
- omap_write_buf8(mtd, buf, len);
|
||||
+ omap_write_buf8(mtd, (u_char *)p, len);
|
||||
} else {
|
||||
- p = (u16 *) buf;
|
||||
while (len) {
|
||||
w_count = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
|
||||
w_count = w_count >> 1;
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-46
@@ -1,46 +0,0 @@
|
||||
From ee2dcb39e9255fc0aa6b4e267e9553bdbd11e82b Mon Sep 17 00:00:00 2001
|
||||
From: Scott Ellis <scottellis.developer@gmail.com>
|
||||
Date: Sun, 23 Jan 2011 20:39:35 -0800
|
||||
Subject: [PATCH 28/32] OMAP: Overo: Add support for spidev
|
||||
|
||||
---
|
||||
arch/arm/mach-omap2/board-overo.c | 16 ++++++++++++++++
|
||||
1 files changed, 16 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
|
||||
index 61c59fc..05dd3eb 100644
|
||||
--- a/arch/arm/mach-omap2/board-overo.c
|
||||
+++ b/arch/arm/mach-omap2/board-overo.c
|
||||
@@ -683,6 +683,14 @@ static struct spi_board_info overo_spi_board_info[] __initdata = {
|
||||
.irq = OMAP_GPIO_IRQ(OVERO_GPIO_PENDOWN),
|
||||
.platform_data = &ads7846_config,
|
||||
},
|
||||
+#elif defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
|
||||
+ {
|
||||
+ .modalias = "spidev",
|
||||
+ .bus_num = 1,
|
||||
+ .chip_select = 0,
|
||||
+ .max_speed_hz = 48000000,
|
||||
+ .mode = SPI_MODE_0,
|
||||
+ },
|
||||
#endif
|
||||
#if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \
|
||||
defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE)
|
||||
@@ -693,6 +701,14 @@ static struct spi_board_info overo_spi_board_info[] __initdata = {
|
||||
.max_speed_hz = 500000,
|
||||
.mode = SPI_MODE_3,
|
||||
},
|
||||
+#elif defined(CONFIG_SPI_SPIDEV) || defined(CONFIG_SPI_SPIDEV_MODULE)
|
||||
+ {
|
||||
+ .modalias = "spidev",
|
||||
+ .bus_num = 1,
|
||||
+ .chip_select = 1,
|
||||
+ .max_speed_hz = 48000000,
|
||||
+ .mode = SPI_MODE_0,
|
||||
+ },
|
||||
#endif
|
||||
};
|
||||
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-11494
File diff suppressed because it is too large
Load Diff
-34
@@ -1,34 +0,0 @@
|
||||
From 728b784863056a2b2e35134f71082271ebab0892 Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <steve@sakoman.com>
|
||||
Date: Mon, 23 May 2011 12:16:50 -0700
|
||||
Subject: [PATCH 30/32] omap: Change omap_device activate latency messages from pr_warning to pr_debug
|
||||
|
||||
Messages can be safely ignored, so reduce console noise
|
||||
|
||||
Signed-off-by: Steve Sakoman <steve@sakoman.com>
|
||||
---
|
||||
arch/arm/plat-omap/omap_device.c | 4 ++--
|
||||
1 files changed, 2 insertions(+), 2 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
|
||||
index 9bbda9a..ca8a479 100644
|
||||
--- a/arch/arm/plat-omap/omap_device.c
|
||||
+++ b/arch/arm/plat-omap/omap_device.c
|
||||
@@ -145,12 +145,12 @@ static int _omap_device_activate(struct omap_device *od, u8 ignore_lat)
|
||||
odpl->activate_lat_worst = act_lat;
|
||||
if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
|
||||
odpl->activate_lat = act_lat;
|
||||
- pr_warning("omap_device: %s.%d: new worst case "
|
||||
+ pr_debug("omap_device: %s.%d: new worst case "
|
||||
"activate latency %d: %llu\n",
|
||||
od->pdev.name, od->pdev.id,
|
||||
od->pm_lat_level, act_lat);
|
||||
} else
|
||||
- pr_warning("omap_device: %s.%d: activate "
|
||||
+ pr_debug("omap_device: %s.%d: activate "
|
||||
"latency %d higher than exptected. "
|
||||
"(%llu > %d)\n",
|
||||
od->pdev.name, od->pdev.id,
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -1,105 +0,0 @@
|
||||
From 530abfee962141f263344b4de3ca48b57e5e514c Mon Sep 17 00:00:00 2001
|
||||
From: Steve Sakoman <steve@sakoman.com>
|
||||
Date: Tue, 24 May 2011 20:36:07 -0700
|
||||
Subject: [PATCH 31/32] omap: overo: Add opp init
|
||||
|
||||
omap: overo: Add opp init
|
||||
|
||||
Work in progress
|
||||
|
||||
Signed-off-by: Steve Sakoman <steve@sakoman.com>
|
||||
---
|
||||
arch/arm/mach-omap2/board-overo.c | 49 +++++++++++++++++++++++++++++++++++++
|
||||
1 files changed, 49 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
|
||||
index 05dd3eb..8c2d21f 100644
|
||||
--- a/arch/arm/mach-omap2/board-overo.c
|
||||
+++ b/arch/arm/mach-omap2/board-overo.c
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <linux/init.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
+#include <linux/opp.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/i2c/twl.h>
|
||||
#include <linux/regulator/machine.h>
|
||||
@@ -43,6 +44,7 @@
|
||||
|
||||
#include <plat/board.h>
|
||||
#include <plat/common.h>
|
||||
+#include <plat/omap_device.h>
|
||||
#include <plat/display.h>
|
||||
#include <plat/panel-generic-dpi.h>
|
||||
#include <mach/gpio.h>
|
||||
@@ -54,6 +56,7 @@
|
||||
#include <plat/usb.h>
|
||||
|
||||
#include "mux.h"
|
||||
+#include "pm.h"
|
||||
#include "sdram-micron-mt46h32m32lf-6.h"
|
||||
#include "hsmmc.h"
|
||||
|
||||
@@ -755,6 +758,51 @@ static struct omap_musb_board_data musb_board_data = {
|
||||
.power = 100,
|
||||
};
|
||||
|
||||
+static void __init overo_opp_init(void)
|
||||
+{
|
||||
+ int r = 0;
|
||||
+
|
||||
+ /* Initialize the omap3 opp table */
|
||||
+ if (omap3_opp_init()) {
|
||||
+ pr_err("%s: opp default init failed\n", __func__);
|
||||
+ return;
|
||||
+ }
|
||||
+
|
||||
+ /* Custom OPP enabled for 36/3730 */
|
||||
+ if (cpu_is_omap3630()) {
|
||||
+ struct omap_hwmod *mh = omap_hwmod_lookup("mpu");
|
||||
+ struct omap_hwmod *dh = omap_hwmod_lookup("iva");
|
||||
+ struct device *dev;
|
||||
+
|
||||
+ if (!mh || !dh) {
|
||||
+ pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
|
||||
+ __func__, mh, dh);
|
||||
+ return;
|
||||
+ }
|
||||
+ /* Enable MPU 1GHz and lower opps */
|
||||
+ dev = &mh->od->pdev.dev;
|
||||
+ r = opp_enable(dev, 1000000000);
|
||||
+
|
||||
+ /* Enable IVA 800MHz and lower opps */
|
||||
+ dev = &dh->od->pdev.dev;
|
||||
+ r |= opp_enable(dev, 800000000);
|
||||
+
|
||||
+ if (r) {
|
||||
+ pr_err("%s: failed to enable higher opp %d\n",
|
||||
+ __func__, r);
|
||||
+ /*
|
||||
+ * Cleanup - disable the higher freqs - we dont care
|
||||
+ * about the results
|
||||
+ */
|
||||
+ dev = &mh->od->pdev.dev;
|
||||
+ opp_disable(dev, 1000000000);
|
||||
+ dev = &dh->od->pdev.dev;
|
||||
+ opp_disable(dev, 800000000);
|
||||
+ }
|
||||
+ }
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
static void __init overo_init(void)
|
||||
{
|
||||
omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
|
||||
@@ -770,6 +818,7 @@ static void __init overo_init(void)
|
||||
overo_display_init();
|
||||
overo_init_led();
|
||||
overo_init_keys();
|
||||
+ overo_opp_init();
|
||||
|
||||
/* Ensure SDRC pins are mux'd for self-refresh */
|
||||
omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
-202
@@ -1,202 +0,0 @@
|
||||
From cd9682b39f41675c4e551c607425226b38fab17d Mon Sep 17 00:00:00 2001
|
||||
From: Sanjeev Premi <premi@ti.com>
|
||||
Date: Tue, 18 Jan 2011 13:19:55 +0530
|
||||
Subject: [PATCH 32/32] omap3: Add basic support for 720MHz part
|
||||
|
||||
This patch adds support for new speed enhanced parts with ARM
|
||||
and IVA running at 720MHz and 520MHz respectively. These parts
|
||||
can be probed at run-time by reading PRODID.SKUID[3:0] at
|
||||
0x4830A20C [1].
|
||||
|
||||
This patch specifically does following:
|
||||
* Detect devices capable of 720MHz.
|
||||
* Add new OPP
|
||||
* Ensure that OPP is conditionally enabled.
|
||||
* Check for presence of IVA before attempting to enable
|
||||
the corresponding OPP.
|
||||
|
||||
[1] http://focus.ti.com/lit/ug/spruff1d/spruff1d.pdf
|
||||
|
||||
Signed-off-by: Sanjeev Premi <premi@ti.com>
|
||||
---
|
||||
arch/arm/mach-omap2/control.h | 7 ++++
|
||||
arch/arm/mach-omap2/id.c | 10 +++++
|
||||
arch/arm/mach-omap2/opp3xxx_data.c | 63 ++++++++++++++++++++++++++++++++-
|
||||
arch/arm/plat-omap/include/plat/cpu.h | 2 +
|
||||
4 files changed, 81 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h
|
||||
index c2804c1..6edd7cc 100644
|
||||
--- a/arch/arm/mach-omap2/control.h
|
||||
+++ b/arch/arm/mach-omap2/control.h
|
||||
@@ -371,6 +371,13 @@
|
||||
#define FEAT_NEON 0
|
||||
#define FEAT_NEON_NONE 1
|
||||
|
||||
+/*
|
||||
+ * Product ID register
|
||||
+ */
|
||||
+#define OMAP3_PRODID 0x020C
|
||||
+
|
||||
+#define OMAP3_SKUID_MASK 0x0f
|
||||
+#define OMAP3_SKUID_720MHZ 0x08
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
#ifdef CONFIG_ARCH_OMAP2PLUS
|
||||
diff --git a/arch/arm/mach-omap2/id.c b/arch/arm/mach-omap2/id.c
|
||||
index 2537090..b6ed78a 100644
|
||||
--- a/arch/arm/mach-omap2/id.c
|
||||
+++ b/arch/arm/mach-omap2/id.c
|
||||
@@ -210,6 +210,15 @@ static void __init omap3_check_features(void)
|
||||
* TODO: Get additional info (where applicable)
|
||||
* e.g. Size of L2 cache.
|
||||
*/
|
||||
+
|
||||
+ /*
|
||||
+ * Does it support 720MHz?
|
||||
+ */
|
||||
+ status = (OMAP3_SKUID_MASK & read_tap_reg(OMAP3_PRODID));
|
||||
+
|
||||
+ if (status & OMAP3_SKUID_720MHZ) {
|
||||
+ omap3_features |= OMAP3_HAS_720MHZ;
|
||||
+ }
|
||||
}
|
||||
|
||||
static void __init ti816x_check_features(void)
|
||||
@@ -490,6 +499,7 @@ static void __init omap3_cpuinfo(void)
|
||||
OMAP3_SHOW_FEATURE(neon);
|
||||
OMAP3_SHOW_FEATURE(isp);
|
||||
OMAP3_SHOW_FEATURE(192mhz_clk);
|
||||
+ OMAP3_SHOW_FEATURE(720mhz);
|
||||
|
||||
printk(")\n");
|
||||
}
|
||||
diff --git a/arch/arm/mach-omap2/opp3xxx_data.c b/arch/arm/mach-omap2/opp3xxx_data.c
|
||||
index d95f3f9..44fbc84 100644
|
||||
--- a/arch/arm/mach-omap2/opp3xxx_data.c
|
||||
+++ b/arch/arm/mach-omap2/opp3xxx_data.c
|
||||
@@ -18,8 +18,10 @@
|
||||
* GNU General Public License for more details.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
+#include <linux/opp.h>
|
||||
|
||||
#include <plat/cpu.h>
|
||||
+#include <plat/omap_device.h>
|
||||
|
||||
#include "control.h"
|
||||
#include "omap_opp_data.h"
|
||||
@@ -98,6 +100,8 @@ static struct omap_opp_def __initdata omap34xx_opp_def_list[] = {
|
||||
OPP_INITIALIZER("mpu", true, 550000000, OMAP3430_VDD_MPU_OPP4_UV),
|
||||
/* MPU OPP5 */
|
||||
OPP_INITIALIZER("mpu", true, 600000000, OMAP3430_VDD_MPU_OPP5_UV),
|
||||
+ /* MPU OPP6 */
|
||||
+ OPP_INITIALIZER("mpu", false, 720000000, 1350000),
|
||||
|
||||
/*
|
||||
* L3 OPP1 - 41.5 MHz is disabled because: The voltage for that OPP is
|
||||
@@ -123,6 +127,8 @@ static struct omap_opp_def __initdata omap34xx_opp_def_list[] = {
|
||||
OPP_INITIALIZER("iva", true, 400000000, OMAP3430_VDD_MPU_OPP4_UV),
|
||||
/* DSP OPP5 */
|
||||
OPP_INITIALIZER("iva", true, 430000000, OMAP3430_VDD_MPU_OPP5_UV),
|
||||
+ /* DSP OPP6 */
|
||||
+ OPP_INITIALIZER("iva", false, 520000000, 1350000),
|
||||
};
|
||||
|
||||
static struct omap_opp_def __initdata omap36xx_opp_def_list[] = {
|
||||
@@ -150,6 +156,57 @@ static struct omap_opp_def __initdata omap36xx_opp_def_list[] = {
|
||||
OPP_INITIALIZER("iva", false, 800000000, OMAP3630_VDD_MPU_OPP1G_UV),
|
||||
};
|
||||
|
||||
+
|
||||
+/**
|
||||
+ * omap3_opp_enable_720Mhz() - Enable the OPP corresponding to 720MHz
|
||||
+ *
|
||||
+ * This function would be executed only if the silicon is capable of
|
||||
+ * running at the 720MHz.
|
||||
+ */
|
||||
+static int __init omap3_opp_enable_720Mhz(void)
|
||||
+{
|
||||
+ int r = -ENODEV;
|
||||
+ struct omap_hwmod *oh_mpu = omap_hwmod_lookup("mpu");
|
||||
+ struct omap_hwmod *oh_iva;
|
||||
+ struct platform_device *pdev;
|
||||
+
|
||||
+ if (!oh_mpu || !oh_mpu->od) {
|
||||
+ goto err;
|
||||
+ } else {
|
||||
+ pdev = &oh_mpu->od->pdev;
|
||||
+
|
||||
+ r = opp_enable(&pdev->dev, 720000000);
|
||||
+ if (r < 0) {
|
||||
+ dev_err(&pdev->dev,
|
||||
+ "opp_enable() failed for mpu@720MHz");
|
||||
+ goto err;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (omap3_has_iva()) {
|
||||
+ oh_iva = omap_hwmod_lookup("iva");
|
||||
+
|
||||
+ if (!oh_iva || !oh_iva->od) {
|
||||
+ r = -ENODEV;
|
||||
+ goto err;
|
||||
+ } else {
|
||||
+ pdev = &oh_iva->od->pdev;
|
||||
+
|
||||
+ r = opp_enable(&pdev->dev, 520000000);
|
||||
+ if (r < 0) {
|
||||
+ dev_err(&pdev->dev,
|
||||
+ "opp_enable() failed for iva@520MHz");
|
||||
+ goto err;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ dev_info(&pdev->dev, "Enabled OPP corresponding to 720MHz\n");
|
||||
+
|
||||
+err:
|
||||
+ return r;
|
||||
+}
|
||||
+
|
||||
/**
|
||||
* omap3_opp_init() - initialize omap3 opp table
|
||||
*/
|
||||
@@ -163,10 +220,14 @@ int __init omap3_opp_init(void)
|
||||
if (cpu_is_omap3630())
|
||||
r = omap_init_opp_table(omap36xx_opp_def_list,
|
||||
ARRAY_SIZE(omap36xx_opp_def_list));
|
||||
- else
|
||||
+ else {
|
||||
r = omap_init_opp_table(omap34xx_opp_def_list,
|
||||
ARRAY_SIZE(omap34xx_opp_def_list));
|
||||
|
||||
+ if (omap3_has_720mhz())
|
||||
+ r = omap3_opp_enable_720Mhz();
|
||||
+ }
|
||||
+
|
||||
return r;
|
||||
}
|
||||
device_initcall(omap3_opp_init);
|
||||
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
|
||||
index 8198bb6..5204c1e 100644
|
||||
--- a/arch/arm/plat-omap/include/plat/cpu.h
|
||||
+++ b/arch/arm/plat-omap/include/plat/cpu.h
|
||||
@@ -478,6 +478,7 @@ extern u32 omap3_features;
|
||||
#define OMAP3_HAS_192MHZ_CLK BIT(5)
|
||||
#define OMAP3_HAS_IO_WAKEUP BIT(6)
|
||||
#define OMAP3_HAS_SDRC BIT(7)
|
||||
+#define OMAP3_HAS_720MHZ BIT(8)
|
||||
|
||||
#define OMAP3_HAS_FEATURE(feat,flag) \
|
||||
static inline unsigned int omap3_has_ ##feat(void) \
|
||||
@@ -493,5 +494,6 @@ OMAP3_HAS_FEATURE(isp, ISP)
|
||||
OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
|
||||
OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
|
||||
OMAP3_HAS_FEATURE(sdrc, SDRC)
|
||||
+OMAP3_HAS_FEATURE(720mhz, 720MHZ)
|
||||
|
||||
#endif
|
||||
--
|
||||
1.6.6.1
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
require linux.inc
|
||||
|
||||
DESCRIPTION = "Linux kernel for OMAP processors"
|
||||
|
||||
COMPATIBLE_MACHINE = "(beagleboard)"
|
||||
|
||||
# The main PR is now using MACHINE_KERNEL_PR, for omap3 see conf/machine/include/omap3.inc
|
||||
SRCREV_pn-${PN} = "v2.6.39"
|
||||
MACHINE_KERNEL_PR_append = "o"
|
||||
|
||||
FILESEXTRAPATHS_prepend := "{THISDIR}/${PN}-${PV}:"
|
||||
|
||||
SRC_URI += "git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap.git;protocol=git \
|
||||
file://defconfig"
|
||||
|
||||
SRC_URI_append = " \
|
||||
file://sakoman/0001-OMAP-DSS2-DSI-fix-use_sys_clk-highfreq.patch \
|
||||
file://sakoman/0002-OMAP-DSS2-DSI-fix-dsi_dump_clocks.patch \
|
||||
file://sakoman/0003-OMAP2PLUS-DSS2-Fix-Return-correct-lcd-clock-source-f.patch \
|
||||
file://sakoman/0004-OMAP-DSS-DSI-Fix-DSI-PLL-power-bug.patch \
|
||||
file://sakoman/0005-OMAP-DSS2-fix-panel-Kconfig-dependencies.patch \
|
||||
file://sakoman/0006-OMAP-DSS2-add-bootarg-for-selecting-svideo-or-compos.patch \
|
||||
file://sakoman/0007-video-add-timings-for-hd720.patch \
|
||||
file://sakoman/0008-drivers-net-smsc911x-return-ENODEV-if-device-is-not-.patch \
|
||||
file://sakoman/0009-drivers-input-touchscreen-ads7846-return-ENODEV-if-d.patch \
|
||||
file://sakoman/0010-Revert-omap2_mcspi-Flush-posted-writes.patch \
|
||||
file://sakoman/0011-Revert-omap_hsmmc-improve-interrupt-synchronisation.patch \
|
||||
file://sakoman/0012-Don-t-turn-SDIO-cards-off-to-save-power.-Doing-so-wi.patch \
|
||||
file://sakoman/0014-soc-codecs-Enable-audio-capture-by-default-for-twl40.patch \
|
||||
file://sakoman/0015-soc-codecs-twl4030-Turn-on-mic-bias-by-default.patch \
|
||||
file://sakoman/0016-RTC-add-support-for-backup-battery-recharge.patch \
|
||||
file://sakoman/0017-ARM-OMAP2-mmc-twl4030-move-clock-input-selection-pri.patch \
|
||||
file://sakoman/0018-Add-power-off-support-for-the-TWL4030-companion.patch \
|
||||
file://sakoman/0019-ARM-OMAP-Add-twl4030-madc-support-to-Overo.patch \
|
||||
file://sakoman/0020-Enabling-Hwmon-driver-for-twl4030-madc.patch \
|
||||
file://sakoman/0021-mfd-twl-core-enable-madc-clock.patch \
|
||||
file://sakoman/0022-rtc-twl-Switch-to-using-threaded-irq.patch \
|
||||
file://sakoman/0023-ARM-OMAP-automatically-set-musb-mode-in-platform-dat.patch \
|
||||
file://sakoman/0024-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch \
|
||||
file://sakoman/0025-omap-Fix-mtd-subpage-read-alignment.patch \
|
||||
file://sakoman/0026-mtd-nand-omap2-Force-all-buffer-reads-to-u32-alignme.patch \
|
||||
file://sakoman/0027-omap-nand-fix-subpage-ecc-issue-with-prefetch.patch \
|
||||
file://sakoman/0028-OMAP-Overo-Add-support-for-spidev.patch \
|
||||
file://sakoman/0029-unionfs-Add-support-for-unionfs-2.5.9.patch \
|
||||
file://sakoman/0030-omap-Change-omap_device-activate-latency-messages-fr.patch \
|
||||
file://sakoman/0031-omap-overo-Add-opp-init.patch \
|
||||
file://sakoman/0032-omap3-Add-basic-support-for-720MHz-part.patch \
|
||||
\
|
||||
file://beagle/0001-OMAP3-beagle-add-support-for-beagleboard-xM-revision.patch \
|
||||
file://beagle/0002-OMAP3-beagle-add-support-for-expansionboards.patch \
|
||||
file://beagle/0003-OMAP3-beagle-add-MADC-support.patch \
|
||||
file://beagle/0004-OMAP3-beagle-add-regulators-for-camera-interface.patch \
|
||||
file://beagle/0005-OMAP3-beagle-HACK-add-in-1GHz-OPP.patch \
|
||||
file://beagle/0006-OMAP3-BEAGLE-fix-RTC.patch \
|
||||
file://beagle/0007-omap-mmc-Adjust-dto-to-eliminate-timeout-errors.patch \
|
||||
\
|
||||
file://camera/0001-Add-driver-for-Aptina-Micron-mt9p031-sensor.patch \
|
||||
file://camera/0002-v4l-Add-mt9v032-sensor-driver.patch \
|
||||
file://camera/0003-Add-support-for-mt9p031-LI-5M03-module-in-Beagleboar.patch \
|
||||
\
|
||||
file://pm/linux-omap-2.6.39-ti-pm/0001-OMAP3-voltage-remove-spurious-pr_notice-for-debugfs.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm/0002-OMAP4-PM-remove-redundant-ifdef-CONFIG_PM.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm/0003-OMAP3-smartreflex-fix-sr_late_init-error-path-in-pro.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm/0004-OMAP3-smartreflex-request-the-memory-region.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm/0005-OMAP3-smartreflex-fix-ioremap-leak-on-probe-error.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm/0006-OMAP3-smartreflex-delete-instance-from-sr_list-on-pr.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm/0007-OMAP3-smartreflex-delete-debugfs-entries-on-probe-er.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm/0008-OMAP3-cpuidle-remove-useless-SDP-specific-timings.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm/0009-OMAP3-SR-make-notify-independent-of-class.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm/0010-OMAP3-SR-disable-interrupt-by-default.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm/0011-OMAP3-SR-enable-disable-SR-only-on-need.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm/0012-OMAP3-SR-fix-cosmetic-indentation.patch \
|
||||
\
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0001-OMAP-CPUfreq-ensure-driver-initializes-after-cpufreq.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0002-OMAP-CPUfreq-ensure-policy-is-fully-initialized.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0003-OMAP3-PM-CPUFreq-driver-for-OMAP3.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0004-OMAP-PM-CPUFREQ-Fix-conditional-compilation.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0005-cpufreq-fixup-after-new-OPP-layer-merged.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0006-OMAP-cpufreq-Split-OMAP1-and-OMAP2PLUS-CPUfreq-drive.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0007-OMAP2PLUS-cpufreq-Add-SMP-support-to-cater-OMAP4430.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq/0008-OMAP2PLUS-cpufreq-Fix-typo-when-attempting-to-set-mp.patch \
|
||||
\
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0001-cpufreq-helpers-for-walking-the-frequency-table.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-hotplug/0002-cpufreq-introduce-hotplug-governor.patch \
|
||||
\
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0001-OMAP2-cpufreq-free-up-table-on-exit.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0002-OMAP2-cpufreq-handle-invalid-cpufreq-table.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0003-OMAP2-cpufreq-minor-comment-cleanup.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0004-OMAP2-cpufreq-use-clk_init_cpufreq_table-if-OPPs-not.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0005-OMAP2-cpufreq-use-cpufreq_frequency_table_target.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpufreq-fixes/0006-OMAP2-cpufreq-fix-freq_table-leak.patch \
|
||||
\
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0001-OMAP2-clockdomain-Add-an-api-to-read-idle-mode.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0002-OMAP2-clockdomain-Add-SoC-support-for-clkdm_is_idle.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0003-OMAP2-PM-Initialise-sleep_switch-to-a-non-valid-valu.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0004-OMAP2-PM-idle-clkdms-only-if-already-in-idle.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0005-OMAP2-hwmod-Follow-the-recomended-PRCM-sequence.patch \
|
||||
file://pm/linux-omap-2.6.39-ti-pm-wip-cpuidle/0006-OMAP-Serial-Check-wk_st-only-if-present.patch \
|
||||
\
|
||||
file://mfd/0001-mfd-Fix-omap-usbhs-crash-when-rmmoding-ehci-or-ohci.patch \
|
||||
file://mfd/0002-mfd-Fix-omap_usbhs_alloc_children-error-handling.patch \
|
||||
file://mfd/0003-mfd-Add-omap-usbhs-runtime-PM-support.patch \
|
||||
file://mfd/0004-arm-omap-usb-ehci-and-ohci-hwmod-structures-for-omap.patch \
|
||||
file://mfd/0005-arm-omap-usb-register-hwmods-of-usbhs.patch \
|
||||
file://mfd/0006-arm-omap-usb-device-name-change-for-the-clk-names-of.patch \
|
||||
file://mfd/0007-mfd-global-Suspend-and-resume-support-of-ehci-and-oh.patch \
|
||||
file://mfd/0008-MFD-TWL4030-Correct-the-warning-print-during-script-.patch \
|
||||
file://mfd/0009-MFD-TWL4030-Modifying-the-macro-name-Main_Ref-to-all.patch \
|
||||
file://mfd/0010-MFD-TWL4030-power-scripts-for-OMAP3-boards.patch \
|
||||
file://mfd/0011-MFD-TWL4030-TWL-version-checking.patch \
|
||||
file://mfd/0012-MFD-TWL4030-workaround-changes-for-Erratum-27.patch \
|
||||
file://mfd/0013-MFD-TWL4030-optimizing-resource-configuration.patch \
|
||||
\
|
||||
file://musb/0001-usb-musb-Enable-DMA-mode1-RX-for-USB-Mass-Storage.patch \
|
||||
\
|
||||
file://net/0001-NFS-Revert-NFSROOT-default-mount-options.patch \
|
||||
"
|
||||
|
||||
SRC_URI_append_beagleboard = " file://logo_linux_clut224.ppm \
|
||||
"
|
||||
|
||||
S = "${WORKDIR}/git"
|
||||
|
||||
Reference in New Issue
Block a user