From 48263504c8d501678acaa90c075f3f7cda17c316 Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Tue, 23 Jan 2018 17:14:55 +0100 Subject: wait_bit: use wait_for_bit_le32 and remove wait_for_bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wait_for_bit callers use the 32 bit LE version Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Daniel Schwierzeck Reviewed-by: Jagan Teki --- drivers/clk/clk_pic32.c | 12 +++---- drivers/clk/renesas/clk-rcar-gen3.c | 4 +-- drivers/ddr/microchip/ddr2.c | 8 ++--- drivers/fpga/socfpga_arria10.c | 17 ++++------ drivers/mmc/msm_sdhci.c | 8 ++--- drivers/mtd/pic32_flash.c | 4 +-- drivers/net/ag7xxx.c | 16 +++++----- drivers/net/dwc_eth_qos.c | 17 +++++----- drivers/net/ethoc.c | 8 ++--- drivers/net/pic32_eth.c | 12 +++---- drivers/net/pic32_mdio.c | 28 ++++++++-------- drivers/net/ravb.c | 4 +-- drivers/net/xilinx_axi_emac.c | 4 +-- drivers/net/zynq_gem.c | 12 +++---- drivers/reset/sti-reset.c | 4 +-- drivers/serial/serial_pic32.c | 4 +-- drivers/spi/atmel_spi.c | 4 +-- drivers/spi/cadence_qspi_apb.c | 14 ++++---- drivers/spi/fsl_qspi.c | 20 ++++++------ drivers/spi/mvebu_a3700_spi.c | 20 ++++++------ drivers/usb/host/dwc2.c | 24 +++++++------- drivers/usb/host/ehci-msm.c | 3 +- drivers/usb/host/ehci-mx6.c | 5 ++- drivers/usb/host/ohci-lpc32xx.c | 12 +++---- drivers/usb/host/xhci-rcar.c | 12 +++---- drivers/video/atmel_hlcdfb.c | 64 ++++++++++++++++++------------------- 26 files changed, 169 insertions(+), 171 deletions(-) (limited to 'drivers') diff --git a/drivers/clk/clk_pic32.c b/drivers/clk/clk_pic32.c index f6eef314ec..177803943d 100644 --- a/drivers/clk/clk_pic32.c +++ b/drivers/clk/clk_pic32.c @@ -197,8 +197,8 @@ static ulong pic32_set_refclk(struct pic32_clk_priv *priv, int periph, writel(REFO_ON | REFO_OE, reg + _CLR_OFFSET); /* wait till previous src change is active */ - wait_for_bit(__func__, reg, REFO_DIVSW_EN | REFO_ACTIVE, - false, CONFIG_SYS_HZ, false); + wait_for_bit_le32(reg, REFO_DIVSW_EN | REFO_ACTIVE, + false, CONFIG_SYS_HZ, false); /* parent_id */ v = readl(reg); @@ -223,8 +223,8 @@ static ulong pic32_set_refclk(struct pic32_clk_priv *priv, int periph, writel(REFO_DIVSW_EN, reg + _SET_OFFSET); /* wait for divider switching to complete */ - return wait_for_bit(__func__, reg, REFO_DIVSW_EN, false, - CONFIG_SYS_HZ, false); + return wait_for_bit_le32(reg, REFO_DIVSW_EN, false, + CONFIG_SYS_HZ, false); } static ulong pic32_get_refclk(struct pic32_clk_priv *priv, int periph) @@ -311,8 +311,8 @@ static int pic32_mpll_init(struct pic32_clk_priv *priv) /* Wait for ready */ mask = MPLL_RDY | MPLL_VREG_RDY; - return wait_for_bit(__func__, priv->syscfg_base + CFGMPLL, mask, - true, get_tbclk(), false); + return wait_for_bit_le32(priv->syscfg_base + CFGMPLL, mask, + true, get_tbclk(), false); } static void pic32_clk_init(struct udevice *dev) diff --git a/drivers/clk/renesas/clk-rcar-gen3.c b/drivers/clk/renesas/clk-rcar-gen3.c index b26bbcc59f..22828fd470 100644 --- a/drivers/clk/renesas/clk-rcar-gen3.c +++ b/drivers/clk/renesas/clk-rcar-gen3.c @@ -1046,8 +1046,8 @@ static int gen3_clk_endisable(struct clk *clk, bool enable) if (ret) return ret; clrbits_le32(priv->base + SMSTPCR(reg), bitmask); - return wait_for_bit("MSTP", priv->base + MSTPSR(reg), - bitmask, 0, 100, 0); + return wait_for_bit_le32(priv->base + MSTPSR(reg), + bitmask, 0, 100, 0); } else { setbits_le32(priv->base + SMSTPCR(reg), bitmask); return 0; diff --git a/drivers/ddr/microchip/ddr2.c b/drivers/ddr/microchip/ddr2.c index 6056418588..a52427c3d6 100644 --- a/drivers/ddr/microchip/ddr2.c +++ b/drivers/ddr/microchip/ddr2.c @@ -57,8 +57,8 @@ static int ddr2_phy_calib_start(void) writel(SCL_START | SCL_EN, &ddr2_phy->scl_start); /* Wait for SCL for data byte to pass */ - return wait_for_bit(__func__, &ddr2_phy->scl_start, SCL_LUBPASS, - true, CONFIG_SYS_HZ, false); + return wait_for_bit_le32(&ddr2_phy->scl_start, SCL_LUBPASS, + true, CONFIG_SYS_HZ, false); } /* DDR2 Controller initialization */ @@ -256,8 +256,8 @@ void ddr2_ctrl_init(void) writel(INIT_START, &ctrl->memcon); /* wait for all host cmds to be transmitted */ - wait_for_bit(__func__, &ctrl->cmdissue, CMD_VALID, false, - CONFIG_SYS_HZ, false); + wait_for_bit_le32(&ctrl->cmdissue, CMD_VALID, false, + CONFIG_SYS_HZ, false); /* inform all cmds issued, ready for normal operation */ writel(INIT_START | INIT_DONE, &ctrl->memcon); diff --git a/drivers/fpga/socfpga_arria10.c b/drivers/fpga/socfpga_arria10.c index 5c1a68a009..d5763965dd 100644 --- a/drivers/fpga/socfpga_arria10.c +++ b/drivers/fpga/socfpga_arria10.c @@ -62,8 +62,7 @@ int is_fpgamgr_user_mode(void) static int wait_for_user_mode(void) { - return wait_for_bit(__func__, - &fpga_manager_base->imgcfg_stat, + return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat, ALT_FPGAMGR_IMGCFG_STAT_F2S_USERMODE_SET_MSK, 1, FPGA_TIMEOUT_MSEC, false); } @@ -115,19 +114,17 @@ static int wait_for_nconfig_pin_and_nstatus_pin(void) /* Poll until f2s_nconfig_pin and f2s_nstatus_pin; loop until de-asserted, * timeout at 1000ms */ - return wait_for_bit(__func__, - &fpga_manager_base->imgcfg_stat, - mask, - false, FPGA_TIMEOUT_MSEC, false); + return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat, + mask, + false, FPGA_TIMEOUT_MSEC, false); } static int wait_for_f2s_nstatus_pin(unsigned long value) { /* Poll until f2s to specific value, timeout at 1000ms */ - return wait_for_bit(__func__, - &fpga_manager_base->imgcfg_stat, - ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK, - value, FPGA_TIMEOUT_MSEC, false); + return wait_for_bit_le32(&fpga_manager_base->imgcfg_stat, + ALT_FPGAMGR_IMGCFG_STAT_F2S_NSTATUS_PIN_SET_MSK, + value, FPGA_TIMEOUT_MSEC, false); } /* set CD ratio */ diff --git a/drivers/mmc/msm_sdhci.c b/drivers/mmc/msm_sdhci.c index 9117ab6bf9..f0661bd96c 100644 --- a/drivers/mmc/msm_sdhci.c +++ b/drivers/mmc/msm_sdhci.c @@ -109,15 +109,15 @@ static int msm_sdc_probe(struct udevice *dev) /* Wait for reset to be written to register */ - if (wait_for_bit(__func__, prv->base + SDCC_MCI_STATUS2, - SDCC_MCI_STATUS2_MCI_ACT, false, 10, false)) { + if (wait_for_bit_le32(prv->base + SDCC_MCI_STATUS2, + SDCC_MCI_STATUS2_MCI_ACT, false, 10, false)) { printf("msm_sdhci: reset request failed\n"); return -EIO; } /* SW reset can take upto 10HCLK + 15MCLK cycles. (min 40us) */ - if (wait_for_bit(__func__, prv->base + SDCC_MCI_POWER, - SDCC_MCI_POWER_SW_RST, false, 2, false)) { + if (wait_for_bit_le32(prv->base + SDCC_MCI_POWER, + SDCC_MCI_POWER_SW_RST, false, 2, false)) { printf("msm_sdhci: stuck in reset\n"); return -ETIMEDOUT; } diff --git a/drivers/mtd/pic32_flash.c b/drivers/mtd/pic32_flash.c index e1a8d3bc4b..8bbf2fa9a2 100644 --- a/drivers/mtd/pic32_flash.c +++ b/drivers/mtd/pic32_flash.c @@ -66,8 +66,8 @@ static inline void flash_initiate_operation(u32 nvmop) static int flash_wait_till_busy(const char *func, ulong timeout) { - int ret = wait_for_bit(__func__, &nvm_regs_p->ctrl.raw, - NVM_WR, false, timeout, false); + int ret = wait_for_bit_le32(&nvm_regs_p->ctrl.raw, + NVM_WR, false, timeout, false); return ret ? ERR_TIMOUT : ERR_OK; } diff --git a/drivers/net/ag7xxx.c b/drivers/net/ag7xxx.c index 00e6806892..f28187058e 100644 --- a/drivers/net/ag7xxx.c +++ b/drivers/net/ag7xxx.c @@ -164,8 +164,8 @@ static int ag7xxx_switch_read(struct mii_dev *bus, int addr, int reg, u16 *val) writel(AG7XXX_ETH_MII_MGMT_CMD_READ, regs + AG7XXX_ETH_MII_MGMT_CMD); - ret = wait_for_bit("ag7xxx", regs + AG7XXX_ETH_MII_MGMT_IND, - AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0); + ret = wait_for_bit_le32(regs + AG7XXX_ETH_MII_MGMT_IND, + AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0); if (ret) return ret; @@ -185,8 +185,8 @@ static int ag7xxx_switch_write(struct mii_dev *bus, int addr, int reg, u16 val) regs + AG7XXX_ETH_MII_MGMT_ADDRESS); writel(val, regs + AG7XXX_ETH_MII_MGMT_CTRL); - ret = wait_for_bit("ag7xxx", regs + AG7XXX_ETH_MII_MGMT_IND, - AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0); + ret = wait_for_bit_le32(regs + AG7XXX_ETH_MII_MGMT_IND, + AG7XXX_ETH_MII_MGMT_IND_BUSY, 0, 1000, 0); return ret; } @@ -510,13 +510,13 @@ static void ag7xxx_eth_stop(struct udevice *dev) /* Stop the TX DMA. */ writel(0, priv->regs + AG7XXX_ETH_DMA_TX_CTRL); - wait_for_bit("ag7xxx", priv->regs + AG7XXX_ETH_DMA_TX_CTRL, ~0, 0, - 1000, 0); + wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_TX_CTRL, ~0, 0, + 1000, 0); /* Stop the RX DMA. */ writel(0, priv->regs + AG7XXX_ETH_DMA_RX_CTRL); - wait_for_bit("ag7xxx", priv->regs + AG7XXX_ETH_DMA_RX_CTRL, ~0, 0, - 1000, 0); + wait_for_bit_le32(priv->regs + AG7XXX_ETH_DMA_RX_CTRL, ~0, 0, + 1000, 0); } /* diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index 00076cffbe..232e8034df 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -361,8 +361,9 @@ static void eqos_flush_buffer(void *buf, size_t size) static int eqos_mdio_wait_idle(struct eqos_priv *eqos) { - return wait_for_bit(__func__, &eqos->mac_regs->mdio_address, - EQOS_MAC_MDIO_ADDRESS_GB, false, 1000000, true); + return wait_for_bit_le32(&eqos->mac_regs->mdio_address, + EQOS_MAC_MDIO_ADDRESS_GB, false, + 1000000, true); } static int eqos_mdio_read(struct mii_dev *bus, int mdio_addr, int mdio_devad, @@ -588,15 +589,15 @@ static int eqos_calibrate_pads_tegra186(struct udevice *dev) setbits_le32(&eqos->tegra186_regs->auto_cal_config, EQOS_AUTO_CAL_CONFIG_START | EQOS_AUTO_CAL_CONFIG_ENABLE); - ret = wait_for_bit(__func__, &eqos->tegra186_regs->auto_cal_status, - EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false); + ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status, + EQOS_AUTO_CAL_STATUS_ACTIVE, true, 10, false); if (ret) { pr_err("calibrate didn't start"); goto failed; } - ret = wait_for_bit(__func__, &eqos->tegra186_regs->auto_cal_status, - EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false); + ret = wait_for_bit_le32(&eqos->tegra186_regs->auto_cal_status, + EQOS_AUTO_CAL_STATUS_ACTIVE, false, 10, false); if (ret) { pr_err("calibrate didn't finish"); goto failed; @@ -862,8 +863,8 @@ static int eqos_start(struct udevice *dev) eqos->reg_access_ok = true; - ret = wait_for_bit(__func__, &eqos->dma_regs->mode, - EQOS_DMA_MODE_SWR, false, 10, false); + ret = wait_for_bit_le32(&eqos->dma_regs->mode, + EQOS_DMA_MODE_SWR, false, 10, false); if (ret) { pr_err("EQOS_DMA_MODE_SWR stuck"); goto err_stop_resets; diff --git a/drivers/net/ethoc.c b/drivers/net/ethoc.c index a6df950081..51a6c97550 100644 --- a/drivers/net/ethoc.c +++ b/drivers/net/ethoc.c @@ -548,8 +548,8 @@ static int ethoc_mdio_read(struct mii_dev *bus, int addr, int devad, int reg) ethoc_write(priv, MIIADDRESS, MIIADDRESS_ADDR(addr, reg)); ethoc_write(priv, MIICOMMAND, MIICOMMAND_READ); - rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS), - MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false); + rc = wait_for_bit_le32(ethoc_reg(priv, MIISTATUS), + MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false); if (rc == 0) { u32 data = ethoc_read(priv, MIIRX_DATA); @@ -571,8 +571,8 @@ static int ethoc_mdio_write(struct mii_dev *bus, int addr, int devad, int reg, ethoc_write(priv, MIITX_DATA, val); ethoc_write(priv, MIICOMMAND, MIICOMMAND_WRITE); - rc = wait_for_bit(__func__, ethoc_reg(priv, MIISTATUS), - MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false); + rc = wait_for_bit_le32(ethoc_reg(priv, MIISTATUS), + MIISTATUS_BUSY, false, CONFIG_SYS_HZ, false); if (rc == 0) { /* reset MII command register */ diff --git a/drivers/net/pic32_eth.c b/drivers/net/pic32_eth.c index 0b89911f04..7129372790 100644 --- a/drivers/net/pic32_eth.c +++ b/drivers/net/pic32_eth.c @@ -64,8 +64,8 @@ static int pic32_mii_init(struct pic32eth_dev *priv) writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr); /* wait till busy */ - wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false, - CONFIG_SYS_HZ, false); + wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false, + CONFIG_SYS_HZ, false); /* turn controller ON to access PHY over MII */ writel(ETHCON_ON, &ectl_p->con1.set); @@ -239,8 +239,8 @@ static void pic32_ctrl_reset(struct pic32eth_dev *priv) writel(ETHCON_ON | ETHCON_TXRTS | ETHCON_RXEN, &ectl_p->con1.clr); /* wait till busy */ - wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false, - CONFIG_SYS_HZ, false); + wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false, + CONFIG_SYS_HZ, false); /* decrement received buffcnt to zero. */ while (readl(&ectl_p->stat.raw) & ETHSTAT_BUFCNT) writel(ETHCON_BUFCDEC, &ectl_p->con1.set); @@ -375,8 +375,8 @@ static void pic32_eth_stop(struct udevice *dev) mdelay(10); /* wait until everything is down */ - wait_for_bit(__func__, &ectl_p->stat.raw, ETHSTAT_BUSY, false, - 2 * CONFIG_SYS_HZ, false); + wait_for_bit_le32(&ectl_p->stat.raw, ETHSTAT_BUSY, false, + 2 * CONFIG_SYS_HZ, false); /* clear any existing interrupt event */ writel(0xffffffff, &ectl_p->irq.clr); diff --git a/drivers/net/pic32_mdio.c b/drivers/net/pic32_mdio.c index 578fc96905..6ae5c40fa3 100644 --- a/drivers/net/pic32_mdio.c +++ b/drivers/net/pic32_mdio.c @@ -22,8 +22,8 @@ static int pic32_mdio_write(struct mii_dev *bus, struct pic32_mii_regs *mii_regs = bus->priv; /* Wait for the previous operation to finish */ - wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY, - false, CONFIG_SYS_HZ, true); + wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY, + false, CONFIG_SYS_HZ, true); /* Put phyaddr and regaddr into MIIMADD */ v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR); @@ -36,8 +36,8 @@ static int pic32_mdio_write(struct mii_dev *bus, udelay(12); /* Wait for write to complete */ - wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY, - false, CONFIG_SYS_HZ, true); + wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY, + false, CONFIG_SYS_HZ, true); return 0; } @@ -48,8 +48,8 @@ static int pic32_mdio_read(struct mii_dev *bus, int addr, int devaddr, int reg) struct pic32_mii_regs *mii_regs = bus->priv; /* Wait for the previous operation to finish */ - wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY, - false, CONFIG_SYS_HZ, true); + wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY, + false, CONFIG_SYS_HZ, true); /* Put phyaddr and regaddr into MIIMADD */ v = (addr << MIIMADD_PHYADDR_SHIFT) | (reg & MIIMADD_REGADDR); @@ -62,9 +62,9 @@ static int pic32_mdio_read(struct mii_dev *bus, int addr, int devaddr, int reg) udelay(12); /* Wait for read to complete */ - wait_for_bit(__func__, &mii_regs->mind.raw, - MIIMIND_NOTVALID | MIIMIND_BUSY, - false, CONFIG_SYS_HZ, false); + wait_for_bit_le32(&mii_regs->mind.raw, + MIIMIND_NOTVALID | MIIMIND_BUSY, + false, CONFIG_SYS_HZ, false); /* Clear the command register */ writel(0, &mii_regs->mcmd.raw); @@ -82,22 +82,22 @@ static int pic32_mdio_reset(struct mii_dev *bus) writel(MIIMCFG_RSTMGMT, &mii_regs->mcfg.raw); /* Wait for the operation to finish */ - wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY, + wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY, false, CONFIG_SYS_HZ, true); /* Clear reset bit */ writel(0, &mii_regs->mcfg); /* Wait for the operation to finish */ - wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY, - false, CONFIG_SYS_HZ, true); + wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY, + false, CONFIG_SYS_HZ, true); /* Set the MII Management Clock (MDC) - no faster than 2.5 MHz */ writel(MIIMCFG_CLKSEL_DIV40, &mii_regs->mcfg.raw); /* Wait for the operation to finish */ - wait_for_bit(__func__, &mii_regs->mind.raw, MIIMIND_BUSY, - false, CONFIG_SYS_HZ, true); + wait_for_bit_le32(&mii_regs->mind.raw, MIIMIND_BUSY, + false, CONFIG_SYS_HZ, true); return 0; } diff --git a/drivers/net/ravb.c b/drivers/net/ravb.c index dc743e113d..26bd915291 100644 --- a/drivers/net/ravb.c +++ b/drivers/net/ravb.c @@ -222,8 +222,8 @@ static int ravb_reset(struct udevice *dev) writel(CCC_OPC_CONFIG, eth->iobase + RAVB_REG_CCC); /* Check the operating mode is changed to the config mode. */ - return wait_for_bit(dev->name, (void *)eth->iobase + RAVB_REG_CSR, - CSR_OPS_CONFIG, true, 100, true); + return wait_for_bit_le32(eth->iobase + RAVB_REG_CSR, + CSR_OPS_CONFIG, true, 100, true); } static void ravb_base_desc_init(struct ravb_priv *eth) diff --git a/drivers/net/xilinx_axi_emac.c b/drivers/net/xilinx_axi_emac.c index 9a2a578ff9..70a2e95a8e 100644 --- a/drivers/net/xilinx_axi_emac.c +++ b/drivers/net/xilinx_axi_emac.c @@ -366,8 +366,8 @@ static int axi_ethernet_init(struct axidma_priv *priv) * processor mode and hence bypass in this mode */ if (!priv->eth_hasnobuf) { - err = wait_for_bit(__func__, (const u32 *)®s->is, - XAE_INT_MGTRDY_MASK, true, 200, false); + err = wait_for_bit_le32(®s->is, XAE_INT_MGTRDY_MASK, + true, 200, false); if (err) { printf("%s: Timeout\n", __func__); return 1; diff --git a/drivers/net/zynq_gem.c b/drivers/net/zynq_gem.c index 1dfd631e1a..2cc49bca92 100644 --- a/drivers/net/zynq_gem.c +++ b/drivers/net/zynq_gem.c @@ -192,8 +192,8 @@ static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum, struct zynq_gem_regs *regs = priv->iobase; int err; - err = wait_for_bit(__func__, ®s->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK, - true, 20000, false); + err = wait_for_bit_le32(®s->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK, + true, 20000, false); if (err) return err; @@ -205,8 +205,8 @@ static u32 phy_setup_op(struct zynq_gem_priv *priv, u32 phy_addr, u32 regnum, /* Write mgtcr and wait for completion */ writel(mgtcr, ®s->phymntnc); - err = wait_for_bit(__func__, ®s->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK, - true, 20000, false); + err = wait_for_bit_le32(®s->nwsr, ZYNQ_GEM_NWSR_MDIOIDLE_MASK, + true, 20000, false); if (err) return err; @@ -514,8 +514,8 @@ static int zynq_gem_send(struct udevice *dev, void *ptr, int len) if (priv->tx_bd->status & ZYNQ_GEM_TXBUF_EXHAUSTED) printf("TX buffers exhausted in mid frame\n"); - return wait_for_bit(__func__, ®s->txsr, ZYNQ_GEM_TSR_DONE, - true, 20000, true); + return wait_for_bit_le32(®s->txsr, ZYNQ_GEM_TSR_DONE, + true, 20000, true); } /* Do not check frame_recd flag in rx_status register 0x20 - just poll BD */ diff --git a/drivers/reset/sti-reset.c b/drivers/reset/sti-reset.c index 17786f976a..0fc5a28802 100644 --- a/drivers/reset/sti-reset.c +++ b/drivers/reset/sti-reset.c @@ -266,8 +266,8 @@ static int sti_reset_program_hw(struct reset_ctl *reset_ctl, int assert) return 0; reg = (void __iomem *)base + ch->ack_offset; - if (wait_for_bit(__func__, reg, BIT(ch->ack_bit), ctrl_val, - 1000, false)) { + if (wait_for_bit_le32(reg, BIT(ch->ack_bit), ctrl_val, + 1000, false)) { pr_err("Stuck on waiting ack reset_ctl=%p dev=%p id=%lu\n", reset_ctl, reset_ctl->dev, reset_ctl->id); diff --git a/drivers/serial/serial_pic32.c b/drivers/serial/serial_pic32.c index b0e01aa0e5..0632d26211 100644 --- a/drivers/serial/serial_pic32.c +++ b/drivers/serial/serial_pic32.c @@ -51,8 +51,8 @@ static int pic32_serial_init(void __iomem *base, ulong clk, u32 baudrate) u32 div = DIV_ROUND_CLOSEST(clk, baudrate * 16); /* wait for TX FIFO to empty */ - wait_for_bit(__func__, base + U_STA, UART_TX_EMPTY, - true, CONFIG_SYS_HZ, false); + wait_for_bit_le32(base + U_STA, UART_TX_EMPTY, + true, CONFIG_SYS_HZ, false); /* send break */ writel(UART_TX_BRK, base + U_STASET); diff --git a/drivers/spi/atmel_spi.c b/drivers/spi/atmel_spi.c index 228e714e09..8010ab434c 100644 --- a/drivers/spi/atmel_spi.c +++ b/drivers/spi/atmel_spi.c @@ -394,8 +394,8 @@ out: * Wait until the transfer is completely done before * we deactivate CS. */ - wait_for_bit(__func__, ®_base->sr, - ATMEL_SPI_SR_TXEMPTY, true, 1000, false); + wait_for_bit_le32(®_base->sr, + ATMEL_SPI_SR_TXEMPTY, true, 1000, false); atmel_spi_cs_deactivate(dev); } diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index e02f2217f4..dca3fdfdea 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -675,8 +675,8 @@ int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat, } /* Check indirect done status */ - ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_INDIRECTRD, - CQSPI_REG_INDIRECTRD_DONE, 1, 10, 0); + ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTRD, + CQSPI_REG_INDIRECTRD_DONE, 1, 10, 0); if (ret) { printf("Indirect read completion error (%i)\n", ret); goto failrd; @@ -762,9 +762,9 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat, bb_txbuf + rounddown(write_bytes, 4), write_bytes % 4); - ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_SDRAMLEVEL, - CQSPI_REG_SDRAMLEVEL_WR_MASK << - CQSPI_REG_SDRAMLEVEL_WR_LSB, 0, 10, 0); + ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_SDRAMLEVEL, + CQSPI_REG_SDRAMLEVEL_WR_MASK << + CQSPI_REG_SDRAMLEVEL_WR_LSB, 0, 10, 0); if (ret) { printf("Indirect write timed out (%i)\n", ret); goto failwr; @@ -775,8 +775,8 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat, } /* Check indirect done status */ - ret = wait_for_bit("QSPI", plat->regbase + CQSPI_REG_INDIRECTWR, - CQSPI_REG_INDIRECTWR_DONE, 1, 10, 0); + ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_INDIRECTWR, + CQSPI_REG_INDIRECTWR_DONE, 1, 10, 0); if (ret) { printf("Indirect write completion error (%i)\n", ret); goto failwr; diff --git a/drivers/spi/fsl_qspi.c b/drivers/spi/fsl_qspi.c index 0f3f7d97f0..eed52c15c8 100644 --- a/drivers/spi/fsl_qspi.c +++ b/drivers/spi/fsl_qspi.c @@ -1011,11 +1011,11 @@ static int fsl_qspi_probe(struct udevice *bus) priv->num_chipselect = plat->num_chipselect; /* make sure controller is not busy anywhere */ - ret = wait_for_bit(__func__, &priv->regs->sr, - QSPI_SR_BUSY_MASK | - QSPI_SR_AHB_ACC_MASK | - QSPI_SR_IP_ACC_MASK, - false, 100, false); + ret = wait_for_bit_le32(&priv->regs->sr, + QSPI_SR_BUSY_MASK | + QSPI_SR_AHB_ACC_MASK | + QSPI_SR_IP_ACC_MASK, + false, 100, false); if (ret) { debug("ERROR : The controller is busy\n"); @@ -1173,11 +1173,11 @@ static int fsl_qspi_claim_bus(struct udevice *dev) priv = dev_get_priv(bus); /* make sure controller is not busy anywhere */ - ret = wait_for_bit(__func__, &priv->regs->sr, - QSPI_SR_BUSY_MASK | - QSPI_SR_AHB_ACC_MASK | - QSPI_SR_IP_ACC_MASK, - false, 100, false); + ret = wait_for_bit_le32(&priv->regs->sr, + QSPI_SR_BUSY_MASK | + QSPI_SR_AHB_ACC_MASK | + QSPI_SR_IP_ACC_MASK, + false, 100, false); if (ret) { debug("ERROR : The controller is busy\n"); diff --git a/drivers/spi/mvebu_a3700_spi.c b/drivers/spi/mvebu_a3700_spi.c index ec4907391c..d1708a8d56 100644 --- a/drivers/spi/mvebu_a3700_spi.c +++ b/drivers/spi/mvebu_a3700_spi.c @@ -95,8 +95,9 @@ static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen, din_8 = din; while (bytelen) { - ret = wait_for_bit(__func__, ®->ctrl, - MVEBU_SPI_A3700_XFER_RDY, true, 100, false); + ret = wait_for_bit_le32(®->ctrl, + MVEBU_SPI_A3700_XFER_RDY, + true,100, false); if (ret) return ret; @@ -109,9 +110,9 @@ static int spi_legacy_shift_byte(struct spi_reg *reg, unsigned int bytelen, writel(pending_dout, ®->dout); if (din) { - ret = wait_for_bit(__func__, ®->ctrl, - MVEBU_SPI_A3700_XFER_RDY, - true, 100, false); + ret = wait_for_bit_le32(®->ctrl, + MVEBU_SPI_A3700_XFER_RDY, + true, 100, false); if (ret) return ret; @@ -160,8 +161,9 @@ static int mvebu_spi_xfer(struct udevice *dev, unsigned int bitlen, /* Deactivate CS */ if (flags & SPI_XFER_END) { - ret = wait_for_bit(__func__, ®->ctrl, - MVEBU_SPI_A3700_XFER_RDY, true, 100, false); + ret = wait_for_bit_le32(®->ctrl, + MVEBU_SPI_A3700_XFER_RDY, + true, 100, false); if (ret) return ret; @@ -231,8 +233,8 @@ static int mvebu_spi_probe(struct udevice *bus) /* Flush read/write FIFO */ data = readl(®->cfg); writel(data | MVEBU_SPI_A3700_FIFO_FLUSH, ®->cfg); - ret = wait_for_bit(__func__, ®->cfg, MVEBU_SPI_A3700_FIFO_FLUSH, - false, 1000, false); + ret = wait_for_bit_le32(®->cfg, MVEBU_SPI_A3700_FIFO_FLUSH, + false, 1000, false); if (ret) return ret; diff --git a/drivers/usb/host/dwc2.c b/drivers/usb/host/dwc2.c index 1293e18f75..540c016412 100644 --- a/drivers/usb/host/dwc2.c +++ b/drivers/usb/host/dwc2.c @@ -108,8 +108,8 @@ static void dwc_otg_flush_tx_fifo(struct dwc2_core_regs *regs, const int num) writel(DWC2_GRSTCTL_TXFFLSH | (num << DWC2_GRSTCTL_TXFNUM_OFFSET), ®s->grstctl); - ret = wait_for_bit(__func__, ®s->grstctl, DWC2_GRSTCTL_TXFFLSH, - false, 1000, false); + ret = wait_for_bit_le32(®s->grstctl, DWC2_GRSTCTL_TXFFLSH, + false, 1000, false); if (ret) printf("%s: Timeout!\n", __func__); @@ -127,8 +127,8 @@ static void dwc_otg_flush_rx_fifo(struct dwc2_core_regs *regs) int ret; writel(DWC2_GRSTCTL_RXFFLSH, ®s->grstctl); - ret = wait_for_bit(__func__, ®s->grstctl, DWC2_GRSTCTL_RXFFLSH, - false, 1000, false); + ret = wait_for_bit_le32(®s->grstctl, DWC2_GRSTCTL_RXFFLSH, + false, 1000, false); if (ret) printf("%s: Timeout!\n", __func__); @@ -145,15 +145,15 @@ static void dwc_otg_core_reset(struct dwc2_core_regs *regs) int ret; /* Wait for AHB master IDLE state. */ - ret = wait_for_bit(__func__, ®s->grstctl, DWC2_GRSTCTL_AHBIDLE, - true, 1000, false); + ret = wait_for_bit_le32(®s->grstctl, DWC2_GRSTCTL_AHBIDLE, + true, 1000, false); if (ret) printf("%s: Timeout!\n", __func__); /* Core Soft Reset */ writel(DWC2_GRSTCTL_CSFTRST, ®s->grstctl); - ret = wait_for_bit(__func__, ®s->grstctl, DWC2_GRSTCTL_CSFTRST, - false, 1000, false); + ret = wait_for_bit_le32(®s->grstctl, DWC2_GRSTCTL_CSFTRST, + false, 1000, false); if (ret) printf("%s: Timeout!\n", __func__); @@ -267,8 +267,8 @@ static void dwc_otg_core_host_init(struct udevice *dev, clrsetbits_le32(®s->hc_regs[i].hcchar, DWC2_HCCHAR_EPDIR, DWC2_HCCHAR_CHEN | DWC2_HCCHAR_CHDIS); - ret = wait_for_bit(__func__, ®s->hc_regs[i].hcchar, - DWC2_HCCHAR_CHEN, false, 1000, false); + ret = wait_for_bit_le32(®s->hc_regs[i].hcchar, + DWC2_HCCHAR_CHEN, false, 1000, false); if (ret) printf("%s: Timeout!\n", __func__); } @@ -783,8 +783,8 @@ int wait_for_chhltd(struct dwc2_hc_regs *hc_regs, uint32_t *sub, u8 *toggle) int ret; uint32_t hcint, hctsiz; - ret = wait_for_bit(__func__, &hc_regs->hcint, DWC2_HCINT_CHHLTD, true, - 1000, false); + ret = wait_for_bit_le32(&hc_regs->hcint, DWC2_HCINT_CHHLTD, true, + 1000, false); if (ret) return ret; diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c index 2c0c63322c..f5320ca298 100644 --- a/drivers/usb/host/ehci-msm.c +++ b/drivers/usb/host/ehci-msm.c @@ -133,8 +133,7 @@ static int ehci_usb_remove(struct udevice *dev) setbits_le32(&ehci->usbcmd, CMD_RESET); /* Wait for reset */ - if (wait_for_bit(__func__, &ehci->usbcmd, CMD_RESET, false, 30, - false)) { + if (wait_for_bit_le32(&ehci->usbcmd, CMD_RESET, false, 30, false)) { printf("Stuck on USB reset.\n"); return -ETIMEDOUT; } diff --git a/drivers/usb/host/ehci-mx6.c b/drivers/usb/host/ehci-mx6.c index fe2627ea93..2c8fc3c4b1 100644 --- a/drivers/usb/host/ehci-mx6.c +++ b/drivers/usb/host/ehci-mx6.c @@ -142,13 +142,12 @@ static int usb_phy_enable(int index, struct usb_ehci *ehci) /* Stop then Reset */ clrbits_le32(usb_cmd, UCMD_RUN_STOP); - ret = wait_for_bit(__func__, usb_cmd, UCMD_RUN_STOP, false, 10000, - false); + ret = wait_for_bit_le32(usb_cmd, UCMD_RUN_STOP, false, 10000, false); if (ret) return ret; setbits_le32(usb_cmd, UCMD_RESET); - ret = wait_for_bit(__func__, usb_cmd, UCMD_RESET, false, 10000, false); + ret = wait_for_bit_le32(usb_cmd, UCMD_RESET, false, 10000, false); if (ret) return ret; diff --git a/drivers/usb/host/ohci-lpc32xx.c b/drivers/usb/host/ohci-lpc32xx.c index 2f2b4b90de..44a49807a4 100644 --- a/drivers/usb/host/ohci-lpc32xx.c +++ b/drivers/usb/host/ohci-lpc32xx.c @@ -143,8 +143,8 @@ static int usbpll_setup(void) setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_POSTDIV_2POW(0x01)); setbits_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_PWRUP); - ret = wait_for_bit(__func__, &clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_STS, - true, CONFIG_SYS_HZ, false); + ret = wait_for_bit_le32(&clk_pwr->usb_ctrl, CLK_USBCTRL_PLL_STS, + true, CONFIG_SYS_HZ, false); if (ret) return ret; @@ -178,8 +178,8 @@ int usb_cpu_init(void) /* enable I2C clock */ writel(OTG_CLK_I2C_EN, &otg->otg_clk_ctrl); - ret = wait_for_bit(__func__, &otg->otg_clk_sts, OTG_CLK_I2C_EN, true, - CONFIG_SYS_HZ, false); + ret = wait_for_bit_le32(&otg->otg_clk_sts, OTG_CLK_I2C_EN, true, + CONFIG_SYS_HZ, false); if (ret) return ret; @@ -199,8 +199,8 @@ int usb_cpu_init(void) OTG_CLK_I2C_EN | OTG_CLK_HOST_EN; writel(mask, &otg->otg_clk_ctrl); - ret = wait_for_bit(__func__, &otg->otg_clk_sts, mask, true, - CONFIG_SYS_HZ, false); + ret = wait_for_bit_le32(&otg->otg_clk_sts, mask, true, + CONFIG_SYS_HZ, false); if (ret) return ret; diff --git a/drivers/usb/host/xhci-rcar.c b/drivers/usb/host/xhci-rcar.c index d47c99644d..71202d7b03 100644 --- a/drivers/usb/host/xhci-rcar.c +++ b/drivers/usb/host/xhci-rcar.c @@ -55,18 +55,18 @@ static int xhci_rcar_download_fw(struct rcar_xhci *ctx, const u32 *fw_data, setbits_le32(regs + RCAR_USB3_DL_CTRL, RCAR_USB3_DL_CTRL_FW_SET_DATA0); - ret = wait_for_bit("xhci-rcar", regs + RCAR_USB3_DL_CTRL, - RCAR_USB3_DL_CTRL_FW_SET_DATA0, false, - 10, false); + ret = wait_for_bit_le32(regs + RCAR_USB3_DL_CTRL, + RCAR_USB3_DL_CTRL_FW_SET_DATA0, false, + 10, false); if (ret) break; } clrbits_le32(regs + RCAR_USB3_DL_CTRL, RCAR_USB3_DL_CTRL_ENABLE); - ret = wait_for_bit("xhci-rcar", regs + RCAR_USB3_DL_CTRL, - RCAR_USB3_DL_CTRL_FW_SUCCESS, true, - 10, false); + ret = wait_for_bit_le32(regs + RCAR_USB3_DL_CTRL, + RCAR_USB3_DL_CTRL_FW_SUCCESS, true, + 10, false); return ret; } diff --git a/drivers/video/atmel_hlcdfb.c b/drivers/video/atmel_hlcdfb.c index f77da2ec97..c0dd689e7c 100644 --- a/drivers/video/atmel_hlcdfb.c +++ b/drivers/video/atmel_hlcdfb.c @@ -70,26 +70,26 @@ void lcd_ctrl_init(void *lcdbase) /* Disable DISP signal */ writel(LCDC_LCDDIS_DISPDIS, ®s->lcdc_lcddis); - ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_DISPSTS, - false, 1000, false); + ret = wait_for_bit_le32(®s->lcdc_lcdsr, LCDC_LCDSR_DISPSTS, + false, 1000, false); if (ret) printf("%s: %d: Timeout!\n", __func__, __LINE__); /* Disable synchronization */ writel(LCDC_LCDDIS_SYNCDIS, ®s->lcdc_lcddis); - ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_LCDSTS, - false, 1000, false); + ret = wait_for_bit_le32(®s->lcdc_lcdsr, LCDC_LCDSR_LCDSTS, + false, 1000, false); if (ret) printf("%s: %d: Timeout!\n", __func__, __LINE__); /* Disable pixel clock */ writel(LCDC_LCDDIS_CLKDIS, ®s->lcdc_lcddis); - ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_CLKSTS, - false, 1000, false); + ret = wait_for_bit_le32(®s->lcdc_lcdsr, LCDC_LCDSR_CLKSTS, + false, 1000, false); if (ret) printf("%s: %d: Timeout!\n", __func__, __LINE__); /* Disable PWM */ writel(LCDC_LCDDIS_PWMDIS, ®s->lcdc_lcddis); - ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_PWMSTS, - false, 1000, false); + ret = wait_for_bit_le32(®s->lcdc_lcdsr, LCDC_LCDSR_PWMSTS, + false, 1000, false); if (ret) printf("%s: %d: Timeout!\n", __func__, __LINE__); @@ -215,26 +215,26 @@ void lcd_ctrl_init(void *lcdbase) /* Enable LCD */ value = readl(®s->lcdc_lcden); writel(value | LCDC_LCDEN_CLKEN, ®s->lcdc_lcden); - ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_CLKSTS, - true, 1000, false); + ret = wait_for_bit_le32(®s->lcdc_lcdsr, LCDC_LCDSR_CLKSTS, + true, 1000, false); if (ret) printf("%s: %d: Timeout!\n", __func__, __LINE__); value = readl(®s->lcdc_lcden); writel(value | LCDC_LCDEN_SYNCEN, ®s->lcdc_lcden); - ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_LCDSTS, - true, 1000, false); + ret = wait_for_bit_le32(®s->lcdc_lcdsr, LCDC_LCDSR_LCDSTS, + true, 1000, false); if (ret) printf("%s: %d: Timeout!\n", __func__, __LINE__); value = readl(®s->lcdc_lcden); writel(value | LCDC_LCDEN_DISPEN, ®s->lcdc_lcden); - ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_DISPSTS, - true, 1000, false); + ret = wait_for_bit_le32(®s->lcdc_lcdsr, LCDC_LCDSR_DISPSTS, + true, 1000, false); if (ret) printf("%s: %d: Timeout!\n", __func__, __LINE__); value = readl(®s->lcdc_lcden); writel(value | LCDC_LCDEN_PWMEN, ®s->lcdc_lcden); - ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_PWMSTS, - true, 1000, false); + ret = wait_for_bit_le32(®s->lcdc_lcdsr, LCDC_LCDSR_PWMSTS, + true, 1000, false); if (ret) printf("%s: %d: Timeout!\n", __func__, __LINE__); @@ -299,26 +299,26 @@ static void atmel_hlcdc_init(struct udevice *dev) /* Disable DISP signal */ writel(LCDC_LCDDIS_DISPDIS, ®s->lcdc_lcddis); - ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_DISPSTS, - false, 1000, false); + ret = wait_for_bit_le32(®s->lcdc_lcdsr, LCDC_LCDSR_DISPSTS, + false, 1000, false); if (ret) printf("%s: %d: Timeout!\n", __func__, __LINE__); /* Disable synchronization */ writel(LCDC_LCDDIS_SYNCDIS, ®s->lcdc_lcddis); - ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_LCDSTS, - false, 1000, false); + ret = wait_for_bit_le32(®s->lcdc_lcdsr, LCDC_LCDSR_LCDSTS, + false, 1000, false); if (ret) printf("%s: %d: Timeout!\n", __func__, __LINE__); /* Disable pixel clock */ writel(LCDC_LCDDIS_CLKDIS, ®s->lcdc_lcddis); - ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_CLKSTS, - false, 1000, false); + ret = wait_for_bit_le32(®s->lcdc_lcdsr, LCDC_LCDSR_CLKSTS, + false, 1000, false); if (ret) printf("%s: %d: Timeout!\n", __func__, __LINE__); /* Disable PWM */ writel(LCDC_LCDDIS_PWMDIS, ®s->lcdc_lcddis); - ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_PWMSTS, - false, 1000, false); + ret = wait_for_bit_le32(®s->lcdc_lcdsr, LCDC_LCDSR_PWMSTS, + false, 1000, false); if (ret) printf("%s: %d: Timeout!\n", __func__, __LINE__); @@ -451,26 +451,26 @@ static void atmel_hlcdc_init(struct udevice *dev) /* Enable LCD */ value = readl(®s->lcdc_lcden); writel(value | LCDC_LCDEN_CLKEN, ®s->lcdc_lcden); - ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_CLKSTS, - true, 1000, false); + ret = wait_for_bit_le32(®s->lcdc_lcdsr, LCDC_LCDSR_CLKSTS, + true, 1000, false); if (ret) printf("%s: %d: Timeout!\n", __func__, __LINE__); value = readl(®s->lcdc_lcden); writel(value | LCDC_LCDEN_SYNCEN, ®s->lcdc_lcden); - ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_LCDSTS, - true, 1000, false); + ret = wait_for_bit_le32(®s->lcdc_lcdsr, LCDC_LCDSR_LCDSTS, + true, 1000, false); if (ret) printf("%s: %d: Timeout!\n", __func__, __LINE__); value = readl(®s->lcdc_lcden); writel(value | LCDC_LCDEN_DISPEN, ®s->lcdc_lcden); - ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_DISPSTS, - true, 1000, false); + ret = wait_for_bit_le32(®s->lcdc_lcdsr, LCDC_LCDSR_DISPSTS, + true, 1000, false); if (ret) printf("%s: %d: Timeout!\n", __func__, __LINE__); value = readl(®s->lcdc_lcden); writel(value | LCDC_LCDEN_PWMEN, ®s->lcdc_lcden); - ret = wait_for_bit(__func__, ®s->lcdc_lcdsr, LCDC_LCDSR_PWMSTS, - true, 1000, false); + ret = wait_for_bit_le32(®s->lcdc_lcdsr, LCDC_LCDSR_PWMSTS, + true, 1000, false); if (ret) printf("%s: %d: Timeout!\n", __func__, __LINE__); } -- cgit From 8af74edc30bb60a90a5c4d2769ff3129b187796e Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Tue, 23 Jan 2018 17:14:56 +0100 Subject: drivers: spi: allow limiting reads MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For some SPI controllers it's not possible to keep the CS active between transfers and they are limited to a known number of bytes. This splits spi_flash reads into different iterations in order to respect the SPI controller limits. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Simon Glass Reviewed-by: Daniel Schwierzeck Reviewed-by: Jagan Teki --- drivers/mtd/spi/spi_flash.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'drivers') diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index 51e28bf07b..e40e1c01de 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -516,6 +516,9 @@ int spi_flash_cmd_read_ops(struct spi_flash *flash, u32 offset, else read_len = remain_len; + if (spi->max_read_size) + read_len = min(read_len, spi->max_read_size); + spi_flash_addr(read_addr, cmd); ret = spi_flash_read_common(flash, cmd, cmdsz, data, read_len); -- cgit From 6c94bd12c4adca45033ef89daafa66fbfc9acd17 Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Tue, 23 Jan 2018 17:14:57 +0100 Subject: drivers: spi: consider command bytes when sending transfers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Command bytes are part of the written bytes and they should be taken into account when sending a spi transfer. Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Simon Glass Reviewed-by: Daniel Schwierzeck Reviewed-by: Jagan Teki --- drivers/mtd/spi/spi_flash.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/spi_flash.c b/drivers/mtd/spi/spi_flash.c index e40e1c01de..294d9f9d79 100644 --- a/drivers/mtd/spi/spi_flash.c +++ b/drivers/mtd/spi/spi_flash.c @@ -405,7 +405,7 @@ int spi_flash_cmd_write_ops(struct spi_flash *flash, u32 offset, if (spi->max_write_size) chunk_len = min(chunk_len, - (size_t)spi->max_write_size); + spi->max_write_size - sizeof(cmd)); spi_flash_addr(write_addr, cmd); -- cgit From 5ac07d2969e7f1ea2582f97ccacbe9ad9c9d62fc Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Tue, 23 Jan 2018 17:14:58 +0100 Subject: dm: spi: add BCM63xx SPI driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This driver is a simplified version of linux/drivers/spi/spi-bcm63xx.c Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Simon Glass Reviewed-by: Daniel Schwierzeck Reviewed-by: Jagan Teki --- drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/bcm63xx_spi.c | 433 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 442 insertions(+) create mode 100644 drivers/spi/bcm63xx_spi.c (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index 494639fb01..ebc71c2e42 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -40,6 +40,14 @@ config ATMEL_SPI many AT91 (ARM) chips. This driver can be used to access the SPI Flash, such as AT25DF321. +config BCM63XX_SPI + bool "BCM6348 SPI driver" + depends on ARCH_BMIPS + help + Enable the BCM6348/BCM6358 SPI driver. This driver can be used to + access the SPI NOR flash on platforms embedding these Broadcom + SPI cores. + config CADENCE_QSPI bool "Cadence QSPI driver" help diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index e3184db67f..5770b3f7cc 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -18,6 +18,7 @@ endif obj-$(CONFIG_ALTERA_SPI) += altera_spi.o obj-$(CONFIG_ATH79_SPI) += ath79_spi.o obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o +obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o obj-$(CONFIG_CF_SPI) += cf_spi.o obj-$(CONFIG_DAVINCI_SPI) += davinci_spi.o diff --git a/drivers/spi/bcm63xx_spi.c b/drivers/spi/bcm63xx_spi.c new file mode 100644 index 0000000000..f0df6871d8 --- /dev/null +++ b/drivers/spi/bcm63xx_spi.c @@ -0,0 +1,433 @@ +/* + * Copyright (C) 2017 Álvaro Fernández Rojas + * + * Derived from linux/drivers/spi/spi-bcm63xx.c: + * Copyright (C) 2009-2012 Florian Fainelli + * Copyright (C) 2010 Tanguy Bouzeloc + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* BCM6348 SPI core */ +#define SPI_6348_CLK 0x06 +#define SPI_6348_CMD 0x00 +#define SPI_6348_CTL 0x40 +#define SPI_6348_CTL_SHIFT 6 +#define SPI_6348_FILL 0x07 +#define SPI_6348_IR_MASK 0x04 +#define SPI_6348_IR_STAT 0x02 +#define SPI_6348_RX 0x80 +#define SPI_6348_RX_SIZE 0x3f +#define SPI_6348_TX 0x41 +#define SPI_6348_TX_SIZE 0x3f + +/* BCM6358 SPI core */ +#define SPI_6358_CLK 0x706 +#define SPI_6358_CMD 0x700 +#define SPI_6358_CTL 0x000 +#define SPI_6358_CTL_SHIFT 14 +#define SPI_6358_FILL 0x707 +#define SPI_6358_IR_MASK 0x702 +#define SPI_6358_IR_STAT 0x704 +#define SPI_6358_RX 0x400 +#define SPI_6358_RX_SIZE 0x220 +#define SPI_6358_TX 0x002 +#define SPI_6358_TX_SIZE 0x21e + +/* SPI Clock register */ +#define SPI_CLK_SHIFT 0 +#define SPI_CLK_20MHZ (0 << SPI_CLK_SHIFT) +#define SPI_CLK_0_391MHZ (1 << SPI_CLK_SHIFT) +#define SPI_CLK_0_781MHZ (2 << SPI_CLK_SHIFT) +#define SPI_CLK_1_563MHZ (3 << SPI_CLK_SHIFT) +#define SPI_CLK_3_125MHZ (4 << SPI_CLK_SHIFT) +#define SPI_CLK_6_250MHZ (5 << SPI_CLK_SHIFT) +#define SPI_CLK_12_50MHZ (6 << SPI_CLK_SHIFT) +#define SPI_CLK_25MHZ (7 << SPI_CLK_SHIFT) +#define SPI_CLK_MASK (7 << SPI_CLK_SHIFT) +#define SPI_CLK_SSOFF_SHIFT 3 +#define SPI_CLK_SSOFF_2 (2 << SPI_CLK_SSOFF_SHIFT) +#define SPI_CLK_SSOFF_MASK (7 << SPI_CLK_SSOFF_SHIFT) +#define SPI_CLK_BSWAP_SHIFT 7 +#define SPI_CLK_BSWAP_MASK (1 << SPI_CLK_BSWAP_SHIFT) + +/* SPI Command register */ +#define SPI_CMD_OP_SHIFT 0 +#define SPI_CMD_OP_START (0x3 << SPI_CMD_OP_SHIFT) +#define SPI_CMD_SLAVE_SHIFT 4 +#define SPI_CMD_SLAVE_MASK (0xf << SPI_CMD_SLAVE_SHIFT) +#define SPI_CMD_PREPEND_SHIFT 8 +#define SPI_CMD_PREPEND_BYTES 0xf +#define SPI_CMD_3WIRE_SHIFT 12 +#define SPI_CMD_3WIRE_MASK (1 << SPI_CMD_3WIRE_SHIFT) + +/* SPI Control register */ +#define SPI_CTL_TYPE_FD_RW 0 +#define SPI_CTL_TYPE_HD_W 1 +#define SPI_CTL_TYPE_HD_R 2 + +/* SPI Interrupt registers */ +#define SPI_IR_DONE_SHIFT 0 +#define SPI_IR_DONE_MASK (1 << SPI_IR_DONE_SHIFT) +#define SPI_IR_RXOVER_SHIFT 1 +#define SPI_IR_RXOVER_MASK (1 << SPI_IR_RXOVER_SHIFT) +#define SPI_IR_TXUNDER_SHIFT 2 +#define SPI_IR_TXUNDER_MASK (1 << SPI_IR_TXUNDER_SHIFT) +#define SPI_IR_TXOVER_SHIFT 3 +#define SPI_IR_TXOVER_MASK (1 << SPI_IR_TXOVER_SHIFT) +#define SPI_IR_RXUNDER_SHIFT 4 +#define SPI_IR_RXUNDER_MASK (1 << SPI_IR_RXUNDER_SHIFT) +#define SPI_IR_CLEAR_MASK (SPI_IR_DONE_MASK |\ + SPI_IR_RXOVER_MASK |\ + SPI_IR_TXUNDER_MASK |\ + SPI_IR_TXOVER_MASK |\ + SPI_IR_RXUNDER_MASK) + +enum bcm63xx_regs_spi { + SPI_CLK, + SPI_CMD, + SPI_CTL, + SPI_CTL_SHIFT, + SPI_FILL, + SPI_IR_MASK, + SPI_IR_STAT, + SPI_RX, + SPI_RX_SIZE, + SPI_TX, + SPI_TX_SIZE, +}; + +struct bcm63xx_spi_priv { + const unsigned long *regs; + void __iomem *base; + size_t tx_bytes; + uint8_t num_cs; +}; + +#define SPI_CLK_CNT 8 +static const unsigned bcm63xx_spi_freq_table[SPI_CLK_CNT][2] = { + { 25000000, SPI_CLK_25MHZ }, + { 20000000, SPI_CLK_20MHZ }, + { 12500000, SPI_CLK_12_50MHZ }, + { 6250000, SPI_CLK_6_250MHZ }, + { 3125000, SPI_CLK_3_125MHZ }, + { 1563000, SPI_CLK_1_563MHZ }, + { 781000, SPI_CLK_0_781MHZ }, + { 391000, SPI_CLK_0_391MHZ } +}; + +static int bcm63xx_spi_cs_info(struct udevice *bus, uint cs, + struct spi_cs_info *info) +{ + struct bcm63xx_spi_priv *priv = dev_get_priv(bus); + + if (cs >= priv->num_cs) { + printf("no cs %u\n", cs); + return -ENODEV; + } + + return 0; +} + +static int bcm63xx_spi_set_mode(struct udevice *bus, uint mode) +{ + struct bcm63xx_spi_priv *priv = dev_get_priv(bus); + const unsigned long *regs = priv->regs; + + if (mode & SPI_LSB_FIRST) + setbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK); + else + clrbits_8(priv->base + regs[SPI_CLK], SPI_CLK_BSWAP_MASK); + + return 0; +} + +static int bcm63xx_spi_set_speed(struct udevice *bus, uint speed) +{ + struct bcm63xx_spi_priv *priv = dev_get_priv(bus); + const unsigned long *regs = priv->regs; + uint8_t clk_cfg; + int i; + + /* default to lowest clock configuration */ + clk_cfg = SPI_CLK_0_391MHZ; + + /* find the closest clock configuration */ + for (i = 0; i < SPI_CLK_CNT; i++) { + if (speed >= bcm63xx_spi_freq_table[i][0]) { + clk_cfg = bcm63xx_spi_freq_table[i][1]; + break; + } + } + + /* write clock configuration */ + clrsetbits_8(priv->base + regs[SPI_CLK], + SPI_CLK_SSOFF_MASK | SPI_CLK_MASK, + clk_cfg | SPI_CLK_SSOFF_2); + + return 0; +} + +/* + * BCM63xx SPI driver doesn't allow keeping CS active between transfers since + * they are HW controlled. + * However, it provides a mechanism to prepend write transfers prior to read + * transfers (with a maximum prepend of 15 bytes), which is usually enough for + * SPI-connected flashes since reading requires prepending a write transfer of + * 5 bytes. + * + * This implementation takes advantage of the prepend mechanism and combines + * multiple transfers into a single one where possible (single/multiple write + * transfer(s) followed by a final read/write transfer). + * However, it's not possible to buffer reads, which means that read transfers + * should always be done as the final ones. + * On the other hand, take into account that combining write transfers into + * a single one is just buffering and doesn't require prepend mechanism. + */ +static int bcm63xx_spi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent); + const unsigned long *regs = priv->regs; + size_t data_bytes = bitlen / 8; + + if (flags & SPI_XFER_BEGIN) { + /* clear prepends */ + priv->tx_bytes = 0; + + /* initialize hardware */ + writeb_be(0, priv->base + regs[SPI_IR_MASK]); + } + + if (din) { + /* buffering reads not possible since cs is hw controlled */ + if (!(flags & SPI_XFER_END)) { + printf("unable to buffer reads\n"); + return -EINVAL; + } + + /* check rx size */ + if (data_bytes > regs[SPI_RX_SIZE]) { + printf("max rx bytes exceeded\n"); + return -EMSGSIZE; + } + } + + if (dout) { + /* check tx size */ + if (priv->tx_bytes + data_bytes > regs[SPI_TX_SIZE]) { + printf("max tx bytes exceeded\n"); + return -EMSGSIZE; + } + + /* copy tx data */ + memcpy_toio(priv->base + regs[SPI_TX] + priv->tx_bytes, + dout, data_bytes); + priv->tx_bytes += data_bytes; + } + + if (flags & SPI_XFER_END) { + struct dm_spi_slave_platdata *plat = + dev_get_parent_platdata(dev); + uint16_t val, cmd; + int ret; + + /* determine control config */ + if (dout && !din) { + /* buffered write transfers */ + val = priv->tx_bytes; + val |= (SPI_CTL_TYPE_HD_W << regs[SPI_CTL_SHIFT]); + priv->tx_bytes = 0; + } else { + if (dout && din && (flags & SPI_XFER_ONCE)) { + /* full duplex read/write */ + val = data_bytes; + val |= (SPI_CTL_TYPE_FD_RW << + regs[SPI_CTL_SHIFT]); + priv->tx_bytes = 0; + } else { + /* prepended write transfer */ + val = data_bytes; + val |= (SPI_CTL_TYPE_HD_R << + regs[SPI_CTL_SHIFT]); + if (priv->tx_bytes > SPI_CMD_PREPEND_BYTES) { + printf("max prepend bytes exceeded\n"); + return -EMSGSIZE; + } + } + } + + if (regs[SPI_CTL_SHIFT] >= 8) + writew_be(val, priv->base + regs[SPI_CTL]); + else + writeb_be(val, priv->base + regs[SPI_CTL]); + + /* clear interrupts */ + writeb_be(SPI_IR_CLEAR_MASK, priv->base + regs[SPI_IR_STAT]); + + /* issue the transfer */ + cmd = SPI_CMD_OP_START; + cmd |= (plat->cs << SPI_CMD_SLAVE_SHIFT) & SPI_CMD_SLAVE_MASK; + cmd |= (priv->tx_bytes << SPI_CMD_PREPEND_SHIFT); + if (plat->mode & SPI_3WIRE) + cmd |= SPI_CMD_3WIRE_MASK; + writew_be(cmd, priv->base + regs[SPI_CMD]); + + /* enable interrupts */ + writeb_be(SPI_IR_DONE_MASK, priv->base + regs[SPI_IR_MASK]); + + ret = wait_for_bit_8(priv->base + regs[SPI_IR_STAT], + SPI_IR_DONE_MASK, true, 1000, false); + if (ret) { + printf("interrupt timeout\n"); + return ret; + } + + /* copy rx data */ + if (din) + memcpy_fromio(din, priv->base + regs[SPI_RX], + data_bytes); + } + + return 0; +} + +static const struct dm_spi_ops bcm63xx_spi_ops = { + .cs_info = bcm63xx_spi_cs_info, + .set_mode = bcm63xx_spi_set_mode, + .set_speed = bcm63xx_spi_set_speed, + .xfer = bcm63xx_spi_xfer, +}; + +static const unsigned long bcm6348_spi_regs[] = { + [SPI_CLK] = SPI_6348_CLK, + [SPI_CMD] = SPI_6348_CMD, + [SPI_CTL] = SPI_6348_CTL, + [SPI_CTL_SHIFT] = SPI_6348_CTL_SHIFT, + [SPI_FILL] = SPI_6348_FILL, + [SPI_IR_MASK] = SPI_6348_IR_MASK, + [SPI_IR_STAT] = SPI_6348_IR_STAT, + [SPI_RX] = SPI_6348_RX, + [SPI_RX_SIZE] = SPI_6348_RX_SIZE, + [SPI_TX] = SPI_6348_TX, + [SPI_TX_SIZE] = SPI_6348_TX_SIZE, +}; + +static const unsigned long bcm6358_spi_regs[] = { + [SPI_CLK] = SPI_6358_CLK, + [SPI_CMD] = SPI_6358_CMD, + [SPI_CTL] = SPI_6358_CTL, + [SPI_CTL_SHIFT] = SPI_6358_CTL_SHIFT, + [SPI_FILL] = SPI_6358_FILL, + [SPI_IR_MASK] = SPI_6358_IR_MASK, + [SPI_IR_STAT] = SPI_6358_IR_STAT, + [SPI_RX] = SPI_6358_RX, + [SPI_RX_SIZE] = SPI_6358_RX_SIZE, + [SPI_TX] = SPI_6358_TX, + [SPI_TX_SIZE] = SPI_6358_TX_SIZE, +}; + +static const struct udevice_id bcm63xx_spi_ids[] = { + { + .compatible = "brcm,bcm6348-spi", + .data = (ulong)&bcm6348_spi_regs, + }, { + .compatible = "brcm,bcm6358-spi", + .data = (ulong)&bcm6358_spi_regs, + }, { /* sentinel */ } +}; + +static int bcm63xx_spi_child_pre_probe(struct udevice *dev) +{ + struct bcm63xx_spi_priv *priv = dev_get_priv(dev->parent); + const unsigned long *regs = priv->regs; + struct spi_slave *slave = dev_get_parent_priv(dev); + struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); + + /* check cs */ + if (plat->cs >= priv->num_cs) { + printf("no cs %u\n", plat->cs); + return -ENODEV; + } + + /* max read/write sizes */ + slave->max_read_size = regs[SPI_RX_SIZE]; + slave->max_write_size = regs[SPI_TX_SIZE]; + + return 0; +} + +static int bcm63xx_spi_probe(struct udevice *dev) +{ + struct bcm63xx_spi_priv *priv = dev_get_priv(dev); + const unsigned long *regs = + (const unsigned long *)dev_get_driver_data(dev); + struct reset_ctl rst_ctl; + struct clk clk; + fdt_addr_t addr; + fdt_size_t size; + int ret; + + addr = devfdt_get_addr_size_index(dev, 0, &size); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->regs = regs; + priv->base = ioremap(addr, size); + priv->num_cs = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), + "num-cs", 8); + + /* enable clock */ + ret = clk_get_by_index(dev, 0, &clk); + if (ret < 0) + return ret; + + ret = clk_enable(&clk); + if (ret < 0) + return ret; + + ret = clk_free(&clk); + if (ret < 0) + return ret; + + /* perform reset */ + ret = reset_get_by_index(dev, 0, &rst_ctl); + if (ret < 0) + return ret; + + ret = reset_deassert(&rst_ctl); + if (ret < 0) + return ret; + + ret = reset_free(&rst_ctl); + if (ret < 0) + return ret; + + /* initialize hardware */ + writeb_be(0, priv->base + regs[SPI_IR_MASK]); + + /* set fill register */ + writeb_be(0xff, priv->base + regs[SPI_FILL]); + + return 0; +} + +U_BOOT_DRIVER(bcm63xx_spi) = { + .name = "bcm63xx_spi", + .id = UCLASS_SPI, + .of_match = bcm63xx_spi_ids, + .ops = &bcm63xx_spi_ops, + .priv_auto_alloc_size = sizeof(struct bcm63xx_spi_priv), + .child_pre_probe = bcm63xx_spi_child_pre_probe, + .probe = bcm63xx_spi_probe, +}; -- cgit From 29cc4368ad4b8d67ae457681e9249e2008d6fee5 Mon Sep 17 00:00:00 2001 From: Álvaro Fernández Rojas Date: Sat, 20 Jan 2018 02:13:38 +0100 Subject: dm: spi: add BCM63xx HSSPI driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This driver is a simplified version of linux/drivers/spi/spi-bcm63xx-hsspi.c Signed-off-by: Álvaro Fernández Rojas Reviewed-by: Simon Glass Reviewed-by: Daniel Schwierzeck Reviewed-by: Jagan Teki --- drivers/spi/Kconfig | 8 + drivers/spi/Makefile | 1 + drivers/spi/bcm63xx_hsspi.c | 414 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 423 insertions(+) create mode 100644 drivers/spi/bcm63xx_hsspi.c (limited to 'drivers') diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index ebc71c2e42..28ddcf85a3 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig @@ -40,6 +40,14 @@ config ATMEL_SPI many AT91 (ARM) chips. This driver can be used to access the SPI Flash, such as AT25DF321. +config BCM63XX_HSSPI + bool "BCM63XX HSSPI driver" + depends on ARCH_BMIPS + help + Enable the BCM6328 HSSPI driver. This driver can be used to + access the SPI NOR flash on platforms embedding this Broadcom + SPI core. + config BCM63XX_SPI bool "BCM6348 SPI driver" depends on ARCH_BMIPS diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile index 5770b3f7cc..4b6000fd9a 100644 --- a/drivers/spi/Makefile +++ b/drivers/spi/Makefile @@ -18,6 +18,7 @@ endif obj-$(CONFIG_ALTERA_SPI) += altera_spi.o obj-$(CONFIG_ATH79_SPI) += ath79_spi.o obj-$(CONFIG_ATMEL_SPI) += atmel_spi.o +obj-$(CONFIG_BCM63XX_HSSPI) += bcm63xx_hsspi.o obj-$(CONFIG_BCM63XX_SPI) += bcm63xx_spi.o obj-$(CONFIG_CADENCE_QSPI) += cadence_qspi.o cadence_qspi_apb.o obj-$(CONFIG_CF_SPI) += cf_spi.o diff --git a/drivers/spi/bcm63xx_hsspi.c b/drivers/spi/bcm63xx_hsspi.c new file mode 100644 index 0000000000..3393166a1e --- /dev/null +++ b/drivers/spi/bcm63xx_hsspi.c @@ -0,0 +1,414 @@ +/* + * Copyright (C) 2017 Álvaro Fernández Rojas + * + * Derived from linux/drivers/spi/spi-bcm63xx-hsspi.c: + * Copyright (C) 2000-2010 Broadcom Corporation + * Copyright (C) 2012-2013 Jonas Gorski + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +#define HSSPI_PP 0 + +#define SPI_MAX_SYNC_CLOCK 30000000 + +/* SPI Control register */ +#define SPI_CTL_REG 0x000 +#define SPI_CTL_CS_POL_SHIFT 0 +#define SPI_CTL_CS_POL_MASK (0xff << SPI_CTL_CS_POL_SHIFT) +#define SPI_CTL_CLK_GATE_SHIFT 16 +#define SPI_CTL_CLK_GATE_MASK (1 << SPI_CTL_CLK_GATE_SHIFT) +#define SPI_CTL_CLK_POL_SHIFT 17 +#define SPI_CTL_CLK_POL_MASK (1 << SPI_CTL_CLK_POL_SHIFT) + +/* SPI Interrupts registers */ +#define SPI_IR_STAT_REG 0x008 +#define SPI_IR_ST_MASK_REG 0x00c +#define SPI_IR_MASK_REG 0x010 + +#define SPI_IR_CLEAR_ALL 0xff001f1f + +/* SPI Ping-Pong Command registers */ +#define SPI_CMD_REG (0x080 + (0x40 * (HSSPI_PP)) + 0x00) +#define SPI_CMD_OP_SHIFT 0 +#define SPI_CMD_OP_START (0x1 << SPI_CMD_OP_SHIFT) +#define SPI_CMD_PFL_SHIFT 8 +#define SPI_CMD_PFL_MASK (0x7 << SPI_CMD_PFL_SHIFT) +#define SPI_CMD_SLAVE_SHIFT 12 +#define SPI_CMD_SLAVE_MASK (0x7 << SPI_CMD_SLAVE_SHIFT) + +/* SPI Ping-Pong Status registers */ +#define SPI_STAT_REG (0x080 + (0x40 * (HSSPI_PP)) + 0x04) +#define SPI_STAT_SRCBUSY_SHIFT 1 +#define SPI_STAT_SRCBUSY_MASK (1 << SPI_STAT_SRCBUSY_SHIFT) + +/* SPI Profile Clock registers */ +#define SPI_PFL_CLK_REG(x) (0x100 + (0x20 * (x)) + 0x00) +#define SPI_PFL_CLK_FREQ_SHIFT 0 +#define SPI_PFL_CLK_FREQ_MASK (0x3fff << SPI_PFL_CLK_FREQ_SHIFT) +#define SPI_PFL_CLK_RSTLOOP_SHIFT 15 +#define SPI_PFL_CLK_RSTLOOP_MASK (1 << SPI_PFL_CLK_RSTLOOP_SHIFT) + +/* SPI Profile Signal registers */ +#define SPI_PFL_SIG_REG(x) (0x100 + (0x20 * (x)) + 0x04) +#define SPI_PFL_SIG_LATCHRIS_SHIFT 12 +#define SPI_PFL_SIG_LATCHRIS_MASK (1 << SPI_PFL_SIG_LATCHRIS_SHIFT) +#define SPI_PFL_SIG_LAUNCHRIS_SHIFT 13 +#define SPI_PFL_SIG_LAUNCHRIS_MASK (1 << SPI_PFL_SIG_LAUNCHRIS_SHIFT) +#define SPI_PFL_SIG_ASYNCIN_SHIFT 16 +#define SPI_PFL_SIG_ASYNCIN_MASK (1 << SPI_PFL_SIG_ASYNCIN_SHIFT) + +/* SPI Profile Mode registers */ +#define SPI_PFL_MODE_REG(x) (0x100 + (0x20 * (x)) + 0x08) +#define SPI_PFL_MODE_FILL_SHIFT 0 +#define SPI_PFL_MODE_FILL_MASK (0xff << SPI_PFL_MODE_FILL_SHIFT) +#define SPI_PFL_MODE_MDRDSZ_SHIFT 16 +#define SPI_PFL_MODE_MDRDSZ_MASK (1 << SPI_PFL_MODE_MDRDSZ_SHIFT) +#define SPI_PFL_MODE_MDWRSZ_SHIFT 18 +#define SPI_PFL_MODE_MDWRSZ_MASK (1 << SPI_PFL_MODE_MDWRSZ_SHIFT) +#define SPI_PFL_MODE_3WIRE_SHIFT 20 +#define SPI_PFL_MODE_3WIRE_MASK (1 << SPI_PFL_MODE_3WIRE_SHIFT) + +/* SPI Ping-Pong FIFO registers */ +#define HSSPI_FIFO_SIZE 0x200 +#define HSSPI_FIFO_BASE (0x200 + \ + (HSSPI_FIFO_SIZE * HSSPI_PP)) + +/* SPI Ping-Pong FIFO OP register */ +#define HSSPI_FIFO_OP_SIZE 0x2 +#define HSSPI_FIFO_OP_REG (HSSPI_FIFO_BASE + 0x00) +#define HSSPI_FIFO_OP_BYTES_SHIFT 0 +#define HSSPI_FIFO_OP_BYTES_MASK (0x3ff << HSSPI_FIFO_OP_BYTES_SHIFT) +#define HSSPI_FIFO_OP_MBIT_SHIFT 11 +#define HSSPI_FIFO_OP_MBIT_MASK (1 << HSSPI_FIFO_OP_MBIT_SHIFT) +#define HSSPI_FIFO_OP_CODE_SHIFT 13 +#define HSSPI_FIFO_OP_READ_WRITE (1 << HSSPI_FIFO_OP_CODE_SHIFT) +#define HSSPI_FIFO_OP_CODE_W (2 << HSSPI_FIFO_OP_CODE_SHIFT) +#define HSSPI_FIFO_OP_CODE_R (3 << HSSPI_FIFO_OP_CODE_SHIFT) + +struct bcm63xx_hsspi_priv { + void __iomem *regs; + ulong clk_rate; + uint8_t num_cs; + uint8_t cs_pols; + uint speed; +}; + +static int bcm63xx_hsspi_cs_info(struct udevice *bus, uint cs, + struct spi_cs_info *info) +{ + struct bcm63xx_hsspi_priv *priv = dev_get_priv(bus); + + if (cs >= priv->num_cs) { + printf("no cs %u\n", cs); + return -ENODEV; + } + + return 0; +} + +static int bcm63xx_hsspi_set_mode(struct udevice *bus, uint mode) +{ + struct bcm63xx_hsspi_priv *priv = dev_get_priv(bus); + + /* clock polarity */ + if (mode & SPI_CPOL) + setbits_be32(priv->regs + SPI_CTL_REG, SPI_CTL_CLK_POL_MASK); + else + clrbits_be32(priv->regs + SPI_CTL_REG, SPI_CTL_CLK_POL_MASK); + + return 0; +} + +static int bcm63xx_hsspi_set_speed(struct udevice *bus, uint speed) +{ + struct bcm63xx_hsspi_priv *priv = dev_get_priv(bus); + + priv->speed = speed; + + return 0; +} + +static void bcm63xx_hsspi_activate_cs(struct bcm63xx_hsspi_priv *priv, + struct dm_spi_slave_platdata *plat) +{ + uint32_t clr, set; + + /* profile clock */ + set = DIV_ROUND_UP(priv->clk_rate, priv->speed); + set = DIV_ROUND_UP(2048, set); + set &= SPI_PFL_CLK_FREQ_MASK; + set |= SPI_PFL_CLK_RSTLOOP_MASK; + writel_be(set, priv->regs + SPI_PFL_CLK_REG(plat->cs)); + + /* profile signal */ + set = 0; + clr = SPI_PFL_SIG_LAUNCHRIS_MASK | + SPI_PFL_SIG_LATCHRIS_MASK | + SPI_PFL_SIG_ASYNCIN_MASK; + + /* latch/launch config */ + if (plat->mode & SPI_CPHA) + set |= SPI_PFL_SIG_LAUNCHRIS_MASK; + else + set |= SPI_PFL_SIG_LATCHRIS_MASK; + + /* async clk */ + if (priv->speed > SPI_MAX_SYNC_CLOCK) + set |= SPI_PFL_SIG_ASYNCIN_MASK; + + clrsetbits_be32(priv->regs + SPI_PFL_SIG_REG(plat->cs), clr, set); + + /* global control */ + set = 0; + clr = 0; + + /* invert cs polarity */ + if (priv->cs_pols & BIT(plat->cs)) + clr |= BIT(plat->cs); + else + set |= BIT(plat->cs); + + /* invert dummy cs polarity */ + if (priv->cs_pols & BIT(!plat->cs)) + clr |= BIT(!plat->cs); + else + set |= BIT(!plat->cs); + + clrsetbits_be32(priv->regs + SPI_CTL_REG, clr, set); +} + +static void bcm63xx_hsspi_deactivate_cs(struct bcm63xx_hsspi_priv *priv) +{ + /* restore cs polarities */ + clrsetbits_be32(priv->regs + SPI_CTL_REG, SPI_CTL_CS_POL_MASK, + priv->cs_pols); +} + +/* + * BCM63xx HSSPI driver doesn't allow keeping CS active between transfers + * because they are controlled by HW. + * However, it provides a mechanism to prepend write transfers prior to read + * transfers (with a maximum prepend of 15 bytes), which is usually enough for + * SPI-connected flashes since reading requires prepending a write transfer of + * 5 bytes. On the other hand it also provides a way to invert each CS + * polarity, not only between transfers like the older BCM63xx SPI driver, but + * also the rest of the time. + * + * Instead of using the prepend mechanism, this implementation inverts the + * polarity of both the desired CS and another dummy CS when the bus is + * claimed. This way, the dummy CS is restored to its inactive value when + * transfers are issued and the desired CS is preserved in its active value + * all the time. This hack is also used in the upstream linux driver and + * allows keeping CS active between trasnfers even if the HW doesn't give + * this possibility. + */ +static int bcm63xx_hsspi_xfer(struct udevice *dev, unsigned int bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct bcm63xx_hsspi_priv *priv = dev_get_priv(dev->parent); + struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); + size_t data_bytes = bitlen / 8; + size_t step_size = HSSPI_FIFO_SIZE; + uint16_t opcode = 0; + uint32_t val; + const uint8_t *tx = dout; + uint8_t *rx = din; + + if (flags & SPI_XFER_BEGIN) + bcm63xx_hsspi_activate_cs(priv, plat); + + /* fifo operation */ + if (tx && rx) + opcode = HSSPI_FIFO_OP_READ_WRITE; + else if (rx) + opcode = HSSPI_FIFO_OP_CODE_R; + else if (tx) + opcode = HSSPI_FIFO_OP_CODE_W; + + if (opcode != HSSPI_FIFO_OP_CODE_R) + step_size -= HSSPI_FIFO_OP_SIZE; + + /* dual mode */ + if ((opcode == HSSPI_FIFO_OP_CODE_R && plat->mode == SPI_RX_DUAL) || + (opcode == HSSPI_FIFO_OP_CODE_W && plat->mode == SPI_TX_DUAL)) + opcode |= HSSPI_FIFO_OP_MBIT_MASK; + + /* profile mode */ + val = SPI_PFL_MODE_FILL_MASK | + SPI_PFL_MODE_MDRDSZ_MASK | + SPI_PFL_MODE_MDWRSZ_MASK; + if (plat->mode & SPI_3WIRE) + val |= SPI_PFL_MODE_3WIRE_MASK; + writel_be(val, priv->regs + SPI_PFL_MODE_REG(plat->cs)); + + /* transfer loop */ + while (data_bytes > 0) { + size_t curr_step = min(step_size, data_bytes); + int ret; + + /* copy tx data */ + if (tx) { + memcpy_toio(priv->regs + HSSPI_FIFO_BASE + + HSSPI_FIFO_OP_SIZE, tx, curr_step); + tx += curr_step; + } + + /* set fifo operation */ + writew_be(opcode | (curr_step & HSSPI_FIFO_OP_BYTES_MASK), + priv->regs + HSSPI_FIFO_OP_REG); + + /* issue the transfer */ + val = SPI_CMD_OP_START; + val |= (plat->cs << SPI_CMD_PFL_SHIFT) & + SPI_CMD_PFL_MASK; + val |= (!plat->cs << SPI_CMD_SLAVE_SHIFT) & + SPI_CMD_SLAVE_MASK; + writel_be(val, priv->regs + SPI_CMD_REG); + + /* wait for completion */ + ret = wait_for_bit_be32(priv->regs + SPI_STAT_REG, + SPI_STAT_SRCBUSY_MASK, false, + 1000, false); + if (ret) { + printf("interrupt timeout\n"); + return ret; + } + + /* copy rx data */ + if (rx) { + memcpy_fromio(rx, priv->regs + HSSPI_FIFO_BASE, + curr_step); + rx += curr_step; + } + + data_bytes -= curr_step; + } + + if (flags & SPI_XFER_END) + bcm63xx_hsspi_deactivate_cs(priv); + + return 0; +} + +static const struct dm_spi_ops bcm63xx_hsspi_ops = { + .cs_info = bcm63xx_hsspi_cs_info, + .set_mode = bcm63xx_hsspi_set_mode, + .set_speed = bcm63xx_hsspi_set_speed, + .xfer = bcm63xx_hsspi_xfer, +}; + +static const struct udevice_id bcm63xx_hsspi_ids[] = { + { .compatible = "brcm,bcm6328-hsspi", }, + { /* sentinel */ } +}; + +static int bcm63xx_hsspi_child_pre_probe(struct udevice *dev) +{ + struct bcm63xx_hsspi_priv *priv = dev_get_priv(dev->parent); + struct dm_spi_slave_platdata *plat = dev_get_parent_platdata(dev); + + /* check cs */ + if (plat->cs >= priv->num_cs) { + printf("no cs %u\n", plat->cs); + return -ENODEV; + } + + /* cs polarity */ + if (plat->mode & SPI_CS_HIGH) + priv->cs_pols |= BIT(plat->cs); + else + priv->cs_pols &= ~BIT(plat->cs); + + return 0; +} + +static int bcm63xx_hsspi_probe(struct udevice *dev) +{ + struct bcm63xx_hsspi_priv *priv = dev_get_priv(dev); + struct reset_ctl rst_ctl; + struct clk clk; + fdt_addr_t addr; + fdt_size_t size; + int ret; + + addr = devfdt_get_addr_size_index(dev, 0, &size); + if (addr == FDT_ADDR_T_NONE) + return -EINVAL; + + priv->regs = ioremap(addr, size); + priv->num_cs = fdtdec_get_uint(gd->fdt_blob, dev_of_offset(dev), + "num-cs", 8); + + /* enable clock */ + ret = clk_get_by_name(dev, "hsspi", &clk); + if (ret < 0) + return ret; + + ret = clk_enable(&clk); + if (ret < 0) + return ret; + + ret = clk_free(&clk); + if (ret < 0) + return ret; + + /* get clock rate */ + ret = clk_get_by_name(dev, "pll", &clk); + if (ret < 0) + return ret; + + priv->clk_rate = clk_get_rate(&clk); + + ret = clk_free(&clk); + if (ret < 0) + return ret; + + /* perform reset */ + ret = reset_get_by_index(dev, 0, &rst_ctl); + if (ret < 0) + return ret; + + ret = reset_deassert(&rst_ctl); + if (ret < 0) + return ret; + + ret = reset_free(&rst_ctl); + if (ret < 0) + return ret; + + /* initialize hardware */ + writel_be(0, priv->regs + SPI_IR_MASK_REG); + + /* clear pending interrupts */ + writel_be(SPI_IR_CLEAR_ALL, priv->regs + SPI_IR_STAT_REG); + + /* enable clk gate */ + setbits_be32(priv->regs + SPI_CTL_REG, SPI_CTL_CLK_GATE_MASK); + + /* read default cs polarities */ + priv->cs_pols = readl_be(priv->regs + SPI_CTL_REG) & + SPI_CTL_CS_POL_MASK; + + return 0; +} + +U_BOOT_DRIVER(bcm63xx_hsspi) = { + .name = "bcm63xx_hsspi", + .id = UCLASS_SPI, + .of_match = bcm63xx_hsspi_ids, + .ops = &bcm63xx_hsspi_ops, + .priv_auto_alloc_size = sizeof(struct bcm63xx_hsspi_priv), + .child_pre_probe = bcm63xx_hsspi_child_pre_probe, + .probe = bcm63xx_hsspi_probe, +}; -- cgit From 547bcc3d18ddcc107b8aa7ca393830590c27978f Mon Sep 17 00:00:00 2001 From: Mario Six Date: Mon, 15 Jan 2018 11:08:35 +0100 Subject: spi: Fix style violation and improve code This patch fixes a printf specifier style violation, reduces the scope of a variable, and turns a void pointer that is used with pointer arithmetic into a u8 pointer. Signed-off-by: Mario Six Reviewed-by: Jagan Teki --- drivers/spi/spi.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 7d81fbd7f8..dea8dcda5b 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -12,7 +12,7 @@ int spi_set_wordlen(struct spi_slave *slave, unsigned int wordlen) { if (wordlen == 0 || wordlen > 32) { - printf("spi: invalid wordlen %d\n", wordlen); + printf("spi: invalid wordlen %u\n", wordlen); return -1; } @@ -24,11 +24,12 @@ int spi_set_wordlen(struct spi_slave *slave, unsigned int wordlen) void *spi_do_alloc_slave(int offset, int size, unsigned int bus, unsigned int cs) { - struct spi_slave *slave; - void *ptr; + u8 *ptr; ptr = malloc(size); if (ptr) { + struct spi_slave *slave; + memset(ptr, '\0', size); slave = (struct spi_slave *)(ptr + offset); slave->bus = bus; -- cgit From c5b88f29ba46997e1cae39153980cae475b87b82 Mon Sep 17 00:00:00 2001 From: Mario Six Date: Mon, 15 Jan 2018 11:08:36 +0100 Subject: spi: Remove obsolete spi_base_setup_slave_fdt 0efc024 ("spi_flash: Add spi_flash_probe_fdt() to locate SPI by FDT node") added a helper function spi_base_setup_slave_fdt to to set up a SPI slave from a given FDT blob. The only user was the exynos SPI driver. But commit 73186c9 ("dm: exynos: Convert SPI to driver model") removed the use of this function, hence rendering it obsolete. Remove this function, as well as the CONFIG_OF_SPI option, which guarded only this function. Reviewed-by: Simon Glass Reviewed-by: Jagan Teki Signed-off-by: Mario Six --- drivers/spi/spi.c | 20 -------------------- 1 file changed, 20 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index dea8dcda5b..45e73d28e4 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -39,23 +39,3 @@ void *spi_do_alloc_slave(int offset, int size, unsigned int bus, return ptr; } - -#ifdef CONFIG_OF_SPI -struct spi_slave *spi_base_setup_slave_fdt(const void *blob, int busnum, - int node) -{ - int cs, max_hz, mode = 0; - - cs = fdtdec_get_int(blob, node, "reg", -1); - max_hz = fdtdec_get_int(blob, node, "spi-max-frequency", 100000); - if (fdtdec_get_bool(blob, node, "spi-cpol")) - mode |= SPI_CPOL; - if (fdtdec_get_bool(blob, node, "spi-cpha")) - mode |= SPI_CPHA; - if (fdtdec_get_bool(blob, node, "spi-cs-high")) - mode |= SPI_CS_HIGH; - if (fdtdec_get_bool(blob, node, "spi-half-duplex")) - mode |= SPI_PREAMBLE; - return spi_setup_slave(busnum, cs, max_hz, mode); -} -#endif -- cgit From 74ea6e82f8f626c8c3098dea72f008e8ec0357f9 Mon Sep 17 00:00:00 2001 From: Mario Six Date: Mon, 15 Jan 2018 11:08:37 +0100 Subject: spi: Remove spi_flash_probe_fdt Commit ba45756 ("dm: x86: spi: Convert ICH SPI driver to driver model") removed the last usage of the spi_flash_probe_fdt function, rendering it obsolete. This patch removes the function. Reviewed-by: Simon Glass Reviewed-by: Jagan Teki Signed-off-by: Mario Six --- drivers/mtd/spi/sf_probe.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 7b296378d2..e25513b77a 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -87,19 +87,6 @@ struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, return spi_flash_probe_tail(bus); } -#ifdef CONFIG_OF_SPI_FLASH -struct spi_flash *spi_flash_probe_fdt(const void *blob, int slave_node, - int spi_node) -{ - struct spi_slave *bus; - - bus = spi_setup_slave_fdt(blob, slave_node, spi_node); - if (!bus) - return NULL; - return spi_flash_probe_tail(bus); -} -#endif - void spi_flash_free(struct spi_flash *flash) { #ifdef CONFIG_SPI_FLASH_MTD -- cgit From 184fa1c8da54d3c5305b3e1975e284e01de68bea Mon Sep 17 00:00:00 2001 From: Mario Six Date: Mon, 15 Jan 2018 11:08:38 +0100 Subject: spi: Remove spi_setup_slave_fdt A previous patch removed the spi_flash_probe_fdt function, which contained the last call of the spi_setup_slave_fdt function, which is now equally obsolete. This patch removes the function. Reviewed-by: Simon Glass Reviewed-by: Jagan Teki Signed-off-by: Mario Six --- drivers/spi/spi-uclass.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index e06a603ab1..6db0eb02b4 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -347,22 +347,6 @@ err: return ret; } -/* Compatibility function - to be removed */ -struct spi_slave *spi_setup_slave_fdt(const void *blob, int node, - int bus_node) -{ - struct udevice *bus, *dev; - int ret; - - ret = uclass_get_device_by_of_offset(UCLASS_SPI, bus_node, &bus); - if (ret) - return NULL; - ret = device_get_child_by_of_offset(bus, node, &dev); - if (ret) - return NULL; - return dev_get_parent_priv(dev); -} - /* Compatibility function - to be removed */ struct spi_slave *spi_setup_slave(unsigned int busnum, unsigned int cs, unsigned int speed, unsigned int mode) -- cgit From a3e32c5038aa674535ba1e48e994e9368ad47055 Mon Sep 17 00:00:00 2001 From: Mario Six Date: Mon, 15 Jan 2018 11:08:40 +0100 Subject: spi: sf_probe: Fix style violations Fix two indention-related style violations. Signed-off-by: Mario Six Reviewed-by: Jagan Teki --- drivers/mtd/spi/sf_probe.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index e25513b77a..68009a6328 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -77,7 +77,7 @@ static struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus) } struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, - unsigned int max_hz, unsigned int spi_mode) + unsigned int max_hz, unsigned int spi_mode) { struct spi_slave *bus; @@ -107,7 +107,7 @@ static int spi_flash_std_read(struct udevice *dev, u32 offset, size_t len, } static int spi_flash_std_write(struct udevice *dev, u32 offset, size_t len, - const void *buf) + const void *buf) { struct spi_flash *flash = dev_get_uclass_priv(dev); -- cgit From 24fc1ec2ee71cd852e556f90bd352cc809ddeef9 Mon Sep 17 00:00:00 2001 From: Mario Six Date: Mon, 15 Jan 2018 11:08:41 +0100 Subject: spi: spi-uclass: Fix style violations Remove a superfluous newline, and reduce the scope of a variable. Reviewed-by: Simon Glass Reviewed-by: Jagan Teki Signed-off-by: Mario Six --- drivers/spi/spi-uclass.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/spi-uclass.c b/drivers/spi/spi-uclass.c index 6db0eb02b4..15d90a54a1 100644 --- a/drivers/spi/spi-uclass.c +++ b/drivers/spi/spi-uclass.c @@ -50,7 +50,6 @@ int dm_spi_claim_bus(struct udevice *dev) struct dm_spi_bus *spi = dev_get_uclass_priv(bus); struct spi_slave *slave = dev_get_parent_priv(dev); int speed; - int ret; speed = slave->max_hz; if (spi->max_hz) { @@ -62,7 +61,8 @@ int dm_spi_claim_bus(struct udevice *dev) if (!speed) speed = 100000; if (speed != slave->speed) { - ret = spi_set_speed_mode(bus, speed, slave->mode); + int ret = spi_set_speed_mode(bus, speed, slave->mode); + if (ret) return ret; slave->speed = speed; @@ -129,7 +129,6 @@ static int spi_post_probe(struct udevice *bus) #if defined(CONFIG_NEEDS_MANUAL_RELOC) struct dm_spi_ops *ops = spi_get_ops(bus); - if (ops->claim_bus) ops->claim_bus += gd->reloc_off; if (ops->release_bus) -- cgit From 36890ff0d00f6c44631a6453b355f8af1b5ddd53 Mon Sep 17 00:00:00 2001 From: Mario Six Date: Mon, 15 Jan 2018 11:08:42 +0100 Subject: sf_probe: Merge spi_flash_probe_tail into spi_flash_probe spi_flash_probe_tail is now only called from spi_flash_probe, hence we can merge its body into spi_flash_probe. Reviewed-by: Jagan Teki Reviewed-by: Simon Glass Signed-off-by: Mario Six --- drivers/mtd/spi/sf_probe.c | 19 +++++++------------ 1 file changed, 7 insertions(+), 12 deletions(-) (limited to 'drivers') diff --git a/drivers/mtd/spi/sf_probe.c b/drivers/mtd/spi/sf_probe.c index 68009a6328..09143d7868 100644 --- a/drivers/mtd/spi/sf_probe.c +++ b/drivers/mtd/spi/sf_probe.c @@ -55,10 +55,16 @@ err_read_id: } #ifndef CONFIG_DM_SPI_FLASH -static struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus) +struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, + unsigned int max_hz, unsigned int spi_mode) { + struct spi_slave *bus; struct spi_flash *flash; + bus = spi_setup_slave(busnum, cs, max_hz, spi_mode); + if (!bus) + return NULL; + /* Allocate space if needed (not used by sf-uclass */ flash = calloc(1, sizeof(*flash)); if (!flash) { @@ -76,17 +82,6 @@ static struct spi_flash *spi_flash_probe_tail(struct spi_slave *bus) return flash; } -struct spi_flash *spi_flash_probe(unsigned int busnum, unsigned int cs, - unsigned int max_hz, unsigned int spi_mode) -{ - struct spi_slave *bus; - - bus = spi_setup_slave(busnum, cs, max_hz, spi_mode); - if (!bus) - return NULL; - return spi_flash_probe_tail(bus); -} - void spi_flash_free(struct spi_flash *flash) { #ifdef CONFIG_SPI_FLASH_MTD -- cgit From df16881cea50a787c37591bd2168c8ea656217bd Mon Sep 17 00:00:00 2001 From: Chris Packham Date: Mon, 22 Jan 2018 22:44:20 +1300 Subject: spi: kirkwood_spi: implement workaround for FE-9144572 Erratum NO. FE-9144572: The device SPI interface supports frequencies of up to 50 MHz. However, due to this erratum, when the device core clock is 250 MHz and the SPI interfaces is configured for 50MHz SPI clock and CPOL=CPHA=1 there might occur data corruption on reads from the SPI device. Implement the workaround by setting the TMISO_SAMPLE value to 0x2 in the timing1 register. Signed-off-by: Chris Packham Reviewed-by: Stefan Roese Reviewed-by: Jagan Teki --- drivers/spi/kirkwood_spi.c | 69 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 66 insertions(+), 3 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/kirkwood_spi.c b/drivers/spi/kirkwood_spi.c index 0c6bd295cd..1ad8cdee64 100644 --- a/drivers/spi/kirkwood_spi.c +++ b/drivers/spi/kirkwood_spi.c @@ -243,6 +243,10 @@ int spi_xfer(struct spi_slave *slave, unsigned int bitlen, /* Here now the DM part */ +struct mvebu_spi_dev { + bool is_errata_50mhz_ac; +}; + struct mvebu_spi_platdata { struct kwspi_registers *spireg; }; @@ -269,10 +273,44 @@ static int mvebu_spi_set_speed(struct udevice *bus, uint hz) return 0; } +static void mvebu_spi_50mhz_ac_timing_erratum(struct udevice *bus, uint mode) +{ + struct mvebu_spi_platdata *plat = dev_get_platdata(bus); + struct kwspi_registers *reg = plat->spireg; + u32 data; + + /* + * Erratum description: (Erratum NO. FE-9144572) The device + * SPI interface supports frequencies of up to 50 MHz. + * However, due to this erratum, when the device core clock is + * 250 MHz and the SPI interfaces is configured for 50MHz SPI + * clock and CPOL=CPHA=1 there might occur data corruption on + * reads from the SPI device. + * Erratum Workaround: + * Work in one of the following configurations: + * 1. Set CPOL=CPHA=0 in "SPI Interface Configuration + * Register". + * 2. Set TMISO_SAMPLE value to 0x2 in "SPI Timing Parameters 1 + * Register" before setting the interface. + */ + data = readl(®->timing1); + data &= ~KW_SPI_TMISO_SAMPLE_MASK; + + if (CONFIG_SYS_TCLK == 250000000 && + mode & SPI_CPOL && + mode & SPI_CPHA) + data |= KW_SPI_TMISO_SAMPLE_2; + else + data |= KW_SPI_TMISO_SAMPLE_1; + + writel(data, ®->timing1); +} + static int mvebu_spi_set_mode(struct udevice *bus, uint mode) { struct mvebu_spi_platdata *plat = dev_get_platdata(bus); struct kwspi_registers *reg = plat->spireg; + const struct mvebu_spi_dev *drvdata; u32 data = readl(®->cfg); data &= ~(KWSPI_CPHA | KWSPI_CPOL | KWSPI_RXLSBF | KWSPI_TXLSBF); @@ -286,6 +324,10 @@ static int mvebu_spi_set_mode(struct udevice *bus, uint mode) writel(data, ®->cfg); + drvdata = (struct mvebu_spi_dev *)dev_get_driver_data(bus); + if (drvdata->is_errata_50mhz_ac) + mvebu_spi_50mhz_ac_timing_erratum(bus, mode); + return 0; } @@ -343,10 +385,31 @@ static const struct dm_spi_ops mvebu_spi_ops = { */ }; +static const struct mvebu_spi_dev armada_xp_spi_dev_data = { + .is_errata_50mhz_ac = false, +}; + +static const struct mvebu_spi_dev armada_375_spi_dev_data = { + .is_errata_50mhz_ac = false, +}; + +static const struct mvebu_spi_dev armada_380_spi_dev_data = { + .is_errata_50mhz_ac = true, +}; + static const struct udevice_id mvebu_spi_ids[] = { - { .compatible = "marvell,armada-375-spi" }, - { .compatible = "marvell,armada-380-spi" }, - { .compatible = "marvell,armada-xp-spi" }, + { + .compatible = "marvell,armada-375-spi", + .data = (ulong)&armada_375_spi_dev_data + }, + { + .compatible = "marvell,armada-380-spi", + .data = (ulong)&armada_380_spi_dev_data + }, + { + .compatible = "marvell,armada-xp-spi", + .data = (ulong)&armada_xp_spi_dev_data + }, { } }; -- cgit From 15a70a5da33229de884f60684a562ea60fe505b2 Mon Sep 17 00:00:00 2001 From: Jason Rush Date: Tue, 23 Jan 2018 17:13:09 -0600 Subject: spi: cadence_spi: Sync DT bindings with Linux Adopt the Linux DT bindings. This also fixes an issue with the indaddrtrig register on the Cadence QSPI device being programmed with the wrong value for the socfpga arch. Tested on TI K2G platform: Tested-by: Vignesh R Tested on a socfpga-cyclonev board: Tested-by: Simon Goldschmidt Signed-off-by: Jason Rush Reviewed-by: Jagan Teki Acked-by: Simon Goldschmidt Acked-by: Marek Vasut --- drivers/spi/cadence_qspi.c | 20 ++++++++++++-------- drivers/spi/cadence_qspi.h | 6 +++++- drivers/spi/cadence_qspi_apb.c | 15 ++++----------- 3 files changed, 21 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/cadence_qspi.c b/drivers/spi/cadence_qspi.c index 9a6e41f330..7b312f8e3e 100644 --- a/drivers/spi/cadence_qspi.c +++ b/drivers/spi/cadence_qspi.c @@ -212,7 +212,7 @@ static int cadence_spi_xfer(struct udevice *dev, unsigned int bitlen, /* Set Chip select */ cadence_qspi_apb_chipselect(base, spi_chip_select(dev), - CONFIG_CQSPI_DECODER); + plat->is_decoded_cs); if ((flags & SPI_XFER_END) || (flags == 0)) { if (priv->cmd_len == 0) { @@ -296,7 +296,11 @@ static int cadence_spi_ofdata_to_platdata(struct udevice *bus) plat->regbase = (void *)data[0]; plat->ahbbase = (void *)data[2]; - plat->sram_size = fdtdec_get_int(blob, node, "sram-size", 128); + plat->is_decoded_cs = fdtdec_get_bool(blob, node, "cdns,is-decoded-cs"); + plat->fifo_depth = fdtdec_get_uint(blob, node, "cdns,fifo-depth", 128); + plat->fifo_width = fdtdec_get_uint(blob, node, "cdns,fifo-width", 4); + plat->trigger_address = fdtdec_get_uint(blob, node, + "cdns,trigger-address", 0); /* All other paramters are embedded in the child node */ subnode = fdt_first_subnode(blob, node); @@ -310,12 +314,12 @@ static int cadence_spi_ofdata_to_platdata(struct udevice *bus) 500000); /* Read other parameters from DT */ - plat->page_size = fdtdec_get_int(blob, subnode, "page-size", 256); - plat->block_size = fdtdec_get_int(blob, subnode, "block-size", 16); - plat->tshsl_ns = fdtdec_get_int(blob, subnode, "tshsl-ns", 200); - plat->tsd2d_ns = fdtdec_get_int(blob, subnode, "tsd2d-ns", 255); - plat->tchsh_ns = fdtdec_get_int(blob, subnode, "tchsh-ns", 20); - plat->tslch_ns = fdtdec_get_int(blob, subnode, "tslch-ns", 20); + plat->page_size = fdtdec_get_uint(blob, subnode, "page-size", 256); + plat->block_size = fdtdec_get_uint(blob, subnode, "block-size", 16); + plat->tshsl_ns = fdtdec_get_uint(blob, subnode, "cdns,tshsl-ns", 200); + plat->tsd2d_ns = fdtdec_get_uint(blob, subnode, "cdns,tsd2d-ns", 255); + plat->tchsh_ns = fdtdec_get_uint(blob, subnode, "cdns,tchsh-ns", 20); + plat->tslch_ns = fdtdec_get_uint(blob, subnode, "cdns,tslch-ns", 20); debug("%s: regbase=%p ahbbase=%p max-frequency=%d page-size=%d\n", __func__, plat->regbase, plat->ahbbase, plat->max_hz, diff --git a/drivers/spi/cadence_qspi.h b/drivers/spi/cadence_qspi.h index d1927a4003..9106b09d29 100644 --- a/drivers/spi/cadence_qspi.h +++ b/drivers/spi/cadence_qspi.h @@ -18,14 +18,18 @@ struct cadence_spi_platdata { unsigned int max_hz; void *regbase; void *ahbbase; + bool is_decoded_cs; + u32 fifo_depth; + u32 fifo_width; + u32 trigger_address; + /* Flash parameters */ u32 page_size; u32 block_size; u32 tshsl_ns; u32 tsd2d_ns; u32 tchsh_ns; u32 tslch_ns; - u32 sram_size; }; struct cadence_spi_priv { diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index dca3fdfdea..c3dd32912e 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -37,10 +37,6 @@ #define CQSPI_REG_RETRY 10000 #define CQSPI_POLL_IDLE_RETRY 3 -#define CQSPI_FIFO_WIDTH 4 - -#define CQSPI_REG_SRAM_THRESHOLD_WORDS 50 - /* Transfer mode */ #define CQSPI_INST_TYPE_SINGLE 0 #define CQSPI_INST_TYPE_DUAL 1 @@ -51,9 +47,6 @@ #define CQSPI_DUMMY_CLKS_PER_BYTE 8 #define CQSPI_DUMMY_BYTES_MAX 4 -#define CQSPI_REG_SRAM_FILL_THRESHOLD \ - ((CQSPI_REG_SRAM_SIZE_WORD / 2) * CQSPI_FIFO_WIDTH) - /**************************************************************************** * Controller's configuration and status register (offset from QSPI_BASE) ****************************************************************************/ @@ -400,7 +393,7 @@ void cadence_qspi_apb_controller_init(struct cadence_spi_platdata *plat) writel(0, plat->regbase + CQSPI_REG_REMAP); /* Indirect mode configurations */ - writel((plat->sram_size/2), plat->regbase + CQSPI_REG_SRAMPARTITION); + writel(plat->fifo_depth / 2, plat->regbase + CQSPI_REG_SRAMPARTITION); /* Disable all interrupts */ writel(0, plat->regbase + CQSPI_REG_IRQMASK); @@ -560,7 +553,7 @@ int cadence_qspi_apb_indirect_read_setup(struct cadence_spi_platdata *plat, addr_bytes = cmdlen - 1; /* Setup the indirect trigger address */ - writel((u32)plat->ahbbase, + writel(plat->trigger_address, plat->regbase + CQSPI_REG_INDIRECTTRIGGER); /* Configure the opcode */ @@ -659,7 +652,7 @@ int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat, bytes_to_read = ret; while (bytes_to_read != 0) { - bytes_to_read *= CQSPI_FIFO_WIDTH; + bytes_to_read *= plat->fifo_width; bytes_to_read = bytes_to_read > remaining ? remaining : bytes_to_read; readsl(plat->ahbbase, bb_rxbuf, bytes_to_read >> 2); @@ -710,7 +703,7 @@ int cadence_qspi_apb_indirect_write_setup(struct cadence_spi_platdata *plat, return -EINVAL; } /* Setup the indirect trigger address */ - writel((u32)plat->ahbbase, + writel(plat->trigger_address, plat->regbase + CQSPI_REG_INDIRECTTRIGGER); /* Configure the opcode */ -- cgit From 948ad4f07598a729a0de523ed3d779115b2fa2f2 Mon Sep 17 00:00:00 2001 From: Goldschmidt Simon Date: Wed, 24 Jan 2018 10:44:05 +0530 Subject: Revert "spi: cadence_qspi_apb: Use 32 bit indirect read transaction when possible" This reverts commit b63b46313ed29e9b0c36b3d6b9407f6eade40c8f. This commit changed cadence_qspi_apb to use bouncebuf.c, which invalidates the data cache after reading. This is meant for dma transfers only and breaks the cadence_qspi driver which copies via cpu only: data that is copied by the cpu is in cache only and the cache invalidation at the end throws away this data. Signed-off-by: Simon Goldschmidt Signed-off-by: Vignesh R Acked-by: Marek Vasut Reviewed-by: Jason Rush Acked-by: Jason Rush Reviewed-by: Jagan Teki --- drivers/spi/cadence_qspi_apb.c | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index c3dd32912e..128c41d715 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -627,8 +627,6 @@ int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat, { unsigned int remaining = n_rx; unsigned int bytes_to_read = 0; - struct bounce_buffer bb; - u8 *bb_rxbuf; int ret; writel(n_rx, plat->regbase + CQSPI_REG_INDIRECTRDBYTES); @@ -637,11 +635,6 @@ int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat, writel(CQSPI_REG_INDIRECTRD_START, plat->regbase + CQSPI_REG_INDIRECTRD); - ret = bounce_buffer_start(&bb, (void *)rxbuf, n_rx, GEN_BB_WRITE); - if (ret) - return ret; - bb_rxbuf = bb.bounce_buffer; - while (remaining > 0) { ret = cadence_qspi_wait_for_data(plat); if (ret < 0) { @@ -655,13 +648,16 @@ int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat, bytes_to_read *= plat->fifo_width; bytes_to_read = bytes_to_read > remaining ? remaining : bytes_to_read; - readsl(plat->ahbbase, bb_rxbuf, bytes_to_read >> 2); - if (bytes_to_read % 4) - readsb(plat->ahbbase, - bb_rxbuf + rounddown(bytes_to_read, 4), - bytes_to_read % 4); - - bb_rxbuf += bytes_to_read; + /* + * Handle non-4-byte aligned access to avoid + * data abort. + */ + if (((uintptr_t)rxbuf % 4) || (bytes_to_read % 4)) + readsb(plat->ahbbase, rxbuf, bytes_to_read); + else + readsl(plat->ahbbase, rxbuf, + bytes_to_read >> 2); + rxbuf += bytes_to_read; remaining -= bytes_to_read; bytes_to_read = cadence_qspi_get_rd_sram_level(plat); } @@ -678,7 +674,6 @@ int cadence_qspi_apb_indirect_read_execute(struct cadence_spi_platdata *plat, /* Clear indirect completion status */ writel(CQSPI_REG_INDIRECTRD_DONE, plat->regbase + CQSPI_REG_INDIRECTRD); - bounce_buffer_stop(&bb); return 0; @@ -686,7 +681,6 @@ failrd: /* Cancel the indirect read */ writel(CQSPI_REG_INDIRECTRD_CANCEL, plat->regbase + CQSPI_REG_INDIRECTRD); - bounce_buffer_stop(&bb); return ret; } -- cgit From a743e2ba3837db5e8499b03f0f57c3610d03a570 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Wed, 24 Jan 2018 10:44:06 +0530 Subject: Revert "spi: cadence_qspi_apb: Use 32 bit indirect write transaction when possible" This reverts commit 57897c13de03ac0136d64641a3eab526c6810387. Using bounce_buf.c to handle non-DMA alignment problems is bad as bounce_buf.c does cache manipulations which is not required. Therefore revert this patch in favour of local bounce buffer solution in the next patch. Signed-off-by: Vignesh R Acked-by: Marek Vasut Acked-by: Simon Goldschmidt Reviewed-by: Jason Rush Acked-by: Jason Rush Reviewed-by: Jagan Teki --- drivers/spi/cadence_qspi_apb.c | 26 ++++++-------------------- 1 file changed, 6 insertions(+), 20 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index 128c41d715..70d0f431ad 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -30,7 +30,6 @@ #include #include #include -#include #include "cadence_qspi.h" #define CQSPI_REG_POLL_US 1 /* 1us */ @@ -722,17 +721,6 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat, unsigned int remaining = n_tx; unsigned int write_bytes; int ret; - struct bounce_buffer bb; - u8 *bb_txbuf; - - /* - * Handle non-4-byte aligned accesses via bounce buffer to - * avoid data abort. - */ - ret = bounce_buffer_start(&bb, (void *)txbuf, n_tx, GEN_BB_READ); - if (ret) - return ret; - bb_txbuf = bb.bounce_buffer; /* Configure the indirect read transfer bytes */ writel(n_tx, plat->regbase + CQSPI_REG_INDIRECTWRBYTES); @@ -743,11 +731,11 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat, while (remaining > 0) { write_bytes = remaining > page_size ? page_size : remaining; - writesl(plat->ahbbase, bb_txbuf, write_bytes >> 2); - if (write_bytes % 4) - writesb(plat->ahbbase, - bb_txbuf + rounddown(write_bytes, 4), - write_bytes % 4); + /* Handle non-4-byte aligned access to avoid data abort. */ + if (((uintptr_t)txbuf % 4) || (write_bytes % 4)) + writesb(plat->ahbbase, txbuf, write_bytes); + else + writesl(plat->ahbbase, txbuf, write_bytes >> 2); ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_SDRAMLEVEL, CQSPI_REG_SDRAMLEVEL_WR_MASK << @@ -757,7 +745,7 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat, goto failwr; } - bb_txbuf += write_bytes; + txbuf += write_bytes; remaining -= write_bytes; } @@ -768,7 +756,6 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat, printf("Indirect write completion error (%i)\n", ret); goto failwr; } - bounce_buffer_stop(&bb); /* Clear indirect completion status */ writel(CQSPI_REG_INDIRECTWR_DONE, @@ -779,7 +766,6 @@ failwr: /* Cancel the indirect write */ writel(CQSPI_REG_INDIRECTWR_CANCEL, plat->regbase + CQSPI_REG_INDIRECTWR); - bounce_buffer_stop(&bb); return ret; } -- cgit From aaa21d3ffc023623a3a8247e5fa25d0db2bfb630 Mon Sep 17 00:00:00 2001 From: Vignesh R Date: Wed, 24 Jan 2018 10:44:07 +0530 Subject: spi: cadence_qspi_apb: Make flash writes 32 bit aligned Make flash writes 32 bit aligned by using bounce buffers to deal with non 32 bit aligned buffers. This is required because as per TI K2G TRM[1], the external master is only permitted to issue 32-bit data interface writes until the last word of an indirect transfer. Otherwise indirect writes is known to fail sometimes. [1] http://www.ti.com/lit/ug/spruhy8g/spruhy8g.pdf Signed-off-by: Vignesh R Acked-by: Marek Vasut Acked-by: Simon Goldschmidt Reviewed-by: Jason Rush Acked-by: Jason Rush Reviewed-by: Jagan Teki --- drivers/spi/cadence_qspi_apb.c | 31 +++++++++++++++++++++++++------ 1 file changed, 25 insertions(+), 6 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/cadence_qspi_apb.c b/drivers/spi/cadence_qspi_apb.c index 70d0f431ad..aa3a9ff5fa 100644 --- a/drivers/spi/cadence_qspi_apb.c +++ b/drivers/spi/cadence_qspi_apb.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "cadence_qspi.h" #define CQSPI_REG_POLL_US 1 /* 1us */ @@ -719,9 +720,23 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat, { unsigned int page_size = plat->page_size; unsigned int remaining = n_tx; + const u8 *bb_txbuf = txbuf; + void *bounce_buf = NULL; unsigned int write_bytes; int ret; + /* + * Use bounce buffer for non 32 bit aligned txbuf to avoid data + * aborts + */ + if ((uintptr_t)txbuf % 4) { + bounce_buf = malloc(n_tx); + if (!bounce_buf) + return -ENOMEM; + memcpy(bounce_buf, txbuf, n_tx); + bb_txbuf = bounce_buf; + } + /* Configure the indirect read transfer bytes */ writel(n_tx, plat->regbase + CQSPI_REG_INDIRECTWRBYTES); @@ -731,11 +746,11 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat, while (remaining > 0) { write_bytes = remaining > page_size ? page_size : remaining; - /* Handle non-4-byte aligned access to avoid data abort. */ - if (((uintptr_t)txbuf % 4) || (write_bytes % 4)) - writesb(plat->ahbbase, txbuf, write_bytes); - else - writesl(plat->ahbbase, txbuf, write_bytes >> 2); + writesl(plat->ahbbase, bb_txbuf, write_bytes >> 2); + if (write_bytes % 4) + writesb(plat->ahbbase, + bb_txbuf + rounddown(write_bytes, 4), + write_bytes % 4); ret = wait_for_bit_le32(plat->regbase + CQSPI_REG_SDRAMLEVEL, CQSPI_REG_SDRAMLEVEL_WR_MASK << @@ -745,7 +760,7 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat, goto failwr; } - txbuf += write_bytes; + bb_txbuf += write_bytes; remaining -= write_bytes; } @@ -760,12 +775,16 @@ int cadence_qspi_apb_indirect_write_execute(struct cadence_spi_platdata *plat, /* Clear indirect completion status */ writel(CQSPI_REG_INDIRECTWR_DONE, plat->regbase + CQSPI_REG_INDIRECTWR); + if (bounce_buf) + free(bounce_buf); return 0; failwr: /* Cancel the indirect write */ writel(CQSPI_REG_INDIRECTWR_CANCEL, plat->regbase + CQSPI_REG_INDIRECTWR); + if (bounce_buf) + free(bounce_buf); return ret; } -- cgit From 58c125b9e2b232ce73ed7b24ba7b1ca5ff41c5bd Mon Sep 17 00:00:00 2001 From: Eugeniy Paltsev Date: Thu, 28 Dec 2017 15:09:03 +0300 Subject: DW SPI: Get clock value from Device Tree Add option to set spi controller clock frequency via device tree using standard clock bindings. Define dw_spi_get_clk function as 'weak' as some targets (like SOCFPGA_GEN5 and SOCFPGA_ARRIA10) don't use standard clock API and implement dw_spi_get_clk their own way in their clock manager. Get rid of clock_manager.h include as we don't use cm_get_spi_controller_clk_hz function anymore. (we use redefined dw_spi_get_clk in SOCFPGA clock managers instead) Reviewed-by: Marek Vasut Signed-off-by: Eugeniy Paltsev Reviewed-by: Jagan Teki --- drivers/spi/designware_spi.c | 45 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 43 insertions(+), 2 deletions(-) (limited to 'drivers') diff --git a/drivers/spi/designware_spi.c b/drivers/spi/designware_spi.c index 5aa507b2d8..c501aeea16 100644 --- a/drivers/spi/designware_spi.c +++ b/drivers/spi/designware_spi.c @@ -11,6 +11,7 @@ */ #include +#include #include #include #include @@ -18,7 +19,6 @@ #include #include #include -#include DECLARE_GLOBAL_DATA_PTR; @@ -94,6 +94,8 @@ struct dw_spi_priv { void __iomem *regs; unsigned int freq; /* Default frequency */ unsigned int mode; + struct clk clk; + unsigned long bus_clk_rate; int bits_per_word; u8 cs; /* chip select pin */ @@ -176,14 +178,53 @@ static void spi_hw_init(struct dw_spi_priv *priv) debug("%s: fifo_len=%d\n", __func__, priv->fifo_len); } +/* + * We define dw_spi_get_clk function as 'weak' as some targets + * (like SOCFPGA_GEN5 and SOCFPGA_ARRIA10) don't use standard clock API + * and implement dw_spi_get_clk their own way in their clock manager. + */ +__weak int dw_spi_get_clk(struct udevice *bus, ulong *rate) +{ + struct dw_spi_priv *priv = dev_get_priv(bus); + int ret; + + ret = clk_get_by_index(bus, 0, &priv->clk); + if (ret) + return ret; + + ret = clk_enable(&priv->clk); + if (ret && ret != -ENOSYS && ret != -ENOTSUPP) + return ret; + + *rate = clk_get_rate(&priv->clk); + if (!*rate) + goto err_rate; + + debug("%s: get spi controller clk via device tree: %lu Hz\n", + __func__, *rate); + + return 0; + +err_rate: + clk_disable(&priv->clk); + clk_free(&priv->clk); + + return -EINVAL; +} + static int dw_spi_probe(struct udevice *bus) { struct dw_spi_platdata *plat = dev_get_platdata(bus); struct dw_spi_priv *priv = dev_get_priv(bus); + int ret; priv->regs = plat->regs; priv->freq = plat->frequency; + ret = dw_spi_get_clk(bus, &priv->bus_clk_rate); + if (ret) + return ret; + /* Currently only bits_per_word == 8 supported */ priv->bits_per_word = 8; @@ -369,7 +410,7 @@ static int dw_spi_set_speed(struct udevice *bus, uint speed) spi_enable_chip(priv, 0); /* clk_div doesn't support odd number */ - clk_div = cm_get_spi_controller_clk_hz() / speed; + clk_div = priv->bus_clk_rate / speed; clk_div = (clk_div + 1) & 0xfffe; dw_writel(priv, DW_SPI_BAUDR, clk_div); -- cgit