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.