aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/soc
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2015-11-10 17:56:23 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2015-11-10 17:56:23 -0500
commit56e0464980febfa50432a070261579415c72664e (patch)
treeec4753abd2562c317ed5f33b81c156b319456fd5 /drivers/soc
parenta5e1d715a8d0696961d99d31d869aa522f1cad5a (diff)
parentb1e4006aeda8c8784029de17d47987c21ea75f6d (diff)
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')
-rw-r--r--drivers/soc/Kconfig1
-rw-r--r--drivers/soc/Makefile1
-rw-r--r--drivers/soc/brcmstb/Kconfig9
-rw-r--r--drivers/soc/brcmstb/Makefile1
-rw-r--r--drivers/soc/brcmstb/biuctrl.c116
-rw-r--r--drivers/soc/brcmstb/common.c33
-rw-r--r--drivers/soc/mediatek/mtk-pmic-wrap.c10
-rw-r--r--drivers/soc/mediatek/mtk-scpsys.c83
-rw-r--r--drivers/soc/ti/knav_qmss.h3
-rw-r--r--drivers/soc/ti/knav_qmss_acc.c10
-rw-r--r--drivers/soc/ti/knav_qmss_queue.c67
11 files changed, 280 insertions, 54 deletions
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 96ddecb92254..c9c0fcce98a7 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -1,5 +1,6 @@
1menu "SOC (System On Chip) specific Drivers" 1menu "SOC (System On Chip) specific Drivers"
2 2
3source "drivers/soc/brcmstb/Kconfig"
3source "drivers/soc/mediatek/Kconfig" 4source "drivers/soc/mediatek/Kconfig"
4source "drivers/soc/qcom/Kconfig" 5source "drivers/soc/qcom/Kconfig"
5source "drivers/soc/sunxi/Kconfig" 6source "drivers/soc/sunxi/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index 0b12d777d3c4..4e27f10367f0 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -2,6 +2,7 @@
2# Makefile for the Linux Kernel SOC specific device drivers. 2# Makefile for the Linux Kernel SOC specific device drivers.
3# 3#
4 4
5obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/
5obj-$(CONFIG_MACH_DOVE) += dove/ 6obj-$(CONFIG_MACH_DOVE) += dove/
6obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ 7obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/
7obj-$(CONFIG_ARCH_QCOM) += qcom/ 8obj-$(CONFIG_ARCH_QCOM) += qcom/
diff --git a/drivers/soc/brcmstb/Kconfig b/drivers/soc/brcmstb/Kconfig
new file mode 100644
index 000000000000..39cab3bd544d
--- /dev/null
+++ b/drivers/soc/brcmstb/Kconfig
@@ -0,0 +1,9 @@
1menuconfig SOC_BRCMSTB
2 bool "Broadcom STB SoC drivers"
3 depends on ARM
4 help
5 Enables drivers for the Broadcom Set-Top Box (STB) series of chips.
6 This option alone enables only some support code, while the drivers
7 can be enabled individually within this menu.
8
9 If unsure, say N.
diff --git a/drivers/soc/brcmstb/Makefile b/drivers/soc/brcmstb/Makefile
new file mode 100644
index 000000000000..9120b2715d3e
--- /dev/null
+++ b/drivers/soc/brcmstb/Makefile
@@ -0,0 +1 @@
obj-y += common.o biuctrl.o
diff --git a/drivers/soc/brcmstb/biuctrl.c b/drivers/soc/brcmstb/biuctrl.c
new file mode 100644
index 000000000000..9049c076f9a1
--- /dev/null
+++ b/drivers/soc/brcmstb/biuctrl.c
@@ -0,0 +1,116 @@
1/*
2 * Broadcom STB SoCs Bus Unit Interface controls
3 *
4 * Copyright (C) 2015, Broadcom Corporation
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 */
15
16#define pr_fmt(fmt) "brcmstb: " KBUILD_MODNAME ": " fmt
17
18#include <linux/kernel.h>
19#include <linux/io.h>
20#include <linux/of_address.h>
21#include <linux/syscore_ops.h>
22
23#define CPU_CREDIT_REG_OFFSET 0x184
24#define CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK 0x70000000
25
26static void __iomem *cpubiuctrl_base;
27static bool mcp_wr_pairing_en;
28
29static int __init mcp_write_pairing_set(void)
30{
31 u32 creds = 0;
32
33 if (!cpubiuctrl_base)
34 return -1;
35
36 creds = readl_relaxed(cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
37 if (mcp_wr_pairing_en) {
38 pr_info("MCP: Enabling write pairing\n");
39 writel_relaxed(creds | CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
40 cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
41 } else if (creds & CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK) {
42 pr_info("MCP: Disabling write pairing\n");
43 writel_relaxed(creds & ~CPU_CREDIT_REG_MCPx_WR_PAIRING_EN_MASK,
44 cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
45 } else {
46 pr_info("MCP: Write pairing already disabled\n");
47 }
48
49 return 0;
50}
51
52static int __init setup_hifcpubiuctrl_regs(void)
53{
54 struct device_node *np;
55 int ret = 0;
56
57 np = of_find_compatible_node(NULL, NULL, "brcm,brcmstb-cpu-biu-ctrl");
58 if (!np) {
59 pr_err("missing BIU control node\n");
60 return -ENODEV;
61 }
62
63 cpubiuctrl_base = of_iomap(np, 0);
64 if (!cpubiuctrl_base) {
65 pr_err("failed to remap BIU control base\n");
66 ret = -ENOMEM;
67 goto out;
68 }
69
70 mcp_wr_pairing_en = of_property_read_bool(np, "brcm,write-pairing");
71out:
72 of_node_put(np);
73 return ret;
74}
75
76#ifdef CONFIG_PM_SLEEP
77static u32 cpu_credit_reg_dump; /* for save/restore */
78
79static int brcmstb_cpu_credit_reg_suspend(void)
80{
81 if (cpubiuctrl_base)
82 cpu_credit_reg_dump =
83 readl_relaxed(cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
84 return 0;
85}
86
87static void brcmstb_cpu_credit_reg_resume(void)
88{
89 if (cpubiuctrl_base)
90 writel_relaxed(cpu_credit_reg_dump,
91 cpubiuctrl_base + CPU_CREDIT_REG_OFFSET);
92}
93
94static struct syscore_ops brcmstb_cpu_credit_syscore_ops = {
95 .suspend = brcmstb_cpu_credit_reg_suspend,
96 .resume = brcmstb_cpu_credit_reg_resume,
97};
98#endif
99
100
101void __init brcmstb_biuctrl_init(void)
102{
103 int ret;
104
105 setup_hifcpubiuctrl_regs();
106
107 ret = mcp_write_pairing_set();
108 if (ret) {
109 pr_err("MCP: Unable to disable write pairing!\n");
110 return;
111 }
112
113#ifdef CONFIG_PM_SLEEP
114 register_syscore_ops(&brcmstb_cpu_credit_syscore_ops);
115#endif
116}
diff --git a/drivers/soc/brcmstb/common.c b/drivers/soc/brcmstb/common.c
new file mode 100644
index 000000000000..c262c029b1b8
--- /dev/null
+++ b/drivers/soc/brcmstb/common.c
@@ -0,0 +1,33 @@
1/*
2 * Copyright © 2014 NVIDIA Corporation
3 * Copyright © 2015 Broadcom Corporation
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 */
14
15#include <linux/of.h>
16
17#include <soc/brcmstb/common.h>
18
19static const struct of_device_id brcmstb_machine_match[] = {
20 { .compatible = "brcm,brcmstb", },
21 { }
22};
23
24bool soc_is_brcmstb(void)
25{
26 struct device_node *root;
27
28 root = of_find_node_by_path("/");
29 if (!root)
30 return false;
31
32 return of_match_node(brcmstb_machine_match, root) != NULL;
33}
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
index 8bc7b41b09fd..105597a885cb 100644
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -725,10 +725,6 @@ static int pwrap_init(struct pmic_wrapper *wrp)
725 pwrap_writel(wrp, 0x1, PWRAP_WACS2_EN); 725 pwrap_writel(wrp, 0x1, PWRAP_WACS2_EN);
726 pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD); 726 pwrap_writel(wrp, 0x5, PWRAP_STAUPD_PRD);
727 pwrap_writel(wrp, 0xff, PWRAP_STAUPD_GRPEN); 727 pwrap_writel(wrp, 0xff, PWRAP_STAUPD_GRPEN);
728 pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT);
729 pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN);
730 pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN);
731 pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN);
732 728
733 if (pwrap_is_mt8135(wrp)) { 729 if (pwrap_is_mt8135(wrp)) {
734 /* enable pwrap events and pwrap bridge in AP side */ 730 /* enable pwrap events and pwrap bridge in AP side */
@@ -896,6 +892,12 @@ static int pwrap_probe(struct platform_device *pdev)
896 return -ENODEV; 892 return -ENODEV;
897 } 893 }
898 894
895 /* Initialize watchdog, may not be done by the bootloader */
896 pwrap_writel(wrp, 0xf, PWRAP_WDT_UNIT);
897 pwrap_writel(wrp, 0xffffffff, PWRAP_WDT_SRC_EN);
898 pwrap_writel(wrp, 0x1, PWRAP_TIMER_EN);
899 pwrap_writel(wrp, ~((1 << 31) | (1 << 1)), PWRAP_INT_EN);
900
899 irq = platform_get_irq(pdev, 0); 901 irq = platform_get_irq(pdev, 0);
900 ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, IRQF_TRIGGER_HIGH, 902 ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt, IRQF_TRIGGER_HIGH,
901 "mt-pmic-pwrap", wrp); 903 "mt-pmic-pwrap", wrp);
diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c
index 164a7d8439b1..4d4203c896c4 100644
--- a/drivers/soc/mediatek/mtk-scpsys.c
+++ b/drivers/soc/mediatek/mtk-scpsys.c
@@ -54,12 +54,16 @@
54#define PWR_STATUS_USB BIT(25) 54#define PWR_STATUS_USB BIT(25)
55 55
56enum clk_id { 56enum clk_id {
57 MT8173_CLK_NONE,
57 MT8173_CLK_MM, 58 MT8173_CLK_MM,
58 MT8173_CLK_MFG, 59 MT8173_CLK_MFG,
59 MT8173_CLK_NONE, 60 MT8173_CLK_VENC,
60 MT8173_CLK_MAX = MT8173_CLK_NONE, 61 MT8173_CLK_VENC_LT,
62 MT8173_CLK_MAX,
61}; 63};
62 64
65#define MAX_CLKS 2
66
63struct scp_domain_data { 67struct scp_domain_data {
64 const char *name; 68 const char *name;
65 u32 sta_mask; 69 u32 sta_mask;
@@ -67,7 +71,8 @@ struct scp_domain_data {
67 u32 sram_pdn_bits; 71 u32 sram_pdn_bits;
68 u32 sram_pdn_ack_bits; 72 u32 sram_pdn_ack_bits;
69 u32 bus_prot_mask; 73 u32 bus_prot_mask;
70 enum clk_id clk_id; 74 enum clk_id clk_id[MAX_CLKS];
75 bool active_wakeup;
71}; 76};
72 77
73static const struct scp_domain_data scp_domain_data[] __initconst = { 78static const struct scp_domain_data scp_domain_data[] __initconst = {
@@ -77,7 +82,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
77 .ctl_offs = SPM_VDE_PWR_CON, 82 .ctl_offs = SPM_VDE_PWR_CON,
78 .sram_pdn_bits = GENMASK(11, 8), 83 .sram_pdn_bits = GENMASK(11, 8),
79 .sram_pdn_ack_bits = GENMASK(12, 12), 84 .sram_pdn_ack_bits = GENMASK(12, 12),
80 .clk_id = MT8173_CLK_MM, 85 .clk_id = {MT8173_CLK_MM},
81 }, 86 },
82 [MT8173_POWER_DOMAIN_VENC] = { 87 [MT8173_POWER_DOMAIN_VENC] = {
83 .name = "venc", 88 .name = "venc",
@@ -85,7 +90,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
85 .ctl_offs = SPM_VEN_PWR_CON, 90 .ctl_offs = SPM_VEN_PWR_CON,
86 .sram_pdn_bits = GENMASK(11, 8), 91 .sram_pdn_bits = GENMASK(11, 8),
87 .sram_pdn_ack_bits = GENMASK(15, 12), 92 .sram_pdn_ack_bits = GENMASK(15, 12),
88 .clk_id = MT8173_CLK_MM, 93 .clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC},
89 }, 94 },
90 [MT8173_POWER_DOMAIN_ISP] = { 95 [MT8173_POWER_DOMAIN_ISP] = {
91 .name = "isp", 96 .name = "isp",
@@ -93,7 +98,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
93 .ctl_offs = SPM_ISP_PWR_CON, 98 .ctl_offs = SPM_ISP_PWR_CON,
94 .sram_pdn_bits = GENMASK(11, 8), 99 .sram_pdn_bits = GENMASK(11, 8),
95 .sram_pdn_ack_bits = GENMASK(13, 12), 100 .sram_pdn_ack_bits = GENMASK(13, 12),
96 .clk_id = MT8173_CLK_MM, 101 .clk_id = {MT8173_CLK_MM},
97 }, 102 },
98 [MT8173_POWER_DOMAIN_MM] = { 103 [MT8173_POWER_DOMAIN_MM] = {
99 .name = "mm", 104 .name = "mm",
@@ -101,7 +106,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
101 .ctl_offs = SPM_DIS_PWR_CON, 106 .ctl_offs = SPM_DIS_PWR_CON,
102 .sram_pdn_bits = GENMASK(11, 8), 107 .sram_pdn_bits = GENMASK(11, 8),
103 .sram_pdn_ack_bits = GENMASK(12, 12), 108 .sram_pdn_ack_bits = GENMASK(12, 12),
104 .clk_id = MT8173_CLK_MM, 109 .clk_id = {MT8173_CLK_MM},
105 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 | 110 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MM_M0 |
106 MT8173_TOP_AXI_PROT_EN_MM_M1, 111 MT8173_TOP_AXI_PROT_EN_MM_M1,
107 }, 112 },
@@ -111,7 +116,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
111 .ctl_offs = SPM_VEN2_PWR_CON, 116 .ctl_offs = SPM_VEN2_PWR_CON,
112 .sram_pdn_bits = GENMASK(11, 8), 117 .sram_pdn_bits = GENMASK(11, 8),
113 .sram_pdn_ack_bits = GENMASK(15, 12), 118 .sram_pdn_ack_bits = GENMASK(15, 12),
114 .clk_id = MT8173_CLK_MM, 119 .clk_id = {MT8173_CLK_MM, MT8173_CLK_VENC_LT},
115 }, 120 },
116 [MT8173_POWER_DOMAIN_AUDIO] = { 121 [MT8173_POWER_DOMAIN_AUDIO] = {
117 .name = "audio", 122 .name = "audio",
@@ -119,7 +124,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
119 .ctl_offs = SPM_AUDIO_PWR_CON, 124 .ctl_offs = SPM_AUDIO_PWR_CON,
120 .sram_pdn_bits = GENMASK(11, 8), 125 .sram_pdn_bits = GENMASK(11, 8),
121 .sram_pdn_ack_bits = GENMASK(15, 12), 126 .sram_pdn_ack_bits = GENMASK(15, 12),
122 .clk_id = MT8173_CLK_NONE, 127 .clk_id = {MT8173_CLK_NONE},
123 }, 128 },
124 [MT8173_POWER_DOMAIN_USB] = { 129 [MT8173_POWER_DOMAIN_USB] = {
125 .name = "usb", 130 .name = "usb",
@@ -127,7 +132,8 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
127 .ctl_offs = SPM_USB_PWR_CON, 132 .ctl_offs = SPM_USB_PWR_CON,
128 .sram_pdn_bits = GENMASK(11, 8), 133 .sram_pdn_bits = GENMASK(11, 8),
129 .sram_pdn_ack_bits = GENMASK(15, 12), 134 .sram_pdn_ack_bits = GENMASK(15, 12),
130 .clk_id = MT8173_CLK_NONE, 135 .clk_id = {MT8173_CLK_NONE},
136 .active_wakeup = true,
131 }, 137 },
132 [MT8173_POWER_DOMAIN_MFG_ASYNC] = { 138 [MT8173_POWER_DOMAIN_MFG_ASYNC] = {
133 .name = "mfg_async", 139 .name = "mfg_async",
@@ -135,7 +141,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
135 .ctl_offs = SPM_MFG_ASYNC_PWR_CON, 141 .ctl_offs = SPM_MFG_ASYNC_PWR_CON,
136 .sram_pdn_bits = GENMASK(11, 8), 142 .sram_pdn_bits = GENMASK(11, 8),
137 .sram_pdn_ack_bits = 0, 143 .sram_pdn_ack_bits = 0,
138 .clk_id = MT8173_CLK_MFG, 144 .clk_id = {MT8173_CLK_MFG},
139 }, 145 },
140 [MT8173_POWER_DOMAIN_MFG_2D] = { 146 [MT8173_POWER_DOMAIN_MFG_2D] = {
141 .name = "mfg_2d", 147 .name = "mfg_2d",
@@ -143,7 +149,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
143 .ctl_offs = SPM_MFG_2D_PWR_CON, 149 .ctl_offs = SPM_MFG_2D_PWR_CON,
144 .sram_pdn_bits = GENMASK(11, 8), 150 .sram_pdn_bits = GENMASK(11, 8),
145 .sram_pdn_ack_bits = GENMASK(13, 12), 151 .sram_pdn_ack_bits = GENMASK(13, 12),
146 .clk_id = MT8173_CLK_NONE, 152 .clk_id = {MT8173_CLK_NONE},
147 }, 153 },
148 [MT8173_POWER_DOMAIN_MFG] = { 154 [MT8173_POWER_DOMAIN_MFG] = {
149 .name = "mfg", 155 .name = "mfg",
@@ -151,7 +157,7 @@ static const struct scp_domain_data scp_domain_data[] __initconst = {
151 .ctl_offs = SPM_MFG_PWR_CON, 157 .ctl_offs = SPM_MFG_PWR_CON,
152 .sram_pdn_bits = GENMASK(13, 8), 158 .sram_pdn_bits = GENMASK(13, 8),
153 .sram_pdn_ack_bits = GENMASK(21, 16), 159 .sram_pdn_ack_bits = GENMASK(21, 16),
154 .clk_id = MT8173_CLK_NONE, 160 .clk_id = {MT8173_CLK_NONE},
155 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S | 161 .bus_prot_mask = MT8173_TOP_AXI_PROT_EN_MFG_S |
156 MT8173_TOP_AXI_PROT_EN_MFG_M0 | 162 MT8173_TOP_AXI_PROT_EN_MFG_M0 |
157 MT8173_TOP_AXI_PROT_EN_MFG_M1 | 163 MT8173_TOP_AXI_PROT_EN_MFG_M1 |
@@ -166,12 +172,13 @@ struct scp;
166struct scp_domain { 172struct scp_domain {
167 struct generic_pm_domain genpd; 173 struct generic_pm_domain genpd;
168 struct scp *scp; 174 struct scp *scp;
169 struct clk *clk; 175 struct clk *clk[MAX_CLKS];
170 u32 sta_mask; 176 u32 sta_mask;
171 void __iomem *ctl_addr; 177 void __iomem *ctl_addr;
172 u32 sram_pdn_bits; 178 u32 sram_pdn_bits;
173 u32 sram_pdn_ack_bits; 179 u32 sram_pdn_ack_bits;
174 u32 bus_prot_mask; 180 u32 bus_prot_mask;
181 bool active_wakeup;
175}; 182};
176 183
177struct scp { 184struct scp {
@@ -212,11 +219,16 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
212 u32 sram_pdn_ack = scpd->sram_pdn_ack_bits; 219 u32 sram_pdn_ack = scpd->sram_pdn_ack_bits;
213 u32 val; 220 u32 val;
214 int ret; 221 int ret;
222 int i;
223
224 for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++) {
225 ret = clk_prepare_enable(scpd->clk[i]);
226 if (ret) {
227 for (--i; i >= 0; i--)
228 clk_disable_unprepare(scpd->clk[i]);
215 229
216 if (scpd->clk) {
217 ret = clk_prepare_enable(scpd->clk);
218 if (ret)
219 goto err_clk; 230 goto err_clk;
231 }
220 } 232 }
221 233
222 val = readl(ctl_addr); 234 val = readl(ctl_addr);
@@ -282,7 +294,10 @@ static int scpsys_power_on(struct generic_pm_domain *genpd)
282 return 0; 294 return 0;
283 295
284err_pwr_ack: 296err_pwr_ack:
285 clk_disable_unprepare(scpd->clk); 297 for (i = MAX_CLKS - 1; i >= 0; i--) {
298 if (scpd->clk[i])
299 clk_disable_unprepare(scpd->clk[i]);
300 }
286err_clk: 301err_clk:
287 dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name); 302 dev_err(scp->dev, "Failed to power on domain %s\n", genpd->name);
288 303
@@ -299,6 +314,7 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
299 u32 pdn_ack = scpd->sram_pdn_ack_bits; 314 u32 pdn_ack = scpd->sram_pdn_ack_bits;
300 u32 val; 315 u32 val;
301 int ret; 316 int ret;
317 int i;
302 318
303 if (scpd->bus_prot_mask) { 319 if (scpd->bus_prot_mask) {
304 ret = mtk_infracfg_set_bus_protection(scp->infracfg, 320 ret = mtk_infracfg_set_bus_protection(scp->infracfg,
@@ -360,8 +376,8 @@ static int scpsys_power_off(struct generic_pm_domain *genpd)
360 expired = true; 376 expired = true;
361 } 377 }
362 378
363 if (scpd->clk) 379 for (i = 0; i < MAX_CLKS && scpd->clk[i]; i++)
364 clk_disable_unprepare(scpd->clk); 380 clk_disable_unprepare(scpd->clk[i]);
365 381
366 return 0; 382 return 0;
367 383
@@ -371,11 +387,22 @@ out:
371 return ret; 387 return ret;
372} 388}
373 389
390static bool scpsys_active_wakeup(struct device *dev)
391{
392 struct generic_pm_domain *genpd;
393 struct scp_domain *scpd;
394
395 genpd = pd_to_genpd(dev->pm_domain);
396 scpd = container_of(genpd, struct scp_domain, genpd);
397
398 return scpd->active_wakeup;
399}
400
374static int __init scpsys_probe(struct platform_device *pdev) 401static int __init scpsys_probe(struct platform_device *pdev)
375{ 402{
376 struct genpd_onecell_data *pd_data; 403 struct genpd_onecell_data *pd_data;
377 struct resource *res; 404 struct resource *res;
378 int i, ret; 405 int i, j, ret;
379 struct scp *scp; 406 struct scp *scp;
380 struct clk *clk[MT8173_CLK_MAX]; 407 struct clk *clk[MT8173_CLK_MAX];
381 408
@@ -405,6 +432,14 @@ static int __init scpsys_probe(struct platform_device *pdev)
405 if (IS_ERR(clk[MT8173_CLK_MFG])) 432 if (IS_ERR(clk[MT8173_CLK_MFG]))
406 return PTR_ERR(clk[MT8173_CLK_MFG]); 433 return PTR_ERR(clk[MT8173_CLK_MFG]);
407 434
435 clk[MT8173_CLK_VENC] = devm_clk_get(&pdev->dev, "venc");
436 if (IS_ERR(clk[MT8173_CLK_VENC]))
437 return PTR_ERR(clk[MT8173_CLK_VENC]);
438
439 clk[MT8173_CLK_VENC_LT] = devm_clk_get(&pdev->dev, "venc_lt");
440 if (IS_ERR(clk[MT8173_CLK_VENC_LT]))
441 return PTR_ERR(clk[MT8173_CLK_VENC_LT]);
442
408 scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node, 443 scp->infracfg = syscon_regmap_lookup_by_phandle(pdev->dev.of_node,
409 "infracfg"); 444 "infracfg");
410 if (IS_ERR(scp->infracfg)) { 445 if (IS_ERR(scp->infracfg)) {
@@ -428,12 +463,14 @@ static int __init scpsys_probe(struct platform_device *pdev)
428 scpd->sram_pdn_bits = data->sram_pdn_bits; 463 scpd->sram_pdn_bits = data->sram_pdn_bits;
429 scpd->sram_pdn_ack_bits = data->sram_pdn_ack_bits; 464 scpd->sram_pdn_ack_bits = data->sram_pdn_ack_bits;
430 scpd->bus_prot_mask = data->bus_prot_mask; 465 scpd->bus_prot_mask = data->bus_prot_mask;
431 if (data->clk_id != MT8173_CLK_NONE) 466 scpd->active_wakeup = data->active_wakeup;
432 scpd->clk = clk[data->clk_id]; 467 for (j = 0; j < MAX_CLKS && data->clk_id[j]; j++)
468 scpd->clk[j] = clk[data->clk_id[j]];
433 469
434 genpd->name = data->name; 470 genpd->name = data->name;
435 genpd->power_off = scpsys_power_off; 471 genpd->power_off = scpsys_power_off;
436 genpd->power_on = scpsys_power_on; 472 genpd->power_on = scpsys_power_on;
473 genpd->dev_ops.active_wakeup = scpsys_active_wakeup;
437 474
438 /* 475 /*
439 * Initially turn on all domains to make the domains usable 476 * Initially turn on all domains to make the domains usable
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
143struct knav_qmgr_info { 144struct 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 = {
486 * Return 0 on success or error 486 * Return 0 on success or error
487 */ 487 */
488int knav_init_acc_range(struct knav_device *kdev, 488int knav_init_acc_range(struct knav_device *kdev,
489 struct device_node *node, 489 struct device_node *node,
490 struct knav_range_info *range) 490 struct knav_range_info *range)
491{ 491{
492 struct knav_acc_channel *acc; 492 struct knav_acc_channel *acc;
493 struct knav_pdsp_info *pdsp; 493 struct knav_pdsp_info *pdsp;
@@ -530,6 +530,12 @@ int knav_init_acc_range(struct knav_device *kdev,
530 return -EINVAL; 530 return -EINVAL;
531 } 531 }
532 532
533 if (!pdsp->started) {
534 dev_err(kdev->dev, "pdsp id %d not started for range %s\n",
535 info->pdsp_id, range->name);
536 return -ENODEV;
537 }
538
533 info->pdsp = pdsp; 539 info->pdsp = pdsp;
534 channels = range->num_queues; 540 channels = range->num_queues;
535 if (of_get_property(node, "multi-queue", NULL)) { 541 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 */
75const 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}