From: Miquel Raynal <miquel.raynal@bootlin.com>
To: masonccyang@mxic.com.tw
Cc: devicetree@vger.kernel.org, christophe.kerello@st.com,
vigneshr@ti.com, jianxin.pan@amlogic.com, bbrezillon@kernel.org,
juliensu@mxic.com.tw, lee.jones@linaro.org,
linux-kernel@vger.kernel.org, stefan@agner.ch,
paul@crapouillou.net, marek.vasut@gmail.com,
paul.burton@mips.com, broonie@kernel.org,
linux-mtd@lists.infradead.org, richard@nod.at,
anders.roxell@linaro.org, liang.yang@amlogic.com,
computersforpeace@gmail.com, dwmw2@infradead.org
Subject: Re: [PATCH v4 1/2] mtd: rawnand: Add Macronix Raw NAND controller
Date: Fri, 28 Jun 2019 09:18:36 +0200 [thread overview]
Message-ID: <20190628091836.3148d450@xps13> (raw)
In-Reply-To: <OFDDC43C05.7B4092B5-ON48258427.001EE57E-48258427.002122D1@mxic.com.tw>
Hi masonccyang@mxic.com.tw,
masonccyang@mxic.com.tw wrote on Fri, 28 Jun 2019 14:01:55 +0800:
> Hi Miquel,
>
>
> > > Add a driver for Macronix raw NAND controller.
> >
> > Could you pass userspace major MTD tests and can you attach/mount/edit
> > a UBI/UBIFS storage?
>
> mtd_debug passed and using dd utility to read and write
> with md5sum checking passed.
Please don't use dd, use nanddump/nandwrite/flasherase/nandbiterrs and
run the other tests from the mtd-utils test suite (available in
Buildroot for instance).
>
> UBI/UBIFS testing is not yet. will do it.
>
>
> > > +static int mxic_nfc_clk_enable(struct mxic_nand_ctlr *nfc)
> > > +{
> > > + int ret;
> > > +
> > > + ret = clk_prepare_enable(nfc->send_clk);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + ret = clk_prepare_enable(nfc->send_dly_clk);
> > > + if (ret)
> > > + goto err_send_dly_clk;
> >
> > I'm not sure why you only enable 2 out of 3 clocks and also why ou
> > handle two of them here (which is great, I prefer having a separate
> > helper for that) and the other one elsewhere?
> >
>
> send_clk and send_dly_clk are device domain clocks.
>
> send_clk is clock without phase delay to ps_clk, used for sending device
> signals except for SIO[7:0].
> send_dly_clk is clock with phase delay to ps_clk, used for sending
> SIO[7:0]
>
> ps_clk is system domain clock and it's a source clock of send_clk and
> send_dly_clk.
And why is that explaining the fact that you configure them in
different places? You can explain this with a nice comment at the top
of the function, but I would rather prefer that you handle all three
clocks in one go if possible.
>
> > > +
> > > + return ret;
> > > +
> > > +err_send_dly_clk:
> > > + clk_disable_unprepare(nfc->send_clk);
> > > +
> > > + return ret;
> > > +}
> > > +
> > > +static void mxic_nfc_clk_disable(struct mxic_nand_ctlr *nfc)
> > > +{
> > > + clk_disable_unprepare(nfc->send_clk);
> > > + clk_disable_unprepare(nfc->send_dly_clk);
> > > +}
> > > +
> > > +static void mxic_nfc_set_input_delay(struct mxic_nand_ctlr *nfc, u8
> idly_code)
> > > +{
> > > + writel(IDLY_CODE_VAL(0, idly_code) |
> > > + IDLY_CODE_VAL(1, idly_code) |
> > > + IDLY_CODE_VAL(2, idly_code) |
> > > + IDLY_CODE_VAL(3, idly_code),
> > > + nfc->regs + IDLY_CODE(0));
> > > + writel(IDLY_CODE_VAL(4, idly_code) |
> > > + IDLY_CODE_VAL(5, idly_code) |
> > > + IDLY_CODE_VAL(6, idly_code) |
> > > + IDLY_CODE_VAL(7, idly_code),
> > > + nfc->regs + IDLY_CODE(1));
> > > +}
> > > +
> > > +static int mxic_nfc_clk_setup(struct mxic_nand_ctlr *nfc, unsigned
> long freq)
> > > +{
> > > + int ret;
> > > +
> > > + ret = clk_set_rate(nfc->send_clk, freq);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + ret = clk_set_rate(nfc->send_dly_clk, freq);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + /*
> > > + * A constant delay range from 0x0 ~ 0x1F for input delay,
> > > + * the unit is 78 ps, the max input delay is 2.418 ns.
> > > + */
> > > + mxic_nfc_set_input_delay(nfc, 0xf);
> > > +
> > > + /*
> > > + * Phase degree = 360 * freq * output-delay
> > > + * where output-delay is a constant value 1 ns in FPGA.
> >
> > Will it always be in FPGA?
>
> yes.
>
> >
> > > + *
> > > + * Get Phase degree = 360 * freq * 1 ns
> > > + * = 360 * freq * 1 sec / 1000000000
> > > + * = 9 * freq / 25000000
> > > + */
> > > + ret = clk_set_phase(nfc->send_dly_clk, 9 * freq / 25000000);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int mxic_nfc_set_freq(struct mxic_nand_ctlr *nfc, unsigned
> long freq)
> > > +{
> > > + int ret;
> > > +
> > > + if (freq > MXIC_NFC_MAX_CLK_HZ)
> > > + freq = MXIC_NFC_MAX_CLK_HZ;
> > > +
> > > + mxic_nfc_clk_disable(nfc);
> > > + ret = mxic_nfc_clk_setup(nfc, freq);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + ret = mxic_nfc_clk_enable(nfc);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static void mxic_nfc_hw_init(struct mxic_nand_ctlr *nfc)
> > > +{
> > > + writel(DATA_STROB_EDO_EN, nfc->regs + DATA_STROB);
> > > + writel(HC_CFG_NIO(8) | HC_CFG_TYPE(1, HC_CFG_TYPE_RAW_NAND) |
> > > + HC_CFG_SLV_ACT(0) | HC_CFG_MAN_CS_EN |
> > > + HC_CFG_IDLE_SIO_LVL(1), nfc->regs + HC_CFG);
> > > + writel(INT_STS_ALL, nfc->regs + INT_STS_EN);
> > > + writel(0x0, nfc->regs + ONFI_DIN_CNT(0));
> > > + writel(0, nfc->regs + LRD_CFG);
> > > + writel(0, nfc->regs + LRD_CTRL);
> > > + writel(0x0, nfc->regs + HC_EN);
> > > +
> > > + /* Default 10 MHz to setup tRC_min/tWC_min:100 ns */
> > > + mxic_nfc_set_freq(nfc, 10000000);
> > > +}
> > > +
> > > +static void mxic_nfc_cs_enable(struct mxic_nand_ctlr *nfc)
> > > +{
> > > + writel(readl(nfc->regs + HC_CFG) | HC_CFG_MAN_CS_EN,
> > > + nfc->regs + HC_CFG);
> > > + writel(HC_CFG_MAN_CS_ASSERT | readl(nfc->regs + HC_CFG),
> > > + nfc->regs + HC_CFG);
> >
> > So you can drive only one CS with this controller?
>
> yes,
>
> >
> > > +}
> > > +
> > > +static void mxic_nfc_cs_disable(struct mxic_nand_ctlr *nfc)
> > > +{
> > > + writel(~HC_CFG_MAN_CS_ASSERT & readl(nfc->regs + HC_CFG),
> > > + nfc->regs + HC_CFG);
> > > +}
> > > +
> > > +static int mxic_nfc_wait_ready(struct nand_chip *chip)
> > > +{
> > > + struct mxic_nand_ctlr *nfc = nand_get_controller_data(chip);
> > > + u32 sts;
> > > +
> > > + return readl_poll_timeout(nfc->regs + INT_STS, sts,
> > > + sts & INT_RDY_PIN, 0, USEC_PER_SEC);
> > > +}
> > > +
> > > +static int mxic_nfc_data_xfer(struct mxic_nand_ctlr *nfc, const void
> *txbuf,
> > > + void *rxbuf, unsigned int len)
> > > +{
> > > + unsigned int pos = 0;
> > > +
> > > + while (pos < len) {
> > > + unsigned int nbytes = len - pos;
> > > + u32 data = 0xffffffff;
> > > + u32 sts;
> > > + int ret;
> > > +
> > > + if (nbytes > 4)
> > > + nbytes = 4;
> > > +
> > > + if (txbuf)
> > > + memcpy(&data, txbuf + pos, nbytes);
> > > +
> > > + ret = readl_poll_timeout(nfc->regs + INT_STS, sts,
> > > + sts & INT_TX_EMPTY, 0, USEC_PER_SEC);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + writel(data, nfc->regs + TXD(nbytes % 4));
> > > +
> > > + if (rxbuf) {
> > > + ret = readl_poll_timeout(nfc->regs + INT_STS, sts,
> > > + sts & INT_TX_EMPTY, 0,
> > > + USEC_PER_SEC);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + ret = readl_poll_timeout(nfc->regs + INT_STS, sts,
> > > + sts & INT_RX_NOT_EMPTY, 0,
> > > + USEC_PER_SEC);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + data = readl(nfc->regs + RXD);
> > > + data >>= (8 * (4 - nbytes));
> > > + memcpy(rxbuf + pos, &data, nbytes);
> > > + WARN_ON(readl(nfc->regs + INT_STS) & INT_RX_NOT_EMPTY);
> > > + } else {
> > > + readl(nfc->regs + RXD);
> > > + }
> > > + WARN_ON(readl(nfc->regs + INT_STS) & INT_RX_NOT_EMPTY);
> >
> > WARN_ON() is maybe a bit overkill here?
>
> should I remove it ?
I would stick to regular dev_warn.
Thanks,
Miquèl
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
WARNING: multiple messages have this Message-ID (diff)
From: Miquel Raynal <miquel.raynal@bootlin.com>
To: masonccyang@mxic.com.tw
Cc: anders.roxell@linaro.org, bbrezillon@kernel.org,
broonie@kernel.org, christophe.kerello@st.com,
computersforpeace@gmail.com, devicetree@vger.kernel.org,
dwmw2@infradead.org, jianxin.pan@amlogic.com,
juliensu@mxic.com.tw, lee.jones@linaro.org,
liang.yang@amlogic.com, linux-kernel@vger.kernel.org,
linux-mtd@lists.infradead.org, marek.vasut@gmail.com,
paul@crapouillou.net, paul.burton@mips.com, richard@nod.at,
stefan@agner.ch, vigneshr@ti.com
Subject: Re: [PATCH v4 1/2] mtd: rawnand: Add Macronix Raw NAND controller
Date: Fri, 28 Jun 2019 09:18:36 +0200 [thread overview]
Message-ID: <20190628091836.3148d450@xps13> (raw)
In-Reply-To: <OFDDC43C05.7B4092B5-ON48258427.001EE57E-48258427.002122D1@mxic.com.tw>
Hi masonccyang@mxic.com.tw,
masonccyang@mxic.com.tw wrote on Fri, 28 Jun 2019 14:01:55 +0800:
> Hi Miquel,
>
>
> > > Add a driver for Macronix raw NAND controller.
> >
> > Could you pass userspace major MTD tests and can you attach/mount/edit
> > a UBI/UBIFS storage?
>
> mtd_debug passed and using dd utility to read and write
> with md5sum checking passed.
Please don't use dd, use nanddump/nandwrite/flasherase/nandbiterrs and
run the other tests from the mtd-utils test suite (available in
Buildroot for instance).
>
> UBI/UBIFS testing is not yet. will do it.
>
>
> > > +static int mxic_nfc_clk_enable(struct mxic_nand_ctlr *nfc)
> > > +{
> > > + int ret;
> > > +
> > > + ret = clk_prepare_enable(nfc->send_clk);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + ret = clk_prepare_enable(nfc->send_dly_clk);
> > > + if (ret)
> > > + goto err_send_dly_clk;
> >
> > I'm not sure why you only enable 2 out of 3 clocks and also why ou
> > handle two of them here (which is great, I prefer having a separate
> > helper for that) and the other one elsewhere?
> >
>
> send_clk and send_dly_clk are device domain clocks.
>
> send_clk is clock without phase delay to ps_clk, used for sending device
> signals except for SIO[7:0].
> send_dly_clk is clock with phase delay to ps_clk, used for sending
> SIO[7:0]
>
> ps_clk is system domain clock and it's a source clock of send_clk and
> send_dly_clk.
And why is that explaining the fact that you configure them in
different places? You can explain this with a nice comment at the top
of the function, but I would rather prefer that you handle all three
clocks in one go if possible.
>
> > > +
> > > + return ret;
> > > +
> > > +err_send_dly_clk:
> > > + clk_disable_unprepare(nfc->send_clk);
> > > +
> > > + return ret;
> > > +}
> > > +
> > > +static void mxic_nfc_clk_disable(struct mxic_nand_ctlr *nfc)
> > > +{
> > > + clk_disable_unprepare(nfc->send_clk);
> > > + clk_disable_unprepare(nfc->send_dly_clk);
> > > +}
> > > +
> > > +static void mxic_nfc_set_input_delay(struct mxic_nand_ctlr *nfc, u8
> idly_code)
> > > +{
> > > + writel(IDLY_CODE_VAL(0, idly_code) |
> > > + IDLY_CODE_VAL(1, idly_code) |
> > > + IDLY_CODE_VAL(2, idly_code) |
> > > + IDLY_CODE_VAL(3, idly_code),
> > > + nfc->regs + IDLY_CODE(0));
> > > + writel(IDLY_CODE_VAL(4, idly_code) |
> > > + IDLY_CODE_VAL(5, idly_code) |
> > > + IDLY_CODE_VAL(6, idly_code) |
> > > + IDLY_CODE_VAL(7, idly_code),
> > > + nfc->regs + IDLY_CODE(1));
> > > +}
> > > +
> > > +static int mxic_nfc_clk_setup(struct mxic_nand_ctlr *nfc, unsigned
> long freq)
> > > +{
> > > + int ret;
> > > +
> > > + ret = clk_set_rate(nfc->send_clk, freq);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + ret = clk_set_rate(nfc->send_dly_clk, freq);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + /*
> > > + * A constant delay range from 0x0 ~ 0x1F for input delay,
> > > + * the unit is 78 ps, the max input delay is 2.418 ns.
> > > + */
> > > + mxic_nfc_set_input_delay(nfc, 0xf);
> > > +
> > > + /*
> > > + * Phase degree = 360 * freq * output-delay
> > > + * where output-delay is a constant value 1 ns in FPGA.
> >
> > Will it always be in FPGA?
>
> yes.
>
> >
> > > + *
> > > + * Get Phase degree = 360 * freq * 1 ns
> > > + * = 360 * freq * 1 sec / 1000000000
> > > + * = 9 * freq / 25000000
> > > + */
> > > + ret = clk_set_phase(nfc->send_dly_clk, 9 * freq / 25000000);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static int mxic_nfc_set_freq(struct mxic_nand_ctlr *nfc, unsigned
> long freq)
> > > +{
> > > + int ret;
> > > +
> > > + if (freq > MXIC_NFC_MAX_CLK_HZ)
> > > + freq = MXIC_NFC_MAX_CLK_HZ;
> > > +
> > > + mxic_nfc_clk_disable(nfc);
> > > + ret = mxic_nfc_clk_setup(nfc, freq);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + ret = mxic_nfc_clk_enable(nfc);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + return 0;
> > > +}
> > > +
> > > +static void mxic_nfc_hw_init(struct mxic_nand_ctlr *nfc)
> > > +{
> > > + writel(DATA_STROB_EDO_EN, nfc->regs + DATA_STROB);
> > > + writel(HC_CFG_NIO(8) | HC_CFG_TYPE(1, HC_CFG_TYPE_RAW_NAND) |
> > > + HC_CFG_SLV_ACT(0) | HC_CFG_MAN_CS_EN |
> > > + HC_CFG_IDLE_SIO_LVL(1), nfc->regs + HC_CFG);
> > > + writel(INT_STS_ALL, nfc->regs + INT_STS_EN);
> > > + writel(0x0, nfc->regs + ONFI_DIN_CNT(0));
> > > + writel(0, nfc->regs + LRD_CFG);
> > > + writel(0, nfc->regs + LRD_CTRL);
> > > + writel(0x0, nfc->regs + HC_EN);
> > > +
> > > + /* Default 10 MHz to setup tRC_min/tWC_min:100 ns */
> > > + mxic_nfc_set_freq(nfc, 10000000);
> > > +}
> > > +
> > > +static void mxic_nfc_cs_enable(struct mxic_nand_ctlr *nfc)
> > > +{
> > > + writel(readl(nfc->regs + HC_CFG) | HC_CFG_MAN_CS_EN,
> > > + nfc->regs + HC_CFG);
> > > + writel(HC_CFG_MAN_CS_ASSERT | readl(nfc->regs + HC_CFG),
> > > + nfc->regs + HC_CFG);
> >
> > So you can drive only one CS with this controller?
>
> yes,
>
> >
> > > +}
> > > +
> > > +static void mxic_nfc_cs_disable(struct mxic_nand_ctlr *nfc)
> > > +{
> > > + writel(~HC_CFG_MAN_CS_ASSERT & readl(nfc->regs + HC_CFG),
> > > + nfc->regs + HC_CFG);
> > > +}
> > > +
> > > +static int mxic_nfc_wait_ready(struct nand_chip *chip)
> > > +{
> > > + struct mxic_nand_ctlr *nfc = nand_get_controller_data(chip);
> > > + u32 sts;
> > > +
> > > + return readl_poll_timeout(nfc->regs + INT_STS, sts,
> > > + sts & INT_RDY_PIN, 0, USEC_PER_SEC);
> > > +}
> > > +
> > > +static int mxic_nfc_data_xfer(struct mxic_nand_ctlr *nfc, const void
> *txbuf,
> > > + void *rxbuf, unsigned int len)
> > > +{
> > > + unsigned int pos = 0;
> > > +
> > > + while (pos < len) {
> > > + unsigned int nbytes = len - pos;
> > > + u32 data = 0xffffffff;
> > > + u32 sts;
> > > + int ret;
> > > +
> > > + if (nbytes > 4)
> > > + nbytes = 4;
> > > +
> > > + if (txbuf)
> > > + memcpy(&data, txbuf + pos, nbytes);
> > > +
> > > + ret = readl_poll_timeout(nfc->regs + INT_STS, sts,
> > > + sts & INT_TX_EMPTY, 0, USEC_PER_SEC);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + writel(data, nfc->regs + TXD(nbytes % 4));
> > > +
> > > + if (rxbuf) {
> > > + ret = readl_poll_timeout(nfc->regs + INT_STS, sts,
> > > + sts & INT_TX_EMPTY, 0,
> > > + USEC_PER_SEC);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + ret = readl_poll_timeout(nfc->regs + INT_STS, sts,
> > > + sts & INT_RX_NOT_EMPTY, 0,
> > > + USEC_PER_SEC);
> > > + if (ret)
> > > + return ret;
> > > +
> > > + data = readl(nfc->regs + RXD);
> > > + data >>= (8 * (4 - nbytes));
> > > + memcpy(rxbuf + pos, &data, nbytes);
> > > + WARN_ON(readl(nfc->regs + INT_STS) & INT_RX_NOT_EMPTY);
> > > + } else {
> > > + readl(nfc->regs + RXD);
> > > + }
> > > + WARN_ON(readl(nfc->regs + INT_STS) & INT_RX_NOT_EMPTY);
> >
> > WARN_ON() is maybe a bit overkill here?
>
> should I remove it ?
I would stick to regular dev_warn.
Thanks,
Miquèl
next prev parent reply other threads:[~2019-06-28 7:19 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2019-06-25 6:10 [PATCH v4 0/2] Add Macronix Raw NAND controller driver Mason Yang
2019-06-25 6:10 ` Mason Yang
2019-06-25 6:10 ` [PATCH v4 1/2] mtd: rawnand: Add Macronix Raw NAND controller Mason Yang
2019-06-25 6:10 ` Mason Yang
2019-06-27 17:36 ` Miquel Raynal
2019-06-27 17:36 ` Miquel Raynal
2019-06-28 6:01 ` masonccyang
2019-06-28 6:01 ` masonccyang
2019-06-28 7:18 ` Miquel Raynal [this message]
2019-06-28 7:18 ` Miquel Raynal
2019-06-28 8:31 ` masonccyang
2019-06-28 8:31 ` masonccyang
2019-06-28 8:44 ` Miquel Raynal
2019-06-28 8:44 ` Miquel Raynal
2019-07-03 3:03 ` masonccyang
2019-07-03 3:03 ` masonccyang
2019-06-25 6:10 ` [PATCH v4 2/2] dt-bindings: mtd: Document Macronix raw NAND controller bindings Mason Yang
2019-06-25 6:10 ` Mason Yang
2019-06-27 17:26 ` Miquel Raynal
2019-06-27 17:26 ` Miquel Raynal
2019-06-28 6:48 ` masonccyang
2019-06-28 6:48 ` masonccyang
2019-06-28 7:42 ` Miquel Raynal
2019-06-28 7:42 ` Miquel Raynal
2019-06-28 9:09 ` masonccyang
2019-06-28 9:09 ` masonccyang
2019-06-28 9:12 ` Miquel Raynal
2019-06-28 9:12 ` Miquel Raynal
2019-06-28 9:23 ` masonccyang
2019-06-28 9:23 ` masonccyang
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=20190628091836.3148d450@xps13 \
--to=miquel.raynal@bootlin.com \
--cc=anders.roxell@linaro.org \
--cc=bbrezillon@kernel.org \
--cc=broonie@kernel.org \
--cc=christophe.kerello@st.com \
--cc=computersforpeace@gmail.com \
--cc=devicetree@vger.kernel.org \
--cc=dwmw2@infradead.org \
--cc=jianxin.pan@amlogic.com \
--cc=juliensu@mxic.com.tw \
--cc=lee.jones@linaro.org \
--cc=liang.yang@amlogic.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mtd@lists.infradead.org \
--cc=marek.vasut@gmail.com \
--cc=masonccyang@mxic.com.tw \
--cc=paul.burton@mips.com \
--cc=paul@crapouillou.net \
--cc=richard@nod.at \
--cc=stefan@agner.ch \
--cc=vigneshr@ti.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.