Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

soc: ti: add firmware file name as part of the driver

Currently firmware file name is included in the DTS. This is not scalable
as user has to change the DTS if they need upgrade to a new firmware.
Instead, add the firmware file name in the driver itself. As long as there
is no API change, new firmware upgrade is easy and require no driver
change. User is expected to copy the firmware image to the file system
and add a sym link to the new firmware for doing an upgrade. Driver add
a array of firmware file names to search for the available firmware blobs.
This scheme also prepare the driver for future changes to API if ever
happens. In such case it is assumed that driver needs to change to
accommodate the new firmware and new firmware file name will get added to
the array.

Also update the DT document to remove the firmware attribute and add
description about firmware in the driver documentation.

Signed-off-by: Murali Karicheri <m-karicheri2@ti.com>
Acked-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Santosh Shilimkar <ssantosh@kernel.org>

authored by

Murali Karicheri and committed by
Santosh Shilimkar
96ee19be 29204a82

+54 -21
+26
Documentation/arm/keystone/knav-qmss.txt
··· 22 22 knav qmss driver provides a set of APIs to drivers to open/close qmss queues, 23 23 allocate descriptor pools, map the descriptors, push/pop to queues etc. For 24 24 details of the available APIs, please refers to include/linux/soc/ti/knav_qmss.h 25 + 26 + DT documentation is available at 27 + Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt 28 + 29 + Accumulator QMSS queues using PDSP firmware 30 + ============================================ 31 + The QMSS PDSP firmware support accumulator channel that can monitor a single 32 + queue or multiple contiguous queues. drivers/soc/ti/knav_qmss_acc.c is the 33 + driver that interface with the accumulator PDSP. This configures 34 + accumulator channels defined in DTS (example in DT documentation) to monitor 35 + 1 or 32 queues per channel. More description on the firmware is available in 36 + CPPI/QMSS Low Level Driver document (docs/CPPI_QMSS_LLD_SDS.pdf) at 37 + git://git.ti.com/keystone-rtos/qmss-lld.git 38 + 39 + k2_qmss_pdsp_acc48_k2_le_1_0_0_9.bin firmware supports upto 48 accumulator 40 + channels. This firmware is available under ti-keystone folder of 41 + firmware.git at 42 + git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git 43 + 44 + To use copy the firmware image to lib/firmware folder of the initramfs or 45 + ubifs file system and provide a sym link to k2_qmss_pdsp_acc48_k2_le_1_0_0_9.bin 46 + in the file system and boot up the kernel. User would see 47 + 48 + "firmware file ks2_qmss_pdsp_acc48.bin downloaded for PDSP" 49 + 50 + in the boot up log if loading of firmware to PDSP is successful.
-1
Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt
··· 221 221 #size-cells = <1>; 222 222 ranges; 223 223 pdsp0@0x2a10000 { 224 - firmware = "keystone/qmss_pdsp_acc48_k2_le_1_0_0_8.fw"; 225 224 reg = <0x2a10000 0x1000>, 226 225 <0x2a0f000 0x100>, 227 226 <0x2a0c000 0x3c8>,
-1
drivers/soc/ti/knav_qmss.h
··· 135 135 }; 136 136 void __iomem *intd; 137 137 u32 __iomem *iram; 138 - const char *firmware; 139 138 u32 id; 140 139 struct list_head list; 141 140 };
+28 -19
drivers/soc/ti/knav_qmss_queue.c
··· 68 68 idx < (kdev)->num_queues_in_use; \ 69 69 idx++, inst = knav_queue_idx_to_inst(kdev, idx)) 70 70 71 + /* All firmware file names end up here. List the firmware file names below. 72 + * Newest followed by older ones. Search is done from start of the array 73 + * until a firmware file is found. 74 + */ 75 + const char *knav_acc_firmwares[] = {"ks2_qmss_pdsp_acc48.bin"}; 76 + 71 77 /** 72 78 * knav_queue_notify: qmss queue notfier call 73 79 * ··· 1445 1439 struct device *dev = kdev->dev; 1446 1440 struct knav_pdsp_info *pdsp; 1447 1441 struct device_node *child; 1448 - int ret; 1449 1442 1450 1443 for_each_child_of_node(pdsps, child) { 1451 1444 pdsp = devm_kzalloc(dev, sizeof(*pdsp), GFP_KERNEL); ··· 1453 1448 return -ENOMEM; 1454 1449 } 1455 1450 pdsp->name = knav_queue_find_name(child); 1456 - ret = of_property_read_string(child, "firmware", 1457 - &pdsp->firmware); 1458 - if (ret < 0 || !pdsp->firmware) { 1459 - dev_err(dev, "unknown firmware for pdsp %s\n", 1460 - pdsp->name); 1461 - devm_kfree(dev, pdsp); 1462 - continue; 1463 - } 1464 - dev_dbg(dev, "pdsp name %s fw name :%s\n", pdsp->name, 1465 - pdsp->firmware); 1466 - 1467 1451 pdsp->iram = 1468 1452 knav_queue_map_reg(kdev, child, 1469 1453 KNAV_QUEUE_PDSP_IRAM_REG_INDEX); ··· 1483 1489 } 1484 1490 of_property_read_u32(child, "id", &pdsp->id); 1485 1491 list_add_tail(&pdsp->list, &kdev->pdsps); 1486 - dev_dbg(dev, "added pdsp %s: command %p, iram %p, regs %p, intd %p, firmware %s\n", 1492 + dev_dbg(dev, "added pdsp %s: command %p, iram %p, regs %p, intd %p\n", 1487 1493 pdsp->name, pdsp->command, pdsp->iram, pdsp->regs, 1488 - pdsp->intd, pdsp->firmware); 1494 + pdsp->intd); 1489 1495 } 1490 1496 return 0; 1491 1497 } ··· 1512 1518 { 1513 1519 int i, ret, fwlen; 1514 1520 const struct firmware *fw; 1521 + bool found = false; 1515 1522 u32 *fwdata; 1516 1523 1517 - ret = request_firmware(&fw, pdsp->firmware, kdev->dev); 1518 - if (ret) { 1519 - dev_err(kdev->dev, "failed to get firmware %s for pdsp %s\n", 1520 - pdsp->firmware, pdsp->name); 1521 - return ret; 1524 + for (i = 0; i < ARRAY_SIZE(knav_acc_firmwares); i++) { 1525 + if (knav_acc_firmwares[i]) { 1526 + ret = request_firmware(&fw, 1527 + knav_acc_firmwares[i], 1528 + kdev->dev); 1529 + if (!ret) { 1530 + found = true; 1531 + break; 1532 + } 1533 + } 1522 1534 } 1535 + 1536 + if (!found) { 1537 + dev_err(kdev->dev, "failed to get firmware for pdsp\n"); 1538 + return -ENODEV; 1539 + } 1540 + 1541 + dev_info(kdev->dev, "firmware file %s downloaded for PDSP\n", 1542 + knav_acc_firmwares[i]); 1543 + 1523 1544 writel_relaxed(pdsp->id + 1, pdsp->command + 0x18); 1524 1545 /* download the firmware */ 1525 1546 fwdata = (u32 *)fw->data;