Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0+
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  * EEPROM driver for RAVE SP
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  * Copyright (C) 2018 Zodiac Inflight Innovations
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10) #include <linux/mfd/rave-sp.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12) #include <linux/nvmem-provider.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13) #include <linux/of_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) #include <linux/platform_device.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/sizes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18)  * enum rave_sp_eeprom_access_type - Supported types of EEPROM access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20)  * @RAVE_SP_EEPROM_WRITE:	EEPROM write
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21)  * @RAVE_SP_EEPROM_READ:	EEPROM read
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) enum rave_sp_eeprom_access_type {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 	RAVE_SP_EEPROM_WRITE = 0,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 	RAVE_SP_EEPROM_READ  = 1,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29)  * enum rave_sp_eeprom_header_size - EEPROM command header sizes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31)  * @RAVE_SP_EEPROM_HEADER_SMALL: EEPROM header size for "small" devices (< 8K)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32)  * @RAVE_SP_EEPROM_HEADER_BIG:	 EEPROM header size for "big" devices (> 8K)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) enum rave_sp_eeprom_header_size {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	RAVE_SP_EEPROM_HEADER_SMALL = 4U,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	RAVE_SP_EEPROM_HEADER_BIG   = 5U,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) #define RAVE_SP_EEPROM_HEADER_MAX	RAVE_SP_EEPROM_HEADER_BIG
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) #define	RAVE_SP_EEPROM_PAGE_SIZE	32U
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43)  * struct rave_sp_eeprom_page - RAVE SP EEPROM page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45)  * @type:	Access type (see enum rave_sp_eeprom_access_type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46)  * @success:	Success flag (Success = 1, Failure = 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47)  * @data:	Read data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49)  * Note this structure corresponds to RSP_*_EEPROM payload from RAVE
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50)  * SP ICD
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) struct rave_sp_eeprom_page {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 	u8  type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 	u8  success;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 	u8  data[RAVE_SP_EEPROM_PAGE_SIZE];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) } __packed;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59)  * struct rave_sp_eeprom - RAVE SP EEPROM device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61)  * @sp:			Pointer to parent RAVE SP device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62)  * @mutex:		Lock protecting access to EEPROM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63)  * @address:		EEPROM device address
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64)  * @header_size:	Size of EEPROM command header for this device
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65)  * @dev:		Pointer to corresponding struct device used for logging
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) struct rave_sp_eeprom {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 	struct rave_sp *sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 	struct mutex mutex;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 	u8 address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) 	unsigned int header_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 	struct device *dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76)  * rave_sp_eeprom_io - Low-level part of EEPROM page access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78)  * @eeprom:	EEPROM device to write to
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79)  * @type:	EEPROM access type (read or write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80)  * @idx:	number of the EEPROM page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81)  * @page:	Data to write or buffer to store result (via page->data)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83)  * This function does all of the low-level work required to perform a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84)  * EEPROM access. This includes formatting correct command payload,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85)  * sending it and checking received results.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87)  * Returns zero in case of success or negative error code in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88)  * case of failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) static int rave_sp_eeprom_io(struct rave_sp_eeprom *eeprom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 			     enum rave_sp_eeprom_access_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) 			     u16 idx,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 			     struct rave_sp_eeprom_page *page)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) 	const bool is_write = type == RAVE_SP_EEPROM_WRITE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) 	const unsigned int data_size = is_write ? sizeof(page->data) : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 	const unsigned int cmd_size = eeprom->header_size + data_size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 	const unsigned int rsp_size =
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 		is_write ? sizeof(*page) - sizeof(page->data) : sizeof(*page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 	unsigned int offset = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) 	u8 cmd[RAVE_SP_EEPROM_HEADER_MAX + sizeof(page->data)];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 	if (WARN_ON(cmd_size > sizeof(cmd)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 	cmd[offset++] = eeprom->address;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 	cmd[offset++] = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 	cmd[offset++] = type;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 	cmd[offset++] = idx;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 	 * If there's still room in this command's header it means we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 	 * are talkin to EEPROM that uses 16-bit page numbers and we
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 	 * have to specify index's MSB in payload as well.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 	if (offset < eeprom->header_size)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		cmd[offset++] = idx >> 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 	 * Copy our data to write to command buffer first. In case of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 	 * a read data_size should be zero and memcpy would become a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 	 * no-op
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 	memcpy(&cmd[offset], page->data, data_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 	ret = rave_sp_exec(eeprom->sp, cmd, cmd_size, page, rsp_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 	if (page->type != type)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 		return -EPROTO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 	if (!page->success)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 		return -EIO;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140)  * rave_sp_eeprom_page_access - Access single EEPROM page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)  * @eeprom:	EEPROM device to access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143)  * @type:	Access type to perform (read or write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144)  * @offset:	Offset within EEPROM to access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)  * @data:	Data buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146)  * @data_len:	Size of the data buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148)  * This function performs a generic access to a single page or a
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)  * portion thereof. Requested access MUST NOT cross the EEPROM page
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150)  * boundary.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)  * Returns zero in case of success or negative error code in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153)  * case of failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) static int
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) rave_sp_eeprom_page_access(struct rave_sp_eeprom *eeprom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 			   enum rave_sp_eeprom_access_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			   unsigned int offset, u8 *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			   size_t data_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 	const unsigned int page_offset = offset % RAVE_SP_EEPROM_PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 	const unsigned int page_nr     = offset / RAVE_SP_EEPROM_PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 	struct rave_sp_eeprom_page page;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 	 * This function will not work if data access we've been asked
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 	 * to do is crossing EEPROM page boundary. Normally this
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 	 * should never happen and getting here would indicate a bug
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 	 * in the code.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 	if (WARN_ON(data_len > sizeof(page.data) - page_offset))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 	if (type == RAVE_SP_EEPROM_WRITE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 		 * If doing a partial write we need to do a read first
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		 * to fill the rest of the page with correct data.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		if (data_len < RAVE_SP_EEPROM_PAGE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) 			ret = rave_sp_eeprom_io(eeprom, RAVE_SP_EEPROM_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 						page_nr, &page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) 			if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) 				return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		memcpy(&page.data[page_offset], data, data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 	ret = rave_sp_eeprom_io(eeprom, type, page_nr, &page);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 	if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 		return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 	 * Since we receive the result of the read via 'page.data'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 	 * buffer we need to copy that to 'data'
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 	if (type == RAVE_SP_EEPROM_READ)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 		memcpy(data, &page.data[page_offset], data_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 	return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) /**
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205)  * rave_sp_eeprom_access - Access EEPROM data
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)  * @eeprom:	EEPROM device to access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208)  * @type:	Access type to perform (read or write)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209)  * @offset:	Offset within EEPROM to access
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210)  * @data:	Data buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211)  * @data_len:	Size of the data buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213)  * This function performs a generic access (either read or write) at
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214)  * arbitrary offset (not necessary page aligned) of arbitrary length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215)  * (is not constrained by EEPROM page size).
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217)  * Returns zero in case of success or negative error code in case of
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218)  * failure.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) static int rave_sp_eeprom_access(struct rave_sp_eeprom *eeprom,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 				 enum rave_sp_eeprom_access_type type,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 				 unsigned int offset, u8 *data,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 				 unsigned int data_len)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 	unsigned int residue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 	unsigned int chunk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 	unsigned int head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 	int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 	mutex_lock(&eeprom->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 	head    = offset % RAVE_SP_EEPROM_PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 	residue = data_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 	do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 		 * First iteration, if we are doing an access that is
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 		 * not 32-byte aligned, we need to access only data up
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		 * to a page boundary to avoid corssing it in
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) 		 * rave_sp_eeprom_page_access()
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) 		if (unlikely(head)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 			chunk = RAVE_SP_EEPROM_PAGE_SIZE - head;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 			/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 			 * This can only happen once per
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 			 * rave_sp_eeprom_access() call, so we set
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 			 * head to zero to process all the other
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 			 * iterations normally.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 			 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 			head  = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 			chunk = RAVE_SP_EEPROM_PAGE_SIZE;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 		/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 		 * We should never read more that 'residue' bytes
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 		 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 		chunk = min(chunk, residue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 		ret = rave_sp_eeprom_page_access(eeprom, type, offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 						 data, chunk);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 		if (ret)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 			goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 		residue -= chunk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		offset  += chunk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 		data    += chunk;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 	} while (residue);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 	mutex_unlock(&eeprom->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 	return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) static int rave_sp_eeprom_reg_read(void *eeprom, unsigned int offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 				   void *val, size_t bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 	return rave_sp_eeprom_access(eeprom, RAVE_SP_EEPROM_READ,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 				     offset, val, bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) static int rave_sp_eeprom_reg_write(void *eeprom, unsigned int offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 				    void *val, size_t bytes)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 	return rave_sp_eeprom_access(eeprom, RAVE_SP_EEPROM_WRITE,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 				     offset, val, bytes);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) static int rave_sp_eeprom_probe(struct platform_device *pdev)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 	struct device *dev = &pdev->dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 	struct rave_sp *sp = dev_get_drvdata(dev->parent);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 	struct device_node *np = dev->of_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 	struct nvmem_config config = { 0 };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 	struct rave_sp_eeprom *eeprom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 	struct nvmem_device *nvmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 	u32 reg[2], size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 	if (of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg))) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		dev_err(dev, "Failed to parse \"reg\" property\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) 	size = reg[1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 	/*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) 	 * Per ICD, we have no more than 2 bytes to specify EEPROM
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 	 * page.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 	 */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) 	if (size > U16_MAX * RAVE_SP_EEPROM_PAGE_SIZE) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 		dev_err(dev, "Specified size is too big\n");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 		return -EINVAL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	eeprom = devm_kzalloc(dev, sizeof(*eeprom), GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	if (!eeprom)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 		return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	eeprom->address = reg[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	eeprom->sp      = sp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	eeprom->dev     = dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 	if (size > SZ_8K)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		eeprom->header_size = RAVE_SP_EEPROM_HEADER_BIG;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		eeprom->header_size = RAVE_SP_EEPROM_HEADER_SMALL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 	mutex_init(&eeprom->mutex);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 	config.id		= -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	of_property_read_string(np, "zii,eeprom-name", &config.name);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 	config.priv		= eeprom;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 	config.dev		= dev;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 	config.size		= size;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 	config.reg_read		= rave_sp_eeprom_reg_read;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 	config.reg_write	= rave_sp_eeprom_reg_write;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 	config.word_size	= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 	config.stride		= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 	nvmem = devm_nvmem_register(dev, &config);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 	return PTR_ERR_OR_ZERO(nvmem);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) static const struct of_device_id rave_sp_eeprom_of_match[] = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	{ .compatible = "zii,rave-sp-eeprom" },
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 	{}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) MODULE_DEVICE_TABLE(of, rave_sp_eeprom_of_match);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) static struct platform_driver rave_sp_eeprom_driver = {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 	.probe = rave_sp_eeprom_probe,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 	.driver	= {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 		.name = KBUILD_MODNAME,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		.of_match_table = rave_sp_eeprom_of_match,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 	},
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) module_platform_driver(rave_sp_eeprom_driver);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) MODULE_AUTHOR("Andrey Vostrikov <andrey.vostrikov@cogentembedded.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) MODULE_AUTHOR("Nikita Yushchenko <nikita.yoush@cogentembedded.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) MODULE_DESCRIPTION("RAVE SP EEPROM driver");