diff options
author | Arnd Bergmann <arnd@arndb.de> | 2015-10-15 16:22:26 -0400 |
---|---|---|
committer | Arnd Bergmann <arnd@arndb.de> | 2015-10-15 16:22:26 -0400 |
commit | cfd96d3e74f72fff552fd996634bdf3497a8acc9 (patch) | |
tree | 6b8ce8341a4445ca0a662a0aadee5dd92d762f0b /drivers/soc | |
parent | d72b712824ef906f548210b0012ff7c2a041ef7e (diff) | |
parent | 045016902bf7abeeb2a86fc9284c30dce228f055 (diff) |
Merge tag 'keystone-driver-soc_v2' of git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone into next/soc
Merge "ARM Keystone SOC driver updates for 4.4" from Santosh Shilimkar:
Documentation and support to be able to load the PDSP
firmware necessary for accumulator operation.
* tag 'keystone-driver-soc_v2' of git://git.kernel.org/pub/scm/linux/kernel/git/ssantosh/linux-keystone:
soc: ti: qmss: make acc queue support optional in the driver
soc: ti: add firmware file name as part of the driver
Documentation: dt: soc: Add description for knav qmss driver
Diffstat (limited to 'drivers/soc')
-rw-r--r-- | drivers/soc/ti/knav_qmss.h | 3 | ||||
-rw-r--r-- | drivers/soc/ti/knav_qmss_acc.c | 10 | ||||
-rw-r--r-- | drivers/soc/ti/knav_qmss_queue.c | 67 |
3 files changed, 53 insertions, 27 deletions
diff --git a/drivers/soc/ti/knav_qmss.h b/drivers/soc/ti/knav_qmss.h index 51da2341280d..6ff936cacb70 100644 --- a/drivers/soc/ti/knav_qmss.h +++ b/drivers/soc/ti/knav_qmss.h | |||
@@ -135,9 +135,10 @@ struct knav_pdsp_info { | |||
135 | }; | 135 | }; |
136 | void __iomem *intd; | 136 | void __iomem *intd; |
137 | u32 __iomem *iram; | 137 | u32 __iomem *iram; |
138 | const char *firmware; | ||
139 | u32 id; | 138 | u32 id; |
140 | struct list_head list; | 139 | struct list_head list; |
140 | bool loaded; | ||
141 | bool started; | ||
141 | }; | 142 | }; |
142 | 143 | ||
143 | struct knav_qmgr_info { | 144 | struct knav_qmgr_info { |
diff --git a/drivers/soc/ti/knav_qmss_acc.c b/drivers/soc/ti/knav_qmss_acc.c index ef6f69db0bd0..37c4aa95492d 100644 --- a/drivers/soc/ti/knav_qmss_acc.c +++ b/drivers/soc/ti/knav_qmss_acc.c | |||
@@ -482,8 +482,8 @@ struct knav_range_ops knav_acc_range_ops = { | |||
482 | * Return 0 on success or error | 482 | * Return 0 on success or error |
483 | */ | 483 | */ |
484 | int knav_init_acc_range(struct knav_device *kdev, | 484 | int knav_init_acc_range(struct knav_device *kdev, |
485 | struct device_node *node, | 485 | struct device_node *node, |
486 | struct knav_range_info *range) | 486 | struct knav_range_info *range) |
487 | { | 487 | { |
488 | struct knav_acc_channel *acc; | 488 | struct knav_acc_channel *acc; |
489 | struct knav_pdsp_info *pdsp; | 489 | struct knav_pdsp_info *pdsp; |
@@ -526,6 +526,12 @@ int knav_init_acc_range(struct knav_device *kdev, | |||
526 | return -EINVAL; | 526 | return -EINVAL; |
527 | } | 527 | } |
528 | 528 | ||
529 | if (!pdsp->started) { | ||
530 | dev_err(kdev->dev, "pdsp id %d not started for range %s\n", | ||
531 | info->pdsp_id, range->name); | ||
532 | return -ENODEV; | ||
533 | } | ||
534 | |||
529 | info->pdsp = pdsp; | 535 | info->pdsp = pdsp; |
530 | channels = range->num_queues; | 536 | channels = range->num_queues; |
531 | if (of_get_property(node, "multi-queue", NULL)) { | 537 | if (of_get_property(node, "multi-queue", NULL)) { |
diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c index 6d8646db52cc..f3a0b6a4b54e 100644 --- a/drivers/soc/ti/knav_qmss_queue.c +++ b/drivers/soc/ti/knav_qmss_queue.c | |||
@@ -68,6 +68,12 @@ static DEFINE_MUTEX(knav_dev_lock); | |||
68 | idx < (kdev)->num_queues_in_use; \ | 68 | idx < (kdev)->num_queues_in_use; \ |
69 | idx++, inst = knav_queue_idx_to_inst(kdev, idx)) | 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 | * knav_queue_notify: qmss queue notfier call | 78 | * knav_queue_notify: qmss queue notfier call |
73 | * | 79 | * |
@@ -1439,7 +1445,6 @@ static int knav_queue_init_pdsps(struct knav_device *kdev, | |||
1439 | struct device *dev = kdev->dev; | 1445 | struct device *dev = kdev->dev; |
1440 | struct knav_pdsp_info *pdsp; | 1446 | struct knav_pdsp_info *pdsp; |
1441 | struct device_node *child; | 1447 | struct device_node *child; |
1442 | int ret; | ||
1443 | 1448 | ||
1444 | for_each_child_of_node(pdsps, child) { | 1449 | for_each_child_of_node(pdsps, child) { |
1445 | pdsp = devm_kzalloc(dev, sizeof(*pdsp), GFP_KERNEL); | 1450 | pdsp = devm_kzalloc(dev, sizeof(*pdsp), GFP_KERNEL); |
@@ -1448,17 +1453,6 @@ static int knav_queue_init_pdsps(struct knav_device *kdev, | |||
1448 | return -ENOMEM; | 1453 | return -ENOMEM; |
1449 | } | 1454 | } |
1450 | pdsp->name = knav_queue_find_name(child); | 1455 | pdsp->name = knav_queue_find_name(child); |
1451 | ret = of_property_read_string(child, "firmware", | ||
1452 | &pdsp->firmware); | ||
1453 | if (ret < 0 || !pdsp->firmware) { | ||
1454 | dev_err(dev, "unknown firmware for pdsp %s\n", | ||
1455 | pdsp->name); | ||
1456 | devm_kfree(dev, pdsp); | ||
1457 | continue; | ||
1458 | } | ||
1459 | dev_dbg(dev, "pdsp name %s fw name :%s\n", pdsp->name, | ||
1460 | pdsp->firmware); | ||
1461 | |||
1462 | pdsp->iram = | 1456 | pdsp->iram = |
1463 | knav_queue_map_reg(kdev, child, | 1457 | knav_queue_map_reg(kdev, child, |
1464 | KNAV_QUEUE_PDSP_IRAM_REG_INDEX); | 1458 | KNAV_QUEUE_PDSP_IRAM_REG_INDEX); |
@@ -1489,9 +1483,9 @@ static int knav_queue_init_pdsps(struct knav_device *kdev, | |||
1489 | } | 1483 | } |
1490 | of_property_read_u32(child, "id", &pdsp->id); | 1484 | of_property_read_u32(child, "id", &pdsp->id); |
1491 | list_add_tail(&pdsp->list, &kdev->pdsps); | 1485 | list_add_tail(&pdsp->list, &kdev->pdsps); |
1492 | dev_dbg(dev, "added pdsp %s: command %p, iram %p, regs %p, intd %p, firmware %s\n", | 1486 | dev_dbg(dev, "added pdsp %s: command %p, iram %p, regs %p, intd %p\n", |
1493 | pdsp->name, pdsp->command, pdsp->iram, pdsp->regs, | 1487 | pdsp->name, pdsp->command, pdsp->iram, pdsp->regs, |
1494 | pdsp->intd, pdsp->firmware); | 1488 | pdsp->intd); |
1495 | } | 1489 | } |
1496 | return 0; | 1490 | return 0; |
1497 | } | 1491 | } |
@@ -1510,6 +1504,8 @@ static int knav_queue_stop_pdsp(struct knav_device *kdev, | |||
1510 | dev_err(kdev->dev, "timed out on pdsp %s stop\n", pdsp->name); | 1504 | dev_err(kdev->dev, "timed out on pdsp %s stop\n", pdsp->name); |
1511 | return ret; | 1505 | return ret; |
1512 | } | 1506 | } |
1507 | pdsp->loaded = false; | ||
1508 | pdsp->started = false; | ||
1513 | return 0; | 1509 | return 0; |
1514 | } | 1510 | } |
1515 | 1511 | ||
@@ -1518,14 +1514,29 @@ static int knav_queue_load_pdsp(struct knav_device *kdev, | |||
1518 | { | 1514 | { |
1519 | int i, ret, fwlen; | 1515 | int i, ret, fwlen; |
1520 | const struct firmware *fw; | 1516 | const struct firmware *fw; |
1517 | bool found = false; | ||
1521 | u32 *fwdata; | 1518 | u32 *fwdata; |
1522 | 1519 | ||
1523 | ret = request_firmware(&fw, pdsp->firmware, kdev->dev); | 1520 | for (i = 0; i < ARRAY_SIZE(knav_acc_firmwares); i++) { |
1524 | if (ret) { | 1521 | if (knav_acc_firmwares[i]) { |
1525 | dev_err(kdev->dev, "failed to get firmware %s for pdsp %s\n", | 1522 | ret = request_firmware(&fw, |
1526 | pdsp->firmware, pdsp->name); | 1523 | knav_acc_firmwares[i], |
1527 | return ret; | 1524 | kdev->dev); |
1525 | if (!ret) { | ||
1526 | found = true; | ||
1527 | break; | ||
1528 | } | ||
1529 | } | ||
1530 | } | ||
1531 | |||
1532 | if (!found) { | ||
1533 | dev_err(kdev->dev, "failed to get firmware for pdsp\n"); | ||
1534 | return -ENODEV; | ||
1528 | } | 1535 | } |
1536 | |||
1537 | dev_info(kdev->dev, "firmware file %s downloaded for PDSP\n", | ||
1538 | knav_acc_firmwares[i]); | ||
1539 | |||
1529 | writel_relaxed(pdsp->id + 1, pdsp->command + 0x18); | 1540 | writel_relaxed(pdsp->id + 1, pdsp->command + 0x18); |
1530 | /* download the firmware */ | 1541 | /* download the firmware */ |
1531 | fwdata = (u32 *)fw->data; | 1542 | fwdata = (u32 *)fw->data; |
@@ -1583,16 +1594,24 @@ static int knav_queue_start_pdsps(struct knav_device *kdev) | |||
1583 | int ret; | 1594 | int ret; |
1584 | 1595 | ||
1585 | knav_queue_stop_pdsps(kdev); | 1596 | knav_queue_stop_pdsps(kdev); |
1586 | /* now load them all */ | 1597 | /* now load them all. We return success even if pdsp |
1598 | * is not loaded as acc channels are optional on having | ||
1599 | * firmware availability in the system. We set the loaded | ||
1600 | * and stated flag and when initialize the acc range, check | ||
1601 | * it and init the range only if pdsp is started. | ||
1602 | */ | ||
1587 | for_each_pdsp(kdev, pdsp) { | 1603 | for_each_pdsp(kdev, pdsp) { |
1588 | ret = knav_queue_load_pdsp(kdev, pdsp); | 1604 | ret = knav_queue_load_pdsp(kdev, pdsp); |
1589 | if (ret < 0) | 1605 | if (!ret) |
1590 | return ret; | 1606 | pdsp->loaded = true; |
1591 | } | 1607 | } |
1592 | 1608 | ||
1593 | for_each_pdsp(kdev, pdsp) { | 1609 | for_each_pdsp(kdev, pdsp) { |
1594 | ret = knav_queue_start_pdsp(kdev, pdsp); | 1610 | if (pdsp->loaded) { |
1595 | WARN_ON(ret); | 1611 | ret = knav_queue_start_pdsp(kdev, pdsp); |
1612 | if (!ret) | ||
1613 | pdsp->started = true; | ||
1614 | } | ||
1596 | } | 1615 | } |
1597 | return 0; | 1616 | return 0; |
1598 | } | 1617 | } |