1 // SPDX-License-Identifier: GPL-2.0
2 // Copyright (C) 2025 Cirrus Logic, Inc. and
3 // Cirrus Logic International Semiconductor Ltd.
4
5 /*
6 * The MIPI SDCA specification is available for public downloads at
7 * https://www.mipi.org/mipi-sdca-v1-0-download
8 */
9
10 #include <linux/acpi.h>
11 #include <linux/device.h>
12 #include <linux/dev_printk.h>
13 #include <linux/dmi.h>
14 #include <linux/firmware.h>
15 #include <linux/module.h>
16 #include <linux/pci.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/regmap.h>
19 #include <linux/sprintf.h>
20 #include <linux/soundwire/sdw.h>
21 #include <linux/soundwire/sdw_registers.h>
22 #include <sound/sdca.h>
23 #include <sound/sdca_fdl.h>
24 #include <sound/sdca_function.h>
25 #include <sound/sdca_interrupts.h>
26 #include <sound/sdca_ump.h>
27
28 /**
29 * sdca_reset_function - send an SDCA function reset
30 * @dev: Device pointer for error messages.
31 * @function: Pointer to the SDCA Function.
32 * @regmap: Pointer to the SDCA Function regmap.
33 *
34 * Return: Zero on success or a negative error code.
35 */
sdca_reset_function(struct device * dev,struct sdca_function_data * function,struct regmap * regmap)36 int sdca_reset_function(struct device *dev, struct sdca_function_data *function,
37 struct regmap *regmap)
38 {
39 unsigned int reg = SDW_SDCA_CTL(function->desc->adr,
40 SDCA_ENTITY_TYPE_ENTITY_0,
41 SDCA_CTL_ENTITY_0_FUNCTION_ACTION, 0);
42 unsigned int val, poll_us;
43 int ret;
44
45 ret = regmap_write(regmap, reg, SDCA_CTL_ENTITY_0_RESET_FUNCTION_NOW);
46 if (ret) // Allowed for function reset to not be implemented
47 return 0;
48
49 /*
50 * Poll up to 16 times but no more than once per ms, these are just
51 * arbitrarily selected values, so may be fine tuned in future.
52 */
53 poll_us = umin(function->reset_max_delay >> 4, 1000);
54
55 ret = regmap_read_poll_timeout(regmap, reg, val, !val, poll_us,
56 function->reset_max_delay);
57 if (ret) {
58 dev_err(dev, "Failed waiting for function reset: %d\n", ret);
59 return ret;
60 }
61
62 return 0;
63 }
64 EXPORT_SYMBOL_NS(sdca_reset_function, "SND_SOC_SDCA");
65
66 /**
67 * sdca_fdl_sync - wait for a function to finish FDL
68 * @dev: Device pointer for error messages.
69 * @function: Pointer to the SDCA Function.
70 * @info: Pointer to the SDCA interrupt info for this device.
71 *
72 * Return: Zero on success or a negative error code.
73 */
sdca_fdl_sync(struct device * dev,struct sdca_function_data * function,struct sdca_interrupt_info * info)74 int sdca_fdl_sync(struct device *dev, struct sdca_function_data *function,
75 struct sdca_interrupt_info *info)
76 {
77 static const int fdl_retries = 6;
78 unsigned long begin_timeout = msecs_to_jiffies(100);
79 unsigned long done_timeout = msecs_to_jiffies(4000);
80 int nfdl;
81 int i, j;
82
83 for (i = 0; i < fdl_retries; i++) {
84 nfdl = 0;
85
86 for (j = 0; j < SDCA_MAX_INTERRUPTS; j++) {
87 struct sdca_interrupt *interrupt = &info->irqs[j];
88 struct fdl_state *fdl_state;
89 unsigned long time;
90
91 if (interrupt->function != function ||
92 !interrupt->entity || !interrupt->control ||
93 interrupt->entity->type != SDCA_ENTITY_TYPE_XU ||
94 interrupt->control->sel != SDCA_CTL_XU_FDL_CURRENTOWNER)
95 continue;
96
97 fdl_state = interrupt->priv;
98 nfdl++;
99
100 /*
101 * Looking for timeout without any new FDL requests
102 * to imply the device has completed initial
103 * firmware setup. Alas the specification doesn't
104 * have any mechanism to detect this.
105 */
106 time = wait_for_completion_timeout(&fdl_state->begin,
107 begin_timeout);
108 if (!time) {
109 dev_dbg(dev, "no new FDL starts\n");
110 nfdl--;
111 continue;
112 }
113
114 time = wait_for_completion_timeout(&fdl_state->done,
115 done_timeout);
116 if (!time) {
117 dev_err(dev, "timed out waiting for FDL to complete\n");
118 goto error;
119 }
120 }
121
122 if (!nfdl)
123 return 0;
124 }
125
126 dev_err(dev, "too many FDL requests\n");
127
128 error:
129 for (j = 0; j < SDCA_MAX_INTERRUPTS; j++) {
130 struct sdca_interrupt *interrupt = &info->irqs[j];
131 struct fdl_state *fdl_state;
132
133 if (interrupt->function != function ||
134 !interrupt->entity || !interrupt->control ||
135 interrupt->entity->type != SDCA_ENTITY_TYPE_XU ||
136 interrupt->control->sel != SDCA_CTL_XU_FDL_CURRENTOWNER)
137 continue;
138
139 disable_irq(interrupt->irq);
140
141 fdl_state = interrupt->priv;
142
143 sdca_ump_cancel_timeout(&fdl_state->timeout);
144 }
145
146 return -ETIMEDOUT;
147 }
148 EXPORT_SYMBOL_NS_GPL(sdca_fdl_sync, "SND_SOC_SDCA");
149
fdl_get_sku_filename(struct device * dev,struct sdca_fdl_file * fdl_file)150 static char *fdl_get_sku_filename(struct device *dev,
151 struct sdca_fdl_file *fdl_file)
152 {
153 struct device *parent = dev;
154 const char *product_vendor;
155 const char *product_sku;
156
157 /*
158 * Try to find pci_dev manually because the card may not be ready to be
159 * used for snd_soc_card_get_pci_ssid yet
160 */
161 while (parent) {
162 if (dev_is_pci(parent)) {
163 struct pci_dev *pci_dev = to_pci_dev(parent);
164
165 return kasprintf(GFP_KERNEL, "sdca/%x/%x/%x/%x.bin",
166 fdl_file->vendor_id,
167 pci_dev->subsystem_vendor,
168 pci_dev->subsystem_device,
169 fdl_file->file_id);
170 } else {
171 parent = parent->parent;
172 }
173 }
174
175 product_vendor = dmi_get_system_info(DMI_SYS_VENDOR);
176 if (!product_vendor || !strcmp(product_vendor, "Default string"))
177 product_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
178 if (!product_vendor || !strcmp(product_vendor, "Default string"))
179 product_vendor = dmi_get_system_info(DMI_CHASSIS_VENDOR);
180 if (!product_vendor)
181 product_vendor = "unknown";
182
183 product_sku = dmi_get_system_info(DMI_PRODUCT_SKU);
184 if (!product_sku || !strcmp(product_sku, "Default string"))
185 product_sku = dmi_get_system_info(DMI_PRODUCT_NAME);
186 if (!product_sku)
187 product_sku = "unknown";
188
189 return kasprintf(GFP_KERNEL, "sdca/%x/%s/%s/%x.bin", fdl_file->vendor_id,
190 product_vendor, product_sku, fdl_file->file_id);
191 }
192
fdl_load_file(struct sdca_interrupt * interrupt,struct sdca_fdl_set * set,int file_index)193 static int fdl_load_file(struct sdca_interrupt *interrupt,
194 struct sdca_fdl_set *set, int file_index)
195 {
196 struct device *dev = interrupt->dev;
197 struct sdca_fdl_data *fdl_data = &interrupt->function->fdl_data;
198 struct acpi_sw_file *swf = NULL, *tmp;
199 struct sdca_fdl_file *fdl_file;
200 char *disk_filename;
201 int ret;
202 int i;
203
204 if (!set) {
205 dev_err(dev, "request to load SWF with no set\n");
206 return -EINVAL;
207 }
208
209 fdl_file = &set->files[file_index];
210
211 if (fdl_data->swft) {
212 tmp = fdl_data->swft->files;
213 for (i = 0; i < fdl_data->swft->header.length; i += tmp->file_length,
214 tmp = ACPI_ADD_PTR(struct acpi_sw_file, tmp, tmp->file_length)) {
215 if (tmp->vendor_id == fdl_file->vendor_id &&
216 tmp->file_id == fdl_file->file_id) {
217 dev_dbg(dev, "located SWF in ACPI: %x-%x-%x\n",
218 tmp->vendor_id, tmp->file_id,
219 tmp->file_version);
220 swf = tmp;
221 break;
222 }
223 }
224 }
225
226 disk_filename = fdl_get_sku_filename(dev, fdl_file);
227 if (!disk_filename)
228 return -ENOMEM;
229
230 dev_dbg(dev, "FDL disk filename: %s\n", disk_filename);
231
232 const struct firmware *firmware __free(firmware) = NULL;
233 ret = firmware_request_nowarn(&firmware, disk_filename, dev);
234 kfree(disk_filename);
235 if (ret) {
236 disk_filename = kasprintf(GFP_KERNEL, "sdca/%x/%x.bin",
237 fdl_file->vendor_id, fdl_file->file_id);
238 if (!disk_filename)
239 return -ENOMEM;
240
241 dev_dbg(dev, "FDL disk filename: %s\n", disk_filename);
242
243 ret = firmware_request_nowarn(&firmware, disk_filename, dev);
244 kfree(disk_filename);
245 }
246
247 if (!ret) {
248 tmp = (struct acpi_sw_file *)&firmware->data[0];
249
250 if (firmware->size < sizeof(*tmp) ||
251 tmp->file_length != firmware->size) {
252 dev_err(dev, "bad disk SWF size\n");
253 } else if (!swf || swf->file_version <= tmp->file_version) {
254 dev_dbg(dev, "using SWF from disk\n");
255 swf = tmp;
256 }
257 }
258
259 if (!swf) {
260 dev_err(dev, "failed to locate SWF\n");
261 return -ENOENT;
262 }
263
264 dev_info(dev, "loading SWF: %x-%x-%x\n",
265 swf->vendor_id, swf->file_id, swf->file_version);
266
267 ret = sdca_ump_write_message(dev, interrupt->device_regmap,
268 interrupt->function_regmap,
269 interrupt->function, interrupt->entity,
270 SDCA_CTL_XU_FDL_MESSAGEOFFSET, fdl_file->fdl_offset,
271 SDCA_CTL_XU_FDL_MESSAGELENGTH, swf->data,
272 swf->file_length - offsetof(struct acpi_sw_file, data));
273 return ret;
274 }
275
fdl_get_set(struct sdca_interrupt * interrupt)276 static struct sdca_fdl_set *fdl_get_set(struct sdca_interrupt *interrupt)
277 {
278 struct device *dev = interrupt->dev;
279 struct sdca_fdl_data *fdl_data = &interrupt->function->fdl_data;
280 struct sdca_entity *xu = interrupt->entity;
281 struct sdca_control_range *range;
282 unsigned int val;
283 int i, ret;
284
285 ret = regmap_read(interrupt->function_regmap,
286 SDW_SDCA_CTL(interrupt->function->desc->adr, xu->id,
287 SDCA_CTL_XU_FDL_SET_INDEX, 0),
288 &val);
289 if (ret < 0) {
290 dev_err(dev, "failed to read FDL set index: %d\n", ret);
291 return NULL;
292 }
293
294 range = sdca_selector_find_range(dev, xu, SDCA_CTL_XU_FDL_SET_INDEX,
295 SDCA_FDL_SET_INDEX_NCOLS, 0);
296
297 val = sdca_range_search(range, SDCA_FDL_SET_INDEX_SET_NUMBER,
298 val, SDCA_FDL_SET_INDEX_FILE_SET_ID);
299
300 for (i = 0; i < fdl_data->num_sets; i++) {
301 if (fdl_data->sets[i].id == val)
302 return &fdl_data->sets[i];
303 }
304
305 dev_err(dev, "invalid fileset id: %d\n", val);
306 return NULL;
307 }
308
fdl_end(struct sdca_interrupt * interrupt)309 static void fdl_end(struct sdca_interrupt *interrupt)
310 {
311 struct fdl_state *fdl_state = interrupt->priv;
312
313 if (!fdl_state->set)
314 return;
315
316 fdl_state->set = NULL;
317
318 pm_runtime_put(interrupt->dev);
319 complete(&fdl_state->done);
320
321 dev_dbg(interrupt->dev, "completed FDL process\n");
322 }
323
sdca_fdl_timeout_work(struct work_struct * work)324 static void sdca_fdl_timeout_work(struct work_struct *work)
325 {
326 struct fdl_state *fdl_state = container_of(work, struct fdl_state,
327 timeout.work);
328 struct sdca_interrupt *interrupt = fdl_state->interrupt;
329 struct device *dev = interrupt->dev;
330
331 dev_err(dev, "FDL transaction timed out\n");
332
333 guard(mutex)(&fdl_state->lock);
334
335 fdl_end(interrupt);
336 sdca_reset_function(dev, interrupt->function, interrupt->function_regmap);
337 }
338
fdl_status_process(struct sdca_interrupt * interrupt,unsigned int status)339 static int fdl_status_process(struct sdca_interrupt *interrupt, unsigned int status)
340 {
341 struct fdl_state *fdl_state = interrupt->priv;
342 int ret;
343
344 switch (status) {
345 case SDCA_CTL_XU_FDLD_NEEDS_SET:
346 dev_dbg(interrupt->dev, "starting FDL process...\n");
347
348 pm_runtime_get(interrupt->dev);
349 complete(&fdl_state->begin);
350
351 fdl_state->file_index = 0;
352 fdl_state->set = fdl_get_set(interrupt);
353 fallthrough;
354 case SDCA_CTL_XU_FDLD_MORE_FILES_OK:
355 ret = fdl_load_file(interrupt, fdl_state->set, fdl_state->file_index);
356 if (ret) {
357 fdl_end(interrupt);
358 return SDCA_CTL_XU_FDLH_REQ_ABORT;
359 }
360
361 return SDCA_CTL_XU_FDLH_FILE_AVAILABLE;
362 case SDCA_CTL_XU_FDLD_FILE_OK:
363 if (!fdl_state->set) {
364 fdl_end(interrupt);
365 return SDCA_CTL_XU_FDLH_REQ_ABORT;
366 }
367
368 fdl_state->file_index++;
369
370 if (fdl_state->file_index < fdl_state->set->num_files)
371 return SDCA_CTL_XU_FDLH_MORE_FILES;
372 fallthrough;
373 case SDCA_CTL_XU_FDLD_COMPLETE:
374 fdl_end(interrupt);
375 return SDCA_CTL_XU_FDLH_COMPLETE;
376 default:
377 fdl_end(interrupt);
378
379 if (status & SDCA_CTL_XU_FDLD_REQ_RESET)
380 return SDCA_CTL_XU_FDLH_RESET_ACK;
381 else if (status & SDCA_CTL_XU_FDLD_REQ_ABORT)
382 return SDCA_CTL_XU_FDLH_COMPLETE;
383
384 dev_err(interrupt->dev, "invalid FDL status: %x\n", status);
385 return -EINVAL;
386 }
387 }
388
389 /**
390 * sdca_fdl_process - Process the FDL state machine
391 * @interrupt: SDCA interrupt structure
392 *
393 * Based on section 13.2.5 Flow Diagram for File Download, Host side.
394 *
395 * Return: Zero on success or a negative error code.
396 */
sdca_fdl_process(struct sdca_interrupt * interrupt)397 int sdca_fdl_process(struct sdca_interrupt *interrupt)
398 {
399 struct device *dev = interrupt->dev;
400 struct sdca_entity_xu *xu = &interrupt->entity->xu;
401 struct fdl_state *fdl_state = interrupt->priv;
402 unsigned int reg, status;
403 int response, ret;
404
405 ret = sdca_ump_get_owner_host(dev, interrupt->function_regmap,
406 interrupt->function, interrupt->entity,
407 interrupt->control);
408 if (ret)
409 goto reset_function;
410
411 sdca_ump_cancel_timeout(&fdl_state->timeout);
412
413 scoped_guard(mutex, &fdl_state->lock) {
414 reg = SDW_SDCA_CTL(interrupt->function->desc->adr,
415 interrupt->entity->id, SDCA_CTL_XU_FDL_STATUS, 0);
416 ret = regmap_read(interrupt->function_regmap, reg, &status);
417 if (ret < 0) {
418 dev_err(dev, "failed to read FDL status: %d\n", ret);
419 return ret;
420 }
421
422 dev_dbg(dev, "FDL status: %#x\n", status);
423
424 ret = fdl_status_process(interrupt, status);
425 if (ret < 0)
426 goto reset_function;
427
428 response = ret;
429
430 dev_dbg(dev, "FDL response: %#x\n", response);
431
432 ret = regmap_write(interrupt->function_regmap, reg,
433 response | (status & ~SDCA_CTL_XU_FDLH_MASK));
434 if (ret < 0) {
435 dev_err(dev, "failed to set FDL status signal: %d\n", ret);
436 return ret;
437 }
438
439 ret = sdca_ump_set_owner_device(dev, interrupt->function_regmap,
440 interrupt->function,
441 interrupt->entity,
442 interrupt->control);
443 if (ret)
444 return ret;
445
446 switch (response) {
447 case SDCA_CTL_XU_FDLH_RESET_ACK:
448 dev_dbg(dev, "FDL request reset\n");
449
450 switch (xu->reset_mechanism) {
451 default:
452 dev_warn(dev, "Requested reset mechanism not implemented\n");
453 fallthrough;
454 case SDCA_XU_RESET_FUNCTION:
455 goto reset_function;
456 }
457 case SDCA_CTL_XU_FDLH_COMPLETE:
458 if (status & SDCA_CTL_XU_FDLD_REQ_ABORT ||
459 status == SDCA_CTL_XU_FDLD_COMPLETE)
460 return 0;
461 fallthrough;
462 default:
463 sdca_ump_schedule_timeout(&fdl_state->timeout, xu->max_delay);
464 return 0;
465 }
466 }
467
468 reset_function:
469 sdca_reset_function(dev, interrupt->function, interrupt->function_regmap);
470
471 return ret;
472 }
473 EXPORT_SYMBOL_NS_GPL(sdca_fdl_process, "SND_SOC_SDCA");
474
475 /**
476 * sdca_fdl_alloc_state - allocate state for an FDL interrupt
477 * @interrupt: SDCA interrupt structure.
478 *
479 * Return: Zero on success or a negative error code.
480 */
sdca_fdl_alloc_state(struct sdca_interrupt * interrupt)481 int sdca_fdl_alloc_state(struct sdca_interrupt *interrupt)
482 {
483 struct fdl_state *fdl_state;
484
485 fdl_state = kzalloc_obj(*fdl_state);
486 if (!fdl_state)
487 return -ENOMEM;
488
489 INIT_DELAYED_WORK(&fdl_state->timeout, sdca_fdl_timeout_work);
490 init_completion(&fdl_state->begin);
491 init_completion(&fdl_state->done);
492 mutex_init(&fdl_state->lock);
493 fdl_state->interrupt = interrupt;
494
495 interrupt->priv = fdl_state;
496
497 return 0;
498 }
499 EXPORT_SYMBOL_NS_GPL(sdca_fdl_alloc_state, "SND_SOC_SDCA");
500
501 /**
502 * sdca_fdl_free_state - free state for an FDL interrupt
503 * @interrupt: SDCA interrupt structure.
504 */
sdca_fdl_free_state(struct sdca_interrupt * interrupt)505 void sdca_fdl_free_state(struct sdca_interrupt *interrupt)
506 {
507 kfree(interrupt->priv);
508 }
509 EXPORT_SYMBOL_NS_GPL(sdca_fdl_free_state, "SND_SOC_SDCA");
510