[PATCH v2 7/9] ARM: dts: stm32: add exti support for stm32h743

2017-10-25 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds support of external interrupt (exti)
for stm32h743.

Signed-off-by: Ludovic Barre 
---
 arch/arm/boot/dts/stm32h743.dtsi | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/stm32h743.dtsi b/arch/arm/boot/dts/stm32h743.dtsi
index 58ec227..6b2fb4c 100644
--- a/arch/arm/boot/dts/stm32h743.dtsi
+++ b/arch/arm/boot/dts/stm32h743.dtsi
@@ -193,6 +193,14 @@
status = "disabled";
};
};
+
+   exti: interrupt-controller@5800 {
+   compatible = "st,stm32h7-exti";
+   interrupt-controller;
+   #interrupt-cells = <2>;
+   reg = <0x5800 0x400>;
+   interrupts = <1>, <2>, <3>, <6>, <7>, <8>, <9>, <10>, 
<23>, <40>, <41>, <62>, <76>;
+   };
};
 };
 
-- 
2.7.4



[PATCH v2 6/9] irqchip: stm32: move the wakeup on interrupt mask

2017-10-25 Thread Ludovic Barre
From: Ludovic Barre 

Move irq_set_wake on interrupt mask, needed to wake up from
low power mode as the event mask is not able to do so.

Signed-off-by: Ludovic Barre 
---
 drivers/irqchip/irq-stm32-exti.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index 9715d57..3e4ee25 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -156,16 +156,16 @@ static int stm32_irq_set_wake(struct irq_data *data, 
unsigned int on)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
const struct stm32_exti_bank *stm32_bank = gc->private;
int pin = data->hwirq % IRQS_PER_BANK;
-   u32 emr;
+   u32 imr;
 
irq_gc_lock(gc);
 
-   emr = irq_reg_readl(gc, stm32_bank->emr_ofst);
+   imr = irq_reg_readl(gc, stm32_bank->imr_ofst);
if (on)
-   emr |= BIT(pin);
+   imr |= BIT(pin);
else
-   emr &= ~BIT(pin);
-   irq_reg_writel(gc, emr, stm32_bank->emr_ofst);
+   imr &= ~BIT(pin);
+   irq_reg_writel(gc, imr, stm32_bank->imr_ofst);
 
irq_gc_unlock(gc);
 
-- 
2.7.4



[PATCH v2 0/9] irqchip: stm32: add stm32h7 support

2017-10-25 Thread Ludovic Barre
From: Ludovic Barre 

This series adds:
-Management of multi-bank of external interrupts
stm32h7 has up to 96 inputs (3 banks of  32 inputs).
-Fix initial value after cold/hot boot (wakeup issue).

Changes v2:
-Remove irq_mask and adds const on struct stm32_exti_bank
-Add wrapper functions pending and ack
-Replace BITS_PER_LONG by IRQS_PER_BANK
-Fill commit message on
"ARM: dts: stm32: add support of exti on stm32h743"
-Add system config bank for stm32h7

Ludovic Barre (9):
  irqchip: stm32: select GENERIC_IRQ_CHIP
  irqchip: stm32: add multi-bank management
  dt-bindings: interrupt-controllers: add compatible string for stm32h7
  irqchip: stm32: add stm32h7 support
  irqchip: stm32: fix initial values
  irqchip: stm32: move the wakeup on interrupt mask
  ARM: dts: stm32: add exti support for stm32h743
  ARM: dts: stm32: add system config bank node for stm32h743
  ARM: dts: stm32: add support of exti on stm32h743 pinctrl

 .../interrupt-controller/st,stm32-exti.txt |   4 +-
 arch/arm/boot/dts/stm32h743-pinctrl.dtsi   |  24 +++
 arch/arm/boot/dts/stm32h743.dtsi   |  13 ++
 drivers/irqchip/Kconfig|   1 +
 drivers/irqchip/irq-stm32-exti.c   | 208 -
 5 files changed, 200 insertions(+), 50 deletions(-)

-- 
2.7.4



[PATCH v2 2/9] irqchip: stm32: add multi-bank management

2017-10-25 Thread Ludovic Barre
From: Ludovic Barre 

-Prepare to manage multi-bank of external interrupts
(N banks of 32 inputs).
-Prepare to manage registers offsets by compatible
(registers offsets could be different follow per stm32 platform).

Signed-off-by: Ludovic Barre 
---
 drivers/irqchip/irq-stm32-exti.c | 151 +++
 1 file changed, 105 insertions(+), 46 deletions(-)

diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index 45363ff..6b4109b 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -14,27 +14,66 @@
 #include 
 #include 
 
-#define EXTI_IMR   0x0
-#define EXTI_EMR   0x4
-#define EXTI_RTSR  0x8
-#define EXTI_FTSR  0xc
-#define EXTI_SWIER 0x10
-#define EXTI_PR0x14
+#define IRQS_PER_BANK 32
+
+struct stm32_exti_bank {
+   u32 imr_ofst;
+   u32 emr_ofst;
+   u32 rtsr_ofst;
+   u32 ftsr_ofst;
+   u32 swier_ofst;
+   u32 pr_ofst;
+};
+
+static const struct stm32_exti_bank stm32f4xx_exti_b1 = {
+   .imr_ofst   = 0x00,
+   .emr_ofst   = 0x04,
+   .rtsr_ofst  = 0x08,
+   .ftsr_ofst  = 0x0C,
+   .swier_ofst = 0x10,
+   .pr_ofst= 0x14,
+};
+
+static const struct stm32_exti_bank *stm32f4xx_exti_banks[] = {
+   &stm32f4xx_exti_b1,
+};
+
+static unsigned long stm32_exti_pending(struct irq_chip_generic *gc)
+{
+   const struct stm32_exti_bank *stm32_bank = gc->private;
+
+   return irq_reg_readl(gc, stm32_bank->pr_ofst);
+}
+
+static void stm32_exti_irq_ack(struct irq_chip_generic *gc, u32 mask)
+{
+   const struct stm32_exti_bank *stm32_bank = gc->private;
+
+   irq_reg_writel(gc, mask, stm32_bank->pr_ofst);
+}
 
 static void stm32_irq_handler(struct irq_desc *desc)
 {
struct irq_domain *domain = irq_desc_get_handler_data(desc);
-   struct irq_chip_generic *gc = domain->gc->gc[0];
struct irq_chip *chip = irq_desc_get_chip(desc);
+   unsigned int virq, nbanks = domain->gc->num_chips;
+   struct irq_chip_generic *gc;
+   const struct stm32_exti_bank *stm32_bank;
unsigned long pending;
-   int n;
+   int n, i, irq_base = 0;
 
chained_irq_enter(chip, desc);
 
-   while ((pending = irq_reg_readl(gc, EXTI_PR))) {
-   for_each_set_bit(n, &pending, BITS_PER_LONG) {
-   generic_handle_irq(irq_find_mapping(domain, n));
-   irq_reg_writel(gc, BIT(n), EXTI_PR);
+   for (i = 0; i < nbanks; i++, irq_base += IRQS_PER_BANK) {
+   gc = irq_get_domain_generic_chip(domain, irq_base);
+   stm32_bank = gc->private;
+
+   while ((pending = stm32_exti_pending(gc))) {
+   for_each_set_bit(n, &pending, IRQS_PER_BANK) {
+   virq = irq_find_mapping(domain, irq_base + n);
+   generic_handle_irq(virq);
+   stm32_exti_irq_ack(gc, BIT(n));
+   }
}
}
 
@@ -44,13 +83,14 @@ static void stm32_irq_handler(struct irq_desc *desc)
 static int stm32_irq_set_type(struct irq_data *data, unsigned int type)
 {
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
-   int pin = data->hwirq;
+   const struct stm32_exti_bank *stm32_bank = gc->private;
+   int pin = data->hwirq % IRQS_PER_BANK;
u32 rtsr, ftsr;
 
irq_gc_lock(gc);
 
-   rtsr = irq_reg_readl(gc, EXTI_RTSR);
-   ftsr = irq_reg_readl(gc, EXTI_FTSR);
+   rtsr = irq_reg_readl(gc, stm32_bank->rtsr_ofst);
+   ftsr = irq_reg_readl(gc, stm32_bank->ftsr_ofst);
 
switch (type) {
case IRQ_TYPE_EDGE_RISING:
@@ -70,8 +110,8 @@ static int stm32_irq_set_type(struct irq_data *data, 
unsigned int type)
return -EINVAL;
}
 
-   irq_reg_writel(gc, rtsr, EXTI_RTSR);
-   irq_reg_writel(gc, ftsr, EXTI_FTSR);
+   irq_reg_writel(gc, rtsr, stm32_bank->rtsr_ofst);
+   irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst);
 
irq_gc_unlock(gc);
 
@@ -81,17 +121,18 @@ static int stm32_irq_set_type(struct irq_data *data, 
unsigned int type)
 static int stm32_irq_set_wake(struct irq_data *data, unsigned int on)
 {
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
-   int pin = data->hwirq;
+   const struct stm32_exti_bank *stm32_bank = gc->private;
+   int pin = data->hwirq % IRQS_PER_BANK;
u32 emr;
 
irq_gc_lock(gc);
 
-   emr = irq_reg_readl(gc, EXTI_EMR);
+   emr = irq_reg_readl(gc, stm32_bank->emr_ofst);
if (on)
emr |= BIT(pin);
else
emr &= ~BIT(pin);
-   irq_reg_writel(gc, emr, EXTI_EMR);
+   irq_reg_writel(gc, emr, stm32_bank->emr_ofst);
 
irq_gc_unlock(gc);
 
@@ -101,11 +142,12 @@ static int stm32_

[PATCH v2 5/9] irqchip: stm32: fix initial values

2017-10-25 Thread Ludovic Barre
From: Ludovic Barre 

-After cold boot, imr default value depends on hardware configuration.
-After hot reboot the registers must be cleared to avoid residue.

Signed-off-by: Ludovic Barre 
---
 drivers/irqchip/irq-stm32-exti.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index d872dea..9715d57 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -260,7 +260,16 @@ __init stm32_exti_init(const struct stm32_exti_bank 
**stm32_exti_banks,
writel_relaxed(~0UL, base + stm32_bank->rtsr_ofst);
irqs_mask = readl_relaxed(base + stm32_bank->rtsr_ofst);
nr_exti = fls(readl_relaxed(base + stm32_bank->rtsr_ofst));
+
+   /*
+* This IP has no reset, so after hot reboot we should
+* clear registers to avoid residue
+*/
+   writel_relaxed(0, base + stm32_bank->imr_ofst);
+   writel_relaxed(0, base + stm32_bank->emr_ofst);
writel_relaxed(0, base + stm32_bank->rtsr_ofst);
+   writel_relaxed(0, base + stm32_bank->ftsr_ofst);
+   writel_relaxed(~0UL, base + stm32_bank->pr_ofst);
 
pr_info("%s: bank%d, External IRQs available:%#x\n",
node->full_name, i, irqs_mask);
-- 
2.7.4



[PATCH v2 9/9] ARM: dts: stm32: add support of exti on stm32h743 pinctrl

2017-10-25 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds support of external interrupt (exti) on
all gpio ports of stm32h743.

Signed-off-by: Ludovic Barre 
---
 arch/arm/boot/dts/stm32h743-pinctrl.dtsi | 24 
 1 file changed, 24 insertions(+)

diff --git a/arch/arm/boot/dts/stm32h743-pinctrl.dtsi 
b/arch/arm/boot/dts/stm32h743-pinctrl.dtsi
index 76bbd65..df0b441 100644
--- a/arch/arm/boot/dts/stm32h743-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stm32h743-pinctrl.dtsi
@@ -49,6 +49,8 @@
#size-cells = <1>;
compatible = "st,stm32h743-pinctrl";
ranges = <0 0x5802 0x3000>;
+   interrupt-parent = <&exti>;
+   st,syscfg = <&syscfg 0x8>;
pins-are-numbered;
 
gpioa: gpio@5802 {
@@ -57,6 +59,8 @@
reg = <0x0 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOA";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpiob: gpio@58020400 {
@@ -65,6 +69,8 @@
reg = <0x400 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOB";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpioc: gpio@58020800 {
@@ -73,6 +79,8 @@
reg = <0x800 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOC";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpiod: gpio@58020c00 {
@@ -81,6 +89,8 @@
reg = <0xc00 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOD";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpioe: gpio@58021000 {
@@ -89,6 +99,8 @@
reg = <0x1000 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOE";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpiof: gpio@58021400 {
@@ -97,6 +109,8 @@
reg = <0x1400 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOF";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpiog: gpio@58021800 {
@@ -105,6 +119,8 @@
reg = <0x1800 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOG";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpioh: gpio@58021c00 {
@@ -113,6 +129,8 @@
reg = <0x1c00 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOH";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpioi: gpio@58022000 {
@@ -121,6 +139,8 @@
reg = <0x2000 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOI";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpioj: gpio@58022400 {
@@ -129,6 +149,8 @@
reg = <0x2400 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOJ";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpiok: gpio@58022800 {
@@ -137,6 +159,8 @@
reg = <0x2800 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOK";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
usart1_pins: usart1@0 {
-- 
2.7.4



[PATCH v2 8/9] ARM: dts: stm32: add system config bank node for stm32h743

2017-10-25 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds system config support for stm32h743.

Signed-off-by: Ludovic Barre 
---
 arch/arm/boot/dts/stm32h743.dtsi | 5 +
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/stm32h743.dtsi b/arch/arm/boot/dts/stm32h743.dtsi
index 6b2fb4c..b17aa5c 100644
--- a/arch/arm/boot/dts/stm32h743.dtsi
+++ b/arch/arm/boot/dts/stm32h743.dtsi
@@ -194,6 +194,11 @@
};
};
 
+   syscfg: system-config@58000400 {
+   compatible = "syscon";
+   reg = <0x58000400 0x400>;
+   };
+
exti: interrupt-controller@5800 {
compatible = "st,stm32h7-exti";
interrupt-controller;
-- 
2.7.4



[PATCH v2 3/9] dt-bindings: interrupt-controllers: add compatible string for stm32h7

2017-10-25 Thread Ludovic Barre
From: Ludovic Barre 

This patch updates stm32-exti documentation with stm32h7-exti
compatible string.

Signed-off-by: Ludovic Barre 
---
 .../devicetree/bindings/interrupt-controller/st,stm32-exti.txt| 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt 
b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
index 6e7703d..edf03f0 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
@@ -2,7 +2,9 @@ STM32 External Interrupt Controller
 
 Required properties:
 
-- compatible: Should be "st,stm32-exti"
+- compatible: Should be:
+"st,stm32-exti"
+"st,stm32h7-exti"
 - reg: Specifies base physical address and size of the registers
 - interrupt-controller: Indentifies the node as an interrupt controller
 - #interrupt-cells: Specifies the number of cells to encode an interrupt
-- 
2.7.4



[PATCH v2 4/9] irqchip: stm32: add stm32h7 support

2017-10-25 Thread Ludovic Barre
From: Ludovic Barre 

stm32h7 has up to 96 inputs
(3 banks of 32 inputs max).

Signed-off-by: Ludovic Barre 
---
 drivers/irqchip/irq-stm32-exti.c | 42 
 1 file changed, 42 insertions(+)

diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index 6b4109b..d872dea 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -38,6 +38,39 @@ static const struct stm32_exti_bank *stm32f4xx_exti_banks[] 
= {
&stm32f4xx_exti_b1,
 };
 
+static const struct stm32_exti_bank stm32h7xx_exti_b1 = {
+   .imr_ofst   = 0x80,
+   .emr_ofst   = 0x84,
+   .rtsr_ofst  = 0x00,
+   .ftsr_ofst  = 0x04,
+   .swier_ofst = 0x08,
+   .pr_ofst= 0x88,
+};
+
+static const struct stm32_exti_bank stm32h7xx_exti_b2 = {
+   .imr_ofst   = 0x90,
+   .emr_ofst   = 0x94,
+   .rtsr_ofst  = 0x20,
+   .ftsr_ofst  = 0x24,
+   .swier_ofst = 0x28,
+   .pr_ofst= 0x98,
+};
+
+static const struct stm32_exti_bank stm32h7xx_exti_b3 = {
+   .imr_ofst   = 0xA0,
+   .emr_ofst   = 0xA4,
+   .rtsr_ofst  = 0x40,
+   .ftsr_ofst  = 0x44,
+   .swier_ofst = 0x48,
+   .pr_ofst= 0xA8,
+};
+
+static const struct stm32_exti_bank *stm32h7xx_exti_banks[] = {
+   &stm32h7xx_exti_b1,
+   &stm32h7xx_exti_b2,
+   &stm32h7xx_exti_b3,
+};
+
 static unsigned long stm32_exti_pending(struct irq_chip_generic *gc)
 {
const struct stm32_exti_bank *stm32_bank = gc->private;
@@ -258,3 +291,12 @@ static int __init stm32f4_exti_of_init(struct device_node 
*np,
 }
 
 IRQCHIP_DECLARE(stm32f4_exti, "st,stm32-exti", stm32f4_exti_of_init);
+
+static int __init stm32h7_exti_of_init(struct device_node *np,
+  struct device_node *parent)
+{
+   return stm32_exti_init(stm32h7xx_exti_banks,
+   ARRAY_SIZE(stm32h7xx_exti_banks), np);
+}
+
+IRQCHIP_DECLARE(stm32h7_exti, "st,stm32h7-exti", stm32h7_exti_of_init);
-- 
2.7.4



[PATCH v2 1/9] irqchip: stm32: select GENERIC_IRQ_CHIP

2017-10-25 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds GENERIC_IRQ_CHIP to stm32 exti
config.

Signed-off-by: Ludovic Barre 
---
 drivers/irqchip/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 9d8a1dd..c067aae 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -304,6 +304,7 @@ config EZNPS_GIC
 config STM32_EXTI
bool
select IRQ_DOMAIN
+   select GENERIC_IRQ_CHIP
 
 config QCOM_IRQ_COMBINER
bool "QCOM IRQ combiner support"
-- 
2.7.4



[PATCH 0/3] mtd: spi-nor: stm32-quadspi: fixes

2017-10-26 Thread Ludovic Barre
From: Ludovic Barre 

This series adds:
-Fix: to avoid compilation warning with older compiler
versions such as gcc-4.6.
This topic has been discussed on 2 threads with Geert and Arnd
https://lkml.org/lkml/2017/9/15/70
https://www.spinics.net/lists/arm-kernel/msg606269.html
-Fix: abort prefetching in memory-mapped mode as soon prefetching
could exceed nor size (not done by fsize limit)
-Change license text and Copyright

Geert Uytterhoeven (1):
  mtd: spi-nor: stm32-quadspi: Fix uninitialized error return code

Ludovic Barre (2):
  mtd: spi-nor: stm32-quadspi: fix prefetching outside fsize
  mtd: spi-nor: stm32-quadspi: change license text

 drivers/mtd/spi-nor/stm32-quadspi.c | 35 +--
 1 file changed, 29 insertions(+), 6 deletions(-)

-- 
2.7.4



[PATCH 3/3] mtd: spi-nor: stm32-quadspi: change license text

2017-10-26 Thread Ludovic Barre
From: Ludovic Barre 

-Change the license text with long template.
-Change Copyright to STMicroelectronics.

Signed-off-by: Ludovic Barre 
---
 drivers/mtd/spi-nor/stm32-quadspi.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/spi-nor/stm32-quadspi.c 
b/drivers/mtd/spi-nor/stm32-quadspi.c
index 70710be..b3c7f6a 100644
--- a/drivers/mtd/spi-nor/stm32-quadspi.c
+++ b/drivers/mtd/spi-nor/stm32-quadspi.c
@@ -1,9 +1,22 @@
 /*
- * stm32_quadspi.c
+ * Driver for stm32 quadspi controller
  *
- * Copyright (C) 2017, Ludovic Barre
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Ludovic Barre author .
  *
- * License terms: GNU General Public License (GPL), version 2
+ * License terms: GPL V2.0.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * This program. If not, see <http://www.gnu.org/licenses/>.
  */
 #include 
 #include 
-- 
2.7.4



[PATCH 1/3] mtd: spi-nor: stm32-quadspi: Fix uninitialized error return code

2017-10-26 Thread Ludovic Barre
From: Geert Uytterhoeven 

With gcc 4.1.2:

drivers/mtd/spi-nor/stm32-quadspi.c: In function ‘stm32_qspi_tx_poll’:
drivers/mtd/spi-nor/stm32-quadspi.c:230: warning: ‘ret’ may be used 
uninitialized in this function

Indeed, if stm32_qspi_cmd.len is zero, ret will be uninitialized.
This length is passed from outside the driver using the
spi_nor.{read,write}{,_reg}() callbacks.

Several functions in drivers/mtd/spi-nor/spi-nor.c (e.g. write_enable(),
write_disable(), and erase_chip()) call spi_nor.write_reg() with a zero
length.

Fix this by returning an explicit zero on success.

Fixes: 0d43d7ab277a048c ("mtd: spi-nor: add driver for STM32 quad spi flash 
controller")
Signed-off-by: Geert Uytterhoeven 
Acked-by: Ludovic Barre 
Signed-off-by: Ludovic Barre 
---
 drivers/mtd/spi-nor/stm32-quadspi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi-nor/stm32-quadspi.c 
b/drivers/mtd/spi-nor/stm32-quadspi.c
index 86c0931..ad6a3e1 100644
--- a/drivers/mtd/spi-nor/stm32-quadspi.c
+++ b/drivers/mtd/spi-nor/stm32-quadspi.c
@@ -240,12 +240,12 @@ static int stm32_qspi_tx_poll(struct stm32_qspi *qspi,
 STM32_QSPI_FIFO_TIMEOUT_US);
if (ret) {
dev_err(qspi->dev, "fifo timeout (stat:%#x)\n", sr);
-   break;
+   return ret;
}
tx_fifo(buf++, qspi->io_base + QUADSPI_DR);
}
 
-   return ret;
+   return 0;
 }
 
 static int stm32_qspi_tx_mm(struct stm32_qspi *qspi,
-- 
2.7.4



[PATCH 2/3] mtd: spi-nor: stm32-quadspi: fix prefetching outside fsize

2017-10-26 Thread Ludovic Barre
From: Ludovic Barre 

When memory-mapped mode is used, a prefetching mechanism fully
managed by the hardware allows to optimize the read from external
the QSPI memory. A 32-bytes FIFO is used for prefetching.
When the limit of flash size - fifo size is reached the prefetching
mechanism tries to read outside the fsize.
The stm32 quadspi hardware become busy and should be aborted.

Signed-off-by: Ludovic Barre 
Reported-by: Bruno Herrera 
Tested-by: Bruno Herrera 
---
 drivers/mtd/spi-nor/stm32-quadspi.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/spi-nor/stm32-quadspi.c 
b/drivers/mtd/spi-nor/stm32-quadspi.c
index ad6a3e1..70710be 100644
--- a/drivers/mtd/spi-nor/stm32-quadspi.c
+++ b/drivers/mtd/spi-nor/stm32-quadspi.c
@@ -113,6 +113,7 @@
 #define STM32_MAX_MMAP_SZ  SZ_256M
 #define STM32_MAX_NORCHIP  2
 
+#define STM32_QSPI_FIFO_SZ 32
 #define STM32_QSPI_FIFO_TIMEOUT_US 3
 #define STM32_QSPI_BUSY_TIMEOUT_US 10
 
@@ -124,6 +125,7 @@ struct stm32_qspi_flash {
u32 presc;
u32 read_mode;
bool registered;
+   u32 prefetch_limit;
 };
 
 struct stm32_qspi {
@@ -272,6 +274,7 @@ static int stm32_qspi_send(struct stm32_qspi_flash *flash,
 {
struct stm32_qspi *qspi = flash->qspi;
u32 ccr, dcr, cr;
+   u32 last_byte;
int err;
 
err = stm32_qspi_wait_nobusy(qspi);
@@ -314,6 +317,10 @@ static int stm32_qspi_send(struct stm32_qspi_flash *flash,
if (err)
goto abort;
writel_relaxed(FCR_CTCF, qspi->io_base + QUADSPI_FCR);
+   } else {
+   last_byte = cmd->addr + cmd->len;
+   if (last_byte > flash->prefetch_limit)
+   goto abort;
}
 
return err;
@@ -322,7 +329,9 @@ static int stm32_qspi_send(struct stm32_qspi_flash *flash,
cr = readl_relaxed(qspi->io_base + QUADSPI_CR) | CR_ABORT;
writel_relaxed(cr, qspi->io_base + QUADSPI_CR);
 
-   dev_err(qspi->dev, "%s abort err:%d\n", __func__, err);
+   if (err)
+   dev_err(qspi->dev, "%s abort err:%d\n", __func__, err);
+
return err;
 }
 
@@ -550,6 +559,7 @@ static int stm32_qspi_flash_setup(struct stm32_qspi *qspi,
}
 
flash->fsize = FSIZE_VAL(mtd->size);
+   flash->prefetch_limit = mtd->size - STM32_QSPI_FIFO_SZ;
 
flash->read_mode = CCR_FMODE_MM;
if (mtd->size > qspi->mm_size)
-- 
2.7.4



[PATCH v2 2/3] mtd: spi-nor: stm32-quadspi: fix prefetching outside fsize

2017-10-26 Thread Ludovic Barre
From: Ludovic Barre 

When memory-mapped mode is used, a prefetching mechanism fully
managed by the hardware allows to optimize the read from external
the QSPI memory. A 32-bytes FIFO is used for prefetching.
When the limit of flash size - fifo size is reached the prefetching
mechanism tries to read outside the fsize.
The stm32 quadspi hardware become busy and should be aborted.

Signed-off-by: Ludovic Barre 
Reported-by: Bruno Herrera 
Tested-by: Bruno Herrera 
---
 drivers/mtd/spi-nor/stm32-quadspi.c | 12 +++-
 1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/mtd/spi-nor/stm32-quadspi.c 
b/drivers/mtd/spi-nor/stm32-quadspi.c
index ad6a3e1..70710be 100644
--- a/drivers/mtd/spi-nor/stm32-quadspi.c
+++ b/drivers/mtd/spi-nor/stm32-quadspi.c
@@ -113,6 +113,7 @@
 #define STM32_MAX_MMAP_SZ  SZ_256M
 #define STM32_MAX_NORCHIP  2
 
+#define STM32_QSPI_FIFO_SZ 32
 #define STM32_QSPI_FIFO_TIMEOUT_US 3
 #define STM32_QSPI_BUSY_TIMEOUT_US 10
 
@@ -124,6 +125,7 @@ struct stm32_qspi_flash {
u32 presc;
u32 read_mode;
bool registered;
+   u32 prefetch_limit;
 };
 
 struct stm32_qspi {
@@ -272,6 +274,7 @@ static int stm32_qspi_send(struct stm32_qspi_flash *flash,
 {
struct stm32_qspi *qspi = flash->qspi;
u32 ccr, dcr, cr;
+   u32 last_byte;
int err;
 
err = stm32_qspi_wait_nobusy(qspi);
@@ -314,6 +317,10 @@ static int stm32_qspi_send(struct stm32_qspi_flash *flash,
if (err)
goto abort;
writel_relaxed(FCR_CTCF, qspi->io_base + QUADSPI_FCR);
+   } else {
+   last_byte = cmd->addr + cmd->len;
+   if (last_byte > flash->prefetch_limit)
+   goto abort;
}
 
return err;
@@ -322,7 +329,9 @@ static int stm32_qspi_send(struct stm32_qspi_flash *flash,
cr = readl_relaxed(qspi->io_base + QUADSPI_CR) | CR_ABORT;
writel_relaxed(cr, qspi->io_base + QUADSPI_CR);
 
-   dev_err(qspi->dev, "%s abort err:%d\n", __func__, err);
+   if (err)
+   dev_err(qspi->dev, "%s abort err:%d\n", __func__, err);
+
return err;
 }
 
@@ -550,6 +559,7 @@ static int stm32_qspi_flash_setup(struct stm32_qspi *qspi,
}
 
flash->fsize = FSIZE_VAL(mtd->size);
+   flash->prefetch_limit = mtd->size - STM32_QSPI_FIFO_SZ;
 
flash->read_mode = CCR_FMODE_MM;
if (mtd->size > qspi->mm_size)
-- 
2.7.4



[PATCH v2 0/3] mtd: spi-nor: stm32-quadspi: fixes

2017-10-26 Thread Ludovic Barre
From: Ludovic Barre 

This series adds:
-Fix: to avoid compilation warning with older compiler
versions such as gcc-4.6.
This topic has been discussed on 2 threads with Geert and Arnd
https://lkml.org/lkml/2017/9/15/70
https://www.spinics.net/lists/arm-kernel/msg606269.html
-Fix: abort prefetching in memory-mapped mode as soon prefetching
could exceed nor size (not done by fsize limit)
-Change license text and Copyright

Changes v2:
with the right Cyrille's email (wedev4u.fr)

Geert Uytterhoeven (1):
  mtd: spi-nor: stm32-quadspi: Fix uninitialized error return code

Ludovic Barre (2):
  mtd: spi-nor: stm32-quadspi: fix prefetching outside fsize
  mtd: spi-nor: stm32-quadspi: change license text

 drivers/mtd/spi-nor/stm32-quadspi.c | 35 +--
 1 file changed, 29 insertions(+), 6 deletions(-)

-- 
2.7.4



[PATCH v2 3/3] mtd: spi-nor: stm32-quadspi: change license text

2017-10-26 Thread Ludovic Barre
From: Ludovic Barre 

-Change the license text with long template.
-Change Copyright to STMicroelectronics.

Signed-off-by: Ludovic Barre 
---
 drivers/mtd/spi-nor/stm32-quadspi.c | 19 ---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/spi-nor/stm32-quadspi.c 
b/drivers/mtd/spi-nor/stm32-quadspi.c
index 70710be..b3c7f6a 100644
--- a/drivers/mtd/spi-nor/stm32-quadspi.c
+++ b/drivers/mtd/spi-nor/stm32-quadspi.c
@@ -1,9 +1,22 @@
 /*
- * stm32_quadspi.c
+ * Driver for stm32 quadspi controller
  *
- * Copyright (C) 2017, Ludovic Barre
+ * Copyright (C) 2017, STMicroelectronics - All Rights Reserved
+ * Author(s): Ludovic Barre author .
  *
- * License terms: GNU General Public License (GPL), version 2
+ * License terms: GPL V2.0.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 
more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * This program. If not, see <http://www.gnu.org/licenses/>.
  */
 #include 
 #include 
-- 
2.7.4



[PATCH v2 1/3] mtd: spi-nor: stm32-quadspi: Fix uninitialized error return code

2017-10-26 Thread Ludovic Barre
From: Geert Uytterhoeven 

With gcc 4.1.2:

drivers/mtd/spi-nor/stm32-quadspi.c: In function ‘stm32_qspi_tx_poll’:
drivers/mtd/spi-nor/stm32-quadspi.c:230: warning: ‘ret’ may be used 
uninitialized in this function

Indeed, if stm32_qspi_cmd.len is zero, ret will be uninitialized.
This length is passed from outside the driver using the
spi_nor.{read,write}{,_reg}() callbacks.

Several functions in drivers/mtd/spi-nor/spi-nor.c (e.g. write_enable(),
write_disable(), and erase_chip()) call spi_nor.write_reg() with a zero
length.

Fix this by returning an explicit zero on success.

Fixes: 0d43d7ab277a048c ("mtd: spi-nor: add driver for STM32 quad spi flash 
controller")
Signed-off-by: Geert Uytterhoeven 
Acked-by: Ludovic Barre 
Signed-off-by: Ludovic Barre 
---
 drivers/mtd/spi-nor/stm32-quadspi.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi-nor/stm32-quadspi.c 
b/drivers/mtd/spi-nor/stm32-quadspi.c
index 86c0931..ad6a3e1 100644
--- a/drivers/mtd/spi-nor/stm32-quadspi.c
+++ b/drivers/mtd/spi-nor/stm32-quadspi.c
@@ -240,12 +240,12 @@ static int stm32_qspi_tx_poll(struct stm32_qspi *qspi,
 STM32_QSPI_FIFO_TIMEOUT_US);
if (ret) {
dev_err(qspi->dev, "fifo timeout (stat:%#x)\n", sr);
-   break;
+   return ret;
}
tx_fifo(buf++, qspi->io_base + QUADSPI_DR);
}
 
-   return ret;
+   return 0;
 }
 
 static int stm32_qspi_tx_mm(struct stm32_qspi *qspi,
-- 
2.7.4



[PATCH v3 3/9] dt-bindings: interrupt-controllers: add compatible string for stm32h7

2017-11-06 Thread Ludovic Barre
From: Ludovic Barre 

This patch updates stm32-exti documentation with stm32h7-exti
compatible string.

Signed-off-by: Ludovic Barre 
Acked-by: Rob Herring 
---
 .../devicetree/bindings/interrupt-controller/st,stm32-exti.txt| 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git 
a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt 
b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
index 6e7703d..edf03f0 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
@@ -2,7 +2,9 @@ STM32 External Interrupt Controller
 
 Required properties:
 
-- compatible: Should be "st,stm32-exti"
+- compatible: Should be:
+"st,stm32-exti"
+"st,stm32h7-exti"
 - reg: Specifies base physical address and size of the registers
 - interrupt-controller: Indentifies the node as an interrupt controller
 - #interrupt-cells: Specifies the number of cells to encode an interrupt
-- 
2.7.4



[PATCH v3 2/9] irqchip: stm32: add multi-bank management

2017-11-06 Thread Ludovic Barre
From: Ludovic Barre 

-Prepare to manage multi-bank of external interrupts
(N banks of 32 inputs).
-Prepare to manage registers offsets by compatible
(registers offsets could be different follow per stm32 platform).

Signed-off-by: Ludovic Barre 
---
 drivers/irqchip/irq-stm32-exti.c | 149 +++
 1 file changed, 103 insertions(+), 46 deletions(-)

diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index 45363ff..ef37870 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -14,27 +14,66 @@
 #include 
 #include 
 
-#define EXTI_IMR   0x0
-#define EXTI_EMR   0x4
-#define EXTI_RTSR  0x8
-#define EXTI_FTSR  0xc
-#define EXTI_SWIER 0x10
-#define EXTI_PR0x14
+#define IRQS_PER_BANK 32
+
+struct stm32_exti_bank {
+   u32 imr_ofst;
+   u32 emr_ofst;
+   u32 rtsr_ofst;
+   u32 ftsr_ofst;
+   u32 swier_ofst;
+   u32 pr_ofst;
+};
+
+static const struct stm32_exti_bank stm32f4xx_exti_b1 = {
+   .imr_ofst   = 0x00,
+   .emr_ofst   = 0x04,
+   .rtsr_ofst  = 0x08,
+   .ftsr_ofst  = 0x0C,
+   .swier_ofst = 0x10,
+   .pr_ofst= 0x14,
+};
+
+static const struct stm32_exti_bank *stm32f4xx_exti_banks[] = {
+   &stm32f4xx_exti_b1,
+};
+
+static unsigned long stm32_exti_pending(struct irq_chip_generic *gc)
+{
+   const struct stm32_exti_bank *stm32_bank = gc->private;
+
+   return irq_reg_readl(gc, stm32_bank->pr_ofst);
+}
+
+static void stm32_exti_irq_ack(struct irq_chip_generic *gc, u32 mask)
+{
+   const struct stm32_exti_bank *stm32_bank = gc->private;
+
+   irq_reg_writel(gc, mask, stm32_bank->pr_ofst);
+}
 
 static void stm32_irq_handler(struct irq_desc *desc)
 {
struct irq_domain *domain = irq_desc_get_handler_data(desc);
-   struct irq_chip_generic *gc = domain->gc->gc[0];
struct irq_chip *chip = irq_desc_get_chip(desc);
+   unsigned int virq, nbanks = domain->gc->num_chips;
+   struct irq_chip_generic *gc;
+   const struct stm32_exti_bank *stm32_bank;
unsigned long pending;
-   int n;
+   int n, i, irq_base = 0;
 
chained_irq_enter(chip, desc);
 
-   while ((pending = irq_reg_readl(gc, EXTI_PR))) {
-   for_each_set_bit(n, &pending, BITS_PER_LONG) {
-   generic_handle_irq(irq_find_mapping(domain, n));
-   irq_reg_writel(gc, BIT(n), EXTI_PR);
+   for (i = 0; i < nbanks; i++, irq_base += IRQS_PER_BANK) {
+   gc = irq_get_domain_generic_chip(domain, irq_base);
+   stm32_bank = gc->private;
+
+   while ((pending = stm32_exti_pending(gc))) {
+   for_each_set_bit(n, &pending, IRQS_PER_BANK) {
+   virq = irq_find_mapping(domain, irq_base + n);
+   generic_handle_irq(virq);
+   stm32_exti_irq_ack(gc, BIT(n));
+   }
}
}
 
@@ -44,13 +83,14 @@ static void stm32_irq_handler(struct irq_desc *desc)
 static int stm32_irq_set_type(struct irq_data *data, unsigned int type)
 {
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
-   int pin = data->hwirq;
+   const struct stm32_exti_bank *stm32_bank = gc->private;
+   int pin = data->hwirq % IRQS_PER_BANK;
u32 rtsr, ftsr;
 
irq_gc_lock(gc);
 
-   rtsr = irq_reg_readl(gc, EXTI_RTSR);
-   ftsr = irq_reg_readl(gc, EXTI_FTSR);
+   rtsr = irq_reg_readl(gc, stm32_bank->rtsr_ofst);
+   ftsr = irq_reg_readl(gc, stm32_bank->ftsr_ofst);
 
switch (type) {
case IRQ_TYPE_EDGE_RISING:
@@ -70,8 +110,8 @@ static int stm32_irq_set_type(struct irq_data *data, 
unsigned int type)
return -EINVAL;
}
 
-   irq_reg_writel(gc, rtsr, EXTI_RTSR);
-   irq_reg_writel(gc, ftsr, EXTI_FTSR);
+   irq_reg_writel(gc, rtsr, stm32_bank->rtsr_ofst);
+   irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst);
 
irq_gc_unlock(gc);
 
@@ -81,17 +121,18 @@ static int stm32_irq_set_type(struct irq_data *data, 
unsigned int type)
 static int stm32_irq_set_wake(struct irq_data *data, unsigned int on)
 {
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
-   int pin = data->hwirq;
+   const struct stm32_exti_bank *stm32_bank = gc->private;
+   int pin = data->hwirq % IRQS_PER_BANK;
u32 emr;
 
irq_gc_lock(gc);
 
-   emr = irq_reg_readl(gc, EXTI_EMR);
+   emr = irq_reg_readl(gc, stm32_bank->emr_ofst);
if (on)
emr |= BIT(pin);
else
emr &= ~BIT(pin);
-   irq_reg_writel(gc, emr, EXTI_EMR);
+   irq_reg_writel(gc, emr, stm32_bank->emr_ofst);
 
irq_gc_unlock(gc);
 
@@ -101,11 +142,12 @@ static int stm32_

[PATCH v3 8/9] ARM: dts: stm32: add system config bank node for stm32h743

2017-11-06 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds system config support for stm32h743.

Signed-off-by: Ludovic Barre 
---
 arch/arm/boot/dts/stm32h743.dtsi | 5 +
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/stm32h743.dtsi b/arch/arm/boot/dts/stm32h743.dtsi
index 6b2fb4c..b17aa5c 100644
--- a/arch/arm/boot/dts/stm32h743.dtsi
+++ b/arch/arm/boot/dts/stm32h743.dtsi
@@ -194,6 +194,11 @@
};
};
 
+   syscfg: system-config@58000400 {
+   compatible = "syscon";
+   reg = <0x58000400 0x400>;
+   };
+
exti: interrupt-controller@5800 {
compatible = "st,stm32h7-exti";
interrupt-controller;
-- 
2.7.4



[PATCH v3 9/9] ARM: dts: stm32: add support of exti on stm32h743 pinctrl

2017-11-06 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds support of external interrupt (exti) on
all gpio ports of stm32h743.

Signed-off-by: Ludovic Barre 
---
 arch/arm/boot/dts/stm32h743-pinctrl.dtsi | 24 
 1 file changed, 24 insertions(+)

diff --git a/arch/arm/boot/dts/stm32h743-pinctrl.dtsi 
b/arch/arm/boot/dts/stm32h743-pinctrl.dtsi
index 76bbd65..df0b441 100644
--- a/arch/arm/boot/dts/stm32h743-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stm32h743-pinctrl.dtsi
@@ -49,6 +49,8 @@
#size-cells = <1>;
compatible = "st,stm32h743-pinctrl";
ranges = <0 0x5802 0x3000>;
+   interrupt-parent = <&exti>;
+   st,syscfg = <&syscfg 0x8>;
pins-are-numbered;
 
gpioa: gpio@5802 {
@@ -57,6 +59,8 @@
reg = <0x0 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOA";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpiob: gpio@58020400 {
@@ -65,6 +69,8 @@
reg = <0x400 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOB";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpioc: gpio@58020800 {
@@ -73,6 +79,8 @@
reg = <0x800 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOC";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpiod: gpio@58020c00 {
@@ -81,6 +89,8 @@
reg = <0xc00 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOD";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpioe: gpio@58021000 {
@@ -89,6 +99,8 @@
reg = <0x1000 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOE";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpiof: gpio@58021400 {
@@ -97,6 +109,8 @@
reg = <0x1400 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOF";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpiog: gpio@58021800 {
@@ -105,6 +119,8 @@
reg = <0x1800 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOG";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpioh: gpio@58021c00 {
@@ -113,6 +129,8 @@
reg = <0x1c00 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOH";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpioi: gpio@58022000 {
@@ -121,6 +139,8 @@
reg = <0x2000 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOI";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpioj: gpio@58022400 {
@@ -129,6 +149,8 @@
reg = <0x2400 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOJ";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
gpiok: gpio@58022800 {
@@ -137,6 +159,8 @@
reg = <0x2800 0x400>;
clocks = <&timer_clk>;
st,bank-name = "GPIOK";
+   interrupt-controller;
+   #interrupt-cells = <2>;
};
 
usart1_pins: usart1@0 {
-- 
2.7.4



[PATCH v3 1/9] irqchip: stm32: select GENERIC_IRQ_CHIP

2017-11-06 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds GENERIC_IRQ_CHIP to stm32 exti
config.

Signed-off-by: Ludovic Barre 
---
 drivers/irqchip/Kconfig | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 9d8a1dd..c067aae 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -304,6 +304,7 @@ config EZNPS_GIC
 config STM32_EXTI
bool
select IRQ_DOMAIN
+   select GENERIC_IRQ_CHIP
 
 config QCOM_IRQ_COMBINER
bool "QCOM IRQ combiner support"
-- 
2.7.4



[PATCH v3 4/9] irqchip: stm32: add stm32h7 support

2017-11-06 Thread Ludovic Barre
From: Ludovic Barre 

stm32h7 has up to 96 inputs
(3 banks of 32 inputs max).

Signed-off-by: Ludovic Barre 
---
 drivers/irqchip/irq-stm32-exti.c | 42 
 1 file changed, 42 insertions(+)

diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index ef37870..8f409a9 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -38,6 +38,39 @@ static const struct stm32_exti_bank *stm32f4xx_exti_banks[] 
= {
&stm32f4xx_exti_b1,
 };
 
+static const struct stm32_exti_bank stm32h7xx_exti_b1 = {
+   .imr_ofst   = 0x80,
+   .emr_ofst   = 0x84,
+   .rtsr_ofst  = 0x00,
+   .ftsr_ofst  = 0x04,
+   .swier_ofst = 0x08,
+   .pr_ofst= 0x88,
+};
+
+static const struct stm32_exti_bank stm32h7xx_exti_b2 = {
+   .imr_ofst   = 0x90,
+   .emr_ofst   = 0x94,
+   .rtsr_ofst  = 0x20,
+   .ftsr_ofst  = 0x24,
+   .swier_ofst = 0x28,
+   .pr_ofst= 0x98,
+};
+
+static const struct stm32_exti_bank stm32h7xx_exti_b3 = {
+   .imr_ofst   = 0xA0,
+   .emr_ofst   = 0xA4,
+   .rtsr_ofst  = 0x40,
+   .ftsr_ofst  = 0x44,
+   .swier_ofst = 0x48,
+   .pr_ofst= 0xA8,
+};
+
+static const struct stm32_exti_bank *stm32h7xx_exti_banks[] = {
+   &stm32h7xx_exti_b1,
+   &stm32h7xx_exti_b2,
+   &stm32h7xx_exti_b3,
+};
+
 static unsigned long stm32_exti_pending(struct irq_chip_generic *gc)
 {
const struct stm32_exti_bank *stm32_bank = gc->private;
@@ -256,3 +289,12 @@ static int __init stm32f4_exti_of_init(struct device_node 
*np,
 }
 
 IRQCHIP_DECLARE(stm32f4_exti, "st,stm32-exti", stm32f4_exti_of_init);
+
+static int __init stm32h7_exti_of_init(struct device_node *np,
+  struct device_node *parent)
+{
+   return stm32_exti_init(stm32h7xx_exti_banks,
+   ARRAY_SIZE(stm32h7xx_exti_banks), np);
+}
+
+IRQCHIP_DECLARE(stm32h7_exti, "st,stm32h7-exti", stm32h7_exti_of_init);
-- 
2.7.4



[PATCH v3 5/9] irqchip: stm32: fix initial values

2017-11-06 Thread Ludovic Barre
From: Ludovic Barre 

-After cold boot, imr default value depends on hardware configuration.
-After hot reboot the registers must be cleared to avoid residue.

Signed-off-by: Ludovic Barre 
---
 drivers/irqchip/irq-stm32-exti.c | 9 +
 1 file changed, 9 insertions(+)

diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index 8f409a9..477d0fa 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -258,7 +258,16 @@ __init stm32_exti_init(const struct stm32_exti_bank 
**stm32_exti_banks,
writel_relaxed(~0UL, base + stm32_bank->rtsr_ofst);
irqs_mask = readl_relaxed(base + stm32_bank->rtsr_ofst);
nr_exti = fls(readl_relaxed(base + stm32_bank->rtsr_ofst));
+
+   /*
+* This IP has no reset, so after hot reboot we should
+* clear registers to avoid residue
+*/
+   writel_relaxed(0, base + stm32_bank->imr_ofst);
+   writel_relaxed(0, base + stm32_bank->emr_ofst);
writel_relaxed(0, base + stm32_bank->rtsr_ofst);
+   writel_relaxed(0, base + stm32_bank->ftsr_ofst);
+   writel_relaxed(~0UL, base + stm32_bank->pr_ofst);
 
pr_info("%s: bank%d, External IRQs available:%#x\n",
node->full_name, i, irqs_mask);
-- 
2.7.4



[PATCH v3 7/9] ARM: dts: stm32: add exti support for stm32h743

2017-11-06 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds support of external interrupt (exti)
for stm32h743.

Signed-off-by: Ludovic Barre 
---
 arch/arm/boot/dts/stm32h743.dtsi | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/stm32h743.dtsi b/arch/arm/boot/dts/stm32h743.dtsi
index 58ec227..6b2fb4c 100644
--- a/arch/arm/boot/dts/stm32h743.dtsi
+++ b/arch/arm/boot/dts/stm32h743.dtsi
@@ -193,6 +193,14 @@
status = "disabled";
};
};
+
+   exti: interrupt-controller@5800 {
+   compatible = "st,stm32h7-exti";
+   interrupt-controller;
+   #interrupt-cells = <2>;
+   reg = <0x5800 0x400>;
+   interrupts = <1>, <2>, <3>, <6>, <7>, <8>, <9>, <10>, 
<23>, <40>, <41>, <62>, <76>;
+   };
};
 };
 
-- 
2.7.4



[PATCH v3 6/9] irqchip: stm32: move the wakeup on interrupt mask

2017-11-06 Thread Ludovic Barre
From: Ludovic Barre 

Move irq_set_wake on interrupt mask, needed to wake up from
low power mode as the event mask is not able to do so.

Signed-off-by: Ludovic Barre 
---
 drivers/irqchip/irq-stm32-exti.c | 10 +-
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index 477d0fa..31ab0de 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -156,16 +156,16 @@ static int stm32_irq_set_wake(struct irq_data *data, 
unsigned int on)
struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
const struct stm32_exti_bank *stm32_bank = gc->private;
int pin = data->hwirq % IRQS_PER_BANK;
-   u32 emr;
+   u32 imr;
 
irq_gc_lock(gc);
 
-   emr = irq_reg_readl(gc, stm32_bank->emr_ofst);
+   imr = irq_reg_readl(gc, stm32_bank->imr_ofst);
if (on)
-   emr |= BIT(pin);
+   imr |= BIT(pin);
else
-   emr &= ~BIT(pin);
-   irq_reg_writel(gc, emr, stm32_bank->emr_ofst);
+   imr &= ~BIT(pin);
+   irq_reg_writel(gc, imr, stm32_bank->imr_ofst);
 
irq_gc_unlock(gc);
 
-- 
2.7.4



[PATCH v3 0/9] irqchip: stm32: add stm32h7 support

2017-11-06 Thread Ludovic Barre
From: Ludovic Barre 

This series adds:
-Management of multi-bank of external interrupts
stm32h7 has up to 96 inputs (3 banks of  32 inputs).
-Fix initial value after cold/hot boot (wakeup issue).

Changes v3:
-remove chip.name and handler, already done by
irq_alloc_domain_generic_chips
-add Rob ack in dt-bindings commit

Changes v2:
-Remove irq_mask and adds const on struct stm32_exti_bank
-Add wrapper functions pending and ack
-Replace BITS_PER_LONG by IRQS_PER_BANK
-Fill commit message on
"ARM: dts: stm32: add support of exti on stm32h743"
-Add system config bank for stm32h7

Ludovic Barre (9):
  irqchip: stm32: select GENERIC_IRQ_CHIP
  irqchip: stm32: add multi-bank management
  dt-bindings: interrupt-controllers: add compatible string for stm32h7
  irqchip: stm32: add stm32h7 support
  irqchip: stm32: fix initial values
  irqchip: stm32: move the wakeup on interrupt mask
  ARM: dts: stm32: add exti support for stm32h743
  ARM: dts: stm32: add system config bank node for stm32h743
  ARM: dts: stm32: add support of exti on stm32h743 pinctrl

 .../interrupt-controller/st,stm32-exti.txt |   4 +-
 arch/arm/boot/dts/stm32h743-pinctrl.dtsi   |  24 +++
 arch/arm/boot/dts/stm32h743.dtsi   |  13 ++
 drivers/irqchip/Kconfig|   1 +
 drivers/irqchip/irq-stm32-exti.c   | 206 -
 5 files changed, 198 insertions(+), 50 deletions(-)

-- 
2.7.4



Re: [PATCH v2 2/9] irqchip: stm32: add multi-bank management

2017-10-27 Thread Ludovic BARRE

Hi Julien

thank for your review

On 10/26/2017 04:36 PM, Julien Thierry wrote:

Hi Ludovic,

On 25/10/17 18:10, Ludovic Barre wrote:

From: Ludovic Barre 

-Prepare to manage multi-bank of external interrupts
(N banks of 32 inputs).
-Prepare to manage registers offsets by compatible
(registers offsets could be different follow per stm32 platform).

Signed-off-by: Ludovic Barre 
---
  drivers/irqchip/irq-stm32-exti.c | 151 
+++

  1 file changed, 105 insertions(+), 46 deletions(-)

diff --git a/drivers/irqchip/irq-stm32-exti.c 
b/drivers/irqchip/irq-stm32-exti.c

index 45363ff..6b4109b 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -14,27 +14,66 @@
  #include 
  #include 
-#define EXTI_IMR    0x0
-#define EXTI_EMR    0x4
-#define EXTI_RTSR    0x8
-#define EXTI_FTSR    0xc
-#define EXTI_SWIER    0x10
-#define EXTI_PR    0x14
+#define IRQS_PER_BANK 32
+
+struct stm32_exti_bank {
+    u32 imr_ofst;
+    u32 emr_ofst;
+    u32 rtsr_ofst;
+    u32 ftsr_ofst;
+    u32 swier_ofst;
+    u32 pr_ofst;
+};
+
+static const struct stm32_exti_bank stm32f4xx_exti_b1 = {
+    .imr_ofst    = 0x00,
+    .emr_ofst    = 0x04,
+    .rtsr_ofst    = 0x08,
+    .ftsr_ofst    = 0x0C,
+    .swier_ofst    = 0x10,
+    .pr_ofst    = 0x14,
+};
+
+static const struct stm32_exti_bank *stm32f4xx_exti_banks[] = {
+    &stm32f4xx_exti_b1,
+};
+
+static unsigned long stm32_exti_pending(struct irq_chip_generic *gc)
+{
+    const struct stm32_exti_bank *stm32_bank = gc->private;
+
+    return irq_reg_readl(gc, stm32_bank->pr_ofst);
+}
+
+static void stm32_exti_irq_ack(struct irq_chip_generic *gc, u32 mask)
+{
+    const struct stm32_exti_bank *stm32_bank = gc->private;
+
+    irq_reg_writel(gc, mask, stm32_bank->pr_ofst);
+}
  static void stm32_irq_handler(struct irq_desc *desc)
  {
  struct irq_domain *domain = irq_desc_get_handler_data(desc);
-    struct irq_chip_generic *gc = domain->gc->gc[0];
  struct irq_chip *chip = irq_desc_get_chip(desc);
+    unsigned int virq, nbanks = domain->gc->num_chips;
+    struct irq_chip_generic *gc;
+    const struct stm32_exti_bank *stm32_bank;
  unsigned long pending;
-    int n;
+    int n, i, irq_base = 0;
  chained_irq_enter(chip, desc);
-    while ((pending = irq_reg_readl(gc, EXTI_PR))) {
-    for_each_set_bit(n, &pending, BITS_PER_LONG) {
-    generic_handle_irq(irq_find_mapping(domain, n));
-    irq_reg_writel(gc, BIT(n), EXTI_PR);
+    for (i = 0; i < nbanks; i++, irq_base += IRQS_PER_BANK) {
+    gc = irq_get_domain_generic_chip(domain, irq_base);
+    stm32_bank = gc->private;
+
+    while ((pending = stm32_exti_pending(gc))) {
+    for_each_set_bit(n, &pending, IRQS_PER_BANK) {
+    virq = irq_find_mapping(domain, irq_base + n);
+    generic_handle_irq(virq);
+    stm32_exti_irq_ack(gc, BIT(n));
+    }
  }
  }
@@ -44,13 +83,14 @@ static void stm32_irq_handler(struct irq_desc *desc)
  static int stm32_irq_set_type(struct irq_data *data, unsigned int type)
  {
  struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
-    int pin = data->hwirq;
+    const struct stm32_exti_bank *stm32_bank = gc->private;
+    int pin = data->hwirq % IRQS_PER_BANK;
  u32 rtsr, ftsr;
  irq_gc_lock(gc);
-    rtsr = irq_reg_readl(gc, EXTI_RTSR);
-    ftsr = irq_reg_readl(gc, EXTI_FTSR);
+    rtsr = irq_reg_readl(gc, stm32_bank->rtsr_ofst);
+    ftsr = irq_reg_readl(gc, stm32_bank->ftsr_ofst);
  switch (type) {
  case IRQ_TYPE_EDGE_RISING:
@@ -70,8 +110,8 @@ static int stm32_irq_set_type(struct irq_data 
*data, unsigned int type)

  return -EINVAL;
  }
-    irq_reg_writel(gc, rtsr, EXTI_RTSR);
-    irq_reg_writel(gc, ftsr, EXTI_FTSR);
+    irq_reg_writel(gc, rtsr, stm32_bank->rtsr_ofst);
+    irq_reg_writel(gc, ftsr, stm32_bank->ftsr_ofst);
  irq_gc_unlock(gc);
@@ -81,17 +121,18 @@ static int stm32_irq_set_type(struct irq_data 
*data, unsigned int type)

  static int stm32_irq_set_wake(struct irq_data *data, unsigned int on)
  {
  struct irq_chip_generic *gc = irq_data_get_irq_chip_data(data);
-    int pin = data->hwirq;
+    const struct stm32_exti_bank *stm32_bank = gc->private;
+    int pin = data->hwirq % IRQS_PER_BANK;
  u32 emr;
  irq_gc_lock(gc);
-    emr = irq_reg_readl(gc, EXTI_EMR);
+    emr = irq_reg_readl(gc, stm32_bank->emr_ofst);
  if (on)
  emr |= BIT(pin);
  else
  emr &= ~BIT(pin);
-    irq_reg_writel(gc, emr, EXTI_EMR);
+    irq_reg_writel(gc, emr, stm32_bank->emr_ofst);
  irq_gc_unlock(gc);
@@ -101,11 +142,12 @@ static int stm32_irq_set_wake(struct irq_data 
*data, unsigned int on)

  static int stm32_exti_alloc(struct irq_domain *d, unsigned int virq,
  unsigned int nr_irqs, void *data)
  {
-    struct irq_chip_generic *gc

Re: [PATCH v2 1/3] mtd: spi-nor: stm32-quadspi: Fix uninitialized error return code

2017-10-30 Thread Ludovic BARRE

thanks Cyrille

indeed, the "Signed-off" on Geert'commit was a mistake

BR
Ludo
On 10/29/2017 06:50 PM, Cyrille Pitchen wrote:

Hi Ludovic,

Le 26/10/2017 à 17:12, Ludovic Barre a écrit :

From: Geert Uytterhoeven 

With gcc 4.1.2:

 drivers/mtd/spi-nor/stm32-quadspi.c: In function ‘stm32_qspi_tx_poll’:
 drivers/mtd/spi-nor/stm32-quadspi.c:230: warning: ‘ret’ may be used 
uninitialized in this function

Indeed, if stm32_qspi_cmd.len is zero, ret will be uninitialized.
This length is passed from outside the driver using the
spi_nor.{read,write}{,_reg}() callbacks.

Several functions in drivers/mtd/spi-nor/spi-nor.c (e.g. write_enable(),
write_disable(), and erase_chip()) call spi_nor.write_reg() with a zero
length.

Fix this by returning an explicit zero on success.

Fixes: 0d43d7ab277a048c ("mtd: spi-nor: add driver for STM32 quad spi flash 
controller")
Signed-off-by: Geert Uytterhoeven 
Acked-by: Ludovic Barre 
Signed-off-by: Ludovic Barre 

I removed your "Signed-off" because I think this is a mistake but kept
your "Acked-by" tag.

Applied to the spi-nor/next branch of l2-mtd.

Thanks!


---
  drivers/mtd/spi-nor/stm32-quadspi.c | 4 ++--
  1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/mtd/spi-nor/stm32-quadspi.c 
b/drivers/mtd/spi-nor/stm32-quadspi.c
index 86c0931..ad6a3e1 100644
--- a/drivers/mtd/spi-nor/stm32-quadspi.c
+++ b/drivers/mtd/spi-nor/stm32-quadspi.c
@@ -240,12 +240,12 @@ static int stm32_qspi_tx_poll(struct stm32_qspi *qspi,
 STM32_QSPI_FIFO_TIMEOUT_US);
if (ret) {
dev_err(qspi->dev, "fifo timeout (stat:%#x)\n", sr);
-   break;
+   return ret;
}
tx_fifo(buf++, qspi->io_base + QUADSPI_DR);
}
  
-	return ret;

+   return 0;
  }
  
  static int stm32_qspi_tx_mm(struct stm32_qspi *qspi,






Re: [PATCH V2 1/3] watchdog: stm32: add pclk feature for stm32mp1

2018-06-20 Thread Ludovic BARRE




On 06/20/2018 03:29 PM, Guenter Roeck wrote:

On 06/20/2018 06:24 AM, Ludovic BARRE wrote:



On 06/20/2018 11:19 AM, Guenter Roeck wrote:

On 06/20/2018 12:53 AM, Ludovic Barre wrote:

From: Ludovic Barre 

This patch adds config data to manage specific properties by
compatible. Adds stm32mp1 config which requires pclk clock.

Signed-off-by: Ludovic Barre 
---
  .../devicetree/bindings/watchdog/st,stm32-iwdg.txt |  21 +++-
  drivers/watchdog/stm32_iwdg.c  | 132 
++---

  2 files changed, 104 insertions(+), 49 deletions(-)

diff --git 
a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt 
b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt

index cc13b10a..f07f6d89 100644
--- a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
+++ b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
@@ -2,18 +2,31 @@ STM32 Independent WatchDoG (IWDG)
  -
  Required properties:
-- compatible: "st,stm32-iwdg"
-- reg: physical base address and length of the registers set for 
the device

-- clocks: must contain a single entry describing the clock input
+- compatible: Should be either "st,stm32-iwdg" or "st,stm32mp1-iwdg"
+- reg: Physical base address and length of the registers set for 
the device
+- clocks: Reference to the clock entry lsi. Additional pclk clock 
entry

+  is required only for st,stm32mp1-iwdg.
+- clock-names: Name of the clocks used.
+  "lsi" for st,stm32-iwdg
+  "pclk", "lsi" for st,stm32mp1-iwdg
  Optional Properties:
  - timeout-sec: Watchdog timeout value in seconds.
-Example:
+Examples:
  iwdg: watchdog@40003000 {
  compatible = "st,stm32-iwdg";
  reg = <0x40003000 0x400>;
  clocks = <&clk_lsi>;
+    clock-names = "lsi";
+    timeout-sec = <32>;
+};
+
+iwdg: iwdg@5a002000 {
+    compatible = "st,stm32mp1-iwdg";
+    reg = <0x5a002000 0x400>;
+    clocks = <&rcc IWDG2>, <&clk_lsi>;
+    clock-names = "pclk", "lsi";
  timeout-sec = <32>;
  };
diff --git a/drivers/watchdog/stm32_iwdg.c 
b/drivers/watchdog/stm32_iwdg.c

index c97ad56..fc96670 100644
--- a/drivers/watchdog/stm32_iwdg.c
+++ b/drivers/watchdog/stm32_iwdg.c
@@ -11,12 +11,13 @@
  #include 
  #include 
-#include 
-#include 
  #include 
  #include 
  #include 
+#include 
+#include 
  #include 
+#include 
  #include 
  #include 
@@ -54,11 +55,17 @@
  #define TIMEOUT_US    10
  #define SLEEP_US    1000
+struct stm32_iwdg_config {
+    bool has_pclk;
+};
+


This data structure is unnecessary. Just assign the boolean directly 
to .data

and ...



Ok, I send a v3, with boolean directly to .data
like:

#define NO_PCLK    false
#define HAS_PCLK    true
...


Just use true/false directly. There is no need for those defines.

If you want the reader to understand what is defined, I would be ok with

#define HAS_PCLK    true

static const struct of_device_id stm32_iwdg_of_match[] = {
  { .compatible = "st,stm32-iwdg", .data = (void *) !HAS_PCLK },
  { .compatible = "st,stm32mp1-iwdg", .data = (void *) HAS_PCLK },
  { /* end node */ }

Guenter


Ok, thanks




static const struct of_device_id stm32_iwdg_of_match[] = {
 { .compatible = "st,stm32-iwdg", .data = (void *) NO_PCLK },
 { .compatible = "st,stm32mp1-iwdg", .data = (void *) HAS_PCLK },
 { /* end node */ }
};

Note:
V3, because I sent my original version with V2
(it's mistake)


  struct stm32_iwdg {
-    struct watchdog_device    wdd;
-    void __iomem    *regs;
-    struct clk    *clk;
-    unsigned int    rate;
+    struct watchdog_device    wdd;
+    void __iomem    *regs;
+    struct stm32_iwdg_config    *config;


declare bool has_pclk here.


+    struct clk    *clk_lsi;
+    struct clk    *clk_pclk;
+    unsigned int    rate;
  };
  static inline u32 reg_read(void __iomem *base, u32 reg)
@@ -133,6 +140,44 @@ static int stm32_iwdg_set_timeout(struct 
watchdog_device *wdd,

  return 0;
  }
+static int stm32_iwdg_clk_init(struct platform_device *pdev,
+   struct stm32_iwdg *wdt)
+{
+    u32 ret;
+
+    wdt->clk_lsi = devm_clk_get(&pdev->dev, "lsi");
+    if (IS_ERR(wdt->clk_lsi)) {
+    dev_err(&pdev->dev, "Unable to get lsi clock\n");
+    return PTR_ERR(wdt->clk_lsi);
+    }
+
+    /* optional peripheral clock */
+    if (wdt->config->has_pclk) {
+    wdt->clk_pclk = devm_clk_get(&pdev->dev, "pclk");
+    if (IS_ERR(wdt->clk_pclk)) {
+    dev_err(&pdev->dev, "Unable to get pclk clock\n");
+    return PTR_ERR(wdt->clk_pclk);
+    }
+
+    ret = clk_prepare_enable(wdt->clk_pclk);
+    if (ret) {
+    dev_err(&am

[PATCH V3 2/3] ARM: dts: stm32: add iwdg2 support for stm32mp157c

2018-06-20 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds independent watchdog support for stm32mp157c.

Signed-off-by: Ludovic Barre 
---
 arch/arm/boot/dts/stm32mp157c.dtsi | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi 
b/arch/arm/boot/dts/stm32mp157c.dtsi
index 7d17538..95cc166 100644
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
@@ -784,6 +784,14 @@
status = "disabled";
};
 
+   iwdg2: watchdog@5a002000 {
+   compatible = "st,stm32mp1-iwdg";
+   reg = <0x5a002000 0x400>;
+   clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
+   clock-names = "pclk", "lsi";
+   status = "disabled";
+   };
+
usbphyc: usbphyc@5a006000 {
#address-cells = <1>;
#size-cells = <0>;
-- 
2.7.4



[PATCH V3 1/3] watchdog: stm32: add pclk feature for stm32mp1

2018-06-20 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds config data to manage specific properties by
compatible. Adds stm32mp1 config which requires pclk clock.

Signed-off-by: Ludovic Barre 
---
 .../devicetree/bindings/watchdog/st,stm32-iwdg.txt |  21 +++-
 drivers/watchdog/stm32_iwdg.c  | 116 +
 2 files changed, 91 insertions(+), 46 deletions(-)

diff --git a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt 
b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
index cc13b10a..f07f6d89 100644
--- a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
+++ b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
@@ -2,18 +2,31 @@ STM32 Independent WatchDoG (IWDG)
 -
 
 Required properties:
-- compatible: "st,stm32-iwdg"
-- reg: physical base address and length of the registers set for the device
-- clocks: must contain a single entry describing the clock input
+- compatible: Should be either "st,stm32-iwdg" or "st,stm32mp1-iwdg"
+- reg: Physical base address and length of the registers set for the device
+- clocks: Reference to the clock entry lsi. Additional pclk clock entry
+  is required only for st,stm32mp1-iwdg.
+- clock-names: Name of the clocks used.
+  "lsi" for st,stm32-iwdg
+  "pclk", "lsi" for st,stm32mp1-iwdg
 
 Optional Properties:
 - timeout-sec: Watchdog timeout value in seconds.
 
-Example:
+Examples:
 
 iwdg: watchdog@40003000 {
compatible = "st,stm32-iwdg";
reg = <0x40003000 0x400>;
clocks = <&clk_lsi>;
+   clock-names = "lsi";
+   timeout-sec = <32>;
+};
+
+iwdg: iwdg@5a002000 {
+   compatible = "st,stm32mp1-iwdg";
+   reg = <0x5a002000 0x400>;
+   clocks = <&rcc IWDG2>, <&clk_lsi>;
+   clock-names = "pclk", "lsi";
timeout-sec = <32>;
 };
diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c
index c97ad56..e00e3b3 100644
--- a/drivers/watchdog/stm32_iwdg.c
+++ b/drivers/watchdog/stm32_iwdg.c
@@ -11,12 +11,13 @@
 
 #include 
 #include 
-#include 
-#include 
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
+#include 
 #include 
 #include 
 
@@ -54,11 +55,15 @@
 #define TIMEOUT_US 10
 #define SLEEP_US   1000
 
+#define HAS_PCLK   true
+
 struct stm32_iwdg {
struct watchdog_device  wdd;
void __iomem*regs;
-   struct clk  *clk;
+   struct clk  *clk_lsi;
+   struct clk  *clk_pclk;
unsigned intrate;
+   boolhas_pclk;
 };
 
 static inline u32 reg_read(void __iomem *base, u32 reg)
@@ -133,6 +138,44 @@ static int stm32_iwdg_set_timeout(struct watchdog_device 
*wdd,
return 0;
 }
 
+static int stm32_iwdg_clk_init(struct platform_device *pdev,
+  struct stm32_iwdg *wdt)
+{
+   u32 ret;
+
+   wdt->clk_lsi = devm_clk_get(&pdev->dev, "lsi");
+   if (IS_ERR(wdt->clk_lsi)) {
+   dev_err(&pdev->dev, "Unable to get lsi clock\n");
+   return PTR_ERR(wdt->clk_lsi);
+   }
+
+   /* optional peripheral clock */
+   if (wdt->has_pclk) {
+   wdt->clk_pclk = devm_clk_get(&pdev->dev, "pclk");
+   if (IS_ERR(wdt->clk_pclk)) {
+   dev_err(&pdev->dev, "Unable to get pclk clock\n");
+   return PTR_ERR(wdt->clk_pclk);
+   }
+
+   ret = clk_prepare_enable(wdt->clk_pclk);
+   if (ret) {
+   dev_err(&pdev->dev, "Unable to prepare pclk clock\n");
+   return ret;
+   }
+   }
+
+   ret = clk_prepare_enable(wdt->clk_lsi);
+   if (ret) {
+   dev_err(&pdev->dev, "Unable to prepare lsi clock\n");
+   clk_disable_unprepare(wdt->clk_pclk);
+   return ret;
+   }
+
+   wdt->rate = clk_get_rate(wdt->clk_lsi);
+
+   return 0;
+}
+
 static const struct watchdog_info stm32_iwdg_info = {
.options= WDIOF_SETTIMEOUT |
  WDIOF_MAGICCLOSE |
@@ -147,49 +190,42 @@ static const struct watchdog_ops stm32_iwdg_ops = {
.set_timeout= stm32_iwdg_set_timeout,
 };
 
+static const struct of_device_id stm32_iwdg_of_match[] = {
+   { .compatible = "st,stm32-iwdg", .data = (void *)!HAS_PCLK },
+   { .compatible = "st,stm32mp1-iwdg", .data = (void *)HAS_PCLK },
+   { /* end node */ }
+};
+MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match);
+
 static int stm32_iwdg_probe(struct platform_device *pdev)
 {
struct watchdog_device *wdd;
+   const struct of_device_id *ma

[PATCH V3 3/3] ARM: dts: stm32: add iwdg2 support for stm32mp157c-ed1

2018-06-20 Thread Ludovic Barre
From: Ludovic Barre 

This patch activates independent watchdog support for
stm32mp157c board.

Signed-off-by: Ludovic Barre 
---
 arch/arm/boot/dts/stm32mp157c-ed1.dts | 5 +
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts 
b/arch/arm/boot/dts/stm32mp157c-ed1.dts
index ae33653..8af263a 100644
--- a/arch/arm/boot/dts/stm32mp157c-ed1.dts
+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts
@@ -68,6 +68,11 @@
status = "okay";
 };
 
+&iwdg2 {
+   timeout-sec = <32>;
+   status = "okay";
+};
+
 &uart4 {
pinctrl-names = "default";
pinctrl-0 = <&uart4_pins_a>;
-- 
2.7.4



[PATCH V3 0/3] add iwdg2 support for stm32mp157c

2018-06-20 Thread Ludovic Barre
From: Ludovic Barre 

This patch series updates stm32_iwdg driver to manage config
by compatible. stm32mp1 config requires a pclk clock.

v3:
-remove stm32_iwdg_config structure, just assign the
 boolean directly to .dat

Ludovic Barre (3):
  watchdog: stm32: add pclk feature for stm32mp1
  ARM: dts: stm32: add iwdg2 support for stm32mp157c
  ARM: dts: stm32: add iwdg2 support for stm32mp157c-ed1

 .../devicetree/bindings/watchdog/st,stm32-iwdg.txt |  21 +++-
 arch/arm/boot/dts/stm32mp157c-ed1.dts  |   5 +
 arch/arm/boot/dts/stm32mp157c.dtsi |   8 ++
 drivers/watchdog/stm32_iwdg.c  | 116 +
 4 files changed, 104 insertions(+), 46 deletions(-)

-- 
2.7.4



Re: [PATCH V3 1/3] watchdog: stm32: add pclk feature for stm32mp1

2018-06-21 Thread Ludovic BARRE




On 06/20/2018 09:14 PM, Rob Herring wrote:

On Wed, Jun 20, 2018 at 03:51:36PM +0200, Ludovic Barre wrote:

From: Ludovic Barre 

This patch adds config data to manage specific properties by
compatible. Adds stm32mp1 config which requires pclk clock.

Signed-off-by: Ludovic Barre 
---
  .../devicetree/bindings/watchdog/st,stm32-iwdg.txt |  21 +++-


Please split bindings to separate patch.


OK




  drivers/watchdog/stm32_iwdg.c  | 116 +
  2 files changed, 91 insertions(+), 46 deletions(-)

diff --git a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt 
b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
index cc13b10a..f07f6d89 100644
--- a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
+++ b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
@@ -2,18 +2,31 @@ STM32 Independent WatchDoG (IWDG)
  -
  
  Required properties:

-- compatible: "st,stm32-iwdg"
-- reg: physical base address and length of the registers set for the device
-- clocks: must contain a single entry describing the clock input
+- compatible: Should be either "st,stm32-iwdg" or "st,stm32mp1-iwdg"


Please format one per line.


OK




+- reg: Physical base address and length of the registers set for the device
+- clocks: Reference to the clock entry lsi. Additional pclk clock entry
+  is required only for st,stm32mp1-iwdg.
+- clock-names: Name of the clocks used.
+  "lsi" for st,stm32-iwdg
+  "pclk", "lsi" for st,stm32mp1-iwdg


Put lsi 1st so it is always index 0.


OK



  
  Optional Properties:

  - timeout-sec: Watchdog timeout value in seconds.
  
-Example:

+Examples:
  
  iwdg: watchdog@40003000 {

compatible = "st,stm32-iwdg";
reg = <0x40003000 0x400>;
clocks = <&clk_lsi>;
+   clock-names = "lsi";
+   timeout-sec = <32>;
+};
+
+iwdg: iwdg@5a002000 {


watchdog@...


sorry, I forget this occurrence.



Do we really need 2 example just to show 2 clocks?


No, I could keep only one




+   compatible = "st,stm32mp1-iwdg";
+   reg = <0x5a002000 0x400>;
+   clocks = <&rcc IWDG2>, <&clk_lsi>;
+   clock-names = "pclk", "lsi";
timeout-sec = <32>;
  };


[PATCH V4 3/4] ARM: dts: stm32: add iwdg2 support for stm32mp157c

2018-06-21 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds independent watchdog support for stm32mp157c.

Signed-off-by: Ludovic Barre 
---
 arch/arm/boot/dts/stm32mp157c.dtsi | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi 
b/arch/arm/boot/dts/stm32mp157c.dtsi
index 7d17538..95cc166 100644
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
@@ -784,6 +784,14 @@
status = "disabled";
};
 
+   iwdg2: watchdog@5a002000 {
+   compatible = "st,stm32mp1-iwdg";
+   reg = <0x5a002000 0x400>;
+   clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
+   clock-names = "pclk", "lsi";
+   status = "disabled";
+   };
+
usbphyc: usbphyc@5a006000 {
#address-cells = <1>;
#size-cells = <0>;
-- 
2.7.4



[PATCH V4 2/4] watchdog: stm32: add pclk feature for stm32mp1

2018-06-21 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds compatible data to manage pclk clock by
compatible. Adds stm32mp1 support which requires pclk clock.

Signed-off-by: Ludovic Barre 
---
 drivers/watchdog/stm32_iwdg.c | 116 +++---
 1 file changed, 74 insertions(+), 42 deletions(-)

diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c
index c97ad56..e00e3b3 100644
--- a/drivers/watchdog/stm32_iwdg.c
+++ b/drivers/watchdog/stm32_iwdg.c
@@ -11,12 +11,13 @@
 
 #include 
 #include 
-#include 
-#include 
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
+#include 
 #include 
 #include 
 
@@ -54,11 +55,15 @@
 #define TIMEOUT_US 10
 #define SLEEP_US   1000
 
+#define HAS_PCLK   true
+
 struct stm32_iwdg {
struct watchdog_device  wdd;
void __iomem*regs;
-   struct clk  *clk;
+   struct clk  *clk_lsi;
+   struct clk  *clk_pclk;
unsigned intrate;
+   boolhas_pclk;
 };
 
 static inline u32 reg_read(void __iomem *base, u32 reg)
@@ -133,6 +138,44 @@ static int stm32_iwdg_set_timeout(struct watchdog_device 
*wdd,
return 0;
 }
 
+static int stm32_iwdg_clk_init(struct platform_device *pdev,
+  struct stm32_iwdg *wdt)
+{
+   u32 ret;
+
+   wdt->clk_lsi = devm_clk_get(&pdev->dev, "lsi");
+   if (IS_ERR(wdt->clk_lsi)) {
+   dev_err(&pdev->dev, "Unable to get lsi clock\n");
+   return PTR_ERR(wdt->clk_lsi);
+   }
+
+   /* optional peripheral clock */
+   if (wdt->has_pclk) {
+   wdt->clk_pclk = devm_clk_get(&pdev->dev, "pclk");
+   if (IS_ERR(wdt->clk_pclk)) {
+   dev_err(&pdev->dev, "Unable to get pclk clock\n");
+   return PTR_ERR(wdt->clk_pclk);
+   }
+
+   ret = clk_prepare_enable(wdt->clk_pclk);
+   if (ret) {
+   dev_err(&pdev->dev, "Unable to prepare pclk clock\n");
+   return ret;
+   }
+   }
+
+   ret = clk_prepare_enable(wdt->clk_lsi);
+   if (ret) {
+   dev_err(&pdev->dev, "Unable to prepare lsi clock\n");
+   clk_disable_unprepare(wdt->clk_pclk);
+   return ret;
+   }
+
+   wdt->rate = clk_get_rate(wdt->clk_lsi);
+
+   return 0;
+}
+
 static const struct watchdog_info stm32_iwdg_info = {
.options= WDIOF_SETTIMEOUT |
  WDIOF_MAGICCLOSE |
@@ -147,49 +190,42 @@ static const struct watchdog_ops stm32_iwdg_ops = {
.set_timeout= stm32_iwdg_set_timeout,
 };
 
+static const struct of_device_id stm32_iwdg_of_match[] = {
+   { .compatible = "st,stm32-iwdg", .data = (void *)!HAS_PCLK },
+   { .compatible = "st,stm32mp1-iwdg", .data = (void *)HAS_PCLK },
+   { /* end node */ }
+};
+MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match);
+
 static int stm32_iwdg_probe(struct platform_device *pdev)
 {
struct watchdog_device *wdd;
+   const struct of_device_id *match;
struct stm32_iwdg *wdt;
struct resource *res;
-   void __iomem *regs;
-   struct clk *clk;
int ret;
 
+   match = of_match_device(stm32_iwdg_of_match, &pdev->dev);
+   if (!match)
+   return -ENODEV;
+
+   wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+   if (!wdt)
+   return -ENOMEM;
+
+   wdt->has_pclk = match->data;
+
/* This is the timer base. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-   regs = devm_ioremap_resource(&pdev->dev, res);
-   if (IS_ERR(regs)) {
+   wdt->regs = devm_ioremap_resource(&pdev->dev, res);
+   if (IS_ERR(wdt->regs)) {
dev_err(&pdev->dev, "Could not get resource\n");
-   return PTR_ERR(regs);
+   return PTR_ERR(wdt->regs);
}
 
-   clk = devm_clk_get(&pdev->dev, NULL);
-   if (IS_ERR(clk)) {
-   dev_err(&pdev->dev, "Unable to get clock\n");
-   return PTR_ERR(clk);
-   }
-
-   ret = clk_prepare_enable(clk);
-   if (ret) {
-   dev_err(&pdev->dev, "Unable to prepare clock %p\n", clk);
+   ret = stm32_iwdg_clk_init(pdev, wdt);
+   if (ret)
return ret;
-   }
-
-   /*
-* Allocate our watchdog driver data, which has the
-* struct watchdog_device nested within it.
-*/
-   wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
-   if (!wdt) {
-   ret = -ENOMEM;
-   goto err;
-   }
-
-   /* Initiali

[PATCH V4 0/4] add iwdg2 support for stm32mp157c

2018-06-21 Thread Ludovic Barre
From: Ludovic Barre 

This patch series updates stm32_iwdg driver to manage pclk
clock by compatible. stm32mp1 requires a pclk clock.

v4:
-dt-bindings: split and review

v3:
-remove stm32_iwdg_config structure, just assign the
 boolean directly to .dat

Ludovic Barre (4):
  dt-bindings: watchdog: add stm32mp1 support
  watchdog: stm32: add pclk feature for stm32mp1
  ARM: dts: stm32: add iwdg2 support for stm32mp157c
  ARM: dts: stm32: add iwdg2 support for stm32mp157c-ed1

 .../devicetree/bindings/watchdog/st,stm32-iwdg.txt |  13 ++-
 arch/arm/boot/dts/stm32mp157c-ed1.dts  |   5 +
 arch/arm/boot/dts/stm32mp157c.dtsi |   8 ++
 drivers/watchdog/stm32_iwdg.c  | 116 +
 4 files changed, 97 insertions(+), 45 deletions(-)

-- 
2.7.4



[PATCH V4 4/4] ARM: dts: stm32: add iwdg2 support for stm32mp157c-ed1

2018-06-21 Thread Ludovic Barre
From: Ludovic Barre 

This patch activates independent watchdog support for
stm32mp157c board.

Signed-off-by: Ludovic Barre 
---
 arch/arm/boot/dts/stm32mp157c-ed1.dts | 5 +
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts 
b/arch/arm/boot/dts/stm32mp157c-ed1.dts
index ae33653..8af263a 100644
--- a/arch/arm/boot/dts/stm32mp157c-ed1.dts
+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts
@@ -68,6 +68,11 @@
status = "okay";
 };
 
+&iwdg2 {
+   timeout-sec = <32>;
+   status = "okay";
+};
+
 &uart4 {
pinctrl-names = "default";
pinctrl-0 = <&uart4_pins_a>;
-- 
2.7.4



[PATCH V4 1/4] dt-bindings: watchdog: add stm32mp1 support

2018-06-21 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds support of stm32mp1.
stm32mp1 requires 2 clocks lsi and pclk.

Signed-off-by: Ludovic Barre 
---
 .../devicetree/bindings/watchdog/st,stm32-iwdg.txt  | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt 
b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
index cc13b10a..d8f4430 100644
--- a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
+++ b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
@@ -2,9 +2,15 @@ STM32 Independent WatchDoG (IWDG)
 -
 
 Required properties:
-- compatible: "st,stm32-iwdg"
-- reg: physical base address and length of the registers set for the device
-- clocks: must contain a single entry describing the clock input
+- compatible: Should be either:
+  - "st,stm32-iwdg"
+  - "st,stm32mp1-iwdg"
+- reg: Physical base address and length of the registers set for the device
+- clocks: Reference to the clock entry lsi. Additional pclk clock entry
+  is required only for st,stm32mp1-iwdg.
+- clock-names: Name of the clocks used.
+  "lsi" for st,stm32-iwdg
+  "lsi", "pclk" for st,stm32mp1-iwdg
 
 Optional Properties:
 - timeout-sec: Watchdog timeout value in seconds.
@@ -15,5 +21,6 @@ iwdg: watchdog@40003000 {
compatible = "st,stm32-iwdg";
reg = <0x40003000 0x400>;
clocks = <&clk_lsi>;
+   clock-names = "lsi";
timeout-sec = <32>;
 };
-- 
2.7.4



Re: [PATCH V4 2/4] watchdog: stm32: add pclk feature for stm32mp1

2018-06-22 Thread Ludovic BARRE




On 06/21/2018 06:53 PM, Guenter Roeck wrote:

On Thu, Jun 21, 2018 at 11:02:15AM +0200, Ludovic Barre wrote:

From: Ludovic Barre 

This patch adds compatible data to manage pclk clock by
compatible. Adds stm32mp1 support which requires pclk clock.

Signed-off-by: Ludovic Barre 
---
  drivers/watchdog/stm32_iwdg.c | 116 +++---
  1 file changed, 74 insertions(+), 42 deletions(-)

diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c
index c97ad56..e00e3b3 100644
--- a/drivers/watchdog/stm32_iwdg.c
+++ b/drivers/watchdog/stm32_iwdg.c
@@ -11,12 +11,13 @@
  
  #include 

  #include 
-#include 
-#include 
  #include 
  #include 
  #include 
+#include 
+#include 
  #include 
+#include 
  #include 
  #include 
  
@@ -54,11 +55,15 @@

  #define TIMEOUT_US10
  #define SLEEP_US  1000
  
+#define HAS_PCLK	true

+
  struct stm32_iwdg {
struct watchdog_device  wdd;
void __iomem*regs;
-   struct clk  *clk;
+   struct clk  *clk_lsi;
+   struct clk  *clk_pclk;
unsigned intrate;
+   boolhas_pclk;
  };
  
  static inline u32 reg_read(void __iomem *base, u32 reg)

@@ -133,6 +138,44 @@ static int stm32_iwdg_set_timeout(struct watchdog_device 
*wdd,
return 0;
  }
  
+static int stm32_iwdg_clk_init(struct platform_device *pdev,

+  struct stm32_iwdg *wdt)
+{
+   u32 ret;
+
+   wdt->clk_lsi = devm_clk_get(&pdev->dev, "lsi");


I just noticed a subtle difference: This used to be
devm_clk_get(&pdev->dev, NULL);
which would always get the first clock, no matter how it is named.
Can that cause problems with backward compatibility ?


You are right Guenter.

When there are multiple clocks, I prefer to use name interface.
I find it easier to use, and avoid misunderstanding.

Today, only one "dtsi" define the watchdog and it's disabled
(stm32f429.dtsi). I think it's good moment to move to clock named
(before it is used anymore).

But you are right I forgot to change stm32f429.dtsi.
If I add a commit for stm32f429.dtsi, it's Ok for you ?

BR
Ludo



Thanks,
Guenter


+   if (IS_ERR(wdt->clk_lsi)) {
+   dev_err(&pdev->dev, "Unable to get lsi clock\n");
+   return PTR_ERR(wdt->clk_lsi);
+   }
+
+   /* optional peripheral clock */
+   if (wdt->has_pclk) {
+   wdt->clk_pclk = devm_clk_get(&pdev->dev, "pclk");
+   if (IS_ERR(wdt->clk_pclk)) {
+   dev_err(&pdev->dev, "Unable to get pclk clock\n");
+   return PTR_ERR(wdt->clk_pclk);
+   }
+
+   ret = clk_prepare_enable(wdt->clk_pclk);
+   if (ret) {
+   dev_err(&pdev->dev, "Unable to prepare pclk clock\n");
+   return ret;
+   }
+   }
+
+   ret = clk_prepare_enable(wdt->clk_lsi);
+   if (ret) {
+   dev_err(&pdev->dev, "Unable to prepare lsi clock\n");
+   clk_disable_unprepare(wdt->clk_pclk);
+   return ret;
+   }
+
+   wdt->rate = clk_get_rate(wdt->clk_lsi);
+
+   return 0;
+}
+
  static const struct watchdog_info stm32_iwdg_info = {
.options= WDIOF_SETTIMEOUT |
  WDIOF_MAGICCLOSE |
@@ -147,49 +190,42 @@ static const struct watchdog_ops stm32_iwdg_ops = {
.set_timeout= stm32_iwdg_set_timeout,
  };
  
+static const struct of_device_id stm32_iwdg_of_match[] = {

+   { .compatible = "st,stm32-iwdg", .data = (void *)!HAS_PCLK },
+   { .compatible = "st,stm32mp1-iwdg", .data = (void *)HAS_PCLK },
+   { /* end node */ }
+};
+MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match);
+
  static int stm32_iwdg_probe(struct platform_device *pdev)
  {
struct watchdog_device *wdd;
+   const struct of_device_id *match;
struct stm32_iwdg *wdt;
struct resource *res;
-   void __iomem *regs;
-   struct clk *clk;
int ret;
  
+	match = of_match_device(stm32_iwdg_of_match, &pdev->dev);

+   if (!match)
+   return -ENODEV;
+
+   wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+   if (!wdt)
+   return -ENOMEM;
+
+   wdt->has_pclk = match->data;
+
/* This is the timer base. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-   regs = devm_ioremap_resource(&pdev->dev, res);
-   if (IS_ERR(regs)) {
+   wdt->regs = devm_ioremap_resource(&pdev->dev, res);
+   if (IS_ERR(wdt->regs)) {
dev_err(&pdev->dev, "Could not get resource\n");
-   return PTR_ERR(regs);

[PATCH V5 1/5] dt-bindings: watchdog: add stm32mp1 support

2018-06-25 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds support of stm32mp1.
stm32mp1 requires 2 clocks lsi and pclk.

Signed-off-by: Ludovic Barre 
---
 .../devicetree/bindings/watchdog/st,stm32-iwdg.txt  | 13 ++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt 
b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
index cc13b10a..d8f4430 100644
--- a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
+++ b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
@@ -2,9 +2,15 @@ STM32 Independent WatchDoG (IWDG)
 -
 
 Required properties:
-- compatible: "st,stm32-iwdg"
-- reg: physical base address and length of the registers set for the device
-- clocks: must contain a single entry describing the clock input
+- compatible: Should be either:
+  - "st,stm32-iwdg"
+  - "st,stm32mp1-iwdg"
+- reg: Physical base address and length of the registers set for the device
+- clocks: Reference to the clock entry lsi. Additional pclk clock entry
+  is required only for st,stm32mp1-iwdg.
+- clock-names: Name of the clocks used.
+  "lsi" for st,stm32-iwdg
+  "lsi", "pclk" for st,stm32mp1-iwdg
 
 Optional Properties:
 - timeout-sec: Watchdog timeout value in seconds.
@@ -15,5 +21,6 @@ iwdg: watchdog@40003000 {
compatible = "st,stm32-iwdg";
reg = <0x40003000 0x400>;
clocks = <&clk_lsi>;
+   clock-names = "lsi";
timeout-sec = <32>;
 };
-- 
2.7.4



[PATCH V5 0/5] add iwdg2 support for stm32mp157c

2018-06-25 Thread Ludovic Barre
From: Ludovic Barre 

This patch series updates stm32_iwdg driver to manage pclk
clock by compatible. stm32mp1 requires a pclk clock.

v5:
-update stm32f429.dtsi

v4:
-dt-bindings: split and review

v3:
-remove stm32_iwdg_config structure, just assign the
 boolean directly to .dat

Ludovic Barre (5):
  dt-bindings: watchdog: add stm32mp1 support
  watchdog: stm32: add pclk feature for stm32mp1
  ARM: dts: stm32: add iwdg2 support for stm32mp157c
  ARM: dts: stm32: add iwdg2 support for stm32mp157c-ed1
  ARM: dts: stm32: update iwdg with lsi clock name for stm32f429

 .../devicetree/bindings/watchdog/st,stm32-iwdg.txt |  13 ++-
 arch/arm/boot/dts/stm32f429.dtsi   |   1 +
 arch/arm/boot/dts/stm32mp157c-ed1.dts  |   5 +
 arch/arm/boot/dts/stm32mp157c.dtsi |   8 ++
 drivers/watchdog/stm32_iwdg.c  | 116 +
 5 files changed, 98 insertions(+), 45 deletions(-)

-- 
2.7.4



[PATCH V5 2/5] watchdog: stm32: add pclk feature for stm32mp1

2018-06-25 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds compatible data to manage pclk clock by
compatible. Adds stm32mp1 support which requires pclk clock.

Signed-off-by: Ludovic Barre 
Acked-by: Alexandre TORGUE 
---
 drivers/watchdog/stm32_iwdg.c | 116 +++---
 1 file changed, 74 insertions(+), 42 deletions(-)

diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c
index c97ad56..e00e3b3 100644
--- a/drivers/watchdog/stm32_iwdg.c
+++ b/drivers/watchdog/stm32_iwdg.c
@@ -11,12 +11,13 @@
 
 #include 
 #include 
-#include 
-#include 
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
+#include 
 #include 
 #include 
 
@@ -54,11 +55,15 @@
 #define TIMEOUT_US 10
 #define SLEEP_US   1000
 
+#define HAS_PCLK   true
+
 struct stm32_iwdg {
struct watchdog_device  wdd;
void __iomem*regs;
-   struct clk  *clk;
+   struct clk  *clk_lsi;
+   struct clk  *clk_pclk;
unsigned intrate;
+   boolhas_pclk;
 };
 
 static inline u32 reg_read(void __iomem *base, u32 reg)
@@ -133,6 +138,44 @@ static int stm32_iwdg_set_timeout(struct watchdog_device 
*wdd,
return 0;
 }
 
+static int stm32_iwdg_clk_init(struct platform_device *pdev,
+  struct stm32_iwdg *wdt)
+{
+   u32 ret;
+
+   wdt->clk_lsi = devm_clk_get(&pdev->dev, "lsi");
+   if (IS_ERR(wdt->clk_lsi)) {
+   dev_err(&pdev->dev, "Unable to get lsi clock\n");
+   return PTR_ERR(wdt->clk_lsi);
+   }
+
+   /* optional peripheral clock */
+   if (wdt->has_pclk) {
+   wdt->clk_pclk = devm_clk_get(&pdev->dev, "pclk");
+   if (IS_ERR(wdt->clk_pclk)) {
+   dev_err(&pdev->dev, "Unable to get pclk clock\n");
+   return PTR_ERR(wdt->clk_pclk);
+   }
+
+   ret = clk_prepare_enable(wdt->clk_pclk);
+   if (ret) {
+   dev_err(&pdev->dev, "Unable to prepare pclk clock\n");
+   return ret;
+   }
+   }
+
+   ret = clk_prepare_enable(wdt->clk_lsi);
+   if (ret) {
+   dev_err(&pdev->dev, "Unable to prepare lsi clock\n");
+   clk_disable_unprepare(wdt->clk_pclk);
+   return ret;
+   }
+
+   wdt->rate = clk_get_rate(wdt->clk_lsi);
+
+   return 0;
+}
+
 static const struct watchdog_info stm32_iwdg_info = {
.options= WDIOF_SETTIMEOUT |
  WDIOF_MAGICCLOSE |
@@ -147,49 +190,42 @@ static const struct watchdog_ops stm32_iwdg_ops = {
.set_timeout= stm32_iwdg_set_timeout,
 };
 
+static const struct of_device_id stm32_iwdg_of_match[] = {
+   { .compatible = "st,stm32-iwdg", .data = (void *)!HAS_PCLK },
+   { .compatible = "st,stm32mp1-iwdg", .data = (void *)HAS_PCLK },
+   { /* end node */ }
+};
+MODULE_DEVICE_TABLE(of, stm32_iwdg_of_match);
+
 static int stm32_iwdg_probe(struct platform_device *pdev)
 {
struct watchdog_device *wdd;
+   const struct of_device_id *match;
struct stm32_iwdg *wdt;
struct resource *res;
-   void __iomem *regs;
-   struct clk *clk;
int ret;
 
+   match = of_match_device(stm32_iwdg_of_match, &pdev->dev);
+   if (!match)
+   return -ENODEV;
+
+   wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
+   if (!wdt)
+   return -ENOMEM;
+
+   wdt->has_pclk = match->data;
+
/* This is the timer base. */
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-   regs = devm_ioremap_resource(&pdev->dev, res);
-   if (IS_ERR(regs)) {
+   wdt->regs = devm_ioremap_resource(&pdev->dev, res);
+   if (IS_ERR(wdt->regs)) {
dev_err(&pdev->dev, "Could not get resource\n");
-   return PTR_ERR(regs);
+   return PTR_ERR(wdt->regs);
}
 
-   clk = devm_clk_get(&pdev->dev, NULL);
-   if (IS_ERR(clk)) {
-   dev_err(&pdev->dev, "Unable to get clock\n");
-   return PTR_ERR(clk);
-   }
-
-   ret = clk_prepare_enable(clk);
-   if (ret) {
-   dev_err(&pdev->dev, "Unable to prepare clock %p\n", clk);
+   ret = stm32_iwdg_clk_init(pdev, wdt);
+   if (ret)
return ret;
-   }
-
-   /*
-* Allocate our watchdog driver data, which has the
-* struct watchdog_device nested within it.
-*/
-   wdt = devm_kzalloc(&pdev->dev, sizeof(*wdt), GFP_KERNEL);
-   if (!wdt) {
-   ret = -ENOMEM;
-   goto err;
-   }

[PATCH V5 5/5] ARM: dts: stm32: update iwdg with lsi clock name for stm32f429

2018-06-25 Thread Ludovic Barre
From: Ludovic Barre 

This patch updates iwdg watchdog to use lsi clock name.

Signed-off-by: Ludovic Barre 
---
 arch/arm/boot/dts/stm32f429.dtsi | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm/boot/dts/stm32f429.dtsi b/arch/arm/boot/dts/stm32f429.dtsi
index ede77e0..39ea13a 100644
--- a/arch/arm/boot/dts/stm32f429.dtsi
+++ b/arch/arm/boot/dts/stm32f429.dtsi
@@ -310,6 +310,7 @@
compatible = "st,stm32-iwdg";
reg = <0x40003000 0x400>;
clocks = <&clk_lsi>;
+   clock-names = "lsi";
status = "disabled";
};
 
-- 
2.7.4



[PATCH V5 4/5] ARM: dts: stm32: add iwdg2 support for stm32mp157c-ed1

2018-06-25 Thread Ludovic Barre
From: Ludovic Barre 

This patch activates independent watchdog support for
stm32mp157c board.

Signed-off-by: Ludovic Barre 
---
 arch/arm/boot/dts/stm32mp157c-ed1.dts | 5 +
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts 
b/arch/arm/boot/dts/stm32mp157c-ed1.dts
index ae33653..8af263a 100644
--- a/arch/arm/boot/dts/stm32mp157c-ed1.dts
+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts
@@ -68,6 +68,11 @@
status = "okay";
 };
 
+&iwdg2 {
+   timeout-sec = <32>;
+   status = "okay";
+};
+
 &uart4 {
pinctrl-names = "default";
pinctrl-0 = <&uart4_pins_a>;
-- 
2.7.4



[PATCH V5 3/5] ARM: dts: stm32: add iwdg2 support for stm32mp157c

2018-06-25 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds independent watchdog support for stm32mp157c.

Signed-off-by: Ludovic Barre 
---
 arch/arm/boot/dts/stm32mp157c.dtsi | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi 
b/arch/arm/boot/dts/stm32mp157c.dtsi
index 7d17538..95cc166 100644
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
@@ -784,6 +784,14 @@
status = "disabled";
};
 
+   iwdg2: watchdog@5a002000 {
+   compatible = "st,stm32mp1-iwdg";
+   reg = <0x5a002000 0x400>;
+   clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
+   clock-names = "pclk", "lsi";
+   status = "disabled";
+   };
+
usbphyc: usbphyc@5a006000 {
#address-cells = <1>;
#size-cells = <0>;
-- 
2.7.4



Re: [PATCH] irqchip/stm32: fix init error handling

2018-08-08 Thread Ludovic BARRE
oh yes, host_data is dereferenced (for kfree into out_free_mem) if 
stm32_exti_host_init fail


thanks Dan

BR
Ludo

On 08/08/2018 02:03 PM, Dan Carpenter wrote:

If there are any errors in stm32_exti_host_init() then it leads to a
NULL dereference in the callers.  The function should clean up after
itself.

Fixes: f9fc1745501e ("irqchip/stm32: Add host and driver data structures")
Signed-off-by: Dan Carpenter 


Reviewed-by: Ludovic Barre 



diff --git a/drivers/irqchip/irq-stm32-exti.c b/drivers/irqchip/irq-stm32-exti.c
index 3df527fcf4e1..0a2088e12d96 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c
@@ -603,17 +603,24 @@ stm32_exti_host_data *stm32_exti_host_init(const struct 
stm32_exti_drv_data *dd,
sizeof(struct stm32_exti_chip_data),
GFP_KERNEL);
if (!host_data->chips_data)
-   return NULL;
+   goto free_host_data;
  
  	host_data->base = of_iomap(node, 0);

if (!host_data->base) {
pr_err("%pOF: Unable to map registers\n", node);
-   return NULL;
+   goto free_chips_data;
}
  
  	stm32_host_data = host_data;
  
  	return host_data;

+
+free_chips_data:
+   kfree(host_data->chips_data);
+free_host_data:
+   kfree(host_data);
+
+   return NULL;
  }
  
  static struct

@@ -665,10 +672,8 @@ static int __init stm32_exti_init(const struct 
stm32_exti_drv_data *drv_data,
struct irq_domain *domain;
  
  	host_data = stm32_exti_host_init(drv_data, node);

-   if (!host_data) {
-   ret = -ENOMEM;
-   goto out_free_mem;
-   }
+   if (!host_data)
+   return -ENOMEM;
  
  	domain = irq_domain_add_linear(node, drv_data->bank_nr * IRQS_PER_BANK,

   &irq_exti_domain_ops, NULL);
@@ -725,7 +730,6 @@ static int __init stm32_exti_init(const struct 
stm32_exti_drv_data *drv_data,
irq_domain_remove(domain);
  out_unmap:
iounmap(host_data->base);
-out_free_mem:
kfree(host_data->chips_data);
kfree(host_data);
return ret;
@@ -752,10 +756,8 @@ __init stm32_exti_hierarchy_init(const struct 
stm32_exti_drv_data *drv_data,
}
  
  	host_data = stm32_exti_host_init(drv_data, node);

-   if (!host_data) {
-   ret = -ENOMEM;
-   goto out_free_mem;
-   }
+   if (!host_data)
+   return -ENOMEM;
  
  	for (i = 0; i < drv_data->bank_nr; i++)

stm32_exti_chip_init(host_data, i, node);
@@ -777,7 +779,6 @@ __init stm32_exti_hierarchy_init(const struct 
stm32_exti_drv_data *drv_data,
  
  out_unmap:

iounmap(host_data->base);
-out_free_mem:
kfree(host_data->chips_data);
kfree(host_data);
return ret;



Re: linux-next: manual merge of the pinctrl tree with the devicetree tree

2018-07-31 Thread Ludovic BARRE




On 07/31/2018 07:42 AM, Stephen Rothwell wrote:

Hi all,

Today's linux-next merge of the pinctrl tree got a conflict in:

   Documentation/devicetree/bindings/pinctrl/st,stm32-pinctrl.txt

between commit:

   791d3ef2e111 ("dt-bindings: remove 'interrupt-parent' from bindings")

from the devicetree tree and commit:

   de1d08b22974 ("dt-bindings: pinctrl: add syscfg mask parameter")

from the pinctrl tree.

I fixed it up (see below) and can carry the fix as necessary. This
is now fixed as far as linux-next is concerned, but any non trivial
conflicts should be mentioned to your upstream maintainer when your tree
is submitted for merging.  You may also want to consider cooperating
with the maintainer of the conflicting tree to minimise any particularly
complex conflicts.



hi Stephen

thanks for the fix conflict, and the fix is OK for me.

BR
Ludo


[PATCH 10/14] mmc: mmci: add dma_release callback

2018-08-01 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds dma_release callback at mmci_host_ops
to allow to call specific variant.

Signed-off-by: Ludovic Barre 
---
 drivers/mmc/host/mmci.c  | 13 -
 drivers/mmc/host/mmci.h  |  2 ++
 drivers/mmc/host/mmci_qcom_dml.c |  1 +
 3 files changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index ae47d08..177e2e8 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -409,6 +409,12 @@ int mmci_dma_setup(struct mmci_host *host)
return host->ops->dma_setup(host);
 }
 
+void mmci_dma_release(struct mmci_host *host)
+{
+   if (host->ops && host->ops->dma_release)
+   host->ops->dma_release(host);
+}
+
 static void
 mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
 {
@@ -546,7 +552,7 @@ int mmci_dmae_setup(struct mmci_host *host)
  * This is used in or so inline it
  * so it can be discarded.
  */
-static inline void mmci_dma_release(struct mmci_host *host)
+void mmci_dmae_release(struct mmci_host *host)
 {
struct dmaengine_priv *dmae = host->dma_priv;
 
@@ -799,13 +805,10 @@ static struct mmci_host_ops mmci_variant_ops = {
.unprepare_data = mmci_dmae_unprepare_data,
.get_next_data = mmci_dmae_get_next_data,
.dma_setup = mmci_dmae_setup,
+   .dma_release = mmci_dmae_release,
 };
 #else
 /* Blank functions if the DMA engine is not available */
-static inline void mmci_dma_release(struct mmci_host *host)
-{
-}
-
 static inline void mmci_dma_finalize(struct mmci_host *host,
 struct mmc_data *data)
 {
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index e1b389c..f961f90 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -279,6 +279,7 @@ struct mmci_host_ops {
   int err);
void (*get_next_data)(struct mmci_host *host, struct mmc_data *data);
int (*dma_setup)(struct mmci_host *host);
+   void (*dma_release)(struct mmci_host *host);
 };
 
 struct mmci_host {
@@ -336,3 +337,4 @@ void mmci_dmae_unprepare_data(struct mmci_host *host,
  struct mmc_data *data, int err);
 void mmci_dmae_get_next_data(struct mmci_host *host, struct mmc_data *data);
 int mmci_dmae_setup(struct mmci_host *host);
+void mmci_dmae_release(struct mmci_host *host);
diff --git a/drivers/mmc/host/mmci_qcom_dml.c b/drivers/mmc/host/mmci_qcom_dml.c
index 47abbdd..3c9d32e 100644
--- a/drivers/mmc/host/mmci_qcom_dml.c
+++ b/drivers/mmc/host/mmci_qcom_dml.c
@@ -186,6 +186,7 @@ static struct mmci_host_ops qcom_variant_ops = {
.unprepare_data = mmci_dmae_unprepare_data,
.get_next_data = mmci_dmae_get_next_data,
.dma_setup = qcom_dma_setup,
+   .dma_release = mmci_dmae_release,
 };
 
 void qcom_variant_init(struct mmci_host *host)
-- 
2.7.4



[PATCH 04/14] mmc: mmci: introduce dma_priv pointer to mmci_host

2018-08-01 Thread Ludovic Barre
From: Ludovic Barre 

This patch introduces dma_priv pointer to define specific
needs for each dma engine. This patch is needed to prepare
sdmmc variant with internal dma which not use dmaengine API.

Signed-off-by: Ludovic Barre 
---
 drivers/mmc/host/mmci.c  | 165 +--
 drivers/mmc/host/mmci.h  |  20 +
 drivers/mmc/host/mmci_qcom_dml.c |   6 +-
 3 files changed, 112 insertions(+), 79 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 8144a87..bdc48c3 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -415,31 +415,57 @@ static void mmci_init_sg(struct mmci_host *host, struct 
mmc_data *data)
  * no custom DMA interfaces are supported.
  */
 #ifdef CONFIG_DMA_ENGINE
-static void mmci_dma_setup(struct mmci_host *host)
+struct dmaengine_next {
+   struct dma_async_tx_descriptor *dma_desc;
+   struct dma_chan *dma_chan;
+   s32 cookie;
+};
+
+struct dmaengine_priv {
+   struct dma_chan *dma_current;
+   struct dma_chan *dma_rx_channel;
+   struct dma_chan *dma_tx_channel;
+   struct dma_async_tx_descriptor  *dma_desc_current;
+   struct dmaengine_next next_data;
+   bool dma_in_progress;
+};
+
+#define __dmae_inprogress(dmae) ((dmae)->dma_in_progress)
+
+static int mmci_dma_setup(struct mmci_host *host)
 {
const char *rxname, *txname;
+   struct dmaengine_priv *dmae;
 
-   host->dma_rx_channel = dma_request_slave_channel(mmc_dev(host->mmc), 
"rx");
-   host->dma_tx_channel = dma_request_slave_channel(mmc_dev(host->mmc), 
"tx");
+   dmae = devm_kzalloc(mmc_dev(host->mmc), sizeof(*dmae), GFP_KERNEL);
+   if (!dmae)
+   return -ENOMEM;
+
+   host->dma_priv = dmae;
+
+   dmae->dma_rx_channel = dma_request_slave_channel(mmc_dev(host->mmc),
+"rx");
+   dmae->dma_tx_channel = dma_request_slave_channel(mmc_dev(host->mmc),
+"tx");
 
/* initialize pre request cookie */
-   host->next_data.cookie = 1;
+   dmae->next_data.cookie = 1;
 
/*
 * If only an RX channel is specified, the driver will
 * attempt to use it bidirectionally, however if it is
 * is specified but cannot be located, DMA will be disabled.
 */
-   if (host->dma_rx_channel && !host->dma_tx_channel)
-   host->dma_tx_channel = host->dma_rx_channel;
+   if (dmae->dma_rx_channel && !dmae->dma_tx_channel)
+   dmae->dma_tx_channel = dmae->dma_rx_channel;
 
-   if (host->dma_rx_channel)
-   rxname = dma_chan_name(host->dma_rx_channel);
+   if (dmae->dma_rx_channel)
+   rxname = dma_chan_name(dmae->dma_rx_channel);
else
rxname = "none";
 
-   if (host->dma_tx_channel)
-   txname = dma_chan_name(host->dma_tx_channel);
+   if (dmae->dma_tx_channel)
+   txname = dma_chan_name(dmae->dma_tx_channel);
else
txname = "none";
 
@@ -450,15 +476,15 @@ static void mmci_dma_setup(struct mmci_host *host)
 * Limit the maximum segment size in any SG entry according to
 * the parameters of the DMA engine device.
 */
-   if (host->dma_tx_channel) {
-   struct device *dev = host->dma_tx_channel->device->dev;
+   if (dmae->dma_tx_channel) {
+   struct device *dev = dmae->dma_tx_channel->device->dev;
unsigned int max_seg_size = dma_get_max_seg_size(dev);
 
if (max_seg_size < host->mmc->max_seg_size)
host->mmc->max_seg_size = max_seg_size;
}
-   if (host->dma_rx_channel) {
-   struct device *dev = host->dma_rx_channel->device->dev;
+   if (dmae->dma_rx_channel) {
+   struct device *dev = dmae->dma_rx_channel->device->dev;
unsigned int max_seg_size = dma_get_max_seg_size(dev);
 
if (max_seg_size < host->mmc->max_seg_size)
@@ -466,7 +492,9 @@ static void mmci_dma_setup(struct mmci_host *host)
}
 
if (host->ops && host->ops->dma_setup)
-   host->ops->dma_setup(host);
+   return host->ops->dma_setup(host);
+
+   return 0;
 }
 
 /*
@@ -475,21 +503,24 @@ static void mmci_dma_setup(struct mmci_host *host)
  */
 static inline void mmci_dma_release(struct mmci_host *host)
 {
-   if (host->dma_rx_channel)
-   dma_release_channel(host->dma_rx_channel);
-   if (host->dma_tx_channel)
-   dma_release_channel(host->dma_tx_channel);
-   host->dma_rx_channel = host

[PATCH 12/14] mmc: mmci: add dma_finalize callback

2018-08-01 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds dma_finalize callback at mmci_host_ops
to allow to call specific variant.

Signed-off-by: Ludovic Barre 
---
 drivers/mmc/host/mmci.c  | 14 --
 drivers/mmc/host/mmci.h  |  2 ++
 drivers/mmc/host/mmci_qcom_dml.c |  1 +
 3 files changed, 11 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 642ef19..b124a73 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -447,6 +447,12 @@ int mmci_dma_start(struct mmci_host *host, unsigned int 
datactrl)
return 0;
 }
 
+void mmci_dma_finalize(struct mmci_host *host, struct mmc_data *data)
+{
+   if (host->ops && host->ops->dma_finalize)
+   host->ops->dma_finalize(host, data);
+}
+
 static void
 mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
 {
@@ -626,7 +632,7 @@ static void mmci_dma_data_error(struct mmci_host *host)
__mmci_dmae_unmap(host, host->data);
 }
 
-static void mmci_dma_finalize(struct mmci_host *host, struct mmc_data *data)
+void mmci_dmae_finalize(struct mmci_host *host, struct mmc_data *data)
 {
struct dmaengine_priv *dmae = host->dma_priv;
u32 status;
@@ -820,14 +826,10 @@ static struct mmci_host_ops mmci_variant_ops = {
.dma_setup = mmci_dmae_setup,
.dma_release = mmci_dmae_release,
.dma_start = mmci_dmae_start,
+   .dma_finalize = mmci_dmae_finalize,
 };
 #else
 /* Blank functions if the DMA engine is not available */
-static inline void mmci_dma_finalize(struct mmci_host *host,
-struct mmc_data *data)
-{
-}
-
 static inline void mmci_dma_data_error(struct mmci_host *host)
 {
 }
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 3a200a9..3f482d5 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -281,6 +281,7 @@ struct mmci_host_ops {
int (*dma_setup)(struct mmci_host *host);
void (*dma_release)(struct mmci_host *host);
int (*dma_start)(struct mmci_host *host, unsigned int *datactrl);
+   void (*dma_finalize)(struct mmci_host *host, struct mmc_data *data);
 };
 
 struct mmci_host {
@@ -340,3 +341,4 @@ void mmci_dmae_get_next_data(struct mmci_host *host, struct 
mmc_data *data);
 int mmci_dmae_setup(struct mmci_host *host);
 void mmci_dmae_release(struct mmci_host *host);
 int mmci_dmae_start(struct mmci_host *host, unsigned int *datactrl);
+void mmci_dmae_finalize(struct mmci_host *host, struct mmc_data *data);
diff --git a/drivers/mmc/host/mmci_qcom_dml.c b/drivers/mmc/host/mmci_qcom_dml.c
index e6267ad..ba7e311 100644
--- a/drivers/mmc/host/mmci_qcom_dml.c
+++ b/drivers/mmc/host/mmci_qcom_dml.c
@@ -188,6 +188,7 @@ static struct mmci_host_ops qcom_variant_ops = {
.dma_setup = qcom_dma_setup,
.dma_release = mmci_dmae_release,
.dma_start = mmci_dmae_start,
+   .dma_finalize = mmci_dmae_finalize,
 };
 
 void qcom_variant_init(struct mmci_host *host)
-- 
2.7.4



[PATCH 07/14] mmc: mmci: add prepare/unprepare_data callbacks

2018-08-01 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds prepare/unprepare callbacks to mmci_host_ops.
Like this mmci_pre/post_request can be generic, mmci_prepare_data
and mmci_unprepare_data provide common next_cookie management.

Signed-off-by: Ludovic Barre 
---
 drivers/mmc/host/mmci.c  | 118 +++
 drivers/mmc/host/mmci.h  |  10 
 drivers/mmc/host/mmci_qcom_dml.c |   2 +
 3 files changed, 93 insertions(+), 37 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index e4d80f1..345aa2e 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -58,6 +58,7 @@ static struct variant_data variant_arm = {
.mmcimask1  = true,
.start_err  = MCI_STARTBITERR,
.opendrain  = MCI_ROD,
+   .init   = mmci_variant_init,
 };
 
 static struct variant_data variant_arm_extended_fifo = {
@@ -69,6 +70,7 @@ static struct variant_data variant_arm_extended_fifo = {
.mmcimask1  = true,
.start_err  = MCI_STARTBITERR,
.opendrain  = MCI_ROD,
+   .init   = mmci_variant_init,
 };
 
 static struct variant_data variant_arm_extended_fifo_hwfc = {
@@ -81,6 +83,7 @@ static struct variant_data variant_arm_extended_fifo_hwfc = {
.mmcimask1  = true,
.start_err  = MCI_STARTBITERR,
.opendrain  = MCI_ROD,
+   .init   = mmci_variant_init,
 };
 
 static struct variant_data variant_u300 = {
@@ -99,6 +102,7 @@ static struct variant_data variant_u300 = {
.mmcimask1  = true,
.start_err  = MCI_STARTBITERR,
.opendrain  = MCI_OD,
+   .init   = mmci_variant_init,
 };
 
 static struct variant_data variant_nomadik = {
@@ -118,6 +122,7 @@ static struct variant_data variant_nomadik = {
.mmcimask1  = true,
.start_err  = MCI_STARTBITERR,
.opendrain  = MCI_OD,
+   .init   = mmci_variant_init,
 };
 
 static struct variant_data variant_ux500 = {
@@ -143,6 +148,7 @@ static struct variant_data variant_ux500 = {
.mmcimask1  = true,
.start_err  = MCI_STARTBITERR,
.opendrain  = MCI_OD,
+   .init   = mmci_variant_init,
 };
 
 static struct variant_data variant_ux500v2 = {
@@ -170,6 +176,7 @@ static struct variant_data variant_ux500v2 = {
.mmcimask1  = true,
.start_err  = MCI_STARTBITERR,
.opendrain  = MCI_OD,
+   .init   = mmci_variant_init,
 };
 
 static struct variant_data variant_stm32 = {
@@ -187,6 +194,7 @@ static struct variant_data variant_stm32 = {
.f_max  = 4800,
.pwrreg_clkgate = true,
.pwrreg_nopower = true,
+   .init   = mmci_variant_init,
 };
 
 static struct variant_data variant_qcom = {
@@ -357,6 +365,31 @@ static void mmci_set_clkreg(struct mmci_host *host, 
unsigned int desired)
mmci_write_clkreg(host, clk);
 }
 
+int mmci_prepare_data(struct mmci_host *host, struct mmc_data *data, bool next)
+{
+   int err;
+
+   if (!host->ops || !host->ops->prepare_data)
+   return 0;
+
+   err = host->ops->prepare_data(host, data, next);
+
+   if (next && !err)
+   data->host_cookie = ++host->next_cookie < 0 ?
+   1 : host->next_cookie;
+
+   return err;
+}
+
+void mmci_unprepare_data(struct mmci_host *host, struct mmc_data *data,
+int err)
+{
+   if (host->ops && host->ops->unprepare_data)
+   host->ops->unprepare_data(host, data, err);
+
+   data->host_cookie = 0;
+}
+
 static void
 mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
 {
@@ -588,9 +621,9 @@ static void mmci_dma_finalize(struct mmci_host *host, 
struct mmc_data *data)
 }
 
 /* prepares DMA channel and DMA descriptor, returns non-zero on failure */
-static int __mmci_dma_prep_data(struct mmci_host *host, struct mmc_data *data,
-   struct dma_chan **dma_chan,
-   struct dma_async_tx_descriptor **dma_desc)
+static int __mmci_dmae_prep_data(struct mmci_host *host, struct mmc_data *data,
+struct dma_chan **dma_chan,
+struct dma_async_tx_descriptor **dma_desc)
 {
struct dmaengine_priv *dmae = host->dma_priv;
struct variant_data *variant = host->variant;
@@ -651,22 +684,21 @@ static int __mmci_dma_prep_data(struct mmci_host *host, 
struct mmc_data *data,
return -ENOMEM;
 }
 
-static inline int mmci_dma_prepare_data(struct mmci_host *

[PATCH 09/14] mmc: mmci: modify dma_setup callback

2018-08-01 Thread Ludovic Barre
From: Ludovic Barre 

This patch creates a generic mmci_dma_setup which calls
dma_setup callback and manages common next_cookie.
This patch is needed for sdmmc variant which has a different
dma settings.

Signed-off-by: Ludovic Barre 
---
 drivers/mmc/host/mmci.c  | 25 +
 drivers/mmc/host/mmci.h  |  1 +
 drivers/mmc/host/mmci_qcom_dml.c |  2 ++
 3 files changed, 16 insertions(+), 12 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 0193da6..ae47d08 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -398,6 +398,17 @@ void mmci_get_next_data(struct mmci_host *host, struct 
mmc_data *data)
host->ops->get_next_data(host, data);
 }
 
+int mmci_dma_setup(struct mmci_host *host)
+{
+   if (!host->ops || !host->ops->dma_setup)
+   return 0;
+
+   /* initialize pre request cookie */
+   host->next_cookie = 1;
+
+   return host->ops->dma_setup(host);
+}
+
 static void
 mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
 {
@@ -472,7 +483,7 @@ struct dmaengine_priv {
 
 #define __dmae_inprogress(dmae) ((dmae)->dma_in_progress)
 
-static int mmci_dma_setup(struct mmci_host *host)
+int mmci_dmae_setup(struct mmci_host *host)
 {
const char *rxname, *txname;
struct dmaengine_priv *dmae;
@@ -488,9 +499,6 @@ static int mmci_dma_setup(struct mmci_host *host)
dmae->dma_tx_channel = dma_request_slave_channel(mmc_dev(host->mmc),
 "tx");
 
-   /* initialize pre request cookie */
-   host->next_cookie = 1;
-
/*
 * If only an RX channel is specified, the driver will
 * attempt to use it bidirectionally, however if it is
@@ -531,9 +539,6 @@ static int mmci_dma_setup(struct mmci_host *host)
host->mmc->max_seg_size = max_seg_size;
}
 
-   if (host->ops && host->ops->dma_setup)
-   return host->ops->dma_setup(host);
-
return 0;
 }
 
@@ -793,14 +798,10 @@ static struct mmci_host_ops mmci_variant_ops = {
.prepare_data = mmci_dmae_prepare_data,
.unprepare_data = mmci_dmae_unprepare_data,
.get_next_data = mmci_dmae_get_next_data,
+   .dma_setup = mmci_dmae_setup,
 };
 #else
 /* Blank functions if the DMA engine is not available */
-static inline int mmci_dma_setup(struct mmci_host *host)
-{
-   return 0;
-}
-
 static inline void mmci_dma_release(struct mmci_host *host)
 {
 }
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index bb1e4ba..e1b389c 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -335,3 +335,4 @@ int mmci_dmae_prepare_data(struct mmci_host *host, struct 
mmc_data *data,
 void mmci_dmae_unprepare_data(struct mmci_host *host,
  struct mmc_data *data, int err);
 void mmci_dmae_get_next_data(struct mmci_host *host, struct mmc_data *data);
+int mmci_dmae_setup(struct mmci_host *host);
diff --git a/drivers/mmc/host/mmci_qcom_dml.c b/drivers/mmc/host/mmci_qcom_dml.c
index e4c505a..47abbdd 100644
--- a/drivers/mmc/host/mmci_qcom_dml.c
+++ b/drivers/mmc/host/mmci_qcom_dml.c
@@ -126,6 +126,8 @@ static int qcom_dma_setup(struct mmci_host *host)
int consumer_id, producer_id;
struct device_node *np = host->mmc->parent->of_node;
 
+   mmci_dmae_setup(host);
+
consumer_id = of_get_dml_pipe_index(np, "tx");
producer_id = of_get_dml_pipe_index(np, "rx");
 
-- 
2.7.4



[PATCH 03/14] mmc: mmci: internalize dma_inprogress into mmci dma functions

2018-08-01 Thread Ludovic Barre
From: Ludovic Barre 

This patch internalizes the dma_inprogress into mmci dma interfaces.
This allows to simplify and prepare the next dma callbacks
for mmci host ops. __dma_inprogress is called in mmci_dma_data_error
and mmci_dma_finalize.

Signed-off-by: Ludovic Barre 
---
 drivers/mmc/host/mmci.c | 16 ++--
 drivers/mmc/host/mmci.h |  4 +---
 2 files changed, 11 insertions(+), 9 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index d8fa178..8144a87 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -497,6 +497,9 @@ static void __mmci_dma_unmap(struct mmci_host *host, struct 
mmc_data *data)
 
 static void mmci_dma_data_error(struct mmci_host *host)
 {
+   if (!__dma_inprogress(host))
+   return;
+
dev_err(mmc_dev(host->mmc), "error during DMA transfer!\n");
dmaengine_terminate_all(host->dma_current);
host->dma_in_progress = false;
@@ -512,6 +515,9 @@ static void mmci_dma_finalize(struct mmci_host *host, 
struct mmc_data *data)
u32 status;
int i;
 
+   if (!__dma_inprogress(dmae))
+   return;
+
/* Wait up to 1ms for the DMA to complete */
for (i = 0; ; i++) {
status = readl(host->base + MMCISTATUS);
@@ -903,8 +909,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
u32 remain, success;
 
/* Terminate the DMA transfer */
-   if (dma_inprogress(host))
-   mmci_dma_data_error(host);
+   mmci_dma_data_error(host);
 
/*
 * Calculate how far we are into the transfer.  Note that
@@ -942,8 +947,8 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
dev_err(mmc_dev(host->mmc), "stray MCI_DATABLOCKEND 
interrupt\n");
 
if (status & MCI_DATAEND || data->error) {
-   if (dma_inprogress(host))
-   mmci_dma_finalize(host, data);
+   mmci_dma_finalize(host, data);
+
mmci_stop_data(host);
 
if (!data->error)
@@ -1050,8 +1055,7 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command 
*cmd,
if ((!sbc && !cmd->data) || cmd->error) {
if (host->data) {
/* Terminate the DMA transfer */
-   if (dma_inprogress(host))
-   mmci_dma_data_error(host);
+   mmci_dma_data_error(host);
 
mmci_stop_data(host);
}
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 696a066..f1ec066 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -332,9 +332,7 @@ struct mmci_host {
struct mmci_host_next   next_data;
booldma_in_progress;
 
-#define dma_inprogress(host)   ((host)->dma_in_progress)
-#else
-#define dma_inprogress(host)   (0)
+#define __dma_inprogress(host) ((host)->dma_in_progress)
 #endif
 };
 
-- 
2.7.4



[PATCH 06/14] mmc: mmci: merge prepare data functions

2018-08-01 Thread Ludovic Barre
From: Ludovic Barre 

This patch merges the prepare data functions.
This allows to define a single access to prepare data service.
This prepares integration for mmci host ops.

Signed-off-by: Ludovic Barre 
---
 drivers/mmc/host/mmci.c | 22 +-
 1 file changed, 9 insertions(+), 13 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 5646c2e6..e4d80f1 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -651,11 +651,16 @@ static int __mmci_dma_prep_data(struct mmci_host *host, 
struct mmc_data *data,
return -ENOMEM;
 }
 
-static inline int mmci_dma_prep_data(struct mmci_host *host,
-struct mmc_data *data)
+static inline int mmci_dma_prepare_data(struct mmci_host *host,
+   struct mmc_data *data,
+   bool next)
 {
struct dmaengine_priv *dmae = host->dma_priv;
+   struct dmaengine_next *nd = &dmae->next_data;
 
+   if (next)
+   return __mmci_dma_prep_data(host, data, &nd->dma_chan,
+   &nd->dma_desc);
/* Check if next job is already prepared. */
if (dmae->dma_current && dmae->dma_desc_current)
return 0;
@@ -665,22 +670,13 @@ static inline int mmci_dma_prep_data(struct mmci_host 
*host,
&dmae->dma_desc_current);
 }
 
-static inline int mmci_dma_prep_next(struct mmci_host *host,
-struct mmc_data *data)
-{
-   struct dmaengine_priv *dmae = host->dma_priv;
-   struct dmaengine_next *nd = &dmae->next_data;
-
-   return __mmci_dma_prep_data(host, data, &nd->dma_chan, &nd->dma_desc);
-}
-
 static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
 {
struct dmaengine_priv *dmae = host->dma_priv;
struct mmc_data *data = host->data;
int ret;
 
-   ret = mmci_dma_prep_data(host, host->data);
+   ret = mmci_dma_prepare_data(host, host->data, false);
if (ret)
return ret;
 
@@ -737,7 +733,7 @@ static void mmci_pre_request(struct mmc_host *mmc, struct 
mmc_request *mrq)
if (mmci_validate_data(host, data))
return;
 
-   if (!mmci_dma_prep_next(host, data))
+   if (!mmci_dma_prepare_data(host, data, true))
data->host_cookie = ++host->next_cookie < 0 ?
1 : host->next_cookie;
 }
-- 
2.7.4



[PATCH 02/14] mmc: mmci: internalize dma map/unmap into mmci dma functions

2018-08-01 Thread Ludovic Barre
From: Ludovic Barre 

This patch internalizes the management of dma map/unmap into
mmci dma interfaces. This allows to simplify and prepare the next dma
callbacks for mmci host ops.
mmci_dma_unmap was called in mmci_data_irq & mmci_cmd_irq functions
and can be integrated in mmci_dma_data_error.

Signed-off-by: Ludovic Barre 
---
 drivers/mmc/host/mmci.c | 44 +++-
 1 file changed, 19 insertions(+), 25 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 1841d250..d8fa178 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -482,17 +482,7 @@ static inline void mmci_dma_release(struct mmci_host *host)
host->dma_rx_channel = host->dma_tx_channel = NULL;
 }
 
-static void mmci_dma_data_error(struct mmci_host *host)
-{
-   dev_err(mmc_dev(host->mmc), "error during DMA transfer!\n");
-   dmaengine_terminate_all(host->dma_current);
-   host->dma_in_progress = false;
-   host->dma_current = NULL;
-   host->dma_desc_current = NULL;
-   host->data->host_cookie = 0;
-}
-
-static void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data)
+static void __mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data)
 {
struct dma_chan *chan;
 
@@ -505,6 +495,18 @@ static void mmci_dma_unmap(struct mmci_host *host, struct 
mmc_data *data)
 mmc_get_dma_dir(data));
 }
 
+static void mmci_dma_data_error(struct mmci_host *host)
+{
+   dev_err(mmc_dev(host->mmc), "error during DMA transfer!\n");
+   dmaengine_terminate_all(host->dma_current);
+   host->dma_in_progress = false;
+   host->dma_current = NULL;
+   host->dma_desc_current = NULL;
+   host->data->host_cookie = 0;
+
+   __mmci_dma_unmap(host, host->data);
+}
+
 static void mmci_dma_finalize(struct mmci_host *host, struct mmc_data *data)
 {
u32 status;
@@ -528,11 +530,10 @@ static void mmci_dma_finalize(struct mmci_host *host, 
struct mmc_data *data)
mmci_dma_data_error(host);
if (!data->error)
data->error = -EIO;
+   } else if (!data->host_cookie) {
+   __mmci_dma_unmap(host, data);
}
 
-   if (!data->host_cookie)
-   mmci_dma_unmap(host, data);
-
/*
 * Use of DMA with scatter-gather is impossible.
 * Give up with DMA and switch back to PIO mode.
@@ -704,7 +705,7 @@ static void mmci_post_request(struct mmc_host *mmc, struct 
mmc_request *mrq,
if (!data || !data->host_cookie)
return;
 
-   mmci_dma_unmap(host, data);
+   __mmci_dma_unmap(host, data);
 
if (err) {
struct mmci_host_next *next = &host->next_data;
@@ -742,10 +743,6 @@ static inline void mmci_dma_release(struct mmci_host *host)
 {
 }
 
-static inline void mmci_dma_unmap(struct mmci_host *host, struct mmc_data 
*data)
-{
-}
-
 static inline void mmci_dma_finalize(struct mmci_host *host,
 struct mmc_data *data)
 {
@@ -906,10 +903,8 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data 
*data,
u32 remain, success;
 
/* Terminate the DMA transfer */
-   if (dma_inprogress(host)) {
+   if (dma_inprogress(host))
mmci_dma_data_error(host);
-   mmci_dma_unmap(host, data);
-   }
 
/*
 * Calculate how far we are into the transfer.  Note that
@@ -1055,10 +1050,9 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command 
*cmd,
if ((!sbc && !cmd->data) || cmd->error) {
if (host->data) {
/* Terminate the DMA transfer */
-   if (dma_inprogress(host)) {
+   if (dma_inprogress(host))
mmci_dma_data_error(host);
-   mmci_dma_unmap(host, host->data);
-   }
+
mmci_stop_data(host);
}
mmci_request_end(host, host->mrq);
-- 
2.7.4



[PATCH 13/14] mmc: mmci: add dma_error callback

2018-08-01 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds dma_error callback at mmci_host_ops
to allow to call specific variant.

Signed-off-by: Ludovic Barre 
---
 drivers/mmc/host/mmci.c  | 20 +++-
 drivers/mmc/host/mmci.h  |  2 ++
 drivers/mmc/host/mmci_qcom_dml.c |  1 +
 3 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index b124a73..d5ca93e 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -453,6 +453,12 @@ void mmci_dma_finalize(struct mmci_host *host, struct 
mmc_data *data)
host->ops->dma_finalize(host, data);
 }
 
+void mmci_dma_error(struct mmci_host *host)
+{
+   if (host->ops && host->ops->dma_error)
+   host->ops->dma_error(host);
+}
+
 static void
 mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
 {
@@ -615,7 +621,7 @@ static void __mmci_dmae_unmap(struct mmci_host *host, 
struct mmc_data *data)
 mmc_get_dma_dir(data));
 }
 
-static void mmci_dma_data_error(struct mmci_host *host)
+void mmci_dmae_error(struct mmci_host *host)
 {
struct dmaengine_priv *dmae = host->dma_priv;
 
@@ -656,7 +662,7 @@ void mmci_dmae_finalize(struct mmci_host *host, struct 
mmc_data *data)
 * contiguous buffers.  On TX, we'll get a FIFO underrun error.
 */
if (status & MCI_RXDATAAVLBLMASK) {
-   mmci_dma_data_error(host);
+   mmci_dma_error(host);
if (!data->error)
data->error = -EIO;
} else if (!data->host_cookie) {
@@ -827,13 +833,9 @@ static struct mmci_host_ops mmci_variant_ops = {
.dma_release = mmci_dmae_release,
.dma_start = mmci_dmae_start,
.dma_finalize = mmci_dmae_finalize,
+   .dma_error = mmci_dmae_error,
 };
 #else
-/* Blank functions if the DMA engine is not available */
-static inline void mmci_dma_data_error(struct mmci_host *host)
-{
-}
-
 static struct mmci_host_ops mmci_variant_ops = {};
 #endif
 
@@ -1011,7 +1013,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data 
*data,
u32 remain, success;
 
/* Terminate the DMA transfer */
-   mmci_dma_data_error(host);
+   mmci_dma_error(host);
 
/*
 * Calculate how far we are into the transfer.  Note that
@@ -1157,7 +1159,7 @@ mmci_cmd_irq(struct mmci_host *host, struct mmc_command 
*cmd,
if ((!sbc && !cmd->data) || cmd->error) {
if (host->data) {
/* Terminate the DMA transfer */
-   mmci_dma_data_error(host);
+   mmci_dma_error(host);
 
mmci_stop_data(host);
}
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 3f482d5..0a4811d 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -282,6 +282,7 @@ struct mmci_host_ops {
void (*dma_release)(struct mmci_host *host);
int (*dma_start)(struct mmci_host *host, unsigned int *datactrl);
void (*dma_finalize)(struct mmci_host *host, struct mmc_data *data);
+   void (*dma_error)(struct mmci_host *host);
 };
 
 struct mmci_host {
@@ -342,3 +343,4 @@ int mmci_dmae_setup(struct mmci_host *host);
 void mmci_dmae_release(struct mmci_host *host);
 int mmci_dmae_start(struct mmci_host *host, unsigned int *datactrl);
 void mmci_dmae_finalize(struct mmci_host *host, struct mmc_data *data);
+void mmci_dmae_error(struct mmci_host *host);
diff --git a/drivers/mmc/host/mmci_qcom_dml.c b/drivers/mmc/host/mmci_qcom_dml.c
index ba7e311..80701b4 100644
--- a/drivers/mmc/host/mmci_qcom_dml.c
+++ b/drivers/mmc/host/mmci_qcom_dml.c
@@ -189,6 +189,7 @@ static struct mmci_host_ops qcom_variant_ops = {
.dma_release = mmci_dmae_release,
.dma_start = mmci_dmae_start,
.dma_finalize = mmci_dmae_finalize,
+   .dma_error = mmci_dmae_error,
 };
 
 void qcom_variant_init(struct mmci_host *host)
-- 
2.7.4



[PATCH 11/14] mmc: mmci: add dma_start callback

2018-08-01 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds dma_start callback to mmci_host_ops.
Create a generic mmci_dma_start function which regroup
common action between variant.

Signed-off-by: Ludovic Barre 
---
 drivers/mmc/host/mmci.c  | 63 +++-
 drivers/mmc/host/mmci.h  |  2 ++
 drivers/mmc/host/mmci_qcom_dml.c |  1 +
 3 files changed, 39 insertions(+), 27 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 177e2e8..642ef19 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -415,6 +415,38 @@ void mmci_dma_release(struct mmci_host *host)
host->ops->dma_release(host);
 }
 
+int mmci_dma_start(struct mmci_host *host, unsigned int datactrl)
+{
+   struct mmc_data *data = host->data;
+   int ret;
+
+   ret = mmci_prepare_data(host, data, false);
+   if (ret)
+   return ret;
+
+   if (!host->ops || !host->ops->dma_start)
+   return -EINVAL;
+
+   /* Okay, go for it. */
+   dev_vdbg(mmc_dev(host->mmc),
+"Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags 
%08x\n",
+data->sg_len, data->blksz, data->blocks, data->flags);
+
+   host->ops->dma_start(host, &datactrl);
+
+   /* Trigger the DMA transfer */
+   mmci_write_datactrlreg(host, datactrl);
+
+   /*
+* Let the MMCI say when the data is ended and it's time
+* to fire next DMA request. When that happens, MMCI will
+* call mmci_data_end()
+*/
+   writel(readl(host->base + MMCIMASK0) | MCI_DATAENDMASK,
+  host->base + MMCIMASK0);
+   return 0;
+}
+
 static void
 mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
 {
@@ -721,20 +753,11 @@ int mmci_dmae_prepare_data(struct mmci_host *host,
&dmae->dma_desc_current);
 }
 
-static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
+int mmci_dmae_start(struct mmci_host *host, unsigned int *datactrl)
 {
struct dmaengine_priv *dmae = host->dma_priv;
struct mmc_data *data = host->data;
-   int ret;
-
-   ret = mmci_prepare_data(host, host->data, false);
-   if (ret)
-   return ret;
 
-   /* Okay, go for it. */
-   dev_vdbg(mmc_dev(host->mmc),
-"Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags 
%08x\n",
-data->sg_len, data->blksz, data->blocks, data->flags);
dmae->dma_in_progress = true;
dmaengine_submit(dmae->dma_desc_current);
dma_async_issue_pending(dmae->dma_current);
@@ -742,18 +765,8 @@ static int mmci_dma_start_data(struct mmci_host *host, 
unsigned int datactrl)
if (host->variant->qcom_dml)
dml_start_xfer(host, data);
 
-   datactrl |= MCI_DPSM_DMAENABLE;
-
-   /* Trigger the DMA transfer */
-   mmci_write_datactrlreg(host, datactrl);
+   *datactrl |= MCI_DPSM_DMAENABLE;
 
-   /*
-* Let the MMCI say when the data is ended and it's time
-* to fire next DMA request. When that happens, MMCI will
-* call mmci_data_end()
-*/
-   writel(readl(host->base + MMCIMASK0) | MCI_DATAENDMASK,
-  host->base + MMCIMASK0);
return 0;
 }
 
@@ -806,6 +819,7 @@ static struct mmci_host_ops mmci_variant_ops = {
.get_next_data = mmci_dmae_get_next_data,
.dma_setup = mmci_dmae_setup,
.dma_release = mmci_dmae_release,
+   .dma_start = mmci_dmae_start,
 };
 #else
 /* Blank functions if the DMA engine is not available */
@@ -818,11 +832,6 @@ static inline void mmci_dma_data_error(struct mmci_host 
*host)
 {
 }
 
-static inline int mmci_dma_start_data(struct mmci_host *host, unsigned int 
datactrl)
-{
-   return -ENOSYS;
-}
-
 static struct mmci_host_ops mmci_variant_ops = {};
 #endif
 
@@ -925,7 +934,7 @@ static void mmci_start_data(struct mmci_host *host, struct 
mmc_data *data)
 * Attempt to use DMA operation mode, if this
 * should fail, fall back to PIO mode
 */
-   if (!mmci_dma_start_data(host, datactrl))
+   if (!mmci_dma_start(host, datactrl))
return;
 
/* IRQ mode, map the SG list for CPU reading/writing */
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index f961f90..3a200a9 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -280,6 +280,7 @@ struct mmci_host_ops {
void (*get_next_data)(struct mmci_host *host, struct mmc_data *data);
int (*dma_setup)(struct mmci_host *host);
void (*dma_release)(struct mmci_host *host);
+   int (*dma_start)(struct mmci_host *host, unsigned int *datactrl);
 };
 
 struct mmci_host {
@@ -338,3 +339,4 @@ void mmci_dmae_unprepare_data(struct mmci_host *host,
 void mmci_dmae_get_next_data(str

[PATCH 14/14] mmc: mmci: add validate_data callback

2018-08-01 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds validate_data callback at mmci_host_ops
to check specific constraints of variant.

Signed-off-by: Ludovic Barre 
---
 drivers/mmc/host/mmci.c | 39 +--
 drivers/mmc/host/mmci.h |  1 +
 2 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index d5ca93e..7ba2f61 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -234,24 +234,6 @@ static int mmci_card_busy(struct mmc_host *mmc)
return busy;
 }
 
-/*
- * Validate mmc prerequisites
- */
-static int mmci_validate_data(struct mmci_host *host,
- struct mmc_data *data)
-{
-   if (!data)
-   return 0;
-
-   if (!is_power_of_2(data->blksz)) {
-   dev_err(mmc_dev(host->mmc),
-   "unsupported block size (%d bytes)\n", data->blksz);
-   return -EINVAL;
-   }
-
-   return 0;
-}
-
 static void mmci_reg_delay(struct mmci_host *host)
 {
/*
@@ -365,6 +347,27 @@ static void mmci_set_clkreg(struct mmci_host *host, 
unsigned int desired)
mmci_write_clkreg(host, clk);
 }
 
+/*
+ * Validate mmc prerequisites
+ */
+static int mmci_validate_data(struct mmci_host *host,
+ struct mmc_data *data)
+{
+   if (!data)
+   return 0;
+
+   if (!is_power_of_2(data->blksz)) {
+   dev_err(mmc_dev(host->mmc),
+   "unsupported block size (%d bytes)\n", data->blksz);
+   return -EINVAL;
+   }
+
+   if (host->ops && host->ops->validate_data)
+   return host->ops->validate_data(host, data);
+
+   return 0;
+}
+
 int mmci_prepare_data(struct mmci_host *host, struct mmc_data *data, bool next)
 {
int err;
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 0a4811d..10b71bf 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -273,6 +273,7 @@ struct variant_data {
 
 /* mmci variant callbacks */
 struct mmci_host_ops {
+   int (*validate_data)(struct mmci_host *host, struct mmc_data *data);
int (*prepare_data)(struct mmci_host *host, struct mmc_data *data,
bool next);
void (*unprepare_data)(struct mmci_host *host, struct mmc_data *data,
-- 
2.7.4



[PATCH 08/14] mmc: mmci: add get_next_data callback

2018-08-01 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds get_next_data callback to mmci_host_ops.
Generic mmci_get_next_data factorizes next_cookie check and
the host ops call.

Signed-off-by: Ludovic Barre 
---
 drivers/mmc/host/mmci.c  | 16 ++--
 drivers/mmc/host/mmci.h  |  2 ++
 drivers/mmc/host/mmci_qcom_dml.c |  1 +
 3 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 345aa2e..0193da6 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -390,6 +390,14 @@ void mmci_unprepare_data(struct mmci_host *host, struct 
mmc_data *data,
data->host_cookie = 0;
 }
 
+void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data)
+{
+   WARN_ON(data->host_cookie && data->host_cookie != host->next_cookie);
+
+   if (host->ops && host->ops->get_next_data)
+   host->ops->get_next_data(host, data);
+}
+
 static void
 mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
 {
@@ -738,12 +746,11 @@ static int mmci_dma_start_data(struct mmci_host *host, 
unsigned int datactrl)
return 0;
 }
 
-static void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data)
+void mmci_dmae_get_next_data(struct mmci_host *host, struct mmc_data *data)
 {
struct dmaengine_priv *dmae = host->dma_priv;
struct dmaengine_next *next = &dmae->next_data;
 
-   WARN_ON(data->host_cookie && data->host_cookie != host->next_cookie);
WARN_ON(!data->host_cookie && (next->dma_desc || next->dma_chan));
 
dmae->dma_desc_current = next->dma_desc;
@@ -785,13 +792,10 @@ void mmci_dmae_unprepare_data(struct mmci_host *host,
 static struct mmci_host_ops mmci_variant_ops = {
.prepare_data = mmci_dmae_prepare_data,
.unprepare_data = mmci_dmae_unprepare_data,
+   .get_next_data = mmci_dmae_get_next_data,
 };
 #else
 /* Blank functions if the DMA engine is not available */
-static void mmci_get_next_data(struct mmci_host *host, struct mmc_data *data)
-{
-}
-
 static inline int mmci_dma_setup(struct mmci_host *host)
 {
return 0;
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index fa2702b..bb1e4ba 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -277,6 +277,7 @@ struct mmci_host_ops {
bool next);
void (*unprepare_data)(struct mmci_host *host, struct mmc_data *data,
   int err);
+   void (*get_next_data)(struct mmci_host *host, struct mmc_data *data);
int (*dma_setup)(struct mmci_host *host);
 };
 
@@ -333,3 +334,4 @@ int mmci_dmae_prepare_data(struct mmci_host *host, struct 
mmc_data *data,
   bool next);
 void mmci_dmae_unprepare_data(struct mmci_host *host,
  struct mmc_data *data, int err);
+void mmci_dmae_get_next_data(struct mmci_host *host, struct mmc_data *data);
diff --git a/drivers/mmc/host/mmci_qcom_dml.c b/drivers/mmc/host/mmci_qcom_dml.c
index d534fa1..e4c505a 100644
--- a/drivers/mmc/host/mmci_qcom_dml.c
+++ b/drivers/mmc/host/mmci_qcom_dml.c
@@ -182,6 +182,7 @@ static int qcom_dma_setup(struct mmci_host *host)
 static struct mmci_host_ops qcom_variant_ops = {
.prepare_data = mmci_dmae_prepare_data,
.unprepare_data = mmci_dmae_unprepare_data,
+   .get_next_data = mmci_dmae_get_next_data,
.dma_setup = qcom_dma_setup,
 };
 
-- 
2.7.4



[PATCH 01/14] mmc: mmci: fix qcom dma issue during mmci init with new dma_setup callback

2018-08-01 Thread Ludovic Barre
From: Ludovic Barre 

This patch fixes qcom dma issue during mmci init.
Like init callback of qcom variant is not set, the qcom dma
is not correctly initialized and fail while dma transfer
("buggy DMA detected. Taking evasive action").

Signed-off-by: Ludovic Barre 
---
 drivers/mmc/host/mmci.c | 1 +
 drivers/mmc/host/mmci.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 71e9336..1841d250 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -208,6 +208,7 @@ static struct variant_data variant_qcom = {
.mmcimask1  = true,
.start_err  = MCI_STARTBITERR,
.opendrain  = MCI_ROD,
+   .init   = qcom_variant_init,
 };
 
 /* Busy detection for the ST Micro variant */
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 517591d..696a066 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -338,3 +338,4 @@ struct mmci_host {
 #endif
 };
 
+void qcom_variant_init(struct mmci_host *host);
-- 
2.7.4



[PATCH 00/14] mmc: mmci: prepare dma callbacks with mmci_host_ops

2018-08-01 Thread Ludovic Barre
From: Ludovic Barre 

This patch series prepares and adds callbacks for dma transfert at
mmci_host_ops. This series is composed of 3 parts:
-Internalize specific needs of legacy dmaengine.
-Create and setup dma_priv pointer
-Create generic callbacks  which share some features
(like cookie...) and call specific needs

This patch series must be applied on top of 
"mmc: mmci: Add and implement a ->dma_setup() callback for qcom dml"

Ludovic Barre (14):
  mmc: mmci: fix qcom dma issue during mmci init with new dma_setup
callback
  mmc: mmci: internalize dma map/unmap into mmci dma functions
  mmc: mmci: internalize dma_inprogress into mmci dma functions
  mmc: mmci: introduce dma_priv pointer to mmci_host
  mmc: mmci: move mmci next cookie to mci host
  mmc: mmci: merge prepare data functions
  mmc: mmci: add prepare/unprepare_data callbacks
  mmc: mmci: add get_next_data callback
  mmc: mmci: modify dma_setup callback
  mmc: mmci: add dma_release callback
  mmc: mmci: add dma_start callback
  mmc: mmci: add dma_finalize callback
  mmc: mmci: add dma_error callback
  mmc: mmci: add validate_data callback

 drivers/mmc/host/mmci.c  | 458 ---
 drivers/mmc/host/mmci.h  |  45 ++--
 drivers/mmc/host/mmci_qcom_dml.c |  15 +-
 3 files changed, 322 insertions(+), 196 deletions(-)

-- 
2.7.4



[PATCH 05/14] mmc: mmci: move mmci next cookie to mci host

2018-08-01 Thread Ludovic Barre
From: Ludovic Barre 

This patch moves next cookie to mmci host structure to
share same cookie management between all variants.

Signed-off-by: Ludovic Barre 
---
 drivers/mmc/host/mmci.c | 10 --
 drivers/mmc/host/mmci.h |  2 ++
 2 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index bdc48c3..5646c2e6 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -418,7 +418,6 @@ static void mmci_init_sg(struct mmci_host *host, struct 
mmc_data *data)
 struct dmaengine_next {
struct dma_async_tx_descriptor *dma_desc;
struct dma_chan *dma_chan;
-   s32 cookie;
 };
 
 struct dmaengine_priv {
@@ -449,7 +448,7 @@ static int mmci_dma_setup(struct mmci_host *host)
 "tx");
 
/* initialize pre request cookie */
-   dmae->next_data.cookie = 1;
+   host->next_cookie = 1;
 
/*
 * If only an RX channel is specified, the driver will
@@ -716,7 +715,7 @@ static void mmci_get_next_data(struct mmci_host *host, 
struct mmc_data *data)
struct dmaengine_priv *dmae = host->dma_priv;
struct dmaengine_next *next = &dmae->next_data;
 
-   WARN_ON(data->host_cookie && data->host_cookie != next->cookie);
+   WARN_ON(data->host_cookie && data->host_cookie != host->next_cookie);
WARN_ON(!data->host_cookie && (next->dma_desc || next->dma_chan));
 
dmae->dma_desc_current = next->dma_desc;
@@ -728,9 +727,7 @@ static void mmci_get_next_data(struct mmci_host *host, 
struct mmc_data *data)
 static void mmci_pre_request(struct mmc_host *mmc, struct mmc_request *mrq)
 {
struct mmci_host *host = mmc_priv(mmc);
-   struct dmaengine_priv *dmae = host->dma_priv;
struct mmc_data *data = mrq->data;
-   struct dmaengine_next *nd = &dmae->next_data;
 
if (!data)
return;
@@ -741,7 +738,8 @@ static void mmci_pre_request(struct mmc_host *mmc, struct 
mmc_request *mrq)
return;
 
if (!mmci_dma_prep_next(host, data))
-   data->host_cookie = ++nd->cookie < 0 ? 1 : nd->cookie;
+   data->host_cookie = ++host->next_cookie < 0 ?
+   1 : host->next_cookie;
 }
 
 static void mmci_post_request(struct mmc_host *mmc, struct mmc_request *mrq,
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 260a1de..d2ec4fd 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -318,6 +318,8 @@ struct mmci_host {
int (*get_rx_fifocnt)(struct mmci_host *h, u32 status, int remain);
 
void*dma_priv;
+
+   s32 next_cookie;
 };
 
 void qcom_variant_init(struct mmci_host *host);
-- 
2.7.4



Re: [PATCH 01/14] mmc: mmci: fix qcom dma issue during mmci init with new dma_setup callback

2018-08-01 Thread Ludovic BARRE




On 08/01/2018 12:08 PM, Ulf Hansson wrote:

Anyway, we can just drop this patch from your series as I amended the
patch causing the problem.

I will continue to review the rest.


yes, I sent to early. (sorry)

BR
Ludo


Re: [PATCH 02/19] mmc: mmci: merge qcom dml feature into mmci dma

2018-07-11 Thread Ludovic BARRE




On 07/05/2018 05:26 PM, Ulf Hansson wrote:

On 12 June 2018 at 15:14, Ludovic Barre  wrote:

From: Ludovic Barre 

This patch integrates qcom dml feature into mmci_dma file.
Qualcomm Data Mover lite/local is already a variant of mmci dmaengine.

Signed-off-by: Ludovic Barre 
---
  drivers/mmc/host/Makefile|   1 -
  drivers/mmc/host/mmci.c  |   1 -
  drivers/mmc/host/mmci.h  |  35 
  drivers/mmc/host/mmci_dma.c  | 135 -
  drivers/mmc/host/mmci_qcom_dml.c | 177 ---
  drivers/mmc/host/mmci_qcom_dml.h |  31 ---
  6 files changed, 169 insertions(+), 211 deletions(-)
  delete mode 100644 drivers/mmc/host/mmci_qcom_dml.c
  delete mode 100644 drivers/mmc/host/mmci_qcom_dml.h


No, this is not the way to go. Instead I I think there are two options.

1) Keep mmci_qcom_dml.c|h and thus add new files for the stm32 dma variant.

2) Start by renaming mmci_qcom_dml.* to mmc_dma.* and then in the next
step add the code for stm32 dma into the renamed files.

I guess if there is some overlap in functionality, 2) may be best as
it could easier avoid open coding. However, I am fine with whatever
option and I expect that you knows what is best.


After patch 01 & 05 comments:
I will try to define a mmci_ops which contain some functions pointer
called by mmci.c (core).
A variant defines its mmci_ops.
where do you define the specific function:
-in a single file, mmci-ops.c or other (for the name, I'm not inspirated)
-or in specific file for each variant mmci-qcom.c or mmci-stm32.c

following the comment (above), I think we define a single file?



Kind regards
Uffe



diff --git a/drivers/mmc/host/Makefile b/drivers/mmc/host/Makefile
index daecaa98..608a020 100644
--- a/drivers/mmc/host/Makefile
+++ b/drivers/mmc/host/Makefile
@@ -5,7 +5,6 @@

  obj-$(CONFIG_MMC_ARMMMCI) += armmmci.o
  armmmci-y := mmci.o mmci_dma.o
-armmmci-$(CONFIG_MMC_QCOM_DML) += mmci_qcom_dml.o
  obj-$(CONFIG_MMC_PXA)  += pxamci.o
  obj-$(CONFIG_MMC_MXC)  += mxcmmc.o
  obj-$(CONFIG_MMC_MXS)  += mxs-mmc.o
diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 8868be0..7a15afd 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -43,7 +43,6 @@

  #include "mmci.h"
  #include "mmci_dma.h"
-#include "mmci_qcom_dml.h"

  #define DRIVER_NAME "mmci-pl18x"

diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index a73bb98..f7cba35 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -194,6 +194,41 @@

  #define MMCI_PINCTRL_STATE_OPENDRAIN "opendrain"

+/* QCOM DML Registers */
+#define DML_CONFIG 0x00
+#define PRODUCER_CRCI_MSK  GENMASK(1, 0)
+#define PRODUCER_CRCI_DISABLE  0
+#define PRODUCER_CRCI_X_SELBIT(0)
+#define PRODUCER_CRCI_Y_SELBIT(1)
+#define CONSUMER_CRCI_MSK  GENMASK(3, 2)
+#define CONSUMER_CRCI_DISABLE  0
+#define CONSUMER_CRCI_X_SELBIT(2)
+#define CONSUMER_CRCI_Y_SELBIT(3)
+#define PRODUCER_TRANS_END_EN  BIT(4)
+#define BYPASS BIT(16)
+#define DIRECT_MODEBIT(17)
+#define INFINITE_CONS_TRANSBIT(18)
+
+#define DML_SW_RESET   0x08
+#define DML_PRODUCER_START 0x0c
+#define DML_CONSUMER_START 0x10
+#define DML_PRODUCER_PIPE_LOGICAL_SIZE 0x14
+#define DML_CONSUMER_PIPE_LOGICAL_SIZE 0x18
+#define DML_PIPE_ID0x1c
+#define PRODUCER_PIPE_ID_SHFT  0
+#define PRODUCER_PIPE_ID_MSK   GENMASK(4, 0)
+#define CONSUMER_PIPE_ID_SHFT  16
+#define CONSUMER_PIPE_ID_MSK   GENMASK(20, 16)
+
+#define DML_PRODUCER_BAM_BLOCK_SIZE0x24
+#define DML_PRODUCER_BAM_TRANS_SIZE0x28
+
+/* other definitions */
+#define PRODUCER_PIPE_LOGICAL_SIZE 4096
+#define CONSUMER_PIPE_LOGICAL_SIZE 4096
+
+#define DML_OFFSET 0x800
+
  struct clk;
  struct dma_chan;

diff --git a/drivers/mmc/host/mmci_dma.c b/drivers/mmc/host/mmci_dma.c
index 98a542d..dd7dae5 100644
--- a/drivers/mmc/host/mmci_dma.c
+++ b/drivers/mmc/host/mmci_dma.c
@@ -8,11 +8,11 @@
  #include 
  #include 
  #include 
+#include 
  #include 

  #include "mmci.h"
  #include "mmci_dma.h"
-#include "mmci_qcom_dml.h"

  int mmci_dma_setup(struct mmci_host *host)
  {
@@ -101,6 +101,139 @@ struct dmaengine_priv {

  #define dma_inprogress(dmae) ((dmae)->dma_in_progress)

+#ifdef CONFIG_MMC_QCOM_DML
+void dml_start_xfer(struct mmci_host *host, struct mmc_data *data)
+{
+   u32 config;
+   void __iomem *base = host->base + DML_OFFSET;
+
+   if (data->flags & MMC_DATA_READ) {
+   /* Read operation: configure DML for producer operation */
+   /* Set producer CRCI-x and disable consumer CRCI */
+ 

Re: [PATCH 01/19] mmc: mmci: regroup and define dma operations

2018-07-12 Thread Ludovic BARRE




On 07/11/2018 02:16 PM, Ulf Hansson wrote:

On 11 July 2018 at 11:41, Ludovic BARRE  wrote:



On 07/05/2018 05:17 PM, Ulf Hansson wrote:


On 12 June 2018 at 15:14, Ludovic Barre  wrote:


From: Ludovic Barre 

Prepare mmci driver to manage dma interface by new property.
This patch defines and regroups dma operations for mmci drivers.
mmci_dma_XX prototypes are added to call member of mmci_dma_ops
if not null. Based on legacy need, a mmci dma interface has been
defined with:
-mmci_dma_setup
-mmci_dma_release
-mmci_dma_pre_req
-mmci_dma_start
-mmci_dma_finalize
-mmci_dma_post_req
-mmci_dma_error
-mmci_dma_get_next_data



As I suggested for one of the other patches, I would rather turn core
mmci functions into library functions, which can be either invoked
from variant callbacks or assigned directly to them.

In other words, I would leave the functions that you move in this
patch to stay in mmci.c. Although some needs to be re-factored and we
also needs to make some of them available to be called from another
file, hence the functions needs to be shared via mmci.h rather than
being declared static.



In previous exchange mail "STM32MP1 SDMMC driver review"
we are said:


-dma variant à should fit in Qualcomm implementation, reuse (rename)
mmci_qcom_dml.c file and integrate ST dma in.


Apologize if I may have lead you in a wrong direction, that was not my intent.

However, by looking at $subject patch, your seems to be unnecessarily
shuffling code around. I would like to avoid that.



stm32 sdmmc has an internal dma, no need to use dmaengine API;
So some modifications in mmci (pre/post request, mmci_dma_xx). perhaps
should be done with an ops or not.


Yes.

The Qualcomm variant is also using an internal DMA, hence I thought
there may be something we could re-use, or at least have some new
common ops for.


It's not crystal clear for me.
Do you always agree with a dma ops which allow to address different
DMA transfer:
-with dmaengine API
-sdmmc idma, without dmaengine API
-...


If we can use a mmci ops callback to manage the variant differences,
that would be perfect. That combined with making the existing DMA
functions in mmci.c converted to "library" functions, which the mmci
ops callbacks can call, in order to re-use code.

When that isn't really suitable, we may need to add a "quirk" instead,
which would be specific for that particular variant. Along the lines
of what we already do for variant specifics inside mmci.c.

I think we have to decide on case by case basis, what fits best.

Hope this makes a better explanation. If not, please tell, and I can
take an initial stab and post a patch to show you with code how I mean
to move forward.






Let me take a concrete example on how I would move forward, hopefully
that explains it a bit better. Please see below.

[...]


-/*
- * All the DMA operation mode stuff goes inside this ifdef.
- * This assumes that you have a generic DMA device interface,
- * no custom DMA interfaces are supported.
- */
-#ifdef CONFIG_DMA_ENGINE
-static void mmci_dma_setup(struct mmci_host *host)
-{
-   const char *rxname, *txname;
-   struct variant_data *variant = host->variant;
-
-   host->dma_rx_channel =
dma_request_slave_channel(mmc_dev(host->mmc), "rx");
-   host->dma_tx_channel =
dma_request_slave_channel(mmc_dev(host->mmc), "tx");
-
-   /* initialize pre request cookie */
-   host->next_data.cookie = 1;
-
-   /*
-* If only an RX channel is specified, the driver will
-* attempt to use it bidirectionally, however if it is
-* is specified but cannot be located, DMA will be disabled.
-*/
-   if (host->dma_rx_channel && !host->dma_tx_channel)
-   host->dma_tx_channel = host->dma_rx_channel;
-
-   if (host->dma_rx_channel)
-   rxname = dma_chan_name(host->dma_rx_channel);
-   else
-   rxname = "none";
-
-   if (host->dma_tx_channel)
-   txname = dma_chan_name(host->dma_tx_channel);
-   else
-   txname = "none";
-
-   dev_info(mmc_dev(host->mmc), "DMA channels RX %s, TX %s\n",
-rxname, txname);
-
-   /*
-* Limit the maximum segment size in any SG entry according to
-* the parameters of the DMA engine device.
-*/
-   if (host->dma_tx_channel) {
-   struct device *dev = host->dma_tx_channel->device->dev;
-   unsigned int max_seg_size = dma_get_max_seg_size(dev);
-
-   if (max_seg_size < host->mmc->max_seg_size)
-   host->mmc->max_seg_size = max_seg_size;
-   }
-   if (host->dma_rx_channel) {
-   struct device *dev = host->dma_rx_channel->device->dev;
-   unsigned int max_seg_size = dma_get_max_seg_size(dev);
-
-   

Re: [PATCH 02/19] mmc: mmci: merge qcom dml feature into mmci dma

2018-07-13 Thread Ludovic BARRE




On 07/13/2018 01:17 PM, Ulf Hansson wrote:

On 11 July 2018 at 17:19, Ludovic BARRE  wrote:



On 07/05/2018 05:26 PM, Ulf Hansson wrote:


On 12 June 2018 at 15:14, Ludovic Barre  wrote:


From: Ludovic Barre 

This patch integrates qcom dml feature into mmci_dma file.
Qualcomm Data Mover lite/local is already a variant of mmci dmaengine.

Signed-off-by: Ludovic Barre 
---
   drivers/mmc/host/Makefile|   1 -
   drivers/mmc/host/mmci.c  |   1 -
   drivers/mmc/host/mmci.h  |  35 
   drivers/mmc/host/mmci_dma.c  | 135 -
   drivers/mmc/host/mmci_qcom_dml.c | 177
---
   drivers/mmc/host/mmci_qcom_dml.h |  31 ---
   6 files changed, 169 insertions(+), 211 deletions(-)
   delete mode 100644 drivers/mmc/host/mmci_qcom_dml.c
   delete mode 100644 drivers/mmc/host/mmci_qcom_dml.h



No, this is not the way to go. Instead I I think there are two options.

1) Keep mmci_qcom_dml.c|h and thus add new files for the stm32 dma
variant.

2) Start by renaming mmci_qcom_dml.* to mmc_dma.* and then in the next
step add the code for stm32 dma into the renamed files.

I guess if there is some overlap in functionality, 2) may be best as
it could easier avoid open coding. However, I am fine with whatever
option and I expect that you knows what is best.



After patch 01 & 05 comments:
I will try to define a mmci_ops which contain some functions pointer
called by mmci.c (core).
A variant defines its mmci_ops.
where do you define the specific function:
-in a single file, mmci-ops.c or other (for the name, I'm not inspirated)
-or in specific file for each variant mmci-qcom.c or mmci-stm32.c

following the comment (above), I think we define a single file?


If I understand the question, the problem is how we should assign the
mmc host ops, which corresponds to the probed variant data!?

I took a stub at it and posted two patches which I think you should be
able to build upon. Please have a look.


I review your patch on mmci_host_ops and init, I agree with your series,
I was going in the same direction.
The comment above was on file organization, what do you prefer?
-a single file with: all callback and all mmci_host_ops of each variant
-or each variant in specific file (like sdhci): mmci-qcom.c | 
mmci-stm32.c ...




[...]

Kind regards
Uffe



[PATCH v4 4/7] ARM: stm32: add initial support for STM32MP157

2018-01-16 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds initial support of STM32MP157 microprocessor (MPU)
based on Arm Cortex-A7. New Cortex-A infrastructure (gic, timer,...)
are selected if ARCH_MULTI_V7 is defined.

Signed-off-by: Ludovic Barre 
---
 Documentation/arm/stm32/stm32mp157-overview.rst | 19 +++
 arch/arm/mach-stm32/Kconfig | 11 +++
 arch/arm/mach-stm32/board-dt.c  |  1 +
 3 files changed, 31 insertions(+)
 create mode 100644 Documentation/arm/stm32/stm32mp157-overview.rst

diff --git a/Documentation/arm/stm32/stm32mp157-overview.rst 
b/Documentation/arm/stm32/stm32mp157-overview.rst
new file mode 100644
index 000..62e176d
--- /dev/null
+++ b/Documentation/arm/stm32/stm32mp157-overview.rst
@@ -0,0 +1,19 @@
+STM32MP157 Overview
+===
+
+Introduction
+
+
+The STM32MP157 is a Cortex-A MPU aimed at various applications.
+It features:
+
+- Dual core Cortex-A7 application core
+- 2D/3D image composition with GPU
+- Standard memories interface support
+- Standard connectivity, widely inherited from the STM32 MCU family
+- Comprehensive security support
+
+:Authors:
+
+- Ludovic Barre 
+- Gerald Baeza 
diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig
index fb4b8b8..6b65df1 100644
--- a/arch/arm/mach-stm32/Kconfig
+++ b/arch/arm/mach-stm32/Kconfig
@@ -1,6 +1,9 @@
 menuconfig ARCH_STM32
bool "STMicroelectronics STM32 family" if ARM_SINGLE_ARMV7M || 
ARCH_MULTI_V7
select ARMV7M_SYSTICK if ARM_SINGLE_ARMV7M
+   select HAVE_ARM_ARCH_TIMER if ARCH_MULTI_V7
+   select ARM_GIC if ARCH_MULTI_V7
+   select ARM_PSCI if ARCH_MULTI_V7
select ARCH_HAS_RESET_CONTROLLER
select CLKSRC_STM32
select PINCTRL
@@ -31,4 +34,12 @@ config MACH_STM32H743
 
 endif # ARMv7-M
 
+if ARCH_MULTI_V7
+
+config MACH_STM32MP157
+   bool "STMicroelectronics STM32MP157"
+   default y
+
+endif # ARMv7-A
+
 endif
diff --git a/arch/arm/mach-stm32/board-dt.c b/arch/arm/mach-stm32/board-dt.c
index 4a258eb..d4e58ea 100644
--- a/arch/arm/mach-stm32/board-dt.c
+++ b/arch/arm/mach-stm32/board-dt.c
@@ -12,6 +12,7 @@ static const char *const stm32_compat[] __initconst = {
"st,stm32f469",
"st,stm32f746",
"st,stm32h743",
+   "st,stm32mp157",
NULL
 };
 
-- 
2.7.4



[PATCH v4 1/7] Documentation: arm: stm32: move to rst format

2018-01-16 Thread Ludovic Barre
From: Ludovic Barre 

This patch rewrites stm32 documentation to rst
(ReStructuredText) format.

Signed-off-by: Ludovic Barre 
---
 Documentation/arm/stm32/overview.rst   | 31 +++
 Documentation/arm/stm32/overview.txt   | 33 -
 Documentation/arm/stm32/stm32f429-overview.rst | 26 
 Documentation/arm/stm32/stm32f429-overview.txt | 22 -
 Documentation/arm/stm32/stm32f746-overview.rst | 33 +
 Documentation/arm/stm32/stm32f746-overview.txt | 34 --
 Documentation/arm/stm32/stm32h743-overview.rst | 34 ++
 Documentation/arm/stm32/stm32h743-overview.txt | 30 ---
 8 files changed, 124 insertions(+), 119 deletions(-)
 create mode 100644 Documentation/arm/stm32/overview.rst
 delete mode 100644 Documentation/arm/stm32/overview.txt
 create mode 100644 Documentation/arm/stm32/stm32f429-overview.rst
 delete mode 100644 Documentation/arm/stm32/stm32f429-overview.txt
 create mode 100644 Documentation/arm/stm32/stm32f746-overview.rst
 delete mode 100644 Documentation/arm/stm32/stm32f746-overview.txt
 create mode 100644 Documentation/arm/stm32/stm32h743-overview.rst
 delete mode 100644 Documentation/arm/stm32/stm32h743-overview.txt

diff --git a/Documentation/arm/stm32/overview.rst 
b/Documentation/arm/stm32/overview.rst
new file mode 100644
index 000..6be6059
--- /dev/null
+++ b/Documentation/arm/stm32/overview.rst
@@ -0,0 +1,31 @@
+
+STM32 ARM Linux Overview
+
+
+Introduction
+
+
+The STMicroelectronics family of Cortex-M based MCUs are supported by the
+'STM32' platform of ARM Linux. Currently only the STM32F429 (Cortex-M4)
+and STM32F746 (Cortex-M7) are supported.
+
+Configuration
+-
+
+A generic configuration is provided for STM32 family, and can be used as the
+default by
+make stm32_defconfig
+
+Layout
+--
+
+All the files for multiple machine families are located in the platform code
+contained in arch/arm/mach-stm32
+
+There is a generic board board-dt.c in the mach folder which support
+Flattened Device Tree, which means, it works with any compatible board with
+Device Trees.
+
+:Authors:
+
+Maxime Coquelin 
diff --git a/Documentation/arm/stm32/overview.txt 
b/Documentation/arm/stm32/overview.txt
deleted file mode 100644
index a03b035..000
--- a/Documentation/arm/stm32/overview.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-   STM32 ARM Linux Overview
-   
-
-Introduction
-
-
-  The STMicroelectronics family of Cortex-M based MCUs are supported by the
-  'STM32' platform of ARM Linux. Currently only the STM32F429 (Cortex-M4)
-  and STM32F746 (Cortex-M7) are supported.
-
-
-Configuration
--
-
-  A generic configuration is provided for STM32 family, and can be used as the
-  default by
-   make stm32_defconfig
-
-Layout
---
-
-  All the files for multiple machine families are located in the platform code
-  contained in arch/arm/mach-stm32
-
-  There is a generic board board-dt.c in the mach folder which support
-  Flattened Device Tree, which means, it works with any compatible board with
-  Device Trees.
-
-
-Document Author

-
-  Maxime Coquelin 
diff --git a/Documentation/arm/stm32/stm32f429-overview.rst 
b/Documentation/arm/stm32/stm32f429-overview.rst
new file mode 100644
index 000..18feda9
--- /dev/null
+++ b/Documentation/arm/stm32/stm32f429-overview.rst
@@ -0,0 +1,26 @@
+STM32F429 Overview
+==
+
+Introduction
+
+
+The STM32F429 is a Cortex-M4 MCU aimed at various applications.
+It features:
+
+- ARM Cortex-M4 up to 180MHz with FPU
+- 2MB internal Flash Memory
+- External memory support through FMC controller (PSRAM, SDRAM, NOR, NAND)
+- I2C, SPI, SAI, CAN, USB OTG, Ethernet controllers
+- LCD controller & Camera interface
+- Cryptographic processor
+
+Resources
+-
+
+Datasheet and reference manual are publicly available on ST website 
(STM32F429_).
+
+.. _STM32F429: 
http://www.st.com/web/en/catalog/mmc/FM141/SC1169/SS1577/LN1806?ecmp=stm32f429-439_pron_pr-ces2014_nov2013
+
+:Authors:
+
+Maxime Coquelin 
diff --git a/Documentation/arm/stm32/stm32f429-overview.txt 
b/Documentation/arm/stm32/stm32f429-overview.txt
deleted file mode 100644
index 5206822..000
--- a/Documentation/arm/stm32/stm32f429-overview.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-   STM32F429 Overview
-   ==
-
-  Introduction
-  
-   The STM32F429 is a Cortex-M4 MCU aimed at various applications.
-   It features:
-   - ARM Cortex-M4 up to 180MHz with FPU
-   - 2MB internal Flash Memory
-   - External memory support through FMC controller (PSRAM, SDRAM, NOR, 
NAND)
-   - I2C, SPI, SAI, CAN, USB OTG, Ethernet c

[PATCH v4 6/7] ARM: dts: stm32: add stm32mp157c initial support

2018-01-16 Thread Ludovic Barre
From: Ludovic Barre 

Add stm32mp157c initial support with:
-Dual Cortex-A7
-Arm psci, timer, gic
-Pinctrl
-Uart

Signed-off-by: Ludovic Barre 
---
 arch/arm/boot/dts/stm32mp157-pinctrl.dtsi | 172 ++
 arch/arm/boot/dts/stm32mp157c.dtsi| 194 ++
 2 files changed, 366 insertions(+)
 create mode 100644 arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
 create mode 100644 arch/arm/boot/dts/stm32mp157c.dtsi

diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi 
b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
new file mode 100644
index 000..440276a
--- /dev/null
+++ b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
@@ -0,0 +1,172 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Author: Ludovic Barre  for STMicroelectronics.
+ */
+#include 
+
+/ {
+   soc {
+   pinctrl: pin-controller {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "st,stm32mp157-pinctrl";
+   ranges = <0 0x50002000 0xa400>;
+   pins-are-numbered;
+
+   gpioa: gpio@50002000 {
+   gpio-controller;
+   #gpio-cells = <2>;
+   interrupt-controller;
+   #interrupt-cells = <2>;
+   reg = <0x0 0x400>;
+   clocks = <&clk_pll3_p>;
+   st,bank-name = "GPIOA";
+   ngpios = <16>;
+   gpio-ranges = <&pinctrl 0 0 16>;
+   };
+
+   gpiob: gpio@50003000 {
+   gpio-controller;
+   #gpio-cells = <2>;
+   interrupt-controller;
+   #interrupt-cells = <2>;
+   reg = <0x1000 0x400>;
+   clocks = <&clk_pll3_p>;
+   st,bank-name = "GPIOB";
+   ngpios = <16>;
+   gpio-ranges = <&pinctrl 0 16 16>;
+   };
+
+   gpioc: gpio@50004000 {
+   gpio-controller;
+   #gpio-cells = <2>;
+   interrupt-controller;
+   #interrupt-cells = <2>;
+   reg = <0x2000 0x400>;
+   clocks = <&clk_pll3_p>;
+   st,bank-name = "GPIOC";
+   ngpios = <16>;
+   gpio-ranges = <&pinctrl 0 32 16>;
+   };
+
+   gpiod: gpio@50005000 {
+   gpio-controller;
+   #gpio-cells = <2>;
+   interrupt-controller;
+   #interrupt-cells = <2>;
+   reg = <0x3000 0x400>;
+   clocks = <&clk_pll3_p>;
+   st,bank-name = "GPIOD";
+   ngpios = <16>;
+   gpio-ranges = <&pinctrl 0 48 16>;
+   };
+
+   gpioe: gpio@50006000 {
+   gpio-controller;
+   #gpio-cells = <2>;
+   interrupt-controller;
+   #interrupt-cells = <2>;
+   reg = <0x4000 0x400>;
+   clocks = <&clk_pll3_p>;
+   st,bank-name = "GPIOE";
+   ngpios = <16>;
+   gpio-ranges = <&pinctrl 0 64 16>;
+   };
+
+   gpiof: gpio@50007000 {
+   gpio-controller;
+   #gpio-cells = <2>;
+   interrupt-controller;
+   #interrupt-cells = <2>;
+   reg = <0x5000 0x400>;
+   clocks = <&clk_pll3_p>;
+   st,bank-name = "GPIOF";
+   ngpios = <16>;
+   gpio-ranges = <&pinctrl 0 80 16>;
+   };
+
+   gpiog: gpio@50008000 {
+

[PATCH v4 3/7] dt-bindings: stm32: add support of STM32MP157

2018-01-16 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds STM32MP157 SoC bindings.

Signed-off-by: Ludovic Barre 
Reviewed-by: Rob Herring 
---
 Documentation/devicetree/bindings/arm/stm32.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/arm/stm32.txt 
b/Documentation/devicetree/bindings/arm/stm32.txt
index 05762b0..6808ed9 100644
--- a/Documentation/devicetree/bindings/arm/stm32.txt
+++ b/Documentation/devicetree/bindings/arm/stm32.txt
@@ -7,3 +7,4 @@ using one of the following compatible strings:
   st,stm32f469
   st,stm32f746
   st,stm32h743
+  st,stm32mp157
-- 
2.7.4



[PATCH v4 2/7] ARM: stm32: prepare stm32 family to welcome armv7 architecture

2018-01-16 Thread Ludovic Barre
From: Ludovic Barre 

This patch prepares the STM32 machine for the integration of Cortex-A
based microprocessor (MPU), on top of the existing Cortex-M
microcontroller family (MCU). Since both MCUs and MPUs are sharing
common hardware blocks we can keep using ARCH_STM32 flag for most of
them. If a hardware block is specific to one family we can use either
ARM_SINGLE_ARMV7M or ARCH_MULTI_V7 flag.

Signed-off-by: Ludovic Barre 
---
 Documentation/arm/stm32/overview.rst | 15 +--
 arch/arm/mach-stm32/Kconfig  | 27 +++
 arch/arm/mach-stm32/board-dt.c   |  4 +---
 3 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/Documentation/arm/stm32/overview.rst 
b/Documentation/arm/stm32/overview.rst
index 6be6059..85cfc84 100644
--- a/Documentation/arm/stm32/overview.rst
+++ b/Documentation/arm/stm32/overview.rst
@@ -5,16 +5,17 @@ STM32 ARM Linux Overview
 Introduction
 
 
-The STMicroelectronics family of Cortex-M based MCUs are supported by the
-'STM32' platform of ARM Linux. Currently only the STM32F429 (Cortex-M4)
-and STM32F746 (Cortex-M7) are supported.
+The STMicroelectronics STM32 family of Cortex-A microprocessors (MPUs) and
+Cortex-M microcontrollers (MCUs) are supported by the 'STM32' platform of
+ARM Linux.
 
 Configuration
 -
 
-A generic configuration is provided for STM32 family, and can be used as the
-default by
+For MCUs, use the provided default configuration:
 make stm32_defconfig
+For MPUs, use multi_v7 configuration:
+make multi_v7_defconfig
 
 Layout
 --
@@ -28,4 +29,6 @@ Device Trees.
 
 :Authors:
 
-Maxime Coquelin 
+- Maxime Coquelin 
+- Ludovic Barre 
+- Gerald Baeza 
diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig
index 0d1889b..fb4b8b8 100644
--- a/arch/arm/mach-stm32/Kconfig
+++ b/arch/arm/mach-stm32/Kconfig
@@ -1,8 +1,7 @@
-config ARCH_STM32
-   bool "STMicrolectronics STM32"
-   depends on ARM_SINGLE_ARMV7M
+menuconfig ARCH_STM32
+   bool "STMicroelectronics STM32 family" if ARM_SINGLE_ARMV7M || 
ARCH_MULTI_V7
+   select ARMV7M_SYSTICK if ARM_SINGLE_ARMV7M
select ARCH_HAS_RESET_CONTROLLER
-   select ARMV7M_SYSTICK
select CLKSRC_STM32
select PINCTRL
select RESET_CONTROLLER
@@ -10,22 +9,26 @@ config ARCH_STM32
help
  Support for STMicroelectronics STM32 processors.
 
+if ARCH_STM32
+
+if ARM_SINGLE_ARMV7M
+
 config MACH_STM32F429
-   bool "STMicrolectronics STM32F429"
-   depends on ARCH_STM32
+   bool "STMicroelectronics STM32F429"
default y
 
 config MACH_STM32F469
-   bool "STMicrolectronics STM32F469"
-   depends on ARCH_STM32
+   bool "STMicroelectronics STM32F469"
default y
 
 config MACH_STM32F746
-   bool "STMicrolectronics STM32F746"
-   depends on ARCH_STM32
+   bool "STMicroelectronics STM32F746"
default y
 
 config MACH_STM32H743
-   bool "STMicrolectronics STM32H743"
-   depends on ARCH_STM32
+   bool "STMicroelectronics STM32H743"
default y
+
+endif # ARMv7-M
+
+endif
diff --git a/arch/arm/mach-stm32/board-dt.c b/arch/arm/mach-stm32/board-dt.c
index e918686..4a258eb 100644
--- a/arch/arm/mach-stm32/board-dt.c
+++ b/arch/arm/mach-stm32/board-dt.c
@@ -1,11 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) Maxime Coquelin 2015
  * Author:  Maxime Coquelin 
- * License terms:  GNU General Public License (GPL), version 2
  */
 
 #include 
-#include 
 #include 
 
 static const char *const stm32_compat[] __initconst = {
@@ -18,5 +17,4 @@ static const char *const stm32_compat[] __initconst = {
 
 DT_MACHINE_START(STM32DT, "STM32 (Device Tree Support)")
.dt_compat = stm32_compat,
-   .restart = armv7m_restart,
 MACHINE_END
-- 
2.7.4



[PATCH v4 7/7] ARM: dts: stm32: add initial support of stm32mp157c eval board

2018-01-16 Thread Ludovic Barre
From: Ludovic Barre 

Add support of stm32mp157c evaluation board (part number: STM32MP157C-EV1)
split in 2 elements:
-Daughter board (part number: STM32MP157C-ED1)
 which includes CPU, memory and power supply
-Mother board (part number: STM32MP157C-EM1)
 which includes external peripherals (like display, camera,...)
 and extension connectors.

The daughter board can run alone, this is why the device tree files
are split in two layers, for the complete evaluation board (ev1)
and for the daughter board alone (ed1).

Signed-off-by: Ludovic Barre 
Signed-off-by: Alexandre Torgue 
---
 arch/arm/boot/dts/Makefile|  6 --
 arch/arm/boot/dts/stm32mp157-pinctrl.dtsi | 13 +
 arch/arm/boot/dts/stm32mp157c-ed1.dts | 32 +++
 arch/arm/boot/dts/stm32mp157c-ev1.dts | 21 
 4 files changed, 70 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/boot/dts/stm32mp157c-ed1.dts
 create mode 100644 arch/arm/boot/dts/stm32mp157c-ev1.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d0381e9..d72c71c 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -839,7 +839,7 @@ dtb-$(CONFIG_ARCH_STI) += \
stih410-b2120.dtb \
stih410-b2260.dtb \
stih418-b2199.dtb
-dtb-$(CONFIG_ARCH_STM32)+= \
+dtb-$(CONFIG_ARCH_STM32) += \
stm32f429-disco.dtb \
stm32f469-disco.dtb \
stm32f746-disco.dtb \
@@ -847,7 +847,9 @@ dtb-$(CONFIG_ARCH_STM32)+= \
stm32429i-eval.dtb \
stm32746g-eval.dtb \
stm32h743i-eval.dtb \
-   stm32h743i-disco.dtb
+   stm32h743i-disco.dtb \
+   stm32mp157c-ed1.dtb \
+   stm32mp157c-ev1.dtb
 dtb-$(CONFIG_MACH_SUN4I) += \
sun4i-a10-a1000.dtb \
sun4i-a10-ba10-tvbox.dtb \
diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi 
b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
index 440276a..7ac65f4 100644
--- a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
@@ -145,6 +145,19 @@
ngpios = <8>;
gpio-ranges = <&pinctrl 0 160 8>;
};
+
+   uart4_pins_a: uart4@0 {
+   pins1 {
+   pinmux = ; 
/* UART4_TX */
+   bias-disable;
+   drive-push-pull;
+   slew-rate = <0>;
+   };
+   pins2 {
+   pinmux = ; 
/* UART4_RX */
+   bias-disable;
+   };
+   };
};
 
pinctrl_z: pin-controller-z {
diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts 
b/arch/arm/boot/dts/stm32mp157c-ed1.dts
new file mode 100644
index 000..f52eba9
--- /dev/null
+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved 
+ * Author: Ludovic Barre  for STMicroelectronics.
+ */
+/dts-v1/;
+
+#include "stm32mp157c.dtsi"
+#include "stm32mp157-pinctrl.dtsi"
+
+/ {
+   model = "STMicroelectronics STM32MP157C eval daughter";
+   compatible = "st,stm32mp157c-ed1", "st,stm32mp157";
+
+   chosen {
+   stdout-path = "serial3:115200n8";
+   };
+
+   memory {
+   reg = <0xC000 0x4000>;
+   };
+
+   aliases {
+   serial3 = &uart4;
+   };
+};
+
+&uart4 {
+   pinctrl-names = "default";
+   pinctrl-0 = <&uart4_pins_a>;
+   status = "okay";
+};
diff --git a/arch/arm/boot/dts/stm32mp157c-ev1.dts 
b/arch/arm/boot/dts/stm32mp157c-ev1.dts
new file mode 100644
index 000..d7dc9bb
--- /dev/null
+++ b/arch/arm/boot/dts/stm32mp157c-ev1.dts
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved 
+ * Author: Ludovic Barre  for STMicroelectronics.
+ */
+/dts-v1/;
+
+#include "stm32mp157c-ed1.dts"
+
+/ {
+   model = "STMicroelectronics STM32MP157C eval daughter on eval mother";
+   compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", 
"st,stm32mp157";
+
+   chosen {
+   stdout-path = "serial3:115200n8";
+   };
+
+   aliases {
+   serial3 = &uart4;
+   };
+};
-- 
2.7.4



[PATCH v4 5/7] ARM: configs: multi_v7: add stm32 support

2018-01-16 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds stm32 support to multi_v7_defconfig

Signed-off-by: Ludovic Barre 
---
 arch/arm/configs/multi_v7_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/configs/multi_v7_defconfig 
b/arch/arm/configs/multi_v7_defconfig
index 11e648a..a0163e7 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -77,6 +77,7 @@ CONFIG_ARCH_SPEAR13XX=y
 CONFIG_MACH_SPEAR1310=y
 CONFIG_MACH_SPEAR1340=y
 CONFIG_ARCH_STI=y
+CONFIG_ARCH_STM32=y
 CONFIG_ARCH_EXYNOS=y
 CONFIG_EXYNOS5420_MCPM=y
 CONFIG_ARCH_RENESAS=y
@@ -324,6 +325,8 @@ CONFIG_SERIAL_CONEXANT_DIGICOLOR=y
 CONFIG_SERIAL_CONEXANT_DIGICOLOR_CONSOLE=y
 CONFIG_SERIAL_ST_ASC=y
 CONFIG_SERIAL_ST_ASC_CONSOLE=y
+CONFIG_SERIAL_STM32=y
+CONFIG_SERIAL_STM32_CONSOLE=y
 CONFIG_VIRTIO_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_ST=y
-- 
2.7.4



[PATCH v4 0/7] ARM: stm32: add initial STM32MPU support

2018-01-16 Thread Ludovic Barre
From: Ludovic Barre 

This patch series extends the existing STM32 microcontrollers (MCUs)
family to microprocessors (MPUs). The MPU platform (based on
Arm Cortex-A) is a continuation of the MCU one (based on Arm
Cortex-M) in that it shares a wide number of hardware blocks.

change v4:
-Add all available uarts in stm32mp157c
-Move uart aliases to board files

change v3:
-Remove bootargs
-Remove armv7m_restart and Share stm32_compat for mcu/mpu
-Modify stm32 kconfig with Arnd template
-Remove patch below (Linus W: Patch applied)
 devicetree: bindings: Document supported STM32 SoC family
 pinctrl: stm32: Add STM32MP157 MPU support

change V2:
-Add stm32 documentation in this serie to avoid merge conflict
thread: "https://patchwork.kernel.org/patch/10102573/";;
-Split bindings (stm32.txt) to separate patches.
-Remove ARCH_STM32_MCU/MPU flags
-Adopt rst format for Documentation/arm/stm32 files
-s/STMicrolectronics/STMicroelectronics/g

Ludovic Barre (7):
  Documentation: arm: stm32: move to rst format
  ARM: stm32: prepare stm32 family to welcome armv7 architecture
  dt-bindings: stm32: add support of STM32MP157
  ARM: stm32: add initial support for STM32MP157
  ARM: configs: multi_v7: add stm32 support
  ARM: dts: stm32: add stm32mp157c initial support
  ARM: dts: stm32: add initial support of stm32mp157c eval board

 Documentation/arm/stm32/overview.rst|  34 +
 Documentation/arm/stm32/overview.txt|  33 
 Documentation/arm/stm32/stm32f429-overview.rst  |  26 
 Documentation/arm/stm32/stm32f429-overview.txt  |  22 ---
 Documentation/arm/stm32/stm32f746-overview.rst  |  33 
 Documentation/arm/stm32/stm32f746-overview.txt  |  34 -
 Documentation/arm/stm32/stm32h743-overview.rst  |  34 +
 Documentation/arm/stm32/stm32h743-overview.txt  |  30 
 Documentation/arm/stm32/stm32mp157-overview.rst |  19 +++
 Documentation/devicetree/bindings/arm/stm32.txt |   1 +
 arch/arm/boot/dts/Makefile  |   6 +-
 arch/arm/boot/dts/stm32mp157-pinctrl.dtsi   | 185 ++
 arch/arm/boot/dts/stm32mp157c-ed1.dts   |  32 
 arch/arm/boot/dts/stm32mp157c-ev1.dts   |  21 +++
 arch/arm/boot/dts/stm32mp157c.dtsi  | 194 
 arch/arm/configs/multi_v7_defconfig |   3 +
 arch/arm/mach-stm32/Kconfig |  38 +++--
 arch/arm/mach-stm32/board-dt.c  |   5 +-
 18 files changed, 614 insertions(+), 136 deletions(-)
 create mode 100644 Documentation/arm/stm32/overview.rst
 delete mode 100644 Documentation/arm/stm32/overview.txt
 create mode 100644 Documentation/arm/stm32/stm32f429-overview.rst
 delete mode 100644 Documentation/arm/stm32/stm32f429-overview.txt
 create mode 100644 Documentation/arm/stm32/stm32f746-overview.rst
 delete mode 100644 Documentation/arm/stm32/stm32f746-overview.txt
 create mode 100644 Documentation/arm/stm32/stm32h743-overview.rst
 delete mode 100644 Documentation/arm/stm32/stm32h743-overview.txt
 create mode 100644 Documentation/arm/stm32/stm32mp157-overview.rst
 create mode 100644 arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
 create mode 100644 arch/arm/boot/dts/stm32mp157c-ed1.dts
 create mode 100644 arch/arm/boot/dts/stm32mp157c-ev1.dts
 create mode 100644 arch/arm/boot/dts/stm32mp157c.dtsi

-- 
2.7.4



Re: [PATCH v4 7/7] ARM: dts: stm32: add initial support of stm32mp157c eval board

2018-01-16 Thread Ludovic BARRE



On 01/16/2018 03:25 PM, Arnd Bergmann wrote:

On Tue, Jan 16, 2018 at 3:12 PM, Ludovic Barre  wrote:


+
+   aliases {
+   serial3 = &uart4;
+   };


Why 'serial3' ? If you have multiple UARTS on this board, just list
all of them, otherwise
start with 'serial0'.

Arnd


sorry, I fix that :-(

BR
Ludo


[PATCH v5 3/7] dt-bindings: stm32: add support of STM32MP157

2018-01-16 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds STM32MP157 SoC bindings.

Signed-off-by: Ludovic Barre 
Reviewed-by: Rob Herring 
---
 Documentation/devicetree/bindings/arm/stm32.txt | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/arm/stm32.txt 
b/Documentation/devicetree/bindings/arm/stm32.txt
index 05762b0..6808ed9 100644
--- a/Documentation/devicetree/bindings/arm/stm32.txt
+++ b/Documentation/devicetree/bindings/arm/stm32.txt
@@ -7,3 +7,4 @@ using one of the following compatible strings:
   st,stm32f469
   st,stm32f746
   st,stm32h743
+  st,stm32mp157
-- 
2.7.4



[PATCH v5 6/7] ARM: dts: stm32: add stm32mp157c initial support

2018-01-16 Thread Ludovic Barre
From: Ludovic Barre 

Add stm32mp157c initial support with:
-Dual Cortex-A7
-Arm psci, timer, gic
-Pinctrl
-Uart

Signed-off-by: Ludovic Barre 
---
 arch/arm/boot/dts/stm32mp157-pinctrl.dtsi | 172 ++
 arch/arm/boot/dts/stm32mp157c.dtsi| 194 ++
 2 files changed, 366 insertions(+)
 create mode 100644 arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
 create mode 100644 arch/arm/boot/dts/stm32mp157c.dtsi

diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi 
b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
new file mode 100644
index 000..440276a
--- /dev/null
+++ b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
@@ -0,0 +1,172 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Author: Ludovic Barre  for STMicroelectronics.
+ */
+#include 
+
+/ {
+   soc {
+   pinctrl: pin-controller {
+   #address-cells = <1>;
+   #size-cells = <1>;
+   compatible = "st,stm32mp157-pinctrl";
+   ranges = <0 0x50002000 0xa400>;
+   pins-are-numbered;
+
+   gpioa: gpio@50002000 {
+   gpio-controller;
+   #gpio-cells = <2>;
+   interrupt-controller;
+   #interrupt-cells = <2>;
+   reg = <0x0 0x400>;
+   clocks = <&clk_pll3_p>;
+   st,bank-name = "GPIOA";
+   ngpios = <16>;
+   gpio-ranges = <&pinctrl 0 0 16>;
+   };
+
+   gpiob: gpio@50003000 {
+   gpio-controller;
+   #gpio-cells = <2>;
+   interrupt-controller;
+   #interrupt-cells = <2>;
+   reg = <0x1000 0x400>;
+   clocks = <&clk_pll3_p>;
+   st,bank-name = "GPIOB";
+   ngpios = <16>;
+   gpio-ranges = <&pinctrl 0 16 16>;
+   };
+
+   gpioc: gpio@50004000 {
+   gpio-controller;
+   #gpio-cells = <2>;
+   interrupt-controller;
+   #interrupt-cells = <2>;
+   reg = <0x2000 0x400>;
+   clocks = <&clk_pll3_p>;
+   st,bank-name = "GPIOC";
+   ngpios = <16>;
+   gpio-ranges = <&pinctrl 0 32 16>;
+   };
+
+   gpiod: gpio@50005000 {
+   gpio-controller;
+   #gpio-cells = <2>;
+   interrupt-controller;
+   #interrupt-cells = <2>;
+   reg = <0x3000 0x400>;
+   clocks = <&clk_pll3_p>;
+   st,bank-name = "GPIOD";
+   ngpios = <16>;
+   gpio-ranges = <&pinctrl 0 48 16>;
+   };
+
+   gpioe: gpio@50006000 {
+   gpio-controller;
+   #gpio-cells = <2>;
+   interrupt-controller;
+   #interrupt-cells = <2>;
+   reg = <0x4000 0x400>;
+   clocks = <&clk_pll3_p>;
+   st,bank-name = "GPIOE";
+   ngpios = <16>;
+   gpio-ranges = <&pinctrl 0 64 16>;
+   };
+
+   gpiof: gpio@50007000 {
+   gpio-controller;
+   #gpio-cells = <2>;
+   interrupt-controller;
+   #interrupt-cells = <2>;
+   reg = <0x5000 0x400>;
+   clocks = <&clk_pll3_p>;
+   st,bank-name = "GPIOF";
+   ngpios = <16>;
+   gpio-ranges = <&pinctrl 0 80 16>;
+   };
+
+   gpiog: gpio@50008000 {
+

[PATCH v5 4/7] ARM: stm32: add initial support for STM32MP157

2018-01-16 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds initial support of STM32MP157 microprocessor (MPU)
based on Arm Cortex-A7. New Cortex-A infrastructure (gic, timer,...)
are selected if ARCH_MULTI_V7 is defined.

Signed-off-by: Ludovic Barre 
---
 Documentation/arm/stm32/stm32mp157-overview.rst | 19 +++
 arch/arm/mach-stm32/Kconfig | 11 +++
 arch/arm/mach-stm32/board-dt.c  |  1 +
 3 files changed, 31 insertions(+)
 create mode 100644 Documentation/arm/stm32/stm32mp157-overview.rst

diff --git a/Documentation/arm/stm32/stm32mp157-overview.rst 
b/Documentation/arm/stm32/stm32mp157-overview.rst
new file mode 100644
index 000..62e176d
--- /dev/null
+++ b/Documentation/arm/stm32/stm32mp157-overview.rst
@@ -0,0 +1,19 @@
+STM32MP157 Overview
+===
+
+Introduction
+
+
+The STM32MP157 is a Cortex-A MPU aimed at various applications.
+It features:
+
+- Dual core Cortex-A7 application core
+- 2D/3D image composition with GPU
+- Standard memories interface support
+- Standard connectivity, widely inherited from the STM32 MCU family
+- Comprehensive security support
+
+:Authors:
+
+- Ludovic Barre 
+- Gerald Baeza 
diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig
index fb4b8b8..6b65df1 100644
--- a/arch/arm/mach-stm32/Kconfig
+++ b/arch/arm/mach-stm32/Kconfig
@@ -1,6 +1,9 @@
 menuconfig ARCH_STM32
bool "STMicroelectronics STM32 family" if ARM_SINGLE_ARMV7M || 
ARCH_MULTI_V7
select ARMV7M_SYSTICK if ARM_SINGLE_ARMV7M
+   select HAVE_ARM_ARCH_TIMER if ARCH_MULTI_V7
+   select ARM_GIC if ARCH_MULTI_V7
+   select ARM_PSCI if ARCH_MULTI_V7
select ARCH_HAS_RESET_CONTROLLER
select CLKSRC_STM32
select PINCTRL
@@ -31,4 +34,12 @@ config MACH_STM32H743
 
 endif # ARMv7-M
 
+if ARCH_MULTI_V7
+
+config MACH_STM32MP157
+   bool "STMicroelectronics STM32MP157"
+   default y
+
+endif # ARMv7-A
+
 endif
diff --git a/arch/arm/mach-stm32/board-dt.c b/arch/arm/mach-stm32/board-dt.c
index 4a258eb..d4e58ea 100644
--- a/arch/arm/mach-stm32/board-dt.c
+++ b/arch/arm/mach-stm32/board-dt.c
@@ -12,6 +12,7 @@ static const char *const stm32_compat[] __initconst = {
"st,stm32f469",
"st,stm32f746",
"st,stm32h743",
+   "st,stm32mp157",
NULL
 };
 
-- 
2.7.4



[PATCH v5 5/7] ARM: configs: multi_v7: add stm32 support

2018-01-16 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds stm32 support to multi_v7_defconfig

Signed-off-by: Ludovic Barre 
---
 arch/arm/configs/multi_v7_defconfig | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/arm/configs/multi_v7_defconfig 
b/arch/arm/configs/multi_v7_defconfig
index 11e648a..a0163e7 100644
--- a/arch/arm/configs/multi_v7_defconfig
+++ b/arch/arm/configs/multi_v7_defconfig
@@ -77,6 +77,7 @@ CONFIG_ARCH_SPEAR13XX=y
 CONFIG_MACH_SPEAR1310=y
 CONFIG_MACH_SPEAR1340=y
 CONFIG_ARCH_STI=y
+CONFIG_ARCH_STM32=y
 CONFIG_ARCH_EXYNOS=y
 CONFIG_EXYNOS5420_MCPM=y
 CONFIG_ARCH_RENESAS=y
@@ -324,6 +325,8 @@ CONFIG_SERIAL_CONEXANT_DIGICOLOR=y
 CONFIG_SERIAL_CONEXANT_DIGICOLOR_CONSOLE=y
 CONFIG_SERIAL_ST_ASC=y
 CONFIG_SERIAL_ST_ASC_CONSOLE=y
+CONFIG_SERIAL_STM32=y
+CONFIG_SERIAL_STM32_CONSOLE=y
 CONFIG_VIRTIO_CONSOLE=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_ST=y
-- 
2.7.4



[PATCH v5 1/7] Documentation: arm: stm32: move to rst format

2018-01-16 Thread Ludovic Barre
From: Ludovic Barre 

This patch rewrites stm32 documentation to rst
(ReStructuredText) format.

Signed-off-by: Ludovic Barre 
---
 Documentation/arm/stm32/overview.rst   | 31 +++
 Documentation/arm/stm32/overview.txt   | 33 -
 Documentation/arm/stm32/stm32f429-overview.rst | 26 
 Documentation/arm/stm32/stm32f429-overview.txt | 22 -
 Documentation/arm/stm32/stm32f746-overview.rst | 33 +
 Documentation/arm/stm32/stm32f746-overview.txt | 34 --
 Documentation/arm/stm32/stm32h743-overview.rst | 34 ++
 Documentation/arm/stm32/stm32h743-overview.txt | 30 ---
 8 files changed, 124 insertions(+), 119 deletions(-)
 create mode 100644 Documentation/arm/stm32/overview.rst
 delete mode 100644 Documentation/arm/stm32/overview.txt
 create mode 100644 Documentation/arm/stm32/stm32f429-overview.rst
 delete mode 100644 Documentation/arm/stm32/stm32f429-overview.txt
 create mode 100644 Documentation/arm/stm32/stm32f746-overview.rst
 delete mode 100644 Documentation/arm/stm32/stm32f746-overview.txt
 create mode 100644 Documentation/arm/stm32/stm32h743-overview.rst
 delete mode 100644 Documentation/arm/stm32/stm32h743-overview.txt

diff --git a/Documentation/arm/stm32/overview.rst 
b/Documentation/arm/stm32/overview.rst
new file mode 100644
index 000..6be6059
--- /dev/null
+++ b/Documentation/arm/stm32/overview.rst
@@ -0,0 +1,31 @@
+
+STM32 ARM Linux Overview
+
+
+Introduction
+
+
+The STMicroelectronics family of Cortex-M based MCUs are supported by the
+'STM32' platform of ARM Linux. Currently only the STM32F429 (Cortex-M4)
+and STM32F746 (Cortex-M7) are supported.
+
+Configuration
+-
+
+A generic configuration is provided for STM32 family, and can be used as the
+default by
+make stm32_defconfig
+
+Layout
+--
+
+All the files for multiple machine families are located in the platform code
+contained in arch/arm/mach-stm32
+
+There is a generic board board-dt.c in the mach folder which support
+Flattened Device Tree, which means, it works with any compatible board with
+Device Trees.
+
+:Authors:
+
+Maxime Coquelin 
diff --git a/Documentation/arm/stm32/overview.txt 
b/Documentation/arm/stm32/overview.txt
deleted file mode 100644
index a03b035..000
--- a/Documentation/arm/stm32/overview.txt
+++ /dev/null
@@ -1,33 +0,0 @@
-   STM32 ARM Linux Overview
-   
-
-Introduction
-
-
-  The STMicroelectronics family of Cortex-M based MCUs are supported by the
-  'STM32' platform of ARM Linux. Currently only the STM32F429 (Cortex-M4)
-  and STM32F746 (Cortex-M7) are supported.
-
-
-Configuration
--
-
-  A generic configuration is provided for STM32 family, and can be used as the
-  default by
-   make stm32_defconfig
-
-Layout
---
-
-  All the files for multiple machine families are located in the platform code
-  contained in arch/arm/mach-stm32
-
-  There is a generic board board-dt.c in the mach folder which support
-  Flattened Device Tree, which means, it works with any compatible board with
-  Device Trees.
-
-
-Document Author

-
-  Maxime Coquelin 
diff --git a/Documentation/arm/stm32/stm32f429-overview.rst 
b/Documentation/arm/stm32/stm32f429-overview.rst
new file mode 100644
index 000..18feda9
--- /dev/null
+++ b/Documentation/arm/stm32/stm32f429-overview.rst
@@ -0,0 +1,26 @@
+STM32F429 Overview
+==
+
+Introduction
+
+
+The STM32F429 is a Cortex-M4 MCU aimed at various applications.
+It features:
+
+- ARM Cortex-M4 up to 180MHz with FPU
+- 2MB internal Flash Memory
+- External memory support through FMC controller (PSRAM, SDRAM, NOR, NAND)
+- I2C, SPI, SAI, CAN, USB OTG, Ethernet controllers
+- LCD controller & Camera interface
+- Cryptographic processor
+
+Resources
+-
+
+Datasheet and reference manual are publicly available on ST website 
(STM32F429_).
+
+.. _STM32F429: 
http://www.st.com/web/en/catalog/mmc/FM141/SC1169/SS1577/LN1806?ecmp=stm32f429-439_pron_pr-ces2014_nov2013
+
+:Authors:
+
+Maxime Coquelin 
diff --git a/Documentation/arm/stm32/stm32f429-overview.txt 
b/Documentation/arm/stm32/stm32f429-overview.txt
deleted file mode 100644
index 5206822..000
--- a/Documentation/arm/stm32/stm32f429-overview.txt
+++ /dev/null
@@ -1,22 +0,0 @@
-   STM32F429 Overview
-   ==
-
-  Introduction
-  
-   The STM32F429 is a Cortex-M4 MCU aimed at various applications.
-   It features:
-   - ARM Cortex-M4 up to 180MHz with FPU
-   - 2MB internal Flash Memory
-   - External memory support through FMC controller (PSRAM, SDRAM, NOR, 
NAND)
-   - I2C, SPI, SAI, CAN, USB OTG, Ethernet c

[PATCH v5 0/7] ARM: stm32: add initial STM32MPU support

2018-01-16 Thread Ludovic Barre
From: Ludovic Barre 

This patch series extends the existing STM32 microcontrollers (MCUs)
family to microprocessors (MPUs). The MPU platform (based on
Arm Cortex-A) is a continuation of the MCU one (based on Arm
Cortex-M) in that it shares a wide number of hardware blocks.

change v5:
-fix serial3 aliases by serial0
 
change v4:
-Add all available uarts in stm32mp157c
-Move uart aliases to board files

change v3:
-Remove bootargs
-Remove armv7m_restart and Share stm32_compat for mcu/mpu
-Modify stm32 kconfig with Arnd template
-Remove patch below (Linus W: Patch applied)
 devicetree: bindings: Document supported STM32 SoC family
 pinctrl: stm32: Add STM32MP157 MPU support

change V2:
-Add stm32 documentation in this serie to avoid merge conflict
thread: "https://patchwork.kernel.org/patch/10102573/";;
-Split bindings (stm32.txt) to separate patches.
-Remove ARCH_STM32_MCU/MPU flags
-Adopt rst format for Documentation/arm/stm32 files
-s/STMicrolectronics/STMicroelectronics/g

Ludovic Barre (7):
  Documentation: arm: stm32: move to rst format
  ARM: stm32: prepare stm32 family to welcome armv7 architecture
  dt-bindings: stm32: add support of STM32MP157
  ARM: stm32: add initial support for STM32MP157
  ARM: configs: multi_v7: add stm32 support
  ARM: dts: stm32: add stm32mp157c initial support
  ARM: dts: stm32: add initial support of stm32mp157c eval board

 Documentation/arm/stm32/overview.rst|  34 +
 Documentation/arm/stm32/overview.txt|  33 
 Documentation/arm/stm32/stm32f429-overview.rst  |  26 
 Documentation/arm/stm32/stm32f429-overview.txt  |  22 ---
 Documentation/arm/stm32/stm32f746-overview.rst  |  33 
 Documentation/arm/stm32/stm32f746-overview.txt  |  34 -
 Documentation/arm/stm32/stm32h743-overview.rst  |  34 +
 Documentation/arm/stm32/stm32h743-overview.txt  |  30 
 Documentation/arm/stm32/stm32mp157-overview.rst |  19 +++
 Documentation/devicetree/bindings/arm/stm32.txt |   1 +
 arch/arm/boot/dts/Makefile  |   6 +-
 arch/arm/boot/dts/stm32mp157-pinctrl.dtsi   | 185 ++
 arch/arm/boot/dts/stm32mp157c-ed1.dts   |  32 
 arch/arm/boot/dts/stm32mp157c-ev1.dts   |  21 +++
 arch/arm/boot/dts/stm32mp157c.dtsi  | 194 
 arch/arm/configs/multi_v7_defconfig |   3 +
 arch/arm/mach-stm32/Kconfig |  38 +++--
 arch/arm/mach-stm32/board-dt.c  |   5 +-
 18 files changed, 614 insertions(+), 136 deletions(-)
 create mode 100644 Documentation/arm/stm32/overview.rst
 delete mode 100644 Documentation/arm/stm32/overview.txt
 create mode 100644 Documentation/arm/stm32/stm32f429-overview.rst
 delete mode 100644 Documentation/arm/stm32/stm32f429-overview.txt
 create mode 100644 Documentation/arm/stm32/stm32f746-overview.rst
 delete mode 100644 Documentation/arm/stm32/stm32f746-overview.txt
 create mode 100644 Documentation/arm/stm32/stm32h743-overview.rst
 delete mode 100644 Documentation/arm/stm32/stm32h743-overview.txt
 create mode 100644 Documentation/arm/stm32/stm32mp157-overview.rst
 create mode 100644 arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
 create mode 100644 arch/arm/boot/dts/stm32mp157c-ed1.dts
 create mode 100644 arch/arm/boot/dts/stm32mp157c-ev1.dts
 create mode 100644 arch/arm/boot/dts/stm32mp157c.dtsi

-- 
2.7.4



[PATCH v5 7/7] ARM: dts: stm32: add initial support of stm32mp157c eval board

2018-01-16 Thread Ludovic Barre
From: Ludovic Barre 

Add support of stm32mp157c evaluation board (part number: STM32MP157C-EV1)
split in 2 elements:
-Daughter board (part number: STM32MP157C-ED1)
 which includes CPU, memory and power supply
-Mother board (part number: STM32MP157C-EM1)
 which includes external peripherals (like display, camera,...)
 and extension connectors.

The daughter board can run alone, this is why the device tree files
are split in two layers, for the complete evaluation board (ev1)
and for the daughter board alone (ed1).

Signed-off-by: Ludovic Barre 
Signed-off-by: Alexandre Torgue 
---
 arch/arm/boot/dts/Makefile|  6 --
 arch/arm/boot/dts/stm32mp157-pinctrl.dtsi | 13 +
 arch/arm/boot/dts/stm32mp157c-ed1.dts | 32 +++
 arch/arm/boot/dts/stm32mp157c-ev1.dts | 21 
 4 files changed, 70 insertions(+), 2 deletions(-)
 create mode 100644 arch/arm/boot/dts/stm32mp157c-ed1.dts
 create mode 100644 arch/arm/boot/dts/stm32mp157c-ev1.dts

diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index d0381e9..d72c71c 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -839,7 +839,7 @@ dtb-$(CONFIG_ARCH_STI) += \
stih410-b2120.dtb \
stih410-b2260.dtb \
stih418-b2199.dtb
-dtb-$(CONFIG_ARCH_STM32)+= \
+dtb-$(CONFIG_ARCH_STM32) += \
stm32f429-disco.dtb \
stm32f469-disco.dtb \
stm32f746-disco.dtb \
@@ -847,7 +847,9 @@ dtb-$(CONFIG_ARCH_STM32)+= \
stm32429i-eval.dtb \
stm32746g-eval.dtb \
stm32h743i-eval.dtb \
-   stm32h743i-disco.dtb
+   stm32h743i-disco.dtb \
+   stm32mp157c-ed1.dtb \
+   stm32mp157c-ev1.dtb
 dtb-$(CONFIG_MACH_SUN4I) += \
sun4i-a10-a1000.dtb \
sun4i-a10-ba10-tvbox.dtb \
diff --git a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi 
b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
index 440276a..7ac65f4 100644
--- a/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
+++ b/arch/arm/boot/dts/stm32mp157-pinctrl.dtsi
@@ -145,6 +145,19 @@
ngpios = <8>;
gpio-ranges = <&pinctrl 0 160 8>;
};
+
+   uart4_pins_a: uart4@0 {
+   pins1 {
+   pinmux = ; 
/* UART4_TX */
+   bias-disable;
+   drive-push-pull;
+   slew-rate = <0>;
+   };
+   pins2 {
+   pinmux = ; 
/* UART4_RX */
+   bias-disable;
+   };
+   };
};
 
pinctrl_z: pin-controller-z {
diff --git a/arch/arm/boot/dts/stm32mp157c-ed1.dts 
b/arch/arm/boot/dts/stm32mp157c-ed1.dts
new file mode 100644
index 000..ee2b17b
--- /dev/null
+++ b/arch/arm/boot/dts/stm32mp157c-ed1.dts
@@ -0,0 +1,32 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Author: Ludovic Barre  for STMicroelectronics.
+ */
+/dts-v1/;
+
+#include "stm32mp157c.dtsi"
+#include "stm32mp157-pinctrl.dtsi"
+
+/ {
+   model = "STMicroelectronics STM32MP157C eval daughter";
+   compatible = "st,stm32mp157c-ed1", "st,stm32mp157";
+
+   chosen {
+   stdout-path = "serial0:115200n8";
+   };
+
+   memory {
+   reg = <0xC000 0x4000>;
+   };
+
+   aliases {
+   serial0 = &uart4;
+   };
+};
+
+&uart4 {
+   pinctrl-names = "default";
+   pinctrl-0 = <&uart4_pins_a>;
+   status = "okay";
+};
diff --git a/arch/arm/boot/dts/stm32mp157c-ev1.dts 
b/arch/arm/boot/dts/stm32mp157c-ev1.dts
new file mode 100644
index 000..0723f17
--- /dev/null
+++ b/arch/arm/boot/dts/stm32mp157c-ev1.dts
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright (C) STMicroelectronics 2017 - All Rights Reserved
+ * Author: Ludovic Barre  for STMicroelectronics.
+ */
+/dts-v1/;
+
+#include "stm32mp157c-ed1.dts"
+
+/ {
+   model = "STMicroelectronics STM32MP157C eval daughter on eval mother";
+   compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", 
"st,stm32mp157";
+
+   chosen {
+   stdout-path = "serial0:115200n8";
+   };
+
+   aliases {
+   serial0 = &uart4;
+   };
+};
-- 
2.7.4



[PATCH v5 2/7] ARM: stm32: prepare stm32 family to welcome armv7 architecture

2018-01-16 Thread Ludovic Barre
From: Ludovic Barre 

This patch prepares the STM32 machine for the integration of Cortex-A
based microprocessor (MPU), on top of the existing Cortex-M
microcontroller family (MCU). Since both MCUs and MPUs are sharing
common hardware blocks we can keep using ARCH_STM32 flag for most of
them. If a hardware block is specific to one family we can use either
ARM_SINGLE_ARMV7M or ARCH_MULTI_V7 flag.

Signed-off-by: Ludovic Barre 
---
 Documentation/arm/stm32/overview.rst | 15 +--
 arch/arm/mach-stm32/Kconfig  | 27 +++
 arch/arm/mach-stm32/board-dt.c   |  4 +---
 3 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/Documentation/arm/stm32/overview.rst 
b/Documentation/arm/stm32/overview.rst
index 6be6059..85cfc84 100644
--- a/Documentation/arm/stm32/overview.rst
+++ b/Documentation/arm/stm32/overview.rst
@@ -5,16 +5,17 @@ STM32 ARM Linux Overview
 Introduction
 
 
-The STMicroelectronics family of Cortex-M based MCUs are supported by the
-'STM32' platform of ARM Linux. Currently only the STM32F429 (Cortex-M4)
-and STM32F746 (Cortex-M7) are supported.
+The STMicroelectronics STM32 family of Cortex-A microprocessors (MPUs) and
+Cortex-M microcontrollers (MCUs) are supported by the 'STM32' platform of
+ARM Linux.
 
 Configuration
 -
 
-A generic configuration is provided for STM32 family, and can be used as the
-default by
+For MCUs, use the provided default configuration:
 make stm32_defconfig
+For MPUs, use multi_v7 configuration:
+make multi_v7_defconfig
 
 Layout
 --
@@ -28,4 +29,6 @@ Device Trees.
 
 :Authors:
 
-Maxime Coquelin 
+- Maxime Coquelin 
+- Ludovic Barre 
+- Gerald Baeza 
diff --git a/arch/arm/mach-stm32/Kconfig b/arch/arm/mach-stm32/Kconfig
index 0d1889b..fb4b8b8 100644
--- a/arch/arm/mach-stm32/Kconfig
+++ b/arch/arm/mach-stm32/Kconfig
@@ -1,8 +1,7 @@
-config ARCH_STM32
-   bool "STMicrolectronics STM32"
-   depends on ARM_SINGLE_ARMV7M
+menuconfig ARCH_STM32
+   bool "STMicroelectronics STM32 family" if ARM_SINGLE_ARMV7M || 
ARCH_MULTI_V7
+   select ARMV7M_SYSTICK if ARM_SINGLE_ARMV7M
select ARCH_HAS_RESET_CONTROLLER
-   select ARMV7M_SYSTICK
select CLKSRC_STM32
select PINCTRL
select RESET_CONTROLLER
@@ -10,22 +9,26 @@ config ARCH_STM32
help
  Support for STMicroelectronics STM32 processors.
 
+if ARCH_STM32
+
+if ARM_SINGLE_ARMV7M
+
 config MACH_STM32F429
-   bool "STMicrolectronics STM32F429"
-   depends on ARCH_STM32
+   bool "STMicroelectronics STM32F429"
default y
 
 config MACH_STM32F469
-   bool "STMicrolectronics STM32F469"
-   depends on ARCH_STM32
+   bool "STMicroelectronics STM32F469"
default y
 
 config MACH_STM32F746
-   bool "STMicrolectronics STM32F746"
-   depends on ARCH_STM32
+   bool "STMicroelectronics STM32F746"
default y
 
 config MACH_STM32H743
-   bool "STMicrolectronics STM32H743"
-   depends on ARCH_STM32
+   bool "STMicroelectronics STM32H743"
default y
+
+endif # ARMv7-M
+
+endif
diff --git a/arch/arm/mach-stm32/board-dt.c b/arch/arm/mach-stm32/board-dt.c
index e918686..4a258eb 100644
--- a/arch/arm/mach-stm32/board-dt.c
+++ b/arch/arm/mach-stm32/board-dt.c
@@ -1,11 +1,10 @@
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) Maxime Coquelin 2015
  * Author:  Maxime Coquelin 
- * License terms:  GNU General Public License (GPL), version 2
  */
 
 #include 
-#include 
 #include 
 
 static const char *const stm32_compat[] __initconst = {
@@ -18,5 +17,4 @@ static const char *const stm32_compat[] __initconst = {
 
 DT_MACHINE_START(STM32DT, "STM32 (Device Tree Support)")
.dt_compat = stm32_compat,
-   .restart = armv7m_restart,
 MACHINE_END
-- 
2.7.4



Re: [PATCH V2 2/2] mmc: mmci: add variant property to send stop cmd if a command fail

2018-11-22 Thread Ludovic BARRE

hi Ulf

due to some ST internal works, I will busy the next days.
But I will sent the change as soon as possible.


On 11/21/18 6:56 PM, Ulf Hansson wrote:

On 7 November 2018 at 10:30, Ludovic Barre  wrote:

From: Ludovic Barre 

The mmc framework follows the requirement of SD_Specification:
the STOP_TRANSMISSION is sent on multiple write/read commands
and the stop command (alone), not needed on other ADTC commands.

But, if an error happens on command or data transmission, some
variants require a stop command "STOP_TRANSMISION" to clear the DPSM
"Data Path State Machine". If it's not done the next data
command freezes hardware block.
Needed to support the STM32 sdmmc variant.


May I suggest some re-wording of this changelog, as to make it more
clear of why this is needed. Something along the lines of:

"The current approach with sending a CMD12 (STOP_TRANSMISSION) to
complete a data transfer request, either because of using the open
ended transmission type or because of receiving an error during a data
transfer, isn't sufficient for the STM32 sdmmc variant.

More precisely, for STM32 sdmmc the DPSM ("Data Path State Machine" )
needs to be cleared by sending a CMD12, also for the so called ADTC
commands. For this reason, add a new mmci variant property and let the
driver send a CMD12 to complete ADTC commands, in case it's set."


I will change, it's more accurate and concise, thanks for re-wording





Signed-off-by: Ludovic Barre 
---
  drivers/mmc/host/mmci.c | 33 +
  drivers/mmc/host/mmci.h |  4 
  2 files changed, 37 insertions(+)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 13fa640..47b865d 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -21,6 +21,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -57,6 +58,8 @@ void sdmmc_variant_init(struct mmci_host *host);
  #else
  static inline void sdmmc_variant_init(struct mmci_host *host) {}
  #endif
+static void
+mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c);

  static unsigned int fmax = 515633;

@@ -274,6 +277,7 @@ static struct variant_data variant_stm32_sdmmc = {
 .cmdreg_lrsp_crc= MCI_CPSM_STM32_LRSP_CRC,
 .cmdreg_srsp_crc= MCI_CPSM_STM32_SRSP_CRC,
 .cmdreg_srsp= MCI_CPSM_STM32_SRSP,
+   .cmdreg_stop= MCI_CPSM_STM32_CMDSTOP,
 .data_cmd_enable= MCI_CPSM_STM32_CMDTRANS,
 .irq_pio_mask   = MCI_IRQ_PIO_STM32_MASK,
 .datactrl_first = true,
@@ -573,6 +577,24 @@ void mmci_dma_error(struct mmci_host *host)
  static void
  mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
  {
+   /*
+* If an error happens on command or data transmission, some variants
+* require a stop command to reinit the DPSM.
+* If it's not done the next data command freeze hardware block.
+*/
+   if (host->variant->cmdreg_stop) {
+   u32 dpsm;
+
+   dpsm = readl_relaxed(host->base + MMCISTATUS);
+   dpsm &= MCI_STM32_DPSMACTIVE;
+
+   if (dpsm && ((mrq->cmd && mrq->cmd->error) ||
+(mrq->data && mrq->data->error))) {
+   mmci_start_command(host, &host->stop_abort, 0);
+   return;
+   }


I would rather move this code to a separate function.


OK

 Also, I think

you need something else (or additional) than polling the MMCISTATUS
register, as in principle you could end up sending CMD12 several times
for the same request, which isn't correct.


In mmci_request_end, if the DPSM is still enabled, there was no previous 
"cmd12" sent. So Normally, the regular and special cmd12 can't be sent 
for the same request.




To me the best solution would probably be to make use of the
host->data pointer, as it becomes set when DPSM has been enabled.
However, host->data is also cleared in mmci_stop_data() which is being
called prior mmci_request_end(). In other words, we need to figure
under what conditions the new code above should be triggered/called
and then also change the conditions for when mmci_request_end() shall
be called.

In principle look at callers of mmci_request_end() and
mmci_stop_data() and update those paths.


+   }
+
 writel(0, host->base + MMCICOMMAND);

 BUG_ON(host->data);
@@ -1100,6 +1122,10 @@ mmci_start_command(struct mmci_host *host, struct 
mmc_command *cmd, u32 c)
 mmci_reg_delay(host);
 }

+   if (host->variant->cmdreg_stop &&
+   cmd->opcode == MMC_STOP_TRANSMISSION)
+   c |= host->variant->cmdreg_stop;
+


Hmm.

It looks like the above changes, together with the introduction of t

Re: [PATCH V2 1/2] mmc: mmci: send stop command if sbc error issue

2018-12-05 Thread Ludovic BARRE




On 12/5/18 3:23 PM, Ulf Hansson wrote:

On Tue, 20 Nov 2018 at 10:42, Ulf Hansson  wrote:


On 7 November 2018 at 10:30, Ludovic Barre  wrote:

From: Ludovic Barre 

Refer to "4.15 set block count command" of sd specification:
Host needs to issue CMD12 if any error is detected in
the CMD18 and CMD25 operations.

In sbc case, the data->stop is fill by framework.

Signed-off-by: Ludovic Barre 
---
  drivers/mmc/host/mmci.c | 5 ++---
  1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 82bab35..13fa640 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1190,11 +1190,10 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data 
*data,
 /* The error clause is handled above, success! */
 data->bytes_xfered = data->blksz * data->blocks;

-   if (!data->stop || host->mrq->sbc) {
+   if (!data->stop || (host->mrq->sbc && !data->error))
 mmci_request_end(host, data->mrq);
-   } else {
+   else
 mmci_start_command(host, data->stop, 0);


This looks correct to me!

Although, just wanted to double check that you tested this for a case
where we have host->mrq->sbc set and got an error in data->error? I
guess it can be tricky, so I was thinking of manually trying to
instruct the code, to set an error in data->error, at some point to
trigger this code. That would at least give us some confidence that it
works as expected.


I did some manual tests to trigger the error path. As far as I can
tell, it works as expected and I observes that the core is able to
recover and re-send the request.

[...]

So, I have added my tested-by tag and applied this for next. Thanks!

In regards to patch2/2 I am awaiting your update.

Kind regards
Uffe



Re: [PATCH V2 1/2] mmc: mmci: send stop command if sbc error issue

2018-12-05 Thread Ludovic BARRE




On 12/5/18 3:23 PM, Ulf Hansson wrote:

On Tue, 20 Nov 2018 at 10:42, Ulf Hansson  wrote:


On 7 November 2018 at 10:30, Ludovic Barre  wrote:

From: Ludovic Barre 

Refer to "4.15 set block count command" of sd specification:
Host needs to issue CMD12 if any error is detected in
the CMD18 and CMD25 operations.

In sbc case, the data->stop is fill by framework.

Signed-off-by: Ludovic Barre 
---
  drivers/mmc/host/mmci.c | 5 ++---
  1 file changed, 2 insertions(+), 3 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 82bab35..13fa640 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -1190,11 +1190,10 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data 
*data,
 /* The error clause is handled above, success! */
 data->bytes_xfered = data->blksz * data->blocks;

-   if (!data->stop || host->mrq->sbc) {
+   if (!data->stop || (host->mrq->sbc && !data->error))
 mmci_request_end(host, data->mrq);
-   } else {
+   else
 mmci_start_command(host, data->stop, 0);


This looks correct to me!

Although, just wanted to double check that you tested this for a case
where we have host->mrq->sbc set and got an error in data->error? I
guess it can be tricky, so I was thinking of manually trying to
instruct the code, to set an error in data->error, at some point to
trigger this code. That would at least give us some confidence that it
works as expected.


I did some manual tests to trigger the error path. As far as I can
tell, it works as expected and I observes that the core is able to
recover and re-send the request.


Ulf, very thanks for the tests, and sorry for my busy status.
I will send as soon as possible the 2/2 with your recommendation (I will 
more spare time for upstream)




[...]

So, I have added my tested-by tag and applied this for next. Thanks!

In regards to patch2/2 I am awaiting your update.

Kind regards
Uffe



[PATCH V3 0/2] mmc: mmci: add stop command

2018-12-06 Thread Ludovic Barre
From: Ludovic Barre 

This patch series adds variant property to:
-Set cmdstop bit on STOP_TRANSMISSION command.
-On command or data error, send a stop command.
to clear DPSM if it's yet activated.

change v3:
-Move the cmdstop bit in separate patch.
-Use Ulf re-wording for patch 2/2.
-Move specific part in a separate function.

Ludovic Barre (2):
  mmc: mmci: add variant property to set command stop bit
  mmc: mmci: send stop command to clear the dpsm

 drivers/mmc/host/mmci.c | 43 +++
 drivers/mmc/host/mmci.h |  4 
 2 files changed, 47 insertions(+)

-- 
2.7.4



[PATCH V3 1/2] mmc: mmci: add variant property to set command stop bit

2018-12-06 Thread Ludovic Barre
From: Ludovic Barre 

On cmd12 (STOP_TRANSMISSION), STM32 sdmmc variant needs to set
cmdstop bit in command register. The CPSM ("Command Path State Machine")
treats the command as a Stop Transmission command and signals
abort to the DPSM ("Data Path State Machine").

Signed-off-by: Ludovic Barre 
---
 drivers/mmc/host/mmci.c | 6 ++
 drivers/mmc/host/mmci.h | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 13fa640..e352f5a 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -274,6 +275,7 @@ static struct variant_data variant_stm32_sdmmc = {
.cmdreg_lrsp_crc= MCI_CPSM_STM32_LRSP_CRC,
.cmdreg_srsp_crc= MCI_CPSM_STM32_SRSP_CRC,
.cmdreg_srsp= MCI_CPSM_STM32_SRSP,
+   .cmdreg_stop= MCI_CPSM_STM32_CMDSTOP,
.data_cmd_enable= MCI_CPSM_STM32_CMDTRANS,
.irq_pio_mask   = MCI_IRQ_PIO_STM32_MASK,
.datactrl_first = true,
@@ -1100,6 +1102,10 @@ mmci_start_command(struct mmci_host *host, struct 
mmc_command *cmd, u32 c)
mmci_reg_delay(host);
}
 
+   if (host->variant->cmdreg_stop &&
+   cmd->opcode == MMC_STOP_TRANSMISSION)
+   c |= host->variant->cmdreg_stop;
+
c |= cmd->opcode | host->variant->cmdreg_cpsm_enable;
if (cmd->flags & MMC_RSP_PRESENT) {
if (cmd->flags & MMC_RSP_136)
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 550dd39..2422909 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -264,6 +264,7 @@ struct mmci_host;
  * @cmdreg_lrsp_crc: enable value for long response with crc
  * @cmdreg_srsp_crc: enable value for short response with crc
  * @cmdreg_srsp: enable value for short response without crc
+ * @cmdreg_stop: enable value for stop and abort transmission
  * @datalength_bits: number of bits in the MMCIDATALENGTH register
  * @fifosize: number of bytes that can be written when MMCI_TXFIFOEMPTY
  *   is asserted (likewise for RX)
@@ -316,6 +317,7 @@ struct variant_data {
unsigned intcmdreg_lrsp_crc;
unsigned intcmdreg_srsp_crc;
unsigned intcmdreg_srsp;
+   unsigned intcmdreg_stop;
unsigned intdatalength_bits;
unsigned intfifosize;
unsigned intfifohalfsize;
-- 
2.7.4



[PATCH V3 2/2] mmc: mmci: send stop command to clear the dpsm

2018-12-06 Thread Ludovic Barre
From: Ludovic Barre 

The current approach with sending a CMD12 (STOP_TRANSMISSION) to
complete a data transfer request, either because of using the open
ended transmission type or because of receiving an error during a data
transfer, isn't sufficient for the STM32 sdmmc variant.

More precisely, for STM32 sdmmc the DPSM ("Data Path State Machine")
needs to be cleared by sending a CMD12, also for the so called ADTC
commands. For this reason, let the driver send a CMD12 to complete
ADTC commands, in case it's set (depend of cmdreg_stop variant property).

Signed-off-by: Ludovic Barre 
---
 drivers/mmc/host/mmci.c | 37 +
 drivers/mmc/host/mmci.h |  2 ++
 2 files changed, 39 insertions(+)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index e352f5a..4e5643d 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -58,6 +58,8 @@ void sdmmc_variant_init(struct mmci_host *host);
 #else
 static inline void sdmmc_variant_init(struct mmci_host *host) {}
 #endif
+static void
+mmci_start_command(struct mmci_host *host, struct mmc_command *cmd, u32 c);
 
 static unsigned int fmax = 515633;
 
@@ -572,9 +574,37 @@ void mmci_dma_error(struct mmci_host *host)
host->ops->dma_error(host);
 }
 
+static int mmci_stop_command(struct mmci_host *host, struct mmc_request *mrq)
+{
+   u32 dpsm;
+
+   /*
+* If an error happens on command or data transmission
+* the DPSM stay enabled. The CPSM required a stop command
+* to reinitialize the DPSM.
+*/
+   dpsm = readl_relaxed(host->base + MMCISTATUS);
+   dpsm &= MCI_STM32_DPSMACTIVE;
+
+   if (dpsm && ((mrq->cmd && mrq->cmd->error) ||
+(mrq->data && mrq->data->error))) {
+   mmci_start_command(host, &host->stop_abort, 0);
+   return -EBUSY;
+   }
+
+   return 0;
+}
+
 static void
 mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
 {
+   /*
+* For variant with cmdstop bit, a stop command could be needed
+* to finish the request.
+*/
+   if (host->variant->cmdreg_stop && mmci_stop_command(host, mrq))
+   return;
+
writel(0, host->base + MMCICOMMAND);
 
BUG_ON(host->data);
@@ -1956,6 +1986,13 @@ static int mmci_probe(struct amba_device *dev,
mmc->max_busy_timeout = 0;
}
 
+   /* prepare the stop command, used to abort and reinitialized the DPSM */
+   if (variant->cmdreg_stop) {
+   host->stop_abort.opcode = MMC_STOP_TRANSMISSION;
+   host->stop_abort.arg = 0;
+   host->stop_abort.flags = MMC_RSP_R1B | MMC_CMD_AC;
+   }
+
mmc->ops = &mmci_ops;
 
/* We support these PM capabilities. */
diff --git a/drivers/mmc/host/mmci.h b/drivers/mmc/host/mmci.h
index 2422909..35372cd 100644
--- a/drivers/mmc/host/mmci.h
+++ b/drivers/mmc/host/mmci.h
@@ -161,6 +161,7 @@
 #define MCI_ST_CEATAEND(1 << 23)
 #define MCI_ST_CARDBUSY(1 << 24)
 /* Extended status bits for the STM32 variants */
+#define MCI_STM32_DPSMACTIVE   BIT(12)
 #define MCI_STM32_BUSYD0   BIT(20)
 
 #define MMCICLEAR  0x038
@@ -377,6 +378,7 @@ struct mmci_host {
void __iomem*base;
struct mmc_request  *mrq;
struct mmc_command  *cmd;
+   struct mmc_command  stop_abort;
struct mmc_data *data;
struct mmc_host *mmc;
struct clk  *clk;
-- 
2.7.4



Re: [PATCH 00/19] mmc: mmci: add stm32 sdmmc variant

2018-06-29 Thread Ludovic BARRE

hi Ulf

I know that you very busy on other task,
but did you have time to look my serie.
do you have first feedback ?

BR
Ludo

On 06/12/2018 03:14 PM, Ludovic Barre wrote:

From: Ludovic Barre 

This patch series adapts mmci driver to add support for stm32
sdmmc variant. stm32h7 SoC integrates the first revision of
stm32 sdmmc.

This series is composed of 3 parts:
-Prepare mmci driver to manage dma interfaces by adding property.
  New mmci dma API is defined according to the legacy needs.
-Adapt mmci driver to dedicated constraints of stm32 sdmmc variant,
  defined under some specific properties.
-Add stm32 sdmmc variant. As Internal DMA way satisfies data
transfer, the mmci driver hasn't been modified for pio_read/write.
Specific adds-ons to stm32 sdmmc:
  + registers
  + clk/power functions
  + idma interface

Ludovic Barre (19):
   mmc: mmci: regroup and define dma operations
   mmc: mmci: merge qcom dml feature into mmci dma
   mmc: mmci: add datactrl block size variant property
   mmc: mmci: expand startbiterr to irqmask and error check
   mmc: mmci: allow to overwrite clock/power procedure to specific
 variant
   mmc: mmci: add variant properties to define cpsm & cmdresp bits
   mmc: mmci: add variant property to define dpsm bit
   mmc: mmci: add variant property to define irq pio mask
   mmc: mmci: add variant property to write datactrl before command
   mmc: mmci: add variant property to allow remain data
   mmc: mmci: add variant property to check specific data constraint
   mmc: mmci: add variant property to request a reset
   mmc: mmci: send stop cmd if a data command fail
   mmc: mmci: add clock divider for stm32 sdmmc
   mmc: mmci: add stm32 sdmmc registers
   mmc: mmci: add DT bindings for STM32 sdmmc
   mmc: mmci: add stm32 sdmmc idma support
   mmc: mmci: add specific clk/pwr procedure for stm32 sdmmc
   mmc: mmci: add stm32 sdmmc variant

  Documentation/devicetree/bindings/mmc/mmci.txt |  11 +
  drivers/mmc/host/Makefile  |   3 +-
  drivers/mmc/host/mmci.c| 846 +++--
  drivers/mmc/host/mmci.h| 237 ++-
  drivers/mmc/host/mmci_dma.c| 780 +++
  drivers/mmc/host/mmci_dma.h|  33 +
  drivers/mmc/host/mmci_qcom_dml.c   | 177 --
  drivers/mmc/host/mmci_qcom_dml.h   |  31 -
  8 files changed, 1410 insertions(+), 708 deletions(-)
  create mode 100644 drivers/mmc/host/mmci_dma.c
  create mode 100644 drivers/mmc/host/mmci_dma.h
  delete mode 100644 drivers/mmc/host/mmci_qcom_dml.c
  delete mode 100644 drivers/mmc/host/mmci_qcom_dml.h



Re: [PATCH 13/19] mmc: mmci: send stop cmd if a data command fail

2018-07-11 Thread Ludovic BARRE

hi Ulf

thanks for review, comments below

On 07/04/2018 03:37 PM, Ulf Hansson wrote:

On 12 June 2018 at 15:14, Ludovic Barre  wrote:

From: Ludovic Barre 

The mmc framework follows the requirement of SD_Specification:
the STOP_TRANSMISSION is sent on multiple write/read commands
and the stop command (alone), not needed on other ADTC commands.

But, some variants require a stop command "STOP_TRANSMISION" to clear
the DPSM "Data Path State Machine" if an error happens on command or data
step. If it's not done the next data command will freeze hardware block.
Needed to support the STM32 sdmmc variant.

Signed-off-by: Ludovic Barre 
---
  drivers/mmc/host/mmci.c | 36 +++-
  drivers/mmc/host/mmci.h |  3 +++
  2 files changed, 34 insertions(+), 5 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index 87724e1..9af7db8 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -24,6 +24,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  #include 
  #include 
@@ -522,11 +523,28 @@ static void mmci_set_mask1(struct mmci_host *host, 
unsigned int mask)
 host->mask1_reg = mask;
  }

-static void mmci_stop_data(struct mmci_host *host)
+static int mmci_stop_data(struct mmci_host *host)


Let's leave this as void function and instead add a check in
mmci_start_command(), to see if the command is a
MMC_STOP_TRANSMISSION. If so, then add host->variant->cmdreg_stop to
the register that is written in it.


In fact: the cmdreg_stop bit (which abort and reinit the DPSM)
should have been activated only in error case. But I see a mistake in 
this piece of code => cmdreg_stop bit is set for all MMC_STOP_TRANSMISSION.


So, I read closely the sdmmc datasheet and it seems possible
to set cmdreg_stop bit for all MMC_STOP_TRANSMISSION (error or not).

So, I will try your proposition to set cmdreg_stop bit in 
mmci_start_command() if the command is MMC_STOP_TRANSMISSION.




And actually, I think this change alone should be a separate patch
coming before $subject patch in the series, as it addresses the first
problem of two.


  {
+   struct mmc_command *stop = &host->stop_abort;
+   struct mmc_data *data = host->data;
+   unsigned int cmd = 0;
+
 mmci_write_datactrlreg(host, 0);
 mmci_set_mask1(host, 0);
 host->data = NULL;
+
+   if (host->variant->cmdreg_stop) {
+   cmd |= host->variant->cmdreg_stop;
+   if (!data->stop) {
+   memset(stop, 0, sizeof(struct mmc_command));
+   stop->opcode = MMC_STOP_TRANSMISSION;
+   stop->arg = 0;
+   stop->flags = MMC_RSP_R1B | MMC_CMD_AC;
+   data->stop = stop;


I don't understand why you want the host->stop_abort being present in
the mmci host struct? Can we get rid of that?

Anyway, re-using the data->stop pointer seems reasonable.


In fact mrq->data->stop could be not referenced (NULL).

for data command, the stop command is allocated in mmc_blk_request
struct mmc_blk_request {
  struct mmc_command stop;
};
struct mmc_data {
  struct mmc_command *stop;
};
struct mmc_request {
  struct mmc_command *stop;
};

in mmc_blk_rw_rq_prep function:
if data.blocks > 1
brq->mrq.stop = &brq->stop;
else
brq->mrq.stop = NULL;

in mmc_mrq_prep function:
if (mrq->stop) {
mrq->data->stop = mrq->stop;


Update about this topic:
This last week I found a new specific need for sdmmc variant.
On response type MMC_RSP_BUSY (example mmc_switch command cmd6, AC
command without data): SDMMC needs to set MMCIDATATIMER to define
busy_timeout.
If timeout expires Datatimeout and DPSM flags occur.
So a MMC_STOP_TRANSMISSION with cmdreg_stop bit is required to
abort and reinitialize the DPSM.

So, I think we could keep "host->stop_abort" which may be used in
cmd or data requests. The stop_abort command is always the same, so
stop_abort command could be initialized only while probe function (under 
variant->cmdreg_stop).


What do you think about it ?




+   }
+   }
+
+   return cmd;
  }

  static void mmci_init_sg(struct mmci_host *host, struct mmc_data *data)
@@ -703,6 +721,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
   unsigned int status)
  {
 unsigned int status_err;
+   unsigned int cmd_reg = 0;

 /* Make sure we have data to handle */
 if (!data)
@@ -761,7 +780,7 @@ mmci_data_irq(struct mmci_host *host, struct mmc_data *data,
 if (status & MCI_DATAEND || data->error) {
 mmci_dma_finalize(host, data);

-   mmci_stop_data(host);
+   cmd_reg = mmci_stop_data(host);

 if (!data->error)
 /* The error clause is handl

Re: [PATCH 01/19] mmc: mmci: regroup and define dma operations

2018-07-11 Thread Ludovic BARRE




On 07/05/2018 05:17 PM, Ulf Hansson wrote:

On 12 June 2018 at 15:14, Ludovic Barre  wrote:

From: Ludovic Barre 

Prepare mmci driver to manage dma interface by new property.
This patch defines and regroups dma operations for mmci drivers.
mmci_dma_XX prototypes are added to call member of mmci_dma_ops
if not null. Based on legacy need, a mmci dma interface has been
defined with:
-mmci_dma_setup
-mmci_dma_release
-mmci_dma_pre_req
-mmci_dma_start
-mmci_dma_finalize
-mmci_dma_post_req
-mmci_dma_error
-mmci_dma_get_next_data


As I suggested for one of the other patches, I would rather turn core
mmci functions into library functions, which can be either invoked
from variant callbacks or assigned directly to them.

In other words, I would leave the functions that you move in this
patch to stay in mmci.c. Although some needs to be re-factored and we
also needs to make some of them available to be called from another
file, hence the functions needs to be shared via mmci.h rather than
being declared static.


In previous exchange mail "STM32MP1 SDMMC driver review"
we are said:

>>> -dma variant à should fit in Qualcomm implementation, reuse (rename)
>>> mmci_qcom_dml.c file and integrate ST dma in.
>>
>> stm32 sdmmc has an internal dma, no need to use dmaengine API;
>> So some modifications in mmci (pre/post request, mmci_dma_xx). perhaps
>> should be done with an ops or not.
>
>Yes.
>
>The Qualcomm variant is also using an internal DMA, hence I thought
>there may be something we could re-use, or at least have some new
>common ops for.

It's not crystal clear for me.
Do you always agree with a dma ops which allow to address different
DMA transfer:
-with dmaengine API
-sdmmc idma, without dmaengine API
-...



Let me take a concrete example on how I would move forward, hopefully
that explains it a bit better. Please see below.

[...]


-/*
- * All the DMA operation mode stuff goes inside this ifdef.
- * This assumes that you have a generic DMA device interface,
- * no custom DMA interfaces are supported.
- */
-#ifdef CONFIG_DMA_ENGINE
-static void mmci_dma_setup(struct mmci_host *host)
-{
-   const char *rxname, *txname;
-   struct variant_data *variant = host->variant;
-
-   host->dma_rx_channel = dma_request_slave_channel(mmc_dev(host->mmc), 
"rx");
-   host->dma_tx_channel = dma_request_slave_channel(mmc_dev(host->mmc), 
"tx");
-
-   /* initialize pre request cookie */
-   host->next_data.cookie = 1;
-
-   /*
-* If only an RX channel is specified, the driver will
-* attempt to use it bidirectionally, however if it is
-* is specified but cannot be located, DMA will be disabled.
-*/
-   if (host->dma_rx_channel && !host->dma_tx_channel)
-   host->dma_tx_channel = host->dma_rx_channel;
-
-   if (host->dma_rx_channel)
-   rxname = dma_chan_name(host->dma_rx_channel);
-   else
-   rxname = "none";
-
-   if (host->dma_tx_channel)
-   txname = dma_chan_name(host->dma_tx_channel);
-   else
-   txname = "none";
-
-   dev_info(mmc_dev(host->mmc), "DMA channels RX %s, TX %s\n",
-rxname, txname);
-
-   /*
-* Limit the maximum segment size in any SG entry according to
-* the parameters of the DMA engine device.
-*/
-   if (host->dma_tx_channel) {
-   struct device *dev = host->dma_tx_channel->device->dev;
-   unsigned int max_seg_size = dma_get_max_seg_size(dev);
-
-   if (max_seg_size < host->mmc->max_seg_size)
-   host->mmc->max_seg_size = max_seg_size;
-   }
-   if (host->dma_rx_channel) {
-   struct device *dev = host->dma_rx_channel->device->dev;
-   unsigned int max_seg_size = dma_get_max_seg_size(dev);
-
-   if (max_seg_size < host->mmc->max_seg_size)
-   host->mmc->max_seg_size = max_seg_size;
-   }


Everything above shall be left as generic library function,
mmci_dma_setup() and I would share it via mmci.h and thus change it
from being static.



each interfaces mmci_dma_XXX have very different needs depending
dma_ops (legacy, sdmmc idma)


-
-   if (variant->qcom_dml && host->dma_rx_channel && host->dma_tx_channel)
-   if (dml_hw_init(host, host->mmc->parent->of_node))
-   variant->qcom_dml = false;


This piece of code, should be made specific to the qcom variant and
managed though a "mmci_host_ops" callback. The corresponding code in
that callback would then start by invoking mmci_dma_setup(), before it
continues with the qcom specific operations.

For legacy variants, the corresponding callback would be set directly
to mmci_dma_setup() and called through the callback from mmci.c when
needed. There is no need to have a separate file for DMA for the
legacy variants, I think.

[...]

Kind regards
Uffe



Re: [PATCH 05/19] mmc: mmci: allow to overwrite clock/power procedure to specific variant

2018-07-11 Thread Ludovic BARRE




On 07/05/2018 03:48 PM, Ulf Hansson wrote:

On 12 June 2018 at 15:14, Ludovic Barre  wrote:

From: Ludovic Barre 

A specific variant could have different power or clock procedures.
This patch allows to overwrite the default mmci_set_clkreg and
mmci_set_pwrreg for a specific variant.

Signed-off-by: Ludovic Barre 
---
  drivers/mmc/host/mmci.c | 96 +
  drivers/mmc/host/mmci.h |  7 
  2 files changed, 64 insertions(+), 39 deletions(-)

diff --git a/drivers/mmc/host/mmci.c b/drivers/mmc/host/mmci.c
index ede95b7..801c86b 100644
--- a/drivers/mmc/host/mmci.c
+++ b/drivers/mmc/host/mmci.c
@@ -374,6 +374,52 @@ static void mmci_set_clkreg(struct mmci_host *host, 
unsigned int desired)
 mmci_write_clkreg(host, clk);
  }

+static void mmci_set_pwrreg(struct mmci_host *host, unsigned char power_mode,
+   unsigned int pwr)
+{
+   struct variant_data *variant = host->variant;
+   struct mmc_host *mmc = host->mmc;
+
+   switch (power_mode) {
+   case MMC_POWER_OFF:
+   if (!IS_ERR(mmc->supply.vmmc))
+   mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
+
+   if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) {
+   regulator_disable(mmc->supply.vqmmc);
+   host->vqmmc_enabled = false;
+   }
+
+   break;
+   case MMC_POWER_UP:
+   if (!IS_ERR(mmc->supply.vmmc))
+   mmc_regulator_set_ocr(mmc, mmc->supply.vmmc,
+ mmc->ios.vdd);
+
+   /*
+* The ST Micro variant doesn't have the PL180s MCI_PWR_UP
+* and instead uses MCI_PWR_ON so apply whatever value is
+* configured in the variant data.
+*/
+   pwr |= variant->pwrreg_powerup;
+
+   break;
+   case MMC_POWER_ON:
+   if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) {
+   if (regulator_enable(mmc->supply.vqmmc) < 0)
+   dev_err(mmc_dev(mmc),
+   "failed to enable vqmmc regulator\n");
+   else
+   host->vqmmc_enabled = true;
+   }
+
+   pwr |= MCI_PWR_ON;
+   break;
+   }
+
+   mmci_write_pwrreg(host, pwr);
+}
+
  static void
  mmci_request_end(struct mmci_host *host, struct mmc_request *mrq)
  {
@@ -1031,7 +1077,7 @@ static void mmci_set_ios(struct mmc_host *mmc, struct 
mmc_ios *ios)
  {
 struct mmci_host *host = mmc_priv(mmc);
 struct variant_data *variant = host->variant;
-   u32 pwr = 0;
+   unsigned int pwr = 0;


?


yes not needed
rewritten due to re-factoring




 unsigned long flags;
 int ret;

@@ -1039,42 +1085,6 @@ static void mmci_set_ios(struct mmc_host *mmc, struct 
mmc_ios *ios)
 host->plat->ios_handler(mmc_dev(mmc), ios))
 dev_err(mmc_dev(mmc), "platform ios_handler failed\n");

-   switch (ios->power_mode) {
-   case MMC_POWER_OFF:
-   if (!IS_ERR(mmc->supply.vmmc))
-   mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, 0);
-
-   if (!IS_ERR(mmc->supply.vqmmc) && host->vqmmc_enabled) {
-   regulator_disable(mmc->supply.vqmmc);
-   host->vqmmc_enabled = false;
-   }
-
-   break;
-   case MMC_POWER_UP:
-   if (!IS_ERR(mmc->supply.vmmc))
-   mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
-
-   /*
-* The ST Micro variant doesn't have the PL180s MCI_PWR_UP
-* and instead uses MCI_PWR_ON so apply whatever value is
-* configured in the variant data.
-*/
-   pwr |= variant->pwrreg_powerup;
-
-   break;
-   case MMC_POWER_ON:
-   if (!IS_ERR(mmc->supply.vqmmc) && !host->vqmmc_enabled) {
-   ret = regulator_enable(mmc->supply.vqmmc);
-   if (ret < 0)
-   dev_err(mmc_dev(mmc),
-   "failed to enable vqmmc regulator\n");
-   else
-   host->vqmmc_enabled = true;
-   }
-
-   pwr |= MCI_PWR_ON;
-   break;
-   }


This above looks like pure re-factoring. Please make the above change
a separate patch.


OK





 if (variant->signal_direction && ios->power_mode != MMC_POWER_OFF) {
 /*
@@ -1126,8 +1136,16 @@ static void mmci_set_ios(struct mmc_h

Re: [PATCH 07/11] irqchip: stm32: add stm32mp1 support with hierarchy domain

2018-05-14 Thread Ludovic BARRE



On 05/04/2018 10:38 PM, Rob Herring wrote:

On Thu, May 3, 2018 at 4:55 AM, Ludovic BARRE  wrote:



On 05/02/2018 07:45 PM, Rob Herring wrote:


On Wed, May 2, 2018 at 11:03 AM, Ludovic BARRE 
wrote:


Hi Rob



On 05/01/2018 04:56 PM, Rob Herring wrote:



On Thu, Apr 26, 2018 at 06:18:30PM +0200, Ludovic Barre wrote:



From: Ludovic Barre 

Exti controller has been differently integrated on stm32mp1 SoC.
A parent irq has only one external interrupt. A hierachy domain could
be used. Handlers are call by parent, each parent interrupt could be
masked and unmasked according to the needs.

Signed-off-by: Ludovic Barre 
---
.../interrupt-controller/st,stm32-exti.txt |   3 +
drivers/irqchip/irq-stm32-exti.c   | 322
+
2 files changed, 325 insertions(+)

diff --git

a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt

b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
index edf03f0..136bd61 100644
---

a/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
+++

b/Documentation/devicetree/bindings/interrupt-controller/st,stm32-exti.txt
@@ -5,11 +5,14 @@ Required properties:
- compatible: Should be:
"st,stm32-exti"
"st,stm32h7-exti"
+"st,stm32mp1-exti"
- reg: Specifies base physical address and size of the registers
- interrupt-controller: Indentifies the node as an interrupt
controller
- #interrupt-cells: Specifies the number of cells to encode an
interrupt
  specifier, shall be 2
- interrupts: interrupts references to primary interrupt controller
+  (only needed for exti controller with multiple exti under
+  same parent interrupt: st,stm32-exti and st,stm32h7-exti")
  Example:
diff --git a/drivers/irqchip/irq-stm32-exti.c
b/drivers/irqchip/irq-stm32-exti.c
index b38c655..ebf7146 100644
--- a/drivers/irqchip/irq-stm32-exti.c
+++ b/drivers/irqchip/irq-stm32-exti.c




[...]


+static const struct stm32_desc_irq stm32mp1_desc_irq[] = {
+   { .exti = 1, .irq_parent = 7 },
+   { .exti = 2, .irq_parent = 8 },
+   { .exti = 3, .irq_parent = 9 },
+   { .exti = 4, .irq_parent = 10 },
+   { .exti = 5, .irq_parent = 23 },
+   { .exti = 6, .irq_parent = 64 },
+   { .exti = 7, .irq_parent = 65 },
+   { .exti = 8, .irq_parent = 66 },
+   { .exti = 9, .irq_parent = 67 },
+   { .exti = 10, .irq_parent = 40 },
+   { .exti = 11, .irq_parent = 42 },
+   { .exti = 12, .irq_parent = 76 },
+   { .exti = 13, .irq_parent = 77 },
+   { .exti = 14, .irq_parent = 121 },
+   { .exti = 15, .irq_parent = 127 },
+   { .exti = 16, .irq_parent = 1 },
+   { .exti = 65, .irq_parent = 144 },
+   { .exti = 68, .irq_parent = 143 },
+   { .exti = 73, .irq_parent = 129 },
+};




You can use an interrupt-map property rather than put this into the
driver.




interrupt-map seemed interesting and promising like used in pci host.
At first sight this property can't be used into node with
"interrupt-controller" property (see in drivers/of/irq.c function:
of_irq_parse_raw) because "of_irq_parse_raw" checks if node got
it first, and after lookup the interrupt-map.

Rob, Thomas, Jason, Marc what do you prefers or the right ways...?



I believe the correct thing to do is simply drop "interrupt-controller".




Actually, that's not right.


if I drop "interrupt-controller" of my node, my driver will not be
initialized by "of_irq_init"
(start_kernel->init_IRQ->irqchip_init->of_irq_init).
Probably, we could replace "IRQCHIP_DECLARE" by a
"module_platform_driver" or "postcore_initcall" but I'm not a big fan of
this solution. what do you think ?


You'd have to parse 'interrupt-map' yourself to extract the data for
this to work because interrupt-map currently only works when the
translation is transparent (i.e. doesn't need s/w handling). So I
guess leave this in the driver. Sorry for the noise.



Sorry, I don't know if I've correctly understand the answer.
I hesitate between:
- keep the code like this, with stm32mp1_desc_irq tab.
- parse interrupt-map property into stm32 exti driver.

Just to be sure, and avoid misunderstand.

BR
Ludo


Rob



[PATCH V2 2/3] ARM: dts: stm32: add iwdg2 support for stm32mp157c

2018-06-20 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds independent watchdog support for stm32mp157c.

Signed-off-by: Ludovic Barre 
---
 arch/arm/boot/dts/stm32mp157c.dtsi | 8 
 1 file changed, 8 insertions(+)

diff --git a/arch/arm/boot/dts/stm32mp157c.dtsi 
b/arch/arm/boot/dts/stm32mp157c.dtsi
index 7d17538..95cc166 100644
--- a/arch/arm/boot/dts/stm32mp157c.dtsi
+++ b/arch/arm/boot/dts/stm32mp157c.dtsi
@@ -784,6 +784,14 @@
status = "disabled";
};
 
+   iwdg2: watchdog@5a002000 {
+   compatible = "st,stm32mp1-iwdg";
+   reg = <0x5a002000 0x400>;
+   clocks = <&rcc IWDG2>, <&rcc CK_LSI>;
+   clock-names = "pclk", "lsi";
+   status = "disabled";
+   };
+
usbphyc: usbphyc@5a006000 {
#address-cells = <1>;
#size-cells = <0>;
-- 
2.7.4



[PATCH V2 1/3] watchdog: stm32: add pclk feature for stm32mp1

2018-06-20 Thread Ludovic Barre
From: Ludovic Barre 

This patch adds config data to manage specific properties by
compatible. Adds stm32mp1 config which requires pclk clock.

Signed-off-by: Ludovic Barre 
---
 .../devicetree/bindings/watchdog/st,stm32-iwdg.txt |  21 +++-
 drivers/watchdog/stm32_iwdg.c  | 132 ++---
 2 files changed, 104 insertions(+), 49 deletions(-)

diff --git a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt 
b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
index cc13b10a..f07f6d89 100644
--- a/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
+++ b/Documentation/devicetree/bindings/watchdog/st,stm32-iwdg.txt
@@ -2,18 +2,31 @@ STM32 Independent WatchDoG (IWDG)
 -
 
 Required properties:
-- compatible: "st,stm32-iwdg"
-- reg: physical base address and length of the registers set for the device
-- clocks: must contain a single entry describing the clock input
+- compatible: Should be either "st,stm32-iwdg" or "st,stm32mp1-iwdg"
+- reg: Physical base address and length of the registers set for the device
+- clocks: Reference to the clock entry lsi. Additional pclk clock entry
+  is required only for st,stm32mp1-iwdg.
+- clock-names: Name of the clocks used.
+  "lsi" for st,stm32-iwdg
+  "pclk", "lsi" for st,stm32mp1-iwdg
 
 Optional Properties:
 - timeout-sec: Watchdog timeout value in seconds.
 
-Example:
+Examples:
 
 iwdg: watchdog@40003000 {
compatible = "st,stm32-iwdg";
reg = <0x40003000 0x400>;
clocks = <&clk_lsi>;
+   clock-names = "lsi";
+   timeout-sec = <32>;
+};
+
+iwdg: iwdg@5a002000 {
+   compatible = "st,stm32mp1-iwdg";
+   reg = <0x5a002000 0x400>;
+   clocks = <&rcc IWDG2>, <&clk_lsi>;
+   clock-names = "pclk", "lsi";
timeout-sec = <32>;
 };
diff --git a/drivers/watchdog/stm32_iwdg.c b/drivers/watchdog/stm32_iwdg.c
index c97ad56..fc96670 100644
--- a/drivers/watchdog/stm32_iwdg.c
+++ b/drivers/watchdog/stm32_iwdg.c
@@ -11,12 +11,13 @@
 
 #include 
 #include 
-#include 
-#include 
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
+#include 
 #include 
 #include 
 
@@ -54,11 +55,17 @@
 #define TIMEOUT_US 10
 #define SLEEP_US   1000
 
+struct stm32_iwdg_config {
+   bool has_pclk;
+};
+
 struct stm32_iwdg {
-   struct watchdog_device  wdd;
-   void __iomem*regs;
-   struct clk  *clk;
-   unsigned intrate;
+   struct watchdog_device  wdd;
+   void __iomem*regs;
+   struct stm32_iwdg_config*config;
+   struct clk  *clk_lsi;
+   struct clk  *clk_pclk;
+   unsigned intrate;
 };
 
 static inline u32 reg_read(void __iomem *base, u32 reg)
@@ -133,6 +140,44 @@ static int stm32_iwdg_set_timeout(struct watchdog_device 
*wdd,
return 0;
 }
 
+static int stm32_iwdg_clk_init(struct platform_device *pdev,
+  struct stm32_iwdg *wdt)
+{
+   u32 ret;
+
+   wdt->clk_lsi = devm_clk_get(&pdev->dev, "lsi");
+   if (IS_ERR(wdt->clk_lsi)) {
+   dev_err(&pdev->dev, "Unable to get lsi clock\n");
+   return PTR_ERR(wdt->clk_lsi);
+   }
+
+   /* optional peripheral clock */
+   if (wdt->config->has_pclk) {
+   wdt->clk_pclk = devm_clk_get(&pdev->dev, "pclk");
+   if (IS_ERR(wdt->clk_pclk)) {
+   dev_err(&pdev->dev, "Unable to get pclk clock\n");
+   return PTR_ERR(wdt->clk_pclk);
+   }
+
+   ret = clk_prepare_enable(wdt->clk_pclk);
+   if (ret) {
+   dev_err(&pdev->dev, "Unable to prepare pclk clock\n");
+   return ret;
+   }
+   }
+
+   ret = clk_prepare_enable(wdt->clk_lsi);
+   if (ret) {
+   dev_err(&pdev->dev, "Unable to prepare lsi clock\n");
+   clk_disable_unprepare(wdt->clk_pclk);
+   return ret;
+   }
+
+   wdt->rate = clk_get_rate(wdt->clk_lsi);
+
+   return 0;
+}
+
 static const struct watchdog_info stm32_iwdg_info = {
.options= WDIOF_SETTIMEOUT |
  WDIOF_MAGICCLOSE |
@@ -147,49 +192,50 @@ static const struct watchdog_ops stm32_iwdg_ops = {
.set_timeout= stm32_iwdg_set_timeout,
 };
 
+static const struct stm32_iwdg_config stm32_iwdg_cfg = {
+   .has_pclk = false,
+};
+
+static const struct stm32_iwdg_config stm32mp1_iwdg_cfg = {
+   .has_pclk = true,
+};
+
+static const struct of_device_id stm32_iwdg_of_match

[PATCH V2 0/3] add iwdg2 support for stm32mp157c

2018-06-20 Thread Ludovic Barre
From: Ludovic Barre 

This patch series updates stm32_iwdg driver to manage config
by compatible. stm32mp1 config requires a pclk clock.

Ludovic Barre (3):
  watchdog: stm32: add pclk feature for stm32mp1
  ARM: dts: stm32: add iwdg2 support for stm32mp157c
  ARM: dts: stm32: add iwdg2 support for stm32mp157c-ed1

 .../devicetree/bindings/watchdog/st,stm32-iwdg.txt |  21 +++-
 arch/arm/boot/dts/stm32mp157c-ed1.dts  |   5 +
 arch/arm/boot/dts/stm32mp157c.dtsi |   8 ++
 drivers/watchdog/stm32_iwdg.c  | 132 ++---
 4 files changed, 117 insertions(+), 49 deletions(-)

-- 
2.7.4



  1   2   3   4   5   6   >