summaryrefslogtreecommitdiff
path: root/arch/arm/plat-omap
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/plat-omap')
-rw-r--r--arch/arm/plat-omap/Kconfig3
-rw-r--r--arch/arm/plat-omap/clock.c39
-rw-r--r--arch/arm/plat-omap/counter_32k.c123
-rw-r--r--arch/arm/plat-omap/dmtimer.c213
-rw-r--r--arch/arm/plat-omap/include/plat/clkdev_omap.h1
-rw-r--r--arch/arm/plat-omap/include/plat/clock.h4
-rw-r--r--arch/arm/plat-omap/include/plat/common.h6
-rw-r--r--arch/arm/plat-omap/include/plat/cpu.h35
-rw-r--r--arch/arm/plat-omap/include/plat/dmtimer.h251
-rw-r--r--arch/arm/plat-omap/include/plat/gpio.h20
-rw-r--r--arch/arm/plat-omap/include/plat/i2c.h6
-rw-r--r--arch/arm/plat-omap/include/plat/irqs.h18
-rw-r--r--arch/arm/plat-omap/include/plat/mcbsp.h74
-rw-r--r--arch/arm/plat-omap/include/plat/nand.h6
-rw-r--r--arch/arm/plat-omap/include/plat/omap-pm.h8
-rw-r--r--arch/arm/plat-omap/include/plat/omap4-keypad.h3
-rw-r--r--arch/arm/plat-omap/include/plat/omap_hwmod.h35
-rw-r--r--arch/arm/plat-omap/include/plat/uncompress.h1
-rw-r--r--arch/arm/plat-omap/iovmm.c6
-rw-r--r--arch/arm/plat-omap/mcbsp.c604
-rw-r--r--arch/arm/plat-omap/omap_device.c94
21 files changed, 1005 insertions, 545 deletions
diff --git a/arch/arm/plat-omap/Kconfig b/arch/arm/plat-omap/Kconfig
index 6e6735f04ee..49a4c75243f 100644
--- a/arch/arm/plat-omap/Kconfig
+++ b/arch/arm/plat-omap/Kconfig
@@ -211,6 +211,9 @@ choice
depends on ARCH_OMAP
default OMAP_PM_NOOP
+config OMAP_PM_NONE
+ bool "No PM layer"
+
config OMAP_PM_NOOP
bool "No-op/debug PM layer"
diff --git a/arch/arm/plat-omap/clock.c b/arch/arm/plat-omap/clock.c
index 156b27dd581..c9122dd6ee8 100644
--- a/arch/arm/plat-omap/clock.c
+++ b/arch/arm/plat-omap/clock.c
@@ -475,41 +475,8 @@ int __init clk_init(struct clk_functions * custom_clocks)
/*
* debugfs support to trace clock tree hierarchy and attributes
*/
-
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-
static struct dentry *clk_debugfs_root;
-static int clk_dbg_show_summary(struct seq_file *s, void *unused)
-{
- struct clk *c;
- struct clk *pa;
-
- seq_printf(s, "%-30s %-30s %-10s %s\n",
- "clock-name", "parent-name", "rate", "use-count");
-
- list_for_each_entry(c, &clocks, node) {
- pa = c->parent;
- seq_printf(s, "%-30s %-30s %-10lu %d\n",
- c->name, pa ? pa->name : "none", c->rate, c->usecount);
- }
-
- return 0;
-}
-
-static int clk_dbg_open(struct inode *inode, struct file *file)
-{
- return single_open(file, clk_dbg_show_summary, inode->i_private);
-}
-
-static const struct file_operations debug_clock_fops = {
- .open = clk_dbg_open,
- .read = seq_read,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
static int clk_debugfs_register_one(struct clk *c)
{
int err;
@@ -584,12 +551,6 @@ static int __init clk_debugfs_init(void)
if (err)
goto err_out;
}
-
- d = debugfs_create_file("summary", S_IRUGO,
- d, NULL, &debug_clock_fops);
- if (!d)
- return -ENOMEM;
-
return 0;
err_out:
debugfs_remove_recursive(clk_debugfs_root);
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
index a6cbb712da5..f7fed608019 100644
--- a/arch/arm/plat-omap/counter_32k.c
+++ b/arch/arm/plat-omap/counter_32k.c
@@ -18,7 +18,6 @@
#include <linux/err.h>
#include <linux/io.h>
#include <linux/sched.h>
-#include <linux/clocksource.h>
#include <asm/sched_clock.h>
@@ -27,16 +26,87 @@
#include <plat/clock.h>
+
/*
* 32KHz clocksource ... always available, on pretty most chips except
* OMAP 730 and 1510. Other timers could be used as clocksources, with
* higher resolution in free-running counter modes (e.g. 12 MHz xtal),
* but systems won't necessarily want to spend resources that way.
*/
-static void __iomem *timer_32k_base;
#define OMAP16XX_TIMER_32K_SYNCHRONIZED 0xfffbc410
+#include <linux/clocksource.h>
+
+/*
+ * offset_32k holds the init time counter value. It is then subtracted
+ * from every counter read to achieve a counter that counts time from the
+ * kernel boot (needed for sched_clock()).
+ */
+static u32 offset_32k __read_mostly;
+
+#ifdef CONFIG_ARCH_OMAP16XX
+static cycle_t notrace omap16xx_32k_read(struct clocksource *cs)
+{
+ return omap_readl(OMAP16XX_TIMER_32K_SYNCHRONIZED) - offset_32k;
+}
+#else
+#define omap16xx_32k_read NULL
+#endif
+
+#ifdef CONFIG_SOC_OMAP2420
+static cycle_t notrace omap2420_32k_read(struct clocksource *cs)
+{
+ return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap2420_32k_read NULL
+#endif
+
+#ifdef CONFIG_SOC_OMAP2430
+static cycle_t notrace omap2430_32k_read(struct clocksource *cs)
+{
+ return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap2430_32k_read NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+static cycle_t notrace omap34xx_32k_read(struct clocksource *cs)
+{
+ return omap_readl(OMAP3430_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap34xx_32k_read NULL
+#endif
+
+#ifdef CONFIG_ARCH_OMAP4
+static cycle_t notrace omap44xx_32k_read(struct clocksource *cs)
+{
+ return omap_readl(OMAP4430_32KSYNCT_BASE + 0x10) - offset_32k;
+}
+#else
+#define omap44xx_32k_read NULL
+#endif
+
+/*
+ * Kernel assumes that sched_clock can be called early but may not have
+ * things ready yet.
+ */
+static cycle_t notrace omap_32k_read_dummy(struct clocksource *cs)
+{
+ return 0;
+}
+
+static struct clocksource clocksource_32k = {
+ .name = "32k_counter",
+ .rating = 250,
+ .read = omap_32k_read_dummy,
+ .mask = CLOCKSOURCE_MASK(32),
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
/*
* Returns current time from boot in nsecs. It's OK for this to wrap
* around for now, as it's just a relative time stamp.
@@ -52,11 +122,11 @@ static DEFINE_CLOCK_DATA(cd);
static inline unsigned long long notrace _omap_32k_sched_clock(void)
{
- u32 cyc = timer_32k_base ? __raw_readl(timer_32k_base) : 0;
+ u32 cyc = clocksource_32k.read(&clocksource_32k);
return cyc_to_fixed_sched_clock(&cd, cyc, (u32)~0, SC_MULT, SC_SHIFT);
}
-#if defined(CONFIG_OMAP_32K_TIMER) && !defined(CONFIG_OMAP_MPU_TIMER)
+#ifndef CONFIG_OMAP_MPU_TIMER
unsigned long long notrace sched_clock(void)
{
return _omap_32k_sched_clock();
@@ -70,7 +140,7 @@ unsigned long long notrace omap_32k_sched_clock(void)
static void notrace omap_update_sched_clock(void)
{
- u32 cyc = timer_32k_base ? __raw_readl(timer_32k_base) : 0;
+ u32 cyc = clocksource_32k.read(&clocksource_32k);
update_sched_clock(&cd, cyc, (u32)~0);
}
@@ -83,7 +153,6 @@ static void notrace omap_update_sched_clock(void)
*/
static struct timespec persistent_ts;
static cycles_t cycles, last_cycles;
-static unsigned int persistent_mult, persistent_shift;
void read_persistent_clock(struct timespec *ts)
{
unsigned long long nsecs;
@@ -91,10 +160,11 @@ void read_persistent_clock(struct timespec *ts)
struct timespec *tsp = &persistent_ts;
last_cycles = cycles;
- cycles = timer_32k_base ? __raw_readl(timer_32k_base) : 0;
+ cycles = clocksource_32k.read(&clocksource_32k);
delta = cycles - last_cycles;
- nsecs = clocksource_cyc2ns(delta, persistent_mult, persistent_shift);
+ nsecs = clocksource_cyc2ns(delta,
+ clocksource_32k.mult, clocksource_32k.shift);
timespec_add_ns(tsp, nsecs);
*ts = *tsp;
@@ -106,46 +176,29 @@ int __init omap_init_clocksource_32k(void)
"%s: can't register clocksource!\n";
if (cpu_is_omap16xx() || cpu_class_is_omap2()) {
- u32 pbase;
- unsigned long size = SZ_4K;
- void __iomem *base;
struct clk *sync_32k_ick;
- if (cpu_is_omap16xx()) {
- pbase = OMAP16XX_TIMER_32K_SYNCHRONIZED;
- size = SZ_1K;
- } else if (cpu_is_omap2420())
- pbase = OMAP2420_32KSYNCT_BASE + 0x10;
+ if (cpu_is_omap16xx())
+ clocksource_32k.read = omap16xx_32k_read;
+ else if (cpu_is_omap2420())
+ clocksource_32k.read = omap2420_32k_read;
else if (cpu_is_omap2430())
- pbase = OMAP2430_32KSYNCT_BASE + 0x10;
+ clocksource_32k.read = omap2430_32k_read;
else if (cpu_is_omap34xx())
- pbase = OMAP3430_32KSYNCT_BASE + 0x10;
+ clocksource_32k.read = omap34xx_32k_read;
else if (cpu_is_omap44xx())
- pbase = OMAP4430_32KSYNCT_BASE + 0x10;
+ clocksource_32k.read = omap44xx_32k_read;
else
return -ENODEV;
- /* For this to work we must have a static mapping in io.c for this area */
- base = ioremap(pbase, size);
- if (!base)
- return -ENODEV;
-
sync_32k_ick = clk_get(NULL, "omap_32ksync_ick");
if (!IS_ERR(sync_32k_ick))
clk_enable(sync_32k_ick);
- timer_32k_base = base;
-
- /*
- * 120000 rough estimate from the calculations in
- * __clocksource_updatefreq_scale.
- */
- clocks_calc_mult_shift(&persistent_mult, &persistent_shift,
- 32768, NSEC_PER_SEC, 120000);
+ offset_32k = clocksource_32k.read(&clocksource_32k);
- if (clocksource_mmio_init(base, "32k_counter", 32768, 250, 32,
- clocksource_mmio_readl_up))
- printk(err, "32k_counter");
+ if (clocksource_register_hz(&clocksource_32k, 32768))
+ printk(err, clocksource_32k.name);
init_fixed_sched_clock(&cd, omap_update_sched_clock, 32,
32768, SC_MULT, SC_SHIFT);
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 75a847dd776..ee9f6ebba29 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -41,6 +41,127 @@
#include <plat/dmtimer.h>
#include <mach/irqs.h>
+/* register offsets */
+#define _OMAP_TIMER_ID_OFFSET 0x00
+#define _OMAP_TIMER_OCP_CFG_OFFSET 0x10
+#define _OMAP_TIMER_SYS_STAT_OFFSET 0x14
+#define _OMAP_TIMER_STAT_OFFSET 0x18
+#define _OMAP_TIMER_INT_EN_OFFSET 0x1c
+#define _OMAP_TIMER_WAKEUP_EN_OFFSET 0x20
+#define _OMAP_TIMER_CTRL_OFFSET 0x24
+#define OMAP_TIMER_CTRL_GPOCFG (1 << 14)
+#define OMAP_TIMER_CTRL_CAPTMODE (1 << 13)
+#define OMAP_TIMER_CTRL_PT (1 << 12)
+#define OMAP_TIMER_CTRL_TCM_LOWTOHIGH (0x1 << 8)
+#define OMAP_TIMER_CTRL_TCM_HIGHTOLOW (0x2 << 8)
+#define OMAP_TIMER_CTRL_TCM_BOTHEDGES (0x3 << 8)
+#define OMAP_TIMER_CTRL_SCPWM (1 << 7)
+#define OMAP_TIMER_CTRL_CE (1 << 6) /* compare enable */
+#define OMAP_TIMER_CTRL_PRE (1 << 5) /* prescaler enable */
+#define OMAP_TIMER_CTRL_PTV_SHIFT 2 /* prescaler value shift */
+#define OMAP_TIMER_CTRL_POSTED (1 << 2)
+#define OMAP_TIMER_CTRL_AR (1 << 1) /* auto-reload enable */
+#define OMAP_TIMER_CTRL_ST (1 << 0) /* start timer */
+#define _OMAP_TIMER_COUNTER_OFFSET 0x28
+#define _OMAP_TIMER_LOAD_OFFSET 0x2c
+#define _OMAP_TIMER_TRIGGER_OFFSET 0x30
+#define _OMAP_TIMER_WRITE_PEND_OFFSET 0x34
+#define WP_NONE 0 /* no write pending bit */
+#define WP_TCLR (1 << 0)
+#define WP_TCRR (1 << 1)
+#define WP_TLDR (1 << 2)
+#define WP_TTGR (1 << 3)
+#define WP_TMAR (1 << 4)
+#define WP_TPIR (1 << 5)
+#define WP_TNIR (1 << 6)
+#define WP_TCVR (1 << 7)
+#define WP_TOCR (1 << 8)
+#define WP_TOWR (1 << 9)
+#define _OMAP_TIMER_MATCH_OFFSET 0x38
+#define _OMAP_TIMER_CAPTURE_OFFSET 0x3c
+#define _OMAP_TIMER_IF_CTRL_OFFSET 0x40
+#define _OMAP_TIMER_CAPTURE2_OFFSET 0x44 /* TCAR2, 34xx only */
+#define _OMAP_TIMER_TICK_POS_OFFSET 0x48 /* TPIR, 34xx only */
+#define _OMAP_TIMER_TICK_NEG_OFFSET 0x4c /* TNIR, 34xx only */
+#define _OMAP_TIMER_TICK_COUNT_OFFSET 0x50 /* TCVR, 34xx only */
+#define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET 0x54 /* TOCR, 34xx only */
+#define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET 0x58 /* TOWR, 34xx only */
+
+/* register offsets with the write pending bit encoded */
+#define WPSHIFT 16
+
+#define OMAP_TIMER_ID_REG (_OMAP_TIMER_ID_OFFSET \
+ | (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_OCP_CFG_REG (_OMAP_TIMER_OCP_CFG_OFFSET \
+ | (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_SYS_STAT_REG (_OMAP_TIMER_SYS_STAT_OFFSET \
+ | (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_STAT_REG (_OMAP_TIMER_STAT_OFFSET \
+ | (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_INT_EN_REG (_OMAP_TIMER_INT_EN_OFFSET \
+ | (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_WAKEUP_EN_REG (_OMAP_TIMER_WAKEUP_EN_OFFSET \
+ | (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_CTRL_REG (_OMAP_TIMER_CTRL_OFFSET \
+ | (WP_TCLR << WPSHIFT))
+
+#define OMAP_TIMER_COUNTER_REG (_OMAP_TIMER_COUNTER_OFFSET \
+ | (WP_TCRR << WPSHIFT))
+
+#define OMAP_TIMER_LOAD_REG (_OMAP_TIMER_LOAD_OFFSET \
+ | (WP_TLDR << WPSHIFT))
+
+#define OMAP_TIMER_TRIGGER_REG (_OMAP_TIMER_TRIGGER_OFFSET \
+ | (WP_TTGR << WPSHIFT))
+
+#define OMAP_TIMER_WRITE_PEND_REG (_OMAP_TIMER_WRITE_PEND_OFFSET \
+ | (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_MATCH_REG (_OMAP_TIMER_MATCH_OFFSET \
+ | (WP_TMAR << WPSHIFT))
+
+#define OMAP_TIMER_CAPTURE_REG (_OMAP_TIMER_CAPTURE_OFFSET \
+ | (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_IF_CTRL_REG (_OMAP_TIMER_IF_CTRL_OFFSET \
+ | (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_CAPTURE2_REG (_OMAP_TIMER_CAPTURE2_OFFSET \
+ | (WP_NONE << WPSHIFT))
+
+#define OMAP_TIMER_TICK_POS_REG (_OMAP_TIMER_TICK_POS_OFFSET \
+ | (WP_TPIR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_NEG_REG (_OMAP_TIMER_TICK_NEG_OFFSET \
+ | (WP_TNIR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_COUNT_REG (_OMAP_TIMER_TICK_COUNT_OFFSET \
+ | (WP_TCVR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_INT_MASK_SET_REG \
+ (_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT))
+
+#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \
+ (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
+
+struct omap_dm_timer {
+ unsigned long phys_base;
+ int irq;
+#ifdef CONFIG_ARCH_OMAP2PLUS
+ struct clk *iclk, *fclk;
+#endif
+ void __iomem *io_base;
+ unsigned reserved:1;
+ unsigned enabled:1;
+ unsigned posted:1;
+};
+
static int dm_timer_count;
#ifdef CONFIG_ARCH_OMAP1
@@ -170,7 +291,11 @@ static spinlock_t dm_timer_lock;
*/
static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
{
- return __omap_dm_timer_read(timer->io_base, reg, timer->posted);
+ if (timer->posted)
+ while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
+ & (reg >> WPSHIFT))
+ cpu_relax();
+ return readl(timer->io_base + (reg & 0xff));
}
/*
@@ -182,7 +307,11 @@ static inline u32 omap_dm_timer_read_reg(struct omap_dm_timer *timer, u32 reg)
static void omap_dm_timer_write_reg(struct omap_dm_timer *timer, u32 reg,
u32 value)
{
- __omap_dm_timer_write(timer->io_base, reg, value, timer->posted);
+ if (timer->posted)
+ while (readl(timer->io_base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
+ & (reg >> WPSHIFT))
+ cpu_relax();
+ writel(value, timer->io_base + (reg & 0xff));
}
static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
@@ -201,7 +330,7 @@ static void omap_dm_timer_wait_for_reset(struct omap_dm_timer *timer)
static void omap_dm_timer_reset(struct omap_dm_timer *timer)
{
- int autoidle = 0, wakeup = 0;
+ u32 l;
if (!cpu_class_is_omap2() || timer != &dm_timers[0]) {
omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG, 0x06);
@@ -209,21 +338,28 @@ static void omap_dm_timer_reset(struct omap_dm_timer *timer)
}
omap_dm_timer_set_source(timer, OMAP_TIMER_SRC_32_KHZ);
- /* Enable autoidle on OMAP2+ */
- if (cpu_class_is_omap2())
- autoidle = 1;
+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_OCP_CFG_REG);
+ l |= 0x02 << 3; /* Set to smart-idle mode */
+ l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
+
+ /* Enable autoidle on OMAP2 / OMAP3 */
+ if (cpu_is_omap24xx() || cpu_is_omap34xx())
+ l |= 0x1 << 0;
/*
* Enable wake-up on OMAP2 CPUs.
*/
if (cpu_class_is_omap2())
- wakeup = 1;
+ l |= 1 << 2;
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_OCP_CFG_REG, l);
- __omap_dm_timer_reset(timer->io_base, autoidle, wakeup);
+ /* Match hardware reset default of posted mode */
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_IF_CTRL_REG,
+ OMAP_TIMER_CTRL_POSTED);
timer->posted = 1;
}
-void omap_dm_timer_prepare(struct omap_dm_timer *timer)
+static void omap_dm_timer_prepare(struct omap_dm_timer *timer)
{
omap_dm_timer_enable(timer);
omap_dm_timer_reset(timer);
@@ -395,13 +531,25 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_start);
void omap_dm_timer_stop(struct omap_dm_timer *timer)
{
- unsigned long rate = 0;
+ u32 l;
+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+ if (l & OMAP_TIMER_CTRL_ST) {
+ l &= ~0x1;
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
#ifdef CONFIG_ARCH_OMAP2PLUS
- rate = clk_get_rate(timer->fclk);
+ /* Readback to make sure write has completed */
+ omap_dm_timer_read_reg(timer, OMAP_TIMER_CTRL_REG);
+ /*
+ * Wait for functional clock period x 3.5 to make sure that
+ * timer is stopped
+ */
+ udelay(3500000 / clk_get_rate(timer->fclk) + 1);
#endif
-
- __omap_dm_timer_stop(timer->io_base, timer->posted, rate);
+ }
+ /* Ack possibly pending interrupt */
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG,
+ OMAP_TIMER_INT_OVERFLOW);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_stop);
@@ -424,11 +572,22 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
int omap_dm_timer_set_source(struct omap_dm_timer *timer, int source)
{
+ int ret = -EINVAL;
+
if (source < 0 || source >= 3)
return -EINVAL;
- return __omap_dm_timer_set_source(timer->fclk,
- dm_source_clocks[source]);
+ clk_disable(timer->fclk);
+ ret = clk_set_parent(timer->fclk, dm_source_clocks[source]);
+ clk_enable(timer->fclk);
+
+ /*
+ * When the functional clock disappears, too quick writes seem
+ * to cause an abort. XXX Is this still necessary?
+ */
+ __delay(300000);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_source);
@@ -466,7 +625,8 @@ void omap_dm_timer_set_load_start(struct omap_dm_timer *timer, int autoreload,
}
l |= OMAP_TIMER_CTRL_ST;
- __omap_dm_timer_load_start(timer->io_base, l, load, timer->posted);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_COUNTER_REG, load);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_CTRL_REG, l);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_load_start);
@@ -519,7 +679,8 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_set_prescaler);
void omap_dm_timer_set_int_enable(struct omap_dm_timer *timer,
unsigned int value)
{
- __omap_dm_timer_int_enable(timer->io_base, value);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_INT_EN_REG, value);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_WAKEUP_EN_REG, value);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_set_int_enable);
@@ -535,13 +696,17 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_read_status);
void omap_dm_timer_write_status(struct omap_dm_timer *timer, unsigned int value)
{
- __omap_dm_timer_write_status(timer->io_base, value);
+ omap_dm_timer_write_reg(timer, OMAP_TIMER_STAT_REG, value);
}
EXPORT_SYMBOL_GPL(omap_dm_timer_write_status);
unsigned int omap_dm_timer_read_counter(struct omap_dm_timer *timer)
{
- return __omap_dm_timer_read_counter(timer->io_base, timer->posted);
+ unsigned int l;
+
+ l = omap_dm_timer_read_reg(timer, OMAP_TIMER_COUNTER_REG);
+
+ return l;
}
EXPORT_SYMBOL_GPL(omap_dm_timer_read_counter);
@@ -572,7 +737,7 @@ int omap_dm_timers_active(void)
}
EXPORT_SYMBOL_GPL(omap_dm_timers_active);
-static int __init omap_dm_timer_init(void)
+int __init omap_dm_timer_init(void)
{
struct omap_dm_timer *timer;
int i, map_size = SZ_8K; /* Module 4KB + L4 4KB except on omap1 */
@@ -625,16 +790,8 @@ static int __init omap_dm_timer_init(void)
sprintf(clk_name, "gpt%d_fck", i + 1);
timer->fclk = clk_get(NULL, clk_name);
}
-
- /* One or two timers may be set up early for sys_timer */
- if (sys_timer_reserved & (1 << i)) {
- timer->reserved = 1;
- timer->posted = 1;
- }
#endif
}
return 0;
}
-
-arch_initcall(omap_dm_timer_init);
diff --git a/arch/arm/plat-omap/include/plat/clkdev_omap.h b/arch/arm/plat-omap/include/plat/clkdev_omap.h
index 387a9638991..f1899a3e417 100644
--- a/arch/arm/plat-omap/include/plat/clkdev_omap.h
+++ b/arch/arm/plat-omap/include/plat/clkdev_omap.h
@@ -39,7 +39,6 @@ struct omap_clk {
#define CK_36XX (1 << 10) /* 36xx/37xx-specific clocks */
#define CK_443X (1 << 11)
#define CK_TI816X (1 << 12)
-#define CK_446X (1 << 13)
#define CK_34XX (CK_3430ES1 | CK_3430ES2PLUS)
diff --git a/arch/arm/plat-omap/include/plat/clock.h b/arch/arm/plat-omap/include/plat/clock.h
index df4b9683f17..006e599c661 100644
--- a/arch/arm/plat-omap/include/plat/clock.h
+++ b/arch/arm/plat-omap/include/plat/clock.h
@@ -58,12 +58,10 @@ struct clkops {
#define RATE_IN_36XX (1 << 4)
#define RATE_IN_4430 (1 << 5)
#define RATE_IN_TI816X (1 << 6)
-#define RATE_IN_4460 (1 << 7)
#define RATE_IN_24XX (RATE_IN_242X | RATE_IN_243X)
#define RATE_IN_34XX (RATE_IN_3430ES1 | RATE_IN_3430ES2PLUS)
#define RATE_IN_3XXX (RATE_IN_34XX | RATE_IN_36XX)
-#define RATE_IN_44XX (RATE_IN_4430 | RATE_IN_4460)
/* 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)
@@ -154,7 +152,7 @@ struct dpll_data {
u16 max_multiplier;
u8 last_rounded_n;
u8 min_divider;
- u16 max_divider;
+ u8 max_divider;
u8 modes;
#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
void __iomem *autoidle_reg;
diff --git a/arch/arm/plat-omap/include/plat/common.h b/arch/arm/plat-omap/include/plat/common.h
index 4564cc697d7..5288130be96 100644
--- a/arch/arm/plat-omap/include/plat/common.h
+++ b/arch/arm/plat-omap/include/plat/common.h
@@ -34,11 +34,7 @@
struct sys_timer;
extern void omap_map_common_io(void);
-extern struct sys_timer omap1_timer;
-extern struct sys_timer omap2_timer;
-extern struct sys_timer omap3_timer;
-extern struct sys_timer omap3_secure_timer;
-extern struct sys_timer omap4_timer;
+extern struct sys_timer omap_timer;
extern bool omap_32k_timer_init(void);
extern int __init omap_init_clocksource_32k(void);
extern unsigned long long notrace omap_32k_sched_clock(void);
diff --git a/arch/arm/plat-omap/include/plat/cpu.h b/arch/arm/plat-omap/include/plat/cpu.h
index 67b3d75884c..8198bb6cdb5 100644
--- a/arch/arm/plat-omap/include/plat/cpu.h
+++ b/arch/arm/plat-omap/include/plat/cpu.h
@@ -88,7 +88,6 @@ unsigned int omap_rev(void);
* cpu_is_omap243x(): True for OMAP2430
* cpu_is_omap343x(): True for OMAP3430
* cpu_is_omap443x(): True for OMAP4430
- * cpu_is_omap446x(): True for OMAP4460
*/
#define GET_OMAP_CLASS (omap_rev() & 0xff)
@@ -124,7 +123,6 @@ IS_OMAP_SUBCLASS(243x, 0x243)
IS_OMAP_SUBCLASS(343x, 0x343)
IS_OMAP_SUBCLASS(363x, 0x363)
IS_OMAP_SUBCLASS(443x, 0x443)
-IS_OMAP_SUBCLASS(446x, 0x446)
IS_TI_SUBCLASS(816x, 0x816)
@@ -139,7 +137,6 @@ IS_TI_SUBCLASS(816x, 0x816)
#define cpu_is_ti816x() 0
#define cpu_is_omap44xx() 0
#define cpu_is_omap443x() 0
-#define cpu_is_omap446x() 0
#if defined(MULTI_OMAP1)
# if defined(CONFIG_ARCH_OMAP730)
@@ -364,10 +361,8 @@ IS_OMAP_TYPE(3517, 0x3517)
# if defined(CONFIG_ARCH_OMAP4)
# undef cpu_is_omap44xx
# undef cpu_is_omap443x
-# undef cpu_is_omap446x
# define cpu_is_omap44xx() is_omap44xx()
# define cpu_is_omap443x() is_omap443x()
-# define cpu_is_omap446x() is_omap446x()
# endif
/* Macros to detect if we have OMAP1 or OMAP2 */
@@ -415,9 +410,6 @@ IS_OMAP_TYPE(3517, 0x3517)
#define OMAP4430_REV_ES2_1 (OMAP443X_CLASS | (0x21 << 8))
#define OMAP4430_REV_ES2_2 (OMAP443X_CLASS | (0x22 << 8))
-#define OMAP446X_CLASS 0x44600044
-#define OMAP4460_REV_ES1_0 (OMAP446X_CLASS | (0x10 << 8))
-
/*
* omap_chip bits
*
@@ -447,15 +439,13 @@ IS_OMAP_TYPE(3517, 0x3517)
#define CHIP_IS_OMAP4430ES2_1 (1 << 12)
#define CHIP_IS_OMAP4430ES2_2 (1 << 13)
#define CHIP_IS_TI816X (1 << 14)
-#define CHIP_IS_OMAP4460ES1_0 (1 << 15)
#define CHIP_IS_OMAP24XX (CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
#define CHIP_IS_OMAP4430 (CHIP_IS_OMAP4430ES1 | \
CHIP_IS_OMAP4430ES2 | \
CHIP_IS_OMAP4430ES2_1 | \
- CHIP_IS_OMAP4430ES2_2 | \
- CHIP_IS_OMAP4460ES1_0)
+ CHIP_IS_OMAP4430ES2_2)
/*
* "GE" here represents "greater than or equal to" in terms of ES
@@ -478,7 +468,7 @@ void omap2_check_revision(void);
/*
* Runtime detection of OMAP3 features
*/
-extern u32 omap_features;
+extern u32 omap3_features;
#define OMAP3_HAS_L2CACHE BIT(0)
#define OMAP3_HAS_IVA BIT(1)
@@ -488,15 +478,11 @@ extern u32 omap_features;
#define OMAP3_HAS_192MHZ_CLK BIT(5)
#define OMAP3_HAS_IO_WAKEUP BIT(6)
#define OMAP3_HAS_SDRC BIT(7)
-#define OMAP4_HAS_MPU_1GHZ BIT(8)
-#define OMAP4_HAS_MPU_1_2GHZ BIT(9)
-#define OMAP4_HAS_MPU_1_5GHZ BIT(10)
-
#define OMAP3_HAS_FEATURE(feat,flag) \
static inline unsigned int omap3_has_ ##feat(void) \
{ \
- return omap_features & OMAP3_HAS_ ##flag; \
+ return (omap3_features & OMAP3_HAS_ ##flag); \
} \
OMAP3_HAS_FEATURE(l2cache, L2CACHE)
@@ -508,19 +494,4 @@ OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
OMAP3_HAS_FEATURE(sdrc, SDRC)
-/*
- * Runtime detection of OMAP4 features
- */
-extern u32 omap_features;
-
-#define OMAP4_HAS_FEATURE(feat, flag) \
-static inline unsigned int omap4_has_ ##feat(void) \
-{ \
- return omap_features & OMAP4_HAS_ ##flag; \
-} \
-
-OMAP4_HAS_FEATURE(mpu_1ghz, MPU_1GHZ)
-OMAP4_HAS_FEATURE(mpu_1_2ghz, MPU_1_2GHZ)
-OMAP4_HAS_FEATURE(mpu_1_5ghz, MPU_1_5GHZ)
-
#endif
diff --git a/arch/arm/plat-omap/include/plat/dmtimer.h b/arch/arm/plat-omap/include/plat/dmtimer.h
index eb5d16c60cd..d6c70d2f403 100644
--- a/arch/arm/plat-omap/include/plat/dmtimer.h
+++ b/arch/arm/plat-omap/include/plat/dmtimer.h
@@ -32,10 +32,6 @@
* 675 Mass Ave, Cambridge, MA 02139, USA.
*/
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
#ifndef __ASM_ARCH_DMTIMER_H
#define __ASM_ARCH_DMTIMER_H
@@ -60,8 +56,12 @@
*/
#define OMAP_TIMER_IP_VERSION_1 0x1
struct omap_dm_timer;
+extern struct omap_dm_timer *gptimer_wakeup;
+extern struct sys_timer omap_timer;
struct clk;
+int omap_dm_timer_init(void);
+
struct omap_dm_timer *omap_dm_timer_request(void);
struct omap_dm_timer *omap_dm_timer_request_specific(int timer_id);
void omap_dm_timer_free(struct omap_dm_timer *timer);
@@ -93,248 +93,5 @@ void omap_dm_timer_write_counter(struct omap_dm_timer *timer, unsigned int value
int omap_dm_timers_active(void);
-/*
- * Do not use the defines below, they are not needed. They should be only
- * used by dmtimer.c and sys_timer related code.
- */
-
-/* register offsets */
-#define _OMAP_TIMER_ID_OFFSET 0x00
-#define _OMAP_TIMER_OCP_CFG_OFFSET 0x10
-#define _OMAP_TIMER_SYS_STAT_OFFSET 0x14
-#define _OMAP_TIMER_STAT_OFFSET 0x18
-#define _OMAP_TIMER_INT_EN_OFFSET 0x1c
-#define _OMAP_TIMER_WAKEUP_EN_OFFSET 0x20
-#define _OMAP_TIMER_CTRL_OFFSET 0x24
-#define OMAP_TIMER_CTRL_GPOCFG (1 << 14)
-#define OMAP_TIMER_CTRL_CAPTMODE (1 << 13)
-#define OMAP_TIMER_CTRL_PT (1 << 12)
-#define OMAP_TIMER_CTRL_TCM_LOWTOHIGH (0x1 << 8)
-#define OMAP_TIMER_CTRL_TCM_HIGHTOLOW (0x2 << 8)
-#define OMAP_TIMER_CTRL_TCM_BOTHEDGES (0x3 << 8)
-#define OMAP_TIMER_CTRL_SCPWM (1 << 7)
-#define OMAP_TIMER_CTRL_CE (1 << 6) /* compare enable */
-#define OMAP_TIMER_CTRL_PRE (1 << 5) /* prescaler enable */
-#define OMAP_TIMER_CTRL_PTV_SHIFT 2 /* prescaler value shift */
-#define OMAP_TIMER_CTRL_POSTED (1 << 2)
-#define OMAP_TIMER_CTRL_AR (1 << 1) /* auto-reload enable */
-#define OMAP_TIMER_CTRL_ST (1 << 0) /* start timer */
-#define _OMAP_TIMER_COUNTER_OFFSET 0x28
-#define _OMAP_TIMER_LOAD_OFFSET 0x2c
-#define _OMAP_TIMER_TRIGGER_OFFSET 0x30
-#define _OMAP_TIMER_WRITE_PEND_OFFSET 0x34
-#define WP_NONE 0 /* no write pending bit */
-#define WP_TCLR (1 << 0)
-#define WP_TCRR (1 << 1)
-#define WP_TLDR (1 << 2)
-#define WP_TTGR (1 << 3)
-#define WP_TMAR (1 << 4)
-#define WP_TPIR (1 << 5)
-#define WP_TNIR (1 << 6)
-#define WP_TCVR (1 << 7)
-#define WP_TOCR (1 << 8)
-#define WP_TOWR (1 << 9)
-#define _OMAP_TIMER_MATCH_OFFSET 0x38
-#define _OMAP_TIMER_CAPTURE_OFFSET 0x3c
-#define _OMAP_TIMER_IF_CTRL_OFFSET 0x40
-#define _OMAP_TIMER_CAPTURE2_OFFSET 0x44 /* TCAR2, 34xx only */
-#define _OMAP_TIMER_TICK_POS_OFFSET 0x48 /* TPIR, 34xx only */
-#define _OMAP_TIMER_TICK_NEG_OFFSET 0x4c /* TNIR, 34xx only */
-#define _OMAP_TIMER_TICK_COUNT_OFFSET 0x50 /* TCVR, 34xx only */
-#define _OMAP_TIMER_TICK_INT_MASK_SET_OFFSET 0x54 /* TOCR, 34xx only */
-#define _OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET 0x58 /* TOWR, 34xx only */
-
-/* register offsets with the write pending bit encoded */
-#define WPSHIFT 16
-
-#define OMAP_TIMER_ID_REG (_OMAP_TIMER_ID_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_OCP_CFG_REG (_OMAP_TIMER_OCP_CFG_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_SYS_STAT_REG (_OMAP_TIMER_SYS_STAT_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_STAT_REG (_OMAP_TIMER_STAT_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_INT_EN_REG (_OMAP_TIMER_INT_EN_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_WAKEUP_EN_REG (_OMAP_TIMER_WAKEUP_EN_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_CTRL_REG (_OMAP_TIMER_CTRL_OFFSET \
- | (WP_TCLR << WPSHIFT))
-
-#define OMAP_TIMER_COUNTER_REG (_OMAP_TIMER_COUNTER_OFFSET \
- | (WP_TCRR << WPSHIFT))
-
-#define OMAP_TIMER_LOAD_REG (_OMAP_TIMER_LOAD_OFFSET \
- | (WP_TLDR << WPSHIFT))
-
-#define OMAP_TIMER_TRIGGER_REG (_OMAP_TIMER_TRIGGER_OFFSET \
- | (WP_TTGR << WPSHIFT))
-
-#define OMAP_TIMER_WRITE_PEND_REG (_OMAP_TIMER_WRITE_PEND_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_MATCH_REG (_OMAP_TIMER_MATCH_OFFSET \
- | (WP_TMAR << WPSHIFT))
-
-#define OMAP_TIMER_CAPTURE_REG (_OMAP_TIMER_CAPTURE_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_IF_CTRL_REG (_OMAP_TIMER_IF_CTRL_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_CAPTURE2_REG (_OMAP_TIMER_CAPTURE2_OFFSET \
- | (WP_NONE << WPSHIFT))
-
-#define OMAP_TIMER_TICK_POS_REG (_OMAP_TIMER_TICK_POS_OFFSET \
- | (WP_TPIR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_NEG_REG (_OMAP_TIMER_TICK_NEG_OFFSET \
- | (WP_TNIR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_COUNT_REG (_OMAP_TIMER_TICK_COUNT_OFFSET \
- | (WP_TCVR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_INT_MASK_SET_REG \
- (_OMAP_TIMER_TICK_INT_MASK_SET_OFFSET | (WP_TOCR << WPSHIFT))
-
-#define OMAP_TIMER_TICK_INT_MASK_COUNT_REG \
- (_OMAP_TIMER_TICK_INT_MASK_COUNT_OFFSET | (WP_TOWR << WPSHIFT))
-
-struct omap_dm_timer {
- unsigned long phys_base;
- int irq;
-#ifdef CONFIG_ARCH_OMAP2PLUS
- struct clk *iclk, *fclk;
-#endif
- void __iomem *io_base;
- unsigned long rate;
- unsigned reserved:1;
- unsigned enabled:1;
- unsigned posted:1;
-};
-
-extern u32 sys_timer_reserved;
-void omap_dm_timer_prepare(struct omap_dm_timer *timer);
-
-static inline u32 __omap_dm_timer_read(void __iomem *base, u32 reg,
- int posted)
-{
- if (posted)
- while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
- & (reg >> WPSHIFT))
- cpu_relax();
-
- return __raw_readl(base + (reg & 0xff));
-}
-
-static inline void __omap_dm_timer_write(void __iomem *base, u32 reg, u32 val,
- int posted)
-{
- if (posted)
- while (__raw_readl(base + (OMAP_TIMER_WRITE_PEND_REG & 0xff))
- & (reg >> WPSHIFT))
- cpu_relax();
-
- __raw_writel(val, base + (reg & 0xff));
-}
-
-/* Assumes the source clock has been set by caller */
-static inline void __omap_dm_timer_reset(void __iomem *base, int autoidle,
- int wakeup)
-{
- u32 l;
-
- l = __omap_dm_timer_read(base, OMAP_TIMER_OCP_CFG_REG, 0);
- l |= 0x02 << 3; /* Set to smart-idle mode */
- l |= 0x2 << 8; /* Set clock activity to perserve f-clock on idle */
-
- if (autoidle)
- l |= 0x1 << 0;
-
- if (wakeup)
- l |= 1 << 2;
-
- __omap_dm_timer_write(base, OMAP_TIMER_OCP_CFG_REG, l, 0);
-
- /* Match hardware reset default of posted mode */
- __omap_dm_timer_write(base, OMAP_TIMER_IF_CTRL_REG,
- OMAP_TIMER_CTRL_POSTED, 0);
-}
-
-static inline int __omap_dm_timer_set_source(struct clk *timer_fck,
- struct clk *parent)
-{
- int ret;
-
- clk_disable(timer_fck);
- ret = clk_set_parent(timer_fck, parent);
- clk_enable(timer_fck);
-
- /*
- * When the functional clock disappears, too quick writes seem
- * to cause an abort. XXX Is this still necessary?
- */
- __delay(300000);
-
- return ret;
-}
-
-static inline void __omap_dm_timer_stop(void __iomem *base, int posted,
- unsigned long rate)
-{
- u32 l;
-
- l = __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
- if (l & OMAP_TIMER_CTRL_ST) {
- l &= ~0x1;
- __omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, l, posted);
-#ifdef CONFIG_ARCH_OMAP2PLUS
- /* Readback to make sure write has completed */
- __omap_dm_timer_read(base, OMAP_TIMER_CTRL_REG, posted);
- /*
- * Wait for functional clock period x 3.5 to make sure that
- * timer is stopped
- */
- udelay(3500000 / rate + 1);
-#endif
- }
-
- /* Ack possibly pending interrupt */
- __omap_dm_timer_write(base, OMAP_TIMER_STAT_REG,
- OMAP_TIMER_INT_OVERFLOW, 0);
-}
-
-static inline void __omap_dm_timer_load_start(void __iomem *base, u32 ctrl,
- unsigned int load, int posted)
-{
- __omap_dm_timer_write(base, OMAP_TIMER_COUNTER_REG, load, posted);
- __omap_dm_timer_write(base, OMAP_TIMER_CTRL_REG, ctrl, posted);
-}
-
-static inline void __omap_dm_timer_int_enable(void __iomem *base,
- unsigned int value)
-{
- __omap_dm_timer_write(base, OMAP_TIMER_INT_EN_REG, value, 0);
- __omap_dm_timer_write(base, OMAP_TIMER_WAKEUP_EN_REG, value, 0);
-}
-
-static inline unsigned int __omap_dm_timer_read_counter(void __iomem *base,
- int posted)
-{
- return __omap_dm_timer_read(base, OMAP_TIMER_COUNTER_REG, posted);
-}
-
-static inline void __omap_dm_timer_write_status(void __iomem *base,
- unsigned int value)
-{
- __omap_dm_timer_write(base, OMAP_TIMER_STAT_REG, value, 0);
-}
#endif /* __ASM_ARCH_DMTIMER_H */
diff --git a/arch/arm/plat-omap/include/plat/gpio.h b/arch/arm/plat-omap/include/plat/gpio.h
index 91e8de3db08..ec97e00cb58 100644
--- a/arch/arm/plat-omap/include/plat/gpio.h
+++ b/arch/arm/plat-omap/include/plat/gpio.h
@@ -174,32 +174,12 @@ struct omap_gpio_dev_attr {
bool dbck_flag; /* dbck required or not - True for OMAP3&4 */
};
-struct omap_gpio_reg_offs {
- u16 revision;
- u16 direction;
- u16 datain;
- u16 dataout;
- u16 set_dataout;
- u16 clr_dataout;
- u16 irqstatus;
- u16 irqstatus2;
- u16 irqenable;
- u16 set_irqenable;
- u16 clr_irqenable;
- u16 debounce;
- u16 debounce_en;
-
- bool irqenable_inv;
-};
-
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 */
-
- struct omap_gpio_reg_offs *regs;
};
/* TODO: Analyze removing gpio_bank_count usage from driver code */
diff --git a/arch/arm/plat-omap/include/plat/i2c.h b/arch/arm/plat-omap/include/plat/i2c.h
index 7c22b9e10dc..878d632c409 100644
--- a/arch/arm/plat-omap/include/plat/i2c.h
+++ b/arch/arm/plat-omap/include/plat/i2c.h
@@ -22,7 +22,6 @@
#define __ASM__ARCH_OMAP_I2C_H
#include <linux/i2c.h>
-#include <linux/i2c-omap.h>
#if defined(CONFIG_I2C_OMAP) || defined(CONFIG_I2C_OMAP_MODULE)
extern int omap_register_i2c_bus(int bus_id, u32 clkrate,
@@ -47,13 +46,10 @@ static inline int omap_register_i2c_bus(int bus_id, u32 clkrate,
*/
struct omap_i2c_dev_attr {
u8 fifo_depth;
- u32 flags;
+ u8 flags;
};
void __init omap1_i2c_mux_pins(int bus_id);
void __init omap2_i2c_mux_pins(int bus_id);
-struct omap_hwmod;
-int omap_i2c_reset(struct omap_hwmod *oh);
-
#endif /* __ASM__ARCH_OMAP_I2C_H */
diff --git a/arch/arm/plat-omap/include/plat/irqs.h b/arch/arm/plat-omap/include/plat/irqs.h
index 926d25c780f..5a25098ea7e 100644
--- a/arch/arm/plat-omap/include/plat/irqs.h
+++ b/arch/arm/plat-omap/include/plat/irqs.h
@@ -407,19 +407,11 @@
#endif
#define TWL6030_IRQ_END (TWL6030_IRQ_BASE + TWL6030_BASE_NR_IRQS)
-#define TWL6040_CODEC_IRQ_BASE TWL6030_IRQ_END
-#ifdef CONFIG_TWL6040_CODEC
-#define TWL6040_CODEC_NR_IRQS 6
-#else
-#define TWL6040_CODEC_NR_IRQS 0
-#endif
-#define TWL6040_CODEC_IRQ_END (TWL6040_CODEC_IRQ_BASE + TWL6040_CODEC_NR_IRQS)
-
/* Total number of interrupts depends on the enabled blocks above */
-#if (TWL4030_GPIO_IRQ_END > TWL6040_CODEC_IRQ_END)
+#if (TWL4030_GPIO_IRQ_END > TWL6030_IRQ_END)
#define TWL_IRQ_END TWL4030_GPIO_IRQ_END
#else
-#define TWL_IRQ_END TWL6040_CODEC_IRQ_END
+#define TWL_IRQ_END TWL6030_IRQ_END
#endif
/* GPMC related */
@@ -436,11 +428,7 @@
#define INTCPS_NR_IRQS 96
#ifndef __ASSEMBLY__
-extern void __iomem *omap_irq_base;
-void omap1_init_irq(void);
-void omap2_init_irq(void);
-void omap3_init_irq(void);
-void ti816x_init_irq(void);
+extern void omap_init_irq(void);
extern int omap_irq_pending(void);
void omap_intc_save_context(void);
void omap_intc_restore_context(void);
diff --git a/arch/arm/plat-omap/include/plat/mcbsp.h b/arch/arm/plat-omap/include/plat/mcbsp.h
index 9882c657b2d..f8f690ab299 100644
--- a/arch/arm/plat-omap/include/plat/mcbsp.h
+++ b/arch/arm/plat-omap/include/plat/mcbsp.h
@@ -24,6 +24,7 @@
#ifndef __ASM_ARCH_OMAP_MCBSP_H
#define __ASM_ARCH_OMAP_MCBSP_H
+#include <linux/completion.h>
#include <linux/spinlock.h>
#include <mach/hardware.h>
@@ -33,7 +34,7 @@
#define OMAP_MCBSP_PLATFORM_DEVICE(port_nr) \
static struct platform_device omap_mcbsp##port_nr = { \
.name = "omap-mcbsp-dai", \
- .id = port_nr - 1, \
+ .id = OMAP_MCBSP##port_nr, \
}
#define MCBSP_CONFIG_TYPE2 0x2
@@ -332,6 +333,18 @@ struct omap_mcbsp_reg_cfg {
};
typedef enum {
+ OMAP_MCBSP1 = 0,
+ OMAP_MCBSP2,
+ OMAP_MCBSP3,
+ OMAP_MCBSP4,
+ OMAP_MCBSP5
+} omap_mcbsp_id;
+
+typedef int __bitwise omap_mcbsp_io_type_t;
+#define OMAP_MCBSP_IRQ_IO ((__force omap_mcbsp_io_type_t) 1)
+#define OMAP_MCBSP_POLL_IO ((__force omap_mcbsp_io_type_t) 2)
+
+typedef enum {
OMAP_MCBSP_WORD_8 = 0,
OMAP_MCBSP_WORD_12,
OMAP_MCBSP_WORD_16,
@@ -340,6 +353,38 @@ typedef enum {
OMAP_MCBSP_WORD_32,
} omap_mcbsp_word_length;
+typedef enum {
+ OMAP_MCBSP_CLK_RISING = 0,
+ OMAP_MCBSP_CLK_FALLING,
+} omap_mcbsp_clk_polarity;
+
+typedef enum {
+ OMAP_MCBSP_FS_ACTIVE_HIGH = 0,
+ OMAP_MCBSP_FS_ACTIVE_LOW,
+} omap_mcbsp_fs_polarity;
+
+typedef enum {
+ OMAP_MCBSP_CLK_STP_MODE_NO_DELAY = 0,
+ OMAP_MCBSP_CLK_STP_MODE_DELAY,
+} omap_mcbsp_clk_stp_mode;
+
+
+/******* SPI specific mode **********/
+typedef enum {
+ OMAP_MCBSP_SPI_MASTER = 0,
+ OMAP_MCBSP_SPI_SLAVE,
+} omap_mcbsp_spi_mode;
+
+struct omap_mcbsp_spi_cfg {
+ omap_mcbsp_spi_mode spi_mode;
+ omap_mcbsp_clk_polarity rx_clock_polarity;
+ omap_mcbsp_clk_polarity tx_clock_polarity;
+ omap_mcbsp_fs_polarity fsx_polarity;
+ u8 clk_div;
+ omap_mcbsp_clk_stp_mode clk_stp_mode;
+ omap_mcbsp_word_length word_length;
+};
+
/* Platform specific configuration */
struct omap_mcbsp_ops {
void (*request)(unsigned int);
@@ -377,13 +422,25 @@ struct omap_mcbsp {
void __iomem *io_base;
u8 id;
u8 free;
+ omap_mcbsp_word_length rx_word_length;
+ omap_mcbsp_word_length tx_word_length;
+ omap_mcbsp_io_type_t io_type; /* IRQ or poll */
+ /* IRQ based TX/RX */
int rx_irq;
int tx_irq;
/* DMA stuff */
u8 dma_rx_sync;
+ short dma_rx_lch;
u8 dma_tx_sync;
+ short dma_tx_lch;
+
+ /* Completion queues */
+ struct completion tx_irq_completion;
+ struct completion rx_irq_completion;
+ struct completion tx_dma_completion;
+ struct completion rx_dma_completion;
/* Protect the field .free, while checking if the mcbsp is in use */
spinlock_t lock;
@@ -442,9 +499,24 @@ int omap_mcbsp_request(unsigned int id);
void omap_mcbsp_free(unsigned int id);
void omap_mcbsp_start(unsigned int id, int tx, int rx);
void omap_mcbsp_stop(unsigned int id, int tx, int rx);
+void omap_mcbsp_xmit_word(unsigned int id, u32 word);
+u32 omap_mcbsp_recv_word(unsigned int id);
+
+int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer, unsigned int length);
+int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer, unsigned int length);
+int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word);
+int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 * word);
+
/* McBSP functional clock source changing function */
extern int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id);
+/* SPI specific API */
+void omap_mcbsp_set_spi_mode(unsigned int id, const struct omap_mcbsp_spi_cfg * spi_cfg);
+
+/* Polled read/write functions */
+int omap_mcbsp_pollread(unsigned int id, u16 * buf);
+int omap_mcbsp_pollwrite(unsigned int id, u16 buf);
+int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type);
/* McBSP signal muxing API */
void omap2_mcbsp1_mux_clkr_src(u8 mux);
diff --git a/arch/arm/plat-omap/include/plat/nand.h b/arch/arm/plat-omap/include/plat/nand.h
index 67fc5060183..d86d1ecf006 100644
--- a/arch/arm/plat-omap/include/plat/nand.h
+++ b/arch/arm/plat-omap/include/plat/nand.h
@@ -19,11 +19,15 @@ enum nand_io {
};
struct omap_nand_platform_data {
+ unsigned int options;
int cs;
+ int gpio_irq;
struct mtd_partition *parts;
struct gpmc_timings *gpmc_t;
int nr_parts;
- bool dev_ready;
+ int (*nand_setup)(void);
+ int (*dev_ready)(struct omap_nand_platform_data *);
+ int dma_channel;
int gpmc_irq;
enum nand_io xfer_type;
unsigned long phys_base;
diff --git a/arch/arm/plat-omap/include/plat/omap-pm.h b/arch/arm/plat-omap/include/plat/omap-pm.h
index 0840df813f4..c0a75205303 100644
--- a/arch/arm/plat-omap/include/plat/omap-pm.h
+++ b/arch/arm/plat-omap/include/plat/omap-pm.h
@@ -40,7 +40,11 @@
* framework starts. The "_if_" is to avoid name collisions with the
* PM idle-loop code.
*/
+#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
@@ -48,7 +52,11 @@ int __init omap_pm_if_early_init(void);
* 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/include/plat/omap4-keypad.h b/arch/arm/plat-omap/include/plat/omap4-keypad.h
index 9fe6c878323..2b1d9bc1eeb 100644
--- a/arch/arm/plat-omap/include/plat/omap4-keypad.h
+++ b/arch/arm/plat-omap/include/plat/omap4-keypad.h
@@ -10,6 +10,5 @@ struct omap4_keypad_platform_data {
u8 cols;
};
-extern int omap4_keyboard_init(struct omap4_keypad_platform_data *,
- struct omap_board_data *);
+extern int omap4_keyboard_init(struct omap4_keypad_platform_data *);
#endif
diff --git a/arch/arm/plat-omap/include/plat/omap_hwmod.h b/arch/arm/plat-omap/include/plat/omap_hwmod.h
index 0e329ca88a7..1adea9c6298 100644
--- a/arch/arm/plat-omap/include/plat/omap_hwmod.h
+++ b/arch/arm/plat-omap/include/plat/omap_hwmod.h
@@ -2,7 +2,6 @@
* omap_hwmod macros, structures
*
* Copyright (C) 2009-2011 Nokia Corporation
- * Copyright (C) 2011 Texas Instruments, Inc.
* Paul Walmsley
*
* Created in collaboration with (alphabetical order): BenoƮt Cousson,
@@ -78,13 +77,9 @@ 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)
-/* modulemode control type (SW or HW) */
-#define MODULEMODE_HWCTRL 1
-#define MODULEMODE_SWCTRL 2
-
-
/**
* struct omap_hwmod_mux_info - hwmod specific mux configuration
* @pads: array of omap_device_pad entries
@@ -103,7 +98,7 @@ struct omap_hwmod_mux_info {
/**
* struct omap_hwmod_irq_info - MPU IRQs used by the hwmod
* @name: name of the IRQ channel (module local name)
- * @irq: IRQ channel ID (should be non-negative except -1 = terminator)
+ * @irq_ch: IRQ channel ID
*
* @name should be something short, e.g., "tx" or "rx". It is for use
* by platform_get_resource_byname(). It is defined locally to the
@@ -111,13 +106,13 @@ struct omap_hwmod_mux_info {
*/
struct omap_hwmod_irq_info {
const char *name;
- s16 irq;
+ u16 irq;
};
/**
* struct omap_hwmod_dma_info - DMA channels used by the hwmod
* @name: name of the DMA channel (module local name)
- * @dma_req: DMA request ID (should be non-negative except -1 = terminator)
+ * @dma_req: DMA request ID
*
* @name should be something short, e.g., "tx" or "rx". It is for use
* by platform_get_resource_byname(). It is defined locally to the
@@ -125,7 +120,7 @@ struct omap_hwmod_irq_info {
*/
struct omap_hwmod_dma_info {
const char *name;
- s16 dma_req;
+ u16 dma_req;
};
/**
@@ -225,6 +220,7 @@ struct omap_hwmod_addr_space {
* @clk: interface clock: OMAP clock name
* @_clk: pointer to the interface struct clk (filled in at runtime)
* @fw: interface firewall data
+ * @addr_cnt: ARRAY_SIZE(@addr)
* @width: OCP data width
* @user: initiators using this interface (see OCP_USER_* macros above)
* @flags: OCP interface flags (see OCPIF_* macros above)
@@ -243,6 +239,7 @@ struct omap_hwmod_ocp_if {
union {
struct omap_hwmod_omap2_firewall omap2;
} fw;
+ u8 addr_cnt;
u8 width;
u8 user;
u8 flags;
@@ -261,7 +258,6 @@ struct omap_hwmod_ocp_if {
#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)
-#define MSTANDBY_SMART_WKUP (HWMOD_IDLEMODE_SMART_WKUP << MASTER_STANDBY_SHIFT)
/* omap_hwmod_sysconfig.sysc_flags capability flags */
#define SYSC_HAS_AUTOIDLE (1 << 0)
@@ -366,11 +362,9 @@ struct omap_hwmod_omap2_prcm {
* @submodule_wkdep_bit: bit shift of the WKDEP range
*/
struct omap_hwmod_omap4_prcm {
- u16 clkctrl_offs;
- u16 rstctrl_offs;
- u16 context_offs;
+ void __iomem *clkctrl_reg;
+ void __iomem *rstctrl_reg;
u8 submodule_wkdep_bit;
- u8 modulemode;
};
@@ -474,8 +468,8 @@ struct omap_hwmod_class {
* @name: name of the hwmod
* @class: struct omap_hwmod_class * to the class of this hwmod
* @od: struct omap_device currently associated with this hwmod (internal use)
- * @mpu_irqs: ptr to an array of MPU IRQs
- * @sdma_reqs: ptr to an array of System DMA request IDs
+ * @mpu_irqs: ptr to an array of MPU IRQs (see also mpu_irqs_cnt)
+ * @sdma_reqs: ptr to an array of System DMA request IDs (see sdma_reqs_cnt)
* @prcm: PRCM data pertaining to this hwmod
* @main_clk: main clock: OMAP clock name
* @_clk: pointer to the main struct clk (filled in at runtime)
@@ -488,6 +482,8 @@ 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)
+ * @mpu_irqs_cnt: number of @mpu_irqs
+ * @sdma_reqs_cnt: number of @sdma_reqs
* @opt_clks_cnt: number of @opt_clks
* @master_cnt: number of @master entries
* @slaves_cnt: number of @slave entries
@@ -523,8 +519,6 @@ struct omap_hwmod {
const char *main_clk;
struct clk *_clk;
struct omap_hwmod_opt_clk *opt_clks;
- char *clkdm_name;
- struct clockdomain *clkdm;
char *vdd_name;
struct voltagedomain *voltdm;
struct omap_hwmod_ocp_if **masters; /* connect to *_IA */
@@ -537,6 +531,8 @@ struct omap_hwmod {
u16 flags;
u8 _mpu_port_index;
u8 response_lat;
+ u8 mpu_irqs_cnt;
+ u8 sdma_reqs_cnt;
u8 rst_lines_cnt;
u8 opt_clks_cnt;
u8 masters_cnt;
@@ -576,7 +572,6 @@ void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
void omap_hwmod_write(u32 v, struct omap_hwmod *oh, u16 reg_offs);
u32 omap_hwmod_read(struct omap_hwmod *oh, u16 reg_offs);
-int omap_hwmod_softreset(struct omap_hwmod *oh);
int omap_hwmod_count_resources(struct omap_hwmod *oh);
int omap_hwmod_fill_resources(struct omap_hwmod *oh, struct resource *res);
diff --git a/arch/arm/plat-omap/include/plat/uncompress.h b/arch/arm/plat-omap/include/plat/uncompress.h
index a067484cc4a..ac4b60d9aa2 100644
--- a/arch/arm/plat-omap/include/plat/uncompress.h
+++ b/arch/arm/plat-omap/include/plat/uncompress.h
@@ -148,7 +148,6 @@ 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, cm_t3730);
DEBUG_LL_OMAP3(3, craneboard);
DEBUG_LL_OMAP3(3, devkit8000);
DEBUG_LL_OMAP3(3, igep0020);
diff --git a/arch/arm/plat-omap/iovmm.c b/arch/arm/plat-omap/iovmm.c
index c60737c49a3..83a37c54342 100644
--- a/arch/arm/plat-omap/iovmm.c
+++ b/arch/arm/plat-omap/iovmm.c
@@ -72,7 +72,7 @@ static size_t sgtable_len(const struct sg_table *sgt)
for_each_sg(sgt->sgl, sg, sgt->nents, i) {
size_t bytes;
- bytes = sg->length;
+ bytes = sg_dma_len(sg);
if (!iopgsz_ok(bytes)) {
pr_err("%s: sg[%d] not iommu pagesize(%x)\n",
@@ -198,7 +198,7 @@ static void *vmap_sg(const struct sg_table *sgt)
int err;
pa = sg_phys(sg);
- bytes = sg->length;
+ bytes = sg_dma_len(sg);
BUG_ON(bytes != PAGE_SIZE);
@@ -476,7 +476,7 @@ static int map_iovm_area(struct iommu *obj, struct iovm_struct *new,
struct iotlb_entry e;
pa = sg_phys(sg);
- bytes = sg->length;
+ bytes = sg_dma_len(sg);
flags &= ~IOVMF_PGSZ_MASK;
pgsz = bytes_to_iopgsz(bytes);
diff --git a/arch/arm/plat-omap/mcbsp.c b/arch/arm/plat-omap/mcbsp.c
index 6c62af10871..5587acf0eb2 100644
--- a/arch/arm/plat-omap/mcbsp.c
+++ b/arch/arm/plat-omap/mcbsp.c
@@ -16,6 +16,8 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/platform_device.h>
+#include <linux/wait.h>
+#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/err.h>
#include <linux/clk.h>
@@ -23,6 +25,7 @@
#include <linux/io.h>
#include <linux/slab.h>
+#include <plat/dma.h>
#include <plat/mcbsp.h>
#include <plat/omap_device.h>
#include <linux/pm_runtime.h>
@@ -133,6 +136,8 @@ static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)
irqst_spcr2);
/* Writing zero to XSYNC_ERR clears the IRQ */
MCBSP_WRITE(mcbsp_tx, SPCR2, MCBSP_READ_CACHE(mcbsp_tx, SPCR2));
+ } else {
+ complete(&mcbsp_tx->tx_irq_completion);
}
return IRQ_HANDLED;
@@ -151,11 +156,41 @@ static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id)
irqst_spcr1);
/* Writing zero to RSYNC_ERR clears the IRQ */
MCBSP_WRITE(mcbsp_rx, SPCR1, MCBSP_READ_CACHE(mcbsp_rx, SPCR1));
+ } else {
+ complete(&mcbsp_rx->rx_irq_completion);
}
return IRQ_HANDLED;
}
+static void omap_mcbsp_tx_dma_callback(int lch, u16 ch_status, void *data)
+{
+ struct omap_mcbsp *mcbsp_dma_tx = data;
+
+ dev_dbg(mcbsp_dma_tx->dev, "TX DMA callback : 0x%x\n",
+ MCBSP_READ(mcbsp_dma_tx, SPCR2));
+
+ /* We can free the channels */
+ omap_free_dma(mcbsp_dma_tx->dma_tx_lch);
+ mcbsp_dma_tx->dma_tx_lch = -1;
+
+ complete(&mcbsp_dma_tx->tx_dma_completion);
+}
+
+static void omap_mcbsp_rx_dma_callback(int lch, u16 ch_status, void *data)
+{
+ struct omap_mcbsp *mcbsp_dma_rx = data;
+
+ dev_dbg(mcbsp_dma_rx->dev, "RX DMA callback : 0x%x\n",
+ MCBSP_READ(mcbsp_dma_rx, SPCR2));
+
+ /* We can free the channels */
+ omap_free_dma(mcbsp_dma_rx->dma_rx_lch);
+ mcbsp_dma_rx->dma_rx_lch = -1;
+
+ complete(&mcbsp_dma_rx->rx_dma_completion);
+}
+
/*
* omap_mcbsp_config simply write a config to the
* appropriate McBSP.
@@ -723,6 +758,37 @@ static inline void omap_st_start(struct omap_mcbsp *mcbsp) {}
static inline void omap_st_stop(struct omap_mcbsp *mcbsp) {}
#endif
+/*
+ * We can choose between IRQ based or polled IO.
+ * This needs to be called before omap_mcbsp_request().
+ */
+int omap_mcbsp_set_io_type(unsigned int id, omap_mcbsp_io_type_t io_type)
+{
+ struct omap_mcbsp *mcbsp;
+
+ if (!omap_mcbsp_check_valid_id(id)) {
+ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+ return -ENODEV;
+ }
+ mcbsp = id_to_mcbsp_ptr(id);
+
+ spin_lock(&mcbsp->lock);
+
+ if (!mcbsp->free) {
+ dev_err(mcbsp->dev, "McBSP%d is currently in use\n",
+ mcbsp->id);
+ spin_unlock(&mcbsp->lock);
+ return -EINVAL;
+ }
+
+ mcbsp->io_type = io_type;
+
+ spin_unlock(&mcbsp->lock);
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_mcbsp_set_io_type);
+
int omap_mcbsp_request(unsigned int id)
{
struct omap_mcbsp *mcbsp;
@@ -767,24 +833,29 @@ int omap_mcbsp_request(unsigned int id)
MCBSP_WRITE(mcbsp, SPCR1, 0);
MCBSP_WRITE(mcbsp, SPCR2, 0);
- err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler,
- 0, "McBSP", (void *)mcbsp);
- if (err != 0) {
- dev_err(mcbsp->dev, "Unable to request TX IRQ %d "
- "for McBSP%d\n", mcbsp->tx_irq,
- mcbsp->id);
- goto err_clk_disable;
- }
-
- if (mcbsp->rx_irq) {
- err = request_irq(mcbsp->rx_irq,
- omap_mcbsp_rx_irq_handler,
- 0, "McBSP", (void *)mcbsp);
+ if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) {
+ /* We need to get IRQs here */
+ init_completion(&mcbsp->tx_irq_completion);
+ err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler,
+ 0, "McBSP", (void *)mcbsp);
if (err != 0) {
- dev_err(mcbsp->dev, "Unable to request RX IRQ %d "
- "for McBSP%d\n", mcbsp->rx_irq,
+ dev_err(mcbsp->dev, "Unable to request TX IRQ %d "
+ "for McBSP%d\n", mcbsp->tx_irq,
mcbsp->id);
- goto err_free_irq;
+ goto err_clk_disable;
+ }
+
+ if (mcbsp->rx_irq) {
+ init_completion(&mcbsp->rx_irq_completion);
+ err = request_irq(mcbsp->rx_irq,
+ omap_mcbsp_rx_irq_handler,
+ 0, "McBSP", (void *)mcbsp);
+ if (err != 0) {
+ dev_err(mcbsp->dev, "Unable to request RX IRQ %d "
+ "for McBSP%d\n", mcbsp->rx_irq,
+ mcbsp->id);
+ goto err_free_irq;
+ }
}
}
@@ -830,9 +901,12 @@ void omap_mcbsp_free(unsigned int id)
pm_runtime_put_sync(mcbsp->dev);
- if (mcbsp->rx_irq)
- free_irq(mcbsp->rx_irq, (void *)mcbsp);
- free_irq(mcbsp->tx_irq, (void *)mcbsp);
+ if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) {
+ /* Free IRQs */
+ if (mcbsp->rx_irq)
+ free_irq(mcbsp->rx_irq, (void *)mcbsp);
+ free_irq(mcbsp->tx_irq, (void *)mcbsp);
+ }
reg_cache = mcbsp->reg_cache;
@@ -869,6 +943,9 @@ void omap_mcbsp_start(unsigned int id, int tx, int rx)
if (cpu_is_omap34xx())
omap_st_start(mcbsp);
+ mcbsp->rx_word_length = (MCBSP_READ_CACHE(mcbsp, RCR1) >> 5) & 0x7;
+ mcbsp->tx_word_length = (MCBSP_READ_CACHE(mcbsp, XCR1) >> 5) & 0x7;
+
/* Only enable SRG, if McBSP is master */
w = MCBSP_READ_CACHE(mcbsp, PCR0);
if (w & (FSXM | FSRM | CLKXM | CLKRM))
@@ -966,32 +1043,484 @@ void omap_mcbsp_stop(unsigned int id, int tx, int rx)
}
EXPORT_SYMBOL(omap_mcbsp_stop);
+/* polled mcbsp i/o operations */
+int omap_mcbsp_pollwrite(unsigned int id, u16 buf)
+{
+ struct omap_mcbsp *mcbsp;
+
+ if (!omap_mcbsp_check_valid_id(id)) {
+ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+ return -ENODEV;
+ }
+
+ mcbsp = id_to_mcbsp_ptr(id);
+
+ MCBSP_WRITE(mcbsp, DXR1, buf);
+ /* if frame sync error - clear the error */
+ if (MCBSP_READ(mcbsp, SPCR2) & XSYNC_ERR) {
+ /* clear error */
+ MCBSP_WRITE(mcbsp, SPCR2, MCBSP_READ_CACHE(mcbsp, SPCR2));
+ /* resend */
+ return -1;
+ } else {
+ /* wait for transmit confirmation */
+ int attemps = 0;
+ while (!(MCBSP_READ(mcbsp, SPCR2) & XRDY)) {
+ if (attemps++ > 1000) {
+ MCBSP_WRITE(mcbsp, SPCR2,
+ MCBSP_READ_CACHE(mcbsp, SPCR2) &
+ (~XRST));
+ udelay(10);
+ MCBSP_WRITE(mcbsp, SPCR2,
+ MCBSP_READ_CACHE(mcbsp, SPCR2) |
+ (XRST));
+ udelay(10);
+ dev_err(mcbsp->dev, "Could not write to"
+ " McBSP%d Register\n", mcbsp->id);
+ return -2;
+ }
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_mcbsp_pollwrite);
+
+int omap_mcbsp_pollread(unsigned int id, u16 *buf)
+{
+ struct omap_mcbsp *mcbsp;
+
+ if (!omap_mcbsp_check_valid_id(id)) {
+ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+ return -ENODEV;
+ }
+ mcbsp = id_to_mcbsp_ptr(id);
+
+ /* if frame sync error - clear the error */
+ if (MCBSP_READ(mcbsp, SPCR1) & RSYNC_ERR) {
+ /* clear error */
+ MCBSP_WRITE(mcbsp, SPCR1, MCBSP_READ_CACHE(mcbsp, SPCR1));
+ /* resend */
+ return -1;
+ } else {
+ /* wait for receive confirmation */
+ int attemps = 0;
+ while (!(MCBSP_READ(mcbsp, SPCR1) & RRDY)) {
+ if (attemps++ > 1000) {
+ MCBSP_WRITE(mcbsp, SPCR1,
+ MCBSP_READ_CACHE(mcbsp, SPCR1) &
+ (~RRST));
+ udelay(10);
+ MCBSP_WRITE(mcbsp, SPCR1,
+ MCBSP_READ_CACHE(mcbsp, SPCR1) |
+ (RRST));
+ udelay(10);
+ dev_err(mcbsp->dev, "Could not read from"
+ " McBSP%d Register\n", mcbsp->id);
+ return -2;
+ }
+ }
+ }
+ *buf = MCBSP_READ(mcbsp, DRR1);
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_mcbsp_pollread);
+
+/*
+ * IRQ based word transmission.
+ */
+void omap_mcbsp_xmit_word(unsigned int id, u32 word)
+{
+ struct omap_mcbsp *mcbsp;
+ omap_mcbsp_word_length word_length;
+
+ if (!omap_mcbsp_check_valid_id(id)) {
+ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+ return;
+ }
+
+ mcbsp = id_to_mcbsp_ptr(id);
+ word_length = mcbsp->tx_word_length;
+
+ wait_for_completion(&mcbsp->tx_irq_completion);
+
+ if (word_length > OMAP_MCBSP_WORD_16)
+ MCBSP_WRITE(mcbsp, DXR2, word >> 16);
+ MCBSP_WRITE(mcbsp, DXR1, word & 0xffff);
+}
+EXPORT_SYMBOL(omap_mcbsp_xmit_word);
+
+u32 omap_mcbsp_recv_word(unsigned int id)
+{
+ struct omap_mcbsp *mcbsp;
+ u16 word_lsb, word_msb = 0;
+ omap_mcbsp_word_length word_length;
+
+ if (!omap_mcbsp_check_valid_id(id)) {
+ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+ return -ENODEV;
+ }
+ mcbsp = id_to_mcbsp_ptr(id);
+
+ word_length = mcbsp->rx_word_length;
+
+ wait_for_completion(&mcbsp->rx_irq_completion);
+
+ if (word_length > OMAP_MCBSP_WORD_16)
+ word_msb = MCBSP_READ(mcbsp, DRR2);
+ word_lsb = MCBSP_READ(mcbsp, DRR1);
+
+ return (word_lsb | (word_msb << 16));
+}
+EXPORT_SYMBOL(omap_mcbsp_recv_word);
+
+int omap_mcbsp_spi_master_xmit_word_poll(unsigned int id, u32 word)
+{
+ struct omap_mcbsp *mcbsp;
+ omap_mcbsp_word_length tx_word_length;
+ omap_mcbsp_word_length rx_word_length;
+ u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
+
+ if (!omap_mcbsp_check_valid_id(id)) {
+ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+ return -ENODEV;
+ }
+ mcbsp = id_to_mcbsp_ptr(id);
+ tx_word_length = mcbsp->tx_word_length;
+ rx_word_length = mcbsp->rx_word_length;
+
+ if (tx_word_length != rx_word_length)
+ return -EINVAL;
+
+ /* First we wait for the transmitter to be ready */
+ spcr2 = MCBSP_READ(mcbsp, SPCR2);
+ while (!(spcr2 & XRDY)) {
+ spcr2 = MCBSP_READ(mcbsp, SPCR2);
+ if (attempts++ > 1000) {
+ /* We must reset the transmitter */
+ MCBSP_WRITE(mcbsp, SPCR2,
+ MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XRST));
+ udelay(10);
+ MCBSP_WRITE(mcbsp, SPCR2,
+ MCBSP_READ_CACHE(mcbsp, SPCR2) | XRST);
+ udelay(10);
+ dev_err(mcbsp->dev, "McBSP%d transmitter not "
+ "ready\n", mcbsp->id);
+ return -EAGAIN;
+ }
+ }
+
+ /* Now we can push the data */
+ if (tx_word_length > OMAP_MCBSP_WORD_16)
+ MCBSP_WRITE(mcbsp, DXR2, word >> 16);
+ MCBSP_WRITE(mcbsp, DXR1, word & 0xffff);
+
+ /* We wait for the receiver to be ready */
+ spcr1 = MCBSP_READ(mcbsp, SPCR1);
+ while (!(spcr1 & RRDY)) {
+ spcr1 = MCBSP_READ(mcbsp, SPCR1);
+ if (attempts++ > 1000) {
+ /* We must reset the receiver */
+ MCBSP_WRITE(mcbsp, SPCR1,
+ MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RRST));
+ udelay(10);
+ MCBSP_WRITE(mcbsp, SPCR1,
+ MCBSP_READ_CACHE(mcbsp, SPCR1) | RRST);
+ udelay(10);
+ dev_err(mcbsp->dev, "McBSP%d receiver not "
+ "ready\n", mcbsp->id);
+ return -EAGAIN;
+ }
+ }
+
+ /* Receiver is ready, let's read the dummy data */
+ if (rx_word_length > OMAP_MCBSP_WORD_16)
+ word_msb = MCBSP_READ(mcbsp, DRR2);
+ word_lsb = MCBSP_READ(mcbsp, DRR1);
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_mcbsp_spi_master_xmit_word_poll);
+
+int omap_mcbsp_spi_master_recv_word_poll(unsigned int id, u32 *word)
+{
+ struct omap_mcbsp *mcbsp;
+ u32 clock_word = 0;
+ omap_mcbsp_word_length tx_word_length;
+ omap_mcbsp_word_length rx_word_length;
+ u16 spcr2, spcr1, attempts = 0, word_lsb, word_msb = 0;
+
+ if (!omap_mcbsp_check_valid_id(id)) {
+ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+ return -ENODEV;
+ }
+
+ mcbsp = id_to_mcbsp_ptr(id);
+
+ tx_word_length = mcbsp->tx_word_length;
+ rx_word_length = mcbsp->rx_word_length;
+
+ if (tx_word_length != rx_word_length)
+ return -EINVAL;
+
+ /* First we wait for the transmitter to be ready */
+ spcr2 = MCBSP_READ(mcbsp, SPCR2);
+ while (!(spcr2 & XRDY)) {
+ spcr2 = MCBSP_READ(mcbsp, SPCR2);
+ if (attempts++ > 1000) {
+ /* We must reset the transmitter */
+ MCBSP_WRITE(mcbsp, SPCR2,
+ MCBSP_READ_CACHE(mcbsp, SPCR2) & (~XRST));
+ udelay(10);
+ MCBSP_WRITE(mcbsp, SPCR2,
+ MCBSP_READ_CACHE(mcbsp, SPCR2) | XRST);
+ udelay(10);
+ dev_err(mcbsp->dev, "McBSP%d transmitter not "
+ "ready\n", mcbsp->id);
+ return -EAGAIN;
+ }
+ }
+
+ /* We first need to enable the bus clock */
+ if (tx_word_length > OMAP_MCBSP_WORD_16)
+ MCBSP_WRITE(mcbsp, DXR2, clock_word >> 16);
+ MCBSP_WRITE(mcbsp, DXR1, clock_word & 0xffff);
+
+ /* We wait for the receiver to be ready */
+ spcr1 = MCBSP_READ(mcbsp, SPCR1);
+ while (!(spcr1 & RRDY)) {
+ spcr1 = MCBSP_READ(mcbsp, SPCR1);
+ if (attempts++ > 1000) {
+ /* We must reset the receiver */
+ MCBSP_WRITE(mcbsp, SPCR1,
+ MCBSP_READ_CACHE(mcbsp, SPCR1) & (~RRST));
+ udelay(10);
+ MCBSP_WRITE(mcbsp, SPCR1,
+ MCBSP_READ_CACHE(mcbsp, SPCR1) | RRST);
+ udelay(10);
+ dev_err(mcbsp->dev, "McBSP%d receiver not "
+ "ready\n", mcbsp->id);
+ return -EAGAIN;
+ }
+ }
+
+ /* Receiver is ready, there is something for us */
+ if (rx_word_length > OMAP_MCBSP_WORD_16)
+ word_msb = MCBSP_READ(mcbsp, DRR2);
+ word_lsb = MCBSP_READ(mcbsp, DRR1);
+
+ word[0] = (word_lsb | (word_msb << 16));
+
+ return 0;
+}
+EXPORT_SYMBOL(omap_mcbsp_spi_master_recv_word_poll);
+
/*
- * The following functions are only required on an OMAP1-only build.
- * mach-omap2/mcbsp.c contains the real functions
+ * Simple DMA based buffer rx/tx routines.
+ * Nothing fancy, just a single buffer tx/rx through DMA.
+ * The DMA resources are released once the transfer is done.
+ * For anything fancier, you should use your own customized DMA
+ * routines and callbacks.
*/
-#ifndef CONFIG_ARCH_OMAP2PLUS
-int omap2_mcbsp_set_clks_src(u8 id, u8 fck_src_id)
+int omap_mcbsp_xmit_buffer(unsigned int id, dma_addr_t buffer,
+ unsigned int length)
{
- WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
- __func__);
- return -EINVAL;
+ struct omap_mcbsp *mcbsp;
+ int dma_tx_ch;
+ int src_port = 0;
+ int dest_port = 0;
+ int sync_dev = 0;
+
+ if (!omap_mcbsp_check_valid_id(id)) {
+ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+ return -ENODEV;
+ }
+ mcbsp = id_to_mcbsp_ptr(id);
+
+ if (omap_request_dma(mcbsp->dma_tx_sync, "McBSP TX",
+ omap_mcbsp_tx_dma_callback,
+ mcbsp,
+ &dma_tx_ch)) {
+ dev_err(mcbsp->dev, " Unable to request DMA channel for "
+ "McBSP%d TX. Trying IRQ based TX\n",
+ mcbsp->id);
+ return -EAGAIN;
+ }
+ mcbsp->dma_tx_lch = dma_tx_ch;
+
+ dev_err(mcbsp->dev, "McBSP%d TX DMA on channel %d\n", mcbsp->id,
+ dma_tx_ch);
+
+ init_completion(&mcbsp->tx_dma_completion);
+
+ if (cpu_class_is_omap1()) {
+ src_port = OMAP_DMA_PORT_TIPB;
+ dest_port = OMAP_DMA_PORT_EMIFF;
+ }
+ if (cpu_class_is_omap2())
+ sync_dev = mcbsp->dma_tx_sync;
+
+ omap_set_dma_transfer_params(mcbsp->dma_tx_lch,
+ OMAP_DMA_DATA_TYPE_S16,
+ length >> 1, 1,
+ OMAP_DMA_SYNC_ELEMENT,
+ sync_dev, 0);
+
+ omap_set_dma_dest_params(mcbsp->dma_tx_lch,
+ src_port,
+ OMAP_DMA_AMODE_CONSTANT,
+ mcbsp->phys_base + OMAP_MCBSP_REG_DXR1,
+ 0, 0);
+
+ omap_set_dma_src_params(mcbsp->dma_tx_lch,
+ dest_port,
+ OMAP_DMA_AMODE_POST_INC,
+ buffer,
+ 0, 0);
+
+ omap_start_dma(mcbsp->dma_tx_lch);
+ wait_for_completion(&mcbsp->tx_dma_completion);
+
+ return 0;
}
+EXPORT_SYMBOL(omap_mcbsp_xmit_buffer);
-void omap2_mcbsp1_mux_clkr_src(u8 mux)
+int omap_mcbsp_recv_buffer(unsigned int id, dma_addr_t buffer,
+ unsigned int length)
{
- WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
- __func__);
- return;
+ struct omap_mcbsp *mcbsp;
+ int dma_rx_ch;
+ int src_port = 0;
+ int dest_port = 0;
+ int sync_dev = 0;
+
+ if (!omap_mcbsp_check_valid_id(id)) {
+ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+ return -ENODEV;
+ }
+ mcbsp = id_to_mcbsp_ptr(id);
+
+ if (omap_request_dma(mcbsp->dma_rx_sync, "McBSP RX",
+ omap_mcbsp_rx_dma_callback,
+ mcbsp,
+ &dma_rx_ch)) {
+ dev_err(mcbsp->dev, "Unable to request DMA channel for "
+ "McBSP%d RX. Trying IRQ based RX\n",
+ mcbsp->id);
+ return -EAGAIN;
+ }
+ mcbsp->dma_rx_lch = dma_rx_ch;
+
+ dev_err(mcbsp->dev, "McBSP%d RX DMA on channel %d\n", mcbsp->id,
+ dma_rx_ch);
+
+ init_completion(&mcbsp->rx_dma_completion);
+
+ if (cpu_class_is_omap1()) {
+ src_port = OMAP_DMA_PORT_TIPB;
+ dest_port = OMAP_DMA_PORT_EMIFF;
+ }
+ if (cpu_class_is_omap2())
+ sync_dev = mcbsp->dma_rx_sync;
+
+ omap_set_dma_transfer_params(mcbsp->dma_rx_lch,
+ OMAP_DMA_DATA_TYPE_S16,
+ length >> 1, 1,
+ OMAP_DMA_SYNC_ELEMENT,
+ sync_dev, 0);
+
+ omap_set_dma_src_params(mcbsp->dma_rx_lch,
+ src_port,
+ OMAP_DMA_AMODE_CONSTANT,
+ mcbsp->phys_base + OMAP_MCBSP_REG_DRR1,
+ 0, 0);
+
+ omap_set_dma_dest_params(mcbsp->dma_rx_lch,
+ dest_port,
+ OMAP_DMA_AMODE_POST_INC,
+ buffer,
+ 0, 0);
+
+ omap_start_dma(mcbsp->dma_rx_lch);
+ wait_for_completion(&mcbsp->rx_dma_completion);
+
+ return 0;
}
+EXPORT_SYMBOL(omap_mcbsp_recv_buffer);
-void omap2_mcbsp1_mux_fsr_src(u8 mux)
+/*
+ * SPI wrapper.
+ * Since SPI setup is much simpler than the generic McBSP one,
+ * this wrapper just need an omap_mcbsp_spi_cfg structure as an input.
+ * Once this is done, you can call omap_mcbsp_start().
+ */
+void omap_mcbsp_set_spi_mode(unsigned int id,
+ const struct omap_mcbsp_spi_cfg *spi_cfg)
{
- WARN(1, "%s: should never be called on an OMAP1-only kernel\n",
- __func__);
- return;
+ struct omap_mcbsp *mcbsp;
+ struct omap_mcbsp_reg_cfg mcbsp_cfg;
+
+ if (!omap_mcbsp_check_valid_id(id)) {
+ printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+ return;
+ }
+ mcbsp = id_to_mcbsp_ptr(id);
+
+ memset(&mcbsp_cfg, 0, sizeof(struct omap_mcbsp_reg_cfg));
+
+ /* SPI has only one frame */
+ mcbsp_cfg.rcr1 |= (RWDLEN1(spi_cfg->word_length) | RFRLEN1(0));
+ mcbsp_cfg.xcr1 |= (XWDLEN1(spi_cfg->word_length) | XFRLEN1(0));
+
+ /* Clock stop mode */
+ if (spi_cfg->clk_stp_mode == OMAP_MCBSP_CLK_STP_MODE_NO_DELAY)
+ mcbsp_cfg.spcr1 |= (1 << 12);
+ else
+ mcbsp_cfg.spcr1 |= (3 << 11);
+
+ /* Set clock parities */
+ if (spi_cfg->rx_clock_polarity == OMAP_MCBSP_CLK_RISING)
+ mcbsp_cfg.pcr0 |= CLKRP;
+ else
+ mcbsp_cfg.pcr0 &= ~CLKRP;
+
+ if (spi_cfg->tx_clock_polarity == OMAP_MCBSP_CLK_RISING)
+ mcbsp_cfg.pcr0 &= ~CLKXP;
+ else
+ mcbsp_cfg.pcr0 |= CLKXP;
+
+ /* Set SCLKME to 0 and CLKSM to 1 */
+ mcbsp_cfg.pcr0 &= ~SCLKME;
+ mcbsp_cfg.srgr2 |= CLKSM;
+
+ /* Set FSXP */
+ if (spi_cfg->fsx_polarity == OMAP_MCBSP_FS_ACTIVE_HIGH)
+ mcbsp_cfg.pcr0 &= ~FSXP;
+ else
+ mcbsp_cfg.pcr0 |= FSXP;
+
+ if (spi_cfg->spi_mode == OMAP_MCBSP_SPI_MASTER) {
+ mcbsp_cfg.pcr0 |= CLKXM;
+ mcbsp_cfg.srgr1 |= CLKGDV(spi_cfg->clk_div - 1);
+ mcbsp_cfg.pcr0 |= FSXM;
+ mcbsp_cfg.srgr2 &= ~FSGM;
+ mcbsp_cfg.xcr2 |= XDATDLY(1);
+ mcbsp_cfg.rcr2 |= RDATDLY(1);
+ } else {
+ mcbsp_cfg.pcr0 &= ~CLKXM;
+ mcbsp_cfg.srgr1 |= CLKGDV(1);
+ mcbsp_cfg.pcr0 &= ~FSXM;
+ mcbsp_cfg.xcr2 &= ~XDATDLY(3);
+ mcbsp_cfg.rcr2 &= ~RDATDLY(3);
+ }
+
+ mcbsp_cfg.xcr2 &= ~XPHASE;
+ mcbsp_cfg.rcr2 &= ~RPHASE;
+
+ omap_mcbsp_config(id, &mcbsp_cfg);
}
-#endif
+EXPORT_SYMBOL(omap_mcbsp_set_spi_mode);
#ifdef CONFIG_ARCH_OMAP3
#define max_thres(m) (mcbsp->pdata->buffer_size)
@@ -1304,6 +1833,8 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
spin_lock_init(&mcbsp->lock);
mcbsp->id = id + 1;
mcbsp->free = true;
+ mcbsp->dma_tx_lch = -1;
+ mcbsp->dma_rx_lch = -1;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
if (!res) {
@@ -1329,6 +1860,9 @@ static int __devinit omap_mcbsp_probe(struct platform_device *pdev)
else
mcbsp->phys_dma_base = res->start;
+ /* Default I/O is IRQ based */
+ mcbsp->io_type = OMAP_MCBSP_IRQ_IO;
+
mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx");
mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");
diff --git a/arch/arm/plat-omap/omap_device.c b/arch/arm/plat-omap/omap_device.c
index be45147651c..49fc0df0c21 100644
--- a/arch/arm/plat-omap/omap_device.c
+++ b/arch/arm/plat-omap/omap_device.c
@@ -236,71 +236,61 @@ static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
return 0;
}
-static void _add_clkdev(struct omap_device *od, const char *clk_alias,
- const char *clk_name)
+static inline struct omap_device *_find_by_pdev(struct platform_device *pdev)
{
- struct clk *r;
- struct clk_lookup *l;
-
- if (!clk_alias || !clk_name)
- return;
-
- pr_debug("omap_device: %s: Creating %s -> %s\n",
- dev_name(&od->pdev.dev), clk_alias, clk_name);
-
- r = clk_get_sys(dev_name(&od->pdev.dev), clk_alias);
- if (!IS_ERR(r)) {
- pr_warning("omap_device: %s: alias %s already exists\n",
- dev_name(&od->pdev.dev), clk_alias);
- clk_put(r);
- return;
- }
-
- r = omap_clk_get_by_name(clk_name);
- if (IS_ERR(r)) {
- pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
- dev_name(&od->pdev.dev), clk_name);
- return;
- }
-
- l = clkdev_alloc(r, clk_alias, dev_name(&od->pdev.dev));
- if (!l) {
- pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
- dev_name(&od->pdev.dev), clk_alias);
- return;
- }
-
- clkdev_add(l);
+ return container_of(pdev, struct omap_device, pdev);
}
/**
- * _add_hwmod_clocks_clkdev - Add clkdev entry for hwmod optional clocks
- * and main clock
+ * _add_optional_clock_clkdev - Add clkdev entry for hwmod optional clocks
* @od: struct omap_device *od
- * @oh: struct omap_hwmod *oh
*
- * For the main clock and every optional clock present per hwmod per
- * omap_device, this function adds an entry in the clkdev table of the
- * form <dev-id=dev_name, con-id=role> if it does not exist already.
+ * For every optional clock present per hwmod per omap_device, this function
+ * adds an entry in the clkdev table of the form <dev-id=dev_name, con-id=role>
+ * if it does not exist already.
*
* The function is called from inside omap_device_build_ss(), after
* omap_device_register.
*
* This allows drivers to get a pointer to its optional clocks based on its role
* by calling clk_get(<dev*>, <role>).
- * In the case of the main clock, a "fck" alias is used.
*
* No return value.
*/
-static void _add_hwmod_clocks_clkdev(struct omap_device *od,
- struct omap_hwmod *oh)
+static void _add_optional_clock_clkdev(struct omap_device *od,
+ struct omap_hwmod *oh)
{
int i;
- _add_clkdev(od, "fck", oh->main_clk);
+ for (i = 0; i < oh->opt_clks_cnt; i++) {
+ struct omap_hwmod_opt_clk *oc;
+ struct clk *r;
+ struct clk_lookup *l;
+
+ oc = &oh->opt_clks[i];
+
+ if (!oc->_clk)
+ continue;
+
+ r = clk_get_sys(dev_name(&od->pdev.dev), oc->role);
+ if (!IS_ERR(r))
+ continue; /* clkdev entry exists */
- for (i = 0; i < oh->opt_clks_cnt; i++)
- _add_clkdev(od, oh->opt_clks[i].role, oh->opt_clks[i].clk);
+ r = omap_clk_get_by_name((char *)oc->clk);
+ if (IS_ERR(r)) {
+ pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
+ dev_name(&od->pdev.dev), oc->clk);
+ continue;
+ }
+
+ l = clkdev_alloc(r, oc->role, dev_name(&od->pdev.dev));
+ if (!l) {
+ pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
+ dev_name(&od->pdev.dev), oc->role);
+ return;
+ }
+ clkdev_add(l);
+ }
}
@@ -326,7 +316,7 @@ u32 omap_device_get_context_loss_count(struct platform_device *pdev)
struct omap_device *od;
u32 ret = 0;
- od = to_omap_device(pdev);
+ od = _find_by_pdev(pdev);
if (od->hwmods_cnt)
ret = omap_hwmod_get_context_loss_count(od->hwmods[0]);
@@ -507,7 +497,7 @@ struct omap_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
for (i = 0; i < oh_cnt; i++) {
hwmods[i]->od = od;
- _add_hwmod_clocks_clkdev(od, hwmods[i]);
+ _add_optional_clock_clkdev(od, hwmods[i]);
}
if (ret)
@@ -621,7 +611,7 @@ int omap_device_enable(struct platform_device *pdev)
int ret;
struct omap_device *od;
- od = to_omap_device(pdev);
+ od = _find_by_pdev(pdev);
if (od->_state == OMAP_DEVICE_STATE_ENABLED) {
WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
@@ -660,7 +650,7 @@ int omap_device_idle(struct platform_device *pdev)
int ret;
struct omap_device *od;
- od = to_omap_device(pdev);
+ od = _find_by_pdev(pdev);
if (od->_state != OMAP_DEVICE_STATE_ENABLED) {
WARN(1, "omap_device: %s.%d: %s() called from invalid state %d\n",
@@ -691,7 +681,7 @@ int omap_device_shutdown(struct platform_device *pdev)
int ret, i;
struct omap_device *od;
- od = to_omap_device(pdev);
+ od = _find_by_pdev(pdev);
if (od->_state != OMAP_DEVICE_STATE_ENABLED &&
od->_state != OMAP_DEVICE_STATE_IDLE) {
@@ -732,7 +722,7 @@ int omap_device_align_pm_lat(struct platform_device *pdev,
int ret = -EINVAL;
struct omap_device *od;
- od = to_omap_device(pdev);
+ od = _find_by_pdev(pdev);
if (new_wakeup_lat_limit == od->dev_wakeup_lat)
return 0;