All of lore.kernel.org
 help / color / mirror / Atom feed
From: Martin Sperl <kernel@martin.sperl.org>
To: Stefan Wahren <stefan.wahren@i2se.com>
Cc: linux-serial@vger.kernel.org,
	linux-clk <linux-clk@vger.kernel.org>,
	Eric Anholt <eric@anholt.net>,
	linux-rpi-kernel <linux-rpi-kernel@lists.infradead.org>,
	linux-arm-kernel@lists.infradead.org
Subject: Re: serial: clk: bcm2835: Strange effects when using aux-uart in console
Date: Tue, 16 Feb 2016 17:31:41 +0100	[thread overview]
Message-ID: <D4D8C3EE-7BDC-44F4-A54F-A6861FE0A174@martin.sperl.org> (raw)
In-Reply-To: <359843746.379810.6eb6c2f5-8282-417a-83d1-1fa79425ff73.open-xchange@email.1und1.de>


> On 13.02.2016, at 21:45, Stefan Wahren <stefan.wahren@i2se.com> wrote:
> 
> 
> According to the datasheet busy bit shouldn't be set while changing the clock.
> So this isn't good. I hope this could be fixed, too.
> 

I had hoped that the patch by Eric:
"clk: bcm2835: Fix setting of PLL divider clock rates"
would fix the issue, but that was unfortunately not the case.

Some more investigation using the debugfs patch I had posted,
which exposes the registers showed that:
plld_per_a2w had a value of 4 before starting getty
and a value of 0 after starting getty.

That made me investigate why this value was changed and I found
the culprit in the form of:
@@ -1167,7 +1171,9 @@ static void bcm2835_pll_divider_off(struct clk_hw *hw)
        cprman_write(cprman, data->cm_reg,
                     (cprman_read(cprman, data->cm_reg) &
                      ~data->load_mask) | data->hold_mask);
-       cprman_write(cprman, data->a2w_reg, A2W_PLL_CHANNEL_DISABLE);
+       cprman_write(cprman, data->a2w_reg,
+                    cprman_read(cprman, data->a2w_reg) |
+                       A2W_PLL_CHANNEL_DISABLE);
 }

after that (with plld itself marked as “prepared” during probe) everything is
working fine.

bcm2835_pll_off shows a similar pattern, but patching that
the same way:
@@ -955,8 +955,12 @@ static void bcm2835_pll_off(struct clk_hw *hw)
        struct bcm2835_cprman *cprman = pll->cprman;
        const struct bcm2835_pll_data *data = pll->data;

-       cprman_write(cprman, data->cm_ctrl_reg, CM_PLL_ANARST);
-       cprman_write(cprman, data->a2w_ctrl_reg, A2W_PLL_CTRL_PWRDN);
+       cprman_write(cprman, data->cm_ctrl_reg,
+                    cprman_read(cprman, data->cm_ctrl_reg) |
+                    CM_PLL_ANARST);
+       cprman_write(cprman, data->a2w_ctrl_reg,
+                    cprman_read(cprman, data->a2w_ctrl_reg) |
+                    A2W_PLL_CTRL_PWRDN);
 }

does not resolve the issue - the system crashes - but without he pll
lock message…

With some debugging messages in place (the register names are
added as a comments indicated via >):

the complete list of writes to the clocks during boot:
[    2.021473] bcm2835_pll_on - pllc - start
[    2.025635] cprman_write - 0x0108 = 0x00000228
> CM_PLLC
[    2.030313] bcm2835_pll_on - pllc - before_wait_pll_lock
[    2.035773] bcm2835_pll_on - pllc - end
[    2.039785] cprman_write - 0x1620 = 0x00000002
> A2W_PLLC_CORE0
[    2.044373] cprman_write - 0x0108 = 0x00000228
> CM_PLLC
[    2.049430] console [ttyS0] disabled
[    2.053237] 20215040.serial: ttyS0 at MMIO 0x0 (irq = 53, base_baud = 31224999) is a 16550
[    2.061878] console [ttyS0] enabled
[    2.069085] bootconsole [earlycon0] disabled
[    2.078668] cprman_write - 0x1520 = 0x00000002
> A2W_PLLC_PER
[    2.083201] cprman_write - 0x0108 = 0x00000228
> CM_PLLC
[    2.087801] cprman_write - 0x01c0 = 0x000002d5
> CM_EMMCCTL
[    2.136432] mmc0: SDHCI controller on 20300000.sdhci [20300000.sdhci] using PIO

