mtk_spi_v2.c revision 310158
1/*- 2 * Copyright (c) 2009, Oleksandr Tymoshenko <gonzo@FreeBSD.org> 3 * Copyright (c) 2011, Aleksandr Rybalko <ray@FreeBSD.org> 4 * Copyright (c) 2013, Alexander A. Mityaev <sansan@adm.ua> 5 * Copyright (c) 2016, Stanislav Galabov <sgalabov@gmail.com> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice unmodified, this list of conditions, and the following 13 * disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31#include <sys/cdefs.h> 32__FBSDID("$FreeBSD: stable/11/sys/mips/mediatek/mtk_spi_v2.c 310158 2016-12-16 15:45:09Z manu $"); 33 34#include <sys/param.h> 35#include <sys/systm.h> 36#include <sys/bus.h> 37 38#include <sys/kernel.h> 39#include <sys/module.h> 40#include <sys/rman.h> 41#include <sys/lock.h> 42#include <sys/mutex.h> 43 44#include <machine/bus.h> 45#include <machine/cpu.h> 46 47#include <dev/spibus/spi.h> 48#include <dev/spibus/spibusvar.h> 49#include "spibus_if.h" 50 51#include "opt_platform.h" 52 53#include <dev/ofw/openfirm.h> 54#include <dev/ofw/ofw_bus.h> 55#include <dev/ofw/ofw_bus_subr.h> 56 57#include <mips/mediatek/mtk_spi_v2.h> 58#include <dev/flash/mx25lreg.h> 59 60#undef MTK_SPI_DEBUG 61#ifdef MTK_SPI_DEBUG 62#define dprintf printf 63#else 64#define dprintf(x, arg...) 65#endif 66 67/* 68 * register space access macros 69 */ 70#define SPI_WRITE(sc, reg, val) do { \ 71 bus_write_4(sc->sc_mem_res, (reg), (val)); \ 72 } while (0) 73 74#define SPI_READ(sc, reg) bus_read_4(sc->sc_mem_res, (reg)) 75 76#define SPI_SET_BITS(sc, reg, bits) \ 77 SPI_WRITE(sc, reg, SPI_READ(sc, (reg)) | (bits)) 78 79#define SPI_CLEAR_BITS(sc, reg, bits) \ 80 SPI_WRITE(sc, reg, SPI_READ(sc, (reg)) & ~(bits)) 81 82struct mtk_spi_softc { 83 device_t sc_dev; 84 struct resource *sc_mem_res; 85}; 86 87static int mtk_spi_probe(device_t); 88static int mtk_spi_attach(device_t); 89static int mtk_spi_detach(device_t); 90static int mtk_spi_wait(struct mtk_spi_softc *); 91static void mtk_spi_chip_activate(struct mtk_spi_softc *); 92static void mtk_spi_chip_deactivate(struct mtk_spi_softc *); 93static uint8_t mtk_spi_txrx(struct mtk_spi_softc *, uint8_t *, int); 94static int mtk_spi_transfer(device_t, device_t, struct spi_command *); 95static phandle_t mtk_spi_get_node(device_t, device_t); 96 97static struct ofw_compat_data compat_data[] = { 98 { "ralink,mt7621-spi", 1 }, 99 { "ralink,mtk7628an-spi", 1 }, 100 { NULL, 0 } 101}; 102 103static int 104mtk_spi_probe(device_t dev) 105{ 106 107 if (!ofw_bus_status_okay(dev)) 108 return (ENXIO); 109 110 if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0) 111 return(ENXIO); 112 113 device_set_desc(dev, "MTK SPI Controller (v2)"); 114 115 return (0); 116} 117 118static int 119mtk_spi_attach(device_t dev) 120{ 121 struct mtk_spi_softc *sc = device_get_softc(dev); 122 uint32_t val; 123 int rid; 124 125 sc->sc_dev = dev; 126 rid = 0; 127 sc->sc_mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, 128 RF_ACTIVE); 129 if (!sc->sc_mem_res) { 130 device_printf(dev, "Could not map memory\n"); 131 return (ENXIO); 132 } 133 134 if (mtk_spi_wait(sc)) { 135 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); 136 return (EBUSY); 137 } 138 139 val = SPI_READ(sc, MTK_SPIMASTER); 140 val &= ~(0xfff << 16); 141 val |= 13 << 16; 142 val |= 7 << 29; 143 val |= 1 << 2; 144 SPI_WRITE(sc, MTK_SPIMASTER, val); 145 /* 146 * W25Q64CV max 104MHz, bus 120-192 MHz, so divide by 2. 147 * Update: divide by 4, DEV2 to fast for flash. 148 */ 149 150 device_add_child(dev, "spibus", 0); 151 return (bus_generic_attach(dev)); 152} 153 154static int 155mtk_spi_detach(device_t dev) 156{ 157 struct mtk_spi_softc *sc = device_get_softc(dev); 158 159 if (sc->sc_mem_res) 160 bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->sc_mem_res); 161 162 return (0); 163} 164 165static void 166mtk_spi_chip_activate(struct mtk_spi_softc *sc) 167{ 168 mtk_spi_wait(sc); 169 /* 170 * Put all CSx to low 171 */ 172 SPI_SET_BITS(sc, MTK_SPIPOLAR, 1); 173} 174 175static void 176mtk_spi_chip_deactivate(struct mtk_spi_softc *sc) 177{ 178 mtk_spi_wait(sc); 179 /* 180 * Put all CSx to high 181 */ 182 SPI_CLEAR_BITS(sc, MTK_SPIPOLAR, 1); 183} 184 185static int 186mtk_spi_wait(struct mtk_spi_softc *sc) 187{ 188 int i = 1000; 189 190 while (i--) { 191 if (!(SPI_READ(sc, MTK_SPITRANS) & SPIBUSY)) 192 break; 193 } 194 if (i == 0) { 195 return (1); 196 } 197 198 return (0); 199} 200 201static uint8_t 202mtk_spi_txrx(struct mtk_spi_softc *sc, uint8_t *data, int write) 203{ 204 205 if (mtk_spi_wait(sc)) 206 return (0xff); 207 208 if (write == MTK_SPI_WRITE) { 209 SPI_WRITE(sc, MTK_SPIOPCODE, (*data)); 210 SPI_WRITE(sc, MTK_SPIMOREBUF, (8<<24)); 211 } else { 212 SPI_WRITE(sc, MTK_SPIMOREBUF, (8<<12)); 213 } 214 215 SPI_SET_BITS(sc, MTK_SPITRANS, SPISTART); 216 217 if (mtk_spi_wait(sc)) 218 return (0xff); 219 220 if (write == MTK_SPI_READ) { 221 *data = SPI_READ(sc, MTK_SPIDATA) & 0xff; 222 } 223 224 return (0); 225} 226 227static int 228mtk_spi_transfer(device_t dev, device_t child, struct spi_command *cmd) 229{ 230 struct mtk_spi_softc *sc; 231 uint8_t *buf, byte, *tx_buf; 232 uint32_t cs; 233 int i, sz, error, write = 0; 234 235 sc = device_get_softc(dev); 236 237 spibus_get_cs(child, &cs); 238 239 if (cs != 0) 240 /* Only 1 CS */ 241 return (ENXIO); 242 243 /* There is always a command to transfer. */ 244 tx_buf = (uint8_t *)(cmd->tx_cmd); 245 246 /* Perform some fixup because MTK dont support duplex SPI */ 247 switch(tx_buf[0]) { 248 case CMD_READ_IDENT: 249 cmd->tx_cmd_sz = 1; 250 cmd->rx_cmd_sz = 3; 251 break; 252 case CMD_ENTER_4B_MODE: 253 case CMD_EXIT_4B_MODE: 254 case CMD_WRITE_ENABLE: 255 case CMD_WRITE_DISABLE: 256 cmd->tx_cmd_sz = 1; 257 cmd->rx_cmd_sz = 0; 258 break; 259 case CMD_READ_STATUS: 260 cmd->tx_cmd_sz = 1; 261 cmd->rx_cmd_sz = 1; 262 break; 263 case CMD_READ: 264 case CMD_FAST_READ: 265 cmd->rx_cmd_sz = cmd->tx_data_sz = 0; 266 break; 267 case CMD_SECTOR_ERASE: 268 cmd->rx_cmd_sz = 0; 269 break; 270 case CMD_PAGE_PROGRAM: 271 cmd->rx_cmd_sz = cmd->rx_data_sz = 0; 272 break; 273 } 274 275 mtk_spi_chip_activate(sc); 276 277 if (cmd->tx_cmd_sz + cmd->rx_cmd_sz) { 278 buf = (uint8_t *)(cmd->rx_cmd); 279 tx_buf = (uint8_t *)(cmd->tx_cmd); 280 sz = cmd->tx_cmd_sz + cmd->rx_cmd_sz; 281 282 for (i = 0; i < sz; i++) { 283 if(i < cmd->tx_cmd_sz) { 284 byte = tx_buf[i]; 285 error = mtk_spi_txrx(sc, &byte, 286 MTK_SPI_WRITE); 287 if (error) 288 goto mtk_spi_transfer_fail; 289 continue; 290 } 291 error = mtk_spi_txrx(sc, &byte, 292 MTK_SPI_READ); 293 if (error) 294 goto mtk_spi_transfer_fail; 295 buf[i] = byte; 296 } 297 } 298 299 /* 300 * Transfer/Receive data 301 */ 302 303 if (cmd->tx_data_sz + cmd->rx_data_sz) { 304 write = (cmd->tx_data_sz > 0)?1:0; 305 buf = (uint8_t *)(write ? cmd->tx_data : cmd->rx_data); 306 sz = write ? cmd->tx_data_sz : cmd->rx_data_sz; 307 308 for (i = 0; i < sz; i++) { 309 byte = buf[i]; 310 error = mtk_spi_txrx(sc, &byte, 311 write ? MTK_SPI_WRITE : MTK_SPI_READ); 312 if (error) 313 goto mtk_spi_transfer_fail; 314 buf[i] = byte; 315 } 316 } 317mtk_spi_transfer_fail: 318 mtk_spi_chip_deactivate(sc); 319 320 return (0); 321} 322 323static phandle_t 324mtk_spi_get_node(device_t bus, device_t dev) 325{ 326 327 /* We only have one child, the SPI bus, which needs our own node. */ 328 return (ofw_bus_get_node(bus)); 329} 330 331static device_method_t mtk_spi_methods[] = { 332 /* Device interface */ 333 DEVMETHOD(device_probe, mtk_spi_probe), 334 DEVMETHOD(device_attach, mtk_spi_attach), 335 DEVMETHOD(device_detach, mtk_spi_detach), 336 337 DEVMETHOD(spibus_transfer, mtk_spi_transfer), 338 339 /* ofw_bus interface */ 340 DEVMETHOD(ofw_bus_get_node, mtk_spi_get_node), 341 342 DEVMETHOD_END 343}; 344 345static driver_t mtk_spi_driver = { 346 .name = "spi", 347 .methods = mtk_spi_methods, 348 .size = sizeof(struct mtk_spi_softc), 349}; 350 351static devclass_t mtk_spi_devclass; 352 353DRIVER_MODULE(mtk_spi_v2, simplebus, mtk_spi_driver, mtk_spi_devclass, 0, 0); 354