Linux-ARM-Kernel Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 2/8] ARM: etm: Don't limit tracing to only non-secure code.
From: Arve Hjønnevåg @ 2011-02-15  6:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1296701663-12168-1-git-send-email-arve@android.com>

On some systems kernel code is considered secure, and this code
already limits tracing to the kernel text segment which results
in no trace data.

Signed-off-by: Arve Hj?nnev?g <arve@android.com>
---
 arch/arm/kernel/etm.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index d4ec368..6e15c48 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -55,7 +55,7 @@ static inline bool trace_isrunning(struct tracectx *t)
 static int etm_setup_address_range(struct tracectx *t, int n,
 		unsigned long start, unsigned long end, int exclude, int data)
 {
-	u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_NSONLY | \
+	u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_IGNSECURITY |
 		    ETMAAT_NOVALCMP;
 
 	if (n < 1 || n > t->ncmppairs)
-- 
1.7.3.1

^ permalink raw reply related

* [PATCH 3/8] ARM: etm: Don't try to clear the buffer full status after reading the buffer
From: Arve Hjønnevåg @ 2011-02-15  6:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1296701663-12168-1-git-send-email-arve@android.com>

If the write address was at the end of the buffer, toggling the trace
capture bit would set the RAM-full status instead of clearing it, and
if any of the stop bits in the formatter is set toggling the trace
capture bit may not do anything.

Instead use the read position to find out if the data has already
been returned.

This also fixes the read function so it works when the trace buffer is
larger than the buffer passed in from user space. The old version
would reset the trace buffer pointers after every read, so the second
call to read would always return 0.

Signed-off-by: Arve Hj?nnev?g <arve@android.com>
---
 arch/arm/kernel/etm.c |   58 ++++++++++++++++++++++---------------------------
 1 files changed, 26 insertions(+), 32 deletions(-)

diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 6e15c48..bc7d8f2 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -91,6 +91,7 @@ static int trace_start(struct tracectx *t)
 
 	etb_unlock(t);
 
+	etb_writel(t, 0, ETBR_WRITEADDR);
 	etb_writel(t, 0, ETBR_FORMATTERCTRL);
 	etb_writel(t, 1, ETBR_CTRL);
 
@@ -184,24 +185,15 @@ static int trace_stop(struct tracectx *t)
 static int etb_getdatalen(struct tracectx *t)
 {
 	u32 v;
-	int rp, wp;
+	int wp;
 
 	v = etb_readl(t, ETBR_STATUS);
 
 	if (v & 1)
 		return t->etb_bufsz;
 
-	rp = etb_readl(t, ETBR_READADDR);
 	wp = etb_readl(t, ETBR_WRITEADDR);
-
-	if (rp > wp) {
-		etb_writel(t, 0, ETBR_READADDR);
-		etb_writel(t, 0, ETBR_WRITEADDR);
-
-		return 0;
-	}
-
-	return wp - rp;
+	return wp;
 }
 
 /* sysrq+v will always stop the running trace and leave it at that */
@@ -234,14 +226,6 @@ static void etm_dump(void)
 		printk("%08x", cpu_to_be32(etb_readl(t, ETBR_READMEM)));
 	printk(KERN_INFO "\n--- ETB buffer end ---\n");
 
-	/* deassert the overflow bit */
-	etb_writel(t, 1, ETBR_CTRL);
-	etb_writel(t, 0, ETBR_CTRL);
-
-	etb_writel(t, 0, ETBR_TRIGGERCOUNT);
-	etb_writel(t, 0, ETBR_READADDR);
-	etb_writel(t, 0, ETBR_WRITEADDR);
-
 	etb_lock(t);
 }
 
@@ -275,6 +259,10 @@ static ssize_t etb_read(struct file *file, char __user *data,
 	struct tracectx *t = file->private_data;
 	u32 first = 0;
 	u32 *buf;
+	int wpos;
+	int skip;
+	long wlength;
+	loff_t pos = *ppos;
 
 	mutex_lock(&t->mutex);
 
@@ -289,28 +277,34 @@ static ssize_t etb_read(struct file *file, char __user *data,
 	if (total == t->etb_bufsz)
 		first = etb_readl(t, ETBR_WRITEADDR);
 
+	if (pos > total * 4) {
+		skip = 0;
+		wpos = total;
+	} else {
+		skip = (int)pos % 4;
+		wpos = (int)pos / 4;
+	}
+	total -= wpos;
+	first = (first + wpos) % t->etb_bufsz;
+
 	etb_writel(t, first, ETBR_READADDR);
 
-	length = min(total * 4, (int)len);
-	buf = vmalloc(length);
+	wlength = min(total, DIV_ROUND_UP(skip + (int)len, 4));
+	length = min(total * 4 - skip, (int)len);
+	buf = vmalloc(wlength * 4);
 
-	dev_dbg(t->dev, "ETB buffer length: %d\n", total);
+	dev_dbg(t->dev, "ETB read %ld bytes to %lld from %ld words at %d\n",
+		length, pos, wlength, first);
+	dev_dbg(t->dev, "ETB buffer length: %d\n", total + wpos);
 	dev_dbg(t->dev, "ETB status reg: %x\n", etb_readl(t, ETBR_STATUS));
-	for (i = 0; i < length / 4; i++)
+	for (i = 0; i < wlength; i++)
 		buf[i] = etb_readl(t, ETBR_READMEM);
 
-	/* the only way to deassert overflow bit in ETB status is this */
-	etb_writel(t, 1, ETBR_CTRL);
-	etb_writel(t, 0, ETBR_CTRL);
-
-	etb_writel(t, 0, ETBR_WRITEADDR);
-	etb_writel(t, 0, ETBR_READADDR);
-	etb_writel(t, 0, ETBR_TRIGGERCOUNT);
-
 	etb_lock(t);
 
-	length -= copy_to_user(data, buf, length);
+	length -= copy_to_user(data, (u8 *)buf + skip, length);
 	vfree(buf);
+	*ppos = pos + length;
 
 out:
 	mutex_unlock(&t->mutex);
-- 
1.7.3.1

^ permalink raw reply related

* [PATCH 4/8] ARM: etm: Allow range selection
From: Arve Hjønnevåg @ 2011-02-15  6:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1296701663-12168-1-git-send-email-arve@android.com>

Trace kernel text segment by default as before, allow tracing of other
ranges by writing a range to /sys/devices/etm/trace_range, or to trace
everything by writing 0 0.

Signed-off-by: Arve Hj?nnev?g <arve@android.com>
---
 arch/arm/kernel/etm.c |   49 ++++++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 46 insertions(+), 3 deletions(-)

diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index bc7d8f2..8a1c422 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -40,12 +40,17 @@ struct tracectx {
 	unsigned long	flags;
 	int		ncmppairs;
 	int		etm_portsz;
+	unsigned long	range_start;
+	unsigned long	range_end;
 	struct device	*dev;
 	struct clk	*emu_clk;
 	struct mutex	mutex;
 };
 
-static struct tracectx tracer;
+static struct tracectx tracer = {
+	.range_start = (unsigned long)_stext,
+	.range_end = (unsigned long)_etext,
+};
 
 static inline bool trace_isrunning(struct tracectx *t)
 {
@@ -115,8 +120,12 @@ static int trace_start(struct tracectx *t)
 		return -EFAULT;
 	}
 
-	etm_setup_address_range(t, 1, (unsigned long)_stext,
-			(unsigned long)_etext, 0, 0);
+	if (t->range_start || t->range_end)
+		etm_setup_address_range(t, 1,
+					t->range_start, t->range_end, 0, 0);
+	else
+		etm_writel(t, ETMTE_INCLEXCL, ETMR_TRACEENCTRL);
+
 	etm_writel(t, 0, ETMR_TRACEENCTRL2);
 	etm_writel(t, 0, ETMR_TRACESSCTRL);
 	etm_writel(t, 0x6f, ETMR_TRACEENEVT);
@@ -525,6 +534,35 @@ static ssize_t trace_mode_store(struct kobject *kobj,
 static struct kobj_attribute trace_mode_attr =
 	__ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store);
 
+static ssize_t trace_range_show(struct kobject *kobj,
+				  struct kobj_attribute *attr,
+				  char *buf)
+{
+	return sprintf(buf, "%08lx %08lx\n",
+			tracer.range_start, tracer.range_end);
+}
+
+static ssize_t trace_range_store(struct kobject *kobj,
+				   struct kobj_attribute *attr,
+				   const char *buf, size_t n)
+{
+	unsigned long range_start, range_end;
+
+	if (sscanf(buf, "%lx %lx", &range_start, &range_end) != 2)
+		return -EINVAL;
+
+	mutex_lock(&tracer.mutex);
+	tracer.range_start = range_start;
+	tracer.range_end = range_end;
+	mutex_unlock(&tracer.mutex);
+
+	return n;
+}
+
+
+static struct kobj_attribute trace_range_attr =
+	__ATTR(trace_range, 0644, trace_range_show, trace_range_store);
+
 static int __init etm_probe(struct amba_device *dev, struct amba_id *id)
 {
 	struct tracectx *t = &tracer;
@@ -576,6 +614,10 @@ static int __init etm_probe(struct amba_device *dev, struct amba_id *id)
 	if (ret)
 		dev_dbg(&dev->dev, "Failed to create trace_mode in sysfs\n");
 
+	ret = sysfs_create_file(&dev->dev.kobj, &trace_range_attr.attr);
+	if (ret)
+		dev_dbg(&dev->dev, "Failed to create trace_range in sysfs\n");
+
 	dev_dbg(t->dev, "ETM AMBA driver initialized.\n");
 
 out:
@@ -605,6 +647,7 @@ static int etm_remove(struct amba_device *dev)
 	sysfs_remove_file(&dev->dev.kobj, &trace_running_attr.attr);
 	sysfs_remove_file(&dev->dev.kobj, &trace_info_attr.attr);
 	sysfs_remove_file(&dev->dev.kobj, &trace_mode_attr.attr);
+	sysfs_remove_file(&dev->dev.kobj, &trace_range_attr.attr);
 
 	return 0;
 }
-- 
1.7.3.1

^ permalink raw reply related

* [PATCH 5/8] ARM: etm: Configure data tracing
From: Arve Hjønnevåg @ 2011-02-15  6:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1296701663-12168-1-git-send-email-arve@android.com>

The old code enabled data tracing, but did not configure the
range. We now configure it to trace all data addresses by default,
and add a trace_data_range attribute to change the range or disable
data tracing.

Signed-off-by: Arve Hj?nnev?g <arve@android.com>
---
 arch/arm/include/asm/hardware/coresight.h |   10 +++-
 arch/arm/kernel/etm.c                     |   77 +++++++++++++++++++++++++++-
 2 files changed, 83 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h
index 7ecd793..6ea507f 100644
--- a/arch/arm/include/asm/hardware/coresight.h
+++ b/arch/arm/include/asm/hardware/coresight.h
@@ -17,9 +17,11 @@
 #define TRACER_ACCESSED_BIT	0
 #define TRACER_RUNNING_BIT	1
 #define TRACER_CYCLE_ACC_BIT	2
+#define TRACER_TRACE_DATA_BIT	3
 #define TRACER_ACCESSED		BIT(TRACER_ACCESSED_BIT)
 #define TRACER_RUNNING		BIT(TRACER_RUNNING_BIT)
 #define TRACER_CYCLE_ACC	BIT(TRACER_CYCLE_ACC_BIT)
+#define TRACER_TRACE_DATA	BIT(TRACER_TRACE_DATA_BIT)
 
 #define TRACER_TIMEOUT 10000
 
@@ -113,8 +115,14 @@
 #define ETMR_TRACEENCTRL	0x24
 #define ETMTE_INCLEXCL		BIT(24)
 #define ETMR_TRACEENEVT		0x20
+
+#define ETMR_VIEWDATAEVT	0x30
+#define ETMR_VIEWDATACTRL1	0x34
+#define ETMR_VIEWDATACTRL2	0x38
+#define ETMR_VIEWDATACTRL3	0x3c
+#define ETMVDC3_EXCLONLY	BIT(16)
+
 #define ETMCTRL_OPTS		(ETMCTRL_DO_CPRT | \
-				ETMCTRL_DATA_DO_ADDR | \
 				ETMCTRL_BRANCH_OUTPUT | \
 				ETMCTRL_DO_CONTEXTID)
 
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 8a1c422..96b1abb 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -42,6 +42,8 @@ struct tracectx {
 	int		etm_portsz;
 	unsigned long	range_start;
 	unsigned long	range_end;
+	unsigned long	data_range_start;
+	unsigned long	data_range_end;
 	struct device	*dev;
 	struct clk	*emu_clk;
 	struct mutex	mutex;
@@ -83,8 +85,15 @@ static int etm_setup_address_range(struct tracectx *t, int n,
 	etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1));
 	etm_writel(t, end, ETMR_COMP_VAL(n * 2 + 1));
 
-	flags = exclude ? ETMTE_INCLEXCL : 0;
-	etm_writel(t, flags | (1 << n), ETMR_TRACEENCTRL);
+	if (data) {
+		flags = exclude ? ETMVDC3_EXCLONLY : 0;
+		if (exclude)
+			n += 8;
+		etm_writel(t, flags | BIT(n), ETMR_VIEWDATACTRL3);
+	} else {
+		flags = exclude ? ETMTE_INCLEXCL : 0;
+		etm_writel(t, flags | (1 << n), ETMR_TRACEENCTRL);
+	}
 
 	return 0;
 }
@@ -108,6 +117,9 @@ static int trace_start(struct tracectx *t)
 	if (t->flags & TRACER_CYCLE_ACC)
 		v |= ETMCTRL_CYCLEACCURATE;
 
+	if (t->flags & TRACER_TRACE_DATA)
+		v |= ETMCTRL_DATA_DO_ADDR;
+
 	etm_unlock(t);
 
 	etm_writel(t, v, ETMR_CTRL);
@@ -130,6 +142,17 @@ static int trace_start(struct tracectx *t)
 	etm_writel(t, 0, ETMR_TRACESSCTRL);
 	etm_writel(t, 0x6f, ETMR_TRACEENEVT);
 
+	etm_writel(t, 0, ETMR_VIEWDATACTRL1);
+	etm_writel(t, 0, ETMR_VIEWDATACTRL2);
+
+	if (t->data_range_start || t->data_range_end)
+		etm_setup_address_range(t, 2, t->data_range_start,
+					t->data_range_end, 0, 1);
+	else
+		etm_writel(t, ETMVDC3_EXCLONLY, ETMR_VIEWDATACTRL3);
+
+	etm_writel(t, 0x6f, ETMR_VIEWDATAEVT);
+
 	v &= ~ETMCTRL_PROGRAM;
 	v |= ETMCTRL_PORTSEL;
 
