1 | // SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) |
2 | // Copyright(c) 2015-17 Intel Corporation. |
3 | |
4 | /* |
5 | * SDW Intel Init Routines |
6 | * |
7 | * Initializes and creates SDW devices based on ACPI and Hardware values |
8 | */ |
9 | |
10 | #include <linux/acpi.h> |
11 | #include <linux/export.h> |
12 | #include <linux/interrupt.h> |
13 | #include <linux/io.h> |
14 | #include <linux/module.h> |
15 | #include <linux/auxiliary_bus.h> |
16 | #include <linux/pm_runtime.h> |
17 | #include <linux/soundwire/sdw_intel.h> |
18 | #include "cadence_master.h" |
19 | #include "intel.h" |
20 | #include "intel_auxdevice.h" |
21 | |
22 | static void intel_link_dev_release(struct device *dev) |
23 | { |
24 | struct auxiliary_device *auxdev = to_auxiliary_dev(dev); |
25 | struct sdw_intel_link_dev *ldev = auxiliary_dev_to_sdw_intel_link_dev(auxdev); |
26 | |
27 | kfree(objp: ldev); |
28 | } |
29 | |
30 | /* alloc, init and add link devices */ |
31 | static struct sdw_intel_link_dev *intel_link_dev_register(struct sdw_intel_res *res, |
32 | struct sdw_intel_ctx *ctx, |
33 | struct fwnode_handle *fwnode, |
34 | const char *name, |
35 | int link_id) |
36 | { |
37 | struct sdw_intel_link_dev *ldev; |
38 | struct sdw_intel_link_res *link; |
39 | struct auxiliary_device *auxdev; |
40 | int ret; |
41 | |
42 | ldev = kzalloc(size: sizeof(*ldev), GFP_KERNEL); |
43 | if (!ldev) |
44 | return ERR_PTR(error: -ENOMEM); |
45 | |
46 | auxdev = &ldev->auxdev; |
47 | auxdev->name = name; |
48 | auxdev->dev.parent = res->parent; |
49 | auxdev->dev.fwnode = fwnode; |
50 | auxdev->dev.release = intel_link_dev_release; |
51 | |
52 | /* we don't use an IDA since we already have a link ID */ |
53 | auxdev->id = link_id; |
54 | |
55 | /* |
56 | * keep a handle on the allocated memory, to be used in all other functions. |
57 | * Since the same pattern is used to skip links that are not enabled, there is |
58 | * no need to check if ctx->ldev[i] is NULL later on. |
59 | */ |
60 | ctx->ldev[link_id] = ldev; |
61 | |
62 | /* Add link information used in the driver probe */ |
63 | link = &ldev->link_res; |
64 | link->hw_ops = res->hw_ops; |
65 | link->mmio_base = res->mmio_base; |
66 | if (!res->ext) { |
67 | link->registers = res->mmio_base + SDW_LINK_BASE |
68 | + (SDW_LINK_SIZE * link_id); |
69 | link->ip_offset = 0; |
70 | link->shim = res->mmio_base + res->shim_base; |
71 | link->alh = res->mmio_base + res->alh_base; |
72 | link->shim_lock = &ctx->shim_lock; |
73 | } else { |
74 | link->registers = res->mmio_base + SDW_IP_BASE(link_id); |
75 | link->ip_offset = SDW_CADENCE_MCP_IP_OFFSET; |
76 | link->shim = res->mmio_base + SDW_SHIM2_GENERIC_BASE(link_id); |
77 | link->shim_vs = res->mmio_base + SDW_SHIM2_VS_BASE(link_id); |
78 | link->shim_lock = res->eml_lock; |
79 | } |
80 | |
81 | link->ops = res->ops; |
82 | link->dev = res->dev; |
83 | |
84 | link->clock_stop_quirks = res->clock_stop_quirks; |
85 | link->shim_mask = &ctx->shim_mask; |
86 | link->link_mask = ctx->link_mask; |
87 | |
88 | link->hbus = res->hbus; |
89 | |
90 | /* now follow the two-step init/add sequence */ |
91 | ret = auxiliary_device_init(auxdev); |
92 | if (ret < 0) { |
93 | dev_err(res->parent, "failed to initialize link dev %s link_id %d\n" , |
94 | name, link_id); |
95 | kfree(objp: ldev); |
96 | return ERR_PTR(error: ret); |
97 | } |
98 | |
99 | ret = auxiliary_device_add(&ldev->auxdev); |
100 | if (ret < 0) { |
101 | dev_err(res->parent, "failed to add link dev %s link_id %d\n" , |
102 | ldev->auxdev.name, link_id); |
103 | /* ldev will be freed with the put_device() and .release sequence */ |
104 | auxiliary_device_uninit(auxdev: &ldev->auxdev); |
105 | return ERR_PTR(error: ret); |
106 | } |
107 | |
108 | return ldev; |
109 | } |
110 | |
111 | static void intel_link_dev_unregister(struct sdw_intel_link_dev *ldev) |
112 | { |
113 | auxiliary_device_delete(auxdev: &ldev->auxdev); |
114 | auxiliary_device_uninit(auxdev: &ldev->auxdev); |
115 | } |
116 | |
117 | static int sdw_intel_cleanup(struct sdw_intel_ctx *ctx) |
118 | { |
119 | struct sdw_intel_link_dev *ldev; |
120 | u32 link_mask; |
121 | int i; |
122 | |
123 | link_mask = ctx->link_mask; |
124 | |
125 | for (i = 0; i < ctx->count; i++) { |
126 | if (!(link_mask & BIT(i))) |
127 | continue; |
128 | |
129 | ldev = ctx->ldev[i]; |
130 | |
131 | pm_runtime_disable(dev: &ldev->auxdev.dev); |
132 | if (!ldev->link_res.clock_stop_quirks) |
133 | pm_runtime_put_noidle(dev: ldev->link_res.dev); |
134 | |
135 | intel_link_dev_unregister(ldev); |
136 | } |
137 | |
138 | return 0; |
139 | } |
140 | |
141 | irqreturn_t sdw_intel_thread(int irq, void *dev_id) |
142 | { |
143 | struct sdw_intel_ctx *ctx = dev_id; |
144 | struct sdw_intel_link_res *link; |
145 | |
146 | list_for_each_entry(link, &ctx->link_list, list) |
147 | sdw_cdns_irq(irq, dev_id: link->cdns); |
148 | |
149 | return IRQ_HANDLED; |
150 | } |
151 | EXPORT_SYMBOL_NS(sdw_intel_thread, SOUNDWIRE_INTEL_INIT); |
152 | |
153 | static struct sdw_intel_ctx |
154 | *sdw_intel_probe_controller(struct sdw_intel_res *res) |
155 | { |
156 | struct sdw_intel_link_res *link; |
157 | struct sdw_intel_link_dev *ldev; |
158 | struct sdw_intel_ctx *ctx; |
159 | struct acpi_device *adev; |
160 | struct sdw_slave *slave; |
161 | struct list_head *node; |
162 | struct sdw_bus *bus; |
163 | u32 link_mask; |
164 | int num_slaves = 0; |
165 | int count; |
166 | int i; |
167 | |
168 | if (!res) |
169 | return NULL; |
170 | |
171 | adev = acpi_fetch_acpi_dev(handle: res->handle); |
172 | if (!adev) |
173 | return NULL; |
174 | |
175 | if (!res->count) |
176 | return NULL; |
177 | |
178 | count = res->count; |
179 | dev_dbg(&adev->dev, "Creating %d SDW Link devices\n" , count); |
180 | |
181 | /* |
182 | * we need to alloc/free memory manually and can't use devm: |
183 | * this routine may be called from a workqueue, and not from |
184 | * the parent .probe. |
185 | * If devm_ was used, the memory might never be freed on errors. |
186 | */ |
187 | ctx = kzalloc(size: sizeof(*ctx), GFP_KERNEL); |
188 | if (!ctx) |
189 | return NULL; |
190 | |
191 | ctx->count = count; |
192 | |
193 | /* |
194 | * allocate the array of pointers. The link-specific data is allocated |
195 | * as part of the first loop below and released with the auxiliary_device_uninit(). |
196 | * If some links are disabled, the link pointer will remain NULL. Given that the |
197 | * number of links is small, this is simpler than using a list to keep track of links. |
198 | */ |
199 | ctx->ldev = kcalloc(n: ctx->count, size: sizeof(*ctx->ldev), GFP_KERNEL); |
200 | if (!ctx->ldev) { |
201 | kfree(objp: ctx); |
202 | return NULL; |
203 | } |
204 | |
205 | ctx->mmio_base = res->mmio_base; |
206 | ctx->shim_base = res->shim_base; |
207 | ctx->alh_base = res->alh_base; |
208 | ctx->link_mask = res->link_mask; |
209 | ctx->handle = res->handle; |
210 | mutex_init(&ctx->shim_lock); |
211 | |
212 | link_mask = ctx->link_mask; |
213 | |
214 | INIT_LIST_HEAD(list: &ctx->link_list); |
215 | |
216 | for (i = 0; i < count; i++) { |
217 | if (!(link_mask & BIT(i))) |
218 | continue; |
219 | |
220 | /* |
221 | * init and add a device for each link |
222 | * |
223 | * The name of the device will be soundwire_intel.link.[i], |
224 | * with the "soundwire_intel" module prefix automatically added |
225 | * by the auxiliary bus core. |
226 | */ |
227 | ldev = intel_link_dev_register(res, |
228 | ctx, |
229 | fwnode: acpi_fwnode_handle(adev), |
230 | name: "link" , |
231 | link_id: i); |
232 | if (IS_ERR(ptr: ldev)) |
233 | goto err; |
234 | |
235 | link = &ldev->link_res; |
236 | link->cdns = auxiliary_get_drvdata(auxdev: &ldev->auxdev); |
237 | |
238 | if (!link->cdns) { |
239 | dev_err(&adev->dev, "failed to get link->cdns\n" ); |
240 | /* |
241 | * 1 will be subtracted from i in the err label, but we need to call |
242 | * intel_link_dev_unregister for this ldev, so plus 1 now |
243 | */ |
244 | i++; |
245 | goto err; |
246 | } |
247 | list_add_tail(new: &link->list, head: &ctx->link_list); |
248 | bus = &link->cdns->bus; |
249 | /* Calculate number of slaves */ |
250 | list_for_each(node, &bus->slaves) |
251 | num_slaves++; |
252 | } |
253 | |
254 | ctx->ids = kcalloc(n: num_slaves, size: sizeof(*ctx->ids), GFP_KERNEL); |
255 | if (!ctx->ids) |
256 | goto err; |
257 | |
258 | ctx->num_slaves = num_slaves; |
259 | i = 0; |
260 | list_for_each_entry(link, &ctx->link_list, list) { |
261 | bus = &link->cdns->bus; |
262 | list_for_each_entry(slave, &bus->slaves, node) { |
263 | ctx->ids[i].id = slave->id; |
264 | ctx->ids[i].link_id = bus->link_id; |
265 | i++; |
266 | } |
267 | } |
268 | |
269 | return ctx; |
270 | |
271 | err: |
272 | while (i--) { |
273 | if (!(link_mask & BIT(i))) |
274 | continue; |
275 | ldev = ctx->ldev[i]; |
276 | intel_link_dev_unregister(ldev); |
277 | } |
278 | kfree(objp: ctx->ldev); |
279 | kfree(objp: ctx); |
280 | return NULL; |
281 | } |
282 | |
283 | static int |
284 | sdw_intel_startup_controller(struct sdw_intel_ctx *ctx) |
285 | { |
286 | struct acpi_device *adev = acpi_fetch_acpi_dev(handle: ctx->handle); |
287 | struct sdw_intel_link_dev *ldev; |
288 | u32 link_mask; |
289 | int i; |
290 | |
291 | if (!adev) |
292 | return -EINVAL; |
293 | |
294 | if (!ctx->ldev) |
295 | return -EINVAL; |
296 | |
297 | link_mask = ctx->link_mask; |
298 | |
299 | /* Startup SDW Master devices */ |
300 | for (i = 0; i < ctx->count; i++) { |
301 | if (!(link_mask & BIT(i))) |
302 | continue; |
303 | |
304 | ldev = ctx->ldev[i]; |
305 | |
306 | intel_link_startup(auxdev: &ldev->auxdev); |
307 | |
308 | if (!ldev->link_res.clock_stop_quirks) { |
309 | /* |
310 | * we need to prevent the parent PCI device |
311 | * from entering pm_runtime suspend, so that |
312 | * power rails to the SoundWire IP are not |
313 | * turned off. |
314 | */ |
315 | pm_runtime_get_noresume(dev: ldev->link_res.dev); |
316 | } |
317 | } |
318 | |
319 | return 0; |
320 | } |
321 | |
322 | /** |
323 | * sdw_intel_probe() - SoundWire Intel probe routine |
324 | * @res: resource data |
325 | * |
326 | * This registers an auxiliary device for each Master handled by the controller, |
327 | * and SoundWire Master and Slave devices will be created by the auxiliary |
328 | * device probe. All the information necessary is stored in the context, and |
329 | * the res argument pointer can be freed after this step. |
330 | * This function will be called after sdw_intel_acpi_scan() by SOF probe. |
331 | */ |
332 | struct sdw_intel_ctx |
333 | *sdw_intel_probe(struct sdw_intel_res *res) |
334 | { |
335 | return sdw_intel_probe_controller(res); |
336 | } |
337 | EXPORT_SYMBOL_NS(sdw_intel_probe, SOUNDWIRE_INTEL_INIT); |
338 | |
339 | /** |
340 | * sdw_intel_startup() - SoundWire Intel startup |
341 | * @ctx: SoundWire context allocated in the probe |
342 | * |
343 | * Startup Intel SoundWire controller. This function will be called after |
344 | * Intel Audio DSP is powered up. |
345 | */ |
346 | int sdw_intel_startup(struct sdw_intel_ctx *ctx) |
347 | { |
348 | return sdw_intel_startup_controller(ctx); |
349 | } |
350 | EXPORT_SYMBOL_NS(sdw_intel_startup, SOUNDWIRE_INTEL_INIT); |
351 | /** |
352 | * sdw_intel_exit() - SoundWire Intel exit |
353 | * @ctx: SoundWire context allocated in the probe |
354 | * |
355 | * Delete the controller instances created and cleanup |
356 | */ |
357 | void sdw_intel_exit(struct sdw_intel_ctx *ctx) |
358 | { |
359 | sdw_intel_cleanup(ctx); |
360 | kfree(objp: ctx->ids); |
361 | kfree(objp: ctx->ldev); |
362 | kfree(objp: ctx); |
363 | } |
364 | EXPORT_SYMBOL_NS(sdw_intel_exit, SOUNDWIRE_INTEL_INIT); |
365 | |
366 | void sdw_intel_process_wakeen_event(struct sdw_intel_ctx *ctx) |
367 | { |
368 | struct sdw_intel_link_dev *ldev; |
369 | u32 link_mask; |
370 | int i; |
371 | |
372 | if (!ctx->ldev) |
373 | return; |
374 | |
375 | link_mask = ctx->link_mask; |
376 | |
377 | /* Startup SDW Master devices */ |
378 | for (i = 0; i < ctx->count; i++) { |
379 | if (!(link_mask & BIT(i))) |
380 | continue; |
381 | |
382 | ldev = ctx->ldev[i]; |
383 | |
384 | intel_link_process_wakeen_event(auxdev: &ldev->auxdev); |
385 | } |
386 | } |
387 | EXPORT_SYMBOL_NS(sdw_intel_process_wakeen_event, SOUNDWIRE_INTEL_INIT); |
388 | |
389 | MODULE_LICENSE("Dual BSD/GPL" ); |
390 | MODULE_DESCRIPTION("Intel Soundwire Init Library" ); |
391 | |