dm-crypt: use __bio_add_page to add single page to clone bio
[linux-block.git] / drivers / soundwire / intel_bus_common.c
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 }