]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
soc/tegra: fuse: Implement nvmem device
authorThierry Reding <treding@nvidia.com>
Tue, 20 Aug 2019 13:57:16 +0000 (15:57 +0200)
committerThierry Reding <treding@nvidia.com>
Wed, 16 Oct 2019 12:33:14 +0000 (14:33 +0200)
The nvmem framework provides a generic infrastructure and API to access
the type of information stored in fuses such as the Tegra FUSE block.

Implement an nvmem device that can be used to access the information in
a more generic way to decouple consumers from the custom Tegra API and
to add a more formal way of creating the dependency between the FUSE
device and the consumers.

Signed-off-by: Thierry Reding <treding@nvidia.com>
drivers/soc/tegra/fuse/fuse-tegra.c
drivers/soc/tegra/fuse/fuse.h

index db516a2a3807865b6cfede2c83ef788041631583..430a47963a5723229875daa18f64accea4d3836f 100644 (file)
@@ -8,6 +8,8 @@
 #include <linux/kobject.h>
 #include <linux/init.h>
 #include <linux/io.h>
+#include <linux/nvmem-consumer.h>
+#include <linux/nvmem-provider.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/platform_device.h>
@@ -31,50 +33,6 @@ static const char *tegra_revision_name[TEGRA_REVISION_MAX] = {
        [TEGRA_REVISION_A04]     = "A04",
 };
 
-static u8 fuse_readb(struct tegra_fuse *fuse, unsigned int offset)
-{
-       u32 val;
-
-       val = fuse->read(fuse, round_down(offset, 4));
-       val >>= (offset % 4) * 8;
-       val &= 0xff;
-
-       return val;
-}
-
-static ssize_t fuse_read(struct file *fd, struct kobject *kobj,
-                        struct bin_attribute *attr, char *buf,
-                        loff_t pos, size_t size)
-{
-       struct device *dev = kobj_to_dev(kobj);
-       struct tegra_fuse *fuse = dev_get_drvdata(dev);
-       int i;
-
-       if (pos < 0 || pos >= attr->size)
-               return 0;
-
-       if (size > attr->size - pos)
-               size = attr->size - pos;
-
-       for (i = 0; i < size; i++)
-               buf[i] = fuse_readb(fuse, pos + i);
-
-       return i;
-}
-
-static struct bin_attribute fuse_bin_attr = {
-       .attr = { .name = "fuse", .mode = S_IRUGO, },
-       .read = fuse_read,
-};
-
-static int tegra_fuse_create_sysfs(struct device *dev, unsigned int size,
-                                  const struct tegra_fuse_info *info)
-{
-       fuse_bin_attr.size = size;
-
-       return device_create_bin_file(dev, &fuse_bin_attr);
-}
-
 static const struct of_device_id car_match[] __initconst = {
        { .compatible = "nvidia,tegra20-car", },
        { .compatible = "nvidia,tegra30-car", },
@@ -115,9 +73,23 @@ static const struct of_device_id tegra_fuse_match[] = {
        { /* sentinel */ }
 };
 
+static int tegra_fuse_read(void *priv, unsigned int offset, void *value,
+                          size_t bytes)
+{
+       unsigned int count = bytes / 4, i;
+       struct tegra_fuse *fuse = priv;
+       u32 *buffer = value;
+
+       for (i = 0; i < count; i++)
+               buffer[i] = fuse->read(fuse, offset + i * 4);
+
+       return 0;
+}
+
 static int tegra_fuse_probe(struct platform_device *pdev)
 {
        void __iomem *base = fuse->base;
+       struct nvmem_config nvmem;
        struct resource *res;
        int err;
 
@@ -150,9 +122,25 @@ static int tegra_fuse_probe(struct platform_device *pdev)
                        goto restore;
        }
 
-       if (tegra_fuse_create_sysfs(&pdev->dev, fuse->soc->info->size,
-                                   fuse->soc->info)) {
-               err = -ENODEV;
+       memset(&nvmem, 0, sizeof(nvmem));
+       nvmem.dev = &pdev->dev;
+       nvmem.name = "fuse";
+       nvmem.id = -1;
+       nvmem.owner = THIS_MODULE;
+       nvmem.type = NVMEM_TYPE_OTP;
+       nvmem.read_only = true;
+       nvmem.root_only = true;
+       nvmem.reg_read = tegra_fuse_read;
+       nvmem.size = fuse->soc->info->size;
+       nvmem.word_size = 4;
+       nvmem.stride = 4;
+       nvmem.priv = fuse;
+
+       fuse->nvmem = devm_nvmem_register(&pdev->dev, &nvmem);
+       if (IS_ERR(fuse->nvmem)) {
+               err = PTR_ERR(fuse->nvmem);
+               dev_err(&pdev->dev, "failed to register NVMEM device: %d\n",
+                       err);
                goto restore;
        }
 
index 7230cb3305033533ca82e777d9b732115da67f1d..32bf6c070ae70342474581fd03cee02f2c0ac719 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/dmaengine.h>
 #include <linux/types.h>
 
+struct nvmem_device;
 struct tegra_fuse;
 
 struct tegra_fuse_info {
@@ -48,6 +49,8 @@ struct tegra_fuse {
                dma_addr_t phys;
                u32 *virt;
        } apbdma;
+
+       struct nvmem_device *nvmem;
 };
 
 void tegra_init_revision(void);