From 4fe20e97c8b1082d16b38e9f4c53feeed143ab98 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Tue, 21 Sep 2010 19:37:13 +0530 Subject: OMAP3: hwmod: add I2C hwmods for OMAP3430 Add hwmod structures for I2C controllers on OMAP3430. This patch was developed in collaboration with Paul Walmsley . OMAP3 fixes for correct IDLEST bit monitoring from G, Manjunath Kondaiah Signed-off-by: Rajendra Nayak Signed-off-by: Paul Walmsley Cc: G, Manjunath Kondaiah Signed-off-by: Kevin Hilman --- arch/arm/plat-omap/include/plat/i2c.h | 13 +++++++++++++ arch/arm/plat-omap/include/plat/l4_3xxx.h | 24 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 arch/arm/plat-omap/include/plat/l4_3xxx.h (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/i2c.h b/arch/arm/plat-omap/include/plat/i2c.h index 36a0befd6168..878d632c4092 100644 --- a/arch/arm/plat-omap/include/plat/i2c.h +++ b/arch/arm/plat-omap/include/plat/i2c.h @@ -36,6 +36,19 @@ static inline int omap_register_i2c_bus(int bus_id, u32 clkrate, } #endif +/** + * i2c_dev_attr - OMAP I2C controller device attributes for omap_hwmod + * @fifo_depth: total controller FIFO size (in bytes) + * @flags: differences in hardware support capability + * + * @fifo_depth represents what exists on the hardware, not what is + * actually configured at runtime by the device driver. + */ +struct omap_i2c_dev_attr { + u8 fifo_depth; + u8 flags; +}; + void __init omap1_i2c_mux_pins(int bus_id); void __init omap2_i2c_mux_pins(int bus_id); diff --git a/arch/arm/plat-omap/include/plat/l4_3xxx.h b/arch/arm/plat-omap/include/plat/l4_3xxx.h new file mode 100644 index 000000000000..5e1949375422 --- /dev/null +++ b/arch/arm/plat-omap/include/plat/l4_3xxx.h @@ -0,0 +1,24 @@ +/* + * arch/arm/plat-omap/include/mach/l4_3xxx.h - L4 firewall definitions + * + * Copyright (C) 2009 Nokia Corporation + * Paul Walmsley + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + */ +#ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_L4_3XXX_H +#define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_L4_3XXX_H + +/* L4 CORE */ +#define OMAP3_L4_CORE_FW_I2C1_REGION 21 +#define OMAP3_L4_CORE_FW_I2C1_TA_REGION 22 +#define OMAP3_L4_CORE_FW_I2C2_REGION 23 +#define OMAP3_L4_CORE_FW_I2C2_TA_REGION 24 +#define OMAP3_L4_CORE_FW_I2C3_REGION 73 +#define OMAP3_L4_CORE_FW_I2C3_TA_REGION 74 + +#endif -- cgit v1.2.3 From 4d17aeb1c5b2375769446d13012a98e6d265ec13 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 21 Sep 2010 19:37:15 +0530 Subject: OMAP: I2C: split device registration and convert OMAP2+ to omap_device Split the OMAP1 and OMAP2+ platform_device build and register code. Convert the OMAP2+ variant to use omap_device. This patch was developed in collaboration with Rajendra Nayak . Signed-off-by: Paul Walmsley Signed-off-by: Rajendra Nayak Cc: Kevin Hilman Signed-off-by: Kevin Hilman --- arch/arm/plat-omap/i2c.c | 124 +++++++++++++++++++---------------------------- 1 file changed, 49 insertions(+), 75 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index a5ce4f0aad35..a5bff9ce7cbe 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,18 +68,11 @@ 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)) @@ -109,35 +93,20 @@ 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 resource_size_t omap4_i2c_irq[4] __initdata = { - OMAP44XX_IRQ_I2C1, - OMAP44XX_IRQ_I2C2, - OMAP44XX_IRQ_I2C3, - OMAP44XX_IRQ_I2C4, -}; - -static inline int omap1_i2c_add_bus(struct platform_device *pdev, int bus_id) +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]; + 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 +117,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); } /** -- cgit v1.2.3 From e6f168212243452eae7c0d0c20c2f6e213933fc8 Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Thu, 18 Nov 2010 19:59:47 +0200 Subject: arm: omap1: make some functions static Make some functions static to get rid of the following sparse warnings: arch/arm/mach-omap1/mcbsp.c:177:12: warning: symbol 'omap1_mcbsp_init' was not declared. Should it be static? arch/arm/mach-omap1/mux.c:346:22: warning: symbol 'omap1_cfg_reg' was not declared. Should it be static? arch/arm/plat-omap/dma.c:177:5: warning: symbol 'omap_dma_in_1510_mode' was not declared. Should it be static? arch/arm/plat-omap/sram.c:273:12: warning: symbol 'omap1_sram_init' was not declared. Should it be static? Signed-off-by: Aaro Koskinen Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 2 +- arch/arm/plat-omap/sram.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 2c2826571d45..a863f5546a6b 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -174,7 +174,7 @@ static inline void omap_enable_channel_irq(int lch); #ifdef CONFIG_ARCH_OMAP15XX /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */ -int omap_dma_in_1510_mode(void) +static int omap_dma_in_1510_mode(void) { return enable_1510_mode; } diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index e2c8eebe6b3a..93641df487a1 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -270,7 +270,7 @@ void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl) _omap_sram_reprogram_clock(dpllctl, ckctl); } -int __init omap1_sram_init(void) +static int __init omap1_sram_init(void) { _omap_sram_reprogram_clock = omap_sram_push(omap1_sram_reprogram_clock, -- cgit v1.2.3 From 1cb125caf2e0fdece14f72efbb3516f5c5fe1de9 Mon Sep 17 00:00:00 2001 From: Srinath Date: Tue, 16 Nov 2010 14:26:58 -0800 Subject: omap: AM3517/05: Add craneboard support Craneboard is a hardware development platform based on the Sitara AM3517 ARM Cortex - A8 microprocessor device. This is a low cost reference design. This patch adds basic board file. Detailed support will follow in subsequent patches. [1] http://www.ti.com/arm [2] http://www.mistralsolutions.com/products/craneboard.php Signed-off-by: Srinath Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/uncompress.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h index 9036e374e0ac..229fbf2cbd26 100644 --- a/arch/arm/plat-omap/include/plat/uncompress.h +++ b/arch/arm/plat-omap/include/plat/uncompress.h @@ -145,6 +145,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) /* omap3 based boards using UART3 */ DEBUG_LL_OMAP3(3, cm_t35); DEBUG_LL_OMAP3(3, cm_t3517); + DEBUG_LL_OMAP3(3, craneboard); DEBUG_LL_OMAP3(3, igep0020); DEBUG_LL_OMAP3(3, igep0030); DEBUG_LL_OMAP3(3, nokia_rx51); -- cgit v1.2.3 From 498cb95175c29ed96bf32f30df2d11ec1c7f3879 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Tue, 30 Nov 2010 14:11:49 -0800 Subject: OMAP: Serial: Define OMAP uart MDR1 reg and remove magic numbers Define MDR1 register serial definitions used in serial and bluetooth drivers. Change magic number to ones defined in serial_reg for omap1/2 serial driver. Remove redefined MDR1 register definitions in omap-serial driver. Signed-off-by: Andrei Emeltchenko Acked-by: G, Manjunath Kondaiah Acked-by: Govindraj.R Acked-by: Greg Kroah-Hartman Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/omap-serial.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index c8dae02f0704..6a1788014611 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h @@ -31,9 +31,6 @@ */ #define OMAP_SERIAL_NAME "ttyO" -#define OMAP_MDR1_DISABLE 0x07 -#define OMAP_MDR1_MODE13X 0x03 -#define OMAP_MDR1_MODE16X 0x00 #define OMAP_MODE13X_SPEED 230400 /* -- cgit v1.2.3 From 662b083a87a3489f3f19c6e0651c1b99b0de5df0 Mon Sep 17 00:00:00 2001 From: Andrei Emeltchenko Date: Tue, 30 Nov 2010 14:11:49 -0800 Subject: omap: Serial: Define register access modes in LCR MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Access to some registers depends on register access mode Three different modes are available for OMAP (at least) • Operational mode LCR_REG[7] = 0x0 • Configuration mode A LCR_REG[7] = 0x1 and LCR_REG[7:0]! = 0xBF • Configuration mode B LCR_REG[7] = 0x1 and LCR_REG[7:0] = 0xBF Define access modes and remove redefinitions and magic numbers in serial drivers (and later in bluetooth driver). Signed-off-by: Andrei Emeltchenko Acked-by: Govindraj.R Acked-by: Greg Kroah-Hartman Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/omap-serial.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index 6a1788014611..b3e0bad9b77e 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h @@ -33,15 +33,6 @@ #define OMAP_MODE13X_SPEED 230400 -/* - * LCR = 0XBF: Switch to Configuration Mode B. - * In configuration mode b allow access - * to EFR,DLL,DLH. - * Reference OMAP TRM Chapter 17 - * Section: 1.4.3 Mode Selection - */ -#define OMAP_UART_LCR_CONF_MDB 0XBF - /* WER = 0x7F * Enable module level wakeup in WER reg */ -- cgit v1.2.3 From d2295042b783c2b17d93cd5ab786bbfd4f2f5c90 Mon Sep 17 00:00:00 2001 From: Fernando Guzman Lugo Date: Mon, 29 Nov 2010 20:24:11 +0000 Subject: OMAP: mailbox: change full flag per mailbox queue instead of global The variable rq_full flag is a global variable, so if there are multiple mailbox users there will be conflicts. Now there is a full flag per mailbox queue. Reported-by: Ohad Ben-Cohen Signed-off-by: Fernando Guzman Lugo Signed-off-by: Hari Kanigeri Acked-by: Hiroshi Doyu --- arch/arm/plat-omap/include/plat/mailbox.h | 1 + arch/arm/plat-omap/mailbox.c | 9 +++++++-- 2 files changed, 8 insertions(+), 2 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/mailbox.h b/arch/arm/plat-omap/include/plat/mailbox.h index 997656552109..13f2ef3ea0ff 100644 --- a/arch/arm/plat-omap/include/plat/mailbox.h +++ b/arch/arm/plat-omap/include/plat/mailbox.h @@ -48,6 +48,7 @@ struct omap_mbox_queue { struct tasklet_struct tasklet; int (*callback)(void *); struct omap_mbox *mbox; + bool full; }; struct omap_mbox { diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index d2fafb892f7f..48e161c642a5 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -33,7 +33,6 @@ static struct workqueue_struct *mboxd; static struct omap_mbox **mboxes; -static bool rq_full; static int mbox_configured; static DEFINE_MUTEX(mbox_configured_lock); @@ -148,6 +147,12 @@ static void mbox_rx_work(struct work_struct *work) if (mq->callback) mq->callback((void *)msg); + spin_lock_irq(&mq->lock); + if (mq->full) { + mq->full = false; + omap_mbox_enable_irq(mq->mbox, IRQ_RX); + } + spin_unlock_irq(&mq->lock); } } @@ -170,7 +175,7 @@ static void __mbox_rx_interrupt(struct omap_mbox *mbox) while (!mbox_fifo_empty(mbox)) { if (unlikely(kfifo_avail(&mq->fifo) < sizeof(msg))) { omap_mbox_disable_irq(mbox, IRQ_RX); - rq_full = true; + mq->full = true; goto nomem; } -- cgit v1.2.3 From ab66ac3007cb3e59fe80dfcf36aff243d3008cb9 Mon Sep 17 00:00:00 2001 From: "Kanigeri, Hari" Date: Mon, 29 Nov 2010 20:24:12 +0000 Subject: OMAP: mailbox: fix checkpatch warnings Fix the following checkpatch warnings observed in mailbox module. WARNING: please, no space for starting a line, excluding comments + fail_alloc_rxq:$ WARNING: please, no space for starting a line, excluding comments + fail_alloc_txq:$ WARNING: please, no space for starting a line, excluding comments + fail_request_irq:$ WARNING: line over 80 characters + mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size, sizeof(mbox_msg_t)); Signed-off-by: Hari Kanigeri Acked-by: Hiroshi Doyu --- arch/arm/plat-omap/mailbox.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index 48e161c642a5..d9aa87c0a921 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -281,11 +281,11 @@ static int omap_mbox_startup(struct omap_mbox *mbox) return 0; - fail_alloc_rxq: +fail_alloc_rxq: mbox_queue_free(mbox->txq); - fail_alloc_txq: +fail_alloc_txq: free_irq(mbox->irq, mbox); - fail_request_irq: +fail_request_irq: if (mbox->ops->shutdown) mbox->ops->shutdown(mbox); @@ -396,7 +396,8 @@ static int __init omap_mbox_init(void) /* kfifo size sanity check: alignment and minimal size */ mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t)); - mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size, sizeof(mbox_msg_t)); + mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size, + sizeof(mbox_msg_t)); return 0; } -- cgit v1.2.3 From a42743c26a53a2a5f2b2018a9659ab3fb604d5bc Mon Sep 17 00:00:00 2001 From: "Kanigeri, Hari" Date: Mon, 29 Nov 2010 20:24:13 +0000 Subject: OMAP: mailbox: send message in process context Schedule the Tasklet to send only when mailbox fifo is full and there are pending messages in kfifo, else send the message directly in the Process context. This would avoid needless scheduling of Tasklet for every message transfer Signed-off-by: Hari Kanigeri Acked-by: Hiroshi Doyu --- arch/arm/plat-omap/mailbox.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index d9aa87c0a921..cc58b44325f2 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -92,20 +92,25 @@ int omap_mbox_msg_send(struct omap_mbox *mbox, mbox_msg_t msg) struct omap_mbox_queue *mq = mbox->txq; int ret = 0, len; - spin_lock(&mq->lock); + spin_lock_bh(&mq->lock); if (kfifo_avail(&mq->fifo) < sizeof(msg)) { ret = -ENOMEM; goto out; } + if (kfifo_is_empty(&mq->fifo) && !__mbox_poll_for_space(mbox)) { + mbox_fifo_write(mbox, msg); + goto out; + } + len = kfifo_in(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); WARN_ON(len != sizeof(msg)); tasklet_schedule(&mbox->txq->tasklet); out: - spin_unlock(&mq->lock); + spin_unlock_bh(&mq->lock); return ret; } EXPORT_SYMBOL(omap_mbox_msg_send); -- cgit v1.2.3 From 582563074a691eb45cb22d2eca70eed8f2091c5f Mon Sep 17 00:00:00 2001 From: "Kanigeri, Hari" Date: Mon, 29 Nov 2010 20:24:14 +0000 Subject: OMAP: mailbox: add notification support for multiple readers In the current mailbox driver, the mailbox internal pointer for callback can be directly manipulated by the Users, so a second User can easily corrupt the first user's callback pointer. The initial effort to correct this issue can be referred here: https://patchwork.kernel.org/patch/107520/ Along with fixing the above stated issue, this patch adds the flexibility option to register notifications from multiple readers to the events received on a mailbox instance. The discussion regarding this can be referred here. http://www.mail-archive.com/linux-omap@vger.kernel.org/msg30671.html Signed-off-by: Hari Kanigeri Signed-off-by: Fernando Guzman Lugo Acked-by: Hiroshi Doyu --- arch/arm/plat-omap/include/plat/mailbox.h | 7 +- arch/arm/plat-omap/mailbox.c | 103 +++++++++++++++++------------- 2 files changed, 61 insertions(+), 49 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/mailbox.h b/arch/arm/plat-omap/include/plat/mailbox.h index 13f2ef3ea0ff..cc3921e9059c 100644 --- a/arch/arm/plat-omap/include/plat/mailbox.h +++ b/arch/arm/plat-omap/include/plat/mailbox.h @@ -46,7 +46,6 @@ struct omap_mbox_queue { struct kfifo fifo; struct work_struct work; struct tasklet_struct tasklet; - int (*callback)(void *); struct omap_mbox *mbox; bool full; }; @@ -58,13 +57,15 @@ struct omap_mbox { struct omap_mbox_ops *ops; struct device *dev; void *priv; + int use_count; + struct blocking_notifier_head notifier; }; int omap_mbox_msg_send(struct omap_mbox *, mbox_msg_t msg); void omap_mbox_init_seq(struct omap_mbox *); -struct omap_mbox *omap_mbox_get(const char *); -void omap_mbox_put(struct omap_mbox *); +struct omap_mbox *omap_mbox_get(const char *, struct notifier_block *nb); +void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb); int omap_mbox_register(struct device *parent, struct omap_mbox **); int omap_mbox_unregister(void); diff --git a/arch/arm/plat-omap/mailbox.c b/arch/arm/plat-omap/mailbox.c index cc58b44325f2..459b319a9fad 100644 --- a/arch/arm/plat-omap/mailbox.c +++ b/arch/arm/plat-omap/mailbox.c @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -150,8 +151,8 @@ static void mbox_rx_work(struct work_struct *work) len = kfifo_out(&mq->fifo, (unsigned char *)&msg, sizeof(msg)); WARN_ON(len != sizeof(msg)); - if (mq->callback) - mq->callback((void *)msg); + blocking_notifier_call_chain(&mq->mbox->notifier, len, + (void *)msg); spin_lock_irq(&mq->lock); if (mq->full) { mq->full = false; @@ -249,41 +250,40 @@ static int omap_mbox_startup(struct omap_mbox *mbox) int ret = 0; struct omap_mbox_queue *mq; - if (mbox->ops->startup) { - mutex_lock(&mbox_configured_lock); - if (!mbox_configured) + mutex_lock(&mbox_configured_lock); + if (!mbox_configured++) { + if (likely(mbox->ops->startup)) { ret = mbox->ops->startup(mbox); - - if (ret) { - mutex_unlock(&mbox_configured_lock); - return ret; - } - mbox_configured++; - mutex_unlock(&mbox_configured_lock); + if (unlikely(ret)) + goto fail_startup; + } else + goto fail_startup; } - ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED, - mbox->name, mbox); - if (ret) { - printk(KERN_ERR - "failed to register mailbox interrupt:%d\n", ret); - goto fail_request_irq; - } - - mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet); - if (!mq) { - ret = -ENOMEM; - goto fail_alloc_txq; - } - mbox->txq = mq; + if (!mbox->use_count++) { + ret = request_irq(mbox->irq, mbox_interrupt, IRQF_SHARED, + mbox->name, mbox); + if (unlikely(ret)) { + pr_err("failed to register mailbox interrupt:%d\n", + ret); + goto fail_request_irq; + } + mq = mbox_queue_alloc(mbox, NULL, mbox_tx_tasklet); + if (!mq) { + ret = -ENOMEM; + goto fail_alloc_txq; + } + mbox->txq = mq; - mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL); - if (!mq) { - ret = -ENOMEM; - goto fail_alloc_rxq; + mq = mbox_queue_alloc(mbox, mbox_rx_work, NULL); + if (!mq) { + ret = -ENOMEM; + goto fail_alloc_rxq; + } + mbox->rxq = mq; + mq->mbox = mbox; } - mbox->rxq = mq; - + mutex_unlock(&mbox_configured_lock); return 0; fail_alloc_rxq: @@ -293,29 +293,34 @@ fail_alloc_txq: fail_request_irq: if (mbox->ops->shutdown) mbox->ops->shutdown(mbox); - + mbox->use_count--; +fail_startup: + mbox_configured--; + mutex_unlock(&mbox_configured_lock); return ret; } static void omap_mbox_fini(struct omap_mbox *mbox) { - free_irq(mbox->irq, mbox); - tasklet_kill(&mbox->txq->tasklet); - flush_work(&mbox->rxq->work); - mbox_queue_free(mbox->txq); - mbox_queue_free(mbox->rxq); + mutex_lock(&mbox_configured_lock); + + if (!--mbox->use_count) { + free_irq(mbox->irq, mbox); + tasklet_kill(&mbox->txq->tasklet); + flush_work(&mbox->rxq->work); + mbox_queue_free(mbox->txq); + mbox_queue_free(mbox->rxq); + } - if (mbox->ops->shutdown) { - mutex_lock(&mbox_configured_lock); - if (mbox_configured > 0) - mbox_configured--; - if (!mbox_configured) + if (likely(mbox->ops->shutdown)) { + if (!--mbox_configured) mbox->ops->shutdown(mbox); - mutex_unlock(&mbox_configured_lock); } + + mutex_unlock(&mbox_configured_lock); } -struct omap_mbox *omap_mbox_get(const char *name) +struct omap_mbox *omap_mbox_get(const char *name, struct notifier_block *nb) { struct omap_mbox *mbox; int ret; @@ -334,12 +339,16 @@ struct omap_mbox *omap_mbox_get(const char *name) if (ret) return ERR_PTR(-ENODEV); + if (nb) + blocking_notifier_chain_register(&mbox->notifier, nb); + return mbox; } EXPORT_SYMBOL(omap_mbox_get); -void omap_mbox_put(struct omap_mbox *mbox) +void omap_mbox_put(struct omap_mbox *mbox, struct notifier_block *nb) { + blocking_notifier_chain_unregister(&mbox->notifier, nb); omap_mbox_fini(mbox); } EXPORT_SYMBOL(omap_mbox_put); @@ -363,6 +372,8 @@ int omap_mbox_register(struct device *parent, struct omap_mbox **list) ret = PTR_ERR(mbox->dev); goto err_out; } + + BLOCKING_INIT_NOTIFIER_HEAD(&mbox->notifier); } return 0; -- cgit v1.2.3 From 00b4ade1f1968b55bb57a91c1f09a40fc33f72a0 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 7 Dec 2010 04:30:57 +0000 Subject: OMAP1: I2C: fix device initialization Commit 4d17aeb1c5b2375769446d13012a98e6d265ec13 ("OMAP: I2C: split device registration and convert OMAP2+ to omap_device") broke I2C on OMAP1. The following messages appear at boot: i2c_omap i2c_omap.1: failure requesting irq 0 i2c_omap: probe of i2c_omap.1 failed with error -22 Investigation revealed that a chunk of code is missing from the original plat-omap/i2c.c file which configured the IRQ and base address for the I2C block on OMAP1. Upon adding this back, the OMAP1 I2C block seems to initialize correctly. Thanks to Cory Maccarrone for reporting the bug, and apologies for the breakage. Signed-off-by: Paul Walmsley Cc: Janusz Krzysztofik Tested-by: Cory Maccarrone Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/i2c.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index a5bff9ce7cbe..a6cf4e94f14c 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -97,10 +97,15 @@ static inline int omap1_i2c_add_bus(int bus_id) { struct platform_device *pdev; struct omap_i2c_bus_platform_data *pdata; + struct resource *res; omap1_i2c_mux_pins(bus_id); pdev = &omap_i2c_devices[bus_id - 1]; + res = pdev->resource; + res[0].start = OMAP1_I2C_BASE; + res[0].end = res[0].start + OMAP_I2C_SIZE; + res[1].start = INT_I2C; pdata = &i2c_pdata[bus_id - 1]; return platform_device_register(pdev); -- cgit v1.2.3 From be40f7a3d7b53c1a44e11b376b4a395d6b91f58d Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 7 Dec 2010 16:25:40 -0800 Subject: omap: Fix undefined reference to omap2_i2c_mux_pins In some cases we can get error function `omap2_i2c_add_bus': arch/arm/plat-omap/i2c.c:136: undefined reference to `omap2_i2c_mux_pins' arch/arm/plat-omap/i2c.c:141: undefined reference to `omap_hwmod_lookup' arch/arm/plat-omap/i2c.c:157: undefined reference to `omap_device_build' Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/i2c.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index a6cf4e94f14c..db9c4efd79e3 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -130,6 +130,7 @@ static struct omap_device_pm_latency omap_i2c_latency[] = { }, }; +#ifdef CONFIG_ARCH_OMAP2PLUS static inline int omap2_i2c_add_bus(int bus_id) { int l; @@ -166,6 +167,12 @@ static inline int omap2_i2c_add_bus(int bus_id) return PTR_ERR(od); } +#else +static inline int omap2_i2c_add_bus(int bus_id) +{ + return 0; +} +#endif static int __init omap_i2c_add_bus(int bus_id) { -- cgit v1.2.3 From b1cc4c55c69efed3ebbb2a13e4c77a2a1a4a6bc9 Mon Sep 17 00:00:00 2001 From: Evgeny Kuznetsov Date: Tue, 7 Dec 2010 16:25:40 -0800 Subject: omap: Ptr "isr_reg" tracked as NULL was dereferenced Value of "isr_reg" pointer is depend on configuration and GPIO method. Potentially it may have NULL value and it is dereferenced later in code. Warning and exit from function are added in this case. Signed-off-by: Evgeny Kuznetsov Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/gpio.c | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index c05c653d1674..e0e2fa725269 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -1318,6 +1318,10 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) if (bank->method == METHOD_GPIO_44XX) isr_reg = bank->base + OMAP4_GPIO_IRQSTATUS0; #endif + + if (WARN_ON(!isr_reg)) + goto exit; + while(1) { u32 isr_saved, level_mask = 0; u32 enabled; @@ -1377,6 +1381,7 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) configured, we must unmask the bank interrupt only after handler(s) are executed in order to avoid spurious bank interrupt */ +exit: if (!unmasked) desc->chip->unmask(irq); -- cgit v1.2.3 From 5f3b7284cb35c9e3eead279cb35f017b9735bb43 Mon Sep 17 00:00:00 2001 From: Jarkko Nikula Date: Tue, 7 Dec 2010 16:25:40 -0800 Subject: omap: McBSP: Fix potential memory leak in omap_mcbsp_remove Function omap_mcbsp_probe allocates struct omap_mcbsp *mcbsp but it is not freed in omap_mcbsp_remove. Fix this, remove unneeded structure cleanups and clk_disable calls since they are not needed here. This is not problem currently but becomes if the mcbsp driver is ever modularized. Signed-off-by: Jarkko Nikula Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/mcbsp.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index eac4b978e9fd..f79090cb823b 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -1836,17 +1836,11 @@ static int __devexit omap_mcbsp_remove(struct platform_device *pdev) omap34xx_device_exit(mcbsp); - clk_disable(mcbsp->fclk); - clk_disable(mcbsp->iclk); clk_put(mcbsp->fclk); clk_put(mcbsp->iclk); iounmap(mcbsp->io_base); - - mcbsp->fclk = NULL; - mcbsp->iclk = NULL; - mcbsp->free = 0; - mcbsp->dev = NULL; + kfree(mcbsp); } return 0; -- cgit v1.2.3 From 6722a7238d062b747fc03b35d3371b935bcc965d Mon Sep 17 00:00:00 2001 From: Shubhrajyoti D Date: Tue, 7 Dec 2010 16:25:41 -0800 Subject: omap: McBSP: Make the free variable update more readable Using true/false instead of 1/0 to update the free variable. Signed-off-by: Shubhrajyoti D Acked-by: Jarkko Nikula Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/mcbsp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index f79090cb823b..fdecd339d4f8 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -755,7 +755,7 @@ int omap_mcbsp_request(unsigned int id) goto err_kfree; } - mcbsp->free = 0; + mcbsp->free = false; mcbsp->reg_cache = reg_cache; spin_unlock(&mcbsp->lock); @@ -815,7 +815,7 @@ err_clk_disable: clk_disable(mcbsp->iclk); spin_lock(&mcbsp->lock); - mcbsp->free = 1; + mcbsp->free = true; mcbsp->reg_cache = NULL; err_kfree: spin_unlock(&mcbsp->lock); @@ -858,7 +858,7 @@ void omap_mcbsp_free(unsigned int id) if (mcbsp->free) dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id); else - mcbsp->free = 1; + mcbsp->free = true; mcbsp->reg_cache = NULL; spin_unlock(&mcbsp->lock); @@ -1771,7 +1771,7 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev) spin_lock_init(&mcbsp->lock); mcbsp->id = id + 1; - mcbsp->free = 1; + mcbsp->free = true; mcbsp->dma_tx_lch = -1; mcbsp->dma_rx_lch = -1; -- cgit v1.2.3 From 2fae7fbed072705d91e09ed393b2e580b2d895fc Mon Sep 17 00:00:00 2001 From: "Varadarajan, Charulatha" Date: Tue, 7 Dec 2010 16:26:55 -0800 Subject: OMAP: GPIO: prepare for platform driver Prepare for implementing GPIO as a platform driver. Modifies omap_gpio_init() to make use of omap_gpio_chip_init() and omap_gpio_mod_init(). omap_gpio_mod_init() does the module init by clearing the status register and initializing the GPIO control register. omap_gpio_chip_init() initializes the chip request, free, get, set and other function pointers and sets the gpio irq handler. This is only to reorganize the code so that the "omap gpio platform driver implementation patch" looks cleaner and better to review. Signed-off-by: Charulatha V Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/gpio.c | 234 +++++++++++++++++++++++----------------------- 1 file changed, 118 insertions(+), 116 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index e0e2fa725269..48bccf2001eb 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -190,14 +190,12 @@ struct gpio_bank { u32 suspend_wakeup; u32 saved_wakeup; #endif -#ifdef CONFIG_ARCH_OMAP2PLUS u32 non_wakeup_gpios; u32 enabled_non_wakeup_gpios; u32 saved_datain; u32 saved_fallingdetect; u32 saved_risingdetect; -#endif u32 level_mask; u32 toggle_mask; spinlock_t lock; @@ -1718,10 +1716,125 @@ static void __init omap_gpio_show_rev(void) */ static struct lock_class_key gpio_lock_class; +static void omap_gpio_mod_init(struct gpio_bank *bank, int id) +{ + if (cpu_class_is_omap2()) { + if (cpu_is_omap44xx()) { + __raw_writel(0xffffffff, bank->base + + OMAP4_GPIO_IRQSTATUSCLR0); + __raw_writel(0x00000000, bank->base + + OMAP4_GPIO_DEBOUNCENABLE); + /* Initialize interface clk ungated, module enabled */ + __raw_writel(0, bank->base + OMAP4_GPIO_CTRL); + } else if (cpu_is_omap34xx()) { + __raw_writel(0x00000000, bank->base + + OMAP24XX_GPIO_IRQENABLE1); + __raw_writel(0xffffffff, bank->base + + OMAP24XX_GPIO_IRQSTATUS1); + __raw_writel(0x00000000, bank->base + + OMAP24XX_GPIO_DEBOUNCE_EN); + + /* Initialize interface clk ungated, module enabled */ + __raw_writel(0, bank->base + OMAP24XX_GPIO_CTRL); + } else if (cpu_is_omap24xx()) { + static const u32 non_wakeup_gpios[] = { + 0xe203ffc0, 0x08700040 + }; + if (id < ARRAY_SIZE(non_wakeup_gpios)) + bank->non_wakeup_gpios = non_wakeup_gpios[id]; + } + } else if (cpu_class_is_omap1()) { + if (bank_is_mpuio(bank)) + __raw_writew(0xffff, bank->base + + OMAP_MPUIO_GPIO_MASKIT); + if (cpu_is_omap15xx() && bank->method == METHOD_GPIO_1510) { + __raw_writew(0xffff, bank->base + + OMAP1510_GPIO_INT_MASK); + __raw_writew(0x0000, bank->base + + OMAP1510_GPIO_INT_STATUS); + } + if (cpu_is_omap16xx() && bank->method == METHOD_GPIO_1610) { + __raw_writew(0x0000, bank->base + + OMAP1610_GPIO_IRQENABLE1); + __raw_writew(0xffff, bank->base + + OMAP1610_GPIO_IRQSTATUS1); + __raw_writew(0x0014, bank->base + + OMAP1610_GPIO_SYSCONFIG); + + /* + * Enable system clock for GPIO module. + * The CAM_CLK_CTRL *is* really the right place. + */ + omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, + ULPD_CAM_CLK_CTRL); + } + if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_7XX) { + __raw_writel(0xffffffff, bank->base + + OMAP7XX_GPIO_INT_MASK); + __raw_writel(0x00000000, bank->base + + OMAP7XX_GPIO_INT_STATUS); + } + } +} + +static void __init omap_gpio_chip_init(struct gpio_bank *bank) +{ + int j, bank_width = 16; + static int gpio; + + if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_7XX) + bank_width = 32; /* 7xx has 32-bit GPIOs */ + + if ((bank->method == METHOD_GPIO_24XX) || + (bank->method == METHOD_GPIO_44XX)) + bank_width = 32; + + bank->mod_usage = 0; + /* + * REVISIT eventually switch from OMAP-specific gpio structs + * over to the generic ones + */ + bank->chip.request = omap_gpio_request; + bank->chip.free = omap_gpio_free; + bank->chip.direction_input = gpio_input; + bank->chip.get = gpio_get; + bank->chip.direction_output = gpio_output; + bank->chip.set_debounce = gpio_debounce; + bank->chip.set = gpio_set; + bank->chip.to_irq = gpio_2irq; + if (bank_is_mpuio(bank)) { + bank->chip.label = "mpuio"; +#ifdef CONFIG_ARCH_OMAP16XX + bank->chip.dev = &omap_mpuio_device.dev; +#endif + bank->chip.base = OMAP_MPUIO(0); + } else { + bank->chip.label = "gpio"; + bank->chip.base = gpio; + gpio += bank_width; + } + bank->chip.ngpio = bank_width; + + gpiochip_add(&bank->chip); + + for (j = bank->virtual_irq_start; + j < bank->virtual_irq_start + bank_width; j++) { + lockdep_set_class(&irq_desc[j].lock, &gpio_lock_class); + set_irq_chip_data(j, bank); + if (bank_is_mpuio(bank)) + set_irq_chip(j, &mpuio_irq_chip); + else + set_irq_chip(j, &gpio_irq_chip); + set_irq_handler(j, handle_simple_irq); + set_irq_flags(j, IRQF_VALID); + } + set_irq_chained_handler(bank->irq, gpio_irq_handler); + set_irq_data(bank->irq, bank); +} + static int __init _omap_gpio_init(void) { int i; - int gpio = 0; struct gpio_bank *bank; int bank_size = SZ_8K; /* Module 4KB + L4 4KB except on omap1 */ char clk_name[11]; @@ -1828,7 +1941,6 @@ static int __init _omap_gpio_init(void) } #endif for (i = 0; i < gpio_bank_count; i++) { - int j, gpio_count = 16; bank = &gpio_bank[i]; spin_lock_init(&bank->lock); @@ -1840,107 +1952,8 @@ static int __init _omap_gpio_init(void) continue; } - if (bank_is_mpuio(bank)) - __raw_writew(0xffff, bank->base + OMAP_MPUIO_GPIO_MASKIT); - if (cpu_is_omap15xx() && bank->method == METHOD_GPIO_1510) { - __raw_writew(0xffff, bank->base + OMAP1510_GPIO_INT_MASK); - __raw_writew(0x0000, bank->base + OMAP1510_GPIO_INT_STATUS); - } - if (cpu_is_omap16xx() && bank->method == METHOD_GPIO_1610) { - __raw_writew(0x0000, bank->base + OMAP1610_GPIO_IRQENABLE1); - __raw_writew(0xffff, bank->base + OMAP1610_GPIO_IRQSTATUS1); - __raw_writew(0x0014, bank->base + OMAP1610_GPIO_SYSCONFIG); - } - if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_7XX) { - __raw_writel(0xffffffff, bank->base + OMAP7XX_GPIO_INT_MASK); - __raw_writel(0x00000000, bank->base + OMAP7XX_GPIO_INT_STATUS); - - gpio_count = 32; /* 7xx has 32-bit GPIOs */ - } - -#ifdef CONFIG_ARCH_OMAP2PLUS - if ((bank->method == METHOD_GPIO_24XX) || - (bank->method == METHOD_GPIO_44XX)) { - static const u32 non_wakeup_gpios[] = { - 0xe203ffc0, 0x08700040 - }; - - if (cpu_is_omap44xx()) { - __raw_writel(0xffffffff, bank->base + - OMAP4_GPIO_IRQSTATUSCLR0); - __raw_writew(0x0015, bank->base + - OMAP4_GPIO_SYSCONFIG); - __raw_writel(0x00000000, bank->base + - OMAP4_GPIO_DEBOUNCENABLE); - /* - * Initialize interface clock ungated, - * module enabled - */ - __raw_writel(0, bank->base + OMAP4_GPIO_CTRL); - } else { - __raw_writel(0x00000000, bank->base + - OMAP24XX_GPIO_IRQENABLE1); - __raw_writel(0xffffffff, bank->base + - OMAP24XX_GPIO_IRQSTATUS1); - __raw_writew(0x0015, bank->base + - OMAP24XX_GPIO_SYSCONFIG); - __raw_writel(0x00000000, bank->base + - OMAP24XX_GPIO_DEBOUNCE_EN); - - /* - * Initialize interface clock ungated, - * module enabled - */ - __raw_writel(0, bank->base + - OMAP24XX_GPIO_CTRL); - } - if (cpu_is_omap24xx() && - i < ARRAY_SIZE(non_wakeup_gpios)) - bank->non_wakeup_gpios = non_wakeup_gpios[i]; - gpio_count = 32; - } -#endif - - bank->mod_usage = 0; - /* REVISIT eventually switch from OMAP-specific gpio structs - * over to the generic ones - */ - bank->chip.request = omap_gpio_request; - bank->chip.free = omap_gpio_free; - bank->chip.direction_input = gpio_input; - bank->chip.get = gpio_get; - bank->chip.direction_output = gpio_output; - bank->chip.set_debounce = gpio_debounce; - bank->chip.set = gpio_set; - bank->chip.to_irq = gpio_2irq; - if (bank_is_mpuio(bank)) { - bank->chip.label = "mpuio"; -#ifdef CONFIG_ARCH_OMAP16XX - bank->chip.dev = &omap_mpuio_device.dev; -#endif - bank->chip.base = OMAP_MPUIO(0); - } else { - bank->chip.label = "gpio"; - bank->chip.base = gpio; - gpio += gpio_count; - } - bank->chip.ngpio = gpio_count; - - gpiochip_add(&bank->chip); - - for (j = bank->virtual_irq_start; - j < bank->virtual_irq_start + gpio_count; j++) { - lockdep_set_class(&irq_desc[j].lock, &gpio_lock_class); - set_irq_chip_data(j, bank); - if (bank_is_mpuio(bank)) - set_irq_chip(j, &mpuio_irq_chip); - else - set_irq_chip(j, &gpio_irq_chip); - set_irq_handler(j, handle_simple_irq); - set_irq_flags(j, IRQF_VALID); - } - set_irq_chained_handler(bank->irq, gpio_irq_handler); - set_irq_data(bank->irq, bank); + omap_gpio_mod_init(bank, i); + omap_gpio_chip_init(bank); if (cpu_is_omap34xx() || cpu_is_omap44xx()) { sprintf(clk_name, "gpio%d_dbck", i + 1); @@ -1950,17 +1963,6 @@ static int __init _omap_gpio_init(void) } } - /* Enable system clock for GPIO module. - * The CAM_CLK_CTRL *is* really the right place. */ - if (cpu_is_omap16xx()) - omap_writel(omap_readl(ULPD_CAM_CLK_CTRL) | 0x04, ULPD_CAM_CLK_CTRL); - - /* Enable autoidle for the OCP interface */ - if (cpu_is_omap24xx()) - omap_writel(1 << 0, 0x48019010); - if (cpu_is_omap34xx()) - omap_writel(1 << 0, 0x48306814); - omap_gpio_show_rev(); return 0; -- cgit v1.2.3 From 9a748053f5f58a77cd71864f1d7b804175b0e47d Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 7 Dec 2010 16:26:56 -0800 Subject: OMAP: GPIO: Make omap_gpio_show_rev bank specific Otherwise GPIO init on 16xx may try to access uninitialized GPIO bank as the MPUIO bank does not have a revision register. Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/gpio.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 48bccf2001eb..e4741905285b 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -1694,16 +1694,16 @@ static struct clk * gpio5_fck; static struct clk *gpio_iclks[OMAP34XX_NR_GPIOS]; #endif -static void __init omap_gpio_show_rev(void) +static void __init omap_gpio_show_rev(struct gpio_bank *bank) { u32 rev; - if (cpu_is_omap16xx()) - rev = __raw_readw(gpio_bank[1].base + OMAP1610_GPIO_REVISION); + if (cpu_is_omap16xx() && !(bank->method != METHOD_MPUIO)) + rev = __raw_readw(bank->base + OMAP1610_GPIO_REVISION); else if (cpu_is_omap24xx() || cpu_is_omap34xx()) - rev = __raw_readl(gpio_bank[0].base + OMAP24XX_GPIO_REVISION); + rev = __raw_readl(bank->base + OMAP24XX_GPIO_REVISION); else if (cpu_is_omap44xx()) - rev = __raw_readl(gpio_bank[0].base + OMAP4_GPIO_REVISION); + rev = __raw_readl(bank->base + OMAP4_GPIO_REVISION); else return; @@ -1963,7 +1963,7 @@ static int __init _omap_gpio_init(void) } } - omap_gpio_show_rev(); + omap_gpio_show_rev(bank); return 0; } -- cgit v1.2.3 From c95d10bc49d50a9bc0f63a6eae79bb2707dabfdc Mon Sep 17 00:00:00 2001 From: "Varadarajan, Charulatha" Date: Tue, 7 Dec 2010 16:26:56 -0800 Subject: OMAP15xx: GPIO: Introduce support for GPIO init Add support for handling OMAP15xx specific gpio_init by providing platform device data and doing device registration. Signed-off-by: Charulatha V Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/gpio.c | 10 ++-------- arch/arm/plat-omap/include/plat/gpio.h | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+), 8 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index e4741905285b..2b0d90109828 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -205,13 +205,6 @@ struct gpio_bank { u32 dbck_enable_mask; }; -#define METHOD_MPUIO 0 -#define METHOD_GPIO_1510 1 -#define METHOD_GPIO_1610 2 -#define METHOD_GPIO_7XX 3 -#define METHOD_GPIO_24XX 5 -#define METHOD_GPIO_44XX 6 - #ifdef CONFIG_ARCH_OMAP16XX static struct gpio_bank gpio_bank_1610[5] = { { OMAP1_MPUIO_VBASE, NULL, INT_MPUIO, IH_MPUIO_BASE, @@ -335,7 +328,8 @@ static struct gpio_bank gpio_bank_44xx[6] = { #endif static struct gpio_bank *gpio_bank; -static int gpio_bank_count; +/* TODO: Analyze removing gpio_bank_count usage from driver code */ +int gpio_bank_count; static inline struct gpio_bank *get_gpio_bank(int gpio) { diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index de1c604962eb..5bef86d76a6a 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -27,6 +27,7 @@ #define __ASM_ARCH_OMAP_GPIO_H #include +#include #include #define OMAP1_MPUIO_BASE 0xfffb5000 @@ -71,6 +72,23 @@ IH_MPUIO_BASE + ((nr) & 0x0f) : \ IH_GPIO_BASE + (nr)) +#define METHOD_MPUIO 0 +#define METHOD_GPIO_1510 1 +#define METHOD_GPIO_1610 2 +#define METHOD_GPIO_7XX 3 +#define METHOD_GPIO_24XX 5 +#define METHOD_GPIO_44XX 6 + +struct omap_gpio_platform_data { + u16 virtual_irq_start; + int bank_type; + int bank_width; /* GPIO bank width */ + bool dbck_flag; /* dbck required or not - True for OMAP3&4 */ +}; + +/* TODO: Analyze removing gpio_bank_count usage from driver code */ +extern int gpio_bank_count; + extern int omap_gpio_init(void); /* Call from board init only */ extern void omap2_gpio_prepare_for_idle(int power_state); extern void omap2_gpio_resume_after_idle(void); -- cgit v1.2.3 From 59c348c38fbe85e6e86c711b9a38c37315008d9e Mon Sep 17 00:00:00 2001 From: "Varadarajan, Charulatha" Date: Tue, 7 Dec 2010 16:26:56 -0800 Subject: OMAP2420: hwmod data: Add GPIO Add GPIO hwmod data for OMAP2420 and add the required GPIO device attributes in the gpio header file Also remove "omap24xx.h" header file as it is not required anymore. Signed-off-by: Charulatha V Acked-by: Benoit Cousson Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/gpio.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index 5bef86d76a6a..24892a6707c4 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -79,6 +79,11 @@ #define METHOD_GPIO_24XX 5 #define METHOD_GPIO_44XX 6 +struct omap_gpio_dev_attr { + int bank_width; /* GPIO bank width */ + bool dbck_flag; /* dbck required or not - True for OMAP3&4 */ +}; + struct omap_gpio_platform_data { u16 virtual_irq_start; int bank_type; -- cgit v1.2.3 From 77640aabd7558e43b65bc1a0311be2dbb42c3ff8 Mon Sep 17 00:00:00 2001 From: "Varadarajan, Charulatha" Date: Tue, 7 Dec 2010 16:26:57 -0800 Subject: OMAP: GPIO: Implement GPIO as a platform device Implement GPIO as a platform device. GPIO APIs are used in machine_init functions. Hence it is required to complete GPIO probe before board_init. Therefore GPIO device register and driver register are implemented as postcore_initcalls. omap_gpio_init() does nothing now and this function would be removed in the next patch as it's usage is spread across most of the board files. Inorder to convert GPIO as platform device, modifications are required in clockxxxx_data.c file for OMAP1 so that device names can be used to obtain clock instead of getting clocks by name/NULL ptr. Use runtime pm APIs (pm_runtime_put*/pm_runtime_get*) for enabling or disabling the clocks, modify sysconfig settings and remove usage of clock FW APIs. Note 1: Converting GPIO driver to use runtime PM APIs is not done as a separate patch because GPIO clock names are different for various OMAPs and are different for some of the banks in the same CPU. This would need usage of cpu_is checks and bank id checks while using clock FW APIs in the gpio driver. Hence while making GPIO a platform driver framework, PM runtime APIs are used directly. Note 2: While implementing GPIO as a platform device, pm runtime APIs are used as mentioned above and modification is not done in gpio's prepare for idle/ resume after idle functions. This would be done in the next patch series and GPIO driver would be made to use dev_pm_ops instead of sysdev_class in that series only. Due to the above, the GPIO driver implicitly relies on CM_AUTOIDLE = 1 on its iclk for power management to work, since the driver never disables its iclk. This would be taken care in the next patch series (see Note 3 below). Refer to http://www.mail-archive.com/linux-omap@vger.kernel.org/msg39112.html for more details. Note 3: only pm_runtime_get_sync is called in gpio's probe() and pm_runtime_put* is never called. This is to make the implementation similar to the existing GPIO code. Another patch series would be sent to correct this. In OMAP3 and OMAP4 gpio's debounce clocks are optional clocks. They are enabled/ disabled whenever required using clock framework APIs TODO: 1. Cleanup the GPIO driver. Use function pointers and register offest pointers instead of using hardcoded values 2. Remove all cpu_is_ checks and OMAP specific macros 3. Remove usage of gpio_bank array so that only instance specific information is used in driver code 4. Rename 'method'/ avoid it's usage 5. Fix the non-wakeup gpios handling for OMAP2430, OMAP3 & OMAP4 6. Modify gpio's prepare for idle/ resume after idle functions to use runtime pm implentation. Signed-off-by: Charulatha V Signed-off-by: Rajendra Nayak Reviewed-by: Basak, Partha Acked-by: Kevin Hilman [tony@atomide.com: updated for bank specific revision and updated boards] Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/gpio.c | 413 ++++++++------------------------- arch/arm/plat-omap/include/plat/gpio.h | 1 - 2 files changed, 98 insertions(+), 316 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 2b0d90109828..6f53dee98a91 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include #include @@ -32,7 +34,6 @@ /* * OMAP1510 GPIO registers */ -#define OMAP1510_GPIO_BASE 0xfffce000 #define OMAP1510_GPIO_DATA_INPUT 0x00 #define OMAP1510_GPIO_DATA_OUTPUT 0x04 #define OMAP1510_GPIO_DIR_CONTROL 0x08 @@ -46,10 +47,6 @@ /* * OMAP1610 specific GPIO registers */ -#define OMAP1610_GPIO1_BASE 0xfffbe400 -#define OMAP1610_GPIO2_BASE 0xfffbec00 -#define OMAP1610_GPIO3_BASE 0xfffbb400 -#define OMAP1610_GPIO4_BASE 0xfffbbc00 #define OMAP1610_GPIO_REVISION 0x0000 #define OMAP1610_GPIO_SYSCONFIG 0x0010 #define OMAP1610_GPIO_SYSSTATUS 0x0014 @@ -71,12 +68,6 @@ /* * OMAP7XX specific GPIO registers */ -#define OMAP7XX_GPIO1_BASE 0xfffbc000 -#define OMAP7XX_GPIO2_BASE 0xfffbc800 -#define OMAP7XX_GPIO3_BASE 0xfffbd000 -#define OMAP7XX_GPIO4_BASE 0xfffbd800 -#define OMAP7XX_GPIO5_BASE 0xfffbe000 -#define OMAP7XX_GPIO6_BASE 0xfffbe800 #define OMAP7XX_GPIO_DATA_INPUT 0x00 #define OMAP7XX_GPIO_DATA_OUTPUT 0x04 #define OMAP7XX_GPIO_DIR_CONTROL 0x08 @@ -84,25 +75,10 @@ #define OMAP7XX_GPIO_INT_MASK 0x10 #define OMAP7XX_GPIO_INT_STATUS 0x14 -#define OMAP1_MPUIO_VBASE OMAP1_MPUIO_BASE - /* - * omap24xx specific GPIO registers + * omap2+ specific GPIO registers */ -#define OMAP242X_GPIO1_BASE 0x48018000 -#define OMAP242X_GPIO2_BASE 0x4801a000 -#define OMAP242X_GPIO3_BASE 0x4801c000 -#define OMAP242X_GPIO4_BASE 0x4801e000 - -#define OMAP243X_GPIO1_BASE 0x4900C000 -#define OMAP243X_GPIO2_BASE 0x4900E000 -#define OMAP243X_GPIO3_BASE 0x49010000 -#define OMAP243X_GPIO4_BASE 0x49012000 -#define OMAP243X_GPIO5_BASE 0x480B6000 - #define OMAP24XX_GPIO_REVISION 0x0000 -#define OMAP24XX_GPIO_SYSCONFIG 0x0010 -#define OMAP24XX_GPIO_SYSSTATUS 0x0014 #define OMAP24XX_GPIO_IRQSTATUS1 0x0018 #define OMAP24XX_GPIO_IRQSTATUS2 0x0028 #define OMAP24XX_GPIO_IRQENABLE2 0x002c @@ -126,7 +102,6 @@ #define OMAP24XX_GPIO_SETDATAOUT 0x0094 #define OMAP4_GPIO_REVISION 0x0000 -#define OMAP4_GPIO_SYSCONFIG 0x0010 #define OMAP4_GPIO_EOI 0x0020 #define OMAP4_GPIO_IRQSTATUSRAW0 0x0024 #define OMAP4_GPIO_IRQSTATUSRAW1 0x0028 @@ -138,7 +113,6 @@ #define OMAP4_GPIO_IRQSTATUSCLR1 0x0040 #define OMAP4_GPIO_IRQWAKEN0 0x0044 #define OMAP4_GPIO_IRQWAKEN1 0x0048 -#define OMAP4_GPIO_SYSSTATUS 0x0114 #define OMAP4_GPIO_IRQENABLE1 0x011c #define OMAP4_GPIO_WAKE_EN 0x0120 #define OMAP4_GPIO_IRQSTATUS2 0x0128 @@ -159,26 +133,6 @@ #define OMAP4_GPIO_SETWKUENA 0x0184 #define OMAP4_GPIO_CLEARDATAOUT 0x0190 #define OMAP4_GPIO_SETDATAOUT 0x0194 -/* - * omap34xx specific GPIO registers - */ - -#define OMAP34XX_GPIO1_BASE 0x48310000 -#define OMAP34XX_GPIO2_BASE 0x49050000 -#define OMAP34XX_GPIO3_BASE 0x49052000 -#define OMAP34XX_GPIO4_BASE 0x49054000 -#define OMAP34XX_GPIO5_BASE 0x49056000 -#define OMAP34XX_GPIO6_BASE 0x49058000 - -/* - * OMAP44XX specific GPIO registers - */ -#define OMAP44XX_GPIO1_BASE 0x4a310000 -#define OMAP44XX_GPIO2_BASE 0x48055000 -#define OMAP44XX_GPIO3_BASE 0x48057000 -#define OMAP44XX_GPIO4_BASE 0x48059000 -#define OMAP44XX_GPIO5_BASE 0x4805B000 -#define OMAP44XX_GPIO6_BASE 0x4805D000 struct gpio_bank { unsigned long pbase; @@ -203,97 +157,12 @@ struct gpio_bank { struct clk *dbck; u32 mod_usage; u32 dbck_enable_mask; + struct device *dev; + bool dbck_flag; }; -#ifdef CONFIG_ARCH_OMAP16XX -static struct gpio_bank gpio_bank_1610[5] = { - { OMAP1_MPUIO_VBASE, NULL, INT_MPUIO, IH_MPUIO_BASE, - METHOD_MPUIO }, - { OMAP1610_GPIO1_BASE, NULL, INT_GPIO_BANK1, IH_GPIO_BASE, - METHOD_GPIO_1610 }, - { OMAP1610_GPIO2_BASE, NULL, INT_1610_GPIO_BANK2, IH_GPIO_BASE + 16, - METHOD_GPIO_1610 }, - { OMAP1610_GPIO3_BASE, NULL, INT_1610_GPIO_BANK3, IH_GPIO_BASE + 32, - METHOD_GPIO_1610 }, - { OMAP1610_GPIO4_BASE, NULL, INT_1610_GPIO_BANK4, IH_GPIO_BASE + 48, - METHOD_GPIO_1610 }, -}; -#endif - -#ifdef CONFIG_ARCH_OMAP15XX -static struct gpio_bank gpio_bank_1510[2] = { - { OMAP1_MPUIO_VBASE, NULL, INT_MPUIO, IH_MPUIO_BASE, - METHOD_MPUIO }, - { OMAP1510_GPIO_BASE, NULL, INT_GPIO_BANK1, IH_GPIO_BASE, - METHOD_GPIO_1510 } -}; -#endif - -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) -static struct gpio_bank gpio_bank_7xx[7] = { - { OMAP1_MPUIO_VBASE, NULL, INT_7XX_MPUIO, IH_MPUIO_BASE, - METHOD_MPUIO }, - { OMAP7XX_GPIO1_BASE, NULL, INT_7XX_GPIO_BANK1, IH_GPIO_BASE, - METHOD_GPIO_7XX }, - { OMAP7XX_GPIO2_BASE, NULL, INT_7XX_GPIO_BANK2, IH_GPIO_BASE + 32, - METHOD_GPIO_7XX }, - { OMAP7XX_GPIO3_BASE, NULL, INT_7XX_GPIO_BANK3, IH_GPIO_BASE + 64, - METHOD_GPIO_7XX }, - { OMAP7XX_GPIO4_BASE, NULL, INT_7XX_GPIO_BANK4, IH_GPIO_BASE + 96, - METHOD_GPIO_7XX }, - { OMAP7XX_GPIO5_BASE, NULL, INT_7XX_GPIO_BANK5, IH_GPIO_BASE + 128, - METHOD_GPIO_7XX }, - { OMAP7XX_GPIO6_BASE, NULL, INT_7XX_GPIO_BANK6, IH_GPIO_BASE + 160, - METHOD_GPIO_7XX }, -}; -#endif - -#ifdef CONFIG_ARCH_OMAP2 - -static struct gpio_bank gpio_bank_242x[4] = { - { OMAP242X_GPIO1_BASE, NULL, INT_24XX_GPIO_BANK1, IH_GPIO_BASE, - METHOD_GPIO_24XX }, - { OMAP242X_GPIO2_BASE, NULL, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32, - METHOD_GPIO_24XX }, - { OMAP242X_GPIO3_BASE, NULL, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64, - METHOD_GPIO_24XX }, - { OMAP242X_GPIO4_BASE, NULL, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96, - METHOD_GPIO_24XX }, -}; - -static struct gpio_bank gpio_bank_243x[5] = { - { OMAP243X_GPIO1_BASE, NULL, INT_24XX_GPIO_BANK1, IH_GPIO_BASE, - METHOD_GPIO_24XX }, - { OMAP243X_GPIO2_BASE, NULL, INT_24XX_GPIO_BANK2, IH_GPIO_BASE + 32, - METHOD_GPIO_24XX }, - { OMAP243X_GPIO3_BASE, NULL, INT_24XX_GPIO_BANK3, IH_GPIO_BASE + 64, - METHOD_GPIO_24XX }, - { OMAP243X_GPIO4_BASE, NULL, INT_24XX_GPIO_BANK4, IH_GPIO_BASE + 96, - METHOD_GPIO_24XX }, - { OMAP243X_GPIO5_BASE, NULL, INT_24XX_GPIO_BANK5, IH_GPIO_BASE + 128, - METHOD_GPIO_24XX }, -}; - -#endif - #ifdef CONFIG_ARCH_OMAP3 -static struct gpio_bank gpio_bank_34xx[6] = { - { OMAP34XX_GPIO1_BASE, NULL, INT_34XX_GPIO_BANK1, IH_GPIO_BASE, - METHOD_GPIO_24XX }, - { OMAP34XX_GPIO2_BASE, NULL, INT_34XX_GPIO_BANK2, IH_GPIO_BASE + 32, - METHOD_GPIO_24XX }, - { OMAP34XX_GPIO3_BASE, NULL, INT_34XX_GPIO_BANK3, IH_GPIO_BASE + 64, - METHOD_GPIO_24XX }, - { OMAP34XX_GPIO4_BASE, NULL, INT_34XX_GPIO_BANK4, IH_GPIO_BASE + 96, - METHOD_GPIO_24XX }, - { OMAP34XX_GPIO5_BASE, NULL, INT_34XX_GPIO_BANK5, IH_GPIO_BASE + 128, - METHOD_GPIO_24XX }, - { OMAP34XX_GPIO6_BASE, NULL, INT_34XX_GPIO_BANK6, IH_GPIO_BASE + 160, - METHOD_GPIO_24XX }, -}; - struct omap3_gpio_regs { - u32 sysconfig; u32 irqenable1; u32 irqenable2; u32 wake_en; @@ -309,25 +178,14 @@ struct omap3_gpio_regs { static struct omap3_gpio_regs gpio_context[OMAP34XX_NR_GPIOS]; #endif -#ifdef CONFIG_ARCH_OMAP4 -static struct gpio_bank gpio_bank_44xx[6] = { - { OMAP44XX_GPIO1_BASE, NULL, OMAP44XX_IRQ_GPIO1, IH_GPIO_BASE, - METHOD_GPIO_44XX }, - { OMAP44XX_GPIO2_BASE, NULL, OMAP44XX_IRQ_GPIO2, IH_GPIO_BASE + 32, - METHOD_GPIO_44XX }, - { OMAP44XX_GPIO3_BASE, NULL, OMAP44XX_IRQ_GPIO3, IH_GPIO_BASE + 64, - METHOD_GPIO_44XX }, - { OMAP44XX_GPIO4_BASE, NULL, OMAP44XX_IRQ_GPIO4, IH_GPIO_BASE + 96, - METHOD_GPIO_44XX }, - { OMAP44XX_GPIO5_BASE, NULL, OMAP44XX_IRQ_GPIO5, IH_GPIO_BASE + 128, - METHOD_GPIO_44XX }, - { OMAP44XX_GPIO6_BASE, NULL, OMAP44XX_IRQ_GPIO6, IH_GPIO_BASE + 160, - METHOD_GPIO_44XX }, -}; +/* + * TODO: Cleanup gpio_bank usage as it is having information + * related to all instances of the device + */ +static struct gpio_bank *gpio_bank; -#endif +static int bank_width; -static struct gpio_bank *gpio_bank; /* TODO: Analyze removing gpio_bank_count usage from driver code */ int gpio_bank_count; @@ -634,6 +492,9 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, u32 val; u32 l; + if (!bank->dbck_flag) + return; + if (debounce < 32) debounce = 0x01; else if (debounce > 7936) @@ -643,7 +504,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, l = 1 << get_gpio_index(gpio); - if (cpu_is_omap44xx()) + if (bank->method == METHOD_GPIO_44XX) reg += OMAP4_GPIO_DEBOUNCINGTIME; else reg += OMAP24XX_GPIO_DEBOUNCE_VAL; @@ -651,7 +512,7 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, __raw_writel(debounce, reg); reg = bank->base; - if (cpu_is_omap44xx()) + if (bank->method == METHOD_GPIO_44XX) reg += OMAP4_GPIO_DEBOUNCENABLE; else reg += OMAP24XX_GPIO_DEBOUNCE_EN; @@ -660,12 +521,10 @@ static void _set_gpio_debounce(struct gpio_bank *bank, unsigned gpio, if (debounce) { val |= l; - if (cpu_is_omap34xx() || cpu_is_omap44xx()) - clk_enable(bank->dbck); + clk_enable(bank->dbck); } else { val &= ~l; - if (cpu_is_omap34xx() || cpu_is_omap44xx()) - clk_disable(bank->dbck); + clk_disable(bank->dbck); } bank->dbck_enable_mask = val; @@ -1537,7 +1396,8 @@ static struct platform_device omap_mpuio_device = { static inline void mpuio_init(void) { - platform_set_drvdata(&omap_mpuio_device, &gpio_bank_1610[0]); + struct gpio_bank *bank = get_gpio_bank(OMAP_MPUIO(0)); + platform_set_drvdata(&omap_mpuio_device, bank); if (platform_driver_register(&omap_mpuio_driver) == 0) (void) platform_device_register(&omap_mpuio_device); @@ -1642,6 +1502,13 @@ static int gpio_debounce(struct gpio_chip *chip, unsigned offset, unsigned long flags; bank = container_of(chip, struct gpio_bank, chip); + + if (!bank->dbck) { + bank->dbck = clk_get(bank->dev, "dbclk"); + if (IS_ERR(bank->dbck)) + dev_err(bank->dev, "Could not get gpio dbck\n"); + } + spin_lock_irqsave(&bank->lock, flags); _set_gpio_debounce(bank, offset, debounce); spin_unlock_irqrestore(&bank->lock, flags); @@ -1670,24 +1537,6 @@ static int gpio_2irq(struct gpio_chip *chip, unsigned offset) /*---------------------------------------------------------------------*/ -static int initialized; -#if defined(CONFIG_ARCH_OMAP1) || defined(CONFIG_ARCH_OMAP2) -static struct clk * gpio_ick; -#endif - -#if defined(CONFIG_ARCH_OMAP2) -static struct clk * gpio_fck; -#endif - -#if defined(CONFIG_ARCH_OMAP2430) -static struct clk * gpio5_ick; -static struct clk * gpio5_fck; -#endif - -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) -static struct clk *gpio_iclks[OMAP34XX_NR_GPIOS]; -#endif - static void __init omap_gpio_show_rev(struct gpio_bank *bank) { u32 rev; @@ -1710,6 +1559,19 @@ static void __init omap_gpio_show_rev(struct gpio_bank *bank) */ static struct lock_class_key gpio_lock_class; +static inline int init_gpio_info(struct platform_device *pdev) +{ + /* TODO: Analyze removing gpio_bank_count usage from driver code */ + gpio_bank = kzalloc(gpio_bank_count * sizeof(struct gpio_bank), + GFP_KERNEL); + if (!gpio_bank) { + dev_err(&pdev->dev, "Memory alloc failed for gpio_bank\n"); + return -ENOMEM; + } + return 0; +} + +/* TODO: Cleanup cpu_is_* checks */ static void omap_gpio_mod_init(struct gpio_bank *bank, int id) { if (cpu_class_is_omap2()) { @@ -1773,16 +1635,9 @@ static void omap_gpio_mod_init(struct gpio_bank *bank, int id) static void __init omap_gpio_chip_init(struct gpio_bank *bank) { - int j, bank_width = 16; + int j; static int gpio; - if (cpu_is_omap7xx() && bank->method == METHOD_GPIO_7XX) - bank_width = 32; /* 7xx has 32-bit GPIOs */ - - if ((bank->method == METHOD_GPIO_24XX) || - (bank->method == METHOD_GPIO_44XX)) - bank_width = 32; - bank->mod_usage = 0; /* * REVISIT eventually switch from OMAP-specific gpio structs @@ -1826,139 +1681,68 @@ static void __init omap_gpio_chip_init(struct gpio_bank *bank) set_irq_data(bank->irq, bank); } -static int __init _omap_gpio_init(void) +static int __devinit omap_gpio_probe(struct platform_device *pdev) { - int i; + static int gpio_init_done; + struct omap_gpio_platform_data *pdata; + struct resource *res; + int id; struct gpio_bank *bank; - int bank_size = SZ_8K; /* Module 4KB + L4 4KB except on omap1 */ - char clk_name[11]; - initialized = 1; + if (!pdev->dev.platform_data) + return -EINVAL; -#if defined(CONFIG_ARCH_OMAP1) - if (cpu_is_omap15xx()) { - gpio_ick = clk_get(NULL, "arm_gpio_ck"); - if (IS_ERR(gpio_ick)) - printk("Could not get arm_gpio_ck\n"); - else - clk_enable(gpio_ick); - } -#endif -#if defined(CONFIG_ARCH_OMAP2) - if (cpu_class_is_omap2()) { - gpio_ick = clk_get(NULL, "gpios_ick"); - if (IS_ERR(gpio_ick)) - printk("Could not get gpios_ick\n"); - else - clk_enable(gpio_ick); - gpio_fck = clk_get(NULL, "gpios_fck"); - if (IS_ERR(gpio_fck)) - printk("Could not get gpios_fck\n"); - else - clk_enable(gpio_fck); + pdata = pdev->dev.platform_data; - /* - * On 2430 & 3430 GPIO 5 uses CORE L4 ICLK - */ -#if defined(CONFIG_ARCH_OMAP2430) - if (cpu_is_omap2430()) { - gpio5_ick = clk_get(NULL, "gpio5_ick"); - if (IS_ERR(gpio5_ick)) - printk("Could not get gpio5_ick\n"); - else - clk_enable(gpio5_ick); - gpio5_fck = clk_get(NULL, "gpio5_fck"); - if (IS_ERR(gpio5_fck)) - printk("Could not get gpio5_fck\n"); - else - clk_enable(gpio5_fck); - } -#endif - } -#endif + if (!gpio_init_done) { + int ret; -#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) - if (cpu_is_omap34xx() || cpu_is_omap44xx()) { - for (i = 0; i < OMAP34XX_NR_GPIOS; i++) { - sprintf(clk_name, "gpio%d_ick", i + 1); - gpio_iclks[i] = clk_get(NULL, clk_name); - if (IS_ERR(gpio_iclks[i])) - printk(KERN_ERR "Could not get %s\n", clk_name); - else - clk_enable(gpio_iclks[i]); - } + ret = init_gpio_info(pdev); + if (ret) + return ret; } -#endif + id = pdev->id; + bank = &gpio_bank[id]; -#ifdef CONFIG_ARCH_OMAP15XX - if (cpu_is_omap15xx()) { - gpio_bank_count = 2; - gpio_bank = gpio_bank_1510; - bank_size = SZ_2K; - } -#endif -#if defined(CONFIG_ARCH_OMAP16XX) - if (cpu_is_omap16xx()) { - gpio_bank_count = 5; - gpio_bank = gpio_bank_1610; - bank_size = SZ_2K; - } -#endif -#if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850) - if (cpu_is_omap7xx()) { - gpio_bank_count = 7; - gpio_bank = gpio_bank_7xx; - bank_size = SZ_2K; - } -#endif -#ifdef CONFIG_ARCH_OMAP2 - if (cpu_is_omap242x()) { - gpio_bank_count = 4; - gpio_bank = gpio_bank_242x; - } - if (cpu_is_omap243x()) { - gpio_bank_count = 5; - gpio_bank = gpio_bank_243x; - } -#endif -#ifdef CONFIG_ARCH_OMAP3 - if (cpu_is_omap34xx()) { - gpio_bank_count = OMAP34XX_NR_GPIOS; - gpio_bank = gpio_bank_34xx; - } -#endif -#ifdef CONFIG_ARCH_OMAP4 - if (cpu_is_omap44xx()) { - gpio_bank_count = OMAP34XX_NR_GPIOS; - gpio_bank = gpio_bank_44xx; + res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); + if (unlikely(!res)) { + dev_err(&pdev->dev, "GPIO Bank %i Invalid IRQ resource\n", id); + return -ENODEV; } -#endif - for (i = 0; i < gpio_bank_count; i++) { - bank = &gpio_bank[i]; - spin_lock_init(&bank->lock); + bank->irq = res->start; + bank->virtual_irq_start = pdata->virtual_irq_start; + bank->method = pdata->bank_type; + bank->dev = &pdev->dev; + bank->dbck_flag = pdata->dbck_flag; + bank_width = pdata->bank_width; - /* Static mapping, never released */ - bank->base = ioremap(bank->pbase, bank_size); - if (!bank->base) { - printk(KERN_ERR "Could not ioremap gpio bank%i\n", i); - continue; - } + spin_lock_init(&bank->lock); - omap_gpio_mod_init(bank, i); - omap_gpio_chip_init(bank); + /* Static mapping, never released */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (unlikely(!res)) { + dev_err(&pdev->dev, "GPIO Bank %i Invalid mem resource\n", id); + return -ENODEV; + } - if (cpu_is_omap34xx() || cpu_is_omap44xx()) { - sprintf(clk_name, "gpio%d_dbck", i + 1); - bank->dbck = clk_get(NULL, clk_name); - if (IS_ERR(bank->dbck)) - printk(KERN_ERR "Could not get %s\n", clk_name); - } + bank->base = ioremap(res->start, resource_size(res)); + if (!bank->base) { + dev_err(&pdev->dev, "Could not ioremap gpio bank%i\n", id); + return -ENOMEM; } + pm_runtime_enable(bank->dev); + pm_runtime_get_sync(bank->dev); + + omap_gpio_mod_init(bank, id); + omap_gpio_chip_init(bank); omap_gpio_show_rev(bank); + if (!gpio_init_done) + gpio_init_done = 1; + return 0; } @@ -2252,8 +2036,6 @@ void omap_gpio_save_context(void) /* saving banks from 2-6 only since GPIO1 is in WKUP */ for (i = 1; i < gpio_bank_count; i++) { struct gpio_bank *bank = &gpio_bank[i]; - gpio_context[i].sysconfig = - __raw_readl(bank->base + OMAP24XX_GPIO_SYSCONFIG); gpio_context[i].irqenable1 = __raw_readl(bank->base + OMAP24XX_GPIO_IRQENABLE1); gpio_context[i].irqenable2 = @@ -2284,8 +2066,6 @@ void omap_gpio_restore_context(void) for (i = 1; i < gpio_bank_count; i++) { struct gpio_bank *bank = &gpio_bank[i]; - __raw_writel(gpio_context[i].sysconfig, - bank->base + OMAP24XX_GPIO_SYSCONFIG); __raw_writel(gpio_context[i].irqenable1, bank->base + OMAP24XX_GPIO_IRQENABLE1); __raw_writel(gpio_context[i].irqenable2, @@ -2310,25 +2090,28 @@ void omap_gpio_restore_context(void) } #endif +static struct platform_driver omap_gpio_driver = { + .probe = omap_gpio_probe, + .driver = { + .name = "omap_gpio", + }, +}; + /* - * This may get called early from board specific init - * for boards that have interrupts routed via FPGA. + * gpio driver register needs to be done before + * machine_init functions access gpio APIs. + * Hence omap_gpio_drv_reg() is a postcore_initcall. */ -int __init omap_gpio_init(void) +static int __init omap_gpio_drv_reg(void) { - if (!initialized) - return _omap_gpio_init(); - else - return 0; + return platform_driver_register(&omap_gpio_driver); } +postcore_initcall(omap_gpio_drv_reg); static int __init omap_gpio_sysinit(void) { int ret = 0; - if (!initialized) - ret = _omap_gpio_init(); - mpuio_init(); #if defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP2PLUS) diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index 24892a6707c4..5f118ff0d3eb 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -94,7 +94,6 @@ struct omap_gpio_platform_data { /* TODO: Analyze removing gpio_bank_count usage from driver code */ extern int gpio_bank_count; -extern int omap_gpio_init(void); /* Call from board init only */ extern void omap2_gpio_prepare_for_idle(int power_state); extern void omap2_gpio_resume_after_idle(void); extern void omap_set_gpio_debounce(int gpio, int enable); -- cgit v1.2.3 From 5de62b86d2f5cf3459cb02ecb7a4530787bbd898 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Tue, 7 Dec 2010 16:26:58 -0800 Subject: omap1: Fix gpio mpuio bank to work for multi-omap for 7xx/15xx/16xx We need to divide the 15xx/16xx offset by 2 for 7xx. Use bank->stride for that. This allows us to get rid of the duplicate defines for the MPUIO registers. Note that this will cause omap-keypad.c driver to not work on 7xx. However, the right fix there is to move over to matrix_keypad instead as suggested by Cory Maccarrone and Janusz Krzysztofik . Cc: Cory Maccarrone Acked-by: Janusz Krzysztofik Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/gpio.c | 33 +++++++++++++++++++-------------- arch/arm/plat-omap/include/plat/gpio.h | 22 +++++----------------- 2 files changed, 24 insertions(+), 31 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 6f53dee98a91..8d493b992e70 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -159,6 +159,7 @@ struct gpio_bank { u32 dbck_enable_mask; struct device *dev; bool dbck_flag; + int stride; }; #ifdef CONFIG_ARCH_OMAP3 @@ -267,7 +268,7 @@ static void _set_gpio_direction(struct gpio_bank *bank, int gpio, int is_input) switch (bank->method) { #ifdef CONFIG_ARCH_OMAP1 case METHOD_MPUIO: - reg += OMAP_MPUIO_IO_CNTL; + reg += OMAP_MPUIO_IO_CNTL / bank->stride; break; #endif #ifdef CONFIG_ARCH_OMAP15XX @@ -315,7 +316,7 @@ static void _set_gpio_dataout(struct gpio_bank *bank, int gpio, int enable) switch (bank->method) { #ifdef CONFIG_ARCH_OMAP1 case METHOD_MPUIO: - reg += OMAP_MPUIO_OUTPUT; + reg += OMAP_MPUIO_OUTPUT / bank->stride; l = __raw_readl(reg); if (enable) l |= 1 << gpio; @@ -387,7 +388,7 @@ static int _get_gpio_datain(struct gpio_bank *bank, int gpio) switch (bank->method) { #ifdef CONFIG_ARCH_OMAP1 case METHOD_MPUIO: - reg += OMAP_MPUIO_INPUT_LATCH; + reg += OMAP_MPUIO_INPUT_LATCH / bank->stride; break; #endif #ifdef CONFIG_ARCH_OMAP15XX @@ -433,7 +434,7 @@ static int _get_gpio_dataout(struct gpio_bank *bank, int gpio) switch (bank->method) { #ifdef CONFIG_ARCH_OMAP1 case METHOD_MPUIO: - reg += OMAP_MPUIO_OUTPUT; + reg += OMAP_MPUIO_OUTPUT / bank->stride; break; #endif #ifdef CONFIG_ARCH_OMAP15XX @@ -620,7 +621,7 @@ static void _toggle_gpio_edge_triggering(struct gpio_bank *bank, int gpio) switch (bank->method) { case METHOD_MPUIO: - reg += OMAP_MPUIO_GPIO_INT_EDGE; + reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride; break; #ifdef CONFIG_ARCH_OMAP15XX case METHOD_GPIO_1510: @@ -654,7 +655,7 @@ static int _set_gpio_triggering(struct gpio_bank *bank, int gpio, int trigger) switch (bank->method) { #ifdef CONFIG_ARCH_OMAP1 case METHOD_MPUIO: - reg += OMAP_MPUIO_GPIO_INT_EDGE; + reg += OMAP_MPUIO_GPIO_INT_EDGE / bank->stride; l = __raw_readl(reg); if ((trigger & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) bank->toggle_mask |= 1 << gpio; @@ -840,7 +841,7 @@ static u32 _get_gpio_irqbank_mask(struct gpio_bank *bank) switch (bank->method) { #ifdef CONFIG_ARCH_OMAP1 case METHOD_MPUIO: - reg += OMAP_MPUIO_GPIO_MASKIT; + reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride; mask = 0xffff; inv = 1; break; @@ -897,7 +898,7 @@ static void _enable_gpio_irqbank(struct gpio_bank *bank, int gpio_mask, int enab switch (bank->method) { #ifdef CONFIG_ARCH_OMAP1 case METHOD_MPUIO: - reg += OMAP_MPUIO_GPIO_MASKIT; + reg += OMAP_MPUIO_GPIO_MASKIT / bank->stride; l = __raw_readl(reg); if (enable) l &= ~(gpio_mask); @@ -1147,7 +1148,8 @@ static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc) bank = get_irq_data(irq); #ifdef CONFIG_ARCH_OMAP1 if (bank->method == METHOD_MPUIO) - isr_reg = bank->base + OMAP_MPUIO_GPIO_INT; + isr_reg = bank->base + + OMAP_MPUIO_GPIO_INT / bank->stride; #endif #ifdef CONFIG_ARCH_OMAP15XX if (bank->method == METHOD_GPIO_1510) @@ -1345,7 +1347,8 @@ static int omap_mpuio_suspend_noirq(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct gpio_bank *bank = platform_get_drvdata(pdev); - void __iomem *mask_reg = bank->base + OMAP_MPUIO_GPIO_MASKIT; + void __iomem *mask_reg = bank->base + + OMAP_MPUIO_GPIO_MASKIT / bank->stride; unsigned long flags; spin_lock_irqsave(&bank->lock, flags); @@ -1360,7 +1363,8 @@ static int omap_mpuio_resume_noirq(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct gpio_bank *bank = platform_get_drvdata(pdev); - void __iomem *mask_reg = bank->base + OMAP_MPUIO_GPIO_MASKIT; + void __iomem *mask_reg = bank->base + + OMAP_MPUIO_GPIO_MASKIT / bank->stride; unsigned long flags; spin_lock_irqsave(&bank->lock, flags); @@ -1440,7 +1444,7 @@ static int gpio_is_input(struct gpio_bank *bank, int mask) switch (bank->method) { case METHOD_MPUIO: - reg += OMAP_MPUIO_IO_CNTL; + reg += OMAP_MPUIO_IO_CNTL / bank->stride; break; case METHOD_GPIO_1510: reg += OMAP1510_GPIO_DIR_CONTROL; @@ -1601,8 +1605,8 @@ static void omap_gpio_mod_init(struct gpio_bank *bank, int id) } } else if (cpu_class_is_omap1()) { if (bank_is_mpuio(bank)) - __raw_writew(0xffff, bank->base - + OMAP_MPUIO_GPIO_MASKIT); + __raw_writew(0xffff, bank->base + + OMAP_MPUIO_GPIO_MASKIT / bank->stride); if (cpu_is_omap15xx() && bank->method == METHOD_GPIO_1510) { __raw_writew(0xffff, bank->base + OMAP1510_GPIO_INT_MASK); @@ -1716,6 +1720,7 @@ static int __devinit omap_gpio_probe(struct platform_device *pdev) bank->method = pdata->bank_type; bank->dev = &pdev->dev; bank->dbck_flag = pdata->dbck_flag; + bank->stride = pdata->bank_stride; bank_width = pdata->bank_width; spin_lock_init(&bank->lock); diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index 5f118ff0d3eb..41ff2f8943f0 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -32,22 +32,10 @@ #define OMAP1_MPUIO_BASE 0xfffb5000 -#if (defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)) - -#define OMAP_MPUIO_INPUT_LATCH 0x00 -#define OMAP_MPUIO_OUTPUT 0x02 -#define OMAP_MPUIO_IO_CNTL 0x04 -#define OMAP_MPUIO_KBR_LATCH 0x08 -#define OMAP_MPUIO_KBC 0x0a -#define OMAP_MPUIO_GPIO_EVENT_MODE 0x0c -#define OMAP_MPUIO_GPIO_INT_EDGE 0x0e -#define OMAP_MPUIO_KBD_INT 0x10 -#define OMAP_MPUIO_GPIO_INT 0x12 -#define OMAP_MPUIO_KBD_MASKIT 0x14 -#define OMAP_MPUIO_GPIO_MASKIT 0x16 -#define OMAP_MPUIO_GPIO_DEBOUNCING 0x18 -#define OMAP_MPUIO_LATCH 0x1a -#else +/* + * These are the omap15xx/16xx offsets. The omap7xx offset are + * OMAP_MPUIO_ / 2 offsets below. + */ #define OMAP_MPUIO_INPUT_LATCH 0x00 #define OMAP_MPUIO_OUTPUT 0x04 #define OMAP_MPUIO_IO_CNTL 0x08 @@ -61,7 +49,6 @@ #define OMAP_MPUIO_GPIO_MASKIT 0x2c #define OMAP_MPUIO_GPIO_DEBOUNCING 0x30 #define OMAP_MPUIO_LATCH 0x34 -#endif #define OMAP34XX_NR_GPIOS 6 @@ -88,6 +75,7 @@ struct omap_gpio_platform_data { u16 virtual_irq_start; int bank_type; int bank_width; /* GPIO bank width */ + int bank_stride; /* Only needed for omap1 MPUIO */ bool dbck_flag; /* dbck required or not - True for OMAP3&4 */ }; -- cgit v1.2.3 From 03a9e5126147c9f92aeba4b34f62b15b625087fb Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 9 Dec 2010 15:49:23 -0800 Subject: omap1: Use asm_irq_flags for entry-macro.S Initialize asm_irq_flags in omap_init_irq and use it in get_irqnr_and_base to detect between omap7xx and omap15xx/16xx. Note that both INT_1510_IH2_IRQ and INT_1510_IH2_IRQ are defined as 0, so use INT_1510_IH2_IRQ for both of them. Tested-by: Janusz Krzysztofik Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/irqs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h index 65e20a686713..2910de921c52 100644 --- a/arch/arm/plat-omap/include/plat/irqs.h +++ b/arch/arm/plat-omap/include/plat/irqs.h @@ -77,7 +77,7 @@ /* * OMAP-1610 specific IRQ numbers for interrupt handler 1 */ -#define INT_1610_IH2_IRQ 0 +#define INT_1610_IH2_IRQ INT_1510_IH2_IRQ #define INT_1610_IH2_FIQ 2 #define INT_1610_McBSP2_TX 4 #define INT_1610_McBSP2_RX 5 -- cgit v1.2.3 From df1e9d1c218ba696e376cad371b57c0109fe98c9 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 10 Dec 2010 09:46:24 -0800 Subject: omap: Split omap_read/write functions for omap1 and omap2+ Otherwise multi-omap1 support for omap1 won't work as the cpu_class_is_omap1() won't work until the SoC is detected. Note that eventually these will go away, please use ioremap + read/write instead. Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/io.c | 58 ------------------------------------------------- 1 file changed, 58 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/io.c b/arch/arm/plat-omap/io.c index b0078cf96281..f1295fafcd31 100644 --- a/arch/arm/plat-omap/io.c +++ b/arch/arm/plat-omap/io.c @@ -136,61 +136,3 @@ void omap_iounmap(volatile void __iomem *addr) __iounmap(addr); } EXPORT_SYMBOL(omap_iounmap); - -/* - * NOTE: Please use ioremap + __raw_read/write where possible instead of these - */ - -u8 omap_readb(u32 pa) -{ - if (cpu_class_is_omap1()) - return __raw_readb(OMAP1_IO_ADDRESS(pa)); - else - return __raw_readb(OMAP2_L4_IO_ADDRESS(pa)); -} -EXPORT_SYMBOL(omap_readb); - -u16 omap_readw(u32 pa) -{ - if (cpu_class_is_omap1()) - return __raw_readw(OMAP1_IO_ADDRESS(pa)); - else - return __raw_readw(OMAP2_L4_IO_ADDRESS(pa)); -} -EXPORT_SYMBOL(omap_readw); - -u32 omap_readl(u32 pa) -{ - if (cpu_class_is_omap1()) - return __raw_readl(OMAP1_IO_ADDRESS(pa)); - else - return __raw_readl(OMAP2_L4_IO_ADDRESS(pa)); -} -EXPORT_SYMBOL(omap_readl); - -void omap_writeb(u8 v, u32 pa) -{ - if (cpu_class_is_omap1()) - __raw_writeb(v, OMAP1_IO_ADDRESS(pa)); - else - __raw_writeb(v, OMAP2_L4_IO_ADDRESS(pa)); -} -EXPORT_SYMBOL(omap_writeb); - -void omap_writew(u16 v, u32 pa) -{ - if (cpu_class_is_omap1()) - __raw_writew(v, OMAP1_IO_ADDRESS(pa)); - else - __raw_writew(v, OMAP2_L4_IO_ADDRESS(pa)); -} -EXPORT_SYMBOL(omap_writew); - -void omap_writel(u32 v, u32 pa) -{ - if (cpu_class_is_omap1()) - __raw_writel(v, OMAP1_IO_ADDRESS(pa)); - else - __raw_writel(v, OMAP2_L4_IO_ADDRESS(pa)); -} -EXPORT_SYMBOL(omap_writel); -- cgit v1.2.3 From ba6e1f4ff41314906d81e6d96e646cdeafe42827 Mon Sep 17 00:00:00 2001 From: "Guzman Lugo, Fernando" Date: Wed, 15 Dec 2010 00:54:00 +0000 Subject: OMAP: iovmm: no gap checking for fixed address If some fixed da address is wanted to be mapped and the page is freed but it is used as gap, the mapping will fail. This patch is fixing that and olny keeps the gap for not fixed address. Signed-off-by: Fernando Guzman Lugo Acked-by: Hiroshi DOYU --- arch/arm/plat-omap/iovmm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c index 8ce0de247c71..34f0012b5676 100644 --- a/arch/arm/plat-omap/iovmm.c +++ b/arch/arm/plat-omap/iovmm.c @@ -289,10 +289,10 @@ static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da, prev_end = 0; list_for_each_entry(tmp, &obj->mmap, list) { - if (prev_end >= start) + if (prev_end > start) break; - if (start + bytes < tmp->da_start) + if (start + bytes <= tmp->da_start) goto found; if (flags & IOVMF_DA_ANON) @@ -301,7 +301,7 @@ static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da, prev_end = tmp->da_end; } - if ((start > prev_end) && (ULONG_MAX - start >= bytes)) + if ((start >= prev_end) && (ULONG_MAX - start + 1 >= bytes)) goto found; dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n", -- cgit v1.2.3 From ad1081210f3c91874f9fe9b48c3934c7db9714b7 Mon Sep 17 00:00:00 2001 From: "Guzman Lugo, Fernando" Date: Wed, 15 Dec 2010 00:54:01 +0000 Subject: OMAP: iovmm: add superpages support to fixed da address This patch adds superpages support to fixed ad address inside iommu_kmap function. Signed-off-by: Fernando Guzman Lugo Acked-by: Hiroshi DOYU --- arch/arm/plat-omap/iovmm.c | 62 +++++++++++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 26 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c index 34f0012b5676..93a34d92b3a2 100644 --- a/arch/arm/plat-omap/iovmm.c +++ b/arch/arm/plat-omap/iovmm.c @@ -87,35 +87,43 @@ static size_t sgtable_len(const struct sg_table *sgt) } #define sgtable_ok(x) (!!sgtable_len(x)) +static unsigned max_alignment(u32 addr) +{ + int i; + unsigned pagesize[] = { SZ_16M, SZ_1M, SZ_64K, SZ_4K, }; + for (i = 0; i < ARRAY_SIZE(pagesize) && addr & (pagesize[i] - 1); i++) + ; + return (i < ARRAY_SIZE(pagesize)) ? pagesize[i] : 0; +} + /* * calculate the optimal number sg elements from total bytes based on * iommu superpages */ -static unsigned int sgtable_nents(size_t bytes) +static unsigned sgtable_nents(size_t bytes, u32 da, u32 pa) { - int i; - unsigned int nr_entries; - const unsigned long pagesize[] = { SZ_16M, SZ_1M, SZ_64K, SZ_4K, }; + unsigned nr_entries = 0, ent_sz; if (!IS_ALIGNED(bytes, PAGE_SIZE)) { pr_err("%s: wrong size %08x\n", __func__, bytes); return 0; } - nr_entries = 0; - for (i = 0; i < ARRAY_SIZE(pagesize); i++) { - if (bytes >= pagesize[i]) { - nr_entries += (bytes / pagesize[i]); - bytes %= pagesize[i]; - } + while (bytes) { + ent_sz = max_alignment(da | pa); + ent_sz = min_t(unsigned, ent_sz, iopgsz_max(bytes)); + nr_entries++; + da += ent_sz; + pa += ent_sz; + bytes -= ent_sz; } - BUG_ON(bytes); return nr_entries; } /* allocate and initialize sg_table header(a kind of 'superblock') */ -static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags) +static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags, + u32 da, u32 pa) { unsigned int nr_entries; int err; @@ -127,9 +135,8 @@ static struct sg_table *sgtable_alloc(const size_t bytes, u32 flags) if (!IS_ALIGNED(bytes, PAGE_SIZE)) return ERR_PTR(-EINVAL); - /* FIXME: IOVMF_DA_FIXED should support 'superpages' */ - if ((flags & IOVMF_LINEAR) && (flags & IOVMF_DA_ANON)) { - nr_entries = sgtable_nents(bytes); + if (flags & IOVMF_LINEAR) { + nr_entries = sgtable_nents(bytes, da, pa); if (!nr_entries) return ERR_PTR(-EINVAL); } else @@ -409,7 +416,8 @@ static inline void sgtable_drain_vmalloc(struct sg_table *sgt) BUG_ON(!sgt); } -static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, size_t len) +static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, u32 da, + size_t len) { unsigned int i; struct scatterlist *sg; @@ -418,9 +426,10 @@ static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, size_t len) va = phys_to_virt(pa); for_each_sg(sgt->sgl, sg, sgt->nents, i) { - size_t bytes; + unsigned bytes; - bytes = iopgsz_max(len); + bytes = max_alignment(da | pa); + bytes = min_t(unsigned, bytes, iopgsz_max(len)); BUG_ON(!iopgsz_ok(bytes)); @@ -429,6 +438,7 @@ static void sgtable_fill_kmalloc(struct sg_table *sgt, u32 pa, size_t len) * 'pa' is cotinuous(linear). */ pa += bytes; + da += bytes; len -= bytes; } BUG_ON(len); @@ -695,18 +705,18 @@ u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags) if (!va) return -ENOMEM; - sgt = sgtable_alloc(bytes, flags); + flags &= IOVMF_HW_MASK; + flags |= IOVMF_DISCONT; + flags |= IOVMF_ALLOC; + flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON); + + sgt = sgtable_alloc(bytes, flags, da, 0); if (IS_ERR(sgt)) { da = PTR_ERR(sgt); goto err_sgt_alloc; } sgtable_fill_vmalloc(sgt, va); - flags &= IOVMF_HW_MASK; - flags |= IOVMF_DISCONT; - flags |= IOVMF_ALLOC; - flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON); - da = __iommu_vmap(obj, da, sgt, va, bytes, flags); if (IS_ERR_VALUE(da)) goto err_iommu_vmap; @@ -746,11 +756,11 @@ static u32 __iommu_kmap(struct iommu *obj, u32 da, u32 pa, void *va, { struct sg_table *sgt; - sgt = sgtable_alloc(bytes, flags); + sgt = sgtable_alloc(bytes, flags, da, pa); if (IS_ERR(sgt)) return PTR_ERR(sgt); - sgtable_fill_kmalloc(sgt, pa, bytes); + sgtable_fill_kmalloc(sgt, pa, da, bytes); da = map_iommu_region(obj, da, sgt, va, bytes, flags); if (IS_ERR_VALUE(da)) { -- cgit v1.2.3 From 9205a109fbeee180254bb5a4020eb71d50735944 Mon Sep 17 00:00:00 2001 From: "Guzman Lugo, Fernando" Date: Wed, 15 Dec 2010 00:54:02 +0000 Subject: OMAP: iovmm: replace __iounmap with iounmap __iounmap function is wrong for OMAP architecture, instead use iounmap which will call to the correct function. Signed-off-by: Fernando Guzman Lugo Acked-by: Hiroshi DOYU --- arch/arm/plat-omap/iovmm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c index 93a34d92b3a2..fa6e64332a9e 100644 --- a/arch/arm/plat-omap/iovmm.c +++ b/arch/arm/plat-omap/iovmm.c @@ -821,7 +821,7 @@ void iommu_kunmap(struct iommu *obj, u32 da) struct sg_table *sgt; typedef void (*func_t)(const void *); - sgt = unmap_vm_area(obj, da, (func_t)__iounmap, + sgt = unmap_vm_area(obj, da, (func_t)iounmap, IOVMF_LINEAR | IOVMF_MMIO); if (!sgt) dev_dbg(obj->dev, "%s: No sgt\n", __func__); -- cgit v1.2.3 From c7f4ab26e3bcdaeb3e19ec658e3ad9092f1a6ceb Mon Sep 17 00:00:00 2001 From: "Guzman Lugo, Fernando" Date: Wed, 15 Dec 2010 00:54:03 +0000 Subject: OMAP: iommu: create new api to set valid da range Some IOMMUs cannot use the whole 0x0 - 0xFFFFFFFF range. With this new API the valid range can be set. Signed-off-by: Fernando Guzman Lugo Acked-by: Hiroshi DOYU --- arch/arm/plat-omap/include/plat/iommu.h | 5 +++++ arch/arm/plat-omap/iommu.c | 24 ++++++++++++++++++++++++ arch/arm/plat-omap/iovmm.c | 15 ++++++++------- 3 files changed, 37 insertions(+), 7 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/iommu.h b/arch/arm/plat-omap/include/plat/iommu.h index 33c7d41cb6a5..69230d685538 100644 --- a/arch/arm/plat-omap/include/plat/iommu.h +++ b/arch/arm/plat-omap/include/plat/iommu.h @@ -50,6 +50,8 @@ struct iommu { int (*isr)(struct iommu *obj); void *ctx; /* iommu context: registres saved area */ + u32 da_start; + u32 da_end; }; struct cr_regs { @@ -103,6 +105,8 @@ struct iommu_platform_data { const char *name; const char *clk_name; const int nr_tlb_entries; + u32 da_start; + u32 da_end; }; #if defined(CONFIG_ARCH_OMAP1) @@ -152,6 +156,7 @@ extern void flush_iotlb_all(struct iommu *obj); extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e); extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova); +extern int iommu_set_da_range(struct iommu *obj, u32 start, u32 end); extern struct iommu *iommu_get(const char *name); extern void iommu_put(struct iommu *obj); diff --git a/arch/arm/plat-omap/iommu.c b/arch/arm/plat-omap/iommu.c index 6cd151b31bc5..b1107c08da56 100644 --- a/arch/arm/plat-omap/iommu.c +++ b/arch/arm/plat-omap/iommu.c @@ -829,6 +829,28 @@ static int device_match_by_alias(struct device *dev, void *data) return strcmp(obj->name, name) == 0; } +/** + * iommu_set_da_range - Set a valid device address range + * @obj: target iommu + * @start Start of valid range + * @end End of valid range + **/ +int iommu_set_da_range(struct iommu *obj, u32 start, u32 end) +{ + + if (!obj) + return -EFAULT; + + if (end < start || !PAGE_ALIGN(start | end)) + return -EINVAL; + + obj->da_start = start; + obj->da_end = end; + + return 0; +} +EXPORT_SYMBOL_GPL(iommu_set_da_range); + /** * iommu_get - Get iommu handler * @name: target iommu name @@ -922,6 +944,8 @@ static int __devinit omap_iommu_probe(struct platform_device *pdev) obj->name = pdata->name; obj->dev = &pdev->dev; obj->ctx = (void *)obj + sizeof(*obj); + obj->da_start = pdata->da_start; + obj->da_end = pdata->da_end; mutex_init(&obj->iommu_lock); mutex_init(&obj->mmap_lock); diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c index fa6e64332a9e..6dc1296c8c77 100644 --- a/arch/arm/plat-omap/iovmm.c +++ b/arch/arm/plat-omap/iovmm.c @@ -280,13 +280,14 @@ static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da, alignement = PAGE_SIZE; if (flags & IOVMF_DA_ANON) { - /* - * Reserve the first page for NULL - */ - start = PAGE_SIZE; + start = obj->da_start; + if (flags & IOVMF_LINEAR) alignement = iopgsz_max(bytes); start = roundup(start, alignement); + } else if (start < obj->da_start || start > obj->da_end || + obj->da_end - start < bytes) { + return ERR_PTR(-EINVAL); } tmp = NULL; @@ -299,16 +300,16 @@ static struct iovm_struct *alloc_iovm_area(struct iommu *obj, u32 da, if (prev_end > start) break; - if (start + bytes <= tmp->da_start) + if (tmp->da_start > start && (tmp->da_start - start) >= bytes) goto found; - if (flags & IOVMF_DA_ANON) + if (tmp->da_end >= start && flags & IOVMF_DA_ANON) start = roundup(tmp->da_end + 1, alignement); prev_end = tmp->da_end; } - if ((start >= prev_end) && (ULONG_MAX - start + 1 >= bytes)) + if ((start >= prev_end) && (obj->da_end - start >= bytes)) goto found; dev_dbg(obj->dev, "%s: no space to fit %08x(%x) flags: %08x\n", -- cgit v1.2.3 From 1cd25df4e53b9507f7abbb8aff8ce2ba644a1468 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Mon, 11 Oct 2010 09:53:49 +0000 Subject: OMAP: iommu: make iva2 iommu selectable It seems dsp-link will do this, and tidspbridge too at some point, but right now it's not possible to select CONFIG_MPU_BRIDGE_IOMMU. Cc: Fernando Guzman Lugo Cc: Yogesh Marathe Signed-off-by: Felipe Contreras --- arch/arm/plat-omap/Kconfig | 3 +++ 1 file changed, 3 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 92c5bb7909f5..5e63e5069e0d 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -109,6 +109,9 @@ config OMAP_IOMMU_DEBUG Say N unless you know you need this. +config OMAP_IOMMU_IVA2 + bool + choice prompt "System timer" default OMAP_32K_TIMER if !ARCH_OMAP15XX -- cgit v1.2.3 From 2d200665c37f544f648d77a05a06ab63328f0d3a Mon Sep 17 00:00:00 2001 From: Aaro Koskinen Date: Fri, 17 Dec 2010 15:13:47 -0800 Subject: arm: omap: add minimal support for RM-680 Add minimal support for Nokia RM-680 board. Tested with omap2plus_defconfig. Signed-off-by: Aaro Koskinen [tony@atomide.com: updated to remove omap_gpio_init Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/uncompress.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h index 9036e374e0ac..d02adb5cc4d9 100644 --- a/arch/arm/plat-omap/include/plat/uncompress.h +++ b/arch/arm/plat-omap/include/plat/uncompress.h @@ -147,6 +147,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) DEBUG_LL_OMAP3(3, cm_t3517); DEBUG_LL_OMAP3(3, igep0020); DEBUG_LL_OMAP3(3, igep0030); + DEBUG_LL_OMAP3(3, nokia_rm680); DEBUG_LL_OMAP3(3, nokia_rx51); DEBUG_LL_OMAP3(3, omap3517evm); DEBUG_LL_OMAP3(3, omap3_beagle); -- cgit v1.2.3 From 6bc56aaecce78113500b150f1f1506029145a370 Mon Sep 17 00:00:00 2001 From: Anand Gadiyar Date: Fri, 3 Dec 2010 17:26:56 +0000 Subject: omap: remove dead wdt code in plat-omap/devices.c Commit f2ce62312650 (OMAP: WDT: Split OMAP1 and OMAP2PLUS device registration) removed omap_init_wdt and related structures from plat-omap/devices.c. However a subsequent commit or merge seems to have reintroduced these by accident. The caller of omap_init_wdt was also removed by that commit, and this did not get restored. So we have the following build warning now: CC arch/arm/plat-omap/devices.o arch/arm/plat-omap/devices.c:252: warning: 'omap_init_wdt' defined but not used Fix this by removing this dead code. Signed-off-by: Anand Gadiyar Cc: Tony Lindgren Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/devices.c | 40 ---------------------------------------- 1 file changed, 40 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index fc819120978d..10245b837c10 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c @@ -232,46 +232,6 @@ static void omap_init_uwire(void) static inline void omap_init_uwire(void) {} #endif -/*-------------------------------------------------------------------------*/ - -#if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE) - -static struct resource wdt_resources[] = { - { - .flags = IORESOURCE_MEM, - }, -}; - -static struct platform_device omap_wdt_device = { - .name = "omap_wdt", - .id = -1, - .num_resources = ARRAY_SIZE(wdt_resources), - .resource = wdt_resources, -}; - -static void omap_init_wdt(void) -{ - if (cpu_is_omap16xx()) - wdt_resources[0].start = 0xfffeb000; - else if (cpu_is_omap2420()) - wdt_resources[0].start = 0x48022000; /* WDT2 */ - else if (cpu_is_omap2430()) - wdt_resources[0].start = 0x49016000; /* WDT2 */ - else if (cpu_is_omap343x()) - wdt_resources[0].start = 0x48314000; /* WDT2 */ - else if (cpu_is_omap44xx()) - wdt_resources[0].start = 0x4a314000; - else - return; - - wdt_resources[0].end = wdt_resources[0].start + 0x4f; - - (void) platform_device_register(&omap_wdt_device); -} -#else -static inline void omap_init_wdt(void) {} -#endif - #if defined(CONFIG_TIDSPBRIDGE) || defined(CONFIG_TIDSPBRIDGE_MODULE) static phys_addr_t omap_dsp_phys_mempool_base; -- cgit v1.2.3 From 374b8cfd61f33b3c1dd4b0f4c2b1bb20079d3090 Mon Sep 17 00:00:00 2001 From: Benoit Cousson Date: Thu, 9 Dec 2010 14:24:17 +0000 Subject: omap: serial: Change device name: omap-hsuart -> omap_uart The naming convention for omap_device is omap_XXX. Rename the device and driver name in order to stick to this naming convention. Remove the hs prefix that is implicit for every OMAP uarts. Signed-off-by: Benoit Cousson Acked-by: Govindraj Raja Cc: Paul Walmsley Cc: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/omap-serial.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/omap-serial.h b/arch/arm/plat-omap/include/plat/omap-serial.h index b3e0bad9b77e..2682043f5a5b 100644 --- a/arch/arm/plat-omap/include/plat/omap-serial.h +++ b/arch/arm/plat-omap/include/plat/omap-serial.h @@ -22,7 +22,7 @@ #include -#define DRIVER_NAME "omap-hsuart" +#define DRIVER_NAME "omap_uart" /* * Use tty device name as ttyO, [O -> OMAP] -- cgit v1.2.3 From f7bb0d9ab29e3159e22c3bfc843bd37c7d3c91a0 Mon Sep 17 00:00:00 2001 From: Benoit Cousson Date: Thu, 9 Dec 2010 14:24:16 +0000 Subject: I2C: i2c-omap: Change device name: i2c_omap -> omap_i2c The convention for omap device naming is omap_XXX. Rename the device and driver name in order to stick to this naming convention. Change device name in clock nodes as well. Signed-off-by: Benoit Cousson Cc: Kevin Hilman Cc: Rajendra Nayak Cc: Ben Dooks Acked-by: Paul Walmsley Acked-by: Ben Dooks Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/i2c.c b/arch/arm/plat-omap/i2c.c index db9c4efd79e3..a4f8003de664 100644 --- a/arch/arm/plat-omap/i2c.c +++ b/arch/arm/plat-omap/i2c.c @@ -40,7 +40,7 @@ #define OMAP_I2C_SIZE 0x3f #define OMAP1_I2C_BASE 0xfffb3800 -static const char name[] = "i2c_omap"; +static const char name[] = "omap_i2c"; #define I2C_RESOURCE_BUILDER(base, irq) \ { \ -- cgit v1.2.3 From a4c537c7f60704691efc5f833b3d440252275c3b Mon Sep 17 00:00:00 2001 From: "G, Manjunath Kondaiah" Date: Mon, 20 Dec 2010 18:27:17 -0800 Subject: OMAP: DMA: Replace read/write macros with functions Prepare DMA library to get converted into DMA driver using platform device model and hwmod infrastucture(for omap2+, resource structures for omap1) The low level read/write macros are replaced with static inline functions and register offsets are handled through static register offset tables mapped through enumeration constants. These low level read/write functions along with static register offset tables will be moved to respective mach-omap dma files in the later patches of this series. There are no functionality changes with these changes except change in logic for handling 16bit registers of OMAP1. Signed-off-by: G, Manjunath Kondaiah Tested-by: Kevin Hilman Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 517 +++++++++++++++++++++------------- arch/arm/plat-omap/include/plat/dma.h | 151 ++-------- 2 files changed, 345 insertions(+), 323 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index a863f5546a6b..49a7cd4763f9 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -40,6 +40,96 @@ #undef DEBUG +static u16 reg_map_omap1[] = { + [GCR] = 0x400, + [GSCR] = 0x404, + [GRST1] = 0x408, + [HW_ID] = 0x442, + [PCH2_ID] = 0x444, + [PCH0_ID] = 0x446, + [PCH1_ID] = 0x448, + [PCHG_ID] = 0x44a, + [PCHD_ID] = 0x44c, + [CAPS_0] = 0x44e, + [CAPS_1] = 0x452, + [CAPS_2] = 0x456, + [CAPS_3] = 0x458, + [CAPS_4] = 0x45a, + [PCH2_SR] = 0x460, + [PCH0_SR] = 0x480, + [PCH1_SR] = 0x482, + [PCHD_SR] = 0x4c0, + + /* Common Registers */ + [CSDP] = 0x00, + [CCR] = 0x02, + [CICR] = 0x04, + [CSR] = 0x06, + [CEN] = 0x10, + [CFN] = 0x12, + [CSFI] = 0x14, + [CSEI] = 0x16, + [CPC] = 0x18, /* 15xx only */ + [CSAC] = 0x18, + [CDAC] = 0x1a, + [CDEI] = 0x1c, + [CDFI] = 0x1e, + [CLNK_CTRL] = 0x28, + + /* Channel specific register offsets */ + [CSSA] = 0x08, + [CDSA] = 0x0c, + [COLOR] = 0x20, + [CCR2] = 0x24, + [LCH_CTRL] = 0x2a, +}; + +static u16 reg_map_omap2[] = { + [REVISION] = 0x00, + [GCR] = 0x78, + [IRQSTATUS_L0] = 0x08, + [IRQSTATUS_L1] = 0x0c, + [IRQSTATUS_L2] = 0x10, + [IRQSTATUS_L3] = 0x14, + [IRQENABLE_L0] = 0x18, + [IRQENABLE_L1] = 0x1c, + [IRQENABLE_L2] = 0x20, + [IRQENABLE_L3] = 0x24, + [SYSSTATUS] = 0x28, + [OCP_SYSCONFIG] = 0x2c, + [CAPS_0] = 0x64, + [CAPS_2] = 0x6c, + [CAPS_3] = 0x70, + [CAPS_4] = 0x74, + + /* Common register offsets */ + [CCR] = 0x80, + [CLNK_CTRL] = 0x84, + [CICR] = 0x88, + [CSR] = 0x8c, + [CSDP] = 0x90, + [CEN] = 0x94, + [CFN] = 0x98, + [CSEI] = 0xa4, + [CSFI] = 0xa8, + [CDEI] = 0xac, + [CDFI] = 0xb0, + [CSAC] = 0xb4, + [CDAC] = 0xb8, + + /* Channel specific register offsets */ + [CSSA] = 0x9c, + [CDSA] = 0xa0, + [CCEN] = 0xbc, + [CCFN] = 0xc0, + [COLOR] = 0xc4, + + /* OMAP4 specific registers */ + [CDP] = 0xd0, + [CNDP] = 0xd4, + [CCDN] = 0xd8, +}; + #ifndef CONFIG_ARCH_OMAP1 enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED, DMA_CH_QUEUED, DMA_CH_NOTSTARTED, DMA_CH_PAUSED, DMA_CH_LINK_ENABLED @@ -138,6 +228,9 @@ static int omap_dma_reserve_channels; static spinlock_t dma_chan_lock; static struct omap_dma_lch *dma_chan; static void __iomem *omap_dma_base; +static u16 *reg_map; +static u8 dma_stride; +static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end; static const u8 omap1_dma_irq[OMAP1_LOGICAL_DMA_CH_COUNT] = { INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3, @@ -154,23 +247,48 @@ static inline void omap_enable_channel_irq(int lch); #define REVISIT_24XX() printk(KERN_ERR "FIXME: no %s on 24xx\n", \ __func__); -#define dma_read(reg) \ -({ \ - u32 __val; \ - if (cpu_class_is_omap1()) \ - __val = __raw_readw(omap_dma_base + OMAP1_DMA_##reg); \ - else \ - __val = __raw_readl(omap_dma_base + OMAP_DMA4_##reg); \ - __val; \ -}) - -#define dma_write(val, reg) \ -({ \ - if (cpu_class_is_omap1()) \ - __raw_writew((u16)(val), omap_dma_base + OMAP1_DMA_##reg); \ - else \ - __raw_writel((val), omap_dma_base + OMAP_DMA4_##reg); \ -}) +static inline void dma_write(u32 val, int reg, int lch) +{ + u8 stride; + u32 offset; + + stride = (reg >= dma_common_ch_start) ? dma_stride : 0; + offset = reg_map[reg] + (stride * lch); + + if (dma_stride == 0x40) { + __raw_writew(val, omap_dma_base + offset); + if ((reg > CLNK_CTRL && reg < CCEN) || + (reg > PCHD_ID && reg < CAPS_2)) { + u32 offset2 = reg_map[reg] + 2 + (stride * lch); + __raw_writew(val >> 16, omap_dma_base + offset2); + } + } else { + __raw_writel(val, omap_dma_base + offset); + } +} + +static inline u32 dma_read(int reg, int lch) +{ + u8 stride; + u32 offset, val; + + stride = (reg >= dma_common_ch_start) ? dma_stride : 0; + offset = reg_map[reg] + (stride * lch); + + if (dma_stride == 0x40) { + val = __raw_readw(omap_dma_base + offset); + if ((reg > CLNK_CTRL && reg < CCEN) || + (reg > PCHD_ID && reg < CAPS_2)) { + u16 upper; + u32 offset2 = reg_map[reg] + 2 + (stride * lch); + upper = __raw_readw(omap_dma_base + offset2); + val |= (upper << 16); + } + } else { + val = __raw_readl(omap_dma_base + offset); + } + return val; +} #ifdef CONFIG_ARCH_OMAP15XX /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */ @@ -209,11 +327,10 @@ static inline void set_gdma_dev(int req, int dev) /* Omap1 only */ static void clear_lch_regs(int lch) { - int i; - void __iomem *lch_base = omap_dma_base + OMAP1_DMA_CH_BASE(lch); + int i = dma_common_ch_start; - for (i = 0; i < 0x2c; i += 2) - __raw_writew(0, lch_base + i); + for (; i <= dma_common_ch_end; i += 1) + dma_write(0, i, lch); } void omap_set_dma_priority(int lch, int dst_port, int priority) @@ -248,12 +365,12 @@ void omap_set_dma_priority(int lch, int dst_port, int priority) if (cpu_class_is_omap2()) { u32 ccr; - ccr = dma_read(CCR(lch)); + ccr = dma_read(CCR, lch); if (priority) ccr |= (1 << 6); else ccr &= ~(1 << 6); - dma_write(ccr, CCR(lch)); + dma_write(ccr, CCR, lch); } } EXPORT_SYMBOL(omap_set_dma_priority); @@ -264,31 +381,31 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, { u32 l; - l = dma_read(CSDP(lch)); + l = dma_read(CSDP, lch); l &= ~0x03; l |= data_type; - dma_write(l, CSDP(lch)); + dma_write(l, CSDP, lch); if (cpu_class_is_omap1()) { u16 ccr; - ccr = dma_read(CCR(lch)); + ccr = dma_read(CCR, lch); ccr &= ~(1 << 5); if (sync_mode == OMAP_DMA_SYNC_FRAME) ccr |= 1 << 5; - dma_write(ccr, CCR(lch)); + dma_write(ccr, CCR, lch); - ccr = dma_read(CCR2(lch)); + ccr = dma_read(CCR2, lch); ccr &= ~(1 << 2); if (sync_mode == OMAP_DMA_SYNC_BLOCK) ccr |= 1 << 2; - dma_write(ccr, CCR2(lch)); + dma_write(ccr, CCR2, lch); } if (cpu_class_is_omap2() && dma_trigger) { u32 val; - val = dma_read(CCR(lch)); + val = dma_read(CCR, lch); /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ val &= ~((1 << 23) | (3 << 19) | 0x1f); @@ -313,11 +430,11 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, } else { val &= ~(1 << 24); /* dest synch */ } - dma_write(val, CCR(lch)); + dma_write(val, CCR, lch); } - dma_write(elem_count, CEN(lch)); - dma_write(frame_count, CFN(lch)); + dma_write(elem_count, CEN, lch); + dma_write(frame_count, CFN, lch); } EXPORT_SYMBOL(omap_set_dma_transfer_params); @@ -328,7 +445,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) if (cpu_class_is_omap1()) { u16 w; - w = dma_read(CCR2(lch)); + w = dma_read(CCR2, lch); w &= ~0x03; switch (mode) { @@ -343,23 +460,22 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) default: BUG(); } - dma_write(w, CCR2(lch)); + dma_write(w, CCR2, lch); - w = dma_read(LCH_CTRL(lch)); + w = dma_read(LCH_CTRL, lch); w &= ~0x0f; /* Default is channel type 2D */ if (mode) { - dma_write((u16)color, COLOR_L(lch)); - dma_write((u16)(color >> 16), COLOR_U(lch)); + dma_write(color, COLOR, lch); w |= 1; /* Channel type G */ } - dma_write(w, LCH_CTRL(lch)); + dma_write(w, LCH_CTRL, lch); } if (cpu_class_is_omap2()) { u32 val; - val = dma_read(CCR(lch)); + val = dma_read(CCR, lch); val &= ~((1 << 17) | (1 << 16)); switch (mode) { @@ -374,10 +490,10 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) default: BUG(); } - dma_write(val, CCR(lch)); + dma_write(val, CCR, lch); color &= 0xffffff; - dma_write(color, COLOR(lch)); + dma_write(color, COLOR, lch); } } EXPORT_SYMBOL(omap_set_dma_color_mode); @@ -387,10 +503,10 @@ void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode) if (cpu_class_is_omap2()) { u32 csdp; - csdp = dma_read(CSDP(lch)); + csdp = dma_read(CSDP, lch); csdp &= ~(0x3 << 16); csdp |= (mode << 16); - dma_write(csdp, CSDP(lch)); + dma_write(csdp, CSDP, lch); } } EXPORT_SYMBOL(omap_set_dma_write_mode); @@ -400,10 +516,10 @@ void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode) if (cpu_class_is_omap1() && !cpu_is_omap15xx()) { u32 l; - l = dma_read(LCH_CTRL(lch)); + l = dma_read(LCH_CTRL, lch); l &= ~0x7; l |= mode; - dma_write(l, LCH_CTRL(lch)); + dma_write(l, LCH_CTRL, lch); } } EXPORT_SYMBOL(omap_set_dma_channel_mode); @@ -418,27 +534,21 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode, if (cpu_class_is_omap1()) { u16 w; - w = dma_read(CSDP(lch)); + w = dma_read(CSDP, lch); w &= ~(0x1f << 2); w |= src_port << 2; - dma_write(w, CSDP(lch)); + dma_write(w, CSDP, lch); } - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); l &= ~(0x03 << 12); l |= src_amode << 12; - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); - if (cpu_class_is_omap1()) { - dma_write(src_start >> 16, CSSA_U(lch)); - dma_write((u16)src_start, CSSA_L(lch)); - } + dma_write(src_start, CSSA, lch); - if (cpu_class_is_omap2()) - dma_write(src_start, CSSA(lch)); - - dma_write(src_ei, CSEI(lch)); - dma_write(src_fi, CSFI(lch)); + dma_write(src_ei, CSEI, lch); + dma_write(src_fi, CSFI, lch); } EXPORT_SYMBOL(omap_set_dma_src_params); @@ -466,8 +576,8 @@ void omap_set_dma_src_index(int lch, int eidx, int fidx) if (cpu_class_is_omap2()) return; - dma_write(eidx, CSEI(lch)); - dma_write(fidx, CSFI(lch)); + dma_write(eidx, CSEI, lch); + dma_write(fidx, CSFI, lch); } EXPORT_SYMBOL(omap_set_dma_src_index); @@ -475,11 +585,11 @@ void omap_set_dma_src_data_pack(int lch, int enable) { u32 l; - l = dma_read(CSDP(lch)); + l = dma_read(CSDP, lch); l &= ~(1 << 6); if (enable) l |= (1 << 6); - dma_write(l, CSDP(lch)); + dma_write(l, CSDP, lch); } EXPORT_SYMBOL(omap_set_dma_src_data_pack); @@ -488,7 +598,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) unsigned int burst = 0; u32 l; - l = dma_read(CSDP(lch)); + l = dma_read(CSDP, lch); l &= ~(0x03 << 7); switch (burst_mode) { @@ -524,7 +634,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) } l |= (burst << 7); - dma_write(l, CSDP(lch)); + dma_write(l, CSDP, lch); } EXPORT_SYMBOL(omap_set_dma_src_burst_mode); @@ -536,27 +646,21 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, u32 l; if (cpu_class_is_omap1()) { - l = dma_read(CSDP(lch)); + l = dma_read(CSDP, lch); l &= ~(0x1f << 9); l |= dest_port << 9; - dma_write(l, CSDP(lch)); + dma_write(l, CSDP, lch); } - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); l &= ~(0x03 << 14); l |= dest_amode << 14; - dma_write(l, CCR(lch)); - - if (cpu_class_is_omap1()) { - dma_write(dest_start >> 16, CDSA_U(lch)); - dma_write(dest_start, CDSA_L(lch)); - } + dma_write(l, CCR, lch); - if (cpu_class_is_omap2()) - dma_write(dest_start, CDSA(lch)); + dma_write(dest_start, CDSA, lch); - dma_write(dst_ei, CDEI(lch)); - dma_write(dst_fi, CDFI(lch)); + dma_write(dst_ei, CDEI, lch); + dma_write(dst_fi, CDFI, lch); } EXPORT_SYMBOL(omap_set_dma_dest_params); @@ -565,8 +669,8 @@ void omap_set_dma_dest_index(int lch, int eidx, int fidx) if (cpu_class_is_omap2()) return; - dma_write(eidx, CDEI(lch)); - dma_write(fidx, CDFI(lch)); + dma_write(eidx, CDEI, lch); + dma_write(fidx, CDFI, lch); } EXPORT_SYMBOL(omap_set_dma_dest_index); @@ -574,11 +678,11 @@ void omap_set_dma_dest_data_pack(int lch, int enable) { u32 l; - l = dma_read(CSDP(lch)); + l = dma_read(CSDP, lch); l &= ~(1 << 13); if (enable) l |= 1 << 13; - dma_write(l, CSDP(lch)); + dma_write(l, CSDP, lch); } EXPORT_SYMBOL(omap_set_dma_dest_data_pack); @@ -587,7 +691,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) unsigned int burst = 0; u32 l; - l = dma_read(CSDP(lch)); + l = dma_read(CSDP, lch); l &= ~(0x03 << 14); switch (burst_mode) { @@ -620,7 +724,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) return; } l |= (burst << 14); - dma_write(l, CSDP(lch)); + dma_write(l, CSDP, lch); } EXPORT_SYMBOL(omap_set_dma_dest_burst_mode); @@ -630,18 +734,18 @@ static inline void omap_enable_channel_irq(int lch) /* Clear CSR */ if (cpu_class_is_omap1()) - status = dma_read(CSR(lch)); + status = dma_read(CSR, lch); else if (cpu_class_is_omap2()) - dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch)); + dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); /* Enable some nice interrupts. */ - dma_write(dma_chan[lch].enabled_irqs, CICR(lch)); + dma_write(dma_chan[lch].enabled_irqs, CICR, lch); } static void omap_disable_channel_irq(int lch) { if (cpu_class_is_omap2()) - dma_write(0, CICR(lch)); + dma_write(0, CICR, lch); } void omap_enable_dma_irq(int lch, u16 bits) @@ -660,7 +764,7 @@ static inline void enable_lnk(int lch) { u32 l; - l = dma_read(CLNK_CTRL(lch)); + l = dma_read(CLNK_CTRL, lch); if (cpu_class_is_omap1()) l &= ~(1 << 14); @@ -675,18 +779,18 @@ static inline void enable_lnk(int lch) l = dma_chan[lch].next_linked_ch | (1 << 15); #endif - dma_write(l, CLNK_CTRL(lch)); + dma_write(l, CLNK_CTRL, lch); } static inline void disable_lnk(int lch) { u32 l; - l = dma_read(CLNK_CTRL(lch)); + l = dma_read(CLNK_CTRL, lch); /* Disable interrupts */ if (cpu_class_is_omap1()) { - dma_write(0, CICR(lch)); + dma_write(0, CICR, lch); /* Set the STOP_LNK bit */ l |= 1 << 14; } @@ -697,7 +801,7 @@ static inline void disable_lnk(int lch) l &= ~(1 << 15); } - dma_write(l, CLNK_CTRL(lch)); + dma_write(l, CLNK_CTRL, lch); dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; } @@ -710,9 +814,9 @@ static inline void omap2_enable_irq_lch(int lch) return; spin_lock_irqsave(&dma_chan_lock, flags); - val = dma_read(IRQENABLE_L0); + val = dma_read(IRQENABLE_L0, lch); val |= 1 << lch; - dma_write(val, IRQENABLE_L0); + dma_write(val, IRQENABLE_L0, lch); spin_unlock_irqrestore(&dma_chan_lock, flags); } @@ -725,9 +829,9 @@ static inline void omap2_disable_irq_lch(int lch) return; spin_lock_irqsave(&dma_chan_lock, flags); - val = dma_read(IRQENABLE_L0); + val = dma_read(IRQENABLE_L0, lch); val &= ~(1 << lch); - dma_write(val, IRQENABLE_L0); + dma_write(val, IRQENABLE_L0, lch); spin_unlock_irqrestore(&dma_chan_lock, flags); } @@ -792,17 +896,17 @@ int omap_request_dma(int dev_id, const char *dev_name, * Disable the 1510 compatibility mode and set the sync device * id. */ - dma_write(dev_id | (1 << 10), CCR(free_ch)); + dma_write(dev_id | (1 << 10), CCR, free_ch); } else if (cpu_is_omap7xx() || cpu_is_omap15xx()) { - dma_write(dev_id, CCR(free_ch)); + dma_write(dev_id, CCR, free_ch); } if (cpu_class_is_omap2()) { omap2_enable_irq_lch(free_ch); omap_enable_channel_irq(free_ch); /* Clear the CSR register and IRQ status register */ - dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(free_ch)); - dma_write(1 << free_ch, IRQSTATUS_L0); + dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch); + dma_write(1 << free_ch, IRQSTATUS_L0, 0); } *dma_ch_out = free_ch; @@ -823,23 +927,23 @@ void omap_free_dma(int lch) if (cpu_class_is_omap1()) { /* Disable all DMA interrupts for the channel. */ - dma_write(0, CICR(lch)); + dma_write(0, CICR, lch); /* Make sure the DMA transfer is stopped. */ - dma_write(0, CCR(lch)); + dma_write(0, CCR, lch); } if (cpu_class_is_omap2()) { omap2_disable_irq_lch(lch); /* Clear the CSR register and IRQ status register */ - dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(lch)); - dma_write(1 << lch, IRQSTATUS_L0); + dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); + dma_write(1 << lch, IRQSTATUS_L0, lch); /* Disable all DMA interrupts for the channel. */ - dma_write(0, CICR(lch)); + dma_write(0, CICR, lch); /* Make sure the DMA transfer is stopped. */ - dma_write(0, CCR(lch)); + dma_write(0, CCR, lch); omap_clear_dma(lch); } @@ -880,7 +984,7 @@ omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams) reg |= (0x3 & tparams) << 12; reg |= (arb_rate & 0xff) << 16; - dma_write(reg, GCR); + dma_write(reg, GCR, 0); } EXPORT_SYMBOL(omap_dma_set_global_params); @@ -903,14 +1007,14 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio, printk(KERN_ERR "Invalid channel id\n"); return -EINVAL; } - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); l &= ~((1 << 6) | (1 << 26)); if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26); else l |= ((read_prio & 0x1) << 6); - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); return 0; } @@ -929,19 +1033,18 @@ void omap_clear_dma(int lch) if (cpu_class_is_omap1()) { u32 l; - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); l &= ~OMAP_DMA_CCR_EN; - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); /* Clear pending interrupts */ - l = dma_read(CSR(lch)); + l = dma_read(CSR, lch); } if (cpu_class_is_omap2()) { - int i; - void __iomem *lch_base = omap_dma_base + OMAP_DMA4_CH_BASE(lch); - for (i = 0; i < 0x44; i += 4) - __raw_writel(0, lch_base + i); + int i = dma_common_ch_start; + for (; i <= dma_common_ch_end; i += 1) + dma_write(0, i, lch); } local_irq_restore(flags); @@ -957,9 +1060,9 @@ void omap_start_dma(int lch) * before starting dma transfer. */ if (cpu_is_omap15xx()) - dma_write(0, CPC(lch)); + dma_write(0, CPC, lch); else - dma_write(0, CDAC(lch)); + dma_write(0, CDAC, lch); if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { int next_lch, cur_lch; @@ -989,12 +1092,12 @@ void omap_start_dma(int lch) (cpu_is_omap243x() && omap_type() <= OMAP2430_REV_ES1_0)) { /* Errata: Need to write lch even if not using chaining */ - dma_write(lch, CLNK_CTRL(lch)); + dma_write(lch, CLNK_CTRL, lch); } omap_enable_channel_irq(lch); - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); /* * Errata: Inter Frame DMA buffering issue (All OMAP2420 and @@ -1010,7 +1113,7 @@ void omap_start_dma(int lch) l |= OMAP_DMA_CCR_BUFFERING_DISABLE; l |= OMAP_DMA_CCR_EN; - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); dma_chan[lch].flags |= OMAP_DMA_ACTIVE; } @@ -1022,41 +1125,41 @@ void omap_stop_dma(int lch) /* Disable all interrupts on the channel */ if (cpu_class_is_omap1()) - dma_write(0, CICR(lch)); + dma_write(0, CICR, lch); - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); /* OMAP3 Errata i541: sDMA FIFO draining does not finish */ if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) { int i = 0; u32 sys_cf; /* Configure No-Standby */ - l = dma_read(OCP_SYSCONFIG); + l = dma_read(OCP_SYSCONFIG, lch); sys_cf = l; l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK; l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE); - dma_write(l , OCP_SYSCONFIG); + dma_write(l , OCP_SYSCONFIG, 0); - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); l &= ~OMAP_DMA_CCR_EN; - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); /* Wait for sDMA FIFO drain */ - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE))) { udelay(5); i++; - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); } if (i >= 100) printk(KERN_ERR "DMA drain did not complete on " "lch %d\n", lch); /* Restore OCP_SYSCONFIG */ - dma_write(sys_cf, OCP_SYSCONFIG); + dma_write(sys_cf, OCP_SYSCONFIG, lch); } else { l &= ~OMAP_DMA_CCR_EN; - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); } if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { @@ -1122,19 +1225,19 @@ dma_addr_t omap_get_dma_src_pos(int lch) dma_addr_t offset = 0; if (cpu_is_omap15xx()) - offset = dma_read(CPC(lch)); + offset = dma_read(CPC, lch); else - offset = dma_read(CSAC(lch)); + offset = dma_read(CSAC, lch); /* * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is * read before the DMA controller finished disabling the channel. */ if (!cpu_is_omap15xx() && offset == 0) - offset = dma_read(CSAC(lch)); + offset = dma_read(CSAC, lch); if (cpu_class_is_omap1()) - offset |= (dma_read(CSSA_U(lch)) << 16); + offset |= (dma_read(CSSA, lch) & 0xFFFF0000); return offset; } @@ -1153,19 +1256,19 @@ dma_addr_t omap_get_dma_dst_pos(int lch) dma_addr_t offset = 0; if (cpu_is_omap15xx()) - offset = dma_read(CPC(lch)); + offset = dma_read(CPC, lch); else - offset = dma_read(CDAC(lch)); + offset = dma_read(CDAC, lch); /* * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is * read before the DMA controller finished disabling the channel. */ if (!cpu_is_omap15xx() && offset == 0) - offset = dma_read(CDAC(lch)); + offset = dma_read(CDAC, lch); if (cpu_class_is_omap1()) - offset |= (dma_read(CDSA_U(lch)) << 16); + offset |= (dma_read(CDSA, lch) & 0xFFFF0000); return offset; } @@ -1173,7 +1276,7 @@ EXPORT_SYMBOL(omap_get_dma_dst_pos); int omap_get_dma_active_status(int lch) { - return (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN) != 0; + return (dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0; } EXPORT_SYMBOL(omap_get_dma_active_status); @@ -1186,7 +1289,7 @@ int omap_dma_running(void) return 1; for (lch = 0; lch < dma_chan_count; lch++) - if (dma_read(CCR(lch)) & OMAP_DMA_CCR_EN) + if (dma_read(CCR, lch) & OMAP_DMA_CCR_EN) return 1; return 0; @@ -1201,8 +1304,8 @@ void omap_dma_link_lch(int lch_head, int lch_queue) { if (omap_dma_in_1510_mode()) { if (lch_head == lch_queue) { - dma_write(dma_read(CCR(lch_head)) | (3 << 8), - CCR(lch_head)); + dma_write(dma_read(CCR, lch_head) | (3 << 8), + CCR, lch_head); return; } printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); @@ -1228,8 +1331,8 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue) { if (omap_dma_in_1510_mode()) { if (lch_head == lch_queue) { - dma_write(dma_read(CCR(lch_head)) & ~(3 << 8), - CCR(lch_head)); + dma_write(dma_read(CCR, lch_head) & ~(3 << 8), + CCR, lch_head); return; } printk(KERN_ERR "DMA linking is not supported in 1510 mode\n"); @@ -1281,15 +1384,15 @@ static void create_dma_lch_chain(int lch_head, int lch_queue) lch_queue; } - l = dma_read(CLNK_CTRL(lch_head)); + l = dma_read(CLNK_CTRL, lch_head); l &= ~(0x1f); l |= lch_queue; - dma_write(l, CLNK_CTRL(lch_head)); + dma_write(l, CLNK_CTRL, lch_head); - l = dma_read(CLNK_CTRL(lch_queue)); + l = dma_read(CLNK_CTRL, lch_queue); l &= ~(0x1f); l |= (dma_chan[lch_queue].next_linked_ch); - dma_write(l, CLNK_CTRL(lch_queue)); + dma_write(l, CLNK_CTRL, lch_queue); } /** @@ -1565,13 +1668,13 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, /* Set the params to the free channel */ if (src_start != 0) - dma_write(src_start, CSSA(lch)); + dma_write(src_start, CSSA, lch); if (dest_start != 0) - dma_write(dest_start, CDSA(lch)); + dma_write(dest_start, CDSA, lch); /* Write the buffer size */ - dma_write(elem_count, CEN(lch)); - dma_write(frame_count, CFN(lch)); + dma_write(elem_count, CEN, lch); + dma_write(frame_count, CFN, lch); /* * If the chain is dynamically linked, @@ -1605,7 +1708,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, dma_chan[lch].state = DMA_CH_QUEUED; start_dma = 0; if (0 == ((1 << 7) & dma_read( - CCR(dma_chan[lch].prev_linked_ch)))) { + CCR, dma_chan[lch].prev_linked_ch))) { disable_lnk(dma_chan[lch]. prev_linked_ch); pr_debug("\n prev ch is stopped\n"); @@ -1621,7 +1724,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, } omap_enable_channel_irq(lch); - l = dma_read(CCR(lch)); + l = dma_read(CCR, lch); if ((0 == (l & (1 << 24)))) l &= ~(1 << 25); @@ -1632,12 +1735,12 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, l |= (1 << 7); dma_chan[lch].state = DMA_CH_STARTED; pr_debug("starting %d\n", lch); - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); } else start_dma = 0; } else { if (0 == (l & (1 << 7))) - dma_write(l, CCR(lch)); + dma_write(l, CCR, lch); } dma_chan[lch].flags |= OMAP_DMA_ACTIVE; } @@ -1682,7 +1785,7 @@ int omap_start_dma_chain_transfers(int chain_id) omap_enable_channel_irq(channels[0]); } - l = dma_read(CCR(channels[0])); + l = dma_read(CCR, channels[0]); l |= (1 << 7); dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED; dma_chan[channels[0]].state = DMA_CH_STARTED; @@ -1691,7 +1794,7 @@ int omap_start_dma_chain_transfers(int chain_id) l &= ~(1 << 25); else l |= (1 << 25); - dma_write(l, CCR(channels[0])); + dma_write(l, CCR, channels[0]); dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE; @@ -1730,18 +1833,18 @@ int omap_stop_dma_chain_transfers(int chain_id) * DMA Errata: * Special programming model needed to disable DMA before end of block */ - sys_cf = dma_read(OCP_SYSCONFIG); + sys_cf = dma_read(OCP_SYSCONFIG, 0); l = sys_cf; /* Middle mode reg set no Standby */ l &= ~((1 << 12)|(1 << 13)); - dma_write(l, OCP_SYSCONFIG); + dma_write(l, OCP_SYSCONFIG, 0); for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) { /* Stop the Channel transmission */ - l = dma_read(CCR(channels[i])); + l = dma_read(CCR, channels[i]); l &= ~(1 << 7); - dma_write(l, CCR(channels[i])); + dma_write(l, CCR, channels[i]); /* Disable the link in all the channels */ disable_lnk(channels[i]); @@ -1754,7 +1857,7 @@ int omap_stop_dma_chain_transfers(int chain_id) OMAP_DMA_CHAIN_QINIT(chain_id); /* Errata - put in the old value */ - dma_write(sys_cf, OCP_SYSCONFIG); + dma_write(sys_cf, OCP_SYSCONFIG, 0); return 0; } @@ -1796,8 +1899,8 @@ int omap_get_dma_chain_index(int chain_id, int *ei, int *fi) /* Get the current channel */ lch = channels[dma_linked_lch[chain_id].q_head]; - *ei = dma_read(CCEN(lch)); - *fi = dma_read(CCFN(lch)); + *ei = dma_read(CCEN, lch); + *fi = dma_read(CCFN, lch); return 0; } @@ -1834,7 +1937,7 @@ int omap_get_dma_chain_dst_pos(int chain_id) /* Get the current channel */ lch = channels[dma_linked_lch[chain_id].q_head]; - return dma_read(CDAC(lch)); + return dma_read(CDAC, lch); } EXPORT_SYMBOL(omap_get_dma_chain_dst_pos); @@ -1868,7 +1971,7 @@ int omap_get_dma_chain_src_pos(int chain_id) /* Get the current channel */ lch = channels[dma_linked_lch[chain_id].q_head]; - return dma_read(CSAC(lch)); + return dma_read(CSAC, lch); } EXPORT_SYMBOL(omap_get_dma_chain_src_pos); #endif /* ifndef CONFIG_ARCH_OMAP1 */ @@ -1885,7 +1988,7 @@ static int omap1_dma_handle_ch(int ch) csr = dma_chan[ch].saved_csr; dma_chan[ch].saved_csr = 0; } else - csr = dma_read(CSR(ch)); + csr = dma_read(CSR, ch); if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) { dma_chan[ch + 6].saved_csr = csr >> 7; csr &= 0x7f; @@ -1938,13 +2041,13 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id) static int omap2_dma_handle_ch(int ch) { - u32 status = dma_read(CSR(ch)); + u32 status = dma_read(CSR, ch); if (!status) { if (printk_ratelimit()) printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n", ch); - dma_write(1 << ch, IRQSTATUS_L0); + dma_write(1 << ch, IRQSTATUS_L0, ch); return 0; } if (unlikely(dma_chan[ch].dev_id == -1)) { @@ -1968,9 +2071,9 @@ static int omap2_dma_handle_ch(int ch) */ u32 ccr; - ccr = dma_read(CCR(ch)); + ccr = dma_read(CCR, ch); ccr &= ~OMAP_DMA_CCR_EN; - dma_write(ccr, CCR(ch)); + dma_write(ccr, CCR, ch); dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE; } } @@ -1981,16 +2084,16 @@ static int omap2_dma_handle_ch(int ch) printk(KERN_INFO "DMA misaligned error with device %d\n", dma_chan[ch].dev_id); - dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(ch)); - dma_write(1 << ch, IRQSTATUS_L0); + dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch); + dma_write(1 << ch, IRQSTATUS_L0, ch); /* read back the register to flush the write */ - dma_read(IRQSTATUS_L0); + dma_read(IRQSTATUS_L0, ch); /* If the ch is not chained then chain_id will be -1 */ if (dma_chan[ch].chain_id != -1) { int chain_id = dma_chan[ch].chain_id; dma_chan[ch].state = DMA_CH_NOTSTARTED; - if (dma_read(CLNK_CTRL(ch)) & (1 << 15)) + if (dma_read(CLNK_CTRL, ch) & (1 << 15)) dma_chan[dma_chan[ch].next_linked_ch].state = DMA_CH_STARTED; if (dma_linked_lch[chain_id].chain_mode == @@ -2000,10 +2103,10 @@ static int omap2_dma_handle_ch(int ch) if (!OMAP_DMA_CHAIN_QEMPTY(chain_id)) OMAP_DMA_CHAIN_INCQHEAD(chain_id); - status = dma_read(CSR(ch)); + status = dma_read(CSR, ch); } - dma_write(status, CSR(ch)); + dma_write(status, CSR, ch); if (likely(dma_chan[ch].callback != NULL)) dma_chan[ch].callback(ch, status, dma_chan[ch].data); @@ -2017,13 +2120,13 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id) u32 val, enable_reg; int i; - val = dma_read(IRQSTATUS_L0); + val = dma_read(IRQSTATUS_L0, 0); if (val == 0) { if (printk_ratelimit()) printk(KERN_WARNING "Spurious DMA IRQ\n"); return IRQ_HANDLED; } - enable_reg = dma_read(IRQENABLE_L0); + enable_reg = dma_read(IRQENABLE_L0, 0); val &= enable_reg; /* Dispatch only relevant interrupts */ for (i = 0; i < dma_lch_count && val != 0; i++) { if (val & 1) @@ -2049,21 +2152,21 @@ static struct irqaction omap24xx_dma_irq; void omap_dma_global_context_save(void) { omap_dma_global_context.dma_irqenable_l0 = - dma_read(IRQENABLE_L0); + dma_read(IRQENABLE_L0, 0); omap_dma_global_context.dma_ocp_sysconfig = - dma_read(OCP_SYSCONFIG); - omap_dma_global_context.dma_gcr = dma_read(GCR); + dma_read(OCP_SYSCONFIG, 0); + omap_dma_global_context.dma_gcr = dma_read(GCR, 0); } void omap_dma_global_context_restore(void) { int ch; - dma_write(omap_dma_global_context.dma_gcr, GCR); + dma_write(omap_dma_global_context.dma_gcr, GCR, 0); dma_write(omap_dma_global_context.dma_ocp_sysconfig, - OCP_SYSCONFIG); + OCP_SYSCONFIG, 0); dma_write(omap_dma_global_context.dma_irqenable_l0, - IRQENABLE_L0); + IRQENABLE_L0, 0); /* * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared @@ -2072,7 +2175,7 @@ void omap_dma_global_context_restore(void) * affects only secure devices. */ if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) - dma_write(0x3 , IRQSTATUS_L0); + dma_write(0x3 , IRQSTATUS_L0, 0); for (ch = 0; ch < dma_chan_count; ch++) if (dma_chan[ch].dev_id != -1) @@ -2106,6 +2209,21 @@ static int __init omap_init_dma(void) omap_dma_base = ioremap(base, SZ_4K); BUG_ON(!omap_dma_base); + if (cpu_class_is_omap1()) { + dma_stride = 0x40; + reg_map = reg_map_omap1; + dma_common_ch_start = CPC; + dma_common_ch_end = COLOR; + } else { + dma_stride = 0x60; + reg_map = reg_map_omap2; + dma_common_ch_start = CSDP; + if (cpu_is_omap3630() || cpu_is_omap4430()) + dma_common_ch_end = CCDN; + else + dma_common_ch_end = CCFN; + } + if (cpu_class_is_omap2() && omap_dma_reserve_channels && (omap_dma_reserve_channels <= dma_lch_count)) dma_lch_count = omap_dma_reserve_channels; @@ -2132,26 +2250,23 @@ static int __init omap_init_dma(void) enable_1510_mode = 1; } else if (cpu_is_omap16xx() || cpu_is_omap7xx()) { printk(KERN_INFO "OMAP DMA hardware version %d\n", - dma_read(HW_ID)); + dma_read(HW_ID, 0)); printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n", - (dma_read(CAPS_0_U) << 16) | - dma_read(CAPS_0_L), - (dma_read(CAPS_1_U) << 16) | - dma_read(CAPS_1_L), - dma_read(CAPS_2), dma_read(CAPS_3), - dma_read(CAPS_4)); + dma_read(CAPS_0, 0), dma_read(CAPS_1, 0), + dma_read(CAPS_2, 0), dma_read(CAPS_3, 0), + dma_read(CAPS_4, 0)); if (!enable_1510_mode) { u16 w; /* Disable OMAP 3.0/3.1 compatibility mode. */ - w = dma_read(GSCR); + w = dma_read(GSCR, 0); w |= 1 << 3; - dma_write(w, GSCR); + dma_write(w, GSCR, 0); dma_chan_count = 16; } else dma_chan_count = 9; } else if (cpu_class_is_omap2()) { - u8 revision = dma_read(REVISION) & 0xff; + u8 revision = dma_read(REVISION, 0) & 0xff; printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", revision >> 4, revision & 0xf); dma_chan_count = dma_lch_count; @@ -2210,14 +2325,14 @@ static int __init omap_init_dma(void) if (cpu_is_omap34xx() || cpu_is_omap44xx()) { /* Enable smartidle idlemodes and autoidle */ - u32 v = dma_read(OCP_SYSCONFIG); + u32 v = dma_read(OCP_SYSCONFIG, 0); v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK | DMA_SYSCONFIG_SIDLEMODE_MASK | DMA_SYSCONFIG_AUTOIDLE); v |= (DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | DMA_SYSCONFIG_AUTOIDLE); - dma_write(v , OCP_SYSCONFIG); + dma_write(v , OCP_SYSCONFIG, 0); /* reserve dma channels 0 and 1 in high security devices */ if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) { diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index 0cce4ca83aa0..dfb1b10dc920 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h @@ -27,136 +27,14 @@ /* Hardware registers for omap1 */ #define OMAP1_DMA_BASE (0xfffed800) -#define OMAP1_DMA_GCR 0x400 -#define OMAP1_DMA_GSCR 0x404 -#define OMAP1_DMA_GRST 0x408 -#define OMAP1_DMA_HW_ID 0x442 -#define OMAP1_DMA_PCH2_ID 0x444 -#define OMAP1_DMA_PCH0_ID 0x446 -#define OMAP1_DMA_PCH1_ID 0x448 -#define OMAP1_DMA_PCHG_ID 0x44a -#define OMAP1_DMA_PCHD_ID 0x44c -#define OMAP1_DMA_CAPS_0_U 0x44e -#define OMAP1_DMA_CAPS_0_L 0x450 -#define OMAP1_DMA_CAPS_1_U 0x452 -#define OMAP1_DMA_CAPS_1_L 0x454 -#define OMAP1_DMA_CAPS_2 0x456 -#define OMAP1_DMA_CAPS_3 0x458 -#define OMAP1_DMA_CAPS_4 0x45a -#define OMAP1_DMA_PCH2_SR 0x460 -#define OMAP1_DMA_PCH0_SR 0x480 -#define OMAP1_DMA_PCH1_SR 0x482 -#define OMAP1_DMA_PCHD_SR 0x4c0 - /* Hardware registers for omap2 and omap3 */ #define OMAP24XX_DMA4_BASE (L4_24XX_BASE + 0x56000) #define OMAP34XX_DMA4_BASE (L4_34XX_BASE + 0x56000) #define OMAP44XX_DMA4_BASE (L4_44XX_BASE + 0x56000) -#define OMAP_DMA4_REVISION 0x00 -#define OMAP_DMA4_GCR 0x78 -#define OMAP_DMA4_IRQSTATUS_L0 0x08 -#define OMAP_DMA4_IRQSTATUS_L1 0x0c -#define OMAP_DMA4_IRQSTATUS_L2 0x10 -#define OMAP_DMA4_IRQSTATUS_L3 0x14 -#define OMAP_DMA4_IRQENABLE_L0 0x18 -#define OMAP_DMA4_IRQENABLE_L1 0x1c -#define OMAP_DMA4_IRQENABLE_L2 0x20 -#define OMAP_DMA4_IRQENABLE_L3 0x24 -#define OMAP_DMA4_SYSSTATUS 0x28 -#define OMAP_DMA4_OCP_SYSCONFIG 0x2c -#define OMAP_DMA4_CAPS_0 0x64 -#define OMAP_DMA4_CAPS_2 0x6c -#define OMAP_DMA4_CAPS_3 0x70 -#define OMAP_DMA4_CAPS_4 0x74 - #define OMAP1_LOGICAL_DMA_CH_COUNT 17 #define OMAP_DMA4_LOGICAL_DMA_CH_COUNT 32 /* REVISIT: Is this 32 + 2? */ -/* Common channel specific registers for omap1 */ -#define OMAP1_DMA_CH_BASE(n) (0x40 * (n) + 0x00) -#define OMAP1_DMA_CSDP(n) (0x40 * (n) + 0x00) -#define OMAP1_DMA_CCR(n) (0x40 * (n) + 0x02) -#define OMAP1_DMA_CICR(n) (0x40 * (n) + 0x04) -#define OMAP1_DMA_CSR(n) (0x40 * (n) + 0x06) -#define OMAP1_DMA_CEN(n) (0x40 * (n) + 0x10) -#define OMAP1_DMA_CFN(n) (0x40 * (n) + 0x12) -#define OMAP1_DMA_CSFI(n) (0x40 * (n) + 0x14) -#define OMAP1_DMA_CSEI(n) (0x40 * (n) + 0x16) -#define OMAP1_DMA_CPC(n) (0x40 * (n) + 0x18) /* 15xx only */ -#define OMAP1_DMA_CSAC(n) (0x40 * (n) + 0x18) -#define OMAP1_DMA_CDAC(n) (0x40 * (n) + 0x1a) -#define OMAP1_DMA_CDEI(n) (0x40 * (n) + 0x1c) -#define OMAP1_DMA_CDFI(n) (0x40 * (n) + 0x1e) -#define OMAP1_DMA_CLNK_CTRL(n) (0x40 * (n) + 0x28) - -/* Common channel specific registers for omap2 */ -#define OMAP_DMA4_CH_BASE(n) (0x60 * (n) + 0x80) -#define OMAP_DMA4_CCR(n) (0x60 * (n) + 0x80) -#define OMAP_DMA4_CLNK_CTRL(n) (0x60 * (n) + 0x84) -#define OMAP_DMA4_CICR(n) (0x60 * (n) + 0x88) -#define OMAP_DMA4_CSR(n) (0x60 * (n) + 0x8c) -#define OMAP_DMA4_CSDP(n) (0x60 * (n) + 0x90) -#define OMAP_DMA4_CEN(n) (0x60 * (n) + 0x94) -#define OMAP_DMA4_CFN(n) (0x60 * (n) + 0x98) -#define OMAP_DMA4_CSEI(n) (0x60 * (n) + 0xa4) -#define OMAP_DMA4_CSFI(n) (0x60 * (n) + 0xa8) -#define OMAP_DMA4_CDEI(n) (0x60 * (n) + 0xac) -#define OMAP_DMA4_CDFI(n) (0x60 * (n) + 0xb0) -#define OMAP_DMA4_CSAC(n) (0x60 * (n) + 0xb4) -#define OMAP_DMA4_CDAC(n) (0x60 * (n) + 0xb8) - -/* Channel specific registers only on omap1 */ -#define OMAP1_DMA_CSSA_L(n) (0x40 * (n) + 0x08) -#define OMAP1_DMA_CSSA_U(n) (0x40 * (n) + 0x0a) -#define OMAP1_DMA_CDSA_L(n) (0x40 * (n) + 0x0c) -#define OMAP1_DMA_CDSA_U(n) (0x40 * (n) + 0x0e) -#define OMAP1_DMA_COLOR_L(n) (0x40 * (n) + 0x20) -#define OMAP1_DMA_COLOR_U(n) (0x40 * (n) + 0x22) -#define OMAP1_DMA_CCR2(n) (0x40 * (n) + 0x24) -#define OMAP1_DMA_LCH_CTRL(n) (0x40 * (n) + 0x2a) /* not on 15xx */ -#define OMAP1_DMA_CCEN(n) 0 -#define OMAP1_DMA_CCFN(n) 0 - -/* Channel specific registers only on omap2 */ -#define OMAP_DMA4_CSSA(n) (0x60 * (n) + 0x9c) -#define OMAP_DMA4_CDSA(n) (0x60 * (n) + 0xa0) -#define OMAP_DMA4_CCEN(n) (0x60 * (n) + 0xbc) -#define OMAP_DMA4_CCFN(n) (0x60 * (n) + 0xc0) -#define OMAP_DMA4_COLOR(n) (0x60 * (n) + 0xc4) - -/* Additional registers available on OMAP4 */ -#define OMAP_DMA4_CDP(n) (0x60 * (n) + 0xd0) -#define OMAP_DMA4_CNDP(n) (0x60 * (n) + 0xd4) -#define OMAP_DMA4_CCDN(n) (0x60 * (n) + 0xd8) - -/* Dummy defines to keep multi-omap compiles happy */ -#define OMAP1_DMA_REVISION 0 -#define OMAP1_DMA_IRQSTATUS_L0 0 -#define OMAP1_DMA_IRQENABLE_L0 0 -#define OMAP1_DMA_OCP_SYSCONFIG 0 -#define OMAP_DMA4_HW_ID 0 -#define OMAP_DMA4_CAPS_0_L 0 -#define OMAP_DMA4_CAPS_0_U 0 -#define OMAP_DMA4_CAPS_1_L 0 -#define OMAP_DMA4_CAPS_1_U 0 -#define OMAP_DMA4_GSCR 0 -#define OMAP_DMA4_CPC(n) 0 - -#define OMAP_DMA4_LCH_CTRL(n) 0 -#define OMAP_DMA4_COLOR_L(n) 0 -#define OMAP_DMA4_COLOR_U(n) 0 -#define OMAP_DMA4_CCR2(n) 0 -#define OMAP1_DMA_CSSA(n) 0 -#define OMAP1_DMA_CDSA(n) 0 -#define OMAP_DMA4_CSSA_L(n) 0 -#define OMAP_DMA4_CSSA_U(n) 0 -#define OMAP_DMA4_CDSA_L(n) 0 -#define OMAP_DMA4_CDSA_U(n) 0 -#define OMAP1_DMA_COLOR(n) 0 - -/*----------------------------------------------------------------------------*/ - /* DMA channels for omap1 */ #define OMAP_DMA_NO_DEVICE 0 #define OMAP_DMA_MCSI1_TX 1 @@ -405,6 +283,35 @@ #define DMA_CH_PRIO_HIGH 0x1 #define DMA_CH_PRIO_LOW 0x0 /* Def */ +enum omap_reg_offsets { + +GCR, GSCR, GRST1, HW_ID, +PCH2_ID, PCH0_ID, PCH1_ID, PCHG_ID, +PCHD_ID, CAPS_0, CAPS_1, CAPS_2, +CAPS_3, CAPS_4, PCH2_SR, PCH0_SR, +PCH1_SR, PCHD_SR, REVISION, IRQSTATUS_L0, +IRQSTATUS_L1, IRQSTATUS_L2, IRQSTATUS_L3, IRQENABLE_L0, +IRQENABLE_L1, IRQENABLE_L2, IRQENABLE_L3, SYSSTATUS, +OCP_SYSCONFIG, + +/* omap1+ specific */ +CPC, CCR2, LCH_CTRL, + +/* Common registers for all omap's */ +CSDP, CCR, CICR, CSR, +CEN, CFN, CSFI, CSEI, +CSAC, CDAC, CDEI, +CDFI, CLNK_CTRL, + +/* Channel specific registers */ +CSSA, CDSA, COLOR, +CCEN, CCFN, + +/* omap3630 and omap4 specific */ +CDP, CNDP, CCDN, + +}; + enum omap_dma_burst_mode { OMAP_DMA_DATA_BURST_DIS = 0, OMAP_DMA_DATA_BURST_4, -- cgit v1.2.3 From d3c9be2f42223f256d06b2b69ed26afdcb02f64a Mon Sep 17 00:00:00 2001 From: "G, Manjunath Kondaiah" Date: Mon, 20 Dec 2010 18:27:18 -0800 Subject: OMAP: DMA: Introduce errata handling feature Implement errata handling to use flags instead of cpu_is_* and cpu_class_* in the code. The errata flags are initialized at init time and during runtime we are using the errata variable (via the IS_DMA_ERRATA macro) to execute the required errata workaround. Reused errata handling patch from: Peter Ujfalusi https://patchwork.kernel.org/patch/231191/ Changes to above patch: 1. Changes are done for converting all the existing errata work arounds to use this feature. 2. Detailed description for each errata is added. 3. Fixed bug in SET_DMA_ERRATA macro 4. Bit shifting in macro definitions are replaced with BIT() macro Signed-off-by: G, Manjunath Kondaiah Tested-by: Kevin Hilman Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 152 +++++++++++++++++++++++----------- arch/arm/plat-omap/include/plat/dma.h | 12 +++ 2 files changed, 114 insertions(+), 50 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 49a7cd4763f9..6f51bf37ec02 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -144,6 +144,7 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED }; #define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec) static int enable_1510_mode; +static u32 errata; static struct omap_dma_global_context_registers { u32 dma_irqenable_l0; @@ -1088,31 +1089,17 @@ void omap_start_dma(int lch) cur_lch = next_lch; } while (next_lch != -1); - } else if (cpu_is_omap242x() || - (cpu_is_omap243x() && omap_type() <= OMAP2430_REV_ES1_0)) { - - /* Errata: Need to write lch even if not using chaining */ + } else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS)) dma_write(lch, CLNK_CTRL, lch); - } omap_enable_channel_irq(lch); l = dma_read(CCR, lch); - /* - * Errata: Inter Frame DMA buffering issue (All OMAP2420 and - * OMAP2430ES1.0): DMA will wrongly buffer elements if packing and - * bursting is enabled. This might result in data gets stalled in - * FIFO at the end of the block. - * Workaround: DMA channels must have BUFFERING_DISABLED bit set to - * guarantee no data will stay in the DMA FIFO in case inter frame - * buffering occurs. - */ - if (cpu_is_omap2420() || - (cpu_is_omap2430() && (omap_type() == OMAP2430_REV_ES1_0))) - l |= OMAP_DMA_CCR_BUFFERING_DISABLE; - + if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING)) + l |= OMAP_DMA_CCR_BUFFERING_DISABLE; l |= OMAP_DMA_CCR_EN; + dma_write(l, CCR, lch); dma_chan[lch].flags |= OMAP_DMA_ACTIVE; @@ -1128,8 +1115,8 @@ void omap_stop_dma(int lch) dma_write(0, CICR, lch); l = dma_read(CCR, lch); - /* OMAP3 Errata i541: sDMA FIFO draining does not finish */ - if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) { + if (IS_DMA_ERRATA(DMA_ERRATA_i541) && + (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) { int i = 0; u32 sys_cf; @@ -1229,11 +1216,7 @@ dma_addr_t omap_get_dma_src_pos(int lch) else offset = dma_read(CSAC, lch); - /* - * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is - * read before the DMA controller finished disabling the channel. - */ - if (!cpu_is_omap15xx() && offset == 0) + if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0) offset = dma_read(CSAC, lch); if (cpu_class_is_omap1()) @@ -1814,7 +1797,7 @@ int omap_stop_dma_chain_transfers(int chain_id) { int *channels; u32 l, i; - u32 sys_cf; + u32 sys_cf = 0; /* Check for input params */ if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) { @@ -1829,15 +1812,13 @@ int omap_stop_dma_chain_transfers(int chain_id) } channels = dma_linked_lch[chain_id].linked_dmach_q; - /* - * DMA Errata: - * Special programming model needed to disable DMA before end of block - */ - sys_cf = dma_read(OCP_SYSCONFIG, 0); - l = sys_cf; - /* Middle mode reg set no Standby */ - l &= ~((1 << 12)|(1 << 13)); - dma_write(l, OCP_SYSCONFIG, 0); + if (IS_DMA_ERRATA(DMA_ERRATA_i88)) { + sys_cf = dma_read(OCP_SYSCONFIG, 0); + l = sys_cf; + /* Middle mode reg set no Standby */ + l &= ~((1 << 12)|(1 << 13)); + dma_write(l, OCP_SYSCONFIG, 0); + } for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) { @@ -1856,8 +1837,8 @@ int omap_stop_dma_chain_transfers(int chain_id) /* Reset the Queue pointers */ OMAP_DMA_CHAIN_QINIT(chain_id); - /* Errata - put in the old value */ - dma_write(sys_cf, OCP_SYSCONFIG, 0); + if (IS_DMA_ERRATA(DMA_ERRATA_i88)) + dma_write(sys_cf, OCP_SYSCONFIG, 0); return 0; } @@ -2063,12 +2044,7 @@ static int omap2_dma_handle_ch(int ch) if (unlikely(status & OMAP2_DMA_TRANS_ERR_IRQ)) { printk(KERN_INFO "DMA transaction error with device %d\n", dma_chan[ch].dev_id); - if (cpu_class_is_omap2()) { - /* - * Errata: sDMA Channel is not disabled - * after a transaction error. So we explicitely - * disable the channel - */ + if (IS_DMA_ERRATA(DMA_ERRATA_i378)) { u32 ccr; ccr = dma_read(CCR, ch); @@ -2168,13 +2144,7 @@ void omap_dma_global_context_restore(void) dma_write(omap_dma_global_context.dma_irqenable_l0, IRQENABLE_L0, 0); - /* - * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared - * after secure sram context save and restore. Hence we need to - * manually clear those IRQs to avoid spurious interrupts. This - * affects only secure devices. - */ - if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) + if (IS_DMA_ERRATA(DMA_ROMCODE_BUG)) dma_write(0x3 , IRQSTATUS_L0, 0); for (ch = 0; ch < dma_chan_count; ch++) @@ -2182,6 +2152,87 @@ void omap_dma_global_context_restore(void) omap_clear_dma(ch); } +static void configure_dma_errata(void) +{ + + /* + * Errata applicable for OMAP2430ES1.0 and all omap2420 + * + * I. + * Erratum ID: Not Available + * Inter Frame DMA buffering issue DMA will wrongly + * buffer elements if packing and bursting is enabled. This might + * result in data gets stalled in FIFO at the end of the block. + * Workaround: DMA channels must have BUFFERING_DISABLED bit set to + * guarantee no data will stay in the DMA FIFO in case inter frame + * buffering occurs + * + * II. + * Erratum ID: Not Available + * DMA may hang when several channels are used in parallel + * In the following configuration, DMA channel hanging can occur: + * a. Channel i, hardware synchronized, is enabled + * b. Another channel (Channel x), software synchronized, is enabled. + * c. Channel i is disabled before end of transfer + * d. Channel i is reenabled. + * e. Steps 1 to 4 are repeated a certain number of times. + * f. A third channel (Channel y), software synchronized, is enabled. + * Channel x and Channel y may hang immediately after step 'f'. + * Workaround: + * For any channel used - make sure NextLCH_ID is set to the value j. + */ + if (cpu_is_omap2420() || (cpu_is_omap2430() && + (omap_type() == OMAP2430_REV_ES1_0))) { + SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING); + SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS); + } + + /* + * Erratum ID: i378: OMAP2plus: sDMA Channel is not disabled + * after a transaction error. + * Workaround: SW should explicitely disable the channel. + */ + if (cpu_class_is_omap2()) + SET_DMA_ERRATA(DMA_ERRATA_i378); + + /* + * Erratum ID: i541: sDMA FIFO draining does not finish + * If sDMA channel is disabled on the fly, sDMA enters standby even + * through FIFO Drain is still in progress + * Workaround: Put sDMA in NoStandby more before a logical channel is + * disabled, then put it back to SmartStandby right after the channel + * finishes FIFO draining. + */ + if (cpu_is_omap34xx()) + SET_DMA_ERRATA(DMA_ERRATA_i541); + + /* + * Erratum ID: i88 : Special programming model needed to disable DMA + * before end of block. + * Workaround: software must ensure that the DMA is configured in No + * Standby mode(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01") + */ + if (cpu_is_omap34xx() && (omap_type() == OMAP3430_REV_ES1_0)) + SET_DMA_ERRATA(DMA_ERRATA_i88); + + /* + * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is + * read before the DMA controller finished disabling the channel. + */ + if (!cpu_is_omap15xx()) + SET_DMA_ERRATA(DMA_ERRATA_3_3); + + /* + * Erratum ID: Not Available + * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared + * after secure sram context save and restore. + * Work around: Hence we need to manually clear those IRQs to avoid + * spurious interrupts. This affects only secure devices. + */ + if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) + SET_DMA_ERRATA(DMA_ROMCODE_BUG); +} + /*----------------------------------------------------------------------------*/ static int __init omap_init_dma(void) @@ -2342,6 +2393,7 @@ static int __init omap_init_dma(void) dma_chan[1].dev_id = 1; } } + configure_dma_errata(); return 0; diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index dfb1b10dc920..23783990eb9a 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h @@ -283,6 +283,18 @@ #define DMA_CH_PRIO_HIGH 0x1 #define DMA_CH_PRIO_LOW 0x0 /* Def */ +/* Errata handling */ +#define IS_DMA_ERRATA(id) (errata & (id)) +#define SET_DMA_ERRATA(id) (errata |= (id)) + +#define DMA_ERRATA_IFRAME_BUFFERING BIT(0x0) +#define DMA_ERRATA_PARALLEL_CHANNELS BIT(0x1) +#define DMA_ERRATA_i378 BIT(0x2) +#define DMA_ERRATA_i541 BIT(0x3) +#define DMA_ERRATA_i88 BIT(0x4) +#define DMA_ERRATA_3_3 BIT(0x5) +#define DMA_ROMCODE_BUG BIT(0x6) + enum omap_reg_offsets { GCR, GSCR, GRST1, HW_ID, -- cgit v1.2.3 From 745685df95961ebbf0bcafcf28f31217a75070ae Mon Sep 17 00:00:00 2001 From: "G, Manjunath Kondaiah" Date: Mon, 20 Dec 2010 18:27:18 -0800 Subject: OMAP2420: hwmod data: add system DMA Add OMAP2420 DMA hwmod data and also add required DMA device attributes. Signed-off-by: G, Manjunath Kondaiah Acked-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/dma.h | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index 23783990eb9a..c4665669a8a3 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h @@ -295,6 +295,13 @@ #define DMA_ERRATA_3_3 BIT(0x5) #define DMA_ROMCODE_BUG BIT(0x6) +/* Attributes for OMAP DMA Contrller */ +#define DMA_LINKED_LCH BIT(0x0) +#define GLOBAL_PRIORITY BIT(0x1) +#define RESERVE_CHANNEL BIT(0x2) +#define IS_CSSA_32 BIT(0x3) +#define IS_CDSA_32 BIT(0x4) + enum omap_reg_offsets { GCR, GSCR, GRST1, HW_ID, @@ -389,6 +396,10 @@ struct omap_dma_channel_params { #endif }; +struct omap_dma_dev_attr { + u32 dev_caps; + u16 lch_count; +}; extern void omap_set_dma_priority(int lch, int dst_port, int priority); extern int omap_request_dma(int dev_id, const char *dev_name, -- cgit v1.2.3 From 82cbd1aebafd126f40a8ed0725a6feb6ed710576 Mon Sep 17 00:00:00 2001 From: "G, Manjunath Kondaiah" Date: Mon, 20 Dec 2010 18:27:18 -0800 Subject: OMAP2430: hwmod data: add system DMA Add OMAP2430 DMA hwmod data and also add required DMA device attributes. Signed-off-by: G, Manjunath Kondaiah Acked-by: Paul Walmsley Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/dma.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index c4665669a8a3..4b51d2b93b0e 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h @@ -301,6 +301,7 @@ #define RESERVE_CHANNEL BIT(0x2) #define IS_CSSA_32 BIT(0x3) #define IS_CDSA_32 BIT(0x4) +#define IS_RW_PRIORITY BIT(0x5) enum omap_reg_offsets { -- cgit v1.2.3 From f31cc9622d75c1c6f041d786698daa425c0425c2 Mon Sep 17 00:00:00 2001 From: "G, Manjunath Kondaiah" Date: Mon, 20 Dec 2010 18:27:19 -0800 Subject: OMAP: DMA: Convert DMA library into platform driver Convert DMA library into DMA platform driver and make use of platform data provided by hwmod data base for OMAP2+ onwards. For OMAP1 processors, the DMA driver in mach-omap uses resource structures for getting platform data. Thanks to Tony Lindgren for fixing various omap1 issues and testing the same on OSK5912 board. Signed-off-by: G, Manjunath Kondaiah Tested-by: Kevin Hilman Acked-by: Kevin Hilman Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/dma.c | 820 +++++++++++----------------------- arch/arm/plat-omap/include/plat/dma.h | 57 ++- 2 files changed, 316 insertions(+), 561 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/dma.c b/arch/arm/plat-omap/dma.c index 6f51bf37ec02..c4b2b478b1a5 100644 --- a/arch/arm/plat-omap/dma.c +++ b/arch/arm/plat-omap/dma.c @@ -15,6 +15,10 @@ * * Support functions for the OMAP internal DMA channels. * + * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/ + * Converted DMA library into DMA platform driver. + * - G, Manjunath Kondaiah + * * 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. @@ -40,96 +44,6 @@ #undef DEBUG -static u16 reg_map_omap1[] = { - [GCR] = 0x400, - [GSCR] = 0x404, - [GRST1] = 0x408, - [HW_ID] = 0x442, - [PCH2_ID] = 0x444, - [PCH0_ID] = 0x446, - [PCH1_ID] = 0x448, - [PCHG_ID] = 0x44a, - [PCHD_ID] = 0x44c, - [CAPS_0] = 0x44e, - [CAPS_1] = 0x452, - [CAPS_2] = 0x456, - [CAPS_3] = 0x458, - [CAPS_4] = 0x45a, - [PCH2_SR] = 0x460, - [PCH0_SR] = 0x480, - [PCH1_SR] = 0x482, - [PCHD_SR] = 0x4c0, - - /* Common Registers */ - [CSDP] = 0x00, - [CCR] = 0x02, - [CICR] = 0x04, - [CSR] = 0x06, - [CEN] = 0x10, - [CFN] = 0x12, - [CSFI] = 0x14, - [CSEI] = 0x16, - [CPC] = 0x18, /* 15xx only */ - [CSAC] = 0x18, - [CDAC] = 0x1a, - [CDEI] = 0x1c, - [CDFI] = 0x1e, - [CLNK_CTRL] = 0x28, - - /* Channel specific register offsets */ - [CSSA] = 0x08, - [CDSA] = 0x0c, - [COLOR] = 0x20, - [CCR2] = 0x24, - [LCH_CTRL] = 0x2a, -}; - -static u16 reg_map_omap2[] = { - [REVISION] = 0x00, - [GCR] = 0x78, - [IRQSTATUS_L0] = 0x08, - [IRQSTATUS_L1] = 0x0c, - [IRQSTATUS_L2] = 0x10, - [IRQSTATUS_L3] = 0x14, - [IRQENABLE_L0] = 0x18, - [IRQENABLE_L1] = 0x1c, - [IRQENABLE_L2] = 0x20, - [IRQENABLE_L3] = 0x24, - [SYSSTATUS] = 0x28, - [OCP_SYSCONFIG] = 0x2c, - [CAPS_0] = 0x64, - [CAPS_2] = 0x6c, - [CAPS_3] = 0x70, - [CAPS_4] = 0x74, - - /* Common register offsets */ - [CCR] = 0x80, - [CLNK_CTRL] = 0x84, - [CICR] = 0x88, - [CSR] = 0x8c, - [CSDP] = 0x90, - [CEN] = 0x94, - [CFN] = 0x98, - [CSEI] = 0xa4, - [CSFI] = 0xa8, - [CDEI] = 0xac, - [CDFI] = 0xb0, - [CSAC] = 0xb4, - [CDAC] = 0xb8, - - /* Channel specific register offsets */ - [CSSA] = 0x9c, - [CDSA] = 0xa0, - [CCEN] = 0xbc, - [CCFN] = 0xc0, - [COLOR] = 0xc4, - - /* OMAP4 specific registers */ - [CDP] = 0xd0, - [CNDP] = 0xd4, - [CCDN] = 0xd8, -}; - #ifndef CONFIG_ARCH_OMAP1 enum { DMA_CH_ALLOC_DONE, DMA_CH_PARAMS_SET_DONE, DMA_CH_STARTED, DMA_CH_QUEUED, DMA_CH_NOTSTARTED, DMA_CH_PAUSED, DMA_CH_LINK_ENABLED @@ -143,6 +57,9 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED }; #define OMAP_FUNC_MUX_ARM_BASE (0xfffe1000 + 0xec) +static struct omap_system_dma_plat_info *p; +static struct omap_dma_dev_attr *d; + static int enable_1510_mode; static u32 errata; @@ -152,27 +69,6 @@ static struct omap_dma_global_context_registers { u32 dma_gcr; } omap_dma_global_context; -struct omap_dma_lch { - int next_lch; - int dev_id; - u16 saved_csr; - u16 enabled_irqs; - const char *dev_name; - void (*callback)(int lch, u16 ch_status, void *data); - void *data; - -#ifndef CONFIG_ARCH_OMAP1 - /* required for Dynamic chaining */ - int prev_linked_ch; - int next_linked_ch; - int state; - int chain_id; - - int status; -#endif - long flags; -}; - struct dma_link_info { int *linked_dmach_q; int no_of_lchs_linked; @@ -228,18 +124,6 @@ static int omap_dma_reserve_channels; static spinlock_t dma_chan_lock; static struct omap_dma_lch *dma_chan; -static void __iomem *omap_dma_base; -static u16 *reg_map; -static u8 dma_stride; -static enum omap_reg_offsets dma_common_ch_start, dma_common_ch_end; - -static const u8 omap1_dma_irq[OMAP1_LOGICAL_DMA_CH_COUNT] = { - INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3, - INT_DMA_CH4, INT_DMA_CH5, INT_1610_DMA_CH6, INT_1610_DMA_CH7, - INT_1610_DMA_CH8, INT_1610_DMA_CH9, INT_1610_DMA_CH10, - INT_1610_DMA_CH11, INT_1610_DMA_CH12, INT_1610_DMA_CH13, - INT_1610_DMA_CH14, INT_1610_DMA_CH15, INT_DMA_LCD -}; static inline void disable_lnk(int lch); static void omap_disable_channel_irq(int lch); @@ -248,52 +132,9 @@ static inline void omap_enable_channel_irq(int lch); #define REVISIT_24XX() printk(KERN_ERR "FIXME: no %s on 24xx\n", \ __func__); -static inline void dma_write(u32 val, int reg, int lch) -{ - u8 stride; - u32 offset; - - stride = (reg >= dma_common_ch_start) ? dma_stride : 0; - offset = reg_map[reg] + (stride * lch); - - if (dma_stride == 0x40) { - __raw_writew(val, omap_dma_base + offset); - if ((reg > CLNK_CTRL && reg < CCEN) || - (reg > PCHD_ID && reg < CAPS_2)) { - u32 offset2 = reg_map[reg] + 2 + (stride * lch); - __raw_writew(val >> 16, omap_dma_base + offset2); - } - } else { - __raw_writel(val, omap_dma_base + offset); - } -} - -static inline u32 dma_read(int reg, int lch) -{ - u8 stride; - u32 offset, val; - - stride = (reg >= dma_common_ch_start) ? dma_stride : 0; - offset = reg_map[reg] + (stride * lch); - - if (dma_stride == 0x40) { - val = __raw_readw(omap_dma_base + offset); - if ((reg > CLNK_CTRL && reg < CCEN) || - (reg > PCHD_ID && reg < CAPS_2)) { - u16 upper; - u32 offset2 = reg_map[reg] + 2 + (stride * lch); - upper = __raw_readw(omap_dma_base + offset2); - val |= (upper << 16); - } - } else { - val = __raw_readl(omap_dma_base + offset); - } - return val; -} - #ifdef CONFIG_ARCH_OMAP15XX /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */ -static int omap_dma_in_1510_mode(void) +int omap_dma_in_1510_mode(void) { return enable_1510_mode; } @@ -325,15 +166,6 @@ static inline void set_gdma_dev(int req, int dev) #define set_gdma_dev(req, dev) do {} while (0) #endif -/* Omap1 only */ -static void clear_lch_regs(int lch) -{ - int i = dma_common_ch_start; - - for (; i <= dma_common_ch_end; i += 1) - dma_write(0, i, lch); -} - void omap_set_dma_priority(int lch, int dst_port, int priority) { unsigned long reg; @@ -366,12 +198,12 @@ void omap_set_dma_priority(int lch, int dst_port, int priority) if (cpu_class_is_omap2()) { u32 ccr; - ccr = dma_read(CCR, lch); + ccr = p->dma_read(CCR, lch); if (priority) ccr |= (1 << 6); else ccr &= ~(1 << 6); - dma_write(ccr, CCR, lch); + p->dma_write(ccr, CCR, lch); } } EXPORT_SYMBOL(omap_set_dma_priority); @@ -382,31 +214,31 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, { u32 l; - l = dma_read(CSDP, lch); + l = p->dma_read(CSDP, lch); l &= ~0x03; l |= data_type; - dma_write(l, CSDP, lch); + p->dma_write(l, CSDP, lch); if (cpu_class_is_omap1()) { u16 ccr; - ccr = dma_read(CCR, lch); + ccr = p->dma_read(CCR, lch); ccr &= ~(1 << 5); if (sync_mode == OMAP_DMA_SYNC_FRAME) ccr |= 1 << 5; - dma_write(ccr, CCR, lch); + p->dma_write(ccr, CCR, lch); - ccr = dma_read(CCR2, lch); + ccr = p->dma_read(CCR2, lch); ccr &= ~(1 << 2); if (sync_mode == OMAP_DMA_SYNC_BLOCK) ccr |= 1 << 2; - dma_write(ccr, CCR2, lch); + p->dma_write(ccr, CCR2, lch); } if (cpu_class_is_omap2() && dma_trigger) { u32 val; - val = dma_read(CCR, lch); + val = p->dma_read(CCR, lch); /* DMA_SYNCHRO_CONTROL_UPPER depends on the channel number */ val &= ~((1 << 23) | (3 << 19) | 0x1f); @@ -431,11 +263,11 @@ void omap_set_dma_transfer_params(int lch, int data_type, int elem_count, } else { val &= ~(1 << 24); /* dest synch */ } - dma_write(val, CCR, lch); + p->dma_write(val, CCR, lch); } - dma_write(elem_count, CEN, lch); - dma_write(frame_count, CFN, lch); + p->dma_write(elem_count, CEN, lch); + p->dma_write(frame_count, CFN, lch); } EXPORT_SYMBOL(omap_set_dma_transfer_params); @@ -446,7 +278,7 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) if (cpu_class_is_omap1()) { u16 w; - w = dma_read(CCR2, lch); + w = p->dma_read(CCR2, lch); w &= ~0x03; switch (mode) { @@ -461,22 +293,22 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) default: BUG(); } - dma_write(w, CCR2, lch); + p->dma_write(w, CCR2, lch); - w = dma_read(LCH_CTRL, lch); + w = p->dma_read(LCH_CTRL, lch); w &= ~0x0f; /* Default is channel type 2D */ if (mode) { - dma_write(color, COLOR, lch); + p->dma_write(color, COLOR, lch); w |= 1; /* Channel type G */ } - dma_write(w, LCH_CTRL, lch); + p->dma_write(w, LCH_CTRL, lch); } if (cpu_class_is_omap2()) { u32 val; - val = dma_read(CCR, lch); + val = p->dma_read(CCR, lch); val &= ~((1 << 17) | (1 << 16)); switch (mode) { @@ -491,10 +323,10 @@ void omap_set_dma_color_mode(int lch, enum omap_dma_color_mode mode, u32 color) default: BUG(); } - dma_write(val, CCR, lch); + p->dma_write(val, CCR, lch); color &= 0xffffff; - dma_write(color, COLOR, lch); + p->dma_write(color, COLOR, lch); } } EXPORT_SYMBOL(omap_set_dma_color_mode); @@ -504,10 +336,10 @@ void omap_set_dma_write_mode(int lch, enum omap_dma_write_mode mode) if (cpu_class_is_omap2()) { u32 csdp; - csdp = dma_read(CSDP, lch); + csdp = p->dma_read(CSDP, lch); csdp &= ~(0x3 << 16); csdp |= (mode << 16); - dma_write(csdp, CSDP, lch); + p->dma_write(csdp, CSDP, lch); } } EXPORT_SYMBOL(omap_set_dma_write_mode); @@ -517,10 +349,10 @@ void omap_set_dma_channel_mode(int lch, enum omap_dma_channel_mode mode) if (cpu_class_is_omap1() && !cpu_is_omap15xx()) { u32 l; - l = dma_read(LCH_CTRL, lch); + l = p->dma_read(LCH_CTRL, lch); l &= ~0x7; l |= mode; - dma_write(l, LCH_CTRL, lch); + p->dma_write(l, LCH_CTRL, lch); } } EXPORT_SYMBOL(omap_set_dma_channel_mode); @@ -535,21 +367,21 @@ void omap_set_dma_src_params(int lch, int src_port, int src_amode, if (cpu_class_is_omap1()) { u16 w; - w = dma_read(CSDP, lch); + w = p->dma_read(CSDP, lch); w &= ~(0x1f << 2); w |= src_port << 2; - dma_write(w, CSDP, lch); + p->dma_write(w, CSDP, lch); } - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); l &= ~(0x03 << 12); l |= src_amode << 12; - dma_write(l, CCR, lch); + p->dma_write(l, CCR, lch); - dma_write(src_start, CSSA, lch); + p->dma_write(src_start, CSSA, lch); - dma_write(src_ei, CSEI, lch); - dma_write(src_fi, CSFI, lch); + p->dma_write(src_ei, CSEI, lch); + p->dma_write(src_fi, CSFI, lch); } EXPORT_SYMBOL(omap_set_dma_src_params); @@ -577,8 +409,8 @@ void omap_set_dma_src_index(int lch, int eidx, int fidx) if (cpu_class_is_omap2()) return; - dma_write(eidx, CSEI, lch); - dma_write(fidx, CSFI, lch); + p->dma_write(eidx, CSEI, lch); + p->dma_write(fidx, CSFI, lch); } EXPORT_SYMBOL(omap_set_dma_src_index); @@ -586,11 +418,11 @@ void omap_set_dma_src_data_pack(int lch, int enable) { u32 l; - l = dma_read(CSDP, lch); + l = p->dma_read(CSDP, lch); l &= ~(1 << 6); if (enable) l |= (1 << 6); - dma_write(l, CSDP, lch); + p->dma_write(l, CSDP, lch); } EXPORT_SYMBOL(omap_set_dma_src_data_pack); @@ -599,7 +431,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) unsigned int burst = 0; u32 l; - l = dma_read(CSDP, lch); + l = p->dma_read(CSDP, lch); l &= ~(0x03 << 7); switch (burst_mode) { @@ -635,7 +467,7 @@ void omap_set_dma_src_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) } l |= (burst << 7); - dma_write(l, CSDP, lch); + p->dma_write(l, CSDP, lch); } EXPORT_SYMBOL(omap_set_dma_src_burst_mode); @@ -647,21 +479,21 @@ void omap_set_dma_dest_params(int lch, int dest_port, int dest_amode, u32 l; if (cpu_class_is_omap1()) { - l = dma_read(CSDP, lch); + l = p->dma_read(CSDP, lch); l &= ~(0x1f << 9); l |= dest_port << 9; - dma_write(l, CSDP, lch); + p->dma_write(l, CSDP, lch); } - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); l &= ~(0x03 << 14); l |= dest_amode << 14; - dma_write(l, CCR, lch); + p->dma_write(l, CCR, lch); - dma_write(dest_start, CDSA, lch); + p->dma_write(dest_start, CDSA, lch); - dma_write(dst_ei, CDEI, lch); - dma_write(dst_fi, CDFI, lch); + p->dma_write(dst_ei, CDEI, lch); + p->dma_write(dst_fi, CDFI, lch); } EXPORT_SYMBOL(omap_set_dma_dest_params); @@ -670,8 +502,8 @@ void omap_set_dma_dest_index(int lch, int eidx, int fidx) if (cpu_class_is_omap2()) return; - dma_write(eidx, CDEI, lch); - dma_write(fidx, CDFI, lch); + p->dma_write(eidx, CDEI, lch); + p->dma_write(fidx, CDFI, lch); } EXPORT_SYMBOL(omap_set_dma_dest_index); @@ -679,11 +511,11 @@ void omap_set_dma_dest_data_pack(int lch, int enable) { u32 l; - l = dma_read(CSDP, lch); + l = p->dma_read(CSDP, lch); l &= ~(1 << 13); if (enable) l |= 1 << 13; - dma_write(l, CSDP, lch); + p->dma_write(l, CSDP, lch); } EXPORT_SYMBOL(omap_set_dma_dest_data_pack); @@ -692,7 +524,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) unsigned int burst = 0; u32 l; - l = dma_read(CSDP, lch); + l = p->dma_read(CSDP, lch); l &= ~(0x03 << 14); switch (burst_mode) { @@ -725,7 +557,7 @@ void omap_set_dma_dest_burst_mode(int lch, enum omap_dma_burst_mode burst_mode) return; } l |= (burst << 14); - dma_write(l, CSDP, lch); + p->dma_write(l, CSDP, lch); } EXPORT_SYMBOL(omap_set_dma_dest_burst_mode); @@ -735,18 +567,18 @@ static inline void omap_enable_channel_irq(int lch) /* Clear CSR */ if (cpu_class_is_omap1()) - status = dma_read(CSR, lch); + status = p->dma_read(CSR, lch); else if (cpu_class_is_omap2()) - dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); + p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); /* Enable some nice interrupts. */ - dma_write(dma_chan[lch].enabled_irqs, CICR, lch); + p->dma_write(dma_chan[lch].enabled_irqs, CICR, lch); } static void omap_disable_channel_irq(int lch) { if (cpu_class_is_omap2()) - dma_write(0, CICR, lch); + p->dma_write(0, CICR, lch); } void omap_enable_dma_irq(int lch, u16 bits) @@ -765,7 +597,7 @@ static inline void enable_lnk(int lch) { u32 l; - l = dma_read(CLNK_CTRL, lch); + l = p->dma_read(CLNK_CTRL, lch); if (cpu_class_is_omap1()) l &= ~(1 << 14); @@ -780,18 +612,18 @@ static inline void enable_lnk(int lch) l = dma_chan[lch].next_linked_ch | (1 << 15); #endif - dma_write(l, CLNK_CTRL, lch); + p->dma_write(l, CLNK_CTRL, lch); } static inline void disable_lnk(int lch) { u32 l; - l = dma_read(CLNK_CTRL, lch); + l = p->dma_read(CLNK_CTRL, lch); /* Disable interrupts */ if (cpu_class_is_omap1()) { - dma_write(0, CICR, lch); + p->dma_write(0, CICR, lch); /* Set the STOP_LNK bit */ l |= 1 << 14; } @@ -802,7 +634,7 @@ static inline void disable_lnk(int lch) l &= ~(1 << 15); } - dma_write(l, CLNK_CTRL, lch); + p->dma_write(l, CLNK_CTRL, lch); dma_chan[lch].flags &= ~OMAP_DMA_ACTIVE; } @@ -815,9 +647,9 @@ static inline void omap2_enable_irq_lch(int lch) return; spin_lock_irqsave(&dma_chan_lock, flags); - val = dma_read(IRQENABLE_L0, lch); + val = p->dma_read(IRQENABLE_L0, lch); val |= 1 << lch; - dma_write(val, IRQENABLE_L0, lch); + p->dma_write(val, IRQENABLE_L0, lch); spin_unlock_irqrestore(&dma_chan_lock, flags); } @@ -830,9 +662,9 @@ static inline void omap2_disable_irq_lch(int lch) return; spin_lock_irqsave(&dma_chan_lock, flags); - val = dma_read(IRQENABLE_L0, lch); + val = p->dma_read(IRQENABLE_L0, lch); val &= ~(1 << lch); - dma_write(val, IRQENABLE_L0, lch); + p->dma_write(val, IRQENABLE_L0, lch); spin_unlock_irqrestore(&dma_chan_lock, flags); } @@ -859,8 +691,8 @@ int omap_request_dma(int dev_id, const char *dev_name, chan = dma_chan + free_ch; chan->dev_id = dev_id; - if (cpu_class_is_omap1()) - clear_lch_regs(free_ch); + if (p->clear_lch_regs) + p->clear_lch_regs(free_ch); if (cpu_class_is_omap2()) omap_clear_dma(free_ch); @@ -897,17 +729,17 @@ int omap_request_dma(int dev_id, const char *dev_name, * Disable the 1510 compatibility mode and set the sync device * id. */ - dma_write(dev_id | (1 << 10), CCR, free_ch); + p->dma_write(dev_id | (1 << 10), CCR, free_ch); } else if (cpu_is_omap7xx() || cpu_is_omap15xx()) { - dma_write(dev_id, CCR, free_ch); + p->dma_write(dev_id, CCR, free_ch); } if (cpu_class_is_omap2()) { omap2_enable_irq_lch(free_ch); omap_enable_channel_irq(free_ch); /* Clear the CSR register and IRQ status register */ - dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch); - dma_write(1 << free_ch, IRQSTATUS_L0, 0); + p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, free_ch); + p->dma_write(1 << free_ch, IRQSTATUS_L0, 0); } *dma_ch_out = free_ch; @@ -928,23 +760,23 @@ void omap_free_dma(int lch) if (cpu_class_is_omap1()) { /* Disable all DMA interrupts for the channel. */ - dma_write(0, CICR, lch); + p->dma_write(0, CICR, lch); /* Make sure the DMA transfer is stopped. */ - dma_write(0, CCR, lch); + p->dma_write(0, CCR, lch); } if (cpu_class_is_omap2()) { omap2_disable_irq_lch(lch); /* Clear the CSR register and IRQ status register */ - dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); - dma_write(1 << lch, IRQSTATUS_L0, lch); + p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, lch); + p->dma_write(1 << lch, IRQSTATUS_L0, lch); /* Disable all DMA interrupts for the channel. */ - dma_write(0, CICR, lch); + p->dma_write(0, CICR, lch); /* Make sure the DMA transfer is stopped. */ - dma_write(0, CCR, lch); + p->dma_write(0, CCR, lch); omap_clear_dma(lch); } @@ -985,7 +817,7 @@ omap_dma_set_global_params(int arb_rate, int max_fifo_depth, int tparams) reg |= (0x3 & tparams) << 12; reg |= (arb_rate & 0xff) << 16; - dma_write(reg, GCR, 0); + p->dma_write(reg, GCR, 0); } EXPORT_SYMBOL(omap_dma_set_global_params); @@ -1008,14 +840,14 @@ omap_dma_set_prio_lch(int lch, unsigned char read_prio, printk(KERN_ERR "Invalid channel id\n"); return -EINVAL; } - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); l &= ~((1 << 6) | (1 << 26)); if (cpu_is_omap2430() || cpu_is_omap34xx() || cpu_is_omap44xx()) l |= ((read_prio & 0x1) << 6) | ((write_prio & 0x1) << 26); else l |= ((read_prio & 0x1) << 6); - dma_write(l, CCR, lch); + p->dma_write(l, CCR, lch); return 0; } @@ -1030,24 +862,7 @@ void omap_clear_dma(int lch) unsigned long flags; local_irq_save(flags); - - if (cpu_class_is_omap1()) { - u32 l; - - l = dma_read(CCR, lch); - l &= ~OMAP_DMA_CCR_EN; - dma_write(l, CCR, lch); - - /* Clear pending interrupts */ - l = dma_read(CSR, lch); - } - - if (cpu_class_is_omap2()) { - int i = dma_common_ch_start; - for (; i <= dma_common_ch_end; i += 1) - dma_write(0, i, lch); - } - + p->clear_dma(lch); local_irq_restore(flags); } EXPORT_SYMBOL(omap_clear_dma); @@ -1061,13 +876,13 @@ void omap_start_dma(int lch) * before starting dma transfer. */ if (cpu_is_omap15xx()) - dma_write(0, CPC, lch); + p->dma_write(0, CPC, lch); else - dma_write(0, CDAC, lch); + p->dma_write(0, CDAC, lch); if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { int next_lch, cur_lch; - char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT]; + char dma_chan_link_map[dma_lch_count]; dma_chan_link_map[lch] = 1; /* Set the link register of the first channel */ @@ -1090,17 +905,17 @@ void omap_start_dma(int lch) cur_lch = next_lch; } while (next_lch != -1); } else if (IS_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS)) - dma_write(lch, CLNK_CTRL, lch); + p->dma_write(lch, CLNK_CTRL, lch); omap_enable_channel_irq(lch); - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); if (IS_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING)) l |= OMAP_DMA_CCR_BUFFERING_DISABLE; l |= OMAP_DMA_CCR_EN; - dma_write(l, CCR, lch); + p->dma_write(l, CCR, lch); dma_chan[lch].flags |= OMAP_DMA_ACTIVE; } @@ -1112,46 +927,46 @@ void omap_stop_dma(int lch) /* Disable all interrupts on the channel */ if (cpu_class_is_omap1()) - dma_write(0, CICR, lch); + p->dma_write(0, CICR, lch); - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); if (IS_DMA_ERRATA(DMA_ERRATA_i541) && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) { int i = 0; u32 sys_cf; /* Configure No-Standby */ - l = dma_read(OCP_SYSCONFIG, lch); + l = p->dma_read(OCP_SYSCONFIG, lch); sys_cf = l; l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK; l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE); - dma_write(l , OCP_SYSCONFIG, 0); + p->dma_write(l , OCP_SYSCONFIG, 0); - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); l &= ~OMAP_DMA_CCR_EN; - dma_write(l, CCR, lch); + p->dma_write(l, CCR, lch); /* Wait for sDMA FIFO drain */ - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); while (i < 100 && (l & (OMAP_DMA_CCR_RD_ACTIVE | OMAP_DMA_CCR_WR_ACTIVE))) { udelay(5); i++; - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); } if (i >= 100) printk(KERN_ERR "DMA drain did not complete on " "lch %d\n", lch); /* Restore OCP_SYSCONFIG */ - dma_write(sys_cf, OCP_SYSCONFIG, lch); + p->dma_write(sys_cf, OCP_SYSCONFIG, lch); } else { l &= ~OMAP_DMA_CCR_EN; - dma_write(l, CCR, lch); + p->dma_write(l, CCR, lch); } if (!omap_dma_in_1510_mode() && dma_chan[lch].next_lch != -1) { int next_lch, cur_lch = lch; - char dma_chan_link_map[OMAP_DMA4_LOGICAL_DMA_CH_COUNT]; + char dma_chan_link_map[dma_lch_count]; memset(dma_chan_link_map, 0, sizeof(dma_chan_link_map)); do { @@ -1212,15 +1027,15 @@ dma_addr_t omap_get_dma_src_pos(int lch) dma_addr_t offset = 0; if (cpu_is_omap15xx()) - offset = dma_read(CPC, lch); + offset = p->dma_read(CPC, lch); else - offset = dma_read(CSAC, lch); + offset = p->dma_read(CSAC, lch); if (IS_DMA_ERRATA(DMA_ERRATA_3_3) && offset == 0) - offset = dma_read(CSAC, lch); + offset = p->dma_read(CSAC, lch); if (cpu_class_is_omap1()) - offset |= (dma_read(CSSA, lch) & 0xFFFF0000); + offset |= (p->dma_read(CSSA, lch) & 0xFFFF0000); return offset; } @@ -1239,19 +1054,19 @@ dma_addr_t omap_get_dma_dst_pos(int lch) dma_addr_t offset = 0; if (cpu_is_omap15xx()) - offset = dma_read(CPC, lch); + offset = p->dma_read(CPC, lch); else - offset = dma_read(CDAC, lch); + offset = p->dma_read(CDAC, lch); /* * omap 3.2/3.3 erratum: sometimes 0 is returned if CSAC/CDAC is * read before the DMA controller finished disabling the channel. */ if (!cpu_is_omap15xx() && offset == 0) - offset = dma_read(CDAC, lch); + offset = p->dma_read(CDAC, lch); if (cpu_class_is_omap1()) - offset |= (dma_read(CDSA, lch) & 0xFFFF0000); + offset |= (p->dma_read(CDSA, lch) & 0xFFFF0000); return offset; } @@ -1259,7 +1074,7 @@ EXPORT_SYMBOL(omap_get_dma_dst_pos); int omap_get_dma_active_status(int lch) { - return (dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0; + return (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN) != 0; } EXPORT_SYMBOL(omap_get_dma_active_status); @@ -1272,7 +1087,7 @@ int omap_dma_running(void) return 1; for (lch = 0; lch < dma_chan_count; lch++) - if (dma_read(CCR, lch) & OMAP_DMA_CCR_EN) + if (p->dma_read(CCR, lch) & OMAP_DMA_CCR_EN) return 1; return 0; @@ -1287,7 +1102,7 @@ void omap_dma_link_lch(int lch_head, int lch_queue) { if (omap_dma_in_1510_mode()) { if (lch_head == lch_queue) { - dma_write(dma_read(CCR, lch_head) | (3 << 8), + p->dma_write(p->dma_read(CCR, lch_head) | (3 << 8), CCR, lch_head); return; } @@ -1314,7 +1129,7 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue) { if (omap_dma_in_1510_mode()) { if (lch_head == lch_queue) { - dma_write(dma_read(CCR, lch_head) & ~(3 << 8), + p->dma_write(p->dma_read(CCR, lch_head) & ~(3 << 8), CCR, lch_head); return; } @@ -1341,8 +1156,6 @@ void omap_dma_unlink_lch(int lch_head, int lch_queue) } EXPORT_SYMBOL(omap_dma_unlink_lch); -/*----------------------------------------------------------------------------*/ - #ifndef CONFIG_ARCH_OMAP1 /* Create chain of DMA channesls */ static void create_dma_lch_chain(int lch_head, int lch_queue) @@ -1367,15 +1180,15 @@ static void create_dma_lch_chain(int lch_head, int lch_queue) lch_queue; } - l = dma_read(CLNK_CTRL, lch_head); + l = p->dma_read(CLNK_CTRL, lch_head); l &= ~(0x1f); l |= lch_queue; - dma_write(l, CLNK_CTRL, lch_head); + p->dma_write(l, CLNK_CTRL, lch_head); - l = dma_read(CLNK_CTRL, lch_queue); + l = p->dma_read(CLNK_CTRL, lch_queue); l &= ~(0x1f); l |= (dma_chan[lch_queue].next_linked_ch); - dma_write(l, CLNK_CTRL, lch_queue); + p->dma_write(l, CLNK_CTRL, lch_queue); } /** @@ -1651,13 +1464,13 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, /* Set the params to the free channel */ if (src_start != 0) - dma_write(src_start, CSSA, lch); + p->dma_write(src_start, CSSA, lch); if (dest_start != 0) - dma_write(dest_start, CDSA, lch); + p->dma_write(dest_start, CDSA, lch); /* Write the buffer size */ - dma_write(elem_count, CEN, lch); - dma_write(frame_count, CFN, lch); + p->dma_write(elem_count, CEN, lch); + p->dma_write(frame_count, CFN, lch); /* * If the chain is dynamically linked, @@ -1690,7 +1503,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, enable_lnk(dma_chan[lch].prev_linked_ch); dma_chan[lch].state = DMA_CH_QUEUED; start_dma = 0; - if (0 == ((1 << 7) & dma_read( + if (0 == ((1 << 7) & p->dma_read( CCR, dma_chan[lch].prev_linked_ch))) { disable_lnk(dma_chan[lch]. prev_linked_ch); @@ -1707,7 +1520,7 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, } omap_enable_channel_irq(lch); - l = dma_read(CCR, lch); + l = p->dma_read(CCR, lch); if ((0 == (l & (1 << 24)))) l &= ~(1 << 25); @@ -1718,12 +1531,12 @@ int omap_dma_chain_a_transfer(int chain_id, int src_start, int dest_start, l |= (1 << 7); dma_chan[lch].state = DMA_CH_STARTED; pr_debug("starting %d\n", lch); - dma_write(l, CCR, lch); + p->dma_write(l, CCR, lch); } else start_dma = 0; } else { if (0 == (l & (1 << 7))) - dma_write(l, CCR, lch); + p->dma_write(l, CCR, lch); } dma_chan[lch].flags |= OMAP_DMA_ACTIVE; } @@ -1768,7 +1581,7 @@ int omap_start_dma_chain_transfers(int chain_id) omap_enable_channel_irq(channels[0]); } - l = dma_read(CCR, channels[0]); + l = p->dma_read(CCR, channels[0]); l |= (1 << 7); dma_linked_lch[chain_id].chain_state = DMA_CHAIN_STARTED; dma_chan[channels[0]].state = DMA_CH_STARTED; @@ -1777,7 +1590,7 @@ int omap_start_dma_chain_transfers(int chain_id) l &= ~(1 << 25); else l |= (1 << 25); - dma_write(l, CCR, channels[0]); + p->dma_write(l, CCR, channels[0]); dma_chan[channels[0]].flags |= OMAP_DMA_ACTIVE; @@ -1813,19 +1626,19 @@ int omap_stop_dma_chain_transfers(int chain_id) channels = dma_linked_lch[chain_id].linked_dmach_q; if (IS_DMA_ERRATA(DMA_ERRATA_i88)) { - sys_cf = dma_read(OCP_SYSCONFIG, 0); + sys_cf = p->dma_read(OCP_SYSCONFIG, 0); l = sys_cf; /* Middle mode reg set no Standby */ l &= ~((1 << 12)|(1 << 13)); - dma_write(l, OCP_SYSCONFIG, 0); + p->dma_write(l, OCP_SYSCONFIG, 0); } for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) { /* Stop the Channel transmission */ - l = dma_read(CCR, channels[i]); + l = p->dma_read(CCR, channels[i]); l &= ~(1 << 7); - dma_write(l, CCR, channels[i]); + p->dma_write(l, CCR, channels[i]); /* Disable the link in all the channels */ disable_lnk(channels[i]); @@ -1838,7 +1651,7 @@ int omap_stop_dma_chain_transfers(int chain_id) OMAP_DMA_CHAIN_QINIT(chain_id); if (IS_DMA_ERRATA(DMA_ERRATA_i88)) - dma_write(sys_cf, OCP_SYSCONFIG, 0); + p->dma_write(sys_cf, OCP_SYSCONFIG, 0); return 0; } @@ -1880,8 +1693,8 @@ int omap_get_dma_chain_index(int chain_id, int *ei, int *fi) /* Get the current channel */ lch = channels[dma_linked_lch[chain_id].q_head]; - *ei = dma_read(CCEN, lch); - *fi = dma_read(CCFN, lch); + *ei = p->dma_read(CCEN, lch); + *fi = p->dma_read(CCFN, lch); return 0; } @@ -1918,7 +1731,7 @@ int omap_get_dma_chain_dst_pos(int chain_id) /* Get the current channel */ lch = channels[dma_linked_lch[chain_id].q_head]; - return dma_read(CDAC, lch); + return p->dma_read(CDAC, lch); } EXPORT_SYMBOL(omap_get_dma_chain_dst_pos); @@ -1952,7 +1765,7 @@ int omap_get_dma_chain_src_pos(int chain_id) /* Get the current channel */ lch = channels[dma_linked_lch[chain_id].q_head]; - return dma_read(CSAC, lch); + return p->dma_read(CSAC, lch); } EXPORT_SYMBOL(omap_get_dma_chain_src_pos); #endif /* ifndef CONFIG_ARCH_OMAP1 */ @@ -1969,7 +1782,7 @@ static int omap1_dma_handle_ch(int ch) csr = dma_chan[ch].saved_csr; dma_chan[ch].saved_csr = 0; } else - csr = dma_read(CSR, ch); + csr = p->dma_read(CSR, ch); if (enable_1510_mode && ch <= 2 && (csr >> 7) != 0) { dma_chan[ch + 6].saved_csr = csr >> 7; csr &= 0x7f; @@ -2022,13 +1835,13 @@ static irqreturn_t omap1_dma_irq_handler(int irq, void *dev_id) static int omap2_dma_handle_ch(int ch) { - u32 status = dma_read(CSR, ch); + u32 status = p->dma_read(CSR, ch); if (!status) { if (printk_ratelimit()) printk(KERN_WARNING "Spurious DMA IRQ for lch %d\n", ch); - dma_write(1 << ch, IRQSTATUS_L0, ch); + p->dma_write(1 << ch, IRQSTATUS_L0, ch); return 0; } if (unlikely(dma_chan[ch].dev_id == -1)) { @@ -2047,9 +1860,9 @@ static int omap2_dma_handle_ch(int ch) if (IS_DMA_ERRATA(DMA_ERRATA_i378)) { u32 ccr; - ccr = dma_read(CCR, ch); + ccr = p->dma_read(CCR, ch); ccr &= ~OMAP_DMA_CCR_EN; - dma_write(ccr, CCR, ch); + p->dma_write(ccr, CCR, ch); dma_chan[ch].flags &= ~OMAP_DMA_ACTIVE; } } @@ -2060,16 +1873,16 @@ static int omap2_dma_handle_ch(int ch) printk(KERN_INFO "DMA misaligned error with device %d\n", dma_chan[ch].dev_id); - dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch); - dma_write(1 << ch, IRQSTATUS_L0, ch); + p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch); + p->dma_write(1 << ch, IRQSTATUS_L0, ch); /* read back the register to flush the write */ - dma_read(IRQSTATUS_L0, ch); + p->dma_read(IRQSTATUS_L0, ch); /* If the ch is not chained then chain_id will be -1 */ if (dma_chan[ch].chain_id != -1) { int chain_id = dma_chan[ch].chain_id; dma_chan[ch].state = DMA_CH_NOTSTARTED; - if (dma_read(CLNK_CTRL, ch) & (1 << 15)) + if (p->dma_read(CLNK_CTRL, ch) & (1 << 15)) dma_chan[dma_chan[ch].next_linked_ch].state = DMA_CH_STARTED; if (dma_linked_lch[chain_id].chain_mode == @@ -2079,10 +1892,10 @@ static int omap2_dma_handle_ch(int ch) if (!OMAP_DMA_CHAIN_QEMPTY(chain_id)) OMAP_DMA_CHAIN_INCQHEAD(chain_id); - status = dma_read(CSR, ch); + status = p->dma_read(CSR, ch); } - dma_write(status, CSR, ch); + p->dma_write(status, CSR, ch); if (likely(dma_chan[ch].callback != NULL)) dma_chan[ch].callback(ch, status, dma_chan[ch].data); @@ -2096,13 +1909,13 @@ static irqreturn_t omap2_dma_irq_handler(int irq, void *dev_id) u32 val, enable_reg; int i; - val = dma_read(IRQSTATUS_L0, 0); + val = p->dma_read(IRQSTATUS_L0, 0); if (val == 0) { if (printk_ratelimit()) printk(KERN_WARNING "Spurious DMA IRQ\n"); return IRQ_HANDLED; } - enable_reg = dma_read(IRQENABLE_L0, 0); + enable_reg = p->dma_read(IRQENABLE_L0, 0); val &= enable_reg; /* Dispatch only relevant interrupts */ for (i = 0; i < dma_lch_count && val != 0; i++) { if (val & 1) @@ -2128,206 +1941,66 @@ static struct irqaction omap24xx_dma_irq; void omap_dma_global_context_save(void) { omap_dma_global_context.dma_irqenable_l0 = - dma_read(IRQENABLE_L0, 0); + p->dma_read(IRQENABLE_L0, 0); omap_dma_global_context.dma_ocp_sysconfig = - dma_read(OCP_SYSCONFIG, 0); - omap_dma_global_context.dma_gcr = dma_read(GCR, 0); + p->dma_read(OCP_SYSCONFIG, 0); + omap_dma_global_context.dma_gcr = p->dma_read(GCR, 0); } void omap_dma_global_context_restore(void) { int ch; - dma_write(omap_dma_global_context.dma_gcr, GCR, 0); - dma_write(omap_dma_global_context.dma_ocp_sysconfig, + p->dma_write(omap_dma_global_context.dma_gcr, GCR, 0); + p->dma_write(omap_dma_global_context.dma_ocp_sysconfig, OCP_SYSCONFIG, 0); - dma_write(omap_dma_global_context.dma_irqenable_l0, + p->dma_write(omap_dma_global_context.dma_irqenable_l0, IRQENABLE_L0, 0); if (IS_DMA_ERRATA(DMA_ROMCODE_BUG)) - dma_write(0x3 , IRQSTATUS_L0, 0); + p->dma_write(0x3 , IRQSTATUS_L0, 0); for (ch = 0; ch < dma_chan_count; ch++) if (dma_chan[ch].dev_id != -1) omap_clear_dma(ch); } -static void configure_dma_errata(void) +static int __devinit omap_system_dma_probe(struct platform_device *pdev) { - - /* - * Errata applicable for OMAP2430ES1.0 and all omap2420 - * - * I. - * Erratum ID: Not Available - * Inter Frame DMA buffering issue DMA will wrongly - * buffer elements if packing and bursting is enabled. This might - * result in data gets stalled in FIFO at the end of the block. - * Workaround: DMA channels must have BUFFERING_DISABLED bit set to - * guarantee no data will stay in the DMA FIFO in case inter frame - * buffering occurs - * - * II. - * Erratum ID: Not Available - * DMA may hang when several channels are used in parallel - * In the following configuration, DMA channel hanging can occur: - * a. Channel i, hardware synchronized, is enabled - * b. Another channel (Channel x), software synchronized, is enabled. - * c. Channel i is disabled before end of transfer - * d. Channel i is reenabled. - * e. Steps 1 to 4 are repeated a certain number of times. - * f. A third channel (Channel y), software synchronized, is enabled. - * Channel x and Channel y may hang immediately after step 'f'. - * Workaround: - * For any channel used - make sure NextLCH_ID is set to the value j. - */ - if (cpu_is_omap2420() || (cpu_is_omap2430() && - (omap_type() == OMAP2430_REV_ES1_0))) { - SET_DMA_ERRATA(DMA_ERRATA_IFRAME_BUFFERING); - SET_DMA_ERRATA(DMA_ERRATA_PARALLEL_CHANNELS); - } - - /* - * Erratum ID: i378: OMAP2plus: sDMA Channel is not disabled - * after a transaction error. - * Workaround: SW should explicitely disable the channel. - */ - if (cpu_class_is_omap2()) - SET_DMA_ERRATA(DMA_ERRATA_i378); - - /* - * Erratum ID: i541: sDMA FIFO draining does not finish - * If sDMA channel is disabled on the fly, sDMA enters standby even - * through FIFO Drain is still in progress - * Workaround: Put sDMA in NoStandby more before a logical channel is - * disabled, then put it back to SmartStandby right after the channel - * finishes FIFO draining. - */ - if (cpu_is_omap34xx()) - SET_DMA_ERRATA(DMA_ERRATA_i541); - - /* - * Erratum ID: i88 : Special programming model needed to disable DMA - * before end of block. - * Workaround: software must ensure that the DMA is configured in No - * Standby mode(DMAx_OCP_SYSCONFIG.MIDLEMODE = "01") - */ - if (cpu_is_omap34xx() && (omap_type() == OMAP3430_REV_ES1_0)) - SET_DMA_ERRATA(DMA_ERRATA_i88); - - /* - * Erratum 3.2/3.3: sometimes 0 is returned if CSAC/CDAC is - * read before the DMA controller finished disabling the channel. - */ - if (!cpu_is_omap15xx()) - SET_DMA_ERRATA(DMA_ERRATA_3_3); - - /* - * Erratum ID: Not Available - * A bug in ROM code leaves IRQ status for channels 0 and 1 uncleared - * after secure sram context save and restore. - * Work around: Hence we need to manually clear those IRQs to avoid - * spurious interrupts. This affects only secure devices. - */ - if (cpu_is_omap34xx() && (omap_type() != OMAP2_DEVICE_TYPE_GP)) - SET_DMA_ERRATA(DMA_ROMCODE_BUG); -} - -/*----------------------------------------------------------------------------*/ - -static int __init omap_init_dma(void) -{ - unsigned long base; - int ch, r; - - if (cpu_class_is_omap1()) { - base = OMAP1_DMA_BASE; - dma_lch_count = OMAP1_LOGICAL_DMA_CH_COUNT; - } else if (cpu_is_omap24xx()) { - base = OMAP24XX_DMA4_BASE; - dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; - } else if (cpu_is_omap34xx()) { - base = OMAP34XX_DMA4_BASE; - dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; - } else if (cpu_is_omap44xx()) { - base = OMAP44XX_DMA4_BASE; - dma_lch_count = OMAP_DMA4_LOGICAL_DMA_CH_COUNT; - } else { - pr_err("DMA init failed for unsupported omap\n"); - return -ENODEV; + int ch, ret = 0; + int dma_irq; + char irq_name[4]; + int irq_rel; + + p = pdev->dev.platform_data; + if (!p) { + dev_err(&pdev->dev, "%s: System DMA initialized without" + "platform data\n", __func__); + return -EINVAL; } - omap_dma_base = ioremap(base, SZ_4K); - BUG_ON(!omap_dma_base); - - if (cpu_class_is_omap1()) { - dma_stride = 0x40; - reg_map = reg_map_omap1; - dma_common_ch_start = CPC; - dma_common_ch_end = COLOR; - } else { - dma_stride = 0x60; - reg_map = reg_map_omap2; - dma_common_ch_start = CSDP; - if (cpu_is_omap3630() || cpu_is_omap4430()) - dma_common_ch_end = CCDN; - else - dma_common_ch_end = CCFN; - } + d = p->dma_attr; + errata = p->errata; - if (cpu_class_is_omap2() && omap_dma_reserve_channels + if ((d->dev_caps & RESERVE_CHANNEL) && omap_dma_reserve_channels && (omap_dma_reserve_channels <= dma_lch_count)) - dma_lch_count = omap_dma_reserve_channels; + d->lch_count = omap_dma_reserve_channels; - dma_chan = kzalloc(sizeof(struct omap_dma_lch) * dma_lch_count, - GFP_KERNEL); - if (!dma_chan) { - r = -ENOMEM; - goto out_unmap; - } + dma_lch_count = d->lch_count; + dma_chan_count = dma_lch_count; + dma_chan = d->chan; + enable_1510_mode = d->dev_caps & ENABLE_1510_MODE; if (cpu_class_is_omap2()) { dma_linked_lch = kzalloc(sizeof(struct dma_link_info) * dma_lch_count, GFP_KERNEL); if (!dma_linked_lch) { - r = -ENOMEM; - goto out_free; + ret = -ENOMEM; + goto exit_dma_lch_fail; } } - if (cpu_is_omap15xx()) { - printk(KERN_INFO "DMA support for OMAP15xx initialized\n"); - dma_chan_count = 9; - enable_1510_mode = 1; - } else if (cpu_is_omap16xx() || cpu_is_omap7xx()) { - printk(KERN_INFO "OMAP DMA hardware version %d\n", - dma_read(HW_ID, 0)); - printk(KERN_INFO "DMA capabilities: %08x:%08x:%04x:%04x:%04x\n", - dma_read(CAPS_0, 0), dma_read(CAPS_1, 0), - dma_read(CAPS_2, 0), dma_read(CAPS_3, 0), - dma_read(CAPS_4, 0)); - if (!enable_1510_mode) { - u16 w; - - /* Disable OMAP 3.0/3.1 compatibility mode. */ - w = dma_read(GSCR, 0); - w |= 1 << 3; - dma_write(w, GSCR, 0); - dma_chan_count = 16; - } else - dma_chan_count = 9; - } else if (cpu_class_is_omap2()) { - u8 revision = dma_read(REVISION, 0) & 0xff; - printk(KERN_INFO "OMAP DMA hardware revision %d.%d\n", - revision >> 4, revision & 0xf); - dma_chan_count = dma_lch_count; - } else { - dma_chan_count = 0; - return 0; - } - spin_lock_init(&dma_chan_lock); - for (ch = 0; ch < dma_chan_count; ch++) { omap_clear_dma(ch); if (cpu_class_is_omap2()) @@ -2344,20 +2017,23 @@ static int __init omap_init_dma(void) * request_irq() doesn't like dev_id (ie. ch) being * zero, so we have to kludge around this. */ - r = request_irq(omap1_dma_irq[ch], + sprintf(&irq_name[0], "%d", ch); + dma_irq = platform_get_irq_byname(pdev, irq_name); + + if (dma_irq < 0) { + ret = dma_irq; + goto exit_dma_irq_fail; + } + + /* INT_DMA_LCD is handled in lcd_dma.c */ + if (dma_irq == INT_DMA_LCD) + continue; + + ret = request_irq(dma_irq, omap1_dma_irq_handler, 0, "DMA", (void *) (ch + 1)); - if (r != 0) { - int i; - - printk(KERN_ERR "unable to request IRQ %d " - "for DMA (error %d)\n", - omap1_dma_irq[ch], r); - for (i = 0; i < ch; i++) - free_irq(omap1_dma_irq[i], - (void *) (i + 1)); - goto out_free; - } + if (ret != 0) + goto exit_dma_irq_fail; } } @@ -2366,47 +2042,91 @@ static int __init omap_init_dma(void) DMA_DEFAULT_FIFO_DEPTH, 0); if (cpu_class_is_omap2()) { - int irq; - if (cpu_is_omap44xx()) - irq = OMAP44XX_IRQ_SDMA_0; - else - irq = INT_24XX_SDMA_IRQ0; - setup_irq(irq, &omap24xx_dma_irq); - } - - if (cpu_is_omap34xx() || cpu_is_omap44xx()) { - /* Enable smartidle idlemodes and autoidle */ - u32 v = dma_read(OCP_SYSCONFIG, 0); - v &= ~(DMA_SYSCONFIG_MIDLEMODE_MASK | - DMA_SYSCONFIG_SIDLEMODE_MASK | - DMA_SYSCONFIG_AUTOIDLE); - v |= (DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | - DMA_SYSCONFIG_SIDLEMODE(DMA_IDLEMODE_SMARTIDLE) | - DMA_SYSCONFIG_AUTOIDLE); - dma_write(v , OCP_SYSCONFIG, 0); - /* reserve dma channels 0 and 1 in high security devices */ - if (cpu_is_omap34xx() && - (omap_type() != OMAP2_DEVICE_TYPE_GP)) { - printk(KERN_INFO "Reserving DMA channels 0 and 1 for " - "HS ROM code\n"); - dma_chan[0].dev_id = 0; - dma_chan[1].dev_id = 1; + strcpy(irq_name, "0"); + dma_irq = platform_get_irq_byname(pdev, irq_name); + if (dma_irq < 0) { + dev_err(&pdev->dev, "failed: request IRQ %d", dma_irq); + goto exit_dma_lch_fail; + } + ret = setup_irq(dma_irq, &omap24xx_dma_irq); + if (ret) { + dev_err(&pdev->dev, "set_up failed for IRQ %d" + "for DMA (error %d)\n", dma_irq, ret); + goto exit_dma_lch_fail; } } - configure_dma_errata(); + /* reserve dma channels 0 and 1 in high security devices */ + if (cpu_is_omap34xx() && + (omap_type() != OMAP2_DEVICE_TYPE_GP)) { + printk(KERN_INFO "Reserving DMA channels 0 and 1 for " + "HS ROM code\n"); + dma_chan[0].dev_id = 0; + dma_chan[1].dev_id = 1; + } + p->show_dma_caps(); return 0; -out_free: +exit_dma_irq_fail: + dev_err(&pdev->dev, "unable to request IRQ %d" + "for DMA (error %d)\n", dma_irq, ret); + for (irq_rel = 0; irq_rel < ch; irq_rel++) { + dma_irq = platform_get_irq(pdev, irq_rel); + free_irq(dma_irq, (void *)(irq_rel + 1)); + } + +exit_dma_lch_fail: + kfree(p); + kfree(d); kfree(dma_chan); + return ret; +} -out_unmap: - iounmap(omap_dma_base); +static int __devexit omap_system_dma_remove(struct platform_device *pdev) +{ + int dma_irq; - return r; + if (cpu_class_is_omap2()) { + char irq_name[4]; + strcpy(irq_name, "0"); + dma_irq = platform_get_irq_byname(pdev, irq_name); + remove_irq(dma_irq, &omap24xx_dma_irq); + } else { + int irq_rel = 0; + for ( ; irq_rel < dma_chan_count; irq_rel++) { + dma_irq = platform_get_irq(pdev, irq_rel); + free_irq(dma_irq, (void *)(irq_rel + 1)); + } + } + kfree(p); + kfree(d); + kfree(dma_chan); + return 0; +} + +static struct platform_driver omap_system_dma_driver = { + .probe = omap_system_dma_probe, + .remove = omap_system_dma_remove, + .driver = { + .name = "omap_dma_system" + }, +}; + +static int __init omap_system_dma_init(void) +{ + return platform_driver_register(&omap_system_dma_driver); +} +arch_initcall(omap_system_dma_init); + +static void __exit omap_system_dma_exit(void) +{ + platform_driver_unregister(&omap_system_dma_driver); } -arch_initcall(omap_init_dma); +MODULE_DESCRIPTION("OMAP SYSTEM DMA DRIVER"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRIVER_NAME); +MODULE_AUTHOR("Texas Instruments Inc"); /* * Reserve the omap SDMA channels using cmdline bootarg diff --git a/arch/arm/plat-omap/include/plat/dma.h b/arch/arm/plat-omap/include/plat/dma.h index 4b51d2b93b0e..d1c916fcf770 100644 --- a/arch/arm/plat-omap/include/plat/dma.h +++ b/arch/arm/plat-omap/include/plat/dma.h @@ -21,19 +21,15 @@ #ifndef __ASM_ARCH_DMA_H #define __ASM_ARCH_DMA_H -/* Move omap4 specific defines to dma-44xx.h */ -#include "dma-44xx.h" - -/* Hardware registers for omap1 */ -#define OMAP1_DMA_BASE (0xfffed800) +#include -/* Hardware registers for omap2 and omap3 */ -#define OMAP24XX_DMA4_BASE (L4_24XX_BASE + 0x56000) -#define OMAP34XX_DMA4_BASE (L4_34XX_BASE + 0x56000) -#define OMAP44XX_DMA4_BASE (L4_44XX_BASE + 0x56000) +/* + * TODO: These dma channel defines should go away once all + * the omap drivers hwmod adapted. + */ -#define OMAP1_LOGICAL_DMA_CH_COUNT 17 -#define OMAP_DMA4_LOGICAL_DMA_CH_COUNT 32 /* REVISIT: Is this 32 + 2? */ +/* Move omap4 specific defines to dma-44xx.h */ +#include "dma-44xx.h" /* DMA channels for omap1 */ #define OMAP_DMA_NO_DEVICE 0 @@ -302,6 +298,14 @@ #define IS_CSSA_32 BIT(0x3) #define IS_CDSA_32 BIT(0x4) #define IS_RW_PRIORITY BIT(0x5) +#define ENABLE_1510_MODE BIT(0x6) +#define SRC_PORT BIT(0x7) +#define DST_PORT BIT(0x8) +#define SRC_INDEX BIT(0x9) +#define DST_INDEX BIT(0xA) +#define IS_BURST_ONLY4 BIT(0xB) +#define CLEAR_CSR_ON_READ BIT(0xC) +#define IS_WORD_16 BIT(0xD) enum omap_reg_offsets { @@ -397,9 +401,40 @@ struct omap_dma_channel_params { #endif }; +struct omap_dma_lch { + int next_lch; + int dev_id; + u16 saved_csr; + u16 enabled_irqs; + const char *dev_name; + void (*callback)(int lch, u16 ch_status, void *data); + void *data; + long flags; + /* required for Dynamic chaining */ + int prev_linked_ch; + int next_linked_ch; + int state; + int chain_id; + int status; +}; + struct omap_dma_dev_attr { u32 dev_caps; u16 lch_count; + u16 chan_count; + struct omap_dma_lch *chan; +}; + +/* System DMA platform data structure */ +struct omap_system_dma_plat_info { + struct omap_dma_dev_attr *dma_attr; + u32 errata; + void (*disable_irq_lch)(int lch); + void (*show_dma_caps)(void); + void (*clear_lch_regs)(int lch); + void (*clear_dma)(int lch); + void (*dma_write)(u32 val, int reg, int lch); + u32 (*dma_read)(int reg, int lch); }; extern void omap_set_dma_priority(int lch, int dst_port, int priority); -- cgit v1.2.3 From 65dd4c1626b396af839881708fdf3bc726a16f73 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 17 Dec 2010 18:37:08 -0800 Subject: omap1: Fix innovator FPGA init for multi-omap No need to call this early from init_irq. Also recent changes initialize GPIO now later, so calling gpio_request from init_irq will make it fail. While at it, also remove the unnecessary EXPORT_SYMBOL. Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/fpga.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/fpga.h b/arch/arm/plat-omap/include/plat/fpga.h index f1864a652f7a..ae39bcb3f5ba 100644 --- a/arch/arm/plat-omap/include/plat/fpga.h +++ b/arch/arm/plat-omap/include/plat/fpga.h @@ -19,11 +19,7 @@ #ifndef __ASM_ARCH_OMAP_FPGA_H #define __ASM_ARCH_OMAP_FPGA_H -#if defined(CONFIG_MACH_OMAP_INNOVATOR) && defined(CONFIG_ARCH_OMAP15XX) extern void omap1510_fpga_init_irq(void); -#else -#define omap1510_fpga_init_irq() (0) -#endif #define fpga_read(reg) __raw_readb(reg) #define fpga_write(val, reg) __raw_writeb(val, reg) -- cgit v1.2.3 From a3551f5b0c3ca7aaa053e554e3ee766983b5d713 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 9 Dec 2010 10:48:27 +0200 Subject: OMAP2/3: GPMC: put sync_clk value in picoseconds instead of nanoseconds The calculations done with sync_clk are anyway in picoseconds and switching to picoseconds allows sync_clk values that are not a whole number of nanoseconds - which is sometimes the case. Signed-off-by: Adrian Hunter Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/gpmc.h | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/gpmc.h b/arch/arm/plat-omap/include/plat/gpmc.h index 9fd99b9e40ab..85ded598853e 100644 --- a/arch/arm/plat-omap/include/plat/gpmc.h +++ b/arch/arm/plat-omap/include/plat/gpmc.h @@ -80,12 +80,12 @@ #define GPMC_PREFETCH_STATUS_COUNT(val) (val & 0x00003fff) /* - * Note that all values in this struct are in nanoseconds, while - * the register values are in gpmc_fck cycles. + * Note that all values in this struct are in nanoseconds except sync_clk + * (which is in picoseconds), while the register values are in gpmc_fck cycles. */ struct gpmc_timings { - /* Minimum clock period for synchronous mode */ - u16 sync_clk; + /* Minimum clock period for synchronous mode (in picoseconds) */ + u32 sync_clk; /* Chip-select signal timings corresponding to GPMC_CS_CONFIG2 */ u16 cs_on; /* Assertion time */ @@ -117,6 +117,7 @@ struct gpmc_timings { }; extern unsigned int gpmc_ns_to_ticks(unsigned int time_ns); +extern unsigned int gpmc_ps_to_ticks(unsigned int time_ps); extern unsigned int gpmc_ticks_to_ns(unsigned int ticks); extern unsigned int gpmc_round_ns_to_ticks(unsigned int time_ns); extern unsigned long gpmc_get_fclk_period(void); -- cgit v1.2.3 From 53da4ce23809ca33405001b0ae117e60b7feced1 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Thu, 9 Dec 2010 09:13:48 -0600 Subject: OMAP3: remove OPP interfaces from OMAP PM layer With new OPP layer, OPP users will access OPP API directly instead of using OMAP PM layer, so remove all notions of OPPs from the OMAP PM layer. Acked-by: Paul Walmsley Signed-off-by: Nishanth Menon Signed-off-by: Kevin Hilman --- arch/arm/plat-omap/include/plat/omap-pm.h | 31 ++++++++++--------------------- arch/arm/plat-omap/omap-pm-noop.c | 11 +---------- 2 files changed, 11 insertions(+), 31 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h index 728fbb9dd549..62c3fe918ab2 100644 --- a/arch/arm/plat-omap/include/plat/omap-pm.h +++ b/arch/arm/plat-omap/include/plat/omap-pm.h @@ -17,27 +17,10 @@ #include #include #include +#include #include "powerdomain.h" -/** - * struct omap_opp - clock frequency-to-OPP ID table for DSP, MPU - * @rate: target clock rate - * @opp_id: OPP ID - * @min_vdd: minimum VDD1 voltage (in millivolts) for this OPP - * - * Operating performance point data. Can vary by OMAP chip and board. - */ -struct omap_opp { - unsigned long rate; - u8 opp_id; - u16 min_vdd; -}; - -extern struct omap_opp *mpu_opps; -extern struct omap_opp *dsp_opps; -extern struct omap_opp *l3_opps; - /* * agent_id values for use with omap_pm_set_min_bus_tput(): * @@ -59,9 +42,11 @@ extern struct omap_opp *l3_opps; * framework starts. The "_if_" is to avoid name collisions with the * PM idle-loop code. */ -int __init omap_pm_if_early_init(struct omap_opp *mpu_opp_table, - struct omap_opp *dsp_opp_table, - struct omap_opp *l3_opp_table); +#ifdef CONFIG_OMAP_PM_NONE +#define omap_pm_if_early_init() 0 +#else +int __init omap_pm_if_early_init(void); +#endif /** * omap_pm_if_init - OMAP PM init code called after clock fw init @@ -69,7 +54,11 @@ int __init omap_pm_if_early_init(struct omap_opp *mpu_opp_table, * The main initialization code. OPP tables are passed in here. The * "_if_" is to avoid name collisions with the PM idle-loop code. */ +#ifdef CONFIG_OMAP_PM_NONE +#define omap_pm_if_init() 0 +#else int __init omap_pm_if_init(void); +#endif /** * omap_pm_if_exit - OMAP PM exit code diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c index e129ce80c53b..ca75abb18068 100644 --- a/arch/arm/plat-omap/omap-pm-noop.c +++ b/arch/arm/plat-omap/omap-pm-noop.c @@ -26,10 +26,6 @@ #include -struct omap_opp *dsp_opps; -struct omap_opp *mpu_opps; -struct omap_opp *l3_opps; - /* * Device-driver-originated constraints (via board-*.c files) */ @@ -308,13 +304,8 @@ int omap_pm_get_dev_context_loss_count(struct device *dev) /* Should be called before clk framework init */ -int __init omap_pm_if_early_init(struct omap_opp *mpu_opp_table, - struct omap_opp *dsp_opp_table, - struct omap_opp *l3_opp_table) +int __init omap_pm_if_early_init(void) { - mpu_opps = mpu_opp_table; - dsp_opps = dsp_opp_table; - l3_opps = l3_opp_table; return 0; } -- cgit v1.2.3 From b4b36fd94e4ca99b3258ff24c2c58cdde67085e0 Mon Sep 17 00:00:00 2001 From: Jean Pihet Date: Sat, 18 Dec 2010 16:44:42 +0100 Subject: OMAP2+: use global values for the SRAM PA addresses The SRAM PA addresses are locally defined and used at different places, i.e. SRAM management code and idle sleep code. The macros are now defined at a centralized place, for easier maintenance. Tested on N900 and Beagleboard with full RET and OFF modes, using cpuidle and suspend. Signed-off-by: Jean Pihet Acked-by: Santosh Shilimkar Tested-by: Nishanth Menon Signed-off-by: Kevin Hilman --- arch/arm/plat-omap/include/plat/sram.h | 11 +++++++++++ arch/arm/plat-omap/sram.c | 7 ++----- 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/sram.h b/arch/arm/plat-omap/include/plat/sram.h index 5905100b29a1..9967d5e855c7 100644 --- a/arch/arm/plat-omap/include/plat/sram.h +++ b/arch/arm/plat-omap/include/plat/sram.h @@ -11,6 +11,7 @@ #ifndef __ARCH_ARM_OMAP_SRAM_H #define __ARCH_ARM_OMAP_SRAM_H +#ifndef __ASSEMBLY__ extern void * omap_sram_push(void * start, unsigned long size); extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl); @@ -74,4 +75,14 @@ extern void omap_push_sram_idle(void); static inline void omap_push_sram_idle(void) {} #endif /* CONFIG_PM */ +#endif /* __ASSEMBLY__ */ + +/* + * OMAP2+: define the SRAM PA addresses. + * Used by the SRAM management code and the idle sleep code. + */ +#define OMAP2_SRAM_PA 0x40200000 +#define OMAP3_SRAM_PA 0x40200000 +#define OMAP4_SRAM_PA 0x40300000 + #endif diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 74dac419d328..86f3eb720f0c 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -41,15 +41,12 @@ #define OMAP1_SRAM_PA 0x20000000 #define OMAP1_SRAM_VA VMALLOC_END -#define OMAP2_SRAM_PA 0x40200000 -#define OMAP2_SRAM_PUB_PA 0x4020f800 +#define OMAP2_SRAM_PUB_PA (OMAP2_SRAM_PA + 0xf800) #define OMAP2_SRAM_VA 0xfe400000 #define OMAP2_SRAM_PUB_VA (OMAP2_SRAM_VA + 0x800) -#define OMAP3_SRAM_PA 0x40200000 #define OMAP3_SRAM_VA 0xfe400000 -#define OMAP3_SRAM_PUB_PA 0x40208000 +#define OMAP3_SRAM_PUB_PA (OMAP3_SRAM_PA + 0x8000) #define OMAP3_SRAM_PUB_VA (OMAP3_SRAM_VA + 0x8000) -#define OMAP4_SRAM_PA 0x40300000 #define OMAP4_SRAM_VA 0xfe400000 #define OMAP4_SRAM_PUB_PA (OMAP4_SRAM_PA + 0x4000) #define OMAP4_SRAM_PUB_VA (OMAP4_SRAM_VA + 0x4000) -- cgit v1.2.3 From 79c5f68dc221df729417823d4981373f4762d8eb Mon Sep 17 00:00:00 2001 From: Thomas Weber Date: Tue, 21 Dec 2010 11:07:09 +0000 Subject: OMAP3: Devkit8000: Add DEBUG_LL support Add support for DEBUG_LL for Devkit8000. Devkit8000 uses uart 3 for debug output. Signed-off-by: Thomas Weber Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/uncompress.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h index 7bbc0740cb46..ad98b85cae21 100644 --- a/arch/arm/plat-omap/include/plat/uncompress.h +++ b/arch/arm/plat-omap/include/plat/uncompress.h @@ -146,6 +146,7 @@ static inline void __arch_decomp_setup(unsigned long arch_id) DEBUG_LL_OMAP3(3, cm_t35); DEBUG_LL_OMAP3(3, cm_t3517); DEBUG_LL_OMAP3(3, craneboard); + DEBUG_LL_OMAP3(3, devkit8000); DEBUG_LL_OMAP3(3, igep0020); DEBUG_LL_OMAP3(3, igep0030); DEBUG_LL_OMAP3(3, nokia_rm680); -- cgit v1.2.3 From 4805734bcc5a6b28b527a13a5c1603a2912c9f48 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 21 Dec 2010 15:25:10 -0700 Subject: OMAP2+: io: split omap2_init_common_hw() Split omap2_init_common_hw() into two functions. The first, omap2_init_common_infrastructure(), initializes the hwmod code and data, the OMAP PM code, and the clock code and data. The second, omap2_init_common_devices(), handles any other early device initialization that, for whatever reason, has not been or cannot be moved to initcalls or early platform devices. This patch is required for the hwmod postsetup patch, which allows board files to change the state that hwmods should be placed into at the conclusion of the hwmod _setup() function. For example, for a board whose creators wish to ensure watchdog coverage across the entire kernel boot process, code to change the watchdog's postsetup state will be added in the board-*.c file between the omap2_init_common_infrastructure() and omap2_init_common_devices() function calls. Signed-off-by: Paul Walmsley Cc: Tony Lindgren --- arch/arm/plat-omap/include/plat/io.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/io.h b/arch/arm/plat-omap/include/plat/io.h index 204865f91d93..ef4106c13183 100644 --- a/arch/arm/plat-omap/include/plat/io.h +++ b/arch/arm/plat-omap/include/plat/io.h @@ -291,8 +291,9 @@ static inline void omap44xx_map_common_io(void) } #endif -extern void omap2_init_common_hw(struct omap_sdrc_params *sdrc_cs0, - struct omap_sdrc_params *sdrc_cs1); +extern void omap2_init_common_infrastructure(void); +extern void omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0, + struct omap_sdrc_params *sdrc_cs1); #define __arch_ioremap omap_ioremap #define __arch_iounmap omap_iounmap -- cgit v1.2.3 From e4dc8f507c3066d6fcece988d99b6d766c46af85 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 14 Dec 2010 12:42:34 -0700 Subject: OMAP2+: hwmod: allow custom pre-shutdown functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some OMAP IP blocks, such as the watchdog timers, cannot be completely shut down via the standard hwmod shutdown mechanism. This patch enables the hwmod data files to supply a pointer to a custom pre-shutdown function via the struct omap_hwmod_class.pre_shutdown function pointer. If the struct omap_hwmod_class.pre_shutdown function pointer is non-null, the function will be executed before the existing hwmod shutdown code runs. Signed-off-by: Paul Walmsley Cc: Benoît Cousson --- arch/arm/plat-omap/include/plat/omap_hwmod.h | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 7eaa8edf3b14..d1f1265fc4a6 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -415,14 +415,24 @@ struct omap_hwmod_omap4_prcm { * @name: name of the hwmod_class * @sysc: device SYSCONFIG/SYSSTATUS register data * @rev: revision of the IP class + * @pre_shutdown: ptr to fn to be executed immediately prior to device shutdown * * Represent the class of a OMAP hardware "modules" (e.g. timer, * smartreflex, gpio, uart...) + * + * @pre_shutdown is a function that will be run immediately before + * hwmod clocks are disabled, etc. It is intended for use for hwmods + * like the MPU watchdog, which cannot be disabled with the standard + * omap_hwmod_shutdown(). The function should return 0 upon success, + * or some negative error upon failure. Returning an error will cause + * omap_hwmod_shutdown() to abort the device shutdown and return an + * error. */ struct omap_hwmod_class { const char *name; struct omap_hwmod_class_sysconfig *sysc; u32 rev; + int (*pre_shutdown)(struct omap_hwmod *oh); }; /** -- cgit v1.2.3 From 2092e5ccf89db09ebde94e9aabd3c86d5fa05c6c Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 14 Dec 2010 12:42:35 -0700 Subject: OMAP2+: hwmod: add postsetup state MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Allow board files and OMAP core code to control the state that some or all of the hwmods end up in at the end of _setup() (called by omap_hwmod_late_init() ). Reimplement the old skip_setup_idle code in terms of this new postsetup state code. There are two use-cases for this patch: the !CONFIG_PM_RUNTIME case, in which all IP blocks should stay enabled after _setup() finishes; and the MPU watchdog case, in which the watchdog IP block should enter idle if watchdog coverage of kernel initialization is desired, and should be disabled otherwise. Signed-off-by: Paul Walmsley Cc: Benoît Cousson Cc: Kevin Hilman Cc: Charulatha Varadarajan --- arch/arm/plat-omap/include/plat/omap_hwmod.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index d1f1265fc4a6..b445ecdb95b8 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -462,6 +462,7 @@ struct omap_hwmod_class { * @response_lat: device OCP response latency (in interface clock cycles) * @_int_flags: internal-use hwmod flags * @_state: internal-use hwmod state + * @_postsetup_state: internal-use state to leave the hwmod in after _setup() * @flags: hwmod flags (documented below) * @omap_chip: OMAP chips this hwmod is present on * @_mutex: mutex serializing operations on this hwmod @@ -510,6 +511,7 @@ struct omap_hwmod { u8 hwmods_cnt; u8 _int_flags; u8 _state; + u8 _postsetup_state; const struct omap_chip_id omap_chip; }; @@ -519,7 +521,7 @@ int omap_hwmod_unregister(struct omap_hwmod *oh); struct omap_hwmod *omap_hwmod_lookup(const char *name); int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data), void *data); -int omap_hwmod_late_init(u8 skip_setup_idle); +int omap_hwmod_late_init(void); int omap_hwmod_enable(struct omap_hwmod *oh); int _omap_hwmod_enable(struct omap_hwmod *oh); @@ -566,6 +568,8 @@ int omap_hwmod_for_each_by_class(const char *classname, void *user), void *user); +int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state); + /* * Chip variant-specific hwmod init routines - XXX should be converted * to use initcalls once the initial boot ordering is straightened out -- cgit v1.2.3 From bd36179eec2827cd60b4a8c6e180cc030c74a4ec Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 14 Dec 2010 12:42:35 -0700 Subject: OMAP2+: hwmod: add support for per-class custom device reset functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The standard omap_hwmod.c _reset() code relies on an IP block's OCP_SYSCONFIG.SOFTRESET register bit to reset the IP block. This works for most IP blocks on the chip, but unfortunately not all. For example, initiator-only IP blocks often don't have any MPU-accessible OCP-header registers, and therefore the MPU can't write to any OCP_SYSCONFIG registers in that block. Other IP blocks, such as the IVA and I2C, require a specialized reset sequence. Since we need to be able to reset these IP blocks as well, allow custom IP block reset functions to be passed into the hwmod code via a per-hwmod-class reset function pointer, struct omap_hwmod_class.reset. If .reset is non-null, then the hwmod _reset() code will call the custom function instead of the standard OCP SOFTRESET-based code. As part of this change, rename most of the existing _reset() function code to _ocp_softreset(), to indicate more clearly that it does not work for all cases. Signed-off-by: Paul Walmsley Cc: Benoît Cousson Cc: Paul Hunt Cc: Stanley Liu --- arch/arm/plat-omap/include/plat/omap_hwmod.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index b445ecdb95b8..e4c4fd4cc1ed 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -364,7 +364,7 @@ struct omap_hwmod_omap4_prcm { * when module is enabled, rather than the default, which is to * enable autoidle * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup - * HWMOD_NO_IDLEST : this module does not have idle status - this is the case + * HWMOD_NO_IDLEST: this module does not have idle status - this is the case * only for few initiator modules on OMAP2 & 3. * HWMOD_CONTROL_OPT_CLKS_IN_RESET: Enable all optional clocks during reset. * This is needed for devices like DSS that require optional clocks enabled @@ -416,6 +416,7 @@ struct omap_hwmod_omap4_prcm { * @sysc: device SYSCONFIG/SYSSTATUS register data * @rev: revision of the IP class * @pre_shutdown: ptr to fn to be executed immediately prior to device shutdown + * @reset: ptr to fn to be executed in place of the standard hwmod reset fn * * Represent the class of a OMAP hardware "modules" (e.g. timer, * smartreflex, gpio, uart...) @@ -427,12 +428,18 @@ struct omap_hwmod_omap4_prcm { * or some negative error upon failure. Returning an error will cause * omap_hwmod_shutdown() to abort the device shutdown and return an * error. + * + * If @reset is defined, then the function it points to will be + * executed in place of the standard hwmod _reset() code in + * mach-omap2/omap_hwmod.c. This is needed for IP blocks which have + * unusual reset sequences - usually processor IP blocks like the IVA. */ struct omap_hwmod_class { const char *name; struct omap_hwmod_class_sysconfig *sysc; u32 rev; int (*pre_shutdown)(struct omap_hwmod *oh); + int (*reset)(struct omap_hwmod *oh); }; /** -- cgit v1.2.3 From dc6d1cda044b24c3d9f8e4af0431887ebe3488ef Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 14 Dec 2010 12:42:35 -0700 Subject: OMAP2+: hwmod: upgrade per-hwmod mutex to a spinlock MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change the per-hwmod mutex to a spinlock. (The per-hwmod lock serializes most post-initialization hwmod operations such as enable, idle, and shutdown.) Spinlocks are needed, because in some cases, hwmods must be enabled from timer interrupt disabled-context, such as an ISR. The current use-case that is driving this is the OMAP GPIO block ISR: it can trigger interrupts even with its clocks disabled, but these clocks are needed for register accesses in the ISR to succeed. This patch also effectively reverts commit 848240223c35fcc71c424ad51a8e8aef42d3879c - this patch makes _omap_hwmod_enable() and _omap_hwmod_init() static, renames them back to _enable() and _idle(), and changes their callers to call the spinlocking versions. Previously, since omap_hwmod_{enable,init}() attempted to take mutexes, these functions could not be called while the timer interrupt was disabled; but now that the functions use spinlocks and save and restore the IRQ state, it is appropriate to call them directly. Kevin Hilman originally proposed this patch - thanks Kevin. Signed-off-by: Paul Walmsley Cc: Kevin Hilman Cc: Benoît Cousson --- arch/arm/plat-omap/include/plat/omap_hwmod.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index e4c4fd4cc1ed..b588f4779806 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -32,7 +32,7 @@ #include #include #include -#include +#include #include struct omap_device; @@ -472,7 +472,7 @@ struct omap_hwmod_class { * @_postsetup_state: internal-use state to leave the hwmod in after _setup() * @flags: hwmod flags (documented below) * @omap_chip: OMAP chips this hwmod is present on - * @_mutex: mutex serializing operations on this hwmod + * @_lock: spinlock serializing operations on this hwmod * @node: list node for hwmod list (internal use) * * @main_clk refers to this module's "main clock," which for our @@ -502,7 +502,7 @@ struct omap_hwmod { void *dev_attr; u32 _sysc_cache; void __iomem *_mpu_rt_va; - struct mutex _mutex; + spinlock_t _lock; struct list_head node; u16 flags; u8 _mpu_port_index; -- cgit v1.2.3 From b56b7bc8d9293b64e7a459527ae78078902751ff Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 14 Dec 2010 12:42:36 -0700 Subject: OMAP2+: hwmod: fix a warning, add some docs, remove unused fields MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Trivial cleanup and documentation changes on the hwmod code and data: - add some hwmod documentation to indicate flags that should be moved outside the static hwmod data in a future patch - remove some unused fields in the struct omap_hwmod_ocp_if and struct omap_hwmod structures Signed-off-by: Paul Walmsley Cc: Benoît Cousson --- arch/arm/plat-omap/include/plat/omap_hwmod.h | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index b588f4779806..62bdb23c95c9 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -23,7 +23,7 @@ * - add pinmuxing * - init_conn_id_bit (CONNID_BIT_VECTOR) * - implement default hwmod SMS/SDRC flags? - * - remove unused fields + * - move Linux-specific data ("non-ROM data") out * */ #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H @@ -159,7 +159,7 @@ struct omap_hwmod_omap2_firewall { * ADDR_MAP_ON_INIT: Map this address space during omap_hwmod init. * ADDR_TYPE_RT: Address space contains module register target data. */ -#define ADDR_MAP_ON_INIT (1 << 0) +#define ADDR_MAP_ON_INIT (1 << 0) /* XXX does not belong */ #define ADDR_TYPE_RT (1 << 1) /** @@ -200,8 +200,6 @@ struct omap_hwmod_addr_space { * @fw: interface firewall data * @addr_cnt: ARRAY_SIZE(@addr) * @width: OCP data width - * @thread_cnt: number of threads - * @max_burst_len: maximum burst length in @width sized words (0 if unlimited) * @user: initiators using this interface (see OCP_USER_* macros above) * @flags: OCP interface flags (see OCPIF_* macros above) * @@ -221,8 +219,6 @@ struct omap_hwmod_ocp_if { } fw; u8 addr_cnt; u8 width; - u8 thread_cnt; - u8 max_burst_len; u8 user; u8 flags; }; @@ -357,9 +353,9 @@ struct omap_hwmod_omap4_prcm { * HWMOD_SWSUP_MSTDBY: omap_hwmod code should manually bring module in and out * of standby, rather than relying on module smart-standby * HWMOD_INIT_NO_RESET: don't reset this module at boot - important for - * SDRAM controller, etc. + * SDRAM controller, etc. XXX probably belongs outside the main hwmod file * HWMOD_INIT_NO_IDLE: don't idle this module at boot - important for SDRAM - * controller, etc. + * controller, etc. XXX probably belongs outside the main hwmod file * HWMOD_NO_AUTOIDLE: disable module autoidle (OCP_SYSCONFIG.AUTOIDLE) * when module is enabled, rather than the default, which is to * enable autoidle @@ -459,8 +455,6 @@ struct omap_hwmod_class { * @_sysc_cache: internal-use hwmod flags * @_mpu_rt_va: cached register target start address (internal use) * @_mpu_port_index: cached MPU register target slave ID (internal use) - * @msuspendmux_reg_id: CONTROL_MSUSPENDMUX register ID (1-6) - * @msuspendmux_shift: CONTROL_MSUSPENDMUX register bit shift * @mpu_irqs_cnt: number of @mpu_irqs * @sdma_reqs_cnt: number of @sdma_reqs * @opt_clks_cnt: number of @opt_clks @@ -506,8 +500,6 @@ struct omap_hwmod { struct list_head node; u16 flags; u8 _mpu_port_index; - u8 msuspendmux_reg_id; - u8 msuspendmux_shift; u8 response_lat; u8 mpu_irqs_cnt; u8 sdma_reqs_cnt; -- cgit v1.2.3 From 74bea6b9881f4b32f6c0379e46d2f5e16fd34a07 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Tue, 21 Dec 2010 20:01:17 -0700 Subject: OMAP: powerdomain: Move static allocations from powerdomains.h to a .c file powerdomains.h header today has only static definitions. Adding any function declarations into it and including it in multiple source file is expected to cause issues. Hence move all the static definitions from powerdomains.h file into powerdomains_data.c file. Also, create a new powerdomain section of the mach-omap2/Makefile, and rearrange the prcm-common part of the Makefile, now that the powerdomain code is in its own Makefile section. Signed-off-by: Rajendra Nayak [paul@pwsan.com: rearrange Makefile changes, tweaked commit message] Signed-off-by: Paul Walmsley Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Tested-by: Santosh Shilimkar Tested-by: Rajendra Nayak --- arch/arm/plat-omap/include/plat/powerdomain.h | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/powerdomain.h b/arch/arm/plat-omap/include/plat/powerdomain.h index 9ca420dcd2f8..e322b39f3a3f 100644 --- a/arch/arm/plat-omap/include/plat/powerdomain.h +++ b/arch/arm/plat-omap/include/plat/powerdomain.h @@ -118,6 +118,7 @@ struct powerdomain { }; +void pwrdm_fw_init(void); void pwrdm_init(struct powerdomain **pwrdm_list); struct powerdomain *pwrdm_lookup(const char *name); -- cgit v1.2.3 From 3b1e8b21fcbd686445f0bb42f84701b4621cdec6 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Tue, 21 Dec 2010 20:01:18 -0700 Subject: OMAP: powerdomain: Infrastructure to put arch specific code Put infrastructure in place, so arch specific func pointers can be hooked up to the platform-independent part of the framework. This is in preparation of splitting the powerdomain framework into platform-independent part (for all omaps) and platform-specific parts. Signed-off-by: Rajendra Nayak Signed-off-by: Paul Walmsley Cc: Benoit Cousson Cc: Kevin Hilman Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Tested-by: Santosh Shilimkar Tested-by: Rajendra Nayak --- arch/arm/plat-omap/include/plat/powerdomain.h | 43 ++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/powerdomain.h b/arch/arm/plat-omap/include/plat/powerdomain.h index e322b39f3a3f..583758cbd7d3 100644 --- a/arch/arm/plat-omap/include/plat/powerdomain.h +++ b/arch/arm/plat-omap/include/plat/powerdomain.h @@ -117,9 +117,50 @@ struct powerdomain { #endif }; +/** + * struct pwrdm_ops - Arch specfic function implementations + * @pwrdm_set_next_pwrst: Set the target power state for a pd + * @pwrdm_read_next_pwrst: Read the target power state set for a pd + * @pwrdm_read_pwrst: Read the current power state of a pd + * @pwrdm_read_prev_pwrst: Read the prev power state entered by the pd + * @pwrdm_set_logic_retst: Set the logic state in RET for a pd + * @pwrdm_set_mem_onst: Set the Memory state in ON for a pd + * @pwrdm_set_mem_retst: Set the Memory state in RET for a pd + * @pwrdm_read_logic_pwrst: Read the current logic state of a pd + * @pwrdm_read_prev_logic_pwrst: Read the previous logic state entered by a pd + * @pwrdm_read_logic_retst: Read the logic state in RET for a pd + * @pwrdm_read_mem_pwrst: Read the current memory state of a pd + * @pwrdm_read_prev_mem_pwrst: Read the previous memory state entered by a pd + * @pwrdm_read_mem_retst: Read the memory state in RET for a pd + * @pwrdm_clear_all_prev_pwrst: Clear all previous power states logged for a pd + * @pwrdm_enable_hdwr_sar: Enable Hardware Save-Restore feature for the pd + * @pwrdm_disable_hdwr_sar: Disable Hardware Save-Restore feature for a pd + * @pwrdm_set_lowpwrstchange: Enable pd transitions from a shallow to deep sleep + * @pwrdm_wait_transition: Wait for a pd state transition to complete + */ +struct pwrdm_ops { + int (*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst); + int (*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm); + int (*pwrdm_read_pwrst)(struct powerdomain *pwrdm); + int (*pwrdm_read_prev_pwrst)(struct powerdomain *pwrdm); + int (*pwrdm_set_logic_retst)(struct powerdomain *pwrdm, u8 pwrst); + int (*pwrdm_set_mem_onst)(struct powerdomain *pwrdm, u8 bank, u8 pwrst); + int (*pwrdm_set_mem_retst)(struct powerdomain *pwrdm, u8 bank, u8 pwrst); + int (*pwrdm_read_logic_pwrst)(struct powerdomain *pwrdm); + int (*pwrdm_read_prev_logic_pwrst)(struct powerdomain *pwrdm); + int (*pwrdm_read_logic_retst)(struct powerdomain *pwrdm); + int (*pwrdm_read_mem_pwrst)(struct powerdomain *pwrdm, u8 bank); + int (*pwrdm_read_prev_mem_pwrst)(struct powerdomain *pwrdm, u8 bank); + int (*pwrdm_read_mem_retst)(struct powerdomain *pwrdm, u8 bank); + int (*pwrdm_clear_all_prev_pwrst)(struct powerdomain *pwrdm); + int (*pwrdm_enable_hdwr_sar)(struct powerdomain *pwrdm); + int (*pwrdm_disable_hdwr_sar)(struct powerdomain *pwrdm); + int (*pwrdm_set_lowpwrstchange)(struct powerdomain *pwrdm); + int (*pwrdm_wait_transition)(struct powerdomain *pwrdm); +}; void pwrdm_fw_init(void); -void pwrdm_init(struct powerdomain **pwrdm_list); +void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs); struct powerdomain *pwrdm_lookup(const char *name); -- cgit v1.2.3 From 6e01478ae8a4322c9a2b2d6efed50196265ed5f2 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 21 Dec 2010 20:01:20 -0700 Subject: OMAP2+: powerdomains: move powerdomain static data to .c files Static data should be declared in .c files, not .h files. It should be possible to #include .h files at any point without creating multiple copies of the same data. We converted the clock data to .c files some time ago. This patch does the same for the powerdomain data. Signed-off-by: Paul Walmsley Cc: Rajendra Nayak Cc: Santosh Shilimkar Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Tested-by: Santosh Shilimkar Tested-by: Rajendra Nayak --- arch/arm/plat-omap/include/plat/powerdomain.h | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/powerdomain.h b/arch/arm/plat-omap/include/plat/powerdomain.h index 583758cbd7d3..b79eebb27a70 100644 --- a/arch/arm/plat-omap/include/plat/powerdomain.h +++ b/arch/arm/plat-omap/include/plat/powerdomain.h @@ -2,17 +2,20 @@ * OMAP2/3 powerdomain control * * Copyright (C) 2007-2008 Texas Instruments, Inc. - * Copyright (C) 2007-2009 Nokia Corporation + * Copyright (C) 2007-2010 Nokia Corporation * * Written by Paul Walmsley * * 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. + * + * XXX This should be moved to the mach-omap2/ directory at the earliest + * opportunity. */ -#ifndef ASM_ARM_ARCH_OMAP_POWERDOMAIN -#define ASM_ARM_ARCH_OMAP_POWERDOMAIN +#ifndef ASM_ARM_PLAT_OMAP_INCLUDE_PLAT_POWERDOMAIN +#define ASM_ARM_PLAT_OMAP_INCLUDE_PLAT_POWERDOMAIN #include #include @@ -206,4 +209,8 @@ int pwrdm_pre_transition(void); int pwrdm_post_transition(void); int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm); +extern void omap2xxx_powerdomains_init(void); +extern void omap3xxx_powerdomains_init(void); +extern void omap44xx_powerdomains_init(void); + #endif -- cgit v1.2.3 From dc0b3a701499bb7727314d7a9c764f7486db4802 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 21 Dec 2010 20:01:20 -0700 Subject: OMAP2+: clockdomains: move clockdomain static data to .c files Static data should be declared in .c files, not .h files. It should be possible to #include .h files at any point without creating multiple copies of the same data. We converted the clock data to .c files some time ago. This patch does the same for the clockdomain data. Signed-off-by: Paul Walmsley Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Tested-by: Santosh Shilimkar Tested-by: Rajendra Nayak --- arch/arm/plat-omap/include/plat/clockdomain.h | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/clockdomain.h b/arch/arm/plat-omap/include/plat/clockdomain.h index ba0a6c07c0fe..a5f8579f7aa9 100644 --- a/arch/arm/plat-omap/include/plat/clockdomain.h +++ b/arch/arm/plat-omap/include/plat/clockdomain.h @@ -4,18 +4,22 @@ * OMAP2/3 clockdomain framework functions * * Copyright (C) 2008 Texas Instruments, Inc. - * Copyright (C) 2008-2009 Nokia Corporation + * Copyright (C) 2008-2010 Nokia Corporation * - * Written by Paul Walmsley + * Paul Walmsley * * 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. + * + * XXX This should be moved to mach-omap2/ at the earliest opportunity. */ #ifndef __ASM_ARM_ARCH_OMAP_CLOCKDOMAIN_H #define __ASM_ARM_ARCH_OMAP_CLOCKDOMAIN_H +#include + #include #include #include @@ -138,4 +142,7 @@ int omap2_clkdm_sleep(struct clockdomain *clkdm); int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk); int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk); +extern void __init omap2_clockdomains_init(void); +extern void __init omap44xx_clockdomains_init(void); + #endif -- cgit v1.2.3 From 59fb659b065f52fcc2deed293cfbfc58f890376c Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 21 Dec 2010 15:30:55 -0700 Subject: OMAP2/3: PRCM: split OMAP2/3-specific PRCM code into OMAP2/3-specific files In preparation for adding OMAP4-specific PRCM accessor/mutator functions, split the existing OMAP2/3 PRCM code into OMAP2/3-specific files. Most of what was in mach-omap2/{cm,prm}.{c,h} has now been moved into mach-omap2/{cm,prm}2xxx_3xxx.{c,h}, since it was OMAP2xxx/3xxx-specific. This process also requires the #includes in each of these files to be changed to reference the new file name. As part of doing so, add some comments into plat-omap/sram.c and plat-omap/mcbsp.c, which use "sideways includes", to indicate that these users of the PRM/CM includes should not be doing so. Thanks to Felipe Contreras for comments on this patch. Signed-off-by: Paul Walmsley Cc: Jarkko Nikula Cc: Peter Ujfalusi Cc: Liam Girdwood Cc: Omar Ramirez Luna Acked-by: Omar Ramirez Luna Cc: Felipe Contreras Acked-by: Felipe Contreras Cc: Greg Kroah-Hartman Acked-by: Mark Brown Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Tested-by: Rajendra Nayak Tested-by: Santosh Shilimkar --- arch/arm/plat-omap/include/plat/common.h | 2 ++ arch/arm/plat-omap/include/plat/prcm.h | 7 ------- arch/arm/plat-omap/mcbsp.c | 2 ++ arch/arm/plat-omap/sram.c | 5 +++-- 4 files changed, 7 insertions(+), 9 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h index a9d69a09920d..6b8088ec74af 100644 --- a/arch/arm/plat-omap/include/plat/common.h +++ b/arch/arm/plat-omap/include/plat/common.h @@ -27,6 +27,8 @@ #ifndef __ARCH_ARM_MACH_OMAP_COMMON_H #define __ARCH_ARM_MACH_OMAP_COMMON_H +#include + #include struct sys_timer; diff --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h index ab77442e42ab..3769fc6eca29 100644 --- a/arch/arm/plat-omap/include/plat/prcm.h +++ b/arch/arm/plat-omap/include/plat/prcm.h @@ -34,15 +34,8 @@ int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest, void omap3_prcm_save_context(void); void omap3_prcm_restore_context(void); -u32 prm_read_mod_reg(s16 module, u16 idx); -void prm_write_mod_reg(u32 val, s16 module, u16 idx); -u32 prm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx); -u32 prm_read_mod_bits_shift(s16 domain, s16 idx, u32 mask); u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask); u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg); -u32 cm_read_mod_reg(s16 module, u16 idx); -void cm_write_mod_reg(u32 val, s16 module, u16 idx); -u32 cm_rmw_mod_reg_bits(u32 mask, u32 bits, s16 module, s16 idx); #endif diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index fdecd339d4f8..95449b90074d 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -28,6 +28,8 @@ #include #include +/* XXX These "sideways" includes are a sign that something is wrong */ +#include "../mach-omap2/cm2xxx_3xxx.h" #include "../mach-omap2/cm-regbits-34xx.h" struct omap_mcbsp **mcbsp_ptr; diff --git a/arch/arm/plat-omap/sram.c b/arch/arm/plat-omap/sram.c index 1a686c89d8dd..e26e50487d60 100644 --- a/arch/arm/plat-omap/sram.c +++ b/arch/arm/plat-omap/sram.c @@ -33,9 +33,10 @@ #include "sram.h" #include "fb.h" + +/* XXX These "sideways" includes are a sign that something is wrong */ #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) -# include "../mach-omap2/prm.h" -# include "../mach-omap2/cm.h" +# include "../mach-omap2/prm2xxx_3xxx.h" # include "../mach-omap2/sdrc.h" #endif -- cgit v1.2.3 From f0611a5c220e50dec65041b10bd2fe9484f061a6 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 21 Dec 2010 15:30:56 -0700 Subject: OMAP3: PRM/CM: separate CM context save/restore; remove PRM context save/restore The OMAP3 PRM module is in the WKUP powerdomain, which is always powered when the chip is powered, so it shouldn't be necessary to save and restore those PRM registers. Remove the PRM register save/restore code, which should save several microseconds during off-mode entry/exit, since PRM register accesses are relatively slow. While doing so, move the CM register save/restore code into CM-specific code. The CM module has been distinct from the PRM module since 2430. This patch includes some minor changes to pm34xx.c. Signed-off-by: Paul Walmsley Cc: Kevin Hilman Cc: Rajendra Nayak Cc: Tero Kristo Cc: Kalle Jokiniemi Reviewed-by: Kevin Hilman Tested-by: Kevin Hilman Tested-by: Santosh Shilimkar Tested-by: Rajendra Nayak --- arch/arm/plat-omap/include/plat/prcm.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h index 3769fc6eca29..d059a05bc457 100644 --- a/arch/arm/plat-omap/include/plat/prcm.h +++ b/arch/arm/plat-omap/include/plat/prcm.h @@ -31,9 +31,6 @@ int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest, #define START_PADCONF_SAVE 0x2 #define PADCONF_SAVE_DONE 0x1 -void omap3_prcm_save_context(void); -void omap3_prcm_restore_context(void); - u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask); u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg); -- cgit v1.2.3 From 2ace831ffc8feaffb8bc03da89ff43d948efdc97 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 21 Dec 2010 21:05:14 -0700 Subject: OMAP4: PRCM: add OMAP4-specific accessor/mutator functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In some ways, the OMAP4 PRCM register layout is quite different than the OMAP2/3 PRCM register layout. For example, on OMAP2/3, from a register layout point of view, all CM instances were located in the CM subsystem, and all PRM instances were located in the PRM subsystem. OMAP4 changes this. Now, for example, some CM instances, such as WKUP_CM and EMU_CM, are located in the system PRM subsystem. And a "local PRCM" exists for the MPU - this PRCM combines registers that would normally appear in both CM and PRM instances, but uses its own register layout which matches neither the OMAP2/3 PRCM layout nor the OMAP4 PRCM layout. To try to deal with this, introduce some new functions, omap4_cminst* and omap4_prminst*. The former is to be used when writing to a CM instance register (no matter what subsystem or hardware module it exists in), and the latter, similarly, with PRM instance registers. To determine which "PRCM partition" to write to, the functions take a PRCM instance ID argument. Subsequent patches add these partition IDs to the OMAP4 powerdomain and clockdomain definitions. As far as I can see, there's really no good way to handle these types of register access inconsistencies. This patch seemed like the least bad approach. Moving forward, the long-term goal is to remove all direct PRCM register access from the PM code. PRCM register access should go through layers such as the powerdomain and clockdomain code that can hide the details of how to interact with the specific hardware variant. While here, rename cm4xxx.c to cm44xx.c to match the naming convention of the other OMAP4 PRCM files. Thanks to Santosh Shilimkar , Rajendra Nayak , and Benoît Cousson for some comments. Signed-off-by: Paul Walmsley Cc: Benoît Cousson Cc: Rajendra Nayak Cc: Santosh Shilimkar --- arch/arm/plat-omap/include/plat/prcm.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h index d059a05bc457..078906d86b6c 100644 --- a/arch/arm/plat-omap/include/plat/prcm.h +++ b/arch/arm/plat-omap/include/plat/prcm.h @@ -18,6 +18,10 @@ * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + * XXX This file is deprecated. The PRCM is an OMAP2+-only subsystem, + * so this file doesn't belong in plat-omap/include/plat. Please + * do not add anything new to this file. */ #ifndef __ASM_ARM_ARCH_OMAP_PRCM_H @@ -31,9 +35,6 @@ int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest, #define START_PADCONF_SAVE 0x2 #define PADCONF_SAVE_DONE 0x1 -u32 omap4_prm_read_bits_shift(void __iomem *reg, u32 mask); -u32 omap4_prm_rmw_reg_bits(u32 mask, u32 bits, void __iomem *reg); - #endif -- cgit v1.2.3 From c4d7e58fb52c632d8e33cd23a4917d7a7f8302ac Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 21 Dec 2010 21:05:14 -0700 Subject: OMAP2/3: PRM/CM: prefix OMAP2 PRM/CM functions with "omap2_" Now that OMAP4-specific PRCM functions have been added, distinguish the existing OMAP2/3-specific PRCM functions by prefixing them with "omap2_". This patch should not result in any functional change. Signed-off-by: Paul Walmsley Cc: Kevin Hilman Cc: Jarkko Nikula Cc: Peter Ujfalusi Cc: Liam Girdwood Cc: Mark Brown Tested-by: Santosh Shilimkar Tested-by: Rajendra Nayak --- arch/arm/plat-omap/mcbsp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c index 95449b90074d..b5a6e178a7f9 100644 --- a/arch/arm/plat-omap/mcbsp.c +++ b/arch/arm/plat-omap/mcbsp.c @@ -236,9 +236,9 @@ static void omap_st_on(struct omap_mcbsp *mcbsp) * Sidetone uses McBSP ICLK - which must not idle when sidetones * are enabled or sidetones start sounding ugly. */ - w = cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE); + w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE); w &= ~(1 << (mcbsp->id - 2)); - cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE); + omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE); /* Enable McBSP Sidetone */ w = MCBSP_READ(mcbsp, SSELCR); @@ -265,9 +265,9 @@ static void omap_st_off(struct omap_mcbsp *mcbsp) w = MCBSP_READ(mcbsp, SSELCR); MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN)); - w = cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE); + w = omap2_cm_read_mod_reg(OMAP3430_PER_MOD, CM_AUTOIDLE); w |= 1 << (mcbsp->id - 2); - cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE); + omap2_cm_write_mod_reg(w, OMAP3430_PER_MOD, CM_AUTOIDLE); } static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir) -- cgit v1.2.3 From a64bb9cda8b12f599766c7dfe81770d2082a133a Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 21 Dec 2010 21:05:14 -0700 Subject: OMAP4: powerdomains: add PRCM partition data; use OMAP4 PRM functions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit OMAP4 powerdomain control registers are split between the PRM hardware module and the PRCM_MPU local PRCM. Add this PRCM partition information to each OMAP4 powerdomain record, and convert the OMAP4 powerdomain function implementations to use the OMAP4 PRM instance functions. Also fixes a potential null pointer dereference of pwrdm->name. The autogeneration scripts have been updated. Signed-off-by: Paul Walmsley Cc: Rajendra Nayak Cc: Santosh Shilimkar Cc: Benoît Cousson Tested-by: Santosh Shilimkar Tested-by: Rajendra Nayak --- arch/arm/plat-omap/include/plat/powerdomain.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/powerdomain.h b/arch/arm/plat-omap/include/plat/powerdomain.h index b79eebb27a70..a0d3a30de9fd 100644 --- a/arch/arm/plat-omap/include/plat/powerdomain.h +++ b/arch/arm/plat-omap/include/plat/powerdomain.h @@ -1,5 +1,5 @@ /* - * OMAP2/3 powerdomain control + * OMAP2/3/4 powerdomain control * * Copyright (C) 2007-2008 Texas Instruments, Inc. * Copyright (C) 2007-2010 Nokia Corporation @@ -24,7 +24,6 @@ #include - /* Powerdomain basic power states */ #define PWRDM_POWER_OFF 0x0 #define PWRDM_POWER_RET 0x1 @@ -84,6 +83,7 @@ struct powerdomain; * @name: Powerdomain name * @omap_chip: represents the OMAP chip types containing this pwrdm * @prcm_offs: the address offset from CM_BASE/PRM_BASE + * @prcm_partition: (OMAP4 only) the PRCM partition ID containing @prcm_offs * @pwrsts: Possible powerdomain power states * @pwrsts_logic_ret: Possible logic power states when pwrdm in RETENTION * @flags: Powerdomain flags @@ -96,6 +96,8 @@ struct powerdomain; * @state_counter: * @timer: * @state_timer: + * + * @prcm_partition possible values are defined in mach-omap2/prcm44xx.h. */ struct powerdomain { const char *name; @@ -107,6 +109,7 @@ struct powerdomain { const u8 banks; const u8 pwrsts_mem_ret[PWRDM_MAX_MEM_BANKS]; const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS]; + const u8 prcm_partition; struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS]; struct list_head node; int state; -- cgit v1.2.3 From bd2122ca358fbd5c8e94869ae731a0951b36c757 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 21 Dec 2010 21:05:15 -0700 Subject: OMAP4: clockdomains: add OMAP4 PRCM data and OMAP4 support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add PRCM partition, CM instance register address offset, and clockdomain register address offset to each OMAP4 struct clockdomain record. Add OMAP4 clockdomain code to use this new data to access registers properly. While here, clean up some nearby clockdomain code to allocate auto variables in my recollection of Linus's preferred style. The autogeneration scripts have been updated. Signed-off-by: Paul Walmsley Cc: Rajendra Nayak Cc: Santosh Shilimkar Cc: Benoît Cousson Tested-by: Rajendra Nayak Tested-by: Santosh Shilimkar --- arch/arm/plat-omap/include/plat/clockdomain.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/clockdomain.h b/arch/arm/plat-omap/include/plat/clockdomain.h index a5f8579f7aa9..ec433c3aef68 100644 --- a/arch/arm/plat-omap/include/plat/clockdomain.h +++ b/arch/arm/plat-omap/include/plat/clockdomain.h @@ -38,12 +38,6 @@ #define OMAP24XX_CLKSTCTRL_DISABLE_AUTO 0x0 #define OMAP24XX_CLKSTCTRL_ENABLE_AUTO 0x1 -/* OMAP3XXX CM_CLKSTCTRL_*.CLKTRCTRL_* register bit values */ -#define OMAP34XX_CLKSTCTRL_DISABLE_AUTO 0x0 -#define OMAP34XX_CLKSTCTRL_FORCE_SLEEP 0x1 -#define OMAP34XX_CLKSTCTRL_FORCE_WAKEUP 0x2 -#define OMAP34XX_CLKSTCTRL_ENABLE_AUTO 0x3 - /** * struct clkdm_autodep - clkdm deps to add when entering/exiting hwsup mode * @clkdm: clockdomain to add wkdep+sleepdep on - set name member only @@ -94,11 +88,20 @@ struct clkdm_dep { * @clktrctrl_mask: CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg * @flags: Clockdomain capability flags * @dep_bit: Bit shift of this clockdomain's PM_WKDEP/CM_SLEEPDEP bit + * @prcm_partition: (OMAP4 only) PRCM partition ID for this clkdm's registers + * @cm_inst: (OMAP4 only) CM instance register offset + * @clkdm_offs: (OMAP4 only) CM clockdomain register offset * @wkdep_srcs: Clockdomains that can be told to wake this powerdomain up * @sleepdep_srcs: Clockdomains that can be told to keep this clkdm from inact * @omap_chip: OMAP chip types that this clockdomain is valid on * @usecount: Usecount tracking * @node: list_head to link all clockdomains together + * + * @prcm_partition should be a macro from mach-omap2/prcm44xx.h (OMAP4 only) + * @cm_inst should be a macro ending in _INST from the OMAP4 CM instance + * definitions (OMAP4 only) + * @clkdm_offs should be a macro ending in _CDOFFS from the OMAP4 CM instance + * definitions (OMAP4 only) */ struct clockdomain { const char *name; @@ -106,10 +109,15 @@ struct clockdomain { const char *name; struct powerdomain *ptr; } pwrdm; +#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) void __iomem *clkstctrl_reg; const u16 clktrctrl_mask; +#endif const u8 flags; const u8 dep_bit; + const u8 prcm_partition; + const s16 cm_inst; + const u16 clkdm_offs; struct clkdm_dep *wkdep_srcs; struct clkdm_dep *sleepdep_srcs; const struct omap_chip_id omap_chip; -- cgit v1.2.3 From 55ae35073b1c76f24c3736cf797c40d9932b19aa Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 21 Dec 2010 21:05:15 -0700 Subject: OMAP2/3: clockdomain: remove unneeded .clkstctrl_reg, remove some direct CM register accesses Reverse some of the effects of commit 84c0c39aec31a09571fc08a752a2f4da0fe9fcf2 ("ARM: OMAP4: PM: Make OMAP3 Clock-domain framework compatible for OMAP4"). On OMAP2/3, the CM_CLKSTCTRL register is at a constant offset from the powerdomain's CM instance. Also, remove some of the direct CM register access from the clockdomain code, moving it to the OMAP2/3 CM code instead. The intention here is to simplify the clockdomain code. (The long-term goal is to move all direct CM register access across the OMAP core code to the appropriate cm*.c file.) Signed-off-by: Paul Walmsley Tested-by: Rajendra Nayak Tested-by: Santosh Shilimkar --- arch/arm/plat-omap/include/plat/clockdomain.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/clockdomain.h b/arch/arm/plat-omap/include/plat/clockdomain.h index ec433c3aef68..e91ae92f217c 100644 --- a/arch/arm/plat-omap/include/plat/clockdomain.h +++ b/arch/arm/plat-omap/include/plat/clockdomain.h @@ -34,10 +34,6 @@ #define CLKDM_CAN_SWSUP (CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP) #define CLKDM_CAN_HWSUP_SWSUP (CLKDM_CAN_SWSUP | CLKDM_CAN_HWSUP) -/* OMAP24XX CM_CLKSTCTRL_*.AUTOSTATE_* register bit values */ -#define OMAP24XX_CLKSTCTRL_DISABLE_AUTO 0x0 -#define OMAP24XX_CLKSTCTRL_ENABLE_AUTO 0x1 - /** * struct clkdm_autodep - clkdm deps to add when entering/exiting hwsup mode * @clkdm: clockdomain to add wkdep+sleepdep on - set name member only @@ -110,7 +106,6 @@ struct clockdomain { struct powerdomain *ptr; } pwrdm; #if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) - void __iomem *clkstctrl_reg; const u16 clktrctrl_mask; #endif const u8 flags; -- cgit v1.2.3 From 1540f214065982e6cbc6b8da1fe65a15e358f7c5 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 21 Dec 2010 21:05:15 -0700 Subject: OMAP2+: clockdomain: move header file from plat-omap to mach-omap2 The OMAP clockdomain code and data is all OMAP2+-specific. This seems unlikely to change any time soon. Move plat-omap/include/plat/clockdomain.h to mach-omap2/clockdomain.h. The primary point of doing this is to remove the temptation for unrelated upper-layer code to access clockdomain code and data directly. DSPBridge also uses the clockdomain headers for some reason, so, modify it also. The DSPBridge code should not be including the clockdomain headers; these should be removed. Signed-off-by: Paul Walmsley Cc: Kevin Hilman Cc: Omar Ramirez Luna Cc: Felipe Contreras Cc: Greg Kroah-Hartman Tested-by: Rajendra Nayak Tested-by: Santosh Shilimkar --- arch/arm/plat-omap/include/plat/clockdomain.h | 151 -------------------------- 1 file changed, 151 deletions(-) delete mode 100644 arch/arm/plat-omap/include/plat/clockdomain.h (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/clockdomain.h b/arch/arm/plat-omap/include/plat/clockdomain.h deleted file mode 100644 index e91ae92f217c..000000000000 --- a/arch/arm/plat-omap/include/plat/clockdomain.h +++ /dev/null @@ -1,151 +0,0 @@ -/* - * arch/arm/plat-omap/include/mach/clockdomain.h - * - * OMAP2/3 clockdomain framework functions - * - * Copyright (C) 2008 Texas Instruments, Inc. - * Copyright (C) 2008-2010 Nokia Corporation - * - * Paul Walmsley - * - * 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. - * - * XXX This should be moved to mach-omap2/ at the earliest opportunity. - */ - -#ifndef __ASM_ARM_ARCH_OMAP_CLOCKDOMAIN_H -#define __ASM_ARM_ARCH_OMAP_CLOCKDOMAIN_H - -#include - -#include -#include -#include - -/* Clockdomain capability flags */ -#define CLKDM_CAN_FORCE_SLEEP (1 << 0) -#define CLKDM_CAN_FORCE_WAKEUP (1 << 1) -#define CLKDM_CAN_ENABLE_AUTO (1 << 2) -#define CLKDM_CAN_DISABLE_AUTO (1 << 3) - -#define CLKDM_CAN_HWSUP (CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO) -#define CLKDM_CAN_SWSUP (CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP) -#define CLKDM_CAN_HWSUP_SWSUP (CLKDM_CAN_SWSUP | CLKDM_CAN_HWSUP) - -/** - * struct clkdm_autodep - clkdm deps to add when entering/exiting hwsup mode - * @clkdm: clockdomain to add wkdep+sleepdep on - set name member only - * @omap_chip: OMAP chip types that this autodep is valid on - * - * A clockdomain that should have wkdeps and sleepdeps added when a - * clockdomain should stay active in hwsup mode; and conversely, - * removed when the clockdomain should be allowed to go inactive in - * hwsup mode. - * - * Autodeps are deprecated and should be removed after - * omap_hwmod-based fine-grained module idle control is added. - */ -struct clkdm_autodep { - union { - const char *name; - struct clockdomain *ptr; - } clkdm; - const struct omap_chip_id omap_chip; -}; - -/** - * struct clkdm_dep - encode dependencies between clockdomains - * @clkdm_name: clockdomain name - * @clkdm: pointer to the struct clockdomain of @clkdm_name - * @omap_chip: OMAP chip types that this dependency is valid on - * @wkdep_usecount: Number of wakeup dependencies causing this clkdm to wake - * @sleepdep_usecount: Number of sleep deps that could prevent clkdm from idle - * - * Statically defined. @clkdm is resolved from @clkdm_name at runtime and - * should not be pre-initialized. - * - * XXX Should also include hardware (fixed) dependencies. - */ -struct clkdm_dep { - const char *clkdm_name; - struct clockdomain *clkdm; - atomic_t wkdep_usecount; - atomic_t sleepdep_usecount; - const struct omap_chip_id omap_chip; -}; - -/** - * struct clockdomain - OMAP clockdomain - * @name: clockdomain name - * @pwrdm: powerdomain containing this clockdomain - * @clktrctrl_reg: CLKSTCTRL reg for the given clock domain - * @clktrctrl_mask: CLKTRCTRL/AUTOSTATE field mask in CM_CLKSTCTRL reg - * @flags: Clockdomain capability flags - * @dep_bit: Bit shift of this clockdomain's PM_WKDEP/CM_SLEEPDEP bit - * @prcm_partition: (OMAP4 only) PRCM partition ID for this clkdm's registers - * @cm_inst: (OMAP4 only) CM instance register offset - * @clkdm_offs: (OMAP4 only) CM clockdomain register offset - * @wkdep_srcs: Clockdomains that can be told to wake this powerdomain up - * @sleepdep_srcs: Clockdomains that can be told to keep this clkdm from inact - * @omap_chip: OMAP chip types that this clockdomain is valid on - * @usecount: Usecount tracking - * @node: list_head to link all clockdomains together - * - * @prcm_partition should be a macro from mach-omap2/prcm44xx.h (OMAP4 only) - * @cm_inst should be a macro ending in _INST from the OMAP4 CM instance - * definitions (OMAP4 only) - * @clkdm_offs should be a macro ending in _CDOFFS from the OMAP4 CM instance - * definitions (OMAP4 only) - */ -struct clockdomain { - const char *name; - union { - const char *name; - struct powerdomain *ptr; - } pwrdm; -#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3) - const u16 clktrctrl_mask; -#endif - const u8 flags; - const u8 dep_bit; - const u8 prcm_partition; - const s16 cm_inst; - const u16 clkdm_offs; - struct clkdm_dep *wkdep_srcs; - struct clkdm_dep *sleepdep_srcs; - const struct omap_chip_id omap_chip; - atomic_t usecount; - struct list_head node; -}; - -void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps); -struct clockdomain *clkdm_lookup(const char *name); - -int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user), - void *user); -struct powerdomain *clkdm_get_pwrdm(struct clockdomain *clkdm); - -int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); -int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); -int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); -int clkdm_clear_all_wkdeps(struct clockdomain *clkdm); -int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); -int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); -int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2); -int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm); - -void omap2_clkdm_allow_idle(struct clockdomain *clkdm); -void omap2_clkdm_deny_idle(struct clockdomain *clkdm); - -int omap2_clkdm_wakeup(struct clockdomain *clkdm); -int omap2_clkdm_sleep(struct clockdomain *clkdm); - -int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk); -int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk); - -extern void __init omap2_clockdomains_init(void); -extern void __init omap44xx_clockdomains_init(void); - -#endif -- cgit v1.2.3 From 72e06d087204f3bc9acf281717b90ebf0b9731f7 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 21 Dec 2010 21:05:16 -0700 Subject: OMAP2+: powerdomain: move header file from plat-omap to mach-omap2 The OMAP powerdomain code and data is all OMAP2+-specific. This seems unlikely to change any time soon. Move plat-omap/include/plat/powerdomain.h to mach-omap2/powerdomain.h. The primary point of doing this is to remove the temptation for unrelated upper-layer code to access powerdomain code and data directly. As part of this process, remove the references to powerdomain data from the GPIO "driver" and the OMAP PM no-op layer, both in plat-omap. Change the DSPBridge code to point to the new location for the powerdomain headers. The DSPBridge code should not be including the powerdomain headers; these should be removed. Signed-off-by: Paul Walmsley Cc: Kevin Hilman Cc: Omar Ramirez Luna Cc: Felipe Contreras Cc: Greg Kroah-Hartman --- arch/arm/plat-omap/gpio.c | 5 +- arch/arm/plat-omap/include/plat/gpio.h | 2 +- arch/arm/plat-omap/include/plat/omap-pm.h | 2 - arch/arm/plat-omap/include/plat/powerdomain.h | 219 -------------------------- arch/arm/plat-omap/omap-pm-noop.c | 2 - 5 files changed, 3 insertions(+), 227 deletions(-) delete mode 100644 arch/arm/plat-omap/include/plat/powerdomain.h (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/gpio.c b/arch/arm/plat-omap/gpio.c index 8d493b992e70..1f98e0b94847 100644 --- a/arch/arm/plat-omap/gpio.c +++ b/arch/arm/plat-omap/gpio.c @@ -29,7 +29,6 @@ #include #include #include -#include /* * OMAP1510 GPIO registers @@ -1864,7 +1863,7 @@ static struct sys_device omap_gpio_device = { static int workaround_enabled; -void omap2_gpio_prepare_for_idle(int power_state) +void omap2_gpio_prepare_for_idle(int off_mode) { int i, c = 0; int min = 0; @@ -1880,7 +1879,7 @@ void omap2_gpio_prepare_for_idle(int power_state) for (j = 0; j < hweight_long(bank->dbck_enable_mask); j++) clk_disable(bank->dbck); - if (power_state > PWRDM_POWER_OFF) + if (!off_mode) continue; /* If going to OFF, remove triggering for all diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h index 41ff2f8943f0..d6f9fa0f62af 100644 --- a/arch/arm/plat-omap/include/plat/gpio.h +++ b/arch/arm/plat-omap/include/plat/gpio.h @@ -82,7 +82,7 @@ struct omap_gpio_platform_data { /* TODO: Analyze removing gpio_bank_count usage from driver code */ extern int gpio_bank_count; -extern void omap2_gpio_prepare_for_idle(int power_state); +extern void omap2_gpio_prepare_for_idle(int off_mode); extern void omap2_gpio_resume_after_idle(void); extern void omap_set_gpio_debounce(int gpio, int enable); extern void omap_set_gpio_debounce_time(int gpio, int enable); diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h index 62c3fe918ab2..47d61107ccda 100644 --- a/arch/arm/plat-omap/include/plat/omap-pm.h +++ b/arch/arm/plat-omap/include/plat/omap-pm.h @@ -19,8 +19,6 @@ #include #include -#include "powerdomain.h" - /* * agent_id values for use with omap_pm_set_min_bus_tput(): * diff --git a/arch/arm/plat-omap/include/plat/powerdomain.h b/arch/arm/plat-omap/include/plat/powerdomain.h deleted file mode 100644 index a0d3a30de9fd..000000000000 --- a/arch/arm/plat-omap/include/plat/powerdomain.h +++ /dev/null @@ -1,219 +0,0 @@ -/* - * OMAP2/3/4 powerdomain control - * - * Copyright (C) 2007-2008 Texas Instruments, Inc. - * Copyright (C) 2007-2010 Nokia Corporation - * - * Written by Paul Walmsley - * - * 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. - * - * XXX This should be moved to the mach-omap2/ directory at the earliest - * opportunity. - */ - -#ifndef ASM_ARM_PLAT_OMAP_INCLUDE_PLAT_POWERDOMAIN -#define ASM_ARM_PLAT_OMAP_INCLUDE_PLAT_POWERDOMAIN - -#include -#include - -#include - -#include - -/* Powerdomain basic power states */ -#define PWRDM_POWER_OFF 0x0 -#define PWRDM_POWER_RET 0x1 -#define PWRDM_POWER_INACTIVE 0x2 -#define PWRDM_POWER_ON 0x3 - -#define PWRDM_MAX_PWRSTS 4 - -/* Powerdomain allowable state bitfields */ -#define PWRSTS_ON (1 << PWRDM_POWER_ON) -#define PWRSTS_OFF (1 << PWRDM_POWER_OFF) -#define PWRSTS_OFF_ON ((1 << PWRDM_POWER_OFF) | \ - (1 << PWRDM_POWER_ON)) - -#define PWRSTS_OFF_RET ((1 << PWRDM_POWER_OFF) | \ - (1 << PWRDM_POWER_RET)) - -#define PWRSTS_RET_ON ((1 << PWRDM_POWER_RET) | \ - (1 << PWRDM_POWER_ON)) - -#define PWRSTS_OFF_RET_ON (PWRSTS_OFF_RET | (1 << PWRDM_POWER_ON)) - - -/* Powerdomain flags */ -#define PWRDM_HAS_HDWR_SAR (1 << 0) /* hardware save-and-restore support */ -#define PWRDM_HAS_MPU_QUIRK (1 << 1) /* MPU pwr domain has MEM bank 0 bits - * in MEM bank 1 position. This is - * true for OMAP3430 - */ -#define PWRDM_HAS_LOWPOWERSTATECHANGE (1 << 2) /* - * support to transition from a - * sleep state to a lower sleep - * state without waking up the - * powerdomain - */ - -/* - * Number of memory banks that are power-controllable. On OMAP4430, the - * maximum is 5. - */ -#define PWRDM_MAX_MEM_BANKS 5 - -/* - * Maximum number of clockdomains that can be associated with a powerdomain. - * CORE powerdomain on OMAP4 is the worst case - */ -#define PWRDM_MAX_CLKDMS 9 - -/* XXX A completely arbitrary number. What is reasonable here? */ -#define PWRDM_TRANSITION_BAILOUT 100000 - -struct clockdomain; -struct powerdomain; - -/** - * struct powerdomain - OMAP powerdomain - * @name: Powerdomain name - * @omap_chip: represents the OMAP chip types containing this pwrdm - * @prcm_offs: the address offset from CM_BASE/PRM_BASE - * @prcm_partition: (OMAP4 only) the PRCM partition ID containing @prcm_offs - * @pwrsts: Possible powerdomain power states - * @pwrsts_logic_ret: Possible logic power states when pwrdm in RETENTION - * @flags: Powerdomain flags - * @banks: Number of software-controllable memory banks in this powerdomain - * @pwrsts_mem_ret: Possible memory bank pwrstates when pwrdm in RETENTION - * @pwrsts_mem_on: Possible memory bank pwrstates when pwrdm in ON - * @pwrdm_clkdms: Clockdomains in this powerdomain - * @node: list_head linking all powerdomains - * @state: - * @state_counter: - * @timer: - * @state_timer: - * - * @prcm_partition possible values are defined in mach-omap2/prcm44xx.h. - */ -struct powerdomain { - const char *name; - const struct omap_chip_id omap_chip; - const s16 prcm_offs; - const u8 pwrsts; - const u8 pwrsts_logic_ret; - const u8 flags; - const u8 banks; - const u8 pwrsts_mem_ret[PWRDM_MAX_MEM_BANKS]; - const u8 pwrsts_mem_on[PWRDM_MAX_MEM_BANKS]; - const u8 prcm_partition; - struct clockdomain *pwrdm_clkdms[PWRDM_MAX_CLKDMS]; - struct list_head node; - int state; - unsigned state_counter[PWRDM_MAX_PWRSTS]; - unsigned ret_logic_off_counter; - unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS]; - -#ifdef CONFIG_PM_DEBUG - s64 timer; - s64 state_timer[PWRDM_MAX_PWRSTS]; -#endif -}; - -/** - * struct pwrdm_ops - Arch specfic function implementations - * @pwrdm_set_next_pwrst: Set the target power state for a pd - * @pwrdm_read_next_pwrst: Read the target power state set for a pd - * @pwrdm_read_pwrst: Read the current power state of a pd - * @pwrdm_read_prev_pwrst: Read the prev power state entered by the pd - * @pwrdm_set_logic_retst: Set the logic state in RET for a pd - * @pwrdm_set_mem_onst: Set the Memory state in ON for a pd - * @pwrdm_set_mem_retst: Set the Memory state in RET for a pd - * @pwrdm_read_logic_pwrst: Read the current logic state of a pd - * @pwrdm_read_prev_logic_pwrst: Read the previous logic state entered by a pd - * @pwrdm_read_logic_retst: Read the logic state in RET for a pd - * @pwrdm_read_mem_pwrst: Read the current memory state of a pd - * @pwrdm_read_prev_mem_pwrst: Read the previous memory state entered by a pd - * @pwrdm_read_mem_retst: Read the memory state in RET for a pd - * @pwrdm_clear_all_prev_pwrst: Clear all previous power states logged for a pd - * @pwrdm_enable_hdwr_sar: Enable Hardware Save-Restore feature for the pd - * @pwrdm_disable_hdwr_sar: Disable Hardware Save-Restore feature for a pd - * @pwrdm_set_lowpwrstchange: Enable pd transitions from a shallow to deep sleep - * @pwrdm_wait_transition: Wait for a pd state transition to complete - */ -struct pwrdm_ops { - int (*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst); - int (*pwrdm_read_next_pwrst)(struct powerdomain *pwrdm); - int (*pwrdm_read_pwrst)(struct powerdomain *pwrdm); - int (*pwrdm_read_prev_pwrst)(struct powerdomain *pwrdm); - int (*pwrdm_set_logic_retst)(struct powerdomain *pwrdm, u8 pwrst); - int (*pwrdm_set_mem_onst)(struct powerdomain *pwrdm, u8 bank, u8 pwrst); - int (*pwrdm_set_mem_retst)(struct powerdomain *pwrdm, u8 bank, u8 pwrst); - int (*pwrdm_read_logic_pwrst)(struct powerdomain *pwrdm); - int (*pwrdm_read_prev_logic_pwrst)(struct powerdomain *pwrdm); - int (*pwrdm_read_logic_retst)(struct powerdomain *pwrdm); - int (*pwrdm_read_mem_pwrst)(struct powerdomain *pwrdm, u8 bank); - int (*pwrdm_read_prev_mem_pwrst)(struct powerdomain *pwrdm, u8 bank); - int (*pwrdm_read_mem_retst)(struct powerdomain *pwrdm, u8 bank); - int (*pwrdm_clear_all_prev_pwrst)(struct powerdomain *pwrdm); - int (*pwrdm_enable_hdwr_sar)(struct powerdomain *pwrdm); - int (*pwrdm_disable_hdwr_sar)(struct powerdomain *pwrdm); - int (*pwrdm_set_lowpwrstchange)(struct powerdomain *pwrdm); - int (*pwrdm_wait_transition)(struct powerdomain *pwrdm); -}; - -void pwrdm_fw_init(void); -void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs); - -struct powerdomain *pwrdm_lookup(const char *name); - -int pwrdm_for_each(int (*fn)(struct powerdomain *pwrdm, void *user), - void *user); -int pwrdm_for_each_nolock(int (*fn)(struct powerdomain *pwrdm, void *user), - void *user); - -int pwrdm_add_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); -int pwrdm_del_clkdm(struct powerdomain *pwrdm, struct clockdomain *clkdm); -int pwrdm_for_each_clkdm(struct powerdomain *pwrdm, - int (*fn)(struct powerdomain *pwrdm, - struct clockdomain *clkdm)); - -int pwrdm_get_mem_bank_count(struct powerdomain *pwrdm); - -int pwrdm_set_next_pwrst(struct powerdomain *pwrdm, u8 pwrst); -int pwrdm_read_next_pwrst(struct powerdomain *pwrdm); -int pwrdm_read_pwrst(struct powerdomain *pwrdm); -int pwrdm_read_prev_pwrst(struct powerdomain *pwrdm); -int pwrdm_clear_all_prev_pwrst(struct powerdomain *pwrdm); - -int pwrdm_set_logic_retst(struct powerdomain *pwrdm, u8 pwrst); -int pwrdm_set_mem_onst(struct powerdomain *pwrdm, u8 bank, u8 pwrst); -int pwrdm_set_mem_retst(struct powerdomain *pwrdm, u8 bank, u8 pwrst); - -int pwrdm_read_logic_pwrst(struct powerdomain *pwrdm); -int pwrdm_read_prev_logic_pwrst(struct powerdomain *pwrdm); -int pwrdm_read_logic_retst(struct powerdomain *pwrdm); -int pwrdm_read_mem_pwrst(struct powerdomain *pwrdm, u8 bank); -int pwrdm_read_prev_mem_pwrst(struct powerdomain *pwrdm, u8 bank); -int pwrdm_read_mem_retst(struct powerdomain *pwrdm, u8 bank); - -int pwrdm_enable_hdwr_sar(struct powerdomain *pwrdm); -int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm); -bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm); - -int pwrdm_wait_transition(struct powerdomain *pwrdm); - -int pwrdm_state_switch(struct powerdomain *pwrdm); -int pwrdm_clkdm_state_switch(struct clockdomain *clkdm); -int pwrdm_pre_transition(void); -int pwrdm_post_transition(void); -int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm); - -extern void omap2xxx_powerdomains_init(void); -extern void omap3xxx_powerdomains_init(void); -extern void omap44xx_powerdomains_init(void); - -#endif diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c index ca75abb18068..19cb9f5a9f04 100644 --- a/arch/arm/plat-omap/omap-pm-noop.c +++ b/arch/arm/plat-omap/omap-pm-noop.c @@ -24,8 +24,6 @@ /* Interface documentation is in mach/omap-pm.h */ #include -#include - /* * Device-driver-originated constraints (via board-*.c files) */ -- cgit v1.2.3 From 596efe4792c50163578578bd4fe470f97652aad7 Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 21 Dec 2010 21:05:16 -0700 Subject: OMAP3: control/PM: move padconf save code to mach-omap2/control.c Move the padconf save code from pm34xx.c to the System Control Module code in mach-omap2/control.c. This is part of the general push to move direct register access from middle-layer core code to low-level core code, so the middle-layer code can be abstracted to work on multiple platforms and cleaned up. In the medium-to-long term, this code should be called by the mux layer code, not the PM idle code. This is because, according to the TRM, saving the padconf only needs to be done when the padconf changes[1]. Signed-off-by: Paul Walmsley Cc: Kevin Hilman Cc: Tony Lindgren Tested-by: Rajendra Nayak Tested-by: Santosh Shilimkar 1. OMAP34xx Multimedia Device Silicon Revision 3.1.x [Rev. ZH] [SWPU222H] Section 4.11.4 "Device Off-Mode Sequences" --- arch/arm/plat-omap/include/plat/prcm.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/prcm.h b/arch/arm/plat-omap/include/plat/prcm.h index 078906d86b6c..2fdf8c80d390 100644 --- a/arch/arm/plat-omap/include/plat/prcm.h +++ b/arch/arm/plat-omap/include/plat/prcm.h @@ -32,9 +32,6 @@ void omap_prcm_arch_reset(char mode, const char *cmd); int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest, const char *name); -#define START_PADCONF_SAVE 0x2 -#define PADCONF_SAVE_DONE 0x1 - #endif -- cgit v1.2.3 From 553d239aadc75bee70c7858ac4548d073cb3daff Mon Sep 17 00:00:00 2001 From: Paul Walmsley Date: Tue, 21 Dec 2010 21:08:14 -0700 Subject: OMAP3: clock: clarify usage of struct clksel_rate.flags and struct omap_clk.cpu Clarify the usage of the struct omap_clk.cpu flags (e.g., CK_*) to use bits only for individual SoC variants (e.g., CK_3430ES1, CK_3505, etc.). Superset flags, such as CK_3XXX or CK_AM35XX, are now defined as disjunctions of individual SoC variant flags. This simplifies the definition and use of these flags. struct omap_clk record definitions can now simply specify the bitmask of actual SoCs that the records are valid for. The clock init code can simply set a single CPU type mask bit for the SoC that is currently in use, and test against that, rather than needing to set some combination of flags. Similarly, clarify the use of struct clksel_rate.flags. The bit allocated for RATE_IN_3XXX has been reassigned, and RATE_IN_3XXX has been defined as a disjunction of the 34xx and 36xx rate flags. The advantages are the same as the above. Clarify the usage of struct omap_clk.cpu flags such as CK_34XX to only apply to the SoCs that they name, e.g., OMAP34xx chips. The previous practice caused significantly different SoCs, such as OMAP36xx, to be included in CK_34XX. In my opinion, this is much more intuitive. Similarly, clarify the use of struct clksel_rate.flags, such that RATE_IN_3430ES2PLUS now only applies to 34xx chips with ES level >= 2 - it does not apply to OMAP36xx. ... At some point, it probably makes sense to collapse the CK_* and RATE_IN_* flags together into a single bitfield, and possibly use the existing CHIP_IS_OMAP* flags for platform detection. ... This all seems to work fine on OMAP34xx and OMAP36xx Beagle. Not sure if it works on Sitara or the TI816X, unfortunately I don't have any here to test with. Signed-off-by: Paul Walmsley --- arch/arm/plat-omap/include/plat/clkdev_omap.h | 20 ++++++++++---------- arch/arm/plat-omap/include/plat/clock.h | 11 ++++++++--- 2 files changed, 18 insertions(+), 13 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/clkdev_omap.h b/arch/arm/plat-omap/include/plat/clkdev_omap.h index bb937f3fabed..b19774c9c112 100644 --- a/arch/arm/plat-omap/include/plat/clkdev_omap.h +++ b/arch/arm/plat-omap/include/plat/clkdev_omap.h @@ -31,18 +31,18 @@ struct omap_clk { #define CK_1510 (1 << 2) #define CK_16XX (1 << 3) /* 16xx, 17xx, 5912 */ #define CK_242X (1 << 4) -#define CK_243X (1 << 5) -#define CK_3XXX (1 << 6) /* OMAP3 + AM3 common clocks*/ -#define CK_343X (1 << 7) /* OMAP34xx common clocks */ -#define CK_3430ES1 (1 << 8) /* 34xxES1 only */ -#define CK_3430ES2 (1 << 9) /* 34xxES2, ES3, non-Sitara 35xx only */ -#define CK_3505 (1 << 10) -#define CK_3517 (1 << 11) -#define CK_36XX (1 << 12) /* OMAP36xx/37xx-specific clocks */ -#define CK_443X (1 << 13) +#define CK_243X (1 << 5) /* 243x, 253x */ +#define CK_3430ES1 (1 << 6) /* 34xxES1 only */ +#define CK_3430ES2PLUS (1 << 7) /* 34xxES2, ES3, non-Sitara 35xx only */ +#define CK_3505 (1 << 8) +#define CK_3517 (1 << 9) +#define CK_36XX (1 << 10) /* 36xx/37xx-specific clocks */ +#define CK_443X (1 << 11) -#define CK_AM35XX (CK_3505 | CK_3517) /* all Sitara AM35xx */ +#define CK_34XX (CK_3430ES1 | CK_3430ES2PLUS) +#define CK_AM35XX (CK_3505 | CK_3517) /* all Sitara AM35xx */ +#define CK_3XXX (CK_34XX | CK_AM35XX | CK_36XX) #endif diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h index fef4696dcf67..6e223158268b 100644 --- a/arch/arm/plat-omap/include/plat/clock.h +++ b/arch/arm/plat-omap/include/plat/clock.h @@ -49,13 +49,18 @@ struct clkops { /* struct clksel_rate.flags possibilities */ #define RATE_IN_242X (1 << 0) #define RATE_IN_243X (1 << 1) -#define RATE_IN_3XXX (1 << 2) /* rates common to all OMAP3 */ -#define RATE_IN_3430ES2 (1 << 3) /* 3430ES2 rates only */ +#define RATE_IN_3430ES1 (1 << 2) /* 3430ES1 rates only */ +#define RATE_IN_3430ES2PLUS (1 << 3) /* 3430 ES >= 2 rates only */ #define RATE_IN_36XX (1 << 4) #define RATE_IN_4430 (1 << 5) #define RATE_IN_24XX (RATE_IN_242X | RATE_IN_243X) -#define RATE_IN_3430ES2PLUS (RATE_IN_3430ES2 | RATE_IN_36XX) +#define RATE_IN_34XX (RATE_IN_3430ES1 | RATE_IN_3430ES2PLUS) +#define RATE_IN_3XXX (RATE_IN_34XX | RATE_IN_36XX) + +/* RATE_IN_3430ES2PLUS_36XX includes 34xx/35xx with ES >=2, and all 36xx/37xx */ +#define RATE_IN_3430ES2PLUS_36XX (RATE_IN_3430ES2PLUS | RATE_IN_36XX) + /** * struct clksel_rate - register bitfield values corresponding to clk divisors -- cgit v1.2.3 From 0102b62789af5aed92cea4cf7f36afaa1ab12c72 Mon Sep 17 00:00:00 2001 From: Benoit Cousson Date: Tue, 21 Dec 2010 21:31:27 -0700 Subject: OMAP2+: hwmod: Make omap_hwmod_register private and remove omap_hwmod_unregister Do not allow omap_hwmod_register to be used outside the core hwmod code. An omap_hwmod should be registered only at init time. Remove the omap_hwmod_unregister that is not used today since the hwmod list will be built once at init time and never be modified at runtime. Signed-off-by: Benoit Cousson Signed-off-by: Paul Walmsley Cc: Kevin Hilman --- arch/arm/plat-omap/include/plat/omap_hwmod.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 62bdb23c95c9..ab99b8cca6ad 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -515,8 +515,6 @@ struct omap_hwmod { }; int omap_hwmod_init(struct omap_hwmod **ohs); -int omap_hwmod_register(struct omap_hwmod *oh); -int omap_hwmod_unregister(struct omap_hwmod *oh); struct omap_hwmod *omap_hwmod_lookup(const char *name); int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data), void *data); -- cgit v1.2.3 From 86009eb326afde34ffdc5648cd344aa86b8d58d4 Mon Sep 17 00:00:00 2001 From: Benoit Cousson Date: Tue, 21 Dec 2010 21:31:28 -0700 Subject: OMAP2+: hwmod: Add wakeup support for new OMAP4 IPs The new OMAP4 IPs introduced a new idle mode named smart-idle with wakeup. This new idlemode replaces the enawakeup for the new IPs but seems to coexist as well for some legacy IPs (UART, GPIO, MCSPI...) Add the new SIDLE_SMART_WKUP flag to mark the IPs that support this capability. The omap_hwmod_44xx_data.c will have to be updated to add this new flag. Enable this new mode when applicable in _enable_wakeup, _enable_sysc and _idle_sysc. Signed-off-by: Benoit Cousson Tested-by: Sebastien Guiriec Signed-off-by: Paul Walmsley Cc: Kevin Hilman Cc: Rajendra Nayak --- arch/arm/plat-omap/include/plat/omap_hwmod.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index ab99b8cca6ad..619877c6b3ab 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -76,6 +76,8 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2; #define HWMOD_IDLEMODE_FORCE (1 << 0) #define HWMOD_IDLEMODE_NO (1 << 1) #define HWMOD_IDLEMODE_SMART (1 << 2) +/* Slave idle mode flag only */ +#define HWMOD_IDLEMODE_SMART_WKUP (1 << 3) /** * struct omap_hwmod_irq_info - MPU IRQs used by the hwmod @@ -227,11 +229,12 @@ struct omap_hwmod_ocp_if { /* Macros for use in struct omap_hwmod_sysconfig */ /* Flags for use in omap_hwmod_sysconfig.idlemodes */ -#define MASTER_STANDBY_SHIFT 2 +#define MASTER_STANDBY_SHIFT 4 #define SLAVE_IDLE_SHIFT 0 #define SIDLE_FORCE (HWMOD_IDLEMODE_FORCE << SLAVE_IDLE_SHIFT) #define SIDLE_NO (HWMOD_IDLEMODE_NO << SLAVE_IDLE_SHIFT) #define SIDLE_SMART (HWMOD_IDLEMODE_SMART << SLAVE_IDLE_SHIFT) +#define SIDLE_SMART_WKUP (HWMOD_IDLEMODE_SMART_WKUP << SLAVE_IDLE_SHIFT) #define MSTANDBY_FORCE (HWMOD_IDLEMODE_FORCE << MASTER_STANDBY_SHIFT) #define MSTANDBY_NO (HWMOD_IDLEMODE_NO << MASTER_STANDBY_SHIFT) #define MSTANDBY_SMART (HWMOD_IDLEMODE_SMART << MASTER_STANDBY_SHIFT) -- cgit v1.2.3 From a36795c1278112af2a78f93c99b7586cb7e2a0a2 Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Tue, 21 Dec 2010 21:31:43 -0700 Subject: OMAP: clock: fix configuration of J-Type DPLLs to work for OMAP3 and OMAP4 J-Type DPLLs have additional configuration parameters that need to be programmed when setting the multipler and divider for the DPLL. These parameters being the sigma delta divider (SD_DIV) for the DPLL and the digital controlled oscillator (DCO) to be used by the DPLL. The current code is implemented specifically to configure the OMAP3630 PER J-Type DPLL. The OMAP4430 USB DPLL is also a J-Type DPLL and so this code needs to be updated to work for both OMAP3 and OMAP4 devices and any other future devices that have J-TYPE DPLLs. For the OMAP3630 PER DPLL both the SD_DIV and DCO paramenters are used but for the OMAP4430 USB DPLL only the SD_DIV field is used. The current implementation will only program the SD_DIV and DCO fields if the DPLL has both and hence this does not work for OMAP4430. In order to make the code more generic add two new fields to the dpll_data structure for the SD_DIV field and DCO field bit-masks and only program these fields if the masks are defined for a specific DPLL. This simplifies the code and allows us to remove the flag DPLL_NO_DCO_SEL. Tested on OMAP36xx Zoom3 and OMAP4 Blaze. Signed-off-by: Jon Hunter [paul@pwsan.com: removed explicit inlining and added '_' prefix on lookup_*() functions; added testing info to commit message; added 35xx comments back in] Signed-off-by: Paul Walmsley --- arch/arm/plat-omap/include/plat/clock.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h index 6e223158268b..8eb0adab19ea 100644 --- a/arch/arm/plat-omap/include/plat/clock.h +++ b/arch/arm/plat-omap/include/plat/clock.h @@ -124,8 +124,7 @@ struct clksel { * * Possible values for @flags: * DPLL_J_TYPE: "J-type DPLL" (only some 36xx, 4xxx DPLLs) - * NO_DCO_SEL: don't program DCO (only for some J-type DPLLs) - + * * @freqsel_mask is only used on the OMAP34xx family and AM35xx. * * XXX Some DPLLs have multiple bypass inputs, so it's not technically @@ -161,6 +160,8 @@ struct dpll_data { u32 autoidle_mask; u32 freqsel_mask; u32 idlest_mask; + u32 dco_mask; + u32 sddiv_mask; u8 auto_recal_bit; u8 recal_en_bit; u8 recal_st_bit; -- cgit v1.2.3 From c80705aa7074045e7431ed2ebeb0f7d5773615ab Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 21 Dec 2010 21:31:55 -0700 Subject: OMAP: PM: implement context loss count APIs Implement OMAP PM layer omap_pm_get_dev_context_loss_count() API by creating similar APIs at the omap_device and omap_hwmod levels. The omap_hwmod level call is the layer with access to the powerdomain core, so it is the place where the powerdomain is queried to get the context loss count. The new APIs return an unsigned value that can wrap as the context-loss count grows. However, the wrapping is not important as the role of this function is to determine context loss by checking for any difference in subsequent calls to this function. Note that these APIs at each level can return zero when no context loss is detected, or on errors. This is to avoid returning error codes which could potentially be mistaken for large context loss counters. NOTE: only works for devices which have been converted to use omap_device/omap_hwmod. Longer term, we could possibly remove this API from the OMAP PM layer, and instead directly use the omap_device level API. Signed-off-by: Kevin Hilman Signed-off-by: Paul Walmsley --- arch/arm/plat-omap/include/plat/omap-pm.h | 4 ++-- arch/arm/plat-omap/include/plat/omap_device.h | 1 + arch/arm/plat-omap/include/plat/omap_hwmod.h | 1 + arch/arm/plat-omap/omap-pm-noop.c | 23 +++++++++++----------- arch/arm/plat-omap/omap_device.c | 28 +++++++++++++++++++++++++++ 5 files changed, 43 insertions(+), 14 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h index 47d61107ccda..c07bb44e9e5a 100644 --- a/arch/arm/plat-omap/include/plat/omap-pm.h +++ b/arch/arm/plat-omap/include/plat/omap-pm.h @@ -350,9 +350,9 @@ unsigned long omap_pm_cpu_get_freq(void); * driver must restore device context. If the number of context losses * exceeds the maximum positive integer, the function will wrap to 0 and * continue counting. Returns the number of context losses for this device, - * or -EINVAL upon error. + * or zero upon error. */ -int omap_pm_get_dev_context_loss_count(struct device *dev); +u32 omap_pm_get_dev_context_loss_count(struct device *dev); #endif diff --git a/arch/arm/plat-omap/include/plat/omap_device.h b/arch/arm/plat-omap/include/plat/omap_device.h index 28e2d1a78433..e4c349ff9fd8 100644 --- a/arch/arm/plat-omap/include/plat/omap_device.h +++ b/arch/arm/plat-omap/include/plat/omap_device.h @@ -107,6 +107,7 @@ void __iomem *omap_device_get_rt_va(struct omap_device *od); int omap_device_align_pm_lat(struct platform_device *pdev, u32 new_wakeup_lat_limit); struct powerdomain *omap_device_get_pwrdm(struct omap_device *od); +u32 omap_device_get_context_loss_count(struct platform_device *pdev); /* Other */ diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 619877c6b3ab..2825b456da0e 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -569,6 +569,7 @@ int omap_hwmod_for_each_by_class(const char *classname, void *user); int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state); +u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh); /* * Chip variant-specific hwmod init routines - XXX should be converted diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c index 19cb9f5a9f04..af58daddcf50 100644 --- a/arch/arm/plat-omap/omap-pm-noop.c +++ b/arch/arm/plat-omap/omap-pm-noop.c @@ -20,9 +20,11 @@ #include #include #include +#include /* Interface documentation is in mach/omap-pm.h */ #include +#include /* * Device-driver-originated constraints (via board-*.c files) @@ -282,22 +284,19 @@ unsigned long omap_pm_cpu_get_freq(void) * Device context loss tracking */ -int omap_pm_get_dev_context_loss_count(struct device *dev) +u32 omap_pm_get_dev_context_loss_count(struct device *dev) { - if (!dev) { - WARN_ON(1); - return -EINVAL; - }; + struct platform_device *pdev = to_platform_device(dev); + u32 count; - pr_debug("OMAP PM: returning context loss count for dev %s\n", - dev_name(dev)); + if (WARN_ON(!dev)) + return 0; - /* - * Map the device to the powerdomain. Return the powerdomain - * off counter. - */ + count = omap_device_get_context_loss_count(pdev); + pr_debug("OMAP PM: context loss count for dev %s = %d\n", + dev_name(dev), count); - return 0; + return count; } diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c index abe933cd8f09..57adb270767b 100644 --- a/arch/arm/plat-omap/omap_device.c +++ b/arch/arm/plat-omap/omap_device.c @@ -279,6 +279,34 @@ static void _add_optional_clock_alias(struct omap_device *od, /* Public functions for use by core code */ +/** + * omap_device_get_context_loss_count - get lost context count + * @od: struct omap_device * + * + * Using the primary hwmod, query the context loss count for this + * device. + * + * Callers should consider context for this device lost any time this + * function returns a value different than the value the caller got + * the last time it called this function. + * + * If any hwmods exist for the omap_device assoiated with @pdev, + * return the context loss counter for that hwmod, otherwise return + * zero. + */ +u32 omap_device_get_context_loss_count(struct platform_device *pdev) +{ + struct omap_device *od; + u32 ret = 0; + + od = _find_by_pdev(pdev); + + if (od->hwmods_cnt) + ret = omap_hwmod_get_context_loss_count(od->hwmods[0]); + + return ret; +} + /** * omap_device_count_resources - count number of struct resource entries needed * @od: struct omap_device * -- cgit v1.2.3 From 6081dc348f122cdb76093b2fc6cf5742c968cb69 Mon Sep 17 00:00:00 2001 From: Kevin Hilman Date: Tue, 21 Dec 2010 21:31:55 -0700 Subject: OMAP: PM noop: implement context loss count for non-omap_devices For devices which have not (yet) been converted to use omap_device, implement the context loss counter using the "brutal method" as originally proposed by Paul Walmsley[1]. The dummy context loss counter is incremented every time it is checked, but only when off-mode is enabled. When off-mode is disabled, the dummy counter stops incrementing. Tested on 36xx/Zoom3 using MMC driver, which is currently the only in-tree user of this API. This patch should be reverted after all devices are converted to using omap_device. [1] http://marc.info/?l=linux-omap&m=129176260000626&w=2 Signed-off-by: Kevin Hilman [paul@pwsan.com: fixed compile warning; fixed to compile on OMAP1] Signed-off-by: Paul Walmsley --- arch/arm/plat-omap/include/plat/omap-pm.h | 2 ++ arch/arm/plat-omap/omap-pm-noop.c | 46 ++++++++++++++++++++++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h index c07bb44e9e5a..c0a752053039 100644 --- a/arch/arm/plat-omap/include/plat/omap-pm.h +++ b/arch/arm/plat-omap/include/plat/omap-pm.h @@ -354,5 +354,7 @@ unsigned long omap_pm_cpu_get_freq(void); */ u32 omap_pm_get_dev_context_loss_count(struct device *dev); +void omap_pm_enable_off_mode(void); +void omap_pm_disable_off_mode(void); #endif diff --git a/arch/arm/plat-omap/omap-pm-noop.c b/arch/arm/plat-omap/omap-pm-noop.c index af58daddcf50..b0471bb2d47d 100644 --- a/arch/arm/plat-omap/omap-pm-noop.c +++ b/arch/arm/plat-omap/omap-pm-noop.c @@ -26,6 +26,9 @@ #include #include +static bool off_mode_enabled; +static u32 dummy_context_loss_counter; + /* * Device-driver-originated constraints (via board-*.c files) */ @@ -280,10 +283,34 @@ unsigned long omap_pm_cpu_get_freq(void) return 0; } +/** + * omap_pm_enable_off_mode - notify OMAP PM that off-mode is enabled + * + * Intended for use only by OMAP PM core code to notify this layer + * that off mode has been enabled. + */ +void omap_pm_enable_off_mode(void) +{ + off_mode_enabled = true; +} + +/** + * omap_pm_disable_off_mode - notify OMAP PM that off-mode is disabled + * + * Intended for use only by OMAP PM core code to notify this layer + * that off mode has been disabled. + */ +void omap_pm_disable_off_mode(void) +{ + off_mode_enabled = false; +} + /* * Device context loss tracking */ +#ifdef CONFIG_ARCH_OMAP2PLUS + u32 omap_pm_get_dev_context_loss_count(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); @@ -292,13 +319,30 @@ u32 omap_pm_get_dev_context_loss_count(struct device *dev) if (WARN_ON(!dev)) return 0; - count = omap_device_get_context_loss_count(pdev); + if (dev->parent == &omap_device_parent) { + count = omap_device_get_context_loss_count(pdev); + } else { + WARN_ONCE(off_mode_enabled, "omap_pm: using dummy context loss counter; device %s should be converted to omap_device", + dev_name(dev)); + if (off_mode_enabled) + dummy_context_loss_counter++; + count = dummy_context_loss_counter; + } + pr_debug("OMAP PM: context loss count for dev %s = %d\n", dev_name(dev), count); return count; } +#else + +u32 omap_pm_get_dev_context_loss_count(struct device *dev) +{ + return dummy_context_loss_counter; +} + +#endif /* Should be called before clk framework init */ int __init omap_pm_if_early_init(void) -- cgit v1.2.3 From da1f026b532ce944d74461497dc6d8c16456466e Mon Sep 17 00:00:00 2001 From: Janusz Krzysztofik Date: Mon, 20 Dec 2010 21:09:22 +0000 Subject: Keyboard: omap-keypad: use matrix_keypad.h Most keypad drivers make use of the defined macros, structures and inline functions. Convert omap-keypad driver to use those as well, as suggested by a compile time warning, hardcoded into the OMAP . Created against linux-2.6.37-rc5. Tested on Amstrad Delta. Compile tested with omap1_defconfig and omap2plus_defconfig shrinked to board-h4. Signed-off-by: Janusz Krzysztofik Reviewed-by: Aaro Koskinen Acked-by: Dmitry Torokhov Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/keypad.h | 35 ++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 15 deletions(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/keypad.h b/arch/arm/plat-omap/include/plat/keypad.h index 3ae52ccc793c..793ce9d53294 100644 --- a/arch/arm/plat-omap/include/plat/keypad.h +++ b/arch/arm/plat-omap/include/plat/keypad.h @@ -10,16 +10,18 @@ #ifndef ASMARM_ARCH_KEYPAD_H #define ASMARM_ARCH_KEYPAD_H -#warning: Please update the board to use matrix_keypad.h instead +#ifndef CONFIG_ARCH_OMAP1 +#warning Please update the board to use matrix-keypad driver +#endif +#include struct omap_kp_platform_data { int rows; int cols; - int *keymap; - unsigned int keymapsize; - unsigned int rep:1; + const struct matrix_keymap_data *keymap_data; + bool rep; unsigned long delay; - unsigned int dbounce:1; + bool dbounce; /* specific to OMAP242x*/ unsigned int *row_gpios; unsigned int *col_gpios; @@ -28,18 +30,21 @@ struct omap_kp_platform_data { /* Group (0..3) -- when multiple keys are pressed, only the * keys pressed in the same group are considered as pressed. This is * in order to workaround certain crappy HW designs that produce ghost - * keypresses. */ -#define GROUP_0 (0 << 16) -#define GROUP_1 (1 << 16) -#define GROUP_2 (2 << 16) -#define GROUP_3 (3 << 16) + * keypresses. Two free bits, not used by neither row/col nor keynum, + * must be available for use as group bits. The below GROUP_SHIFT + * macro definition is based on some prior knowledge of the + * matrix_keypad defined KEY() macro internals. + */ +#define GROUP_SHIFT 14 +#define GROUP_0 (0 << GROUP_SHIFT) +#define GROUP_1 (1 << GROUP_SHIFT) +#define GROUP_2 (2 << GROUP_SHIFT) +#define GROUP_3 (3 << GROUP_SHIFT) #define GROUP_MASK GROUP_3 +#if KEY_MAX & GROUP_MASK +#error Group bits in conflict with keynum bits +#endif -#define KEY_PERSISTENT 0x00800000 -#define KEYNUM_MASK 0x00EFFFFF -#define KEY(col, row, val) (((col) << 28) | ((row) << 24) | (val)) -#define PERSISTENT_KEY(col, row) (((col) << 28) | ((row) << 24) | \ - KEY_PERSISTENT) #endif -- cgit v1.2.3 From 2f34ce81b8c05c900e45bd88595cc154f7bb5957 Mon Sep 17 00:00:00 2001 From: Thara Gopinath Date: Sat, 29 May 2010 22:02:21 +0530 Subject: OMAP3: PM: Adding voltage driver support. This patch adds voltage driver support for OMAP3. The driver allows configuring the voltage controller and voltage processors during init and exports APIs to enable/disable voltage processors, scale voltage and reset voltage. The driver maintains the global voltage table on a per VDD basis which contains the various voltages supported by the VDD along with per voltage dependent data like smartreflex efuse offset, errminlimit and voltage processor errorgain. The driver also allows the voltage parameters dependent on the PMIC to be passed from the PMIC file through an API. The driver allows scaling of VDD voltages either through "vc bypass method" or through "vp forceupdate method" the choice being configurable through the board file. This patch contains code originally in linux omap pm branch smartreflex driver. Major contributors to this driver are Lesly A M, Rajendra Nayak, Kalle Jokiniemi, Paul Walmsley, Nishant Menon, Kevin Hilman. The separation of PMIC parameters into a separate structure which can be populated from the PMIC file is based on the work of Lun Chang from Motorola in an internal tree. Signed-off-by: Thara Gopinath [khilman: fixed link error for OMAP2-only defconfig] Signed-off-by: Kevin Hilman --- arch/arm/plat-omap/include/plat/voltage.h | 134 ++++++++++++++++++++++++++++++ 1 file changed, 134 insertions(+) create mode 100644 arch/arm/plat-omap/include/plat/voltage.h (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h new file mode 100644 index 000000000000..2f4f59abd19f --- /dev/null +++ b/arch/arm/plat-omap/include/plat/voltage.h @@ -0,0 +1,134 @@ +/* + * OMAP Voltage Management Routines + * + * Author: Thara Gopinath + * + * Copyright (C) 2009 Texas Instruments, Inc. + * Thara Gopinath + * + * 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. + */ + +#ifndef __ARCH_ARM_MACH_OMAP2_VOLTAGE_H +#define __ARCH_ARM_MACH_OMAP2_VOLTAGE_H + +#define VOLTSCALE_VPFORCEUPDATE 1 +#define VOLTSCALE_VCBYPASS 2 + +/* + * OMAP3 GENERIC setup times. Revisit to see if these needs to be + * passed from board or PMIC file + */ +#define OMAP3_CLKSETUP 0xff +#define OMAP3_VOLTOFFSET 0xff +#define OMAP3_VOLTSETUP2 0xff + +/* Voltage value defines */ +#define OMAP3430_VDD_MPU_OPP1_UV 975000 +#define OMAP3430_VDD_MPU_OPP2_UV 1075000 +#define OMAP3430_VDD_MPU_OPP3_UV 1200000 +#define OMAP3430_VDD_MPU_OPP4_UV 1270000 +#define OMAP3430_VDD_MPU_OPP5_UV 1350000 + +#define OMAP3430_VDD_CORE_OPP1_UV 975000 +#define OMAP3430_VDD_CORE_OPP2_UV 1050000 +#define OMAP3430_VDD_CORE_OPP3_UV 1150000 + +#define OMAP3630_VDD_MPU_OPP50_UV 1012500 +#define OMAP3630_VDD_MPU_OPP100_UV 1200000 +#define OMAP3630_VDD_MPU_OPP120_UV 1325000 +#define OMAP3630_VDD_MPU_OPP1G_UV 1375000 + +#define OMAP3630_VDD_CORE_OPP50_UV 1000000 +#define OMAP3630_VDD_CORE_OPP100_UV 1200000 + +/** + * struct voltagedomain - omap voltage domain global structure. + * @name: Name of the voltage domain which can be used as a unique + * identifier. + */ +struct voltagedomain { + char *name; +}; + +/* API to get the voltagedomain pointer */ +struct voltagedomain *omap_voltage_domain_lookup(char *name); + +/** + * struct omap_volt_data - Omap voltage specific data. + * @voltage_nominal: The possible voltage value in uV + * @sr_efuse_offs: The offset of the efuse register(from system + * control module base address) from where to read + * the n-target value for the smartreflex module. + * @sr_errminlimit: Error min limit value for smartreflex. This value + * differs at differnet opp and thus is linked + * with voltage. + * @vp_errorgain: Error gain value for the voltage processor. This + * field also differs according to the voltage/opp. + */ +struct omap_volt_data { + u32 volt_nominal; + u32 sr_efuse_offs; + u8 sr_errminlimit; + u8 vp_errgain; +}; + +/** + * struct omap_volt_pmic_info - PMIC specific data required by voltage driver. + * @slew_rate: PMIC slew rate (in uv/us) + * @step_size: PMIC voltage step size (in uv) + * @vsel_to_uv: PMIC API to convert vsel value to actual voltage in uV. + * @uv_to_vsel: PMIC API to convert voltage in uV to vsel value. + */ +struct omap_volt_pmic_info { + int slew_rate; + int step_size; + u32 on_volt; + u32 onlp_volt; + u32 ret_volt; + u32 off_volt; + u16 volt_setup_time; + u8 vp_erroroffset; + u8 vp_vstepmin; + u8 vp_vstepmax; + u8 vp_vddmin; + u8 vp_vddmax; + u8 vp_timeout_us; + u8 i2c_slave_addr; + u8 pmic_reg; + unsigned long (*vsel_to_uv) (const u8 vsel); + u8 (*uv_to_vsel) (unsigned long uV); +}; + +unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm); +void omap_vp_enable(struct voltagedomain *voltdm); +void omap_vp_disable(struct voltagedomain *voltdm); +int omap_voltage_scale_vdd(struct voltagedomain *voltdm, + unsigned long target_volt); +void omap_voltage_reset(struct voltagedomain *voltdm); +void omap_voltage_get_volttable(struct voltagedomain *voltdm, + struct omap_volt_data **volt_data); +struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm, + unsigned long volt); +unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm); +struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm); +#ifdef CONFIG_PM +int omap_voltage_register_pmic(struct voltagedomain *voltdm, + struct omap_volt_pmic_info *pmic_info); +void omap_change_voltscale_method(struct voltagedomain *voltdm, + int voltscale_method); +int omap_voltage_late_init(void); +#else +static inline int omap_voltage_register_pmic(struct voltagedomain *voltdm, + struct omap_volt_pmic_info *pmic_info) {} +static inline void omap_change_voltscale_method(struct voltagedomain *voltdm, + int voltscale_method) {} +static inline int omap_voltage_late_init(void) +{ + return -EINVAL; +} +#endif + +#endif -- cgit v1.2.3 From 3b92408c7dfeb918fdd2f9fadc73177a59ad621c Mon Sep 17 00:00:00 2001 From: Thara Gopinath Date: Wed, 18 Aug 2010 16:21:58 +0530 Subject: OMAP: Introduce voltage domain information in the hwmod structures This patch extends the device hwmod structure to contain info about the voltage domain to which the device belongs to. This is needed to support a device based DVFS where the device knows which voltage domain it belongs to. Signed-off-by: Thara Gopinath Signed-off-by: Kevin Hilman --- arch/arm/plat-omap/include/plat/omap_hwmod.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index 2825b456da0e..b219a88cac2c 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -34,6 +34,7 @@ #include #include #include +#include struct omap_device; @@ -452,6 +453,8 @@ struct omap_hwmod_class { * @main_clk: main clock: OMAP clock name * @_clk: pointer to the main struct clk (filled in at runtime) * @opt_clks: other device clocks that drivers can request (0..*) + * @vdd_name: voltage domain name + * @voltdm: pointer to voltage domain (filled in at runtime) * @masters: ptr to array of OCP ifs that this hwmod can initiate on * @slaves: ptr to array of OCP ifs that this hwmod can respond on * @dev_attr: arbitrary device attributes that can be passed to the driver @@ -494,6 +497,8 @@ struct omap_hwmod { const char *main_clk; struct clk *_clk; struct omap_hwmod_opt_clk *opt_clks; + char *vdd_name; + struct voltagedomain *voltdm; struct omap_hwmod_ocp_if **masters; /* connect to *_IA */ struct omap_hwmod_ocp_if **slaves; /* connect to *_TA */ void *dev_attr; -- cgit v1.2.3 From 984aa6dbf4ca5be806fee217311c9cc68e8f2e88 Mon Sep 17 00:00:00 2001 From: Thara Gopinath Date: Sat, 29 May 2010 22:02:22 +0530 Subject: OMAP3: PM: Adding smartreflex driver support. SmartReflex modules do adaptive voltage control for real-time voltage adjustments. With Smartreflex the power supply voltage can be adapted to the silicon performance(manufacturing process, temperature induced performance, age induced performance etc). There are differnet classes of smartreflex implementation. Class-0: Manufacturing Test Calibration Class-1: Boot-Time Software Calibration Class-2: Continuous Software Calibration Class-3: Continuous Hardware Calibration Class-4: Fully Integrated Power Management OMAP3 has two smartreflex modules one associated with VDD MPU and the other associated with VDD CORE. This patch adds support for smartreflex driver. The driver is designed for Class-1 , Class-2 and Class-3 support and is a platform driver. Smartreflex driver can be enabled through a Kconfig option "SmartReflex support" under "System type"->"TI OMAP implementations" menu. Smartreflex autocompensation feature can be enabled runtime through a debug fs option. To enable smartreflex autocompensation feature echo 1 > /debug/voltage/vdd_/smartreflex/autocomp To disable smartreflex autocompensation feature echo 0 > /debug/voltage/vdd_/smartreflex/autocomp where X can be mpu, core , iva etc. This patch contains code originally in linux omap pm branch. Major contributors to this driver are Lesly A M, Rajendra Nayak, Kalle Jokiniemi, Paul Walmsley, Nishant Menon, Kevin Hilman. Signed-off-by: Thara Gopinath Signed-off-by: Kevin Hilman --- arch/arm/plat-omap/Kconfig | 22 +++ arch/arm/plat-omap/include/plat/smartreflex.h | 245 ++++++++++++++++++++++++++ 2 files changed, 267 insertions(+) create mode 100644 arch/arm/plat-omap/include/plat/smartreflex.h (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 5e63e5069e0d..f1673fb96fe9 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -35,6 +35,28 @@ config OMAP_DEBUG_LEDS depends on OMAP_DEBUG_DEVICES default y if LEDS_CLASS +config OMAP_SMARTREFLEX + bool "SmartReflex support" + depends on ARCH_OMAP3 && PM + help + Say Y if you want to enable SmartReflex. + + SmartReflex can perform continuous dynamic voltage + scaling around the nominal operating point voltage + according to silicon characteristics and operating + conditions. Enabling SmartReflex reduces power + consumption. + + Please note, that by default SmartReflex is only + initialized. To enable the automatic voltage + compensation for vdd mpu and vdd core from user space, + user must write 1 to + /debug/voltage/vdd_/smartreflex/autocomp, + where X is mpu or core for OMAP3. + Optionallly autocompensation can be enabled in the kernel + by default during system init via the enable_on_init flag + which an be passed as platform data to the smartreflex driver. + config OMAP_RESET_CLOCKS bool "Reset unused clocks during boot" depends on ARCH_OMAP diff --git a/arch/arm/plat-omap/include/plat/smartreflex.h b/arch/arm/plat-omap/include/plat/smartreflex.h new file mode 100644 index 000000000000..6568c885f37a --- /dev/null +++ b/arch/arm/plat-omap/include/plat/smartreflex.h @@ -0,0 +1,245 @@ +/* + * OMAP Smartreflex Defines and Routines + * + * Author: Thara Gopinath + * + * Copyright (C) 2010 Texas Instruments, Inc. + * Thara Gopinath + * + * Copyright (C) 2008 Nokia Corporation + * Kalle Jokiniemi + * + * Copyright (C) 2007 Texas Instruments, Inc. + * Lesly A M + * + * 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. + */ + +#ifndef __ASM_ARM_OMAP_SMARTREFLEX_H +#define __ASM_ARM_OMAP_SMARTREFLEX_H + +#include +#include + +/* + * Different Smartreflex IPs version. The v1 is the 65nm version used in + * OMAP3430. The v2 is the update for the 45nm version of the IP + * used in OMAP3630 and OMAP4430 + */ +#define SR_TYPE_V1 1 +#define SR_TYPE_V2 2 + +/* SMART REFLEX REG ADDRESS OFFSET */ +#define SRCONFIG 0x00 +#define SRSTATUS 0x04 +#define SENVAL 0x08 +#define SENMIN 0x0C +#define SENMAX 0x10 +#define SENAVG 0x14 +#define AVGWEIGHT 0x18 +#define NVALUERECIPROCAL 0x1c +#define SENERROR_V1 0x20 +#define ERRCONFIG_V1 0x24 +#define IRQ_EOI 0x20 +#define IRQSTATUS_RAW 0x24 +#define IRQSTATUS 0x28 +#define IRQENABLE_SET 0x2C +#define IRQENABLE_CLR 0x30 +#define SENERROR_V2 0x34 +#define ERRCONFIG_V2 0x38 + +/* Bit/Shift Positions */ + +/* SRCONFIG */ +#define SRCONFIG_ACCUMDATA_SHIFT 22 +#define SRCONFIG_SRCLKLENGTH_SHIFT 12 +#define SRCONFIG_SENNENABLE_V1_SHIFT 5 +#define SRCONFIG_SENPENABLE_V1_SHIFT 3 +#define SRCONFIG_SENNENABLE_V2_SHIFT 1 +#define SRCONFIG_SENPENABLE_V2_SHIFT 0 +#define SRCONFIG_CLKCTRL_SHIFT 0 + +#define SRCONFIG_ACCUMDATA_MASK (0x3ff << 22) + +#define SRCONFIG_SRENABLE BIT(11) +#define SRCONFIG_SENENABLE BIT(10) +#define SRCONFIG_ERRGEN_EN BIT(9) +#define SRCONFIG_MINMAXAVG_EN BIT(8) +#define SRCONFIG_DELAYCTRL BIT(2) + +/* AVGWEIGHT */ +#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT 2 +#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT 0 + +/* NVALUERECIPROCAL */ +#define NVALUERECIPROCAL_SENPGAIN_SHIFT 20 +#define NVALUERECIPROCAL_SENNGAIN_SHIFT 16 +#define NVALUERECIPROCAL_RNSENP_SHIFT 8 +#define NVALUERECIPROCAL_RNSENN_SHIFT 0 + +/* ERRCONFIG */ +#define ERRCONFIG_ERRWEIGHT_SHIFT 16 +#define ERRCONFIG_ERRMAXLIMIT_SHIFT 8 +#define ERRCONFIG_ERRMINLIMIT_SHIFT 0 + +#define SR_ERRWEIGHT_MASK (0x07 << 16) +#define SR_ERRMAXLIMIT_MASK (0xff << 8) +#define SR_ERRMINLIMIT_MASK (0xff << 0) + +#define ERRCONFIG_VPBOUNDINTEN_V1 BIT(31) +#define ERRCONFIG_VPBOUNDINTST_V1 BIT(30) +#define ERRCONFIG_MCUACCUMINTEN BIT(29) +#define ERRCONFIG_MCUACCUMINTST BIT(28) +#define ERRCONFIG_MCUVALIDINTEN BIT(27) +#define ERRCONFIG_MCUVALIDINTST BIT(26) +#define ERRCONFIG_MCUBOUNDINTEN BIT(25) +#define ERRCONFIG_MCUBOUNDINTST BIT(24) +#define ERRCONFIG_MCUDISACKINTEN BIT(23) +#define ERRCONFIG_VPBOUNDINTST_V2 BIT(23) +#define ERRCONFIG_MCUDISACKINTST BIT(22) +#define ERRCONFIG_VPBOUNDINTEN_V2 BIT(22) + +#define ERRCONFIG_STATUS_V1_MASK (ERRCONFIG_VPBOUNDINTST_V1 | \ + ERRCONFIG_MCUACCUMINTST | \ + ERRCONFIG_MCUVALIDINTST | \ + ERRCONFIG_MCUBOUNDINTST | \ + ERRCONFIG_MCUDISACKINTST) +/* IRQSTATUS */ +#define IRQSTATUS_MCUACCUMINT BIT(3) +#define IRQSTATUS_MCVALIDINT BIT(2) +#define IRQSTATUS_MCBOUNDSINT BIT(1) +#define IRQSTATUS_MCUDISABLEACKINT BIT(0) + +/* IRQENABLE_SET and IRQENABLE_CLEAR */ +#define IRQENABLE_MCUACCUMINT BIT(3) +#define IRQENABLE_MCUVALIDINT BIT(2) +#define IRQENABLE_MCUBOUNDSINT BIT(1) +#define IRQENABLE_MCUDISABLEACKINT BIT(0) + +/* Common Bit values */ + +#define SRCLKLENGTH_12MHZ_SYSCLK 0x3c +#define SRCLKLENGTH_13MHZ_SYSCLK 0x41 +#define SRCLKLENGTH_19MHZ_SYSCLK 0x60 +#define SRCLKLENGTH_26MHZ_SYSCLK 0x82 +#define SRCLKLENGTH_38MHZ_SYSCLK 0xC0 + +/* + * 3430 specific values. Maybe these should be passed from board file or + * pmic structures. + */ +#define OMAP3430_SR_ACCUMDATA 0x1f4 + +#define OMAP3430_SR1_SENPAVGWEIGHT 0x03 +#define OMAP3430_SR1_SENNAVGWEIGHT 0x03 + +#define OMAP3430_SR2_SENPAVGWEIGHT 0x01 +#define OMAP3430_SR2_SENNAVGWEIGHT 0x01 + +#define OMAP3430_SR_ERRWEIGHT 0x04 +#define OMAP3430_SR_ERRMAXLIMIT 0x02 + +/** + * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass + * pmic specific info to smartreflex driver + * + * @sr_pmic_init: API to initialize smartreflex on the PMIC side. + */ +struct omap_sr_pmic_data { + void (*sr_pmic_init) (void); +}; + +#ifdef CONFIG_OMAP_SMARTREFLEX +/* + * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR. + * The smartreflex class driver should pass the class type. + * Should be used to populate the class_type field of the + * omap_smartreflex_class_data structure. + */ +#define SR_CLASS1 0x1 +#define SR_CLASS2 0x2 +#define SR_CLASS3 0x3 + +/** + * struct omap_sr_class_data - Smartreflex class driver info + * + * @enable: API to enable a particular class smaartreflex. + * @disable: API to disable a particular class smartreflex. + * @configure: API to configure a particular class smartreflex. + * @notify: API to notify the class driver about an event in SR. + * Not needed for class3. + * @notify_flags: specify the events to be notified to the class driver + * @class_type: specify which smartreflex class. + * Can be used by the SR driver to take any class + * based decisions. + */ +struct omap_sr_class_data { + int (*enable)(struct voltagedomain *voltdm); + int (*disable)(struct voltagedomain *voltdm, int is_volt_reset); + int (*configure)(struct voltagedomain *voltdm); + int (*notify)(struct voltagedomain *voltdm, u32 status); + u8 notify_flags; + u8 class_type; +}; + +/** + * struct omap_sr_nvalue_table - Smartreflex n-target value info + * + * @efuse_offs: The offset of the efuse where n-target values are stored. + * @nvalue: The n-target value. + */ +struct omap_sr_nvalue_table { + u32 efuse_offs; + u32 nvalue; +}; + +/** + * struct omap_sr_data - Smartreflex platform data. + * + * @ip_type: Smartreflex IP type. + * @senp_mod: SENPENABLE value for the sr + * @senn_mod: SENNENABLE value for sr + * @nvalue_count: Number of distinct nvalues in the nvalue table + * @enable_on_init: whether this sr module needs to enabled at + * boot up or not. + * @nvalue_table: table containing the efuse offsets and nvalues + * corresponding to them. + * @voltdm: Pointer to the voltage domain associated with the SR + */ +struct omap_sr_data { + int ip_type; + u32 senp_mod; + u32 senn_mod; + int nvalue_count; + bool enable_on_init; + struct omap_sr_nvalue_table *nvalue_table; + struct voltagedomain *voltdm; +}; + +/* Smartreflex module enable/disable interface */ +void omap_sr_enable(struct voltagedomain *voltdm); +void omap_sr_disable(struct voltagedomain *voltdm); +void omap_sr_disable_reset_volt(struct voltagedomain *voltdm); + +/* API to register the pmic specific data with the smartreflex driver. */ +void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data); + +/* Smartreflex driver hooks to be called from Smartreflex class driver */ +int sr_enable(struct voltagedomain *voltdm, unsigned long volt); +void sr_disable(struct voltagedomain *voltdm); +int sr_configure_errgen(struct voltagedomain *voltdm); +int sr_configure_minmax(struct voltagedomain *voltdm); + +/* API to register the smartreflex class driver with the smartreflex driver */ +int sr_register_class(struct omap_sr_class_data *class_data); +#else +static inline void omap_sr_enable(struct voltagedomain *voltdm) {} +static inline void omap_sr_disable(struct voltagedomain *voltdm) {} +static inline void omap_sr_disable_reset_volt( + struct voltagedomain *voltdm) {} +static inline void omap_sr_register_pmic( + struct omap_sr_pmic_data *pmic_data) {} +#endif +#endif -- cgit v1.2.3 From fa765823a3cbb9ce1b13ce2832109a50d899c471 Mon Sep 17 00:00:00 2001 From: Thara Gopinath Date: Sat, 29 May 2010 22:02:25 +0530 Subject: OMAP3: PM: Adding smartreflex class3 driver Smartreflex Class3 implementation continuously monitors silicon performance and instructs the Voltage Processors to increase or decrease the voltage. This patch adds smartreflex class 3 driver. This driver hooks up with the generic smartreflex driver smartreflex.c to abstract out class specific implementations out of the generic driver. Class3 driver is chosen as the default class driver for smartreflex. If any other class driver needs to be implemented, the init of that driver should be called from the board file. That way the new class driver will over-ride the Class3 driver. Signed-off-by: Thara Gopinath Signed-off-by: Kevin Hilman --- arch/arm/plat-omap/Kconfig | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index f1673fb96fe9..f4e05134aafa 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -57,6 +57,15 @@ config OMAP_SMARTREFLEX by default during system init via the enable_on_init flag which an be passed as platform data to the smartreflex driver. +config OMAP_SMARTREFLEX_CLASS3 + bool "Class 3 mode of Smartreflex Implementation" + depends on OMAP_SMARTREFLEX && TWL4030_CORE + help + Say Y to enable Class 3 implementation of Smartreflex + + Class 3 implementation of Smartreflex employs continuous hardware + voltage calibration. + config OMAP_RESET_CLOCKS bool "Reset unused clocks during boot" depends on ARCH_OMAP -- cgit v1.2.3 From bd38107b565a41d994aa22db0962ffcc34ebef02 Mon Sep 17 00:00:00 2001 From: Thara Gopinath Date: Fri, 10 Dec 2010 23:15:23 +0530 Subject: OMAP4: Adding voltage driver support OMAP4 has three scalable voltage domains vdd_mpu, vdd_iva and vdd_core. This patch adds the voltage tables and other configurable voltage processor and voltage controller settings to control these three scalable domains in OMAP4. Signed-off-by: Thara Gopinath Signed-off-by: Kevin Hilman --- arch/arm/plat-omap/include/plat/voltage.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/voltage.h b/arch/arm/plat-omap/include/plat/voltage.h index 2f4f59abd19f..0ff123399f3b 100644 --- a/arch/arm/plat-omap/include/plat/voltage.h +++ b/arch/arm/plat-omap/include/plat/voltage.h @@ -44,6 +44,18 @@ #define OMAP3630_VDD_CORE_OPP50_UV 1000000 #define OMAP3630_VDD_CORE_OPP100_UV 1200000 +#define OMAP4430_VDD_MPU_OPP50_UV 930000 +#define OMAP4430_VDD_MPU_OPP100_UV 1100000 +#define OMAP4430_VDD_MPU_OPPTURBO_UV 1260000 +#define OMAP4430_VDD_MPU_OPPNITRO_UV 1350000 + +#define OMAP4430_VDD_IVA_OPP50_UV 930000 +#define OMAP4430_VDD_IVA_OPP100_UV 1100000 +#define OMAP4430_VDD_IVA_OPPTURBO_UV 1260000 + +#define OMAP4430_VDD_CORE_OPP50_UV 930000 +#define OMAP4430_VDD_CORE_OPP100_UV 1100000 + /** * struct voltagedomain - omap voltage domain global structure. * @name: Name of the voltage domain which can be used as a unique -- cgit v1.2.3 From b35cecf978e33bf8f4be0f36ffe00fe10f381c4a Mon Sep 17 00:00:00 2001 From: Thara Gopinath Date: Wed, 18 Aug 2010 12:23:12 +0530 Subject: OMAP4: Smartreflex framework extensions This patch extends the smartreflex framework to support OMAP4. The changes are minor like compiling smartreflex Kconfig option for OMAP4 also, and a couple of OMAP4 checks in the smartreflex framework. The change in sr_device.c where new logic has to be introduced for reading the efuse registers is due to the fact that in OMAP4 the efuse registers are 24 bit aligned. A __raw_readl will fail for non-32 bit aligned address and hence the 8-bit read and shift. Signed-off-by: Thara Gopinath Signed-off-by: Kevin Hilman --- arch/arm/plat-omap/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index f4e05134aafa..11bf9f991509 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -37,7 +37,7 @@ config OMAP_DEBUG_LEDS config OMAP_SMARTREFLEX bool "SmartReflex support" - depends on ARCH_OMAP3 && PM + depends on (ARCH_OMAP3 || ARCH_OMAP4) && PM help Say Y if you want to enable SmartReflex. -- cgit v1.2.3 From 9796b323b5a1940f9ec62c3a6cf7e442bf540d53 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 22 Dec 2010 18:42:35 -0800 Subject: omap2+: Add support for hwmod specific muxing of devices This allows adding hwmod specific pads dynamically during the platform device init. Note that we don't currently have the hwmod specific signals listed in the hwmod data, but struct omap_hwmod_mux_info will make that possible if necessary. Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/omap_hwmod.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h index b219a88cac2c..6864a997f2ca 100644 --- a/arch/arm/plat-omap/include/plat/omap_hwmod.h +++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h @@ -80,6 +80,18 @@ extern struct omap_hwmod_sysc_fields omap_hwmod_sysc_type2; /* Slave idle mode flag only */ #define HWMOD_IDLEMODE_SMART_WKUP (1 << 3) +/** + * struct omap_hwmod_mux_info - hwmod specific mux configuration + * @pads: array of omap_device_pad entries + * @nr_pads: number of omap_device_pad entries + * + * Note that this is currently built during init as needed. + */ +struct omap_hwmod_mux_info { + int nr_pads; + struct omap_device_pad *pads; +}; + /** * struct omap_hwmod_irq_info - MPU IRQs used by the hwmod * @name: name of the IRQ channel (module local name) @@ -487,6 +499,7 @@ struct omap_hwmod { const char *name; struct omap_hwmod_class *class; struct omap_device *od; + struct omap_hwmod_mux_info *mux; struct omap_hwmod_irq_info *mpu_irqs; struct omap_hwmod_dma_info *sdma_reqs; struct omap_hwmod_rst_info *rst_lines; -- cgit v1.2.3 From 40e44399301b6dbd997408a184140b79b77f632d Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 22 Dec 2010 18:42:35 -0800 Subject: omap2+: Add struct omap_board_data and use it for platform level serial init This is needed to pass board specific data such as pads used to the platform level driver init code. Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/include/plat/serial.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/include/plat/serial.h b/arch/arm/plat-omap/include/plat/serial.h index 19145f5c32ba..cec5d56db2eb 100644 --- a/arch/arm/plat-omap/include/plat/serial.h +++ b/arch/arm/plat-omap/include/plat/serial.h @@ -93,9 +93,12 @@ }) #ifndef __ASSEMBLER__ + +struct omap_board_data; + extern void __init omap_serial_early_init(void); extern void omap_serial_init(void); -extern void omap_serial_init_port(int port); +extern void omap_serial_init_port(struct omap_board_data *bdata); extern int omap_uart_can_sleep(void); extern void omap_uart_check_wakeup(void); extern void omap_uart_prepare_suspend(void); -- cgit v1.2.3 From dc69d1af9e8d9cbbabff88bb35a6782187a22229 Mon Sep 17 00:00:00 2001 From: Ben Gamari Date: Fri, 24 Dec 2010 02:48:09 +0000 Subject: omap2: Make OMAP2PLUS select OMAP_DM_TIMER It appears that arch/arm/mach-omap2/timer-gp.o is needed by OMAP2PLUS. Since timer-gp.o has direct dependencies on omap_dm_timer_*, it seems correct for the architecture to depend upon OMAP_DM_TIMER, otherwise unsuspecting integrators will be faced with a whole bunch of linker errors at the end of their kernel build: arch/arm/mach-omap2/built-in.o: In function `omap2_gp_timer_set_mode': /home/bgamari/trees/linux-2.6/arch/arm/mach-omap2/timer-gp.c:84: undefined reference to `omap_dm_timer_stop' /home/bgamari/trees/linux-2.6/arch/arm/mach-omap2/timer-gp.c:88: undefined reference to `omap_dm_timer_get_fclk' /home/bgamari/trees/linux-2.6/arch/arm/mach-omap2/timer-gp.c:90: undefined reference to `omap_dm_timer_set_load_start' ... Signed-off-by: Ben Gamari Signed-off-by: Tony Lindgren --- arch/arm/plat-omap/Kconfig | 1 + 1 file changed, 1 insertion(+) (limited to 'arch/arm/plat-omap') diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig index 11bf9f991509..bc0c7aae3214 100644 --- a/arch/arm/plat-omap/Kconfig +++ b/arch/arm/plat-omap/Kconfig @@ -18,6 +18,7 @@ config ARCH_OMAP1 config ARCH_OMAP2PLUS bool "TI OMAP2/3/4" select COMMON_CLKDEV + select OMAP_DM_TIMER help "Systems based on OMAP2, OMAP3 or OMAP4" -- cgit v1.2.3