1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2019 Axiado Corporation 5 * All rights reserved. 6 * 7 * This software was developed in part by Philip Paeps and Kristof Provost 8 * under contract for Axiado Corporation. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 * SUCH DAMAGE. 30 */ 31 32 #include <sys/cdefs.h> 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/bus.h> 36 #include <sys/kernel.h> 37 #include <sys/lock.h> 38 #include <sys/module.h> 39 #include <sys/mutex.h> 40 #include <sys/rman.h> 41 42 #include <machine/bus.h> 43 #include <machine/cpu.h> 44 45 #include <dev/extres/clk/clk.h> 46 47 #include <dev/ofw/ofw_bus.h> 48 #include <dev/ofw/ofw_bus_subr.h> 49 #include <dev/ofw/openfirm.h> 50 51 #include <dev/spibus/spi.h> 52 #include <dev/spibus/spibusvar.h> 53 54 #include "spibus_if.h" 55 56 #if 1 57 #define DBGPRINT(dev, fmt, args...) \ 58 device_printf(dev, "%s: " fmt "\n", __func__, ## args) 59 #else 60 #define DBGPRINT(dev, fmt, args...) 61 #endif 62 63 static struct resource_spec sfspi_spec[] = { 64 { SYS_RES_MEMORY, 0, RF_ACTIVE }, 65 RESOURCE_SPEC_END 66 }; 67 68 struct sfspi_softc { 69 device_t dev; 70 device_t parent; 71 72 struct mtx mtx; 73 74 struct resource *res; 75 bus_space_tag_t bst; 76 bus_space_handle_t bsh; 77 78 void *ih; 79 80 clk_t clk; 81 uint64_t freq; 82 uint32_t cs_max; 83 }; 84 85 #define SFSPI_LOCK(sc) mtx_lock(&(sc)->mtx) 86 #define SFSPI_UNLOCK(sc) mtx_unlock(&(sc)->mtx) 87 #define SFSPI_ASSERT_LOCKED(sc) mtx_assert(&(sc)->mtx, MA_OWNED); 88 #define SFSPI_ASSERT_UNLOCKED(sc) mtx_assert(&(sc)->mtx, MA_NOTOWNED); 89 90 /* 91 * Register offsets. 92 * From Sifive-Unleashed-FU540-C000-v1.0.pdf page 101. 93 */ 94 #define SFSPI_REG_SCKDIV 0x00 /* Serial clock divisor */ 95 #define SFSPI_REG_SCKMODE 0x04 /* Serial clock mode */ 96 #define SFSPI_REG_CSID 0x10 /* Chip select ID */ 97 #define SFSPI_REG_CSDEF 0x14 /* Chip select default */ 98 #define SFSPI_REG_CSMODE 0x18 /* Chip select mode */ 99 #define SFSPI_REG_DELAY0 0x28 /* Delay control 0 */ 100 #define SFSPI_REG_DELAY1 0x2C /* Delay control 1 */ 101 #define SFSPI_REG_FMT 0x40 /* Frame format */ 102 #define SFSPI_REG_TXDATA 0x48 /* Tx FIFO data */ 103 #define SFSPI_REG_RXDATA 0x4C /* Rx FIFO data */ 104 #define SFSPI_REG_TXMARK 0x50 /* Tx FIFO watermark */ 105 #define SFSPI_REG_RXMARK 0x54 /* Rx FIFO watermark */ 106 #define SFSPI_REG_FCTRL 0x60 /* SPI flash interface control* */ 107 #define SFSPI_REG_FFMT 0x64 /* SPI flash instruction format* */ 108 #define SFSPI_REG_IE 0x70 /* SPI interrupt enable */ 109 #define SFSPI_REG_IP 0x74 /* SPI interrupt pending */ 110 111 #define SFSPI_SCKDIV_MASK 0xfff 112 113 #define SFSPI_CSDEF_ALL ((1 << sc->cs_max)-1) 114 115 #define SFSPI_CSMODE_AUTO 0x0U 116 #define SFSPI_CSMODE_HOLD 0x2U 117 #define SFSPI_CSMODE_OFF 0x3U 118 119 #define SFSPI_TXDATA_DATA_MASK 0xff 120 #define SFSPI_TXDATA_FULL (1 << 31) 121 122 #define SFSPI_RXDATA_DATA_MASK 0xff 123 #define SFSPI_RXDATA_EMPTY (1 << 31) 124 125 #define SFSPI_SCKMODE_PHA (1 << 0) 126 #define SFSPI_SCKMODE_POL (1 << 1) 127 128 #define SFSPI_FMT_PROTO_SINGLE 0x0U 129 #define SFSPI_FMT_PROTO_DUAL 0x1U 130 #define SFSPI_FMT_PROTO_QUAD 0x2U 131 #define SFSPI_FMT_PROTO_MASK 0x3U 132 #define SFSPI_FMT_ENDIAN (1 << 2) 133 #define SFSPI_FMT_DIR (1 << 3) 134 #define SFSPI_FMT_LEN(x) ((uint32_t)(x) << 16) 135 #define SFSPI_FMT_LEN_MASK (0xfU << 16) 136 137 #define SFSPI_FIFO_DEPTH 8 138 139 #define SFSPI_READ(_sc, _reg) \ 140 bus_space_read_4((_sc)->bst, (_sc)->bsh, (_reg)) 141 #define SFSPI_WRITE(_sc, _reg, _val) \ 142 bus_space_write_4((_sc)->bst, (_sc)->bsh, (_reg), (_val)) 143 144 static void 145 sfspi_tx(struct sfspi_softc *sc, uint8_t *buf, uint32_t bufsiz) 146 { 147 uint32_t val; 148 uint8_t *p, *end; 149 150 KASSERT(buf != NULL, ("TX buffer cannot be NULL")); 151 152 end = buf + bufsiz; 153 for (p = buf; p < end; p++) { 154 do { 155 val = SFSPI_READ(sc, SFSPI_REG_TXDATA); 156 } while (val & SFSPI_TXDATA_FULL); 157 val = *p; 158 SFSPI_WRITE(sc, SFSPI_REG_TXDATA, val); 159 } 160 } 161 162 static void 163 sfspi_rx(struct sfspi_softc *sc, uint8_t *buf, uint32_t bufsiz) 164 { 165 uint32_t val; 166 uint8_t *p, *end; 167 168 KASSERT(buf != NULL, ("RX buffer cannot be NULL")); 169 KASSERT(bufsiz <= SFSPI_FIFO_DEPTH, 170 ("Cannot receive more than %d bytes at a time\n", 171 SFSPI_FIFO_DEPTH)); 172 173 end = buf + bufsiz; 174 for (p = buf; p < end; p++) { 175 do { 176 val = SFSPI_READ(sc, SFSPI_REG_RXDATA); 177 } while (val & SFSPI_RXDATA_EMPTY); 178 *p = val & SFSPI_RXDATA_DATA_MASK; 179 }; 180 } 181 182 static int 183 sfspi_xfer_buf(struct sfspi_softc *sc, uint8_t *rxbuf, uint8_t *txbuf, 184 uint32_t txlen, uint32_t rxlen) 185 { 186 uint32_t bytes; 187 188 KASSERT(txlen == rxlen, ("TX and RX lengths must be equal")); 189 KASSERT(rxbuf != NULL, ("RX buffer cannot be NULL")); 190 KASSERT(txbuf != NULL, ("TX buffer cannot be NULL")); 191 192 while (txlen) { 193 bytes = (txlen > SFSPI_FIFO_DEPTH) ? SFSPI_FIFO_DEPTH : txlen; 194 sfspi_tx(sc, txbuf, bytes); 195 txbuf += bytes; 196 sfspi_rx(sc, rxbuf, bytes); 197 rxbuf += bytes; 198 txlen -= bytes; 199 } 200 201 return (0); 202 } 203 204 static int 205 sfspi_setup(struct sfspi_softc *sc, uint32_t cs, uint32_t mode, 206 uint32_t freq) 207 { 208 uint32_t csmode, fmt, sckdiv, sckmode; 209 210 SFSPI_ASSERT_LOCKED(sc); 211 212 /* 213 * Fsck = Fin / 2 * (div + 1) 214 * -> div = Fin / (2 * Fsck) - 1 215 */ 216 sckdiv = (howmany(sc->freq >> 1, freq) - 1) & SFSPI_SCKDIV_MASK; 217 SFSPI_WRITE(sc, SFSPI_REG_SCKDIV, sckdiv); 218 219 switch (mode) { 220 case SPIBUS_MODE_NONE: 221 sckmode = 0; 222 break; 223 case SPIBUS_MODE_CPHA: 224 sckmode = SFSPI_SCKMODE_PHA; 225 break; 226 case SPIBUS_MODE_CPOL: 227 sckmode = SFSPI_SCKMODE_POL; 228 break; 229 case SPIBUS_MODE_CPOL_CPHA: 230 sckmode = SFSPI_SCKMODE_PHA | SFSPI_SCKMODE_POL; 231 break; 232 default: 233 return (EINVAL); 234 } 235 SFSPI_WRITE(sc, SFSPI_REG_SCKMODE, sckmode); 236 237 csmode = SFSPI_CSMODE_HOLD; 238 if (cs & SPIBUS_CS_HIGH) 239 csmode = SFSPI_CSMODE_AUTO; 240 SFSPI_WRITE(sc, SFSPI_REG_CSMODE, csmode); 241 242 SFSPI_WRITE(sc, SFSPI_REG_CSID, cs & ~SPIBUS_CS_HIGH); 243 244 fmt = SFSPI_FMT_PROTO_SINGLE | SFSPI_FMT_LEN(8); 245 SFSPI_WRITE(sc, SFSPI_REG_FMT, fmt); 246 247 return (0); 248 } 249 250 static int 251 sfspi_transfer(device_t dev, device_t child, struct spi_command *cmd) 252 { 253 struct sfspi_softc *sc; 254 uint32_t clock, cs, csdef, mode; 255 int err; 256 257 KASSERT(cmd->tx_cmd_sz == cmd->rx_cmd_sz, 258 ("TX and RX command sizes must be equal")); 259 KASSERT(cmd->tx_data_sz == cmd->rx_data_sz, 260 ("TX and RX data sizes must be equal")); 261 262 sc = device_get_softc(dev); 263 spibus_get_cs(child, &cs); 264 spibus_get_clock(child, &clock); 265 spibus_get_mode(child, &mode); 266 267 if (cs > sc->cs_max) { 268 device_printf(sc->dev, "Invalid chip select %u\n", cs); 269 return (EINVAL); 270 } 271 272 SFSPI_LOCK(sc); 273 device_busy(sc->dev); 274 275 err = sfspi_setup(sc, cs, mode, clock); 276 if (err != 0) { 277 SFSPI_UNLOCK(sc); 278 return (err); 279 } 280 281 err = 0; 282 if (cmd->tx_cmd_sz > 0) 283 err = sfspi_xfer_buf(sc, cmd->rx_cmd, cmd->tx_cmd, 284 cmd->tx_cmd_sz, cmd->rx_cmd_sz); 285 if (cmd->tx_data_sz > 0 && err == 0) 286 err = sfspi_xfer_buf(sc, cmd->rx_data, cmd->tx_data, 287 cmd->tx_data_sz, cmd->rx_data_sz); 288 289 /* Deassert chip select. */ 290 csdef = SFSPI_CSDEF_ALL & ~(1 << cs); 291 SFSPI_WRITE(sc, SFSPI_REG_CSDEF, csdef); 292 SFSPI_WRITE(sc, SFSPI_REG_CSDEF, SFSPI_CSDEF_ALL); 293 294 device_unbusy(sc->dev); 295 SFSPI_UNLOCK(sc); 296 297 return (err); 298 } 299 300 static int 301 sfspi_attach(device_t dev) 302 { 303 struct sfspi_softc *sc; 304 int error; 305 306 sc = device_get_softc(dev); 307 sc->dev = dev; 308 309 mtx_init(&sc->mtx, device_get_nameunit(sc->dev), NULL, MTX_DEF); 310 311 error = bus_alloc_resources(dev, sfspi_spec, &sc->res); 312 if (error) { 313 device_printf(dev, "Couldn't allocate resources\n"); 314 goto fail; 315 } 316 sc->bst = rman_get_bustag(sc->res); 317 sc->bsh = rman_get_bushandle(sc->res); 318 319 error = clk_get_by_ofw_index(dev, 0, 0, &sc->clk); 320 if (error) { 321 device_printf(dev, "Couldn't allocate clock: %d\n", error); 322 goto fail; 323 } 324 error = clk_enable(sc->clk); 325 if (error) { 326 device_printf(dev, "Couldn't enable clock: %d\n", error); 327 goto fail; 328 } 329 330 error = clk_get_freq(sc->clk, &sc->freq); 331 if (error) { 332 device_printf(sc->dev, "Couldn't get frequency: %d\n", error); 333 goto fail; 334 } 335 336 /* 337 * From Sifive-Unleashed-FU540-C000-v1.0.pdf page 103: 338 * csdef is cs_width bits wide and all ones on reset. 339 */ 340 sc->cs_max = SFSPI_READ(sc, SFSPI_REG_CSDEF); 341 342 /* 343 * We don't support the direct-mapped flash interface. 344 * Disable it. 345 */ 346 SFSPI_WRITE(sc, SFSPI_REG_FCTRL, 0x0); 347 348 /* Probe and attach the spibus when interrupts are available. */ 349 sc->parent = device_add_child(dev, "spibus", -1); 350 config_intrhook_oneshot((ich_func_t)bus_generic_attach, dev); 351 352 return (0); 353 354 fail: 355 bus_release_resources(dev, sfspi_spec, &sc->res); 356 mtx_destroy(&sc->mtx); 357 return (error); 358 } 359 360 static int 361 sfspi_probe(device_t dev) 362 { 363 364 if (!ofw_bus_status_okay(dev)) 365 return (ENXIO); 366 367 if (!ofw_bus_is_compatible(dev, "sifive,spi0")) 368 return (ENXIO); 369 370 device_set_desc(dev, "SiFive SPI controller"); 371 372 return (BUS_PROBE_DEFAULT); 373 } 374 375 static phandle_t 376 sfspi_get_node(device_t bus, device_t dev) 377 { 378 379 return (ofw_bus_get_node(bus)); 380 } 381 382 static device_method_t sfspi_methods[] = { 383 DEVMETHOD(device_probe, sfspi_probe), 384 DEVMETHOD(device_attach, sfspi_attach), 385 386 DEVMETHOD(spibus_transfer, sfspi_transfer), 387 388 DEVMETHOD(ofw_bus_get_node, sfspi_get_node), 389 390 DEVMETHOD_END 391 }; 392 393 static driver_t sfspi_driver = { 394 "sifive_spi", 395 sfspi_methods, 396 sizeof(struct sfspi_softc) 397 }; 398 399 DRIVER_MODULE(sifive_spi, simplebus, sfspi_driver, 0, 0); 400 DRIVER_MODULE(ofw_spibus, sifive_spi, ofw_spibus_driver, 0, 0); 401 MODULE_DEPEND(sifive_spi, ofw_spibus, 1, 1, 1); 402