dumping the registers for PLLD 
root@raspcm:~# cat /sys/kernel/debug/clk/plld/regdump
cm_ctrl = 0x0000020a
> CM_PLLD
a2w_ctrl = 0x00021034
> A2W_PLLD_PER
frac = 0x00015554
> A2W_PLLD_FRAC
ana0 = 0x00000000
> A2W_PLLD_ANA0
ana1 = 0x00144000
> A2W_PLLD_ANA1
ana2 = 0x00000000
> A2W_PLLD_ANA2
ana3 = 0x00000100
> A2W_PLLD_ANA3

running getty:
root@raspcm:~# /sbin/getty -a root -L ttyAMA0 115200 vt100
[   71.110032] pl011_startup - start
[   71.113452] pl011_hwinit - prepare-enable
[   71.117656] bcm2835_pll_on - plld - start
[   71.121750] cprman_write - 0x010c = 0x0000020a
> CM_PLLD
[   71.126274] bcm2835_pll_on - plld - before_wait_pll_lock
[   71.131728] bcm2835_pll_on - plld - end
[   71.135648] cprman_write - 0x1540 = 0x00000004
> A2W_PLLD_PER
[   71.140228] cprman_write - 0x010c = 0x0000020a
> CM_PLLD
[   71.144760] cprman_write - 0x00f0 = 0x000002d6
> CM_UARTCTL
[   71.149340] pl011_hwinit - prepare-enable - ret = 0
[   71.156743] pl011_startup - exit
[   71.163324] pl011_shutdown - start
[   71.168032] pl011_shutdown - disable_unprepare
[   71.172603] cprman_write - 0x00f0 = 0x00000286
> CM_UARTCTL
[   71.177269] cprman_write - 0x010c = 0x0000028a
> CM_PLLD
[   71.181809] cprman_write - 0x1540 = 0x00000104
> A2W_PLLD_PER
[   71.186334] bcm2835_pll_off - plld - start
[   71.190547] cprman_write - 0x010c = 0x0000038a
> CM_PLLD
[   71.195088] cprman_write - 0x1140 = 0x00031034
> A2W_PLLD_CTRL
[   71.199643] bcm2835_pll_off - plld - end
[   71.203643] pl011_shutdown - exit
[   71.209122] pl011_startup - start
[   71.212522] pl011_hwinit - prepare-enable
[   71.216695] bcm2835_pll_on - plld - start
[   71.220801] cprman_write - 0x010c = 0x0000028a
>  CM_PLLD
[   71.225326] bcm2835_pll_on - plld - before_wait_pll_lock
[   71.230775] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.235840] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.240926] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.245983] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.251067] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.256123] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.261206] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.266272] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.271364] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.276419] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.281523] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.286691] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.291753] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.296838] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.301937] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.307030] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.312087] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.317180] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.322235] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.327319] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.332387] bcm2835-clk 20101000.cprman: plld: couldn't lock PLL
[   71.338532] bcm2835_pll_on - plld - timeout
[   71.342801] pl011_hwinit - prepare-enable - ret = -110
[   71.348080] pl011_startup - error = -110 - disable_unprepare
[   71.353862] ------------[ cut here ]------------
[   71.358593] WARNING: CPU: 0 PID: 2339 at drivers/clk/clk.c:680 clk_core_disab
le+0x34/0xf0()
[   71.367840] ---[ end trace f080e315d858793e ]---
[   71.372614] ------------[ cut here ]------------
[   71.377408] WARNING: CPU: 0 PID: 2339 at drivers/clk/clk.c:575 clk_core_unpre
pare+0x34/0x110()
[   71.387073] ---[ end trace f080e315d858793f ]—

