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/clk.h>
18 #include <linux/delay.h>
19 #include <linux/device.h>
21 #include <linux/module.h>
22 #include <linux/nvmem-provider.h>
23 #include <linux/slab.h>
25 #include <linux/platform_device.h>
27 #define EFUSE_A_SHIFT 6
28 #define EFUSE_A_MASK 0x3ff
29 #define EFUSE_PGENB BIT(3)
30 #define EFUSE_LOAD BIT(2)
31 #define EFUSE_STROBE BIT(1)
32 #define EFUSE_CSB BIT(0)
34 #define REG_EFUSE_CTRL 0x0000
35 #define REG_EFUSE_DOUT 0x0004
37 struct rockchip_efuse_chip
{
43 static int rockchip_efuse_read(void *context
, unsigned int offset
,
44 void *val
, size_t bytes
)
46 struct rockchip_efuse_chip
*efuse
= context
;
50 ret
= clk_prepare_enable(efuse
->clk
);
52 dev_err(efuse
->dev
, "failed to prepare/enable efuse clk\n");
56 writel(EFUSE_LOAD
| EFUSE_PGENB
, efuse
->base
+ REG_EFUSE_CTRL
);
59 writel(readl(efuse
->base
+ REG_EFUSE_CTRL
) &
60 (~(EFUSE_A_MASK
<< EFUSE_A_SHIFT
)),
61 efuse
->base
+ REG_EFUSE_CTRL
);
62 writel(readl(efuse
->base
+ REG_EFUSE_CTRL
) |
63 ((offset
++ & EFUSE_A_MASK
) << EFUSE_A_SHIFT
),
64 efuse
->base
+ REG_EFUSE_CTRL
);
66 writel(readl(efuse
->base
+ REG_EFUSE_CTRL
) |
67 EFUSE_STROBE
, efuse
->base
+ REG_EFUSE_CTRL
);
69 *buf
++ = readb(efuse
->base
+ REG_EFUSE_DOUT
);
70 writel(readl(efuse
->base
+ REG_EFUSE_CTRL
) &
71 (~EFUSE_STROBE
), efuse
->base
+ REG_EFUSE_CTRL
);
75 /* Switch to standby mode */
76 writel(EFUSE_PGENB
| EFUSE_CSB
, efuse
->base
+ REG_EFUSE_CTRL
);
78 clk_disable_unprepare(efuse
->clk
);
83 static struct nvmem_config econfig
= {
84 .name
= "rockchip-efuse",
91 static const struct of_device_id rockchip_efuse_match
[] = {
92 { .compatible
= "rockchip,rockchip-efuse", },
95 MODULE_DEVICE_TABLE(of
, rockchip_efuse_match
);
97 static int rockchip_efuse_probe(struct platform_device
*pdev
)
100 struct nvmem_device
*nvmem
;
101 struct rockchip_efuse_chip
*efuse
;
103 efuse
= devm_kzalloc(&pdev
->dev
, sizeof(struct rockchip_efuse_chip
),
108 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
109 efuse
->base
= devm_ioremap_resource(&pdev
->dev
, res
);
110 if (IS_ERR(efuse
->base
))
111 return PTR_ERR(efuse
->base
);
113 efuse
->clk
= devm_clk_get(&pdev
->dev
, "pclk_efuse");
114 if (IS_ERR(efuse
->clk
))
115 return PTR_ERR(efuse
->clk
);
117 efuse
->dev
= &pdev
->dev
;
118 econfig
.size
= resource_size(res
);
119 econfig
.reg_read
= rockchip_efuse_read
;
120 econfig
.priv
= efuse
;
121 econfig
.dev
= efuse
->dev
;
122 nvmem
= nvmem_register(&econfig
);
124 return PTR_ERR(nvmem
);
126 platform_set_drvdata(pdev
, nvmem
);
131 static int rockchip_efuse_remove(struct platform_device
*pdev
)
133 struct nvmem_device
*nvmem
= platform_get_drvdata(pdev
);
135 return nvmem_unregister(nvmem
);
138 static struct platform_driver rockchip_efuse_driver
= {
139 .probe
= rockchip_efuse_probe
,
140 .remove
= rockchip_efuse_remove
,
142 .name
= "rockchip-efuse",
143 .of_match_table
= rockchip_efuse_match
,
147 module_platform_driver(rockchip_efuse_driver
);
148 MODULE_DESCRIPTION("rockchip_efuse driver");
149 MODULE_LICENSE("GPL v2");