From patchwork Mon Aug 9 14:36:25 2010 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Rajendra Nayak X-Patchwork-Id: 118402 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by demeter.kernel.org (8.14.4/8.14.3) with ESMTP id o79EauCK010026 for ; Mon, 9 Aug 2010 14:36:57 GMT Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756809Ab0HIOgi (ORCPT ); Mon, 9 Aug 2010 10:36:38 -0400 Received: from arroyo.ext.ti.com ([192.94.94.40]:41475 "EHLO arroyo.ext.ti.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756714Ab0HIOge (ORCPT ); Mon, 9 Aug 2010 10:36:34 -0400 Received: from dbdp31.itg.ti.com ([172.24.170.98]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id o79EaUYQ025184 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO); Mon, 9 Aug 2010 09:36:32 -0500 Received: from linfarm476.india.ti.com (localhost [127.0.0.1]) by dbdp31.itg.ti.com (8.13.8/8.13.8) with ESMTP id o79EaS8R001870; Mon, 9 Aug 2010 20:06:28 +0530 (IST) Received: from linfarm476.india.ti.com (localhost [127.0.0.1]) by linfarm476.india.ti.com (8.12.11/8.12.11) with ESMTP id o79EaRKR026420; Mon, 9 Aug 2010 20:06:27 +0530 Received: (from x0016154@localhost) by linfarm476.india.ti.com (8.12.11/8.12.11/Submit) id o79EaR9w026418; Mon, 9 Aug 2010 20:06:27 +0530 From: Rajendra Nayak To: linux-omap@vger.kernel.org Cc: Paul Walmsley , Rajendra Nayak , Kevin Hilman Subject: [PATCH 4/5] OMAP: I2C: split device registration; convert OMAP2+ to omap_device Date: Mon, 9 Aug 2010 20:06:25 +0530 Message-Id: <1281364586-26323-4-git-send-email-rnayak@ti.com> X-Mailer: git-send-email 1.5.6.6 In-Reply-To: <1281364586-26323-3-git-send-email-rnayak@ti.com> References: <1281364586-26323-1-git-send-email-rnayak@ti.com> <1281364586-26323-2-git-send-email-rnayak@ti.com> <1281364586-26323-3-git-send-email-rnayak@ti.com> Sender: linux-omap-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-omap@vger.kernel.org X-Greylist: IP, sender and recipient auto-whitelisted, not delayed by milter-greylist-4.2.3 (demeter.kernel.org [140.211.167.41]); Mon, 09 Aug 2010 14:36:57 +0000 (UTC) diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index a5ce4f0..f58b425 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -27,18 +27,18 @@ #include #include #include +#include +#include +#include #include #include #include #include +#include #define OMAP_I2C_SIZE 0x3f #define OMAP1_I2C_BASE 0xfffb3800 -#define OMAP2_I2C_BASE1 0x48070000 -#define OMAP2_I2C_BASE2 0x48072000 -#define OMAP2_I2C_BASE3 0x48060000 -#define OMAP4_I2C_BASE4 0x48350000 static const char name[] = "i2c_omap"; @@ -55,15 +55,6 @@ static const char name[] = "i2c_omap"; static struct resource i2c_resources[][2] = { { I2C_RESOURCE_BUILDER(0, 0) }, -#if defined(CONFIG_ARCH_OMAP2PLUS) - { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE2, 0) }, -#endif -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) - { I2C_RESOURCE_BUILDER(OMAP2_I2C_BASE3, 0) }, -#endif -#if defined(CONFIG_ARCH_OMAP4) - { I2C_RESOURCE_BUILDER(OMAP4_I2C_BASE4, 0) }, -#endif }; #define I2C_DEV_BUILDER(bus_id, res, data) \ @@ -77,22 +68,19 @@ static struct resource i2c_resources[][2] = { }, \ } -static struct omap_i2c_bus_platform_data i2c_pdata[ARRAY_SIZE(i2c_resources)]; +#define MAX_OMAP_I2C_HWMOD_NAME_LEN 16 +#define OMAP_I2C_MAX_CONTROLLERS 4 +static struct omap_i2c_bus_platform_data i2c_pdata[OMAP_I2C_MAX_CONTROLLERS]; static struct platform_device omap_i2c_devices[] = { I2C_DEV_BUILDER(1, i2c_resources[0], &i2c_pdata[0]), -#if defined(CONFIG_ARCH_OMAP2PLUS) - I2C_DEV_BUILDER(2, i2c_resources[1], &i2c_pdata[1]), -#endif -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) - I2C_DEV_BUILDER(3, i2c_resources[2], &i2c_pdata[2]), -#endif -#if defined(CONFIG_ARCH_OMAP4) - I2C_DEV_BUILDER(4, i2c_resources[3], &i2c_pdata[3]), -#endif }; #define OMAP_I2C_CMDLINE_SETUP (BIT(31)) +#define I2C_ICLK 0 +#define I2C_FCLK 1 +static struct clk *omap_i2c_clks[ARRAY_SIZE(omap_i2c_devices)][2]; + static int __init omap_i2c_nr_ports(void) { int ports = 0; @@ -109,35 +97,57 @@ static int __init omap_i2c_nr_ports(void) return ports; } -/* Shared between omap2 and 3 */ -static resource_size_t omap2_i2c_irq[3] __initdata = { - INT_24XX_I2C1_IRQ, - INT_24XX_I2C2_IRQ, - INT_34XX_I2C3_IRQ, -}; +static int omap1_i2c_device_enable(struct platform_device *pdev) +{ + struct clk *c; + c = omap_i2c_clks[pdev->id - 1][I2C_ICLK]; + if (c && !IS_ERR(c)) + clk_enable(c); -static resource_size_t omap4_i2c_irq[4] __initdata = { - OMAP44XX_IRQ_I2C1, - OMAP44XX_IRQ_I2C2, - OMAP44XX_IRQ_I2C3, - OMAP44XX_IRQ_I2C4, -}; + c = omap_i2c_clks[pdev->id - 1][I2C_FCLK]; + if (c && !IS_ERR(c)) + clk_enable(c); + + return 0; +} + +static int omap1_i2c_device_idle(struct platform_device *pdev) +{ + struct clk *c; + + c = omap_i2c_clks[pdev->id - 1][I2C_FCLK]; + if (c && !IS_ERR(c)) + clk_disable(c); -static inline int omap1_i2c_add_bus(struct platform_device *pdev, int bus_id) + c = omap_i2c_clks[pdev->id - 1][I2C_ICLK]; + if (c && !IS_ERR(c)) + clk_disable(c); + + return 0; +} + +static inline int omap1_i2c_add_bus(int bus_id) { - struct omap_i2c_bus_platform_data *pd; - struct resource *res; - - pd = pdev->dev.platform_data; - res = pdev->resource; - res[0].start = OMAP1_I2C_BASE; - res[0].end = res[0].start + OMAP_I2C_SIZE; - res[1].start = INT_I2C; + struct platform_device *pdev; + struct omap_i2c_bus_platform_data *pdata; + omap1_i2c_mux_pins(bus_id); + pdev = &omap_i2c_devices[bus_id - 1]; + pdata = &i2c_pdata[bus_id - 1]; + + /* idle and shutdown share the same code */ + pdata->device_enable = omap1_i2c_device_enable; + pdata->device_idle = omap1_i2c_device_idle; + pdata->device_shutdown = omap1_i2c_device_idle; + + omap_i2c_clks[bus_id - 1][I2C_ICLK] = clk_get(&pdev->dev, "ick"); + omap_i2c_clks[bus_id - 1][I2C_FCLK] = clk_get(&pdev->dev, "fck"); + return platform_device_register(pdev); } + /* * XXX This function is a temporary compatibility wrapper - only * needed until the I2C driver can be converted to call @@ -148,52 +158,57 @@ static void omap_pm_set_max_mpu_wakeup_lat_compat(struct device *dev, long t) omap_pm_set_max_mpu_wakeup_lat(dev, t); } -static inline int omap2_i2c_add_bus(struct platform_device *pdev, int bus_id) -{ - struct resource *res; - resource_size_t *irq; +static struct omap_device_pm_latency omap_i2c_latency[] = { + [0] = { + .deactivate_func = omap_device_idle_hwmods, + .activate_func = omap_device_enable_hwmods, + .flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST, + }, +}; - res = pdev->resource; +static inline int omap2_i2c_add_bus(int bus_id) +{ + int l; + struct omap_hwmod *oh; + struct omap_device *od; + char oh_name[MAX_OMAP_I2C_HWMOD_NAME_LEN]; + struct omap_i2c_bus_platform_data *pdata; - if (!cpu_is_omap44xx()) - irq = omap2_i2c_irq; - else - irq = omap4_i2c_irq; + omap2_i2c_mux_pins(bus_id); - if (bus_id == 1) { - res[0].start = OMAP2_I2C_BASE1; - res[0].end = res[0].start + OMAP_I2C_SIZE; + l = snprintf(oh_name, MAX_OMAP_I2C_HWMOD_NAME_LEN, "i2c%d", bus_id); + WARN(l >= MAX_OMAP_I2C_HWMOD_NAME_LEN, + "String buffer overflow in I2C%d device setup\n", bus_id); + oh = omap_hwmod_lookup(oh_name); + if (!oh) { + pr_err("Could not look up %s\n", oh_name); + return -EEXIST; } - res[1].start = irq[bus_id - 1]; - omap2_i2c_mux_pins(bus_id); - + pdata = &i2c_pdata[bus_id - 1]; /* * 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. + * Only omap3 has support for constraints */ - if (cpu_is_omap34xx()) { - struct omap_i2c_bus_platform_data *pd; - - pd = pdev->dev.platform_data; - pd->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat; - } - - return platform_device_register(pdev); + if (cpu_is_omap34xx()) + pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat; + od = omap_device_build(name, bus_id, oh, pdata, + sizeof(struct omap_i2c_bus_platform_data), + omap_i2c_latency, ARRAY_SIZE(omap_i2c_latency), 0); + WARN(IS_ERR(od), "Could not build omap_device for %s\n", name); + + return PTR_ERR(od); } static int __init omap_i2c_add_bus(int bus_id) { - struct platform_device *pdev; - - pdev = &omap_i2c_devices[bus_id - 1]; - if (cpu_class_is_omap1()) - return omap1_i2c_add_bus(pdev, bus_id); + return omap1_i2c_add_bus(bus_id); else - return omap2_i2c_add_bus(pdev, bus_id); + return omap2_i2c_add_bus(bus_id); } /** diff --git a/include/linux/i2c-omap.h b/include/linux/i2c-omap.h index 78ebf50..7472449 100644 --- a/include/linux/i2c-omap.h +++ b/include/linux/i2c-omap.h @@ -1,9 +1,14 @@ #ifndef __I2C_OMAP_H__ #define __I2C_OMAP_H__ +#include + struct omap_i2c_bus_platform_data { u32 clkrate; void (*set_mpu_wkup_lat)(struct device *dev, long set); + int (*device_enable) (struct platform_device *pdev); + int (*device_shutdown) (struct platform_device *pdev); + int (*device_idle) (struct platform_device *pdev); }; #endif