History

Merge tag 'arm-drivers-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc

Pull ARM driver updates from Arnd Bergmann: "These are the usual updates for SoC specific device drivers and related subsystems that don't have their own top-level maintainers: - ARM SCMI/SCPI updates to allow pluggable transport layers - TEE subsystem cleanups - A new driver for the Amlogic secure power domain controller - Various driver updates for the NXP Layerscape DPAA2, NXP i.MX SCU and TI OMAP2+ sysc drivers. - Qualcomm SoC driver updates, including a new library module for "protection domain" notifications - Lots of smaller bugfixes and cleanups in other drivers" * tag 'arm-drivers-5.7' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (70 commits) soc: fsl: qe: fix sparse warnings for ucc_slow.c soc: fsl: qe: ucc_slow: remove 0 assignment for kzalloc'ed structure soc: fsl: qe: fix sparse warnings for ucc_fast.c soc: fsl: qe: fix sparse warnings for qe_ic.c soc: fsl: qe: fix sparse warnings for ucc.c soc: fsl: qe: fix sparse warning for qe_common.c soc: fsl: qe: fix sparse warnings for qe.c soc: qcom: Fix QCOM_APR dependencies soc: qcom: pdr: Avoid uninitialized use of found in pdr_indication_cb soc: imx: drop COMPILE_TEST for IMX_SCU_SOC firmware: imx: add COMPILE_TEST for IMX_SCU driver soc: imx: gpc: fix power up sequencing soc: imx: increase build coverage for imx8m soc driver soc: qcom: apr: Add avs/audio tracking functionality dt-bindings: soc: qcom: apr: Add protection domain bindings soc: qcom: Introduce Protection Domain Restart helpers devicetree: bindings: firmware: add ipq806x to qcom_scm memory: tegra: Correct debugfs clk rate-range on Tegra124 memory: tegra: Correct debugfs clk rate-range on Tegra30 memory: tegra: Correct debugfs clk rate-range on Tegra20 ...

Linus Torvalds committed 6 years ago

Commit d18292d2 parents 0e8fb69 cedb41468 files · +3692 −633Browse files

Unified · Split

68 files
  1. Documentation/devicetree/bindings/bus/ti-sysc.txt +1 −0
  2. Documentation/devicetree/bindings/firmware/qcom,scm.txt +1 −0
  3. Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml +40 −0
  4. Documentation/devicetree/bindings/soc/qcom/qcom,apr.txt +50 −0
  5. arch/arm/mach-omap2/pdata-quirks.c +6 −0
  6. drivers/bus/hisi_lpc.c +25 −2
  7. drivers/bus/ti-sysc.c +515 −89
  8. drivers/firmware/arm_scmi/Makefile +2 −1
  9. drivers/firmware/arm_scmi/common.h +113 −2
  10. drivers/firmware/arm_scmi/driver.c +34 −259
  11. drivers/firmware/arm_scmi/mailbox.c +184 −0
  12. drivers/firmware/arm_scmi/perf.c +1 −1
  13. drivers/firmware/arm_scmi/shmem.c +83 −0
  14. drivers/firmware/arm_scpi.c +2 −2
  15. drivers/firmware/imx/scu-pd.c +12 −1
  16. drivers/firmware/meson/meson_sm.c +2 −0
  17. drivers/firmware/tegra/Kconfig +1 −1
  18. drivers/gpu/drm/omapdrm/dss/dss.c +22 −3
  19. drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c +17 −8
  20. drivers/memory/tegra/tegra124-emc.c +5 −0
  21. drivers/memory/tegra/tegra20-emc.c +5 −0
  22. drivers/memory/tegra/tegra30-emc.c +5 −0
  23. drivers/soc/Makefile +1 −1
  24. drivers/soc/amlogic/Kconfig +13 −0
  25. drivers/soc/amlogic/Makefile +1 −0
  26. drivers/soc/amlogic/meson-secure-pwrc.c +204 −0
  27. drivers/soc/fsl/dpio/dpio-service.c +66 −3
  28. drivers/soc/fsl/dpio/qbman-portal.c +686 −81
  29. drivers/soc/fsl/dpio/qbman-portal.h +151 −7
  30. drivers/soc/fsl/qe/qe.c +2 −2
  31. drivers/soc/fsl/qe/qe_common.c +1 −1
  32. drivers/soc/fsl/qe/qe_ic.c +1 −1
  33. drivers/soc/fsl/qe/ucc.c +1 −1
  34. drivers/soc/fsl/qe/ucc_slow.c +13 −20
  35. drivers/soc/imx/Kconfig +10 −1
  36. drivers/soc/imx/Makefile +1 −1
  37. drivers/soc/imx/gpc.c +13 −11
  38. drivers/soc/imx/gpcv2.c +1 −0
  39. drivers/soc/imx/soc-imx8m.c +0 −0
  40. drivers/soc/qcom/Kconfig +6 −1
  41. drivers/soc/qcom/Makefile +1 −0
  42. drivers/soc/qcom/apr.c +114 −9
  43. drivers/soc/qcom/pdr_interface.c +757 −0
  44. drivers/soc/qcom/pdr_internal.h +379 −0
  45. drivers/soc/qcom/qcom_aoss.c +5 −1
  46. drivers/soc/qcom/rpmh-internal.h +1 −0
  47. drivers/soc/qcom/rpmh-rsc.c +1 −1
  48. drivers/soc/qcom/rpmh.c +10 −12
  49. drivers/soc/qcom/socinfo.c +1 −1
  50. drivers/soc/renesas/Kconfig +8 −8
  51. drivers/soc/renesas/rcar-sysc.h +2 −2
  52. drivers/soc/renesas/renesas-soc.c +1 −1
  53. drivers/tee/tee_core.c +0 −1
  54. drivers/tee/tee_private.h +2 −1
  55. drivers/tee/tee_shm.c +24 −61
  56. include/dt-bindings/bus/ti-sysc.h +4 −0
  57. include/dt-bindings/power/meson-a1-power.h +32 −0
  58. include/linux/firmware/imx/ipc.h +0 −1
  59. include/linux/firmware/meson/meson_sm.h +2 −0
  60. include/linux/platform_data/ti-sysc.h +5 −0
  61. include/linux/soc/qcom/apr.h +1 −0
  62. include/linux/soc/qcom/pdr.h +29 −0
  63. include/linux/soc/qcom/qmi.h +1 −0
  64. include/linux/tee_drv.h +1 −18
  65. include/soc/fsl/dpaa2-io.h +5 −1
  66. include/soc/fsl/qe/ucc_fast.h +3 −3
  67. include/soc/fsl/qe/ucc_slow.h +6 −7
  68. include/soc/qcom/rpmh.h +0 −5
