* [PATCH v3 1/2] drivers/base: permit base components to omit the bind/unbind ops
From: Russell King - ARM Linux @ 2014-02-10 13:12 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210125307.GG20143@ulmo.nvidia.com>
On Mon, Feb 10, 2014 at 01:53:08PM +0100, Thierry Reding wrote:
> On Fri, Feb 07, 2014 at 04:55:00PM +0100, Jean-Francois Moine wrote:
> > Some simple components don't need to do any specific action on
> > bind to / unbind from a master component.
> >
> > This patch permits such components to omit the bind/unbind
> > operations.
> >
> > Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
> > ---
> > drivers/base/component.c | 9 +++++++--
> > 1 file changed, 7 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/base/component.c b/drivers/base/component.c
> > index c53efe6..0a39d7a 100644
> > --- a/drivers/base/component.c
> > +++ b/drivers/base/component.c
> > @@ -225,7 +225,8 @@ static void component_unbind(struct component *component,
> > {
> > WARN_ON(!component->bound);
> >
> > - component->ops->unbind(component->dev, master->dev, data);
> > + if (component->ops)
> > + component->ops->unbind(component->dev, master->dev, data);
>
> This doesn't actually do what the commit message says. This makes
> component->ops optional, not component->ops->unbind().
>
> A more correct check would be:
>
> if (component->ops && component->ops->unbind)
>
> > component->bound = false;
> >
> > /* Release all resources claimed in the binding of this component */
> > @@ -274,7 +275,11 @@ static int component_bind(struct component *component, struct master *master,
> > dev_dbg(master->dev, "binding %s (ops %ps)\n",
> > dev_name(component->dev), component->ops);
> >
> > - ret = component->ops->bind(component->dev, master->dev, data);
> > + if (component->ops)
> > + ret = component->ops->bind(component->dev, master->dev, data);
>
> Same here.
I've NAK'd these patches already - I believe they're based on a
mis-understanding of how this should be used. I believe Jean-Francois
has only looked at the core, rather than looking at the imx-drm example
it was posted with in an attempt to understand it.
Omitting the component bind operations is absurd because it makes the
component code completely pointless, since there is then no way to
control the sequencing of driver initialisation - something which is
one of the primary reasons for this code existing in the first place.
--
FTTC broadband for 0.8mile line: 5.8Mbps down 500kbps up. Estimation
in database were 13.1 to 19Mbit for a good line, about 7.5+ for a bad.
Estimate before purchase was "up to 13.2Mbit".
^ permalink raw reply
* [PATCH 4/4] arm64: topology: Provide relative power numbers for cores
From: Mark Brown @ 2014-02-10 13:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1392037324-5069-1-git-send-email-broonie@kernel.org>
From: Mark Brown <broonie@linaro.org>
Provide performance numbers to the scheduler to help it fill the cores in
the system on big.LITTLE systems. With the current scheduler this may
perform poorly for applications that try to do OpenMP style work over all
cores but should help for more common workloads. The current 32 bit ARM
implementation provides a similar estimate so this helps ensure that
work to improve big.LITTLE systems on ARMv7 systems performs similarly
on ARMv8 systems.
The power numbers are the same as for ARMv7 since it seems that the
expected differential between the big and little cores is very similar on
both ARMv7 and ARMv8. In both ARMv7 and ARMv8 cases the numbers were
based on the published DMIPS numbers.
These numbers are just an initial and basic approximation for use with
the current scheduler, it is likely that both experience with silicon
and ongoing work on improving the scheduler will lead to further tuning
or will tune automatically at runtime and so make the specific choice of
numbers here less critical.
Signed-off-by: Mark Brown <broonie@linaro.org>
---
arch/arm64/kernel/topology.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index 951b55e24f13..0728264e14ee 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -177,6 +177,8 @@ struct cpu_efficiency {
* use the default SCHED_POWER_SCALE value for cpu_scale.
*/
static const struct cpu_efficiency table_efficiency[] = {
+ { "arm,cortex-a57", 3891 },
+ { "arm,cortex-a53", 2048 },
{ NULL, },
};
--
1.9.0.rc3
^ permalink raw reply related
* [PATCH 3/4] arm64: topology: Tell the scheduler about the relative power of cores
From: Mark Brown @ 2014-02-10 13:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1392037324-5069-1-git-send-email-broonie@kernel.org>
From: Mark Brown <broonie@linaro.org>
In heterogeneous systems like big.LITTLE systems the scheduler will be
able to make better use of the available cores if we provide power numbers
to it indicating their relative performance. Do this by parsing the CPU
nodes in the DT.
This code currently has no effect as no information on the relative
performance of the cores is provided.
Signed-off-by: Mark Brown <broonie@linaro.org>
---
arch/arm64/kernel/topology.c | 142 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 142 insertions(+)
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index 061e3b813b9f..951b55e24f13 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -19,9 +19,33 @@
#include <linux/nodemask.h>
#include <linux/of.h>
#include <linux/sched.h>
+#include <linux/slab.h>
#include <asm/topology.h>
+/*
+ * cpu power table
+ * This per cpu data structure describes the relative capacity of each core.
+ * On a heteregenous system, cores don't have the same computation capacity
+ * and we reflect that difference in the cpu_power field so the scheduler can
+ * take this difference into account during load balance. A per cpu structure
+ * is preferred because each CPU updates its own cpu_power field during the
+ * load balance except for idle cores. One idle core is selected to run the
+ * rebalance_domains for all idle cores and the cpu_power can be updated
+ * during this sequence.
+ */
+static DEFINE_PER_CPU(unsigned long, cpu_scale);
+
+unsigned long arch_scale_freq_power(struct sched_domain *sd, int cpu)
+{
+ return per_cpu(cpu_scale, cpu);
+}
+
+static void set_power_scale(unsigned int cpu, unsigned long power)
+{
+ per_cpu(cpu_scale, cpu) = power;
+}
+
#ifdef CONFIG_OF
static int __init get_cpu_for_node(struct device_node *node)
{
@@ -137,9 +161,49 @@ static void __init parse_cluster(struct device_node *cluster, int depth)
cluster_id++;
}
+struct cpu_efficiency {
+ const char *compatible;
+ unsigned long efficiency;
+};
+
+/*
+ * Table of relative efficiency of each processors
+ * The efficiency value must fit in 20bit and the final
+ * cpu_scale value must be in the range
+ * 0 < cpu_scale < 3*SCHED_POWER_SCALE/2
+ * in order to return@most 1 when DIV_ROUND_CLOSEST
+ * is used to compute the capacity of a CPU.
+ * Processors that are not defined in the table,
+ * use the default SCHED_POWER_SCALE value for cpu_scale.
+ */
+static const struct cpu_efficiency table_efficiency[] = {
+ { NULL, },
+};
+
+static unsigned long *__cpu_capacity;
+#define cpu_capacity(cpu) __cpu_capacity[cpu]
+
+static unsigned long middle_capacity = 1;
+
+/*
+ * Iterate all CPUs' descriptor in DT and compute the efficiency
+ * (as per table_efficiency). Also calculate a middle efficiency
+ * as close as possible to (max{eff_i} - min{eff_i}) / 2
+ * This is later used to scale the cpu_power field such that an
+ * 'average' CPU is of middle power. Also see the comments near
+ * table_efficiency[] and update_cpu_power().
+ */
static void __init parse_dt_topology(void)
{
+ const struct cpu_efficiency *cpu_eff;
struct device_node *cn;
+ unsigned long min_capacity = ULONG_MAX;
+ unsigned long max_capacity = 0;
+ unsigned long capacity = 0;
+ int cpu;
+
+ __cpu_capacity = kcalloc(nr_cpu_ids, sizeof(*__cpu_capacity),
+ GFP_NOWAIT);
cn = of_find_node_by_path("/cpus");
if (!cn) {
@@ -155,10 +219,84 @@ static void __init parse_dt_topology(void)
if (!cn)
return;
parse_cluster(cn, 0);
+
+ for_each_possible_cpu(cpu) {
+ const u32 *rate;
+ int len;
+
+ /* Too early to use cpu->of_node */
+ cn = of_get_cpu_node(cpu, NULL);
+ if (!cn) {
+ pr_err("Missing device node for CPU %d\n", cpu);
+ continue;
+ }
+
+ for (cpu_eff = table_efficiency; cpu_eff->compatible; cpu_eff++)
+ if (of_device_is_compatible(cn, cpu_eff->compatible))
+ break;
+
+ if (cpu_eff->compatible == NULL) {
+ pr_warn("%s: Unknown CPU type\n", cn->full_name);
+ continue;
+ }
+
+ rate = of_get_property(cn, "clock-frequency", &len);
+ if (!rate || len != 4) {
+ pr_err("%s: Missing clock-frequency property\n",
+ cn->full_name);
+ continue;
+ }
+
+ capacity = ((be32_to_cpup(rate)) >> 20) * cpu_eff->efficiency;
+
+ /* Save min capacity of the system */
+ if (capacity < min_capacity)
+ min_capacity = capacity;
+
+ /* Save max capacity of the system */
+ if (capacity > max_capacity)
+ max_capacity = capacity;
+
+ cpu_capacity(cpu) = capacity;
+ }
+
+ /* If min and max capacities are equal we bypass the update of the
+ * cpu_scale because all CPUs have the same capacity. Otherwise, we
+ * compute a middle_capacity factor that will ensure that the capacity
+ * of an 'average' CPU of the system will be as close as possible to
+ * SCHED_POWER_SCALE, which is the default value, but with the
+ * constraint explained near table_efficiency[].
+ */
+ if (min_capacity == max_capacity)
+ return;
+ else if (4 * max_capacity < (3 * (max_capacity + min_capacity)))
+ middle_capacity = (min_capacity + max_capacity)
+ >> (SCHED_POWER_SHIFT+1);
+ else
+ middle_capacity = ((max_capacity / 3)
+ >> (SCHED_POWER_SHIFT-1)) + 1;
+
+}
+
+/*
+ * Look for a customed capacity of a CPU in the cpu_topo_data table during the
+ * boot. The update of all CPUs is in O(n^2) for heteregeneous system but the
+ * function returns directly for SMP system.
+ */
+static void update_cpu_power(unsigned int cpu)
+{
+ if (!cpu_capacity(cpu))
+ return;
+
+ set_power_scale(cpu, cpu_capacity(cpu) / middle_capacity);
+
+ pr_info("CPU%u: update cpu_power %lu\n",
+ cpu, arch_scale_freq_power(NULL, cpu));
}
#else
static inline void parse_dt_topology(void) {}
+static inline void update_cpu_power(unsigned int cpuid) {}
#endif
/*
@@ -207,6 +345,8 @@ void store_cpu_topology(unsigned int cpuid)
pr_info("CPU%u: No topology information configured\n", cpuid);
else
update_siblings_masks(cpuid);
+
+ update_cpu_power(cpuid);
}
/*
@@ -226,6 +366,8 @@ void __init init_cpu_topology(void)
cpu_topo->cluster_id = -1;
cpumask_clear(&cpu_topo->core_sibling);
cpumask_clear(&cpu_topo->thread_sibling);
+
+ set_power_scale(cpu, SCHED_POWER_SCALE);
}
parse_dt_topology();
--
1.9.0.rc3
^ permalink raw reply related
* [PATCH 2/4] arm64: topology: Add support for topology DT bindings
From: Mark Brown @ 2014-02-10 13:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1392037324-5069-1-git-send-email-broonie@kernel.org>
From: Mark Brown <broonie@linaro.org>
Add support for parsing the explicit topology bindings to discover the
topology of the system.
Since it is not currently clear how to map multi-level clusters for the
scheduler all leaf clusters are presented to the scheduler at the same
level. This should be enough to provide good support for current systems.
Signed-off-by: Mark Brown <broonie@linaro.org>
---
arch/arm64/kernel/topology.c | 143 +++++++++++++++++++++++++++++++++++++++++++
1 file changed, 143 insertions(+)
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
index a6d4ed2d69c0..061e3b813b9f 100644
--- a/arch/arm64/kernel/topology.c
+++ b/arch/arm64/kernel/topology.c
@@ -17,10 +17,150 @@
#include <linux/percpu.h>
#include <linux/node.h>
#include <linux/nodemask.h>
+#include <linux/of.h>
#include <linux/sched.h>
#include <asm/topology.h>
+#ifdef CONFIG_OF
+static int __init get_cpu_for_node(struct device_node *node)
+{
+ struct device_node *cpu_node;
+ int cpu;
+
+ cpu_node = of_parse_phandle(node, "cpu", 0);
+ if (!cpu_node)
+ return -1;
+
+ for_each_possible_cpu(cpu) {
+ if (of_get_cpu_node(cpu, NULL) == cpu_node)
+ return cpu;
+ }
+
+ pr_crit("Unable to find CPU node for %s\n", cpu_node->full_name);
+ return -1;
+}
+
+static void __init parse_core(struct device_node *core, int cluster_id,
+ int core_id)
+{
+ char name[10];
+ bool leaf = true;
+ int i = 0;
+ int cpu;
+ struct device_node *t;
+
+ do {
+ snprintf(name, sizeof(name), "thread%d", i);
+ t = of_get_child_by_name(core, name);
+ if (t) {
+ leaf = false;
+ cpu = get_cpu_for_node(t);
+ if (cpu >= 0) {
+ cpu_topology[cpu].cluster_id = cluster_id;
+ cpu_topology[cpu].core_id = core_id;
+ cpu_topology[cpu].thread_id = i;
+ } else {
+ pr_err("%s: Can't get CPU for thread\n",
+ t->full_name);
+ }
+ }
+ i++;
+ } while (t);
+
+ cpu = get_cpu_for_node(core);
+ if (cpu >= 0) {
+ if (!leaf) {
+ pr_err("%s: Core has both threads and CPU\n",
+ core->full_name);
+ return;
+ }
+
+ cpu_topology[cpu].cluster_id = cluster_id;
+ cpu_topology[cpu].core_id = core_id;
+ } else if (leaf) {
+ pr_err("%s: Can't get CPU for leaf core\n", core->full_name);
+ }
+}
+
+static void __init parse_cluster(struct device_node *cluster, int depth)
+{
+ char name[10];
+ bool leaf = true;
+ bool has_cores = false;
+ struct device_node *c;
+ static int __initdata cluster_id;
+ int core_id = 0;
+ int i;
+
+ /*
+ * First check for child clusters; we currently ignore any
+ * information about the nesting of clusters and present the
+ * scheduler with a flat list of them.
+ */
+ i = 0;
+ do {
+ snprintf(name, sizeof(name), "cluster%d", i);
+ c = of_get_child_by_name(cluster, name);
+ if (c) {
+ parse_cluster(c, depth + 1);
+ leaf = false;
+ }
+ i++;
+ } while (c);
+
+ /* Now check for cores */
+ i = 0;
+ do {
+ snprintf(name, sizeof(name), "core%d", i);
+ c = of_get_child_by_name(cluster, name);
+ if (c) {
+ has_cores = true;
+
+ if (depth == 0)
+ pr_err("%s: cpu-map children should be clusters\n",
+ c->full_name);
+
+ if (leaf)
+ parse_core(c, cluster_id, core_id++);
+ else
+ pr_err("%s: Non-leaf cluster with core %s\n",
+ cluster->full_name, name);
+ }
+ i++;
+ } while (c);
+
+ if (leaf && !has_cores)
+ pr_warn("%s: empty cluster\n", cluster->full_name);
+
+ if (leaf)
+ cluster_id++;
+}
+
+static void __init parse_dt_topology(void)
+{
+ struct device_node *cn;
+
+ cn = of_find_node_by_path("/cpus");
+ if (!cn) {
+ pr_err("No CPU information found in DT\n");
+ return;
+ }
+
+ /*
+ * When topology is provided cpu-map is essentially a root
+ * cluster with restricted subnodes.
+ */
+ cn = of_find_node_by_name(cn, "cpu-map");
+ if (!cn)
+ return;
+ parse_cluster(cn, 0);
+}
+
+#else
+static inline void parse_dt_topology(void) {}
+#endif
+
/*
* cpu topology table
*/
@@ -87,5 +227,8 @@ void __init init_cpu_topology(void)
cpumask_clear(&cpu_topo->core_sibling);
cpumask_clear(&cpu_topo->thread_sibling);
}
+
+ parse_dt_topology();
+
smp_wmb();
}
--
1.9.0.rc3
^ permalink raw reply related
* [PATCH 1/4] arm64: topology: Implement basic CPU topology support
From: Mark Brown @ 2014-02-10 13:02 UTC (permalink / raw)
To: linux-arm-kernel
From: Mark Brown <broonie@linaro.org>
Add basic CPU topology support to arm64, based on the existing pre-v8
code and some work done by Mark Hambleton. This patch does not
implement any topology discovery support since that should be based on
information from firmware, it merely implements the scaffolding for
integration of topology support in the architecture.
The goal is to separate the architecture hookup for providing topology
information from the DT parsing in order to ease review and avoid
blocking the architecture code (which will be built on by other work)
with the DT code review by providing something simple and basic.
A following patch will implement support for parsing the DT topology
bindings for ARM, similar patches will be needed for ACPI.
Signed-off-by: Mark Brown <broonie@linaro.org>
---
arch/arm64/Kconfig | 24 +++++++++++
arch/arm64/include/asm/topology.h | 39 +++++++++++++++++
arch/arm64/kernel/Makefile | 1 +
arch/arm64/kernel/smp.c | 11 +++++
arch/arm64/kernel/topology.c | 91 +++++++++++++++++++++++++++++++++++++++
5 files changed, 166 insertions(+)
create mode 100644 arch/arm64/include/asm/topology.h
create mode 100644 arch/arm64/kernel/topology.c
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 27bbcfc7202a..fea7b477676b 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -164,6 +164,30 @@ config SMP
If you don't know what to do here, say N.
+config CPU_TOPOLOGY
+ bool "Support CPU topology definition"
+ depends on SMP
+ default y
+ help
+ Support CPU topology definition, based on configuration
+ provided by the firmware.
+
+config SCHED_MC
+ bool "Multi-core scheduler support"
+ depends on CPU_TOPOLOGY
+ help
+ Multi-core scheduler support improves the CPU scheduler's decision
+ making when dealing with multi-core CPU chips at a cost of slightly
+ increased overhead in some places. If unsure say N here.
+
+config SCHED_SMT
+ bool "SMT scheduler support"
+ depends on CPU_TOPOLOGY
+ help
+ Improves the CPU scheduler's decision making when dealing with
+ MultiThreading at a cost of slightly increased overhead in some
+ places. If unsure say N here.
+
config NR_CPUS
int "Maximum number of CPUs (2-32)"
range 2 32
diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h
new file mode 100644
index 000000000000..c8a47e8f452b
--- /dev/null
+++ b/arch/arm64/include/asm/topology.h
@@ -0,0 +1,39 @@
+#ifndef __ASM_TOPOLOGY_H
+#define __ASM_TOPOLOGY_H
+
+#ifdef CONFIG_CPU_TOPOLOGY
+
+#include <linux/cpumask.h>
+
+struct cpu_topology {
+ int thread_id;
+ int core_id;
+ int cluster_id;
+ cpumask_t thread_sibling;
+ cpumask_t core_sibling;
+};
+
+extern struct cpu_topology cpu_topology[NR_CPUS];
+
+#define topology_physical_package_id(cpu) (cpu_topology[cpu].cluster_id)
+#define topology_core_id(cpu) (cpu_topology[cpu].core_id)
+#define topology_core_cpumask(cpu) (&cpu_topology[cpu].core_sibling)
+#define topology_thread_cpumask(cpu) (&cpu_topology[cpu].thread_sibling)
+
+#define mc_capable() (cpu_topology[0].cluster_id != -1)
+#define smt_capable() (cpu_topology[0].thread_id != -1)
+
+void init_cpu_topology(void);
+void store_cpu_topology(unsigned int cpuid);
+const struct cpumask *cpu_coregroup_mask(int cpu);
+
+#else
+
+static inline void init_cpu_topology(void) { }
+static inline void store_cpu_topology(unsigned int cpuid) { }
+
+#endif
+
+#include <asm-generic/topology.h>
+
+#endif /* _ASM_ARM_TOPOLOGY_H */
diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile
index 2d4554b13410..252b62181532 100644
--- a/arch/arm64/kernel/Makefile
+++ b/arch/arm64/kernel/Makefile
@@ -20,6 +20,7 @@ arm64-obj-$(CONFIG_HAVE_HW_BREAKPOINT)+= hw_breakpoint.o
arm64-obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
arm64-obj-$(CONFIG_ARM64_CPU_SUSPEND) += sleep.o suspend.o
arm64-obj-$(CONFIG_JUMP_LABEL) += jump_label.o
+arm64-obj-$(CONFIG_CPU_TOPOLOGY) += topology.o
obj-y += $(arm64-obj-y) vdso/
obj-m += $(arm64-obj-m)
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 7cfb92a4ab66..9660750f34ba 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -114,6 +114,11 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
return ret;
}
+static void smp_store_cpu_info(unsigned int cpuid)
+{
+ store_cpu_topology(cpuid);
+}
+
/*
* This is the secondary CPU boot entry. We're using this CPUs
* idle thread stack, but a set of temporary page tables.
@@ -152,6 +157,8 @@ asmlinkage void secondary_start_kernel(void)
*/
notify_cpu_starting(cpu);
+ smp_store_cpu_info(cpu);
+
/*
* OK, now it's safe to let the boot CPU continue. Wait for
* the CPU migration code to notice that the CPU is online
@@ -390,6 +397,10 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
int err;
unsigned int cpu, ncores = num_possible_cpus();
+ init_cpu_topology();
+
+ smp_store_cpu_info(smp_processor_id());
+
/*
* are we trying to boot more cores than exist?
*/
diff --git a/arch/arm64/kernel/topology.c b/arch/arm64/kernel/topology.c
new file mode 100644
index 000000000000..a6d4ed2d69c0
--- /dev/null
+++ b/arch/arm64/kernel/topology.c
@@ -0,0 +1,91 @@
+/*
+ * arch/arm64/kernel/topology.c
+ *
+ * Copyright (C) 2011,2013 Linaro Limited.
+ *
+ * Based on the arm32 version written by Vincent Guittot in turn based on
+ * arch/sh/kernel/topology.c
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/cpu.h>
+#include <linux/cpumask.h>
+#include <linux/init.h>
+#include <linux/percpu.h>
+#include <linux/node.h>
+#include <linux/nodemask.h>
+#include <linux/sched.h>
+
+#include <asm/topology.h>
+
+/*
+ * cpu topology table
+ */
+struct cpu_topology cpu_topology[NR_CPUS];
+EXPORT_SYMBOL_GPL(cpu_topology);
+
+const struct cpumask *cpu_coregroup_mask(int cpu)
+{
+ return &cpu_topology[cpu].core_sibling;
+}
+
+static void update_siblings_masks(unsigned int cpuid)
+{
+ struct cpu_topology *cpu_topo, *cpuid_topo = &cpu_topology[cpuid];
+ int cpu;
+
+ /* update core and thread sibling masks */
+ for_each_possible_cpu(cpu) {
+ cpu_topo = &cpu_topology[cpu];
+
+ if (cpuid_topo->cluster_id != cpu_topo->cluster_id)
+ continue;
+
+ cpumask_set_cpu(cpuid, &cpu_topo->core_sibling);
+ if (cpu != cpuid)
+ cpumask_set_cpu(cpu, &cpuid_topo->core_sibling);
+
+ if (cpuid_topo->core_id != cpu_topo->core_id)
+ continue;
+
+ cpumask_set_cpu(cpuid, &cpu_topo->thread_sibling);
+ if (cpu != cpuid)
+ cpumask_set_cpu(cpu, &cpuid_topo->thread_sibling);
+ }
+ smp_wmb();
+}
+
+void store_cpu_topology(unsigned int cpuid)
+{
+ struct cpu_topology *cpuid_topo = &cpu_topology[cpuid];
+
+ /* DT should have been parsed by the time we get here */
+ if (cpuid_topo->core_id == -1)
+ pr_info("CPU%u: No topology information configured\n", cpuid);
+ else
+ update_siblings_masks(cpuid);
+}
+
+/*
+ * init_cpu_topology is called at boot when only one cpu is running
+ * which prevent simultaneous write access to cpu_topology array
+ */
+void __init init_cpu_topology(void)
+{
+ unsigned int cpu;
+
+ /* init core mask and power*/
+ for_each_possible_cpu(cpu) {
+ struct cpu_topology *cpu_topo = &cpu_topology[cpu];
+
+ cpu_topo->thread_id = -1;
+ cpu_topo->core_id = -1;
+ cpu_topo->cluster_id = -1;
+ cpumask_clear(&cpu_topo->core_sibling);
+ cpumask_clear(&cpu_topo->thread_sibling);
+ }
+ smp_wmb();
+}
--
1.9.0.rc3
^ permalink raw reply related
* [PATCH 1/7] pinctrl: sh-pfc: r8a7790: Add QSPI pin groups
From: Geert Uytterhoeven @ 2014-02-10 12:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <8438484.DB7cn7tjVR@avalon>
On Mon, Feb 10, 2014 at 1:48 PM, Laurent Pinchart
<laurent.pinchart@ideasonboard.com> wrote:
>> @@ -4212,6 +4244,7 @@ static const struct sh_pfc_function pinmux_functions[]
>> = { SH_PFC_FUNCTION(msiof0),
>> SH_PFC_FUNCTION(msiof1),
>> SH_PFC_FUNCTION(msiof2),
>> + SH_PFC_FUNCTION(qspi),
>> SH_PFC_FUNCTION(msiof3),
>
> I believe qspi comes after msiof3 :-)
Doh... silly me...
> Apart from that the patch looks good.
>
> Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Thanks!
Gr{oetje,eeting}s,
Geert
--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert at linux-m68k.org
In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
-- Linus Torvalds
^ permalink raw reply
* [GIT PULL] at91: fixes for 3.14 #1
From: Nicolas Ferre @ 2014-02-10 12:58 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140207172055.GC9558@ns203013.ovh.net>
On 07/02/2014 18:20, Jean-Christophe PLAGNIOL-VILLARD :
> On 17:36 Fri 07 Feb , Nicolas Ferre wrote:
>> Arnd, Olof, Kevin,
>>
>> This is a first "fixes" series for AT91 on 3.14.
>> The content is only DT-related and quite boring.
>> I took the opportunity of this early "fixes" pull-request to collect
>> some Documentation patches that were lying around and I guess that
>> they can be merged by arm-soc nicely (addition of CCF to 2 drivers).
>> A new board is added to the lot because it is dead simple and integrates
>> well with the new sama5d36 SoC that we added earlier in this development cycle.
>>
>> Thanks, best regards,
>>
>> The following changes since commit 38dbfb59d1175ef458d006556061adeaa8751b72:
>>
>> Linus 3.14-rc1 (2014-02-02 16:42:13 -0800)
>>
>> are available in the git repository at:
>>
>> git://github.com/at91linux/linux-at91.git tags/at91-fixes
>>
>> for you to fetch changes up to b7c2b6157079811586180d13c44a1095b57c2d47:
>>
>> ARM: at91: add Atmel's SAMA5D3 Xplained board (2014-02-07 17:20:39 +0100)
>>
>> ----------------------------------------------------------------
>> First series of AT91 fixes for 3.14.
>> All of them are DT-related.
>> - fixes for typos in i2c and ohci clocks
>> - addition of a USB host node for at91sam9n12ek
>> - 2 DT documentation updates that have been sent a long time ago
>> - a new board based on the sama5d36 SoC
>>
>> ----------------------------------------------------------------
>> Bo Shen (1):
>> ARM: at91: enable USB host on at91sam9n12ek board
>>
>> Boris BREZILLON (3):
>> ARM: at91/dt: fix sama5d3 ohci hclk clock reference
>> mmc: atmel-mci: document clock properties
>> spi/atmel: document clock properties
>>
>> Jean-Jacques Hiblot (1):
>> ARM: at91/dt: sam9263: fix compatibility string for the I2C
>>
>> Nicolas Ferre (1):
>> ARM: at91: add Atmel's SAMA5D3 Xplained board
>
> still comment on it please drop it on the PULL
No, please don't.
I wrote this pull-request after having considered Jean-Christophe's
comments and having corrected my initial DTS file.
The comments that Jean-Christophe made in addition to the patch included
in this pull-request are just his point of view that I don't share (and
I've just answered his email BTW).
Jean-Christophe, I tend to ask for code inclusion when I am sure that
the content is ready and don't build a pull-request lightly. So please
do not add fuzziness to the AT91 maintenance process.
That said, I do not plan to put pressure on anybody. I just thought that
this board was simple enough so that it can seamlessly integrate 3.14...
Bye,
>> .../devicetree/bindings/mmc/atmel-hsmci.txt | 5 +
>> .../devicetree/bindings/spi/spi_atmel.txt | 5 +
>> arch/arm/boot/dts/Makefile | 1 +
>> arch/arm/boot/dts/at91-sama5d3_xplained.dts | 229 +++++++++++++++++++++
>> arch/arm/boot/dts/at91sam9263.dtsi | 2 +-
>> arch/arm/boot/dts/at91sam9n12ek.dts | 4 +
>> arch/arm/boot/dts/sama5d3.dtsi | 2 +-
>> 7 files changed, 246 insertions(+), 2 deletions(-)
>> create mode 100644 arch/arm/boot/dts/at91-sama5d3_xplained.dts
>>
>> --
>> Nicolas Ferre
>
--
Nicolas Ferre
^ permalink raw reply
* [PATCH] reset: Add generic GPIO reset driver.
From: Martin Fuzzey @ 2014-02-10 12:54 UTC (permalink / raw)
To: linux-arm-kernel
This driver allows GPIO lines to be used as reset signals.
It has two main use cases:
1) Allow drivers to reset their hardware via a GPIO line in a standard fashion
as supplied by the reset framework.
This allows adhoc driver code requesting GPIOs etc to be replaced with a
single call to device_reset().
2) Allow hardware on discoverable busses to be rest via a GPIO line
without driver modifications.
Examples of the second use case include:
* SDIO wifi modules
* USB hub chips with a reset line
In this second use case the reset has to be done externally to the driver
managing the hardware since resetting the device from the driver's probe()
method will either do nothing (if the device needs to be reset before
ennumeration will work) or cause racy beahviour (when the device disappears
from the bus during probe()).
So, in addition to providing a gpio based reset controller implementation
it is also possible to reset devices at boot via a DT property or from
userspace on request via sysfs attributes.
Signed-off-by: Martin Fuzzey <mfuzzey@parkeon.com>
---
Documentation/ABI/testing/sysfs-driver-gpio-reset | 18 +
Documentation/devicetree/bindings/reset/gpio.txt | 44 ++
drivers/reset/Kconfig | 13 +
drivers/reset/Makefile | 1
drivers/reset/gpio-reset.c | 460 +++++++++++++++++++++
5 files changed, 536 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-driver-gpio-reset
create mode 100644 Documentation/devicetree/bindings/reset/gpio.txt
create mode 100644 drivers/reset/gpio-reset.c
diff --git a/Documentation/ABI/testing/sysfs-driver-gpio-reset b/Documentation/ABI/testing/sysfs-driver-gpio-reset
new file mode 100644
index 0000000..6c14144
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-driver-gpio-reset
@@ -0,0 +1,18 @@
+In the descriptions below <line-name> is the name of the device tree node
+describing the reset line.
+
+What: /sys/bus/platform/devices/gpio-reset.<ID>/<line-name>/duration_ms
+Date: February 2014
+Contact: Martin Fuzzey <mfuzzey@parkeon.com>
+Description: Allows reset duration to be configured
+ Read: returns reset duration in ms (decimal)
+ Write: sets new resst duration in ms (decimal)
+
+What: /sys/bus/platform/devices/gpio-reset.<ID>/<line-name>/control
+Date: February 2014
+Contact: Martin Fuzzey <mfuzzey@parkeon.com>
+Description: Allows reset line state to be controlled
+ Write only accepting the following strings:
+ "reset" : Line will be asserted during the reset duration then deasserted
+ "assert" : Line will be asserted until next write operation
+ "deassert" : Line will be deasserted until the next write operation
diff --git a/Documentation/devicetree/bindings/reset/gpio.txt b/Documentation/devicetree/bindings/reset/gpio.txt
new file mode 100644
index 0000000..1a36821
--- /dev/null
+++ b/Documentation/devicetree/bindings/reset/gpio.txt
@@ -0,0 +1,44 @@
+Generic GPIO based Reset Controller
+======================================
+
+Please also refer to reset.txt in this directory for common reset
+controller binding usage.
+
+The parent node only needs a compatible property "linux,gpio-reset".
+
+Eaach reset line is described by a child node with the following properties:
+Required properties:
+- gpios : phandle of the GPIO line to use
+
+Optional properties:
+- asserted-state: 0 => line low to reset, 1 => line high to reset. Defalut 0
+- duration-ms : Number of ms the line should be asserted while resetting (default 1)
+- auto : boolean property - if present a reset will be done on boot
+- #reset-cells: 0 if drivers can trigger reset via phandle
+
+example:
+
+gpio-reset {
+ compatible = "linux,gpio-reset";
+
+ wifi {
+ gpios = <&gpio2 1 0>;
+ asserted-state = <0>;
+ duration-ms = <100>;
+ auto;
+ };
+
+ ethernet_phy_reset:ethernet_phy {
+ #reset-cells = <0>;
+ gpios = <&gpio7 6 0>;
+ asserted-state = <0>;
+ duration-ms = <100>;
+ };
+};
+
+Note that, although this controller may be used as part of the reset
+framework, meaning that a device driver may request the reset using the
+child node's phandle it (ethernet example above) it can also be used
+in a standalone mode where the reset is performed automatically at boot
+or from userspace by sysfs. This is particularly for devices that require
+reset but are on discoverable busses (eg SDIO, USB).
diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index c9d04f7..edf867c 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -11,3 +11,16 @@ menuconfig RESET_CONTROLLER
via GPIOs or SoC-internal reset controller modules.
If unsure, say no.
+
+config GPIO_RESET_CONTROLLER
+ tristate "GPIO reset controller"
+ help
+ Reset controller using GPIO lines
+
+ There are two main methods of using this controller:
+ * As a reset controller within the reset framework allowing device
+ drivers to request a hardware reset of their devices.
+ * As a standalone driver performing reset at boot or upon userspace
+ request (via sysfs)
+ The second method is suitable for devices on discoverable busses
+ (SDIO, USB)
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 1e2d83f..57c2751 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -1 +1,2 @@
obj-$(CONFIG_RESET_CONTROLLER) += core.o
+obj-$(CONFIG_GPIO_RESET_CONTROLLER) += gpio-reset.o
diff --git a/drivers/reset/gpio-reset.c b/drivers/reset/gpio-reset.c
new file mode 100644
index 0000000..17f8a45
--- /dev/null
+++ b/drivers/reset/gpio-reset.c
@@ -0,0 +1,460 @@
+/*
+ * Copyright 2014 Parkeon
+ * Martin Fuzzey <mfuzzey@parkeon.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU General Public License version 2 as published by the
+ * Free Software Foundation.
+ *
+ * Driver allowing arbitary hardware to be reset by GPIO signals.
+ * The reset may be triggered in several ways:
+ * At boot time (if configured in DT)
+ * On userspace request via sysfs
+ * By a driver using the reset controller framework
+ *
+ * The first two methods are supplied for devices on discoverable busses
+ * needing an external reset (eg some SDIO modules, USB hub chips)
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+
+
+struct gpio_reset_priv;
+
+struct gpio_reset_line {
+ struct kobject kobj;
+ struct gpio_reset_priv *priv;
+ const char *name;
+ int gpio;
+ uint32_t asserted_value;
+ uint32_t duration_ms;
+#ifdef CONFIG_RESET_CONTROLLER
+ struct reset_controller_dev rcdev;
+#endif
+};
+#define kobj_to_gpio_reset_line(x) container_of(x, struct gpio_reset_line, kobj)
+
+
+struct gpio_reset_priv {
+ struct kref refcount;
+ struct device *dev;
+ int num_lines;
+ struct gpio_reset_line lines[];
+};
+
+struct gpio_reset_attribute {
+ struct attribute attr;
+ ssize_t (*show)(struct gpio_reset_line *line,
+ struct gpio_reset_attribute *attr, char *buf);
+ ssize_t (*store)(struct gpio_reset_line *line,
+ struct gpio_reset_attribute *attr,
+ const char *buf, size_t count);
+};
+#define to_gpio_reset_attr(x) container_of(x, struct gpio_reset_attribute, attr)
+
+
+static void gpio_reset_assert(struct gpio_reset_line *line)
+{
+ gpio_set_value(line->gpio, line->asserted_value);
+}
+
+static void gpio_reset_deassert(struct gpio_reset_line *line)
+{
+ gpio_set_value(line->gpio, !line->asserted_value);
+}
+
+static void gpio_reset_reset(struct gpio_reset_line *line)
+{
+ dev_info(line->priv->dev, "Resetting '%s' (%dms)",
+ line->name, line->duration_ms);
+ gpio_reset_assert(line);
+ msleep(line->duration_ms);
+ gpio_reset_deassert(line);
+}
+
+
+static void gpio_reset_free_priv(struct kref *ref)
+{
+ struct gpio_reset_priv *priv = container_of(ref,
+ struct gpio_reset_priv, refcount);
+
+ kfree(priv);
+}
+
+static void gpio_reset_release_kobj(struct kobject *kobj)
+{
+ struct gpio_reset_line *line;
+
+ line = kobj_to_gpio_reset_line(kobj);
+
+ kref_put(&line->priv->refcount, gpio_reset_free_priv);
+}
+
+
+#ifdef CONFIG_SYSFS
+
+static ssize_t gpio_reset_attr_show(struct kobject *kobj,
+ struct attribute *attr,
+ char *buf)
+{
+ struct gpio_reset_attribute *attribute;
+ struct gpio_reset_line *line;
+
+ attribute = to_gpio_reset_attr(attr);
+ line = kobj_to_gpio_reset_line(kobj);
+
+ if (!attribute->show)
+ return -EIO;
+
+ return attribute->show(line, attribute, buf);
+}
+
+static ssize_t gpio_reset_attr_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *buf, size_t len)
+{
+ struct gpio_reset_attribute *attribute;
+ struct gpio_reset_line *line;
+
+ attribute = to_gpio_reset_attr(attr);
+ line = kobj_to_gpio_reset_line(kobj);
+
+ if (!attribute->store)
+ return -EIO;
+
+ return attribute->store(line, attribute, buf, len);
+}
+
+static ssize_t control_store(struct gpio_reset_line *line,
+ struct gpio_reset_attribute *attr, const char *buf, size_t count)
+{
+ char action[10];
+ char *eol;
+
+ strncpy(action, buf, min(count, sizeof(action)));
+ action[sizeof(action) - 1] = '\0';
+ eol = strrchr(action, '\n');
+ if (eol)
+ *eol = '\0';
+
+ if (!strcmp("reset", action))
+ gpio_reset_reset(line);
+ else if (!strcmp("assert", action))
+ gpio_reset_assert(line);
+ else if (!strcmp("deassert", action))
+ gpio_reset_deassert(line);
+ else
+ return -EINVAL;
+
+ return count;
+}
+
+static ssize_t duration_ms_show(struct gpio_reset_line *line,
+ struct gpio_reset_attribute *attr, char *buf)
+{
+ return sprintf(buf, "%d\n", line->duration_ms);
+}
+
+static ssize_t duration_ms_store(struct gpio_reset_line *line,
+ struct gpio_reset_attribute *attr, const char *buf, size_t count)
+{
+ if (sscanf(buf, "%u", &line->duration_ms) != 1)
+ return -EINVAL;
+
+ return count;
+}
+
+static struct gpio_reset_attribute control_attribute = __ATTR_WO(control);
+static struct gpio_reset_attribute duration_attribute = __ATTR_RW(duration_ms);
+
+static struct attribute *gpio_reset_attrs[] = {
+ &control_attribute.attr,
+ &duration_attribute.attr,
+ NULL
+};
+
+
+static const struct sysfs_ops gpio_reset_sysfs_ops = {
+ .show = gpio_reset_attr_show,
+ .store = gpio_reset_attr_store,
+};
+
+
+static struct kobj_type gpio_reset_ktype = {
+ .release = gpio_reset_release_kobj,
+ .sysfs_ops = &gpio_reset_sysfs_ops,
+ .default_attrs = gpio_reset_attrs,
+};
+
+static int gpio_reset_create_sysfs(struct gpio_reset_line *line)
+{
+ int ret;
+
+ ret = kobject_init_and_add(&line->kobj, &gpio_reset_ktype,
+ &line->priv->dev->kobj, "reset-%s", line->name);
+
+ kref_get(&line->priv->refcount); /* kobject part of private structure */
+
+ if (ret) {
+ kobject_put(&line->kobj);
+ return ret;
+ }
+
+ kobject_uevent(&line->kobj, KOBJ_ADD);
+
+ return 0;
+}
+
+static void gpio_reset_destroy_sysfs(struct gpio_reset_line *line)
+{
+ kobject_put(&line->kobj);
+}
+
+
+#else
+
+static int gpio_reset_create_sysfs(struct gpio_reset_line *line)
+{
+ return 0;
+}
+
+static void gpio_reset_destroy_sysfs(struct gpio_reset_line *line)
+{
+}
+
+#endif /* CONFIG_SYSFS */
+
+
+#ifdef CONFIG_RESET_CONTROLLER
+#define rcdev_to_gpio_reset_line(x) \
+ container_of(x, struct gpio_reset_line, rcdev)
+
+static int gpio_reset_controller_assert(struct reset_controller_dev *rcdev,
+ unsigned long sw_reset_idx)
+{
+ struct gpio_reset_line *line = rcdev_to_gpio_reset_line(rcdev);
+
+ gpio_reset_assert(line);
+
+ return 0;
+}
+
+static int gpio_reset_controller_deassert(struct reset_controller_dev *rcdev,
+ unsigned long sw_reset_idx)
+{
+ struct gpio_reset_line *line = rcdev_to_gpio_reset_line(rcdev);
+
+ gpio_reset_deassert(line);
+
+ return 0;
+}
+
+static int gpio_reset_controller_reset(struct reset_controller_dev *rcdev,
+ unsigned long sw_reset_idx)
+{
+ struct gpio_reset_line *line = rcdev_to_gpio_reset_line(rcdev);
+
+ gpio_reset_reset(line);
+
+ return 0;
+}
+
+static struct reset_control_ops gpio_reset_ops = {
+ .assert = gpio_reset_controller_assert,
+ .deassert = gpio_reset_controller_deassert,
+ .reset = gpio_reset_controller_reset,
+};
+
+
+int gpio_reset_nooarg_xlate(struct reset_controller_dev *rcdev,
+ const struct of_phandle_args *reset_spec)
+{
+ if (WARN_ON(reset_spec->args_count != 0))
+ return -EINVAL;
+
+ return 0;
+}
+
+/* We register one controller per line rather than a single
+ * global controller so that drivers my directly reference the
+ * phandle of the gpio_reset subnode rather than having to know
+ * the index.
+ */
+static int gpio_reset_register_controller(
+ struct device_node *np,
+ struct gpio_reset_line *line)
+{
+ line->rcdev.of_node = np;
+ line->rcdev.nr_resets = 1;
+ line->rcdev.ops = &gpio_reset_ops;
+ line->rcdev.of_xlate = gpio_reset_nooarg_xlate;
+
+ return reset_controller_register(&line->rcdev);
+}
+
+static void gpio_reset_unregister_controller(struct gpio_reset_line *line)
+{
+ if (line->rcdev.nr_resets)
+ reset_controller_unregister(&line->rcdev);
+}
+
+#else
+
+static int gpio_reset_register_controller(
+ struct device_node *np,
+ struct gpio_reset_line *line)
+{
+ return 0;
+}
+
+static void gpio_reset_unregister_controller(struct gpio_reset_line *line)
+{
+}
+#endif /* CONFIG_RESET_CONTROLLER */
+
+
+static int gpio_reset_init_line(
+ struct device_node *np,
+ struct gpio_reset_line *line)
+{
+ int ret;
+ struct device *dev = line->priv->dev;
+
+ line->name = np->name;
+
+ line->gpio = of_get_gpio(np, 0);
+ if (!gpio_is_valid(line->gpio)) {
+ dev_warn(dev, "Invalid reset gpio for '%s'", np->name);
+ return 0;
+ }
+
+ line->duration_ms = 1;
+ of_property_read_u32(np, "asserted-state", &line->asserted_value);
+ of_property_read_u32(np, "duration-ms", &line->duration_ms);
+
+ ret = devm_gpio_request_one(dev, line->gpio,
+ line->asserted_value ? GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH,
+ line->name);
+ if (ret)
+ return ret;
+
+ ret = gpio_reset_create_sysfs(line);
+ if (ret)
+ return ret;
+
+ ret = gpio_reset_register_controller(np, line);
+ if (ret)
+ return ret;
+
+
+ if (of_property_read_bool(np, "auto"))
+ gpio_reset_reset(line);
+
+ return 0;
+}
+
+static void gpio_reset_free_line(struct gpio_reset_line *line)
+{
+ gpio_reset_destroy_sysfs(line);
+ gpio_reset_unregister_controller(line);
+}
+
+static int gpio_reset_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node, *child;
+ struct gpio_reset_priv *priv;
+ struct gpio_reset_line *line;
+ int num_lines;
+ int ret;
+
+ num_lines = of_get_available_child_count(np);
+ if (!num_lines)
+ return -ENODEV;
+
+ for_each_available_child_of_node(np, child) {
+ ret = of_get_gpio(child, 0);
+ if (ret == -EPROBE_DEFER)
+ return ret;
+ }
+
+ priv = kzalloc(sizeof(*priv) + sizeof(*line) * num_lines, GFP_KERNEL);
+ if (!priv)
+ return -ENOMEM;
+
+ kref_init(&priv->refcount);
+ priv->dev = &pdev->dev;
+ priv->num_lines = num_lines;
+
+ line = priv->lines;
+ for_each_available_child_of_node(np, child) {
+ line->priv = priv;
+ ret = gpio_reset_init_line(child, line);
+ if (ret)
+ goto rollback;
+ line++;
+ }
+
+ platform_set_drvdata(pdev, priv);
+
+ return 0;
+
+rollback:
+ while (line >= priv->lines)
+ gpio_reset_free_line(line--);
+
+ kref_put(&priv->refcount, gpio_reset_free_priv);
+
+ return ret;
+}
+
+static int gpio_reset_remove(struct platform_device *pdev)
+{
+ struct gpio_reset_priv *priv = platform_get_drvdata(pdev);
+ int i;
+
+ for (i = 0; i < priv->num_lines; i++)
+ gpio_reset_free_line(&priv->lines[i]);
+
+ kref_put(&priv->refcount, gpio_reset_free_priv);
+
+ return 0;
+}
+
+static const struct of_device_id gpio_reset_dt_ids[] = {
+ { .compatible = "linux,gpio-reset" },
+ {}
+};
+
+static struct platform_driver gpio_reset_driver = {
+ .probe = gpio_reset_probe,
+ .remove = gpio_reset_remove,
+ .driver = {
+ .name = "gpio_reset",
+ .owner = THIS_MODULE,
+ .of_match_table = gpio_reset_dt_ids,
+ },
+};
+
+static int __init gpio_reset_init(void)
+{
+ return platform_driver_register(&gpio_reset_driver);
+}
+subsys_initcall(gpio_reset_init);
+
+static void __exit gpio_reset_exit(void)
+{
+ platform_driver_unregister(&gpio_reset_driver);
+}
+module_exit(gpio_reset_exit);
+
+MODULE_AUTHOR("Martin Fuzzey <mfuzzey@parkeon.com>");
+MODULE_DESCRIPTION("GPIO reset controller");
+MODULE_LICENSE("GPL");
^ permalink raw reply related
* [PATCH 1/2] ARM: shmobile: r8a7791: add Ether DT support
From: Ben Dooks @ 2014-02-10 12:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <201402070112.48304.sergei.shtylyov@cogentembedded.com>
On 06/02/14 22:12, Sergei Shtylyov wrote:
> Define the generic R8A7791 part of the Ether device node.
>
> Signed-off-by: Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>
>
> ---
> arch/arm/boot/dts/r8a7791.dtsi | 15 ++++++++++++++-
> 1 file changed, 14 insertions(+), 1 deletion(-)
>
> Index: renesas/arch/arm/boot/dts/r8a7791.dtsi
> ===================================================================
> --- renesas.orig/arch/arm/boot/dts/r8a7791.dtsi
> +++ renesas/arch/arm/boot/dts/r8a7791.dtsi
> @@ -2,7 +2,8 @@
> * Device Tree Source for the r8a7791 SoC
> *
> * Copyright (C) 2013 Renesas Electronics Corporation
> - * Copyright (C) 2013 Renesas Solutions Corp.
> + * Copyright (C) 2013-2014 Renesas Solutions Corp.
> + * Copyright (C) 2014 Cogent Embedded Inc.
> *
> * This file is licensed under the terms of the GNU General Public License
> * version 2. This program is licensed "as is" without any warranty of any
> @@ -366,6 +367,18 @@
> status = "disabled";
> };
>
> + ether: ethernet at ee700000 {
> + compatible = "renesas,ether-r8a7791";
> + reg = <0 0xee700000 0 0x400>;
> + interrupt-parent = <&gic>;
> + interrupts = <0 162 IRQ_TYPE_LEVEL_HIGH>;
> + clocks = <&mstp8_clks R8A7791_CLK_ETHER>;
> + phy-mode = "rmii";
> + #address-cells = <1>;
> + #size-cells = <0>;
> + status = "disabled";
> + };
Is the device only capable of doing RMII?
--
Ben Dooks http://www.codethink.co.uk/
Senior Engineer Codethink - Providing Genius
^ permalink raw reply
* [PATCH v3 1/2] drivers/base: permit base components to omit the bind/unbind ops
From: Thierry Reding @ 2014-02-10 12:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <9b3c3c2c982f31b026fd1516a2b608026d55b1e9.1391792986.git.moinejf@free.fr>
On Fri, Feb 07, 2014 at 04:55:00PM +0100, Jean-Francois Moine wrote:
> Some simple components don't need to do any specific action on
> bind to / unbind from a master component.
>
> This patch permits such components to omit the bind/unbind
> operations.
>
> Signed-off-by: Jean-Francois Moine <moinejf@free.fr>
> ---
> drivers/base/component.c | 9 +++++++--
> 1 file changed, 7 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/base/component.c b/drivers/base/component.c
> index c53efe6..0a39d7a 100644
> --- a/drivers/base/component.c
> +++ b/drivers/base/component.c
> @@ -225,7 +225,8 @@ static void component_unbind(struct component *component,
> {
> WARN_ON(!component->bound);
>
> - component->ops->unbind(component->dev, master->dev, data);
> + if (component->ops)
> + component->ops->unbind(component->dev, master->dev, data);
This doesn't actually do what the commit message says. This makes
component->ops optional, not component->ops->unbind().
A more correct check would be:
if (component->ops && component->ops->unbind)
> component->bound = false;
>
> /* Release all resources claimed in the binding of this component */
> @@ -274,7 +275,11 @@ static int component_bind(struct component *component, struct master *master,
> dev_dbg(master->dev, "binding %s (ops %ps)\n",
> dev_name(component->dev), component->ops);
>
> - ret = component->ops->bind(component->dev, master->dev, data);
> + if (component->ops)
> + ret = component->ops->bind(component->dev, master->dev, data);
Same here.
Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 836 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140210/0969c543/attachment.sig>
^ permalink raw reply
* [PATCH v2] dma: Add Xilinx AXI Video Direct Memory Access Engine driver support
From: Srikanth Thokala @ 2014-02-10 12:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <52F3B017.5030100@metafoo.de>
On Thu, Feb 6, 2014 at 9:23 PM, Lars-Peter Clausen <lars@metafoo.de> wrote:
> On 02/06/2014 02:34 PM, Srikanth Thokala wrote:
>>
>> On Wed, Feb 5, 2014 at 10:00 PM, Lars-Peter Clausen <lars@metafoo.de>
>> wrote:
>>>
>>> On 02/05/2014 05:25 PM, Srikanth Thokala wrote:
>>>>
>>>>
>>>> On Fri, Jan 31, 2014 at 12:21 PM, Srikanth Thokala <sthokal@xilinx.com>
>>>> wrote:
>>>>>
>>>>>
>>>>> Hi Vinod,
>>>>>
>>>>> On Tue, Jan 28, 2014 at 8:43 AM, Vinod Koul <vinod.koul@intel.com>
>>>>> wrote:
>>>>>>
>>>>>>
>>>>>> On Mon, Jan 27, 2014 at 06:42:36PM +0530, Srikanth Thokala wrote:
>>>>>>>
>>>>>>>
>>>>>>> Hi Lars/Vinod,
>>>>>>>>>
>>>>>>>>>
>>>>>>>>> The question here i think would be waht this device supports? Is
>>>>>>>>> the
>>>>>>>>> hardware
>>>>>>>>> capable of doing interleaved transfers, then would make sense.
>>>>>>>>
>>>>>>>>
>>>>>>>>
>>>>>>>> The hardware does 2D transfers. The parameters for a transfer are
>>>>>>>> height,
>>>>>>>> width and stride. That's only a subset of what interleaved transfers
>>>>>>>> can be
>>>>>>>> (xt->num_frames must be one for 2d transfers). But if I remember
>>>>>>>> correctly
>>>>>>>> there has been some discussion on this in the past and the result of
>>>>>>>> that
>>>>>>>> discussion was that using interleaved transfers for 2D transfers is
>>>>>>>> preferred over adding a custom API for 2D transfers.
>>>>>>>
>>>>>>>
>>>>>>>
>>>>>>> I went through the prep_interleaved_dma API and I see only one
>>>>>>> descriptor
>>>>>>> is prepared per API call (i.e. per frame). As our IP supports upto
>>>>>>> 16
>>>>>>> frame
>>>>>>> buffers (can be more in future), isn't it less efficient compared to
>>>>>>> the
>>>>>>> prep_slave_sg where we get a single sg list and can prepare all the
>>>>>>> descriptors
>>>>>>> (of non-contiguous buffers) in one go? Correct me, if am wrong and
>>>>>>> let
>>>>>>> me
>>>>>>> know your opinions.
>>>>>>
>>>>>>
>>>>>> Well the descriptor maybe one, but that can represent multiple frames,
>>>>>> for
>>>>>> example 16 as in your case. Can you read up the documentation of how
>>>>>> multiple
>>>>>> frames are passed. Pls see include/linux/dmaengine.h
>>>>>>
>>>>>> /**
>>>>>> * Interleaved Transfer Request
>>>>>> * ----------------------------
>>>>>> * A chunk is collection of contiguous bytes to be transfered.
>>>>>> * The gap(in bytes) between two chunks is called
>>>>>> inter-chunk-gap(ICG).
>>>>>> * ICGs may or maynot change between chunks.
>>>>>> * A FRAME is the smallest series of contiguous {chunk,icg} pairs,
>>>>>> * that when repeated an integral number of times, specifies the
>>>>>> transfer.
>>>>>> * A transfer template is specification of a Frame, the number of
>>>>>> times
>>>>>> * it is to be repeated and other per-transfer attributes.
>>>>>> *
>>>>>> * Practically, a client driver would have ready a template for each
>>>>>> * type of transfer it is going to need during its lifetime and
>>>>>> * set only 'src_start' and 'dst_start' before submitting the
>>>>>> requests.
>>>>>> *
>>>>>> *
>>>>>> * | Frame-1 | Frame-2 | ~ |
>>>>>> Frame-'numf' |
>>>>>> * |====....==.===...=...|====....==.===...=...| ~
>>>>>> |====....==.===...=...|
>>>>>> *
>>>>>> * == Chunk size
>>>>>> * ... ICG
>>>>>> */
>>>>>
>>>>>
>>>>>
>>>>> Yes, it can handle multiple frames specified by 'numf' each of size
>>>>> 'frame_size * sgl[0].size'.
>>>>> But, I see it only works if all the frames' memory is contiguous and
>>>>> in this case we
>>>>> can just increment 'src_start' by the total frame size 'numf' number
>>>>> of times to fill in
>>>>> for each HW descriptor (each frame is one HW descriptor). So, there
>>>>> is no issue when the
>>>>> memory is contiguous. If the frames are non contiguous, we have to
>>>>> call this API for each
>>>>> frame (hence for each descriptor), as the src_start for each frame is
>>>>> different. Is it correct?
>>>>>
>>>>> FYI: This hardware has an inbuilt Scatter-Gather engine.
>>>>>
>>>>
>>>> Ping?
>>>
>>>
>>>
>>> If you want to submit multiple frames at once I think you should look at
>>> how
>>> the current dmaengine API can be extended to allow that. And also provide
>>> an
>>> explanation on how this is superior over submitting them one by one.
>>
>>
>>
>> Sure. I would start with explaning the current implementation of this
>> driver.
>>
>> Using prep_slave_sg(), we can define multiple segments in a
>> async_tx_descriptor where each frame is defined by a segment (a sg
>> list entry). So, the slave device could DMA the data (of multiple
>> frames) with a descriptor by calling tx_submit in a transaction i.e.,
>>
>> prep_slave_sg(16) -> tx_submit(1) -> interrupt (16 frames)
>>
>> Using interleaved_dma(), we could not divide into segments when we
>> have scattered memory (for the reasons mentioned in above thread).
>> This implies we are restricting the slave device to process frame by
>> frame i.e.,
>>
>> interleaved_dma(1) -> tx_submit(1) -> interrupt -> interleaved_dma(2)
>> -> tx_submit (2) -> interrupt -> ........ tx_submit(16) -> interrupt
>>
>
> The API allows you to create and submit multiple interleaved descriptors
> before you have to issue them.
>
> interleaved_dma(1) -> tx_submit(1) -> interleaved_dma(2) -> tx_submit(2) ->
> ... -> issue_pending() -> interrupt
>
>
>> This implementation makes the hardware to wait until the next frame is
>> submitted.
>>
>> To overcome this, I feel it would be a good option if we could extend
>> interleaved_dma template to modify src_start/dest_start to be a
>> pointer to an array of addresses. Here, number of addresses will be
>> defined by numf. The other option would be to include scatterlist in
>> the interleaved template. This way we can handle scattered memory
>> using this API.
>
>
> Each "frame" in a interleaved transfer describes a single line in your video
> frame (size = width, icg = stride). numf is the number of lines per video
> frame. So the suggested change does not make that much sense. If you want to
> submit multiple video frames in one batch the best option is in my opinion
> to allow to pass an array of dma_interleaved_template structs instead of a
> single one.
Ok. I agree with you. Will fix it in v3.
Srikanth
>
> - Lars
>
>>
>> Srikanth
>>
>>>
>>> - Lars
>>>
>>>
>>> --
>>> To unsubscribe from this list: send the line "unsubscribe linux-kernel"
>>> in
>>> the body of a message to majordomo at vger.kernel.org
>>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>> Please read the FAQ at http://www.tux.org/lkml/
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe dmaengine" in
>>
>> the body of a message to majordomo at vger.kernel.org
>> More majordomo info at http://vger.kernel.org/majordomo-info.html
>>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo at vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at http://www.tux.org/lkml/
^ permalink raw reply
* [PATCH 07/17] spi: pl022: Don't ignore power domain and amba bus at system suspend
From: Mark Brown @ 2014-02-10 12:51 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAPDyKFqNdw-6R12cUOre8UOTOnB-PpxHD5rPAMCwuS3i--Sesg@mail.gmail.com>
On Mon, Feb 10, 2014 at 01:33:50PM +0100, Ulf Hansson wrote:
> On 4 February 2014 20:16, Mark Brown <broonie@kernel.org> wrote:
> > This seems like a fairly hideous thing to be having to open code in an
> > individual driver, it all looks generic and like something that most if
...
> > Putting it in a helper would at least mean that it's easier for the
> > mechanics to be transferred to the core proper later on.
> I agree, a helper function would be nice. I have earlier sent a patch
> to the PM core, that is similar to the code above, though it was
> rejected in it's current form. Let me follow up on this again.
> At this point, would a way forward be to still go ahead with this
> patch and then convert to, when/if, the helper function from the PM
> core becomes available?
It's definitely *a* way forward, but I'm not convinced it's a good way
forward. Since it's something that I'd expect us to be doing in all
drivers we'd want to replicate it all over the place which is obviously
not good, or conversely if there are issues that prevented the code
being added to the PM core then presumably we're just adding problematic
code to the driver (you've not mentioned what the problems were with
doing this in the PM core).
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140210/caed4c27/attachment.sig>
^ permalink raw reply
* [PATCH 1/7] pinctrl: sh-pfc: r8a7790: Add QSPI pin groups
From: Laurent Pinchart @ 2014-02-10 12:48 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1392029254-15400-2-git-send-email-geert@linux-m68k.org>
Hi Geert,
Thank you for the patch.
On Monday 10 February 2014 11:47:27 Geert Uytterhoeven wrote:
> From: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
>
> A QSPI function set consists of 3 groups:
> - qspi_ctrl (2 control wires)
> - qspi_data2 (2 data wires, for Single/Dual SPI)
> - qspi_data4 (4 data wires, for Quad SPI)
>
> Signed-off-by: Geert Uytterhoeven <geert+renesas@linux-m68k.org>
> Cc: Linus Walleij <linus.walleij@linaro.org>
> Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> ---
> drivers/pinctrl/sh-pfc/pfc-r8a7790.c | 33 +++++++++++++++++++++++++++++++
> 1 file changed, 33 insertions(+)
>
> diff --git a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
> b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c index c381ae63c508..bc9ced3ccd58
> 100644
> --- a/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
> +++ b/drivers/pinctrl/sh-pfc/pfc-r8a7790.c
> @@ -2389,6 +2389,29 @@ static const unsigned int msiof3_tx_pins[] = {
> static const unsigned int msiof3_tx_mux[] = {
> MSIOF3_TXD_MARK,
> };
> +/* - QSPI -------------------------------------------------------------- */
> +static const unsigned int qspi_ctrl_pins[] = {
> + /* SPCLK, SSL */
> + RCAR_GP_PIN(1, 4), RCAR_GP_PIN(1, 9),
> +};
> +static const unsigned int qspi_ctrl_mux[] = {
> + SPCLK_MARK, SSL_MARK,
> +};
> +static const unsigned int qspi_data2_pins[] = {
> + /* MOSI_IO0, MISO_IO1 */
> + RCAR_GP_PIN(1, 5), RCAR_GP_PIN(1, 6),
> +};
> +static const unsigned int qspi_data2_mux[] = {
> + MOSI_IO0_MARK, MISO_IO1_MARK,
> +};
> +static const unsigned int qspi_data4_pins[] = {
> + /* MOSI_IO0, MISO_IO1, IO2, IO3 */
> + RCAR_GP_PIN(1, 5), RCAR_GP_PIN(1, 6), RCAR_GP_PIN(1, 7),
> + RCAR_GP_PIN(1, 8),
> +};
> +static const unsigned int qspi_data4_mux[] = {
> + MOSI_IO0_MARK, MISO_IO1_MARK, IO2_MARK, IO3_MARK,
> +};
> /* - SCIF0 ------------------------------------------------------------- */
> static const unsigned int scif0_data_pins[] = {
> /* RX, TX */
> @@ -3671,6 +3694,9 @@ static const struct sh_pfc_pin_group pinmux_groups[] =
> { SH_PFC_PIN_GROUP(msiof3_ss2),
> SH_PFC_PIN_GROUP(msiof3_rx),
> SH_PFC_PIN_GROUP(msiof3_tx),
> + SH_PFC_PIN_GROUP(qspi_ctrl),
> + SH_PFC_PIN_GROUP(qspi_data2),
> + SH_PFC_PIN_GROUP(qspi_data4),
> SH_PFC_PIN_GROUP(scif0_data),
> SH_PFC_PIN_GROUP(scif0_clk),
> SH_PFC_PIN_GROUP(scif0_ctrl),
> @@ -3970,6 +3996,12 @@ static const char * const msiof3_groups[] = {
> "msiof3_tx",
> };
>
> +static const char * const qspi_groups[] = {
> + "qspi_ctrl",
> + "qspi_data2",
> + "qspi_data4",
> +};
> +
> static const char * const scif0_groups[] = {
> "scif0_data",
> "scif0_clk",
> @@ -4212,6 +4244,7 @@ static const struct sh_pfc_function pinmux_functions[]
> = { SH_PFC_FUNCTION(msiof0),
> SH_PFC_FUNCTION(msiof1),
> SH_PFC_FUNCTION(msiof2),
> + SH_PFC_FUNCTION(qspi),
> SH_PFC_FUNCTION(msiof3),
I believe qspi comes after msiof3 :-)
Apart from that the patch looks good.
Acked-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
> SH_PFC_FUNCTION(scif0),
> SH_PFC_FUNCTION(scif1),
--
Regards,
Laurent Pinchart
^ permalink raw reply
* [PATCH 07/17] spi: pl022: Don't ignore power domain and amba bus at system suspend
From: Ulf Hansson @ 2014-02-10 12:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140204191609.GU22609@sirena.org.uk>
On 4 February 2014 20:16, Mark Brown <broonie@kernel.org> wrote:
> On Tue, Feb 04, 2014 at 04:58:48PM +0100, Ulf Hansson wrote:
>
>> @@ -2328,8 +2300,23 @@ static int pl022_suspend(struct device *dev)
>> return ret;
>> }
>>
>> - pm_runtime_get_sync(dev);
>> - pl022_suspend_resources(pl022, false);
>> + pm_runtime_disable(dev);
>> +
>> + if (!pm_runtime_status_suspended(dev)) {
>> + if (dev->pm_domain && dev->pm_domain->ops.runtime_suspend)
>> + ret = dev->pm_domain->ops.runtime_suspend(dev);
>> + else
>> + ret = dev->bus->pm->runtime_suspend(dev);
>> +
>> + if (ret) {
>> + pm_runtime_enable(dev);
>> + return ret;
>> + }
>> +
>> + pm_runtime_set_suspended(dev);
>> + }
>
> This seems like a fairly hideous thing to be having to open code in an
> individual driver, it all looks generic and like something that most if
> not all devices ought to be doing and it looks very vulnerable to being
> broken by changes in the core. At the very least I would expect this to
> be done in a helper function, though it would be even nicer if the
> driver core were figuring this stuff out for us based on the device
> level callback so that drivers didn't need to worry about being in power
> domains or manually calling bus level callbacks.
>
> Putting it in a helper would at least mean that it's easier for the
> mechanics to be transferred to the core proper later on.
I agree, a helper function would be nice. I have earlier sent a patch
to the PM core, that is similar to the code above, though it was
rejected in it's current form. Let me follow up on this again.
At this point, would a way forward be to still go ahead with this
patch and then convert to, when/if, the helper function from the PM
core becomes available?
Kind regards
Ulf Hansson
^ permalink raw reply
* [PATCH RFC v2 19/35] imx-drm: convert to componentised device support
From: Russell King @ 2014-02-10 12:30 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210122802.GS26684@n2100.arm.linux.org.uk>
Use the componentised device support for imx-drm. This requires all
the sub-components and the master device to register with the component
device support.
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/boot/dts/imx51-babbage.dts | 10 ++-
arch/arm/boot/dts/imx53-m53evk.dts | 8 ++-
arch/arm/boot/dts/imx53-mba53.dts | 6 ++
arch/arm/boot/dts/imx53-qsb.dts | 8 ++-
arch/arm/boot/dts/imx6q-sabresd.dts | 4 ++
arch/arm/boot/dts/imx6qdl-sabresd.dtsi | 6 ++
drivers/staging/imx-drm/imx-drm-core.c | 105 +++++++++++++++++++++++------
drivers/staging/imx-drm/imx-ldb.c | 40 +++++++----
drivers/staging/imx-drm/imx-tve.c | 63 ++++++++++-------
drivers/staging/imx-drm/ipuv3-crtc.c | 46 +++++++++----
drivers/staging/imx-drm/parallel-display.c | 30 +++++++--
11 files changed, 246 insertions(+), 80 deletions(-)
diff --git a/arch/arm/boot/dts/imx51-babbage.dts b/arch/arm/boot/dts/imx51-babbage.dts
index be1407cf5abd..6ff15a0eacb3 100644
--- a/arch/arm/boot/dts/imx51-babbage.dts
+++ b/arch/arm/boot/dts/imx51-babbage.dts
@@ -21,7 +21,7 @@
reg = <0x90000000 0x20000000>;
};
- display at di0 {
+ display0: display at di0 {
compatible = "fsl,imx-parallel-display";
crtcs = <&ipu 0>;
interface-pix-fmt = "rgb24";
@@ -43,7 +43,7 @@
};
};
- display at di1 {
+ display1: display at di1 {
compatible = "fsl,imx-parallel-display";
crtcs = <&ipu 1>;
interface-pix-fmt = "rgb565";
@@ -81,6 +81,12 @@
};
};
+ imx-drm {
+ compatible = "fsl,imx-drm";
+ crtcs = <&ipu 0>, <&ipu 1>;
+ connectors = <&display0>, <&display1>;
+ };
+
sound {
compatible = "fsl,imx51-babbage-sgtl5000",
"fsl,imx-audio-sgtl5000";
diff --git a/arch/arm/boot/dts/imx53-m53evk.dts b/arch/arm/boot/dts/imx53-m53evk.dts
index 7d304d02ed38..ee6107b6484c 100644
--- a/arch/arm/boot/dts/imx53-m53evk.dts
+++ b/arch/arm/boot/dts/imx53-m53evk.dts
@@ -21,7 +21,7 @@
};
soc {
- display at di1 {
+ display1: display at di1 {
compatible = "fsl,imx-parallel-display";
crtcs = <&ipu 1>;
interface-pix-fmt = "bgr666";
@@ -53,6 +53,12 @@
default-brightness-level = <6>;
};
+ imx-drm {
+ compatible = "fsl,imx-drm";
+ crtcs = <&ipu 1>;
+ connectors = <&display1>;
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/imx53-mba53.dts b/arch/arm/boot/dts/imx53-mba53.dts
index a63090267941..9b6e76980a74 100644
--- a/arch/arm/boot/dts/imx53-mba53.dts
+++ b/arch/arm/boot/dts/imx53-mba53.dts
@@ -43,6 +43,12 @@
status = "disabled";
};
+ imx-drm {
+ compatible = "fsl,imx-drm";
+ crtcs = <&ipu 1>;
+ connectors = <&disp1>, <&tve>;
+ };
+
reg_3p2v: 3p2v {
compatible = "regulator-fixed";
regulator-name = "3P2V";
diff --git a/arch/arm/boot/dts/imx53-qsb.dts b/arch/arm/boot/dts/imx53-qsb.dts
index 91a5935a4aac..3cb4f7791a91 100644
--- a/arch/arm/boot/dts/imx53-qsb.dts
+++ b/arch/arm/boot/dts/imx53-qsb.dts
@@ -21,7 +21,7 @@
reg = <0x70000000 0x40000000>;
};
- display at di0 {
+ display0: display at di0 {
compatible = "fsl,imx-parallel-display";
crtcs = <&ipu 0>;
interface-pix-fmt = "rgb565";
@@ -72,6 +72,12 @@
};
};
+ imx-drm {
+ compatible = "fsl,imx-drm";
+ crtcs = <&ipu 0>;
+ connectors = <&display0>;
+ };
+
leds {
compatible = "gpio-leds";
pinctrl-names = "default";
diff --git a/arch/arm/boot/dts/imx6q-sabresd.dts b/arch/arm/boot/dts/imx6q-sabresd.dts
index 9cbdfe7a0931..66f220a82e45 100644
--- a/arch/arm/boot/dts/imx6q-sabresd.dts
+++ b/arch/arm/boot/dts/imx6q-sabresd.dts
@@ -20,6 +20,10 @@
compatible = "fsl,imx6q-sabresd", "fsl,imx6q";
};
+&imx_drm {
+ crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
+};
+
&sata {
status = "okay";
};
diff --git a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
index e75e11b36dff..dfca3e001398 100644
--- a/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
+++ b/arch/arm/boot/dts/imx6qdl-sabresd.dtsi
@@ -62,6 +62,12 @@
};
};
+ imx_drm: imx-drm {
+ compatible = "fsl,imx-drm";
+ crtcs = <&ipu1 0>, <&ipu1 1>;
+ connectors = <&ldb>;
+ };
+
sound {
compatible = "fsl,imx6q-sabresd-wm8962",
"fsl,imx-audio-wm8962";
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index d9786eca3a36..82b0337096b0 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -13,7 +13,7 @@
* GNU General Public License for more details.
*
*/
-
+#include <linux/component.h>
#include <linux/device.h>
#include <linux/platform_device.h>
#include <drm/drmP.h>
@@ -90,6 +90,8 @@ static int imx_drm_driver_unload(struct drm_device *drm)
{
struct imx_drm_device *imxdrm = drm->dev_private;
+ component_unbind_all(drm->dev, drm);
+
imx_drm_device_put();
drm_vblank_cleanup(drm);
@@ -371,11 +373,8 @@ static void imx_drm_connector_unregister(
}
/*
- * Called by the CRTC driver when all CRTCs are registered. This
- * puts all the pieces together and initializes the driver.
- * Once this is called no more CRTCs can be registered since
- * the drm core has hardcoded the number of crtcs in several
- * places.
+ * Main DRM initialisation. This binds, initialises and registers
+ * with DRM the subcomponents of the driver.
*/
static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
{
@@ -428,8 +427,15 @@ static int imx_drm_driver_load(struct drm_device *drm, unsigned long flags)
platform_set_drvdata(drm->platformdev, drm);
mutex_unlock(&imxdrm->mutex);
+
+ /* Now try and bind all our sub-components */
+ ret = component_bind_all(drm->dev, drm);
+ if (ret)
+ goto err_relock;
return 0;
+err_relock:
+ mutex_lock(&imxdrm->mutex);
err_vblank:
drm_vblank_cleanup(drm);
err_kms:
@@ -809,6 +815,70 @@ static struct drm_driver imx_drm_driver = {
.patchlevel = 0,
};
+static int compare_parent_of(struct device *dev, void *data)
+{
+ struct of_phandle_args *args = data;
+ return dev->parent && dev->parent->of_node == args->np;
+}
+
+static int compare_of(struct device *dev, void *data)
+{
+ return dev->of_node == data;
+}
+
+static int imx_drm_add_components(struct device *master, struct master *m)
+{
+ struct device_node *np = master->of_node;
+ unsigned i;
+ int ret;
+
+ for (i = 0; ; i++) {
+ struct of_phandle_args args;
+
+ ret = of_parse_phandle_with_fixed_args(np, "crtcs", 1,
+ i, &args);
+ if (ret)
+ break;
+
+ ret = component_master_add_child(m, compare_parent_of, &args);
+ of_node_put(args.np);
+
+ if (ret)
+ return ret;
+ }
+
+ for (i = 0; ; i++) {
+ struct device_node *node;
+
+ node = of_parse_phandle(np, "connectors", i);
+ if (!node)
+ break;
+
+ ret = component_master_add_child(m, compare_of, node);
+ of_node_put(node);
+
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
+static int imx_drm_bind(struct device *dev)
+{
+ return drm_platform_init(&imx_drm_driver, to_platform_device(dev));
+}
+
+static void imx_drm_unbind(struct device *dev)
+{
+ drm_put_dev(dev_get_drvdata(dev));
+}
+
+static const struct component_master_ops imx_drm_ops = {
+ .add_components = imx_drm_add_components,
+ .bind = imx_drm_bind,
+ .unbind = imx_drm_unbind,
+};
+
static int imx_drm_platform_probe(struct platform_device *pdev)
{
int ret;
@@ -819,27 +889,31 @@ static int imx_drm_platform_probe(struct platform_device *pdev)
imx_drm_device->dev = &pdev->dev;
- return drm_platform_init(&imx_drm_driver, pdev);
+ return component_master_add(&pdev->dev, &imx_drm_ops);
}
static int imx_drm_platform_remove(struct platform_device *pdev)
{
- drm_put_dev(platform_get_drvdata(pdev));
-
+ component_master_del(&pdev->dev, &imx_drm_ops);
return 0;
}
+static const struct of_device_id imx_drm_dt_ids[] = {
+ { .compatible = "fsl,imx-drm", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, imx_drm_dt_ids);
+
static struct platform_driver imx_drm_pdrv = {
.probe = imx_drm_platform_probe,
.remove = imx_drm_platform_remove,
.driver = {
.owner = THIS_MODULE,
.name = "imx-drm",
+ .of_match_table = imx_drm_dt_ids,
},
};
-static struct platform_device *imx_drm_pdev;
-
static int __init imx_drm_init(void)
{
int ret;
@@ -852,12 +926,6 @@ static int __init imx_drm_init(void)
INIT_LIST_HEAD(&imx_drm_device->connector_list);
INIT_LIST_HEAD(&imx_drm_device->encoder_list);
- imx_drm_pdev = platform_device_register_simple("imx-drm", -1, NULL, 0);
- if (IS_ERR(imx_drm_pdev)) {
- ret = PTR_ERR(imx_drm_pdev);
- goto err_pdev;
- }
-
ret = platform_driver_register(&imx_drm_pdrv);
if (ret)
goto err_pdrv;
@@ -865,8 +933,6 @@ static int __init imx_drm_init(void)
return 0;
err_pdrv:
- platform_device_unregister(imx_drm_pdev);
-err_pdev:
kfree(imx_drm_device);
return ret;
@@ -874,7 +940,6 @@ static int __init imx_drm_init(void)
static void __exit imx_drm_exit(void)
{
- platform_device_unregister(imx_drm_pdev);
platform_driver_unregister(&imx_drm_pdrv);
kfree(imx_drm_device);
diff --git a/drivers/staging/imx-drm/imx-ldb.c b/drivers/staging/imx-drm/imx-ldb.c
index dd29a4aad376..d00f93f3440d 100644
--- a/drivers/staging/imx-drm/imx-ldb.c
+++ b/drivers/staging/imx-drm/imx-ldb.c
@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/clk.h>
+#include <linux/component.h>
#include <drm/drmP.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_crtc_helper.h>
@@ -450,11 +451,11 @@ static const struct of_device_id imx_ldb_dt_ids[] = {
};
MODULE_DEVICE_TABLE(of, imx_ldb_dt_ids);
-static int imx_ldb_probe(struct platform_device *pdev)
+static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
{
- struct device_node *np = pdev->dev.of_node;
+ struct device_node *np = dev->of_node;
const struct of_device_id *of_id =
- of_match_device(imx_ldb_dt_ids, &pdev->dev);
+ of_match_device(imx_ldb_dt_ids, dev);
struct device_node *child;
const u8 *edidp;
struct imx_ldb *imx_ldb;
@@ -464,17 +465,17 @@ static int imx_ldb_probe(struct platform_device *pdev)
int ret;
int i;
- imx_ldb = devm_kzalloc(&pdev->dev, sizeof(*imx_ldb), GFP_KERNEL);
+ imx_ldb = devm_kzalloc(dev, sizeof(*imx_ldb), GFP_KERNEL);
if (!imx_ldb)
return -ENOMEM;
imx_ldb->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
if (IS_ERR(imx_ldb->regmap)) {
- dev_err(&pdev->dev, "failed to get parent regmap\n");
+ dev_err(dev, "failed to get parent regmap\n");
return PTR_ERR(imx_ldb->regmap);
}
- imx_ldb->dev = &pdev->dev;
+ imx_ldb->dev = dev;
if (of_id)
imx_ldb->lvds_mux = of_id->data;
@@ -512,7 +513,7 @@ static int imx_ldb_probe(struct platform_device *pdev)
return -EINVAL;
if (dual && i > 0) {
- dev_warn(&pdev->dev, "dual-channel mode, ignoring second output\n");
+ dev_warn(dev, "dual-channel mode, ignoring second output\n");
continue;
}
@@ -551,7 +552,7 @@ static int imx_ldb_probe(struct platform_device *pdev)
break;
case LVDS_BIT_MAP_JEIDA:
if (datawidth == 18) {
- dev_err(&pdev->dev, "JEIDA standard only supported in 24 bit\n");
+ dev_err(dev, "JEIDA standard only supported in 24 bit\n");
return -EINVAL;
}
if (i == 0 || dual)
@@ -560,7 +561,7 @@ static int imx_ldb_probe(struct platform_device *pdev)
imx_ldb->ldb_ctrl |= LDB_DATA_WIDTH_CH1_24 | LDB_BIT_MAP_CH1_JEIDA;
break;
default:
- dev_err(&pdev->dev, "data mapping not specified or invalid\n");
+ dev_err(dev, "data mapping not specified or invalid\n");
return -EINVAL;
}
@@ -571,14 +572,15 @@ static int imx_ldb_probe(struct platform_device *pdev)
imx_drm_encoder_add_possible_crtcs(channel->imx_drm_encoder, child);
}
- platform_set_drvdata(pdev, imx_ldb);
+ dev_set_drvdata(dev, imx_ldb);
return 0;
}
-static int imx_ldb_remove(struct platform_device *pdev)
+static void imx_ldb_unbind(struct device *dev, struct device *master,
+ void *data)
{
- struct imx_ldb *imx_ldb = platform_get_drvdata(pdev);
+ struct imx_ldb *imx_ldb = dev_get_drvdata(dev);
int i;
for (i = 0; i < 2; i++) {
@@ -591,7 +593,21 @@ static int imx_ldb_remove(struct platform_device *pdev)
imx_drm_remove_connector(channel->imx_drm_connector);
imx_drm_remove_encoder(channel->imx_drm_encoder);
}
+}
+static const struct component_ops imx_ldb_ops = {
+ .bind = imx_ldb_bind,
+ .unbind = imx_ldb_unbind,
+};
+
+static int imx_ldb_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &imx_ldb_ops);
+}
+
+static int imx_ldb_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &imx_ldb_ops);
return 0;
}
diff --git a/drivers/staging/imx-drm/imx-tve.c b/drivers/staging/imx-drm/imx-tve.c
index 77131e5770f3..ad840d78a09a 100644
--- a/drivers/staging/imx-drm/imx-tve.c
+++ b/drivers/staging/imx-drm/imx-tve.c
@@ -20,6 +20,7 @@
#include <linux/clk.h>
#include <linux/clk-provider.h>
+#include <linux/component.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
@@ -583,9 +584,10 @@ static const int of_get_tve_mode(struct device_node *np)
return -EINVAL;
}
-static int imx_tve_probe(struct platform_device *pdev)
+static int imx_tve_bind(struct device *dev, struct device *master, void *data)
{
- struct device_node *np = pdev->dev.of_node;
+ struct platform_device *pdev = to_platform_device(dev);
+ struct device_node *np = dev->of_node;
struct device_node *ddc_node;
struct imx_tve *tve;
struct resource *res;
@@ -594,11 +596,11 @@ static int imx_tve_probe(struct platform_device *pdev)
int irq;
int ret;
- tve = devm_kzalloc(&pdev->dev, sizeof(*tve), GFP_KERNEL);
+ tve = devm_kzalloc(dev, sizeof(*tve), GFP_KERNEL);
if (!tve)
return -ENOMEM;
- tve->dev = &pdev->dev;
+ tve->dev = dev;
spin_lock_init(&tve->lock);
ddc_node = of_parse_phandle(np, "ddc", 0);
@@ -609,7 +611,7 @@ static int imx_tve_probe(struct platform_device *pdev)
tve->mode = of_get_tve_mode(np);
if (tve->mode != TVE_MODE_VGA) {
- dev_err(&pdev->dev, "only VGA mode supported, currently\n");
+ dev_err(dev, "only VGA mode supported, currently\n");
return -EINVAL;
}
@@ -618,7 +620,7 @@ static int imx_tve_probe(struct platform_device *pdev)
&tve->hsync_pin);
if (ret < 0) {
- dev_err(&pdev->dev, "failed to get vsync pin\n");
+ dev_err(dev, "failed to get vsync pin\n");
return ret;
}
@@ -626,40 +628,40 @@ static int imx_tve_probe(struct platform_device *pdev)
&tve->vsync_pin);
if (ret < 0) {
- dev_err(&pdev->dev, "failed to get vsync pin\n");
+ dev_err(dev, "failed to get vsync pin\n");
return ret;
}
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- base = devm_ioremap_resource(&pdev->dev, res);
+ base = devm_ioremap_resource(dev, res);
if (IS_ERR(base))
return PTR_ERR(base);
tve_regmap_config.lock_arg = tve;
- tve->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "tve", base,
+ tve->regmap = devm_regmap_init_mmio_clk(dev, "tve", base,
&tve_regmap_config);
if (IS_ERR(tve->regmap)) {
- dev_err(&pdev->dev, "failed to init regmap: %ld\n",
+ dev_err(dev, "failed to init regmap: %ld\n",
PTR_ERR(tve->regmap));
return PTR_ERR(tve->regmap);
}
irq = platform_get_irq(pdev, 0);
if (irq < 0) {
- dev_err(&pdev->dev, "failed to get irq\n");
+ dev_err(dev, "failed to get irq\n");
return irq;
}
- ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+ ret = devm_request_threaded_irq(dev, irq, NULL,
imx_tve_irq_handler, IRQF_ONESHOT,
"imx-tve", tve);
if (ret < 0) {
- dev_err(&pdev->dev, "failed to request irq: %d\n", ret);
+ dev_err(dev, "failed to request irq: %d\n", ret);
return ret;
}
- tve->dac_reg = devm_regulator_get(&pdev->dev, "dac");
+ tve->dac_reg = devm_regulator_get(dev, "dac");
if (!IS_ERR(tve->dac_reg)) {
regulator_set_voltage(tve->dac_reg, 2750000, 2750000);
ret = regulator_enable(tve->dac_reg);
@@ -667,17 +669,17 @@ static int imx_tve_probe(struct platform_device *pdev)
return ret;
}
- tve->clk = devm_clk_get(&pdev->dev, "tve");
+ tve->clk = devm_clk_get(dev, "tve");
if (IS_ERR(tve->clk)) {
- dev_err(&pdev->dev, "failed to get high speed tve clock: %ld\n",
+ dev_err(dev, "failed to get high speed tve clock: %ld\n",
PTR_ERR(tve->clk));
return PTR_ERR(tve->clk);
}
/* this is the IPU DI clock input selector, can be parented to tve_di */
- tve->di_sel_clk = devm_clk_get(&pdev->dev, "di_sel");
+ tve->di_sel_clk = devm_clk_get(dev, "di_sel");
if (IS_ERR(tve->di_sel_clk)) {
- dev_err(&pdev->dev, "failed to get ipu di mux clock: %ld\n",
+ dev_err(dev, "failed to get ipu di mux clock: %ld\n",
PTR_ERR(tve->di_sel_clk));
return PTR_ERR(tve->di_sel_clk);
}
@@ -688,11 +690,11 @@ static int imx_tve_probe(struct platform_device *pdev)
ret = regmap_read(tve->regmap, TVE_COM_CONF_REG, &val);
if (ret < 0) {
- dev_err(&pdev->dev, "failed to read configuration register: %d\n", ret);
+ dev_err(dev, "failed to read configuration register: %d\n", ret);
return ret;
}
if (val != 0x00100000) {
- dev_err(&pdev->dev, "configuration register default value indicates this is not a TVEv2\n");
+ dev_err(dev, "configuration register default value indicates this is not a TVEv2\n");
return -ENODEV;
}
@@ -705,14 +707,15 @@ static int imx_tve_probe(struct platform_device *pdev)
ret = imx_drm_encoder_add_possible_crtcs(tve->imx_drm_encoder, np);
- platform_set_drvdata(pdev, tve);
+ dev_set_drvdata(dev, tve);
return 0;
}
-static int imx_tve_remove(struct platform_device *pdev)
+static void imx_tve_unbind(struct device *dev, struct device *master,
+ void *data)
{
- struct imx_tve *tve = platform_get_drvdata(pdev);
+ struct imx_tve *tve = dev_get_drvdata(dev);
struct drm_connector *connector = &tve->connector;
struct drm_encoder *encoder = &tve->encoder;
@@ -723,7 +726,21 @@ static int imx_tve_remove(struct platform_device *pdev)
if (!IS_ERR(tve->dac_reg))
regulator_disable(tve->dac_reg);
+}
+static const struct component_ops imx_tve_ops = {
+ .bind = imx_tve_bind,
+ .unbind = imx_tve_unbind,
+};
+
+static int imx_tve_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &imx_tve_ops);
+}
+
+static int imx_tve_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &imx_tve_ops);
return 0;
}
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
index 08e0a3b29174..d779ad2d1f4e 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -17,6 +17,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*/
+#include <linux/component.h>
#include <linux/module.h>
#include <linux/export.h>
#include <linux/device.h>
@@ -400,43 +401,60 @@ static int ipu_crtc_init(struct ipu_crtc *ipu_crtc,
return ret;
}
-static int ipu_drm_probe(struct platform_device *pdev)
+static int ipu_drm_bind(struct device *dev, struct device *master, void *data)
{
- struct ipu_client_platformdata *pdata = pdev->dev.platform_data;
+ struct ipu_client_platformdata *pdata = dev->platform_data;
struct ipu_crtc *ipu_crtc;
int ret;
- if (!pdata)
- return -EINVAL;
-
- ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
- if (ret)
- return ret;
-
- ipu_crtc = devm_kzalloc(&pdev->dev, sizeof(*ipu_crtc), GFP_KERNEL);
+ ipu_crtc = devm_kzalloc(dev, sizeof(*ipu_crtc), GFP_KERNEL);
if (!ipu_crtc)
return -ENOMEM;
- ipu_crtc->dev = &pdev->dev;
+ ipu_crtc->dev = dev;
ret = ipu_crtc_init(ipu_crtc, pdata);
if (ret)
return ret;
- platform_set_drvdata(pdev, ipu_crtc);
+ dev_set_drvdata(dev, ipu_crtc);
return 0;
}
-static int ipu_drm_remove(struct platform_device *pdev)
+static void ipu_drm_unbind(struct device *dev, struct device *master,
+ void *data)
{
- struct ipu_crtc *ipu_crtc = platform_get_drvdata(pdev);
+ struct ipu_crtc *ipu_crtc = dev_get_drvdata(dev);
imx_drm_remove_crtc(ipu_crtc->imx_crtc);
ipu_plane_put_resources(ipu_crtc->plane[0]);
ipu_put_resources(ipu_crtc);
+}
+
+static const struct component_ops ipu_crtc_ops = {
+ .bind = ipu_drm_bind,
+ .unbind = ipu_drm_unbind,
+};
+static int ipu_drm_probe(struct platform_device *pdev)
+{
+ int ret;
+
+ if (!pdev->dev.platform_data)
+ return -EINVAL;
+
+ ret = dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(32));
+ if (ret)
+ return ret;
+
+ return component_add(&pdev->dev, &ipu_crtc_ops);
+}
+
+static int ipu_drm_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &ipu_crtc_ops);
return 0;
}
diff --git a/drivers/staging/imx-drm/parallel-display.c b/drivers/staging/imx-drm/parallel-display.c
index 12bcf4f58bdf..4019cae35ff9 100644
--- a/drivers/staging/imx-drm/parallel-display.c
+++ b/drivers/staging/imx-drm/parallel-display.c
@@ -18,6 +18,7 @@
* MA 02110-1301, USA.
*/
+#include <linux/component.h>
#include <linux/module.h>
#include <drm/drmP.h>
#include <drm/drm_fb_helper.h>
@@ -192,15 +193,15 @@ static int imx_pd_register(struct imx_parallel_display *imxpd)
return 0;
}
-static int imx_pd_probe(struct platform_device *pdev)
+static int imx_pd_bind(struct device *dev, struct device *master, void *data)
{
- struct device_node *np = pdev->dev.of_node;
+ struct device_node *np = dev->of_node;
const u8 *edidp;
struct imx_parallel_display *imxpd;
int ret;
const char *fmt;
- imxpd = devm_kzalloc(&pdev->dev, sizeof(*imxpd), GFP_KERNEL);
+ imxpd = devm_kzalloc(dev, sizeof(*imxpd), GFP_KERNEL);
if (!imxpd)
return -ENOMEM;
@@ -218,7 +219,7 @@ static int imx_pd_probe(struct platform_device *pdev)
imxpd->interface_pix_fmt = V4L2_PIX_FMT_BGR666;
}
- imxpd->dev = &pdev->dev;
+ imxpd->dev = dev;
ret = imx_pd_register(imxpd);
if (ret)
@@ -226,14 +227,15 @@ static int imx_pd_probe(struct platform_device *pdev)
ret = imx_drm_encoder_add_possible_crtcs(imxpd->imx_drm_encoder, np);
- platform_set_drvdata(pdev, imxpd);
+ dev_set_drvdata(dev, imxpd);
return 0;
}
-static int imx_pd_remove(struct platform_device *pdev)
+static void imx_pd_unbind(struct device *dev, struct device *master,
+ void *data)
{
- struct imx_parallel_display *imxpd = platform_get_drvdata(pdev);
+ struct imx_parallel_display *imxpd = dev_get_drvdata(dev);
struct drm_connector *connector = &imxpd->connector;
struct drm_encoder *encoder = &imxpd->encoder;
@@ -241,7 +243,21 @@ static int imx_pd_remove(struct platform_device *pdev)
imx_drm_remove_connector(imxpd->imx_drm_connector);
imx_drm_remove_encoder(imxpd->imx_drm_encoder);
+}
+static const struct component_ops imx_pd_ops = {
+ .bind = imx_pd_bind,
+ .unbind = imx_pd_unbind,
+};
+
+static int imx_pd_probe(struct platform_device *pdev)
+{
+ return component_add(&pdev->dev, &imx_pd_ops);
+}
+
+static int imx_pd_remove(struct platform_device *pdev)
+{
+ component_del(&pdev->dev, &imx_pd_ops);
return 0;
}
--
1.8.3.1
^ permalink raw reply related
* [PATCH RFC v2 14/35] imx-drm: update and fix imx6 DT descriptions for v3 HDMI driver
From: Russell King @ 2014-02-10 12:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210122802.GS26684@n2100.arm.linux.org.uk>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/boot/dts/imx6dl.dtsi | 3 ++-
arch/arm/boot/dts/imx6q.dtsi | 1 +
arch/arm/boot/dts/imx6qdl.dtsi | 1 -
3 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index 65e54b4529c5..6dc397022214 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -90,5 +90,6 @@
};
&hdmi {
+ compatible = "fsl,imx6dl-hdmi";
crtcs = <&ipu1 0>, <&ipu1 1>;
-}
+};
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index d2467f532de6..187fe33ba515 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -161,5 +161,6 @@
};
&hdmi {
+ compatible = "fsl,imx6q-hdmi";
crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
};
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index 400bbc624f25..930ebe0c2937 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -1369,7 +1369,6 @@
};
hdmi: hdmi at 0120000 {
- compatible = "fsl,imx6q-hdmi";
reg = <0x00120000 0x9000>;
interrupts = <0 115 0x04>;
gpr = <&gpr>;
--
1.8.3.1
^ permalink raw reply related
* [PATCH RFC v2 13/35] imx-drm: add imx6 DT configuration for HDMI
From: Russell King @ 2014-02-10 12:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140210122802.GS26684@n2100.arm.linux.org.uk>
Extracted from another patch by Fabio Estevam, this adds the DT
configuration for HDMI output on the IMX6 SoCs
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
---
arch/arm/boot/dts/imx6dl.dtsi | 4 ++++
arch/arm/boot/dts/imx6q.dtsi | 4 ++++
arch/arm/boot/dts/imx6qdl.dtsi | 10 ++++++++++
3 files changed, 18 insertions(+)
diff --git a/arch/arm/boot/dts/imx6dl.dtsi b/arch/arm/boot/dts/imx6dl.dtsi
index 9e8ae118fdd4..65e54b4529c5 100644
--- a/arch/arm/boot/dts/imx6dl.dtsi
+++ b/arch/arm/boot/dts/imx6dl.dtsi
@@ -88,3 +88,7 @@
crtcs = <&ipu1 0>, <&ipu1 1>;
};
};
+
+&hdmi {
+ crtcs = <&ipu1 0>, <&ipu1 1>;
+}
diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index f024ef28b34b..d2467f532de6 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -159,3 +159,7 @@
crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
};
};
+
+&hdmi {
+ crtcs = <&ipu1 0>, <&ipu1 1>, <&ipu2 0>, <&ipu2 1>;
+};
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index fb28b2ecb1db..400bbc624f25 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -1368,6 +1368,16 @@
};
};
+ hdmi: hdmi at 0120000 {
+ compatible = "fsl,imx6q-hdmi";
+ reg = <0x00120000 0x9000>;
+ interrupts = <0 115 0x04>;
+ gpr = <&gpr>;
+ clocks = <&clks 123>, <&clks 124>;
+ clock-names = "iahb", "isfr";
+ status = "disabled";
+ };
+
dcic1: dcic at 020e4000 {
reg = <0x020e4000 0x4000>;
interrupts = <0 124 0x04>;
--
1.8.3.1
^ permalink raw reply related
* [PATCH RFC v2 00/35] Second preview of imx-drm cleanup series
From: Russell King - ARM Linux @ 2014-02-10 12:28 UTC (permalink / raw)
To: linux-arm-kernel
This is the latest revision of my series cleaning up imx-drm and
hopefully getting it ready to be moved out of drivers/staging.
This series is updated to v3.14-rc2.
Since the last round of patches were posted, the component support
has been merged into mainline, and thus dropped from this series.
Greg has taken the first three patches and merged them into his
linux-next tree - however, I include them here for completness.
Most of the comments from last time still apply, and I'll look at
incorporating some of the other patches that were posted in the
coming week.
If I can have some acks for this, I'll start sending some of it to
Greg - I'd like to at least get the five or six initial imx-hdmi
patches to Greg and queued up for the next merge window sooner
rather than later, preferably getting most of this ready for that
window too.
arch/arm/boot/dts/imx51-babbage.dts | 10 +-
arch/arm/boot/dts/imx53-m53evk.dts | 8 +-
arch/arm/boot/dts/imx53-mba53.dts | 6 +
arch/arm/boot/dts/imx53-qsb.dts | 8 +-
arch/arm/boot/dts/imx6dl.dtsi | 5 +
arch/arm/boot/dts/imx6q-sabresd.dts | 4 +
arch/arm/boot/dts/imx6q.dtsi | 5 +
arch/arm/boot/dts/imx6qdl-sabresd.dtsi | 6 +
arch/arm/boot/dts/imx6qdl.dtsi | 9 +
drivers/staging/imx-drm/Makefile | 3 +-
drivers/staging/imx-drm/imx-drm-core.c | 831 ++++++++++-------------------
drivers/staging/imx-drm/imx-drm.h | 39 +-
drivers/staging/imx-drm/imx-fb.c | 47 --
drivers/staging/imx-drm/imx-fbdev.c | 74 ---
drivers/staging/imx-drm/imx-hdmi.c | 680 +++++++++--------------
drivers/staging/imx-drm/imx-ldb.c | 125 ++---
drivers/staging/imx-drm/imx-tve.c | 134 +++--
drivers/staging/imx-drm/ipu-v3/ipu-di.c | 317 +++++------
drivers/staging/imx-drm/ipuv3-crtc.c | 56 +-
drivers/staging/imx-drm/parallel-display.c | 100 ++--
20 files changed, 934 insertions(+), 1533 deletions(-)
^ permalink raw reply
* [PATCH v6 05/19] watchdog: orion: Make sure the watchdog is initially stopped
From: Ezequiel Garcia @ 2014-02-10 12:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20140207174314.GB16263@obsidianresearch.com>
On Fri, Feb 07, 2014 at 10:43:14AM -0700, Jason Gunthorpe wrote:
> On Fri, Feb 07, 2014 at 07:40:45AM -0300, Ezequiel Garcia wrote:
>
> > Well, this is related to the discussion about the bootloader not
> > reseting the watchdog properly, provoking spurious watchdog triggering.
> >
> > Jason Gunthorpe explained [1] that we needed a particular sequence:
> >
> > 1. Disable WDT
> > 2. Clear bridge
> > 3. Enable WDT
> >
> > We added the irq handling to satisfy (2), and the watchdog stop for (1).
>
> The issue here is the driver configures two 'machine kill' elements:
> the PANIC IRQ and the RstOut setup.
>
> Before configuring either of those the driver needs to ensure that any
> old watchdog events are cleared out of the HW. We must not get a
> spurious event.
>
> I agree not disabling an already functional and properly configured
> counter from the bootloader is desirable.
>
> So lets break it down a bit..
>
> 1) The IRQ:
> It looks like the cause bit latches high on watchdog timer
> expiration but has no side effect unless it is unmasked.
>
> The new IRQ flow code ensures the bit is cleared during request_irq
> so no old events can trigger the IRQ. Thus it is solved now.
>
Agreed.
> 3) The timer itself:
> The WDT is just a general timer with an optional hookup to the
> rst control. If it is harmlessly counting but not resetting we need
> to stop that before enabling rst out.
>
Actually, the current flow is to:
1. Disable rst out and then disable the counter, in probe().
2. Enable the counter, and then enable rst out, in start().
> So, how about this for psuedo-code in probe:
>
> if (readl(RSTOUTn) & WDRstOutEn)
> {
> /* Watchdog is configured and may be down counting,
> don't touch it */
> request_irq(..);
> }
> else
> {
> /* Watchdog is not configured, fully disable the timer
> and configure for watchdog operation. */
> disable_watchdog();
> request_irq();
> writel(RSTOUTn), .. WDRstOutEn);
> }
>
Sounds good, although it seems to me it's actually simpler:
/* Let's make sure the watchdog is fully stopped, unless
* it's explicitly enabled and running
*/
if ( !(wdt_rst_out_en && wdt_timer_enabled) ) {
watchdog_stop();
}
--
Ezequiel Garc?a, Free Electrons
Embedded Linux, Kernel and Android Engineering
http://free-electrons.com
^ permalink raw reply
* [PATCH] ARM: shmobile: r8a7790: Correct SYS DMAC clock defines
From: Ben Dooks @ 2014-02-10 12:22 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391646301-20197-1-git-send-email-horms+renesas@verge.net.au>
On 06/02/14 00:25, Simon Horman wrote:
> This brings the implementation into line with the documentation.
>
> This problem was introduced when SYS DMAC clock defines were added by
> ac991dce6498b5fc ("ARM: shmobile: r8a7790: Add clock index macros for DT
> sources") in v3.13-rc2. I do not believe this results in any problems as
> these defines do not appear to be used anywhere yet.
>
> Cc: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
> Signed-off-by: Simon Horman <horms+renesas@verge.net.au>
Reviewed-by: Ben Dooks <ben.dooks@codethink.co.uk>
I agree, although I have yet to get the DMA working.
--
Ben Dooks http://www.codethink.co.uk/
Senior Engineer Codethink - Providing Genius
^ permalink raw reply
* [PATCH] video: imxfb: Use regulator API with LCD class for powering
From: Tomi Valkeinen @ 2014-02-10 12:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1392034587.333931582@f419.i.mail.ru>
On 10/02/14 14:16, Alexander Shiyan wrote:
> ???????????, 10 ??????? 2014, 14:05 +02:00 ?? Tomi Valkeinen <tomi.valkeinen@ti.com>:
>> On 21/12/13 13:08, Alexander Shiyan wrote:
>>> This patch replaces custom lcd_power() callback with
>>> regulator API over LCD class.
>>>
>>> Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
>>> ---
>>> .../devicetree/bindings/video/fsl,imx-fb.txt | 1 +
>>> arch/arm/mach-imx/mach-mx27ads.c | 55 +++++++++++++++--
>>> drivers/video/imxfb.c | 71
>> +++++++++++++++++++---
>>> include/linux/platform_data/video-imxfb.h | 1 -
>>> 4 files changed, 114 insertions(+), 14 deletions(-)
>>>
>>> diff --git a/Documentation/devicetree/bindings/video/fsl,imx-fb.txt
>> b/Documentation/devicetree/bindings/video/fsl,imx-fb.txt
>>> index 46da08d..e6b1ee9 100644
>>> --- a/Documentation/devicetree/bindings/video/fsl,imx-fb.txt
>>> +++ b/Documentation/devicetree/bindings/video/fsl,imx-fb.txt
>>> @@ -15,6 +15,7 @@ Required nodes:
>>> - fsl,pcr: LCDC PCR value
>>>
>>> Optional properties:
>>> +- lcd-supply: Regulator for LCD supply voltage.
>>> - fsl,dmacr: DMA Control Register value. This is optional. By default, the
>>> register is not modified as recommended by the datasheet.
>>> - fsl,lscr1: LCDC Sharp Configuration Register value.
>>> diff --git a/arch/arm/mach-imx/mach-mx27ads.c
> ...
>>> +static void __init mx27ads_regulator_init(void)
>>> +{
>>> + struct gpio_chip *vchip;
>>> +
>>> + vchip = kzalloc(sizeof(*vchip), GFP_KERNEL);
>>> + vchip->owner = THIS_MODULE;
>>> + vchip->label = "LCD";
>>> + vchip->base = MX27ADS_LCD_GPIO;
>>> + vchip->ngpio = 1;
>>> + vchip->direction_output = vgpio_dir_out;
>>> + vchip->set = vgpio_set;
>>> + gpiochip_add(vchip);
>>> +
>>> + platform_device_register_data(&platform_bus, "reg-fixed-voltage",
>>> + PLATFORM_DEVID_AUTO,
>>> + &mx27ads_lcd_regulator_pdata,
>>> + sizeof(mx27ads_lcd_regulator_pdata));
>>> +}
>>> +
>>
>> Hmm, isn't all this something that should be in the board's .dts?
>
> There are no DT support for this board yet.
Oh, ok. You added 'lcd-supply' to devtree binding documentation, so I
presumed DT is being used.
The drivers/video side looks fine. I can either merge this via fbdev
tree if I get an ack from arch/arm/mach-imx/mach-mx27ads.c's maintainer,
or this can go via imx tree with my ack.
Tomi
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 901 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140210/dc5d854f/attachment-0001.sig>
^ permalink raw reply
* [PATCHv5] omap3: Add basic support for 720MHz part
From: Laurent Pinchart @ 2014-02-10 12:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAGo_u6r4Q0QyaZ9jPyiBNT-xBqxWA1MpESiyG7quzUn5kkoLhA@mail.gmail.com>
Hi Nishanth,
On Friday 07 February 2014 07:51:00 Nishanth Menon wrote:
> On Thu, Feb 6, 2014 at 1:26 PM, Laurent Pinchart wrote:
> > On Friday 22 June 2012 11:33:51 Laurent Pinchart wrote:
> >> On Thursday 10 February 2011 08:45:00 Kevin Hilman wrote:
> >> > Sanjeev Premi <premi@ti.com> writes:
> >> > > This patch adds support for speed enhanced variant of OMAP35x
> >> > > processors. These parts allow ARM and IVA running at 720MHz
> >> > > and 520MHz respectively.
> >> > >
> >> > > These parts can be detected at runtime by reading contents of
> >> > > PRODID.SKUID[3:0] at 0x4830A20C [1].
> >> > >
> >> > > This patch specifically does following:
> >> > > * Add new OPP to omap34xx_opp_def_list[] - disabled by default.
> >> > > * Detect devices capable of running at new OPP.
> >> > > * Enable new OPP only if device supports it.
> >> > > * Check for presence of IVA before attempting to enable the
> >> > > corresponding OPP.
> >> > >
> >> > > [1] http://focus.ti.com/lit/ug/spruff1d/spruff1d.pdf
> >> > >
> >> > > It appears from discussions (on this patch) that a variant of
> >> > > OMAP3430 supports this OPP but lacks runtime detection. This
> >> > > OPP can be enabled for these device by either:
> >> > > 1) Setting the bit corresponding to OMAP3_HAS_720MHZ
> >> > > in 'omap3_features'. (Refer changes to id.c)
> >> > >
> >> > > 2) Removing check for omap3_has_720mhz() before enabling
> >> > > the OPP. (Refer changes to opp3xxx_data.c)
> >> > >
> >> > > 3) Calling opp_enable() for 720MHz/VDD1 and 520MHz/VDD2 in
> >> > > the board file. (Refer changes to opp3xxx_data.c).
> >> > > This should, ideally, be done before omap3_opp_init() is
> >> > > called during device_initcall().
> >> > >
> >> > > CAUTION: This should be done for identified parts only.
> >> > > Else, the device could be damaged permanently.
> >> > >
> >> > > Signed-off-by: Sanjeev Premi <premi@ti.com>
> >> > > Reviewed-by: G, Manjunath Kondaiah <manjugk@ti.com>
> >> >
> >> > Acked-by: Kevin Hilman <khilman@ti.com>
> >>
> >> This patch seems to never have made it upstream. Is there a reason for
> >> that
> >> ?
> >
> > Ping ?
>
> We'd have to figure out a proper opp modifier logic with device tree.
> considering that non-dt boot is slowly getting dismantled in mach-omap2, to
> add new capabilities in non-dt is not really a good idea at this point in
> time - Further, we do have equivalent requirements in other TI SoCs as well
Good point, but I'm not sure to see where this patch is specific to legacy
boot. The two functions it modifies, and omap3xxx_check_features() and
omap3_opp_init(), are called for DT boot as well.
--
Regards,
Laurent Pinchart
^ permalink raw reply
* [GIT PULL] Xilinx Zynq fix for v3.14
From: Michal Simek @ 2014-02-10 12:17 UTC (permalink / raw)
To: linux-arm-kernel
Hi,
please consider to queue this bug fix for v3.14.
Bug was reported here:
https://lkml.org/lkml/2014/1/27/212
I have also discussed this with Rob regarding memreserve DT feature.
Here is thread with Rob:
https://lkml.org/lkml/2014/1/31/105
Moving kernel start is currently enabled by:
"ARM: ignore memory below PHYS_OFFSET"
(sha1: 571b14375019c3a66ef70d4d4a7083f4238aca30)
Thanks,
Michal
The following changes since commit 38dbfb59d1175ef458d006556061adeaa8751b72:
Linus 3.14-rc1 (2014-02-02 16:42:13 -0800)
are available in the git repository at:
git://git.xilinx.com/linux-xlnx.git tags/zynq-fixes-for-3.14
for you to fetch changes up to a73cbb758171c34cc3d58f3dfb80feef501a2079:
ARM: zynq: Reserve not DMAable space in front of the kernel (2014-02-10 13:04:35 +0100)
----------------------------------------------------------------
arm: Xilinx Zynq fixes for v3.14
- Protect DMA buffer allocation below
kernel start address
----------------------------------------------------------------
Michal Simek (1):
ARM: zynq: Reserve not DMAable space in front of the kernel
arch/arm/mach-zynq/common.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
--
Michal Simek, Ing. (M.Eng), OpenPGP -> KeyID: FE3D1F91
w: www.monstr.eu p: +42-0-721842854
Maintainer of Linux kernel - Microblaze cpu - http://www.monstr.eu/fdt/
Maintainer of Linux kernel - Xilinx Zynq ARM architecture
Microblaze U-BOOT custodian and responsible for u-boot arm zynq platform
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 263 bytes
Desc: OpenPGP digital signature
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20140210/bbac3ae6/attachment.sig>
^ permalink raw reply
* Re: [PATCH] video: imxfb: Use regulator API with LCD class for powering
From: Alexander Shiyan @ 2014-02-10 12:16 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <52F8C091.50704@ti.com>
???????????, 10 ??????? 2014, 14:05 +02:00 ?? Tomi Valkeinen <tomi.valkeinen@ti.com>:
> On 21/12/13 13:08, Alexander Shiyan wrote:
> > This patch replaces custom lcd_power() callback with
> > regulator API over LCD class.
> >
> > Signed-off-by: Alexander Shiyan <shc_work@mail.ru>
> > ---
> > .../devicetree/bindings/video/fsl,imx-fb.txt | 1 +
> > arch/arm/mach-imx/mach-mx27ads.c | 55 +++++++++++++++--
> > drivers/video/imxfb.c | 71
> +++++++++++++++++++---
> > include/linux/platform_data/video-imxfb.h | 1 -
> > 4 files changed, 114 insertions(+), 14 deletions(-)
> >
> > diff --git a/Documentation/devicetree/bindings/video/fsl,imx-fb.txt
> b/Documentation/devicetree/bindings/video/fsl,imx-fb.txt
> > index 46da08d..e6b1ee9 100644
> > --- a/Documentation/devicetree/bindings/video/fsl,imx-fb.txt
> > +++ b/Documentation/devicetree/bindings/video/fsl,imx-fb.txt
> > @@ -15,6 +15,7 @@ Required nodes:
> > - fsl,pcr: LCDC PCR value
> >
> > Optional properties:
> > +- lcd-supply: Regulator for LCD supply voltage.
> > - fsl,dmacr: DMA Control Register value. This is optional. By default, the
> > register is not modified as recommended by the datasheet.
> > - fsl,lscr1: LCDC Sharp Configuration Register value.
> > diff --git a/arch/arm/mach-imx/mach-mx27ads.c
...
> > +static void __init mx27ads_regulator_init(void)
> > +{
> > + struct gpio_chip *vchip;
> > +
> > + vchip = kzalloc(sizeof(*vchip), GFP_KERNEL);
> > + vchip->owner = THIS_MODULE;
> > + vchip->label = "LCD";
> > + vchip->base = MX27ADS_LCD_GPIO;
> > + vchip->ngpio = 1;
> > + vchip->direction_output = vgpio_dir_out;
> > + vchip->set = vgpio_set;
> > + gpiochip_add(vchip);
> > +
> > + platform_device_register_data(&platform_bus, "reg-fixed-voltage",
> > + PLATFORM_DEVID_AUTO,
> > + &mx27ads_lcd_regulator_pdata,
> > + sizeof(mx27ads_lcd_regulator_pdata));
> > +}
> > +
>
> Hmm, isn't all this something that should be in the board's .dts?
There are no DT support for this board yet.
---
^ permalink raw reply
* [PATCH v2 14/15] charger: max14577: Configure battery-dependent settings from DTS
From: Lee Jones @ 2014-02-10 12:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1391767487-10017-15-git-send-email-k.kozlowski@samsung.com>
> Remove hard-coded values for:
> - Fast Charge current,
> - End Of Charge current,
> - Fast Charge timer,
> - Overvoltage Protection Threshold,
> - Battery Constant Voltage,
> and use DTS to configure them. This allows using the max14577 charger
> driver with different batteries.
>
> Now the charger driver requires valid configuration data from DTS. In
> case of wrong configuration data it fails during probe. Patch adds
> of_compatible to the charger mfd cell in MFD driver core.
>
> Signed-off-by: Krzysztof Kozlowski <k.kozlowski@samsung.com>
> Cc: Kyungmin Park <kyungmin.park@samsung.com>
> Cc: Marek Szyprowski <m.szyprowski@samsung.com>
> Cc: Dmitry Eremin-Solenikov <dbaryshkov@gmail.com>
> Cc: David Woodhouse <dwmw2@infradead.org>
> Cc: Jenny Tc <jenny.tc@intel.com>
> ---
> drivers/mfd/max14577.c | 5 +-
> drivers/power/max14577_charger.c | 234 +++++++++++++++++++++++++++++-----
> include/linux/mfd/max14577-private.h | 10 ++
> include/linux/mfd/max14577.h | 8 ++
> 4 files changed, 227 insertions(+), 30 deletions(-)
<snip>
> diff --git a/include/linux/mfd/max14577-private.h b/include/linux/mfd/max14577-private.h
> index a8cd7de3526a..50cf70bec4d4 100644
> --- a/include/linux/mfd/max14577-private.h
> +++ b/include/linux/mfd/max14577-private.h
> @@ -269,6 +269,16 @@ enum maxim_muic_charger_type {
> #define MAX77836_CHARGER_CURRENT_LIMIT_HIGH_STEP 25000U
> #define MAX77836_CHARGER_CURRENT_LIMIT_MAX 475000U
>
> +/* MAX14577 charger End-Of-Charge current limits (as in MAXIM_CHGCTRL5 register), uA */
Too many chars. Didn't checkpatch.pl complain about this?
> +#define MAX14577_CHARGER_EOC_CURRENT_LIMIT_MIN 50000U
> +#define MAX14577_CHARGER_EOC_CURRENT_LIMIT_STEP 10000U
> +#define MAX14577_CHARGER_EOC_CURRENT_LIMIT_MAX 200000U
> +
> +/* MAX14577/MAX77836 Battery Constant Voltage (as in MAXIM_CHGCTRL3
> register), uV */
Same here
--
Lee Jones
Linaro STMicroelectronics Landing Team Lead
Linaro.org ? Open source software for ARM SoCs
Follow Linaro: Facebook | Twitter | Blog
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox