Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1741344 > unrolled thread

[PATCH v4 0/8] Various patches for SAMA5D2 backup mode

Started byRomain Izard <romain.izard.pro@gmail.com>
First post2017-09-28 11:50 +0200
Last post2017-09-28 12:10 +0200
Articles 6 — 2 participants

Back to article view | Back to linux.kernel


Contents

  [PATCH v4 0/8] Various patches for SAMA5D2 backup mode Romain Izard <romain.izard.pro@gmail.com> - 2017-09-28 11:50 +0200
    [PATCH v4 1/8] clk: at91: pmc: Wait for clocks when resuming Romain Izard <romain.izard.pro@gmail.com> - 2017-09-28 11:50 +0200
    [PATCH v4 8/8] tty/serial: atmel: Prevent a warning on suspend Romain Izard <romain.izard.pro@gmail.com> - 2017-09-28 11:50 +0200
    [PATCH v4 2/8] clk: at91: pmc: Save SCSR during suspend Romain Izard <romain.izard.pro@gmail.com> - 2017-09-28 11:50 +0200
    [PATCH v4 4/8] mtd: nand: atmel: Avoid ECC errors when leaving backup mode Romain Izard <romain.izard.pro@gmail.com> - 2017-09-28 11:50 +0200
    Re: [PATCH v4 0/8] Various patches for SAMA5D2 backup mode Alexandre Belloni <alexandre.belloni@free-electrons.com> - 2017-09-28 12:10 +0200

#1741344 — [PATCH v4 0/8] Various patches for SAMA5D2 backup mode

FromRomain Izard <romain.izard.pro@gmail.com>
Date2017-09-28 11:50 +0200
Subject[PATCH v4 0/8] Various patches for SAMA5D2 backup mode
Message-ID<uuDC9-7kq-3@gated-at.bofh.it>
While the core of the backup mode for SAMA5D2 has been integrated in
v4.13, it is far from complete. Individual controllers in the chip have
drivers that do not support the reset of the registers during suspend,
and they need to be adapted to handle it.

The first patch uses the clock wakeup code from the prototype backup
mode instead of the version integrated in the mainline, as the mainline
version is not stable. During a test loop with two-second backup
suspend, the mainline version will hang in less than one day, whereas
the prototype version has been running the same test for more than a
week without hanging.

While all these patches are provided in a series, the clock, mtd,
usb, pwm and mfd patch do not depend on each other.

Changes in v2:
* drop the IIO patch duplicating existing code
* determine the number of programmable clocks to save dynamically
* declare a required local variable in the tty/serial patch

Changes in v3:
* drop dev_printk changes for PMECC
* rework the resume code for PMECC
* improve comments on PMC clock handling

Changes in v4:
* fix a bug in the PMECC resume code

Romain Izard (8):
  clk: at91: pmc: Wait for clocks when resuming
  clk: at91: pmc: Save SCSR during suspend
  clk: at91: pmc: Support backup for programmable clocks
  mtd: nand: atmel: Avoid ECC errors when leaving backup mode
  ehci-atmel: Power down during suspend is normal
  pwm: atmel-tcb: Support backup mode
  atmel_flexcom: Support backup mode
  tty/serial: atmel: Prevent a warning on suspend

 drivers/clk/at91/clk-programmable.c      |  2 +
 drivers/clk/at91/pmc.c                   | 63 ++++++++++++++++++++++++++-----
 drivers/clk/at91/pmc.h                   |  2 +
 drivers/mfd/atmel-flexcom.c              | 65 ++++++++++++++++++++++++--------
 drivers/mtd/nand/atmel/nand-controller.c |  3 ++
 drivers/mtd/nand/atmel/pmecc.c           | 17 +++++----
 drivers/mtd/nand/atmel/pmecc.h           |  1 +
 drivers/pwm/pwm-atmel-tcb.c              | 63 ++++++++++++++++++++++++++++++-
 drivers/tty/serial/atmel_serial.c        | 13 +++++++
 drivers/usb/host/ehci-atmel.c            |  3 +-
 10 files changed, 196 insertions(+), 36 deletions(-)

-- 
2.11.0

[toc] | [next] | [standalone]


#1741345 — [PATCH v4 1/8] clk: at91: pmc: Wait for clocks when resuming

FromRomain Izard <romain.izard.pro@gmail.com>
Date2017-09-28 11:50 +0200
Subject[PATCH v4 1/8] clk: at91: pmc: Wait for clocks when resuming
Message-ID<uuDCa-7kq-25@gated-at.bofh.it>
In reply to#1741344
Wait for the syncronization of all clocks when resuming, not only the
UPLL clock. Do not use regmap_read_poll_timeout, as it will call BUG()
when interrupts are masked, which is the case in here.

Signed-off-by: Romain Izard <romain.izard.pro@gmail.com>
Acked-by: Ludovic Desroches <ludovic.desroches@microchip.com>
Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
---
 drivers/clk/at91/pmc.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 775af473fe11..5c2b26de303e 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -107,10 +107,20 @@ static int pmc_suspend(void)
 	return 0;
 }
 
+static bool pmc_ready(unsigned int mask)
+{
+	unsigned int status;
+
+	regmap_read(pmcreg, AT91_PMC_SR, &status);
+
+	return ((status & mask) == mask) ? 1 : 0;
+}
+
 static void pmc_resume(void)
 {
-	int i, ret = 0;
+	int i;
 	u32 tmp;
+	u32 mask = AT91_PMC_MCKRDY | AT91_PMC_LOCKA;
 
 	regmap_read(pmcreg, AT91_PMC_MCKR, &tmp);
 	if (pmc_cache.mckr != tmp)
@@ -134,13 +144,11 @@ static void pmc_resume(void)
 			     AT91_PMC_PCR_CMD);
 	}
 
-	if (pmc_cache.uckr & AT91_PMC_UPLLEN) {
-		ret = regmap_read_poll_timeout(pmcreg, AT91_PMC_SR, tmp,
-					       !(tmp & AT91_PMC_LOCKU),
-					       10, 5000);
-		if (ret)
-			pr_crit("USB PLL didn't lock when resuming\n");
-	}
+	if (pmc_cache.uckr & AT91_PMC_UPLLEN)
+		mask |= AT91_PMC_LOCKU;
+
+	while (!pmc_ready(mask))
+		cpu_relax();
 }
 
 static struct syscore_ops pmc_syscore_ops = {
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1741346 — [PATCH v4 8/8] tty/serial: atmel: Prevent a warning on suspend

FromRomain Izard <romain.izard.pro@gmail.com>
Date2017-09-28 11:50 +0200
Subject[PATCH v4 8/8] tty/serial: atmel: Prevent a warning on suspend
Message-ID<uuDCa-7kq-27@gated-at.bofh.it>
In reply to#1741344
The atmel serial port driver reported the following warning on suspend:
atmel_usart f8020000.serial: ttyS1: Unable to drain transmitter

As the ATMEL_US_TXEMPTY status bit in ATMEL_US_CSR is always cleared
when the transmitter is disabled, we need to know the transmitter's
state to return the real fifo state. And as ATMEL_US_CR is write-only,
it is necessary to save the state of the transmitter in a local
variable, and update the variable when TXEN and TXDIS is written in
ATMEL_US_CR.

After those changes, atmel_tx_empty can return "empty" on suspend, the
warning in uart_suspend_port disappears, and suspending is 20ms shorter
for each enabled Atmel serial port.

Signed-off-by: Romain Izard <romain.izard.pro@gmail.com>
Tested-by: Nicolas Ferre <nicolas.ferre@microchip.com>
Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
Acked-by: Richard Genoud <richard.genoud@gmail.com>
---
 drivers/tty/serial/atmel_serial.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index 7551cab438ff..ce45b4ada0bf 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -171,6 +171,7 @@ struct atmel_uart_port {
 	bool			has_hw_timer;
 	struct timer_list	uart_timer;
 
+	bool			tx_stopped;
 	bool			suspended;
 	unsigned int		pending;
 	unsigned int		pending_status;
@@ -380,6 +381,10 @@ static int atmel_config_rs485(struct uart_port *port,
  */
 static u_int atmel_tx_empty(struct uart_port *port)
 {
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
+
+	if (atmel_port->tx_stopped)
+		return TIOCSER_TEMT;
 	return (atmel_uart_readl(port, ATMEL_US_CSR) & ATMEL_US_TXEMPTY) ?
 		TIOCSER_TEMT :
 		0;
@@ -485,6 +490,7 @@ static void atmel_stop_tx(struct uart_port *port)
 	 * is fully transmitted.
 	 */
 	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS);
+	atmel_port->tx_stopped = true;
 
 	/* Disable interrupts */
 	atmel_uart_writel(port, ATMEL_US_IDR, atmel_port->tx_done_mask);
@@ -521,6 +527,7 @@ static void atmel_start_tx(struct uart_port *port)
 
 	/* re-enable the transmitter */
 	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN);
+	atmel_port->tx_stopped = false;
 }
 
 /*
@@ -1866,6 +1873,7 @@ static int atmel_startup(struct uart_port *port)
 	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
 	/* enable xmit & rcvr */
 	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
+	atmel_port->tx_stopped = false;
 
 	setup_timer(&atmel_port->uart_timer,
 			atmel_uart_timer_callback,
@@ -2122,6 +2130,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 
 	/* disable receiver and transmitter */
 	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXDIS | ATMEL_US_RXDIS);
+	atmel_port->tx_stopped = true;
 
 	/* mode */
 	if (port->rs485.flags & SER_RS485_ENABLED) {
@@ -2207,6 +2216,7 @@ static void atmel_set_termios(struct uart_port *port, struct ktermios *termios,
 	atmel_uart_writel(port, ATMEL_US_BRGR, quot);
 	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
 	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
+	atmel_port->tx_stopped = false;
 
 	/* restore interrupts */
 	atmel_uart_writel(port, ATMEL_US_IER, imr);
@@ -2450,6 +2460,7 @@ static void atmel_console_write(struct console *co, const char *s, u_int count)
 
 	/* Make sure that tx path is actually able to send characters */
 	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN);
+	atmel_port->tx_stopped = false;
 
 	uart_console_write(port, s, count, atmel_console_putchar);
 
@@ -2511,6 +2522,7 @@ static int __init atmel_console_setup(struct console *co, char *options)
 {
 	int ret;
 	struct uart_port *port = &atmel_ports[co->index].uart;
+	struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
 	int baud = 115200;
 	int bits = 8;
 	int parity = 'n';
@@ -2528,6 +2540,7 @@ static int __init atmel_console_setup(struct console *co, char *options)
 	atmel_uart_writel(port, ATMEL_US_IDR, -1);
 	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_RSTSTA | ATMEL_US_RSTRX);
 	atmel_uart_writel(port, ATMEL_US_CR, ATMEL_US_TXEN | ATMEL_US_RXEN);
+	atmel_port->tx_stopped = false;
 
 	if (options)
 		uart_parse_options(options, &baud, &parity, &bits, &flow);
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1741349 — [PATCH v4 2/8] clk: at91: pmc: Save SCSR during suspend

FromRomain Izard <romain.izard.pro@gmail.com>
Date2017-09-28 11:50 +0200
Subject[PATCH v4 2/8] clk: at91: pmc: Save SCSR during suspend
Message-ID<uuDCb-7kq-37@gated-at.bofh.it>
In reply to#1741344
The contents of the System Clock Status Register (SCSR) needs to be
restored into the System Clock Enable Register (SCER).

As the bootloader will restore some clocks by itself, the issue can be
missed as only the USB controller, the LCD controller, the Image Sensor
controller and the programmable clocks will be impacted.

Fix the obvious typo in the suspend/resume code, as the IMR register
does not need to be saved twice.

Signed-off-by: Romain Izard <romain.izard.pro@gmail.com>
Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com>
---
 drivers/clk/at91/pmc.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/clk/at91/pmc.c b/drivers/clk/at91/pmc.c
index 5c2b26de303e..07dc2861ad3f 100644
--- a/drivers/clk/at91/pmc.c
+++ b/drivers/clk/at91/pmc.c
@@ -86,7 +86,7 @@ static int pmc_suspend(void)
 {
 	int i;
 
-	regmap_read(pmcreg, AT91_PMC_IMR, &pmc_cache.scsr);
+	regmap_read(pmcreg, AT91_PMC_SCSR, &pmc_cache.scsr);
 	regmap_read(pmcreg, AT91_PMC_PCSR, &pmc_cache.pcsr0);
 	regmap_read(pmcreg, AT91_CKGR_UCKR, &pmc_cache.uckr);
 	regmap_read(pmcreg, AT91_CKGR_MOR, &pmc_cache.mor);
@@ -129,7 +129,7 @@ static void pmc_resume(void)
 	if (pmc_cache.pllar != tmp)
 		pr_warn("PLLAR was not configured properly by the firmware\n");
 
-	regmap_write(pmcreg, AT91_PMC_IMR, pmc_cache.scsr);
+	regmap_write(pmcreg, AT91_PMC_SCER, pmc_cache.scsr);
 	regmap_write(pmcreg, AT91_PMC_PCER, pmc_cache.pcsr0);
 	regmap_write(pmcreg, AT91_CKGR_UCKR, pmc_cache.uckr);
 	regmap_write(pmcreg, AT91_CKGR_MOR, pmc_cache.mor);
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1741352 — [PATCH v4 4/8] mtd: nand: atmel: Avoid ECC errors when leaving backup mode

FromRomain Izard <romain.izard.pro@gmail.com>
Date2017-09-28 11:50 +0200
Subject[PATCH v4 4/8] mtd: nand: atmel: Avoid ECC errors when leaving backup mode
Message-ID<uuDCb-7kq-45@gated-at.bofh.it>
In reply to#1741344
During backup mode, the contents of all registers will be cleared as the
SoC will be completely powered down. For a product that boots on NAND
Flash memory, the bootloader will obviously use the related controller
to read the Flash and correct any detected error in the memory, before
handling back control to the kernel's resuming entry point.

But it does not clean the NAND controller registers after use and on its
side the kernel driver expects the error locator to be powered down and
in a clean state. Add a resume hook for the PMECC error locator, and
reset its registers.

Signed-off-by: Romain Izard <romain.izard.pro@gmail.com>
---
Changes in v3:
* keep the PMECC disabled when not in use, and use atmel_pmecc_resume to
  reset the controller after the bootloader has left it enabled.

Changes in v4:
* export atmel_pmecc_reset instead of atmel_pmecc_resume
* use the correct pointer in atmel_nand_controller_resume

 drivers/mtd/nand/atmel/nand-controller.c |  3 +++
 drivers/mtd/nand/atmel/pmecc.c           | 17 +++++++++--------
 drivers/mtd/nand/atmel/pmecc.h           |  1 +
 3 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/drivers/mtd/nand/atmel/nand-controller.c b/drivers/mtd/nand/atmel/nand-controller.c
index f25eca79f4e5..8afcff9a66ea 100644
--- a/drivers/mtd/nand/atmel/nand-controller.c
+++ b/drivers/mtd/nand/atmel/nand-controller.c
@@ -2530,6 +2530,9 @@ static __maybe_unused int atmel_nand_controller_resume(struct device *dev)
 	struct atmel_nand_controller *nc = dev_get_drvdata(dev);
 	struct atmel_nand *nand;
 
+	if (nc->pmecc)
+		atmel_pmecc_reset(nc->pmecc);
+
 	list_for_each_entry(nand, &nc->chips, node) {
 		int i;
 
diff --git a/drivers/mtd/nand/atmel/pmecc.c b/drivers/mtd/nand/atmel/pmecc.c
index 146af8218314..0a3f12141c45 100644
--- a/drivers/mtd/nand/atmel/pmecc.c
+++ b/drivers/mtd/nand/atmel/pmecc.c
@@ -765,6 +765,13 @@ void atmel_pmecc_get_generated_eccbytes(struct atmel_pmecc_user *user,
 }
 EXPORT_SYMBOL_GPL(atmel_pmecc_get_generated_eccbytes);
 
+void atmel_pmecc_reset(struct atmel_pmecc *pmecc)
+{
+	writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL);
+	writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL);
+}
+EXPORT_SYMBOL_GPL(atmel_pmecc_reset);
+
 int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op)
 {
 	struct atmel_pmecc *pmecc = user->pmecc;
@@ -797,10 +804,7 @@ EXPORT_SYMBOL_GPL(atmel_pmecc_enable);
 
 void atmel_pmecc_disable(struct atmel_pmecc_user *user)
 {
-	struct atmel_pmecc *pmecc = user->pmecc;
-
-	writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL);
-	writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL);
+	atmel_pmecc_reset(user->pmecc);
 	mutex_unlock(&user->pmecc->lock);
 }
 EXPORT_SYMBOL_GPL(atmel_pmecc_disable);
