1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2019 Spreadtrum Communications Inc.
5 #include <linux/delay.h>
6 #include <linux/hwspinlock.h>
8 #include <linux/module.h>
9 #include <linux/nvmem-provider.h>
10 #include <linux/of_device.h>
11 #include <linux/platform_device.h>
13 #define SPRD_EFUSE_ENABLE 0x20
14 #define SPRD_EFUSE_ERR_FLAG 0x24
15 #define SPRD_EFUSE_ERR_CLR 0x28
16 #define SPRD_EFUSE_MAGIC_NUM 0x2c
17 #define SPRD_EFUSE_FW_CFG 0x50
18 #define SPRD_EFUSE_PW_SWT 0x54
19 #define SPRD_EFUSE_MEM(val) (0x1000 + ((val) << 2))
21 #define SPRD_EFUSE_VDD_EN BIT(0)
22 #define SPRD_EFUSE_AUTO_CHECK_EN BIT(1)
23 #define SPRD_EFUSE_DOUBLE_EN BIT(2)
24 #define SPRD_EFUSE_MARGIN_RD_EN BIT(3)
25 #define SPRD_EFUSE_LOCK_WR_EN BIT(4)
27 #define SPRD_EFUSE_ERR_CLR_MASK GENMASK(13, 0)
29 #define SPRD_EFUSE_ENK1_ON BIT(0)
30 #define SPRD_EFUSE_ENK2_ON BIT(1)
31 #define SPRD_EFUSE_PROG_EN BIT(2)
33 #define SPRD_EFUSE_MAGIC_NUMBER 0x8810
35 /* Block width (bytes) definitions */
36 #define SPRD_EFUSE_BLOCK_WIDTH 4
39 * The Spreadtrum AP efuse contains 2 parts: normal efuse and secure efuse,
40 * and we can only access the normal efuse in kernel. So define the normal
41 * block offset index and normal block numbers.
43 #define SPRD_EFUSE_NORMAL_BLOCK_NUMS 24
44 #define SPRD_EFUSE_NORMAL_BLOCK_OFFSET 72
46 /* Timeout (ms) for the trylock of hardware spinlocks */
47 #define SPRD_EFUSE_HWLOCK_TIMEOUT 5000
50 * Since different Spreadtrum SoC chip can have different normal block numbers
51 * and offset. And some SoC can support block double feature, which means
52 * when reading or writing data to efuse memory, the controller can save double
53 * data in case one data become incorrect after a long period.
55 * Thus we should save them in the device data structure.
57 struct sprd_efuse_variant_data
{
66 struct hwspinlock
*hwlock
;
69 const struct sprd_efuse_variant_data
*data
;
72 static const struct sprd_efuse_variant_data ums312_data
= {
73 .blk_nums
= SPRD_EFUSE_NORMAL_BLOCK_NUMS
,
74 .blk_offset
= SPRD_EFUSE_NORMAL_BLOCK_OFFSET
,
79 * On Spreadtrum platform, we have multi-subsystems will access the unique
80 * efuse controller, so we need one hardware spinlock to synchronize between
81 * the multiple subsystems.
83 static int sprd_efuse_lock(struct sprd_efuse
*efuse
)
87 mutex_lock(&efuse
->mutex
);
89 ret
= hwspin_lock_timeout_raw(efuse
->hwlock
,
90 SPRD_EFUSE_HWLOCK_TIMEOUT
);
92 dev_err(efuse
->dev
, "timeout get the hwspinlock\n");
93 mutex_unlock(&efuse
->mutex
);
100 static void sprd_efuse_unlock(struct sprd_efuse
*efuse
)
102 hwspin_unlock_raw(efuse
->hwlock
);
103 mutex_unlock(&efuse
->mutex
);
106 static void sprd_efuse_set_prog_power(struct sprd_efuse
*efuse
, bool en
)
108 u32 val
= readl(efuse
->base
+ SPRD_EFUSE_PW_SWT
);
111 val
&= ~SPRD_EFUSE_ENK2_ON
;
113 val
&= ~SPRD_EFUSE_ENK1_ON
;
115 writel(val
, efuse
->base
+ SPRD_EFUSE_PW_SWT
);
117 /* Open or close efuse power need wait 1000us to make power stable. */
118 usleep_range(1000, 1200);
121 val
|= SPRD_EFUSE_ENK1_ON
;
123 val
|= SPRD_EFUSE_ENK2_ON
;
125 writel(val
, efuse
->base
+ SPRD_EFUSE_PW_SWT
);
127 /* Open or close efuse power need wait 1000us to make power stable. */
128 usleep_range(1000, 1200);
131 static void sprd_efuse_set_read_power(struct sprd_efuse
*efuse
, bool en
)
133 u32 val
= readl(efuse
->base
+ SPRD_EFUSE_ENABLE
);
136 val
|= SPRD_EFUSE_VDD_EN
;
138 val
&= ~SPRD_EFUSE_VDD_EN
;
140 writel(val
, efuse
->base
+ SPRD_EFUSE_ENABLE
);
142 /* Open or close efuse power need wait 1000us to make power stable. */
143 usleep_range(1000, 1200);
146 static void sprd_efuse_set_prog_lock(struct sprd_efuse
*efuse
, bool en
)
148 u32 val
= readl(efuse
->base
+ SPRD_EFUSE_ENABLE
);
151 val
|= SPRD_EFUSE_LOCK_WR_EN
;
153 val
&= ~SPRD_EFUSE_LOCK_WR_EN
;
155 writel(val
, efuse
->base
+ SPRD_EFUSE_ENABLE
);
158 static void sprd_efuse_set_auto_check(struct sprd_efuse
*efuse
, bool en
)
160 u32 val
= readl(efuse
->base
+ SPRD_EFUSE_ENABLE
);
163 val
|= SPRD_EFUSE_AUTO_CHECK_EN
;
165 val
&= ~SPRD_EFUSE_AUTO_CHECK_EN
;
167 writel(val
, efuse
->base
+ SPRD_EFUSE_ENABLE
);
170 static void sprd_efuse_set_data_double(struct sprd_efuse
*efuse
, bool en
)
172 u32 val
= readl(efuse
->base
+ SPRD_EFUSE_ENABLE
);
175 val
|= SPRD_EFUSE_DOUBLE_EN
;
177 val
&= ~SPRD_EFUSE_DOUBLE_EN
;
179 writel(val
, efuse
->base
+ SPRD_EFUSE_ENABLE
);
182 static void sprd_efuse_set_prog_en(struct sprd_efuse
*efuse
, bool en
)
184 u32 val
= readl(efuse
->base
+ SPRD_EFUSE_PW_SWT
);
187 val
|= SPRD_EFUSE_PROG_EN
;
189 val
&= ~SPRD_EFUSE_PROG_EN
;
191 writel(val
, efuse
->base
+ SPRD_EFUSE_PW_SWT
);
194 static int sprd_efuse_raw_prog(struct sprd_efuse
*efuse
, u32 blk
, bool doub
,
195 bool lock
, u32
*data
)
201 * We need set the correct magic number before writing the efuse to
202 * allow programming, and block other programming until we clear the
205 writel(SPRD_EFUSE_MAGIC_NUMBER
,
206 efuse
->base
+ SPRD_EFUSE_MAGIC_NUM
);
209 * Power on the efuse, enable programme and enable double data
212 sprd_efuse_set_prog_power(efuse
, true);
213 sprd_efuse_set_prog_en(efuse
, true);
214 sprd_efuse_set_data_double(efuse
, doub
);
217 * Enable the auto-check function to validate if the programming is
221 sprd_efuse_set_auto_check(efuse
, true);
223 writel(*data
, efuse
->base
+ SPRD_EFUSE_MEM(blk
));
225 /* Disable auto-check and data double after programming */
227 sprd_efuse_set_auto_check(efuse
, false);
228 sprd_efuse_set_data_double(efuse
, false);
231 * Check the efuse error status, if the programming is successful,
232 * we should lock this efuse block to avoid programming again.
234 status
= readl(efuse
->base
+ SPRD_EFUSE_ERR_FLAG
);
237 "write error status %d of block %d\n", ret
, blk
);
239 writel(SPRD_EFUSE_ERR_CLR_MASK
,
240 efuse
->base
+ SPRD_EFUSE_ERR_CLR
);
243 sprd_efuse_set_prog_lock(efuse
, lock
);
244 writel(0, efuse
->base
+ SPRD_EFUSE_MEM(blk
));
245 sprd_efuse_set_prog_lock(efuse
, false);
248 sprd_efuse_set_prog_power(efuse
, false);
249 writel(0, efuse
->base
+ SPRD_EFUSE_MAGIC_NUM
);
254 static int sprd_efuse_raw_read(struct sprd_efuse
*efuse
, int blk
, u32
*val
,
260 * Need power on the efuse before reading data from efuse, and will
261 * power off the efuse after reading process.
263 sprd_efuse_set_read_power(efuse
, true);
265 /* Enable double data if asked */
266 sprd_efuse_set_data_double(efuse
, doub
);
268 /* Start to read data from efuse block */
269 *val
= readl(efuse
->base
+ SPRD_EFUSE_MEM(blk
));
271 /* Disable double data */
272 sprd_efuse_set_data_double(efuse
, false);
274 /* Power off the efuse */
275 sprd_efuse_set_read_power(efuse
, false);
278 * Check the efuse error status and clear them if there are some
281 status
= readl(efuse
->base
+ SPRD_EFUSE_ERR_FLAG
);
284 "read error status %d of block %d\n", status
, blk
);
286 writel(SPRD_EFUSE_ERR_CLR_MASK
,
287 efuse
->base
+ SPRD_EFUSE_ERR_CLR
);
294 static int sprd_efuse_read(void *context
, u32 offset
, void *val
, size_t bytes
)
296 struct sprd_efuse
*efuse
= context
;
297 bool blk_double
= efuse
->data
->blk_double
;
298 u32 index
= offset
/ SPRD_EFUSE_BLOCK_WIDTH
+ efuse
->data
->blk_offset
;
299 u32 blk_offset
= (offset
% SPRD_EFUSE_BLOCK_WIDTH
) * BITS_PER_BYTE
;
303 ret
= sprd_efuse_lock(efuse
);
307 ret
= clk_prepare_enable(efuse
->clk
);
311 ret
= sprd_efuse_raw_read(efuse
, index
, &data
, blk_double
);
314 memcpy(val
, &data
, bytes
);
317 clk_disable_unprepare(efuse
->clk
);
320 sprd_efuse_unlock(efuse
);
324 static int sprd_efuse_write(void *context
, u32 offset
, void *val
, size_t bytes
)
326 struct sprd_efuse
*efuse
= context
;
327 bool blk_double
= efuse
->data
->blk_double
;
331 ret
= sprd_efuse_lock(efuse
);
335 ret
= clk_prepare_enable(efuse
->clk
);
340 * If the writing bytes are equal with the block width, which means the
341 * whole block will be programmed. For this case, we should not allow
342 * this block to be programmed again by locking this block.
344 * If the block was programmed partially, we should allow this block to
345 * be programmed again.
347 if (bytes
< SPRD_EFUSE_BLOCK_WIDTH
)
352 ret
= sprd_efuse_raw_prog(efuse
, offset
, blk_double
, lock
, val
);
354 clk_disable_unprepare(efuse
->clk
);
357 sprd_efuse_unlock(efuse
);
361 static int sprd_efuse_probe(struct platform_device
*pdev
)
363 struct device_node
*np
= pdev
->dev
.of_node
;
364 struct nvmem_device
*nvmem
;
365 struct nvmem_config econfig
= { };
366 struct sprd_efuse
*efuse
;
367 const struct sprd_efuse_variant_data
*pdata
;
370 pdata
= of_device_get_match_data(&pdev
->dev
);
372 dev_err(&pdev
->dev
, "No matching driver data found\n");
376 efuse
= devm_kzalloc(&pdev
->dev
, sizeof(*efuse
), GFP_KERNEL
);
380 efuse
->base
= devm_platform_ioremap_resource(pdev
, 0);
381 if (IS_ERR(efuse
->base
))
382 return PTR_ERR(efuse
->base
);
384 ret
= of_hwspin_lock_get_id(np
, 0);
386 dev_err(&pdev
->dev
, "failed to get hwlock id\n");
390 efuse
->hwlock
= devm_hwspin_lock_request_specific(&pdev
->dev
, ret
);
391 if (!efuse
->hwlock
) {
392 dev_err(&pdev
->dev
, "failed to request hwlock\n");
396 efuse
->clk
= devm_clk_get(&pdev
->dev
, "enable");
397 if (IS_ERR(efuse
->clk
)) {
398 dev_err(&pdev
->dev
, "failed to get enable clock\n");
399 return PTR_ERR(efuse
->clk
);
402 mutex_init(&efuse
->mutex
);
403 efuse
->dev
= &pdev
->dev
;
407 econfig
.word_size
= 1;
408 econfig
.read_only
= false;
409 econfig
.name
= "sprd-efuse";
410 econfig
.size
= efuse
->data
->blk_nums
* SPRD_EFUSE_BLOCK_WIDTH
;
411 econfig
.reg_read
= sprd_efuse_read
;
412 econfig
.reg_write
= sprd_efuse_write
;
413 econfig
.priv
= efuse
;
414 econfig
.dev
= &pdev
->dev
;
415 nvmem
= devm_nvmem_register(&pdev
->dev
, &econfig
);
417 dev_err(&pdev
->dev
, "failed to register nvmem\n");
418 return PTR_ERR(nvmem
);
424 static const struct of_device_id sprd_efuse_of_match
[] = {
425 { .compatible
= "sprd,ums312-efuse", .data
= &ums312_data
},
429 static struct platform_driver sprd_efuse_driver
= {
430 .probe
= sprd_efuse_probe
,
432 .name
= "sprd-efuse",
433 .of_match_table
= sprd_efuse_of_match
,
437 module_platform_driver(sprd_efuse_driver
);
439 MODULE_AUTHOR("Freeman Liu <freeman.liu@spreadtrum.com>");
440 MODULE_DESCRIPTION("Spreadtrum AP efuse driver");
441 MODULE_LICENSE("GPL v2");