Hi Jagan

My upstream topic status is Awaiting Upstream.
but now Meta needs to use this driver.
What could I do to make it merge fast?

Best regards,
Jim





On Thu, Oct 27, 2022 at 2:57 PM jjl...@nuvoton.com <jjl...@nuvoton.com> wrote:
>
> fyi
>
> -----Original Message-----
> From: Jim Liu <jim.t90...@gmail.com>
> Sent: Tuesday, May 31, 2022 6:14 PM
> To: CS20 JJLiu0 <jjl...@nuvoton.com>; ja...@amarulasolutions.com; CS20 YSChu 
> <ys...@nuvoton.com>; CS20 KWLiu <kw...@nuvoton.com>
> Cc: u-boot@lists.denx.de
> Subject: [PATCH v1] spi: nuvoton: add NPCM PSPI controller driver
>
> Add Nuvoton NPCM BMC Peripheral SPI controller driver.
> NPCM750 include two general-purpose SPI interface.
>
> Signed-off-by: Jim Liu <jjl...@nuvoton.com>
> ---
>  drivers/spi/Kconfig     |   5 +
>  drivers/spi/Makefile    |   1 +
>  drivers/spi/npcm_pspi.c | 226 ++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 232 insertions(+)
>  create mode 100644 drivers/spi/npcm_pspi.c
>
> diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 
> a1e515cb2b..4e4e05f849 100644
> --- a/drivers/spi/Kconfig
> +++ b/drivers/spi/Kconfig
> @@ -289,6 +289,11 @@ config NPCM_FIU_SPI
>           This enables support for the Flash Interface Unit SPI controller
>           in master mode.
>
> +config NPCM_PSPI
> +       bool "PSPI driver for Nuvoton NPCM SoC"
> +       help
> +         PSPI driver for NPCM SoC
> +
>  config NXP_FSPI
>         bool "NXP FlexSPI driver"
>         depends on SPI_MEM
> diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 
> 06e81b465b..1b843636bc 100644
> --- a/drivers/spi/Makefile
> +++ b/drivers/spi/Makefile
> @@ -48,6 +48,7 @@ obj-$(CONFIG_MVEBU_A3700_SPI) += mvebu_a3700_spi.o
>  obj-$(CONFIG_MXC_SPI) += mxc_spi.o
>  obj-$(CONFIG_MXS_SPI) += mxs_spi.o
>  obj-$(CONFIG_NPCM_FIU_SPI) += npcm_fiu_spi.o
> +obj-$(CONFIG_NPCM_PSPI) += npcm_pspi.o
>  obj-$(CONFIG_NXP_FSPI) += nxp_fspi.o
>  obj-$(CONFIG_ATCSPI200_SPI) += atcspi200_spi.o
>  obj-$(CONFIG_OCTEON_SPI) += octeon_spi.o diff --git 
> a/drivers/spi/npcm_pspi.c b/drivers/spi/npcm_pspi.c new file mode 100644 
> index 0000000000..bd9ac65411
> --- /dev/null
> +++ b/drivers/spi/npcm_pspi.c
> @@ -0,0 +1,226 @@
> +// SPDX-License-Identifier: GPL-2.0+
> +/*
> + * Copyright (c) 2021 Nuvoton Technology.
> + */
> +
> +#include <common.h>
> +#include <dm.h>
> +#include <spi.h>
> +#include <clk.h>
> +#include <asm/gpio.h>
> +#include <linux/iopoll.h>
> +
> +#define MAX_DIV        127
> +
> +/* Register offsets */
> +#define PSPI_DATA              0
> +#define PSPI_CTL1              2
> +#define PSPI_STAT              4
> +
> +/* PSPI_CTL1 fields */
> +#define PSPI_CTL1_SPIEN                BIT(0)
> +#define PSPI_CTL1_SCM          BIT(7)
> +#define PSPI_CTL1_SCIDL                BIT(8)
> +#define PSPI_CTL1_SCDV_MASK    GENMASK(15, 9)
> +#define PSPI_CTL1_SCDV_SHIFT   9
> +
> +/* PSPI_STAT fields */
> +#define PSPI_STAT_BSY          BIT(0)
> +#define PSPI_STAT_RBF          BIT(1)
> +
> +struct npcm_pspi_priv {
> +       void __iomem *base;
> +       struct clk clk;
> +       struct gpio_desc cs_gpio;
> +       u32 max_hz;
> +};
> +
> +static inline void spi_cs_activate(struct udevice *dev) {
> +       struct udevice *bus = dev->parent;
> +       struct npcm_pspi_priv *priv = dev_get_priv(bus);
> +
> +       dm_gpio_set_value(&priv->cs_gpio, 0);
> +}
> +
> +static inline void spi_cs_deactivate(struct udevice *dev) {
> +       struct udevice *bus = dev->parent;
> +       struct npcm_pspi_priv *priv = dev_get_priv(bus);
> +
> +       dm_gpio_set_value(&priv->cs_gpio, 1);
> +}
> +
> +static inline void npcm_pspi_enable(struct npcm_pspi_priv *priv) {
> +       u16 val;
> +
> +       val = readw(priv->base + PSPI_CTL1);
> +       val |= PSPI_CTL1_SPIEN;
> +       writew(val, priv->base + PSPI_CTL1);
> +}
> +
> +static inline void npcm_pspi_disable(struct npcm_pspi_priv *priv) {
> +       u16 val;
> +
> +       val = readw(priv->base + PSPI_CTL1);
> +       val &= ~PSPI_CTL1_SPIEN;
> +       writew(val, priv->base + PSPI_CTL1);
> +}
> +
> +static int npcm_pspi_xfer(struct udevice *dev, unsigned int bitlen,
> +                         const void *dout, void *din, unsigned long flags) {
> +       struct udevice *bus = dev->parent;
> +       struct npcm_pspi_priv *priv = dev_get_priv(bus);
> +       void __iomem *base = priv->base;
> +       const u8 *tx = dout;
> +       u8 *rx = din;
> +       u32 bytes = bitlen / 8;
> +       u8 tmp;
> +       u32 val;
> +       int i, ret = 0;
> +
> +       npcm_pspi_enable(priv);
> +
> +       if (flags & SPI_XFER_BEGIN)
> +               spi_cs_activate(dev);
> +
> +       for (i = 0; i < bytes; i++) {
> +               /* Making sure we can write */
> +               ret = readb_poll_timeout(base + PSPI_STAT, val,
> +                                        !(val & PSPI_STAT_BSY),
> +                                        1000000);
> +               if (ret < 0)
> +                       break;
> +
> +               if (tx)
> +                       writeb(*tx++, base + PSPI_DATA);
> +               else
> +                       writeb(0, base + PSPI_DATA);
> +
> +               /* Wait till write completed */
> +               ret = readb_poll_timeout(base + PSPI_STAT, val,
> +                                        !(val & PSPI_STAT_BSY),
> +                                        1000000);
> +               if (ret < 0)
> +                       break;
> +
> +               /* Wait till read buffer full */
> +               ret = readb_poll_timeout(base + PSPI_STAT, val,
> +                                        (val & PSPI_STAT_RBF),
> +                                        1000000);
> +               if (ret < 0)
> +                       break;
> +
> +               tmp = readb(base + PSPI_DATA);
> +               if (rx)
> +                       *rx++ = tmp;
> +       }
> +
> +       if (flags & SPI_XFER_END)
> +               spi_cs_deactivate(dev);
> +
> +       npcm_pspi_disable(priv);
> +
> +       return ret;
> +}
> +
> +static int npcm_pspi_set_speed(struct udevice *bus, uint speed) {
> +       struct npcm_pspi_priv *priv = dev_get_priv(bus);
> +       ulong apb_clock;
> +       u32 divisor;
> +       u16 val;
> +
> +       apb_clock = clk_get_rate(&priv->clk);
> +       if (!apb_clock)
> +               return -EINVAL;
> +
> +       if (speed > priv->max_hz)
> +               speed = priv->max_hz;
> +
> +       divisor = DIV_ROUND_CLOSEST(apb_clock, (2 * speed) - 1);
> +       if (divisor > MAX_DIV)
> +               divisor = MAX_DIV;
> +
> +       val = readw(priv->base + PSPI_CTL1);
> +       val &= ~PSPI_CTL1_SCDV_MASK;
> +       val |= divisor << PSPI_CTL1_SCDV_SHIFT;
> +       writew(val, priv->base + PSPI_CTL1);
> +
> +       debug("%s: apb_clock=%lu speed=%d divisor=%u\n",
> +             __func__, apb_clock, speed, divisor);
> +
> +       return 0;
> +}
> +
> +static int npcm_pspi_set_mode(struct udevice *bus, uint mode) {
> +       struct npcm_pspi_priv *priv = dev_get_priv(bus);
> +       u16 pspi_mode, val;
> +
> +       switch (mode & (SPI_CPOL | SPI_CPHA)) {
> +       case SPI_MODE_0:
> +               pspi_mode = 0;
> +               break;
> +       case SPI_MODE_1:
> +               pspi_mode = PSPI_CTL1_SCM;
> +               break;
> +       case SPI_MODE_2:
> +               pspi_mode = PSPI_CTL1_SCIDL;
> +               break;
> +       case SPI_MODE_3:
> +               pspi_mode = PSPI_CTL1_SCIDL | PSPI_CTL1_SCM;
> +               break;
> +       default:
> +               break;
> +       }
> +
> +       val = readw(priv->base + PSPI_CTL1);
> +       val &= ~(PSPI_CTL1_SCIDL | PSPI_CTL1_SCM);
> +       val |= pspi_mode;
> +       writew(val, priv->base + PSPI_CTL1);
> +
> +       return 0;
> +}
> +
> +static int npcm_pspi_probe(struct udevice *bus) {
> +       struct npcm_pspi_priv *priv = dev_get_priv(bus);
> +       int node = dev_of_offset(bus);
> +       int ret;
> +
> +       ret = clk_get_by_index(bus, 0, &priv->clk);
> +       if (ret < 0)
> +               return ret;
> +
> +       priv->base = dev_read_addr_ptr(bus);
> +       priv->max_hz = dev_read_u32_default(bus, "spi-max-frequency", 0);
> +       gpio_request_by_name_nodev(offset_to_ofnode(node), "cs-gpios", 0,
> +                                  &priv->cs_gpio, GPIOD_IS_OUT);
> +
> +       return 0;
> +}
> +
> +static const struct dm_spi_ops npcm_pspi_ops = {
> +       .xfer           = npcm_pspi_xfer,
> +       .set_speed      = npcm_pspi_set_speed,
> +       .set_mode       = npcm_pspi_set_mode,
> +};
> +
> +static const struct udevice_id npcm_pspi_ids[] = {
> +       { .compatible = "nuvoton,npcm845-pspi"},
> +       { .compatible = "nuvoton,npcm750-pspi"},
> +       { }
> +};
> +
> +U_BOOT_DRIVER(npcm_pspi) = {
> +       .name   = "npcm_pspi",
> +       .id     = UCLASS_SPI,
> +       .of_match = npcm_pspi_ids,
> +       .ops    = &npcm_pspi_ops,
> +       .priv_auto = sizeof(struct npcm_pspi_priv),
> +       .probe  = npcm_pspi_probe,
> +};
> --
> 2.17.1
>
> ________________________________
> ________________________________
>  The privileged confidential information contained in this email is intended 
> for use only by the addressees as indicated by the original sender of this 
> email. If you are not the addressee indicated in this email or are not 
> responsible for delivery of the email to such a person, please kindly reply 
> to the sender indicating this fact and delete all copies of it from your 
> computer and network server immediately. Your cooperation is highly 
> appreciated. It is advised that any unauthorized use of confidential 
> information of Nuvoton is strictly prohibited; and any information in this 
> email irrelevant to the official business of Nuvoton shall be deemed as 
> neither given nor endorsed by Nuvoton.

Reply via email to