blob: 2bedda07cb9f40bc1ff4853664991c6af94eb87c [file] [log] [blame]
Nicholas Flintham1e3d3112013-04-10 10:48:38 +01001/* Copyright (c) 2010-2012, Code Aurora Forum. All rights reserved.
2 *
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#include <linux/module.h>
14#include <linux/string.h>
15#include <linux/device.h>
16#include <linux/firmware.h>
17#include <linux/io.h>
18#include <linux/debugfs.h>
19#include <linux/elf.h>
20#include <linux/mutex.h>
21#include <linux/memblock.h>
22#include <linux/slab.h>
23#include <linux/atomic.h>
24#include <linux/suspend.h>
25#include <linux/rwsem.h>
26#include <linux/sysfs.h>
27#include <linux/workqueue.h>
28#include <linux/jiffies.h>
29#include <linux/wakelock.h>
30#include <linux/delay.h>
31
32#include <asm/uaccess.h>
33#include <asm/setup.h>
34#include <mach/peripheral-loader.h>
35
36#include "peripheral-loader.h"
37
38enum pil_state {
39 PIL_OFFLINE,
40 PIL_ONLINE,
41};
42
43static const char *pil_states[] = {
44 [PIL_OFFLINE] = "OFFLINE",
45 [PIL_ONLINE] = "ONLINE",
46};
47
48struct pil_device {
49 struct pil_desc *desc;
50 int count;
51 enum pil_state state;
52 struct mutex lock;
53 struct device dev;
54 struct module *owner;
55#ifdef CONFIG_DEBUG_FS
56 struct dentry *dentry;
57#endif
58 struct delayed_work proxy;
59 struct wake_lock wlock;
60 char wake_name[32];
61};
62
63#define to_pil_device(d) container_of(d, struct pil_device, dev)
64
65static ssize_t name_show(struct device *dev, struct device_attribute *attr,
66 char *buf)
67{
68 return snprintf(buf, PAGE_SIZE, "%s\n", to_pil_device(dev)->desc->name);
69}
70
71static ssize_t state_show(struct device *dev, struct device_attribute *attr,
72 char *buf)
73{
74 enum pil_state state = to_pil_device(dev)->state;
75 return snprintf(buf, PAGE_SIZE, "%s\n", pil_states[state]);
76}
77
78static struct device_attribute pil_attrs[] = {
79 __ATTR_RO(name),
80 __ATTR_RO(state),
81 { },
82};
83
84struct bus_type pil_bus_type = {
85 .name = "pil",
86 .dev_attrs = pil_attrs,
87};
88
89static int __find_peripheral(struct device *dev, void *data)
90{
91 struct pil_device *pdev = to_pil_device(dev);
92 return !strncmp(pdev->desc->name, data, INT_MAX);
93}
94
95static struct pil_device *find_peripheral(const char *str)
96{
97 struct device *dev;
98
99 if (!str)
100 return NULL;
101
102 dev = bus_find_device(&pil_bus_type, NULL, (void *)str,
103 __find_peripheral);
104 return dev ? to_pil_device(dev) : NULL;
105}
106
107static void pil_proxy_work(struct work_struct *work)
108{
109 struct pil_device *pil;
110
111 pil = container_of(work, struct pil_device, proxy.work);
112 pil->desc->ops->proxy_unvote(pil->desc);
113 wake_unlock(&pil->wlock);
114}
115
116static int pil_proxy_vote(struct pil_device *pil)
117{
118 int ret = 0;
119
120 if (pil->desc->ops->proxy_vote) {
121 wake_lock(&pil->wlock);
122 ret = pil->desc->ops->proxy_vote(pil->desc);
123 if (ret)
124 wake_unlock(&pil->wlock);
125 }
126 return ret;
127}
128
129static void pil_proxy_unvote(struct pil_device *pil, unsigned long timeout)
130{
131 if (pil->desc->ops->proxy_unvote)
132 schedule_delayed_work(&pil->proxy, msecs_to_jiffies(timeout));
133}
134
135#define IOMAP_SIZE SZ_4M
136
137static int load_segment(const struct elf32_phdr *phdr, unsigned num,
138 struct pil_device *pil)
139{
140 int ret = 0, count, paddr;
141 char fw_name[30];
142 const struct firmware *fw = NULL;
143 const u8 *data;
144
145 if (memblock_overlaps_memory(phdr->p_paddr, phdr->p_memsz)) {
146 dev_err(&pil->dev, "%s: kernel memory would be overwritten "
147 "[%#08lx, %#08lx)\n", pil->desc->name,
148 (unsigned long)phdr->p_paddr,
149 (unsigned long)(phdr->p_paddr + phdr->p_memsz));
150 return -EPERM;
151 }
152
153 if (phdr->p_filesz) {
154 snprintf(fw_name, ARRAY_SIZE(fw_name), "%s.b%02d",
155 pil->desc->name, num);
156 ret = request_firmware(&fw, fw_name, &pil->dev);
157 if (ret) {
158 dev_err(&pil->dev, "%s: Failed to locate blob %s\n",
159 pil->desc->name, fw_name);
160 return ret;
161 }
162
163 if (fw->size != phdr->p_filesz) {
164 dev_err(&pil->dev, "%s: Blob size %u doesn't match "
165 "%u\n", pil->desc->name, fw->size,
166 phdr->p_filesz);
167 ret = -EPERM;
168 goto release_fw;
169 }
170 }
171
172
173 count = phdr->p_filesz;
174 paddr = phdr->p_paddr;
175 data = fw ? fw->data : NULL;
176 while (count > 0) {
177 int size;
178 u8 __iomem *buf;
179
180 size = min_t(size_t, IOMAP_SIZE, count);
181 buf = ioremap(paddr, size);
182 if (!buf) {
183 dev_err(&pil->dev, "%s: Failed to map memory\n",
184 pil->desc->name);
185 ret = -ENOMEM;
186 goto release_fw;
187 }
188 memcpy(buf, data, size);
189 iounmap(buf);
190
191 count -= size;
192 paddr += size;
193 data += size;
194 }
195
196
197 count = phdr->p_memsz - phdr->p_filesz;
198 while (count > 0) {
199 int size;
200 u8 __iomem *buf;
201
202 size = min_t(size_t, IOMAP_SIZE, count);
203 buf = ioremap(paddr, size);
204 if (!buf) {
205 dev_err(&pil->dev, "%s: Failed to map memory\n",
206 pil->desc->name);
207 ret = -ENOMEM;
208 goto release_fw;
209 }
210 memset(buf, 0, size);
211 iounmap(buf);
212
213 count -= size;
214 paddr += size;
215 }
216
217 if (pil->desc->ops->verify_blob) {
218 ret = pil->desc->ops->verify_blob(pil->desc, phdr->p_paddr,
219 phdr->p_memsz);
220 if (ret)
221 dev_err(&pil->dev, "%s: Blob%u failed verification\n",
222 pil->desc->name, num);
223 }
224
225release_fw:
226 release_firmware(fw);
227 return ret;
228}
229
230#define segment_is_hash(flag) (((flag) & (0x7 << 24)) == (0x2 << 24))
231
232static int segment_is_loadable(const struct elf32_phdr *p)
233{
234 return (p->p_type == PT_LOAD) && !segment_is_hash(p->p_flags);
235}
236
237static DECLARE_RWSEM(pil_pm_rwsem);
238
239static int load_image(struct pil_device *pil)
240{
241 int i, ret;
242 char fw_name[30];
243 struct elf32_hdr *ehdr;
244 const struct elf32_phdr *phdr;
245 const struct firmware *fw;
246 unsigned long proxy_timeout = pil->desc->proxy_timeout;
247
248 down_read(&pil_pm_rwsem);
249 snprintf(fw_name, sizeof(fw_name), "%s.mdt", pil->desc->name);
250 ret = request_firmware(&fw, fw_name, &pil->dev);
251 if (ret) {
252 dev_err(&pil->dev, "%s: Failed to locate %s\n",
253 pil->desc->name, fw_name);
254 goto out;
255 }
256
257 if (fw->size < sizeof(*ehdr)) {
258 dev_err(&pil->dev, "%s: Not big enough to be an elf header\n",
259 pil->desc->name);
260 ret = -EIO;
261 goto release_fw;
262 }
263
264 ehdr = (struct elf32_hdr *)fw->data;
265 if (memcmp(ehdr->e_ident, ELFMAG, SELFMAG)) {
266 dev_err(&pil->dev, "%s: Not an elf header\n", pil->desc->name);
267 ret = -EIO;
268 goto release_fw;
269 }
270
271 if (ehdr->e_phnum == 0) {
272 dev_err(&pil->dev, "%s: No loadable segments\n",
273 pil->desc->name);
274 ret = -EIO;
275 goto release_fw;
276 }
277 if (sizeof(struct elf32_phdr) * ehdr->e_phnum +
278 sizeof(struct elf32_hdr) > fw->size) {
279 dev_err(&pil->dev, "%s: Program headers not within mdt\n",
280 pil->desc->name);
281 ret = -EIO;
282 goto release_fw;
283 }
284
285 ret = pil->desc->ops->init_image(pil->desc, fw->data, fw->size);
286 if (ret) {
287 dev_err(&pil->dev, "%s: Invalid firmware metadata\n",
288 pil->desc->name);
289 goto release_fw;
290 }
291
292 phdr = (const struct elf32_phdr *)(fw->data + sizeof(struct elf32_hdr));
293 for (i = 0; i < ehdr->e_phnum; i++, phdr++) {
294 if (!segment_is_loadable(phdr))
295 continue;
296
297 ret = load_segment(phdr, i, pil);
298 if (ret) {
299 dev_err(&pil->dev, "%s: Failed to load segment %d\n",
300 pil->desc->name, i);
301 goto release_fw;
302 }
303 }
304
305 ret = pil_proxy_vote(pil);
306 if (ret) {
307 dev_err(&pil->dev, "%s: Failed to proxy vote\n",
308 pil->desc->name);
309 goto release_fw;
310 }
311
312 ret = pil->desc->ops->auth_and_reset(pil->desc);
313 if (ret) {
314 dev_err(&pil->dev, "%s: Failed to bring out of reset\n",
315 pil->desc->name);
316 proxy_timeout = 0;
317 goto err_boot;
318 }
319 dev_info(&pil->dev, "%s: Brought out of reset\n", pil->desc->name);
320err_boot:
321 pil_proxy_unvote(pil, proxy_timeout);
322release_fw:
323 release_firmware(fw);
324out:
325 up_read(&pil_pm_rwsem);
326 return ret;
327}
328
329static void pil_set_state(struct pil_device *pil, enum pil_state state)
330{
331 if (pil->state != state) {
332 pil->state = state;
333 sysfs_notify(&pil->dev.kobj, NULL, "state");
334 }
335}
336
337void *pil_get(const char *name)
338{
339 int ret;
340 struct pil_device *pil;
341 struct pil_device *pil_d;
342 void *retval;
343#ifdef CONFIG_MSM8960_ONLY
344 static int modem_initialized = 0;
345 int loop_count = 0;
346#endif
347
348 if (!name)
349 return NULL;
350
351 pil = retval = find_peripheral(name);
352 if (!pil)
353 return ERR_PTR(-ENODEV);
354 if (!try_module_get(pil->owner)) {
355 put_device(&pil->dev);
356 return ERR_PTR(-ENODEV);
357 }
358
359 pil_d = pil_get(pil->desc->depends_on);
360 if (IS_ERR(pil_d)) {
361 retval = pil_d;
362 goto err_depends;
363 }
364
365#ifdef CONFIG_MSM8960_ONLY
366 if (!strcmp("modem", name)) {
367 while (unlikely(!modem_initialized && strcmp("rmt_storage", current->comm) && loop_count++ < 10)) {
368
369 printk("%s: %s(%d) waiting for rmt_storage %d\n", __func__, current->comm, current->pid, loop_count);
370 msleep(500);
371 }
372 }
373#endif
374 mutex_lock(&pil->lock);
375 if (!pil->count) {
376 if (!strcmp("modem", name)) {
377 printk("%s: %s(%d) for %s\n", __func__, current->comm, current->pid, name);
378#ifdef CONFIG_MSM8960_ONLY
379 modem_initialized = 1;
380#endif
381 }
382 ret = load_image(pil);
383 if (ret) {
384 retval = ERR_PTR(ret);
385 goto err_load;
386 }
387 }
388 pil->count++;
389 pil_set_state(pil, PIL_ONLINE);
390 mutex_unlock(&pil->lock);
391out:
392 return retval;
393err_load:
394 mutex_unlock(&pil->lock);
395 pil_put(pil_d);
396err_depends:
397 put_device(&pil->dev);
398 module_put(pil->owner);
399 goto out;
400}
401EXPORT_SYMBOL(pil_get);
402
403static void pil_shutdown(struct pil_device *pil)
404{
405 pil->desc->ops->shutdown(pil->desc);
406 flush_delayed_work(&pil->proxy);
407 pil_set_state(pil, PIL_OFFLINE);
408}
409
410void pil_put(void *peripheral_handle)
411{
412 struct pil_device *pil_d, *pil = peripheral_handle;
413
414 if (IS_ERR_OR_NULL(pil))
415 return;
416
417 printk("%s: %s(%d) for %s\n", __func__, current->comm, current->pid, pil->desc->name);
418 mutex_lock(&pil->lock);
419 if (WARN(!pil->count, "%s: %s: Reference count mismatch\n",
420 pil->desc->name, __func__))
421 goto err_out;
422#ifdef CONFIG_MACH_DUMMY
423 if (pil->count == 1)
424 goto unlock;
425#endif
426 if (!--pil->count)
427 pil_shutdown(pil);
428#ifdef CONFIG_MACH_DUMMY
429unlock:
430#endif
431 mutex_unlock(&pil->lock);
432
433 pil_d = find_peripheral(pil->desc->depends_on);
434 module_put(pil->owner);
435 if (pil_d) {
436 pil_put(pil_d);
437 put_device(&pil_d->dev);
438 }
439 put_device(&pil->dev);
440 return;
441err_out:
442 mutex_unlock(&pil->lock);
443 return;
444}
445EXPORT_SYMBOL(pil_put);
446
447void pil_force_shutdown(const char *name)
448{
449 struct pil_device *pil;
450
451 pil = find_peripheral(name);
452 if (!pil) {
453 pr_err("%s: Couldn't find %s\n", __func__, name);
454 return;
455 }
456
457 mutex_lock(&pil->lock);
458 if (!WARN(!pil->count, "%s: %s: Reference count mismatch\n",
459 pil->desc->name, __func__))
460 pil_shutdown(pil);
461 mutex_unlock(&pil->lock);
462
463 put_device(&pil->dev);
464}
465EXPORT_SYMBOL(pil_force_shutdown);
466
467int pil_force_boot(const char *name)
468{
469 int ret = -EINVAL;
470 struct pil_device *pil;
471
472 pil = find_peripheral(name);
473 if (!pil) {
474 pr_err("%s: Couldn't find %s\n", __func__, name);
475 return -EINVAL;
476 }
477
478 mutex_lock(&pil->lock);
479 if (!WARN(!pil->count, "%s: %s: Reference count mismatch\n",
480 pil->desc->name, __func__))
481 ret = load_image(pil);
482 if (!ret)
483 pil_set_state(pil, PIL_ONLINE);
484 mutex_unlock(&pil->lock);
485 put_device(&pil->dev);
486
487 return ret;
488}
489EXPORT_SYMBOL(pil_force_boot);
490
491#ifdef CONFIG_DEBUG_FS
492static int msm_pil_debugfs_open(struct inode *inode, struct file *filp)
493{
494 filp->private_data = inode->i_private;
495 return 0;
496}
497
498static ssize_t msm_pil_debugfs_read(struct file *filp, char __user *ubuf,
499 size_t cnt, loff_t *ppos)
500{
501 int r;
502 char buf[40];
503 struct pil_device *pil = filp->private_data;
504
505 mutex_lock(&pil->lock);
506 r = snprintf(buf, sizeof(buf), "%d\n", pil->count);
507 mutex_unlock(&pil->lock);
508 return simple_read_from_buffer(ubuf, cnt, ppos, buf, r);
509}
510
511static ssize_t msm_pil_debugfs_write(struct file *filp,
512 const char __user *ubuf, size_t cnt, loff_t *ppos)
513{
514 struct pil_device *pil = filp->private_data;
515 char buf[4];
516
517 if (cnt > sizeof(buf))
518 return -EINVAL;
519
520 if (copy_from_user(&buf, ubuf, cnt))
521 return -EFAULT;
522
523 if (!strncmp(buf, "get", 3)) {
524 if (IS_ERR(pil_get(pil->desc->name)))
525 return -EIO;
526 } else if (!strncmp(buf, "put", 3))
527 pil_put(pil);
528 else
529 return -EINVAL;
530
531 return cnt;
532}
533
534static const struct file_operations msm_pil_debugfs_fops = {
535 .open = msm_pil_debugfs_open,
536 .read = msm_pil_debugfs_read,
537 .write = msm_pil_debugfs_write,
538};
539
540static struct dentry *pil_base_dir;
541
542static int __init msm_pil_debugfs_init(void)
543{
544 pil_base_dir = debugfs_create_dir("pil", NULL);
545 if (!pil_base_dir) {
546 pil_base_dir = NULL;
547 return -ENOMEM;
548 }
549
550 return 0;
551}
552
553static void __exit msm_pil_debugfs_exit(void)
554{
555 debugfs_remove_recursive(pil_base_dir);
556}
557
558static int msm_pil_debugfs_add(struct pil_device *pil)
559{
560 if (!pil_base_dir)
561 return -ENOMEM;
562
563 pil->dentry = debugfs_create_file(pil->desc->name, S_IRUGO | S_IWUSR,
564 pil_base_dir, pil, &msm_pil_debugfs_fops);
565 return !pil->dentry ? -ENOMEM : 0;
566}
567
568static void msm_pil_debugfs_remove(struct pil_device *pil)
569{
570 debugfs_remove(pil->dentry);
571}
572#else
573static int __init msm_pil_debugfs_init(void) { return 0; };
574static void __exit msm_pil_debugfs_exit(void) { return 0; };
575static int msm_pil_debugfs_add(struct pil_device *pil) { return 0; }
576static void msm_pil_debugfs_remove(struct pil_device *pil) { }
577#endif
578
579static int __msm_pil_shutdown(struct device *dev, void *data)
580{
581 pil_shutdown(to_pil_device(dev));
582 return 0;
583}
584
585static int msm_pil_shutdown_at_boot(void)
586{
587 return bus_for_each_dev(&pil_bus_type, NULL, NULL, __msm_pil_shutdown);
588}
589late_initcall(msm_pil_shutdown_at_boot);
590
591static void pil_device_release(struct device *dev)
592{
593 struct pil_device *pil = to_pil_device(dev);
594 wake_lock_destroy(&pil->wlock);
595 mutex_destroy(&pil->lock);
596 kfree(pil);
597}
598
599struct pil_device *msm_pil_register(struct pil_desc *desc)
600{
601 int err;
602 static atomic_t pil_count = ATOMIC_INIT(-1);
603 struct pil_device *pil;
604
605
606 if (WARN(desc->ops->proxy_unvote && !desc->ops->proxy_vote,
607 "invalid proxy voting. ignoring\n"))
608 ((struct pil_reset_ops *)desc->ops)->proxy_unvote = NULL;
609
610 WARN(desc->ops->proxy_unvote && !desc->proxy_timeout,
611 "A proxy timeout of 0 ms was specified for %s. Specify one in "
612 "desc->proxy_timeout.\n", desc->name);
613
614 pil = kzalloc(sizeof(*pil), GFP_KERNEL);
615 if (!pil)
616 return ERR_PTR(-ENOMEM);
617
618 mutex_init(&pil->lock);
619 pil->desc = desc;
620 pil->owner = desc->owner;
621 pil->dev.parent = desc->dev;
622 pil->dev.bus = &pil_bus_type;
623 pil->dev.release = pil_device_release;
624
625 snprintf(pil->wake_name, sizeof(pil->wake_name), "pil-%s", desc->name);
626 wake_lock_init(&pil->wlock, WAKE_LOCK_SUSPEND, pil->wake_name);
627 INIT_DELAYED_WORK(&pil->proxy, pil_proxy_work);
628
629 dev_set_name(&pil->dev, "pil%d", atomic_inc_return(&pil_count));
630 err = device_register(&pil->dev);
631 if (err) {
632 put_device(&pil->dev);
633 wake_lock_destroy(&pil->wlock);
634 mutex_destroy(&pil->lock);
635 kfree(pil);
636 return ERR_PTR(err);
637 }
638
639 err = msm_pil_debugfs_add(pil);
640 if (err) {
641 device_unregister(&pil->dev);
642 return ERR_PTR(err);
643 }
644
645 return pil;
646}
647EXPORT_SYMBOL(msm_pil_register);
648
649void msm_pil_unregister(struct pil_device *pil)
650{
651 if (IS_ERR_OR_NULL(pil))
652 return;
653
654 if (get_device(&pil->dev)) {
655 mutex_lock(&pil->lock);
656 WARN_ON(pil->count);
657 flush_delayed_work_sync(&pil->proxy);
658 msm_pil_debugfs_remove(pil);
659 device_unregister(&pil->dev);
660 mutex_unlock(&pil->lock);
661 put_device(&pil->dev);
662 }
663}
664EXPORT_SYMBOL(msm_pil_unregister);
665
666static int pil_pm_notify(struct notifier_block *b, unsigned long event, void *p)
667{
668 switch (event) {
669 case PM_SUSPEND_PREPARE:
670 down_write(&pil_pm_rwsem);
671 break;
672 case PM_POST_SUSPEND:
673 up_write(&pil_pm_rwsem);
674 break;
675 }
676 return NOTIFY_DONE;
677}
678
679static struct notifier_block pil_pm_notifier = {
680 .notifier_call = pil_pm_notify,
681};
682
683static int __init msm_pil_init(void)
684{
685 int ret = msm_pil_debugfs_init();
686 if (ret)
687 return ret;
688 register_pm_notifier(&pil_pm_notifier);
689 return bus_register(&pil_bus_type);
690}
691subsys_initcall(msm_pil_init);
692
693static void __exit msm_pil_exit(void)
694{
695 bus_unregister(&pil_bus_type);
696 unregister_pm_notifier(&pil_pm_notifier);
697 msm_pil_debugfs_exit();
698}
699module_exit(msm_pil_exit);
700
701MODULE_LICENSE("GPL v2");
702MODULE_DESCRIPTION("Load peripheral images and bring peripherals out of reset");