@@ -563,6 +586,48 @@ static ssize_t trace_range_store(struct kobject *kobj,
 static struct kobj_attribute trace_range_attr =
 	__ATTR(trace_range, 0644, trace_range_show, trace_range_store);
 
+static ssize_t trace_data_range_show(struct kobject *kobj,
+				  struct kobj_attribute *attr,
+				  char *buf)
+{
+	unsigned long range_start;
+	u64 range_end;
+	mutex_lock(&tracer.mutex);
+	range_start = tracer.data_range_start;
+	range_end = tracer.data_range_end;
+	if (!range_end && (tracer.flags & TRACER_TRACE_DATA))
+		range_end = 0x100000000ULL;
+	mutex_unlock(&tracer.mutex);
+	return sprintf(buf, "%08lx %08llx\n", range_start, range_end);
+}
+
+static ssize_t trace_data_range_store(struct kobject *kobj,
+				   struct kobj_attribute *attr,
+				   const char *buf, size_t n)
+{
+	unsigned long range_start;
+	u64 range_end;
+
+	if (sscanf(buf, "%lx %llx", &range_start, &range_end) != 2)
+		return -EINVAL;
+
+	mutex_lock(&tracer.mutex);
+	tracer.data_range_start = range_start;
+	tracer.data_range_end = (unsigned long)range_end;
+	if (range_end)
+		tracer.flags |= TRACER_TRACE_DATA;
+	else
+		tracer.flags &= ~TRACER_TRACE_DATA;
+	mutex_unlock(&tracer.mutex);
+
+	return n;
+}
+
+
+static struct kobj_attribute trace_data_range_attr =
+	__ATTR(trace_data_range, 0644,
+		trace_data_range_show, trace_data_range_store);
+
 static int __init etm_probe(struct amba_device *dev, struct amba_id *id)
 {
 	struct tracectx *t = &tracer;
@@ -588,7 +653,7 @@ static int __init etm_probe(struct amba_device *dev, struct amba_id *id)
 
 	mutex_init(&t->mutex);
 	t->dev = &dev->dev;
-	t->flags = TRACER_CYCLE_ACC;
+	t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA;
 	t->etm_portsz = 1;
 
 	etm_unlock(t);
@@ -618,6 +683,11 @@ static int __init etm_probe(struct amba_device *dev, struct amba_id *id)
 	if (ret)
 		dev_dbg(&dev->dev, "Failed to create trace_range in sysfs\n");
 
+	ret = sysfs_create_file(&dev->dev.kobj, &trace_data_range_attr.attr);
+	if (ret)
+		dev_dbg(&dev->dev,
+			"Failed to create trace_data_range in sysfs\n");
+
 	dev_dbg(t->dev, "ETM AMBA driver initialized.\n");
 
 out:
@@ -648,6 +718,7 @@ static int etm_remove(struct amba_device *dev)
 	sysfs_remove_file(&dev->dev.kobj, &trace_info_attr.attr);
 	sysfs_remove_file(&dev->dev.kobj, &trace_mode_attr.attr);
 	sysfs_remove_file(&dev->dev.kobj, &trace_range_attr.attr);
+	sysfs_remove_file(&dev->dev.kobj, &trace_data_range_attr.attr);
 
 	return 0;
 }
-- 
1.7.3.1

^ permalink raw reply related

* [PATCH 6/8] ARM: etm: Add some missing locks and error checks
From: Arve Hjønnevåg @ 2011-02-15  6:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1296701663-12168-1-git-send-email-arve@android.com>

It is not safe to call etm_lock or etb_lock without holding the
mutex since another thread may also have unlocked the registers.

Also add some missing checks for valid etb_regs in the etm sysfs
entries.

Signed-off-by: Arve Hj?nnev?g <arve@android.com>
---
 arch/arm/kernel/etm.c |   57 +++++++++++++++++++++++++++++++++---------------
 1 files changed, 39 insertions(+), 18 deletions(-)

diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 96b1abb..8126beb 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -263,8 +263,13 @@ static void etm_dump(void)
 
 static void sysrq_etm_dump(int key)
 {
+	if (!mutex_trylock(&tracer.mutex)) {
+		printk(KERN_INFO "Tracing hardware busy\n");
+		return;
+	}
 	dev_dbg(tracer.dev, "Dumping ETB buffer\n");
 	etm_dump();
+	mutex_unlock(&tracer.mutex);
 }
 
 static struct sysrq_key_op sysrq_etm_op = {
@@ -373,6 +378,7 @@ static int __init etb_probe(struct amba_device *dev, struct amba_id *id)
 	if (ret)
 		goto out;
 
+	mutex_lock(&t->mutex);
 	t->etb_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res));
 	if (!t->etb_regs) {
 		ret = -ENOMEM;
@@ -381,6 +387,16 @@ static int __init etb_probe(struct amba_device *dev, struct amba_id *id)
 
 	amba_set_drvdata(dev, t);
 
+	etb_unlock(t);
+	t->etb_bufsz = etb_readl(t, ETBR_DEPTH);
+	dev_dbg(&dev->dev, "Size: %x\n", t->etb_bufsz);
+
+	/* make sure trace capture is disabled */
+	etb_writel(t, 0, ETBR_CTRL);
+	etb_writel(t, 0x1000, ETBR_FORMATTERCTRL);
+	etb_lock(t);
+	mutex_unlock(&t->mutex);
+
 	etb_miscdev.parent = &dev->dev;
 
 	ret = misc_register(&etb_miscdev);
@@ -394,25 +410,19 @@ static int __init etb_probe(struct amba_device *dev, struct amba_id *id)
 	else
 		clk_enable(t->emu_clk);
 
-	etb_unlock(t);
-	t->etb_bufsz = etb_readl(t, ETBR_DEPTH);
-	dev_dbg(&dev->dev, "Size: %x\n", t->etb_bufsz);
-
-	/* make sure trace capture is disabled */
-	etb_writel(t, 0, ETBR_CTRL);
-	etb_writel(t, 0x1000, ETBR_FORMATTERCTRL);
-	etb_lock(t);
-
 	dev_dbg(&dev->dev, "ETB AMBA driver initialized.\n");
 
 out:
 	return ret;
 
 out_unmap:
+	mutex_lock(&t->mutex);
 	amba_set_drvdata(dev, NULL);
 	iounmap(t->etb_regs);
+	t->etb_regs = NULL;
 
 out_release:
+	mutex_unlock(&t->mutex);
 	amba_release_regions(dev);
 
 	return ret;
@@ -474,7 +484,10 @@ static ssize_t trace_running_store(struct kobject *kobj,
 		return -EINVAL;
 
 	mutex_lock(&tracer.mutex);
-	ret = value ? trace_start(&tracer) : trace_stop(&tracer);
+	if (!tracer.etb_regs)
+		ret = -ENODEV;
+	else
+		ret = value ? trace_start(&tracer) : trace_stop(&tracer);
 	mutex_unlock(&tracer.mutex);
 
 	return ret ? : n;
@@ -490,18 +503,25 @@ static ssize_t trace_info_show(struct kobject *kobj,
 	u32 etb_wa, etb_ra, etb_st, etb_fc, etm_ctrl, etm_st;
 	int datalen;
 
-	etb_unlock(&tracer);
-	datalen = etb_getdatalen(&tracer);
-	etb_wa = etb_readl(&tracer, ETBR_WRITEADDR);
-	etb_ra = etb_readl(&tracer, ETBR_READADDR);
-	etb_st = etb_readl(&tracer, ETBR_STATUS);
-	etb_fc = etb_readl(&tracer, ETBR_FORMATTERCTRL);
-	etb_lock(&tracer);
+	mutex_lock(&tracer.mutex);
+	if (tracer.etb_regs) {
+		etb_unlock(&tracer);
+		datalen = etb_getdatalen(&tracer);
+		etb_wa = etb_readl(&tracer, ETBR_WRITEADDR);
+		etb_ra = etb_readl(&tracer, ETBR_READADDR);
+		etb_st = etb_readl(&tracer, ETBR_STATUS);
+		etb_fc = etb_readl(&tracer, ETBR_FORMATTERCTRL);
+		etb_lock(&tracer);
+	} else {
+		etb_wa = etb_ra = etb_st = etb_fc = ~0;
+		datalen = -1;
+	}
 
 	etm_unlock(&tracer);
 	etm_ctrl = etm_readl(&tracer, ETMR_CTRL);
 	etm_st = etm_readl(&tracer, ETMR_STATUS);
 	etm_lock(&tracer);
+	mutex_unlock(&tracer.mutex);
 
 	return sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n"
 			"ETBR_WRITEADDR:\t%08x\n"
@@ -651,7 +671,6 @@ static int __init etm_probe(struct amba_device *dev, struct amba_id *id)
 
 	amba_set_drvdata(dev, t);
 
-	mutex_init(&t->mutex);
 	t->dev = &dev->dev;
 	t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA;
 	t->etm_portsz = 1;
@@ -745,6 +764,8 @@ static int __init etm_init(void)
 {
 	int retval;
 
+	mutex_init(&tracer.mutex);
+
 	retval = amba_driver_register(&etb_driver);
 	if (retval) {
 		printk(KERN_ERR "Failed to register etb\n");
-- 
1.7.3.1

^ permalink raw reply related

* [PATCH 7/8] ARM: etm: Return the entire trace buffer if it is empty after reset
From: Arve Hjønnevåg @ 2011-02-15  6:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1296701663-12168-1-git-send-email-arve@android.com>

On some SOCs the read and write pointer are reset when the chip
resets, but the trace buffer content is preserved. If the status
bits indicates that the buffer is empty and we have never started
tracing, assume the buffer is full instead. This can be useful
if the system rebooted from a watchdog reset.

Signed-off-by: Arve Hj?nnev?g <arve@android.com>
---
 arch/arm/kernel/etm.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 8126beb..4ad1257 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -44,6 +44,7 @@ struct tracectx {
 	unsigned long	range_end;
 	unsigned long	data_range_start;
 	unsigned long	data_range_end;
+	bool		dump_initial_etb;
 	struct device	*dev;
 	struct clk	*emu_clk;
 	struct mutex	mutex;
@@ -105,6 +106,7 @@ static int trace_start(struct tracectx *t)
 
 	etb_unlock(t);
 
+	t->dump_initial_etb = false;
 	etb_writel(t, 0, ETBR_WRITEADDR);
 	etb_writel(t, 0, ETBR_FORMATTERCTRL);
 	etb_writel(t, 1, ETBR_CTRL);
@@ -311,6 +313,8 @@ static ssize_t etb_read(struct file *file, char __user *data,
 	etb_unlock(t);
 
 	total = etb_getdatalen(t);
+	if (total == 0 && t->dump_initial_etb)
+		total = t->etb_bufsz;
 	if (total == t->etb_bufsz)
 		first = etb_readl(t, ETBR_WRITEADDR);
 
@@ -385,6 +389,7 @@ static int __init etb_probe(struct amba_device *dev, struct amba_id *id)
 		goto out_release;
 	}
 
+	t->dump_initial_etb = true;
 	amba_set_drvdata(dev, t);
 
 	etb_unlock(t);
-- 
1.7.3.1

^ permalink raw reply related

* [PATCH 8/8] ARM: etm: Support multiple ETMs/PTMs.
From: Arve Hjønnevåg @ 2011-02-15  6:11 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1296701663-12168-1-git-send-email-arve@android.com>

If more than one ETM or PTM are present, configure all of them
and enable the formatter in the ETB. This allows tracing on dual
core systems (e.g. omap4).

Signed-off-by: Arve Hj?nnev?g <arve@android.com>
---
 arch/arm/include/asm/hardware/coresight.h |   16 ++-
 arch/arm/kernel/etm.c                     |  234 +++++++++++++++++++----------
 2 files changed, 166 insertions(+), 84 deletions(-)

diff --git a/arch/arm/include/asm/hardware/coresight.h b/arch/arm/include/asm/hardware/coresight.h
index 6ea507f..6643d6c 100644
--- a/arch/arm/include/asm/hardware/coresight.h
+++ b/arch/arm/include/asm/hardware/coresight.h
@@ -25,9 +25,9 @@
 
 #define TRACER_TIMEOUT 10000
 
-#define etm_writel(t, v, x) \
-	(__raw_writel((v), (t)->etm_regs + (x)))
-#define etm_readl(t, x) (__raw_readl((t)->etm_regs + (x)))
+#define etm_writel(t, id, v, x) \
+	(__raw_writel((v), (t)->etm_regs[(id)] + (x)))
+#define etm_readl(t, id, x) (__raw_readl((t)->etm_regs[(id)] + (x)))
 
 /* CoreSight Management Registers */
 #define CSMR_LOCKACCESS 0xfb0
@@ -126,6 +126,8 @@
 				ETMCTRL_BRANCH_OUTPUT | \
 				ETMCTRL_DO_CONTEXTID)
 
+#define ETMR_TRACEIDR		0x200
+
 /* ETM management registers, "ETM Architecture", 3.5.24 */
 #define ETMMR_OSLAR	0x300
 #define ETMMR_OSLSR	0x304
@@ -148,14 +150,16 @@
 #define ETBFF_TRIGIN		BIT(8)
 #define ETBFF_TRIGEVT		BIT(9)
 #define ETBFF_TRIGFL		BIT(10)
+#define ETBFF_STOPFL		BIT(12)
 
 #define etb_writel(t, v, x) \
 	(__raw_writel((v), (t)->etb_regs + (x)))
 #define etb_readl(t, x) (__raw_readl((t)->etb_regs + (x)))
 
-#define etm_lock(t) do { etm_writel((t), 0, CSMR_LOCKACCESS); } while (0)
-#define etm_unlock(t) \
-	do { etm_writel((t), UNLOCK_MAGIC, CSMR_LOCKACCESS); } while (0)
+#define etm_lock(t, id) \
+	do { etm_writel((t), (id), 0, CSMR_LOCKACCESS); } while (0)
+#define etm_unlock(t, id) \
+	do { etm_writel((t), (id), UNLOCK_MAGIC, CSMR_LOCKACCESS); } while (0)
 
 #define etb_lock(t) do { etb_writel((t), 0, CSMR_LOCKACCESS); } while (0)
 #define etb_unlock(t) \
diff --git a/arch/arm/kernel/etm.c b/arch/arm/kernel/etm.c
index 4ad1257..48de5a4 100644
--- a/arch/arm/kernel/etm.c
+++ b/arch/arm/kernel/etm.c
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/types.h>
 #include <linux/io.h>
+#include <linux/slab.h>
 #include <linux/sysrq.h>
 #include <linux/device.h>
 #include <linux/clk.h>
@@ -36,10 +37,12 @@ MODULE_AUTHOR("Alexander Shishkin");
 struct tracectx {
 	unsigned int	etb_bufsz;
 	void __iomem	*etb_regs;
-	void __iomem	*etm_regs;
+	void __iomem	**etm_regs;
+	int		etm_regs_count;
 	unsigned long	flags;
 	int		ncmppairs;
 	int		etm_portsz;
+	u32		etb_fc;
 	unsigned long	range_start;
 	unsigned long	range_end;
 	unsigned long	data_range_start;
@@ -60,7 +63,7 @@ static inline bool trace_isrunning(struct tracectx *t)
 	return !!(t->flags & TRACER_RUNNING);
 }
 
-static int etm_setup_address_range(struct tracectx *t, int n,
+static int etm_setup_address_range(struct tracectx *t, int id, int n,
 		unsigned long start, unsigned long end, int exclude, int data)
 {
 	u32 flags = ETMAAT_ARM | ETMAAT_IGNCONTEXTID | ETMAAT_IGNSECURITY |
@@ -79,41 +82,31 @@ static int etm_setup_address_range(struct tracectx *t, int n,
 		flags |= ETMAAT_IEXEC;
 
 	/* first comparator for the range */
-	etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2));
-	etm_writel(t, start, ETMR_COMP_VAL(n * 2));
+	etm_writel(t, id, flags, ETMR_COMP_ACC_TYPE(n * 2));
+	etm_writel(t, id, start, ETMR_COMP_VAL(n * 2));
 
 	/* second comparator is right next to it */
-	etm_writel(t, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1));
-	etm_writel(t, end, ETMR_COMP_VAL(n * 2 + 1));
+	etm_writel(t, id, flags, ETMR_COMP_ACC_TYPE(n * 2 + 1));
+	etm_writel(t, id, end, ETMR_COMP_VAL(n * 2 + 1));
 
 	if (data) {
 		flags = exclude ? ETMVDC3_EXCLONLY : 0;
 		if (exclude)
 			n += 8;
-		etm_writel(t, flags | BIT(n), ETMR_VIEWDATACTRL3);
+		etm_writel(t, id, flags | BIT(n), ETMR_VIEWDATACTRL3);
 	} else {
 		flags = exclude ? ETMTE_INCLEXCL : 0;
-		etm_writel(t, flags | (1 << n), ETMR_TRACEENCTRL);
+		etm_writel(t, id, flags | (1 << n), ETMR_TRACEENCTRL);
 	}
 
 	return 0;
 }
 
-static int trace_start(struct tracectx *t)
+static int trace_start_etm(struct tracectx *t, int id)
 {
 	u32 v;
 	unsigned long timeout = TRACER_TIMEOUT;
 
-	etb_unlock(t);
-
-	t->dump_initial_etb = false;
-	etb_writel(t, 0, ETBR_WRITEADDR);
-	etb_writel(t, 0, ETBR_FORMATTERCTRL);
-	etb_writel(t, 1, ETBR_CTRL);
-
-	etb_lock(t);
-
-	/* configure etm */
 	v = ETMCTRL_OPTS | ETMCTRL_PROGRAM | ETMCTRL_PORTSIZE(t->etm_portsz);
 
 	if (t->flags & TRACER_CYCLE_ACC)
@@ -122,79 +115,122 @@ static int trace_start(struct tracectx *t)
 	if (t->flags & TRACER_TRACE_DATA)
 		v |= ETMCTRL_DATA_DO_ADDR;
 
-	etm_unlock(t);
+	etm_unlock(t, id);
 
-	etm_writel(t, v, ETMR_CTRL);
+	etm_writel(t, id, v, ETMR_CTRL);
 
-	while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
+	while (!(etm_readl(t, id, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
 		;
 	if (!timeout) {
 		dev_dbg(t->dev, "Waiting for progbit to assert timed out\n");
-		etm_lock(t);
+		etm_lock(t, id);
 		return -EFAULT;
 	}
 
 	if (t->range_start || t->range_end)
-		etm_setup_address_range(t, 1,
+		etm_setup_address_range(t, id, 1,
 					t->range_start, t->range_end, 0, 0);
 	else
-		etm_writel(t, ETMTE_INCLEXCL, ETMR_TRACEENCTRL);
+		etm_writel(t, id, ETMTE_INCLEXCL, ETMR_TRACEENCTRL);
 
-	etm_writel(t, 0, ETMR_TRACEENCTRL2);
-	etm_writel(t, 0, ETMR_TRACESSCTRL);
-	etm_writel(t, 0x6f, ETMR_TRACEENEVT);
+	etm_writel(t, id, 0, ETMR_TRACEENCTRL2);
+	etm_writel(t, id, 0, ETMR_TRACESSCTRL);
+	etm_writel(t, id, 0x6f, ETMR_TRACEENEVT);
 
-	etm_writel(t, 0, ETMR_VIEWDATACTRL1);
-	etm_writel(t, 0, ETMR_VIEWDATACTRL2);
+	etm_writel(t, id, 0, ETMR_VIEWDATACTRL1);
+	etm_writel(t, id, 0, ETMR_VIEWDATACTRL2);
 
 	if (t->data_range_start || t->data_range_end)
-		etm_setup_address_range(t, 2, t->data_range_start,
+		etm_setup_address_range(t, id, 2, t->data_range_start,
 					t->data_range_end, 0, 1);
 	else
-		etm_writel(t, ETMVDC3_EXCLONLY, ETMR_VIEWDATACTRL3);
+		etm_writel(t, id, ETMVDC3_EXCLONLY, ETMR_VIEWDATACTRL3);
 
-	etm_writel(t, 0x6f, ETMR_VIEWDATAEVT);
+	etm_writel(t, id, 0x6f, ETMR_VIEWDATAEVT);
 
 	v &= ~ETMCTRL_PROGRAM;
 	v |= ETMCTRL_PORTSEL;
 
-	etm_writel(t, v, ETMR_CTRL);
+	etm_writel(t, id, v, ETMR_CTRL);
 
 	timeout = TRACER_TIMEOUT;
-	while (etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM && --timeout)
+	while (etm_readl(t, id, ETMR_CTRL) & ETMCTRL_PROGRAM && --timeout)
 		;
 	if (!timeout) {
 		dev_dbg(t->dev, "Waiting for progbit to deassert timed out\n");
-		etm_lock(t);
+		etm_lock(t, id);
 		return -EFAULT;
 	}
 
-	etm_lock(t);
+	etm_lock(t, id);
+	return 0;
+}
+
+static int trace_start(struct tracectx *t)
+{
+	int ret;
+	int id;
+	u32 etb_fc = t->etb_fc;
+
+	etb_unlock(t);
+
+	t->dump_initial_etb = false;
+	etb_writel(t, 0, ETBR_WRITEADDR);
+	etb_writel(t, etb_fc, ETBR_FORMATTERCTRL);
+	etb_writel(t, 1, ETBR_CTRL);
+
+	etb_lock(t);
+
+	/* configure etm(s) */
+	for (id = 0; id < t->etm_regs_count; id++) {
+		ret = trace_start_etm(t, id);
+		if (ret)
+			return ret;
+	}
 
 	t->flags |= TRACER_RUNNING;
 
 	return 0;
 }
 
-static int trace_stop(struct tracectx *t)
+static int trace_stop_etm(struct tracectx *t, int id)
 {
 	unsigned long timeout = TRACER_TIMEOUT;
 
-	etm_unlock(t);
+	etm_unlock(t, id);
 
-	etm_writel(t, 0x440, ETMR_CTRL);
-	while (!(etm_readl(t, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
+	etm_writel(t, id, 0x440, ETMR_CTRL);
+	while (!(etm_readl(t, id, ETMR_CTRL) & ETMCTRL_PROGRAM) && --timeout)
 		;
 	if (!timeout) {
 		dev_dbg(t->dev, "Waiting for progbit to assert timed out\n");
-		etm_lock(t);
+		etm_lock(t, id);
 		return -EFAULT;
 	}
 
-	etm_lock(t);
+	etm_lock(t, id);
+	return 0;
+}
+
+static int trace_stop(struct tracectx *t)
+{
+	int id;
+	int ret;
+	unsigned long timeout = TRACER_TIMEOUT;
+	u32 etb_fc = t->etb_fc;
+
+	for (id = 0; id < t->etm_regs_count; id++) {
+		ret = trace_stop_etm(t, id);
+		if (ret)
+			return ret;
+	}
 
 	etb_unlock(t);
-	etb_writel(t, ETBFF_MANUAL_FLUSH, ETBR_FORMATTERCTRL);
+	if (etb_fc) {
+		etb_fc |= ETBFF_STOPFL;
+		etb_writel(t, t->etb_fc, ETBR_FORMATTERCTRL);
+	}
+	etb_writel(t, etb_fc | ETBFF_MANUAL_FLUSH, ETBR_FORMATTERCTRL);
 
 	timeout = TRACER_TIMEOUT;
 	while (etb_readl(t, ETBR_FORMATTERCTRL) &
@@ -389,6 +425,7 @@ static int __init etb_probe(struct amba_device *dev, struct amba_id *id)
 		goto out_release;
 	}
 
+	t->dev = &dev->dev;
 	t->dump_initial_etb = true;
 	amba_set_drvdata(dev, t);
 
@@ -507,6 +544,8 @@ static ssize_t trace_info_show(struct kobject *kobj,
 {
 	u32 etb_wa, etb_ra, etb_st, etb_fc, etm_ctrl, etm_st;
 	int datalen;
+	int id;
+	int ret;
 
 	mutex_lock(&tracer.mutex);
 	if (tracer.etb_regs) {
@@ -522,28 +561,33 @@ static ssize_t trace_info_show(struct kobject *kobj,
 		datalen = -1;
 	}
 
-	etm_unlock(&tracer);
-	etm_ctrl = etm_readl(&tracer, ETMR_CTRL);
-	etm_st = etm_readl(&tracer, ETMR_STATUS);
-	etm_lock(&tracer);
-	mutex_unlock(&tracer.mutex);
-
-	return sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n"
+	ret = sprintf(buf, "Trace buffer len: %d\nComparator pairs: %d\n"
 			"ETBR_WRITEADDR:\t%08x\n"
 			"ETBR_READADDR:\t%08x\n"
 			"ETBR_STATUS:\t%08x\n"
-			"ETBR_FORMATTERCTRL:\t%08x\n"
-			"ETMR_CTRL:\t%08x\n"
-			"ETMR_STATUS:\t%08x\n",
+			"ETBR_FORMATTERCTRL:\t%08x\n",
 			datalen,
 			tracer.ncmppairs,
 			etb_wa,
 			etb_ra,
 			etb_st,
-			etb_fc,
+			etb_fc
+			);
+
+	for (id = 0; id < tracer.etm_regs_count; id++) {
+		etm_unlock(&tracer, id);
+		etm_ctrl = etm_readl(&tracer, id, ETMR_CTRL);
+		etm_st = etm_readl(&tracer, id, ETMR_STATUS);
+		etm_lock(&tracer, id);
+		ret += sprintf(buf + ret, "ETMR_CTRL:\t%08x\n"
+			"ETMR_STATUS:\t%08x\n",
 			etm_ctrl,
 			etm_st
 			);
+	}
+	mutex_unlock(&tracer.mutex);
+
+	return ret;
 }
 
 static struct kobj_attribute trace_info_attr =
@@ -657,37 +701,46 @@ static int __init etm_probe(struct amba_device *dev, struct amba_id *id)
 {
 	struct tracectx *t = &tracer;
 	int ret = 0;
+	void __iomem **new_regs;
+	int new_count;
 
-	if (t->etm_regs) {
-		dev_dbg(&dev->dev, "ETM already initialized\n");
-		ret = -EBUSY;
+	mutex_lock(&t->mutex);
+	new_count = t->etm_regs_count + 1;
+	new_regs = krealloc(t->etm_regs,
+				sizeof(t->etm_regs[0]) * new_count, GFP_KERNEL);
+
+	if (!new_regs) {
+		dev_dbg(&dev->dev, "Failed to allocate ETM register array\n");
+		ret = -ENOMEM;
 		goto out;
 	}
+	t->etm_regs = new_regs;
 
 	ret = amba_request_regions(dev, NULL);
 	if (ret)
 		goto out;
 
-	t->etm_regs = ioremap_nocache(dev->res.start, resource_size(&dev->res));
-	if (!t->etm_regs) {
+	t->etm_regs[t->etm_regs_count] =
+		ioremap_nocache(dev->res.start, resource_size(&dev->res));
+	if (!t->etm_regs[t->etm_regs_count]) {
 		ret = -ENOMEM;
 		goto out_release;
 	}
 
-	amba_set_drvdata(dev, t);
+	amba_set_drvdata(dev, t->etm_regs[t->etm_regs_count]);
 
-	t->dev = &dev->dev;
 	t->flags = TRACER_CYCLE_ACC | TRACER_TRACE_DATA;
 	t->etm_portsz = 1;
 
-	etm_unlock(t);
-	(void)etm_readl(t, ETMMR_PDSR);
+	etm_unlock(t, t->etm_regs_count);
+	(void)etm_readl(t, t->etm_regs_count, ETMMR_PDSR);
 	/* dummy first read */
-	(void)etm_readl(&tracer, ETMMR_OSSRR);
+	(void)etm_readl(&tracer, t->etm_regs_count, ETMMR_OSSRR);
 
-	t->ncmppairs = etm_readl(t, ETMR_CONFCODE) & 0xf;
-	etm_writel(t, 0x440, ETMR_CTRL);
-	etm_lock(t);
+	t->ncmppairs = etm_readl(t, t->etm_regs_count, ETMR_CONFCODE) & 0xf;
+	etm_writel(t, t->etm_regs_count, 0x440, ETMR_CTRL);
+	etm_writel(t, t->etm_regs_count, new_count, ETMR_TRACEIDR);
+	etm_lock(t, t->etm_regs_count);
 
 	ret = sysfs_create_file(&dev->dev.kobj,
 			&trace_running_attr.attr);
@@ -712,31 +765,34 @@ static int __init etm_probe(struct amba_device *dev, struct amba_id *id)
 		dev_dbg(&dev->dev,
 			"Failed to create trace_data_range in sysfs\n");
 
-	dev_dbg(t->dev, "ETM AMBA driver initialized.\n");
+	dev_dbg(&dev->dev, "ETM AMBA driver initialized.\n");
+
+	/* Enable formatter if there are multiple trace sources */
+	if (new_count > 1)
+		t->etb_fc = ETBFF_ENFCONT | ETBFF_ENFTC;
+
+	t->etm_regs_count = new_count;
 
 out:
+	mutex_unlock(&t->mutex);
 	return ret;
 
 out_unmap:
 	amba_set_drvdata(dev, NULL);
-	iounmap(t->etm_regs);
+	iounmap(t->etm_regs[t->etm_regs_count]);
 
 out_release:
 	amba_release_regions(dev);
 
+	mutex_unlock(&t->mutex);
 	return ret;
 }
 
 static int etm_remove(struct amba_device *dev)
 {
-	struct tracectx *t = amba_get_drvdata(dev);
-
-	amba_set_drvdata(dev, NULL);
-
-	iounmap(t->etm_regs);
-	t->etm_regs = NULL;
-
-	amba_release_regions(dev);
+	int i;
+	struct tracectx *t = &tracer;
+	void __iomem	*etm_regs = amba_get_drvdata(dev);
 
 	sysfs_remove_file(&dev->dev.kobj, &trace_running_attr.attr);
 	sysfs_remove_file(&dev->dev.kobj, &trace_info_attr.attr);
@@ -744,6 +800,24 @@ static int etm_remove(struct amba_device *dev)
 	sysfs_remove_file(&dev->dev.kobj, &trace_range_attr.attr);
 	sysfs_remove_file(&dev->dev.kobj, &trace_data_range_attr.attr);
 
+	amba_set_drvdata(dev, NULL);
+
+	mutex_lock(&t->mutex);
+	for (i = 0; i < t->etm_regs_count; i++)
+		if (t->etm_regs[i] == etm_regs)
+			break;
+	for (; i < t->etm_regs_count - 1; i++)
+		t->etm_regs[i] = t->etm_regs[i + 1];
+	t->etm_regs_count--;
+	if (!t->etm_regs_count) {
+		kfree(t->etm_regs);
+		t->etm_regs = NULL;
+	}
+	mutex_unlock(&t->mutex);
+
+	iounmap(etm_regs);
+	amba_release_regions(dev);
+
 	return 0;
 }
 
@@ -752,6 +826,10 @@ static struct amba_id etm_ids[] = {
 		.id	= 0x0003b921,
 		.mask	= 0x0007ffff,
 	},
+	{
+		.id	= 0x0003b950,
+		.mask	= 0x0007ffff,
+	},
 	{ 0, 0 },
 };
 
-- 
1.7.3.1

^ permalink raw reply related

* [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
From: Jeremy Kerr @ 2011-02-15  6:18 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4D5A063F.1010102@codeaurora.org>

Hi Saravana,

> >> A fixed clock may still have other operations such as enable/disable.
> > 
> > Then it's not a fixed clock; I'd prefer this to be a separate type, as
> > it's now hardware dependent.
> 
> I'm confused. If a clock's rate can't be changed and it can't be enabled
> or disabled, then what's the point of representing that clock
> signal/line as a clock in the driver.

Because the drivers using this clock don't know that it's a fixed clock.

For example, a uart needs to know the rate of its clock source, so that it can 
set its internal divisors to get a valid baud rate. The uart driver will query  
the input rate using clk_get_rate(). The driver still needs to call 
clk_enable/clk_prepare/etc, because on some systems it may have a switchable 
clock.

Cheers,


Jeremy

^ permalink raw reply

* [RFC,PATCH 2/3] clk: Generic support for fixed-rate clocks
From: Saravana Kannan @ 2011-02-15  6:31 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201102151418.37780.jeremy.kerr@canonical.com>

On 02/14/2011 10:18 PM, Jeremy Kerr wrote:

> Because the drivers using this clock don't know that it's a fixed clock.
>
> For example, a uart needs to know the rate of its clock source, so that it can
> set its internal divisors to get a valid baud rate. The uart driver will query
> the input rate using clk_get_rate(). The driver still needs to call
> clk_enable/clk_prepare/etc, because on some systems it may have a switchable
> clock.

Thanks. Makes sense.

-Saravana
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply

* [PATCH 3/5] ARM: l2x0: Errata fix for flush by Way operation can cause data corruption
From: Santosh Shilimkar @ 2011-02-15  7:14 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <33573d5cfc91cf45dc58ee861cccc2ae@mail.gmail.com>

> -----Original Message-----
> From: Santosh Shilimkar [mailto:santosh.shilimkar at ti.com]
> Sent: Monday, February 14, 2011 10:39 AM
> To: Andrei Warkentin
> Cc: linux-omap at vger.kernel.org; Kevin Hilman; tony at atomide.com;
> linux-arm-kernel at lists.infradead.org; Catalin Marinas
> Subject: RE: [PATCH 3/5] ARM: l2x0: Errata fix for flush by Way
> operation can cause data corruption
>

[....]

> > ...
> I understood that from first comment. But I am not in favor
> of polluting common ARM files with SOC specific #ifdeffery.
> We have gone over this when first errata support
> was added for PL310
>
> I have a better way to handle this scenario.
> Expect an updated patch for this.
>

Below is the updated version which should remove any
OMAP dependency on these errata's. Attached same.

----
From: Santosh Shilimkar <santosh.shilimkar@ti.com>
Date: Fri, 14 Jan 2011 14:16:04 +0530
Subject: [v2 PATCH 3/5] ARM: l2x0: Errata fix for flush by Way operation
can cause data corruption

PL310 implements the Clean & Invalidate by Way L2 cache maintenance
operation (offset 0x7FC). This operation runs in background so that
PL310 can handle normal accesses while it is in progress. Under very
rare circumstances, due to this erratum, write data can be lost when
PL310 treats a cacheable write transaction during a Clean & Invalidate
by Way operation.

Workaround:
Disable Write-Back and Cache Linefill (Debug Control Register)
Clean & Invalidate by Way (0x7FC)
Re-enable Write-Back and Cache Linefill (Debug Control Register)

Signed-off-by: Santosh Shilimkar <santosh.shilimkar@ti.com>
Cc: Catalin Marinas <catalin.marinas@arm.com>
---
 arch/arm/Kconfig                   |   13 ++++++++++++-
 arch/arm/include/asm/outercache.h  |    1 +
 arch/arm/mach-omap2/Kconfig        |    3 +++
 arch/arm/mach-omap2/omap4-common.c |    7 +++++++
 arch/arm/mm/cache-l2x0.c           |   28 +++++++++++++++-------------
 5 files changed, 38 insertions(+), 14 deletions(-)

diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 5cff165..ebadd95 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1140,7 +1140,7 @@ config ARM_ERRATA_742231

 config PL310_ERRATA_588369
 	bool "Clean & Invalidate maintenance operations do not invalidate
clean lines"
-	depends on CACHE_L2X0 && ARCH_OMAP4
+	depends on CACHE_L2X0 && CACHE_PL310
 	help
 	   The PL310 L2 cache controller implements three types of Clean &
 	   Invalidate maintenance operations: by Physical Address
@@ -1177,6 +1177,17 @@ config ARM_ERRATA_743622
 	  visible impact on the overall performance or power consumption
of the
 	  processor.

+config PL310_ERRATA_727915
+	bool "Background Clean & Invalidate by Way operation can cause
data corruption"
+	depends on CACHE_L2X0 && CACHE_PL310
+	help
+	  PL310 implements the Clean & Invalidate by Way L2 cache
maintenance
+	  operation (offset 0x7FC). This operation runs in background so
that
+	  PL310 can handle normal accesses while it is in progress. Under
very
+	  rare circumstances, due to this erratum, write data can be lost
when
+	  PL310 treats a cacheable write transaction during a Clean &
+	  Invalidate by Way operation Note that this errata uses Texas
+	  Instrument's secure monitor api to implement the work around.
 endmenu

 source "arch/arm/common/Kconfig"
diff --git a/arch/arm/include/asm/outercache.h
b/arch/arm/include/asm/outercache.h
index fc19009..348d513 100644
--- a/arch/arm/include/asm/outercache.h
+++ b/arch/arm/include/asm/outercache.h
@@ -31,6 +31,7 @@ struct outer_cache_fns {
 #ifdef CONFIG_OUTER_CACHE_SYNC
 	void (*sync)(void);
 #endif
+	void (*set_debug)(unsigned long);
 };

 #ifdef CONFIG_OUTER_CACHE
diff --git a/arch/arm/mach-omap2/Kconfig b/arch/arm/mach-omap2/Kconfig
index f285dd7..fd11ab4 100644
--- a/arch/arm/mach-omap2/Kconfig
+++ b/arch/arm/mach-omap2/Kconfig
@@ -45,7 +45,10 @@ config ARCH_OMAP4
 	select CPU_V7
 	select ARM_GIC
 	select LOCAL_TIMERS
+	select CACHE_L2X0
+	select CACHE_PL310
 	select PL310_ERRATA_588369
+	select PL310_ERRATA_727915
 	select ARM_ERRATA_720789
 	select ARCH_HAS_OPP
 	select PM_OPP if PM
diff --git a/arch/arm/mach-omap2/omap4-common.c
b/arch/arm/mach-omap2/omap4-common.c
index 1926864..9ef8c29 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -52,6 +52,12 @@ static void omap4_l2x0_disable(void)
 	omap_smc1(0x102, 0x0);
 }

+static void omap4_l2x0_set_debug(unsigned long val)
+{
+	/* Program PL310 L2 Cache controller debug register */
+	omap_smc1(0x100, val);
+}
+
 static int __init omap_l2_cache_init(void)
 {
 	u32 aux_ctrl = 0;
@@ -99,6 +105,7 @@ static int __init omap_l2_cache_init(void)
 	 * specific one
 	*/
 	outer_cache.disable = omap4_l2x0_disable;
+	outer_cache.set_debug = omap4_l2x0_set_debug;

 	return 0;
 }
diff --git a/arch/arm/mm/cache-l2x0.c b/arch/arm/mm/cache-l2x0.c
index 170c9bb..a8caee4 100644
--- a/arch/arm/mm/cache-l2x0.c
+++ b/arch/arm/mm/cache-l2x0.c
@@ -67,18 +67,22 @@ static inline void l2x0_inv_line(unsigned long addr)
 	writel_relaxed(addr, base + L2X0_INV_LINE_PA);
 }

-#ifdef CONFIG_PL310_ERRATA_588369
+#if defined(CONFIG_PL310_ERRATA_588369) ||
defined(CONFIG_PL310_ERRATA_727915)
 static void debug_writel(unsigned long val)
 {
-	extern void omap_smc1(u32 fn, u32 arg);
-
-	/*
-	 * Texas Instrument secure monitor api to modify the
-	 * PL310 Debug Control Register.
-	 */
-	omap_smc1(0x100, val);
+	if (outer_cache.set_debug)
+		outer_cache.set_debug(val);
+	else
+		writel(val, l2x0_base + L2X0_DEBUG_CTRL);
+}
+#else
+/* Optimised out for non-errata case */
+static inline void debug_writel(unsigned long val)
+{
 }
+#endif

+#ifdef CONFIG_PL310_ERRATA_588369
 static inline void l2x0_flush_line(unsigned long addr)
 {
 	void __iomem *base = l2x0_base;
@@ -91,11 +95,6 @@ static inline void l2x0_flush_line(unsigned long addr)
 }
 #else

-/* Optimised out for non-errata case */
-static inline void debug_writel(unsigned long val)
-{
-}
-
 static inline void l2x0_flush_line(unsigned long addr)
 {
 	void __iomem *base = l2x0_base;
@@ -119,9 +118,11 @@ static void l2x0_flush_all(void)

 	/* clean all ways */
 	spin_lock_irqsave(&l2x0_lock, flags);
+	debug_writel(0x03);
 	writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY);
 	cache_wait_way(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask);
 	cache_sync();
+	debug_writel(0x00);
 	spin_unlock_irqrestore(&l2x0_lock, flags);
 }

@@ -329,6 +330,7 @@ void __init l2x0_init(void __iomem *base, __u32
aux_val, __u32 aux_mask)
 	outer_cache.flush_all = l2x0_flush_all;
 	outer_cache.inv_all = l2x0_inv_all;
 	outer_cache.disable = l2x0_disable;
+	outer_cache.set_debug = NULL;

 	printk(KERN_INFO "%s cache controller enabled\n", type);
 	printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x,
Cache size: %d B\n",
-- 
1.6.0.4
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0003-ARM-l2x0-Errata-fix-for-flush-by-Way-operation-can.patch
Type: application/octet-stream
Size: 6061 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20110215/2e6980b7/attachment-0001.obj>

^ permalink raw reply related

* [GIT] dmaengine fixes for 2.6.38-rc5
From: Dan Williams @ 2011-02-15  7:24 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Linus, please pull from:

  git://git.kernel.org/pub/scm/linux/kernel/git/djbw/async_tx.git fixes

Here is a collection of pent up fixes for 2.6.38 across ipu_idmac,
amba-pl08x, imx-dma, and imx-sdma.  Some have not appeared in -next, but
they have passed my build regression tests and been pending for a few
weeks.

--
Dan

Anatolij Gustschin (1):
      dma: ipu_idmac: do not lose valid received data in the irq handler

Dan Williams (2):
      Merge branch 'imx' into dmaengine-fixes
      dmaengine: add slave-dma maintainer

Russell King - ARM Linux (2):
      DMA: PL08x: fix infinite wait when terminating transfers
      DMA: PL08x: fix channel pausing to timeout rather than lockup

Sascha Hauer (12):
      dmaengine i.MX SDMA: Fix firmware loading
      dmaengine i.MX sdma: set maximum segment size for our device
      dmaengine i.MX sdma: check sg entries for valid addresses and lengths
      dmaengine i.MX SDMA: do not initialize chan_id field
      dmaengine i.MX SDMA: initialize dma capabilities outside channel loop
      dmaengine i.MX SDMA: reserve channel 0 by not registering it
      dmaengine i.MX dma: set maximum segment size for our device
      dmaengine i.MX dma: check sg entries for valid addresses and lengths
      dmaengine i.MX DMA: do not initialize chan_id field
      dmaengine i.MX dma: initialize dma capabilities outside channel loop
      Merge branch 'dmaengine-sdma' into dmaengine
      Merge branch 'dmaengine-shawn' into dmaengine

Shawn Guo (7):
      dmaengine: imx-sdma: propagate error in sdma_probe() instead of returning 0
      dmaengine: imx-sdma: fix inconsistent naming in sdma_assign_cookie()
      dmaengine: imx-sdma: remove IMX_DMA_SG_LOOP handling in sdma_prep_slave_sg()
      dmaengine: imx-sdma: set sdmac->status to DMA_ERROR in err_out of sdma_prep_slave_sg()
      dmaengine: imx-sdma: return sdmac->status in sdma_tx_status()
      dmaengine: imx-sdma: correct sdmac->status in sdma_handle_channel_loop()
      dmaengine: imx-sdma: fix up param for the last BD in sdma_prep_slave_sg()

 MAINTAINERS                 |    1 +
 drivers/dma/amba-pl08x.c    |   53 ++++++++++++++++----------
 drivers/dma/imx-dma.c       |   26 +++++++++++--
 drivers/dma/imx-sdma.c      |   88 +++++++++++++++++++++++--------------------
 drivers/dma/ipu/ipu_idmac.c |   50 ------------------------
 5 files changed, 103 insertions(+), 115 deletions(-)

commit 4abed0af1e9bc911f28bb525eece522d94d047f2
Author: Dan Williams <dan.j.williams@intel.com>
Date:   Mon Feb 14 00:42:08 2011 -0800

    dmaengine: add slave-dma maintainer
    
    Slave-dma has become the predominant usage model for dmaengine and needs
    special attention.  Memory-to-memory dma usage cases will continue to be
    maintained by Dan.
    
    Cc: Alan Cox <alan@linux.intel.com>
    Acked-by: Vinod Koul <vinod.koul@intel.com>
    Signed-off-by: Dan Williams <dan.j.williams@intel.com>

commit a646bd7f0824d3e0f02ff8d7410704f965de01bc
Author: Anatolij Gustschin <agust@denx.de>
Date:   Mon Jan 31 13:22:29 2011 +0100

    dma: ipu_idmac: do not lose valid received data in the irq handler
    
    Currently when two or more buffers are queued by the camera driver
    and so the double buffering is enabled in the idmac, we lose one
    frame comming from CSI since the reporting of arrival of the first
    frame is deferred by the DMAIC_7_EOF interrupt handler and reporting
    of the arrival of the last frame is not done at all. So when requesting
    N frames from the image sensor we actually receive N - 1 frames in
    user space.
    
    The reason for this behaviour is that the DMAIC_7_EOF interrupt
    handler misleadingly assumes that the CUR_BUF flag is pointing to the
    buffer used by the IDMAC. Actually it is not the case since the
    CUR_BUF flag will be flipped by the FSU when the FSU is sending the
    <TASK>_NEW_FRM_RDY signal when new frame data is delivered by the CSI.
    When sending this singal, FSU updates the DMA_CUR_BUF and the
    DMA_BUFx_RDY flags: the DMA_CUR_BUF is flipped, the DMA_BUFx_RDY
    is cleared, indicating that the frame data is beeing written by
    the IDMAC to the pointed buffer. DMA_BUFx_RDY is supposed to be
    set to the ready state again by the MCU, when it has handled the
    received data. DMAIC_7_CUR_BUF flag won't be flipped here by the
    IPU, so waiting for this event in the EOF interrupt handler is wrong.
    Actually there is no spurious interrupt as described in the comments,
    this is the valid DMAIC_7_EOF interrupt indicating reception of the
    frame from CSI.
    
    The patch removes code that waits for flipping of the DMAIC_7_CUR_BUF
    flag in the DMAIC_7_EOF interrupt handler. As the comment in the
    current code denotes, this waiting doesn't help anyway. As a result
    of this removal the reporting of the first arrived frame is not
    deferred to the time of arrival of the next frame and the drivers
    software flag 'ichan->active_buffer' is in sync with DMAIC_7_CUR_BUF
    flag, so the reception of all requested frames works.
    
    This has been verified on the hardware which is triggering the
    image sensor by the programmable state machine, allowing to
    obtain exact number of frames. On this hardware we do not tolerate
    losing frames.
    
    This patch also removes resetting the DMA_BUFx_RDY flags of
    all channels in ipu_disable_channel() since transfers on other
    DMA channels might be triggered by other running tasks and the
    buffers should always be ready for data sending or reception.
    
    Signed-off-by: Anatolij Gustschin <agust@denx.de>
    Reviewed-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
    Tested-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
    Signed-off-by: Dan Williams <dan.j.williams@intel.com>

commit 341b9419a8c0a4cdb75773c576870f1eb655516d
Author: Shawn Guo <shawn.guo@freescale.com>
Date:   Thu Jan 20 05:50:39 2011 +0800

    dmaengine: imx-sdma: fix up param for the last BD in sdma_prep_slave_sg()
    
    As per the reference manual, bit "L" should be set while bit "C"
    should be cleared for the last buffer descriptor in the non-cyclic
    chain, so that sdma can stop trying to find the next BD and end
    the transfer.
    
    In case of sdma_prep_slave_sg(), BD_LAST needs to be set and BD_CONT
    be cleared for the last BD.
    
    Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
    Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

commit 1e9cebb42de57f1243261939c77ab5b0f9bcf311
Author: Shawn Guo <shawn.guo@freescale.com>
Date:   Thu Jan 20 05:50:38 2011 +0800

    dmaengine: imx-sdma: correct sdmac->status in sdma_handle_channel_loop()
    
    sdma_handle_channel_loop() is the handler of cyclic tx.  One period
    success does not really mean the success of the tx.  Instead of
    DMA_SUCCESS, DMA_IN_PROGRESS should be the one to tell.
    
    Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
    Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

commit 8a9659114c7be6f88253618252881ea6fe0588b4
Author: Shawn Guo <shawn.guo@freescale.com>
Date:   Thu Jan 20 05:50:37 2011 +0800

    dmaengine: imx-sdma: return sdmac->status in sdma_tx_status()
    
    The sdmac->status was designed to reflect the status of the tx,
    so simply return it in sdma_tx_status().  Then dma client can call
    dma_async_is_tx_complete() to know the status of the tx.
    
    Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
    Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

commit 4b2ce9ddb370c4eb573540611c347d78ac4b54a0
Author: Shawn Guo <shawn.guo@freescale.com>
Date:   Thu Jan 20 05:50:36 2011 +0800

    dmaengine: imx-sdma: set sdmac->status to DMA_ERROR in err_out of sdma_prep_slave_sg()
    
    sdma_prep_dma_cyclic() sets sdmac->status to DMA_ERROR in err_out,
    and sdma_prep_slave_sg() needs to do the same.  Otherwise,
    sdmac->status stays at DMA_IN_PROGRESS, which will make the function
    return immediately next time it gets called.
    
    Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
    Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

commit 1797c33f0edcdcc9a483c06233a203786666a97f
Author: Shawn Guo <shawn.guo@freescale.com>
Date:   Thu Jan 20 05:50:35 2011 +0800

    dmaengine: imx-sdma: remove IMX_DMA_SG_LOOP handling in sdma_prep_slave_sg()
    
    This is a leftover from the time that the driver did not have
    sdma_prep_dma_cyclic callback and implemented sound dma as a looped
    sg chain.  And it can be removed now.
    
    Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
    Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

commit f8a356ff96a9070156f863e4f7716e2a0eb8c995
Author: Sascha Hauer <s.hauer@pengutronix.de>
Date:   Mon Jan 31 11:35:59 2011 +0100

    dmaengine i.MX dma: initialize dma capabilities outside channel loop
    
    The capabilities are device specific fields, not channel specific fields.
    
    Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

commit 97a43dfe84119528ec2576129b91d619219ab716
Author: Sascha Hauer <s.hauer@pengutronix.de>
Date:   Mon Jan 31 11:35:44 2011 +0100

    dmaengine i.MX DMA: do not initialize chan_id field
    
    Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

commit d07102a1bb0e759ce4571df30c62998ef5d8a8d3
Author: Sascha Hauer <s.hauer@pengutronix.de>
Date:   Wed Jan 12 14:13:23 2011 +0100

    dmaengine i.MX dma: check sg entries for valid addresses and lengths
    
    Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

commit 1e070a60997f5bbaadd498c34380e2aa110336cf
Author: Sascha Hauer <s.hauer@pengutronix.de>
Date:   Wed Jan 12 13:14:37 2011 +0100

    dmaengine i.MX dma: set maximum segment size for our device
    
    Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

commit 23889c6352ab4a842a30221bb412ff49954b2fb3
Author: Sascha Hauer <s.hauer@pengutronix.de>
Date:   Mon Jan 31 10:56:58 2011 +0100

    dmaengine i.MX SDMA: reserve channel 0 by not registering it
    
    We need channel 0 of the sdma engine for internal purposes. We
    accomplished this by calling dma_request_channel() in the probe
    function. This does not work when multiple dma engines are
    present which is the case when IPU support for i.MX31/35 is
    compiled in. So instead of registering channel 0 and reserving
    it afterwards simply do not register it in the first place.
    With this the dmaengine channel counting does not match sdma
    channel counting anymore, so we have to use sdma channel counting
    in the driver.
    
    Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

commit 7214a8b14f63a1603401124bc150e17b145aa476
Author: Sascha Hauer <s.hauer@pengutronix.de>
Date:   Mon Jan 31 10:21:35 2011 +0100

    dmaengine i.MX SDMA: initialize dma capabilities outside channel loop
    
    The capabilities are device specific fields, not channel specific fields.
    
    Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

commit 7a0e9b2557902bdca563a5eb1bbac87560bd7d20
Author: Sascha Hauer <s.hauer@pengutronix.de>
Date:   Mon Jan 31 10:19:53 2011 +0100

    dmaengine i.MX SDMA: do not initialize chan_id field
    
    This is bogus as the dmaengine core will overwrite this field.
    
    Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

commit 1fa81c270da4d8dffa84fcca448654a10ed0a5dc
Author: Sascha Hauer <s.hauer@pengutronix.de>
Date:   Wed Jan 12 13:02:28 2011 +0100

    dmaengine i.MX sdma: check sg entries for valid addresses and lengths
    
    This patch lets sdma_prep_slave_sg fail if the entries of an
    sg list do not start on multiples of the word size or if the
    lengths are not multiple of the word size.
    Also, catch the previously unhandled DMA_SLAVE_BUSWIDTH_8_BYTES
    and DMA_SLAVE_BUSWIDTH_UNDEFINED cases.
    
    Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

commit b9b3f82f94b52ebb0bbdf6cd77ccc5e8ee3f53b5
Author: Sascha Hauer <s.hauer@pengutronix.de>
Date:   Wed Jan 12 12:12:31 2011 +0100

    dmaengine i.MX sdma: set maximum segment size for our device
    
    Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>

commit 8179661694595eb3a4f2ff9bb0b73acbb7d2f4a9
Author: Russell King - ARM Linux <linux@arm.linux.org.uk>
Date:   Thu Jan 27 12:37:44 2011 +0000

    DMA: PL08x: fix channel pausing to timeout rather than lockup
    
    If a transfer is initiated from memory to a peripheral, then data is
    fetched and the channel is marked busy.  This busy status persists until
    the HALT bit is set and the queued data has been transfered to the
    peripheral.  Waiting indefinitely after setting the HALT bit results in
    system lockups.  Timeout this operation, and print an error when this
    happens.
    
    Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
    Acked-by: Linus Walleij <linus.walleij@stericsson.com>
    Signed-off-by: Dan Williams <dan.j.williams@intel.com>

commit fb526210b2b961b5d590b89fd8f45c0ca5769688
Author: Russell King - ARM Linux <linux@arm.linux.org.uk>
Date:   Thu Jan 27 12:32:53 2011 +0000

    DMA: PL08x: fix infinite wait when terminating transfers
    
    If we try to pause a channel when terminating a transfer, we could end
    up spinning for it to become inactive indefinitely, and can result in
    an uninterruptible wait requiring a reset to recover from.
    
    Terminating a transfer is supposed to take effect immediately, but may
    result in data loss.
    
    To make this clear, rename the function to pl08x_terminate_phy_chan().
    Also, make sure it is always consistently called - with the spinlock
    held and IRQs disabled, and ensure that the TC and ERR interrupt status
    is always cleared.
    
    Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
    Acked-by: Linus Walleij <linus.walleij@stericsson.com>
    Signed-off-by: Dan Williams <dan.j.williams@intel.com>

commit d718f4ebddcb0bebdbf771a6672756b666e5c31b
Author: Shawn Guo <shawn.guo@freescale.com>
Date:   Mon Jan 17 22:39:24 2011 +0800

    dmaengine: imx-sdma: fix inconsistent naming in sdma_assign_cookie()
    
    Variable name sdma and sdmac are consistently used as the pointer to
    sdma_engine and sdma_channel respectively throughout the file.  The
    patch fixes the inconsistency seen in function sdma_assign_cookie().
    
    Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
    Signed-off-by: Dan Williams <dan.j.williams@intel.com>

commit 939fd4f077269dd863cd630a3b3195a20acf7d02
Author: Shawn Guo <shawn.guo@freescale.com>
Date:   Wed Jan 19 19:13:06 2011 +0800

    dmaengine: imx-sdma: propagate error in sdma_probe() instead of returning 0
    
    Signed-off-by: Shawn Guo <shawn.guo@freescale.com>
    Acked-by: Uwe Kleine-K?nig <u.kleine-koenig@pengutronix.de>
    Signed-off-by: Dan Williams <dan.j.williams@intel.com>

commit 6866fd3b7289a283741752b73e0e09f410b7639d
Author: Sascha Hauer <s.hauer@pengutronix.de>
Date:   Wed Jan 12 11:18:14 2011 +0100

    dmaengine i.MX SDMA: Fix firmware loading
    
    When loading the microcode to the SDMA engine we have to use
    the ram_code_start_addr found in the firmware image. The copy
    in the sdma engine is not initialized correctly. This is broken
    since:
    5b28aa3 dmaengine i.MX SDMA: Allow to run without firmware
    
    Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
    Signed-off-by: Dan Williams <dan.j.williams@intel.com>

^ permalink raw reply

* [RFC,PATCH 1/3] Add a common struct clk
From: Jeremy Kerr @ 2011-02-15  7:26 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <4D5A100F.9000809@codeaurora.org>

Hi Saravana,

> Sure, one could argue that in some archs for a certain set of clocks the
> slow stuff in prepare/unprepare won't need to be done during set rate --
> say, a simple clock that always runs off the same PLL but just has a
> integer divider to change the rate.
> 
> In those cases, not grabbing the prepare_lock would make the code less
> "locky".
> 
> > We
> > may even want to disallow set_rate (and set_parent) when prepare_count is
> > non- zero.
> 
> This is definitely not right.

Why is that? Consider two devices using one clock; one does some 
initialisation based on the return value of clk_get_rate(), the other calls 
clk_set_rate() some time later. Now the first device is incorrectly 
initialised.

Regardless, this is definitely something to flag for a later discussion. I'm 
happy to return to that, but we should focus on one issue at a time here.

> Changing the rate of a clock when it's
> already enabled/prepared is a very reasonable thing to do. It's only
> doing a set rate at the "same time" as a prepare/unprepare that's wrong
> for some clocks. We could have the specific implementation deal with the
> locking internally.

Yes, hence leaving the locking here to the clock implementation.

> > I'd prefer to enforce the 'sleepability' with might_sleep instead.
> 
> Yeah, I realized this option after sending out my previous email. Please
> do add a might_sleep(). It will actually point out errors (per the new
> clarification) in some serial drivers.

Yep, will do.

> >>> +	.enable_lock	= __SPIN_LOCK_UNLOCKED(name.enable_lock),	\
> >>> +	.prepare_lock	= __MUTEX_INITIALIZER(name.prepare_lock),	\
> >> 
> >> After a long day, I'm not able to wrap my head around this. Probably a
> >> stupid question, but will this name.xxx thing prevent using this
> >> INIT_CLK macro to initialize an array of clocks? More specifically,
> >> prevent the sub class macro (like INIT_CLK_FIXED) from being used to
> >> initialize an array of clocks?
> > 
> > That's correct. For an array of clocks, you'll have to use a different
> > initialiser. We can add helpers for that that when (and if) the need
> > arises.
> 
> Would it even be possible to get this to work for an array? You don't
> have to change this in the patch, but I'm curious to know how to get
> this to work for an array without doing a run time init of the lock.

I'd assume that you'd have to do this at run time, as with any other array of 
structs that contain a mutex or spinlock.

Cheers,


Jeremy

^ permalink raw reply

* [PATCH] ARM: PXA: Make PXA27x/PXA3xx overlay actually work
From: Eric Miao @ 2011-02-15  7:35 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1296679619-32666-1-git-send-email-anarsoul@gmail.com>

On Thu, Feb 3, 2011 at 4:46 AM, Vasily Khoruzhick <anarsoul@gmail.com> wrote:
> From: "Russell King - ARM Linux" <linux@arm.linux.org.uk>
>
> Release callback tries to free memory even if it was not allocated in
> map_video_memory. Fix PXA27x/3xx overlay memory management and make overlay
> actually work.

That's indeed an issue.

>
> Added by Vasily Khoruzhick:
>
> - Move overlay Z-ordering selection into main fb initialization,
> otherwise plane ordering is wrong.
> - Clear x_res/y_res fields of fb.var on release, to make sure
> our callback will be called on next FBIOPUT_VSCREENINFO ioctl.
> - Disable overlay only if it was enabled.

The patch looks generally OK to me, some points for discussion
below though:

>
> Signed-off-by: Vasily Khoruzhick <anarsoul@gmail.com>
> ---
> ?drivers/video/pxafb.c | ? 86 ++++++++++++++++++++++++++++++------------------
> ?drivers/video/pxafb.h | ? ?2 +-
> ?2 files changed, 55 insertions(+), 33 deletions(-)
>
> diff --git a/drivers/video/pxafb.c b/drivers/video/pxafb.c
> index 825b665..33f607a 100644
> --- a/drivers/video/pxafb.c
> +++ b/drivers/video/pxafb.c
> @@ -629,16 +629,19 @@ static void overlay1fb_disable(struct pxafb_layer *ofb)
> ?{
> ? ? ? ?uint32_t lccr5 = lcd_readl(ofb->fbi, LCCR5);
>

Or maybe simply:

	if (lcd_readl(ofb->fbi, OVL1C1) & OVLxC1_OEN)
		return;

this makes this block of change much cleaner.

> - ? ? ? lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] & ~OVLxC1_OEN);
> + ? ? ? if (lcd_readl(ofb->fbi, OVL1C1) & OVLxC1_OEN) {
> + ? ? ? ? ? ? ? lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] & ~OVLxC1_OEN);
>
> - ? ? ? lcd_writel(ofb->fbi, LCSR1, LCSR1_BS(1));
> - ? ? ? lcd_writel(ofb->fbi, LCCR5, lccr5 & ~LCSR1_BS(1));
> - ? ? ? lcd_writel(ofb->fbi, FBR1, ofb->fbi->fdadr[DMA_OV1] | 0x3);
> + ? ? ? ? ? ? ? lcd_writel(ofb->fbi, LCSR1, LCSR1_BS(1));
> + ? ? ? ? ? ? ? lcd_writel(ofb->fbi, LCCR5, lccr5 & ~LCSR1_BS(1));
> + ? ? ? ? ? ? ? lcd_writel(ofb->fbi, FBR1, ofb->fbi->fdadr[DMA_OV1] | 0x3);
>
> - ? ? ? if (wait_for_completion_timeout(&ofb->branch_done, 1 * HZ) == 0)
> - ? ? ? ? ? ? ? pr_warning("%s: timeout disabling overlay1\n", __func__);
> + ? ? ? ? ? ? ? if (wait_for_completion_timeout(&ofb->branch_done, 1 * HZ) == 0)
> + ? ? ? ? ? ? ? ? ? ? ? pr_warning("%s: timeout disabling overlay1\n",
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? __func__);
>
> - ? ? ? lcd_writel(ofb->fbi, LCCR5, lccr5);
> + ? ? ? ? ? ? ? lcd_writel(ofb->fbi, LCCR5, lccr5);
> + ? ? ? }
> ?}
>
> ?static void overlay2fb_setup(struct pxafb_layer *ofb)
> @@ -687,16 +690,19 @@ static void overlay2fb_disable(struct pxafb_layer *ofb)
> ?{
> ? ? ? ?uint32_t lccr5 = lcd_readl(ofb->fbi, LCCR5);
>
> - ? ? ? lcd_writel(ofb->fbi, OVL2C1, ofb->control[0] & ~OVLxC1_OEN);
> + ? ? ? if (lcd_readl(ofb->fbi, OVL2C1) & OVLxC1_OEN) {
> + ? ? ? ? ? ? ? lcd_writel(ofb->fbi, OVL2C1, ofb->control[0] & ~OVLxC1_OEN);

Ditto.

>
> - ? ? ? lcd_writel(ofb->fbi, LCSR1, LCSR1_BS(2));
> - ? ? ? lcd_writel(ofb->fbi, LCCR5, lccr5 & ~LCSR1_BS(2));
> - ? ? ? lcd_writel(ofb->fbi, FBR2, ofb->fbi->fdadr[DMA_OV2_Y] ?| 0x3);
> - ? ? ? lcd_writel(ofb->fbi, FBR3, ofb->fbi->fdadr[DMA_OV2_Cb] | 0x3);
> - ? ? ? lcd_writel(ofb->fbi, FBR4, ofb->fbi->fdadr[DMA_OV2_Cr] | 0x3);
> + ? ? ? ? ? ? ? lcd_writel(ofb->fbi, LCSR1, LCSR1_BS(2));
> + ? ? ? ? ? ? ? lcd_writel(ofb->fbi, LCCR5, lccr5 & ~LCSR1_BS(2));
> + ? ? ? ? ? ? ? lcd_writel(ofb->fbi, FBR2, ofb->fbi->fdadr[DMA_OV2_Y] ?| 0x3);
> + ? ? ? ? ? ? ? lcd_writel(ofb->fbi, FBR3, ofb->fbi->fdadr[DMA_OV2_Cb] | 0x3);
> + ? ? ? ? ? ? ? lcd_writel(ofb->fbi, FBR4, ofb->fbi->fdadr[DMA_OV2_Cr] | 0x3);
>
> - ? ? ? if (wait_for_completion_timeout(&ofb->branch_done, 1 * HZ) == 0)
> - ? ? ? ? ? ? ? pr_warning("%s: timeout disabling overlay2\n", __func__);
> + ? ? ? ? ? ? ? if (wait_for_completion_timeout(&ofb->branch_done, 1 * HZ) == 0)
> + ? ? ? ? ? ? ? ? ? ? ? pr_warning("%s: timeout disabling overlay2\n",
> + ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? __func__);
> + ? ? ? }
> ?}
>
> ?static struct pxafb_layer_ops ofb_ops[] = {
> @@ -720,12 +726,10 @@ static int overlayfb_open(struct fb_info *info, int user)
> ? ? ? ?if (user == 0)
> ? ? ? ? ? ? ? ?return -ENODEV;
>
> - ? ? ? /* allow only one user at a time */
> - ? ? ? if (atomic_inc_and_test(&ofb->usage))
> - ? ? ? ? ? ? ? return -EBUSY;
> + ? ? ? if (ofb->usage++ == 0)
> + ? ? ? ? ? ? ? /* unblank the base framebuffer */
> + ? ? ? ? ? ? ? fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK);

The change above allows multiple user at a time? Then I guess
some other places need to be changed accordingly to avoid the
racing conditions.

If this is a feature request, can we postpone it to subsequent
patches?

>
> - ? ? ? /* unblank the base framebuffer */
> - ? ? ? fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK);
> ? ? ? ?return 0;
> ?}
>
> @@ -733,12 +737,24 @@ static int overlayfb_release(struct fb_info *info, int user)
> ?{
> ? ? ? ?struct pxafb_layer *ofb = (struct pxafb_layer*) info;
>
> - ? ? ? atomic_dec(&ofb->usage);
> - ? ? ? ofb->ops->disable(ofb);
> -
> - ? ? ? free_pages_exact(ofb->video_mem, ofb->video_mem_size);
> - ? ? ? ofb->video_mem = NULL;
> - ? ? ? ofb->video_mem_size = 0;
> + ? ? ? if (--ofb->usage == 0) {
> + ? ? ? ? ? ? ? ofb->ops->disable(ofb);
> + ? ? ? ? ? ? ? ofb->fb.var.height ? ? ?= -1;
> + ? ? ? ? ? ? ? ofb->fb.var.width ? ? ? = -1;
> + ? ? ? ? ? ? ? ofb->fb.var.xres = ofb->fb.var.xres_virtual = 0;
> + ? ? ? ? ? ? ? ofb->fb.var.yres = ofb->fb.var.yres_virtual = 0;
> +
> + ? ? ? ? ? ? ? mutex_lock(&ofb->fb.mm_lock);
> + ? ? ? ? ? ? ? ofb->fb.fix.smem_start ?= 0;
> + ? ? ? ? ? ? ? ofb->fb.fix.smem_len ? ?= 0;
> + ? ? ? ? ? ? ? mutex_unlock(&ofb->fb.mm_lock);
> +
> + ? ? ? ? ? ? ? if (ofb->video_mem) {
> + ? ? ? ? ? ? ? ? ? ? ? free_pages_exact(ofb->video_mem, ofb->video_mem_size);
> + ? ? ? ? ? ? ? ? ? ? ? ofb->video_mem = NULL;
> + ? ? ? ? ? ? ? ? ? ? ? ofb->video_mem_size = 0;
> + ? ? ? ? ? ? ? }
> + ? ? ? }
> ? ? ? ?return 0;
> ?}
>
> @@ -817,7 +833,8 @@ static int overlayfb_map_video_memory(struct pxafb_layer *ofb)
> ? ? ? ? ? ? ? ?if (ofb->video_mem_size >= size)
> ? ? ? ? ? ? ? ? ? ? ? ?return 0;
>
> - ? ? ? ? ? ? ? free_pages_exact(ofb->video_mem, ofb->video_mem_size);
> + ? ? ? ? ? ? ? /* don't re-allocate: userspace may have the buffer mapped */
> + ? ? ? ? ? ? ? return -EINVAL;
> ? ? ? ?}
>
> ? ? ? ?ofb->video_mem = alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
> @@ -891,7 +908,7 @@ static void __devinit init_pxafb_overlay(struct pxafb_info *fbi,
>
> ? ? ? ?ofb->id = id;
> ? ? ? ?ofb->ops = &ofb_ops[id];
> - ? ? ? atomic_set(&ofb->usage, 0);
> + ? ? ? ofb->usage = 0;
> ? ? ? ?ofb->fbi = fbi;
> ? ? ? ?init_completion(&ofb->branch_done);
> ?}
> @@ -923,8 +940,6 @@ static int __devinit pxafb_overlay_init(struct pxafb_info *fbi)
> ? ? ? ?/* mask all IU/BS/EOF/SOF interrupts */
> ? ? ? ?lcd_writel(fbi, LCCR5, ~0);
>
> - ? ? ? /* place overlay(s) on top of base */
> - ? ? ? fbi->lccr0 |= LCCR0_OUC;
> ? ? ? ?pr_info("PXA Overlay driver loaded successfully!\n");
> ? ? ? ?return 0;
> ?}
> @@ -1368,7 +1383,8 @@ static int pxafb_activate_var(struct fb_var_screeninfo *var,
> ? ? ? ? ? ?(lcd_readl(fbi, LCCR3) != fbi->reg_lccr3) ||
> ? ? ? ? ? ?(lcd_readl(fbi, LCCR4) != fbi->reg_lccr4) ||
> ? ? ? ? ? ?(lcd_readl(fbi, FDADR0) != fbi->fdadr[0]) ||
> - ? ? ? ? ? (lcd_readl(fbi, FDADR1) != fbi->fdadr[1]))
> + ? ? ? ? ? ((fbi->lccr0 & LCCR0_SDS) &&
> + ? ? ? ? ? (lcd_readl(fbi, FDADR1) != fbi->fdadr[1])))
> ? ? ? ? ? ? ? ?pxafb_schedule_work(fbi, C_REENABLE);
>
> ? ? ? ?return 0;
> @@ -1420,7 +1436,8 @@ static void pxafb_enable_controller(struct pxafb_info *fbi)
> ? ? ? ?lcd_writel(fbi, LCCR0, fbi->reg_lccr0 & ~LCCR0_ENB);
>
> ? ? ? ?lcd_writel(fbi, FDADR0, fbi->fdadr[0]);
> - ? ? ? lcd_writel(fbi, FDADR1, fbi->fdadr[1]);
> + ? ? ? if (fbi->lccr0 & LCCR0_SDS)
> + ? ? ? ? ? ? ? lcd_writel(fbi, FDADR1, fbi->fdadr[1]);

My original intention was to simplify the code a bit by ignoring
LCCR0_SDS, as FDADR1 would not take effect if not enabled even
if it's being read/written.

> ? ? ? ?lcd_writel(fbi, LCCR0, fbi->reg_lccr0 | LCCR0_ENB);
> ?}
>
> @@ -1806,6 +1823,11 @@ static struct pxafb_info * __devinit pxafb_init_fbinfo(struct device *dev)
>
> ? ? ? ?pxafb_decode_mach_info(fbi, inf);
>
> +#ifdef CONFIG_FB_PXA_OVERLAY
> + ? ? ? if (cpu_is_pxa27x())
> + ? ? ? ? ? ? ? fbi->lccr0 |= LCCR0_OUC;
> +#endif
> +

I seem to remember LCCR0_OUC is still valid on pxa3xx, did you
do some test on pxa3xx as well?

> ? ? ? ?init_waitqueue_head(&fbi->ctrlr_wait);
> ? ? ? ?INIT_WORK(&fbi->task, pxafb_task);
> ? ? ? ?mutex_init(&fbi->ctrlr_lock);
> diff --git a/drivers/video/pxafb.h b/drivers/video/pxafb.h
> index 2353521..84e3ae1 100644
> --- a/drivers/video/pxafb.h
> +++ b/drivers/video/pxafb.h
> @@ -92,7 +92,7 @@ struct pxafb_layer_ops {
> ?struct pxafb_layer {
> ? ? ? ?struct fb_info ? ? ? ? ?fb;
> ? ? ? ?int ? ? ? ? ? ? ? ? ? ? id;
> - ? ? ? atomic_t ? ? ? ? ? ? ? ?usage;
> + ? ? ? uint32_t ? ? ? ? ? ? ? ?usage;
> ? ? ? ?uint32_t ? ? ? ? ? ? ? ?control[2];
>
> ? ? ? ?struct pxafb_layer_ops ?*ops;
> --
> 1.7.4.rc1
>
>

^ permalink raw reply

* [PATCH] Clean up set_pxa_fb_info
From: Eric Miao @ 2011-02-15  7:38 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <20110213103510.GA4799@n2100.arm.linux.org.uk>

On Sun, Feb 13, 2011 at 6:35 PM, Russell King - ARM Linux
<linux@arm.linux.org.uk> wrote:
> Eric, ping.
>

Merged.

> On Sun, Feb 06, 2011 at 11:52:54AM +0000, Russell King - ARM Linux wrote:
>> set_pxa_fb_info() has been a long-standing wart in the naming scheme
>> of the pxa_set_xxx_info() functions. ?This renames the function, and
>> combines set_pxa_fb_parent() with set_pxa_fb_info().
>>
>> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
>> ---
>> I've had this patch sitting around for a while, so it's been updated.
>> It might be worth merging it.
>>
>> ?arch/arm/mach-pxa/am200epd.c ? ? ? ? ? ? ?| ? ?4 ++--
>> ?arch/arm/mach-pxa/balloon3.c ? ? ? ? ? ? ?| ? ?2 +-
>> ?arch/arm/mach-pxa/cm-x2xx.c ? ? ? ? ? ? ? | ? ?2 +-
>> ?arch/arm/mach-pxa/cm-x300.c ? ? ? ? ? ? ? | ? ?2 +-
>> ?arch/arm/mach-pxa/colibri-pxa270-income.c | ? ?2 +-
>> ?arch/arm/mach-pxa/colibri-pxa3xx.c ? ? ? ?| ? ?2 +-
>> ?arch/arm/mach-pxa/devices.c ? ? ? ? ? ? ? | ? ?8 ++------
>> ?arch/arm/mach-pxa/em-x270.c ? ? ? ? ? ? ? | ? ?2 +-
>> ?arch/arm/mach-pxa/eseries.c ? ? ? ? ? ? ? | ? ?2 +-
>> ?arch/arm/mach-pxa/ezx.c ? ? ? ? ? ? ? ? ? | ? 12 ++++++------
>> ?arch/arm/mach-pxa/idp.c ? ? ? ? ? ? ? ? ? | ? ?2 +-
>> ?arch/arm/mach-pxa/include/mach/pxafb.h ? ?| ? ?3 +--
>> ?arch/arm/mach-pxa/littleton.c ? ? ? ? ? ? | ? ?2 +-
>> ?arch/arm/mach-pxa/lpd270.c ? ? ? ? ? ? ? ?| ? ?2 +-
>> ?arch/arm/mach-pxa/lubbock.c ? ? ? ? ? ? ? | ? ?2 +-
>> ?arch/arm/mach-pxa/magician.c ? ? ? ? ? ? ?| ? ?2 +-
>> ?arch/arm/mach-pxa/mainstone.c ? ? ? ? ? ? | ? ?2 +-
>> ?arch/arm/mach-pxa/mioa701.c ? ? ? ? ? ? ? | ? ?2 +-
>> ?arch/arm/mach-pxa/palm27x.c ? ? ? ? ? ? ? | ? ?2 +-
>> ?arch/arm/mach-pxa/palmtc.c ? ? ? ? ? ? ? ?| ? ?2 +-
>> ?arch/arm/mach-pxa/palmte2.c ? ? ? ? ? ? ? | ? ?2 +-
>> ?arch/arm/mach-pxa/pcm990-baseboard.c ? ? ?| ? ?2 +-
>> ?arch/arm/mach-pxa/poodle.c ? ? ? ? ? ? ? ?| ? ?3 +--
>> ?arch/arm/mach-pxa/raumfeld.c ? ? ? ? ? ? ?| ? ?2 +-
>> ?arch/arm/mach-pxa/saar.c ? ? ? ? ? ? ? ? ?| ? ?2 +-
>> ?arch/arm/mach-pxa/spitz.c ? ? ? ? ? ? ? ? | ? ?2 +-
>> ?arch/arm/mach-pxa/tavorevb.c ? ? ? ? ? ? ?| ? ?2 +-
>> ?arch/arm/mach-pxa/trizeps4.c ? ? ? ? ? ? ?| ? ?4 ++--
>> ?arch/arm/mach-pxa/viper.c ? ? ? ? ? ? ? ? | ? ?2 +-
>> ?arch/arm/mach-pxa/vpac270.c ? ? ? ? ? ? ? | ? ?2 +-
>> ?arch/arm/mach-pxa/z2.c ? ? ? ? ? ? ? ? ? ?| ? ?2 +-
>> ?arch/arm/mach-pxa/zeus.c ? ? ? ? ? ? ? ? ?| ? ?2 +-
>> ?arch/arm/mach-pxa/zylonite.c ? ? ? ? ? ? ?| ? ?4 ++--
>> ?33 files changed, 42 insertions(+), 48 deletions(-)
>>
>> diff --git a/arch/arm/mach-pxa/am200epd.c b/arch/arm/mach-pxa/am200epd.c
>> index 3499fad..10964e3 100644
>> --- a/arch/arm/mach-pxa/am200epd.c
>> +++ b/arch/arm/mach-pxa/am200epd.c
>> @@ -194,7 +194,7 @@ static struct notifier_block am200_fb_notif = {
>> ?};
>>
>> ?/* this gets called as part of our init. these steps must be done now so
>> - * that we can use set_pxa_fb_info */
>> + * that we can use pxa_set_fb_info */
>> ?static void __init am200_presetup_fb(void)
>> ?{
>> ? ? ? int fw;
>> @@ -249,7 +249,7 @@ static void __init am200_presetup_fb(void)
>> ? ? ? /* we divide since we told the LCD controller we're 16bpp */
>> ? ? ? am200_fb_info.modes->xres /= 2;
>>
>> - ? ? set_pxa_fb_info(&am200_fb_info);
>> + ? ? pxa_set_fb_info(NULL, &am200_fb_info);
>>
>> ?}
>>
>> diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
>> index e194d92..0e12667 100644
>> --- a/arch/arm/mach-pxa/balloon3.c
>> +++ b/arch/arm/mach-pxa/balloon3.c
>> @@ -264,7 +264,7 @@ static void __init balloon3_lcd_init(void)
>> ? ? ? }
>>
>> ? ? ? balloon3_lcd_screen.pxafb_backlight_power = balloon3_backlight_power;
>> - ? ? set_pxa_fb_info(&balloon3_lcd_screen);
>> + ? ? pxa_set_fb_info(NULL, &balloon3_lcd_screen);
>> ? ? ? return;
>>
>> ?err2:
>> diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c
>> index b734d84..8225e2e 100644
>> --- a/arch/arm/mach-pxa/cm-x2xx.c
>> +++ b/arch/arm/mach-pxa/cm-x2xx.c
>> @@ -379,7 +379,7 @@ __setup("monitor=", cmx2xx_set_display);
>>
>> ?static void __init cmx2xx_init_display(void)
>> ?{
>> - ? ? set_pxa_fb_info(cmx2xx_display);
>> + ? ? pxa_set_fb_info(NULL, cmx2xx_display);
>> ?}
>> ?#else
>> ?static inline void cmx2xx_init_display(void) {}
>> diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
>> index 7984268..0c9cfbc 100644
>> --- a/arch/arm/mach-pxa/cm-x300.c
>> +++ b/arch/arm/mach-pxa/cm-x300.c
>> @@ -296,7 +296,7 @@ static struct pxafb_mach_info cm_x300_lcd = {
>>
>> ?static void __init cm_x300_init_lcd(void)
>> ?{
>> - ? ? set_pxa_fb_info(&cm_x300_lcd);
>> + ? ? pxa_set_fb_info(NULL, &cm_x300_lcd);
>> ?}
>> ?#else
>> ?static inline void cm_x300_init_lcd(void) {}
>> diff --git a/arch/arm/mach-pxa/colibri-pxa270-income.c b/arch/arm/mach-pxa/colibri-pxa270-income.c
>> index 07b62a0..c2f164b 100644
>> --- a/arch/arm/mach-pxa/colibri-pxa270-income.c
>> +++ b/arch/arm/mach-pxa/colibri-pxa270-income.c
>> @@ -176,7 +176,7 @@ static struct pxafb_mach_info income_lcd_screen = {
>>
>> ?static void __init income_lcd_init(void)
>> ?{
>> - ? ? set_pxa_fb_info(&income_lcd_screen);
>> + ? ? pxa_set_fb_info(NULL, &income_lcd_screen);
>> ?}
>> ?#else
>> ?static inline void income_lcd_init(void) {}
>> diff --git a/arch/arm/mach-pxa/colibri-pxa3xx.c b/arch/arm/mach-pxa/colibri-pxa3xx.c
>> index 96b2d9f..3f9be41 100644
>> --- a/arch/arm/mach-pxa/colibri-pxa3xx.c
>> +++ b/arch/arm/mach-pxa/colibri-pxa3xx.c
>> @@ -105,7 +105,7 @@ void __init colibri_pxa3xx_init_lcd(int bl_pin)
>> ? ? ? lcd_bl_pin = bl_pin;
>> ? ? ? gpio_request(bl_pin, "lcd backlight");
>> ? ? ? gpio_direction_output(bl_pin, 0);
>> - ? ? set_pxa_fb_info(&sharp_lq43_info);
>> + ? ? pxa_set_fb_info(NULL, &sharp_lq43_info);
>> ?}
>> ?#endif
>>
>> diff --git a/arch/arm/mach-pxa/devices.c b/arch/arm/mach-pxa/devices.c
>> index 4c766e3..edfe803 100644
>> --- a/arch/arm/mach-pxa/devices.c
>> +++ b/arch/arm/mach-pxa/devices.c
>> @@ -188,16 +188,12 @@ struct platform_device pxa_device_fb = {
>> ? ? ? .resource ? ? ? = pxafb_resources,
>> ?};
>>
>> -void __init set_pxa_fb_info(struct pxafb_mach_info *info)
>> +void __init pxa_set_fb_info(struct device *parent, struct pxafb_mach_info *info)
>> ?{
>> + ? ? pxa_device_fb.dev.parent = parent;
>> ? ? ? pxa_register_device(&pxa_device_fb, info);
>> ?}
>>
>> -void __init set_pxa_fb_parent(struct device *parent_dev)
>> -{
>> - ? ? pxa_device_fb.dev.parent = parent_dev;
>> -}
>> -
>> ?static struct resource pxa_resource_ffuart[] = {
>> ? ? ? {
>> ? ? ? ? ? ? ? .start ?= 0x40100000,
>> diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
>> index a78bb30..2da03a4 100644
>> --- a/arch/arm/mach-pxa/em-x270.c
>> +++ b/arch/arm/mach-pxa/em-x270.c
>> @@ -689,7 +689,7 @@ static struct pxafb_mach_info em_x270_lcd = {
>>
>> ?static void __init em_x270_init_lcd(void)
>> ?{
>> - ? ? set_pxa_fb_info(&em_x270_lcd);
>> + ? ? pxa_set_fb_info(NULL, &em_x270_lcd);
>> ?}
>> ?#else
>> ?static inline void em_x270_init_lcd(void) {}
>> diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c
>> index edca0a0..8fdf5a3 100644
>> --- a/arch/arm/mach-pxa/eseries.c
>> +++ b/arch/arm/mach-pxa/eseries.c
>> @@ -344,7 +344,7 @@ static void __init e400_init(void)
>> ? ? ? /* Fixme - e400 may have a switched clock */
>> ? ? ? eseries_register_clks();
>> ? ? ? eseries_get_tmio_gpios();
>> - ? ? set_pxa_fb_info(&e400_pxafb_mach_info);
>> + ? ? pxa_set_fb_info(NULL, &e400_pxafb_mach_info);
>> ? ? ? platform_add_devices(ARRAY_AND_SIZE(e400_devices));
>> ? ? ? pxa_set_udc_info(&e7xx_udc_mach_info);
>> ?}
>> diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
>> index 87cec0a..fcd366a 100644
>> --- a/arch/arm/mach-pxa/ezx.c
>> +++ b/arch/arm/mach-pxa/ezx.c
>> @@ -783,7 +783,7 @@ static void __init a780_init(void)
>>
>> ? ? ? pxa_set_i2c_info(NULL);
>>
>> - ? ? set_pxa_fb_info(&ezx_fb_info_1);
>> + ? ? pxa_set_fb_info(NULL, &ezx_fb_info_1);
>>
>> ? ? ? pxa_set_keypad_info(&a780_keypad_platform_data);
>>
>> @@ -853,7 +853,7 @@ static void __init e680_init(void)
>> ? ? ? pxa_set_i2c_info(NULL);
>> ? ? ? i2c_register_board_info(0, ARRAY_AND_SIZE(e680_i2c_board_info));
>>
>> - ? ? set_pxa_fb_info(&ezx_fb_info_1);
>> + ? ? pxa_set_fb_info(NULL, &ezx_fb_info_1);
>>
>> ? ? ? pxa_set_keypad_info(&e680_keypad_platform_data);
>>
>> @@ -918,7 +918,7 @@ static void __init a1200_init(void)
>> ? ? ? pxa_set_i2c_info(NULL);
>> ? ? ? i2c_register_board_info(0, ARRAY_AND_SIZE(a1200_i2c_board_info));
>>
>> - ? ? set_pxa_fb_info(&ezx_fb_info_2);
>> + ? ? pxa_set_fb_info(NULL, &ezx_fb_info_2);
>>
>> ? ? ? pxa_set_keypad_info(&a1200_keypad_platform_data);
>>
>> @@ -1103,7 +1103,7 @@ static void __init a910_init(void)
>> ? ? ? pxa_set_i2c_info(NULL);
>> ? ? ? i2c_register_board_info(0, ARRAY_AND_SIZE(a910_i2c_board_info));
>>
>> - ? ? set_pxa_fb_info(&ezx_fb_info_2);
>> + ? ? pxa_set_fb_info(NULL, &ezx_fb_info_2);
>>
>> ? ? ? pxa_set_keypad_info(&a910_keypad_platform_data);
>>
>> @@ -1173,7 +1173,7 @@ static void __init e6_init(void)
>> ? ? ? pxa_set_i2c_info(NULL);
>> ? ? ? i2c_register_board_info(0, ARRAY_AND_SIZE(e6_i2c_board_info));
>>
>> - ? ? set_pxa_fb_info(&ezx_fb_info_2);
>> + ? ? pxa_set_fb_info(NULL, &ezx_fb_info_2);
>>
>> ? ? ? pxa_set_keypad_info(&e6_keypad_platform_data);
>>
>> @@ -1212,7 +1212,7 @@ static void __init e2_init(void)
>> ? ? ? pxa_set_i2c_info(NULL);
>> ? ? ? i2c_register_board_info(0, ARRAY_AND_SIZE(e2_i2c_board_info));
>>
>> - ? ? set_pxa_fb_info(&ezx_fb_info_2);
>> + ? ? pxa_set_fb_info(NULL, &ezx_fb_info_2);
>>
>> ? ? ? pxa_set_keypad_info(&e2_keypad_platform_data);
>>
>> diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
>> index dd40e4a..f7fb64f 100644
>> --- a/arch/arm/mach-pxa/idp.c
>> +++ b/arch/arm/mach-pxa/idp.c
>> @@ -167,7 +167,7 @@ static void __init idp_init(void)
>>
>> ? ? ? platform_device_register(&smc91x_device);
>> ? ? ? //platform_device_register(&mst_audio_device);
>> - ? ? set_pxa_fb_info(&sharp_lm8v31);
>> + ? ? pxa_set_fb_info(NULL, &sharp_lm8v31);
>> ? ? ? pxa_set_mci_info(&idp_mci_platform_data);
>> ?}
>>
>> diff --git a/arch/arm/mach-pxa/include/mach/pxafb.h b/arch/arm/mach-pxa/include/mach/pxafb.h
>> index 160ec83..1288e83 100644
>> --- a/arch/arm/mach-pxa/include/mach/pxafb.h
>> +++ b/arch/arm/mach-pxa/include/mach/pxafb.h
>> @@ -154,8 +154,7 @@ struct pxafb_mach_info {
>> ? ? ? void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
>> ? ? ? void (*smart_update)(struct fb_info *);
>> ?};
>> -void set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info);
>> -void set_pxa_fb_parent(struct device *parent_dev);
>> +void pxa_set_fb_info(struct pxafb_mach_info *hard_pxa_fb_info);
>> ?unsigned long pxafb_get_hsync_time(struct device *dev);
>>
>> ?extern int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int);
>> diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
>> index ccb7bfa..4b2c45f 100644
>> --- a/arch/arm/mach-pxa/littleton.c
>> +++ b/arch/arm/mach-pxa/littleton.c
>> @@ -185,7 +185,7 @@ static struct pxafb_mach_info littleton_lcd_info = {
>>
>> ?static void littleton_init_lcd(void)
>> ?{
>> - ? ? set_pxa_fb_info(&littleton_lcd_info);
>> + ? ? pxa_set_fb_info(NULL, &littleton_lcd_info);
>> ?}
>> ?#else
>> ?static inline void littleton_init_lcd(void) {};
>> diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
>> index c9a3e77..8aebc58 100644
>> --- a/arch/arm/mach-pxa/lpd270.c
>> +++ b/arch/arm/mach-pxa/lpd270.c
>> @@ -480,7 +480,7 @@ static void __init lpd270_init(void)
>> ? ? ? pxa_set_ac97_info(NULL);
>>
>> ? ? ? if (lpd270_lcd_to_use != NULL)
>> - ? ? ? ? ? ? set_pxa_fb_info(lpd270_lcd_to_use);
>> + ? ? ? ? ? ? pxa_set_fb_info(NULL, lpd270_lcd_to_use);
>>
>> ? ? ? pxa_set_ohci_info(&lpd270_ohci_platform_data);
>> ?}
>> diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
>> index dca20de..12a2a56 100644
>> --- a/arch/arm/mach-pxa/lubbock.c
>> +++ b/arch/arm/mach-pxa/lubbock.c
>> @@ -521,7 +521,7 @@ static void __init lubbock_init(void)
>>
>> ? ? ? clk_add_alias("SA1111_CLK", NULL, "GPIO11_CLK", NULL);
>> ? ? ? pxa_set_udc_info(&udc_info);
>> - ? ? set_pxa_fb_info(&sharp_lm8v31);
>> + ? ? pxa_set_fb_info(NULL, &sharp_lm8v31);
>> ? ? ? pxa_set_mci_info(&lubbock_mci_platform_data);
>> ? ? ? pxa_set_ficp_info(&lubbock_ficp_platform_data);
>> ? ? ? pxa_set_ac97_info(NULL);
>> diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
>> index 41198f0..ad70264 100644
>> --- a/arch/arm/mach-pxa/magician.c
>> +++ b/arch/arm/mach-pxa/magician.c
>> @@ -757,7 +757,7 @@ static void __init magician_init(void)
>> ? ? ? ? ? ? ? gpio_direction_output(GPIO104_MAGICIAN_LCD_POWER_1, 0);
>> ? ? ? ? ? ? ? gpio_direction_output(GPIO105_MAGICIAN_LCD_POWER_2, 0);
>> ? ? ? ? ? ? ? gpio_direction_output(GPIO106_MAGICIAN_LCD_POWER_3, 0);
>> - ? ? ? ? ? ? set_pxa_fb_info(lcd_select ? &samsung_info : &toppoly_info);
>> + ? ? ? ? ? ? pxa_set_fb_info(NULL, lcd_select ? &samsung_info : &toppoly_info);
>> ? ? ? } else
>> ? ? ? ? ? ? ? pr_err("LCD detection: CPLD mapping failed\n");
>> ?}
>> diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
>> index d4b6f23..a58f522 100644
>> --- a/arch/arm/mach-pxa/mainstone.c
>> +++ b/arch/arm/mach-pxa/mainstone.c
>> @@ -592,7 +592,7 @@ static void __init mainstone_init(void)
>> ? ? ? else
>> ? ? ? ? ? ? ? mainstone_pxafb_info.modes = &toshiba_ltm035a776c_mode;
>>
>> - ? ? set_pxa_fb_info(&mainstone_pxafb_info);
>> + ? ? pxa_set_fb_info(NULL, &mainstone_pxafb_info);
>> ? ? ? mainstone_backlight_register();
>>
>> ? ? ? pxa_set_mci_info(&mainstone_mci_platform_data);
>> diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
>> index faafea3..18e05b1 100644
>> --- a/arch/arm/mach-pxa/mioa701.c
>> +++ b/arch/arm/mach-pxa/mioa701.c
>> @@ -795,7 +795,7 @@ static void __init mioa701_machine_init(void)
>> ? ? ? pxa_set_stuart_info(NULL);
>> ? ? ? mio_gpio_request(ARRAY_AND_SIZE(global_gpios));
>> ? ? ? bootstrap_init();
>> - ? ? set_pxa_fb_info(&mioa701_pxafb_info);
>> + ? ? pxa_set_fb_info(NULL, &mioa701_pxafb_info);
>> ? ? ? pxa_set_mci_info(&mioa701_mci_info);
>> ? ? ? pxa_set_keypad_info(&mioa701_keypad_info);
>> ? ? ? pxa_set_udc_info(&mioa701_udc_info);
>> diff --git a/arch/arm/mach-pxa/palm27x.c b/arch/arm/mach-pxa/palm27x.c
>> index 405b92a..4f26d78 100644
>> --- a/arch/arm/mach-pxa/palm27x.c
>> +++ b/arch/arm/mach-pxa/palm27x.c
>> @@ -159,7 +159,7 @@ void __init palm27x_lcd_init(int power, struct pxafb_mode_info *mode)
>> ? ? ? ? ? ? ? palm27x_lcd_screen.pxafb_lcd_power = palm27x_lcd_ctl;
>> ? ? ? }
>>
>> - ? ? set_pxa_fb_info(&palm27x_lcd_screen);
>> + ? ? pxa_set_fb_info(NULL, &palm27x_lcd_screen);
>> ?}
>> ?#endif
>>
>> diff --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c
>> index a09a237..fb06bd0 100644
>> --- a/arch/arm/mach-pxa/palmtc.c
>> +++ b/arch/arm/mach-pxa/palmtc.c
>> @@ -507,7 +507,7 @@ static struct pxafb_mach_info palmtc_lcd_screen = {
>>
>> ?static void __init palmtc_lcd_init(void)
>> ?{
>> - ? ? set_pxa_fb_info(&palmtc_lcd_screen);
>> + ? ? pxa_set_fb_info(NULL, &palmtc_lcd_screen);
>> ?}
>> ?#else
>> ?static inline void palmtc_lcd_init(void) {}
>> diff --git a/arch/arm/mach-pxa/palmte2.c b/arch/arm/mach-pxa/palmte2.c
>> index 3f25014..7fdf099 100644
>> --- a/arch/arm/mach-pxa/palmte2.c
>> +++ b/arch/arm/mach-pxa/palmte2.c
>> @@ -363,7 +363,7 @@ static void __init palmte2_init(void)
>> ? ? ? pxa_set_btuart_info(NULL);
>> ? ? ? pxa_set_stuart_info(NULL);
>>
>> - ? ? set_pxa_fb_info(&palmte2_lcd_screen);
>> + ? ? pxa_set_fb_info(NULL, &palmte2_lcd_screen);
>> ? ? ? pxa_set_mci_info(&palmte2_mci_platform_data);
>> ? ? ? palmte2_udc_init();
>> ? ? ? pxa_set_ac97_info(&palmte2_ac97_pdata);
>> diff --git a/arch/arm/mach-pxa/pcm990-baseboard.c b/arch/arm/mach-pxa/pcm990-baseboard.c
>> index 90820fa..c1a6448 100644
>> --- a/arch/arm/mach-pxa/pcm990-baseboard.c
>> +++ b/arch/arm/mach-pxa/pcm990-baseboard.c
>> @@ -515,7 +515,7 @@ void __init pcm990_baseboard_init(void)
>> ? ? ? pcm990_init_irq();
>>
>> ?#ifndef CONFIG_PCM990_DISPLAY_NONE
>> - ? ? set_pxa_fb_info(&pcm990_fbinfo);
>> + ? ? pxa_set_fb_info(NULL, &pcm990_fbinfo);
>> ?#endif
>> ? ? ? platform_device_register(&pcm990_backlight_device);
>>
>> diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
>> index 4f0ff1a..be68ec5 100644
>> --- a/arch/arm/mach-pxa/poodle.c
>> +++ b/arch/arm/mach-pxa/poodle.c
>> @@ -445,8 +445,7 @@ static void __init poodle_init(void)
>> ? ? ? if (ret)
>> ? ? ? ? ? ? ? pr_warning("poodle: Unable to register LoCoMo device\n");
>>
>> - ? ? set_pxa_fb_parent(&poodle_locomo_device.dev);
>> - ? ? set_pxa_fb_info(&poodle_fb_info);
>> + ? ? pxa_set_fb_info(&poodle_locomo_device.dev, &poodle_fb_info);
>> ? ? ? pxa_set_udc_info(&udc_info);
>> ? ? ? pxa_set_mci_info(&poodle_mci_platform_data);
>> ? ? ? pxa_set_ficp_info(&poodle_ficp_platform_data);
>> diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
>> index 8361151..d9a5791 100644
>> --- a/arch/arm/mach-pxa/raumfeld.c
>> +++ b/arch/arm/mach-pxa/raumfeld.c
>> @@ -597,7 +597,7 @@ static void __init raumfeld_lcd_init(void)
>> ?{
>> ? ? ? int ret;
>>
>> - ? ? set_pxa_fb_info(&raumfeld_sharp_lcd_info);
>> + ? ? pxa_set_fb_info(NULL, &raumfeld_sharp_lcd_info);
>>
>> ? ? ? /* Earlier devices had the backlight regulator controlled
>> ? ? ? ?* via PWM, later versions use another controller for that */
>> diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c
>> index c1ca8cb..dd0118f 100644
>> --- a/arch/arm/mach-pxa/saar.c
>> +++ b/arch/arm/mach-pxa/saar.c
>> @@ -473,7 +473,7 @@ static struct pxafb_mach_info saar_lcd_info = {
>>
>> ?static void __init saar_init_lcd(void)
>> ?{
>> - ? ? set_pxa_fb_info(&saar_lcd_info);
>> + ? ? pxa_set_fb_info(NULL, &saar_lcd_info);
>> ?}
>> ?#else
>> ?static inline void saar_init_lcd(void) {}
>> diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
>> index b49a2c2..e646b6d 100644
>> --- a/arch/arm/mach-pxa/spitz.c
>> +++ b/arch/arm/mach-pxa/spitz.c
>> @@ -725,7 +725,7 @@ static struct pxafb_mach_info spitz_pxafb_info = {
>>
>> ?static void __init spitz_lcd_init(void)
>> ?{
>> - ? ? set_pxa_fb_info(&spitz_pxafb_info);
>> + ? ? pxa_set_fb_info(NULL, &spitz_pxafb_info);
>> ?}
>> ?#else
>> ?static inline void spitz_lcd_init(void) {}
>> diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c
>> index 9cecf83..53d4a47 100644
>> --- a/arch/arm/mach-pxa/tavorevb.c
>> +++ b/arch/arm/mach-pxa/tavorevb.c
>> @@ -466,7 +466,7 @@ static void __init tavorevb_init_lcd(void)
>> ?{
>> ? ? ? platform_device_register(&tavorevb_backlight_devices[0]);
>> ? ? ? platform_device_register(&tavorevb_backlight_devices[1]);
>> - ? ? set_pxa_fb_info(&tavorevb_lcd_info);
>> + ? ? pxa_set_fb_info(NULL, &tavorevb_lcd_info);
>> ?}
>> ?#else
>> ?static inline void tavorevb_init_lcd(void) {}
>> diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
>> index 423261d..fa510fd 100644
>> --- a/arch/arm/mach-pxa/trizeps4.c
>> +++ b/arch/arm/mach-pxa/trizeps4.c
>> @@ -516,9 +516,9 @@ static void __init trizeps4_init(void)
>> ? ? ? pxa_set_stuart_info(NULL);
>>
>> ? ? ? if (0) ?/* dont know how to determine LCD */
>> - ? ? ? ? ? ? set_pxa_fb_info(&sharp_lcd);
>> + ? ? ? ? ? ? pxa_set_fb_info(NULL, &sharp_lcd);
>> ? ? ? else
>> - ? ? ? ? ? ? set_pxa_fb_info(&toshiba_lcd);
>> + ? ? ? ? ? ? pxa_set_fb_info(NULL, &toshiba_lcd);
>>
>> ? ? ? pxa_set_mci_info(&trizeps4_mci_platform_data);
>> ?#ifndef STATUS_LEDS_ON_STUART_PINS
>> diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
>> index 49eeeab..53b2495 100644
>> --- a/arch/arm/mach-pxa/viper.c
>> +++ b/arch/arm/mach-pxa/viper.c
>> @@ -932,7 +932,7 @@ static void __init viper_init(void)
>> ? ? ? /* Wake-up serial console */
>> ? ? ? viper_init_serial_gpio();
>>
>> - ? ? set_pxa_fb_info(&fb_info);
>> + ? ? pxa_set_fb_info(NULL, &fb_info);
>>
>> ? ? ? /* v1 hardware cannot use the datacs line */
>> ? ? ? version = viper_hw_version();
>> diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c
>> index b9b5797..a46f8d1 100644
>> --- a/arch/arm/mach-pxa/vpac270.c
>> +++ b/arch/arm/mach-pxa/vpac270.c
>> @@ -573,7 +573,7 @@ static void __init vpac270_lcd_init(void)
>> ? ? ? }
>>
>> ? ? ? vpac270_lcd_screen.pxafb_lcd_power = vpac270_lcd_power;
>> - ? ? set_pxa_fb_info(&vpac270_lcd_screen);
>> + ? ? pxa_set_fb_info(NULL, &vpac270_lcd_screen);
>> ? ? ? return;
>>
>> ?err2:
>> diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
>> index a323e07..084c724 100644
>> --- a/arch/arm/mach-pxa/z2.c
>> +++ b/arch/arm/mach-pxa/z2.c
>> @@ -272,7 +272,7 @@ static struct pxafb_mach_info z2_lcd_screen = {
>>
>> ?static void __init z2_lcd_init(void)
>> ?{
>> - ? ? set_pxa_fb_info(&z2_lcd_screen);
>> + ? ? pxa_set_fb_info(NULL, &z2_lcd_screen);
>> ?}
>> ?#else
>> ?static inline void z2_lcd_init(void) {}
>> diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
>> index f4b053b..3db0ba4 100644
>> --- a/arch/arm/mach-pxa/zeus.c
>> +++ b/arch/arm/mach-pxa/zeus.c
>> @@ -847,7 +847,7 @@ static void __init zeus_init(void)
>> ? ? ? if (zeus_setup_fb_gpios())
>> ? ? ? ? ? ? ? pr_err("Failed to setup fb gpios\n");
>> ? ? ? else
>> - ? ? ? ? ? ? set_pxa_fb_info(&zeus_fb_info);
>> + ? ? ? ? ? ? pxa_set_fb_info(NULL, &zeus_fb_info);
>>
>> ? ? ? pxa_set_mci_info(&zeus_mci_platform_data);
>> ? ? ? pxa_set_udc_info(&zeus_udc_info);
>> diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
>> index a4c784a..5821185 100644
>> --- a/arch/arm/mach-pxa/zylonite.c
>> +++ b/arch/arm/mach-pxa/zylonite.c
>> @@ -208,7 +208,7 @@ static void __init zylonite_init_lcd(void)
>> ? ? ? platform_device_register(&zylonite_backlight_device);
>>
>> ? ? ? if (lcd_id & 0x20) {
>> - ? ? ? ? ? ? set_pxa_fb_info(&zylonite_sharp_lcd_info);
>> + ? ? ? ? ? ? pxa_set_fb_info(NULL, &zylonite_sharp_lcd_info);
>> ? ? ? ? ? ? ? return;
>> ? ? ? }
>>
>> @@ -220,7 +220,7 @@ static void __init zylonite_init_lcd(void)
>> ? ? ? else
>> ? ? ? ? ? ? ? zylonite_toshiba_lcd_info.modes = &toshiba_ltm04c380k_mode;
>>
>> - ? ? set_pxa_fb_info(&zylonite_toshiba_lcd_info);
>> + ? ? pxa_set_fb_info(NULL, &zylonite_toshiba_lcd_info);
>> ?}
>> ?#else
>> ?static inline void zylonite_init_lcd(void) {}
>>
>> _______________________________________________
>> linux-arm-kernel mailing list
>> linux-arm-kernel at lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
>

^ permalink raw reply

* [PATCH V4] OMAP3: PM: Set/clear T2 bit for Smartreflex on TWL
From: Shweta Gulati @ 2011-02-15  7:58 UTC (permalink / raw)
  To: linux-arm-kernel

From: Thara Gopinath <thara@ti.com>

Voltage control on TWL can be done using VMODE/I2C1/I2C_SR.
Since almost all platforms use I2C_SR on omap3, omap3_twl_init by
default expects that OMAP's I2C_SR is plugged in to TWL's I2C
and calls omap3_twl_set_sr_bit. On platforms where I2C_SR is not connected,
the board files are expected to call omap3_twl_set_sr_bit(false) to
ensure that I2C_SR path is not set for voltage control and prevent
the default behavior of omap3_twl_init.

Signed-off-by: Nishanth Menon <nm@ti.com>
Signed-off-by: Thara Gopinath <thara@ti.com>
Signed-off-by: Shweta Gulati <shweta.gulati@ti.com>
Cc: linux-arm-kernel at lists.infradead.org
---
This patch is based on LO PM Branch and Smartreflex has been
tested on OMAP3430 SDP, OMAP3630 SDP and boot tested on
OMAP2430 SDP.

 arch/arm/mach-omap2/omap_twl.c |   60 ++++++++++++++++++++++++++++++++++++++++
 arch/arm/mach-omap2/pm.h       |    1 +
 2 files changed, 61 insertions(+), 0 deletions(-)

diff --git a/arch/arm/mach-omap2/omap_twl.c b/arch/arm/mach-omap2/omap_twl.c
index 00e1d2b..b341c36 100644
--- a/arch/arm/mach-omap2/omap_twl.c
+++ b/arch/arm/mach-omap2/omap_twl.c
@@ -59,8 +59,15 @@
 
 static bool is_offset_valid;
 static u8 smps_offset;
+/*
+ * Flag to ensure Smartreflex bit in TWL
+ * being cleared in board file is not overwritten.
+ */
+static bool __initdata twl_sr_enable_autoinit;
 
+#define TWL4030_DCDC_GLOBAL_CFG        0x06
 #define REG_SMPS_OFFSET         0xE0
+#define SMARTREFLEX_ENABLE     BIT(3)
 
 static unsigned long twl4030_vsel_to_uv(const u8 vsel)
 {
@@ -269,6 +276,18 @@ int __init omap3_twl_init(void)
 		omap3_core_volt_info.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
 	}
 
+	/*
+	 * The smartreflex bit on twl4030 specifies if the setting of voltage
+	 * is done over the I2C_SR path. Since this setting is independent of
+	 * the actual usage of smartreflex AVS module, we enable TWL SR bit
+	 * by default irrespective of whether smartreflex AVS module is enabled
+	 * on the OMAP side or not. This is because without this bit enabled,
+	 * the voltage scaling through vp forceupdate/bypass mechanism of
+	 * voltage scaling will not function on TWL over I2C_SR.
+	 */
+	if (!twl_sr_enable_autoinit)
+		omap3_twl_set_sr_bit(true);
+
 	voltdm = omap_voltage_domain_lookup("mpu");
 	omap_voltage_register_pmic(voltdm, &omap3_mpu_volt_info);
 
@@ -277,3 +296,44 @@ int __init omap3_twl_init(void)
 
 	return 0;
 }
+
+/**
+ * omap3_twl_set_sr_bit() - Set/Clear SR bit on TWL
+ * @enable: enable SR mode in twl or not
+ *
+ * If 'enable' is true, enables Smartreflex bit on TWL 4030 to make sure
+ * voltage scaling through OMAP SR works. Else, the smartreflex bit
+ * on twl4030 is cleared as there are platforms which use OMAP3 and T2 but
+ * use Synchronized Scaling Hardware Strategy (ENABLE_VMODE=1) and Direct
+ * Strategy Software Scaling Mode (ENABLE_VMODE=0), for setting the voltages,
+ * in those scenarios this bit is to be cleared (enable = false).
+ *
+ * Returns 0 on sucess, error is returned if I2C read/write fails.
+ */
+int __init omap3_twl_set_sr_bit(bool enable)
+{
+	u8 temp;
+	int ret;
+	if (twl_sr_enable_autoinit)
+		pr_warning("%s: unexpected multiple calls\n", __func__);
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &temp,
+					TWL4030_DCDC_GLOBAL_CFG);
+	if (ret)
+		goto err;
+
+	if (enable)
+		temp |= SMARTREFLEX_ENABLE;
+	else
+		temp &= ~SMARTREFLEX_ENABLE;
+
+	ret = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, temp,
+				TWL4030_DCDC_GLOBAL_CFG);
+	if (!ret) {
+		twl_sr_enable_autoinit = true;
+		return 0;
+	}
+err:
+	pr_err("%s: Error access to TWL4030 (%d)\n", __func__, ret);
+	return ret;
+}
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index 39580e6..797bfd1 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -127,6 +127,7 @@ static inline void omap_enable_smartreflex_on_init(void) {}
 #ifdef CONFIG_TWL4030_CORE
 extern int omap3_twl_init(void);
 extern int omap4_twl_init(void);
+extern int omap3_twl_set_sr_bit(bool enable);
 #else
 static inline int omap3_twl_init(void)
 {
-- 
1.7.0.4

^ permalink raw reply related

* [PATCH] OMAP: Fix Memory Leaks in Smartreflex driver
From: Shweta Gulati @ 2011-02-15  8:10 UTC (permalink / raw)
  To: linux-arm-kernel

This Patch frees all the dynamically allocated memory
which couldn't have been released in some error hitting cases.

Signed-off-by: Shweta Gulati <shweta.gulati@ti.com>
Cc: linux-arm-kernel at lists.infradead.org
---
 arch/arm/mach-omap2/smartreflex.c |   18 ++++++++++++------
 1 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-omap2/smartreflex.c b/arch/arm/mach-omap2/smartreflex.c
index a1f532e..5af8829 100644
--- a/arch/arm/mach-omap2/smartreflex.c
+++ b/arch/arm/mach-omap2/smartreflex.c
@@ -284,6 +284,7 @@ error:
 		dev_err(&sr_info->pdev->dev, "%s: ERROR in registering"
 			"interrupt handler. Smartreflex will"
 			"not function as desired\n", __func__);
+		kfree(name);
 		kfree(sr_info);
 		return ret;
 }
@@ -881,7 +882,7 @@ static int __init omap_sr_probe(struct platform_device *pdev)
 		ret = sr_late_init(sr_info);
 		if (ret) {
 			pr_warning("%s: Error in SR late init\n", __func__);
-			return ret;
+			goto err_release_region;
 		}
 	}
 
