/** * @file sdrv_xspi_slv.c * @brief sdrv_xspi_slv driver * * @copyright Copyright (c) 2021 Semidrive Semiconductor. * All rights reserved. */ #include #include #include #include #include #include "sdrv_xspi_slv.h" #include "regs_base.h" #include "sdrv_xspi_slv_reg.h" #include "udelay/udelay.h" status_t sdrv_xspi_slv_init(struct sdrv_xspi_slv *slave, const struct sdrv_xspi_slv_conf *conf) { ASSERT(slave && conf); memset(slave, 0, sizeof(*slave)); slave->base = conf->base; slave->irq = conf->irq; sdrv_xspi_slv_set_en(slave->base, 0); sdrv_xspi_slv_set_crc_en(slave->base, !conf->crc_dis); sdrv_xspi_slv_set_bit_endian(slave->base, conf->bit_endian); sdrv_xspi_slv_set_tx_mode(slave->base, conf->tx_mode); sdrv_xspi_slv_set_mode(slave->base, conf->mode); sdrv_xspi_slv_set_rate(slave->base, conf->is_ddr); sdrv_xspi_slv_set_line(slave->base, conf->line); sdrv_xspi_slv_set_timeout_time(slave->base, 20000); sdrv_xspi_slv_set_timeout_en(slave->base, 1); sdrv_xspi_slv_set_cmd_write_trigger(slave->base, conf->cmd_wr_trg); sdrv_xspi_slv_set_cmd_read_trigger(slave->base, conf->cmd_rd_trg); sdrv_xspi_slv_set_cmd_write_packet0(slave->base, conf->cmd_wr_packet0); sdrv_xspi_slv_set_cmd_write_packet1(slave->base, conf->cmd_wr_packet1); sdrv_xspi_slv_set_cmd_write_payload(slave->base, conf->cmd_wr_payload); sdrv_xspi_slv_set_cmd_write_wdata(slave->base, conf->cmd_wr_wdata); sdrv_xspi_slv_set_cmd_write_status(slave->base, conf->cmd_wr_st); sdrv_xspi_slv_set_cmd_read_id(slave->base, conf->cmd_rd_id); sdrv_xspi_slv_set_cmd_read_status(slave->base, conf->cmd_rd_st); sdrv_xspi_slv_set_cmd_read_rdata(slave->base, conf->cmd_rd_rdata); sdrv_xspi_slv_set_cmd_read_rdata_crc(slave->base, conf->cmd_rd_rdata_crc); return SDRV_STATUS_OK; } status_t sdrv_xspi_slv_clr_status(struct sdrv_xspi_slv *slave) { sdrv_xspi_slv_set_slv_status_update(slave->base, 0xe0u); sdrv_xspi_slv_set_pad_crcb_mask(slave->base, 0x7cu); udelay(1); uint32_t val = sdrv_xspi_slv_get_slv_status(slave->base); if (val & 0x1f00u) { ssdk_printf(0, "update xspi slv status = 0x%x fail \r\n", val); return SSDRV_STATUS_GROUP_XSPI_SLAVER_GET_STATUS_ERR; } sdrv_xspi_slv_set_pad_crcb_mask(slave->base, 0x0u); return SDRV_STATUS_OK; } status_t sdrv_xspi_slv_enable(struct sdrv_xspi_slv *slave) { ASSERT(slave); sdrv_xspi_slv_soft_reset(slave->base); sdrv_xspi_slv_set_en(slave->base, 1); return SDRV_STATUS_OK; } status_t sdrv_xspi_slv_disable(struct sdrv_xspi_slv *slave) { ASSERT(slave); sdrv_xspi_slv_set_en(slave->base, 0); return SDRV_STATUS_OK; } status_t sdrv_xspi_slv_set_attr(struct sdrv_xspi_slv *slave, enum sdrv_xspi_slv_ioctl_flag flag, const void *buf) { ASSERT(slave && flag < XSPI_SLV_FLAG_MAX && buf); const struct sdrv_xspi_slv_sclk_idle_time_conf *idle_time_conf; const struct sdrv_xspi_slv_debounce_ctrl_conf *debounce_conf; const struct sdrv_xspi_slv_timeout_mon_ctrl_conf *timeout_conf; const struct sdrv_xspi_slv_aid_conf *aid_conf; const struct sdrv_xspi_slv_acache_conf *acache_conf; const struct sdrv_xspi_slv_aprot_conf *aprot_conf; const struct sdrv_xspi_slv_mon_conf *mon_conf; const struct sdrv_xspi_slv_region_map_conf *map_conf; const struct sdrv_xspi_slv_dummy_cycle_conf *dummy_cycle_conf; sdrv_xspi_slv_set_en(slave->base, 0); switch (flag) { case XSPI_SLV_FLAG_EN: sdrv_xspi_slv_set_en(slave->base, *(bool *)buf); break; case XSPI_SLV_FLAG_CRC_EN: sdrv_xspi_slv_set_crc_en(slave->base, *(bool *)buf); break; case XSPI_SLV_FLAG_BIT_ENDIAN: sdrv_xspi_slv_set_bit_endian(slave->base, *(bool *)buf); break; case XSPI_SLV_FLAG_PAD_RESET_MASK: sdrv_xspi_slv_set_pad_reset_mask(slave->base, *(bool *)buf); break; case XSPI_SLV_FLAG_WR_CHK_EN: sdrv_xspi_slv_set_write_chk_en(slave->base, *(bool *)buf); break; case XSPI_SLV_FLAG_TX_MODE: sdrv_xspi_slv_set_tx_mode(slave->base, *(enum sdrv_xspi_slv_tx_mode *)buf); break; case XSPI_SLV_FLAG_AXI_WR_EN: sdrv_xspi_slv_set_write_en(slave->base, *(bool *)buf); break; case XSPI_SLV_FLAG_AXI_RD_EN: sdrv_xspi_slv_set_read_en(slave->base, *(bool *)buf); break; case XSPI_SLV_FLAG_MODE: sdrv_xspi_slv_set_mode(slave->base, *(enum sdrv_xspi_slv_mode *)buf); break; case XSPI_SLV_FLAG_SCLK_IDLE_TIME: idle_time_conf = buf; sdrv_xspi_slv_set_sclk_idle_time_en(slave->base, idle_time_conf->enable); sdrv_xspi_slv_set_sclk_idle_time(slave->base, idle_time_conf->idle_time); break; case XSPI_SLV_FLAG_RATE: sdrv_xspi_slv_set_rate(slave->base, *(bool *)buf); break; case XSPI_SLV_FLAG_LINE: sdrv_xspi_slv_set_line(slave->base, *(enum sdrv_xspi_slv_line *)buf); break; case XSPI_SLV_FLAG_DEBOUNCE_CTRL: debounce_conf = buf; sdrv_xspi_slv_set_debounce_en(slave->base, debounce_conf->enable); sdrv_xspi_slv_set_debounce_time(slave->base, debounce_conf->time); break; case XSPI_SLV_FLAG_WR_DUMMY_CYCLE: dummy_cycle_conf = buf; sdrv_xspi_slv_set_dummy_cycle(slave->base, dummy_cycle_conf->dummy_val); break; case XSPI_SLV_FLAG_TIMEOUT_CTRL: timeout_conf = buf; sdrv_xspi_slv_set_timeout_en(slave->base, timeout_conf->enable); sdrv_xspi_slv_set_timeout_time(slave->base, timeout_conf->time); break; case XSPI_SLV_FLAG_ST_ACCESS: sdrv_xspi_slv_set_status_access_en(slave->base, *(uint16_t *)buf); break; case XSPI_SLV_FLAG_ID0: sdrv_xspi_slv_set_id0(slave->base, *(uint32_t *)buf); break; case XSPI_SLV_FLAG_ID1: sdrv_xspi_slv_set_id1(slave->base, *(uint32_t *)buf); break; case XSPI_SLV_FLAG_PAD_INTB_MASK: sdrv_xspi_slv_set_pad_intb_mask(slave->base, *(uint8_t *)buf); break; case XSPI_SLV_FLAG_PAD_CRCB_MASK: sdrv_xspi_slv_set_pad_crcb_mask(slave->base, *(uint8_t *)buf); break; case XSPI_SLV_FLAG_INT_MASK: sdrv_xspi_slv_set_int_mask(slave->base, *(uint32_t *)buf); break; case XSPI_SLV_FLAG_ST_UPDATE: sdrv_xspi_slv_set_slv_status_update(slave->base, *(uint16_t *)buf); break; case XSPI_SLV_FLAG_CMD_WR_TRG: sdrv_xspi_slv_set_cmd_write_trigger(slave->base, *(uint8_t *)buf); break; case XSPI_SLV_FLAG_CMD_RD_TRG: sdrv_xspi_slv_set_cmd_read_trigger(slave->base, *(uint8_t *)buf); break; case XSPI_SLV_FLAG_CMD_WR_PACKET0: sdrv_xspi_slv_set_cmd_write_packet0(slave->base, *(uint8_t *)buf); break; case XSPI_SLV_FLAG_CMD_WR_PACKET1: sdrv_xspi_slv_set_cmd_write_packet1(slave->base, *(uint8_t *)buf); break; case XSPI_SLV_FLAG_CMD_WR_PAYLOAD: sdrv_xspi_slv_set_cmd_write_payload(slave->base, *(uint8_t *)buf); break; case XSPI_SLV_FLAG_CMD_WR_WDATA: sdrv_xspi_slv_set_cmd_write_wdata(slave->base, *(uint8_t *)buf); break; case XSPI_SLV_FLAG_CMD_WR_ST: sdrv_xspi_slv_set_cmd_write_status(slave->base, *(uint8_t *)buf); break; case XSPI_SLV_FLAG_CMD_RD_ID: sdrv_xspi_slv_set_cmd_read_id(slave->base, *(uint8_t *)buf); break; case XSPI_SLV_FLAG_CMD_RD_ST: sdrv_xspi_slv_set_cmd_read_status(slave->base, *(uint8_t *)buf); break; case XSPI_SLV_FLAG_CMD_RD_RDATA: sdrv_xspi_slv_set_cmd_read_rdata(slave->base, *(uint8_t *)buf); break; case XSPI_SLV_FLAG_CMD_RD_RDATA_CRC: sdrv_xspi_slv_set_cmd_read_rdata_crc(slave->base, *(uint8_t *)buf); break; case XSPI_SLV_FLAG_ARID_OVERRIDE: aid_conf = buf; sdrv_xspi_slv_set_arid_override_en(slave->base, aid_conf->enable); sdrv_xspi_slv_set_override_arid(slave->base, aid_conf->aid); break; case XSPI_SLV_FLAG_ARCACHE_OVERRIDE: acache_conf = buf; sdrv_xspi_slv_set_arcache_override_en(slave->base, acache_conf->enable); sdrv_xspi_slv_set_override_arcache(slave->base, acache_conf->acache); break; case XSPI_SLV_FLAG_ARPROT_OVERRIDE: aprot_conf = buf; sdrv_xspi_slv_set_arprot_override_en(slave->base, aprot_conf->enable); sdrv_xspi_slv_set_override_arprot(slave->base, aprot_conf->aprot); break; case XSPI_SLV_FLAG_AWID_OVERRIDE: aid_conf = buf; sdrv_xspi_slv_set_awid_override_en(slave->base, aid_conf->enable); sdrv_xspi_slv_set_override_awid(slave->base, aid_conf->aid); break; case XSPI_SLV_FLAG_AWCACHE_OVERRIDE: acache_conf = buf; sdrv_xspi_slv_set_awcache_override_en(slave->base, acache_conf->enable); sdrv_xspi_slv_set_override_awcache(slave->base, acache_conf->acache); break; case XSPI_SLV_FLAG_AWPROT_OVERRIDE: aprot_conf = buf; sdrv_xspi_slv_set_awprot_override_en(slave->base, aprot_conf->enable); sdrv_xspi_slv_set_override_awprot(slave->base, aprot_conf->aprot); break; case XSPI_SLV_FLAG_REGION_MAP: map_conf = buf; sdrv_xspi_slv_set_region_map_en(slave->base, map_conf->enable, map_conf->id); sdrv_xspi_slv_set_region_map_offset(slave->base, map_conf->offset_addr, map_conf->id); sdrv_xspi_slv_set_region_map_begin_addr(slave->base, map_conf->begin_addr, map_conf->id); sdrv_xspi_slv_set_region_map_end_addr(slave->base, map_conf->end_addr, map_conf->id); break; case XSPI_SLV_FLAG_RD_MON: mon_conf = buf; sdrv_xspi_slv_set_read_ctrl_addr_en(slave->base, mon_conf->addr_en); sdrv_xspi_slv_set_read_mon_perm_addr_en(slave->base, mon_conf->addr_en, mon_conf->id); sdrv_xspi_slv_set_r_mon_begin_addr(slave->base, mon_conf->begin_addr, mon_conf->id); sdrv_xspi_slv_set_r_mon_end_addr(slave->base, mon_conf->end_addr, mon_conf->id); sdrv_xspi_slv_set_read_mon_perm_addr_lock(slave->base, mon_conf->addr_lock, mon_conf->id); break; case XSPI_SLV_FLAG_WR_MON: mon_conf = buf; sdrv_xspi_slv_set_write_ctrl_addr_en(slave->base, mon_conf->addr_en); sdrv_xspi_slv_set_write_mon_perm_addr_en(slave->base, mon_conf->addr_en, mon_conf->id); sdrv_xspi_slv_set_w_mon_begin_addr(slave->base, mon_conf->begin_addr, mon_conf->id); sdrv_xspi_slv_set_w_mon_end_addr(slave->base, mon_conf->end_addr, mon_conf->id); sdrv_xspi_slv_set_write_mon_perm_addr_lock(slave->base, mon_conf->addr_lock, mon_conf->id); break; default: ssdk_printf(SSDK_EMERG, "set flag error: %d\r\n", flag); return SSDRV_STATUS_GROUP_XSPI_SLAVER_GET_FLAG_ATTR_ERR; } return SDRV_STATUS_OK; } status_t sdrv_xspi_slv_get_attr(struct sdrv_xspi_slv *slave, enum sdrv_xspi_slv_ioctl_flag flag, void *buf) { ASSERT(slave && flag < XSPI_SLV_FLAG_MAX && buf); struct sdrv_xspi_slv_sclk_idle_time_conf *idle_time_conf; struct sdrv_xspi_slv_debounce_ctrl_conf *debounce_conf; struct sdrv_xspi_slv_timeout_mon_ctrl_conf *timeout_conf; struct sdrv_xspi_slv_aid_conf *aid_conf; struct sdrv_xspi_slv_acache_conf *acache_conf; struct sdrv_xspi_slv_aprot_conf *aprot_conf; struct sdrv_xspi_slv_mon_conf *mon_conf; struct sdrv_xspi_slv_region_map_conf *map_conf; switch (flag) { case XSPI_SLV_FLAG_EN: *(bool *)buf = sdrv_xspi_slv_get_en(slave->base); break; case XSPI_SLV_FLAG_CRC_EN: *(bool *)buf = sdrv_xspi_slv_get_crc_en(slave->base); break; case XSPI_SLV_FLAG_BIT_ENDIAN: *(bool *)buf = sdrv_xspi_slv_get_crc_en(slave->base); break; case XSPI_SLV_FLAG_PAD_RESET_MASK: *(bool *)buf = sdrv_xspi_slv_get_pad_reset_mask(slave->base); break; case XSPI_SLV_FLAG_WR_CHK_EN: *(bool *)buf = sdrv_xspi_slv_get_write_chk_en(slave->base); break; case XSPI_SLV_FLAG_TX_MODE: *(enum sdrv_xspi_slv_tx_mode *)buf = (enum sdrv_xspi_slv_tx_mode)sdrv_xspi_slv_get_tx_mode(slave->base); break; case XSPI_SLV_FLAG_AXI_WR_EN: *(bool *)buf = sdrv_xspi_slv_get_write_en(slave->base); break; case XSPI_SLV_FLAG_AXI_RD_EN: *(bool *)buf = sdrv_xspi_slv_get_read_en(slave->base); break; case XSPI_SLV_FLAG_MODE: *(enum sdrv_xspi_slv_mode *)buf = (enum sdrv_xspi_slv_mode)sdrv_xspi_slv_get_mode(slave->base); break; case XSPI_SLV_FLAG_SCLK_IDLE_TIME: idle_time_conf = buf; idle_time_conf->enable = sdrv_xspi_slv_get_sclk_idle_time_en(slave->base); idle_time_conf->idle_time = sdrv_xspi_slv_get_sclk_idle_time(slave->base); break; case XSPI_SLV_FLAG_RATE: *(bool *)buf = sdrv_xspi_slv_get_rate(slave->base); break; case XSPI_SLV_FLAG_LINE: *(enum sdrv_xspi_slv_line *)buf = (enum sdrv_xspi_slv_line)sdrv_xspi_slv_get_line(slave->base); break; case XSPI_SLV_FLAG_DEBOUNCE_CTRL: debounce_conf = buf; debounce_conf->enable = sdrv_xspi_slv_get_debounce_en(slave->base); debounce_conf->time = sdrv_xspi_slv_get_debounce_time(slave->base); break; case XSPI_SLV_FLAG_TIMEOUT_CTRL: timeout_conf = buf; timeout_conf->enable = sdrv_xspi_slv_get_timeout_en(slave->base); timeout_conf->time = sdrv_xspi_slv_get_timeout_time(slave->base); break; case XSPI_SLV_FLAG_ST_ACCESS: *(uint16_t *)buf = sdrv_xspi_slv_get_status_access_en(slave->base); break; case XSPI_SLV_FLAG_ID0: *(uint32_t *)buf = sdrv_xspi_slv_get_id0(slave->base); break; case XSPI_SLV_FLAG_ID1: *(uint32_t *)buf = sdrv_xspi_slv_get_id1(slave->base); break; case XSPI_SLV_FLAG_PAD_INTB_MASK: *(uint8_t *)buf = sdrv_xspi_slv_get_pad_intb_mask(slave->base); break; case XSPI_SLV_FLAG_PAD_CRCB_MASK: *(uint8_t *)buf = sdrv_xspi_slv_get_pad_crcb_mask(slave->base); break; case XSPI_SLV_FLAG_INT_ST: *(uint32_t *)buf = sdrv_xspi_slv_get_int_st(slave->base); break; case XSPI_SLV_FLAG_INT_MASK: *(uint32_t *)buf = sdrv_xspi_slv_get_int_mask(slave->base); break; case XSPI_SLV_FLAG_ST: *(uint16_t *)buf = sdrv_xspi_slv_get_slv_status(slave->base); break; case XSPI_SLV_FLAG_ST_UPDATE: *(uint16_t *)buf = sdrv_xspi_slv_get_slv_status_update(slave->base); break; case XSPI_SLV_FLAG_CMD_WR_TRG: *(uint8_t *)buf = sdrv_xspi_slv_get_cmd_write_trigger(slave->base); break; case XSPI_SLV_FLAG_CMD_RD_TRG: *(uint8_t *)buf = sdrv_xspi_slv_get_cmd_read_trigger(slave->base); break; case XSPI_SLV_FLAG_CMD_WR_PACKET0: *(uint8_t *)buf = sdrv_xspi_slv_get_cmd_write_packet0(slave->base); break; case XSPI_SLV_FLAG_CMD_WR_PACKET1: *(uint8_t *)buf = sdrv_xspi_slv_get_cmd_write_packet1(slave->base); break; case XSPI_SLV_FLAG_CMD_WR_PAYLOAD: *(uint8_t *)buf = sdrv_xspi_slv_get_cmd_write_payload(slave->base); break; case XSPI_SLV_FLAG_CMD_WR_WDATA: *(uint8_t *)buf = sdrv_xspi_slv_get_cmd_write_wdata(slave->base); break; case XSPI_SLV_FLAG_CMD_WR_ST: *(uint8_t *)buf = sdrv_xspi_slv_get_cmd_write_status(slave->base); break; case XSPI_SLV_FLAG_CMD_RD_ID: *(uint8_t *)buf = sdrv_xspi_slv_get_cmd_read_id(slave->base); break; case XSPI_SLV_FLAG_CMD_RD_ST: *(uint8_t *)buf = sdrv_xspi_slv_get_cmd_read_status(slave->base); break; case XSPI_SLV_FLAG_CMD_RD_RDATA: *(uint8_t *)buf = sdrv_xspi_slv_get_cmd_read_rdata(slave->base); break; case XSPI_SLV_FLAG_CMD_RD_RDATA_CRC: *(uint8_t *)buf = sdrv_xspi_slv_get_cmd_read_rdata_crc(slave->base); break; case XSPI_SLV_FLAG_ARID_OVERRIDE: aid_conf = buf; aid_conf->enable = sdrv_xspi_slv_get_arid_override_en(slave->base); aid_conf->aid = sdrv_xspi_slv_get_override_arid(slave->base); break; case XSPI_SLV_FLAG_ARCACHE_OVERRIDE: acache_conf = buf; acache_conf->enable = sdrv_xspi_slv_get_arcache_override_en(slave->base); acache_conf->acache = sdrv_xspi_slv_get_override_arcache(slave->base); break; case XSPI_SLV_FLAG_ARPROT_OVERRIDE: aprot_conf = buf; sdrv_xspi_slv_set_arprot_override_en(slave->base, aprot_conf->enable); sdrv_xspi_slv_set_override_arprot(slave->base, aprot_conf->aprot); break; case XSPI_SLV_FLAG_AWID_OVERRIDE: aid_conf = buf; aid_conf->enable = sdrv_xspi_slv_get_awid_override_en(slave->base); aid_conf->aid = sdrv_xspi_slv_get_override_awid(slave->base); break; case XSPI_SLV_FLAG_AWCACHE_OVERRIDE: acache_conf = buf; acache_conf->enable = sdrv_xspi_slv_get_awcache_override_en(slave->base); acache_conf->acache = sdrv_xspi_slv_get_override_awcache(slave->base); break; case XSPI_SLV_FLAG_AWPROT_OVERRIDE: aprot_conf = buf; aprot_conf->enable = sdrv_xspi_slv_get_awprot_override_en(slave->base); aprot_conf->aprot = sdrv_xspi_slv_get_override_awprot(slave->base); break; case XSPI_SLV_FLAG_REGION_MAP: map_conf = buf; map_conf->enable = sdrv_xspi_slv_get_region_map_en(slave->base, map_conf->id); map_conf->offset_addr = sdrv_xspi_slv_get_region_map_addr(slave->base, map_conf->id); map_conf->begin_addr = sdrv_xspi_slv_get_region_map_begin_addr(slave->base, map_conf->id); map_conf->end_addr = sdrv_xspi_slv_get_region_map_end_addr(slave->base, map_conf->id); case XSPI_SLV_FLAG_RD_MON: mon_conf = buf; mon_conf->addr_en = sdrv_xspi_slv_get_read_ctrl_addr_en(slave->base); mon_conf->addr_en = sdrv_xspi_slv_get_read_mon_perm_addr_en(slave->base, mon_conf->id); mon_conf->begin_addr = sdrv_xspi_slv_get_r_mon_begin_addr(slave->base, mon_conf->id); mon_conf->end_addr = sdrv_xspi_slv_get_r_mon_end_addr(slave->base, mon_conf->id); mon_conf->addr_lock = sdrv_xspi_slv_get_read_mon_perm_addr_lock(slave->base, mon_conf->id); break; case XSPI_SLV_FLAG_WR_MON: mon_conf = buf; mon_conf->addr_en = sdrv_xspi_slv_get_write_ctrl_addr_en(slave->base); mon_conf->addr_en = sdrv_xspi_slv_get_write_mon_perm_addr_en(slave->base, mon_conf->id); mon_conf->begin_addr = sdrv_xspi_slv_get_w_mon_begin_addr(slave->base, mon_conf->id); mon_conf->end_addr = sdrv_xspi_slv_get_w_mon_end_addr(slave->base, mon_conf->id); mon_conf->addr_lock = sdrv_xspi_slv_get_write_mon_perm_addr_lock(slave->base, mon_conf->id); break; default: ssdk_printf(SSDK_EMERG, "set flag error: %d\r\n", flag); return SSDRV_STATUS_GROUP_XSPI_SLAVER_SET_FLAG_ATTR_ERR; } return SDRV_STATUS_OK; } status_t sdrv_xspi_slv_deinit(struct sdrv_xspi_slv *slave) { ASSERT(slave); return SDRV_STATUS_OK; }