11b2fd5bfSSimon Glass /* 21b2fd5bfSSimon Glass * spi driver for rockchip 31b2fd5bfSSimon Glass * 41b2fd5bfSSimon Glass * (C) Copyright 2015 Google, Inc 51b2fd5bfSSimon Glass * 61b2fd5bfSSimon Glass * (C) Copyright 2008-2013 Rockchip Electronics 71b2fd5bfSSimon Glass * Peter, Software Engineering, <superpeter.cai@gmail.com>. 81b2fd5bfSSimon Glass * 91b2fd5bfSSimon Glass * SPDX-License-Identifier: GPL-2.0+ 101b2fd5bfSSimon Glass */ 111b2fd5bfSSimon Glass 121b2fd5bfSSimon Glass #include <common.h> 131b2fd5bfSSimon Glass #include <clk.h> 141b2fd5bfSSimon Glass #include <dm.h> 156e019c4fSSimon Glass #include <dt-structs.h> 161b2fd5bfSSimon Glass #include <errno.h> 171b2fd5bfSSimon Glass #include <spi.h> 181221ce45SMasahiro Yamada #include <linux/errno.h> 191b2fd5bfSSimon Glass #include <asm/io.h> 201b2fd5bfSSimon Glass #include <asm/arch/clock.h> 211b2fd5bfSSimon Glass #include <asm/arch/periph.h> 221b2fd5bfSSimon Glass #include <dm/pinctrl.h> 231b2fd5bfSSimon Glass #include "rk_spi.h" 241b2fd5bfSSimon Glass 251b2fd5bfSSimon Glass DECLARE_GLOBAL_DATA_PTR; 261b2fd5bfSSimon Glass 271b2fd5bfSSimon Glass /* Change to 1 to output registers at the start of each transaction */ 281b2fd5bfSSimon Glass #define DEBUG_RK_SPI 0 291b2fd5bfSSimon Glass 301b2fd5bfSSimon Glass struct rockchip_spi_platdata { 316e019c4fSSimon Glass #if CONFIG_IS_ENABLED(OF_PLATDATA) 326e019c4fSSimon Glass struct dtd_rockchip_rk3288_spi of_plat; 336e019c4fSSimon Glass #endif 341b2fd5bfSSimon Glass s32 frequency; /* Default clock frequency, -1 for none */ 351b2fd5bfSSimon Glass fdt_addr_t base; 361b2fd5bfSSimon Glass uint deactivate_delay_us; /* Delay to wait after deactivate */ 37183a3a0fSSimon Glass uint activate_delay_us; /* Delay to wait after activate */ 381b2fd5bfSSimon Glass }; 391b2fd5bfSSimon Glass 401b2fd5bfSSimon Glass struct rockchip_spi_priv { 411b2fd5bfSSimon Glass struct rockchip_spi *regs; 42135aa950SStephen Warren struct clk clk; 431b2fd5bfSSimon Glass unsigned int max_freq; 441b2fd5bfSSimon Glass unsigned int mode; 451b2fd5bfSSimon Glass ulong last_transaction_us; /* Time of last transaction end */ 461b2fd5bfSSimon Glass u8 bits_per_word; /* max 16 bits per word */ 471b2fd5bfSSimon Glass u8 n_bytes; 481b2fd5bfSSimon Glass unsigned int speed_hz; 4928a943c1SSimon Glass unsigned int last_speed_hz; 501b2fd5bfSSimon Glass unsigned int tmode; 511b2fd5bfSSimon Glass uint input_rate; 521b2fd5bfSSimon Glass }; 531b2fd5bfSSimon Glass 541b2fd5bfSSimon Glass #define SPI_FIFO_DEPTH 32 551b2fd5bfSSimon Glass 561b2fd5bfSSimon Glass static void rkspi_dump_regs(struct rockchip_spi *regs) 571b2fd5bfSSimon Glass { 581b2fd5bfSSimon Glass debug("ctrl0: \t\t0x%08x\n", readl(®s->ctrlr0)); 591b2fd5bfSSimon Glass debug("ctrl1: \t\t0x%08x\n", readl(®s->ctrlr1)); 601b2fd5bfSSimon Glass debug("ssienr: \t\t0x%08x\n", readl(®s->enr)); 611b2fd5bfSSimon Glass debug("ser: \t\t0x%08x\n", readl(®s->ser)); 621b2fd5bfSSimon Glass debug("baudr: \t\t0x%08x\n", readl(®s->baudr)); 631b2fd5bfSSimon Glass debug("txftlr: \t\t0x%08x\n", readl(®s->txftlr)); 641b2fd5bfSSimon Glass debug("rxftlr: \t\t0x%08x\n", readl(®s->rxftlr)); 651b2fd5bfSSimon Glass debug("txflr: \t\t0x%08x\n", readl(®s->txflr)); 661b2fd5bfSSimon Glass debug("rxflr: \t\t0x%08x\n", readl(®s->rxflr)); 671b2fd5bfSSimon Glass debug("sr: \t\t0x%08x\n", readl(®s->sr)); 681b2fd5bfSSimon Glass debug("imr: \t\t0x%08x\n", readl(®s->imr)); 691b2fd5bfSSimon Glass debug("isr: \t\t0x%08x\n", readl(®s->isr)); 701b2fd5bfSSimon Glass debug("dmacr: \t\t0x%08x\n", readl(®s->dmacr)); 711b2fd5bfSSimon Glass debug("dmatdlr: \t0x%08x\n", readl(®s->dmatdlr)); 721b2fd5bfSSimon Glass debug("dmardlr: \t0x%08x\n", readl(®s->dmardlr)); 731b2fd5bfSSimon Glass } 741b2fd5bfSSimon Glass 751b2fd5bfSSimon Glass static void rkspi_enable_chip(struct rockchip_spi *regs, bool enable) 761b2fd5bfSSimon Glass { 771b2fd5bfSSimon Glass writel(enable ? 1 : 0, ®s->enr); 781b2fd5bfSSimon Glass } 791b2fd5bfSSimon Glass 801b2fd5bfSSimon Glass static void rkspi_set_clk(struct rockchip_spi_priv *priv, uint speed) 811b2fd5bfSSimon Glass { 829fc354e2SPhilipp Tomsich /* 839fc354e2SPhilipp Tomsich * We should try not to exceed the speed requested by the caller: 849fc354e2SPhilipp Tomsich * when selecting a divider, we need to make sure we round up. 859fc354e2SPhilipp Tomsich */ 869fc354e2SPhilipp Tomsich uint clk_div = DIV_ROUND_UP(priv->input_rate, speed); 871b2fd5bfSSimon Glass 889fc354e2SPhilipp Tomsich /* The baudrate register (BAUDR) is defined as a 32bit register where 899fc354e2SPhilipp Tomsich * the upper 16bit are reserved and having 'Fsclk_out' in the lower 909fc354e2SPhilipp Tomsich * 16bits with 'Fsclk_out' defined as follows: 919fc354e2SPhilipp Tomsich * 929fc354e2SPhilipp Tomsich * Fsclk_out = Fspi_clk/ SCKDV 939fc354e2SPhilipp Tomsich * Where SCKDV is any even value between 2 and 65534. 949fc354e2SPhilipp Tomsich */ 959fc354e2SPhilipp Tomsich if (clk_div > 0xfffe) { 969fc354e2SPhilipp Tomsich clk_div = 0xfffe; 97204b4e68SHeinrich Schuchardt debug("%s: can't divide down to %d Hz (actual will be %d Hz)\n", 989fc354e2SPhilipp Tomsich __func__, speed, priv->input_rate / clk_div); 999fc354e2SPhilipp Tomsich } 1009fc354e2SPhilipp Tomsich 1019fc354e2SPhilipp Tomsich /* Round up to the next even 16bit number */ 1029fc354e2SPhilipp Tomsich clk_div = (clk_div + 1) & 0xfffe; 1039fc354e2SPhilipp Tomsich 1041b2fd5bfSSimon Glass debug("spi speed %u, div %u\n", speed, clk_div); 1051b2fd5bfSSimon Glass 1069fc354e2SPhilipp Tomsich clrsetbits_le32(&priv->regs->baudr, 0xffff, clk_div); 10728a943c1SSimon Glass priv->last_speed_hz = speed; 1081b2fd5bfSSimon Glass } 1091b2fd5bfSSimon Glass 1101b2fd5bfSSimon Glass static int rkspi_wait_till_not_busy(struct rockchip_spi *regs) 1111b2fd5bfSSimon Glass { 1121b2fd5bfSSimon Glass unsigned long start; 1131b2fd5bfSSimon Glass 1141b2fd5bfSSimon Glass start = get_timer(0); 1151b2fd5bfSSimon Glass while (readl(®s->sr) & SR_BUSY) { 1161b2fd5bfSSimon Glass if (get_timer(start) > ROCKCHIP_SPI_TIMEOUT_MS) { 1171b2fd5bfSSimon Glass debug("RK SPI: Status keeps busy for 1000us after a read/write!\n"); 1181b2fd5bfSSimon Glass return -ETIMEDOUT; 1191b2fd5bfSSimon Glass } 1201b2fd5bfSSimon Glass } 1211b2fd5bfSSimon Glass 1221b2fd5bfSSimon Glass return 0; 1231b2fd5bfSSimon Glass } 1241b2fd5bfSSimon Glass 125183a3a0fSSimon Glass static void spi_cs_activate(struct udevice *dev, uint cs) 1261b2fd5bfSSimon Glass { 127183a3a0fSSimon Glass struct udevice *bus = dev->parent; 128183a3a0fSSimon Glass struct rockchip_spi_platdata *plat = bus->platdata; 129183a3a0fSSimon Glass struct rockchip_spi_priv *priv = dev_get_priv(bus); 130183a3a0fSSimon Glass struct rockchip_spi *regs = priv->regs; 131183a3a0fSSimon Glass 132b4252474SSimon Glass /* If it's too soon to do another transaction, wait */ 133b4252474SSimon Glass if (plat->deactivate_delay_us && priv->last_transaction_us) { 134b4252474SSimon Glass ulong delay_us; /* The delay completed so far */ 135b4252474SSimon Glass delay_us = timer_get_us() - priv->last_transaction_us; 136b4252474SSimon Glass if (delay_us < plat->deactivate_delay_us) 137b4252474SSimon Glass udelay(plat->deactivate_delay_us - delay_us); 138b4252474SSimon Glass } 139b4252474SSimon Glass 1401b2fd5bfSSimon Glass debug("activate cs%u\n", cs); 1411b2fd5bfSSimon Glass writel(1 << cs, ®s->ser); 142183a3a0fSSimon Glass if (plat->activate_delay_us) 143183a3a0fSSimon Glass udelay(plat->activate_delay_us); 1441b2fd5bfSSimon Glass } 1451b2fd5bfSSimon Glass 146183a3a0fSSimon Glass static void spi_cs_deactivate(struct udevice *dev, uint cs) 1471b2fd5bfSSimon Glass { 148183a3a0fSSimon Glass struct udevice *bus = dev->parent; 149183a3a0fSSimon Glass struct rockchip_spi_platdata *plat = bus->platdata; 150183a3a0fSSimon Glass struct rockchip_spi_priv *priv = dev_get_priv(bus); 151183a3a0fSSimon Glass struct rockchip_spi *regs = priv->regs; 152183a3a0fSSimon Glass 1531b2fd5bfSSimon Glass debug("deactivate cs%u\n", cs); 1541b2fd5bfSSimon Glass writel(0, ®s->ser); 155183a3a0fSSimon Glass 156183a3a0fSSimon Glass /* Remember time of this transaction so we can honour the bus delay */ 157183a3a0fSSimon Glass if (plat->deactivate_delay_us) 158183a3a0fSSimon Glass priv->last_transaction_us = timer_get_us(); 1591b2fd5bfSSimon Glass } 1601b2fd5bfSSimon Glass 1616e019c4fSSimon Glass #if CONFIG_IS_ENABLED(OF_PLATDATA) 1626e019c4fSSimon Glass static int conv_of_platdata(struct udevice *dev) 1636e019c4fSSimon Glass { 1646e019c4fSSimon Glass struct rockchip_spi_platdata *plat = dev->platdata; 1656e019c4fSSimon Glass struct dtd_rockchip_rk3288_spi *dtplat = &plat->of_plat; 1666e019c4fSSimon Glass struct rockchip_spi_priv *priv = dev_get_priv(dev); 1676e019c4fSSimon Glass int ret; 1686e019c4fSSimon Glass 1696e019c4fSSimon Glass plat->base = dtplat->reg[0]; 1706e019c4fSSimon Glass plat->frequency = 20000000; 1716e019c4fSSimon Glass ret = clk_get_by_index_platdata(dev, 0, dtplat->clocks, &priv->clk); 1726e019c4fSSimon Glass if (ret < 0) 1736e019c4fSSimon Glass return ret; 1746e019c4fSSimon Glass dev->req_seq = 0; 1756e019c4fSSimon Glass 1766e019c4fSSimon Glass return 0; 1776e019c4fSSimon Glass } 1786e019c4fSSimon Glass #endif 1796e019c4fSSimon Glass 1801b2fd5bfSSimon Glass static int rockchip_spi_ofdata_to_platdata(struct udevice *bus) 1811b2fd5bfSSimon Glass { 1826e019c4fSSimon Glass #if !CONFIG_IS_ENABLED(OF_PLATDATA) 1836e019c4fSSimon Glass struct rockchip_spi_platdata *plat = dev_get_platdata(bus); 18471037d1cSSimon Glass struct rockchip_spi_priv *priv = dev_get_priv(bus); 1851b2fd5bfSSimon Glass int ret; 1861b2fd5bfSSimon Glass 187a9db6e69SPhilipp Tomsich plat->base = dev_read_addr(bus); 1881b2fd5bfSSimon Glass 18971037d1cSSimon Glass ret = clk_get_by_index(bus, 0, &priv->clk); 19071037d1cSSimon Glass if (ret < 0) { 19171037d1cSSimon Glass debug("%s: Could not get clock for %s: %d\n", __func__, 19271037d1cSSimon Glass bus->name, ret); 19371037d1cSSimon Glass return ret; 19471037d1cSSimon Glass } 1951b2fd5bfSSimon Glass 1966c65577cSPhilipp Tomsich plat->frequency = 1976c65577cSPhilipp Tomsich dev_read_u32_default(bus, "spi-max-frequency", 50000000); 1986c65577cSPhilipp Tomsich plat->deactivate_delay_us = 1996c65577cSPhilipp Tomsich dev_read_u32_default(bus, "spi-deactivate-delay", 0); 2006c65577cSPhilipp Tomsich plat->activate_delay_us = 2016c65577cSPhilipp Tomsich dev_read_u32_default(bus, "spi-activate-delay", 0); 2026c65577cSPhilipp Tomsich 20390a28470SSimon Glass debug("%s: base=%x, max-frequency=%d, deactivate_delay=%d\n", 20490a28470SSimon Glass __func__, (uint)plat->base, plat->frequency, 2051b2fd5bfSSimon Glass plat->deactivate_delay_us); 2066e019c4fSSimon Glass #endif 2071b2fd5bfSSimon Glass 2081b2fd5bfSSimon Glass return 0; 2091b2fd5bfSSimon Glass } 2101b2fd5bfSSimon Glass 211bd376714SPhilipp Tomsich static int rockchip_spi_calc_modclk(ulong max_freq) 212bd376714SPhilipp Tomsich { 213d16120a6SPhilipp Tomsich /* 214d16120a6SPhilipp Tomsich * While this is not strictly correct for the RK3368, as the 215d16120a6SPhilipp Tomsich * GPLL will be 576MHz, things will still work, as the 216d16120a6SPhilipp Tomsich * clk_set_rate(...) implementation in our clock-driver will 217d16120a6SPhilipp Tomsich * chose the next closest rate not exceeding what we request 218d16120a6SPhilipp Tomsich * based on the output of this function. 219d16120a6SPhilipp Tomsich */ 220d16120a6SPhilipp Tomsich 221bd376714SPhilipp Tomsich unsigned div; 222bd376714SPhilipp Tomsich const unsigned long gpll_hz = 594000000UL; 223bd376714SPhilipp Tomsich 224bd376714SPhilipp Tomsich /* 225bd376714SPhilipp Tomsich * We need to find an input clock that provides at least twice 226bd376714SPhilipp Tomsich * the maximum frequency and can be generated from the assumed 227bd376714SPhilipp Tomsich * speed of GPLL (594MHz) using an integer divider. 228bd376714SPhilipp Tomsich * 229bd376714SPhilipp Tomsich * To give us more achievable bitrates at higher speeds (these 230bd376714SPhilipp Tomsich * are generated by dividing by an even 16-bit integer from 231bd376714SPhilipp Tomsich * this frequency), we try to have an input frequency of at 232bd376714SPhilipp Tomsich * least 4x our max_freq. 233bd376714SPhilipp Tomsich */ 234bd376714SPhilipp Tomsich 235bd376714SPhilipp Tomsich div = DIV_ROUND_UP(gpll_hz, max_freq * 4); 236bd376714SPhilipp Tomsich return gpll_hz / div; 237bd376714SPhilipp Tomsich } 238bd376714SPhilipp Tomsich 2391b2fd5bfSSimon Glass static int rockchip_spi_probe(struct udevice *bus) 2401b2fd5bfSSimon Glass { 2411b2fd5bfSSimon Glass struct rockchip_spi_platdata *plat = dev_get_platdata(bus); 2421b2fd5bfSSimon Glass struct rockchip_spi_priv *priv = dev_get_priv(bus); 2431b2fd5bfSSimon Glass int ret; 2441b2fd5bfSSimon Glass 2451b2fd5bfSSimon Glass debug("%s: probe\n", __func__); 2466e019c4fSSimon Glass #if CONFIG_IS_ENABLED(OF_PLATDATA) 2476e019c4fSSimon Glass ret = conv_of_platdata(bus); 2486e019c4fSSimon Glass if (ret) 2496e019c4fSSimon Glass return ret; 2506e019c4fSSimon Glass #endif 2511b2fd5bfSSimon Glass priv->regs = (struct rockchip_spi *)plat->base; 2521b2fd5bfSSimon Glass 2531b2fd5bfSSimon Glass priv->last_transaction_us = timer_get_us(); 2541b2fd5bfSSimon Glass priv->max_freq = plat->frequency; 2551b2fd5bfSSimon Glass 256bd376714SPhilipp Tomsich /* Clamp the value from the DTS against any hardware limits */ 257bd376714SPhilipp Tomsich if (priv->max_freq > ROCKCHIP_SPI_MAX_RATE) 258bd376714SPhilipp Tomsich priv->max_freq = ROCKCHIP_SPI_MAX_RATE; 259bd376714SPhilipp Tomsich 260bd376714SPhilipp Tomsich /* Find a module-input clock that fits with the max_freq setting */ 261bd376714SPhilipp Tomsich ret = clk_set_rate(&priv->clk, 262bd376714SPhilipp Tomsich rockchip_spi_calc_modclk(priv->max_freq)); 2631b2fd5bfSSimon Glass if (ret < 0) { 2641b2fd5bfSSimon Glass debug("%s: Failed to set clock: %d\n", __func__, ret); 2651b2fd5bfSSimon Glass return ret; 2661b2fd5bfSSimon Glass } 2671b2fd5bfSSimon Glass priv->input_rate = ret; 2681b2fd5bfSSimon Glass debug("%s: rate = %u\n", __func__, priv->input_rate); 2691b2fd5bfSSimon Glass priv->bits_per_word = 8; 2701b2fd5bfSSimon Glass priv->tmode = TMOD_TR; /* Tx & Rx */ 2711b2fd5bfSSimon Glass 2721b2fd5bfSSimon Glass return 0; 2731b2fd5bfSSimon Glass } 2741b2fd5bfSSimon Glass 2751b2fd5bfSSimon Glass static int rockchip_spi_claim_bus(struct udevice *dev) 2761b2fd5bfSSimon Glass { 2771b2fd5bfSSimon Glass struct udevice *bus = dev->parent; 2781b2fd5bfSSimon Glass struct rockchip_spi_priv *priv = dev_get_priv(bus); 2791b2fd5bfSSimon Glass struct rockchip_spi *regs = priv->regs; 2801b2fd5bfSSimon Glass u8 spi_dfs, spi_tf; 2811b2fd5bfSSimon Glass uint ctrlr0; 2821b2fd5bfSSimon Glass 2831b2fd5bfSSimon Glass /* Disable the SPI hardware */ 2841b2fd5bfSSimon Glass rkspi_enable_chip(regs, 0); 2851b2fd5bfSSimon Glass 2861b2fd5bfSSimon Glass switch (priv->bits_per_word) { 2871b2fd5bfSSimon Glass case 8: 2881b2fd5bfSSimon Glass priv->n_bytes = 1; 2891b2fd5bfSSimon Glass spi_dfs = DFS_8BIT; 2901b2fd5bfSSimon Glass spi_tf = HALF_WORD_OFF; 2911b2fd5bfSSimon Glass break; 2921b2fd5bfSSimon Glass case 16: 2931b2fd5bfSSimon Glass priv->n_bytes = 2; 2941b2fd5bfSSimon Glass spi_dfs = DFS_16BIT; 2951b2fd5bfSSimon Glass spi_tf = HALF_WORD_ON; 2961b2fd5bfSSimon Glass break; 2971b2fd5bfSSimon Glass default: 2981b2fd5bfSSimon Glass debug("%s: unsupported bits: %dbits\n", __func__, 2991b2fd5bfSSimon Glass priv->bits_per_word); 3001b2fd5bfSSimon Glass return -EPROTONOSUPPORT; 3011b2fd5bfSSimon Glass } 3021b2fd5bfSSimon Glass 30328a943c1SSimon Glass if (priv->speed_hz != priv->last_speed_hz) 3041b2fd5bfSSimon Glass rkspi_set_clk(priv, priv->speed_hz); 3051b2fd5bfSSimon Glass 3061b2fd5bfSSimon Glass /* Operation Mode */ 3071b2fd5bfSSimon Glass ctrlr0 = OMOD_MASTER << OMOD_SHIFT; 3081b2fd5bfSSimon Glass 3091b2fd5bfSSimon Glass /* Data Frame Size */ 3102b9fe111SSimon Glass ctrlr0 |= spi_dfs << DFS_SHIFT; 3111b2fd5bfSSimon Glass 3121b2fd5bfSSimon Glass /* set SPI mode 0..3 */ 3131b2fd5bfSSimon Glass if (priv->mode & SPI_CPOL) 3141b2fd5bfSSimon Glass ctrlr0 |= SCOL_HIGH << SCOL_SHIFT; 3151b2fd5bfSSimon Glass if (priv->mode & SPI_CPHA) 3161b2fd5bfSSimon Glass ctrlr0 |= SCPH_TOGSTA << SCPH_SHIFT; 3171b2fd5bfSSimon Glass 3181b2fd5bfSSimon Glass /* Chip Select Mode */ 3191b2fd5bfSSimon Glass ctrlr0 |= CSM_KEEP << CSM_SHIFT; 3201b2fd5bfSSimon Glass 3211b2fd5bfSSimon Glass /* SSN to Sclk_out delay */ 3221b2fd5bfSSimon Glass ctrlr0 |= SSN_DELAY_ONE << SSN_DELAY_SHIFT; 3231b2fd5bfSSimon Glass 3241b2fd5bfSSimon Glass /* Serial Endian Mode */ 3251b2fd5bfSSimon Glass ctrlr0 |= SEM_LITTLE << SEM_SHIFT; 3261b2fd5bfSSimon Glass 3271b2fd5bfSSimon Glass /* First Bit Mode */ 3281b2fd5bfSSimon Glass ctrlr0 |= FBM_MSB << FBM_SHIFT; 3291b2fd5bfSSimon Glass 3301b2fd5bfSSimon Glass /* Byte and Halfword Transform */ 3312b9fe111SSimon Glass ctrlr0 |= spi_tf << HALF_WORD_TX_SHIFT; 3321b2fd5bfSSimon Glass 3331b2fd5bfSSimon Glass /* Rxd Sample Delay */ 3341b2fd5bfSSimon Glass ctrlr0 |= 0 << RXDSD_SHIFT; 3351b2fd5bfSSimon Glass 3361b2fd5bfSSimon Glass /* Frame Format */ 3371b2fd5bfSSimon Glass ctrlr0 |= FRF_SPI << FRF_SHIFT; 3381b2fd5bfSSimon Glass 3391b2fd5bfSSimon Glass /* Tx and Rx mode */ 3401b2fd5bfSSimon Glass ctrlr0 |= (priv->tmode & TMOD_MASK) << TMOD_SHIFT; 3411b2fd5bfSSimon Glass 3421b2fd5bfSSimon Glass writel(ctrlr0, ®s->ctrlr0); 3431b2fd5bfSSimon Glass 3441b2fd5bfSSimon Glass return 0; 3451b2fd5bfSSimon Glass } 3461b2fd5bfSSimon Glass 3471b2fd5bfSSimon Glass static int rockchip_spi_release_bus(struct udevice *dev) 3481b2fd5bfSSimon Glass { 349e15af8e2SSimon Glass struct udevice *bus = dev->parent; 350e15af8e2SSimon Glass struct rockchip_spi_priv *priv = dev_get_priv(bus); 351e15af8e2SSimon Glass 352e15af8e2SSimon Glass rkspi_enable_chip(priv->regs, false); 353e15af8e2SSimon Glass 3541b2fd5bfSSimon Glass return 0; 3551b2fd5bfSSimon Glass } 3561b2fd5bfSSimon Glass 3571b2fd5bfSSimon Glass static int rockchip_spi_xfer(struct udevice *dev, unsigned int bitlen, 3581b2fd5bfSSimon Glass const void *dout, void *din, unsigned long flags) 3591b2fd5bfSSimon Glass { 3601b2fd5bfSSimon Glass struct udevice *bus = dev->parent; 3611b2fd5bfSSimon Glass struct rockchip_spi_priv *priv = dev_get_priv(bus); 3621b2fd5bfSSimon Glass struct rockchip_spi *regs = priv->regs; 3631b2fd5bfSSimon Glass struct dm_spi_slave_platdata *slave_plat = dev_get_parent_platdata(dev); 3641b2fd5bfSSimon Glass int len = bitlen >> 3; 3651b2fd5bfSSimon Glass const u8 *out = dout; 3661b2fd5bfSSimon Glass u8 *in = din; 3671b2fd5bfSSimon Glass int toread, towrite; 3681b2fd5bfSSimon Glass int ret; 3691b2fd5bfSSimon Glass 3701b2fd5bfSSimon Glass debug("%s: dout=%p, din=%p, len=%x, flags=%lx\n", __func__, dout, din, 3711b2fd5bfSSimon Glass len, flags); 3721b2fd5bfSSimon Glass if (DEBUG_RK_SPI) 3731b2fd5bfSSimon Glass rkspi_dump_regs(regs); 3741b2fd5bfSSimon Glass 3751b2fd5bfSSimon Glass /* Assert CS before transfer */ 3761b2fd5bfSSimon Glass if (flags & SPI_XFER_BEGIN) 377183a3a0fSSimon Glass spi_cs_activate(dev, slave_plat->cs); 3781b2fd5bfSSimon Glass 3791b2fd5bfSSimon Glass while (len > 0) { 3801b2fd5bfSSimon Glass int todo = min(len, 0xffff); 3811b2fd5bfSSimon Glass 382e15af8e2SSimon Glass rkspi_enable_chip(regs, false); 3831b2fd5bfSSimon Glass writel(todo - 1, ®s->ctrlr1); 3841b2fd5bfSSimon Glass rkspi_enable_chip(regs, true); 3851b2fd5bfSSimon Glass 3861b2fd5bfSSimon Glass toread = todo; 3871b2fd5bfSSimon Glass towrite = todo; 3881b2fd5bfSSimon Glass while (toread || towrite) { 3891b2fd5bfSSimon Glass u32 status = readl(®s->sr); 3901b2fd5bfSSimon Glass 3911b2fd5bfSSimon Glass if (towrite && !(status & SR_TF_FULL)) { 3921b2fd5bfSSimon Glass writel(out ? *out++ : 0, regs->txdr); 3931b2fd5bfSSimon Glass towrite--; 3941b2fd5bfSSimon Glass } 3951b2fd5bfSSimon Glass if (toread && !(status & SR_RF_EMPT)) { 3961b2fd5bfSSimon Glass u32 byte = readl(regs->rxdr); 3971b2fd5bfSSimon Glass 3981b2fd5bfSSimon Glass if (in) 3991b2fd5bfSSimon Glass *in++ = byte; 4001b2fd5bfSSimon Glass toread--; 4011b2fd5bfSSimon Glass } 4021b2fd5bfSSimon Glass } 4031b2fd5bfSSimon Glass ret = rkspi_wait_till_not_busy(regs); 4041b2fd5bfSSimon Glass if (ret) 4051b2fd5bfSSimon Glass break; 4061b2fd5bfSSimon Glass len -= todo; 4071b2fd5bfSSimon Glass } 4081b2fd5bfSSimon Glass 4091b2fd5bfSSimon Glass /* Deassert CS after transfer */ 4101b2fd5bfSSimon Glass if (flags & SPI_XFER_END) 411183a3a0fSSimon Glass spi_cs_deactivate(dev, slave_plat->cs); 4121b2fd5bfSSimon Glass 4131b2fd5bfSSimon Glass rkspi_enable_chip(regs, false); 4141b2fd5bfSSimon Glass 4151b2fd5bfSSimon Glass return ret; 4161b2fd5bfSSimon Glass } 4171b2fd5bfSSimon Glass 4181b2fd5bfSSimon Glass static int rockchip_spi_set_speed(struct udevice *bus, uint speed) 4191b2fd5bfSSimon Glass { 4201b2fd5bfSSimon Glass struct rockchip_spi_priv *priv = dev_get_priv(bus); 4211b2fd5bfSSimon Glass 422bd376714SPhilipp Tomsich /* Clamp to the maximum frequency specified in the DTS */ 4231b2fd5bfSSimon Glass if (speed > priv->max_freq) 4241b2fd5bfSSimon Glass speed = priv->max_freq; 425bd376714SPhilipp Tomsich 4261b2fd5bfSSimon Glass priv->speed_hz = speed; 4271b2fd5bfSSimon Glass 4281b2fd5bfSSimon Glass return 0; 4291b2fd5bfSSimon Glass } 4301b2fd5bfSSimon Glass 4311b2fd5bfSSimon Glass static int rockchip_spi_set_mode(struct udevice *bus, uint mode) 4321b2fd5bfSSimon Glass { 4331b2fd5bfSSimon Glass struct rockchip_spi_priv *priv = dev_get_priv(bus); 4341b2fd5bfSSimon Glass 4351b2fd5bfSSimon Glass priv->mode = mode; 4361b2fd5bfSSimon Glass 4371b2fd5bfSSimon Glass return 0; 4381b2fd5bfSSimon Glass } 4391b2fd5bfSSimon Glass 4401b2fd5bfSSimon Glass static const struct dm_spi_ops rockchip_spi_ops = { 4411b2fd5bfSSimon Glass .claim_bus = rockchip_spi_claim_bus, 4421b2fd5bfSSimon Glass .release_bus = rockchip_spi_release_bus, 4431b2fd5bfSSimon Glass .xfer = rockchip_spi_xfer, 4441b2fd5bfSSimon Glass .set_speed = rockchip_spi_set_speed, 4451b2fd5bfSSimon Glass .set_mode = rockchip_spi_set_mode, 4461b2fd5bfSSimon Glass /* 4471b2fd5bfSSimon Glass * cs_info is not needed, since we require all chip selects to be 4481b2fd5bfSSimon Glass * in the device tree explicitly 4491b2fd5bfSSimon Glass */ 4501b2fd5bfSSimon Glass }; 4511b2fd5bfSSimon Glass 4521b2fd5bfSSimon Glass static const struct udevice_id rockchip_spi_ids[] = { 4531b2fd5bfSSimon Glass { .compatible = "rockchip,rk3288-spi" }, 454d16120a6SPhilipp Tomsich { .compatible = "rockchip,rk3368-spi" }, 455cdeb4d78SJakob Unterwurzacher { .compatible = "rockchip,rk3399-spi" }, 456*08ab3f3cSYifeng Zhao { .compatible = "rockchip,rk3066-spi" }, 457*08ab3f3cSYifeng Zhao { .compatible = "rockchip,rk3328-spi" }, 4581b2fd5bfSSimon Glass { } 4591b2fd5bfSSimon Glass }; 4601b2fd5bfSSimon Glass 4611b2fd5bfSSimon Glass U_BOOT_DRIVER(rockchip_spi) = { 4626e019c4fSSimon Glass #if CONFIG_IS_ENABLED(OF_PLATDATA) 4636e019c4fSSimon Glass .name = "rockchip_rk3288_spi", 4646e019c4fSSimon Glass #else 4651b2fd5bfSSimon Glass .name = "rockchip_spi", 4666e019c4fSSimon Glass #endif 4671b2fd5bfSSimon Glass .id = UCLASS_SPI, 4681b2fd5bfSSimon Glass .of_match = rockchip_spi_ids, 4691b2fd5bfSSimon Glass .ops = &rockchip_spi_ops, 4701b2fd5bfSSimon Glass .ofdata_to_platdata = rockchip_spi_ofdata_to_platdata, 4711b2fd5bfSSimon Glass .platdata_auto_alloc_size = sizeof(struct rockchip_spi_platdata), 4721b2fd5bfSSimon Glass .priv_auto_alloc_size = sizeof(struct rockchip_spi_priv), 4731b2fd5bfSSimon Glass .probe = rockchip_spi_probe, 4741b2fd5bfSSimon Glass }; 475