@@ -855,10 +859,7 @@ static struct atmel_pmecc *atmel_pmecc_create(struct platform_device *pdev,
 
 	/* Disable all interrupts before registering the PMECC handler. */
 	writel(0xffffffff, pmecc->regs.base + ATMEL_PMECC_IDR);
-
-	/* Reset the ECC engine */
-	writel(PMECC_CTRL_RST, pmecc->regs.base + ATMEL_PMECC_CTRL);
-	writel(PMECC_CTRL_DISABLE, pmecc->regs.base + ATMEL_PMECC_CTRL);
+	atmel_pmecc_reset(pmecc);
 
 	return pmecc;
 }
diff --git a/drivers/mtd/nand/atmel/pmecc.h b/drivers/mtd/nand/atmel/pmecc.h
index a8ddbfca2ea5..817e0dd9fd15 100644
--- a/drivers/mtd/nand/atmel/pmecc.h
+++ b/drivers/mtd/nand/atmel/pmecc.h
@@ -61,6 +61,7 @@ atmel_pmecc_create_user(struct atmel_pmecc *pmecc,
 			struct atmel_pmecc_user_req *req);
 void atmel_pmecc_destroy_user(struct atmel_pmecc_user *user);
 
+void atmel_pmecc_reset(struct atmel_pmecc *pmecc);
 int atmel_pmecc_enable(struct atmel_pmecc_user *user, int op);
 void atmel_pmecc_disable(struct atmel_pmecc_user *user);
 int atmel_pmecc_wait_rdy(struct atmel_pmecc_user *user);
