From patchwork Wed Nov 25 18:03:49 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: kalle.jokiniemi@nokia.com X-Patchwork-Id: 62836 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 nAPG4RJi025172 for ; Wed, 25 Nov 2009 16:04:27 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753566AbZKYQET (ORCPT ); Wed, 25 Nov 2009 11:04:19 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1753727AbZKYQET (ORCPT ); Wed, 25 Nov 2009 11:04:19 -0500 Received: from smtp.nokia.com ([192.100.105.134]:45426 "EHLO mgw-mx09.nokia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753389AbZKYQES (ORCPT ); Wed, 25 Nov 2009 11:04:18 -0500 Received: from vaebh105.NOE.Nokia.com (vaebh105.europe.nokia.com [10.160.244.31]) by mgw-mx09.nokia.com (Switch-3.3.3/Switch-3.3.3) with ESMTP id nAPG42Ax025306; Wed, 25 Nov 2009 10:04:03 -0600 Received: from esebh102.NOE.Nokia.com ([172.21.138.183]) by vaebh105.NOE.Nokia.com with Microsoft SMTPSVC(6.0.3790.3959); Wed, 25 Nov 2009 18:04:01 +0200 Received: from mgw-sa01.ext.nokia.com ([147.243.1.47]) by esebh102.NOE.Nokia.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.3959); Wed, 25 Nov 2009 18:04:01 +0200 Received: from localhost.localdomain (trdhcp146219.ntc.nokia.com [172.22.146.219]) by mgw-sa01.ext.nokia.com (Switch-3.3.3/Switch-3.3.3) with ESMTP id nAPG3w6U003836; Wed, 25 Nov 2009 18:03:59 +0200 From: Kalle Jokiniemi To: ben-linux@fluff.org, linux-i2c@vger.kernel.org Cc: linux-omap@vger.kernel.org, peter.ujfalusi@nokia.com, jouni.hogander@nokia.com, khilman@deeprootsystems.com, ext Kalle Jokiniemi , Moiz Sonasath , Jarkko Nikula , Paul Walmsley , Nishanth Menon Subject: [PATCH] OMAP: I2C: Add mpu wake up latency constraint in i2c Date: Wed, 25 Nov 2009 20:03:49 +0200 Message-Id: <1259172229-25386-1-git-send-email-kalle.jokiniemi@nokia.com> X-Mailer: git-send-email 1.6.3.3 X-OriginalArrivalTime: 25 Nov 2009 16:04:01.0874 (UTC) FILETIME=[E796CB20:01CA6DE8] X-Nokia-AV: Clean 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..3c122cd 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)) +#ifdef CONFIG_ARCH_OMAP34XX +/* + * omap_i2c_set_wfc_mpu_wkup_lat - sets mpu wake up constraint + * @dev: i2c bus device pointer + * @val: latency constraint to set, -1 to disable constraint + * + * 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. + */ +static void omap_i2c_set_wfc_mpu_wkup_lat(struct device *dev, int val) +{ + omap_pm_set_max_mpu_wakeup_lat(dev, val); +} +#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 = omap_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 827da08..ac0bfd2 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,9 @@ struct omap_i2c_dev { struct clk *fclk; /* Functional clock */ struct completion cmd_complete; struct resource *ioarea; + u32 latency; /* maximum mpu wkup latency */ + void (*set_mpu_wkup_lat)(struct device *dev, + int latency); u32 speed; /* Speed of bus in Khz */ u16 cmd_err; u8 *buf; @@ -508,8 +512,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, dev->latency); 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, -1); dev->buf_len = 0; if (r < 0) return r; @@ -826,6 +834,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; @@ -855,10 +864,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; @@ -893,6 +905,11 @@ omap_i2c_probe(struct platform_device *pdev) */ dev->fifo_size = (dev->fifo_size / 2); dev->b_hw = 1; /* Enable hardware fixes */ + + /* calculate wakeup latency constraint for MPU */ + if (dev->set_mpu_wkup_lat != NULL) + dev->latency = (1000000 * dev->fifo_size) / + (1000 * speed / 8); } /* reset ASAP, clearing any IRQs */ 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