1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause)
2 // Copyright(c) 2015-2023 Intel Corporation. All rights reserved.
3 
4 #include <linux/acpi.h>
5 #include <linux/soundwire/sdw_registers.h>
6 #include <linux/soundwire/sdw.h>
7 #include <linux/soundwire/sdw_intel.h>
8 #include "cadence_master.h"
9 #include "bus.h"
10 #include "intel.h"
11 
12 int intel_start_bus(struct sdw_intel *sdw)
13 {
14 	struct device *dev = sdw->cdns.dev;
15 	struct sdw_cdns *cdns = &sdw->cdns;
16 	struct sdw_bus *bus = &cdns->bus;
17 	int ret;
18 
19 	ret = sdw_cdns_enable_interrupt(cdns, true);
20 	if (ret < 0) {
21 		dev_err(dev, "%s: cannot enable interrupts: %d\n", __func__, ret);
22 		return ret;
23 	}
24 
25 	/*
26 	 * follow recommended programming flows to avoid timeouts when
27 	 * gsync is enabled
28 	 */
29 	if (bus->multi_link)
30 		sdw_intel_sync_arm(sdw);
31 
32 	ret = sdw_cdns_init(cdns);
33 	if (ret < 0) {
34 		dev_err(dev, "%s: unable to initialize Cadence IP: %d\n", __func__, ret);
35 		goto err_interrupt;
36 	}
37 
38 	ret = sdw_cdns_exit_reset(cdns);
39 	if (ret < 0) {
40 		dev_err(dev, "%s: unable to exit bus reset sequence: %d\n", __func__, ret);
41 		goto err_interrupt;
42 	}
43 
44 	if (bus->multi_link) {
45 		ret = sdw_intel_sync_go(sdw);
46 		if (ret < 0) {
47 			dev_err(dev, "%s: sync go failed: %d\n", __func__, ret);
48 			goto err_interrupt;
49 		}
50 	}
51 	sdw_cdns_check_self_clearing_bits(cdns, __func__,
52 					  true, INTEL_MASTER_RESET_ITERATIONS);
53 
54 	return 0;
55 
56 err_interrupt:
57 	sdw_cdns_enable_interrupt(cdns, false);
58 	return ret;
59 }
60 
61 int intel_start_bus_after_reset(struct sdw_intel *sdw)
62 {
63 	struct device *dev = sdw->cdns.dev;
64 	struct sdw_cdns *cdns = &sdw->cdns;
65 	struct sdw_bus *bus = &cdns->bus;
66 	bool clock_stop0;
67 	int status;
68 	int ret;
69 
70 	/*
71 	 * An exception condition occurs for the CLK_STOP_BUS_RESET
72 	 * case if one or more masters remain active. In this condition,
73 	 * all the masters are powered on for they are in the same power
74 	 * domain. Master can preserve its context for clock stop0, so
75 	 * there is no need to clear slave status and reset bus.
76 	 */
77 	clock_stop0 = sdw_cdns_is_clock_stop(&sdw->cdns);
78 
79 	if (!clock_stop0) {
80 
81 		/*
82 		 * make sure all Slaves are tagged as UNATTACHED and
83 		 * provide reason for reinitialization
84 		 */
85 
86 		status = SDW_UNATTACH_REQUEST_MASTER_RESET;
87 		sdw_clear_slave_status(bus, status);
88 
89 		ret = sdw_cdns_enable_interrupt(cdns, true);
90 		if (ret < 0) {
91 			dev_err(dev, "cannot enable interrupts during resume\n");
92 			return ret;
93 		}
94 
95 		/*
96 		 * follow recommended programming flows to avoid
97 		 * timeouts when gsync is enabled
98 		 */
99 		if (bus->multi_link)
100 			sdw_intel_sync_arm(sdw);
101 
102 		/*
103 		 * Re-initialize the IP since it was powered-off
104 		 */
105 		sdw_cdns_init(&sdw->cdns);
106 
107 	} else {
108 		ret = sdw_cdns_enable_interrupt(cdns, true);
109 		if (ret < 0) {
110 			dev_err(dev, "cannot enable interrupts during resume\n");
111 			return ret;
112 		}
113 	}
114 
115 	ret = sdw_cdns_clock_restart(cdns, !clock_stop0);
116 	if (ret < 0) {
117 		dev_err(dev, "unable to restart clock during resume\n");
118 		goto err_interrupt;
119 	}
120 
121 	if (!clock_stop0) {
122 		ret = sdw_cdns_exit_reset(cdns);
123 		if (ret < 0) {
124 			dev_err(dev, "unable to exit bus reset sequence during resume\n");
125 			goto err_interrupt;
126 		}
127 
128 		if (bus->multi_link) {
129 			ret = sdw_intel_sync_go(sdw);
130 			if (ret < 0) {
131 				dev_err(sdw->cdns.dev, "sync go failed during resume\n");
132 				goto err_interrupt;
133 			}
134 		}
135 	}
136 	sdw_cdns_check_self_clearing_bits(cdns, __func__, true, INTEL_MASTER_RESET_ITERATIONS);
137 
138 	return 0;
139 
140 err_interrupt:
141 	sdw_cdns_enable_interrupt(cdns, false);
142 	return ret;
143 }
144 
145 void intel_check_clock_stop(struct sdw_intel *sdw)
146 {
147 	struct device *dev = sdw->cdns.dev;
148 	bool clock_stop0;
149 
150 	clock_stop0 = sdw_cdns_is_clock_stop(&sdw->cdns);
151 	if (!clock_stop0)
152 		dev_err(dev, "%s: invalid configuration, clock was not stopped\n", __func__);
153 }
154 
155 int intel_start_bus_after_clock_stop(struct sdw_intel *sdw)
156 {
157 	struct device *dev = sdw->cdns.dev;
158 	struct sdw_cdns *cdns = &sdw->cdns;
159 	int ret;
160 
161 	ret = sdw_cdns_enable_interrupt(cdns, true);
162 	if (ret < 0) {
163 		dev_err(dev, "%s: cannot enable interrupts: %d\n", __func__, ret);
164 		return ret;
165 	}
166 
167 	ret = sdw_cdns_clock_restart(cdns, false);
168 	if (ret < 0) {
169 		dev_err(dev, "%s: unable to restart clock: %d\n", __func__, ret);
170 		sdw_cdns_enable_interrupt(cdns, false);
171 		return ret;
172 	}
173 
174 	sdw_cdns_check_self_clearing_bits(cdns, "intel_resume_runtime no_quirks",
175 					  true, INTEL_MASTER_RESET_ITERATIONS);
176 
177 	return 0;
178 }
179 
180 int intel_stop_bus(struct sdw_intel *sdw, bool clock_stop)
181 {
182 	struct device *dev = sdw->cdns.dev;
183 	struct sdw_cdns *cdns = &sdw->cdns;
184 	bool wake_enable = false;
185 	int ret;
186 
187 	if (clock_stop) {
188 		ret = sdw_cdns_clock_stop(cdns, true);
189 		if (ret < 0)
190 			dev_err(dev, "%s: cannot stop clock: %d\n", __func__, ret);
191 		else
192 			wake_enable = true;
193 	}
194 
195 	ret = sdw_cdns_enable_interrupt(cdns, false);
196 	if (ret < 0) {
197 		dev_err(dev, "%s: cannot disable interrupts: %d\n", __func__, ret);
198 		return ret;
199 	}
200 
201 	ret = sdw_intel_link_power_down(sdw);
202 	if (ret) {
203 		dev_err(dev, "%s: Link power down failed: %d\n", __func__, ret);
204 		return ret;
205 	}
206 
207 	sdw_intel_shim_wake(sdw, wake_enable);
208 
209 	return 0;
210 }
211 
212 /*
213  * bank switch routines
214  */
215 
216 int intel_pre_bank_switch(struct sdw_intel *sdw)
217 {
218 	struct sdw_cdns *cdns = &sdw->cdns;
219 	struct sdw_bus *bus = &cdns->bus;
220 
221 	/* Write to register only for multi-link */
222 	if (!bus->multi_link)
223 		return 0;
224 
225 	sdw_intel_sync_arm(sdw);
226 
227 	return 0;
228 }
229 
230 int intel_post_bank_switch(struct sdw_intel *sdw)
231 {
232 	struct sdw_cdns *cdns = &sdw->cdns;
233 	struct sdw_bus *bus = &cdns->bus;
234 	int ret = 0;
235 
236 	/* Write to register only for multi-link */
237 	if (!bus->multi_link)
238 		return 0;
239 
240 	mutex_lock(sdw->link_res->shim_lock);
241 
242 	/*
243 	 * post_bank_switch() ops is called from the bus in loop for
244 	 * all the Masters in the steam with the expectation that
245 	 * we trigger the bankswitch for the only first Master in the list
246 	 * and do nothing for the other Masters
247 	 *
248 	 * So, set the SYNCGO bit only if CMDSYNC bit is set for any Master.
249 	 */
250 	if (sdw_intel_sync_check_cmdsync_unlocked(sdw))
251 		ret = sdw_intel_sync_go_unlocked(sdw);
252 
253 	mutex_unlock(sdw->link_res->shim_lock);
254 
255 	if (ret < 0)
256 		dev_err(sdw->cdns.dev, "Post bank switch failed: %d\n", ret);
257 
258 	return ret;
259 }
260