1*a51cd54eSJagan Teki /* 2*a51cd54eSJagan Teki * (C) Copyright 2017 Whitebox Systems / Northend Systems B.V. 3*a51cd54eSJagan Teki * S.J.R. van Schaik <stephan@whiteboxsystems.nl> 4*a51cd54eSJagan Teki * M.B.W. Wajer <merlijn@whiteboxsystems.nl> 5*a51cd54eSJagan Teki * 6*a51cd54eSJagan Teki * (C) Copyright 2017 Olimex Ltd.. 7*a51cd54eSJagan Teki * Stefan Mavrodiev <stefan@olimex.com> 8*a51cd54eSJagan Teki * 9*a51cd54eSJagan Teki * Based on linux spi driver. Original copyright follows: 10*a51cd54eSJagan Teki * linux/drivers/spi/spi-sun4i.c 11*a51cd54eSJagan Teki * 12*a51cd54eSJagan Teki * Copyright (C) 2012 - 2014 Allwinner Tech 13*a51cd54eSJagan Teki * Pan Nan <pannan@allwinnertech.com> 14*a51cd54eSJagan Teki * 15*a51cd54eSJagan Teki * Copyright (C) 2014 Maxime Ripard 16*a51cd54eSJagan Teki * Maxime Ripard <maxime.ripard@free-electrons.com> 17*a51cd54eSJagan Teki * 18*a51cd54eSJagan Teki * SPDX-License-Identifier: GPL-2.0+ 19*a51cd54eSJagan Teki */ 20*a51cd54eSJagan Teki 21*a51cd54eSJagan Teki #include <common.h> 22*a51cd54eSJagan Teki #include <clk.h> 23*a51cd54eSJagan Teki #include <dm.h> 24*a51cd54eSJagan Teki #include <spi.h> 25*a51cd54eSJagan Teki #include <errno.h> 26*a51cd54eSJagan Teki #include <fdt_support.h> 27*a51cd54eSJagan Teki #include <reset.h> 28*a51cd54eSJagan Teki #include <wait_bit.h> 29*a51cd54eSJagan Teki 30*a51cd54eSJagan Teki #include <asm/bitops.h> 31*a51cd54eSJagan Teki #include <asm/gpio.h> 32*a51cd54eSJagan Teki #include <asm/io.h> 33*a51cd54eSJagan Teki 34*a51cd54eSJagan Teki #include <linux/iopoll.h> 35*a51cd54eSJagan Teki 36*a51cd54eSJagan Teki DECLARE_GLOBAL_DATA_PTR; 37*a51cd54eSJagan Teki 38*a51cd54eSJagan Teki /* sun4i spi registers */ 39*a51cd54eSJagan Teki #define SUN4I_RXDATA_REG 0x00 40*a51cd54eSJagan Teki #define SUN4I_TXDATA_REG 0x04 41*a51cd54eSJagan Teki #define SUN4I_CTL_REG 0x08 42*a51cd54eSJagan Teki #define SUN4I_CLK_CTL_REG 0x1c 43*a51cd54eSJagan Teki #define SUN4I_BURST_CNT_REG 0x20 44*a51cd54eSJagan Teki #define SUN4I_XMIT_CNT_REG 0x24 45*a51cd54eSJagan Teki #define SUN4I_FIFO_STA_REG 0x28 46*a51cd54eSJagan Teki 47*a51cd54eSJagan Teki /* sun6i spi registers */ 48*a51cd54eSJagan Teki #define SUN6I_GBL_CTL_REG 0x04 49*a51cd54eSJagan Teki #define SUN6I_TFR_CTL_REG 0x08 50*a51cd54eSJagan Teki #define SUN6I_FIFO_CTL_REG 0x18 51*a51cd54eSJagan Teki #define SUN6I_FIFO_STA_REG 0x1c 52*a51cd54eSJagan Teki #define SUN6I_CLK_CTL_REG 0x24 53*a51cd54eSJagan Teki #define SUN6I_BURST_CNT_REG 0x30 54*a51cd54eSJagan Teki #define SUN6I_XMIT_CNT_REG 0x34 55*a51cd54eSJagan Teki #define SUN6I_BURST_CTL_REG 0x38 56*a51cd54eSJagan Teki #define SUN6I_TXDATA_REG 0x200 57*a51cd54eSJagan Teki #define SUN6I_RXDATA_REG 0x300 58*a51cd54eSJagan Teki 59*a51cd54eSJagan Teki /* sun spi bits */ 60*a51cd54eSJagan Teki #define SUN4I_CTL_ENABLE BIT(0) 61*a51cd54eSJagan Teki #define SUN4I_CTL_MASTER BIT(1) 62*a51cd54eSJagan Teki #define SUN4I_CLK_CTL_CDR2_MASK 0xff 63*a51cd54eSJagan Teki #define SUN4I_CLK_CTL_CDR2(div) ((div) & SUN4I_CLK_CTL_CDR2_MASK) 64*a51cd54eSJagan Teki #define SUN4I_CLK_CTL_CDR1_MASK 0xf 65*a51cd54eSJagan Teki #define SUN4I_CLK_CTL_CDR1(div) (((div) & SUN4I_CLK_CTL_CDR1_MASK) << 8) 66*a51cd54eSJagan Teki #define SUN4I_CLK_CTL_DRS BIT(12) 67*a51cd54eSJagan Teki #define SUN4I_MAX_XFER_SIZE 0xffffff 68*a51cd54eSJagan Teki #define SUN4I_BURST_CNT(cnt) ((cnt) & SUN4I_MAX_XFER_SIZE) 69*a51cd54eSJagan Teki #define SUN4I_XMIT_CNT(cnt) ((cnt) & SUN4I_MAX_XFER_SIZE) 70*a51cd54eSJagan Teki #define SUN4I_FIFO_STA_RF_CNT_BITS 0 71*a51cd54eSJagan Teki 72*a51cd54eSJagan Teki #define SUN4I_SPI_MAX_RATE 24000000 73*a51cd54eSJagan Teki #define SUN4I_SPI_MIN_RATE 3000 74*a51cd54eSJagan Teki #define SUN4I_SPI_DEFAULT_RATE 1000000 75*a51cd54eSJagan Teki #define SUN4I_SPI_TIMEOUT_US 1000000 76*a51cd54eSJagan Teki 77*a51cd54eSJagan Teki #define SPI_REG(priv, reg) ((priv)->base + \ 78*a51cd54eSJagan Teki (priv)->variant->regs[reg]) 79*a51cd54eSJagan Teki #define SPI_BIT(priv, bit) ((priv)->variant->bits[bit]) 80*a51cd54eSJagan Teki #define SPI_CS(priv, cs) (((cs) << SPI_BIT(priv, SPI_TCR_CS_SEL)) & \ 81*a51cd54eSJagan Teki SPI_BIT(priv, SPI_TCR_CS_MASK)) 82*a51cd54eSJagan Teki 83*a51cd54eSJagan Teki /* sun spi register set */ 84*a51cd54eSJagan Teki enum sun4i_spi_regs { 85*a51cd54eSJagan Teki SPI_GCR, 86*a51cd54eSJagan Teki SPI_TCR, 87*a51cd54eSJagan Teki SPI_FCR, 88*a51cd54eSJagan Teki SPI_FSR, 89*a51cd54eSJagan Teki SPI_CCR, 90*a51cd54eSJagan Teki SPI_BC, 91*a51cd54eSJagan Teki SPI_TC, 92*a51cd54eSJagan Teki SPI_BCTL, 93*a51cd54eSJagan Teki SPI_TXD, 94*a51cd54eSJagan Teki SPI_RXD, 95*a51cd54eSJagan Teki }; 96*a51cd54eSJagan Teki 97*a51cd54eSJagan Teki /* sun spi register bits */ 98*a51cd54eSJagan Teki enum sun4i_spi_bits { 99*a51cd54eSJagan Teki SPI_GCR_TP, 100*a51cd54eSJagan Teki SPI_GCR_SRST, 101*a51cd54eSJagan Teki SPI_TCR_CPHA, 102*a51cd54eSJagan Teki SPI_TCR_CPOL, 103*a51cd54eSJagan Teki SPI_TCR_CS_ACTIVE_LOW, 104*a51cd54eSJagan Teki SPI_TCR_CS_SEL, 105*a51cd54eSJagan Teki SPI_TCR_CS_MASK, 106*a51cd54eSJagan Teki SPI_TCR_XCH, 107*a51cd54eSJagan Teki SPI_TCR_CS_MANUAL, 108*a51cd54eSJagan Teki SPI_TCR_CS_LEVEL, 109*a51cd54eSJagan Teki SPI_FCR_TF_RST, 110*a51cd54eSJagan Teki SPI_FCR_RF_RST, 111*a51cd54eSJagan Teki SPI_FSR_RF_CNT_MASK, 112*a51cd54eSJagan Teki }; 113*a51cd54eSJagan Teki 114*a51cd54eSJagan Teki struct sun4i_spi_variant { 115*a51cd54eSJagan Teki const unsigned long *regs; 116*a51cd54eSJagan Teki const u32 *bits; 117*a51cd54eSJagan Teki u32 fifo_depth; 118*a51cd54eSJagan Teki bool has_soft_reset; 119*a51cd54eSJagan Teki bool has_burst_ctl; 120*a51cd54eSJagan Teki }; 121*a51cd54eSJagan Teki 122*a51cd54eSJagan Teki struct sun4i_spi_platdata { 123*a51cd54eSJagan Teki struct sun4i_spi_variant *variant; 124*a51cd54eSJagan Teki u32 base; 125*a51cd54eSJagan Teki u32 max_hz; 126*a51cd54eSJagan Teki }; 127*a51cd54eSJagan Teki 128*a51cd54eSJagan Teki struct sun4i_spi_priv { 129*a51cd54eSJagan Teki struct sun4i_spi_variant *variant; 130*a51cd54eSJagan Teki struct clk clk_ahb, clk_mod; 131*a51cd54eSJagan Teki struct reset_ctl reset; 132*a51cd54eSJagan Teki u32 base; 133*a51cd54eSJagan Teki u32 freq; 134*a51cd54eSJagan Teki u32 mode; 135*a51cd54eSJagan Teki 136*a51cd54eSJagan Teki const u8 *tx_buf; 137*a51cd54eSJagan Teki u8 *rx_buf; 138*a51cd54eSJagan Teki }; 139*a51cd54eSJagan Teki 140*a51cd54eSJagan Teki static inline void sun4i_spi_drain_fifo(struct sun4i_spi_priv *priv, int len) 141*a51cd54eSJagan Teki { 142*a51cd54eSJagan Teki u8 byte; 143*a51cd54eSJagan Teki 144*a51cd54eSJagan Teki while (len--) { 145*a51cd54eSJagan Teki byte = readb(SPI_REG(priv, SPI_RXD)); 146*a51cd54eSJagan Teki if (priv->rx_buf) 147*a51cd54eSJagan Teki *priv->rx_buf++ = byte; 148*a51cd54eSJagan Teki } 149*a51cd54eSJagan Teki } 150*a51cd54eSJagan Teki 151*a51cd54eSJagan Teki static inline void sun4i_spi_fill_fifo(struct sun4i_spi_priv *priv, int len) 152*a51cd54eSJagan Teki { 153*a51cd54eSJagan Teki u8 byte; 154*a51cd54eSJagan Teki 155*a51cd54eSJagan Teki while (len--) { 156*a51cd54eSJagan Teki byte = priv->tx_buf ? *priv->tx_buf++ : 0; 157*a51cd54eSJagan Teki writeb(byte, SPI_REG(priv, SPI_TXD)); 158*a51cd54eSJagan Teki } 159*a51cd54eSJagan Teki } 160*a51cd54eSJagan Teki 161*a51cd54eSJagan Teki static void sun4i_spi_set_cs(struct udevice *bus, u8 cs, bool enable) 162*a51cd54eSJagan Teki { 163*a51cd54eSJagan Teki struct sun4i_spi_priv *priv = dev_get_priv(bus); 164*a51cd54eSJagan Teki u32 reg; 165*a51cd54eSJagan Teki 166*a51cd54eSJagan Teki reg = readl(SPI_REG(priv, SPI_TCR)); 167*a51cd54eSJagan Teki 168*a51cd54eSJagan Teki reg &= ~SPI_BIT(priv, SPI_TCR_CS_MASK); 169*a51cd54eSJagan Teki reg |= SPI_CS(priv, cs); 170*a51cd54eSJagan Teki 171*a51cd54eSJagan Teki if (enable) 172*a51cd54eSJagan Teki reg &= ~SPI_BIT(priv, SPI_TCR_CS_LEVEL); 173*a51cd54eSJagan Teki else 174*a51cd54eSJagan Teki reg |= SPI_BIT(priv, SPI_TCR_CS_LEVEL); 175*a51cd54eSJagan Teki 176*a51cd54eSJagan Teki writel(reg, SPI_REG(priv, SPI_TCR)); 177*a51cd54eSJagan Teki } 178*a51cd54eSJagan Teki 179*a51cd54eSJagan Teki static int sun4i_spi_parse_pins(struct udevice *dev) 180*a51cd54eSJagan Teki { 181*a51cd54eSJagan Teki const void *fdt = gd->fdt_blob; 182*a51cd54eSJagan Teki const char *pin_name; 183*a51cd54eSJagan Teki const fdt32_t *list; 184*a51cd54eSJagan Teki u32 phandle; 185*a51cd54eSJagan Teki int drive, pull = 0, pin, i; 186*a51cd54eSJagan Teki int offset; 187*a51cd54eSJagan Teki int size; 188*a51cd54eSJagan Teki 189*a51cd54eSJagan Teki list = fdt_getprop(fdt, dev_of_offset(dev), "pinctrl-0", &size); 190*a51cd54eSJagan Teki if (!list) { 191*a51cd54eSJagan Teki printf("WARNING: sun4i_spi: cannot find pinctrl-0 node\n"); 192*a51cd54eSJagan Teki return -EINVAL; 193*a51cd54eSJagan Teki } 194*a51cd54eSJagan Teki 195*a51cd54eSJagan Teki while (size) { 196*a51cd54eSJagan Teki phandle = fdt32_to_cpu(*list++); 197*a51cd54eSJagan Teki size -= sizeof(*list); 198*a51cd54eSJagan Teki 199*a51cd54eSJagan Teki offset = fdt_node_offset_by_phandle(fdt, phandle); 200*a51cd54eSJagan Teki if (offset < 0) 201*a51cd54eSJagan Teki return offset; 202*a51cd54eSJagan Teki 203*a51cd54eSJagan Teki drive = fdt_getprop_u32_default_node(fdt, offset, 0, 204*a51cd54eSJagan Teki "drive-strength", 0); 205*a51cd54eSJagan Teki if (drive) { 206*a51cd54eSJagan Teki if (drive <= 10) 207*a51cd54eSJagan Teki drive = 0; 208*a51cd54eSJagan Teki else if (drive <= 20) 209*a51cd54eSJagan Teki drive = 1; 210*a51cd54eSJagan Teki else if (drive <= 30) 211*a51cd54eSJagan Teki drive = 2; 212*a51cd54eSJagan Teki else 213*a51cd54eSJagan Teki drive = 3; 214*a51cd54eSJagan Teki } else { 215*a51cd54eSJagan Teki drive = fdt_getprop_u32_default_node(fdt, offset, 0, 216*a51cd54eSJagan Teki "allwinner,drive", 217*a51cd54eSJagan Teki 0); 218*a51cd54eSJagan Teki drive = min(drive, 3); 219*a51cd54eSJagan Teki } 220*a51cd54eSJagan Teki 221*a51cd54eSJagan Teki if (fdt_get_property(fdt, offset, "bias-disable", NULL)) 222*a51cd54eSJagan Teki pull = 0; 223*a51cd54eSJagan Teki else if (fdt_get_property(fdt, offset, "bias-pull-up", NULL)) 224*a51cd54eSJagan Teki pull = 1; 225*a51cd54eSJagan Teki else if (fdt_get_property(fdt, offset, "bias-pull-down", NULL)) 226*a51cd54eSJagan Teki pull = 2; 227*a51cd54eSJagan Teki else 228*a51cd54eSJagan Teki pull = fdt_getprop_u32_default_node(fdt, offset, 0, 229*a51cd54eSJagan Teki "allwinner,pull", 230*a51cd54eSJagan Teki 0); 231*a51cd54eSJagan Teki pull = min(pull, 2); 232*a51cd54eSJagan Teki 233*a51cd54eSJagan Teki for (i = 0; ; i++) { 234*a51cd54eSJagan Teki pin_name = fdt_stringlist_get(fdt, offset, 235*a51cd54eSJagan Teki "pins", i, NULL); 236*a51cd54eSJagan Teki if (!pin_name) { 237*a51cd54eSJagan Teki pin_name = fdt_stringlist_get(fdt, offset, 238*a51cd54eSJagan Teki "allwinner,pins", 239*a51cd54eSJagan Teki i, NULL); 240*a51cd54eSJagan Teki if (!pin_name) 241*a51cd54eSJagan Teki break; 242*a51cd54eSJagan Teki } 243*a51cd54eSJagan Teki 244*a51cd54eSJagan Teki pin = name_to_gpio(pin_name); 245*a51cd54eSJagan Teki if (pin < 0) 246*a51cd54eSJagan Teki break; 247*a51cd54eSJagan Teki 248*a51cd54eSJagan Teki if (IS_ENABLED(CONFIG_MACH_SUN50I)) 249*a51cd54eSJagan Teki sunxi_gpio_set_cfgpin(pin, SUN50I_GPC_SPI0); 250*a51cd54eSJagan Teki else 251*a51cd54eSJagan Teki sunxi_gpio_set_cfgpin(pin, SUNXI_GPC_SPI0); 252*a51cd54eSJagan Teki sunxi_gpio_set_drv(pin, drive); 253*a51cd54eSJagan Teki sunxi_gpio_set_pull(pin, pull); 254*a51cd54eSJagan Teki } 255*a51cd54eSJagan Teki } 256*a51cd54eSJagan Teki return 0; 257*a51cd54eSJagan Teki } 258*a51cd54eSJagan Teki 259*a51cd54eSJagan Teki static inline int sun4i_spi_set_clock(struct udevice *dev, bool enable) 260*a51cd54eSJagan Teki { 261*a51cd54eSJagan Teki struct sun4i_spi_priv *priv = dev_get_priv(dev); 262*a51cd54eSJagan Teki int ret; 263*a51cd54eSJagan Teki 264*a51cd54eSJagan Teki if (!enable) { 265*a51cd54eSJagan Teki clk_disable(&priv->clk_ahb); 266*a51cd54eSJagan Teki clk_disable(&priv->clk_mod); 267*a51cd54eSJagan Teki if (reset_valid(&priv->reset)) 268*a51cd54eSJagan Teki reset_assert(&priv->reset); 269*a51cd54eSJagan Teki return 0; 270*a51cd54eSJagan Teki } 271*a51cd54eSJagan Teki 272*a51cd54eSJagan Teki ret = clk_enable(&priv->clk_ahb); 273*a51cd54eSJagan Teki if (ret) { 274*a51cd54eSJagan Teki dev_err(dev, "failed to enable ahb clock (ret=%d)\n", ret); 275*a51cd54eSJagan Teki return ret; 276*a51cd54eSJagan Teki } 277*a51cd54eSJagan Teki 278*a51cd54eSJagan Teki ret = clk_enable(&priv->clk_mod); 279*a51cd54eSJagan Teki if (ret) { 280*a51cd54eSJagan Teki dev_err(dev, "failed to enable mod clock (ret=%d)\n", ret); 281*a51cd54eSJagan Teki goto err_ahb; 282*a51cd54eSJagan Teki } 283*a51cd54eSJagan Teki 284*a51cd54eSJagan Teki if (reset_valid(&priv->reset)) { 285*a51cd54eSJagan Teki ret = reset_deassert(&priv->reset); 286*a51cd54eSJagan Teki if (ret) { 287*a51cd54eSJagan Teki dev_err(dev, "failed to deassert reset\n"); 288*a51cd54eSJagan Teki goto err_mod; 289*a51cd54eSJagan Teki } 290*a51cd54eSJagan Teki } 291*a51cd54eSJagan Teki 292*a51cd54eSJagan Teki return 0; 293*a51cd54eSJagan Teki 294*a51cd54eSJagan Teki err_mod: 295*a51cd54eSJagan Teki clk_disable(&priv->clk_mod); 296*a51cd54eSJagan Teki err_ahb: 297*a51cd54eSJagan Teki clk_disable(&priv->clk_ahb); 298*a51cd54eSJagan Teki return ret; 299*a51cd54eSJagan Teki } 300*a51cd54eSJagan Teki 301*a51cd54eSJagan Teki static int sun4i_spi_claim_bus(struct udevice *dev) 302*a51cd54eSJagan Teki { 303*a51cd54eSJagan Teki struct sun4i_spi_priv *priv = dev_get_priv(dev->parent); 304*a51cd54eSJagan Teki int ret; 305*a51cd54eSJagan Teki 306*a51cd54eSJagan Teki ret = sun4i_spi_set_clock(dev->parent, true); 307*a51cd54eSJagan Teki if (ret) 308*a51cd54eSJagan Teki return ret; 309*a51cd54eSJagan Teki 310*a51cd54eSJagan Teki setbits_le32(SPI_REG(priv, SPI_GCR), SUN4I_CTL_ENABLE | 311*a51cd54eSJagan Teki SUN4I_CTL_MASTER | SPI_BIT(priv, SPI_GCR_TP)); 312*a51cd54eSJagan Teki 313*a51cd54eSJagan Teki if (priv->variant->has_soft_reset) 314*a51cd54eSJagan Teki setbits_le32(SPI_REG(priv, SPI_GCR), 315*a51cd54eSJagan Teki SPI_BIT(priv, SPI_GCR_SRST)); 316*a51cd54eSJagan Teki 317*a51cd54eSJagan Teki setbits_le32(SPI_REG(priv, SPI_TCR), SPI_BIT(priv, SPI_TCR_CS_MANUAL) | 318*a51cd54eSJagan Teki SPI_BIT(priv, SPI_TCR_CS_ACTIVE_LOW)); 319*a51cd54eSJagan Teki 320*a51cd54eSJagan Teki return 0; 321*a51cd54eSJagan Teki } 322*a51cd54eSJagan Teki 323*a51cd54eSJagan Teki static int sun4i_spi_release_bus(struct udevice *dev) 324*a51cd54eSJagan Teki { 325*a51cd54eSJagan Teki struct sun4i_spi_priv *priv = dev_get_priv(dev->parent); 326*a51cd54eSJagan Teki 327*a51cd54eSJagan Teki clrbits_le32(SPI_REG(priv, SPI_GCR), SUN4I_CTL_ENABLE); 328*a51cd54eSJagan Teki 329*a51cd54eSJagan Teki sun4i_spi_set_clock(dev->parent, false); 330*a51cd54eSJagan Teki 331*a51cd54eSJagan Teki return 0; 332*a51cd54eSJagan Teki } 333*a51cd54eSJagan Teki 334*a51cd54eSJagan Teki static int sun4i_spi_xfer(struct udevice *dev, unsigned int bitlen, 335*a51cd54eSJagan Teki const void *dout, void *din, unsigned long flags) 336*a51cd54eSJagan Teki { 337*a51cd54eSJagan Teki struct udevice *bus = dev->parent; 338*a51cd54eSJagan Teki struct sun4i_spi_priv *priv = dev_get_priv(bus); 339*a51cd54eSJagan Teki struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); 340*a51cd54eSJagan Teki 341*a51cd54eSJagan Teki u32 len = bitlen / 8; 342*a51cd54eSJagan Teki u32 rx_fifocnt; 343*a51cd54eSJagan Teki u8 nbytes; 344*a51cd54eSJagan Teki int ret; 345*a51cd54eSJagan Teki 346*a51cd54eSJagan Teki priv->tx_buf = dout; 347*a51cd54eSJagan Teki priv->rx_buf = din; 348*a51cd54eSJagan Teki 349*a51cd54eSJagan Teki if (bitlen % 8) { 350*a51cd54eSJagan Teki debug("%s: non byte-aligned SPI transfer.\n", __func__); 351*a51cd54eSJagan Teki return -ENAVAIL; 352*a51cd54eSJagan Teki } 353*a51cd54eSJagan Teki 354*a51cd54eSJagan Teki if (flags & SPI_XFER_BEGIN) 355*a51cd54eSJagan Teki sun4i_spi_set_cs(bus, slave_plat->cs, true); 356*a51cd54eSJagan Teki 357*a51cd54eSJagan Teki /* Reset FIFOs */ 358*a51cd54eSJagan Teki setbits_le32(SPI_REG(priv, SPI_FCR), SPI_BIT(priv, SPI_FCR_RF_RST) | 359*a51cd54eSJagan Teki SPI_BIT(priv, SPI_FCR_TF_RST)); 360*a51cd54eSJagan Teki 361*a51cd54eSJagan Teki while (len) { 362*a51cd54eSJagan Teki /* Setup the transfer now... */ 363*a51cd54eSJagan Teki nbytes = min(len, (priv->variant->fifo_depth - 1)); 364*a51cd54eSJagan Teki 365*a51cd54eSJagan Teki /* Setup the counters */ 366*a51cd54eSJagan Teki writel(SUN4I_BURST_CNT(nbytes), SPI_REG(priv, SPI_BC)); 367*a51cd54eSJagan Teki writel(SUN4I_XMIT_CNT(nbytes), SPI_REG(priv, SPI_TC)); 368*a51cd54eSJagan Teki 369*a51cd54eSJagan Teki if (priv->variant->has_burst_ctl) 370*a51cd54eSJagan Teki writel(SUN4I_BURST_CNT(nbytes), 371*a51cd54eSJagan Teki SPI_REG(priv, SPI_BCTL)); 372*a51cd54eSJagan Teki 373*a51cd54eSJagan Teki /* Fill the TX FIFO */ 374*a51cd54eSJagan Teki sun4i_spi_fill_fifo(priv, nbytes); 375*a51cd54eSJagan Teki 376*a51cd54eSJagan Teki /* Start the transfer */ 377*a51cd54eSJagan Teki setbits_le32(SPI_REG(priv, SPI_TCR), 378*a51cd54eSJagan Teki SPI_BIT(priv, SPI_TCR_XCH)); 379*a51cd54eSJagan Teki 380*a51cd54eSJagan Teki /* Wait till RX FIFO to be empty */ 381*a51cd54eSJagan Teki ret = readl_poll_timeout(SPI_REG(priv, SPI_FSR), 382*a51cd54eSJagan Teki rx_fifocnt, 383*a51cd54eSJagan Teki (((rx_fifocnt & 384*a51cd54eSJagan Teki SPI_BIT(priv, SPI_FSR_RF_CNT_MASK)) >> 385*a51cd54eSJagan Teki SUN4I_FIFO_STA_RF_CNT_BITS) >= nbytes), 386*a51cd54eSJagan Teki SUN4I_SPI_TIMEOUT_US); 387*a51cd54eSJagan Teki if (ret < 0) { 388*a51cd54eSJagan Teki printf("ERROR: sun4i_spi: Timeout transferring data\n"); 389*a51cd54eSJagan Teki sun4i_spi_set_cs(bus, slave_plat->cs, false); 390*a51cd54eSJagan Teki return ret; 391*a51cd54eSJagan Teki } 392*a51cd54eSJagan Teki 393*a51cd54eSJagan Teki /* Drain the RX FIFO */ 394*a51cd54eSJagan Teki sun4i_spi_drain_fifo(priv, nbytes); 395*a51cd54eSJagan Teki 396*a51cd54eSJagan Teki len -= nbytes; 397*a51cd54eSJagan Teki } 398*a51cd54eSJagan Teki 399*a51cd54eSJagan Teki if (flags & SPI_XFER_END) 400*a51cd54eSJagan Teki sun4i_spi_set_cs(bus, slave_plat->cs, false); 401*a51cd54eSJagan Teki 402*a51cd54eSJagan Teki return 0; 403*a51cd54eSJagan Teki } 404*a51cd54eSJagan Teki 405*a51cd54eSJagan Teki static int sun4i_spi_set_speed(struct udevice *dev, uint speed) 406*a51cd54eSJagan Teki { 407*a51cd54eSJagan Teki struct sun4i_spi_platdata *plat = dev_get_platdata(dev); 408*a51cd54eSJagan Teki struct sun4i_spi_priv *priv = dev_get_priv(dev); 409*a51cd54eSJagan Teki unsigned int div; 410*a51cd54eSJagan Teki u32 reg; 411*a51cd54eSJagan Teki 412*a51cd54eSJagan Teki if (speed > plat->max_hz) 413*a51cd54eSJagan Teki speed = plat->max_hz; 414*a51cd54eSJagan Teki 415*a51cd54eSJagan Teki if (speed < SUN4I_SPI_MIN_RATE) 416*a51cd54eSJagan Teki speed = SUN4I_SPI_MIN_RATE; 417*a51cd54eSJagan Teki /* 418*a51cd54eSJagan Teki * Setup clock divider. 419*a51cd54eSJagan Teki * 420*a51cd54eSJagan Teki * We have two choices there. Either we can use the clock 421*a51cd54eSJagan Teki * divide rate 1, which is calculated thanks to this formula: 422*a51cd54eSJagan Teki * SPI_CLK = MOD_CLK / (2 ^ (cdr + 1)) 423*a51cd54eSJagan Teki * Or we can use CDR2, which is calculated with the formula: 424*a51cd54eSJagan Teki * SPI_CLK = MOD_CLK / (2 * (cdr + 1)) 425*a51cd54eSJagan Teki * Whether we use the former or the latter is set through the 426*a51cd54eSJagan Teki * DRS bit. 427*a51cd54eSJagan Teki * 428*a51cd54eSJagan Teki * First try CDR2, and if we can't reach the expected 429*a51cd54eSJagan Teki * frequency, fall back to CDR1. 430*a51cd54eSJagan Teki */ 431*a51cd54eSJagan Teki 432*a51cd54eSJagan Teki div = SUN4I_SPI_MAX_RATE / (2 * speed); 433*a51cd54eSJagan Teki reg = readl(SPI_REG(priv, SPI_CCR)); 434*a51cd54eSJagan Teki 435*a51cd54eSJagan Teki if (div <= (SUN4I_CLK_CTL_CDR2_MASK + 1)) { 436*a51cd54eSJagan Teki if (div > 0) 437*a51cd54eSJagan Teki div--; 438*a51cd54eSJagan Teki 439*a51cd54eSJagan Teki reg &= ~(SUN4I_CLK_CTL_CDR2_MASK | SUN4I_CLK_CTL_DRS); 440*a51cd54eSJagan Teki reg |= SUN4I_CLK_CTL_CDR2(div) | SUN4I_CLK_CTL_DRS; 441*a51cd54eSJagan Teki } else { 442*a51cd54eSJagan Teki div = __ilog2(SUN4I_SPI_MAX_RATE) - __ilog2(speed); 443*a51cd54eSJagan Teki reg &= ~((SUN4I_CLK_CTL_CDR1_MASK << 8) | SUN4I_CLK_CTL_DRS); 444*a51cd54eSJagan Teki reg |= SUN4I_CLK_CTL_CDR1(div); 445*a51cd54eSJagan Teki } 446*a51cd54eSJagan Teki 447*a51cd54eSJagan Teki priv->freq = speed; 448*a51cd54eSJagan Teki writel(reg, SPI_REG(priv, SPI_CCR)); 449*a51cd54eSJagan Teki 450*a51cd54eSJagan Teki return 0; 451*a51cd54eSJagan Teki } 452*a51cd54eSJagan Teki 453*a51cd54eSJagan Teki static int sun4i_spi_set_mode(struct udevice *dev, uint mode) 454*a51cd54eSJagan Teki { 455*a51cd54eSJagan Teki struct sun4i_spi_priv *priv = dev_get_priv(dev); 456*a51cd54eSJagan Teki u32 reg; 457*a51cd54eSJagan Teki 458*a51cd54eSJagan Teki reg = readl(SPI_REG(priv, SPI_TCR)); 459*a51cd54eSJagan Teki reg &= ~(SPI_BIT(priv, SPI_TCR_CPOL) | SPI_BIT(priv, SPI_TCR_CPHA)); 460*a51cd54eSJagan Teki 461*a51cd54eSJagan Teki if (mode & SPI_CPOL) 462*a51cd54eSJagan Teki reg |= SPI_BIT(priv, SPI_TCR_CPOL); 463*a51cd54eSJagan Teki 464*a51cd54eSJagan Teki if (mode & SPI_CPHA) 465*a51cd54eSJagan Teki reg |= SPI_BIT(priv, SPI_TCR_CPHA); 466*a51cd54eSJagan Teki 467*a51cd54eSJagan Teki priv->mode = mode; 468*a51cd54eSJagan Teki writel(reg, SPI_REG(priv, SPI_TCR)); 469*a51cd54eSJagan Teki 470*a51cd54eSJagan Teki return 0; 471*a51cd54eSJagan Teki } 472*a51cd54eSJagan Teki 473*a51cd54eSJagan Teki static const struct dm_spi_ops sun4i_spi_ops = { 474*a51cd54eSJagan Teki .claim_bus = sun4i_spi_claim_bus, 475*a51cd54eSJagan Teki .release_bus = sun4i_spi_release_bus, 476*a51cd54eSJagan Teki .xfer = sun4i_spi_xfer, 477*a51cd54eSJagan Teki .set_speed = sun4i_spi_set_speed, 478*a51cd54eSJagan Teki .set_mode = sun4i_spi_set_mode, 479*a51cd54eSJagan Teki }; 480*a51cd54eSJagan Teki 481*a51cd54eSJagan Teki static int sun4i_spi_probe(struct udevice *bus) 482*a51cd54eSJagan Teki { 483*a51cd54eSJagan Teki struct sun4i_spi_platdata *plat = dev_get_platdata(bus); 484*a51cd54eSJagan Teki struct sun4i_spi_priv *priv = dev_get_priv(bus); 485*a51cd54eSJagan Teki int ret; 486*a51cd54eSJagan Teki 487*a51cd54eSJagan Teki ret = clk_get_by_name(bus, "ahb", &priv->clk_ahb); 488*a51cd54eSJagan Teki if (ret) { 489*a51cd54eSJagan Teki dev_err(dev, "failed to get ahb clock\n"); 490*a51cd54eSJagan Teki return ret; 491*a51cd54eSJagan Teki } 492*a51cd54eSJagan Teki 493*a51cd54eSJagan Teki ret = clk_get_by_name(bus, "mod", &priv->clk_mod); 494*a51cd54eSJagan Teki if (ret) { 495*a51cd54eSJagan Teki dev_err(dev, "failed to get mod clock\n"); 496*a51cd54eSJagan Teki return ret; 497*a51cd54eSJagan Teki } 498*a51cd54eSJagan Teki 499*a51cd54eSJagan Teki ret = reset_get_by_index(bus, 0, &priv->reset); 500*a51cd54eSJagan Teki if (ret && ret != -ENOENT) { 501*a51cd54eSJagan Teki dev_err(dev, "failed to get reset\n"); 502*a51cd54eSJagan Teki return ret; 503*a51cd54eSJagan Teki } 504*a51cd54eSJagan Teki 505*a51cd54eSJagan Teki sun4i_spi_parse_pins(bus); 506*a51cd54eSJagan Teki 507*a51cd54eSJagan Teki priv->variant = plat->variant; 508*a51cd54eSJagan Teki priv->base = plat->base; 509*a51cd54eSJagan Teki priv->freq = plat->max_hz; 510*a51cd54eSJagan Teki 511*a51cd54eSJagan Teki return 0; 512*a51cd54eSJagan Teki } 513*a51cd54eSJagan Teki 514*a51cd54eSJagan Teki static int sun4i_spi_ofdata_to_platdata(struct udevice *bus) 515*a51cd54eSJagan Teki { 516*a51cd54eSJagan Teki struct sun4i_spi_platdata *plat = dev_get_platdata(bus); 517*a51cd54eSJagan Teki int node = dev_of_offset(bus); 518*a51cd54eSJagan Teki 519*a51cd54eSJagan Teki plat->base = devfdt_get_addr(bus); 520*a51cd54eSJagan Teki plat->variant = (struct sun4i_spi_variant *)dev_get_driver_data(bus); 521*a51cd54eSJagan Teki plat->max_hz = fdtdec_get_int(gd->fdt_blob, node, 522*a51cd54eSJagan Teki "spi-max-frequency", 523*a51cd54eSJagan Teki SUN4I_SPI_DEFAULT_RATE); 524*a51cd54eSJagan Teki 525*a51cd54eSJagan Teki if (plat->max_hz > SUN4I_SPI_MAX_RATE) 526*a51cd54eSJagan Teki plat->max_hz = SUN4I_SPI_MAX_RATE; 527*a51cd54eSJagan Teki 528*a51cd54eSJagan Teki return 0; 529*a51cd54eSJagan Teki } 530*a51cd54eSJagan Teki 531*a51cd54eSJagan Teki static const unsigned long sun4i_spi_regs[] = { 532*a51cd54eSJagan Teki [SPI_GCR] = SUN4I_CTL_REG, 533*a51cd54eSJagan Teki [SPI_TCR] = SUN4I_CTL_REG, 534*a51cd54eSJagan Teki [SPI_FCR] = SUN4I_CTL_REG, 535*a51cd54eSJagan Teki [SPI_FSR] = SUN4I_FIFO_STA_REG, 536*a51cd54eSJagan Teki [SPI_CCR] = SUN4I_CLK_CTL_REG, 537*a51cd54eSJagan Teki [SPI_BC] = SUN4I_BURST_CNT_REG, 538*a51cd54eSJagan Teki [SPI_TC] = SUN4I_XMIT_CNT_REG, 539*a51cd54eSJagan Teki [SPI_TXD] = SUN4I_TXDATA_REG, 540*a51cd54eSJagan Teki [SPI_RXD] = SUN4I_RXDATA_REG, 541*a51cd54eSJagan Teki }; 542*a51cd54eSJagan Teki 543*a51cd54eSJagan Teki static const u32 sun4i_spi_bits[] = { 544*a51cd54eSJagan Teki [SPI_GCR_TP] = BIT(18), 545*a51cd54eSJagan Teki [SPI_TCR_CPHA] = BIT(2), 546*a51cd54eSJagan Teki [SPI_TCR_CPOL] = BIT(3), 547*a51cd54eSJagan Teki [SPI_TCR_CS_ACTIVE_LOW] = BIT(4), 548*a51cd54eSJagan Teki [SPI_TCR_XCH] = BIT(10), 549*a51cd54eSJagan Teki [SPI_TCR_CS_SEL] = 12, 550*a51cd54eSJagan Teki [SPI_TCR_CS_MASK] = 0x3000, 551*a51cd54eSJagan Teki [SPI_TCR_CS_MANUAL] = BIT(16), 552*a51cd54eSJagan Teki [SPI_TCR_CS_LEVEL] = BIT(17), 553*a51cd54eSJagan Teki [SPI_FCR_TF_RST] = BIT(8), 554*a51cd54eSJagan Teki [SPI_FCR_RF_RST] = BIT(9), 555*a51cd54eSJagan Teki [SPI_FSR_RF_CNT_MASK] = GENMASK(6, 0), 556*a51cd54eSJagan Teki }; 557*a51cd54eSJagan Teki 558*a51cd54eSJagan Teki static const unsigned long sun6i_spi_regs[] = { 559*a51cd54eSJagan Teki [SPI_GCR] = SUN6I_GBL_CTL_REG, 560*a51cd54eSJagan Teki [SPI_TCR] = SUN6I_TFR_CTL_REG, 561*a51cd54eSJagan Teki [SPI_FCR] = SUN6I_FIFO_CTL_REG, 562*a51cd54eSJagan Teki [SPI_FSR] = SUN6I_FIFO_STA_REG, 563*a51cd54eSJagan Teki [SPI_CCR] = SUN6I_CLK_CTL_REG, 564*a51cd54eSJagan Teki [SPI_BC] = SUN6I_BURST_CNT_REG, 565*a51cd54eSJagan Teki [SPI_TC] = SUN6I_XMIT_CNT_REG, 566*a51cd54eSJagan Teki [SPI_BCTL] = SUN6I_BURST_CTL_REG, 567*a51cd54eSJagan Teki [SPI_TXD] = SUN6I_TXDATA_REG, 568*a51cd54eSJagan Teki [SPI_RXD] = SUN6I_RXDATA_REG, 569*a51cd54eSJagan Teki }; 570*a51cd54eSJagan Teki 571*a51cd54eSJagan Teki static const u32 sun6i_spi_bits[] = { 572*a51cd54eSJagan Teki [SPI_GCR_TP] = BIT(7), 573*a51cd54eSJagan Teki [SPI_GCR_SRST] = BIT(31), 574*a51cd54eSJagan Teki [SPI_TCR_CPHA] = BIT(0), 575*a51cd54eSJagan Teki [SPI_TCR_CPOL] = BIT(1), 576*a51cd54eSJagan Teki [SPI_TCR_CS_ACTIVE_LOW] = BIT(2), 577*a51cd54eSJagan Teki [SPI_TCR_CS_SEL] = 4, 578*a51cd54eSJagan Teki [SPI_TCR_CS_MASK] = 0x30, 579*a51cd54eSJagan Teki [SPI_TCR_CS_MANUAL] = BIT(6), 580*a51cd54eSJagan Teki [SPI_TCR_CS_LEVEL] = BIT(7), 581*a51cd54eSJagan Teki [SPI_TCR_XCH] = BIT(31), 582*a51cd54eSJagan Teki [SPI_FCR_RF_RST] = BIT(15), 583*a51cd54eSJagan Teki [SPI_FCR_TF_RST] = BIT(31), 584*a51cd54eSJagan Teki [SPI_FSR_RF_CNT_MASK] = GENMASK(7, 0), 585*a51cd54eSJagan Teki }; 586*a51cd54eSJagan Teki 587*a51cd54eSJagan Teki static const struct sun4i_spi_variant sun4i_a10_spi_variant = { 588*a51cd54eSJagan Teki .regs = sun4i_spi_regs, 589*a51cd54eSJagan Teki .bits = sun4i_spi_bits, 590*a51cd54eSJagan Teki .fifo_depth = 64, 591*a51cd54eSJagan Teki }; 592*a51cd54eSJagan Teki 593*a51cd54eSJagan Teki static const struct sun4i_spi_variant sun6i_a31_spi_variant = { 594*a51cd54eSJagan Teki .regs = sun6i_spi_regs, 595*a51cd54eSJagan Teki .bits = sun6i_spi_bits, 596*a51cd54eSJagan Teki .fifo_depth = 128, 597*a51cd54eSJagan Teki .has_soft_reset = true, 598*a51cd54eSJagan Teki .has_burst_ctl = true, 599*a51cd54eSJagan Teki }; 600*a51cd54eSJagan Teki 601*a51cd54eSJagan Teki static const struct sun4i_spi_variant sun8i_h3_spi_variant = { 602*a51cd54eSJagan Teki .regs = sun6i_spi_regs, 603*a51cd54eSJagan Teki .bits = sun6i_spi_bits, 604*a51cd54eSJagan Teki .fifo_depth = 64, 605*a51cd54eSJagan Teki .has_soft_reset = true, 606*a51cd54eSJagan Teki .has_burst_ctl = true, 607*a51cd54eSJagan Teki }; 608*a51cd54eSJagan Teki 609*a51cd54eSJagan Teki static const struct udevice_id sun4i_spi_ids[] = { 610*a51cd54eSJagan Teki { 611*a51cd54eSJagan Teki .compatible = "allwinner,sun4i-a10-spi", 612*a51cd54eSJagan Teki .data = (ulong)&sun4i_a10_spi_variant, 613*a51cd54eSJagan Teki }, 614*a51cd54eSJagan Teki { 615*a51cd54eSJagan Teki .compatible = "allwinner,sun6i-a31-spi", 616*a51cd54eSJagan Teki .data = (ulong)&sun6i_a31_spi_variant, 617*a51cd54eSJagan Teki }, 618*a51cd54eSJagan Teki { 619*a51cd54eSJagan Teki .compatible = "allwinner,sun8i-h3-spi", 620*a51cd54eSJagan Teki .data = (ulong)&sun8i_h3_spi_variant, 621*a51cd54eSJagan Teki }, 622*a51cd54eSJagan Teki { /* sentinel */ } 623*a51cd54eSJagan Teki }; 624*a51cd54eSJagan Teki 625*a51cd54eSJagan Teki U_BOOT_DRIVER(sun4i_spi) = { 626*a51cd54eSJagan Teki .name = "sun4i_spi", 627*a51cd54eSJagan Teki .id = UCLASS_SPI, 628*a51cd54eSJagan Teki .of_match = sun4i_spi_ids, 629*a51cd54eSJagan Teki .ops = &sun4i_spi_ops, 630*a51cd54eSJagan Teki .ofdata_to_platdata = sun4i_spi_ofdata_to_platdata, 631*a51cd54eSJagan Teki .platdata_auto_alloc_size = sizeof(struct sun4i_spi_platdata), 632*a51cd54eSJagan Teki .priv_auto_alloc_size = sizeof(struct sun4i_spi_priv), 633*a51cd54eSJagan Teki .probe = sun4i_spi_probe, 634*a51cd54eSJagan Teki }; 635