blob: 404c8f0065999fbd90c6f7a6dd8ebe883709abcf [file] [log] [blame]
Laura Abbott306bcc22012-03-08 11:24:53 -08001/* Copyright (c) 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
14#include <linux/module.h>
15#include <linux/kernel.h>
16#include <linux/init.h>
17#include <linux/io.h>
18#include <linux/delay.h>
19#include <linux/workqueue.h>
20#include <linux/platform_device.h>
21#include <linux/pm.h>
22#include <linux/memory_alloc.h>
Laura Abbott7b637362012-03-29 16:43:49 -070023#include <linux/notifier.h>
Laura Abbott306bcc22012-03-08 11:24:53 -080024#include <mach/scm.h>
25#include <mach/msm_cache_dump.h>
26#include <mach/memory.h>
27#include <mach/msm_iomap.h>
28
29#define L2C_IMEM_ADDR 0x2a03f014
30
31static unsigned long msm_cache_dump_addr;
32
33/*
34 * These are dummy pointers so the defintion of l1_cache_dump
35 * and l2_cache_dump don't get optimized away. If they aren't
36 * referenced, the structure definitions don't show up in the
37 * debugging information which is needed for post processing.
38 */
39static struct l1_cache_dump __used *l1_dump;
40static struct l2_cache_dump __used *l2_dump;
41
Laura Abbott7b637362012-03-29 16:43:49 -070042static int msm_cache_dump_panic(struct notifier_block *this,
43 unsigned long event, void *ptr)
44{
45#ifdef CONFIG_MSM_CACHE_DUMP_ON_PANIC
46 scm_call_atomic1(L1C_SERVICE_ID, CACHE_BUFFER_DUMP_COMMAND_ID, 2);
47 scm_call_atomic1(L1C_SERVICE_ID, CACHE_BUFFER_DUMP_COMMAND_ID, 1);
48#endif
49 return 0;
50}
51
52static struct notifier_block msm_cache_dump_blk = {
53 .notifier_call = msm_cache_dump_panic,
54 /*
55 * higher priority to ensure this runs before another panic handler
56 * flushes the caches.
57 */
58 .priority = 1,
59};
60
Laura Abbott306bcc22012-03-08 11:24:53 -080061static int msm_cache_dump_probe(struct platform_device *pdev)
62{
63 struct msm_cache_dump_platform_data *d = pdev->dev.platform_data;
64 int ret;
65 struct {
66 unsigned long buf;
67 unsigned long size;
68 } l1_cache_data;
Laura Abbott7b637362012-03-29 16:43:49 -070069#ifndef CONFIG_MSM_CACHE_DUMP_ON_PANIC
Laura Abbott306bcc22012-03-08 11:24:53 -080070 unsigned int *imem_loc;
Laura Abbott7b637362012-03-29 16:43:49 -070071#endif
Laura Abbott306bcc22012-03-08 11:24:53 -080072 void *temp;
73 unsigned long total_size = d->l1_size + d->l2_size;
74
75 msm_cache_dump_addr = allocate_contiguous_ebi_nomap(total_size, SZ_4K);
76
77 if (!msm_cache_dump_addr) {
78 pr_err("%s: Could not get memory for cache dumping\n",
79 __func__);
80 return -ENOMEM;
81 }
82
83 temp = ioremap(msm_cache_dump_addr, total_size);
84 memset(temp, 0xFF, total_size);
85 iounmap(temp);
86
87 l1_cache_data.buf = msm_cache_dump_addr;
88 l1_cache_data.size = d->l1_size;
89
90 ret = scm_call(L1C_SERVICE_ID, L1C_BUFFER_SET_COMMAND_ID,
91 &l1_cache_data, sizeof(l1_cache_data), NULL, 0);
92
93 if (ret)
94 pr_err("%s: could not register L1 buffer ret = %d.\n",
95 __func__, ret);
96
Laura Abbott7b637362012-03-29 16:43:49 -070097#if defined(CONFIG_MSM_CACHE_DUMP_ON_PANIC)
98 l1_cache_data.buf = msm_cache_dump_addr + d->l1_size;
99 l1_cache_data.size = d->l2_size;
100
101 ret = scm_call(L1C_SERVICE_ID, L2C_BUFFER_SET_COMMAND_ID,
102 &l1_cache_data, sizeof(l1_cache_data), NULL, 0);
103
104 if (ret)
105 pr_err("%s: could not register L2 buffer ret = %d.\n",
106 __func__, ret);
107#else
Laura Abbott306bcc22012-03-08 11:24:53 -0800108 imem_loc = ioremap(L2C_IMEM_ADDR, SZ_4K);
109 __raw_writel(msm_cache_dump_addr + d->l1_size, imem_loc);
110 iounmap(imem_loc);
Laura Abbott7b637362012-03-29 16:43:49 -0700111#endif
Laura Abbott306bcc22012-03-08 11:24:53 -0800112
Laura Abbott7b637362012-03-29 16:43:49 -0700113 atomic_notifier_chain_register(&panic_notifier_list,
114 &msm_cache_dump_blk);
115 return 0;
116}
117
118static int msm_cache_dump_remove(struct platform_device *pdev)
119{
120 atomic_notifier_chain_unregister(&panic_notifier_list,
121 &msm_cache_dump_blk);
Laura Abbott306bcc22012-03-08 11:24:53 -0800122 return 0;
123}
124
125static struct platform_driver msm_cache_dump_driver = {
Laura Abbott7b637362012-03-29 16:43:49 -0700126 .remove = __devexit_p(msm_cache_dump_remove),
Laura Abbott306bcc22012-03-08 11:24:53 -0800127 .driver = {
128 .name = "msm_cache_dump",
129 .owner = THIS_MODULE
130 },
131};
132
133static int __init msm_cache_dump_init(void)
134{
135 return platform_driver_probe(&msm_cache_dump_driver,
136 msm_cache_dump_probe);
137}
138
139static void __exit msm_cache_dump_exit(void)
140{
141 platform_driver_unregister(&msm_cache_dump_driver);
142}
143late_initcall(msm_cache_dump_init);
144module_exit(msm_cache_dump_exit)