* [PATCH v26 2/7] arm64: kdump: implement machine_crash_shutdown()
From: James Morse @ 2016-09-16 14:49 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160915114815.GK16712@linaro.org>
On 16/09/16 04:21, AKASHI Takahiro wrote:
> On Wed, Sep 14, 2016 at 07:09:33PM +0100, James Morse wrote:
>> On 07/09/16 05:29, AKASHI Takahiro wrote:
>>> Primary kernel calls machine_crash_shutdown() to shut down non-boot cpus
>>> and save registers' status in per-cpu ELF notes before starting crash
>>> dump kernel. See kernel_kexec().
>>> Even if not all secondary cpus have shut down, we do kdump anyway.
>>>
>>> As we don't have to make non-boot(crashed) cpus offline (to preserve
>>> correct status of cpus at crash dump) before shutting down, this patch
>>> also adds a variant of smp_send_stop().
>>> diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h
>>> index 04744dc..a908958 100644
>>> --- a/arch/arm64/include/asm/kexec.h
>>> +++ b/arch/arm64/include/asm/kexec.h
>>> @@ -40,7 +40,46 @@
>>> static inline void crash_setup_regs(struct pt_regs *newregs,
>>> struct pt_regs *oldregs)
>>> {
>>> - /* Empty routine needed to avoid build errors. */
>>> + if (oldregs) {
>>> + memcpy(newregs, oldregs, sizeof(*newregs));
>>> + } else {
>>> + u64 tmp1, tmp2;
>>> +
>>> + __asm__ __volatile__ (
>>> + "stp x0, x1, [%2, #16 * 0]\n"
>>> + "stp x2, x3, [%2, #16 * 1]\n"
>>> + "stp x4, x5, [%2, #16 * 2]\n"
>>> + "stp x6, x7, [%2, #16 * 3]\n"
>>> + "stp x8, x9, [%2, #16 * 4]\n"
>>> + "stp x10, x11, [%2, #16 * 5]\n"
>>> + "stp x12, x13, [%2, #16 * 6]\n"
>>> + "stp x14, x15, [%2, #16 * 7]\n"
>>> + "stp x16, x17, [%2, #16 * 8]\n"
>>> + "stp x18, x19, [%2, #16 * 9]\n"
>>> + "stp x20, x21, [%2, #16 * 10]\n"
>>> + "stp x22, x23, [%2, #16 * 11]\n"
>>> + "stp x24, x25, [%2, #16 * 12]\n"
>>> + "stp x26, x27, [%2, #16 * 13]\n"
>>> + "stp x28, x29, [%2, #16 * 14]\n"
>>> + "mov %0, sp\n"
>>> + "stp x30, %0, [%2, #16 * 15]\n"
>>> +
>>> + "/* faked current PSTATE */\n"
>>> + "mrs %0, CurrentEL\n"
>>> + "mrs %1, DAIF\n"
>>> + "orr %0, %0, %1\n"
>>> + "mrs %1, NZCV\n"
>>> + "orr %0, %0, %1\n"
>>> +
>>
>> What about SPSEL? While we don't use it, it is correctly preserved for
>> everything except a CPU that calls panic()...
>
> My comment above might be confusing, but what I want to fake
> here is "spsr" as pt_regs.pstate is normally set based on spsr_el1.
> So there is no corresponding field of SPSEL in spsr.
Here is my logic, I may have missed something obvious, see what you think:
SPSR_EL{1,2} shows the CPU mode 'M' in bits 0-4, From aarch64 bit 4 is always 0.
>From the register definitions in the ARM-ARM C5.2, likely values in 0-3 are:
0100 EL1t
0101 EL1h
1000 EL2t
1001 EL2h
I'm pretty sure this least significant bit is what SPSEL changes, so it does get
implicitly recorded in SPSR.
CurrentEL returns a value in bits 0-3, of which 0-1 are RES0, so we lose the
difference between EL?t and EL?h.
>
>>
>>> + /* pc */
>>> + "adr %1, 1f\n"
>>> + "1:\n"
>>> + "stp %1, %0, [%2, #16 * 16]\n"
>>> + : "=r" (tmp1), "=r" (tmp2), "+r" (newregs)
>>> + :
>>> + : "memory"
Do you need the memory clobber? This asm only modifies values in newregs.
>>> + );
>>> + }
>>> }
>>>
>>> #endif /* __ASSEMBLY__ */
>>> diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
>>> +#ifdef CONFIG_KEXEC_CORE
>>> +void smp_send_crash_stop(void)
>>> +{
>>> + cpumask_t mask;
>>> + unsigned long timeout;
>>> +
>>> + if (num_online_cpus() == 1)
>>> + return;
>>> +
>>> + cpumask_copy(&mask, cpu_online_mask);
>>> + cpumask_clear_cpu(smp_processor_id(), &mask);
>>> +
>>> + atomic_set(&waiting_for_crash_ipi, num_online_cpus() - 1);
>>> +
>>> + pr_crit("SMP: stopping secondary CPUs\n");
>>> + smp_cross_call(&mask, IPI_CPU_CRASH_STOP);
>>> +
>>> + /* Wait up to one second for other CPUs to stop */
>>> + timeout = USEC_PER_SEC;
>>> + while ((atomic_read(&waiting_for_crash_ipi) > 0) && timeout--)
>>> + udelay(1);
>>> +
>>> + if (atomic_read(&waiting_for_crash_ipi) > 0)
>>> + pr_warning("SMP: failed to stop secondary CPUs %*pbl\n",
>>> + cpumask_pr_args(cpu_online_mask));
>>> +}
>>> +#endif
>>
>> This is very similar to smp_send_stop() which also has the timeout. Is it
>> possible to merge them? You could use in_crash_kexec to choose the IPI type.
>
> Yeah, we could merge them along with ipi_cpu_(crash_)stop().
> But the resulting code would be quite noisy if each line
> is switched by "if (in_crash_kexec)."
> Otherwise, we may have one big "if" like:
> void smp_send_stop(void)
> {
> if (in_crash_kexec)
> ...
> else
> ...
> }
> It seems to me that it is not much different from the current code.
> What do you think?
Hmm, yes, its too fiddly to keep the existing behaviour of both.
The problems are ipi_cpu_stop() doesn't call cpu_die(), (I can't see a good
reason for this, but more archaeology is needed), and ipi_cpu_crash_stop()
doesn't modify the online cpu mask.
I don't suggest we do this yet, but it could be future cleanup if it's proved to
be safe:
smp_send_stop() is only called from: machine_halt(), machine_power_off(),
machine_restart() and panic(). In all those cases the CPUs are never expected to
come back, so we can probably merge the IPIs. This involves modifying the
online cpu mask during kdump, (which I think is fine as it uses the atomic
bitops so we won't get blocked on a lock), and promoting in_crash_kexec to some
atomic type.
But I think we should leave it as it is for now,
Thanks,
James
^ permalink raw reply
* [PATCH V7 3/3] perf tools: adding support for address filters
From: Mathieu Poirier @ 2016-09-16 14:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474037045-31730-1-git-send-email-mathieu.poirier@linaro.org>
This patch makes it possible to use the current filter
framework with address filters. That way address filters for
HW tracers such as CoreSight and Intel PT can be communicated
to the kernel drivers.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
---
tools/perf/util/evsel.c | 5 +++++
tools/perf/util/evsel.h | 2 ++
tools/perf/util/parse-events.c | 39 ++++++++++++++++++++++++++++++++++-----
3 files changed, 41 insertions(+), 5 deletions(-)
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index a99e82d97df2..e0bb399dcdd4 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1067,6 +1067,11 @@ int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter)
return perf_evsel__append_filter(evsel, "(%s) && (%s)", filter);
}
+int perf_evsel__append_addr_filter(struct perf_evsel *evsel, const char *filter)
+{
+ return perf_evsel__append_filter(evsel, "%s,%s", filter);
+}
+
int perf_evsel__enable(struct perf_evsel *evsel)
{
int nthreads = thread_map__nr(evsel->threads);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 36ed0997e65b..49c51fb3d05c 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -234,6 +234,8 @@ void perf_evsel__set_sample_id(struct perf_evsel *evsel,
int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter);
int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter);
+int perf_evsel__append_addr_filter(struct perf_evsel *evsel,
+ const char *filter);
int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
const char *filter);
int perf_evsel__enable(struct perf_evsel *evsel);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 751b48fc641c..c23f2d5fc134 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1755,20 +1755,49 @@ foreach_evsel_in_last_glob(struct perf_evlist *evlist,
static int set_filter(struct perf_evsel *evsel, const void *arg)
{
const char *str = arg;
+ bool found = false;
+ int nr_addr_filters = 0;
+ struct perf_pmu *pmu = NULL;
- if (evsel == NULL || evsel->attr.type != PERF_TYPE_TRACEPOINT) {
- fprintf(stderr,
- "--filter option should follow a -e tracepoint option\n");
- return -1;
+ if (evsel == NULL)
+ goto err;
+
+ if (evsel->attr.type == PERF_TYPE_TRACEPOINT) {
+ if (perf_evsel__append_tp_filter(evsel, str) < 0) {
+ fprintf(stderr,
+ "not enough memory to hold filter string\n");
+ return -1;
+ }
+
+ return 0;
}
- if (perf_evsel__append_tp_filter(evsel, str) < 0) {
+ while ((pmu = perf_pmu__scan(pmu)) != NULL)
+ if (pmu->type == evsel->attr.type) {
+ found = true;
+ break;
+ }
+
+ if (found)
+ perf_pmu__scan_file(pmu, "nr_addr_filters",
+ "%d", &nr_addr_filters);
+
+ if (!nr_addr_filters)
+ goto err;
+
+ if (perf_evsel__append_addr_filter(evsel, str) < 0) {
fprintf(stderr,
"not enough memory to hold filter string\n");
return -1;
}
return 0;
+
+err:
+ fprintf(stderr,
+ "--filter option should follow a -e tracepoint or HW tracer option\n");
+
+ return -1;
}
int parse_filter(const struct option *opt, const char *str,
--
2.7.4
^ permalink raw reply related
* [PATCH V7 2/3] perf tools: new tracepoint specific function
From: Mathieu Poirier @ 2016-09-16 14:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474037045-31730-1-git-send-email-mathieu.poirier@linaro.org>
Making function perf_evsel__append_filter() static and
introducing a new tracepoint specific function to append
filters. That way we eliminate redundant code and avoid
formatting mistake.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
---
tools/perf/builtin-trace.c | 7 +++----
tools/perf/util/evsel.c | 9 +++++++--
tools/perf/util/evsel.h | 3 +--
tools/perf/util/parse-events.c | 4 ++--
4 files changed, 13 insertions(+), 10 deletions(-)
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index 4c2704332c14..34effab09f39 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2148,11 +2148,10 @@ static int trace__set_ev_qualifier_filter(struct trace *trace)
if (filter == NULL)
goto out_enomem;
- if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter,
- "(%s) && (%s)", filter)) {
+ if (!perf_evsel__append_tp_filter(trace->syscalls.events.sys_enter,
+ filter)) {
sys_exit = trace->syscalls.events.sys_exit;
- err = perf_evsel__append_filter(sys_exit,
- "(%s) && (%s)", filter);
+ err = perf_evsel__append_tp_filter(sys_exit, filter);
}
free(filter);
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index b93369745e08..a99e82d97df2 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1045,8 +1045,8 @@ int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter)
return -1;
}
-int perf_evsel__append_filter(struct perf_evsel *evsel,
- const char *fmt, const char *filter)
+static int perf_evsel__append_filter(struct perf_evsel *evsel,
+ const char *fmt, const char *filter)
{
char *new_filter;
@@ -1062,6 +1062,11 @@ int perf_evsel__append_filter(struct perf_evsel *evsel,
return -1;
}
+int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter)
+{
+ return perf_evsel__append_filter(evsel, "(%s) && (%s)", filter);
+}
+
int perf_evsel__enable(struct perf_evsel *evsel)
{
int nthreads = thread_map__nr(evsel->threads);
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 7ab59f15892f..36ed0997e65b 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -233,8 +233,7 @@ void perf_evsel__set_sample_id(struct perf_evsel *evsel,
bool use_sample_identifier);
int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter);
-int perf_evsel__append_filter(struct perf_evsel *evsel,
- const char *fmt, const char *filter);
+int perf_evsel__append_tp_filter(struct perf_evsel *evsel, const char *filter);
int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
const char *filter);
int perf_evsel__enable(struct perf_evsel *evsel);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 9692300585f6..751b48fc641c 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1762,7 +1762,7 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
return -1;
}
- if (perf_evsel__append_filter(evsel, "(%s) && (%s)", str) < 0) {
+ if (perf_evsel__append_tp_filter(evsel, str) < 0) {
fprintf(stderr,
"not enough memory to hold filter string\n");
return -1;
@@ -1793,7 +1793,7 @@ static int add_exclude_perf_filter(struct perf_evsel *evsel,
snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid());
- if (perf_evsel__append_filter(evsel, "(%s) && (%s)", new_filter) < 0) {
+ if (perf_evsel__append_tp_filter(evsel, new_filter) < 0) {
fprintf(stderr,
"not enough memory to hold filter string\n");
return -1;
--
2.7.4
^ permalink raw reply related
* [PATCH V7 1/3] perf tools: making perf_evsel__append_filter() generic
From: Mathieu Poirier @ 2016-09-16 14:44 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474037045-31730-1-git-send-email-mathieu.poirier@linaro.org>
By making function perf_evsel__append_filter() take a format rather
than an operator it is possible to reuse the code for other purposes
(ex. Intel PT and CoreSight) than tracepoints.
Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
Acked-by: Adrian Hunter <adrian.hunter@intel.com>
---
tools/perf/builtin-trace.c | 9 +++++++--
tools/perf/util/evsel.c | 4 ++--
tools/perf/util/evsel.h | 2 +-
tools/perf/util/parse-events.c | 4 ++--
4 files changed, 12 insertions(+), 7 deletions(-)
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index b8c6766301db..4c2704332c14 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -2140,6 +2140,7 @@ out_delete_sys_enter:
static int trace__set_ev_qualifier_filter(struct trace *trace)
{
int err = -1;
+ struct perf_evsel *sys_exit;
char *filter = asprintf_expr_inout_ints("id", !trace->not_ev_qualifier,
trace->ev_qualifier_ids.nr,
trace->ev_qualifier_ids.entries);
@@ -2147,8 +2148,12 @@ static int trace__set_ev_qualifier_filter(struct trace *trace)
if (filter == NULL)
goto out_enomem;
- if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter, "&&", filter))
- err = perf_evsel__append_filter(trace->syscalls.events.sys_exit, "&&", filter);
+ if (!perf_evsel__append_filter(trace->syscalls.events.sys_enter,
+ "(%s) && (%s)", filter)) {
+ sys_exit = trace->syscalls.events.sys_exit;
+ err = perf_evsel__append_filter(sys_exit,
+ "(%s) && (%s)", filter);
+ }
free(filter);
out:
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 21fd573106ed..b93369745e08 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -1046,14 +1046,14 @@ int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter)
}
int perf_evsel__append_filter(struct perf_evsel *evsel,
- const char *op, const char *filter)
+ const char *fmt, const char *filter)
{
char *new_filter;
if (evsel->filter == NULL)
return perf_evsel__set_filter(evsel, filter);
- if (asprintf(&new_filter,"(%s) %s (%s)", evsel->filter, op, filter) > 0) {
+ if (asprintf(&new_filter, fmt, evsel->filter, filter) > 0) {
free(evsel->filter);
evsel->filter = new_filter;
return 0;
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 4d44129e050b..7ab59f15892f 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -234,7 +234,7 @@ void perf_evsel__set_sample_id(struct perf_evsel *evsel,
int perf_evsel__set_filter(struct perf_evsel *evsel, const char *filter);
int perf_evsel__append_filter(struct perf_evsel *evsel,
- const char *op, const char *filter);
+ const char *fmt, const char *filter);
int perf_evsel__apply_filter(struct perf_evsel *evsel, int ncpus, int nthreads,
const char *filter);
int perf_evsel__enable(struct perf_evsel *evsel);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 6c913c3914fb..9692300585f6 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -1762,7 +1762,7 @@ static int set_filter(struct perf_evsel *evsel, const void *arg)
return -1;
}
- if (perf_evsel__append_filter(evsel, "&&", str) < 0) {
+ if (perf_evsel__append_filter(evsel, "(%s) && (%s)", str) < 0) {
fprintf(stderr,
"not enough memory to hold filter string\n");
return -1;
@@ -1793,7 +1793,7 @@ static int add_exclude_perf_filter(struct perf_evsel *evsel,
snprintf(new_filter, sizeof(new_filter), "common_pid != %d", getpid());
- if (perf_evsel__append_filter(evsel, "&&", new_filter) < 0) {
+ if (perf_evsel__append_filter(evsel, "(%s) && (%s)", new_filter) < 0) {
fprintf(stderr,
"not enough memory to hold filter string\n");
return -1;
--
2.7.4
^ permalink raw reply related
* [PATCH V7 0/3] Adding support for address filters
From: Mathieu Poirier @ 2016-09-16 14:44 UTC (permalink / raw)
To: linux-arm-kernel
This patch set makes it possible to use the current filter
framework with address filters. That way address filters for
HW tracers such as CoreSight and Intel PT can be communicated
to the kernel drivers.
In this revision precursor work is done to make function
perf_evsel__append_filter() generic, along with changes to
current customers. From there the work on address filters is
introduced.
Thanks,
Mathieu
---
Changes for V7:
- s/intelPT/Intel PT
- Added Adrian's ack.
Changes for V6:
- Split work in 3 (small) patches.
- Adding tracepoint and address filter append() functions
Changes for V5:
- Modified perf_evsel__append_filter() to take a string format
rather than an operation.
Changes for V4:
- Added support for address filters over more than one
nibble.
- Removed Jiri's ack, this version is too different from
what was reviewed.
Changes for V3:
- Added Jiri's ack.
- Rebased to v4.8-rc5.
Changes for V2:
- Rebased to v4.8-rc4.
- Revisited error path.
Mathieu Poirier (3):
perf tools: making perf_evsel__append_filter() generic
perf tools: new tracepoint specific function
perf tools: adding support for address filters
tools/perf/builtin-trace.c | 8 ++++++--
tools/perf/util/evsel.c | 16 +++++++++++++---
tools/perf/util/evsel.h | 5 +++--
tools/perf/util/parse-events.c | 41 +++++++++++++++++++++++++++++++++++------
4 files changed, 57 insertions(+), 13 deletions(-)
--
2.7.4
^ permalink raw reply
* [PATCH v5 3/3] clk: imx6: Fix procedure to switch the parent of LDB_DI_CLK
From: Philipp Zabel @ 2016-09-16 14:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOMZO5DPTSGafyYavoOcpKgo7Y=bh9Kd7KPHQ2QKLAxqzbQyMA@mail.gmail.com>
Am Freitag, den 16.09.2016, 11:33 -0300 schrieb Fabio Estevam:
> On Thu, Sep 15, 2016 at 10:36 PM, Shawn Guo <shawnguo@kernel.org> wrote:
>
> >> Shawn,
> >>
> >> Are you happy with it?
> >
> > Acked-by: Shawn Guo <shawnguo@kernel.org>
> >
> > Please send it to clk maintainers for applying.
>
> Thanks. Just sent it to the clk folks.
Thanks!
^ permalink raw reply
* [PATCH 3/3] clk: imx6: Fix procedure to switch the parent of LDB_DI_CLK
From: Fabio Estevam @ 2016-09-16 14:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474036587-13819-1-git-send-email-fabio.estevam@nxp.com>
Due to incorrect placement of the clock gate cell in the ldb_di[x]_clk
tree, the glitchy parent mux of ldb_di[x]_clk can cause a glitch to
enter the ldb_di_ipu_div divider. If the divider gets locked up, no
ldb_di[x]_clk is generated, and the LVDS display will hang when the
ipu_di_clk is sourced from ldb_di_clk.
To fix the problem, both the new and current parent of the ldb_di_clk
should be disabled before the switch. This patch ensures that correct
steps are followed when ldb_di_clk parent is switched in the beginning
of boot. The glitchy muxes are then registered as read-only. The clock
parent can be selected using the assigned-clocks and
assigned-clock-parents properties of the ccm device tree node:
&clks {
assigned-clocks = <&clks IMX6QDL_CLK_LDB_DI0_SEL>,
<&clks IMX6QDL_CLK_LDB_DI1_SEL>;
assigned-clock-parents = <&clks IMX6QDL_CLK_MMDC_CH1_AXI>,
<&clks IMX6QDL_CLK_PLL5_VIDEO_DIV>;
};
The issue is explained in detail in EB821 ("LDB Clock Switch Procedure &
i.MX6 Asynchronous Clock Switching Guidelines") [1].
[1] http://www.nxp.com/files/32bit/doc/eng_bulletin/EB821.pdf
Signed-off-by: Ranjani Vaidyanathan <Ranjani.Vaidyanathan@nxp.com>
Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Reviewed-by: Akshay Bhat <akshay.bhat@timesys.com>
Tested-by Joshua Clayton <stillcompiling@gmail.com>
Tested-by: Charles Kang <Charles.Kang@advantech.com.tw>
Acked-by: Shawn Guo <shawnguo@kernel.org>
---
drivers/clk/imx/clk-imx6q.c | 264 +++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 259 insertions(+), 5 deletions(-)
diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c
index 9bbc994..fc3ed87 100644
--- a/drivers/clk/imx/clk-imx6q.c
+++ b/drivers/clk/imx/clk-imx6q.c
@@ -156,9 +156,90 @@ static struct clk ** const uart_clks[] __initconst = {
NULL
};
+static int ldb_di_sel_by_clock_id(int clock_id)
+{
+ switch (clock_id) {
+ case IMX6QDL_CLK_PLL5_VIDEO_DIV:
+ if (clk_on_imx6q() &&
+ imx_get_soc_revision() == IMX_CHIP_REVISION_1_0)
+ return -ENOENT;
+ return 0;
+ case IMX6QDL_CLK_PLL2_PFD0_352M:
+ return 1;
+ case IMX6QDL_CLK_PLL2_PFD2_396M:
+ return 2;
+ case IMX6QDL_CLK_MMDC_CH1_AXI:
+ return 3;
+ case IMX6QDL_CLK_PLL3_USB_OTG:
+ return 4;
+ default:
+ return -ENOENT;
+ }
+}
+
+static void of_assigned_ldb_sels(struct device_node *node,
+ unsigned int *ldb_di0_sel,
+ unsigned int *ldb_di1_sel)
+{
+ struct of_phandle_args clkspec;
+ int index, rc, num_parents;
+ int parent, child, sel;
+
+ num_parents = of_count_phandle_with_args(node, "assigned-clock-parents",
+ "#clock-cells");
+ for (index = 0; index < num_parents; index++) {
+ rc = of_parse_phandle_with_args(node, "assigned-clock-parents",
+ "#clock-cells", index, &clkspec);
+ if (rc < 0) {
+ /* skip empty (null) phandles */
+ if (rc == -ENOENT)
+ continue;
+ else
+ return;
+ }
+ if (clkspec.np != node || clkspec.args[0] >= IMX6QDL_CLK_END) {
+ pr_err("ccm: parent clock %d not in ccm\n", index);
+ return;
+ }
+ parent = clkspec.args[0];
+
+ rc = of_parse_phandle_with_args(node, "assigned-clocks",
+ "#clock-cells", index, &clkspec);
+ if (rc < 0)
+ return;
+ if (clkspec.np != node || clkspec.args[0] >= IMX6QDL_CLK_END) {
+ pr_err("ccm: child clock %d not in ccm\n", index);
+ return;
+ }
+ child = clkspec.args[0];
+
+ if (child != IMX6QDL_CLK_LDB_DI0_SEL &&
+ child != IMX6QDL_CLK_LDB_DI1_SEL)
+ continue;
+
+ sel = ldb_di_sel_by_clock_id(parent);
+ if (sel < 0) {
+ pr_err("ccm: invalid ldb_di%d parent clock: %d\n",
+ child == IMX6QDL_CLK_LDB_DI1_SEL, parent);
+ continue;
+ }
+
+ if (child == IMX6QDL_CLK_LDB_DI0_SEL)
+ *ldb_di0_sel = sel;
+ if (child == IMX6QDL_CLK_LDB_DI1_SEL)
+ *ldb_di1_sel = sel;
+ }
+}
+
#define CCM_CCDR 0x04
+#define CCM_CCSR 0x0c
+#define CCM_CS2CDR 0x2c
+
+#define CCDR_MMDC_CH1_MASK BIT(16)
+#define CCSR_PLL3_SW_CLK_SEL BIT(0)
-#define CCDR_MMDC_CH1_MASK BIT(16)
+#define CS2CDR_LDB_DI0_CLK_SEL_SHIFT 9
+#define CS2CDR_LDB_DI1_CLK_SEL_SHIFT 12
static void __init imx6q_mmdc_ch1_mask_handshake(void __iomem *ccm_base)
{
@@ -169,10 +250,173 @@ static void __init imx6q_mmdc_ch1_mask_handshake(void __iomem *ccm_base)
writel_relaxed(reg, ccm_base + CCM_CCDR);
}
+/*
+ * The only way to disable the MMDC_CH1 clock is to move it to pll3_sw_clk
+ * via periph2_clk2_sel and then to disable pll3_sw_clk by selecting the
+ * bypass clock source, since there is no CG bit for mmdc_ch1.
+ */
+static void mmdc_ch1_disable(void __iomem *ccm_base)
+{
+ unsigned int reg;
+
+ clk_set_parent(clk[IMX6QDL_CLK_PERIPH2_CLK2_SEL],
+ clk[IMX6QDL_CLK_PLL3_USB_OTG]);
+
+ /*
+ * Handshake with mmdc_ch1 module must be masked when changing
+ * periph2_clk_sel.
+ */
+ clk_set_parent(clk[IMX6QDL_CLK_PERIPH2], clk[IMX6QDL_CLK_PERIPH2_CLK2]);
+
+ /* Disable pll3_sw_clk by selecting the bypass clock source */
+ reg = readl_relaxed(ccm_base + CCM_CCSR);
+ reg |= CCSR_PLL3_SW_CLK_SEL;
+ writel_relaxed(reg, ccm_base + CCM_CCSR);
+}
+
+static void mmdc_ch1_reenable(void __iomem *ccm_base)
+{
+ unsigned int reg;
+
+ /* Enable pll3_sw_clk by disabling the bypass */
+ reg = readl_relaxed(ccm_base + CCM_CCSR);
+ reg &= ~CCSR_PLL3_SW_CLK_SEL;
+ writel_relaxed(reg, ccm_base + CCM_CCSR);
+
+ clk_set_parent(clk[IMX6QDL_CLK_PERIPH2], clk[IMX6QDL_CLK_PERIPH2_PRE]);
+}
+
+/*
+ * We have to follow a strict procedure when changing the LDB clock source,
+ * otherwise we risk introducing a glitch that can lock up the LDB divider.
+ * Things to keep in mind:
+ *
+ * 1. The current and new parent clock inputs to the mux must be disabled.
+ * 2. The default clock input for ldb_di0/1_clk_sel is mmdc_ch1_axi, which
+ * has no CG bit.
+ * 3. pll2_pfd2_396m can not be gated if it is used as memory clock.
+ * 4. In the RTL implementation of the LDB_DI_CLK_SEL muxes the top four
+ * options are in one mux and the PLL3 option along with three unused
+ * inputs is in a second mux. There is a third mux with two inputs used
+ * to decide between the first and second 4-port mux:
+ *
+ * pll5_video_div 0 --|\
+ * pll2_pfd0_352m 1 --| |_
+ * pll2_pfd2_396m 2 --| | `-|\
+ * mmdc_ch1_axi 3 --|/ | |
+ * | |--
+ * pll3_usb_otg 4 --|\ | |
+ * 5 --| |_,-|/
+ * 6 --| |
+ * 7 --|/
+ *
+ * The ldb_di0/1_clk_sel[1:0] bits control both 4-port muxes@the same time.
+ * The ldb_di0/1_clk_sel[2] bit controls the 2-port mux. The code below
+ * switches the parent to the bottom mux first and then manipulates the top
+ * mux to ensure that no glitch will enter the divider.
+ */
+static void init_ldb_clks(struct device_node *np, void __iomem *ccm_base)
+{
+ unsigned int reg;
+ unsigned int sel[2][4];
+ int i;
+
+ reg = readl_relaxed(ccm_base + CCM_CS2CDR);
+ sel[0][0] = (reg >> CS2CDR_LDB_DI0_CLK_SEL_SHIFT) & 7;
+ sel[1][0] = (reg >> CS2CDR_LDB_DI1_CLK_SEL_SHIFT) & 7;
+
+ sel[0][3] = sel[0][2] = sel[0][1] = sel[0][0];
+ sel[1][3] = sel[1][2] = sel[1][1] = sel[1][0];
+
+ of_assigned_ldb_sels(np, &sel[0][3], &sel[1][3]);
+
+ for (i = 0; i < 2; i++) {
+ /* Warn if a glitch might have been introduced already */
+ if (sel[i][0] != 3) {
+ pr_warn("ccm: ldb_di%d_sel already changed from reset value: %d\n",
+ i, sel[i][0]);
+ }
+
+ if (sel[i][0] == sel[i][3])
+ continue;
+
+ /* Only switch to or from pll2_pfd2_396m if it is disabled */
+ if ((sel[i][0] == 2 || sel[i][3] == 2) &&
+ (clk_get_parent(clk[IMX6QDL_CLK_PERIPH_PRE]) ==
+ clk[IMX6QDL_CLK_PLL2_PFD2_396M])) {
+ pr_err("ccm: ldb_di%d_sel: couldn't disable pll2_pfd2_396m\n",
+ i);
+ sel[i][3] = sel[i][2] = sel[i][1] = sel[i][0];
+ continue;
+ }
+
+ /* First switch to the bottom mux */
+ sel[i][1] = sel[i][0] | 4;
+
+ /* Then configure the top mux before switching back to it */
+ sel[i][2] = sel[i][3] | 4;
+
+ pr_debug("ccm: switching ldb_di%d_sel: %d->%d->%d->%d\n", i,
+ sel[i][0], sel[i][1], sel[i][2], sel[i][3]);
+ }
+
+ if (sel[0][0] == sel[0][3] && sel[1][0] == sel[1][3])
+ return;
+
+ mmdc_ch1_disable(ccm_base);
+
+ for (i = 1; i < 4; i++) {
+ reg = readl_relaxed(ccm_base + CCM_CS2CDR);
+ reg &= ~((7 << CS2CDR_LDB_DI0_CLK_SEL_SHIFT) |
+ (7 << CS2CDR_LDB_DI1_CLK_SEL_SHIFT));
+ reg |= ((sel[0][i] << CS2CDR_LDB_DI0_CLK_SEL_SHIFT) |
+ (sel[1][i] << CS2CDR_LDB_DI1_CLK_SEL_SHIFT));
+ writel_relaxed(reg, ccm_base + CCM_CS2CDR);
+ }
+
+ mmdc_ch1_reenable(ccm_base);
+}
+
+#define CCM_ANALOG_PLL_VIDEO 0xa0
+#define CCM_ANALOG_PFD_480 0xf0
+#define CCM_ANALOG_PFD_528 0x100
+
+#define PLL_ENABLE BIT(13)
+
+#define PFD0_CLKGATE BIT(7)
+#define PFD1_CLKGATE BIT(15)
+#define PFD2_CLKGATE BIT(23)
+#define PFD3_CLKGATE BIT(31)
+
+static void disable_anatop_clocks(void __iomem *anatop_base)
+{
+ unsigned int reg;
+
+ /* Make sure PLL2 PFDs 0-2 are gated */
+ reg = readl_relaxed(anatop_base + CCM_ANALOG_PFD_528);
+ /* Cannot gate PFD2 if pll2_pfd2_396m is the parent of MMDC clock */
+ if (clk_get_parent(clk[IMX6QDL_CLK_PERIPH_PRE]) ==
+ clk[IMX6QDL_CLK_PLL2_PFD2_396M])
+ reg |= PFD0_CLKGATE | PFD1_CLKGATE;
+ else
+ reg |= PFD0_CLKGATE | PFD1_CLKGATE | PFD2_CLKGATE;
+ writel_relaxed(reg, anatop_base + CCM_ANALOG_PFD_528);
+
+ /* Make sure PLL3 PFDs 0-3 are gated */
+ reg = readl_relaxed(anatop_base + CCM_ANALOG_PFD_480);
+ reg |= PFD0_CLKGATE | PFD1_CLKGATE | PFD2_CLKGATE | PFD3_CLKGATE;
+ writel_relaxed(reg, anatop_base + CCM_ANALOG_PFD_480);
+
+ /* Make sure PLL5 is disabled */
+ reg = readl_relaxed(anatop_base + CCM_ANALOG_PLL_VIDEO);
+ reg &= ~PLL_ENABLE;
+ writel_relaxed(reg, anatop_base + CCM_ANALOG_PLL_VIDEO);
+}
+
static void __init imx6q_clocks_init(struct device_node *ccm_node)
{
struct device_node *np;
- void __iomem *base;
+ void __iomem *anatop_base, *base;
int i;
int ret;
@@ -185,7 +429,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_ANACLK2] = imx_obtain_fixed_clock("anaclk2", 0);
np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
- base = of_iomap(np, 0);
+ anatop_base = base = of_iomap(np, 0);
WARN_ON(!base);
/* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */
@@ -310,8 +554,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
base = of_iomap(np, 0);
WARN_ON(!base);
- imx6q_mmdc_ch1_mask_handshake(base);
-
/* name reg shift width parent_names num_parents */
clk[IMX6QDL_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels));
clk[IMX6QDL_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
@@ -340,6 +582,18 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_GPU3D_SHADER_SEL] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8, 2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
clk[IMX6QDL_CLK_IPU1_SEL] = imx_clk_mux("ipu1_sel", base + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
clk[IMX6QDL_CLK_IPU2_SEL] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
+
+ disable_anatop_clocks(anatop_base);
+
+ imx6q_mmdc_ch1_mask_handshake(base);
+
+ /*
+ * The LDB_DI0/1_SEL muxes are registered read-only due to a hardware
+ * bug. Set the muxes to the requested values before registering the
+ * ldb_di_sel clocks.
+ */
+ init_ldb_clks(np, base);
+
clk[IMX6QDL_CLK_LDB_DI0_SEL] = imx_clk_mux_ldb("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels));
clk[IMX6QDL_CLK_LDB_DI1_SEL] = imx_clk_mux_ldb("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels));
clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
--
2.7.4
^ permalink raw reply related
* [PATCH 2/3] clk: imx6: Make the LDB_DI0 and LDB_DI1 clocks read-only
From: Fabio Estevam @ 2016-09-16 14:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474036587-13819-1-git-send-email-fabio.estevam@nxp.com>
From: Philipp Zabel <p.zabel@pengutronix.de>
Due to incorrect placement of the clock gate cell in the ldb_di[x]_clk
tree, the glitchy parent mux of ldb_di[x]_clk can cause a glitch to
enter the ldb_di_ipu_div divider. If the divider gets locked up, no
ldb_di[x]_clk is generated, and the LVDS display will hang when the
ipu_di_clk is sourced from ldb_di_clk.
To fix the problem, both the new and current parent of the ldb_di_clk
should be disabled before the switch. As this can not be guaranteed by
the clock framework during runtime, make the ldb_di[x]_sel muxes read-only.
A workaround to set the muxes once during boot could be added to the
kernel or bootloader.
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
---
drivers/clk/imx/clk-imx6q.c | 10 ++--------
drivers/clk/imx/clk.h | 8 ++++++++
2 files changed, 10 insertions(+), 8 deletions(-)
diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c
index dd33ebc..9bbc994 100644
--- a/drivers/clk/imx/clk-imx6q.c
+++ b/drivers/clk/imx/clk-imx6q.c
@@ -340,8 +340,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk[IMX6QDL_CLK_GPU3D_SHADER_SEL] = imx_clk_mux("gpu3d_shader_sel", base + 0x18, 8, 2, gpu3d_shader_sels, ARRAY_SIZE(gpu3d_shader_sels));
clk[IMX6QDL_CLK_IPU1_SEL] = imx_clk_mux("ipu1_sel", base + 0x3c, 9, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
clk[IMX6QDL_CLK_IPU2_SEL] = imx_clk_mux("ipu2_sel", base + 0x3c, 14, 2, ipu_sels, ARRAY_SIZE(ipu_sels));
- clk[IMX6QDL_CLK_LDB_DI0_SEL] = imx_clk_mux_flags("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
- clk[IMX6QDL_CLK_LDB_DI1_SEL] = imx_clk_mux_flags("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels), CLK_SET_RATE_PARENT);
+ clk[IMX6QDL_CLK_LDB_DI0_SEL] = imx_clk_mux_ldb("ldb_di0_sel", base + 0x2c, 9, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels));
+ clk[IMX6QDL_CLK_LDB_DI1_SEL] = imx_clk_mux_ldb("ldb_di1_sel", base + 0x2c, 12, 3, ldb_di_sels, ARRAY_SIZE(ldb_di_sels));
clk[IMX6QDL_CLK_IPU1_DI0_PRE_SEL] = imx_clk_mux_flags("ipu1_di0_pre_sel", base + 0x34, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
clk[IMX6QDL_CLK_IPU1_DI1_PRE_SEL] = imx_clk_mux_flags("ipu1_di1_pre_sel", base + 0x34, 15, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
clk[IMX6QDL_CLK_IPU2_DI0_PRE_SEL] = imx_clk_mux_flags("ipu2_di0_pre_sel", base + 0x38, 6, 3, ipu_di_pre_sels, ARRAY_SIZE(ipu_di_pre_sels), CLK_SET_RATE_PARENT);
@@ -593,12 +593,6 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
clk_register_clkdev(clk[IMX6QDL_CLK_ENET_REF], "enet_ref", NULL);
- if ((imx_get_soc_revision() != IMX_CHIP_REVISION_1_0) ||
- clk_on_imx6dl()) {
- clk_set_parent(clk[IMX6QDL_CLK_LDB_DI0_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
- clk_set_parent(clk[IMX6QDL_CLK_LDB_DI1_SEL], clk[IMX6QDL_CLK_PLL5_VIDEO_DIV]);
- }
-
clk_set_rate(clk[IMX6QDL_CLK_PLL3_PFD1_540M], 540000000);
if (clk_on_imx6dl())
clk_set_parent(clk[IMX6QDL_CLK_IPU1_SEL], clk[IMX6QDL_CLK_PLL3_PFD1_540M]);
diff --git a/drivers/clk/imx/clk.h b/drivers/clk/imx/clk.h
index 3799ff8..4afad3b 100644
--- a/drivers/clk/imx/clk.h
+++ b/drivers/clk/imx/clk.h
@@ -75,6 +75,14 @@ static inline struct clk *imx_clk_fixed(const char *name, int rate)
return clk_register_fixed_rate(NULL, name, NULL, 0, rate);
}
+static inline struct clk *imx_clk_mux_ldb(const char *name, void __iomem *reg,
+ u8 shift, u8 width, const char **parents, int num_parents)
+{
+ return clk_register_mux(NULL, name, parents, num_parents,
+ CLK_SET_RATE_NO_REPARENT | CLK_SET_RATE_PARENT, reg,
+ shift, width, CLK_MUX_READ_ONLY, &imx_ccm_lock);
+}
+
static inline struct clk *imx_clk_fixed_factor(const char *name,
const char *parent, unsigned int mult, unsigned int div)
{
--
2.7.4
^ permalink raw reply related
* [PATCH 1/3] clk: imx6: Mask mmdc_ch1 handshake for periph2_sel and mmdc_ch1_axi_podf
From: Fabio Estevam @ 2016-09-16 14:36 UTC (permalink / raw)
To: linux-arm-kernel
From: Philipp Zabel <p.zabel@pengutronix.de>
MMDC CH1 is not used on i.MX6Q, so the handshake needed to change the
parent of periph2_sel or the divider of mmdc_ch1_axi_podf will never
succeed.
Disable the handshake mechanism to allow changing the frequency of
mmdc_ch1_axi, allowing to use it as a possible source for the LDB DI
clock.
Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
---
drivers/clk/imx/clk-imx6q.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/clk/imx/clk-imx6q.c b/drivers/clk/imx/clk-imx6q.c
index ba1c1ae..dd33ebc 100644
--- a/drivers/clk/imx/clk-imx6q.c
+++ b/drivers/clk/imx/clk-imx6q.c
@@ -156,6 +156,19 @@ static struct clk ** const uart_clks[] __initconst = {
NULL
};
+#define CCM_CCDR 0x04
+
+#define CCDR_MMDC_CH1_MASK BIT(16)
+
+static void __init imx6q_mmdc_ch1_mask_handshake(void __iomem *ccm_base)
+{
+ unsigned int reg;
+
+ reg = readl_relaxed(ccm_base + CCM_CCDR);
+ reg |= CCDR_MMDC_CH1_MASK;
+ writel_relaxed(reg, ccm_base + CCM_CCDR);
+}
+
static void __init imx6q_clocks_init(struct device_node *ccm_node)
{
struct device_node *np;
@@ -297,6 +310,8 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
base = of_iomap(np, 0);
WARN_ON(!base);
+ imx6q_mmdc_ch1_mask_handshake(base);
+
/* name reg shift width parent_names num_parents */
clk[IMX6QDL_CLK_STEP] = imx_clk_mux("step", base + 0xc, 8, 1, step_sels, ARRAY_SIZE(step_sels));
clk[IMX6QDL_CLK_PLL1_SW] = imx_clk_mux("pll1_sw", base + 0xc, 2, 1, pll1_sw_sels, ARRAY_SIZE(pll1_sw_sels));
--
2.7.4
^ permalink raw reply related
* [PATCH 5/6] arm/arm64: vgic-new: Implement VGICv3 CPU interface access
From: Marc Zyngier @ 2016-09-16 14:36 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474028453-29132-6-git-send-email-vijay.kilari@gmail.com>
On 16/09/16 13:20, vijay.kilari at gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
>
> VGICv3 CPU interface registers are accessed using
> KVM_DEV_ARM_VGIC_CPU_SYSREGS ioctl. These registers are accessed
> as 64-bit. The cpu MPIDR value is passed along with register id.
> is used to identify the cpu for registers access.
>
> The version of VGIC v3 specification is define here
> http://lists.infradead.org/pipermail/linux-arm-kernel/2016-July/445611.html
>
> Signed-off-by: Pavel Fedin <p.fedin@samsung.com>
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
> ---
> arch/arm64/include/uapi/asm/kvm.h | 3 +
> arch/arm64/kvm/Makefile | 1 +
> include/linux/irqchip/arm-gic-v3.h | 30 ++++
> virt/kvm/arm/vgic/vgic-kvm-device.c | 27 ++++
> virt/kvm/arm/vgic/vgic-mmio-v3.c | 18 +++
> virt/kvm/arm/vgic/vgic-sys-reg-v3.c | 296 ++++++++++++++++++++++++++++++++++++
> virt/kvm/arm/vgic/vgic.h | 10 ++
> 7 files changed, 385 insertions(+)
>
> diff --git a/arch/arm64/include/uapi/asm/kvm.h b/arch/arm64/include/uapi/asm/kvm.h
> index 56dc08d..91c7137 100644
> --- a/arch/arm64/include/uapi/asm/kvm.h
> +++ b/arch/arm64/include/uapi/asm/kvm.h
> @@ -206,9 +206,12 @@ struct kvm_arch_memory_slot {
> (0xffffffffULL << KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT)
> #define KVM_DEV_ARM_VGIC_OFFSET_SHIFT 0
> #define KVM_DEV_ARM_VGIC_OFFSET_MASK (0xffffffffULL << KVM_DEV_ARM_VGIC_OFFSET_SHIFT)
> +#define KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK (0xffff)
> #define KVM_DEV_ARM_VGIC_GRP_NR_IRQS 3
> #define KVM_DEV_ARM_VGIC_GRP_CTRL 4
> #define KVM_DEV_ARM_VGIC_GRP_REDIST_REGS 5
> +#define KVM_DEV_ARM_VGIC_CPU_SYSREGS 6
> +
> #define KVM_DEV_ARM_VGIC_CTRL_INIT 0
>
> /* Device Control API on vcpu fd */
> diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
> index d50a82a..1a14e29 100644
> --- a/arch/arm64/kvm/Makefile
> +++ b/arch/arm64/kvm/Makefile
> @@ -32,5 +32,6 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
> kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-kvm-device.o
> kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-its.o
> kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/irqchip.o
> +kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-sys-reg-v3.o
> kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/arch_timer.o
> kvm-$(CONFIG_KVM_ARM_PMU) += $(KVM)/arm/pmu.o
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index 88d83d3..d4e9c7d 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -355,6 +355,27 @@
> #define ICC_CTLR_EL1_EOImode_SHIFT (1)
> #define ICC_CTLR_EL1_EOImode_drop_dir (0U << ICC_CTLR_EL1_EOImode_SHIFT)
> #define ICC_CTLR_EL1_EOImode_drop (1U << ICC_CTLR_EL1_EOImode_SHIFT)
> +#define ICC_CTLR_EL1_EOImode_MASK (1 << ICC_CTLR_EL1_EOImode_SHIFT)
> +#define ICC_CTLR_EL1_CBPR_SHIFT (0)
> +#define ICC_CTLR_EL1_CBPR_MASK (1 << ICC_CTLR_EL1_CBPR_SHIFT)
> +#define ICC_CTLR_EL1_PRI_BITS_SHIFT (8)
> +#define ICC_CTLR_EL1_PRI_BITS_MASK (0x7 << ICC_CTLR_EL1_PRI_BITS_SHIFT)
> +#define ICC_CTLR_EL1_ID_BITS_SHIFT (11)
> +#define ICC_CTLR_EL1_ID_BITS_MASK (0x7 << ICC_CTLR_EL1_ID_BITS_SHIFT)
> +#define ICC_CTLR_EL1_SEIS_SHIFT (14)
> +#define ICC_CTLR_EL1_SEIS_MASK (0x1 << ICC_CTLR_EL1_SEIS_SHIFT)
> +#define ICC_CTLR_EL1_A3V_SHIFT (15)
> +#define ICC_CTLR_EL1_A3V_MASK (0x1 << ICC_CTLR_EL1_A3V_SHIFT)
> +#define ICC_PMR_EL1_SHIFT (0)
> +#define ICC_PMR_EL1_MASK (0xff << ICC_PMR_EL1_SHIFT)
> +#define ICC_BPR0_EL1_SHIFT (0)
> +#define ICC_BPR0_EL1_MASK (0x7 << ICC_BPR0_EL1_SHIFT)
> +#define ICC_BPR1_EL1_SHIFT (0)
> +#define ICC_BPR1_EL1_MASK (0x7 << ICC_BPR1_EL1_SHIFT)
> +#define ICC_IGRPEN0_EL1_SHIFT (0)
> +#define ICC_IGRPEN0_EL1_MASK (1 << ICC_IGRPEN0_EL1_SHIFT)
> +#define ICC_IGRPEN1_EL1_SHIFT (0)
> +#define ICC_IGRPEN1_EL1_MASK (1 << ICC_IGRPEN1_EL1_SHIFT)
> #define ICC_SRE_EL1_SRE (1U << 0)
>
> /*
> @@ -398,6 +419,15 @@
> #define ICH_VMCR_ENG1_SHIFT 1
> #define ICH_VMCR_ENG1_MASK (1 << ICH_VMCR_ENG1_SHIFT)
>
> +#define ICH_VTR_PRI_BITS_SHIFT 29
> +#define ICH_VTR_PRI_BITS_MASK (7 << ICH_VTR_PRI_BITS_SHIFT)
> +#define ICH_VTR_ID_BITS_SHIFT 23
> +#define ICH_VTR_ID_BITS_MASK (7 << ICH_VTR_ID_BITS_SHIFT)
> +#define ICH_VTR_SEIS_SHIFT 22
> +#define ICH_VTR_SEIS_MASK (1 << ICH_VTR_SEIS_SHIFT)
> +#define ICH_VTR_A3V_SHIFT 21
> +#define ICH_VTR_A3V_MASK (1 << ICH_VTR_A3V_SHIFT)
> +
Same thing here. Please group all the additions to this file into a
single, independent patch.
> #define ICC_IAR1_EL1_SPURIOUS 0x3ff
>
> #define ICC_SRE_EL2_SRE (1 << 0)
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index a4656fc..a48101f 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -506,6 +506,14 @@ static int vgic_v3_attr_regs_access(struct kvm_device *dev,
> if (!is_write)
> *reg = tmp32;
> break;
> + case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
> + u64 regid;
> +
> + regid = (attr->attr & KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK);
> + ret = vgic_v3_cpu_sysregs_uaccess(vcpu, is_write,
> + regid, reg);
> + break;
> + }
> default:
> ret = -EINVAL;
> break;
> @@ -539,6 +547,15 @@ static int vgic_v3_set_attr(struct kvm_device *dev,
> reg = tmp32;
> return vgic_v3_attr_regs_access(dev, attr, ®, true);
> }
> + case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
> + u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> + u64 reg;
> +
> + if (get_user(reg, uaddr))
> + return -EFAULT;
> +
> + return vgic_v3_attr_regs_access(dev, attr, ®, true);
> + }
> }
> return -ENXIO;
> }
> @@ -565,6 +582,15 @@ static int vgic_v3_get_attr(struct kvm_device *dev,
> tmp32 = reg;
> return put_user(tmp32, uaddr);
> }
> + case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
> + u64 __user *uaddr = (u64 __user *)(long)attr->addr;
> + u64 reg;
> +
> + ret = vgic_v3_attr_regs_access(dev, attr, ®, false);
> + if (ret)
> + return ret;
> + return put_user(reg, uaddr);
> + }
> }
>
> return -ENXIO;
> @@ -583,6 +609,7 @@ static int vgic_v3_has_attr(struct kvm_device *dev,
> break;
> case KVM_DEV_ARM_VGIC_GRP_DIST_REGS:
> case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:
> + case KVM_DEV_ARM_VGIC_CPU_SYSREGS:
> return vgic_v3_has_attr_regs(dev, attr);
> case KVM_DEV_ARM_VGIC_GRP_NR_IRQS:
> return 0;
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index 83dece8..af748d7 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -23,6 +23,7 @@
>
> #include "vgic.h"
> #include "vgic-mmio.h"
> +#include "sys_regs.h"
>
> /* extract @num bytes at @offset bytes offset in data */
> unsigned long extract_bytes(u64 data, unsigned int offset,
> @@ -639,6 +640,23 @@ int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr)
> nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers);
> break;
> }
> + case KVM_DEV_ARM_VGIC_CPU_SYSREGS: {
> + u64 reg, id;
> + unsigned long mpidr;
> + struct kvm_vcpu *vcpu;
> +
> + mpidr = (attr->attr & KVM_DEV_ARM_VGIC_V3_MPIDR_MASK) >>
> + KVM_DEV_ARM_VGIC_V3_MPIDR_SHIFT;
> +
> + vcpu = kvm_mpidr_to_vcpu(dev->kvm, mpidr);
No. Your "mpidr" variable is not an MPIDR. It represents the same
thing, but not with the right format.
> + if (!vcpu)
> + return -EINVAL;
> + if (vcpu->vcpu_id >= atomic_read(&dev->kvm->online_vcpus))
How can that happen?
> + return -EINVAL;
> +
> + id = (attr->attr & KVM_DEV_ARM_VGIC_SYSREG_INSTR_MASK);
> + return vgic_v3_has_cpu_sysregs_attr(vcpu, 0, id, ®);
> + }
> default:
> return -ENXIO;
> }
> diff --git a/virt/kvm/arm/vgic/vgic-sys-reg-v3.c b/virt/kvm/arm/vgic/vgic-sys-reg-v3.c
> new file mode 100644
> index 0000000..8e4f403
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-sys-reg-v3.c
> @@ -0,0 +1,296 @@
> +#include <linux/irqchip/arm-gic-v3.h>
> +#include <linux/kvm.h>
> +#include <linux/kvm_host.h>
> +#include <kvm/iodev.h>
> +#include <kvm/arm_vgic.h>
> +#include <asm/kvm_emulate.h>
> +#include <asm/kvm_arm.h>
> +#include <asm/kvm_mmu.h>
> +
> +#include "vgic.h"
> +#include "vgic-mmio.h"
> +#include "sys_regs.h"
> +
> +static bool access_gic_ctlr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> + u64 val;
> + u32 ich_vtr;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + val = p->regval;
> + vmcr.ctlr &= ~(ICH_VMCR_CBPR_MASK | ICH_VMCR_EOIM_MASK);
> + vmcr.ctlr |= ((val & ICC_CTLR_EL1_CBPR_MASK) >>
> + ICC_CTLR_EL1_CBPR_SHIFT) << ICH_VMCR_CBPR_SHIFT;
> + vmcr.ctlr |= ((val & ICC_CTLR_EL1_EOImode_MASK) >>
> + ICC_CTLR_EL1_EOImode_SHIFT) << ICH_VMCR_EOIM_SHIFT;
> + vgic_set_vmcr(vcpu, &vmcr);
You've ignored my comments again: "What if userspace writes something
that is incompatible with the current configuration? Wrong number of ID
bits, or number of priorities?"
> + } else {
> + ich_vtr = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
> +
> + val = 0;
> + val |= ((ich_vtr & ICH_VTR_PRI_BITS_MASK) >>
> + ICH_VTR_PRI_BITS_SHIFT) << ICC_CTLR_EL1_PRI_BITS_SHIFT;
> + val |= ((ich_vtr & ICH_VTR_ID_BITS_MASK) >>
> + ICH_VTR_ID_BITS_SHIFT) << ICC_CTLR_EL1_ID_BITS_SHIFT;
> + val |= ((ich_vtr & ICH_VTR_SEIS_MASK) >> ICH_VTR_SEIS_SHIFT)
> + << ICC_CTLR_EL1_SEIS_SHIFT;
> + val |= ((ich_vtr & ICH_VTR_A3V_MASK) >> ICH_VTR_A3V_SHIFT)
> + << ICC_CTLR_EL1_A3V_SHIFT;
> + val |= ((vmcr.ctlr & ICH_VMCR_CBPR_MASK) >>
> + ICH_VMCR_CBPR_SHIFT) << ICC_CTLR_EL1_CBPR_SHIFT;
> + val |= ((vmcr.ctlr & ICH_VMCR_EOIM_MASK) >>
> + ICH_VMCR_EOIM_SHIFT) << ICC_CTLR_EL1_EOImode_SHIFT;
> +
> + p->regval = val;
> + }
> +
> + return true;
> +}
> +
> +static bool access_gic_pmr(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + vmcr.pmr = (p->regval & ICC_PMR_EL1_MASK) >> ICC_PMR_EL1_SHIFT;
> + vgic_set_vmcr(vcpu, &vmcr);
> + } else {
> + p->regval = (vmcr.pmr << ICC_PMR_EL1_SHIFT) & ICC_PMR_EL1_MASK;
> + }
> +
> + return true;
> +}
> +
> +static bool access_gic_bpr0(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + vmcr.bpr = (p->regval & ICC_BPR0_EL1_MASK) >>
> + ICC_BPR0_EL1_SHIFT;
> + vgic_set_vmcr(vcpu, &vmcr);
> + } else {
> + p->regval = (vmcr.bpr << ICC_BPR0_EL1_SHIFT) &
> + ICC_BPR0_EL1_MASK;
> + }
> +
> + return true;
> +}
> +
> +static bool access_gic_bpr1(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + vmcr.abpr = (p->regval & ICC_BPR1_EL1_MASK) >>
> + ICC_BPR1_EL1_SHIFT;
> + vgic_set_vmcr(vcpu, &vmcr);
> + } else {
> + p->regval = (vmcr.abpr << ICC_BPR1_EL1_SHIFT) &
> + ICC_BPR1_EL1_MASK;
> + }
> +
> + return true;
> +}
> +
> +static bool access_gic_grpen0(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + vmcr.grpen0 = (p->regval & ICC_IGRPEN0_EL1_MASK) >>
> + ICC_IGRPEN0_EL1_SHIFT;
> + vgic_set_vmcr(vcpu, &vmcr);
> + } else {
> + p->regval = (vmcr.grpen0 << ICC_IGRPEN0_EL1_SHIFT) &
> + ICC_IGRPEN0_EL1_MASK;
> + }
> +
> + return true;
> +}
> +
> +static bool access_gic_grpen1(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_vmcr vmcr;
> +
> + vgic_get_vmcr(vcpu, &vmcr);
> + if (p->is_write) {
> + vmcr.grpen1 = (p->regval & ICC_IGRPEN1_EL1_MASK) >>
> + ICC_IGRPEN1_EL1_SHIFT;
> + vgic_set_vmcr(vcpu, &vmcr);
> + } else {
> + p->regval = (vmcr.grpen1 << ICC_IGRPEN1_EL1_SHIFT) &
> + ICC_IGRPEN1_EL1_MASK;
>From the previous review comments: "Shouldn't this account for the
ICC_CTLR_EL1.CBPR setting?"
> + }
> +
> + return true;
> +}
> +
> +static void vgic_v3_access_apr_reg(struct kvm_vcpu *vcpu,
> + struct sys_reg_params *p, u8 apr, u8 idx)
> +{
> + struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3;
> + uint32_t *ap_reg;
> +
> + if (apr)
> + ap_reg = &vgicv3->vgic_ap1r[idx];
> + else
> + ap_reg = &vgicv3->vgic_ap0r[idx];
> +
> + if (p->is_write)
> + *ap_reg = p->regval;
> + else
> + p->regval = *ap_reg;
> +}
> +
> +static void access_gic_aprn(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r, u8 apr)
> +{
> + u8 num_pri_bits, idx;
> + u32 ich_vtr = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
Maybe you should cache this once and for all? It is fairly unlikely to
change over time...
> +
> +
> + num_pri_bits = ((ich_vtr & ICH_VTR_PRI_BITS_MASK) >>
> + ICH_VTR_PRI_BITS_SHIFT) + 1;
> + idx = r->Op2 & 3;
> +
> + switch (num_pri_bits) {
> + case 7:
> + if (idx > 3)
> + goto err;
> + vgic_v3_access_apr_reg(vcpu, p, apr, idx);
> + break;
> + case 6:
> + if (idx > 1)
> + goto err;
> + vgic_v3_access_apr_reg(vcpu, p, apr, idx);
> + break;
> + default:
> + if (idx > 0)
> + goto err;
> + vgic_v3_access_apr_reg(vcpu, p, apr, idx);
> + }
> +
> + return;
> +err:
> + if (!p->is_write)
> + p->regval = 0;
> +}
> +
> +static bool access_gic_ap0r(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + access_gic_aprn(vcpu, p, r, 0);
> +
> + return true;
> +}
> +
> +static bool access_gic_ap1r(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + access_gic_aprn(vcpu, p, r, 1);
> +
> + return true;
> +}
> +
> +static bool access_gic_sre(struct kvm_vcpu *vcpu, struct sys_reg_params *p,
> + const struct sys_reg_desc *r)
> +{
> + struct vgic_v3_cpu_if *vgicv3 = &vcpu->arch.vgic_cpu.vgic_v3;
> +
> + /* Read only. Write ignore */
> + if (!p->is_write)
> + p->regval = vgicv3->vgic_sre;
> +
> + return true;
> +}
> +
> +static const struct sys_reg_desc gic_v3_icc_reg_descs[] = {
> + /* ICC_PMR_EL1 */
> + { Op0(3), Op1(0), CRn(4), CRm(6), Op2(0), access_gic_pmr },
> + /* ICC_BPR0_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(8), Op2(3), access_gic_bpr0 },
> + /* ICC_AP0R0_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(8), Op2(4), access_gic_ap0r },
> + /* ICC_AP0R1_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(8), Op2(5), access_gic_ap0r },
> + /* ICC_AP0R2_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(8), Op2(6), access_gic_ap0r },
> + /* ICC_AP0R3_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(8), Op2(7), access_gic_ap0r },
> + /* ICC_AP1R0_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(9), Op2(0), access_gic_ap1r },
> + /* ICC_AP1R1_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(9), Op2(1), access_gic_ap1r },
> + /* ICC_AP1R2_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(9), Op2(2), access_gic_ap1r },
> + /* ICC_AP1R3_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(9), Op2(3), access_gic_ap1r },
> + /* ICC_BPR1_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(12), Op2(3), access_gic_bpr1 },
> + /* ICC_CTLR_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(12), Op2(4), access_gic_ctlr },
> + /* ICC_SRE_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(12), Op2(5), access_gic_sre },
> + /* ICC_IGRPEN0_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(12), Op2(6), access_gic_grpen0 },
> + /* ICC_GRPEN1_EL1 */
> + { Op0(3), Op1(0), CRn(12), CRm(12), Op2(7), access_gic_grpen1 },
> +};
> +
> +int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
> + u64 *reg)
> +{
> + struct sys_reg_params params;
> + u64 sysreg = (id & KVM_DEV_ARM_VGIC_SYSREG_MASK) | KVM_REG_SIZE_U64;
> +
> + params.regval = *reg;
> + params.is_write = is_write;
> + params.is_aarch32 = false;
> + params.is_32bit = false;
> +
> + if (find_reg_by_id(sysreg, ¶ms, gic_v3_icc_reg_descs,
> + ARRAY_SIZE(gic_v3_icc_reg_descs)))
> + return 0;
> +
> + return -ENXIO;
> +}
> +
> +int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write, u64 id,
> + u64 *reg)
> +{
> + struct sys_reg_params params;
> + const struct sys_reg_desc *r;
> + u64 sysreg = (id & KVM_DEV_ARM_VGIC_SYSREG_MASK) | KVM_REG_SIZE_U64;
> +
> + if (is_write)
> + params.regval = *reg;
> + params.is_write = is_write;
> + params.is_aarch32 = false;
> + params.is_32bit = false;
> +
> + r = find_reg_by_id(sysreg, ¶ms, gic_v3_icc_reg_descs,
> + ARRAY_SIZE(gic_v3_icc_reg_descs));
> + if (!r)
> + return -ENXIO;
> +
> + if (!r->access(vcpu, ¶ms, r))
> + return -EINVAL;
> +
> + if (!is_write)
> + *reg = params.regval;
> +
> + return 0;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 9ee54e3..4c0076c 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -30,6 +30,12 @@
>
> #define vgic_irq_is_sgi(intid) ((intid) < VGIC_NR_SGIS)
>
> +#define KVM_DEV_ARM_VGIC_SYSREG_MASK (KVM_REG_ARM64_SYSREG_OP0_MASK | \
> + KVM_REG_ARM64_SYSREG_OP1_MASK | \
> + KVM_REG_ARM64_SYSREG_CRN_MASK | \
> + KVM_REG_ARM64_SYSREG_CRM_MASK | \
> + KVM_REG_ARM64_SYSREG_OP2_MASK)
> +
> struct vgic_vmcr {
> u32 ctlr;
> u32 abpr;
> @@ -98,6 +104,10 @@ int vgic_v3_dist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> int offset, u32 *val);
> int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> int offset, u32 *val);
> +int vgic_v3_cpu_sysregs_uaccess(struct kvm_vcpu *vcpu, bool is_write,
> + u64 id, u64 *val);
> +int vgic_v3_has_cpu_sysregs_attr(struct kvm_vcpu *vcpu, bool is_write, u64 id,
> + u64 *reg);
> #else
> static inline int vgic_register_its_iodevs(struct kvm *kvm)
> {
>
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH v5 3/3] clk: imx6: Fix procedure to switch the parent of LDB_DI_CLK
From: Fabio Estevam @ 2016-09-16 14:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160916013621.GB7398@tiger>
On Thu, Sep 15, 2016 at 10:36 PM, Shawn Guo <shawnguo@kernel.org> wrote:
>> Shawn,
>>
>> Are you happy with it?
>
> Acked-by: Shawn Guo <shawnguo@kernel.org>
>
> Please send it to clk maintainers for applying.
Thanks. Just sent it to the clk folks.
^ permalink raw reply
* [GIT PULL] ARM: exynos: Fixes for v4.8, secound round
From: Arnd Bergmann @ 2016-09-16 14:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474009808-8520-1-git-send-email-k.kozlowski@samsung.com>
On Friday, September 16, 2016 9:10:08 AM CEST Krzysztof Kozlowski wrote:
> 1. A recent change in populating irqchip devices from Device Tree
> broke Suspend to RAM on Exynos boards due to lack of probing of
> PMU (Power Management Unit) driver. Multiple drivers attach to
> the PMU's DT node: irqchip, clock controller and PMU platform
> driver for handling suspend. The new irqchip code marked the
> PMU's DT node as OF_POPULATED but we need to attach to this
> node also PMU platform driver.
>
> 2. Add Javier as additional reviewer for Exynos patches.
>
Pulled into fixes, thanks!
Arnd
^ permalink raw reply
* [PATCH v3 1/3] tty: amba-pl011: define flag register bits for ZTE device
From: Sudeep Holla @ 2016-09-16 14:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1467968441-4056-2-git-send-email-shawn.guo@linaro.org>
Hi Shawn, Russell,
I noticed this change is in linux-next and but I happen to hit an issue
with this as I tested it with earlycon enabled today for the first time.
On 08/07/16 10:00, Shawn Guo wrote:
> For some reason we do not really understand, ZTE hardware designers
> choose to define PL011 Flag Register bit positions differently from
> standard ones as below.
>
> Bit Standard ZTE
> -----------------------------------
> CTS 0 1
> DSR 1 3
> BUSY 3 8
> RI 8 0
>
> Let's define these bits into vendor data and get ZTE PL011 supported
> properly.
>
> Signed-off-by: Shawn Guo <shawn.guo@linaro.org>
[...]
> @@ -2303,13 +2325,16 @@ static struct console amba_console = {
>
> static void pl011_putc(struct uart_port *port, int c)
> {
> + struct uart_amba_port *uap =
> + container_of(port, struct uart_amba_port, port);
> +
> while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF)
> cpu_relax();
> if (port->iotype == UPIO_MEM32)
> writel(c, port->membase + UART01x_DR);
> else
> writeb(c, port->membase + UART01x_DR);
> - while (readl(port->membase + UART01x_FR) & UART01x_FR_BUSY)
> + while (readl(port->membase + UART01x_FR) & uap->vendor->fr_busy)
> cpu_relax();
> }
The above hunk won't work for early console devices. The earlycon_device
just has uart_port and is not uart_amba_port. I don't know how to fix
this properly but I thought we could reuse private_data in uart_port for
early_con devices. Something like below(incomplete for other vendors,
works only for ARM)
Regards,
Sudeep
-->8
diff --git i/drivers/tty/serial/amba-pl011.c
w/drivers/tty/serial/amba-pl011.c
index 0b78b04e895e..abe88223790c 100644
--- i/drivers/tty/serial/amba-pl011.c
+++ w/drivers/tty/serial/amba-pl011.c
@@ -2330,8 +2330,7 @@ static struct console amba_console = {
static void pl011_putc(struct uart_port *port, int c)
{
- struct uart_amba_port *uap =
- container_of(port, struct uart_amba_port, port);
+ struct vendor_data *vendor = port->private_data;
while (readl(port->membase + UART01x_FR) & UART01x_FR_TXFF)
cpu_relax();
@@ -2339,7 +2338,7 @@ static void pl011_putc(struct uart_port *port, int c)
writel(c, port->membase + UART01x_DR);
else
writeb(c, port->membase + UART01x_DR);
- while (readl(port->membase + UART01x_FR) & uap->vendor->fr_busy)
+ while (readl(port->membase + UART01x_FR) & vendor->fr_busy)
cpu_relax();
}
@@ -2356,6 +2355,7 @@ static int __init pl011_early_console_setup(struct
earlycon_device *device,
if (!device->port.membase)
return -ENODEV;
+ device->port.private_data = &vendor_arm;
device->con->write = pl011_early_write;
return 0;
}
^ permalink raw reply related
* [PATCH v4 21/22] phy: Add support for Qualcomm's USB HSIC phy
From: Rob Herring @ 2016-09-16 14:21 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160907213519.27340-22-stephen.boyd@linaro.org>
On Wed, Sep 07, 2016 at 02:35:18PM -0700, Stephen Boyd wrote:
> The HSIC USB controller on qcom SoCs has an integrated all
> digital phy controlled via the ULPI viewport.
>
> Cc: Kishon Vijay Abraham I <kishon@ti.com>
> Cc: <devicetree@vger.kernel.org>
> Signed-off-by: Stephen Boyd <stephen.boyd@linaro.org>
> ---
> .../devicetree/bindings/phy/qcom,usb-hsic-phy.txt | 65 +++++++++
Acked-by: Rob Herring <robh@kernel.org>
> drivers/phy/Kconfig | 7 +
> drivers/phy/Makefile | 1 +
> drivers/phy/phy-qcom-usb-hsic.c | 160 +++++++++++++++++++++
> 4 files changed, 233 insertions(+)
> create mode 100644 Documentation/devicetree/bindings/phy/qcom,usb-hsic-phy.txt
> create mode 100644 drivers/phy/phy-qcom-usb-hsic.c
^ permalink raw reply
* [PATCH] pcie: qcom: add support to msm8996 PCIE controller
From: Rob Herring @ 2016-09-16 14:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1473246412-24616-1-git-send-email-srinivas.kandagatla@linaro.org>
On Wed, Sep 07, 2016 at 12:06:52PM +0100, Srinivas Kandagatla wrote:
> This patch adds support to msm8996/apq8096 pcie, MSM8996 supports
> Gen 1/2, One lane, 3 pcie root-complex with support to MSI and
> legacy interrupts and it conforms to PCI Express Base 2.1 specification.
>
> This patch adds post_init callback to qcom_pcie_ops, as this is pcie
> pipe clocks and smmu configuration are only setup after the phy is
> powered on. It also adds ltssm_enable callback as it is very much
> different to other supported SOCs in the driver.
>
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@linaro.org>
> ---
>
> I tested this patch along with phy driver patch on DB820c based on
> APQ8096 on port A and port B using sata and ethernet controllers.
>
> Thanks
> srini
>
> .../devicetree/bindings/pci/qcom,pcie.txt | 88 +++++++-
> drivers/pci/host/pcie-qcom.c | 237 ++++++++++++++++++++-
> 2 files changed, 318 insertions(+), 7 deletions(-)
>
> diff --git a/Documentation/devicetree/bindings/pci/qcom,pcie.txt b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
> index 4059a6f..1ddfcb4 100644
> --- a/Documentation/devicetree/bindings/pci/qcom,pcie.txt
> +++ b/Documentation/devicetree/bindings/pci/qcom,pcie.txt
> @@ -92,6 +92,18 @@
> - "aux" Auxiliary (AUX) clock
> - "bus_master" Master AXI clock
> - "bus_slave" Slave AXI clock
> +
> +- clock-names:
> + Usage: required for msm8996/apq8096
> + Value type: <stringlist>
> + Definition: Should contain the following entries
> + - "aux" Auxiliary (AUX) clock
> + - "bus_master" Master AXI clock
> + - "bus_slave" Slave AXI clock
> + - "pipe" Pipe Clock driving internal logic.
> + - "cfg" Configuration clk.
> + - "snoc_axi" SNOC AXI clk
> + - "cnoc_ahb" CNOC AHB clk
> - resets:
> Usage: required
> Value type: <prop-encoded-array>
> @@ -114,8 +126,15 @@
> Definition: Should contain the following entries
> - "core" Core reset
>
> +- iommus:
> + Usage: required for msm8996/apq8096
> + Value type: <prop-encoded-array>
> + Definition: Should point to the respective IOMMU block with master port
> + as argument, see Documentation/devicetree/bindings/iommu/
> + mediatek,iommu.txt for details.
> +
> - power-domains:
> - Usage: required for apq8084
> + Usage: required for apq8084 and msm8996/apq8096
> Value type: <prop-encoded-array>
> Definition: A phandle and power domain specifier pair to the
> power domain which is responsible for collapsing
> @@ -137,6 +156,11 @@
> Definition: A phandle to the analog power supply for IC which generates
> reference clock
>
> +- vdda_1p8-supply:
Don't use '_' in property names.
> + Usage: required for msm8996/apq8096
> + Value type: <phandle>
> + Definition: A phandle to the analog power supply for PCIE_1P8
> +
> - phys:
> Usage: required for apq8084
> Value type: <phandle>
> @@ -231,3 +255,65 @@
> pinctrl-0 = <&pcie0_pins_default>;
> pinctrl-names = "default";
> };
> +
> +* Example for apq8096:
> + pcie1: qcom,pcie at 00608000 {
pcie at ...
> + compatible = "qcom,pcie-msm8996", "snps,dw-pcie";
> + power-domains = <&gcc PCIE1_GDSC>;
> + bus-range = <0x00 0xff>;
> + num-lanes = <1>;
> +
> + status = "disabled";
> +
> + reg = <0x00608000 0x2000>,
> + <0x0d000000 0xf1d>,
> + <0x0d000f20 0xa8>,
> + <0x0d100000 0x100000>;
> +
> + reg-names = "parf", "dbi", "elbi","config";
> +
> + phys = <&pcie_phy 1>;
> + phy-names = "pciephy";
> +
> + #address-cells = <3>;
> + #size-cells = <2>;
> + ranges = <0x01000000 0x0 0x0d200000 0x0d200000 0x0 0x100000>,
> + <0x02000000 0x0 0x0d300000 0x0d300000 0x0 0xd00000>;
> +
> + interrupts = <GIC_SPI 413 IRQ_TYPE_NONE>;
> + interrupt-names = "msi";
> + #interrupt-cells = <1>;
> + interrupt-map-mask = <0 0 0 0x7>;
> + interrupt-map = <0 0 0 1 &intc 0 272 IRQ_TYPE_LEVEL_HIGH>, /* int_a */
> + <0 0 0 2 &intc 0 273 IRQ_TYPE_LEVEL_HIGH>, /* int_b */
> + <0 0 0 3 &intc 0 274 IRQ_TYPE_LEVEL_HIGH>, /* int_c */
> + <0 0 0 4 &intc 0 275 IRQ_TYPE_LEVEL_HIGH>; /* int_d */
> +
> + pinctrl-names = "default", "sleep";
> + pinctrl-0 = <&pcie1_clkreq_default &pcie1_perst_default &pcie1_wake_default>;
> + pinctrl-1 = <&pcie1_clkreq_sleep &pcie1_perst_default &pcie1_wake_sleep>;
> +
> +
> + vreg-1.8-supply = <&pm8994_l12>;
> + vreg-0.9-supply = <&pm8994_l28>;
Doesn't match binding?
> + iommus = <&anoc0_smmu>;
> +
> + linux,pci-domain = <1>;
> +
> + clocks = <&gcc GCC_PCIE_1_PIPE_CLK>,
> + <&gcc GCC_PCIE_1_AUX_CLK>,
> + <&gcc GCC_PCIE_1_CFG_AHB_CLK>,
> + <&gcc GCC_PCIE_1_MSTR_AXI_CLK>,
> + <&gcc GCC_PCIE_1_SLV_AXI_CLK>,
> + <&gcc GCC_AGGRE0_SNOC_AXI_CLK>,
> + <&gcc GCC_AGGRE0_CNOC_AHB_CLK>;
> +
> + clock-names = "pipe",
> + "aux",
> + "cfg",
> + "bus_master",
> + "bus_slave",
> + "snoc_axi",
> + "cnoc_ahb";
> +
> + };
^ permalink raw reply
* [PATCH v6 2/3] ARM: dts: add TOPEET itop elite based board
From: ayaka @ 2016-09-16 14:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <6bd9905d-0818-a917-8b8e-6abce134a3d3@kernel.org>
On 09/16/2016 03:23 PM, Krzysztof Kozlowski wrote:
> On 09/07/2016 11:58 PM, Randy Li wrote:
>> The TOPEET itop exynos 4412 have three versions base board. The
>> Elite version is the cheap one without too much peripheral devices
>> on it.
>>
>> Currently supported are serial console, wired networking(USB),
>> USB OTG in peripheral mode, USB host, SD storage, GPIO buttons,
>> PWM beeper, ADC and LEDs. The WM8960 analog audio codec is also
>> enabled.
>>
>> The FIMC is not used for camera currently, I enabled it just for a
>> colorspace convertor.
>>
>> Signed-off-by: Randy Li <ayaka@soulik.info>
>> ---
>> .../bindings/arm/samsung/samsung-boards.txt | 3 +
>> arch/arm/boot/dts/Makefile | 1 +
>> arch/arm/boot/dts/exynos4412-itop-elite.dts | 239 +++++++++++++++++++++
>> 3 files changed, 243 insertions(+)
>> create mode 100644 arch/arm/boot/dts/exynos4412-itop-elite.dts
>>
>> diff --git a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
>> index 0ea7f14..c7159ac 100644
>> --- a/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
>> +++ b/Documentation/devicetree/bindings/arm/samsung/samsung-boards.txt
>> @@ -22,6 +22,9 @@ Required root node properties:
>> * FriendlyARM
>> - "friendlyarm,tiny4412" - for Exynos4412-based FriendlyARM
>> TINY4412 board.
>> + * TOPEET
>> + - "topeet,itop4412-elite" - for Exynos4412-based TOPEET
>> + Elite base board.
>>
>> * Google
>> - "google,pi" - for Exynos5800-based Google Peach Pi
>> diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
>> index 207f96f..0b39d00 100644
>> --- a/arch/arm/boot/dts/Makefile
>> +++ b/arch/arm/boot/dts/Makefile
>> @@ -130,6 +130,7 @@ dtb-$(CONFIG_ARCH_EXYNOS4) += \
>> exynos4210-smdkv310.dtb \
>> exynos4210-trats.dtb \
>> exynos4210-universal_c210.dtb \
>> + exynos4412-itop-elite.dtb \
>> exynos4412-odroidu3.dtb \
>> exynos4412-odroidx.dtb \
>> exynos4412-odroidx2.dtb \
>> diff --git a/arch/arm/boot/dts/exynos4412-itop-elite.dts b/arch/arm/boot/dts/exynos4412-itop-elite.dts
>> new file mode 100644
>> index 0000000..dd83689
>> --- /dev/null
>> +++ b/arch/arm/boot/dts/exynos4412-itop-elite.dts
>> @@ -0,0 +1,239 @@
>> +/*
>> + * TOPEET's Exynos4412 based itop board device tree source
>> + *
>> + * Copyright (c) 2016 SUMOMO Computer Association
>> + * https://www.sumomo.mobi
>> + * Randy Li <ayaka@soulik.info>
>> + *
>> + * Device tree source file for TOPEET iTop Exynos 4412 core board
>> + * which is based on Samsung's Exynos4412 SoC.
>> + *
>> + * 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.
>> +*/
>> +
>> +/dts-v1/;
>> +#include <dt-bindings/sound/samsung-i2s.h>
>> +#include "exynos4412-itop-scp-core.dtsi"
>> +
>> +/ {
>> + model = "TOPEET iTop 4412 Elite board based on Exynos4412";
>> + compatible = "topeet,itop4412-elite", "samsung,exynos4412", "samsung,exynos4";
>> +
>> + chosen {
>> + bootargs = "root=/dev/mmcblk0p2 rw rootfstype=ext4 rootwait";
>> + stdout-path = "serial2:115200n8";
>> + };
>> +
>> + leds {
>> + compatible = "gpio-leds";
>> +
>> + led2 {
>> + label = "red:system";
>> + gpios = <&gpx1 0 GPIO_ACTIVE_HIGH>;
>> + default-state = "off";
>> + linux,default-trigger = "heartbeat";
>> + };
>> +
>> + led3 {
>> + label = "red:user";
>> + gpios = <&gpk1 1 GPIO_ACTIVE_HIGH>;
>> + default-state = "off";
>> + };
>> + };
>> +
>> + gpio-keys {
>> + compatible = "gpio-keys";
>> +
>> + home {
>> + label = "GPIO Key Home";
>> + linux,code = <KEY_HOME>;
>> + gpios = <&gpx1 1 GPIO_ACTIVE_LOW>;
>> + };
>> +
>> + back {
>> + label = "GPIO Key Back";
>> + linux,code = <KEY_BACK>;
>> + gpios = <&gpx1 2 GPIO_ACTIVE_LOW>;
>> + };
>> +
>> + sleep {
>> + label = "GPIO Key Sleep";
>> + linux,code = <KEY_POWER>;
>> + gpios = <&gpx3 3 GPIO_ACTIVE_LOW>;
>> + };
>> +
>> + vol-up {
>> + label = "GPIO Key Vol+";
>> + linux,code = <KEY_UP>;
>> + gpios = <&gpx2 1 GPIO_ACTIVE_LOW>;
>> + };
>> +
>> + vol-down {
>> + label = "GPIO Key Vol-";
>> + linux,code = <KEY_DOWN>;
>> + gpios = <&gpx2 0 GPIO_ACTIVE_LOW>;
>> + };
>> + };
>> +
>> + sound {
>> + compatible = "simple-audio-card";
>> + simple-audio-card,name = "wm-sound";
>> +
>> + assigned-clocks = <&clock_audss EXYNOS_MOUT_AUDSS>,
>> + <&clock_audss EXYNOS_MOUT_I2S>,
>> + <&clock_audss EXYNOS_DOUT_SRP>,
>> + <&clock_audss EXYNOS_DOUT_AUD_BUS>;
>> + assigned-clock-parents = <&clock CLK_FOUT_EPLL>,
>> + <&clock_audss EXYNOS_MOUT_AUDSS>;
>> + assigned-clock-rates = <0>,
>> + <0>,
>> + <112896000>,
>> + <11289600>;
>> +
>> + simple-audio-card,format = "i2s";
>> + simple-audio-card,bitclock-master = <&link0_codec>;
>> + simple-audio-card,frame-master = <&link0_codec>;
>> +
>> + simple-audio-card,widgets =
>> + "Microphone", "Mic Jack",
>> + "Line", "Line In",
>> + "Line", "Line Out",
>> + "Speaker", "Speaker",
>> + "Headphone", "Headphone Jack";
>> + simple-audio-card,routing =
>> + "Headphone Jack", "HP_L",
>> + "Headphone Jack", "HP_R",
>> + "Speaker", "SPK_LP",
>> + "Speaker", "SPK_LN",
>> + "Speaker", "SPK_RP",
>> + "Speaker", "SPK_RN",
>> + "LINPUT1", "Mic Jack",
>> + "LINPUT3", "Mic Jack",
>> + "RINPUT1", "Mic Jack",
>> + "RINPUT2", "Mic Jack";
>> +
>> + simple-audio-card,cpu {
>> + sound-dai = <&i2s0 0>;
>> + };
>> +
>> + link0_codec: simple-audio-card,codec {
>> + sound-dai = <&codec>;
>> + clocks = <&i2s0 CLK_I2S_CDCLK>;
>> + system-clock-frequency = <11289600>;
>> + };
>> + };
>> +
>> + beep {
>> + compatible = "pwm-beeper";
>> + pwms = <&pwm 0 4000000 PWM_POLARITY_INVERTED>;
> I have serious doubts that you run this code... if it does not even
> compile. Sorry, I cannot accept code that does not compile and was not
> tested.
>
> Please, test your DTS on top of current Linux tree, which would be one of:
> 1. Linus' master branch: v4.8-rc6,
> 2. one of my branches (for-next, next/dt etc),
When I sent those patches, I tested in "Add linux-next specific files
for 20160907"
> 3. recent linux-next.
>
> Best regards,
> Krzysztof
^ permalink raw reply
* [PATCH v5 4/6] arm/arm64: vgic-new: Introduce VENG0 and VENG1 fields to vmcr struct
From: Marc Zyngier @ 2016-09-16 13:54 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1474028453-29132-5-git-send-email-vijay.kilari@gmail.com>
On 16/09/16 13:20, vijay.kilari at gmail.com wrote:
> From: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
>
> ICC_VMCR_EL2 supports virtual access to ICC_IGRPEN1_EL1.Enable
> and ICC_IGRPEN0_EL1.Enable fields. Add grpen0 and grpen1 member
> variables to struct vmcr to support read and write of these fields.
>
> ICH_VMCR_CTLR_MASK is changed to mask only ICC_CTLR_EL1 fields.
This comment doesn't match the patch.
> Also refactor vgic_set_vmcr and vgic_get_vmcr() code.
>
> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@cavium.com>
> ---
> include/linux/irqchip/arm-gic-v3.h | 15 +++++++++++----
> virt/kvm/arm/vgic/vgic-mmio-v2.c | 16 ----------------
> virt/kvm/arm/vgic/vgic-mmio.c | 16 ++++++++++++++++
> virt/kvm/arm/vgic/vgic-v3.c | 10 ++++++++--
> virt/kvm/arm/vgic/vgic.h | 5 +++++
> 5 files changed, 40 insertions(+), 22 deletions(-)
>
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index 99ac022..88d83d3 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -352,8 +352,9 @@
> /*
> * CPU interface registers
> */
> -#define ICC_CTLR_EL1_EOImode_drop_dir (0U << 1)
> -#define ICC_CTLR_EL1_EOImode_drop (1U << 1)
> +#define ICC_CTLR_EL1_EOImode_SHIFT (1)
> +#define ICC_CTLR_EL1_EOImode_drop_dir (0U << ICC_CTLR_EL1_EOImode_SHIFT)
> +#define ICC_CTLR_EL1_EOImode_drop (1U << ICC_CTLR_EL1_EOImode_SHIFT)
> #define ICC_SRE_EL1_SRE (1U << 0)
>
> /*
> @@ -382,14 +383,20 @@
> #define ICH_HCR_EN (1 << 0)
> #define ICH_HCR_UIE (1 << 1)
>
> -#define ICH_VMCR_CTLR_SHIFT 0
> -#define ICH_VMCR_CTLR_MASK (0x21f << ICH_VMCR_CTLR_SHIFT)
> +#define ICH_VMCR_CBPR_SHIFT 4
> +#define ICH_VMCR_CBPR_MASK (1 << ICH_VMCR_CBPR_SHIFT)
> +#define ICH_VMCR_EOIM_SHIFT 9
> +#define ICH_VMCR_EOIM_MASK (1 << ICH_VMCR_EOIM_SHIFT)
> #define ICH_VMCR_BPR1_SHIFT 18
> #define ICH_VMCR_BPR1_MASK (7 << ICH_VMCR_BPR1_SHIFT)
> #define ICH_VMCR_BPR0_SHIFT 21
> #define ICH_VMCR_BPR0_MASK (7 << ICH_VMCR_BPR0_SHIFT)
> #define ICH_VMCR_PMR_SHIFT 24
> #define ICH_VMCR_PMR_MASK (0xffUL << ICH_VMCR_PMR_SHIFT)
> +#define ICH_VMCR_ENG0_SHIFT 0
> +#define ICH_VMCR_ENG0_MASK (1 << ICH_VMCR_ENG0_SHIFT)
> +#define ICH_VMCR_ENG1_SHIFT 1
> +#define ICH_VMCR_ENG1_MASK (1 << ICH_VMCR_ENG1_SHIFT)
>
> #define ICC_IAR1_EL1_SPURIOUS 0x3ff
I've asked you to make this a separate patch, which you've ignored.
Please make this change a separate patch, independent of any KVM change.
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply
* [PATCH v3 0/2] KVM: ARM: Enable vtimers with user space gic
From: Gerd Hoffmann @ 2016-09-16 13:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160916133027.GA27036@cbox>
Hi,
> That being said, I'm not categorically against these patches, but I
> share Marc's view that we've already seen that non-vgic support had been
> broken for multiple versions without anyone complaining,
Oh, did this ever work? Work as in "can actually run a virtual
machine", not as in "kvm doesn't throw an error on initialization".
> and without
> automated testing or substantial interest in the work, the patches
> really are likely to bit-rot.
Well, as far I know the rpi3 is the *only* aarch64 hardware which is
easily available and can (with these patches) run kvm.
More powerful stuff with more ram and sata storage and gbit network
(which I'd love to have to play with arm virt on real hardware) is
announced to be available really soon now since ... half a year at
least?
cheers,
Gerd
^ permalink raw reply
* [PATCH 4/7] phy: meson: add USB2 PHY support for Meson8b and GXBB
From: Arnd Bergmann @ 2016-09-16 13:47 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <57DBAB2F.3040905@ti.com>
On Friday, September 16, 2016 1:49:59 PM CEST Kishon Vijay Abraham I wrote:
>
> I think the offset information can come from the devicetree too. The phy can be
> modeled something like below.
>
> usb-phys at c0000000 {
> compatible = "amlogic,meson-gxbb-usb2-phy";
> reg = <0x0 0xc0000000 0x0 0x40>;
> #address-cells = <2>;
> #size-cells = <2>;
> ranges = <0x0 0x0 0x0 0xc0000000 0x0 0x40>;
> resets = <&reset 34>;
>
> usb0_phy: usb_phy at 0 {
> #phy-cells = <0>;
> reg = <0x0 0x0 0x0 0x20>;
> clocks = <&clkc CLKID_USB &clkc CLKID_USB0>;
> clock-names = "usb_general", "usb";
> status = "disabled";
> };
>
> usb1_phy: usb_phy at 20 {
> #phy-cells = <0>;
> reg = <0x0 0x20 0x0 0x20>;
> clocks = <&clkc CLKID_USB &clkc CLKID_USB1>;
> clock-names = "usb_general", "usb";
> status = "disabled";
> };
> };
>
> This way the driver will be probed only once (the reset can be done during
> probe). The phy driver should scan the dt node and for every sub-node it
> invokes phy_create?
Why not just use #phy-cells=<1> and pass the phy number as an argument
in the reference?
Arnd
^ permalink raw reply
* [PATCH v3 0/2] KVM: ARM: Enable vtimers with user space gic
From: Andrew Jones @ 2016-09-16 13:46 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160916133027.GA27036@cbox>
On Fri, Sep 16, 2016 at 03:30:27PM +0200, Christoffer Dall wrote:
> On Fri, Sep 16, 2016 at 02:31:42PM +0200, Paolo Bonzini wrote:
> >
> >
> > On 16/09/2016 14:30, Christoffer Dall wrote:
> > > > > > This patch set allows user space to receive vtimer events as well as mask
> > > > > > them, so that we can handle all vtimer related interrupt injection from user
> > > > > > space, enabling us to use architected timer with user space gic emulation.
> > > > >
> > > > > I have already voiced my concerns in the past, including face to face,
> > > > > and I'm going to repeat it: I not keen at all on adding a new userspace
> > > > > interface that is going to bitrot extremely quickly.
> > > >
> > > > You don't have automated tests set up? It's not going to bitrot if you
> > > > test it, either with kvm-unit-tests or just by smoke-testing Linux.
> > > > It's _for_ the raspi, but it's not limited to it.
> > >
> > > Our automated testing situation is not great, no. Something we're
> > > looking at, but have resource problems with.
> >
> > But it's not a good reason to hold back a feature...
> >
>
> I didn't say that exactly, but choosing not to merge something we cannot
> maintain and which we're not paid to look after and where there's a
> minimal interest, is not entirely unreasonable.
>
> That being said, I'm not categorically against these patches, but I
> share Marc's view that we've already seen that non-vgic support had been
> broken for multiple versions without anyone complaining, and without
> automated testing or substantial interest in the work, the patches
> really are likely to bit-rot.
>
> But I haven't even looked at the patches in detail, I was just replying
> to the comment about testing.
This may be a great time to start encouraging feature writers to submit
kvm-unit-tests patches at the same time as the feature (Hi Alex :-) I'm
happy to help when a test isn't easy to write due to a lack of framework,
but don't have nearly enough bandwidth to write all the tests myself.
As for additional motivation for this series, I'll point out that it's
good for bug isolation. When a guest fails to boot over KVM I can try
TCG. If that works, then I've likely narrowed it to KVM. If I can
further try kernel_irqchip=no, then I may further narrow it down to
the vgic implementation.
Thanks,
drew
^ permalink raw reply
* [GIT PULL 4/5] Freescale arm64 device tree updates for 4.9
From: Arnd Bergmann @ 2016-09-16 13:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160916014703.GC7398@tiger>
On Friday, September 16, 2016 9:47:03 AM CEST Shawn Guo wrote:
> On Wed, Sep 14, 2016 at 05:30:49PM +0200, Arnd Bergmann wrote:
> > On Monday, September 12, 2016 5:02:27 PM CEST Shawn Guo wrote:
> > > i.MX arm64 device tree changes for 4.9:
> > > - Add property dma-coherent for ls2080a PCI device to save software
> > > cache maintenance.
> > > - Update serial aliases and use stdout-path to sepecify console for
> > > ls2080a and ls1043a boards.
> > > - Add DDR memory controller device node for ls2080a and ls1043a SoCs.
> > >
> >
> > Pulled into next/dt64, thanks!
> >
> > The "dma-coherent" change sounds like a bugfix, should that be backported
> > to stable kernels? Usually if you lack that property on a device that
> > is actually coherent, you can get silent data corruption by treating it as
> > non-coherent.
>
> My impression is that those cache maintenance enforced for non-coherent
> device will hurt performance on coherent device. I don't know it will
> cause data corruption.
The problem is that the device in this case is accessing data from
the cache, while the CPU bypasses the cache for coherent mappings.
The cache might have a stale cache line as the device reads data, or
it could be in a writeback configuration, where the data written
from the device to the cache has not made it into RAM at the time it
is accessed by the CPU.
For streaming mappings, the CPU will invalidate cache lines
before reading the data, so again if the device has written data
into the cache but not yet into memory, we will see stale data
after dma_unmap_single().
Arnd
^ permalink raw reply
* [PATCH V6 2/5] PCI/ACPI: Check platform specific ECAM quirks
From: Gabriele Paoloni @ 2016-09-16 13:42 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <42c3f965-b40c-f2bb-e12c-34da6af1a4b7@codeaurora.org>
Hi Cov
> -----Original Message-----
> From: Christopher Covington [mailto:cov at codeaurora.org]
> Sent: 16 September 2016 13:28
> To: Gabriele Paoloni; Lorenzo Pieralisi; liudongdong (C)
> Cc: Tomasz Nowicki; helgaas at kernel.org; will.deacon at arm.com;
> catalin.marinas at arm.com; rafael at kernel.org; arnd at arndb.de;
> hanjun.guo at linaro.org; okaya at codeaurora.org; jchandra at broadcom.com;
> dhdang at apm.com; ard.biesheuvel at linaro.org;
> robert.richter at caviumnetworks.com; mw at semihalf.com;
> Liviu.Dudau at arm.com; ddaney at caviumnetworks.com; Wangyijing;
> msalter at redhat.com; linux-pci at vger.kernel.org; linux-arm-
> kernel at lists.infradead.org; linaro-acpi at lists.linaro.org;
> jcm at redhat.com; andrea.gallo at linaro.org; jeremy.linton at arm.com;
> jhugo at codeaurora.org; linux-acpi at vger.kernel.org; linux-
> kernel at vger.kernel.org
> Subject: Re: [PATCH V6 2/5] PCI/ACPI: Check platform specific ECAM
> quirks
>
> On 09/16/2016 05:02 AM, Gabriele Paoloni wrote:
> > Hi Lorenzo and Tomasz
> >
> > Many Thanks for looking at this
> >
> >> -----Original Message-----
> >> From: Lorenzo Pieralisi [mailto:lorenzo.pieralisi at arm.com]
> >> Sent: 15 September 2016 11:59
> >> To: liudongdong (C)
> >> Cc: Tomasz Nowicki; helgaas at kernel.org; will.deacon at arm.com;
> >> catalin.marinas at arm.com; rafael at kernel.org; arnd at arndb.de;
> >> hanjun.guo at linaro.org; okaya at codeaurora.org; jchandra at broadcom.com;
> >> cov at codeaurora.org; dhdang at apm.com; ard.biesheuvel at linaro.org;
> >> robert.richter at caviumnetworks.com; mw at semihalf.com;
> >> Liviu.Dudau at arm.com; ddaney at caviumnetworks.com; Wangyijing;
> >> msalter at redhat.com; linux-pci at vger.kernel.org; linux-arm-
> >> kernel at lists.infradead.org; linaro-acpi at lists.linaro.org;
> >> jcm at redhat.com; andrea.gallo at linaro.org; jeremy.linton at arm.com;
> >> Gabriele Paoloni; jhugo at codeaurora.org; linux-acpi at vger.kernel.org;
> >> linux-kernel at vger.kernel.org
> >> Subject: Re: [PATCH V6 2/5] PCI/ACPI: Check platform specific ECAM
> >> quirks
> >>
> >> On Tue, Sep 13, 2016 at 07:38:39PM +0800, Dongdong Liu wrote:
> >>
> >> [...]
> >>
> >>> Our host bridge is non ECAM only for the RC bus config space;
> >>> for any other bus underneath the root bus we support ECAM access.
> >>>
> >>> RC config resource with hardcode as DEFINE_RES_MEM(0xb0070000,
> >> SZ_4K),
> >>> EP config resource we get it from MCFG table.
> >>> So we need to override ops, but config resource we only need to
> >> hardcode with RC config resource.
> >>>
> >>> Our host controller ACPI support patch can be found:
> >>> https://lkml.org/lkml/2016/8/31/340
> >>
> >> Sorry I misread your code. IIUC you create an array of resources
> that
> >> represent non-ECAM config space (and incidentally contain debug
> >> registers to check the link status - that you need to check for
> every
> >> given config access (?)), but you still need to have an MCFG entry
> that
> >
> > The link status check is inherited from the designware framework (see
> > http://lxr.free-electrons.com/source/drivers/pci/host/pcie-
> designware.c#L678)
> >
> > However I think that in this case we can just check the link status
> > in our init function and return an error if the link is down
> >
> >> covers the bus number subject to quirk to make sure this mechanism
> >> works. Correct ?
> >
> > Well we need the quirks for the root bus numbers but if read this v6
> > quirk mechanism correctly even if we do not specify an mcfg entry for
> > bus 0 oci_mcfg_match_quirks() is called anyway and we can set our
> > special configuration space addresses for the root buses (i.e. I
> think
> > we can have a clean MCFG table with entries only for those bus ranges
> > that are really ECAM)
> >
> >>
> >> This also means that, with the MCFG tables you have and current
> >> mainline kernel you are able to probe a root bridge (because the
> MCFG
> >> table covers the bus number that is not ECAM), with enumeration
> >> going haywire because it is trying to carry out ECAM accesses on
> >> non-ECAM space.
> >
> > Yes correct, we cannot access the host controller configuration space
> > with our current MCFG table and current Linux mainline
> >
> >>
> >> Is my reading correct ?
> >>
> >> Anyway, that's not stricly related to this discussion, it is time we
> >> converge on this patchset, we can add a domain range if that
> >> simplifies things.
> >
> > IMO it would be better to have the domain range to avoid
> > a very large and repetitive static quirk array
>
> The v6 framework requires what, 21 additional lines of quirk data? What
> if you were to define some preprocessor macros to slim it down? I think
> something like the following would bring it down to roughly 7
> additional
> lines.
Thanks, yes this would work as well. To be honest this is not a big issue.
So either we go this way or we introduce domain range...
Cheers
Gab
>
> #define PCI_ACPI_QUIRK_QUAD_DOM(rev, dom, ops) \
> { "HISI ", rev, 0, dom+0, MCFG_BUS_ANY, ops,
> MCFG_RES_EMPTY}, \
> { "HISI ", rev, 0, dom+1, MCFG_BUS_ANY, ops,
> MCFG_RES_EMPTY}, \
> { "HISI ", rev, 0, dom+2, MCFG_BUS_ANY, ops,
> MCFG_RES_EMPTY}, \
> { "HISI ", rev, 0, dom+3, MCFG_BUS_ANY, ops,
> MCFG_RES_EMPTY},
>
> PCI_ACPI_QUIRK_QUAD_DOM("HIP05 ", 0, &hisi_pcie_hip05_ops)
> PCI_ACPI_QUIRK_QUAD_DOM("HIP06 ", 0, &hisi_pcie_hip05_ops)
> PCI_ACPI_QUIRK_QUAD_DOM("HIP07 ", 0, &hisi_pcie_hip06_ops)
> PCI_ACPI_QUIRK_QUAD_DOM("HIP07 ", 4, &hisi_pcie_hip07_ops)
> PCI_ACPI_QUIRK_QUAD_DOM("HIP07 ", 8, &hisi_pcie_hip07_ops)
> PCI_ACPI_QUIRK_QUAD_DOM("HIP07 ", 12, &hisi_pcie_hip07_ops)
>
> Cov
> --
> Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm
> Technologies, Inc. Qualcomm Technologies, Inc. is a member of the Code
> Aurora Forum, a Linux Foundation Collaborative Project.
^ permalink raw reply
* [PATCH v10 0/4] ACPI: parse the SPCR table
From: Aleksey Makarov @ 2016-09-16 13:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20160905123617.18775-1-aleksey.makarov@linaro.org>
+ CC: Lorenzo Pieralisi <lorenzo.pieralisi@arm.com>
On 09/05/2016 03:36 PM, Aleksey Makarov wrote:
> 'ARM Server Base Boot Requirements' [1] mentions SPCR (Serial Port Console
> Redirection Table) [2] as a mandatory ACPI table that specifies the
> configuration of serial console.
Hi Rafael,
Could you pull these patches please?
Each of them is ACKed now.
Thank you
Aleksey Makarov
> Move "earlycon" early_param handling to earlycon.c to parse this option once
>
> Parse SPCR table, setup earlycon and register specified console.
>
> Enable parsing this table on ARM64. Earlycon should be set up as early as
> possible. ACPI boot tables are mapped in
> arch/arm64/kernel/acpi.c:acpi_boot_table_init() called from setup_arch() and
> that's where we parse spcr. So it has to be opted-in per-arch. When
> ACPI_SPCR_TABLE is defined initialization of DT earlycon is deferred until the
> DT/ACPI decision is done.
>
> Implement console_match() for pl011.
>
> Based on the work by Leif Lindholm [3]
> Thanks to Peter Hurley for explaining how this should work.
>
> Should be applied to v4.8-rc5
> Tested on QEMU and ThunderX.
> SPCR support is included in QEMU's ARM64 mach-virt since 2.4 release.
>
> v10:
> - rebase to v4.8-rc5
> - fix the issue with comparing the console name in pl011_console_match()
> (Russell King)
> - fix build on sh arch (kbuild test robot)
> - add Acked-by: Russell King <rmk+kernel@armlinux.org.uk> for 4/4
> - add Tested-by: Christopher Covington <cov@codeaurora.org>
>
> v9:
> https://lkml.kernel.org/g/20160811153152.755-1-aleksey.makarov at linaro.org
> - rebase to v4.8-rc1
> - fix compilation for !CONFIG_SERIAL_EARLYCON case
> - add Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> for ACPI part
> - move constant check out of loop (Yury Norov)
> - add '\n' to info message
>
> v8:
> https://lkml.kernel.org/g/1463749405-11640-1-git-send-email-aleksey.makarov at linaro.org
> - rebase to next-20160520
> - remove the patch "ACPICA: Headers: Add new constants for the DBG2 ACPI table"
> as it have got to linux-next
> - add Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Reviewed-by:
> Peter Hurley <peter@hurleysoftware.com> (but see below)
> - fix the patch "serial: pl011: add console matching function". The patch by
> Christopher Covington [4] specifies that SBSA uart does 32-bit access to
> registers and this breaks the match function. In this series the function
> was changed to match when SPCR specifies both mmio32 and mmio access.
> I removed Acked-by: Greg from this patch because of these changes.
>
> v7:
> https://lkml.kernel.org/g/1459431629-27934-1-git-send-email-aleksey.makarov at linaro.org
> - add Acked-by: Rob Herring for "of/serial: move earlycon early_param handling
> to serial"
> - call DT earlycon initialization from the arch ACPI code, not from parse_spcr()
> (Rafael J. Wysocki)
> - fix a few minor issues (Rafael J. Wysocki)
>
> v6:
> https://lkml.kernel.org/g/1458823925-19560-1-git-send-email-aleksey.makarov at linaro.org
> - add documentation for parse_spcr() functioin (Yury Norov)
> - don't initialize err variable (Yury Norov)
> - add __initdata for the earlycon_init_is_deferred flag variable
> - rename the function exported in "of/serial: move earlycon early_param handling
> to serial" to avoid clash with the function from arch/microblaze/kernel/prom.c
> - defer initialization of DT earlycon until DT/ACPI decision is made
> (Rob Herring, Peter Hurley)
> - use snprintf instead of sprintf (Andy Shevchenko)
> - drop patch that adds EARLYCON_DECLARE for pl011 as EARLYCON_DECLARE is
> equivalent to OF_EARLYCON_DECLARE for 4.6+ (Peter Hurley). This means that
> SPCR earlycon will not work on the kernels before 4.6
>
> v5:
> https://lkml.kernel.org/g/1458643595-14719-1-git-send-email-aleksey.makarov at linaro.org
> - drop patch "serial: pl011: use ACPI SPCR to setup 32-bit access" because
> it is ugly. Also because Christopher Covington came with a better solution [4]
> - remove error message when the table is not provided by ACPI (Andy Shevchenko)
> - rewrite spcr.c following the suggestions by Peter Hurley
> - add console_match() for pl011 in a separate patch
> - add EARLYCON_DECLARE for pl011 in a separate patch
> - add patch "of/serial: move earlycon early_param handling to serial" from
> the GDB2 series
>
> v4:
> https://lkml.kernel.org/g/1456747355-15692-1-git-send-email-aleksey.makarov at linaro.org
> - drop patch "ACPI: change __init to __ref for early_acpi_os_unmap_memory()"
> ACPI developers work on a new API and asked not to do that.
> Instead, use acpi_get_table_with_size()/early_acpi_os_unmap_memory() once
> and cache the result. (Lv Zheng)
> - fix some style issues (Yury Norov)
>
> v3:
> https://lkml.kernel.org/g/1455559532-8305-1-git-send-email-aleksey.makarov at linaro.org
>
> Greg Kroah-Hartman did not like v2 so I have rewritten this patchset:
>
> - drop acpi_match() member of struct console
> - drop implementations of this member for pl011 and 8250
> - drop the patch that renames some vars in printk.c as it is not needed anymore
> - drop patch that introduces system wide acpi_table_parse2().
> Instead introduce a custom acpi_table_parse_spcr() in spcr.c
>
> Instead of introducing a new match_acpi() member of struct console,
> this patchset introduces a new function acpi_console_check().
> This function is called when a new uart is registered at serial_core.c
> the same way OF code checks for console. If the registered uart is the
> console specified by SPCR table, this function calls add_preferred_console()
>
> The restrictions of this approach are:
>
> - only serial consoles can be set up
> - only consoles specified by the memory/io address can be set up
> (SPCR can specify devices by PCI id/PCI address)
>
> v2:
> https://lkml.kernel.org/g/1455299022-11641-1-git-send-email-aleksey.makarov at linaro.org
> - don't use SPCR if user specified console in command line
> - fix initialization order of newcon->index = 0
> - rename some variables at printk.c (Joe Perches, Peter Hurley)
> - enable ACPI_SPCR_TABLE in a separate patch (Andy Shevchenko)
> - remove the retry loop for console registering (Peter Hurley).
> Instead, obtain SPCR with acpi_get_table(). That works after
> call to acpi_early_init() i. e. in any *_initcall()
> - describe design decision behind introducing acpi_match() (Peter Hurley)
> - fix compilation for x86 + ACPI (Graeme Gregory)
> - introduce DBG2 constants in a separate patch (Andy Shevchenko)
> - fix a typo in DBG2 constants (Andy Shevchenko)
> - add ACPI_DBG2_ARM_SBSA_32BIT constant (Christopher Covington)
> - add support for ACPI_DBG2_ARM_SBSA_* consoles (Christopher Covington)
> - add documentation for functions
> - add a patch that uses SPCR to find if SBSA serial driver should use 32-bit
> accessor functions (Christopher Covington)
> - change __init to __ref for early_acpi_os_unmap_memory() in a separate patch
> - introduce acpi_table_parse2() in a separate patch
> - fix fetching the SPCR table early (Mark Salter)
> - add a patch from Mark Salter that introduces support for matching 8250-based
> consoles
>
> v1:
> https://lkml.kernel.org/g/1453722324-22407-1-git-send-email-aleksey.makarov at linaro.org
>
> [1] http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.den0044a/index.html
> [2] https://msdn.microsoft.com/en-us/library/windows/hardware/dn639132(v=vs.85).aspx
> [3] https://lkml.kernel.org/g/1441716217-23786-1-git-send-email-leif.lindholm at linaro.org
> [4] https://lkml.kernel.org/g/1457415800-8799-1-git-send-email-cov at codeaurora.org
>
> Aleksey Makarov (3):
> ACPI: parse SPCR and enable matching console
> ARM64: ACPI: enable ACPI_SPCR_TABLE
> serial: pl011: add console matching function
>
> Leif Lindholm (1):
> of/serial: move earlycon early_param handling to serial
>
> arch/arm64/Kconfig | 1 +
> arch/arm64/kernel/acpi.c | 11 +++-
> drivers/acpi/Kconfig | 3 ++
> drivers/acpi/Makefile | 1 +
> drivers/acpi/spcr.c | 111 ++++++++++++++++++++++++++++++++++++++++
> drivers/of/fdt.c | 11 +---
> drivers/tty/serial/amba-pl011.c | 55 ++++++++++++++++++++
> drivers/tty/serial/earlycon.c | 19 ++++++-
> include/linux/acpi.h | 6 +++
> include/linux/of_fdt.h | 3 ++
> include/linux/serial_core.h | 9 +++-
> 11 files changed, 216 insertions(+), 14 deletions(-)
> create mode 100644 drivers/acpi/spcr.c
>
^ permalink raw reply
* [PATCH v1 3/3] ARM: dts: imx6qdl-apalis: Use enable-gpios property for backlight
From: Marcel Ziswiler @ 2016-09-16 13:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <dff8d58c4021719184af2c83773e86f175ad910e.1473833908.git.maitysanchayan@gmail.com>
On Wed, 2016-09-14 at 12:05 +0530, Sanchayan Maity wrote:
> Use enable-gpios property of PWM backlight driver for backlight
> control. While at it also fix the use of brightness levels required
> by EDT displays which require inverted PWM's.
That part I am missing below. Did you forget to include it?
> Signed-off-by: Sanchayan Maity <maitysanchayan@gmail.com>
> ---
> ?arch/arm/boot/dts/imx6qdl-apalis.dtsi | 9 +++++++++
> ?1 file changed, 9 insertions(+)
>
> diff --git a/arch/arm/boot/dts/imx6qdl-apalis.dtsi
> b/arch/arm/boot/dts/imx6qdl-apalis.dtsi
> index 8c67dd8..9100bde 100644
> --- a/arch/arm/boot/dts/imx6qdl-apalis.dtsi
> +++ b/arch/arm/boot/dts/imx6qdl-apalis.dtsi
> @@ -49,7 +49,10 @@
> ?
> ? backlight: backlight {
> ? compatible = "pwm-backlight";
> + pinctrl-names = "default";
> + pinctrl-0 = <&pinctrl_gpio_bl_on>;
> ? pwms = <&pwm4 0 5000000>;
> + enable-gpios = <&gpio3 13 GPIO_ACTIVE_HIGH>;
> ? status = "disabled";
> ? };
> ?
> @@ -614,6 +617,12 @@
> ? >;
> ? };
> ?
> + pinctrl_gpio_bl_on: gpioblon {
> + fsl,pins = <
> + MX6QDL_PAD_EIM_DA13__GPIO3_IO13 0x1b0b0
> + >;
> + };
> +
> ? pinctrl_gpio_keys: gpio1io04grp {
> ? fsl,pins = <
> ? /* Power button */
^ permalink raw reply
* [PATCH v1 2/3] ARM: dts: imx6q-apalis-ixora: Remove use of pwm-leds
From: Marcel Ziswiler @ 2016-09-16 13:38 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <6111feb57b5fbaa29eeb6ba089bb2824bbf2f8ff.1473833908.git.maitysanchayan@gmail.com>
On Wed, 2016-09-14 at 12:05 +0530, Sanchayan Maity wrote:
> Remove use of pwm-leds and use the standard /sys/class/pwm
> interface from PWM subsystem.
>
> Signed-off-by: Sanchayan Maity <maitysanchayan@gmail.com>
Acked-by: Marcel Ziswiler <marcel.ziswiler@toradex.com>
> ---
> ?arch/arm/boot/dts/imx6q-apalis-ixora.dts | 22 ----------------------
> ?1 file changed, 22 deletions(-)
>
> diff --git a/arch/arm/boot/dts/imx6q-apalis-ixora.dts
> b/arch/arm/boot/dts/imx6q-apalis-ixora.dts
> index d99979e..70a3da0 100644
> --- a/arch/arm/boot/dts/imx6q-apalis-ixora.dts
> +++ b/arch/arm/boot/dts/imx6q-apalis-ixora.dts
> @@ -146,28 +146,6 @@
> ? gpios = <&gpio2 2 GPIO_ACTIVE_HIGH>;
> ? };
> ? };
> -
> - pwmleds {
> - compatible = "pwm-leds";
> -
> - ledpwm1 {
> - label = "PWM1";
> - pwms = <&pwm1 0 50000>;
> - max-brightness = <255>;
> - };
> -
> - ledpwm2 {
> - label = "PWM2";
> - pwms = <&pwm2 0 50000>;
> - max-brightness = <255>;
> - };
> -
> - ledpwm3 {
> - label = "PWM3";
> - pwms = <&pwm3 0 50000>;
> - max-brightness = <255>;
> - };
> - };
> ?};
> ?
> ?&backlight {
Tested working fine analogous to what we documented for Vybrid:
http://developer.toradex.com/knowledge-base/pwm-(linux)#Colibri_VFxx
^ 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