-- 
2.11.0

[toc] | [prev] | [next] | [standalone]


#1741383

FromAlexandre Belloni <alexandre.belloni@free-electrons.com>
Date2017-09-28 12:10 +0200
Message-ID<uuDVv-7Gp-9@gated-at.bofh.it>
In reply to#1741344
Hi,

On 28/09/2017 at 11:46:19 +0200, Romain Izard wrote:
> While the core of the backup mode for SAMA5D2 has been integrated in
> v4.13, it is far from complete. Individual controllers in the chip have
> drivers that do not support the reset of the registers during suspend,
> and they need to be adapted to handle it.
> 
> The first patch uses the clock wakeup code from the prototype backup
> mode instead of the version integrated in the mainline, as the mainline
> version is not stable. During a test loop with two-second backup
> suspend, the mainline version will hang in less than one day, whereas
> the prototype version has been running the same test for more than a
> week without hanging.
> 
> While all these patches are provided in a series, the clock, mtd,
> usb, pwm and mfd patch do not depend on each other.
> 
> Changes in v2:
> * drop the IIO patch duplicating existing code
> * determine the number of programmable clocks to save dynamically
> * declare a required local variable in the tty/serial patch
> 
> Changes in v3:
> * drop dev_printk changes for PMECC
> * rework the resume code for PMECC
> * improve comments on PMC clock handling
> 
> Changes in v4:
> * fix a bug in the PMECC resume code
> 
> Romain Izard (8):
>   clk: at91: pmc: Wait for clocks when resuming
>   clk: at91: pmc: Save SCSR during suspend
>   clk: at91: pmc: Support backup for programmable clocks
>   mtd: nand: atmel: Avoid ECC errors when leaving backup mode
>   ehci-atmel: Power down during suspend is normal
>   pwm: atmel-tcb: Support backup mode
>   atmel_flexcom: Support backup mode
>   tty/serial: atmel: Prevent a warning on suspend
> 

Really, you have to stop sending those independent patches as a series
if you want to have a chance to see them being merged.

>  drivers/clk/at91/clk-programmable.c      |  2 +
>  drivers/clk/at91/pmc.c                   | 63 ++++++++++++++++++++++++++-----
>  drivers/clk/at91/pmc.h                   |  2 +
>  drivers/mfd/atmel-flexcom.c              | 65 ++++++++++++++++++++++++--------
>  drivers/mtd/nand/atmel/nand-controller.c |  3 ++
>  drivers/mtd/nand/atmel/pmecc.c           | 17 +++++----
>  drivers/mtd/nand/atmel/pmecc.h           |  1 +
>  drivers/pwm/pwm-atmel-tcb.c              | 63 ++++++++++++++++++++++++++++++-
>  drivers/tty/serial/atmel_serial.c        | 13 +++++++
>  drivers/usb/host/ehci-atmel.c            |  3 +-
>  10 files changed, 196 insertions(+), 36 deletions(-)
> 
> -- 
> 2.11.0
> 

-- 
Alexandre Belloni, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com

[toc] | [prev] | [standalone]


Back to top | Article view | linux.kernel


csiph-web