blob: 9624275e93d60523b0c7ca3623abba7ff7410cf0 [file] [log] [blame]
Raghavendra Rao Anantacaa60aa2017-10-20 11:27:12 -07001/* Copyright (c) 2014-2015, 2017-2018, The Linux Foundation. All rights reserved.
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -08002 *
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 "esoc-mdm.h"
14
15/* This function can be called from atomic context. */
16static int mdm4x_toggle_soft_reset(struct mdm_ctrl *mdm, bool atomic)
17{
18 int soft_reset_direction_assert = 0,
19 soft_reset_direction_de_assert = 1;
20
21 if (mdm->soft_reset_inverted) {
22 soft_reset_direction_assert = 1;
23 soft_reset_direction_de_assert = 0;
24 }
25 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
26 soft_reset_direction_assert);
27 /*
28 * Allow PS hold assert to be detected
29 */
30 if (!atomic)
31 usleep_range(8000, 9000);
32 else
33 mdelay(6);
34 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
35 soft_reset_direction_de_assert);
36 return 0;
37}
38
39/* This function can be called from atomic context. */
40static int mdm9x55_toggle_soft_reset(struct mdm_ctrl *mdm, bool atomic)
41{
42 int soft_reset_direction_assert = 0,
43 soft_reset_direction_de_assert = 1;
44
45 if (mdm->soft_reset_inverted) {
46 soft_reset_direction_assert = 1;
47 soft_reset_direction_de_assert = 0;
48 }
49 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
50 soft_reset_direction_assert);
51 /*
52 * Allow PS hold assert to be detected
53 */
54 if (!atomic)
55 usleep_range(203000, 300000);
56 else
57 mdelay(203);
58 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
59 soft_reset_direction_de_assert);
60 return 0;
61}
62
Raghavendra Rao Anantacaa60aa2017-10-20 11:27:12 -070063/* This function can be called from atomic context. */
64static int sdxpoorwills_toggle_soft_reset(struct mdm_ctrl *mdm, bool atomic)
65{
66 int soft_reset_direction_assert = mdm->soft_reset_inverted;
67
68 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
69 soft_reset_direction_assert);
70 /*
71 * Allow PS hold assert to be detected
72 */
73 if (!atomic)
74 usleep_range(80000, 180000);
75 else
76 mdelay(100);
77 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
78 !soft_reset_direction_assert);
79 return 0;
80}
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -080081
82static int mdm4x_do_first_power_on(struct mdm_ctrl *mdm)
83{
84 int i;
85 int pblrdy;
86 struct device *dev = mdm->dev;
87
88 dev_dbg(dev, "Powering on modem for the first time\n");
Arun KS0cb73fd2017-01-16 17:47:03 +053089 if (mdm->esoc->auto_boot)
90 return 0;
91
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -080092 mdm_toggle_soft_reset(mdm, false);
93 /* Add a delay to allow PON sequence to complete*/
94 mdelay(50);
95 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_STATUS), 1);
96 if (gpio_is_valid(MDM_GPIO(mdm, MDM2AP_PBLRDY))) {
97 for (i = 0; i < MDM_PBLRDY_CNT; i++) {
98 pblrdy = gpio_get_value(MDM_GPIO(mdm, MDM2AP_PBLRDY));
99 if (pblrdy)
100 break;
101 usleep_range(5000, 6000);
102 }
103 dev_dbg(dev, "pblrdy i:%d\n", i);
104 mdelay(200);
105 }
106 /*
107 * No PBLRDY gpio associated with this modem
108 * Send request for image. Let userspace confirm establishment of
109 * link to external modem.
110 */
111 else
112 esoc_clink_queue_request(ESOC_REQ_IMG, mdm->esoc);
113 return 0;
114}
115
116static int mdm4x_power_down(struct mdm_ctrl *mdm)
117{
118 struct device *dev = mdm->dev;
119 int soft_reset_direction = mdm->soft_reset_inverted ? 1 : 0;
Raghavendra Rao Anantacaa60aa2017-10-20 11:27:12 -0700120
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800121 /* Assert the soft reset line whether mdm2ap_status went low or not */
122 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
123 soft_reset_direction);
124 dev_dbg(dev, "Doing a hard reset\n");
125 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
126 soft_reset_direction);
127 /*
128 * Currently, there is a debounce timer on the charm PMIC. It is
129 * necessary to hold the PMIC RESET low for 400ms
130 * for the reset to fully take place. Sleep here to ensure the
131 * reset has occurred before the function exits.
132 */
133 mdelay(400);
134 return 0;
135}
136
137static int mdm9x55_power_down(struct mdm_ctrl *mdm)
138{
139 struct device *dev = mdm->dev;
140 int soft_reset_direction = mdm->soft_reset_inverted ? 1 : 0;
141 /* Assert the soft reset line whether mdm2ap_status went low or not */
142 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
143 soft_reset_direction);
144 dev_dbg(dev, "Doing a hard reset\n");
145 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
146 soft_reset_direction);
147 /*
148 * Currently, there is a debounce timer on the charm PMIC. It is
149 * necessary to hold the PMIC RESET low for 406ms
150 * for the reset to fully take place. Sleep here to ensure the
151 * reset has occurred before the function exits.
152 */
153 mdelay(406);
154 return 0;
155}
156
Raghavendra Rao Anantacaa60aa2017-10-20 11:27:12 -0700157static int sdxpoorwills_power_down(struct mdm_ctrl *mdm)
158{
159 struct device *dev = mdm->dev;
160 int soft_reset_direction = mdm->soft_reset_inverted ? 1 : 0;
161
162 /* Assert the soft reset line whether mdm2ap_status went low or not */
163 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
164 soft_reset_direction);
165 dev_info(dev, "Doing a hard reset\n");
166 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
167 soft_reset_direction);
168 /*
169 * Currently, there is a debounce timer on the charm PMIC. It is
170 * necessary to hold the PMIC RESET low for 325ms
171 * for the reset to fully take place. Sleep here to ensure the
172 * reset has occurred before the function exits.
173 */
174 mdelay(325);
175 return 0;
176}
177
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800178static void mdm4x_cold_reset(struct mdm_ctrl *mdm)
179{
Arun KS0cb73fd2017-01-16 17:47:03 +0530180 if (!gpio_is_valid(MDM_GPIO(mdm, AP2MDM_SOFT_RESET)))
181 return;
182
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800183 dev_dbg(mdm->dev, "Triggering mdm cold reset");
184 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
185 !!mdm->soft_reset_inverted);
186 mdelay(300);
187 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
188 !mdm->soft_reset_inverted);
189}
190
191static void mdm9x55_cold_reset(struct mdm_ctrl *mdm)
192{
193 dev_dbg(mdm->dev, "Triggering mdm cold reset");
194 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
195 !!mdm->soft_reset_inverted);
196 mdelay(334);
197 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
198 !mdm->soft_reset_inverted);
199}
200
Raghavendra Rao Anantacaa60aa2017-10-20 11:27:12 -0700201static void sdxpoorwills_cold_reset(struct mdm_ctrl *mdm)
202{
203 dev_info(mdm->dev, "Triggering mdm cold reset");
204 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
205 !!mdm->soft_reset_inverted);
206 mdelay(600);
207 gpio_direction_output(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
208 !mdm->soft_reset_inverted);
209}
210
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800211static int mdm4x_pon_dt_init(struct mdm_ctrl *mdm)
212{
213 int val;
214 struct device_node *node = mdm->dev->of_node;
215 enum of_gpio_flags flags = OF_GPIO_ACTIVE_LOW;
216
217 val = of_get_named_gpio_flags(node, "qcom,ap2mdm-soft-reset-gpio",
218 0, &flags);
219 if (val >= 0) {
220 MDM_GPIO(mdm, AP2MDM_SOFT_RESET) = val;
221 if (flags & OF_GPIO_ACTIVE_LOW)
222 mdm->soft_reset_inverted = 1;
223 return 0;
224 } else
225 return -EIO;
226}
227
228static int mdm4x_pon_setup(struct mdm_ctrl *mdm)
229{
230 struct device *dev = mdm->dev;
231
232 if (gpio_is_valid(MDM_GPIO(mdm, AP2MDM_SOFT_RESET))) {
233 if (gpio_request(MDM_GPIO(mdm, AP2MDM_SOFT_RESET),
234 "AP2MDM_SOFT_RESET")) {
235 dev_err(dev, "Cannot config AP2MDM_SOFT_RESET gpio\n");
236 return -EIO;
237 }
238 }
239 return 0;
240}
241
242struct mdm_pon_ops mdm9x25_pon_ops = {
243 .pon = mdm4x_do_first_power_on,
244 .soft_reset = mdm4x_toggle_soft_reset,
245 .poff_force = mdm4x_power_down,
246 .cold_reset = mdm4x_cold_reset,
247 .dt_init = mdm4x_pon_dt_init,
248 .setup = mdm4x_pon_setup,
249};
250
251struct mdm_pon_ops mdm9x35_pon_ops = {
252 .pon = mdm4x_do_first_power_on,
253 .soft_reset = mdm4x_toggle_soft_reset,
254 .poff_force = mdm4x_power_down,
255 .cold_reset = mdm4x_cold_reset,
256 .dt_init = mdm4x_pon_dt_init,
257 .setup = mdm4x_pon_setup,
258};
259
Abhimanyu Kapurc75b2e12016-02-22 18:15:13 -0800260struct mdm_pon_ops mdm9x55_pon_ops = {
261 .pon = mdm4x_do_first_power_on,
262 .soft_reset = mdm9x55_toggle_soft_reset,
263 .poff_force = mdm9x55_power_down,
264 .cold_reset = mdm9x55_cold_reset,
265 .dt_init = mdm4x_pon_dt_init,
266 .setup = mdm4x_pon_setup,
267};
Raghavendra Rao Anantacaa60aa2017-10-20 11:27:12 -0700268
269struct mdm_pon_ops sdxpoorwills_pon_ops = {
270 .pon = mdm4x_do_first_power_on,
271 .soft_reset = sdxpoorwills_toggle_soft_reset,
272 .poff_force = sdxpoorwills_power_down,
273 .cold_reset = sdxpoorwills_cold_reset,
274 .dt_init = mdm4x_pon_dt_init,
275 .setup = mdm4x_pon_setup,
276};