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