diff mbox

[v2,6/6] serial: imx: implement DSR irq handling for DTE mode

Message ID 1458825865-7434-7-git-send-email-u.kleine-koenig@pengutronix.de
State New
Headers show

Commit Message

Uwe Kleine-König March 24, 2016, 1:24 p.m. UTC
Enable reporting of DSR events (which is named DTR in the registers
because Freescale uses the names as seem from a DCE).

Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
---
 drivers/tty/serial/imx.c | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

Comments

Uwe Kleine-König Aug. 5, 2016, 6:58 a.m. UTC | #1
Hello Christoph,

Cc += Shawn, Fabio

On Fri, Aug 05, 2016 at 12:44:23AM +0200, Christoph Fritz wrote:
> here on a imx6sx board newly introduced DSR-irq-handling breaks serial
> console and network support.
> 
> Reverting commit 27e16501052e5341934d3 "serial: imx: implement DSR irq
> handling for DTE mode" fixes the issue.
> 
> The underlying cause is the RMII network configuration where register
> bit SION in IOMUXC_SW_MUX_CTL_PAD_ENET1_TX_CLK is necessary. But this
> also falsely feeds signal UART1_DTR_B and triggers DSR irq...
> 
> Can we revert this commit or add a quirk for RMII-SION configs or make
> this optional by a device tree option?

Hmm, MX6SX_PAD_ENET1_TX_CLK__ENET1_TX_CLK in
arch/arm/boot/dts/imx6sx-pinfunc.h doesn't have SION set.

I remember there were issues around eth and SION on i.MX6DL, but don't
know the details. A quick net research found
https://community.nxp.com/thread/359531 which has: "Set the SION bit.
Note that this is not required because the funtion setting controls the
signal path, but it is good practice as it reminds the user that the
clock needs to fed back into the Ethernet MAC.". Sounds like dangerous
smattering and a wrong expectation about "users".

https://community.nxp.com/thread/376821 is from someone who has the same
problem(?) on i.MX6SX, but no solution yet.

