* [PATCH 5/5] ARM: dts: imx28-cfa10049: Move i2cmux out of bus node
From: Maxime Ripard @ 2018-01-04 12:53 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1514383478-32544-5-git-send-email-festevam@gmail.com>
On Wed, Dec 27, 2017 at 12:04:38PM -0200, Fabio Estevam wrote:
> From: Fabio Estevam <fabio.estevam@nxp.com>
>
> Move i2cmux node from soc node to root node.
>
> i2cmux node does not have any register properties and thus shouldn't be
> placed on the bus.
>
> This fixes the following build warnings with W=1:
>
> arch/arm/boot/dts/imx28-cfa10049.dtb: Warning (simple_bus_reg): Node /apb at 80000000/apbx at 80040000/i2cmux missing or empty reg/ranges property
>
> Cc: Maxime Ripard <maxime.ripard@free-electrons.com>
> Signed-off-by: Fabio Estevam <fabio.estevam@nxp.com>
Acked-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180104/6213d373/attachment-0001.sig>
^ permalink raw reply
* [PATCH 12/12] clocksource/drivers/stm32: Start the timer's counter sooner
From: Daniel Lezcano @ 2018-01-04 12:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515070228-10481-1-git-send-email-daniel.lezcano@linaro.org>
As we have a lot of timers on this platform, we can have potentially all the
timers enabled in the DT, so we don't want to start the timer for every probe
otherwise they will be running for nothing as only one will be used.
Start the timer only when setting the mode or when the clocksource is
enabled.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/clocksource/timer-stm32.c | 21 ++++++++++++++++++---
1 file changed, 18 insertions(+), 3 deletions(-)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index dcf8445..4ce2345 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -101,7 +101,15 @@ static void stm32_clock_event_disable(struct timer_of *to)
writel_relaxed(0, timer_of_base(to) + TIM_DIER);
}
-static void stm32_clock_event_enable(struct timer_of *to)
+/**
+ * stm32_timer_start - Start the counter without event
+ * @to: a timer_of structure pointer
+ *
+ * Start the timer in order to have the counter reset and start
+ * incrementing but disable interrupt event when there is a counter
+ * overflow. By default, the counter direction is used as upcounter.
+ */
+static void stm32_timer_start(struct timer_of *to)
{
writel_relaxed(TIM_CR1_UDIS | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
}
@@ -137,7 +145,7 @@ static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
{
struct timer_of *to = to_timer_of(clkevt);
- stm32_clock_event_enable(to);
+ stm32_timer_start(to);
return stm32_clock_event_set_next_event(timer_of_period(to), clkevt);
}
@@ -146,7 +154,7 @@ static int stm32_clock_event_set_oneshot(struct clock_event_device *clkevt)
{
struct timer_of *to = to_timer_of(clkevt);
- stm32_clock_event_enable(to);
+ stm32_timer_start(to);
return 0;
}
@@ -235,6 +243,13 @@ static int __init stm32_clocksource_init(struct timer_of *to)
* sched_clock.
*/
if (bits == 32 && !stm32_timer_cnt) {
+
+ /*
+ * Start immediately the counter as we will be using
+ * it right after.
+ */
+ stm32_timer_start(to);
+
stm32_timer_cnt = timer_of_base(to) + TIM_CNT;
sched_clock_register(stm32_read_sched_clock, bits, timer_of_rate(to));
pr_info("%s: STM32 sched_clock registered\n", name);
--
2.7.4
^ permalink raw reply related
* [PATCH 11/12] clocksource/drivers/stm32: Add the timer delay
From: Daniel Lezcano @ 2018-01-04 12:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515070228-10481-1-git-send-email-daniel.lezcano@linaro.org>
Add the timer delay, that saves us ~90ms of boot time.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/clocksource/timer-stm32.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 4634f4d..dcf8445 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -9,6 +9,7 @@
#include <linux/kernel.h>
#include <linux/clocksource.h>
#include <linux/clockchips.h>
+#include <linux/delay.h>
#include <linux/irq.h>
#include <linux/interrupt.h>
#include <linux/of.h>
@@ -88,6 +89,13 @@ static u64 notrace stm32_read_sched_clock(void)
return readl_relaxed(stm32_timer_cnt);
}
+static struct delay_timer stm32_timer_delay;
+
+static unsigned long stm32_read_delay(void)
+{
+ return readl_relaxed(stm32_timer_cnt);
+}
+
static void stm32_clock_event_disable(struct timer_of *to)
{
writel_relaxed(0, timer_of_base(to) + TIM_DIER);
@@ -230,6 +238,11 @@ static int __init stm32_clocksource_init(struct timer_of *to)
stm32_timer_cnt = timer_of_base(to) + TIM_CNT;
sched_clock_register(stm32_read_sched_clock, bits, timer_of_rate(to));
pr_info("%s: STM32 sched_clock registered\n", name);
+
+ stm32_timer_delay.read_current_timer = stm32_read_delay;
+ stm32_timer_delay.freq = timer_of_rate(to);
+ register_current_timer_delay(&stm32_timer_delay);
+ pr_info("%s: STM32 delay timer registered\n", name);
}
return clocksource_mmio_init(timer_of_base(to) + TIM_CNT, name,
--
2.7.4
^ permalink raw reply related
* [PATCH 10/12] clocksource/drivers/stm32: Add the clocksource
From: Daniel Lezcano @ 2018-01-04 12:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515070228-10481-1-git-send-email-daniel.lezcano@linaro.org>
From: Benjamin Gaignard <benjamin.gaignard@st.com>
The scene is set for the clocksource, let's add it for this driver.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/clocksource/timer-stm32.c | 37 +++++++++++++++++++++++++++++++++++++
1 file changed, 37 insertions(+)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 1891924..4634f4d 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -16,6 +16,7 @@
#include <linux/of_irq.h>
#include <linux/clk.h>
#include <linux/reset.h>
+#include <linux/sched_clock.h>
#include <linux/slab.h>
#include "timer-of.h"
@@ -80,6 +81,13 @@ static int stm32_timer_of_bits_get(struct timer_of *to)
return pd->bits;
}
+static void __iomem *stm32_timer_cnt __read_mostly;
+
+static u64 notrace stm32_read_sched_clock(void)
+{
+ return readl_relaxed(stm32_timer_cnt);
+}
+
static void stm32_clock_event_disable(struct timer_of *to)
{
writel_relaxed(0, timer_of_base(to) + TIM_DIER);
@@ -204,6 +212,31 @@ static void __init stm32_timer_set_prescaler(struct timer_of *to)
to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
}
+static int __init stm32_clocksource_init(struct timer_of *to)
+{
+ u32 bits = stm32_timer_of_bits_get(to);
+ const char *name = to->np->full_name;
+
+ /*
+ * This driver allows to register several timers and relies on
+ * the generic time framework to select the right one.
+ * However, nothing allows to do the same for the
+ * sched_clock. We are not interested in a sched_clock for the
+ * 16bits timers but only for the 32bits, so if no 32bits
+ * timer registered yet, we select this 32bits timer as a
+ * sched_clock.
+ */
+ if (bits == 32 && !stm32_timer_cnt) {
+ stm32_timer_cnt = timer_of_base(to) + TIM_CNT;
+ sched_clock_register(stm32_read_sched_clock, bits, timer_of_rate(to));
+ pr_info("%s: STM32 sched_clock registered\n", name);
+ }
+
+ return clocksource_mmio_init(timer_of_base(to) + TIM_CNT, name,
+ timer_of_rate(to), bits == 32 ? 250 : 100,
+ bits, clocksource_mmio_readl_up);
+}
+
static void __init stm32_clockevent_init(struct timer_of *to)
{
u32 bits = stm32_timer_of_bits_get(to);
@@ -256,6 +289,10 @@ static int __init stm32_timer_init(struct device_node *node)
stm32_timer_set_prescaler(to);
+ ret = stm32_clocksource_init(to);
+ if (ret)
+ goto deinit;
+
stm32_clockevent_init(to);
return 0;
--
2.7.4
^ permalink raw reply related
* [PATCH 09/12] clocksource/drivers/stm32: Encapsulate more the clockevent code
From: Daniel Lezcano @ 2018-01-04 12:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515070228-10481-1-git-send-email-daniel.lezcano@linaro.org>
In order to prepare the clocksource code, let's encapsulate the clockevent
code, split the prescaler and timer width code into separate functions.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/clocksource/timer-stm32.c | 107 +++++++++++++++++++++++++++++---------
1 file changed, 82 insertions(+), 25 deletions(-)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index baca42c..1891924 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -44,6 +44,42 @@
#define TIM_PSC_MAX USHRT_MAX
#define TIM_PSC_CLKRATE 10000
+struct stm32_timer_private {
+ int bits;
+};
+
+/**
+ * stm32_timer_of_bits_set - set accessor helper
+ * @to: a timer_of structure pointer
+ * @bits: the number of bits (16 or 32)
+ *
+ * Accessor helper to set the number of bits in the timer-of private
+ * structure.
+ *
+ */
+static void stm32_timer_of_bits_set(struct timer_of *to, int bits)
+{
+ struct stm32_timer_private *pd = to->private_data;
+
+ pd->bits = bits;
+}
+
+/**
+ * stm32_timer_of_bits_get - get accessor helper
+ * @to: a timer_of structure pointer
+ *
+ * Accessor helper to get the number of bits in the timer-of private
+ * structure.
+ *
+ * Returns an integer corresponding to the number of bits.
+ */
+static int stm32_timer_of_bits_get(struct timer_of *to)
+{
+ struct stm32_timer_private *pd = to->private_data;
+
+ return pd->bits;
+}
+
static void stm32_clock_event_disable(struct timer_of *to)
{
writel_relaxed(0, timer_of_base(to) + TIM_DIER);
@@ -124,35 +160,31 @@ static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
* is a 32bits width, the result will be UINT_MAX, otherwise it will
* be truncated by the 16bits register to USHRT_MAX.
*
- * Returns UINT_MAX if the timer is 32bits width, USHRT_MAX if it is a
- * 16bits width.
*/
-static u32 __init stm32_timer_width(struct timer_of *to)
+static void __init stm32_timer_set_width(struct timer_of *to)
{
+ u32 width;
+
writel_relaxed(UINT_MAX, timer_of_base(to) + TIM_ARR);
- return readl_relaxed(timer_of_base(to) + TIM_ARR);
+ width = readl_relaxed(timer_of_base(to) + TIM_ARR);
+
+ stm32_timer_of_bits_set(to, width == UINT_MAX ? 32 : 16);
}
-static void __init stm32_clockevent_init(struct timer_of *to)
+/**
+ * stm32_timer_set_prescaler - Compute and set the prescaler register
+ * @to: a pointer to a timer-of structure
+ *
+ * Depending on the timer width, compute the prescaler to always
+ * target a 10MHz timer rate for the 16bits. 32bits timers are
+ * considered precise and long enough to not use the prescaler.
+ */
+static void __init stm32_timer_set_prescaler(struct timer_of *to)
{
- u32 width = 0;
- int prescaler;
+ int prescaler = 1;
- to->clkevt.name = to->np->full_name;
- to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
- to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
- to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
- to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
- to->clkevt.set_state_oneshot = stm32_clock_event_set_oneshot;
- to->clkevt.tick_resume = stm32_clock_event_shutdown;
- to->clkevt.set_next_event = stm32_clock_event_set_next_event;
-
- width = stm32_timer_width(to);
- if (width == UINT_MAX) {
- prescaler = 1;
- to->clkevt.rating = 250;
- } else {
+ if (stm32_timer_of_bits_get(to) != 32) {
prescaler = DIV_ROUND_CLOSEST(timer_of_rate(to),
TIM_PSC_CLKRATE);
/*
@@ -161,7 +193,6 @@ static void __init stm32_clockevent_init(struct timer_of *to)
* this case.
*/
prescaler = prescaler < TIM_PSC_MAX ? prescaler : TIM_PSC_MAX;
- to->clkevt.rating = 100;
}
writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
@@ -171,12 +202,26 @@ static void __init stm32_clockevent_init(struct timer_of *to)
/* Adjust rate and period given the prescaler value */
to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);
to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
+}
+
+static void __init stm32_clockevent_init(struct timer_of *to)
+{
+ u32 bits = stm32_timer_of_bits_get(to);
- clockevents_config_and_register(&to->clkevt,
- timer_of_rate(to), 0x1, width);
+ to->clkevt.name = to->np->full_name;
+ to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+ to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
+ to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
+ to->clkevt.set_state_oneshot = stm32_clock_event_set_oneshot;
+ to->clkevt.tick_resume = stm32_clock_event_shutdown;
+ to->clkevt.set_next_event = stm32_clock_event_set_next_event;
+ to->clkevt.rating = bits == 32 ? 250 : 100;
+
+ clockevents_config_and_register(&to->clkevt, timer_of_rate(to), 0x1,
+ (1 << bits) - 1);
pr_info("%pOF: STM32 clockevent driver initialized (%d bits)\n",
- to->np, width == UINT_MAX ? 32 : 16);
+ to->np, bits);
}
static int __init stm32_timer_init(struct device_node *node)
@@ -196,14 +241,26 @@ static int __init stm32_timer_init(struct device_node *node)
if (ret)
goto err;
+ to->private_data = kzalloc(sizeof(struct stm32_timer_private),
+ GFP_KERNEL);
+ if (!to->private_data)
+ goto deinit;
+
rstc = of_reset_control_get(node, NULL);
if (!IS_ERR(rstc)) {
reset_control_assert(rstc);
reset_control_deassert(rstc);
}
+ stm32_timer_set_width(to);
+
+ stm32_timer_set_prescaler(to);
+
stm32_clockevent_init(to);
return 0;
+
+deinit:
+ timer_of_cleanup(to);
err:
kfree(to);
return ret;
--
2.7.4
^ permalink raw reply related
* [PATCH 08/12] clocksource/drivers/stm32: Add the oneshot mode
From: Daniel Lezcano @ 2018-01-04 12:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515070228-10481-1-git-send-email-daniel.lezcano@linaro.org>
From: Benjamin Gaignard <benjamin.gaignard@st.com>
The stm32 timer block is able to have a counter and a comparator.
Instead of using the auto-reload register for periodic event, we switch
to the oneshot mode by using the comparator register.
The timer is able to generate an interrupt when the counter overflows but
we don't want that as this counter will be use as a clocksource in the next
patches. So it is disabled by the UDIS bit of the control register.
[Daniel Lezcano]: Modified the changelog and splitted the oneshot mode from
the original patch in order to provide one feature at a time.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/clocksource/timer-stm32.c | 56 ++++++++++++++++++++++++++++++---------
1 file changed, 44 insertions(+), 12 deletions(-)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index ac55896..baca42c 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -24,14 +24,18 @@
#define TIM_DIER 0x0c
#define TIM_SR 0x10
#define TIM_EGR 0x14
+#define TIM_CNT 0x24
#define TIM_PSC 0x28
#define TIM_ARR 0x2c
+#define TIM_CCR1 0x34
#define TIM_CR1_CEN BIT(0)
+#define TIM_CR1_UDIS BIT(1)
#define TIM_CR1_OPM BIT(3)
#define TIM_CR1_ARPE BIT(7)
#define TIM_DIER_UIE BIT(0)
+#define TIM_DIER_CC1IE BIT(1)
#define TIM_SR_UIF BIT(0)
@@ -40,33 +44,57 @@
#define TIM_PSC_MAX USHRT_MAX
#define TIM_PSC_CLKRATE 10000
+static void stm32_clock_event_disable(struct timer_of *to)
+{
+ writel_relaxed(0, timer_of_base(to) + TIM_DIER);
+}
+
+static void stm32_clock_event_enable(struct timer_of *to)
+{
+ writel_relaxed(TIM_CR1_UDIS | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
+}
+
static int stm32_clock_event_shutdown(struct clock_event_device *clkevt)
{
struct timer_of *to = to_timer_of(clkevt);
- writel_relaxed(0, timer_of_base(to) + TIM_CR1);
+ stm32_clock_event_disable(to);
return 0;
}
-static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
+static int stm32_clock_event_set_next_event(unsigned long evt,
+ struct clock_event_device *clkevt)
{
struct timer_of *to = to_timer_of(clkevt);
+ unsigned long now, next;
+
+ next = readl_relaxed(timer_of_base(to) + TIM_CNT) + evt;
+ writel_relaxed(next, timer_of_base(to) + TIM_CCR1);
+ now = readl_relaxed(timer_of_base(to) + TIM_CNT);
+
+ if ((next - now) > evt)
+ return -ETIME;
- writel_relaxed(timer_of_period(to), timer_of_base(to) + TIM_ARR);
- writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
+ writel_relaxed(TIM_DIER_CC1IE, timer_of_base(to) + TIM_DIER);
return 0;
}
-static int stm32_clock_event_set_next_event(unsigned long evt,
- struct clock_event_device *clkevt)
+static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
+{
+ struct timer_of *to = to_timer_of(clkevt);
+
+ stm32_clock_event_enable(to);
+
+ return stm32_clock_event_set_next_event(timer_of_period(to), clkevt);
+}
+
+static int stm32_clock_event_set_oneshot(struct clock_event_device *clkevt)
{
struct timer_of *to = to_timer_of(clkevt);
- writel_relaxed(evt, timer_of_base(to) + TIM_ARR);
- writel_relaxed(TIM_CR1_ARPE | TIM_CR1_OPM | TIM_CR1_CEN,
- timer_of_base(to) + TIM_CR1);
+ stm32_clock_event_enable(to);
return 0;
}
@@ -78,6 +106,11 @@ static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
writel_relaxed(0, timer_of_base(to) + TIM_SR);
+ if (clockevent_state_periodic(clkevt))
+ stm32_clock_event_set_periodic(clkevt);
+ else
+ stm32_clock_event_shutdown(clkevt);
+
clkevt->event_handler(clkevt);
return IRQ_HANDLED;
@@ -108,9 +141,10 @@ static void __init stm32_clockevent_init(struct timer_of *to)
to->clkevt.name = to->np->full_name;
to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
+ to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
- to->clkevt.set_state_oneshot = stm32_clock_event_shutdown;
+ to->clkevt.set_state_oneshot = stm32_clock_event_set_oneshot;
to->clkevt.tick_resume = stm32_clock_event_shutdown;
to->clkevt.set_next_event = stm32_clock_event_set_next_event;
@@ -129,12 +163,10 @@ static void __init stm32_clockevent_init(struct timer_of *to)
prescaler = prescaler < TIM_PSC_MAX ? prescaler : TIM_PSC_MAX;
to->clkevt.rating = 100;
}
- writel_relaxed(0, timer_of_base(to) + TIM_ARR);
writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
writel_relaxed(TIM_EGR_UG, timer_of_base(to) + TIM_EGR);
writel_relaxed(0, timer_of_base(to) + TIM_SR);
- writel_relaxed(TIM_DIER_UIE, timer_of_base(to) + TIM_DIER);
/* Adjust rate and period given the prescaler value */
to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);
--
2.7.4
^ permalink raw reply related
* [PATCH 07/12] clocksource/drivers/stm32: Compute a prescaler value with a targeted rate
From: Daniel Lezcano @ 2018-01-04 12:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515070228-10481-1-git-send-email-daniel.lezcano@linaro.org>
From: Benjamin Gaignard <benjamin.gaignard@st.com>
The prescaler value is arbitrarily set to 1024 without any regard to the
timer frequency. For 32bits timers, there is no need to set a prescaler
value as they wrap in an acceptable interval and give the opportunity to
have precise timers on this platform. However, for 16bits timers a prescaler
value is needed if we don't want to wrap too often per second which is
unefficient and adds more and more error margin. With a targeted clock
of 10MHz, the 16bits are precise enough whatever the timer frequency is
as we will compute the prescaler.
[Daniel Lezcano]: Massaged the changelog and added comment.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/clocksource/timer-stm32.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 862134e..ac55896 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -37,6 +37,9 @@
#define TIM_EGR_UG BIT(0)
+#define TIM_PSC_MAX USHRT_MAX
+#define TIM_PSC_CLKRATE 10000
+
static int stm32_clock_event_shutdown(struct clock_event_device *clkevt)
{
struct timer_of *to = to_timer_of(clkevt);
@@ -116,7 +119,14 @@ static void __init stm32_clockevent_init(struct timer_of *to)
prescaler = 1;
to->clkevt.rating = 250;
} else {
- prescaler = 1024;
+ prescaler = DIV_ROUND_CLOSEST(timer_of_rate(to),
+ TIM_PSC_CLKRATE);
+ /*
+ * The prescaler register is an u16, the variable
+ * can't be greater than TIM_PSC_MAX, let's cap it in
+ * this case.
+ */
+ prescaler = prescaler < TIM_PSC_MAX ? prescaler : TIM_PSC_MAX;
to->clkevt.rating = 100;
}
writel_relaxed(0, timer_of_base(to) + TIM_ARR);
--
2.7.4
^ permalink raw reply related
* [PATCH 06/12] clocksource/drivers/stm32: Encapsulate the timer width sorting out function
From: Daniel Lezcano @ 2018-01-04 12:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515070228-10481-1-git-send-email-daniel.lezcano@linaro.org>
In order to clarify and encapsulate the code for the next changes move the
timer width check into a function and add some documentation.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/clocksource/timer-stm32.c | 30 +++++++++++++++++++++++-------
1 file changed, 23 insertions(+), 7 deletions(-)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 14b7a2b..862134e 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -80,9 +80,27 @@ static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
return IRQ_HANDLED;
}
+/**
+ * stm32_timer_width - Sort out the timer width (32/16)
+ * @to: a pointer to a timer-of structure
+ *
+ * Write the 32bits max value and read/return the result. If the timer
+ * is a 32bits width, the result will be UINT_MAX, otherwise it will
+ * be truncated by the 16bits register to USHRT_MAX.
+ *
+ * Returns UINT_MAX if the timer is 32bits width, USHRT_MAX if it is a
+ * 16bits width.
+ */
+static u32 __init stm32_timer_width(struct timer_of *to)
+{
+ writel_relaxed(UINT_MAX, timer_of_base(to) + TIM_ARR);
+
+ return readl_relaxed(timer_of_base(to) + TIM_ARR);
+}
+
static void __init stm32_clockevent_init(struct timer_of *to)
{
- unsigned long max_delta;
+ u32 width = 0;
int prescaler;
to->clkevt.name = to->np->full_name;
@@ -93,10 +111,8 @@ static void __init stm32_clockevent_init(struct timer_of *to)
to->clkevt.tick_resume = stm32_clock_event_shutdown;
to->clkevt.set_next_event = stm32_clock_event_set_next_event;
- /* Detect whether the timer is 16 or 32 bits */
- writel_relaxed(~0U, timer_of_base(to) + TIM_ARR);
- max_delta = readl_relaxed(timer_of_base(to) + TIM_ARR);
- if (max_delta == ~0U) {
+ width = stm32_timer_width(to);
+ if (width == UINT_MAX) {
prescaler = 1;
to->clkevt.rating = 250;
} else {
@@ -115,10 +131,10 @@ static void __init stm32_clockevent_init(struct timer_of *to)
to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
clockevents_config_and_register(&to->clkevt,
- timer_of_rate(to), 0x1, max_delta);
+ timer_of_rate(to), 0x1, width);
pr_info("%pOF: STM32 clockevent driver initialized (%d bits)\n",
- to->np, max_delta == UINT_MAX ? 32 : 16);
+ to->np, width == UINT_MAX ? 32 : 16);
}
static int __init stm32_timer_init(struct device_node *node)
--
2.7.4
^ permalink raw reply related
* [PATCH 05/12] clocksource/drivers/stm32: Use the node name as timer name
From: Daniel Lezcano @ 2018-01-04 12:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515070228-10481-1-git-send-email-daniel.lezcano@linaro.org>
As there are different timers on the stm32, use the node name for the timer
name in order to give the indication of which timer the kernel is using.
The /proc/timer_list gives all the information with the right name, otherwise
we end up digging in the kernel log and /proc/interrupt to do the connection
between the used timer.
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/clocksource/timer-stm32.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 3e4ab07..14b7a2b 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -85,7 +85,7 @@ static void __init stm32_clockevent_init(struct timer_of *to)
unsigned long max_delta;
int prescaler;
- to->clkevt.name = "stm32_clockevent";
+ to->clkevt.name = to->np->full_name;
to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
--
2.7.4
^ permalink raw reply related
* [PATCH 04/12] clocksource/drivers/stm32: Convert the driver to timer-of
From: Daniel Lezcano @ 2018-01-04 12:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515070228-10481-1-git-send-email-daniel.lezcano@linaro.org>
From: Benjamin Gaignard <benjamin.gaignard@st.com>
Convert the driver to use the timer_of helpers. This allows to remove custom
proprietary structure, factors out and simplifies the code.
[Daniel Lezcano] : Respin against the critical fix patch and massaged the
changelog.
Signed-off-by: Benjamin Gaignard <benjamin.gaignard@st.com>
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/clocksource/Kconfig | 1 +
drivers/clocksource/timer-stm32.c | 187 +++++++++++++++-----------------------
2 files changed, 74 insertions(+), 114 deletions(-)
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 9a6b087..786db7a 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -269,6 +269,7 @@ config CLKSRC_STM32
bool "Clocksource for STM32 SoCs" if !ARCH_STM32
depends on OF && ARM && (ARCH_STM32 || COMPILE_TEST)
select CLKSRC_MMIO
+ select TIMER_OF
config CLKSRC_MPS2
bool "Clocksource for MPS2 SoCs" if COMPILE_TEST
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 4bfeb99..3e4ab07 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -16,6 +16,9 @@
#include <linux/of_irq.h>
#include <linux/clk.h>
#include <linux/reset.h>
+#include <linux/slab.h>
+
+#include "timer-of.h"
#define TIM_CR1 0x00
#define TIM_DIER 0x0c
@@ -34,162 +37,118 @@
#define TIM_EGR_UG BIT(0)
-struct stm32_clock_event_ddata {
- struct clock_event_device evtdev;
- unsigned periodic_top;
- void __iomem *base;
-};
-
-static int stm32_clock_event_shutdown(struct clock_event_device *evtdev)
+static int stm32_clock_event_shutdown(struct clock_event_device *clkevt)
{
- struct stm32_clock_event_ddata *data =
- container_of(evtdev, struct stm32_clock_event_ddata, evtdev);
- void *base = data->base;
+ struct timer_of *to = to_timer_of(clkevt);
+
+ writel_relaxed(0, timer_of_base(to) + TIM_CR1);
- writel_relaxed(0, base + TIM_CR1);
return 0;
}
-static int stm32_clock_event_set_periodic(struct clock_event_device *evtdev)
+static int stm32_clock_event_set_periodic(struct clock_event_device *clkevt)
{
- struct stm32_clock_event_ddata *data =
- container_of(evtdev, struct stm32_clock_event_ddata, evtdev);
- void *base = data->base;
+ struct timer_of *to = to_timer_of(clkevt);
+
+ writel_relaxed(timer_of_period(to), timer_of_base(to) + TIM_ARR);
+ writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, timer_of_base(to) + TIM_CR1);
- writel_relaxed(data->periodic_top, base + TIM_ARR);
- writel_relaxed(TIM_CR1_ARPE | TIM_CR1_CEN, base + TIM_CR1);
return 0;
}
static int stm32_clock_event_set_next_event(unsigned long evt,
- struct clock_event_device *evtdev)
+ struct clock_event_device *clkevt)
{
- struct stm32_clock_event_ddata *data =
- container_of(evtdev, struct stm32_clock_event_ddata, evtdev);
+ struct timer_of *to = to_timer_of(clkevt);
- writel_relaxed(evt, data->base + TIM_ARR);
+ writel_relaxed(evt, timer_of_base(to) + TIM_ARR);
writel_relaxed(TIM_CR1_ARPE | TIM_CR1_OPM | TIM_CR1_CEN,
- data->base + TIM_CR1);
+ timer_of_base(to) + TIM_CR1);
return 0;
}
static irqreturn_t stm32_clock_event_handler(int irq, void *dev_id)
{
- struct stm32_clock_event_ddata *data = dev_id;
+ struct clock_event_device *clkevt = (struct clock_event_device *)dev_id;
+ struct timer_of *to = to_timer_of(clkevt);
- writel_relaxed(0, data->base + TIM_SR);
+ writel_relaxed(0, timer_of_base(to) + TIM_SR);
- data->evtdev.event_handler(&data->evtdev);
+ clkevt->event_handler(clkevt);
return IRQ_HANDLED;
}
-static struct stm32_clock_event_ddata clock_event_ddata = {
- .evtdev = {
- .name = "stm32 clockevent",
- .features = CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
- .set_state_shutdown = stm32_clock_event_shutdown,
- .set_state_periodic = stm32_clock_event_set_periodic,
- .set_state_oneshot = stm32_clock_event_shutdown,
- .tick_resume = stm32_clock_event_shutdown,
- .set_next_event = stm32_clock_event_set_next_event,
- .rating = 200,
- },
-};
-
-static int __init stm32_clockevent_init(struct device_node *np)
+static void __init stm32_clockevent_init(struct timer_of *to)
{
- struct stm32_clock_event_ddata *data = &clock_event_ddata;
- struct clk *clk;
- struct reset_control *rstc;
- unsigned long rate, max_delta;
- int irq, ret, bits, prescaler = 1;
-
- data = kmemdup(&clock_event_ddata, sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
-
- clk = of_clk_get(np, 0);
- if (IS_ERR(clk)) {
- ret = PTR_ERR(clk);
- pr_err("failed to get clock for clockevent (%d)\n", ret);
- goto err_clk_get;
- }
-
- ret = clk_prepare_enable(clk);
- if (ret) {
- pr_err("failed to enable timer clock for clockevent (%d)\n",
- ret);
- goto err_clk_enable;
- }
-
- rate = clk_get_rate(clk);
-
- rstc = of_reset_control_get(np, NULL);
- if (!IS_ERR(rstc)) {
- reset_control_assert(rstc);
- reset_control_deassert(rstc);
- }
-
- data->base = of_iomap(np, 0);
- if (!data->base) {
- ret = -ENXIO;
- pr_err("failed to map registers for clockevent\n");
- goto err_iomap;
- }
+ unsigned long max_delta;
+ int prescaler;
- irq = irq_of_parse_and_map(np, 0);
- if (!irq) {
- ret = -EINVAL;
- pr_err("%pOF: failed to get irq.\n", np);
- goto err_get_irq;
- }
+ to->clkevt.name = "stm32_clockevent";
+ to->clkevt.features = CLOCK_EVT_FEAT_PERIODIC;
+ to->clkevt.set_state_shutdown = stm32_clock_event_shutdown;
+ to->clkevt.set_state_periodic = stm32_clock_event_set_periodic;
+ to->clkevt.set_state_oneshot = stm32_clock_event_shutdown;
+ to->clkevt.tick_resume = stm32_clock_event_shutdown;
+ to->clkevt.set_next_event = stm32_clock_event_set_next_event;
/* Detect whether the timer is 16 or 32 bits */
- writel_relaxed(~0U, data->base + TIM_ARR);
- max_delta = readl_relaxed(data->base + TIM_ARR);
+ writel_relaxed(~0U, timer_of_base(to) + TIM_ARR);
+ max_delta = readl_relaxed(timer_of_base(to) + TIM_ARR);
if (max_delta == ~0U) {
prescaler = 1;
- bits = 32;
+ to->clkevt.rating = 250;
} else {
prescaler = 1024;
- bits = 16;
+ to->clkevt.rating = 100;
}
- writel_relaxed(0, data->base + TIM_ARR);
+ writel_relaxed(0, timer_of_base(to) + TIM_ARR);
- writel_relaxed(prescaler - 1, data->base + TIM_PSC);
- writel_relaxed(TIM_EGR_UG, data->base + TIM_EGR);
- writel_relaxed(0, data->base + TIM_SR);
- writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER);
+ writel_relaxed(prescaler - 1, timer_of_base(to) + TIM_PSC);
+ writel_relaxed(TIM_EGR_UG, timer_of_base(to) + TIM_EGR);
+ writel_relaxed(0, timer_of_base(to) + TIM_SR);
+ writel_relaxed(TIM_DIER_UIE, timer_of_base(to) + TIM_DIER);
- data->periodic_top = DIV_ROUND_CLOSEST(rate, prescaler * HZ);
+ /* Adjust rate and period given the prescaler value */
+ to->of_clk.rate = DIV_ROUND_CLOSEST(to->of_clk.rate, prescaler);
+ to->of_clk.period = DIV_ROUND_UP(to->of_clk.rate, HZ);
- clockevents_config_and_register(&data->evtdev,
- DIV_ROUND_CLOSEST(rate, prescaler),
- 0x1, max_delta);
-
- ret = request_irq(irq, stm32_clock_event_handler, IRQF_TIMER,
- "stm32 clockevent", data);
- if (ret) {
- pr_err("%pOF: failed to request irq.\n", np);
- goto err_get_irq;
- }
+ clockevents_config_and_register(&to->clkevt,
+ timer_of_rate(to), 0x1, max_delta);
pr_info("%pOF: STM32 clockevent driver initialized (%d bits)\n",
- np, bits);
+ to->np, max_delta == UINT_MAX ? 32 : 16);
+}
- return ret;
+static int __init stm32_timer_init(struct device_node *node)
+{
+ struct reset_control *rstc;
+ struct timer_of *to;
+ int ret;
+
+ to = kzalloc(sizeof(*to), GFP_KERNEL);
+ if (!to)
+ return -ENOMEM;
+
+ to->flags = TIMER_OF_IRQ | TIMER_OF_CLOCK | TIMER_OF_BASE;
+ to->of_irq.handler = stm32_clock_event_handler;
+
+ ret = timer_of_init(node, to);
+ if (ret)
+ goto err;
-err_get_irq:
- iounmap(data->base);
-err_iomap:
- clk_disable_unprepare(clk);
-err_clk_enable:
- clk_put(clk);
-err_clk_get:
- kfree(data);
+ rstc = of_reset_control_get(node, NULL);
+ if (!IS_ERR(rstc)) {
+ reset_control_assert(rstc);
+ reset_control_deassert(rstc);
+ }
+
+ stm32_clockevent_init(to);
+ return 0;
+err:
+ kfree(to);
return ret;
}
-TIMER_OF_DECLARE(stm32, "st,stm32-timer", stm32_clockevent_init);
+TIMER_OF_DECLARE(stm32, "st,stm32-timer", stm32_timer_init);
--
2.7.4
^ permalink raw reply related
* [PATCH 03/12] clocksource/drivers/stm32: Fix kernel panic with multiple timers
From: Daniel Lezcano @ 2018-01-04 12:50 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515070228-10481-1-git-send-email-daniel.lezcano@linaro.org>
The current code hides a couple of bugs.
- The global variable 'clock_event_ddata' is overwritten each time the
init function is invoked.
This is fixed with a kmemdup instead of assigning the global variable. That
prevents a memory corruption when several timers are defined in the DT.
- The clockevent's event_handler is NULL if the time framework does
not select the clockevent when registering it, this is fine but the init
code generates in any case an interrupt leading to dereference this
NULL pointer.
The stm32 timer works with shadow registers, a mechanism to cache the
registers. When a change is done in one buffered register, we need to
artificially generate an event to force the timer to copy the content
of the register to the shadowed register.
The auto-reload register (ARR) is one of the shadowed register as well as
the prescaler register (PSC), so in order to force the copy, we issue an
event which in turn leads to an interrupt and the NULL dereference.
This is fixed by inverting two lines where we clear the status register
before enabling the update event interrupt.
As this kernel crash is resulting from the combination of these two bugs,
the fixes are grouped into a single patch.
Cc: stable at vger.kernel.org
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
---
drivers/clocksource/timer-stm32.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 8f24237..4bfeb99 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -106,6 +106,10 @@ static int __init stm32_clockevent_init(struct device_node *np)
unsigned long rate, max_delta;
int irq, ret, bits, prescaler = 1;
+ data = kmemdup(&clock_event_ddata, sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
clk = of_clk_get(np, 0);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
@@ -156,8 +160,8 @@ static int __init stm32_clockevent_init(struct device_node *np)
writel_relaxed(prescaler - 1, data->base + TIM_PSC);
writel_relaxed(TIM_EGR_UG, data->base + TIM_EGR);
- writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER);
writel_relaxed(0, data->base + TIM_SR);
+ writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER);
data->periodic_top = DIV_ROUND_CLOSEST(rate, prescaler * HZ);
@@ -184,6 +188,7 @@ static int __init stm32_clockevent_init(struct device_node *np)
err_clk_enable:
clk_put(clk);
err_clk_get:
+ kfree(data);
return ret;
}
--
2.7.4
^ permalink raw reply related
* [PATCH v4 5/7] clk: Introduce davinci clocks
From: Sekhar Nori @ 2018-01-04 12:43 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1514763588-31560-6-git-send-email-david@lechnology.com>
Hi David,
On Monday 01 January 2018 05:09 AM, David Lechner wrote:
> + /* TODO: old davinci clocks for da850 set MDCTL_FORCE bit for sata and
> + * dsp here. Is this really needed?
> + */
The commit that introduced this flag suggests so.
commit aad70de20fc69970a3080e7e8f02b54a4a3fe3e6
Author: Sekhar Nori <nsekhar@ti.com>
AuthorDate: Wed Jul 6 06:01:22 2011 +0000
Commit: Sekhar Nori <nsekhar@ti.com>
CommitDate: Fri Jul 8 11:10:09 2011 +0530
davinci: enable forced transitions on PSC
Some DaVinci modules like the SATA on DA850
need forced module state transitions.
Define a "force" flag which can be passed to
the PSC config function to enable it to make
forced transitions.
Forced transitions shouldn't normally be attempted,
unless the TRM explicitly specifies its usage.
ChangeLog:
v2:
Modified to take care of the fact that
davinci_psc_config() now takes the flags
directly.
Signed-off-by: Sekhar Nori <nsekhar@ti.com>
I can check without that flag again, but I do recall it being needed.
Thanks,
Sekhar
^ permalink raw reply
* [PATCH v4 6/7] ARM: davinci: convert to common clock framework
From: Sekhar Nori @ 2018-01-04 12:39 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1514763588-31560-7-git-send-email-david@lechnology.com>
On Monday 01 January 2018 05:09 AM, David Lechner wrote:
> This converts all of arch/arm/mach-davinci to the common clock framework.
> The clock drivers from clock.c and psc.c have been moved to drivers/clk,
> so these files are removed.
>
> There is one subtle change in the clock trees. AUX, BPDIV and OSCDIV
> clocks now have "ref_clk" as a parent instead of the PLL clock. These
> clocks are part of the PLL's MMIO block, but they bypass the PLL and
> therefore it makes more sense to have "ref_clk" as their parent since
> "ref_clk" is the input clock of the PLL.
>
> CONFIG_DAVINCI_RESET_CLOCKS is removed since the common clock frameworks
> takes care of disabling unused clocks.
>
> Known issue: This breaks CPU frequency scaling on da850.
This functionality needs to be restored as part of this series since we
cannot commit anything with regressions.
>
> Also, the order of #includes are cleaned up in files while we are touching
> this code.
>
> Signed-off-by: David Lechner <david@lechnology.com>
This is a pretty huge patch again and I hope it can be broken down.
Ideally one per SoC converted and then the unused code removal.
Thanks,
Sekhar
^ permalink raw reply
* [PATCH v2] dt: psci: Update DT bindings to support hierarchical PSCI states
From: Sudeep Holla @ 2018-01-04 12:31 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1514472037-25969-1-git-send-email-ulf.hansson@linaro.org>
Hi Ulf,
I will suggest some wording changes not of which are not compulsory and
left to you to pick up or drop.
On 28/12/17 14:40, Ulf Hansson wrote:
> From: Lina Iyer <lina.iyer@linaro.org>
>
> Update DT bindings to represent hierarchical CPU and CPU domain idle states
> for PSCI. Also update the PSCI examples to clearly show how flattened and
> hierarchical idle states can be represented in DT.
>
> Signed-off-by: Lina Iyer <lina.iyer@linaro.org>
> Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
> ---
>
> Changes in v2:
> - Addressed comments from Rob.
> - Updated some labels in the examples to get more consistency.
>
> For your information, I have picked up the work from Lina Iyer around the so
> called CPU cluster idling series [1,2] and I working on new versions. However,
> I decided to post the updates to the PSCI DT bindings first, as they will be
> needed to be agreed upon before further changes can be done to the PSCI firmware
> driver.
>
> Note, these bindings have been discussed over and over again, at LKML, but
> especially also at various Linux conferences, like LPC and Linaro Connect. We
> finally came to a conclusion and the changes we agreed upon, should be reflected
> in this update.
>
> Of course, it's a while ago since the latest discussions, but hopefully people
> don't have too hard time to remember.
>
> Kind regards
> Uffe
>
> [1]
> https://www.spinics.net/lists/arm-kernel/msg566200.html
>
> [2]
> https://lwn.net/Articles/716300/
>
> ---
> Documentation/devicetree/bindings/arm/psci.txt | 152 +++++++++++++++++++++++++
> 1 file changed, 152 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/arm/psci.txt b/Documentation/devicetree/bindings/arm/psci.txt
> index a2c4f1d..8a09bd2 100644
> --- a/Documentation/devicetree/bindings/arm/psci.txt
> +++ b/Documentation/devicetree/bindings/arm/psci.txt
> @@ -105,7 +105,159 @@ Case 3: PSCI v0.2 and PSCI v0.1.
> ...
> };
>
> +PSCI v1.0 onwards, supports OS-Initiated mode for powering off CPUs and CPU
> +clusters from the firmware.
Since we are trying to avoid usage of "clusters"(as it's not architecturally
defined, but I know it's too late as it widely used everywhere). Also this
binding is not just OSI specific, it can be used for Platform Co-ordinated
also so let's not specify them at all.
How about:
"ARM systems can have multiple cores sometimes in hierarchical arrangement.
This often, but not always, maps directly to the processor power topology
of the system. Individual nodes in a topology have their own specific power
states and can be better represented in DT hierarchically"
> For such topologies the PSCI firmware driver acts
PSCI firmware can be represented as a pseudo power controller ?
> +as pseudo-controller, which may be specified in the psci DT node. The
> +definitions of the CPU and the CPU cluster topology, must conform to the domain
> +idle state specification [3].
I assume it should be "..definitions of the idle states for CPU and the CPU
topology" above, otherwise they should conform to topology binding :) rather
than domain idle state bindings.
> The domain idle states themselves, must be
> +compatible with the defined 'domain-idle-state' binding [1], and also need to
> +specify the arm,psci-suspend-param property for each idle state.
> +
> +DT allows representing CPU and CPU cluster idle states in two different ways -
> +
> +The flattened model as given in Example 1, lists CPU's idle states followed by
> +the domain idle state that the CPUs may choose. This is the general practice
> +followed in PSCI firmwares that support Platform Coordinated mode.
I would rather drop the above statement or specify in Example 2 that it can be
used for both OSI and PC.
> Note that
> +the idle states are all compatible with "arm,idle-state".
> +
> +Example 2 represents the hierarchical model of CPU and domain idle states.
> +CPUs define their domain provider in their DT node. The domain controls the
> +power to the CPU and possibly other h/w blocks that would be powered off when
> +the CPU is powered off. The CPU's idle states may therefore be considered as
> +the domain's idle states and have the compatible "arm,idle-state". Such domains
> +may be embedded within another domain that represents common h/w blocks between
> +these CPUs viz. the cluster. The idle states of the cluster would be
> +represented as the domain's idle states. In order to use OS-Initiated mode of
> +PSCI in the firmware, the hierarchical representation must be used.
> +
Can we avoid using poweroff as it's one of the idle states and not the only
one ?
Other than that, the examples look good to me.
--
Regards,
Sudeep
^ permalink raw reply
* [PATCH v4 5/7] clk: Introduce davinci clocks
From: Sekhar Nori @ 2018-01-04 12:28 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <42102b7d-4e3c-d5fc-b0db-48a1203757ba@lechnology.com>
On Wednesday 03 January 2018 03:01 AM, David Lechner wrote:
> Forgot to cc linux-clk, so doing that now...
>
>
> On 12/31/2017 05:39 PM, David Lechner wrote:
>> This introduces new drivers for arch/arm/mach-davinci. The code is based
>> on the clock drivers from there and adapted to use the common clock
>> framework.
>>
>> Signed-off-by: David Lechner <david@lechnology.com>
>> ---
>> ? drivers/clk/Makefile????????????????????? |?? 1 +
>> ? drivers/clk/davinci/Makefile????????????? |?? 3 +
>> ? drivers/clk/davinci/da8xx-cfgchip-clk.c?? | 380
>> ++++++++++++++++++++++++++++++
>> ? drivers/clk/davinci/pll.c???????????????? | 333
>> ++++++++++++++++++++++++++
>> ? drivers/clk/davinci/psc.c???????????????? | 217 +++++++++++++++++
>> ? include/linux/clk/davinci.h?????????????? |? 46 ++++
>> ? include/linux/platform_data/davinci_clk.h |? 25 ++
>> ? 7 files changed, 1005 insertions(+)
This is a pretty huge patch and I think each of cfgchip, pll and PSC
clocks deserve a patch of their own.
On the PLL patch, please describe how the PLL implementation on DaVinci
is different from Keystone, so no reuse is really possible. Similarly
for the PSC patch (no non-DT support in keystone etc).
>> diff --git a/drivers/clk/davinci/psc.c b/drivers/clk/davinci/psc.c
>> new file mode 100644
>> index 0000000..8ae85ee
>> --- /dev/null
>> +++ b/drivers/clk/davinci/psc.c
>> @@ -0,0 +1,217 @@
>> +static void psc_config(struct davinci_psc_clk *psc,
>> +?????????????? enum davinci_psc_state next_state)
>> +{
>> +??? u32 epcpr, ptcmd, pdstat, pdctl, mdstat, mdctl, ptstat;
>> +
>> +??? mdctl = readl(psc->base + MDCTL + 4 * psc->lpsc);
>> +??? mdctl &= ~MDSTAT_STATE_MASK;
>> +??? mdctl |= next_state;
>> +??? /* TODO: old davinci clocks for da850 set MDCTL_FORCE bit for
>> sata and
>> +???? * dsp here. Is this really needed?
>> +???? */
>> +??? writel(mdctl, psc->base + MDCTL + 4 * psc->lpsc);
>> +
>> +??? pdstat = readl(psc->base + PDSTAT + 4 * psc->pd);
>> +??? if ((pdstat & PDSTAT_STATE_MASK) == 0) {
>> +??????? pdctl = readl(psc->base + PDSTAT + 4 * psc->pd);
>> +??????? pdctl |= PDCTL_NEXT;
>> +??????? writel(pdctl, psc->base + PDSTAT + 4 * psc->pd);
>> +
>> +??????? ptcmd = BIT(psc->pd);
>> +??????? writel(ptcmd, psc->base + PTCMD);
>> +
>> +??????? do {
>> +??????????? epcpr = __raw_readl(psc->base + EPCPR);
>> +??????? } while (!(epcpr & BIT(psc->pd)));
>> +
>> +??????? pdctl = __raw_readl(psc->base + PDCTL + 4 * psc->pd);
>> +??????? pdctl |= PDCTL_EPCGOOD;
>> +??????? __raw_writel(pdctl, psc->base + PDCTL + 4 * psc->pd);
Can we shift to regmap here too? Then the polling loops like above can
be converted to regmap_read_poll_timeout() too like you have done elsewhere.
Thanks,
Sekhar
^ permalink raw reply
* [kernel-hardening] [PATCH] arm: Always use REFCOUNT_FULL
From: Jinbum Park @ 2018-01-04 12:28 UTC (permalink / raw)
To: linux-arm-kernel
arm prefers to use REFCOUNT_FULL by default.
This enables it for arm.
Signed-off-by: Jinbum Park <jinb.park7@gmail.com>
---
arch/arm/Kconfig | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 3d349b4..ec80270 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -100,6 +100,7 @@ config ARM
select OLD_SIGACTION
select OLD_SIGSUSPEND3
select PERF_USE_VMALLOC
+ select REFCOUNT_FULL
select RTC_LIB
select SYS_SUPPORTS_APM_EMULATION
# Above selects are sorted alphabetically; please add new ones
--
1.9.1
^ permalink raw reply related
* [PATCH V4 08/26] drm/gma500: deprecate pci_get_bus_and_slot()
From: Sinan Kaya @ 2018-01-04 12:27 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513661883-28662-9-git-send-email-okaya@codeaurora.org>
On 12/19/2017 12:37 AM, Sinan Kaya wrote:
> pci_get_bus_and_slot() is restrictive such that it assumes domain=0 as
> where a PCI device is present. This restricts the device drivers to be
> reused for other domain numbers.
>
> Getting ready to remove pci_get_bus_and_slot() function in favor of
> pci_get_domain_bus_and_slot().
>
> Add domain parameter to CDV_MSG_READ32, CDV_MSG_WRITE32, MRST_MSG_READ32,
> MRST_MSG_WRITE32, MDFLD_MSG_READ32, MDFLD_MSG_WRITE32.
>
> Extract pci_dev from struct drm_device and use pdev to find the domain
> number while calling pci_get_domain_bus_and_slot().
>
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
> drivers/gpu/drm/gma500/cdv_device.c | 16 +++++++++-------
> drivers/gpu/drm/gma500/gma_device.c | 4 +++-
> drivers/gpu/drm/gma500/mid_bios.c | 12 +++++++++---
> drivers/gpu/drm/gma500/psb_drv.c | 10 ++++++++--
> drivers/gpu/drm/gma500/psb_drv.h | 18 ++++++++++--------
> 5 files changed, 39 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/gpu/drm/gma500/cdv_device.c b/drivers/gpu/drm/gma500/cdv_device.c
> index 8745971..3a3bf75 100644
> --- a/drivers/gpu/drm/gma500/cdv_device.c
> +++ b/drivers/gpu/drm/gma500/cdv_device.c
> @@ -185,21 +185,22 @@ static int cdv_backlight_init(struct drm_device *dev)
> * for this and the MID devices.
> */
>
> -static inline u32 CDV_MSG_READ32(uint port, uint offset)
> +static inline u32 CDV_MSG_READ32(int domain, uint port, uint offset)
> {
> int mcr = (0x10<<24) | (port << 16) | (offset << 8);
> uint32_t ret_val = 0;
> - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
> + struct pci_dev *pci_root = pci_get_domain_bus_and_slot(domain, 0, 0);
> pci_write_config_dword(pci_root, 0xD0, mcr);
> pci_read_config_dword(pci_root, 0xD4, &ret_val);
> pci_dev_put(pci_root);
> return ret_val;
> }
>
> -static inline void CDV_MSG_WRITE32(uint port, uint offset, u32 value)
> +static inline void CDV_MSG_WRITE32(int domain, uint port, uint offset,
> + u32 value)
> {
> int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
> - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
> + struct pci_dev *pci_root = pci_get_domain_bus_and_slot(domain, 0, 0);
> pci_write_config_dword(pci_root, 0xD4, value);
> pci_write_config_dword(pci_root, 0xD0, mcr);
> pci_dev_put(pci_root);
> @@ -216,11 +217,12 @@ static void cdv_init_pm(struct drm_device *dev)
> {
> struct drm_psb_private *dev_priv = dev->dev_private;
> u32 pwr_cnt;
> + int domain = pci_domain_nr(dev->pdev->bus);
> int i;
>
> - dev_priv->apm_base = CDV_MSG_READ32(PSB_PUNIT_PORT,
> + dev_priv->apm_base = CDV_MSG_READ32(domain, PSB_PUNIT_PORT,
> PSB_APMBA) & 0xFFFF;
> - dev_priv->ospm_base = CDV_MSG_READ32(PSB_PUNIT_PORT,
> + dev_priv->ospm_base = CDV_MSG_READ32(domain, PSB_PUNIT_PORT,
> PSB_OSPMBA) & 0xFFFF;
>
> /* Power status */
> @@ -251,7 +253,7 @@ static void cdv_errata(struct drm_device *dev)
> * Bonus Launch to work around the issue, by degrading
> * performance.
> */
> - CDV_MSG_WRITE32(3, 0x30, 0x08027108);
> + CDV_MSG_WRITE32(pci_domain_nr(dev->pdev->bus), 3, 0x30, 0x08027108);
> }
>
> /**
> diff --git a/drivers/gpu/drm/gma500/gma_device.c b/drivers/gpu/drm/gma500/gma_device.c
> index 4a295f9..a7fb6de 100644
> --- a/drivers/gpu/drm/gma500/gma_device.c
> +++ b/drivers/gpu/drm/gma500/gma_device.c
> @@ -19,7 +19,9 @@
> void gma_get_core_freq(struct drm_device *dev)
> {
> uint32_t clock;
> - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
> + struct pci_dev *pci_root =
> + pci_get_domain_bus_and_slot(pci_domain_nr(dev->pdev->bus),
> + 0, 0);
> struct drm_psb_private *dev_priv = dev->dev_private;
>
> /*pci_write_config_dword(pci_root, 0xD4, 0x00C32004);*/
> diff --git a/drivers/gpu/drm/gma500/mid_bios.c b/drivers/gpu/drm/gma500/mid_bios.c
> index 1fa1633..7171b74 100644
> --- a/drivers/gpu/drm/gma500/mid_bios.c
> +++ b/drivers/gpu/drm/gma500/mid_bios.c
> @@ -32,7 +32,9 @@
> static void mid_get_fuse_settings(struct drm_device *dev)
> {
> struct drm_psb_private *dev_priv = dev->dev_private;
> - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
> + struct pci_dev *pci_root =
> + pci_get_domain_bus_and_slot(pci_domain_nr(dev->pdev->bus),
> + 0, 0);
> uint32_t fuse_value = 0;
> uint32_t fuse_value_tmp = 0;
>
> @@ -104,7 +106,9 @@ static void mid_get_fuse_settings(struct drm_device *dev)
> static void mid_get_pci_revID(struct drm_psb_private *dev_priv)
> {
> uint32_t platform_rev_id = 0;
> - struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
> + int domain = pci_domain_nr(dev_priv->dev->pdev->bus);
> + struct pci_dev *pci_gfx_root =
> + pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(2, 0));
>
> if (pci_gfx_root == NULL) {
> WARN_ON(1);
> @@ -281,7 +285,9 @@ static void mid_get_vbt_data(struct drm_psb_private *dev_priv)
> u32 addr;
> u8 __iomem *vbt_virtual;
> struct mid_vbt_header vbt_header;
> - struct pci_dev *pci_gfx_root = pci_get_bus_and_slot(0, PCI_DEVFN(2, 0));
> + struct pci_dev *pci_gfx_root =
> + pci_get_domain_bus_and_slot(pci_domain_nr(dev->pdev->bus),
> + 0, PCI_DEVFN(2, 0));
> int ret = -1;
>
> /* Get the address of the platform config vbt */
> diff --git a/drivers/gpu/drm/gma500/psb_drv.c b/drivers/gpu/drm/gma500/psb_drv.c
> index 38d09d4..ac32ab5 100644
> --- a/drivers/gpu/drm/gma500/psb_drv.c
> +++ b/drivers/gpu/drm/gma500/psb_drv.c
> @@ -248,7 +248,11 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags)
> goto out_err;
>
> if (IS_MRST(dev)) {
> - dev_priv->aux_pdev = pci_get_bus_and_slot(0, PCI_DEVFN(3, 0));
> + int domain = pci_domain_nr(dev->pdev->bus);
> +
> + dev_priv->aux_pdev =
> + pci_get_domain_bus_and_slot(domain, 0,
> + PCI_DEVFN(3, 0));
>
> if (dev_priv->aux_pdev) {
> resource_start = pci_resource_start(dev_priv->aux_pdev,
> @@ -268,7 +272,9 @@ static int psb_driver_load(struct drm_device *dev, unsigned long flags)
> }
> dev_priv->gmbus_reg = dev_priv->aux_reg;
>
> - dev_priv->lpc_pdev = pci_get_bus_and_slot(0, PCI_DEVFN(31, 0));
> + dev_priv->lpc_pdev =
> + pci_get_domain_bus_and_slot(domain, 0,
> + PCI_DEVFN(31, 0));
> if (dev_priv->lpc_pdev) {
> pci_read_config_word(dev_priv->lpc_pdev, PSB_LPC_GBA,
> &dev_priv->lpc_gpio_base);
> diff --git a/drivers/gpu/drm/gma500/psb_drv.h b/drivers/gpu/drm/gma500/psb_drv.h
> index 4918efc..e8300f5 100644
> --- a/drivers/gpu/drm/gma500/psb_drv.h
> +++ b/drivers/gpu/drm/gma500/psb_drv.h
> @@ -780,38 +780,40 @@ extern int psb_gem_dumb_create(struct drm_file *file, struct drm_device *dev,
> extern int drm_idle_check_interval;
>
> /* Utilities */
> -static inline u32 MRST_MSG_READ32(uint port, uint offset)
> +static inline u32 MRST_MSG_READ32(int domain, uint port, uint offset)
> {
> int mcr = (0xD0<<24) | (port << 16) | (offset << 8);
> uint32_t ret_val = 0;
> - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
> + struct pci_dev *pci_root = pci_get_domain_bus_and_slot(domain, 0, 0);
> pci_write_config_dword(pci_root, 0xD0, mcr);
> pci_read_config_dword(pci_root, 0xD4, &ret_val);
> pci_dev_put(pci_root);
> return ret_val;
> }
> -static inline void MRST_MSG_WRITE32(uint port, uint offset, u32 value)
> +static inline void MRST_MSG_WRITE32(int domain, uint port, uint offset,
> + u32 value)
> {
> int mcr = (0xE0<<24) | (port << 16) | (offset << 8) | 0xF0;
> - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
> + struct pci_dev *pci_root = pci_get_domain_bus_and_slot(domain, 0, 0);
> pci_write_config_dword(pci_root, 0xD4, value);
> pci_write_config_dword(pci_root, 0xD0, mcr);
> pci_dev_put(pci_root);
> }
> -static inline u32 MDFLD_MSG_READ32(uint port, uint offset)
> +static inline u32 MDFLD_MSG_READ32(int domain, uint port, uint offset)
> {
> int mcr = (0x10<<24) | (port << 16) | (offset << 8);
> uint32_t ret_val = 0;
> - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
> + struct pci_dev *pci_root = pci_get_domain_bus_and_slot(domain, 0, 0);
> pci_write_config_dword(pci_root, 0xD0, mcr);
> pci_read_config_dword(pci_root, 0xD4, &ret_val);
> pci_dev_put(pci_root);
> return ret_val;
> }
> -static inline void MDFLD_MSG_WRITE32(uint port, uint offset, u32 value)
> +static inline void MDFLD_MSG_WRITE32(int domain, uint port, uint offset,
> + u32 value)
> {
> int mcr = (0x11<<24) | (port << 16) | (offset << 8) | 0xF0;
> - struct pci_dev *pci_root = pci_get_bus_and_slot(0, 0);
> + struct pci_dev *pci_root = pci_get_domain_bus_and_slot(domain, 0, 0);
> pci_write_config_dword(pci_root, 0xD4, value);
> pci_write_config_dword(pci_root, 0xD0, mcr);
> pci_dev_put(pci_root);
>
Any feedback here? I don't have any hardware to test the changes. I just did a compile test.
--
Sinan Kaya
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 V4 09/26] drm/nouveau: deprecate pci_get_bus_and_slot()
From: Sinan Kaya @ 2018-01-04 12:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513661883-28662-10-git-send-email-okaya@codeaurora.org>
On 12/19/2017 12:37 AM, Sinan Kaya wrote:
> pci_get_bus_and_slot() is restrictive such that it assumes domain=0 as
> where a PCI device is present. This restricts the device drivers to be
> reused for other domain numbers.
>
> Getting ready to remove pci_get_bus_and_slot() function in favor of
> pci_get_domain_bus_and_slot().
>
> Replace pci_get_bus_and_slot() with pci_get_domain_bus_and_slot()
> and extract the domain number from
> 1. struct pci_dev
> 2. struct pci_dev through drm_device->pdev
> 3. struct pci_dev through fb->subdev->drm_device->pdev
>
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
> drivers/gpu/drm/nouveau/dispnv04/arb.c | 4 +++-
> drivers/gpu/drm/nouveau/dispnv04/hw.c | 10 +++++++---
> drivers/gpu/drm/nouveau/nouveau_drm.c | 3 ++-
> drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c | 10 +++++++++-
> 4 files changed, 21 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/gpu/drm/nouveau/dispnv04/arb.c b/drivers/gpu/drm/nouveau/dispnv04/arb.c
> index 90075b6..c79160c 100644
> --- a/drivers/gpu/drm/nouveau/dispnv04/arb.c
> +++ b/drivers/gpu/drm/nouveau/dispnv04/arb.c
> @@ -213,8 +213,10 @@ struct nv_sim_state {
> if ((dev->pdev->device & 0xffff) == 0x01a0 /*CHIPSET_NFORCE*/ ||
> (dev->pdev->device & 0xffff) == 0x01f0 /*CHIPSET_NFORCE2*/) {
> uint32_t type;
> + int domain = pci_domain_nr(dev->pdev->bus);
>
> - pci_read_config_dword(pci_get_bus_and_slot(0, 1), 0x7c, &type);
> + pci_read_config_dword(pci_get_domain_bus_and_slot(domain, 0, 1),
> + 0x7c, &type);
>
> sim_data.memory_type = (type >> 12) & 1;
> sim_data.memory_width = 64;
> diff --git a/drivers/gpu/drm/nouveau/dispnv04/hw.c b/drivers/gpu/drm/nouveau/dispnv04/hw.c
> index b985990..0c9bdf0 100644
> --- a/drivers/gpu/drm/nouveau/dispnv04/hw.c
> +++ b/drivers/gpu/drm/nouveau/dispnv04/hw.c
> @@ -216,12 +216,15 @@
> {
> struct nvkm_pll_vals pllvals;
> int ret;
> + int domain;
> +
> + domain = pci_domain_nr(dev->pdev->bus);
>
> if (plltype == PLL_MEMORY &&
> (dev->pdev->device & 0x0ff0) == CHIPSET_NFORCE) {
> uint32_t mpllP;
> -
> - pci_read_config_dword(pci_get_bus_and_slot(0, 3), 0x6c, &mpllP);
> + pci_read_config_dword(pci_get_domain_bus_and_slot(domain, 0, 3),
> + 0x6c, &mpllP);
> mpllP = (mpllP >> 8) & 0xf;
> if (!mpllP)
> mpllP = 4;
> @@ -232,7 +235,8 @@
> (dev->pdev->device & 0xff0) == CHIPSET_NFORCE2) {
> uint32_t clock;
>
> - pci_read_config_dword(pci_get_bus_and_slot(0, 5), 0x4c, &clock);
> + pci_read_config_dword(pci_get_domain_bus_and_slot(domain, 0, 5),
> + 0x4c, &clock);
> return clock / 1000;
> }
>
> diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
> index 8d4a5be..33b6139 100644
> --- a/drivers/gpu/drm/nouveau/nouveau_drm.c
> +++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
> @@ -524,7 +524,8 @@ static int nouveau_drm_probe(struct pci_dev *pdev,
> }
>
> /* subfunction one is a hdmi audio device? */
> - drm->hdmi_device = pci_get_bus_and_slot((unsigned int)pdev->bus->number,
> + drm->hdmi_device = pci_get_domain_bus_and_slot(pci_domain_nr(pdev->bus),
> + (unsigned int)pdev->bus->number,
> PCI_DEVFN(PCI_SLOT(pdev->devfn), 1));
>
> if (!drm->hdmi_device) {
> diff --git a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c
> index 4c07d10..18241c6 100644
> --- a/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c
> +++ b/drivers/gpu/drm/nouveau/nvkm/subdev/fb/ramnv1a.c
> @@ -28,8 +28,16 @@
> {
> struct pci_dev *bridge;
> u32 mem, mib;
> + int domain = 0;
> + struct pci_dev *pdev = NULL;
>
> - bridge = pci_get_bus_and_slot(0, PCI_DEVFN(0, 1));
> + if (dev_is_pci(fb->subdev.device->dev))
> + pdev = to_pci_dev(fb->subdev.device->dev);
> +
> + if (pdev)
> + domain = pci_domain_nr(pdev->bus);
> +
> + bridge = pci_get_domain_bus_and_slot(domain, 0, PCI_DEVFN(0, 1));
> if (!bridge) {
> nvkm_error(&fb->subdev, "no bridge device\n");
> return -ENODEV;
>
Any feedback here? I don't have any hardware to test the changes. I just did a compile test.
--
Sinan Kaya
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 V4] ARM: imx_v6_v7_defconfig: select the CONFIG_CPUFREQ_DT
From: Fabio Estevam @ 2018-01-04 12:26 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1515095504-4570-1-git-send-email-Anson.Huang@nxp.com>
On Thu, Jan 4, 2018 at 5:51 PM, Anson Huang <Anson.Huang@nxp.com> wrote:
> Select CONFIG_CPUFREQ_DT by default to enable
> cpu-freq driver for i.MX7D.
>
> Signed-off-by: Anson Huang <Anson.Huang@nxp.com>
Reviewed-by: Fabio Estevam <fabio.estevam@nxp.com>
^ permalink raw reply
* [PATCH V4 11/26] iommu/amd: deprecate pci_get_bus_and_slot()
From: Sinan Kaya @ 2018-01-04 12:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1513661883-28662-12-git-send-email-okaya@codeaurora.org>
On 12/19/2017 12:37 AM, Sinan Kaya wrote:
> pci_get_bus_and_slot() is restrictive such that it assumes domain=0 as
> where a PCI device is present. This restricts the device drivers to be
> reused for other domain numbers.
>
> Getting ready to remove pci_get_bus_and_slot() function in favor of
> pci_get_domain_bus_and_slot().
>
> Hard-code the domain number as 0 for the AMD IOMMU driver.
>
> Signed-off-by: Sinan Kaya <okaya@codeaurora.org>
> ---
> drivers/iommu/amd_iommu.c | 3 ++-
> drivers/iommu/amd_iommu_init.c | 9 +++++----
> drivers/iommu/amd_iommu_v2.c | 3 ++-
> 3 files changed, 9 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
> index 7d5eb00..821547b 100644
> --- a/drivers/iommu/amd_iommu.c
> +++ b/drivers/iommu/amd_iommu.c
> @@ -527,7 +527,8 @@ static void amd_iommu_report_page_fault(u16 devid, u16 domain_id,
> struct iommu_dev_data *dev_data = NULL;
> struct pci_dev *pdev;
>
> - pdev = pci_get_bus_and_slot(PCI_BUS_NUM(devid), devid & 0xff);
> + pdev = pci_get_domain_bus_and_slot(0, PCI_BUS_NUM(devid),
> + devid & 0xff);
> if (pdev)
> dev_data = get_dev_data(&pdev->dev);
>
> diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
> index 6fe2d03..4e4a615 100644
> --- a/drivers/iommu/amd_iommu_init.c
> +++ b/drivers/iommu/amd_iommu_init.c
> @@ -1697,8 +1697,8 @@ static int iommu_init_pci(struct amd_iommu *iommu)
> u32 range, misc, low, high;
> int ret;
>
> - iommu->dev = pci_get_bus_and_slot(PCI_BUS_NUM(iommu->devid),
> - iommu->devid & 0xff);
> + iommu->dev = pci_get_domain_bus_and_slot(0, PCI_BUS_NUM(iommu->devid),
> + iommu->devid & 0xff);
> if (!iommu->dev)
> return -ENODEV;
>
> @@ -1764,8 +1764,9 @@ static int iommu_init_pci(struct amd_iommu *iommu)
> if (is_rd890_iommu(iommu->dev)) {
> int i, j;
>
> - iommu->root_pdev = pci_get_bus_and_slot(iommu->dev->bus->number,
> - PCI_DEVFN(0, 0));
> + iommu->root_pdev =
> + pci_get_domain_bus_and_slot(0, iommu->dev->bus->number,
> + PCI_DEVFN(0, 0));
>
> /*
> * Some rd890 systems may not be fully reconfigured by the
> diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c
> index 7d94e1d..8696382 100644
> --- a/drivers/iommu/amd_iommu_v2.c
> +++ b/drivers/iommu/amd_iommu_v2.c
> @@ -564,7 +564,8 @@ static int ppr_notifier(struct notifier_block *nb, unsigned long e, void *data)
> finish = (iommu_fault->tag >> 9) & 1;
>
> devid = iommu_fault->device_id;
> - pdev = pci_get_bus_and_slot(PCI_BUS_NUM(devid), devid & 0xff);
> + pdev = pci_get_domain_bus_and_slot(0, PCI_BUS_NUM(devid),
> + devid & 0xff);
> if (!pdev)
> return -ENODEV;
> dev_data = get_dev_data(&pdev->dev);
>
Any comments from the IOMMU people?
--
Sinan Kaya
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 V2] ARM: imx_v6_v7_defconfig: select the CONFIG_CPUFREQ_DT
From: Anson Huang @ 2018-01-04 12:06 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAOMZO5DnSVKvteBtNB5RqXg3v0kV889w9eDOw=rjx90SiiPx1A@mail.gmail.com>
Best Regards!
Anson Huang
> -----Original Message-----
> From: Fabio Estevam [mailto:festevam at gmail.com]
> Sent: 2018-01-04 7:37 PM
> To: Anson Huang <anson.huang@nxp.com>
> Cc: Shawn Guo <shawnguo@kernel.org>; Sascha Hauer
> <kernel@pengutronix.de>; Fabio Estevam <fabio.estevam@nxp.com>; Russell
> King - ARM Linux <linux@armlinux.org.uk>; linux-kernel <linux-
> kernel at vger.kernel.org>; moderated list:ARM/FREESCALE IMX / MXC ARM
> ARCHITECTURE <linux-arm-kernel@lists.infradead.org>
> Subject: Re: [PATCH V2] ARM: imx_v6_v7_defconfig: select the
> CONFIG_CPUFREQ_DT
>
> On Thu, Jan 4, 2018 at 4:39 PM, Anson Huang <Anson.Huang@nxp.com> wrote:
>
> > diff --git a/arch/arm/configs/imx_v6_v7_defconfig
> > b/arch/arm/configs/imx_v6_v7_defconfig
> > index 29cd1ac..885db90 100644
> > --- a/arch/arm/configs/imx_v6_v7_defconfig
> > +++ b/arch/arm/configs/imx_v6_v7_defconfig
> > @@ -58,6 +58,7 @@ CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
> > CONFIG_CPU_FREQ_GOV_POWERSAVE=y
> > CONFIG_CPU_FREQ_GOV_USERSPACE=y
> > CONFIG_CPU_FREQ_GOV_CONSERVATIVE=y
> > +CONFIG_CPUFREQ_DT=y
> > CONFIG_ARM_IMX6Q_CPUFREQ=y
> > CONFIG_CPU_IDLE=y
> > CONFIG_VFP=y
> > @@ -318,14 +319,6 @@ CONFIG_USB_CONFIGFS_F_MIDI=y
> > CONFIG_USB_CONFIGFS_F_HID=y CONFIG_USB_CONFIGFS_F_UVC=y
> > CONFIG_USB_CONFIGFS_F_PRINTER=y -CONFIG_USB_ZERO=m -
> CONFIG_USB_AUDIO=m
> > -CONFIG_USB_ETH=m -CONFIG_USB_G_NCM=m -
> CONFIG_USB_GADGETFS=m
> > -CONFIG_USB_FUNCTIONFS=m -CONFIG_USB_MASS_STORAGE=m
> > -CONFIG_USB_G_SERIAL=m
>
> Not sure why these are getting removed automatically.
>
> > CONFIG_MMC=y
> > CONFIG_MMC_SDHCI=y
> > CONFIG_MMC_SDHCI_PLTFM=y
> > @@ -350,7 +343,6 @@ CONFIG_RTC_DRV_PCF8563=y
> CONFIG_RTC_DRV_M41T80=y
> > CONFIG_RTC_DRV_MC13XXX=y CONFIG_RTC_DRV_MXC=y
> > -CONFIG_RTC_DRV_MXC_V2=y
>
> This is the rtc driver for mx53.
>
> This driver will land in 4.16, so that's the reason it got removed automatically by
> savedefconfig.
>
> It would be safer if your patch could only add a single line:
> 'CONFIG_CPUFREQ_DT=y'.
Thanks Fabio, I send a V3 patch with the only change.
Anson.
^ permalink raw reply
* [RESEND PATCH v2 14/15] ASoC: qcom: apq8096: Add db820c machine driver
From: Mark Brown @ 2018-01-04 12:02 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <f72f32dd-e248-47c3-23cc-eabe1b85d9ae@codeaurora.org>
On Wed, Jan 03, 2018 at 09:20:45AM -0800, Stephen Boyd wrote:
> On 12/14/2017 09:34 AM, srinivas.kandagatla at linaro.org wrote:
> > uThis patch adds support to DB820c machine driver.
> > + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
> Why do we need to do this? Can you add some sort of comment in the code
> about why?
And why are we applying DMA restrictions in a machine driver?
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 488 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20180104/e5b6f774/attachment.sig>
^ permalink raw reply
* Tegra baseline test results for v4.15-rc6
From: Jon Hunter @ 2018-01-04 11:51 UTC (permalink / raw)
To: linux-arm-kernel
Here are some basic Tegra test results for Linux v4.15-rc6.
Logs and other details at:
https://nvtb.github.io//linux/test_v4.15-rc6/20180102073103/
Test summary - 84% Success
--------------------------
Build: zImage:
Pass: ( 3/ 3): multi_v7_defconfig, tegra_defconfig,
tegra_defconfig%tegra-fw
Build: Image:
Pass: ( 3/ 3): defconfig, defconfig%jetson-tx2,
defconfig%jetson-tx1
Boot to userspace: defconfig:
Pass: ( 4/ 4): qemu-vexpress64, tegra132-norrin,
tegra210-p2371-0000, tegra210-smaug
Boot to userspace: defconfig%jetson-tx1:
Pass: ( 2/ 2): tegra210-p2371-0000, tegra210-p2371-2180
Boot to userspace: defconfig%jetson-tx2:
Pass: ( 1/ 1): tegra186-p2771-0000
Boot to userspace: multi_v7_defconfig:
FAIL: ( 1/ 5): tegra124-nyan-big
Pass: ( 4/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
tegra20-trimslice, tegra30-beaver
Boot to userspace: tegra_defconfig:
FAIL: ( 1/ 5): tegra124-nyan-big
Pass: ( 4/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
tegra20-trimslice, tegra30-beaver
Boot to userspace: tegra_defconfig%tegra-fw:
FAIL: ( 1/ 2): tegra124-nyan-big
Pass: ( 1/ 2): tegra124-jetson-tk1
PM: System suspend: multi_v7_defconfig:
FAIL: ( 1/ 5): tegra124-nyan-big
Pass: ( 4/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
tegra20-trimslice, tegra30-beaver
PM: System suspend: tegra_defconfig:
FAIL: ( 1/ 5): tegra124-nyan-big
Pass: ( 4/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
tegra20-trimslice, tegra30-beaver
PM: System suspend: tegra_defconfig%tegra-fw:
FAIL: ( 1/ 2): tegra124-nyan-big
Pass: ( 1/ 2): tegra124-jetson-tk1
vmlinux object size
(delta in bytes from test_v4.15-rc5 (464e1d5f23cca236b930ef068c328a64cab78fb1)):
text data bss total kernel
+3476 +1932 0 +5408 defconfig
+2748 +408 0 +3156 multi_v7_defconfig
+2368 +152 0 +2520 tegra_defconfig
Boot-time memory difference
(delta in bytes from test_v4.15-rc5 (464e1d5f23cca236b930ef068c328a64cab78fb1))
avail rsrvd high freed board kconfig dtb
. . . . qemu-vexpress64 defconfig __internal
. . . . tegra114-dalmore-a04 multi_v7_defconfig tegra114-dalmore
. . . . tegra114-dalmore-a04 tegra_defconfig tegra114-dalmore
. . . . tegra124-jetson-tk1 multi_v7_defconfig tegra124-jetson-tk1
. . . . tegra124-jetson-tk1 tegra_defconfig%tegr tegra124-jetson-tk1
. . . . tegra124-jetson-tk1 tegra_defconfig tegra124-jetson-tk1
. . . . tegra124-nyan-big multi_v7_defconfig tegra124-nyan-big
. . . . tegra124-nyan-big tegra_defconfig%tegr tegra124-nyan-big
. . . . tegra124-nyan-big tegra_defconfig tegra124-nyan-big
. . . . tegra132-norrin defconfig tegra132-norrin
. . . . tegra186-p2771-0000 defconfig%jetson-tx2 tegra186-p2771-0000
. . . . tegra20-trimslice multi_v7_defconfig tegra20-trimslice
. . . . tegra20-trimslice tegra_defconfig tegra20-trimslice
. . . . tegra210-p2371-0000 defconfig%jetson-tx1 tegra210-p2371-0000
. . . . tegra210-p2371-0000 defconfig tegra210-p2371-0000
. . . . tegra210-p2371-2180 defconfig%jetson-tx1 tegra210-p2371-2180
. . . . tegra210-smaug defconfig tegra210-smaug
. . . . tegra30-beaver multi_v7_defconfig tegra30-beaver
. . . . tegra30-beaver tegra_defconfig tegra30-beaver
--
nvpublic
^ permalink raw reply
* Tegra baseline test results for v4.15-rc5
From: Jon Hunter @ 2018-01-04 11:51 UTC (permalink / raw)
To: linux-arm-kernel
Here are some basic Tegra test results for Linux v4.15-rc5.
Logs and other details at:
https://nvtb.github.io//linux/test_v4.15-rc5/20171223210103/
Test summary - 84% Success
--------------------------
Build: zImage:
Pass: ( 3/ 3): multi_v7_defconfig, tegra_defconfig,
tegra_defconfig%tegra-fw
Build: Image:
Pass: ( 3/ 3): defconfig, defconfig%jetson-tx2,
defconfig%jetson-tx1
Boot to userspace: defconfig:
Pass: ( 4/ 4): qemu-vexpress64, tegra132-norrin,
tegra210-p2371-0000, tegra210-smaug
Boot to userspace: defconfig%jetson-tx1:
Pass: ( 2/ 2): tegra210-p2371-0000, tegra210-p2371-2180
Boot to userspace: defconfig%jetson-tx2:
Pass: ( 1/ 1): tegra186-p2771-0000
Boot to userspace: multi_v7_defconfig:
FAIL: ( 1/ 5): tegra124-nyan-big
Pass: ( 4/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
tegra20-trimslice, tegra30-beaver
Boot to userspace: tegra_defconfig:
FAIL: ( 1/ 5): tegra124-nyan-big
Pass: ( 4/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
tegra20-trimslice, tegra30-beaver
Boot to userspace: tegra_defconfig%tegra-fw:
FAIL: ( 1/ 2): tegra124-nyan-big
Pass: ( 1/ 2): tegra124-jetson-tk1
PM: System suspend: multi_v7_defconfig:
FAIL: ( 1/ 5): tegra124-nyan-big
Pass: ( 4/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
tegra20-trimslice, tegra30-beaver
PM: System suspend: tegra_defconfig:
FAIL: ( 1/ 5): tegra124-nyan-big
Pass: ( 4/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
tegra20-trimslice, tegra30-beaver
PM: System suspend: tegra_defconfig%tegra-fw:
FAIL: ( 1/ 2): tegra124-nyan-big
Pass: ( 1/ 2): tegra124-jetson-tk1
vmlinux object size
(delta in bytes from test_v4.15-rc4 (1291a0d5049dbc06baaaf66a9ff3f53db493b19b)):
text data bss total kernel
+48 -48 0 0 defconfig
+1232 0 0 +1232 multi_v7_defconfig
+1140 +64 0 +1204 tegra_defconfig
Boot-time memory difference
(delta in bytes from test_v4.15-rc4 (1291a0d5049dbc06baaaf66a9ff3f53db493b19b))
avail rsrvd high freed board kconfig dtb
. . . . qemu-vexpress64 defconfig __internal
. . . . tegra114-dalmore-a04 multi_v7_defconfig tegra114-dalmore
. . . . tegra114-dalmore-a04 tegra_defconfig tegra114-dalmore
. . . . tegra124-jetson-tk1 multi_v7_defconfig tegra124-jetson-tk1
. . . . tegra124-jetson-tk1 tegra_defconfig%tegr tegra124-jetson-tk1
. . . . tegra124-jetson-tk1 tegra_defconfig tegra124-jetson-tk1
. . . . tegra124-nyan-big multi_v7_defconfig tegra124-nyan-big
. . . . tegra124-nyan-big tegra_defconfig%tegr tegra124-nyan-big
. . . . tegra124-nyan-big tegra_defconfig tegra124-nyan-big
. . . . tegra132-norrin defconfig tegra132-norrin
. . . . tegra186-p2771-0000 defconfig%jetson-tx2 tegra186-p2771-0000
. . . . tegra20-trimslice multi_v7_defconfig tegra20-trimslice
. . . . tegra20-trimslice tegra_defconfig tegra20-trimslice
. . . . tegra210-p2371-0000 defconfig%jetson-tx1 tegra210-p2371-0000
. . . . tegra210-p2371-0000 defconfig tegra210-p2371-0000
. . . . tegra210-p2371-2180 defconfig%jetson-tx1 tegra210-p2371-2180
. . . . tegra210-smaug defconfig tegra210-smaug
. . . . tegra30-beaver multi_v7_defconfig tegra30-beaver
. . . . tegra30-beaver tegra_defconfig tegra30-beaver
--
nvpublic
^ permalink raw reply
* Tegra baseline test results for v4.15-rc4
From: Jon Hunter @ 2018-01-04 11:51 UTC (permalink / raw)
To: linux-arm-kernel
Here are some basic Tegra test results for Linux v4.15-rc4.
Logs and other details at:
https://nvtb.github.io//linux/test_v4.15-rc4/20171217193104/
Test summary - 84% Success
--------------------------
Build: zImage:
Pass: ( 3/ 3): multi_v7_defconfig, tegra_defconfig,
tegra_defconfig%tegra-fw
Build: Image:
Pass: ( 3/ 3): defconfig, defconfig%jetson-tx2,
defconfig%jetson-tx1
Boot to userspace: defconfig:
Pass: ( 4/ 4): qemu-vexpress64, tegra132-norrin,
tegra210-p2371-0000, tegra210-smaug
Boot to userspace: defconfig%jetson-tx1:
Pass: ( 2/ 2): tegra210-p2371-0000, tegra210-p2371-2180
Boot to userspace: defconfig%jetson-tx2:
Pass: ( 1/ 1): tegra186-p2771-0000
Boot to userspace: multi_v7_defconfig:
FAIL: ( 1/ 5): tegra124-nyan-big
Pass: ( 4/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
tegra20-trimslice, tegra30-beaver
Boot to userspace: tegra_defconfig:
FAIL: ( 1/ 5): tegra124-nyan-big
Pass: ( 4/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
tegra20-trimslice, tegra30-beaver
Boot to userspace: tegra_defconfig%tegra-fw:
FAIL: ( 1/ 2): tegra124-nyan-big
Pass: ( 1/ 2): tegra124-jetson-tk1
PM: System suspend: multi_v7_defconfig:
FAIL: ( 1/ 5): tegra124-nyan-big
Pass: ( 4/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
tegra20-trimslice, tegra30-beaver
PM: System suspend: tegra_defconfig:
FAIL: ( 1/ 5): tegra124-nyan-big
Pass: ( 4/ 5): tegra114-dalmore-a04, tegra124-jetson-tk1,
tegra20-trimslice, tegra30-beaver
PM: System suspend: tegra_defconfig%tegra-fw:
FAIL: ( 1/ 2): tegra124-nyan-big
Pass: ( 1/ 2): tegra124-jetson-tk1
vmlinux object size
(delta in bytes from test_v4.15-rc3 (50c4c4e268a2d7a3e58ebb698ac74da0de40ae36)):
text data bss total kernel
-571 +732 0 +161 defconfig
+1189 +12 0 +1201 multi_v7_defconfig
+1069 +76 0 +1145 tegra_defconfig
Boot-time memory difference
(delta in bytes from test_v4.15-rc3 (50c4c4e268a2d7a3e58ebb698ac74da0de40ae36))
avail rsrvd high freed board kconfig dtb
. . . . qemu-vexpress64 defconfig __internal
. . . . tegra114-dalmore-a04 multi_v7_defconfig tegra114-dalmore
. . . . tegra114-dalmore-a04 tegra_defconfig tegra114-dalmore
. . . . tegra124-jetson-tk1 multi_v7_defconfig tegra124-jetson-tk1
. . . . tegra124-jetson-tk1 tegra_defconfig%tegr tegra124-jetson-tk1
. . . . tegra124-jetson-tk1 tegra_defconfig tegra124-jetson-tk1
. . . . tegra124-nyan-big multi_v7_defconfig tegra124-nyan-big
. . . . tegra124-nyan-big tegra_defconfig%tegr tegra124-nyan-big
. . . . tegra124-nyan-big tegra_defconfig tegra124-nyan-big
. . . . tegra132-norrin defconfig tegra132-norrin
. . . . tegra186-p2771-0000 defconfig%jetson-tx2 tegra186-p2771-0000
. . . . tegra20-trimslice multi_v7_defconfig tegra20-trimslice
. . . . tegra20-trimslice tegra_defconfig tegra20-trimslice
-64k 64k . . tegra210-p2371-0000 defconfig%jetson-tx1 tegra210-p2371-0000
. . . . tegra210-p2371-0000 defconfig tegra210-p2371-0000
. . . . tegra210-p2371-2180 defconfig%jetson-tx1 tegra210-p2371-2180
. . . . tegra210-smaug defconfig tegra210-smaug
. . . . tegra30-beaver multi_v7_defconfig tegra30-beaver
. . . . tegra30-beaver tegra_defconfig tegra30-beaver
--
nvpublic
^ 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