1 // SPDX-License-Identifier: GPL-2.0-only
3 * Layerscape SFP driver
5 * Copyright (c) 2022 Michael Walle <michael@walle.cc>
9 #include <linux/device.h>
11 #include <linux/mod_devicetable.h>
12 #include <linux/module.h>
13 #include <linux/nvmem-provider.h>
14 #include <linux/platform_device.h>
15 #include <linux/property.h>
16 #include <linux/regmap.h>
18 #define LAYERSCAPE_SFP_OTP_OFFSET 0x0200
20 struct layerscape_sfp_priv
{
21 struct regmap
*regmap
;
24 struct layerscape_sfp_data
{
26 enum regmap_endian endian
;
29 static int layerscape_sfp_read(void *context
, unsigned int offset
, void *val
,
32 struct layerscape_sfp_priv
*priv
= context
;
34 return regmap_bulk_read(priv
->regmap
,
35 LAYERSCAPE_SFP_OTP_OFFSET
+ offset
, val
,
39 static struct nvmem_config layerscape_sfp_nvmem_config
= {
41 .reg_read
= layerscape_sfp_read
,
46 static int layerscape_sfp_probe(struct platform_device
*pdev
)
48 const struct layerscape_sfp_data
*data
;
49 struct layerscape_sfp_priv
*priv
;
50 struct nvmem_device
*nvmem
;
51 struct regmap_config config
= { 0 };
54 priv
= devm_kzalloc(&pdev
->dev
, sizeof(*priv
), GFP_KERNEL
);
58 base
= devm_platform_ioremap_resource(pdev
, 0);
62 data
= device_get_match_data(&pdev
->dev
);
64 config
.reg_stride
= 4;
66 config
.val_format_endian
= data
->endian
;
67 config
.max_register
= LAYERSCAPE_SFP_OTP_OFFSET
+ data
->size
- 4;
68 priv
->regmap
= devm_regmap_init_mmio(&pdev
->dev
, base
, &config
);
69 if (IS_ERR(priv
->regmap
))
70 return PTR_ERR(priv
->regmap
);
72 layerscape_sfp_nvmem_config
.size
= data
->size
;
73 layerscape_sfp_nvmem_config
.dev
= &pdev
->dev
;
74 layerscape_sfp_nvmem_config
.priv
= priv
;
76 nvmem
= devm_nvmem_register(&pdev
->dev
, &layerscape_sfp_nvmem_config
);
78 return PTR_ERR_OR_ZERO(nvmem
);
81 static const struct layerscape_sfp_data ls1021a_data
= {
83 .endian
= REGMAP_ENDIAN_BIG
,
86 static const struct layerscape_sfp_data ls1028a_data
= {
88 .endian
= REGMAP_ENDIAN_LITTLE
,
91 static const struct of_device_id layerscape_sfp_dt_ids
[] = {
92 { .compatible
= "fsl,ls1021a-sfp", .data
= &ls1021a_data
},
93 { .compatible
= "fsl,ls1028a-sfp", .data
= &ls1028a_data
},
96 MODULE_DEVICE_TABLE(of
, layerscape_sfp_dt_ids
);
98 static struct platform_driver layerscape_sfp_driver
= {
99 .probe
= layerscape_sfp_probe
,
101 .name
= "layerscape_sfp",
102 .of_match_table
= layerscape_sfp_dt_ids
,
105 module_platform_driver(layerscape_sfp_driver
);
107 MODULE_AUTHOR("Michael Walle <michael@walle.cc>");
108 MODULE_DESCRIPTION("Layerscape Security Fuse Processor driver");
109 MODULE_LICENSE("GPL");