1 | // SPDX-License-Identifier: GPL-2.0 |
2 | |
3 | /* |
4 | * The OCOTP driver for Sunplus SP7021 |
5 | * |
6 | * Copyright (C) 2019 Sunplus Technology Inc., All rights reserved. |
7 | */ |
8 | |
9 | #include <linux/bitfield.h> |
10 | #include <linux/clk.h> |
11 | #include <linux/delay.h> |
12 | #include <linux/device.h> |
13 | #include <linux/io.h> |
14 | #include <linux/iopoll.h> |
15 | #include <linux/module.h> |
16 | #include <linux/mod_devicetable.h> |
17 | #include <linux/nvmem-provider.h> |
18 | #include <linux/platform_device.h> |
19 | |
20 | /* |
21 | * OTP memory |
22 | * Each bank contains 4 words (32 bits). |
23 | * Bank 0 starts at offset 0 from the base. |
24 | */ |
25 | |
26 | #define OTP_WORDS_PER_BANK 4 |
27 | #define OTP_WORD_SIZE sizeof(u32) |
28 | #define OTP_BIT_ADDR_OF_BANK (8 * OTP_WORD_SIZE * OTP_WORDS_PER_BANK) |
29 | #define QAC628_OTP_NUM_BANKS 8 |
30 | #define QAC628_OTP_SIZE (QAC628_OTP_NUM_BANKS * OTP_WORDS_PER_BANK * OTP_WORD_SIZE) |
31 | #define OTP_READ_TIMEOUT_US 200000 |
32 | |
33 | /* HB_GPIO */ |
34 | #define ADDRESS_8_DATA 0x20 |
35 | |
36 | /* OTP_RX */ |
37 | #define OTP_CONTROL_2 0x48 |
38 | #define OTP_RD_PERIOD GENMASK(15, 8) |
39 | #define OTP_RD_PERIOD_MASK ~GENMASK(15, 8) |
40 | #define CPU_CLOCK FIELD_PREP(OTP_RD_PERIOD, 30) |
41 | #define SEL_BAK_KEY2 BIT(5) |
42 | #define SEL_BAK_KEY2_MASK ~BIT(5) |
43 | #define SW_TRIM_EN BIT(4) |
44 | #define SW_TRIM_EN_MASK ~BIT(4) |
45 | #define SEL_BAK_KEY BIT(3) |
46 | #define SEL_BAK_KEY_MASK ~BIT(3) |
47 | #define OTP_READ BIT(2) |
48 | #define OTP_LOAD_SECURE_DATA BIT(1) |
49 | #define OTP_LOAD_SECURE_DATA_MASK ~BIT(1) |
50 | #define OTP_DO_CRC BIT(0) |
51 | #define OTP_DO_CRC_MASK ~BIT(0) |
52 | #define OTP_STATUS 0x4c |
53 | #define OTP_READ_DONE BIT(4) |
54 | #define OTP_READ_DONE_MASK ~BIT(4) |
55 | #define OTP_LOAD_SECURE_DONE_MASK ~BIT(2) |
56 | #define OTP_READ_ADDRESS 0x50 |
57 | |
58 | enum base_type { |
59 | HB_GPIO, |
60 | OTPRX, |
61 | BASEMAX, |
62 | }; |
63 | |
64 | struct sp_ocotp_priv { |
65 | struct device *dev; |
66 | void __iomem *base[BASEMAX]; |
67 | struct clk *clk; |
68 | }; |
69 | |
70 | struct sp_ocotp_data { |
71 | int size; |
72 | }; |
73 | |
74 | static const struct sp_ocotp_data sp_otp_v0 = { |
75 | .size = QAC628_OTP_SIZE, |
76 | }; |
77 | |
78 | static int sp_otp_read_real(struct sp_ocotp_priv *otp, int addr, char *value) |
79 | { |
80 | unsigned int addr_data; |
81 | unsigned int byte_shift; |
82 | unsigned int status; |
83 | int ret; |
84 | |
85 | addr_data = addr % (OTP_WORD_SIZE * OTP_WORDS_PER_BANK); |
86 | addr_data = addr_data / OTP_WORD_SIZE; |
87 | |
88 | byte_shift = addr % (OTP_WORD_SIZE * OTP_WORDS_PER_BANK); |
89 | byte_shift = byte_shift % OTP_WORD_SIZE; |
90 | |
91 | addr = addr / (OTP_WORD_SIZE * OTP_WORDS_PER_BANK); |
92 | addr = addr * OTP_BIT_ADDR_OF_BANK; |
93 | |
94 | writel(readl(addr: otp->base[OTPRX] + OTP_STATUS) & OTP_READ_DONE_MASK & |
95 | OTP_LOAD_SECURE_DONE_MASK, addr: otp->base[OTPRX] + OTP_STATUS); |
96 | writel(val: addr, addr: otp->base[OTPRX] + OTP_READ_ADDRESS); |
97 | writel(readl(addr: otp->base[OTPRX] + OTP_CONTROL_2) | OTP_READ, |
98 | addr: otp->base[OTPRX] + OTP_CONTROL_2); |
99 | writel(readl(addr: otp->base[OTPRX] + OTP_CONTROL_2) & SEL_BAK_KEY2_MASK & SW_TRIM_EN_MASK |
100 | & SEL_BAK_KEY_MASK & OTP_LOAD_SECURE_DATA_MASK & OTP_DO_CRC_MASK, |
101 | addr: otp->base[OTPRX] + OTP_CONTROL_2); |
102 | writel(val: (readl(addr: otp->base[OTPRX] + OTP_CONTROL_2) & OTP_RD_PERIOD_MASK) | CPU_CLOCK, |
103 | addr: otp->base[OTPRX] + OTP_CONTROL_2); |
104 | |
105 | ret = readl_poll_timeout(otp->base[OTPRX] + OTP_STATUS, status, |
106 | status & OTP_READ_DONE, 10, OTP_READ_TIMEOUT_US); |
107 | |
108 | if (ret < 0) |
109 | return ret; |
110 | |
111 | *value = (readl(addr: otp->base[HB_GPIO] + ADDRESS_8_DATA + addr_data * OTP_WORD_SIZE) |
112 | >> (8 * byte_shift)) & 0xff; |
113 | |
114 | return ret; |
115 | } |
116 | |
117 | static int sp_ocotp_read(void *priv, unsigned int offset, void *value, size_t bytes) |
118 | { |
119 | struct sp_ocotp_priv *otp = priv; |
120 | unsigned int addr; |
121 | char *buf = value; |
122 | char val[4]; |
123 | int ret; |
124 | |
125 | ret = clk_enable(clk: otp->clk); |
126 | if (ret) |
127 | return ret; |
128 | |
129 | *buf = 0; |
130 | for (addr = offset; addr < (offset + bytes); addr++) { |
131 | ret = sp_otp_read_real(otp, addr, value: val); |
132 | if (ret < 0) { |
133 | dev_err(otp->dev, "OTP read fail:%d at %d" , ret, addr); |
134 | goto disable_clk; |
135 | } |
136 | |
137 | *buf++ = *val; |
138 | } |
139 | |
140 | disable_clk: |
141 | clk_disable(clk: otp->clk); |
142 | |
143 | return ret; |
144 | } |
145 | |
146 | static struct nvmem_config sp_ocotp_nvmem_config = { |
147 | .name = "sp-ocotp" , |
148 | .add_legacy_fixed_of_cells = true, |
149 | .read_only = true, |
150 | .word_size = 1, |
151 | .size = QAC628_OTP_SIZE, |
152 | .stride = 1, |
153 | .reg_read = sp_ocotp_read, |
154 | .owner = THIS_MODULE, |
155 | }; |
156 | |
157 | static int sp_ocotp_probe(struct platform_device *pdev) |
158 | { |
159 | struct device *dev = &pdev->dev; |
160 | struct nvmem_device *nvmem; |
161 | struct sp_ocotp_priv *otp; |
162 | struct resource *res; |
163 | int ret; |
164 | |
165 | otp = devm_kzalloc(dev, size: sizeof(*otp), GFP_KERNEL); |
166 | if (!otp) |
167 | return -ENOMEM; |
168 | |
169 | otp->dev = dev; |
170 | |
171 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hb_gpio" ); |
172 | otp->base[HB_GPIO] = devm_ioremap_resource(dev, res); |
173 | if (IS_ERR(ptr: otp->base[HB_GPIO])) |
174 | return PTR_ERR(ptr: otp->base[HB_GPIO]); |
175 | |
176 | res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "otprx" ); |
177 | otp->base[OTPRX] = devm_ioremap_resource(dev, res); |
178 | if (IS_ERR(ptr: otp->base[OTPRX])) |
179 | return PTR_ERR(ptr: otp->base[OTPRX]); |
180 | |
181 | otp->clk = devm_clk_get(dev: &pdev->dev, NULL); |
182 | if (IS_ERR(ptr: otp->clk)) |
183 | return dev_err_probe(dev: &pdev->dev, err: PTR_ERR(ptr: otp->clk), |
184 | fmt: "devm_clk_get fail\n" ); |
185 | |
186 | ret = clk_prepare(clk: otp->clk); |
187 | if (ret < 0) { |
188 | dev_err(dev, "failed to prepare clk: %d\n" , ret); |
189 | return ret; |
190 | } |
191 | |
192 | sp_ocotp_nvmem_config.priv = otp; |
193 | sp_ocotp_nvmem_config.dev = dev; |
194 | |
195 | nvmem = devm_nvmem_register(dev, cfg: &sp_ocotp_nvmem_config); |
196 | if (IS_ERR(ptr: nvmem)) { |
197 | ret = dev_err_probe(dev: &pdev->dev, err: PTR_ERR(ptr: nvmem), |
198 | fmt: "register nvmem device fail\n" ); |
199 | goto err; |
200 | } |
201 | |
202 | platform_set_drvdata(pdev, data: nvmem); |
203 | |
204 | dev_dbg(dev, "banks:%d x wpb:%d x wsize:%d = %d" , |
205 | (int)QAC628_OTP_NUM_BANKS, (int)OTP_WORDS_PER_BANK, |
206 | (int)OTP_WORD_SIZE, (int)QAC628_OTP_SIZE); |
207 | |
208 | return 0; |
209 | err: |
210 | clk_unprepare(clk: otp->clk); |
211 | return ret; |
212 | } |
213 | |
214 | static const struct of_device_id sp_ocotp_dt_ids[] = { |
215 | { .compatible = "sunplus,sp7021-ocotp" , .data = &sp_otp_v0 }, |
216 | { } |
217 | }; |
218 | MODULE_DEVICE_TABLE(of, sp_ocotp_dt_ids); |
219 | |
220 | static struct platform_driver sp_otp_driver = { |
221 | .probe = sp_ocotp_probe, |
222 | .driver = { |
223 | .name = "sunplus,sp7021-ocotp" , |
224 | .of_match_table = sp_ocotp_dt_ids, |
225 | } |
226 | }; |
227 | module_platform_driver(sp_otp_driver); |
228 | |
229 | MODULE_AUTHOR("Vincent Shih <vincent.sunplus@gmail.com>" ); |
230 | MODULE_DESCRIPTION("Sunplus On-Chip OTP driver" ); |
231 | MODULE_LICENSE("GPL" ); |
232 | |
233 | |