@@ -892,14 +893,17 @@ static int __init omap_sr_probe(struct platform_device *pdev)
 	 * not try to create rest of the debugfs entries.
 	 */
 	vdd_dbg_dir = omap_voltage_get_dbgdir(sr_info->voltdm);
-	if (!vdd_dbg_dir)
-		return -EINVAL;
+	if (!vdd_dbg_dir) {
+		ret = -EINVAL;
+		goto err_release_region;
+	}
 
 	dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir);
 	if (IS_ERR(dbg_dir)) {
 		dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
 			__func__);
-		return PTR_ERR(dbg_dir);
+		ret = PTR_ERR(dbg_dir);
+		goto err_release_region;
 	}
 
 	(void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR, dbg_dir,
@@ -915,7 +919,8 @@ static int __init omap_sr_probe(struct platform_device *pdev)
 	if (IS_ERR(nvalue_dir)) {
 		dev_err(&pdev->dev, "%s: Unable to create debugfs directory"
 			"for n-values\n", __func__);
-		return PTR_ERR(nvalue_dir);
+		ret = PTR_ERR(nvalue_dir);
+		goto err_release_region;
 	}
 
 	omap_voltage_get_volttable(sr_info->voltdm, &volt_data);
@@ -924,7 +929,8 @@ static int __init omap_sr_probe(struct platform_device *pdev)
 			" corresponding vdd vdd_%s. Cannot create debugfs"
 			"entries for n-values\n",
 			__func__, sr_info->voltdm->name);
