1309215d4d7ce4797c580b7cf071f5b1177014bc
[oweals/u-boot.git] / drivers / misc / imx8 / fuse.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright 2019 NXP
4  */
5
6 #include <common.h>
7 #include <console.h>
8 #include <errno.h>
9 #include <fuse.h>
10 #include <asm/arch/sci/sci.h>
11 #include <asm/arch/sys_proto.h>
12
13 DECLARE_GLOBAL_DATA_PTR;
14
15 #define FSL_ECC_WORD_START_1     0x10
16 #define FSL_ECC_WORD_END_1       0x10F
17
18 #define FSL_ECC_WORD_START_2     0x220
19 #define FSL_ECC_WORD_END_2       0x31F
20
21 #define FSL_QXP_FUSE_GAP_START   0x110
22 #define FSL_QXP_FUSE_GAP_END     0x21F
23
24 #define FSL_SIP_OTP_READ             0xc200000A
25 #define FSL_SIP_OTP_WRITE            0xc200000B
26
27 int fuse_read(u32 bank, u32 word, u32 *val)
28 {
29         return fuse_sense(bank, word, val);
30 }
31
32 int fuse_sense(u32 bank, u32 word, u32 *val)
33 {
34         unsigned long ret = 0, value = 0;
35
36         if (bank != 0) {
37                 printf("Invalid bank argument, ONLY bank 0 is supported\n");
38                 return -EINVAL;
39         }
40
41         ret = call_imx_sip_ret2(FSL_SIP_OTP_READ, (unsigned long)word, &value,
42                                 0, 0);
43         *val = (u32)value;
44
45         return ret;
46 }
47
48 int fuse_prog(u32 bank, u32 word, u32 val)
49 {
50         if (bank != 0) {
51                 printf("Invalid bank argument, ONLY bank 0 is supported\n");
52                 return -EINVAL;
53         }
54
55         if (IS_ENABLED(CONFIG_IMX8QXP)) {
56                 if (word >= FSL_QXP_FUSE_GAP_START &&
57                     word <= FSL_QXP_FUSE_GAP_END) {
58                         printf("Invalid word argument for this SoC\n");
59                         return -EINVAL;
60                 }
61         }
62
63         if ((word >= FSL_ECC_WORD_START_1 && word <= FSL_ECC_WORD_END_1) ||
64             (word >= FSL_ECC_WORD_START_2 && word <= FSL_ECC_WORD_END_2)) {
65                 puts("Warning: Words in this index range have ECC protection\n"
66                      "and can only be programmed once per word. Individual bit\n"
67                      "operations will be rejected after the first one.\n"
68                      "\n\n Really program this word? <y/N>\n");
69
70                 if (!confirm_yesno()) {
71                         puts("Word programming aborted\n");
72                         return -EPERM;
73                 }
74         }
75
76         return call_imx_sip(FSL_SIP_OTP_WRITE, (unsigned long)word,
77                             (unsigned long)val, 0, 0);
78 }
79
80 int fuse_override(u32 bank, u32 word, u32 val)
81 {
82         printf("Override fuse to i.MX8 in u-boot is forbidden\n");
83         return -EPERM;
84 }