mm, tracing: unify PFN format strings
[linux-2.6-microblaze.git] / drivers / nvmem / core.c
index a5ab1e0..bca671f 100644 (file)
@@ -1606,6 +1606,101 @@ int nvmem_cell_read_u64(struct device *dev, const char *cell_id, u64 *val)
 }
 EXPORT_SYMBOL_GPL(nvmem_cell_read_u64);
 
+static void *nvmem_cell_read_variable_common(struct device *dev,
+                                            const char *cell_id,
+                                            size_t max_len, size_t *len)
+{
+       struct nvmem_cell *cell;
+       int nbits;
+       void *buf;
+
+       cell = nvmem_cell_get(dev, cell_id);
+       if (IS_ERR(cell))
+               return cell;
+
+       nbits = cell->nbits;
+       buf = nvmem_cell_read(cell, len);
+       nvmem_cell_put(cell);
+       if (IS_ERR(buf))
+               return buf;
+
+       /*
+        * If nbits is set then nvmem_cell_read() can significantly exaggerate
+        * the length of the real data. Throw away the extra junk.
+        */
+       if (nbits)
+               *len = DIV_ROUND_UP(nbits, 8);
+
+       if (*len > max_len) {
+               kfree(buf);
+               return ERR_PTR(-ERANGE);
+       }
+
+       return buf;
+}
+
+/**
+ * nvmem_cell_read_variable_le_u32() - Read up to 32-bits of data as a little endian number.
+ *
+ * @dev: Device that requests the nvmem cell.
+ * @cell_id: Name of nvmem cell to read.
+ * @val: pointer to output value.
+ *
+ * Return: 0 on success or negative errno.
+ */
+int nvmem_cell_read_variable_le_u32(struct device *dev, const char *cell_id,
+                                   u32 *val)
+{
+       size_t len;
+       u8 *buf;
+       int i;
+
+       buf = nvmem_cell_read_variable_common(dev, cell_id, sizeof(*val), &len);
+       if (IS_ERR(buf))
+               return PTR_ERR(buf);
+
+       /* Copy w/ implicit endian conversion */
+       *val = 0;
+       for (i = 0; i < len; i++)
+               *val |= buf[i] << (8 * i);
+
+       kfree(buf);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_read_variable_le_u32);
+
+/**
+ * nvmem_cell_read_variable_le_u64() - Read up to 64-bits of data as a little endian number.
+ *
+ * @dev: Device that requests the nvmem cell.
+ * @cell_id: Name of nvmem cell to read.
+ * @val: pointer to output value.
+ *
+ * Return: 0 on success or negative errno.
+ */
+int nvmem_cell_read_variable_le_u64(struct device *dev, const char *cell_id,
+                                   u64 *val)
+{
+       size_t len;
+       u8 *buf;
+       int i;
+
+       buf = nvmem_cell_read_variable_common(dev, cell_id, sizeof(*val), &len);
+       if (IS_ERR(buf))
+               return PTR_ERR(buf);
+
+       /* Copy w/ implicit endian conversion */
+       *val = 0;
+       for (i = 0; i < len; i++)
+               *val |= (uint64_t)buf[i] << (8 * i);
+
+       kfree(buf);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(nvmem_cell_read_variable_le_u64);
+
 /**
  * nvmem_device_cell_read() - Read a given nvmem device and cell
  *