Does that mean MX6SX_PAD_ENET1_TX_CLK__ENET1_TX_CLK always needs the
SION bit set? Even if not, I'd like to have that documented there,
similar to da4fa6fa8016 ("ARM: imx25-pinfunc: document SION being
important for MX25_PAD_SD1_CMD__SD1_CMD").

Once this is done (and still an issue) I'd suggest to standardize a dt
property

	disable-dsr;

(and the same for the other handshaking lines) and support th{is,ese} in
the imx uart driver. Reverting 27e16501052e IMO isn't a sensible option.

Best regards
Uwe
Christoph Fritz Aug. 5, 2016, 12:03 p.m. UTC | #2
On Fri, 2016-08-05 at 08:58 +0200, Uwe Kleine-König wrote:
> On Fri, Aug 05, 2016 at 12:44:23AM +0200, Christoph Fritz wrote:
> > here on a imx6sx board newly introduced DSR-irq-handling breaks serial
> > console and network support.
> > 
> > Reverting commit 27e16501052e5341934d3 "serial: imx: implement DSR irq
> > handling for DTE mode" fixes the issue.
> > 
> > The underlying cause is the RMII network configuration where register
> > bit SION in IOMUXC_SW_MUX_CTL_PAD_ENET1_TX_CLK is necessary. But this
> > also falsely feeds signal UART1_DTR_B and triggers DSR irq...
> > 
> > Can we revert this commit or add a quirk for RMII-SION configs or make
> > this optional by a device tree option?
> 
> Hmm, MX6SX_PAD_ENET1_TX_CLK__ENET1_TX_CLK in
> arch/arm/boot/dts/imx6sx-pinfunc.h doesn't have SION set.
> 
> I remember there were issues around eth and SION on i.MX6DL, but don't
> know the details. A quick net research found
> https://community.nxp.com/thread/359531 which has: "Set the SION bit.
> Note that this is not required because the funtion setting controls the
> signal path, but it is good practice as it reminds the user that the
> clock needs to fed back into the Ethernet MAC.". Sounds like dangerous
> smattering and a wrong expectation about "users".
> 
> https://community.nxp.com/thread/376821 is from someone who has the same
> problem(?) on i.MX6SX, but no solution yet.
> 
> Does that mean MX6SX_PAD_ENET1_TX_CLK__ENET1_TX_CLK always needs the
> SION bit set?

SION is necessary for pinconfig MX6SX_PAD_ENET1_TX_CLK__ENET1_REF_CLK1
if bit 17 in IOMUXC_GPR_GPR1 is set and bit 13 not.

So that ref_enetpll1 provides a clock not only for the external PHY but
also for the internal controller.

Using SION is a quirk here, because the silicon doesn't feed the clock
back to the internal controller automatically.

On the other hand, NXP could argue: You need to add a wire on your PCB
between ENET1_REF_CLK1 and ENET1_TX_CLK -- but referring to the
datasheet ENET1_TX_CLK isn't used in RMII config...

So if Fabio or Shawn agrees with my assumption above, I'll add something
like 27e16501052e5341934d3 "serial: imx: implement DSR irq
handling for DTE mode".

Okay?
Fabio Estevam Aug. 10, 2016, 8:54 p.m. UTC | #3
Hi Christoph,

On Fri, Aug 5, 2016 at 9:03 AM, Christoph Fritz
<chf.fritz@googlemail.com> wrote:

> SION is necessary for pinconfig MX6SX_PAD_ENET1_TX_CLK__ENET1_REF_CLK1
> if bit 17 in IOMUXC_GPR_GPR1 is set and bit 13 not.
>
> So that ref_enetpll1 provides a clock not only for the external PHY but
> also for the internal controller.
>
> Using SION is a quirk here, because the silicon doesn't feed the clock
> back to the internal controller automatically.
>
> On the other hand, NXP could argue: You need to add a wire on your PCB
> between ENET1_REF_CLK1 and ENET1_TX_CLK -- but referring to the
> datasheet ENET1_TX_CLK isn't used in RMII config...
>
> So if Fabio or Shawn agrees with my assumption above, I'll add something
> like 27e16501052e5341934d3 "serial: imx: implement DSR irq
> handling for DTE mode".
>
> Okay?

Could you please post your suggestion as a patch or RFC so that we can
understand what your proposal is?

Thanks
Uwe Kleine-König Aug. 15, 2016, 5:22 a.m. UTC | #4
Hello Christoph,

On Sat, Aug 13, 2016 at 10:35:32PM +0200, Christoph Fritz wrote:
> On Wed, 2016-08-10 at 17:54 -0300, Fabio Estevam wrote:
> > Could you please post your suggestion as a patch or RFC so that we can
> > understand what your proposal is?
> 
> Sure, here is my proposal:

I like it, just a few minor nits below.

> +/*
> + * SION bit is necessary for ENET1_REF_CLK1 (ENET2_REF_CLK2 untested) if it is
> + * used as clock output of IMX6SX_CLK_ENET_REF (ENET1_TX_CLK) to e.g. supply a
> + * PHY in RMII mode. This configuration is true if:

Sounds a bit strage to me. Maybe s/true/necessary/? Or "valid"?

> + *  - bit 1 in field IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK is set
> + *  - bit 1 in field IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_MASK unset
> + * It seems to be a silicon bug that in this configuration ENET1_TX reference
> + * clock isn't provided automatically.  According to i.mx6sx reference manual

s/i.mx6sx/i.MX6SX/

> + * (IOMUXC_GPR_GPR1 field descriptions: ENET1_CLK_SEL, Rev. 0 from 2/2015) it
> + * should be the case.
> + * This might have side effects for other hardware units that are connected to
> + * that pin and use the respective function as input (e.g. DSR irq handling).

s/DSR irq/UART1's DTR/. Then it's more obvious to relate to
MX6SX_PAD_ENET1_TX_CLK__UART1_DTR_B.

> + */
>  #define MX6SX_PAD_ENET1_TX_CLK__ENET1_REF_CLK1                    0x0090 0x03D8 0x0760 0x1 0x1
>  #define MX6SX_PAD_ENET1_TX_CLK__AUDMUX_AUD4_RXD                   0x0090 0x03D8 0x0644 0x2 0x1
>  #define MX6SX_PAD_ENET1_TX_CLK__UART1_DTR_B                       0x0090 0x03D8 0x0000 0x3 0x0

Thanks
Uwe
Fabio Estevam Aug. 17, 2016, 2:26 p.m. UTC | #5
Hi Christoph,

On Wed, Aug 17, 2016 at 6:25 AM, Christoph Fritz
<chf.fritz@googlemail.com> wrote:

> +/*
> + * SION bit is necessary for ENET1_REF_CLK1 (ENET2_REF_CLK2 untested) if it is
> + * used as clock output of IMX6SX_CLK_ENET_REF (ENET1_TX_CLK) to e.g. supply a
> + * PHY in RMII mode. This configuration is valid if:
> + *  - bit 1 in field IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK is set
> + *  - bit 1 in field IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_MASK unset

So in your case the imx6sx_enet_clk_sel() does not do what you need:

static void __init imx6sx_enet_clk_sel(void)
{
    struct regmap *gpr;

    gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sx-iomuxc-gpr");
    if (!IS_ERR(gpr)) {
        regmap_update_bits(gpr, IOMUXC_GPR1,
                   IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_MASK, 0);
        regmap_update_bits(gpr, IOMUXC_GPR1,
                   IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK, 0);
    } else {
        pr_err("failed to find fsl,imx6sx-iomux-gpr regmap\n");
    }
}

It seems that it is not a good idea to have imx6sx_enet_clk_sel() in
common code as the GPR1 setting can change from board to board.

I think we need the fec driver to be in charge of configuring the GPR1 register.

This is unrelated to your patch though :-)
Christoph Fritz Aug. 17, 2016, 6:03 p.m. UTC | #6
On Wed, 2016-08-17 at 11:26 -0300, Fabio Estevam wrote:
> Hi Christoph,
> 
> On Wed, Aug 17, 2016 at 6:25 AM, Christoph Fritz
> <chf.fritz@googlemail.com> wrote:
> 
> > +/*
> > + * SION bit is necessary for ENET1_REF_CLK1 (ENET2_REF_CLK2 untested) if it is
> > + * used as clock output of IMX6SX_CLK_ENET_REF (ENET1_TX_CLK) to e.g. supply a
> > + * PHY in RMII mode. This configuration is valid if:
> > + *  - bit 1 in field IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK is set
> > + *  - bit 1 in field IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_MASK unset
> 
> So in your case the imx6sx_enet_clk_sel() does not do what you need:
> 
> static void __init imx6sx_enet_clk_sel(void)
> {
>     struct regmap *gpr;
> 
>     gpr = syscon_regmap_lookup_by_compatible("fsl,imx6sx-iomuxc-gpr");
>     if (!IS_ERR(gpr)) {
>         regmap_update_bits(gpr, IOMUXC_GPR1,
>                    IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_MASK, 0);
>         regmap_update_bits(gpr, IOMUXC_GPR1,
>                    IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK, 0);
>     } else {
>         pr_err("failed to find fsl,imx6sx-iomux-gpr regmap\n");
>     }
> }
> 
> It seems that it is not a good idea to have imx6sx_enet_clk_sel() in
> common code as the GPR1 setting can change from board to board.

Yes, currently I'm adapting/quirking the fec config there and in
imx6sx_clocks_init() to set the Phy-Clock-Frequency to 50Mhz.

> I think we need the fec driver to be in charge of configuring the GPR1 register.

What about making the Phy-Clock-Frequency IMX6SX_CLK_ENET_REF
adjustable?

> This is unrelated to your patch though :-)

Thanks
 -- Christoph
Christoph Fritz Aug. 22, 2016, 3:08 p.m. UTC | #7
On Wed, 2016-08-17 at 11:25 +0200, Christoph Fritz wrote:
> Signed-off-by: Christoph Fritz <chf.fritz@googlemail.com>
> ---
>  arch/arm/boot/dts/imx6sx-pinfunc.h | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/imx6sx-pinfunc.h b/arch/arm/boot/dts/imx6sx-pinfunc.h
> index bb9c6b7..42c4c80 100644
> --- a/arch/arm/boot/dts/imx6sx-pinfunc.h
> +++ b/arch/arm/boot/dts/imx6sx-pinfunc.h
> @@ -308,6 +308,20 @@
>  #define MX6SX_PAD_ENET1_RX_CLK__VDEC_DEBUG_35                     0x008C 0x03D4 0x0000 0x8 0x0
>  #define MX6SX_PAD_ENET1_RX_CLK__PCIE_CTRL_DEBUG_29                0x008C 0x03D4 0x0000 0x9 0x0
>  #define MX6SX_PAD_ENET1_TX_CLK__ENET1_TX_CLK                      0x0090 0x03D8 0x0000 0x0 0x0
> +/*
> + * SION bit is necessary for ENET1_REF_CLK1 (ENET2_REF_CLK2 untested) if it is
> + * used as clock output of IMX6SX_CLK_ENET_REF (ENET1_TX_CLK) to e.g. supply a
> + * PHY in RMII mode. This configuration is valid if:
> + *  - bit 1 in field IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK is set
> + *  - bit 1 in field IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_MASK unset
> + * It seems to be a silicon bug that in this configuration ENET1_TX reference
> + * clock isn't provided automatically.  According to i.MX6SX reference manual
> + * (IOMUXC_GPR_GPR1 field descriptions: ENET1_CLK_SEL, Rev. 0 from 2/2015) it
> + * should be the case.
> + * So this might have unwanted side effects for other hardware units that are
> + * also connected to that pin and using respective function as input (e.g.
> + * UART1's DTR handling on MX6SX_PAD_ENET1_TX_CLK__UART1_DTR_B).
> + */
>  #define MX6SX_PAD_ENET1_TX_CLK__ENET1_REF_CLK1                    0x0090 0x03D8 0x0760 0x1 0x1
>  #define MX6SX_PAD_ENET1_TX_CLK__AUDMUX_AUD4_RXD                   0x0090 0x03D8 0x0644 0x2 0x1
>  #define MX6SX_PAD_ENET1_TX_CLK__UART1_DTR_B                       0x0090 0x03D8 0x0000 0x3 0x0

@Uwe and Fabio: Can I get your Ack on this?
@Shawn: Can you queue this patch for upstream?
Shawn Guo Aug. 29, 2016, 1:18 a.m. UTC | #8
On Wed, Aug 17, 2016 at 11:25:31AM +0200, Christoph Fritz wrote:
> 
> Signed-off-by: Christoph Fritz <chf.fritz@googlemail.com>

Applied, thanks.

> ---
>  arch/arm/boot/dts/imx6sx-pinfunc.h | 14 ++++++++++++++
>  1 file changed, 14 insertions(+)
> 
> diff --git a/arch/arm/boot/dts/imx6sx-pinfunc.h b/arch/arm/boot/dts/imx6sx-pinfunc.h
> index bb9c6b7..42c4c80 100644
> --- a/arch/arm/boot/dts/imx6sx-pinfunc.h
> +++ b/arch/arm/boot/dts/imx6sx-pinfunc.h
> @@ -308,6 +308,20 @@
>  #define MX6SX_PAD_ENET1_RX_CLK__VDEC_DEBUG_35                     0x008C 0x03D4 0x0000 0x8 0x0
>  #define MX6SX_PAD_ENET1_RX_CLK__PCIE_CTRL_DEBUG_29                0x008C 0x03D4 0x0000 0x9 0x0
>  #define MX6SX_PAD_ENET1_TX_CLK__ENET1_TX_CLK                      0x0090 0x03D8 0x0000 0x0 0x0
> +/*
> + * SION bit is necessary for ENET1_REF_CLK1 (ENET2_REF_CLK2 untested) if it is
> + * used as clock output of IMX6SX_CLK_ENET_REF (ENET1_TX_CLK) to e.g. supply a
> + * PHY in RMII mode. This configuration is valid if:
> + *  - bit 1 in field IMX6SX_GPR1_FEC_CLOCK_PAD_DIR_MASK is set
> + *  - bit 1 in field IMX6SX_GPR1_FEC_CLOCK_MUX_SEL_MASK unset
> + * It seems to be a silicon bug that in this configuration ENET1_TX reference
> + * clock isn't provided automatically.  According to i.MX6SX reference manual
> + * (IOMUXC_GPR_GPR1 field descriptions: ENET1_CLK_SEL, Rev. 0 from 2/2015) it
> + * should be the case.
> + * So this might have unwanted side effects for other hardware units that are
> + * also connected to that pin and using respective function as input (e.g.
> + * UART1's DTR handling on MX6SX_PAD_ENET1_TX_CLK__UART1_DTR_B).
> + */
>  #define MX6SX_PAD_ENET1_TX_CLK__ENET1_REF_CLK1                    0x0090 0x03D8 0x0760 0x1 0x1
>  #define MX6SX_PAD_ENET1_TX_CLK__AUDMUX_AUD4_RXD                   0x0090 0x03D8 0x0644 0x2 0x1
>  #define MX6SX_PAD_ENET1_TX_CLK__UART1_DTR_B                       0x0090 0x03D8 0x0000 0x3 0x0
> -- 
> 2.1.4
> 
> 
> _______________________________________________
> linux-arm-kernel mailing list
> linux-arm-kernel@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
Christoph Fritz Nov. 21, 2016, 11 a.m. UTC | #9
Hey Uwe

On Fri, 2016-08-05 at 08:58 +0200, Uwe Kleine-König wrote:
> Once this is done (and still an issue)

Yes, patch b5ca028fe9ba2090a (ARM: dts: imx6sx: document SION necessity
of ENET1_REF_CLK1) is done and mainline and DSR irq handling is still an
issue.

>  I'd suggest to standardize a dt
> property
> 
> 	disable-dsr;

Would you go forward?

> (and the same for the other handshaking lines) and support th{is,ese} in
> the imx uart driver. Reverting 27e16501052e IMO isn't a sensible option.

Okay, I'm fine with a 'disable-dsr' solution.

Thanks
  -- Christoph
Uwe Kleine-König Nov. 21, 2016, 11:07 a.m. UTC | #10
Hello Christoph,

On Mon, Nov 21, 2016 at 12:00:11PM +0100, Christoph Fritz wrote:
> On Fri, 2016-08-05 at 08:58 +0200, Uwe Kleine-König wrote:
> > Once this is done (and still an issue)
> 
> Yes, patch b5ca028fe9ba2090a (ARM: dts: imx6sx: document SION necessity
> of ENET1_REF_CLK1) is done and mainline and DSR irq handling is still an
> issue.
> 
> >  I'd suggest to standardize a dt
> > property
> > 
> > 	disable-dsr;
> 
> Would you go forward?

Currently I don't have the need and time to do this myself. So if you
want to propose a patch and send if for review to the dt and serial MLs
that would be a good next step. If you add me to Cc (or To) I can take a
look.

Best regards
Uwe
diff mbox

Patch

diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index c07e652f8f58..621e488cbb12 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -114,6 +114,7 @@ 
 #define UCR3_RXDSEN	(1<<6)	/* Receive status interrupt enable */
 #define UCR3_AIRINTEN	(1<<5)	/* Async IR wake interrupt enable */
 #define UCR3_AWAKEN	(1<<4)	/* Async wake interrupt enable */
+#define UCR3_DTRDEN	(1<<3)	/* Data Terminal Ready Delta Enable. */
 #define IMX21_UCR3_RXDMUXSEL	(1<<2)	/* RXD Muxed Input Select */
 #define UCR3_INVT	(1<<1)	/* Inverted Infrared transmission */
 #define UCR3_BPEN	(1<<0)	/* Preset registers enable */
@@ -142,7 +143,7 @@ 
 #define USR1_FRAMERR	(1<<10) /* Frame error interrupt flag */
 #define USR1_RRDY	(1<<9)	 /* Receiver ready interrupt/dma flag */
 #define USR1_AGTIM	(1<<8)	 /* Ageing timer interrupt flag */
-#define USR1_TIMEOUT	(1<<7)	 /* Receive timeout interrupt status */
+#define USR1_DTRD	(1<<7)	 /* DTR Delta */
 #define USR1_RXDS	 (1<<6)	 /* Receiver idle interrupt flag */
 #define USR1_AIRINT	 (1<<5)	 /* Async IR wake interrupt flag */
 #define USR1_AWAKE	 (1<<4)	 /* Aysnc wake interrupt flag */
@@ -804,6 +805,19 @@  static irqreturn_t imx_int(int irq, void *dev_id)
 		ret = IRQ_HANDLED;
 	}
 