-		return -ENODATA;
+		ret = -ENODATA;
+		goto err_release_region;
 	}
 
 	for (i = 0; i < sr_info->nvalue_count; i++) {
-- 
1.7.0.4

^ permalink raw reply related

* [RFC,PATCH 1/3] Add a common struct clk
From: Saravana Kannan @ 2011-02-15  8:33 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201102151526.54280.jeremy.kerr@canonical.com>

Hi Jeremy,

Sorry, if the formatting is weird. Using webmail client

On Mon, February 14, 2011 11:26 pm, Jeremy Kerr wrote:
>> > We
>> > may even want to disallow set_rate (and set_parent) when prepare_count
>> is
>> > non- zero.
>>
>> This is definitely not right.
>
> Why is that? Consider two devices using one clock; one does some
> initialisation based on the return value of clk_get_rate(), the other
> calls
> clk_set_rate() some time later. Now the first device is incorrectly
> initialised.

The case you describe is certainly something I consider as incorrect and
agree with you in that we should try to prevent it. But

(prepare_count != 0) != (two devices using one clock).

For one, prepare_count == 1 would be a normal case when a clock is enabled
and the MSM drivers certainly want to be able to set the rate when the
clock is enabled.

But (prepare_count > 1 || enable_count > 1) doesn't mean more than one
device/device driver using the clock either. A simple example would be a
driver wrapping all it's register accesses with a clk_enable/clk_disable
and not having to worry about if a clock is enabled during register access
when it has multiple execution paths (threads, interrupt handler, timers,
etc) that access registers. The driver would just do the enable/disable
around register accesses and let the clock code's ref counting dealing
with making sure a clock is never turned off when it's needed. In these
case both the prepare_count (less likely, but likely) and enable_count can
greater than 1.

Long story short, I support your desire to prevent one driver from
changing the rate from underneath another driver, but the condition you
chose to figure that out is not accurate.

> Regardless, this is definitely something to flag for a later discussion.
> I'm
> happy to return to that, but we should focus on one issue at a time here.

Sure, this discussion of set rate with count is non-zero can be reserved
for later. But I think the discussion of grabbing the lock during
set_parent should be discussed in the context of this patch.

Waiting to see how others feel about this.

Thanks,
Saravana

-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.

^ permalink raw reply

* [RFC,PATCH 1/3] Add a common struct clk
From: Russell King - ARM Linux @ 2011-02-15  8:37 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <201102151526.54280.jeremy.kerr@canonical.com>

On Tue, Feb 15, 2011 at 03:26:53PM +0800, Jeremy Kerr wrote:
> Hi Saravana,
> 
> > Sure, one could argue that in some archs for a certain set of clocks the
> > slow stuff in prepare/unprepare won't need to be done during set rate --
> > say, a simple clock that always runs off the same PLL but just has a
> > integer divider to change the rate.
> > 
> > In those cases, not grabbing the prepare_lock would make the code less
> > "locky".
> > 
> > > We
> > > may even want to disallow set_rate (and set_parent) when prepare_count is
> > > non- zero.
> > 
> > This is definitely not right.
> 
> Why is that? Consider two devices using one clock; one does some 
> initialisation based on the return value of clk_get_rate(), the other calls 
> clk_set_rate() some time later. Now the first device is incorrectly 
> initialised.

What about a clock sourced from a PLL which provides the dotclock for a
framebuffer device?  On every mode set, should the clk have to be disabled,
unprepared, rate set, re-prepared and re-enabled?

^ permalink raw reply

* [PATCH] ARM: PXA: Make PXA27x/PXA3xx overlay actually work
From: Vasily Khoruzhick @ 2011-02-15  8:41 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <AANLkTi=AfxN73pSNZ5RiTiTWfxR7PhcyJUyXzzeaYNWw@mail.gmail.com>

On Tuesday 15 February 2011 09:35:44 Eric Miao wrote:

> Or maybe simply:
> 
> 	if (lcd_readl(ofb->fbi, OVL1C1) & OVLxC1_OEN)
> 		return;

You mean if (!lcd_readl.....) return? Then OK.

> this makes this block of change much cleaner.
> 
> > -       lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] & ~OVLxC1_OEN);
> > +       if (lcd_readl(ofb->fbi, OVL1C1) & OVLxC1_OEN) {
> > +               lcd_writel(ofb->fbi, OVL1C1, ofb->control[0] &

<skip>

> >  static struct pxafb_layer_ops ofb_ops[] = {
> > @@ -720,12 +726,10 @@ static int overlayfb_open(struct fb_info *info, int
> > user) if (user == 0)
> >                return -ENODEV;
> > 
> > -       /* allow only one user at a time */
> > -       if (atomic_inc_and_test(&ofb->usage))
> > -               return -EBUSY;
> > +       if (ofb->usage++ == 0)
> > +               /* unblank the base framebuffer */
> > +               fb_blank(&ofb->fbi->fb, FB_BLANK_UNBLANK);
> 
> The change above allows multiple user at a time? Then I guess
> some other places need to be changed accordingly to avoid the
> racing conditions.

For multiple users driver needs some rework indeed.

> If this is a feature request, can we postpone it to subsequent
> patches?

I prefer to fix it later.

> >        lcd_writel(fbi, FDADR0, fbi->fdadr[0]);
> > -       lcd_writel(fbi, FDADR1, fbi->fdadr[1]);
> > +       if (fbi->lccr0 & LCCR0_SDS)
> > +               lcd_writel(fbi, FDADR1, fbi->fdadr[1]);
> 
> My original intention was to simplify the code a bit by ignoring
> LCCR0_SDS, as FDADR1 would not take effect if not enabled even
> if it's being read/written.

It leads to potential race condition when you try to reconfigure main plane 
and overlay1 simultaneously.

> > +#ifdef CONFIG_FB_PXA_OVERLAY
> > +       if (cpu_is_pxa27x())
> > +               fbi->lccr0 |= LCCR0_OUC;
> > +#endif
> > +
> 
> I seem to remember LCCR0_OUC is still valid on pxa3xx, did you
> do some test on pxa3xx as well?

Sorry, I have no any pxa3xx boards.
 
Regards
Vasily

^ permalink raw reply

* [PATCH v2] ARM: S5PV210: Add GONI board setup for CIF camera support
From: Sylwester Nawrocki @ 2011-02-15  8:54 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <008d01cbccd4$3897da00$a9c78e00$%kim@samsung.com>

Hi Kukjin,

On 02/15/2011 06:50 AM, Kukjin Kim wrote:
> Sylwester Nawrocki wrote:
>>
>> Hello,
>>
> Hi,
> 
>> the following patch series introduces changes in GONI board setup file
>> required for the CIF camera sensor driver.
>> The first patch adds the I2C0 bus driver, the second one adds the
> regulator
>> supply definitions and the third one just increases virtual size
>> of the framebuffer window 0 to enable double-buffering.
>> The added regulator supplies are also a subset of the supplies of the high
>> resolution camera which that reference board is equipped with.
>>
>> Changes since v1:
>>  - removed unnecessary "select CONFIG_S3C_DEV_I2C0"
>>
>>
>> The patch series contains:
>>
>> [PATCH 1/3] ARM: S5PV210: Enable I2C0 bus on GONI board
>> [PATCH 2/3] ARM: S5PV210: Add supplies for CIF camera on GONI board
>> [PATCH 3/3] ARM: S5PV210: Change framebuffer window 0 size on GONI
>>
>> Created against for-next branch at:
>> git://git.kernel.org/pub/scm/linux/kernel/git/kgene/linux-samsung.git
>>
> Hmm...looks you don't want to follow my suggestion on 2nd patch.

I've attempted to make a change as you suggested but it turned out
that all regulators I'm adding supplies for in the second patch are
also used by the other, high resolution camera. It's not about I don't
want to follow you suggestions. The argument is that I's like to add shortly
support for the other camera and then the patch would be just one line
per a power supply rather than 4. I really don't mind to adhere to your
preferred style. But in this case it would be just more work to revert
things back and forth.

I've boot tested your patch:
ARM: S5PV210: Use REGULATOR_SUPPLY macro for regulator consumers
on Aquila and GONI board altogether with my changeset.

> 
> I'm still wondering why array is needed for just one member in
> regulator_consumer_supply structure now even though other something will be
> added later.
> 
> Nevertheless will apply your 3 patches but if not required array will be
> removed later.

Thanks! I am going to post further patches for this board soon so there
should be no need to change anything. Please use you time for more important
things ;)

I've noticed one issue with the first patch, i.e. Kyungmin's email address
is broken. Should I resend the patch or could you please correct this on your side?

Thanks,
-- 
Sylwester Nawrocki
Samsung Poland R&D Center

^ permalink raw reply

* [PATCH 1/3] IPUv3: Add i.MX53 IPU support
From: jason.chen at freescale.com @ 2011-02-15  8:56 UTC (permalink / raw)
  To: linux-arm-kernel

From: Jason Chen <b02280@freescale.com>

Signed-off-by: Jason Chen <b02280@freescale.com>
---
 arch/arm/mach-mx5/board-mx51_babbage.c          |    2 +-
 arch/arm/mach-mx5/devices-imx51.h               |    3 -
 arch/arm/plat-mxc/devices/platform-imx_ipuv3.c  |   97 +++++++++++++++++++++--
 arch/arm/plat-mxc/include/mach/devices-common.h |    4 +-
 arch/arm/plat-mxc/include/mach/ipu-v3.h         |    1 +
 drivers/mfd/Kconfig                             |    6 +-
 drivers/mfd/imx-ipu-v3/ipu-common.c             |   66 +++------------
 drivers/mfd/imx-ipu-v3/ipu-prv.h                |   32 ++++----
 8 files changed, 126 insertions(+), 85 deletions(-)

diff --git a/arch/arm/mach-mx5/board-mx51_babbage.c b/arch/arm/mach-mx5/board-mx51_babbage.c
index ff951f8..176b9bc 100644
--- a/arch/arm/mach-mx5/board-mx51_babbage.c
+++ b/arch/arm/mach-mx5/board-mx51_babbage.c
@@ -457,7 +457,7 @@ static void __init mxc_board_init(void)
 	gpio_request(GPIO_DVI_I2C, "dvi i2c");
 	gpio_direction_output(GPIO_DVI_I2C, 0);
 
-	imx51_add_ipuv3(&ipu_data);
+	imx_add_ipuv3(&ipu_data);
 }
 
 static void __init mx51_babbage_timer_init(void)
diff --git a/arch/arm/mach-mx5/devices-imx51.h b/arch/arm/mach-mx5/devices-imx51.h
index 1bd73b3..065ac87 100644
--- a/arch/arm/mach-mx5/devices-imx51.h
+++ b/arch/arm/mach-mx5/devices-imx51.h
@@ -56,6 +56,3 @@ extern const struct imx_imx_keypad_data imx51_imx_keypad_data __initconst;
 #define imx51_add_imx_keypad(pdata)	\
 	imx_add_imx_keypad(&imx51_imx_keypad_data, pdata)
 
-extern const struct imx_ipuv3_data imx51_ipuv3_data __initconst;
-#define imx51_add_ipuv3(pdata)	\
-	imx_add_ipuv3(&imx51_ipuv3_data, pdata)
diff --git a/arch/arm/plat-mxc/devices/platform-imx_ipuv3.c b/arch/arm/plat-mxc/devices/platform-imx_ipuv3.c
index 2c6b913..c867f97 100644
--- a/arch/arm/plat-mxc/devices/platform-imx_ipuv3.c
+++ b/arch/arm/plat-mxc/devices/platform-imx_ipuv3.c
@@ -8,27 +8,93 @@
  */
 #include <mach/hardware.h>
 #include <mach/devices-common.h>
+#include <linux/clk.h>
 
-#define imx51_ipuv3_data_entry_single(soc)				\
+#define imx5_ipuv3_data_entry_single(soc)				\
 	{								\
 		.iobase = soc ## _IPU_CTRL_BASE_ADDR,			\
 		.irq_err = soc ## _INT_IPU_ERR,				\
 		.irq = soc ## _INT_IPU_SYN,				\
 	}
 
-#ifdef CONFIG_SOC_IMX51
-const struct imx_ipuv3_data imx51_ipuv3_data __initconst =
-	imx51_ipuv3_data_entry_single(MX51);
-#endif /* ifdef CONFIG_SOC_IMX35 */
+struct imx_ipuv3_data __initdata imx51_ipuv3_data =
+		imx5_ipuv3_data_entry_single(MX51);
+struct imx_ipuv3_data __initdata imx53_ipuv3_data =
+		imx5_ipuv3_data_entry_single(MX53);
 
-struct platform_device *__init imx_add_ipuv3(
+/*
+ * The MIPI HSC unit has been removed from the i.MX51 Reference Manual by
+ * the Freescale marketing division. However this did not remove the
+ * hardware from the chip which still needs to be configured...
+ */
+static int __init ipu_mipi_setup(void)
+{
+	struct clk *hsc_clk;
+	void __iomem *hsc_addr;
+	int ret = 0;
+
+	hsc_addr = ioremap(MX51_MIPI_HSC_BASE_ADDR, PAGE_SIZE);
+	if (!hsc_addr)
+		return -ENOMEM;
+
+	hsc_clk = clk_get_sys(NULL, "mipi_hsp");
+	if (IS_ERR(hsc_clk)) {
+		ret = PTR_ERR(hsc_clk);
+		goto unmap;
+	}
+	clk_enable(hsc_clk);
+
+	/* setup MIPI module to legacy mode */
+	__raw_writel(0xF00, hsc_addr);
+
+	/* CSI mode: reserved; DI control mode: legacy (from Freescale BSP) */
+	__raw_writel(__raw_readl(hsc_addr + 0x800) | 0x30ff,
+		hsc_addr + 0x800);
+
+	clk_disable(hsc_clk);
+	clk_put(hsc_clk);
+unmap:
+	iounmap(hsc_addr);
+
+	return ret;
+}
+
+int __init mx51_ipuv3_init(void)
+{
+	int ret = 0;
+	u32 val;
+
+	ret = ipu_mipi_setup();
+
+	/* hard reset the IPU */
+	val = readl(MX51_IO_ADDRESS(MX51_SRC_BASE_ADDR));
+	val |= 1 << 3;
+	writel(val, MX51_IO_ADDRESS(MX51_SRC_BASE_ADDR));
+
+	return ret;
+}
+
+int __init mx53_ipuv3_init(void)
+{
+	int ret = 0;
+	u32 val;
+
+	/* hard reset the IPU */
+	val = readl(MX53_IO_ADDRESS(MX53_SRC_BASE_ADDR));
+	val |= 1 << 3;
+	writel(val, MX53_IO_ADDRESS(MX53_SRC_BASE_ADDR));
+
+	return ret;
+}
+
+struct platform_device *__init _imx_add_ipuv3(
 		const struct imx_ipuv3_data *data,
 		const struct imx_ipuv3_platform_data *pdata)
 {
 	struct resource res[] = {
 		{
 			.start = data->iobase,
-			.end = data->iobase + SZ_512M - 1,
+			.end = data->iobase + data->iosize - 1,
 			.flags = IORESOURCE_MEM,
 		}, {
 			.start = data->irq_err,
@@ -45,3 +111,20 @@ struct platform_device *__init imx_add_ipuv3(
 			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
 }
 
+struct platform_device *__init imx_add_ipuv3(
+		struct imx_ipuv3_platform_data *pdata)
+{
+	if (cpu_is_mx51()) {
+		imx51_ipuv3_data.iosize = SZ_512M;
+		pdata->init = mx51_ipuv3_init;
+		return _imx_add_ipuv3(&imx51_ipuv3_data, pdata);
+	} else if (cpu_is_mx53()) {
+		/* fix offset */
+		imx53_ipuv3_data.iobase -= 0x18000000;
+		imx51_ipuv3_data.iosize = SZ_128M;
+		pdata->init = mx53_ipuv3_init;
+		return _imx_add_ipuv3(&imx53_ipuv3_data, pdata);
+	} else
+		return ERR_PTR(-EINVAL);
+}
+
diff --git a/arch/arm/plat-mxc/include/mach/devices-common.h b/arch/arm/plat-mxc/include/mach/devices-common.h
index 8f5197f..d9824a2 100644
--- a/arch/arm/plat-mxc/include/mach/devices-common.h
+++ b/arch/arm/plat-mxc/include/mach/devices-common.h
@@ -268,9 +268,9 @@ struct platform_device *__init imx_add_spi_imx(
 #include <mach/ipu-v3.h>
 struct imx_ipuv3_data {
 	resource_size_t iobase;
+	resource_size_t iosize;
 	resource_size_t irq_err;
 	resource_size_t irq;
 };
 struct platform_device *__init imx_add_ipuv3(
-		const struct imx_ipuv3_data *data,
-		const struct imx_ipuv3_platform_data *pdata);
+		struct imx_ipuv3_platform_data *pdata);
diff --git a/arch/arm/plat-mxc/include/mach/ipu-v3.h b/arch/arm/plat-mxc/include/mach/ipu-v3.h
index f8900b9..1a4a271 100644
--- a/arch/arm/plat-mxc/include/mach/ipu-v3.h
+++ b/arch/arm/plat-mxc/include/mach/ipu-v3.h
@@ -42,6 +42,7 @@ struct ipuv3_fb_platform_data {
 
 struct imx_ipuv3_platform_data {
 	int rev;
+	int (*init) (void);
 	struct ipuv3_fb_platform_data	*fb_head0_platform_data;
 	struct ipuv3_fb_platform_data	*fb_head1_platform_data;
 };
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index d1aa701..0d218cd 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -625,11 +625,11 @@ config MFD_WL1273_CORE
 	  audio codec.
 
 config MFD_IMX_IPU_V3
-	tristate "Support the Image Processing Unit (IPU) found on the i.MX51"
-	depends on ARCH_MX51
+	tristate "Support the Image Processing Unit (IPUv3) found on the i.MX5X"
+	depends on ARCH_MX51 || ARCH_MX53
 	select MFD_CORE
 	help
-	  Say yes here to support the IPU on i.MX51.
+	  Say yes here to support the IPUv3 on i.MX5X.
 
 endif # MFD_SUPPORT
 
diff --git a/drivers/mfd/imx-ipu-v3/ipu-common.c b/drivers/mfd/imx-ipu-v3/ipu-common.c
index d96245f..3a026c0 100644
--- a/drivers/mfd/imx-ipu-v3/ipu-common.c
+++ b/drivers/mfd/imx-ipu-v3/ipu-common.c
@@ -345,15 +345,9 @@ ipu_color_space_t format_to_colorspace(u32 fmt)
 	}
 }
 
-static int ipu_reset(void)
+static int ipu_mem_reset(void)
 {
 	int timeout = 10000;
-	u32 val;
-
-	/* hard reset the IPU */
-	val = readl(MX51_IO_ADDRESS(MX51_SRC_BASE_ADDR));
-	val |= 1 << 3;
-	writel(val, MX51_IO_ADDRESS(MX51_SRC_BASE_ADDR));
 
 	ipu_cm_write(0x807FFFFF, IPU_MEM_RST);
 
@@ -366,43 +360,6 @@ static int ipu_reset(void)
 	return 0;
 }
 
-/*
- * The MIPI HSC unit has been removed from the i.MX51 Reference Manual by
- * the Freescale marketing division. However this did not remove the
- * hardware from the chip which still needs to be configured...
- */
-static int __devinit ipu_mipi_setup(void)
-{
-	struct clk *hsc_clk;
-	void __iomem *hsc_addr;
-	int ret = 0;
-
-	hsc_addr = ioremap(MX51_MIPI_HSC_BASE_ADDR, PAGE_SIZE);
-	if (!hsc_addr)
-		return -ENOMEM;
-
-	hsc_clk = clk_get_sys(NULL, "mipi_hsp");
-	if (IS_ERR(hsc_clk)) {
-		ret = PTR_ERR(hsc_clk);
-		goto unmap;
-	}
-	clk_enable(hsc_clk);
-
-	/* setup MIPI module to legacy mode */
-	__raw_writel(0xF00, hsc_addr);
-
-	/* CSI mode: reserved; DI control mode: legacy (from Freescale BSP) */
-	__raw_writel(__raw_readl(hsc_addr + 0x800) | 0x30ff,
-		hsc_addr + 0x800);
-
-	clk_disable(hsc_clk);
-	clk_put(hsc_clk);
-unmap:
-	iounmap(hsc_addr);
-
-	return ret;
-}
-
 static int ipu_submodules_init(struct platform_device *pdev,
 		unsigned long ipu_base, struct clk *ipu_clk)
 {
@@ -526,9 +483,9 @@ static int ipu_add_client_devices(struct platform_device *pdev)
 	fbdata = plat_data->fb_head0_platform_data;
 	if (fbdata) {
 		fbdata->ipu_channel_bg =
-			MX51_IPU_CHANNEL_MEM_BG_SYNC;
+			MX5_IPU_CHANNEL_MEM_BG_SYNC;
 		fbdata->ipu_channel_fg =
-			MX51_IPU_CHANNEL_MEM_FG_SYNC;
+			MX5_IPU_CHANNEL_MEM_FG_SYNC;
 		fbdata->dc_channel = 5;
 		fbdata->dp_channel = IPU_DP_FLOW_SYNC;
 
@@ -539,7 +496,7 @@ static int ipu_add_client_devices(struct platform_device *pdev)
 	fbdata = plat_data->fb_head1_platform_data;
 	if (fbdata) {
 		fbdata->ipu_channel_bg =
-			MX51_IPU_CHANNEL_MEM_DC_SYNC;
+			MX5_IPU_CHANNEL_MEM_DC_SYNC;
 		fbdata->ipu_channel_fg = -1;
 		fbdata->dc_channel = 1;
 		fbdata->dp_channel = -1;
@@ -554,6 +511,7 @@ static int ipu_add_client_devices(struct platform_device *pdev)
 static int __devinit ipu_probe(struct platform_device *pdev)
 {
 	struct resource *res;
+	struct imx_ipuv3_platform_data *plat_data = pdev->dev.platform_data;
 	unsigned long ipu_base;
 	int ret, irq1, irq2;
 
@@ -586,10 +544,6 @@ static int __devinit ipu_probe(struct platform_device *pdev)
 		goto failed_ioremap2;
 	}
 
-	ret = ipu_mipi_setup();
-	if (ret)
-		goto failed_mipi_setup;
-
 	ipu_clk = clk_get(&pdev->dev, "ipu");
 	if (IS_ERR(ipu_clk)) {
 		ret = PTR_ERR(ipu_clk);
@@ -613,7 +567,13 @@ static int __devinit ipu_probe(struct platform_device *pdev)
 		goto failed_request_irq2;
 	}
 
-	ipu_reset();
+	if (plat_data->init) {
+		ret = plat_data->init();
+		if (ret)
+			goto failed_plat_init;
+	}
+
+	ipu_mem_reset();
 
 	ret = ipu_submodules_init(pdev, ipu_base, ipu_clk);
 	if (ret)
@@ -634,6 +594,7 @@ static int __devinit ipu_probe(struct platform_device *pdev)
 
 failed_add_clients:
 	ipu_submodules_exit(pdev, ipu_base);
+failed_plat_init:
 failed_submodules_init:
 	free_irq(irq2, &pdev->dev);
 failed_request_irq2:
@@ -642,7 +603,6 @@ failed_request_irq2:
 failed_request_irq1:
 	clk_put(ipu_clk);
 failed_clk_get:
-failed_mipi_setup:
 	iounmap(ipu_idmac_reg);
 failed_ioremap2:
 	iounmap(ipu_cm_reg);
diff --git a/drivers/mfd/imx-ipu-v3/ipu-prv.h b/drivers/mfd/imx-ipu-v3/ipu-prv.h
index 339b554..8469337 100644
--- a/drivers/mfd/imx-ipu-v3/ipu-prv.h
+++ b/drivers/mfd/imx-ipu-v3/ipu-prv.h
@@ -21,22 +21,22 @@
 #include <linux/platform_device.h>
 #include <mach/hardware.h>
 
-#define MX51_IPU_CHANNEL_CSI0			 0
-#define MX51_IPU_CHANNEL_CSI1			 1
-#define MX51_IPU_CHANNEL_CSI2			 2
-#define MX51_IPU_CHANNEL_CSI3			 3
-#define MX51_IPU_CHANNEL_MEM_BG_SYNC		23
-#define MX51_IPU_CHANNEL_MEM_FG_SYNC		27
-#define MX51_IPU_CHANNEL_MEM_DC_SYNC		28
-#define MX51_IPU_CHANNEL_MEM_FG_SYNC_ALPHA	31
-#define MX51_IPU_CHANNEL_MEM_DC_ASYNC		41
-#define MX51_IPU_CHANNEL_ROT_ENC_MEM		45
-#define MX51_IPU_CHANNEL_ROT_VF_MEM		46
-#define MX51_IPU_CHANNEL_ROT_PP_MEM		47
-#define MX51_IPU_CHANNEL_ROT_ENC_MEM_OUT	48
-#define MX51_IPU_CHANNEL_ROT_VF_MEM_OUT		49
-#define MX51_IPU_CHANNEL_ROT_PP_MEM_OUT		50
-#define MX51_IPU_CHANNEL_MEM_BG_SYNC_ALPHA	51
+#define MX5_IPU_CHANNEL_CSI0			 0
+#define MX5_IPU_CHANNEL_CSI1			 1
+#define MX5_IPU_CHANNEL_CSI2			 2
+#define MX5_IPU_CHANNEL_CSI3			 3
+#define MX5_IPU_CHANNEL_MEM_BG_SYNC		23
+#define MX5_IPU_CHANNEL_MEM_FG_SYNC		27
+#define MX5_IPU_CHANNEL_MEM_DC_SYNC		28
+#define MX5_IPU_CHANNEL_MEM_FG_SYNC_ALPHA	31
+#define MX5_IPU_CHANNEL_MEM_DC_ASYNC		41
+#define MX5_IPU_CHANNEL_ROT_ENC_MEM		45
+#define MX5_IPU_CHANNEL_ROT_VF_MEM		46
+#define MX5_IPU_CHANNEL_ROT_PP_MEM		47
+#define MX5_IPU_CHANNEL_ROT_ENC_MEM_OUT	48
+#define MX5_IPU_CHANNEL_ROT_VF_MEM_OUT		49
+#define MX5_IPU_CHANNEL_ROT_PP_MEM_OUT		50
+#define MX5_IPU_CHANNEL_MEM_BG_SYNC_ALPHA	51
 
 #define IPU_DISP0_BASE		0x00000000
 #define IPU_MCU_T_DEFAULT	8
-- 
1.7.1

^ permalink raw reply related

* [PATCH 2/3] ARM i.MX53 LoCo: Add ipu device & framebuffer support
From: jason.chen at freescale.com @ 2011-02-15  8:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1297760175-19211-1-git-send-email-jason.chen@freescale.com>

From: Jason Chen <b02280@freescale.com>

Signed-off-by: Jason Chen <b02280@freescale.com>
---
 arch/arm/mach-mx5/Kconfig           |    1 +
 arch/arm/mach-mx5/board-mx53_loco.c |   52 +++++++++++++++++++++++++++++++++++
 arch/arm/mach-mx5/clock-mx51-mx53.c |    5 +++-
 3 files changed, 57 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-mx5/Kconfig b/arch/arm/mach-mx5/Kconfig
index 8afdb75..14840c3 100644
--- a/arch/arm/mach-mx5/Kconfig
+++ b/arch/arm/mach-mx5/Kconfig
@@ -147,6 +147,7 @@ config MACH_MX53_LOCO
 	bool "Support MX53 LOCO platforms"
 	select SOC_IMX53
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_IMX_IPUV3
 	help
 	  Include support for MX53 LOCO platform. This includes specific
 	  configurations for the board and its peripherals.
diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c
index 0fea252..8da1cd4 100644
--- a/arch/arm/mach-mx5/board-mx53_loco.c
+++ b/arch/arm/mach-mx5/board-mx53_loco.c
@@ -23,11 +23,13 @@
 #include <linux/fec.h>
 #include <linux/delay.h>
 #include <linux/gpio.h>
+#include <linux/mfd/imx-ipu-v3.h>
 
 #include <mach/common.h>
 #include <mach/hardware.h>
 #include <mach/imx-uart.h>
 #include <mach/iomux-mx53.h>
+#include <mach/ipu-v3.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -35,12 +37,43 @@
 
 #include "crm_regs.h"
 #include "devices-imx53.h"
+#include "devices.h"
 
 #define LOCO_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
 
 static iomux_v3_cfg_t mx53_loco_pads[] = {
 	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
 	MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
+
+	/* DISPLAY */
+	MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK,
+	MX53_PAD_DI0_PIN15__IPU_DI0_PIN15,
+	MX53_PAD_DI0_PIN2__IPU_DI0_PIN2,
+	MX53_PAD_DI0_PIN3__IPU_DI0_PIN3,
+	MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0,
+	MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1,
+	MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2,
+	MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3,
+	MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4,
+	MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5,
+	MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6,
+	MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7,
+	MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8,
+	MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9,
+	MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10,
+	MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11,
+	MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12,
+	MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13,
+	MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14,
+	MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15,
+	MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16,
+	MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17,
+	MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18,
+	MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19,
+	MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20,
+	MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21,
+	MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22,
+	MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23,
 };
 
 static inline void mx53_loco_fec_reset(void)
@@ -62,6 +95,23 @@ static struct fec_platform_data mx53_loco_fec_data = {
 	.phy = PHY_INTERFACE_MODE_RMII,
 };
 
+static struct ipuv3_fb_platform_data loco_fb0_data = {
+	.interface_pix_fmt = IPU_PIX_FMT_RGB565,
+	.flags = IMX_IPU_FB_USE_MODEDB | IMX_IPU_FB_USE_OVERLAY,
+	.display = 0,
+};
+
+static struct ipuv3_fb_platform_data loco_fb1_data = {
+	.interface_pix_fmt = IPU_PIX_FMT_RGB24,
+	.flags = IMX_IPU_FB_USE_MODEDB,
+	.display = 1,
+};
+
+static struct imx_ipuv3_platform_data ipu_data = {
+	.fb_head0_platform_data = &loco_fb0_data,
+	.fb_head1_platform_data = &loco_fb1_data,
+};
+
 static void __init mx53_loco_board_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
@@ -69,6 +119,8 @@ static void __init mx53_loco_board_init(void)
 	imx53_add_imx_uart(0, NULL);
 	mx53_loco_fec_reset();
 	imx53_add_fec(&mx53_loco_fec_data);
+
+	imx_add_ipuv3(&ipu_data);
 }
 
 static void __init mx53_loco_timer_init(void)
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
index c66be0e..043572f 100644
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -1317,7 +1317,7 @@ static struct clk_lookup mx51_lookups[] = {
 	_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
 	_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
 	_REGISTER_CLOCK(NULL, "mipi_hsp", mipi_hsp_clk)
-	_REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk)
+	_REGISTER_CLOCK("imx-ipuv3", "ipu", ipu_clk)
 	_REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
 	_REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
 };
@@ -1336,6 +1336,9 @@ static struct clk_lookup mx53_lookups[] = {
 	_REGISTER_CLOCK("imx53-ecspi.0", NULL, ecspi1_clk)
 	_REGISTER_CLOCK("imx53-ecspi.1", NULL, ecspi2_clk)
 	_REGISTER_CLOCK("imx53-cspi.0", NULL, cspi_clk)
+	_REGISTER_CLOCK("imx-ipuv3", "ipu", ipu_clk)
+	_REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
+	_REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
 };
 
 static void clk_tree_init(void)
-- 
1.7.1

^ permalink raw reply related

* [PATCH 3/3] ARM i.MX53 LoCo: Add PWM backlight device support
From: jason.chen at freescale.com @ 2011-02-15  8:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1297760175-19211-1-git-send-email-jason.chen@freescale.com>

From: Jason Chen <b02280@freescale.com>

Signed-off-by: Jason Chen <b02280@freescale.com>
---
 arch/arm/mach-mx5/board-mx53_loco.c          |   29 ++++++++++++++++++++++++++
 arch/arm/mach-mx5/clock-mx51-mx53.c          |    2 +
 arch/arm/mach-mx5/devices-imx53.h            |    2 +
 arch/arm/mach-mx5/devices.c                  |   10 +++++++++
 arch/arm/mach-mx5/devices.h                  |    2 +
 arch/arm/plat-mxc/devices/Kconfig            |    1 +
 arch/arm/plat-mxc/devices/platform-mxc_pwm.c |    9 ++++++++
 arch/arm/plat-mxc/pwm.c                      |    3 +-
 8 files changed, 57 insertions(+), 1 deletions(-)

diff --git a/arch/arm/mach-mx5/board-mx53_loco.c b/arch/arm/mach-mx5/board-mx53_loco.c
index 8da1cd4..1ded0ef 100644
--- a/arch/arm/mach-mx5/board-mx53_loco.c
+++ b/arch/arm/mach-mx5/board-mx53_loco.c
@@ -24,6 +24,7 @@
 #include <linux/delay.h>
 #include <linux/gpio.h>
 #include <linux/mfd/imx-ipu-v3.h>
+#include <linux/pwm_backlight.h>
 
 #include <mach/common.h>
 #include <mach/hardware.h>
@@ -39,6 +40,7 @@
 #include "devices-imx53.h"
 #include "devices.h"
 
+#define LOCO_DISP0_PWR			IMX_GPIO_NR(3, 24)
 #define LOCO_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
 
 static iomux_v3_cfg_t mx53_loco_pads[] = {
@@ -74,6 +76,12 @@ static iomux_v3_cfg_t mx53_loco_pads[] = {
 	MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21,
 	MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22,
 	MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23,
+
+	/* DISP0_POWER_EN */
+	MX53_PAD_EIM_D24__GPIO3_24,
+
+	/* PWM */
+	MX53_PAD_GPIO_1__PWM2_PWMO,
 };
 
 static inline void mx53_loco_fec_reset(void)
@@ -95,6 +103,13 @@ static struct fec_platform_data mx53_loco_fec_data = {
 	.phy = PHY_INTERFACE_MODE_RMII,
 };
 
+static struct platform_pwm_backlight_data loco_pwm_backlight_data = {
+        .pwm_id = 1,
+        .max_brightness = 255,
+        .dft_brightness = 128,
+        .pwm_period_ns = 50000,
+};
+
 static struct ipuv3_fb_platform_data loco_fb0_data = {
 	.interface_pix_fmt = IPU_PIX_FMT_RGB565,
 	.flags = IMX_IPU_FB_USE_MODEDB | IMX_IPU_FB_USE_OVERLAY,
@@ -114,6 +129,8 @@ static struct imx_ipuv3_platform_data ipu_data = {
 
 static void __init mx53_loco_board_init(void)
 {
+	int ret;
+
 	mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
 					ARRAY_SIZE(mx53_loco_pads));
 	imx53_add_imx_uart(0, NULL);
@@ -121,6 +138,18 @@ static void __init mx53_loco_board_init(void)
 	imx53_add_fec(&mx53_loco_fec_data);
 
 	imx_add_ipuv3(&ipu_data);
+
+	imx_add_mxc_pwm(&imx53_mxc_pwm_data[1]);
+	mxc_register_device(&mxc_pwm1_backlight_device,
+			&loco_pwm_backlight_data);
+
+	/* enable disp0 power */
+	ret = gpio_request(LOCO_DISP0_PWR, "disp0-power-en");
+	if (ret) {
+		printk(KERN_ERR"failed to get GPIO_LOCO_DISP0_PWR: %d\n", ret);
+		return;
+	}
+	gpio_direction_output(LOCO_DISP0_PWR, 1);
 }
 
 static void __init mx53_loco_timer_init(void)
diff --git a/arch/arm/mach-mx5/clock-mx51-mx53.c b/arch/arm/mach-mx5/clock-mx51-mx53.c
index 043572f..64419e0 100644
--- a/arch/arm/mach-mx5/clock-mx51-mx53.c
+++ b/arch/arm/mach-mx5/clock-mx51-mx53.c
@@ -1339,6 +1339,8 @@ static struct clk_lookup mx53_lookups[] = {
 	_REGISTER_CLOCK("imx-ipuv3", "ipu", ipu_clk)
 	_REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
 	_REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
+	_REGISTER_CLOCK("mxc_pwm.0", "pwm", pwm1_clk)
+	_REGISTER_CLOCK("mxc_pwm.1", "pwm", pwm2_clk)
 };
 
 static void clk_tree_init(void)
diff --git a/arch/arm/mach-mx5/devices-imx53.h b/arch/arm/mach-mx5/devices-imx53.h
index 8639735..a60ef2e 100644
--- a/arch/arm/mach-mx5/devices-imx53.h
+++ b/arch/arm/mach-mx5/devices-imx53.h
@@ -29,3 +29,5 @@ imx53_sdhci_esdhc_imx_data[] __initconst;
 extern const struct imx_spi_imx_data imx53_ecspi_data[] __initconst;
 #define imx53_add_ecspi(id, pdata)	\
 	imx_add_spi_imx(&imx53_ecspi_data[id], pdata)
+
+extern const struct imx_mxc_pwm_data imx53_mxc_pwm_data[] __initconst;
diff --git a/arch/arm/mach-mx5/devices.c b/arch/arm/mach-mx5/devices.c
index 153ada5..f523209 100644
--- a/arch/arm/mach-mx5/devices.c
+++ b/arch/arm/mach-mx5/devices.c
@@ -120,6 +120,16 @@ struct platform_device mxc_usbh2_device = {
 	},
 };
 
+struct platform_device mxc_pwm1_backlight_device = {
+        .name = "pwm-backlight",
+        .id = 0,
+};
+
+struct platform_device mxc_pwm2_backlight_device = {
+        .name = "pwm-backlight",
+        .id = 1,
+};
+
 static struct mxc_gpio_port mxc_gpio_ports[] = {
 	{
 		.chip.label = "gpio-0",
diff --git a/arch/arm/mach-mx5/devices.h b/arch/arm/mach-mx5/devices.h
index 55a5129..a74cd97 100644
--- a/arch/arm/mach-mx5/devices.h
+++ b/arch/arm/mach-mx5/devices.h
@@ -3,3 +3,5 @@ extern struct platform_device mxc_usbh1_device;
 extern struct platform_device mxc_usbh2_device;
 extern struct platform_device mxc_usbdr_udc_device;
 extern struct platform_device mxc_hsi2c_device;
+extern struct platform_device mxc_pwm1_backlight_device;
+extern struct platform_device mxc_pwm2_backlight_device;
diff --git a/arch/arm/plat-mxc/devices/Kconfig b/arch/arm/plat-mxc/devices/Kconfig
index f99317e..83e9f1c 100644
--- a/arch/arm/plat-mxc/devices/Kconfig
+++ b/arch/arm/plat-mxc/devices/Kconfig
@@ -58,6 +58,7 @@ config IMX_HAVE_PLATFORM_MXC_NAND
 
 config IMX_HAVE_PLATFORM_MXC_PWM
 	bool
+	default y if HAVE_PWM
 
 config IMX_HAVE_PLATFORM_MXC_RNGA
 	bool
diff --git a/arch/arm/plat-mxc/devices/platform-mxc_pwm.c b/arch/arm/plat-mxc/devices/platform-mxc_pwm.c
index b0c4ae2..18cfd07 100644
--- a/arch/arm/plat-mxc/devices/platform-mxc_pwm.c
+++ b/arch/arm/plat-mxc/devices/platform-mxc_pwm.c
@@ -49,6 +49,15 @@ const struct imx_mxc_pwm_data imx51_mxc_pwm_data[] __initconst = {
 };
 #endif /* ifdef CONFIG_SOC_IMX51 */
 
+#ifdef CONFIG_SOC_IMX53
+const struct imx_mxc_pwm_data imx53_mxc_pwm_data[] __initconst = {
+#define imx53_mxc_pwm_data_entry(_id, _hwid)				\
+	imx_mxc_pwm_data_entry(MX53, _id, _hwid, SZ_16K)
+	imx53_mxc_pwm_data_entry(0, 1),
+	imx53_mxc_pwm_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
 struct platform_device *__init imx_add_mxc_pwm(
 		const struct imx_mxc_pwm_data *data)
 {
diff --git a/arch/arm/plat-mxc/pwm.c b/arch/arm/plat-mxc/pwm.c
index 7a61ef8..61dd8fb 100644
--- a/arch/arm/plat-mxc/pwm.c
+++ b/arch/arm/plat-mxc/pwm.c
@@ -57,7 +57,8 @@ int pwm_config(struct pwm_device *pwm, int duty_ns, int period_ns)
 	if (pwm == NULL || period_ns == 0 || duty_ns > period_ns)
 		return -EINVAL;
 
-	if (cpu_is_mx27() || cpu_is_mx3() || cpu_is_mx25() || cpu_is_mx51()) {
+	if (cpu_is_mx27() || cpu_is_mx3() || cpu_is_mx25() || cpu_is_mx51() ||
+		cpu_is_mx53()) {
 		unsigned long long c;
 		unsigned long period_cycles, duty_cycles, prescale;
 		u32 cr;
-- 
1.7.1

^ permalink raw reply related

* [PATCH for 2.6.38] ARM: S5PC110: update max8998_platform_data
From: Marek Szyprowski @ 2011-02-15  9:01 UTC (permalink / raw)
  To: linux-arm-kernel

Max8998 PMIC driver's platform data has been changed once again in
commit 735a3d9efdc. This patch fixes build break caused by that commit.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-s5pv210/mach-aquila.c |    9 ++++++---
 arch/arm/mach-s5pv210/mach-goni.c   |    9 ++++++---
 2 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index 461aa035..1236e19 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -381,9 +381,12 @@ static struct max8998_platform_data aquila_max8998_pdata = {
 	.buck1_set1	= S5PV210_GPH0(3),
 	.buck1_set2	= S5PV210_GPH0(4),
 	.buck2_set3	= S5PV210_GPH0(5),
-	.buck1_max_voltage1 = 1200000,
-	.buck1_max_voltage2 = 1200000,
-	.buck2_max_voltage = 1200000,
+	.buck1_voltage1	= 1200000,
+	.buck1_voltage2	= 1200000,
+	.buck1_voltage3	= 1200000,
+	.buck1_voltage4	= 1200000,
+	.buck2_voltage1	= 1200000,
+	.buck2_voltage2	= 1200000,
 };
 #endif
 
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index e22d511..2beeb66 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -521,9 +521,12 @@ static struct max8998_platform_data goni_max8998_pdata = {
 	.buck1_set1	= S5PV210_GPH0(3),
 	.buck1_set2	= S5PV210_GPH0(4),
 	.buck2_set3	= S5PV210_GPH0(5),
-	.buck1_max_voltage1 = 1200000,
-	.buck1_max_voltage2 = 1200000,
-	.buck2_max_voltage = 1200000,
+	.buck1_voltage1	= 1200000,
+	.buck1_voltage2	= 1200000,
+	.buck1_voltage3	= 1200000,
+	.buck1_voltage4	= 1200000,
+	.buck2_voltage1	= 1200000,
+	.buck2_voltage2	= 1200000,
 };
 #endif
 
-- 
1.7.1.569.g6f426

^ permalink raw reply related

* [PATCH for 2.6.38] ARM: S5PC110: fix regulator names
From: Marek Szyprowski @ 2011-02-15  9:01 UTC (permalink / raw)
  To: linux-arm-kernel

Since commit 1130e5b3ff4 regulators are exported to debugfs. The names
of the regulators that contains slash ('/') causes an ops during kernel
boot. This patch fixes this issue.

Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
---
 arch/arm/mach-s5pv210/mach-aquila.c |    6 +++---
 arch/arm/mach-s5pv210/mach-goni.c   |    6 +++---
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index 1236e19..557add4 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -149,7 +149,7 @@ static struct regulator_init_data aquila_ldo2_data = {
 
 static struct regulator_init_data aquila_ldo3_data = {
 	.constraints	= {
-		.name		= "VUSB/MIPI_1.1V",
+		.name		= "VUSB+MIPI_1.1V",
 		.min_uV		= 1100000,
 		.max_uV		= 1100000,
 		.apply_uV	= 1,
@@ -197,7 +197,7 @@ static struct regulator_init_data aquila_ldo7_data = {
 
 static struct regulator_init_data aquila_ldo8_data = {
 	.constraints	= {
-		.name		= "VUSB/VADC_3.3V",
+		.name		= "VUSB+VADC_3.3V",
 		.min_uV		= 3300000,
 		.max_uV		= 3300000,
 		.apply_uV	= 1,
@@ -207,7 +207,7 @@ static struct regulator_init_data aquila_ldo8_data = {
 
 static struct regulator_init_data aquila_ldo9_data = {
 	.constraints	= {
-		.name		= "VCC/VCAM_2.8V",
+		.name		= "VCC+VCAM_2.8V",
 		.min_uV		= 2800000,
 		.max_uV		= 2800000,
 		.apply_uV	= 1,
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index 2beeb66..056f5c7 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -288,7 +288,7 @@ static struct regulator_init_data goni_ldo2_data = {
 
 static struct regulator_init_data goni_ldo3_data = {
 	.constraints	= {
-		.name		= "VUSB/MIPI_1.1V",
+		.name		= "VUSB+MIPI_1.1V",
 		.min_uV		= 1100000,
 		.max_uV		= 1100000,
 		.apply_uV	= 1,
@@ -337,7 +337,7 @@ static struct regulator_init_data goni_ldo7_data = {
 
 static struct regulator_init_data goni_ldo8_data = {
 	.constraints	= {
-		.name		= "VUSB/VADC_3.3V",
+		.name		= "VUSB+VADC_3.3V",
 		.min_uV		= 3300000,
 		.max_uV		= 3300000,
 		.apply_uV	= 1,
@@ -347,7 +347,7 @@ static struct regulator_init_data goni_ldo8_data = {
 
 static struct regulator_init_data goni_ldo9_data = {
 	.constraints	= {
-		.name		= "VCC/VCAM_2.8V",
+		.name		= "VCC+VCAM_2.8V",
 		.min_uV		= 2800000,
 		.max_uV		= 2800000,
 		.apply_uV	= 1,
-- 
1.7.1.569.g6f426

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox