blob: 0a64b7866fe80b46182a9ca406a6a7342f64917f [file] [log] [blame]
xjb04a4022021-11-25 15:01:52 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (c) 2020 MediaTek Inc.
4 */
5
6#include <linux/delay.h>
7#include <linux/mfd/mt6359/registers.h>
8#include <linux/mfd/mt6330/registers.h>
9#include <linux/mfd/mt6397/core.h>
10#include <linux/module.h>
11#include <linux/mutex.h>
12#include <linux/nvmem-provider.h>
13#include <linux/of.h>
14#include <linux/of_device.h>
15#include <linux/platform_device.h>
16#include <linux/regmap.h>
17
18/* PMIC EFUSE registers definition */
19#define RG_OTP_PA 0
20#define RG_OTP_PDIN 1
21#define RG_OTP_PTM 2
22#define RG_OTP_PWE 3
23#define RG_OTP_PPROG 4
24#define RG_OTP_PWE_SRC 5
25#define RG_OTP_PROG_PKEY 6
26#define RG_OTP_RD_PKEY 7
27#define RG_OTP_RD_TRIG 8
28#define RG_RD_RDY_BYPASS 9
29#define RG_SKIP_OTP_OUT 10
30#define RG_OTP_RD_SW 11
31#define RG_OTP_DOUT_SW 12
32#define RG_OTP_RD_BUSY 13
33#define RG_OTP_PA_SW 14
34#define RG_OTP_OSC_CK_EN_SW 15
35
36
37/* Mask definition for EFUSE control engine clock register */
38#define RG_EFUSE_CK_PDN_HWEN_MASK BIT(2)
39#define RG_EFUSE_CK_PDN_MASK BIT(4)
40#define RG_OTP_RD_BUSY_MASK BIT(0)
41#define RG_OTP_OSC_CK_EN_SW_MASK BIT(0)
42#define RG_OTP_OSC_CK_EN_SW_SEL_MASK BIT(1)
43
44
45/* Register SET/CLR offset */
46#define SET_OFFSET 0x2
47#define CLR_OFFSET 0x4
48
49/* EFUSE Register width (bytes) definitions */
50#define EFUSE_REG_WIDTH 2
51
52/* Timeout (us) of polling the status */
53#define EFUSE_POLL_TIMEOUT 30000
54#define EFUSE_POLL_DELAY_US 50
55#define EFUSE_READ_DELAY_US 80
56
57/* efuse attribute for chip dependent charasterictic*/
58#define EFUSE_ATTR_BASIC 0x0
59#define EFUSE_ATTR_OSC_CK 0x1
60#define EFUSE_ATTR_SPMI_8BIT 0x2
61
62struct efuse_chip_data {
63 unsigned int reg_num;
64 unsigned int base;
65 unsigned int ck_pdn;
66 unsigned int ck_pdn_hwen;
67 const unsigned int *regtbl;
68 unsigned int attr;
69};
70
71struct mt6359_efuse {
72 struct device *dev;
73 struct regmap *regmap;
74 struct mutex lock;
75 unsigned int base;
76 const struct efuse_chip_data *data;
77 int trig_sta;
78};
79
80static const unsigned int mt6330_efuse_regs_tbl[] = {
81 0x0,
82 0x1,
83 0x2,
84 0x3,
85 0x4,
86 0x5,
87 0x6,
88 0x8,
89 0xa,
90 0xb,
91 0xc,
92 0xd,
93 0xe,
94 0x10,
95 0x11,
96 -1
97};
98
99static const unsigned int mt6359_efuse_regs_tbl[] = {
100 0x0,
101 0x2,
102 0x4,
103 0x6,
104 0x8,
105 0xA,
106 0xC,
107 0xE,
108 0x10,
109 0x12,
110 0x14,
111 0x16,
112 0x18,
113 0x1A,
114 0x1C
115};
116
117static int mt6359_efuse_poll_busy(struct mt6359_efuse *efuse)
118{
119 int ret;
120 unsigned int val = 0;
121
122 udelay(EFUSE_POLL_DELAY_US);
123 ret = regmap_read_poll_timeout(efuse->regmap,
124 efuse->data->base + efuse->data->regtbl[RG_OTP_RD_BUSY],
125 val,
126 !(val & RG_OTP_RD_BUSY_MASK),
127 EFUSE_POLL_DELAY_US,
128 EFUSE_POLL_TIMEOUT);
129 if (ret) {
130 dev_err(efuse->dev, "timeout to update the efuse status\n");
131 return ret;
132 }
133 return 0;
134}
135
136static int mt6359_efuse_read(void *context, unsigned int offset,
137 void *_val, size_t bytes)
138{
139 struct mt6359_efuse *efuse = context;
140 unsigned int base = efuse->data->base;
141 unsigned int buf = 0;
142 unsigned int offset_end = offset + bytes;
143 unsigned short *val = _val;
144 unsigned int clroffset = CLR_OFFSET, setoffset = SET_OFFSET;
145 int ret;
146
147 if(efuse->data->attr & EFUSE_ATTR_SPMI_8BIT){
148 clroffset >>= 1;
149 setoffset >>= 1;
150 }
151 mutex_lock(&efuse->lock);
152 /* Enable the efuse ctrl engine clock */
153 ret = regmap_write(efuse->regmap,
154 efuse->data->ck_pdn_hwen + clroffset,
155 RG_EFUSE_CK_PDN_HWEN_MASK);
156 if (ret)
157 goto unlock_efuse;
158 ret = regmap_write(efuse->regmap,
159 efuse->data->ck_pdn + clroffset,
160 RG_EFUSE_CK_PDN_MASK);
161 if (ret)
162 goto disable_efuse;
163
164 if(efuse->data->attr & EFUSE_ATTR_OSC_CK){
165 regmap_update_bits(efuse->regmap, base + efuse->data->regtbl[RG_OTP_OSC_CK_EN_SW],
166 RG_OTP_OSC_CK_EN_SW_SEL_MASK, RG_OTP_OSC_CK_EN_SW_SEL_MASK);
167 regmap_update_bits(efuse->regmap, base + efuse->data->regtbl[RG_OTP_OSC_CK_EN_SW],
168 RG_OTP_OSC_CK_EN_SW_MASK, RG_OTP_OSC_CK_EN_SW_MASK);
169 }
170
171 /* Set SW trigger read */
172 ret = regmap_write(efuse->regmap, base + efuse->data->regtbl[RG_OTP_RD_SW], 1);
173 if (ret)
174 goto disable_efuse;
175 for (; offset < offset_end; offset += EFUSE_REG_WIDTH) {
176 /* Set the row to be read, one row is 2 bytes data */
177 ret = regmap_write(efuse->regmap, base + efuse->data->regtbl[RG_OTP_PA], offset);
178 if (ret)
179 goto disable_efuse;
180 /* Start trigger read */
181 efuse->trig_sta = efuse->trig_sta ? 0 : 1;
182 ret = regmap_write(efuse->regmap, base + efuse->data->regtbl[RG_OTP_RD_TRIG],
183 efuse->trig_sta);
184 if (ret) {
185 efuse->trig_sta = efuse->trig_sta ? 0 : 1;
186 goto disable_efuse;
187 }
188
189 /*
190 * Polling the busy status to make sure the reading process
191 * is completed, that means the data can be read out now.
192 */
193 ret = mt6359_efuse_poll_busy(efuse);
194 if (ret)
195 goto disable_efuse;
196
197 /* Read data from efuse memory, must delay before read */
198 udelay(EFUSE_READ_DELAY_US);
199 if(efuse->data->attr & EFUSE_ATTR_SPMI_8BIT)
200 ret = regmap_bulk_read(efuse->regmap, base + efuse->data->regtbl[RG_OTP_DOUT_SW],
201 &buf, 2);
202 else
203 ret = regmap_read(efuse->regmap, base + efuse->data->regtbl[RG_OTP_DOUT_SW],
204 &buf);
205 if (ret)
206 goto disable_efuse;
207 dev_dbg(efuse->dev, "EFUSE[%d]=0x%x\n", offset, buf);
208 *val++ = (unsigned short)buf;
209 }
210disable_efuse:
211 /* Disable SW trigger read */
212 regmap_write(efuse->regmap, base + efuse->data->regtbl[RG_OTP_RD_SW], 0);
213 /* Disable the efuse ctrl engine clock */
214 regmap_write(efuse->regmap, efuse->data->ck_pdn_hwen + setoffset,
215 RG_EFUSE_CK_PDN_HWEN_MASK);
216 regmap_write(efuse->regmap, efuse->data->ck_pdn + setoffset,
217 RG_EFUSE_CK_PDN_MASK);
218 if(efuse->data->attr & EFUSE_ATTR_OSC_CK){
219 regmap_update_bits(efuse->regmap, base + efuse->data->regtbl[RG_OTP_OSC_CK_EN_SW],
220 RG_OTP_OSC_CK_EN_SW_SEL_MASK, 0);
221 regmap_update_bits(efuse->regmap, base + efuse->data->regtbl[RG_OTP_OSC_CK_EN_SW],
222 RG_OTP_OSC_CK_EN_SW_MASK, 0);
223 }
224unlock_efuse:
225 mutex_unlock(&efuse->lock);
226
227 return ret;
228}
229
230static int mt6359_efuse_probe(struct platform_device *pdev)
231{
232 struct nvmem_config econfig = { };
233 struct nvmem_device *nvmem;
234 struct mt6359_efuse *efuse;
235 struct mt6397_chip *chip;
236 int ret;
237
238 chip = dev_get_drvdata(pdev->dev.parent);
239 efuse = devm_kzalloc(&pdev->dev, sizeof(*efuse), GFP_KERNEL);
240 if (!efuse)
241 return -ENOMEM;
242
243 efuse->regmap = chip->regmap;
244 if (!efuse->regmap) {
245 dev_err(&pdev->dev, "failed to get efuse regmap\n");
246 return -ENODEV;
247 }
248
249 efuse->data = of_device_get_match_data(&pdev->dev);
250 if (!efuse->data) {
251 dev_err(&pdev->dev, "failed to get efuse data\n");
252 return -ENODEV;
253 }
254 ret = regmap_read(efuse->regmap, efuse->data->base + efuse->data->regtbl[RG_OTP_RD_TRIG],
255 &efuse->trig_sta);
256 if (ret)
257 return ret;
258
259 mutex_init(&efuse->lock);
260 efuse->dev = &pdev->dev;
261 platform_set_drvdata(pdev, efuse);
262
263 econfig.stride = 2;
264 econfig.word_size = EFUSE_REG_WIDTH;
265 econfig.read_only = true;
266 econfig.name = "mt6359-efuse";
267 econfig.size = efuse->data->reg_num * EFUSE_REG_WIDTH;
268 econfig.reg_read = mt6359_efuse_read;
269 econfig.priv = efuse;
270 econfig.dev = &pdev->dev;
271 nvmem = devm_nvmem_register(&pdev->dev, &econfig);
272 if (IS_ERR(nvmem)) {
273 dev_err(&pdev->dev, "failed to register %s nvmem config\n",
274 econfig.name);
275 mutex_destroy(&efuse->lock);
276 return PTR_ERR(nvmem);
277 }
278
279 return 0;
280}
281
282static const struct efuse_chip_data mt6330_efuse_data = {
283 .reg_num = 128,
284 .base = MT6330_OTP_CON0,
285 .ck_pdn = MT6330_TOP_CKPDN_CON1,
286 .ck_pdn_hwen = MT6330_TOP_CKHWEN_CON0,
287 .regtbl = mt6330_efuse_regs_tbl,
288 .attr = (EFUSE_ATTR_BASIC | EFUSE_ATTR_OSC_CK | EFUSE_ATTR_SPMI_8BIT)
289};
290
291static const struct efuse_chip_data mt6359_efuse_data = {
292 .reg_num = 128,
293 .base = MT6359_OTP_CON0,
294 .ck_pdn = MT6359_TOP_CKPDN_CON0,
295 .ck_pdn_hwen = MT6359_TOP_CKHWEN_CON0,
296 .regtbl = mt6359_efuse_regs_tbl,
297 .attr = EFUSE_ATTR_BASIC
298};
299
300static const struct of_device_id mt6359_efuse_of_match[] = {
301 {
302 .compatible = "mediatek,mt6330-efuse",
303 .data = &mt6330_efuse_data
304 }, {
305 .compatible = "mediatek,mt6359-efuse",
306 .data = &mt6359_efuse_data
307 }, {
308 /* sentinel */
309 }
310};
311
312static struct platform_driver mt6359_efuse_driver = {
313 .probe = mt6359_efuse_probe,
314 .driver = {
315 .name = "mt6359-efuse",
316 .of_match_table = mt6359_efuse_of_match,
317 },
318};
319module_platform_driver(mt6359_efuse_driver);
320
321MODULE_LICENSE("GPL v2");
322MODULE_AUTHOR("Jeter Chen <Jeter.Chen@mediatek.com>");
323MODULE_DESCRIPTION("MediaTek PMIC eFuse Driver for MT6359 PMIC");