no more activity - system crashed - HDMI looses signal
So disabling PLL itself seems not to be recommended

I could create a patch with the following content as a bandaid:
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 5293338..4dfb8e3 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -37,6 +37,7 @@
  * generator).
  */

+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/clk/bcm2835.h>
@@ -1750,6 +1767,9 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
			clks[i] = desc->clk_register(cprman, desc->data);
 	}
 
+	/* prepare PLLD, so that it never gets unprepared */
+	clk_prepare(clks[BCM2835_PLLD]);
+
 	return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
 				   &cprman->onecell);
 }

Note that this this needed on top of the patch to bcm2835_pll_divider_off,
which is applied in the kernel used during reporting...

Martin

WARNING: multiple messages have this Message-ID (diff)
From: kernel@martin.sperl.org (Martin Sperl)
To: linux-arm-kernel@lists.infradead.org
Subject: serial: clk: bcm2835: Strange effects when using aux-uart in console
Date: Tue, 16 Feb 2016 17:31:41 +0100	[thread overview]
Message-ID: <D4D8C3EE-7BDC-44F4-A54F-A6861FE0A174@martin.sperl.org> (raw)
In-Reply-To: <359843746.379810.6eb6c2f5-8282-417a-83d1-1fa79425ff73.open-xchange@email.1und1.de>


> On 13.02.2016, at 21:45, Stefan Wahren <stefan.wahren@i2se.com> wrote:
> 
> 
> According to the datasheet busy bit shouldn't be set while changing the clock.
> So this isn't good. I hope this could be fixed, too.
> 

I had hoped that the patch by Eric:
"clk: bcm2835: Fix setting of PLL divider clock rates"
would fix the issue, but that was unfortunately not the case.

Some more investigation using the debugfs patch I had posted,
which exposes the registers showed that:
plld_per_a2w had a value of 4 before starting getty
and a value of 0 after starting getty.

That made me investigate why this value was changed and I found
the culprit in the form of:
@@ -1167,7 +1171,9 @@ static void bcm2835_pll_divider_off(struct clk_hw *hw)
        cprman_write(cprman, data->cm_reg,
                     (cprman_read(cprman, data->cm_reg) &
                      ~data->load_mask) | data->hold_mask);
-       cprman_write(cprman, data->a2w_reg, A2W_PLL_CHANNEL_DISABLE);
+       cprman_write(cprman, data->a2w_reg,
+                    cprman_read(cprman, data->a2w_reg) |
+                       A2W_PLL_CHANNEL_DISABLE);
 }

after that (with plld itself marked as ?prepared? during probe) everything is
working fine.

bcm2835_pll_off shows a similar pattern, but patching that
the same way:
@@ -955,8 +955,12 @@ static void bcm2835_pll_off(struct clk_hw *hw)
        struct bcm2835_cprman *cprman = pll->cprman;
        const struct bcm2835_pll_data *data = pll->data;

-       cprman_write(cprman, data->cm_ctrl_reg, CM_PLL_ANARST);
-       cprman_write(cprman, data->a2w_ctrl_reg, A2W_PLL_CTRL_PWRDN);
+       cprman_write(cprman, data->cm_ctrl_reg,
+                    cprman_read(cprman, data->cm_ctrl_reg) |
+                    CM_PLL_ANARST);
+       cprman_write(cprman, data->a2w_ctrl_reg,
+                    cprman_read(cprman, data->a2w_ctrl_reg) |
+                    A2W_PLL_CTRL_PWRDN);
 }

does not resolve the issue - the system crashes - but without he pll
lock message?

With some debugging messages in place (the register names are
added as a comments indicated via >):

