root/drivers/nvmem/rave-sp-eeprom.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rave_sp_eeprom_io
  2. rave_sp_eeprom_page_access
  3. rave_sp_eeprom_access
  4. rave_sp_eeprom_reg_read
  5. rave_sp_eeprom_reg_write
  6. rave_sp_eeprom_probe

   1 // SPDX-License-Identifier: GPL-2.0+
   2 
   3 /*
   4  * EEPROM driver for RAVE SP
   5  *
   6  * Copyright (C) 2018 Zodiac Inflight Innovations
   7  *
   8  */
   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>
  16 
  17 /**
  18  * enum rave_sp_eeprom_access_type - Supported types of EEPROM access
  19  *
  20  * @RAVE_SP_EEPROM_WRITE:       EEPROM write
  21  * @RAVE_SP_EEPROM_READ:        EEPROM read
  22  */
  23 enum rave_sp_eeprom_access_type {
  24         RAVE_SP_EEPROM_WRITE = 0,
  25         RAVE_SP_EEPROM_READ  = 1,
  26 };
  27 
  28 /**
  29  * enum rave_sp_eeprom_header_size - EEPROM command header sizes
  30  *
  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)
  33  */
  34 enum rave_sp_eeprom_header_size {
  35         RAVE_SP_EEPROM_HEADER_SMALL = 4U,
  36         RAVE_SP_EEPROM_HEADER_BIG   = 5U,
  37 };
  38 #define RAVE_SP_EEPROM_HEADER_MAX       RAVE_SP_EEPROM_HEADER_BIG
  39 
  40 #define RAVE_SP_EEPROM_PAGE_SIZE        32U
  41 
  42 /**
  43  * struct rave_sp_eeprom_page - RAVE SP EEPROM page
  44  *
  45  * @type:       Access type (see enum rave_sp_eeprom_access_type)
  46  * @success:    Success flag (Success = 1, Failure = 0)
  47  * @data:       Read data
  48 
  49  * Note this structure corresponds to RSP_*_EEPROM payload from RAVE
  50  * SP ICD
  51  */
  52 struct rave_sp_eeprom_page {
  53         u8  type;
  54         u8  success;
  55         u8  data[RAVE_SP_EEPROM_PAGE_SIZE];
  56 } __packed;
  57 
  58 /**
  59  * struct rave_sp_eeprom - RAVE SP EEPROM device
  60  *
  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
  66  */
  67 struct rave_sp_eeprom {
  68         struct rave_sp *sp;
  69         struct mutex mutex;
  70         u8 address;
  71         unsigned int header_size;
  72         struct device *dev;
  73 };
  74 
  75 /**
  76  * rave_sp_eeprom_io - Low-level part of EEPROM page access
  77  *
  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)
  82  *
  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.
  86  *
  87  * Returns zero in case of success or negative error code in
  88  * case of failure.
  89  */
  90 static int rave_sp_eeprom_io(struct rave_sp_eeprom *eeprom,
  91                              enum rave_sp_eeprom_access_type type,
  92                              u16 idx,
  93                              struct rave_sp_eeprom_page *page)
  94 {
  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)];
 102         int ret;
 103 
 104         if (WARN_ON(cmd_size > sizeof(cmd)))
 105                 return -EINVAL;
 106 
 107         cmd[offset++] = eeprom->address;
 108         cmd[offset++] = 0;
 109         cmd[offset++] = type;
 110         cmd[offset++] = idx;
 111 
 112         /*
 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.
 116          */
 117         if (offset < eeprom->header_size)
 118                 cmd[offset++] = idx >> 8;
 119         /*
 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
 122          * no-op
 123          */
 124         memcpy(&cmd[offset], page->data, data_size);
 125 
 126         ret = rave_sp_exec(eeprom->sp, cmd, cmd_size, page, rsp_size);
 127         if (ret)
 128                 return ret;
 129 
 130         if (page->type != type)
 131                 return -EPROTO;
 132 
 133         if (!page->success)
 134                 return -EIO;
 135 
 136         return 0;
 137 }
 138 
 139 /**
 140  * rave_sp_eeprom_page_access - Access single EEPROM page
 141  *
 142  * @eeprom:     EEPROM device to access
 143  * @type:       Access type to perform (read or write)
 144  * @offset:     Offset within EEPROM to access
 145  * @data:       Data buffer
 146  * @data_len:   Size of the data buffer
 147  *
 148  * This function performs a generic access to a single page or a
 149  * portion thereof. Requested access MUST NOT cross the EEPROM page
 150  * boundary.
 151  *
 152  * Returns zero in case of success or negative error code in
 153  * case of failure.
 154  */
 155 static int
 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,
 159                            size_t data_len)
 160 {
 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;
 164         int ret;
 165 
 166         /*
 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
 170          * in the code.
 171          */
 172         if (WARN_ON(data_len > sizeof(page.data) - page_offset))
 173                 return -EINVAL;
 174 
 175         if (type == RAVE_SP_EEPROM_WRITE) {
 176                 /*
 177                  * If doing a partial write we need to do a read first
 178                  * to fill the rest of the page with correct data.
 179                  */
 180                 if (data_len < RAVE_SP_EEPROM_PAGE_SIZE) {
 181                         ret = rave_sp_eeprom_io(eeprom, RAVE_SP_EEPROM_READ,
 182                                                 page_nr, &page);
 183                         if (ret)
 184                                 return ret;
 185                 }
 186 
 187                 memcpy(&page.data[page_offset], data, data_len);
 188         }
 189 
 190         ret = rave_sp_eeprom_io(eeprom, type, page_nr, &page);
 191         if (ret)
 192                 return ret;
 193 
 194         /*
 195          * Since we receive the result of the read via 'page.data'
 196          * buffer we need to copy that to 'data'
 197          */
 198         if (type == RAVE_SP_EEPROM_READ)
 199                 memcpy(data, &page.data[page_offset], data_len);
 200 
 201         return 0;
 202 }
 203 
 204 /**
 205  * rave_sp_eeprom_access - Access EEPROM data
 206  *
 207  * @eeprom:     EEPROM device to access
 208  * @type:       Access type to perform (read or write)
 209  * @offset:     Offset within EEPROM to access
 210  * @data:       Data buffer
 211  * @data_len:   Size of the data buffer
 212  *
 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).
 216  *
 217  * Returns zero in case of success or negative error code in case of
 218  * failure.
 219  */
 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)
 224 {
 225         unsigned int residue;
 226         unsigned int chunk;
 227         unsigned int head;
 228         int ret;
 229 
 230         mutex_lock(&eeprom->mutex);
 231 
 232         head    = offset % RAVE_SP_EEPROM_PAGE_SIZE;
 233         residue = data_len;
 234 
 235         do {
 236                 /*
 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()
 241                  */
 242                 if (unlikely(head)) {
 243                         chunk = RAVE_SP_EEPROM_PAGE_SIZE - head;
 244                         /*
 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.
 249                          */
 250                         head  = 0;
 251                 } else {
 252                         chunk = RAVE_SP_EEPROM_PAGE_SIZE;
 253                 }
 254 
 255                 /*
 256                  * We should never read more that 'residue' bytes
 257                  */
 258                 chunk = min(chunk, residue);
 259                 ret = rave_sp_eeprom_page_access(eeprom, type, offset,
 260                                                  data, chunk);
 261                 if (ret)
 262                         goto out;
 263 
 264                 residue -= chunk;
 265                 offset  += chunk;
 266                 data    += chunk;
 267         } while (residue);
 268 out:
 269         mutex_unlock(&eeprom->mutex);
 270         return ret;
 271 }
 272 
 273 static int rave_sp_eeprom_reg_read(void *eeprom, unsigned int offset,
 274                                    void *val, size_t bytes)
 275 {
 276         return rave_sp_eeprom_access(eeprom, RAVE_SP_EEPROM_READ,
 277                                      offset, val, bytes);
 278 }
 279 
 280 static int rave_sp_eeprom_reg_write(void *eeprom, unsigned int offset,
 281                                     void *val, size_t bytes)
 282 {
 283         return rave_sp_eeprom_access(eeprom, RAVE_SP_EEPROM_WRITE,
 284                                      offset, val, bytes);
 285 }
 286 
 287 static int rave_sp_eeprom_probe(struct platform_device *pdev)
 288 {
 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;
 295         u32 reg[2], size;
 296 
 297         if (of_property_read_u32_array(np, "reg", reg, ARRAY_SIZE(reg))) {
 298                 dev_err(dev, "Failed to parse \"reg\" property\n");
 299                 return -EINVAL;
 300         }
 301 
 302         size = reg[1];
 303         /*
 304          * Per ICD, we have no more than 2 bytes to specify EEPROM
 305          * page.
 306          */
 307         if (size > U16_MAX * RAVE_SP_EEPROM_PAGE_SIZE) {
 308                 dev_err(dev, "Specified size is too big\n");
 309                 return -EINVAL;
 310         }
 311 
 312         eeprom = devm_kzalloc(dev, sizeof(*eeprom), GFP_KERNEL);
 313         if (!eeprom)
 314                 return -ENOMEM;
 315 
 316         eeprom->address = reg[0];
 317         eeprom->sp      = sp;
 318         eeprom->dev     = dev;
 319 
 320         if (size > SZ_8K)
 321                 eeprom->header_size = RAVE_SP_EEPROM_HEADER_BIG;
 322         else
 323                 eeprom->header_size = RAVE_SP_EEPROM_HEADER_SMALL;
 324 
 325         mutex_init(&eeprom->mutex);
 326 
 327         config.id               = -1;
 328         of_property_read_string(np, "zii,eeprom-name", &config.name);
 329         config.priv             = eeprom;
 330         config.dev              = dev;
 331         config.size             = size;
 332         config.reg_read         = rave_sp_eeprom_reg_read;
 333         config.reg_write        = rave_sp_eeprom_reg_write;
 334         config.word_size        = 1;
 335         config.stride           = 1;
 336 
 337         nvmem = devm_nvmem_register(dev, &config);
 338 
 339         return PTR_ERR_OR_ZERO(nvmem);
 340 }
 341 
 342 static const struct of_device_id rave_sp_eeprom_of_match[] = {
 343         { .compatible = "zii,rave-sp-eeprom" },
 344         {}
 345 };
 346 MODULE_DEVICE_TABLE(of, rave_sp_eeprom_of_match);
 347 
 348 static struct platform_driver rave_sp_eeprom_driver = {
 349         .probe = rave_sp_eeprom_probe,
 350         .driver = {
 351                 .name = KBUILD_MODNAME,
 352                 .of_match_table = rave_sp_eeprom_of_match,
 353         },
 354 };
 355 module_platform_driver(rave_sp_eeprom_driver);
 356 
 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");

/* [<][>][^][v][top][bottom][index][help] */