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