1 // SPDX-License-Identifier: GPL-2.0+
4 * EEPROM driver for RAVE SP
6 * Copyright (C) 2018 Zodiac Inflight Innovations
9 #include <linux/kernel.h>
10 #include <linux/mfd/rave-sp.h>
11 #include <linux/module.h>
12 #include <linux/nvmem-provider.h>
13 #include <linux/of_device.h>
14 #include <linux/platform_device.h>
15 #include <linux/sizes.h>
18 * enum rave_sp_eeprom_access_type - Supported types of EEPROM access
20 * @RAVE_SP_EEPROM_WRITE: EEPROM write
21 * @RAVE_SP_EEPROM_READ: EEPROM read
23 enum rave_sp_eeprom_access_type
{
24 RAVE_SP_EEPROM_WRITE
= 0,
25 RAVE_SP_EEPROM_READ
= 1,
29 * enum rave_sp_eeprom_header_size - EEPROM command header sizes
31 * @RAVE_SP_EEPROM_HEADER_SMALL: EEPROM header size for "small" devices (< 8K)
32 * @RAVE_SP_EEPROM_HEADER_BIG: EEPROM header size for "big" devices (> 8K)
34 enum rave_sp_eeprom_header_size
{
35 RAVE_SP_EEPROM_HEADER_SMALL
= 4U,
36 RAVE_SP_EEPROM_HEADER_BIG
= 5U,
38 #define RAVE_SP_EEPROM_HEADER_MAX RAVE_SP_EEPROM_HEADER_BIG
40 #define RAVE_SP_EEPROM_PAGE_SIZE 32U
43 * struct rave_sp_eeprom_page - RAVE SP EEPROM page
45 * @type: Access type (see enum rave_sp_eeprom_access_type)
46 * @success: Success flag (Success = 1, Failure = 0)
49 * Note this structure corresponds to RSP_*_EEPROM payload from RAVE
52 struct rave_sp_eeprom_page
{
55 u8 data
[RAVE_SP_EEPROM_PAGE_SIZE
];
59 * struct rave_sp_eeprom - RAVE SP EEPROM device
61 * @sp: Pointer to parent RAVE SP device
62 * @mutex: Lock protecting access to EEPROM
63 * @address: EEPROM device address
64 * @header_size: Size of EEPROM command header for this device
65 * @dev: Pointer to corresponding struct device used for logging
67 struct rave_sp_eeprom
{
71 unsigned int header_size
;
76 * rave_sp_eeprom_io - Low-level part of EEPROM page access
78 * @eeprom: EEPROM device to write to
79 * @type: EEPROM access type (read or write)
80 * @idx: number of the EEPROM page
81 * @page: Data to write or buffer to store result (via page->data)
83 * This function does all of the low-level work required to perform a
84 * EEPROM access. This includes formatting correct command payload,
85 * sending it and checking received results.
87 * Returns zero in case of success or negative error code in
90 static int rave_sp_eeprom_io(struct rave_sp_eeprom
*eeprom
,
91 enum rave_sp_eeprom_access_type type
,
93 struct rave_sp_eeprom_page
*page
)
95 const bool is_write
= type
== RAVE_SP_EEPROM_WRITE
;
96 const unsigned int data_size
= is_write
? sizeof(page
->data
) : 0;
97 const unsigned int cmd_size
= eeprom
->header_size
+ data_size
;
98 const unsigned int rsp_size
=
99 is_write
? sizeof(*page
) - sizeof(page
->data
) : sizeof(*page
);
100 unsigned int offset
= 0;
101 u8 cmd
[RAVE_SP_EEPROM_HEADER_MAX
+ sizeof(page
->data
)];
104 if (WARN_ON(cmd_size
> sizeof(cmd
)))
107 cmd
[offset
++] = eeprom
->address
;
109 cmd
[offset
++] = type
;
113 * If there's still room in this command's header it means we
114 * are talkin to EEPROM that uses 16-bit page numbers and we
115 * have to specify index's MSB in payload as well.
117 if (offset
< eeprom
->header_size
)
118 cmd
[offset
++] = idx
>> 8;
120 * Copy our data to write to command buffer first. In case of
121 * a read data_size should be zero and memcpy would become a
124 memcpy(&cmd
[offset
], page
->data
, data_size
);
126 ret
= rave_sp_exec(eeprom
->sp
, cmd
, cmd_size
, page
, rsp_size
);
130 if (page
->type
!= type
)
140 * rave_sp_eeprom_page_access - Access single EEPROM page
142 * @eeprom: EEPROM device to access
143 * @type: Access type to perform (read or write)
144 * @offset: Offset within EEPROM to access
146 * @data_len: Size of the data buffer
148 * This function performs a generic access to a single page or a
149 * portion thereof. Requested access MUST NOT cross the EEPROM page
152 * Returns zero in case of success or negative error code in
156 rave_sp_eeprom_page_access(struct rave_sp_eeprom
*eeprom
,
157 enum rave_sp_eeprom_access_type type
,
158 unsigned int offset
, u8
*data
,
161 const unsigned int page_offset
= offset
% RAVE_SP_EEPROM_PAGE_SIZE
;
162 const unsigned int page_nr
= offset
/ RAVE_SP_EEPROM_PAGE_SIZE
;
163 struct rave_sp_eeprom_page page
;
167 * This function will not work if data access we've been asked
168 * to do is crossing EEPROM page boundary. Normally this
169 * should never happen and getting here would indicate a bug
172 if (WARN_ON(data_len
> sizeof(page
.data
) - page_offset
))
175 if (type
== RAVE_SP_EEPROM_WRITE
) {
177 * If doing a partial write we need to do a read first
178 * to fill the rest of the page with correct data.
180 if (data_len
< RAVE_SP_EEPROM_PAGE_SIZE
) {
181 ret
= rave_sp_eeprom_io(eeprom
, RAVE_SP_EEPROM_READ
,
187 memcpy(&page
.data
[page_offset
], data
, data_len
);
190 ret
= rave_sp_eeprom_io(eeprom
, type
, page_nr
, &page
);
195 * Since we receive the result of the read via 'page.data'
196 * buffer we need to copy that to 'data'
198 if (type
== RAVE_SP_EEPROM_READ
)
199 memcpy(data
, &page
.data
[page_offset
], data_len
);
205 * rave_sp_eeprom_access - Access EEPROM data
207 * @eeprom: EEPROM device to access
208 * @type: Access type to perform (read or write)
209 * @offset: Offset within EEPROM to access
211 * @data_len: Size of the data buffer
213 * This function performs a generic access (either read or write) at
214 * arbitrary offset (not necessary page aligned) of arbitrary length
215 * (is not constrained by EEPROM page size).
217 * Returns zero in case of success or negative error code in case of
220 static int rave_sp_eeprom_access(struct rave_sp_eeprom
*eeprom
,
221 enum rave_sp_eeprom_access_type type
,
222 unsigned int offset
, u8
*data
,
223 unsigned int data_len
)
225 unsigned int residue
;
230 mutex_lock(&eeprom
->mutex
);
232 head
= offset
% RAVE_SP_EEPROM_PAGE_SIZE
;
237 * First iteration, if we are doing an access that is
238 * not 32-byte aligned, we need to access only data up
239 * to a page boundary to avoid corssing it in
240 * rave_sp_eeprom_page_access()
242 if (unlikely(head
)) {
243 chunk
= RAVE_SP_EEPROM_PAGE_SIZE
- head
;
245 * This can only happen once per
246 * rave_sp_eeprom_access() call, so we set
247 * head to zero to process all the other
248 * iterations normally.
252 chunk
= RAVE_SP_EEPROM_PAGE_SIZE
;
256 * We should never read more that 'residue' bytes
258 chunk
= min(chunk
, residue
);
259 ret
= rave_sp_eeprom_page_access(eeprom
, type
, offset
,
269 mutex_unlock(&eeprom
->mutex
);
273 static int rave_sp_eeprom_reg_read(void *eeprom
, unsigned int offset
,
274 void *val
, size_t bytes
)
276 return rave_sp_eeprom_access(eeprom
, RAVE_SP_EEPROM_READ
,
280 static int rave_sp_eeprom_reg_write(void *eeprom
, unsigned int offset
,
281 void *val
, size_t bytes
)
283 return rave_sp_eeprom_access(eeprom
, RAVE_SP_EEPROM_WRITE
,
287 static int rave_sp_eeprom_probe(struct platform_device
*pdev
)
289 struct device
*dev
= &pdev
->dev
;
290 struct rave_sp
*sp
= dev_get_drvdata(dev
->parent
);
291 struct device_node
*np
= dev
->of_node
;
292 struct nvmem_config config
= { 0 };
293 struct rave_sp_eeprom
*eeprom
;
294 struct nvmem_device
*nvmem
;
297 if (of_property_read_u32_array(np
, "reg", reg
, ARRAY_SIZE(reg
))) {
298 dev_err(dev
, "Failed to parse \"reg\" property\n");
304 * Per ICD, we have no more than 2 bytes to specify EEPROM
307 if (size
> U16_MAX
* RAVE_SP_EEPROM_PAGE_SIZE
) {
308 dev_err(dev
, "Specified size is too big\n");
312 eeprom
= devm_kzalloc(dev
, sizeof(*eeprom
), GFP_KERNEL
);
316 eeprom
->address
= reg
[0];
321 eeprom
->header_size
= RAVE_SP_EEPROM_HEADER_BIG
;
323 eeprom
->header_size
= RAVE_SP_EEPROM_HEADER_SMALL
;
325 mutex_init(&eeprom
->mutex
);
328 of_property_read_string(np
, "zii,eeprom-name", &config
.name
);
329 config
.priv
= eeprom
;
332 config
.reg_read
= rave_sp_eeprom_reg_read
;
333 config
.reg_write
= rave_sp_eeprom_reg_write
;
334 config
.word_size
= 1;
337 nvmem
= devm_nvmem_register(dev
, &config
);
339 return PTR_ERR_OR_ZERO(nvmem
);
342 static const struct of_device_id rave_sp_eeprom_of_match
[] = {
343 { .compatible
= "zii,rave-sp-eeprom" },
346 MODULE_DEVICE_TABLE(of
, rave_sp_eeprom_of_match
);
348 static struct platform_driver rave_sp_eeprom_driver
= {
349 .probe
= rave_sp_eeprom_probe
,
351 .name
= KBUILD_MODNAME
,
352 .of_match_table
= rave_sp_eeprom_of_match
,
355 module_platform_driver(rave_sp_eeprom_driver
);
357 MODULE_LICENSE("GPL");
358 MODULE_AUTHOR("Andrey Vostrikov <andrey.vostrikov@cogentembedded.com>");
359 MODULE_AUTHOR("Nikita Yushchenko <nikita.yoush@cogentembedded.com>");
360 MODULE_AUTHOR("Andrey Smirnov <andrew.smirnov@gmail.com>");
361 MODULE_DESCRIPTION("RAVE SP EEPROM driver");