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 
pnv_spi_xscom_write(QTestState * qts,const PnvChip * chip,uint32_t reg,uint64_t val)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 
pnv_spi_xscom_read(QTestState * qts,const PnvChip * chip,uint32_t reg)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 
spi_seeprom_transaction(QTestState * qts,const PnvChip * chip)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 
test_spi_seeprom(const void * data)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 
main(int argc,char ** argv)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