^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");