blob: f271f96ba3983e415007de7ac9733545ade5dec4 [file] [log] [blame]
Venkatesh Yadav Abbarapu011d62c2014-02-17 16:48:33 +05301/* Copyright (c) 2011, 2014 The Linux Foundation. All rights reserved.
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -07002 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#define pr_fmt(fmt) "%s: " fmt, __func__
14
15#include <linux/init.h>
16#include <linux/module.h>
17#include <linux/fs.h>
18#include <linux/slab.h>
19#include <linux/miscdevice.h>
20#include <linux/delay.h>
21#include <linux/qfp_fuse.h>
22#include <linux/io.h>
23#include <linux/uaccess.h>
24#include <linux/regulator/consumer.h>
25#include <linux/platform_device.h>
26#include <linux/mutex.h>
27
28/*
29 * Time QFPROM requires to reliably burn a fuse.
30 */
Venkatesh Yadav Abbarapu011d62c2014-02-17 16:48:33 +053031#define QFPROM_BLOW_TIMEOUT_US 20
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070032#define QFPROM_BLOW_TIMER_OFFSET 0x2038
33/*
34 * Denotes number of cycles required to blow the fuse.
35 */
36#define QFPROM_BLOW_TIMER_VALUE (QFPROM_BLOW_TIMEOUT_US * 83)
37
38#define QFPROM_BLOW_STATUS_OFFSET 0x204C
39#define QFPROM_BLOW_STATUS_BUSY 0x01
40#define QFPROM_BLOW_STATUS_ERROR 0x02
41
42#define QFP_FUSE_READY 0x01
43#define QFP_FUSE_OFF 0x00
44
Venkatesh Yadav Abbarapu011d62c2014-02-17 16:48:33 +053045#define QFP_FUSE_BUF_SIZE 64
Venkatesh Yadav Abbarapue4ca8f42014-03-06 18:42:05 +053046#define UINT32_MAX (0xFFFFFFFFU)
Venkatesh Yadav Abbarapu011d62c2014-02-17 16:48:33 +053047
48
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070049struct qfp_priv_t {
50 uint32_t base;
51 uint32_t end;
52 struct mutex lock;
53 struct regulator *fuse_vdd;
54 u8 state;
55};
56
57/* We need only one instance of this for the driver */
58static struct qfp_priv_t *qfp_priv;
59
Venkatesh Yadav Abbarapu011d62c2014-02-17 16:48:33 +053060static inline bool is_usr_req_valid(const struct qfp_fuse_req *req)
61{
62 uint32_t size = qfp_priv->end - qfp_priv->base;
Venkatesh Yadav Abbarapue4ca8f42014-03-06 18:42:05 +053063 uint32_t req_size;
Venkatesh Yadav Abbarapu011d62c2014-02-17 16:48:33 +053064
Venkatesh Yadav Abbarapue4ca8f42014-03-06 18:42:05 +053065 if (req->size >= (UINT32_MAX / sizeof(uint32_t)))
66 return false;
67 req_size = req->size * sizeof(uint32_t);
Venkatesh Yadav Abbarapu011d62c2014-02-17 16:48:33 +053068 if ((req_size == 0) || (req_size > size))
69 return false;
70 if (req->offset >= size)
71 return false;
72 if ((req->offset + req_size) > size)
73 return false;
74
75 return true;
76}
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -070077
78static int qfp_fuse_open(struct inode *inode, struct file *filp)
79{
80 if (qfp_priv == NULL)
81 return -ENODEV;
82
83 filp->private_data = qfp_priv;
84
85 return 0;
86}
87
88static int qfp_fuse_release(struct inode *inode, struct file *filp)
89{
90
91 filp->private_data = NULL;
92
93 return 0;
94}
95
96static inline int qfp_fuse_wait_for_fuse_blow(u32 *status)
97{
98 u32 timeout = QFPROM_BLOW_TIMEOUT_US;
99 /* wait for 400us before checking for the first time */
100 udelay(400);
101 do {
102 *status = readl_relaxed(
103 qfp_priv->base + QFPROM_BLOW_STATUS_OFFSET);
104
105 if (!(*status & QFPROM_BLOW_STATUS_BUSY))
106 return 0;
107
108 timeout--;
109 udelay(1);
110 } while (timeout);
111 pr_err("Timeout waiting for FUSE blow, status = %x\n", *status);
112 return -ETIMEDOUT;
113}
114
115static inline int qfp_fuse_enable_regulator(void)
116{
117 int err;
118 err = regulator_enable(qfp_priv->fuse_vdd);
119 if (err != 0)
120 pr_err("Error (%d) enabling regulator\n", err);
121 return err;
122}
123
124static inline int qfp_fuse_disable_regulator(void)
125{
126 int err;
127 err = regulator_disable(qfp_priv->fuse_vdd);
128 if (err != 0)
129 pr_err("Error (%d) disabling regulator\n", err);
130 return err;
131}
132
133static int qfp_fuse_write_word(u32 *addr, u32 data)
134{
135 u32 blow_status = 0;
136 u32 read_data;
137 int err;
138
139 /* Set QFPROM blow timer register */
140 writel_relaxed(QFPROM_BLOW_TIMER_VALUE,
141 qfp_priv->base + QFPROM_BLOW_TIMER_OFFSET);
142 mb();
143
144 /* Enable LVS0 regulator */
145 err = qfp_fuse_enable_regulator();
146 if (err != 0)
147 return err;
148
149 /*
150 * Wait for about 1ms. However msleep(1) can sleep for
151 * up to 20ms as per Documentation/timers/timers-howto.txt.
152 * Time is not a constraint here.
153 */
154
155 msleep(20);
156
157 /* Write data */
158 __raw_writel(data, addr);
159 mb();
160
161 /* blow_status = QFPROM_BLOW_STATUS_BUSY; */
162 err = qfp_fuse_wait_for_fuse_blow(&blow_status);
163 if (err) {
164 qfp_fuse_disable_regulator();
165 return err;
166 }
167
168 /* Check error status */
169 if (blow_status & QFPROM_BLOW_STATUS_ERROR) {
170 pr_err("Fuse blow status error: %d\n", blow_status);
171 qfp_fuse_disable_regulator();
172 return -EFAULT;
173 }
174
175 /* Disable regulator */
176 qfp_fuse_disable_regulator();
177 /*
178 * Wait for about 1ms. However msleep(1) can sleep for
179 * up to 20ms as per Documentation/timers/timers-howto.txt.
180 * Time is not a constraint here.
181 */
182 msleep(20);
183
184 /* Verify written data */
185 read_data = readl_relaxed(addr);
186 if (read_data != data) {
187 pr_err("Error: read/write data mismatch\n");
188 pr_err("Address = %p written data = %x read data = %x\n",
189 addr, data, read_data);
190 return -EFAULT;
191 }
192
193 return 0;
194}
195
196static long
197qfp_fuse_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
198{
199 int err = 0;
200 struct qfp_fuse_req req;
Venkatesh Yadav Abbarapu011d62c2014-02-17 16:48:33 +0530201 u32 fuse_buf[QFP_FUSE_BUF_SIZE];
202 u32 *buf = fuse_buf;
203 u32 *ptr = NULL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700204 int i;
205
206 /* Verify user arguments. */
207 if (_IOC_TYPE(cmd) != QFP_FUSE_IOC_MAGIC)
208 return -ENOTTY;
209
210 switch (cmd) {
211 case QFP_FUSE_IOC_READ:
212 if (arg == 0) {
213 pr_err("user space arg not supplied\n");
214 err = -EFAULT;
215 break;
216 }
217
218 if (copy_from_user(&req, (void __user *)arg, sizeof(req))) {
219 pr_err("Error copying req from user space\n");
220 err = -EFAULT;
221 break;
222 }
223
224 /* Check for limits */
Venkatesh Yadav Abbarapu011d62c2014-02-17 16:48:33 +0530225 if (is_usr_req_valid(&req) == false) {
226 pr_err("Invalid request\n");
227 err = -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700228 break;
229 }
230
Venkatesh Yadav Abbarapu011d62c2014-02-17 16:48:33 +0530231 if (req.size > QFP_FUSE_BUF_SIZE) {
232 /* Allocate memory for buffer */
233 ptr = kzalloc(req.size * 4, GFP_KERNEL);
234 if (ptr == NULL) {
235 pr_alert("No memory for data\n");
236 err = -ENOMEM;
237 break;
238 }
239 buf = ptr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700240 }
241
242 if (mutex_lock_interruptible(&qfp_priv->lock)) {
243 err = -ERESTARTSYS;
244 break;
245 }
246
247 /* Read data */
248 for (i = 0; i < req.size; i++)
249 buf[i] = readl_relaxed(
250 ((u32 *) (qfp_priv->base + req.offset)) + i);
251
252 if (copy_to_user((void __user *)req.data, buf, 4*(req.size))) {
253 pr_err("Error copying to user space\n");
254 err = -EFAULT;
255 }
256
257 mutex_unlock(&qfp_priv->lock);
258 break;
259
260 case QFP_FUSE_IOC_WRITE:
261 if (arg == 0) {
262 pr_err("user space arg not supplied\n");
263 err = -EFAULT;
264 break;
265 }
266
267 if (copy_from_user(&req, (void __user *)arg, sizeof(req))) {
268 pr_err("Error copying req from user space\n");
269 err = -EFAULT;
270 break;
271 }
272 /* Check for limits */
Venkatesh Yadav Abbarapu011d62c2014-02-17 16:48:33 +0530273 if (is_usr_req_valid(&req) == false) {
274 pr_err("Invalid request\n");
275 err = -EINVAL;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700276 break;
277 }
278
Venkatesh Yadav Abbarapu011d62c2014-02-17 16:48:33 +0530279 if (req.size > QFP_FUSE_BUF_SIZE) {
280 /* Allocate memory for buffer */
281 ptr = kzalloc(req.size * 4, GFP_KERNEL);
282 if (ptr == NULL) {
283 pr_alert("No memory for data\n");
284 err = -ENOMEM;
285 break;
286 }
287 buf = ptr;
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700288 }
289
290 /* Copy user data to local buffer */
291 if (copy_from_user(buf, (void __user *)req.data,
292 4 * (req.size))) {
293 pr_err("Error copying data from user space\n");
294 err = -EFAULT;
295 break;
296 }
297
298 if (mutex_lock_interruptible(&qfp_priv->lock)) {
299 err = -ERESTARTSYS;
300 break;
301 }
302
303 /* Write data word at a time */
304 for (i = 0; i < req.size && !err; i++) {
305 err = qfp_fuse_write_word(((u32 *) (
306 qfp_priv->base + req.offset) + i), buf[i]);
307 }
308
309 mutex_unlock(&qfp_priv->lock);
310 break;
311 default:
312 pr_err("Invalid ioctl command.\n");
313 return -ENOTTY;
314 }
Venkatesh Yadav Abbarapu011d62c2014-02-17 16:48:33 +0530315 kfree(ptr);
Bryan Huntsman3f2bc4d2011-08-16 17:27:22 -0700316 return err;
317}
318
319static const struct file_operations qfp_fuse_fops = {
320 .owner = THIS_MODULE,
321 .unlocked_ioctl = qfp_fuse_ioctl,
322 .open = qfp_fuse_open,
323 .release = qfp_fuse_release
324};
325
326static struct miscdevice qfp_fuse_dev = {
327 .minor = MISC_DYNAMIC_MINOR,
328 .name = "qfpfuse",
329 .fops = &qfp_fuse_fops
330};
331
332
333static int qfp_fuse_probe(struct platform_device *pdev)
334{
335 int ret = 0;
336 struct resource *res;
337 const char *regulator_name = pdev->dev.platform_data;
338
339
340 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
341 if (!res)
342 return -ENODEV;
343
344 if (!regulator_name)
345 return -EINVAL;
346
347 /* Initialize */
348 qfp_priv = kzalloc(sizeof(struct qfp_priv_t), GFP_KERNEL);
349
350 if (qfp_priv == NULL) {
351 pr_alert("Not enough memory to initialize device\n");
352 return -ENOMEM;
353 }
354
355 /* The driver is passed ioremapped address */
356 qfp_priv->base = res->start;
357 qfp_priv->end = res->end;
358
359 /* Get regulator for QFPROM writes */
360 qfp_priv->fuse_vdd = regulator_get(NULL, regulator_name);
361 if (IS_ERR(qfp_priv->fuse_vdd)) {
362 ret = PTR_ERR(qfp_priv->fuse_vdd);
363 pr_err("Err (%d) getting %s\n", ret, regulator_name);
364 qfp_priv->fuse_vdd = NULL;
365 goto err;
366 }
367
368 mutex_init(&qfp_priv->lock);
369
370 ret = misc_register(&qfp_fuse_dev);
371 if (ret < 0)
372 goto err;
373
374 pr_info("Fuse driver base:%x end:%x\n", qfp_priv->base, qfp_priv->end);
375 return 0;
376
377err:
378 if (qfp_priv->fuse_vdd)
379 regulator_put(qfp_priv->fuse_vdd);
380
381 kfree(qfp_priv);
382 qfp_priv = NULL;
383
384 return ret;
385
386}
387
388static int __devexit qfp_fuse_remove(struct platform_device *plat)
389{
390 if (qfp_priv && qfp_priv->fuse_vdd)
391 regulator_put(qfp_priv->fuse_vdd);
392
393 kfree(qfp_priv);
394 qfp_priv = NULL;
395
396 misc_deregister(&qfp_fuse_dev);
397 pr_info("Removing Fuse driver\n");
398 return 0;
399}
400
401static struct platform_driver qfp_fuse_driver = {
402 .probe = qfp_fuse_probe,
403 .remove = qfp_fuse_remove,
404 .driver = {
405 .name = "qfp_fuse_driver",
406 .owner = THIS_MODULE,
407 },
408};
409
410static int __init qfp_fuse_init(void)
411{
412 return platform_driver_register(&qfp_fuse_driver);
413}
414
415static void __exit qfp_fuse_exit(void)
416{
417 platform_driver_unregister(&qfp_fuse_driver);
418}
419
420MODULE_LICENSE("GPL v2");
421MODULE_AUTHOR("Rohit Vaswani <rvaswani@codeaurora.org>");
422MODULE_DESCRIPTION("Driver to read/write to QFPROM fuses.");
423MODULE_VERSION("1.01");
424
425module_init(qfp_fuse_init);
426module_exit(qfp_fuse_exit);