xref: /kvmtool/hw/cfi_flash.c (revision d632faceb69d7816b7b5ec645ece22c2507d00d3)
125cf3198SRaphael Gault #include <stdbool.h>
225cf3198SRaphael Gault #include <stdlib.h>
325cf3198SRaphael Gault #include <string.h>
425cf3198SRaphael Gault #include <linux/bitops.h>
525cf3198SRaphael Gault #include <linux/err.h>
625cf3198SRaphael Gault #include <linux/sizes.h>
725cf3198SRaphael Gault #include <linux/types.h>
825cf3198SRaphael Gault 
925cf3198SRaphael Gault #include "kvm/kvm.h"
1025cf3198SRaphael Gault #include "kvm/kvm-arch.h"
11*d632faceSAndre Przywara #include "kvm/kvm-cpu.h"
1225cf3198SRaphael Gault #include "kvm/devices.h"
1325cf3198SRaphael Gault #include "kvm/fdt.h"
1425cf3198SRaphael Gault #include "kvm/mutex.h"
1525cf3198SRaphael Gault #include "kvm/util.h"
1625cf3198SRaphael Gault 
1725cf3198SRaphael Gault /*
1825cf3198SRaphael Gault  * The EDK2 driver hardcodes two 16-bit chips on a 32-bit bus.
1925cf3198SRaphael Gault  * This code supports one or two chips (enforced below).
2025cf3198SRaphael Gault  */
2125cf3198SRaphael Gault #define CFI_NR_FLASH_CHIPS			2
2225cf3198SRaphael Gault 
2325cf3198SRaphael Gault /* We always emulate a 32 bit bus width. */
2425cf3198SRaphael Gault #define CFI_BUS_WIDTH				4
2525cf3198SRaphael Gault 
2625cf3198SRaphael Gault /* The *effective* size of an erase block (over all chips) */
2725cf3198SRaphael Gault #define FLASH_BLOCK_SIZE			SZ_64K
2825cf3198SRaphael Gault #define FLASH_BLOCK_SIZE_PER_CHIP					\
2925cf3198SRaphael Gault 	(FLASH_BLOCK_SIZE / CFI_NR_FLASH_CHIPS)
3025cf3198SRaphael Gault 
3125cf3198SRaphael Gault #define PROGRAM_BUFF_SIZE_BITS			7
3225cf3198SRaphael Gault #define PROGRAM_BUFF_SIZE			(1U << PROGRAM_BUFF_SIZE_BITS)
3325cf3198SRaphael Gault #define PROGRAM_BUFF_SIZE_BITS_PER_CHIP					\
3425cf3198SRaphael Gault 	(PROGRAM_BUFF_SIZE_BITS + 1 - CFI_NR_FLASH_CHIPS)
3525cf3198SRaphael Gault 
3625cf3198SRaphael Gault /* CFI commands */
3725cf3198SRaphael Gault #define CFI_CMD_LOCK_BLOCK			0x01
3825cf3198SRaphael Gault #define CFI_CMD_ALTERNATE_WORD_PROGRAM		0x10
3925cf3198SRaphael Gault #define CFI_CMD_ERASE_BLOCK_SETUP		0x20
4025cf3198SRaphael Gault #define CFI_CMD_WORD_PROGRAM			0x40
4125cf3198SRaphael Gault #define CFI_CMD_CLEAR_STATUS_REG		0x50
4225cf3198SRaphael Gault #define CFI_CMD_LOCK_BLOCK_SETUP		0x60
4325cf3198SRaphael Gault #define CFI_CMD_READ_STATUS_REG			0x70
4425cf3198SRaphael Gault #define CFI_CMD_READ_JEDEC_DEVID		0x90
4525cf3198SRaphael Gault #define CFI_CMD_READ_CFI_QUERY			0x98
4625cf3198SRaphael Gault #define CFI_CMD_CONFIRM				0xd0
4725cf3198SRaphael Gault #define CFI_CMD_BUFFERED_PROGRAM_SETUP		0xe8
4825cf3198SRaphael Gault #define CFI_CMD_READ_ARRAY			0xff
4925cf3198SRaphael Gault 
5025cf3198SRaphael Gault #define CFI_STATUS_PROTECT_BIT		0x02
5125cf3198SRaphael Gault #define CFI_STATUS_PROGRAM_LOCK_BIT	0x10
5225cf3198SRaphael Gault #define CFI_STATUS_ERASE_CLEAR_LOCK_BIT	0x20
5325cf3198SRaphael Gault #define CFI_STATUS_LOCK_ERROR		CFI_STATUS_PROGRAM_LOCK_BIT |	\
5425cf3198SRaphael Gault 					CFI_STATUS_PROTECT_BIT
5525cf3198SRaphael Gault #define CFI_STATUS_ERASE_ERROR		CFI_STATUS_ERASE_CLEAR_LOCK_BIT | \
5625cf3198SRaphael Gault 					CFI_STATUS_PROGRAM_LOCK_BIT
5725cf3198SRaphael Gault #define CFI_STATUS_READY		0x80
5825cf3198SRaphael Gault 
5925cf3198SRaphael Gault /*
6025cf3198SRaphael Gault  * CFI query table contents, as far as it is constant.
6125cf3198SRaphael Gault  * The dynamic information (size, etc.) will be generated on the fly.
6225cf3198SRaphael Gault  */
6325cf3198SRaphael Gault #define CFI_GEOM_OFFSET				0x27
6425cf3198SRaphael Gault static const u8 cfi_query_table[] = {
6525cf3198SRaphael Gault 		/* CFI query identification string */
6625cf3198SRaphael Gault 	[0x10] = 'Q', 'R', 'Y',		/* ID string */
6725cf3198SRaphael Gault 	0x01, 0x00,		/* primary command set: Intel/Sharp extended */
6825cf3198SRaphael Gault 	0x31, 0x00,		/* address of primary extended query table */
6925cf3198SRaphael Gault 	0x00, 0x00,		/* alternative command set: unused */
7025cf3198SRaphael Gault 	0x00, 0x00,		/* address of alternative extended query table*/
7125cf3198SRaphael Gault 		/* system interface information */
7225cf3198SRaphael Gault 	[0x1b] = 0x45,			/* minimum Vcc voltage: 4.5V */
7325cf3198SRaphael Gault 	0x55,			/* maximum Vcc voltage: 5.5V */
7425cf3198SRaphael Gault 	0x00,			/* minimum Vpp voltage: 0.0V (unused) */
7525cf3198SRaphael Gault 	0x00,			/* maximum Vpp voltage: 0.0V *(unused) */
7625cf3198SRaphael Gault 	0x01,			/* timeout for single word program: 2 us */
7725cf3198SRaphael Gault 	0x01,			/* timeout for multi-byte program: 2 us */
7825cf3198SRaphael Gault 	0x01,			/* timeout for block erase: 2 ms */
7925cf3198SRaphael Gault 	0x00,			/* timeout for full chip erase: not supported */
8025cf3198SRaphael Gault 	0x00,			/* max timeout for single word program: 1x */
8125cf3198SRaphael Gault 	0x00,			/* max timeout for mulit-byte program: 1x */
8225cf3198SRaphael Gault 	0x00,			/* max timeout for block erase: 1x */
8325cf3198SRaphael Gault 	0x00,			/* max timeout for chip erase: not supported */
8425cf3198SRaphael Gault 		/* flash geometry information */
8525cf3198SRaphael Gault 	[0x27] = 0x00,		/* size in power-of-2 bytes, filled later */
8625cf3198SRaphael Gault 	0x05, 0x00,		/* interface description: 32 and 16 bits */
8725cf3198SRaphael Gault 	PROGRAM_BUFF_SIZE_BITS_PER_CHIP, 0x00,
8825cf3198SRaphael Gault 				/* number of bytes in write buffer */
8925cf3198SRaphael Gault 	0x01,			/* one erase block region */
9025cf3198SRaphael Gault 	0x00, 0x00, 0x00, 0x00, /* number and size of erase blocks, generated */
9125cf3198SRaphael Gault 		/* Intel primary algorithm extended query table */
9225cf3198SRaphael Gault 	[0x31] = 'P', 'R', 'I',
9325cf3198SRaphael Gault 	'1', '0',		/* version 1.0 */
9425cf3198SRaphael Gault 	0xa0, 0x00, 0x00, 0x00, /* optional features: instant lock & pm-read */
9525cf3198SRaphael Gault 	0x00,			/* no functions after suspend */
9625cf3198SRaphael Gault 	0x01, 0x00,		/* only lock bit supported */
9725cf3198SRaphael Gault 	0x50,			/* best Vcc value: 5.0V */
9825cf3198SRaphael Gault 	0x00,			/* best Vpp value: 0.0V (unused) */
9925cf3198SRaphael Gault 	0x01,			/* number of protection register fields */
10025cf3198SRaphael Gault 	0x00, 0x00, 0x00, 0x00,	/* protection field 1 description */
10125cf3198SRaphael Gault };
10225cf3198SRaphael Gault 
10325cf3198SRaphael Gault /*
10425cf3198SRaphael Gault  * Those states represent a subset of the CFI flash state machine.
10525cf3198SRaphael Gault  */
10625cf3198SRaphael Gault enum cfi_flash_state {
10725cf3198SRaphael Gault 	READY,
10825cf3198SRaphael Gault 	LOCK_BLOCK_SETUP,
10925cf3198SRaphael Gault 	WORD_PROGRAM,
11025cf3198SRaphael Gault 	BUFFERED_PROGRAM_SETUP,
11125cf3198SRaphael Gault 	BUFFER_WRITE,
11225cf3198SRaphael Gault 	ERASE_BLOCK_SETUP,
11325cf3198SRaphael Gault };
11425cf3198SRaphael Gault 
11525cf3198SRaphael Gault /*
11625cf3198SRaphael Gault  * The device can be in several **Read** modes.
11725cf3198SRaphael Gault  * We don't implement the asynchronous burst mode.
11825cf3198SRaphael Gault  */
11925cf3198SRaphael Gault enum cfi_read_mode {
12025cf3198SRaphael Gault 	READ_ARRAY,
12125cf3198SRaphael Gault 	READ_STATUS_REG,
12225cf3198SRaphael Gault 	READ_JEDEC_DEVID,
12325cf3198SRaphael Gault 	READ_CFI_QUERY,
12425cf3198SRaphael Gault };
12525cf3198SRaphael Gault 
12625cf3198SRaphael Gault struct cfi_flash_device {
12725cf3198SRaphael Gault 	struct device_header	dev_hdr;
12825cf3198SRaphael Gault 	/* Protects the CFI state machine variables in this data structure. */
12925cf3198SRaphael Gault 	struct mutex		mutex;
13025cf3198SRaphael Gault 	u64			base_addr;
13125cf3198SRaphael Gault 	u32			size;
13225cf3198SRaphael Gault 
13325cf3198SRaphael Gault 	void			*flash_memory;
13425cf3198SRaphael Gault 	u8			program_buffer[PROGRAM_BUFF_SIZE];
13525cf3198SRaphael Gault 	unsigned long		*lock_bm;
13625cf3198SRaphael Gault 	u64			block_address;
13725cf3198SRaphael Gault 	unsigned int		buff_written;
13825cf3198SRaphael Gault 	unsigned int		buffer_length;
13925cf3198SRaphael Gault 
14025cf3198SRaphael Gault 	enum cfi_flash_state	state;
14125cf3198SRaphael Gault 	enum cfi_read_mode	read_mode;
14225cf3198SRaphael Gault 	u8			sr;
143*d632faceSAndre Przywara 	bool			is_mapped;
14425cf3198SRaphael Gault };
14525cf3198SRaphael Gault 
nr_erase_blocks(struct cfi_flash_device * sfdev)14625cf3198SRaphael Gault static int nr_erase_blocks(struct cfi_flash_device *sfdev)
14725cf3198SRaphael Gault {
14825cf3198SRaphael Gault 	return sfdev->size / FLASH_BLOCK_SIZE;
14925cf3198SRaphael Gault }
15025cf3198SRaphael Gault 
15125cf3198SRaphael Gault /*
15225cf3198SRaphael Gault  * CFI queries always deal with one byte of information, possibly mirrored
15325cf3198SRaphael Gault  * to other bytes on the bus. This is dealt with in the callers.
15425cf3198SRaphael Gault  * The address provided is the one for 8-bit addressing, and would need to
15525cf3198SRaphael Gault  * be adjusted for wider accesses.
15625cf3198SRaphael Gault  */
read_cfi(struct cfi_flash_device * sfdev,u64 faddr)15725cf3198SRaphael Gault static u8 read_cfi(struct cfi_flash_device *sfdev, u64 faddr)
15825cf3198SRaphael Gault {
15925cf3198SRaphael Gault 	if (faddr > sizeof(cfi_query_table)) {
16025cf3198SRaphael Gault 		pr_debug("CFI query read access beyond the end of table");
16125cf3198SRaphael Gault 		return 0;
16225cf3198SRaphael Gault 	}
16325cf3198SRaphael Gault 
16425cf3198SRaphael Gault 	/* Fixup dynamic information in the geometry part of the table. */
16525cf3198SRaphael Gault 	switch (faddr) {
16625cf3198SRaphael Gault 	case 0x27:		/* device size in bytes, power of two */
16725cf3198SRaphael Gault 		return pow2_size(sfdev->size / CFI_NR_FLASH_CHIPS);
16825cf3198SRaphael Gault 	case 0x2d + 0:	/* number of erase blocks, minus one */
16925cf3198SRaphael Gault 		return (nr_erase_blocks(sfdev) - 1) & 0xff;
17025cf3198SRaphael Gault 	case 0x2d + 1:
17125cf3198SRaphael Gault 		return ((nr_erase_blocks(sfdev) - 1) >> 8) & 0xff;
17225cf3198SRaphael Gault 	case 0x2d + 2:	/* erase block size, in units of 256 */
17325cf3198SRaphael Gault 		return (FLASH_BLOCK_SIZE_PER_CHIP / 256) & 0xff;
17425cf3198SRaphael Gault 	case 0x2d + 3:
17525cf3198SRaphael Gault 		return ((FLASH_BLOCK_SIZE_PER_CHIP / 256) >> 8) & 0xff;
17625cf3198SRaphael Gault 	}
17725cf3198SRaphael Gault 
17825cf3198SRaphael Gault 	return cfi_query_table[faddr];
17925cf3198SRaphael Gault }
18025cf3198SRaphael Gault 
block_is_locked(struct cfi_flash_device * sfdev,u64 faddr)18125cf3198SRaphael Gault static bool block_is_locked(struct cfi_flash_device *sfdev, u64 faddr)
18225cf3198SRaphael Gault {
18325cf3198SRaphael Gault 	int block_nr = faddr / FLASH_BLOCK_SIZE;
18425cf3198SRaphael Gault 
18525cf3198SRaphael Gault 	return test_bit(block_nr, sfdev->lock_bm);
18625cf3198SRaphael Gault }
18725cf3198SRaphael Gault 
18825cf3198SRaphael Gault #define DEV_ID_MASK 0x7ff
read_dev_id(struct cfi_flash_device * sfdev,u64 faddr)18925cf3198SRaphael Gault static u16 read_dev_id(struct cfi_flash_device *sfdev, u64 faddr)
19025cf3198SRaphael Gault {
19125cf3198SRaphael Gault 	switch ((faddr & DEV_ID_MASK) / CFI_BUS_WIDTH) {
19225cf3198SRaphael Gault 	case 0x0:				/* vendor ID */
19325cf3198SRaphael Gault 		return 0x0000;
19425cf3198SRaphael Gault 	case 0x1:				/* device ID */
19525cf3198SRaphael Gault 		return 0xffff;
19625cf3198SRaphael Gault 	case 0x2:
19725cf3198SRaphael Gault 		return block_is_locked(sfdev, faddr & ~DEV_ID_MASK);
19825cf3198SRaphael Gault 	default:			/* Ignore the other entries. */
19925cf3198SRaphael Gault 		return 0;
20025cf3198SRaphael Gault 	}
20125cf3198SRaphael Gault }
20225cf3198SRaphael Gault 
lock_block(struct cfi_flash_device * sfdev,u64 faddr,bool lock)20325cf3198SRaphael Gault static void lock_block(struct cfi_flash_device *sfdev, u64 faddr, bool lock)
20425cf3198SRaphael Gault {
20525cf3198SRaphael Gault 	int block_nr = faddr / FLASH_BLOCK_SIZE;
20625cf3198SRaphael Gault 
20725cf3198SRaphael Gault 	if (lock)
20825cf3198SRaphael Gault 		set_bit(block_nr, sfdev->lock_bm);
20925cf3198SRaphael Gault 	else
21025cf3198SRaphael Gault 		clear_bit(block_nr, sfdev->lock_bm);
21125cf3198SRaphael Gault }
21225cf3198SRaphael Gault 
word_program(struct cfi_flash_device * sfdev,u64 faddr,void * data,int len)21325cf3198SRaphael Gault static void word_program(struct cfi_flash_device *sfdev,
21425cf3198SRaphael Gault 			 u64 faddr, void *data, int len)
21525cf3198SRaphael Gault {
21625cf3198SRaphael Gault 	if (block_is_locked(sfdev, faddr)) {
21725cf3198SRaphael Gault 		sfdev->sr |= CFI_STATUS_LOCK_ERROR;
21825cf3198SRaphael Gault 		return;
21925cf3198SRaphael Gault 	}
22025cf3198SRaphael Gault 
22125cf3198SRaphael Gault 	memcpy(sfdev->flash_memory + faddr, data, len);
22225cf3198SRaphael Gault }
22325cf3198SRaphael Gault 
22425cf3198SRaphael Gault /* Reset the program buffer state to prepare for follow-up writes. */
buffer_setup(struct cfi_flash_device * sfdev)22525cf3198SRaphael Gault static void buffer_setup(struct cfi_flash_device *sfdev)
22625cf3198SRaphael Gault {
22725cf3198SRaphael Gault 	memset(sfdev->program_buffer, 0, sizeof(sfdev->program_buffer));
22825cf3198SRaphael Gault 	sfdev->block_address = ~0ULL;
22925cf3198SRaphael Gault 	sfdev->buff_written = 0;
23025cf3198SRaphael Gault }
23125cf3198SRaphael Gault 
buffer_write(struct cfi_flash_device * sfdev,u64 faddr,void * buffer,int len)23225cf3198SRaphael Gault static bool buffer_write(struct cfi_flash_device *sfdev,
23325cf3198SRaphael Gault 			 u64 faddr, void *buffer, int len)
23425cf3198SRaphael Gault {
23525cf3198SRaphael Gault 	unsigned int buff_addr;
23625cf3198SRaphael Gault 
23725cf3198SRaphael Gault 	if (sfdev->buff_written >= sfdev->buffer_length)
23825cf3198SRaphael Gault 		return false;
23925cf3198SRaphael Gault 
24025cf3198SRaphael Gault 	/*
24125cf3198SRaphael Gault 	 * The first word written into the buffer after the setup command
24225cf3198SRaphael Gault 	 * happens to be the base address for the buffer.
24325cf3198SRaphael Gault 	 * All subsequent writes need to be within this address and this
24425cf3198SRaphael Gault 	 * address plus the buffer size, so keep this value around.
24525cf3198SRaphael Gault 	 */
24625cf3198SRaphael Gault 	if (sfdev->block_address == ~0ULL)
24725cf3198SRaphael Gault 		sfdev->block_address = faddr;
24825cf3198SRaphael Gault 
24925cf3198SRaphael Gault 	if (faddr < sfdev->block_address)
25025cf3198SRaphael Gault 		return false;
25125cf3198SRaphael Gault 	buff_addr = faddr - sfdev->block_address;
25225cf3198SRaphael Gault 	if (buff_addr >= PROGRAM_BUFF_SIZE)
25325cf3198SRaphael Gault 		return false;
25425cf3198SRaphael Gault 
25525cf3198SRaphael Gault 	memcpy(sfdev->program_buffer + buff_addr, buffer, len);
25625cf3198SRaphael Gault 	sfdev->buff_written += len;
25725cf3198SRaphael Gault 
25825cf3198SRaphael Gault 	return true;
25925cf3198SRaphael Gault }
26025cf3198SRaphael Gault 
buffer_confirm(struct cfi_flash_device * sfdev)26125cf3198SRaphael Gault static void buffer_confirm(struct cfi_flash_device *sfdev)
26225cf3198SRaphael Gault {
26325cf3198SRaphael Gault 	if (block_is_locked(sfdev, sfdev->block_address)) {
26425cf3198SRaphael Gault 		sfdev->sr |= CFI_STATUS_LOCK_ERROR;
26525cf3198SRaphael Gault 		return;
26625cf3198SRaphael Gault 	}
26725cf3198SRaphael Gault 	memcpy(sfdev->flash_memory + sfdev->block_address,
26825cf3198SRaphael Gault 	       sfdev->program_buffer, sfdev->buff_written);
26925cf3198SRaphael Gault }
27025cf3198SRaphael Gault 
block_erase_confirm(struct cfi_flash_device * sfdev,u64 faddr)27125cf3198SRaphael Gault static void block_erase_confirm(struct cfi_flash_device *sfdev, u64 faddr)
27225cf3198SRaphael Gault {
27325cf3198SRaphael Gault 	if (block_is_locked(sfdev, faddr)) {
27425cf3198SRaphael Gault 		sfdev->sr |= CFI_STATUS_LOCK_ERROR;
27525cf3198SRaphael Gault 		return;
27625cf3198SRaphael Gault 	}
27725cf3198SRaphael Gault 
27825cf3198SRaphael Gault 	memset(sfdev->flash_memory + faddr, 0xff, FLASH_BLOCK_SIZE);
27925cf3198SRaphael Gault }
28025cf3198SRaphael Gault 
cfi_flash_read(struct cfi_flash_device * sfdev,u64 faddr,u8 * data,u32 len)28125cf3198SRaphael Gault static void cfi_flash_read(struct cfi_flash_device *sfdev,
28225cf3198SRaphael Gault 			   u64 faddr, u8 *data, u32 len)
28325cf3198SRaphael Gault {
28425cf3198SRaphael Gault 	u16 cfi_value = 0;
28525cf3198SRaphael Gault 
28625cf3198SRaphael Gault 	switch (sfdev->read_mode) {
28725cf3198SRaphael Gault 	case READ_ARRAY:
28825cf3198SRaphael Gault 		/* just copy the requested bytes from the array */
28925cf3198SRaphael Gault 		memcpy(data, sfdev->flash_memory + faddr, len);
29025cf3198SRaphael Gault 		return;
29125cf3198SRaphael Gault 	case READ_STATUS_REG:
29225cf3198SRaphael Gault 		cfi_value = sfdev->sr;
29325cf3198SRaphael Gault 		break;
29425cf3198SRaphael Gault 	case READ_JEDEC_DEVID:
29525cf3198SRaphael Gault 		cfi_value = read_dev_id(sfdev, faddr);
29625cf3198SRaphael Gault 		break;
29725cf3198SRaphael Gault 	case READ_CFI_QUERY:
29825cf3198SRaphael Gault 		cfi_value = read_cfi(sfdev, faddr / CFI_BUS_WIDTH);
29925cf3198SRaphael Gault 		break;
30025cf3198SRaphael Gault 	}
30125cf3198SRaphael Gault 	switch (len) {
30225cf3198SRaphael Gault 	case 1:
30325cf3198SRaphael Gault 		*data = cfi_value;
30425cf3198SRaphael Gault 		break;
30525cf3198SRaphael Gault 	case 8: memset(data + 4, 0, 4);
30625cf3198SRaphael Gault 		/* fall-through */
30725cf3198SRaphael Gault 	case 4:
30825cf3198SRaphael Gault 		if (CFI_NR_FLASH_CHIPS == 2)
30925cf3198SRaphael Gault 			memcpy(data + 2, &cfi_value, 2);
31025cf3198SRaphael Gault 		else
31125cf3198SRaphael Gault 			memset(data + 2, 0, 2);
31225cf3198SRaphael Gault 		/* fall-through */
31325cf3198SRaphael Gault 	case 2:
31425cf3198SRaphael Gault 		memcpy(data, &cfi_value, 2);
31525cf3198SRaphael Gault 		break;
31625cf3198SRaphael Gault 	default:
31725cf3198SRaphael Gault 		pr_debug("CFI flash: illegal access length %d for read mode %d",
31825cf3198SRaphael Gault 			 len, sfdev->read_mode);
31925cf3198SRaphael Gault 		break;
32025cf3198SRaphael Gault 	}
32125cf3198SRaphael Gault }
32225cf3198SRaphael Gault 
32325cf3198SRaphael Gault /*
32425cf3198SRaphael Gault  * Any writes happening in "READY" state don't actually write to the memory,
32525cf3198SRaphael Gault  * but are really treated as commands to advance the state machine and select
32625cf3198SRaphael Gault  * the next action.
32725cf3198SRaphael Gault  * Change the state and modes according to the value written. The address
32825cf3198SRaphael Gault  * that value is written to does not matter and is ignored.
32925cf3198SRaphael Gault  */
cfi_flash_write_ready(struct cfi_flash_device * sfdev,u8 command)33025cf3198SRaphael Gault static void cfi_flash_write_ready(struct cfi_flash_device *sfdev, u8 command)
33125cf3198SRaphael Gault {
33225cf3198SRaphael Gault 	switch (command) {
33325cf3198SRaphael Gault 	case CFI_CMD_READ_JEDEC_DEVID:
33425cf3198SRaphael Gault 		sfdev->read_mode = READ_JEDEC_DEVID;
33525cf3198SRaphael Gault 		break;
33625cf3198SRaphael Gault 	case CFI_CMD_READ_STATUS_REG:
33725cf3198SRaphael Gault 		sfdev->read_mode = READ_STATUS_REG;
33825cf3198SRaphael Gault 		break;
33925cf3198SRaphael Gault 	case CFI_CMD_READ_CFI_QUERY:
34025cf3198SRaphael Gault 		sfdev->read_mode = READ_CFI_QUERY;
34125cf3198SRaphael Gault 		break;
34225cf3198SRaphael Gault 	case CFI_CMD_CLEAR_STATUS_REG:
34325cf3198SRaphael Gault 		sfdev->sr = CFI_STATUS_READY;
34425cf3198SRaphael Gault 		break;
34525cf3198SRaphael Gault 	case CFI_CMD_WORD_PROGRAM:
34625cf3198SRaphael Gault 	case CFI_CMD_ALTERNATE_WORD_PROGRAM:
34725cf3198SRaphael Gault 		sfdev->state = WORD_PROGRAM;
34825cf3198SRaphael Gault 		sfdev->read_mode = READ_STATUS_REG;
34925cf3198SRaphael Gault 		break;
35025cf3198SRaphael Gault 	case CFI_CMD_LOCK_BLOCK_SETUP:
35125cf3198SRaphael Gault 		sfdev->state = LOCK_BLOCK_SETUP;
35225cf3198SRaphael Gault 		break;
35325cf3198SRaphael Gault 	case CFI_CMD_ERASE_BLOCK_SETUP:
35425cf3198SRaphael Gault 		sfdev->state = ERASE_BLOCK_SETUP;
35525cf3198SRaphael Gault 		sfdev->read_mode = READ_STATUS_REG;
35625cf3198SRaphael Gault 		break;
35725cf3198SRaphael Gault 	case CFI_CMD_BUFFERED_PROGRAM_SETUP:
35825cf3198SRaphael Gault 		buffer_setup(sfdev);
35925cf3198SRaphael Gault 		sfdev->state = BUFFERED_PROGRAM_SETUP;
36025cf3198SRaphael Gault 		sfdev->read_mode = READ_STATUS_REG;
36125cf3198SRaphael Gault 		break;
36225cf3198SRaphael Gault 	case CFI_CMD_CONFIRM:
36325cf3198SRaphael Gault 		pr_debug("CFI flash: unexpected confirm command 0xd0");
36425cf3198SRaphael Gault 		break;
36525cf3198SRaphael Gault 	default:
36625cf3198SRaphael Gault 		pr_debug("CFI flash: unknown command 0x%x", command);
36725cf3198SRaphael Gault 		/* fall-through */
36825cf3198SRaphael Gault 	case CFI_CMD_READ_ARRAY:
36925cf3198SRaphael Gault 		sfdev->read_mode = READ_ARRAY;
37025cf3198SRaphael Gault 		break;
37125cf3198SRaphael Gault 	}
37225cf3198SRaphael Gault }
37325cf3198SRaphael Gault 
cfi_flash_write(struct cfi_flash_device * sfdev,u16 command,u64 faddr,u8 * data,u32 len)37425cf3198SRaphael Gault static void cfi_flash_write(struct cfi_flash_device *sfdev, u16 command,
37525cf3198SRaphael Gault 			    u64 faddr, u8 *data, u32 len)
37625cf3198SRaphael Gault {
37725cf3198SRaphael Gault 	switch (sfdev->state) {
37825cf3198SRaphael Gault 	case READY:
37925cf3198SRaphael Gault 		cfi_flash_write_ready(sfdev, command & 0xff);
38025cf3198SRaphael Gault 		return;
38125cf3198SRaphael Gault 	case LOCK_BLOCK_SETUP:
38225cf3198SRaphael Gault 		switch (command & 0xff) {
38325cf3198SRaphael Gault 		case CFI_CMD_LOCK_BLOCK:
38425cf3198SRaphael Gault 			lock_block(sfdev, faddr, true);
38525cf3198SRaphael Gault 			sfdev->read_mode = READ_STATUS_REG;
38625cf3198SRaphael Gault 			break;
38725cf3198SRaphael Gault 		case CFI_CMD_CONFIRM:
38825cf3198SRaphael Gault 			lock_block(sfdev, faddr, false);
38925cf3198SRaphael Gault 			sfdev->read_mode = READ_STATUS_REG;
39025cf3198SRaphael Gault 			break;
39125cf3198SRaphael Gault 		default:
39225cf3198SRaphael Gault 			sfdev->sr |= CFI_STATUS_ERASE_ERROR;
39325cf3198SRaphael Gault 			break;
39425cf3198SRaphael Gault 		}
39525cf3198SRaphael Gault 		sfdev->state = READY;
39625cf3198SRaphael Gault 		break;
39725cf3198SRaphael Gault 
39825cf3198SRaphael Gault 	case WORD_PROGRAM:
39925cf3198SRaphael Gault 		word_program(sfdev, faddr, data, len);
40025cf3198SRaphael Gault 		sfdev->read_mode = READ_STATUS_REG;
40125cf3198SRaphael Gault 		sfdev->state = READY;
40225cf3198SRaphael Gault 		break;
40325cf3198SRaphael Gault 
40425cf3198SRaphael Gault 	case BUFFER_WRITE:
40525cf3198SRaphael Gault 		if (buffer_write(sfdev, faddr, data, len))
40625cf3198SRaphael Gault 			break;
40725cf3198SRaphael Gault 
40825cf3198SRaphael Gault 		if ((command & 0xff) == CFI_CMD_CONFIRM) {
40925cf3198SRaphael Gault 			buffer_confirm(sfdev);
41025cf3198SRaphael Gault 			sfdev->read_mode = READ_STATUS_REG;
41125cf3198SRaphael Gault 		} else {
41225cf3198SRaphael Gault 			pr_debug("CFI flash: BUFFER_WRITE: expected CONFIRM(0xd0), got 0x%x @ 0x%llx",
41325cf3198SRaphael Gault 				 command, faddr);
41425cf3198SRaphael Gault 			sfdev->sr |= CFI_STATUS_PROGRAM_LOCK_BIT;
41525cf3198SRaphael Gault 		}
41625cf3198SRaphael Gault 		sfdev->state = READY;
41725cf3198SRaphael Gault 		break;
41825cf3198SRaphael Gault 
41925cf3198SRaphael Gault 	case BUFFERED_PROGRAM_SETUP:
42025cf3198SRaphael Gault 		sfdev->buffer_length = (command + 1) * CFI_BUS_WIDTH;
42125cf3198SRaphael Gault 		if (sfdev->buffer_length > PROGRAM_BUFF_SIZE)
42225cf3198SRaphael Gault 			sfdev->buffer_length = PROGRAM_BUFF_SIZE;
42325cf3198SRaphael Gault 		sfdev->state = BUFFER_WRITE;
42425cf3198SRaphael Gault 		sfdev->read_mode = READ_STATUS_REG;
42525cf3198SRaphael Gault 		break;
42625cf3198SRaphael Gault 
42725cf3198SRaphael Gault 	case ERASE_BLOCK_SETUP:
42825cf3198SRaphael Gault 		if ((command & 0xff) == CFI_CMD_CONFIRM)
42925cf3198SRaphael Gault 			block_erase_confirm(sfdev, faddr);
43025cf3198SRaphael Gault 		else
43125cf3198SRaphael Gault 			sfdev->sr |= CFI_STATUS_ERASE_ERROR;
43225cf3198SRaphael Gault 
43325cf3198SRaphael Gault 		sfdev->state = READY;
43425cf3198SRaphael Gault 		sfdev->read_mode = READ_STATUS_REG;
43525cf3198SRaphael Gault 		break;
43625cf3198SRaphael Gault 	default:
43725cf3198SRaphael Gault 		pr_debug("CFI flash: unexpected/unknown command 0x%x", command);
43825cf3198SRaphael Gault 		break;
43925cf3198SRaphael Gault 	}
44025cf3198SRaphael Gault }
44125cf3198SRaphael Gault 
442*d632faceSAndre Przywara /*
443*d632faceSAndre Przywara  * If we are in ARRAY_READ mode, we can map the flash array directly
444*d632faceSAndre Przywara  * into the guest, just as read-only. This greatly improves read
445*d632faceSAndre Przywara  * performance, and avoids problems with exits due to accesses from
446*d632faceSAndre Przywara  * load instructions without syndrome information (on ARM).
447*d632faceSAndre Przywara  * Also it could allow code to be executed XIP in there.
448*d632faceSAndre Przywara  */
map_flash_memory(struct kvm * kvm,struct cfi_flash_device * sfdev)449*d632faceSAndre Przywara static int map_flash_memory(struct kvm *kvm, struct cfi_flash_device *sfdev)
450*d632faceSAndre Przywara {
451*d632faceSAndre Przywara 	int ret;
452*d632faceSAndre Przywara 
453*d632faceSAndre Przywara 	ret = kvm__register_mem(kvm, sfdev->base_addr, sfdev->size,
454*d632faceSAndre Przywara 				sfdev->flash_memory,
455*d632faceSAndre Przywara 				KVM_MEM_TYPE_RAM | KVM_MEM_TYPE_READONLY);
456*d632faceSAndre Przywara 	if (!ret)
457*d632faceSAndre Przywara 		sfdev->is_mapped = true;
458*d632faceSAndre Przywara 
459*d632faceSAndre Przywara 	return ret;
460*d632faceSAndre Przywara }
461*d632faceSAndre Przywara 
462*d632faceSAndre Przywara /*
463*d632faceSAndre Przywara  * Any write access changing the read mode would need to bring us back to
464*d632faceSAndre Przywara  * "trap everything", as the CFI query read need proper handholding.
465*d632faceSAndre Przywara  */
unmap_flash_memory(struct kvm * kvm,struct cfi_flash_device * sfdev)466*d632faceSAndre Przywara static int unmap_flash_memory(struct kvm *kvm, struct cfi_flash_device *sfdev)
467*d632faceSAndre Przywara {
468*d632faceSAndre Przywara 	int ret;
469*d632faceSAndre Przywara 
470*d632faceSAndre Przywara 	ret = kvm__destroy_mem(kvm, sfdev->base_addr, sfdev->size,
471*d632faceSAndre Przywara 			       sfdev->flash_memory);
472*d632faceSAndre Przywara 
473*d632faceSAndre Przywara 	if (!ret)
474*d632faceSAndre Przywara 		sfdev->is_mapped = false;
475*d632faceSAndre Przywara 
476*d632faceSAndre Przywara 	return ret;
477*d632faceSAndre Przywara }
478*d632faceSAndre Przywara 
cfi_flash_mmio(struct kvm_cpu * vcpu,u64 addr,u8 * data,u32 len,u8 is_write,void * context)47925cf3198SRaphael Gault static void cfi_flash_mmio(struct kvm_cpu *vcpu,
48025cf3198SRaphael Gault 			   u64 addr, u8 *data, u32 len, u8 is_write,
48125cf3198SRaphael Gault 			   void *context)
48225cf3198SRaphael Gault {
48325cf3198SRaphael Gault 	struct cfi_flash_device *sfdev = context;
48425cf3198SRaphael Gault 	u64 faddr = addr - sfdev->base_addr;
48525cf3198SRaphael Gault 	u32 value;
48625cf3198SRaphael Gault 
48725cf3198SRaphael Gault 	if (!is_write) {
48825cf3198SRaphael Gault 		mutex_lock(&sfdev->mutex);
48925cf3198SRaphael Gault 
49025cf3198SRaphael Gault 		cfi_flash_read(sfdev, faddr, data, len);
49125cf3198SRaphael Gault 
49225cf3198SRaphael Gault 		mutex_unlock(&sfdev->mutex);
49325cf3198SRaphael Gault 
49425cf3198SRaphael Gault 		return;
49525cf3198SRaphael Gault 	}
49625cf3198SRaphael Gault 
49725cf3198SRaphael Gault 	if (len > 4) {
49825cf3198SRaphael Gault 		pr_info("CFI flash: MMIO %d-bit write access not supported",
49925cf3198SRaphael Gault 			 len * 8);
50025cf3198SRaphael Gault 		return;
50125cf3198SRaphael Gault 	}
50225cf3198SRaphael Gault 
50325cf3198SRaphael Gault 	memcpy(&value, data, len);
50425cf3198SRaphael Gault 
50525cf3198SRaphael Gault 	mutex_lock(&sfdev->mutex);
50625cf3198SRaphael Gault 
50725cf3198SRaphael Gault 	cfi_flash_write(sfdev, value & 0xffff, faddr, data, len);
50825cf3198SRaphael Gault 
509*d632faceSAndre Przywara 	/* Adjust our mapping status accordingly. */
510*d632faceSAndre Przywara 	if (!sfdev->is_mapped && sfdev->read_mode == READ_ARRAY)
511*d632faceSAndre Przywara 		map_flash_memory(vcpu->kvm, sfdev);
512*d632faceSAndre Przywara 	else if (sfdev->is_mapped && sfdev->read_mode != READ_ARRAY)
513*d632faceSAndre Przywara 		unmap_flash_memory(vcpu->kvm, sfdev);
514*d632faceSAndre Przywara 
51525cf3198SRaphael Gault 	mutex_unlock(&sfdev->mutex);
51625cf3198SRaphael Gault }
51725cf3198SRaphael Gault 
51825cf3198SRaphael Gault #ifdef CONFIG_HAS_LIBFDT
generate_cfi_flash_fdt_node(void * fdt,struct device_header * dev_hdr,void (* generate_irq_prop)(void * fdt,u8 irq,enum irq_type))51925cf3198SRaphael Gault static void generate_cfi_flash_fdt_node(void *fdt,
52025cf3198SRaphael Gault 					struct device_header *dev_hdr,
52125cf3198SRaphael Gault 					void (*generate_irq_prop)(void *fdt,
52225cf3198SRaphael Gault 								  u8 irq,
52325cf3198SRaphael Gault 								enum irq_type))
52425cf3198SRaphael Gault {
52525cf3198SRaphael Gault 	struct cfi_flash_device *sfdev;
52625cf3198SRaphael Gault 	u64 reg_prop[2];
52725cf3198SRaphael Gault 
52825cf3198SRaphael Gault 	sfdev = container_of(dev_hdr, struct cfi_flash_device, dev_hdr);
52925cf3198SRaphael Gault 	reg_prop[0] = cpu_to_fdt64(sfdev->base_addr);
53025cf3198SRaphael Gault 	reg_prop[1] = cpu_to_fdt64(sfdev->size);
53125cf3198SRaphael Gault 
53225cf3198SRaphael Gault 	_FDT(fdt_begin_node(fdt, "flash"));
53325cf3198SRaphael Gault 	_FDT(fdt_property_cell(fdt, "bank-width", CFI_BUS_WIDTH));
53425cf3198SRaphael Gault 	_FDT(fdt_property_cell(fdt, "#address-cells", 0x1));
53525cf3198SRaphael Gault 	_FDT(fdt_property_cell(fdt, "#size-cells", 0x1));
53625cf3198SRaphael Gault 	_FDT(fdt_property_string(fdt, "compatible", "cfi-flash"));
53725cf3198SRaphael Gault 	_FDT(fdt_property_string(fdt, "label", "System-firmware"));
53825cf3198SRaphael Gault 	_FDT(fdt_property(fdt, "reg", &reg_prop, sizeof(reg_prop)));
53925cf3198SRaphael Gault 	_FDT(fdt_end_node(fdt));
54025cf3198SRaphael Gault }
54125cf3198SRaphael Gault #else
54225cf3198SRaphael Gault #define generate_cfi_flash_fdt_node NULL
54325cf3198SRaphael Gault #endif
54425cf3198SRaphael Gault 
create_flash_device_file(struct kvm * kvm,const char * filename)54525cf3198SRaphael Gault static struct cfi_flash_device *create_flash_device_file(struct kvm *kvm,
54625cf3198SRaphael Gault 							 const char *filename)
54725cf3198SRaphael Gault {
54825cf3198SRaphael Gault 	struct cfi_flash_device *sfdev;
54925cf3198SRaphael Gault 	struct stat statbuf;
55025cf3198SRaphael Gault 	unsigned int value;
55125cf3198SRaphael Gault 	int ret;
55225cf3198SRaphael Gault 	int fd;
55325cf3198SRaphael Gault 
55425cf3198SRaphael Gault 	fd = open(filename, O_RDWR);
55525cf3198SRaphael Gault 	if (fd < 0)
55625cf3198SRaphael Gault 		return ERR_PTR(-errno);
55725cf3198SRaphael Gault 
55825cf3198SRaphael Gault 	if (fstat(fd, &statbuf) < 0) {
55925cf3198SRaphael Gault 		ret = -errno;
56025cf3198SRaphael Gault 		goto out_close;
56125cf3198SRaphael Gault 	}
56225cf3198SRaphael Gault 
56325cf3198SRaphael Gault 	sfdev = malloc(sizeof(struct cfi_flash_device));
56425cf3198SRaphael Gault 	if (!sfdev) {
56525cf3198SRaphael Gault 		ret = -ENOMEM;
56625cf3198SRaphael Gault 		goto out_close;
56725cf3198SRaphael Gault 	}
56825cf3198SRaphael Gault 
56925cf3198SRaphael Gault 	sfdev->size = statbuf.st_size;
57025cf3198SRaphael Gault 	/* Round down to nearest power-of-2 size value. */
57125cf3198SRaphael Gault 	sfdev->size = 1U << (pow2_size(sfdev->size + 1) - 1);
57225cf3198SRaphael Gault 	if (sfdev->size > KVM_FLASH_MAX_SIZE)
57325cf3198SRaphael Gault 		sfdev->size = KVM_FLASH_MAX_SIZE;
57425cf3198SRaphael Gault 	if (sfdev->size < statbuf.st_size) {
57525cf3198SRaphael Gault 		pr_info("flash file size (%llu bytes) is not a power of two",
57625cf3198SRaphael Gault 			(unsigned long long)statbuf.st_size);
57725cf3198SRaphael Gault 		pr_info("only using first %u bytes", sfdev->size);
57825cf3198SRaphael Gault 	}
57925cf3198SRaphael Gault 	sfdev->flash_memory = mmap(NULL, sfdev->size,
58025cf3198SRaphael Gault 				   PROT_READ | PROT_WRITE, MAP_SHARED,
58125cf3198SRaphael Gault 				   fd, 0);
58225cf3198SRaphael Gault 	if (sfdev->flash_memory == MAP_FAILED) {
58325cf3198SRaphael Gault 		ret = -errno;
58425cf3198SRaphael Gault 		goto out_free;
58525cf3198SRaphael Gault 	}
58625cf3198SRaphael Gault 	sfdev->base_addr = KVM_FLASH_MMIO_BASE;
58725cf3198SRaphael Gault 	sfdev->state = READY;
58825cf3198SRaphael Gault 	sfdev->read_mode = READ_ARRAY;
58925cf3198SRaphael Gault 	sfdev->sr = CFI_STATUS_READY;
59025cf3198SRaphael Gault 
591*d632faceSAndre Przywara 	map_flash_memory(kvm, sfdev);
592*d632faceSAndre Przywara 
59325cf3198SRaphael Gault 	value = roundup(nr_erase_blocks(sfdev), BITS_PER_LONG) / 8;
59425cf3198SRaphael Gault 	sfdev->lock_bm = malloc(value);
59525cf3198SRaphael Gault 	memset(sfdev->lock_bm, 0, value);
59625cf3198SRaphael Gault 
59725cf3198SRaphael Gault 	sfdev->dev_hdr.bus_type = DEVICE_BUS_MMIO;
59825cf3198SRaphael Gault 	sfdev->dev_hdr.data = generate_cfi_flash_fdt_node;
59925cf3198SRaphael Gault 	mutex_init(&sfdev->mutex);
60025cf3198SRaphael Gault 	ret = device__register(&sfdev->dev_hdr);
60125cf3198SRaphael Gault 	if (ret)
60225cf3198SRaphael Gault 		goto out_unmap;
60325cf3198SRaphael Gault 
60425cf3198SRaphael Gault 	ret = kvm__register_mmio(kvm,
60525cf3198SRaphael Gault 				 sfdev->base_addr, sfdev->size,
60625cf3198SRaphael Gault 				 false, cfi_flash_mmio, sfdev);
60725cf3198SRaphael Gault 	if (ret) {
60825cf3198SRaphael Gault 		device__unregister(&sfdev->dev_hdr);
60925cf3198SRaphael Gault 		goto out_unmap;
61025cf3198SRaphael Gault 	}
61125cf3198SRaphael Gault 
61225cf3198SRaphael Gault 	return sfdev;
61325cf3198SRaphael Gault 
61425cf3198SRaphael Gault out_unmap:
61525cf3198SRaphael Gault 	munmap(sfdev->flash_memory, sfdev->size);
61625cf3198SRaphael Gault out_free:
61725cf3198SRaphael Gault 	free(sfdev);
61825cf3198SRaphael Gault out_close:
61925cf3198SRaphael Gault 	close(fd);
62025cf3198SRaphael Gault 
62125cf3198SRaphael Gault 	return ERR_PTR(ret);
62225cf3198SRaphael Gault }
62325cf3198SRaphael Gault 
cfi_flash__init(struct kvm * kvm)62425cf3198SRaphael Gault static int cfi_flash__init(struct kvm *kvm)
62525cf3198SRaphael Gault {
62625cf3198SRaphael Gault 	struct cfi_flash_device *sfdev;
62725cf3198SRaphael Gault 
62825cf3198SRaphael Gault 	BUILD_BUG_ON(CFI_NR_FLASH_CHIPS != 1 && CFI_NR_FLASH_CHIPS != 2);
62925cf3198SRaphael Gault 
63025cf3198SRaphael Gault 	if (!kvm->cfg.flash_filename)
63125cf3198SRaphael Gault 		return 0;
63225cf3198SRaphael Gault 
63325cf3198SRaphael Gault 	sfdev = create_flash_device_file(kvm, kvm->cfg.flash_filename);
63425cf3198SRaphael Gault 	if (IS_ERR(sfdev))
63525cf3198SRaphael Gault 		return PTR_ERR(sfdev);
63625cf3198SRaphael Gault 
63725cf3198SRaphael Gault 	return 0;
63825cf3198SRaphael Gault }
63925cf3198SRaphael Gault dev_init(cfi_flash__init);
640