Documentation/devicetree/bindings/bus/ti-sysc.txt+1−0
@@ -38,6 +38,7 @@ Required standard properties: · 37 unmodified lines
38 "ti,sysc-dra7-mcasp"38 "ti,sysc-dra7-mcasp"
39 "ti,sysc-usb-host-fs"39 "ti,sysc-usb-host-fs"
40 "ti,sysc-dra7-mcan"40 "ti,sysc-dra7-mcan"
41 "ti,sysc-pruss"
41 42
42- reg shall have register areas implemented for the interconnect43- reg shall have register areas implemented for the interconnect
43 target module in question such as revision, sysc and syss44 target module in question such as revision, sysc and syss
Documentation/devicetree/bindings/firmware/qcom,scm.txt+1−0
@@ -10,6 +10,7 @@ Required properties: · 9 unmodified lines
10 * "qcom,scm-apq8064"10 * "qcom,scm-apq8064"
11 * "qcom,scm-apq8084"11 * "qcom,scm-apq8084"
12 * "qcom,scm-ipq4019"12 * "qcom,scm-ipq4019"
13 * "qcom,scm-ipq806x"
13 * "qcom,scm-msm8660"14 * "qcom,scm-msm8660"
14 * "qcom,scm-msm8916"15 * "qcom,scm-msm8916"
15 * "qcom,scm-msm8960"16 * "qcom,scm-msm8960"
Documentation/devicetree/bindings/power/amlogic,meson-sec-pwrc.yaml+40−0
@@ -0,0 +1,40 @@
1# SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2# Copyright (c) 2019 Amlogic, Inc
3# Author: Jianxin Pan <jianxin.pan@amlogic.com>
4%YAML 1.2
5---
6$id: "http://devicetree.org/schemas/power/amlogic,meson-sec-pwrc.yaml#"
7$schema: "http://devicetree.org/meta-schemas/core.yaml#"
8
9title: Amlogic Meson Secure Power Domains
10
11maintainers:
12 - Jianxin Pan <jianxin.pan@amlogic.com>
13
14description: |+
15 Secure Power Domains used in Meson A1/C1 SoCs, and should be the child node
16 of secure-monitor.
17
18properties:
19 compatible:
20 enum:
21 - amlogic,meson-a1-pwrc
22
23 "#power-domain-cells":
24 const: 1
25
26required:
27 - compatible
28 - "#power-domain-cells"
29
30examples:
31 - |
32 secure-monitor {
33 compatible = "amlogic,meson-gxbb-sm";
34
35 pwrc: power-controller {
36 compatible = "amlogic,meson-a1-pwrc";
37 #power-domain-cells = <1>;
38 };
39 };
40
Documentation/devicetree/bindings/soc/qcom/qcom,apr.txt+50−0
@@ -45,6 +45,18 @@ by the individual bindings for the specific service · 44 unmodified lines
45 12 - Ultrasound stream manager.45 12 - Ultrasound stream manager.
46 13 - Listen stream manager.46 13 - Listen stream manager.
47 47
48- qcom,protection-domain
49 Usage: optional
50 Value type: <stringlist>
51 Definition: Must list the protection domain service name and path
52 that the particular apr service has a dependency on.
53 Possible values are :
54 "avs/audio", "msm/adsp/audio_pd".
55 "kernel/elf_loader", "msm/modem/wlan_pd".
56 "tms/servreg", "msm/adsp/audio_pd".
57 "tms/servreg", "msm/modem/wlan_pd".
58 "tms/servreg", "msm/slpi/sensor_pd".
59
48= EXAMPLE60= EXAMPLE
49The following example represents a QDSP based sound card on a MSM8996 device61The following example represents a QDSP based sound card on a MSM8996 device
50which uses apr as communication between Apps and QDSP.62which uses apr as communication between Apps and QDSP.
@@ -82,3 +94,41 @@ which uses apr as communication between Apps and QDSP. · 31 unmodified lines
82 ...94 ...
83 };95 };
84 };96 };
97
98= EXAMPLE 2
99The following example represents a QDSP based sound card with protection domain
100dependencies specified. Here some of the apr services are dependent on services
101running on protection domain hosted on ADSP/SLPI remote processors while others
102have no such dependency.
103
104 apr {
105 compatible = "qcom,apr-v2";
106 qcom,glink-channels = "apr_audio_svc";
107 qcom,apr-domain = <APR_DOMAIN_ADSP>;
108
109 q6core {
110 compatible = "qcom,q6core";
111 reg = <APR_SVC_ADSP_CORE>;
112 };
113
114 q6afe: q6afe {
115 compatible = "qcom,q6afe";
116 reg = <APR_SVC_AFE>;
117 qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
118 ...
119 };
120
121 q6asm: q6asm {
122 compatible = "qcom,q6asm";
123 reg = <APR_SVC_ASM>;
124 qcom,protection-domain = "tms/servreg", "msm/slpi/sensor_pd";
125 ...
126 };
127
128 q6adm: q6adm {
129 compatible = "qcom,q6adm";
130 reg = <APR_SVC_ADM>;
131 qcom,protection-domain = "avs/audio", "msm/adsp/audio_pd";
132 ...
133 };
134 };
arch/arm/mach-omap2/pdata-quirks.c+6−0
@@ -397,10 +397,16 @@ static int ti_sysc_shutdown_module(struct device *dev, · 396 unmodified lines
397 return omap_hwmod_shutdown(cookie->data);397 return omap_hwmod_shutdown(cookie->data);
398}398}
399 399
400static bool ti_sysc_soc_type_gp(void)
401{
402 return omap_type() == OMAP2_DEVICE_TYPE_GP;
403}
404
400static struct of_dev_auxdata omap_auxdata_lookup[];405static struct of_dev_auxdata omap_auxdata_lookup[];
401 406
402static struct ti_sysc_platform_data ti_sysc_pdata = {407static struct ti_sysc_platform_data ti_sysc_pdata = {
403 .auxdata = omap_auxdata_lookup,408 .auxdata = omap_auxdata_lookup,
409 .soc_type_gp = ti_sysc_soc_type_gp,
404 .init_clockdomain = ti_sysc_clkdm_init,410 .init_clockdomain = ti_sysc_clkdm_init,
405 .clkdm_deny_idle = ti_sysc_clkdm_deny_idle,411 .clkdm_deny_idle = ti_sysc_clkdm_deny_idle,
406 .clkdm_allow_idle = ti_sysc_clkdm_allow_idle,412 .clkdm_allow_idle = ti_sysc_clkdm_allow_idle,
drivers/bus/hisi_lpc.c+25−2
@@ -357,6 +357,26 @@ static int hisi_lpc_acpi_xlat_io_res(struct acpi_device *adev, · 356 unmodified lines
357 return 0;357 return 0;
358}358}
359 359
360/*
361 * Released firmware describes the IO port max address as 0x3fff, which is
362 * the max host bus address. Fixup to a proper range. This will probably
363 * never be fixed in firmware.
364 */
365static void hisi_lpc_acpi_fixup_child_resource(struct device *hostdev,
366 struct resource *r)
367{
368 if (r->end != 0x3fff)
369 return;
370
371 if (r->start == 0xe4)
372 r->end = 0xe4 + 0x04 - 1;
373 else if (r->start == 0x2f8)
374 r->end = 0x2f8 + 0x08 - 1;
375 else
376 dev_warn(hostdev, "unrecognised resource %pR to fixup, ignoring\n",
377 r);
378}
379
360/*380/*
361 * hisi_lpc_acpi_set_io_res - set the resources for a child381 * hisi_lpc_acpi_set_io_res - set the resources for a child
362 * @child: the device node to be updated the I/O resource382 * @child: the device node to be updated the I/O resource
@@ -418,8 +438,11 @@ static int hisi_lpc_acpi_set_io_res(struct device *child, · 55 unmodified lines
418 return -ENOMEM;438 return -ENOMEM;
419 }439 }
420 count = 0;440 count = 0;
421 list_for_each_entry(rentry, &resource_list, node)441 list_for_each_entry(rentry, &resource_list, node) {
422 resources[count++] = *rentry->res;442 resources[count] = *rentry->res;
443 hisi_lpc_acpi_fixup_child_resource(hostdev, &resources[count]);
444 count++;
445 }
423 446
424 acpi_dev_free_resource_list(&resource_list);447 acpi_dev_free_resource_list(&resource_list);
425 448
drivers/bus/ti-sysc.c+515−89
@@ -7,6 +7,7 @@ · 6 unmodified lines
7#include <linux/clk.h>7#include <linux/clk.h>
8#include <linux/clkdev.h>8#include <linux/clkdev.h>
9#include <linux/delay.h>9#include <linux/delay.h>
10#include <linux/list.h>
10#include <linux/module.h>11#include <linux/module.h>
11#include <linux/platform_device.h>12#include <linux/platform_device.h>
12#include <linux/pm_domain.h>13#include <linux/pm_domain.h>
@@ -15,15 +16,47 @@ · 2 unmodified lines
15#include <linux/of_address.h>16#include <linux/of_address.h>
16#include <linux/of_platform.h>17#include <linux/of_platform.h>
17#include <linux/slab.h>18#include <linux/slab.h>
19#include <linux/sys_soc.h>
18#include <linux/iopoll.h>20#include <linux/iopoll.h>
19 21
20#include <linux/platform_data/ti-sysc.h>22#include <linux/platform_data/ti-sysc.h>
21 23
22#include <dt-bindings/bus/ti-sysc.h>24#include <dt-bindings/bus/ti-sysc.h>
23 25
26#define DIS_ISP BIT(2)
27#define DIS_IVA BIT(1)
28#define DIS_SGX BIT(0)
29
30#define SOC_FLAG(match, flag) { .machine = match, .data = (void *)(flag), }
31
24#define MAX_MODULE_SOFTRESET_WAIT 1000032#define MAX_MODULE_SOFTRESET_WAIT 10000
25 33
26static const char * const reg_names[] = { "rev", "sysc", "syss", };34enum sysc_soc {
35 SOC_UNKNOWN,
36 SOC_2420,
37 SOC_2430,
38 SOC_3430,
39 SOC_3630,
40 SOC_4430,
41 SOC_4460,
42 SOC_4470,
43 SOC_5430,
44 SOC_AM3,
45 SOC_AM4,
46 SOC_DRA7,
47};
48
49struct sysc_address {
50 unsigned long base;
51 struct list_head node;
52};
53
54struct sysc_soc_info {
55 unsigned long general_purpose:1;
56 enum sysc_soc soc;
57 struct mutex list_lock; /* disabled modules list lock */
58 struct list_head disabled_modules;
59};
27 60
28enum sysc_clocks {61enum sysc_clocks {
29 SYSC_FCK,62 SYSC_FCK,
@@ -39,6 +72,8 @@ enum sysc_clocks { · 9 unmodified lines
39 SYSC_MAX_CLOCKS,72 SYSC_MAX_CLOCKS,
40};73};
41 74
75static struct sysc_soc_info *sysc_soc;
76static const char * const reg_names[] = { "rev", "sysc", "syss", };
42static const char * const clock_names[SYSC_MAX_CLOCKS] = {77static const char * const clock_names[SYSC_MAX_CLOCKS] = {
43 "fck", "ick", "opt0", "opt1", "opt2", "opt3", "opt4",78 "fck", "ick", "opt0", "opt1", "opt2", "opt3", "opt4",
44 "opt5", "opt6", "opt7",79 "opt5", "opt6", "opt7",
@@ -70,11 +105,13 @@ static const char * const clock_names[SYSC_MAX_CLOCKS] = { · 25 unmodified lines
70 * @child_needs_resume: runtime resume needed for child on resume from suspend105 * @child_needs_resume: runtime resume needed for child on resume from suspend
71 * @disable_on_idle: status flag used for disabling modules with resets106 * @disable_on_idle: status flag used for disabling modules with resets
72 * @idle_work: work structure used to perform delayed idle on a module107 * @idle_work: work structure used to perform delayed idle on a module
73 * @clk_enable_quirk: module specific clock enable quirk108 * @pre_reset_quirk: module specific pre-reset quirk
74 * @clk_disable_quirk: module specific clock disable quirk109 * @post_reset_quirk: module specific post-reset quirk
75 * @reset_done_quirk: module specific reset done quirk110 * @reset_done_quirk: module specific reset done quirk
76 * @module_enable_quirk: module specific enable quirk111 * @module_enable_quirk: module specific enable quirk
77 * @module_disable_quirk: module specific disable quirk112 * @module_disable_quirk: module specific disable quirk
113 * @module_unlock_quirk: module specific sysconfig unlock quirk
114 * @module_lock_quirk: module specific sysconfig lock quirk
78 */115 */
79struct sysc {116struct sysc {
80 struct device *dev;117 struct device *dev;
@@ -97,11 +134,13 @@ struct sysc { · 16 unmodified lines
97 unsigned int needs_resume:1;134 unsigned int needs_resume:1;
98 unsigned int child_needs_resume:1;135 unsigned int child_needs_resume:1;
99 struct delayed_work idle_work;136 struct delayed_work idle_work;
100 void (*clk_enable_quirk)(struct sysc *sysc);137 void (*pre_reset_quirk)(struct sysc *sysc);
101 void (*clk_disable_quirk)(struct sysc *sysc);138 void (*post_reset_quirk)(struct sysc *sysc);
102 void (*reset_done_quirk)(struct sysc *sysc);139 void (*reset_done_quirk)(struct sysc *sysc);
103 void (*module_enable_quirk)(struct sysc *sysc);140 void (*module_enable_quirk)(struct sysc *sysc);
104 void (*module_disable_quirk)(struct sysc *sysc);141 void (*module_disable_quirk)(struct sysc *sysc);
142 void (*module_unlock_quirk)(struct sysc *sysc);
143 void (*module_lock_quirk)(struct sysc *sysc);
105};144};
106 145
107static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np,146static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np,
@@ -624,7 +663,7 @@ static void sysc_check_one_child(struct sysc *ddata, · 516 unmodified lines
624 const char *name;663 const char *name;
625 664
626 name = of_get_property(np, "ti,hwmods", NULL);665 name = of_get_property(np, "ti,hwmods", NULL);
627 if (name)666 if (name && !of_device_is_compatible(np, "ti,sysc"))
628 dev_warn(ddata->dev, "really a child ti,hwmods property?");667 dev_warn(ddata->dev, "really a child ti,hwmods property?");
629 668
630 sysc_check_quirk_stdout(ddata, np);669 sysc_check_quirk_stdout(ddata, np);
@@ -861,6 +900,22 @@ static void sysc_show_registers(struct sysc *ddata) · 230 unmodified lines
861 buf);900 buf);
862}901}
863 902
903/**
904 * sysc_write_sysconfig - handle sysconfig quirks for register write
905 * @ddata: device driver data
906 * @value: register value
907 */
908static void sysc_write_sysconfig(struct sysc *ddata, u32 value)
909{
910 if (ddata->module_unlock_quirk)
911 ddata->module_unlock_quirk(ddata);
912
913 sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], value);
914
915 if (ddata->module_lock_quirk)
916 ddata->module_lock_quirk(ddata);
917}
918
864#define SYSC_IDLE_MASK (SYSC_NR_IDLEMODES - 1)919#define SYSC_IDLE_MASK (SYSC_NR_IDLEMODES - 1)
865#define SYSC_CLOCACT_ICK 2920#define SYSC_CLOCACT_ICK 2
866 921
@@ -907,7 +962,7 @@ static int sysc_enable_module(struct device *dev) · 40 unmodified lines
907 962
908 reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift);963 reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift);
909 reg |= best_mode << regbits->sidle_shift;964 reg |= best_mode << regbits->sidle_shift;
910 sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);965 sysc_write_sysconfig(ddata, reg);
911 966
912set_midle:967set_midle:
913 /* Set MIDLE mode */968 /* Set MIDLE mode */
@@ -926,14 +981,14 @@ set_midle: · 12 unmodified lines
926 981
927 reg &= ~(SYSC_IDLE_MASK << regbits->midle_shift);982 reg &= ~(SYSC_IDLE_MASK << regbits->midle_shift);
928 reg |= best_mode << regbits->midle_shift;983 reg |= best_mode << regbits->midle_shift;
929 sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);984 sysc_write_sysconfig(ddata, reg);
930 985
931set_autoidle:986set_autoidle:
932 /* Autoidle bit must enabled separately if available */987 /* Autoidle bit must enabled separately if available */
933 if (regbits->autoidle_shift >= 0 &&988 if (regbits->autoidle_shift >= 0 &&
934 ddata->cfg.sysc_val & BIT(regbits->autoidle_shift)) {989 ddata->cfg.sysc_val & BIT(regbits->autoidle_shift)) {
935 reg |= 1 << regbits->autoidle_shift;990 reg |= 1 << regbits->autoidle_shift;
936 sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);991 sysc_write_sysconfig(ddata, reg);
937 }992 }
938 993
939 if (ddata->module_enable_quirk)994 if (ddata->module_enable_quirk)
@@ -991,7 +1046,7 @@ static int sysc_disable_module(struct device *dev) · 51 unmodified lines
991 1046
992 reg &= ~(SYSC_IDLE_MASK << regbits->midle_shift);1047 reg &= ~(SYSC_IDLE_MASK << regbits->midle_shift);
993 reg |= best_mode << regbits->midle_shift;1048 reg |= best_mode << regbits->midle_shift;
994 sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);1049 sysc_write_sysconfig(ddata, reg);
995 1050
996set_sidle:1051set_sidle:
997 /* Set SIDLE mode */1052 /* Set SIDLE mode */
@@ -1014,7 +1069,7 @@ set_sidle: · 16 unmodified lines
1014 if (regbits->autoidle_shift >= 0 &&1069 if (regbits->autoidle_shift >= 0 &&
1015 ddata->cfg.sysc_val & BIT(regbits->autoidle_shift))1070 ddata->cfg.sysc_val & BIT(regbits->autoidle_shift))
1016 reg |= 1 << regbits->autoidle_shift;1071 reg |= 1 << regbits->autoidle_shift;
1017 sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);1072 sysc_write_sysconfig(ddata, reg);
1018 1073
1019 return 0;1074 return 0;
1020}1075}
@@ -1216,16 +1271,16 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { · 195 unmodified lines
1216 SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_OPT_CLKS_IN_RESET),1271 SYSC_QUIRK_LEGACY_IDLE | SYSC_QUIRK_OPT_CLKS_IN_RESET),
1217 SYSC_QUIRK("sham", 0, 0x100, 0x110, 0x114, 0x40000c03, 0xffffffff,1272 SYSC_QUIRK("sham", 0, 0x100, 0x110, 0x114, 0x40000c03, 0xffffffff,
1218 SYSC_QUIRK_LEGACY_IDLE),1273 SYSC_QUIRK_LEGACY_IDLE),
1219 SYSC_QUIRK("smartreflex", 0, -1, 0x24, -1, 0x00000000, 0xffffffff,1274 SYSC_QUIRK("smartreflex", 0, -ENODEV, 0x24, -ENODEV, 0x00000000, 0xffffffff,
1220 SYSC_QUIRK_LEGACY_IDLE),1275 SYSC_QUIRK_LEGACY_IDLE),
1221 SYSC_QUIRK("smartreflex", 0, -1, 0x38, -1, 0x00000000, 0xffffffff,1276 SYSC_QUIRK("smartreflex", 0, -ENODEV, 0x38, -ENODEV, 0x00000000, 0xffffffff,
1222 SYSC_QUIRK_LEGACY_IDLE),1277 SYSC_QUIRK_LEGACY_IDLE),
1223 SYSC_QUIRK("timer", 0, 0, 0x10, 0x14, 0x00000015, 0xffffffff,1278 SYSC_QUIRK("timer", 0, 0, 0x10, 0x14, 0x00000015, 0xffffffff,
1224 0),1279 0),
1225 /* Some timers on omap4 and later */1280 /* Some timers on omap4 and later */
1226 SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x50002100, 0xffffffff,1281 SYSC_QUIRK("timer", 0, 0, 0x10, -ENODEV, 0x50002100, 0xffffffff,
1227 0),1282 0),
1228 SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffff00ff,1283 SYSC_QUIRK("timer", 0, 0, 0x10, -ENODEV, 0x4fff1301, 0xffff00ff,
1229 0),1284 0),
1230 SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000046, 0xffffffff,1285 SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000046, 0xffffffff,
1231 SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),1286 SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE),
@@ -1238,19 +1293,27 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { · 6 unmodified lines
1238 SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),1293 SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE),
1239 1294
1240 /* Quirks that need to be set based on the module address */1295 /* Quirks that need to be set based on the module address */
1241 SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -1, 0x50000800, 0xffffffff,1296 SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -ENODEV, 0x50000800, 0xffffffff,
1242 SYSC_QUIRK_EXT_OPT_CLOCK | SYSC_QUIRK_NO_RESET_ON_INIT |1297 SYSC_QUIRK_EXT_OPT_CLOCK | SYSC_QUIRK_NO_RESET_ON_INIT |
1243 SYSC_QUIRK_SWSUP_SIDLE),1298 SYSC_QUIRK_SWSUP_SIDLE),
1244 1299
1245 /* Quirks that need to be set based on detected module */1300 /* Quirks that need to be set based on detected module */
1246 SYSC_QUIRK("aess", 0, 0, 0x10, -1, 0x40000000, 0xffffffff,1301 SYSC_QUIRK("aess", 0, 0, 0x10, -ENODEV, 0x40000000, 0xffffffff,
1247 SYSC_MODULE_QUIRK_AESS),1302 SYSC_MODULE_QUIRK_AESS),
1248 SYSC_QUIRK("dcan", 0x48480000, 0x20, -1, -1, 0xa3170504, 0xffffffff,1303 SYSC_QUIRK("dcan", 0x48480000, 0x20, -ENODEV, -ENODEV, 0xa3170504, 0xffffffff,
1249 SYSC_QUIRK_CLKDM_NOAUTO),1304 SYSC_QUIRK_CLKDM_NOAUTO),
1250 SYSC_QUIRK("dwc3", 0x48880000, 0, 0x10, -1, 0x500a0200, 0xffffffff,1305 SYSC_QUIRK("dss", 0x4832a000, 0, 0x10, 0x14, 0x00000020, 0xffffffff,
1306 SYSC_QUIRK_OPT_CLKS_IN_RESET | SYSC_MODULE_QUIRK_DSS_RESET),
1307 SYSC_QUIRK("dss", 0x58000000, 0, -ENODEV, 0x14, 0x00000040, 0xffffffff,
1308 SYSC_QUIRK_OPT_CLKS_IN_RESET | SYSC_MODULE_QUIRK_DSS_RESET),
1309 SYSC_QUIRK("dss", 0x58000000, 0, -ENODEV, 0x14, 0x00000061, 0xffffffff,
1310 SYSC_QUIRK_OPT_CLKS_IN_RESET | SYSC_MODULE_QUIRK_DSS_RESET),
1311 SYSC_QUIRK("dwc3", 0x48880000, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff,
1251 SYSC_QUIRK_CLKDM_NOAUTO),1312 SYSC_QUIRK_CLKDM_NOAUTO),
1252 SYSC_QUIRK("dwc3", 0x488c0000, 0, 0x10, -1, 0x500a0200, 0xffffffff,1313 SYSC_QUIRK("dwc3", 0x488c0000, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff,
1253 SYSC_QUIRK_CLKDM_NOAUTO),1314 SYSC_QUIRK_CLKDM_NOAUTO),
1315 SYSC_QUIRK("hdmi", 0, 0, 0x10, -ENODEV, 0x50030200, 0xffffffff,
1316 SYSC_QUIRK_OPT_CLKS_NEEDED),
1254 SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff,1317 SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff,
1255 SYSC_MODULE_QUIRK_HDQ1W),1318 SYSC_MODULE_QUIRK_HDQ1W),
1256 SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff,1319 SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff,
@@ -1263,72 +1326,92 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { · 6 unmodified lines
1263 SYSC_MODULE_QUIRK_I2C),1326 SYSC_MODULE_QUIRK_I2C),
1264 SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0,1327 SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0,
1265 SYSC_MODULE_QUIRK_I2C),1328 SYSC_MODULE_QUIRK_I2C),
1266 SYSC_QUIRK("gpu", 0x50000000, 0x14, -1, -1, 0x00010201, 0xffffffff, 0),1329 SYSC_QUIRK("gpu", 0x50000000, 0x14, -ENODEV, -ENODEV, 0x00010201, 0xffffffff, 0),
1267 SYSC_QUIRK("gpu", 0x50000000, 0xfe00, 0xfe10, -1, 0x40000000 , 0xffffffff,1330 SYSC_QUIRK("gpu", 0x50000000, 0xfe00, 0xfe10, -ENODEV, 0x40000000 , 0xffffffff,
1268 SYSC_MODULE_QUIRK_SGX),1331 SYSC_MODULE_QUIRK_SGX),
1269 SYSC_QUIRK("lcdc", 0, 0, 0x54, -1, 0x4f201000, 0xffffffff,1332 SYSC_QUIRK("lcdc", 0, 0, 0x54, -ENODEV, 0x4f201000, 0xffffffff,
1333 SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
1334 SYSC_QUIRK("rtc", 0, 0x74, 0x78, -ENODEV, 0x4eb01908, 0xffff00f0,
1335 SYSC_MODULE_QUIRK_RTC_UNLOCK),
1336 SYSC_QUIRK("tptc", 0, 0, 0x10, -ENODEV, 0x40006c00, 0xffffefff,
1337 SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
1338 SYSC_QUIRK("tptc", 0, 0, -ENODEV, -ENODEV, 0x40007c00, 0xffffffff,
1270 SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),1339 SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
1271 SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050,1340 SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050,
1272 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),1341 0xffffffff, SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
1273 SYSC_QUIRK("usb_otg_hs", 0, 0, 0x10, -1, 0x4ea2080d, 0xffffffff,1342 SYSC_QUIRK("usb_otg_hs", 0, 0, 0x10, -ENODEV, 0x4ea2080d, 0xffffffff,
1274 SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),1343 SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_SWSUP_MSTANDBY),
1275 SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0,1344 SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0,
1276 SYSC_MODULE_QUIRK_WDT),1345 SYSC_MODULE_QUIRK_WDT),
1346 /* PRUSS on am3, am4 and am5 */
1347 SYSC_QUIRK("pruss", 0, 0x26000, 0x26004, -ENODEV, 0x47000000, 0xff000000,
1348 SYSC_MODULE_QUIRK_PRUSS),
1277 /* Watchdog on am3 and am4 */1349 /* Watchdog on am3 and am4 */
1278 SYSC_QUIRK("wdt", 0x44e35000, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0,1350 SYSC_QUIRK("wdt", 0x44e35000, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0,
1279 SYSC_MODULE_QUIRK_WDT | SYSC_QUIRK_SWSUP_SIDLE),1351 SYSC_MODULE_QUIRK_WDT | SYSC_QUIRK_SWSUP_SIDLE),
1280 1352
1281#ifdef DEBUG1353#ifdef DEBUG
1282 SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0),1354 SYSC_QUIRK("adc", 0, 0, 0x10, -ENODEV, 0x47300001, 0xffffffff, 0),
1283 SYSC_QUIRK("atl", 0, 0, -1, -1, 0x0a070100, 0xffffffff, 0),1355 SYSC_QUIRK("atl", 0, 0, -ENODEV, -ENODEV, 0x0a070100, 0xffffffff, 0),
1284 SYSC_QUIRK("cm", 0, 0, -1, -1, 0x40000301, 0xffffffff, 0),1356 SYSC_QUIRK("cm", 0, 0, -ENODEV, -ENODEV, 0x40000301, 0xffffffff, 0),
1285 SYSC_QUIRK("control", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0),1357 SYSC_QUIRK("control", 0, 0, 0x10, -ENODEV, 0x40000900, 0xffffffff, 0),
1286 SYSC_QUIRK("cpgmac", 0, 0x1200, 0x1208, 0x1204, 0x4edb1902,1358 SYSC_QUIRK("cpgmac", 0, 0x1200, 0x1208, 0x1204, 0x4edb1902,
1287 0xffff00f0, 0),1359 0xffff00f0, 0),
1288 SYSC_QUIRK("dcan", 0, 0x20, -1, -1, 0xa3170504, 0xffffffff, 0),1360 SYSC_QUIRK("dcan", 0, 0x20, -ENODEV, -ENODEV, 0xa3170504, 0xffffffff, 0),
1289 SYSC_QUIRK("dcan", 0, 0x20, -1, -1, 0x4edb1902, 0xffffffff, 0),1361 SYSC_QUIRK("dcan", 0, 0x20, -ENODEV, -ENODEV, 0x4edb1902, 0xffffffff, 0),
1290 SYSC_QUIRK("dmic", 0, 0, 0x10, -1, 0x50010000, 0xffffffff, 0),1362 SYSC_QUIRK("dispc", 0x4832a400, 0, 0x10, 0x14, 0x00000030, 0xffffffff, 0),
1291 SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0),1363 SYSC_QUIRK("dispc", 0x58001000, 0, 0x10, 0x14, 0x00000040, 0xffffffff, 0),
1364 SYSC_QUIRK("dispc", 0x58001000, 0, 0x10, 0x14, 0x00000051, 0xffffffff, 0),
1365 SYSC_QUIRK("dmic", 0, 0, 0x10, -ENODEV, 0x50010000, 0xffffffff, 0),
1366 SYSC_QUIRK("dsi", 0x58004000, 0, 0x10, 0x14, 0x00000030, 0xffffffff, 0),
1367 SYSC_QUIRK("dsi", 0x58005000, 0, 0x10, 0x14, 0x00000030, 0xffffffff, 0),
1368 SYSC_QUIRK("dsi", 0x58005000, 0, 0x10, 0x14, 0x00000040, 0xffffffff, 0),
1369 SYSC_QUIRK("dsi", 0x58009000, 0, 0x10, 0x14, 0x00000040, 0xffffffff, 0),
1370 SYSC_QUIRK("dwc3", 0, 0, 0x10, -ENODEV, 0x500a0200, 0xffffffff, 0),
1292 SYSC_QUIRK("d2d", 0x4a0b6000, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0),1371 SYSC_QUIRK("d2d", 0x4a0b6000, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0),
1293 SYSC_QUIRK("d2d", 0x4a0cd000, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0),1372 SYSC_QUIRK("d2d", 0x4a0cd000, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0),
1294 SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0),1373 SYSC_QUIRK("epwmss", 0, 0, 0x4, -ENODEV, 0x47400001, 0xffffffff, 0),
1295 SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -1, 0, 0, 0),1374 SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -ENODEV, 0, 0, 0),
1296 SYSC_QUIRK("gpu", 0, 0xfe00, 0xfe10, -1, 0x40000000 , 0xffffffff, 0),1375 SYSC_QUIRK("gpu", 0, 0xfe00, 0xfe10, -ENODEV, 0x40000000 , 0xffffffff, 0),
1376 SYSC_QUIRK("hdmi", 0, 0, 0x10, -ENODEV, 0x50031d00, 0xffffffff, 0),
1297 SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0),1377 SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0),
1298 SYSC_QUIRK("iss", 0, 0, 0x10, -1, 0x40000101, 0xffffffff, 0),1378 SYSC_QUIRK("iss", 0, 0, 0x10, -ENODEV, 0x40000101, 0xffffffff, 0),
1299 SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44306302, 0xffffffff, 0),1379 SYSC_QUIRK("mcasp", 0, 0, 0x4, -ENODEV, 0x44306302, 0xffffffff, 0),
1300 SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44307b02, 0xffffffff, 0),1380 SYSC_QUIRK("mcasp", 0, 0, 0x4, -ENODEV, 0x44307b02, 0xffffffff, 0),
1301 SYSC_QUIRK("mcbsp", 0, -1, 0x8c, -1, 0, 0, 0),1381 SYSC_QUIRK("mcbsp", 0, -ENODEV, 0x8c, -ENODEV, 0, 0, 0),
1302 SYSC_QUIRK("mcspi", 0, 0, 0x10, -1, 0x40300a0b, 0xffff00ff, 0),1382 SYSC_QUIRK("mcspi", 0, 0, 0x10, -ENODEV, 0x40300a0b, 0xffff00ff, 0),
1303 SYSC_QUIRK("mcspi", 0, 0, 0x110, 0x114, 0x40300a0b, 0xffffffff, 0),1383 SYSC_QUIRK("mcspi", 0, 0, 0x110, 0x114, 0x40300a0b, 0xffffffff, 0),
1304 SYSC_QUIRK("mailbox", 0, 0, 0x10, -1, 0x00000400, 0xffffffff, 0),1384 SYSC_QUIRK("mailbox", 0, 0, 0x10, -ENODEV, 0x00000400, 0xffffffff, 0),
1305 SYSC_QUIRK("m3", 0, 0, -1, -1, 0x5f580105, 0x0fff0f00, 0),1385 SYSC_QUIRK("m3", 0, 0, -ENODEV, -ENODEV, 0x5f580105, 0x0fff0f00, 0),
1306 SYSC_QUIRK("ocp2scp", 0, 0, 0x10, 0x14, 0x50060005, 0xfffffff0, 0),1386 SYSC_QUIRK("ocp2scp", 0, 0, 0x10, 0x14, 0x50060005, 0xfffffff0, 0),
1307 SYSC_QUIRK("ocp2scp", 0, 0, -1, -1, 0x50060007, 0xffffffff, 0),1387 SYSC_QUIRK("ocp2scp", 0, 0, -ENODEV, -ENODEV, 0x50060007, 0xffffffff, 0),
1308 SYSC_QUIRK("padconf", 0, 0, 0x10, -1, 0x4fff0800, 0xffffffff, 0),1388 SYSC_QUIRK("padconf", 0, 0, 0x10, -ENODEV, 0x4fff0800, 0xffffffff, 0),
1309 SYSC_QUIRK("padconf", 0, 0, -1, -1, 0x40001100, 0xffffffff, 0),1389 SYSC_QUIRK("padconf", 0, 0, -ENODEV, -ENODEV, 0x40001100, 0xffffffff, 0),
1310 SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000100, 0xffffffff, 0),1390 SYSC_QUIRK("prcm", 0, 0, -ENODEV, -ENODEV, 0x40000100, 0xffffffff, 0),
1311 SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x00004102, 0xffffffff, 0),1391 SYSC_QUIRK("prcm", 0, 0, -ENODEV, -ENODEV, 0x00004102, 0xffffffff, 0),
1312 SYSC_QUIRK("prcm", 0, 0, -1, -1, 0x40000400, 0xffffffff, 0),1392 SYSC_QUIRK("prcm", 0, 0, -ENODEV, -ENODEV, 0x40000400, 0xffffffff, 0),
1313 SYSC_QUIRK("scm", 0, 0, 0x10, -1, 0x40000900, 0xffffffff, 0),1393 SYSC_QUIRK("rfbi", 0x4832a800, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0),
1314 SYSC_QUIRK("scm", 0, 0, -1, -1, 0x4e8b0100, 0xffffffff, 0),1394 SYSC_QUIRK("rfbi", 0x58002000, 0, 0x10, 0x14, 0x00000010, 0xffffffff, 0),
1315 SYSC_QUIRK("scm", 0, 0, -1, -1, 0x4f000100, 0xffffffff, 0),1395 SYSC_QUIRK("scm", 0, 0, 0x10, -ENODEV, 0x40000900, 0xffffffff, 0),
1316 SYSC_QUIRK("scm", 0, 0, -1, -1, 0x40000900, 0xffffffff, 0),1396 SYSC_QUIRK("scm", 0, 0, -ENODEV, -ENODEV, 0x4e8b0100, 0xffffffff, 0),
1317 SYSC_QUIRK("scrm", 0, 0, -1, -1, 0x00000010, 0xffffffff, 0),1397 SYSC_QUIRK("scm", 0, 0, -ENODEV, -ENODEV, 0x4f000100, 0xffffffff, 0),
1318 SYSC_QUIRK("sdio", 0, 0, 0x10, -1, 0x40202301, 0xffff0ff0, 0),1398 SYSC_QUIRK("scm", 0, 0, -ENODEV, -ENODEV, 0x40000900, 0xffffffff, 0),
1399 SYSC_QUIRK("scrm", 0, 0, -ENODEV, -ENODEV, 0x00000010, 0xffffffff, 0),
1400 SYSC_QUIRK("sdio", 0, 0, 0x10, -ENODEV, 0x40202301, 0xffff0ff0, 0),
1319 SYSC_QUIRK("sdio", 0, 0x2fc, 0x110, 0x114, 0x31010000, 0xffffffff, 0),1401 SYSC_QUIRK("sdio", 0, 0x2fc, 0x110, 0x114, 0x31010000, 0xffffffff, 0),
1320 SYSC_QUIRK("sdma", 0, 0, 0x2c, 0x28, 0x00010900, 0xffffffff, 0),1402 SYSC_QUIRK("sdma", 0, 0, 0x2c, 0x28, 0x00010900, 0xffffffff, 0),
1321 SYSC_QUIRK("slimbus", 0, 0, 0x10, -1, 0x40000902, 0xffffffff, 0),1403 SYSC_QUIRK("slimbus", 0, 0, 0x10, -ENODEV, 0x40000902, 0xffffffff, 0),
1322 SYSC_QUIRK("slimbus", 0, 0, 0x10, -1, 0x40002903, 0xffffffff, 0),1404 SYSC_QUIRK("slimbus", 0, 0, 0x10, -ENODEV, 0x40002903, 0xffffffff, 0),
1323 SYSC_QUIRK("spinlock", 0, 0, 0x10, -1, 0x50020000, 0xffffffff, 0),1405 SYSC_QUIRK("spinlock", 0, 0, 0x10, -ENODEV, 0x50020000, 0xffffffff, 0),
1324 SYSC_QUIRK("rng", 0, 0x1fe0, 0x1fe4, -1, 0x00000020, 0xffffffff, 0),1406 SYSC_QUIRK("rng", 0, 0x1fe0, 0x1fe4, -ENODEV, 0x00000020, 0xffffffff, 0),
1325 SYSC_QUIRK("rtc", 0, 0x74, 0x78, -1, 0x4eb01908, 0xffff00f0, 0),1407 SYSC_QUIRK("timer32k", 0, 0, 0x4, -ENODEV, 0x00000060, 0xffffffff, 0),
1326 SYSC_QUIRK("timer32k", 0, 0, 0x4, -1, 0x00000060, 0xffffffff, 0),1408 SYSC_QUIRK("tpcc", 0, 0, -ENODEV, -ENODEV, 0x40014c00, 0xffffffff, 0),
1327 SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000004, 0xffffffff, 0),1409 SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000004, 0xffffffff, 0),
1328 SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000008, 0xffffffff, 0),1410 SYSC_QUIRK("usbhstll", 0, 0, 0x10, 0x14, 0x00000008, 0xffffffff, 0),
1329 SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, 0x14, 0x50700100, 0xffffffff, 0),1411 SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, 0x14, 0x50700100, 0xffffffff, 0),
1330 SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, -1, 0x50700101, 0xffffffff, 0),1412 SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, -ENODEV, 0x50700101, 0xffffffff, 0),
1331 SYSC_QUIRK("vfpe", 0, 0, 0x104, -1, 0x4d001200, 0xffffffff, 0),1413 SYSC_QUIRK("venc", 0x58003000, 0, -ENODEV, -ENODEV, 0x00000002, 0xffffffff, 0),
1414 SYSC_QUIRK("vfpe", 0, 0, 0x104, -ENODEV, 0x4d001200, 0xffffffff, 0),
1332#endif1415#endif
1333};1416};
1334 1417
@@ -1350,16 +1433,13 @@ static void sysc_init_early_quirks(struct sysc *ddata) · 15 unmodified lines
1350 if (q->base != ddata->module_pa)1433 if (q->base != ddata->module_pa)
1351 continue;1434 continue;
1352 1435
1353 if (q->rev_offset >= 0 &&1436 if (q->rev_offset != ddata->offsets[SYSC_REVISION])
1354 q->rev_offset != ddata->offsets[SYSC_REVISION])
1355 continue;1437 continue;
1356 1438
1357 if (q->sysc_offset >= 0 &&1439 if (q->sysc_offset != ddata->offsets[SYSC_SYSCONFIG])
1358 q->sysc_offset != ddata->offsets[SYSC_SYSCONFIG])
1359 continue;1440 continue;
1360 1441
1361 if (q->syss_offset >= 0 &&1442 if (q->syss_offset != ddata->offsets[SYSC_SYSSTATUS])
1362 q->syss_offset != ddata->offsets[SYSC_SYSSTATUS])
1363 continue;1443 continue;
1364 1444
1365 ddata->name = q->name;1445 ddata->name = q->name;
@@ -1379,16 +1459,13 @@ static void sysc_init_revision_quirks(struct sysc *ddata) · 13 unmodified lines
1379 if (q->base && q->base != ddata->module_pa)1459 if (q->base && q->base != ddata->module_pa)
1380 continue;1460 continue;
1381 1461
1382 if (q->rev_offset >= 0 &&1462 if (q->rev_offset != ddata->offsets[SYSC_REVISION])
1383 q->rev_offset != ddata->offsets[SYSC_REVISION])
1384 continue;1463 continue;
1385 1464
1386 if (q->sysc_offset >= 0 &&1465 if (q->sysc_offset != ddata->offsets[SYSC_SYSCONFIG])
1387 q->sysc_offset != ddata->offsets[SYSC_SYSCONFIG])
1388 continue;1466 continue;
1389 1467
1390 if (q->syss_offset >= 0 &&1468 if (q->syss_offset != ddata->offsets[SYSC_SYSSTATUS])
1391 q->syss_offset != ddata->offsets[SYSC_SYSSTATUS])
1392 continue;1469 continue;
1393 1470
1394 if (q->revision == ddata->revision ||1471 if (q->revision == ddata->revision ||
@@ -1400,6 +1477,128 @@ static void sysc_init_revision_quirks(struct sysc *ddata) · 5 unmodified lines
1400 }1477 }
1401}1478}
1402 1479
1480/*
1481 * DSS needs dispc outputs disabled to reset modules. Returns mask of
1482 * enabled DSS interrupts. Eventually we may be able to do this on
1483 * dispc init rather than top-level DSS init.
1484 */
1485static u32 sysc_quirk_dispc(struct sysc *ddata, int dispc_offset,
1486 bool disable)
1487{
1488 bool lcd_en, digit_en, lcd2_en = false, lcd3_en = false;
1489 const int lcd_en_mask = BIT(0), digit_en_mask = BIT(1);
1490 int manager_count;
1491 bool framedonetv_irq;
1492 u32 val, irq_mask = 0;
1493
1494 switch (sysc_soc->soc) {
1495 case SOC_2420 ... SOC_3630:
1496 manager_count = 2;
1497 framedonetv_irq = false;
1498 break;
1499 case SOC_4430 ... SOC_4470:
1500 manager_count = 3;
1501 break;
1502 case SOC_5430:
1503 case SOC_DRA7:
1504 manager_count = 4;
1505 break;
1506 case SOC_AM4:
1507 manager_count = 1;
1508 break;
1509 case SOC_UNKNOWN:
1510 default:
1511 return 0;
1512 };
1513
1514 /* Remap the whole module range to be able to reset dispc outputs */
1515 devm_iounmap(ddata->dev, ddata->module_va);
1516 ddata->module_va = devm_ioremap(ddata->dev,
1517 ddata->module_pa,
1518 ddata->module_size);
1519 if (!ddata->module_va)
1520 return -EIO;
1521
1522 /* DISP_CONTROL */
1523 val = sysc_read(ddata, dispc_offset + 0x40);
1524 lcd_en = val & lcd_en_mask;
1525 digit_en = val & digit_en_mask;
1526 if (lcd_en)
1527 irq_mask |= BIT(0); /* FRAMEDONE */
1528 if (digit_en) {
1529 if (framedonetv_irq)
1530 irq_mask |= BIT(24); /* FRAMEDONETV */
1531 else
1532 irq_mask |= BIT(2) | BIT(3); /* EVSYNC bits */
1533 }
1534 if (disable & (lcd_en | digit_en))
1535 sysc_write(ddata, dispc_offset + 0x40,
1536 val & ~(lcd_en_mask | digit_en_mask));
1537
1538 if (manager_count <= 2)
1539 return irq_mask;
1540
1541 /* DISPC_CONTROL2 */
1542 val = sysc_read(ddata, dispc_offset + 0x238);
1543 lcd2_en = val & lcd_en_mask;
1544 if (lcd2_en)
1545 irq_mask |= BIT(22); /* FRAMEDONE2 */
1546 if (disable && lcd2_en)
1547 sysc_write(ddata, dispc_offset + 0x238,
1548 val & ~lcd_en_mask);
1549
1550 if (manager_count <= 3)
1551 return irq_mask;
1552
1553 /* DISPC_CONTROL3 */
1554 val = sysc_read(ddata, dispc_offset + 0x848);
1555 lcd3_en = val & lcd_en_mask;
1556 if (lcd3_en)
1557 irq_mask |= BIT(30); /* FRAMEDONE3 */
1558 if (disable && lcd3_en)
1559 sysc_write(ddata, dispc_offset + 0x848,
1560 val & ~lcd_en_mask);
1561
1562 return irq_mask;
1563}
1564
1565/* DSS needs child outputs disabled and SDI registers cleared for reset */
1566static void sysc_pre_reset_quirk_dss(struct sysc *ddata)
1567{
1568 const int dispc_offset = 0x1000;
1569 int error;
1570 u32 irq_mask, val;
1571
1572 /* Get enabled outputs */
1573 irq_mask = sysc_quirk_dispc(ddata, dispc_offset, false);
1574 if (!irq_mask)
1575 return;
1576
1577 /* Clear IRQSTATUS */
1578 sysc_write(ddata, dispc_offset + 0x18, irq_mask);
1579
1580 /* Disable outputs */
1581 val = sysc_quirk_dispc(ddata, dispc_offset, true);
1582
1583 /* Poll IRQSTATUS */
1584 error = readl_poll_timeout(ddata->module_va + dispc_offset + 0x18,
1585 val, val != irq_mask, 100, 50);
1586 if (error)
1587 dev_warn(ddata->dev, "%s: timed out %08x !+ %08x\n",
1588 __func__, val, irq_mask);
1589
1590 if (sysc_soc->soc == SOC_3430) {
1591 /* Clear DSS_SDI_CONTROL */
1592 sysc_write(ddata, 0x44, 0);
1593
1594 /* Clear DSS_PLL_CONTROL */
1595 sysc_write(ddata, 0x48, 0);
1596 }
1597
1598 /* Clear DSS_CONTROL to switch DSS clock sources to PRCM if not */
1599 sysc_write(ddata, 0x40, 0);
1600}
1601
1403/* 1-wire needs module's internal clocks enabled for reset */1602/* 1-wire needs module's internal clocks enabled for reset */
1404static void sysc_pre_reset_quirk_hdq1w(struct sysc *ddata)1603static void sysc_pre_reset_quirk_hdq1w(struct sysc *ddata)
1405{1604{
@@ -1419,7 +1618,7 @@ static void sysc_module_enable_quirk_aess(struct sysc *ddata) · 13 unmodified lines
1419 sysc_write(ddata, offset, 1);1618 sysc_write(ddata, offset, 1);
1420}1619}
1421 1620
1422/* I2C needs extra enable bit toggling for reset */1621/* I2C needs to be disabled for reset */
1423static void sysc_clk_quirk_i2c(struct sysc *ddata, bool enable)1622static void sysc_clk_quirk_i2c(struct sysc *ddata, bool enable)
1424{1623{
1425 int offset;1624 int offset;
@@ -1440,14 +1639,48 @@ static void sysc_clk_quirk_i2c(struct sysc *ddata, bool enable) · 14 unmodified lines
1440 sysc_write(ddata, offset, val);1639 sysc_write(ddata, offset, val);
1441}1640}
1442 1641
1443static void sysc_clk_enable_quirk_i2c(struct sysc *ddata)1642static void sysc_pre_reset_quirk_i2c(struct sysc *ddata)
1643{
1644 sysc_clk_quirk_i2c(ddata, false);
1645}
1646
1647static void sysc_post_reset_quirk_i2c(struct sysc *ddata)
1444{1648{
1445 sysc_clk_quirk_i2c(ddata, true);1649 sysc_clk_quirk_i2c(ddata, true);
1446}1650}
1447 1651
1448static void sysc_clk_disable_quirk_i2c(struct sysc *ddata)1652/* RTC on am3 and 4 needs to be unlocked and locked for sysconfig */
1653static void sysc_quirk_rtc(struct sysc *ddata, bool lock)
1449{1654{
1450 sysc_clk_quirk_i2c(ddata, false);1655 u32 val, kick0_val = 0, kick1_val = 0;
1656 unsigned long flags;
1657 int error;
1658
1659 if (!lock) {
1660 kick0_val = 0x83e70b13;
1661 kick1_val = 0x95a4f1e0;
1662 }
1663
1664 local_irq_save(flags);
1665 /* RTC_STATUS BUSY bit may stay active for 1/32768 seconds (~30 usec) */
1666 error = readl_poll_timeout(ddata->module_va + 0x44, val,
1667 !(val & BIT(0)), 100, 50);
1668 if (error)
1669 dev_warn(ddata->dev, "rtc busy timeout\n");
1670 /* Now we have ~15 microseconds to read/write various registers */
1671 sysc_write(ddata, 0x6c, kick0_val);
1672 sysc_write(ddata, 0x70, kick1_val);
1673 local_irq_restore(flags);
1674}
1675
1676static void sysc_module_unlock_quirk_rtc(struct sysc *ddata)
1677{
1678 sysc_quirk_rtc(ddata, false);
1679}
1680
1681static void sysc_module_lock_quirk_rtc(struct sysc *ddata)
1682{
1683 sysc_quirk_rtc(ddata, true);
1451}1684}
1452 1685
1453/* 36xx SGX needs a quirk for to bypass OCP IPG interrupt logic */1686/* 36xx SGX needs a quirk for to bypass OCP IPG interrupt logic */
@@ -1483,20 +1716,30 @@ static void sysc_reset_done_quirk_wdt(struct sysc *ddata) · 29 unmodified lines
1483 dev_warn(ddata->dev, "wdt disable step2 failed\n");1716 dev_warn(ddata->dev, "wdt disable step2 failed\n");
1484}1717}
1485 1718
1719/* PRUSS needs to set MSTANDBY_INIT inorder to idle properly */
1720static void sysc_module_disable_quirk_pruss(struct sysc *ddata)
1721{
1722 u32 reg;
1723
1724 reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]);
1725 reg |= SYSC_PRUSS_STANDBY_INIT;
1726 sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg);
1727}
1728
1486static void sysc_init_module_quirks(struct sysc *ddata)1729static void sysc_init_module_quirks(struct sysc *ddata)
1487{1730{
1488 if (ddata->legacy_mode || !ddata->name)1731 if (ddata->legacy_mode || !ddata->name)
1489 return;1732 return;
1490 1733
1491 if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_HDQ1W) {1734 if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_HDQ1W) {
1492 ddata->clk_disable_quirk = sysc_pre_reset_quirk_hdq1w;1735 ddata->pre_reset_quirk = sysc_pre_reset_quirk_hdq1w;
1493 1736
1494 return;1737 return;
1495 }1738 }
1496 1739
1497 if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_I2C) {1740 if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_I2C) {
1498 ddata->clk_enable_quirk = sysc_clk_enable_quirk_i2c;1741 ddata->pre_reset_quirk = sysc_pre_reset_quirk_i2c;
1499 ddata->clk_disable_quirk = sysc_clk_disable_quirk_i2c;1742 ddata->post_reset_quirk = sysc_post_reset_quirk_i2c;
1500 1743
1501 return;1744 return;
1502 }1745 }
@@ -1504,6 +1747,16 @@ static void sysc_init_module_quirks(struct sysc *ddata) · 1 unmodified line
1504 if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_AESS)1747 if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_AESS)
1505 ddata->module_enable_quirk = sysc_module_enable_quirk_aess;1748 ddata->module_enable_quirk = sysc_module_enable_quirk_aess;
1506 1749
1750 if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_DSS_RESET)
1751 ddata->pre_reset_quirk = sysc_pre_reset_quirk_dss;
1752
1753 if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_RTC_UNLOCK) {
1754 ddata->module_unlock_quirk = sysc_module_unlock_quirk_rtc;
1755 ddata->module_lock_quirk = sysc_module_lock_quirk_rtc;
1756
1757 return;
1758 }
1759
1507 if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_SGX)1760 if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_SGX)
1508 ddata->module_enable_quirk = sysc_module_enable_quirk_sgx;1761 ddata->module_enable_quirk = sysc_module_enable_quirk_sgx;
1509 1762
@@ -1511,6 +1764,9 @@ static void sysc_init_module_quirks(struct sysc *ddata) · 1 unmodified line
1511 ddata->reset_done_quirk = sysc_reset_done_quirk_wdt;1764 ddata->reset_done_quirk = sysc_reset_done_quirk_wdt;
1512 ddata->module_disable_quirk = sysc_reset_done_quirk_wdt;1765 ddata->module_disable_quirk = sysc_reset_done_quirk_wdt;
1513 }1766 }
1767
1768 if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_PRUSS)
1769 ddata->module_disable_quirk = sysc_module_disable_quirk_pruss;
1514}1770}
1515 1771
1516static int sysc_clockdomain_init(struct sysc *ddata)1772static int sysc_clockdomain_init(struct sysc *ddata)
@@ -1572,7 +1828,7 @@ static int sysc_reset(struct sysc *ddata) · 55 unmodified lines
1572 sysc_offset = ddata->offsets[SYSC_SYSCONFIG];1828 sysc_offset = ddata->offsets[SYSC_SYSCONFIG];
1573 syss_offset = ddata->offsets[SYSC_SYSSTATUS];1829 syss_offset = ddata->offsets[SYSC_SYSSTATUS];
1574 1830
1575 if (ddata->legacy_mode || sysc_offset < 0 ||1831 if (ddata->legacy_mode ||
1576 ddata->cap->regbits->srst_shift < 0 ||1832 ddata->cap->regbits->srst_shift < 0 ||
1577 ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)1833 ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)
1578 return 0;1834 return 0;
@@ -1584,19 +1840,21 @@ static int sysc_reset(struct sysc *ddata) · 5 unmodified lines
1584 else1840 else
1585 syss_done = ddata->cfg.syss_mask;1841 syss_done = ddata->cfg.syss_mask;
1586 1842
1587 if (ddata->clk_disable_quirk)1843 if (ddata->pre_reset_quirk)
1588 ddata->clk_disable_quirk(ddata);1844 ddata->pre_reset_quirk(ddata);
1589 1845
1590 sysc_val = sysc_read_sysconfig(ddata);1846 if (sysc_offset >= 0) {
1591 sysc_val |= sysc_mask;1847 sysc_val = sysc_read_sysconfig(ddata);
1592 sysc_write(ddata, sysc_offset, sysc_val);1848 sysc_val |= sysc_mask;
1849 sysc_write(ddata, sysc_offset, sysc_val);
1850 }
1593 1851
1594 if (ddata->cfg.srst_udelay)1852 if (ddata->cfg.srst_udelay)
1595 usleep_range(ddata->cfg.srst_udelay,1853 usleep_range(ddata->cfg.srst_udelay,
1596 ddata->cfg.srst_udelay * 2);1854 ddata->cfg.srst_udelay * 2);
1597 1855
1598 if (ddata->clk_enable_quirk)1856 if (ddata->post_reset_quirk)
1599 ddata->clk_enable_quirk(ddata);1857 ddata->post_reset_quirk(ddata);
1600 1858
1601 /* Poll on reset status */1859 /* Poll on reset status */
1602 if (syss_offset >= 0) {1860 if (syss_offset >= 0) {
@@ -2314,6 +2572,16 @@ static const struct sysc_capabilities sysc_dra7_mcan = { · 711 unmodified lines
2314 .mod_quirks = SYSS_QUIRK_RESETDONE_INVERTED,2572 .mod_quirks = SYSS_QUIRK_RESETDONE_INVERTED,
2315};2573};
2316 2574
2575/*
2576 * PRUSS found on some AM33xx, AM437x and AM57xx SoCs
2577 */
2578static const struct sysc_capabilities sysc_pruss = {
2579 .type = TI_SYSC_PRUSS,
2580 .sysc_mask = SYSC_PRUSS_STANDBY_INIT | SYSC_PRUSS_SUB_MWAIT,
2581 .regbits = &sysc_regbits_omap4_simple,
2582 .mod_quirks = SYSC_MODULE_QUIRK_PRUSS,
2583};
2584
2317static int sysc_init_pdata(struct sysc *ddata)2585static int sysc_init_pdata(struct sysc *ddata)
2318{2586{
2319 struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev);2587 struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev);
@@ -2387,6 +2655,154 @@ static void ti_sysc_idle(struct work_struct *work) · 67 unmodified lines
2387 pm_runtime_put_sync(ddata->dev);2655 pm_runtime_put_sync(ddata->dev);
2388}2656}
2389 2657
2658/*
2659 * SoC model and features detection. Only needed for SoCs that need
2660 * special handling for quirks, no need to list others.
2661 */
2662static const struct soc_device_attribute sysc_soc_match[] = {
2663 SOC_FLAG("OMAP242*", SOC_2420),
2664 SOC_FLAG("OMAP243*", SOC_2430),
2665 SOC_FLAG("OMAP3[45]*", SOC_3430),
2666 SOC_FLAG("OMAP3[67]*", SOC_3630),
2667 SOC_FLAG("OMAP443*", SOC_4430),
2668 SOC_FLAG("OMAP446*", SOC_4460),
2669 SOC_FLAG("OMAP447*", SOC_4470),
2670 SOC_FLAG("OMAP54*", SOC_5430),
2671 SOC_FLAG("AM433", SOC_AM3),
2672 SOC_FLAG("AM43*", SOC_AM4),
2673 SOC_FLAG("DRA7*", SOC_DRA7),
2674
2675 { /* sentinel */ },
2676};
2677
2678/*
2679 * List of SoCs variants with disabled features. By default we assume all
2680 * devices in the device tree are available so no need to list those SoCs.
2681 */
2682static const struct soc_device_attribute sysc_soc_feat_match[] = {
2683 /* OMAP3430/3530 and AM3517 variants with some accelerators disabled */
2684 SOC_FLAG("AM3505", DIS_SGX),
2685 SOC_FLAG("OMAP3525", DIS_SGX),
2686 SOC_FLAG("OMAP3515", DIS_IVA | DIS_SGX),
2687 SOC_FLAG("OMAP3503", DIS_ISP | DIS_IVA | DIS_SGX),
2688
2689 /* OMAP3630/DM3730 variants with some accelerators disabled */
2690 SOC_FLAG("AM3703", DIS_IVA | DIS_SGX),
2691 SOC_FLAG("DM3725", DIS_SGX),
2692 SOC_FLAG("OMAP3611", DIS_ISP | DIS_IVA | DIS_SGX),
2693 SOC_FLAG("OMAP3615/AM3715", DIS_IVA),
2694 SOC_FLAG("OMAP3621", DIS_ISP),
2695
2696 { /* sentinel */ },
2697};
2698
2699static int sysc_add_disabled(unsigned long base)
2700{
2701 struct sysc_address *disabled_module;
2702
2703 disabled_module = kzalloc(sizeof(*disabled_module), GFP_KERNEL);
2704 if (!disabled_module)
2705 return -ENOMEM;
2706
2707 disabled_module->base = base;
2708
2709 mutex_lock(&sysc_soc->list_lock);
2710 list_add(&disabled_module->node, &sysc_soc->disabled_modules);
2711 mutex_unlock(&sysc_soc->list_lock);
2712
2713 return 0;
2714}
2715
2716/*
2717 * One time init to detect the booted SoC and disable unavailable features.
2718 * Note that we initialize static data shared across all ti-sysc instances
2719 * so ddata is only used for SoC type. This can be called from module_init
2720 * once we no longer need to rely on platform data.
2721 */
2722static int sysc_init_soc(struct sysc *ddata)
2723{
2724 const struct soc_device_attribute *match;
2725 struct ti_sysc_platform_data *pdata;
2726 unsigned long features = 0;
2727
2728 if (sysc_soc)
2729 return 0;
2730
2731 sysc_soc = kzalloc(sizeof(*sysc_soc), GFP_KERNEL);
2732 if (!sysc_soc)
2733 return -ENOMEM;
2734
2735 mutex_init(&sysc_soc->list_lock);
2736 INIT_LIST_HEAD(&sysc_soc->disabled_modules);
2737 sysc_soc->general_purpose = true;
2738
2739 pdata = dev_get_platdata(ddata->dev);
2740 if (pdata && pdata->soc_type_gp)
2741 sysc_soc->general_purpose = pdata->soc_type_gp();
2742
2743 match = soc_device_match(sysc_soc_match);
2744 if (match && match->data)
2745 sysc_soc->soc = (int)match->data;
2746
2747 match = soc_device_match(sysc_soc_feat_match);
2748 if (!match)
2749 return 0;
2750
2751 if (match->data)
2752 features = (unsigned long)match->data;
2753
2754 /*
2755 * Add disabled devices to the list based on the module base.
2756 * Note that this must be done before we attempt to access the
2757 * device and have module revision checks working.
2758 */
2759 if (features & DIS_ISP)
2760 sysc_add_disabled(0x480bd400);
2761 if (features & DIS_IVA)
2762 sysc_add_disabled(0x5d000000);
2763 if (features & DIS_SGX)
2764 sysc_add_disabled(0x50000000);
2765
2766 return 0;
2767}
2768
2769static void sysc_cleanup_soc(void)
2770{
2771 struct sysc_address *disabled_module;
2772 struct list_head *pos, *tmp;
2773
2774 if (!sysc_soc)
2775 return;
2776
2777 mutex_lock(&sysc_soc->list_lock);
2778 list_for_each_safe(pos, tmp, &sysc_soc->disabled_modules) {
2779 disabled_module = list_entry(pos, struct sysc_address, node);
2780 list_del(pos);
2781 kfree(disabled_module);
2782 }
2783 mutex_unlock(&sysc_soc->list_lock);
2784}
2785
2786static int sysc_check_disabled_devices(struct sysc *ddata)
2787{
2788 struct sysc_address *disabled_module;
2789 struct list_head *pos;
2790 int error = 0;
2791
2792 mutex_lock(&sysc_soc->list_lock);
2793 list_for_each(pos, &sysc_soc->disabled_modules) {
2794 disabled_module = list_entry(pos, struct sysc_address, node);
2795 if (ddata->module_pa == disabled_module->base) {
2796 dev_dbg(ddata->dev, "module disabled for this SoC\n");
2797 error = -ENODEV;
2798 break;
2799 }
2800 }
2801 mutex_unlock(&sysc_soc->list_lock);
2802
2803 return error;
2804}
2805
2390static const struct of_device_id sysc_match_table[] = {2806static const struct of_device_id sysc_match_table[] = {
2391 { .compatible = "simple-bus", },2807 { .compatible = "simple-bus", },
2392 { /* sentinel */ },2808 { /* sentinel */ },
@@ -2405,6 +2821,10 @@ static int sysc_probe(struct platform_device *pdev) · 12 unmodified lines
2405 ddata->dev = &pdev->dev;2821 ddata->dev = &pdev->dev;
2406 platform_set_drvdata(pdev, ddata);2822 platform_set_drvdata(pdev, ddata);
2407 2823
2824 error = sysc_init_soc(ddata);
2825 if (error)
2826 return error;
2827
2408 error = sysc_init_match(ddata);2828 error = sysc_init_match(ddata);
2409 if (error)2829 if (error)
2410 return error;2830 return error;
@@ -2435,6 +2855,10 @@ static int sysc_probe(struct platform_device *pdev) · 24 unmodified lines
2435 2855
2436 sysc_init_early_quirks(ddata);2856 sysc_init_early_quirks(ddata);
2437 2857
2858 error = sysc_check_disabled_devices(ddata);
2859 if (error)
2860 return error;
2861
2438 error = sysc_get_clocks(ddata);2862 error = sysc_get_clocks(ddata);
2439 if (error)2863 if (error)
2440 return error;2864 return error;
@@ -2539,6 +2963,7 @@ static const struct of_device_id sysc_match[] = { · 98 unmodified lines
2539 { .compatible = "ti,sysc-usb-host-fs",2963 { .compatible = "ti,sysc-usb-host-fs",
2540 .data = &sysc_omap4_usb_host_fs, },2964 .data = &sysc_omap4_usb_host_fs, },
2541 { .compatible = "ti,sysc-dra7-mcan", .data = &sysc_dra7_mcan, },2965 { .compatible = "ti,sysc-dra7-mcan", .data = &sysc_dra7_mcan, },
2966 { .compatible = "ti,sysc-pruss", .data = &sysc_pruss, },
2542 { },2967 { },
2543};2968};
2544MODULE_DEVICE_TABLE(of, sysc_match);2969MODULE_DEVICE_TABLE(of, sysc_match);
@@ -2565,6 +2990,7 @@ static void __exit sysc_exit(void) · 20 unmodified lines
2565{2990{
2566 bus_unregister_notifier(&platform_bus_type, &sysc_nb);2991 bus_unregister_notifier(&platform_bus_type, &sysc_nb);
2567 platform_driver_unregister(&sysc_driver);2992 platform_driver_unregister(&sysc_driver);
2993 sysc_cleanup_soc();
2568}2994}
2569module_exit(sysc_exit);2995module_exit(sysc_exit);
2570 2996
drivers/firmware/arm_scmi/Makefile+2−1
@@ -1,6 +1,7 @@
1# SPDX-License-Identifier: GPL-2.0-only1# SPDX-License-Identifier: GPL-2.0-only
2obj-y = scmi-bus.o scmi-driver.o scmi-protocols.o2obj-y = scmi-bus.o scmi-driver.o scmi-protocols.o scmi-transport.o
3scmi-bus-y = bus.o3scmi-bus-y = bus.o
4scmi-driver-y = driver.o4scmi-driver-y = driver.o
5scmi-transport-y = mailbox.o shmem.o
5scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o6scmi-protocols-y = base.o clock.o perf.o power.o reset.o sensors.o
6obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o7obj-$(CONFIG_ARM_SCMI_POWER_DOMAIN) += scmi_pm_domain.o
drivers/firmware/arm_scmi/common.h+113−2
@@ -33,8 +33,8 @@ enum scmi_common_cmd { · 32 unmodified lines
33/**33/**
34 * struct scmi_msg_resp_prot_version - Response for a message34 * struct scmi_msg_resp_prot_version - Response for a message
35 *35 *
36 * @major_version: Major version of the ABI that firmware supports
37 * @minor_version: Minor version of the ABI that firmware supports36 * @minor_version: Minor version of the ABI that firmware supports
37 * @major_version: Major version of the ABI that firmware supports
38 *38 *
39 * In general, ABI version changes follow the rule that minor version increments39 * In general, ABI version changes follow the rule that minor version increments
40 * are backward compatible. Major revision changes in ABI may not be40 * are backward compatible. Major revision changes in ABI may not be
@@ -47,6 +47,19 @@ struct scmi_msg_resp_prot_version { · 6 unmodified lines
47 __le16 major_version;47 __le16 major_version;
48};48};
49 49
50#define MSG_ID_MASK GENMASK(7, 0)
51#define MSG_XTRACT_ID(hdr) FIELD_GET(MSG_ID_MASK, (hdr))
52#define MSG_TYPE_MASK GENMASK(9, 8)
53#define MSG_XTRACT_TYPE(hdr) FIELD_GET(MSG_TYPE_MASK, (hdr))
54#define MSG_TYPE_COMMAND 0
55#define MSG_TYPE_DELAYED_RESP 2
56#define MSG_TYPE_NOTIFICATION 3
57#define MSG_PROTOCOL_ID_MASK GENMASK(17, 10)
58#define MSG_XTRACT_PROT_ID(hdr) FIELD_GET(MSG_PROTOCOL_ID_MASK, (hdr))
59#define MSG_TOKEN_ID_MASK GENMASK(27, 18)
60#define MSG_XTRACT_TOKEN(hdr) FIELD_GET(MSG_TOKEN_ID_MASK, (hdr))
61#define MSG_TOKEN_MAX (MSG_XTRACT_TOKEN(MSG_TOKEN_ID_MASK) + 1)
62
50/**63/**
51 * struct scmi_msg_hdr - Message(Tx/Rx) header64 * struct scmi_msg_hdr - Message(Tx/Rx) header
52 *65 *
@@ -67,6 +80,33 @@ struct scmi_msg_hdr { · 14 unmodified lines
67 bool poll_completion;80 bool poll_completion;
68};81};
69 82
83/**
84 * pack_scmi_header() - packs and returns 32-bit header
85 *
86 * @hdr: pointer to header containing all the information on message id,
87 * protocol id and sequence id.
88 *
89 * Return: 32-bit packed message header to be sent to the platform.
90 */
91static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr)
92{
93 return FIELD_PREP(MSG_ID_MASK, hdr->id) |
94 FIELD_PREP(MSG_TOKEN_ID_MASK, hdr->seq) |
95 FIELD_PREP(MSG_PROTOCOL_ID_MASK, hdr->protocol_id);
96}
97
98/**
99 * unpack_scmi_header() - unpacks and records message and protocol id
100 *
101 * @msg_hdr: 32-bit packed message header sent from the platform
102 * @hdr: pointer to header to fetch message and protocol id.
103 */
104static inline void unpack_scmi_header(u32 msg_hdr, struct scmi_msg_hdr *hdr)
105{
106 hdr->id = MSG_XTRACT_ID(msg_hdr);
107 hdr->protocol_id = MSG_XTRACT_PROT_ID(msg_hdr);
108}
109
70/**110/**
71 * struct scmi_msg - Message(Tx/Rx) structure111 * struct scmi_msg - Message(Tx/Rx) structure
72 *112 *
@@ -88,7 +128,7 @@ struct scmi_msg { · 15 unmodified lines
88 * message. If request-ACK protocol is used, we can reuse the same128 * message. If request-ACK protocol is used, we can reuse the same
89 * buffer for the rx path as we use for the tx path.129 * buffer for the rx path as we use for the tx path.
90 * @done: command message transmit completion event130 * @done: command message transmit completion event
91 * @async: pointer to delayed response message received event completion131 * @async_done: pointer to delayed response message received event completion
92 */132 */
93struct scmi_xfer {133struct scmi_xfer {
94 int transfer_id;134 int transfer_id;
@@ -113,3 +153,74 @@ void scmi_setup_protocol_implemented(const struct scmi_handle *handle, · 18 unmodified lines
113 u8 *prot_imp);153 u8 *prot_imp);
114 154
115int scmi_base_protocol_init(struct scmi_handle *h);155int scmi_base_protocol_init(struct scmi_handle *h);
156
157/* SCMI Transport */
158/**
159 * struct scmi_chan_info - Structure representing a SCMI channel information
160 *
161 * @dev: Reference to device in the SCMI hierarchy corresponding to this
162 * channel
163 * @handle: Pointer to SCMI entity handle
164 * @transport_info: Transport layer related information
165 */
166struct scmi_chan_info {
167 struct device *dev;
168 struct scmi_handle *handle;
169 void *transport_info;
170};
171
172/**
173 * struct scmi_transport_ops - Structure representing a SCMI transport ops
174 *
175 * @chan_available: Callback to check if channel is available or not
176 * @chan_setup: Callback to allocate and setup a channel
177 * @chan_free: Callback to free a channel
178 * @send_message: Callback to send a message
179 * @mark_txdone: Callback to mark tx as done
180 * @fetch_response: Callback to fetch response
181 * @poll_done: Callback to poll transfer status
182 */
183struct scmi_transport_ops {
184 bool (*chan_available)(struct device *dev, int idx);
185 int (*chan_setup)(struct scmi_chan_info *cinfo, struct device *dev,
186 bool tx);
187 int (*chan_free)(int id, void *p, void *data);
188 int (*send_message)(struct scmi_chan_info *cinfo,
189 struct scmi_xfer *xfer);
190 void (*mark_txdone)(struct scmi_chan_info *cinfo, int ret);
191 void (*fetch_response)(struct scmi_chan_info *cinfo,
192 struct scmi_xfer *xfer);
193 bool (*poll_done)(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer);
194};
195
196/**
197 * struct scmi_desc - Description of SoC integration
198 *
199 * @ops: Pointer to the transport specific ops structure
200 * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds)
201 * @max_msg: Maximum number of messages that can be pending
202 * simultaneously in the system
203 * @max_msg_size: Maximum size of data per message that can be handled.
204 */
205struct scmi_desc {
206 struct scmi_transport_ops *ops;
207 int max_rx_timeout_ms;
208 int max_msg;
209 int max_msg_size;
210};
211
212extern const struct scmi_desc scmi_mailbox_desc;
213
214void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr);
215void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id);
216
217/* shmem related declarations */
218struct scmi_shared_mem;
219
220void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem,
221 struct scmi_xfer *xfer);
222u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem);
223void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem,
224 struct scmi_xfer *xfer);
225bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem,
226 struct scmi_xfer *xfer);
drivers/firmware/arm_scmi/driver.c+34−259
@@ -19,12 +19,10 @@ · 18 unmodified lines
19#include <linux/io.h>19#include <linux/io.h>
20#include <linux/kernel.h>20#include <linux/kernel.h>
21#include <linux/ktime.h>21#include <linux/ktime.h>
22#include <linux/mailbox_client.h>
23#include <linux/module.h>22#include <linux/module.h>
24#include <linux/of_address.h>23#include <linux/of_address.h>
25#include <linux/of_device.h>24#include <linux/of_device.h>
26#include <linux/processor.h>25#include <linux/processor.h>
27#include <linux/semaphore.h>
28#include <linux/slab.h>26#include <linux/slab.h>
29 27
30#include "common.h"28#include "common.h"
@@ -32,19 +30,6 @@ · 1 unmodified line
32#define CREATE_TRACE_POINTS30#define CREATE_TRACE_POINTS
33#include <trace/events/scmi.h>31#include <trace/events/scmi.h>
34 32
35#define MSG_ID_MASK GENMASK(7, 0)
36#define MSG_XTRACT_ID(hdr) FIELD_GET(MSG_ID_MASK, (hdr))
37#define MSG_TYPE_MASK GENMASK(9, 8)
38#define MSG_XTRACT_TYPE(hdr) FIELD_GET(MSG_TYPE_MASK, (hdr))
39#define MSG_TYPE_COMMAND 0
40#define MSG_TYPE_DELAYED_RESP 2
41#define MSG_TYPE_NOTIFICATION 3
42#define MSG_PROTOCOL_ID_MASK GENMASK(17, 10)
43#define MSG_XTRACT_PROT_ID(hdr) FIELD_GET(MSG_PROTOCOL_ID_MASK, (hdr))
44#define MSG_TOKEN_ID_MASK GENMASK(27, 18)
45#define MSG_XTRACT_TOKEN(hdr) FIELD_GET(MSG_TOKEN_ID_MASK, (hdr))
46#define MSG_TOKEN_MAX (MSG_XTRACT_TOKEN(MSG_TOKEN_ID_MASK) + 1)
47
48enum scmi_error_codes {33enum scmi_error_codes {
49 SCMI_SUCCESS = 0, /* Success */34 SCMI_SUCCESS = 0, /* Success */
50 SCMI_ERR_SUPPORT = -1, /* Not supported */35 SCMI_ERR_SUPPORT = -1, /* Not supported */
@@ -82,46 +67,14 @@ struct scmi_xfers_info { · 31 unmodified lines
82 spinlock_t xfer_lock;67 spinlock_t xfer_lock;
83};68};
84 69
85/**
86 * struct scmi_desc - Description of SoC integration
87 *
88 * @max_rx_timeout_ms: Timeout for communication with SoC (in Milliseconds)
89 * @max_msg: Maximum number of messages that can be pending
90 * simultaneously in the system
91 * @max_msg_size: Maximum size of data per message that can be handled.
92 */
93struct scmi_desc {
94 int max_rx_timeout_ms;
95 int max_msg;
96 int max_msg_size;
97};
98
99/**
100 * struct scmi_chan_info - Structure representing a SCMI channel information
101 *
102 * @cl: Mailbox Client
103 * @chan: Transmit/Receive mailbox channel
104 * @payload: Transmit/Receive mailbox channel payload area
105 * @dev: Reference to device in the SCMI hierarchy corresponding to this
106 * channel
107 * @handle: Pointer to SCMI entity handle
108 */
109struct scmi_chan_info {
110 struct mbox_client cl;
111 struct mbox_chan *chan;
112 void __iomem *payload;
113 struct device *dev;
114 struct scmi_handle *handle;
115};
116
117/**70/**
118 * struct scmi_info - Structure representing a SCMI instance71 * struct scmi_info - Structure representing a SCMI instance
119 *72 *
120 * @dev: Device pointer73 * @dev: Device pointer
121 * @desc: SoC description for this instance74 * @desc: SoC description for this instance
122 * @handle: Instance of SCMI handle to send to clients
123 * @version: SCMI revision information containing protocol version,75 * @version: SCMI revision information containing protocol version,
124 * implementation version and (sub-)vendor identification.76 * implementation version and (sub-)vendor identification.
77 * @handle: Instance of SCMI handle to send to clients
125 * @tx_minfo: Universal Transmit Message management info78 * @tx_minfo: Universal Transmit Message management info
126 * @tx_idr: IDR object to map protocol id to Tx channel info pointer79 * @tx_idr: IDR object to map protocol id to Tx channel info pointer
127 * @rx_idr: IDR object to map protocol id to Rx channel info pointer80 * @rx_idr: IDR object to map protocol id to Rx channel info pointer
@@ -143,27 +96,8 @@ struct scmi_info { · 15 unmodified lines
143 int users;96 int users;
144};97};
145 98
146#define client_to_scmi_chan_info(c) container_of(c, struct scmi_chan_info, cl)
147#define handle_to_scmi_info(h) container_of(h, struct scmi_info, handle)99#define handle_to_scmi_info(h) container_of(h, struct scmi_info, handle)
148 100
149/*
150 * SCMI specification requires all parameters, message headers, return
151 * arguments or any protocol data to be expressed in little endian
152 * format only.
153 */
154struct scmi_shared_mem {
155 __le32 reserved;
156 __le32 channel_status;
157#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR BIT(1)
158#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE BIT(0)
159 __le32 reserved1[2];
160 __le32 flags;
161#define SCMI_SHMEM_FLAG_INTR_ENABLED BIT(0)
162 __le32 length;
163 __le32 msg_header;
164 u8 msg_payload[0];
165};
166
167static const int scmi_linux_errmap[] = {101static const int scmi_linux_errmap[] = {
168 /* better than switch case as long as return value is continuous */102 /* better than switch case as long as return value is continuous */
169 0, /* SCMI_SUCCESS */103 0, /* SCMI_SUCCESS */
@@ -199,77 +133,6 @@ static inline void scmi_dump_header_dbg(struct device *dev, · 29 unmodified lines
199 hdr->id, hdr->seq, hdr->protocol_id);133 hdr->id, hdr->seq, hdr->protocol_id);
200}134}
201 135
202static void scmi_fetch_response(struct scmi_xfer *xfer,
203 struct scmi_shared_mem __iomem *mem)
204{
205 xfer->hdr.status = ioread32(mem->msg_payload);
206 /* Skip the length of header and status in payload area i.e 8 bytes */
207 xfer->rx.len = min_t(size_t, xfer->rx.len, ioread32(&mem->length) - 8);
208
209 /* Take a copy to the rx buffer.. */
210 memcpy_fromio(xfer->rx.buf, mem->msg_payload + 4, xfer->rx.len);
211}
212
213/**
214 * pack_scmi_header() - packs and returns 32-bit header
215 *
216 * @hdr: pointer to header containing all the information on message id,
217 * protocol id and sequence id.
218 *
219 * Return: 32-bit packed message header to be sent to the platform.
220 */
221static inline u32 pack_scmi_header(struct scmi_msg_hdr *hdr)
222{
223 return FIELD_PREP(MSG_ID_MASK, hdr->id) |
224 FIELD_PREP(MSG_TOKEN_ID_MASK, hdr->seq) |
225 FIELD_PREP(MSG_PROTOCOL_ID_MASK, hdr->protocol_id);
226}
227
228/**
229 * unpack_scmi_header() - unpacks and records message and protocol id
230 *
231 * @msg_hdr: 32-bit packed message header sent from the platform
232 * @hdr: pointer to header to fetch message and protocol id.
233 */
234static inline void unpack_scmi_header(u32 msg_hdr, struct scmi_msg_hdr *hdr)
235{
236 hdr->id = MSG_XTRACT_ID(msg_hdr);
237 hdr->protocol_id = MSG_XTRACT_PROT_ID(msg_hdr);
238}
239
240/**
241 * scmi_tx_prepare() - mailbox client callback to prepare for the transfer
242 *
243 * @cl: client pointer
244 * @m: mailbox message
245 *
246 * This function prepares the shared memory which contains the header and the
247 * payload.
248 */
249static void scmi_tx_prepare(struct mbox_client *cl, void *m)
250{
251 struct scmi_xfer *t = m;
252 struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
253 struct scmi_shared_mem __iomem *mem = cinfo->payload;
254
255 /*
256 * Ideally channel must be free by now unless OS timeout last
257 * request and platform continued to process the same, wait
258 * until it releases the shared memory, otherwise we may endup
259 * overwriting its response with new message payload or vice-versa
260 */
261 spin_until_cond(ioread32(&mem->channel_status) &
262 SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
263 /* Mark channel busy + clear error */
264 iowrite32(0x0, &mem->channel_status);
265 iowrite32(t->hdr.poll_completion ? 0 : SCMI_SHMEM_FLAG_INTR_ENABLED,
266 &mem->flags);
267 iowrite32(sizeof(mem->msg_header) + t->tx.len, &mem->length);
268 iowrite32(pack_scmi_header(&t->hdr), &mem->msg_header);
269 if (t->tx.buf)
270 memcpy_toio(mem->msg_payload, t->tx.buf, t->tx.len);
271}
272
273/**136/**
274 * scmi_xfer_get() - Allocate one message137 * scmi_xfer_get() - Allocate one message
275 *138 *
@@ -338,10 +201,10 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer) · 62 unmodified lines
338}201}
339 202
340/**203/**
341 * scmi_rx_callback() - mailbox client callback for receive messages204 * scmi_rx_callback() - callback for receiving messages
342 *205 *
343 * @cl: client pointer206 * @cinfo: SCMI channel info
344 * @m: mailbox message207 * @msg_hdr: Message header
345 *208 *
346 * Processes one received message to appropriate transfer information and209 * Processes one received message to appropriate transfer information and
347 * signals completion of the transfer.210 * signals completion of the transfer.
@@ -349,21 +212,14 @@ __scmi_xfer_put(struct scmi_xfers_info *minfo, struct scmi_xfer *xfer) · 1 unmodified line
349 * NOTE: This function will be invoked in IRQ context, hence should be212 * NOTE: This function will be invoked in IRQ context, hence should be
350 * as optimal as possible.213 * as optimal as possible.
351 */214 */
352static void scmi_rx_callback(struct mbox_client *cl, void *m)215void scmi_rx_callback(struct scmi_chan_info *cinfo, u32 msg_hdr)
353{216{
354 u8 msg_type;
355 u32 msg_hdr;
356 u16 xfer_id;
357 struct scmi_xfer *xfer;
358 struct scmi_chan_info *cinfo = client_to_scmi_chan_info(cl);
359 struct device *dev = cinfo->dev;
360 struct scmi_info *info = handle_to_scmi_info(cinfo->handle);217 struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
361 struct scmi_xfers_info *minfo = &info->tx_minfo;218 struct scmi_xfers_info *minfo = &info->tx_minfo;
362 struct scmi_shared_mem __iomem *mem = cinfo->payload;219 u16 xfer_id = MSG_XTRACT_TOKEN(msg_hdr);
363 220 u8 msg_type = MSG_XTRACT_TYPE(msg_hdr);
364 msg_hdr = ioread32(&mem->msg_header);221 struct device *dev = cinfo->dev;
365 msg_type = MSG_XTRACT_TYPE(msg_hdr);222 struct scmi_xfer *xfer;
366 xfer_id = MSG_XTRACT_TOKEN(msg_hdr);
367 223
368 if (msg_type == MSG_TYPE_NOTIFICATION)224 if (msg_type == MSG_TYPE_NOTIFICATION)
369 return; /* Notifications not yet supported */225 return; /* Notifications not yet supported */
@@ -378,7 +234,7 @@ static void scmi_rx_callback(struct mbox_client *cl, void *m) · 8 unmodified lines
378 234
379 scmi_dump_header_dbg(dev, &xfer->hdr);235 scmi_dump_header_dbg(dev, &xfer->hdr);
380 236
381 scmi_fetch_response(xfer, mem);237 info->desc->ops->fetch_response(cinfo, xfer);
382 238
383 trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id,239 trace_scmi_rx_done(xfer->transfer_id, xfer->hdr.id,
384 xfer->hdr.protocol_id, xfer->hdr.seq,240 xfer->hdr.protocol_id, xfer->hdr.seq,
@@ -403,28 +259,15 @@ void scmi_xfer_put(const struct scmi_handle *handle, struct scmi_xfer *xfer) · 18 unmodified lines
403 __scmi_xfer_put(&info->tx_minfo, xfer);259 __scmi_xfer_put(&info->tx_minfo, xfer);
404}260}
405 261
406static bool
407scmi_xfer_poll_done(const struct scmi_chan_info *cinfo, struct scmi_xfer *xfer)
408{
409 struct scmi_shared_mem __iomem *mem = cinfo->payload;
410 u16 xfer_id = MSG_XTRACT_TOKEN(ioread32(&mem->msg_header));
411
412 if (xfer->hdr.seq != xfer_id)
413 return false;
414
415 return ioread32(&mem->channel_status) &
416 (SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR |
417 SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
418}
419
420#define SCMI_MAX_POLL_TO_NS (100 * NSEC_PER_USEC)262#define SCMI_MAX_POLL_TO_NS (100 * NSEC_PER_USEC)
421 263
422static bool scmi_xfer_done_no_timeout(const struct scmi_chan_info *cinfo,264static bool scmi_xfer_done_no_timeout(struct scmi_chan_info *cinfo,
423 struct scmi_xfer *xfer, ktime_t stop)265 struct scmi_xfer *xfer, ktime_t stop)
424{266{
425 ktime_t __cur = ktime_get();267 struct scmi_info *info = handle_to_scmi_info(cinfo->handle);
426 268
427 return scmi_xfer_poll_done(cinfo, xfer) || ktime_after(__cur, stop);269 return info->desc->ops->poll_done(cinfo, xfer) ||
270 ktime_after(ktime_get(), stop);
428}271}
429 272
430/**273/**
@@ -453,29 +296,26 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer) · 22 unmodified lines
453 xfer->hdr.protocol_id, xfer->hdr.seq,296 xfer->hdr.protocol_id, xfer->hdr.seq,
454 xfer->hdr.poll_completion);297 xfer->hdr.poll_completion);
455 298
456 ret = mbox_send_message(cinfo->chan, xfer);299 ret = info->desc->ops->send_message(cinfo, xfer);
457 if (ret < 0) {300 if (ret < 0) {
458 dev_dbg(dev, "mbox send fail %d\n", ret);301 dev_dbg(dev, "Failed to send message %d\n", ret);
459 return ret;302 return ret;
460 }303 }
461 304
462 /* mbox_send_message returns non-negative value on success, so reset */
463 ret = 0;
464
465 if (xfer->hdr.poll_completion) {305 if (xfer->hdr.poll_completion) {
466 ktime_t stop = ktime_add_ns(ktime_get(), SCMI_MAX_POLL_TO_NS);306 ktime_t stop = ktime_add_ns(ktime_get(), SCMI_MAX_POLL_TO_NS);
467 307
468 spin_until_cond(scmi_xfer_done_no_timeout(cinfo, xfer, stop));308 spin_until_cond(scmi_xfer_done_no_timeout(cinfo, xfer, stop));
469 309
470 if (ktime_before(ktime_get(), stop))310 if (ktime_before(ktime_get(), stop))
471 scmi_fetch_response(xfer, cinfo->payload);311 info->desc->ops->fetch_response(cinfo, xfer);
472 else312 else
473 ret = -ETIMEDOUT;313 ret = -ETIMEDOUT;
474 } else {314 } else {
475 /* And we wait for the response. */315 /* And we wait for the response. */
476 timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);316 timeout = msecs_to_jiffies(info->desc->max_rx_timeout_ms);
477 if (!wait_for_completion_timeout(&xfer->done, timeout)) {317 if (!wait_for_completion_timeout(&xfer->done, timeout)) {
478 dev_err(dev, "mbox timed out in resp(caller: %pS)\n",318 dev_err(dev, "timed out in resp(caller: %pS)\n",
479 (void *)_RET_IP_);319 (void *)_RET_IP_);
480 ret = -ETIMEDOUT;320 ret = -ETIMEDOUT;
481 }321 }
@@ -484,13 +324,8 @@ int scmi_do_xfer(const struct scmi_handle *handle, struct scmi_xfer *xfer) · 2 unmodified lines
484 if (!ret && xfer->hdr.status)324 if (!ret && xfer->hdr.status)
485 ret = scmi_to_linux_errno(xfer->hdr.status);325 ret = scmi_to_linux_errno(xfer->hdr.status);
486 326
487 /*327 if (info->desc->ops->mark_txdone)
488 * NOTE: we might prefer not to need the mailbox ticker to manage the328 info->desc->ops->mark_txdone(cinfo, ret);
489 * transfer queueing since the protocol layer queues things by itself.
490 * Unfortunately, we have to kick the mailbox framework after we have
491 * received our message.
492 */
493 mbox_client_txdone(cinfo->chan, ret);
494 329
495 trace_scmi_xfer_end(xfer->transfer_id, xfer->hdr.id,330 trace_scmi_xfer_end(xfer->transfer_id, xfer->hdr.id,
496 xfer->hdr.protocol_id, xfer->hdr.seq,331 xfer->hdr.protocol_id, xfer->hdr.seq,
@@ -731,23 +566,12 @@ static int scmi_xfer_info_init(struct scmi_info *sinfo) · 234 unmodified lines
731 return 0;566 return 0;
732}567}
733 568
734static int scmi_mailbox_check(struct device_node *np, int idx)569static int scmi_chan_setup(struct scmi_info *info, struct device *dev,
735{570 int prot_id, bool tx)
736 return of_parse_phandle_with_args(np, "mboxes", "#mbox-cells",
737 idx, NULL);
738}
739
740static int scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev,
741 int prot_id, bool tx)
742{571{
743 int ret, idx;572 int ret, idx;
744 struct resource res;
745 resource_size_t size;
746 struct device_node *shmem, *np = dev->of_node;
747 struct scmi_chan_info *cinfo;573 struct scmi_chan_info *cinfo;
748 struct mbox_client *cl;
749 struct idr *idr;574 struct idr *idr;
750 const char *desc = tx ? "Tx" : "Rx";
751 575
752 /* Transmit channel is first entry i.e. index 0 */576 /* Transmit channel is first entry i.e. index 0 */
753 idx = tx ? 0 : 1;577 idx = tx ? 0 : 1;
@@ -758,7 +582,7 @@ static int scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, · 4 unmodified lines
758 if (cinfo)582 if (cinfo)
759 return 0;583 return 0;
760 584
761 if (scmi_mailbox_check(np, idx)) {585 if (!info->desc->ops->chan_available(dev, idx)) {
762 cinfo = idr_find(idr, SCMI_PROTOCOL_BASE);586 cinfo = idr_find(idr, SCMI_PROTOCOL_BASE);
763 if (unlikely(!cinfo)) /* Possible only if platform has no Rx */587 if (unlikely(!cinfo)) /* Possible only if platform has no Rx */
764 return -EINVAL;588 return -EINVAL;
@@ -771,36 +595,9 @@ static int scmi_mbox_chan_setup(struct scmi_info *info, struct device *dev, · 6 unmodified lines
771 595
772 cinfo->dev = dev;596 cinfo->dev = dev;
773 597
774 cl = &cinfo->cl;598 ret = info->desc->ops->chan_setup(cinfo, info->dev, tx);
775 cl->dev = dev;599 if (ret)
776 cl->rx_callback = scmi_rx_callback;
777 cl->tx_prepare = tx ? scmi_tx_prepare : NULL;
778 cl->tx_block = false;
779 cl->knows_txdone = tx;
780
781 shmem = of_parse_phandle(np, "shmem", idx);
782 ret = of_address_to_resource(shmem, 0, &res);
783 of_node_put(shmem);
784 if (ret) {
785 dev_err(dev, "failed to get SCMI %s payload memory\n", desc);
786 return ret;
787 }
788
789 size = resource_size(&res);
790 cinfo->payload = devm_ioremap(info->dev, res.start, size);
791 if (!cinfo->payload) {
792 dev_err(dev, "failed to ioremap SCMI %s payload\n", desc);
793 return -EADDRNOTAVAIL;
794 }
795
796 cinfo->chan = mbox_request_channel(cl, idx);
797 if (IS_ERR(cinfo->chan)) {
798 ret = PTR_ERR(cinfo->chan);
799 if (ret != -EPROBE_DEFER)
800 dev_err(dev, "failed to request SCMI %s mailbox\n",
801 desc);
802 return ret;600 return ret;
803 }
804 601
805idr_alloc:602idr_alloc:
806 ret = idr_alloc(idr, cinfo, prot_id, prot_id + 1, GFP_KERNEL);603 ret = idr_alloc(idr, cinfo, prot_id, prot_id + 1, GFP_KERNEL);
@@ -814,12 +611,12 @@ idr_alloc: · 7 unmodified lines
814}611}
815 612
816static inline int613static inline int
817scmi_mbox_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id)614scmi_txrx_setup(struct scmi_info *info, struct device *dev, int prot_id)
818{615{
819 int ret = scmi_mbox_chan_setup(info, dev, prot_id, true);616 int ret = scmi_chan_setup(info, dev, prot_id, true);
820 617
821 if (!ret) /* Rx is optional, hence no error check */618 if (!ret) /* Rx is optional, hence no error check */
822 scmi_mbox_chan_setup(info, dev, prot_id, false);619 scmi_chan_setup(info, dev, prot_id, false);
823 620
824 return ret;621 return ret;
825}622}
@@ -837,7 +634,7 @@ scmi_create_protocol_device(struct device_node *np, struct scmi_info *info, · 11 unmodified lines
837 return;634 return;
838 }635 }
839 636
840 if (scmi_mbox_txrx_setup(info, &sdev->dev, prot_id)) {637 if (scmi_txrx_setup(info, &sdev->dev, prot_id)) {
841 dev_err(&sdev->dev, "failed to setup transport\n");638 dev_err(&sdev->dev, "failed to setup transport\n");
842 scmi_device_destroy(sdev);639 scmi_device_destroy(sdev);
843 return;640 return;
@@ -890,12 +687,6 @@ static int scmi_probe(struct platform_device *pdev) · 46 unmodified lines
890 struct device *dev = &pdev->dev;687 struct device *dev = &pdev->dev;
891 struct device_node *child, *np = dev->of_node;688 struct device_node *child, *np = dev->of_node;
892 689
893 /* Only mailbox method supported, check for the presence of one */
894 if (scmi_mailbox_check(np, 0)) {
895 dev_err(dev, "no mailbox found in %pOF\n", np);
896 return -EINVAL;
897 }
898
899 desc = of_device_get_match_data(dev);690 desc = of_device_get_match_data(dev);
900 if (!desc)691 if (!desc)
901 return -EINVAL;692 return -EINVAL;
@@ -920,7 +711,7 @@ static int scmi_probe(struct platform_device *pdev) · 18 unmodified lines
920 handle->dev = info->dev;711 handle->dev = info->dev;
921 handle->version = &info->version;712 handle->version = &info->version;
922 713
923 ret = scmi_mbox_txrx_setup(info, dev, SCMI_PROTOCOL_BASE);714 ret = scmi_txrx_setup(info, dev, SCMI_PROTOCOL_BASE);
924 if (ret)715 if (ret)
925 return ret;716 return ret;
926 717
@@ -955,19 +746,9 @@ static int scmi_probe(struct platform_device *pdev) · 28 unmodified lines
955 return 0;746 return 0;
956}747}
957 748
958static int scmi_mbox_free_channel(int id, void *p, void *data)749void scmi_free_channel(struct scmi_chan_info *cinfo, struct idr *idr, int id)
959{750{
960 struct scmi_chan_info *cinfo = p;
961 struct idr *idr = data;
962
963 if (!IS_ERR_OR_NULL(cinfo->chan)) {
964 mbox_free_channel(cinfo->chan);
965 cinfo->chan = NULL;
966 }
967
968 idr_remove(idr, id);751 idr_remove(idr, id);
969
970 return 0;
971}752}
972 753
973static int scmi_remove(struct platform_device *pdev)754static int scmi_remove(struct platform_device *pdev)
@@ -987,11 +768,11 @@ static int scmi_remove(struct platform_device *pdev) · 13 unmodified lines
987 return ret;768 return ret;
988 769
989 /* Safe to free channels since no more users */770 /* Safe to free channels since no more users */
990 ret = idr_for_each(idr, scmi_mbox_free_channel, idr);771 ret = idr_for_each(idr, info->desc->ops->chan_free, idr);
991 idr_destroy(&info->tx_idr);772 idr_destroy(&info->tx_idr);
992 773
993 idr = &info->rx_idr;774 idr = &info->rx_idr;
994 ret = idr_for_each(idr, scmi_mbox_free_channel, idr);775 ret = idr_for_each(idr, info->desc->ops->chan_free, idr);
995 idr_destroy(&info->rx_idr);776 idr_destroy(&info->rx_idr);
996 777
997 return ret;778 return ret;
@@ -1043,15 +824,9 @@ static struct attribute *versions_attrs[] = { · 45 unmodified lines
1043};824};
1044ATTRIBUTE_GROUPS(versions);825ATTRIBUTE_GROUPS(versions);
1045 826
1046static const struct scmi_desc scmi_generic_desc = {
1047 .max_rx_timeout_ms = 30, /* We may increase this if required */
1048 .max_msg = 20, /* Limited by MBOX_TX_QUEUE_LEN */
1049 .max_msg_size = 128,
1050};
1051
1052/* Each compatible listed below must have descriptor associated with it */827/* Each compatible listed below must have descriptor associated with it */
1053static const struct of_device_id scmi_of_match[] = {828static const struct of_device_id scmi_of_match[] = {
1054 { .compatible = "arm,scmi", .data = &scmi_generic_desc },829 { .compatible = "arm,scmi", .data = &scmi_mailbox_desc },
1055 { /* Sentinel */ },830 { /* Sentinel */ },
1056};831};
1057 832
drivers/firmware/arm_scmi/mailbox.c+184−0
@@ -0,0 +1,184 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * System Control and Management Interface (SCMI) Message Mailbox Transport
4 * driver.
5 *
6 * Copyright (C) 2019 ARM Ltd.
7 */
8
9#include <linux/err.h>
10#include <linux/device.h>
11#include <linux/mailbox_client.h>
12#include <linux/of.h>
13#include <linux/of_address.h>
14#include <linux/slab.h>
15
16#include "common.h"
17
18/**
19 * struct scmi_mailbox - Structure representing a SCMI mailbox transport
20 *
21 * @cl: Mailbox Client
22 * @chan: Transmit/Receive mailbox channel
23 * @cinfo: SCMI channel info
24 * @shmem: Transmit/Receive shared memory area
25 */
26struct scmi_mailbox {
27 struct mbox_client cl;
28 struct mbox_chan *chan;
29 struct scmi_chan_info *cinfo;
30 struct scmi_shared_mem __iomem *shmem;
31};
32
33#define client_to_scmi_mailbox(c) container_of(c, struct scmi_mailbox, cl)
34
35static void tx_prepare(struct mbox_client *cl, void *m)
36{
37 struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl);
38
39 shmem_tx_prepare(smbox->shmem, m);
40}
41
42static void rx_callback(struct mbox_client *cl, void *m)
43{
44 struct scmi_mailbox *smbox = client_to_scmi_mailbox(cl);
45
46 scmi_rx_callback(smbox->cinfo, shmem_read_header(smbox->shmem));
47}
48
49static bool mailbox_chan_available(struct device *dev, int idx)
50{
51 return !of_parse_phandle_with_args(dev->of_node, "mboxes",
52 "#mbox-cells", idx, NULL);
53}
54
55static int mailbox_chan_setup(struct scmi_chan_info *cinfo, struct device *dev,
56 bool tx)
57{
58 const char *desc = tx ? "Tx" : "Rx";
59 struct device *cdev = cinfo->dev;
60 struct scmi_mailbox *smbox;
61 struct device_node *shmem;
62 int ret, idx = tx ? 0 : 1;
63 struct mbox_client *cl;
64 resource_size_t size;
65 struct resource res;
66
67 smbox = devm_kzalloc(dev, sizeof(*smbox), GFP_KERNEL);
68 if (!smbox)
69 return -ENOMEM;
70
71 shmem = of_parse_phandle(cdev->of_node, "shmem", idx);
72 ret = of_address_to_resource(shmem, 0, &res);
73 of_node_put(shmem);
74 if (ret) {
75 dev_err(cdev, "failed to get SCMI %s shared memory\n", desc);
76 return ret;
77 }
78
79 size = resource_size(&res);
80 smbox->shmem = devm_ioremap(dev, res.start, size);
81 if (!smbox->shmem) {
82 dev_err(dev, "failed to ioremap SCMI %s shared memory\n", desc);
83 return -EADDRNOTAVAIL;
84 }
85
86 cl = &smbox->cl;
87 cl->dev = cdev;
88 cl->tx_prepare = tx ? tx_prepare : NULL;
89 cl->rx_callback = rx_callback;
90 cl->tx_block = false;
91 cl->knows_txdone = tx;
92
93 smbox->chan = mbox_request_channel(cl, tx ? 0 : 1);
94 if (IS_ERR(smbox->chan)) {
95 ret = PTR_ERR(smbox->chan);
96 if (ret != -EPROBE_DEFER)
97 dev_err(cdev, "failed to request SCMI %s mailbox\n",
98 tx ? "Tx" : "Rx");
99 return ret;
100 }
101
102 cinfo->transport_info = smbox;
103 smbox->cinfo = cinfo;
104
105 return 0;
106}
107
108static int mailbox_chan_free(int id, void *p, void *data)
109{
110 struct scmi_chan_info *cinfo = p;
111 struct scmi_mailbox *smbox = cinfo->transport_info;
112
113 if (!IS_ERR(smbox->chan)) {
114 mbox_free_channel(smbox->chan);
115 cinfo->transport_info = NULL;
116 smbox->chan = NULL;
117 smbox->cinfo = NULL;
118 }
119
120 scmi_free_channel(cinfo, data, id);
121
122 return 0;
123}
124
125static int mailbox_send_message(struct scmi_chan_info *cinfo,
126 struct scmi_xfer *xfer)
127{
128 struct scmi_mailbox *smbox = cinfo->transport_info;
129 int ret;
130
131 ret = mbox_send_message(smbox->chan, xfer);
132
133 /* mbox_send_message returns non-negative value on success, so reset */
134 if (ret > 0)
135 ret = 0;
136
137 return ret;
138}
139
140static void mailbox_mark_txdone(struct scmi_chan_info *cinfo, int ret)
141{
142 struct scmi_mailbox *smbox = cinfo->transport_info;
143
144 /*
145 * NOTE: we might prefer not to need the mailbox ticker to manage the
146 * transfer queueing since the protocol layer queues things by itself.
147 * Unfortunately, we have to kick the mailbox framework after we have
148 * received our message.
149 */
150 mbox_client_txdone(smbox->chan, ret);
151}
152
153static void mailbox_fetch_response(struct scmi_chan_info *cinfo,
154 struct scmi_xfer *xfer)
155{
156 struct scmi_mailbox *smbox = cinfo->transport_info;
157
158 shmem_fetch_response(smbox->shmem, xfer);
159}
160
161static bool
162mailbox_poll_done(struct scmi_chan_info *cinfo, struct scmi_xfer *xfer)
163{
164 struct scmi_mailbox *smbox = cinfo->transport_info;
165
166 return shmem_poll_done(smbox->shmem, xfer);
167}
168
169static struct scmi_transport_ops scmi_mailbox_ops = {
170 .chan_available = mailbox_chan_available,
171 .chan_setup = mailbox_chan_setup,
172 .chan_free = mailbox_chan_free,
173 .send_message = mailbox_send_message,
174 .mark_txdone = mailbox_mark_txdone,
175 .fetch_response = mailbox_fetch_response,
176 .poll_done = mailbox_poll_done,
177};
178
179const struct scmi_desc scmi_mailbox_desc = {
180 .ops = &scmi_mailbox_ops,
181 .max_rx_timeout_ms = 30, /* We may increase this if required */
182 .max_msg = 20, /* Limited by MBOX_TX_QUEUE_LEN */
183 .max_msg_size = 128,
184};
drivers/firmware/arm_scmi/perf.c+1−1
@@ -89,7 +89,7 @@ struct scmi_msg_resp_perf_describe_levels { · 88 unmodified lines
89 __le32 power;89 __le32 power;
90 __le16 transition_latency_us;90 __le16 transition_latency_us;
91 __le16 reserved;91 __le16 reserved;
92 } opp[0];92 } opp[];
93};93};
94 94
95struct scmi_perf_get_fc_info {95struct scmi_perf_get_fc_info {
drivers/firmware/arm_scmi/shmem.c+83−0
@@ -0,0 +1,83 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * For transport using shared mem structure.
4 *
5 * Copyright (C) 2019 ARM Ltd.
6 */
7
8#include <linux/io.h>
9#include <linux/processor.h>
10#include <linux/types.h>
11
12#include "common.h"
13
14/*
15 * SCMI specification requires all parameters, message headers, return
16 * arguments or any protocol data to be expressed in little endian
17 * format only.
18 */
19struct scmi_shared_mem {
20 __le32 reserved;
21 __le32 channel_status;
22#define SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR BIT(1)
23#define SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE BIT(0)
24 __le32 reserved1[2];
25 __le32 flags;
26#define SCMI_SHMEM_FLAG_INTR_ENABLED BIT(0)
27 __le32 length;
28 __le32 msg_header;
29 u8 msg_payload[];
30};
31
32void shmem_tx_prepare(struct scmi_shared_mem __iomem *shmem,
33 struct scmi_xfer *xfer)
34{
35 /*
36 * Ideally channel must be free by now unless OS timeout last
37 * request and platform continued to process the same, wait
38 * until it releases the shared memory, otherwise we may endup
39 * overwriting its response with new message payload or vice-versa
40 */
41 spin_until_cond(ioread32(&shmem->channel_status) &
42 SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
43 /* Mark channel busy + clear error */
44 iowrite32(0x0, &shmem->channel_status);
45 iowrite32(xfer->hdr.poll_completion ? 0 : SCMI_SHMEM_FLAG_INTR_ENABLED,
46 &shmem->flags);
47 iowrite32(sizeof(shmem->msg_header) + xfer->tx.len, &shmem->length);
48 iowrite32(pack_scmi_header(&xfer->hdr), &shmem->msg_header);
49 if (xfer->tx.buf)
50 memcpy_toio(shmem->msg_payload, xfer->tx.buf, xfer->tx.len);
51}
52
53u32 shmem_read_header(struct scmi_shared_mem __iomem *shmem)
54{
55 return ioread32(&shmem->msg_header);
56}
57
58void shmem_fetch_response(struct scmi_shared_mem __iomem *shmem,
59 struct scmi_xfer *xfer)
60{
61 xfer->hdr.status = ioread32(shmem->msg_payload);
62 /* Skip the length of header and status in shmem area i.e 8 bytes */
63 xfer->rx.len = min_t(size_t, xfer->rx.len,
64 ioread32(&shmem->length) - 8);
65
66 /* Take a copy to the rx buffer.. */
67 memcpy_fromio(xfer->rx.buf, shmem->msg_payload + 4, xfer->rx.len);
68}
69
70bool shmem_poll_done(struct scmi_shared_mem __iomem *shmem,
71 struct scmi_xfer *xfer)
72{
73 u16 xfer_id;
74
75 xfer_id = MSG_XTRACT_TOKEN(ioread32(&shmem->msg_header));
76
77 if (xfer->hdr.seq != xfer_id)
78 return false;
79
80 return ioread32(&shmem->channel_status) &
81 (SCMI_SHMEM_CHAN_STAT_CHANNEL_ERROR |
82 SCMI_SHMEM_CHAN_STAT_CHANNEL_FREE);
83}
drivers/firmware/arm_scpi.c+2−2
@@ -262,12 +262,12 @@ struct scpi_drvinfo { · 261 unmodified lines
262struct scpi_shared_mem {262struct scpi_shared_mem {
263 __le32 command;263 __le32 command;
264 __le32 status;264 __le32 status;
265 u8 payload[0];265 u8 payload[];
266} __packed;266} __packed;
267 267
268struct legacy_scpi_shared_mem {268struct legacy_scpi_shared_mem {
269 __le32 status;269 __le32 status;
270 u8 payload[0];270 u8 payload[];
271} __packed;271} __packed;
272 272
273struct scp_capabilities {273struct scp_capabilities {
drivers/firmware/imx/scu-pd.c+12−1
@@ -93,7 +93,7 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { · 92 unmodified lines
93 { "kpp", IMX_SC_R_KPP, 1, false, 0 },93 { "kpp", IMX_SC_R_KPP, 1, false, 0 },
94 { "fspi", IMX_SC_R_FSPI_0, 2, true, 0 },94 { "fspi", IMX_SC_R_FSPI_0, 2, true, 0 },
95 { "mu_a", IMX_SC_R_MU_0A, 14, true, 0 },95 { "mu_a", IMX_SC_R_MU_0A, 14, true, 0 },
96 { "mu_b", IMX_SC_R_MU_13B, 1, true, 13 },96 { "mu_b", IMX_SC_R_MU_5B, 9, true, 5 },
97 97
98 /* CONN SS */98 /* CONN SS */
99 { "usb", IMX_SC_R_USB_0, 2, true, 0 },99 { "usb", IMX_SC_R_USB_0, 2, true, 0 },
@@ -109,6 +109,7 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { · 9 unmodified lines
109 { "audio-pll0", IMX_SC_R_AUDIO_PLL_0, 1, false, 0 },109 { "audio-pll0", IMX_SC_R_AUDIO_PLL_0, 1, false, 0 },
110 { "audio-pll1", IMX_SC_R_AUDIO_PLL_1, 1, false, 0 },110 { "audio-pll1", IMX_SC_R_AUDIO_PLL_1, 1, false, 0 },
111 { "audio-clk-0", IMX_SC_R_AUDIO_CLK_0, 1, false, 0 },111 { "audio-clk-0", IMX_SC_R_AUDIO_CLK_0, 1, false, 0 },
112 { "audio-clk-1", IMX_SC_R_AUDIO_CLK_1, 1, false, 0 },
112 { "dma0-ch", IMX_SC_R_DMA_0_CH0, 16, true, 0 },113 { "dma0-ch", IMX_SC_R_DMA_0_CH0, 16, true, 0 },
113 { "dma1-ch", IMX_SC_R_DMA_1_CH0, 16, true, 0 },114 { "dma1-ch", IMX_SC_R_DMA_1_CH0, 16, true, 0 },
114 { "dma2-ch", IMX_SC_R_DMA_2_CH0, 5, true, 0 },115 { "dma2-ch", IMX_SC_R_DMA_2_CH0, 5, true, 0 },
@@ -116,7 +117,13 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { · 1 unmodified line
116 { "asrc1", IMX_SC_R_ASRC_1, 1, false, 0 },117 { "asrc1", IMX_SC_R_ASRC_1, 1, false, 0 },
117 { "esai0", IMX_SC_R_ESAI_0, 1, false, 0 },118 { "esai0", IMX_SC_R_ESAI_0, 1, false, 0 },
118 { "spdif0", IMX_SC_R_SPDIF_0, 1, false, 0 },119 { "spdif0", IMX_SC_R_SPDIF_0, 1, false, 0 },
120 { "spdif1", IMX_SC_R_SPDIF_1, 1, false, 0 },
119 { "sai", IMX_SC_R_SAI_0, 3, true, 0 },121 { "sai", IMX_SC_R_SAI_0, 3, true, 0 },
122 { "sai3", IMX_SC_R_SAI_3, 1, false, 0 },
123 { "sai4", IMX_SC_R_SAI_4, 1, false, 0 },
124 { "sai5", IMX_SC_R_SAI_5, 1, false, 0 },
125 { "sai6", IMX_SC_R_SAI_6, 1, false, 0 },
126 { "sai7", IMX_SC_R_SAI_7, 1, false, 0 },
120 { "amix", IMX_SC_R_AMIX, 1, false, 0 },127 { "amix", IMX_SC_R_AMIX, 1, false, 0 },
121 { "mqs0", IMX_SC_R_MQS_0, 1, false, 0 },128 { "mqs0", IMX_SC_R_MQS_0, 1, false, 0 },
122 { "dsp", IMX_SC_R_DSP, 1, false, 0 },129 { "dsp", IMX_SC_R_DSP, 1, false, 0 },
@@ -158,6 +165,10 @@ static const struct imx_sc_pd_range imx8qxp_scu_pd_ranges[] = { · 35 unmodified lines
158 /* DC SS */165 /* DC SS */
159 { "dc0", IMX_SC_R_DC_0, 1, false, 0 },166 { "dc0", IMX_SC_R_DC_0, 1, false, 0 },
160 { "dc0-pll", IMX_SC_R_DC_0_PLL_0, 2, true, 0 },167 { "dc0-pll", IMX_SC_R_DC_0_PLL_0, 2, true, 0 },
168
169 /* CM40 SS */
170 { "cm40_i2c", IMX_SC_R_M4_0_I2C, 1, 0 },
171 { "cm40_intmux", IMX_SC_R_M4_0_INTMUX, 1, 0 },
161};172};
162 173
163static const struct imx_sc_pd_soc imx8qxp_scu_pd = {174static const struct imx_sc_pd_soc imx8qxp_scu_pd = {
drivers/firmware/meson/meson_sm.c+2−0
@@ -44,6 +44,8 @@ static const struct meson_sm_chip gxbb_chip = { · 43 unmodified lines
44 CMD(SM_EFUSE_WRITE, 0x82000031),44 CMD(SM_EFUSE_WRITE, 0x82000031),
45 CMD(SM_EFUSE_USER_MAX, 0x82000033),45 CMD(SM_EFUSE_USER_MAX, 0x82000033),
46 CMD(SM_GET_CHIP_ID, 0x82000044),46 CMD(SM_GET_CHIP_ID, 0x82000044),
47 CMD(SM_A1_PWRC_SET, 0x82000093),
48 CMD(SM_A1_PWRC_GET, 0x82000095),
47 { /* sentinel */ },49 { /* sentinel */ },
48 },50 },
49};51};
drivers/firmware/tegra/Kconfig+1−1
@@ -7,7 +7,7 @@ config TEGRA_IVC · 6 unmodified lines
7 help7 help
8 IVC (Inter-VM Communication) protocol is part of the IPC8 IVC (Inter-VM Communication) protocol is part of the IPC
9 (Inter Processor Communication) framework on Tegra. It maintains the9 (Inter Processor Communication) framework on Tegra. It maintains the
10 data and the different commuication channels in SysRAM or RAM and10 data and the different communication channels in SysRAM or RAM and
11 keeps the content is synchronization between host CPU and remote11 keeps the content is synchronization between host CPU and remote
12 processors.12 processors.
13 13
drivers/gpu/drm/omapdrm/dss/dss.c+22−3
@@ -1348,9 +1348,15 @@ static int dss_component_compare(struct device *dev, void *data) · 1347 unmodified lines
1348 return dev == child;1348 return dev == child;
1349}1349}
1350 1350
1351struct dss_component_match_data {
1352 struct device *dev;
1353 struct component_match **match;
1354};
1355
1351static int dss_add_child_component(struct device *dev, void *data)1356static int dss_add_child_component(struct device *dev, void *data)
1352{1357{
1353 struct component_match **match = data;1358 struct dss_component_match_data *cmatch = data;
1359 struct component_match **match = cmatch->match;
1354 1360
1355 /*1361 /*
1356 * HACK1362 * HACK
@@ -1361,7 +1367,17 @@ static int dss_add_child_component(struct device *dev, void *data) · 4 unmodified lines
1361 if (strstr(dev_name(dev), "rfbi"))1367 if (strstr(dev_name(dev), "rfbi"))
1362 return 0;1368 return 0;
1363 1369
1364 component_match_add(dev->parent, match, dss_component_compare, dev);1370 /*
1371 * Handle possible interconnect target modules defined within the DSS.
1372 * The DSS components can be children of an interconnect target module
1373 * after the device tree has been updated for the module data.
1374 * See also omapdss_boot_init() for compatible fixup.
1375 */
1376 if (strstr(dev_name(dev), "target-module"))
1377 return device_for_each_child(dev, cmatch,
1378 dss_add_child_component);
1379
1380 component_match_add(cmatch->dev, match, dss_component_compare, dev);
1365 1381
1366 return 0;1382 return 0;
1367}1383}
@@ -1404,6 +1420,7 @@ static int dss_probe_hardware(struct dss_device *dss) · 36 unmodified lines
1404static int dss_probe(struct platform_device *pdev)1420static int dss_probe(struct platform_device *pdev)
1405{1421{
1406 const struct soc_device_attribute *soc;1422 const struct soc_device_attribute *soc;
1423 struct dss_component_match_data cmatch;
1407 struct component_match *match = NULL;1424 struct component_match *match = NULL;
1408 struct resource *dss_mem;1425 struct resource *dss_mem;
1409 struct dss_device *dss;1426 struct dss_device *dss;
@@ -1481,7 +1498,9 @@ static int dss_probe(struct platform_device *pdev) · 71 unmodified lines
1481 1498
1482 omapdss_gather_components(&pdev->dev);1499 omapdss_gather_components(&pdev->dev);
1483 1500
1484 device_for_each_child(&pdev->dev, &match, dss_add_child_component);1501 cmatch.dev = &pdev->dev;
1502 cmatch.match = &match;
1503 device_for_each_child(&pdev->dev, &cmatch, dss_add_child_component);
1485 1504
1486 r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match);1505 r = component_master_add_with_match(&pdev->dev, &dss_component_ops, match);
1487 if (r)1506 if (r)
drivers/gpu/drm/omapdrm/dss/omapdss-boot-init.c+17−8
@@ -178,9 +178,24 @@ static const struct of_device_id omapdss_of_fixups_whitelist[] __initconst = { · 177 unmodified lines
178 {},178 {},
179};179};
180 180
181static void __init omapdss_find_children(struct device_node *np)
182{
183 struct device_node *child;
184
185 for_each_available_child_of_node(np, child) {
186 if (!of_find_property(child, "compatible", NULL))
187 continue;
188
189 omapdss_walk_device(child, true);
190
191 if (of_device_is_compatible(child, "ti,sysc"))
192 omapdss_find_children(child);
193 }
194}
195
181static int __init omapdss_boot_init(void)196static int __init omapdss_boot_init(void)
182{197{
183 struct device_node *dss, *child;198 struct device_node *dss;
184 199
185 INIT_LIST_HEAD(&dss_conv_list);200 INIT_LIST_HEAD(&dss_conv_list);
186 201
@@ -190,13 +205,7 @@ static int __init omapdss_boot_init(void) · 3 unmodified lines
190 goto put_node;205 goto put_node;
191 206
192 omapdss_walk_device(dss, true);207 omapdss_walk_device(dss, true);
193 208 omapdss_find_children(dss);
194 for_each_available_child_of_node(dss, child) {
195 if (!of_find_property(child, "compatible", NULL))
196 continue;
197
198 omapdss_walk_device(child, true);
199 }
200 209
201 while (!list_empty(&dss_conv_list)) {210 while (!list_empty(&dss_conv_list)) {
202 struct dss_conv_node *n;211 struct dss_conv_node *n;
drivers/memory/tegra/tegra124-emc.c+5−0
@@ -1158,6 +1158,11 @@ static void emc_debugfs_init(struct device *dev, struct tegra_emc *emc) · 1157 unmodified lines
1158 emc->debugfs.max_rate = emc->timings[i].rate;1158 emc->debugfs.max_rate = emc->timings[i].rate;
1159 }1159 }
1160 1160
1161 if (!emc->num_timings) {
1162 emc->debugfs.min_rate = clk_get_rate(emc->clk);
1163 emc->debugfs.max_rate = emc->debugfs.min_rate;
1164 }
1165
1161 err = clk_set_rate_range(emc->clk, emc->debugfs.min_rate,1166 err = clk_set_rate_range(emc->clk, emc->debugfs.min_rate,
1162 emc->debugfs.max_rate);1167 emc->debugfs.max_rate);
1163 if (err < 0) {1168 if (err < 0) {
drivers/memory/tegra/tegra20-emc.c+5−0
@@ -628,6 +628,11 @@ static void tegra_emc_debugfs_init(struct tegra_emc *emc) · 627 unmodified lines
628 emc->debugfs.max_rate = emc->timings[i].rate;628 emc->debugfs.max_rate = emc->timings[i].rate;
629 }629 }
630 630
631 if (!emc->num_timings) {
632 emc->debugfs.min_rate = clk_get_rate(emc->clk);
633 emc->debugfs.max_rate = emc->debugfs.min_rate;
634 }
635
631 err = clk_set_rate_range(emc->clk, emc->debugfs.min_rate,636 err = clk_set_rate_range(emc->clk, emc->debugfs.min_rate,
632 emc->debugfs.max_rate);637 emc->debugfs.max_rate);
633 if (err < 0) {638 if (err < 0) {
drivers/memory/tegra/tegra30-emc.c+5−0
@@ -1256,6 +1256,11 @@ static void tegra_emc_debugfs_init(struct tegra_emc *emc) · 1255 unmodified lines
1256 emc->debugfs.max_rate = emc->timings[i].rate;1256 emc->debugfs.max_rate = emc->timings[i].rate;
1257 }1257 }
1258 1258
1259 if (!emc->num_timings) {
1260 emc->debugfs.min_rate = clk_get_rate(emc->clk);
1261 emc->debugfs.max_rate = emc->debugfs.min_rate;
1262 }
1263
1259 err = clk_set_rate_range(emc->clk, emc->debugfs.min_rate,1264 err = clk_set_rate_range(emc->clk, emc->debugfs.min_rate,
1260 emc->debugfs.max_rate);1265 emc->debugfs.max_rate);
1261 if (err < 0) {1266 if (err < 0) {
drivers/soc/Makefile+1−1
@@ -11,7 +11,7 @@ obj-$(CONFIG_ARCH_DOVE) += dove/ · 10 unmodified lines
11obj-$(CONFIG_MACH_DOVE) += dove/11obj-$(CONFIG_MACH_DOVE) += dove/
12obj-y += fsl/12obj-y += fsl/
13obj-$(CONFIG_ARCH_GEMINI) += gemini/13obj-$(CONFIG_ARCH_GEMINI) += gemini/
14obj-$(CONFIG_ARCH_MXC) += imx/14obj-y += imx/
15obj-$(CONFIG_ARCH_IXP4XX) += ixp4xx/15obj-$(CONFIG_ARCH_IXP4XX) += ixp4xx/
16obj-$(CONFIG_SOC_XWAY) += lantiq/16obj-$(CONFIG_SOC_XWAY) += lantiq/
17obj-y += mediatek/17obj-y += mediatek/
drivers/soc/amlogic/Kconfig+13−0
@@ -48,6 +48,19 @@ config MESON_EE_PM_DOMAINS · 47 unmodified lines
48 Say yes to expose Amlogic Meson Everything-Else Power Domains as48 Say yes to expose Amlogic Meson Everything-Else Power Domains as
49 Generic Power Domains.49 Generic Power Domains.
50 50
51config MESON_SECURE_PM_DOMAINS
52 bool "Amlogic Meson Secure Power Domains driver"
53 depends on (ARCH_MESON || COMPILE_TEST) && MESON_SM
54 depends on PM && OF
55 depends on HAVE_ARM_SMCCC
56 default ARCH_MESON
57 select PM_GENERIC_DOMAINS
58 select PM_GENERIC_DOMAINS_OF
59 help
60 Support for the power controller on Amlogic A1/C1 series.
61 Say yes to expose Amlogic Meson Secure Power Domains as Generic
62 Power Domains.
63
51config MESON_MX_SOCINFO64config MESON_MX_SOCINFO
52 bool "Amlogic Meson MX SoC Information driver"65 bool "Amlogic Meson MX SoC Information driver"
53 depends on ARCH_MESON || COMPILE_TEST66 depends on ARCH_MESON || COMPILE_TEST
drivers/soc/amlogic/Makefile+1−0
@@ -5,3 +5,4 @@ obj-$(CONFIG_MESON_GX_SOCINFO) += meson-gx-socinfo.o · 4 unmodified lines
5obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o5obj-$(CONFIG_MESON_GX_PM_DOMAINS) += meson-gx-pwrc-vpu.o
6obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o6obj-$(CONFIG_MESON_MX_SOCINFO) += meson-mx-socinfo.o
7obj-$(CONFIG_MESON_EE_PM_DOMAINS) += meson-ee-pwrc.o7obj-$(CONFIG_MESON_EE_PM_DOMAINS) += meson-ee-pwrc.o
8obj-$(CONFIG_MESON_SECURE_PM_DOMAINS) += meson-secure-pwrc.o
drivers/soc/amlogic/meson-secure-pwrc.c+204−0
@@ -0,0 +1,204 @@
1// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
2/*
3 * Copyright (c) 2019 Amlogic, Inc.
4 * Author: Jianxin Pan <jianxin.pan@amlogic.com>
5 */
6
7#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
8
9#include <linux/io.h>
10#include <linux/of_device.h>
11#include <linux/platform_device.h>
12#include <linux/pm_domain.h>
13#include <dt-bindings/power/meson-a1-power.h>
14#include <linux/arm-smccc.h>
15#include <linux/firmware/meson/meson_sm.h>
16
17#define PWRC_ON 1
18#define PWRC_OFF 0
19
20struct meson_secure_pwrc_domain {
21 struct generic_pm_domain base;
22 unsigned int index;
23 struct meson_secure_pwrc *pwrc;
24};
25
26struct meson_secure_pwrc {
27 struct meson_secure_pwrc_domain *domains;
28 struct genpd_onecell_data xlate;
29 struct meson_sm_firmware *fw;
30};
31
32struct meson_secure_pwrc_domain_desc {
33 unsigned int index;
34 unsigned int flags;
35 char *name;
36 bool (*is_off)(struct meson_secure_pwrc_domain *pwrc_domain);
37};
38
39struct meson_secure_pwrc_domain_data {
40 unsigned int count;
41 struct meson_secure_pwrc_domain_desc *domains;
42};
43
44static bool pwrc_secure_is_off(struct meson_secure_pwrc_domain *pwrc_domain)
45{
46 int is_off = 1;
47
48 if (meson_sm_call(pwrc_domain->pwrc->fw, SM_A1_PWRC_GET, &is_off,
49 pwrc_domain->index, 0, 0, 0, 0) < 0)
50 pr_err("failed to get power domain status\n");
51
52 return is_off;
53}
54
55static int meson_secure_pwrc_off(struct generic_pm_domain *domain)
56{
57 int ret = 0;
58 struct meson_secure_pwrc_domain *pwrc_domain =
59 container_of(domain, struct meson_secure_pwrc_domain, base);
60
61 if (meson_sm_call(pwrc_domain->pwrc->fw, SM_A1_PWRC_SET, NULL,
62 pwrc_domain->index, PWRC_OFF, 0, 0, 0) < 0) {
63 pr_err("failed to set power domain off\n");
64 ret = -EINVAL;
65 }
66
67 return ret;
68}
69
70static int meson_secure_pwrc_on(struct generic_pm_domain *domain)
71{
72 int ret = 0;
73 struct meson_secure_pwrc_domain *pwrc_domain =
74 container_of(domain, struct meson_secure_pwrc_domain, base);
75
76 if (meson_sm_call(pwrc_domain->pwrc->fw, SM_A1_PWRC_SET, NULL,
77 pwrc_domain->index, PWRC_ON, 0, 0, 0) < 0) {
78 pr_err("failed to set power domain on\n");
79 ret = -EINVAL;
80 }
81
82 return ret;
83}
84
85#define SEC_PD(__name, __flag) \
86[PWRC_##__name##_ID] = \
87{ \
88 .name = #__name, \
89 .index = PWRC_##__name##_ID, \
90 .is_off = pwrc_secure_is_off, \
91 .flags = __flag, \
92}
93
94static struct meson_secure_pwrc_domain_desc a1_pwrc_domains[] = {
95 SEC_PD(DSPA, 0),
96 SEC_PD(DSPB, 0),
97 /* UART should keep working in ATF after suspend and before resume */
98 SEC_PD(UART, GENPD_FLAG_ALWAYS_ON),
99 /* DMC is for DDR PHY ana/dig and DMC, and should be always on */
100 SEC_PD(DMC, GENPD_FLAG_ALWAYS_ON),
101 SEC_PD(I2C, 0),
102 SEC_PD(PSRAM, 0),
103 SEC_PD(ACODEC, 0),
104 SEC_PD(AUDIO, 0),
105 SEC_PD(OTP, 0),
106 SEC_PD(DMA, 0),
107 SEC_PD(SD_EMMC, 0),
108 SEC_PD(RAMA, 0),
109 /* SRAMB is used as ATF runtime memory, and should be always on */
110 SEC_PD(RAMB, GENPD_FLAG_ALWAYS_ON),
111 SEC_PD(IR, 0),
112 SEC_PD(SPICC, 0),
113 SEC_PD(SPIFC, 0),
114 SEC_PD(USB, 0),
115 /* NIC is for the Arm NIC-400 interconnect, and should be always on */
116 SEC_PD(NIC, GENPD_FLAG_ALWAYS_ON),
117 SEC_PD(PDMIN, 0),
118 SEC_PD(RSA, 0),
119};
120
121static int meson_secure_pwrc_probe(struct platform_device *pdev)
122{
123 int i;
124 struct device_node *sm_np;
125 struct meson_secure_pwrc *pwrc;
126 const struct meson_secure_pwrc_domain_data *match;
127
128 match = of_device_get_match_data(&pdev->dev);
129 if (!match) {
130 dev_err(&pdev->dev, "failed to get match data\n");
131 return -ENODEV;
132 }
133
134 sm_np = of_find_compatible_node(NULL, NULL, "amlogic,meson-gxbb-sm");
135 if (!sm_np) {
136 dev_err(&pdev->dev, "no secure-monitor node\n");
137 return -ENODEV;
138 }
139
140 pwrc = devm_kzalloc(&pdev->dev, sizeof(*pwrc), GFP_KERNEL);
141 if (!pwrc)
142 return -ENOMEM;
143
144 pwrc->fw = meson_sm_get(sm_np);
145 of_node_put(sm_np);
146 if (!pwrc->fw)
147 return -EPROBE_DEFER;
148
149 pwrc->xlate.domains = devm_kcalloc(&pdev->dev, match->count,
150 sizeof(*pwrc->xlate.domains),
151 GFP_KERNEL);
152 if (!pwrc->xlate.domains)
153 return -ENOMEM;
154
155 pwrc->domains = devm_kcalloc(&pdev->dev, match->count,
156 sizeof(*pwrc->domains), GFP_KERNEL);
157 if (!pwrc->domains)
158 return -ENOMEM;
159
160 pwrc->xlate.num_domains = match->count;
161 platform_set_drvdata(pdev, pwrc);
162
163 for (i = 0 ; i < match->count ; ++i) {
164 struct meson_secure_pwrc_domain *dom = &pwrc->domains[i];
165
166 if (!match->domains[i].index)
167 continue;
168
169 dom->pwrc = pwrc;
170 dom->index = match->domains[i].index;
171 dom->base.name = match->domains[i].name;
172 dom->base.flags = match->domains[i].flags;
173 dom->base.power_on = meson_secure_pwrc_on;
174 dom->base.power_off = meson_secure_pwrc_off;
175
176 pm_genpd_init(&dom->base, NULL, match->domains[i].is_off(dom));
177
178 pwrc->xlate.domains[i] = &dom->base;
179 }
180
181 return of_genpd_add_provider_onecell(pdev->dev.of_node, &pwrc->xlate);
182}
183
184static struct meson_secure_pwrc_domain_data meson_secure_a1_pwrc_data = {
185 .domains = a1_pwrc_domains,
186 .count = ARRAY_SIZE(a1_pwrc_domains),
187};
188
189static const struct of_device_id meson_secure_pwrc_match_table[] = {
190 {
191 .compatible = "amlogic,meson-a1-pwrc",
192 .data = &meson_secure_a1_pwrc_data,
193 },
194 { /* sentinel */ }
195};
196
197static struct platform_driver meson_secure_pwrc_driver = {
198 .probe = meson_secure_pwrc_probe,
199 .driver = {
200 .name = "meson_secure_pwrc",
201 .of_match_table = meson_secure_pwrc_match_table,
202 },
203};
204builtin_platform_driver(meson_secure_pwrc_driver);
drivers/soc/fsl/dpio/dpio-service.c+66−3
@@ -1,7 +1,7 @@
1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2/*2/*
3 * Copyright 2014-2016 Freescale Semiconductor Inc.3 * Copyright 2014-2016 Freescale Semiconductor Inc.
4 * Copyright 2016 NXP4 * Copyright 2016-2019 NXP
5 *5 *
6 */6 */
7#include <linux/types.h>7#include <linux/types.h>
@@ -432,6 +432,69 @@ int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, · 424 unmodified lines
432}432}
433EXPORT_SYMBOL(dpaa2_io_service_enqueue_fq);433EXPORT_SYMBOL(dpaa2_io_service_enqueue_fq);
434 434
435/**
436 * dpaa2_io_service_enqueue_multiple_fq() - Enqueue multiple frames
437 * to a frame queue using one fqid.
438 * @d: the given DPIO service.
439 * @fqid: the given frame queue id.
440 * @fd: the frame descriptor which is enqueued.
441 * @nb: number of frames to be enqueud
442 *
443 * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready,
444 * or -ENODEV if there is no dpio service.
445 */
446int dpaa2_io_service_enqueue_multiple_fq(struct dpaa2_io *d,
447 u32 fqid,
448 const struct dpaa2_fd *fd,
449 int nb)
450{
451 struct qbman_eq_desc ed;
452
453 d = service_select(d);
454 if (!d)
455 return -ENODEV;
456
457 qbman_eq_desc_clear(&ed);
458 qbman_eq_desc_set_no_orp(&ed, 0);
459 qbman_eq_desc_set_fq(&ed, fqid);
460
461 return qbman_swp_enqueue_multiple(d->swp, &ed, fd, 0, nb);
462}
463EXPORT_SYMBOL(dpaa2_io_service_enqueue_multiple_fq);
464
465/**
466 * dpaa2_io_service_enqueue_multiple_desc_fq() - Enqueue multiple frames
467 * to different frame queue using a list of fqids.
468 * @d: the given DPIO service.
469 * @fqid: the given list of frame queue ids.
470 * @fd: the frame descriptor which is enqueued.
471 * @nb: number of frames to be enqueud
472 *
473 * Return 0 for successful enqueue, -EBUSY if the enqueue ring is not ready,
474 * or -ENODEV if there is no dpio service.
475 */
476int dpaa2_io_service_enqueue_multiple_desc_fq(struct dpaa2_io *d,
477 u32 *fqid,
478 const struct dpaa2_fd *fd,
479 int nb)
480{
481 int i;
482 struct qbman_eq_desc ed[32];
483
484 d = service_select(d);
485 if (!d)
486 return -ENODEV;
487
488 for (i = 0; i < nb; i++) {
489 qbman_eq_desc_clear(&ed[i]);
490 qbman_eq_desc_set_no_orp(&ed[i], 0);
491 qbman_eq_desc_set_fq(&ed[i], fqid[i]);
492 }
493
494 return qbman_swp_enqueue_multiple_desc(d->swp, &ed[0], fd, nb);
495}
496EXPORT_SYMBOL(dpaa2_io_service_enqueue_multiple_desc_fq);
497
435/**498/**
436 * dpaa2_io_service_enqueue_qd() - Enqueue a frame to a QD.499 * dpaa2_io_service_enqueue_qd() - Enqueue a frame to a QD.
437 * @d: the given DPIO service.500 * @d: the given DPIO service.
@@ -526,7 +589,7 @@ EXPORT_SYMBOL_GPL(dpaa2_io_service_acquire); · 88 unmodified lines
526 589
527/**590/**
528 * dpaa2_io_store_create() - Create the dma memory storage for dequeue result.591 * dpaa2_io_store_create() - Create the dma memory storage for dequeue result.
529 * @max_frames: the maximum number of dequeued result for frames, must be <= 16.592 * @max_frames: the maximum number of dequeued result for frames, must be <= 32.
530 * @dev: the device to allow mapping/unmapping the DMAable region.593 * @dev: the device to allow mapping/unmapping the DMAable region.
531 *594 *
532 * The size of the storage is "max_frames*sizeof(struct dpaa2_dq)".595 * The size of the storage is "max_frames*sizeof(struct dpaa2_dq)".
@@ -541,7 +604,7 @@ struct dpaa2_io_store *dpaa2_io_store_create(unsigned int max_frames, · 8 unmodified lines
541 struct dpaa2_io_store *ret;604 struct dpaa2_io_store *ret;
542 size_t size;605 size_t size;
543 606
544 if (!max_frames || (max_frames > 16))607 if (!max_frames || (max_frames > 32))
545 return NULL;608 return NULL;
546 609
547 ret = kmalloc(sizeof(*ret), GFP_KERNEL);610 ret = kmalloc(sizeof(*ret), GFP_KERNEL);
drivers/soc/fsl/dpio/qbman-portal.c+686−81
@@ -1,24 +1,18 @@
1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)1// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause)
2/*2/*
3 * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.3 * Copyright (C) 2014-2016 Freescale Semiconductor, Inc.
4 * Copyright 2016 NXP4 * Copyright 2016-2019 NXP
5 *5 *
6 */6 */
7 7
8#include <asm/cacheflush.h>8#include <asm/cacheflush.h>
9#include <linux/io.h>9#include <linux/io.h>
10#include <linux/slab.h>10#include <linux/slab.h>
11#include <linux/spinlock.h>
11#include <soc/fsl/dpaa2-global.h>12#include <soc/fsl/dpaa2-global.h>
12 13
13#include "qbman-portal.h"14#include "qbman-portal.h"
14 15
15#define QMAN_REV_4000 0x04000000
16#define QMAN_REV_4100 0x04010000
17#define QMAN_REV_4101 0x04010001
18#define QMAN_REV_5000 0x05000000
19
20#define QMAN_REV_MASK 0xffff0000
21
22/* All QBMan command and result structures use this "valid bit" encoding */16/* All QBMan command and result structures use this "valid bit" encoding */
23#define QB_VALID_BIT ((u32)0x80)17#define QB_VALID_BIT ((u32)0x80)
24 18
@@ -28,6 +22,7 @@ · 3 unmodified lines
28 22
29/* CINH register offsets */23/* CINH register offsets */
30#define QBMAN_CINH_SWP_EQCR_PI 0x80024#define QBMAN_CINH_SWP_EQCR_PI 0x800
25#define QBMAN_CINH_SWP_EQCR_CI 0x840
31#define QBMAN_CINH_SWP_EQAR 0x8c026#define QBMAN_CINH_SWP_EQAR 0x8c0
32#define QBMAN_CINH_SWP_CR_RT 0x90027#define QBMAN_CINH_SWP_CR_RT 0x900
33#define QBMAN_CINH_SWP_VDQCR_RT 0x94028#define QBMAN_CINH_SWP_VDQCR_RT 0x940
@@ -51,6 +46,8 @@ · 17 unmodified lines
51#define QBMAN_CENA_SWP_CR 0x60046#define QBMAN_CENA_SWP_CR 0x600
52#define QBMAN_CENA_SWP_RR(vb) (0x700 + ((u32)(vb) >> 1))47#define QBMAN_CENA_SWP_RR(vb) (0x700 + ((u32)(vb) >> 1))
53#define QBMAN_CENA_SWP_VDQCR 0x78048#define QBMAN_CENA_SWP_VDQCR 0x780
49#define QBMAN_CENA_SWP_EQCR_CI 0x840
50#define QBMAN_CENA_SWP_EQCR_CI_MEMBACK 0x1840
54 51
55/* CENA register offsets in memory-backed mode */52/* CENA register offsets in memory-backed mode */
56#define QBMAN_CENA_SWP_DQRR_MEM(n) (0x800 + ((u32)(n) << 6))53#define QBMAN_CENA_SWP_DQRR_MEM(n) (0x800 + ((u32)(n) << 6))
@@ -78,6 +75,12 @@ · 21 unmodified lines
78/* opaque token for static dequeues */75/* opaque token for static dequeues */
79#define QMAN_SDQCR_TOKEN 0xbb76#define QMAN_SDQCR_TOKEN 0xbb
80 77
78#define QBMAN_EQCR_DCA_IDXMASK 0x0f
79#define QBMAN_ENQUEUE_FLAG_DCA (1ULL << 31)
80
81#define EQ_DESC_SIZE_WITHOUT_FD 29
82#define EQ_DESC_SIZE_FD_START 32
83
81enum qbman_sdqcr_dct {84enum qbman_sdqcr_dct {
82 qbman_sdqcr_dct_null = 0,85 qbman_sdqcr_dct_null = 0,
83 qbman_sdqcr_dct_prio_ics,86 qbman_sdqcr_dct_prio_ics,
@@ -90,6 +93,82 @@ enum qbman_sdqcr_fc { · 6 unmodified lines
90 qbman_sdqcr_fc_up_to_3 = 193 qbman_sdqcr_fc_up_to_3 = 1
91};94};
92 95
96/* Internal Function declaration */
97static int qbman_swp_enqueue_direct(struct qbman_swp *s,
98 const struct qbman_eq_desc *d,
99 const struct dpaa2_fd *fd);
100static int qbman_swp_enqueue_mem_back(struct qbman_swp *s,
101 const struct qbman_eq_desc *d,
102 const struct dpaa2_fd *fd);
103static int qbman_swp_enqueue_multiple_direct(struct qbman_swp *s,
104 const struct qbman_eq_desc *d,
105 const struct dpaa2_fd *fd,
106 uint32_t *flags,
107 int num_frames);
108static int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s,
109 const struct qbman_eq_desc *d,
110 const struct dpaa2_fd *fd,
111 uint32_t *flags,
112 int num_frames);
113static int
114qbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s,
115 const struct qbman_eq_desc *d,
116 const struct dpaa2_fd *fd,
117 int num_frames);
118static
119int qbman_swp_enqueue_multiple_desc_mem_back(struct qbman_swp *s,
120 const struct qbman_eq_desc *d,
121 const struct dpaa2_fd *fd,
122 int num_frames);
123static int qbman_swp_pull_direct(struct qbman_swp *s,
124 struct qbman_pull_desc *d);
125static int qbman_swp_pull_mem_back(struct qbman_swp *s,
126 struct qbman_pull_desc *d);
127
128const struct dpaa2_dq *qbman_swp_dqrr_next_direct(struct qbman_swp *s);
129const struct dpaa2_dq *qbman_swp_dqrr_next_mem_back(struct qbman_swp *s);
130
131static int qbman_swp_release_direct(struct qbman_swp *s,
132 const struct qbman_release_desc *d,
133 const u64 *buffers,
134 unsigned int num_buffers);
135static int qbman_swp_release_mem_back(struct qbman_swp *s,
136 const struct qbman_release_desc *d,
137 const u64 *buffers,
138 unsigned int num_buffers);
139
140/* Function pointers */
141int (*qbman_swp_enqueue_ptr)(struct qbman_swp *s,
142 const struct qbman_eq_desc *d,
143 const struct dpaa2_fd *fd)
144 = qbman_swp_enqueue_direct;
145
146int (*qbman_swp_enqueue_multiple_ptr)(struct qbman_swp *s,
147 const struct qbman_eq_desc *d,
148 const struct dpaa2_fd *fd,
149 uint32_t *flags,
150 int num_frames)
151 = qbman_swp_enqueue_multiple_direct;
152
153int
154(*qbman_swp_enqueue_multiple_desc_ptr)(struct qbman_swp *s,
155 const struct qbman_eq_desc *d,
156 const struct dpaa2_fd *fd,
157 int num_frames)
158 = qbman_swp_enqueue_multiple_desc_direct;
159
160int (*qbman_swp_pull_ptr)(struct qbman_swp *s, struct qbman_pull_desc *d)
161 = qbman_swp_pull_direct;
162
163const struct dpaa2_dq *(*qbman_swp_dqrr_next_ptr)(struct qbman_swp *s)
164 = qbman_swp_dqrr_next_direct;
165
166int (*qbman_swp_release_ptr)(struct qbman_swp *s,
167 const struct qbman_release_desc *d,
168 const u64 *buffers,
169 unsigned int num_buffers)
170 = qbman_swp_release_direct;
171
93/* Portal Access */172/* Portal Access */
94 173
95static inline u32 qbman_read_register(struct qbman_swp *p, u32 offset)174static inline u32 qbman_read_register(struct qbman_swp *p, u32 offset)
@@ -146,6 +225,15 @@ static inline u32 qbman_set_swp_cfg(u8 max_fill, u8 wn, u8 est, u8 rpm, u8 dcm, · 50 unmodified lines
146 225
147#define QMAN_RT_MODE 0x00000100226#define QMAN_RT_MODE 0x00000100
148 227
228static inline u8 qm_cyc_diff(u8 ringsize, u8 first, u8 last)
229{
230 /* 'first' is included, 'last' is excluded */
231 if (first <= last)
232 return last - first;
233 else
234 return (2 * ringsize) - (first - last);
235}
236
149/**237/**
150 * qbman_swp_init() - Create a functional object representing the given238 * qbman_swp_init() - Create a functional object representing the given
151 * QBMan portal descriptor.239 * QBMan portal descriptor.
@@ -156,11 +244,16 @@ static inline u32 qbman_set_swp_cfg(u8 max_fill, u8 wn, u8 est, u8 rpm, u8 dcm, · 4 unmodified lines
156 */244 */
157struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)245struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
158{246{
159 struct qbman_swp *p = kmalloc(sizeof(*p), GFP_KERNEL);247 struct qbman_swp *p = kzalloc(sizeof(*p), GFP_KERNEL);
160 u32 reg;248 u32 reg;
249 u32 mask_size;
250 u32 eqcr_pi;
161 251
162 if (!p)252 if (!p)
163 return NULL;253 return NULL;
254
255 spin_lock_init(&p->access_spinlock);
256
164 p->desc = d;257 p->desc = d;
165 p->mc.valid_bit = QB_VALID_BIT;258 p->mc.valid_bit = QB_VALID_BIT;
166 p->sdq = 0;259 p->sdq = 0;
@@ -186,25 +279,38 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) · 19 unmodified lines
186 p->addr_cena = d->cena_bar;279 p->addr_cena = d->cena_bar;
187 p->addr_cinh = d->cinh_bar;280 p->addr_cinh = d->cinh_bar;
188 281
189 if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000)282 if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) {
190 memset(p->addr_cena, 0, 64 * 1024);
191 283
192 reg = qbman_set_swp_cfg(p->dqrr.dqrr_size,284 reg = qbman_set_swp_cfg(p->dqrr.dqrr_size,
193 1, /* Writes Non-cacheable */285 1, /* Writes Non-cacheable */
194 0, /* EQCR_CI stashing threshold */286 0, /* EQCR_CI stashing threshold */
195 3, /* RPM: Valid bit mode, RCR in array mode */287 3, /* RPM: RCR in array mode */
196 2, /* DCM: Discrete consumption ack mode */288 2, /* DCM: Discrete consumption ack */
197 3, /* EPM: Valid bit mode, EQCR in array mode */289 2, /* EPM: EQCR in ring mode */
198 1, /* mem stashing drop enable == TRUE */290 1, /* mem stashing drop enable enable */
199 1, /* mem stashing priority == TRUE */291 1, /* mem stashing priority enable */
200 1, /* mem stashing enable == TRUE */292 1, /* mem stashing enable */
201 1, /* dequeue stashing priority == TRUE */293 1, /* dequeue stashing priority enable */
202 0, /* dequeue stashing enable == FALSE */294 0, /* dequeue stashing enable enable */
203 0); /* EQCR_CI stashing priority == FALSE */295 0); /* EQCR_CI stashing priority enable */
204 if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000)296 } else {
297 memset(p->addr_cena, 0, 64 * 1024);
298 reg = qbman_set_swp_cfg(p->dqrr.dqrr_size,
299 1, /* Writes Non-cacheable */
300 1, /* EQCR_CI stashing threshold */
301 3, /* RPM: RCR in array mode */
302 2, /* DCM: Discrete consumption ack */
303 0, /* EPM: EQCR in ring mode */
304 1, /* mem stashing drop enable */
305 1, /* mem stashing priority enable */
306 1, /* mem stashing enable */
307 1, /* dequeue stashing priority enable */
308 0, /* dequeue stashing enable */
309 0); /* EQCR_CI stashing priority enable */
205 reg |= 1 << SWP_CFG_CPBS_SHIFT | /* memory-backed mode */310 reg |= 1 << SWP_CFG_CPBS_SHIFT | /* memory-backed mode */
206 1 << SWP_CFG_VPM_SHIFT | /* VDQCR read triggered mode */311 1 << SWP_CFG_VPM_SHIFT | /* VDQCR read triggered mode */
207 1 << SWP_CFG_CPM_SHIFT; /* CR read triggered mode */312 1 << SWP_CFG_CPM_SHIFT; /* CR read triggered mode */
313 }
208 314
209 qbman_write_register(p, QBMAN_CINH_SWP_CFG, reg);315 qbman_write_register(p, QBMAN_CINH_SWP_CFG, reg);
210 reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG);316 reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG);
@@ -225,6 +331,30 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) · 14 unmodified lines
225 * applied when dequeues from a specific channel are enabled.331 * applied when dequeues from a specific channel are enabled.
226 */332 */
227 qbman_write_register(p, QBMAN_CINH_SWP_SDQCR, 0);333 qbman_write_register(p, QBMAN_CINH_SWP_SDQCR, 0);
334
335 p->eqcr.pi_ring_size = 8;
336 if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000) {
337 p->eqcr.pi_ring_size = 32;
338 qbman_swp_enqueue_ptr =
339 qbman_swp_enqueue_mem_back;
340 qbman_swp_enqueue_multiple_ptr =
341 qbman_swp_enqueue_multiple_mem_back;
342 qbman_swp_enqueue_multiple_desc_ptr =
343 qbman_swp_enqueue_multiple_desc_mem_back;
344 qbman_swp_pull_ptr = qbman_swp_pull_mem_back;
345 qbman_swp_dqrr_next_ptr = qbman_swp_dqrr_next_mem_back;
346 qbman_swp_release_ptr = qbman_swp_release_mem_back;
347 }
348
349 for (mask_size = p->eqcr.pi_ring_size; mask_size > 0; mask_size >>= 1)
350 p->eqcr.pi_ci_mask = (p->eqcr.pi_ci_mask << 1) + 1;
351 eqcr_pi = qbman_read_register(p, QBMAN_CINH_SWP_EQCR_PI);
352 p->eqcr.pi = eqcr_pi & p->eqcr.pi_ci_mask;
353 p->eqcr.pi_vb = eqcr_pi & QB_VALID_BIT;
354 p->eqcr.ci = qbman_read_register(p, QBMAN_CINH_SWP_EQCR_CI)
355 & p->eqcr.pi_ci_mask;
356 p->eqcr.available = p->eqcr.pi_ring_size;
357
228 return p;358 return p;
229}359}
230 360
@@ -378,6 +508,7 @@ enum qb_enqueue_commands { · 147 unmodified lines
378#define QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT 2508#define QB_ENQUEUE_CMD_ORP_ENABLE_SHIFT 2
379#define QB_ENQUEUE_CMD_IRQ_ON_DISPATCH_SHIFT 3509#define QB_ENQUEUE_CMD_IRQ_ON_DISPATCH_SHIFT 3
380#define QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT 4510#define QB_ENQUEUE_CMD_TARGET_TYPE_SHIFT 4
511#define QB_ENQUEUE_CMD_DCA_EN_SHIFT 7
381 512
382/**513/**
383 * qbman_eq_desc_clear() - Clear the contents of a descriptor to514 * qbman_eq_desc_clear() - Clear the contents of a descriptor to
@@ -453,8 +584,9 @@ static inline void qbman_write_eqcr_am_rt_register(struct qbman_swp *p, · 69 unmodified lines
453 QMAN_RT_MODE);584 QMAN_RT_MODE);
454}585}
455 586
587#define QB_RT_BIT ((u32)0x100)
456/**588/**
457 * qbman_swp_enqueue() - Issue an enqueue command589 * qbman_swp_enqueue_direct() - Issue an enqueue command
458 * @s: the software portal used for enqueue590 * @s: the software portal used for enqueue
459 * @d: the enqueue descriptor591 * @d: the enqueue descriptor
460 * @fd: the frame descriptor to be enqueued592 * @fd: the frame descriptor to be enqueued
@@ -464,30 +596,351 @@ static inline void qbman_write_eqcr_am_rt_register(struct qbman_swp *p, · 3 unmodified lines
464 *596 *
465 * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready.597 * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready.
466 */598 */
467int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d,599static
468 const struct dpaa2_fd *fd)600int qbman_swp_enqueue_direct(struct qbman_swp *s,
601 const struct qbman_eq_desc *d,
602 const struct dpaa2_fd *fd)
469{603{
470 struct qbman_eq_desc *p;604 int flags = 0;
471 u32 eqar = qbman_read_register(s, QBMAN_CINH_SWP_EQAR);605 int ret = qbman_swp_enqueue_multiple_direct(s, d, fd, &flags, 1);
472 606
473 if (!EQAR_SUCCESS(eqar))607 if (ret >= 0)
474 return -EBUSY;608 ret = 0;
609 else
610 ret = -EBUSY;
611 return ret;
612}
613
614/**
615 * qbman_swp_enqueue_mem_back() - Issue an enqueue command
616 * @s: the software portal used for enqueue
617 * @d: the enqueue descriptor
618 * @fd: the frame descriptor to be enqueued
619 *
620 * Please note that 'fd' should only be NULL if the "action" of the
621 * descriptor is "orp_hole" or "orp_nesn".
622 *
623 * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready.
624 */
625static
626int qbman_swp_enqueue_mem_back(struct qbman_swp *s,
627 const struct qbman_eq_desc *d,
628 const struct dpaa2_fd *fd)
629{
630 int flags = 0;
631 int ret = qbman_swp_enqueue_multiple_mem_back(s, d, fd, &flags, 1);
475 632
476 p = qbman_get_cmd(s, QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar)));633 if (ret >= 0)
477 memcpy(&p->dca, &d->dca, 31);634 ret = 0;
478 memcpy(&p->fd, fd, sizeof(*fd));635 else
636 ret = -EBUSY;
637 return ret;
638}
479 639
480 if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) {640/**
481 /* Set the verb byte, have to substitute in the valid-bit */641 * qbman_swp_enqueue_multiple_direct() - Issue a multi enqueue command
482 dma_wmb();642 * using one enqueue descriptor
483 p->verb = d->verb | EQAR_VB(eqar);643 * @s: the software portal used for enqueue
484 } else {644 * @d: the enqueue descriptor
485 p->verb = d->verb | EQAR_VB(eqar);645 * @fd: table pointer of frame descriptor table to be enqueued
486 dma_wmb();646 * @flags: table pointer of QBMAN_ENQUEUE_FLAG_DCA flags, not used if NULL
487 qbman_write_eqcr_am_rt_register(s, EQAR_IDX(eqar));647 * @num_frames: number of fd to be enqueued
648 *
649 * Return the number of fd enqueued, or a negative error number.
650 */
651static
652int qbman_swp_enqueue_multiple_direct(struct qbman_swp *s,
653 const struct qbman_eq_desc *d,
654 const struct dpaa2_fd *fd,
655 uint32_t *flags,
656 int num_frames)
657{
658 uint32_t *p = NULL;
659 const uint32_t *cl = (uint32_t *)d;
660 uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
661 int i, num_enqueued = 0;
662 uint64_t addr_cena;
663
664 spin_lock(&s->access_spinlock);
665 half_mask = (s->eqcr.pi_ci_mask>>1);
666 full_mask = s->eqcr.pi_ci_mask;
667
668 if (!s->eqcr.available) {
669 eqcr_ci = s->eqcr.ci;
670 p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI;
671 s->eqcr.ci = qbman_read_register(s, QBMAN_CINH_SWP_EQCR_CI);
672
673 s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
674 eqcr_ci, s->eqcr.ci);
675 if (!s->eqcr.available) {
676 spin_unlock(&s->access_spinlock);
677 return 0;
678 }
488 }679 }
489 680
490 return 0;681 eqcr_pi = s->eqcr.pi;
682 num_enqueued = (s->eqcr.available < num_frames) ?
683 s->eqcr.available : num_frames;
684 s->eqcr.available -= num_enqueued;
685 /* Fill in the EQCR ring */
686 for (i = 0; i < num_enqueued; i++) {
687 p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
688 /* Skip copying the verb */
689 memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1);
690 memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)],
691 &fd[i], sizeof(*fd));
692 eqcr_pi++;
693 }
694
695 dma_wmb();
696
697 /* Set the verb byte, have to substitute in the valid-bit */
698 eqcr_pi = s->eqcr.pi;
699 for (i = 0; i < num_enqueued; i++) {
700 p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
701 p[0] = cl[0] | s->eqcr.pi_vb;
702 if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
703 struct qbman_eq_desc *d = (struct qbman_eq_desc *)p;
704
705 d->dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) |
706 ((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
707 }
708 eqcr_pi++;
709 if (!(eqcr_pi & half_mask))
710 s->eqcr.pi_vb ^= QB_VALID_BIT;
711 }
712
713 /* Flush all the cacheline without load/store in between */
714 eqcr_pi = s->eqcr.pi;
715 addr_cena = (size_t)s->addr_cena;
716 for (i = 0; i < num_enqueued; i++)
717 eqcr_pi++;
718 s->eqcr.pi = eqcr_pi & full_mask;
719 spin_unlock(&s->access_spinlock);
720
721 return num_enqueued;
722}
723
724/**
725 * qbman_swp_enqueue_multiple_mem_back() - Issue a multi enqueue command
726 * using one enqueue descriptor
727 * @s: the software portal used for enqueue
728 * @d: the enqueue descriptor
729 * @fd: table pointer of frame descriptor table to be enqueued
730 * @flags: table pointer of QBMAN_ENQUEUE_FLAG_DCA flags, not used if NULL
731 * @num_frames: number of fd to be enqueued
732 *
733 * Return the number of fd enqueued, or a negative error number.
734 */
735static
736int qbman_swp_enqueue_multiple_mem_back(struct qbman_swp *s,
737 const struct qbman_eq_desc *d,
738 const struct dpaa2_fd *fd,
739 uint32_t *flags,
740 int num_frames)
741{
742 uint32_t *p = NULL;
743 const uint32_t *cl = (uint32_t *)(d);
744 uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
745 int i, num_enqueued = 0;
746 unsigned long irq_flags;
747
748 spin_lock(&s->access_spinlock);
749 local_irq_save(irq_flags);
750
751 half_mask = (s->eqcr.pi_ci_mask>>1);
752 full_mask = s->eqcr.pi_ci_mask;
753 if (!s->eqcr.available) {
754 eqcr_ci = s->eqcr.ci;
755 p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI_MEMBACK;
756 s->eqcr.ci = __raw_readl(p) & full_mask;
757 s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
758 eqcr_ci, s->eqcr.ci);
759 if (!s->eqcr.available) {
760 local_irq_restore(irq_flags);
761 spin_unlock(&s->access_spinlock);
762 return 0;
763 }
764 }
765
766 eqcr_pi = s->eqcr.pi;
767 num_enqueued = (s->eqcr.available < num_frames) ?
768 s->eqcr.available : num_frames;
769 s->eqcr.available -= num_enqueued;
770 /* Fill in the EQCR ring */
771 for (i = 0; i < num_enqueued; i++) {
772 p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
773 /* Skip copying the verb */
774 memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1);
775 memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)],
776 &fd[i], sizeof(*fd));
777 eqcr_pi++;
778 }
779
780 /* Set the verb byte, have to substitute in the valid-bit */
781 eqcr_pi = s->eqcr.pi;
782 for (i = 0; i < num_enqueued; i++) {
783 p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
784 p[0] = cl[0] | s->eqcr.pi_vb;
785 if (flags && (flags[i] & QBMAN_ENQUEUE_FLAG_DCA)) {
786 struct qbman_eq_desc *d = (struct qbman_eq_desc *)p;
787
788 d->dca = (1 << QB_ENQUEUE_CMD_DCA_EN_SHIFT) |
789 ((flags[i]) & QBMAN_EQCR_DCA_IDXMASK);
790 }
791 eqcr_pi++;
792 if (!(eqcr_pi & half_mask))
793 s->eqcr.pi_vb ^= QB_VALID_BIT;
794 }
795 s->eqcr.pi = eqcr_pi & full_mask;
796
797 dma_wmb();
798 qbman_write_register(s, QBMAN_CINH_SWP_EQCR_PI,
799 (QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb);
800 local_irq_restore(irq_flags);
801 spin_unlock(&s->access_spinlock);
802
803 return num_enqueued;
804}
805
806/**
807 * qbman_swp_enqueue_multiple_desc_direct() - Issue a multi enqueue command
808 * using multiple enqueue descriptor
809 * @s: the software portal used for enqueue
810 * @d: table of minimal enqueue descriptor
811 * @fd: table pointer of frame descriptor table to be enqueued
812 * @num_frames: number of fd to be enqueued
813 *
814 * Return the number of fd enqueued, or a negative error number.
815 */
816static
817int qbman_swp_enqueue_multiple_desc_direct(struct qbman_swp *s,
818 const struct qbman_eq_desc *d,
819 const struct dpaa2_fd *fd,
820 int num_frames)
821{
822 uint32_t *p;
823 const uint32_t *cl;
824 uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
825 int i, num_enqueued = 0;
826 uint64_t addr_cena;
827
828 half_mask = (s->eqcr.pi_ci_mask>>1);
829 full_mask = s->eqcr.pi_ci_mask;
830 if (!s->eqcr.available) {
831 eqcr_ci = s->eqcr.ci;
832 p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI;
833 s->eqcr.ci = qbman_read_register(s, QBMAN_CINH_SWP_EQCR_CI);
834 s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
835 eqcr_ci, s->eqcr.ci);
836 if (!s->eqcr.available)
837 return 0;
838 }
839
840 eqcr_pi = s->eqcr.pi;
841 num_enqueued = (s->eqcr.available < num_frames) ?
842 s->eqcr.available : num_frames;
843 s->eqcr.available -= num_enqueued;
844 /* Fill in the EQCR ring */
845 for (i = 0; i < num_enqueued; i++) {
846 p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
847 cl = (uint32_t *)(&d[i]);
848 /* Skip copying the verb */
849 memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1);
850 memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)],
851 &fd[i], sizeof(*fd));
852 eqcr_pi++;
853 }
854
855 dma_wmb();
856
857 /* Set the verb byte, have to substitute in the valid-bit */
858 eqcr_pi = s->eqcr.pi;
859 for (i = 0; i < num_enqueued; i++) {
860 p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
861 cl = (uint32_t *)(&d[i]);
862 p[0] = cl[0] | s->eqcr.pi_vb;
863 eqcr_pi++;
864 if (!(eqcr_pi & half_mask))
865 s->eqcr.pi_vb ^= QB_VALID_BIT;
866 }
867
868 /* Flush all the cacheline without load/store in between */
869 eqcr_pi = s->eqcr.pi;
870 addr_cena = (uint64_t)s->addr_cena;
871 for (i = 0; i < num_enqueued; i++)
872 eqcr_pi++;
873 s->eqcr.pi = eqcr_pi & full_mask;
874
875 return num_enqueued;
876}
877
878/**
879 * qbman_swp_enqueue_multiple_desc_mem_back() - Issue a multi enqueue command
880 * using multiple enqueue descriptor
881 * @s: the software portal used for enqueue
882 * @d: table of minimal enqueue descriptor
883 * @fd: table pointer of frame descriptor table to be enqueued
884 * @num_frames: number of fd to be enqueued
885 *
886 * Return the number of fd enqueued, or a negative error number.
887 */
888static
889int qbman_swp_enqueue_multiple_desc_mem_back(struct qbman_swp *s,
890 const struct qbman_eq_desc *d,
891 const struct dpaa2_fd *fd,
892 int num_frames)
893{
894 uint32_t *p;
895 const uint32_t *cl;
896 uint32_t eqcr_ci, eqcr_pi, half_mask, full_mask;
897 int i, num_enqueued = 0;
898
899 half_mask = (s->eqcr.pi_ci_mask>>1);
900 full_mask = s->eqcr.pi_ci_mask;
901 if (!s->eqcr.available) {
902 eqcr_ci = s->eqcr.ci;
903 p = s->addr_cena + QBMAN_CENA_SWP_EQCR_CI_MEMBACK;
904 s->eqcr.ci = __raw_readl(p) & full_mask;
905 s->eqcr.available = qm_cyc_diff(s->eqcr.pi_ring_size,
906 eqcr_ci, s->eqcr.ci);
907 if (!s->eqcr.available)
908 return 0;
909 }
910
911 eqcr_pi = s->eqcr.pi;
912 num_enqueued = (s->eqcr.available < num_frames) ?
913 s->eqcr.available : num_frames;
914 s->eqcr.available -= num_enqueued;
915 /* Fill in the EQCR ring */
916 for (i = 0; i < num_enqueued; i++) {
917 p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
918 cl = (uint32_t *)(&d[i]);
919 /* Skip copying the verb */
920 memcpy(&p[1], &cl[1], EQ_DESC_SIZE_WITHOUT_FD - 1);
921 memcpy(&p[EQ_DESC_SIZE_FD_START/sizeof(uint32_t)],
922 &fd[i], sizeof(*fd));
923 eqcr_pi++;
924 }
925
926 /* Set the verb byte, have to substitute in the valid-bit */
927 eqcr_pi = s->eqcr.pi;
928 for (i = 0; i < num_enqueued; i++) {
929 p = (s->addr_cena + QBMAN_CENA_SWP_EQCR(eqcr_pi & half_mask));
930 cl = (uint32_t *)(&d[i]);
931 p[0] = cl[0] | s->eqcr.pi_vb;
932 eqcr_pi++;
933 if (!(eqcr_pi & half_mask))
934 s->eqcr.pi_vb ^= QB_VALID_BIT;
935 }
936
937 s->eqcr.pi = eqcr_pi & full_mask;
938
939 dma_wmb();
940 qbman_write_register(s, QBMAN_CINH_SWP_EQCR_PI,
941 (QB_RT_BIT)|(s->eqcr.pi)|s->eqcr.pi_vb);
942
943 return num_enqueued;
491}944}
492 945
493/* Static (push) dequeue */946/* Static (push) dequeue */
@@ -645,7 +1098,7 @@ void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid, · 151 unmodified lines
645}1098}
646 1099
647/**1100/**
648 * qbman_swp_pull() - Issue the pull dequeue command1101 * qbman_swp_pull_direct() - Issue the pull dequeue command
649 * @s: the software portal object1102 * @s: the software portal object
650 * @d: the software portal descriptor which has been configured with1103 * @d: the software portal descriptor which has been configured with
651 * the set of qbman_pull_desc_set_*() calls1104 * the set of qbman_pull_desc_set_*() calls
@@ -653,7 +1106,8 @@ void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid, · 1 unmodified line
653 * Return 0 for success, and -EBUSY if the software portal is not ready1106 * Return 0 for success, and -EBUSY if the software portal is not ready
654 * to do pull dequeue.1107 * to do pull dequeue.
655 */1108 */
656int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d)1109static
1110int qbman_swp_pull_direct(struct qbman_swp *s, struct qbman_pull_desc *d)
657{1111{
658 struct qbman_pull_desc *p;1112 struct qbman_pull_desc *p;
659 1113
@@ -671,18 +1125,48 @@ int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d) · 11 unmodified lines
671 p->dq_src = d->dq_src;1125 p->dq_src = d->dq_src;
672 p->rsp_addr = d->rsp_addr;1126 p->rsp_addr = d->rsp_addr;
673 p->rsp_addr_virt = d->rsp_addr_virt;1127 p->rsp_addr_virt = d->rsp_addr_virt;
1128 dma_wmb();
1129 /* Set the verb byte, have to substitute in the valid-bit */
1130 p->verb = d->verb | s->vdq.valid_bit;
1131 s->vdq.valid_bit ^= QB_VALID_BIT;
674 1132
675 if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) {1133 return 0;
676 dma_wmb();1134}
677 /* Set the verb byte, have to substitute in the valid-bit */1135
678 p->verb = d->verb | s->vdq.valid_bit;1136/**
679 s->vdq.valid_bit ^= QB_VALID_BIT;1137 * qbman_swp_pull_mem_back() - Issue the pull dequeue command
680 } else {1138 * @s: the software portal object
681 p->verb = d->verb | s->vdq.valid_bit;1139 * @d: the software portal descriptor which has been configured with
682 s->vdq.valid_bit ^= QB_VALID_BIT;1140 * the set of qbman_pull_desc_set_*() calls
683 dma_wmb();1141 *
684 qbman_write_register(s, QBMAN_CINH_SWP_VDQCR_RT, QMAN_RT_MODE);1142 * Return 0 for success, and -EBUSY if the software portal is not ready
1143 * to do pull dequeue.
1144 */
1145static
1146int qbman_swp_pull_mem_back(struct qbman_swp *s, struct qbman_pull_desc *d)
1147{
1148 struct qbman_pull_desc *p;
1149
1150 if (!atomic_dec_and_test(&s->vdq.available)) {
1151 atomic_inc(&s->vdq.available);
1152 return -EBUSY;
685 }1153 }
1154 s->vdq.storage = (void *)(uintptr_t)d->rsp_addr_virt;
1155 if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000)
1156 p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR);
1157 else
1158 p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR_MEM);
1159 p->numf = d->numf;
1160 p->tok = QMAN_DQ_TOKEN_VALID;
1161 p->dq_src = d->dq_src;
1162 p->rsp_addr = d->rsp_addr;
1163 p->rsp_addr_virt = d->rsp_addr_virt;
1164
1165 /* Set the verb byte, have to substitute in the valid-bit */
1166 p->verb = d->verb | s->vdq.valid_bit;
1167 s->vdq.valid_bit ^= QB_VALID_BIT;
1168 dma_wmb();
1169 qbman_write_register(s, QBMAN_CINH_SWP_VDQCR_RT, QMAN_RT_MODE);
686 1170
687 return 0;1171 return 0;
688}1172}
@@ -690,14 +1174,14 @@ int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d) · 1 unmodified line
690#define QMAN_DQRR_PI_MASK 0xf1174#define QMAN_DQRR_PI_MASK 0xf
691 1175
692/**1176/**
693 * qbman_swp_dqrr_next() - Get an valid DQRR entry1177 * qbman_swp_dqrr_next_direct() - Get an valid DQRR entry
694 * @s: the software portal object1178 * @s: the software portal object
695 *1179 *
696 * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry1180 * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry
697 * only once, so repeated calls can return a sequence of DQRR entries, without1181 * only once, so repeated calls can return a sequence of DQRR entries, without
698 * requiring they be consumed immediately or in any particular order.1182 * requiring they be consumed immediately or in any particular order.
699 */1183 */
700const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s)1184const struct dpaa2_dq *qbman_swp_dqrr_next_direct(struct qbman_swp *s)
701{1185{
702 u32 verb;1186 u32 verb;
703 u32 response_verb;1187 u32 response_verb;
@@ -740,10 +1224,99 @@ const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s) · 36 unmodified lines
740 QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));1224 QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
741 }1225 }
742 1226
743 if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000)1227 p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
744 p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));1228 verb = p->dq.verb;
745 else1229
746 p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR_MEM(s->dqrr.next_idx));1230 /*
1231 * If the valid-bit isn't of the expected polarity, nothing there. Note,
1232 * in the DQRR reset bug workaround, we shouldn't need to skip these
1233 * check, because we've already determined that a new entry is available
1234 * and we've invalidated the cacheline before reading it, so the
1235 * valid-bit behaviour is repaired and should tell us what we already
1236 * knew from reading PI.
1237 */
1238 if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) {
1239 prefetch(qbman_get_cmd(s,
1240 QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
1241 return NULL;
1242 }
1243 /*
1244 * There's something there. Move "next_idx" attention to the next ring
1245 * entry (and prefetch it) before returning what we found.
1246 */
1247 s->dqrr.next_idx++;
1248 s->dqrr.next_idx &= s->dqrr.dqrr_size - 1; /* Wrap around */
1249 if (!s->dqrr.next_idx)
1250 s->dqrr.valid_bit ^= QB_VALID_BIT;
1251
1252 /*
1253 * If this is the final response to a volatile dequeue command
1254 * indicate that the vdq is available
1255 */
1256 flags = p->dq.stat;
1257 response_verb = verb & QBMAN_RESULT_MASK;
1258 if ((response_verb == QBMAN_RESULT_DQ) &&
1259 (flags & DPAA2_DQ_STAT_VOLATILE) &&
1260 (flags & DPAA2_DQ_STAT_EXPIRED))
1261 atomic_inc(&s->vdq.available);
1262
1263 prefetch(qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
1264
1265 return p;
1266}
1267
1268/**
1269 * qbman_swp_dqrr_next_mem_back() - Get an valid DQRR entry
1270 * @s: the software portal object
1271 *
1272 * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry
1273 * only once, so repeated calls can return a sequence of DQRR entries, without
1274 * requiring they be consumed immediately or in any particular order.
1275 */
1276const struct dpaa2_dq *qbman_swp_dqrr_next_mem_back(struct qbman_swp *s)
1277{
1278 u32 verb;
1279 u32 response_verb;
1280 u32 flags;
1281 struct dpaa2_dq *p;
1282
1283 /* Before using valid-bit to detect if something is there, we have to
1284 * handle the case of the DQRR reset bug...
1285 */
1286 if (unlikely(s->dqrr.reset_bug)) {
1287 /*
1288 * We pick up new entries by cache-inhibited producer index,
1289 * which means that a non-coherent mapping would require us to
1290 * invalidate and read *only* once that PI has indicated that
1291 * there's an entry here. The first trip around the DQRR ring
1292 * will be much less efficient than all subsequent trips around
1293 * it...
1294 */
1295 u8 pi = qbman_read_register(s, QBMAN_CINH_SWP_DQPI) &
1296 QMAN_DQRR_PI_MASK;
1297
1298 /* there are new entries if pi != next_idx */
1299 if (pi == s->dqrr.next_idx)
1300 return NULL;
1301
1302 /*
1303 * if next_idx is/was the last ring index, and 'pi' is
1304 * different, we can disable the workaround as all the ring
1305 * entries have now been DMA'd to so valid-bit checking is
1306 * repaired. Note: this logic needs to be based on next_idx
1307 * (which increments one at a time), rather than on pi (which
1308 * can burst and wrap-around between our snapshots of it).
1309 */
1310 if (s->dqrr.next_idx == (s->dqrr.dqrr_size - 1)) {
1311 pr_debug("next_idx=%d, pi=%d, clear reset bug\n",
1312 s->dqrr.next_idx, pi);
1313 s->dqrr.reset_bug = 0;
1314 }
1315 prefetch(qbman_get_cmd(s,
1316 QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)));
1317 }
1318
1319 p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR_MEM(s->dqrr.next_idx));
747 verb = p->dq.verb;1320 verb = p->dq.verb;
748 1321
749 /*1322 /*
@@ -872,7 +1445,7 @@ void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable) · 122 unmodified lines
872#define RAR_SUCCESS(rar) ((rar) & 0x100)1445#define RAR_SUCCESS(rar) ((rar) & 0x100)
873 1446
874/**1447/**
875 * qbman_swp_release() - Issue a buffer release command1448 * qbman_swp_release_direct() - Issue a buffer release command
876 * @s: the software portal object1449 * @s: the software portal object
877 * @d: the release descriptor1450 * @d: the release descriptor
878 * @buffers: a pointer pointing to the buffer address to be released1451 * @buffers: a pointer pointing to the buffer address to be released
@@ -880,8 +1453,9 @@ void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable) · 1 unmodified line
880 *1453 *
881 * Return 0 for success, -EBUSY if the release command ring is not ready.1454 * Return 0 for success, -EBUSY if the release command ring is not ready.
882 */1455 */
883int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d,1456int qbman_swp_release_direct(struct qbman_swp *s,
884 const u64 *buffers, unsigned int num_buffers)1457 const struct qbman_release_desc *d,
1458 const u64 *buffers, unsigned int num_buffers)
885{1459{
886 int i;1460 int i;
887 struct qbman_release_desc *p;1461 struct qbman_release_desc *p;
@@ -895,28 +1469,59 @@ int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d, · 7 unmodified lines
895 return -EBUSY;1469 return -EBUSY;
896 1470
897 /* Start the release command */1471 /* Start the release command */
898 if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000)1472 p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR(RAR_IDX(rar)));
899 p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR(RAR_IDX(rar)));1473
900 else
901 p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR_MEM(RAR_IDX(rar)));
902 /* Copy the caller's buffer pointers to the command */1474 /* Copy the caller's buffer pointers to the command */
903 for (i = 0; i < num_buffers; i++)1475 for (i = 0; i < num_buffers; i++)
904 p->buf[i] = cpu_to_le64(buffers[i]);1476 p->buf[i] = cpu_to_le64(buffers[i]);
905 p->bpid = d->bpid;1477 p->bpid = d->bpid;
906 1478
907 if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) {1479 /*
908 /*1480 * Set the verb byte, have to substitute in the valid-bit
909 * Set the verb byte, have to substitute in the valid-bit1481 * and the number of buffers.
910 * and the number of buffers.1482 */
911 */1483 dma_wmb();
912 dma_wmb();1484 p->verb = d->verb | RAR_VB(rar) | num_buffers;
913 p->verb = d->verb | RAR_VB(rar) | num_buffers;1485
914 } else {1486 return 0;
915 p->verb = d->verb | RAR_VB(rar) | num_buffers;1487}
916 dma_wmb();1488
917 qbman_write_register(s, QBMAN_CINH_SWP_RCR_AM_RT +1489/**
918 RAR_IDX(rar) * 4, QMAN_RT_MODE);1490 * qbman_swp_release_mem_back() - Issue a buffer release command
919 }1491 * @s: the software portal object
1492 * @d: the release descriptor
1493 * @buffers: a pointer pointing to the buffer address to be released
1494 * @num_buffers: number of buffers to be released, must be less than 8
1495 *
1496 * Return 0 for success, -EBUSY if the release command ring is not ready.
1497 */
1498int qbman_swp_release_mem_back(struct qbman_swp *s,
1499 const struct qbman_release_desc *d,
1500 const u64 *buffers, unsigned int num_buffers)
1501{
1502 int i;
1503 struct qbman_release_desc *p;
1504 u32 rar;
1505
1506 if (!num_buffers || (num_buffers > 7))
1507 return -EINVAL;
1508
1509 rar = qbman_read_register(s, QBMAN_CINH_SWP_RAR);
1510 if (!RAR_SUCCESS(rar))
1511 return -EBUSY;
1512
1513 /* Start the release command */
1514 p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR_MEM(RAR_IDX(rar)));
1515
1516 /* Copy the caller's buffer pointers to the command */
1517 for (i = 0; i < num_buffers; i++)
1518 p->buf[i] = cpu_to_le64(buffers[i]);
1519 p->bpid = d->bpid;
1520
1521 p->verb = d->verb | RAR_VB(rar) | num_buffers;
1522 dma_wmb();
1523 qbman_write_register(s, QBMAN_CINH_SWP_RCR_AM_RT +
1524 RAR_IDX(rar) * 4, QMAN_RT_MODE);
920 1525
921 return 0;1526 return 0;
922}1527}
drivers/soc/fsl/dpio/qbman-portal.h+151−7
@@ -9,6 +9,13 @@ · 8 unmodified lines
9 9
10#include <soc/fsl/dpaa2-fd.h>10#include <soc/fsl/dpaa2-fd.h>
11 11
12#define QMAN_REV_4000 0x04000000
13#define QMAN_REV_4100 0x04010000
14#define QMAN_REV_4101 0x04010001
15#define QMAN_REV_5000 0x05000000
16
17#define QMAN_REV_MASK 0xffff0000
18
12struct dpaa2_dq;19struct dpaa2_dq;
13struct qbman_swp;20struct qbman_swp;
14 21
@@ -81,6 +88,10 @@ struct qbman_eq_desc { · 66 unmodified lines
81 u8 wae;88 u8 wae;
82 u8 rspid;89 u8 rspid;
83 __le64 rsp_addr;90 __le64 rsp_addr;
91};
92
93struct qbman_eq_desc_with_fd {
94 struct qbman_eq_desc desc;
84 u8 fd[32];95 u8 fd[32];
85};96};
86 97
@@ -132,8 +143,48 @@ struct qbman_swp { · 45 unmodified lines
132 u8 dqrr_size;143 u8 dqrr_size;
133 int reset_bug; /* indicates dqrr reset workaround is needed */144 int reset_bug; /* indicates dqrr reset workaround is needed */
134 } dqrr;145 } dqrr;
146
147 struct {
148 u32 pi;
149 u32 pi_vb;
150 u32 pi_ring_size;
151 u32 pi_ci_mask;
152 u32 ci;
153 int available;
154 u32 pend;
155 u32 no_pfdr;
156 } eqcr;
157
158 spinlock_t access_spinlock;
135};159};
136 160
161/* Function pointers */
162extern
163int (*qbman_swp_enqueue_ptr)(struct qbman_swp *s,
164 const struct qbman_eq_desc *d,
165 const struct dpaa2_fd *fd);
166extern
167int (*qbman_swp_enqueue_multiple_ptr)(struct qbman_swp *s,
168 const struct qbman_eq_desc *d,
169 const struct dpaa2_fd *fd,
170 uint32_t *flags,
171 int num_frames);
172extern
173int (*qbman_swp_enqueue_multiple_desc_ptr)(struct qbman_swp *s,
174 const struct qbman_eq_desc *d,
175 const struct dpaa2_fd *fd,
176 int num_frames);
177extern
178int (*qbman_swp_pull_ptr)(struct qbman_swp *s, struct qbman_pull_desc *d);
179extern
180const struct dpaa2_dq *(*qbman_swp_dqrr_next_ptr)(struct qbman_swp *s);
181extern
182int (*qbman_swp_release_ptr)(struct qbman_swp *s,
183 const struct qbman_release_desc *d,
184 const u64 *buffers,
185 unsigned int num_buffers);
186
187/* Functions */
137struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d);188struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d);
138void qbman_swp_finish(struct qbman_swp *p);189void qbman_swp_finish(struct qbman_swp *p);
139u32 qbman_swp_interrupt_read_status(struct qbman_swp *p);190u32 qbman_swp_interrupt_read_status(struct qbman_swp *p);
@@ -158,9 +209,6 @@ void qbman_pull_desc_set_wq(struct qbman_pull_desc *d, u32 wqid, · 18 unmodified lines
158void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid,209void qbman_pull_desc_set_channel(struct qbman_pull_desc *d, u32 chid,
159 enum qbman_pull_type_e dct);210 enum qbman_pull_type_e dct);
160 211
161int qbman_swp_pull(struct qbman_swp *p, struct qbman_pull_desc *d);
162
163const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s);
164void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct dpaa2_dq *dq);212void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct dpaa2_dq *dq);
165 213
166int qbman_result_has_new_result(struct qbman_swp *p, const struct dpaa2_dq *dq);214int qbman_result_has_new_result(struct qbman_swp *p, const struct dpaa2_dq *dq);
@@ -172,15 +220,11 @@ void qbman_eq_desc_set_fq(struct qbman_eq_desc *d, u32 fqid); · 5 unmodified lines
172void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid,220void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid,
173 u32 qd_bin, u32 qd_prio);221 u32 qd_bin, u32 qd_prio);
174 222
175int qbman_swp_enqueue(struct qbman_swp *p, const struct qbman_eq_desc *d,
176 const struct dpaa2_fd *fd);
177 223
178void qbman_release_desc_clear(struct qbman_release_desc *d);224void qbman_release_desc_clear(struct qbman_release_desc *d);
179void qbman_release_desc_set_bpid(struct qbman_release_desc *d, u16 bpid);225void qbman_release_desc_set_bpid(struct qbman_release_desc *d, u16 bpid);
180void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable);226void qbman_release_desc_set_rcdi(struct qbman_release_desc *d, int enable);
181 227
182int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d,
183 const u64 *buffers, unsigned int num_buffers);
184int qbman_swp_acquire(struct qbman_swp *s, u16 bpid, u64 *buffers,228int qbman_swp_acquire(struct qbman_swp *s, u16 bpid, u64 *buffers,
185 unsigned int num_buffers);229 unsigned int num_buffers);
186int qbman_swp_alt_fq_state(struct qbman_swp *s, u32 fqid,230int qbman_swp_alt_fq_state(struct qbman_swp *s, u32 fqid,
@@ -193,6 +237,61 @@ void *qbman_swp_mc_start(struct qbman_swp *p); · 6 unmodified lines
193void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb);237void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb);
194void *qbman_swp_mc_result(struct qbman_swp *p);238void *qbman_swp_mc_result(struct qbman_swp *p);
195 239
240/**
241 * qbman_swp_enqueue() - Issue an enqueue command
242 * @s: the software portal used for enqueue
243 * @d: the enqueue descriptor
244 * @fd: the frame descriptor to be enqueued
245 *
246 * Return 0 for successful enqueue, -EBUSY if the EQCR is not ready.
247 */
248static inline int
249qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d,
250 const struct dpaa2_fd *fd)
251{
252 return qbman_swp_enqueue_ptr(s, d, fd);
253}
254
255/**
256 * qbman_swp_enqueue_multiple() - Issue a multi enqueue command
257 * using one enqueue descriptor
258 * @s: the software portal used for enqueue
259 * @d: the enqueue descriptor
260 * @fd: table pointer of frame descriptor table to be enqueued
261 * @flags: table pointer of QBMAN_ENQUEUE_FLAG_DCA flags, not used if NULL
262 * @num_frames: number of fd to be enqueued
263 *
264 * Return the number of fd enqueued, or a negative error number.
265 */
266static inline int
267qbman_swp_enqueue_multiple(struct qbman_swp *s,
268 const struct qbman_eq_desc *d,
269 const struct dpaa2_fd *fd,
270 uint32_t *flags,
271 int num_frames)
272{
273 return qbman_swp_enqueue_multiple_ptr(s, d, fd, flags, num_frames);
274}
275
276/**
277 * qbman_swp_enqueue_multiple_desc() - Issue a multi enqueue command
278 * using multiple enqueue descriptor
279 * @s: the software portal used for enqueue
280 * @d: table of minimal enqueue descriptor
281 * @fd: table pointer of frame descriptor table to be enqueued
282 * @num_frames: number of fd to be enqueued
283 *
284 * Return the number of fd enqueued, or a negative error number.
285 */
286static inline int
287qbman_swp_enqueue_multiple_desc(struct qbman_swp *s,
288 const struct qbman_eq_desc *d,
289 const struct dpaa2_fd *fd,
290 int num_frames)
291{
292 return qbman_swp_enqueue_multiple_desc_ptr(s, d, fd, num_frames);
293}
294
196/**295/**
197 * qbman_result_is_DQ() - check if the dequeue result is a dequeue response296 * qbman_result_is_DQ() - check if the dequeue result is a dequeue response
198 * @dq: the dequeue result to be checked297 * @dq: the dequeue result to be checked
@@ -504,4 +603,49 @@ int qbman_bp_query(struct qbman_swp *s, u16 bpid, · 305 unmodified lines
504 603
505u32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a);604u32 qbman_bp_info_num_free_bufs(struct qbman_bp_query_rslt *a);
506 605
606/**
607 * qbman_swp_release() - Issue a buffer release command
608 * @s: the software portal object
609 * @d: the release descriptor
610 * @buffers: a pointer pointing to the buffer address to be released
611 * @num_buffers: number of buffers to be released, must be less than 8
612 *
613 * Return 0 for success, -EBUSY if the release command ring is not ready.
614 */
615static inline int qbman_swp_release(struct qbman_swp *s,
616 const struct qbman_release_desc *d,
617 const u64 *buffers,
618 unsigned int num_buffers)
619{
620 return qbman_swp_release_ptr(s, d, buffers, num_buffers);
621}
622
623/**
624 * qbman_swp_pull() - Issue the pull dequeue command
625 * @s: the software portal object
626 * @d: the software portal descriptor which has been configured with
627 * the set of qbman_pull_desc_set_*() calls
628 *
629 * Return 0 for success, and -EBUSY if the software portal is not ready
630 * to do pull dequeue.
631 */
632static inline int qbman_swp_pull(struct qbman_swp *s,
633 struct qbman_pull_desc *d)
634{
635 return qbman_swp_pull_ptr(s, d);
636}
637
638/**
639 * qbman_swp_dqrr_next() - Get an valid DQRR entry
640 * @s: the software portal object
641 *
642 * Return NULL if there are no unconsumed DQRR entries. Return a DQRR entry
643 * only once, so repeated calls can return a sequence of DQRR entries, without
644 * requiring they be consumed immediately or in any particular order.
645 */
646static inline const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s)
647{
648 return qbman_swp_dqrr_next_ptr(s);
649}
650
507#endif /* __FSL_QBMAN_PORTAL_H */651#endif /* __FSL_QBMAN_PORTAL_H */
drivers/soc/fsl/qe/qe.c+2−2
@@ -423,7 +423,7 @@ static void qe_upload_microcode(const void *base, · 422 unmodified lines
423 qe_iowrite32be(be32_to_cpu(code[i]), &qe_immr->iram.idata);423 qe_iowrite32be(be32_to_cpu(code[i]), &qe_immr->iram.idata);
424 424
425 /* Set I-RAM Ready Register */425 /* Set I-RAM Ready Register */
426 qe_iowrite32be(be32_to_cpu(QE_IRAM_READY), &qe_immr->iram.iready);426 qe_iowrite32be(QE_IRAM_READY, &qe_immr->iram.iready);
427}427}
428 428
429/*429/*
@@ -525,7 +525,7 @@ int qe_upload_firmware(const struct qe_firmware *firmware) · 95 unmodified lines
525 */525 */
526 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));526 memset(&qe_firmware_info, 0, sizeof(qe_firmware_info));
527 strlcpy(qe_firmware_info.id, firmware->id, sizeof(qe_firmware_info.id));527 strlcpy(qe_firmware_info.id, firmware->id, sizeof(qe_firmware_info.id));
528 qe_firmware_info.extended_modes = firmware->extended_modes;528 qe_firmware_info.extended_modes = be64_to_cpu(firmware->extended_modes);
529 memcpy(qe_firmware_info.vtraps, firmware->vtraps,529 memcpy(qe_firmware_info.vtraps, firmware->vtraps,
530 sizeof(firmware->vtraps));530 sizeof(firmware->vtraps));
531 531
drivers/soc/fsl/qe/qe_common.c+1−1
@@ -46,7 +46,7 @@ int cpm_muram_init(void) · 45 unmodified lines
46{46{
47 struct device_node *np;47 struct device_node *np;
48 struct resource r;48 struct resource r;
49 u32 zero[OF_MAX_ADDR_CELLS] = {};49 __be32 zero[OF_MAX_ADDR_CELLS] = {};
50 resource_size_t max = 0;50 resource_size_t max = 0;
51 int i = 0;51 int i = 0;
52 int ret = 0;52 int ret = 0;
drivers/soc/fsl/qe/qe_ic.c+1−1
@@ -44,7 +44,7 @@ · 43 unmodified lines
44 44
45struct qe_ic {45struct qe_ic {
46 /* Control registers offset */46 /* Control registers offset */
47 u32 __iomem *regs;47 __be32 __iomem *regs;
48 48
49 /* The remapper for this QEIC */49 /* The remapper for this QEIC */
50 struct irq_domain *irqhost;50 struct irq_domain *irqhost;
drivers/soc/fsl/qe/ucc.c+1−1
@@ -632,7 +632,7 @@ int ucc_set_tdm_rxtx_sync(u32 tdm_num, enum qe_clock clock, · 631 unmodified lines
632{632{
633 int source;633 int source;
634 u32 shift;634 u32 shift;
635 struct qe_mux *qe_mux_reg;635 struct qe_mux __iomem *qe_mux_reg;
636 636
637 qe_mux_reg = &qe_immr->qmx;637 qe_mux_reg = &qe_immr->qmx;
638 638
drivers/soc/fsl/qe/ucc_slow.c+13−20
@@ -72,7 +72,7 @@ EXPORT_SYMBOL(ucc_slow_restart_tx); · 71 unmodified lines
72 72
73void ucc_slow_enable(struct ucc_slow_private * uccs, enum comm_dir mode)73void ucc_slow_enable(struct ucc_slow_private * uccs, enum comm_dir mode)
74{74{
75 struct ucc_slow *us_regs;75 struct ucc_slow __iomem *us_regs;
76 u32 gumr_l;76 u32 gumr_l;
77 77
78 us_regs = uccs->us_regs;78 us_regs = uccs->us_regs;
@@ -93,7 +93,7 @@ EXPORT_SYMBOL(ucc_slow_enable); · 14 unmodified lines
93 93
94void ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode)94void ucc_slow_disable(struct ucc_slow_private * uccs, enum comm_dir mode)
95{95{
96 struct ucc_slow *us_regs;96 struct ucc_slow __iomem *us_regs;
97 u32 gumr_l;97 u32 gumr_l;
98 98
99 us_regs = uccs->us_regs;99 us_regs = uccs->us_regs;
@@ -122,7 +122,7 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc · 22 unmodified lines
122 u32 i;122 u32 i;
123 struct ucc_slow __iomem *us_regs;123 struct ucc_slow __iomem *us_regs;
124 u32 gumr;124 u32 gumr;
125 struct qe_bd *bd;125 struct qe_bd __iomem *bd;
126 u32 id;126 u32 id;
127 u32 command;127 u32 command;
128 int ret = 0;128 int ret = 0;
@@ -168,16 +168,9 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc · 39 unmodified lines
168 return -ENOMEM;168 return -ENOMEM;
169 }169 }
170 170
171 uccs->saved_uccm = 0;
172 uccs->p_rx_frame = 0;
173 us_regs = uccs->us_regs;171 us_regs = uccs->us_regs;
174 uccs->p_ucce = (u16 *) & (us_regs->ucce);172 uccs->p_ucce = &us_regs->ucce;
175 uccs->p_uccm = (u16 *) & (us_regs->uccm);173 uccs->p_uccm = &us_regs->uccm;
176#ifdef STATISTICS
177 uccs->rx_frames = 0;
178 uccs->tx_frames = 0;
179 uccs->rx_discarded = 0;
180#endif /* STATISTICS */
181 174
182 /* Get PRAM base */175 /* Get PRAM base */
183 uccs->us_pram_offset =176 uccs->us_pram_offset =
@@ -231,24 +224,24 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc · 47 unmodified lines
231 /* clear bd buffer */224 /* clear bd buffer */
232 qe_iowrite32be(0, &bd->buf);225 qe_iowrite32be(0, &bd->buf);
233 /* set bd status and length */226 /* set bd status and length */
234 qe_iowrite32be(0, (u32 *)bd);227 qe_iowrite32be(0, (u32 __iomem *)bd);
235 bd++;228 bd++;
236 }229 }
237 /* for last BD set Wrap bit */230 /* for last BD set Wrap bit */
238 qe_iowrite32be(0, &bd->buf);231 qe_iowrite32be(0, &bd->buf);
239 qe_iowrite32be(cpu_to_be32(T_W), (u32 *)bd);232 qe_iowrite32be(T_W, (u32 __iomem *)bd);
240 233
241 /* Init Rx bds */234 /* Init Rx bds */
242 bd = uccs->rx_bd = qe_muram_addr(uccs->rx_base_offset);235 bd = uccs->rx_bd = qe_muram_addr(uccs->rx_base_offset);
243 for (i = 0; i < us_info->rx_bd_ring_len - 1; i++) {236 for (i = 0; i < us_info->rx_bd_ring_len - 1; i++) {
244 /* set bd status and length */237 /* set bd status and length */
245 qe_iowrite32be(0, (u32 *)bd);238 qe_iowrite32be(0, (u32 __iomem *)bd);
246 /* clear bd buffer */239 /* clear bd buffer */
247 qe_iowrite32be(0, &bd->buf);240 qe_iowrite32be(0, &bd->buf);
248 bd++;241 bd++;
249 }242 }
250 /* for last BD set Wrap bit */243 /* for last BD set Wrap bit */
251 qe_iowrite32be(cpu_to_be32(R_W), (u32 *)bd);244 qe_iowrite32be(R_W, (u32 __iomem *)bd);
252 qe_iowrite32be(0, &bd->buf);245 qe_iowrite32be(0, &bd->buf);
253 246
254 /* Set GUMR (For more details see the hardware spec.). */247 /* Set GUMR (For more details see the hardware spec.). */
@@ -273,8 +266,8 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc · 18 unmodified lines
273 qe_iowrite32be(gumr, &us_regs->gumr_h);266 qe_iowrite32be(gumr, &us_regs->gumr_h);
274 267
275 /* gumr_l */268 /* gumr_l */
276 gumr = us_info->tdcr | us_info->rdcr | us_info->tenc | us_info->renc |269 gumr = (u32)us_info->tdcr | (u32)us_info->rdcr | (u32)us_info->tenc |
277 us_info->diag | us_info->mode;270 (u32)us_info->renc | (u32)us_info->diag | (u32)us_info->mode;
278 if (us_info->tci)271 if (us_info->tci)
279 gumr |= UCC_SLOW_GUMR_L_TCI;272 gumr |= UCC_SLOW_GUMR_L_TCI;
280 if (us_info->rinv)273 if (us_info->rinv)
@@ -289,8 +282,8 @@ int ucc_slow_init(struct ucc_slow_info * us_info, struct ucc_slow_private ** ucc · 8 unmodified lines
289 282
290 /* if the data is in cachable memory, the 'global' */283 /* if the data is in cachable memory, the 'global' */
291 /* in the function code should be set. */284 /* in the function code should be set. */
292 uccs->us_pram->tbmr = UCC_BMR_BO_BE;285 qe_iowrite8(UCC_BMR_BO_BE, &uccs->us_pram->tbmr);
293 uccs->us_pram->rbmr = UCC_BMR_BO_BE;286 qe_iowrite8(UCC_BMR_BO_BE, &uccs->us_pram->rbmr);
294 287
295 /* rbase, tbase are offsets from MURAM base */288 /* rbase, tbase are offsets from MURAM base */
296 qe_iowrite16be(uccs->rx_base_offset, &uccs->us_pram->rbase);289 qe_iowrite16be(uccs->rx_base_offset, &uccs->us_pram->rbase);
drivers/soc/imx/Kconfig+10−1
@@ -10,11 +10,20 @@ config IMX_GPCV2_PM_DOMAINS · 9 unmodified lines
10 10
11config IMX_SCU_SOC11config IMX_SCU_SOC
12 bool "i.MX System Controller Unit SoC info support"12 bool "i.MX System Controller Unit SoC info support"
13 depends on IMX_SCU || COMPILE_TEST13 depends on IMX_SCU
14 select SOC_BUS14 select SOC_BUS
15 help15 help
16 If you say yes here you get support for the NXP i.MX System16 If you say yes here you get support for the NXP i.MX System
17 Controller Unit SoC info module, it will provide the SoC info17 Controller Unit SoC info module, it will provide the SoC info
18 like SoC family, ID and revision etc.18 like SoC family, ID and revision etc.
19 19
20config SOC_IMX8M
21 bool "i.MX8M SoC family support"
22 depends on ARCH_MXC || COMPILE_TEST
23 default ARCH_MXC && ARM64
24 help
25 If you say yes here you get support for the NXP i.MX8M family
26 support, it will provide the SoC info like SoC family,
27 ID and revision etc.
28
20endmenu29endmenu
drivers/soc/imx/Makefile+1−1
@@ -1,5 +1,5 @@
1# SPDX-License-Identifier: GPL-2.0-only1# SPDX-License-Identifier: GPL-2.0-only
2obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o2obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
3obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o3obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
4obj-$(CONFIG_ARCH_MXC) += soc-imx8.o4obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o
5obj-$(CONFIG_IMX_SCU_SOC) += soc-imx-scu.o5obj-$(CONFIG_IMX_SCU_SOC) += soc-imx-scu.o
drivers/soc/imx/gpc.c+13−11
@@ -87,8 +87,8 @@ static int imx6_pm_domain_power_off(struct generic_pm_domain *genpd) · 86 unmodified lines
87static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd)87static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd)
88{88{
89 struct imx_pm_domain *pd = to_imx_pm_domain(genpd);89 struct imx_pm_domain *pd = to_imx_pm_domain(genpd);
90 int i, ret, sw, sw2iso;90 int i, ret;
91 u32 val;91 u32 val, req;
92 92
93 if (pd->supply) {93 if (pd->supply) {
94 ret = regulator_enable(pd->supply);94 ret = regulator_enable(pd->supply);
@@ -107,17 +107,18 @@ static int imx6_pm_domain_power_on(struct generic_pm_domain *genpd) · 12 unmodified lines
107 regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,107 regmap_update_bits(pd->regmap, pd->reg_offs + GPC_PGC_CTRL_OFFS,
108 0x1, 0x1);108 0x1, 0x1);
109 109
110 /* Read ISO and ISO2SW power up delays */
111 regmap_read(pd->regmap, pd->reg_offs + GPC_PGC_PUPSCR_OFFS, &val);
112 sw = val & 0x3f;
113 sw2iso = (val >> 8) & 0x3f;
114
115 /* Request GPC to power up domain */110 /* Request GPC to power up domain */
116 val = BIT(pd->cntr_pdn_bit + 1);111 req = BIT(pd->cntr_pdn_bit + 1);
117 regmap_update_bits(pd->regmap, GPC_CNTR, val, val);112 regmap_update_bits(pd->regmap, GPC_CNTR, req, req);
118 113
119 /* Wait ISO + ISO2SW IPG clock cycles */114 /* Wait for the PGC to handle the request */
120 udelay(DIV_ROUND_UP(sw + sw2iso, pd->ipg_rate_mhz));115 ret = regmap_read_poll_timeout(pd->regmap, GPC_CNTR, val, !(val & req),
116 1, 50);
117 if (ret)
118 pr_err("powerup request on domain %s timed out\n", genpd->name);
119
120 /* Wait for reset to propagate through peripherals */
121 usleep_range(5, 10);
121 122
122 /* Disable reset clocks for all devices in the domain */123 /* Disable reset clocks for all devices in the domain */
123 for (i = 0; i < pd->num_clks; i++)124 for (i = 0; i < pd->num_clks; i++)
@@ -343,6 +344,7 @@ static const struct regmap_config imx_gpc_regmap_config = { · 219 unmodified lines
343 .rd_table = &access_table,344 .rd_table = &access_table,
344 .wr_table = &access_table,345 .wr_table = &access_table,
345 .max_register = 0x2ac,346 .max_register = 0x2ac,
347 .fast_io = true,
346};348};
347 349
348static struct generic_pm_domain *imx_gpc_onecell_domains[] = {350static struct generic_pm_domain *imx_gpc_onecell_domains[] = {
drivers/soc/imx/gpcv2.c+1−0
@@ -14,6 +14,7 @@ · 13 unmodified lines
14#include <linux/pm_domain.h>14#include <linux/pm_domain.h>
15#include <linux/regmap.h>15#include <linux/regmap.h>
16#include <linux/regulator/consumer.h>16#include <linux/regulator/consumer.h>
17#include <linux/sizes.h>
17#include <dt-bindings/power/imx7-power.h>18#include <dt-bindings/power/imx7-power.h>
18#include <dt-bindings/power/imx8mq-power.h>19#include <dt-bindings/power/imx8mq-power.h>
19 20
drivers/soc/imx/soc-imx8m.crenamed from drivers/soc/imx/soc-imx8.c+0−0

File renamed without changes.

drivers/soc/qcom/Kconfig+6−1
@@ -76,6 +76,10 @@ config QCOM_OCMEM · 75 unmodified lines
76 requirements. This is typically used by the GPU, camera/video, and76 requirements. This is typically used by the GPU, camera/video, and
77 audio components on some Snapdragon SoCs.77 audio components on some Snapdragon SoCs.
78 78
79config QCOM_PDR_HELPERS
80 tristate
81 select QCOM_QMI_HELPERS
82
79config QCOM_PM83config QCOM_PM
80 bool "Qualcomm Power Management"84 bool "Qualcomm Power Management"
81 depends on ARCH_QCOM && !ARM6485 depends on ARCH_QCOM && !ARM64
@@ -88,7 +92,6 @@ config QCOM_PM · 6 unmodified lines
88 92
89config QCOM_QMI_HELPERS93config QCOM_QMI_HELPERS
90 tristate94 tristate
91 depends on ARCH_QCOM || COMPILE_TEST
92 depends on NET95 depends on NET
93 96
94config QCOM_RMTFS_MEM97config QCOM_RMTFS_MEM
@@ -197,6 +200,8 @@ config QCOM_APR · 102 unmodified lines
197 tristate "Qualcomm APR Bus (Asynchronous Packet Router)"200 tristate "Qualcomm APR Bus (Asynchronous Packet Router)"
198 depends on ARCH_QCOM || COMPILE_TEST201 depends on ARCH_QCOM || COMPILE_TEST
199 depends on RPMSG202 depends on RPMSG
203 depends on NET
204 select QCOM_PDR_HELPERS
200 help205 help
201 Enable APR IPC protocol support between206 Enable APR IPC protocol support between
202 application processor and QDSP6. APR is207 application processor and QDSP6. APR is
drivers/soc/qcom/Makefile+1−0
@@ -7,6 +7,7 @@ obj-$(CONFIG_QCOM_GLINK_SSR) += glink_ssr.o · 6 unmodified lines
7obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o7obj-$(CONFIG_QCOM_GSBI) += qcom_gsbi.o
8obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o8obj-$(CONFIG_QCOM_MDT_LOADER) += mdt_loader.o
9obj-$(CONFIG_QCOM_OCMEM) += ocmem.o9obj-$(CONFIG_QCOM_OCMEM) += ocmem.o
10obj-$(CONFIG_QCOM_PDR_HELPERS) += pdr_interface.o
10obj-$(CONFIG_QCOM_PM) += spm.o11obj-$(CONFIG_QCOM_PM) += spm.o
11obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o12obj-$(CONFIG_QCOM_QMI_HELPERS) += qmi_helpers.o
12qmi_helpers-y += qmi_encdec.o qmi_interface.o13qmi_helpers-y += qmi_encdec.o qmi_interface.o
drivers/soc/qcom/apr.c+114−9
@@ -11,6 +11,7 @@ · 10 unmodified lines
11#include <linux/workqueue.h>11#include <linux/workqueue.h>
12#include <linux/of_device.h>12#include <linux/of_device.h>
13#include <linux/soc/qcom/apr.h>13#include <linux/soc/qcom/apr.h>
14#include <linux/soc/qcom/pdr.h>
14#include <linux/rpmsg.h>15#include <linux/rpmsg.h>
15#include <linux/of.h>16#include <linux/of.h>
16 17
@@ -21,6 +22,7 @@ struct apr { · 4 unmodified lines
21 spinlock_t rx_lock;22 spinlock_t rx_lock;
22 struct idr svcs_idr;23 struct idr svcs_idr;
23 int dest_domain_id;24 int dest_domain_id;
25 struct pdr_handle *pdr;
24 struct workqueue_struct *rxwq;26 struct workqueue_struct *rxwq;
25 struct work_struct rx_work;27 struct work_struct rx_work;
26 struct list_head rx_list;28 struct list_head rx_list;
@@ -289,6 +291,9 @@ static int apr_add_device(struct device *dev, struct device_node *np, · 262 unmodified lines
289 id->svc_id + 1, GFP_ATOMIC);291 id->svc_id + 1, GFP_ATOMIC);
290 spin_unlock(&apr->svcs_lock);292 spin_unlock(&apr->svcs_lock);
291 293
294 of_property_read_string_index(np, "qcom,protection-domain",
295 1, &adev->service_path);
296
292 dev_info(dev, "Adding APR dev: %s\n", dev_name(&adev->dev));297 dev_info(dev, "Adding APR dev: %s\n", dev_name(&adev->dev));
293 298
294 ret = device_register(&adev->dev);299 ret = device_register(&adev->dev);
@@ -300,14 +305,75 @@ static int apr_add_device(struct device *dev, struct device_node *np, · 5 unmodified lines
300 return ret;305 return ret;
301}306}
302 307
303static void of_register_apr_devices(struct device *dev)308static int of_apr_add_pd_lookups(struct device *dev)
309{
310 const char *service_name, *service_path;
311 struct apr *apr = dev_get_drvdata(dev);
312 struct device_node *node;
313 struct pdr_service *pds;
314 int ret;
315
316 for_each_child_of_node(dev->of_node, node) {
317 ret = of_property_read_string_index(node, "qcom,protection-domain",
318 0, &service_name);
319 if (ret < 0)
320 continue;
321
322 ret = of_property_read_string_index(node, "qcom,protection-domain",
323 1, &service_path);
324 if (ret < 0) {
325 dev_err(dev, "pdr service path missing: %d\n", ret);
326 return ret;
327 }
328
329 pds = pdr_add_lookup(apr->pdr, service_name, service_path);
330 if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) {
331 dev_err(dev, "pdr add lookup failed: %d\n", ret);
332 return PTR_ERR(pds);
333 }
334 }
335
336 return 0;
337}
338
339static void of_register_apr_devices(struct device *dev, const char *svc_path)
304{340{
305 struct apr *apr = dev_get_drvdata(dev);341 struct apr *apr = dev_get_drvdata(dev);
306 struct device_node *node;342 struct device_node *node;
343 const char *service_path;
344 int ret;
307 345
308 for_each_child_of_node(dev->of_node, node) {346 for_each_child_of_node(dev->of_node, node) {
309 struct apr_device_id id = { {0} };347 struct apr_device_id id = { {0} };
310 348
349 /*
350 * This function is called with svc_path NULL during
351 * apr_probe(), in which case we register any apr devices
352 * without a qcom,protection-domain specified.
353 *
354 * Then as the protection domains becomes available
355 * (if applicable) this function is again called, but with
356 * svc_path representing the service becoming available. In
357 * this case we register any apr devices with a matching
358 * qcom,protection-domain.
359 */
360
361 ret = of_property_read_string_index(node, "qcom,protection-domain",
362 1, &service_path);
363 if (svc_path) {
364 /* skip APR services that are PD independent */
365 if (ret)
366 continue;
367
368 /* skip APR services whose PD paths don't match */
369 if (strcmp(service_path, svc_path))
370 continue;
371 } else {
372 /* skip APR services whose PD lookups are registered */
373 if (ret == 0)
374 continue;
375 }
376
311 if (of_property_read_u32(node, "reg", &id.svc_id))377 if (of_property_read_u32(node, "reg", &id.svc_id))
312 continue;378 continue;
313 379
@@ -318,6 +384,34 @@ static void of_register_apr_devices(struct device *dev) · 4 unmodified lines
318 }384 }
319}385}
320 386
387static int apr_remove_device(struct device *dev, void *svc_path)
388{
389 struct apr_device *adev = to_apr_device(dev);
390
391 if (svc_path && adev->service_path) {
392 if (!strcmp(adev->service_path, (char *)svc_path))
393 device_unregister(&adev->dev);
394 } else {
395 device_unregister(&adev->dev);
396 }
397
398 return 0;
399}
400
401static void apr_pd_status(int state, char *svc_path, void *priv)
402{
403 struct apr *apr = (struct apr *)priv;
404
405 switch (state) {
406 case SERVREG_SERVICE_STATE_UP:
407 of_register_apr_devices(apr->dev, svc_path);
408 break;
409 case SERVREG_SERVICE_STATE_DOWN:
410 device_for_each_child(apr->dev, svc_path, apr_remove_device);
411 break;
412 }
413}
414
321static int apr_probe(struct rpmsg_device *rpdev)415static int apr_probe(struct rpmsg_device *rpdev)
322{416{
323 struct device *dev = &rpdev->dev;417 struct device *dev = &rpdev->dev;
@@ -343,28 +437,39 @@ static int apr_probe(struct rpmsg_device *rpdev) · 19 unmodified lines
343 return -ENOMEM;437 return -ENOMEM;
344 }438 }
345 INIT_WORK(&apr->rx_work, apr_rxwq);439 INIT_WORK(&apr->rx_work, apr_rxwq);
440
441 apr->pdr = pdr_handle_alloc(apr_pd_status, apr);
442 if (IS_ERR(apr->pdr)) {
443 dev_err(dev, "Failed to init PDR handle\n");
444 ret = PTR_ERR(apr->pdr);
445 goto destroy_wq;
446 }
447
346 INIT_LIST_HEAD(&apr->rx_list);448 INIT_LIST_HEAD(&apr->rx_list);
347 spin_lock_init(&apr->rx_lock);449 spin_lock_init(&apr->rx_lock);
348 spin_lock_init(&apr->svcs_lock);450 spin_lock_init(&apr->svcs_lock);
349 idr_init(&apr->svcs_idr);451 idr_init(&apr->svcs_idr);
350 of_register_apr_devices(dev);
351
352 return 0;
353}
354 452
355static int apr_remove_device(struct device *dev, void *null)453 ret = of_apr_add_pd_lookups(dev);
356{454 if (ret)
357 struct apr_device *adev = to_apr_device(dev);455 goto handle_release;
358 456
359 device_unregister(&adev->dev);457 of_register_apr_devices(dev, NULL);
360 458
361 return 0;459 return 0;
460
461handle_release:
462 pdr_handle_release(apr->pdr);
463destroy_wq:
464 destroy_workqueue(apr->rxwq);
465 return ret;
362}466}
363 467
364static void apr_remove(struct rpmsg_device *rpdev)468static void apr_remove(struct rpmsg_device *rpdev)
365{469{
366 struct apr *apr = dev_get_drvdata(&rpdev->dev);470 struct apr *apr = dev_get_drvdata(&rpdev->dev);
367 471
472 pdr_handle_release(apr->pdr);
368 device_for_each_child(&rpdev->dev, NULL, apr_remove_device);473 device_for_each_child(&rpdev->dev, NULL, apr_remove_device);
369 flush_workqueue(apr->rxwq);474 flush_workqueue(apr->rxwq);
370 destroy_workqueue(apr->rxwq);475 destroy_workqueue(apr->rxwq);
drivers/soc/qcom/pdr_interface.c+757−0
@@ -0,0 +1,757 @@
1// SPDX-License-Identifier: GPL-2.0
2/*
3 * Copyright (C) 2020 The Linux Foundation. All rights reserved.
4 */
5
6#include <linux/kernel.h>
7#include <linux/module.h>
8#include <linux/string.h>
9#include <linux/workqueue.h>
10
11#include "pdr_internal.h"
12
13struct pdr_service {
14 char service_name[SERVREG_NAME_LENGTH + 1];
15 char service_path[SERVREG_NAME_LENGTH + 1];
16
17 struct sockaddr_qrtr addr;
18
19 unsigned int instance;
20 unsigned int service;
21 u8 service_data_valid;
22 u32 service_data;
23 int state;
24
25 bool need_notifier_register;
26 bool need_notifier_remove;
27 bool need_locator_lookup;
28 bool service_connected;
29
30 struct list_head node;
31};
32
33struct pdr_handle {
34 struct qmi_handle locator_hdl;
35 struct qmi_handle notifier_hdl;
36
37 struct sockaddr_qrtr locator_addr;
38
39 struct list_head lookups;
40 struct list_head indack_list;
41
42 /* control access to pdr lookup/indack lists */
43 struct mutex list_lock;
44
45 /* serialize pd status invocation */
46 struct mutex status_lock;
47
48 /* control access to the locator state */
49 struct mutex lock;
50
51 bool locator_init_complete;
52
53 struct work_struct locator_work;
54 struct work_struct notifier_work;
55 struct work_struct indack_work;
56
57 struct workqueue_struct *notifier_wq;
58 struct workqueue_struct *indack_wq;
59
60 void (*status)(int state, char *service_path, void *priv);
61 void *priv;
62};
63
64struct pdr_list_node {
65 enum servreg_service_state curr_state;
66 u16 transaction_id;
67 struct pdr_service *pds;
68 struct list_head node;
69};
70
71static int pdr_locator_new_server(struct qmi_handle *qmi,
72 struct qmi_service *svc)
73{
74 struct pdr_handle *pdr = container_of(qmi, struct pdr_handle,
75 locator_hdl);
76 struct pdr_service *pds;
77
78 /* Create a local client port for QMI communication */
79 pdr->locator_addr.sq_family = AF_QIPCRTR;
80 pdr->locator_addr.sq_node = svc->node;
81 pdr->locator_addr.sq_port = svc->port;
82
83 mutex_lock(&pdr->lock);
84 pdr->locator_init_complete = true;
85 mutex_unlock(&pdr->lock);
86
87 /* Service pending lookup requests */
88 mutex_lock(&pdr->list_lock);
89 list_for_each_entry(pds, &pdr->lookups, node) {
90 if (pds->need_locator_lookup)
91 schedule_work(&pdr->locator_work);
92 }
93 mutex_unlock(&pdr->list_lock);
94
95 return 0;
96}
97
98static void pdr_locator_del_server(struct qmi_handle *qmi,
99 struct qmi_service *svc)
100{
101 struct pdr_handle *pdr = container_of(qmi, struct pdr_handle,
102 locator_hdl);
103
104 mutex_lock(&pdr->lock);
105 pdr->locator_init_complete = false;
106 mutex_unlock(&pdr->lock);
107
108 pdr->locator_addr.sq_node = 0;
109 pdr->locator_addr.sq_port = 0;
110}
111
112static struct qmi_ops pdr_locator_ops = {
113 .new_server = pdr_locator_new_server,
114 .del_server = pdr_locator_del_server,
115};
116
117static int pdr_register_listener(struct pdr_handle *pdr,
118 struct pdr_service *pds,
119 bool enable)
120{
121 struct servreg_register_listener_resp resp;
122 struct servreg_register_listener_req req;
123 struct qmi_txn txn;
124 int ret;
125
126 ret = qmi_txn_init(&pdr->notifier_hdl, &txn,
127 servreg_register_listener_resp_ei,
128 &resp);
129 if (ret < 0)
130 return ret;
131
132 req.enable = enable;
133 strcpy(req.service_path, pds->service_path);
134
135 ret = qmi_send_request(&pdr->notifier_hdl, &pds->addr,
136 &txn, SERVREG_REGISTER_LISTENER_REQ,
137 SERVREG_REGISTER_LISTENER_REQ_LEN,
138 servreg_register_listener_req_ei,
139 &req);
140 if (ret < 0) {
141 qmi_txn_cancel(&txn);
142 return ret;
143 }
144
145 ret = qmi_txn_wait(&txn, 5 * HZ);
146 if (ret < 0) {
147 pr_err("PDR: %s register listener txn wait failed: %d\n",
148 pds->service_path, ret);
149 return ret;
150 }
151
152 if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
153 pr_err("PDR: %s register listener failed: 0x%x\n",
154 pds->service_path, resp.resp.error);
155 return ret;
156 }
157
158 if ((int)resp.curr_state < INT_MIN || (int)resp.curr_state > INT_MAX)
159 pr_err("PDR: %s notification state invalid: 0x%x\n",
160 pds->service_path, resp.curr_state);
161
162 pds->state = resp.curr_state;
163
164 return 0;
165}
166
167static void pdr_notifier_work(struct work_struct *work)
168{
169 struct pdr_handle *pdr = container_of(work, struct pdr_handle,
170 notifier_work);
171 struct pdr_service *pds;
172 int ret;
173
174 mutex_lock(&pdr->list_lock);
175 list_for_each_entry(pds, &pdr->lookups, node) {
176 if (pds->service_connected) {
177 if (!pds->need_notifier_register)
178 continue;
179
180 pds->need_notifier_register = false;
181 ret = pdr_register_listener(pdr, pds, true);
182 if (ret < 0)
183 pds->state = SERVREG_SERVICE_STATE_DOWN;
184 } else {
185 if (!pds->need_notifier_remove)
186 continue;
187
188 pds->need_notifier_remove = false;
189 pds->state = SERVREG_SERVICE_STATE_DOWN;
190 }
191
192 mutex_lock(&pdr->status_lock);
193 pdr->status(pds->state, pds->service_path, pdr->priv);
194 mutex_unlock(&pdr->status_lock);
195 }
196 mutex_unlock(&pdr->list_lock);
197}
198
199static int pdr_notifier_new_server(struct qmi_handle *qmi,
200 struct qmi_service *svc)
201{
202 struct pdr_handle *pdr = container_of(qmi, struct pdr_handle,
203 notifier_hdl);
204 struct pdr_service *pds;
205
206 mutex_lock(&pdr->list_lock);
207 list_for_each_entry(pds, &pdr->lookups, node) {
208 if (pds->service == svc->service &&
209 pds->instance == svc->instance) {
210 pds->service_connected = true;
211 pds->need_notifier_register = true;
212 pds->addr.sq_family = AF_QIPCRTR;
213 pds->addr.sq_node = svc->node;
214 pds->addr.sq_port = svc->port;
215 queue_work(pdr->notifier_wq, &pdr->notifier_work);
216 }
217 }
218 mutex_unlock(&pdr->list_lock);
219
220 return 0;
221}
222
223static void pdr_notifier_del_server(struct qmi_handle *qmi,
224 struct qmi_service *svc)
225{
226 struct pdr_handle *pdr = container_of(qmi, struct pdr_handle,
227 notifier_hdl);
228 struct pdr_service *pds;
229
230 mutex_lock(&pdr->list_lock);
231 list_for_each_entry(pds, &pdr->lookups, node) {
232 if (pds->service == svc->service &&
233 pds->instance == svc->instance) {
234 pds->service_connected = false;
235 pds->need_notifier_remove = true;
236 pds->addr.sq_node = 0;
237 pds->addr.sq_port = 0;
238 queue_work(pdr->notifier_wq, &pdr->notifier_work);
239 }
240 }
241 mutex_unlock(&pdr->list_lock);
242}
243
244static struct qmi_ops pdr_notifier_ops = {
245 .new_server = pdr_notifier_new_server,
246 .del_server = pdr_notifier_del_server,
247};
248
249static int pdr_send_indack_msg(struct pdr_handle *pdr, struct pdr_service *pds,
250 u16 tid)
251{
252 struct servreg_set_ack_resp resp;
253 struct servreg_set_ack_req req;
254 struct qmi_txn txn;
255 int ret;
256
257 ret = qmi_txn_init(&pdr->notifier_hdl, &txn, servreg_set_ack_resp_ei,
258 &resp);
259 if (ret < 0)
260 return ret;
261
262 req.transaction_id = tid;
263 strcpy(req.service_path, pds->service_path);
264
265 ret = qmi_send_request(&pdr->notifier_hdl, &pds->addr,
266 &txn, SERVREG_SET_ACK_REQ,
267 SERVREG_SET_ACK_REQ_LEN,
268 servreg_set_ack_req_ei,
269 &req);
270
271 /* Skip waiting for response */
272 qmi_txn_cancel(&txn);
273 return ret;
274}
275
276static void pdr_indack_work(struct work_struct *work)
277{
278 struct pdr_handle *pdr = container_of(work, struct pdr_handle,
279 indack_work);
280 struct pdr_list_node *ind, *tmp;
281 struct pdr_service *pds;
282
283 list_for_each_entry_safe(ind, tmp, &pdr->indack_list, node) {
284 pds = ind->pds;
285 pdr_send_indack_msg(pdr, pds, ind->transaction_id);
286
287 mutex_lock(&pdr->status_lock);
288 pds->state = ind->curr_state;
289 pdr->status(pds->state, pds->service_path, pdr->priv);
290 mutex_unlock(&pdr->status_lock);
291
292 mutex_lock(&pdr->list_lock);
293 list_del(&ind->node);
294 mutex_unlock(&pdr->list_lock);
295
296 kfree(ind);
297 }
298}
299
300static void pdr_indication_cb(struct qmi_handle *qmi,
301 struct sockaddr_qrtr *sq,
302 struct qmi_txn *txn, const void *data)
303{
304 struct pdr_handle *pdr = container_of(qmi, struct pdr_handle,
305 notifier_hdl);
306 const struct servreg_state_updated_ind *ind_msg = data;
307 struct pdr_list_node *ind;
308 struct pdr_service *pds;
309 bool found = false;
310
311 if (!ind_msg || !ind_msg->service_path[0] ||
312 strlen(ind_msg->service_path) > SERVREG_NAME_LENGTH)
313 return;
314
315 mutex_lock(&pdr->list_lock);
316 list_for_each_entry(pds, &pdr->lookups, node) {
317 if (strcmp(pds->service_path, ind_msg->service_path))
318 continue;
319
320 found = true;
321 break;
322 }
323 mutex_unlock(&pdr->list_lock);
324
325 if (!found)
326 return;
327
328 pr_info("PDR: Indication received from %s, state: 0x%x, trans-id: %d\n",
329 ind_msg->service_path, ind_msg->curr_state,
330 ind_msg->transaction_id);
331
332 ind = kzalloc(sizeof(*ind), GFP_KERNEL);
333 if (!ind)
334 return;
335
336 ind->transaction_id = ind_msg->transaction_id;
337 ind->curr_state = ind_msg->curr_state;
338 ind->pds = pds;
339
340 mutex_lock(&pdr->list_lock);
341 list_add_tail(&ind->node, &pdr->indack_list);
342 mutex_unlock(&pdr->list_lock);
343
344 queue_work(pdr->indack_wq, &pdr->indack_work);
345}
346
347static struct qmi_msg_handler qmi_indication_handler[] = {
348 {
349 .type = QMI_INDICATION,
350 .msg_id = SERVREG_STATE_UPDATED_IND_ID,
351 .ei = servreg_state_updated_ind_ei,
352 .decoded_size = sizeof(struct servreg_state_updated_ind),
353 .fn = pdr_indication_cb,
354 },
355 {}
356};
357
358static int pdr_get_domain_list(struct servreg_get_domain_list_req *req,
359 struct servreg_get_domain_list_resp *resp,
360 struct pdr_handle *pdr)
361{
362 struct qmi_txn txn;
363 int ret;
364
365 ret = qmi_txn_init(&pdr->locator_hdl, &txn,
366 servreg_get_domain_list_resp_ei, resp);
367 if (ret < 0)
368 return ret;
369
370 ret = qmi_send_request(&pdr->locator_hdl,
371 &pdr->locator_addr,
372 &txn, SERVREG_GET_DOMAIN_LIST_REQ,
373 SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN,
374 servreg_get_domain_list_req_ei,
375 req);
376 if (ret < 0) {
377 qmi_txn_cancel(&txn);
378 return ret;
379 }
380
381 ret = qmi_txn_wait(&txn, 5 * HZ);
382 if (ret < 0) {
383 pr_err("PDR: %s get domain list txn wait failed: %d\n",
384 req->service_name, ret);
385 return ret;
386 }
387
388 if (resp->resp.result != QMI_RESULT_SUCCESS_V01) {
389 pr_err("PDR: %s get domain list failed: 0x%x\n",
390 req->service_name, resp->resp.error);
391 return -EREMOTEIO;
392 }
393
394 return 0;
395}
396
397static int pdr_locate_service(struct pdr_handle *pdr, struct pdr_service *pds)
398{
399 struct servreg_get_domain_list_resp *resp;
400 struct servreg_get_domain_list_req req;
401 struct servreg_location_entry *entry;
402 int domains_read = 0;
403 int ret, i;
404
405 resp = kzalloc(sizeof(*resp), GFP_KERNEL);
406 if (!resp)
407 return -ENOMEM;
408
409 /* Prepare req message */
410 strcpy(req.service_name, pds->service_name);
411 req.domain_offset_valid = true;
412 req.domain_offset = 0;
413
414 do {
415 req.domain_offset = domains_read;
416 ret = pdr_get_domain_list(&req, resp, pdr);
417 if (ret < 0)
418 goto out;
419
420 for (i = domains_read; i < resp->domain_list_len; i++) {
421 entry = &resp->domain_list[i];
422
423 if (strnlen(entry->name, sizeof(entry->name)) == sizeof(entry->name))
424 continue;
425
426 if (!strcmp(entry->name, pds->service_path)) {
427 pds->service_data_valid = entry->service_data_valid;
428 pds->service_data = entry->service_data;
429 pds->instance = entry->instance;
430 goto out;
431 }
432 }
433
434 /* Update ret to indicate that the service is not yet found */
435 ret = -ENXIO;
436
437 /* Always read total_domains from the response msg */
438 if (resp->domain_list_len > resp->total_domains)
439 resp->domain_list_len = resp->total_domains;
440
441 domains_read += resp->domain_list_len;
442 } while (domains_read < resp->total_domains);
443out:
444 kfree(resp);
445 return ret;
446}
447
448static void pdr_notify_lookup_failure(struct pdr_handle *pdr,
449 struct pdr_service *pds,
450 int err)
451{
452 pr_err("PDR: service lookup for %s failed: %d\n",
453 pds->service_name, err);
454
455 if (err == -ENXIO)
456 return;
457
458 list_del(&pds->node);
459 pds->state = SERVREG_LOCATOR_ERR;
460 mutex_lock(&pdr->status_lock);
461 pdr->status(pds->state, pds->service_path, pdr->priv);
462 mutex_unlock(&pdr->status_lock);
463 kfree(pds);
464}
465
466static void pdr_locator_work(struct work_struct *work)
467{
468 struct pdr_handle *pdr = container_of(work, struct pdr_handle,
469 locator_work);
470 struct pdr_service *pds, *tmp;
471 int ret = 0;
472
473 /* Bail out early if the SERVREG LOCATOR QMI service is not up */
474 mutex_lock(&pdr->lock);
475 if (!pdr->locator_init_complete) {
476 mutex_unlock(&pdr->lock);
477 pr_debug("PDR: SERVICE LOCATOR service not available\n");
478 return;
479 }
480 mutex_unlock(&pdr->lock);
481
482 mutex_lock(&pdr->list_lock);
483 list_for_each_entry_safe(pds, tmp, &pdr->lookups, node) {
484 if (!pds->need_locator_lookup)
485 continue;
486
487 ret = pdr_locate_service(pdr, pds);
488 if (ret < 0) {
489 pdr_notify_lookup_failure(pdr, pds, ret);
490 continue;
491 }
492
493 ret = qmi_add_lookup(&pdr->notifier_hdl, pds->service, 1,
494 pds->instance);
495 if (ret < 0) {
496 pdr_notify_lookup_failure(pdr, pds, ret);
497 continue;
498 }
499
500 pds->need_locator_lookup = false;
501 }
502 mutex_unlock(&pdr->list_lock);
503}
504
505/**
506 * pdr_add_lookup() - register a tracking request for a PD
507 * @pdr: PDR client handle
508 * @service_name: service name of the tracking request
509 * @service_path: service path of the tracking request
510 *
511 * Registering a pdr lookup allows for tracking the life cycle of the PD.
512 *
513 * Return: pdr_service object on success, ERR_PTR on failure. -EALREADY is
514 * returned if a lookup is already in progress for the given service path.
515 */
516struct pdr_service *pdr_add_lookup(struct pdr_handle *pdr,
517 const char *service_name,
518 const char *service_path)
519{
520 struct pdr_service *pds, *tmp;
521 int ret;
522
523 if (IS_ERR_OR_NULL(pdr))
524 return ERR_PTR(-EINVAL);
525
526 if (!service_name || strlen(service_name) > SERVREG_NAME_LENGTH ||
527 !service_path || strlen(service_path) > SERVREG_NAME_LENGTH)
528 return ERR_PTR(-EINVAL);
529
530 pds = kzalloc(sizeof(*pds), GFP_KERNEL);
531 if (!pds)
532 return ERR_PTR(-ENOMEM);
533
534 pds->service = SERVREG_NOTIFIER_SERVICE;
535 strcpy(pds->service_name, service_name);
536 strcpy(pds->service_path, service_path);
537 pds->need_locator_lookup = true;
538
539 mutex_lock(&pdr->list_lock);
540 list_for_each_entry(tmp, &pdr->lookups, node) {
541 if (strcmp(tmp->service_path, service_path))
542 continue;
543
544 mutex_unlock(&pdr->list_lock);
545 ret = -EALREADY;
546 goto err;
547 }
548
549 list_add(&pds->node, &pdr->lookups);
550 mutex_unlock(&pdr->list_lock);
551
552 schedule_work(&pdr->locator_work);
553
554 return pds;
555err:
556 kfree(pds);
557 return ERR_PTR(ret);
558}
559EXPORT_SYMBOL(pdr_add_lookup);
560
561/**
562 * pdr_restart_pd() - restart PD
563 * @pdr: PDR client handle
564 * @pds: PD service handle
565 *
566 * Restarts the PD tracked by the PDR client handle for a given service path.
567 *
568 * Return: 0 on success, negative errno on failure.
569 */
570int pdr_restart_pd(struct pdr_handle *pdr, struct pdr_service *pds)
571{
572 struct servreg_restart_pd_resp resp;
573 struct servreg_restart_pd_req req;
574 struct sockaddr_qrtr addr;
575 struct pdr_service *tmp;
576 struct qmi_txn txn;
577 int ret;
578
579 if (IS_ERR_OR_NULL(pdr) || IS_ERR_OR_NULL(pds))
580 return -EINVAL;
581
582 mutex_lock(&pdr->list_lock);
583 list_for_each_entry(tmp, &pdr->lookups, node) {
584 if (tmp != pds)
585 continue;
586
587 if (!pds->service_connected)
588 break;
589
590 /* Prepare req message */
591 strcpy(req.service_path, pds->service_path);
592 addr = pds->addr;
593 break;
594 }
595 mutex_unlock(&pdr->list_lock);
596
597 if (!req.service_path[0])
598 return -EINVAL;
599
600 ret = qmi_txn_init(&pdr->notifier_hdl, &txn,
601 servreg_restart_pd_resp_ei,
602 &resp);
603 if (ret < 0)
604 return ret;
605
606 ret = qmi_send_request(&pdr->notifier_hdl, &addr,
607 &txn, SERVREG_RESTART_PD_REQ,
608 SERVREG_RESTART_PD_REQ_MAX_LEN,
609 servreg_restart_pd_req_ei, &req);
610 if (ret < 0) {
611 qmi_txn_cancel(&txn);
612 return ret;
613 }
614
615 ret = qmi_txn_wait(&txn, 5 * HZ);
616 if (ret < 0) {
617 pr_err("PDR: %s PD restart txn wait failed: %d\n",
618 req.service_path, ret);
619 return ret;
620 }
621
622 /* Check response if PDR is disabled */
623 if (resp.resp.result == QMI_RESULT_FAILURE_V01 &&
624 resp.resp.error == QMI_ERR_DISABLED_V01) {
625 pr_err("PDR: %s PD restart is disabled: 0x%x\n",
626 req.service_path, resp.resp.error);
627 return -EOPNOTSUPP;
628 }
629
630 /* Check the response for other error case*/
631 if (resp.resp.result != QMI_RESULT_SUCCESS_V01) {
632 pr_err("PDR: %s request for PD restart failed: 0x%x\n",
633 req.service_path, resp.resp.error);
634 return -EREMOTEIO;
635 }
636
637 return 0;
638}
639EXPORT_SYMBOL(pdr_restart_pd);
640
641/**
642 * pdr_handle_alloc() - initialize the PDR client handle
643 * @status: function to be called on PD state change
644 * @priv: handle for client's use
645 *
646 * Initializes the PDR client handle to allow for tracking/restart of PDs.
647 *
648 * Return: pdr_handle object on success, ERR_PTR on failure.
649 */
650struct pdr_handle *pdr_handle_alloc(void (*status)(int state,
651 char *service_path,
652 void *priv), void *priv)
653{
654 struct pdr_handle *pdr;
655 int ret;
656
657 if (!status)
658 return ERR_PTR(-EINVAL);
659
660 pdr = kzalloc(sizeof(*pdr), GFP_KERNEL);
661 if (!pdr)
662 return ERR_PTR(-ENOMEM);
663
664 pdr->status = status;
665 pdr->priv = priv;
666
667 mutex_init(&pdr->status_lock);
668 mutex_init(&pdr->list_lock);
669 mutex_init(&pdr->lock);
670
671 INIT_LIST_HEAD(&pdr->lookups);
672 INIT_LIST_HEAD(&pdr->indack_list);
673
674 INIT_WORK(&pdr->locator_work, pdr_locator_work);
675 INIT_WORK(&pdr->notifier_work, pdr_notifier_work);
676 INIT_WORK(&pdr->indack_work, pdr_indack_work);
677
678 pdr->notifier_wq = create_singlethread_workqueue("pdr_notifier_wq");
679 if (!pdr->notifier_wq) {
680 ret = -ENOMEM;
681 goto free_pdr_handle;
682 }
683
684 pdr->indack_wq = alloc_ordered_workqueue("pdr_indack_wq", WQ_HIGHPRI);
685 if (!pdr->indack_wq) {
686 ret = -ENOMEM;
687 goto destroy_notifier;
688 }
689
690 ret = qmi_handle_init(&pdr->locator_hdl,
691 SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN,
692 &pdr_locator_ops, NULL);
693 if (ret < 0)
694 goto destroy_indack;
695
696 ret = qmi_add_lookup(&pdr->locator_hdl, SERVREG_LOCATOR_SERVICE, 1, 1);
697 if (ret < 0)
698 goto release_qmi_handle;
699
700 ret = qmi_handle_init(&pdr->notifier_hdl,
701 SERVREG_STATE_UPDATED_IND_MAX_LEN,
702 &pdr_notifier_ops,
703 qmi_indication_handler);
704 if (ret < 0)
705 goto release_qmi_handle;
706
707 return pdr;
708
709release_qmi_handle:
710 qmi_handle_release(&pdr->locator_hdl);
711destroy_indack:
712 destroy_workqueue(pdr->indack_wq);
713destroy_notifier:
714 destroy_workqueue(pdr->notifier_wq);
715free_pdr_handle:
716 kfree(pdr);
717
718 return ERR_PTR(ret);
719}
720EXPORT_SYMBOL(pdr_handle_alloc);
721
722/**
723 * pdr_handle_release() - release the PDR client handle
724 * @pdr: PDR client handle
725 *
726 * Cleans up pending tracking requests and releases the underlying qmi handles.
727 */
728void pdr_handle_release(struct pdr_handle *pdr)
729{
730 struct pdr_service *pds, *tmp;
731
732 if (IS_ERR_OR_NULL(pdr))
733 return;
734
735 mutex_lock(&pdr->list_lock);
736 list_for_each_entry_safe(pds, tmp, &pdr->lookups, node) {
737 list_del(&pds->node);
738 kfree(pds);
739 }
740 mutex_unlock(&pdr->list_lock);
741
742 cancel_work_sync(&pdr->locator_work);
743 cancel_work_sync(&pdr->notifier_work);
744 cancel_work_sync(&pdr->indack_work);
745
746 destroy_workqueue(pdr->notifier_wq);
747 destroy_workqueue(pdr->indack_wq);
748
749 qmi_handle_release(&pdr->locator_hdl);
750 qmi_handle_release(&pdr->notifier_hdl);
751
752 kfree(pdr);
753}
754EXPORT_SYMBOL(pdr_handle_release);
755
756MODULE_LICENSE("GPL v2");
757MODULE_DESCRIPTION("Qualcomm Protection Domain Restart helpers");
drivers/soc/qcom/pdr_internal.h+379−0
@@ -0,0 +1,379 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef __QCOM_PDR_HELPER_INTERNAL__
3#define __QCOM_PDR_HELPER_INTERNAL__
4
5#include <linux/soc/qcom/pdr.h>
6
7#define SERVREG_LOCATOR_SERVICE 0x40
8#define SERVREG_NOTIFIER_SERVICE 0x42
9
10#define SERVREG_REGISTER_LISTENER_REQ 0x20
11#define SERVREG_GET_DOMAIN_LIST_REQ 0x21
12#define SERVREG_STATE_UPDATED_IND_ID 0x22
13#define SERVREG_SET_ACK_REQ 0x23
14#define SERVREG_RESTART_PD_REQ 0x24
15
16#define SERVREG_DOMAIN_LIST_LENGTH 32
17#define SERVREG_RESTART_PD_REQ_MAX_LEN 67
18#define SERVREG_REGISTER_LISTENER_REQ_LEN 71
19#define SERVREG_SET_ACK_REQ_LEN 72
20#define SERVREG_GET_DOMAIN_LIST_REQ_MAX_LEN 74
21#define SERVREG_STATE_UPDATED_IND_MAX_LEN 79
22#define SERVREG_GET_DOMAIN_LIST_RESP_MAX_LEN 2389
23
24struct servreg_location_entry {
25 char name[SERVREG_NAME_LENGTH + 1];
26 u8 service_data_valid;
27 u32 service_data;
28 u32 instance;
29};
30
31struct qmi_elem_info servreg_location_entry_ei[] = {
32 {
33 .data_type = QMI_STRING,
34 .elem_len = SERVREG_NAME_LENGTH + 1,
35 .elem_size = sizeof(char),
36 .array_type = NO_ARRAY,
37 .tlv_type = 0,
38 .offset = offsetof(struct servreg_location_entry,
39 name),
40 },
41 {
42 .data_type = QMI_UNSIGNED_4_BYTE,
43 .elem_len = 1,
44 .elem_size = sizeof(u32),
45 .array_type = NO_ARRAY,
46 .tlv_type = 0,
47 .offset = offsetof(struct servreg_location_entry,
48 instance),
49 },
50 {
51 .data_type = QMI_UNSIGNED_1_BYTE,
52 .elem_len = 1,
53 .elem_size = sizeof(u8),
54 .array_type = NO_ARRAY,
55 .tlv_type = 0,
56 .offset = offsetof(struct servreg_location_entry,
57 service_data_valid),
58 },
59 {
60 .data_type = QMI_UNSIGNED_4_BYTE,
61 .elem_len = 1,
62 .elem_size = sizeof(u32),
63 .array_type = NO_ARRAY,
64 .tlv_type = 0,
65 .offset = offsetof(struct servreg_location_entry,
66 service_data),
67 },
68 {}
69};
70
71struct servreg_get_domain_list_req {
72 char service_name[SERVREG_NAME_LENGTH + 1];
73 u8 domain_offset_valid;
74 u32 domain_offset;
75};
76
77struct qmi_elem_info servreg_get_domain_list_req_ei[] = {
78 {
79 .data_type = QMI_STRING,
80 .elem_len = SERVREG_NAME_LENGTH + 1,
81 .elem_size = sizeof(char),
82 .array_type = NO_ARRAY,
83 .tlv_type = 0x01,
84 .offset = offsetof(struct servreg_get_domain_list_req,
85 service_name),
86 },
87 {
88 .data_type = QMI_OPT_FLAG,
89 .elem_len = 1,
90 .elem_size = sizeof(u8),
91 .array_type = NO_ARRAY,
92 .tlv_type = 0x10,
93 .offset = offsetof(struct servreg_get_domain_list_req,
94 domain_offset_valid),
95 },
96 {
97 .data_type = QMI_UNSIGNED_4_BYTE,
98 .elem_len = 1,
99 .elem_size = sizeof(u32),
100 .array_type = NO_ARRAY,
101 .tlv_type = 0x10,
102 .offset = offsetof(struct servreg_get_domain_list_req,
103 domain_offset),
104 },
105 {}
106};
107
108struct servreg_get_domain_list_resp {
109 struct qmi_response_type_v01 resp;
110 u8 total_domains_valid;
111 u16 total_domains;
112 u8 db_rev_count_valid;
113 u16 db_rev_count;
114 u8 domain_list_valid;
115 u32 domain_list_len;
116 struct servreg_location_entry domain_list[SERVREG_DOMAIN_LIST_LENGTH];
117};
118
119struct qmi_elem_info servreg_get_domain_list_resp_ei[] = {
120 {
121 .data_type = QMI_STRUCT,
122 .elem_len = 1,
123 .elem_size = sizeof(struct qmi_response_type_v01),
124 .array_type = NO_ARRAY,
125 .tlv_type = 0x02,
126 .offset = offsetof(struct servreg_get_domain_list_resp,
127 resp),
128 .ei_array = qmi_response_type_v01_ei,
129 },
130 {
131 .data_type = QMI_OPT_FLAG,
132 .elem_len = 1,
133 .elem_size = sizeof(u8),
134 .array_type = NO_ARRAY,
135 .tlv_type = 0x10,
136 .offset = offsetof(struct servreg_get_domain_list_resp,
137 total_domains_valid),
138 },
139 {
140 .data_type = QMI_UNSIGNED_2_BYTE,
141 .elem_len = 1,
142 .elem_size = sizeof(u16),
143 .array_type = NO_ARRAY,
144 .tlv_type = 0x10,
145 .offset = offsetof(struct servreg_get_domain_list_resp,
146 total_domains),
147 },
148 {
149 .data_type = QMI_OPT_FLAG,
150 .elem_len = 1,
151 .elem_size = sizeof(u8),
152 .array_type = NO_ARRAY,
153 .tlv_type = 0x11,
154 .offset = offsetof(struct servreg_get_domain_list_resp,
155 db_rev_count_valid),
156 },
157 {
158 .data_type = QMI_UNSIGNED_2_BYTE,
159 .elem_len = 1,
160 .elem_size = sizeof(u16),
161 .array_type = NO_ARRAY,
162 .tlv_type = 0x11,
163 .offset = offsetof(struct servreg_get_domain_list_resp,
164 db_rev_count),
165 },
166 {
167 .data_type = QMI_OPT_FLAG,
168 .elem_len = 1,
169 .elem_size = sizeof(u8),
170 .array_type = NO_ARRAY,
171 .tlv_type = 0x12,
172 .offset = offsetof(struct servreg_get_domain_list_resp,
173 domain_list_valid),
174 },
175 {
176 .data_type = QMI_DATA_LEN,
177 .elem_len = 1,
178 .elem_size = sizeof(u8),
179 .array_type = NO_ARRAY,
180 .tlv_type = 0x12,
181 .offset = offsetof(struct servreg_get_domain_list_resp,
182 domain_list_len),
183 },
184 {
185 .data_type = QMI_STRUCT,
186 .elem_len = SERVREG_DOMAIN_LIST_LENGTH,
187 .elem_size = sizeof(struct servreg_location_entry),
188 .array_type = NO_ARRAY,
189 .tlv_type = 0x12,
190 .offset = offsetof(struct servreg_get_domain_list_resp,
191 domain_list),
192 .ei_array = servreg_location_entry_ei,
193 },
194 {}
195};
196
197struct servreg_register_listener_req {
198 u8 enable;
199 char service_path[SERVREG_NAME_LENGTH + 1];
200};
201
202struct qmi_elem_info servreg_register_listener_req_ei[] = {
203 {
204 .data_type = QMI_UNSIGNED_1_BYTE,
205 .elem_len = 1,
206 .elem_size = sizeof(u8),
207 .array_type = NO_ARRAY,
208 .tlv_type = 0x01,
209 .offset = offsetof(struct servreg_register_listener_req,
210 enable),
211 },
212 {
213 .data_type = QMI_STRING,
214 .elem_len = SERVREG_NAME_LENGTH + 1,
215 .elem_size = sizeof(char),
216 .array_type = NO_ARRAY,
217 .tlv_type = 0x02,
218 .offset = offsetof(struct servreg_register_listener_req,
219 service_path),
220 },
221 {}
222};
223
224struct servreg_register_listener_resp {
225 struct qmi_response_type_v01 resp;
226 u8 curr_state_valid;
227 enum servreg_service_state curr_state;
228};
229
230struct qmi_elem_info servreg_register_listener_resp_ei[] = {
231 {
232 .data_type = QMI_STRUCT,
233 .elem_len = 1,
234 .elem_size = sizeof(struct qmi_response_type_v01),
235 .array_type = NO_ARRAY,
236 .tlv_type = 0x02,
237 .offset = offsetof(struct servreg_register_listener_resp,
238 resp),
239 .ei_array = qmi_response_type_v01_ei,
240 },
241 {
242 .data_type = QMI_OPT_FLAG,
243 .elem_len = 1,
244 .elem_size = sizeof(u8),
245 .array_type = NO_ARRAY,
246 .tlv_type = 0x10,
247 .offset = offsetof(struct servreg_register_listener_resp,
248 curr_state_valid),
249 },
250 {
251 .data_type = QMI_SIGNED_4_BYTE_ENUM,
252 .elem_len = 1,
253 .elem_size = sizeof(enum servreg_service_state),
254 .array_type = NO_ARRAY,
255 .tlv_type = 0x10,
256 .offset = offsetof(struct servreg_register_listener_resp,
257 curr_state),
258 },
259 {}
260};
261
262struct servreg_restart_pd_req {
263 char service_path[SERVREG_NAME_LENGTH + 1];
264};
265
266struct qmi_elem_info servreg_restart_pd_req_ei[] = {
267 {
268 .data_type = QMI_STRING,
269 .elem_len = SERVREG_NAME_LENGTH + 1,
270 .elem_size = sizeof(char),
271 .array_type = NO_ARRAY,
272 .tlv_type = 0x01,
273 .offset = offsetof(struct servreg_restart_pd_req,
274 service_path),
275 },
276 {}
277};
278
279struct servreg_restart_pd_resp {
280 struct qmi_response_type_v01 resp;
281};
282
283struct qmi_elem_info servreg_restart_pd_resp_ei[] = {
284 {
285 .data_type = QMI_STRUCT,
286 .elem_len = 1,
287 .elem_size = sizeof(struct qmi_response_type_v01),
288 .array_type = NO_ARRAY,
289 .tlv_type = 0x02,
290 .offset = offsetof(struct servreg_restart_pd_resp,
291 resp),
292 .ei_array = qmi_response_type_v01_ei,
293 },
294 {}
295};
296
297struct servreg_state_updated_ind {
298 enum servreg_service_state curr_state;
299 char service_path[SERVREG_NAME_LENGTH + 1];
300 u16 transaction_id;
301};
302
303struct qmi_elem_info servreg_state_updated_ind_ei[] = {
304 {
305 .data_type = QMI_SIGNED_4_BYTE_ENUM,
306 .elem_len = 1,
307 .elem_size = sizeof(u32),
308 .array_type = NO_ARRAY,
309 .tlv_type = 0x01,
310 .offset = offsetof(struct servreg_state_updated_ind,
311 curr_state),
312 },
313 {
314 .data_type = QMI_STRING,
315 .elem_len = SERVREG_NAME_LENGTH + 1,
316 .elem_size = sizeof(char),
317 .array_type = NO_ARRAY,
318 .tlv_type = 0x02,
319 .offset = offsetof(struct servreg_state_updated_ind,
320 service_path),
321 },
322 {
323 .data_type = QMI_UNSIGNED_2_BYTE,
324 .elem_len = 1,
325 .elem_size = sizeof(u16),
326 .array_type = NO_ARRAY,
327 .tlv_type = 0x03,
328 .offset = offsetof(struct servreg_state_updated_ind,
329 transaction_id),
330 },
331 {}
332};
333
334struct servreg_set_ack_req {
335 char service_path[SERVREG_NAME_LENGTH + 1];
336 u16 transaction_id;
337};
338
339struct qmi_elem_info servreg_set_ack_req_ei[] = {
340 {
341 .data_type = QMI_STRING,
342 .elem_len = SERVREG_NAME_LENGTH + 1,
343 .elem_size = sizeof(char),
344 .array_type = NO_ARRAY,
345 .tlv_type = 0x01,
346 .offset = offsetof(struct servreg_set_ack_req,
347 service_path),
348 },
349 {
350 .data_type = QMI_UNSIGNED_2_BYTE,
351 .elem_len = 1,
352 .elem_size = sizeof(u16),
353 .array_type = NO_ARRAY,
354 .tlv_type = 0x02,
355 .offset = offsetof(struct servreg_set_ack_req,
356 transaction_id),
357 },
358 {}
359};
360
361struct servreg_set_ack_resp {
362 struct qmi_response_type_v01 resp;
363};
364
365struct qmi_elem_info servreg_set_ack_resp_ei[] = {
366 {
367 .data_type = QMI_STRUCT,
368 .elem_len = 1,
369 .elem_size = sizeof(struct qmi_response_type_v01),
370 .array_type = NO_ARRAY,
371 .tlv_type = 0x02,
372 .offset = offsetof(struct servreg_set_ack_resp,
373 resp),
374 .ei_array = qmi_response_type_v01_ei,
375 },
376 {}
377};
378
379#endif
drivers/soc/qcom/qcom_aoss.c+5−1
@@ -200,7 +200,7 @@ static irqreturn_t qmp_intr(int irq, void *data) · 199 unmodified lines
200{200{
201 struct qmp *qmp = data;201 struct qmp *qmp = data;
202 202
203 wake_up_interruptible_all(&qmp->event);203 wake_up_all(&qmp->event);
204 204
205 return IRQ_HANDLED;205 return IRQ_HANDLED;
206}206}
@@ -225,6 +225,7 @@ static bool qmp_message_empty(struct qmp *qmp) · 18 unmodified lines
225static int qmp_send(struct qmp *qmp, const void *data, size_t len)225static int qmp_send(struct qmp *qmp, const void *data, size_t len)
226{226{
227 long time_left;227 long time_left;
228 size_t tlen;
228 int ret;229 int ret;
229 230
230 if (WARN_ON(len + sizeof(u32) > qmp->size))231 if (WARN_ON(len + sizeof(u32) > qmp->size))
@@ -239,6 +240,9 @@ static int qmp_send(struct qmp *qmp, const void *data, size_t len) · 8 unmodified lines
239 __iowrite32_copy(qmp->msgram + qmp->offset + sizeof(u32),240 __iowrite32_copy(qmp->msgram + qmp->offset + sizeof(u32),
240 data, len / sizeof(u32));241 data, len / sizeof(u32));
241 writel(len, qmp->msgram + qmp->offset);242 writel(len, qmp->msgram + qmp->offset);
243
244 /* Read back len to confirm data written in message RAM */
245 tlen = readl(qmp->msgram + qmp->offset);
242 qmp_kick(qmp);246 qmp_kick(qmp);
243 247
244 time_left = wait_event_interruptible_timeout(qmp->event,248 time_left = wait_event_interruptible_timeout(qmp->event,
drivers/soc/qcom/rpmh-internal.h+1−0
@@ -110,5 +110,6 @@ int rpmh_rsc_write_ctrl_data(struct rsc_drv *drv, · 109 unmodified lines
110int rpmh_rsc_invalidate(struct rsc_drv *drv);110int rpmh_rsc_invalidate(struct rsc_drv *drv);
111 111
112void rpmh_tx_done(const struct tcs_request *msg, int r);112void rpmh_tx_done(const struct tcs_request *msg, int r);
113int rpmh_flush(struct rpmh_ctrlr *ctrlr);
113 114
114#endif /* __RPM_INTERNAL_H__ */115#endif /* __RPM_INTERNAL_H__ */
drivers/soc/qcom/rpmh-rsc.c+1−1
@@ -277,7 +277,7 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id, · 276 unmodified lines
277 write_tcs_cmd(drv, RSC_DRV_CMD_MSGID, tcs_id, j, msgid);277 write_tcs_cmd(drv, RSC_DRV_CMD_MSGID, tcs_id, j, msgid);
278 write_tcs_cmd(drv, RSC_DRV_CMD_ADDR, tcs_id, j, cmd->addr);278 write_tcs_cmd(drv, RSC_DRV_CMD_ADDR, tcs_id, j, cmd->addr);
279 write_tcs_cmd(drv, RSC_DRV_CMD_DATA, tcs_id, j, cmd->data);279 write_tcs_cmd(drv, RSC_DRV_CMD_DATA, tcs_id, j, cmd->data);
280 trace_rpmh_send_msg(drv, tcs_id, j, msgid, cmd);280 trace_rpmh_send_msg_rcuidle(drv, tcs_id, j, msgid, cmd);
281 }281 }
282 282
283 write_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id, cmd_complete);283 write_tcs_reg(drv, RSC_DRV_CMD_WAIT_FOR_CMPL, tcs_id, cmd_complete);
drivers/soc/qcom/rpmh.c+10−12
@@ -23,7 +23,7 @@ · 22 unmodified lines
23 23
24#define RPMH_TIMEOUT_MS msecs_to_jiffies(10000)24#define RPMH_TIMEOUT_MS msecs_to_jiffies(10000)
25 25
26#define DEFINE_RPMH_MSG_ONSTACK(dev, s, q, name) \26#define DEFINE_RPMH_MSG_ONSTACK(device, s, q, name) \
27 struct rpmh_request name = { \27 struct rpmh_request name = { \
28 .msg = { \28 .msg = { \
29 .state = s, \29 .state = s, \
@@ -33,7 +33,7 @@ · 3 unmodified lines
33 }, \33 }, \
34 .cmd = { { 0 } }, \34 .cmd = { { 0 } }, \
35 .completion = q, \35 .completion = q, \
36 .dev = dev, \36 .dev = device, \
37 .needs_free = false, \37 .needs_free = false, \
38 }38 }
39 39
@@ -427,11 +427,10 @@ static int is_req_valid(struct cache_req *req) · 387 unmodified lines
427 req->sleep_val != req->wake_val);427 req->sleep_val != req->wake_val);
428}428}
429 429
430static int send_single(const struct device *dev, enum rpmh_state state,430static int send_single(struct rpmh_ctrlr *ctrlr, enum rpmh_state state,
431 u32 addr, u32 data)431 u32 addr, u32 data)
432{432{
433 DEFINE_RPMH_MSG_ONSTACK(dev, state, NULL, rpm_msg);433 DEFINE_RPMH_MSG_ONSTACK(NULL, state, NULL, rpm_msg);
434 struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
435 434
436 /* Wake sets are always complete and sleep sets are not */435 /* Wake sets are always complete and sleep sets are not */
437 rpm_msg.msg.wait_for_compl = (state == RPMH_WAKE_ONLY_STATE);436 rpm_msg.msg.wait_for_compl = (state == RPMH_WAKE_ONLY_STATE);
@@ -445,7 +444,7 @@ static int send_single(const struct device *dev, enum rpmh_state state, · 7 unmodified lines
445/**444/**
446 * rpmh_flush: Flushes the buffered active and sleep sets to TCS445 * rpmh_flush: Flushes the buffered active and sleep sets to TCS
447 *446 *
448 * @dev: The device making the request447 * @ctrlr: controller making request to flush cached data
449 *448 *
450 * Return: -EBUSY if the controller is busy, probably waiting on a response449 * Return: -EBUSY if the controller is busy, probably waiting on a response
451 * to a RPMH request sent earlier.450 * to a RPMH request sent earlier.
@@ -454,10 +453,9 @@ static int send_single(const struct device *dev, enum rpmh_state state, · 2 unmodified lines
454 * that is powering down the entire system. Since no other RPMH API would be453 * that is powering down the entire system. Since no other RPMH API would be
455 * executing at this time, it is safe to run lockless.454 * executing at this time, it is safe to run lockless.
456 */455 */
457int rpmh_flush(const struct device *dev)456int rpmh_flush(struct rpmh_ctrlr *ctrlr)
458{457{
459 struct cache_req *p;458 struct cache_req *p;
460 struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
461 int ret;459 int ret;
462 460
463 if (!ctrlr->dirty) {461 if (!ctrlr->dirty) {
@@ -480,11 +478,12 @@ int rpmh_flush(const struct device *dev) · 16 unmodified lines
480 __func__, p->addr, p->sleep_val, p->wake_val);478 __func__, p->addr, p->sleep_val, p->wake_val);
481 continue;479 continue;
482 }480 }
483 ret = send_single(dev, RPMH_SLEEP_STATE, p->addr, p->sleep_val);481 ret = send_single(ctrlr, RPMH_SLEEP_STATE, p->addr,
482 p->sleep_val);
484 if (ret)483 if (ret)
485 return ret;484 return ret;
486 ret = send_single(dev, RPMH_WAKE_ONLY_STATE,485 ret = send_single(ctrlr, RPMH_WAKE_ONLY_STATE, p->addr,
487 p->addr, p->wake_val);486 p->wake_val);
488 if (ret)487 if (ret)
489 return ret;488 return ret;
490 }489 }
@@ -493,7 +492,6 @@ int rpmh_flush(const struct device *dev) · 2 unmodified lines
493 492
494 return 0;493 return 0;
495}494}
496EXPORT_SYMBOL(rpmh_flush);
497 495
498/**496/**
499 * rpmh_invalidate: Invalidate all sleep and active sets497 * rpmh_invalidate: Invalidate all sleep and active sets
drivers/soc/qcom/socinfo.c+1−1
@@ -277,7 +277,7 @@ static int show_image_##type(struct seq_file *seq, void *p) \ · 276 unmodified lines
277{ \277{ \
278 struct smem_image_version *image_version = seq->private; \278 struct smem_image_version *image_version = seq->private; \
279 seq_puts(seq, image_version->type); \279 seq_puts(seq, image_version->type); \
280 seq_puts(seq, "\n"); \280 seq_putc(seq, '\n'); \
281 return 0; \281 return 0; \
282} \282} \
283static int open_image_##type(struct inode *inode, struct file *file) \283static int open_image_##type(struct inode *inode, struct file *file) \
drivers/soc/renesas/Kconfig+8−8
@@ -195,19 +195,19 @@ config ARCH_R8A774C0 · 194 unmodified lines
195 This enables support for the Renesas RZ/G2E SoC.195 This enables support for the Renesas RZ/G2E SoC.
196 196
197config ARCH_R8A77950197config ARCH_R8A77950
198 bool198 bool "Renesas R-Car H3 ES1.x SoC Platform"
199 select ARCH_RCAR_GEN3
200 select SYSC_R8A7795
201 help
202 This enables support for the Renesas R-Car H3 SoC (revision 1.x).
199 203
200config ARCH_R8A77951204config ARCH_R8A77951
201 bool205 bool "Renesas R-Car H3 ES2.0+ SoC Platform"
202
203config ARCH_R8A7795
204 bool "Renesas R-Car H3 SoC Platform"
205 select ARCH_R8A77950
206 select ARCH_R8A77951
207 select ARCH_RCAR_GEN3206 select ARCH_RCAR_GEN3
208 select SYSC_R8A7795207 select SYSC_R8A7795
209 help208 help
210 This enables support for the Renesas R-Car H3 SoC.209 This enables support for the Renesas R-Car H3 SoC (revisions 2.0 and
210 later).
211 211
212config ARCH_R8A77960212config ARCH_R8A77960
213 bool "Renesas R-Car M3-W SoC Platform"213 bool "Renesas R-Car M3-W SoC Platform"
drivers/soc/renesas/rcar-sysc.h+2−2
@@ -1,5 +1,5 @@
1/* SPDX-License-Identifier: GPL-2.01/* SPDX-License-Identifier: GPL-2.0 */
2 *2/*
3 * Renesas R-Car System Controller3 * Renesas R-Car System Controller
4 *4 *
5 * Copyright (C) 2016 Glider bvba5 * Copyright (C) 2016 Glider bvba
drivers/soc/renesas/renesas-soc.c+1−1
@@ -259,7 +259,7 @@ static const struct of_device_id renesas_socs[] __initconst = { · 258 unmodified lines
259#ifdef CONFIG_ARCH_R8A7794259#ifdef CONFIG_ARCH_R8A7794
260 { .compatible = "renesas,r8a7794", .data = &soc_rcar_e2 },260 { .compatible = "renesas,r8a7794", .data = &soc_rcar_e2 },
261#endif261#endif
262#ifdef CONFIG_ARCH_R8A7795262#if defined(CONFIG_ARCH_R8A77950) || defined(CONFIG_ARCH_R8A77951)
263 { .compatible = "renesas,r8a7795", .data = &soc_rcar_h3 },263 { .compatible = "renesas,r8a7795", .data = &soc_rcar_h3 },
264#endif264#endif
265#ifdef CONFIG_ARCH_R8A77960265#ifdef CONFIG_ARCH_R8A77960
drivers/tee/tee_core.c+0−1
@@ -44,7 +44,6 @@ static struct tee_context *teedev_open(struct tee_device *teedev) · 43 unmodified lines
44 44
45 kref_init(&ctx->refcount);45 kref_init(&ctx->refcount);
46 ctx->teedev = teedev;46 ctx->teedev = teedev;
47 INIT_LIST_HEAD(&ctx->list_shm);
48 rc = teedev->desc->ops->open(ctx);47 rc = teedev->desc->ops->open(ctx);
49 if (rc)48 if (rc)
50 goto err;49 goto err;
drivers/tee/tee_private.h+2−1
@@ -37,7 +37,8 @@ struct tee_shm_pool { · 36 unmodified lines
37 * @num_users: number of active users of this device37 * @num_users: number of active users of this device
38 * @c_no_user: completion used when unregistering the device38 * @c_no_user: completion used when unregistering the device
39 * @mutex: mutex protecting @num_users and @idr39 * @mutex: mutex protecting @num_users and @idr
40 * @idr: register of shared memory object allocated on this device40 * @idr: register of user space shared memory objects allocated or
41 * registered on this device
41 * @pool: shared memory pool42 * @pool: shared memory pool
42 */43 */
43struct tee_device {44struct tee_device {
drivers/tee/tee_shm.c+24−61
@@ -13,13 +13,13 @@ · 12 unmodified lines
13 13
14static void tee_shm_release(struct tee_shm *shm)14static void tee_shm_release(struct tee_shm *shm)
15{15{
16 struct tee_device *teedev = shm->teedev;16 struct tee_device *teedev = shm->ctx->teedev;
17 17
18 mutex_lock(&teedev->mutex);18 if (shm->flags & TEE_SHM_DMA_BUF) {
19 idr_remove(&teedev->idr, shm->id);19 mutex_lock(&teedev->mutex);
20 if (shm->ctx)20 idr_remove(&teedev->idr, shm->id);
21 list_del(&shm->link);21 mutex_unlock(&teedev->mutex);
22 mutex_unlock(&teedev->mutex);22 }
23 23
24 if (shm->flags & TEE_SHM_POOL) {24 if (shm->flags & TEE_SHM_POOL) {
25 struct tee_shm_pool_mgr *poolm;25 struct tee_shm_pool_mgr *poolm;
@@ -44,8 +44,7 @@ static void tee_shm_release(struct tee_shm *shm) · 18 unmodified lines
44 kfree(shm->pages);44 kfree(shm->pages);
45 }45 }
46 46
47 if (shm->ctx)47 teedev_ctx_put(shm->ctx);
48 teedev_ctx_put(shm->ctx);
49 48
50 kfree(shm);49 kfree(shm);
51 50
@@ -77,7 +76,7 @@ static int tee_shm_op_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) · 25 unmodified lines
77 size_t size = vma->vm_end - vma->vm_start;76 size_t size = vma->vm_end - vma->vm_start;
78 77
79 /* Refuse sharing shared memory provided by application */78 /* Refuse sharing shared memory provided by application */
80 if (shm->flags & TEE_SHM_REGISTER)79 if (shm->flags & TEE_SHM_USER_MAPPED)
81 return -EINVAL;80 return -EINVAL;
82 81
83 return remap_pfn_range(vma, vma->vm_start, shm->paddr >> PAGE_SHIFT,82 return remap_pfn_range(vma, vma->vm_start, shm->paddr >> PAGE_SHIFT,
@@ -91,20 +90,14 @@ static const struct dma_buf_ops tee_shm_dma_buf_ops = { · 7 unmodified lines
91 .mmap = tee_shm_op_mmap,90 .mmap = tee_shm_op_mmap,
92};91};
93 92
94static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx,93struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
95 struct tee_device *teedev,
96 size_t size, u32 flags)
97{94{
95 struct tee_device *teedev = ctx->teedev;
98 struct tee_shm_pool_mgr *poolm = NULL;96 struct tee_shm_pool_mgr *poolm = NULL;
99 struct tee_shm *shm;97 struct tee_shm *shm;
100 void *ret;98 void *ret;
101 int rc;99 int rc;
102 100
103 if (ctx && ctx->teedev != teedev) {
104 dev_err(teedev->dev.parent, "ctx and teedev mismatch\n");
105 return ERR_PTR(-EINVAL);
106 }
107
108 if (!(flags & TEE_SHM_MAPPED)) {101 if (!(flags & TEE_SHM_MAPPED)) {
109 dev_err(teedev->dev.parent,102 dev_err(teedev->dev.parent,
110 "only mapped allocations supported\n");103 "only mapped allocations supported\n");
@@ -132,7 +125,6 @@ static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx, · 21 unmodified lines
132 }125 }
133 126
134 shm->flags = flags | TEE_SHM_POOL;127 shm->flags = flags | TEE_SHM_POOL;
135 shm->teedev = teedev;
136 shm->ctx = ctx;128 shm->ctx = ctx;
137 if (flags & TEE_SHM_DMA_BUF)129 if (flags & TEE_SHM_DMA_BUF)
138 poolm = teedev->pool->dma_buf_mgr;130 poolm = teedev->pool->dma_buf_mgr;
@@ -145,17 +137,18 @@ static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx, · 6 unmodified lines
145 goto err_kfree;137 goto err_kfree;
146 }138 }
147 139
148 mutex_lock(&teedev->mutex);
149 shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
150 mutex_unlock(&teedev->mutex);
151 if (shm->id < 0) {
152 ret = ERR_PTR(shm->id);
153 goto err_pool_free;
154 }
155 140
156 if (flags & TEE_SHM_DMA_BUF) {141 if (flags & TEE_SHM_DMA_BUF) {
157 DEFINE_DMA_BUF_EXPORT_INFO(exp_info);142 DEFINE_DMA_BUF_EXPORT_INFO(exp_info);
158 143
144 mutex_lock(&teedev->mutex);
145 shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL);
146 mutex_unlock(&teedev->mutex);
147 if (shm->id < 0) {
148 ret = ERR_PTR(shm->id);
149 goto err_pool_free;
150 }
151
159 exp_info.ops = &tee_shm_dma_buf_ops;152 exp_info.ops = &tee_shm_dma_buf_ops;
160 exp_info.size = shm->size;153 exp_info.size = shm->size;
161 exp_info.flags = O_RDWR;154 exp_info.flags = O_RDWR;
@@ -168,18 +161,16 @@ static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx, · 6 unmodified lines
168 }161 }
169 }162 }
170 163
171 if (ctx) {164 if (ctx)
172 teedev_ctx_get(ctx);165 teedev_ctx_get(ctx);
173 mutex_lock(&teedev->mutex);
174 list_add_tail(&shm->link, &ctx->list_shm);
175 mutex_unlock(&teedev->mutex);
176 }
177 166
178 return shm;167 return shm;
179err_rem:168err_rem:
180 mutex_lock(&teedev->mutex);169 if (flags & TEE_SHM_DMA_BUF) {
181 idr_remove(&teedev->idr, shm->id);170 mutex_lock(&teedev->mutex);
182 mutex_unlock(&teedev->mutex);171 idr_remove(&teedev->idr, shm->id);
172 mutex_unlock(&teedev->mutex);
173 }
183err_pool_free:174err_pool_free:
184 poolm->ops->free(poolm, shm);175 poolm->ops->free(poolm, shm);
185err_kfree:176err_kfree:
@@ -188,31 +179,8 @@ err_dev_put: · 2 unmodified lines
188 tee_device_put(teedev);179 tee_device_put(teedev);
189 return ret;180 return ret;
190}181}
191
192/**
193 * tee_shm_alloc() - Allocate shared memory
194 * @ctx: Context that allocates the shared memory
195 * @size: Requested size of shared memory
196 * @flags: Flags setting properties for the requested shared memory.
197 *
198 * Memory allocated as global shared memory is automatically freed when the
199 * TEE file pointer is closed. The @flags field uses the bits defined by
200 * TEE_SHM_* in <linux/tee_drv.h>. TEE_SHM_MAPPED must currently always be
201 * set. If TEE_SHM_DMA_BUF global shared memory will be allocated and
202 * associated with a dma-buf handle, else driver private memory.
203 */
204struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags)
205{
206 return __tee_shm_alloc(ctx, ctx->teedev, size, flags);
207}
208EXPORT_SYMBOL_GPL(tee_shm_alloc);182EXPORT_SYMBOL_GPL(tee_shm_alloc);
209 183
210struct tee_shm *tee_shm_priv_alloc(struct tee_device *teedev, size_t size)
211{
212 return __tee_shm_alloc(NULL, teedev, size, TEE_SHM_MAPPED);
213}
214EXPORT_SYMBOL_GPL(tee_shm_priv_alloc);
215
216struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,184struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr,
217 size_t length, u32 flags)185 size_t length, u32 flags)
218{186{
@@ -245,7 +213,6 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, · 26 unmodified lines
245 }213 }
246 214
247 shm->flags = flags | TEE_SHM_REGISTER;215 shm->flags = flags | TEE_SHM_REGISTER;
248 shm->teedev = teedev;
249 shm->ctx = ctx;216 shm->ctx = ctx;
250 shm->id = -1;217 shm->id = -1;
251 addr = untagged_addr(addr);218 addr = untagged_addr(addr);
@@ -301,10 +268,6 @@ struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, · 49 unmodified lines
301 }268 }
302 }269 }
303 270
304 mutex_lock(&teedev->mutex);
305 list_add_tail(&shm->link, &ctx->list_shm);
306 mutex_unlock(&teedev->mutex);
307
308 return shm;271 return shm;
309err:272err:
310 if (shm) {273 if (shm) {
include/dt-bindings/bus/ti-sysc.h+4−0
@@ -18,6 +18,10 @@ · 17 unmodified lines
18 18
19#define SYSC_DRA7_MCAN_ENAWAKEUP (1 << 4)19#define SYSC_DRA7_MCAN_ENAWAKEUP (1 << 4)
20 20
21/* PRUSS sysc found on AM33xx/AM43xx/AM57xx */
22#define SYSC_PRUSS_SUB_MWAIT (1 << 5)
23#define SYSC_PRUSS_STANDBY_INIT (1 << 4)
24
21/* SYSCONFIG STANDBYMODE/MIDLEMODE/SIDLEMODE supported by hardware */25/* SYSCONFIG STANDBYMODE/MIDLEMODE/SIDLEMODE supported by hardware */
22#define SYSC_IDLE_FORCE 026#define SYSC_IDLE_FORCE 0
23#define SYSC_IDLE_NO 127#define SYSC_IDLE_NO 1
include/dt-bindings/power/meson-a1-power.h+32−0
@@ -0,0 +1,32 @@
1/* SPDX-License-Identifier: (GPL-2.0+ or MIT) */
2/*
3 * Copyright (c) 2019 Amlogic, Inc.
4 * Author: Jianxin Pan <jianxin.pan@amlogic.com>
5 */
6
7#ifndef _DT_BINDINGS_MESON_A1_POWER_H
8#define _DT_BINDINGS_MESON_A1_POWER_H
9
10#define PWRC_DSPA_ID 8
11#define PWRC_DSPB_ID 9
12#define PWRC_UART_ID 10
13#define PWRC_DMC_ID 11
14#define PWRC_I2C_ID 12
15#define PWRC_PSRAM_ID 13
16#define PWRC_ACODEC_ID 14
17#define PWRC_AUDIO_ID 15
18#define PWRC_OTP_ID 16
19#define PWRC_DMA_ID 17
20#define PWRC_SD_EMMC_ID 18
21#define PWRC_RAMA_ID 19
22#define PWRC_RAMB_ID 20
23#define PWRC_IR_ID 21
24#define PWRC_SPICC_ID 22
25#define PWRC_SPIFC_ID 23
26#define PWRC_USB_ID 24
27#define PWRC_NIC_ID 25
28#define PWRC_PDMIN_ID 26
29#define PWRC_RSA_ID 27
30#define PWRC_MAX_ID 28
31
32#endif
include/linux/firmware/imx/ipc.h+0−1
@@ -25,7 +25,6 @@ enum imx_sc_rpc_svc { · 24 unmodified lines
25 IMX_SC_RPC_SVC_PAD = 6,25 IMX_SC_RPC_SVC_PAD = 6,
26 IMX_SC_RPC_SVC_MISC = 7,26 IMX_SC_RPC_SVC_MISC = 7,
27 IMX_SC_RPC_SVC_IRQ = 8,27 IMX_SC_RPC_SVC_IRQ = 8,
28 IMX_SC_RPC_SVC_ABORT = 9
29};28};
30 29
31struct imx_sc_rpc_msg {30struct imx_sc_rpc_msg {
include/linux/firmware/meson/meson_sm.h+2−0
@@ -12,6 +12,8 @@ enum { · 11 unmodified lines
12 SM_EFUSE_WRITE,12 SM_EFUSE_WRITE,
13 SM_EFUSE_USER_MAX,13 SM_EFUSE_USER_MAX,
14 SM_GET_CHIP_ID,14 SM_GET_CHIP_ID,
15 SM_A1_PWRC_SET,
16 SM_A1_PWRC_GET,
15};17};
16 18
17struct meson_sm_firmware;19struct meson_sm_firmware;
include/linux/platform_data/ti-sysc.h+5−0
@@ -17,6 +17,7 @@ enum ti_sysc_module_type { · 16 unmodified lines
17 TI_SYSC_OMAP4_MCASP,17 TI_SYSC_OMAP4_MCASP,
18 TI_SYSC_OMAP4_USB_HOST_FS,18 TI_SYSC_OMAP4_USB_HOST_FS,
19 TI_SYSC_DRA7_MCAN,19 TI_SYSC_DRA7_MCAN,
20 TI_SYSC_PRUSS,
20};21};
21 22
22struct ti_sysc_cookie {23struct ti_sysc_cookie {
@@ -49,6 +50,9 @@ struct sysc_regbits { · 26 unmodified lines
49 s8 emufree_shift;50 s8 emufree_shift;
50};51};
51 52
53#define SYSC_MODULE_QUIRK_PRUSS BIT(24)
54#define SYSC_MODULE_QUIRK_DSS_RESET BIT(23)
55#define SYSC_MODULE_QUIRK_RTC_UNLOCK BIT(22)
52#define SYSC_QUIRK_CLKDM_NOAUTO BIT(21)56#define SYSC_QUIRK_CLKDM_NOAUTO BIT(21)
53#define SYSC_QUIRK_FORCE_MSTANDBY BIT(20)57#define SYSC_QUIRK_FORCE_MSTANDBY BIT(20)
54#define SYSC_MODULE_QUIRK_AESS BIT(19)58#define SYSC_MODULE_QUIRK_AESS BIT(19)
@@ -141,6 +145,7 @@ struct clk; · 86 unmodified lines
141 145
142struct ti_sysc_platform_data {146struct ti_sysc_platform_data {
143 struct of_dev_auxdata *auxdata;147 struct of_dev_auxdata *auxdata;
148 bool (*soc_type_gp)(void);
144 int (*init_clockdomain)(struct device *dev, struct clk *fck,149 int (*init_clockdomain)(struct device *dev, struct clk *fck,
145 struct clk *ick, struct ti_sysc_cookie *cookie);150 struct clk *ick, struct ti_sysc_cookie *cookie);
146 void (*clkdm_deny_idle)(struct device *dev,151 void (*clkdm_deny_idle)(struct device *dev,
include/linux/soc/qcom/apr.h+1−0
@@ -85,6 +85,7 @@ struct apr_device { · 84 unmodified lines
85 uint16_t domain_id;85 uint16_t domain_id;
86 uint32_t version;86 uint32_t version;
87 char name[APR_NAME_SIZE];87 char name[APR_NAME_SIZE];
88 const char *service_path;
88 spinlock_t lock;89 spinlock_t lock;
89 struct list_head node;90 struct list_head node;
90};91};
include/linux/soc/qcom/pdr.h+29−0
@@ -0,0 +1,29 @@
1/* SPDX-License-Identifier: GPL-2.0 */
2#ifndef __QCOM_PDR_HELPER__
3#define __QCOM_PDR_HELPER__
4
5#include <linux/soc/qcom/qmi.h>
6
7#define SERVREG_NAME_LENGTH 64
8
9struct pdr_service;
10struct pdr_handle;
11
12enum servreg_service_state {
13 SERVREG_LOCATOR_ERR = 0x1,
14 SERVREG_SERVICE_STATE_DOWN = 0x0FFFFFFF,
15 SERVREG_SERVICE_STATE_UP = 0x1FFFFFFF,
16 SERVREG_SERVICE_STATE_EARLY_DOWN = 0x2FFFFFFF,
17 SERVREG_SERVICE_STATE_UNINIT = 0x7FFFFFFF,
18};
19
20struct pdr_handle *pdr_handle_alloc(void (*status)(int state,
21 char *service_path,
22 void *priv), void *priv);
23struct pdr_service *pdr_add_lookup(struct pdr_handle *pdr,
24 const char *service_name,
25 const char *service_path);
26int pdr_restart_pd(struct pdr_handle *pdr, struct pdr_service *pds);
27void pdr_handle_release(struct pdr_handle *pdr);
28
29#endif
include/linux/soc/qcom/qmi.h+1−0
@@ -88,6 +88,7 @@ struct qmi_elem_info { · 87 unmodified lines
88#define QMI_ERR_CLIENT_IDS_EXHAUSTED_V01 588#define QMI_ERR_CLIENT_IDS_EXHAUSTED_V01 5
89#define QMI_ERR_INVALID_ID_V01 4189#define QMI_ERR_INVALID_ID_V01 41
90#define QMI_ERR_ENCODING_V01 5890#define QMI_ERR_ENCODING_V01 58
91#define QMI_ERR_DISABLED_V01 69
91#define QMI_ERR_INCOMPATIBLE_STATE_V01 9092#define QMI_ERR_INCOMPATIBLE_STATE_V01 90
92#define QMI_ERR_NOT_SUPPORTED_V01 9493#define QMI_ERR_NOT_SUPPORTED_V01 94
93 94
include/linux/tee_drv.h+1−18
@@ -49,7 +49,6 @@ struct tee_shm_pool; · 48 unmodified lines
49 */49 */
50struct tee_context {50struct tee_context {
51 struct tee_device *teedev;51 struct tee_device *teedev;
52 struct list_head list_shm;
53 void *data;52 void *data;
54 struct kref refcount;53 struct kref refcount;
55 bool releasing;54 bool releasing;
@@ -168,9 +167,7 @@ void tee_device_unregister(struct tee_device *teedev); · 112 unmodified lines
168 167
169/**168/**
170 * struct tee_shm - shared memory object169 * struct tee_shm - shared memory object
171 * @teedev: device used to allocate the object170 * @ctx: context using the object
172 * @ctx: context using the object, if NULL the context is gone
173 * @link link element
174 * @paddr: physical address of the shared memory171 * @paddr: physical address of the shared memory
175 * @kaddr: virtual address of the shared memory172 * @kaddr: virtual address of the shared memory
176 * @size: size of shared memory173 * @size: size of shared memory
@@ -185,9 +182,7 @@ void tee_device_unregister(struct tee_device *teedev); · 8 unmodified lines
185 * subsystem and from drivers that implements their own shm pool manager.182 * subsystem and from drivers that implements their own shm pool manager.
186 */183 */
187struct tee_shm {184struct tee_shm {
188 struct tee_device *teedev;
189 struct tee_context *ctx;185 struct tee_context *ctx;
190 struct list_head link;
191 phys_addr_t paddr;186 phys_addr_t paddr;
192 void *kaddr;187 void *kaddr;
193 size_t size;188 size_t size;
@@ -318,18 +313,6 @@ void *tee_get_drvdata(struct tee_device *teedev); · 124 unmodified lines
318 */313 */
319struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags);314struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags);
320 315
321/**
322 * tee_shm_priv_alloc() - Allocate shared memory privately
323 * @dev: Device that allocates the shared memory
324 * @size: Requested size of shared memory
325 *
326 * Allocates shared memory buffer that is not associated with any client
327 * context. Such buffers are owned by TEE driver and used for internal calls.
328 *
329 * @returns a pointer to 'struct tee_shm'
330 */
331struct tee_shm *tee_shm_priv_alloc(struct tee_device *teedev, size_t size);
332
333/**316/**
334 * tee_shm_register() - Register shared memory buffer317 * tee_shm_register() - Register shared memory buffer
335 * @ctx: Context that registers the shared memory318 * @ctx: Context that registers the shared memory
include/soc/fsl/dpaa2-io.h+5−1
@@ -1,7 +1,7 @@
1/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */1/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
2/*2/*
3 * Copyright 2014-2016 Freescale Semiconductor Inc.3 * Copyright 2014-2016 Freescale Semiconductor Inc.
4 * Copyright NXP4 * Copyright 2017-2019 NXP
5 *5 *
6 */6 */
7#ifndef __FSL_DPAA2_IO_H7#ifndef __FSL_DPAA2_IO_H
@@ -109,6 +109,10 @@ int dpaa2_io_service_pull_channel(struct dpaa2_io *d, u32 channelid, · 101 unmodified lines
109 109
110int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, u32 fqid,110int dpaa2_io_service_enqueue_fq(struct dpaa2_io *d, u32 fqid,
111 const struct dpaa2_fd *fd);111 const struct dpaa2_fd *fd);
112int dpaa2_io_service_enqueue_multiple_fq(struct dpaa2_io *d, u32 fqid,
113 const struct dpaa2_fd *fd, int number_of_frame);
114int dpaa2_io_service_enqueue_multiple_desc_fq(struct dpaa2_io *d, u32 *fqid,
115 const struct dpaa2_fd *fd, int number_of_frame);
112int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, u32 qdid, u8 prio,116int dpaa2_io_service_enqueue_qd(struct dpaa2_io *d, u32 qdid, u8 prio,
113 u16 qdbin, const struct dpaa2_fd *fd);117 u16 qdbin, const struct dpaa2_fd *fd);
114int dpaa2_io_service_release(struct dpaa2_io *d, u16 bpid,118int dpaa2_io_service_release(struct dpaa2_io *d, u16 bpid,
include/soc/fsl/qe/ucc_fast.h+3−3
@@ -178,10 +178,10 @@ struct ucc_fast_info { · 177 unmodified lines
178struct ucc_fast_private {178struct ucc_fast_private {
179 struct ucc_fast_info *uf_info;179 struct ucc_fast_info *uf_info;
180 struct ucc_fast __iomem *uf_regs; /* a pointer to the UCC regs. */180 struct ucc_fast __iomem *uf_regs; /* a pointer to the UCC regs. */
181 u32 __iomem *p_ucce; /* a pointer to the event register in memory. */181 __be32 __iomem *p_ucce; /* a pointer to the event register in memory. */
182 u32 __iomem *p_uccm; /* a pointer to the mask register in memory. */182 __be32 __iomem *p_uccm; /* a pointer to the mask register in memory. */
183#ifdef CONFIG_UGETH_TX_ON_DEMAND183#ifdef CONFIG_UGETH_TX_ON_DEMAND
184 u16 __iomem *p_utodr; /* pointer to the transmit on demand register */184 __be16 __iomem *p_utodr;/* pointer to the transmit on demand register */
185#endif185#endif
186 int enabled_tx; /* Whether channel is enabled for Tx (ENT) */186 int enabled_tx; /* Whether channel is enabled for Tx (ENT) */
187 int enabled_rx; /* Whether channel is enabled for Rx (ENR) */187 int enabled_rx; /* Whether channel is enabled for Rx (ENR) */
include/soc/fsl/qe/ucc_slow.h+6−7
@@ -184,7 +184,7 @@ struct ucc_slow_info { · 183 unmodified lines
184struct ucc_slow_private {184struct ucc_slow_private {
185 struct ucc_slow_info *us_info;185 struct ucc_slow_info *us_info;
186 struct ucc_slow __iomem *us_regs; /* Ptr to memory map of UCC regs */186 struct ucc_slow __iomem *us_regs; /* Ptr to memory map of UCC regs */
187 struct ucc_slow_pram *us_pram; /* a pointer to the parameter RAM */187 struct ucc_slow_pram __iomem *us_pram; /* a pointer to the parameter RAM */
188 s32 us_pram_offset;188 s32 us_pram_offset;
189 int enabled_tx; /* Whether channel is enabled for Tx (ENT) */189 int enabled_tx; /* Whether channel is enabled for Tx (ENT) */
190 int enabled_rx; /* Whether channel is enabled for Rx (ENR) */190 int enabled_rx; /* Whether channel is enabled for Rx (ENR) */
@@ -196,13 +196,12 @@ struct ucc_slow_private { · 5 unmodified lines
196 and length for first BD in a frame */196 and length for first BD in a frame */
197 s32 tx_base_offset; /* first BD in Tx BD table offset (In MURAM) */197 s32 tx_base_offset; /* first BD in Tx BD table offset (In MURAM) */
198 s32 rx_base_offset; /* first BD in Rx BD table offset (In MURAM) */198 s32 rx_base_offset; /* first BD in Rx BD table offset (In MURAM) */
199 struct qe_bd *confBd; /* next BD for confirm after Tx */199 struct qe_bd __iomem *confBd; /* next BD for confirm after Tx */
200 struct qe_bd *tx_bd; /* next BD for new Tx request */200 struct qe_bd __iomem *tx_bd; /* next BD for new Tx request */
201 struct qe_bd *rx_bd; /* next BD to collect after Rx */201 struct qe_bd __iomem *rx_bd; /* next BD to collect after Rx */
202 void *p_rx_frame; /* accumulating receive frame */202 void *p_rx_frame; /* accumulating receive frame */
203 u16 *p_ucce; /* a pointer to the event register in memory.203 __be16 __iomem *p_ucce; /* a pointer to the event register in memory */
204 */204 __be16 __iomem *p_uccm; /* a pointer to the mask register in memory */
205 u16 *p_uccm; /* a pointer to the mask register in memory */
206 u16 saved_uccm; /* a saved mask for the RX Interrupt bits */205 u16 saved_uccm; /* a saved mask for the RX Interrupt bits */
207#ifdef STATISTICS206#ifdef STATISTICS
208 u32 tx_frames; /* Transmitted frames counters */207 u32 tx_frames; /* Transmitted frames counters */
include/soc/qcom/rpmh.h+0−5
@@ -20,8 +20,6 @@ int rpmh_write_async(const struct device *dev, enum rpmh_state state, · 19 unmodified lines
20int rpmh_write_batch(const struct device *dev, enum rpmh_state state,20int rpmh_write_batch(const struct device *dev, enum rpmh_state state,
21 const struct tcs_cmd *cmd, u32 *n);21 const struct tcs_cmd *cmd, u32 *n);
22 22
23int rpmh_flush(const struct device *dev);
24
25int rpmh_invalidate(const struct device *dev);23int rpmh_invalidate(const struct device *dev);
26 24
27#else25#else
@@ -40,9 +38,6 @@ static inline int rpmh_write_batch(const struct device *dev, · 12 unmodified lines
40 const struct tcs_cmd *cmd, u32 *n)38 const struct tcs_cmd *cmd, u32 *n)
41{ return -ENODEV; }39{ return -ENODEV; }
42 40
43static inline int rpmh_flush(const struct device *dev)
44{ return -ENODEV; }
45
46static inline int rpmh_invalidate(const struct device *dev)41static inline int rpmh_invalidate(const struct device *dev)
47{ return -ENODEV; }42{ return -ENODEV; }
48 43