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:
Arnd Bergmann 2015-10-15 22:22:26 +02:00
commit cfd96d3e74
5 changed files with 109 additions and 28 deletions

View file

@ -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 {

View file

@ -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)) {

View file

@ -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;
}