From patchwork Wed Oct 7 10:49:29 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kalle Jokiniemi X-Patchwork-Id: 52246 Received: from vger.kernel.org (vger.kernel.org [209.132.176.167]) by demeter.kernel.org (8.14.2/8.14.2) with ESMTP id n97AwAb7026656 for ; Wed, 7 Oct 2009 10:58:10 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1758874AbZJGKtX (ORCPT ); Wed, 7 Oct 2009 06:49:23 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1758881AbZJGKtX (ORCPT ); Wed, 7 Oct 2009 06:49:23 -0400 Received: from smtp1.digia.com ([82.118.214.156]:59247 "EHLO smtp1.digia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1758842AbZJGKtW (ORCPT ); Wed, 7 Oct 2009 06:49:22 -0400 Received: from smtp1.digia.com (unknown [127.0.0.1]) by IMSA (Postfix) with ESMTP id ED7D44789FC; Wed, 7 Oct 2009 13:48:44 +0300 (EEST) Received: from IT-EXCH01-HKI.it.local (unknown [10.9.52.52]) by smtp1.digia.com (Postfix) with ESMTP id D701047898F; Wed, 7 Oct 2009 13:48:44 +0300 (EEST) Received: from localhost.localdomain (10.120.146.33) by IT-EXCH01-HKI.it.local (10.9.52.56) with Microsoft SMTP Server id 8.1.340.0; Wed, 7 Oct 2009 13:48:44 +0300 From: Kalle Jokiniemi To: CC: , , , Kalle Jokiniemi Subject: [PATCH V3] OMAP: I2C: Add mpu wake up latency constraint in i2c Date: Wed, 7 Oct 2009 13:49:29 +0300 Message-ID: <1254912569-30089-1-git-send-email-kalle.jokiniemi@digia.com> X-Mailer: git-send-email 1.5.4.3 In-Reply-To: <> References: <> MIME-Version: 1.0 Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index 8b84839..e923db5 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -26,8 +26,10 @@ #include #include #include +#include #include #include +#include #define OMAP_I2C_SIZE 0x3f #define OMAP1_I2C_BASE 0xfffb3800 @@ -69,14 +71,14 @@ static struct resource i2c_resources[][2] = { }, \ } -static u32 i2c_rate[ARRAY_SIZE(i2c_resources)]; +static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)]; static struct platform_device omap_i2c_devices[] = { - I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_rate[0]), + I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_pdata[0]), #if defined(CONFIG_ARCH_OMAP24XX) || defined(CONFIG_ARCH_OMAP34XX) - I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_rate[1]), + I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_pdata[1]), #endif #if defined(CONFIG_ARCH_OMAP34XX) - I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_rate[2]), + I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_pdata[2]), #endif }; @@ -100,6 +102,31 @@ static const int omap34xx_pins[][2] = {}; #define OMAP_I2C_CMDLINE_SETUP (BIT(31)) +/** + * omap3_i2c_set_wfc_mpu_wkup_lat - sets mpu wake up constraint + * @dev: i2c bus device pointer + * @set: set or clear constraints + * + * When waiting for completion of a i2c transfer, we need to set a wake up + * latency constraint for the MPU. This is to ensure quick enough wakeup from + * idle, when transfer completes. For OMAP3 platform. + */ +#ifdef CONFIG_ARCH_OMAP34XX +static void omap3_i2c_set_wfc_mpu_wkup_lat(struct device *dev, int set) +{ + omap_pm_set_max_mpu_wakeup_lat(dev, set ? 400 : -1); +} +#endif + +static void __init omap_set_i2c_constraint_func( + struct omap_i2c_bus_platform_data *pd) +{ + if (cpu_is_omap34xx()) + pd->set_mpu_wkup_lat = omap3_i2c_set_wfc_mpu_wkup_lat; + else + pd->set_mpu_wkup_lat = NULL; +} + static void __init omap_i2c_mux_pins(int bus) { int scl, sda; @@ -180,8 +207,8 @@ static int __init omap_i2c_bus_setup(char *str) get_options(str, 3, ints); if (ints[0] < 2 || ints[1] < 1 || ints[1] > ports) return 0; - i2c_rate[ints[1] - 1] = ints[2]; - i2c_rate[ints[1] - 1] |= OMAP_I2C_CMDLINE_SETUP; + i2c_pdata[ints[1] - 1].clkrate = ints[2]; + i2c_pdata[ints[1] - 1].clkrate |= OMAP_I2C_CMDLINE_SETUP; return 1; } @@ -195,9 +222,10 @@ static int __init omap_register_i2c_bus_cmdline(void) { int i, err = 0; - for (i = 0; i < ARRAY_SIZE(i2c_rate); i++) - if (i2c_rate[i] & OMAP_I2C_CMDLINE_SETUP) { - i2c_rate[i] &= ~OMAP_I2C_CMDLINE_SETUP; + for (i = 0; i < ARRAY_SIZE(i2c_pdata); i++) + if (i2c_pdata[i].clkrate & OMAP_I2C_CMDLINE_SETUP) { + i2c_pdata[i].clkrate &= ~OMAP_I2C_CMDLINE_SETUP; + omap_set_i2c_constraint_func(&i2c_pdata[i]); err = omap_i2c_add_bus(i + 1); if (err) goto out; @@ -231,9 +259,11 @@ int __init omap_register_i2c_bus(int bus_id, u32 clkrate, return err; } - if (!i2c_rate[bus_id - 1]) - i2c_rate[bus_id - 1] = clkrate; - i2c_rate[bus_id - 1] &= ~OMAP_I2C_CMDLINE_SETUP; + if (!i2c_pdata[bus_id - 1].clkrate) + i2c_pdata[bus_id - 1].clkrate = clkrate; + + omap_set_i2c_constraint_func(&i2c_pdata[bus_id - 1]); + i2c_pdata[bus_id - 1].clkrate &= ~OMAP_I2C_CMDLINE_SETUP; return omap_i2c_add_bus(bus_id); } diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c index 75bf3ad..168623f 100644 --- a/drivers/i2c/busses/i2c-omap.c +++ b/drivers/i2c/busses/i2c-omap.c @@ -37,6 +37,7 @@ #include #include #include +#include /* I2C controller revisions */ #define OMAP_I2C_REV_2 0x20 @@ -165,6 +166,8 @@ struct omap_i2c_dev { struct clk *fclk; /* Functional clock */ struct completion cmd_complete; struct resource *ioarea; + void (*set_mpu_wkup_lat)(struct device *dev, + int set); u32 speed; /* Speed of bus in Khz */ u16 cmd_err; u8 *buf; @@ -526,8 +529,12 @@ static int omap_i2c_xfer_msg(struct i2c_adapter *adap, * REVISIT: We should abort the transfer on signals, but the bus goes * into arbitration and we're currently unable to recover from it. */ + if (dev->set_mpu_wkup_lat != NULL) + dev->set_mpu_wkup_lat(dev->dev, 1); r = wait_for_completion_timeout(&dev->cmd_complete, OMAP_I2C_TIMEOUT); + if (dev->set_mpu_wkup_lat != NULL) + dev->set_mpu_wkup_lat(dev->dev, 0); dev->buf_len = 0; if (r < 0) return r; @@ -844,6 +851,7 @@ omap_i2c_probe(struct platform_device *pdev) struct omap_i2c_dev *dev; struct i2c_adapter *adap; struct resource *mem, *irq, *ioarea; + struct omap_i2c_bus_platform_data *pdata = pdev->dev.platform_data; irq_handler_t isr; int r; u32 speed = 0; @@ -873,10 +881,13 @@ omap_i2c_probe(struct platform_device *pdev) goto err_release_region; } - if (pdev->dev.platform_data != NULL) - speed = *(u32 *)pdev->dev.platform_data; - else - speed = 100; /* Defualt speed */ + if (pdata != NULL) { + speed = pdata->clkrate; + dev->set_mpu_wkup_lat = pdata->set_mpu_wkup_lat; + } else { + speed = 100; /* Default speed */ + dev->set_mpu_wkup_lat = NULL; + } dev->speed = speed; dev->idle = 1; diff --git a/include/linux/i2c-omap.h b/include/linux/i2c-omap.h new file mode 100644 index 0000000..1362fba --- /dev/null +++ b/include/linux/i2c-omap.h @@ -0,0 +1,9 @@ +#ifndef __I2C_OMAP_H__ +#define __I2C_OMAP_H__ + +struct omap_i2c_bus_platform_data { + u32 clkrate; + void (*set_mpu_wkup_lat)(struct device *dev, int set); +}; + +#endif