1 /*
2  * Copyright (c) 2022 Intel Corporation
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 #define DT_DRV_COMPAT cdns_qspi_nor
7 
8 #include "flash_cadence_qspi_nor_ll.h"
9 
10 #include <string.h>
11 
12 #include <zephyr/kernel.h>
13 #include <zephyr/device.h>
14 #include <zephyr/drivers/flash.h>
15 #include <zephyr/logging/log.h>
16 
17 LOG_MODULE_REGISTER(flash_cadence, CONFIG_FLASH_LOG_LEVEL);
18 
19 struct flash_cad_priv {
20 	DEVICE_MMIO_NAMED_RAM(qspi_reg);
21 	DEVICE_MMIO_NAMED_RAM(qspi_data);
22 	struct cad_qspi_params params;
23 };
24 
25 struct flash_cad_config {
26 	DEVICE_MMIO_NAMED_ROM(qspi_reg);
27 	DEVICE_MMIO_NAMED_ROM(qspi_data);
28 };
29 
30 static const struct flash_parameters flash_cad_parameters = {
31 	.write_block_size = QSPI_BYTES_PER_DEV,
32 	.erase_value = 0xff,
33 };
34 
35 #define DEV_DATA(dev)	((struct flash_cad_priv *)((dev)->data))
36 #define DEV_CFG(dev)	((struct flash_cad_config *)((dev)->config))
37 
flash_cad_read(const struct device * dev,off_t offset,void * data,size_t len)38 static int flash_cad_read(const struct device *dev, off_t offset,
39 				void *data, size_t len)
40 {
41 	struct flash_cad_priv *priv = dev->data;
42 	struct cad_qspi_params *cad_params = &priv->params;
43 	int rc;
44 
45 	if ((data == NULL) || (len == 0)) {
46 		LOG_ERR("Invalid input parameter for QSPI Read!");
47 		return -EINVAL;
48 	}
49 
50 	rc = cad_qspi_read(cad_params, data, (uint32_t)offset, len);
51 
52 	if (rc < 0) {
53 		LOG_ERR("Cadence QSPI Flash Read Failed");
54 		return rc;
55 	}
56 
57 	return 0;
58 }
59 
flash_cad_erase(const struct device * dev,off_t offset,size_t len)60 static int flash_cad_erase(const struct device *dev, off_t offset,
61 				size_t len)
62 {
63 	struct flash_cad_priv *priv = dev->data;
64 	struct cad_qspi_params *cad_params = &priv->params;
65 	int rc;
66 
67 	if (len == 0) {
68 		LOG_ERR("Invalid input parameter for QSPI Erase!");
69 		return -EINVAL;
70 	}
71 
72 	rc = cad_qspi_erase(cad_params, (uint32_t)offset, len);
73 
74 	if (rc < 0) {
75 		LOG_ERR("Cadence QSPI Flash Erase Failed!");
76 		return rc;
77 	}
78 
79 	return 0;
80 }
81 
flash_cad_write(const struct device * dev,off_t offset,const void * data,size_t len)82 static int flash_cad_write(const struct device *dev, off_t offset,
83 				const void *data, size_t len)
84 {
85 	struct flash_cad_priv *priv = dev->data;
86 	struct cad_qspi_params *cad_params = &priv->params;
87 	int rc;
88 
89 	if ((data == NULL) || (len == 0)) {
90 		LOG_ERR("Invalid input parameter for QSPI Write!");
91 		return -EINVAL;
92 	}
93 
94 	rc = cad_qspi_write(cad_params, (void *)data, (uint32_t)offset, len);
95 
96 	if (rc < 0) {
97 		LOG_ERR("Cadence QSPI Flash Write Failed!");
98 		return rc;
99 	}
100 
101 	return 0;
102 }
103 
104 static const struct flash_parameters *
flash_cad_get_parameters(const struct device * dev)105 flash_cad_get_parameters(const struct device *dev)
106 {
107 	ARG_UNUSED(dev);
108 
109 	return &flash_cad_parameters;
110 }
111 
112 static const struct flash_driver_api flash_cad_api = {
113 	.erase = flash_cad_erase,
114 	.write = flash_cad_write,
115 	.read = flash_cad_read,
116 	.get_parameters = flash_cad_get_parameters,
117 };
118 
flash_cad_init(const struct device * dev)119 static int flash_cad_init(const struct device *dev)
120 {
121 	struct flash_cad_priv *priv = dev->data;
122 	struct cad_qspi_params *cad_params = &priv->params;
123 	int rc;
124 
125 	DEVICE_MMIO_NAMED_MAP(dev, qspi_reg, K_MEM_CACHE_NONE);
126 	DEVICE_MMIO_NAMED_MAP(dev, qspi_data, K_MEM_CACHE_NONE);
127 
128 	cad_params->reg_base = DEVICE_MMIO_NAMED_GET(dev, qspi_reg);
129 	cad_params->data_base = DEVICE_MMIO_NAMED_GET(dev, qspi_data);
130 
131 	rc = cad_qspi_init(cad_params, QSPI_CONFIG_CPHA,
132 			QSPI_CONFIG_CPOL, QSPI_CONFIG_CSDA,
133 			QSPI_CONFIG_CSDADS, QSPI_CONFIG_CSEOT,
134 			QSPI_CONFIG_CSSOT, 0);
135 
136 	if (rc < 0) {
137 		LOG_ERR("Cadence QSPI Flash Init Failed");
138 		return rc;
139 	}
140 
141 	return 0;
142 }
143 
144 #define CREATE_FLASH_CADENCE_QSPI_DEVICE(inst)				\
145 	static struct flash_cad_priv flash_cad_priv_##inst = {		\
146 		.params = {						\
147 			.clk_rate = DT_INST_PROP(inst, clock_frequency),\
148 			.data_size = DT_INST_REG_SIZE_BY_IDX(inst, 1),  \
149 		},							\
150 	};								\
151 									\
152 	static struct flash_cad_config flash_cad_config_##inst = {	\
153 		DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(			\
154 				qspi_reg, DT_DRV_INST(inst)),		\
155 		DEVICE_MMIO_NAMED_ROM_INIT_BY_NAME(			\
156 				qspi_data, DT_DRV_INST(inst)),		\
157 	};								\
158 									\
159 	DEVICE_DT_INST_DEFINE(inst,					\
160 			flash_cad_init,					\
161 			NULL,						\
162 			&flash_cad_priv_##inst,				\
163 			&flash_cad_config_##inst,			\
164 			POST_KERNEL,					\
165 			CONFIG_KERNEL_INIT_PRIORITY_DEVICE,		\
166 			&flash_cad_api);
167 
168 DT_INST_FOREACH_STATUS_OKAY(CREATE_FLASH_CADENCE_QSPI_DEVICE)
169