Pull ARM SoC-related driver updates from Olof Johansson: "Various driver updates for platforms and a couple of the small driver subsystems we merge through our tree: - A driver for SCU (system control) on NXP i.MX8QXP - Qualcomm Always-on Subsystem messaging driver (AOSS QMP) - Qualcomm PM support for MSM8998 - Support for a newer version of DRAM PHY driver for Broadcom (DPFE) - Reset controller support for Bitmain BM1880 - TI SCI (System Control Interface) support for CPU control on AM654 processors - More TI sysc refactoring and rework" * tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (84 commits) reset: remove redundant null check on pointer dev soc: rockchip: work around clang warning dt-bindings: reset: imx7: Fix the spelling of 'indices' soc: imx: Add i.MX8MN SoC driver support soc: aspeed: lpc-ctrl: Fix probe error handling soc: qcom: geni: Add support for ACPI firmware: ti_sci: Fix gcc unused-but-set-variable warning firmware: ti_sci: Use the correct style for SPDX License Identifier soc: imx8: Use existing of_root directly soc: imx8: Fix potential kernel dump in error path firmware/psci: psci_checker: Park kthreads before stopping them memory: move jedec_ddr.h from include/memory to drivers/memory/ memory: move jedec_ddr_data.c from lib/ to drivers/memory/ MAINTAINERS: Remove myself as qcom maintainer soc: aspeed: lpc-ctrl: make parameter optional soc: qcom: apr: Don't use reg for domain id soc: qcom: fix QCOM_AOSS_QMP dependency and build errors memory: tegra: Fix -Wunused-const-variable firmware: tegra: Early resume BPMP soc/tegra: Select pinctrl for Tegra194 ...
Unified · Split
| @@ -6,7 +6,7 @@ that are provided by the hardware platform it is running on, including power · 5 unmodified lines | |||
| 6 | and performance functions. | 6 | and performance functions. |
| 7 | 7 | ||
| 8 | This binding is intended to define the interface the firmware implementing | 8 | This binding is intended to define the interface the firmware implementing |
| 9 | the SCMI as described in ARM document number ARM DUI 0922B ("ARM System Control | 9 | the SCMI as described in ARM document number ARM DEN 0056A ("ARM System Control |
| 10 | and Management Interface Platform Design Document")[0] provide for OSPM in | 10 | and Management Interface Platform Design Document")[0] provide for OSPM in |
| 11 | the device tree. | 11 | the device tree. |
| 12 | 12 | ||
| @@ -0,0 +1,11 @@ | |||
| 1 | DPAA2 console support | ||
| 2 | |||
| 3 | Required properties: | ||
| 4 | |||
| 5 | - compatible | ||
| 6 | Value type: <string> | ||
| 7 | Definition: Must be "fsl,dpaa2-console". | ||
| 8 | - reg | ||
| 9 | Value type: <prop-encoded-array> | ||
| 10 | Definition: A standard property. Specifies the region where the MCFBA | ||
| 11 | (MC firmware base address) register can be found. | ||
| @@ -6,6 +6,8 @@ which then translates it into a corresponding voltage on a rail · 5 unmodified lines | |||
| 6 | Required Properties: | 6 | Required Properties: |
| 7 | - compatible: Should be one of the following | 7 | - compatible: Should be one of the following |
| 8 | * qcom,msm8996-rpmpd: RPM Power domain for the msm8996 family of SoC | 8 | * qcom,msm8996-rpmpd: RPM Power domain for the msm8996 family of SoC |
| 9 | * qcom,msm8998-rpmpd: RPM Power domain for the msm8998 family of SoC | ||
| 10 | * qcom,qcs404-rpmpd: RPM Power domain for the qcs404 family of SoC | ||
| 9 | * qcom,sdm845-rpmhpd: RPMh Power domain for the sdm845 family of SoC | 11 | * qcom,sdm845-rpmhpd: RPMh Power domain for the sdm845 family of SoC |
| 10 | - #power-domain-cells: number of cells in Power domain specifier | 12 | - #power-domain-cells: number of cells in Power domain specifier |
| 11 | must be 1. | 13 | must be 1. |
| @@ -0,0 +1,18 @@ | |||
| 1 | Bitmain BM1880 SoC Reset Controller | ||
| 2 | =================================== | ||
| 3 | |||
| 4 | Please also refer to reset.txt in this directory for common reset | ||
| 5 | controller binding usage. | ||
| 6 | |||
| 7 | Required properties: | ||
| 8 | - compatible: Should be "bitmain,bm1880-reset" | ||
| 9 | - reg: Offset and length of reset controller space in SCTRL. | ||
| 10 | - #reset-cells: Must be 1. | ||
| 11 | |||
| 12 | Example: | ||
| 13 | |||
| 14 | rst: reset-controller@c00 { | ||
| 15 | compatible = "bitmain,bm1880-reset"; | ||
| 16 | reg = <0xc00 0x8>; | ||
| 17 | #reset-cells = <1>; | ||
| 18 | }; | ||
| @@ -45,6 +45,6 @@ Example: · 44 unmodified lines | |||
| 45 | }; | 45 | }; |
| 46 | 46 | ||
| 47 | 47 | ||
| 48 | For list of all valid reset indicies see | 48 | For list of all valid reset indices see |
| 49 | <dt-bindings/reset/imx7-reset.h> for i.MX7 and | 49 | <dt-bindings/reset/imx7-reset.h> for i.MX7 and |
| 50 | <dt-bindings/reset/imx8mq-reset.h> for i.MX8MQ | 50 | <dt-bindings/reset/imx8mq-reset.h> for i.MX8MQ |
| @@ -2,8 +2,8 @@ Amlogic Canvas · 1 unmodified line | |||
| 2 | ================================ | 2 | ================================ |
| 3 | 3 | ||
| 4 | A canvas is a collection of metadata that describes a pixel buffer. | 4 | A canvas is a collection of metadata that describes a pixel buffer. |
| 5 | Those metadata include: width, height, phyaddr, wrapping, block mode | 5 | Those metadata include: width, height, phyaddr, wrapping and block mode. |
| 6 | and endianness. | 6 | Starting with GXBB the endianness can also be described. |
| 7 | 7 | ||
| 8 | Many IPs within Amlogic SoCs rely on canvas indexes to read/write pixel data | 8 | Many IPs within Amlogic SoCs rely on canvas indexes to read/write pixel data |
| 9 | rather than use the phy addresses directly. For instance, this is the case for | 9 | rather than use the phy addresses directly. For instance, this is the case for |
| @@ -18,7 +18,11 @@ Video Lookup Table · 8 unmodified lines | |||
| 18 | -------------------------- | 18 | -------------------------- |
| 19 | 19 | ||
| 20 | Required properties: | 20 | Required properties: |
| 21 | - compatible: "amlogic,canvas" | 21 | - compatible: has to be one of: |
| 22 | - "amlogic,meson8-canvas", "amlogic,canvas" on Meson8 | ||
| 23 | - "amlogic,meson8b-canvas", "amlogic,canvas" on Meson8b | ||
| 24 | - "amlogic,meson8m2-canvas", "amlogic,canvas" on Meson8m2 | ||
| 25 | - "amlogic,canvas" on GXBB and newer | ||
| 22 | - reg: Base physical address and size of the canvas registers. | 26 | - reg: Base physical address and size of the canvas registers. |
| 23 | 27 | ||
| 24 | Example: | 28 | Example: |
| @@ -0,0 +1,81 @@ | |||
| 1 | Qualcomm Always-On Subsystem side channel binding | ||
| 2 | |||
| 3 | This binding describes the hardware component responsible for side channel | ||
| 4 | requests to the always-on subsystem (AOSS), used for certain power management | ||
| 5 | requests that is not handled by the standard RPMh interface. Each client in the | ||
| 6 | SoC has it's own block of message RAM and IRQ for communication with the AOSS. | ||
| 7 | The protocol used to communicate in the message RAM is known as Qualcomm | ||
| 8 | Messaging Protocol (QMP) | ||
| 9 | |||
| 10 | The AOSS side channel exposes control over a set of resources, used to control | ||
| 11 | a set of debug related clocks and to affect the low power state of resources | ||
| 12 | related to the secondary subsystems. These resources are exposed as a set of | ||
| 13 | power-domains. | ||
| 14 | |||
| 15 | - compatible: | ||
| 16 | Usage: required | ||
| 17 | Value type: <string> | ||
| 18 | Definition: must be "qcom,sdm845-aoss-qmp" | ||
| 19 | |||
| 20 | - reg: | ||
| 21 | Usage: required | ||
| 22 | Value type: <prop-encoded-array> | ||
| 23 | Definition: the base address and size of the message RAM for this | ||
| 24 | client's communication with the AOSS | ||
| 25 | |||
| 26 | - interrupts: | ||
| 27 | Usage: required | ||
| 28 | Value type: <prop-encoded-array> | ||
| 29 | Definition: should specify the AOSS message IRQ for this client | ||
| 30 | |||
| 31 | - mboxes: | ||
| 32 | Usage: required | ||
| 33 | Value type: <prop-encoded-array> | ||
| 34 | Definition: reference to the mailbox representing the outgoing doorbell | ||
| 35 | in APCS for this client, as described in mailbox/mailbox.txt | ||
| 36 | |||
| 37 | - #clock-cells: | ||
| 38 | Usage: optional | ||
| 39 | Value type: <u32> | ||
| 40 | Definition: must be 0 | ||
| 41 | The single clock represents the QDSS clock. | ||
| 42 | |||
| 43 | - #power-domain-cells: | ||
| 44 | Usage: optional | ||
| 45 | Value type: <u32> | ||
| 46 | Definition: must be 1 | ||
| 47 | The provided power-domains are: | ||
| 48 | CDSP state (0), LPASS state (1), modem state (2), SLPI | ||
| 49 | state (3), SPSS state (4) and Venus state (5). | ||
| 50 | |||
| 51 | = SUBNODES | ||
| 52 | The AOSS side channel also provides the controls for three cooling devices, | ||
| 53 | these are expressed as subnodes of the QMP node. The name of the node is used | ||
| 54 | to identify the resource and must therefor be "cx", "mx" or "ebi". | ||
| 55 | |||
| 56 | - #cooling-cells: | ||
| 57 | Usage: optional | ||
| 58 | Value type: <u32> | ||
| 59 | Definition: must be 2 | ||
| 60 | |||
| 61 | = EXAMPLE | ||
| 62 | |||
| 63 | The following example represents the AOSS side-channel message RAM and the | ||
| 64 | mechanism exposing the power-domains, as found in SDM845. | ||
| 65 | |||
| 66 | aoss_qmp: qmp@c300000 { | ||
| 67 | compatible = "qcom,sdm845-aoss-qmp"; | ||
| 68 | reg = <0x0c300000 0x100000>; | ||
| 69 | interrupts = <GIC_SPI 389 IRQ_TYPE_EDGE_RISING>; | ||
| 70 | mboxes = <&apss_shared 0>; | ||
| 71 | |||
| 72 | #power-domain-cells = <1>; | ||
| 73 | |||
| 74 | cx_cdev: cx { | ||
| 75 | #cooling-cells = <2>; | ||
| 76 | }; | ||
| 77 | |||
| 78 | mx_cdev: mx { | ||
| 79 | #cooling-cells = <2>; | ||
| 80 | }; | ||
| 81 | }; | ||
| @@ -9,7 +9,7 @@ used for audio/voice services on the QDSP. · 8 unmodified lines | |||
| 9 | Value type: <stringlist> | 9 | Value type: <stringlist> |
| 10 | Definition: must be "qcom,apr-v<VERSION-NUMBER>", example "qcom,apr-v2" | 10 | Definition: must be "qcom,apr-v<VERSION-NUMBER>", example "qcom,apr-v2" |
| 11 | 11 | ||
| 12 | - reg | 12 | - qcom,apr-domain |
| 13 | Usage: required | 13 | Usage: required |
| 14 | Value type: <u32> | 14 | Value type: <u32> |
| 15 | Definition: Destination processor ID. | 15 | Definition: Destination processor ID. |
| @@ -49,9 +49,9 @@ by the individual bindings for the specific service · 33 unmodified lines | |||
| 49 | The following example represents a QDSP based sound card on a MSM8996 device | 49 | The following example represents a QDSP based sound card on a MSM8996 device |
| 50 | which uses apr as communication between Apps and QDSP. | 50 | which uses apr as communication between Apps and QDSP. |
| 51 | 51 | ||
| 52 | apr@4 { | 52 | apr { |
| 53 | compatible = "qcom,apr-v2"; | 53 | compatible = "qcom,apr-v2"; |
| 54 | reg = <APR_DOMAIN_ADSP>; | 54 | qcom,apr-domain = <APR_DOMAIN_ADSP>; |
| 55 | 55 | ||
| 56 | q6core@3 { | 56 | q6core@3 { |
| 57 | compatible = "qcom,q6core"; | 57 | compatible = "qcom,q6core"; |
| @@ -2091,7 +2091,6 @@ S: Maintained · 2090 unmodified lines | |||
| 2091 | 2091 | ||
| 2092 | ARM/QUALCOMM SUPPORT | 2092 | ARM/QUALCOMM SUPPORT |
| 2093 | M: Andy Gross <agross@kernel.org> | 2093 | M: Andy Gross <agross@kernel.org> |
| 2094 | M: David Brown <david.brown@linaro.org> | ||
| 2095 | L: linux-arm-msm@vger.kernel.org | 2094 | L: linux-arm-msm@vger.kernel.org |
| 2096 | S: Maintained | 2095 | S: Maintained |
| 2097 | F: Documentation/devicetree/bindings/soc/qcom/ | 2096 | F: Documentation/devicetree/bindings/soc/qcom/ |
| @@ -2113,7 +2112,7 @@ F: drivers/i2c/busses/i2c-qup.c · 15 unmodified lines | |||
| 2113 | F: drivers/i2c/busses/i2c-qcom-geni.c | 2112 | F: drivers/i2c/busses/i2c-qcom-geni.c |
| 2114 | F: drivers/mfd/ssbi.c | 2113 | F: drivers/mfd/ssbi.c |
| 2115 | F: drivers/mmc/host/mmci_qcom* | 2114 | F: drivers/mmc/host/mmci_qcom* |
| 2116 | F: drivers/mmc/host/sdhci_msm.c | 2115 | F: drivers/mmc/host/sdhci-msm.c |
| 2117 | F: drivers/pci/controller/dwc/pcie-qcom.c | 2116 | F: drivers/pci/controller/dwc/pcie-qcom.c |
| 2118 | F: drivers/phy/qualcomm/ | 2117 | F: drivers/phy/qualcomm/ |
| 2119 | F: drivers/power/*/msm* | 2118 | F: drivers/power/*/msm* |
| @@ -6527,6 +6526,7 @@ M: Li Yang <leoyang.li@nxp.com> · 4407 unmodified lines | |||
| 6527 | L: linuxppc-dev@lists.ozlabs.org | 6526 | L: linuxppc-dev@lists.ozlabs.org |
| 6528 | L: linux-arm-kernel@lists.infradead.org | 6527 | L: linux-arm-kernel@lists.infradead.org |
| 6529 | S: Maintained | 6528 | S: Maintained |
| 6529 | F: Documentation/devicetree/bindings/misc/fsl,dpaa2-console.txt | ||
| 6530 | F: Documentation/devicetree/bindings/soc/fsl/ | 6530 | F: Documentation/devicetree/bindings/soc/fsl/ |
| 6531 | F: drivers/soc/fsl/ | 6531 | F: drivers/soc/fsl/ |
| 6532 | F: include/linux/fsl/ | 6532 | F: include/linux/fsl/ |
| @@ -11907,11 +11907,13 @@ F: include/linux/mtd/onenand*.h · 5374 unmodified lines | |||
| 11907 | 11907 | ||
| 11908 | OP-TEE DRIVER | 11908 | OP-TEE DRIVER |
| 11909 | M: Jens Wiklander <jens.wiklander@linaro.org> | 11909 | M: Jens Wiklander <jens.wiklander@linaro.org> |
| 11910 | L: tee-dev@lists.linaro.org | ||
| 11910 | S: Maintained | 11911 | S: Maintained |
| 11911 | F: drivers/tee/optee/ | 11912 | F: drivers/tee/optee/ |
| 11912 | 11913 | ||
| 11913 | OP-TEE RANDOM NUMBER GENERATOR (RNG) DRIVER | 11914 | OP-TEE RANDOM NUMBER GENERATOR (RNG) DRIVER |
| 11914 | M: Sumit Garg <sumit.garg@linaro.org> | 11915 | M: Sumit Garg <sumit.garg@linaro.org> |
| 11916 | L: tee-dev@lists.linaro.org | ||
| 11915 | S: Maintained | 11917 | S: Maintained |
| 11916 | F: drivers/char/hw_random/optee-rng.c | 11918 | F: drivers/char/hw_random/optee-rng.c |
| 11917 | 11919 | ||
| @@ -13295,7 +13297,7 @@ M: Niklas Cassel <niklas.cassel@linaro.org> · 1377 unmodified lines | |||
| 13295 | L: netdev@vger.kernel.org | 13297 | L: netdev@vger.kernel.org |
| 13296 | S: Maintained | 13298 | S: Maintained |
| 13297 | F: drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c | 13299 | F: drivers/net/ethernet/stmicro/stmmac/dwmac-qcom-ethqos.c |
| 13298 | F: Documentation/devicetree/bindings/net/qcom,dwmac.txt | 13300 | F: Documentation/devicetree/bindings/net/qcom,ethqos.txt |
| 13299 | 13301 | ||
| 13300 | QUALCOMM GENERIC INTERFACE I2C DRIVER | 13302 | QUALCOMM GENERIC INTERFACE I2C DRIVER |
| 13301 | M: Alok Chauhan <alokc@codeaurora.org> | 13303 | M: Alok Chauhan <alokc@codeaurora.org> |
| @@ -15745,6 +15747,7 @@ F: include/media/i2c/tw9910.h · 2443 unmodified lines | |||
| 15745 | 15747 | ||
| 15746 | TEE SUBSYSTEM | 15748 | TEE SUBSYSTEM |
| 15747 | M: Jens Wiklander <jens.wiklander@linaro.org> | 15749 | M: Jens Wiklander <jens.wiklander@linaro.org> |
| 15750 | L: tee-dev@lists.linaro.org | ||
| 15748 | S: Maintained | 15751 | S: Maintained |
| 15749 | F: include/linux/tee_drv.h | 15752 | F: include/linux/tee_drv.h |
| 15750 | F: include/uapi/linux/tee.h | 15753 | F: include/uapi/linux/tee.h |
| @@ -3442,6 +3442,7 @@ static int omap_hwmod_check_module(struct device *dev, · 3441 unmodified lines | |||
| 3442 | * @dev: struct device | 3442 | * @dev: struct device |
| 3443 | * @oh: module | 3443 | * @oh: module |
| 3444 | * @sysc_fields: sysc register bits | 3444 | * @sysc_fields: sysc register bits |
| 3445 | * @clockdomain: clockdomain | ||
| 3445 | * @rev_offs: revision register offset | 3446 | * @rev_offs: revision register offset |
| 3446 | * @sysc_offs: sysconfig register offset | 3447 | * @sysc_offs: sysconfig register offset |
| 3447 | * @syss_offs: sysstatus register offset | 3448 | * @syss_offs: sysstatus register offset |
| @@ -3453,6 +3454,7 @@ static int omap_hwmod_check_module(struct device *dev, · 5 unmodified lines | |||
| 3453 | static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh, | 3454 | static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh, |
| 3454 | const struct ti_sysc_module_data *data, | 3455 | const struct ti_sysc_module_data *data, |
| 3455 | struct sysc_regbits *sysc_fields, | 3456 | struct sysc_regbits *sysc_fields, |
| 3457 | struct clockdomain *clkdm, | ||
| 3456 | s32 rev_offs, s32 sysc_offs, | 3458 | s32 rev_offs, s32 sysc_offs, |
| 3457 | s32 syss_offs, u32 sysc_flags, | 3459 | s32 syss_offs, u32 sysc_flags, |
| 3458 | u32 idlemodes) | 3460 | u32 idlemodes) |
| @@ -3460,8 +3462,6 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh, · 1 unmodified line | |||
| 3460 | struct omap_hwmod_class_sysconfig *sysc; | 3462 | struct omap_hwmod_class_sysconfig *sysc; |
| 3461 | struct omap_hwmod_class *class = NULL; | 3463 | struct omap_hwmod_class *class = NULL; |
| 3462 | struct omap_hwmod_ocp_if *oi = NULL; | 3464 | struct omap_hwmod_ocp_if *oi = NULL; |
| 3463 | struct clockdomain *clkdm = NULL; | ||
| 3464 | struct clk *clk = NULL; | ||
| 3465 | void __iomem *regs = NULL; | 3465 | void __iomem *regs = NULL; |
| 3466 | unsigned long flags; | 3466 | unsigned long flags; |
| 3467 | 3467 | ||
| @@ -3508,36 +3508,6 @@ static int omap_hwmod_allocate_module(struct device *dev, struct omap_hwmod *oh, · 40 unmodified lines | |||
| 3508 | oi->user = OCP_USER_MPU | OCP_USER_SDMA; | 3508 | oi->user = OCP_USER_MPU | OCP_USER_SDMA; |
| 3509 | } | 3509 | } |
| 3510 | 3510 | ||
| 3511 | if (!oh->_clk) { | ||
| 3512 | struct clk_hw_omap *hwclk; | ||
| 3513 | |||
| 3514 | clk = of_clk_get_by_name(dev->of_node, "fck"); | ||
| 3515 | if (!IS_ERR(clk)) | ||
| 3516 | clk_prepare(clk); | ||
| 3517 | else | ||
| 3518 | clk = NULL; | ||
| 3519 | |||
| 3520 | /* | ||
| 3521 | * Populate clockdomain based on dts clock. It is needed for | ||
| 3522 | * clkdm_deny_idle() and clkdm_allow_idle() until we have have | ||
| 3523 | * interconnect driver and reset driver capable of blocking | ||
| 3524 | * clockdomain idle during reset, enable and idle. | ||
| 3525 | */ | ||
| 3526 | if (clk) { | ||
| 3527 | hwclk = to_clk_hw_omap(__clk_get_hw(clk)); | ||
| 3528 | if (hwclk && hwclk->clkdm_name) | ||
| 3529 | clkdm = clkdm_lookup(hwclk->clkdm_name); | ||
| 3530 | } | ||
| 3531 | |||
| 3532 | /* | ||
| 3533 | * Note that we assume interconnect driver manages the clocks | ||
| 3534 | * and do not need to populate oh->_clk for dynamically | ||
| 3535 | * allocated modules. | ||
| 3536 | */ | ||
| 3537 | clk_unprepare(clk); | ||
| 3538 | clk_put(clk); | ||
| 3539 | } | ||
| 3540 | |||
| 3541 | spin_lock_irqsave(&oh->_lock, flags); | 3511 | spin_lock_irqsave(&oh->_lock, flags); |
| 3542 | if (regs) | 3512 | if (regs) |
| 3543 | oh->_mpu_rt_va = regs; | 3513 | oh->_mpu_rt_va = regs; |
| @@ -3623,7 +3593,7 @@ int omap_hwmod_init_module(struct device *dev, · 79 unmodified lines | |||
| 3623 | u32 sysc_flags, idlemodes; | 3593 | u32 sysc_flags, idlemodes; |
| 3624 | int error; | 3594 | int error; |
| 3625 | 3595 | ||
| 3626 | if (!dev || !data) | 3596 | if (!dev || !data || !data->name || !cookie) |
| 3627 | return -EINVAL; | 3597 | return -EINVAL; |
| 3628 | 3598 | ||
| 3629 | oh = _lookup(data->name); | 3599 | oh = _lookup(data->name); |
| @@ -3694,7 +3664,8 @@ int omap_hwmod_init_module(struct device *dev, · 64 unmodified lines | |||
| 3694 | return error; | 3664 | return error; |
| 3695 | 3665 | ||
| 3696 | return omap_hwmod_allocate_module(dev, oh, data, sysc_fields, | 3666 | return omap_hwmod_allocate_module(dev, oh, data, sysc_fields, |
| 3697 | rev_offs, sysc_offs, syss_offs, | 3667 | cookie->clkdm, rev_offs, |
| 3668 | sysc_offs, syss_offs, | ||
| 3698 | sysc_flags, idlemodes); | 3669 | sysc_flags, idlemodes); |
| 3699 | } | 3670 | } |
| 3700 | 3671 | ||
| @@ -26,6 +26,7 @@ · 25 unmodified lines | |||
| 26 | #include <linux/platform_data/wkup_m3.h> | 26 | #include <linux/platform_data/wkup_m3.h> |
| 27 | #include <linux/platform_data/asoc-ti-mcbsp.h> | 27 | #include <linux/platform_data/asoc-ti-mcbsp.h> |
| 28 | 28 | ||
| 29 | #include "clockdomain.h" | ||
| 29 | #include "common.h" | 30 | #include "common.h" |
| 30 | #include "common-board-devices.h" | 31 | #include "common-board-devices.h" |
| 31 | #include "control.h" | 32 | #include "control.h" |
| @@ -460,6 +461,62 @@ static void __init dra7x_evm_mmc_quirk(void) · 428 unmodified lines | |||
| 460 | } | 461 | } |
| 461 | #endif | 462 | #endif |
| 462 | 463 | ||
| 464 | static struct clockdomain *ti_sysc_find_one_clockdomain(struct clk *clk) | ||
| 465 | { | ||
| 466 | struct clockdomain *clkdm = NULL; | ||
| 467 | struct clk_hw_omap *hwclk; | ||
| 468 | |||
| 469 | hwclk = to_clk_hw_omap(__clk_get_hw(clk)); | ||
| 470 | if (hwclk && hwclk->clkdm_name) | ||
| 471 | clkdm = clkdm_lookup(hwclk->clkdm_name); | ||
| 472 | |||
| 473 | return clkdm; | ||
| 474 | } | ||
| 475 | |||
| 476 | /** | ||
| 477 | * ti_sysc_clkdm_init - find clockdomain based on clock | ||
| 478 | * @fck: device functional clock | ||
| 479 | * @ick: device interface clock | ||
| 480 | * @dev: struct device | ||
| 481 | * | ||
| 482 | * Populate clockdomain based on clock. It is needed for | ||
| 483 | * clkdm_deny_idle() and clkdm_allow_idle() for blocking clockdomain | ||
| 484 | * clockdomain idle during reset, enable and idle. | ||
| 485 | * | ||
| 486 | * Note that we assume interconnect driver manages the clocks | ||
| 487 | * and do not need to populate oh->_clk for dynamically | ||
| 488 | * allocated modules. | ||
| 489 | */ | ||
| 490 | static int ti_sysc_clkdm_init(struct device *dev, | ||
| 491 | struct clk *fck, struct clk *ick, | ||
| 492 | struct ti_sysc_cookie *cookie) | ||
| 493 | { | ||
| 494 | if (fck) | ||
| 495 | cookie->clkdm = ti_sysc_find_one_clockdomain(fck); | ||
| 496 | if (cookie->clkdm) | ||
| 497 | return 0; | ||
| 498 | if (ick) | ||
| 499 | cookie->clkdm = ti_sysc_find_one_clockdomain(ick); | ||
| 500 | if (cookie->clkdm) | ||
| 501 | return 0; | ||
| 502 | |||
| 503 | return -ENODEV; | ||
| 504 | } | ||
| 505 | |||
| 506 | static void ti_sysc_clkdm_deny_idle(struct device *dev, | ||
| 507 | const struct ti_sysc_cookie *cookie) | ||
| 508 | { | ||
| 509 | if (cookie->clkdm) | ||
| 510 | clkdm_deny_idle(cookie->clkdm); | ||
| 511 | } | ||
| 512 | |||
| 513 | static void ti_sysc_clkdm_allow_idle(struct device *dev, | ||
| 514 | const struct ti_sysc_cookie *cookie) | ||
| 515 | { | ||
| 516 | if (cookie->clkdm) | ||
| 517 | clkdm_allow_idle(cookie->clkdm); | ||
| 518 | } | ||
| 519 | |||
| 463 | static int ti_sysc_enable_module(struct device *dev, | 520 | static int ti_sysc_enable_module(struct device *dev, |
| 464 | const struct ti_sysc_cookie *cookie) | 521 | const struct ti_sysc_cookie *cookie) |
| 465 | { | 522 | { |
| @@ -491,6 +548,9 @@ static struct of_dev_auxdata omap_auxdata_lookup[]; · 25 unmodified lines | |||
| 491 | 548 | ||
| 492 | static struct ti_sysc_platform_data ti_sysc_pdata = { | 549 | static struct ti_sysc_platform_data ti_sysc_pdata = { |
| 493 | .auxdata = omap_auxdata_lookup, | 550 | .auxdata = omap_auxdata_lookup, |
| 551 | .init_clockdomain = ti_sysc_clkdm_init, | ||
| 552 | .clkdm_deny_idle = ti_sysc_clkdm_deny_idle, | ||
| 553 | .clkdm_allow_idle = ti_sysc_clkdm_allow_idle, | ||
| 494 | .init_module = omap_hwmod_init_module, | 554 | .init_module = omap_hwmod_init_module, |
| 495 | .enable_module = ti_sysc_enable_module, | 555 | .enable_module = ti_sysc_enable_module, |
| 496 | .idle_module = ti_sysc_idle_module, | 556 | .idle_module = ti_sysc_idle_module, |
| @@ -399,8 +399,8 @@ static int __init brcmstb_gisb_arb_probe(struct platform_device *pdev) · 398 unmodified lines | |||
| 399 | &gisb_panic_notifier); | 399 | &gisb_panic_notifier); |
| 400 | } | 400 | } |
| 401 | 401 | ||
| 402 | dev_info(&pdev->dev, "registered mem: %p, irqs: %d, %d\n", | 402 | dev_info(&pdev->dev, "registered irqs: %d, %d\n", |
| 403 | gdev->base, timeout_irq, tea_irq); | 403 | timeout_irq, tea_irq); |
| 404 | 404 | ||
| 405 | return 0; | 405 | return 0; |
| 406 | } | 406 | } |
| @@ -443,11 +443,31 @@ int dprc_get_obj_region(struct fsl_mc_io *mc_io, · 442 unmodified lines | |||
| 443 | struct fsl_mc_command cmd = { 0 }; | 443 | struct fsl_mc_command cmd = { 0 }; |
| 444 | struct dprc_cmd_get_obj_region *cmd_params; | 444 | struct dprc_cmd_get_obj_region *cmd_params; |
| 445 | struct dprc_rsp_get_obj_region *rsp_params; | 445 | struct dprc_rsp_get_obj_region *rsp_params; |
| 446 | u16 major_ver, minor_ver; | ||
| 446 | int err; | 447 | int err; |
| 447 | 448 | ||
| 448 | /* prepare command */ | 449 | /* prepare command */ |
| 449 | cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG, | 450 | err = dprc_get_api_version(mc_io, 0, |
| 450 | cmd_flags, token); | 451 | &major_ver, |
| 452 | &minor_ver); | ||
| 453 | if (err) | ||
| 454 | return err; | ||
| 455 | |||
| 456 | /** | ||
| 457 | * MC API version 6.3 introduced a new field to the region | ||
| 458 | * descriptor: base_address. If the older API is in use then the base | ||
| 459 | * address is set to zero to indicate it needs to be obtained elsewhere | ||
| 460 | * (typically the device tree). | ||
| 461 | */ | ||
| 462 | if (major_ver > 6 || (major_ver == 6 && minor_ver >= 3)) | ||
| 463 | cmd.header = | ||
| 464 | mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG_V2, | ||
| 465 | cmd_flags, token); | ||
| 466 | else | ||
| 467 | cmd.header = | ||
| 468 | mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG, | ||
| 469 | cmd_flags, token); | ||
| 470 | |||
| 451 | cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params; | 471 | cmd_params = (struct dprc_cmd_get_obj_region *)cmd.params; |
| 452 | cmd_params->obj_id = cpu_to_le32(obj_id); | 472 | cmd_params->obj_id = cpu_to_le32(obj_id); |
| 453 | cmd_params->region_index = region_index; | 473 | cmd_params->region_index = region_index; |
| @@ -461,8 +481,12 @@ int dprc_get_obj_region(struct fsl_mc_io *mc_io, · 7 unmodified lines | |||
| 461 | 481 | ||
| 462 | /* retrieve response parameters */ | 482 | /* retrieve response parameters */ |
| 463 | rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params; | 483 | rsp_params = (struct dprc_rsp_get_obj_region *)cmd.params; |
| 464 | region_desc->base_offset = le64_to_cpu(rsp_params->base_addr); | 484 | region_desc->base_offset = le64_to_cpu(rsp_params->base_offset); |
| 465 | region_desc->size = le32_to_cpu(rsp_params->size); | 485 | region_desc->size = le32_to_cpu(rsp_params->size); |
| 486 | if (major_ver > 6 || (major_ver == 6 && minor_ver >= 3)) | ||
| 487 | region_desc->base_address = le64_to_cpu(rsp_params->base_addr); | ||
| 488 | else | ||
| 489 | region_desc->base_address = 0; | ||
| 466 | 490 | ||
| 467 | return 0; | 491 | return 0; |
| 468 | } | 492 | } |
| @@ -487,10 +487,19 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, · 486 unmodified lines | |||
| 487 | "dprc_get_obj_region() failed: %d\n", error); | 487 | "dprc_get_obj_region() failed: %d\n", error); |
| 488 | goto error_cleanup_regions; | 488 | goto error_cleanup_regions; |
| 489 | } | 489 | } |
| 490 | 490 | /* | |
| 491 | error = translate_mc_addr(mc_dev, mc_region_type, | 491 | * Older MC only returned region offset and no base address |
| 492 | * If base address is in the region_desc use it otherwise | ||
| 493 | * revert to old mechanism | ||
| 494 | */ | ||
| 495 | if (region_desc.base_address) | ||
| 496 | regions[i].start = region_desc.base_address + | ||
| 497 | region_desc.base_offset; | ||
| 498 | else | ||
| 499 | error = translate_mc_addr(mc_dev, mc_region_type, | ||
| 492 | region_desc.base_offset, | 500 | region_desc.base_offset, |
| 493 | ®ions[i].start); | 501 | ®ions[i].start); |
| 502 | |||
| 494 | if (error < 0) { | 503 | if (error < 0) { |
| 495 | dev_err(parent_dev, | 504 | dev_err(parent_dev, |
| 496 | "Invalid MC offset: %#x (for %s.%d\'s region %d)\n", | 505 | "Invalid MC offset: %#x (for %s.%d\'s region %d)\n", |
| @@ -504,6 +513,8 @@ static int fsl_mc_device_get_mmio_regions(struct fsl_mc_device *mc_dev, · 7 unmodified lines | |||
| 504 | regions[i].flags = IORESOURCE_IO; | 513 | regions[i].flags = IORESOURCE_IO; |
| 505 | if (region_desc.flags & DPRC_REGION_CACHEABLE) | 514 | if (region_desc.flags & DPRC_REGION_CACHEABLE) |
| 506 | regions[i].flags |= IORESOURCE_CACHEABLE; | 515 | regions[i].flags |= IORESOURCE_CACHEABLE; |
| 516 | if (region_desc.flags & DPRC_REGION_SHAREABLE) | ||
| 517 | regions[i].flags |= IORESOURCE_MEM; | ||
| 507 | } | 518 | } |
| 508 | 519 | ||
| 509 | mc_dev->regions = regions; | 520 | mc_dev->regions = regions; |
| @@ -79,9 +79,11 @@ int dpmcp_reset(struct fsl_mc_io *mc_io, · 78 unmodified lines | |||
| 79 | 79 | ||
| 80 | /* DPRC command versioning */ | 80 | /* DPRC command versioning */ |
| 81 | #define DPRC_CMD_BASE_VERSION 1 | 81 | #define DPRC_CMD_BASE_VERSION 1 |
| 82 | #define DPRC_CMD_2ND_VERSION 2 | ||
| 82 | #define DPRC_CMD_ID_OFFSET 4 | 83 | #define DPRC_CMD_ID_OFFSET 4 |
| 83 | 84 | ||
| 84 | #define DPRC_CMD(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION) | 85 | #define DPRC_CMD(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_BASE_VERSION) |
| 86 | #define DPRC_CMD_V2(id) (((id) << DPRC_CMD_ID_OFFSET) | DPRC_CMD_2ND_VERSION) | ||
| 85 | 87 | ||
| 86 | /* DPRC command IDs */ | 88 | /* DPRC command IDs */ |
| 87 | #define DPRC_CMDID_CLOSE DPRC_CMD(0x800) | 89 | #define DPRC_CMDID_CLOSE DPRC_CMD(0x800) |
| @@ -100,6 +102,7 @@ int dpmcp_reset(struct fsl_mc_io *mc_io, · 12 unmodified lines | |||
| 100 | #define DPRC_CMDID_GET_OBJ_COUNT DPRC_CMD(0x159) | 102 | #define DPRC_CMDID_GET_OBJ_COUNT DPRC_CMD(0x159) |
| 101 | #define DPRC_CMDID_GET_OBJ DPRC_CMD(0x15A) | 103 | #define DPRC_CMDID_GET_OBJ DPRC_CMD(0x15A) |
| 102 | #define DPRC_CMDID_GET_OBJ_REG DPRC_CMD(0x15E) | 104 | #define DPRC_CMDID_GET_OBJ_REG DPRC_CMD(0x15E) |
| 105 | #define DPRC_CMDID_GET_OBJ_REG_V2 DPRC_CMD_V2(0x15E) | ||
| 103 | #define DPRC_CMDID_SET_OBJ_IRQ DPRC_CMD(0x15F) | 106 | #define DPRC_CMDID_SET_OBJ_IRQ DPRC_CMD(0x15F) |
| 104 | 107 | ||
| 105 | struct dprc_cmd_open { | 108 | struct dprc_cmd_open { |
| @@ -199,9 +202,16 @@ struct dprc_rsp_get_obj_region { · 93 unmodified lines | |||
| 199 | /* response word 0 */ | 202 | /* response word 0 */ |
| 200 | __le64 pad; | 203 | __le64 pad; |
| 201 | /* response word 1 */ | 204 | /* response word 1 */ |
| 202 | __le64 base_addr; | 205 | __le64 base_offset; |
| 203 | /* response word 2 */ | 206 | /* response word 2 */ |
| 204 | __le32 size; | 207 | __le32 size; |
| 208 | __le32 pad2; | ||
| 209 | /* response word 3 */ | ||
| 210 | __le32 flags; | ||
| 211 | __le32 pad3; | ||
| 212 | /* response word 4 */ | ||
| 213 | /* base_addr may be zero if older MC firmware is used */ | ||
| 214 | __le64 base_addr; | ||
| 205 | }; | 215 | }; |
| 206 | 216 | ||
| 207 | struct dprc_cmd_set_obj_irq { | 217 | struct dprc_cmd_set_obj_irq { |
| @@ -334,6 +344,7 @@ int dprc_set_obj_irq(struct fsl_mc_io *mc_io, · 126 unmodified lines | |||
| 334 | /* Region flags */ | 344 | /* Region flags */ |
| 335 | /* Cacheable - Indicates that region should be mapped as cacheable */ | 345 | /* Cacheable - Indicates that region should be mapped as cacheable */ |
| 336 | #define DPRC_REGION_CACHEABLE 0x00000001 | 346 | #define DPRC_REGION_CACHEABLE 0x00000001 |
| 347 | #define DPRC_REGION_SHAREABLE 0x00000002 | ||
| 337 | 348 | ||
| 338 | /** | 349 | /** |
| 339 | * enum dprc_region_type - Region type | 350 | * enum dprc_region_type - Region type |
| @@ -342,7 +353,8 @@ int dprc_set_obj_irq(struct fsl_mc_io *mc_io, · 2 unmodified lines | |||
| 342 | */ | 353 | */ |
| 343 | enum dprc_region_type { | 354 | enum dprc_region_type { |
| 344 | DPRC_REGION_TYPE_MC_PORTAL, | 355 | DPRC_REGION_TYPE_MC_PORTAL, |
| 345 | DPRC_REGION_TYPE_QBMAN_PORTAL | 356 | DPRC_REGION_TYPE_QBMAN_PORTAL, |
| 357 | DPRC_REGION_TYPE_QBMAN_MEM_BACKED_PORTAL | ||
| 346 | }; | 358 | }; |
| 347 | 359 | ||
| 348 | /** | 360 | /** |
| @@ -360,6 +372,7 @@ struct dprc_region_desc { · 11 unmodified lines | |||
| 360 | u32 size; | 372 | u32 size; |
| 361 | u32 flags; | 373 | u32 flags; |
| 362 | enum dprc_region_type type; | 374 | enum dprc_region_type type; |
| 375 | u64 base_address; | ||
| 363 | }; | 376 | }; |
| 364 | 377 | ||
| 365 | int dprc_get_obj_region(struct fsl_mc_io *mc_io, | 378 | int dprc_get_obj_region(struct fsl_mc_io *mc_io, |
| @@ -71,6 +71,9 @@ static const char * const clock_names[SYSC_MAX_CLOCKS] = { · 70 unmodified lines | |||
| 71 | * @name: name if available | 71 | * @name: name if available |
| 72 | * @revision: interconnect target module revision | 72 | * @revision: interconnect target module revision |
| 73 | * @needs_resume: runtime resume needed on resume from suspend | 73 | * @needs_resume: runtime resume needed on resume from suspend |
| 74 | * @clk_enable_quirk: module specific clock enable quirk | ||
| 75 | * @clk_disable_quirk: module specific clock disable quirk | ||
| 76 | * @reset_done_quirk: module specific reset done quirk | ||
| 74 | */ | 77 | */ |
| 75 | struct sysc { | 78 | struct sysc { |
| 76 | struct device *dev; | 79 | struct device *dev; |
| @@ -89,10 +92,14 @@ struct sysc { · 12 unmodified lines | |||
| 89 | struct ti_sysc_cookie cookie; | 92 | struct ti_sysc_cookie cookie; |
| 90 | const char *name; | 93 | const char *name; |
| 91 | u32 revision; | 94 | u32 revision; |
| 92 | bool enabled; | 95 | unsigned int enabled:1; |
| 93 | bool needs_resume; | 96 | unsigned int needs_resume:1; |
| 94 | bool child_needs_resume; | 97 | unsigned int child_needs_resume:1; |
| 98 | unsigned int disable_on_idle:1; | ||
| 95 | struct delayed_work idle_work; | 99 | struct delayed_work idle_work; |
| 100 | void (*clk_enable_quirk)(struct sysc *sysc); | ||
| 101 | void (*clk_disable_quirk)(struct sysc *sysc); | ||
| 102 | void (*reset_done_quirk)(struct sysc *sysc); | ||
| 96 | }; | 103 | }; |
| 97 | 104 | ||
| 98 | static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np, | 105 | static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np, |
| @@ -100,6 +107,20 @@ static void sysc_parse_dts_quirks(struct sysc *ddata, struct device_node *np, · 1 unmodified line | |||
| 100 | 107 | ||
| 101 | static void sysc_write(struct sysc *ddata, int offset, u32 value) | 108 | static void sysc_write(struct sysc *ddata, int offset, u32 value) |
| 102 | { | 109 | { |
| 110 | if (ddata->cfg.quirks & SYSC_QUIRK_16BIT) { | ||
| 111 | writew_relaxed(value & 0xffff, ddata->module_va + offset); | ||
| 112 | |||
| 113 | /* Only i2c revision has LO and HI register with stride of 4 */ | ||
| 114 | if (ddata->offsets[SYSC_REVISION] >= 0 && | ||
| 115 | offset == ddata->offsets[SYSC_REVISION]) { | ||
| 116 | u16 hi = value >> 16; | ||
| 117 | |||
| 118 | writew_relaxed(hi, ddata->module_va + offset + 4); | ||
| 119 | } | ||
| 120 | |||
| 121 | return; | ||
| 122 | } | ||
| 123 | |||
| 103 | writel_relaxed(value, ddata->module_va + offset); | 124 | writel_relaxed(value, ddata->module_va + offset); |
| 104 | } | 125 | } |
| 105 | 126 | ||
| @@ -109,7 +130,14 @@ static u32 sysc_read(struct sysc *ddata, int offset) · 3 unmodified lines | |||
| 109 | u32 val; | 130 | u32 val; |
| 110 | 131 | ||
| 111 | val = readw_relaxed(ddata->module_va + offset); | 132 | val = readw_relaxed(ddata->module_va + offset); |
| 112 | val |= (readw_relaxed(ddata->module_va + offset + 4) << 16); | 133 | |
| 134 | /* Only i2c revision has LO and HI register with stride of 4 */ | ||
| 135 | if (ddata->offsets[SYSC_REVISION] >= 0 && | ||
| 136 | offset == ddata->offsets[SYSC_REVISION]) { | ||
| 137 | u16 tmp = readw_relaxed(ddata->module_va + offset + 4); | ||
| 138 | |||
| 139 | val |= tmp << 16; | ||
| 140 | } | ||
| 113 | 141 | ||
| 114 | return val; | 142 | return val; |
| 115 | } | 143 | } |
| @@ -132,6 +160,26 @@ static u32 sysc_read_revision(struct sysc *ddata) · 16 unmodified lines | |||
| 132 | return sysc_read(ddata, offset); | 160 | return sysc_read(ddata, offset); |
| 133 | } | 161 | } |
| 134 | 162 | ||
| 163 | static u32 sysc_read_sysconfig(struct sysc *ddata) | ||
| 164 | { | ||
| 165 | int offset = ddata->offsets[SYSC_SYSCONFIG]; | ||
| 166 | |||
| 167 | if (offset < 0) | ||
| 168 | return 0; | ||
| 169 | |||
| 170 | return sysc_read(ddata, offset); | ||
| 171 | } | ||
| 172 | |||
| 173 | static u32 sysc_read_sysstatus(struct sysc *ddata) | ||
| 174 | { | ||
| 175 | int offset = ddata->offsets[SYSC_SYSSTATUS]; | ||
| 176 | |||
| 177 | if (offset < 0) | ||
| 178 | return 0; | ||
| 179 | |||
| 180 | return sysc_read(ddata, offset); | ||
| 181 | } | ||
| 182 | |||
| 135 | static int sysc_add_named_clock_from_child(struct sysc *ddata, | 183 | static int sysc_add_named_clock_from_child(struct sysc *ddata, |
| 136 | const char *name, | 184 | const char *name, |
| 137 | const char *optfck_name) | 185 | const char *optfck_name) |
| @@ -422,6 +470,30 @@ static void sysc_disable_opt_clocks(struct sysc *ddata) · 284 unmodified lines | |||
| 422 | } | 470 | } |
| 423 | } | 471 | } |
| 424 | 472 | ||
| 473 | static void sysc_clkdm_deny_idle(struct sysc *ddata) | ||
| 474 | { | ||
| 475 | struct ti_sysc_platform_data *pdata; | ||
| 476 | |||
| 477 | if (ddata->legacy_mode) | ||
| 478 | return; | ||
| 479 | |||
| 480 | pdata = dev_get_platdata(ddata->dev); | ||
| 481 | if (pdata && pdata->clkdm_deny_idle) | ||
| 482 | pdata->clkdm_deny_idle(ddata->dev, &ddata->cookie); | ||
| 483 | } | ||
| 484 | |||
| 485 | static void sysc_clkdm_allow_idle(struct sysc *ddata) | ||
| 486 | { | ||
| 487 | struct ti_sysc_platform_data *pdata; | ||
| 488 | |||
| 489 | if (ddata->legacy_mode) | ||
| 490 | return; | ||
| 491 | |||
| 492 | pdata = dev_get_platdata(ddata->dev); | ||
| 493 | if (pdata && pdata->clkdm_allow_idle) | ||
| 494 | pdata->clkdm_allow_idle(ddata->dev, &ddata->cookie); | ||
| 495 | } | ||
| 496 | |||
| 425 | /** | 497 | /** |
| 426 | * sysc_init_resets - init rstctrl reset line if configured | 498 | * sysc_init_resets - init rstctrl reset line if configured |
| 427 | * @ddata: device driver data | 499 | * @ddata: device driver data |
| @@ -431,7 +503,7 @@ static void sysc_disable_opt_clocks(struct sysc *ddata) · 3 unmodified lines | |||
| 431 | static int sysc_init_resets(struct sysc *ddata) | 503 | static int sysc_init_resets(struct sysc *ddata) |
| 432 | { | 504 | { |
| 433 | ddata->rsts = | 505 | ddata->rsts = |
| 434 | devm_reset_control_array_get_optional_exclusive(ddata->dev); | 506 | devm_reset_control_get_optional(ddata->dev, "rstctrl"); |
| 435 | if (IS_ERR(ddata->rsts)) | 507 | if (IS_ERR(ddata->rsts)) |
| 436 | return PTR_ERR(ddata->rsts); | 508 | return PTR_ERR(ddata->rsts); |
| 437 | 509 | ||
| @@ -694,8 +766,11 @@ static int sysc_ioremap(struct sysc *ddata) · 256 unmodified lines | |||
| 694 | ddata->offsets[SYSC_SYSCONFIG], | 766 | ddata->offsets[SYSC_SYSCONFIG], |
| 695 | ddata->offsets[SYSC_SYSSTATUS]); | 767 | ddata->offsets[SYSC_SYSSTATUS]); |
| 696 | 768 | ||
| 769 | if (size < SZ_1K) | ||
| 770 | size = SZ_1K; | ||
| 771 | |||
| 697 | if ((size + sizeof(u32)) > ddata->module_size) | 772 | if ((size + sizeof(u32)) > ddata->module_size) |
| 698 | return -EINVAL; | 773 | size = ddata->module_size; |
| 699 | } | 774 | } |
| 700 | 775 | ||
| 701 | ddata->module_va = devm_ioremap(ddata->dev, | 776 | ddata->module_va = devm_ioremap(ddata->dev, |
| @@ -794,7 +869,9 @@ static void sysc_show_registers(struct sysc *ddata) · 92 unmodified lines | |||
| 794 | } | 869 | } |
| 795 | 870 | ||
| 796 | #define SYSC_IDLE_MASK (SYSC_NR_IDLEMODES - 1) | 871 | #define SYSC_IDLE_MASK (SYSC_NR_IDLEMODES - 1) |
| 872 | #define SYSC_CLOCACT_ICK 2 | ||
| 797 | 873 | ||
| 874 | /* Caller needs to manage sysc_clkdm_deny_idle() and sysc_clkdm_allow_idle() */ | ||
| 798 | static int sysc_enable_module(struct device *dev) | 875 | static int sysc_enable_module(struct device *dev) |
| 799 | { | 876 | { |
| 800 | struct sysc *ddata; | 877 | struct sysc *ddata; |
| @@ -805,23 +882,34 @@ static int sysc_enable_module(struct device *dev) · 4 unmodified lines | |||
| 805 | if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV) | 882 | if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV) |
| 806 | return 0; | 883 | return 0; |
| 807 | 884 | ||
| 808 | /* | ||
| 809 | * TODO: Need to prevent clockdomain autoidle? | ||
| 810 | * See clkdm_deny_idle() in arch/mach-omap2/omap_hwmod.c | ||
| 811 | */ | ||
| 812 | |||
| 813 | regbits = ddata->cap->regbits; | 885 | regbits = ddata->cap->regbits; |
| 814 | reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]); | 886 | reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]); |
| 815 | 887 | ||
| 888 | /* Set CLOCKACTIVITY, we only use it for ick */ | ||
| 889 | if (regbits->clkact_shift >= 0 && | ||
| 890 | (ddata->cfg.quirks & SYSC_QUIRK_USE_CLOCKACT || | ||
| 891 | ddata->cfg.sysc_val & BIT(regbits->clkact_shift))) | ||
| 892 | reg |= SYSC_CLOCACT_ICK << regbits->clkact_shift; | ||
| 893 | |||
| 816 | /* Set SIDLE mode */ | 894 | /* Set SIDLE mode */ |
| 817 | idlemodes = ddata->cfg.sidlemodes; | 895 | idlemodes = ddata->cfg.sidlemodes; |
| 818 | if (!idlemodes || regbits->sidle_shift < 0) | 896 | if (!idlemodes || regbits->sidle_shift < 0) |
| 819 | goto set_midle; | 897 | goto set_midle; |
| 820 | 898 | ||
| 821 | best_mode = fls(ddata->cfg.sidlemodes) - 1; | 899 | if (ddata->cfg.quirks & (SYSC_QUIRK_SWSUP_SIDLE | |
| 822 | if (best_mode > SYSC_IDLE_MASK) { | 900 | SYSC_QUIRK_SWSUP_SIDLE_ACT)) { |
| 823 | dev_err(dev, "%s: invalid sidlemode\n", __func__); | 901 | best_mode = SYSC_IDLE_NO; |
| 824 | return -EINVAL; | 902 | } else { |
| 903 | best_mode = fls(ddata->cfg.sidlemodes) - 1; | ||
| 904 | if (best_mode > SYSC_IDLE_MASK) { | ||
| 905 | dev_err(dev, "%s: invalid sidlemode\n", __func__); | ||
| 906 | return -EINVAL; | ||
| 907 | } | ||
| 908 | |||
| 909 | /* Set WAKEUP */ | ||
| 910 | if (regbits->enwkup_shift >= 0 && | ||
| 911 | ddata->cfg.sysc_val & BIT(regbits->enwkup_shift)) | ||
| 912 | reg |= BIT(regbits->enwkup_shift); | ||
| 825 | } | 913 | } |
| 826 | 914 | ||
| 827 | reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift); | 915 | reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift); |
| @@ -832,7 +920,7 @@ set_midle: · 4 unmodified lines | |||
| 832 | /* Set MIDLE mode */ | 920 | /* Set MIDLE mode */ |
| 833 | idlemodes = ddata->cfg.midlemodes; | 921 | idlemodes = ddata->cfg.midlemodes; |
| 834 | if (!idlemodes || regbits->midle_shift < 0) | 922 | if (!idlemodes || regbits->midle_shift < 0) |
| 835 | return 0; | 923 | goto set_autoidle; |
| 836 | 924 | ||
| 837 | best_mode = fls(ddata->cfg.midlemodes) - 1; | 925 | best_mode = fls(ddata->cfg.midlemodes) - 1; |
| 838 | if (best_mode > SYSC_IDLE_MASK) { | 926 | if (best_mode > SYSC_IDLE_MASK) { |
| @@ -844,6 +932,14 @@ set_midle: · 5 unmodified lines | |||
| 844 | reg |= best_mode << regbits->midle_shift; | 932 | reg |= best_mode << regbits->midle_shift; |
| 845 | sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg); | 933 | sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg); |
| 846 | 934 | ||
| 935 | set_autoidle: | ||
| 936 | /* Autoidle bit must enabled separately if available */ | ||
| 937 | if (regbits->autoidle_shift >= 0 && | ||
| 938 | ddata->cfg.sysc_val & BIT(regbits->autoidle_shift)) { | ||
| 939 | reg |= 1 << regbits->autoidle_shift; | ||
| 940 | sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg); | ||
| 941 | } | ||
| 942 | |||
| 847 | return 0; | 943 | return 0; |
| 848 | } | 944 | } |
| 849 | 945 | ||
| @@ -861,6 +957,7 @@ static int sysc_best_idle_mode(u32 idlemodes, u32 *best_mode) · 11 unmodified lines | |||
| 861 | return 0; | 957 | return 0; |
| 862 | } | 958 | } |
| 863 | 959 | ||
| 960 | /* Caller needs to manage sysc_clkdm_deny_idle() and sysc_clkdm_allow_idle() */ | ||
| 864 | static int sysc_disable_module(struct device *dev) | 961 | static int sysc_disable_module(struct device *dev) |
| 865 | { | 962 | { |
| 866 | struct sysc *ddata; | 963 | struct sysc *ddata; |
| @@ -872,11 +969,6 @@ static int sysc_disable_module(struct device *dev) · 5 unmodified lines | |||
| 872 | if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV) | 969 | if (ddata->offsets[SYSC_SYSCONFIG] == -ENODEV) |
| 873 | return 0; | 970 | return 0; |
| 874 | 971 | ||
| 875 | /* | ||
| 876 | * TODO: Need to prevent clockdomain autoidle? | ||
| 877 | * See clkdm_deny_idle() in arch/mach-omap2/omap_hwmod.c | ||
| 878 | */ | ||
| 879 | |||
| 880 | regbits = ddata->cap->regbits; | 972 | regbits = ddata->cap->regbits; |
| 881 | reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]); | 973 | reg = sysc_read(ddata, ddata->offsets[SYSC_SYSCONFIG]); |
| 882 | 974 | ||
| @@ -901,14 +993,21 @@ set_sidle: · 18 unmodified lines | |||
| 901 | if (!idlemodes || regbits->sidle_shift < 0) | 993 | if (!idlemodes || regbits->sidle_shift < 0) |
| 902 | return 0; | 994 | return 0; |
| 903 | 995 | ||
| 904 | ret = sysc_best_idle_mode(idlemodes, &best_mode); | 996 | if (ddata->cfg.quirks & SYSC_QUIRK_SWSUP_SIDLE) { |
| 905 | if (ret) { | 997 | best_mode = SYSC_IDLE_FORCE; |
| 906 | dev_err(dev, "%s: invalid sidlemode\n", __func__); | 998 | } else { |
| 907 | return ret; | 999 | ret = sysc_best_idle_mode(idlemodes, &best_mode); |
| 1000 | if (ret) { | ||
| 1001 | dev_err(dev, "%s: invalid sidlemode\n", __func__); | ||
| 1002 | return ret; | ||
| 1003 | } | ||
| 908 | } | 1004 | } |
| 909 | 1005 | ||
| 910 | reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift); | 1006 | reg &= ~(SYSC_IDLE_MASK << regbits->sidle_shift); |
| 911 | reg |= best_mode << regbits->sidle_shift; | 1007 | reg |= best_mode << regbits->sidle_shift; |
| 1008 | if (regbits->autoidle_shift >= 0 && | ||
| 1009 | ddata->cfg.sysc_val & BIT(regbits->autoidle_shift)) | ||
| 1010 | reg |= 1 << regbits->autoidle_shift; | ||
| 912 | sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg); | 1011 | sysc_write(ddata, ddata->offsets[SYSC_SYSCONFIG], reg); |
| 913 | 1012 | ||
| 914 | return 0; | 1013 | return 0; |
| @@ -932,6 +1031,9 @@ static int __maybe_unused sysc_runtime_suspend_legacy(struct device *dev, · 17 unmodified lines | |||
| 932 | dev_err(dev, "%s: could not idle: %i\n", | 1031 | dev_err(dev, "%s: could not idle: %i\n", |
| 933 | __func__, error); | 1032 | __func__, error); |
| 934 | 1033 | ||
| 1034 | if (ddata->disable_on_idle) | ||
| 1035 | reset_control_assert(ddata->rsts); | ||
| 1036 | |||
| 935 | return 0; | 1037 | return 0; |
| 936 | } | 1038 | } |
| 937 | 1039 | ||
| @@ -941,6 +1043,9 @@ static int __maybe_unused sysc_runtime_resume_legacy(struct device *dev, · 3 unmodified lines | |||
| 941 | struct ti_sysc_platform_data *pdata; | 1043 | struct ti_sysc_platform_data *pdata; |
| 942 | int error; | 1044 | int error; |
| 943 | 1045 | ||
| 1046 | if (ddata->disable_on_idle) | ||
| 1047 | reset_control_deassert(ddata->rsts); | ||
| 1048 | |||
| 944 | pdata = dev_get_platdata(ddata->dev); | 1049 | pdata = dev_get_platdata(ddata->dev); |
| 945 | if (!pdata) | 1050 | if (!pdata) |
| 946 | return 0; | 1051 | return 0; |
| @@ -966,14 +1071,16 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev) · 19 unmodified lines | |||
| 966 | if (!ddata->enabled) | 1071 | if (!ddata->enabled) |
| 967 | return 0; | 1072 | return 0; |
| 968 | 1073 | ||
| 1074 | sysc_clkdm_deny_idle(ddata); | ||
| 1075 | |||
| 969 | if (ddata->legacy_mode) { | 1076 | if (ddata->legacy_mode) { |
| 970 | error = sysc_runtime_suspend_legacy(dev, ddata); | 1077 | error = sysc_runtime_suspend_legacy(dev, ddata); |
| 971 | if (error) | 1078 | if (error) |
| 972 | return error; | 1079 | goto err_allow_idle; |
| 973 | } else { | 1080 | } else { |
| 974 | error = sysc_disable_module(dev); | 1081 | error = sysc_disable_module(dev); |
| 975 | if (error) | 1082 | if (error) |
| 976 | return error; | 1083 | goto err_allow_idle; |
| 977 | } | 1084 | } |
| 978 | 1085 | ||
| 979 | sysc_disable_main_clocks(ddata); | 1086 | sysc_disable_main_clocks(ddata); |
| @@ -983,6 +1090,12 @@ static int __maybe_unused sysc_runtime_suspend(struct device *dev) · 3 unmodified lines | |||
| 983 | 1090 | ||
| 984 | ddata->enabled = false; | 1091 | ddata->enabled = false; |
| 985 | 1092 | ||
| 1093 | err_allow_idle: | ||
| 1094 | sysc_clkdm_allow_idle(ddata); | ||
| 1095 | |||
| 1096 | if (ddata->disable_on_idle) | ||
| 1097 | reset_control_assert(ddata->rsts); | ||
| 1098 | |||
| 986 | return error; | 1099 | return error; |
| 987 | } | 1100 | } |
| 988 | 1101 | ||
| @@ -996,10 +1109,15 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev) · 7 unmodified lines | |||
| 996 | if (ddata->enabled) | 1109 | if (ddata->enabled) |
| 997 | return 0; | 1110 | return 0; |
| 998 | 1111 | ||
| 1112 | if (ddata->disable_on_idle) | ||
| 1113 | reset_control_deassert(ddata->rsts); | ||
| 1114 | |||
| 1115 | sysc_clkdm_deny_idle(ddata); | ||
| 1116 | |||
| 999 | if (sysc_opt_clks_needed(ddata)) { | 1117 | if (sysc_opt_clks_needed(ddata)) { |
| 1000 | error = sysc_enable_opt_clocks(ddata); | 1118 | error = sysc_enable_opt_clocks(ddata); |
| 1001 | if (error) | 1119 | if (error) |
| 1002 | return error; | 1120 | goto err_allow_idle; |
| 1003 | } | 1121 | } |
| 1004 | 1122 | ||
| 1005 | error = sysc_enable_main_clocks(ddata); | 1123 | error = sysc_enable_main_clocks(ddata); |
| @@ -1018,6 +1136,8 @@ static int __maybe_unused sysc_runtime_resume(struct device *dev) · 12 unmodified lines | |||
| 1018 | 1136 | ||
| 1019 | ddata->enabled = true; | 1137 | ddata->enabled = true; |
| 1020 | 1138 | ||
| 1139 | sysc_clkdm_allow_idle(ddata); | ||
| 1140 | |||
| 1021 | return 0; | 1141 | return 0; |
| 1022 | 1142 | ||
| 1023 | err_main_clocks: | 1143 | err_main_clocks: |
| @@ -1025,6 +1145,8 @@ err_main_clocks: · 1 unmodified line | |||
| 1025 | err_opt_clocks: | 1145 | err_opt_clocks: |
| 1026 | if (sysc_opt_clks_needed(ddata)) | 1146 | if (sysc_opt_clks_needed(ddata)) |
| 1027 | sysc_disable_opt_clocks(ddata); | 1147 | sysc_disable_opt_clocks(ddata); |
| 1148 | err_allow_idle: | ||
| 1149 | sysc_clkdm_allow_idle(ddata); | ||
| 1028 | 1150 | ||
| 1029 | return error; | 1151 | return error; |
| 1030 | } | 1152 | } |
| @@ -1106,8 +1228,10 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { · 75 unmodified lines | |||
| 1106 | 0), | 1228 | 0), |
| 1107 | SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffff00ff, | 1229 | SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffff00ff, |
| 1108 | 0), | 1230 | 0), |
| 1231 | SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000046, 0xffffffff, | ||
| 1232 | SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE), | ||
| 1109 | SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff, | 1233 | SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff, |
| 1110 | SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE), | 1234 | SYSC_QUIRK_SWSUP_SIDLE | SYSC_QUIRK_LEGACY_IDLE), |
| 1111 | /* Uarts on omap4 and later */ | 1235 | /* Uarts on omap4 and later */ |
| 1112 | SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffff00ff, | 1236 | SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffff00ff, |
| 1113 | SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE), | 1237 | SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE), |
| @@ -1119,6 +1243,22 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { · 5 unmodified lines | |||
| 1119 | SYSC_QUIRK_EXT_OPT_CLOCK | SYSC_QUIRK_NO_RESET_ON_INIT | | 1243 | SYSC_QUIRK_EXT_OPT_CLOCK | SYSC_QUIRK_NO_RESET_ON_INIT | |
| 1120 | SYSC_QUIRK_SWSUP_SIDLE), | 1244 | SYSC_QUIRK_SWSUP_SIDLE), |
| 1121 | 1245 | ||
| 1246 | /* Quirks that need to be set based on detected module */ | ||
| 1247 | SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff, | ||
| 1248 | SYSC_MODULE_QUIRK_HDQ1W), | ||
| 1249 | SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff, | ||
| 1250 | SYSC_MODULE_QUIRK_HDQ1W), | ||
| 1251 | SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x00000036, 0x000000ff, | ||
| 1252 | SYSC_MODULE_QUIRK_I2C), | ||
| 1253 | SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x0000003c, 0x000000ff, | ||
| 1254 | SYSC_MODULE_QUIRK_I2C), | ||
| 1255 | SYSC_QUIRK("i2c", 0, 0, 0x20, 0x10, 0x00000040, 0x000000ff, | ||
| 1256 | SYSC_MODULE_QUIRK_I2C), | ||
| 1257 | SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0, | ||
| 1258 | SYSC_MODULE_QUIRK_I2C), | ||
| 1259 | SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, | ||
| 1260 | SYSC_MODULE_QUIRK_WDT), | ||
| 1261 | |||
| 1122 | #ifdef DEBUG | 1262 | #ifdef DEBUG |
| 1123 | SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0), | 1263 | SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0), |
| 1124 | SYSC_QUIRK("atl", 0, 0, -1, -1, 0x0a070100, 0xffffffff, 0), | 1264 | SYSC_QUIRK("atl", 0, 0, -1, -1, 0x0a070100, 0xffffffff, 0), |
| @@ -1132,11 +1272,8 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { · 7 unmodified lines | |||
| 1132 | SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0), | 1272 | SYSC_QUIRK("dwc3", 0, 0, 0x10, -1, 0x500a0200, 0xffffffff, 0), |
| 1133 | SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0), | 1273 | SYSC_QUIRK("epwmss", 0, 0, 0x4, -1, 0x47400001, 0xffffffff, 0), |
| 1134 | SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -1, 0, 0, 0), | 1274 | SYSC_QUIRK("gpu", 0, 0x1fc00, 0x1fc10, -1, 0, 0, 0), |
| 1135 | SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x00000006, 0xffffffff, 0), | ||
| 1136 | SYSC_QUIRK("hdq1w", 0, 0, 0x14, 0x18, 0x0000000a, 0xffffffff, 0), | ||
| 1137 | SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0), | 1275 | SYSC_QUIRK("hsi", 0, 0, 0x10, 0x14, 0x50043101, 0xffffffff, 0), |
| 1138 | SYSC_QUIRK("iss", 0, 0, 0x10, -1, 0x40000101, 0xffffffff, 0), | 1276 | SYSC_QUIRK("iss", 0, 0, 0x10, -1, 0x40000101, 0xffffffff, 0), |
| 1139 | SYSC_QUIRK("i2c", 0, 0, 0x10, 0x90, 0x5040000a, 0xfffff0f0, 0), | ||
| 1140 | SYSC_QUIRK("lcdc", 0, 0, 0x54, -1, 0x4f201000, 0xffffffff, 0), | 1277 | SYSC_QUIRK("lcdc", 0, 0, 0x54, -1, 0x4f201000, 0xffffffff, 0), |
| 1141 | SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44306302, 0xffffffff, 0), | 1278 | SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44306302, 0xffffffff, 0), |
| 1142 | SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44307b02, 0xffffffff, 0), | 1279 | SYSC_QUIRK("mcasp", 0, 0, 0x4, -1, 0x44307b02, 0xffffffff, 0), |
| @@ -1172,7 +1309,6 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { · 29 unmodified lines | |||
| 1172 | SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, -1, 0x50700101, 0xffffffff, 0), | 1309 | SYSC_QUIRK("usb_host_hs", 0, 0, 0x10, -1, 0x50700101, 0xffffffff, 0), |
| 1173 | SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050, | 1310 | SYSC_QUIRK("usb_otg_hs", 0, 0x400, 0x404, 0x408, 0x00000050, |
| 1174 | 0xffffffff, 0), | 1311 | 0xffffffff, 0), |
| 1175 | SYSC_QUIRK("wdt", 0, 0, 0x10, 0x14, 0x502a0500, 0xfffff0f0, 0), | ||
| 1176 | SYSC_QUIRK("vfpe", 0, 0, 0x104, -1, 0x4d001200, 0xffffffff, 0), | 1312 | SYSC_QUIRK("vfpe", 0, 0, 0x104, -1, 0x4d001200, 0xffffffff, 0), |
| 1177 | #endif | 1313 | #endif |
| 1178 | }; | 1314 | }; |
| @@ -1245,6 +1381,121 @@ static void sysc_init_revision_quirks(struct sysc *ddata) · 66 unmodified lines | |||
| 1245 | } | 1381 | } |
| 1246 | } | 1382 | } |
| 1247 | 1383 | ||
| 1384 | /* 1-wire needs module's internal clocks enabled for reset */ | ||
| 1385 | static void sysc_clk_enable_quirk_hdq1w(struct sysc *ddata) | ||
| 1386 | { | ||
| 1387 | int offset = 0x0c; /* HDQ_CTRL_STATUS */ | ||
| 1388 | u16 val; | ||
| 1389 | |||
| 1390 | val = sysc_read(ddata, offset); | ||
| 1391 | val |= BIT(5); | ||
| 1392 | sysc_write(ddata, offset, val); | ||
| 1393 | } | ||
| 1394 | |||
| 1395 | /* I2C needs extra enable bit toggling for reset */ | ||
| 1396 | static void sysc_clk_quirk_i2c(struct sysc *ddata, bool enable) | ||
| 1397 | { | ||
| 1398 | int offset; | ||
| 1399 | u16 val; | ||
| 1400 | |||
| 1401 | /* I2C_CON, omap2/3 is different from omap4 and later */ | ||
| 1402 | if ((ddata->revision & 0xffffff00) == 0x001f0000) | ||
| 1403 | offset = 0x24; | ||
| 1404 | else | ||
| 1405 | offset = 0xa4; | ||
| 1406 | |||
| 1407 | /* I2C_EN */ | ||
| 1408 | val = sysc_read(ddata, offset); | ||
| 1409 | if (enable) | ||
| 1410 | val |= BIT(15); | ||
| 1411 | else | ||
| 1412 | val &= ~BIT(15); | ||
| 1413 | sysc_write(ddata, offset, val); | ||
| 1414 | } | ||
| 1415 | |||
| 1416 | static void sysc_clk_enable_quirk_i2c(struct sysc *ddata) | ||
| 1417 | { | ||
| 1418 | sysc_clk_quirk_i2c(ddata, true); | ||
| 1419 | } | ||
| 1420 | |||
| 1421 | static void sysc_clk_disable_quirk_i2c(struct sysc *ddata) | ||
| 1422 | { | ||
| 1423 | sysc_clk_quirk_i2c(ddata, false); | ||
| 1424 | } | ||
| 1425 | |||
| 1426 | /* Watchdog timer needs a disable sequence after reset */ | ||
| 1427 | static void sysc_reset_done_quirk_wdt(struct sysc *ddata) | ||
| 1428 | { | ||
| 1429 | int wps, spr, error; | ||
| 1430 | u32 val; | ||
| 1431 | |||
| 1432 | wps = 0x34; | ||
| 1433 | spr = 0x48; | ||
| 1434 | |||
| 1435 | sysc_write(ddata, spr, 0xaaaa); | ||
| 1436 | error = readl_poll_timeout(ddata->module_va + wps, val, | ||
| 1437 | !(val & 0x10), 100, | ||
| 1438 | MAX_MODULE_SOFTRESET_WAIT); | ||
| 1439 | if (error) | ||
| 1440 | dev_warn(ddata->dev, "wdt disable spr failed\n"); | ||
| 1441 | |||
| 1442 | sysc_write(ddata, wps, 0x5555); | ||
| 1443 | error = readl_poll_timeout(ddata->module_va + wps, val, | ||
| 1444 | !(val & 0x10), 100, | ||
| 1445 | MAX_MODULE_SOFTRESET_WAIT); | ||
| 1446 | if (error) | ||
| 1447 | dev_warn(ddata->dev, "wdt disable wps failed\n"); | ||
| 1448 | } | ||
| 1449 | |||
| 1450 | static void sysc_init_module_quirks(struct sysc *ddata) | ||
| 1451 | { | ||
| 1452 | if (ddata->legacy_mode || !ddata->name) | ||
| 1453 | return; | ||
| 1454 | |||
| 1455 | if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_HDQ1W) { | ||
| 1456 | ddata->clk_enable_quirk = sysc_clk_enable_quirk_hdq1w; | ||
| 1457 | |||
| 1458 | return; | ||
| 1459 | } | ||
| 1460 | |||
| 1461 | if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_I2C) { | ||
| 1462 | ddata->clk_enable_quirk = sysc_clk_enable_quirk_i2c; | ||
| 1463 | ddata->clk_disable_quirk = sysc_clk_disable_quirk_i2c; | ||
| 1464 | |||
| 1465 | return; | ||
| 1466 | } | ||
| 1467 | |||
| 1468 | if (ddata->cfg.quirks & SYSC_MODULE_QUIRK_WDT) | ||
| 1469 | ddata->reset_done_quirk = sysc_reset_done_quirk_wdt; | ||
| 1470 | } | ||
| 1471 | |||
| 1472 | static int sysc_clockdomain_init(struct sysc *ddata) | ||
| 1473 | { | ||
| 1474 | struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev); | ||
| 1475 | struct clk *fck = NULL, *ick = NULL; | ||
| 1476 | int error; | ||
| 1477 | |||
| 1478 | if (!pdata || !pdata->init_clockdomain) | ||
| 1479 | return 0; | ||
| 1480 | |||
| 1481 | switch (ddata->nr_clocks) { | ||
| 1482 | case 2: | ||
| 1483 | ick = ddata->clocks[SYSC_ICK]; | ||
| 1484 | /* fallthrough */ | ||
| 1485 | case 1: | ||
| 1486 | fck = ddata->clocks[SYSC_FCK]; | ||
| 1487 | break; | ||
| 1488 | case 0: | ||
| 1489 | return 0; | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | error = pdata->init_clockdomain(ddata->dev, fck, ick, &ddata->cookie); | ||
| 1493 | if (!error || error == -ENODEV) | ||
| 1494 | return 0; | ||
| 1495 | |||
| 1496 | return error; | ||
| 1497 | } | ||
| 1498 | |||
| 1248 | /* | 1499 | /* |
| 1249 | * Note that pdata->init_module() typically does a reset first. After | 1500 | * Note that pdata->init_module() typically does a reset first. After |
| 1250 | * pdata->init_module() is done, PM runtime can be used for the interconnect | 1501 | * pdata->init_module() is done, PM runtime can be used for the interconnect |
| @@ -1255,7 +1506,7 @@ static int sysc_legacy_init(struct sysc *ddata) · 4 unmodified lines | |||
| 1255 | struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev); | 1506 | struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev); |
| 1256 | int error; | 1507 | int error; |
| 1257 | 1508 | ||
| 1258 | if (!ddata->legacy_mode || !pdata || !pdata->init_module) | 1509 | if (!pdata || !pdata->init_module) |
| 1259 | return 0; | 1510 | return 0; |
| 1260 | 1511 | ||
| 1261 | error = pdata->init_module(ddata->dev, ddata->mdata, &ddata->cookie); | 1512 | error = pdata->init_module(ddata->dev, ddata->mdata, &ddata->cookie); |
| @@ -1280,7 +1531,7 @@ static int sysc_legacy_init(struct sysc *ddata) · 18 unmodified lines | |||
| 1280 | */ | 1531 | */ |
| 1281 | static int sysc_rstctrl_reset_deassert(struct sysc *ddata, bool reset) | 1532 | static int sysc_rstctrl_reset_deassert(struct sysc *ddata, bool reset) |
| 1282 | { | 1533 | { |
| 1283 | int error; | 1534 | int error, val; |
| 1284 | 1535 | ||
| 1285 | if (!ddata->rsts) | 1536 | if (!ddata->rsts) |
| 1286 | return 0; | 1537 | return 0; |
| @@ -1291,37 +1542,68 @@ static int sysc_rstctrl_reset_deassert(struct sysc *ddata, bool reset) · 4 unmodified lines | |||
| 1291 | return error; | 1542 | return error; |
| 1292 | } | 1543 | } |
| 1293 | 1544 | ||
| 1294 | return reset_control_deassert(ddata->rsts); | 1545 | error = reset_control_deassert(ddata->rsts); |
| 1546 | if (error == -EEXIST) | ||
| 1547 | return 0; | ||
| 1548 | |||
| 1549 | error = readx_poll_timeout(reset_control_status, ddata->rsts, val, | ||
| 1550 | val == 0, 100, MAX_MODULE_SOFTRESET_WAIT); | ||
| 1551 | |||
| 1552 | return error; | ||
| 1295 | } | 1553 | } |
| 1296 | 1554 | ||
| 1555 | /* | ||
| 1556 | * Note that the caller must ensure the interconnect target module is enabled | ||
| 1557 | * before calling reset. Otherwise reset will not complete. | ||
| 1558 | */ | ||
| 1297 | static int sysc_reset(struct sysc *ddata) | 1559 | static int sysc_reset(struct sysc *ddata) |
| 1298 | { | 1560 | { |
| 1299 | int offset = ddata->offsets[SYSC_SYSCONFIG]; | 1561 | int sysc_offset, syss_offset, sysc_val, rstval, quirks, error = 0; |
| 1300 | int val; | 1562 | u32 sysc_mask, syss_done; |
| 1563 | |||
| 1564 | sysc_offset = ddata->offsets[SYSC_SYSCONFIG]; | ||
| 1565 | syss_offset = ddata->offsets[SYSC_SYSSTATUS]; | ||
| 1566 | quirks = ddata->cfg.quirks; | ||
| 1301 | 1567 | ||
| 1302 | if (ddata->legacy_mode || offset < 0 || | 1568 | if (ddata->legacy_mode || sysc_offset < 0 || |
| 1569 | ddata->cap->regbits->srst_shift < 0 || | ||
| 1303 | ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) | 1570 | ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) |
| 1304 | return 0; | 1571 | return 0; |
| 1305 | 1572 | ||
| 1306 | /* | 1573 | sysc_mask = BIT(ddata->cap->regbits->srst_shift); |
| 1307 | * Currently only support reset status in sysstatus. | ||
| 1308 | * Warn and return error in all other cases | ||
| 1309 | */ | ||
| 1310 | if (!ddata->cfg.syss_mask) { | ||
| 1311 | dev_err(ddata->dev, "No ti,syss-mask. Reset failed\n"); | ||
| 1312 | return -EINVAL; | ||
| 1313 | } | ||
| 1314 | 1574 | ||
| 1315 | val = sysc_read(ddata, offset); | 1575 | if (ddata->cfg.quirks & SYSS_QUIRK_RESETDONE_INVERTED) |
| 1316 | val |= (0x1 << ddata->cap->regbits->srst_shift); | 1576 | syss_done = 0; |
| 1317 | sysc_write(ddata, offset, val); | 1577 | else |
| 1578 | syss_done = ddata->cfg.syss_mask; | ||
| 1579 | |||
| 1580 | if (ddata->clk_disable_quirk) | ||
| 1581 | ddata->clk_disable_quirk(ddata); | ||
| 1582 | |||
| 1583 | sysc_val = sysc_read_sysconfig(ddata); | ||
| 1584 | sysc_val |= sysc_mask; | ||
| 1585 | sysc_write(ddata, sysc_offset, sysc_val); | ||
| 1586 | |||
| 1587 | if (ddata->clk_enable_quirk) | ||
| 1588 | ddata->clk_enable_quirk(ddata); | ||
| 1318 | 1589 | ||
| 1319 | /* Poll on reset status */ | 1590 | /* Poll on reset status */ |
| 1320 | offset = ddata->offsets[SYSC_SYSSTATUS]; | 1591 | if (syss_offset >= 0) { |
| 1592 | error = readx_poll_timeout(sysc_read_sysstatus, ddata, rstval, | ||
| 1593 | (rstval & ddata->cfg.syss_mask) == | ||
| 1594 | syss_done, | ||
| 1595 | 100, MAX_MODULE_SOFTRESET_WAIT); | ||
| 1596 | |||
| 1597 | } else if (ddata->cfg.quirks & SYSC_QUIRK_RESET_STATUS) { | ||
| 1598 | error = readx_poll_timeout(sysc_read_sysconfig, ddata, rstval, | ||
| 1599 | !(rstval & sysc_mask), | ||
| 1600 | 100, MAX_MODULE_SOFTRESET_WAIT); | ||
| 1601 | } | ||
| 1602 | |||
| 1603 | if (ddata->reset_done_quirk) | ||
| 1604 | ddata->reset_done_quirk(ddata); | ||
| 1321 | 1605 | ||
| 1322 | return readl_poll_timeout(ddata->module_va + offset, val, | 1606 | return error; |
| 1323 | (val & ddata->cfg.syss_mask) == 0x0, | ||
| 1324 | 100, MAX_MODULE_SOFTRESET_WAIT); | ||
| 1325 | } | 1607 | } |
| 1326 | 1608 | ||
| 1327 | /* | 1609 | /* |
| @@ -1334,12 +1616,8 @@ static int sysc_init_module(struct sysc *ddata) · 6 unmodified lines | |||
| 1334 | { | 1616 | { |
| 1335 | int error = 0; | 1617 | int error = 0; |
| 1336 | bool manage_clocks = true; | 1618 | bool manage_clocks = true; |
| 1337 | bool reset = true; | ||
| 1338 | |||
| 1339 | if (ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT) | ||
| 1340 | reset = false; | ||
| 1341 | 1619 | ||
| 1342 | error = sysc_rstctrl_reset_deassert(ddata, reset); | 1620 | error = sysc_rstctrl_reset_deassert(ddata, false); |
| 1343 | if (error) | 1621 | if (error) |
| 1344 | return error; | 1622 | return error; |
| 1345 | 1623 | ||
| @@ -1347,7 +1625,13 @@ static int sysc_init_module(struct sysc *ddata) · 1 unmodified line | |||
| 1347 | (SYSC_QUIRK_NO_IDLE | SYSC_QUIRK_NO_IDLE_ON_INIT)) | 1625 | (SYSC_QUIRK_NO_IDLE | SYSC_QUIRK_NO_IDLE_ON_INIT)) |
| 1348 | manage_clocks = false; | 1626 | manage_clocks = false; |
| 1349 | 1627 | ||
| 1628 | error = sysc_clockdomain_init(ddata); | ||
| 1629 | if (error) | ||
| 1630 | return error; | ||
| 1631 | |||
| 1350 | if (manage_clocks) { | 1632 | if (manage_clocks) { |
| 1633 | sysc_clkdm_deny_idle(ddata); | ||
| 1634 | |||
| 1351 | error = sysc_enable_opt_clocks(ddata); | 1635 | error = sysc_enable_opt_clocks(ddata); |
| 1352 | if (error) | 1636 | if (error) |
| 1353 | return error; | 1637 | return error; |
| @@ -1357,23 +1641,43 @@ static int sysc_init_module(struct sysc *ddata) · 3 unmodified lines | |||
| 1357 | goto err_opt_clocks; | 1641 | goto err_opt_clocks; |
| 1358 | } | 1642 | } |
| 1359 | 1643 | ||
| 1644 | if (!(ddata->cfg.quirks & SYSC_QUIRK_NO_RESET_ON_INIT)) { | ||
| 1645 | error = sysc_rstctrl_reset_deassert(ddata, true); | ||
| 1646 | if (error) | ||
| 1647 | goto err_main_clocks; | ||
| 1648 | } | ||
| 1649 | |||
| 1360 | ddata->revision = sysc_read_revision(ddata); | 1650 | ddata->revision = sysc_read_revision(ddata); |
| 1361 | sysc_init_revision_quirks(ddata); | 1651 | sysc_init_revision_quirks(ddata); |
| 1652 | sysc_init_module_quirks(ddata); | ||
| 1362 | 1653 | ||
| 1363 | error = sysc_legacy_init(ddata); | 1654 | if (ddata->legacy_mode) { |
| 1364 | if (error) | 1655 | error = sysc_legacy_init(ddata); |
| 1365 | goto err_main_clocks; | 1656 | if (error) |
| 1657 | goto err_main_clocks; | ||
| 1658 | } | ||
| 1659 | |||
| 1660 | if (!ddata->legacy_mode && manage_clocks) { | ||
| 1661 | error = sysc_enable_module(ddata->dev); | ||
| 1662 | if (error) | ||
| 1663 | goto err_main_clocks; | ||
| 1664 | } | ||
| 1366 | 1665 | ||
| 1367 | error = sysc_reset(ddata); | 1666 | error = sysc_reset(ddata); |
| 1368 | if (error) | 1667 | if (error) |
| 1369 | dev_err(ddata->dev, "Reset failed with %d\n", error); | 1668 | dev_err(ddata->dev, "Reset failed with %d\n", error); |
| 1370 | 1669 | ||
| 1670 | if (!ddata->legacy_mode && manage_clocks) | ||
| 1671 | sysc_disable_module(ddata->dev); | ||
| 1672 | |||
| 1371 | err_main_clocks: | 1673 | err_main_clocks: |
| 1372 | if (manage_clocks) | 1674 | if (manage_clocks) |
| 1373 | sysc_disable_main_clocks(ddata); | 1675 | sysc_disable_main_clocks(ddata); |
| 1374 | err_opt_clocks: | 1676 | err_opt_clocks: |
| 1375 | if (manage_clocks) | 1677 | if (manage_clocks) { |
| 1376 | sysc_disable_opt_clocks(ddata); | 1678 | sysc_disable_opt_clocks(ddata); |
| 1679 | sysc_clkdm_allow_idle(ddata); | ||
| 1680 | } | ||
| 1377 | 1681 | ||
| 1378 | return error; | 1682 | return error; |
| 1379 | } | 1683 | } |
| @@ -1663,9 +1967,6 @@ static struct dev_pm_domain sysc_child_pm_domain = { · 283 unmodified lines | |||
| 1663 | */ | 1967 | */ |
| 1664 | static void sysc_legacy_idle_quirk(struct sysc *ddata, struct device *child) | 1968 | static void sysc_legacy_idle_quirk(struct sysc *ddata, struct device *child) |
| 1665 | { | 1969 | { |
| 1666 | if (!ddata->legacy_mode) | ||
| 1667 | return; | ||
| 1668 | |||
| 1669 | if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE) | 1970 | if (ddata->cfg.quirks & SYSC_QUIRK_LEGACY_IDLE) |
| 1670 | dev_pm_domain_set(child, &sysc_child_pm_domain); | 1971 | dev_pm_domain_set(child, &sysc_child_pm_domain); |
| 1671 | } | 1972 | } |
| @@ -2005,6 +2306,7 @@ static const struct sysc_capabilities sysc_dra7_mcan = { · 333 unmodified lines | |||
| 2005 | .type = TI_SYSC_DRA7_MCAN, | 2306 | .type = TI_SYSC_DRA7_MCAN, |
| 2006 | .sysc_mask = SYSC_DRA7_MCAN_ENAWAKEUP | SYSC_OMAP4_SOFTRESET, | 2307 | .sysc_mask = SYSC_DRA7_MCAN_ENAWAKEUP | SYSC_OMAP4_SOFTRESET, |
| 2007 | .regbits = &sysc_regbits_dra7_mcan, | 2308 | .regbits = &sysc_regbits_dra7_mcan, |
| 2309 | .mod_quirks = SYSS_QUIRK_RESETDONE_INVERTED, | ||
| 2008 | }; | 2310 | }; |
| 2009 | 2311 | ||
| 2010 | static int sysc_init_pdata(struct sysc *ddata) | 2312 | static int sysc_init_pdata(struct sysc *ddata) |
| @@ -2012,20 +2314,22 @@ static int sysc_init_pdata(struct sysc *ddata) · 1 unmodified line | |||
| 2012 | struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev); | 2314 | struct ti_sysc_platform_data *pdata = dev_get_platdata(ddata->dev); |
| 2013 | struct ti_sysc_module_data *mdata; | 2315 | struct ti_sysc_module_data *mdata; |
| 2014 | 2316 | ||
| 2015 | if (!pdata || !ddata->legacy_mode) | 2317 | if (!pdata) |
| 2016 | return 0; | 2318 | return 0; |
| 2017 | 2319 | ||
| 2018 | mdata = devm_kzalloc(ddata->dev, sizeof(*mdata), GFP_KERNEL); | 2320 | mdata = devm_kzalloc(ddata->dev, sizeof(*mdata), GFP_KERNEL); |
| 2019 | if (!mdata) | 2321 | if (!mdata) |
| 2020 | return -ENOMEM; | 2322 | return -ENOMEM; |
| 2021 | 2323 | ||
| 2022 | mdata->name = ddata->legacy_mode; | 2324 | if (ddata->legacy_mode) { |
| 2023 | mdata->module_pa = ddata->module_pa; | 2325 | mdata->name = ddata->legacy_mode; |
| 2024 | mdata->module_size = ddata->module_size; | 2326 | mdata->module_pa = ddata->module_pa; |
| 2025 | mdata->offsets = ddata->offsets; | 2327 | mdata->module_size = ddata->module_size; |
| 2026 | mdata->nr_offsets = SYSC_MAX_REGS; | 2328 | mdata->offsets = ddata->offsets; |
| 2027 | mdata->cap = ddata->cap; | 2329 | mdata->nr_offsets = SYSC_MAX_REGS; |
| 2028 | mdata->cfg = &ddata->cfg; | 2330 | mdata->cap = ddata->cap; |
| 2331 | mdata->cfg = &ddata->cfg; | ||
| 2332 | } | ||
| 2029 | 2333 | ||
| 2030 | ddata->mdata = mdata; | 2334 | ddata->mdata = mdata; |
| 2031 | 2335 | ||
| @@ -2145,7 +2449,7 @@ static int sysc_probe(struct platform_device *pdev) · 113 unmodified lines | |||
| 2145 | } | 2449 | } |
| 2146 | 2450 | ||
| 2147 | if (!of_get_available_child_count(ddata->dev->of_node)) | 2451 | if (!of_get_available_child_count(ddata->dev->of_node)) |
| 2148 | reset_control_assert(ddata->rsts); | 2452 | ddata->disable_on_idle = true; |
| 2149 | 2453 | ||
| 2150 | return 0; | 2454 | return 0; |
| 2151 | 2455 | ||
| @@ -185,6 +185,8 @@ scmi_clock_describe_rates_get(const struct scmi_handle *handle, u32 clk_id, · 184 unmodified lines | |||
| 185 | if (rate_discrete) | 185 | if (rate_discrete) |
| 186 | clk->list.num_rates = tot_rate_cnt; | 186 | clk->list.num_rates = tot_rate_cnt; |
| 187 | 187 | ||
| 188 | clk->rate_discrete = rate_discrete; | ||
| 189 | |||
| 188 | err: | 190 | err: |
| 189 | scmi_xfer_put(handle, t); | 191 | scmi_xfer_put(handle, t); |
| 190 | return ret; | 192 | return ret; |
| @@ -30,10 +30,12 @@ struct scmi_msg_resp_sensor_description { · 29 unmodified lines | |||
| 30 | __le32 id; | 30 | __le32 id; |
| 31 | __le32 attributes_low; | 31 | __le32 attributes_low; |
| 32 | #define SUPPORTS_ASYNC_READ(x) ((x) & BIT(31)) | 32 | #define SUPPORTS_ASYNC_READ(x) ((x) & BIT(31)) |
| 33 | #define NUM_TRIP_POINTS(x) (((x) >> 4) & 0xff) | 33 | #define NUM_TRIP_POINTS(x) ((x) & 0xff) |
| 34 | __le32 attributes_high; | 34 | __le32 attributes_high; |
| 35 | #define SENSOR_TYPE(x) ((x) & 0xff) | 35 | #define SENSOR_TYPE(x) ((x) & 0xff) |
| 36 | #define SENSOR_SCALE(x) (((x) >> 11) & 0x3f) | 36 | #define SENSOR_SCALE(x) (((x) >> 11) & 0x1f) |
| 37 | #define SENSOR_SCALE_SIGN BIT(4) | ||
| 38 | #define SENSOR_SCALE_EXTEND GENMASK(7, 5) | ||
| 37 | #define SENSOR_UPDATE_SCALE(x) (((x) >> 22) & 0x1f) | 39 | #define SENSOR_UPDATE_SCALE(x) (((x) >> 22) & 0x1f) |
| 38 | #define SENSOR_UPDATE_BASE(x) (((x) >> 27) & 0x1f) | 40 | #define SENSOR_UPDATE_BASE(x) (((x) >> 27) & 0x1f) |
| 39 | u8 name[SCMI_MAX_STR_SIZE]; | 41 | u8 name[SCMI_MAX_STR_SIZE]; |
| @@ -140,6 +142,10 @@ static int scmi_sensor_description_get(const struct scmi_handle *handle, · 100 unmodified lines | |||
| 140 | s = &si->sensors[desc_index + cnt]; | 142 | s = &si->sensors[desc_index + cnt]; |
| 141 | s->id = le32_to_cpu(buf->desc[cnt].id); | 143 | s->id = le32_to_cpu(buf->desc[cnt].id); |
| 142 | s->type = SENSOR_TYPE(attrh); | 144 | s->type = SENSOR_TYPE(attrh); |
| 145 | s->scale = SENSOR_SCALE(attrh); | ||
| 146 | /* Sign extend to a full s8 */ | ||
| 147 | if (s->scale & SENSOR_SCALE_SIGN) | ||
| 148 | s->scale |= SENSOR_SCALE_EXTEND; | ||
| 143 | strlcpy(s->name, buf->desc[cnt].name, SCMI_MAX_STR_SIZE); | 149 | strlcpy(s->name, buf->desc[cnt].name, SCMI_MAX_STR_SIZE); |
| 144 | } | 150 | } |
| 145 | 151 | ||
| @@ -359,16 +359,16 @@ static int suspend_test_thread(void *arg) · 358 unmodified lines | |||
| 359 | for (;;) { | 359 | for (;;) { |
| 360 | /* Needs to be set first to avoid missing a wakeup. */ | 360 | /* Needs to be set first to avoid missing a wakeup. */ |
| 361 | set_current_state(TASK_INTERRUPTIBLE); | 361 | set_current_state(TASK_INTERRUPTIBLE); |
| 362 | if (kthread_should_stop()) { | 362 | if (kthread_should_park()) |
| 363 | __set_current_state(TASK_RUNNING); | ||
| 364 | break; | 363 | break; |
| 365 | } | ||
| 366 | schedule(); | 364 | schedule(); |
| 367 | } | 365 | } |
| 368 | 366 | ||
| 369 | pr_info("CPU %d suspend test results: success %d, shallow states %d, errors %d\n", | 367 | pr_info("CPU %d suspend test results: success %d, shallow states %d, errors %d\n", |
| 370 | cpu, nb_suspend, nb_shallow_sleep, nb_err); | 368 | cpu, nb_suspend, nb_shallow_sleep, nb_err); |
| 371 | 369 | ||
| 370 | kthread_parkme(); | ||
| 371 | |||
| 372 | return nb_err; | 372 | return nb_err; |
| 373 | } | 373 | } |
| 374 | 374 | ||
| @@ -433,8 +433,10 @@ static int suspend_tests(void) · 58 unmodified lines | |||
| 433 | 433 | ||
| 434 | 434 | ||
| 435 | /* Stop and destroy all threads, get return status. */ | 435 | /* Stop and destroy all threads, get return status. */ |
| 436 | for (i = 0; i < nb_threads; ++i) | 436 | for (i = 0; i < nb_threads; ++i) { |
| 437 | err += kthread_park(threads[i]); | ||
| 437 | err += kthread_stop(threads[i]); | 438 | err += kthread_stop(threads[i]); |
| 439 | } | ||
| 438 | out: | 440 | out: |
| 439 | cpuidle_resume_and_unlock(); | 441 | cpuidle_resume_and_unlock(); |
| 440 | kfree(threads); | 442 | kfree(threads); |
| @@ -803,7 +803,9 @@ static int __maybe_unused tegra_bpmp_resume(struct device *dev) · 802 unmodified lines | |||
| 803 | return 0; | 803 | return 0; |
| 804 | } | 804 | } |
| 805 | 805 | ||
| 806 | static SIMPLE_DEV_PM_OPS(tegra_bpmp_pm_ops, NULL, tegra_bpmp_resume); | 806 | static const struct dev_pm_ops tegra_bpmp_pm_ops = { |
| 807 | .resume_early = tegra_bpmp_resume, | ||
| 808 | }; | ||
| 807 | 809 | ||
| 808 | #if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \ | 810 | #if IS_ENABLED(CONFIG_ARCH_TEGRA_186_SOC) || \ |
| 809 | IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) | 811 | IS_ENABLED(CONFIG_ARCH_TEGRA_194_SOC) |
| @@ -466,9 +466,9 @@ static int ti_sci_cmd_get_revision(struct ti_sci_info *info) · 465 unmodified lines | |||
| 466 | struct ti_sci_xfer *xfer; | 466 | struct ti_sci_xfer *xfer; |
| 467 | int ret; | 467 | int ret; |
| 468 | 468 | ||
| 469 | /* No need to setup flags since it is expected to respond */ | ||
| 470 | xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_VERSION, | 469 | xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_VERSION, |
| 471 | 0x0, sizeof(struct ti_sci_msg_hdr), | 470 | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, |
| 471 | sizeof(struct ti_sci_msg_hdr), | ||
| 472 | sizeof(*rev_info)); | 472 | sizeof(*rev_info)); |
| 473 | if (IS_ERR(xfer)) { | 473 | if (IS_ERR(xfer)) { |
| 474 | ret = PTR_ERR(xfer); | 474 | ret = PTR_ERR(xfer); |
| @@ -596,9 +596,9 @@ static int ti_sci_get_device_state(const struct ti_sci_handle *handle, · 121 unmodified lines | |||
| 596 | info = handle_to_ti_sci_info(handle); | 596 | info = handle_to_ti_sci_info(handle); |
| 597 | dev = info->dev; | 597 | dev = info->dev; |
| 598 | 598 | ||
| 599 | /* Response is expected, so need of any flags */ | ||
| 600 | xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_DEVICE_STATE, | 599 | xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_DEVICE_STATE, |
| 601 | 0, sizeof(*req), sizeof(*resp)); | 600 | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, |
| 601 | sizeof(*req), sizeof(*resp)); | ||
| 602 | if (IS_ERR(xfer)) { | 602 | if (IS_ERR(xfer)) { |
| 603 | ret = PTR_ERR(xfer); | 603 | ret = PTR_ERR(xfer); |
| 604 | dev_err(dev, "Message alloc failed(%d)\n", ret); | 604 | dev_err(dev, "Message alloc failed(%d)\n", ret); |
| @@ -2057,122 +2057,175 @@ static int ti_sci_cmd_free_event_map(const struct ti_sci_handle *handle, · 1452 unmodified lines | |||
| 2057 | ia_id, vint, global_event, vint_status_bit, 0); | 2057 | ia_id, vint, global_event, vint_status_bit, 0); |
| 2058 | } | 2058 | } |
| 2059 | 2059 | ||
| 2060 | /* | 2060 | /** |
| 2061 | * ti_sci_setup_ops() - Setup the operations structures | 2061 | * ti_sci_cmd_ring_config() - configure RA ring |
| 2062 | * @info: pointer to TISCI pointer | 2062 | * @handle: Pointer to TI SCI handle. |
| 2063 | * @valid_params: Bitfield defining validity of ring configuration | ||
| 2064 | * parameters | ||
| 2065 | * @nav_id: Device ID of Navigator Subsystem from which the ring is | ||
| 2066 | * allocated | ||
| 2067 | * @index: Ring index | ||
| 2068 | * @addr_lo: The ring base address lo 32 bits | ||
| 2069 | * @addr_hi: The ring base address hi 32 bits | ||
| 2070 | * @count: Number of ring elements | ||
| 2071 | * @mode: The mode of the ring | ||
| 2072 | * @size: The ring element size. | ||
| 2073 | * @order_id: Specifies the ring's bus order ID | ||
| 2074 | * | ||
| 2075 | * Return: 0 if all went well, else returns appropriate error value. | ||
| 2076 | * | ||
| 2077 | * See @ti_sci_msg_rm_ring_cfg_req for more info. | ||
| 2063 | */ | 2078 | */ |
| 2064 | static void ti_sci_setup_ops(struct ti_sci_info *info) | 2079 | static int ti_sci_cmd_ring_config(const struct ti_sci_handle *handle, |
| 2080 | u32 valid_params, u16 nav_id, u16 index, | ||
| 2081 | u32 addr_lo, u32 addr_hi, u32 count, | ||
| 2082 | u8 mode, u8 size, u8 order_id) | ||
| 2065 | { | 2083 | { |
| 2066 | struct ti_sci_ops *ops = &info->handle.ops; | 2084 | struct ti_sci_msg_rm_ring_cfg_req *req; |
| 2067 | struct ti_sci_core_ops *core_ops = &ops->core_ops; | 2085 | struct ti_sci_msg_hdr *resp; |
| 2068 | struct ti_sci_dev_ops *dops = &ops->dev_ops; | 2086 | struct ti_sci_xfer *xfer; |
| 2069 | struct ti_sci_clk_ops *cops = &ops->clk_ops; | 2087 | struct ti_sci_info *info; |
| 2070 | struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops; | 2088 | struct device *dev; |
| 2071 | struct ti_sci_rm_irq_ops *iops = &ops->rm_irq_ops; | 2089 | int ret = 0; |
| 2072 | |||
| 2073 | core_ops->reboot_device = ti_sci_cmd_core_reboot; | ||
| 2074 | |||
| 2075 | dops->get_device = ti_sci_cmd_get_device; | ||
| 2076 | dops->idle_device = ti_sci_cmd_idle_device; | ||
| 2077 | dops->put_device = ti_sci_cmd_put_device; | ||
| 2078 | 2090 | ||
| 2079 | dops->is_valid = ti_sci_cmd_dev_is_valid; | 2091 | if (IS_ERR_OR_NULL(handle)) |
| 2080 | dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt; | 2092 | return -EINVAL; |
| 2081 | dops->is_idle = ti_sci_cmd_dev_is_idle; | ||
| 2082 | dops->is_stop = ti_sci_cmd_dev_is_stop; | ||
| 2083 | dops->is_on = ti_sci_cmd_dev_is_on; | ||
| 2084 | dops->is_transitioning = ti_sci_cmd_dev_is_trans; | ||
| 2085 | dops->set_device_resets = ti_sci_cmd_set_device_resets; | ||
| 2086 | dops->get_device_resets = ti_sci_cmd_get_device_resets; | ||
| 2087 | 2093 | ||
| 2088 | cops->get_clock = ti_sci_cmd_get_clock; | 2094 | info = handle_to_ti_sci_info(handle); |
| 2089 | cops->idle_clock = ti_sci_cmd_idle_clock; | 2095 | dev = info->dev; |
| 2090 | cops->put_clock = ti_sci_cmd_put_clock; | ||
| 2091 | cops->is_auto = ti_sci_cmd_clk_is_auto; | ||
| 2092 | cops->is_on = ti_sci_cmd_clk_is_on; | ||
| 2093 | cops->is_off = ti_sci_cmd_clk_is_off; | ||
| 2094 | 2096 | ||
| 2095 | cops->set_parent = ti_sci_cmd_clk_set_parent; | 2097 | xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_RM_RING_CFG, |
| 2096 | cops->get_parent = ti_sci_cmd_clk_get_parent; | 2098 | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, |
| 2097 | cops->get_num_parents = ti_sci_cmd_clk_get_num_parents; | 2099 | sizeof(*req), sizeof(*resp)); |
| 2100 | if (IS_ERR(xfer)) { | ||
| 2101 | ret = PTR_ERR(xfer); | ||
| 2102 | dev_err(dev, "RM_RA:Message config failed(%d)\n", ret); | ||
| 2103 | return ret; | ||
| 2104 | } | ||
| 2105 | req = (struct ti_sci_msg_rm_ring_cfg_req *)xfer->xfer_buf; | ||
| 2106 | req->valid_params = valid_params; | ||
| 2107 | req->nav_id = nav_id; | ||
| 2108 | req->index = index; | ||
| 2109 | req->addr_lo = addr_lo; | ||
| 2110 | req->addr_hi = addr_hi; | ||
| 2111 | req->count = count; | ||
| 2112 | req->mode = mode; | ||
| 2113 | req->size = size; | ||
| 2114 | req->order_id = order_id; | ||
| 2098 | 2115 | ||
| 2099 | cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq; | 2116 | ret = ti_sci_do_xfer(info, xfer); |
| 2100 | cops->set_freq = ti_sci_cmd_clk_set_freq; | 2117 | if (ret) { |
| 2101 | cops->get_freq = ti_sci_cmd_clk_get_freq; | 2118 | dev_err(dev, "RM_RA:Mbox config send fail %d\n", ret); |
| 2119 | goto fail; | ||
| 2120 | } | ||
| 2102 | 2121 | ||
| 2103 | rm_core_ops->get_range = ti_sci_cmd_get_resource_range; | 2122 | resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; |
| 2104 | rm_core_ops->get_range_from_shost = | 2123 | ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; |
| 2105 | ti_sci_cmd_get_resource_range_from_shost; | ||
| 2106 | 2124 | ||
| 2107 | iops->set_irq = ti_sci_cmd_set_irq; | 2125 | fail: |
| 2108 | iops->set_event_map = ti_sci_cmd_set_event_map; | 2126 | ti_sci_put_one_xfer(&info->minfo, xfer); |
| 2109 | iops->free_irq = ti_sci_cmd_free_irq; | 2127 | dev_dbg(dev, "RM_RA:config ring %u ret:%d\n", index, ret); |
| 2110 | iops->free_event_map = ti_sci_cmd_free_event_map; | 2128 | return ret; |
| 2111 | } | 2129 | } |
| 2112 | 2130 | ||
| 2113 | /** | 2131 | /** |
| 2114 | * ti_sci_get_handle() - Get the TI SCI handle for a device | 2132 | * ti_sci_cmd_ring_get_config() - get RA ring configuration |
| 2115 | * @dev: Pointer to device for which we want SCI handle | 2133 | * @handle: Pointer to TI SCI handle. |
| 2134 | * @nav_id: Device ID of Navigator Subsystem from which the ring is | ||
| 2135 | * allocated | ||
| 2136 | * @index: Ring index | ||
| 2137 | * @addr_lo: Returns ring's base address lo 32 bits | ||
| 2138 | * @addr_hi: Returns ring's base address hi 32 bits | ||
| 2139 | * @count: Returns number of ring elements | ||
| 2140 | * @mode: Returns mode of the ring | ||
| 2141 | * @size: Returns ring element size | ||
| 2142 | * @order_id: Returns ring's bus order ID | ||
| 2116 | * | 2143 | * |
| 2117 | * NOTE: The function does not track individual clients of the framework | 2144 | * Return: 0 if all went well, else returns appropriate error value. |
| 2118 | * and is expected to be maintained by caller of TI SCI protocol library. | 2145 | * |
| 2119 | * ti_sci_put_handle must be balanced with successful ti_sci_get_handle | 2146 | * See @ti_sci_msg_rm_ring_get_cfg_req for more info. |
| 2120 | * Return: pointer to handle if successful, else: | ||
| 2121 | * -EPROBE_DEFER if the instance is not ready | ||
| 2122 | * -ENODEV if the required node handler is missing | ||
| 2123 | * -EINVAL if invalid conditions are encountered. | ||
| 2124 | */ | 2147 | */ |
| 2125 | const struct ti_sci_handle *ti_sci_get_handle(struct device *dev) | 2148 | static int ti_sci_cmd_ring_get_config(const struct ti_sci_handle *handle, |
| 2149 | u32 nav_id, u32 index, u8 *mode, | ||
| 2150 | u32 *addr_lo, u32 *addr_hi, | ||
| 2151 | u32 *count, u8 *size, u8 *order_id) | ||
| 2126 | { | 2152 | { |
| 2127 | struct device_node *ti_sci_np; | 2153 | struct ti_sci_msg_rm_ring_get_cfg_resp *resp; |
| 2128 | struct list_head *p; | 2154 | struct ti_sci_msg_rm_ring_get_cfg_req *req; |
| 2129 | struct ti_sci_handle *handle = NULL; | 2155 | struct ti_sci_xfer *xfer; |
| 2130 | struct ti_sci_info *info; | 2156 | struct ti_sci_info *info; |
| 2157 | struct device *dev; | ||
| 2158 | int ret = 0; | ||
| 2131 | 2159 | ||
| 2132 | if (!dev) { | 2160 | if (IS_ERR_OR_NULL(handle)) |
| 2133 | pr_err("I need a device pointer\n"); | 2161 | return -EINVAL; |
| 2134 | return ERR_PTR(-EINVAL); | 2162 | |
| 2135 | } | 2163 | info = handle_to_ti_sci_info(handle); |
| 2136 | ti_sci_np = of_get_parent(dev->of_node); | 2164 | dev = info->dev; |
| 2137 | if (!ti_sci_np) { | 2165 | |
| 2138 | dev_err(dev, "No OF information\n"); | 2166 | xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_RM_RING_GET_CFG, |
| 2139 | return ERR_PTR(-EINVAL); | 2167 | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, |
| 2168 | sizeof(*req), sizeof(*resp)); | ||
| 2169 | if (IS_ERR(xfer)) { | ||
| 2170 | ret = PTR_ERR(xfer); | ||
| 2171 | dev_err(dev, | ||
| 2172 | "RM_RA:Message get config failed(%d)\n", ret); | ||
| 2173 | return ret; | ||
| 2140 | } | 2174 | } |
| 2175 | req = (struct ti_sci_msg_rm_ring_get_cfg_req *)xfer->xfer_buf; | ||
| 2176 | req->nav_id = nav_id; | ||
| 2177 | req->index = index; | ||
| 2141 | 2178 | ||
| 2142 | mutex_lock(&ti_sci_list_mutex); | 2179 | ret = ti_sci_do_xfer(info, xfer); |
| 2143 | list_for_each(p, &ti_sci_list) { | 2180 | if (ret) { |
| 2144 | info = list_entry(p, struct ti_sci_info, node); | 2181 | dev_err(dev, "RM_RA:Mbox get config send fail %d\n", ret); |
| 2145 | if (ti_sci_np == info->dev->of_node) { | 2182 | goto fail; |
| 2146 | handle = &info->handle; | ||
| 2147 | info->users++; | ||
| 2148 | break; | ||
| 2149 | } | ||
| 2150 | } | 2183 | } |
| 2151 | mutex_unlock(&ti_sci_list_mutex); | ||
| 2152 | of_node_put(ti_sci_np); | ||
| 2153 | 2184 | ||
| 2154 | if (!handle) | 2185 | resp = (struct ti_sci_msg_rm_ring_get_cfg_resp *)xfer->xfer_buf; |
| 2155 | return ERR_PTR(-EPROBE_DEFER); | ||
| 2156 | 2186 | ||
| 2157 | return handle; | 2187 | if (!ti_sci_is_response_ack(resp)) { |
| 2188 | ret = -ENODEV; | ||
| 2189 | } else { | ||
| 2190 | if (mode) | ||
| 2191 | *mode = resp->mode; | ||
| 2192 | if (addr_lo) | ||
| 2193 | *addr_lo = resp->addr_lo; | ||
| 2194 | if (addr_hi) | ||
| 2195 | *addr_hi = resp->addr_hi; | ||
| 2196 | if (count) | ||
| 2197 | *count = resp->count; | ||
| 2198 | if (size) | ||
| 2199 | *size = resp->size; | ||
| 2200 | if (order_id) | ||
| 2201 | *order_id = resp->order_id; | ||
| 2202 | }; | ||
| 2203 | |||
| 2204 | fail: | ||
| 2205 | ti_sci_put_one_xfer(&info->minfo, xfer); | ||
| 2206 | dev_dbg(dev, "RM_RA:get config ring %u ret:%d\n", index, ret); | ||
| 2207 | return ret; | ||
| 2158 | } | 2208 | } |
| 2159 | EXPORT_SYMBOL_GPL(ti_sci_get_handle); | ||
| 2160 | 2209 | ||
| 2161 | /** | 2210 | /** |
| 2162 | * ti_sci_put_handle() - Release the handle acquired by ti_sci_get_handle | 2211 | * ti_sci_cmd_rm_psil_pair() - Pair PSI-L source to destination thread |
| 2163 | * @handle: Handle acquired by ti_sci_get_handle | 2212 | * @handle: Pointer to TI SCI handle. |
| 2164 | * | 2213 | * @nav_id: Device ID of Navigator Subsystem which should be used for |
| 2165 | * NOTE: The function does not track individual clients of the framework | 2214 | * pairing |
| 2166 | * and is expected to be maintained by caller of TI SCI protocol library. | 2215 | * @src_thread: Source PSI-L thread ID |
| 2167 | * ti_sci_put_handle must be balanced with successful ti_sci_get_handle | 2216 | * @dst_thread: Destination PSI-L thread ID |
| 2168 | * | 2217 | * |
| 2169 | * Return: 0 is successfully released | 2218 | * Return: 0 if all went well, else returns appropriate error value. |
| 2170 | * if an error pointer was passed, it returns the error value back, | ||
| 2171 | * if null was passed, it returns -EINVAL; | ||
| 2172 | */ | 2219 | */ |
| 2173 | int ti_sci_put_handle(const struct ti_sci_handle *handle) | 2220 | static int ti_sci_cmd_rm_psil_pair(const struct ti_sci_handle *handle, |
| 2221 | u32 nav_id, u32 src_thread, u32 dst_thread) | ||
| 2174 | { | 2222 | { |
| 2223 | struct ti_sci_msg_psil_pair *req; | ||
| 2224 | struct ti_sci_msg_hdr *resp; | ||
| 2225 | struct ti_sci_xfer *xfer; | ||
| 2175 | struct ti_sci_info *info; | 2226 | struct ti_sci_info *info; |
| 2227 | struct device *dev; | ||
| 2228 | int ret = 0; | ||
| 2176 | 2229 | ||
| 2177 | if (IS_ERR(handle)) | 2230 | if (IS_ERR(handle)) |
| 2178 | return PTR_ERR(handle); | 2231 | return PTR_ERR(handle); |
| @@ -2180,81 +2233,866 @@ int ti_sci_put_handle(const struct ti_sci_handle *handle) · 1 unmodified line | |||
| 2180 | return -EINVAL; | 2233 | return -EINVAL; |
| 2181 | 2234 | ||
| 2182 | info = handle_to_ti_sci_info(handle); | 2235 | info = handle_to_ti_sci_info(handle); |
| 2183 | mutex_lock(&ti_sci_list_mutex); | 2236 | dev = info->dev; |
| 2184 | if (!WARN_ON(!info->users)) | ||
| 2185 | info->users--; | ||
| 2186 | mutex_unlock(&ti_sci_list_mutex); | ||
| 2187 | 2237 | ||
| 2188 | return 0; | 2238 | xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_RM_PSIL_PAIR, |
| 2189 | } | 2239 | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, |
| 2190 | EXPORT_SYMBOL_GPL(ti_sci_put_handle); | 2240 | sizeof(*req), sizeof(*resp)); |
| 2241 | if (IS_ERR(xfer)) { | ||
| 2242 | ret = PTR_ERR(xfer); | ||
| 2243 | dev_err(dev, "RM_PSIL:Message reconfig failed(%d)\n", ret); | ||
| 2244 | return ret; | ||
| 2245 | } | ||
| 2246 | req = (struct ti_sci_msg_psil_pair *)xfer->xfer_buf; | ||
| 2247 | req->nav_id = nav_id; | ||
| 2248 | req->src_thread = src_thread; | ||
| 2249 | req->dst_thread = dst_thread; | ||
| 2191 | 2250 | ||
| 2192 | static void devm_ti_sci_release(struct device *dev, void *res) | 2251 | ret = ti_sci_do_xfer(info, xfer); |
| 2193 | { | 2252 | if (ret) { |
| 2194 | const struct ti_sci_handle **ptr = res; | 2253 | dev_err(dev, "RM_PSIL:Mbox send fail %d\n", ret); |
| 2195 | const struct ti_sci_handle *handle = *ptr; | 2254 | goto fail; |
| 2196 | int ret; | 2255 | } |
| 2197 | 2256 | ||
| 2198 | ret = ti_sci_put_handle(handle); | 2257 | resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; |
| 2199 | if (ret) | 2258 | ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL; |
| 2200 | dev_err(dev, "failed to put handle %d\n", ret); | 2259 | |
| 2260 | fail: | ||
| 2261 | ti_sci_put_one_xfer(&info->minfo, xfer); | ||
| 2262 | |||
| 2263 | return ret; | ||
| 2201 | } | 2264 | } |
| 2202 | 2265 | ||
| 2203 | /** | 2266 | /** |
| 2204 | * devm_ti_sci_get_handle() - Managed get handle | 2267 | * ti_sci_cmd_rm_psil_unpair() - Unpair PSI-L source from destination thread |
| 2205 | * @dev: device for which we want SCI handle for. | 2268 | * @handle: Pointer to TI SCI handle. |
| 2269 | * @nav_id: Device ID of Navigator Subsystem which should be used for | ||
| 2270 | * unpairing | ||
| 2271 | * @src_thread: Source PSI-L thread ID | ||
| 2272 | * @dst_thread: Destination PSI-L thread ID | ||
| 2206 | * | 2273 | * |
| 2207 | * NOTE: This releases the handle once the device resources are | 2274 | * Return: 0 if all went well, else returns appropriate error value. |
| 2208 | * no longer needed. MUST NOT BE released with ti_sci_put_handle. | ||
| 2209 | * The function does not track individual clients of the framework | ||
| 2210 | * and is expected to be maintained by caller of TI SCI protocol library. | ||
| 2211 | * | ||
| 2212 | * Return: 0 if all went fine, else corresponding error. | ||
| 2213 | */ | 2275 | */ |
| 2214 | const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev) | 2276 | static int ti_sci_cmd_rm_psil_unpair(const struct ti_sci_handle *handle, |
| 2277 | u32 nav_id, u32 src_thread, u32 dst_thread) | ||
| 2215 | { | 2278 | { |
| 2216 | const struct ti_sci_handle **ptr; | 2279 | struct ti_sci_msg_psil_unpair *req; |
| 2217 | const struct ti_sci_handle *handle; | 2280 | struct ti_sci_msg_hdr *resp; |
| 2281 | struct ti_sci_xfer *xfer; | ||
| 2282 | struct ti_sci_info *info; | ||
| 2283 | struct device *dev; | ||
| 2284 | int ret = 0; | ||
| 2218 | 2285 | ||
| 2219 | ptr = devres_alloc(devm_ti_sci_release, sizeof(*ptr), GFP_KERNEL); | 2286 | if (IS_ERR(handle)) |
| 2220 | if (!ptr) | 2287 | return PTR_ERR(handle); |
| 2221 | return ERR_PTR(-ENOMEM); | 2288 | if (!handle) |
| 2222 | handle = ti_sci_get_handle(dev); | 2289 | return -EINVAL; |
| 2223 | 2290 | ||
| 2224 | if (!IS_ERR(handle)) { | 2291 | info = handle_to_ti_sci_info(handle); |
| 2225 | *ptr = handle; | 2292 | dev = info->dev; |
| 2226 | devres_add(dev, ptr); | 2293 | |
| 2227 | } else { | 2294 | xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_RM_PSIL_UNPAIR, |
| 2228 | devres_free(ptr); | 2295 | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, |
| 2296 | sizeof(*req), sizeof(*resp)); | ||
| 2297 | if (IS_ERR(xfer)) { | ||
| 2298 | ret = PTR_ERR(xfer); | ||
| 2299 | dev_err(dev, "RM_PSIL:Message reconfig failed(%d)\n", ret); | ||
| 2300 | return ret; | ||
| 2229 | } | 2301 | } |
| 2302 | req = (struct ti_sci_msg_psil_unpair *)xfer->xfer_buf; | ||
| 2303 | req->nav_id = nav_id; | ||
| 2304 | req->src_thread = src_thread; | ||
| 2305 | req->dst_thread = dst_thread; | ||
| 2230 | 2306 | ||
| 2231 | return handle; | 2307 | ret = ti_sci_do_xfer(info, xfer); |
| 2308 | if (ret) { | ||
| 2309 | dev_err(dev, "RM_PSIL:Mbox send fail %d\n", ret); | ||
| 2310 | goto fail; | ||
| 2311 | } | ||
| 2312 | |||
| 2313 | resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; | ||
| 2314 | ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL; | ||
| 2315 | |||
| 2316 | fail: | ||
| 2317 | ti_sci_put_one_xfer(&info->minfo, xfer); | ||
| 2318 | |||
| 2319 | return ret; | ||
| 2232 | } | 2320 | } |
| 2233 | EXPORT_SYMBOL_GPL(devm_ti_sci_get_handle); | ||
| 2234 | 2321 | ||
| 2235 | /** | 2322 | /** |
| 2236 | * ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle | 2323 | * ti_sci_cmd_rm_udmap_tx_ch_cfg() - Configure a UDMAP TX channel |
| 2237 | * @np: device node | 2324 | * @handle: Pointer to TI SCI handle. |
| 2238 | * @property: property name containing phandle on TISCI node | 2325 | * @params: Pointer to ti_sci_msg_rm_udmap_tx_ch_cfg TX channel config |
| 2326 | * structure | ||
| 2239 | * | 2327 | * |
| 2240 | * NOTE: The function does not track individual clients of the framework | 2328 | * Return: 0 if all went well, else returns appropriate error value. |
| 2241 | * and is expected to be maintained by caller of TI SCI protocol library. | 2329 | * |
| 2242 | * ti_sci_put_handle must be balanced with successful ti_sci_get_by_phandle | 2330 | * See @ti_sci_msg_rm_udmap_tx_ch_cfg and @ti_sci_msg_rm_udmap_tx_ch_cfg_req for |
| 2243 | * Return: pointer to handle if successful, else: | 2331 | * more info. |
| 2244 | * -EPROBE_DEFER if the instance is not ready | ||
| 2245 | * -ENODEV if the required node handler is missing | ||
| 2246 | * -EINVAL if invalid conditions are encountered. | ||
| 2247 | */ | 2332 | */ |
| 2248 | const struct ti_sci_handle *ti_sci_get_by_phandle(struct device_node *np, | 2333 | static int ti_sci_cmd_rm_udmap_tx_ch_cfg(const struct ti_sci_handle *handle, |
| 2249 | const char *property) | 2334 | const struct ti_sci_msg_rm_udmap_tx_ch_cfg *params) |
| 2250 | { | 2335 | { |
| 2251 | struct ti_sci_handle *handle = NULL; | 2336 | struct ti_sci_msg_rm_udmap_tx_ch_cfg_req *req; |
| 2252 | struct device_node *ti_sci_np; | 2337 | struct ti_sci_msg_hdr *resp; |
| 2338 | struct ti_sci_xfer *xfer; | ||
| 2253 | struct ti_sci_info *info; | 2339 | struct ti_sci_info *info; |
| 2254 | struct list_head *p; | 2340 | struct device *dev; |
| 2341 | int ret = 0; | ||
| 2255 | 2342 | ||
| 2256 | if (!np) { | 2343 | if (IS_ERR_OR_NULL(handle)) |
| 2257 | pr_err("I need a device pointer\n"); | 2344 | return -EINVAL; |
| 2345 | |||
| 2346 | info = handle_to_ti_sci_info(handle); | ||
| 2347 | dev = info->dev; | ||
| 2348 | |||
| 2349 | xfer = ti_sci_get_one_xfer(info, TISCI_MSG_RM_UDMAP_TX_CH_CFG, | ||
| 2350 | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, | ||
| 2351 | sizeof(*req), sizeof(*resp)); | ||
| 2352 | if (IS_ERR(xfer)) { | ||
| 2353 | ret = PTR_ERR(xfer); | ||
| 2354 | dev_err(dev, "Message TX_CH_CFG alloc failed(%d)\n", ret); | ||
| 2355 | return ret; | ||
| 2356 | } | ||
| 2357 | req = (struct ti_sci_msg_rm_udmap_tx_ch_cfg_req *)xfer->xfer_buf; | ||
| 2358 | req->valid_params = params->valid_params; | ||
| 2359 | req->nav_id = params->nav_id; | ||
| 2360 | req->index = params->index; | ||
| 2361 | req->tx_pause_on_err = params->tx_pause_on_err; | ||
| 2362 | req->tx_filt_einfo = params->tx_filt_einfo; | ||
| 2363 | req->tx_filt_pswords = params->tx_filt_pswords; | ||
| 2364 | req->tx_atype = params->tx_atype; | ||
| 2365 | req->tx_chan_type = params->tx_chan_type; | ||
| 2366 | req->tx_supr_tdpkt = params->tx_supr_tdpkt; | ||
| 2367 | req->tx_fetch_size = params->tx_fetch_size; | ||
| 2368 | req->tx_credit_count = params->tx_credit_count; | ||
| 2369 | req->txcq_qnum = params->txcq_qnum; | ||
| 2370 | req->tx_priority = params->tx_priority; | ||
| 2371 | req->tx_qos = params->tx_qos; | ||
| 2372 | req->tx_orderid = params->tx_orderid; | ||
| 2373 | req->fdepth = params->fdepth; | ||
| 2374 | req->tx_sched_priority = params->tx_sched_priority; | ||
| 2375 | req->tx_burst_size = params->tx_burst_size; | ||
| 2376 | |||
| 2377 | ret = ti_sci_do_xfer(info, xfer); | ||
| 2378 | if (ret) { | ||
| 2379 | dev_err(dev, "Mbox send TX_CH_CFG fail %d\n", ret); | ||
| 2380 | goto fail; | ||
| 2381 | } | ||
| 2382 | |||
| 2383 | resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; | ||
| 2384 | ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL; | ||
| 2385 | |||
| 2386 | fail: | ||
| 2387 | ti_sci_put_one_xfer(&info->minfo, xfer); | ||
| 2388 | dev_dbg(dev, "TX_CH_CFG: chn %u ret:%u\n", params->index, ret); | ||
| 2389 | return ret; | ||
| 2390 | } | ||
| 2391 | |||
| 2392 | /** | ||
| 2393 | * ti_sci_cmd_rm_udmap_rx_ch_cfg() - Configure a UDMAP RX channel | ||
| 2394 | * @handle: Pointer to TI SCI handle. | ||
| 2395 | * @params: Pointer to ti_sci_msg_rm_udmap_rx_ch_cfg RX channel config | ||
| 2396 | * structure | ||
| 2397 | * | ||
| 2398 | * Return: 0 if all went well, else returns appropriate error value. | ||
| 2399 | * | ||
| 2400 | * See @ti_sci_msg_rm_udmap_rx_ch_cfg and @ti_sci_msg_rm_udmap_rx_ch_cfg_req for | ||
| 2401 | * more info. | ||
| 2402 | */ | ||
| 2403 | static int ti_sci_cmd_rm_udmap_rx_ch_cfg(const struct ti_sci_handle *handle, | ||
| 2404 | const struct ti_sci_msg_rm_udmap_rx_ch_cfg *params) | ||
| 2405 | { | ||
| 2406 | struct ti_sci_msg_rm_udmap_rx_ch_cfg_req *req; | ||
| 2407 | struct ti_sci_msg_hdr *resp; | ||
| 2408 | struct ti_sci_xfer *xfer; | ||
| 2409 | struct ti_sci_info *info; | ||
| 2410 | struct device *dev; | ||
| 2411 | int ret = 0; | ||
| 2412 | |||
| 2413 | if (IS_ERR_OR_NULL(handle)) | ||
| 2414 | return -EINVAL; | ||
| 2415 | |||
| 2416 | info = handle_to_ti_sci_info(handle); | ||
| 2417 | dev = info->dev; | ||
| 2418 | |||
| 2419 | xfer = ti_sci_get_one_xfer(info, TISCI_MSG_RM_UDMAP_RX_CH_CFG, | ||
| 2420 | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, | ||
| 2421 | sizeof(*req), sizeof(*resp)); | ||
| 2422 | if (IS_ERR(xfer)) { | ||
| 2423 | ret = PTR_ERR(xfer); | ||
| 2424 | dev_err(dev, "Message RX_CH_CFG alloc failed(%d)\n", ret); | ||
| 2425 | return ret; | ||
| 2426 | } | ||
| 2427 | req = (struct ti_sci_msg_rm_udmap_rx_ch_cfg_req *)xfer->xfer_buf; | ||
| 2428 | req->valid_params = params->valid_params; | ||
| 2429 | req->nav_id = params->nav_id; | ||
| 2430 | req->index = params->index; | ||
| 2431 | req->rx_fetch_size = params->rx_fetch_size; | ||
| 2432 | req->rxcq_qnum = params->rxcq_qnum; | ||
| 2433 | req->rx_priority = params->rx_priority; | ||
| 2434 | req->rx_qos = params->rx_qos; | ||
| 2435 | req->rx_orderid = params->rx_orderid; | ||
| 2436 | req->rx_sched_priority = params->rx_sched_priority; | ||
| 2437 | req->flowid_start = params->flowid_start; | ||
| 2438 | req->flowid_cnt = params->flowid_cnt; | ||
| 2439 | req->rx_pause_on_err = params->rx_pause_on_err; | ||
| 2440 | req->rx_atype = params->rx_atype; | ||
| 2441 | req->rx_chan_type = params->rx_chan_type; | ||
| 2442 | req->rx_ignore_short = params->rx_ignore_short; | ||
| 2443 | req->rx_ignore_long = params->rx_ignore_long; | ||
| 2444 | req->rx_burst_size = params->rx_burst_size; | ||
| 2445 | |||
| 2446 | ret = ti_sci_do_xfer(info, xfer); | ||
| 2447 | if (ret) { | ||
| 2448 | dev_err(dev, "Mbox send RX_CH_CFG fail %d\n", ret); | ||
| 2449 | goto fail; | ||
| 2450 | } | ||
| 2451 | |||
| 2452 | resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; | ||
| 2453 | ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL; | ||
| 2454 | |||
| 2455 | fail: | ||
| 2456 | ti_sci_put_one_xfer(&info->minfo, xfer); | ||
| 2457 | dev_dbg(dev, "RX_CH_CFG: chn %u ret:%d\n", params->index, ret); | ||
| 2458 | return ret; | ||
| 2459 | } | ||
| 2460 | |||
| 2461 | /** | ||
| 2462 | * ti_sci_cmd_rm_udmap_rx_flow_cfg() - Configure UDMAP RX FLOW | ||
| 2463 | * @handle: Pointer to TI SCI handle. | ||
| 2464 | * @params: Pointer to ti_sci_msg_rm_udmap_flow_cfg RX FLOW config | ||
| 2465 | * structure | ||
| 2466 | * | ||
| 2467 | * Return: 0 if all went well, else returns appropriate error value. | ||
| 2468 | * | ||
| 2469 | * See @ti_sci_msg_rm_udmap_flow_cfg and @ti_sci_msg_rm_udmap_flow_cfg_req for | ||
| 2470 | * more info. | ||
| 2471 | */ | ||
| 2472 | static int ti_sci_cmd_rm_udmap_rx_flow_cfg(const struct ti_sci_handle *handle, | ||
| 2473 | const struct ti_sci_msg_rm_udmap_flow_cfg *params) | ||
| 2474 | { | ||
| 2475 | struct ti_sci_msg_rm_udmap_flow_cfg_req *req; | ||
| 2476 | struct ti_sci_msg_hdr *resp; | ||
| 2477 | struct ti_sci_xfer *xfer; | ||
| 2478 | struct ti_sci_info *info; | ||
| 2479 | struct device *dev; | ||
| 2480 | int ret = 0; | ||
| 2481 | |||
| 2482 | if (IS_ERR_OR_NULL(handle)) | ||
| 2483 | return -EINVAL; | ||
| 2484 | |||
| 2485 | info = handle_to_ti_sci_info(handle); | ||
| 2486 | dev = info->dev; | ||
| 2487 | |||
| 2488 | xfer = ti_sci_get_one_xfer(info, TISCI_MSG_RM_UDMAP_FLOW_CFG, | ||
| 2489 | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, | ||
| 2490 | sizeof(*req), sizeof(*resp)); | ||
| 2491 | if (IS_ERR(xfer)) { | ||
| 2492 | ret = PTR_ERR(xfer); | ||
| 2493 | dev_err(dev, "RX_FL_CFG: Message alloc failed(%d)\n", ret); | ||
| 2494 | return ret; | ||
| 2495 | } | ||
| 2496 | req = (struct ti_sci_msg_rm_udmap_flow_cfg_req *)xfer->xfer_buf; | ||
| 2497 | req->valid_params = params->valid_params; | ||
| 2498 | req->nav_id = params->nav_id; | ||
| 2499 | req->flow_index = params->flow_index; | ||
| 2500 | req->rx_einfo_present = params->rx_einfo_present; | ||
| 2501 | req->rx_psinfo_present = params->rx_psinfo_present; | ||
| 2502 | req->rx_error_handling = params->rx_error_handling; | ||
| 2503 | req->rx_desc_type = params->rx_desc_type; | ||
| 2504 | req->rx_sop_offset = params->rx_sop_offset; | ||
| 2505 | req->rx_dest_qnum = params->rx_dest_qnum; | ||
| 2506 | req->rx_src_tag_hi = params->rx_src_tag_hi; | ||
| 2507 | req->rx_src_tag_lo = params->rx_src_tag_lo; | ||
| 2508 | req->rx_dest_tag_hi = params->rx_dest_tag_hi; | ||
| 2509 | req->rx_dest_tag_lo = params->rx_dest_tag_lo; | ||
| 2510 | req->rx_src_tag_hi_sel = params->rx_src_tag_hi_sel; | ||
| 2511 | req->rx_src_tag_lo_sel = params->rx_src_tag_lo_sel; | ||
| 2512 | req->rx_dest_tag_hi_sel = params->rx_dest_tag_hi_sel; | ||
| 2513 | req->rx_dest_tag_lo_sel = params->rx_dest_tag_lo_sel; | ||
| 2514 | req->rx_fdq0_sz0_qnum = params->rx_fdq0_sz0_qnum; | ||
| 2515 | req->rx_fdq1_qnum = params->rx_fdq1_qnum; | ||
| 2516 | req->rx_fdq2_qnum = params->rx_fdq2_qnum; | ||
| 2517 | req->rx_fdq3_qnum = params->rx_fdq3_qnum; | ||
| 2518 | req->rx_ps_location = params->rx_ps_location; | ||
| 2519 | |||
| 2520 | ret = ti_sci_do_xfer(info, xfer); | ||
| 2521 | if (ret) { | ||
| 2522 | dev_err(dev, "RX_FL_CFG: Mbox send fail %d\n", ret); | ||
| 2523 | goto fail; | ||
| 2524 | } | ||
| 2525 | |||
| 2526 | resp = (struct ti_sci_msg_hdr *)xfer->xfer_buf; | ||
| 2527 | ret = ti_sci_is_response_ack(resp) ? 0 : -EINVAL; | ||
| 2528 | |||
| 2529 | fail: | ||
| 2530 | ti_sci_put_one_xfer(&info->minfo, xfer); | ||
| 2531 | dev_dbg(info->dev, "RX_FL_CFG: %u ret:%d\n", params->flow_index, ret); | ||
| 2532 | return ret; | ||
| 2533 | } | ||
| 2534 | |||
| 2535 | /** | ||
| 2536 | * ti_sci_cmd_proc_request() - Command to request a physical processor control | ||
| 2537 | * @handle: Pointer to TI SCI handle | ||
| 2538 | * @proc_id: Processor ID this request is for | ||
| 2539 | * | ||
| 2540 | * Return: 0 if all went well, else returns appropriate error value. | ||
| 2541 | */ | ||
| 2542 | static int ti_sci_cmd_proc_request(const struct ti_sci_handle *handle, | ||
| 2543 | u8 proc_id) | ||
| 2544 | { | ||
| 2545 | struct ti_sci_msg_req_proc_request *req; | ||
| 2546 | struct ti_sci_msg_hdr *resp; | ||
| 2547 | struct ti_sci_info *info; | ||
| 2548 | struct ti_sci_xfer *xfer; | ||
| 2549 | struct device *dev; | ||
| 2550 | int ret = 0; | ||
| 2551 | |||
| 2552 | if (!handle) | ||
| 2553 | return -EINVAL; | ||
| 2554 | if (IS_ERR(handle)) | ||
| 2555 | return PTR_ERR(handle); | ||
| 2556 | |||
| 2557 | info = handle_to_ti_sci_info(handle); | ||
| 2558 | dev = info->dev; | ||
| 2559 | |||
| 2560 | xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PROC_REQUEST, | ||
| 2561 | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, | ||
| 2562 | sizeof(*req), sizeof(*resp)); | ||
| 2563 | if (IS_ERR(xfer)) { | ||
| 2564 | ret = PTR_ERR(xfer); | ||
| 2565 | dev_err(dev, "Message alloc failed(%d)\n", ret); | ||
| 2566 | return ret; | ||
| 2567 | } | ||
| 2568 | req = (struct ti_sci_msg_req_proc_request *)xfer->xfer_buf; | ||
| 2569 | req->processor_id = proc_id; | ||
| 2570 | |||
| 2571 | ret = ti_sci_do_xfer(info, xfer); | ||
| 2572 | if (ret) { | ||
| 2573 | dev_err(dev, "Mbox send fail %d\n", ret); | ||
| 2574 | goto fail; | ||
| 2575 | } | ||
| 2576 | |||
| 2577 | resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; | ||
| 2578 | |||
| 2579 | ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; | ||
| 2580 | |||
| 2581 | fail: | ||
| 2582 | ti_sci_put_one_xfer(&info->minfo, xfer); | ||
| 2583 | |||
| 2584 | return ret; | ||
| 2585 | } | ||
| 2586 | |||
| 2587 | /** | ||
| 2588 | * ti_sci_cmd_proc_release() - Command to release a physical processor control | ||
| 2589 | * @handle: Pointer to TI SCI handle | ||
| 2590 | * @proc_id: Processor ID this request is for | ||
| 2591 | * | ||
| 2592 | * Return: 0 if all went well, else returns appropriate error value. | ||
| 2593 | */ | ||
| 2594 | static int ti_sci_cmd_proc_release(const struct ti_sci_handle *handle, | ||
| 2595 | u8 proc_id) | ||
| 2596 | { | ||
| 2597 | struct ti_sci_msg_req_proc_release *req; | ||
| 2598 | struct ti_sci_msg_hdr *resp; | ||
| 2599 | struct ti_sci_info *info; | ||
| 2600 | struct ti_sci_xfer *xfer; | ||
| 2601 | struct device *dev; | ||
| 2602 | int ret = 0; | ||
| 2603 | |||
| 2604 | if (!handle) | ||
| 2605 | return -EINVAL; | ||
| 2606 | if (IS_ERR(handle)) | ||
| 2607 | return PTR_ERR(handle); | ||
| 2608 | |||
| 2609 | info = handle_to_ti_sci_info(handle); | ||
| 2610 | dev = info->dev; | ||
| 2611 | |||
| 2612 | xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PROC_RELEASE, | ||
| 2613 | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, | ||
| 2614 | sizeof(*req), sizeof(*resp)); | ||
| 2615 | if (IS_ERR(xfer)) { | ||
| 2616 | ret = PTR_ERR(xfer); | ||
| 2617 | dev_err(dev, "Message alloc failed(%d)\n", ret); | ||
| 2618 | return ret; | ||
| 2619 | } | ||
| 2620 | req = (struct ti_sci_msg_req_proc_release *)xfer->xfer_buf; | ||
| 2621 | req->processor_id = proc_id; | ||
| 2622 | |||
| 2623 | ret = ti_sci_do_xfer(info, xfer); | ||
| 2624 | if (ret) { | ||
| 2625 | dev_err(dev, "Mbox send fail %d\n", ret); | ||
| 2626 | goto fail; | ||
| 2627 | } | ||
| 2628 | |||
| 2629 | resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; | ||
| 2630 | |||
| 2631 | ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; | ||
| 2632 | |||
| 2633 | fail: | ||
| 2634 | ti_sci_put_one_xfer(&info->minfo, xfer); | ||
| 2635 | |||
| 2636 | return ret; | ||
| 2637 | } | ||
| 2638 | |||
| 2639 | /** | ||
| 2640 | * ti_sci_cmd_proc_handover() - Command to handover a physical processor | ||
| 2641 | * control to a host in the processor's access | ||
| 2642 | * control list. | ||
| 2643 | * @handle: Pointer to TI SCI handle | ||
| 2644 | * @proc_id: Processor ID this request is for | ||
| 2645 | * @host_id: Host ID to get the control of the processor | ||
| 2646 | * | ||
| 2647 | * Return: 0 if all went well, else returns appropriate error value. | ||
| 2648 | */ | ||
| 2649 | static int ti_sci_cmd_proc_handover(const struct ti_sci_handle *handle, | ||
| 2650 | u8 proc_id, u8 host_id) | ||
| 2651 | { | ||
| 2652 | struct ti_sci_msg_req_proc_handover *req; | ||
| 2653 | struct ti_sci_msg_hdr *resp; | ||
| 2654 | struct ti_sci_info *info; | ||
| 2655 | struct ti_sci_xfer *xfer; | ||
| 2656 | struct device *dev; | ||
| 2657 | int ret = 0; | ||
| 2658 | |||
| 2659 | if (!handle) | ||
| 2660 | return -EINVAL; | ||
| 2661 | if (IS_ERR(handle)) | ||
| 2662 | return PTR_ERR(handle); | ||
| 2663 | |||
| 2664 | info = handle_to_ti_sci_info(handle); | ||
| 2665 | dev = info->dev; | ||
| 2666 | |||
| 2667 | xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_PROC_HANDOVER, | ||
| 2668 | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, | ||
| 2669 | sizeof(*req), sizeof(*resp)); | ||
| 2670 | if (IS_ERR(xfer)) { | ||
| 2671 | ret = PTR_ERR(xfer); | ||
| 2672 | dev_err(dev, "Message alloc failed(%d)\n", ret); | ||
| 2673 | return ret; | ||
| 2674 | } | ||
| 2675 | req = (struct ti_sci_msg_req_proc_handover *)xfer->xfer_buf; | ||
| 2676 | req->processor_id = proc_id; | ||
| 2677 | req->host_id = host_id; | ||
| 2678 | |||
| 2679 | ret = ti_sci_do_xfer(info, xfer); | ||
| 2680 | if (ret) { | ||
| 2681 | dev_err(dev, "Mbox send fail %d\n", ret); | ||
| 2682 | goto fail; | ||
| 2683 | } | ||
| 2684 | |||
| 2685 | resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; | ||
| 2686 | |||
| 2687 | ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; | ||
| 2688 | |||
| 2689 | fail: | ||
| 2690 | ti_sci_put_one_xfer(&info->minfo, xfer); | ||
| 2691 | |||
| 2692 | return ret; | ||
| 2693 | } | ||
| 2694 | |||
| 2695 | /** | ||
| 2696 | * ti_sci_cmd_proc_set_config() - Command to set the processor boot | ||
| 2697 | * configuration flags | ||
| 2698 | * @handle: Pointer to TI SCI handle | ||
| 2699 | * @proc_id: Processor ID this request is for | ||
| 2700 | * @config_flags_set: Configuration flags to be set | ||
| 2701 | * @config_flags_clear: Configuration flags to be cleared. | ||
| 2702 | * | ||
| 2703 | * Return: 0 if all went well, else returns appropriate error value. | ||
| 2704 | */ | ||
| 2705 | static int ti_sci_cmd_proc_set_config(const struct ti_sci_handle *handle, | ||
| 2706 | u8 proc_id, u64 bootvector, | ||
| 2707 | u32 config_flags_set, | ||
| 2708 | u32 config_flags_clear) | ||
| 2709 | { | ||
| 2710 | struct ti_sci_msg_req_set_config *req; | ||
| 2711 | struct ti_sci_msg_hdr *resp; | ||
| 2712 | struct ti_sci_info *info; | ||
| 2713 | struct ti_sci_xfer *xfer; | ||
| 2714 | struct device *dev; | ||
| 2715 | int ret = 0; | ||
| 2716 | |||
| 2717 | if (!handle) | ||
| 2718 | return -EINVAL; | ||
| 2719 | if (IS_ERR(handle)) | ||
| 2720 | return PTR_ERR(handle); | ||
| 2721 | |||
| 2722 | info = handle_to_ti_sci_info(handle); | ||
| 2723 | dev = info->dev; | ||
| 2724 | |||
| 2725 | xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CONFIG, | ||
| 2726 | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, | ||
| 2727 | sizeof(*req), sizeof(*resp)); | ||
| 2728 | if (IS_ERR(xfer)) { | ||
| 2729 | ret = PTR_ERR(xfer); | ||
| 2730 | dev_err(dev, "Message alloc failed(%d)\n", ret); | ||
| 2731 | return ret; | ||
| 2732 | } | ||
| 2733 | req = (struct ti_sci_msg_req_set_config *)xfer->xfer_buf; | ||
| 2734 | req->processor_id = proc_id; | ||
| 2735 | req->bootvector_low = bootvector & TI_SCI_ADDR_LOW_MASK; | ||
| 2736 | req->bootvector_high = (bootvector & TI_SCI_ADDR_HIGH_MASK) >> | ||
| 2737 | TI_SCI_ADDR_HIGH_SHIFT; | ||
| 2738 | req->config_flags_set = config_flags_set; | ||
| 2739 | req->config_flags_clear = config_flags_clear; | ||
| 2740 | |||
| 2741 | ret = ti_sci_do_xfer(info, xfer); | ||
| 2742 | if (ret) { | ||
| 2743 | dev_err(dev, "Mbox send fail %d\n", ret); | ||
| 2744 | goto fail; | ||
| 2745 | } | ||
| 2746 | |||
| 2747 | resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; | ||
| 2748 | |||
| 2749 | ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; | ||
| 2750 | |||
| 2751 | fail: | ||
| 2752 | ti_sci_put_one_xfer(&info->minfo, xfer); | ||
| 2753 | |||
| 2754 | return ret; | ||
| 2755 | } | ||
| 2756 | |||
| 2757 | /** | ||
| 2758 | * ti_sci_cmd_proc_set_control() - Command to set the processor boot | ||
| 2759 | * control flags | ||
| 2760 | * @handle: Pointer to TI SCI handle | ||
| 2761 | * @proc_id: Processor ID this request is for | ||
| 2762 | * @control_flags_set: Control flags to be set | ||
| 2763 | * @control_flags_clear: Control flags to be cleared | ||
| 2764 | * | ||
| 2765 | * Return: 0 if all went well, else returns appropriate error value. | ||
| 2766 | */ | ||
| 2767 | static int ti_sci_cmd_proc_set_control(const struct ti_sci_handle *handle, | ||
| 2768 | u8 proc_id, u32 control_flags_set, | ||
| 2769 | u32 control_flags_clear) | ||
| 2770 | { | ||
| 2771 | struct ti_sci_msg_req_set_ctrl *req; | ||
| 2772 | struct ti_sci_msg_hdr *resp; | ||
| 2773 | struct ti_sci_info *info; | ||
| 2774 | struct ti_sci_xfer *xfer; | ||
| 2775 | struct device *dev; | ||
| 2776 | int ret = 0; | ||
| 2777 | |||
| 2778 | if (!handle) | ||
| 2779 | return -EINVAL; | ||
| 2780 | if (IS_ERR(handle)) | ||
| 2781 | return PTR_ERR(handle); | ||
| 2782 | |||
| 2783 | info = handle_to_ti_sci_info(handle); | ||
| 2784 | dev = info->dev; | ||
| 2785 | |||
| 2786 | xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_SET_CTRL, | ||
| 2787 | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, | ||
| 2788 | sizeof(*req), sizeof(*resp)); | ||
| 2789 | if (IS_ERR(xfer)) { | ||
| 2790 | ret = PTR_ERR(xfer); | ||
| 2791 | dev_err(dev, "Message alloc failed(%d)\n", ret); | ||
| 2792 | return ret; | ||
| 2793 | } | ||
| 2794 | req = (struct ti_sci_msg_req_set_ctrl *)xfer->xfer_buf; | ||
| 2795 | req->processor_id = proc_id; | ||
| 2796 | req->control_flags_set = control_flags_set; | ||
| 2797 | req->control_flags_clear = control_flags_clear; | ||
| 2798 | |||
| 2799 | ret = ti_sci_do_xfer(info, xfer); | ||
| 2800 | if (ret) { | ||
| 2801 | dev_err(dev, "Mbox send fail %d\n", ret); | ||
| 2802 | goto fail; | ||
| 2803 | } | ||
| 2804 | |||
| 2805 | resp = (struct ti_sci_msg_hdr *)xfer->tx_message.buf; | ||
| 2806 | |||
| 2807 | ret = ti_sci_is_response_ack(resp) ? 0 : -ENODEV; | ||
| 2808 | |||
| 2809 | fail: | ||
| 2810 | ti_sci_put_one_xfer(&info->minfo, xfer); | ||
| 2811 | |||
| 2812 | return ret; | ||
| 2813 | } | ||
| 2814 | |||
| 2815 | /** | ||
| 2816 | * ti_sci_cmd_get_boot_status() - Command to get the processor boot status | ||
| 2817 | * @handle: Pointer to TI SCI handle | ||
| 2818 | * @proc_id: Processor ID this request is for | ||
| 2819 | * | ||
| 2820 | * Return: 0 if all went well, else returns appropriate error value. | ||
| 2821 | */ | ||
| 2822 | static int ti_sci_cmd_proc_get_status(const struct ti_sci_handle *handle, | ||
| 2823 | u8 proc_id, u64 *bv, u32 *cfg_flags, | ||
| 2824 | u32 *ctrl_flags, u32 *sts_flags) | ||
| 2825 | { | ||
| 2826 | struct ti_sci_msg_resp_get_status *resp; | ||
| 2827 | struct ti_sci_msg_req_get_status *req; | ||
| 2828 | struct ti_sci_info *info; | ||
| 2829 | struct ti_sci_xfer *xfer; | ||
| 2830 | struct device *dev; | ||
| 2831 | int ret = 0; | ||
| 2832 | |||
| 2833 | if (!handle) | ||
| 2834 | return -EINVAL; | ||
| 2835 | if (IS_ERR(handle)) | ||
| 2836 | return PTR_ERR(handle); | ||
| 2837 | |||
| 2838 | info = handle_to_ti_sci_info(handle); | ||
| 2839 | dev = info->dev; | ||
| 2840 | |||
| 2841 | xfer = ti_sci_get_one_xfer(info, TI_SCI_MSG_GET_STATUS, | ||
| 2842 | TI_SCI_FLAG_REQ_ACK_ON_PROCESSED, | ||
| 2843 | sizeof(*req), sizeof(*resp)); | ||
| 2844 | if (IS_ERR(xfer)) { | ||
| 2845 | ret = PTR_ERR(xfer); | ||
| 2846 | dev_err(dev, "Message alloc failed(%d)\n", ret); | ||
| 2847 | return ret; | ||
| 2848 | } | ||
| 2849 | req = (struct ti_sci_msg_req_get_status *)xfer->xfer_buf; | ||
| 2850 | req->processor_id = proc_id; | ||
| 2851 | |||
| 2852 | ret = ti_sci_do_xfer(info, xfer); | ||
| 2853 | if (ret) { | ||
| 2854 | dev_err(dev, "Mbox send fail %d\n", ret); | ||
| 2855 | goto fail; | ||
| 2856 | } | ||
| 2857 | |||
| 2858 | resp = (struct ti_sci_msg_resp_get_status *)xfer->tx_message.buf; | ||
| 2859 | |||
| 2860 | if (!ti_sci_is_response_ack(resp)) { | ||
| 2861 | ret = -ENODEV; | ||
| 2862 | } else { | ||
| 2863 | *bv = (resp->bootvector_low & TI_SCI_ADDR_LOW_MASK) | | ||
| 2864 | (((u64)resp->bootvector_high << TI_SCI_ADDR_HIGH_SHIFT) & | ||
| 2865 | TI_SCI_ADDR_HIGH_MASK); | ||
| 2866 | *cfg_flags = resp->config_flags; | ||
| 2867 | *ctrl_flags = resp->control_flags; | ||
| 2868 | *sts_flags = resp->status_flags; | ||
| 2869 | } | ||
| 2870 | |||
| 2871 | fail: | ||
| 2872 | ti_sci_put_one_xfer(&info->minfo, xfer); | ||
| 2873 | |||
| 2874 | return ret; | ||
| 2875 | } | ||
| 2876 | |||
| 2877 | /* | ||
| 2878 | * ti_sci_setup_ops() - Setup the operations structures | ||
| 2879 | * @info: pointer to TISCI pointer | ||
| 2880 | */ | ||
| 2881 | static void ti_sci_setup_ops(struct ti_sci_info *info) | ||
| 2882 | { | ||
| 2883 | struct ti_sci_ops *ops = &info->handle.ops; | ||
| 2884 | struct ti_sci_core_ops *core_ops = &ops->core_ops; | ||
| 2885 | struct ti_sci_dev_ops *dops = &ops->dev_ops; | ||
| 2886 | struct ti_sci_clk_ops *cops = &ops->clk_ops; | ||
| 2887 | struct ti_sci_rm_core_ops *rm_core_ops = &ops->rm_core_ops; | ||
| 2888 | struct ti_sci_rm_irq_ops *iops = &ops->rm_irq_ops; | ||
| 2889 | struct ti_sci_rm_ringacc_ops *rops = &ops->rm_ring_ops; | ||
| 2890 | struct ti_sci_rm_psil_ops *psilops = &ops->rm_psil_ops; | ||
| 2891 | struct ti_sci_rm_udmap_ops *udmap_ops = &ops->rm_udmap_ops; | ||
| 2892 | struct ti_sci_proc_ops *pops = &ops->proc_ops; | ||
| 2893 | |||
| 2894 | core_ops->reboot_device = ti_sci_cmd_core_reboot; | ||
| 2895 | |||
| 2896 | dops->get_device = ti_sci_cmd_get_device; | ||
| 2897 | dops->idle_device = ti_sci_cmd_idle_device; | ||
| 2898 | dops->put_device = ti_sci_cmd_put_device; | ||
| 2899 | |||
| 2900 | dops->is_valid = ti_sci_cmd_dev_is_valid; | ||
| 2901 | dops->get_context_loss_count = ti_sci_cmd_dev_get_clcnt; | ||
| 2902 | dops->is_idle = ti_sci_cmd_dev_is_idle; | ||
| 2903 | dops->is_stop = ti_sci_cmd_dev_is_stop; | ||
| 2904 | dops->is_on = ti_sci_cmd_dev_is_on; | ||
| 2905 | dops->is_transitioning = ti_sci_cmd_dev_is_trans; | ||
| 2906 | dops->set_device_resets = ti_sci_cmd_set_device_resets; | ||
| 2907 | dops->get_device_resets = ti_sci_cmd_get_device_resets; | ||
| 2908 | |||
| 2909 | cops->get_clock = ti_sci_cmd_get_clock; | ||
| 2910 | cops->idle_clock = ti_sci_cmd_idle_clock; | ||
| 2911 | cops->put_clock = ti_sci_cmd_put_clock; | ||
| 2912 | cops->is_auto = ti_sci_cmd_clk_is_auto; | ||
| 2913 | cops->is_on = ti_sci_cmd_clk_is_on; | ||
| 2914 | cops->is_off = ti_sci_cmd_clk_is_off; | ||
| 2915 | |||
| 2916 | cops->set_parent = ti_sci_cmd_clk_set_parent; | ||
| 2917 | cops->get_parent = ti_sci_cmd_clk_get_parent; | ||
| 2918 | cops->get_num_parents = ti_sci_cmd_clk_get_num_parents; | ||
| 2919 | |||
| 2920 | cops->get_best_match_freq = ti_sci_cmd_clk_get_match_freq; | ||
| 2921 | cops->set_freq = ti_sci_cmd_clk_set_freq; | ||
| 2922 | cops->get_freq = ti_sci_cmd_clk_get_freq; | ||
| 2923 | |||
| 2924 | rm_core_ops->get_range = ti_sci_cmd_get_resource_range; | ||
| 2925 | rm_core_ops->get_range_from_shost = | ||
| 2926 | ti_sci_cmd_get_resource_range_from_shost; | ||
| 2927 | |||
| 2928 | iops->set_irq = ti_sci_cmd_set_irq; | ||
| 2929 | iops->set_event_map = ti_sci_cmd_set_event_map; | ||
| 2930 | iops->free_irq = ti_sci_cmd_free_irq; | ||
| 2931 | iops->free_event_map = ti_sci_cmd_free_event_map; | ||
| 2932 | |||
| 2933 | rops->config = ti_sci_cmd_ring_config; | ||
| 2934 | rops->get_config = ti_sci_cmd_ring_get_config; | ||
| 2935 | |||
| 2936 | psilops->pair = ti_sci_cmd_rm_psil_pair; | ||
| 2937 | psilops->unpair = ti_sci_cmd_rm_psil_unpair; | ||
| 2938 | |||
| 2939 | udmap_ops->tx_ch_cfg = ti_sci_cmd_rm_udmap_tx_ch_cfg; | ||
| 2940 | udmap_ops->rx_ch_cfg = ti_sci_cmd_rm_udmap_rx_ch_cfg; | ||
| 2941 | udmap_ops->rx_flow_cfg = ti_sci_cmd_rm_udmap_rx_flow_cfg; | ||
| 2942 | |||
| 2943 | pops->request = ti_sci_cmd_proc_request; | ||
| 2944 | pops->release = ti_sci_cmd_proc_release; | ||
| 2945 | pops->handover = ti_sci_cmd_proc_handover; | ||
| 2946 | pops->set_config = ti_sci_cmd_proc_set_config; | ||
| 2947 | pops->set_control = ti_sci_cmd_proc_set_control; | ||
| 2948 | pops->get_status = ti_sci_cmd_proc_get_status; | ||
| 2949 | } | ||
| 2950 | |||
| 2951 | /** | ||
| 2952 | * ti_sci_get_handle() - Get the TI SCI handle for a device | ||
| 2953 | * @dev: Pointer to device for which we want SCI handle | ||
| 2954 | * | ||
| 2955 | * NOTE: The function does not track individual clients of the framework | ||
| 2956 | * and is expected to be maintained by caller of TI SCI protocol library. | ||
| 2957 | * ti_sci_put_handle must be balanced with successful ti_sci_get_handle | ||
| 2958 | * Return: pointer to handle if successful, else: | ||
| 2959 | * -EPROBE_DEFER if the instance is not ready | ||
| 2960 | * -ENODEV if the required node handler is missing | ||
| 2961 | * -EINVAL if invalid conditions are encountered. | ||
| 2962 | */ | ||
| 2963 | const struct ti_sci_handle *ti_sci_get_handle(struct device *dev) | ||
| 2964 | { | ||
| 2965 | struct device_node *ti_sci_np; | ||
| 2966 | struct list_head *p; | ||
| 2967 | struct ti_sci_handle *handle = NULL; | ||
| 2968 | struct ti_sci_info *info; | ||
| 2969 | |||
| 2970 | if (!dev) { | ||
| 2971 | pr_err("I need a device pointer\n"); | ||
| 2972 | return ERR_PTR(-EINVAL); | ||
| 2973 | } | ||
| 2974 | ti_sci_np = of_get_parent(dev->of_node); | ||
| 2975 | if (!ti_sci_np) { | ||
| 2976 | dev_err(dev, "No OF information\n"); | ||
| 2977 | return ERR_PTR(-EINVAL); | ||
| 2978 | } | ||
| 2979 | |||
| 2980 | mutex_lock(&ti_sci_list_mutex); | ||
| 2981 | list_for_each(p, &ti_sci_list) { | ||
| 2982 | info = list_entry(p, struct ti_sci_info, node); | ||
| 2983 | if (ti_sci_np == info->dev->of_node) { | ||
| 2984 | handle = &info->handle; | ||
| 2985 | info->users++; | ||
| 2986 | break; | ||
| 2987 | } | ||
| 2988 | } | ||
| 2989 | mutex_unlock(&ti_sci_list_mutex); | ||
| 2990 | of_node_put(ti_sci_np); | ||
| 2991 | |||
| 2992 | if (!handle) | ||
| 2993 | return ERR_PTR(-EPROBE_DEFER); | ||
| 2994 | |||
| 2995 | return handle; | ||
| 2996 | } | ||
| 2997 | EXPORT_SYMBOL_GPL(ti_sci_get_handle); | ||
| 2998 | |||
| 2999 | /** | ||
| 3000 | * ti_sci_put_handle() - Release the handle acquired by ti_sci_get_handle | ||
| 3001 | * @handle: Handle acquired by ti_sci_get_handle | ||
| 3002 | * | ||
| 3003 | * NOTE: The function does not track individual clients of the framework | ||
| 3004 | * and is expected to be maintained by caller of TI SCI protocol library. | ||
| 3005 | * ti_sci_put_handle must be balanced with successful ti_sci_get_handle | ||
| 3006 | * | ||
| 3007 | * Return: 0 is successfully released | ||
| 3008 | * if an error pointer was passed, it returns the error value back, | ||
| 3009 | * if null was passed, it returns -EINVAL; | ||
| 3010 | */ | ||
| 3011 | int ti_sci_put_handle(const struct ti_sci_handle *handle) | ||
| 3012 | { | ||
| 3013 | struct ti_sci_info *info; | ||
| 3014 | |||
| 3015 | if (IS_ERR(handle)) | ||
| 3016 | return PTR_ERR(handle); | ||
| 3017 | if (!handle) | ||
| 3018 | return -EINVAL; | ||
| 3019 | |||
| 3020 | info = handle_to_ti_sci_info(handle); | ||
| 3021 | mutex_lock(&ti_sci_list_mutex); | ||
| 3022 | if (!WARN_ON(!info->users)) | ||
| 3023 | info->users--; | ||
| 3024 | mutex_unlock(&ti_sci_list_mutex); | ||
| 3025 | |||
| 3026 | return 0; | ||
| 3027 | } | ||
| 3028 | EXPORT_SYMBOL_GPL(ti_sci_put_handle); | ||
| 3029 | |||
| 3030 | static void devm_ti_sci_release(struct device *dev, void *res) | ||
| 3031 | { | ||
| 3032 | const struct ti_sci_handle **ptr = res; | ||
| 3033 | const struct ti_sci_handle *handle = *ptr; | ||
| 3034 | int ret; | ||
| 3035 | |||
| 3036 | ret = ti_sci_put_handle(handle); | ||
| 3037 | if (ret) | ||
| 3038 | dev_err(dev, "failed to put handle %d\n", ret); | ||
| 3039 | } | ||
| 3040 | |||
| 3041 | /** | ||
| 3042 | * devm_ti_sci_get_handle() - Managed get handle | ||
| 3043 | * @dev: device for which we want SCI handle for. | ||
| 3044 | * | ||
| 3045 | * NOTE: This releases the handle once the device resources are | ||
| 3046 | * no longer needed. MUST NOT BE released with ti_sci_put_handle. | ||
| 3047 | * The function does not track individual clients of the framework | ||
| 3048 | * and is expected to be maintained by caller of TI SCI protocol library. | ||
| 3049 | * | ||
| 3050 | * Return: 0 if all went fine, else corresponding error. | ||
| 3051 | */ | ||
| 3052 | const struct ti_sci_handle *devm_ti_sci_get_handle(struct device *dev) | ||
| 3053 | { | ||
| 3054 | const struct ti_sci_handle **ptr; | ||
| 3055 | const struct ti_sci_handle *handle; | ||
| 3056 | |||
| 3057 | ptr = devres_alloc(devm_ti_sci_release, sizeof(*ptr), GFP_KERNEL); | ||
| 3058 | if (!ptr) | ||
| 3059 | return ERR_PTR(-ENOMEM); | ||
| 3060 | handle = ti_sci_get_handle(dev); | ||
| 3061 | |||
| 3062 | if (!IS_ERR(handle)) { | ||
| 3063 | *ptr = handle; | ||
| 3064 | devres_add(dev, ptr); | ||
| 3065 | } else { | ||
| 3066 | devres_free(ptr); | ||
| 3067 | } | ||
| 3068 | |||
| 3069 | return handle; | ||
| 3070 | } | ||
| 3071 | EXPORT_SYMBOL_GPL(devm_ti_sci_get_handle); | ||
| 3072 | |||
| 3073 | /** | ||
| 3074 | * ti_sci_get_by_phandle() - Get the TI SCI handle using DT phandle | ||
| 3075 | * @np: device node | ||
| 3076 | * @property: property name containing phandle on TISCI node | ||
| 3077 | * | ||
| 3078 | * NOTE: The function does not track individual clients of the framework | ||
| 3079 | * and is expected to be maintained by caller of TI SCI protocol library. | ||
| 3080 | * ti_sci_put_handle must be balanced with successful ti_sci_get_by_phandle | ||
| 3081 | * Return: pointer to handle if successful, else: | ||
| 3082 | * -EPROBE_DEFER if the instance is not ready | ||
| 3083 | * -ENODEV if the required node handler is missing | ||
| 3084 | * -EINVAL if invalid conditions are encountered. | ||
| 3085 | */ | ||
| 3086 | const struct ti_sci_handle *ti_sci_get_by_phandle(struct device_node *np, | ||
| 3087 | const char *property) | ||
| 3088 | { | ||
| 3089 | struct ti_sci_handle *handle = NULL; | ||
| 3090 | struct device_node *ti_sci_np; | ||
| 3091 | struct ti_sci_info *info; | ||
| 3092 | struct list_head *p; | ||
| 3093 | |||
| 3094 | if (!np) { | ||
| 3095 | pr_err("I need a device pointer\n"); | ||
| 2258 | return ERR_PTR(-EINVAL); | 3096 | return ERR_PTR(-EINVAL); |
| 2259 | } | 3097 | } |
| 2260 | 3098 | ||
| @@ -2395,6 +3233,7 @@ devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, · 134 unmodified lines | |||
| 2395 | struct device *dev, u32 dev_id, char *of_prop) | 3233 | struct device *dev, u32 dev_id, char *of_prop) |
| 2396 | { | 3234 | { |
| 2397 | struct ti_sci_resource *res; | 3235 | struct ti_sci_resource *res; |
| 3236 | bool valid_set = false; | ||
| 2398 | u32 resource_subtype; | 3237 | u32 resource_subtype; |
| 2399 | int i, ret; | 3238 | int i, ret; |
| 2400 | 3239 | ||
| @@ -2426,15 +3265,18 @@ devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, · 25 unmodified lines | |||
| 2426 | &res->desc[i].start, | 3265 | &res->desc[i].start, |
| 2427 | &res->desc[i].num); | 3266 | &res->desc[i].num); |
| 2428 | if (ret) { | 3267 | if (ret) { |
| 2429 | dev_err(dev, "dev = %d subtype %d not allocated for this host\n", | 3268 | dev_dbg(dev, "dev = %d subtype %d not allocated for this host\n", |
| 2430 | dev_id, resource_subtype); | 3269 | dev_id, resource_subtype); |
| 2431 | return ERR_PTR(ret); | 3270 | res->desc[i].start = 0; |
| 3271 | res->desc[i].num = 0; | ||
| 3272 | continue; | ||
| 2432 | } | 3273 | } |
| 2433 | 3274 | ||
| 2434 | dev_dbg(dev, "dev = %d, subtype = %d, start = %d, num = %d\n", | 3275 | dev_dbg(dev, "dev = %d, subtype = %d, start = %d, num = %d\n", |
| 2435 | dev_id, resource_subtype, res->desc[i].start, | 3276 | dev_id, resource_subtype, res->desc[i].start, |
| 2436 | res->desc[i].num); | 3277 | res->desc[i].num); |
| 2437 | 3278 | ||
| 3279 | valid_set = true; | ||
| 2438 | res->desc[i].res_map = | 3280 | res->desc[i].res_map = |
| 2439 | devm_kzalloc(dev, BITS_TO_LONGS(res->desc[i].num) * | 3281 | devm_kzalloc(dev, BITS_TO_LONGS(res->desc[i].num) * |
| 2440 | sizeof(*res->desc[i].res_map), GFP_KERNEL); | 3282 | sizeof(*res->desc[i].res_map), GFP_KERNEL); |
| @@ -2443,7 +3285,10 @@ devm_ti_sci_get_of_resource(const struct ti_sci_handle *handle, · 2 unmodified lines | |||
| 2443 | } | 3285 | } |
| 2444 | raw_spin_lock_init(&res->lock); | 3286 | raw_spin_lock_init(&res->lock); |
| 2445 | 3287 | ||
| 2446 | return res; | 3288 | if (valid_set) |
| 3289 | return res; | ||
| 3290 | |||
| 3291 | return ERR_PTR(-EINVAL); | ||
| 2447 | } | 3292 | } |
| 2448 | 3293 | ||
| 2449 | static int tisci_reboot_handler(struct notifier_block *nb, unsigned long mode, | 3294 | static int tisci_reboot_handler(struct notifier_block *nb, unsigned long mode, |
| @@ -42,6 +42,43 @@ · 41 unmodified lines | |||
| 42 | #define TI_SCI_MSG_SET_IRQ 0x1000 | 42 | #define TI_SCI_MSG_SET_IRQ 0x1000 |
| 43 | #define TI_SCI_MSG_FREE_IRQ 0x1001 | 43 | #define TI_SCI_MSG_FREE_IRQ 0x1001 |
| 44 | 44 | ||
| 45 | /* NAVSS resource management */ | ||
| 46 | /* Ringacc requests */ | ||
| 47 | #define TI_SCI_MSG_RM_RING_ALLOCATE 0x1100 | ||
| 48 | #define TI_SCI_MSG_RM_RING_FREE 0x1101 | ||
| 49 | #define TI_SCI_MSG_RM_RING_RECONFIG 0x1102 | ||
| 50 | #define TI_SCI_MSG_RM_RING_RESET 0x1103 | ||
| 51 | #define TI_SCI_MSG_RM_RING_CFG 0x1110 | ||
| 52 | #define TI_SCI_MSG_RM_RING_GET_CFG 0x1111 | ||
| 53 | |||
| 54 | /* PSI-L requests */ | ||
| 55 | #define TI_SCI_MSG_RM_PSIL_PAIR 0x1280 | ||
| 56 | #define TI_SCI_MSG_RM_PSIL_UNPAIR 0x1281 | ||
| 57 | |||
| 58 | #define TI_SCI_MSG_RM_UDMAP_TX_ALLOC 0x1200 | ||
| 59 | #define TI_SCI_MSG_RM_UDMAP_TX_FREE 0x1201 | ||
| 60 | #define TI_SCI_MSG_RM_UDMAP_RX_ALLOC 0x1210 | ||
| 61 | #define TI_SCI_MSG_RM_UDMAP_RX_FREE 0x1211 | ||
| 62 | #define TI_SCI_MSG_RM_UDMAP_FLOW_CFG 0x1220 | ||
| 63 | #define TI_SCI_MSG_RM_UDMAP_OPT_FLOW_CFG 0x1221 | ||
| 64 | |||
| 65 | #define TISCI_MSG_RM_UDMAP_TX_CH_CFG 0x1205 | ||
| 66 | #define TISCI_MSG_RM_UDMAP_TX_CH_GET_CFG 0x1206 | ||
| 67 | #define TISCI_MSG_RM_UDMAP_RX_CH_CFG 0x1215 | ||
| 68 | #define TISCI_MSG_RM_UDMAP_RX_CH_GET_CFG 0x1216 | ||
| 69 | #define TISCI_MSG_RM_UDMAP_FLOW_CFG 0x1230 | ||
| 70 | #define TISCI_MSG_RM_UDMAP_FLOW_SIZE_THRESH_CFG 0x1231 | ||
| 71 | #define TISCI_MSG_RM_UDMAP_FLOW_GET_CFG 0x1232 | ||
| 72 | #define TISCI_MSG_RM_UDMAP_FLOW_SIZE_THRESH_GET_CFG 0x1233 | ||
| 73 | |||
| 74 | /* Processor Control requests */ | ||
| 75 | #define TI_SCI_MSG_PROC_REQUEST 0xc000 | ||
| 76 | #define TI_SCI_MSG_PROC_RELEASE 0xc001 | ||
| 77 | #define TI_SCI_MSG_PROC_HANDOVER 0xc005 | ||
| 78 | #define TI_SCI_MSG_SET_CONFIG 0xc100 | ||
| 79 | #define TI_SCI_MSG_SET_CTRL 0xc101 | ||
| 80 | #define TI_SCI_MSG_GET_STATUS 0xc400 | ||
| 81 | |||
| 45 | /** | 82 | /** |
| 46 | * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses | 83 | * struct ti_sci_msg_hdr - Generic Message Header for All messages and responses |
| 47 | * @type: Type of messages: One of TI_SCI_MSG* values | 84 | * @type: Type of messages: One of TI_SCI_MSG* values |
| @@ -604,4 +641,777 @@ struct ti_sci_msg_req_manage_irq { · 556 unmodified lines | |||
| 604 | u8 secondary_host; | 641 | u8 secondary_host; |
| 605 | } __packed; | 642 | } __packed; |
| 606 | 643 | ||
| 644 | /** | ||
| 645 | * struct ti_sci_msg_rm_ring_cfg_req - Configure a Navigator Subsystem ring | ||
| 646 | * | ||
| 647 | * Configures the non-real-time registers of a Navigator Subsystem ring. | ||
| 648 | * @hdr: Generic Header | ||
| 649 | * @valid_params: Bitfield defining validity of ring configuration parameters. | ||
| 650 | * The ring configuration fields are not valid, and will not be used for | ||
| 651 | * ring configuration, if their corresponding valid bit is zero. | ||
| 652 | * Valid bit usage: | ||
| 653 | * 0 - Valid bit for @tisci_msg_rm_ring_cfg_req addr_lo | ||
| 654 | * 1 - Valid bit for @tisci_msg_rm_ring_cfg_req addr_hi | ||
| 655 | * 2 - Valid bit for @tisci_msg_rm_ring_cfg_req count | ||
| 656 | * 3 - Valid bit for @tisci_msg_rm_ring_cfg_req mode | ||
| 657 | * 4 - Valid bit for @tisci_msg_rm_ring_cfg_req size | ||
| 658 | * 5 - Valid bit for @tisci_msg_rm_ring_cfg_req order_id | ||
| 659 | * @nav_id: Device ID of Navigator Subsystem from which the ring is allocated | ||
| 660 | * @index: ring index to be configured. | ||
| 661 | * @addr_lo: 32 LSBs of ring base address to be programmed into the ring's | ||
| 662 | * RING_BA_LO register | ||
| 663 | * @addr_hi: 16 MSBs of ring base address to be programmed into the ring's | ||
| 664 | * RING_BA_HI register. | ||
| 665 | * @count: Number of ring elements. Must be even if mode is CREDENTIALS or QM | ||
| 666 | * modes. | ||
| 667 | * @mode: Specifies the mode the ring is to be configured. | ||
| 668 | * @size: Specifies encoded ring element size. To calculate the encoded size use | ||
| 669 | * the formula (log2(size_bytes) - 2), where size_bytes cannot be | ||
| 670 | * greater than 256. | ||
| 671 | * @order_id: Specifies the ring's bus order ID. | ||
| 672 | */ | ||
| 673 | struct ti_sci_msg_rm_ring_cfg_req { | ||
| 674 | struct ti_sci_msg_hdr hdr; | ||
| 675 | u32 valid_params; | ||
| 676 | u16 nav_id; | ||
| 677 | u16 index; | ||
| 678 | u32 addr_lo; | ||
| 679 | u32 addr_hi; | ||
| 680 | u32 count; | ||
| 681 | u8 mode; | ||
| 682 | u8 size; | ||
| 683 | u8 order_id; | ||
| 684 | } __packed; | ||
| 685 | |||
| 686 | /** | ||
| 687 | * struct ti_sci_msg_rm_ring_get_cfg_req - Get RA ring's configuration | ||
| 688 | * | ||
| 689 | * Gets the configuration of the non-real-time register fields of a ring. The | ||
| 690 | * host, or a supervisor of the host, who owns the ring must be the requesting | ||
| 691 | * host. The values of the non-real-time registers are returned in | ||
| 692 | * @ti_sci_msg_rm_ring_get_cfg_resp. | ||
| 693 | * | ||
| 694 | * @hdr: Generic Header | ||
| 695 | * @nav_id: Device ID of Navigator Subsystem from which the ring is allocated | ||
| 696 | * @index: ring index. | ||
| 697 | */ | ||
| 698 | struct ti_sci_msg_rm_ring_get_cfg_req { | ||
| 699 | struct ti_sci_msg_hdr hdr; | ||
| 700 | u16 nav_id; | ||
| 701 | u16 index; | ||
| 702 | } __packed; | ||
| 703 | |||
| 704 | /** | ||
| 705 | * struct ti_sci_msg_rm_ring_get_cfg_resp - Ring get configuration response | ||
| 706 | * | ||
| 707 | * Response received by host processor after RM has handled | ||
| 708 | * @ti_sci_msg_rm_ring_get_cfg_req. The response contains the ring's | ||
| 709 | * non-real-time register values. | ||
| 710 | * | ||
| 711 | * @hdr: Generic Header | ||
| 712 | * @addr_lo: Ring 32 LSBs of base address | ||
| 713 | * @addr_hi: Ring 16 MSBs of base address. | ||
| 714 | * @count: Ring number of elements. | ||
| 715 | * @mode: Ring mode. | ||
| 716 | * @size: encoded Ring element size | ||
| 717 | * @order_id: ing order ID. | ||
| 718 | */ | ||
| 719 | struct ti_sci_msg_rm_ring_get_cfg_resp { | ||
| 720 | struct ti_sci_msg_hdr hdr; | ||
| 721 | u32 addr_lo; | ||
| 722 | u32 addr_hi; | ||
| 723 | u32 count; | ||
| 724 | u8 mode; | ||
| 725 | u8 size; | ||
| 726 | u8 order_id; | ||
| 727 | } __packed; | ||
| 728 | |||
| 729 | /** | ||
| 730 | * struct ti_sci_msg_psil_pair - Pairs a PSI-L source thread to a destination | ||
| 731 | * thread | ||
| 732 | * @hdr: Generic Header | ||
| 733 | * @nav_id: SoC Navigator Subsystem device ID whose PSI-L config proxy is | ||
| 734 | * used to pair the source and destination threads. | ||
| 735 | * @src_thread: PSI-L source thread ID within the PSI-L System thread map. | ||
| 736 | * | ||
| 737 | * UDMAP transmit channels mapped to source threads will have their | ||
| 738 | * TCHAN_THRD_ID register programmed with the destination thread if the pairing | ||
| 739 | * is successful. | ||
| 740 | |||
| 741 | * @dst_thread: PSI-L destination thread ID within the PSI-L System thread map. | ||
| 742 | * PSI-L destination threads start at index 0x8000. The request is NACK'd if | ||
| 743 | * the destination thread is not greater than or equal to 0x8000. | ||
| 744 | * | ||
| 745 | * UDMAP receive channels mapped to destination threads will have their | ||
| 746 | * RCHAN_THRD_ID register programmed with the source thread if the pairing | ||
| 747 | * is successful. | ||
| 748 | * | ||
| 749 | * Request type is TI_SCI_MSG_RM_PSIL_PAIR, response is a generic ACK or NACK | ||
| 750 | * message. | ||
| 751 | */ | ||
| 752 | struct ti_sci_msg_psil_pair { | ||
| 753 | struct ti_sci_msg_hdr hdr; | ||
| 754 | u32 nav_id; | ||
| 755 | u32 src_thread; | ||
| 756 | u32 dst_thread; | ||
| 757 | } __packed; | ||
| 758 | |||
| 759 | /** | ||
| 760 | * struct ti_sci_msg_psil_unpair - Unpairs a PSI-L source thread from a | ||
| 761 | * destination thread | ||
| 762 | * @hdr: Generic Header | ||
| 763 | * @nav_id: SoC Navigator Subsystem device ID whose PSI-L config proxy is | ||
| 764 | * used to unpair the source and destination threads. | ||
| 765 | * @src_thread: PSI-L source thread ID within the PSI-L System thread map. | ||
| 766 | * | ||
| 767 | * UDMAP transmit channels mapped to source threads will have their | ||
| 768 | * TCHAN_THRD_ID register cleared if the unpairing is successful. | ||
| 769 | * | ||
| 770 | * @dst_thread: PSI-L destination thread ID within the PSI-L System thread map. | ||
| 771 | * PSI-L destination threads start at index 0x8000. The request is NACK'd if | ||
| 772 | * the destination thread is not greater than or equal to 0x8000. | ||
| 773 | * | ||
| 774 | * UDMAP receive channels mapped to destination threads will have their | ||
| 775 | * RCHAN_THRD_ID register cleared if the unpairing is successful. | ||
| 776 | * | ||
| 777 | * Request type is TI_SCI_MSG_RM_PSIL_UNPAIR, response is a generic ACK or NACK | ||
| 778 | * message. | ||
| 779 | */ | ||
| 780 | struct ti_sci_msg_psil_unpair { | ||
| 781 | struct ti_sci_msg_hdr hdr; | ||
| 782 | u32 nav_id; | ||
| 783 | u32 src_thread; | ||
| 784 | u32 dst_thread; | ||
| 785 | } __packed; | ||
| 786 | |||
| 787 | /** | ||
| 788 | * struct ti_sci_msg_udmap_rx_flow_cfg - UDMAP receive flow configuration | ||
| 789 | * message | ||
| 790 | * @hdr: Generic Header | ||
| 791 | * @nav_id: SoC Navigator Subsystem device ID from which the receive flow is | ||
| 792 | * allocated | ||
| 793 | * @flow_index: UDMAP receive flow index for non-optional configuration. | ||
| 794 | * @rx_ch_index: Specifies the index of the receive channel using the flow_index | ||
| 795 | * @rx_einfo_present: UDMAP receive flow extended packet info present. | ||
| 796 | * @rx_psinfo_present: UDMAP receive flow PS words present. | ||
| 797 | * @rx_error_handling: UDMAP receive flow error handling configuration. Valid | ||
| 798 | * values are TI_SCI_RM_UDMAP_RX_FLOW_ERR_DROP/RETRY. | ||
| 799 | * @rx_desc_type: UDMAP receive flow descriptor type. It can be one of | ||
| 800 | * TI_SCI_RM_UDMAP_RX_FLOW_DESC_HOST/MONO. | ||
| 801 | * @rx_sop_offset: UDMAP receive flow start of packet offset. | ||
| 802 | * @rx_dest_qnum: UDMAP receive flow destination queue number. | ||
| 803 | * @rx_ps_location: UDMAP receive flow PS words location. | ||
| 804 | * 0 - end of packet descriptor | ||
| 805 | * 1 - Beginning of the data buffer | ||
| 806 | * @rx_src_tag_hi: UDMAP receive flow source tag high byte constant | ||
| 807 | * @rx_src_tag_lo: UDMAP receive flow source tag low byte constant | ||
| 808 | * @rx_dest_tag_hi: UDMAP receive flow destination tag high byte constant | ||
| 809 | * @rx_dest_tag_lo: UDMAP receive flow destination tag low byte constant | ||
| 810 | * @rx_src_tag_hi_sel: UDMAP receive flow source tag high byte selector | ||
| 811 | * @rx_src_tag_lo_sel: UDMAP receive flow source tag low byte selector | ||
| 812 | * @rx_dest_tag_hi_sel: UDMAP receive flow destination tag high byte selector | ||
| 813 | * @rx_dest_tag_lo_sel: UDMAP receive flow destination tag low byte selector | ||
| 814 | * @rx_size_thresh_en: UDMAP receive flow packet size based free buffer queue | ||
| 815 | * enable. If enabled, the ti_sci_rm_udmap_rx_flow_opt_cfg also need to be | ||
| 816 | * configured and sent. | ||
| 817 | * @rx_fdq0_sz0_qnum: UDMAP receive flow free descriptor queue 0. | ||
| 818 | * @rx_fdq1_qnum: UDMAP receive flow free descriptor queue 1. | ||
| 819 | * @rx_fdq2_qnum: UDMAP receive flow free descriptor queue 2. | ||
| 820 | * @rx_fdq3_qnum: UDMAP receive flow free descriptor queue 3. | ||
| 821 | * | ||
| 822 | * For detailed information on the settings, see the UDMAP section of the TRM. | ||
| 823 | */ | ||
| 824 | struct ti_sci_msg_udmap_rx_flow_cfg { | ||
| 825 | struct ti_sci_msg_hdr hdr; | ||
| 826 | u32 nav_id; | ||
| 827 | u32 flow_index; | ||
| 828 | u32 rx_ch_index; | ||
| 829 | u8 rx_einfo_present; | ||
| 830 | u8 rx_psinfo_present; | ||
| 831 | u8 rx_error_handling; | ||
| 832 | u8 rx_desc_type; | ||
| 833 | u16 rx_sop_offset; | ||
| 834 | u16 rx_dest_qnum; | ||
| 835 | u8 rx_ps_location; | ||
| 836 | u8 rx_src_tag_hi; | ||
| 837 | u8 rx_src_tag_lo; | ||
| 838 | u8 rx_dest_tag_hi; | ||
| 839 | u8 rx_dest_tag_lo; | ||
| 840 | u8 rx_src_tag_hi_sel; | ||
| 841 | u8 rx_src_tag_lo_sel; | ||
| 842 | u8 rx_dest_tag_hi_sel; | ||
| 843 | u8 rx_dest_tag_lo_sel; | ||
| 844 | u8 rx_size_thresh_en; | ||
| 845 | u16 rx_fdq0_sz0_qnum; | ||
| 846 | u16 rx_fdq1_qnum; | ||
| 847 | u16 rx_fdq2_qnum; | ||
| 848 | u16 rx_fdq3_qnum; | ||
| 849 | } __packed; | ||
| 850 | |||
| 851 | /** | ||
| 852 | * struct rm_ti_sci_msg_udmap_rx_flow_opt_cfg - parameters for UDMAP receive | ||
| 853 | * flow optional configuration | ||
| 854 | * @hdr: Generic Header | ||
| 855 | * @nav_id: SoC Navigator Subsystem device ID from which the receive flow is | ||
| 856 | * allocated | ||
| 857 | * @flow_index: UDMAP receive flow index for optional configuration. | ||
| 858 | * @rx_ch_index: Specifies the index of the receive channel using the flow_index | ||
| 859 | * @rx_size_thresh0: UDMAP receive flow packet size threshold 0. | ||
| 860 | * @rx_size_thresh1: UDMAP receive flow packet size threshold 1. | ||
| 861 | * @rx_size_thresh2: UDMAP receive flow packet size threshold 2. | ||
| 862 | * @rx_fdq0_sz1_qnum: UDMAP receive flow free descriptor queue for size | ||
| 863 | * threshold 1. | ||
| 864 | * @rx_fdq0_sz2_qnum: UDMAP receive flow free descriptor queue for size | ||
| 865 | * threshold 2. | ||
| 866 | * @rx_fdq0_sz3_qnum: UDMAP receive flow free descriptor queue for size | ||
| 867 | * threshold 3. | ||
| 868 | * | ||
| 869 | * For detailed information on the settings, see the UDMAP section of the TRM. | ||
| 870 | */ | ||
| 871 | struct rm_ti_sci_msg_udmap_rx_flow_opt_cfg { | ||
| 872 | struct ti_sci_msg_hdr hdr; | ||
| 873 | u32 nav_id; | ||
| 874 | u32 flow_index; | ||
| 875 | u32 rx_ch_index; | ||
| 876 | u16 rx_size_thresh0; | ||
| 877 | u16 rx_size_thresh1; | ||
| 878 | u16 rx_size_thresh2; | ||
| 879 | u16 rx_fdq0_sz1_qnum; | ||
| 880 | u16 rx_fdq0_sz2_qnum; | ||
| 881 | u16 rx_fdq0_sz3_qnum; | ||
| 882 | } __packed; | ||
| 883 | |||
| 884 | /** | ||
| 885 | * Configures a Navigator Subsystem UDMAP transmit channel | ||
| 886 | * | ||
| 887 | * Configures the non-real-time registers of a Navigator Subsystem UDMAP | ||
| 888 | * transmit channel. The channel index must be assigned to the host defined | ||
| 889 | * in the TISCI header via the RM board configuration resource assignment | ||
| 890 | * range list. | ||
| 891 | * | ||
| 892 | * @hdr: Generic Header | ||
| 893 | * | ||
| 894 | * @valid_params: Bitfield defining validity of tx channel configuration | ||
| 895 | * parameters. The tx channel configuration fields are not valid, and will not | ||
| 896 | * be used for ch configuration, if their corresponding valid bit is zero. | ||
| 897 | * Valid bit usage: | ||
| 898 | * 0 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_pause_on_err | ||
| 899 | * 1 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_atype | ||
| 900 | * 2 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_chan_type | ||
| 901 | * 3 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_fetch_size | ||
| 902 | * 4 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::txcq_qnum | ||
| 903 | * 5 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_priority | ||
| 904 | * 6 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_qos | ||
| 905 | * 7 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_orderid | ||
| 906 | * 8 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_sched_priority | ||
| 907 | * 9 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_filt_einfo | ||
| 908 | * 10 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_filt_pswords | ||
| 909 | * 11 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_supr_tdpkt | ||
| 910 | * 12 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_credit_count | ||
| 911 | * 13 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::fdepth | ||
| 912 | * 14 - Valid bit for @ref ti_sci_msg_rm_udmap_tx_ch_cfg::tx_burst_size | ||
| 913 | * | ||
| 914 | * @nav_id: SoC device ID of Navigator Subsystem where tx channel is located | ||
| 915 | * | ||
| 916 | * @index: UDMAP transmit channel index. | ||
| 917 | * | ||
| 918 | * @tx_pause_on_err: UDMAP transmit channel pause on error configuration to | ||
| 919 | * be programmed into the tx_pause_on_err field of the channel's TCHAN_TCFG | ||
| 920 | * register. | ||
| 921 | * | ||
| 922 | * @tx_filt_einfo: UDMAP transmit channel extended packet information passing | ||
| 923 | * configuration to be programmed into the tx_filt_einfo field of the | ||
| 924 | * channel's TCHAN_TCFG register. | ||
| 925 | * | ||
| 926 | * @tx_filt_pswords: UDMAP transmit channel protocol specific word passing | ||
| 927 | * configuration to be programmed into the tx_filt_pswords field of the | ||
| 928 | * channel's TCHAN_TCFG register. | ||
| 929 | * | ||
| 930 | * @tx_atype: UDMAP transmit channel non Ring Accelerator access pointer | ||
| 931 | * interpretation configuration to be programmed into the tx_atype field of | ||
| 932 | * the channel's TCHAN_TCFG register. | ||
| 933 | * | ||
| 934 | * @tx_chan_type: UDMAP transmit channel functional channel type and work | ||
| 935 | * passing mechanism configuration to be programmed into the tx_chan_type | ||
| 936 | * field of the channel's TCHAN_TCFG register. | ||
| 937 | * | ||
| 938 | * @tx_supr_tdpkt: UDMAP transmit channel teardown packet generation suppression | ||
| 939 | * configuration to be programmed into the tx_supr_tdpkt field of the channel's | ||
| 940 | * TCHAN_TCFG register. | ||
| 941 | * | ||
| 942 | * @tx_fetch_size: UDMAP transmit channel number of 32-bit descriptor words to | ||
| 943 | * fetch configuration to be programmed into the tx_fetch_size field of the | ||
| 944 | * channel's TCHAN_TCFG register. The user must make sure to set the maximum | ||
| 945 | * word count that can pass through the channel for any allowed descriptor type. | ||
| 946 | * | ||
| 947 | * @tx_credit_count: UDMAP transmit channel transfer request credit count | ||
| 948 | * configuration to be programmed into the count field of the TCHAN_TCREDIT | ||
| 949 | * register. Specifies how many credits for complete TRs are available. | ||
| 950 | * | ||
| 951 | * @txcq_qnum: UDMAP transmit channel completion queue configuration to be | ||
| 952 | * programmed into the txcq_qnum field of the TCHAN_TCQ register. The specified | ||
| 953 | * completion queue must be assigned to the host, or a subordinate of the host, | ||
| 954 | * requesting configuration of the transmit channel. | ||
| 955 | * | ||
| 956 | * @tx_priority: UDMAP transmit channel transmit priority value to be programmed | ||
| 957 | * into the priority field of the channel's TCHAN_TPRI_CTRL register. | ||
| 958 | * | ||
| 959 | * @tx_qos: UDMAP transmit channel transmit qos value to be programmed into the | ||
| 960 | * qos field of the channel's TCHAN_TPRI_CTRL register. | ||
| 961 | * | ||
| 962 | * @tx_orderid: UDMAP transmit channel bus order id value to be programmed into | ||
| 963 | * the orderid field of the channel's TCHAN_TPRI_CTRL register. | ||
| 964 | * | ||
| 965 | * @fdepth: UDMAP transmit channel FIFO depth configuration to be programmed | ||
| 966 | * into the fdepth field of the TCHAN_TFIFO_DEPTH register. Sets the number of | ||
| 967 | * Tx FIFO bytes which are allowed to be stored for the channel. Check the UDMAP | ||
| 968 | * section of the TRM for restrictions regarding this parameter. | ||
| 969 | * | ||
| 970 | * @tx_sched_priority: UDMAP transmit channel tx scheduling priority | ||
| 971 | * configuration to be programmed into the priority field of the channel's | ||
| 972 | * TCHAN_TST_SCHED register. | ||
| 973 | * | ||
| 974 | * @tx_burst_size: UDMAP transmit channel burst size configuration to be | ||
| 975 | * programmed into the tx_burst_size field of the TCHAN_TCFG register. | ||
| 976 | */ | ||
| 977 | struct ti_sci_msg_rm_udmap_tx_ch_cfg_req { | ||
| 978 | struct ti_sci_msg_hdr hdr; | ||
| 979 | u32 valid_params; | ||
| 980 | u16 nav_id; | ||
| 981 | u16 index; | ||
| 982 | u8 tx_pause_on_err; | ||
| 983 | u8 tx_filt_einfo; | ||
| 984 | u8 tx_filt_pswords; | ||
| 985 | u8 tx_atype; | ||
| 986 | u8 tx_chan_type; | ||
| 987 | u8 tx_supr_tdpkt; | ||
| 988 | u16 tx_fetch_size; | ||
| 989 | u8 tx_credit_count; | ||
| 990 | u16 txcq_qnum; | ||
| 991 | u8 tx_priority; | ||
| 992 | u8 tx_qos; | ||
| 993 | u8 tx_orderid; | ||
| 994 | u16 fdepth; | ||
| 995 | u8 tx_sched_priority; | ||
| 996 | u8 tx_burst_size; | ||
| 997 | } __packed; | ||
| 998 | |||
| 999 | /** | ||
| 1000 | * Configures a Navigator Subsystem UDMAP receive channel | ||
| 1001 | * | ||
| 1002 | * Configures the non-real-time registers of a Navigator Subsystem UDMAP | ||
| 1003 | * receive channel. The channel index must be assigned to the host defined | ||
| 1004 | * in the TISCI header via the RM board configuration resource assignment | ||
| 1005 | * range list. | ||
| 1006 | * | ||
| 1007 | * @hdr: Generic Header | ||
| 1008 | * | ||
| 1009 | * @valid_params: Bitfield defining validity of rx channel configuration | ||
| 1010 | * parameters. | ||
| 1011 | * The rx channel configuration fields are not valid, and will not be used for | ||
| 1012 | * ch configuration, if their corresponding valid bit is zero. | ||
| 1013 | * Valid bit usage: | ||
| 1014 | * 0 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_pause_on_err | ||
| 1015 | * 1 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_atype | ||
| 1016 | * 2 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_chan_type | ||
| 1017 | * 3 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_fetch_size | ||
| 1018 | * 4 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rxcq_qnum | ||
| 1019 | * 5 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_priority | ||
| 1020 | * 6 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_qos | ||
| 1021 | * 7 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_orderid | ||
| 1022 | * 8 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_sched_priority | ||
| 1023 | * 9 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::flowid_start | ||
| 1024 | * 10 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::flowid_cnt | ||
| 1025 | * 11 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_ignore_short | ||
| 1026 | * 12 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_ignore_long | ||
| 1027 | * 14 - Valid bit for @ti_sci_msg_rm_udmap_rx_ch_cfg_req::rx_burst_size | ||
| 1028 | * | ||
| 1029 | * @nav_id: SoC device ID of Navigator Subsystem where rx channel is located | ||
| 1030 | * | ||
| 1031 | * @index: UDMAP receive channel index. | ||
| 1032 | * | ||
| 1033 | * @rx_fetch_size: UDMAP receive channel number of 32-bit descriptor words to | ||
| 1034 | * fetch configuration to be programmed into the rx_fetch_size field of the | ||
| 1035 | * channel's RCHAN_RCFG register. | ||
| 1036 | * | ||
| 1037 | * @rxcq_qnum: UDMAP receive channel completion queue configuration to be | ||
| 1038 | * programmed into the rxcq_qnum field of the RCHAN_RCQ register. | ||
| 1039 | * The specified completion queue must be assigned to the host, or a subordinate | ||
| 1040 | * of the host, requesting configuration of the receive channel. | ||
| 1041 | * | ||
| 1042 | * @rx_priority: UDMAP receive channel receive priority value to be programmed | ||
| 1043 | * into the priority field of the channel's RCHAN_RPRI_CTRL register. | ||
| 1044 | * | ||
| 1045 | * @rx_qos: UDMAP receive channel receive qos value to be programmed into the | ||
| 1046 | * qos field of the channel's RCHAN_RPRI_CTRL register. | ||
| 1047 | * | ||
| 1048 | * @rx_orderid: UDMAP receive channel bus order id value to be programmed into | ||
| 1049 | * the orderid field of the channel's RCHAN_RPRI_CTRL register. | ||
| 1050 | * | ||
| 1051 | * @rx_sched_priority: UDMAP receive channel rx scheduling priority | ||
| 1052 | * configuration to be programmed into the priority field of the channel's | ||
| 1053 | * RCHAN_RST_SCHED register. | ||
| 1054 | * | ||
| 1055 | * @flowid_start: UDMAP receive channel additional flows starting index | ||
| 1056 | * configuration to program into the flow_start field of the RCHAN_RFLOW_RNG | ||
| 1057 | * register. Specifies the starting index for flow IDs the receive channel is to | ||
| 1058 | * make use of beyond the default flow. flowid_start and @ref flowid_cnt must be | ||
| 1059 | * set as valid and configured together. The starting flow ID set by | ||
| 1060 | * @ref flowid_cnt must be a flow index within the Navigator Subsystem's subset | ||
| 1061 | * of flows beyond the default flows statically mapped to receive channels. | ||
| 1062 | * The additional flows must be assigned to the host, or a subordinate of the | ||
| 1063 | * host, requesting configuration of the receive channel. | ||
| 1064 | * | ||
| 1065 | * @flowid_cnt: UDMAP receive channel additional flows count configuration to | ||
| 1066 | * program into the flowid_cnt field of the RCHAN_RFLOW_RNG register. | ||
| 1067 | * This field specifies how many flow IDs are in the additional contiguous range | ||
| 1068 | * of legal flow IDs for the channel. @ref flowid_start and flowid_cnt must be | ||
| 1069 | * set as valid and configured together. Disabling the valid_params field bit | ||
| 1070 | * for flowid_cnt indicates no flow IDs other than the default are to be | ||
| 1071 | * allocated and used by the receive channel. @ref flowid_start plus flowid_cnt | ||
| 1072 | * cannot be greater than the number of receive flows in the receive channel's | ||
| 1073 | * Navigator Subsystem. The additional flows must be assigned to the host, or a | ||
| 1074 | * subordinate of the host, requesting configuration of the receive channel. | ||
| 1075 | * | ||
| 1076 | * @rx_pause_on_err: UDMAP receive channel pause on error configuration to be | ||
| 1077 | * programmed into the rx_pause_on_err field of the channel's RCHAN_RCFG | ||
| 1078 | * register. | ||
| 1079 | * | ||
| 1080 | * @rx_atype: UDMAP receive channel non Ring Accelerator access pointer | ||
| 1081 | * interpretation configuration to be programmed into the rx_atype field of the | ||
| 1082 | * channel's RCHAN_RCFG register. | ||
| 1083 | * | ||
| 1084 | * @rx_chan_type: UDMAP receive channel functional channel type and work passing | ||
| 1085 | * mechanism configuration to be programmed into the rx_chan_type field of the | ||
| 1086 | * channel's RCHAN_RCFG register. | ||
| 1087 | * | ||
| 1088 | * @rx_ignore_short: UDMAP receive channel short packet treatment configuration | ||
| 1089 | * to be programmed into the rx_ignore_short field of the RCHAN_RCFG register. | ||
| 1090 | * | ||
| 1091 | * @rx_ignore_long: UDMAP receive channel long packet treatment configuration to | ||
| 1092 | * be programmed into the rx_ignore_long field of the RCHAN_RCFG register. | ||
| 1093 | * | ||
| 1094 | * @rx_burst_size: UDMAP receive channel burst size configuration to be | ||
| 1095 | * programmed into the rx_burst_size field of the RCHAN_RCFG register. | ||
| 1096 | */ | ||
| 1097 | struct ti_sci_msg_rm_udmap_rx_ch_cfg_req { | ||
| 1098 | struct ti_sci_msg_hdr hdr; | ||
| 1099 | u32 valid_params; | ||
| 1100 | u16 nav_id; | ||
| 1101 | u16 index; | ||
| 1102 | u16 rx_fetch_size; | ||
| 1103 | u16 rxcq_qnum; | ||
| 1104 | u8 rx_priority; | ||
| 1105 | u8 rx_qos; | ||
| 1106 | u8 rx_orderid; | ||
| 1107 | u8 rx_sched_priority; | ||
| 1108 | u16 flowid_start; | ||
| 1109 | u16 flowid_cnt; | ||
| 1110 | u8 rx_pause_on_err; | ||
| 1111 | u8 rx_atype; | ||
| 1112 | u8 rx_chan_type; | ||
| 1113 | u8 rx_ignore_short; | ||
| 1114 | u8 rx_ignore_long; | ||
| 1115 | u8 rx_burst_size; | ||
| 1116 | } __packed; | ||
| 1117 | |||
| 1118 | /** | ||
| 1119 | * Configures a Navigator Subsystem UDMAP receive flow | ||
| 1120 | * | ||
| 1121 | * Configures a Navigator Subsystem UDMAP receive flow's registers. | ||
| 1122 | * Configuration does not include the flow registers which handle size-based | ||
| 1123 | * free descriptor queue routing. | ||
| 1124 | * | ||
| 1125 | * The flow index must be assigned to the host defined in the TISCI header via | ||
| 1126 | * the RM board configuration resource assignment range list. | ||
| 1127 | * | ||
| 1128 | * @hdr: Standard TISCI header | ||
| 1129 | * | ||
| 1130 | * @valid_params | ||
| 1131 | * Bitfield defining validity of rx flow configuration parameters. The | ||
| 1132 | * rx flow configuration fields are not valid, and will not be used for flow | ||
| 1133 | * configuration, if their corresponding valid bit is zero. Valid bit usage: | ||
| 1134 | * 0 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_einfo_present | ||
| 1135 | * 1 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_psinfo_present | ||
| 1136 | * 2 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_error_handling | ||
| 1137 | * 3 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_desc_type | ||
| 1138 | * 4 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_sop_offset | ||
| 1139 | * 5 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_dest_qnum | ||
| 1140 | * 6 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_src_tag_hi | ||
| 1141 | * 7 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_src_tag_lo | ||
| 1142 | * 8 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_dest_tag_hi | ||
| 1143 | * 9 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_dest_tag_lo | ||
| 1144 | * 10 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_src_tag_hi_sel | ||
| 1145 | * 11 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_src_tag_lo_sel | ||
| 1146 | * 12 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_dest_tag_hi_sel | ||
| 1147 | * 13 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_dest_tag_lo_sel | ||
| 1148 | * 14 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_fdq0_sz0_qnum | ||
| 1149 | * 15 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_fdq1_sz0_qnum | ||
| 1150 | * 16 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_fdq2_sz0_qnum | ||
| 1151 | * 17 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_fdq3_sz0_qnum | ||
| 1152 | * 18 - Valid bit for @tisci_msg_rm_udmap_flow_cfg_req::rx_ps_location | ||
| 1153 | * | ||
| 1154 | * @nav_id: SoC device ID of Navigator Subsystem from which the receive flow is | ||
| 1155 | * allocated | ||
| 1156 | * | ||
| 1157 | * @flow_index: UDMAP receive flow index for non-optional configuration. | ||
| 1158 | * | ||
| 1159 | * @rx_einfo_present: | ||
| 1160 | * UDMAP receive flow extended packet info present configuration to be | ||
| 1161 | * programmed into the rx_einfo_present field of the flow's RFLOW_RFA register. | ||
| 1162 | * | ||
| 1163 | * @rx_psinfo_present: | ||
| 1164 | * UDMAP receive flow PS words present configuration to be programmed into the | ||
| 1165 | * rx_psinfo_present field of the flow's RFLOW_RFA register. | ||
| 1166 | * | ||
| 1167 | * @rx_error_handling: | ||
| 1168 | * UDMAP receive flow error handling configuration to be programmed into the | ||
| 1169 | * rx_error_handling field of the flow's RFLOW_RFA register. | ||
| 1170 | * | ||
| 1171 | * @rx_desc_type: | ||
| 1172 | * UDMAP receive flow descriptor type configuration to be programmed into the | ||
| 1173 | * rx_desc_type field field of the flow's RFLOW_RFA register. | ||
| 1174 | * | ||
| 1175 | * @rx_sop_offset: | ||
| 1176 | * UDMAP receive flow start of packet offset configuration to be programmed | ||
| 1177 | * into the rx_sop_offset field of the RFLOW_RFA register. See the UDMAP | ||
| 1178 | * section of the TRM for more information on this setting. Valid values for | ||
| 1179 | * this field are 0-255 bytes. | ||
| 1180 | * | ||
| 1181 | * @rx_dest_qnum: | ||
| 1182 | * UDMAP receive flow destination queue configuration to be programmed into the | ||
| 1183 | * rx_dest_qnum field of the flow's RFLOW_RFA register. The specified | ||
| 1184 | * destination queue must be valid within the Navigator Subsystem and must be | ||
| 1185 | * owned by the host, or a subordinate of the host, requesting allocation and | ||
| 1186 | * configuration of the receive flow. | ||
| 1187 | * | ||
| 1188 | * @rx_src_tag_hi: | ||
| 1189 | * UDMAP receive flow source tag high byte constant configuration to be | ||
| 1190 | * programmed into the rx_src_tag_hi field of the flow's RFLOW_RFB register. | ||
| 1191 | * See the UDMAP section of the TRM for more information on this setting. | ||
| 1192 | * | ||
| 1193 | * @rx_src_tag_lo: | ||
| 1194 | * UDMAP receive flow source tag low byte constant configuration to be | ||
| 1195 | * programmed into the rx_src_tag_lo field of the flow's RFLOW_RFB register. | ||
| 1196 | * See the UDMAP section of the TRM for more information on this setting. | ||
| 1197 | * | ||
| 1198 | * @rx_dest_tag_hi: | ||
| 1199 | * UDMAP receive flow destination tag high byte constant configuration to be | ||
| 1200 | * programmed into the rx_dest_tag_hi field of the flow's RFLOW_RFB register. | ||
| 1201 | * See the UDMAP section of the TRM for more information on this setting. | ||
| 1202 | * | ||
| 1203 | * @rx_dest_tag_lo: | ||
| 1204 | * UDMAP receive flow destination tag low byte constant configuration to be | ||
| 1205 | * programmed into the rx_dest_tag_lo field of the flow's RFLOW_RFB register. | ||
| 1206 | * See the UDMAP section of the TRM for more information on this setting. | ||
| 1207 | * | ||
| 1208 | * @rx_src_tag_hi_sel: | ||
| 1209 | * UDMAP receive flow source tag high byte selector configuration to be | ||
| 1210 | * programmed into the rx_src_tag_hi_sel field of the RFLOW_RFC register. See | ||
| 1211 | * the UDMAP section of the TRM for more information on this setting. | ||
| 1212 | * | ||
| 1213 | * @rx_src_tag_lo_sel: | ||
| 1214 | * UDMAP receive flow source tag low byte selector configuration to be | ||
| 1215 | * programmed into the rx_src_tag_lo_sel field of the RFLOW_RFC register. See | ||
| 1216 | * the UDMAP section of the TRM for more information on this setting. | ||
| 1217 | * | ||
| 1218 | * @rx_dest_tag_hi_sel: | ||
| 1219 | * UDMAP receive flow destination tag high byte selector configuration to be | ||
| 1220 | * programmed into the rx_dest_tag_hi_sel field of the RFLOW_RFC register. See | ||
| 1221 | * the UDMAP section of the TRM for more information on this setting. | ||
| 1222 | * | ||
| 1223 | * @rx_dest_tag_lo_sel: | ||
| 1224 | * UDMAP receive flow destination tag low byte selector configuration to be | ||
| 1225 | * programmed into the rx_dest_tag_lo_sel field of the RFLOW_RFC register. See | ||
| 1226 | * the UDMAP section of the TRM for more information on this setting. | ||
| 1227 | * | ||
| 1228 | * @rx_fdq0_sz0_qnum: | ||
| 1229 | * UDMAP receive flow free descriptor queue 0 configuration to be programmed | ||
| 1230 | * into the rx_fdq0_sz0_qnum field of the flow's RFLOW_RFD register. See the | ||
| 1231 | * UDMAP section of the TRM for more information on this setting. The specified | ||
| 1232 | * free queue must be valid within the Navigator Subsystem and must be owned | ||
| 1233 | * by the host, or a subordinate of the host, requesting allocation and | ||
| 1234 | * configuration of the receive flow. | ||
| 1235 | * | ||
| 1236 | * @rx_fdq1_qnum: | ||
| 1237 | * UDMAP receive flow free descriptor queue 1 configuration to be programmed | ||
| 1238 | * into the rx_fdq1_qnum field of the flow's RFLOW_RFD register. See the | ||
| 1239 | * UDMAP section of the TRM for more information on this setting. The specified | ||
| 1240 | * free queue must be valid within the Navigator Subsystem and must be owned | ||
| 1241 | * by the host, or a subordinate of the host, requesting allocation and | ||
| 1242 | * configuration of the receive flow. | ||
| 1243 | * | ||
| 1244 | * @rx_fdq2_qnum: | ||
| 1245 | * UDMAP receive flow free descriptor queue 2 configuration to be programmed | ||
| 1246 | * into the rx_fdq2_qnum field of the flow's RFLOW_RFE register. See the | ||
| 1247 | * UDMAP section of the TRM for more information on this setting. The specified | ||
| 1248 | * free queue must be valid within the Navigator Subsystem and must be owned | ||
| 1249 | * by the host, or a subordinate of the host, requesting allocation and | ||
| 1250 | * configuration of the receive flow. | ||
| 1251 | * | ||
| 1252 | * @rx_fdq3_qnum: | ||
| 1253 | * UDMAP receive flow free descriptor queue 3 configuration to be programmed | ||
| 1254 | * into the rx_fdq3_qnum field of the flow's RFLOW_RFE register. See the | ||
| 1255 | * UDMAP section of the TRM for more information on this setting. The specified | ||
| 1256 | * free queue must be valid within the Navigator Subsystem and must be owned | ||
| 1257 | * by the host, or a subordinate of the host, requesting allocation and | ||
| 1258 | * configuration of the receive flow. | ||
| 1259 | * | ||
| 1260 | * @rx_ps_location: | ||
| 1261 | * UDMAP receive flow PS words location configuration to be programmed into the | ||
| 1262 | * rx_ps_location field of the flow's RFLOW_RFA register. | ||
| 1263 | */ | ||
| 1264 | struct ti_sci_msg_rm_udmap_flow_cfg_req { | ||
| 1265 | struct ti_sci_msg_hdr hdr; | ||
| 1266 | u32 valid_params; | ||
| 1267 | u16 nav_id; | ||
| 1268 | u16 flow_index; | ||
| 1269 | u8 rx_einfo_present; | ||
| 1270 | u8 rx_psinfo_present; | ||
| 1271 | u8 rx_error_handling; | ||
| 1272 | u8 rx_desc_type; | ||
| 1273 | u16 rx_sop_offset; | ||
| 1274 | u16 rx_dest_qnum; | ||
| 1275 | u8 rx_src_tag_hi; | ||
| 1276 | u8 rx_src_tag_lo; | ||
| 1277 | u8 rx_dest_tag_hi; | ||
| 1278 | u8 rx_dest_tag_lo; | ||
| 1279 | u8 rx_src_tag_hi_sel; | ||
| 1280 | u8 rx_src_tag_lo_sel; | ||
| 1281 | u8 rx_dest_tag_hi_sel; | ||
| 1282 | u8 rx_dest_tag_lo_sel; | ||
| 1283 | u16 rx_fdq0_sz0_qnum; | ||
| 1284 | u16 rx_fdq1_qnum; | ||
| 1285 | u16 rx_fdq2_qnum; | ||
| 1286 | u16 rx_fdq3_qnum; | ||
| 1287 | u8 rx_ps_location; | ||
| 1288 | } __packed; | ||
| 1289 | |||
| 1290 | /** | ||
| 1291 | * struct ti_sci_msg_req_proc_request - Request a processor | ||
| 1292 | * @hdr: Generic Header | ||
| 1293 | * @processor_id: ID of processor being requested | ||
| 1294 | * | ||
| 1295 | * Request type is TI_SCI_MSG_PROC_REQUEST, response is a generic ACK/NACK | ||
| 1296 | * message. | ||
| 1297 | */ | ||
| 1298 | struct ti_sci_msg_req_proc_request { | ||
| 1299 | struct ti_sci_msg_hdr hdr; | ||
| 1300 | u8 processor_id; | ||
| 1301 | } __packed; | ||
| 1302 | |||
| 1303 | /** | ||
| 1304 | * struct ti_sci_msg_req_proc_release - Release a processor | ||
| 1305 | * @hdr: Generic Header | ||
| 1306 | * @processor_id: ID of processor being released | ||
| 1307 | * | ||
| 1308 | * Request type is TI_SCI_MSG_PROC_RELEASE, response is a generic ACK/NACK | ||
| 1309 | * message. | ||
| 1310 | */ | ||
| 1311 | struct ti_sci_msg_req_proc_release { | ||
| 1312 | struct ti_sci_msg_hdr hdr; | ||
| 1313 | u8 processor_id; | ||
| 1314 | } __packed; | ||
| 1315 | |||
| 1316 | /** | ||
| 1317 | * struct ti_sci_msg_req_proc_handover - Handover a processor to a host | ||
| 1318 | * @hdr: Generic Header | ||
| 1319 | * @processor_id: ID of processor being handed over | ||
| 1320 | * @host_id: Host ID the control needs to be transferred to | ||
| 1321 | * | ||
| 1322 | * Request type is TI_SCI_MSG_PROC_HANDOVER, response is a generic ACK/NACK | ||
| 1323 | * message. | ||
| 1324 | */ | ||
| 1325 | struct ti_sci_msg_req_proc_handover { | ||
| 1326 | struct ti_sci_msg_hdr hdr; | ||
| 1327 | u8 processor_id; | ||
| 1328 | u8 host_id; | ||
| 1329 | } __packed; | ||
| 1330 | |||
| 1331 | /* Boot Vector masks */ | ||
| 1332 | #define TI_SCI_ADDR_LOW_MASK GENMASK_ULL(31, 0) | ||
| 1333 | #define TI_SCI_ADDR_HIGH_MASK GENMASK_ULL(63, 32) | ||
| 1334 | #define TI_SCI_ADDR_HIGH_SHIFT 32 | ||
| 1335 | |||
| 1336 | /** | ||
| 1337 | * struct ti_sci_msg_req_set_config - Set Processor boot configuration | ||
| 1338 | * @hdr: Generic Header | ||
| 1339 | * @processor_id: ID of processor being configured | ||
| 1340 | * @bootvector_low: Lower 32 bit address (Little Endian) of boot vector | ||
| 1341 | * @bootvector_high: Higher 32 bit address (Little Endian) of boot vector | ||
| 1342 | * @config_flags_set: Optional Processor specific Config Flags to set. | ||
| 1343 | * Setting a bit here implies the corresponding mode | ||
| 1344 | * will be set | ||
| 1345 | * @config_flags_clear: Optional Processor specific Config Flags to clear. | ||
| 1346 | * Setting a bit here implies the corresponding mode | ||
| 1347 | * will be cleared | ||
| 1348 | * | ||
| 1349 | * Request type is TI_SCI_MSG_PROC_HANDOVER, response is a generic ACK/NACK | ||
| 1350 | * message. | ||
| 1351 | */ | ||
| 1352 | struct ti_sci_msg_req_set_config { | ||
| 1353 | struct ti_sci_msg_hdr hdr; | ||
| 1354 | u8 processor_id; | ||
| 1355 | u32 bootvector_low; | ||
| 1356 | u32 bootvector_high; | ||
| 1357 | u32 config_flags_set; | ||
| 1358 | u32 config_flags_clear; | ||
| 1359 | } __packed; | ||
| 1360 | |||
| 1361 | /** | ||
| 1362 | * struct ti_sci_msg_req_set_ctrl - Set Processor boot control flags | ||
| 1363 | * @hdr: Generic Header | ||
| 1364 | * @processor_id: ID of processor being configured | ||
| 1365 | * @control_flags_set: Optional Processor specific Control Flags to set. | ||
| 1366 | * Setting a bit here implies the corresponding mode | ||
| 1367 | * will be set | ||
| 1368 | * @control_flags_clear:Optional Processor specific Control Flags to clear. | ||
| 1369 | * Setting a bit here implies the corresponding mode | ||
| 1370 | * will be cleared | ||
| 1371 | * | ||
| 1372 | * Request type is TI_SCI_MSG_SET_CTRL, response is a generic ACK/NACK | ||
| 1373 | * message. | ||
| 1374 | */ | ||
| 1375 | struct ti_sci_msg_req_set_ctrl { | ||
| 1376 | struct ti_sci_msg_hdr hdr; | ||
| 1377 | u8 processor_id; | ||
| 1378 | u32 control_flags_set; | ||
| 1379 | u32 control_flags_clear; | ||
| 1380 | } __packed; | ||
| 1381 | |||
| 1382 | /** | ||
| 1383 | * struct ti_sci_msg_req_get_status - Processor boot status request | ||
| 1384 | * @hdr: Generic Header | ||
| 1385 | * @processor_id: ID of processor whose status is being requested | ||
| 1386 | * | ||
| 1387 | * Request type is TI_SCI_MSG_GET_STATUS, response is an appropriate | ||
| 1388 | * message, or NACK in case of inability to satisfy request. | ||
| 1389 | */ | ||
| 1390 | struct ti_sci_msg_req_get_status { | ||
| 1391 | struct ti_sci_msg_hdr hdr; | ||
| 1392 | u8 processor_id; | ||
| 1393 | } __packed; | ||
| 1394 | |||
| 1395 | /** | ||
| 1396 | * struct ti_sci_msg_resp_get_status - Processor boot status response | ||
| 1397 | * @hdr: Generic Header | ||
| 1398 | * @processor_id: ID of processor whose status is returned | ||
| 1399 | * @bootvector_low: Lower 32 bit address (Little Endian) of boot vector | ||
| 1400 | * @bootvector_high: Higher 32 bit address (Little Endian) of boot vector | ||
| 1401 | * @config_flags: Optional Processor specific Config Flags set currently | ||
| 1402 | * @control_flags: Optional Processor specific Control Flags set currently | ||
| 1403 | * @status_flags: Optional Processor specific Status Flags set currently | ||
| 1404 | * | ||
| 1405 | * Response structure to a TI_SCI_MSG_GET_STATUS request. | ||
| 1406 | */ | ||
| 1407 | struct ti_sci_msg_resp_get_status { | ||
| 1408 | struct ti_sci_msg_hdr hdr; | ||
| 1409 | u8 processor_id; | ||
| 1410 | u32 bootvector_low; | ||
| 1411 | u32 bootvector_high; | ||
| 1412 | u32 config_flags; | ||
| 1413 | u32 control_flags; | ||
| 1414 | u32 status_flags; | ||
| 1415 | } __packed; | ||
| 1416 | |||
| 607 | #endif /* __TI_SCI_H */ | 1417 | #endif /* __TI_SCI_H */ |
| @@ -18,6 +18,50 @@ struct scmi_sensors { · 17 unmodified lines | |||
| 18 | const struct scmi_sensor_info **info[hwmon_max]; | 18 | const struct scmi_sensor_info **info[hwmon_max]; |
| 19 | }; | 19 | }; |
| 20 | 20 | ||
| 21 | static inline u64 __pow10(u8 x) | ||
| 22 | { | ||
| 23 | u64 r = 1; | ||
| 24 | |||
| 25 | while (x--) | ||
| 26 | r *= 10; | ||
| 27 | |||
| 28 | return r; | ||
| 29 | } | ||
| 30 | |||
| 31 | static int scmi_hwmon_scale(const struct scmi_sensor_info *sensor, u64 *value) | ||
| 32 | { | ||
| 33 | s8 scale = sensor->scale; | ||
| 34 | u64 f; | ||
| 35 | |||
| 36 | switch (sensor->type) { | ||
| 37 | case TEMPERATURE_C: | ||
| 38 | case VOLTAGE: | ||
| 39 | case CURRENT: | ||
| 40 | scale += 3; | ||
| 41 | break; | ||
| 42 | case POWER: | ||
| 43 | case ENERGY: | ||
| 44 | scale += 6; | ||
| 45 | break; | ||
| 46 | default: | ||
| 47 | break; | ||
| 48 | } | ||
| 49 | |||
| 50 | if (scale == 0) | ||
| 51 | return 0; | ||
| 52 | |||
| 53 | if (abs(scale) > 19) | ||
| 54 | return -E2BIG; | ||
| 55 | |||
| 56 | f = __pow10(abs(scale)); | ||
| 57 | if (scale > 0) | ||
| 58 | *value *= f; | ||
| 59 | else | ||
| 60 | *value = div64_u64(*value, f); | ||
| 61 | |||
| 62 | return 0; | ||
| 63 | } | ||
| 64 | |||
| 21 | static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, | 65 | static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, |
| 22 | u32 attr, int channel, long *val) | 66 | u32 attr, int channel, long *val) |
| 23 | { | 67 | { |
| @@ -29,6 +73,10 @@ static int scmi_hwmon_read(struct device *dev, enum hwmon_sensor_types type, · 5 unmodified lines | |||
| 29 | 73 | ||
| 30 | sensor = *(scmi_sensors->info[type] + channel); | 74 | sensor = *(scmi_sensors->info[type] + channel); |
| 31 | ret = h->sensor_ops->reading_get(h, sensor->id, false, &value); | 75 | ret = h->sensor_ops->reading_get(h, sensor->id, false, &value); |
| 76 | if (ret) | ||
| 77 | return ret; | ||
| 78 | |||
| 79 | ret = scmi_hwmon_scale(sensor, &value); | ||
| 32 | if (!ret) | 80 | if (!ret) |
| 33 | *val = value; | 81 | *val = value; |
| 34 | 82 | ||
| @@ -8,6 +8,14 @@ menuconfig MEMORY · 7 unmodified lines | |||
| 8 | 8 | ||
| 9 | if MEMORY | 9 | if MEMORY |
| 10 | 10 | ||
| 11 | config DDR | ||
| 12 | bool | ||
| 13 | help | ||
| 14 | Data from JEDEC specs for DDR SDRAM memories, | ||
| 15 | particularly the AC timing parameters and addressing | ||
| 16 | information. This data is useful for drivers handling | ||
| 17 | DDR SDRAM controllers. | ||
| 18 | |||
| 11 | config ARM_PL172_MPMC | 19 | config ARM_PL172_MPMC |
| 12 | tristate "ARM PL172 MPMC driver" | 20 | tristate "ARM PL172 MPMC driver" |
| 13 | depends on ARM_AMBA && OF | 21 | depends on ARM_AMBA && OF |
| @@ -3,6 +3,7 @@ · 2 unmodified lines | |||
| 3 | # Makefile for memory devices | 3 | # Makefile for memory devices |
| 4 | # | 4 | # |
| 5 | 5 | ||
| 6 | obj-$(CONFIG_DDR) += jedec_ddr_data.o | ||
| 6 | ifeq ($(CONFIG_DDR),y) | 7 | ifeq ($(CONFIG_DDR),y) |
| 7 | obj-$(CONFIG_OF) += of_memory.o | 8 | obj-$(CONFIG_OF) += of_memory.o |
| 8 | endif | 9 | endif |
| @@ -33,10 +33,10 @@ · 32 unmodified lines | |||
| 33 | #include <linux/io.h> | 33 | #include <linux/io.h> |
| 34 | #include <linux/module.h> | 34 | #include <linux/module.h> |
| 35 | #include <linux/of_address.h> | 35 | #include <linux/of_address.h> |
| 36 | #include <linux/of_device.h> | ||
| 36 | #include <linux/platform_device.h> | 37 | #include <linux/platform_device.h> |
| 37 | 38 | ||
| 38 | #define DRVNAME "brcmstb-dpfe" | 39 | #define DRVNAME "brcmstb-dpfe" |
| 39 | #define FIRMWARE_NAME "dpfe.bin" | ||
| 40 | 40 | ||
| 41 | /* DCPU register offsets */ | 41 | /* DCPU register offsets */ |
| 42 | #define REG_DCPU_RESET 0x0 | 42 | #define REG_DCPU_RESET 0x0 |
| @@ -59,6 +59,7 @@ · 16 unmodified lines | |||
| 59 | #define DRAM_INFO_MR4 0x4 | 59 | #define DRAM_INFO_MR4 0x4 |
| 60 | #define DRAM_INFO_ERROR 0x8 | 60 | #define DRAM_INFO_ERROR 0x8 |
| 61 | #define DRAM_INFO_MR4_MASK 0xff | 61 | #define DRAM_INFO_MR4_MASK 0xff |
| 62 | #define DRAM_INFO_MR4_SHIFT 24 /* We need to look at byte 3 */ | ||
| 62 | 63 | ||
| 63 | /* DRAM MR4 Offsets & Masks */ | 64 | /* DRAM MR4 Offsets & Masks */ |
| 64 | #define DRAM_MR4_REFRESH 0x0 /* Refresh rate */ | 65 | #define DRAM_MR4_REFRESH 0x0 /* Refresh rate */ |
| @@ -73,13 +74,23 @@ · 8 unmodified lines | |||
| 73 | #define DRAM_MR4_TH_OFFS_MASK 0x3 | 74 | #define DRAM_MR4_TH_OFFS_MASK 0x3 |
| 74 | #define DRAM_MR4_TUF_MASK 0x1 | 75 | #define DRAM_MR4_TUF_MASK 0x1 |
| 75 | 76 | ||
| 76 | /* DRAM Vendor Offsets & Masks */ | 77 | /* DRAM Vendor Offsets & Masks (API v2) */ |
| 77 | #define DRAM_VENDOR_MR5 0x0 | 78 | #define DRAM_VENDOR_MR5 0x0 |
| 78 | #define DRAM_VENDOR_MR6 0x4 | 79 | #define DRAM_VENDOR_MR6 0x4 |
| 79 | #define DRAM_VENDOR_MR7 0x8 | 80 | #define DRAM_VENDOR_MR7 0x8 |
| 80 | #define DRAM_VENDOR_MR8 0xc | 81 | #define DRAM_VENDOR_MR8 0xc |
| 81 | #define DRAM_VENDOR_ERROR 0x10 | 82 | #define DRAM_VENDOR_ERROR 0x10 |
| 82 | #define DRAM_VENDOR_MASK 0xff | 83 | #define DRAM_VENDOR_MASK 0xff |
| 84 | #define DRAM_VENDOR_SHIFT 24 /* We need to look at byte 3 */ | ||
| 85 | |||
| 86 | /* DRAM Information Offsets & Masks (API v3) */ | ||
| 87 | #define DRAM_DDR_INFO_MR4 0x0 | ||
| 88 | #define DRAM_DDR_INFO_MR5 0x4 | ||
| 89 | #define DRAM_DDR_INFO_MR6 0x8 | ||
| 90 | #define DRAM_DDR_INFO_MR7 0xc | ||
| 91 | #define DRAM_DDR_INFO_MR8 0x10 | ||
| 92 | #define DRAM_DDR_INFO_ERROR 0x14 | ||
| 93 | #define DRAM_DDR_INFO_MASK 0xff | ||
| 83 | 94 | ||
| 84 | /* Reset register bits & masks */ | 95 | /* Reset register bits & masks */ |
| 85 | #define DCPU_RESET_SHIFT 0x0 | 96 | #define DCPU_RESET_SHIFT 0x0 |
| @@ -109,7 +120,7 @@ · 23 unmodified lines | |||
| 109 | #define DPFE_MSG_TYPE_COMMAND 1 | 120 | #define DPFE_MSG_TYPE_COMMAND 1 |
| 110 | #define DPFE_MSG_TYPE_RESPONSE 2 | 121 | #define DPFE_MSG_TYPE_RESPONSE 2 |
| 111 | 122 | ||
| 112 | #define DELAY_LOOP_MAX 200000 | 123 | #define DELAY_LOOP_MAX 1000 |
| 113 | 124 | ||
| 114 | enum dpfe_msg_fields { | 125 | enum dpfe_msg_fields { |
| 115 | MSG_HEADER, | 126 | MSG_HEADER, |
| @@ -117,7 +128,7 @@ enum dpfe_msg_fields { · 1 unmodified line | |||
| 117 | MSG_ARG_COUNT, | 128 | MSG_ARG_COUNT, |
| 118 | MSG_ARG0, | 129 | MSG_ARG0, |
| 119 | MSG_CHKSUM, | 130 | MSG_CHKSUM, |
| 120 | MSG_FIELD_MAX /* Last entry */ | 131 | MSG_FIELD_MAX = 16 /* Max number of arguments */ |
| 121 | }; | 132 | }; |
| 122 | 133 | ||
| 123 | enum dpfe_commands { | 134 | enum dpfe_commands { |
| @@ -127,14 +138,6 @@ enum dpfe_commands { · 3 unmodified lines | |||
| 127 | DPFE_CMD_MAX /* Last entry */ | 138 | DPFE_CMD_MAX /* Last entry */ |
| 128 | }; | 139 | }; |
| 129 | 140 | ||
| 130 | struct dpfe_msg { | ||
| 131 | u32 header; | ||
| 132 | u32 command; | ||
| 133 | u32 arg_count; | ||
| 134 | u32 arg0; | ||
| 135 | u32 chksum; /* This is the sum of all other entries. */ | ||
| 136 | }; | ||
| 137 | |||
| 138 | /* | 141 | /* |
| 139 | * Format of the binary firmware file: | 142 | * Format of the binary firmware file: |
| 140 | * | 143 | * |
| @@ -168,12 +171,21 @@ struct init_data { · 27 unmodified lines | |||
| 168 | bool is_big_endian; | 171 | bool is_big_endian; |
| 169 | }; | 172 | }; |
| 170 | 173 | ||
| 174 | /* API version and corresponding commands */ | ||
| 175 | struct dpfe_api { | ||
| 176 | int version; | ||
| 177 | const char *fw_name; | ||
| 178 | const struct attribute_group **sysfs_attrs; | ||
| 179 | u32 command[DPFE_CMD_MAX][MSG_FIELD_MAX]; | ||
| 180 | }; | ||
| 181 | |||
| 171 | /* Things we need for as long as we are active. */ | 182 | /* Things we need for as long as we are active. */ |
| 172 | struct private_data { | 183 | struct private_data { |
| 173 | void __iomem *regs; | 184 | void __iomem *regs; |
| 174 | void __iomem *dmem; | 185 | void __iomem *dmem; |
| 175 | void __iomem *imem; | 186 | void __iomem *imem; |
| 176 | struct device *dev; | 187 | struct device *dev; |
| 188 | const struct dpfe_api *dpfe_api; | ||
| 177 | struct mutex lock; | 189 | struct mutex lock; |
| 178 | }; | 190 | }; |
| 179 | 191 | ||
| @@ -182,28 +194,99 @@ static const char *error_text[] = { · 2 unmodified lines | |||
| 182 | "Incorrect checksum", "Malformed command", "Timed out", | 194 | "Incorrect checksum", "Malformed command", "Timed out", |
| 183 | }; | 195 | }; |
| 184 | 196 | ||
| 185 | /* List of supported firmware commands */ | 197 | /* |
| 186 | static const u32 dpfe_commands[DPFE_CMD_MAX][MSG_FIELD_MAX] = { | 198 | * Forward declaration of our sysfs attribute functions, so we can declare the |
| 187 | [DPFE_CMD_GET_INFO] = { | 199 | * attribute data structures early. |
| 188 | [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND, | 200 | */ |
| 189 | [MSG_COMMAND] = 1, | 201 | static ssize_t show_info(struct device *, struct device_attribute *, char *); |
| 190 | [MSG_ARG_COUNT] = 1, | 202 | static ssize_t show_refresh(struct device *, struct device_attribute *, char *); |
| 191 | [MSG_ARG0] = 1, | 203 | static ssize_t store_refresh(struct device *, struct device_attribute *, |
| 192 | [MSG_CHKSUM] = 4, | 204 | const char *, size_t); |
| 193 | }, | 205 | static ssize_t show_vendor(struct device *, struct device_attribute *, char *); |
| 194 | [DPFE_CMD_GET_REFRESH] = { | 206 | static ssize_t show_dram(struct device *, struct device_attribute *, char *); |
| 195 | [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND, | 207 | |
| 196 | [MSG_COMMAND] = 2, | 208 | /* |
| 197 | [MSG_ARG_COUNT] = 1, | 209 | * Declare our attributes early, so they can be referenced in the API data |
| 198 | [MSG_ARG0] = 1, | 210 | * structure. We need to do this, because the attributes depend on the API |
| 199 | [MSG_CHKSUM] = 5, | 211 | * version. |
| 200 | }, | 212 | */ |
| 201 | [DPFE_CMD_GET_VENDOR] = { | 213 | static DEVICE_ATTR(dpfe_info, 0444, show_info, NULL); |
| 202 | [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND, | 214 | static DEVICE_ATTR(dpfe_refresh, 0644, show_refresh, store_refresh); |
| 203 | [MSG_COMMAND] = 2, | 215 | static DEVICE_ATTR(dpfe_vendor, 0444, show_vendor, NULL); |
| 204 | [MSG_ARG_COUNT] = 1, | 216 | static DEVICE_ATTR(dpfe_dram, 0444, show_dram, NULL); |
| 205 | [MSG_ARG0] = 2, | 217 | |
| 206 | [MSG_CHKSUM] = 6, | 218 | /* API v2 sysfs attributes */ |
| 219 | static struct attribute *dpfe_v2_attrs[] = { | ||
| 220 | &dev_attr_dpfe_info.attr, | ||
| 221 | &dev_attr_dpfe_refresh.attr, | ||
| 222 | &dev_attr_dpfe_vendor.attr, | ||
| 223 | NULL | ||
| 224 | }; | ||
| 225 | ATTRIBUTE_GROUPS(dpfe_v2); | ||
| 226 | |||
| 227 | /* API v3 sysfs attributes */ | ||
| 228 | static struct attribute *dpfe_v3_attrs[] = { | ||
| 229 | &dev_attr_dpfe_info.attr, | ||
| 230 | &dev_attr_dpfe_dram.attr, | ||
| 231 | NULL | ||
| 232 | }; | ||
| 233 | ATTRIBUTE_GROUPS(dpfe_v3); | ||
| 234 | |||
| 235 | /* API v2 firmware commands */ | ||
| 236 | static const struct dpfe_api dpfe_api_v2 = { | ||
| 237 | .version = 2, | ||
| 238 | .fw_name = "dpfe.bin", | ||
| 239 | .sysfs_attrs = dpfe_v2_groups, | ||
| 240 | .command = { | ||
| 241 | [DPFE_CMD_GET_INFO] = { | ||
| 242 | [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND, | ||
| 243 | [MSG_COMMAND] = 1, | ||
| 244 | [MSG_ARG_COUNT] = 1, | ||
| 245 | [MSG_ARG0] = 1, | ||
| 246 | [MSG_CHKSUM] = 4, | ||
| 247 | }, | ||
| 248 | [DPFE_CMD_GET_REFRESH] = { | ||
| 249 | [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND, | ||
| 250 | [MSG_COMMAND] = 2, | ||
| 251 | [MSG_ARG_COUNT] = 1, | ||
| 252 | [MSG_ARG0] = 1, | ||
| 253 | [MSG_CHKSUM] = 5, | ||
| 254 | }, | ||
| 255 | [DPFE_CMD_GET_VENDOR] = { | ||
| 256 | [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND, | ||
| 257 | [MSG_COMMAND] = 2, | ||
| 258 | [MSG_ARG_COUNT] = 1, | ||
| 259 | [MSG_ARG0] = 2, | ||
| 260 | [MSG_CHKSUM] = 6, | ||
| 261 | }, | ||
| 262 | } | ||
| 263 | }; | ||
| 264 | |||
| 265 | /* API v3 firmware commands */ | ||
| 266 | static const struct dpfe_api dpfe_api_v3 = { | ||
| 267 | .version = 3, | ||
| 268 | .fw_name = NULL, /* We expect the firmware to have been downloaded! */ | ||
| 269 | .sysfs_attrs = dpfe_v3_groups, | ||
| 270 | .command = { | ||
| 271 | [DPFE_CMD_GET_INFO] = { | ||
| 272 | [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND, | ||
| 273 | [MSG_COMMAND] = 0x0101, | ||
| 274 | [MSG_ARG_COUNT] = 1, | ||
| 275 | [MSG_ARG0] = 1, | ||
| 276 | [MSG_CHKSUM] = 0x104, | ||
| 277 | }, | ||
| 278 | [DPFE_CMD_GET_REFRESH] = { | ||
| 279 | [MSG_HEADER] = DPFE_MSG_TYPE_COMMAND, | ||
| 280 | [MSG_COMMAND] = 0x0202, | ||
| 281 | [MSG_ARG_COUNT] = 0, | ||
| 282 | /* | ||
| 283 | * This is a bit ugly. Without arguments, the checksum | ||
| 284 | * follows right after the argument count and not at | ||
| 285 | * offset MSG_CHKSUM. | ||
| 286 | */ | ||
| 287 | [MSG_ARG0] = 0x203, | ||
| 288 | }, | ||
| 289 | /* There's no GET_VENDOR command in API v3. */ | ||
| 207 | }, | 290 | }, |
| 208 | }; | 291 | }; |
| 209 | 292 | ||
| @@ -248,13 +331,13 @@ static void __enable_dcpu(void __iomem *regs) · 38 unmodified lines | |||
| 248 | writel_relaxed(val, regs + REG_DCPU_RESET); | 331 | writel_relaxed(val, regs + REG_DCPU_RESET); |
| 249 | } | 332 | } |
| 250 | 333 | ||
| 251 | static unsigned int get_msg_chksum(const u32 msg[]) | 334 | static unsigned int get_msg_chksum(const u32 msg[], unsigned int max) |
| 252 | { | 335 | { |
| 253 | unsigned int sum = 0; | 336 | unsigned int sum = 0; |
| 254 | unsigned int i; | 337 | unsigned int i; |
| 255 | 338 | ||
| 256 | /* Don't include the last field in the checksum. */ | 339 | /* Don't include the last field in the checksum. */ |
| 257 | for (i = 0; i < MSG_FIELD_MAX - 1; i++) | 340 | for (i = 0; i < max; i++) |
| 258 | sum += msg[i]; | 341 | sum += msg[i]; |
| 259 | 342 | ||
| 260 | return sum; | 343 | return sum; |
| @@ -267,6 +350,11 @@ static void __iomem *get_msg_ptr(struct private_data *priv, u32 response, · 6 unmodified lines | |||
| 267 | unsigned int offset; | 350 | unsigned int offset; |
| 268 | void __iomem *ptr = NULL; | 351 | void __iomem *ptr = NULL; |
| 269 | 352 | ||
| 353 | /* There is no need to use this function for API v3 or later. */ | ||
| 354 | if (unlikely(priv->dpfe_api->version >= 3)) { | ||
| 355 | return NULL; | ||
| 356 | } | ||
| 357 | |||
| 270 | msg_type = (response >> DRAM_MSG_TYPE_OFFSET) & DRAM_MSG_TYPE_MASK; | 358 | msg_type = (response >> DRAM_MSG_TYPE_OFFSET) & DRAM_MSG_TYPE_MASK; |
| 271 | offset = (response >> DRAM_MSG_ADDR_OFFSET) & DRAM_MSG_ADDR_MASK; | 359 | offset = (response >> DRAM_MSG_ADDR_OFFSET) & DRAM_MSG_ADDR_MASK; |
| 272 | 360 | ||
| @@ -294,12 +382,25 @@ static void __iomem *get_msg_ptr(struct private_data *priv, u32 response, · 21 unmodified lines | |||
| 294 | return ptr; | 382 | return ptr; |
| 295 | } | 383 | } |
| 296 | 384 | ||
| 385 | static void __finalize_command(struct private_data *priv) | ||
| 386 | { | ||
| 387 | unsigned int release_mbox; | ||
| 388 | |||
| 389 | /* | ||
| 390 | * It depends on the API version which MBOX register we have to write to | ||
| 391 | * to signal we are done. | ||
| 392 | */ | ||
| 393 | release_mbox = (priv->dpfe_api->version < 3) | ||
| 394 | ? REG_TO_HOST_MBOX : REG_TO_DCPU_MBOX; | ||
| 395 | writel_relaxed(0, priv->regs + release_mbox); | ||
| 396 | } | ||
| 397 | |||
| 297 | static int __send_command(struct private_data *priv, unsigned int cmd, | 398 | static int __send_command(struct private_data *priv, unsigned int cmd, |
| 298 | u32 result[]) | 399 | u32 result[]) |
| 299 | { | 400 | { |
| 300 | const u32 *msg = dpfe_commands[cmd]; | 401 | const u32 *msg = priv->dpfe_api->command[cmd]; |
| 301 | void __iomem *regs = priv->regs; | 402 | void __iomem *regs = priv->regs; |
| 302 | unsigned int i, chksum; | 403 | unsigned int i, chksum, chksum_idx; |
| 303 | int ret = 0; | 404 | int ret = 0; |
| 304 | u32 resp; | 405 | u32 resp; |
| 305 | 406 | ||
| @@ -308,6 +409,18 @@ static int __send_command(struct private_data *priv, unsigned int cmd, · 2 unmodified lines | |||
| 308 | 409 | ||
| 309 | mutex_lock(&priv->lock); | 410 | mutex_lock(&priv->lock); |
| 310 | 411 | ||
| 412 | /* Wait for DCPU to become ready */ | ||
| 413 | for (i = 0; i < DELAY_LOOP_MAX; i++) { | ||
| 414 | resp = readl_relaxed(regs + REG_TO_HOST_MBOX); | ||
| 415 | if (resp == 0) | ||
| 416 | break; | ||
| 417 | msleep(1); | ||
| 418 | } | ||
| 419 | if (resp != 0) { | ||
| 420 | mutex_unlock(&priv->lock); | ||
| 421 | return -ETIMEDOUT; | ||
| 422 | } | ||
| 423 | |||
| 311 | /* Write command and arguments to message area */ | 424 | /* Write command and arguments to message area */ |
| 312 | for (i = 0; i < MSG_FIELD_MAX; i++) | 425 | for (i = 0; i < MSG_FIELD_MAX; i++) |
| 313 | writel_relaxed(msg[i], regs + DCPU_MSG_RAM(i)); | 426 | writel_relaxed(msg[i], regs + DCPU_MSG_RAM(i)); |
| @@ -321,7 +434,7 @@ static int __send_command(struct private_data *priv, unsigned int cmd, · 7 unmodified lines | |||
| 321 | resp = readl_relaxed(regs + REG_TO_HOST_MBOX); | 434 | resp = readl_relaxed(regs + REG_TO_HOST_MBOX); |
| 322 | if (resp > 0) | 435 | if (resp > 0) |
| 323 | break; | 436 | break; |
| 324 | udelay(5); | 437 | msleep(1); |
| 325 | } | 438 | } |
| 326 | 439 | ||
| 327 | if (i == DELAY_LOOP_MAX) { | 440 | if (i == DELAY_LOOP_MAX) { |
| @@ -331,10 +444,11 @@ static int __send_command(struct private_data *priv, unsigned int cmd, · 3 unmodified lines | |||
| 331 | /* Read response data */ | 444 | /* Read response data */ |
| 332 | for (i = 0; i < MSG_FIELD_MAX; i++) | 445 | for (i = 0; i < MSG_FIELD_MAX; i++) |
| 333 | result[i] = readl_relaxed(regs + DCPU_MSG_RAM(i)); | 446 | result[i] = readl_relaxed(regs + DCPU_MSG_RAM(i)); |
| 447 | chksum_idx = result[MSG_ARG_COUNT] + MSG_ARG_COUNT + 1; | ||
| 334 | } | 448 | } |
| 335 | 449 | ||
| 336 | /* Tell DCPU we are done */ | 450 | /* Tell DCPU we are done */ |
| 337 | writel_relaxed(0, regs + REG_TO_HOST_MBOX); | 451 | __finalize_command(priv); |
| 338 | 452 | ||
| 339 | mutex_unlock(&priv->lock); | 453 | mutex_unlock(&priv->lock); |
| 340 | 454 | ||
| @@ -342,8 +456,8 @@ static int __send_command(struct private_data *priv, unsigned int cmd, · 1 unmodified line | |||
| 342 | return ret; | 456 | return ret; |
| 343 | 457 | ||
| 344 | /* Verify response */ | 458 | /* Verify response */ |
| 345 | chksum = get_msg_chksum(result); | 459 | chksum = get_msg_chksum(result, chksum_idx); |
| 346 | if (chksum != result[MSG_CHKSUM]) | 460 | if (chksum != result[chksum_idx]) |
| 347 | resp = DCPU_RET_ERR_CHKSUM; | 461 | resp = DCPU_RET_ERR_CHKSUM; |
| 348 | 462 | ||
| 349 | if (resp != DCPU_RET_SUCCESS) { | 463 | if (resp != DCPU_RET_SUCCESS) { |
| @@ -484,7 +598,15 @@ static int brcmstb_dpfe_download_firmware(struct platform_device *pdev, · 134 unmodified lines | |||
| 484 | return 0; | 598 | return 0; |
| 485 | } | 599 | } |
| 486 | 600 | ||
| 487 | ret = request_firmware(&fw, FIRMWARE_NAME, dev); | 601 | /* |
| 602 | * If the firmware filename is NULL it means the boot firmware has to | ||
| 603 | * download the DCPU firmware for us. If that didn't work, we have to | ||
| 604 | * bail, since downloading it ourselves wouldn't work either. | ||
| 605 | */ | ||
| 606 | if (!priv->dpfe_api->fw_name) | ||
| 607 | return -ENODEV; | ||
| 608 | |||
| 609 | ret = request_firmware(&fw, priv->dpfe_api->fw_name, dev); | ||
| 488 | /* request_firmware() prints its own error messages. */ | 610 | /* request_firmware() prints its own error messages. */ |
| 489 | if (ret) | 611 | if (ret) |
| 490 | return ret; | 612 | return ret; |
| @@ -525,12 +647,10 @@ static int brcmstb_dpfe_download_firmware(struct platform_device *pdev, · 34 unmodified lines | |||
| 525 | } | 647 | } |
| 526 | 648 | ||
| 527 | static ssize_t generic_show(unsigned int command, u32 response[], | 649 | static ssize_t generic_show(unsigned int command, u32 response[], |
| 528 | struct device *dev, char *buf) | 650 | struct private_data *priv, char *buf) |
| 529 | { | 651 | { |
| 530 | struct private_data *priv; | ||
| 531 | int ret; | 652 | int ret; |
| 532 | 653 | ||
| 533 | priv = dev_get_drvdata(dev); | ||
| 534 | if (!priv) | 654 | if (!priv) |
| 535 | return sprintf(buf, "ERROR: driver private data not set\n"); | 655 | return sprintf(buf, "ERROR: driver private data not set\n"); |
| 536 | 656 | ||
| @@ -545,10 +665,12 @@ static ssize_t show_info(struct device *dev, struct device_attribute *devattr, · 8 unmodified lines | |||
| 545 | char *buf) | 665 | char *buf) |
| 546 | { | 666 | { |
| 547 | u32 response[MSG_FIELD_MAX]; | 667 | u32 response[MSG_FIELD_MAX]; |
| 668 | struct private_data *priv; | ||
| 548 | unsigned int info; | 669 | unsigned int info; |
| 549 | ssize_t ret; | 670 | ssize_t ret; |
| 550 | 671 | ||
| 551 | ret = generic_show(DPFE_CMD_GET_INFO, response, dev, buf); | 672 | priv = dev_get_drvdata(dev); |
| 673 | ret = generic_show(DPFE_CMD_GET_INFO, response, priv, buf); | ||
| 552 | if (ret) | 674 | if (ret) |
| 553 | return ret; | 675 | return ret; |
| 554 | 676 | ||
| @@ -571,17 +693,17 @@ static ssize_t show_refresh(struct device *dev, · 16 unmodified lines | |||
| 571 | u32 mr4; | 693 | u32 mr4; |
| 572 | ssize_t ret; | 694 | ssize_t ret; |
| 573 | 695 | ||
| 574 | ret = generic_show(DPFE_CMD_GET_REFRESH, response, dev, buf); | 696 | priv = dev_get_drvdata(dev); |
| 697 | ret = generic_show(DPFE_CMD_GET_REFRESH, response, priv, buf); | ||
| 575 | if (ret) | 698 | if (ret) |
| 576 | return ret; | 699 | return ret; |
| 577 | 700 | ||
| 578 | priv = dev_get_drvdata(dev); | ||
| 579 | |||
| 580 | info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret); | 701 | info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret); |
| 581 | if (!info) | 702 | if (!info) |
| 582 | return ret; | 703 | return ret; |
| 583 | 704 | ||
| 584 | mr4 = readl_relaxed(info + DRAM_INFO_MR4) & DRAM_INFO_MR4_MASK; | 705 | mr4 = (readl_relaxed(info + DRAM_INFO_MR4) >> DRAM_INFO_MR4_SHIFT) & |
| 706 | DRAM_INFO_MR4_MASK; | ||
| 585 | 707 | ||
| 586 | refresh = (mr4 >> DRAM_MR4_REFRESH) & DRAM_MR4_REFRESH_MASK; | 708 | refresh = (mr4 >> DRAM_MR4_REFRESH) & DRAM_MR4_REFRESH_MASK; |
| 587 | sr_abort = (mr4 >> DRAM_MR4_SR_ABORT) & DRAM_MR4_SR_ABORT_MASK; | 709 | sr_abort = (mr4 >> DRAM_MR4_SR_ABORT) & DRAM_MR4_SR_ABORT_MASK; |
| @@ -608,7 +730,6 @@ static ssize_t store_refresh(struct device *dev, struct device_attribute *attr, · 20 unmodified lines | |||
| 608 | return -EINVAL; | 730 | return -EINVAL; |
| 609 | 731 | ||
| 610 | priv = dev_get_drvdata(dev); | 732 | priv = dev_get_drvdata(dev); |
| 611 | |||
| 612 | ret = __send_command(priv, DPFE_CMD_GET_REFRESH, response); | 733 | ret = __send_command(priv, DPFE_CMD_GET_REFRESH, response); |
| 613 | if (ret) | 734 | if (ret) |
| 614 | return ret; | 735 | return ret; |
| @@ -623,30 +744,58 @@ static ssize_t store_refresh(struct device *dev, struct device_attribute *attr, · 8 unmodified lines | |||
| 623 | } | 744 | } |
| 624 | 745 | ||
| 625 | static ssize_t show_vendor(struct device *dev, struct device_attribute *devattr, | 746 | static ssize_t show_vendor(struct device *dev, struct device_attribute *devattr, |
| 626 | char *buf) | 747 | char *buf) |
| 627 | { | 748 | { |
| 628 | u32 response[MSG_FIELD_MAX]; | 749 | u32 response[MSG_FIELD_MAX]; |
| 629 | struct private_data *priv; | 750 | struct private_data *priv; |
| 630 | void __iomem *info; | 751 | void __iomem *info; |
| 631 | ssize_t ret; | 752 | ssize_t ret; |
| 753 | u32 mr5, mr6, mr7, mr8, err; | ||
| 632 | 754 | ||
| 633 | ret = generic_show(DPFE_CMD_GET_VENDOR, response, dev, buf); | 755 | priv = dev_get_drvdata(dev); |
| 756 | ret = generic_show(DPFE_CMD_GET_VENDOR, response, priv, buf); | ||
| 634 | if (ret) | 757 | if (ret) |
| 635 | return ret; | 758 | return ret; |
| 636 | 759 | ||
| 637 | priv = dev_get_drvdata(dev); | ||
| 638 | |||
| 639 | info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret); | 760 | info = get_msg_ptr(priv, response[MSG_ARG0], buf, &ret); |
| 640 | if (!info) | 761 | if (!info) |
| 641 | return ret; | 762 | return ret; |
| 642 | 763 | ||
| 643 | return sprintf(buf, "%#x %#x %#x %#x %#x\n", | 764 | mr5 = (readl_relaxed(info + DRAM_VENDOR_MR5) >> DRAM_VENDOR_SHIFT) & |
| 644 | readl_relaxed(info + DRAM_VENDOR_MR5) & DRAM_VENDOR_MASK, | 765 | DRAM_VENDOR_MASK; |
| 645 | readl_relaxed(info + DRAM_VENDOR_MR6) & DRAM_VENDOR_MASK, | 766 | mr6 = (readl_relaxed(info + DRAM_VENDOR_MR6) >> DRAM_VENDOR_SHIFT) & |
| 646 | readl_relaxed(info + DRAM_VENDOR_MR7) & DRAM_VENDOR_MASK, | 767 | DRAM_VENDOR_MASK; |
| 647 | readl_relaxed(info + DRAM_VENDOR_MR8) & DRAM_VENDOR_MASK, | 768 | mr7 = (readl_relaxed(info + DRAM_VENDOR_MR7) >> DRAM_VENDOR_SHIFT) & |
| 648 | readl_relaxed(info + DRAM_VENDOR_ERROR) & | 769 | DRAM_VENDOR_MASK; |
| 649 | DRAM_VENDOR_MASK); | 770 | mr8 = (readl_relaxed(info + DRAM_VENDOR_MR8) >> DRAM_VENDOR_SHIFT) & |
| 771 | DRAM_VENDOR_MASK; | ||
| 772 | err = readl_relaxed(info + DRAM_VENDOR_ERROR) & DRAM_VENDOR_MASK; | ||
| 773 | |||
| 774 | return sprintf(buf, "%#x %#x %#x %#x %#x\n", mr5, mr6, mr7, mr8, err); | ||
| 775 | } | ||
| 776 | |||
| 777 | static ssize_t show_dram(struct device *dev, struct device_attribute *devattr, | ||
| 778 | char *buf) | ||
| 779 | { | ||
| 780 | u32 response[MSG_FIELD_MAX]; | ||
| 781 | struct private_data *priv; | ||
| 782 | ssize_t ret; | ||
| 783 | u32 mr4, mr5, mr6, mr7, mr8, err; | ||
| 784 | |||
| 785 | priv = dev_get_drvdata(dev); | ||
| 786 | ret = generic_show(DPFE_CMD_GET_REFRESH, response, priv, buf); | ||
| 787 | if (ret) | ||
| 788 | return ret; | ||
| 789 | |||
| 790 | mr4 = response[MSG_ARG0 + 0] & DRAM_INFO_MR4_MASK; | ||
| 791 | mr5 = response[MSG_ARG0 + 1] & DRAM_DDR_INFO_MASK; | ||
| 792 | mr6 = response[MSG_ARG0 + 2] & DRAM_DDR_INFO_MASK; | ||
| 793 | mr7 = response[MSG_ARG0 + 3] & DRAM_DDR_INFO_MASK; | ||
| 794 | mr8 = response[MSG_ARG0 + 4] & DRAM_DDR_INFO_MASK; | ||
| 795 | err = response[MSG_ARG0 + 5] & DRAM_DDR_INFO_MASK; | ||
| 796 | |||
| 797 | return sprintf(buf, "%#x %#x %#x %#x %#x %#x\n", mr4, mr5, mr6, mr7, | ||
| 798 | mr8, err); | ||
| 650 | } | 799 | } |
| 651 | 800 | ||
| 652 | static int brcmstb_dpfe_resume(struct platform_device *pdev) | 801 | static int brcmstb_dpfe_resume(struct platform_device *pdev) |
| @@ -656,17 +805,6 @@ static int brcmstb_dpfe_resume(struct platform_device *pdev) · 3 unmodified lines | |||
| 656 | return brcmstb_dpfe_download_firmware(pdev, &init); | 805 | return brcmstb_dpfe_download_firmware(pdev, &init); |
| 657 | } | 806 | } |
| 658 | 807 | ||
| 659 | static DEVICE_ATTR(dpfe_info, 0444, show_info, NULL); | ||
| 660 | static DEVICE_ATTR(dpfe_refresh, 0644, show_refresh, store_refresh); | ||
| 661 | static DEVICE_ATTR(dpfe_vendor, 0444, show_vendor, NULL); | ||
| 662 | static struct attribute *dpfe_attrs[] = { | ||
| 663 | &dev_attr_dpfe_info.attr, | ||
| 664 | &dev_attr_dpfe_refresh.attr, | ||
| 665 | &dev_attr_dpfe_vendor.attr, | ||
| 666 | NULL | ||
| 667 | }; | ||
| 668 | ATTRIBUTE_GROUPS(dpfe); | ||
| 669 | |||
| 670 | static int brcmstb_dpfe_probe(struct platform_device *pdev) | 808 | static int brcmstb_dpfe_probe(struct platform_device *pdev) |
| 671 | { | 809 | { |
| 672 | struct device *dev = &pdev->dev; | 810 | struct device *dev = &pdev->dev; |
| @@ -703,26 +841,47 @@ static int brcmstb_dpfe_probe(struct platform_device *pdev) · 30 unmodified lines | |||
| 703 | return -ENOENT; | 841 | return -ENOENT; |
| 704 | } | 842 | } |
| 705 | 843 | ||
| 844 | priv->dpfe_api = of_device_get_match_data(dev); | ||
| 845 | if (unlikely(!priv->dpfe_api)) { | ||
| 846 | /* | ||
| 847 | * It should be impossible to end up here, but to be safe we | ||
| 848 | * check anyway. | ||
| 849 | */ | ||
| 850 | dev_err(dev, "Couldn't determine API\n"); | ||
| 851 | return -ENOENT; | ||
| 852 | } | ||
| 853 | |||
| 706 | ret = brcmstb_dpfe_download_firmware(pdev, &init); | 854 | ret = brcmstb_dpfe_download_firmware(pdev, &init); |
| 707 | if (ret) | 855 | if (ret) { |
| 856 | dev_err(dev, "Couldn't download firmware -- %d\n", ret); | ||
| 708 | return ret; | 857 | return ret; |
| 858 | } | ||
| 709 | 859 | ||
| 710 | ret = sysfs_create_groups(&pdev->dev.kobj, dpfe_groups); | 860 | ret = sysfs_create_groups(&pdev->dev.kobj, priv->dpfe_api->sysfs_attrs); |
| 711 | if (!ret) | 861 | if (!ret) |
| 712 | dev_info(dev, "registered.\n"); | 862 | dev_info(dev, "registered with API v%d.\n", |
| 863 | priv->dpfe_api->version); | ||
| 713 | 864 | ||
| 714 | return ret; | 865 | return ret; |
| 715 | } | 866 | } |
| 716 | 867 | ||
| 717 | static int brcmstb_dpfe_remove(struct platform_device *pdev) | 868 | static int brcmstb_dpfe_remove(struct platform_device *pdev) |
| 718 | { | 869 | { |
| 719 | sysfs_remove_groups(&pdev->dev.kobj, dpfe_groups); | 870 | struct private_data *priv = dev_get_drvdata(&pdev->dev); |
| 871 | |||
| 872 | sysfs_remove_groups(&pdev->dev.kobj, priv->dpfe_api->sysfs_attrs); | ||
| 720 | 873 | ||
| 721 | return 0; | 874 | return 0; |
| 722 | } | 875 | } |
| 723 | 876 | ||
| 724 | static const struct of_device_id brcmstb_dpfe_of_match[] = { | 877 | static const struct of_device_id brcmstb_dpfe_of_match[] = { |
| 725 | { .compatible = "brcm,dpfe-cpu", }, | 878 | /* Use legacy API v2 for a select number of chips */ |
| 879 | { .compatible = "brcm,bcm7268-dpfe-cpu", .data = &dpfe_api_v2 }, | ||
| 880 | { .compatible = "brcm,bcm7271-dpfe-cpu", .data = &dpfe_api_v2 }, | ||
| 881 | { .compatible = "brcm,bcm7278-dpfe-cpu", .data = &dpfe_api_v2 }, | ||
| 882 | { .compatible = "brcm,bcm7211-dpfe-cpu", .data = &dpfe_api_v2 }, | ||
| 883 | /* API v3 is the default going forward */ | ||
| 884 | { .compatible = "brcm,dpfe-cpu", .data = &dpfe_api_v3 }, | ||
| 726 | {} | 885 | {} |
| 727 | }; | 886 | }; |
| 728 | MODULE_DEVICE_TABLE(of, brcmstb_dpfe_of_match); | 887 | MODULE_DEVICE_TABLE(of, brcmstb_dpfe_of_match); |
| @@ -23,8 +23,9 @@ · 22 unmodified lines | |||
| 23 | #include <linux/list.h> | 23 | #include <linux/list.h> |
| 24 | #include <linux/spinlock.h> | 24 | #include <linux/spinlock.h> |
| 25 | #include <linux/pm.h> | 25 | #include <linux/pm.h> |
| 26 | #include <memory/jedec_ddr.h> | 26 | |
| 27 | #include "emif.h" | 27 | #include "emif.h" |
| 28 | #include "jedec_ddr.h" | ||
| 28 | #include "of_memory.h" | 29 | #include "of_memory.h" |
| 29 | 30 | ||
| 30 | /** | 31 | /** |
| @@ -6,8 +6,8 @@ · 5 unmodified lines | |||
| 6 | * | 6 | * |
| 7 | * Aneesh V <aneesh@ti.com> | 7 | * Aneesh V <aneesh@ti.com> |
| 8 | */ | 8 | */ |
| 9 | #ifndef __LINUX_JEDEC_DDR_H | 9 | #ifndef __JEDEC_DDR_H |
| 10 | #define __LINUX_JEDEC_DDR_H | 10 | #define __JEDEC_DDR_H |
| 11 | 11 | ||
| 12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
| 13 | 13 | ||
| @@ -169,4 +169,4 @@ extern const struct lpddr2_timings · 155 unmodified lines | |||
| 169 | lpddr2_jedec_timings[NUM_DDR_TIMING_TABLE_ENTRIES]; | 169 | lpddr2_jedec_timings[NUM_DDR_TIMING_TABLE_ENTRIES]; |
| 170 | extern const struct lpddr2_min_tck lpddr2_jedec_min_tck; | 170 | extern const struct lpddr2_min_tck lpddr2_jedec_min_tck; |
| 171 | 171 | ||
| 172 | #endif /* __LINUX_JEDEC_DDR_H */ | 172 | #endif /* __JEDEC_DDR_H */ |
| @@ -7,8 +7,9 @@ · 6 unmodified lines | |||
| 7 | * Aneesh V <aneesh@ti.com> | 7 | * Aneesh V <aneesh@ti.com> |
| 8 | */ | 8 | */ |
| 9 | 9 | ||
| 10 | #include <memory/jedec_ddr.h> | 10 | #include <linux/export.h> |
| 11 | #include <linux/module.h> | 11 | |
| 12 | #include "jedec_ddr.h" | ||
| 12 | 13 | ||
| 13 | /* LPDDR2 addressing details from JESD209-2 section 2.4 */ | 14 | /* LPDDR2 addressing details from JESD209-2 section 2.4 */ |
| 14 | const struct lpddr2_addressing | 15 | const struct lpddr2_addressing |
| @@ -10,8 +10,9 @@ · 9 unmodified lines | |||
| 10 | #include <linux/list.h> | 10 | #include <linux/list.h> |
| 11 | #include <linux/of.h> | 11 | #include <linux/of.h> |
| 12 | #include <linux/gfp.h> | 12 | #include <linux/gfp.h> |
| 13 | #include <memory/jedec_ddr.h> | ||
| 14 | #include <linux/export.h> | 13 | #include <linux/export.h> |
| 14 | |||
| 15 | #include "jedec_ddr.h" | ||
| 15 | #include "of_memory.h" | 16 | #include "of_memory.h" |
| 16 | 17 | ||
| 17 | /** | 18 | /** |
| @@ -30,28 +30,6 @@ · 29 unmodified lines | |||
| 30 | #define MC_EMEM_ARB_MISC1 0xdc | 30 | #define MC_EMEM_ARB_MISC1 0xdc |
| 31 | #define MC_EMEM_ARB_RING1_THROTTLE 0xe0 | 31 | #define MC_EMEM_ARB_RING1_THROTTLE 0xe0 |
| 32 | 32 | ||
| 33 | static const unsigned long tegra124_mc_emem_regs[] = { | ||
| 34 | MC_EMEM_ARB_CFG, | ||
| 35 | MC_EMEM_ARB_OUTSTANDING_REQ, | ||
| 36 | MC_EMEM_ARB_TIMING_RCD, | ||
| 37 | MC_EMEM_ARB_TIMING_RP, | ||
| 38 | MC_EMEM_ARB_TIMING_RC, | ||
| 39 | MC_EMEM_ARB_TIMING_RAS, | ||
| 40 | MC_EMEM_ARB_TIMING_FAW, | ||
| 41 | MC_EMEM_ARB_TIMING_RRD, | ||
| 42 | MC_EMEM_ARB_TIMING_RAP2PRE, | ||
| 43 | MC_EMEM_ARB_TIMING_WAP2PRE, | ||
| 44 | MC_EMEM_ARB_TIMING_R2R, | ||
| 45 | MC_EMEM_ARB_TIMING_W2W, | ||
| 46 | MC_EMEM_ARB_TIMING_R2W, | ||
| 47 | MC_EMEM_ARB_TIMING_W2R, | ||
| 48 | MC_EMEM_ARB_DA_TURNS, | ||
| 49 | MC_EMEM_ARB_DA_COVERS, | ||
| 50 | MC_EMEM_ARB_MISC0, | ||
| 51 | MC_EMEM_ARB_MISC1, | ||
| 52 | MC_EMEM_ARB_RING1_THROTTLE | ||
| 53 | }; | ||
| 54 | |||
| 55 | static const struct tegra_mc_client tegra124_mc_clients[] = { | 33 | static const struct tegra_mc_client tegra124_mc_clients[] = { |
| 56 | { | 34 | { |
| 57 | .id = 0x00, | 35 | .id = 0x00, |
| @@ -1046,6 +1024,28 @@ static const struct tegra_mc_reset tegra124_mc_resets[] = { · 988 unmodified lines | |||
| 1046 | }; | 1024 | }; |
| 1047 | 1025 | ||
| 1048 | #ifdef CONFIG_ARCH_TEGRA_124_SOC | 1026 | #ifdef CONFIG_ARCH_TEGRA_124_SOC |
| 1027 | static const unsigned long tegra124_mc_emem_regs[] = { | ||
| 1028 | MC_EMEM_ARB_CFG, | ||
| 1029 | MC_EMEM_ARB_OUTSTANDING_REQ, | ||
| 1030 | MC_EMEM_ARB_TIMING_RCD, | ||
| 1031 | MC_EMEM_ARB_TIMING_RP, | ||
| 1032 | MC_EMEM_ARB_TIMING_RC, | ||
| 1033 | MC_EMEM_ARB_TIMING_RAS, | ||
| 1034 | MC_EMEM_ARB_TIMING_FAW, | ||
| 1035 | MC_EMEM_ARB_TIMING_RRD, | ||
| 1036 | MC_EMEM_ARB_TIMING_RAP2PRE, | ||
| 1037 | MC_EMEM_ARB_TIMING_WAP2PRE, | ||
| 1038 | MC_EMEM_ARB_TIMING_R2R, | ||
| 1039 | MC_EMEM_ARB_TIMING_W2W, | ||
| 1040 | MC_EMEM_ARB_TIMING_R2W, | ||
| 1041 | MC_EMEM_ARB_TIMING_W2R, | ||
| 1042 | MC_EMEM_ARB_DA_TURNS, | ||
| 1043 | MC_EMEM_ARB_DA_COVERS, | ||
| 1044 | MC_EMEM_ARB_MISC0, | ||
| 1045 | MC_EMEM_ARB_MISC1, | ||
| 1046 | MC_EMEM_ARB_RING1_THROTTLE | ||
| 1047 | }; | ||
| 1048 | |||
| 1049 | static const struct tegra_smmu_soc tegra124_smmu_soc = { | 1049 | static const struct tegra_smmu_soc tegra124_smmu_soc = { |
| 1050 | .clients = tegra124_mc_clients, | 1050 | .clients = tegra124_mc_clients, |
| 1051 | .num_clients = ARRAY_SIZE(tegra124_mc_clients), | 1051 | .num_clients = ARRAY_SIZE(tegra124_mc_clients), |
| @@ -118,7 +118,7 @@ config RESET_QCOM_PDC · 117 unmodified lines | |||
| 118 | 118 | ||
| 119 | config RESET_SIMPLE | 119 | config RESET_SIMPLE |
| 120 | bool "Simple Reset Controller Driver" if COMPILE_TEST | 120 | bool "Simple Reset Controller Driver" if COMPILE_TEST |
| 121 | default ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED | 121 | default ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED || ARCH_BITMAIN |
| 122 | help | 122 | help |
| 123 | This enables a simple reset controller driver for reset lines that | 123 | This enables a simple reset controller driver for reset lines that |
| 124 | that can be asserted and deasserted by toggling bits in a contiguous, | 124 | that can be asserted and deasserted by toggling bits in a contiguous, |
| @@ -130,6 +130,7 @@ config RESET_SIMPLE · 5 unmodified lines | |||
| 130 | - RCC reset controller in STM32 MCUs | 130 | - RCC reset controller in STM32 MCUs |
| 131 | - Allwinner SoCs | 131 | - Allwinner SoCs |
| 132 | - ZTE's zx2967 family | 132 | - ZTE's zx2967 family |
| 133 | - Bitmain BM1880 SoC | ||
| 133 | 134 | ||
| 134 | config RESET_STM32MP157 | 135 | config RESET_STM32MP157 |
| 135 | bool "STM32MP157 Reset Driver" if COMPILE_TEST | 136 | bool "STM32MP157 Reset Driver" if COMPILE_TEST |
| @@ -690,9 +690,6 @@ __reset_control_get_from_lookup(struct device *dev, const char *con_id, · 689 unmodified lines | |||
| 690 | const char *dev_id = dev_name(dev); | 690 | const char *dev_id = dev_name(dev); |
| 691 | struct reset_control *rstc = NULL; | 691 | struct reset_control *rstc = NULL; |
| 692 | 692 | ||
| 693 | if (!dev) | ||
| 694 | return ERR_PTR(-EINVAL); | ||
| 695 | |||
| 696 | mutex_lock(&reset_lookup_mutex); | 693 | mutex_lock(&reset_lookup_mutex); |
| 697 | 694 | ||
| 698 | list_for_each_entry(lookup, &reset_lookup_list, list) { | 695 | list_for_each_entry(lookup, &reset_lookup_list, list) { |
| @@ -125,6 +125,8 @@ static const struct of_device_id reset_simple_dt_ids[] = { · 124 unmodified lines | |||
| 125 | .data = &reset_simple_active_low }, | 125 | .data = &reset_simple_active_low }, |
| 126 | { .compatible = "aspeed,ast2400-lpc-reset" }, | 126 | { .compatible = "aspeed,ast2400-lpc-reset" }, |
| 127 | { .compatible = "aspeed,ast2500-lpc-reset" }, | 127 | { .compatible = "aspeed,ast2500-lpc-reset" }, |
| 128 | { .compatible = "bitmain,bm1880-reset", | ||
| 129 | .data = &reset_simple_active_low }, | ||
| 128 | { /* sentinel */ }, | 130 | { /* sentinel */ }, |
| 129 | }; | 131 | }; |
| 130 | 132 | ||
| @@ -35,6 +35,7 @@ struct meson_canvas { · 34 unmodified lines | |||
| 35 | void __iomem *reg_base; | 35 | void __iomem *reg_base; |
| 36 | spinlock_t lock; /* canvas device lock */ | 36 | spinlock_t lock; /* canvas device lock */ |
| 37 | u8 used[NUM_CANVAS]; | 37 | u8 used[NUM_CANVAS]; |
| 38 | bool supports_endianness; | ||
| 38 | }; | 39 | }; |
| 39 | 40 | ||
| 40 | static void canvas_write(struct meson_canvas *canvas, u32 reg, u32 val) | 41 | static void canvas_write(struct meson_canvas *canvas, u32 reg, u32 val) |
| @@ -86,6 +87,12 @@ int meson_canvas_config(struct meson_canvas *canvas, u8 canvas_index, · 45 unmodified lines | |||
| 86 | { | 87 | { |
| 87 | unsigned long flags; | 88 | unsigned long flags; |
| 88 | 89 | ||
| 90 | if (endian && !canvas->supports_endianness) { | ||
| 91 | dev_err(canvas->dev, | ||
| 92 | "Endianness is not supported on this SoC\n"); | ||
| 93 | return -EINVAL; | ||
| 94 | } | ||
| 95 | |||
| 89 | spin_lock_irqsave(&canvas->lock, flags); | 96 | spin_lock_irqsave(&canvas->lock, flags); |
| 90 | if (!canvas->used[canvas_index]) { | 97 | if (!canvas->used[canvas_index]) { |
| 91 | dev_err(canvas->dev, | 98 | dev_err(canvas->dev, |
| @@ -172,6 +179,8 @@ static int meson_canvas_probe(struct platform_device *pdev) · 80 unmodified lines | |||
| 172 | if (IS_ERR(canvas->reg_base)) | 179 | if (IS_ERR(canvas->reg_base)) |
| 173 | return PTR_ERR(canvas->reg_base); | 180 | return PTR_ERR(canvas->reg_base); |
| 174 | 181 | ||
| 182 | canvas->supports_endianness = of_device_get_match_data(dev); | ||
| 183 | |||
| 175 | canvas->dev = dev; | 184 | canvas->dev = dev; |
| 176 | spin_lock_init(&canvas->lock); | 185 | spin_lock_init(&canvas->lock); |
| 177 | dev_set_drvdata(dev, canvas); | 186 | dev_set_drvdata(dev, canvas); |
| @@ -180,7 +189,10 @@ static int meson_canvas_probe(struct platform_device *pdev) · 2 unmodified lines | |||
| 180 | } | 189 | } |
| 181 | 190 | ||
| 182 | static const struct of_device_id canvas_dt_match[] = { | 191 | static const struct of_device_id canvas_dt_match[] = { |
| 183 | { .compatible = "amlogic,canvas" }, | 192 | { .compatible = "amlogic,meson8-canvas", .data = (void *)false, }, |
| 193 | { .compatible = "amlogic,meson8b-canvas", .data = (void *)false, }, | ||
| 194 | { .compatible = "amlogic,meson8m2-canvas", .data = (void *)false, }, | ||
| 195 | { .compatible = "amlogic,canvas", .data = (void *)true, }, | ||
| 184 | {} | 196 | {} |
| 185 | }; | 197 | }; |
| 186 | MODULE_DEVICE_TABLE(of, canvas_dt_match); | 198 | MODULE_DEVICE_TABLE(of, canvas_dt_match); |
| @@ -64,6 +64,7 @@ static long aspeed_lpc_ctrl_ioctl(struct file *file, unsigned int cmd, · 63 unmodified lines | |||
| 64 | unsigned long param) | 64 | unsigned long param) |
| 65 | { | 65 | { |
| 66 | struct aspeed_lpc_ctrl *lpc_ctrl = file_aspeed_lpc_ctrl(file); | 66 | struct aspeed_lpc_ctrl *lpc_ctrl = file_aspeed_lpc_ctrl(file); |
| 67 | struct device *dev = file->private_data; | ||
| 67 | void __user *p = (void __user *)param; | 68 | void __user *p = (void __user *)param; |
| 68 | struct aspeed_lpc_ctrl_mapping map; | 69 | struct aspeed_lpc_ctrl_mapping map; |
| 69 | u32 addr; | 70 | u32 addr; |
| @@ -86,6 +87,12 @@ static long aspeed_lpc_ctrl_ioctl(struct file *file, unsigned int cmd, · 16 unmodified lines | |||
| 86 | if (map.window_id != 0) | 87 | if (map.window_id != 0) |
| 87 | return -EINVAL; | 88 | return -EINVAL; |
| 88 | 89 | ||
| 90 | /* If memory-region is not described in device tree */ | ||
| 91 | if (!lpc_ctrl->mem_size) { | ||
| 92 | dev_dbg(dev, "Didn't find reserved memory\n"); | ||
| 93 | return -ENXIO; | ||
| 94 | } | ||
| 95 | |||
| 89 | map.size = lpc_ctrl->mem_size; | 96 | map.size = lpc_ctrl->mem_size; |
| 90 | 97 | ||
| 91 | return copy_to_user(p, &map, sizeof(map)) ? -EFAULT : 0; | 98 | return copy_to_user(p, &map, sizeof(map)) ? -EFAULT : 0; |
| @@ -122,9 +129,18 @@ static long aspeed_lpc_ctrl_ioctl(struct file *file, unsigned int cmd, · 30 unmodified lines | |||
| 122 | return -EINVAL; | 129 | return -EINVAL; |
| 123 | 130 | ||
| 124 | if (map.window_type == ASPEED_LPC_CTRL_WINDOW_FLASH) { | 131 | if (map.window_type == ASPEED_LPC_CTRL_WINDOW_FLASH) { |
| 132 | if (!lpc_ctrl->pnor_size) { | ||
| 133 | dev_dbg(dev, "Didn't find host pnor flash\n"); | ||
| 134 | return -ENXIO; | ||
| 135 | } | ||
| 125 | addr = lpc_ctrl->pnor_base; | 136 | addr = lpc_ctrl->pnor_base; |
| 126 | size = lpc_ctrl->pnor_size; | 137 | size = lpc_ctrl->pnor_size; |
| 127 | } else if (map.window_type == ASPEED_LPC_CTRL_WINDOW_MEMORY) { | 138 | } else if (map.window_type == ASPEED_LPC_CTRL_WINDOW_MEMORY) { |
| 139 | /* If memory-region is not described in device tree */ | ||
| 140 | if (!lpc_ctrl->mem_size) { | ||
| 141 | dev_dbg(dev, "Didn't find reserved memory\n"); | ||
| 142 | return -ENXIO; | ||
| 143 | } | ||
| 128 | addr = lpc_ctrl->mem_base; | 144 | addr = lpc_ctrl->mem_base; |
| 129 | size = lpc_ctrl->mem_size; | 145 | size = lpc_ctrl->mem_size; |
| 130 | } else { | 146 | } else { |
| @@ -192,40 +208,41 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev) · 61 unmodified lines | |||
| 192 | if (!lpc_ctrl) | 208 | if (!lpc_ctrl) |
| 193 | return -ENOMEM; | 209 | return -ENOMEM; |
| 194 | 210 | ||
| 211 | /* If flash is described in device tree then store */ | ||
| 195 | node = of_parse_phandle(dev->of_node, "flash", 0); | 212 | node = of_parse_phandle(dev->of_node, "flash", 0); |
| 196 | if (!node) { | 213 | if (!node) { |
| 197 | dev_err(dev, "Didn't find host pnor flash node\n"); | 214 | dev_dbg(dev, "Didn't find host pnor flash node\n"); |
| 198 | return -ENODEV; | 215 | } else { |
| 199 | } | 216 | rc = of_address_to_resource(node, 1, &resm); |
| 217 | of_node_put(node); | ||
| 218 | if (rc) { | ||
| 219 | dev_err(dev, "Couldn't address to resource for flash\n"); | ||
| 220 | return rc; | ||
| 221 | } | ||
| 200 | 222 | ||
| 201 | rc = of_address_to_resource(node, 1, &resm); | 223 | lpc_ctrl->pnor_size = resource_size(&resm); |
| 202 | of_node_put(node); | 224 | lpc_ctrl->pnor_base = resm.start; |
| 203 | if (rc) { | ||
| 204 | dev_err(dev, "Couldn't address to resource for flash\n"); | ||
| 205 | return rc; | ||
| 206 | } | 225 | } |
| 207 | 226 | ||
| 208 | lpc_ctrl->pnor_size = resource_size(&resm); | ||
| 209 | lpc_ctrl->pnor_base = resm.start; | ||
| 210 | 227 | ||
| 211 | dev_set_drvdata(&pdev->dev, lpc_ctrl); | 228 | dev_set_drvdata(&pdev->dev, lpc_ctrl); |
| 212 | 229 | ||
| 230 | /* If memory-region is described in device tree then store */ | ||
| 213 | node = of_parse_phandle(dev->of_node, "memory-region", 0); | 231 | node = of_parse_phandle(dev->of_node, "memory-region", 0); |
| 214 | if (!node) { | 232 | if (!node) { |
| 215 | dev_err(dev, "Didn't find reserved memory\n"); | 233 | dev_dbg(dev, "Didn't find reserved memory\n"); |
| 216 | return -EINVAL; | 234 | } else { |
| 217 | } | 235 | rc = of_address_to_resource(node, 0, &resm); |
| 236 | of_node_put(node); | ||
| 237 | if (rc) { | ||
| 238 | dev_err(dev, "Couldn't address to resource for reserved memory\n"); | ||
| 239 | return -ENXIO; | ||
| 240 | } | ||
| 218 | 241 | ||
| 219 | rc = of_address_to_resource(node, 0, &resm); | 242 | lpc_ctrl->mem_size = resource_size(&resm); |
| 220 | of_node_put(node); | 243 | lpc_ctrl->mem_base = resm.start; |
| 221 | if (rc) { | ||
| 222 | dev_err(dev, "Couldn't address to resource for reserved memory\n"); | ||
| 223 | return -ENOMEM; | ||
| 224 | } | 244 | } |
| 225 | 245 | ||
| 226 | lpc_ctrl->mem_size = resource_size(&resm); | ||
| 227 | lpc_ctrl->mem_base = resm.start; | ||
| 228 | |||
| 229 | lpc_ctrl->regmap = syscon_node_to_regmap( | 246 | lpc_ctrl->regmap = syscon_node_to_regmap( |
| 230 | pdev->dev.parent->of_node); | 247 | pdev->dev.parent->of_node); |
| 231 | if (IS_ERR(lpc_ctrl->regmap)) { | 248 | if (IS_ERR(lpc_ctrl->regmap)) { |
| @@ -254,8 +271,6 @@ static int aspeed_lpc_ctrl_probe(struct platform_device *pdev) · 22 unmodified lines | |||
| 254 | goto err; | 271 | goto err; |
| 255 | } | 272 | } |
| 256 | 273 | ||
| 257 | dev_info(dev, "Loaded at %pr\n", &resm); | ||
| 258 | |||
| 259 | return 0; | 274 | return 0; |
| 260 | 275 | ||
| 261 | err: | 276 | err: |
| @@ -30,4 +30,14 @@ config FSL_MC_DPIO · 29 unmodified lines | |||
| 30 | other DPAA2 objects. This driver does not expose the DPIO | 30 | other DPAA2 objects. This driver does not expose the DPIO |
| 31 | objects individually, but groups them under a service layer | 31 | objects individually, but groups them under a service layer |
| 32 | API. | 32 | API. |
| 33 | |||
| 34 | config DPAA2_CONSOLE | ||
| 35 | tristate "QorIQ DPAA2 console driver" | ||
| 36 | depends on OF && (ARCH_LAYERSCAPE || COMPILE_TEST) | ||
| 37 | default y | ||
| 38 | help | ||
| 39 | Console driver for DPAA2 platforms. Exports 2 char devices, | ||
| 40 | /dev/dpaa2_mc_console and /dev/dpaa2_aiop_console, | ||
| 41 | which can be used to dump the Management Complex and AIOP | ||
| 42 | firmware logs. | ||
| 33 | endmenu | 43 | endmenu |
| @@ -8,3 +8,4 @@ obj-$(CONFIG_QUICC_ENGINE) += qe/ · 7 unmodified lines | |||
| 8 | obj-$(CONFIG_CPM) += qe/ | 8 | obj-$(CONFIG_CPM) += qe/ |
| 9 | obj-$(CONFIG_FSL_GUTS) += guts.o | 9 | obj-$(CONFIG_FSL_GUTS) += guts.o |
| 10 | obj-$(CONFIG_FSL_MC_DPIO) += dpio/ | 10 | obj-$(CONFIG_FSL_MC_DPIO) += dpio/ |
| 11 | obj-$(CONFIG_DPAA2_CONSOLE) += dpaa2-console.o | ||
| @@ -0,0 +1,329 @@ | |||
| 1 | // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) | ||
| 2 | /* | ||
| 3 | * Freescale DPAA2 Platforms Console Driver | ||
| 4 | * | ||
| 5 | * Copyright 2015-2016 Freescale Semiconductor Inc. | ||
| 6 | * Copyright 2018 NXP | ||
| 7 | */ | ||
| 8 | |||
| 9 | #define pr_fmt(fmt) "dpaa2-console: " fmt | ||
| 10 | |||
| 11 | #include <linux/module.h> | ||
| 12 | #include <linux/of_device.h> | ||
| 13 | #include <linux/of_address.h> | ||
| 14 | #include <linux/miscdevice.h> | ||
| 15 | #include <linux/uaccess.h> | ||
| 16 | #include <linux/slab.h> | ||
| 17 | #include <linux/fs.h> | ||
| 18 | #include <linux/io.h> | ||
| 19 | |||
| 20 | /* MC firmware base low/high registers indexes */ | ||
| 21 | #define MCFBALR_OFFSET 0 | ||
| 22 | #define MCFBAHR_OFFSET 1 | ||
| 23 | |||
| 24 | /* Bit masks used to get the most/least significant part of the MC base addr */ | ||
| 25 | #define MC_FW_ADDR_MASK_HIGH 0x1FFFF | ||
| 26 | #define MC_FW_ADDR_MASK_LOW 0xE0000000 | ||
| 27 | |||
| 28 | #define MC_BUFFER_OFFSET 0x01000000 | ||
| 29 | #define MC_BUFFER_SIZE (1024 * 1024 * 16) | ||
| 30 | #define MC_OFFSET_DELTA MC_BUFFER_OFFSET | ||
| 31 | |||
| 32 | #define AIOP_BUFFER_OFFSET 0x06000000 | ||
| 33 | #define AIOP_BUFFER_SIZE (1024 * 1024 * 16) | ||
| 34 | #define AIOP_OFFSET_DELTA 0 | ||
| 35 | |||
| 36 | #define LOG_HEADER_FLAG_BUFFER_WRAPAROUND 0x80000000 | ||
| 37 | #define LAST_BYTE(a) ((a) & ~(LOG_HEADER_FLAG_BUFFER_WRAPAROUND)) | ||
| 38 | |||
| 39 | /* MC and AIOP Magic words */ | ||
| 40 | #define MAGIC_MC 0x4d430100 | ||
| 41 | #define MAGIC_AIOP 0x41494F50 | ||
| 42 | |||
| 43 | struct log_header { | ||
| 44 | __le32 magic_word; | ||
| 45 | char reserved[4]; | ||
| 46 | __le32 buf_start; | ||
| 47 | __le32 buf_length; | ||
| 48 | __le32 last_byte; | ||
| 49 | }; | ||
| 50 | |||
| 51 | struct console_data { | ||
| 52 | void __iomem *map_addr; | ||
| 53 | struct log_header __iomem *hdr; | ||
| 54 | void __iomem *start_addr; | ||
| 55 | void __iomem *end_addr; | ||
| 56 | void __iomem *end_of_data; | ||
| 57 | void __iomem *cur_ptr; | ||
| 58 | }; | ||
| 59 | |||
| 60 | static struct resource mc_base_addr; | ||
| 61 | |||
| 62 | static inline void adjust_end(struct console_data *cd) | ||
| 63 | { | ||
| 64 | u32 last_byte = readl(&cd->hdr->last_byte); | ||
| 65 | |||
| 66 | cd->end_of_data = cd->start_addr + LAST_BYTE(last_byte); | ||
| 67 | } | ||
| 68 | |||
| 69 | static u64 get_mc_fw_base_address(void) | ||
| 70 | { | ||
| 71 | u64 mcfwbase = 0ULL; | ||
| 72 | u32 __iomem *mcfbaregs; | ||
| 73 | |||
| 74 | mcfbaregs = ioremap(mc_base_addr.start, resource_size(&mc_base_addr)); | ||
| 75 | if (!mcfbaregs) { | ||
| 76 | pr_err("could not map MC Firmaware Base registers\n"); | ||
| 77 | return 0; | ||
| 78 | } | ||
| 79 | |||
| 80 | mcfwbase = readl(mcfbaregs + MCFBAHR_OFFSET) & | ||
| 81 | MC_FW_ADDR_MASK_HIGH; | ||
| 82 | mcfwbase <<= 32; | ||
| 83 | mcfwbase |= readl(mcfbaregs + MCFBALR_OFFSET) & MC_FW_ADDR_MASK_LOW; | ||
| 84 | iounmap(mcfbaregs); | ||
| 85 | |||
| 86 | pr_debug("MC base address at 0x%016llx\n", mcfwbase); | ||
| 87 | return mcfwbase; | ||
| 88 | } | ||
| 89 | |||
| 90 | static ssize_t dpaa2_console_size(struct console_data *cd) | ||
| 91 | { | ||
| 92 | ssize_t size; | ||
| 93 | |||
| 94 | if (cd->cur_ptr <= cd->end_of_data) | ||
| 95 | size = cd->end_of_data - cd->cur_ptr; | ||
| 96 | else | ||
| 97 | size = (cd->end_addr - cd->cur_ptr) + | ||
| 98 | (cd->end_of_data - cd->start_addr); | ||
| 99 | |||
| 100 | return size; | ||
| 101 | } | ||
| 102 | |||
| 103 | static int dpaa2_generic_console_open(struct inode *node, struct file *fp, | ||
| 104 | u64 offset, u64 size, | ||
| 105 | u32 expected_magic, | ||
| 106 | u32 offset_delta) | ||
| 107 | { | ||
| 108 | u32 read_magic, wrapped, last_byte, buf_start, buf_length; | ||
| 109 | struct console_data *cd; | ||
| 110 | u64 base_addr; | ||
| 111 | int err; | ||
| 112 | |||
| 113 | cd = kmalloc(sizeof(*cd), GFP_KERNEL); | ||
| 114 | if (!cd) | ||
| 115 | return -ENOMEM; | ||
| 116 | |||
| 117 | base_addr = get_mc_fw_base_address(); | ||
| 118 | if (!base_addr) { | ||
| 119 | err = -EIO; | ||
| 120 | goto err_fwba; | ||
| 121 | } | ||
| 122 | |||
| 123 | cd->map_addr = ioremap(base_addr + offset, size); | ||
| 124 | if (!cd->map_addr) { | ||
| 125 | pr_err("cannot map console log memory\n"); | ||
| 126 | err = -EIO; | ||
| 127 | goto err_ioremap; | ||
| 128 | } | ||
| 129 | |||
| 130 | cd->hdr = (struct log_header __iomem *)cd->map_addr; | ||
| 131 | read_magic = readl(&cd->hdr->magic_word); | ||
| 132 | last_byte = readl(&cd->hdr->last_byte); | ||
| 133 | buf_start = readl(&cd->hdr->buf_start); | ||
| 134 | buf_length = readl(&cd->hdr->buf_length); | ||
| 135 | |||
| 136 | if (read_magic != expected_magic) { | ||
| 137 | pr_warn("expected = %08x, read = %08x\n", | ||
| 138 | expected_magic, read_magic); | ||
| 139 | err = -EIO; | ||
| 140 | goto err_magic; | ||
| 141 | } | ||
| 142 | |||
| 143 | cd->start_addr = cd->map_addr + buf_start - offset_delta; | ||
| 144 | cd->end_addr = cd->start_addr + buf_length; | ||
| 145 | |||
| 146 | wrapped = last_byte & LOG_HEADER_FLAG_BUFFER_WRAPAROUND; | ||
| 147 | |||
| 148 | adjust_end(cd); | ||
| 149 | if (wrapped && cd->end_of_data != cd->end_addr) | ||
| 150 | cd->cur_ptr = cd->end_of_data + 1; | ||
| 151 | else | ||
| 152 | cd->cur_ptr = cd->start_addr; | ||
| 153 | |||
| 154 | fp->private_data = cd; | ||
| 155 | |||
| 156 | return 0; | ||
| 157 | |||
| 158 | err_magic: | ||
| 159 | iounmap(cd->map_addr); | ||
| 160 | |||
| 161 | err_ioremap: | ||
| 162 | err_fwba: | ||
| 163 | kfree(cd); | ||
| 164 | |||
| 165 | return err; | ||
| 166 | } | ||
| 167 | |||
| 168 | static int dpaa2_mc_console_open(struct inode *node, struct file *fp) | ||
| 169 | { | ||
| 170 | return dpaa2_generic_console_open(node, fp, | ||
| 171 | MC_BUFFER_OFFSET, MC_BUFFER_SIZE, | ||
| 172 | MAGIC_MC, MC_OFFSET_DELTA); | ||
| 173 | } | ||
| 174 | |||
| 175 | static int dpaa2_aiop_console_open(struct inode *node, struct file *fp) | ||
| 176 | { | ||
| 177 | return dpaa2_generic_console_open(node, fp, | ||
| 178 | AIOP_BUFFER_OFFSET, AIOP_BUFFER_SIZE, | ||
| 179 | MAGIC_AIOP, AIOP_OFFSET_DELTA); | ||
| 180 | } | ||
| 181 | |||
| 182 | static int dpaa2_console_close(struct inode *node, struct file *fp) | ||
| 183 | { | ||
| 184 | struct console_data *cd = fp->private_data; | ||
| 185 | |||
| 186 | iounmap(cd->map_addr); | ||
| 187 | kfree(cd); | ||
| 188 | return 0; | ||
| 189 | } | ||
| 190 | |||
| 191 | static ssize_t dpaa2_console_read(struct file *fp, char __user *buf, | ||
| 192 | size_t count, loff_t *f_pos) | ||
| 193 | { | ||
| 194 | struct console_data *cd = fp->private_data; | ||
| 195 | size_t bytes = dpaa2_console_size(cd); | ||
| 196 | size_t bytes_end = cd->end_addr - cd->cur_ptr; | ||
| 197 | size_t written = 0; | ||
| 198 | void *kbuf; | ||
| 199 | int err; | ||
| 200 | |||
| 201 | /* Check if we need to adjust the end of data addr */ | ||
| 202 | adjust_end(cd); | ||
| 203 | |||
| 204 | if (cd->end_of_data == cd->cur_ptr) | ||
| 205 | return 0; | ||
| 206 | |||
| 207 | if (count < bytes) | ||
| 208 | bytes = count; | ||
| 209 | |||
| 210 | kbuf = kmalloc(bytes, GFP_KERNEL); | ||
| 211 | if (!kbuf) | ||
| 212 | return -ENOMEM; | ||
| 213 | |||
| 214 | if (bytes > bytes_end) { | ||
| 215 | memcpy_fromio(kbuf, cd->cur_ptr, bytes_end); | ||
| 216 | if (copy_to_user(buf, kbuf, bytes_end)) { | ||
| 217 | err = -EFAULT; | ||
| 218 | goto err_free_buf; | ||
| 219 | } | ||
| 220 | buf += bytes_end; | ||
| 221 | cd->cur_ptr = cd->start_addr; | ||
| 222 | bytes -= bytes_end; | ||
| 223 | written += bytes_end; | ||
| 224 | } | ||
| 225 | |||
| 226 | memcpy_fromio(kbuf, cd->cur_ptr, bytes); | ||
| 227 | if (copy_to_user(buf, kbuf, bytes)) { | ||
| 228 | err = -EFAULT; | ||
| 229 | goto err_free_buf; | ||
| 230 | } | ||
| 231 | cd->cur_ptr += bytes; | ||
| 232 | written += bytes; | ||
| 233 | |||
| 234 | return written; | ||
| 235 | |||
| 236 | err_free_buf: | ||
| 237 | kfree(kbuf); | ||
| 238 | |||
| 239 | return err; | ||
| 240 | } | ||
| 241 | |||
| 242 | static const struct file_operations dpaa2_mc_console_fops = { | ||
| 243 | .owner = THIS_MODULE, | ||
| 244 | .open = dpaa2_mc_console_open, | ||
| 245 | .release = dpaa2_console_close, | ||
| 246 | .read = dpaa2_console_read, | ||
| 247 | }; | ||
| 248 | |||
| 249 | static struct miscdevice dpaa2_mc_console_dev = { | ||
| 250 | .minor = MISC_DYNAMIC_MINOR, | ||
| 251 | .name = "dpaa2_mc_console", | ||
| 252 | .fops = &dpaa2_mc_console_fops | ||
| 253 | }; | ||
| 254 | |||
| 255 | static const struct file_operations dpaa2_aiop_console_fops = { | ||
| 256 | .owner = THIS_MODULE, | ||
| 257 | .open = dpaa2_aiop_console_open, | ||
| 258 | .release = dpaa2_console_close, | ||
| 259 | .read = dpaa2_console_read, | ||
| 260 | }; | ||
| 261 | |||
| 262 | static struct miscdevice dpaa2_aiop_console_dev = { | ||
| 263 | .minor = MISC_DYNAMIC_MINOR, | ||
| 264 | .name = "dpaa2_aiop_console", | ||
| 265 | .fops = &dpaa2_aiop_console_fops | ||
| 266 | }; | ||
| 267 | |||
| 268 | static int dpaa2_console_probe(struct platform_device *pdev) | ||
| 269 | { | ||
| 270 | int error; | ||
| 271 | |||
| 272 | error = of_address_to_resource(pdev->dev.of_node, 0, &mc_base_addr); | ||
| 273 | if (error < 0) { | ||
| 274 | pr_err("of_address_to_resource() failed for %pOF with %d\n", | ||
| 275 | pdev->dev.of_node, error); | ||
| 276 | return error; | ||
| 277 | } | ||
| 278 | |||
| 279 | error = misc_register(&dpaa2_mc_console_dev); | ||
| 280 | if (error) { | ||
| 281 | pr_err("cannot register device %s\n", | ||
| 282 | dpaa2_mc_console_dev.name); | ||
| 283 | goto err_register_mc; | ||
| 284 | } | ||
| 285 | |||
| 286 | error = misc_register(&dpaa2_aiop_console_dev); | ||
| 287 | if (error) { | ||
| 288 | pr_err("cannot register device %s\n", | ||
| 289 | dpaa2_aiop_console_dev.name); | ||
| 290 | goto err_register_aiop; | ||
| 291 | } | ||
| 292 | |||
| 293 | return 0; | ||
| 294 | |||
| 295 | err_register_aiop: | ||
| 296 | misc_deregister(&dpaa2_mc_console_dev); | ||
| 297 | err_register_mc: | ||
| 298 | return error; | ||
| 299 | } | ||
| 300 | |||
| 301 | static int dpaa2_console_remove(struct platform_device *pdev) | ||
| 302 | { | ||
| 303 | misc_deregister(&dpaa2_mc_console_dev); | ||
| 304 | misc_deregister(&dpaa2_aiop_console_dev); | ||
| 305 | |||
| 306 | return 0; | ||
| 307 | } | ||
| 308 | |||
| 309 | static const struct of_device_id dpaa2_console_match_table[] = { | ||
| 310 | { .compatible = "fsl,dpaa2-console",}, | ||
| 311 | {}, | ||
| 312 | }; | ||
| 313 | |||
| 314 | MODULE_DEVICE_TABLE(of, dpaa2_console_match_table); | ||
| 315 | |||
| 316 | static struct platform_driver dpaa2_console_driver = { | ||
| 317 | .driver = { | ||
| 318 | .name = "dpaa2-console", | ||
| 319 | .pm = NULL, | ||
| 320 | .of_match_table = dpaa2_console_match_table, | ||
| 321 | }, | ||
| 322 | .probe = dpaa2_console_probe, | ||
| 323 | .remove = dpaa2_console_remove, | ||
| 324 | }; | ||
| 325 | module_platform_driver(dpaa2_console_driver); | ||
| 326 | |||
| 327 | MODULE_LICENSE("Dual BSD/GPL"); | ||
| 328 | MODULE_AUTHOR("Roy Pledge <roy.pledge@nxp.com>"); | ||
| 329 | MODULE_DESCRIPTION("DPAA2 console driver"); | ||
| @@ -197,13 +197,22 @@ static int dpaa2_dpio_probe(struct fsl_mc_device *dpio_dev) · 196 unmodified lines | |||
| 197 | desc.cpu); | 197 | desc.cpu); |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | /* | 200 | if (dpio_dev->obj_desc.region_count < 3) { |
| 201 | * Set the CENA regs to be the cache inhibited area of the portal to | 201 | /* No support for DDR backed portals, use classic mapping */ |
| 202 | * avoid coherency issues if a user migrates to another core. | 202 | /* |
| 203 | */ | 203 | * Set the CENA regs to be the cache inhibited area of the |
| 204 | desc.regs_cena = devm_memremap(dev, dpio_dev->regions[1].start, | 204 | * portal to avoid coherency issues if a user migrates to |
| 205 | resource_size(&dpio_dev->regions[1]), | 205 | * another core. |
| 206 | MEMREMAP_WC); | 206 | */ |
| 207 | desc.regs_cena = devm_memremap(dev, dpio_dev->regions[1].start, | ||
| 208 | resource_size(&dpio_dev->regions[1]), | ||
| 209 | MEMREMAP_WC); | ||
| 210 | } else { | ||
| 211 | desc.regs_cena = devm_memremap(dev, dpio_dev->regions[2].start, | ||
| 212 | resource_size(&dpio_dev->regions[2]), | ||
| 213 | MEMREMAP_WB); | ||
| 214 | } | ||
| 215 | |||
| 207 | if (IS_ERR(desc.regs_cena)) { | 216 | if (IS_ERR(desc.regs_cena)) { |
| 208 | dev_err(dev, "devm_memremap failed\n"); | 217 | dev_err(dev, "devm_memremap failed\n"); |
| 209 | err = PTR_ERR(desc.regs_cena); | 218 | err = PTR_ERR(desc.regs_cena); |
| @@ -15,6 +15,8 @@ · 14 unmodified lines | |||
| 15 | #define QMAN_REV_4000 0x04000000 | 15 | #define QMAN_REV_4000 0x04000000 |
| 16 | #define QMAN_REV_4100 0x04010000 | 16 | #define QMAN_REV_4100 0x04010000 |
| 17 | #define QMAN_REV_4101 0x04010001 | 17 | #define QMAN_REV_4101 0x04010001 |
| 18 | #define QMAN_REV_5000 0x05000000 | ||
| 19 | |||
| 18 | #define QMAN_REV_MASK 0xffff0000 | 20 | #define QMAN_REV_MASK 0xffff0000 |
| 19 | 21 | ||
| 20 | /* All QBMan command and result structures use this "valid bit" encoding */ | 22 | /* All QBMan command and result structures use this "valid bit" encoding */ |
| @@ -25,10 +27,17 @@ · 4 unmodified lines | |||
| 25 | #define QBMAN_WQCHAN_CONFIGURE 0x46 | 27 | #define QBMAN_WQCHAN_CONFIGURE 0x46 |
| 26 | 28 | ||
| 27 | /* CINH register offsets */ | 29 | /* CINH register offsets */ |
| 30 | #define QBMAN_CINH_SWP_EQCR_PI 0x800 | ||
| 28 | #define QBMAN_CINH_SWP_EQAR 0x8c0 | 31 | #define QBMAN_CINH_SWP_EQAR 0x8c0 |
| 32 | #define QBMAN_CINH_SWP_CR_RT 0x900 | ||
| 33 | #define QBMAN_CINH_SWP_VDQCR_RT 0x940 | ||
| 34 | #define QBMAN_CINH_SWP_EQCR_AM_RT 0x980 | ||
| 35 | #define QBMAN_CINH_SWP_RCR_AM_RT 0x9c0 | ||
| 29 | #define QBMAN_CINH_SWP_DQPI 0xa00 | 36 | #define QBMAN_CINH_SWP_DQPI 0xa00 |
| 30 | #define QBMAN_CINH_SWP_DCAP 0xac0 | 37 | #define QBMAN_CINH_SWP_DCAP 0xac0 |
| 31 | #define QBMAN_CINH_SWP_SDQCR 0xb00 | 38 | #define QBMAN_CINH_SWP_SDQCR 0xb00 |
| 39 | #define QBMAN_CINH_SWP_EQCR_AM_RT2 0xb40 | ||
| 40 | #define QBMAN_CINH_SWP_RCR_PI 0xc00 | ||
| 32 | #define QBMAN_CINH_SWP_RAR 0xcc0 | 41 | #define QBMAN_CINH_SWP_RAR 0xcc0 |
| 33 | #define QBMAN_CINH_SWP_ISR 0xe00 | 42 | #define QBMAN_CINH_SWP_ISR 0xe00 |
| 34 | #define QBMAN_CINH_SWP_IER 0xe40 | 43 | #define QBMAN_CINH_SWP_IER 0xe40 |
| @@ -43,6 +52,13 @@ · 8 unmodified lines | |||
| 43 | #define QBMAN_CENA_SWP_RR(vb) (0x700 + ((u32)(vb) >> 1)) | 52 | #define QBMAN_CENA_SWP_RR(vb) (0x700 + ((u32)(vb) >> 1)) |
| 44 | #define QBMAN_CENA_SWP_VDQCR 0x780 | 53 | #define QBMAN_CENA_SWP_VDQCR 0x780 |
| 45 | 54 | ||
| 55 | /* CENA register offsets in memory-backed mode */ | ||
| 56 | #define QBMAN_CENA_SWP_DQRR_MEM(n) (0x800 + ((u32)(n) << 6)) | ||
| 57 | #define QBMAN_CENA_SWP_RCR_MEM(n) (0x1400 + ((u32)(n) << 6)) | ||
| 58 | #define QBMAN_CENA_SWP_CR_MEM 0x1600 | ||
| 59 | #define QBMAN_CENA_SWP_RR_MEM 0x1680 | ||
| 60 | #define QBMAN_CENA_SWP_VDQCR_MEM 0x1780 | ||
| 61 | |||
| 46 | /* Reverse mapping of QBMAN_CENA_SWP_DQRR() */ | 62 | /* Reverse mapping of QBMAN_CENA_SWP_DQRR() */ |
| 47 | #define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)(p) & 0x1ff) >> 6) | 63 | #define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)(p) & 0x1ff) >> 6) |
| 48 | 64 | ||
| @@ -96,10 +112,13 @@ static inline void *qbman_get_cmd(struct qbman_swp *p, u32 offset) · 47 unmodified lines | |||
| 96 | 112 | ||
| 97 | #define SWP_CFG_DQRR_MF_SHIFT 20 | 113 | #define SWP_CFG_DQRR_MF_SHIFT 20 |
| 98 | #define SWP_CFG_EST_SHIFT 16 | 114 | #define SWP_CFG_EST_SHIFT 16 |
| 115 | #define SWP_CFG_CPBS_SHIFT 15 | ||
| 99 | #define SWP_CFG_WN_SHIFT 14 | 116 | #define SWP_CFG_WN_SHIFT 14 |
| 100 | #define SWP_CFG_RPM_SHIFT 12 | 117 | #define SWP_CFG_RPM_SHIFT 12 |
| 101 | #define SWP_CFG_DCM_SHIFT 10 | 118 | #define SWP_CFG_DCM_SHIFT 10 |
| 102 | #define SWP_CFG_EPM_SHIFT 8 | 119 | #define SWP_CFG_EPM_SHIFT 8 |
| 120 | #define SWP_CFG_VPM_SHIFT 7 | ||
| 121 | #define SWP_CFG_CPM_SHIFT 6 | ||
| 103 | #define SWP_CFG_SD_SHIFT 5 | 122 | #define SWP_CFG_SD_SHIFT 5 |
| 104 | #define SWP_CFG_SP_SHIFT 4 | 123 | #define SWP_CFG_SP_SHIFT 4 |
| 105 | #define SWP_CFG_SE_SHIFT 3 | 124 | #define SWP_CFG_SE_SHIFT 3 |
| @@ -125,6 +144,8 @@ static inline u32 qbman_set_swp_cfg(u8 max_fill, u8 wn, u8 est, u8 rpm, u8 dcm, · 19 unmodified lines | |||
| 125 | ep << SWP_CFG_EP_SHIFT); | 144 | ep << SWP_CFG_EP_SHIFT); |
| 126 | } | 145 | } |
| 127 | 146 | ||
| 147 | #define QMAN_RT_MODE 0x00000100 | ||
| 148 | |||
| 128 | /** | 149 | /** |
| 129 | * qbman_swp_init() - Create a functional object representing the given | 150 | * qbman_swp_init() - Create a functional object representing the given |
| 130 | * QBMan portal descriptor. | 151 | * QBMan portal descriptor. |
| @@ -146,6 +167,8 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) · 15 unmodified lines | |||
| 146 | p->sdq |= qbman_sdqcr_dct_prio_ics << QB_SDQCR_DCT_SHIFT; | 167 | p->sdq |= qbman_sdqcr_dct_prio_ics << QB_SDQCR_DCT_SHIFT; |
| 147 | p->sdq |= qbman_sdqcr_fc_up_to_3 << QB_SDQCR_FC_SHIFT; | 168 | p->sdq |= qbman_sdqcr_fc_up_to_3 << QB_SDQCR_FC_SHIFT; |
| 148 | p->sdq |= QMAN_SDQCR_TOKEN << QB_SDQCR_TOK_SHIFT; | 169 | p->sdq |= QMAN_SDQCR_TOKEN << QB_SDQCR_TOK_SHIFT; |
| 170 | if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000) | ||
| 171 | p->mr.valid_bit = QB_VALID_BIT; | ||
| 149 | 172 | ||
| 150 | atomic_set(&p->vdq.available, 1); | 173 | atomic_set(&p->vdq.available, 1); |
| 151 | p->vdq.valid_bit = QB_VALID_BIT; | 174 | p->vdq.valid_bit = QB_VALID_BIT; |
| @@ -163,6 +186,9 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) · 11 unmodified lines | |||
| 163 | p->addr_cena = d->cena_bar; | 186 | p->addr_cena = d->cena_bar; |
| 164 | p->addr_cinh = d->cinh_bar; | 187 | p->addr_cinh = d->cinh_bar; |
| 165 | 188 | ||
| 189 | if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000) | ||
| 190 | memset(p->addr_cena, 0, 64 * 1024); | ||
| 191 | |||
| 166 | reg = qbman_set_swp_cfg(p->dqrr.dqrr_size, | 192 | reg = qbman_set_swp_cfg(p->dqrr.dqrr_size, |
| 167 | 1, /* Writes Non-cacheable */ | 193 | 1, /* Writes Non-cacheable */ |
| 168 | 0, /* EQCR_CI stashing threshold */ | 194 | 0, /* EQCR_CI stashing threshold */ |
| @@ -175,6 +201,10 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) · 6 unmodified lines | |||
| 175 | 1, /* dequeue stashing priority == TRUE */ | 201 | 1, /* dequeue stashing priority == TRUE */ |
| 176 | 0, /* dequeue stashing enable == FALSE */ | 202 | 0, /* dequeue stashing enable == FALSE */ |
| 177 | 0); /* EQCR_CI stashing priority == FALSE */ | 203 | 0); /* EQCR_CI stashing priority == FALSE */ |
| 204 | if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000) | ||
| 205 | reg |= 1 << SWP_CFG_CPBS_SHIFT | /* memory-backed mode */ | ||
| 206 | 1 << SWP_CFG_VPM_SHIFT | /* VDQCR read triggered mode */ | ||
| 207 | 1 << SWP_CFG_CPM_SHIFT; /* CR read triggered mode */ | ||
| 178 | 208 | ||
| 179 | qbman_write_register(p, QBMAN_CINH_SWP_CFG, reg); | 209 | qbman_write_register(p, QBMAN_CINH_SWP_CFG, reg); |
| 180 | reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG); | 210 | reg = qbman_read_register(p, QBMAN_CINH_SWP_CFG); |
| @@ -184,6 +214,10 @@ struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d) · 3 unmodified lines | |||
| 184 | return NULL; | 214 | return NULL; |
| 185 | } | 215 | } |
| 186 | 216 | ||
| 217 | if ((p->desc->qman_version & QMAN_REV_MASK) >= QMAN_REV_5000) { | ||
| 218 | qbman_write_register(p, QBMAN_CINH_SWP_EQCR_PI, QMAN_RT_MODE); | ||
| 219 | qbman_write_register(p, QBMAN_CINH_SWP_RCR_PI, QMAN_RT_MODE); | ||
| 220 | } | ||
| 187 | /* | 221 | /* |
| 188 | * SDQCR needs to be initialized to 0 when no channels are | 222 | * SDQCR needs to be initialized to 0 when no channels are |
| 189 | * being dequeued from or else the QMan HW will indicate an | 223 | * being dequeued from or else the QMan HW will indicate an |
| @@ -278,7 +312,10 @@ void qbman_swp_interrupt_set_inhibit(struct qbman_swp *p, int inhibit) · 88 unmodified lines | |||
| 278 | */ | 312 | */ |
| 279 | void *qbman_swp_mc_start(struct qbman_swp *p) | 313 | void *qbman_swp_mc_start(struct qbman_swp *p) |
| 280 | { | 314 | { |
| 281 | return qbman_get_cmd(p, QBMAN_CENA_SWP_CR); | 315 | if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) |
| 316 | return qbman_get_cmd(p, QBMAN_CENA_SWP_CR); | ||
| 317 | else | ||
| 318 | return qbman_get_cmd(p, QBMAN_CENA_SWP_CR_MEM); | ||
| 282 | } | 319 | } |
| 283 | 320 | ||
| 284 | /* | 321 | /* |
| @@ -289,8 +326,14 @@ void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, u8 cmd_verb) · 4 unmodified lines | |||
| 289 | { | 326 | { |
| 290 | u8 *v = cmd; | 327 | u8 *v = cmd; |
| 291 | 328 | ||
| 292 | dma_wmb(); | 329 | if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) { |
| 293 | *v = cmd_verb | p->mc.valid_bit; | 330 | dma_wmb(); |
| 331 | *v = cmd_verb | p->mc.valid_bit; | ||
| 332 | } else { | ||
| 333 | *v = cmd_verb | p->mc.valid_bit; | ||
| 334 | dma_wmb(); | ||
| 335 | qbman_write_register(p, QBMAN_CINH_SWP_CR_RT, QMAN_RT_MODE); | ||
| 336 | } | ||
| 294 | } | 337 | } |
| 295 | 338 | ||
| 296 | /* | 339 | /* |
| @@ -301,13 +344,27 @@ void *qbman_swp_mc_result(struct qbman_swp *p) · 4 unmodified lines | |||
| 301 | { | 344 | { |
| 302 | u32 *ret, verb; | 345 | u32 *ret, verb; |
| 303 | 346 | ||
| 304 | ret = qbman_get_cmd(p, QBMAN_CENA_SWP_RR(p->mc.valid_bit)); | 347 | if ((p->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) { |
| 348 | ret = qbman_get_cmd(p, QBMAN_CENA_SWP_RR(p->mc.valid_bit)); | ||
| 349 | /* Remove the valid-bit - command completed if the rest | ||
| 350 | * is non-zero. | ||
| 351 | */ | ||
| 352 | verb = ret[0] & ~QB_VALID_BIT; | ||
| 353 | if (!verb) | ||
| 354 | return NULL; | ||
| 355 | p->mc.valid_bit ^= QB_VALID_BIT; | ||
| 356 | } else { | ||
| 357 | ret = qbman_get_cmd(p, QBMAN_CENA_SWP_RR_MEM); | ||
| 358 | /* Command completed if the valid bit is toggled */ | ||
| 359 | if (p->mr.valid_bit != (ret[0] & QB_VALID_BIT)) | ||
| 360 | return NULL; | ||
| 361 | /* Command completed if the rest is non-zero */ | ||
| 362 | verb = ret[0] & ~QB_VALID_BIT; | ||
| 363 | if (!verb) | ||
| 364 | return NULL; | ||
| 365 | p->mr.valid_bit ^= QB_VALID_BIT; | ||
| 366 | } | ||
| 305 | 367 | ||
| 306 | /* Remove the valid-bit - command completed if the rest is non-zero */ | ||
| 307 | verb = ret[0] & ~QB_VALID_BIT; | ||
| 308 | if (!verb) | ||
| 309 | return NULL; | ||
| 310 | p->mc.valid_bit ^= QB_VALID_BIT; | ||
| 311 | return ret; | 368 | return ret; |
| 312 | } | 369 | } |
| 313 | 370 | ||
| @@ -384,6 +441,18 @@ void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, u32 qdid, · 70 unmodified lines | |||
| 384 | #define EQAR_VB(eqar) ((eqar) & 0x80) | 441 | #define EQAR_VB(eqar) ((eqar) & 0x80) |
| 385 | #define EQAR_SUCCESS(eqar) ((eqar) & 0x100) | 442 | #define EQAR_SUCCESS(eqar) ((eqar) & 0x100) |
| 386 | 443 | ||
| 444 | static inline void qbman_write_eqcr_am_rt_register(struct qbman_swp *p, | ||
| 445 | u8 idx) | ||
| 446 | { | ||
| 447 | if (idx < 16) | ||
| 448 | qbman_write_register(p, QBMAN_CINH_SWP_EQCR_AM_RT + idx * 4, | ||
| 449 | QMAN_RT_MODE); | ||
| 450 | else | ||
| 451 | qbman_write_register(p, QBMAN_CINH_SWP_EQCR_AM_RT2 + | ||
| 452 | (idx - 16) * 4, | ||
| 453 | QMAN_RT_MODE); | ||
| 454 | } | ||
| 455 | |||
| 387 | /** | 456 | /** |
| 388 | * qbman_swp_enqueue() - Issue an enqueue command | 457 | * qbman_swp_enqueue() - Issue an enqueue command |
| 389 | * @s: the software portal used for enqueue | 458 | * @s: the software portal used for enqueue |
| @@ -408,9 +477,15 @@ int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d, · 18 unmodified lines | |||
| 408 | memcpy(&p->dca, &d->dca, 31); | 477 | memcpy(&p->dca, &d->dca, 31); |
| 409 | memcpy(&p->fd, fd, sizeof(*fd)); | 478 | memcpy(&p->fd, fd, sizeof(*fd)); |
| 410 | 479 | ||
| 411 | /* Set the verb byte, have to substitute in the valid-bit */ | 480 | if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) { |
| 412 | dma_wmb(); | 481 | /* Set the verb byte, have to substitute in the valid-bit */ |
| 413 | p->verb = d->verb | EQAR_VB(eqar); | 482 | dma_wmb(); |
| 483 | p->verb = d->verb | EQAR_VB(eqar); | ||
| 484 | } else { | ||
| 485 | p->verb = d->verb | EQAR_VB(eqar); | ||
| 486 | dma_wmb(); | ||
| 487 | qbman_write_eqcr_am_rt_register(s, EQAR_IDX(eqar)); | ||
| 488 | } | ||
| 414 | 489 | ||
| 415 | return 0; | 490 | return 0; |
| 416 | } | 491 | } |
| @@ -587,17 +662,27 @@ int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d) · 170 unmodified lines | |||
| 587 | return -EBUSY; | 662 | return -EBUSY; |
| 588 | } | 663 | } |
| 589 | s->vdq.storage = (void *)(uintptr_t)d->rsp_addr_virt; | 664 | s->vdq.storage = (void *)(uintptr_t)d->rsp_addr_virt; |
| 590 | p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR); | 665 | if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) |
| 666 | p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR); | ||
| 667 | else | ||
| 668 | p = qbman_get_cmd(s, QBMAN_CENA_SWP_VDQCR_MEM); | ||
| 591 | p->numf = d->numf; | 669 | p->numf = d->numf; |
| 592 | p->tok = QMAN_DQ_TOKEN_VALID; | 670 | p->tok = QMAN_DQ_TOKEN_VALID; |
| 593 | p->dq_src = d->dq_src; | 671 | p->dq_src = d->dq_src; |
| 594 | p->rsp_addr = d->rsp_addr; | 672 | p->rsp_addr = d->rsp_addr; |
| 595 | p->rsp_addr_virt = d->rsp_addr_virt; | 673 | p->rsp_addr_virt = d->rsp_addr_virt; |
| 596 | dma_wmb(); | ||
| 597 | 674 | ||
| 598 | /* Set the verb byte, have to substitute in the valid-bit */ | 675 | if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) { |
| 599 | p->verb = d->verb | s->vdq.valid_bit; | 676 | dma_wmb(); |
| 600 | s->vdq.valid_bit ^= QB_VALID_BIT; | 677 | /* Set the verb byte, have to substitute in the valid-bit */ |
| 678 | p->verb = d->verb | s->vdq.valid_bit; | ||
| 679 | s->vdq.valid_bit ^= QB_VALID_BIT; | ||
| 680 | } else { | ||
| 681 | p->verb = d->verb | s->vdq.valid_bit; | ||
| 682 | s->vdq.valid_bit ^= QB_VALID_BIT; | ||
| 683 | dma_wmb(); | ||
| 684 | qbman_write_register(s, QBMAN_CINH_SWP_VDQCR_RT, QMAN_RT_MODE); | ||
| 685 | } | ||
| 601 | 686 | ||
| 602 | return 0; | 687 | return 0; |
| 603 | } | 688 | } |
| @@ -655,7 +740,10 @@ const struct dpaa2_dq *qbman_swp_dqrr_next(struct qbman_swp *s) · 51 unmodified lines | |||
| 655 | QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx))); | 740 | QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx))); |
| 656 | } | 741 | } |
| 657 | 742 | ||
| 658 | p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); | 743 | if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) |
| 744 | p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx)); | ||
| 745 | else | ||
| 746 | p = qbman_get_cmd(s, QBMAN_CENA_SWP_DQRR_MEM(s->dqrr.next_idx)); | ||
| 659 | verb = p->dq.verb; | 747 | verb = p->dq.verb; |
| 660 | 748 | ||
| 661 | /* | 749 | /* |
| @@ -807,18 +895,28 @@ int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d, · 145 unmodified lines | |||
| 807 | return -EBUSY; | 895 | return -EBUSY; |
| 808 | 896 | ||
| 809 | /* Start the release command */ | 897 | /* Start the release command */ |
| 810 | p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR(RAR_IDX(rar))); | 898 | if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) |
| 899 | p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR(RAR_IDX(rar))); | ||
| 900 | else | ||
| 901 | p = qbman_get_cmd(s, QBMAN_CENA_SWP_RCR_MEM(RAR_IDX(rar))); | ||
| 811 | /* Copy the caller's buffer pointers to the command */ | 902 | /* Copy the caller's buffer pointers to the command */ |
| 812 | for (i = 0; i < num_buffers; i++) | 903 | for (i = 0; i < num_buffers; i++) |
| 813 | p->buf[i] = cpu_to_le64(buffers[i]); | 904 | p->buf[i] = cpu_to_le64(buffers[i]); |
| 814 | p->bpid = d->bpid; | 905 | p->bpid = d->bpid; |
| 815 | 906 | ||
| 816 | /* | 907 | if ((s->desc->qman_version & QMAN_REV_MASK) < QMAN_REV_5000) { |
| 817 | * Set the verb byte, have to substitute in the valid-bit and the number | 908 | /* |
| 818 | * of buffers. | 909 | * Set the verb byte, have to substitute in the valid-bit |
| 819 | */ | 910 | * and the number of buffers. |
| 820 | dma_wmb(); | 911 | */ |
| 821 | p->verb = d->verb | RAR_VB(rar) | num_buffers; | 912 | dma_wmb(); |
| 913 | p->verb = d->verb | RAR_VB(rar) | num_buffers; | ||
| 914 | } else { | ||
| 915 | p->verb = d->verb | RAR_VB(rar) | num_buffers; | ||
| 916 | dma_wmb(); | ||
| 917 | qbman_write_register(s, QBMAN_CINH_SWP_RCR_AM_RT + | ||
| 918 | RAR_IDX(rar) * 4, QMAN_RT_MODE); | ||
| 919 | } | ||
| 822 | 920 | ||
| 823 | return 0; | 921 | return 0; |
| 824 | } | 922 | } |
| @@ -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 (C) 2014-2016 Freescale Semiconductor, Inc. | 3 | * Copyright (C) 2014-2016 Freescale Semiconductor, Inc. |
| 4 | * Copyright 2016 NXP | 4 | * Copyright 2016-2019 NXP |
| 5 | * | 5 | * |
| 6 | */ | 6 | */ |
| 7 | #ifndef __FSL_QBMAN_PORTAL_H | 7 | #ifndef __FSL_QBMAN_PORTAL_H |
| @@ -110,6 +110,11 @@ struct qbman_swp { · 102 unmodified lines | |||
| 110 | u32 valid_bit; /* 0x00 or 0x80 */ | 110 | u32 valid_bit; /* 0x00 or 0x80 */ |
| 111 | } mc; | 111 | } mc; |
| 112 | 112 | ||
| 113 | /* Management response */ | ||
| 114 | struct { | ||
| 115 | u32 valid_bit; /* 0x00 or 0x80 */ | ||
| 116 | } mr; | ||
| 117 | |||
| 113 | /* Push dequeues */ | 118 | /* Push dequeues */ |
| 114 | u32 sdq; | 119 | u32 sdq; |
| 115 | 120 | ||
| @@ -428,7 +433,7 @@ static inline int qbman_swp_CDAN_set_context_enable(struct qbman_swp *s, · 312 unmodified lines | |||
| 428 | static inline void *qbman_swp_mc_complete(struct qbman_swp *swp, void *cmd, | 433 | static inline void *qbman_swp_mc_complete(struct qbman_swp *swp, void *cmd, |
| 429 | u8 cmd_verb) | 434 | u8 cmd_verb) |
| 430 | { | 435 | { |
| 431 | int loopvar = 1000; | 436 | int loopvar = 2000; |
| 432 | 437 | ||
| 433 | qbman_swp_mc_submit(swp, cmd, cmd_verb); | 438 | qbman_swp_mc_submit(swp, cmd, cmd_verb); |
| 434 | 439 | ||
| @@ -97,6 +97,11 @@ static const struct fsl_soc_die_attr fsl_soc_die[] = { · 96 unmodified lines | |||
| 97 | .svr = 0x87000000, | 97 | .svr = 0x87000000, |
| 98 | .mask = 0xfff70000, | 98 | .mask = 0xfff70000, |
| 99 | }, | 99 | }, |
| 100 | /* Die: LX2160A, SoC: LX2160A/LX2120A/LX2080A */ | ||
| 101 | { .die = "LX2160A", | ||
| 102 | .svr = 0x87360000, | ||
| 103 | .mask = 0xff3f0000, | ||
| 104 | }, | ||
| 100 | { }, | 105 | { }, |
| 101 | }; | 106 | }; |
| 102 | 107 | ||
| @@ -218,6 +223,7 @@ static const struct of_device_id fsl_guts_of_match[] = { · 115 unmodified lines | |||
| 218 | { .compatible = "fsl,ls1088a-dcfg", }, | 223 | { .compatible = "fsl,ls1088a-dcfg", }, |
| 219 | { .compatible = "fsl,ls1012a-dcfg", }, | 224 | { .compatible = "fsl,ls1012a-dcfg", }, |
| 220 | { .compatible = "fsl,ls1046a-dcfg", }, | 225 | { .compatible = "fsl,ls1046a-dcfg", }, |
| 226 | { .compatible = "fsl,lx2160a-dcfg", }, | ||
| 221 | {} | 227 | {} |
| 222 | }; | 228 | }; |
| 223 | MODULE_DEVICE_TABLE(of, fsl_guts_of_match); | 229 | MODULE_DEVICE_TABLE(of, fsl_guts_of_match); |
| @@ -32,6 +32,7 @@ · 31 unmodified lines | |||
| 32 | 32 | ||
| 33 | static struct bman_portal *affine_bportals[NR_CPUS]; | 33 | static struct bman_portal *affine_bportals[NR_CPUS]; |
| 34 | static struct cpumask portal_cpus; | 34 | static struct cpumask portal_cpus; |
| 35 | static int __bman_portals_probed; | ||
| 35 | /* protect bman global registers and global data shared among portals */ | 36 | /* protect bman global registers and global data shared among portals */ |
| 36 | static DEFINE_SPINLOCK(bman_lock); | 37 | static DEFINE_SPINLOCK(bman_lock); |
| 37 | 38 | ||
| @@ -87,6 +88,12 @@ static int bman_online_cpu(unsigned int cpu) · 49 unmodified lines | |||
| 87 | return 0; | 88 | return 0; |
| 88 | } | 89 | } |
| 89 | 90 | ||
| 91 | int bman_portals_probed(void) | ||
| 92 | { | ||
| 93 | return __bman_portals_probed; | ||
| 94 | } | ||
| 95 | EXPORT_SYMBOL_GPL(bman_portals_probed); | ||
| 96 | |||
| 90 | static int bman_portal_probe(struct platform_device *pdev) | 97 | static int bman_portal_probe(struct platform_device *pdev) |
| 91 | { | 98 | { |
| 92 | struct device *dev = &pdev->dev; | 99 | struct device *dev = &pdev->dev; |
| @@ -104,8 +111,10 @@ static int bman_portal_probe(struct platform_device *pdev) · 11 unmodified lines | |||
| 104 | } | 111 | } |
| 105 | 112 | ||
| 106 | pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL); | 113 | pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL); |
| 107 | if (!pcfg) | 114 | if (!pcfg) { |
| 115 | __bman_portals_probed = -1; | ||
| 108 | return -ENOMEM; | 116 | return -ENOMEM; |
| 117 | } | ||
| 109 | 118 | ||
| 110 | pcfg->dev = dev; | 119 | pcfg->dev = dev; |
| 111 | 120 | ||
| @@ -113,14 +122,14 @@ static int bman_portal_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 113 | DPAA_PORTAL_CE); | 122 | DPAA_PORTAL_CE); |
| 114 | if (!addr_phys[0]) { | 123 | if (!addr_phys[0]) { |
| 115 | dev_err(dev, "Can't get %pOF property 'reg::CE'\n", node); | 124 | dev_err(dev, "Can't get %pOF property 'reg::CE'\n", node); |
| 116 | return -ENXIO; | 125 | goto err_ioremap1; |
| 117 | } | 126 | } |
| 118 | 127 | ||
| 119 | addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM, | 128 | addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM, |
| 120 | DPAA_PORTAL_CI); | 129 | DPAA_PORTAL_CI); |
| 121 | if (!addr_phys[1]) { | 130 | if (!addr_phys[1]) { |
| 122 | dev_err(dev, "Can't get %pOF property 'reg::CI'\n", node); | 131 | dev_err(dev, "Can't get %pOF property 'reg::CI'\n", node); |
| 123 | return -ENXIO; | 132 | goto err_ioremap1; |
| 124 | } | 133 | } |
| 125 | 134 | ||
| 126 | pcfg->cpu = -1; | 135 | pcfg->cpu = -1; |
| @@ -128,7 +137,7 @@ static int bman_portal_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 128 | irq = platform_get_irq(pdev, 0); | 137 | irq = platform_get_irq(pdev, 0); |
| 129 | if (irq <= 0) { | 138 | if (irq <= 0) { |
| 130 | dev_err(dev, "Can't get %pOF IRQ'\n", node); | 139 | dev_err(dev, "Can't get %pOF IRQ'\n", node); |
| 131 | return -ENXIO; | 140 | goto err_ioremap1; |
| 132 | } | 141 | } |
| 133 | pcfg->irq = irq; | 142 | pcfg->irq = irq; |
| 134 | 143 | ||
| @@ -150,6 +159,7 @@ static int bman_portal_probe(struct platform_device *pdev) · 15 unmodified lines | |||
| 150 | spin_lock(&bman_lock); | 159 | spin_lock(&bman_lock); |
| 151 | cpu = cpumask_next_zero(-1, &portal_cpus); | 160 | cpu = cpumask_next_zero(-1, &portal_cpus); |
| 152 | if (cpu >= nr_cpu_ids) { | 161 | if (cpu >= nr_cpu_ids) { |
| 162 | __bman_portals_probed = 1; | ||
| 153 | /* unassigned portal, skip init */ | 163 | /* unassigned portal, skip init */ |
| 154 | spin_unlock(&bman_lock); | 164 | spin_unlock(&bman_lock); |
| 155 | return 0; | 165 | return 0; |
| @@ -175,6 +185,8 @@ err_portal_init: · 19 unmodified lines | |||
| 175 | err_ioremap2: | 185 | err_ioremap2: |
| 176 | memunmap(pcfg->addr_virt_ce); | 186 | memunmap(pcfg->addr_virt_ce); |
| 177 | err_ioremap1: | 187 | err_ioremap1: |
| 188 | __bman_portals_probed = -1; | ||
| 189 | |||
| 178 | return -ENXIO; | 190 | return -ENXIO; |
| 179 | } | 191 | } |
| 180 | 192 | ||
| @@ -596,7 +596,7 @@ static int qman_init_ccsr(struct device *dev) · 595 unmodified lines | |||
| 596 | } | 596 | } |
| 597 | 597 | ||
| 598 | #define LIO_CFG_LIODN_MASK 0x0fff0000 | 598 | #define LIO_CFG_LIODN_MASK 0x0fff0000 |
| 599 | void qman_liodn_fixup(u16 channel) | 599 | void __qman_liodn_fixup(u16 channel) |
| 600 | { | 600 | { |
| 601 | static int done; | 601 | static int done; |
| 602 | static u32 liodn_offset; | 602 | static u32 liodn_offset; |
| @@ -38,6 +38,7 @@ EXPORT_SYMBOL(qman_dma_portal); · 37 unmodified lines | |||
| 38 | #define CONFIG_FSL_DPA_PIRQ_FAST 1 | 38 | #define CONFIG_FSL_DPA_PIRQ_FAST 1 |
| 39 | 39 | ||
| 40 | static struct cpumask portal_cpus; | 40 | static struct cpumask portal_cpus; |
| 41 | static int __qman_portals_probed; | ||
| 41 | /* protect qman global registers and global data shared among portals */ | 42 | /* protect qman global registers and global data shared among portals */ |
| 42 | static DEFINE_SPINLOCK(qman_lock); | 43 | static DEFINE_SPINLOCK(qman_lock); |
| 43 | 44 | ||
| @@ -220,6 +221,12 @@ static int qman_online_cpu(unsigned int cpu) · 176 unmodified lines | |||
| 220 | return 0; | 221 | return 0; |
| 221 | } | 222 | } |
| 222 | 223 | ||
| 224 | int qman_portals_probed(void) | ||
| 225 | { | ||
| 226 | return __qman_portals_probed; | ||
| 227 | } | ||
| 228 | EXPORT_SYMBOL_GPL(qman_portals_probed); | ||
| 229 | |||
| 223 | static int qman_portal_probe(struct platform_device *pdev) | 230 | static int qman_portal_probe(struct platform_device *pdev) |
| 224 | { | 231 | { |
| 225 | struct device *dev = &pdev->dev; | 232 | struct device *dev = &pdev->dev; |
| @@ -238,8 +245,10 @@ static int qman_portal_probe(struct platform_device *pdev) · 12 unmodified lines | |||
| 238 | } | 245 | } |
| 239 | 246 | ||
| 240 | pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL); | 247 | pcfg = devm_kmalloc(dev, sizeof(*pcfg), GFP_KERNEL); |
| 241 | if (!pcfg) | 248 | if (!pcfg) { |
| 249 | __qman_portals_probed = -1; | ||
| 242 | return -ENOMEM; | 250 | return -ENOMEM; |
| 251 | } | ||
| 243 | 252 | ||
| 244 | pcfg->dev = dev; | 253 | pcfg->dev = dev; |
| 245 | 254 | ||
| @@ -247,19 +256,20 @@ static int qman_portal_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 247 | DPAA_PORTAL_CE); | 256 | DPAA_PORTAL_CE); |
| 248 | if (!addr_phys[0]) { | 257 | if (!addr_phys[0]) { |
| 249 | dev_err(dev, "Can't get %pOF property 'reg::CE'\n", node); | 258 | dev_err(dev, "Can't get %pOF property 'reg::CE'\n", node); |
| 250 | return -ENXIO; | 259 | goto err_ioremap1; |
| 251 | } | 260 | } |
| 252 | 261 | ||
| 253 | addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM, | 262 | addr_phys[1] = platform_get_resource(pdev, IORESOURCE_MEM, |
| 254 | DPAA_PORTAL_CI); | 263 | DPAA_PORTAL_CI); |
| 255 | if (!addr_phys[1]) { | 264 | if (!addr_phys[1]) { |
| 256 | dev_err(dev, "Can't get %pOF property 'reg::CI'\n", node); | 265 | dev_err(dev, "Can't get %pOF property 'reg::CI'\n", node); |
| 257 | return -ENXIO; | 266 | goto err_ioremap1; |
| 258 | } | 267 | } |
| 259 | 268 | ||
| 260 | err = of_property_read_u32(node, "cell-index", &val); | 269 | err = of_property_read_u32(node, "cell-index", &val); |
| 261 | if (err) { | 270 | if (err) { |
| 262 | dev_err(dev, "Can't get %pOF property 'cell-index'\n", node); | 271 | dev_err(dev, "Can't get %pOF property 'cell-index'\n", node); |
| 272 | __qman_portals_probed = -1; | ||
| 263 | return err; | 273 | return err; |
| 264 | } | 274 | } |
| 265 | pcfg->channel = val; | 275 | pcfg->channel = val; |
| @@ -267,7 +277,7 @@ static int qman_portal_probe(struct platform_device *pdev) · 1 unmodified line | |||
| 267 | irq = platform_get_irq(pdev, 0); | 277 | irq = platform_get_irq(pdev, 0); |
| 268 | if (irq <= 0) { | 278 | if (irq <= 0) { |
| 269 | dev_err(dev, "Can't get %pOF IRQ\n", node); | 279 | dev_err(dev, "Can't get %pOF IRQ\n", node); |
| 270 | return -ENXIO; | 280 | goto err_ioremap1; |
| 271 | } | 281 | } |
| 272 | pcfg->irq = irq; | 282 | pcfg->irq = irq; |
| 273 | 283 | ||
| @@ -291,6 +301,7 @@ static int qman_portal_probe(struct platform_device *pdev) · 17 unmodified lines | |||
| 291 | spin_lock(&qman_lock); | 301 | spin_lock(&qman_lock); |
| 292 | cpu = cpumask_next_zero(-1, &portal_cpus); | 302 | cpu = cpumask_next_zero(-1, &portal_cpus); |
| 293 | if (cpu >= nr_cpu_ids) { | 303 | if (cpu >= nr_cpu_ids) { |
| 304 | __qman_portals_probed = 1; | ||
| 294 | /* unassigned portal, skip init */ | 305 | /* unassigned portal, skip init */ |
| 295 | spin_unlock(&qman_lock); | 306 | spin_unlock(&qman_lock); |
| 296 | return 0; | 307 | return 0; |
| @@ -321,6 +332,8 @@ err_portal_init: · 24 unmodified lines | |||
| 321 | err_ioremap2: | 332 | err_ioremap2: |
| 322 | memunmap(pcfg->addr_virt_ce); | 333 | memunmap(pcfg->addr_virt_ce); |
| 323 | err_ioremap1: | 334 | err_ioremap1: |
| 335 | __qman_portals_probed = -1; | ||
| 336 | |||
| 324 | return -ENXIO; | 337 | return -ENXIO; |
| 325 | } | 338 | } |
| 326 | 339 | ||
| @@ -193,7 +193,14 @@ extern struct gen_pool *qm_cgralloc; /* CGR ID allocator */ · 192 unmodified lines | |||
| 193 | u32 qm_get_pools_sdqcr(void); | 193 | u32 qm_get_pools_sdqcr(void); |
| 194 | 194 | ||
| 195 | int qman_wq_alloc(void); | 195 | int qman_wq_alloc(void); |
| 196 | void qman_liodn_fixup(u16 channel); | 196 | #ifdef CONFIG_FSL_PAMU |
| 197 | #define qman_liodn_fixup __qman_liodn_fixup | ||
| 198 | #else | ||
| 199 | static inline void qman_liodn_fixup(u16 channel) | ||
| 200 | { | ||
| 201 | } | ||
| 202 | #endif | ||
| 203 | void __qman_liodn_fixup(u16 channel); | ||
| 197 | void qman_set_sdest(u16 channel, unsigned int cpu_idx); | 204 | void qman_set_sdest(u16 channel, unsigned int cpu_idx); |
| 198 | 205 | ||
| 199 | struct qman_portal *qman_create_affine_portal( | 206 | struct qman_portal *qman_create_affine_portal( |
| @@ -8,4 +8,13 @@ config IMX_GPCV2_PM_DOMAINS · 7 unmodified lines | |||
| 8 | select PM_GENERIC_DOMAINS | 8 | select PM_GENERIC_DOMAINS |
| 9 | default y if SOC_IMX7D | 9 | default y if SOC_IMX7D |
| 10 | 10 | ||
| 11 | config IMX_SCU_SOC | ||
| 12 | bool "i.MX System Controller Unit SoC info support" | ||
| 13 | depends on IMX_SCU | ||
| 14 | select SOC_BUS | ||
| 15 | help | ||
| 16 | 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 info | ||
| 18 | like SoC family, ID and revision etc. | ||
| 19 | |||
| 11 | endmenu | 20 | endmenu |
| @@ -2,3 +2,4 @@ · 1 unmodified line | |||
| 2 | obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o | 2 | obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o |
| 3 | obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o | 3 | obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o |
| 4 | obj-$(CONFIG_ARCH_MXC) += soc-imx8.o | 4 | obj-$(CONFIG_ARCH_MXC) += soc-imx8.o |
| 5 | obj-$(CONFIG_IMX_SCU_SOC) += soc-imx-scu.o | ||
| @@ -0,0 +1,144 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Copyright 2019 NXP. | ||
| 4 | */ | ||
| 5 | |||
| 6 | #include <dt-bindings/firmware/imx/rsrc.h> | ||
| 7 | #include <linux/firmware/imx/sci.h> | ||
| 8 | #include <linux/slab.h> | ||
| 9 | #include <linux/sys_soc.h> | ||
| 10 | #include <linux/platform_device.h> | ||
| 11 | #include <linux/of.h> | ||
| 12 | |||
| 13 | #define IMX_SCU_SOC_DRIVER_NAME "imx-scu-soc" | ||
| 14 | |||
| 15 | static struct imx_sc_ipc *soc_ipc_handle; | ||
| 16 | |||
| 17 | struct imx_sc_msg_misc_get_soc_id { | ||
| 18 | struct imx_sc_rpc_msg hdr; | ||
| 19 | union { | ||
| 20 | struct { | ||
| 21 | u32 control; | ||
| 22 | u16 resource; | ||
| 23 | } __packed req; | ||
| 24 | struct { | ||
| 25 | u32 id; | ||
| 26 | } resp; | ||
| 27 | } data; | ||
| 28 | } __packed; | ||
| 29 | |||
| 30 | static int imx_scu_soc_id(void) | ||
| 31 | { | ||
| 32 | struct imx_sc_msg_misc_get_soc_id msg; | ||
| 33 | struct imx_sc_rpc_msg *hdr = &msg.hdr; | ||
| 34 | int ret; | ||
| 35 | |||
| 36 | hdr->ver = IMX_SC_RPC_VERSION; | ||
| 37 | hdr->svc = IMX_SC_RPC_SVC_MISC; | ||
| 38 | hdr->func = IMX_SC_MISC_FUNC_GET_CONTROL; | ||
| 39 | hdr->size = 3; | ||
| 40 | |||
| 41 | msg.data.req.control = IMX_SC_C_ID; | ||
| 42 | msg.data.req.resource = IMX_SC_R_SYSTEM; | ||
| 43 | |||
| 44 | ret = imx_scu_call_rpc(soc_ipc_handle, &msg, true); | ||
| 45 | if (ret) { | ||
| 46 | pr_err("%s: get soc info failed, ret %d\n", __func__, ret); | ||
| 47 | return ret; | ||
| 48 | } | ||
| 49 | |||
| 50 | return msg.data.resp.id; | ||
| 51 | } | ||
| 52 | |||
| 53 | static int imx_scu_soc_probe(struct platform_device *pdev) | ||
| 54 | { | ||
| 55 | struct soc_device_attribute *soc_dev_attr; | ||
| 56 | struct soc_device *soc_dev; | ||
| 57 | int id, ret; | ||
| 58 | u32 val; | ||
| 59 | |||
| 60 | ret = imx_scu_get_handle(&soc_ipc_handle); | ||
| 61 | if (ret) | ||
| 62 | return ret; | ||
| 63 | |||
| 64 | soc_dev_attr = devm_kzalloc(&pdev->dev, sizeof(*soc_dev_attr), | ||
| 65 | GFP_KERNEL); | ||
| 66 | if (!soc_dev_attr) | ||
| 67 | return -ENOMEM; | ||
| 68 | |||
| 69 | soc_dev_attr->family = "Freescale i.MX"; | ||
| 70 | |||
| 71 | ret = of_property_read_string(of_root, | ||
| 72 | "model", | ||
| 73 | &soc_dev_attr->machine); | ||
| 74 | if (ret) | ||
| 75 | return ret; | ||
| 76 | |||
| 77 | id = imx_scu_soc_id(); | ||
| 78 | if (id < 0) | ||
| 79 | return -EINVAL; | ||
| 80 | |||
| 81 | /* format soc_id value passed from SCU firmware */ | ||
| 82 | val = id & 0x1f; | ||
| 83 | soc_dev_attr->soc_id = kasprintf(GFP_KERNEL, "0x%x", val); | ||
| 84 | if (!soc_dev_attr->soc_id) | ||
| 85 | return -ENOMEM; | ||
| 86 | |||
| 87 | /* format revision value passed from SCU firmware */ | ||
| 88 | val = (id >> 5) & 0xf; | ||
| 89 | val = (((val >> 2) + 1) << 4) | (val & 0x3); | ||
| 90 | soc_dev_attr->revision = kasprintf(GFP_KERNEL, | ||
| 91 | "%d.%d", | ||
| 92 | (val >> 4) & 0xf, | ||
| 93 | val & 0xf); | ||
| 94 | if (!soc_dev_attr->revision) { | ||
| 95 | ret = -ENOMEM; | ||
| 96 | goto free_soc_id; | ||
| 97 | } | ||
| 98 | |||
| 99 | soc_dev = soc_device_register(soc_dev_attr); | ||
| 100 | if (IS_ERR(soc_dev)) { | ||
| 101 | ret = PTR_ERR(soc_dev); | ||
| 102 | goto free_revision; | ||
| 103 | } | ||
| 104 | |||
| 105 | return 0; | ||
| 106 | |||
| 107 | free_revision: | ||
| 108 | kfree(soc_dev_attr->revision); | ||
| 109 | free_soc_id: | ||
| 110 | kfree(soc_dev_attr->soc_id); | ||
| 111 | return ret; | ||
| 112 | } | ||
| 113 | |||
| 114 | static struct platform_driver imx_scu_soc_driver = { | ||
| 115 | .driver = { | ||
| 116 | .name = IMX_SCU_SOC_DRIVER_NAME, | ||
| 117 | }, | ||
| 118 | .probe = imx_scu_soc_probe, | ||
| 119 | }; | ||
| 120 | |||
| 121 | static int __init imx_scu_soc_init(void) | ||
| 122 | { | ||
| 123 | struct platform_device *pdev; | ||
| 124 | struct device_node *np; | ||
| 125 | int ret; | ||
| 126 | |||
| 127 | np = of_find_compatible_node(NULL, NULL, "fsl,imx-scu"); | ||
| 128 | if (!np) | ||
| 129 | return -ENODEV; | ||
| 130 | |||
| 131 | of_node_put(np); | ||
| 132 | |||
| 133 | ret = platform_driver_register(&imx_scu_soc_driver); | ||
| 134 | if (ret) | ||
| 135 | return ret; | ||
| 136 | |||
| 137 | pdev = platform_device_register_simple(IMX_SCU_SOC_DRIVER_NAME, | ||
| 138 | -1, NULL, 0); | ||
| 139 | if (IS_ERR(pdev)) | ||
| 140 | platform_driver_unregister(&imx_scu_soc_driver); | ||
| 141 | |||
| 142 | return PTR_ERR_OR_ZERO(pdev); | ||
| 143 | } | ||
| 144 | device_initcall(imx_scu_soc_init); | ||
| @@ -16,6 +16,9 @@ · 15 unmodified lines | |||
| 16 | #define IMX8MQ_SW_INFO_B1 0x40 | 16 | #define IMX8MQ_SW_INFO_B1 0x40 |
| 17 | #define IMX8MQ_SW_MAGIC_B1 0xff0055aa | 17 | #define IMX8MQ_SW_MAGIC_B1 0xff0055aa |
| 18 | 18 | ||
| 19 | /* Same as ANADIG_DIGPROG_IMX7D */ | ||
| 20 | #define ANADIG_DIGPROG_IMX8MM 0x800 | ||
| 21 | |||
| 19 | struct imx8_soc_data { | 22 | struct imx8_soc_data { |
| 20 | char *name; | 23 | char *name; |
| 21 | u32 (*soc_revision)(void); | 24 | u32 (*soc_revision)(void); |
| @@ -46,13 +49,45 @@ out: · 24 unmodified lines | |||
| 46 | return rev; | 49 | return rev; |
| 47 | } | 50 | } |
| 48 | 51 | ||
| 52 | static u32 __init imx8mm_soc_revision(void) | ||
| 53 | { | ||
| 54 | struct device_node *np; | ||
| 55 | void __iomem *anatop_base; | ||
| 56 | u32 rev; | ||
| 57 | |||
| 58 | np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop"); | ||
| 59 | if (!np) | ||
| 60 | return 0; | ||
| 61 | |||
| 62 | anatop_base = of_iomap(np, 0); | ||
| 63 | WARN_ON(!anatop_base); | ||
| 64 | |||
| 65 | rev = readl_relaxed(anatop_base + ANADIG_DIGPROG_IMX8MM); | ||
| 66 | |||
| 67 | iounmap(anatop_base); | ||
| 68 | of_node_put(np); | ||
| 69 | return rev; | ||
| 70 | } | ||
| 71 | |||
| 49 | static const struct imx8_soc_data imx8mq_soc_data = { | 72 | static const struct imx8_soc_data imx8mq_soc_data = { |
| 50 | .name = "i.MX8MQ", | 73 | .name = "i.MX8MQ", |
| 51 | .soc_revision = imx8mq_soc_revision, | 74 | .soc_revision = imx8mq_soc_revision, |
| 52 | }; | 75 | }; |
| 53 | 76 | ||
| 77 | static const struct imx8_soc_data imx8mm_soc_data = { | ||
| 78 | .name = "i.MX8MM", | ||
| 79 | .soc_revision = imx8mm_soc_revision, | ||
| 80 | }; | ||
| 81 | |||
| 82 | static const struct imx8_soc_data imx8mn_soc_data = { | ||
| 83 | .name = "i.MX8MN", | ||
| 84 | .soc_revision = imx8mm_soc_revision, | ||
| 85 | }; | ||
| 86 | |||
| 54 | static const struct of_device_id imx8_soc_match[] = { | 87 | static const struct of_device_id imx8_soc_match[] = { |
| 55 | { .compatible = "fsl,imx8mq", .data = &imx8mq_soc_data, }, | 88 | { .compatible = "fsl,imx8mq", .data = &imx8mq_soc_data, }, |
| 89 | { .compatible = "fsl,imx8mm", .data = &imx8mm_soc_data, }, | ||
| 90 | { .compatible = "fsl,imx8mn", .data = &imx8mn_soc_data, }, | ||
| 56 | { } | 91 | { } |
| 57 | }; | 92 | }; |
| 58 | 93 | ||
| @@ -65,7 +100,6 @@ static int __init imx8_soc_init(void) · 6 unmodified lines | |||
| 65 | { | 100 | { |
| 66 | struct soc_device_attribute *soc_dev_attr; | 101 | struct soc_device_attribute *soc_dev_attr; |
| 67 | struct soc_device *soc_dev; | 102 | struct soc_device *soc_dev; |
| 68 | struct device_node *root; | ||
| 69 | const struct of_device_id *id; | 103 | const struct of_device_id *id; |
| 70 | u32 soc_rev = 0; | 104 | u32 soc_rev = 0; |
| 71 | const struct imx8_soc_data *data; | 105 | const struct imx8_soc_data *data; |
| @@ -73,20 +107,19 @@ static int __init imx8_soc_init(void) · 1 unmodified line | |||
| 73 | 107 | ||
| 74 | soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); | 108 | soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL); |
| 75 | if (!soc_dev_attr) | 109 | if (!soc_dev_attr) |
| 76 | return -ENODEV; | 110 | return -ENOMEM; |
| 77 | 111 | ||
| 78 | soc_dev_attr->family = "Freescale i.MX"; | 112 | soc_dev_attr->family = "Freescale i.MX"; |
| 79 | 113 | ||
| 80 | root = of_find_node_by_path("/"); | 114 | ret = of_property_read_string(of_root, "model", &soc_dev_attr->machine); |
| 81 | ret = of_property_read_string(root, "model", &soc_dev_attr->machine); | ||
| 82 | if (ret) | 115 | if (ret) |
| 83 | goto free_soc; | 116 | goto free_soc; |
| 84 | 117 | ||
| 85 | id = of_match_node(imx8_soc_match, root); | 118 | id = of_match_node(imx8_soc_match, of_root); |
| 86 | if (!id) | 119 | if (!id) { |
| 120 | ret = -ENODEV; | ||
| 87 | goto free_soc; | 121 | goto free_soc; |
| 88 | 122 | } | |
| 89 | of_node_put(root); | ||
| 90 | 123 | ||
| 91 | data = id->data; | 124 | data = id->data; |
| 92 | if (data) { | 125 | if (data) { |
| @@ -96,12 +129,16 @@ static int __init imx8_soc_init(void) · 3 unmodified lines | |||
| 96 | } | 129 | } |
| 97 | 130 | ||
| 98 | soc_dev_attr->revision = imx8_revision(soc_rev); | 131 | soc_dev_attr->revision = imx8_revision(soc_rev); |
| 99 | if (!soc_dev_attr->revision) | 132 | if (!soc_dev_attr->revision) { |
| 133 | ret = -ENOMEM; | ||
| 100 | goto free_soc; | 134 | goto free_soc; |
| 135 | } | ||
| 101 | 136 | ||
| 102 | soc_dev = soc_device_register(soc_dev_attr); | 137 | soc_dev = soc_device_register(soc_dev_attr); |
| 103 | if (IS_ERR(soc_dev)) | 138 | if (IS_ERR(soc_dev)) { |
| 139 | ret = PTR_ERR(soc_dev); | ||
| 104 | goto free_rev; | 140 | goto free_rev; |
| 141 | } | ||
| 105 | 142 | ||
| 106 | if (IS_ENABLED(CONFIG_ARM_IMX_CPUFREQ_DT)) | 143 | if (IS_ENABLED(CONFIG_ARM_IMX_CPUFREQ_DT)) |
| 107 | platform_device_register_simple("imx-cpufreq-dt", -1, NULL, 0); | 144 | platform_device_register_simple("imx-cpufreq-dt", -1, NULL, 0); |
| @@ -109,10 +146,10 @@ static int __init imx8_soc_init(void) · 1 unmodified line | |||
| 109 | return 0; | 146 | return 0; |
| 110 | 147 | ||
| 111 | free_rev: | 148 | free_rev: |
| 112 | kfree(soc_dev_attr->revision); | 149 | if (strcmp(soc_dev_attr->revision, "unknown")) |
| 150 | kfree(soc_dev_attr->revision); | ||
| 113 | free_soc: | 151 | free_soc: |
| 114 | kfree(soc_dev_attr); | 152 | kfree(soc_dev_attr); |
| 115 | of_node_put(root); | 153 | return ret; |
| 116 | return -ENODEV; | ||
| 117 | } | 154 | } |
| 118 | device_initcall(imx8_soc_init); | 155 | device_initcall(imx8_soc_init); |
| @@ -4,6 +4,18 @@ · 3 unmodified lines | |||
| 4 | # | 4 | # |
| 5 | menu "Qualcomm SoC drivers" | 5 | menu "Qualcomm SoC drivers" |
| 6 | 6 | ||
| 7 | config QCOM_AOSS_QMP | ||
| 8 | tristate "Qualcomm AOSS Driver" | ||
| 9 | depends on ARCH_QCOM || COMPILE_TEST | ||
| 10 | depends on MAILBOX | ||
| 11 | depends on COMMON_CLK && PM | ||
| 12 | select PM_GENERIC_DOMAINS | ||
| 13 | help | ||
| 14 | This driver provides the means of communicating with and controlling | ||
| 15 | the low-power state for resources related to the remoteproc | ||
| 16 | subsystems as well as controlling the debug clocks exposed by the Always On | ||
| 17 | Subsystem (AOSS) using Qualcomm Messaging Protocol (QMP). | ||
| 18 | |||
| 7 | config QCOM_COMMAND_DB | 19 | config QCOM_COMMAND_DB |
| 8 | bool "Qualcomm Command DB" | 20 | bool "Qualcomm Command DB" |
| 9 | depends on ARCH_QCOM || COMPILE_TEST | 21 | depends on ARCH_QCOM || COMPILE_TEST |
| @@ -1,5 +1,6 @@ | |||
| 1 | # SPDX-License-Identifier: GPL-2.0 | 1 | # SPDX-License-Identifier: GPL-2.0 |
| 2 | CFLAGS_rpmh-rsc.o := -I$(src) | 2 | CFLAGS_rpmh-rsc.o := -I$(src) |
| 3 | obj-$(CONFIG_QCOM_AOSS_QMP) += qcom_aoss.o | ||
| 3 | obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o | 4 | obj-$(CONFIG_QCOM_GENI_SE) += qcom-geni-se.o |
| 4 | obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o | 5 | obj-$(CONFIG_QCOM_COMMAND_DB) += cmd-db.o |
| 5 | obj-$(CONFIG_QCOM_GLINK_SSR) += glink_ssr.o | 6 | obj-$(CONFIG_QCOM_GLINK_SSR) += glink_ssr.o |
| @@ -8,6 +8,7 @@ · 7 unmodified lines | |||
| 8 | #include <linux/spinlock.h> | 8 | #include <linux/spinlock.h> |
| 9 | #include <linux/idr.h> | 9 | #include <linux/idr.h> |
| 10 | #include <linux/slab.h> | 10 | #include <linux/slab.h> |
| 11 | #include <linux/workqueue.h> | ||
| 11 | #include <linux/of_device.h> | 12 | #include <linux/of_device.h> |
| 12 | #include <linux/soc/qcom/apr.h> | 13 | #include <linux/soc/qcom/apr.h> |
| 13 | #include <linux/rpmsg.h> | 14 | #include <linux/rpmsg.h> |
| @@ -17,8 +18,18 @@ struct apr { · 3 unmodified lines | |||
| 17 | struct rpmsg_endpoint *ch; | 18 | struct rpmsg_endpoint *ch; |
| 18 | struct device *dev; | 19 | struct device *dev; |
| 19 | spinlock_t svcs_lock; | 20 | spinlock_t svcs_lock; |
| 21 | spinlock_t rx_lock; | ||
| 20 | struct idr svcs_idr; | 22 | struct idr svcs_idr; |
| 21 | int dest_domain_id; | 23 | int dest_domain_id; |
| 24 | struct workqueue_struct *rxwq; | ||
| 25 | struct work_struct rx_work; | ||
| 26 | struct list_head rx_list; | ||
| 27 | }; | ||
| 28 | |||
| 29 | struct apr_rx_buf { | ||
| 30 | struct list_head node; | ||
| 31 | int len; | ||
| 32 | uint8_t buf[]; | ||
| 22 | }; | 33 | }; |
| 23 | 34 | ||
| 24 | /** | 35 | /** |
| @@ -62,11 +73,7 @@ static int apr_callback(struct rpmsg_device *rpdev, void *buf, · 37 unmodified lines | |||
| 62 | int len, void *priv, u32 addr) | 73 | int len, void *priv, u32 addr) |
| 63 | { | 74 | { |
| 64 | struct apr *apr = dev_get_drvdata(&rpdev->dev); | 75 | struct apr *apr = dev_get_drvdata(&rpdev->dev); |
| 65 | uint16_t hdr_size, msg_type, ver, svc_id; | 76 | struct apr_rx_buf *abuf; |
| 66 | struct apr_device *svc = NULL; | ||
| 67 | struct apr_driver *adrv = NULL; | ||
| 68 | struct apr_resp_pkt resp; | ||
| 69 | struct apr_hdr *hdr; | ||
| 70 | unsigned long flags; | 77 | unsigned long flags; |
| 71 | 78 | ||
| 72 | if (len <= APR_HDR_SIZE) { | 79 | if (len <= APR_HDR_SIZE) { |
| @@ -75,6 +82,34 @@ static int apr_callback(struct rpmsg_device *rpdev, void *buf, · 2 unmodified lines | |||
| 75 | return -EINVAL; | 82 | return -EINVAL; |
| 76 | } | 83 | } |
| 77 | 84 | ||
| 85 | abuf = kzalloc(sizeof(*abuf) + len, GFP_ATOMIC); | ||
| 86 | if (!abuf) | ||
| 87 | return -ENOMEM; | ||
| 88 | |||
| 89 | abuf->len = len; | ||
| 90 | memcpy(abuf->buf, buf, len); | ||
| 91 | |||
| 92 | spin_lock_irqsave(&apr->rx_lock, flags); | ||
| 93 | list_add_tail(&abuf->node, &apr->rx_list); | ||
| 94 | spin_unlock_irqrestore(&apr->rx_lock, flags); | ||
| 95 | |||
| 96 | queue_work(apr->rxwq, &apr->rx_work); | ||
| 97 | |||
| 98 | return 0; | ||
| 99 | } | ||
| 100 | |||
| 101 | |||
| 102 | static int apr_do_rx_callback(struct apr *apr, struct apr_rx_buf *abuf) | ||
| 103 | { | ||
| 104 | uint16_t hdr_size, msg_type, ver, svc_id; | ||
| 105 | struct apr_device *svc = NULL; | ||
| 106 | struct apr_driver *adrv = NULL; | ||
| 107 | struct apr_resp_pkt resp; | ||
| 108 | struct apr_hdr *hdr; | ||
| 109 | unsigned long flags; | ||
| 110 | void *buf = abuf->buf; | ||
| 111 | int len = abuf->len; | ||
| 112 | |||
| 78 | hdr = buf; | 113 | hdr = buf; |
| 79 | ver = APR_HDR_FIELD_VER(hdr->hdr_field); | 114 | ver = APR_HDR_FIELD_VER(hdr->hdr_field); |
| 80 | if (ver > APR_PKT_VER + 1) | 115 | if (ver > APR_PKT_VER + 1) |
| @@ -132,6 +167,23 @@ static int apr_callback(struct rpmsg_device *rpdev, void *buf, · 51 unmodified lines | |||
| 132 | return 0; | 167 | return 0; |
| 133 | } | 168 | } |
| 134 | 169 | ||
| 170 | static void apr_rxwq(struct work_struct *work) | ||
| 171 | { | ||
| 172 | struct apr *apr = container_of(work, struct apr, rx_work); | ||
| 173 | struct apr_rx_buf *abuf, *b; | ||
| 174 | unsigned long flags; | ||
| 175 | |||
| 176 | if (!list_empty(&apr->rx_list)) { | ||
| 177 | list_for_each_entry_safe(abuf, b, &apr->rx_list, node) { | ||
| 178 | apr_do_rx_callback(apr, abuf); | ||
| 179 | spin_lock_irqsave(&apr->rx_lock, flags); | ||
| 180 | list_del(&abuf->node); | ||
| 181 | spin_unlock_irqrestore(&apr->rx_lock, flags); | ||
| 182 | kfree(abuf); | ||
| 183 | } | ||
| 184 | } | ||
| 185 | } | ||
| 186 | |||
| 135 | static int apr_device_match(struct device *dev, struct device_driver *drv) | 187 | static int apr_device_match(struct device *dev, struct device_driver *drv) |
| 136 | { | 188 | { |
| 137 | struct apr_device *adev = to_apr_device(dev); | 189 | struct apr_device *adev = to_apr_device(dev); |
| @@ -276,7 +328,7 @@ static int apr_probe(struct rpmsg_device *rpdev) · 138 unmodified lines | |||
| 276 | if (!apr) | 328 | if (!apr) |
| 277 | return -ENOMEM; | 329 | return -ENOMEM; |
| 278 | 330 | ||
| 279 | ret = of_property_read_u32(dev->of_node, "reg", &apr->dest_domain_id); | 331 | ret = of_property_read_u32(dev->of_node, "qcom,apr-domain", &apr->dest_domain_id); |
| 280 | if (ret) { | 332 | if (ret) { |
| 281 | dev_err(dev, "APR Domain ID not specified in DT\n"); | 333 | dev_err(dev, "APR Domain ID not specified in DT\n"); |
| 282 | return ret; | 334 | return ret; |
| @@ -285,6 +337,14 @@ static int apr_probe(struct rpmsg_device *rpdev) · 2 unmodified lines | |||
| 285 | dev_set_drvdata(dev, apr); | 337 | dev_set_drvdata(dev, apr); |
| 286 | apr->ch = rpdev->ept; | 338 | apr->ch = rpdev->ept; |
| 287 | apr->dev = dev; | 339 | apr->dev = dev; |
| 340 | apr->rxwq = create_singlethread_workqueue("qcom_apr_rx"); | ||
| 341 | if (!apr->rxwq) { | ||
| 342 | dev_err(apr->dev, "Failed to start Rx WQ\n"); | ||
| 343 | return -ENOMEM; | ||
| 344 | } | ||
| 345 | INIT_WORK(&apr->rx_work, apr_rxwq); | ||
| 346 | INIT_LIST_HEAD(&apr->rx_list); | ||
| 347 | spin_lock_init(&apr->rx_lock); | ||
| 288 | spin_lock_init(&apr->svcs_lock); | 348 | spin_lock_init(&apr->svcs_lock); |
| 289 | idr_init(&apr->svcs_idr); | 349 | idr_init(&apr->svcs_idr); |
| 290 | of_register_apr_devices(dev); | 350 | of_register_apr_devices(dev); |
| @@ -303,7 +363,11 @@ static int apr_remove_device(struct device *dev, void *null) · 12 unmodified lines | |||
| 303 | 363 | ||
| 304 | static void apr_remove(struct rpmsg_device *rpdev) | 364 | static void apr_remove(struct rpmsg_device *rpdev) |
| 305 | { | 365 | { |
| 366 | struct apr *apr = dev_get_drvdata(&rpdev->dev); | ||
| 367 | |||
| 306 | device_for_each_child(&rpdev->dev, NULL, apr_remove_device); | 368 | device_for_each_child(&rpdev->dev, NULL, apr_remove_device); |
| 369 | flush_workqueue(apr->rxwq); | ||
| 370 | destroy_workqueue(apr->rxwq); | ||
| 307 | } | 371 | } |
| 308 | 372 | ||
| 309 | /* | 373 | /* |
| @@ -0,0 +1,480 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | /* | ||
| 3 | * Copyright (c) 2019, Linaro Ltd | ||
| 4 | */ | ||
| 5 | #include <dt-bindings/power/qcom-aoss-qmp.h> | ||
| 6 | #include <linux/clk-provider.h> | ||
| 7 | #include <linux/interrupt.h> | ||
| 8 | #include <linux/io.h> | ||
| 9 | #include <linux/mailbox_client.h> | ||
| 10 | #include <linux/module.h> | ||
| 11 | #include <linux/platform_device.h> | ||
| 12 | #include <linux/pm_domain.h> | ||
| 13 | |||
| 14 | #define QMP_DESC_MAGIC 0x0 | ||
| 15 | #define QMP_DESC_VERSION 0x4 | ||
| 16 | #define QMP_DESC_FEATURES 0x8 | ||
| 17 | |||
| 18 | /* AOP-side offsets */ | ||
| 19 | #define QMP_DESC_UCORE_LINK_STATE 0xc | ||
| 20 | #define QMP_DESC_UCORE_LINK_STATE_ACK 0x10 | ||
| 21 | #define QMP_DESC_UCORE_CH_STATE 0x14 | ||
| 22 | #define QMP_DESC_UCORE_CH_STATE_ACK 0x18 | ||
| 23 | #define QMP_DESC_UCORE_MBOX_SIZE 0x1c | ||
| 24 | #define QMP_DESC_UCORE_MBOX_OFFSET 0x20 | ||
| 25 | |||
| 26 | /* Linux-side offsets */ | ||
| 27 | #define QMP_DESC_MCORE_LINK_STATE 0x24 | ||
| 28 | #define QMP_DESC_MCORE_LINK_STATE_ACK 0x28 | ||
| 29 | #define QMP_DESC_MCORE_CH_STATE 0x2c | ||
| 30 | #define QMP_DESC_MCORE_CH_STATE_ACK 0x30 | ||
| 31 | #define QMP_DESC_MCORE_MBOX_SIZE 0x34 | ||
| 32 | #define QMP_DESC_MCORE_MBOX_OFFSET 0x38 | ||
| 33 | |||
| 34 | #define QMP_STATE_UP GENMASK(15, 0) | ||
| 35 | #define QMP_STATE_DOWN GENMASK(31, 16) | ||
| 36 | |||
| 37 | #define QMP_MAGIC 0x4d41494c /* mail */ | ||
| 38 | #define QMP_VERSION 1 | ||
| 39 | |||
| 40 | /* 64 bytes is enough to store the requests and provides padding to 4 bytes */ | ||
| 41 | #define QMP_MSG_LEN 64 | ||
| 42 | |||
| 43 | /** | ||
| 44 | * struct qmp - driver state for QMP implementation | ||
| 45 | * @msgram: iomem referencing the message RAM used for communication | ||
| 46 | * @dev: reference to QMP device | ||
| 47 | * @mbox_client: mailbox client used to ring the doorbell on transmit | ||
| 48 | * @mbox_chan: mailbox channel used to ring the doorbell on transmit | ||
| 49 | * @offset: offset within @msgram where messages should be written | ||
| 50 | * @size: maximum size of the messages to be transmitted | ||
| 51 | * @event: wait_queue for synchronization with the IRQ | ||
| 52 | * @tx_lock: provides synchronization between multiple callers of qmp_send() | ||
| 53 | * @qdss_clk: QDSS clock hw struct | ||
| 54 | * @pd_data: genpd data | ||
| 55 | */ | ||
| 56 | struct qmp { | ||
| 57 | void __iomem *msgram; | ||
| 58 | struct device *dev; | ||
| 59 | |||
| 60 | struct mbox_client mbox_client; | ||
| 61 | struct mbox_chan *mbox_chan; | ||
| 62 | |||
| 63 | size_t offset; | ||
| 64 | size_t size; | ||
| 65 | |||
| 66 | wait_queue_head_t event; | ||
| 67 | |||
| 68 | struct mutex tx_lock; | ||
| 69 | |||
| 70 | struct clk_hw qdss_clk; | ||
| 71 | struct genpd_onecell_data pd_data; | ||
| 72 | }; | ||
| 73 | |||
| 74 | struct qmp_pd { | ||
| 75 | struct qmp *qmp; | ||
| 76 | struct generic_pm_domain pd; | ||
| 77 | }; | ||
| 78 | |||
| 79 | #define to_qmp_pd_resource(res) container_of(res, struct qmp_pd, pd) | ||
| 80 | |||
| 81 | static void qmp_kick(struct qmp *qmp) | ||
| 82 | { | ||
| 83 | mbox_send_message(qmp->mbox_chan, NULL); | ||
| 84 | mbox_client_txdone(qmp->mbox_chan, 0); | ||
| 85 | } | ||
| 86 | |||
| 87 | static bool qmp_magic_valid(struct qmp *qmp) | ||
| 88 | { | ||
| 89 | return readl(qmp->msgram + QMP_DESC_MAGIC) == QMP_MAGIC; | ||
| 90 | } | ||
| 91 | |||
| 92 | static bool qmp_link_acked(struct qmp *qmp) | ||
| 93 | { | ||
| 94 | return readl(qmp->msgram + QMP_DESC_MCORE_LINK_STATE_ACK) == QMP_STATE_UP; | ||
| 95 | } | ||
| 96 | |||
| 97 | static bool qmp_mcore_channel_acked(struct qmp *qmp) | ||
| 98 | { | ||
| 99 | return readl(qmp->msgram + QMP_DESC_MCORE_CH_STATE_ACK) == QMP_STATE_UP; | ||
| 100 | } | ||
| 101 | |||
| 102 | static bool qmp_ucore_channel_up(struct qmp *qmp) | ||
| 103 | { | ||
| 104 | return readl(qmp->msgram + QMP_DESC_UCORE_CH_STATE) == QMP_STATE_UP; | ||
| 105 | } | ||
| 106 | |||
| 107 | static int qmp_open(struct qmp *qmp) | ||
| 108 | { | ||
| 109 | int ret; | ||
| 110 | u32 val; | ||
| 111 | |||
| 112 | if (!qmp_magic_valid(qmp)) { | ||
| 113 | dev_err(qmp->dev, "QMP magic doesn't match\n"); | ||
| 114 | return -EINVAL; | ||
| 115 | } | ||
| 116 | |||
| 117 | val = readl(qmp->msgram + QMP_DESC_VERSION); | ||
| 118 | if (val != QMP_VERSION) { | ||
| 119 | dev_err(qmp->dev, "unsupported QMP version %d\n", val); | ||
| 120 | return -EINVAL; | ||
| 121 | } | ||
| 122 | |||
| 123 | qmp->offset = readl(qmp->msgram + QMP_DESC_MCORE_MBOX_OFFSET); | ||
| 124 | qmp->size = readl(qmp->msgram + QMP_DESC_MCORE_MBOX_SIZE); | ||
| 125 | if (!qmp->size) { | ||
| 126 | dev_err(qmp->dev, "invalid mailbox size\n"); | ||
| 127 | return -EINVAL; | ||
| 128 | } | ||
| 129 | |||
| 130 | /* Ack remote core's link state */ | ||
| 131 | val = readl(qmp->msgram + QMP_DESC_UCORE_LINK_STATE); | ||
| 132 | writel(val, qmp->msgram + QMP_DESC_UCORE_LINK_STATE_ACK); | ||
| 133 | |||
| 134 | /* Set local core's link state to up */ | ||
| 135 | writel(QMP_STATE_UP, qmp->msgram + QMP_DESC_MCORE_LINK_STATE); | ||
| 136 | |||
| 137 | qmp_kick(qmp); | ||
| 138 | |||
| 139 | ret = wait_event_timeout(qmp->event, qmp_link_acked(qmp), HZ); | ||
| 140 | if (!ret) { | ||
| 141 | dev_err(qmp->dev, "ucore didn't ack link\n"); | ||
| 142 | goto timeout_close_link; | ||
| 143 | } | ||
| 144 | |||
| 145 | writel(QMP_STATE_UP, qmp->msgram + QMP_DESC_MCORE_CH_STATE); | ||
| 146 | |||
| 147 | qmp_kick(qmp); | ||
| 148 | |||
| 149 | ret = wait_event_timeout(qmp->event, qmp_ucore_channel_up(qmp), HZ); | ||
| 150 | if (!ret) { | ||
| 151 | dev_err(qmp->dev, "ucore didn't open channel\n"); | ||
| 152 | goto timeout_close_channel; | ||
| 153 | } | ||
| 154 | |||
| 155 | /* Ack remote core's channel state */ | ||
| 156 | writel(QMP_STATE_UP, qmp->msgram + QMP_DESC_UCORE_CH_STATE_ACK); | ||
| 157 | |||
| 158 | qmp_kick(qmp); | ||
| 159 | |||
| 160 | ret = wait_event_timeout(qmp->event, qmp_mcore_channel_acked(qmp), HZ); | ||
| 161 | if (!ret) { | ||
| 162 | dev_err(qmp->dev, "ucore didn't ack channel\n"); | ||
| 163 | goto timeout_close_channel; | ||
| 164 | } | ||
| 165 | |||
| 166 | return 0; | ||
| 167 | |||
| 168 | timeout_close_channel: | ||
| 169 | writel(QMP_STATE_DOWN, qmp->msgram + QMP_DESC_MCORE_CH_STATE); | ||
| 170 | |||
| 171 | timeout_close_link: | ||
| 172 | writel(QMP_STATE_DOWN, qmp->msgram + QMP_DESC_MCORE_LINK_STATE); | ||
| 173 | qmp_kick(qmp); | ||
| 174 | |||
| 175 | return -ETIMEDOUT; | ||
| 176 | } | ||
| 177 | |||
| 178 | static void qmp_close(struct qmp *qmp) | ||
| 179 | { | ||
| 180 | writel(QMP_STATE_DOWN, qmp->msgram + QMP_DESC_MCORE_CH_STATE); | ||
| 181 | writel(QMP_STATE_DOWN, qmp->msgram + QMP_DESC_MCORE_LINK_STATE); | ||
| 182 | qmp_kick(qmp); | ||
| 183 | } | ||
| 184 | |||
| 185 | static irqreturn_t qmp_intr(int irq, void *data) | ||
| 186 | { | ||
| 187 | struct qmp *qmp = data; | ||
| 188 | |||
| 189 | wake_up_interruptible_all(&qmp->event); | ||
| 190 | |||
| 191 | return IRQ_HANDLED; | ||
| 192 | } | ||
| 193 | |||
| 194 | static bool qmp_message_empty(struct qmp *qmp) | ||
| 195 | { | ||
| 196 | return readl(qmp->msgram + qmp->offset) == 0; | ||
| 197 | } | ||
| 198 | |||
| 199 | /** | ||
| 200 | * qmp_send() - send a message to the AOSS | ||
| 201 | * @qmp: qmp context | ||
| 202 | * @data: message to be sent | ||
| 203 | * @len: length of the message | ||
| 204 | * | ||
| 205 | * Transmit @data to AOSS and wait for the AOSS to acknowledge the message. | ||
| 206 | * @len must be a multiple of 4 and not longer than the mailbox size. Access is | ||
| 207 | * synchronized by this implementation. | ||
| 208 | * | ||
| 209 | * Return: 0 on success, negative errno on failure | ||
| 210 | */ | ||
| 211 | static int qmp_send(struct qmp *qmp, const void *data, size_t len) | ||
| 212 | { | ||
| 213 | long time_left; | ||
| 214 | int ret; | ||
| 215 | |||
| 216 | if (WARN_ON(len + sizeof(u32) > qmp->size)) | ||
| 217 | return -EINVAL; | ||
| 218 | |||
| 219 | if (WARN_ON(len % sizeof(u32))) | ||
| 220 | return -EINVAL; | ||
| 221 | |||
| 222 | mutex_lock(&qmp->tx_lock); | ||
| 223 | |||
| 224 | /* The message RAM only implements 32-bit accesses */ | ||
| 225 | __iowrite32_copy(qmp->msgram + qmp->offset + sizeof(u32), | ||
| 226 | data, len / sizeof(u32)); | ||
| 227 | writel(len, qmp->msgram + qmp->offset); | ||
| 228 | qmp_kick(qmp); | ||
| 229 | |||
| 230 | time_left = wait_event_interruptible_timeout(qmp->event, | ||
| 231 | qmp_message_empty(qmp), HZ); | ||
| 232 | if (!time_left) { | ||
| 233 | dev_err(qmp->dev, "ucore did not ack channel\n"); | ||
| 234 | ret = -ETIMEDOUT; | ||
| 235 | |||
| 236 | /* Clear message from buffer */ | ||
| 237 | writel(0, qmp->msgram + qmp->offset); | ||
| 238 | } else { | ||
| 239 | ret = 0; | ||
| 240 | } | ||
| 241 | |||
| 242 | mutex_unlock(&qmp->tx_lock); | ||
| 243 | |||
| 244 | return ret; | ||
| 245 | } | ||
| 246 | |||
| 247 | static int qmp_qdss_clk_prepare(struct clk_hw *hw) | ||
| 248 | { | ||
| 249 | static const char buf[QMP_MSG_LEN] = "{class: clock, res: qdss, val: 1}"; | ||
| 250 | struct qmp *qmp = container_of(hw, struct qmp, qdss_clk); | ||
| 251 | |||
| 252 | return qmp_send(qmp, buf, sizeof(buf)); | ||
| 253 | } | ||
| 254 | |||
| 255 | static void qmp_qdss_clk_unprepare(struct clk_hw *hw) | ||
| 256 | { | ||
| 257 | static const char buf[QMP_MSG_LEN] = "{class: clock, res: qdss, val: 0}"; | ||
| 258 | struct qmp *qmp = container_of(hw, struct qmp, qdss_clk); | ||
| 259 | |||
| 260 | qmp_send(qmp, buf, sizeof(buf)); | ||
| 261 | } | ||
| 262 | |||
| 263 | static const struct clk_ops qmp_qdss_clk_ops = { | ||
| 264 | .prepare = qmp_qdss_clk_prepare, | ||
| 265 | .unprepare = qmp_qdss_clk_unprepare, | ||
| 266 | }; | ||
| 267 | |||
| 268 | static int qmp_qdss_clk_add(struct qmp *qmp) | ||
| 269 | { | ||
| 270 | static const struct clk_init_data qdss_init = { | ||
| 271 | .ops = &qmp_qdss_clk_ops, | ||
| 272 | .name = "qdss", | ||
| 273 | }; | ||
| 274 | int ret; | ||
| 275 | |||
| 276 | qmp->qdss_clk.init = &qdss_init; | ||
| 277 | ret = clk_hw_register(qmp->dev, &qmp->qdss_clk); | ||
| 278 | if (ret < 0) { | ||
| 279 | dev_err(qmp->dev, "failed to register qdss clock\n"); | ||
| 280 | return ret; | ||
| 281 | } | ||
| 282 | |||
| 283 | ret = of_clk_add_hw_provider(qmp->dev->of_node, of_clk_hw_simple_get, | ||
| 284 | &qmp->qdss_clk); | ||
| 285 | if (ret < 0) { | ||
| 286 | dev_err(qmp->dev, "unable to register of clk hw provider\n"); | ||
| 287 | clk_hw_unregister(&qmp->qdss_clk); | ||
| 288 | } | ||
| 289 | |||
| 290 | return ret; | ||
| 291 | } | ||
| 292 | |||
| 293 | static void qmp_qdss_clk_remove(struct qmp *qmp) | ||
| 294 | { | ||
| 295 | of_clk_del_provider(qmp->dev->of_node); | ||
| 296 | clk_hw_unregister(&qmp->qdss_clk); | ||
| 297 | } | ||
| 298 | |||
| 299 | static int qmp_pd_power_toggle(struct qmp_pd *res, bool enable) | ||
| 300 | { | ||
| 301 | char buf[QMP_MSG_LEN] = {}; | ||
| 302 | |||
| 303 | snprintf(buf, sizeof(buf), | ||
| 304 | "{class: image, res: load_state, name: %s, val: %s}", | ||
| 305 | res->pd.name, enable ? "on" : "off"); | ||
| 306 | return qmp_send(res->qmp, buf, sizeof(buf)); | ||
| 307 | } | ||
| 308 | |||
| 309 | static int qmp_pd_power_on(struct generic_pm_domain *domain) | ||
| 310 | { | ||
| 311 | return qmp_pd_power_toggle(to_qmp_pd_resource(domain), true); | ||
| 312 | } | ||
| 313 | |||
| 314 | static int qmp_pd_power_off(struct generic_pm_domain *domain) | ||
| 315 | { | ||
| 316 | return qmp_pd_power_toggle(to_qmp_pd_resource(domain), false); | ||
| 317 | } | ||
| 318 | |||
| 319 | static const char * const sdm845_resources[] = { | ||
| 320 | [AOSS_QMP_LS_CDSP] = "cdsp", | ||
| 321 | [AOSS_QMP_LS_LPASS] = "adsp", | ||
| 322 | [AOSS_QMP_LS_MODEM] = "modem", | ||
| 323 | [AOSS_QMP_LS_SLPI] = "slpi", | ||
| 324 | [AOSS_QMP_LS_SPSS] = "spss", | ||
| 325 | [AOSS_QMP_LS_VENUS] = "venus", | ||
| 326 | }; | ||
| 327 | |||
| 328 | static int qmp_pd_add(struct qmp *qmp) | ||
| 329 | { | ||
| 330 | struct genpd_onecell_data *data = &qmp->pd_data; | ||
| 331 | struct device *dev = qmp->dev; | ||
| 332 | struct qmp_pd *res; | ||
| 333 | size_t num = ARRAY_SIZE(sdm845_resources); | ||
| 334 | int ret; | ||
| 335 | int i; | ||
| 336 | |||
| 337 | res = devm_kcalloc(dev, num, sizeof(*res), GFP_KERNEL); | ||
| 338 | if (!res) | ||
| 339 | return -ENOMEM; | ||
| 340 | |||
| 341 | data->domains = devm_kcalloc(dev, num, sizeof(*data->domains), | ||
| 342 | GFP_KERNEL); | ||
| 343 | if (!data->domains) | ||
| 344 | return -ENOMEM; | ||
| 345 | |||
| 346 | for (i = 0; i < num; i++) { | ||
| 347 | res[i].qmp = qmp; | ||
| 348 | res[i].pd.name = sdm845_resources[i]; | ||
| 349 | res[i].pd.power_on = qmp_pd_power_on; | ||
| 350 | res[i].pd.power_off = qmp_pd_power_off; | ||
| 351 | |||
| 352 | ret = pm_genpd_init(&res[i].pd, NULL, true); | ||
| 353 | if (ret < 0) { | ||
| 354 | dev_err(dev, "failed to init genpd\n"); | ||
| 355 | goto unroll_genpds; | ||
| 356 | } | ||
| 357 | |||
| 358 | data->domains[i] = &res[i].pd; | ||
| 359 | } | ||
| 360 | |||
| 361 | data->num_domains = i; | ||
| 362 | |||
| 363 | ret = of_genpd_add_provider_onecell(dev->of_node, data); | ||
| 364 | if (ret < 0) | ||
| 365 | goto unroll_genpds; | ||
| 366 | |||
| 367 | return 0; | ||
| 368 | |||
| 369 | unroll_genpds: | ||
| 370 | for (i--; i >= 0; i--) | ||
| 371 | pm_genpd_remove(data->domains[i]); | ||
| 372 | |||
| 373 | return ret; | ||
| 374 | } | ||
| 375 | |||
| 376 | static void qmp_pd_remove(struct qmp *qmp) | ||
| 377 | { | ||
| 378 | struct genpd_onecell_data *data = &qmp->pd_data; | ||
| 379 | struct device *dev = qmp->dev; | ||
| 380 | int i; | ||
| 381 | |||
| 382 | of_genpd_del_provider(dev->of_node); | ||
| 383 | |||
| 384 | for (i = 0; i < data->num_domains; i++) | ||
| 385 | pm_genpd_remove(data->domains[i]); | ||
| 386 | } | ||
| 387 | |||
| 388 | static int qmp_probe(struct platform_device *pdev) | ||
| 389 | { | ||
| 390 | struct resource *res; | ||
| 391 | struct qmp *qmp; | ||
| 392 | int irq; | ||
| 393 | int ret; | ||
| 394 | |||
| 395 | qmp = devm_kzalloc(&pdev->dev, sizeof(*qmp), GFP_KERNEL); | ||
| 396 | if (!qmp) | ||
| 397 | return -ENOMEM; | ||
| 398 | |||
| 399 | qmp->dev = &pdev->dev; | ||
| 400 | init_waitqueue_head(&qmp->event); | ||
| 401 | mutex_init(&qmp->tx_lock); | ||
| 402 | |||
| 403 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
| 404 | qmp->msgram = devm_ioremap_resource(&pdev->dev, res); | ||
| 405 | if (IS_ERR(qmp->msgram)) | ||
| 406 | return PTR_ERR(qmp->msgram); | ||
| 407 | |||
| 408 | qmp->mbox_client.dev = &pdev->dev; | ||
| 409 | qmp->mbox_client.knows_txdone = true; | ||
| 410 | qmp->mbox_chan = mbox_request_channel(&qmp->mbox_client, 0); | ||
| 411 | if (IS_ERR(qmp->mbox_chan)) { | ||
| 412 | dev_err(&pdev->dev, "failed to acquire ipc mailbox\n"); | ||
| 413 | return PTR_ERR(qmp->mbox_chan); | ||
| 414 | } | ||
| 415 | |||
| 416 | irq = platform_get_irq(pdev, 0); | ||
| 417 | ret = devm_request_irq(&pdev->dev, irq, qmp_intr, IRQF_ONESHOT, | ||
| 418 | "aoss-qmp", qmp); | ||
| 419 | if (ret < 0) { | ||
| 420 | dev_err(&pdev->dev, "failed to request interrupt\n"); | ||
| 421 | goto err_free_mbox; | ||
| 422 | } | ||
| 423 | |||
| 424 | ret = qmp_open(qmp); | ||
| 425 | if (ret < 0) | ||
| 426 | goto err_free_mbox; | ||
| 427 | |||
| 428 | ret = qmp_qdss_clk_add(qmp); | ||
| 429 | if (ret) | ||
| 430 | goto err_close_qmp; | ||
| 431 | |||
| 432 | ret = qmp_pd_add(qmp); | ||
| 433 | if (ret) | ||
| 434 | goto err_remove_qdss_clk; | ||
| 435 | |||
| 436 | platform_set_drvdata(pdev, qmp); | ||
| 437 | |||
| 438 | return 0; | ||
| 439 | |||
| 440 | err_remove_qdss_clk: | ||
| 441 | qmp_qdss_clk_remove(qmp); | ||
| 442 | err_close_qmp: | ||
| 443 | qmp_close(qmp); | ||
| 444 | err_free_mbox: | ||
| 445 | mbox_free_channel(qmp->mbox_chan); | ||
| 446 | |||
| 447 | return ret; | ||
| 448 | } | ||
| 449 | |||
| 450 | static int qmp_remove(struct platform_device *pdev) | ||
| 451 | { | ||
| 452 | struct qmp *qmp = platform_get_drvdata(pdev); | ||
| 453 | |||
| 454 | qmp_qdss_clk_remove(qmp); | ||
| 455 | qmp_pd_remove(qmp); | ||
| 456 | |||
| 457 | qmp_close(qmp); | ||
| 458 | mbox_free_channel(qmp->mbox_chan); | ||
| 459 | |||
| 460 | return 0; | ||
| 461 | } | ||
| 462 | |||
| 463 | static const struct of_device_id qmp_dt_match[] = { | ||
| 464 | { .compatible = "qcom,sdm845-aoss-qmp", }, | ||
| 465 | {} | ||
| 466 | }; | ||
| 467 | MODULE_DEVICE_TABLE(of, qmp_dt_match); | ||
| 468 | |||
| 469 | static struct platform_driver qmp_driver = { | ||
| 470 | .driver = { | ||
| 471 | .name = "qcom_aoss_qmp", | ||
| 472 | .of_match_table = qmp_dt_match, | ||
| 473 | }, | ||
| 474 | .probe = qmp_probe, | ||
| 475 | .remove = qmp_remove, | ||
| 476 | }; | ||
| 477 | module_platform_driver(qmp_driver); | ||
| 478 | |||
| 479 | MODULE_DESCRIPTION("Qualcomm AOSS QMP driver"); | ||
| 480 | MODULE_LICENSE("GPL v2"); | ||
| @@ -16,56 +16,76 @@ · 15 unmodified lines | |||
| 16 | 16 | ||
| 17 | #define domain_to_rpmpd(domain) container_of(domain, struct rpmpd, pd) | 17 | #define domain_to_rpmpd(domain) container_of(domain, struct rpmpd, pd) |
| 18 | 18 | ||
| 19 | /* Resource types */ | 19 | /* Resource types: |
| 20 | * RPMPD_X is X encoded as a little-endian, lower-case, ASCII string */ | ||
| 20 | #define RPMPD_SMPA 0x61706d73 | 21 | #define RPMPD_SMPA 0x61706d73 |
| 21 | #define RPMPD_LDOA 0x616f646c | 22 | #define RPMPD_LDOA 0x616f646c |
| 23 | #define RPMPD_RWCX 0x78637772 | ||
| 24 | #define RPMPD_RWMX 0x786d7772 | ||
| 25 | #define RPMPD_RWLC 0x636c7772 | ||
| 26 | #define RPMPD_RWLM 0x6d6c7772 | ||
| 27 | #define RPMPD_RWSC 0x63737772 | ||
| 28 | #define RPMPD_RWSM 0x6d737772 | ||
| 22 | 29 | ||
| 23 | /* Operation Keys */ | 30 | /* Operation Keys */ |
| 24 | #define KEY_CORNER 0x6e726f63 /* corn */ | 31 | #define KEY_CORNER 0x6e726f63 /* corn */ |
| 25 | #define KEY_ENABLE 0x6e657773 /* swen */ | 32 | #define KEY_ENABLE 0x6e657773 /* swen */ |
| 26 | #define KEY_FLOOR_CORNER 0x636676 /* vfc */ | 33 | #define KEY_FLOOR_CORNER 0x636676 /* vfc */ |
| 34 | #define KEY_FLOOR_LEVEL 0x6c6676 /* vfl */ | ||
| 35 | #define KEY_LEVEL 0x6c766c76 /* vlvl */ | ||
| 27 | 36 | ||
| 28 | #define MAX_RPMPD_STATE 6 | 37 | #define MAX_8996_RPMPD_STATE 6 |
| 29 | 38 | ||
| 30 | #define DEFINE_RPMPD_CORNER_SMPA(_platform, _name, _active, r_id) \ | 39 | #define DEFINE_RPMPD_PAIR(_platform, _name, _active, r_type, r_key, \ |
| 40 | r_id) \ | ||
| 31 | static struct rpmpd _platform##_##_active; \ | 41 | static struct rpmpd _platform##_##_active; \ |
| 32 | static struct rpmpd _platform##_##_name = { \ | 42 | static struct rpmpd _platform##_##_name = { \ |
| 33 | .pd = { .name = #_name, }, \ | 43 | .pd = { .name = #_name, }, \ |
| 34 | .peer = &_platform##_##_active, \ | 44 | .peer = &_platform##_##_active, \ |
| 35 | .res_type = RPMPD_SMPA, \ | 45 | .res_type = RPMPD_##r_type, \ |
| 36 | .res_id = r_id, \ | 46 | .res_id = r_id, \ |
| 37 | .key = KEY_CORNER, \ | 47 | .key = KEY_##r_key, \ |
| 38 | }; \ | 48 | }; \ |
| 39 | static struct rpmpd _platform##_##_active = { \ | 49 | static struct rpmpd _platform##_##_active = { \ |
| 40 | .pd = { .name = #_active, }, \ | 50 | .pd = { .name = #_active, }, \ |
| 41 | .peer = &_platform##_##_name, \ | 51 | .peer = &_platform##_##_name, \ |
| 42 | .active_only = true, \ | 52 | .active_only = true, \ |
| 43 | .res_type = RPMPD_SMPA, \ | 53 | .res_type = RPMPD_##r_type, \ |
| 44 | .res_id = r_id, \ | 54 | .res_id = r_id, \ |
| 45 | .key = KEY_CORNER, \ | 55 | .key = KEY_##r_key, \ |
| 46 | } | 56 | } |
| 47 | 57 | ||
| 48 | #define DEFINE_RPMPD_CORNER_LDOA(_platform, _name, r_id) \ | 58 | #define DEFINE_RPMPD_CORNER(_platform, _name, r_type, r_id) \ |
| 49 | static struct rpmpd _platform##_##_name = { \ | 59 | static struct rpmpd _platform##_##_name = { \ |
| 50 | .pd = { .name = #_name, }, \ | 60 | .pd = { .name = #_name, }, \ |
| 51 | .res_type = RPMPD_LDOA, \ | 61 | .res_type = RPMPD_##r_type, \ |
| 52 | .res_id = r_id, \ | 62 | .res_id = r_id, \ |
| 53 | .key = KEY_CORNER, \ | 63 | .key = KEY_CORNER, \ |
| 54 | } | 64 | } |
| 55 | 65 | ||
| 56 | #define DEFINE_RPMPD_VFC(_platform, _name, r_id, r_type) \ | 66 | #define DEFINE_RPMPD_LEVEL(_platform, _name, r_type, r_id) \ |
| 57 | static struct rpmpd _platform##_##_name = { \ | 67 | static struct rpmpd _platform##_##_name = { \ |
| 58 | .pd = { .name = #_name, }, \ | 68 | .pd = { .name = #_name, }, \ |
| 59 | .res_type = r_type, \ | 69 | .res_type = RPMPD_##r_type, \ |
| 60 | .res_id = r_id, \ | 70 | .res_id = r_id, \ |
| 61 | .key = KEY_FLOOR_CORNER, \ | 71 | .key = KEY_LEVEL, \ |
| 62 | } | 72 | } |
| 63 | 73 | ||
| 64 | #define DEFINE_RPMPD_VFC_SMPA(_platform, _name, r_id) \ | 74 | #define DEFINE_RPMPD_VFC(_platform, _name, r_type, r_id) \ |
| 65 | DEFINE_RPMPD_VFC(_platform, _name, r_id, RPMPD_SMPA) | 75 | static struct rpmpd _platform##_##_name = { \ |
| 76 | .pd = { .name = #_name, }, \ | ||
| 77 | .res_type = RPMPD_##r_type, \ | ||
| 78 | .res_id = r_id, \ | ||
| 79 | .key = KEY_FLOOR_CORNER, \ | ||
| 80 | } | ||
| 66 | 81 | ||
| 67 | #define DEFINE_RPMPD_VFC_LDOA(_platform, _name, r_id) \ | 82 | #define DEFINE_RPMPD_VFL(_platform, _name, r_type, r_id) \ |
| 68 | DEFINE_RPMPD_VFC(_platform, _name, r_id, RPMPD_LDOA) | 83 | static struct rpmpd _platform##_##_name = { \ |
| 84 | .pd = { .name = #_name, }, \ | ||
| 85 | .res_type = RPMPD_##r_type, \ | ||
| 86 | .res_id = r_id, \ | ||
| 87 | .key = KEY_FLOOR_LEVEL, \ | ||
| 88 | } | ||
| 69 | 89 | ||
| 70 | struct rpmpd_req { | 90 | struct rpmpd_req { |
| 71 | __le32 key; | 91 | __le32 key; |
| @@ -83,23 +103,25 @@ struct rpmpd { · 11 unmodified lines | |||
| 83 | const int res_type; | 103 | const int res_type; |
| 84 | const int res_id; | 104 | const int res_id; |
| 85 | struct qcom_smd_rpm *rpm; | 105 | struct qcom_smd_rpm *rpm; |
| 106 | unsigned int max_state; | ||
| 86 | __le32 key; | 107 | __le32 key; |
| 87 | }; | 108 | }; |
| 88 | 109 | ||
| 89 | struct rpmpd_desc { | 110 | struct rpmpd_desc { |
| 90 | struct rpmpd **rpmpds; | 111 | struct rpmpd **rpmpds; |
| 91 | size_t num_pds; | 112 | size_t num_pds; |
| 113 | unsigned int max_state; | ||
| 92 | }; | 114 | }; |
| 93 | 115 | ||
| 94 | static DEFINE_MUTEX(rpmpd_lock); | 116 | static DEFINE_MUTEX(rpmpd_lock); |
| 95 | 117 | ||
| 96 | /* msm8996 RPM Power domains */ | 118 | /* msm8996 RPM Power domains */ |
| 97 | DEFINE_RPMPD_CORNER_SMPA(msm8996, vddcx, vddcx_ao, 1); | 119 | DEFINE_RPMPD_PAIR(msm8996, vddcx, vddcx_ao, SMPA, CORNER, 1); |
| 98 | DEFINE_RPMPD_CORNER_SMPA(msm8996, vddmx, vddmx_ao, 2); | 120 | DEFINE_RPMPD_PAIR(msm8996, vddmx, vddmx_ao, SMPA, CORNER, 2); |
| 99 | DEFINE_RPMPD_CORNER_LDOA(msm8996, vddsscx, 26); | 121 | DEFINE_RPMPD_CORNER(msm8996, vddsscx, LDOA, 26); |
| 100 | 122 | ||
| 101 | DEFINE_RPMPD_VFC_SMPA(msm8996, vddcx_vfc, 1); | 123 | DEFINE_RPMPD_VFC(msm8996, vddcx_vfc, SMPA, 1); |
| 102 | DEFINE_RPMPD_VFC_LDOA(msm8996, vddsscx_vfc, 26); | 124 | DEFINE_RPMPD_VFC(msm8996, vddsscx_vfc, LDOA, 26); |
| 103 | 125 | ||
| 104 | static struct rpmpd *msm8996_rpmpds[] = { | 126 | static struct rpmpd *msm8996_rpmpds[] = { |
| 105 | [MSM8996_VDDCX] = &msm8996_vddcx, | 127 | [MSM8996_VDDCX] = &msm8996_vddcx, |
| @@ -114,10 +136,71 @@ static struct rpmpd *msm8996_rpmpds[] = { · 8 unmodified lines | |||
| 114 | static const struct rpmpd_desc msm8996_desc = { | 136 | static const struct rpmpd_desc msm8996_desc = { |
| 115 | .rpmpds = msm8996_rpmpds, | 137 | .rpmpds = msm8996_rpmpds, |
| 116 | .num_pds = ARRAY_SIZE(msm8996_rpmpds), | 138 | .num_pds = ARRAY_SIZE(msm8996_rpmpds), |
| 139 | .max_state = MAX_8996_RPMPD_STATE, | ||
| 140 | }; | ||
| 141 | |||
| 142 | /* msm8998 RPM Power domains */ | ||
| 143 | DEFINE_RPMPD_PAIR(msm8998, vddcx, vddcx_ao, RWCX, LEVEL, 0); | ||
| 144 | DEFINE_RPMPD_VFL(msm8998, vddcx_vfl, RWCX, 0); | ||
| 145 | |||
| 146 | DEFINE_RPMPD_PAIR(msm8998, vddmx, vddmx_ao, RWMX, LEVEL, 0); | ||
| 147 | DEFINE_RPMPD_VFL(msm8998, vddmx_vfl, RWMX, 0); | ||
| 148 | |||
| 149 | DEFINE_RPMPD_LEVEL(msm8998, vdd_ssccx, RWSC, 0); | ||
| 150 | DEFINE_RPMPD_VFL(msm8998, vdd_ssccx_vfl, RWSC, 0); | ||
| 151 | |||
| 152 | DEFINE_RPMPD_LEVEL(msm8998, vdd_sscmx, RWSM, 0); | ||
| 153 | DEFINE_RPMPD_VFL(msm8998, vdd_sscmx_vfl, RWSM, 0); | ||
| 154 | |||
| 155 | static struct rpmpd *msm8998_rpmpds[] = { | ||
| 156 | [MSM8998_VDDCX] = &msm8998_vddcx, | ||
| 157 | [MSM8998_VDDCX_AO] = &msm8998_vddcx_ao, | ||
| 158 | [MSM8998_VDDCX_VFL] = &msm8998_vddcx_vfl, | ||
| 159 | [MSM8998_VDDMX] = &msm8998_vddmx, | ||
| 160 | [MSM8998_VDDMX_AO] = &msm8998_vddmx_ao, | ||
| 161 | [MSM8998_VDDMX_VFL] = &msm8998_vddmx_vfl, | ||
| 162 | [MSM8998_SSCCX] = &msm8998_vdd_ssccx, | ||
| 163 | [MSM8998_SSCCX_VFL] = &msm8998_vdd_ssccx_vfl, | ||
| 164 | [MSM8998_SSCMX] = &msm8998_vdd_sscmx, | ||
| 165 | [MSM8998_SSCMX_VFL] = &msm8998_vdd_sscmx_vfl, | ||
| 166 | }; | ||
| 167 | |||
| 168 | static const struct rpmpd_desc msm8998_desc = { | ||
| 169 | .rpmpds = msm8998_rpmpds, | ||
| 170 | .num_pds = ARRAY_SIZE(msm8998_rpmpds), | ||
| 171 | .max_state = RPM_SMD_LEVEL_BINNING, | ||
| 172 | }; | ||
| 173 | |||
| 174 | /* qcs404 RPM Power domains */ | ||
| 175 | DEFINE_RPMPD_PAIR(qcs404, vddmx, vddmx_ao, RWMX, LEVEL, 0); | ||
| 176 | DEFINE_RPMPD_VFL(qcs404, vddmx_vfl, RWMX, 0); | ||
| 177 | |||
| 178 | DEFINE_RPMPD_LEVEL(qcs404, vdd_lpicx, RWLC, 0); | ||
| 179 | DEFINE_RPMPD_VFL(qcs404, vdd_lpicx_vfl, RWLC, 0); | ||
| 180 | |||
| 181 | DEFINE_RPMPD_LEVEL(qcs404, vdd_lpimx, RWLM, 0); | ||
| 182 | DEFINE_RPMPD_VFL(qcs404, vdd_lpimx_vfl, RWLM, 0); | ||
| 183 | |||
| 184 | static struct rpmpd *qcs404_rpmpds[] = { | ||
| 185 | [QCS404_VDDMX] = &qcs404_vddmx, | ||
| 186 | [QCS404_VDDMX_AO] = &qcs404_vddmx_ao, | ||
| 187 | [QCS404_VDDMX_VFL] = &qcs404_vddmx_vfl, | ||
| 188 | [QCS404_LPICX] = &qcs404_vdd_lpicx, | ||
| 189 | [QCS404_LPICX_VFL] = &qcs404_vdd_lpicx_vfl, | ||
| 190 | [QCS404_LPIMX] = &qcs404_vdd_lpimx, | ||
| 191 | [QCS404_LPIMX_VFL] = &qcs404_vdd_lpimx_vfl, | ||
| 192 | }; | ||
| 193 | |||
| 194 | static const struct rpmpd_desc qcs404_desc = { | ||
| 195 | .rpmpds = qcs404_rpmpds, | ||
| 196 | .num_pds = ARRAY_SIZE(qcs404_rpmpds), | ||
| 197 | .max_state = RPM_SMD_LEVEL_BINNING, | ||
| 117 | }; | 198 | }; |
| 118 | 199 | ||
| 119 | static const struct of_device_id rpmpd_match_table[] = { | 200 | static const struct of_device_id rpmpd_match_table[] = { |
| 120 | { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc }, | 201 | { .compatible = "qcom,msm8996-rpmpd", .data = &msm8996_desc }, |
| 202 | { .compatible = "qcom,msm8998-rpmpd", .data = &msm8998_desc }, | ||
| 203 | { .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc }, | ||
| 121 | { } | 204 | { } |
| 122 | }; | 205 | }; |
| 123 | 206 | ||
| @@ -225,14 +308,16 @@ static int rpmpd_set_performance(struct generic_pm_domain *domain, · 101 unmodified lines | |||
| 225 | int ret = 0; | 308 | int ret = 0; |
| 226 | struct rpmpd *pd = domain_to_rpmpd(domain); | 309 | struct rpmpd *pd = domain_to_rpmpd(domain); |
| 227 | 310 | ||
| 228 | if (state > MAX_RPMPD_STATE) | 311 | if (state > pd->max_state) |
| 229 | goto out; | 312 | state = pd->max_state; |
| 230 | 313 | ||
| 231 | mutex_lock(&rpmpd_lock); | 314 | mutex_lock(&rpmpd_lock); |
| 232 | 315 | ||
| 233 | pd->corner = state; | 316 | pd->corner = state; |
| 234 | 317 | ||
| 235 | if (!pd->enabled && pd->key != KEY_FLOOR_CORNER) | 318 | /* Always send updates for vfc and vfl */ |
| 319 | if (!pd->enabled && pd->key != KEY_FLOOR_CORNER && | ||
| 320 | pd->key != KEY_FLOOR_LEVEL) | ||
| 236 | goto out; | 321 | goto out; |
| 237 | 322 | ||
| 238 | ret = rpmpd_aggregate_corner(pd); | 323 | ret = rpmpd_aggregate_corner(pd); |
| @@ -287,6 +372,7 @@ static int rpmpd_probe(struct platform_device *pdev) · 48 unmodified lines | |||
| 287 | } | 372 | } |
| 288 | 373 | ||
| 289 | rpmpds[i]->rpm = rpm; | 374 | rpmpds[i]->rpm = rpm; |
| 375 | rpmpds[i]->max_state = desc->max_state; | ||
| 290 | rpmpds[i]->pd.power_off = rpmpd_power_off; | 376 | rpmpds[i]->pd.power_off = rpmpd_power_off; |
| 291 | rpmpds[i]->pd.power_on = rpmpd_power_on; | 377 | rpmpds[i]->pd.power_on = rpmpd_power_on; |
| 292 | rpmpds[i]->pd.set_performance_state = rpmpd_set_performance; | 378 | rpmpds[i]->pd.set_performance_state = rpmpd_set_performance; |
| @@ -86,47 +86,47 @@ struct rockchip_pmu { · 85 unmodified lines | |||
| 86 | #define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd) | 86 | #define to_rockchip_pd(gpd) container_of(gpd, struct rockchip_pm_domain, genpd) |
| 87 | 87 | ||
| 88 | #define DOMAIN(pwr, status, req, idle, ack, wakeup) \ | 88 | #define DOMAIN(pwr, status, req, idle, ack, wakeup) \ |
| 89 | { \ | 89 | { \ |
| 90 | .pwr_mask = (pwr >= 0) ? BIT(pwr) : 0, \ | 90 | .pwr_mask = (pwr), \ |
| 91 | .status_mask = (status >= 0) ? BIT(status) : 0, \ | 91 | .status_mask = (status), \ |
| 92 | .req_mask = (req >= 0) ? BIT(req) : 0, \ | 92 | .req_mask = (req), \ |
| 93 | .idle_mask = (idle >= 0) ? BIT(idle) : 0, \ | 93 | .idle_mask = (idle), \ |
| 94 | .ack_mask = (ack >= 0) ? BIT(ack) : 0, \ | 94 | .ack_mask = (ack), \ |
| 95 | .active_wakeup = wakeup, \ | 95 | .active_wakeup = (wakeup), \ |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | #define DOMAIN_M(pwr, status, req, idle, ack, wakeup) \ | 98 | #define DOMAIN_M(pwr, status, req, idle, ack, wakeup) \ |
| 99 | { \ | 99 | { \ |
| 100 | .pwr_w_mask = (pwr >= 0) ? BIT(pwr + 16) : 0, \ | 100 | .pwr_w_mask = (pwr) << 16, \ |
| 101 | .pwr_mask = (pwr >= 0) ? BIT(pwr) : 0, \ | 101 | .pwr_mask = (pwr), \ |
| 102 | .status_mask = (status >= 0) ? BIT(status) : 0, \ | 102 | .status_mask = (status), \ |
| 103 | .req_w_mask = (req >= 0) ? BIT(req + 16) : 0, \ | 103 | .req_w_mask = (req) << 16, \ |
| 104 | .req_mask = (req >= 0) ? BIT(req) : 0, \ | 104 | .req_mask = (req), \ |
| 105 | .idle_mask = (idle >= 0) ? BIT(idle) : 0, \ | 105 | .idle_mask = (idle), \ |
| 106 | .ack_mask = (ack >= 0) ? BIT(ack) : 0, \ | 106 | .ack_mask = (ack), \ |
| 107 | .active_wakeup = wakeup, \ | 107 | .active_wakeup = wakeup, \ |
| 108 | } | 108 | } |
| 109 | 109 | ||
| 110 | #define DOMAIN_RK3036(req, ack, idle, wakeup) \ | 110 | #define DOMAIN_RK3036(req, ack, idle, wakeup) \ |
| 111 | { \ | 111 | { \ |
| 112 | .req_mask = (req >= 0) ? BIT(req) : 0, \ | 112 | .req_mask = (req), \ |
| 113 | .req_w_mask = (req >= 0) ? BIT(req + 16) : 0, \ | 113 | .req_w_mask = (req) << 16, \ |
| 114 | .ack_mask = (ack >= 0) ? BIT(ack) : 0, \ | 114 | .ack_mask = (ack), \ |
| 115 | .idle_mask = (idle >= 0) ? BIT(idle) : 0, \ | 115 | .idle_mask = (idle), \ |
| 116 | .active_wakeup = wakeup, \ | 116 | .active_wakeup = wakeup, \ |
| 117 | } | 117 | } |
| 118 | 118 | ||
| 119 | #define DOMAIN_PX30(pwr, status, req, wakeup) \ | 119 | #define DOMAIN_PX30(pwr, status, req, wakeup) \ |
| 120 | DOMAIN_M(pwr, status, req, (req) + 16, req, wakeup) | 120 | DOMAIN_M(pwr, status, req, (req) << 16, req, wakeup) |
| 121 | 121 | ||
| 122 | #define DOMAIN_RK3288(pwr, status, req, wakeup) \ | 122 | #define DOMAIN_RK3288(pwr, status, req, wakeup) \ |
| 123 | DOMAIN(pwr, status, req, req, (req) + 16, wakeup) | 123 | DOMAIN(pwr, status, req, req, (req) << 16, wakeup) |
| 124 | 124 | ||
| 125 | #define DOMAIN_RK3328(pwr, status, req, wakeup) \ | 125 | #define DOMAIN_RK3328(pwr, status, req, wakeup) \ |
| 126 | DOMAIN_M(pwr, pwr, req, (req) + 10, req, wakeup) | 126 | DOMAIN_M(pwr, pwr, req, (req) << 10, req, wakeup) |
| 127 | 127 | ||
| 128 | #define DOMAIN_RK3368(pwr, status, req, wakeup) \ | 128 | #define DOMAIN_RK3368(pwr, status, req, wakeup) \ |
| 129 | DOMAIN(pwr, status, req, (req) + 16, req, wakeup) | 129 | DOMAIN(pwr, status, req, (req) << 16, req, wakeup) |
| 130 | 130 | ||
| 131 | #define DOMAIN_RK3399(pwr, status, req, wakeup) \ | 131 | #define DOMAIN_RK3399(pwr, status, req, wakeup) \ |
| 132 | DOMAIN(pwr, status, req, req, req, wakeup) | 132 | DOMAIN(pwr, status, req, req, req, wakeup) |
| @@ -716,129 +716,129 @@ err_out: · 583 unmodified lines | |||
| 716 | } | 716 | } |
| 717 | 717 | ||
| 718 | static const struct rockchip_domain_info px30_pm_domains[] = { | 718 | static const struct rockchip_domain_info px30_pm_domains[] = { |
| 719 | [PX30_PD_USB] = DOMAIN_PX30(5, 5, 10, false), | 719 | [PX30_PD_USB] = DOMAIN_PX30(BIT(5), BIT(5), BIT(10), false), |
| 720 | [PX30_PD_SDCARD] = DOMAIN_PX30(8, 8, 9, false), | 720 | [PX30_PD_SDCARD] = DOMAIN_PX30(BIT(8), BIT(8), BIT(9), false), |
| 721 | [PX30_PD_GMAC] = DOMAIN_PX30(10, 10, 6, false), | 721 | [PX30_PD_GMAC] = DOMAIN_PX30(BIT(10), BIT(10), BIT(6), false), |
| 722 | [PX30_PD_MMC_NAND] = DOMAIN_PX30(11, 11, 5, false), | 722 | [PX30_PD_MMC_NAND] = DOMAIN_PX30(BIT(11), BIT(11), BIT(5), false), |
| 723 | [PX30_PD_VPU] = DOMAIN_PX30(12, 12, 14, false), | 723 | [PX30_PD_VPU] = DOMAIN_PX30(BIT(12), BIT(12), BIT(14), false), |
| 724 | [PX30_PD_VO] = DOMAIN_PX30(13, 13, 7, false), | 724 | [PX30_PD_VO] = DOMAIN_PX30(BIT(13), BIT(13), BIT(7), false), |
| 725 | [PX30_PD_VI] = DOMAIN_PX30(14, 14, 8, false), | 725 | [PX30_PD_VI] = DOMAIN_PX30(BIT(14), BIT(14), BIT(8), false), |
| 726 | [PX30_PD_GPU] = DOMAIN_PX30(15, 15, 2, false), | 726 | [PX30_PD_GPU] = DOMAIN_PX30(BIT(15), BIT(15), BIT(2), false), |
| 727 | }; | 727 | }; |
| 728 | 728 | ||
| 729 | static const struct rockchip_domain_info rk3036_pm_domains[] = { | 729 | static const struct rockchip_domain_info rk3036_pm_domains[] = { |
| 730 | [RK3036_PD_MSCH] = DOMAIN_RK3036(14, 23, 30, true), | 730 | [RK3036_PD_MSCH] = DOMAIN_RK3036(BIT(14), BIT(23), BIT(30), true), |
| 731 | [RK3036_PD_CORE] = DOMAIN_RK3036(13, 17, 24, false), | 731 | [RK3036_PD_CORE] = DOMAIN_RK3036(BIT(13), BIT(17), BIT(24), false), |
| 732 | [RK3036_PD_PERI] = DOMAIN_RK3036(12, 18, 25, false), | 732 | [RK3036_PD_PERI] = DOMAIN_RK3036(BIT(12), BIT(18), BIT(25), false), |
| 733 | [RK3036_PD_VIO] = DOMAIN_RK3036(11, 19, 26, false), | 733 | [RK3036_PD_VIO] = DOMAIN_RK3036(BIT(11), BIT(19), BIT(26), false), |
| 734 | [RK3036_PD_VPU] = DOMAIN_RK3036(10, 20, 27, false), | 734 | [RK3036_PD_VPU] = DOMAIN_RK3036(BIT(10), BIT(20), BIT(27), false), |
| 735 | [RK3036_PD_GPU] = DOMAIN_RK3036(9, 21, 28, false), | 735 | [RK3036_PD_GPU] = DOMAIN_RK3036(BIT(9), BIT(21), BIT(28), false), |
| 736 | [RK3036_PD_SYS] = DOMAIN_RK3036(8, 22, 29, false), | 736 | [RK3036_PD_SYS] = DOMAIN_RK3036(BIT(8), BIT(22), BIT(29), false), |
| 737 | }; | 737 | }; |
| 738 | 738 | ||
| 739 | static const struct rockchip_domain_info rk3066_pm_domains[] = { | 739 | static const struct rockchip_domain_info rk3066_pm_domains[] = { |
| 740 | [RK3066_PD_GPU] = DOMAIN(9, 9, 3, 24, 29, false), | 740 | [RK3066_PD_GPU] = DOMAIN(BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false), |
| 741 | [RK3066_PD_VIDEO] = DOMAIN(8, 8, 4, 23, 28, false), | 741 | [RK3066_PD_VIDEO] = DOMAIN(BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false), |
| 742 | [RK3066_PD_VIO] = DOMAIN(7, 7, 5, 22, 27, false), | 742 | [RK3066_PD_VIO] = DOMAIN(BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false), |
| 743 | [RK3066_PD_PERI] = DOMAIN(6, 6, 2, 25, 30, false), | 743 | [RK3066_PD_PERI] = DOMAIN(BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false), |
| 744 | [RK3066_PD_CPU] = DOMAIN(-1, 5, 1, 26, 31, false), | 744 | [RK3066_PD_CPU] = DOMAIN(0, BIT(5), BIT(1), BIT(26), BIT(31), false), |
| 745 | }; | 745 | }; |
| 746 | 746 | ||
| 747 | static const struct rockchip_domain_info rk3128_pm_domains[] = { | 747 | static const struct rockchip_domain_info rk3128_pm_domains[] = { |
| 748 | [RK3128_PD_CORE] = DOMAIN_RK3288(0, 0, 4, false), | 748 | [RK3128_PD_CORE] = DOMAIN_RK3288(BIT(0), BIT(0), BIT(4), false), |
| 749 | [RK3128_PD_MSCH] = DOMAIN_RK3288(-1, -1, 6, true), | 749 | [RK3128_PD_MSCH] = DOMAIN_RK3288(0, 0, BIT(6), true), |
| 750 | [RK3128_PD_VIO] = DOMAIN_RK3288(3, 3, 2, false), | 750 | [RK3128_PD_VIO] = DOMAIN_RK3288(BIT(3), BIT(3), BIT(2), false), |
| 751 | [RK3128_PD_VIDEO] = DOMAIN_RK3288(2, 2, 1, false), | 751 | [RK3128_PD_VIDEO] = DOMAIN_RK3288(BIT(2), BIT(2), BIT(1), false), |
| 752 | [RK3128_PD_GPU] = DOMAIN_RK3288(1, 1, 3, false), | 752 | [RK3128_PD_GPU] = DOMAIN_RK3288(BIT(1), BIT(1), BIT(3), false), |
| 753 | }; | 753 | }; |
| 754 | 754 | ||
| 755 | static const struct rockchip_domain_info rk3188_pm_domains[] = { | 755 | static const struct rockchip_domain_info rk3188_pm_domains[] = { |
| 756 | [RK3188_PD_GPU] = DOMAIN(9, 9, 3, 24, 29, false), | 756 | [RK3188_PD_GPU] = DOMAIN(BIT(9), BIT(9), BIT(3), BIT(24), BIT(29), false), |
| 757 | [RK3188_PD_VIDEO] = DOMAIN(8, 8, 4, 23, 28, false), | 757 | [RK3188_PD_VIDEO] = DOMAIN(BIT(8), BIT(8), BIT(4), BIT(23), BIT(28), false), |
| 758 | [RK3188_PD_VIO] = DOMAIN(7, 7, 5, 22, 27, false), | 758 | [RK3188_PD_VIO] = DOMAIN(BIT(7), BIT(7), BIT(5), BIT(22), BIT(27), false), |
| 759 | [RK3188_PD_PERI] = DOMAIN(6, 6, 2, 25, 30, false), | 759 | [RK3188_PD_PERI] = DOMAIN(BIT(6), BIT(6), BIT(2), BIT(25), BIT(30), false), |
| 760 | [RK3188_PD_CPU] = DOMAIN(5, 5, 1, 26, 31, false), | 760 | [RK3188_PD_CPU] = DOMAIN(BIT(5), BIT(5), BIT(1), BIT(26), BIT(31), false), |
| 761 | }; | 761 | }; |
| 762 | 762 | ||
| 763 | static const struct rockchip_domain_info rk3228_pm_domains[] = { | 763 | static const struct rockchip_domain_info rk3228_pm_domains[] = { |
| 764 | [RK3228_PD_CORE] = DOMAIN_RK3036(0, 0, 16, true), | 764 | [RK3228_PD_CORE] = DOMAIN_RK3036(BIT(0), BIT(0), BIT(16), true), |
| 765 | [RK3228_PD_MSCH] = DOMAIN_RK3036(1, 1, 17, true), | 765 | [RK3228_PD_MSCH] = DOMAIN_RK3036(BIT(1), BIT(1), BIT(17), true), |
| 766 | [RK3228_PD_BUS] = DOMAIN_RK3036(2, 2, 18, true), | 766 | [RK3228_PD_BUS] = DOMAIN_RK3036(BIT(2), BIT(2), BIT(18), true), |
| 767 | [RK3228_PD_SYS] = DOMAIN_RK3036(3, 3, 19, true), | 767 | [RK3228_PD_SYS] = DOMAIN_RK3036(BIT(3), BIT(3), BIT(19), true), |
| 768 | [RK3228_PD_VIO] = DOMAIN_RK3036(4, 4, 20, false), | 768 | [RK3228_PD_VIO] = DOMAIN_RK3036(BIT(4), BIT(4), BIT(20), false), |
| 769 | [RK3228_PD_VOP] = DOMAIN_RK3036(5, 5, 21, false), | 769 | [RK3228_PD_VOP] = DOMAIN_RK3036(BIT(5), BIT(5), BIT(21), false), |
| 770 | [RK3228_PD_VPU] = DOMAIN_RK3036(6, 6, 22, false), | 770 | [RK3228_PD_VPU] = DOMAIN_RK3036(BIT(6), BIT(6), BIT(22), false), |
| 771 | [RK3228_PD_RKVDEC] = DOMAIN_RK3036(7, 7, 23, false), | 771 | [RK3228_PD_RKVDEC] = DOMAIN_RK3036(BIT(7), BIT(7), BIT(23), false), |
| 772 | [RK3228_PD_GPU] = DOMAIN_RK3036(8, 8, 24, false), | 772 | [RK3228_PD_GPU] = DOMAIN_RK3036(BIT(8), BIT(8), BIT(24), false), |
| 773 | [RK3228_PD_PERI] = DOMAIN_RK3036(9, 9, 25, true), | 773 | [RK3228_PD_PERI] = DOMAIN_RK3036(BIT(9), BIT(9), BIT(25), true), |
| 774 | [RK3228_PD_GMAC] = DOMAIN_RK3036(10, 10, 26, false), | 774 | [RK3228_PD_GMAC] = DOMAIN_RK3036(BIT(10), BIT(10), BIT(26), false), |
| 775 | }; | 775 | }; |
| 776 | 776 | ||
| 777 | static const struct rockchip_domain_info rk3288_pm_domains[] = { | 777 | static const struct rockchip_domain_info rk3288_pm_domains[] = { |
| 778 | [RK3288_PD_VIO] = DOMAIN_RK3288(7, 7, 4, false), | 778 | [RK3288_PD_VIO] = DOMAIN_RK3288(BIT(7), BIT(7), BIT(4), false), |
| 779 | [RK3288_PD_HEVC] = DOMAIN_RK3288(14, 10, 9, false), | 779 | [RK3288_PD_HEVC] = DOMAIN_RK3288(BIT(14), BIT(10), BIT(9), false), |
| 780 | [RK3288_PD_VIDEO] = DOMAIN_RK3288(8, 8, 3, false), | 780 | [RK3288_PD_VIDEO] = DOMAIN_RK3288(BIT(8), BIT(8), BIT(3), false), |
| 781 | [RK3288_PD_GPU] = DOMAIN_RK3288(9, 9, 2, false), | 781 | [RK3288_PD_GPU] = DOMAIN_RK3288(BIT(9), BIT(9), BIT(2), false), |
| 782 | }; | 782 | }; |
| 783 | 783 | ||
| 784 | static const struct rockchip_domain_info rk3328_pm_domains[] = { | 784 | static const struct rockchip_domain_info rk3328_pm_domains[] = { |
| 785 | [RK3328_PD_CORE] = DOMAIN_RK3328(-1, 0, 0, false), | 785 | [RK3328_PD_CORE] = DOMAIN_RK3328(0, BIT(0), BIT(0), false), |
| 786 | [RK3328_PD_GPU] = DOMAIN_RK3328(-1, 1, 1, false), | 786 | [RK3328_PD_GPU] = DOMAIN_RK3328(0, BIT(1), BIT(1), false), |
| 787 | [RK3328_PD_BUS] = DOMAIN_RK3328(-1, 2, 2, true), | 787 | [RK3328_PD_BUS] = DOMAIN_RK3328(0, BIT(2), BIT(2), true), |
| 788 | [RK3328_PD_MSCH] = DOMAIN_RK3328(-1, 3, 3, true), | 788 | [RK3328_PD_MSCH] = DOMAIN_RK3328(0, BIT(3), BIT(3), true), |
| 789 | [RK3328_PD_PERI] = DOMAIN_RK3328(-1, 4, 4, true), | 789 | [RK3328_PD_PERI] = DOMAIN_RK3328(0, BIT(4), BIT(4), true), |
| 790 | [RK3328_PD_VIDEO] = DOMAIN_RK3328(-1, 5, 5, false), | 790 | [RK3328_PD_VIDEO] = DOMAIN_RK3328(0, BIT(5), BIT(5), false), |
| 791 | [RK3328_PD_HEVC] = DOMAIN_RK3328(-1, 6, 6, false), | 791 | [RK3328_PD_HEVC] = DOMAIN_RK3328(0, BIT(6), BIT(6), false), |
| 792 | [RK3328_PD_VIO] = DOMAIN_RK3328(-1, 8, 8, false), | 792 | [RK3328_PD_VIO] = DOMAIN_RK3328(0, BIT(8), BIT(8), false), |
| 793 | [RK3328_PD_VPU] = DOMAIN_RK3328(-1, 9, 9, false), | 793 | [RK3328_PD_VPU] = DOMAIN_RK3328(0, BIT(9), BIT(9), false), |
| 794 | }; | 794 | }; |
| 795 | 795 | ||
| 796 | static const struct rockchip_domain_info rk3366_pm_domains[] = { | 796 | static const struct rockchip_domain_info rk3366_pm_domains[] = { |
| 797 | [RK3366_PD_PERI] = DOMAIN_RK3368(10, 10, 6, true), | 797 | [RK3366_PD_PERI] = DOMAIN_RK3368(BIT(10), BIT(10), BIT(6), true), |
| 798 | [RK3366_PD_VIO] = DOMAIN_RK3368(14, 14, 8, false), | 798 | [RK3366_PD_VIO] = DOMAIN_RK3368(BIT(14), BIT(14), BIT(8), false), |
| 799 | [RK3366_PD_VIDEO] = DOMAIN_RK3368(13, 13, 7, false), | 799 | [RK3366_PD_VIDEO] = DOMAIN_RK3368(BIT(13), BIT(13), BIT(7), false), |
| 800 | [RK3366_PD_RKVDEC] = DOMAIN_RK3368(11, 11, 7, false), | 800 | [RK3366_PD_RKVDEC] = DOMAIN_RK3368(BIT(11), BIT(11), BIT(7), false), |
| 801 | [RK3366_PD_WIFIBT] = DOMAIN_RK3368(8, 8, 9, false), | 801 | [RK3366_PD_WIFIBT] = DOMAIN_RK3368(BIT(8), BIT(8), BIT(9), false), |
| 802 | [RK3366_PD_VPU] = DOMAIN_RK3368(12, 12, 7, false), | 802 | [RK3366_PD_VPU] = DOMAIN_RK3368(BIT(12), BIT(12), BIT(7), false), |
| 803 | [RK3366_PD_GPU] = DOMAIN_RK3368(15, 15, 2, false), | 803 | [RK3366_PD_GPU] = DOMAIN_RK3368(BIT(15), BIT(15), BIT(2), false), |
| 804 | }; | 804 | }; |
| 805 | 805 | ||
| 806 | static const struct rockchip_domain_info rk3368_pm_domains[] = { | 806 | static const struct rockchip_domain_info rk3368_pm_domains[] = { |
| 807 | [RK3368_PD_PERI] = DOMAIN_RK3368(13, 12, 6, true), | 807 | [RK3368_PD_PERI] = DOMAIN_RK3368(BIT(13), BIT(12), BIT(6), true), |
| 808 | [RK3368_PD_VIO] = DOMAIN_RK3368(15, 14, 8, false), | 808 | [RK3368_PD_VIO] = DOMAIN_RK3368(BIT(15), BIT(14), BIT(8), false), |
| 809 | [RK3368_PD_VIDEO] = DOMAIN_RK3368(14, 13, 7, false), | 809 | [RK3368_PD_VIDEO] = DOMAIN_RK3368(BIT(14), BIT(13), BIT(7), false), |
| 810 | [RK3368_PD_GPU_0] = DOMAIN_RK3368(16, 15, 2, false), | 810 | [RK3368_PD_GPU_0] = DOMAIN_RK3368(BIT(16), BIT(15), BIT(2), false), |
| 811 | [RK3368_PD_GPU_1] = DOMAIN_RK3368(17, 16, 2, false), | 811 | [RK3368_PD_GPU_1] = DOMAIN_RK3368(BIT(17), BIT(16), BIT(2), false), |
| 812 | }; | 812 | }; |
| 813 | 813 | ||
| 814 | static const struct rockchip_domain_info rk3399_pm_domains[] = { | 814 | static const struct rockchip_domain_info rk3399_pm_domains[] = { |
| 815 | [RK3399_PD_TCPD0] = DOMAIN_RK3399(8, 8, -1, false), | 815 | [RK3399_PD_TCPD0] = DOMAIN_RK3399(BIT(8), BIT(8), 0, false), |
| 816 | [RK3399_PD_TCPD1] = DOMAIN_RK3399(9, 9, -1, false), | 816 | [RK3399_PD_TCPD1] = DOMAIN_RK3399(BIT(9), BIT(9), 0, false), |
| 817 | [RK3399_PD_CCI] = DOMAIN_RK3399(10, 10, -1, true), | 817 | [RK3399_PD_CCI] = DOMAIN_RK3399(BIT(10), BIT(10), 0, true), |
| 818 | [RK3399_PD_CCI0] = DOMAIN_RK3399(-1, -1, 15, true), | 818 | [RK3399_PD_CCI0] = DOMAIN_RK3399(0, 0, BIT(15), true), |
| 819 | [RK3399_PD_CCI1] = DOMAIN_RK3399(-1, -1, 16, true), | 819 | [RK3399_PD_CCI1] = DOMAIN_RK3399(0, 0, BIT(16), true), |
| 820 | [RK3399_PD_PERILP] = DOMAIN_RK3399(11, 11, 1, true), | 820 | [RK3399_PD_PERILP] = DOMAIN_RK3399(BIT(11), BIT(11), BIT(1), true), |
| 821 | [RK3399_PD_PERIHP] = DOMAIN_RK3399(12, 12, 2, true), | 821 | [RK3399_PD_PERIHP] = DOMAIN_RK3399(BIT(12), BIT(12), BIT(2), true), |
| 822 | [RK3399_PD_CENTER] = DOMAIN_RK3399(13, 13, 14, true), | 822 | [RK3399_PD_CENTER] = DOMAIN_RK3399(BIT(13), BIT(13), BIT(14), true), |
| 823 | [RK3399_PD_VIO] = DOMAIN_RK3399(14, 14, 17, false), | 823 | [RK3399_PD_VIO] = DOMAIN_RK3399(BIT(14), BIT(14), BIT(17), false), |
| 824 | [RK3399_PD_GPU] = DOMAIN_RK3399(15, 15, 0, false), | 824 | [RK3399_PD_GPU] = DOMAIN_RK3399(BIT(15), BIT(15), BIT(0), false), |
| 825 | [RK3399_PD_VCODEC] = DOMAIN_RK3399(16, 16, 3, false), | 825 | [RK3399_PD_VCODEC] = DOMAIN_RK3399(BIT(16), BIT(16), BIT(3), false), |
| 826 | [RK3399_PD_VDU] = DOMAIN_RK3399(17, 17, 4, false), | 826 | [RK3399_PD_VDU] = DOMAIN_RK3399(BIT(17), BIT(17), BIT(4), false), |
| 827 | [RK3399_PD_RGA] = DOMAIN_RK3399(18, 18, 5, false), | 827 | [RK3399_PD_RGA] = DOMAIN_RK3399(BIT(18), BIT(18), BIT(5), false), |
| 828 | [RK3399_PD_IEP] = DOMAIN_RK3399(19, 19, 6, false), | 828 | [RK3399_PD_IEP] = DOMAIN_RK3399(BIT(19), BIT(19), BIT(6), false), |
| 829 | [RK3399_PD_VO] = DOMAIN_RK3399(20, 20, -1, false), | 829 | [RK3399_PD_VO] = DOMAIN_RK3399(BIT(20), BIT(20), 0, false), |
| 830 | [RK3399_PD_VOPB] = DOMAIN_RK3399(-1, -1, 7, false), | 830 | [RK3399_PD_VOPB] = DOMAIN_RK3399(0, 0, BIT(7), false), |
| 831 | [RK3399_PD_VOPL] = DOMAIN_RK3399(-1, -1, 8, false), | 831 | [RK3399_PD_VOPL] = DOMAIN_RK3399(0, 0, BIT(8), false), |
| 832 | [RK3399_PD_ISP0] = DOMAIN_RK3399(22, 22, 9, false), | 832 | [RK3399_PD_ISP0] = DOMAIN_RK3399(BIT(22), BIT(22), BIT(9), false), |
| 833 | [RK3399_PD_ISP1] = DOMAIN_RK3399(23, 23, 10, false), | 833 | [RK3399_PD_ISP1] = DOMAIN_RK3399(BIT(23), BIT(23), BIT(10), false), |
| 834 | [RK3399_PD_HDCP] = DOMAIN_RK3399(24, 24, 11, false), | 834 | [RK3399_PD_HDCP] = DOMAIN_RK3399(BIT(24), BIT(24), BIT(11), false), |
| 835 | [RK3399_PD_GMAC] = DOMAIN_RK3399(25, 25, 23, true), | 835 | [RK3399_PD_GMAC] = DOMAIN_RK3399(BIT(25), BIT(25), BIT(23), true), |
| 836 | [RK3399_PD_EMMC] = DOMAIN_RK3399(26, 26, 24, true), | 836 | [RK3399_PD_EMMC] = DOMAIN_RK3399(BIT(26), BIT(26), BIT(24), true), |
| 837 | [RK3399_PD_USB3] = DOMAIN_RK3399(27, 27, 12, true), | 837 | [RK3399_PD_USB3] = DOMAIN_RK3399(BIT(27), BIT(27), BIT(12), true), |
| 838 | [RK3399_PD_EDP] = DOMAIN_RK3399(28, 28, 22, false), | 838 | [RK3399_PD_EDP] = DOMAIN_RK3399(BIT(28), BIT(28), BIT(22), false), |
| 839 | [RK3399_PD_GIC] = DOMAIN_RK3399(29, 29, 27, true), | 839 | [RK3399_PD_GIC] = DOMAIN_RK3399(BIT(29), BIT(29), BIT(27), true), |
| 840 | [RK3399_PD_SD] = DOMAIN_RK3399(30, 30, 28, true), | 840 | [RK3399_PD_SD] = DOMAIN_RK3399(BIT(30), BIT(30), BIT(28), true), |
| 841 | [RK3399_PD_SDIOAUDIO] = DOMAIN_RK3399(31, 31, 29, true), | 841 | [RK3399_PD_SDIOAUDIO] = DOMAIN_RK3399(BIT(31), BIT(31), BIT(29), true), |
| 842 | }; | 842 | }; |
| 843 | 843 | ||
| 844 | static const struct rockchip_pmu_info px30_pmu = { | 844 | static const struct rockchip_pmu_info px30_pmu = { |
| @@ -109,6 +109,7 @@ config ARCH_TEGRA_186_SOC · 108 unmodified lines | |||
| 109 | config ARCH_TEGRA_194_SOC | 109 | config ARCH_TEGRA_194_SOC |
| 110 | bool "NVIDIA Tegra194 SoC" | 110 | bool "NVIDIA Tegra194 SoC" |
| 111 | select MAILBOX | 111 | select MAILBOX |
| 112 | select PINCTRL_TEGRA194 | ||
| 112 | select TEGRA_BPMP | 113 | select TEGRA_BPMP |
| 113 | select TEGRA_HSP_MBOX | 114 | select TEGRA_HSP_MBOX |
| 114 | select TEGRA_IVC | 115 | select TEGRA_IVC |
| @@ -133,8 +133,10 @@ static int tegra_fuse_probe(struct platform_device *pdev) · 132 unmodified lines | |||
| 133 | 133 | ||
| 134 | fuse->clk = devm_clk_get(&pdev->dev, "fuse"); | 134 | fuse->clk = devm_clk_get(&pdev->dev, "fuse"); |
| 135 | if (IS_ERR(fuse->clk)) { | 135 | if (IS_ERR(fuse->clk)) { |
| 136 | dev_err(&pdev->dev, "failed to get FUSE clock: %ld", | 136 | if (PTR_ERR(fuse->clk) != -EPROBE_DEFER) |
| 137 | PTR_ERR(fuse->clk)); | 137 | dev_err(&pdev->dev, "failed to get FUSE clock: %ld", |
| 138 | PTR_ERR(fuse->clk)); | ||
| 139 | |||
| 138 | fuse->base = base; | 140 | fuse->base = base; |
| 139 | return PTR_ERR(fuse->clk); | 141 | return PTR_ERR(fuse->clk); |
| 140 | } | 142 | } |
| @@ -232,6 +232,11 @@ struct tegra_pmc_soc { · 231 unmodified lines | |||
| 232 | const char * const *reset_levels; | 232 | const char * const *reset_levels; |
| 233 | unsigned int num_reset_levels; | 233 | unsigned int num_reset_levels; |
| 234 | 234 | ||
| 235 | /* | ||
| 236 | * These describe events that can wake the system from sleep (i.e. | ||
| 237 | * LP0 or SC7). Wakeup from other sleep states (such as LP1 or LP2) | ||
| 238 | * are dealt with in the LIC. | ||
| 239 | */ | ||
| 235 | const struct tegra_wake_event *wake_events; | 240 | const struct tegra_wake_event *wake_events; |
| 236 | unsigned int num_wake_events; | 241 | unsigned int num_wake_events; |
| 237 | }; | 242 | }; |
| @@ -1855,6 +1860,9 @@ static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq, · 1617 unmodified lines | |||
| 1855 | unsigned int i; | 1860 | unsigned int i; |
| 1856 | int err = 0; | 1861 | int err = 0; |
| 1857 | 1862 | ||
| 1863 | if (WARN_ON(num_irqs > 1)) | ||
| 1864 | return -EINVAL; | ||
| 1865 | |||
| 1858 | for (i = 0; i < soc->num_wake_events; i++) { | 1866 | for (i = 0; i < soc->num_wake_events; i++) { |
| 1859 | const struct tegra_wake_event *event = &soc->wake_events[i]; | 1867 | const struct tegra_wake_event *event = &soc->wake_events[i]; |
| 1860 | 1868 | ||
| @@ -1895,6 +1903,11 @@ static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq, · 34 unmodified lines | |||
| 1895 | } | 1903 | } |
| 1896 | } | 1904 | } |
| 1897 | 1905 | ||
| 1906 | /* | ||
| 1907 | * For interrupts that don't have associated wake events, assign a | ||
| 1908 | * dummy hardware IRQ number. This is used in the ->irq_set_type() | ||
| 1909 | * and ->irq_set_wake() callbacks to return early for these IRQs. | ||
| 1910 | */ | ||
| 1898 | if (i == soc->num_wake_events) | 1911 | if (i == soc->num_wake_events) |
| 1899 | err = irq_domain_set_hwirq_and_chip(domain, virq, ULONG_MAX, | 1912 | err = irq_domain_set_hwirq_and_chip(domain, virq, ULONG_MAX, |
| 1900 | &pmc->irq, pmc); | 1913 | &pmc->irq, pmc); |
| @@ -1913,6 +1926,10 @@ static int tegra_pmc_irq_set_wake(struct irq_data *data, unsigned int on) · 12 unmodified lines | |||
| 1913 | unsigned int offset, bit; | 1926 | unsigned int offset, bit; |
| 1914 | u32 value; | 1927 | u32 value; |
| 1915 | 1928 | ||
| 1929 | /* nothing to do if there's no associated wake event */ | ||
| 1930 | if (WARN_ON(data->hwirq == ULONG_MAX)) | ||
| 1931 | return 0; | ||
| 1932 | |||
| 1916 | offset = data->hwirq / 32; | 1933 | offset = data->hwirq / 32; |
| 1917 | bit = data->hwirq % 32; | 1934 | bit = data->hwirq % 32; |
| 1918 | 1935 | ||
| @@ -1940,6 +1957,7 @@ static int tegra_pmc_irq_set_type(struct irq_data *data, unsigned int type) · 21 unmodified lines | |||
| 1940 | struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data); | 1957 | struct tegra_pmc *pmc = irq_data_get_irq_chip_data(data); |
| 1941 | u32 value; | 1958 | u32 value; |
| 1942 | 1959 | ||
| 1960 | /* nothing to do if there's no associated wake event */ | ||
| 1943 | if (data->hwirq == ULONG_MAX) | 1961 | if (data->hwirq == ULONG_MAX) |
| 1944 | return 0; | 1962 | return 0; |
| 1945 | 1963 | ||
| @@ -0,0 +1,14 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0 */ | ||
| 2 | /* Copyright (c) 2018, Linaro Ltd. */ | ||
| 3 | |||
| 4 | #ifndef __DT_BINDINGS_POWER_QCOM_AOSS_QMP_H | ||
| 5 | #define __DT_BINDINGS_POWER_QCOM_AOSS_QMP_H | ||
| 6 | |||
| 7 | #define AOSS_QMP_LS_CDSP 0 | ||
| 8 | #define AOSS_QMP_LS_LPASS 1 | ||
| 9 | #define AOSS_QMP_LS_MODEM 2 | ||
| 10 | #define AOSS_QMP_LS_SLPI 3 | ||
| 11 | #define AOSS_QMP_LS_SPSS 4 | ||
| 12 | #define AOSS_QMP_LS_VENUS 5 | ||
| 13 | |||
| 14 | #endif | ||
| @@ -36,4 +36,38 @@ · 35 unmodified lines | |||
| 36 | #define MSM8996_VDDSSCX 5 | 36 | #define MSM8996_VDDSSCX 5 |
| 37 | #define MSM8996_VDDSSCX_VFC 6 | 37 | #define MSM8996_VDDSSCX_VFC 6 |
| 38 | 38 | ||
| 39 | /* MSM8998 Power Domain Indexes */ | ||
| 40 | #define MSM8998_VDDCX 0 | ||
| 41 | #define MSM8998_VDDCX_AO 1 | ||
| 42 | #define MSM8998_VDDCX_VFL 2 | ||
| 43 | #define MSM8998_VDDMX 3 | ||
| 44 | #define MSM8998_VDDMX_AO 4 | ||
| 45 | #define MSM8998_VDDMX_VFL 5 | ||
| 46 | #define MSM8998_SSCCX 6 | ||
| 47 | #define MSM8998_SSCCX_VFL 7 | ||
| 48 | #define MSM8998_SSCMX 8 | ||
| 49 | #define MSM8998_SSCMX_VFL 9 | ||
| 50 | |||
| 51 | /* QCS404 Power Domains */ | ||
| 52 | #define QCS404_VDDMX 0 | ||
| 53 | #define QCS404_VDDMX_AO 1 | ||
| 54 | #define QCS404_VDDMX_VFL 2 | ||
| 55 | #define QCS404_LPICX 3 | ||
| 56 | #define QCS404_LPICX_VFL 4 | ||
| 57 | #define QCS404_LPIMX 5 | ||
| 58 | #define QCS404_LPIMX_VFL 6 | ||
| 59 | |||
| 60 | /* RPM SMD Power Domain performance levels */ | ||
| 61 | #define RPM_SMD_LEVEL_RETENTION 16 | ||
| 62 | #define RPM_SMD_LEVEL_RETENTION_PLUS 32 | ||
| 63 | #define RPM_SMD_LEVEL_MIN_SVS 48 | ||
| 64 | #define RPM_SMD_LEVEL_LOW_SVS 64 | ||
| 65 | #define RPM_SMD_LEVEL_SVS 128 | ||
| 66 | #define RPM_SMD_LEVEL_SVS_PLUS 192 | ||
| 67 | #define RPM_SMD_LEVEL_NOM 256 | ||
| 68 | #define RPM_SMD_LEVEL_NOM_PLUS 320 | ||
| 69 | #define RPM_SMD_LEVEL_TURBO 384 | ||
| 70 | #define RPM_SMD_LEVEL_TURBO_NO_CPR 416 | ||
| 71 | #define RPM_SMD_LEVEL_BINNING 512 | ||
| 72 | |||
| 39 | #endif | 73 | #endif |
| @@ -0,0 +1,51 @@ | |||
| 1 | /* SPDX-License-Identifier: GPL-2.0+ */ | ||
| 2 | /* | ||
| 3 | * Copyright (c) 2018 Bitmain Ltd. | ||
| 4 | * Copyright (c) 2019 Linaro Ltd. | ||
| 5 | */ | ||
| 6 | |||
| 7 | #ifndef _DT_BINDINGS_BM1880_RESET_H | ||
| 8 | #define _DT_BINDINGS_BM1880_RESET_H | ||
| 9 | |||
| 10 | #define BM1880_RST_MAIN_AP 0 | ||
| 11 | #define BM1880_RST_SECOND_AP 1 | ||
| 12 | #define BM1880_RST_DDR 2 | ||
| 13 | #define BM1880_RST_VIDEO 3 | ||
| 14 | #define BM1880_RST_JPEG 4 | ||
| 15 | #define BM1880_RST_VPP 5 | ||
| 16 | #define BM1880_RST_GDMA 6 | ||
| 17 | #define BM1880_RST_AXI_SRAM 7 | ||
| 18 | #define BM1880_RST_TPU 8 | ||
| 19 | #define BM1880_RST_USB 9 | ||
| 20 | #define BM1880_RST_ETH0 10 | ||
| 21 | #define BM1880_RST_ETH1 11 | ||
| 22 | #define BM1880_RST_NAND 12 | ||
| 23 | #define BM1880_RST_EMMC 13 | ||
| 24 | #define BM1880_RST_SD 14 | ||
| 25 | #define BM1880_RST_SDMA 15 | ||
| 26 | #define BM1880_RST_I2S0 16 | ||
| 27 | #define BM1880_RST_I2S1 17 | ||
| 28 | #define BM1880_RST_UART0_1_CLK 18 | ||
| 29 | #define BM1880_RST_UART0_1_ACLK 19 | ||
| 30 | #define BM1880_RST_UART2_3_CLK 20 | ||
| 31 | #define BM1880_RST_UART2_3_ACLK 21 | ||
| 32 | #define BM1880_RST_MINER 22 | ||
| 33 | #define BM1880_RST_I2C0 23 | ||
| 34 | #define BM1880_RST_I2C1 24 | ||
| 35 | #define BM1880_RST_I2C2 25 | ||
| 36 | #define BM1880_RST_I2C3 26 | ||
| 37 | #define BM1880_RST_I2C4 27 | ||
| 38 | #define BM1880_RST_PWM0 28 | ||
| 39 | #define BM1880_RST_PWM1 29 | ||
| 40 | #define BM1880_RST_PWM2 30 | ||
| 41 | #define BM1880_RST_PWM3 31 | ||
| 42 | #define BM1880_RST_SPI 32 | ||
| 43 | #define BM1880_RST_GPIO0 33 | ||
| 44 | #define BM1880_RST_GPIO1 34 | ||
| 45 | #define BM1880_RST_GPIO2 35 | ||
| 46 | #define BM1880_RST_EFUSE 36 | ||
| 47 | #define BM1880_RST_WDT 37 | ||
| 48 | #define BM1880_RST_AHB_ROM 38 | ||
| 49 | #define BM1880_RST_SPIC 39 | ||
| 50 | |||
| 51 | #endif /* _DT_BINDINGS_BM1880_RESET_H */ | ||
| @@ -19,6 +19,7 @@ enum ti_sysc_module_type { · 18 unmodified lines | |||
| 19 | 19 | ||
| 20 | struct ti_sysc_cookie { | 20 | struct ti_sysc_cookie { |
| 21 | void *data; | 21 | void *data; |
| 22 | void *clkdm; | ||
| 22 | }; | 23 | }; |
| 23 | 24 | ||
| 24 | /** | 25 | /** |
| @@ -46,6 +47,10 @@ struct sysc_regbits { · 21 unmodified lines | |||
| 46 | s8 emufree_shift; | 47 | s8 emufree_shift; |
| 47 | }; | 48 | }; |
| 48 | 49 | ||
| 50 | #define SYSC_MODULE_QUIRK_HDQ1W BIT(17) | ||
| 51 | #define SYSC_MODULE_QUIRK_I2C BIT(16) | ||
| 52 | #define SYSC_MODULE_QUIRK_WDT BIT(15) | ||
| 53 | #define SYSS_QUIRK_RESETDONE_INVERTED BIT(14) | ||
| 49 | #define SYSC_QUIRK_SWSUP_MSTANDBY BIT(13) | 54 | #define SYSC_QUIRK_SWSUP_MSTANDBY BIT(13) |
| 50 | #define SYSC_QUIRK_SWSUP_SIDLE_ACT BIT(12) | 55 | #define SYSC_QUIRK_SWSUP_SIDLE_ACT BIT(12) |
| 51 | #define SYSC_QUIRK_SWSUP_SIDLE BIT(11) | 56 | #define SYSC_QUIRK_SWSUP_SIDLE BIT(11) |
| @@ -125,9 +130,16 @@ struct ti_sysc_module_data { · 73 unmodified lines | |||
| 125 | }; | 130 | }; |
| 126 | 131 | ||
| 127 | struct device; | 132 | struct device; |
| 133 | struct clk; | ||
| 128 | 134 | ||
| 129 | struct ti_sysc_platform_data { | 135 | struct ti_sysc_platform_data { |
| 130 | struct of_dev_auxdata *auxdata; | 136 | struct of_dev_auxdata *auxdata; |
| 137 | int (*init_clockdomain)(struct device *dev, struct clk *fck, | ||
| 138 | struct clk *ick, struct ti_sysc_cookie *cookie); | ||
| 139 | void (*clkdm_deny_idle)(struct device *dev, | ||
| 140 | const struct ti_sysc_cookie *cookie); | ||
| 141 | void (*clkdm_allow_idle)(struct device *dev, | ||
| 142 | const struct ti_sysc_cookie *cookie); | ||
| 131 | int (*init_module)(struct device *dev, | 143 | int (*init_module)(struct device *dev, |
| 132 | const struct ti_sysc_module_data *data, | 144 | const struct ti_sysc_module_data *data, |
| 133 | struct ti_sysc_cookie *cookie); | 145 | struct ti_sysc_cookie *cookie); |
| @@ -144,6 +144,7 @@ struct scmi_power_ops { · 143 unmodified lines | |||
| 144 | struct scmi_sensor_info { | 144 | struct scmi_sensor_info { |
| 145 | u32 id; | 145 | u32 id; |
| 146 | u8 type; | 146 | u8 type; |
| 147 | s8 scale; | ||
| 147 | char name[SCMI_MAX_STR_SIZE]; | 148 | char name[SCMI_MAX_STR_SIZE]; |
| 148 | }; | 149 | }; |
| 149 | 150 | ||
| @@ -241,12 +241,254 @@ struct ti_sci_rm_irq_ops { · 240 unmodified lines | |||
| 241 | u16 global_event, u8 vint_status_bit); | 241 | u16 global_event, u8 vint_status_bit); |
| 242 | }; | 242 | }; |
| 243 | 243 | ||
| 244 | /* RA config.addr_lo parameter is valid for RM ring configure TI_SCI message */ | ||
| 245 | #define TI_SCI_MSG_VALUE_RM_RING_ADDR_LO_VALID BIT(0) | ||
| 246 | /* RA config.addr_hi parameter is valid for RM ring configure TI_SCI message */ | ||
| 247 | #define TI_SCI_MSG_VALUE_RM_RING_ADDR_HI_VALID BIT(1) | ||
| 248 | /* RA config.count parameter is valid for RM ring configure TI_SCI message */ | ||
| 249 | #define TI_SCI_MSG_VALUE_RM_RING_COUNT_VALID BIT(2) | ||
| 250 | /* RA config.mode parameter is valid for RM ring configure TI_SCI message */ | ||
| 251 | #define TI_SCI_MSG_VALUE_RM_RING_MODE_VALID BIT(3) | ||
| 252 | /* RA config.size parameter is valid for RM ring configure TI_SCI message */ | ||
| 253 | #define TI_SCI_MSG_VALUE_RM_RING_SIZE_VALID BIT(4) | ||
| 254 | /* RA config.order_id parameter is valid for RM ring configure TISCI message */ | ||
| 255 | #define TI_SCI_MSG_VALUE_RM_RING_ORDER_ID_VALID BIT(5) | ||
| 256 | |||
| 257 | #define TI_SCI_MSG_VALUE_RM_ALL_NO_ORDER \ | ||
| 258 | (TI_SCI_MSG_VALUE_RM_RING_ADDR_LO_VALID | \ | ||
| 259 | TI_SCI_MSG_VALUE_RM_RING_ADDR_HI_VALID | \ | ||
| 260 | TI_SCI_MSG_VALUE_RM_RING_COUNT_VALID | \ | ||
| 261 | TI_SCI_MSG_VALUE_RM_RING_MODE_VALID | \ | ||
| 262 | TI_SCI_MSG_VALUE_RM_RING_SIZE_VALID) | ||
| 263 | |||
| 264 | /** | ||
| 265 | * struct ti_sci_rm_ringacc_ops - Ring Accelerator Management operations | ||
| 266 | * @config: configure the SoC Navigator Subsystem Ring Accelerator ring | ||
| 267 | * @get_config: get the SoC Navigator Subsystem Ring Accelerator ring | ||
| 268 | * configuration | ||
| 269 | */ | ||
| 270 | struct ti_sci_rm_ringacc_ops { | ||
| 271 | int (*config)(const struct ti_sci_handle *handle, | ||
| 272 | u32 valid_params, u16 nav_id, u16 index, | ||
| 273 | u32 addr_lo, u32 addr_hi, u32 count, u8 mode, | ||
| 274 | u8 size, u8 order_id | ||
| 275 | ); | ||
| 276 | int (*get_config)(const struct ti_sci_handle *handle, | ||
| 277 | u32 nav_id, u32 index, u8 *mode, | ||
| 278 | u32 *addr_lo, u32 *addr_hi, u32 *count, | ||
| 279 | u8 *size, u8 *order_id); | ||
| 280 | }; | ||
| 281 | |||
| 282 | /** | ||
| 283 | * struct ti_sci_rm_psil_ops - PSI-L thread operations | ||
| 284 | * @pair: pair PSI-L source thread to a destination thread. | ||
| 285 | * If the src_thread is mapped to UDMA tchan, the corresponding channel's | ||
| 286 | * TCHAN_THRD_ID register is updated. | ||
| 287 | * If the dst_thread is mapped to UDMA rchan, the corresponding channel's | ||
| 288 | * RCHAN_THRD_ID register is updated. | ||
| 289 | * @unpair: unpair PSI-L source thread from a destination thread. | ||
| 290 | * If the src_thread is mapped to UDMA tchan, the corresponding channel's | ||
| 291 | * TCHAN_THRD_ID register is cleared. | ||
| 292 | * If the dst_thread is mapped to UDMA rchan, the corresponding channel's | ||
| 293 | * RCHAN_THRD_ID register is cleared. | ||
| 294 | */ | ||
| 295 | struct ti_sci_rm_psil_ops { | ||
| 296 | int (*pair)(const struct ti_sci_handle *handle, u32 nav_id, | ||
| 297 | u32 src_thread, u32 dst_thread); | ||
| 298 | int (*unpair)(const struct ti_sci_handle *handle, u32 nav_id, | ||
| 299 | u32 src_thread, u32 dst_thread); | ||
| 300 | }; | ||
| 301 | |||
| 302 | /* UDMAP channel types */ | ||
| 303 | #define TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR 2 | ||
| 304 | #define TI_SCI_RM_UDMAP_CHAN_TYPE_PKT_PBRR_SB 3 /* RX only */ | ||
| 305 | #define TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_PBRR 10 | ||
| 306 | #define TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_PBVR 11 | ||
| 307 | #define TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBRR 12 | ||
| 308 | #define TI_SCI_RM_UDMAP_CHAN_TYPE_3RDP_BCOPY_PBVR 13 | ||
| 309 | |||
| 310 | #define TI_SCI_RM_UDMAP_RX_FLOW_DESC_HOST 0 | ||
| 311 | #define TI_SCI_RM_UDMAP_RX_FLOW_DESC_MONO 2 | ||
| 312 | |||
| 313 | #define TI_SCI_RM_UDMAP_CHAN_BURST_SIZE_64_BYTES 1 | ||
| 314 | #define TI_SCI_RM_UDMAP_CHAN_BURST_SIZE_128_BYTES 2 | ||
| 315 | #define TI_SCI_RM_UDMAP_CHAN_BURST_SIZE_256_BYTES 3 | ||
| 316 | |||
| 317 | /* UDMAP TX/RX channel valid_params common declarations */ | ||
| 318 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_PAUSE_ON_ERR_VALID BIT(0) | ||
| 319 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_ATYPE_VALID BIT(1) | ||
| 320 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_CHAN_TYPE_VALID BIT(2) | ||
| 321 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_FETCH_SIZE_VALID BIT(3) | ||
| 322 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_CQ_QNUM_VALID BIT(4) | ||
| 323 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_PRIORITY_VALID BIT(5) | ||
| 324 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_QOS_VALID BIT(6) | ||
| 325 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_ORDER_ID_VALID BIT(7) | ||
| 326 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_SCHED_PRIORITY_VALID BIT(8) | ||
| 327 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_BURST_SIZE_VALID BIT(14) | ||
| 328 | |||
| 329 | /** | ||
| 330 | * Configures a Navigator Subsystem UDMAP transmit channel | ||
| 331 | * | ||
| 332 | * Configures a Navigator Subsystem UDMAP transmit channel registers. | ||
| 333 | * See @ti_sci_msg_rm_udmap_tx_ch_cfg_req | ||
| 334 | */ | ||
| 335 | struct ti_sci_msg_rm_udmap_tx_ch_cfg { | ||
| 336 | u32 valid_params; | ||
| 337 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_FILT_EINFO_VALID BIT(9) | ||
| 338 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_FILT_PSWORDS_VALID BIT(10) | ||
| 339 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_SUPR_TDPKT_VALID BIT(11) | ||
| 340 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_CREDIT_COUNT_VALID BIT(12) | ||
| 341 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_TX_FDEPTH_VALID BIT(13) | ||
| 342 | u16 nav_id; | ||
| 343 | u16 index; | ||
| 344 | u8 tx_pause_on_err; | ||
| 345 | u8 tx_filt_einfo; | ||
| 346 | u8 tx_filt_pswords; | ||
| 347 | u8 tx_atype; | ||
| 348 | u8 tx_chan_type; | ||
| 349 | u8 tx_supr_tdpkt; | ||
| 350 | u16 tx_fetch_size; | ||
| 351 | u8 tx_credit_count; | ||
| 352 | u16 txcq_qnum; | ||
| 353 | u8 tx_priority; | ||
| 354 | u8 tx_qos; | ||
| 355 | u8 tx_orderid; | ||
| 356 | u16 fdepth; | ||
| 357 | u8 tx_sched_priority; | ||
| 358 | u8 tx_burst_size; | ||
| 359 | }; | ||
| 360 | |||
| 361 | /** | ||
| 362 | * Configures a Navigator Subsystem UDMAP receive channel | ||
| 363 | * | ||
| 364 | * Configures a Navigator Subsystem UDMAP receive channel registers. | ||
| 365 | * See @ti_sci_msg_rm_udmap_rx_ch_cfg_req | ||
| 366 | */ | ||
| 367 | struct ti_sci_msg_rm_udmap_rx_ch_cfg { | ||
| 368 | u32 valid_params; | ||
| 369 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_START_VALID BIT(9) | ||
| 370 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_FLOWID_CNT_VALID BIT(10) | ||
| 371 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_IGNORE_SHORT_VALID BIT(11) | ||
| 372 | #define TI_SCI_MSG_VALUE_RM_UDMAP_CH_RX_IGNORE_LONG_VALID BIT(12) | ||
| 373 | u16 nav_id; | ||
| 374 | u16 index; | ||
| 375 | u16 rx_fetch_size; | ||
| 376 | u16 rxcq_qnum; | ||
| 377 | u8 rx_priority; | ||
| 378 | u8 rx_qos; | ||
| 379 | u8 rx_orderid; | ||
| 380 | u8 rx_sched_priority; | ||
| 381 | u16 flowid_start; | ||
| 382 | u16 flowid_cnt; | ||
| 383 | u8 rx_pause_on_err; | ||
| 384 | u8 rx_atype; | ||
| 385 | u8 rx_chan_type; | ||
| 386 | u8 rx_ignore_short; | ||
| 387 | u8 rx_ignore_long; | ||
| 388 | u8 rx_burst_size; | ||
| 389 | }; | ||
| 390 | |||
| 391 | /** | ||
| 392 | * Configures a Navigator Subsystem UDMAP receive flow | ||
| 393 | * | ||
| 394 | * Configures a Navigator Subsystem UDMAP receive flow's registers. | ||
| 395 | * See @tis_ci_msg_rm_udmap_flow_cfg_req | ||
| 396 | */ | ||
| 397 | struct ti_sci_msg_rm_udmap_flow_cfg { | ||
| 398 | u32 valid_params; | ||
| 399 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_EINFO_PRESENT_VALID BIT(0) | ||
| 400 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_PSINFO_PRESENT_VALID BIT(1) | ||
| 401 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_ERROR_HANDLING_VALID BIT(2) | ||
| 402 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DESC_TYPE_VALID BIT(3) | ||
| 403 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SOP_OFFSET_VALID BIT(4) | ||
| 404 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_QNUM_VALID BIT(5) | ||
| 405 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_HI_VALID BIT(6) | ||
| 406 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_LO_VALID BIT(7) | ||
| 407 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_HI_VALID BIT(8) | ||
| 408 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_LO_VALID BIT(9) | ||
| 409 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_HI_SEL_VALID BIT(10) | ||
| 410 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_SRC_TAG_LO_SEL_VALID BIT(11) | ||
| 411 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_HI_SEL_VALID BIT(12) | ||
| 412 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_DEST_TAG_LO_SEL_VALID BIT(13) | ||
| 413 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ0_SZ0_QNUM_VALID BIT(14) | ||
| 414 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ1_QNUM_VALID BIT(15) | ||
| 415 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ2_QNUM_VALID BIT(16) | ||
| 416 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_FDQ3_QNUM_VALID BIT(17) | ||
| 417 | #define TI_SCI_MSG_VALUE_RM_UDMAP_FLOW_PS_LOCATION_VALID BIT(18) | ||
| 418 | u16 nav_id; | ||
| 419 | u16 flow_index; | ||
| 420 | u8 rx_einfo_present; | ||
| 421 | u8 rx_psinfo_present; | ||
| 422 | u8 rx_error_handling; | ||
| 423 | u8 rx_desc_type; | ||
| 424 | u16 rx_sop_offset; | ||
| 425 | u16 rx_dest_qnum; | ||
| 426 | u8 rx_src_tag_hi; | ||
| 427 | u8 rx_src_tag_lo; | ||
| 428 | u8 rx_dest_tag_hi; | ||
| 429 | u8 rx_dest_tag_lo; | ||
| 430 | u8 rx_src_tag_hi_sel; | ||
| 431 | u8 rx_src_tag_lo_sel; | ||
| 432 | u8 rx_dest_tag_hi_sel; | ||
| 433 | u8 rx_dest_tag_lo_sel; | ||
| 434 | u16 rx_fdq0_sz0_qnum; | ||
| 435 | u16 rx_fdq1_qnum; | ||
| 436 | u16 rx_fdq2_qnum; | ||
| 437 | u16 rx_fdq3_qnum; | ||
| 438 | u8 rx_ps_location; | ||
| 439 | }; | ||
| 440 | |||
| 441 | /** | ||
| 442 | * struct ti_sci_rm_udmap_ops - UDMA Management operations | ||
| 443 | * @tx_ch_cfg: configure SoC Navigator Subsystem UDMA transmit channel. | ||
| 444 | * @rx_ch_cfg: configure SoC Navigator Subsystem UDMA receive channel. | ||
| 445 | * @rx_flow_cfg1: configure SoC Navigator Subsystem UDMA receive flow. | ||
| 446 | */ | ||
| 447 | struct ti_sci_rm_udmap_ops { | ||
| 448 | int (*tx_ch_cfg)(const struct ti_sci_handle *handle, | ||
| 449 | const struct ti_sci_msg_rm_udmap_tx_ch_cfg *params); | ||
| 450 | int (*rx_ch_cfg)(const struct ti_sci_handle *handle, | ||
| 451 | const struct ti_sci_msg_rm_udmap_rx_ch_cfg *params); | ||
| 452 | int (*rx_flow_cfg)(const struct ti_sci_handle *handle, | ||
| 453 | const struct ti_sci_msg_rm_udmap_flow_cfg *params); | ||
| 454 | }; | ||
| 455 | |||
| 456 | /** | ||
| 457 | * struct ti_sci_proc_ops - Processor Control operations | ||
| 458 | * @request: Request to control a physical processor. The requesting host | ||
| 459 | * should be in the processor access list | ||
| 460 | * @release: Relinquish a physical processor control | ||
| 461 | * @handover: Handover a physical processor control to another host | ||
| 462 | * in the permitted list | ||
| 463 | * @set_config: Set base configuration of a processor | ||
| 464 | * @set_control: Setup limited control flags in specific cases | ||
| 465 | * @get_status: Get the state of physical processor | ||
| 466 | * | ||
| 467 | * NOTE: The following paramteres are generic in nature for all these ops, | ||
| 468 | * -handle: Pointer to TI SCI handle as retrieved by *ti_sci_get_handle | ||
| 469 | * -pid: Processor ID | ||
| 470 | * -hid: Host ID | ||
| 471 | */ | ||
| 472 | struct ti_sci_proc_ops { | ||
| 473 | int (*request)(const struct ti_sci_handle *handle, u8 pid); | ||
| 474 | int (*release)(const struct ti_sci_handle *handle, u8 pid); | ||
| 475 | int (*handover)(const struct ti_sci_handle *handle, u8 pid, u8 hid); | ||
| 476 | int (*set_config)(const struct ti_sci_handle *handle, u8 pid, | ||
| 477 | u64 boot_vector, u32 cfg_set, u32 cfg_clr); | ||
| 478 | int (*set_control)(const struct ti_sci_handle *handle, u8 pid, | ||
| 479 | u32 ctrl_set, u32 ctrl_clr); | ||
| 480 | int (*get_status)(const struct ti_sci_handle *handle, u8 pid, | ||
| 481 | u64 *boot_vector, u32 *cfg_flags, u32 *ctrl_flags, | ||
| 482 | u32 *status_flags); | ||
| 483 | }; | ||
| 484 | |||
| 244 | /** | 485 | /** |
| 245 | * struct ti_sci_ops - Function support for TI SCI | 486 | * struct ti_sci_ops - Function support for TI SCI |
| 246 | * @dev_ops: Device specific operations | 487 | * @dev_ops: Device specific operations |
| 247 | * @clk_ops: Clock specific operations | 488 | * @clk_ops: Clock specific operations |
| 248 | * @rm_core_ops: Resource management core operations. | 489 | * @rm_core_ops: Resource management core operations. |
| 249 | * @rm_irq_ops: IRQ management specific operations | 490 | * @rm_irq_ops: IRQ management specific operations |
| 491 | * @proc_ops: Processor Control specific operations | ||
| 250 | */ | 492 | */ |
| 251 | struct ti_sci_ops { | 493 | struct ti_sci_ops { |
| 252 | struct ti_sci_core_ops core_ops; | 494 | struct ti_sci_core_ops core_ops; |
| @@ -254,6 +496,10 @@ struct ti_sci_ops { · 1 unmodified line | |||
| 254 | struct ti_sci_clk_ops clk_ops; | 496 | struct ti_sci_clk_ops clk_ops; |
| 255 | struct ti_sci_rm_core_ops rm_core_ops; | 497 | struct ti_sci_rm_core_ops rm_core_ops; |
| 256 | struct ti_sci_rm_irq_ops rm_irq_ops; | 498 | struct ti_sci_rm_irq_ops rm_irq_ops; |
| 499 | struct ti_sci_rm_ringacc_ops rm_ring_ops; | ||
| 500 | struct ti_sci_rm_psil_ops rm_psil_ops; | ||
| 501 | struct ti_sci_rm_udmap_ops rm_udmap_ops; | ||
| 502 | struct ti_sci_proc_ops proc_ops; | ||
| 257 | }; | 503 | }; |
| 258 | 504 | ||
| 259 | /** | 505 | /** |
| @@ -133,5 +133,13 @@ int bman_acquire(struct bman_pool *pool, struct bm_buffer *bufs, u8 num); · 132 unmodified lines | |||
| 133 | * failed to probe or 0 if the bman driver did not probed yet. | 133 | * failed to probe or 0 if the bman driver did not probed yet. |
| 134 | */ | 134 | */ |
| 135 | int bman_is_probed(void); | 135 | int bman_is_probed(void); |
| 136 | /** | ||
| 137 | * bman_portals_probed - Check if all cpu bound bman portals are probed | ||
| 138 | * | ||
| 139 | * Returns 1 if all the required cpu bound bman portals successfully probed, | ||
| 140 | * -1 if probe errors appeared or 0 if the bman portals did not yet finished | ||
| 141 | * probing. | ||
| 142 | */ | ||
| 143 | int bman_portals_probed(void); | ||
| 136 | 144 | ||
| 137 | #endif /* __FSL_BMAN_H */ | 145 | #endif /* __FSL_BMAN_H */ |
| @@ -1194,6 +1194,15 @@ int qman_release_cgrid(u32 id); · 1193 unmodified lines | |||
| 1194 | */ | 1194 | */ |
| 1195 | int qman_is_probed(void); | 1195 | int qman_is_probed(void); |
| 1196 | 1196 | ||
| 1197 | /** | ||
| 1198 | * qman_portals_probed - Check if all cpu bound qman portals are probed | ||
| 1199 | * | ||
| 1200 | * Returns 1 if all the required cpu bound qman portals successfully probed, | ||
| 1201 | * -1 if probe errors appeared or 0 if the qman portals did not yet finished | ||
| 1202 | * probing. | ||
| 1203 | */ | ||
| 1204 | int qman_portals_probed(void); | ||
| 1205 | |||
| 1197 | /** | 1206 | /** |
| 1198 | * qman_dqrr_get_ithresh - Get coalesce interrupt threshold | 1207 | * qman_dqrr_get_ithresh - Get coalesce interrupt threshold |
| 1199 | * @portal: portal to get the value for | 1208 | * @portal: portal to get the value for |
| @@ -531,14 +531,6 @@ config LRU_CACHE · 530 unmodified lines | |||
| 531 | config CLZ_TAB | 531 | config CLZ_TAB |
| 532 | bool | 532 | bool |
| 533 | 533 | ||
| 534 | config DDR | ||
| 535 | bool "JEDEC DDR data" | ||
| 536 | help | ||
| 537 | Data from JEDEC specs for DDR SDRAM memories, | ||
| 538 | particularly the AC timing parameters and addressing | ||
| 539 | information. This data is useful for drivers handling | ||
| 540 | DDR SDRAM controllers. | ||
| 541 | |||
| 542 | config IRQ_POLL | 534 | config IRQ_POLL |
| 543 | bool "IRQ polling library" | 535 | bool "IRQ polling library" |
| 544 | help | 536 | help |
| @@ -209,8 +209,6 @@ obj-$(CONFIG_SIGNATURE) += digsig.o · 208 unmodified lines | |||
| 209 | 209 | ||
| 210 | lib-$(CONFIG_CLZ_TAB) += clz_tab.o | 210 | lib-$(CONFIG_CLZ_TAB) += clz_tab.o |
| 211 | 211 | ||
| 212 | obj-$(CONFIG_DDR) += jedec_ddr_data.o | ||
| 213 | |||
| 214 | obj-$(CONFIG_GENERIC_STRNCPY_FROM_USER) += strncpy_from_user.o | 212 | obj-$(CONFIG_GENERIC_STRNCPY_FROM_USER) += strncpy_from_user.o |
| 215 | obj-$(CONFIG_GENERIC_STRNLEN_USER) += strnlen_user.o | 213 | obj-$(CONFIG_GENERIC_STRNLEN_USER) += strnlen_user.o |
| 216 | 214 | ||