* [PATCH v2 5/9] clk: stm32f4: Add I2S clock
From: gabriel.fernandez at st.com @ 2016-11-24 14:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479998749-20358-1-git-send-email-gabriel.fernandez@st.com>
From: Gabriel Fernandez <gabriel.fernandez@st.com>
This patch introduces I2S clock for stm32f4 soc.
The I2S clock could be derived from an external clock or from pll-i2s
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
Documentation/devicetree/bindings/clock/st,stm32-rcc.txt | 4 +++-
drivers/clk/clk-stm32f4.c | 14 +++++++++++++-
include/dt-bindings/clock/stm32f4-clock.h | 3 ++-
3 files changed, 18 insertions(+), 3 deletions(-)
diff --git a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
index 4cd08da6..8c1ca68 100644
--- a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
+++ b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
@@ -19,6 +19,7 @@ Required properties:
use.
- clocks: External oscillator clock phandle
- high speed external clock signal (HSE)
+ - external I2S clock (I2S_CKIN)
Example:
@@ -27,7 +28,7 @@ Example:
#clock-cells = <2>
compatible = "st,stm32f42xx-rcc", "st,stm32-rcc";
reg = <0x40023800 0x400>;
- clocks = <&clk_hse>;
+ clocks = <&clk_hse>, <&clk_i2s_ckin>;
};
Specifying gated clocks
@@ -77,6 +78,7 @@ The secondary index is bound with the following magic numbers:
6 PLL_VCO_I2S (vco frequency of I2S pll)
7 PLL_VCO_SAI (vco frequency of SAI pll)
8 CLK_LCD (LCD-TFT)
+ 9 CLK_I2S (I2S clocks)
Example:
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
index 86244fc..3063b30 100644
--- a/drivers/clk/clk-stm32f4.c
+++ b/drivers/clk/clk-stm32f4.c
@@ -935,6 +935,8 @@ static struct clk_hw *stm32_register_cclk(struct device *dev, const char *name,
static const char *lcd_parent[1] = { "pllsai-r-div" };
+static const char *i2s_parents[2] = { "plli2s-r", NULL };
+
struct stm32_aux_clk {
int idx;
const char *name;
@@ -969,6 +971,12 @@ struct stm32f4_clk_data {
STM32F4_RCC_APB2ENR, 26,
CLK_SET_RATE_PARENT
},
+ {
+ CLK_I2S, "i2s", i2s_parents, ARRAY_SIZE(i2s_parents),
+ STM32F4_RCC_CFGR, 23, 1,
+ NO_GATE, 0,
+ CLK_SET_RATE_PARENT
+ },
};
static const struct stm32f4_clk_data stm32f429_clk_data = {
@@ -1063,7 +1071,7 @@ static struct clk_hw *stm32_register_aux_clk(const char *name,
static void __init stm32f4_rcc_init(struct device_node *np)
{
- const char *hse_clk;
+ const char *hse_clk, *i2s_in_clk;
int n;
const struct of_device_id *match;
const struct stm32f4_clk_data *data;
@@ -1098,6 +1106,10 @@ static void __init stm32f4_rcc_init(struct device_node *np)
hse_clk = of_clk_get_parent_name(np, 0);
+ i2s_in_clk = of_clk_get_parent_name(np, 1);
+
+ i2s_parents[1] = i2s_in_clk;
+
clk_register_fixed_rate_with_accuracy(NULL, "hsi", NULL, 0,
16000000, 160000);
pllcfgr = readl(base + STM32F4_RCC_PLLCFGR);
diff --git a/include/dt-bindings/clock/stm32f4-clock.h b/include/dt-bindings/clock/stm32f4-clock.h
index 1be4a3a..b129ab9 100644
--- a/include/dt-bindings/clock/stm32f4-clock.h
+++ b/include/dt-bindings/clock/stm32f4-clock.h
@@ -28,7 +28,8 @@
#define PLL_VCO_I2S 6
#define PLL_VCO_SAI 7
#define CLK_LCD 8
+#define CLK_I2S 9
-#define END_PRIMARY_CLK 9
+#define END_PRIMARY_CLK 10
#endif
--
1.9.1
^ permalink raw reply related
* [PATCH v2 4/9] clk: stm32f4: Add lcd-tft clock
From: gabriel.fernandez at st.com @ 2016-11-24 14:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479998749-20358-1-git-send-email-gabriel.fernandez@st.com>
From: Gabriel Fernandez <gabriel.fernandez@st.com>
This patch introduces lcd-tft clock for stm32f4 soc.
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
.../devicetree/bindings/clock/st,stm32-rcc.txt | 1 +
drivers/clk/clk-stm32f4.c | 118 +++++++++++++++++++++
include/dt-bindings/clock/stm32f4-clock.h | 3 +-
3 files changed, 121 insertions(+), 1 deletion(-)
diff --git a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
index eb6733c..4cd08da6 100644
--- a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
+++ b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
@@ -76,6 +76,7 @@ The secondary index is bound with the following magic numbers:
5 CLK_RTC (real-time clock)
6 PLL_VCO_I2S (vco frequency of I2S pll)
7 PLL_VCO_SAI (vco frequency of SAI pll)
+ 8 CLK_LCD (LCD-TFT)
Example:
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
index 3918305..86244fc 100644
--- a/drivers/clk/clk-stm32f4.c
+++ b/drivers/clk/clk-stm32f4.c
@@ -47,6 +47,7 @@
#define STM32F4_RCC_CSR 0x74
#define STM32F4_RCC_PLLI2SCFGR 0x84
#define STM32F4_RCC_PLLSAICFGR 0x88
+#define STM32F4_RCC_DCKCFGR 0x8c
struct stm32f4_gate_data {
u8 offset;
@@ -932,11 +933,42 @@ static struct clk_hw *stm32_register_cclk(struct device *dev, const char *name,
"no-clock", "lse", "lsi", "hse-rtc"
};
+static const char *lcd_parent[1] = { "pllsai-r-div" };
+
+struct stm32_aux_clk {
+ int idx;
+ const char *name;
+ const char * const *parent_names;
+ int num_parents;
+ int offset_mux;
+ u8 shift;
+ u8 mask;
+ int offset_gate;
+ u8 bit_idx;
+ unsigned long flags;
+};
+
struct stm32f4_clk_data {
const struct stm32f4_gate_data *gates_data;
const u64 *gates_map;
int gates_num;
const struct stm32f4_pll_data *pll_data;
+ const struct stm32_aux_clk *aux_clk;
+ int aux_clk_num;
+};
+
+#define NONE -1
+#define NO_IDX NONE
+#define NO_MUX NONE
+#define NO_GATE NONE
+
+static const struct stm32_aux_clk stm32f429_aux_clk[] = {
+ {
+ CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
+ NO_MUX, 0, 0,
+ STM32F4_RCC_APB2ENR, 26,
+ CLK_SET_RATE_PARENT
+ },
};
static const struct stm32f4_clk_data stm32f429_clk_data = {
@@ -944,6 +976,8 @@ struct stm32f4_clk_data {
.gates_map = stm32f42xx_gate_map,
.gates_num = ARRAY_SIZE(stm32f429_gates),
.pll_data = stm32f429_pll,
+ .aux_clk = stm32f429_aux_clk,
+ .aux_clk_num = ARRAY_SIZE(stm32f429_aux_clk),
};
static const struct stm32f4_clk_data stm32f469_clk_data = {
@@ -951,6 +985,8 @@ struct stm32f4_clk_data {
.gates_map = stm32f46xx_gate_map,
.gates_num = ARRAY_SIZE(stm32f469_gates),
.pll_data = stm32f469_pll,
+ .aux_clk = stm32f429_aux_clk,
+ .aux_clk_num = ARRAY_SIZE(stm32f429_aux_clk),
};
static const struct of_device_id stm32f4_of_match[] = {
@@ -965,6 +1001,66 @@ struct stm32f4_clk_data {
{}
};
+static struct clk_hw *stm32_register_aux_clk(const char *name,
+ const char * const *parent_names, int num_parents,
+ int offset_mux, u8 shift, u8 mask,
+ int offset_gate, u8 bit_idx,
+ unsigned long flags, spinlock_t *lock)
+{
+ struct clk_hw *hw;
+ struct clk_gate *gate;
+ struct clk_mux *mux = NULL;
+ struct clk_hw *mux_hw = NULL, *gate_hw = NULL;
+ const struct clk_ops *mux_ops = NULL, *gate_ops = NULL;
+
+ if (offset_gate != NO_GATE) {
+ gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+ if (!gate) {
+ hw = ERR_PTR(-EINVAL);
+ goto fail;
+ }
+
+ gate->reg = base + offset_gate;
+ gate->bit_idx = bit_idx;
+ gate->flags = 0;
+ gate->lock = lock;
+ gate_hw = &gate->hw;
+ gate_ops = &clk_gate_ops;
+ }
+
+ if (offset_mux != NO_MUX) {
+ mux = kzalloc(sizeof(*mux), GFP_KERNEL);
+ if (!mux) {
+ kfree(gate);
+ hw = ERR_PTR(-EINVAL);
+ goto fail;
+ }
+
+ mux->reg = base + offset_mux;
+ mux->shift = shift;
+ mux->mask = mask;
+ mux->flags = 0;
+ mux_hw = &mux->hw;
+ mux_ops = &clk_mux_ops;
+ }
+
+ if (mux_hw == NULL && gate_hw == NULL)
+ return ERR_PTR(-EINVAL);
+
+ hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
+ mux_hw, mux_ops,
+ NULL, NULL,
+ gate_hw, gate_ops,
+ flags);
+
+ if (IS_ERR(hw)) {
+ kfree(gate);
+ kfree(mux);
+ }
+fail:
+ return hw;
+}
+
static void __init stm32f4_rcc_init(struct device_node *np)
{
const char *hse_clk;
@@ -1120,6 +1216,28 @@ static void __init stm32f4_rcc_init(struct device_node *np)
goto fail;
}
+ for (n = 0; n < data->aux_clk_num; n++) {
+ const struct stm32_aux_clk *aux_clk;
+ struct clk_hw *hw;
+
+ aux_clk = &data->aux_clk[n];
+
+ hw = stm32_register_aux_clk(aux_clk->name,
+ aux_clk->parent_names, aux_clk->num_parents,
+ aux_clk->offset_mux, aux_clk->shift,
+ aux_clk->mask, aux_clk->offset_gate,
+ aux_clk->bit_idx, aux_clk->flags,
+ &stm32f4_clk_lock);
+
+ if (IS_ERR(hw)) {
+ pr_warn("Unable to register %s clk\n", aux_clk->name);
+ continue;
+ }
+
+ if (aux_clk->idx != NO_IDX)
+ clks[aux_clk->idx] = hw;
+ }
+
of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL);
return;
fail:
diff --git a/include/dt-bindings/clock/stm32f4-clock.h b/include/dt-bindings/clock/stm32f4-clock.h
index 56b8e10..1be4a3a 100644
--- a/include/dt-bindings/clock/stm32f4-clock.h
+++ b/include/dt-bindings/clock/stm32f4-clock.h
@@ -27,7 +27,8 @@
#define CLK_RTC 5
#define PLL_VCO_I2S 6
#define PLL_VCO_SAI 7
+#define CLK_LCD 8
-#define END_PRIMARY_CLK 8
+#define END_PRIMARY_CLK 9
#endif
--
1.9.1
^ permalink raw reply related
* [PATCH v2 3/9] clk: stm32f4: Add post divisor for I2S & SAI PLLs
From: gabriel.fernandez at st.com @ 2016-11-24 14:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479998749-20358-1-git-send-email-gabriel.fernandez@st.com>
From: Gabriel Fernandez <gabriel.fernandez@st.com>
This patch adds post dividers of I2S & SAI PLLs.
These dividers are managed by a dedicated register (RCC_DCKCFGR).
The PLL should be off before a set rate.
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
drivers/clk/clk-stm32f4.c | 41 +++++++++++++++++++++++++++++++++++++++++
1 file changed, 41 insertions(+)
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
index c2b62cc..3918305 100644
--- a/drivers/clk/clk-stm32f4.c
+++ b/drivers/clk/clk-stm32f4.c
@@ -357,6 +357,18 @@ struct stm32f4_pll {
#define to_stm32f4_pll(_gate) container_of(_gate, struct stm32f4_pll, gate)
+struct stm32f4_pll_post_div_data {
+ u8 pll_num;
+ const char *name;
+ const char *parent;
+ u8 flag;
+ u8 offset;
+ u8 shift;
+ u8 width;
+ u8 flag_div;
+ const struct clk_div_table *div_table;
+};
+
struct stm32f4_vco_data {
const char *vco_name;
u8 offset;
@@ -370,6 +382,18 @@ struct stm32f4_vco_data {
{ "vco-sai", STM32F4_RCC_PLLSAICFGR, 28, 29 },
};
+#define MAX_POST_DIV 3
+static const struct stm32f4_pll_post_div_data post_div_data[MAX_POST_DIV] = {
+ { PLL_I2S, "plli2s-q-div", "plli2s-q", CLK_SET_RATE_PARENT,
+ STM32F4_RCC_DCKCFGR, 0, 5, 0, NULL},
+
+ { PLL_SAI, "pllsai-q-div", "pllsai-q", CLK_SET_RATE_PARENT,
+ STM32F4_RCC_DCKCFGR, 8, 5, 0, NULL },
+
+ { PLL_SAI, "pllsai-r-div", "pllsai-r", CLK_SET_RATE_PARENT,
+ STM32F4_RCC_DCKCFGR, 16, 2, CLK_DIVIDER_POWER_OF_TWO},
+};
+
struct stm32f4_div_data {
u8 shift;
u8 width;
@@ -996,6 +1020,23 @@ static void __init stm32f4_rcc_init(struct device_node *np)
clks[PLL_VCO_SAI] = stm32f4_rcc_register_pll("vco_in",
&data->pll_data[2], &stm32f4_clk_lock);
+ for (n = 0; n < MAX_POST_DIV; n++) {
+ const struct stm32f4_pll_post_div_data *post_div;
+
+ post_div = &post_div_data[n];
+
+ clk_register_pll_div(post_div->name,
+ post_div->parent,
+ post_div->flag,
+ base + post_div->offset,
+ post_div->shift,
+ post_div->width,
+ post_div->flag_div,
+ post_div->div_table,
+ clks[post_div->pll_num],
+ &stm32f4_clk_lock);
+ }
+
sys_parents[1] = hse_clk;
clk_register_mux_table(
NULL, "sys", sys_parents, ARRAY_SIZE(sys_parents), 0,
--
1.9.1
^ permalink raw reply related
* [PATCH v2 2/9] clk: stm32f4: Add PLL_I2S & PLL_SAI for STM32F429/469 boards
From: gabriel.fernandez at st.com @ 2016-11-24 14:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479998749-20358-1-git-send-email-gabriel.fernandez@st.com>
From: Gabriel Fernandez <gabriel.fernandez@st.com>
This patch introduces PLL_I2S and PLL_SAI.
Vco clock of these PLLs can be modify by DT (only n multiplicator,
m divider is still fixed by the boot-loader).
Each PLL has 3 dividers. PLL should be off when we modify the rate.
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
.../devicetree/bindings/clock/st,stm32-rcc.txt | 2 +
drivers/clk/clk-stm32f4.c | 342 ++++++++++++++++++++-
include/dt-bindings/clock/stm32f4-clock.h | 4 +-
3 files changed, 332 insertions(+), 16 deletions(-)
diff --git a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
index 18e05c2..eb6733c 100644
--- a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
+++ b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
@@ -74,6 +74,8 @@ The secondary index is bound with the following magic numbers:
crystal or ceramic resonator)
4 CLK_HSE_RTC (HSE division factor for RTC clock)
5 CLK_RTC (real-time clock)
+ 6 PLL_VCO_I2S (vco frequency of I2S pll)
+ 7 PLL_VCO_SAI (vco frequency of SAI pll)
Example:
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
index 39965ab..c2b62cc 100644
--- a/drivers/clk/clk-stm32f4.c
+++ b/drivers/clk/clk-stm32f4.c
@@ -35,6 +35,7 @@
*/
#include <dt-bindings/clock/stm32f4-clock.h>
+#define STM32F4_RCC_CR 0x00
#define STM32F4_RCC_PLLCFGR 0x04
#define STM32F4_RCC_CFGR 0x08
#define STM32F4_RCC_AHB1ENR 0x30
@@ -44,6 +45,8 @@
#define STM32F4_RCC_APB2ENR 0x44
#define STM32F4_RCC_BDCR 0x70
#define STM32F4_RCC_CSR 0x74
+#define STM32F4_RCC_PLLI2SCFGR 0x84
+#define STM32F4_RCC_PLLSAICFGR 0x88
struct stm32f4_gate_data {
u8 offset;
@@ -329,23 +332,312 @@ static struct clk *clk_register_apb_mul(struct device *dev, const char *name,
return clk;
}
-/*
- * Decode current PLL state and (statically) model the state we inherit from
- * the bootloader.
- */
-static void stm32f4_rcc_register_pll(const char *hse_clk, const char *hsi_clk)
+enum {
+ PLL,
+ PLL_I2S,
+ PLL_SAI,
+};
+
+static const struct clk_div_table pll_divp_table[] = {
+ { 0, 2 }, { 1, 4 }, { 2, 6 }, { 3, 8 }, { 0 }
+};
+
+static const struct clk_div_table pll_divr_table[] = {
+ { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 }, { 7, 7 }, { 0 }
+};
+
+struct stm32f4_pll {
+ spinlock_t *lock;
+ struct clk_gate gate;
+ u8 offset;
+ u8 bit_rdy_idx;
+ u8 status;
+ u8 n_start;
+};
+
+#define to_stm32f4_pll(_gate) container_of(_gate, struct stm32f4_pll, gate)
+
+struct stm32f4_vco_data {
+ const char *vco_name;
+ u8 offset;
+ u8 bit_idx;
+ u8 bit_rdy_idx;
+};
+
+static const struct stm32f4_vco_data vco_data[] = {
+ { "vco", STM32F4_RCC_PLLCFGR, 24, 25 },
+ { "vco-i2s", STM32F4_RCC_PLLI2SCFGR, 26, 27 },
+ { "vco-sai", STM32F4_RCC_PLLSAICFGR, 28, 29 },
+};
+
+struct stm32f4_div_data {
+ u8 shift;
+ u8 width;
+ u8 flag_div;
+ const struct clk_div_table *div_table;
+};
+
+#define MAX_PLL_DIV 3
+static const struct stm32f4_div_data div_data[MAX_PLL_DIV] = {
+ { 16, 2, 0, pll_divp_table },
+ { 24, 4, CLK_DIVIDER_ONE_BASED, NULL },
+ { 28, 3, 0, pll_divr_table },
+};
+
+struct stm32f4_pll_data {
+ u8 pll_num;
+ u8 n_start;
+ const char *div_name[MAX_PLL_DIV];
+};
+
+static const struct stm32f4_pll_data stm32f429_pll[MAX_PLL_DIV] = {
+ { PLL, 192, { "pll", "pll48", NULL } },
+ { PLL_I2S, 192, { NULL, "plli2s-q", "plli2s-r" } },
+ { PLL_SAI, 49, { NULL, "pllsai-q", "pllsai-r" } },
+};
+
+static const struct stm32f4_pll_data stm32f469_pll[MAX_PLL_DIV] = {
+ { PLL, 50, { "pll", "pll-q", NULL } },
+ { PLL_I2S, 50, { "plli2s-p", "plli2s-q", "plli2s-r" } },
+ { PLL_SAI, 50, { "pllsai-p", "pllsai-q", "pllsai-r" } },
+};
+
+static int stm32f4_pll_is_enabled(struct clk_hw *hw)
+{
+ return clk_gate_ops.is_enabled(hw);
+}
+
+static int stm32f4_pll_enable(struct clk_hw *hw)
+{
+ struct clk_gate *gate = to_clk_gate(hw);
+ struct stm32f4_pll *pll = to_stm32f4_pll(gate);
+ int ret = 0;
+ unsigned long reg;
+
+ ret = clk_gate_ops.enable(hw);
+
+ ret = readl_relaxed_poll_timeout_atomic(base + STM32F4_RCC_CR, reg,
+ reg & (1 << pll->bit_rdy_idx), 0, 10000);
+
+ return ret;
+}
+
+static void stm32f4_pll_disable(struct clk_hw *hw)
{
- unsigned long pllcfgr = readl(base + STM32F4_RCC_PLLCFGR);
+ clk_gate_ops.disable(hw);
+}
- unsigned long pllm = pllcfgr & 0x3f;
- unsigned long plln = (pllcfgr >> 6) & 0x1ff;
- unsigned long pllp = BIT(((pllcfgr >> 16) & 3) + 1);
- const char *pllsrc = pllcfgr & BIT(22) ? hse_clk : hsi_clk;
- unsigned long pllq = (pllcfgr >> 24) & 0xf;
+static unsigned long stm32f4_pll_recalc(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ struct clk_gate *gate = to_clk_gate(hw);
+ struct stm32f4_pll *pll = to_stm32f4_pll(gate);
+ unsigned long n;
- clk_register_fixed_factor(NULL, "vco", pllsrc, 0, plln, pllm);
- clk_register_fixed_factor(NULL, "pll", "vco", 0, 1, pllp);
- clk_register_fixed_factor(NULL, "pll48", "vco", 0, 1, pllq);
+ n = (readl(base + pll->offset) >> 6) & 0x1ff;
+
+ return parent_rate * n;
+}
+
+static long stm32f4_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ struct clk_gate *gate = to_clk_gate(hw);
+ struct stm32f4_pll *pll = to_stm32f4_pll(gate);
+ unsigned long n;
+
+ n = rate / *prate;
+
+ if (n < pll->n_start)
+ n = pll->n_start;
+ else if (n > 432)
+ n = 432;
+
+ return *prate * n;
+}
+
+static int stm32f4_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ struct clk_gate *gate = to_clk_gate(hw);
+ struct stm32f4_pll *pll = to_stm32f4_pll(gate);
+
+ unsigned long n;
+ unsigned long val;
+ int pll_state;
+
+ pll_state = stm32f4_pll_is_enabled(hw);
+
+ if (pll_state)
+ stm32f4_pll_disable(hw);
+
+ n = rate / parent_rate;
+
+ val = readl(base + pll->offset) & ~(0x1ff << 6);
+
+ writel(val | ((n & 0x1ff) << 6), base + pll->offset);
+
+ if (pll_state)
+ stm32f4_pll_enable(hw);
+
+ return 0;
+}
+
+static const struct clk_ops stm32f4_pll_gate_ops = {
+ .enable = stm32f4_pll_enable,
+ .disable = stm32f4_pll_disable,
+ .is_enabled = stm32f4_pll_is_enabled,
+ .recalc_rate = stm32f4_pll_recalc,
+ .round_rate = stm32f4_pll_round_rate,
+ .set_rate = stm32f4_pll_set_rate,
+};
+
+struct stm32f4_pll_div {
+ struct clk_divider div;
+ struct clk_hw *hw_pll;
+};
+
+#define to_pll_div_clk(_div) container_of(_div, struct stm32f4_pll_div, div)
+
+static unsigned long stm32f4_pll_div_recalc_rate(struct clk_hw *hw,
+ unsigned long parent_rate)
+{
+ return clk_divider_ops.recalc_rate(hw, parent_rate);
+}
+
+static long stm32f4_pll_div_round_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long *prate)
+{
+ return clk_divider_ops.round_rate(hw, rate, prate);
+}
+
+static int stm32f4_pll_div_set_rate(struct clk_hw *hw, unsigned long rate,
+ unsigned long parent_rate)
+{
+ int pll_state, ret;
+
+ struct clk_divider *div = to_clk_divider(hw);
+ struct stm32f4_pll_div *pll_div = to_pll_div_clk(div);
+
+ pll_state = stm32f4_pll_is_enabled(pll_div->hw_pll);
+
+ if (pll_state)
+ stm32f4_pll_disable(pll_div->hw_pll);
+
+ ret = clk_divider_ops.set_rate(hw, rate, parent_rate);
+
+ if (pll_state)
+ stm32f4_pll_enable(pll_div->hw_pll);
+
+ return ret;
+}
+
+const struct clk_ops stm32f4_pll_div_ops = {
+ .recalc_rate = stm32f4_pll_div_recalc_rate,
+ .round_rate = stm32f4_pll_div_round_rate,
+ .set_rate = stm32f4_pll_div_set_rate,
+};
+
+static struct clk_hw *clk_register_pll_div(const char *name,
+ const char *parent_name, unsigned long flags,
+ void __iomem *reg, u8 shift, u8 width,
+ u8 clk_divider_flags, const struct clk_div_table *table,
+ struct clk_hw *pll_hw, spinlock_t *lock)
+{
+ struct stm32f4_pll_div *pll_div;
+ struct clk_hw *hw;
+ struct clk_init_data init;
+ int ret;
+
+ /* allocate the divider */
+ pll_div = kzalloc(sizeof(*pll_div), GFP_KERNEL);
+ if (!pll_div)
+ return ERR_PTR(-ENOMEM);
+
+ init.name = name;
+ init.ops = &stm32f4_pll_div_ops;
+ init.flags = flags;
+ init.parent_names = (parent_name ? &parent_name : NULL);
+ init.num_parents = (parent_name ? 1 : 0);
+
+ /* struct clk_divider assignments */
+ pll_div->div.reg = reg;
+ pll_div->div.shift = shift;
+ pll_div->div.width = width;
+ pll_div->div.flags = clk_divider_flags;
+ pll_div->div.lock = lock;
+ pll_div->div.table = table;
+ pll_div->div.hw.init = &init;
+
+ pll_div->hw_pll = pll_hw;
+
+ /* register the clock */
+ hw = &pll_div->div.hw;
+ ret = clk_hw_register(NULL, hw);
+ if (ret) {
+ kfree(pll_div);
+ hw = ERR_PTR(ret);
+ }
+
+ return hw;
+}
+
+static struct clk_hw *stm32f4_rcc_register_pll(const char *pllsrc,
+ const struct stm32f4_pll_data *data, spinlock_t *lock)
+{
+ struct stm32f4_pll *pll;
+ struct clk_init_data init = { NULL };
+ void __iomem *reg;
+ struct clk_hw *pll_hw;
+ int ret;
+ int i;
+ const struct stm32f4_vco_data *vco;
+
+
+ pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+ if (!pll)
+ return ERR_PTR(-ENOMEM);
+
+ vco = &vco_data[data->pll_num];
+
+ init.name = vco->vco_name;
+ init.ops = &stm32f4_pll_gate_ops;
+ init.flags = CLK_SET_RATE_GATE;
+ init.parent_names = &pllsrc;
+ init.num_parents = 1;
+
+ pll->gate.lock = lock;
+ pll->gate.reg = base + STM32F4_RCC_CR;
+ pll->gate.bit_idx = vco->bit_idx;
+ pll->gate.hw.init = &init;
+
+ pll->offset = vco->offset;
+ pll->n_start = data->n_start;
+ pll->bit_rdy_idx = vco->bit_rdy_idx;
+ pll->status = (readl(base + STM32F4_RCC_CR) >> vco->bit_idx) & 0x1;
+
+ reg = base + pll->offset;
+
+ pll_hw = &pll->gate.hw;
+ ret = clk_hw_register(NULL, pll_hw);
+ if (ret) {
+ kfree(pll);
+ return ERR_PTR(ret);
+ }
+
+ for (i = 0; i < MAX_PLL_DIV; i++)
+ if (data->div_name[i])
+ clk_register_pll_div(data->div_name[i],
+ vco->vco_name,
+ 0,
+ reg,
+ div_data[i].shift,
+ div_data[i].width,
+ div_data[i].flag_div,
+ div_data[i].div_table,
+ pll_hw,
+ lock);
+ return pll_hw;
}
/*
@@ -620,18 +912,21 @@ struct stm32f4_clk_data {
const struct stm32f4_gate_data *gates_data;
const u64 *gates_map;
int gates_num;
+ const struct stm32f4_pll_data *pll_data;
};
static const struct stm32f4_clk_data stm32f429_clk_data = {
.gates_data = stm32f429_gates,
.gates_map = stm32f42xx_gate_map,
.gates_num = ARRAY_SIZE(stm32f429_gates),
+ .pll_data = stm32f429_pll,
};
static const struct stm32f4_clk_data stm32f469_clk_data = {
.gates_data = stm32f469_gates,
.gates_map = stm32f46xx_gate_map,
.gates_num = ARRAY_SIZE(stm32f469_gates),
+ .pll_data = stm32f469_pll,
};
static const struct of_device_id stm32f4_of_match[] = {
@@ -652,6 +947,9 @@ static void __init stm32f4_rcc_init(struct device_node *np)
int n;
const struct of_device_id *match;
const struct stm32f4_clk_data *data;
+ unsigned long pllcfgr;
+ const char *pllsrc;
+ unsigned long pllm;
base = of_iomap(np, 0);
if (!base) {
@@ -682,7 +980,21 @@ static void __init stm32f4_rcc_init(struct device_node *np)
clk_register_fixed_rate_with_accuracy(NULL, "hsi", NULL, 0,
16000000, 160000);
- stm32f4_rcc_register_pll(hse_clk, "hsi");
+ pllcfgr = readl(base + STM32F4_RCC_PLLCFGR);
+ pllsrc = pllcfgr & BIT(22) ? hse_clk : "hsi";
+ pllm = pllcfgr & 0x3f;
+
+ clk_hw_register_fixed_factor(NULL, "vco_in", pllsrc,
+ 0, 1, pllm);
+
+ stm32f4_rcc_register_pll("vco_in", &data->pll_data[0],
+ &stm32f4_clk_lock);
+
+ clks[PLL_VCO_I2S] = stm32f4_rcc_register_pll("vco_in",
+ &data->pll_data[1], &stm32f4_clk_lock);
+
+ clks[PLL_VCO_SAI] = stm32f4_rcc_register_pll("vco_in",
+ &data->pll_data[2], &stm32f4_clk_lock);
sys_parents[1] = hse_clk;
clk_register_mux_table(
diff --git a/include/dt-bindings/clock/stm32f4-clock.h b/include/dt-bindings/clock/stm32f4-clock.h
index 3132b6a..56b8e10 100644
--- a/include/dt-bindings/clock/stm32f4-clock.h
+++ b/include/dt-bindings/clock/stm32f4-clock.h
@@ -25,7 +25,9 @@
#define CLK_LSE 3
#define CLK_HSE_RTC 4
#define CLK_RTC 5
+#define PLL_VCO_I2S 6
+#define PLL_VCO_SAI 7
-#define END_PRIMARY_CLK 6
+#define END_PRIMARY_CLK 8
#endif
--
1.9.1
^ permalink raw reply related
* [PATCH v2 1/9] clk: stm32f4: Update DT bindings documentation
From: gabriel.fernandez at st.com @ 2016-11-24 14:45 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479998749-20358-1-git-send-email-gabriel.fernandez@st.com>
From: Gabriel Fernandez <gabriel.fernandez@st.com>
Creation of dt include file for specific stm32f4 clocks.
These specific clocks are not derived from system clock (SYSCLOCK)
We should use index 1 to use these clocks in DT.
e.g. <&rcc 1 CLK_LSI>
Signed-off-by: Gabriel Fernandez <gabriel.fernandez@st.com>
---
.../devicetree/bindings/clock/st,stm32-rcc.txt | 8 ++++++
drivers/clk/clk-stm32f4.c | 9 +++++--
include/dt-bindings/clock/stm32f4-clock.h | 31 ++++++++++++++++++++++
3 files changed, 46 insertions(+), 2 deletions(-)
create mode 100644 include/dt-bindings/clock/stm32f4-clock.h
diff --git a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
index 0532d81..18e05c2 100644
--- a/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
+++ b/Documentation/devicetree/bindings/clock/st,stm32-rcc.txt
@@ -17,6 +17,8 @@ Required properties:
property, containing a phandle to the clock device node, an index selecting
between gated clocks and other clocks and an index specifying the clock to
use.
+- clocks: External oscillator clock phandle
+ - high speed external clock signal (HSE)
Example:
@@ -25,6 +27,7 @@ Example:
#clock-cells = <2>
compatible = "st,stm32f42xx-rcc", "st,stm32-rcc";
reg = <0x40023800 0x400>;
+ clocks = <&clk_hse>;
};
Specifying gated clocks
@@ -66,6 +69,11 @@ The secondary index is bound with the following magic numbers:
0 SYSTICK
1 FCLK
+ 2 CLK_LSI (low-power clock source)
+ 3 CLK_LSE (generated from a 32.768 kHz low-speed external
+ crystal or ceramic resonator)
+ 4 CLK_HSE_RTC (HSE division factor for RTC clock)
+ 5 CLK_RTC (real-time clock)
Example:
diff --git a/drivers/clk/clk-stm32f4.c b/drivers/clk/clk-stm32f4.c
index 5eb05db..39965ab 100644
--- a/drivers/clk/clk-stm32f4.c
+++ b/drivers/clk/clk-stm32f4.c
@@ -28,6 +28,13 @@
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
+/*
+ * Include list of clocks wich are not derived from system clock (SYSCLOCK)
+ * The index of these clocks is the secondary index of DT bindings
+ *
+ */
+#include <dt-bindings/clock/stm32f4-clock.h>
+
#define STM32F4_RCC_PLLCFGR 0x04
#define STM32F4_RCC_CFGR 0x08
#define STM32F4_RCC_AHB1ENR 0x30
@@ -208,8 +215,6 @@ struct stm32f4_gate_data {
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
};
-enum { SYSTICK, FCLK, CLK_LSI, CLK_LSE, CLK_HSE_RTC, CLK_RTC, END_PRIMARY_CLK };
-
/*
* This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx
* have gate bits associated with them. Its combined hweight is 71.
diff --git a/include/dt-bindings/clock/stm32f4-clock.h b/include/dt-bindings/clock/stm32f4-clock.h
new file mode 100644
index 0000000..3132b6a
--- /dev/null
+++ b/include/dt-bindings/clock/stm32f4-clock.h
@@ -0,0 +1,31 @@
+/*
+ * stm32f4-clock.h
+ *
+ * Copyright (C) 2016 STMicroelectronics
+ * Author: Gabriel Fernandez for STMicroelectronics.
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+/*
+ * List of clocks wich are not derived from system clock (SYSCLOCK)
+ *
+ * The index of these clocks is the secondary index of DT bindings
+ * (see Documentatoin/devicetree/bindings/clock/st,stm32-rcc.txt)
+ *
+ * e.g:
+ <assigned-clocks = <&rcc 1 CLK_LSE>;
+*/
+
+#ifndef _DT_BINDINGS_CLK_STMF4_H
+#define _DT_BINDINGS_CLK_STMF4_H
+
+#define SYSTICK 0
+#define FCLK 1
+#define CLK_LSI 2
+#define CLK_LSE 3
+#define CLK_HSE_RTC 4
+#define CLK_RTC 5
+
+#define END_PRIMARY_CLK 6
+
+#endif
--
1.9.1
^ permalink raw reply related
* [PATCH v2 0/9] STM32F4 missing clocks
From: gabriel.fernandez at st.com @ 2016-11-24 14:45 UTC (permalink / raw)
To: linux-arm-kernel
From: Gabriel Fernandez <gabriel.fernandez@st.com>
v2:
- Put post divider in config structure
- Rework patch-set
- add update dt binding documentation
- add clock definition file
- Use composite for pll vco clocks
- For auxiliary clock, allow the possiblity to enable peripheral
clocks at same time (sugested by radek)
- Add vco_in clock (entry frequency for all pll) to simplify the code and clarify clock tree
- Fix missing end of divider tables
This patch-set adds:
- I2S & SAI PLLs
- SDIO & 48 Mhz clocks
- LCD-TFT clock
- I2S & SAI clocks
Gabriel Fernandez (9):
clk: stm32f4: Update DT bindings documentation
clk: stm32f4: Add PLL_I2S & PLL_SAI for STM32F429/469 boards
clk: stm32f4: Add post divisor for I2S & SAI PLLs
clk: stm32f4: Add lcd-tft clock
clk: stm32f4: Add I2S clock
clk: stm32f4: Add SAI clocks
clk: stm32f4: SDIO & 48Mhz clock management for STM32F469 board
arm: dts: stm32f4: Add external I2S clock
arm: dts: stm32f4: Include auxiliary stm32f4 clock definition
.../devicetree/bindings/clock/st,stm32-rcc.txt | 15 +
arch/arm/boot/dts/stm32f429.dtsi | 9 +-
drivers/clk/clk-stm32f4.c | 585 ++++++++++++++++++++-
include/dt-bindings/clock/stm32f4-clock.h | 37 ++
4 files changed, 626 insertions(+), 20 deletions(-)
create mode 100644 include/dt-bindings/clock/stm32f4-clock.h
--
1.9.1
^ permalink raw reply
* [RFC PATCH net v2 0/3] Fix OdroidC2 Gigabit Tx link issue
From: Martin Blumenstingl @ 2016-11-24 14:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479742524-30222-1-git-send-email-jbrunet@baylibre.com>
Hi Jerome,
On Mon, Nov 21, 2016 at 4:35 PM, Jerome Brunet <jbrunet@baylibre.com> wrote:
> This patchset fixes an issue with the OdroidC2 board (DWMAC + RTL8211F).
> Initially reported as a low Tx throughput issue at gigabit speed, the
> platform enters LPI too often. This eventually break the link (both Tx
> and Rx), and require to bring the interface down and up again to get the
> Rx path working again.
>
> The root cause of this issue is not fully understood yet but disabling EEE
> advertisement on the PHY prevent this feature to be negotiated.
> With this change, the link is stable and reliable, with the expected
> throughput performance.
I have just sent a series which allows configuring the TX delay on the
MAC (dwmac-meson8b glue) side: [0]
Disabling the TX delay generated by the MAC fixes TX throughput for
me, even when leaving EEE enabled in the RTL8211F PHY driver!
Unfortunately the RTL8211F PHY is a black-box for the community
because there is no public datasheeet available.
*maybe* (pure speculation!) they're enabling the TX delay based on
some internal magic only when EEE is enabled.
Jerome, could you please re-test the behavior on your Odroid-C2 when
you have EEE still enabled but the TX-delay disabled?
In my case throughput is fine, and "$ ethtool -S eth0 | grep lpi" gives:
irq_tx_path_in_lpi_mode_n: 0
irq_tx_path_exit_lpi_mode_n: 0
irq_rx_path_in_lpi_mode_n: 0
irq_rx_path_exit_lpi_mode_n: 0
Regards,
Martin
[0] http://lists.infradead.org/pipermail/linux-amlogic/2016-November/001674.html
^ permalink raw reply
* TDA998x crash on HDLCD probe failure
From: Robin Murphy @ 2016-11-24 14:40 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <459978b7-39d8-feae-257a-40b047f8d379@arm.com>
On 24/11/16 13:49, Robin Murphy wrote:
> On 24/11/16 13:29, Russell King - ARM Linux wrote:
>> On Thu, Nov 24, 2016 at 01:18:39PM +0000, Robin Murphy wrote:
>>> Hi Liviu, Russell,
>>>
>>> I'd been meaning to try digging into this if it hadn't gone away since I
>>> first noticed it, but I don't really have the time and it still happens
>>> with 4.9-rc and today's -next. Representative splat below, but in
>>> summary what happens is that if the HDLCD fails to probe, the TDA998x
>>> connector seems to get cleaned up twice, resulting in a NULL dereference
>>> the second time. I got as far as sketching out the following flow from a
>>> debug session (on the same 4.8-rc2 kernel), but I don't know nearly
>>> enough to tell which driver is at fault:
>>>
>>> hdlcd_drm_bind
>>> -> drm_fbdev_cma_init (fails)
>>> ...
>>> -> drm_mode_config_cleanup
>>> ...
>>> -> drm_connector_cleanup
>>> -> component_unbind_all
>>> ...
>>> -> tda998x_unbind
>>> -> drm_connector_cleanup (NULL connector)
>>>
>>> It's easily reproduced on Juno by booting arm64 defconfig with
>>> CONFIG_CMA_SIZE_MBYTES=1 and a sufficiently large monitor connected to
>>> warrant a >1MB framebuffer.
>>
>> It looks to me like a hdlcd bug.
>>
>> The probe path operates in this order:
>>
>> - allocates hdlcd - 1
>> - allocates drm device - 2
>> - drm_mode_config_init - 3
>> - hdlcd_load - 4
>> - binds all components - 5
>> - enables runtime PM - 6
>> - drm_vblank_init - 7
>> - drm_mode_config_reset - 8
>> - drm_kms_helper_poll_init - 9
>> - drm_fbdev_cma_init - 10
>> - drm_dev_register - 11
>>
>> However, the cleanup operates in this order:
>> - drm_fbdev_cma_fini - undoes 10
>> - drm_kms_helper_poll_fini - undoes 9
>> - drm_mode_config_cleanup - undoes 3
>> - drm_vblank_cleanup - undoes 7
>> - pm_runtime_disable - undoes 6
>> - component_unbind_all - undoes 5
>> - drm_irq_uninstall - undoes 4
>> - of_reserved_mem_device_release - undoes other half of 4
>> - drm_dev_unref - undoes 2
>>
>> Spot the step which is out of the correct order - drm_mode_config_cleanup()
>> is misplaced - it's reversing the actions of drm_mode_config_init(), not
>> drm_mode_config_reset().
>
> Thanks for the explanation - that saves at least a day's worth of me
> trying to understand DRM code :)
>
>> So, drm_mode_config_cleanup() should be much later, after step 4 has
>> been undone, otherwise there are paths that leave various DRM objects
>> (created by drm_mode_create_standard_properties()) referenced, and
>> will cause problems exactly like you're seeing here.
>
> Liviu, can I leave this with you then?
That said, I just tried the quick and obvious thing over lunch and it
does *seem* to be OK:
----->8-----
From: Robin Murphy <robin.murphy@arm.com>
Subject: [PATCH] drm: hdlcd: Fix cleanup order
If hdlcd_drm_bind() fails at drm_fbdev_cma_init(), its cleanup will call
drm_mode_config_cleanup() as if to balance drm_mode_config_reset(). The
net result is that drm_connector_cleanup() will clean up the active
connectors long before component_unbind_all() gets called, so when the
connector later tries to clean up itself after being unbound, Bad Things
can happen:
[ 4.121888] Unable to handle kernel NULL pointer dereference at
virtual address 00000000
[ 4.129951] pgd = ffffff80091e0000
[ 4.133345] [00000000] *pgd=00000009ffffe003, *pud=00000009ffffe003,
*pmd=0000000000000000
[ 4.141613] Internal error: Oops: 96000005 [#1] PREEMPT SMP
[ 4.147144] Modules linked in:
[ 4.150188] CPU: 0 PID: 122 Comm: kworker/u12:2 Not tainted
4.8.0-rc2+ #989
[ 4.157097] Hardware name: ARM Juno development board (r1) (DT)
[ 4.162981] Workqueue: deferwq deferred_probe_work_func
[ 4.168173] task: ffffffc975d93200 task.stack: ffffffc975dac000
[ 4.174055] PC is at drm_connector_cleanup+0x58/0x1c0
[ 4.179074] LR is at tda998x_unbind+0x24/0x40
[ 4.183401] pc : [<ffffff80084c46f0>] lr : [<ffffff800850414c>]
pstate: 00000045
[ 4.190750] sp : ffffffc975dafa10
[ 4.194041] x29: ffffffc975dafa10 x28: ffffffc9768152a8
[ 4.199325] x27: ffffffc97ff46450 x26: ffffff8008d99000
[ 4.204608] x25: dead000000000100 x24: dead000000000200
[ 4.209891] x23: ffffffc976bf91e8 x22: 0000000000000000
[ 4.215172] x21: ffffffc976bf9170 x20: ffffffc976bf9170
[ 4.220454] x19: ffffffc976bf9018 x18: 0000000000000000
[ 4.225737] x17: 0000000074ce71ee x16: 000000008ff5d35f
[ 4.231019] x15: ffffffc97681e91c x14: ffffffffffffffff
[ 4.236301] x13: ffffffc97681e185 x12: 0000000000000038
[ 4.241583] x11: 0101010101010101 x10: 0000000000000000
[ 4.246866] x9 : 0000000040000000 x8 : 0000000000210d00
[ 4.252148] x7 : ffffffc97fea8c00 x6 : 000000000000001b
[ 4.257430] x5 : ffffff80084b7b8c x4 : 0000000000000080
[ 4.262712] x3 : ffffff8008504128 x2 : ffffffc975df3800
[ 4.267993] x1 : 0000000000000000 x0 : 0000000000000000
...
[ 4.750937] [<ffffff80084c46f0>] drm_connector_cleanup+0x58/0x1c0
[ 4.756990] [<ffffff800850414c>] tda998x_unbind+0x24/0x40
[ 4.762354] [<ffffff8008507918>] component_unbind.isra.4+0x28/0x50
[ 4.768492] [<ffffff8008507a0c>] component_unbind_all+0xcc/0xd8
[ 4.774373] [<ffffff80084d5adc>] hdlcd_drm_bind+0x234/0x418
[ 4.779909] [<ffffff8008507b58>] try_to_bring_up_master+0x140/0x1a0
[ 4.786133] [<ffffff8008507c50>] component_add+0x98/0x170
[ 4.791496] [<ffffff8008504b90>] tda998x_probe+0x18/0x20
[ 4.796774] [<ffffff80086bf914>] i2c_device_probe+0x164/0x258
[ 4.802481] [<ffffff800850d094>] driver_probe_device+0x204/0x2b0
[ 4.808447] [<ffffff800850d28c>] __device_attach_driver+0x9c/0xf8
[ 4.814498] [<ffffff800850b108>] bus_for_each_drv+0x58/0x98
[ 4.820033] [<ffffff800850cd64>] __device_attach+0xc4/0x138
[ 4.825567] [<ffffff800850d338>] device_initial_probe+0x10/0x18
[ 4.831446] [<ffffff800850c124>] bus_probe_device+0x94/0xa0
[ 4.836981] [<ffffff800850c5b0>] deferred_probe_work_func+0x78/0xb0
[ 4.843207] [<ffffff80080d2998>] process_one_work+0x118/0x378
[ 4.848914] [<ffffff80080d2c40>] worker_thread+0x48/0x498
[ 4.854276] [<ffffff80080d8918>] kthread+0xd0/0xe8
[ 4.859036] [<ffffff8008082e90>] ret_from_fork+0x10/0x40
[ 4.864314] Code: f2fbd5b9 f2fbd5b8 f8478ee0 eb17001f (f9400013)
[ 4.870472] ---[ end trace a643cfe4ce1d838b ]---
Fix this by moving the drm_mode_config_cleanup() much later such that it
correctly balances drm_mode_config_init().
Suggested-by: Russell King <linux@armlinux.org.uk>
Signed-off-by: Robin Murphy <robin.murphy@arm.com>
---
drivers/gpu/drm/arm/hdlcd_drv.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/arm/hdlcd_drv.c
b/drivers/gpu/drm/arm/hdlcd_drv.c
index 59b76054edc9..1a4fff7c0a7c 100644
--- a/drivers/gpu/drm/arm/hdlcd_drv.c
+++ b/drivers/gpu/drm/arm/hdlcd_drv.c
@@ -420,7 +420,6 @@ static int hdlcd_drm_bind(struct device *dev)
err_fbdev:
drm_kms_helper_poll_fini(drm);
- drm_mode_config_cleanup(drm);
drm_vblank_cleanup(drm);
err_vblank:
pm_runtime_disable(drm->dev);
@@ -432,6 +431,7 @@ static int hdlcd_drm_bind(struct device *dev)
drm_irq_uninstall(drm);
of_reserved_mem_device_release(drm->dev);
err_free:
+ drm_mode_config_cleanup(drm);
dev_set_drvdata(dev, NULL);
drm_dev_unref(drm);
--
2.10.2.dirty
^ permalink raw reply related
* [PATCH] ARM: dts: da850-lcdk: Add ethernet0 alias to DT
From: Fabien Parent @ 2016-11-24 14:35 UTC (permalink / raw)
To: linux-arm-kernel
In order to avoid Linux generating a random mac address on every boot,
add an ethernet0 alias that will allow u-boot to patch the dtb with
the MAC address programmed into the EEPROM.
Signed-off-by: Fabien Parent <fparent@baylibre.com>
---
arch/arm/boot/dts/da850-lcdk.dts | 1 +
1 file changed, 1 insertion(+)
diff --git a/arch/arm/boot/dts/da850-lcdk.dts b/arch/arm/boot/dts/da850-lcdk.dts
index 7b8ab21..18dfec93 100644
--- a/arch/arm/boot/dts/da850-lcdk.dts
+++ b/arch/arm/boot/dts/da850-lcdk.dts
@@ -13,6 +13,7 @@
aliases {
serial2 = &serial2;
+ ethernet0 = ð0;
};
chosen {
--
2.10.2
^ permalink raw reply related
* [net-next PATCH v1 2/2] net: stmmac: dwmac-meson8b: make the RGMII TX delay configurable
From: Martin Blumenstingl @ 2016-11-24 14:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161124143417.10178-1-martin.blumenstingl@googlemail.com>
Prior to this patch we were using a hardcoded RGMII TX clock delay of
1/4 cycle (= 2ns). This value works for many boards, but unfortunately
not for all (due to the way the actual circuit is designed, sometimes
because the TX delay is enabled in the PHY, etc.).
Making the TX delay on the MAC side configurable allows us to support
all possible hardware combinations (which may or not be out there).
This allows fixing a compatibility issue on some boards, where the
RTL8211F PHY is configured to generate the TX delay. We can now turn
off the TX delay in the MAC, because otherwise we would be applying the
delay twice (which results in non-working TX traffic).
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
index 250e4ce..1697d1a 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
@@ -23,6 +23,8 @@
#include <linux/platform_device.h>
#include <linux/stmmac.h>
+#include <dt-bindings/net/dwmac-meson8b.h>
+
#include "stmmac_platform.h"
#define PRG_ETH0 0x0
@@ -35,10 +37,6 @@
#define PRG_ETH0_TXDLY_SHIFT 5
#define PRG_ETH0_TXDLY_MASK GENMASK(6, 5)
-#define PRG_ETH0_TXDLY_OFF (0x0 << PRG_ETH0_TXDLY_SHIFT)
-#define PRG_ETH0_TXDLY_QUARTER (0x1 << PRG_ETH0_TXDLY_SHIFT)
-#define PRG_ETH0_TXDLY_HALF (0x2 << PRG_ETH0_TXDLY_SHIFT)
-#define PRG_ETH0_TXDLY_THREE_QUARTERS (0x3 << PRG_ETH0_TXDLY_SHIFT)
/* divider for the result of m250_sel */
#define PRG_ETH0_CLK_M250_DIV_SHIFT 7
@@ -69,6 +67,8 @@ struct meson8b_dwmac {
struct clk_divider m25_div;
struct clk *m25_div_clk;
+
+ u32 tx_dly;
};
static void meson8b_dwmac_mask_bits(struct meson8b_dwmac *dwmac, u32 reg,
@@ -198,7 +198,7 @@ static int meson8b_init_prg_eth(struct meson8b_dwmac *dwmac)
/* TX clock delay - all known boards use a 1/4 cycle delay */
meson8b_dwmac_mask_bits(dwmac, PRG_ETH0, PRG_ETH0_TXDLY_MASK,
- PRG_ETH0_TXDLY_QUARTER);
+ dwmac->tx_dly << PRG_ETH0_TXDLY_SHIFT);
break;
case PHY_INTERFACE_MODE_RMII:
@@ -279,6 +279,12 @@ static int meson8b_dwmac_probe(struct platform_device *pdev)
return -EINVAL;
}
+ ret = of_property_read_u32(pdev->dev.of_node, "amlogic,tx-delay",
+ &dwmac->tx_dly);
+ if (ret)
+ /* default to 1/4 cycle (= 2ns for RGMII) */
+ dwmac->tx_dly = DWMAC_MESON8B_TXDLY_QUARTER_CYCLE;
+
ret = meson8b_init_clk(dwmac);
if (ret)
return ret;
--
2.10.2
^ permalink raw reply related
* [net-next PATCH v1 1/2] net: dt-bindings: add RGMII TX delay configuration to meson8b-dwmac
From: Martin Blumenstingl @ 2016-11-24 14:34 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161124143417.10178-1-martin.blumenstingl@googlemail.com>
This allows configuring the RGMII TX clock delay. This clock is
generated by the Meson 8b / GXBB DWMAC glue. The configuration depends
on the actual hardware (no delay may be needed due to the design of the
actual circuit, the PHY might add this delay, etc.).
The configuration values are provided as preprocessor macros to make the
devicetree files easier to read.
Signed-off-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
---
Documentation/devicetree/bindings/net/meson-dwmac.txt | 11 +++++++++++
include/dt-bindings/net/dwmac-meson8b.h | 18 ++++++++++++++++++
2 files changed, 29 insertions(+)
create mode 100644 include/dt-bindings/net/dwmac-meson8b.h
diff --git a/Documentation/devicetree/bindings/net/meson-dwmac.txt b/Documentation/devicetree/bindings/net/meson-dwmac.txt
index 89e62dd..fe526d0 100644
--- a/Documentation/devicetree/bindings/net/meson-dwmac.txt
+++ b/Documentation/devicetree/bindings/net/meson-dwmac.txt
@@ -25,6 +25,17 @@ Required properties on Meson8b and newer:
- "clkin0" - first parent clock of the internal mux
- "clkin1" - second parent clock of the internal mux
+Optional properties on Meson8b and newer:
+- amlogic,tx-delay: The internal RGMII TX clock delay configuration.
+ Defaults to DWMAC_MESON8B_TXDLY_QUARTER_CYCLE
+ when not given. All possible values are defined
+ as preprocessor macro in
+ <dt-bindings/net/dwmac-meson8b.h>.
+ The delay is specified as divider for the
+ internal clock (RGMII typically uses a 125MHz
+ clock clock (= 8ns per cycle), so setting
+ DWMAC_MESON8B_TXDLY_QUARTER_CYCLE
+ results in a TX delay of 8ns/4 = 2ns.
Example for Meson6:
diff --git a/include/dt-bindings/net/dwmac-meson8b.h b/include/dt-bindings/net/dwmac-meson8b.h
new file mode 100644
index 0000000..4fc149e
--- /dev/null
+++ b/include/dt-bindings/net/dwmac-meson8b.h
@@ -0,0 +1,18 @@
+/*
+ * Devicetree constants for the Amlogic Meson8b and GXBB DWMAC glue layer
+ *
+ * Copyright (C) 2016 Martin Blumenstingl <martin.blumenstingl@googlemail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+/* TX delay configuration */
+#define DWMAC_MESON8B_TXDLY_OFF 0x0
+#define DWMAC_MESON8B_TXDLY_QUARTER_CYCLE 0x1
+#define DWMAC_MESON8B_TXDLY_HALF_CYCLE 0x2
+#define DWMAC_MESON8B_TXDLY_THREE_QUARTER_CYCLE 0x3
--
2.10.2
^ permalink raw reply related
* [net-next PATCH v1 0/2] stmmac: dwmac-meson8b: configurable RGMII TX delay
From: Martin Blumenstingl @ 2016-11-24 14:34 UTC (permalink / raw)
To: linux-arm-kernel
Currently the dwmac-meson8b stmmac glue driver uses a hardcoded 1/4
cycle TX clock delay. This seems to work fine for many boards (for
example Odroid-C2 or Amlogic's reference boards) but there are some
others where TX traffic is simply broken.
There are probably multiple reasons why it's working on some boards
while it's broken on others:
- some of Amlogic's reference boards are using a Micrel PHY
- hardware circuit design
- maybe more...
This raises a question though:
Which device is supposed to enable the TX delay when both MAC and PHY
support it? And should we implement it for each PHY / MAC separately
or should we think about a more generic solution (currently it's not
possible to disable the TX delay generated by the RTL8211F PHY via
devicetree when using phy-mode "rgmii")?
iperf3 results on my Mecool BB2 board (Meson GXM, RTL8211F PHY) with
TX clock delay disabled on the MAC (as it's enabled in the PHY driver).
TX throughput was virtually zero before:
$ iperf3 -c 192.168.1.100 -R
Connecting to host 192.168.1.100, port 5201
Reverse mode, remote host 192.168.1.100 is sending
[ 4] local 192.168.1.206 port 52828 connected to 192.168.1.100 port 5201
[ ID] Interval Transfer Bandwidth
[ 4] 0.00-1.00 sec 108 MBytes 901 Mbits/sec
[ 4] 1.00-2.00 sec 94.2 MBytes 791 Mbits/sec
[ 4] 2.00-3.00 sec 96.5 MBytes 810 Mbits/sec
[ 4] 3.00-4.00 sec 96.2 MBytes 808 Mbits/sec
[ 4] 4.00-5.00 sec 96.6 MBytes 810 Mbits/sec
[ 4] 5.00-6.00 sec 96.5 MBytes 810 Mbits/sec
[ 4] 6.00-7.00 sec 96.6 MBytes 810 Mbits/sec
[ 4] 7.00-8.00 sec 96.5 MBytes 809 Mbits/sec
[ 4] 8.00-9.00 sec 105 MBytes 884 Mbits/sec
[ 4] 9.00-10.00 sec 111 MBytes 934 Mbits/sec
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-10.00 sec 1000 MBytes 839 Mbits/sec 0 sender
[ 4] 0.00-10.00 sec 998 MBytes 837 Mbits/sec receiver
iperf Done.
$ iperf3 -c 192.168.1.100
Connecting to host 192.168.1.100, port 5201
[ 4] local 192.168.1.206 port 52832 connected to 192.168.1.100 port 5201
[ ID] Interval Transfer Bandwidth Retr Cwnd
[ 4] 0.00-1.01 sec 99.5 MBytes 829 Mbits/sec 117 139 KBytes
[ 4] 1.01-2.00 sec 105 MBytes 884 Mbits/sec 129 70.7 KBytes
[ 4] 2.00-3.01 sec 107 MBytes 889 Mbits/sec 106 187 KBytes
[ 4] 3.01-4.01 sec 105 MBytes 878 Mbits/sec 92 143 KBytes
[ 4] 4.01-5.00 sec 105 MBytes 882 Mbits/sec 140 129 KBytes
[ 4] 5.00-6.01 sec 106 MBytes 883 Mbits/sec 115 195 KBytes
[ 4] 6.01-7.00 sec 102 MBytes 863 Mbits/sec 133 70.7 KBytes
[ 4] 7.00-8.01 sec 106 MBytes 884 Mbits/sec 143 97.6 KBytes
[ 4] 8.01-9.01 sec 104 MBytes 875 Mbits/sec 124 107 KBytes
[ 4] 9.01-10.01 sec 105 MBytes 876 Mbits/sec 90 139 KBytes
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bandwidth Retr
[ 4] 0.00-10.01 sec 1.02 GBytes 874 Mbits/sec 1189 sender
[ 4] 0.00-10.01 sec 1.02 GBytes 873 Mbits/sec receiver
iperf Done.
Martin Blumenstingl (2):
net: dt-bindings: add RGMII TX delay configuration to meson8b-dwmac
net: stmmac: dwmac-meson8b: make the RGMII TX delay configurable
Documentation/devicetree/bindings/net/meson-dwmac.txt | 11 +++++++++++
drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c | 16 +++++++++++-----
include/dt-bindings/net/dwmac-meson8b.h | 18 ++++++++++++++++++
3 files changed, 40 insertions(+), 5 deletions(-)
create mode 100644 include/dt-bindings/net/dwmac-meson8b.h
--
2.10.2
^ permalink raw reply
* [PATCH 7/10] mmc: sdhci-xenon: Add support to PHYs of Marvell Xenon SDHC
From: Ulf Hansson @ 2016-11-24 14:33 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <3cd05a26-d340-476e-bab1-8be9d5446f47@marvell.com>
[...]
>>
>>>
>>> +
>>> +static int __xenon_emmc_delay_adj_test(struct mmc_card *card)
>>> +{
>>> + int err;
>>> + u8 *ext_csd = NULL;
>>> +
>>> + err = mmc_get_ext_csd(card, &ext_csd);
>>> + kfree(ext_csd);
>>
>> Why do you read the ext csd here?
>>
> I would like to simply introduce the PHY setting of our SDHC.
> The target of the PHY setting is to achieve a perfect sampling
> point for transfers, during card initialization.
Okay, so the phy is involved when running the tuning sequence.
>
> For HS200/HS400/SDR104 whose SDCLK is more than 50MHz, SDHC HW
> will search for this sampling point with DLL's help.
Apologize for my ignorance, but what is a "DLL" in this case?
>
> For other speed mode whose SDLCK is less than or equals to 50MHz,
> SW has to scan the PHY delay line to find out this perfect sampling
> point. Our driver sends a command to verify a sampling point
> in current environment.
Ahh, okay! I guess the important part here is to not only send a
command, but also to make sure data becomes transferred on the DAT
lines, as to confirm your tuning sequence!?
In cases of HS200/HS400/SDR104 you should be able to use the
mmc_send_tuning() API, don't you think?
For the other cases (lower speed modes) which cards doesn't support
the tuning command, perhaps you can just assume the PHY scan succeeded
and then allow to core to continue with the card initialization
sequence? Or do you foresee any issues with that? My point is that, if
it will fail - it will fail anyway.
>
> As result, our SDHC driver has to implement the functionality to
> send commands and check the results, in host layer.
> If directly calling mmc_wait_for_cmd() is improper, could you please
> give us some suggestions?
>
> For eMMC, CMD8 is used to test current sampling point set in PHY.
Try to use mmc_send_tuning().
>
>>> +
>>> + return err;
>>> +}
>>> +
>>> +static int __xenon_sdio_delay_adj_test(struct mmc_card *card)
>>> +{
>>> + struct mmc_command cmd = {0};
>>> + int err;
>>> +
>>> + cmd.opcode = SD_IO_RW_DIRECT;
>>> + cmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
>>> +
>>> + err = mmc_wait_for_cmd(card->host, &cmd, 0);
>>> + if (err)
>>> + return err;
>>> +
>>> + if (cmd.resp[0] & R5_ERROR)
>>> + return -EIO;
>>> + if (cmd.resp[0] & R5_FUNCTION_NUMBER)
>>> + return -EINVAL;
>>> + if (cmd.resp[0] & R5_OUT_OF_RANGE)
>>> + return -ERANGE;
>>> + return 0;
>>
>> No thanks! MMC/SD/SDIO protocol code belongs in the core.
>>
> For SDIO, SD_IO_RW_DIRECT command is sent to test current sampling point
> in PHY.
> Please help provide some suggestion to implement the command transfer.
Again, I think mmc_send_tuning() should be possible for you to use.
[...]
>>> + if (mmc->card)
>>> + card = mmc->card;
>>> + else
>>> + /*
>>> + * Only valid during initialization
>>> + * before mmc->card is set
>>> + */
>>> + card = priv->card_candidate;
>>> + if (unlikely(!card)) {
>>> + dev_warn(mmc_dev(mmc), "card is not present\n");
>>> + return -EINVAL;
>>> + }
>>
>> That your host need to hold a copy of the card pointer, tells me that
>> something is not really correct.
>>
>> I might be wrong, if this turns out to be a special case, but I doubt
>> it. Although, if it *is* a special such case, we shall most likely try
>> to extend the the mmc core layer instead of adding all these hacks in
>> your host driver.
>>
> This card pointer copies the temporary structure mmc_card
> used in mmc_init_card(), mmc_sd_init_card() and mmc_sdio_init_card().
> Since we call mmc_wait_for_cmd() to send test commands, we need a copy
> of that temporary mmc_card here in our host driver.
I see, thanks for clarifying.
>
> During PHY setting in card initialization, mmc_host->card is not updated
> yet with that temporary mmc_card. Thus we are not able to directly use
> mmc_host->card. Instead, this card pointer is introduced to enable
> mmc_wait_for_cmd().
>
> If we can improve our host driver to send test commands without mmc_card,
> this card pointer can be removed.
> Could you please share your opinion please?
The mmc_send_tuning() API takes the mmc_host as parameter. If you
convert to that, perhaps you would be able to remove the need to hold
the card pointer.
BTW, the reason why mmc_send_tuning() doesn't take the card as a
parameter, is exactly those you just described above.
[...]
Kind regards
Uffe
^ permalink raw reply
* [PATCH 0/3] arm64: dts: r8a7796: Add CAN/CAN FD support
From: Simon Horman @ 2016-11-24 14:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <HK2PR0601MB1329C747CA5C6B5222C02C3FB7B60@HK2PR0601MB1329.apcprd06.prod.outlook.com>
Hi Chris,
On Thu, Nov 24, 2016 at 02:25:06PM +0000, Chris Paterson wrote:
> Hello Simon,
>
> From: Simon Horman [mailto:horms at verge.net.au]
> Sent: 24 November 2016 10:18
> > Hi Chris,
> >
> > On Thu, Nov 24, 2016 at 10:05:08AM +0000, Chris Paterson wrote:
> > > Hello Simon,
> > >
> > > From: Simon Horman [mailto:horms at verge.net.au]
> > > Sent: 23 November 2016 14:30
> > > > On Wed, Nov 23, 2016 at 02:18:13PM +0100, Marc Kleine-Budde wrote:
> > > > > On 11/23/2016 01:14 PM, Chris Paterson wrote:
...
> > > > Regarding the arch/arm64/boot/dts/renesas/ portion, I would like
> > > > some consideration given to what effect enabling memory above 4Gb
> > > > (64bit
> > > > addressing) would have.
> > >
> > > Can you give me some guidance here? I'm not sure what you're referring
> > > to. As far as I know the DT reg definition here is 64-bit, or are you
> > > referring to DMA usage? If the later, neither CAN driver uses DMA.
> >
> > Sorry for not being clearer.
> >
> > What I would like to know is if there are any problems in the CAN driver or
> > hardware that would prevent it from functioning with memory that requires
> > 64bit addressing present.
> >
> > If the CAN hardware cannot use DMA then DMA doesn't need to be taken
> > into account. But if it DMA could be enabled in future for CAN, for example
> > after some driver enhancements, then it would be good to know if 64bit
> > memory can be supported - if not it would imply DMA cannot be enabled.
>
> Thank you for the clarification.
>
> The CAN interface for r8a7795/6 does not support DMA.
>
> With CAN FD there is currently a H/W issue that means DMA is unusable.
> Potentially this issue could be fixed in the future and DMA support could
> be added to the driver. If this happens I can see no reason why the CAN
> FD IP wouldn't be able to handle DMA transfers when using 64bit
> addressing.
>
> >
> > As for non-DMA mode, will this function if memory above 4G is present?
> > If not then in theory such memory couldn't be enabled if the CAN driver
> > is enabled. This is my main concern.
>
> Yes, it functions fine. We have already tested this with the Renesas
> v3.3.2 BSP with >4Gb memory.
>
> If this is explanation okay for you, I'll proceed with a v2 splitting off
> the DT bindings documentation.
Thanks for the explanation. I think it would be good to proceed with a v2.
^ permalink raw reply
* [PATCH 7/9] clocksource/drivers/rockchip_timer: implement clocksource timer
From: Heiko Stübner @ 2016-11-24 14:32 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <95FE175F-B7B4-4271-99FE-69516140C56A@gmail.com>
Am Donnerstag, 24. November 2016, 17:14:56 schrieb Alexander Kochetkov:
> > 24 ????. 2016 ?., ? 16:21, Heiko St?bner <heiko@sntech.de> ???????(?):
> >
> > what I actually meant was that the driver could also recognize the rk3188-
> > timer compatible as "we need a clocksource" and it shouldn't matter which
> > timer actually gets used for this.
>
> One rockchip timer cannot be used as clockevent and clocksource at the same
> time.
>
> In case of clockevent we want interrupts from it at specified times. So we
> load one value into timer counter and it generates an interrupt.
>
> In case of clocksource we load max value into timer counter, run timer and
> read current value on demand.
>
> rockchip_timer driver currently implement clockevent. So, if I create only
> one timer in the device tree, it should be clockevent timer. As that
> behavior already expected from driver by people used it.
>
> I may suggest such solution here: if I want clocksource, I have to declare
> two timer in device tree. First probed timer would be clockevent and second
> one would be clocksource. All other timers will be ignored. Is that
> solution good?
yep, sounds good, especially as with your patch 9/9 you already declare these
necessary timers.
> If I want one timer and want it be clocksource not clockevent how that
> situation should be configured? Device tree not good for this. Kconfig not
> good. Pass that configuration on kernel command line?
simply ignore that case :-)
I.e. newer kernels are supposed to be able to run old devicetrees and in that
case they will have the global-timer as (slightly unstable) clocksource.
Also on the cortex-a9 we also still have the smp-twd as clockevent device.
Heiko
^ permalink raw reply
* [PATCH v2] ARM: dts: AM571x-IDK Initial Support
From: Tony Lindgren @ 2016-11-24 14:29 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAL_JsqLv2t0qzJ1V6NGPj3iy9tOmMcnr3nsHxojb9aJxp9+8BQ@mail.gmail.com>
* Rob Herring <robh+dt@kernel.org> [161122 07:43]:
> On Mon, Nov 21, 2016 at 10:17 PM, Lokesh Vutla <lokeshvutla@ti.com> wrote:
> > From: Schuyler Patton <spatton@ti.com>
> >
> > The AM571x-IDK board is a board based on TI's AM5718 SOC
> > which has a single core 1.5GHz A15 processor. This board is a
> > development platform for the Industrial market with:
> > - 1GB of DDR3L
> > - Dual 1Gbps Ethernet
> > - HDMI,
> > - PRU-ICSS
> > - uSD
> > - 16GB eMMC
> > - CAN
> > - RS-485
> > - PCIe
> > - USB3.0
> > - Video Input Port
> > - Industrial IO port and expansion connector
> >
> > The link to the data sheet and TRM can be found here:
> >
> > http://www.ti.com/product/AM5718
> >
> > Initial support is only for basic peripherals.
> >
> > Signed-off-by: Schuyler Patton <spatton@ti.com>
> > Signed-off-by: Nishanth Menon <nm@ti.com>
> > Signed-off-by: Dave Gerlach <d-gerlach@ti.com>
> > Signed-off-by: Lokesh Vutla <lokeshvutla@ti.com>
> > ---
> > Cahnges since v1:
> > - Dropped "ti,dra722", and "ti,dra72" from compatibles
> > - Fixes few node names as suggested by Rob.
> > Logs: http://pastebin.ubuntu.com/23515001/
>
> Please add acks when posting new versions.
I applied this with your ack as I was aware of the
context in this case :)
Tony
^ permalink raw reply
* [PATCH 0/3] arm64: dts: r8a7796: Add CAN/CAN FD support
From: Chris Paterson @ 2016-11-24 14:25 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161124101733.GA18027@verge.net.au>
Hello Simon,
From: Simon Horman [mailto:horms at verge.net.au]
Sent: 24 November 2016 10:18
> Hi Chris,
>
> On Thu, Nov 24, 2016 at 10:05:08AM +0000, Chris Paterson wrote:
> > Hello Simon,
> >
> > From: Simon Horman [mailto:horms at verge.net.au]
> > Sent: 23 November 2016 14:30
> > > On Wed, Nov 23, 2016 at 02:18:13PM +0100, Marc Kleine-Budde wrote:
> > > > On 11/23/2016 01:14 PM, Chris Paterson wrote:
> > > > > This patch series adds CAN and CAN FD support to the r8a7796.
> > > > >
> > > > > Based on renesas-devel-20161122-v4.9-rc6.
> > > > >
> > > > > Chris Paterson (3):
> > > > > arm64: dts: r8a7796: Add CAN external clock support
> > > > > arm64: dts: r8a7796: Add CAN support
> > > > > arm64: dts: r8a7796: Add CAN FD support
> > > > >
> > > > > .../devicetree/bindings/net/can/rcar_can.txt | 12 +++--
> > > > > .../devicetree/bindings/net/can/rcar_canfd.txt | 12 +++--
> > > > > arch/arm64/boot/dts/renesas/r8a7796.dtsi | 61
> > > ++++++++++++++++++++++
> > > > > 3 files changed, 75 insertions(+), 10 deletions(-)
> > > >
> > > > For all three:
> > > >
> > > > Acked-by: Marc Kleine-Budde <mkl@pengutronix.de>
> > > >
> > > > Who takes this series?
> > >
> > > I would like to see these patches split up so that the
> > > .../devicetree/bindings/ portions can go through you whole the
> > > arch/arm64/boot/dts/renesas/ portions go thorugh my renesas tree.
> >
> > Okay, will do.
>
> Thanks.
>
> > > Regarding the arch/arm64/boot/dts/renesas/ portion, I would like
> > > some consideration given to what effect enabling memory above 4Gb
> > > (64bit
> > > addressing) would have.
> >
> > Can you give me some guidance here? I'm not sure what you're referring
> > to. As far as I know the DT reg definition here is 64-bit, or are you
> > referring to DMA usage? If the later, neither CAN driver uses DMA.
>
> Sorry for not being clearer.
>
> What I would like to know is if there are any problems in the CAN driver or
> hardware that would prevent it from functioning with memory that requires
> 64bit addressing present.
>
> If the CAN hardware cannot use DMA then DMA doesn't need to be taken
> into account. But if it DMA could be enabled in future for CAN, for example
> after some driver enhancements, then it would be good to know if 64bit
> memory can be supported - if not it would imply DMA cannot be enabled.
Thank you for the clarification.
The CAN interface for r8a7795/6 does not support DMA.
With CAN FD there is currently a H/W issue that means DMA is unusable. Potentially this issue could be fixed in the future and DMA support could be added to the driver. If this happens I can see no reason why the CAN FD IP wouldn't be able to handle DMA transfers when using 64bit addressing.
>
> As for non-DMA mode, will this function if memory above 4G is present?
> If not then in theory such memory couldn't be enabled if the CAN driver is
> enabled. This is my main concern.
Yes, it functions fine. We have already tested this with the Renesas v3.3.2 BSP with >4Gb memory.
If this is explanation okay for you, I'll proceed with a v2 splitting off the DT bindings documentation.
Kind regards, Chris
>
> Does the above help?
^ permalink raw reply
* [PATCH] arm64: mm: Fix memmap to be initialized for the entire section
From: Ard Biesheuvel @ 2016-11-24 14:23 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161124141149.GE2213@rric.localdomain>
On 24 November 2016 at 14:11, Robert Richter <robert.richter@cavium.com> wrote:
> On 24.11.16 13:58:30, Ard Biesheuvel wrote:
>> On 24 November 2016 at 13:51, Robert Richter <robert.richter@cavium.com> wrote:
>> > On 24.11.16 13:44:31, Ard Biesheuvel wrote:
>> >> On 24 November 2016 at 13:42, Robert Richter <robert.richter@cavium.com> wrote:
>> >> > On 23.11.16 21:25:06, Ard Biesheuvel wrote:
>> >> >> Why? MEMREMAP_WB is used often, among other things for mapping
>> >> >> firmware tables, which are marked as NOMAP, so in these cases, the
>> >> >> linear address is not mapped.
>> >> >
>> >> > If fw tables are mapped wb, that is wrong and needs a separate fix.
>> >> >
>> >>
>> >> Why is that wrong?
>> >
>> > The whole issue with mapping acpi tables is not marking them cachable,
>> > what wb does.
>>
>> What 'issue'?
>>
>> > Otherwise we could just use linear mapping for those mem
>> > ranges.
>> >
>>
>> Regions containing firmware tables are owned by the firmware, and it
>> is the firmware that tells us which memory attributes we are allowed
>> to use. If those attributes include WB, it is perfectly legal to use a
>> cacheable mapping. That does *not* mean they should be covered by the
>> linear mapping. The linear mapping is read-write-non-exec, for
>> instance, and we may prefer to use a read-only mapping and/or
>> executable mapping.
>
> Ok, I am going to fix try_ram_remap().
>
Thanks. Could you also add an arm64 version of page_is_ram() that uses
memblock_is_memory() while you're at it? I think using memblock
directly in try_ram_remap() may not be the best approach
> Are there other concerns with this patch?
>
I think we all agree that pfn_valid() should return whether a pfn has
a struct page associated with it, the debate is about whether it makes
sense to allocate struct pages for memory that the kernel does not
own. But given that it does not really hurt to do so for small holes,
I think your suggestion makes sense.
Should we be doing anything more to ensure that those pages are not
dereferenced inadvertently? Is there a page flag we should be setting?
^ permalink raw reply
* [PATCH RESEND 2/2] gpio: axp209: add pinctrl support
From: Linus Walleij @ 2016-11-24 14:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161123141151.25315-3-quentin.schulz@free-electrons.com>
On Wed, Nov 23, 2016 at 3:11 PM, Quentin Schulz
<quentin.schulz@free-electrons.com> wrote:
> The GPIOs present in the AXP209 PMIC have multiple functions. They
> typically allow a pin to be used as GPIO input or output and can also be
> used as ADC or regulator for example.[1]
>
> This adds the possibility to use all functions of the GPIOs present in
> the AXP209 PMIC thanks to pinctrl subsystem.
>
> [1] see registers 90H, 92H and 93H at
> http://dl.linux-sunxi.org/AXP/AXP209_Datasheet_v1.0en.pdf
>
> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
I need Maxime's review on this patch.
> .../devicetree/bindings/gpio/gpio-axp209.txt | 28 +-
Also move the bindings to pinctrl/pinctrl-axp209.txt
> drivers/gpio/gpio-axp209.c | 551 ++++++++++++++++++---
Combined drivers should be in drivers/pinctrl/*.
Make a separate patch moving the driver to
drivers/pinctrl/pinctrl-axp209.c (remember -M to git format-patch)
augment Kconfig and Makefile in both subsystems and make
these patches on top of that.
I will deal with cross-merging the result between the GPIO
and pin control trees.
Yours,
Linus Walleij
^ permalink raw reply
* Tearing down DMA transfer setup after DMA client has finished
From: Måns Rullgård @ 2016-11-24 14:17 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <5836C69A.3030309@free.fr>
Mason <slash.tmp@free.fr> writes:
>>> I'm confused. Are you saying there is no solution to my problem
>>> within the existing DMA framework?
>>>
>>> In its current form, the tangox-dma.c driver will fail randomly
>>> for writes to a device (SATA, NFC).
>>>
>>> Maybe an extra hook can be added to the DMA framework?
>>>
>>> I'd like to hear from the framework's maintainers. Perhaps they
>>> can provide some guidance.
>>
>> You could have the dma descriptor callback wait for the receiving device
>> to finish. Bear in mind this runs from a tasklet, so it's not allowed
>> to sleep.
>
> Thanks for the suggestion, but I don't think it works :-(
>
> This is my DMA desc callback:
>
> static void tango_dma_callback(void *arg)
> {
> printk("%s from %pf\n", __func__, __builtin_return_address(0));
> mdelay(10000);
> printk("DONE FAKE SPINNING\n");
> complete(arg);
> }
>
> I also added
> printk("%s from %pf\n", __func__, __builtin_return_address(0));
> after tangox_dma_pchan_detach(pchan);
>
> And I get this output:
>
> [ 35.085854] SETUP DMA
> [ 35.088272] START NAND TRANSFER
> [ 35.091670] tangox_dma_pchan_start from tangox_dma_irq
> [ 35.096882] tango_dma_callback from vchan_complete
> [ 45.102513] DONE FAKE SPINNING
>
> So the IRQ rolls in, the ISR calls tangox_dma_pchan_start,
> which calls tangox_dma_pchan_detach to tear down the sbox
> setup; and only sometime later does the DMA framework call
> my callback function.
Yes, I realised this soon after I said it. The dma driver could be
rearranged to make it work though.
> So far, the work-arounds I've tested are:
>
> 1) delay sbox tear-down by 10 ?s in tangox_dma_pchan_detach.
> 2) statically setup sbox in probe, and never touch it henceforth.
>
> WA1 is fragile, it might break for devices other than NFC.
> WA2 is what I used when I wrote the NFC driver.
>
> Can tangox_dma_irq() be changed to have the framework call
> the client's callback *before* tangox_dma_pchan_start?
>
> (Thinking out loud) The DMA_PREP_INTERRUPT requests that the
> DMA framework invoke the callback from tasklet context,
> maybe a different flag DMA_PREP_INTERRUPT_EX can request
> calling the call-back directly from within the ISR?
>
> (Looking at existing flags) Could I use DMA_CTRL_ACK?
> Description sounds like some kind hand-shake between
> client and dmaengine.
>
> Grepping for DMA_PREP_INTERRUPT, I don't see where the framework
> checks that flag to spawn the tasklet? Or is that up to each
> driver individually?
Those flags all have defined meanings and abusing them for other things
is a bad idea. As far as possible, device drivers should work with any
dma driver.
--
M?ns Rullg?rd
^ permalink raw reply
* [PATCH 7/9] clocksource/drivers/rockchip_timer: implement clocksource timer
From: Alexander Kochetkov @ 2016-11-24 14:14 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <4357439.aV0xjsImc7@diego>
> 24 ????. 2016 ?., ? 16:21, Heiko St?bner <heiko@sntech.de> ???????(?):
>
> what I actually meant was that the driver could also recognize the rk3188-
> timer compatible as "we need a clocksource" and it shouldn't matter which
> timer actually gets used for this.
One rockchip timer cannot be used as clockevent and clocksource at the same time.
In case of clockevent we want interrupts from it at specified times. So we load one
value into timer counter and it generates an interrupt.
In case of clocksource we load max value into timer counter, run timer and read current
value on demand.
rockchip_timer driver currently implement clockevent. So, if I create only one timer
in the device tree, it should be clockevent timer. As that behavior already expected
from driver by people used it.
I may suggest such solution here: if I want clocksource, I have to declare two timer
in device tree. First probed timer would be clockevent and second one would be
clocksource. All other timers will be ignored. Is that solution good?
If I want one timer and want it be clocksource not clockevent how that situation should
be configured? Device tree not good for this. Kconfig not good. Pass that configuration
on kernel command line?
> Only devicetree people can really tell you if that is ok :-) .
>
> The devicetree is supposed to be a hardware-description and implementation-
> independent, so rockchip,clocksource sounds pretty much like linux-specific
> configuration things leaking into the devicetree.
You are right. They don?t allow pass linux configuration using device tree.
Regards,
Alexander.
^ permalink raw reply
* [PATCH RESEND 1/2] gpio: axp209: use correct register for GPIO input status
From: Linus Walleij @ 2016-11-24 14:13 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <20161123141151.25315-2-quentin.schulz@free-electrons.com>
On Wed, Nov 23, 2016 at 3:11 PM, Quentin Schulz
<quentin.schulz@free-electrons.com> wrote:
> The GPIO input status was read from control register
> (AXP20X_GPIO[210]_CTRL) instead of status register (AXP20X_GPIO20_SS).
>
> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
Patch applied.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH] arm64: mm: Fix memmap to be initialized for the entire section
From: Robert Richter @ 2016-11-24 14:11 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <CAKv+Gu9qB7P2epMGdwFJ3vJR3vt-bBxU0nKwmKdpaOpTKdqzzA@mail.gmail.com>
On 24.11.16 13:58:30, Ard Biesheuvel wrote:
> On 24 November 2016 at 13:51, Robert Richter <robert.richter@cavium.com> wrote:
> > On 24.11.16 13:44:31, Ard Biesheuvel wrote:
> >> On 24 November 2016 at 13:42, Robert Richter <robert.richter@cavium.com> wrote:
> >> > On 23.11.16 21:25:06, Ard Biesheuvel wrote:
> >> >> Why? MEMREMAP_WB is used often, among other things for mapping
> >> >> firmware tables, which are marked as NOMAP, so in these cases, the
> >> >> linear address is not mapped.
> >> >
> >> > If fw tables are mapped wb, that is wrong and needs a separate fix.
> >> >
> >>
> >> Why is that wrong?
> >
> > The whole issue with mapping acpi tables is not marking them cachable,
> > what wb does.
>
> What 'issue'?
>
> > Otherwise we could just use linear mapping for those mem
> > ranges.
> >
>
> Regions containing firmware tables are owned by the firmware, and it
> is the firmware that tells us which memory attributes we are allowed
> to use. If those attributes include WB, it is perfectly legal to use a
> cacheable mapping. That does *not* mean they should be covered by the
> linear mapping. The linear mapping is read-write-non-exec, for
> instance, and we may prefer to use a read-only mapping and/or
> executable mapping.
Ok, I am going to fix try_ram_remap().
Are there other concerns with this patch?
Thanks,
-Robert
^ permalink raw reply
* [PATCH 2/3] pinctrl: New driver for TI DA8XX/OMAP-L138/AM18XX pinconf
From: Linus Walleij @ 2016-11-24 14:05 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479871767-20160-3-git-send-email-david@lechnology.com>
On Wed, Nov 23, 2016 at 4:29 AM, David Lechner <david@lechnology.com> wrote:
> This adds a new driver for pinconf on TI DA8XX/OMAP-L138/AM18XX. These
> SoCs have a separate controller for controlling pullup/pulldown groups.
>
> Signed-off-by: David Lechner <david@lechnology.com>
Nice and clean driver, resend with the minor fixes pointed out
by Sekhar and I'll merge it.
Yours,
Linus Walleij
^ permalink raw reply
* [PATCH 1/3] devicetree: bindings: pinctrl: Add binding for ti, da850-pupd
From: Linus Walleij @ 2016-11-24 14:04 UTC (permalink / raw)
To: linux-arm-kernel
In-Reply-To: <1479871767-20160-2-git-send-email-david@lechnology.com>
On Wed, Nov 23, 2016 at 4:29 AM, David Lechner <david@lechnology.com> wrote:
> Device-tree bindings for TI DA8XX/OMAP-L138/AM18XX pullup/pulldown
> pinconf controller.
>
> Signed-off-by: David Lechner <david@lechnology.com>
Looks good to me.
Yours,
Linus Walleij
^ 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