1 /*
2  * Copyright 2022 NXP
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/kernel.h>
8 #include <string.h>
9 #include <zephyr/drivers/mspi.h>
10 #include <zephyr/pm/device_runtime.h>
11 
12 #if DT_HAS_COMPAT_STATUS_OKAY(nxp_imx_flexspi)
13 /* Use memc API to get AHB base address for the device */
14 #include "memc_mcux_flexspi.h"
15 #define FLEXSPI_DEV DEVICE_DT_GET(DT_PARENT(DT_ALIAS(sram_ext)))
16 #define MEMC_DEV DT_ALIAS(sram_ext)
17 #define MEMC_PORT DT_REG_ADDR(DT_ALIAS(sram_ext))
18 #define MEMC_BASE ((void *)memc_flexspi_get_ahb_address(FLEXSPI_DEV, MEMC_PORT, 0))
19 #define MEMC_SIZE (DT_PROP(DT_ALIAS(sram_ext), size) / 8)
20 #elif DT_HAS_COMPAT_STATUS_OKAY(renesas_smartbond_nor_psram)
21 #include <da1469x_config.h>
22 #define MEMC_DEV DT_ALIAS(sram_ext)
23 #define MEMC_BASE ((void *)MCU_QSPIR_M_BASE)
24 #define MEMC_SIZE (DT_PROP(DT_ALIAS(sram_ext), dev_size) / 8)
25 #elif DT_HAS_COMPAT_STATUS_OKAY(ambiq_mspi_controller)
26 #define MEMC_DEV DT_ALIAS(psram0)
27 #define MSPI_BUS DT_BUS(MEMC_DEV)
28 #define mspi_get_xip_address(controller) DT_REG_ADDR_BY_IDX(controller, 1)
29 #define MEMC_BASE (void *)(mspi_get_xip_address(MSPI_BUS))
30 #define MEMC_SIZE (DT_PROP(MEMC_DEV, size) / 8)
31 #elif DT_HAS_COMPAT_STATUS_OKAY(st_stm32_fmc_sdram)
32 #define MEMC_DEV  DT_ALIAS(sram_ext)
33 #define MEMC_BASE DT_REG_ADDR(MEMC_DEV)
34 #define MEMC_SIZE DT_REG_SIZE(MEMC_DEV)
35 #elif DT_HAS_COMPAT_STATUS_OKAY(nxp_xspi_psram)
36 #define MEMC_DEV DT_ALIAS(sram_ext)
37 #define MSPI_BUS DT_BUS(MEMC_DEV)
38 #define MEMC_BASE DT_REG_ADDR_BY_IDX(MSPI_BUS, 1)
39 #define MEMC_SIZE (DT_PROP(MEMC_DEV, size) / 8)
40 #else
41 #error At least one driver should be selected!
42 #endif
43 
dump_memory(uint8_t * p,uint32_t size)44 void dump_memory(uint8_t *p, uint32_t size)
45 {
46 	uint32_t i, j;
47 
48 	for (i = 0, j = 0; j < (size / 16); i += 16, j++) {
49 		printk("%02x %02x %02x %02x %02x %02x %02x %02x ",
50 			p[i], p[i+1], p[i+2], p[i+3],
51 			p[i+4], p[i+5], p[i+6], p[i+7]);
52 		printk("%02x %02x %02x %02x %02x %02x %02x %02x\n",
53 			p[i+8], p[i+9], p[i+10], p[i+11],
54 			p[i+12], p[i+13], p[i+14], p[i+15]);
55 		/* Split dump at 256B boundaries */
56 		if (((i + 16) & 0xFF) == 0) {
57 			printk("\n");
58 		}
59 	}
60 	/* Dump any remaining data after 16 byte blocks */
61 	for (; i < size; i++) {
62 		printk("%02x ", p[i]);
63 	}
64 	printk("\n");
65 }
66 
67 #define BUF_SIZE 1024
68 
69 uint8_t memc_write_buffer[BUF_SIZE];
70 uint8_t memc_read_buffer[BUF_SIZE];
71 
main(void)72 int main(void)
73 {
74 	uint8_t *memc = (uint8_t *)MEMC_BASE;
75 	uint32_t i, j;
76 
77 	/* Initialize write buffer */
78 	for (i = 0; i < BUF_SIZE; i++) {
79 		memc_write_buffer[i] = (uint8_t)i;
80 	}
81 
82 	pm_device_runtime_get(DEVICE_DT_GET(MEMC_DEV));
83 
84 	printk("Writing to memory region with base %p, size 0x%0x\n\n",
85 		memc, MEMC_SIZE);
86 	/* Copy write buffer into memc region */
87 	for (i = 0, j = 0; j < (MEMC_SIZE / BUF_SIZE); i += BUF_SIZE, j++) {
88 		memcpy(memc + i, memc_write_buffer, BUF_SIZE);
89 	}
90 	/* Copy any remaining space bytewise */
91 	for (; i < MEMC_SIZE; i++) {
92 		memc[i] = memc_write_buffer[i];
93 	}
94 	/* Read from memc region into buffer */
95 	for (i = 0, j = 0; j < (MEMC_SIZE / BUF_SIZE); i += BUF_SIZE, j++) {
96 		memcpy(memc_read_buffer, memc + i, BUF_SIZE);
97 		/* Compare memory */
98 		if (memcmp(memc_read_buffer, memc_write_buffer, BUF_SIZE)) {
99 			printk("Error: read data differs in range [0x%x- 0x%x]\n",
100 				i, i + (BUF_SIZE - 1));
101 			dump_memory(memc_write_buffer, BUF_SIZE);
102 			dump_memory(memc_read_buffer, BUF_SIZE);
103 			return 0;
104 		}
105 		printk("Check (%i/%i) passed!\n", j, (MEMC_SIZE / BUF_SIZE) - 1);
106 	}
107 	/* Copy any remaining space bytewise */
108 	for (; i < MEMC_SIZE; i++) {
109 		memc_read_buffer[i] = memc[i];
110 		if (memc_write_buffer[i] != memc_read_buffer[i]) {
111 			printk("Error: read data differs at offset 0x%x\n", i);
112 			return 0;
113 		}
114 	}
115 	printk("First 1KB of Data in memory:\n");
116 	printk("===========================\n");
117 	dump_memory(memc, MIN(MEMC_SIZE, KB(1)));
118 	pm_device_runtime_put(DEVICE_DT_GET(MEMC_DEV));
119 	printk("Read data matches written data\n");
120 	return 0;
121 }
122