diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-10 14:56:23 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-10 14:56:23 -0800 |
commit | 56e0464980febfa50432a070261579415c72664e (patch) | |
tree | ec4753abd2562c317ed5f33b81c156b319456fd5 /drivers/soc/ti | |
parent | a5e1d715a8d0696961d99d31d869aa522f1cad5a (diff) | |
parent | b1e4006aeda8c8784029de17d47987c21ea75f6d (diff) | |
download | linux-56e0464980febfa50432a070261579415c72664e.tar.bz2 |
Merge tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
Pull ARM SoC platform updates from Olof Johansson:
"New and/or improved SoC support for this release:
Marvell Berlin:
- Enable standard DT-based cpufreq
- Add CPU hotplug support
Freescale:
- Ethernet init for i.MX7D
- Suspend/resume support for i.MX6UL
Allwinner:
- Support for R8 chipset (used on NTC's $9 C.H.I.P board)
Mediatek:
- SMP support for some platforms
Uniphier:
- L2 support
- Cleaned up SMP support, etc.
plus a handful of other patches around above functionality, and a few
other smaller changes"
* tag 'armsoc-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (42 commits)
ARM: uniphier: rework SMP operations to use trampoline code
ARM: uniphier: add outer cache support
Documentation: EXYNOS: Update bootloader interface on exynos542x
ARM: mvebu: add broken-idle option
ARM: orion5x: use mac_pton() helper
ARM: at91: pm: at91_pm_suspend_in_sram() must be 8-byte aligned
ARM: sunxi: Add R8 support
ARM: digicolor: select pinctrl/gpio driver
arm: berlin: add CPU hotplug support
arm: berlin: use non-self-cleared reset register to reset cpu
ARM: mediatek: add smp bringup code
ARM: mediatek: enable gpt6 on boot up to make arch timer working
soc: mediatek: Fix random hang up issue while kernel init
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
ARM: S3C64XX: Use PWM lookup table for mach-smartq
ARM: S3C64XX: Use PWM lookup table for mach-hmt
ARM: S3C64XX: Use PWM lookup table for mach-crag6410
ARM: S3C64XX: Use PWM lookup table for smdk6410
...
Diffstat (limited to 'drivers/soc/ti')
-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 { }; void __iomem *intd; u32 __iomem *iram; - const char *firmware; u32 id; struct list_head list; + bool loaded; + bool started; }; struct knav_qmgr_info { diff --git a/drivers/soc/ti/knav_qmss_acc.c b/drivers/soc/ti/knav_qmss_acc.c index b98fe56598dd..d2d48f2802bc 100644 --- a/drivers/soc/ti/knav_qmss_acc.c +++ b/drivers/soc/ti/knav_qmss_acc.c @@ -486,8 +486,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; @@ -530,6 +530,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)) { 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); 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; } |