1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (C) 2019 Xilinx, Inc.
6 #include <linux/module.h>
7 #include <linux/nvmem-provider.h>
9 #include <linux/platform_device.h>
10 #include <linux/firmware/xlnx-zynqmp.h>
12 #define SILICON_REVISION_MASK 0xF
14 struct zynqmp_nvmem_data
{
16 struct nvmem_device
*nvmem
;
19 static int zynqmp_nvmem_read(void *context
, unsigned int offset
,
20 void *val
, size_t bytes
)
24 struct zynqmp_nvmem_data
*priv
= context
;
26 const struct zynqmp_eemi_ops
*eemi_ops
= zynqmp_pm_get_eemi_ops();
28 if (!eemi_ops
|| !eemi_ops
->get_chipid
)
31 ret
= eemi_ops
->get_chipid(&idcode
, &version
);
35 dev_dbg(priv
->dev
, "Read chipid val %x %x\n", idcode
, version
);
36 *(int *)val
= version
& SILICON_REVISION_MASK
;
41 static struct nvmem_config econfig
= {
42 .name
= "zynqmp-nvmem",
49 static const struct of_device_id zynqmp_nvmem_match
[] = {
50 { .compatible
= "xlnx,zynqmp-nvmem-fw", },
53 MODULE_DEVICE_TABLE(of
, zynqmp_nvmem_match
);
55 static int zynqmp_nvmem_probe(struct platform_device
*pdev
)
57 struct device
*dev
= &pdev
->dev
;
58 struct zynqmp_nvmem_data
*priv
;
60 priv
= devm_kzalloc(dev
, sizeof(struct zynqmp_nvmem_data
), GFP_KERNEL
);
66 econfig
.reg_read
= zynqmp_nvmem_read
;
69 priv
->nvmem
= devm_nvmem_register(dev
, &econfig
);
71 return PTR_ERR_OR_ZERO(priv
->nvmem
);
74 static struct platform_driver zynqmp_nvmem_driver
= {
75 .probe
= zynqmp_nvmem_probe
,
77 .name
= "zynqmp-nvmem",
78 .of_match_table
= zynqmp_nvmem_match
,
82 module_platform_driver(zynqmp_nvmem_driver
);
84 MODULE_AUTHOR("Michal Simek <michal.simek@xilinx.com>, Nava kishore Manne <navam@xilinx.com>");
85 MODULE_DESCRIPTION("ZynqMP NVMEM driver");
86 MODULE_LICENSE("GPL");