15bef6fd7SStefan Roese /* 25bef6fd7SStefan Roese * Designware master SPI core controller driver 35bef6fd7SStefan Roese * 45bef6fd7SStefan Roese * Copyright (C) 2014 Stefan Roese <sr@denx.de> 55bef6fd7SStefan Roese * 6*a72f8020SStefan Roese * Very loosely based on the Linux driver: 7*a72f8020SStefan Roese * drivers/spi/spi-dw.c, which is: 85bef6fd7SStefan Roese * Copyright (c) 2009, Intel Corporation. 95bef6fd7SStefan Roese * 105bef6fd7SStefan Roese * SPDX-License-Identifier: GPL-2.0 115bef6fd7SStefan Roese */ 125bef6fd7SStefan Roese 135bef6fd7SStefan Roese #include <common.h> 145bef6fd7SStefan Roese #include <dm.h> 155bef6fd7SStefan Roese #include <errno.h> 165bef6fd7SStefan Roese #include <malloc.h> 175bef6fd7SStefan Roese #include <spi.h> 185bef6fd7SStefan Roese #include <fdtdec.h> 195bef6fd7SStefan Roese #include <linux/compat.h> 205bef6fd7SStefan Roese #include <asm/io.h> 21*a72f8020SStefan Roese #include <asm/arch/clock_manager.h> 225bef6fd7SStefan Roese 235bef6fd7SStefan Roese DECLARE_GLOBAL_DATA_PTR; 245bef6fd7SStefan Roese 255bef6fd7SStefan Roese /* Register offsets */ 265bef6fd7SStefan Roese #define DW_SPI_CTRL0 0x00 275bef6fd7SStefan Roese #define DW_SPI_CTRL1 0x04 285bef6fd7SStefan Roese #define DW_SPI_SSIENR 0x08 295bef6fd7SStefan Roese #define DW_SPI_MWCR 0x0c 305bef6fd7SStefan Roese #define DW_SPI_SER 0x10 315bef6fd7SStefan Roese #define DW_SPI_BAUDR 0x14 325bef6fd7SStefan Roese #define DW_SPI_TXFLTR 0x18 335bef6fd7SStefan Roese #define DW_SPI_RXFLTR 0x1c 345bef6fd7SStefan Roese #define DW_SPI_TXFLR 0x20 355bef6fd7SStefan Roese #define DW_SPI_RXFLR 0x24 365bef6fd7SStefan Roese #define DW_SPI_SR 0x28 375bef6fd7SStefan Roese #define DW_SPI_IMR 0x2c 385bef6fd7SStefan Roese #define DW_SPI_ISR 0x30 395bef6fd7SStefan Roese #define DW_SPI_RISR 0x34 405bef6fd7SStefan Roese #define DW_SPI_TXOICR 0x38 415bef6fd7SStefan Roese #define DW_SPI_RXOICR 0x3c 425bef6fd7SStefan Roese #define DW_SPI_RXUICR 0x40 435bef6fd7SStefan Roese #define DW_SPI_MSTICR 0x44 445bef6fd7SStefan Roese #define DW_SPI_ICR 0x48 455bef6fd7SStefan Roese #define DW_SPI_DMACR 0x4c 465bef6fd7SStefan Roese #define DW_SPI_DMATDLR 0x50 475bef6fd7SStefan Roese #define DW_SPI_DMARDLR 0x54 485bef6fd7SStefan Roese #define DW_SPI_IDR 0x58 495bef6fd7SStefan Roese #define DW_SPI_VERSION 0x5c 505bef6fd7SStefan Roese #define DW_SPI_DR 0x60 515bef6fd7SStefan Roese 525bef6fd7SStefan Roese /* Bit fields in CTRLR0 */ 535bef6fd7SStefan Roese #define SPI_DFS_OFFSET 0 545bef6fd7SStefan Roese 555bef6fd7SStefan Roese #define SPI_FRF_OFFSET 4 565bef6fd7SStefan Roese #define SPI_FRF_SPI 0x0 575bef6fd7SStefan Roese #define SPI_FRF_SSP 0x1 585bef6fd7SStefan Roese #define SPI_FRF_MICROWIRE 0x2 595bef6fd7SStefan Roese #define SPI_FRF_RESV 0x3 605bef6fd7SStefan Roese 615bef6fd7SStefan Roese #define SPI_MODE_OFFSET 6 625bef6fd7SStefan Roese #define SPI_SCPH_OFFSET 6 635bef6fd7SStefan Roese #define SPI_SCOL_OFFSET 7 645bef6fd7SStefan Roese 655bef6fd7SStefan Roese #define SPI_TMOD_OFFSET 8 665bef6fd7SStefan Roese #define SPI_TMOD_MASK (0x3 << SPI_TMOD_OFFSET) 675bef6fd7SStefan Roese #define SPI_TMOD_TR 0x0 /* xmit & recv */ 685bef6fd7SStefan Roese #define SPI_TMOD_TO 0x1 /* xmit only */ 695bef6fd7SStefan Roese #define SPI_TMOD_RO 0x2 /* recv only */ 705bef6fd7SStefan Roese #define SPI_TMOD_EPROMREAD 0x3 /* eeprom read mode */ 715bef6fd7SStefan Roese 725bef6fd7SStefan Roese #define SPI_SLVOE_OFFSET 10 735bef6fd7SStefan Roese #define SPI_SRL_OFFSET 11 745bef6fd7SStefan Roese #define SPI_CFS_OFFSET 12 755bef6fd7SStefan Roese 765bef6fd7SStefan Roese /* Bit fields in SR, 7 bits */ 775bef6fd7SStefan Roese #define SR_MASK 0x7f /* cover 7 bits */ 785bef6fd7SStefan Roese #define SR_BUSY (1 << 0) 795bef6fd7SStefan Roese #define SR_TF_NOT_FULL (1 << 1) 805bef6fd7SStefan Roese #define SR_TF_EMPT (1 << 2) 815bef6fd7SStefan Roese #define SR_RF_NOT_EMPT (1 << 3) 825bef6fd7SStefan Roese #define SR_RF_FULL (1 << 4) 835bef6fd7SStefan Roese #define SR_TX_ERR (1 << 5) 845bef6fd7SStefan Roese #define SR_DCOL (1 << 6) 855bef6fd7SStefan Roese 86*a72f8020SStefan Roese #define RX_TIMEOUT 1000 /* timeout in ms */ 875bef6fd7SStefan Roese 885bef6fd7SStefan Roese struct dw_spi_platdata { 895bef6fd7SStefan Roese s32 frequency; /* Default clock frequency, -1 for none */ 905bef6fd7SStefan Roese void __iomem *regs; 915bef6fd7SStefan Roese }; 925bef6fd7SStefan Roese 935bef6fd7SStefan Roese struct dw_spi_priv { 945bef6fd7SStefan Roese void __iomem *regs; 955bef6fd7SStefan Roese unsigned int freq; /* Default frequency */ 965bef6fd7SStefan Roese unsigned int mode; 975bef6fd7SStefan Roese 985bef6fd7SStefan Roese int bits_per_word; 995bef6fd7SStefan Roese u8 cs; /* chip select pin */ 1005bef6fd7SStefan Roese u8 tmode; /* TR/TO/RO/EEPROM */ 1015bef6fd7SStefan Roese u8 type; /* SPI/SSP/MicroWire */ 1025bef6fd7SStefan Roese int len; 1035bef6fd7SStefan Roese 1045bef6fd7SStefan Roese u32 fifo_len; /* depth of the FIFO buffer */ 1055bef6fd7SStefan Roese void *tx; 1065bef6fd7SStefan Roese void *tx_end; 1075bef6fd7SStefan Roese void *rx; 1085bef6fd7SStefan Roese void *rx_end; 1095bef6fd7SStefan Roese }; 1105bef6fd7SStefan Roese 1115bef6fd7SStefan Roese static inline u32 dw_readl(struct dw_spi_priv *priv, u32 offset) 1125bef6fd7SStefan Roese { 1135bef6fd7SStefan Roese return __raw_readl(priv->regs + offset); 1145bef6fd7SStefan Roese } 1155bef6fd7SStefan Roese 1165bef6fd7SStefan Roese static inline void dw_writel(struct dw_spi_priv *priv, u32 offset, u32 val) 1175bef6fd7SStefan Roese { 1185bef6fd7SStefan Roese __raw_writel(val, priv->regs + offset); 1195bef6fd7SStefan Roese } 1205bef6fd7SStefan Roese 1215bef6fd7SStefan Roese static inline u16 dw_readw(struct dw_spi_priv *priv, u32 offset) 1225bef6fd7SStefan Roese { 1235bef6fd7SStefan Roese return __raw_readw(priv->regs + offset); 1245bef6fd7SStefan Roese } 1255bef6fd7SStefan Roese 1265bef6fd7SStefan Roese static inline void dw_writew(struct dw_spi_priv *priv, u32 offset, u16 val) 1275bef6fd7SStefan Roese { 1285bef6fd7SStefan Roese __raw_writew(val, priv->regs + offset); 1295bef6fd7SStefan Roese } 1305bef6fd7SStefan Roese 1315bef6fd7SStefan Roese static int dw_spi_ofdata_to_platdata(struct udevice *bus) 1325bef6fd7SStefan Roese { 1335bef6fd7SStefan Roese struct dw_spi_platdata *plat = bus->platdata; 1345bef6fd7SStefan Roese const void *blob = gd->fdt_blob; 1355bef6fd7SStefan Roese int node = bus->of_offset; 1365bef6fd7SStefan Roese 1375bef6fd7SStefan Roese plat->regs = (struct dw_spi *)fdtdec_get_addr(blob, node, "reg"); 1385bef6fd7SStefan Roese 1395bef6fd7SStefan Roese /* Use 500KHz as a suitable default */ 1405bef6fd7SStefan Roese plat->frequency = fdtdec_get_int(blob, node, "spi-max-frequency", 1415bef6fd7SStefan Roese 500000); 1425bef6fd7SStefan Roese debug("%s: regs=%p max-frequency=%d\n", __func__, plat->regs, 1435bef6fd7SStefan Roese plat->frequency); 1445bef6fd7SStefan Roese 1455bef6fd7SStefan Roese return 0; 1465bef6fd7SStefan Roese } 1475bef6fd7SStefan Roese 1485bef6fd7SStefan Roese static inline void spi_enable_chip(struct dw_spi_priv *priv, int enable) 1495bef6fd7SStefan Roese { 1505bef6fd7SStefan Roese dw_writel(priv, DW_SPI_SSIENR, (enable ? 1 : 0)); 1515bef6fd7SStefan Roese } 1525bef6fd7SStefan Roese 1535bef6fd7SStefan Roese /* Restart the controller, disable all interrupts, clean rx fifo */ 1545bef6fd7SStefan Roese static void spi_hw_init(struct dw_spi_priv *priv) 1555bef6fd7SStefan Roese { 1565bef6fd7SStefan Roese spi_enable_chip(priv, 0); 1575bef6fd7SStefan Roese dw_writel(priv, DW_SPI_IMR, 0xff); 1585bef6fd7SStefan Roese spi_enable_chip(priv, 1); 1595bef6fd7SStefan Roese 1605bef6fd7SStefan Roese /* 1615bef6fd7SStefan Roese * Try to detect the FIFO depth if not set by interface driver, 1625bef6fd7SStefan Roese * the depth could be from 2 to 256 from HW spec 1635bef6fd7SStefan Roese */ 1645bef6fd7SStefan Roese if (!priv->fifo_len) { 1655bef6fd7SStefan Roese u32 fifo; 1665bef6fd7SStefan Roese 1675bef6fd7SStefan Roese for (fifo = 2; fifo <= 257; fifo++) { 1685bef6fd7SStefan Roese dw_writew(priv, DW_SPI_TXFLTR, fifo); 1695bef6fd7SStefan Roese if (fifo != dw_readw(priv, DW_SPI_TXFLTR)) 1705bef6fd7SStefan Roese break; 1715bef6fd7SStefan Roese } 1725bef6fd7SStefan Roese 1735bef6fd7SStefan Roese priv->fifo_len = (fifo == 257) ? 0 : fifo; 1745bef6fd7SStefan Roese dw_writew(priv, DW_SPI_TXFLTR, 0); 1755bef6fd7SStefan Roese } 1765bef6fd7SStefan Roese debug("%s: fifo_len=%d\n", __func__, priv->fifo_len); 1775bef6fd7SStefan Roese } 1785bef6fd7SStefan Roese 1795bef6fd7SStefan Roese static int dw_spi_probe(struct udevice *bus) 1805bef6fd7SStefan Roese { 1815bef6fd7SStefan Roese struct dw_spi_platdata *plat = dev_get_platdata(bus); 1825bef6fd7SStefan Roese struct dw_spi_priv *priv = dev_get_priv(bus); 1835bef6fd7SStefan Roese 1845bef6fd7SStefan Roese priv->regs = plat->regs; 1855bef6fd7SStefan Roese priv->freq = plat->frequency; 1865bef6fd7SStefan Roese 1875bef6fd7SStefan Roese /* Currently only bits_per_word == 8 supported */ 1885bef6fd7SStefan Roese priv->bits_per_word = 8; 1895bef6fd7SStefan Roese 1905bef6fd7SStefan Roese priv->tmode = 0; /* Tx & Rx */ 1915bef6fd7SStefan Roese 1925bef6fd7SStefan Roese /* Basic HW init */ 1935bef6fd7SStefan Roese spi_hw_init(priv); 1945bef6fd7SStefan Roese 1955bef6fd7SStefan Roese return 0; 1965bef6fd7SStefan Roese } 1975bef6fd7SStefan Roese 1985bef6fd7SStefan Roese /* Return the max entries we can fill into tx fifo */ 1995bef6fd7SStefan Roese static inline u32 tx_max(struct dw_spi_priv *priv) 2005bef6fd7SStefan Roese { 2015bef6fd7SStefan Roese u32 tx_left, tx_room, rxtx_gap; 2025bef6fd7SStefan Roese 203*a72f8020SStefan Roese tx_left = (priv->tx_end - priv->tx) / (priv->bits_per_word >> 3); 2045bef6fd7SStefan Roese tx_room = priv->fifo_len - dw_readw(priv, DW_SPI_TXFLR); 2055bef6fd7SStefan Roese 2065bef6fd7SStefan Roese /* 2075bef6fd7SStefan Roese * Another concern is about the tx/rx mismatch, we 208*a72f8020SStefan Roese * thought about using (priv->fifo_len - rxflr - txflr) as 2095bef6fd7SStefan Roese * one maximum value for tx, but it doesn't cover the 2105bef6fd7SStefan Roese * data which is out of tx/rx fifo and inside the 2115bef6fd7SStefan Roese * shift registers. So a control from sw point of 2125bef6fd7SStefan Roese * view is taken. 2135bef6fd7SStefan Roese */ 2145bef6fd7SStefan Roese rxtx_gap = ((priv->rx_end - priv->rx) - (priv->tx_end - priv->tx)) / 215*a72f8020SStefan Roese (priv->bits_per_word >> 3); 2165bef6fd7SStefan Roese 2175bef6fd7SStefan Roese return min3(tx_left, tx_room, (u32)(priv->fifo_len - rxtx_gap)); 2185bef6fd7SStefan Roese } 2195bef6fd7SStefan Roese 2205bef6fd7SStefan Roese /* Return the max entries we should read out of rx fifo */ 2215bef6fd7SStefan Roese static inline u32 rx_max(struct dw_spi_priv *priv) 2225bef6fd7SStefan Roese { 223*a72f8020SStefan Roese u32 rx_left = (priv->rx_end - priv->rx) / (priv->bits_per_word >> 3); 2245bef6fd7SStefan Roese 2255bef6fd7SStefan Roese return min_t(u32, rx_left, dw_readw(priv, DW_SPI_RXFLR)); 2265bef6fd7SStefan Roese } 2275bef6fd7SStefan Roese 2285bef6fd7SStefan Roese static void dw_writer(struct dw_spi_priv *priv) 2295bef6fd7SStefan Roese { 2305bef6fd7SStefan Roese u32 max = tx_max(priv); 2315bef6fd7SStefan Roese u16 txw = 0; 2325bef6fd7SStefan Roese 2335bef6fd7SStefan Roese while (max--) { 2345bef6fd7SStefan Roese /* Set the tx word if the transfer's original "tx" is not null */ 2355bef6fd7SStefan Roese if (priv->tx_end - priv->len) { 236*a72f8020SStefan Roese if (priv->bits_per_word == 8) 2375bef6fd7SStefan Roese txw = *(u8 *)(priv->tx); 2385bef6fd7SStefan Roese else 2395bef6fd7SStefan Roese txw = *(u16 *)(priv->tx); 2405bef6fd7SStefan Roese } 2415bef6fd7SStefan Roese dw_writew(priv, DW_SPI_DR, txw); 2425bef6fd7SStefan Roese debug("%s: tx=0x%02x\n", __func__, txw); 243*a72f8020SStefan Roese priv->tx += priv->bits_per_word >> 3; 2445bef6fd7SStefan Roese } 2455bef6fd7SStefan Roese } 2465bef6fd7SStefan Roese 2475bef6fd7SStefan Roese static int dw_reader(struct dw_spi_priv *priv) 2485bef6fd7SStefan Roese { 2495bef6fd7SStefan Roese unsigned start = get_timer(0); 2505bef6fd7SStefan Roese u32 max; 2515bef6fd7SStefan Roese u16 rxw; 2525bef6fd7SStefan Roese 2535bef6fd7SStefan Roese /* Wait for rx data to be ready */ 2545bef6fd7SStefan Roese while (rx_max(priv) == 0) { 2555bef6fd7SStefan Roese if (get_timer(start) > RX_TIMEOUT) 2565bef6fd7SStefan Roese return -ETIMEDOUT; 2575bef6fd7SStefan Roese } 2585bef6fd7SStefan Roese 2595bef6fd7SStefan Roese max = rx_max(priv); 2605bef6fd7SStefan Roese 2615bef6fd7SStefan Roese while (max--) { 2625bef6fd7SStefan Roese rxw = dw_readw(priv, DW_SPI_DR); 2635bef6fd7SStefan Roese debug("%s: rx=0x%02x\n", __func__, rxw); 264*a72f8020SStefan Roese 265*a72f8020SStefan Roese /* 266*a72f8020SStefan Roese * Care about rx only if the transfer's original "rx" is 267*a72f8020SStefan Roese * not null 268*a72f8020SStefan Roese */ 2695bef6fd7SStefan Roese if (priv->rx_end - priv->len) { 270*a72f8020SStefan Roese if (priv->bits_per_word == 8) 2715bef6fd7SStefan Roese *(u8 *)(priv->rx) = rxw; 2725bef6fd7SStefan Roese else 2735bef6fd7SStefan Roese *(u16 *)(priv->rx) = rxw; 2745bef6fd7SStefan Roese } 275*a72f8020SStefan Roese priv->rx += priv->bits_per_word >> 3; 2765bef6fd7SStefan Roese } 2775bef6fd7SStefan Roese 2785bef6fd7SStefan Roese return 0; 2795bef6fd7SStefan Roese } 2805bef6fd7SStefan Roese 2815bef6fd7SStefan Roese static int poll_transfer(struct dw_spi_priv *priv) 2825bef6fd7SStefan Roese { 2835bef6fd7SStefan Roese int ret; 2845bef6fd7SStefan Roese 2855bef6fd7SStefan Roese do { 2865bef6fd7SStefan Roese dw_writer(priv); 2875bef6fd7SStefan Roese ret = dw_reader(priv); 2885bef6fd7SStefan Roese if (ret < 0) 2895bef6fd7SStefan Roese return ret; 2905bef6fd7SStefan Roese } while (priv->rx_end > priv->rx); 2915bef6fd7SStefan Roese 2925bef6fd7SStefan Roese return 0; 2935bef6fd7SStefan Roese } 2945bef6fd7SStefan Roese 2955bef6fd7SStefan Roese static int dw_spi_xfer(struct udevice *dev, unsigned int bitlen, 2965bef6fd7SStefan Roese const void *dout, void *din, unsigned long flags) 2975bef6fd7SStefan Roese { 2985bef6fd7SStefan Roese struct udevice *bus = dev->parent; 2995bef6fd7SStefan Roese struct dw_spi_priv *priv = dev_get_priv(bus); 3005bef6fd7SStefan Roese const u8 *tx = dout; 3015bef6fd7SStefan Roese u8 *rx = din; 3025bef6fd7SStefan Roese int ret = 0; 3035bef6fd7SStefan Roese u32 cr0 = 0; 3045bef6fd7SStefan Roese u32 cs; 3055bef6fd7SStefan Roese 3065bef6fd7SStefan Roese /* spi core configured to do 8 bit transfers */ 3075bef6fd7SStefan Roese if (bitlen % 8) { 3085bef6fd7SStefan Roese debug("Non byte aligned SPI transfer.\n"); 3095bef6fd7SStefan Roese return -1; 3105bef6fd7SStefan Roese } 3115bef6fd7SStefan Roese 312*a72f8020SStefan Roese cr0 = (priv->bits_per_word - 1) | (priv->type << SPI_FRF_OFFSET) | 3135bef6fd7SStefan Roese (priv->mode << SPI_MODE_OFFSET) | 3145bef6fd7SStefan Roese (priv->tmode << SPI_TMOD_OFFSET); 3155bef6fd7SStefan Roese 3165bef6fd7SStefan Roese if (rx && tx) 3175bef6fd7SStefan Roese priv->tmode = SPI_TMOD_TR; 3185bef6fd7SStefan Roese else if (rx) 3195bef6fd7SStefan Roese priv->tmode = SPI_TMOD_RO; 3205bef6fd7SStefan Roese else 3215bef6fd7SStefan Roese priv->tmode = SPI_TMOD_TO; 3225bef6fd7SStefan Roese 3235bef6fd7SStefan Roese cr0 &= ~SPI_TMOD_MASK; 3245bef6fd7SStefan Roese cr0 |= (priv->tmode << SPI_TMOD_OFFSET); 3255bef6fd7SStefan Roese 326*a72f8020SStefan Roese priv->len = bitlen >> 3; 3275bef6fd7SStefan Roese debug("%s: rx=%p tx=%p len=%d [bytes]\n", __func__, rx, tx, priv->len); 3285bef6fd7SStefan Roese 3295bef6fd7SStefan Roese priv->tx = (void *)tx; 3305bef6fd7SStefan Roese priv->tx_end = priv->tx + priv->len; 3315bef6fd7SStefan Roese priv->rx = rx; 3325bef6fd7SStefan Roese priv->rx_end = priv->rx + priv->len; 3335bef6fd7SStefan Roese 3345bef6fd7SStefan Roese /* Disable controller before writing control registers */ 3355bef6fd7SStefan Roese spi_enable_chip(priv, 0); 3365bef6fd7SStefan Roese 3375bef6fd7SStefan Roese debug("%s: cr0=%08x\n", __func__, cr0); 3385bef6fd7SStefan Roese /* Reprogram cr0 only if changed */ 3395bef6fd7SStefan Roese if (dw_readw(priv, DW_SPI_CTRL0) != cr0) 3405bef6fd7SStefan Roese dw_writew(priv, DW_SPI_CTRL0, cr0); 3415bef6fd7SStefan Roese 3425bef6fd7SStefan Roese /* 3435bef6fd7SStefan Roese * Configure the desired SS (slave select 0...3) in the controller 3445bef6fd7SStefan Roese * The DW SPI controller will activate and deactivate this CS 3455bef6fd7SStefan Roese * automatically. So no cs_activate() etc is needed in this driver. 3465bef6fd7SStefan Roese */ 3475bef6fd7SStefan Roese cs = spi_chip_select(dev); 3485bef6fd7SStefan Roese dw_writel(priv, DW_SPI_SER, 1 << cs); 3495bef6fd7SStefan Roese 3505bef6fd7SStefan Roese /* Enable controller after writing control registers */ 3515bef6fd7SStefan Roese spi_enable_chip(priv, 1); 3525bef6fd7SStefan Roese 3535bef6fd7SStefan Roese /* Start transfer in a polling loop */ 3545bef6fd7SStefan Roese ret = poll_transfer(priv); 3555bef6fd7SStefan Roese 3565bef6fd7SStefan Roese return ret; 3575bef6fd7SStefan Roese } 3585bef6fd7SStefan Roese 3595bef6fd7SStefan Roese static int dw_spi_set_speed(struct udevice *bus, uint speed) 3605bef6fd7SStefan Roese { 3615bef6fd7SStefan Roese struct dw_spi_platdata *plat = bus->platdata; 3625bef6fd7SStefan Roese struct dw_spi_priv *priv = dev_get_priv(bus); 3635bef6fd7SStefan Roese u16 clk_div; 3645bef6fd7SStefan Roese 3655bef6fd7SStefan Roese if (speed > plat->frequency) 3665bef6fd7SStefan Roese speed = plat->frequency; 3675bef6fd7SStefan Roese 3685bef6fd7SStefan Roese /* Disable controller before writing control registers */ 3695bef6fd7SStefan Roese spi_enable_chip(priv, 0); 3705bef6fd7SStefan Roese 3715bef6fd7SStefan Roese /* clk_div doesn't support odd number */ 372*a72f8020SStefan Roese clk_div = cm_get_spi_controller_clk_hz() / speed; 3735bef6fd7SStefan Roese clk_div = (clk_div + 1) & 0xfffe; 3745bef6fd7SStefan Roese dw_writel(priv, DW_SPI_BAUDR, clk_div); 3755bef6fd7SStefan Roese 3765bef6fd7SStefan Roese /* Enable controller after writing control registers */ 3775bef6fd7SStefan Roese spi_enable_chip(priv, 1); 3785bef6fd7SStefan Roese 3795bef6fd7SStefan Roese priv->freq = speed; 3805bef6fd7SStefan Roese debug("%s: regs=%p speed=%d clk_div=%d\n", __func__, priv->regs, 3815bef6fd7SStefan Roese priv->freq, clk_div); 3825bef6fd7SStefan Roese 3835bef6fd7SStefan Roese return 0; 3845bef6fd7SStefan Roese } 3855bef6fd7SStefan Roese 3865bef6fd7SStefan Roese static int dw_spi_set_mode(struct udevice *bus, uint mode) 3875bef6fd7SStefan Roese { 3885bef6fd7SStefan Roese struct dw_spi_priv *priv = dev_get_priv(bus); 3895bef6fd7SStefan Roese 3905bef6fd7SStefan Roese /* 3915bef6fd7SStefan Roese * Can't set mode yet. Since this depends on if rx, tx, or 3925bef6fd7SStefan Roese * rx & tx is requested. So we have to defer this to the 3935bef6fd7SStefan Roese * real transfer function. 3945bef6fd7SStefan Roese */ 3955bef6fd7SStefan Roese priv->mode = mode; 3965bef6fd7SStefan Roese debug("%s: regs=%p, mode=%d\n", __func__, priv->regs, priv->mode); 3975bef6fd7SStefan Roese 3985bef6fd7SStefan Roese return 0; 3995bef6fd7SStefan Roese } 4005bef6fd7SStefan Roese 4015bef6fd7SStefan Roese static const struct dm_spi_ops dw_spi_ops = { 4025bef6fd7SStefan Roese .xfer = dw_spi_xfer, 4035bef6fd7SStefan Roese .set_speed = dw_spi_set_speed, 4045bef6fd7SStefan Roese .set_mode = dw_spi_set_mode, 4055bef6fd7SStefan Roese /* 4065bef6fd7SStefan Roese * cs_info is not needed, since we require all chip selects to be 4075bef6fd7SStefan Roese * in the device tree explicitly 4085bef6fd7SStefan Roese */ 4095bef6fd7SStefan Roese }; 4105bef6fd7SStefan Roese 4115bef6fd7SStefan Roese static const struct udevice_id dw_spi_ids[] = { 4125bef6fd7SStefan Roese { .compatible = "snps,dw-spi-mmio" }, 4135bef6fd7SStefan Roese { } 4145bef6fd7SStefan Roese }; 4155bef6fd7SStefan Roese 4165bef6fd7SStefan Roese U_BOOT_DRIVER(dw_spi) = { 4175bef6fd7SStefan Roese .name = "dw_spi", 4185bef6fd7SStefan Roese .id = UCLASS_SPI, 4195bef6fd7SStefan Roese .of_match = dw_spi_ids, 4205bef6fd7SStefan Roese .ops = &dw_spi_ops, 4215bef6fd7SStefan Roese .ofdata_to_platdata = dw_spi_ofdata_to_platdata, 4225bef6fd7SStefan Roese .platdata_auto_alloc_size = sizeof(struct dw_spi_platdata), 4235bef6fd7SStefan Roese .priv_auto_alloc_size = sizeof(struct dw_spi_priv), 4245bef6fd7SStefan Roese .per_child_auto_alloc_size = sizeof(struct spi_slave), 4255bef6fd7SStefan Roese .probe = dw_spi_probe, 4265bef6fd7SStefan Roese }; 427