1 /*
2  * Copyright (c) 2024 ITE Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #define DT_DRV_COMPAT ite_it8xxx2_sha_v2
8 
9 #include <zephyr/kernel.h>
10 #include <zephyr/crypto/crypto.h>
11 #include <zephyr/sys/byteorder.h>
12 #include <chip_chipregs.h>
13 #include <errno.h>
14 
15 #include <zephyr/logging/log.h>
16 LOG_MODULE_REGISTER(sha_it8xxx2, CONFIG_CRYPTO_LOG_LEVEL);
17 
18 BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) == 1,
19 	     "support only one sha compatible node");
20 
21 #define IT8XXX2_SHA_REGS_BASE DT_REG_ADDR(DT_NODELABEL(sha0))
22 
23 /* 0x00: SHA Control Register */
24 #define IT8XXX2_REG_SHACR        (0x00)
25 #define IT8XXX2_SEL1SHA1         BIT(6)
26 #define IT8XXX2_SELSHA2ALL       (BIT(5) | BIT(4))
27 #define IT8XXX2_SHAWB            BIT(2)
28 #define IT8XXX2_SHAINI           BIT(1)
29 #define IT8XXX2_SHAEXE           BIT(0)
30 /* 0x01: SHA Status Register */
31 #define IT8XXX2_REG_SHASR        (0x01)
32 #define IT8XXX2_SHAIE            BIT(3)
33 #define IT8XXX2_SHAIS            BIT(2)
34 #define IT8XXX2_SHABUSY          BIT(0)
35 /* 0x02: SHA Execution Counter Register */
36 #define IT8XXX2_REG_SHAECR       (0x02)
37 #define IT8XXX2_SHAEXEC_64Byte   0x0
38 #define IT8XXX2_SHAEXEC_512Byte  0x7
39 #define IT8XXX2_SHAEXEC_1KByte   0xf
40 /* 0x03: SHA DLM Base Address 0 Register */
41 #define IT8XXX2_REG_SHADBA0R     (0x03)
42 /* 0x04: SHA DLM Base Address 1 Register */
43 #define IT8XXX2_REG_SHADBA1R     (0x04)
44 
45 #define SHA_SHA256_HASH_LEN                32
46 #define SHA_SHA256_BLOCK_LEN               64
47 #define SHA_SHA256_SRAM_BUF                1024
48 #define SHA_SHA256_HASH_LEN_WORDS          (SHA_SHA256_HASH_LEN / sizeof(uint32_t))
49 #define SHA_SHA256_BLOCK_LEN_WORDS         (SHA_SHA256_BLOCK_LEN / sizeof(uint32_t))
50 #define SHA_SHA256_SRAM_BUF_WORDS          (SHA_SHA256_SRAM_BUF / sizeof(uint32_t))
51 #define SHA_SHA256_CALCULATE_TIMEOUT_US    150
52 #define SHA_SHA256_WRITE_BACK_TIMEOUT_US   45
53 #define SHA_SHA256_WAIT_NEXT_CLOCK_TIME_US 15
54 
55 /*
56  * This struct is used by the hardware and must be stored in RAM first 4k-byte
57  * and aligned on a 256-byte boundary.
58  */
59 struct chip_sha256_ctx {
60 	union {
61 		/* SHA data buffer */
62 		uint32_t w_sha[SHA_SHA256_SRAM_BUF_WORDS];
63 		uint8_t w_input[SHA_SHA256_SRAM_BUF];
64 	};
65 	/* H[0] ~ H[7] */
66 	uint32_t h[SHA_SHA256_HASH_LEN_WORDS];
67 	uint32_t sha_init;
68 	uint32_t w_input_index;
69 	uint32_t total_len;
70 } __aligned(256);
71 
72 Z_GENERIC_SECTION(.__sha256_ram_block) struct chip_sha256_ctx chip_ctx;
73 
it8xxx2_sha256_init(bool init_k)74 static void it8xxx2_sha256_init(bool init_k)
75 {
76 	chip_ctx.sha_init = init_k;
77 	chip_ctx.w_input_index = 0;
78 	chip_ctx.total_len = 0;
79 
80 	/* Set DLM address for input data */
81 	sys_write8(((uint32_t)&chip_ctx) & 0xc0,
82 			IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHADBA0R);
83 	sys_write8(((uint32_t)&chip_ctx) >> 8,
84 			IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHADBA1R);
85 }
86 
it8xxx2_sha256_module_calculation(void)87 static int it8xxx2_sha256_module_calculation(void)
88 {
89 	struct gctrl_it8xxx2_regs *const gctrl_regs = GCTRL_IT8XXX2_REGS_BASE;
90 	uint32_t key, count;
91 	uint8_t sha_ctrl;
92 	bool timeout = true;
93 
94 	sha_ctrl = sys_read8(IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHACR);
95 
96 	if (chip_ctx.sha_init) {
97 		sha_ctrl |= (IT8XXX2_SHAINI | IT8XXX2_SHAEXE);
98 		chip_ctx.sha_init = 0;
99 	} else {
100 		sha_ctrl |= IT8XXX2_SHAEXE;
101 	}
102 
103 	/*
104 	 * Global interrupt is disabled because the CPU cannot access memory
105 	 * via the DLM (Data Local Memory) bus while HW module is computing
106 	 * hash.
107 	 */
108 	key = irq_lock();
109 	/* Crypto use SRAM */
110 	gctrl_regs->GCTRL_PMER3 |= IT8XXX2_GCTRL_SRAM_CRYPTO_USED;
111 	sys_write8(sha_ctrl, IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHACR);
112 
113 	/*
114 	 * HW 64 bytes data calculation ~= 4us;
115 	 * HW 1024 bytes data calculation ~= 66us.
116 	 */
117 	for (count = 0; count <= (SHA_SHA256_CALCULATE_TIMEOUT_US /
118 	     SHA_SHA256_WAIT_NEXT_CLOCK_TIME_US); count++) {
119 		/* Delay 15us */
120 		gctrl_regs->GCTRL_WNCKR = IT8XXX2_GCTRL_WN65K;
121 
122 		if ((sys_read8(IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHASR) & IT8XXX2_SHAIS)) {
123 			timeout = 0;
124 			break;
125 		}
126 	}
127 
128 	sys_write8(IT8XXX2_SHAIS, IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHASR);
129 	/* CPU use SRAM */
130 	gctrl_regs->GCTRL_PMER3 &= ~IT8XXX2_GCTRL_SRAM_CRYPTO_USED;
131 	gctrl_regs->GCTRL_PMER3;
132 	irq_unlock(key);
133 
134 	if (timeout) {
135 		LOG_ERR("HW execute sha256 calculation timeout");
136 		it8xxx2_sha256_init(true);
137 
138 		return -ETIMEDOUT;
139 	}
140 
141 	chip_ctx.w_input_index = 0;
142 
143 	return 0;
144 }
145 
it8xxx2_hash_handler(struct hash_ctx * ctx,struct hash_pkt * pkt,bool finish)146 static int it8xxx2_hash_handler(struct hash_ctx *ctx, struct hash_pkt *pkt,
147 				bool finish)
148 {
149 	struct gctrl_it8xxx2_regs *const gctrl_regs = GCTRL_IT8XXX2_REGS_BASE;
150 	uint32_t rem_len = pkt->in_len;
151 	uint32_t in_buf_idx = 0;
152 	uint32_t i, key, count;
153 	uint8_t sha_ctrl;
154 	bool timeout = true;
155 	int ret;
156 
157 	while (rem_len) {
158 		/* Data length >= 1KB */
159 		if (rem_len >= SHA_SHA256_SRAM_BUF) {
160 			rem_len = rem_len - SHA_SHA256_SRAM_BUF;
161 
162 			for (i = 0; i < SHA_SHA256_SRAM_BUF; i++) {
163 				chip_ctx.w_input[chip_ctx.w_input_index++] =
164 								pkt->in_buf[in_buf_idx++];
165 			}
166 
167 			/* HW automatically load 1KB data from DLM */
168 			sys_write8(IT8XXX2_SHAEXEC_1KByte,
169 					IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHAECR);
170 			ret = it8xxx2_sha256_module_calculation();
171 
172 			if (ret) {
173 				return ret;
174 			}
175 		} else {
176 			/* 0 <= Data length < 1KB */
177 			while (rem_len) {
178 				rem_len--;
179 				chip_ctx.w_input[chip_ctx.w_input_index++] =
180 								pkt->in_buf[in_buf_idx++];
181 
182 				/*
183 				 * If fill full 64byte then execute HW calculation.
184 				 * If not, will execute in later finish block.
185 				 */
186 				if (chip_ctx.w_input_index >= SHA_SHA256_BLOCK_LEN) {
187 					/* HW automatically load 64Bytes data from DLM */
188 					sys_write8(IT8XXX2_SHAEXEC_64Byte,
189 							IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHAECR);
190 					ret = it8xxx2_sha256_module_calculation();
191 
192 					if (ret) {
193 						return ret;
194 					}
195 				}
196 			}
197 		}
198 	}
199 
200 	chip_ctx.total_len += pkt->in_len;
201 
202 	if (finish) {
203 		uint32_t *ob_ptr = (uint32_t *)pkt->out_buf;
204 
205 		/* Pre-processing (Padding) */
206 		memset(&chip_ctx.w_input[chip_ctx.w_input_index],
207 			0, SHA_SHA256_BLOCK_LEN - chip_ctx.w_input_index);
208 		chip_ctx.w_input[chip_ctx.w_input_index] = 0x80;
209 
210 		/*
211 		 * Handles the boundary case of rest data:
212 		 * Because the last eight bytes are bit length field of sha256 rule.
213 		 * If the data index >= 56, it needs to trigger HW to calculate,
214 		 * then fill 0 data and the last eight bytes bit length, and calculate again.
215 		 */
216 		if (chip_ctx.w_input_index >= 56) {
217 			/* HW automatically load 64Bytes data from DLM */
218 			sys_write8(IT8XXX2_SHAEXEC_64Byte,
219 					IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHAECR);
220 			ret = it8xxx2_sha256_module_calculation();
221 
222 			if (ret) {
223 				return ret;
224 			}
225 			memset(&chip_ctx.w_input[chip_ctx.w_input_index],
226 				0, SHA_SHA256_BLOCK_LEN - chip_ctx.w_input_index);
227 		}
228 
229 		/*
230 		 * Since input data (big-endian) are copied 1byte by 1byte to
231 		 * it8xxx2 memory (little-endian), so the bit length needs to
232 		 * be transformed into big-endian format and then write to memory.
233 		 */
234 		chip_ctx.w_sha[15] = sys_cpu_to_be32(chip_ctx.total_len * 8);
235 
236 		/* HW automatically load 64Bytes data from DLM */
237 		sys_write8(IT8XXX2_SHAEXEC_64Byte, IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHAECR);
238 		ret = it8xxx2_sha256_module_calculation();
239 
240 		if (ret) {
241 			return ret;
242 		}
243 
244 		/* HW write back the hash result to DLM */
245 		/* Set DLM address for input data */
246 		sys_write8(((uint32_t)&chip_ctx.h) & 0xc0,
247 				IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHADBA0R);
248 		sys_write8(((uint32_t)&chip_ctx.h) >> 8,
249 				IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHADBA1R);
250 
251 		key = irq_lock();
252 		/* Crypto use SRAM */
253 		gctrl_regs->GCTRL_PMER3 |= IT8XXX2_GCTRL_SRAM_CRYPTO_USED;
254 		sha_ctrl = sys_read8(IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHACR);
255 		sys_write8(sha_ctrl | IT8XXX2_SHAWB, IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHACR);
256 
257 		/* HW write back the hash result to DLM ~= 1us */
258 		for (count = 0; count <= (SHA_SHA256_WRITE_BACK_TIMEOUT_US /
259 		     SHA_SHA256_WAIT_NEXT_CLOCK_TIME_US); count++) {
260 			/* Delay 15us */
261 			gctrl_regs->GCTRL_WNCKR = IT8XXX2_GCTRL_WN65K;
262 
263 			if ((sys_read8(IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHASR)
264 			      & IT8XXX2_SHAIS)) {
265 				timeout = 0;
266 				break;
267 			}
268 		}
269 
270 		sys_write8(IT8XXX2_SHAIS, IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHASR);
271 		/* CPU use SRAM */
272 		gctrl_regs->GCTRL_PMER3 &= ~IT8XXX2_GCTRL_SRAM_CRYPTO_USED;
273 		gctrl_regs->GCTRL_PMER3;
274 		irq_unlock(key);
275 
276 		if (timeout) {
277 			LOG_ERR("HW write back hash timeout");
278 			it8xxx2_sha256_init(true);
279 
280 			return -ETIMEDOUT;
281 		}
282 
283 		for (i = 0; i < SHA_SHA256_HASH_LEN_WORDS; i++) {
284 			ob_ptr[i] = chip_ctx.h[i];
285 		}
286 
287 		it8xxx2_sha256_init(true);
288 	}
289 
290 	return 0;
291 }
292 
it8xxx2_hash_session_free(const struct device * dev,struct hash_ctx * ctx)293 static int it8xxx2_hash_session_free(const struct device *dev,
294 				struct hash_ctx *ctx)
295 {
296 	it8xxx2_sha256_init(true);
297 
298 	return 0;
299 }
300 
it8xxx2_query_hw_caps(const struct device * dev)301 static inline int it8xxx2_query_hw_caps(const struct device *dev)
302 {
303 	return (CAP_SEPARATE_IO_BUFS | CAP_SYNC_OPS);
304 }
305 
it8xxx2_hash_begin_session(const struct device * dev,struct hash_ctx * ctx,enum hash_algo algo)306 static int it8xxx2_hash_begin_session(const struct device *dev,
307 				struct hash_ctx *ctx, enum hash_algo algo)
308 {
309 	if (algo != CRYPTO_HASH_ALGO_SHA256) {
310 		LOG_ERR("Unsupported algorithm");
311 		return -EINVAL;
312 	}
313 
314 	if (ctx->flags & ~(it8xxx2_query_hw_caps(dev))) {
315 		LOG_ERR("Unsupported flag");
316 		return -EINVAL;
317 	}
318 
319 	it8xxx2_sha256_init(true);
320 	ctx->hash_hndlr = it8xxx2_hash_handler;
321 
322 	return 0;
323 }
324 
it8xxx2_sha_init(const struct device * dev)325 static int it8xxx2_sha_init(const struct device *dev)
326 {
327 	struct gctrl_it8xxx2_regs *const gctrl_regs = GCTRL_IT8XXX2_REGS_BASE;
328 
329 	/* CPU use SRAM */
330 	gctrl_regs->GCTRL_PMER3 &= ~IT8XXX2_GCTRL_SRAM_CRYPTO_USED;
331 	gctrl_regs->GCTRL_PMER3;
332 
333 	it8xxx2_sha256_init(true);
334 
335 	/* Select SHA-2 Family, SHA-256 */
336 	sys_write8(0, IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHACR);
337 	/* SHA interrupt disable */
338 	sys_write8(0, IT8XXX2_SHA_REGS_BASE + IT8XXX2_REG_SHASR);
339 
340 	return 0;
341 }
342 
343 static DEVICE_API(crypto, it8xxx2_crypto_api) = {
344 	.hash_begin_session = it8xxx2_hash_begin_session,
345 	.hash_free_session = it8xxx2_hash_session_free,
346 	.query_hw_caps = it8xxx2_query_hw_caps,
347 };
348 
349 DEVICE_DT_INST_DEFINE(0, &it8xxx2_sha_init, NULL, NULL, NULL, POST_KERNEL,
350 			CONFIG_CRYPTO_INIT_PRIORITY, &it8xxx2_crypto_api);
351