13b51f47bSAndrey Smirnov // SPDX-License-Identifier: GPL-2.0+
23b51f47bSAndrey Smirnov
33b51f47bSAndrey Smirnov /*
43b51f47bSAndrey Smirnov * EEPROM driver for RAVE SP
53b51f47bSAndrey Smirnov *
63b51f47bSAndrey Smirnov * Copyright (C) 2018 Zodiac Inflight Innovations
73b51f47bSAndrey Smirnov *
83b51f47bSAndrey Smirnov */
93b51f47bSAndrey Smirnov #include <linux/kernel.h>
103b51f47bSAndrey Smirnov #include <linux/mfd/rave-sp.h>
113b51f47bSAndrey Smirnov #include <linux/module.h>
123b51f47bSAndrey Smirnov #include <linux/nvmem-provider.h>
139bf75da0SRob Herring #include <linux/of.h>
143b51f47bSAndrey Smirnov #include <linux/platform_device.h>
153b51f47bSAndrey Smirnov #include <linux/sizes.h>
163b51f47bSAndrey Smirnov
173b51f47bSAndrey Smirnov /**
183b51f47bSAndrey Smirnov * enum rave_sp_eeprom_access_type - Supported types of EEPROM access
193b51f47bSAndrey Smirnov *
203b51f47bSAndrey Smirnov * @RAVE_SP_EEPROM_WRITE: EEPROM write
213b51f47bSAndrey Smirnov * @RAVE_SP_EEPROM_READ: EEPROM read
223b51f47bSAndrey Smirnov */
233b51f47bSAndrey Smirnov enum rave_sp_eeprom_access_type {
243b51f47bSAndrey Smirnov RAVE_SP_EEPROM_WRITE = 0,
253b51f47bSAndrey Smirnov RAVE_SP_EEPROM_READ = 1,
263b51f47bSAndrey Smirnov };
273b51f47bSAndrey Smirnov
283b51f47bSAndrey Smirnov /**
293b51f47bSAndrey Smirnov * enum rave_sp_eeprom_header_size - EEPROM command header sizes
303b51f47bSAndrey Smirnov *
313b51f47bSAndrey Smirnov * @RAVE_SP_EEPROM_HEADER_SMALL: EEPROM header size for "small" devices (< 8K)
323b51f47bSAndrey Smirnov * @RAVE_SP_EEPROM_HEADER_BIG: EEPROM header size for "big" devices (> 8K)
333b51f47bSAndrey Smirnov */
343b51f47bSAndrey Smirnov enum rave_sp_eeprom_header_size {
353b51f47bSAndrey Smirnov RAVE_SP_EEPROM_HEADER_SMALL = 4U,
363b51f47bSAndrey Smirnov RAVE_SP_EEPROM_HEADER_BIG = 5U,
373b51f47bSAndrey Smirnov };
3826d79b82SKees Cook #define RAVE_SP_EEPROM_HEADER_MAX RAVE_SP_EEPROM_HEADER_BIG
393b51f47bSAndrey Smirnov
403b51f47bSAndrey Smirnov #define RAVE_SP_EEPROM_PAGE_SIZE 32U
413b51f47bSAndrey Smirnov
423b51f47bSAndrey Smirnov /**
433b51f47bSAndrey Smirnov * struct rave_sp_eeprom_page - RAVE SP EEPROM page
443b51f47bSAndrey Smirnov *
453b51f47bSAndrey Smirnov * @type: Access type (see enum rave_sp_eeprom_access_type)
463b51f47bSAndrey Smirnov * @success: Success flag (Success = 1, Failure = 0)
473b51f47bSAndrey Smirnov * @data: Read data
483e5ac22aSRandy Dunlap *
493b51f47bSAndrey Smirnov * Note this structure corresponds to RSP_*_EEPROM payload from RAVE
503b51f47bSAndrey Smirnov * SP ICD
513b51f47bSAndrey Smirnov */
523b51f47bSAndrey Smirnov struct rave_sp_eeprom_page {
533b51f47bSAndrey Smirnov u8 type;
543b51f47bSAndrey Smirnov u8 success;
553b51f47bSAndrey Smirnov u8 data[RAVE_SP_EEPROM_PAGE_SIZE];
563b51f47bSAndrey Smirnov } __packed;
573b51f47bSAndrey Smirnov
583b51f47bSAndrey Smirnov /**
593b51f47bSAndrey Smirnov * struct rave_sp_eeprom - RAVE SP EEPROM device
603b51f47bSAndrey Smirnov *
613b51f47bSAndrey Smirnov * @sp: Pointer to parent RAVE SP device
623b51f47bSAndrey Smirnov * @mutex: Lock protecting access to EEPROM
633b51f47bSAndrey Smirnov * @address: EEPROM device address
643b51f47bSAndrey Smirnov * @header_size: Size of EEPROM command header for this device
653b51f47bSAndrey Smirnov * @dev: Pointer to corresponding struct device used for logging
663b51f47bSAndrey Smirnov */
673b51f47bSAndrey Smirnov struct rave_sp_eeprom {
683b51f47bSAndrey Smirnov struct rave_sp *sp;
693b51f47bSAndrey Smirnov struct mutex mutex;
703b51f47bSAndrey Smirnov u8 address;
713b51f47bSAndrey Smirnov unsigned int header_size;
723b51f47bSAndrey Smirnov struct device *dev;
733b51f47bSAndrey Smirnov };
743b51f47bSAndrey Smirnov
753b51f47bSAndrey Smirnov /**
763b51f47bSAndrey Smirnov * rave_sp_eeprom_io - Low-level part of EEPROM page access
773b51f47bSAndrey Smirnov *
783b51f47bSAndrey Smirnov * @eeprom: EEPROM device to write to
793b51f47bSAndrey Smirnov * @type: EEPROM access type (read or write)
803b51f47bSAndrey Smirnov * @idx: number of the EEPROM page
813b51f47bSAndrey Smirnov * @page: Data to write or buffer to store result (via page->data)
823b51f47bSAndrey Smirnov *
833b51f47bSAndrey Smirnov * This function does all of the low-level work required to perform a
843b51f47bSAndrey Smirnov * EEPROM access. This includes formatting correct command payload,
853b51f47bSAndrey Smirnov * sending it and checking received results.
863b51f47bSAndrey Smirnov *
873b51f47bSAndrey Smirnov * Returns zero in case of success or negative error code in
883b51f47bSAndrey Smirnov * case of failure.
893b51f47bSAndrey Smirnov */
rave_sp_eeprom_io(struct rave_sp_eeprom * eeprom,enum rave_sp_eeprom_access_type type,u16 idx,struct rave_sp_eeprom_page * page)903b51f47bSAndrey Smirnov static int rave_sp_eeprom_io(struct rave_sp_eeprom *eeprom,
913b51f47bSAndrey Smirnov enum rave_sp_eeprom_access_type type,
923b51f47bSAndrey Smirnov u16 idx,
933b51f47bSAndrey Smirnov struct rave_sp_eeprom_page *page)
943b51f47bSAndrey Smirnov {
953b51f47bSAndrey Smirnov const bool is_write = type == RAVE_SP_EEPROM_WRITE;
963b51f47bSAndrey Smirnov const unsigned int data_size = is_write ? sizeof(page->data) : 0;
973b51f47bSAndrey Smirnov const unsigned int cmd_size = eeprom->header_size + data_size;
983b51f47bSAndrey Smirnov const unsigned int rsp_size =
993b51f47bSAndrey Smirnov is_write ? sizeof(*page) - sizeof(page->data) : sizeof(*page);
1003b51f47bSAndrey Smirnov unsigned int offset = 0;
10126d79b82SKees Cook u8 cmd[RAVE_SP_EEPROM_HEADER_MAX + sizeof(page->data)];
1023b51f47bSAndrey Smirnov int ret;
1033b51f47bSAndrey Smirnov
10426d79b82SKees Cook if (WARN_ON(cmd_size > sizeof(cmd)))
10526d79b82SKees Cook return -EINVAL;
10626d79b82SKees Cook
1073b51f47bSAndrey Smirnov cmd[offset++] = eeprom->address;
1083b51f47bSAndrey Smirnov cmd[offset++] = 0;
1093b51f47bSAndrey Smirnov cmd[offset++] = type;
1103b51f47bSAndrey Smirnov cmd[offset++] = idx;
1113b51f47bSAndrey Smirnov
1123b51f47bSAndrey Smirnov /*
1133b51f47bSAndrey Smirnov * If there's still room in this command's header it means we
1143b51f47bSAndrey Smirnov * are talkin to EEPROM that uses 16-bit page numbers and we
1153b51f47bSAndrey Smirnov * have to specify index's MSB in payload as well.
1163b51f47bSAndrey Smirnov */
1173b51f47bSAndrey Smirnov if (offset < eeprom->header_size)
1183b51f47bSAndrey Smirnov cmd[offset++] = idx >> 8;
1193b51f47bSAndrey Smirnov /*
1203b51f47bSAndrey Smirnov * Copy our data to write to command buffer first. In case of
1213b51f47bSAndrey Smirnov * a read data_size should be zero and memcpy would become a
1223b51f47bSAndrey Smirnov * no-op
1233b51f47bSAndrey Smirnov */
1243b51f47bSAndrey Smirnov memcpy(&cmd[offset], page->data, data_size);
1253b51f47bSAndrey Smirnov
1263b51f47bSAndrey Smirnov ret = rave_sp_exec(eeprom->sp, cmd, cmd_size, page, rsp_size);
1273b51f47bSAndrey Smirnov if (ret)
1283b51f47bSAndrey Smirnov return ret;
1293b51f47bSAndrey Smirnov
1303b51f47bSAndrey Smirnov if (page->type != type)
1313b51f47bSAndrey Smirnov return -EPROTO;
1323b51f47bSAndrey Smirnov
1333b51f47bSAndrey Smirnov if (!page->success)
1343b51f47bSAndrey Smirnov return -EIO;
1353b51f47bSAndrey Smirnov
1363b51f47bSAndrey Smirnov return 0;
1373b51f47bSAndrey Smirnov }
1383b51f47bSAndrey Smirnov
1393b51f47bSAndrey Smirnov /**
1403b51f47bSAndrey Smirnov * rave_sp_eeprom_page_access - Access single EEPROM page
1413b51f47bSAndrey Smirnov *
1423b51f47bSAndrey Smirnov * @eeprom: EEPROM device to access
1433b51f47bSAndrey Smirnov * @type: Access type to perform (read or write)
1443b51f47bSAndrey Smirnov * @offset: Offset within EEPROM to access
1453b51f47bSAndrey Smirnov * @data: Data buffer
1463b51f47bSAndrey Smirnov * @data_len: Size of the data buffer
1473b51f47bSAndrey Smirnov *
1483b51f47bSAndrey Smirnov * This function performs a generic access to a single page or a
1493b51f47bSAndrey Smirnov * portion thereof. Requested access MUST NOT cross the EEPROM page
1503b51f47bSAndrey Smirnov * boundary.
1513b51f47bSAndrey Smirnov *
1523b51f47bSAndrey Smirnov * Returns zero in case of success or negative error code in
1533b51f47bSAndrey Smirnov * case of failure.
1543b51f47bSAndrey Smirnov */
1553b51f47bSAndrey Smirnov static int
rave_sp_eeprom_page_access(struct rave_sp_eeprom * eeprom,enum rave_sp_eeprom_access_type type,unsigned int offset,u8 * data,size_t data_len)1563b51f47bSAndrey Smirnov rave_sp_eeprom_page_access(struct rave_sp_eeprom *eeprom,
1573b51f47bSAndrey Smirnov enum rave_sp_eeprom_access_type type,
1583b51f47bSAndrey Smirnov unsigned int offset, u8 *data,
1593b51f47bSAndrey Smirnov size_t data_len)
1603b51f47bSAndrey Smirnov {
1613b51f47bSAndrey Smirnov const unsigned int page_offset = offset % RAVE_SP_EEPROM_PAGE_SIZE;
1623b51f47bSAndrey Smirnov const unsigned int page_nr = offset / RAVE_SP_EEPROM_PAGE_SIZE;
1633b51f47bSAndrey Smirnov struct rave_sp_eeprom_page page;
1643b51f47bSAndrey Smirnov int ret;
1653b51f47bSAndrey Smirnov
1663b51f47bSAndrey Smirnov /*
1673b51f47bSAndrey Smirnov * This function will not work if data access we've been asked
1683b51f47bSAndrey Smirnov * to do is crossing EEPROM page boundary. Normally this
1693b51f47bSAndrey Smirnov * should never happen and getting here would indicate a bug
1703b51f47bSAndrey Smirnov * in the code.
1713b51f47bSAndrey Smirnov */
1723b51f47bSAndrey Smirnov if (WARN_ON(data_len > sizeof(page.data) - page_offset))
1733b51f47bSAndrey Smirnov return -EINVAL;
1743b51f47bSAndrey Smirnov
1753b51f47bSAndrey Smirnov if (type == RAVE_SP_EEPROM_WRITE) {
1763b51f47bSAndrey Smirnov /*
1773b51f47bSAndrey Smirnov * If doing a partial write we need to do a read first
1783b51f47bSAndrey Smirnov * to fill the rest of the page with correct data.
1793b51f47bSAndrey Smirnov */
1803b51f47bSAndrey Smirnov if (data_len < RAVE_SP_EEPROM_PAGE_SIZE) {
1813b51f47bSAndrey Smirnov ret = rave_sp_eeprom_io(eeprom, RAVE_SP_EEPROM_READ,
1823b51f47bSAndrey Smirnov page_nr, &page);
1833b51f47bSAndrey Smirnov if (ret)
1843b51f47bSAndrey Smirnov return ret;
1853b51f47bSAndrey Smirnov }
1863b51f47bSAndrey Smirnov
1873b51f47bSAndrey Smirnov memcpy(&page.data[page_offset], data, data_len);
1883b51f47bSAndrey Smirnov }
1893b51f47bSAndrey Smirnov
1903b51f47bSAndrey Smirnov ret = rave_sp_eeprom_io(eeprom, type, page_nr, &page);
1913b51f47bSAndrey Smirnov if (ret)
1923b51f47bSAndrey Smirnov return ret;
1933b51f47bSAndrey Smirnov
1943b51f47bSAndrey Smirnov /*
1953b51f47bSAndrey Smirnov * Since we receive the result of the read via 'page.data'
1963b51f47bSAndrey Smirnov * buffer we need to copy that to 'data'
1973b51f47bSAndrey Smirnov */
1983b51f47bSAndrey Smirnov if (type == RAVE_SP_EEPROM_READ)
1993b51f47bSAndrey Smirnov memcpy(data, &page.data[page_offset], data_len);
2003b51f47bSAndrey Smirnov
2013b51f47bSAndrey Smirnov return 0;
2023b51f47bSAndrey Smirnov }
2033b51f47bSAndrey Smirnov
2043b51f47bSAndrey Smirnov /**
2053b51f47bSAndrey Smirnov * rave_sp_eeprom_access - Access EEPROM data
2063b51f47bSAndrey Smirnov *
2073b51f47bSAndrey Smirnov * @eeprom: EEPROM device to access
2083b51f47bSAndrey Smirnov * @type: Access type to perform (read or write)
2093b51f47bSAndrey Smirnov * @offset: Offset within EEPROM to access
2103b51f47bSAndrey Smirnov * @data: Data buffer
2113b51f47bSAndrey Smirnov * @data_len: Size of the data buffer
2123b51f47bSAndrey Smirnov *
2133b51f47bSAndrey Smirnov * This function performs a generic access (either read or write) at
2143b51f47bSAndrey Smirnov * arbitrary offset (not necessary page aligned) of arbitrary length
2153b51f47bSAndrey Smirnov * (is not constrained by EEPROM page size).
2163b51f47bSAndrey Smirnov *
2173b51f47bSAndrey Smirnov * Returns zero in case of success or negative error code in case of
2183b51f47bSAndrey Smirnov * failure.
2193b51f47bSAndrey Smirnov */
rave_sp_eeprom_access(struct rave_sp_eeprom * eeprom,enum rave_sp_eeprom_access_type type,unsigned int offset,u8 * data,unsigned int data_len)2203b51f47bSAndrey Smirnov static int rave_sp_eeprom_access(struct rave_sp_eeprom *eeprom,
2213b51f47bSAndrey Smirnov enum rave_sp_eeprom_access_type type,
2223b51f47bSAndrey Smirnov unsigned int offset, u8 *data,
2233b51f47bSAndrey Smirnov unsigned int data_len)
2243b51f47bSAndrey Smirnov {
2253b51f47bSAndrey Smirnov unsigned int residue;
2263b51f47bSAndrey Smirnov unsigned int chunk;
2273b51f47bSAndrey Smirnov unsigned int head;
2283b51f47bSAndrey Smirnov int ret;
2293b51f47bSAndrey Smirnov
2303b51f47bSAndrey Smirnov mutex_lock(&eeprom->mutex);
2313b51f47bSAndrey Smirnov
2323b51f47bSAndrey Smirnov head = offset % RAVE_SP_EEPROM_PAGE_SIZE;
2333b51f47bSAndrey Smirnov residue = data_len;
2343b51f47bSAndrey Smirnov
2353b51f47bSAndrey Smirnov do {
2363b51f47bSAndrey Smirnov /*
2373b51f47bSAndrey Smirnov * First iteration, if we are doing an access that is
2383b51f47bSAndrey Smirnov * not 32-byte aligned, we need to access only data up
2393b51f47bSAndrey Smirnov * to a page boundary to avoid corssing it in
2403b51f47bSAndrey Smirnov * rave_sp_eeprom_page_access()
2413b51f47bSAndrey Smirnov */
2423b51f47bSAndrey Smirnov if (unlikely(head)) {
2433b51f47bSAndrey Smirnov chunk = RAVE_SP_EEPROM_PAGE_SIZE - head;
2443b51f47bSAndrey Smirnov /*
2453b51f47bSAndrey Smirnov * This can only happen once per
2463b51f47bSAndrey Smirnov * rave_sp_eeprom_access() call, so we set
2473b51f47bSAndrey Smirnov * head to zero to process all the other
2483b51f47bSAndrey Smirnov * iterations normally.
2493b51f47bSAndrey Smirnov */
2503b51f47bSAndrey Smirnov head = 0;
2513b51f47bSAndrey Smirnov } else {
2523b51f47bSAndrey Smirnov chunk = RAVE_SP_EEPROM_PAGE_SIZE;
2533b51f47bSAndrey Smirnov }
2543b51f47bSAndrey Smirnov
2553b51f47bSAndrey Smirnov /*
2563b51f47bSAndrey Smirnov * We should never read more that 'residue' bytes
2573b51f47bSAndrey Smirnov */
2583b51f47bSAndrey Smirnov chunk = min(chunk, residue);
2593b51f47bSAndrey Smirnov ret = rave_sp_eeprom_page_access(eeprom, type, offset,
2603b51f47bSAndrey Smirnov data, chunk);
2613b51f47bSAndrey Smirnov if (ret)
2623b51f47bSAndrey Smirnov goto out;
2633b51f47bSAndrey Smirnov
2643b51f47bSAndrey Smirnov residue -= chunk;
2653b51f47bSAndrey Smirnov offset += chunk;
2663b51f47bSAndrey Smirnov data += chunk;
2673b51f47bSAndrey Smirnov } while (residue);
2683b51f47bSAndrey Smirnov out:
2693b51f47bSAndrey Smirnov mutex_unlock(&eeprom->mutex);
2703b51f47bSAndrey Smirnov return ret;
2713b51f47bSAndrey Smirnov }
2723b51f47bSAndrey Smirnov
rave_sp_eeprom_reg_read(void * eeprom,unsigned int offset,void * val,size_t bytes)2733b51f47bSAndrey Smirnov static int rave_sp_eeprom_reg_read(void *eeprom, unsigned int offset,
2743b51f47bSAndrey Smirnov void *val, size_t bytes)
2753b51f47bSAndrey Smirnov {
2763b51f47bSAndrey Smirnov return rave_sp_eeprom_access(eeprom, RAVE_SP_EEPROM_READ,
2773b51f47bSAndrey Smirnov offset, val, bytes);
2783b51f47bSAndrey Smirnov }
2793b51f47bSAndrey Smirnov
rave_sp_eeprom_reg_write(void * eeprom,unsigned int offset,void * val,size_t bytes)2803b51f47bSAndrey Smirnov static int rave_sp_eeprom_reg_write(void *eeprom, unsigned int offset,
2813b51f47bSAndrey Smirnov void *val, size_t bytes)
2823b51f47bSAndrey Smirnov {
2833b51f47bSAndrey Smirnov return rave_sp_eeprom_access(eeprom, RAVE_SP_EEPROM_WRITE,
2843b51f47bSAndrey Smirnov offset, val, bytes);
2853b51f47bSAndrey Smirnov }
2863b51f47bSAndrey Smirnov
rave_sp_eeprom_probe(struct platform_device * pdev)2873b51f47bSAndrey Smirnov static int rave_sp_eeprom_probe(struct platform_device *pdev)
2883b51f47bSAndrey Smirnov {
2893b51f47bSAndrey Smirnov struct device *dev = &pdev->dev;
2903b51f47bSAndrey Smirnov struct rave_sp *sp = dev_get_drvdata(dev->parent);
2913b51f47bSAndrey Smirnov struct device_node *np = dev->of_node;
2923b51f47bSAndrey Smirnov struct nvmem_config config = { 0 };
2933b51f47bSAndrey Smirnov struct rave_sp_eeprom *eeprom;
2943b51f47bSAndrey Smirnov struct nvmem_device *nvmem;
2953b51f47bSAndrey Smirnov u32 reg[2], size;
2963b51f47bSAndrey Smirnov
2973b51f47bSAndrey Smirnov if (of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg))) {
2983b51f47bSAndrey Smirnov dev_err(dev, "Failed to parse \"reg\" property\n");
2993b51f47bSAndrey Smirnov return -EINVAL;
3003b51f47bSAndrey Smirnov }
3013b51f47bSAndrey Smirnov
3023b51f47bSAndrey Smirnov size = reg[1];
3033b51f47bSAndrey Smirnov /*
3043b51f47bSAndrey Smirnov * Per ICD, we have no more than 2 bytes to specify EEPROM
3053b51f47bSAndrey Smirnov * page.
3063b51f47bSAndrey Smirnov */
3073b51f47bSAndrey Smirnov if (size > U16_MAX * RAVE_SP_EEPROM_PAGE_SIZE) {
3083b51f47bSAndrey Smirnov dev_err(dev, "Specified size is too big\n");
3093b51f47bSAndrey Smirnov return -EINVAL;
3103b51f47bSAndrey Smirnov }
3113b51f47bSAndrey Smirnov
3123b51f47bSAndrey Smirnov eeprom = devm_kzalloc(dev, sizeof(*eeprom), GFP_KERNEL);
3133b51f47bSAndrey Smirnov if (!eeprom)
3143b51f47bSAndrey Smirnov return -ENOMEM;
3153b51f47bSAndrey Smirnov
3163b51f47bSAndrey Smirnov eeprom->address = reg[0];
3173b51f47bSAndrey Smirnov eeprom->sp = sp;
3183b51f47bSAndrey Smirnov eeprom->dev = dev;
3193b51f47bSAndrey Smirnov
3203b51f47bSAndrey Smirnov if (size > SZ_8K)
3213b51f47bSAndrey Smirnov eeprom->header_size = RAVE_SP_EEPROM_HEADER_BIG;
3223b51f47bSAndrey Smirnov else
3233b51f47bSAndrey Smirnov eeprom->header_size = RAVE_SP_EEPROM_HEADER_SMALL;
3243b51f47bSAndrey Smirnov
3253b51f47bSAndrey Smirnov mutex_init(&eeprom->mutex);
3263b51f47bSAndrey Smirnov
3273b51f47bSAndrey Smirnov config.id = -1;
3283b51f47bSAndrey Smirnov of_property_read_string(np, "zii,eeprom-name", &config.name);
3293b51f47bSAndrey Smirnov config.priv = eeprom;
3303b51f47bSAndrey Smirnov config.dev = dev;
331*26e2fe4cSRafał Miłecki config.add_legacy_fixed_of_cells = true;
3323b51f47bSAndrey Smirnov config.size = size;
3333b51f47bSAndrey Smirnov config.reg_read = rave_sp_eeprom_reg_read;
3343b51f47bSAndrey Smirnov config.reg_write = rave_sp_eeprom_reg_write;
3353b51f47bSAndrey Smirnov config.word_size = 1;
3363b51f47bSAndrey Smirnov config.stride = 1;
3373b51f47bSAndrey Smirnov
3383b51f47bSAndrey Smirnov nvmem = devm_nvmem_register(dev, &config);
3393b51f47bSAndrey Smirnov
3403b51f47bSAndrey Smirnov return PTR_ERR_OR_ZERO(nvmem);
3413b51f47bSAndrey Smirnov }
3423b51f47bSAndrey Smirnov
3433b51f47bSAndrey Smirnov static const struct of_device_id rave_sp_eeprom_of_match[] = {
3443b51f47bSAndrey Smirnov { .compatible = "zii,rave-sp-eeprom" },
3453b51f47bSAndrey Smirnov {}
3463b51f47bSAndrey Smirnov };
3473b51f47bSAndrey Smirnov MODULE_DEVICE_TABLE(of, rave_sp_eeprom_of_match);
3483b51f47bSAndrey Smirnov
3493b51f47bSAndrey Smirnov static struct platform_driver rave_sp_eeprom_driver = {
3503b51f47bSAndrey Smirnov .probe = rave_sp_eeprom_probe,
3513b51f47bSAndrey Smirnov .driver = {
3523b51f47bSAndrey Smirnov .name = KBUILD_MODNAME,
3533b51f47bSAndrey Smirnov .of_match_table = rave_sp_eeprom_of_match,
3543b51f47bSAndrey Smirnov },
3553b51f47bSAndrey Smirnov };
3563b51f47bSAndrey Smirnov module_platform_driver(rave_sp_eeprom_driver);
3573b51f47bSAndrey Smirnov
3583b51f47bSAndrey Smirnov MODULE_LICENSE("GPL");
3593b51f47bSAndrey Smirnov MODULE_AUTHOR("Andrey Vostrikov <andrey.vostrikov@cogentembedded.com>");
3603b51f47bSAndrey Smirnov MODULE_AUTHOR("Nikita Yushchenko <nikita.yoush@cogentembedded.com>");
3613b51f47bSAndrey Smirnov MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
3623b51f47bSAndrey Smirnov MODULE_DESCRIPTION("RAVE SP EEPROM driver");
363