blob: 8615de5914c268fa5a4bea3ce2988224acde4684 [file] [log] [blame]
Ankur Nandwanie258cf02011-08-19 10:16:38 -07001/* Copyright (c) 2011, 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/kernel.h>
14#include <linux/interrupt.h>
15#include <linux/reboot.h>
16#include <linux/workqueue.h>
17#include <linux/io.h>
18#include <linux/delay.h>
19#include <linux/module.h>
20#include <mach/irqs.h>
21#include <mach/scm.h>
22#include <mach/subsystem_restart.h>
23#include <mach/subsystem_notif.h>
24#include "smd_private.h"
25#include "ramdump.h"
26
27#define MODULE_NAME "wcnss_8960"
28
29static void riva_smsm_cb_fn(struct work_struct *);
30static DECLARE_WORK(riva_smsm_cb_work, riva_smsm_cb_fn);
31
32static void riva_fatal_fn(struct work_struct *);
33static DECLARE_WORK(riva_fatal_work, riva_fatal_fn);
34
35static void *riva_ramdump_dev;
36static int riva_crash;
37static int ss_restart_inprogress;
38
39static void riva_smsm_cb_fn(struct work_struct *work)
40{
41 pr_err("%s: Initiating subsytem restart\n", MODULE_NAME);
42 subsystem_restart("riva");
43}
44
45static void smsm_state_cb_hdlr(void *data, uint32_t old_state,
46 uint32_t new_state)
47{
48 riva_crash = true;
49 pr_err("%s: smsm state changed to smsm reset\n", MODULE_NAME);
50
51 if (ss_restart_inprogress) {
52 pr_err("%s: Ignoring smsm reset req, restart in progress\n",
53 MODULE_NAME);
54 return;
55 }
56 if (new_state & SMSM_RESET)
57 schedule_work(&riva_smsm_cb_work);
58}
59
60static void riva_fatal_fn(struct work_struct *work)
61{
62 pr_err("%s: Watchdog bite received from Riva\n", MODULE_NAME);
63 if (!ss_restart_inprogress)
64 subsystem_restart("riva");
65}
66
67static irqreturn_t riva_wdog_bite_irq_hdlr(int irq, void *dev_id)
68{
69 riva_crash = true;
70 pr_debug("%s: rxed irq[0x%x]", MODULE_NAME, irq);
71 disable_irq_nosync(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ);
72 schedule_work(&riva_fatal_work);
73
74 return IRQ_HANDLED;
75}
76
77/* SMSM reset Riva */
78static void smsm_riva_reset(void)
79{
80 /* per SS reset request bit is not available now,
81 * all SS host modules are setting this bit
82 * This is still under discussion*/
83 smsm_change_state(SMSM_APPS_STATE, SMSM_RESET, SMSM_RESET);
84}
85
86/* Subsystem handlers */
87static int riva_shutdown(const struct subsys_data *subsys)
88{
89 /* TODO for phase 3 */
90 return 0;
91}
92
93static int riva_powerup(const struct subsys_data *subsys)
94{
95 /* TODO for phase 3 */
96 return 0;
97}
98
99/* RAM segments for Riva SS;
100 * We don't specify the full 5MB allocated for Riva. Only 3MB is specified */
101static struct ramdump_segment riva_segments[] = {{0x8f200000,
102 0x8f500000 - 0x8f200000} };
103
104static int riva_ramdump(int enable, const struct subsys_data *subsys)
105{
106 pr_debug("%s: enable[%d]\n", MODULE_NAME, enable);
107 if (enable)
108 return do_ramdump(riva_ramdump_dev,
109 riva_segments,
110 ARRAY_SIZE(riva_segments));
111 else
112 return 0;
113}
114
115/* Riva crash handler */
116static void riva_crash_shutdown(const struct subsys_data *subsys)
117{
118 ss_restart_inprogress = true;
119
120 pr_err("%s: crash shutdown : %d\n", MODULE_NAME, riva_crash);
121 if (riva_crash != true)
122 smsm_riva_reset();
123}
124
125static struct subsys_data riva_8960 = {
126 .name = "riva",
127 .shutdown = riva_shutdown,
128 .powerup = riva_powerup,
129 .ramdump = riva_ramdump,
130 .crash_shutdown = riva_crash_shutdown
131};
132
133static int __init riva_restart_init(void)
134{
135 return ssr_register_subsystem(&riva_8960);
136}
137
138static int __init riva_ssr_module_init(void)
139{
140 int ret;
141
142 ret = smsm_state_cb_register(SMSM_WCNSS_STATE, SMSM_RESET,
143 smsm_state_cb_hdlr, 0);
144 if (ret < 0) {
145 pr_err("%s: Unable to register smsm callback for Riva Reset!"
146 " (%d)\n", MODULE_NAME, ret);
147 goto out;
148 }
149 ret = request_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ,
150 riva_wdog_bite_irq_hdlr,
151 IRQF_TRIGGER_HIGH, "riva_wdog", NULL);
152 if (ret < 0) {
153 pr_err("%s: Unable to register RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ irq.",
154 MODULE_NAME);
155 goto out;
156 }
157 ret = riva_restart_init();
158 if (ret < 0) {
159 pr_err("%s: Unable to register with ssr. (%d)\n",
160 MODULE_NAME, ret);
161 goto out;
162 }
163 riva_ramdump_dev = create_ramdump_device("riva");
164 if (!riva_ramdump_dev) {
165 pr_err("%s: Unable to create ramdump device.\n",
166 MODULE_NAME);
167 ret = -ENOMEM;
168 goto out;
169 }
170 pr_info("%s: module initialized\n", MODULE_NAME);
171out:
172 return ret;
173}
174
175static void __exit riva_ssr_module_exit(void)
176{
177 free_irq(RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ, NULL);
178}
179
180module_init(riva_ssr_module_init);
181module_exit(riva_ssr_module_exit);
182
183MODULE_LICENSE("GPL v2");