+	if (sts & USR1_DTRD) {
+		unsigned long flags;
+
+		if (sts & USR1_DTRD)
+			writel(USR1_DTRD, sport->port.membase + USR1);
+
+		spin_lock_irqsave(&sport->port.lock, flags);
+		imx_mctrl_check(sport);
+		spin_unlock_irqrestore(&sport->port.lock, flags);
+
+		ret = IRQ_HANDLED;
+	}
+
 	if (sts & USR1_RTSD) {
 		imx_rtsint(irq, dev_id);
 		ret = IRQ_HANDLED;
@@ -1202,7 +1216,7 @@  static int imx_startup(struct uart_port *port)
 	/*
 	 * Finally, clear and enable interrupts
 	 */
-	writel(USR1_RTSD, sport->port.membase + USR1);
+	writel(USR1_RTSD | USR1_DTRD, sport->port.membase + USR1);
 	writel(USR2_ORE, sport->port.membase + USR2);
 
 	if (sport->dma_is_inited && !sport->dma_is_enabled)
@@ -1242,7 +1256,7 @@  static int imx_startup(struct uart_port *port)
 		 * now, too.
 		 */
 		temp |= IMX21_UCR3_RXDMUXSEL | UCR3_ADNIMP |
-			UCR3_RI | UCR3_DCD;
+			UCR3_DTRDEN | UCR3_RI | UCR3_DCD;
 
 		if (sport->dte_mode)
 			temp &= ~(UCR3_RI | UCR3_DCD);