2 * Rockchip eFuse Driver
4 * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
5 * Author: Caesar Wang <wxt@rock-chips.com>
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of version 2 of the GNU General Public License as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
17 #include <linux/platform_device.h>
18 #include <linux/nvmem-provider.h>
19 #include <linux/slab.h>
20 #include <linux/regmap.h>
21 #include <linux/device.h>
23 #include <linux/module.h>
24 #include <linux/delay.h>
26 #include <linux/clk.h>
28 #define EFUSE_A_SHIFT 6
29 #define EFUSE_A_MASK 0x3ff
30 #define EFUSE_PGENB BIT(3)
31 #define EFUSE_LOAD BIT(2)
32 #define EFUSE_STROBE BIT(1)
33 #define EFUSE_CSB BIT(0)
35 #define REG_EFUSE_CTRL 0x0000
36 #define REG_EFUSE_DOUT 0x0004
38 struct rockchip_efuse_context
{
41 struct clk
*efuse_clk
;
44 static int rockchip_efuse_write(void *context
, const void *data
, size_t count
)
46 /* Nothing TBD, Read-Only */
50 static int rockchip_efuse_read(void *context
,
51 const void *reg
, size_t reg_size
,
52 void *val
, size_t val_size
)
54 unsigned int offset
= *(u32
*)reg
;
55 struct rockchip_efuse_context
*_context
= context
;
56 void __iomem
*base
= _context
->base
;
57 struct clk
*clk
= _context
->efuse_clk
;
61 ret
= clk_prepare_enable(clk
);
63 dev_err(_context
->dev
, "failed to prepare/enable efuse clk\n");
67 writel(EFUSE_LOAD
| EFUSE_PGENB
, base
+ REG_EFUSE_CTRL
);
70 writel(readl(base
+ REG_EFUSE_CTRL
) &
71 (~(EFUSE_A_MASK
<< EFUSE_A_SHIFT
)),
72 base
+ REG_EFUSE_CTRL
);
73 writel(readl(base
+ REG_EFUSE_CTRL
) |
74 ((offset
& EFUSE_A_MASK
) << EFUSE_A_SHIFT
),
75 base
+ REG_EFUSE_CTRL
);
77 writel(readl(base
+ REG_EFUSE_CTRL
) |
78 EFUSE_STROBE
, base
+ REG_EFUSE_CTRL
);
80 *buf
++ = readb(base
+ REG_EFUSE_DOUT
);
81 writel(readl(base
+ REG_EFUSE_CTRL
) &
82 (~EFUSE_STROBE
), base
+ REG_EFUSE_CTRL
);
89 /* Switch to standby mode */
90 writel(EFUSE_PGENB
| EFUSE_CSB
, base
+ REG_EFUSE_CTRL
);
92 clk_disable_unprepare(clk
);
97 static struct regmap_bus rockchip_efuse_bus
= {
98 .read
= rockchip_efuse_read
,
99 .write
= rockchip_efuse_write
,
100 .reg_format_endian_default
= REGMAP_ENDIAN_NATIVE
,
101 .val_format_endian_default
= REGMAP_ENDIAN_NATIVE
,
104 static struct regmap_config rockchip_efuse_regmap_config
= {
110 static struct nvmem_config econfig
= {
111 .name
= "rockchip-efuse",
112 .owner
= THIS_MODULE
,
116 static const struct of_device_id rockchip_efuse_match
[] = {
117 { .compatible
= "rockchip,rockchip-efuse",},
120 MODULE_DEVICE_TABLE(of
, rockchip_efuse_match
);
122 static int rockchip_efuse_probe(struct platform_device
*pdev
)
124 struct device
*dev
= &pdev
->dev
;
125 struct resource
*res
;
126 struct nvmem_device
*nvmem
;
127 struct regmap
*regmap
;
130 struct rockchip_efuse_context
*context
;
132 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
133 base
= devm_ioremap_resource(dev
, res
);
135 return PTR_ERR(base
);
137 context
= devm_kzalloc(dev
, sizeof(struct rockchip_efuse_context
),
140 return PTR_ERR(context
);
142 clk
= devm_clk_get(dev
, "pclk_efuse");
147 context
->base
= base
;
148 context
->efuse_clk
= clk
;
150 rockchip_efuse_regmap_config
.max_register
= resource_size(res
) - 1;
152 regmap
= devm_regmap_init(dev
, &rockchip_efuse_bus
,
153 context
, &rockchip_efuse_regmap_config
);
154 if (IS_ERR(regmap
)) {
155 dev_err(dev
, "regmap init failed\n");
156 return PTR_ERR(regmap
);
159 nvmem
= nvmem_register(&econfig
);
161 return PTR_ERR(nvmem
);
163 platform_set_drvdata(pdev
, nvmem
);
168 static int rockchip_efuse_remove(struct platform_device
*pdev
)
170 struct nvmem_device
*nvmem
= platform_get_drvdata(pdev
);
172 return nvmem_unregister(nvmem
);
175 static struct platform_driver rockchip_efuse_driver
= {
176 .probe
= rockchip_efuse_probe
,
177 .remove
= rockchip_efuse_remove
,
179 .name
= "rockchip-efuse",
180 .of_match_table
= rockchip_efuse_match
,
184 module_platform_driver(rockchip_efuse_driver
);
185 MODULE_DESCRIPTION("rockchip_efuse driver");
186 MODULE_LICENSE("GPL v2");