diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-10 17:56:23 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-11-10 17:56:23 -0500 |
commit | 56e0464980febfa50432a070261579415c72664e (patch) | |
tree | ec4753abd2562c317ed5f33b81c156b319456fd5 /drivers/soc | |
parent | a5e1d715a8d0696961d99d31d869aa522f1cad5a (diff) | |
parent | b1e4006aeda8c8784029de17d47987c21ea75f6d (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/Kconfig | 1 | ||||
-rw-r--r-- | drivers/soc/Makefile | 1 | ||||
-rw-r--r-- | drivers/soc/brcmstb/Kconfig | 9 | ||||
-rw-r--r-- | drivers/soc/brcmstb/Makefile | 1 | ||||
-rw-r--r-- | drivers/soc/brcmstb/biuctrl.c | 116 | ||||
-rw-r--r-- | drivers/soc/brcmstb/common.c | 33 | ||||
-rw-r--r-- | drivers/soc/mediatek/mtk-pmic-wrap.c | 10 | ||||
-rw-r--r-- | drivers/soc/mediatek/mtk-scpsys.c | 83 | ||||
-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 |
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 @@ | |||
1 | menu "SOC (System On Chip) specific Drivers" | 1 | menu "SOC (System On Chip) specific Drivers" |
2 | 2 | ||
3 | source "drivers/soc/brcmstb/Kconfig" | ||
3 | source "drivers/soc/mediatek/Kconfig" | 4 | source "drivers/soc/mediatek/Kconfig" |
4 | source "drivers/soc/qcom/Kconfig" | 5 | source "drivers/soc/qcom/Kconfig" |
5 | source "drivers/soc/sunxi/Kconfig" | 6 | source "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 | ||
5 | obj-$(CONFIG_SOC_BRCMSTB) += brcmstb/ | ||
5 | obj-$(CONFIG_MACH_DOVE) += dove/ | 6 | obj-$(CONFIG_MACH_DOVE) += dove/ |
6 | obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ | 7 | obj-$(CONFIG_ARCH_MEDIATEK) += mediatek/ |
7 | obj-$(CONFIG_ARCH_QCOM) += qcom/ | 8 | obj-$(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 @@ | |||
1 | menuconfig 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 | |||
26 | static void __iomem *cpubiuctrl_base; | ||
27 | static bool mcp_wr_pairing_en; | ||
28 | |||
29 | static 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 | |||
52 | static 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"); | ||
71 | out: | ||
72 | of_node_put(np); | ||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | #ifdef CONFIG_PM_SLEEP | ||
77 | static u32 cpu_credit_reg_dump; /* for save/restore */ | ||
78 | |||
79 | static 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 | |||
87 | static 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 | |||
94 | static 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 | |||
101 | void __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 | |||
19 | static const struct of_device_id brcmstb_machine_match[] = { | ||
20 | { .compatible = "brcm,brcmstb", }, | ||
21 | { } | ||
22 | }; | ||
23 | |||
24 | bool 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 | ||
56 | enum clk_id { | 56 | enum 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 | |||
63 | struct scp_domain_data { | 67 | struct 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 | ||
73 | static const struct scp_domain_data scp_domain_data[] __initconst = { | 78 | static 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; | |||
166 | struct scp_domain { | 172 | struct 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 | ||
177 | struct scp { | 184 | struct 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 | ||
284 | err_pwr_ack: | 296 | err_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 | } | ||
286 | err_clk: | 301 | err_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 | ||
390 | static 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 | |||
374 | static int __init scpsys_probe(struct platform_device *pdev) | 401 | static 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 | ||
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 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 | */ |
488 | int knav_init_acc_range(struct knav_device *kdev, | 488 | int 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 | */ | ||
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 | } |