mss-spi.c (12194B)
1/* 2 * Block model of SPI controller present in 3 * Microsemi's SmartFusion2 and SmartFusion SoCs. 4 * 5 * Copyright (C) 2017 Subbaraya Sundeep <sundeep.lkml@gmail.com> 6 * 7 * Permission is hereby granted, free of charge, to any person obtaining a copy 8 * of this software and associated documentation files (the "Software"), to deal 9 * in the Software without restriction, including without limitation the rights 10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 * copies of the Software, and to permit persons to whom the Software is 12 * furnished to do so, subject to the following conditions: 13 * 14 * The above copyright notice and this permission notice shall be included in 15 * all copies or substantial portions of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 20 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 * THE SOFTWARE. 24 */ 25 26#include "qemu/osdep.h" 27#include "hw/irq.h" 28#include "hw/ssi/mss-spi.h" 29#include "migration/vmstate.h" 30#include "qemu/log.h" 31#include "qemu/module.h" 32 33#ifndef MSS_SPI_ERR_DEBUG 34#define MSS_SPI_ERR_DEBUG 0 35#endif 36 37#define DB_PRINT_L(lvl, fmt, args...) do { \ 38 if (MSS_SPI_ERR_DEBUG >= lvl) { \ 39 qemu_log("%s: " fmt "\n", __func__, ## args); \ 40 } \ 41} while (0) 42 43#define DB_PRINT(fmt, args...) DB_PRINT_L(1, fmt, ## args) 44 45#define FIFO_CAPACITY 32 46 47#define R_SPI_CONTROL 0 48#define R_SPI_DFSIZE 1 49#define R_SPI_STATUS 2 50#define R_SPI_INTCLR 3 51#define R_SPI_RX 4 52#define R_SPI_TX 5 53#define R_SPI_CLKGEN 6 54#define R_SPI_SS 7 55#define R_SPI_MIS 8 56#define R_SPI_RIS 9 57 58#define S_TXDONE (1 << 0) 59#define S_RXRDY (1 << 1) 60#define S_RXCHOVRF (1 << 2) 61#define S_RXFIFOFUL (1 << 4) 62#define S_RXFIFOFULNXT (1 << 5) 63#define S_RXFIFOEMP (1 << 6) 64#define S_RXFIFOEMPNXT (1 << 7) 65#define S_TXFIFOFUL (1 << 8) 66#define S_TXFIFOFULNXT (1 << 9) 67#define S_TXFIFOEMP (1 << 10) 68#define S_TXFIFOEMPNXT (1 << 11) 69#define S_FRAMESTART (1 << 12) 70#define S_SSEL (1 << 13) 71#define S_ACTIVE (1 << 14) 72 73#define C_ENABLE (1 << 0) 74#define C_MODE (1 << 1) 75#define C_INTRXDATA (1 << 4) 76#define C_INTTXDATA (1 << 5) 77#define C_INTRXOVRFLO (1 << 6) 78#define C_SPS (1 << 26) 79#define C_BIGFIFO (1 << 29) 80#define C_RESET (1 << 31) 81 82#define FRAMESZ_MASK 0x3F 83#define FMCOUNT_MASK 0x00FFFF00 84#define FMCOUNT_SHIFT 8 85#define FRAMESZ_MAX 32 86 87static void txfifo_reset(MSSSpiState *s) 88{ 89 fifo32_reset(&s->tx_fifo); 90 91 s->regs[R_SPI_STATUS] &= ~S_TXFIFOFUL; 92 s->regs[R_SPI_STATUS] |= S_TXFIFOEMP; 93} 94 95static void rxfifo_reset(MSSSpiState *s) 96{ 97 fifo32_reset(&s->rx_fifo); 98 99 s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL; 100 s->regs[R_SPI_STATUS] |= S_RXFIFOEMP; 101} 102 103static void set_fifodepth(MSSSpiState *s) 104{ 105 unsigned int size = s->regs[R_SPI_DFSIZE] & FRAMESZ_MASK; 106 107 if (size <= 8) { 108 s->fifo_depth = 32; 109 } else if (size <= 16) { 110 s->fifo_depth = 16; 111 } else { 112 s->fifo_depth = 8; 113 } 114} 115 116static void update_mis(MSSSpiState *s) 117{ 118 uint32_t reg = s->regs[R_SPI_CONTROL]; 119 uint32_t tmp; 120 121 /* 122 * form the Control register interrupt enable bits 123 * same as RIS, MIS and Interrupt clear registers for simplicity 124 */ 125 tmp = ((reg & C_INTRXOVRFLO) >> 4) | ((reg & C_INTRXDATA) >> 3) | 126 ((reg & C_INTTXDATA) >> 5); 127 s->regs[R_SPI_MIS] |= tmp & s->regs[R_SPI_RIS]; 128} 129 130static void spi_update_irq(MSSSpiState *s) 131{ 132 int irq; 133 134 update_mis(s); 135 irq = !!(s->regs[R_SPI_MIS]); 136 137 qemu_set_irq(s->irq, irq); 138} 139 140static void mss_spi_reset(DeviceState *d) 141{ 142 MSSSpiState *s = MSS_SPI(d); 143 144 memset(s->regs, 0, sizeof s->regs); 145 s->regs[R_SPI_CONTROL] = 0x80000102; 146 s->regs[R_SPI_DFSIZE] = 0x4; 147 s->regs[R_SPI_STATUS] = S_SSEL | S_TXFIFOEMP | S_RXFIFOEMP; 148 s->regs[R_SPI_CLKGEN] = 0x7; 149 s->regs[R_SPI_RIS] = 0x0; 150 151 s->fifo_depth = 4; 152 s->frame_count = 1; 153 s->enabled = false; 154 155 rxfifo_reset(s); 156 txfifo_reset(s); 157} 158 159static uint64_t 160spi_read(void *opaque, hwaddr addr, unsigned int size) 161{ 162 MSSSpiState *s = opaque; 163 uint32_t ret = 0; 164 165 addr >>= 2; 166 switch (addr) { 167 case R_SPI_RX: 168 s->regs[R_SPI_STATUS] &= ~S_RXFIFOFUL; 169 s->regs[R_SPI_STATUS] &= ~S_RXCHOVRF; 170 if (fifo32_is_empty(&s->rx_fifo)) { 171 qemu_log_mask(LOG_GUEST_ERROR, 172 "%s: Reading empty RX_FIFO\n", 173 __func__); 174 } else { 175 ret = fifo32_pop(&s->rx_fifo); 176 } 177 if (fifo32_is_empty(&s->rx_fifo)) { 178 s->regs[R_SPI_STATUS] |= S_RXFIFOEMP; 179 } 180 break; 181 182 case R_SPI_MIS: 183 update_mis(s); 184 ret = s->regs[R_SPI_MIS]; 185 break; 186 187 default: 188 if (addr < ARRAY_SIZE(s->regs)) { 189 ret = s->regs[addr]; 190 } else { 191 qemu_log_mask(LOG_GUEST_ERROR, 192 "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, 193 addr * 4); 194 return ret; 195 } 196 break; 197 } 198 199 DB_PRINT("addr=0x%" HWADDR_PRIx " = 0x%" PRIx32, addr * 4, ret); 200 spi_update_irq(s); 201 return ret; 202} 203 204static void assert_cs(MSSSpiState *s) 205{ 206 qemu_set_irq(s->cs_line, 0); 207} 208 209static void deassert_cs(MSSSpiState *s) 210{ 211 qemu_set_irq(s->cs_line, 1); 212} 213 214static void spi_flush_txfifo(MSSSpiState *s) 215{ 216 uint32_t tx; 217 uint32_t rx; 218 bool sps = !!(s->regs[R_SPI_CONTROL] & C_SPS); 219 220 /* 221 * Chip Select(CS) is automatically controlled by this controller. 222 * If SPS bit is set in Control register then CS is asserted 223 * until all the frames set in frame count of Control register are 224 * transferred. If SPS is not set then CS pulses between frames. 225 * Note that Slave Select register specifies which of the CS line 226 * has to be controlled automatically by controller. Bits SS[7:1] are for 227 * masters in FPGA fabric since we model only Microcontroller subsystem 228 * of Smartfusion2 we control only one CS(SS[0]) line. 229 */ 230 while (!fifo32_is_empty(&s->tx_fifo) && s->frame_count) { 231 assert_cs(s); 232 233 s->regs[R_SPI_STATUS] &= ~(S_TXDONE | S_RXRDY); 234 235 tx = fifo32_pop(&s->tx_fifo); 236 DB_PRINT("data tx:0x%" PRIx32, tx); 237 rx = ssi_transfer(s->spi, tx); 238 DB_PRINT("data rx:0x%" PRIx32, rx); 239 240 if (fifo32_num_used(&s->rx_fifo) == s->fifo_depth) { 241 s->regs[R_SPI_STATUS] |= S_RXCHOVRF; 242 s->regs[R_SPI_RIS] |= S_RXCHOVRF; 243 } else { 244 fifo32_push(&s->rx_fifo, rx); 245 s->regs[R_SPI_STATUS] &= ~S_RXFIFOEMP; 246 if (fifo32_num_used(&s->rx_fifo) == (s->fifo_depth - 1)) { 247 s->regs[R_SPI_STATUS] |= S_RXFIFOFULNXT; 248 } else if (fifo32_num_used(&s->rx_fifo) == s->fifo_depth) { 249 s->regs[R_SPI_STATUS] |= S_RXFIFOFUL; 250 } 251 } 252 s->frame_count--; 253 if (!sps) { 254 deassert_cs(s); 255 } 256 } 257 258 if (!s->frame_count) { 259 s->frame_count = (s->regs[R_SPI_CONTROL] & FMCOUNT_MASK) >> 260 FMCOUNT_SHIFT; 261 deassert_cs(s); 262 s->regs[R_SPI_RIS] |= S_TXDONE | S_RXRDY; 263 s->regs[R_SPI_STATUS] |= S_TXDONE | S_RXRDY; 264 } 265} 266 267static void spi_write(void *opaque, hwaddr addr, 268 uint64_t val64, unsigned int size) 269{ 270 MSSSpiState *s = opaque; 271 uint32_t value = val64; 272 273 DB_PRINT("addr=0x%" HWADDR_PRIx " =0x%" PRIx32, addr, value); 274 addr >>= 2; 275 276 switch (addr) { 277 case R_SPI_TX: 278 /* adding to already full FIFO */ 279 if (fifo32_num_used(&s->tx_fifo) == s->fifo_depth) { 280 break; 281 } 282 s->regs[R_SPI_STATUS] &= ~S_TXFIFOEMP; 283 fifo32_push(&s->tx_fifo, value); 284 if (fifo32_num_used(&s->tx_fifo) == (s->fifo_depth - 1)) { 285 s->regs[R_SPI_STATUS] |= S_TXFIFOFULNXT; 286 } else if (fifo32_num_used(&s->tx_fifo) == s->fifo_depth) { 287 s->regs[R_SPI_STATUS] |= S_TXFIFOFUL; 288 } 289 if (s->enabled) { 290 spi_flush_txfifo(s); 291 } 292 break; 293 294 case R_SPI_CONTROL: 295 s->regs[R_SPI_CONTROL] = value; 296 if (value & C_BIGFIFO) { 297 set_fifodepth(s); 298 } else { 299 s->fifo_depth = 4; 300 } 301 s->enabled = value & C_ENABLE; 302 s->frame_count = (value & FMCOUNT_MASK) >> FMCOUNT_SHIFT; 303 if (value & C_RESET) { 304 mss_spi_reset(DEVICE(s)); 305 } 306 break; 307 308 case R_SPI_DFSIZE: 309 if (s->enabled) { 310 break; 311 } 312 /* 313 * [31:6] bits are reserved bits and for future use. 314 * [5:0] are for frame size. Only [5:0] bits are validated 315 * during write, [31:6] bits are untouched. 316 */ 317 if ((value & FRAMESZ_MASK) > FRAMESZ_MAX) { 318 qemu_log_mask(LOG_GUEST_ERROR, "%s: Incorrect size %u provided." 319 "Maximum frame size is %u\n", 320 __func__, value & FRAMESZ_MASK, FRAMESZ_MAX); 321 break; 322 } 323 s->regs[R_SPI_DFSIZE] = value; 324 break; 325 326 case R_SPI_INTCLR: 327 s->regs[R_SPI_INTCLR] = value; 328 if (value & S_TXDONE) { 329 s->regs[R_SPI_RIS] &= ~S_TXDONE; 330 } 331 if (value & S_RXRDY) { 332 s->regs[R_SPI_RIS] &= ~S_RXRDY; 333 } 334 if (value & S_RXCHOVRF) { 335 s->regs[R_SPI_RIS] &= ~S_RXCHOVRF; 336 } 337 break; 338 339 case R_SPI_MIS: 340 case R_SPI_STATUS: 341 case R_SPI_RIS: 342 qemu_log_mask(LOG_GUEST_ERROR, 343 "%s: Write to read only register 0x%" HWADDR_PRIx "\n", 344 __func__, addr * 4); 345 break; 346 347 default: 348 if (addr < ARRAY_SIZE(s->regs)) { 349 s->regs[addr] = value; 350 } else { 351 qemu_log_mask(LOG_GUEST_ERROR, 352 "%s: Bad offset 0x%" HWADDR_PRIx "\n", __func__, 353 addr * 4); 354 } 355 break; 356 } 357 358 spi_update_irq(s); 359} 360 361static const MemoryRegionOps spi_ops = { 362 .read = spi_read, 363 .write = spi_write, 364 .endianness = DEVICE_NATIVE_ENDIAN, 365 .valid = { 366 .min_access_size = 1, 367 .max_access_size = 4 368 } 369}; 370 371static void mss_spi_realize(DeviceState *dev, Error **errp) 372{ 373 MSSSpiState *s = MSS_SPI(dev); 374 SysBusDevice *sbd = SYS_BUS_DEVICE(dev); 375 376 s->spi = ssi_create_bus(dev, "spi"); 377 378 sysbus_init_irq(sbd, &s->irq); 379 sysbus_init_irq(sbd, &s->cs_line); 380 381 memory_region_init_io(&s->mmio, OBJECT(s), &spi_ops, s, 382 TYPE_MSS_SPI, R_SPI_MAX * 4); 383 sysbus_init_mmio(sbd, &s->mmio); 384 385 fifo32_create(&s->tx_fifo, FIFO_CAPACITY); 386 fifo32_create(&s->rx_fifo, FIFO_CAPACITY); 387} 388 389static const VMStateDescription vmstate_mss_spi = { 390 .name = TYPE_MSS_SPI, 391 .version_id = 1, 392 .minimum_version_id = 1, 393 .fields = (VMStateField[]) { 394 VMSTATE_FIFO32(tx_fifo, MSSSpiState), 395 VMSTATE_FIFO32(rx_fifo, MSSSpiState), 396 VMSTATE_UINT32_ARRAY(regs, MSSSpiState, R_SPI_MAX), 397 VMSTATE_END_OF_LIST() 398 } 399}; 400 401static void mss_spi_class_init(ObjectClass *klass, void *data) 402{ 403 DeviceClass *dc = DEVICE_CLASS(klass); 404 405 dc->realize = mss_spi_realize; 406 dc->reset = mss_spi_reset; 407 dc->vmsd = &vmstate_mss_spi; 408} 409 410static const TypeInfo mss_spi_info = { 411 .name = TYPE_MSS_SPI, 412 .parent = TYPE_SYS_BUS_DEVICE, 413 .instance_size = sizeof(MSSSpiState), 414 .class_init = mss_spi_class_init, 415}; 416 417static void mss_spi_register_types(void) 418{ 419 type_register_static(&mss_spi_info); 420} 421 422type_init(mss_spi_register_types)