mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2025-01-16 13:34:30 +00:00
ARM Keystone SOC driver updates for 4.4
Documentation and support to be able to load the PDSP firmware necessary for accumulator operation. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJWHW8iAAoJEHJsHOdBp5c/9ywP/3Qpvy+kcnwMvwrnq/jxLlGk qc+gQTAMMguenYGZmIqnyLVHG9B4UUNZ6e/uiukzCxMP1SWx8KmgKNFSQonJuFVV wLufo+wYBTH4P8VIM5OJNkJVPqZ8YXwtVJ09LhVxYNh1vF/l6aOEQ/kaEC22f5sD jycgKdKx3yRn67VrWiuXS1MGXIDkGR3ABCxv6iJHSKyP15HArQ6fAhyrkfP/mNkr 9YXIrX+vmMdsICfXG19R2z/lCuM+JadXz9Rjo9yMQwvUw+3QAHYy8m4JXb9cZFZq jNZnzWQj5azuxaGnLVS1UNggsEXuxmd0S1PJvdF1N2ISHVYqwCtFuLjQ2r+z4WQm uzo9DyPTaYtASO6iSq9MQVzKKW0r0a5dPlAJIYTJHR11xi8kOpu04KUkJUR4c1ly X5I9zJ7ishV1VxFUZaMJtl/nX7B18WiKZyHhtO4MqRLPFA1fjH1psA/s8vRk6l6e unawCOM5oT8KvuSyijTNq2sQlxgRJJW7S4F1P1iUxsA6nocaPdTV+Oi/aECt8mFQ Q9gFVgCTEMWBYPuVqVisfU/mmZFPRDiotknMAeM+mUF6D/DkA0NSPvNWH0LP4rrA kIGRHQWtJMBTdxdBhjKoCsEEk1DR0wOCTUqow77SR/H3wl1FL1EYDB2J15JD7vzM lVTrZzd1wRXSsHINdnY6 =T5UX -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
cfd96d3e74
56
Documentation/arm/keystone/knav-qmss.txt
Normal file
56
Documentation/arm/keystone/knav-qmss.txt
Normal file
@ -0,0 +1,56 @@
|
||||
* Texas Instruments Keystone Navigator Queue Management SubSystem driver
|
||||
|
||||
Driver source code path
|
||||
drivers/soc/ti/knav_qmss.c
|
||||
drivers/soc/ti/knav_qmss_acc.c
|
||||
|
||||
The QMSS (Queue Manager Sub System) found on Keystone SOCs is one of
|
||||
the main hardware sub system which forms the backbone of the Keystone
|
||||
multi-core Navigator. QMSS consist of queue managers, packed-data structure
|
||||
processors(PDSP), linking RAM, descriptor pools and infrastructure
|
||||
Packet DMA.
|
||||
The Queue Manager is a hardware module that is responsible for accelerating
|
||||
management of the packet queues. Packets are queued/de-queued by writing or
|
||||
reading descriptor address to a particular memory mapped location. The PDSPs
|
||||
perform QMSS related functions like accumulation, QoS, or event management.
|
||||
Linking RAM registers are used to link the descriptors which are stored in
|
||||
descriptor RAM. Descriptor RAM is configurable as internal or external memory.
|
||||
The QMSS driver manages the PDSP setups, linking RAM regions,
|
||||
queue pool management (allocation, push, pop and notify) and descriptor
|
||||
pool management.
|
||||
|
||||
knav qmss driver provides a set of APIs to drivers to open/close qmss queues,
|
||||
allocate descriptor pools, map the descriptors, push/pop to queues etc. For
|
||||
details of the available APIs, please refers to include/linux/soc/ti/knav_qmss.h
|
||||
|
||||
DT documentation is available at
|
||||
Documentation/devicetree/bindings/soc/ti/keystone-navigator-qmss.txt
|
||||
|
||||
Accumulator QMSS queues using PDSP firmware
|
||||
============================================
|
||||
The QMSS PDSP firmware support accumulator channel that can monitor a single
|
||||
queue or multiple contiguous queues. drivers/soc/ti/knav_qmss_acc.c is the
|
||||
driver that interface with the accumulator PDSP. This configures
|
||||
accumulator channels defined in DTS (example in DT documentation) to monitor
|
||||
1 or 32 queues per channel. More description on the firmware is available in
|
||||
CPPI/QMSS Low Level Driver document (docs/CPPI_QMSS_LLD_SDS.pdf) at
|
||||
git://git.ti.com/keystone-rtos/qmss-lld.git
|
||||
|
||||
k2_qmss_pdsp_acc48_k2_le_1_0_0_9.bin firmware supports upto 48 accumulator
|
||||
channels. This firmware is available under ti-keystone folder of
|
||||
firmware.git at
|
||||
git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git
|
||||
|
||||
To use copy the firmware image to lib/firmware folder of the initramfs or
|
||||
ubifs file system and provide a sym link to k2_qmss_pdsp_acc48_k2_le_1_0_0_9.bin
|
||||
in the file system and boot up the kernel. User would see
|
||||
|
||||
"firmware file ks2_qmss_pdsp_acc48.bin downloaded for PDSP"
|
||||
|
||||
in the boot up log if loading of firmware to PDSP is successful.
|
||||
|
||||
Use of accumulated queues requires the firmware image to be present in the
|
||||
file system. The driver doesn't acc queues to the supported queue range if
|
||||
PDSP is not running in the SoC. The API call fails if there is a queue open
|
||||
request to an acc queue and PDSP is not running. So make sure to copy firmware
|
||||
to file system before using these queue types.
|
@ -221,7 +221,6 @@ qmss: qmss@2a40000 {
|
||||
#size-cells = <1>;
|
||||
ranges;
|
||||
pdsp0@0x2a10000 {
|
||||
firmware = "keystone/qmss_pdsp_acc48_k2_le_1_0_0_8.fw";
|
||||
reg = <0x2a10000 0x1000>,
|
||||
<0x2a0f000 0x100>,
|
||||
<0x2a0c000 0x3c8>,
|
||||
|
@ -135,9 +135,10 @@ struct knav_pdsp_info {
|
||||
};
|
||||
void __iomem *intd;
|
||||
u32 __iomem *iram;
|
||||
const char *firmware;
|
||||
u32 id;
|
||||
struct list_head list;
|
||||
bool loaded;
|
||||
bool started;
|
||||
};
|
||||
|
||||
struct knav_qmgr_info {
|
||||
|
@ -482,8 +482,8 @@ struct knav_range_ops knav_acc_range_ops = {
|
||||
* Return 0 on success or error
|
||||
*/
|
||||
int knav_init_acc_range(struct knav_device *kdev,
|
||||
struct device_node *node,
|
||||
struct knav_range_info *range)
|
||||
struct device_node *node,
|
||||
struct knav_range_info *range)
|
||||
{
|
||||
struct knav_acc_channel *acc;
|
||||
struct knav_pdsp_info *pdsp;
|
||||
@ -526,6 +526,12 @@ int knav_init_acc_range(struct knav_device *kdev,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!pdsp->started) {
|
||||
dev_err(kdev->dev, "pdsp id %d not started for range %s\n",
|
||||
info->pdsp_id, range->name);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
info->pdsp = pdsp;
|
||||
channels = range->num_queues;
|
||||
if (of_get_property(node, "multi-queue", NULL)) {
|
||||
|
@ -68,6 +68,12 @@ static DEFINE_MUTEX(knav_dev_lock);
|
||||
idx < (kdev)->num_queues_in_use; \
|
||||
idx++, inst = knav_queue_idx_to_inst(kdev, idx))
|
||||
|
||||
/* All firmware file names end up here. List the firmware file names below.
|
||||
* Newest followed by older ones. Search is done from start of the array
|
||||
* until a firmware file is found.
|
||||
*/
|
||||
const char *knav_acc_firmwares[] = {"ks2_qmss_pdsp_acc48.bin"};
|
||||
|
||||
/**
|
||||
* knav_queue_notify: qmss queue notfier call
|
||||
*
|
||||
@ -1439,7 +1445,6 @@ static int knav_queue_init_pdsps(struct knav_device *kdev,
|
||||
struct device *dev = kdev->dev;
|
||||
struct knav_pdsp_info *pdsp;
|
||||
struct device_node *child;
|
||||
int ret;
|
||||
|
||||
for_each_child_of_node(pdsps, child) {
|
||||
pdsp = devm_kzalloc(dev, sizeof(*pdsp), GFP_KERNEL);
|
||||
@ -1448,17 +1453,6 @@ static int knav_queue_init_pdsps(struct knav_device *kdev,
|
||||
return -ENOMEM;
|
||||
}
|
||||
pdsp->name = knav_queue_find_name(child);
|
||||
ret = of_property_read_string(child, "firmware",
|
||||
&pdsp->firmware);
|
||||
if (ret < 0 || !pdsp->firmware) {
|
||||
dev_err(dev, "unknown firmware for pdsp %s\n",
|
||||
pdsp->name);
|
||||
devm_kfree(dev, pdsp);
|
||||
continue;
|
||||
}
|
||||
dev_dbg(dev, "pdsp name %s fw name :%s\n", pdsp->name,
|
||||
pdsp->firmware);
|
||||
|
||||
pdsp->iram =
|
||||
knav_queue_map_reg(kdev, child,
|
||||
KNAV_QUEUE_PDSP_IRAM_REG_INDEX);
|
||||
@ -1489,9 +1483,9 @@ static int knav_queue_init_pdsps(struct knav_device *kdev,
|
||||
}
|
||||
of_property_read_u32(child, "id", &pdsp->id);
|
||||
list_add_tail(&pdsp->list, &kdev->pdsps);
|
||||
dev_dbg(dev, "added pdsp %s: command %p, iram %p, regs %p, intd %p, firmware %s\n",
|
||||
dev_dbg(dev, "added pdsp %s: command %p, iram %p, regs %p, intd %p\n",
|
||||
pdsp->name, pdsp->command, pdsp->iram, pdsp->regs,
|
||||
pdsp->intd, pdsp->firmware);
|
||||
pdsp->intd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -1510,6 +1504,8 @@ static int knav_queue_stop_pdsp(struct knav_device *kdev,
|
||||
dev_err(kdev->dev, "timed out on pdsp %s stop\n", pdsp->name);
|
||||
return ret;
|
||||
}
|
||||
pdsp->loaded = false;
|
||||
pdsp->started = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -1518,14 +1514,29 @@ static int knav_queue_load_pdsp(struct knav_device *kdev,
|
||||
{
|
||||
int i, ret, fwlen;
|
||||
const struct firmware *fw;
|
||||
bool found = false;
|
||||
u32 *fwdata;
|
||||
|
||||
ret = request_firmware(&fw, pdsp->firmware, kdev->dev);
|
||||
if (ret) {
|
||||
dev_err(kdev->dev, "failed to get firmware %s for pdsp %s\n",
|
||||
pdsp->firmware, pdsp->name);
|
||||
return ret;
|
||||
for (i = 0; i < ARRAY_SIZE(knav_acc_firmwares); i++) {
|
||||
if (knav_acc_firmwares[i]) {
|
||||
ret = request_firmware(&fw,
|
||||
knav_acc_firmwares[i],
|
||||
kdev->dev);
|
||||
if (!ret) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
dev_err(kdev->dev, "failed to get firmware for pdsp\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dev_info(kdev->dev, "firmware file %s downloaded for PDSP\n",
|
||||
knav_acc_firmwares[i]);
|
||||
|
||||
writel_relaxed(pdsp->id + 1, pdsp->command + 0x18);
|
||||
/* download the firmware */
|
||||
fwdata = (u32 *)fw->data;
|
||||
@ -1583,16 +1594,24 @@ static int knav_queue_start_pdsps(struct knav_device *kdev)
|
||||
int ret;
|
||||
|
||||
knav_queue_stop_pdsps(kdev);
|
||||
/* now load them all */
|
||||
/* now load them all. We return success even if pdsp
|
||||
* is not loaded as acc channels are optional on having
|
||||
* firmware availability in the system. We set the loaded
|
||||
* and stated flag and when initialize the acc range, check
|
||||
* it and init the range only if pdsp is started.
|
||||
*/
|
||||
for_each_pdsp(kdev, pdsp) {
|
||||
ret = knav_queue_load_pdsp(kdev, pdsp);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (!ret)
|
||||
pdsp->loaded = true;
|
||||
}
|
||||
|
||||
for_each_pdsp(kdev, pdsp) {
|
||||
ret = knav_queue_start_pdsp(kdev, pdsp);
|
||||
WARN_ON(ret);
|
||||
if (pdsp->loaded) {
|
||||
ret = knav_queue_start_pdsp(kdev, pdsp);
|
||||
if (!ret)
|
||||
pdsp->started = true;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user