the complete list of writes to the clocks during boot:
[    2.021473] bcm2835_pll_on - pllc - start
[    2.025635] cprman_write - 0x0108 = 0x00000228
> CM_PLLC
[    2.030313] bcm2835_pll_on - pllc - before_wait_pll_lock
[    2.035773] bcm2835_pll_on - pllc - end
[    2.039785] cprman_write - 0x1620 = 0x00000002
> A2W_PLLC_CORE0
[    2.044373] cprman_write - 0x0108 = 0x00000228
> CM_PLLC
[    2.049430] console [ttyS0] disabled
[    2.053237] 20215040.serial: ttyS0 at MMIO 0x0 (irq = 53, base_baud = 31224999) is a 16550
[    2.061878] console [ttyS0] enabled
[    2.069085] bootconsole [earlycon0] disabled
[    2.078668] cprman_write - 0x1520 = 0x00000002
> A2W_PLLC_PER
[    2.083201] cprman_write - 0x0108 = 0x00000228
> CM_PLLC
[    2.087801] cprman_write - 0x01c0 = 0x000002d5
> CM_EMMCCTL
[    2.136432] mmc0: SDHCI controller on 20300000.sdhci [20300000.sdhci] using PIO

dumping the registers for PLLD 
root at raspcm:~# cat /sys/kernel/debug/clk/plld/regdump
cm_ctrl = 0x0000020a
> CM_PLLD
a2w_ctrl = 0x00021034
> A2W_PLLD_PER
frac = 0x00015554
> A2W_PLLD_FRAC
ana0 = 0x00000000
> A2W_PLLD_ANA0
ana1 = 0x00144000
> A2W_PLLD_ANA1
ana2 = 0x00000000
> A2W_PLLD_ANA2
ana3 = 0x00000100
> A2W_PLLD_ANA3

running getty:
root at raspcm:~# /sbin/getty -a root -L ttyAMA0 115200 vt100
[   71.110032] pl011_startup - start
[   71.113452] pl011_hwinit - prepare-enable
[   71.117656] bcm2835_pll_on - plld - start
[   71.121750] cprman_write - 0x010c = 0x0000020a
> CM_PLLD
[   71.126274] bcm2835_pll_on - plld - before_wait_pll_lock
[   71.131728] bcm2835_pll_on - plld - end
[   71.135648] cprman_write - 0x1540 = 0x00000004
> A2W_PLLD_PER
[   71.140228] cprman_write - 0x010c = 0x0000020a
> CM_PLLD
[   71.144760] cprman_write - 0x00f0 = 0x000002d6
> CM_UARTCTL
[   71.149340] pl011_hwinit - prepare-enable - ret = 0
[   71.156743] pl011_startup - exit
[   71.163324] pl011_shutdown - start
[   71.168032] pl011_shutdown - disable_unprepare
[   71.172603] cprman_write - 0x00f0 = 0x00000286
> CM_UARTCTL
[   71.177269] cprman_write - 0x010c = 0x0000028a
> CM_PLLD
[   71.181809] cprman_write - 0x1540 = 0x00000104
> A2W_PLLD_PER
[   71.186334] bcm2835_pll_off - plld - start
[   71.190547] cprman_write - 0x010c = 0x0000038a
> CM_PLLD
[   71.195088] cprman_write - 0x1140 = 0x00031034
> A2W_PLLD_CTRL
[   71.199643] bcm2835_pll_off - plld - end
[   71.203643] pl011_shutdown - exit
[   71.209122] pl011_startup - start
[   71.212522] pl011_hwinit - prepare-enable
[   71.216695] bcm2835_pll_on - plld - start
[   71.220801] cprman_write - 0x010c = 0x0000028a
>  CM_PLLD
[   71.225326] bcm2835_pll_on - plld - before_wait_pll_lock
[   71.230775] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.235840] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.240926] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.245983] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.251067] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.256123] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.261206] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.266272] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.271364] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.276419] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.281523] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.286691] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.291753] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.296838] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.301937] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.307030] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.312087] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.317180] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.322235] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.327319] bcm2835_pll_on - plld - in_pll_lock_loop
[   71.332387] bcm2835-clk 20101000.cprman: plld: couldn't lock PLL
[   71.338532] bcm2835_pll_on - plld - timeout
[   71.342801] pl011_hwinit - prepare-enable - ret = -110
[   71.348080] pl011_startup - error = -110 - disable_unprepare
[   71.353862] ------------[ cut here ]------------
[   71.358593] WARNING: CPU: 0 PID: 2339 at drivers/clk/clk.c:680 clk_core_disab
le+0x34/0xf0()
[   71.367840] ---[ end trace f080e315d858793e ]---
[   71.372614] ------------[ cut here ]------------
[   71.377408] WARNING: CPU: 0 PID: 2339 at drivers/clk/clk.c:575 clk_core_unpre
pare+0x34/0x110()
[   71.387073] ---[ end trace f080e315d858793f ]?

