Lines Matching +full:auto +full:- +full:cmd12
27 #include "hw/qdev-properties.h"
29 #include "hw/sd/allwinner-sdhost.h"
34 #define TYPE_AW_SDHOST_BUS "allwinner-sdhost-bus"
60 REG_SD_A12A = 0x58, /* Auto command 12 argument */
80 REG_SD_SAMP_DL = 0x144, /* Sample Delay Control (sun50i-a64) */
189 if (s->global_ctl & SD_GCTL_INT_ENB) { in allwinner_sdhost_update_irq()
190 irq = s->irq_status & s->irq_mask; in allwinner_sdhost_update_irq()
196 qemu_set_irq(s->irq, !!irq); in allwinner_sdhost_update_irq()
202 if (s->transfer_cnt > bytes) { in allwinner_sdhost_update_transfer_cnt()
203 s->transfer_cnt -= bytes; in allwinner_sdhost_update_transfer_cnt()
205 s->transfer_cnt = 0; in allwinner_sdhost_update_transfer_cnt()
208 if (!s->transfer_cnt) { in allwinner_sdhost_update_transfer_cnt()
209 s->irq_status |= SD_RISR_DATA_COMPLETE; in allwinner_sdhost_update_transfer_cnt()
220 s->irq_status |= SD_RISR_CARD_INSERT; in allwinner_sdhost_set_inserted()
221 s->irq_status &= ~SD_RISR_CARD_REMOVE; in allwinner_sdhost_set_inserted()
222 s->status |= SD_STAR_CARD_PRESENT; in allwinner_sdhost_set_inserted()
224 s->irq_status &= ~SD_RISR_CARD_INSERT; in allwinner_sdhost_set_inserted()
225 s->irq_status |= SD_RISR_CARD_REMOVE; in allwinner_sdhost_set_inserted()
226 s->status &= ~SD_STAR_CARD_PRESENT; in allwinner_sdhost_set_inserted()
238 /* Auto clear load flag */ in allwinner_sdhost_send_command()
239 s->command &= ~SD_CMDR_LOAD; in allwinner_sdhost_send_command()
242 if (!(s->command & SD_CMDR_CLKCHANGE)) { in allwinner_sdhost_send_command()
245 request.cmd = s->command & SD_CMDR_CMDID_MASK; in allwinner_sdhost_send_command()
246 request.arg = s->command_arg; in allwinner_sdhost_send_command()
249 rlen = sdbus_do_command(&s->sdbus, &request, resp); in allwinner_sdhost_send_command()
255 if ((s->command & SD_CMDR_RESPONSE)) { in allwinner_sdhost_send_command()
256 if (rlen == 4 && !(s->command & SD_CMDR_RESPONSE_LONG)) { in allwinner_sdhost_send_command()
257 s->response[0] = ldl_be_p(&resp[0]); in allwinner_sdhost_send_command()
258 s->response[1] = s->response[2] = s->response[3] = 0; in allwinner_sdhost_send_command()
260 } else if (rlen == 16 && (s->command & SD_CMDR_RESPONSE_LONG)) { in allwinner_sdhost_send_command()
261 s->response[0] = ldl_be_p(&resp[12]); in allwinner_sdhost_send_command()
262 s->response[1] = ldl_be_p(&resp[8]); in allwinner_sdhost_send_command()
263 s->response[2] = ldl_be_p(&resp[4]); in allwinner_sdhost_send_command()
264 s->response[3] = ldl_be_p(&resp[0]); in allwinner_sdhost_send_command()
272 s->irq_status |= SD_RISR_CMD_COMPLETE; in allwinner_sdhost_send_command()
276 s->irq_status |= SD_RISR_NO_RESPONSE; in allwinner_sdhost_send_command()
282 * The stop command (CMD12) ensures the SD bus in allwinner_sdhost_auto_stop()
285 if ((s->command & SD_CMDR_AUTOSTOP) && (s->transfer_cnt == 0)) { in allwinner_sdhost_auto_stop()
287 uint32_t saved_cmd = s->command; in allwinner_sdhost_auto_stop()
288 uint32_t saved_arg = s->command_arg; in allwinner_sdhost_auto_stop()
290 /* Prepare stop command (CMD12) */ in allwinner_sdhost_auto_stop()
291 s->command &= ~SD_CMDR_CMDID_MASK; in allwinner_sdhost_auto_stop()
292 s->command |= 12; /* CMD12 */ in allwinner_sdhost_auto_stop()
293 s->command_arg = 0; in allwinner_sdhost_auto_stop()
299 s->command = saved_cmd; in allwinner_sdhost_auto_stop()
300 s->command_arg = saved_arg; in allwinner_sdhost_auto_stop()
303 s->irq_status |= SD_RISR_AUTOCMD_DONE; in allwinner_sdhost_auto_stop()
311 dma_memory_read(&s->dma_as, desc_addr, &desc_words, sizeof(desc_words), in read_descriptor()
313 desc->status = le32_to_cpu(desc_words[0]); in read_descriptor()
314 desc->size = le32_to_cpu(desc_words[1]); in read_descriptor()
315 desc->addr = le32_to_cpu(desc_words[2]); in read_descriptor()
316 desc->next = le32_to_cpu(desc_words[3]); in read_descriptor()
323 desc_words[0] = cpu_to_le32(desc->status); in write_descriptor()
324 desc_words[1] = cpu_to_le32(desc->size); in write_descriptor()
325 desc_words[2] = cpu_to_le32(desc->addr); in write_descriptor()
326 desc_words[3] = cpu_to_le32(desc->next); in write_descriptor()
327 dma_memory_write(&s->dma_as, desc_addr, &desc_words, sizeof(desc_words), in write_descriptor()
342 if (desc->size == 0) { in allwinner_sdhost_process_desc()
343 desc->size = klass->max_desc_size; in allwinner_sdhost_process_desc()
344 } else if (desc->size > klass->max_desc_size) { in allwinner_sdhost_process_desc()
346 " is out-of-bounds: %" PRIu32 " > %zu", in allwinner_sdhost_process_desc()
347 __func__, desc->size, klass->max_desc_size); in allwinner_sdhost_process_desc()
348 desc->size = klass->max_desc_size; in allwinner_sdhost_process_desc()
350 if (desc->size < num_bytes) { in allwinner_sdhost_process_desc()
351 num_bytes = desc->size; in allwinner_sdhost_process_desc()
354 trace_allwinner_sdhost_process_desc(desc_addr, desc->size, in allwinner_sdhost_process_desc()
359 uint32_t buf_bytes = num_bytes - num_done; in allwinner_sdhost_process_desc()
366 dma_memory_read(&s->dma_as, in allwinner_sdhost_process_desc()
367 (desc->addr & DESC_SIZE_MASK) + num_done, buf, in allwinner_sdhost_process_desc()
369 sdbus_write_data(&s->sdbus, buf, buf_bytes); in allwinner_sdhost_process_desc()
373 sdbus_read_data(&s->sdbus, buf, buf_bytes); in allwinner_sdhost_process_desc()
374 dma_memory_write(&s->dma_as, in allwinner_sdhost_process_desc()
375 (desc->addr & DESC_SIZE_MASK) + num_done, buf, in allwinner_sdhost_process_desc()
382 desc->status &= ~DESC_STATUS_HOLD; in allwinner_sdhost_process_desc()
391 hwaddr desc_addr = s->desc_base; in allwinner_sdhost_dma()
392 bool is_write = (s->command & SD_CMDR_WRITE); in allwinner_sdhost_dma()
396 if (s->byte_count == 0 || s->block_size == 0 || in allwinner_sdhost_dma()
397 !(s->global_ctl & SD_GCTL_DMA_ENB)) { in allwinner_sdhost_dma()
405 if (!is_write && !sdbus_data_ready(&s->sdbus)) { in allwinner_sdhost_dma()
410 while (s->byte_count > 0) { in allwinner_sdhost_dma()
412 is_write, s->byte_count); in allwinner_sdhost_dma()
415 if (bytes_done <= s->byte_count) { in allwinner_sdhost_dma()
416 s->byte_count -= bytes_done; in allwinner_sdhost_dma()
418 s->byte_count = 0; in allwinner_sdhost_dma()
429 s->irq_status |= SD_RISR_DATA_COMPLETE | SD_RISR_SDIO_INTR; in allwinner_sdhost_dma()
432 s->dmac_status |= SD_IDST_INT_SUMMARY; in allwinner_sdhost_dma()
435 s->dmac_status |= SD_IDST_TRANSMIT_IRQ; in allwinner_sdhost_dma()
437 s->dmac_status |= SD_IDST_RECEIVE_IRQ; in allwinner_sdhost_dma()
445 if (sdbus_data_ready(&s->sdbus)) { in allwinner_sdhost_fifo_read()
446 sdbus_read_data(&s->sdbus, &res, sizeof(uint32_t)); in allwinner_sdhost_fifo_read()
469 res = s->global_ctl; in allwinner_sdhost_read()
472 res = s->clock_ctl; in allwinner_sdhost_read()
475 res = s->timeout; in allwinner_sdhost_read()
478 res = s->bus_width; in allwinner_sdhost_read()
481 res = s->block_size; in allwinner_sdhost_read()
484 res = s->byte_count; in allwinner_sdhost_read()
487 res = s->command; in allwinner_sdhost_read()
490 res = s->command_arg; in allwinner_sdhost_read()
493 res = s->response[0]; in allwinner_sdhost_read()
496 res = s->response[1]; in allwinner_sdhost_read()
499 res = s->response[2]; in allwinner_sdhost_read()
502 res = s->response[3]; in allwinner_sdhost_read()
505 res = s->irq_mask; in allwinner_sdhost_read()
508 res = s->irq_status & s->irq_mask; in allwinner_sdhost_read()
511 res = s->irq_status; in allwinner_sdhost_read()
514 res = s->status; in allwinner_sdhost_read()
515 if (sdbus_data_ready(&s->sdbus)) { in allwinner_sdhost_read()
522 res = s->fifo_wlevel; in allwinner_sdhost_read()
525 res = s->fifo_func_sel; in allwinner_sdhost_read()
528 res = s->debug_enable; in allwinner_sdhost_read()
530 case REG_SD_A12A: /* Auto command 12 argument */ in allwinner_sdhost_read()
531 res = s->auto12_arg; in allwinner_sdhost_read()
534 res = s->newtiming_set; in allwinner_sdhost_read()
537 res = s->newtiming_debug; in allwinner_sdhost_read()
540 res = s->hardware_rst; in allwinner_sdhost_read()
543 res = s->dmac; in allwinner_sdhost_read()
546 res = s->desc_base; in allwinner_sdhost_read()
549 res = s->dmac_status; in allwinner_sdhost_read()
552 res = s->dmac_irq; in allwinner_sdhost_read()
555 if (sc->is_sun4i) { in allwinner_sdhost_read()
558 res = s->card_threshold; in allwinner_sdhost_read()
562 res = s->startbit_detect; in allwinner_sdhost_read()
565 res = s->response_crc; in allwinner_sdhost_read()
575 res = s->data_crc[((offset - REG_SD_DATA7_CRC) / sizeof(uint32_t))]; in allwinner_sdhost_read()
578 res = s->status_crc; in allwinner_sdhost_read()
584 if (sc->can_calibrate) { in allwinner_sdhost_read()
585 res = s->sample_delay; in allwinner_sdhost_read()
597 qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %" in allwinner_sdhost_read()
608 sdbus_write_data(&s->sdbus, &u32, sizeof(u32)); in allwinner_sdhost_fifo_write()
625 s->global_ctl = value; in allwinner_sdhost_write()
626 s->global_ctl &= ~(SD_GCTL_DMA_RST | SD_GCTL_FIFO_RST | in allwinner_sdhost_write()
631 s->clock_ctl = value; in allwinner_sdhost_write()
634 s->timeout = value; in allwinner_sdhost_write()
637 s->bus_width = value; in allwinner_sdhost_write()
640 s->block_size = value; in allwinner_sdhost_write()
643 s->byte_count = value; in allwinner_sdhost_write()
644 s->transfer_cnt = value; in allwinner_sdhost_write()
647 s->command = value; in allwinner_sdhost_write()
656 s->command_arg = value; in allwinner_sdhost_write()
659 s->response[0] = value; in allwinner_sdhost_write()
662 s->response[1] = value; in allwinner_sdhost_write()
665 s->response[2] = value; in allwinner_sdhost_write()
668 s->response[3] = value; in allwinner_sdhost_write()
671 s->irq_mask = value; in allwinner_sdhost_write()
676 s->irq_status &= ~value; in allwinner_sdhost_write()
680 s->status &= ~value; in allwinner_sdhost_write()
684 s->fifo_wlevel = value; in allwinner_sdhost_write()
687 s->fifo_func_sel = value; in allwinner_sdhost_write()
690 s->debug_enable = value; in allwinner_sdhost_write()
692 case REG_SD_A12A: /* Auto command 12 argument */ in allwinner_sdhost_write()
693 s->auto12_arg = value; in allwinner_sdhost_write()
696 s->newtiming_set = value; in allwinner_sdhost_write()
699 s->newtiming_debug = value; in allwinner_sdhost_write()
702 s->hardware_rst = value; in allwinner_sdhost_write()
705 s->dmac = value; in allwinner_sdhost_write()
709 s->desc_base = value; in allwinner_sdhost_write()
712 s->dmac_status &= (~SD_IDST_WR_MASK) | (~value & SD_IDST_WR_MASK); in allwinner_sdhost_write()
716 s->dmac_irq = value; in allwinner_sdhost_write()
720 if (sc->is_sun4i) { in allwinner_sdhost_write()
723 s->card_threshold = value; in allwinner_sdhost_write()
727 s->startbit_detect = value; in allwinner_sdhost_write()
744 if (sc->can_calibrate) { in allwinner_sdhost_write()
745 s->sample_delay = value; in allwinner_sdhost_write()
756 qemu_log_mask(LOG_GUEST_ERROR, "%s: out-of-bounds offset %" in allwinner_sdhost_write()
773 .name = "allwinner-sdhost",
812 DEFINE_PROP_LINK("dma-memory", AwSdHostState, dma_mr,
821 qbus_init(&s->sdbus, sizeof(s->sdbus), in allwinner_sdhost_init()
822 TYPE_AW_SDHOST_BUS, DEVICE(s), "sd-bus"); in allwinner_sdhost_init()
824 memory_region_init_io(&s->iomem, obj, &allwinner_sdhost_ops, s, in allwinner_sdhost_init()
826 sysbus_init_mmio(SYS_BUS_DEVICE(s), &s->iomem); in allwinner_sdhost_init()
827 sysbus_init_irq(SYS_BUS_DEVICE(s), &s->irq); in allwinner_sdhost_init()
834 if (!s->dma_mr) { in allwinner_sdhost_realize()
835 error_setg(errp, TYPE_AW_SDHOST " 'dma-memory' link not set"); in allwinner_sdhost_realize()
839 address_space_init(&s->dma_as, s->dma_mr, "sdhost-dma"); in allwinner_sdhost_realize()
847 s->global_ctl = REG_SD_GCTL_RST; in allwinner_sdhost_reset()
848 s->clock_ctl = REG_SD_CKCR_RST; in allwinner_sdhost_reset()
849 s->timeout = REG_SD_TMOR_RST; in allwinner_sdhost_reset()
850 s->bus_width = REG_SD_BWDR_RST; in allwinner_sdhost_reset()
851 s->block_size = REG_SD_BKSR_RST; in allwinner_sdhost_reset()
852 s->byte_count = REG_SD_BYCR_RST; in allwinner_sdhost_reset()
853 s->transfer_cnt = 0; in allwinner_sdhost_reset()
855 s->command = REG_SD_CMDR_RST; in allwinner_sdhost_reset()
856 s->command_arg = REG_SD_CAGR_RST; in allwinner_sdhost_reset()
858 for (int i = 0; i < ARRAY_SIZE(s->response); i++) { in allwinner_sdhost_reset()
859 s->response[i] = REG_SD_RESP_RST; in allwinner_sdhost_reset()
862 s->irq_mask = REG_SD_IMKR_RST; in allwinner_sdhost_reset()
863 s->irq_status = REG_SD_RISR_RST; in allwinner_sdhost_reset()
864 s->status = REG_SD_STAR_RST; in allwinner_sdhost_reset()
866 s->fifo_wlevel = REG_SD_FWLR_RST; in allwinner_sdhost_reset()
867 s->fifo_func_sel = REG_SD_FUNS_RST; in allwinner_sdhost_reset()
868 s->debug_enable = REG_SD_DBGC_RST; in allwinner_sdhost_reset()
869 s->auto12_arg = REG_SD_A12A_RST; in allwinner_sdhost_reset()
870 s->newtiming_set = REG_SD_NTSR_RST; in allwinner_sdhost_reset()
871 s->newtiming_debug = REG_SD_SDBG_RST; in allwinner_sdhost_reset()
872 s->hardware_rst = REG_SD_HWRST_RST; in allwinner_sdhost_reset()
873 s->dmac = REG_SD_DMAC_RST; in allwinner_sdhost_reset()
874 s->desc_base = REG_SD_DLBA_RST; in allwinner_sdhost_reset()
875 s->dmac_status = REG_SD_IDST_RST; in allwinner_sdhost_reset()
876 s->dmac_irq = REG_SD_IDIE_RST; in allwinner_sdhost_reset()
877 s->card_threshold = REG_SD_THLDC_RST; in allwinner_sdhost_reset()
878 s->startbit_detect = REG_SD_DSBD_RST; in allwinner_sdhost_reset()
879 s->response_crc = REG_SD_RES_CRC_RST; in allwinner_sdhost_reset()
881 for (int i = 0; i < ARRAY_SIZE(s->data_crc); i++) { in allwinner_sdhost_reset()
882 s->data_crc[i] = REG_SD_DATA_CRC_RST; in allwinner_sdhost_reset()
885 s->status_crc = REG_SD_CRC_STA_RST; in allwinner_sdhost_reset()
887 if (sc->can_calibrate) { in allwinner_sdhost_reset()
888 s->sample_delay = REG_SD_SAMPLE_DL_RST; in allwinner_sdhost_reset()
896 sbc->set_inserted = allwinner_sdhost_set_inserted; in allwinner_sdhost_bus_class_init()
904 dc->vmsd = &vmstate_allwinner_sdhost; in allwinner_sdhost_class_init()
905 dc->realize = allwinner_sdhost_realize; in allwinner_sdhost_class_init()
912 sc->max_desc_size = 8 * KiB; in allwinner_sdhost_sun4i_class_init()
913 sc->is_sun4i = true; in allwinner_sdhost_sun4i_class_init()
914 sc->can_calibrate = false; in allwinner_sdhost_sun4i_class_init()
920 sc->max_desc_size = 64 * KiB; in allwinner_sdhost_sun5i_class_init()
921 sc->is_sun4i = false; in allwinner_sdhost_sun5i_class_init()
922 sc->can_calibrate = false; in allwinner_sdhost_sun5i_class_init()
929 sc->max_desc_size = 64 * KiB; in allwinner_sdhost_sun50i_a64_class_init()
930 sc->is_sun4i = false; in allwinner_sdhost_sun50i_a64_class_init()
931 sc->can_calibrate = true; in allwinner_sdhost_sun50i_a64_class_init()
938 sc->max_desc_size = 8 * KiB; in allwinner_sdhost_sun50i_a64_emmc_class_init()
939 sc->is_sun4i = false; in allwinner_sdhost_sun50i_a64_emmc_class_init()
940 sc->can_calibrate = true; in allwinner_sdhost_sun50i_a64_emmc_class_init()