1*53307491SChalapathi V /* 2*53307491SChalapathi V * QTest testcase for PowerNV 10 Seeprom Communications 3*53307491SChalapathi V * 4*53307491SChalapathi V * Copyright (c) 2024, IBM Corporation. 5*53307491SChalapathi V * 6*53307491SChalapathi V * SPDX-License-Identifier: GPL-2.0-or-later 7*53307491SChalapathi V */ 8*53307491SChalapathi V #include <unistd.h> 9*53307491SChalapathi V #include "qemu/osdep.h" 10*53307491SChalapathi V #include "libqtest.h" 11*53307491SChalapathi V #include "qemu/bswap.h" 12*53307491SChalapathi V #include "hw/ssi/pnv_spi_regs.h" 13*53307491SChalapathi V #include "pnv-xscom.h" 14*53307491SChalapathi V 15*53307491SChalapathi V #define FLASH_SIZE (512 * 1024) 16*53307491SChalapathi V #define SPIC2_XSCOM_BASE 0xc0040 17*53307491SChalapathi V 18*53307491SChalapathi V /* To transmit READ opcode and address */ 19*53307491SChalapathi V #define READ_OP_TDR_DATA 0x0300010000000000 20*53307491SChalapathi V /* 21*53307491SChalapathi V * N1 shift - tx 4 bytes (transmit opcode and address) 22*53307491SChalapathi V * N2 shift - tx and rx 8 bytes. 23*53307491SChalapathi V */ 24*53307491SChalapathi V #define READ_OP_COUNTER_CONFIG 0x2040000000002b00 25*53307491SChalapathi V /* SEQ_OP_SELECT_RESPONDER - N1 Shift - N2 Shift * 5 - SEQ_OP_STOP */ 26*53307491SChalapathi V #define READ_OP_SEQUENCER 0x1130404040404010 27*53307491SChalapathi V 28*53307491SChalapathi V /* To transmit WREN(Set Write Enable Latch in status0 register) opcode */ 29*53307491SChalapathi V #define WRITE_OP_WREN 0x0600000000000000 30*53307491SChalapathi V /* To transmit WRITE opcode, address and data */ 31*53307491SChalapathi V #define WRITE_OP_TDR_DATA 0x0300010012345678 32*53307491SChalapathi V /* N1 shift - tx 8 bytes (transmit opcode, address and data) */ 33*53307491SChalapathi V #define WRITE_OP_COUNTER_CONFIG 0x4000000000002000 34*53307491SChalapathi V /* SEQ_OP_SELECT_RESPONDER - N1 Shift - SEQ_OP_STOP */ 35*53307491SChalapathi V #define WRITE_OP_SEQUENCER 0x1130100000000000 36*53307491SChalapathi V 37*53307491SChalapathi V static void pnv_spi_xscom_write(QTestState *qts, const PnvChip *chip, 38*53307491SChalapathi V uint32_t reg, uint64_t val) 39*53307491SChalapathi V { 40*53307491SChalapathi V uint32_t pcba = SPIC2_XSCOM_BASE + reg; 41*53307491SChalapathi V qtest_writeq(qts, pnv_xscom_addr(chip, pcba), val); 42*53307491SChalapathi V } 43*53307491SChalapathi V 44*53307491SChalapathi V static uint64_t pnv_spi_xscom_read(QTestState *qts, const PnvChip *chip, 45*53307491SChalapathi V uint32_t reg) 46*53307491SChalapathi V { 47*53307491SChalapathi V uint32_t pcba = SPIC2_XSCOM_BASE + reg; 48*53307491SChalapathi V return qtest_readq(qts, pnv_xscom_addr(chip, pcba)); 49*53307491SChalapathi V } 50*53307491SChalapathi V 51*53307491SChalapathi V static void spi_seeprom_transaction(QTestState *qts, const PnvChip *chip) 52*53307491SChalapathi V { 53*53307491SChalapathi V /* SPI transactions to SEEPROM to read from SEEPROM image */ 54*53307491SChalapathi V pnv_spi_xscom_write(qts, chip, SPI_CTR_CFG_REG, READ_OP_COUNTER_CONFIG); 55*53307491SChalapathi V pnv_spi_xscom_write(qts, chip, SPI_SEQ_OP_REG, READ_OP_SEQUENCER); 56*53307491SChalapathi V pnv_spi_xscom_write(qts, chip, SPI_XMIT_DATA_REG, READ_OP_TDR_DATA); 57*53307491SChalapathi V pnv_spi_xscom_write(qts, chip, SPI_XMIT_DATA_REG, 0); 58*53307491SChalapathi V /* Read 5*8 bytes from SEEPROM at 0x100 */ 59*53307491SChalapathi V uint64_t rdr_val = pnv_spi_xscom_read(qts, chip, SPI_RCV_DATA_REG); 60*53307491SChalapathi V g_test_message("RDR READ = 0x%" PRIx64, rdr_val); 61*53307491SChalapathi V rdr_val = pnv_spi_xscom_read(qts, chip, SPI_RCV_DATA_REG); 62*53307491SChalapathi V rdr_val = pnv_spi_xscom_read(qts, chip, SPI_RCV_DATA_REG); 63*53307491SChalapathi V rdr_val = pnv_spi_xscom_read(qts, chip, SPI_RCV_DATA_REG); 64*53307491SChalapathi V rdr_val = pnv_spi_xscom_read(qts, chip, SPI_RCV_DATA_REG); 65*53307491SChalapathi V g_test_message("RDR READ = 0x%" PRIx64, rdr_val); 66*53307491SChalapathi V 67*53307491SChalapathi V /* SPI transactions to SEEPROM to write to SEEPROM image */ 68*53307491SChalapathi V pnv_spi_xscom_write(qts, chip, SPI_CTR_CFG_REG, WRITE_OP_COUNTER_CONFIG); 69*53307491SChalapathi V /* Set Write Enable Latch bit of status0 register */ 70*53307491SChalapathi V pnv_spi_xscom_write(qts, chip, SPI_SEQ_OP_REG, WRITE_OP_SEQUENCER); 71*53307491SChalapathi V pnv_spi_xscom_write(qts, chip, SPI_XMIT_DATA_REG, WRITE_OP_WREN); 72*53307491SChalapathi V /* write 8 bytes to SEEPROM at 0x100 */ 73*53307491SChalapathi V pnv_spi_xscom_write(qts, chip, SPI_SEQ_OP_REG, WRITE_OP_SEQUENCER); 74*53307491SChalapathi V pnv_spi_xscom_write(qts, chip, SPI_XMIT_DATA_REG, WRITE_OP_TDR_DATA); 75*53307491SChalapathi V } 76*53307491SChalapathi V 77*53307491SChalapathi V static void test_spi_seeprom(const void *data) 78*53307491SChalapathi V { 79*53307491SChalapathi V const PnvChip *chip = data; 80*53307491SChalapathi V QTestState *qts = NULL; 81*53307491SChalapathi V g_autofree char *tmp_path = NULL; 82*53307491SChalapathi V int ret; 83*53307491SChalapathi V int fd; 84*53307491SChalapathi V 85*53307491SChalapathi V /* Create a temporary raw image */ 86*53307491SChalapathi V fd = g_file_open_tmp("qtest-seeprom-XXXXXX", &tmp_path, NULL); 87*53307491SChalapathi V g_assert(fd >= 0); 88*53307491SChalapathi V ret = ftruncate(fd, FLASH_SIZE); 89*53307491SChalapathi V g_assert(ret == 0); 90*53307491SChalapathi V close(fd); 91*53307491SChalapathi V 92*53307491SChalapathi V qts = qtest_initf("-machine powernv10 -smp 2,cores=2," 93*53307491SChalapathi V "threads=1 -accel tcg,thread=single -nographic " 94*53307491SChalapathi V "-blockdev node-name=pib_spic2,driver=file," 95*53307491SChalapathi V "filename=%s -device 25csm04,bus=pnv-spi-bus.2,cs=0," 96*53307491SChalapathi V "drive=pib_spic2", tmp_path); 97*53307491SChalapathi V spi_seeprom_transaction(qts, chip); 98*53307491SChalapathi V qtest_quit(qts); 99*53307491SChalapathi V unlink(tmp_path); 100*53307491SChalapathi V } 101*53307491SChalapathi V 102*53307491SChalapathi V int main(int argc, char **argv) 103*53307491SChalapathi V { 104*53307491SChalapathi V g_test_init(&argc, &argv, NULL); 105*53307491SChalapathi V char *tname = g_strdup_printf("pnv-xscom/spi-seeprom/%s", 106*53307491SChalapathi V pnv_chips[3].cpu_model); 107*53307491SChalapathi V qtest_add_data_func(tname, &pnv_chips[3], test_spi_seeprom); 108*53307491SChalapathi V g_free(tname); 109*53307491SChalapathi V return g_test_run(); 110*53307491SChalapathi V } 111