986734aef252060b9bf931b81653ab40d6e99b71
[firefly-linux-kernel-4.4.55.git] / drivers / nvmem / rockchip-efuse.c
1 /*
2  * Rockchip eFuse Driver
3  *
4  * Copyright (c) 2015 Rockchip Electronics Co. Ltd.
5  * Author: Caesar Wang <wxt@rock-chips.com>
6  *
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.
10  *
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
14  * more details.
15  */
16
17 #include <linux/clk.h>
18 #include <linux/delay.h>
19 #include <linux/device.h>
20 #include <linux/io.h>
21 #include <linux/module.h>
22 #include <linux/nvmem-provider.h>
23 #include <linux/slab.h>
24 #include <linux/of.h>
25 #include <linux/of_platform.h>
26 #include <linux/platform_device.h>
27 #include <linux/rockchip/rockchip_sip.h>
28
29 #define RK3288_A_SHIFT          6
30 #define RK3288_A_MASK           0x3ff
31 #define RK3288_PGENB            BIT(3)
32 #define RK3288_LOAD             BIT(2)
33 #define RK3288_STROBE           BIT(1)
34 #define RK3288_CSB              BIT(0)
35
36 #define RK3366_A_SHIFT          6
37 #define RK3366_A_MASK           0x3ff
38 #define RK3366_RDEN             BIT(2)
39 #define RK3366_AEN              BIT(1)
40
41 #define RK3399_A_SHIFT          16
42 #define RK3399_A_MASK           0x3ff
43 #define RK3399_NBYTES           4
44 #define RK3399_STROBSFTSEL      BIT(9)
45 #define RK3399_RSB              BIT(7)
46 #define RK3399_PD               BIT(5)
47 #define RK3399_PGENB            BIT(3)
48 #define RK3399_LOAD             BIT(2)
49 #define RK3399_STROBE           BIT(1)
50 #define RK3399_CSB              BIT(0)
51
52 #define REG_EFUSE_CTRL          0x0000
53 #define REG_EFUSE_DOUT          0x0004
54
55 struct rockchip_efuse_chip {
56         struct device *dev;
57         void __iomem *base;
58         struct clk *clk;
59         phys_addr_t phys;
60 };
61
62 static int rockchip_rk3288_efuse_read(void *context, unsigned int offset,
63                                       void *val, size_t bytes)
64 {
65         struct rockchip_efuse_chip *efuse = context;
66         u8 *buf = val;
67         int ret;
68
69         ret = clk_prepare_enable(efuse->clk);
70         if (ret < 0) {
71                 dev_err(efuse->dev, "failed to prepare/enable efuse clk\n");
72                 return ret;
73         }
74
75         writel(RK3288_LOAD | RK3288_PGENB, efuse->base + REG_EFUSE_CTRL);
76         udelay(1);
77         while (bytes--) {
78                 writel(readl(efuse->base + REG_EFUSE_CTRL) &
79                              (~(RK3288_A_MASK << RK3288_A_SHIFT)),
80                              efuse->base + REG_EFUSE_CTRL);
81                 writel(readl(efuse->base + REG_EFUSE_CTRL) |
82                              ((offset++ & RK3288_A_MASK) << RK3288_A_SHIFT),
83                              efuse->base + REG_EFUSE_CTRL);
84                 udelay(1);
85                 writel(readl(efuse->base + REG_EFUSE_CTRL) |
86                              RK3288_STROBE, efuse->base + REG_EFUSE_CTRL);
87                 udelay(1);
88                 *buf++ = readb(efuse->base + REG_EFUSE_DOUT);
89                 writel(readl(efuse->base + REG_EFUSE_CTRL) &
90                        (~RK3288_STROBE), efuse->base + REG_EFUSE_CTRL);
91                 udelay(1);
92         }
93
94         /* Switch to standby mode */
95         writel(RK3288_PGENB | RK3288_CSB, efuse->base + REG_EFUSE_CTRL);
96
97         clk_disable_unprepare(efuse->clk);
98
99         return 0;
100 }
101
102 static int rockchip_rk3366_efuse_read(void *context, unsigned int offset,
103                                       void *val, size_t bytes)
104 {
105         struct rockchip_efuse_chip *efuse = context;
106         u8 *buf = val;
107         int ret;
108
109         ret = clk_prepare_enable(efuse->clk);
110         if (ret < 0) {
111                 dev_err(efuse->dev, "failed to prepare/enable efuse clk\n");
112                 return ret;
113         }
114
115         writel(RK3366_RDEN, efuse->base + REG_EFUSE_CTRL);
116         udelay(1);
117         while (bytes--) {
118                 writel(readl(efuse->base + REG_EFUSE_CTRL) &
119                        (~(RK3366_A_MASK << RK3366_A_SHIFT)),
120                        efuse->base + REG_EFUSE_CTRL);
121                 writel(readl(efuse->base + REG_EFUSE_CTRL) |
122                        ((offset++ & RK3366_A_MASK) << RK3366_A_SHIFT),
123                        efuse->base + REG_EFUSE_CTRL);
124                 udelay(1);
125                 writel(readl(efuse->base + REG_EFUSE_CTRL) |
126                        RK3366_AEN, efuse->base + REG_EFUSE_CTRL);
127                 udelay(1);
128                 *buf++ = readb(efuse->base + REG_EFUSE_DOUT);
129                 writel(readl(efuse->base + REG_EFUSE_CTRL) &
130                        (~RK3366_AEN), efuse->base + REG_EFUSE_CTRL);
131                 udelay(1);
132         }
133
134         writel(readl(efuse->base + REG_EFUSE_CTRL) &
135                (~RK3366_RDEN), efuse->base + REG_EFUSE_CTRL);
136
137         clk_disable_unprepare(efuse->clk);
138
139         return 0;
140 }
141
142 static int rockchip_rk3368_efuse_read(void *context, unsigned int offset,
143                                       void *val, size_t bytes)
144 {
145         struct rockchip_efuse_chip *efuse = context;
146         u8 *buf = val;
147         u32 wr_val;
148         int ret;
149
150         ret = clk_prepare_enable(efuse->clk);
151         if (ret < 0) {
152                 dev_err(efuse->dev, "failed to prepare/enable efuse clk\n");
153                 return ret;
154         }
155
156         sip_smc_secure_reg_write(efuse->phys + REG_EFUSE_CTRL,
157                                  RK3288_LOAD | RK3288_PGENB);
158         udelay(1);
159         while (bytes--) {
160                 wr_val = sip_smc_secure_reg_read(efuse->phys + REG_EFUSE_CTRL) &
161                          (~(RK3288_A_MASK << RK3288_A_SHIFT));
162                 sip_smc_secure_reg_write(efuse->phys + REG_EFUSE_CTRL, wr_val);
163                 wr_val = sip_smc_secure_reg_read(efuse->phys + REG_EFUSE_CTRL) |
164                          ((offset++ & RK3288_A_MASK) << RK3288_A_SHIFT);
165                 sip_smc_secure_reg_write(efuse->phys + REG_EFUSE_CTRL, wr_val);
166                 udelay(1);
167                 wr_val = sip_smc_secure_reg_read(efuse->phys + REG_EFUSE_CTRL) |
168                          RK3288_STROBE;
169                 sip_smc_secure_reg_write(efuse->phys + REG_EFUSE_CTRL, wr_val);
170                 udelay(1);
171                 *buf++ = sip_smc_secure_reg_read(efuse->phys + REG_EFUSE_DOUT);
172                 wr_val = sip_smc_secure_reg_read(efuse->phys + REG_EFUSE_CTRL) &
173                          (~RK3288_STROBE);
174                 sip_smc_secure_reg_write(efuse->phys + REG_EFUSE_CTRL, wr_val);
175                 udelay(1);
176         }
177
178         /* Switch to standby mode */
179         sip_smc_secure_reg_write(efuse->phys + REG_EFUSE_CTRL,
180                                  RK3288_PGENB | RK3288_CSB);
181
182         clk_disable_unprepare(efuse->clk);
183
184         return 0;
185 }
186
187 static int rockchip_rk3399_efuse_read(void *context, unsigned int offset,
188                                       void *val, size_t bytes)
189 {
190         struct rockchip_efuse_chip *efuse = context;
191         unsigned int addr_start, addr_end, addr_offset, addr_len;
192         u32 out_value;
193         u8 *buf;
194         int ret, i = 0;
195
196         ret = clk_prepare_enable(efuse->clk);
197         if (ret < 0) {
198                 dev_err(efuse->dev, "failed to prepare/enable efuse clk\n");
199                 return ret;
200         }
201
202         addr_start = rounddown(offset, RK3399_NBYTES) / RK3399_NBYTES;
203         addr_end = roundup(offset + bytes, RK3399_NBYTES) / RK3399_NBYTES;
204         addr_offset = offset % RK3399_NBYTES;
205         addr_len = addr_end - addr_start;
206
207         buf = kzalloc(sizeof(*buf) * addr_len * RK3399_NBYTES, GFP_KERNEL);
208         if (!buf) {
209                 clk_disable_unprepare(efuse->clk);
210                 return -ENOMEM;
211         }
212
213         writel(RK3399_LOAD | RK3399_PGENB | RK3399_STROBSFTSEL | RK3399_RSB,
214                efuse->base + REG_EFUSE_CTRL);
215         udelay(1);
216         while (addr_len--) {
217                 writel(readl(efuse->base + REG_EFUSE_CTRL) | RK3399_STROBE |
218                        ((addr_start++ & RK3399_A_MASK) << RK3399_A_SHIFT),
219                        efuse->base + REG_EFUSE_CTRL);
220                 udelay(1);
221                 out_value = readl(efuse->base + REG_EFUSE_DOUT);
222                 writel(readl(efuse->base + REG_EFUSE_CTRL) & (~RK3399_STROBE),
223                        efuse->base + REG_EFUSE_CTRL);
224                 udelay(1);
225
226                 memcpy(&buf[i], &out_value, RK3399_NBYTES);
227                 i += RK3399_NBYTES;
228         }
229
230         /* Switch to standby mode */
231         writel(RK3399_PD | RK3399_CSB, efuse->base + REG_EFUSE_CTRL);
232
233         memcpy(val, buf + addr_offset, bytes);
234
235         kfree(buf);
236
237         clk_disable_unprepare(efuse->clk);
238
239         return 0;
240 }
241
242 static struct nvmem_config econfig = {
243         .name = "rockchip-efuse",
244         .owner = THIS_MODULE,
245         .stride = 1,
246         .word_size = 1,
247         .read_only = true,
248 };
249
250 static const struct of_device_id rockchip_efuse_match[] = {
251         /* deprecated but kept around for dts binding compatibility */
252         {
253                 .compatible = "rockchip,rockchip-efuse",
254                 .data = (void *)&rockchip_rk3288_efuse_read,
255         },
256         {
257                 .compatible = "rockchip,rk3066a-efuse",
258                 .data = (void *)&rockchip_rk3288_efuse_read,
259         },
260         {
261                 .compatible = "rockchip,rk3188-efuse",
262                 .data = (void *)&rockchip_rk3288_efuse_read,
263         },
264         {
265                 .compatible = "rockchip,rk3288-efuse",
266                 .data = (void *)&rockchip_rk3288_efuse_read,
267         },
268         {
269                 .compatible = "rockchip,rk3366-efuse",
270                 .data = (void *)&rockchip_rk3366_efuse_read,
271         },
272         {
273                 .compatible = "rockchip,rk3368-efuse",
274                 .data = (void *)&rockchip_rk3368_efuse_read,
275         },
276         {
277                 .compatible = "rockchip,rk3399-efuse",
278                 .data = (void *)&rockchip_rk3399_efuse_read,
279         },
280         { /* sentinel */},
281 };
282 MODULE_DEVICE_TABLE(of, rockchip_efuse_match);
283
284 static int __init rockchip_efuse_probe(struct platform_device *pdev)
285 {
286         struct resource *res;
287         struct nvmem_device *nvmem;
288         struct rockchip_efuse_chip *efuse;
289         const struct of_device_id *match;
290         struct device *dev = &pdev->dev;
291
292         match = of_match_device(dev->driver->of_match_table, dev);
293         if (!match || !match->data) {
294                 dev_err(dev, "failed to get match data\n");
295                 return -EINVAL;
296         }
297
298         efuse = devm_kzalloc(&pdev->dev, sizeof(struct rockchip_efuse_chip),
299                              GFP_KERNEL);
300         if (!efuse)
301                 return -ENOMEM;
302
303         res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
304         efuse->phys = res->start;
305         efuse->base = devm_ioremap_resource(&pdev->dev, res);
306         if (IS_ERR(efuse->base))
307                 return PTR_ERR(efuse->base);
308
309         efuse->clk = devm_clk_get(&pdev->dev, "pclk_efuse");
310         if (IS_ERR(efuse->clk))
311                 return PTR_ERR(efuse->clk);
312
313         efuse->dev = &pdev->dev;
314         econfig.size = resource_size(res);
315         econfig.reg_read = match->data;
316         econfig.priv = efuse;
317         econfig.dev = efuse->dev;
318         nvmem = nvmem_register(&econfig);
319         if (IS_ERR(nvmem))
320                 return PTR_ERR(nvmem);
321
322         platform_set_drvdata(pdev, nvmem);
323
324         return 0;
325 }
326
327 static int rockchip_efuse_remove(struct platform_device *pdev)
328 {
329         struct nvmem_device *nvmem = platform_get_drvdata(pdev);
330
331         return nvmem_unregister(nvmem);
332 }
333
334 static struct platform_driver rockchip_efuse_driver = {
335         .remove = rockchip_efuse_remove,
336         .driver = {
337                 .name = "rockchip-efuse",
338                 .of_match_table = rockchip_efuse_match,
339         },
340 };
341
342 static int __init rockchip_efuse_module_init(void)
343 {
344         return platform_driver_probe(&rockchip_efuse_driver,
345                                      rockchip_efuse_probe);
346 }
347
348 subsys_initcall(rockchip_efuse_module_init);
349
350 MODULE_DESCRIPTION("rockchip_efuse driver");
351 MODULE_LICENSE("GPL v2");