no more activity - system crashed - HDMI looses signal
So disabling PLL itself seems not to be recommended

I could create a patch with the following content as a bandaid:
diff --git a/drivers/clk/bcm/clk-bcm2835.c b/drivers/clk/bcm/clk-bcm2835.c
index 5293338..4dfb8e3 100644
--- a/drivers/clk/bcm/clk-bcm2835.c
+++ b/drivers/clk/bcm/clk-bcm2835.c
@@ -37,6 +37,7 @@
  * generator).
  */

+#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/clk/bcm2835.h>
@@ -1750,6 +1767,9 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
			clks[i] = desc->clk_register(cprman, desc->data);
 	}
 
+	/* prepare PLLD, so that it never gets unprepared */
+	clk_prepare(clks[BCM2835_PLLD]);
+
 	return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
 				   &cprman->onecell);
 }

Note that this this needed on top of the patch to bcm2835_pll_divider_off,
which is applied in the kernel used during reporting...

Martin

  reply	other threads:[~2016-02-16 16:31 UTC|newest]

Thread overview: 33+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-02-10 15:12 serial: clk: bcm2835: Strange effects when using aux-uart in console Martin Sperl
2016-02-10 15:12 ` Martin Sperl
2016-02-10 17:21 ` Stefan Wahren
2016-02-10 17:21   ` Stefan Wahren
2016-02-10 17:42   ` Martin Sperl
2016-02-10 17:42     ` Martin Sperl
2016-02-11 13:15 ` Martin Sperl
2016-02-11 13:15   ` Martin Sperl
2016-02-11 17:55   ` Stefan Wahren
2016-02-11 17:55     ` Stefan Wahren
2016-02-12 11:56     ` Martin Sperl
2016-02-12 11:56       ` Martin Sperl
2016-02-12 17:34       ` Martin Sperl
2016-02-12 17:34         ` Martin Sperl
2016-02-12 19:44         ` Martin Sperl
2016-02-12 19:44           ` Martin Sperl
2016-02-13 10:01           ` Stefan Wahren
2016-02-13 10:01             ` Stefan Wahren
2016-02-13 11:24             ` Martin Sperl
2016-02-13 11:24               ` Martin Sperl
2016-02-16 18:57               ` Michael Turquette
2016-02-16 18:57                 ` Michael Turquette
2016-02-16 18:57                 ` Michael Turquette
2016-02-17 10:43                 ` Martin Sperl
2016-02-17 10:43                   ` Martin Sperl
2016-02-13 11:53             ` Martin Sperl
2016-02-13 11:53               ` Martin Sperl
2016-02-13 20:45               ` Stefan Wahren
2016-02-13 20:45                 ` Stefan Wahren
2016-02-16 16:31                 ` Martin Sperl [this message]
2016-02-16 16:31                   ` Martin Sperl
2016-02-16 19:29                   ` Stefan Wahren
2016-02-16 19:29                     ` Stefan Wahren

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=D4D8C3EE-7BDC-44F4-A54F-A6861FE0A174@martin.sperl.org \
    --to=kernel@martin.sperl.org \
    --cc=eric@anholt.net \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-clk@vger.kernel.org \
    --cc=linux-rpi-kernel@lists.infradead.org \
    --cc=linux-serial@vger.kernel.org \
    --cc=stefan.wahren@i2se.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.