xref: /aosp_15_r20/external/flashrom/parade_lspcon.c (revision 0d6140be3aa665ecc836e8907834fcd3e3b018fc)
1 /*
2  * This file is part of the flashrom project.
3  *
4  * Copyright (C) 2020 The Chromium OS Authors
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  */
16 
17 #include <stdlib.h>
18 #include <stdint.h>
19 #include <stdio.h>
20 #include <string.h>
21 #include <time.h>
22 #include <errno.h>
23 
24 #include "programmer.h"
25 #include "spi.h"
26 #include "i2c_helper.h"
27 
28 #define REGISTER_ADDRESS	(0x94 >> 1)
29 #define PAGE_ADDRESS		(0x9e >> 1)
30 #define TUNNEL_PAGE_SIZE	256
31 #define MAX_SPI_WAIT_RETRIES	1000
32 
33 #define CLT2_SPI		0x82
34 #define SPIEDID_BASE_ADDR2	0x8d
35 #define ROMADDR_BYTE1		0x8e
36 #define ROMADDR_BYTE2		0x8f
37 #define SWSPI_WDATA		0x90
38 /* SWSPI_WDATA_* appear to be numerically the same as JEDEC commands. */
39  #define SWSPI_WDATA_CLEAR_STATUS		0x00
40  #define SWSPI_WDATA_WRITE_REGISTER		0x01 /* JEDEC_WRSR */
41  #define SWSPI_WDATA_READ_REGISTER		0x05 /* JEDEC_RDSR */
42  #define SWSPI_WDATA_ENABLE_REGISTER		0x06 /* JEDEC_WREN */
43  #define SWSPI_WDATA_PROTECT_BP			0x8c
44 #define SWSPI_RDATA		0x91
45 #define SWSPI_LEN		0x92
46 #define SWSPICTL		0x93
47  #define SWSPICTL_ACCESS_TRIGGER		BIT(0)
48  #define SWSPICTL_CLEAR_PTR			BIT(1)
49  #define SWSPICTL_NO_READ			BIT(2)
50  #define SWSPICTL_ENABLE_READBACK		BIT(3)
51  #define SWSPICTL_MOT				BIT(4)
52 #define SPISTATUS		0x9e
53  #define SPISTATUS_BYTE_PROGRAM_FINISHED	0
54  #define SPISTATUS_BYTE_PROGRAM_IN_IF		BIT(0)
55  #define SPISTATUS_BYTE_PROGRAM_SEND_DONE	BIT(1)
56  #define SPISTATUS_SECTOR_ERASE_FINISHED	0
57  #define SPISTATUS_SECTOR_ERASE_IN_IF		BIT(2)
58  #define SPISTATUS_SECTOR_ERASE_SEND_DONE	BIT(3)
59  #define SPISTATUS_CHIP_ERASE_FINISHED		0
60  #define SPISTATUS_CHIP_ERASE_IN_IF		BIT(4)
61  #define SPISTATUS_CHIP_ERASE_SEND_DONE		BIT(5)
62  #define SPISTATUS_FW_UPDATE_ENABLE		BIT(6)
63 #define WRITE_PROTECTION	0xb3
64  #define WRITE_PROTECTION_ON			0
65  #define WRITE_PROTECTION_OFF			0x10
66 #define MPU			0xbc
67 #define PAGE_HW_WRITE		0xda
68  #define PAGE_HW_WRITE_DISABLE			0
69  #define PAGE_HW_COFIG_REGISTER			0xaa
70  #define PAGE_HW_WRITE_ENABLE			0x55
71 
72 struct parade_lspcon_data {
73 	int fd;
74 };
75 
76 typedef struct {
77 	uint8_t command;
78 	const uint8_t *data;
79 	uint8_t data_size;
80 	uint8_t control;
81 } packet_t;
82 
parade_lspcon_write_data(int fd,uint16_t addr,void * buf,uint16_t len)83 static int parade_lspcon_write_data(int fd, uint16_t addr, void *buf, uint16_t len)
84 {
85 	i2c_buffer_t data;
86 	if (i2c_buffer_t_fill(&data, buf, len))
87 		return SPI_GENERIC_ERROR;
88 
89 	return i2c_write(fd, addr, &data) == len ? 0 : SPI_GENERIC_ERROR;
90 }
91 
parade_lspcon_read_data(int fd,uint16_t addr,void * buf,uint16_t len)92 static int parade_lspcon_read_data(int fd, uint16_t addr, void *buf, uint16_t len)
93 {
94 	i2c_buffer_t data;
95 	if (i2c_buffer_t_fill(&data, buf, len))
96 		return SPI_GENERIC_ERROR;
97 
98 	return i2c_read(fd, addr, &data) == len ? 0 : SPI_GENERIC_ERROR;
99 }
100 
get_fd_from_context(const struct flashctx * flash)101 static int get_fd_from_context(const struct flashctx *flash)
102 {
103 	if (!flash || !flash->mst || !flash->mst->spi.data) {
104 		msg_perr("Unable to extract fd from flash context.\n");
105 		return SPI_GENERIC_ERROR;
106 	}
107 	const struct parade_lspcon_data *data =
108 		(const struct parade_lspcon_data *)flash->mst->spi.data;
109 
110 	return data->fd;
111 }
112 
parade_lspcon_write_register(int fd,uint8_t i2c_register,uint8_t value)113 static int parade_lspcon_write_register(int fd, uint8_t i2c_register, uint8_t value)
114 {
115 	uint8_t command[] = { i2c_register, value };
116 	return parade_lspcon_write_data(fd, REGISTER_ADDRESS, command, 2);
117 }
118 
parade_lspcon_read_register(int fd,uint8_t i2c_register,uint8_t * value)119 static int parade_lspcon_read_register(int fd, uint8_t i2c_register, uint8_t *value)
120 {
121 	uint8_t command[] = { i2c_register };
122 	int ret = parade_lspcon_write_data(fd, REGISTER_ADDRESS, command, 1);
123 	ret |= parade_lspcon_read_data(fd, REGISTER_ADDRESS, value, 1);
124 
125 	return ret ? SPI_GENERIC_ERROR : 0;
126 }
127 
parade_lspcon_register_control(int fd,packet_t * packet)128 static int parade_lspcon_register_control(int fd, packet_t *packet)
129 {
130 	int i;
131 	int ret = parade_lspcon_write_register(fd, SWSPI_WDATA, packet->command);
132 	if (ret)
133 		return ret;
134 
135 	/* Higher 4 bits are read size. */
136 	int write_size = packet->data_size & 0x0f;
137 	for (i = 0; i < write_size; ++i) {
138 		ret |= parade_lspcon_write_register(fd, SWSPI_WDATA, packet->data[i]);
139 	}
140 
141 	ret |= parade_lspcon_write_register(fd, SWSPI_LEN, packet->data_size);
142 	ret |= parade_lspcon_write_register(fd, SWSPICTL, packet->control);
143 
144 	return ret;
145 }
146 
parade_lspcon_wait_command_done(int fd,unsigned int offset,int mask)147 static int parade_lspcon_wait_command_done(int fd, unsigned int offset, int mask)
148 {
149 	uint8_t val;
150 	int tried = 0;
151 	int ret = 0;
152 	do {
153 		ret |= parade_lspcon_read_register(fd, offset, &val);
154 	} while (!ret && (val & mask) && ++tried < MAX_SPI_WAIT_RETRIES);
155 
156 	if (tried == MAX_SPI_WAIT_RETRIES) {
157 		msg_perr("%s: Time out on sending command.\n", __func__);
158 		return -MAX_SPI_WAIT_RETRIES;
159 	}
160 
161 	return (val & mask) ? SPI_GENERIC_ERROR : ret;
162 }
163 
parade_lspcon_wait_rom_free(int fd)164 static int parade_lspcon_wait_rom_free(int fd)
165 {
166 	uint8_t val;
167 	int tried = 0;
168 	int ret = 0;
169 	ret |= parade_lspcon_wait_command_done(fd, SPISTATUS,
170 		SPISTATUS_SECTOR_ERASE_IN_IF | SPISTATUS_SECTOR_ERASE_SEND_DONE);
171 	if (ret)
172 		return ret;
173 
174 	do {
175 		packet_t packet = { SWSPI_WDATA_READ_REGISTER, NULL, 0,  SWSPICTL_ACCESS_TRIGGER };
176 		ret |= parade_lspcon_register_control(fd, &packet);
177 		ret |= parade_lspcon_wait_command_done(fd, SWSPICTL, SWSPICTL_ACCESS_TRIGGER);
178 		ret |= parade_lspcon_read_register(fd, SWSPI_RDATA, &val);
179 	} while (!ret && (val & SWSPICTL_ACCESS_TRIGGER) && ++tried < MAX_SPI_WAIT_RETRIES);
180 
181 	if (tried == MAX_SPI_WAIT_RETRIES) {
182 		msg_perr("%s: Time out on waiting ROM free.\n", __func__);
183 		return -MAX_SPI_WAIT_RETRIES;
184 	}
185 
186 	return (val & SWSPICTL_ACCESS_TRIGGER) ? SPI_GENERIC_ERROR : ret;
187 }
188 
parade_lspcon_toggle_register_protection(int fd,int toggle)189 static int parade_lspcon_toggle_register_protection(int fd, int toggle)
190 {
191 	return parade_lspcon_write_register(fd, WRITE_PROTECTION,
192 		toggle ? WRITE_PROTECTION_OFF : WRITE_PROTECTION_ON);
193 }
194 
parade_lspcon_enable_write_status_register(int fd)195 static int parade_lspcon_enable_write_status_register(int fd)
196 {
197 	int ret = parade_lspcon_toggle_register_protection(fd, 1);
198 	packet_t packet = {
199 		SWSPI_WDATA_ENABLE_REGISTER, NULL, 0, SWSPICTL_ACCESS_TRIGGER | SWSPICTL_NO_READ };
200 	ret |= parade_lspcon_register_control(fd, &packet);
201 	ret |= parade_lspcon_toggle_register_protection(fd, 0);
202 
203 	return ret;
204 }
205 
parade_lspcon_enable_write_status_register_protection(int fd)206 static int parade_lspcon_enable_write_status_register_protection(int fd)
207 {
208 	int ret = parade_lspcon_toggle_register_protection(fd, 1);
209 	uint8_t data[] = { SWSPI_WDATA_PROTECT_BP };
210 	packet_t packet = {
211 		SWSPI_WDATA_WRITE_REGISTER, data, 1, SWSPICTL_ACCESS_TRIGGER | SWSPICTL_NO_READ };
212 	ret |= parade_lspcon_register_control(fd, &packet);
213 	ret |= parade_lspcon_toggle_register_protection(fd, 0);
214 
215 	return ret;
216 }
217 
parade_lspcon_disable_protection(int fd)218 static int parade_lspcon_disable_protection(int fd)
219 {
220 	int ret = parade_lspcon_toggle_register_protection(fd, 1);
221 	uint8_t data[] = { SWSPI_WDATA_CLEAR_STATUS };
222 	packet_t packet = {
223 		SWSPI_WDATA_WRITE_REGISTER, data, 1, SWSPICTL_ACCESS_TRIGGER | SWSPICTL_NO_READ };
224 	ret |= parade_lspcon_register_control(fd, &packet);
225 	ret |= parade_lspcon_toggle_register_protection(fd, 0);
226 
227 	return ret;
228 }
229 
parade_lspcon_disable_hw_write(int fd)230 static int parade_lspcon_disable_hw_write(int fd)
231 {
232 	return parade_lspcon_write_register(fd, PAGE_HW_WRITE, PAGE_HW_WRITE_DISABLE);
233 }
234 
parade_lspcon_enable_write_protection(int fd)235 static int parade_lspcon_enable_write_protection(int fd)
236 {
237 	int ret = parade_lspcon_enable_write_status_register(fd);
238 	ret |= parade_lspcon_enable_write_status_register_protection(fd);
239 	ret |= parade_lspcon_wait_rom_free(fd);
240 	ret |= parade_lspcon_disable_hw_write(fd);
241 
242 	return ret;
243 }
244 
parade_lspcon_disable_all_protection(int fd)245 static int parade_lspcon_disable_all_protection(int fd)
246 {
247 	int ret = parade_lspcon_enable_write_status_register(fd);
248 	ret |= parade_lspcon_disable_protection(fd);
249 	ret |= parade_lspcon_wait_rom_free(fd);
250 
251 	return ret;
252 }
253 
parade_lspcon_send_command(const struct flashctx * flash,unsigned int writecnt,unsigned int readcnt,const unsigned char * writearr,unsigned char * readarr)254 static int parade_lspcon_send_command(const struct flashctx *flash,
255 				unsigned int writecnt, unsigned int readcnt,
256 				const unsigned char *writearr,
257 				unsigned char *readarr)
258 {
259 	unsigned int i;
260 	if (writecnt > 16 || readcnt > 16 || writecnt == 0) {
261 		msg_perr("%s: Invalid read/write count for send command.\n",
262                          __func__);
263 		return SPI_GENERIC_ERROR;
264 	}
265 
266 	int fd = get_fd_from_context(flash);
267 	if (fd < 0)
268 		return SPI_GENERIC_ERROR;
269 
270 	int ret = parade_lspcon_disable_all_protection(fd);
271 	ret |= parade_lspcon_enable_write_status_register(fd);
272 	ret |= parade_lspcon_toggle_register_protection(fd, 1);
273 
274 	/* First byte of writearr should be the command value, followed by the value to write.
275 	   Read length occupies 4 bit and represents 16 level, thus if read 1 byte,
276            read length should be set 0. */
277 	packet_t packet = {
278 		writearr[0], &writearr[1], (writecnt - 1) | ((readcnt - 1) << 4),
279 		SWSPICTL_ACCESS_TRIGGER | (readcnt ? 0 : SWSPICTL_NO_READ),
280 	};
281 
282 	ret |= parade_lspcon_register_control(fd, &packet);
283 	ret |= parade_lspcon_wait_command_done(fd, SWSPICTL, SWSPICTL_ACCESS_TRIGGER);
284 	ret |= parade_lspcon_toggle_register_protection(fd, 0);
285 	if (ret)
286 		return ret;
287 
288 	for (i = 0; i < readcnt; ++i) {
289 		ret |= parade_lspcon_read_register(fd, SWSPI_RDATA, &readarr[i]);
290 	}
291 
292 	ret |= parade_lspcon_wait_rom_free(fd);
293 
294 	return ret;
295 }
296 
parade_lspcon_enable_hw_write(int fd)297 static int parade_lspcon_enable_hw_write(int fd)
298 {
299 	int ret = 0;
300 	ret |= parade_lspcon_write_register(fd, PAGE_HW_WRITE, PAGE_HW_COFIG_REGISTER);
301 	ret |= parade_lspcon_write_register(fd, PAGE_HW_WRITE, PAGE_HW_WRITE_ENABLE);
302 	ret |= parade_lspcon_write_register(fd, PAGE_HW_WRITE, 0x50);
303 	ret |= parade_lspcon_write_register(fd, PAGE_HW_WRITE, 0x41);
304 	ret |= parade_lspcon_write_register(fd, PAGE_HW_WRITE, 0x52);
305 	ret |= parade_lspcon_write_register(fd, PAGE_HW_WRITE, 0x44);
306 
307 	return ret;
308 }
309 
parade_lspcon_i2c_clt2_spi_reset(int fd)310 static int parade_lspcon_i2c_clt2_spi_reset(int fd)
311 {
312 	int ret = 0;
313 	ret |= parade_lspcon_write_register(fd, CLT2_SPI, 0x20);
314 	struct timespec wait_100ms = { 0, (unsigned)1e8 };
315 	nanosleep(&wait_100ms, NULL);
316 	ret |= parade_lspcon_write_register(fd, CLT2_SPI, 0x00);
317 
318 	return ret;
319 }
320 
parade_lspcon_set_mpu_active(int fd,int running)321 static int parade_lspcon_set_mpu_active(int fd, int running)
322 {
323 	int ret = 0;
324 	// Cmd mode
325 	ret |= parade_lspcon_write_register(fd, MPU, 0xc0);
326 	// Stop or release MPU
327 	ret |= parade_lspcon_write_register(fd, MPU, running ? 0 : 0x40);
328 
329 	return ret;
330 }
331 
parade_lspcon_map_page(int fd,unsigned int offset)332 static int parade_lspcon_map_page(int fd, unsigned int offset)
333 {
334 	int ret = 0;
335 	/* Page number byte, need to / TUNNEL_PAGE_SIZE. */
336 	ret |= parade_lspcon_write_register(fd, ROMADDR_BYTE1, (offset >> 8) & 0xff);
337 	ret |= parade_lspcon_write_register(fd, ROMADDR_BYTE2, (offset >> 16));
338 
339 	return ret ? SPI_GENERIC_ERROR : 0;
340 }
341 
parade_lspcon_read(struct flashctx * flash,uint8_t * buf,unsigned int start,unsigned int len)342 static int parade_lspcon_read(struct flashctx *flash, uint8_t *buf,
343 			unsigned int start, unsigned int len)
344 {
345 	unsigned int i;
346 	int ret = 0;
347 	if (start & 0xff)
348 		return default_spi_read(flash, buf, start, len);
349 
350 	int fd = get_fd_from_context(flash);
351 	if (fd < 0)
352 		return SPI_GENERIC_ERROR;
353 
354 	for (i = 0; i < len; i += TUNNEL_PAGE_SIZE) {
355 		ret |= parade_lspcon_map_page(fd, start + i);
356 		ret |= parade_lspcon_read_data(fd, PAGE_ADDRESS, buf + i, min(len - i, TUNNEL_PAGE_SIZE));
357 		update_progress(flash, FLASHROM_PROGRESS_READ, i + TUNNEL_PAGE_SIZE, len);
358 	}
359 
360 	return ret;
361 }
362 
parade_lspcon_write_page(int fd,const uint8_t * buf,unsigned int len)363 static int parade_lspcon_write_page(int fd, const uint8_t *buf, unsigned int len)
364 {
365 	/**
366          * Using static buffer with maximum possible size,
367          * extra byte is needed for prefixing zero at index 0.
368          */
369 	uint8_t write_buffer[TUNNEL_PAGE_SIZE + 1] = { 0 };
370 	if (len > TUNNEL_PAGE_SIZE)
371 		return SPI_GENERIC_ERROR;
372 
373 	/* First byte represents the writing offset and should always be zero. */
374 	memcpy(&write_buffer[1], buf, len);
375 
376 	return parade_lspcon_write_data(fd, PAGE_ADDRESS, write_buffer, len + 1);
377 }
378 
parade_lspcon_write_256(struct flashctx * flash,const uint8_t * buf,unsigned int start,unsigned int len)379 static int parade_lspcon_write_256(struct flashctx *flash, const uint8_t *buf,
380 				unsigned int start, unsigned int len)
381 {
382 	int ret = 0;
383 	if (start & 0xff)
384 		return default_spi_write_256(flash, buf, start, len);
385 
386 	int fd = get_fd_from_context(flash);
387 	if (fd < 0)
388 		return SPI_GENERIC_ERROR;
389 
390 	ret |= parade_lspcon_disable_all_protection(fd);
391 	/* Enable hardware write and reset clt2SPI interface. */
392 	ret |= parade_lspcon_enable_hw_write(fd);
393 	ret |= parade_lspcon_i2c_clt2_spi_reset(fd);
394 
395 	for (unsigned int i = 0; i < len; i += TUNNEL_PAGE_SIZE) {
396 		ret |= parade_lspcon_map_page(fd, start + i);
397 		ret |= parade_lspcon_write_page(fd, buf + i, min(len - i, TUNNEL_PAGE_SIZE));
398 		update_progress(flash, FLASHROM_PROGRESS_WRITE, i + TUNNEL_PAGE_SIZE, len);
399 	}
400 
401 	ret |= parade_lspcon_enable_write_protection(fd);
402 	ret |= parade_lspcon_disable_hw_write(fd);
403 
404 	return ret;
405 }
406 
parade_lspcon_write_aai(struct flashctx * flash,const uint8_t * buf,unsigned int start,unsigned int len)407 static int parade_lspcon_write_aai(struct flashctx *flash, const uint8_t *buf,
408 				 unsigned int start, unsigned int len)
409 {
410 	msg_perr("%s: AAI write function is not supported.\n",
411                  __func__);
412 	return SPI_GENERIC_ERROR;
413 }
414 
parade_lspcon_shutdown(void * data)415 static int parade_lspcon_shutdown(void *data)
416 {
417 	int ret = 0;
418 	struct parade_lspcon_data *parade_lspcon_data =
419 		(struct parade_lspcon_data *)data;
420 	int fd = parade_lspcon_data->fd;
421 
422 	ret |= parade_lspcon_enable_write_protection(fd);
423 	ret |= parade_lspcon_toggle_register_protection(fd, 0);
424 	ret |= parade_lspcon_set_mpu_active(fd, 1);
425 	i2c_close(fd);
426 	free(data);
427 
428 	return ret;
429 }
430 
431 static const struct spi_master spi_master_parade_lspcon = {
432 	.max_data_read	= 16,
433 	.max_data_write	= 12,
434 	.command	= parade_lspcon_send_command,
435 	.read		= parade_lspcon_read,
436 	.write_256	= parade_lspcon_write_256,
437 	.write_aai	= parade_lspcon_write_aai,
438 	.shutdown	= parade_lspcon_shutdown,
439 };
440 
get_params(const struct programmer_cfg * cfg,bool * allow_brick)441 static int get_params(const struct programmer_cfg *cfg, bool *allow_brick)
442 {
443 	char *brick_str = NULL;
444 	int ret = 0;
445 
446 	*allow_brick = false; /* Default behaviour is to bail. */
447 	brick_str = extract_programmer_param_str(cfg, "allow_brick");
448 	if (brick_str) {
449 		if (!strcmp(brick_str, "yes")) {
450 			*allow_brick = true;
451 		} else {
452 			msg_perr("%s: Incorrect param format, allow_brick=yes.\n", __func__);
453 			ret = SPI_GENERIC_ERROR;
454 		}
455 	}
456 	free(brick_str);
457 
458 	return ret;
459 }
460 
parade_lspcon_init(const struct programmer_cfg * cfg)461 static int parade_lspcon_init(const struct programmer_cfg *cfg)
462 {
463 	bool allow_brick;
464 
465 	if (get_params(cfg, &allow_brick))
466 		return SPI_GENERIC_ERROR;
467 
468 	/*
469 	 * TODO: Once board_enable can facilitate safe i2c allow listing
470 	 * 	 then this can be removed.
471 	 */
472 	if (!allow_brick) {
473 		msg_perr("%s: For i2c drivers you must explicitly 'allow_brick=yes'. ", __func__);
474 		msg_perr("There is currently no way to determine if the programmer works on a board "
475 			 "as i2c device address space can be overloaded. Set 'allow_brick=yes' if "
476 			 "you are sure you know what you are doing.\n");
477 		return SPI_GENERIC_ERROR;
478 	}
479 
480 	int fd = i2c_open_from_programmer_params(cfg, REGISTER_ADDRESS, 0);
481 	if (fd < 0)
482 		return fd;
483 
484 	int ret = parade_lspcon_set_mpu_active(fd, 0);
485 	if (ret) {
486 		msg_perr("%s: call to set_mpu_active failed.\n", __func__);
487 		i2c_close(fd);
488 		return ret;
489 	}
490 
491 	struct parade_lspcon_data *data = calloc(1, sizeof(*data));
492 	if (!data) {
493 		msg_perr("Unable to allocate space for extra SPI master data.\n");
494 		i2c_close(fd);
495 		return SPI_GENERIC_ERROR;
496 	}
497 
498 	data->fd = fd;
499 
500 	return register_spi_master(&spi_master_parade_lspcon, data);
501 }
502 
503 const struct programmer_entry programmer_parade_lspcon = {
504 	.name			= "parade_lspcon",
505 	.type			= OTHER,
506 	.devs.note		= "Device files /dev/i2c-*.\n",
507 	.init			= parade_lspcon_init,
508 };
509