mirror of
https://gitee.com/bianbu-linux/linux-6.6
synced 2025-04-24 14:07:52 -04:00
ARM: driver updates for 6.1
The drivers branch for 6.1 is a bit larger than for most releases. Most of the changes come from SoC maintainers for the drivers/soc subsystem: - A new driver for error handling on the NVIDIA Tegra 'control backbone' bus. - A new driver for Qualcomm LLCC/DDR bandwidth measurement - New Rockchip rv1126 and rk3588 power domain drivers - DT binding updates for memory controllers, older Rockchip SoCs, various Mediatek devices, Qualcomm SCM firmware - Minor updates to Hisilicon LPC bus, the Allwinner SRAM driver, the Apple rtkit firmware driver, Tegra firmware - Minor updates for SoC drivers (Samsung, Mediatek, Renesas, Tegra, Qualcomm, Broadcom, NXP, ...) There are also some separate subsystem with downstream maintainers that merge updates this way: - Various updates and new drivers in the memory controller subsystem for Mediatek and Broadcom SoCs - Small set of changes in preparation to add support for FF-A v1.1 specification later, in the Arm FF-A firmware subsystem - debugfs support in the PSCI firmware subsystem -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmM+j54ACgkQmmx57+YA GNkK1Q//fSzCHUPNTrZKJi8mRtp/32Nrpav3eorMZWltKnYbYQyhqH/LCuSZJfe/ rmGYFxsH6DHEgfHqqyzm6PNC0S4Hle6KiB5xnqXrTgqciPuSg4Fa9OMQgkbiQF6x uB2KR+TouQA3MssQh6NW4wy5XAkEqudZCSnEyOTJTmdpepZd/1Eu2Rhn8kx5AYQN pzYNGURRoirgYbO9vHMssCcpqyGNdR9SWXcOkROyd65L4LCHQ9JRh4etg7fSXP5j abWtTHSOwD8MTXOENOiNw/vyCfBX7wUoJkY2v8OUo3G/20qbOXKWPWi056gyDjVQ kJdlnnK4APtiluyBg2alEEZmJOd1iCaVP2j84EO1N4FEek2UGd/lMNOtAOJa+wbh eiE6KC5gswe+99//PdY4gB+7dRM3I0gU7FDMl9G5A4DPMEE/0bMKLKk1jR5vyYXl 6QpN2N0OlU7d16MJiP9RvWf2/xJrcQrLQcy8FKvFVWClJ9wMvBXozKrvXgji9l3I ZTW+EViQiyWmj6KbFlDZkYT+Q6YosxaogJUNrZeIaAwmwJj1oTa+M6jYRnFU6uha XxG5TrybC9JQ/BpYCTYEqb16LOYALwEm7NWmylWASUCCZclC1u35qmmVEhDyBcS9 98ePumkAwrcjmW0TZsiYXOCQWNOITuvU/Ku2t/+6Mhg+Xl44zX4= =WX9J -----END PGP SIGNATURE----- Merge tag 'arm-drivers-6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc Pull ARM driver updates from Arnd Bergmann: "The drivers branch for 6.1 is a bit larger than for most releases. Most of the changes come from SoC maintainers for the drivers/soc subsystem: - A new driver for error handling on the NVIDIA Tegra 'control backbone' bus. - A new driver for Qualcomm LLCC/DDR bandwidth measurement - New Rockchip rv1126 and rk3588 power domain drivers - DT binding updates for memory controllers, older Rockchip SoCs, various Mediatek devices, Qualcomm SCM firmware - Minor updates to Hisilicon LPC bus, the Allwinner SRAM driver, the Apple rtkit firmware driver, Tegra firmware - Minor updates for SoC drivers (Samsung, Mediatek, Renesas, Tegra, Qualcomm, Broadcom, NXP, ...) There are also some separate subsystem with downstream maintainers that merge updates this way: - Various updates and new drivers in the memory controller subsystem for Mediatek and Broadcom SoCs - Small set of changes in preparation to add support for FF-A v1.1 specification later, in the Arm FF-A firmware subsystem - debugfs support in the PSCI firmware subsystem" * tag 'arm-drivers-6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (149 commits) ARM: remove check for CONFIG_DEBUG_LL_SER3 firmware/psci: Add debugfs support to ease debugging firmware/psci: Print a warning if PSCI doesn't accept PC mode dt-bindings: memory: snps,dw-umctl2-ddrc: Extend schema with IRQs/resets/clocks props dt-bindings: memory: snps,dw-umctl2-ddrc: Replace opencoded numbers with macros dt-bindings: memory: snps,dw-umctl2-ddrc: Use more descriptive device name dt-bindings: memory: synopsys,ddrc-ecc: Detach Zynq DDRC controller support soc: sunxi: sram: Add support for the D1 system control soc: sunxi: sram: Export the LDO control register soc: sunxi: sram: Save a pointer to the OF match data soc: sunxi: sram: Return void from the release function soc: apple: rtkit: Add apple_rtkit_poll soc: imx: add i.MX93 media blk ctrl driver soc: imx: add i.MX93 SRC power domain driver soc: imx: imx8m-blk-ctrl: Use genpd_xlate_onecell soc: imx: imx8mp-blk-ctrl: handle PCIe PHY resets soc: imx: imx8m-blk-ctrl: add i.MX8MP VPU blk ctrl soc: imx: add i.MX8MP HDMI blk ctrl HDCP/HRV_MWR soc: imx: add icc paths for i.MX8MP hsio/hdmi blk ctrl soc: imx: add icc paths for i.MX8MP media blk ctrl ...
This commit is contained in:
commit
ff6862c23d
121 changed files with 7566 additions and 885 deletions
15
Documentation/ABI/testing/sysfs-platform-brcmstb-memc
Normal file
15
Documentation/ABI/testing/sysfs-platform-brcmstb-memc
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
What: /sys/bus/platform/devices/*/srpd
|
||||||
|
Date: July 2022
|
||||||
|
KernelVersion: 5.21
|
||||||
|
Contact: Florian Fainelli <f.fainelli@gmail.com>
|
||||||
|
Description:
|
||||||
|
Self Refresh Power Down (SRPD) inactivity timeout counted in
|
||||||
|
internal DDR controller clock cycles. Possible values range
|
||||||
|
from 0 (disable inactivity timeout) to 65535 (0xffff).
|
||||||
|
|
||||||
|
What: /sys/bus/platform/devices/*/frequency
|
||||||
|
Date: July 2022
|
||||||
|
KernelVersion: 5.21
|
||||||
|
Contact: Florian Fainelli <f.fainelli@gmail.com>
|
||||||
|
Description:
|
||||||
|
DDR PHY frequency in Hz.
|
|
@ -187,15 +187,8 @@ Required properties:
|
||||||
Sequencer DRAM parameters and control registers. Used for Self-Refresh
|
Sequencer DRAM parameters and control registers. Used for Self-Refresh
|
||||||
Power-Down (SRPD), among other things.
|
Power-Down (SRPD), among other things.
|
||||||
|
|
||||||
Required properties:
|
See Documentation/devicetree/bindings/memory-controllers/brcm,brcmstb-memc-ddr.yaml for a
|
||||||
- compatible : should contain one of these
|
full list of supported compatible strings and properties.
|
||||||
"brcm,brcmstb-memc-ddr-rev-b.2.1"
|
|
||||||
"brcm,brcmstb-memc-ddr-rev-b.2.2"
|
|
||||||
"brcm,brcmstb-memc-ddr-rev-b.2.3"
|
|
||||||
"brcm,brcmstb-memc-ddr-rev-b.3.0"
|
|
||||||
"brcm,brcmstb-memc-ddr-rev-b.3.1"
|
|
||||||
"brcm,brcmstb-memc-ddr"
|
|
||||||
- reg : the MEMC DDR register range
|
|
||||||
|
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
|
|
|
@ -554,8 +554,7 @@ properties:
|
||||||
- engicam,imx6ul-isiot # Engicam Is.IoT MX6UL eMMC/NAND Starter kit
|
- engicam,imx6ul-isiot # Engicam Is.IoT MX6UL eMMC/NAND Starter kit
|
||||||
- fsl,imx6ul-14x14-evk # i.MX6 UltraLite 14x14 EVK Board
|
- fsl,imx6ul-14x14-evk # i.MX6 UltraLite 14x14 EVK Board
|
||||||
- karo,imx6ul-tx6ul # Ka-Ro electronics TXUL-0010 Module
|
- karo,imx6ul-tx6ul # Ka-Ro electronics TXUL-0010 Module
|
||||||
- kontron,imx6ul-n6310-som # Kontron N6310 SOM
|
- kontron,sl-imx6ul # Kontron SL i.MX6UL SoM
|
||||||
- kontron,imx6ul-n6311-som # Kontron N6311 SOM
|
|
||||||
- prt,prti6g # Protonic PRTI6G Board
|
- prt,prti6g # Protonic PRTI6G Board
|
||||||
- technexion,imx6ul-pico-dwarf # TechNexion i.MX6UL Pico-Dwarf
|
- technexion,imx6ul-pico-dwarf # TechNexion i.MX6UL Pico-Dwarf
|
||||||
- technexion,imx6ul-pico-hobbit # TechNexion i.MX6UL Pico-Hobbit
|
- technexion,imx6ul-pico-hobbit # TechNexion i.MX6UL Pico-Hobbit
|
||||||
|
@ -591,23 +590,17 @@ properties:
|
||||||
- const: phytec,imx6ul-pcl063 # PHYTEC phyCORE-i.MX 6UL
|
- const: phytec,imx6ul-pcl063 # PHYTEC phyCORE-i.MX 6UL
|
||||||
- const: fsl,imx6ul
|
- const: fsl,imx6ul
|
||||||
|
|
||||||
- description: Kontron N6310 S Board
|
- description: Kontron BL i.MX6UL (N631X S) Board
|
||||||
items:
|
items:
|
||||||
- const: kontron,imx6ul-n6310-s
|
- const: kontron,bl-imx6ul # Kontron BL i.MX6UL Carrier Board
|
||||||
- const: kontron,imx6ul-n6310-som
|
- const: kontron,sl-imx6ul # Kontron SL i.MX6UL SoM
|
||||||
- const: fsl,imx6ul
|
- const: fsl,imx6ul
|
||||||
|
|
||||||
- description: Kontron N6311 S Board
|
- description: Kontron BL i.MX6UL 43 (N631X S 43) Board
|
||||||
items:
|
items:
|
||||||
- const: kontron,imx6ul-n6311-s
|
- const: kontron,bl-imx6ul-43 # Kontron BL i.MX6UL Carrier Board with 4.3" Display
|
||||||
- const: kontron,imx6ul-n6311-som
|
- const: kontron,bl-imx6ul # Kontron BL i.MX6UL Carrier Board
|
||||||
- const: fsl,imx6ul
|
- const: kontron,sl-imx6ul # Kontron SL i.MX6UL SoM
|
||||||
|
|
||||||
- description: Kontron N6310 S 43 Board
|
|
||||||
items:
|
|
||||||
- const: kontron,imx6ul-n6310-s-43
|
|
||||||
- const: kontron,imx6ul-n6310-s
|
|
||||||
- const: kontron,imx6ul-n6310-som
|
|
||||||
- const: fsl,imx6ul
|
- const: fsl,imx6ul
|
||||||
|
|
||||||
- description: TQ-Systems TQMa6UL1 SoM on MBa6ULx board
|
- description: TQ-Systems TQMa6UL1 SoM on MBa6ULx board
|
||||||
|
@ -637,7 +630,7 @@ properties:
|
||||||
- enum:
|
- enum:
|
||||||
- fsl,imx6ull-14x14-evk # i.MX6 UltraLiteLite 14x14 EVK Board
|
- fsl,imx6ull-14x14-evk # i.MX6 UltraLiteLite 14x14 EVK Board
|
||||||
- joz,jozacp # JOZ Access Point
|
- joz,jozacp # JOZ Access Point
|
||||||
- kontron,imx6ull-n6411-som # Kontron N6411 SOM
|
- kontron,sl-imx6ull # Kontron SL i.MX6ULL SoM
|
||||||
- myir,imx6ull-mys-6ulx-eval # MYiR Tech iMX6ULL Evaluation Board
|
- myir,imx6ull-mys-6ulx-eval # MYiR Tech iMX6ULL Evaluation Board
|
||||||
- toradex,colibri-imx6ull # Colibri iMX6ULL Modules
|
- toradex,colibri-imx6ull # Colibri iMX6ULL Modules
|
||||||
- toradex,colibri-imx6ull-emmc # Colibri iMX6ULL 1GB (eMMC) Module
|
- toradex,colibri-imx6ull-emmc # Colibri iMX6ULL 1GB (eMMC) Module
|
||||||
|
@ -698,10 +691,10 @@ properties:
|
||||||
- const: toradex,colibri-imx6ull-wifi # Colibri iMX6ULL Wi-Fi / BT Module
|
- const: toradex,colibri-imx6ull-wifi # Colibri iMX6ULL Wi-Fi / BT Module
|
||||||
- const: fsl,imx6ull
|
- const: fsl,imx6ull
|
||||||
|
|
||||||
- description: Kontron N6411 S Board
|
- description: Kontron BL i.MX6ULL (N6411 S) Board
|
||||||
items:
|
items:
|
||||||
- const: kontron,imx6ull-n6411-s
|
- const: kontron,bl-imx6ull # Kontron BL i.MX6ULL Carrier Board
|
||||||
- const: kontron,imx6ull-n6411-som
|
- const: kontron,sl-imx6ull # Kontron SL i.MX6ULL SoM
|
||||||
- const: fsl,imx6ull
|
- const: fsl,imx6ull
|
||||||
|
|
||||||
- description: TQ Systems TQMa6ULLx SoM on MBa6ULx board
|
- description: TQ Systems TQMa6ULLx SoM on MBa6ULx board
|
||||||
|
@ -825,13 +818,15 @@ properties:
|
||||||
- emtrion,emcon-mx8mm-avari # emCON-MX8MM SoM on Avari Base
|
- emtrion,emcon-mx8mm-avari # emCON-MX8MM SoM on Avari Base
|
||||||
- fsl,imx8mm-ddr4-evk # i.MX8MM DDR4 EVK Board
|
- fsl,imx8mm-ddr4-evk # i.MX8MM DDR4 EVK Board
|
||||||
- fsl,imx8mm-evk # i.MX8MM EVK Board
|
- fsl,imx8mm-evk # i.MX8MM EVK Board
|
||||||
|
- gateworks,imx8mm-gw7904
|
||||||
- gw,imx8mm-gw71xx-0x # i.MX8MM Gateworks Development Kit
|
- gw,imx8mm-gw71xx-0x # i.MX8MM Gateworks Development Kit
|
||||||
- gw,imx8mm-gw72xx-0x # i.MX8MM Gateworks Development Kit
|
- gw,imx8mm-gw72xx-0x # i.MX8MM Gateworks Development Kit
|
||||||
- gw,imx8mm-gw73xx-0x # i.MX8MM Gateworks Development Kit
|
- gw,imx8mm-gw73xx-0x # i.MX8MM Gateworks Development Kit
|
||||||
- gw,imx8mm-gw7901 # i.MX8MM Gateworks Board
|
- gw,imx8mm-gw7901 # i.MX8MM Gateworks Board
|
||||||
- gw,imx8mm-gw7902 # i.MX8MM Gateworks Board
|
- gw,imx8mm-gw7902 # i.MX8MM Gateworks Board
|
||||||
- gw,imx8mm-gw7903 # i.MX8MM Gateworks Board
|
- gw,imx8mm-gw7903 # i.MX8MM Gateworks Board
|
||||||
- kontron,imx8mm-n801x-som # i.MX8MM Kontron SL (N801X) SOM
|
- kontron,imx8mm-sl # i.MX8MM Kontron SL (N801X) SOM
|
||||||
|
- kontron,imx8mm-osm-s # i.MX8MM Kontron OSM-S (N802X) SOM
|
||||||
- menlo,mx8menlo # i.MX8MM Menlo board with Verdin SoM
|
- menlo,mx8menlo # i.MX8MM Menlo board with Verdin SoM
|
||||||
- toradex,verdin-imx8mm # Verdin iMX8M Mini Modules
|
- toradex,verdin-imx8mm # Verdin iMX8M Mini Modules
|
||||||
- toradex,verdin-imx8mm-nonwifi # Verdin iMX8M Mini Modules without Wi-Fi / BT
|
- toradex,verdin-imx8mm-nonwifi # Verdin iMX8M Mini Modules without Wi-Fi / BT
|
||||||
|
@ -850,8 +845,14 @@ properties:
|
||||||
|
|
||||||
- description: Kontron BL i.MX8MM (N801X S) Board
|
- description: Kontron BL i.MX8MM (N801X S) Board
|
||||||
items:
|
items:
|
||||||
- const: kontron,imx8mm-n801x-s
|
- const: kontron,imx8mm-bl
|
||||||
- const: kontron,imx8mm-n801x-som
|
- const: kontron,imx8mm-sl
|
||||||
|
- const: fsl,imx8mm
|
||||||
|
|
||||||
|
- description: Kontron BL i.MX8MM OSM-S (N802X S) Board
|
||||||
|
items:
|
||||||
|
- const: kontron,imx8mm-bl-osm-s
|
||||||
|
- const: kontron,imx8mm-osm-s
|
||||||
- const: fsl,imx8mm
|
- const: fsl,imx8mm
|
||||||
|
|
||||||
- description: Toradex Boards with Verdin iMX8M Mini Modules
|
- description: Toradex Boards with Verdin iMX8M Mini Modules
|
||||||
|
@ -936,6 +937,13 @@ properties:
|
||||||
- toradex,verdin-imx8mp-wifi # Verdin iMX8M Plus Wi-Fi / BT Modules
|
- toradex,verdin-imx8mp-wifi # Verdin iMX8M Plus Wi-Fi / BT Modules
|
||||||
- const: fsl,imx8mp
|
- const: fsl,imx8mp
|
||||||
|
|
||||||
|
- description: Avnet (MSC Branded) Boards with SM2S i.MX8M Plus Modules
|
||||||
|
items:
|
||||||
|
- const: avnet,sm2s-imx8mp-14N0600E-ep1 # SM2S-IMX8PLUS-14N0600E on SM2-MB-EP1 Carrier Board
|
||||||
|
- const: avnet,sm2s-imx8mp-14N0600E # 14N0600E variant of SM2S-IMX8PLUS SoM
|
||||||
|
- const: avnet,sm2s-imx8mp # SM2S-IMX8PLUS SoM
|
||||||
|
- const: fsl,imx8mp
|
||||||
|
|
||||||
- description: Engicam i.Core MX8M Plus SoM based boards
|
- description: Engicam i.Core MX8M Plus SoM based boards
|
||||||
items:
|
items:
|
||||||
- enum:
|
- enum:
|
||||||
|
@ -1034,6 +1042,12 @@ properties:
|
||||||
- toradex,colibri-imx8x # Colibri iMX8X Modules
|
- toradex,colibri-imx8x # Colibri iMX8X Modules
|
||||||
- const: fsl,imx8qxp
|
- const: fsl,imx8qxp
|
||||||
|
|
||||||
|
- description: i.MX8DXL based Boards
|
||||||
|
items:
|
||||||
|
- enum:
|
||||||
|
- fsl,imx8dxl-evk # i.MX8DXL EVK Board
|
||||||
|
- const: fsl,imx8dxl
|
||||||
|
|
||||||
- description: i.MX8QXP Boards with Toradex Coilbri iMX8X Modules
|
- description: i.MX8QXP Boards with Toradex Coilbri iMX8X Modules
|
||||||
items:
|
items:
|
||||||
- enum:
|
- enum:
|
||||||
|
|
|
@ -21,10 +21,12 @@ select:
|
||||||
enum:
|
enum:
|
||||||
- rockchip,px30-pmu
|
- rockchip,px30-pmu
|
||||||
- rockchip,rk3066-pmu
|
- rockchip,rk3066-pmu
|
||||||
|
- rockchip,rk3128-pmu
|
||||||
- rockchip,rk3288-pmu
|
- rockchip,rk3288-pmu
|
||||||
- rockchip,rk3368-pmu
|
- rockchip,rk3368-pmu
|
||||||
- rockchip,rk3399-pmu
|
- rockchip,rk3399-pmu
|
||||||
- rockchip,rk3568-pmu
|
- rockchip,rk3568-pmu
|
||||||
|
- rockchip,rk3588-pmu
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
|
@ -35,10 +37,12 @@ properties:
|
||||||
- enum:
|
- enum:
|
||||||
- rockchip,px30-pmu
|
- rockchip,px30-pmu
|
||||||
- rockchip,rk3066-pmu
|
- rockchip,rk3066-pmu
|
||||||
|
- rockchip,rk3128-pmu
|
||||||
- rockchip,rk3288-pmu
|
- rockchip,rk3288-pmu
|
||||||
- rockchip,rk3368-pmu
|
- rockchip,rk3368-pmu
|
||||||
- rockchip,rk3399-pmu
|
- rockchip,rk3399-pmu
|
||||||
- rockchip,rk3568-pmu
|
- rockchip,rk3568-pmu
|
||||||
|
- rockchip,rk3588-pmu
|
||||||
- const: syscon
|
- const: syscon
|
||||||
- const: simple-mfd
|
- const: simple-mfd
|
||||||
|
|
||||||
|
|
|
@ -1,61 +0,0 @@
|
||||||
QCOM Secure Channel Manager (SCM)
|
|
||||||
|
|
||||||
Qualcomm processors include an interface to communicate to the secure firmware.
|
|
||||||
This interface allows for clients to request different types of actions. These
|
|
||||||
can include CPU power up/down, HDCP requests, loading of firmware, and other
|
|
||||||
assorted actions.
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
- compatible: must contain one of the following:
|
|
||||||
* "qcom,scm-apq8064"
|
|
||||||
* "qcom,scm-apq8084"
|
|
||||||
* "qcom,scm-ipq4019"
|
|
||||||
* "qcom,scm-ipq806x"
|
|
||||||
* "qcom,scm-ipq8074"
|
|
||||||
* "qcom,scm-mdm9607"
|
|
||||||
* "qcom,scm-msm8226"
|
|
||||||
* "qcom,scm-msm8660"
|
|
||||||
* "qcom,scm-msm8916"
|
|
||||||
* "qcom,scm-msm8953"
|
|
||||||
* "qcom,scm-msm8960"
|
|
||||||
* "qcom,scm-msm8974"
|
|
||||||
* "qcom,scm-msm8976"
|
|
||||||
* "qcom,scm-msm8994"
|
|
||||||
* "qcom,scm-msm8996"
|
|
||||||
* "qcom,scm-msm8998"
|
|
||||||
* "qcom,scm-qcs404"
|
|
||||||
* "qcom,scm-sc7180"
|
|
||||||
* "qcom,scm-sc7280"
|
|
||||||
* "qcom,scm-sm6125"
|
|
||||||
* "qcom,scm-sdm845"
|
|
||||||
* "qcom,scm-sdx55"
|
|
||||||
* "qcom,scm-sdx65"
|
|
||||||
* "qcom,scm-sm6350"
|
|
||||||
* "qcom,scm-sm8150"
|
|
||||||
* "qcom,scm-sm8250"
|
|
||||||
* "qcom,scm-sm8350"
|
|
||||||
* "qcom,scm-sm8450"
|
|
||||||
and:
|
|
||||||
* "qcom,scm"
|
|
||||||
- clocks: Specifies clocks needed by the SCM interface, if any:
|
|
||||||
* core clock required for "qcom,scm-apq8064", "qcom,scm-msm8660" and
|
|
||||||
"qcom,scm-msm8960"
|
|
||||||
* core, iface and bus clocks required for "qcom,scm-apq8084",
|
|
||||||
"qcom,scm-msm8916", "qcom,scm-msm8953", "qcom,scm-msm8974" and "qcom,scm-msm8976"
|
|
||||||
- clock-names: Must contain "core" for the core clock, "iface" for the interface
|
|
||||||
clock and "bus" for the bus clock per the requirements of the compatible.
|
|
||||||
- qcom,dload-mode: phandle to the TCSR hardware block and offset of the
|
|
||||||
download mode control register (optional)
|
|
||||||
- interconnects: Specifies the bandwidth requirements of the SCM interface (optional)
|
|
||||||
|
|
||||||
Example for MSM8916:
|
|
||||||
|
|
||||||
firmware {
|
|
||||||
scm {
|
|
||||||
compatible = "qcom,msm8916", "qcom,scm";
|
|
||||||
clocks = <&gcc GCC_CRYPTO_CLK> ,
|
|
||||||
<&gcc GCC_CRYPTO_AXI_CLK>,
|
|
||||||
<&gcc GCC_CRYPTO_AHB_CLK>;
|
|
||||||
clock-names = "core", "bus", "iface";
|
|
||||||
};
|
|
||||||
};
|
|
148
Documentation/devicetree/bindings/firmware/qcom,scm.yaml
Normal file
148
Documentation/devicetree/bindings/firmware/qcom,scm.yaml
Normal file
|
@ -0,0 +1,148 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/firmware/qcom,scm.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: QCOM Secure Channel Manager (SCM)
|
||||||
|
|
||||||
|
description: |
|
||||||
|
Qualcomm processors include an interface to communicate to the secure firmware.
|
||||||
|
This interface allows for clients to request different types of actions.
|
||||||
|
These can include CPU power up/down, HDCP requests, loading of firmware,
|
||||||
|
and other assorted actions.
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Bjorn Andersson <bjorn.andersson@linaro.org>
|
||||||
|
- Robert Marko <robimarko@gmail.com>
|
||||||
|
- Guru Das Srinagesh <quic_gurus@quicinc.com>
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
items:
|
||||||
|
- enum:
|
||||||
|
- qcom,scm-apq8064
|
||||||
|
- qcom,scm-apq8084
|
||||||
|
- qcom,scm-ipq4019
|
||||||
|
- qcom,scm-ipq6018
|
||||||
|
- qcom,scm-ipq806x
|
||||||
|
- qcom,scm-ipq8074
|
||||||
|
- qcom,scm-mdm9607
|
||||||
|
- qcom,scm-msm8226
|
||||||
|
- qcom,scm-msm8660
|
||||||
|
- qcom,scm-msm8916
|
||||||
|
- qcom,scm-msm8953
|
||||||
|
- qcom,scm-msm8960
|
||||||
|
- qcom,scm-msm8974
|
||||||
|
- qcom,scm-msm8976
|
||||||
|
- qcom,scm-msm8994
|
||||||
|
- qcom,scm-msm8996
|
||||||
|
- qcom,scm-msm8998
|
||||||
|
- qcom,scm-sc7180
|
||||||
|
- qcom,scm-sc7280
|
||||||
|
- qcom,scm-sc8280xp
|
||||||
|
- qcom,scm-sdm845
|
||||||
|
- qcom,scm-sdx55
|
||||||
|
- qcom,scm-sdx65
|
||||||
|
- qcom,scm-sm6115
|
||||||
|
- qcom,scm-sm6125
|
||||||
|
- qcom,scm-sm6350
|
||||||
|
- qcom,scm-sm8150
|
||||||
|
- qcom,scm-sm8250
|
||||||
|
- qcom,scm-sm8350
|
||||||
|
- qcom,scm-sm8450
|
||||||
|
- qcom,scm-qcs404
|
||||||
|
- const: qcom,scm
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 3
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 3
|
||||||
|
|
||||||
|
interconnects:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
interconnect-names:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
'#reset-cells':
|
||||||
|
const: 1
|
||||||
|
|
||||||
|
qcom,dload-mode:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/phandle-array
|
||||||
|
items:
|
||||||
|
- items:
|
||||||
|
- description: phandle to TCSR hardware block
|
||||||
|
- description: offset of the download mode control register
|
||||||
|
description: TCSR hardware block
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
|
- qcom,scm-apq8064
|
||||||
|
- qcom,scm-msm8660
|
||||||
|
- qcom,scm-msm8960
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: core
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
required:
|
||||||
|
- clocks
|
||||||
|
- clock-names
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
|
- qcom,scm-apq8084
|
||||||
|
- qcom,scm-mdm9607
|
||||||
|
- qcom,scm-msm8916
|
||||||
|
- qcom,scm-msm8953
|
||||||
|
- qcom,scm-msm8974
|
||||||
|
- qcom,scm-msm8976
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: core
|
||||||
|
- const: bus
|
||||||
|
- const: iface
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
minItems: 3
|
||||||
|
maxItems: 3
|
||||||
|
|
||||||
|
required:
|
||||||
|
- clocks
|
||||||
|
- clock-names
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/clock/qcom,gcc-msm8916.h>
|
||||||
|
|
||||||
|
firmware {
|
||||||
|
scm {
|
||||||
|
compatible = "qcom,scm-msm8916", "qcom,scm";
|
||||||
|
clocks = <&gcc GCC_CRYPTO_CLK>,
|
||||||
|
<&gcc GCC_CRYPTO_AXI_CLK>,
|
||||||
|
<&gcc GCC_CRYPTO_AHB_CLK>;
|
||||||
|
clock-names = "core", "bus", "iface";
|
||||||
|
};
|
||||||
|
};
|
|
@ -24,9 +24,12 @@ properties:
|
||||||
oneOf:
|
oneOf:
|
||||||
- items:
|
- items:
|
||||||
- enum:
|
- enum:
|
||||||
|
- qcom,sc7280-bwmon
|
||||||
- qcom,sdm845-bwmon
|
- qcom,sdm845-bwmon
|
||||||
- const: qcom,msm8998-bwmon
|
- const: qcom,msm8998-bwmon
|
||||||
- const: qcom,msm8998-bwmon # BWMON v4
|
- const: qcom,msm8998-bwmon # BWMON v4
|
||||||
|
- const: qcom,sc7280-llcc-bwmon # BWMON v5
|
||||||
|
- const: qcom,sdm845-llcc-bwmon # BWMON v5
|
||||||
|
|
||||||
interconnects:
|
interconnects:
|
||||||
maxItems: 1
|
maxItems: 1
|
||||||
|
|
|
@ -1,38 +0,0 @@
|
||||||
* Samsung Exynos5 G-Scaler device
|
|
||||||
|
|
||||||
G-Scaler is used for scaling and color space conversion on Exynos5 SoCs.
|
|
||||||
|
|
||||||
Required properties:
|
|
||||||
- compatible: should be one of
|
|
||||||
"samsung,exynos5250-gsc"
|
|
||||||
"samsung,exynos5420-gsc"
|
|
||||||
"samsung,exynos5433-gsc"
|
|
||||||
"samsung,exynos5-gsc" (deprecated)
|
|
||||||
- reg: should contain G-Scaler physical address location and length.
|
|
||||||
- interrupts: should contain G-Scaler interrupt number
|
|
||||||
|
|
||||||
Optional properties:
|
|
||||||
- samsung,sysreg: handle to syscon used to control the system registers to
|
|
||||||
set writeback input and destination
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
gsc_0: gsc@13e00000 {
|
|
||||||
compatible = "samsung,exynos5250-gsc";
|
|
||||||
reg = <0x13e00000 0x1000>;
|
|
||||||
interrupts = <0 85 0>;
|
|
||||||
};
|
|
||||||
|
|
||||||
Aliases:
|
|
||||||
Each G-Scaler node should have a numbered alias in the aliases node,
|
|
||||||
in the form of gscN, N = 0...3. G-Scaler driver uses these aliases
|
|
||||||
to retrieve the device IDs using "of_alias_get_id()" call.
|
|
||||||
|
|
||||||
Example:
|
|
||||||
|
|
||||||
aliases {
|
|
||||||
gsc0 =&gsc_0;
|
|
||||||
gsc1 =&gsc_1;
|
|
||||||
gsc2 =&gsc_2;
|
|
||||||
gsc3 =&gsc_3;
|
|
||||||
};
|
|
|
@ -0,0 +1,109 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/media/samsung,exynos5250-gsc.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Samsung Exynos SoC G-Scaler
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Inki Dae <inki.dae@samsung.com>
|
||||||
|
- Krzysztof Kozlowski <krzk@kernel.org>
|
||||||
|
- Seung-Woo Kim <sw0312.kim@samsung.com
|
||||||
|
|
||||||
|
description:
|
||||||
|
G-Scaler is used for scaling and color space conversion on Samsung Exynos
|
||||||
|
SoCs.
|
||||||
|
|
||||||
|
Each G-Scaler node should have a numbered alias in the aliases node, in the
|
||||||
|
form of gscN, N = 0...3.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
oneOf:
|
||||||
|
- items:
|
||||||
|
- enum:
|
||||||
|
- samsung,exynos5250-gsc
|
||||||
|
- samsung,exynos5420-gsc
|
||||||
|
- const: samsung,exynos5-gsc
|
||||||
|
- enum:
|
||||||
|
- samsung,exynos5433-gsc
|
||||||
|
- const: samsung,exynos5-gsc
|
||||||
|
deprecated: True
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 5
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 5
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
iommus:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
power-domains:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
samsung,sysreg:
|
||||||
|
$ref: /schemas/types.yaml#/definitions/phandle
|
||||||
|
description:
|
||||||
|
Syscon used to control the system registers to set writeback input and destination.
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- clocks
|
||||||
|
- clock-names
|
||||||
|
- interrupts
|
||||||
|
- reg
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
enum:
|
||||||
|
- samsung,exynos5-gsc
|
||||||
|
- samsung,exynos5250-gsc
|
||||||
|
- samsung,exynos5420-gsc
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
clocks:
|
||||||
|
maxItems: 1
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: gscl
|
||||||
|
else:
|
||||||
|
properties:
|
||||||
|
clocks:
|
||||||
|
minItems: 5
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: pclk
|
||||||
|
- const: aclk
|
||||||
|
- const: aclk_xiu
|
||||||
|
- const: aclk_gsclbend
|
||||||
|
- const: gsd
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/clock/exynos5250.h>
|
||||||
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
|
||||||
|
video-scaler@13e00000 {
|
||||||
|
compatible = "samsung,exynos5250-gsc", "samsung,exynos5-gsc";
|
||||||
|
reg = <0x13e00000 0x1000>;
|
||||||
|
interrupts = <GIC_SPI 85 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
power-domains = <&pd_gsc>;
|
||||||
|
clocks = <&clock CLK_GSCL0>;
|
||||||
|
clock-names = "gscl";
|
||||||
|
iommus = <&sysmmu_gsc0>;
|
||||||
|
};
|
|
@ -0,0 +1,52 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/memory-controllers/brcm,brcmstb-memc-ddr.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Memory controller (MEMC) for Broadcom STB
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Florian Fainelli <f.fainelli@gmail.com>
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
items:
|
||||||
|
- enum:
|
||||||
|
- brcm,brcmstb-memc-ddr-rev-b.1.x
|
||||||
|
- brcm,brcmstb-memc-ddr-rev-b.2.0
|
||||||
|
- brcm,brcmstb-memc-ddr-rev-b.2.1
|
||||||
|
- brcm,brcmstb-memc-ddr-rev-b.2.2
|
||||||
|
- brcm,brcmstb-memc-ddr-rev-b.2.3
|
||||||
|
- brcm,brcmstb-memc-ddr-rev-b.2.5
|
||||||
|
- brcm,brcmstb-memc-ddr-rev-b.2.6
|
||||||
|
- brcm,brcmstb-memc-ddr-rev-b.2.7
|
||||||
|
- brcm,brcmstb-memc-ddr-rev-b.2.8
|
||||||
|
- brcm,brcmstb-memc-ddr-rev-b.3.0
|
||||||
|
- brcm,brcmstb-memc-ddr-rev-b.3.1
|
||||||
|
- brcm,brcmstb-memc-ddr-rev-c.1.0
|
||||||
|
- brcm,brcmstb-memc-ddr-rev-c.1.1
|
||||||
|
- brcm,brcmstb-memc-ddr-rev-c.1.2
|
||||||
|
- brcm,brcmstb-memc-ddr-rev-c.1.3
|
||||||
|
- brcm,brcmstb-memc-ddr-rev-c.1.4
|
||||||
|
- const: brcm,brcmstb-memc-ddr
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
clock-frequency:
|
||||||
|
description: DDR PHY frequency in Hz
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
memory-controller@9902000 {
|
||||||
|
compatible = "brcm,brcmstb-memc-ddr-rev-c.1.1", "brcm,brcmstb-memc-ddr";
|
||||||
|
reg = <0x9902000 0x600>;
|
||||||
|
clock-frequency = <2133000000>;
|
||||||
|
};
|
|
@ -16,7 +16,7 @@ description: |
|
||||||
MediaTek SMI have two generations of HW architecture, here is the list
|
MediaTek SMI have two generations of HW architecture, here is the list
|
||||||
which generation the SoCs use:
|
which generation the SoCs use:
|
||||||
generation 1: mt2701 and mt7623.
|
generation 1: mt2701 and mt7623.
|
||||||
generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8186, mt8192 and mt8195.
|
generation 2: mt2712, mt6779, mt8167, mt8173, mt8183, mt8186, mt8188, mt8192 and mt8195.
|
||||||
|
|
||||||
There's slight differences between the two SMI, for generation 2, the
|
There's slight differences between the two SMI, for generation 2, the
|
||||||
register which control the iommu port is at each larb's register base. But
|
register which control the iommu port is at each larb's register base. But
|
||||||
|
@ -37,6 +37,8 @@ properties:
|
||||||
- mediatek,mt8173-smi-common
|
- mediatek,mt8173-smi-common
|
||||||
- mediatek,mt8183-smi-common
|
- mediatek,mt8183-smi-common
|
||||||
- mediatek,mt8186-smi-common
|
- mediatek,mt8186-smi-common
|
||||||
|
- mediatek,mt8188-smi-common-vdo
|
||||||
|
- mediatek,mt8188-smi-common-vpp
|
||||||
- mediatek,mt8192-smi-common
|
- mediatek,mt8192-smi-common
|
||||||
- mediatek,mt8195-smi-common-vdo
|
- mediatek,mt8195-smi-common-vdo
|
||||||
- mediatek,mt8195-smi-common-vpp
|
- mediatek,mt8195-smi-common-vpp
|
||||||
|
@ -144,7 +146,16 @@ allOf:
|
||||||
- const: gals0
|
- const: gals0
|
||||||
- const: gals1
|
- const: gals1
|
||||||
|
|
||||||
else: # for gen2 HW that don't have gals
|
- if: # for gen2 HW that don't have gals
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
enum:
|
||||||
|
- mediatek,mt2712-smi-common
|
||||||
|
- mediatek,mt6795-smi-common
|
||||||
|
- mediatek,mt8167-smi-common
|
||||||
|
- mediatek,mt8173-smi-common
|
||||||
|
|
||||||
|
then:
|
||||||
properties:
|
properties:
|
||||||
clocks:
|
clocks:
|
||||||
minItems: 2
|
minItems: 2
|
||||||
|
|
|
@ -25,6 +25,7 @@ properties:
|
||||||
- mediatek,mt8173-smi-larb
|
- mediatek,mt8173-smi-larb
|
||||||
- mediatek,mt8183-smi-larb
|
- mediatek,mt8183-smi-larb
|
||||||
- mediatek,mt8186-smi-larb
|
- mediatek,mt8186-smi-larb
|
||||||
|
- mediatek,mt8188-smi-larb
|
||||||
- mediatek,mt8192-smi-larb
|
- mediatek,mt8192-smi-larb
|
||||||
- mediatek,mt8195-smi-larb
|
- mediatek,mt8195-smi-larb
|
||||||
|
|
||||||
|
@ -78,6 +79,7 @@ allOf:
|
||||||
enum:
|
enum:
|
||||||
- mediatek,mt8183-smi-larb
|
- mediatek,mt8183-smi-larb
|
||||||
- mediatek,mt8186-smi-larb
|
- mediatek,mt8186-smi-larb
|
||||||
|
- mediatek,mt8188-smi-larb
|
||||||
- mediatek,mt8195-smi-larb
|
- mediatek,mt8195-smi-larb
|
||||||
|
|
||||||
then:
|
then:
|
||||||
|
@ -111,6 +113,7 @@ allOf:
|
||||||
- mediatek,mt2712-smi-larb
|
- mediatek,mt2712-smi-larb
|
||||||
- mediatek,mt6779-smi-larb
|
- mediatek,mt6779-smi-larb
|
||||||
- mediatek,mt8186-smi-larb
|
- mediatek,mt8186-smi-larb
|
||||||
|
- mediatek,mt8188-smi-larb
|
||||||
- mediatek,mt8192-smi-larb
|
- mediatek,mt8192-smi-larb
|
||||||
- mediatek,mt8195-smi-larb
|
- mediatek,mt8195-smi-larb
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/memory-controllers/snps,dw-umctl2-ddrc.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Synopsys DesignWare Universal Multi-Protocol Memory Controller
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Krzysztof Kozlowski <krzk@kernel.org>
|
||||||
|
- Manish Narani <manish.narani@xilinx.com>
|
||||||
|
- Michal Simek <michal.simek@xilinx.com>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
Synopsys DesignWare Enhanced uMCTL2 DDR Memory Controller is capable of
|
||||||
|
working with the memory devices supporting up to (LP)DDR4 protocol. It can
|
||||||
|
be equipped with SEC/DEC ECC feature if DRAM data bus width is either
|
||||||
|
16-bits or 32-bits or 64-bits wide.
|
||||||
|
|
||||||
|
For instance the ZynqMP DDR controller is based on the DW uMCTL2 v2.40a
|
||||||
|
controller. It has an optional SEC/DEC ECC support in 64- and 32-bits
|
||||||
|
bus width configurations.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
oneOf:
|
||||||
|
- deprecated: true
|
||||||
|
description: Synopsys DW uMCTL2 DDR controller v3.80a
|
||||||
|
const: snps,ddrc-3.80a
|
||||||
|
- description: Synopsys DW uMCTL2 DDR controller
|
||||||
|
const: snps,dw-umctl2-ddrc
|
||||||
|
- description: Xilinx ZynqMP DDR controller v2.40a
|
||||||
|
const: xlnx,zynqmp-ddrc-2.40a
|
||||||
|
|
||||||
|
interrupts:
|
||||||
|
description:
|
||||||
|
DW uMCTL2 DDRC IP-core provides individual IRQ signal for each event":"
|
||||||
|
ECC Corrected Error, ECC Uncorrected Error, ECC Address Protection,
|
||||||
|
Scrubber-Done signal, DFI Parity/CRC Error. Some platforms may have the
|
||||||
|
signals merged before they reach the IRQ controller or have some of them
|
||||||
|
absent in case if the corresponding feature is unavailable/disabled.
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 5
|
||||||
|
|
||||||
|
interrupt-names:
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 5
|
||||||
|
oneOf:
|
||||||
|
- description: Common ECC CE/UE/Scrubber/DFI Errors IRQ
|
||||||
|
items:
|
||||||
|
- const: ecc
|
||||||
|
- description: Individual ECC CE/UE/Scrubber/DFI Errors IRQs
|
||||||
|
items:
|
||||||
|
enum: [ ecc_ce, ecc_ue, ecc_ap, ecc_sbr, dfi_e ]
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
description:
|
||||||
|
A standard set of the clock sources contains CSRs bus clock, AXI-ports
|
||||||
|
reference clock, DDRC core clock, Scrubber standalone clock
|
||||||
|
(synchronous to the DDRC clock).
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 4
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 4
|
||||||
|
items:
|
||||||
|
enum: [ pclk, aclk, core, sbr ]
|
||||||
|
|
||||||
|
resets:
|
||||||
|
description:
|
||||||
|
Each clock domain can have separate reset signal.
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 4
|
||||||
|
|
||||||
|
reset-names:
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 4
|
||||||
|
items:
|
||||||
|
enum: [ prst, arst, core, sbr ]
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- interrupts
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/interrupt-controller/arm-gic.h>
|
||||||
|
|
||||||
|
memory-controller@fd070000 {
|
||||||
|
compatible = "xlnx,zynqmp-ddrc-2.40a";
|
||||||
|
reg = <0xfd070000 0x30000>;
|
||||||
|
|
||||||
|
interrupt-parent = <&gic>;
|
||||||
|
interrupts = <GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
interrupt-names = "ecc";
|
||||||
|
};
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/interrupt-controller/irq.h>
|
||||||
|
|
||||||
|
memory-controller@3d400000 {
|
||||||
|
compatible = "snps,dw-umctl2-ddrc";
|
||||||
|
reg = <0x3d400000 0x400000>;
|
||||||
|
|
||||||
|
interrupts = <147 IRQ_TYPE_LEVEL_HIGH>, <148 IRQ_TYPE_LEVEL_HIGH>,
|
||||||
|
<149 IRQ_TYPE_LEVEL_HIGH>, <150 IRQ_TYPE_LEVEL_HIGH>;
|
||||||
|
interrupt-names = "ecc_ce", "ecc_ue", "ecc_sbr", "dfi_e";
|
||||||
|
|
||||||
|
clocks = <&pclk>, <&aclk>, <&core_clk>, <&sbr_clk>;
|
||||||
|
clock-names = "pclk", "aclk", "core", "sbr";
|
||||||
|
};
|
||||||
|
...
|
|
@ -1,76 +0,0 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0-only
|
|
||||||
%YAML 1.2
|
|
||||||
---
|
|
||||||
$id: http://devicetree.org/schemas/memory-controllers/synopsys,ddrc-ecc.yaml#
|
|
||||||
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
|
||||||
|
|
||||||
title: Synopsys IntelliDDR Multi Protocol memory controller
|
|
||||||
|
|
||||||
maintainers:
|
|
||||||
- Krzysztof Kozlowski <krzk@kernel.org>
|
|
||||||
- Manish Narani <manish.narani@xilinx.com>
|
|
||||||
- Michal Simek <michal.simek@xilinx.com>
|
|
||||||
|
|
||||||
description: |
|
|
||||||
The ZynqMP DDR ECC controller has an optional ECC support in 64-bit and
|
|
||||||
32-bit bus width configurations.
|
|
||||||
|
|
||||||
The Zynq DDR ECC controller has an optional ECC support in half-bus width
|
|
||||||
(16-bit) configuration.
|
|
||||||
|
|
||||||
These both ECC controllers correct single bit ECC errors and detect double bit
|
|
||||||
ECC errors.
|
|
||||||
|
|
||||||
properties:
|
|
||||||
compatible:
|
|
||||||
enum:
|
|
||||||
- snps,ddrc-3.80a
|
|
||||||
- xlnx,zynq-ddrc-a05
|
|
||||||
- xlnx,zynqmp-ddrc-2.40a
|
|
||||||
|
|
||||||
interrupts:
|
|
||||||
maxItems: 1
|
|
||||||
|
|
||||||
reg:
|
|
||||||
maxItems: 1
|
|
||||||
|
|
||||||
required:
|
|
||||||
- compatible
|
|
||||||
- reg
|
|
||||||
|
|
||||||
allOf:
|
|
||||||
- if:
|
|
||||||
properties:
|
|
||||||
compatible:
|
|
||||||
contains:
|
|
||||||
enum:
|
|
||||||
- snps,ddrc-3.80a
|
|
||||||
- xlnx,zynqmp-ddrc-2.40a
|
|
||||||
then:
|
|
||||||
required:
|
|
||||||
- interrupts
|
|
||||||
else:
|
|
||||||
properties:
|
|
||||||
interrupts: false
|
|
||||||
|
|
||||||
additionalProperties: false
|
|
||||||
|
|
||||||
examples:
|
|
||||||
- |
|
|
||||||
memory-controller@f8006000 {
|
|
||||||
compatible = "xlnx,zynq-ddrc-a05";
|
|
||||||
reg = <0xf8006000 0x1000>;
|
|
||||||
};
|
|
||||||
|
|
||||||
- |
|
|
||||||
axi {
|
|
||||||
#address-cells = <2>;
|
|
||||||
#size-cells = <2>;
|
|
||||||
|
|
||||||
memory-controller@fd070000 {
|
|
||||||
compatible = "xlnx,zynqmp-ddrc-2.40a";
|
|
||||||
reg = <0x0 0xfd070000 0x0 0x30000>;
|
|
||||||
interrupt-parent = <&gic>;
|
|
||||||
interrupts = <0 112 4>;
|
|
||||||
};
|
|
||||||
};
|
|
|
@ -0,0 +1,38 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only OR BSD-2-Clause
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/memory-controllers/xlnx,zynq-ddrc-a05.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: Zynq A05 DDR Memory Controller
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Krzysztof Kozlowski <krzk@kernel.org>
|
||||||
|
- Manish Narani <manish.narani@xilinx.com>
|
||||||
|
- Michal Simek <michal.simek@xilinx.com>
|
||||||
|
|
||||||
|
description:
|
||||||
|
The Zynq DDR ECC controller has an optional ECC support in half-bus width
|
||||||
|
(16-bit) configuration. It is cappable of correcting single bit ECC errors
|
||||||
|
and detecting double bit ECC errors.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
const: xlnx,zynq-ddrc-a05
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
memory-controller@f8006000 {
|
||||||
|
compatible = "xlnx,zynq-ddrc-a05";
|
||||||
|
reg = <0xf8006000 0x1000>;
|
||||||
|
};
|
||||||
|
...
|
|
@ -40,6 +40,8 @@ properties:
|
||||||
- allwinner,sun50i-a64-system-controller
|
- allwinner,sun50i-a64-system-controller
|
||||||
- brcm,cru-clkset
|
- brcm,cru-clkset
|
||||||
- freecom,fsg-cs2-system-controller
|
- freecom,fsg-cs2-system-controller
|
||||||
|
- fsl,imx93-aonmix-ns-syscfg
|
||||||
|
- fsl,imx93-wakeupmix-syscfg
|
||||||
- hisilicon,dsa-subctrl
|
- hisilicon,dsa-subctrl
|
||||||
- hisilicon,hi6220-sramctrl
|
- hisilicon,hi6220-sramctrl
|
||||||
- hisilicon,pcie-sas-subctrl
|
- hisilicon,pcie-sas-subctrl
|
||||||
|
|
|
@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
title: Mediatek Power Domains Controller
|
title: Mediatek Power Domains Controller
|
||||||
|
|
||||||
maintainers:
|
maintainers:
|
||||||
- Weiyi Lu <weiyi.lu@mediatek.com>
|
- MandyJH Liu <mandyjh.liu@mediatek.com>
|
||||||
- Matthias Brugger <mbrugger@suse.com>
|
- Matthias Brugger <mbrugger@suse.com>
|
||||||
|
|
||||||
description: |
|
description: |
|
||||||
|
@ -19,7 +19,7 @@ description: |
|
||||||
|
|
||||||
properties:
|
properties:
|
||||||
$nodename:
|
$nodename:
|
||||||
const: power-controller
|
pattern: '^power-controller(@[0-9a-f]+)?$'
|
||||||
|
|
||||||
compatible:
|
compatible:
|
||||||
enum:
|
enum:
|
||||||
|
@ -42,6 +42,23 @@ properties:
|
||||||
|
|
||||||
patternProperties:
|
patternProperties:
|
||||||
"^power-domain@[0-9a-f]+$":
|
"^power-domain@[0-9a-f]+$":
|
||||||
|
$ref: "#/$defs/power-domain-node"
|
||||||
|
patternProperties:
|
||||||
|
"^power-domain@[0-9a-f]+$":
|
||||||
|
$ref: "#/$defs/power-domain-node"
|
||||||
|
patternProperties:
|
||||||
|
"^power-domain@[0-9a-f]+$":
|
||||||
|
$ref: "#/$defs/power-domain-node"
|
||||||
|
patternProperties:
|
||||||
|
"^power-domain@[0-9a-f]+$":
|
||||||
|
$ref: "#/$defs/power-domain-node"
|
||||||
|
unevaluatedProperties: false
|
||||||
|
unevaluatedProperties: false
|
||||||
|
unevaluatedProperties: false
|
||||||
|
unevaluatedProperties: false
|
||||||
|
|
||||||
|
$defs:
|
||||||
|
power-domain-node:
|
||||||
type: object
|
type: object
|
||||||
description: |
|
description: |
|
||||||
Represents the power domains within the power controller node as documented
|
Represents the power domains within the power controller node as documented
|
||||||
|
@ -100,123 +117,9 @@ patternProperties:
|
||||||
$ref: /schemas/types.yaml#/definitions/phandle
|
$ref: /schemas/types.yaml#/definitions/phandle
|
||||||
description: phandle to the device containing the SMI register range.
|
description: phandle to the device containing the SMI register range.
|
||||||
|
|
||||||
patternProperties:
|
|
||||||
"^power-domain@[0-9a-f]+$":
|
|
||||||
type: object
|
|
||||||
description: |
|
|
||||||
Represents a power domain child within a power domain parent node.
|
|
||||||
|
|
||||||
properties:
|
|
||||||
|
|
||||||
'#power-domain-cells':
|
|
||||||
description:
|
|
||||||
Must be 0 for nodes representing a single PM domain and 1 for nodes
|
|
||||||
providing multiple PM domains.
|
|
||||||
|
|
||||||
'#address-cells':
|
|
||||||
const: 1
|
|
||||||
|
|
||||||
'#size-cells':
|
|
||||||
const: 0
|
|
||||||
|
|
||||||
reg:
|
|
||||||
maxItems: 1
|
|
||||||
|
|
||||||
clocks:
|
|
||||||
description: |
|
|
||||||
A number of phandles to clocks that need to be enabled during domain
|
|
||||||
power-up sequencing.
|
|
||||||
|
|
||||||
clock-names:
|
|
||||||
description: |
|
|
||||||
List of names of clocks, in order to match the power-up sequencing
|
|
||||||
for each power domain we need to group the clocks by name. BASIC
|
|
||||||
clocks need to be enabled before enabling the corresponding power
|
|
||||||
domain, and should not have a '-' in their name (i.e mm, mfg, venc).
|
|
||||||
SUSBYS clocks need to be enabled before releasing the bus protection,
|
|
||||||
and should contain a '-' in their name (i.e mm-0, isp-0, cam-0).
|
|
||||||
|
|
||||||
In order to follow properly the power-up sequencing, the clocks must
|
|
||||||
be specified by order, adding first the BASIC clocks followed by the
|
|
||||||
SUSBSYS clocks.
|
|
||||||
|
|
||||||
domain-supply:
|
|
||||||
description: domain regulator supply.
|
|
||||||
|
|
||||||
mediatek,infracfg:
|
|
||||||
$ref: /schemas/types.yaml#/definitions/phandle
|
|
||||||
description: phandle to the device containing the INFRACFG register range.
|
|
||||||
|
|
||||||
mediatek,smi:
|
|
||||||
$ref: /schemas/types.yaml#/definitions/phandle
|
|
||||||
description: phandle to the device containing the SMI register range.
|
|
||||||
|
|
||||||
patternProperties:
|
|
||||||
"^power-domain@[0-9a-f]+$":
|
|
||||||
type: object
|
|
||||||
description: |
|
|
||||||
Represents a power domain child within a power domain parent node.
|
|
||||||
|
|
||||||
properties:
|
|
||||||
|
|
||||||
'#power-domain-cells':
|
|
||||||
description:
|
|
||||||
Must be 0 for nodes representing a single PM domain and 1 for nodes
|
|
||||||
providing multiple PM domains.
|
|
||||||
|
|
||||||
'#address-cells':
|
|
||||||
const: 1
|
|
||||||
|
|
||||||
'#size-cells':
|
|
||||||
const: 0
|
|
||||||
|
|
||||||
reg:
|
|
||||||
maxItems: 1
|
|
||||||
|
|
||||||
clocks:
|
|
||||||
description: |
|
|
||||||
A number of phandles to clocks that need to be enabled during domain
|
|
||||||
power-up sequencing.
|
|
||||||
|
|
||||||
clock-names:
|
|
||||||
description: |
|
|
||||||
List of names of clocks, in order to match the power-up sequencing
|
|
||||||
for each power domain we need to group the clocks by name. BASIC
|
|
||||||
clocks need to be enabled before enabling the corresponding power
|
|
||||||
domain, and should not have a '-' in their name (i.e mm, mfg, venc).
|
|
||||||
SUSBYS clocks need to be enabled before releasing the bus protection,
|
|
||||||
and should contain a '-' in their name (i.e mm-0, isp-0, cam-0).
|
|
||||||
|
|
||||||
In order to follow properly the power-up sequencing, the clocks must
|
|
||||||
be specified by order, adding first the BASIC clocks followed by the
|
|
||||||
SUSBSYS clocks.
|
|
||||||
|
|
||||||
domain-supply:
|
|
||||||
description: domain regulator supply.
|
|
||||||
|
|
||||||
mediatek,infracfg:
|
|
||||||
$ref: /schemas/types.yaml#/definitions/phandle
|
|
||||||
description: phandle to the device containing the INFRACFG register range.
|
|
||||||
|
|
||||||
mediatek,smi:
|
|
||||||
$ref: /schemas/types.yaml#/definitions/phandle
|
|
||||||
description: phandle to the device containing the SMI register range.
|
|
||||||
|
|
||||||
required:
|
|
||||||
- reg
|
|
||||||
|
|
||||||
additionalProperties: false
|
|
||||||
|
|
||||||
required:
|
|
||||||
- reg
|
|
||||||
|
|
||||||
additionalProperties: false
|
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- reg
|
- reg
|
||||||
|
|
||||||
additionalProperties: false
|
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,7 @@ properties:
|
||||||
- qcom,sm6115-rpmpd
|
- qcom,sm6115-rpmpd
|
||||||
- qcom,sm6125-rpmpd
|
- qcom,sm6125-rpmpd
|
||||||
- qcom,sm6350-rpmhpd
|
- qcom,sm6350-rpmhpd
|
||||||
|
- qcom,sm6375-rpmpd
|
||||||
- qcom,sm8150-rpmhpd
|
- qcom,sm8150-rpmhpd
|
||||||
- qcom,sm8250-rpmhpd
|
- qcom,sm8250-rpmhpd
|
||||||
- qcom,sm8350-rpmhpd
|
- qcom,sm8350-rpmhpd
|
||||||
|
|
|
@ -41,6 +41,8 @@ properties:
|
||||||
- rockchip,rk3368-power-controller
|
- rockchip,rk3368-power-controller
|
||||||
- rockchip,rk3399-power-controller
|
- rockchip,rk3399-power-controller
|
||||||
- rockchip,rk3568-power-controller
|
- rockchip,rk3568-power-controller
|
||||||
|
- rockchip,rk3588-power-controller
|
||||||
|
- rockchip,rv1126-power-controller
|
||||||
|
|
||||||
"#power-domain-cells":
|
"#power-domain-cells":
|
||||||
const: 1
|
const: 1
|
||||||
|
@ -119,6 +121,8 @@ $defs:
|
||||||
"include/dt-bindings/power/rk3368-power.h"
|
"include/dt-bindings/power/rk3368-power.h"
|
||||||
"include/dt-bindings/power/rk3399-power.h"
|
"include/dt-bindings/power/rk3399-power.h"
|
||||||
"include/dt-bindings/power/rk3568-power.h"
|
"include/dt-bindings/power/rk3568-power.h"
|
||||||
|
"include/dt-bindings/power/rk3588-power.h"
|
||||||
|
"include/dt-bindings/power/rockchip,rv1126-power.h"
|
||||||
|
|
||||||
clocks:
|
clocks:
|
||||||
minItems: 1
|
minItems: 1
|
||||||
|
|
|
@ -58,6 +58,7 @@ properties:
|
||||||
- rockchip,rk3568-pmu-io-voltage-domain
|
- rockchip,rk3568-pmu-io-voltage-domain
|
||||||
- rockchip,rv1108-io-voltage-domain
|
- rockchip,rv1108-io-voltage-domain
|
||||||
- rockchip,rv1108-pmu-io-voltage-domain
|
- rockchip,rv1108-pmu-io-voltage-domain
|
||||||
|
- rockchip,rv1126-pmu-io-voltage-domain
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
|
@ -78,6 +79,7 @@ allOf:
|
||||||
- $ref: "#/$defs/rk3568-pmu"
|
- $ref: "#/$defs/rk3568-pmu"
|
||||||
- $ref: "#/$defs/rv1108"
|
- $ref: "#/$defs/rv1108"
|
||||||
- $ref: "#/$defs/rv1108-pmu"
|
- $ref: "#/$defs/rv1108-pmu"
|
||||||
|
- $ref: "#/$defs/rv1126-pmu"
|
||||||
|
|
||||||
$defs:
|
$defs:
|
||||||
px30:
|
px30:
|
||||||
|
@ -344,6 +346,34 @@ $defs:
|
||||||
pmu-supply:
|
pmu-supply:
|
||||||
description: The supply connected to PMUIO_VDD.
|
description: The supply connected to PMUIO_VDD.
|
||||||
|
|
||||||
|
rv1126-pmu:
|
||||||
|
if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
const: rockchip,rv1126-pmu-io-voltage-domain
|
||||||
|
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
vccio1-supply:
|
||||||
|
description: The supply connected to VCCIO1.
|
||||||
|
vccio2-supply:
|
||||||
|
description: The supply connected to VCCIO2.
|
||||||
|
vccio3-supply:
|
||||||
|
description: The supply connected to VCCIO3.
|
||||||
|
vccio4-supply:
|
||||||
|
description: The supply connected to VCCIO4.
|
||||||
|
vccio5-supply:
|
||||||
|
description: The supply connected to VCCIO5.
|
||||||
|
vccio6-supply:
|
||||||
|
description: The supply connected to VCCIO6.
|
||||||
|
vccio7-supply:
|
||||||
|
description: The supply connected to VCCIO7.
|
||||||
|
pmuio0-supply:
|
||||||
|
description: The supply connected to PMUIO0.
|
||||||
|
pmuio1-supply:
|
||||||
|
description: The supply connected to PMUIO1.
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
- |
|
- |
|
||||||
io-domains {
|
io-domains {
|
||||||
|
|
|
@ -27,25 +27,22 @@ properties:
|
||||||
const: 1
|
const: 1
|
||||||
|
|
||||||
power-domains:
|
power-domains:
|
||||||
minItems: 4
|
|
||||||
maxItems: 4
|
maxItems: 4
|
||||||
|
|
||||||
power-domain-names:
|
power-domain-names:
|
||||||
items:
|
maxItems: 4
|
||||||
- const: bus
|
|
||||||
- const: g1
|
|
||||||
- const: g2
|
|
||||||
- const: h1
|
|
||||||
|
|
||||||
clocks:
|
clocks:
|
||||||
minItems: 3
|
|
||||||
maxItems: 3
|
maxItems: 3
|
||||||
|
|
||||||
clock-names:
|
clock-names:
|
||||||
items:
|
maxItems: 3
|
||||||
- const: g1
|
|
||||||
- const: g2
|
interconnects:
|
||||||
- const: h1
|
maxItems: 3
|
||||||
|
|
||||||
|
interconnect-names:
|
||||||
|
maxItems: 3
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
|
@ -55,6 +52,97 @@ required:
|
||||||
- clocks
|
- clocks
|
||||||
- clock-names
|
- clock-names
|
||||||
|
|
||||||
|
allOf:
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
const: fsl,imx8mm-vpu-blk-ctrl
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
power-domains:
|
||||||
|
items:
|
||||||
|
- description: bus power domain
|
||||||
|
- description: G1 decoder power domain
|
||||||
|
- description: G2 decoder power domain
|
||||||
|
- description: H1 encoder power domain
|
||||||
|
|
||||||
|
power-domain-names:
|
||||||
|
items:
|
||||||
|
- const: bus
|
||||||
|
- const: g1
|
||||||
|
- const: g2
|
||||||
|
- const: h1
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
items:
|
||||||
|
- description: G1 decoder clk
|
||||||
|
- description: G2 decoder clk
|
||||||
|
- description: H1 encoder clk
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: g1
|
||||||
|
- const: g2
|
||||||
|
- const: h1
|
||||||
|
|
||||||
|
interconnects:
|
||||||
|
items:
|
||||||
|
- description: G1 decoder interconnect
|
||||||
|
- description: G2 decoder interconnect
|
||||||
|
- description: H1 encoder power domain
|
||||||
|
|
||||||
|
interconnect-names:
|
||||||
|
items:
|
||||||
|
- const: g1
|
||||||
|
- const: g2
|
||||||
|
- const: h1
|
||||||
|
|
||||||
|
- if:
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
contains:
|
||||||
|
const: fsl,imx8mp-vpu-blk-ctrl
|
||||||
|
then:
|
||||||
|
properties:
|
||||||
|
power-domains:
|
||||||
|
items:
|
||||||
|
- description: bus power domain
|
||||||
|
- description: G1 decoder power domain
|
||||||
|
- description: G2 decoder power domain
|
||||||
|
- description: VC8000E encoder power domain
|
||||||
|
|
||||||
|
power-domain-names:
|
||||||
|
items:
|
||||||
|
- const: bus
|
||||||
|
- const: g1
|
||||||
|
- const: g2
|
||||||
|
- const: vc8000e
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
items:
|
||||||
|
- description: G1 decoder clk
|
||||||
|
- description: G2 decoder clk
|
||||||
|
- description: VC8000E encoder clk
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: g1
|
||||||
|
- const: g2
|
||||||
|
- const: vc8000e
|
||||||
|
|
||||||
|
interconnects:
|
||||||
|
items:
|
||||||
|
- description: G1 decoder interconnect
|
||||||
|
- description: G2 decoder interconnect
|
||||||
|
- description: VC8000E encoder interconnect
|
||||||
|
|
||||||
|
interconnect-names:
|
||||||
|
items:
|
||||||
|
- const: g1
|
||||||
|
- const: g2
|
||||||
|
- const: vc8000e
|
||||||
|
|
||||||
additionalProperties: false
|
additionalProperties: false
|
||||||
|
|
||||||
examples:
|
examples:
|
||||||
|
|
|
@ -52,6 +52,15 @@ properties:
|
||||||
- const: ref_266m
|
- const: ref_266m
|
||||||
- const: ref_24m
|
- const: ref_24m
|
||||||
|
|
||||||
|
interconnects:
|
||||||
|
maxItems: 3
|
||||||
|
|
||||||
|
interconnect-names:
|
||||||
|
items:
|
||||||
|
- const: hrv
|
||||||
|
- const: lcdif-hdmi
|
||||||
|
- const: hdcp
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
|
|
|
@ -48,6 +48,16 @@ properties:
|
||||||
- const: usb
|
- const: usb
|
||||||
- const: pcie
|
- const: pcie
|
||||||
|
|
||||||
|
interconnects:
|
||||||
|
maxItems: 4
|
||||||
|
|
||||||
|
interconnect-names:
|
||||||
|
items:
|
||||||
|
- const: noc-pcie
|
||||||
|
- const: usb1
|
||||||
|
- const: usb2
|
||||||
|
- const: pcie
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
|
|
|
@ -64,6 +64,20 @@ properties:
|
||||||
- const: isp
|
- const: isp
|
||||||
- const: phy
|
- const: phy
|
||||||
|
|
||||||
|
interconnects:
|
||||||
|
maxItems: 8
|
||||||
|
|
||||||
|
interconnect-names:
|
||||||
|
items:
|
||||||
|
- const: lcdif-rd
|
||||||
|
- const: lcdif-wr
|
||||||
|
- const: isi0
|
||||||
|
- const: isi1
|
||||||
|
- const: isi2
|
||||||
|
- const: isp0
|
||||||
|
- const: isp1
|
||||||
|
- const: dwe
|
||||||
|
|
||||||
required:
|
required:
|
||||||
- compatible
|
- compatible
|
||||||
- reg
|
- reg
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/soc/imx/fsl,imx93-media-blk-ctrl.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: NXP i.MX93 Media blk-ctrl
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Peng Fan <peng.fan@nxp.com>
|
||||||
|
|
||||||
|
description:
|
||||||
|
The i.MX93 MEDIAMIX domain contains control and status registers known
|
||||||
|
as MEDIAMIX Block Control (MEDIAMIX BLK_CTRL). These registers include
|
||||||
|
clocking, reset, and miscellaneous top-level controls for peripherals
|
||||||
|
within the MEDIAMIX domain
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
items:
|
||||||
|
- const: fsl,imx93-media-blk-ctrl
|
||||||
|
- const: syscon
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
'#power-domain-cells':
|
||||||
|
const: 1
|
||||||
|
|
||||||
|
power-domains:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
maxItems: 10
|
||||||
|
|
||||||
|
clock-names:
|
||||||
|
items:
|
||||||
|
- const: apb
|
||||||
|
- const: axi
|
||||||
|
- const: nic
|
||||||
|
- const: disp
|
||||||
|
- const: cam
|
||||||
|
- const: pxp
|
||||||
|
- const: lcdif
|
||||||
|
- const: isi
|
||||||
|
- const: csi
|
||||||
|
- const: dsi
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- power-domains
|
||||||
|
- clocks
|
||||||
|
- clock-names
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/clock/imx93-clock.h>
|
||||||
|
#include <dt-bindings/power/fsl,imx93-power.h>
|
||||||
|
|
||||||
|
media_blk_ctrl: system-controller@4ac10000 {
|
||||||
|
compatible = "fsl,imx93-media-blk-ctrl", "syscon";
|
||||||
|
reg = <0x4ac10000 0x10000>;
|
||||||
|
power-domains = <&mediamix>;
|
||||||
|
clocks = <&clk IMX93_CLK_MEDIA_APB>,
|
||||||
|
<&clk IMX93_CLK_MEDIA_AXI>,
|
||||||
|
<&clk IMX93_CLK_NIC_MEDIA_GATE>,
|
||||||
|
<&clk IMX93_CLK_MEDIA_DISP_PIX>,
|
||||||
|
<&clk IMX93_CLK_CAM_PIX>,
|
||||||
|
<&clk IMX93_CLK_PXP_GATE>,
|
||||||
|
<&clk IMX93_CLK_LCDIF_GATE>,
|
||||||
|
<&clk IMX93_CLK_ISI_GATE>,
|
||||||
|
<&clk IMX93_CLK_MIPI_CSI_GATE>,
|
||||||
|
<&clk IMX93_CLK_MIPI_DSI_GATE>;
|
||||||
|
clock-names = "apb", "axi", "nic", "disp", "cam",
|
||||||
|
"pxp", "lcdif", "isi", "csi", "dsi";
|
||||||
|
#power-domain-cells = <1>;
|
||||||
|
};
|
96
Documentation/devicetree/bindings/soc/imx/fsl,imx93-src.yaml
Normal file
96
Documentation/devicetree/bindings/soc/imx/fsl,imx93-src.yaml
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
|
||||||
|
%YAML 1.2
|
||||||
|
---
|
||||||
|
$id: http://devicetree.org/schemas/soc/imx/fsl,imx93-src.yaml#
|
||||||
|
$schema: http://devicetree.org/meta-schemas/core.yaml#
|
||||||
|
|
||||||
|
title: NXP i.MX93 System Reset Controller
|
||||||
|
|
||||||
|
maintainers:
|
||||||
|
- Peng Fan <peng.fan@nxp.com>
|
||||||
|
|
||||||
|
description: |
|
||||||
|
The System Reset Controller (SRC) is responsible for the generation of
|
||||||
|
all the system reset signals and boot argument latching.
|
||||||
|
|
||||||
|
Its main functions are as follows,
|
||||||
|
- Deals with all global system reset sources from other modules,
|
||||||
|
and generates global system reset.
|
||||||
|
- Responsible for power gating of MIXs (Slices) and their memory
|
||||||
|
low power control.
|
||||||
|
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
items:
|
||||||
|
- const: fsl,imx93-src
|
||||||
|
- const: syscon
|
||||||
|
|
||||||
|
reg:
|
||||||
|
maxItems: 1
|
||||||
|
|
||||||
|
ranges: true
|
||||||
|
|
||||||
|
'#address-cells':
|
||||||
|
const: 1
|
||||||
|
|
||||||
|
'#size-cells':
|
||||||
|
const: 1
|
||||||
|
|
||||||
|
patternProperties:
|
||||||
|
"power-domain@[0-9a-f]+$":
|
||||||
|
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
compatible:
|
||||||
|
items:
|
||||||
|
- const: fsl,imx93-src-slice
|
||||||
|
|
||||||
|
'#power-domain-cells':
|
||||||
|
const: 0
|
||||||
|
|
||||||
|
reg:
|
||||||
|
items:
|
||||||
|
- description: mix slice register region
|
||||||
|
- description: mem slice register region
|
||||||
|
|
||||||
|
clocks:
|
||||||
|
description: |
|
||||||
|
A number of phandles to clocks that need to be enabled
|
||||||
|
during domain power-up sequencing to ensure reset
|
||||||
|
propagation into devices located inside this power domain.
|
||||||
|
minItems: 1
|
||||||
|
maxItems: 5
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- '#power-domain-cells'
|
||||||
|
- reg
|
||||||
|
|
||||||
|
required:
|
||||||
|
- compatible
|
||||||
|
- reg
|
||||||
|
- ranges
|
||||||
|
- '#address-cells'
|
||||||
|
- '#size-cells'
|
||||||
|
|
||||||
|
additionalProperties: false
|
||||||
|
|
||||||
|
examples:
|
||||||
|
- |
|
||||||
|
#include <dt-bindings/clock/imx93-clock.h>
|
||||||
|
|
||||||
|
system-controller@44460000 {
|
||||||
|
compatible = "fsl,imx93-src", "syscon";
|
||||||
|
reg = <0x44460000 0x10000>;
|
||||||
|
#address-cells = <1>;
|
||||||
|
#size-cells = <1>;
|
||||||
|
ranges;
|
||||||
|
|
||||||
|
mediamix: power-domain@0 {
|
||||||
|
compatible = "fsl,imx93-src-slice";
|
||||||
|
reg = <0x44462400 0x400>, <0x44465800 0x400>;
|
||||||
|
#power-domain-cells = <0>;
|
||||||
|
clocks = <&clk IMX93_CLK_MEDIA_AXI>,
|
||||||
|
<&clk IMX93_CLK_MEDIA_APB>;
|
||||||
|
};
|
||||||
|
};
|
|
@ -26,10 +26,12 @@ properties:
|
||||||
enum:
|
enum:
|
||||||
- mediatek,mt2701-disp-mutex
|
- mediatek,mt2701-disp-mutex
|
||||||
- mediatek,mt2712-disp-mutex
|
- mediatek,mt2712-disp-mutex
|
||||||
|
- mediatek,mt6795-disp-mutex
|
||||||
- mediatek,mt8167-disp-mutex
|
- mediatek,mt8167-disp-mutex
|
||||||
- mediatek,mt8173-disp-mutex
|
- mediatek,mt8173-disp-mutex
|
||||||
- mediatek,mt8183-disp-mutex
|
- mediatek,mt8183-disp-mutex
|
||||||
- mediatek,mt8186-disp-mutex
|
- mediatek,mt8186-disp-mutex
|
||||||
|
- mediatek,mt8186-mdp3-mutex
|
||||||
- mediatek,mt8192-disp-mutex
|
- mediatek,mt8192-disp-mutex
|
||||||
- mediatek,mt8195-disp-mutex
|
- mediatek,mt8195-disp-mutex
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,7 @@ Required properties in pwrap device node.
|
||||||
"mediatek,mt8173-pwrap" for MT8173 SoCs
|
"mediatek,mt8173-pwrap" for MT8173 SoCs
|
||||||
"mediatek,mt8183-pwrap" for MT8183 SoCs
|
"mediatek,mt8183-pwrap" for MT8183 SoCs
|
||||||
"mediatek,mt8186-pwrap" for MT8186 SoCs
|
"mediatek,mt8186-pwrap" for MT8186 SoCs
|
||||||
|
"mediatek,mt8188-pwrap", "mediatek,mt8195-pwrap" for MT8188 SoCs
|
||||||
"mediatek,mt8195-pwrap" for MT8195 SoCs
|
"mediatek,mt8195-pwrap" for MT8195 SoCs
|
||||||
"mediatek,mt8516-pwrap" for MT8516 SoCs
|
"mediatek,mt8516-pwrap" for MT8516 SoCs
|
||||||
- interrupts: IRQ for pwrap in SOC
|
- interrupts: IRQ for pwrap in SOC
|
||||||
|
|
|
@ -20,6 +20,7 @@ properties:
|
||||||
compatible:
|
compatible:
|
||||||
enum:
|
enum:
|
||||||
- qcom,rpmh-stats
|
- qcom,rpmh-stats
|
||||||
|
- qcom,sdm845-rpmh-stats
|
||||||
- qcom,rpm-stats
|
- qcom,rpm-stats
|
||||||
# For older RPM firmware versions with fixed offset for the sleep stats
|
# For older RPM firmware versions with fixed offset for the sleep stats
|
||||||
- qcom,apq8084-rpm-stats
|
- qcom,apq8084-rpm-stats
|
||||||
|
|
|
@ -16,9 +16,12 @@ properties:
|
||||||
- enum:
|
- enum:
|
||||||
- rockchip,rk3288-sgrf
|
- rockchip,rk3288-sgrf
|
||||||
- rockchip,rk3566-pipe-grf
|
- rockchip,rk3566-pipe-grf
|
||||||
|
- rockchip,rk3568-pcie3-phy-grf
|
||||||
- rockchip,rk3568-pipe-grf
|
- rockchip,rk3568-pipe-grf
|
||||||
- rockchip,rk3568-pipe-phy-grf
|
- rockchip,rk3568-pipe-phy-grf
|
||||||
- rockchip,rk3568-usb2phy-grf
|
- rockchip,rk3568-usb2phy-grf
|
||||||
|
- rockchip,rk3588-pcie3-phy-grf
|
||||||
|
- rockchip,rk3588-pcie3-pipe-grf
|
||||||
- rockchip,rv1108-usbgrf
|
- rockchip,rv1108-usbgrf
|
||||||
- const: syscon
|
- const: syscon
|
||||||
- items:
|
- items:
|
||||||
|
@ -28,6 +31,7 @@ properties:
|
||||||
- rockchip,px30-usb2phy-grf
|
- rockchip,px30-usb2phy-grf
|
||||||
- rockchip,rk3036-grf
|
- rockchip,rk3036-grf
|
||||||
- rockchip,rk3066-grf
|
- rockchip,rk3066-grf
|
||||||
|
- rockchip,rk3128-grf
|
||||||
- rockchip,rk3188-grf
|
- rockchip,rk3188-grf
|
||||||
- rockchip,rk3228-grf
|
- rockchip,rk3228-grf
|
||||||
- rockchip,rk3288-grf
|
- rockchip,rk3288-grf
|
||||||
|
@ -45,6 +49,8 @@ properties:
|
||||||
- rockchip,rk3568-pmugrf
|
- rockchip,rk3568-pmugrf
|
||||||
- rockchip,rv1108-grf
|
- rockchip,rv1108-grf
|
||||||
- rockchip,rv1108-pmugrf
|
- rockchip,rv1108-pmugrf
|
||||||
|
- rockchip,rv1126-grf
|
||||||
|
- rockchip,rv1126-pmugrf
|
||||||
- const: syscon
|
- const: syscon
|
||||||
- const: simple-mfd
|
- const: simple-mfd
|
||||||
|
|
||||||
|
@ -178,6 +184,7 @@ allOf:
|
||||||
contains:
|
contains:
|
||||||
enum:
|
enum:
|
||||||
- rockchip,px30-usb2phy-grf
|
- rockchip,px30-usb2phy-grf
|
||||||
|
- rockchip,rk3128-grf
|
||||||
- rockchip,rk3228-grf
|
- rockchip,rk3228-grf
|
||||||
- rockchip,rk3308-usb2phy-grf
|
- rockchip,rk3308-usb2phy-grf
|
||||||
- rockchip,rk3328-usb2phy-grf
|
- rockchip,rk3328-usb2phy-grf
|
||||||
|
|
15
MAINTAINERS
15
MAINTAINERS
|
@ -3125,6 +3125,8 @@ W: http://wiki.xilinx.com
|
||||||
T: git https://github.com/Xilinx/linux-xlnx.git
|
T: git https://github.com/Xilinx/linux-xlnx.git
|
||||||
F: Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml
|
F: Documentation/devicetree/bindings/i2c/cdns,i2c-r1p10.yaml
|
||||||
F: Documentation/devicetree/bindings/i2c/xlnx,xps-iic-2.00.a.yaml
|
F: Documentation/devicetree/bindings/i2c/xlnx,xps-iic-2.00.a.yaml
|
||||||
|
F: Documentation/devicetree/bindings/memory-controllers/snps,dw-umctl2-ddrc.yaml
|
||||||
|
F: Documentation/devicetree/bindings/memory-controllers/xlnx,zynq-ddrc-a05.yaml
|
||||||
F: Documentation/devicetree/bindings/spi/xlnx,zynq-qspi.yaml
|
F: Documentation/devicetree/bindings/spi/xlnx,zynq-qspi.yaml
|
||||||
F: arch/arm/mach-zynq/
|
F: arch/arm/mach-zynq/
|
||||||
F: drivers/clocksource/timer-cadence-ttc.c
|
F: drivers/clocksource/timer-cadence-ttc.c
|
||||||
|
@ -5407,8 +5409,8 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
|
||||||
F: drivers/cpuidle/cpuidle-big_little.c
|
F: drivers/cpuidle/cpuidle-big_little.c
|
||||||
|
|
||||||
CPUIDLE DRIVER - ARM EXYNOS
|
CPUIDLE DRIVER - ARM EXYNOS
|
||||||
M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
|
|
||||||
M: Daniel Lezcano <daniel.lezcano@linaro.org>
|
M: Daniel Lezcano <daniel.lezcano@linaro.org>
|
||||||
|
R: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||||
M: Kukjin Kim <kgene@kernel.org>
|
M: Kukjin Kim <kgene@kernel.org>
|
||||||
L: linux-pm@vger.kernel.org
|
L: linux-pm@vger.kernel.org
|
||||||
L: linux-samsung-soc@vger.kernel.org
|
L: linux-samsung-soc@vger.kernel.org
|
||||||
|
@ -12441,7 +12443,6 @@ F: drivers/power/supply/max77976_charger.c
|
||||||
|
|
||||||
MAXIM MUIC CHARGER DRIVERS FOR EXYNOS BASED BOARDS
|
MAXIM MUIC CHARGER DRIVERS FOR EXYNOS BASED BOARDS
|
||||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||||
M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
|
|
||||||
L: linux-pm@vger.kernel.org
|
L: linux-pm@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
B: mailto:linux-samsung-soc@vger.kernel.org
|
B: mailto:linux-samsung-soc@vger.kernel.org
|
||||||
|
@ -12453,7 +12454,6 @@ F: drivers/power/supply/max77693_charger.c
|
||||||
MAXIM PMIC AND MUIC DRIVERS FOR EXYNOS BASED BOARDS
|
MAXIM PMIC AND MUIC DRIVERS FOR EXYNOS BASED BOARDS
|
||||||
M: Chanwoo Choi <cw00.choi@samsung.com>
|
M: Chanwoo Choi <cw00.choi@samsung.com>
|
||||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||||
M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
|
|
||||||
L: linux-kernel@vger.kernel.org
|
L: linux-kernel@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
B: mailto:linux-samsung-soc@vger.kernel.org
|
B: mailto:linux-samsung-soc@vger.kernel.org
|
||||||
|
@ -16587,14 +16587,6 @@ T: git git://linuxtv.org/media_tree.git
|
||||||
F: drivers/media/usb/pwc/*
|
F: drivers/media/usb/pwc/*
|
||||||
F: include/trace/events/pwc.h
|
F: include/trace/events/pwc.h
|
||||||
|
|
||||||
PWM FAN DRIVER
|
|
||||||
M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
|
|
||||||
L: linux-hwmon@vger.kernel.org
|
|
||||||
S: Supported
|
|
||||||
F: Documentation/devicetree/bindings/hwmon/pwm-fan.txt
|
|
||||||
F: Documentation/hwmon/pwm-fan.rst
|
|
||||||
F: drivers/hwmon/pwm-fan.c
|
|
||||||
|
|
||||||
PWM IR Transmitter
|
PWM IR Transmitter
|
||||||
M: Sean Young <sean@mess.org>
|
M: Sean Young <sean@mess.org>
|
||||||
L: linux-media@vger.kernel.org
|
L: linux-media@vger.kernel.org
|
||||||
|
@ -18055,7 +18047,6 @@ F: drivers/platform/x86/samsung-laptop.c
|
||||||
|
|
||||||
SAMSUNG MULTIFUNCTION PMIC DEVICE DRIVERS
|
SAMSUNG MULTIFUNCTION PMIC DEVICE DRIVERS
|
||||||
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
M: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
|
||||||
M: Bartlomiej Zolnierkiewicz <b.zolnierkie@samsung.com>
|
|
||||||
L: linux-kernel@vger.kernel.org
|
L: linux-kernel@vger.kernel.org
|
||||||
L: linux-samsung-soc@vger.kernel.org
|
L: linux-samsung-soc@vger.kernel.org
|
||||||
S: Supported
|
S: Supported
|
||||||
|
|
|
@ -67,11 +67,7 @@
|
||||||
#if defined(CONFIG_ARCH_SA1100)
|
#if defined(CONFIG_ARCH_SA1100)
|
||||||
.macro loadsp, rb, tmp1, tmp2
|
.macro loadsp, rb, tmp1, tmp2
|
||||||
mov \rb, #0x80000000 @ physical base address
|
mov \rb, #0x80000000 @ physical base address
|
||||||
#ifdef CONFIG_DEBUG_LL_SER3
|
|
||||||
add \rb, \rb, #0x00050000 @ Ser3
|
|
||||||
#else
|
|
||||||
add \rb, \rb, #0x00010000 @ Ser1
|
add \rb, \rb, #0x00010000 @ Ser1
|
||||||
#endif
|
|
||||||
.endm
|
.endm
|
||||||
#else
|
#else
|
||||||
.macro loadsp, rb, tmp1, tmp2
|
.macro loadsp, rb, tmp1, tmp2
|
||||||
|
|
|
@ -85,7 +85,7 @@ static int wait_lpc_idle(void __iomem *mbase, unsigned int waitcnt)
|
||||||
ndelay(LPC_NSEC_PERWAIT);
|
ndelay(LPC_NSEC_PERWAIT);
|
||||||
} while (--waitcnt);
|
} while (--waitcnt);
|
||||||
|
|
||||||
return -ETIME;
|
return -ETIMEDOUT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -347,7 +347,7 @@ static int hisi_lpc_acpi_xlat_io_res(struct acpi_device *adev,
|
||||||
unsigned long sys_port;
|
unsigned long sys_port;
|
||||||
resource_size_t len = resource_size(res);
|
resource_size_t len = resource_size(res);
|
||||||
|
|
||||||
sys_port = logic_pio_trans_hwaddr(&host->fwnode, res->start, len);
|
sys_port = logic_pio_trans_hwaddr(acpi_fwnode_handle(host), res->start, len);
|
||||||
if (sys_port == ~0UL)
|
if (sys_port == ~0UL)
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
|
||||||
|
@ -472,9 +472,7 @@ static int hisi_lpc_acpi_clear_enumerated(struct acpi_device *adev, void *not_us
|
||||||
|
|
||||||
struct hisi_lpc_acpi_cell {
|
struct hisi_lpc_acpi_cell {
|
||||||
const char *hid;
|
const char *hid;
|
||||||
const char *name;
|
const struct platform_device_info *pdevinfo;
|
||||||
void *pdata;
|
|
||||||
size_t pdata_size;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void hisi_lpc_acpi_remove(struct device *hostdev)
|
static void hisi_lpc_acpi_remove(struct device *hostdev)
|
||||||
|
@ -505,28 +503,45 @@ static int hisi_lpc_acpi_add_child(struct acpi_device *child, void *data)
|
||||||
/* ipmi */
|
/* ipmi */
|
||||||
{
|
{
|
||||||
.hid = "IPI0001",
|
.hid = "IPI0001",
|
||||||
.name = "hisi-lpc-ipmi",
|
.pdevinfo = (struct platform_device_info []) {
|
||||||
|
{
|
||||||
|
.parent = hostdev,
|
||||||
|
.fwnode = acpi_fwnode_handle(child),
|
||||||
|
.name = "hisi-lpc-ipmi",
|
||||||
|
.id = PLATFORM_DEVID_AUTO,
|
||||||
|
.res = res,
|
||||||
|
.num_res = num_res,
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
/* 8250-compatible uart */
|
/* 8250-compatible uart */
|
||||||
{
|
{
|
||||||
.hid = "HISI1031",
|
.hid = "HISI1031",
|
||||||
.name = "serial8250",
|
.pdevinfo = (struct platform_device_info []) {
|
||||||
.pdata = (struct plat_serial8250_port []) {
|
|
||||||
{
|
{
|
||||||
.iobase = res->start,
|
.parent = hostdev,
|
||||||
.uartclk = 1843200,
|
.fwnode = acpi_fwnode_handle(child),
|
||||||
.iotype = UPIO_PORT,
|
.name = "serial8250",
|
||||||
.flags = UPF_BOOT_AUTOCONF,
|
.id = PLATFORM_DEVID_AUTO,
|
||||||
|
.res = res,
|
||||||
|
.num_res = num_res,
|
||||||
|
.data = (struct plat_serial8250_port []) {
|
||||||
|
{
|
||||||
|
.iobase = res->start,
|
||||||
|
.uartclk = 1843200,
|
||||||
|
.iotype = UPIO_PORT,
|
||||||
|
.flags = UPF_BOOT_AUTOCONF,
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
},
|
||||||
|
.size_data = 2 * sizeof(struct plat_serial8250_port),
|
||||||
},
|
},
|
||||||
{}
|
|
||||||
},
|
},
|
||||||
.pdata_size = 2 *
|
|
||||||
sizeof(struct plat_serial8250_port),
|
|
||||||
},
|
},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
for (; cell && cell->name; cell++) {
|
for (; cell && cell->hid; cell++) {
|
||||||
if (!strcmp(cell->hid, hid)) {
|
if (!strcmp(cell->hid, hid)) {
|
||||||
found = true;
|
found = true;
|
||||||
break;
|
break;
|
||||||
|
@ -540,31 +555,12 @@ static int hisi_lpc_acpi_add_child(struct acpi_device *child, void *data)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
pdev = platform_device_alloc(cell->name, PLATFORM_DEVID_AUTO);
|
pdev = platform_device_register_full(cell->pdevinfo);
|
||||||
if (!pdev)
|
if (IS_ERR(pdev))
|
||||||
return -ENOMEM;
|
return PTR_ERR(pdev);
|
||||||
|
|
||||||
pdev->dev.parent = hostdev;
|
|
||||||
ACPI_COMPANION_SET(&pdev->dev, child);
|
|
||||||
|
|
||||||
ret = platform_device_add_resources(pdev, res, num_res);
|
|
||||||
if (ret)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
ret = platform_device_add_data(pdev, cell->pdata, cell->pdata_size);
|
|
||||||
if (ret)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
ret = platform_device_add(pdev);
|
|
||||||
if (ret)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
acpi_device_set_enumerated(child);
|
acpi_device_set_enumerated(child);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
fail:
|
|
||||||
platform_device_put(pdev);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -589,11 +585,6 @@ static int hisi_lpc_acpi_probe(struct device *hostdev)
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct acpi_device_id hisi_lpc_acpi_match[] = {
|
|
||||||
{"HISI0191"},
|
|
||||||
{}
|
|
||||||
};
|
|
||||||
#else
|
#else
|
||||||
static int hisi_lpc_acpi_probe(struct device *dev)
|
static int hisi_lpc_acpi_probe(struct device *dev)
|
||||||
{
|
{
|
||||||
|
@ -615,11 +606,9 @@ static void hisi_lpc_acpi_remove(struct device *hostdev)
|
||||||
static int hisi_lpc_probe(struct platform_device *pdev)
|
static int hisi_lpc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct acpi_device *acpi_device = ACPI_COMPANION(dev);
|
|
||||||
struct logic_pio_hwaddr *range;
|
struct logic_pio_hwaddr *range;
|
||||||
struct hisi_lpc_dev *lpcdev;
|
struct hisi_lpc_dev *lpcdev;
|
||||||
resource_size_t io_end;
|
resource_size_t io_end;
|
||||||
struct resource *res;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
lpcdev = devm_kzalloc(dev, sizeof(*lpcdev), GFP_KERNEL);
|
lpcdev = devm_kzalloc(dev, sizeof(*lpcdev), GFP_KERNEL);
|
||||||
|
@ -628,8 +617,7 @@ static int hisi_lpc_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
spin_lock_init(&lpcdev->cycle_lock);
|
spin_lock_init(&lpcdev->cycle_lock);
|
||||||
|
|
||||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
lpcdev->membase = devm_platform_ioremap_resource(pdev, 0);
|
||||||
lpcdev->membase = devm_ioremap_resource(dev, res);
|
|
||||||
if (IS_ERR(lpcdev->membase))
|
if (IS_ERR(lpcdev->membase))
|
||||||
return PTR_ERR(lpcdev->membase);
|
return PTR_ERR(lpcdev->membase);
|
||||||
|
|
||||||
|
@ -637,7 +625,7 @@ static int hisi_lpc_probe(struct platform_device *pdev)
|
||||||
if (!range)
|
if (!range)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
range->fwnode = dev->fwnode;
|
range->fwnode = dev_fwnode(dev);
|
||||||
range->flags = LOGIC_PIO_INDIRECT;
|
range->flags = LOGIC_PIO_INDIRECT;
|
||||||
range->size = PIO_INDIRECT_SIZE;
|
range->size = PIO_INDIRECT_SIZE;
|
||||||
range->hostdata = lpcdev;
|
range->hostdata = lpcdev;
|
||||||
|
@ -651,7 +639,7 @@ static int hisi_lpc_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* register the LPC host PIO resources */
|
/* register the LPC host PIO resources */
|
||||||
if (acpi_device)
|
if (is_acpi_device_node(range->fwnode))
|
||||||
ret = hisi_lpc_acpi_probe(dev);
|
ret = hisi_lpc_acpi_probe(dev);
|
||||||
else
|
else
|
||||||
ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
|
ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
|
||||||
|
@ -672,11 +660,10 @@ static int hisi_lpc_probe(struct platform_device *pdev)
|
||||||
static int hisi_lpc_remove(struct platform_device *pdev)
|
static int hisi_lpc_remove(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct acpi_device *acpi_device = ACPI_COMPANION(dev);
|
|
||||||
struct hisi_lpc_dev *lpcdev = dev_get_drvdata(dev);
|
struct hisi_lpc_dev *lpcdev = dev_get_drvdata(dev);
|
||||||
struct logic_pio_hwaddr *range = lpcdev->io_host;
|
struct logic_pio_hwaddr *range = lpcdev->io_host;
|
||||||
|
|
||||||
if (acpi_device)
|
if (is_acpi_device_node(range->fwnode))
|
||||||
hisi_lpc_acpi_remove(dev);
|
hisi_lpc_acpi_remove(dev);
|
||||||
else
|
else
|
||||||
of_platform_depopulate(dev);
|
of_platform_depopulate(dev);
|
||||||
|
@ -692,11 +679,16 @@ static const struct of_device_id hisi_lpc_of_match[] = {
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct acpi_device_id hisi_lpc_acpi_match[] = {
|
||||||
|
{"HISI0191"},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
static struct platform_driver hisi_lpc_driver = {
|
static struct platform_driver hisi_lpc_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = DRV_NAME,
|
.name = DRV_NAME,
|
||||||
.of_match_table = hisi_lpc_of_match,
|
.of_match_table = hisi_lpc_of_match,
|
||||||
.acpi_match_table = ACPI_PTR(hisi_lpc_acpi_match),
|
.acpi_match_table = hisi_lpc_acpi_match,
|
||||||
},
|
},
|
||||||
.probe = hisi_lpc_probe,
|
.probe = hisi_lpc_probe,
|
||||||
.remove = hisi_lpc_remove,
|
.remove = hisi_lpc_remove,
|
||||||
|
|
|
@ -124,10 +124,8 @@ static bool psci_pd_try_set_osi_mode(void)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
ret = psci_set_osi_mode(true);
|
ret = psci_set_osi_mode(true);
|
||||||
if (ret) {
|
if (ret)
|
||||||
pr_warn("failed to enable OSI mode: %d\n", ret);
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,7 +167,8 @@ bool ffa_device_is_valid(struct ffa_device *ffa_dev)
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id)
|
struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id,
|
||||||
|
const struct ffa_ops *ops)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
|
@ -183,6 +184,7 @@ struct ffa_device *ffa_device_register(const uuid_t *uuid, int vm_id)
|
||||||
dev_set_name(&ffa_dev->dev, "arm-ffa-%04x", vm_id);
|
dev_set_name(&ffa_dev->dev, "arm-ffa-%04x", vm_id);
|
||||||
|
|
||||||
ffa_dev->vm_id = vm_id;
|
ffa_dev->vm_id = vm_id;
|
||||||
|
ffa_dev->ops = ops;
|
||||||
uuid_copy(&ffa_dev->uuid, uuid);
|
uuid_copy(&ffa_dev->uuid, uuid);
|
||||||
|
|
||||||
ret = device_register(&ffa_dev->dev);
|
ret = device_register(&ffa_dev->dev);
|
||||||
|
|
|
@ -163,6 +163,7 @@ struct ffa_drv_info {
|
||||||
struct mutex tx_lock; /* lock to protect Tx buffer */
|
struct mutex tx_lock; /* lock to protect Tx buffer */
|
||||||
void *rx_buffer;
|
void *rx_buffer;
|
||||||
void *tx_buffer;
|
void *tx_buffer;
|
||||||
|
bool mem_ops_native;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct ffa_drv_info *drv_info;
|
static struct ffa_drv_info *drv_info;
|
||||||
|
@ -263,18 +264,24 @@ static int ffa_rxtx_unmap(u16 vm_id)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define PARTITION_INFO_GET_RETURN_COUNT_ONLY BIT(0)
|
||||||
|
|
||||||
/* buffer must be sizeof(struct ffa_partition_info) * num_partitions */
|
/* buffer must be sizeof(struct ffa_partition_info) * num_partitions */
|
||||||
static int
|
static int
|
||||||
__ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
|
__ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
|
||||||
struct ffa_partition_info *buffer, int num_partitions)
|
struct ffa_partition_info *buffer, int num_partitions)
|
||||||
{
|
{
|
||||||
int count;
|
int idx, count, flags = 0, sz, buf_sz;
|
||||||
ffa_value_t partition_info;
|
ffa_value_t partition_info;
|
||||||
|
|
||||||
|
if (!buffer || !num_partitions) /* Just get the count for now */
|
||||||
|
flags = PARTITION_INFO_GET_RETURN_COUNT_ONLY;
|
||||||
|
|
||||||
mutex_lock(&drv_info->rx_lock);
|
mutex_lock(&drv_info->rx_lock);
|
||||||
invoke_ffa_fn((ffa_value_t){
|
invoke_ffa_fn((ffa_value_t){
|
||||||
.a0 = FFA_PARTITION_INFO_GET,
|
.a0 = FFA_PARTITION_INFO_GET,
|
||||||
.a1 = uuid0, .a2 = uuid1, .a3 = uuid2, .a4 = uuid3,
|
.a1 = uuid0, .a2 = uuid1, .a3 = uuid2, .a4 = uuid3,
|
||||||
|
.a5 = flags,
|
||||||
}, &partition_info);
|
}, &partition_info);
|
||||||
|
|
||||||
if (partition_info.a0 == FFA_ERROR) {
|
if (partition_info.a0 == FFA_ERROR) {
|
||||||
|
@ -284,8 +291,19 @@ __ffa_partition_info_get(u32 uuid0, u32 uuid1, u32 uuid2, u32 uuid3,
|
||||||
|
|
||||||
count = partition_info.a2;
|
count = partition_info.a2;
|
||||||
|
|
||||||
|
if (drv_info->version > FFA_VERSION_1_0) {
|
||||||
|
buf_sz = sz = partition_info.a3;
|
||||||
|
if (sz > sizeof(*buffer))
|
||||||
|
buf_sz = sizeof(*buffer);
|
||||||
|
} else {
|
||||||
|
/* FFA_VERSION_1_0 lacks size in the response */
|
||||||
|
buf_sz = sz = 8;
|
||||||
|
}
|
||||||
|
|
||||||
if (buffer && count <= num_partitions)
|
if (buffer && count <= num_partitions)
|
||||||
memcpy(buffer, drv_info->rx_buffer, sizeof(*buffer) * count);
|
for (idx = 0; idx < count; idx++)
|
||||||
|
memcpy(buffer + idx, drv_info->rx_buffer + idx * sz,
|
||||||
|
buf_sz);
|
||||||
|
|
||||||
ffa_rx_release();
|
ffa_rx_release();
|
||||||
|
|
||||||
|
@ -571,6 +589,39 @@ static int ffa_memory_reclaim(u64 g_handle, u32 flags)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int ffa_features(u32 func_feat_id, u32 input_props,
|
||||||
|
u32 *if_props_1, u32 *if_props_2)
|
||||||
|
{
|
||||||
|
ffa_value_t id;
|
||||||
|
|
||||||
|
if (!ARM_SMCCC_IS_FAST_CALL(func_feat_id) && input_props) {
|
||||||
|
pr_err("%s: Invalid Parameters: %x, %x", __func__,
|
||||||
|
func_feat_id, input_props);
|
||||||
|
return ffa_to_linux_errno(FFA_RET_INVALID_PARAMETERS);
|
||||||
|
}
|
||||||
|
|
||||||
|
invoke_ffa_fn((ffa_value_t){
|
||||||
|
.a0 = FFA_FEATURES, .a1 = func_feat_id, .a2 = input_props,
|
||||||
|
}, &id);
|
||||||
|
|
||||||
|
if (id.a0 == FFA_ERROR)
|
||||||
|
return ffa_to_linux_errno((int)id.a2);
|
||||||
|
|
||||||
|
if (if_props_1)
|
||||||
|
*if_props_1 = id.a2;
|
||||||
|
if (if_props_2)
|
||||||
|
*if_props_2 = id.a3;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void ffa_set_up_mem_ops_native_flag(void)
|
||||||
|
{
|
||||||
|
if (!ffa_features(FFA_FN_NATIVE(MEM_LEND), 0, NULL, NULL) ||
|
||||||
|
!ffa_features(FFA_FN_NATIVE(MEM_SHARE), 0, NULL, NULL))
|
||||||
|
drv_info->mem_ops_native = true;
|
||||||
|
}
|
||||||
|
|
||||||
static u32 ffa_api_version_get(void)
|
static u32 ffa_api_version_get(void)
|
||||||
{
|
{
|
||||||
return drv_info->version;
|
return drv_info->version;
|
||||||
|
@ -597,11 +648,19 @@ static int ffa_partition_info_get(const char *uuid_str,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ffa_mode_32bit_set(struct ffa_device *dev)
|
static void _ffa_mode_32bit_set(struct ffa_device *dev)
|
||||||
{
|
{
|
||||||
dev->mode_32bit = true;
|
dev->mode_32bit = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void ffa_mode_32bit_set(struct ffa_device *dev)
|
||||||
|
{
|
||||||
|
if (drv_info->version > FFA_VERSION_1_0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_ffa_mode_32bit_set(dev);
|
||||||
|
}
|
||||||
|
|
||||||
static int ffa_sync_send_receive(struct ffa_device *dev,
|
static int ffa_sync_send_receive(struct ffa_device *dev,
|
||||||
struct ffa_send_direct_data *data)
|
struct ffa_send_direct_data *data)
|
||||||
{
|
{
|
||||||
|
@ -609,17 +668,15 @@ static int ffa_sync_send_receive(struct ffa_device *dev,
|
||||||
dev->mode_32bit, data);
|
dev->mode_32bit, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int ffa_memory_share(struct ffa_mem_ops_args *args)
|
||||||
ffa_memory_share(struct ffa_device *dev, struct ffa_mem_ops_args *args)
|
|
||||||
{
|
{
|
||||||
if (dev->mode_32bit)
|
if (drv_info->mem_ops_native)
|
||||||
return ffa_memory_ops(FFA_MEM_SHARE, args);
|
return ffa_memory_ops(FFA_FN_NATIVE(MEM_SHARE), args);
|
||||||
|
|
||||||
return ffa_memory_ops(FFA_FN_NATIVE(MEM_SHARE), args);
|
return ffa_memory_ops(FFA_MEM_SHARE, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int ffa_memory_lend(struct ffa_mem_ops_args *args)
|
||||||
ffa_memory_lend(struct ffa_device *dev, struct ffa_mem_ops_args *args)
|
|
||||||
{
|
{
|
||||||
/* Note that upon a successful MEM_LEND request the caller
|
/* Note that upon a successful MEM_LEND request the caller
|
||||||
* must ensure that the memory region specified is not accessed
|
* must ensure that the memory region specified is not accessed
|
||||||
|
@ -628,36 +685,47 @@ ffa_memory_lend(struct ffa_device *dev, struct ffa_mem_ops_args *args)
|
||||||
* however on systems without a hypervisor the responsibility
|
* however on systems without a hypervisor the responsibility
|
||||||
* falls to the calling kernel driver to prevent access.
|
* falls to the calling kernel driver to prevent access.
|
||||||
*/
|
*/
|
||||||
if (dev->mode_32bit)
|
if (drv_info->mem_ops_native)
|
||||||
return ffa_memory_ops(FFA_MEM_LEND, args);
|
return ffa_memory_ops(FFA_FN_NATIVE(MEM_LEND), args);
|
||||||
|
|
||||||
return ffa_memory_ops(FFA_FN_NATIVE(MEM_LEND), args);
|
return ffa_memory_ops(FFA_MEM_LEND, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct ffa_dev_ops ffa_ops = {
|
static const struct ffa_info_ops ffa_drv_info_ops = {
|
||||||
.api_version_get = ffa_api_version_get,
|
.api_version_get = ffa_api_version_get,
|
||||||
.partition_info_get = ffa_partition_info_get,
|
.partition_info_get = ffa_partition_info_get,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct ffa_msg_ops ffa_drv_msg_ops = {
|
||||||
.mode_32bit_set = ffa_mode_32bit_set,
|
.mode_32bit_set = ffa_mode_32bit_set,
|
||||||
.sync_send_receive = ffa_sync_send_receive,
|
.sync_send_receive = ffa_sync_send_receive,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct ffa_mem_ops ffa_drv_mem_ops = {
|
||||||
.memory_reclaim = ffa_memory_reclaim,
|
.memory_reclaim = ffa_memory_reclaim,
|
||||||
.memory_share = ffa_memory_share,
|
.memory_share = ffa_memory_share,
|
||||||
.memory_lend = ffa_memory_lend,
|
.memory_lend = ffa_memory_lend,
|
||||||
};
|
};
|
||||||
|
|
||||||
const struct ffa_dev_ops *ffa_dev_ops_get(struct ffa_device *dev)
|
static const struct ffa_ops ffa_drv_ops = {
|
||||||
{
|
.info_ops = &ffa_drv_info_ops,
|
||||||
if (ffa_device_is_valid(dev))
|
.msg_ops = &ffa_drv_msg_ops,
|
||||||
return &ffa_ops;
|
.mem_ops = &ffa_drv_mem_ops,
|
||||||
|
};
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(ffa_dev_ops_get);
|
|
||||||
|
|
||||||
void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
|
void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
|
||||||
{
|
{
|
||||||
int count, idx;
|
int count, idx;
|
||||||
struct ffa_partition_info *pbuf, *tpbuf;
|
struct ffa_partition_info *pbuf, *tpbuf;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* FF-A v1.1 provides UUID for each partition as part of the discovery
|
||||||
|
* API, the discovered UUID must be populated in the device's UUID and
|
||||||
|
* there is no need to copy the same from the driver table.
|
||||||
|
*/
|
||||||
|
if (drv_info->version > FFA_VERSION_1_0)
|
||||||
|
return;
|
||||||
|
|
||||||
count = ffa_partition_probe(uuid, &pbuf);
|
count = ffa_partition_probe(uuid, &pbuf);
|
||||||
if (count <= 0)
|
if (count <= 0)
|
||||||
return;
|
return;
|
||||||
|
@ -671,6 +739,7 @@ void ffa_device_match_uuid(struct ffa_device *ffa_dev, const uuid_t *uuid)
|
||||||
static void ffa_setup_partitions(void)
|
static void ffa_setup_partitions(void)
|
||||||
{
|
{
|
||||||
int count, idx;
|
int count, idx;
|
||||||
|
uuid_t uuid;
|
||||||
struct ffa_device *ffa_dev;
|
struct ffa_device *ffa_dev;
|
||||||
struct ffa_partition_info *pbuf, *tpbuf;
|
struct ffa_partition_info *pbuf, *tpbuf;
|
||||||
|
|
||||||
|
@ -681,19 +750,24 @@ static void ffa_setup_partitions(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
for (idx = 0, tpbuf = pbuf; idx < count; idx++, tpbuf++) {
|
for (idx = 0, tpbuf = pbuf; idx < count; idx++, tpbuf++) {
|
||||||
/* Note that the &uuid_null parameter will require
|
import_uuid(&uuid, (u8 *)tpbuf->uuid);
|
||||||
|
|
||||||
|
/* Note that if the UUID will be uuid_null, that will require
|
||||||
* ffa_device_match() to find the UUID of this partition id
|
* ffa_device_match() to find the UUID of this partition id
|
||||||
* with help of ffa_device_match_uuid(). Once the FF-A spec
|
* with help of ffa_device_match_uuid(). FF-A v1.1 and above
|
||||||
* is updated to provide correct UUID here for each partition
|
* provides UUID here for each partition as part of the
|
||||||
* as part of the discovery API, we need to pass the
|
* discovery API and the same is passed.
|
||||||
* discovered UUID here instead.
|
|
||||||
*/
|
*/
|
||||||
ffa_dev = ffa_device_register(&uuid_null, tpbuf->id);
|
ffa_dev = ffa_device_register(&uuid, tpbuf->id, &ffa_drv_ops);
|
||||||
if (!ffa_dev) {
|
if (!ffa_dev) {
|
||||||
pr_err("%s: failed to register partition ID 0x%x\n",
|
pr_err("%s: failed to register partition ID 0x%x\n",
|
||||||
__func__, tpbuf->id);
|
__func__, tpbuf->id);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (drv_info->version > FFA_VERSION_1_0 &&
|
||||||
|
!(tpbuf->properties & FFA_PARTITION_AARCH64_EXEC))
|
||||||
|
_ffa_mode_32bit_set(ffa_dev);
|
||||||
}
|
}
|
||||||
kfree(pbuf);
|
kfree(pbuf);
|
||||||
}
|
}
|
||||||
|
@ -751,6 +825,8 @@ static int __init ffa_init(void)
|
||||||
|
|
||||||
ffa_setup_partitions();
|
ffa_setup_partitions();
|
||||||
|
|
||||||
|
ffa_set_up_mem_ops_native_flag();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
free_pages:
|
free_pages:
|
||||||
if (drv_info->tx_buffer)
|
if (drv_info->tx_buffer)
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include <linux/acpi.h>
|
#include <linux/acpi.h>
|
||||||
#include <linux/arm-smccc.h>
|
#include <linux/arm-smccc.h>
|
||||||
#include <linux/cpuidle.h>
|
#include <linux/cpuidle.h>
|
||||||
|
#include <linux/debugfs.h>
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/linkage.h>
|
#include <linux/linkage.h>
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
|
@ -163,6 +164,8 @@ int psci_set_osi_mode(bool enable)
|
||||||
PSCI_1_0_SUSPEND_MODE_PC;
|
PSCI_1_0_SUSPEND_MODE_PC;
|
||||||
|
|
||||||
err = invoke_psci_fn(PSCI_1_0_FN_SET_SUSPEND_MODE, suspend_mode, 0, 0);
|
err = invoke_psci_fn(PSCI_1_0_FN_SET_SUSPEND_MODE, suspend_mode, 0, 0);
|
||||||
|
if (err < 0)
|
||||||
|
pr_warn("failed to set %s mode: %d\n", enable ? "OSI" : "PC", err);
|
||||||
return psci_to_linux_errno(err);
|
return psci_to_linux_errno(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -324,12 +327,125 @@ static void psci_sys_poweroff(void)
|
||||||
invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
|
invoke_psci_fn(PSCI_0_2_FN_SYSTEM_OFF, 0, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __init psci_features(u32 psci_func_id)
|
static int psci_features(u32 psci_func_id)
|
||||||
{
|
{
|
||||||
return invoke_psci_fn(PSCI_1_0_FN_PSCI_FEATURES,
|
return invoke_psci_fn(PSCI_1_0_FN_PSCI_FEATURES,
|
||||||
psci_func_id, 0, 0);
|
psci_func_id, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_DEBUG_FS
|
||||||
|
|
||||||
|
#define PSCI_ID(ver, _name) \
|
||||||
|
{ .fn = PSCI_##ver##_FN_##_name, .name = #_name, }
|
||||||
|
#define PSCI_ID_NATIVE(ver, _name) \
|
||||||
|
{ .fn = PSCI_FN_NATIVE(ver, _name), .name = #_name, }
|
||||||
|
|
||||||
|
/* A table of all optional functions */
|
||||||
|
static const struct {
|
||||||
|
u32 fn;
|
||||||
|
const char *name;
|
||||||
|
} psci_fn_ids[] = {
|
||||||
|
PSCI_ID_NATIVE(0_2, MIGRATE),
|
||||||
|
PSCI_ID(0_2, MIGRATE_INFO_TYPE),
|
||||||
|
PSCI_ID_NATIVE(0_2, MIGRATE_INFO_UP_CPU),
|
||||||
|
PSCI_ID(1_0, CPU_FREEZE),
|
||||||
|
PSCI_ID_NATIVE(1_0, CPU_DEFAULT_SUSPEND),
|
||||||
|
PSCI_ID_NATIVE(1_0, NODE_HW_STATE),
|
||||||
|
PSCI_ID_NATIVE(1_0, SYSTEM_SUSPEND),
|
||||||
|
PSCI_ID(1_0, SET_SUSPEND_MODE),
|
||||||
|
PSCI_ID_NATIVE(1_0, STAT_RESIDENCY),
|
||||||
|
PSCI_ID_NATIVE(1_0, STAT_COUNT),
|
||||||
|
PSCI_ID_NATIVE(1_1, SYSTEM_RESET2),
|
||||||
|
PSCI_ID(1_1, MEM_PROTECT),
|
||||||
|
PSCI_ID_NATIVE(1_1, MEM_PROTECT_CHECK_RANGE),
|
||||||
|
};
|
||||||
|
|
||||||
|
static int psci_debugfs_read(struct seq_file *s, void *data)
|
||||||
|
{
|
||||||
|
int feature, type, i;
|
||||||
|
u32 ver;
|
||||||
|
|
||||||
|
ver = psci_ops.get_version();
|
||||||
|
seq_printf(s, "PSCIv%d.%d\n",
|
||||||
|
PSCI_VERSION_MAJOR(ver),
|
||||||
|
PSCI_VERSION_MINOR(ver));
|
||||||
|
|
||||||
|
/* PSCI_FEATURES is available only starting from 1.0 */
|
||||||
|
if (PSCI_VERSION_MAJOR(ver) < 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
feature = psci_features(ARM_SMCCC_VERSION_FUNC_ID);
|
||||||
|
if (feature != PSCI_RET_NOT_SUPPORTED) {
|
||||||
|
ver = invoke_psci_fn(ARM_SMCCC_VERSION_FUNC_ID, 0, 0, 0);
|
||||||
|
seq_printf(s, "SMC Calling Convention v%d.%d\n",
|
||||||
|
PSCI_VERSION_MAJOR(ver),
|
||||||
|
PSCI_VERSION_MINOR(ver));
|
||||||
|
} else {
|
||||||
|
seq_puts(s, "SMC Calling Convention v1.0 is assumed\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
feature = psci_features(PSCI_FN_NATIVE(0_2, CPU_SUSPEND));
|
||||||
|
if (feature < 0) {
|
||||||
|
seq_printf(s, "PSCI_FEATURES(CPU_SUSPEND) error (%d)\n", feature);
|
||||||
|
} else {
|
||||||
|
seq_printf(s, "OSI is %ssupported\n",
|
||||||
|
(feature & BIT(0)) ? "" : "not ");
|
||||||
|
seq_printf(s, "%s StateID format is used\n",
|
||||||
|
(feature & BIT(1)) ? "Extended" : "Original");
|
||||||
|
}
|
||||||
|
|
||||||
|
type = psci_ops.migrate_info_type();
|
||||||
|
if (type == PSCI_0_2_TOS_UP_MIGRATE ||
|
||||||
|
type == PSCI_0_2_TOS_UP_NO_MIGRATE) {
|
||||||
|
unsigned long cpuid;
|
||||||
|
|
||||||
|
seq_printf(s, "Trusted OS %smigrate capable\n",
|
||||||
|
type == PSCI_0_2_TOS_UP_NO_MIGRATE ? "not " : "");
|
||||||
|
cpuid = psci_migrate_info_up_cpu();
|
||||||
|
seq_printf(s, "Trusted OS resident on physical CPU 0x%lx (#%d)\n",
|
||||||
|
cpuid, resident_cpu);
|
||||||
|
} else if (type == PSCI_0_2_TOS_MP) {
|
||||||
|
seq_puts(s, "Trusted OS migration not required\n");
|
||||||
|
} else {
|
||||||
|
if (type != PSCI_RET_NOT_SUPPORTED)
|
||||||
|
seq_printf(s, "MIGRATE_INFO_TYPE returned unknown type (%d)\n", type);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(psci_fn_ids); i++) {
|
||||||
|
feature = psci_features(psci_fn_ids[i].fn);
|
||||||
|
if (feature == PSCI_RET_NOT_SUPPORTED)
|
||||||
|
continue;
|
||||||
|
if (feature < 0)
|
||||||
|
seq_printf(s, "PSCI_FEATURES(%s) error (%d)\n",
|
||||||
|
psci_fn_ids[i].name, feature);
|
||||||
|
else
|
||||||
|
seq_printf(s, "%s is supported\n", psci_fn_ids[i].name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int psci_debugfs_open(struct inode *inode, struct file *f)
|
||||||
|
{
|
||||||
|
return single_open(f, psci_debugfs_read, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations psci_debugfs_ops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.open = psci_debugfs_open,
|
||||||
|
.release = single_release,
|
||||||
|
.read = seq_read,
|
||||||
|
.llseek = seq_lseek
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init psci_debugfs_init(void)
|
||||||
|
{
|
||||||
|
return PTR_ERR_OR_ZERO(debugfs_create_file("psci", 0444, NULL, NULL,
|
||||||
|
&psci_debugfs_ops));
|
||||||
|
}
|
||||||
|
late_initcall(psci_debugfs_init)
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef CONFIG_CPU_IDLE
|
#ifdef CONFIG_CPU_IDLE
|
||||||
static int psci_suspend_finisher(unsigned long state)
|
static int psci_suspend_finisher(unsigned long state)
|
||||||
{
|
{
|
||||||
|
|
|
@ -129,8 +129,6 @@ extern int scm_legacy_call(struct device *dev, const struct qcom_scm_desc *desc,
|
||||||
#define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x03
|
#define QCOM_SCM_SMMU_CONFIG_ERRATA1 0x03
|
||||||
#define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x02
|
#define QCOM_SCM_SMMU_CONFIG_ERRATA1_CLIENT_ALL 0x02
|
||||||
|
|
||||||
extern void __qcom_scm_init(void);
|
|
||||||
|
|
||||||
/* common error codes */
|
/* common error codes */
|
||||||
#define QCOM_SCM_V2_EBUSY -12
|
#define QCOM_SCM_V2_EBUSY -12
|
||||||
#define QCOM_SCM_ENOMEM -5
|
#define QCOM_SCM_ENOMEM -5
|
||||||
|
|
|
@ -377,18 +377,11 @@ static ssize_t bpmp_debug_store(struct file *file, const char __user *buf,
|
||||||
if (!filename)
|
if (!filename)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
databuf = kmalloc(count, GFP_KERNEL);
|
databuf = memdup_user(buf, count);
|
||||||
if (!databuf)
|
if (IS_ERR(databuf))
|
||||||
return -ENOMEM;
|
return PTR_ERR(databuf);
|
||||||
|
|
||||||
if (copy_from_user(databuf, buf, count)) {
|
|
||||||
err = -EFAULT;
|
|
||||||
goto free_ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
err = mrq_debug_write(bpmp, filename, databuf, count);
|
err = mrq_debug_write(bpmp, filename, databuf, count);
|
||||||
|
|
||||||
free_ret:
|
|
||||||
kfree(databuf);
|
kfree(databuf);
|
||||||
|
|
||||||
return err ?: count;
|
return err ?: count;
|
||||||
|
|
|
@ -488,8 +488,8 @@ config I2C_BCM_KONA
|
||||||
|
|
||||||
config I2C_BRCMSTB
|
config I2C_BRCMSTB
|
||||||
tristate "BRCM Settop/DSL I2C controller"
|
tristate "BRCM Settop/DSL I2C controller"
|
||||||
depends on ARCH_BCM2835 || ARCH_BCM4908 || ARCH_BCMBCA || \
|
depends on ARCH_BCM2835 || ARCH_BCMBCA || ARCH_BRCMSTB || \
|
||||||
ARCH_BRCMSTB || BMIPS_GENERIC || COMPILE_TEST
|
BMIPS_GENERIC || COMPILE_TEST
|
||||||
default y
|
default y
|
||||||
help
|
help
|
||||||
If you say yes to this option, support will be included for the
|
If you say yes to this option, support will be included for the
|
||||||
|
|
|
@ -66,6 +66,15 @@ config BRCMSTB_DPFE
|
||||||
for the DRAM's temperature. Slower refresh rate means cooler RAM,
|
for the DRAM's temperature. Slower refresh rate means cooler RAM,
|
||||||
higher refresh rate means hotter RAM.
|
higher refresh rate means hotter RAM.
|
||||||
|
|
||||||
|
config BRCMSTB_MEMC
|
||||||
|
tristate "Broadcom STB MEMC driver"
|
||||||
|
default ARCH_BRCMSTB
|
||||||
|
depends on ARCH_BRCMSTB || COMPILE_TEST
|
||||||
|
help
|
||||||
|
This driver provides a way to configure the Broadcom STB memory
|
||||||
|
controller and specifically control the Self Refresh Power Down
|
||||||
|
(SRPD) inactivity timeout.
|
||||||
|
|
||||||
config BT1_L2_CTL
|
config BT1_L2_CTL
|
||||||
bool "Baikal-T1 CM2 L2-RAM Cache Control Block"
|
bool "Baikal-T1 CM2 L2-RAM Cache Control Block"
|
||||||
depends on MIPS_BAIKAL_T1 || COMPILE_TEST
|
depends on MIPS_BAIKAL_T1 || COMPILE_TEST
|
||||||
|
|
|
@ -11,6 +11,7 @@ obj-$(CONFIG_ARM_PL172_MPMC) += pl172.o
|
||||||
obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o
|
obj-$(CONFIG_ATMEL_SDRAMC) += atmel-sdramc.o
|
||||||
obj-$(CONFIG_ATMEL_EBI) += atmel-ebi.o
|
obj-$(CONFIG_ATMEL_EBI) += atmel-ebi.o
|
||||||
obj-$(CONFIG_BRCMSTB_DPFE) += brcmstb_dpfe.o
|
obj-$(CONFIG_BRCMSTB_DPFE) += brcmstb_dpfe.o
|
||||||
|
obj-$(CONFIG_BRCMSTB_MEMC) += brcmstb_memc.o
|
||||||
obj-$(CONFIG_BT1_L2_CTL) += bt1-l2-ctl.o
|
obj-$(CONFIG_BT1_L2_CTL) += bt1-l2-ctl.o
|
||||||
obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
|
obj-$(CONFIG_TI_AEMIF) += ti-aemif.o
|
||||||
obj-$(CONFIG_TI_EMIF) += emif.o
|
obj-$(CONFIG_TI_EMIF) += emif.o
|
||||||
|
|
301
drivers/memory/brcmstb_memc.c
Normal file
301
drivers/memory/brcmstb_memc.c
Normal file
|
@ -0,0 +1,301 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* DDR Self-Refresh Power Down (SRPD) support for Broadcom STB SoCs
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
|
#define REG_MEMC_CNTRLR_CONFIG 0x00
|
||||||
|
#define CNTRLR_CONFIG_LPDDR4_SHIFT 5
|
||||||
|
#define CNTRLR_CONFIG_MASK 0xf
|
||||||
|
#define REG_MEMC_SRPD_CFG_21 0x20
|
||||||
|
#define REG_MEMC_SRPD_CFG_20 0x34
|
||||||
|
#define REG_MEMC_SRPD_CFG_1x 0x3c
|
||||||
|
#define INACT_COUNT_SHIFT 0
|
||||||
|
#define INACT_COUNT_MASK 0xffff
|
||||||
|
#define SRPD_EN_SHIFT 16
|
||||||
|
|
||||||
|
struct brcmstb_memc_data {
|
||||||
|
u32 srpd_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct brcmstb_memc {
|
||||||
|
struct device *dev;
|
||||||
|
void __iomem *ddr_ctrl;
|
||||||
|
unsigned int timeout_cycles;
|
||||||
|
u32 frequency;
|
||||||
|
u32 srpd_offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int brcmstb_memc_uses_lpddr4(struct brcmstb_memc *memc)
|
||||||
|
{
|
||||||
|
void __iomem *config = memc->ddr_ctrl + REG_MEMC_CNTRLR_CONFIG;
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
reg = readl_relaxed(config) & CNTRLR_CONFIG_MASK;
|
||||||
|
|
||||||
|
return reg == CNTRLR_CONFIG_LPDDR4_SHIFT;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int brcmstb_memc_srpd_config(struct brcmstb_memc *memc,
|
||||||
|
unsigned int cycles)
|
||||||
|
{
|
||||||
|
void __iomem *cfg = memc->ddr_ctrl + memc->srpd_offset;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
/* Max timeout supported in HW */
|
||||||
|
if (cycles > INACT_COUNT_MASK)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
memc->timeout_cycles = cycles;
|
||||||
|
|
||||||
|
val = (cycles << INACT_COUNT_SHIFT) & INACT_COUNT_MASK;
|
||||||
|
if (cycles)
|
||||||
|
val |= BIT(SRPD_EN_SHIFT);
|
||||||
|
|
||||||
|
writel_relaxed(val, cfg);
|
||||||
|
/* Ensure the write is committed to the controller */
|
||||||
|
(void)readl_relaxed(cfg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t frequency_show(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct brcmstb_memc *memc = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
return sprintf(buf, "%d\n", memc->frequency);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t srpd_show(struct device *dev,
|
||||||
|
struct device_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
struct brcmstb_memc *memc = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
return sprintf(buf, "%d\n", memc->timeout_cycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t srpd_store(struct device *dev, struct device_attribute *attr,
|
||||||
|
const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct brcmstb_memc *memc = dev_get_drvdata(dev);
|
||||||
|
unsigned int val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Cannot change the inactivity timeout on LPDDR4 chips because the
|
||||||
|
* dynamic tuning process will also get affected by the inactivity
|
||||||
|
* timeout, thus making it non functional.
|
||||||
|
*/
|
||||||
|
if (brcmstb_memc_uses_lpddr4(memc))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
ret = kstrtouint(buf, 10, &val);
|
||||||
|
if (ret < 0)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
ret = brcmstb_memc_srpd_config(memc, val);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEVICE_ATTR_RO(frequency);
|
||||||
|
static DEVICE_ATTR_RW(srpd);
|
||||||
|
|
||||||
|
static struct attribute *dev_attrs[] = {
|
||||||
|
&dev_attr_frequency.attr,
|
||||||
|
&dev_attr_srpd.attr,
|
||||||
|
NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct attribute_group dev_attr_group = {
|
||||||
|
.attrs = dev_attrs,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct of_device_id brcmstb_memc_of_match[];
|
||||||
|
|
||||||
|
static int brcmstb_memc_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
const struct brcmstb_memc_data *memc_data;
|
||||||
|
const struct of_device_id *of_id;
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct brcmstb_memc *memc;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
memc = devm_kzalloc(dev, sizeof(*memc), GFP_KERNEL);
|
||||||
|
if (!memc)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dev_set_drvdata(dev, memc);
|
||||||
|
|
||||||
|
of_id = of_match_device(brcmstb_memc_of_match, dev);
|
||||||
|
memc_data = of_id->data;
|
||||||
|
memc->srpd_offset = memc_data->srpd_offset;
|
||||||
|
|
||||||
|
memc->ddr_ctrl = devm_platform_ioremap_resource(pdev, 0);
|
||||||
|
if (IS_ERR(memc->ddr_ctrl))
|
||||||
|
return PTR_ERR(memc->ddr_ctrl);
|
||||||
|
|
||||||
|
of_property_read_u32(pdev->dev.of_node, "clock-frequency",
|
||||||
|
&memc->frequency);
|
||||||
|
|
||||||
|
ret = sysfs_create_group(&dev->kobj, &dev_attr_group);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int brcmstb_memc_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
|
||||||
|
sysfs_remove_group(&dev->kobj, &dev_attr_group);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum brcmstb_memc_hwtype {
|
||||||
|
BRCMSTB_MEMC_V21,
|
||||||
|
BRCMSTB_MEMC_V20,
|
||||||
|
BRCMSTB_MEMC_V1X,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct brcmstb_memc_data brcmstb_memc_versions[] = {
|
||||||
|
{ .srpd_offset = REG_MEMC_SRPD_CFG_21 },
|
||||||
|
{ .srpd_offset = REG_MEMC_SRPD_CFG_20 },
|
||||||
|
{ .srpd_offset = REG_MEMC_SRPD_CFG_1x },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct of_device_id brcmstb_memc_of_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr-rev-b.1.x",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V1X]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.0",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V20]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.1",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.2",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.3",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.5",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.6",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.7",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr-rev-b.2.8",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr-rev-b.3.0",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr-rev-b.3.1",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr-rev-c.1.0",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr-rev-c.1.1",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr-rev-c.1.2",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr-rev-c.1.3",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr-rev-c.1.4",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V21]
|
||||||
|
},
|
||||||
|
/* default to the original offset */
|
||||||
|
{
|
||||||
|
.compatible = "brcm,brcmstb-memc-ddr",
|
||||||
|
.data = &brcmstb_memc_versions[BRCMSTB_MEMC_V1X]
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
|
static int brcmstb_memc_suspend(struct device *dev)
|
||||||
|
{
|
||||||
|
struct brcmstb_memc *memc = dev_get_drvdata(dev);
|
||||||
|
void __iomem *cfg = memc->ddr_ctrl + memc->srpd_offset;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
if (memc->timeout_cycles == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Disable SRPD prior to suspending the system since that can
|
||||||
|
* cause issues with other memory clients managed by the ARM
|
||||||
|
* trusted firmware to access memory.
|
||||||
|
*/
|
||||||
|
val = readl_relaxed(cfg);
|
||||||
|
val &= ~BIT(SRPD_EN_SHIFT);
|
||||||
|
writel_relaxed(val, cfg);
|
||||||
|
/* Ensure the write is committed to the controller */
|
||||||
|
(void)readl_relaxed(cfg);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int brcmstb_memc_resume(struct device *dev)
|
||||||
|
{
|
||||||
|
struct brcmstb_memc *memc = dev_get_drvdata(dev);
|
||||||
|
|
||||||
|
if (memc->timeout_cycles == 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return brcmstb_memc_srpd_config(memc, memc->timeout_cycles);
|
||||||
|
}
|
||||||
|
|
||||||
|
static DEFINE_SIMPLE_DEV_PM_OPS(brcmstb_memc_pm_ops, brcmstb_memc_suspend,
|
||||||
|
brcmstb_memc_resume);
|
||||||
|
|
||||||
|
static struct platform_driver brcmstb_memc_driver = {
|
||||||
|
.probe = brcmstb_memc_probe,
|
||||||
|
.remove = brcmstb_memc_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = "brcmstb_memc",
|
||||||
|
.of_match_table = brcmstb_memc_of_match,
|
||||||
|
.pm = pm_ptr(&brcmstb_memc_pm_ops),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
module_platform_driver(brcmstb_memc_driver);
|
||||||
|
|
||||||
|
MODULE_LICENSE("GPL");
|
||||||
|
MODULE_AUTHOR("Broadcom");
|
||||||
|
MODULE_DESCRIPTION("DDR SRPD driver for Broadcom STB chips");
|
|
@ -24,11 +24,24 @@
|
||||||
#define EMIF_STAT_CLEAR_BUSY_SFT 16
|
#define EMIF_STAT_CLEAR_BUSY_SFT 16
|
||||||
#define EMIF_CTRL 0x10
|
#define EMIF_CTRL 0x10
|
||||||
#define EMIF_CTRL_CLEAR_EN_SFT 0
|
#define EMIF_CTRL_CLEAR_EN_SFT 0
|
||||||
#define EMIF_CTRL_CLEAR_EN_MSK GENMASK_ULL(3, 0)
|
#define EMIF_CTRL_CLEAR_EN_MSK GENMASK_ULL(7, 0)
|
||||||
|
|
||||||
#define EMIF_POLL_INVL 10000 /* us */
|
#define EMIF_POLL_INVL 10000 /* us */
|
||||||
#define EMIF_POLL_TIMEOUT 5000000 /* us */
|
#define EMIF_POLL_TIMEOUT 5000000 /* us */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The Capability Register replaces the Control Register (at the same
|
||||||
|
* offset) for EMIF feature revisions > 0. The bitmask that indicates
|
||||||
|
* the presence of memory channels exists in both the Capability Register
|
||||||
|
* and Control Register definitions. These can be thought of as a C union.
|
||||||
|
* The Capability Register definitions are used to check for the existence
|
||||||
|
* of a memory channel, and the Control Register definitions are used for
|
||||||
|
* managing the memory-clear functionality in revision 0.
|
||||||
|
*/
|
||||||
|
#define EMIF_CAPABILITY_BASE 0x10
|
||||||
|
#define EMIF_CAPABILITY_CHN_MSK_V0 GENMASK_ULL(3, 0)
|
||||||
|
#define EMIF_CAPABILITY_CHN_MSK GENMASK_ULL(7, 0)
|
||||||
|
|
||||||
struct dfl_emif {
|
struct dfl_emif {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
void __iomem *base;
|
void __iomem *base;
|
||||||
|
@ -106,16 +119,30 @@ emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 0);
|
||||||
emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 1);
|
emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 1);
|
||||||
emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 2);
|
emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 2);
|
||||||
emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 3);
|
emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 3);
|
||||||
|
emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 4);
|
||||||
|
emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 5);
|
||||||
|
emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 6);
|
||||||
|
emif_state_attr(init_done, EMIF_STAT_INIT_DONE_SFT, 7);
|
||||||
|
|
||||||
emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 0);
|
emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 0);
|
||||||
emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 1);
|
emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 1);
|
||||||
emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 2);
|
emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 2);
|
||||||
emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 3);
|
emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 3);
|
||||||
|
emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 4);
|
||||||
|
emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 5);
|
||||||
|
emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 6);
|
||||||
|
emif_state_attr(cal_fail, EMIF_STAT_CALC_FAIL_SFT, 7);
|
||||||
|
|
||||||
|
|
||||||
emif_clear_attr(0);
|
emif_clear_attr(0);
|
||||||
emif_clear_attr(1);
|
emif_clear_attr(1);
|
||||||
emif_clear_attr(2);
|
emif_clear_attr(2);
|
||||||
emif_clear_attr(3);
|
emif_clear_attr(3);
|
||||||
|
emif_clear_attr(4);
|
||||||
|
emif_clear_attr(5);
|
||||||
|
emif_clear_attr(6);
|
||||||
|
emif_clear_attr(7);
|
||||||
|
|
||||||
|
|
||||||
static struct attribute *dfl_emif_attrs[] = {
|
static struct attribute *dfl_emif_attrs[] = {
|
||||||
&emif_attr_inf0_init_done.attr.attr,
|
&emif_attr_inf0_init_done.attr.attr,
|
||||||
|
@ -134,6 +161,22 @@ static struct attribute *dfl_emif_attrs[] = {
|
||||||
&emif_attr_inf3_cal_fail.attr.attr,
|
&emif_attr_inf3_cal_fail.attr.attr,
|
||||||
&emif_attr_inf3_clear.attr.attr,
|
&emif_attr_inf3_clear.attr.attr,
|
||||||
|
|
||||||
|
&emif_attr_inf4_init_done.attr.attr,
|
||||||
|
&emif_attr_inf4_cal_fail.attr.attr,
|
||||||
|
&emif_attr_inf4_clear.attr.attr,
|
||||||
|
|
||||||
|
&emif_attr_inf5_init_done.attr.attr,
|
||||||
|
&emif_attr_inf5_cal_fail.attr.attr,
|
||||||
|
&emif_attr_inf5_clear.attr.attr,
|
||||||
|
|
||||||
|
&emif_attr_inf6_init_done.attr.attr,
|
||||||
|
&emif_attr_inf6_cal_fail.attr.attr,
|
||||||
|
&emif_attr_inf6_clear.attr.attr,
|
||||||
|
|
||||||
|
&emif_attr_inf7_init_done.attr.attr,
|
||||||
|
&emif_attr_inf7_cal_fail.attr.attr,
|
||||||
|
&emif_attr_inf7_clear.attr.attr,
|
||||||
|
|
||||||
NULL,
|
NULL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -143,15 +186,24 @@ static umode_t dfl_emif_visible(struct kobject *kobj,
|
||||||
struct dfl_emif *de = dev_get_drvdata(kobj_to_dev(kobj));
|
struct dfl_emif *de = dev_get_drvdata(kobj_to_dev(kobj));
|
||||||
struct emif_attr *eattr = container_of(attr, struct emif_attr,
|
struct emif_attr *eattr = container_of(attr, struct emif_attr,
|
||||||
attr.attr);
|
attr.attr);
|
||||||
|
struct dfl_device *ddev = to_dfl_dev(de->dev);
|
||||||
u64 val;
|
u64 val;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This device supports upto 4 memory interfaces, but not all
|
* This device supports up to 8 memory interfaces, but not all
|
||||||
* interfaces are used on different platforms. The read out value of
|
* interfaces are used on different platforms. The read out value of
|
||||||
* CLEAN_EN field (which is a bitmap) could tell how many interfaces
|
* CAPABILITY_CHN_MSK field (which is a bitmap) indicates which
|
||||||
* are available.
|
* interfaces are available.
|
||||||
*/
|
*/
|
||||||
val = FIELD_GET(EMIF_CTRL_CLEAR_EN_MSK, readq(de->base + EMIF_CTRL));
|
if (ddev->revision > 0 && strstr(attr->name, "_clear"))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (ddev->revision == 0)
|
||||||
|
val = FIELD_GET(EMIF_CAPABILITY_CHN_MSK_V0,
|
||||||
|
readq(de->base + EMIF_CAPABILITY_BASE));
|
||||||
|
else
|
||||||
|
val = FIELD_GET(EMIF_CAPABILITY_CHN_MSK,
|
||||||
|
readq(de->base + EMIF_CAPABILITY_BASE));
|
||||||
|
|
||||||
return (val & BIT_ULL(eattr->index)) ? attr->mode : 0;
|
return (val & BIT_ULL(eattr->index)) ? attr->mode : 0;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* Copyright (c) 2015-2016 MediaTek Inc.
|
* Copyright (c) 2015-2016 MediaTek Inc.
|
||||||
* Author: Yong Wu <yong.wu@mediatek.com>
|
* Author: Yong Wu <yong.wu@mediatek.com>
|
||||||
*/
|
*/
|
||||||
|
#include <linux/arm-smccc.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/component.h>
|
#include <linux/component.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
@ -14,6 +15,7 @@
|
||||||
#include <linux/of_platform.h>
|
#include <linux/of_platform.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/pm_runtime.h>
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/soc/mediatek/mtk_sip_svc.h>
|
||||||
#include <soc/mediatek/smi.h>
|
#include <soc/mediatek/smi.h>
|
||||||
#include <dt-bindings/memory/mt2701-larb-port.h>
|
#include <dt-bindings/memory/mt2701-larb-port.h>
|
||||||
#include <dt-bindings/memory/mtk-memory-port.h>
|
#include <dt-bindings/memory/mtk-memory-port.h>
|
||||||
|
@ -89,6 +91,7 @@
|
||||||
#define MTK_SMI_FLAG_THRT_UPDATE BIT(0)
|
#define MTK_SMI_FLAG_THRT_UPDATE BIT(0)
|
||||||
#define MTK_SMI_FLAG_SW_FLAG BIT(1)
|
#define MTK_SMI_FLAG_SW_FLAG BIT(1)
|
||||||
#define MTK_SMI_FLAG_SLEEP_CTL BIT(2)
|
#define MTK_SMI_FLAG_SLEEP_CTL BIT(2)
|
||||||
|
#define MTK_SMI_FLAG_CFG_PORT_SEC_CTL BIT(3)
|
||||||
#define MTK_SMI_CAPS(flags, _x) (!!((flags) & (_x)))
|
#define MTK_SMI_CAPS(flags, _x) (!!((flags) & (_x)))
|
||||||
|
|
||||||
struct mtk_smi_reg_pair {
|
struct mtk_smi_reg_pair {
|
||||||
|
@ -127,7 +130,7 @@ struct mtk_smi_common_plat {
|
||||||
|
|
||||||
struct mtk_smi_larb_gen {
|
struct mtk_smi_larb_gen {
|
||||||
int port_in_larb[MTK_LARB_NR_MAX + 1];
|
int port_in_larb[MTK_LARB_NR_MAX + 1];
|
||||||
void (*config_port)(struct device *dev);
|
int (*config_port)(struct device *dev);
|
||||||
unsigned int larb_direct_to_common_mask;
|
unsigned int larb_direct_to_common_mask;
|
||||||
unsigned int flags_general;
|
unsigned int flags_general;
|
||||||
const u8 (*ostd)[SMI_LARB_PORT_NR_MAX];
|
const u8 (*ostd)[SMI_LARB_PORT_NR_MAX];
|
||||||
|
@ -185,7 +188,7 @@ static const struct component_ops mtk_smi_larb_component_ops = {
|
||||||
.unbind = mtk_smi_larb_unbind,
|
.unbind = mtk_smi_larb_unbind,
|
||||||
};
|
};
|
||||||
|
|
||||||
static void mtk_smi_larb_config_port_gen1(struct device *dev)
|
static int mtk_smi_larb_config_port_gen1(struct device *dev)
|
||||||
{
|
{
|
||||||
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
|
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
|
||||||
const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
|
const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
|
||||||
|
@ -214,31 +217,35 @@ static void mtk_smi_larb_config_port_gen1(struct device *dev)
|
||||||
common->smi_ao_base
|
common->smi_ao_base
|
||||||
+ REG_SMI_SECUR_CON_ADDR(m4u_port_id));
|
+ REG_SMI_SECUR_CON_ADDR(m4u_port_id));
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mtk_smi_larb_config_port_mt8167(struct device *dev)
|
static int mtk_smi_larb_config_port_mt8167(struct device *dev)
|
||||||
{
|
{
|
||||||
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
|
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
|
||||||
|
|
||||||
writel(*larb->mmu, larb->base + MT8167_SMI_LARB_MMU_EN);
|
writel(*larb->mmu, larb->base + MT8167_SMI_LARB_MMU_EN);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mtk_smi_larb_config_port_mt8173(struct device *dev)
|
static int mtk_smi_larb_config_port_mt8173(struct device *dev)
|
||||||
{
|
{
|
||||||
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
|
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
|
||||||
|
|
||||||
writel(*larb->mmu, larb->base + MT8173_SMI_LARB_MMU_EN);
|
writel(*larb->mmu, larb->base + MT8173_SMI_LARB_MMU_EN);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mtk_smi_larb_config_port_gen2_general(struct device *dev)
|
static int mtk_smi_larb_config_port_gen2_general(struct device *dev)
|
||||||
{
|
{
|
||||||
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
|
struct mtk_smi_larb *larb = dev_get_drvdata(dev);
|
||||||
u32 reg, flags_general = larb->larb_gen->flags_general;
|
u32 reg, flags_general = larb->larb_gen->flags_general;
|
||||||
const u8 *larbostd = larb->larb_gen->ostd ? larb->larb_gen->ostd[larb->larbid] : NULL;
|
const u8 *larbostd = larb->larb_gen->ostd ? larb->larb_gen->ostd[larb->larbid] : NULL;
|
||||||
|
struct arm_smccc_res res;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (BIT(larb->larbid) & larb->larb_gen->larb_direct_to_common_mask)
|
if (BIT(larb->larbid) & larb->larb_gen->larb_direct_to_common_mask)
|
||||||
return;
|
return 0;
|
||||||
|
|
||||||
if (MTK_SMI_CAPS(flags_general, MTK_SMI_FLAG_THRT_UPDATE)) {
|
if (MTK_SMI_CAPS(flags_general, MTK_SMI_FLAG_THRT_UPDATE)) {
|
||||||
reg = readl_relaxed(larb->base + SMI_LARB_CMD_THRT_CON);
|
reg = readl_relaxed(larb->base + SMI_LARB_CMD_THRT_CON);
|
||||||
|
@ -253,14 +260,78 @@ static void mtk_smi_larb_config_port_gen2_general(struct device *dev)
|
||||||
for (i = 0; i < SMI_LARB_PORT_NR_MAX && larbostd && !!larbostd[i]; i++)
|
for (i = 0; i < SMI_LARB_PORT_NR_MAX && larbostd && !!larbostd[i]; i++)
|
||||||
writel_relaxed(larbostd[i], larb->base + SMI_LARB_OSTDL_PORTx(i));
|
writel_relaxed(larbostd[i], larb->base + SMI_LARB_OSTDL_PORTx(i));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* When mmu_en bits are in security world, the bank_sel still is in the
|
||||||
|
* LARB_NONSEC_CON below. And the mmu_en bits of LARB_NONSEC_CON have no
|
||||||
|
* effect in this case.
|
||||||
|
*/
|
||||||
|
if (MTK_SMI_CAPS(flags_general, MTK_SMI_FLAG_CFG_PORT_SEC_CTL)) {
|
||||||
|
arm_smccc_smc(MTK_SIP_KERNEL_IOMMU_CONTROL, IOMMU_ATF_CMD_CONFIG_SMI_LARB,
|
||||||
|
larb->larbid, *larb->mmu, 0, 0, 0, 0, &res);
|
||||||
|
if (res.a0 != 0) {
|
||||||
|
dev_err(dev, "Enable iommu fail, ret %ld\n", res.a0);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for_each_set_bit(i, (unsigned long *)larb->mmu, 32) {
|
for_each_set_bit(i, (unsigned long *)larb->mmu, 32) {
|
||||||
reg = readl_relaxed(larb->base + SMI_LARB_NONSEC_CON(i));
|
reg = readl_relaxed(larb->base + SMI_LARB_NONSEC_CON(i));
|
||||||
reg |= F_MMU_EN;
|
reg |= F_MMU_EN;
|
||||||
reg |= BANK_SEL(larb->bank[i]);
|
reg |= BANK_SEL(larb->bank[i]);
|
||||||
writel(reg, larb->base + SMI_LARB_NONSEC_CON(i));
|
writel(reg, larb->base + SMI_LARB_NONSEC_CON(i));
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const u8 mtk_smi_larb_mt8188_ostd[][SMI_LARB_PORT_NR_MAX] = {
|
||||||
|
[0] = {0x02, 0x18, 0x22, 0x22, 0x01, 0x02, 0x0a,},
|
||||||
|
[1] = {0x12, 0x02, 0x14, 0x14, 0x01, 0x18, 0x0a,},
|
||||||
|
[2] = {0x12, 0x12, 0x12, 0x12, 0x0a,},
|
||||||
|
[3] = {0x12, 0x12, 0x12, 0x12, 0x28, 0x28, 0x0a,},
|
||||||
|
[4] = {0x06, 0x01, 0x17, 0x06, 0x0a, 0x07, 0x07,},
|
||||||
|
[5] = {0x02, 0x01, 0x04, 0x02, 0x06, 0x01, 0x06, 0x0a,},
|
||||||
|
[6] = {0x06, 0x01, 0x06, 0x0a,},
|
||||||
|
[7] = {0x0c, 0x0c, 0x12,},
|
||||||
|
[8] = {0x0c, 0x01, 0x0a, 0x05, 0x02, 0x03, 0x01, 0x01, 0x14, 0x14,
|
||||||
|
0x0a, 0x14, 0x1e, 0x01, 0x0c, 0x0a, 0x05, 0x02, 0x02, 0x05,
|
||||||
|
0x03, 0x01, 0x1e, 0x01, 0x05,},
|
||||||
|
[9] = {0x1e, 0x01, 0x0a, 0x0a, 0x01, 0x01, 0x03, 0x1e, 0x1e, 0x10,
|
||||||
|
0x07, 0x01, 0x0a, 0x06, 0x03, 0x03, 0x0e, 0x01, 0x04, 0x28,},
|
||||||
|
[10] = {0x03, 0x20, 0x01, 0x20, 0x01, 0x01, 0x14, 0x0a, 0x0a, 0x0c,
|
||||||
|
0x0a, 0x05, 0x02, 0x03, 0x02, 0x14, 0x0a, 0x0a, 0x14, 0x14,
|
||||||
|
0x14, 0x01, 0x01, 0x14, 0x1e, 0x01, 0x05, 0x03, 0x02, 0x28,},
|
||||||
|
[11] = {0x03, 0x20, 0x01, 0x20, 0x01, 0x01, 0x14, 0x0a, 0x0a, 0x0c,
|
||||||
|
0x0a, 0x05, 0x02, 0x03, 0x02, 0x14, 0x0a, 0x0a, 0x14, 0x14,
|
||||||
|
0x14, 0x01, 0x01, 0x14, 0x1e, 0x01, 0x05, 0x03, 0x02, 0x28,},
|
||||||
|
[12] = {0x03, 0x20, 0x01, 0x20, 0x01, 0x01, 0x14, 0x0a, 0x0a, 0x0c,
|
||||||
|
0x0a, 0x05, 0x02, 0x03, 0x02, 0x14, 0x0a, 0x0a, 0x14, 0x14,
|
||||||
|
0x14, 0x01, 0x01, 0x14, 0x1e, 0x01, 0x05, 0x03, 0x02, 0x28,},
|
||||||
|
[13] = {0x07, 0x02, 0x04, 0x02, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
|
||||||
|
0x07, 0x02, 0x04, 0x02, 0x05, 0x05,},
|
||||||
|
[14] = {0x02, 0x02, 0x0c, 0x0c, 0x0c, 0x0c, 0x01, 0x01, 0x02, 0x02,
|
||||||
|
0x02, 0x02, 0x0c, 0x0c, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
|
||||||
|
0x02, 0x02, 0x01, 0x01,},
|
||||||
|
[15] = {0x0c, 0x0c, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x0c, 0x0c,
|
||||||
|
0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02,
|
||||||
|
0x0c, 0x01, 0x01,},
|
||||||
|
[16] = {0x28, 0x28, 0x03, 0x01, 0x01, 0x03, 0x14, 0x14, 0x0a, 0x0d,
|
||||||
|
0x03, 0x05, 0x0e, 0x01, 0x01, 0x05, 0x06, 0x0d, 0x01,},
|
||||||
|
[17] = {0x28, 0x02, 0x02, 0x12, 0x02, 0x12, 0x10, 0x02, 0x02, 0x0a,
|
||||||
|
0x12, 0x02, 0x02, 0x0a, 0x16, 0x02, 0x04,},
|
||||||
|
[18] = {0x28, 0x02, 0x02, 0x12, 0x02, 0x12, 0x10, 0x02, 0x02, 0x0a,
|
||||||
|
0x12, 0x02, 0x02, 0x0a, 0x16, 0x02, 0x04,},
|
||||||
|
[19] = {0x1a, 0x0e, 0x0a, 0x0a, 0x0c, 0x0e, 0x10,},
|
||||||
|
[20] = {0x1a, 0x0e, 0x0a, 0x0a, 0x0c, 0x0e, 0x10,},
|
||||||
|
[21] = {0x01, 0x04, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04, 0x04, 0x01,
|
||||||
|
0x01, 0x01, 0x04, 0x0a, 0x06, 0x01, 0x01, 0x01, 0x0a, 0x06,
|
||||||
|
0x01, 0x01, 0x05, 0x03, 0x03, 0x04, 0x01,},
|
||||||
|
[22] = {0x28, 0x19, 0x0c, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x04,
|
||||||
|
0x01,},
|
||||||
|
[23] = {0x01, 0x01, 0x04, 0x01, 0x01, 0x01, 0x18, 0x01, 0x01,},
|
||||||
|
[24] = {0x12, 0x06, 0x12, 0x06,},
|
||||||
|
[25] = {0x01},
|
||||||
|
};
|
||||||
|
|
||||||
static const u8 mtk_smi_larb_mt8195_ostd[][SMI_LARB_PORT_NR_MAX] = {
|
static const u8 mtk_smi_larb_mt8195_ostd[][SMI_LARB_PORT_NR_MAX] = {
|
||||||
[0] = {0x0a, 0xc, 0x22, 0x22, 0x01, 0x0a,}, /* larb0 */
|
[0] = {0x0a, 0xc, 0x22, 0x22, 0x01, 0x0a,}, /* larb0 */
|
||||||
[1] = {0x0a, 0xc, 0x22, 0x22, 0x01, 0x0a,}, /* larb1 */
|
[1] = {0x0a, 0xc, 0x22, 0x22, 0x01, 0x0a,}, /* larb1 */
|
||||||
|
@ -347,6 +418,13 @@ static const struct mtk_smi_larb_gen mtk_smi_larb_mt8186 = {
|
||||||
.flags_general = MTK_SMI_FLAG_SLEEP_CTL,
|
.flags_general = MTK_SMI_FLAG_SLEEP_CTL,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8188 = {
|
||||||
|
.config_port = mtk_smi_larb_config_port_gen2_general,
|
||||||
|
.flags_general = MTK_SMI_FLAG_THRT_UPDATE | MTK_SMI_FLAG_SW_FLAG |
|
||||||
|
MTK_SMI_FLAG_SLEEP_CTL | MTK_SMI_FLAG_CFG_PORT_SEC_CTL,
|
||||||
|
.ostd = mtk_smi_larb_mt8188_ostd,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = {
|
static const struct mtk_smi_larb_gen mtk_smi_larb_mt8192 = {
|
||||||
.config_port = mtk_smi_larb_config_port_gen2_general,
|
.config_port = mtk_smi_larb_config_port_gen2_general,
|
||||||
};
|
};
|
||||||
|
@ -367,6 +445,7 @@ static const struct of_device_id mtk_smi_larb_of_ids[] = {
|
||||||
{.compatible = "mediatek,mt8173-smi-larb", .data = &mtk_smi_larb_mt8173},
|
{.compatible = "mediatek,mt8173-smi-larb", .data = &mtk_smi_larb_mt8173},
|
||||||
{.compatible = "mediatek,mt8183-smi-larb", .data = &mtk_smi_larb_mt8183},
|
{.compatible = "mediatek,mt8183-smi-larb", .data = &mtk_smi_larb_mt8183},
|
||||||
{.compatible = "mediatek,mt8186-smi-larb", .data = &mtk_smi_larb_mt8186},
|
{.compatible = "mediatek,mt8186-smi-larb", .data = &mtk_smi_larb_mt8186},
|
||||||
|
{.compatible = "mediatek,mt8188-smi-larb", .data = &mtk_smi_larb_mt8188},
|
||||||
{.compatible = "mediatek,mt8192-smi-larb", .data = &mtk_smi_larb_mt8192},
|
{.compatible = "mediatek,mt8192-smi-larb", .data = &mtk_smi_larb_mt8192},
|
||||||
{.compatible = "mediatek,mt8195-smi-larb", .data = &mtk_smi_larb_mt8195},
|
{.compatible = "mediatek,mt8195-smi-larb", .data = &mtk_smi_larb_mt8195},
|
||||||
{}
|
{}
|
||||||
|
@ -511,9 +590,7 @@ static int __maybe_unused mtk_smi_larb_resume(struct device *dev)
|
||||||
mtk_smi_larb_sleep_ctrl_disable(larb);
|
mtk_smi_larb_sleep_ctrl_disable(larb);
|
||||||
|
|
||||||
/* Configure the basic setting for this larb */
|
/* Configure the basic setting for this larb */
|
||||||
larb_gen->config_port(dev);
|
return larb_gen->config_port(dev);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __maybe_unused mtk_smi_larb_suspend(struct device *dev)
|
static int __maybe_unused mtk_smi_larb_suspend(struct device *dev)
|
||||||
|
@ -597,6 +674,18 @@ static const struct mtk_smi_common_plat mtk_smi_common_mt8186 = {
|
||||||
.bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(4) | F_MMU1_LARB(7),
|
.bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(4) | F_MMU1_LARB(7),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct mtk_smi_common_plat mtk_smi_common_mt8188_vdo = {
|
||||||
|
.type = MTK_SMI_GEN2,
|
||||||
|
.bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(5) | F_MMU1_LARB(7),
|
||||||
|
.init = mtk_smi_common_mt8195_init,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct mtk_smi_common_plat mtk_smi_common_mt8188_vpp = {
|
||||||
|
.type = MTK_SMI_GEN2,
|
||||||
|
.bus_sel = F_MMU1_LARB(1) | F_MMU1_LARB(2) | F_MMU1_LARB(7),
|
||||||
|
.init = mtk_smi_common_mt8195_init,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = {
|
static const struct mtk_smi_common_plat mtk_smi_common_mt8192 = {
|
||||||
.type = MTK_SMI_GEN2,
|
.type = MTK_SMI_GEN2,
|
||||||
.has_gals = true,
|
.has_gals = true,
|
||||||
|
@ -633,6 +722,8 @@ static const struct of_device_id mtk_smi_common_of_ids[] = {
|
||||||
{.compatible = "mediatek,mt8173-smi-common", .data = &mtk_smi_common_gen2},
|
{.compatible = "mediatek,mt8173-smi-common", .data = &mtk_smi_common_gen2},
|
||||||
{.compatible = "mediatek,mt8183-smi-common", .data = &mtk_smi_common_mt8183},
|
{.compatible = "mediatek,mt8183-smi-common", .data = &mtk_smi_common_mt8183},
|
||||||
{.compatible = "mediatek,mt8186-smi-common", .data = &mtk_smi_common_mt8186},
|
{.compatible = "mediatek,mt8186-smi-common", .data = &mtk_smi_common_mt8186},
|
||||||
|
{.compatible = "mediatek,mt8188-smi-common-vdo", .data = &mtk_smi_common_mt8188_vdo},
|
||||||
|
{.compatible = "mediatek,mt8188-smi-common-vpp", .data = &mtk_smi_common_mt8188_vpp},
|
||||||
{.compatible = "mediatek,mt8192-smi-common", .data = &mtk_smi_common_mt8192},
|
{.compatible = "mediatek,mt8192-smi-common", .data = &mtk_smi_common_mt8192},
|
||||||
{.compatible = "mediatek,mt8195-smi-common-vdo", .data = &mtk_smi_common_mt8195_vdo},
|
{.compatible = "mediatek,mt8195-smi-common-vdo", .data = &mtk_smi_common_mt8195_vdo},
|
||||||
{.compatible = "mediatek,mt8195-smi-common-vpp", .data = &mtk_smi_common_mt8195_vpp},
|
{.compatible = "mediatek,mt8195-smi-common-vpp", .data = &mtk_smi_common_mt8195_vpp},
|
||||||
|
|
|
@ -134,6 +134,7 @@ const struct lpddr2_timings *of_get_ddr_timings(struct device_node *np_ddr,
|
||||||
for_each_child_of_node(np_ddr, np_tim) {
|
for_each_child_of_node(np_ddr, np_tim) {
|
||||||
if (of_device_is_compatible(np_tim, tim_compat)) {
|
if (of_device_is_compatible(np_tim, tim_compat)) {
|
||||||
if (of_do_get_timings(np_tim, &timings[i])) {
|
if (of_do_get_timings(np_tim, &timings[i])) {
|
||||||
|
of_node_put(np_tim);
|
||||||
devm_kfree(dev, timings);
|
devm_kfree(dev, timings);
|
||||||
goto default_timings;
|
goto default_timings;
|
||||||
}
|
}
|
||||||
|
@ -284,6 +285,7 @@ const struct lpddr3_timings
|
||||||
if (of_device_is_compatible(np_tim, tim_compat)) {
|
if (of_device_is_compatible(np_tim, tim_compat)) {
|
||||||
if (of_lpddr3_do_get_timings(np_tim, &timings[i])) {
|
if (of_lpddr3_do_get_timings(np_tim, &timings[i])) {
|
||||||
devm_kfree(dev, timings);
|
devm_kfree(dev, timings);
|
||||||
|
of_node_put(np_tim);
|
||||||
goto default_timings;
|
goto default_timings;
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
|
|
|
@ -122,6 +122,7 @@ static int pl353_smc_probe(struct amba_device *adev, const struct amba_id *id)
|
||||||
}
|
}
|
||||||
|
|
||||||
of_platform_device_create(child, NULL, &adev->dev);
|
of_platform_device_create(child, NULL, &adev->dev);
|
||||||
|
of_node_put(child);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
|
|
@ -69,8 +69,8 @@ config MTD_OF_PARTS
|
||||||
|
|
||||||
config MTD_OF_PARTS_BCM4908
|
config MTD_OF_PARTS_BCM4908
|
||||||
bool "BCM4908 partitioning support"
|
bool "BCM4908 partitioning support"
|
||||||
depends on MTD_OF_PARTS && (ARCH_BCM4908 || COMPILE_TEST)
|
depends on MTD_OF_PARTS && (ARCH_BCMBCA || COMPILE_TEST)
|
||||||
default ARCH_BCM4908
|
default ARCH_BCMBCA
|
||||||
help
|
help
|
||||||
This provides partitions parser for BCM4908 family devices
|
This provides partitions parser for BCM4908 family devices
|
||||||
that can have multiple "firmware" partitions. It takes care of
|
that can have multiple "firmware" partitions. It takes care of
|
||||||
|
@ -78,7 +78,7 @@ config MTD_OF_PARTS_BCM4908
|
||||||
|
|
||||||
config MTD_OF_PARTS_LINKSYS_NS
|
config MTD_OF_PARTS_LINKSYS_NS
|
||||||
bool "Linksys Northstar partitioning support"
|
bool "Linksys Northstar partitioning support"
|
||||||
depends on MTD_OF_PARTS && (ARCH_BCM_5301X || ARCH_BCM4908 || COMPILE_TEST)
|
depends on MTD_OF_PARTS && (ARCH_BCM_5301X || ARCH_BCMBCA || COMPILE_TEST)
|
||||||
default ARCH_BCM_5301X
|
default ARCH_BCM_5301X
|
||||||
help
|
help
|
||||||
This provides partitions parser for Linksys devices based on Broadcom
|
This provides partitions parser for Linksys devices based on Broadcom
|
||||||
|
|
|
@ -53,8 +53,8 @@ config B44_PCI
|
||||||
|
|
||||||
config BCM4908_ENET
|
config BCM4908_ENET
|
||||||
tristate "Broadcom BCM4908 internal mac support"
|
tristate "Broadcom BCM4908 internal mac support"
|
||||||
depends on ARCH_BCM4908 || COMPILE_TEST
|
depends on ARCH_BCMBCA || COMPILE_TEST
|
||||||
default y if ARCH_BCM4908
|
default y if ARCH_BCMBCA
|
||||||
help
|
help
|
||||||
This driver supports Ethernet controller integrated into Broadcom
|
This driver supports Ethernet controller integrated into Broadcom
|
||||||
BCM4908 family SoCs.
|
BCM4908 family SoCs.
|
||||||
|
|
|
@ -274,7 +274,7 @@ config VMD
|
||||||
|
|
||||||
config PCIE_BRCMSTB
|
config PCIE_BRCMSTB
|
||||||
tristate "Broadcom Brcmstb PCIe host controller"
|
tristate "Broadcom Brcmstb PCIe host controller"
|
||||||
depends on ARCH_BRCMSTB || ARCH_BCM2835 || ARCH_BCM4908 || \
|
depends on ARCH_BRCMSTB || ARCH_BCM2835 || ARCH_BCMBCA || \
|
||||||
BMIPS_GENERIC || COMPILE_TEST
|
BMIPS_GENERIC || COMPILE_TEST
|
||||||
depends on OF
|
depends on OF
|
||||||
depends on PCI_MSI_IRQ_DOMAIN
|
depends on PCI_MSI_IRQ_DOMAIN
|
||||||
|
|
|
@ -93,11 +93,11 @@ config PHY_BRCM_SATA
|
||||||
|
|
||||||
config PHY_BRCM_USB
|
config PHY_BRCM_USB
|
||||||
tristate "Broadcom STB USB PHY driver"
|
tristate "Broadcom STB USB PHY driver"
|
||||||
depends on ARCH_BCM4908 || ARCH_BRCMSTB || COMPILE_TEST
|
depends on ARCH_BCMBCA || ARCH_BRCMSTB || COMPILE_TEST
|
||||||
depends on OF
|
depends on OF
|
||||||
select GENERIC_PHY
|
select GENERIC_PHY
|
||||||
select SOC_BRCMSTB if ARCH_BRCMSTB
|
select SOC_BRCMSTB if ARCH_BRCMSTB
|
||||||
default ARCH_BCM4908 || ARCH_BRCMSTB
|
default ARCH_BCMBCA || ARCH_BRCMSTB
|
||||||
help
|
help
|
||||||
Enable this to support the Broadcom STB USB PHY.
|
Enable this to support the Broadcom STB USB PHY.
|
||||||
This driver is required by the USB XHCI, EHCI and OHCI
|
This driver is required by the USB XHCI, EHCI and OHCI
|
||||||
|
|
|
@ -31,13 +31,13 @@ config PINCTRL_BCM2835
|
||||||
|
|
||||||
config PINCTRL_BCM4908
|
config PINCTRL_BCM4908
|
||||||
tristate "Broadcom BCM4908 pinmux driver"
|
tristate "Broadcom BCM4908 pinmux driver"
|
||||||
depends on OF && (ARCH_BCM4908 || COMPILE_TEST)
|
depends on OF && (ARCH_BCMBCA || COMPILE_TEST)
|
||||||
select PINMUX
|
select PINMUX
|
||||||
select PINCONF
|
select PINCONF
|
||||||
select GENERIC_PINCONF
|
select GENERIC_PINCONF
|
||||||
select GENERIC_PINCTRL_GROUPS
|
select GENERIC_PINCTRL_GROUPS
|
||||||
select GENERIC_PINMUX_FUNCTIONS
|
select GENERIC_PINMUX_FUNCTIONS
|
||||||
default ARCH_BCM4908
|
default ARCH_BCMBCA
|
||||||
help
|
help
|
||||||
Driver for BCM4908 family SoCs with integrated pin controller.
|
Driver for BCM4908 family SoCs with integrated pin controller.
|
||||||
|
|
||||||
|
|
|
@ -201,7 +201,7 @@ config RESET_SCMI
|
||||||
|
|
||||||
config RESET_SIMPLE
|
config RESET_SIMPLE
|
||||||
bool "Simple Reset Controller Driver" if COMPILE_TEST || EXPERT
|
bool "Simple Reset Controller Driver" if COMPILE_TEST || EXPERT
|
||||||
default ARCH_ASPEED || ARCH_BCM4908 || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC
|
default ARCH_ASPEED || ARCH_BCMBCA || ARCH_BITMAIN || ARCH_REALTEK || ARCH_STM32 || (ARCH_INTEL_SOCFPGA && ARM64) || ARCH_SUNXI || ARC
|
||||||
depends on HAS_IOMEM
|
depends on HAS_IOMEM
|
||||||
help
|
help
|
||||||
This enables a simple reset controller driver for reset lines that
|
This enables a simple reset controller driver for reset lines that
|
||||||
|
|
|
@ -469,6 +469,7 @@ static int meson_ee_pwrc_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
const struct meson_ee_pwrc_domain_data *match;
|
const struct meson_ee_pwrc_domain_data *match;
|
||||||
struct regmap *regmap_ao, *regmap_hhi;
|
struct regmap *regmap_ao, *regmap_hhi;
|
||||||
|
struct device_node *parent_np;
|
||||||
struct meson_ee_pwrc *pwrc;
|
struct meson_ee_pwrc *pwrc;
|
||||||
int i, ret;
|
int i, ret;
|
||||||
|
|
||||||
|
@ -495,7 +496,9 @@ static int meson_ee_pwrc_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
pwrc->xlate.num_domains = match->count;
|
pwrc->xlate.num_domains = match->count;
|
||||||
|
|
||||||
regmap_hhi = syscon_node_to_regmap(of_get_parent(pdev->dev.of_node));
|
parent_np = of_get_parent(pdev->dev.of_node);
|
||||||
|
regmap_hhi = syscon_node_to_regmap(parent_np);
|
||||||
|
of_node_put(parent_np);
|
||||||
if (IS_ERR(regmap_hhi)) {
|
if (IS_ERR(regmap_hhi)) {
|
||||||
dev_err(&pdev->dev, "failed to get HHI regmap\n");
|
dev_err(&pdev->dev, "failed to get HHI regmap\n");
|
||||||
return PTR_ERR(regmap_hhi);
|
return PTR_ERR(regmap_hhi);
|
||||||
|
|
|
@ -273,6 +273,7 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
|
||||||
const struct meson_gx_pwrc_vpu *vpu_pd_match;
|
const struct meson_gx_pwrc_vpu *vpu_pd_match;
|
||||||
struct regmap *regmap_ao, *regmap_hhi;
|
struct regmap *regmap_ao, *regmap_hhi;
|
||||||
struct meson_gx_pwrc_vpu *vpu_pd;
|
struct meson_gx_pwrc_vpu *vpu_pd;
|
||||||
|
struct device_node *parent_np;
|
||||||
struct reset_control *rstc;
|
struct reset_control *rstc;
|
||||||
struct clk *vpu_clk;
|
struct clk *vpu_clk;
|
||||||
struct clk *vapb_clk;
|
struct clk *vapb_clk;
|
||||||
|
@ -291,7 +292,9 @@ static int meson_gx_pwrc_vpu_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
memcpy(vpu_pd, vpu_pd_match, sizeof(*vpu_pd));
|
memcpy(vpu_pd, vpu_pd_match, sizeof(*vpu_pd));
|
||||||
|
|
||||||
regmap_ao = syscon_node_to_regmap(of_get_parent(pdev->dev.of_node));
|
parent_np = of_get_parent(pdev->dev.of_node);
|
||||||
|
regmap_ao = syscon_node_to_regmap(parent_np);
|
||||||
|
of_node_put(parent_np);
|
||||||
if (IS_ERR(regmap_ao)) {
|
if (IS_ERR(regmap_ao)) {
|
||||||
dev_err(&pdev->dev, "failed to get regmap\n");
|
dev_err(&pdev->dev, "failed to get regmap\n");
|
||||||
return PTR_ERR(regmap_ao);
|
return PTR_ERR(regmap_ao);
|
||||||
|
|
|
@ -660,6 +660,12 @@ int apple_rtkit_send_message_wait(struct apple_rtkit *rtk, u8 ep, u64 message,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(apple_rtkit_send_message_wait);
|
EXPORT_SYMBOL_GPL(apple_rtkit_send_message_wait);
|
||||||
|
|
||||||
|
int apple_rtkit_poll(struct apple_rtkit *rtk)
|
||||||
|
{
|
||||||
|
return mbox_client_peek_data(rtk->mbox_chan);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(apple_rtkit_poll);
|
||||||
|
|
||||||
int apple_rtkit_start_ep(struct apple_rtkit *rtk, u8 endpoint)
|
int apple_rtkit_start_ep(struct apple_rtkit *rtk, u8 endpoint)
|
||||||
{
|
{
|
||||||
u64 msg;
|
u64 msg;
|
||||||
|
|
|
@ -13,8 +13,8 @@ endif # SOC_BCM63XX
|
||||||
|
|
||||||
config BCM_PMB
|
config BCM_PMB
|
||||||
bool "Broadcom PMB (Power Management Bus) driver"
|
bool "Broadcom PMB (Power Management Bus) driver"
|
||||||
depends on ARCH_BCM4908 || (COMPILE_TEST && OF)
|
depends on ARCH_BCMBCA || (COMPILE_TEST && OF)
|
||||||
default ARCH_BCM4908
|
default ARCH_BCMBCA
|
||||||
select PM_GENERIC_DOMAINS if PM
|
select PM_GENERIC_DOMAINS if PM
|
||||||
help
|
help
|
||||||
This enables support for the Broadcom's PMB (Power Management Bus) that
|
This enables support for the Broadcom's PMB (Power Management Bus) that
|
||||||
|
|
|
@ -25,7 +25,6 @@
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/memblock.h>
|
#include <linux/memblock.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/notifier.h>
|
|
||||||
#include <linux/of.h>
|
#include <linux/of.h>
|
||||||
#include <linux/of_address.h>
|
#include <linux/of_address.h>
|
||||||
#include <linux/panic_notifier.h>
|
#include <linux/panic_notifier.h>
|
||||||
|
@ -664,7 +663,20 @@ static void __iomem *brcmstb_ioremap_match(const struct of_device_id *matches,
|
||||||
|
|
||||||
return of_io_request_and_map(dn, index, dn->full_name);
|
return of_io_request_and_map(dn, index, dn->full_name);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* The AON is a small domain in the SoC that can retain its state across
|
||||||
|
* various system wide sleep states and specific reset conditions; the
|
||||||
|
* AON DATA RAM is a small RAM of a few words (< 1KB) which can store
|
||||||
|
* persistent information across such events.
|
||||||
|
*
|
||||||
|
* The purpose of the below panic notifier is to help with notifying
|
||||||
|
* the bootloader that a panic occurred and so that it should try its
|
||||||
|
* best to preserve the DRAM contents holding that buffer for recovery
|
||||||
|
* by the kernel as opposed to wiping out DRAM clean again.
|
||||||
|
*
|
||||||
|
* Reference: comment from Florian Fainelli, at
|
||||||
|
* https://lore.kernel.org/lkml/781cafb0-8d06-8b56-907a-5175c2da196a@gmail.com
|
||||||
|
*/
|
||||||
static int brcmstb_pm_panic_notify(struct notifier_block *nb,
|
static int brcmstb_pm_panic_notify(struct notifier_block *nb,
|
||||||
unsigned long action, void *data)
|
unsigned long action, void *data)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,4 +20,12 @@ config SOC_IMX8M
|
||||||
support, it will provide the SoC info like SoC family,
|
support, it will provide the SoC info like SoC family,
|
||||||
ID and revision etc.
|
ID and revision etc.
|
||||||
|
|
||||||
|
config SOC_IMX9
|
||||||
|
tristate "i.MX9 SoC family support"
|
||||||
|
depends on ARCH_MXC || COMPILE_TEST
|
||||||
|
default ARCH_MXC && ARM64
|
||||||
|
select SOC_BUS
|
||||||
|
help
|
||||||
|
If you say yes here, you get support for the NXP i.MX9 family
|
||||||
|
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -7,3 +7,5 @@ obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
|
||||||
obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o
|
obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o
|
||||||
obj-$(CONFIG_SOC_IMX8M) += imx8m-blk-ctrl.o
|
obj-$(CONFIG_SOC_IMX8M) += imx8m-blk-ctrl.o
|
||||||
obj-$(CONFIG_SOC_IMX8M) += imx8mp-blk-ctrl.o
|
obj-$(CONFIG_SOC_IMX8M) += imx8mp-blk-ctrl.o
|
||||||
|
obj-$(CONFIG_SOC_IMX9) += imx93-src.o imx93-pd.o
|
||||||
|
obj-$(CONFIG_SOC_IMX9) += imx93-blk-ctrl.o
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include <linux/interconnect.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
@ -37,6 +38,8 @@ struct imx8m_blk_ctrl_domain_data {
|
||||||
const char *name;
|
const char *name;
|
||||||
const char * const *clk_names;
|
const char * const *clk_names;
|
||||||
int num_clks;
|
int num_clks;
|
||||||
|
const char * const *path_names;
|
||||||
|
int num_paths;
|
||||||
const char *gpc_name;
|
const char *gpc_name;
|
||||||
u32 rst_mask;
|
u32 rst_mask;
|
||||||
u32 clk_mask;
|
u32 clk_mask;
|
||||||
|
@ -52,13 +55,16 @@ struct imx8m_blk_ctrl_domain_data {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DOMAIN_MAX_CLKS 4
|
#define DOMAIN_MAX_CLKS 4
|
||||||
|
#define DOMAIN_MAX_PATHS 4
|
||||||
|
|
||||||
struct imx8m_blk_ctrl_domain {
|
struct imx8m_blk_ctrl_domain {
|
||||||
struct generic_pm_domain genpd;
|
struct generic_pm_domain genpd;
|
||||||
const struct imx8m_blk_ctrl_domain_data *data;
|
const struct imx8m_blk_ctrl_domain_data *data;
|
||||||
struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
|
struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
|
||||||
|
struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
|
||||||
struct device *power_dev;
|
struct device *power_dev;
|
||||||
struct imx8m_blk_ctrl *bc;
|
struct imx8m_blk_ctrl *bc;
|
||||||
|
int num_paths;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct imx8m_blk_ctrl_data {
|
struct imx8m_blk_ctrl_data {
|
||||||
|
@ -117,6 +123,10 @@ static int imx8m_blk_ctrl_power_on(struct generic_pm_domain *genpd)
|
||||||
if (data->mipi_phy_rst_mask)
|
if (data->mipi_phy_rst_mask)
|
||||||
regmap_set_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
|
regmap_set_bits(bc->regmap, BLK_MIPI_RESET_DIV, data->mipi_phy_rst_mask);
|
||||||
|
|
||||||
|
ret = icc_bulk_set_bw(domain->num_paths, domain->paths);
|
||||||
|
if (ret)
|
||||||
|
dev_err(bc->dev, "failed to set icc bw\n");
|
||||||
|
|
||||||
/* disable upstream clocks */
|
/* disable upstream clocks */
|
||||||
clk_bulk_disable_unprepare(data->num_clks, domain->clks);
|
clk_bulk_disable_unprepare(data->num_clks, domain->clks);
|
||||||
|
|
||||||
|
@ -152,19 +162,6 @@ static int imx8m_blk_ctrl_power_off(struct generic_pm_domain *genpd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct generic_pm_domain *
|
|
||||||
imx8m_blk_ctrl_xlate(struct of_phandle_args *args, void *data)
|
|
||||||
{
|
|
||||||
struct genpd_onecell_data *onecell_data = data;
|
|
||||||
unsigned int index = args->args[0];
|
|
||||||
|
|
||||||
if (args->args_count != 1 ||
|
|
||||||
index >= onecell_data->num_domains)
|
|
||||||
return ERR_PTR(-EINVAL);
|
|
||||||
|
|
||||||
return onecell_data->domains[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct lock_class_key blk_ctrl_genpd_lock_class;
|
static struct lock_class_key blk_ctrl_genpd_lock_class;
|
||||||
|
|
||||||
static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
|
static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
|
||||||
|
@ -206,7 +203,6 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
bc->onecell_data.num_domains = bc_data->num_domains;
|
bc->onecell_data.num_domains = bc_data->num_domains;
|
||||||
bc->onecell_data.xlate = imx8m_blk_ctrl_xlate;
|
|
||||||
bc->onecell_data.domains =
|
bc->onecell_data.domains =
|
||||||
devm_kcalloc(dev, bc_data->num_domains,
|
devm_kcalloc(dev, bc_data->num_domains,
|
||||||
sizeof(struct generic_pm_domain *), GFP_KERNEL);
|
sizeof(struct generic_pm_domain *), GFP_KERNEL);
|
||||||
|
@ -224,10 +220,29 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
domain->data = data;
|
domain->data = data;
|
||||||
|
domain->num_paths = data->num_paths;
|
||||||
|
|
||||||
for (j = 0; j < data->num_clks; j++)
|
for (j = 0; j < data->num_clks; j++)
|
||||||
domain->clks[j].id = data->clk_names[j];
|
domain->clks[j].id = data->clk_names[j];
|
||||||
|
|
||||||
|
for (j = 0; j < data->num_paths; j++) {
|
||||||
|
domain->paths[j].name = data->path_names[j];
|
||||||
|
/* Fake value for now, just let ICC could configure NoC mode/priority */
|
||||||
|
domain->paths[j].avg_bw = 1;
|
||||||
|
domain->paths[j].peak_bw = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = devm_of_icc_bulk_get(dev, data->num_paths, domain->paths);
|
||||||
|
if (ret) {
|
||||||
|
if (ret != -EPROBE_DEFER) {
|
||||||
|
dev_warn_once(dev, "Could not get interconnect paths, NoC will stay unconfigured!\n");
|
||||||
|
domain->num_paths = 0;
|
||||||
|
} else {
|
||||||
|
dev_err_probe(dev, ret, "failed to get noc entries\n");
|
||||||
|
goto cleanup_pds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
|
ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err_probe(dev, ret, "failed to get clock\n");
|
dev_err_probe(dev, ret, "failed to get clock\n");
|
||||||
|
@ -454,6 +469,46 @@ static const struct imx8m_blk_ctrl_data imx8mm_vpu_blk_ctl_dev_data = {
|
||||||
.num_domains = ARRAY_SIZE(imx8mm_vpu_blk_ctl_domain_data),
|
.num_domains = ARRAY_SIZE(imx8mm_vpu_blk_ctl_domain_data),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct imx8m_blk_ctrl_domain_data imx8mp_vpu_blk_ctl_domain_data[] = {
|
||||||
|
[IMX8MP_VPUBLK_PD_G1] = {
|
||||||
|
.name = "vpublk-g1",
|
||||||
|
.clk_names = (const char *[]){ "g1", },
|
||||||
|
.num_clks = 1,
|
||||||
|
.gpc_name = "g1",
|
||||||
|
.rst_mask = BIT(1),
|
||||||
|
.clk_mask = BIT(1),
|
||||||
|
.path_names = (const char *[]){"g1"},
|
||||||
|
.num_paths = 1,
|
||||||
|
},
|
||||||
|
[IMX8MP_VPUBLK_PD_G2] = {
|
||||||
|
.name = "vpublk-g2",
|
||||||
|
.clk_names = (const char *[]){ "g2", },
|
||||||
|
.num_clks = 1,
|
||||||
|
.gpc_name = "g2",
|
||||||
|
.rst_mask = BIT(0),
|
||||||
|
.clk_mask = BIT(0),
|
||||||
|
.path_names = (const char *[]){"g2"},
|
||||||
|
.num_paths = 1,
|
||||||
|
},
|
||||||
|
[IMX8MP_VPUBLK_PD_VC8000E] = {
|
||||||
|
.name = "vpublk-vc8000e",
|
||||||
|
.clk_names = (const char *[]){ "vc8000e", },
|
||||||
|
.num_clks = 1,
|
||||||
|
.gpc_name = "vc8000e",
|
||||||
|
.rst_mask = BIT(2),
|
||||||
|
.clk_mask = BIT(2),
|
||||||
|
.path_names = (const char *[]){"vc8000e"},
|
||||||
|
.num_paths = 1,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct imx8m_blk_ctrl_data imx8mp_vpu_blk_ctl_dev_data = {
|
||||||
|
.max_reg = 0x18,
|
||||||
|
.power_notifier_fn = imx8mm_vpu_power_notifier,
|
||||||
|
.domains = imx8mp_vpu_blk_ctl_domain_data,
|
||||||
|
.num_domains = ARRAY_SIZE(imx8mp_vpu_blk_ctl_domain_data),
|
||||||
|
};
|
||||||
|
|
||||||
static int imx8mm_disp_power_notifier(struct notifier_block *nb,
|
static int imx8mm_disp_power_notifier(struct notifier_block *nb,
|
||||||
unsigned long action, void *data)
|
unsigned long action, void *data)
|
||||||
{
|
{
|
||||||
|
@ -649,6 +704,8 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[
|
||||||
.gpc_name = "lcdif1",
|
.gpc_name = "lcdif1",
|
||||||
.rst_mask = BIT(4) | BIT(5) | BIT(23),
|
.rst_mask = BIT(4) | BIT(5) | BIT(23),
|
||||||
.clk_mask = BIT(4) | BIT(5) | BIT(23),
|
.clk_mask = BIT(4) | BIT(5) | BIT(23),
|
||||||
|
.path_names = (const char *[]){"lcdif-rd", "lcdif-wr"},
|
||||||
|
.num_paths = 2,
|
||||||
},
|
},
|
||||||
[IMX8MP_MEDIABLK_PD_ISI] = {
|
[IMX8MP_MEDIABLK_PD_ISI] = {
|
||||||
.name = "mediablk-isi",
|
.name = "mediablk-isi",
|
||||||
|
@ -657,6 +714,8 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[
|
||||||
.gpc_name = "isi",
|
.gpc_name = "isi",
|
||||||
.rst_mask = BIT(6) | BIT(7),
|
.rst_mask = BIT(6) | BIT(7),
|
||||||
.clk_mask = BIT(6) | BIT(7),
|
.clk_mask = BIT(6) | BIT(7),
|
||||||
|
.path_names = (const char *[]){"isi0", "isi1", "isi2"},
|
||||||
|
.num_paths = 3,
|
||||||
},
|
},
|
||||||
[IMX8MP_MEDIABLK_PD_MIPI_CSI2_2] = {
|
[IMX8MP_MEDIABLK_PD_MIPI_CSI2_2] = {
|
||||||
.name = "mediablk-mipi-csi2-2",
|
.name = "mediablk-mipi-csi2-2",
|
||||||
|
@ -674,6 +733,8 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[
|
||||||
.gpc_name = "lcdif2",
|
.gpc_name = "lcdif2",
|
||||||
.rst_mask = BIT(11) | BIT(12) | BIT(24),
|
.rst_mask = BIT(11) | BIT(12) | BIT(24),
|
||||||
.clk_mask = BIT(11) | BIT(12) | BIT(24),
|
.clk_mask = BIT(11) | BIT(12) | BIT(24),
|
||||||
|
.path_names = (const char *[]){"lcdif-rd", "lcdif-wr"},
|
||||||
|
.num_paths = 2,
|
||||||
},
|
},
|
||||||
[IMX8MP_MEDIABLK_PD_ISP] = {
|
[IMX8MP_MEDIABLK_PD_ISP] = {
|
||||||
.name = "mediablk-isp",
|
.name = "mediablk-isp",
|
||||||
|
@ -682,6 +743,8 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[
|
||||||
.gpc_name = "isp",
|
.gpc_name = "isp",
|
||||||
.rst_mask = BIT(16) | BIT(17) | BIT(18),
|
.rst_mask = BIT(16) | BIT(17) | BIT(18),
|
||||||
.clk_mask = BIT(16) | BIT(17) | BIT(18),
|
.clk_mask = BIT(16) | BIT(17) | BIT(18),
|
||||||
|
.path_names = (const char *[]){"isp0", "isp1"},
|
||||||
|
.num_paths = 2,
|
||||||
},
|
},
|
||||||
[IMX8MP_MEDIABLK_PD_DWE] = {
|
[IMX8MP_MEDIABLK_PD_DWE] = {
|
||||||
.name = "mediablk-dwe",
|
.name = "mediablk-dwe",
|
||||||
|
@ -690,6 +753,8 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[
|
||||||
.gpc_name = "dwe",
|
.gpc_name = "dwe",
|
||||||
.rst_mask = BIT(19) | BIT(20) | BIT(21),
|
.rst_mask = BIT(19) | BIT(20) | BIT(21),
|
||||||
.clk_mask = BIT(19) | BIT(20) | BIT(21),
|
.clk_mask = BIT(19) | BIT(20) | BIT(21),
|
||||||
|
.path_names = (const char *[]){"dwe"},
|
||||||
|
.num_paths = 1,
|
||||||
},
|
},
|
||||||
[IMX8MP_MEDIABLK_PD_MIPI_DSI_2] = {
|
[IMX8MP_MEDIABLK_PD_MIPI_DSI_2] = {
|
||||||
.name = "mediablk-mipi-dsi-2",
|
.name = "mediablk-mipi-dsi-2",
|
||||||
|
@ -787,6 +852,9 @@ static const struct of_device_id imx8m_blk_ctrl_of_match[] = {
|
||||||
}, {
|
}, {
|
||||||
.compatible = "fsl,imx8mq-vpu-blk-ctrl",
|
.compatible = "fsl,imx8mq-vpu-blk-ctrl",
|
||||||
.data = &imx8mq_vpu_blk_ctl_dev_data
|
.data = &imx8mq_vpu_blk_ctl_dev_data
|
||||||
|
}, {
|
||||||
|
.compatible = "fsl,imx8mp-vpu-blk-ctrl",
|
||||||
|
.data = &imx8mp_vpu_blk_ctl_dev_data
|
||||||
}, {
|
}, {
|
||||||
/* Sentinel */
|
/* Sentinel */
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/device.h>
|
#include <linux/device.h>
|
||||||
|
#include <linux/interconnect.h>
|
||||||
#include <linux/module.h>
|
#include <linux/module.h>
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
|
@ -18,6 +19,8 @@
|
||||||
#define GPR_REG0 0x0
|
#define GPR_REG0 0x0
|
||||||
#define PCIE_CLOCK_MODULE_EN BIT(0)
|
#define PCIE_CLOCK_MODULE_EN BIT(0)
|
||||||
#define USB_CLOCK_MODULE_EN BIT(1)
|
#define USB_CLOCK_MODULE_EN BIT(1)
|
||||||
|
#define PCIE_PHY_APB_RST BIT(4)
|
||||||
|
#define PCIE_PHY_INIT_RST BIT(5)
|
||||||
|
|
||||||
struct imx8mp_blk_ctrl_domain;
|
struct imx8mp_blk_ctrl_domain;
|
||||||
|
|
||||||
|
@ -36,17 +39,22 @@ struct imx8mp_blk_ctrl_domain_data {
|
||||||
const char *name;
|
const char *name;
|
||||||
const char * const *clk_names;
|
const char * const *clk_names;
|
||||||
int num_clks;
|
int num_clks;
|
||||||
|
const char * const *path_names;
|
||||||
|
int num_paths;
|
||||||
const char *gpc_name;
|
const char *gpc_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define DOMAIN_MAX_CLKS 2
|
#define DOMAIN_MAX_CLKS 2
|
||||||
|
#define DOMAIN_MAX_PATHS 3
|
||||||
|
|
||||||
struct imx8mp_blk_ctrl_domain {
|
struct imx8mp_blk_ctrl_domain {
|
||||||
struct generic_pm_domain genpd;
|
struct generic_pm_domain genpd;
|
||||||
const struct imx8mp_blk_ctrl_domain_data *data;
|
const struct imx8mp_blk_ctrl_domain_data *data;
|
||||||
struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
|
struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
|
||||||
|
struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
|
||||||
struct device *power_dev;
|
struct device *power_dev;
|
||||||
struct imx8mp_blk_ctrl *bc;
|
struct imx8mp_blk_ctrl *bc;
|
||||||
|
int num_paths;
|
||||||
int id;
|
int id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -75,6 +83,10 @@ static void imx8mp_hsio_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
|
||||||
case IMX8MP_HSIOBLK_PD_PCIE:
|
case IMX8MP_HSIOBLK_PD_PCIE:
|
||||||
regmap_set_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
|
regmap_set_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
|
||||||
break;
|
break;
|
||||||
|
case IMX8MP_HSIOBLK_PD_PCIE_PHY:
|
||||||
|
regmap_set_bits(bc->regmap, GPR_REG0,
|
||||||
|
PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -90,6 +102,10 @@ static void imx8mp_hsio_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
|
||||||
case IMX8MP_HSIOBLK_PD_PCIE:
|
case IMX8MP_HSIOBLK_PD_PCIE:
|
||||||
regmap_clear_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
|
regmap_clear_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
|
||||||
break;
|
break;
|
||||||
|
case IMX8MP_HSIOBLK_PD_PCIE_PHY:
|
||||||
|
regmap_clear_bits(bc->regmap, GPR_REG0,
|
||||||
|
PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -144,6 +160,8 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = {
|
||||||
.clk_names = (const char *[]){ "usb" },
|
.clk_names = (const char *[]){ "usb" },
|
||||||
.num_clks = 1,
|
.num_clks = 1,
|
||||||
.gpc_name = "usb",
|
.gpc_name = "usb",
|
||||||
|
.path_names = (const char *[]){"usb1", "usb2"},
|
||||||
|
.num_paths = 2,
|
||||||
},
|
},
|
||||||
[IMX8MP_HSIOBLK_PD_USB_PHY1] = {
|
[IMX8MP_HSIOBLK_PD_USB_PHY1] = {
|
||||||
.name = "hsioblk-usb-phy1",
|
.name = "hsioblk-usb-phy1",
|
||||||
|
@ -158,6 +176,8 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = {
|
||||||
.clk_names = (const char *[]){ "pcie" },
|
.clk_names = (const char *[]){ "pcie" },
|
||||||
.num_clks = 1,
|
.num_clks = 1,
|
||||||
.gpc_name = "pcie",
|
.gpc_name = "pcie",
|
||||||
|
.path_names = (const char *[]){"noc-pcie", "pcie"},
|
||||||
|
.num_paths = 2,
|
||||||
},
|
},
|
||||||
[IMX8MP_HSIOBLK_PD_PCIE_PHY] = {
|
[IMX8MP_HSIOBLK_PD_PCIE_PHY] = {
|
||||||
.name = "hsioblk-pcie-phy",
|
.name = "hsioblk-pcie-phy",
|
||||||
|
@ -225,6 +245,13 @@ static void imx8mp_hdmi_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
|
||||||
regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
|
regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
|
||||||
regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
|
regmap_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
|
||||||
break;
|
break;
|
||||||
|
case IMX8MP_HDMIBLK_PD_HDCP:
|
||||||
|
regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11));
|
||||||
|
break;
|
||||||
|
case IMX8MP_HDMIBLK_PD_HRV:
|
||||||
|
regmap_set_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5));
|
||||||
|
regmap_set_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -273,6 +300,13 @@ static void imx8mp_hdmi_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
|
||||||
regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
|
regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(12));
|
||||||
regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
|
regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(22) | BIT(24));
|
||||||
break;
|
break;
|
||||||
|
case IMX8MP_HDMIBLK_PD_HDCP:
|
||||||
|
regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL0, BIT(11));
|
||||||
|
break;
|
||||||
|
case IMX8MP_HDMIBLK_PD_HRV:
|
||||||
|
regmap_clear_bits(bc->regmap, HDMI_RTX_RESET_CTL0, BIT(15));
|
||||||
|
regmap_clear_bits(bc->regmap, HDMI_RTX_CLK_CTL1, BIT(3) | BIT(4) | BIT(5));
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -322,6 +356,8 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = {
|
||||||
.clk_names = (const char *[]){ "axi", "apb" },
|
.clk_names = (const char *[]){ "axi", "apb" },
|
||||||
.num_clks = 2,
|
.num_clks = 2,
|
||||||
.gpc_name = "lcdif",
|
.gpc_name = "lcdif",
|
||||||
|
.path_names = (const char *[]){"lcdif-hdmi"},
|
||||||
|
.num_paths = 1,
|
||||||
},
|
},
|
||||||
[IMX8MP_HDMIBLK_PD_PAI] = {
|
[IMX8MP_HDMIBLK_PD_PAI] = {
|
||||||
.name = "hdmiblk-pai",
|
.name = "hdmiblk-pai",
|
||||||
|
@ -353,6 +389,22 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = {
|
||||||
.num_clks = 2,
|
.num_clks = 2,
|
||||||
.gpc_name = "hdmi-tx-phy",
|
.gpc_name = "hdmi-tx-phy",
|
||||||
},
|
},
|
||||||
|
[IMX8MP_HDMIBLK_PD_HRV] = {
|
||||||
|
.name = "hdmiblk-hrv",
|
||||||
|
.clk_names = (const char *[]){ "axi", "apb" },
|
||||||
|
.num_clks = 2,
|
||||||
|
.gpc_name = "hrv",
|
||||||
|
.path_names = (const char *[]){"hrv"},
|
||||||
|
.num_paths = 1,
|
||||||
|
},
|
||||||
|
[IMX8MP_HDMIBLK_PD_HDCP] = {
|
||||||
|
.name = "hdmiblk-hdcp",
|
||||||
|
.clk_names = (const char *[]){ "axi", "apb" },
|
||||||
|
.num_clks = 2,
|
||||||
|
.gpc_name = "hdcp",
|
||||||
|
.path_names = (const char *[]){"hdcp"},
|
||||||
|
.num_paths = 1,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct imx8mp_blk_ctrl_data imx8mp_hdmi_blk_ctl_dev_data = {
|
static const struct imx8mp_blk_ctrl_data imx8mp_hdmi_blk_ctl_dev_data = {
|
||||||
|
@ -395,6 +447,10 @@ static int imx8mp_blk_ctrl_power_on(struct generic_pm_domain *genpd)
|
||||||
goto clk_disable;
|
goto clk_disable;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ret = icc_bulk_set_bw(domain->num_paths, domain->paths);
|
||||||
|
if (ret)
|
||||||
|
dev_err(bc->dev, "failed to set icc bw\n");
|
||||||
|
|
||||||
clk_bulk_disable_unprepare(data->num_clks, domain->clks);
|
clk_bulk_disable_unprepare(data->num_clks, domain->clks);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -434,19 +490,6 @@ static int imx8mp_blk_ctrl_power_off(struct generic_pm_domain *genpd)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct generic_pm_domain *
|
|
||||||
imx8m_blk_ctrl_xlate(struct of_phandle_args *args, void *data)
|
|
||||||
{
|
|
||||||
struct genpd_onecell_data *onecell_data = data;
|
|
||||||
unsigned int index = args->args[0];
|
|
||||||
|
|
||||||
if (args->args_count != 1 ||
|
|
||||||
index >= onecell_data->num_domains)
|
|
||||||
return ERR_PTR(-EINVAL);
|
|
||||||
|
|
||||||
return onecell_data->domains[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
static struct lock_class_key blk_ctrl_genpd_lock_class;
|
static struct lock_class_key blk_ctrl_genpd_lock_class;
|
||||||
|
|
||||||
static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
|
static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
|
||||||
|
@ -489,7 +532,6 @@ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
bc->onecell_data.num_domains = num_domains;
|
bc->onecell_data.num_domains = num_domains;
|
||||||
bc->onecell_data.xlate = imx8m_blk_ctrl_xlate;
|
|
||||||
bc->onecell_data.domains =
|
bc->onecell_data.domains =
|
||||||
devm_kcalloc(dev, num_domains,
|
devm_kcalloc(dev, num_domains,
|
||||||
sizeof(struct generic_pm_domain *), GFP_KERNEL);
|
sizeof(struct generic_pm_domain *), GFP_KERNEL);
|
||||||
|
@ -510,10 +552,29 @@ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
|
||||||
int j;
|
int j;
|
||||||
|
|
||||||
domain->data = data;
|
domain->data = data;
|
||||||
|
domain->num_paths = data->num_paths;
|
||||||
|
|
||||||
for (j = 0; j < data->num_clks; j++)
|
for (j = 0; j < data->num_clks; j++)
|
||||||
domain->clks[j].id = data->clk_names[j];
|
domain->clks[j].id = data->clk_names[j];
|
||||||
|
|
||||||
|
for (j = 0; j < data->num_paths; j++) {
|
||||||
|
domain->paths[j].name = data->path_names[j];
|
||||||
|
/* Fake value for now, just let ICC could configure NoC mode/priority */
|
||||||
|
domain->paths[j].avg_bw = 1;
|
||||||
|
domain->paths[j].peak_bw = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = devm_of_icc_bulk_get(dev, data->num_paths, domain->paths);
|
||||||
|
if (ret) {
|
||||||
|
if (ret != -EPROBE_DEFER) {
|
||||||
|
dev_warn_once(dev, "Could not get interconnect paths, NoC will stay unconfigured!\n");
|
||||||
|
domain->num_paths = 0;
|
||||||
|
} else {
|
||||||
|
dev_err_probe(dev, ret, "failed to get noc entries\n");
|
||||||
|
goto cleanup_pds;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
|
ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err_probe(dev, ret, "failed to get clock\n");
|
dev_err_probe(dev, ret, "failed to get clock\n");
|
||||||
|
|
436
drivers/soc/imx/imx93-blk-ctrl.c
Normal file
436
drivers/soc/imx/imx93-blk-ctrl.c
Normal file
|
@ -0,0 +1,436 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/*
|
||||||
|
* Copyright 2022 NXP, Peng Fan <peng.fan@nxp.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/pm_domain.h>
|
||||||
|
#include <linux/pm_runtime.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
#include <linux/sizes.h>
|
||||||
|
|
||||||
|
#include <dt-bindings/power/fsl,imx93-power.h>
|
||||||
|
|
||||||
|
#define BLK_SFT_RSTN 0x0
|
||||||
|
#define BLK_CLK_EN 0x4
|
||||||
|
#define BLK_MAX_CLKS 4
|
||||||
|
|
||||||
|
#define DOMAIN_MAX_CLKS 4
|
||||||
|
|
||||||
|
#define LCDIF_QOS_REG 0xC
|
||||||
|
#define LCDIF_DEFAULT_QOS_OFF 12
|
||||||
|
#define LCDIF_CFG_QOS_OFF 8
|
||||||
|
|
||||||
|
#define PXP_QOS_REG 0x10
|
||||||
|
#define PXP_R_DEFAULT_QOS_OFF 28
|
||||||
|
#define PXP_R_CFG_QOS_OFF 24
|
||||||
|
#define PXP_W_DEFAULT_QOS_OFF 20
|
||||||
|
#define PXP_W_CFG_QOS_OFF 16
|
||||||
|
|
||||||
|
#define ISI_CACHE_REG 0x14
|
||||||
|
|
||||||
|
#define ISI_QOS_REG 0x1C
|
||||||
|
#define ISI_V_DEFAULT_QOS_OFF 28
|
||||||
|
#define ISI_V_CFG_QOS_OFF 24
|
||||||
|
#define ISI_U_DEFAULT_QOS_OFF 20
|
||||||
|
#define ISI_U_CFG_QOS_OFF 16
|
||||||
|
#define ISI_Y_R_DEFAULT_QOS_OFF 12
|
||||||
|
#define ISI_Y_R_CFG_QOS_OFF 8
|
||||||
|
#define ISI_Y_W_DEFAULT_QOS_OFF 4
|
||||||
|
#define ISI_Y_W_CFG_QOS_OFF 0
|
||||||
|
|
||||||
|
#define PRIO_MASK 0xF
|
||||||
|
|
||||||
|
#define PRIO(X) (X)
|
||||||
|
|
||||||
|
struct imx93_blk_ctrl_domain;
|
||||||
|
|
||||||
|
struct imx93_blk_ctrl {
|
||||||
|
struct device *dev;
|
||||||
|
struct regmap *regmap;
|
||||||
|
int num_clks;
|
||||||
|
struct clk_bulk_data clks[BLK_MAX_CLKS];
|
||||||
|
struct imx93_blk_ctrl_domain *domains;
|
||||||
|
struct genpd_onecell_data onecell_data;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define DOMAIN_MAX_QOS 4
|
||||||
|
|
||||||
|
struct imx93_blk_ctrl_qos {
|
||||||
|
u32 reg;
|
||||||
|
u32 cfg_off;
|
||||||
|
u32 default_prio;
|
||||||
|
u32 cfg_prio;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct imx93_blk_ctrl_domain_data {
|
||||||
|
const char *name;
|
||||||
|
const char * const *clk_names;
|
||||||
|
int num_clks;
|
||||||
|
u32 rst_mask;
|
||||||
|
u32 clk_mask;
|
||||||
|
int num_qos;
|
||||||
|
struct imx93_blk_ctrl_qos qos[DOMAIN_MAX_QOS];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct imx93_blk_ctrl_domain {
|
||||||
|
struct generic_pm_domain genpd;
|
||||||
|
const struct imx93_blk_ctrl_domain_data *data;
|
||||||
|
struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
|
||||||
|
struct imx93_blk_ctrl *bc;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct imx93_blk_ctrl_data {
|
||||||
|
const struct imx93_blk_ctrl_domain_data *domains;
|
||||||
|
int num_domains;
|
||||||
|
const char * const *clk_names;
|
||||||
|
int num_clks;
|
||||||
|
const struct regmap_access_table *reg_access_table;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline struct imx93_blk_ctrl_domain *
|
||||||
|
to_imx93_blk_ctrl_domain(struct generic_pm_domain *genpd)
|
||||||
|
{
|
||||||
|
return container_of(genpd, struct imx93_blk_ctrl_domain, genpd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx93_blk_ctrl_set_qos(struct imx93_blk_ctrl_domain *domain)
|
||||||
|
{
|
||||||
|
const struct imx93_blk_ctrl_domain_data *data = domain->data;
|
||||||
|
struct imx93_blk_ctrl *bc = domain->bc;
|
||||||
|
const struct imx93_blk_ctrl_qos *qos;
|
||||||
|
u32 val, mask;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < data->num_qos; i++) {
|
||||||
|
qos = &data->qos[i];
|
||||||
|
|
||||||
|
mask = PRIO_MASK << qos->cfg_off;
|
||||||
|
mask |= PRIO_MASK << (qos->cfg_off + 4);
|
||||||
|
val = qos->cfg_prio << qos->cfg_off;
|
||||||
|
val |= qos->default_prio << (qos->cfg_off + 4);
|
||||||
|
|
||||||
|
regmap_write_bits(bc->regmap, qos->reg, mask, val);
|
||||||
|
|
||||||
|
dev_dbg(bc->dev, "data->qos[i].reg 0x%x 0x%x\n", qos->reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx93_blk_ctrl_power_on(struct generic_pm_domain *genpd)
|
||||||
|
{
|
||||||
|
struct imx93_blk_ctrl_domain *domain = to_imx93_blk_ctrl_domain(genpd);
|
||||||
|
const struct imx93_blk_ctrl_domain_data *data = domain->data;
|
||||||
|
struct imx93_blk_ctrl *bc = domain->bc;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = clk_bulk_prepare_enable(bc->num_clks, bc->clks);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(bc->dev, "failed to enable bus clocks\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = clk_bulk_prepare_enable(data->num_clks, domain->clks);
|
||||||
|
if (ret) {
|
||||||
|
clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
|
||||||
|
dev_err(bc->dev, "failed to enable clocks\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pm_runtime_get_sync(bc->dev);
|
||||||
|
if (ret < 0) {
|
||||||
|
pm_runtime_put_noidle(bc->dev);
|
||||||
|
dev_err(bc->dev, "failed to power up domain\n");
|
||||||
|
goto disable_clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ungate clk */
|
||||||
|
regmap_clear_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
|
||||||
|
|
||||||
|
/* release reset */
|
||||||
|
regmap_set_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
|
||||||
|
|
||||||
|
dev_dbg(bc->dev, "pd_on: name: %s\n", genpd->name);
|
||||||
|
|
||||||
|
return imx93_blk_ctrl_set_qos(domain);
|
||||||
|
|
||||||
|
disable_clk:
|
||||||
|
clk_bulk_disable_unprepare(data->num_clks, domain->clks);
|
||||||
|
|
||||||
|
clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx93_blk_ctrl_power_off(struct generic_pm_domain *genpd)
|
||||||
|
{
|
||||||
|
struct imx93_blk_ctrl_domain *domain = to_imx93_blk_ctrl_domain(genpd);
|
||||||
|
const struct imx93_blk_ctrl_domain_data *data = domain->data;
|
||||||
|
struct imx93_blk_ctrl *bc = domain->bc;
|
||||||
|
|
||||||
|
dev_dbg(bc->dev, "pd_off: name: %s\n", genpd->name);
|
||||||
|
|
||||||
|
regmap_clear_bits(bc->regmap, BLK_SFT_RSTN, data->rst_mask);
|
||||||
|
regmap_set_bits(bc->regmap, BLK_CLK_EN, data->clk_mask);
|
||||||
|
|
||||||
|
pm_runtime_put(bc->dev);
|
||||||
|
|
||||||
|
clk_bulk_disable_unprepare(data->num_clks, domain->clks);
|
||||||
|
|
||||||
|
clk_bulk_disable_unprepare(bc->num_clks, bc->clks);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx93_blk_ctrl_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
const struct imx93_blk_ctrl_data *bc_data = of_device_get_match_data(dev);
|
||||||
|
struct imx93_blk_ctrl *bc;
|
||||||
|
void __iomem *base;
|
||||||
|
int i, ret;
|
||||||
|
|
||||||
|
struct regmap_config regmap_config = {
|
||||||
|
.reg_bits = 32,
|
||||||
|
.val_bits = 32,
|
||||||
|
.reg_stride = 4,
|
||||||
|
.rd_table = bc_data->reg_access_table,
|
||||||
|
.wr_table = bc_data->reg_access_table,
|
||||||
|
.max_register = SZ_4K,
|
||||||
|
};
|
||||||
|
|
||||||
|
bc = devm_kzalloc(dev, sizeof(*bc), GFP_KERNEL);
|
||||||
|
if (!bc)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
bc->dev = dev;
|
||||||
|
|
||||||
|
base = devm_platform_ioremap_resource(pdev, 0);
|
||||||
|
if (IS_ERR(base))
|
||||||
|
return PTR_ERR(base);
|
||||||
|
|
||||||
|
bc->regmap = devm_regmap_init_mmio(dev, base, ®map_config);
|
||||||
|
if (IS_ERR(bc->regmap))
|
||||||
|
return dev_err_probe(dev, PTR_ERR(bc->regmap),
|
||||||
|
"failed to init regmap\n");
|
||||||
|
|
||||||
|
bc->domains = devm_kcalloc(dev, bc_data->num_domains,
|
||||||
|
sizeof(struct imx93_blk_ctrl_domain),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!bc->domains)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
bc->onecell_data.num_domains = bc_data->num_domains;
|
||||||
|
bc->onecell_data.domains =
|
||||||
|
devm_kcalloc(dev, bc_data->num_domains,
|
||||||
|
sizeof(struct generic_pm_domain *), GFP_KERNEL);
|
||||||
|
if (!bc->onecell_data.domains)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
for (i = 0; i < bc_data->num_clks; i++)
|
||||||
|
bc->clks[i].id = bc_data->clk_names[i];
|
||||||
|
bc->num_clks = bc_data->num_clks;
|
||||||
|
|
||||||
|
ret = devm_clk_bulk_get(dev, bc->num_clks, bc->clks);
|
||||||
|
if (ret) {
|
||||||
|
dev_err_probe(dev, ret, "failed to get bus clock\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < bc_data->num_domains; i++) {
|
||||||
|
const struct imx93_blk_ctrl_domain_data *data = &bc_data->domains[i];
|
||||||
|
struct imx93_blk_ctrl_domain *domain = &bc->domains[i];
|
||||||
|
int j;
|
||||||
|
|
||||||
|
domain->data = data;
|
||||||
|
|
||||||
|
for (j = 0; j < data->num_clks; j++)
|
||||||
|
domain->clks[j].id = data->clk_names[j];
|
||||||
|
|
||||||
|
ret = devm_clk_bulk_get(dev, data->num_clks, domain->clks);
|
||||||
|
if (ret) {
|
||||||
|
dev_err_probe(dev, ret, "failed to get clock\n");
|
||||||
|
goto cleanup_pds;
|
||||||
|
}
|
||||||
|
|
||||||
|
domain->genpd.name = data->name;
|
||||||
|
domain->genpd.power_on = imx93_blk_ctrl_power_on;
|
||||||
|
domain->genpd.power_off = imx93_blk_ctrl_power_off;
|
||||||
|
domain->bc = bc;
|
||||||
|
|
||||||
|
ret = pm_genpd_init(&domain->genpd, NULL, true);
|
||||||
|
if (ret) {
|
||||||
|
dev_err_probe(dev, ret, "failed to init power domain\n");
|
||||||
|
goto cleanup_pds;
|
||||||
|
}
|
||||||
|
|
||||||
|
bc->onecell_data.domains[i] = &domain->genpd;
|
||||||
|
}
|
||||||
|
|
||||||
|
pm_runtime_enable(dev);
|
||||||
|
|
||||||
|
ret = of_genpd_add_provider_onecell(dev->of_node, &bc->onecell_data);
|
||||||
|
if (ret) {
|
||||||
|
dev_err_probe(dev, ret, "failed to add power domain provider\n");
|
||||||
|
goto cleanup_pds;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_set_drvdata(dev, bc);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cleanup_pds:
|
||||||
|
for (i--; i >= 0; i--)
|
||||||
|
pm_genpd_remove(&bc->domains[i].genpd);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx93_blk_ctrl_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct imx93_blk_ctrl *bc = dev_get_drvdata(&pdev->dev);
|
||||||
|
int i;
|
||||||
|
|
||||||
|
of_genpd_del_provider(pdev->dev.of_node);
|
||||||
|
|
||||||
|
for (i = 0; bc->onecell_data.num_domains; i++) {
|
||||||
|
struct imx93_blk_ctrl_domain *domain = &bc->domains[i];
|
||||||
|
|
||||||
|
pm_genpd_remove(&domain->genpd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct imx93_blk_ctrl_domain_data imx93_media_blk_ctl_domain_data[] = {
|
||||||
|
[IMX93_MEDIABLK_PD_MIPI_DSI] = {
|
||||||
|
.name = "mediablk-mipi-dsi",
|
||||||
|
.clk_names = (const char *[]){ "dsi" },
|
||||||
|
.num_clks = 1,
|
||||||
|
.rst_mask = BIT(11) | BIT(12),
|
||||||
|
.clk_mask = BIT(11) | BIT(12),
|
||||||
|
},
|
||||||
|
[IMX93_MEDIABLK_PD_MIPI_CSI] = {
|
||||||
|
.name = "mediablk-mipi-csi",
|
||||||
|
.clk_names = (const char *[]){ "cam", "csi" },
|
||||||
|
.num_clks = 2,
|
||||||
|
.rst_mask = BIT(9) | BIT(10),
|
||||||
|
.clk_mask = BIT(9) | BIT(10),
|
||||||
|
},
|
||||||
|
[IMX93_MEDIABLK_PD_PXP] = {
|
||||||
|
.name = "mediablk-pxp",
|
||||||
|
.clk_names = (const char *[]){ "pxp" },
|
||||||
|
.num_clks = 1,
|
||||||
|
.rst_mask = BIT(7) | BIT(8),
|
||||||
|
.clk_mask = BIT(7) | BIT(8),
|
||||||
|
.num_qos = 2,
|
||||||
|
.qos = {
|
||||||
|
{
|
||||||
|
.reg = PXP_QOS_REG,
|
||||||
|
.cfg_off = PXP_R_CFG_QOS_OFF,
|
||||||
|
.default_prio = PRIO(3),
|
||||||
|
.cfg_prio = PRIO(6),
|
||||||
|
}, {
|
||||||
|
.reg = PXP_QOS_REG,
|
||||||
|
.cfg_off = PXP_W_CFG_QOS_OFF,
|
||||||
|
.default_prio = PRIO(3),
|
||||||
|
.cfg_prio = PRIO(6),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[IMX93_MEDIABLK_PD_LCDIF] = {
|
||||||
|
.name = "mediablk-lcdif",
|
||||||
|
.clk_names = (const char *[]){ "disp", "lcdif" },
|
||||||
|
.num_clks = 2,
|
||||||
|
.rst_mask = BIT(4) | BIT(5) | BIT(6),
|
||||||
|
.clk_mask = BIT(4) | BIT(5) | BIT(6),
|
||||||
|
.num_qos = 1,
|
||||||
|
.qos = {
|
||||||
|
{
|
||||||
|
.reg = LCDIF_QOS_REG,
|
||||||
|
.cfg_off = LCDIF_CFG_QOS_OFF,
|
||||||
|
.default_prio = PRIO(3),
|
||||||
|
.cfg_prio = PRIO(7),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[IMX93_MEDIABLK_PD_ISI] = {
|
||||||
|
.name = "mediablk-isi",
|
||||||
|
.clk_names = (const char *[]){ "isi" },
|
||||||
|
.num_clks = 1,
|
||||||
|
.rst_mask = BIT(2) | BIT(3),
|
||||||
|
.clk_mask = BIT(2) | BIT(3),
|
||||||
|
.num_qos = 4,
|
||||||
|
.qos = {
|
||||||
|
{
|
||||||
|
.reg = ISI_QOS_REG,
|
||||||
|
.cfg_off = ISI_Y_W_CFG_QOS_OFF,
|
||||||
|
.default_prio = PRIO(3),
|
||||||
|
.cfg_prio = PRIO(7),
|
||||||
|
}, {
|
||||||
|
.reg = ISI_QOS_REG,
|
||||||
|
.cfg_off = ISI_Y_R_CFG_QOS_OFF,
|
||||||
|
.default_prio = PRIO(3),
|
||||||
|
.cfg_prio = PRIO(7),
|
||||||
|
}, {
|
||||||
|
.reg = ISI_QOS_REG,
|
||||||
|
.cfg_off = ISI_U_CFG_QOS_OFF,
|
||||||
|
.default_prio = PRIO(3),
|
||||||
|
.cfg_prio = PRIO(7),
|
||||||
|
}, {
|
||||||
|
.reg = ISI_QOS_REG,
|
||||||
|
.cfg_off = ISI_V_CFG_QOS_OFF,
|
||||||
|
.default_prio = PRIO(3),
|
||||||
|
.cfg_prio = PRIO(7),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_range imx93_media_blk_ctl_yes_ranges[] = {
|
||||||
|
regmap_reg_range(BLK_SFT_RSTN, BLK_CLK_EN),
|
||||||
|
regmap_reg_range(LCDIF_QOS_REG, ISI_CACHE_REG),
|
||||||
|
regmap_reg_range(ISI_QOS_REG, ISI_QOS_REG),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_access_table imx93_media_blk_ctl_access_table = {
|
||||||
|
.yes_ranges = imx93_media_blk_ctl_yes_ranges,
|
||||||
|
.n_yes_ranges = ARRAY_SIZE(imx93_media_blk_ctl_yes_ranges),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct imx93_blk_ctrl_data imx93_media_blk_ctl_dev_data = {
|
||||||
|
.domains = imx93_media_blk_ctl_domain_data,
|
||||||
|
.num_domains = ARRAY_SIZE(imx93_media_blk_ctl_domain_data),
|
||||||
|
.clk_names = (const char *[]){ "axi", "apb", "nic", },
|
||||||
|
.num_clks = 3,
|
||||||
|
.reg_access_table = &imx93_media_blk_ctl_access_table,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct of_device_id imx93_blk_ctrl_of_match[] = {
|
||||||
|
{
|
||||||
|
.compatible = "fsl,imx93-media-blk-ctrl",
|
||||||
|
.data = &imx93_media_blk_ctl_dev_data
|
||||||
|
}, {
|
||||||
|
/* Sentinel */
|
||||||
|
}
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, imx93_blk_ctrl_of_match);
|
||||||
|
|
||||||
|
static struct platform_driver imx93_blk_ctrl_driver = {
|
||||||
|
.probe = imx93_blk_ctrl_probe,
|
||||||
|
.remove = imx93_blk_ctrl_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = "imx93-blk-ctrl",
|
||||||
|
.of_match_table = imx93_blk_ctrl_of_match,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
module_platform_driver(imx93_blk_ctrl_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
|
||||||
|
MODULE_DESCRIPTION("i.MX93 BLK CTRL driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
164
drivers/soc/imx/imx93-pd.c
Normal file
164
drivers/soc/imx/imx93-pd.c
Normal file
|
@ -0,0 +1,164 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/*
|
||||||
|
* Copyright 2022 NXP
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/iopoll.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/pm_domain.h>
|
||||||
|
|
||||||
|
#define MIX_SLICE_SW_CTRL_OFF 0x20
|
||||||
|
#define SLICE_SW_CTRL_PSW_CTRL_OFF_MASK BIT(4)
|
||||||
|
#define SLICE_SW_CTRL_PDN_SOFT_MASK BIT(31)
|
||||||
|
|
||||||
|
#define MIX_FUNC_STAT_OFF 0xB4
|
||||||
|
|
||||||
|
#define FUNC_STAT_PSW_STAT_MASK BIT(0)
|
||||||
|
#define FUNC_STAT_RST_STAT_MASK BIT(2)
|
||||||
|
#define FUNC_STAT_ISO_STAT_MASK BIT(4)
|
||||||
|
|
||||||
|
struct imx93_power_domain {
|
||||||
|
struct generic_pm_domain genpd;
|
||||||
|
struct device *dev;
|
||||||
|
void __iomem *addr;
|
||||||
|
struct clk_bulk_data *clks;
|
||||||
|
int num_clks;
|
||||||
|
bool init_off;
|
||||||
|
};
|
||||||
|
|
||||||
|
#define to_imx93_pd(_genpd) container_of(_genpd, struct imx93_power_domain, genpd)
|
||||||
|
|
||||||
|
static int imx93_pd_on(struct generic_pm_domain *genpd)
|
||||||
|
{
|
||||||
|
struct imx93_power_domain *domain = to_imx93_pd(genpd);
|
||||||
|
void __iomem *addr = domain->addr;
|
||||||
|
u32 val;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(domain->dev, "failed to enable clocks for domain: %s\n", genpd->name);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
val = readl(addr + MIX_SLICE_SW_CTRL_OFF);
|
||||||
|
val &= ~SLICE_SW_CTRL_PDN_SOFT_MASK;
|
||||||
|
writel(val, addr + MIX_SLICE_SW_CTRL_OFF);
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(addr + MIX_FUNC_STAT_OFF, val,
|
||||||
|
!(val & FUNC_STAT_ISO_STAT_MASK), 1, 10000);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(domain->dev, "pd_on timeout: name: %s, stat: %x\n", genpd->name, val);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx93_pd_off(struct generic_pm_domain *genpd)
|
||||||
|
{
|
||||||
|
struct imx93_power_domain *domain = to_imx93_pd(genpd);
|
||||||
|
void __iomem *addr = domain->addr;
|
||||||
|
int ret;
|
||||||
|
u32 val;
|
||||||
|
|
||||||
|
/* Power off MIX */
|
||||||
|
val = readl(addr + MIX_SLICE_SW_CTRL_OFF);
|
||||||
|
val |= SLICE_SW_CTRL_PDN_SOFT_MASK;
|
||||||
|
writel(val, addr + MIX_SLICE_SW_CTRL_OFF);
|
||||||
|
|
||||||
|
ret = readl_poll_timeout(addr + MIX_FUNC_STAT_OFF, val,
|
||||||
|
val & FUNC_STAT_PSW_STAT_MASK, 1, 1000);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(domain->dev, "pd_off timeout: name: %s, stat: %x\n", genpd->name, val);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int imx93_pd_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct imx93_power_domain *domain = platform_get_drvdata(pdev);
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct device_node *np = dev->of_node;
|
||||||
|
|
||||||
|
if (!domain->init_off)
|
||||||
|
clk_bulk_disable_unprepare(domain->num_clks, domain->clks);
|
||||||
|
|
||||||
|
of_genpd_del_provider(np);
|
||||||
|
pm_genpd_remove(&domain->genpd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int imx93_pd_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct device_node *np = dev->of_node;
|
||||||
|
struct imx93_power_domain *domain;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
domain = devm_kzalloc(dev, sizeof(*domain), GFP_KERNEL);
|
||||||
|
if (!domain)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
domain->addr = devm_platform_ioremap_resource(pdev, 0);
|
||||||
|
if (IS_ERR(domain->addr))
|
||||||
|
return PTR_ERR(domain->addr);
|
||||||
|
|
||||||
|
domain->num_clks = devm_clk_bulk_get_all(dev, &domain->clks);
|
||||||
|
if (domain->num_clks < 0)
|
||||||
|
return dev_err_probe(dev, domain->num_clks, "Failed to get domain's clocks\n");
|
||||||
|
|
||||||
|
domain->genpd.name = dev_name(dev);
|
||||||
|
domain->genpd.power_off = imx93_pd_off;
|
||||||
|
domain->genpd.power_on = imx93_pd_on;
|
||||||
|
domain->dev = dev;
|
||||||
|
|
||||||
|
domain->init_off = readl(domain->addr + MIX_FUNC_STAT_OFF) & FUNC_STAT_ISO_STAT_MASK;
|
||||||
|
/* Just to sync the status of hardware */
|
||||||
|
if (!domain->init_off) {
|
||||||
|
ret = clk_bulk_prepare_enable(domain->num_clks, domain->clks);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(domain->dev, "failed to enable clocks for domain: %s\n",
|
||||||
|
domain->genpd.name);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = pm_genpd_init(&domain->genpd, NULL, domain->init_off);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, domain);
|
||||||
|
|
||||||
|
return of_genpd_add_provider_simple(np, &domain->genpd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id imx93_pd_ids[] = {
|
||||||
|
{ .compatible = "fsl,imx93-src-slice" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, imx93_pd_ids);
|
||||||
|
|
||||||
|
static struct platform_driver imx93_power_domain_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "imx93_power_domain",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.of_match_table = imx93_pd_ids,
|
||||||
|
},
|
||||||
|
.probe = imx93_pd_probe,
|
||||||
|
.remove = imx93_pd_remove,
|
||||||
|
};
|
||||||
|
module_platform_driver(imx93_power_domain_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
|
||||||
|
MODULE_DESCRIPTION("NXP i.MX93 power domain driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
33
drivers/soc/imx/imx93-src.c
Normal file
33
drivers/soc/imx/imx93-src.c
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/*
|
||||||
|
* Copyright 2022 NXP
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of_platform.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
|
||||||
|
static int imx93_src_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
return devm_of_platform_populate(&pdev->dev);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id imx93_src_ids[] = {
|
||||||
|
{ .compatible = "fsl,imx93-src" },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, imx93_src_ids);
|
||||||
|
|
||||||
|
static struct platform_driver imx93_src_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "imx93_src",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.of_match_table = imx93_src_ids,
|
||||||
|
},
|
||||||
|
.probe = imx93_src_probe,
|
||||||
|
};
|
||||||
|
module_platform_driver(imx93_src_driver);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Peng Fan <peng.fan@nxp.com>");
|
||||||
|
MODULE_DESCRIPTION("NXP i.MX93 src driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
|
@ -37,6 +37,7 @@ config MTK_INFRACFG
|
||||||
config MTK_PMIC_WRAP
|
config MTK_PMIC_WRAP
|
||||||
tristate "MediaTek PMIC Wrapper Support"
|
tristate "MediaTek PMIC Wrapper Support"
|
||||||
depends on RESET_CONTROLLER
|
depends on RESET_CONTROLLER
|
||||||
|
depends on OF
|
||||||
select REGMAP
|
select REGMAP
|
||||||
help
|
help
|
||||||
Say yes here to add support for MediaTek PMIC Wrapper found
|
Say yes here to add support for MediaTek PMIC Wrapper found
|
||||||
|
@ -46,6 +47,7 @@ config MTK_PMIC_WRAP
|
||||||
config MTK_SCPSYS
|
config MTK_SCPSYS
|
||||||
bool "MediaTek SCPSYS Support"
|
bool "MediaTek SCPSYS Support"
|
||||||
default ARCH_MEDIATEK
|
default ARCH_MEDIATEK
|
||||||
|
depends on OF
|
||||||
select REGMAP
|
select REGMAP
|
||||||
select MTK_INFRACFG
|
select MTK_INFRACFG
|
||||||
select PM_GENERIC_DOMAINS if PM
|
select PM_GENERIC_DOMAINS if PM
|
||||||
|
|
|
@ -3,6 +3,12 @@
|
||||||
#ifndef __SOC_MEDIATEK_MT8186_MMSYS_H
|
#ifndef __SOC_MEDIATEK_MT8186_MMSYS_H
|
||||||
#define __SOC_MEDIATEK_MT8186_MMSYS_H
|
#define __SOC_MEDIATEK_MT8186_MMSYS_H
|
||||||
|
|
||||||
|
/* Values for DPI configuration in MMSYS address space */
|
||||||
|
#define MT8186_MMSYS_DPI_OUTPUT_FORMAT 0x400
|
||||||
|
#define DPI_FORMAT_MASK 0x1
|
||||||
|
#define DPI_RGB888_DDR_CON BIT(0)
|
||||||
|
#define DPI_RGB565_SDR_CON BIT(1)
|
||||||
|
|
||||||
#define MT8186_MMSYS_OVL_CON 0xF04
|
#define MT8186_MMSYS_OVL_CON 0xF04
|
||||||
#define MT8186_MMSYS_OVL0_CON_MASK 0x3
|
#define MT8186_MMSYS_OVL0_CON_MASK 0x3
|
||||||
#define MT8186_MMSYS_OVL0_2L_CON_MASK 0xC
|
#define MT8186_MMSYS_OVL0_2L_CON_MASK 0xC
|
||||||
|
|
|
@ -227,6 +227,26 @@ void mtk_mmsys_ddp_disconnect(struct device *dev,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_disconnect);
|
EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_disconnect);
|
||||||
|
|
||||||
|
static void mtk_mmsys_update_bits(struct mtk_mmsys *mmsys, u32 offset, u32 mask, u32 val)
|
||||||
|
{
|
||||||
|
u32 tmp;
|
||||||
|
|
||||||
|
tmp = readl_relaxed(mmsys->regs + offset);
|
||||||
|
tmp = (tmp & ~mask) | val;
|
||||||
|
writel_relaxed(tmp, mmsys->regs + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
void mtk_mmsys_ddp_dpi_fmt_config(struct device *dev, u32 val)
|
||||||
|
{
|
||||||
|
if (val)
|
||||||
|
mtk_mmsys_update_bits(dev_get_drvdata(dev), MT8186_MMSYS_DPI_OUTPUT_FORMAT,
|
||||||
|
DPI_RGB888_DDR_CON, DPI_FORMAT_MASK);
|
||||||
|
else
|
||||||
|
mtk_mmsys_update_bits(dev_get_drvdata(dev), MT8186_MMSYS_DPI_OUTPUT_FORMAT,
|
||||||
|
DPI_RGB565_SDR_CON, DPI_FORMAT_MASK);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(mtk_mmsys_ddp_dpi_fmt_config);
|
||||||
|
|
||||||
static int mtk_mmsys_reset_update(struct reset_controller_dev *rcdev, unsigned long id,
|
static int mtk_mmsys_reset_update(struct reset_controller_dev *rcdev, unsigned long id,
|
||||||
bool assert)
|
bool assert)
|
||||||
{
|
{
|
||||||
|
|
|
@ -91,6 +91,15 @@
|
||||||
#define MT8183_MUTEX_MOD_MDP_AAL0 23
|
#define MT8183_MUTEX_MOD_MDP_AAL0 23
|
||||||
#define MT8183_MUTEX_MOD_MDP_CCORR0 24
|
#define MT8183_MUTEX_MOD_MDP_CCORR0 24
|
||||||
|
|
||||||
|
#define MT8186_MUTEX_MOD_MDP_RDMA0 0
|
||||||
|
#define MT8186_MUTEX_MOD_MDP_AAL0 2
|
||||||
|
#define MT8186_MUTEX_MOD_MDP_HDR0 4
|
||||||
|
#define MT8186_MUTEX_MOD_MDP_RSZ0 5
|
||||||
|
#define MT8186_MUTEX_MOD_MDP_RSZ1 6
|
||||||
|
#define MT8186_MUTEX_MOD_MDP_WROT0 7
|
||||||
|
#define MT8186_MUTEX_MOD_MDP_TDSHP0 9
|
||||||
|
#define MT8186_MUTEX_MOD_MDP_COLOR0 14
|
||||||
|
|
||||||
#define MT8173_MUTEX_MOD_DISP_OVL0 11
|
#define MT8173_MUTEX_MOD_DISP_OVL0 11
|
||||||
#define MT8173_MUTEX_MOD_DISP_OVL1 12
|
#define MT8173_MUTEX_MOD_DISP_OVL1 12
|
||||||
#define MT8173_MUTEX_MOD_DISP_RDMA0 13
|
#define MT8173_MUTEX_MOD_DISP_RDMA0 13
|
||||||
|
@ -324,6 +333,17 @@ static const unsigned int mt8186_mutex_mod[DDP_COMPONENT_ID_MAX] = {
|
||||||
[DDP_COMPONENT_RDMA1] = MT8186_MUTEX_MOD_DISP_RDMA1,
|
[DDP_COMPONENT_RDMA1] = MT8186_MUTEX_MOD_DISP_RDMA1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const unsigned int mt8186_mdp_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
|
||||||
|
[MUTEX_MOD_IDX_MDP_RDMA0] = MT8186_MUTEX_MOD_MDP_RDMA0,
|
||||||
|
[MUTEX_MOD_IDX_MDP_RSZ0] = MT8186_MUTEX_MOD_MDP_RSZ0,
|
||||||
|
[MUTEX_MOD_IDX_MDP_RSZ1] = MT8186_MUTEX_MOD_MDP_RSZ1,
|
||||||
|
[MUTEX_MOD_IDX_MDP_TDSHP0] = MT8186_MUTEX_MOD_MDP_TDSHP0,
|
||||||
|
[MUTEX_MOD_IDX_MDP_WROT0] = MT8186_MUTEX_MOD_MDP_WROT0,
|
||||||
|
[MUTEX_MOD_IDX_MDP_HDR0] = MT8186_MUTEX_MOD_MDP_HDR0,
|
||||||
|
[MUTEX_MOD_IDX_MDP_AAL0] = MT8186_MUTEX_MOD_MDP_AAL0,
|
||||||
|
[MUTEX_MOD_IDX_MDP_COLOR0] = MT8186_MUTEX_MOD_MDP_COLOR0,
|
||||||
|
};
|
||||||
|
|
||||||
static const unsigned int mt8192_mutex_mod[DDP_COMPONENT_ID_MAX] = {
|
static const unsigned int mt8192_mutex_mod[DDP_COMPONENT_ID_MAX] = {
|
||||||
[DDP_COMPONENT_AAL0] = MT8192_MUTEX_MOD_DISP_AAL0,
|
[DDP_COMPONENT_AAL0] = MT8192_MUTEX_MOD_DISP_AAL0,
|
||||||
[DDP_COMPONENT_CCORR] = MT8192_MUTEX_MOD_DISP_CCORR0,
|
[DDP_COMPONENT_CCORR] = MT8192_MUTEX_MOD_DISP_CCORR0,
|
||||||
|
@ -380,6 +400,13 @@ static const unsigned int mt2712_mutex_sof[DDP_MUTEX_SOF_MAX] = {
|
||||||
[MUTEX_SOF_DSI3] = MUTEX_SOF_DSI3,
|
[MUTEX_SOF_DSI3] = MUTEX_SOF_DSI3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const unsigned int mt6795_mutex_sof[DDP_MUTEX_SOF_MAX] = {
|
||||||
|
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
|
||||||
|
[MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
|
||||||
|
[MUTEX_SOF_DSI1] = MUTEX_SOF_DSI1,
|
||||||
|
[MUTEX_SOF_DPI0] = MUTEX_SOF_DPI0,
|
||||||
|
};
|
||||||
|
|
||||||
static const unsigned int mt8167_mutex_sof[DDP_MUTEX_SOF_MAX] = {
|
static const unsigned int mt8167_mutex_sof[DDP_MUTEX_SOF_MAX] = {
|
||||||
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
|
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
|
||||||
[MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
|
[MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
|
||||||
|
@ -434,6 +461,13 @@ static const struct mtk_mutex_data mt2712_mutex_driver_data = {
|
||||||
.mutex_sof_reg = MT2701_MUTEX0_SOF0,
|
.mutex_sof_reg = MT2701_MUTEX0_SOF0,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct mtk_mutex_data mt6795_mutex_driver_data = {
|
||||||
|
.mutex_mod = mt8173_mutex_mod,
|
||||||
|
.mutex_sof = mt6795_mutex_sof,
|
||||||
|
.mutex_mod_reg = MT2701_MUTEX0_MOD0,
|
||||||
|
.mutex_sof_reg = MT2701_MUTEX0_SOF0,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct mtk_mutex_data mt8167_mutex_driver_data = {
|
static const struct mtk_mutex_data mt8167_mutex_driver_data = {
|
||||||
.mutex_mod = mt8167_mutex_mod,
|
.mutex_mod = mt8167_mutex_mod,
|
||||||
.mutex_sof = mt8167_mutex_sof,
|
.mutex_sof = mt8167_mutex_sof,
|
||||||
|
@ -458,6 +492,12 @@ static const struct mtk_mutex_data mt8183_mutex_driver_data = {
|
||||||
.no_clk = true,
|
.no_clk = true,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct mtk_mutex_data mt8186_mdp_mutex_driver_data = {
|
||||||
|
.mutex_mod_reg = MT8183_MUTEX0_MOD0,
|
||||||
|
.mutex_sof_reg = MT8183_MUTEX0_SOF0,
|
||||||
|
.mutex_table_mod = mt8186_mdp_mutex_table_mod,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct mtk_mutex_data mt8186_mutex_driver_data = {
|
static const struct mtk_mutex_data mt8186_mutex_driver_data = {
|
||||||
.mutex_mod = mt8186_mutex_mod,
|
.mutex_mod = mt8186_mutex_mod,
|
||||||
.mutex_sof = mt8186_mutex_sof,
|
.mutex_sof = mt8186_mutex_sof,
|
||||||
|
@ -802,6 +842,8 @@ static const struct of_device_id mutex_driver_dt_match[] = {
|
||||||
.data = &mt2701_mutex_driver_data},
|
.data = &mt2701_mutex_driver_data},
|
||||||
{ .compatible = "mediatek,mt2712-disp-mutex",
|
{ .compatible = "mediatek,mt2712-disp-mutex",
|
||||||
.data = &mt2712_mutex_driver_data},
|
.data = &mt2712_mutex_driver_data},
|
||||||
|
{ .compatible = "mediatek,mt6795-disp-mutex",
|
||||||
|
.data = &mt6795_mutex_driver_data},
|
||||||
{ .compatible = "mediatek,mt8167-disp-mutex",
|
{ .compatible = "mediatek,mt8167-disp-mutex",
|
||||||
.data = &mt8167_mutex_driver_data},
|
.data = &mt8167_mutex_driver_data},
|
||||||
{ .compatible = "mediatek,mt8173-disp-mutex",
|
{ .compatible = "mediatek,mt8173-disp-mutex",
|
||||||
|
@ -810,6 +852,8 @@ static const struct of_device_id mutex_driver_dt_match[] = {
|
||||||
.data = &mt8183_mutex_driver_data},
|
.data = &mt8183_mutex_driver_data},
|
||||||
{ .compatible = "mediatek,mt8186-disp-mutex",
|
{ .compatible = "mediatek,mt8186-disp-mutex",
|
||||||
.data = &mt8186_mutex_driver_data},
|
.data = &mt8186_mutex_driver_data},
|
||||||
|
{ .compatible = "mediatek,mt8186-mdp3-mutex",
|
||||||
|
.data = &mt8186_mdp_mutex_driver_data},
|
||||||
{ .compatible = "mediatek,mt8192-disp-mutex",
|
{ .compatible = "mediatek,mt8192-disp-mutex",
|
||||||
.data = &mt8192_mutex_driver_data},
|
.data = &mt8192_mutex_driver_data},
|
||||||
{ .compatible = "mediatek,mt8195-disp-mutex",
|
{ .compatible = "mediatek,mt8195-disp-mutex",
|
||||||
|
|
|
@ -393,7 +393,7 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
|
||||||
if (IS_ERR(clk)) {
|
if (IS_ERR(clk)) {
|
||||||
ret = PTR_ERR(clk);
|
ret = PTR_ERR(clk);
|
||||||
dev_err_probe(scpsys->dev, ret,
|
dev_err_probe(scpsys->dev, ret,
|
||||||
"%pOF: failed to get clk at index %d: %d\n", node, i, ret);
|
"%pOF: failed to get clk at index %d\n", node, i);
|
||||||
goto err_put_clocks;
|
goto err_put_clocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -405,8 +405,8 @@ generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_no
|
||||||
if (IS_ERR(clk)) {
|
if (IS_ERR(clk)) {
|
||||||
ret = PTR_ERR(clk);
|
ret = PTR_ERR(clk);
|
||||||
dev_err_probe(scpsys->dev, ret,
|
dev_err_probe(scpsys->dev, ret,
|
||||||
"%pOF: failed to get clk at index %d: %d\n", node,
|
"%pOF: failed to get clk at index %d\n", node,
|
||||||
i + clk_ind, ret);
|
i + clk_ind);
|
||||||
goto err_put_subsys_clocks;
|
goto err_put_subsys_clocks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2316,7 +2316,7 @@ err_out1:
|
||||||
static struct platform_driver pwrap_drv = {
|
static struct platform_driver pwrap_drv = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "mt-pmic-pwrap",
|
.name = "mt-pmic-pwrap",
|
||||||
.of_match_table = of_match_ptr(of_pwrap_match_tbl),
|
.of_match_table = of_pwrap_match_tbl,
|
||||||
},
|
},
|
||||||
.probe = pwrap_probe,
|
.probe = pwrap_probe,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1141,7 +1141,7 @@ static struct platform_driver scpsys_drv = {
|
||||||
.name = "mtk-scpsys",
|
.name = "mtk-scpsys",
|
||||||
.suppress_bind_attrs = true,
|
.suppress_bind_attrs = true,
|
||||||
.owner = THIS_MODULE,
|
.owner = THIS_MODULE,
|
||||||
.of_match_table = of_match_ptr(of_scpsys_match_tbl),
|
.of_match_table = of_scpsys_match_tbl,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
builtin_platform_driver(scpsys_drv);
|
builtin_platform_driver(scpsys_drv);
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* Copyright (C) 2022 MediaTek Inc.
|
* Copyright (C) 2022 MediaTek Inc.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/bitfield.h>
|
||||||
#include <linux/bits.h>
|
#include <linux/bits.h>
|
||||||
#include <linux/clk.h>
|
#include <linux/clk.h>
|
||||||
#include <linux/completion.h>
|
#include <linux/completion.h>
|
||||||
|
@ -53,22 +54,79 @@
|
||||||
#define SVSB_MON_VOLT_IGNORE BIT(16)
|
#define SVSB_MON_VOLT_IGNORE BIT(16)
|
||||||
#define SVSB_REMOVE_DVTFIXED_VOLT BIT(24)
|
#define SVSB_REMOVE_DVTFIXED_VOLT BIT(24)
|
||||||
|
|
||||||
/* svs bank register common configuration */
|
/* svs bank register fields and common configuration */
|
||||||
#define SVSB_DET_MAX 0xffff
|
#define SVSB_PTPCONFIG_DETMAX GENMASK(15, 0)
|
||||||
|
#define SVSB_DET_MAX FIELD_PREP(SVSB_PTPCONFIG_DETMAX, 0xffff)
|
||||||
#define SVSB_DET_WINDOW 0xa28
|
#define SVSB_DET_WINDOW 0xa28
|
||||||
#define SVSB_DTHI 0x1
|
|
||||||
#define SVSB_DTLO 0xfe
|
/* DESCHAR */
|
||||||
#define SVSB_EN_INIT01 0x1
|
#define SVSB_DESCHAR_FLD_MDES GENMASK(7, 0)
|
||||||
#define SVSB_EN_INIT02 0x5
|
#define SVSB_DESCHAR_FLD_BDES GENMASK(15, 8)
|
||||||
#define SVSB_EN_MON 0x2
|
|
||||||
#define SVSB_EN_OFF 0x0
|
/* TEMPCHAR */
|
||||||
#define SVSB_INTEN_INIT0x 0x00005f01
|
#define SVSB_TEMPCHAR_FLD_DVT_FIXED GENMASK(7, 0)
|
||||||
#define SVSB_INTEN_MONVOPEN 0x00ff0000
|
#define SVSB_TEMPCHAR_FLD_MTDES GENMASK(15, 8)
|
||||||
#define SVSB_INTSTS_CLEAN 0x00ffffff
|
#define SVSB_TEMPCHAR_FLD_VCO GENMASK(23, 16)
|
||||||
#define SVSB_INTSTS_COMPLETE 0x1
|
|
||||||
#define SVSB_INTSTS_MONVOP 0x00ff0000
|
/* DETCHAR */
|
||||||
|
#define SVSB_DETCHAR_FLD_DCMDET GENMASK(7, 0)
|
||||||
|
#define SVSB_DETCHAR_FLD_DCBDET GENMASK(15, 8)
|
||||||
|
|
||||||
|
/* SVSEN (PTPEN) */
|
||||||
|
#define SVSB_PTPEN_INIT01 BIT(0)
|
||||||
|
#define SVSB_PTPEN_MON BIT(1)
|
||||||
|
#define SVSB_PTPEN_INIT02 (SVSB_PTPEN_INIT01 | BIT(2))
|
||||||
|
#define SVSB_PTPEN_OFF 0x0
|
||||||
|
|
||||||
|
/* FREQPCTS */
|
||||||
|
#define SVSB_FREQPCTS_FLD_PCT0_4 GENMASK(7, 0)
|
||||||
|
#define SVSB_FREQPCTS_FLD_PCT1_5 GENMASK(15, 8)
|
||||||
|
#define SVSB_FREQPCTS_FLD_PCT2_6 GENMASK(23, 16)
|
||||||
|
#define SVSB_FREQPCTS_FLD_PCT3_7 GENMASK(31, 24)
|
||||||
|
|
||||||
|
/* INTSTS */
|
||||||
|
#define SVSB_INTSTS_VAL_CLEAN 0x00ffffff
|
||||||
|
#define SVSB_INTSTS_F0_COMPLETE BIT(0)
|
||||||
|
#define SVSB_INTSTS_FLD_MONVOP GENMASK(23, 16)
|
||||||
#define SVSB_RUNCONFIG_DEFAULT 0x80000000
|
#define SVSB_RUNCONFIG_DEFAULT 0x80000000
|
||||||
|
|
||||||
|
/* LIMITVALS */
|
||||||
|
#define SVSB_LIMITVALS_FLD_DTLO GENMASK(7, 0)
|
||||||
|
#define SVSB_LIMITVALS_FLD_DTHI GENMASK(15, 8)
|
||||||
|
#define SVSB_LIMITVALS_FLD_VMIN GENMASK(23, 16)
|
||||||
|
#define SVSB_LIMITVALS_FLD_VMAX GENMASK(31, 24)
|
||||||
|
#define SVSB_VAL_DTHI 0x1
|
||||||
|
#define SVSB_VAL_DTLO 0xfe
|
||||||
|
|
||||||
|
/* INTEN */
|
||||||
|
#define SVSB_INTEN_F0EN BIT(0)
|
||||||
|
#define SVSB_INTEN_DACK0UPEN BIT(8)
|
||||||
|
#define SVSB_INTEN_DC0EN BIT(9)
|
||||||
|
#define SVSB_INTEN_DC1EN BIT(10)
|
||||||
|
#define SVSB_INTEN_DACK0LOEN BIT(11)
|
||||||
|
#define SVSB_INTEN_INITPROD_OVF_EN BIT(12)
|
||||||
|
#define SVSB_INTEN_INITSUM_OVF_EN BIT(14)
|
||||||
|
#define SVSB_INTEN_MONVOPEN GENMASK(23, 16)
|
||||||
|
#define SVSB_INTEN_INIT0x (SVSB_INTEN_F0EN | SVSB_INTEN_DACK0UPEN | \
|
||||||
|
SVSB_INTEN_DC0EN | SVSB_INTEN_DC1EN | \
|
||||||
|
SVSB_INTEN_DACK0LOEN | \
|
||||||
|
SVSB_INTEN_INITPROD_OVF_EN | \
|
||||||
|
SVSB_INTEN_INITSUM_OVF_EN)
|
||||||
|
|
||||||
|
/* TSCALCS */
|
||||||
|
#define SVSB_TSCALCS_FLD_MTS GENMASK(11, 0)
|
||||||
|
#define SVSB_TSCALCS_FLD_BTS GENMASK(23, 12)
|
||||||
|
|
||||||
|
/* INIT2VALS */
|
||||||
|
#define SVSB_INIT2VALS_FLD_DCVOFFSETIN GENMASK(15, 0)
|
||||||
|
#define SVSB_INIT2VALS_FLD_AGEVOFFSETIN GENMASK(31, 16)
|
||||||
|
|
||||||
|
/* VOPS */
|
||||||
|
#define SVSB_VOPS_FLD_VOP0_4 GENMASK(7, 0)
|
||||||
|
#define SVSB_VOPS_FLD_VOP1_5 GENMASK(15, 8)
|
||||||
|
#define SVSB_VOPS_FLD_VOP2_6 GENMASK(23, 16)
|
||||||
|
#define SVSB_VOPS_FLD_VOP3_7 GENMASK(31, 24)
|
||||||
|
|
||||||
/* svs bank related setting */
|
/* svs bank related setting */
|
||||||
#define BITS8 8
|
#define BITS8 8
|
||||||
#define MAX_OPP_ENTRIES 16
|
#define MAX_OPP_ENTRIES 16
|
||||||
|
@ -262,7 +320,6 @@ static const u32 svs_regs_v2[] = {
|
||||||
* @rst: svs platform reset control
|
* @rst: svs platform reset control
|
||||||
* @efuse_parsing: svs platform efuse parsing function pointer
|
* @efuse_parsing: svs platform efuse parsing function pointer
|
||||||
* @probe: svs platform probe function pointer
|
* @probe: svs platform probe function pointer
|
||||||
* @irqflags: svs platform irq settings flags
|
|
||||||
* @efuse_max: total number of svs efuse
|
* @efuse_max: total number of svs efuse
|
||||||
* @tefuse_max: total number of thermal efuse
|
* @tefuse_max: total number of thermal efuse
|
||||||
* @regs: svs platform registers map
|
* @regs: svs platform registers map
|
||||||
|
@ -280,7 +337,6 @@ struct svs_platform {
|
||||||
struct reset_control *rst;
|
struct reset_control *rst;
|
||||||
bool (*efuse_parsing)(struct svs_platform *svsp);
|
bool (*efuse_parsing)(struct svs_platform *svsp);
|
||||||
int (*probe)(struct svs_platform *svsp);
|
int (*probe)(struct svs_platform *svsp);
|
||||||
unsigned long irqflags;
|
|
||||||
size_t efuse_max;
|
size_t efuse_max;
|
||||||
size_t tefuse_max;
|
size_t tefuse_max;
|
||||||
const u32 *regs;
|
const u32 *regs;
|
||||||
|
@ -294,7 +350,6 @@ struct svs_platform_data {
|
||||||
struct svs_bank *banks;
|
struct svs_bank *banks;
|
||||||
bool (*efuse_parsing)(struct svs_platform *svsp);
|
bool (*efuse_parsing)(struct svs_platform *svsp);
|
||||||
int (*probe)(struct svs_platform *svsp);
|
int (*probe)(struct svs_platform *svsp);
|
||||||
unsigned long irqflags;
|
|
||||||
const u32 *regs;
|
const u32 *regs;
|
||||||
u32 bank_max;
|
u32 bank_max;
|
||||||
};
|
};
|
||||||
|
@ -668,8 +723,8 @@ static ssize_t svs_enable_debug_write(struct file *filp,
|
||||||
svsp->pbank = svsb;
|
svsp->pbank = svsb;
|
||||||
svsb->mode_support = SVSB_MODE_ALL_DISABLE;
|
svsb->mode_support = SVSB_MODE_ALL_DISABLE;
|
||||||
svs_switch_bank(svsp);
|
svs_switch_bank(svsp);
|
||||||
svs_writel_relaxed(svsp, SVSB_EN_OFF, SVSEN);
|
svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
|
||||||
svs_writel_relaxed(svsp, SVSB_INTSTS_CLEAN, INTSTS);
|
svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
|
||||||
spin_unlock_irqrestore(&svs_lock, flags);
|
spin_unlock_irqrestore(&svs_lock, flags);
|
||||||
|
|
||||||
svsb->phase = SVSB_PHASE_ERROR;
|
svsb->phase = SVSB_PHASE_ERROR;
|
||||||
|
@ -830,7 +885,7 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp)
|
||||||
} else if (svsb->type == SVSB_LOW) {
|
} else if (svsb->type == SVSB_LOW) {
|
||||||
/* volt[turn_pt] + volt[j] ~ volt[opp_count - 1] */
|
/* volt[turn_pt] + volt[j] ~ volt[opp_count - 1] */
|
||||||
j = svsb->opp_count - 7;
|
j = svsb->opp_count - 7;
|
||||||
svsb->volt[turn_pt] = vop30 & GENMASK(7, 0);
|
svsb->volt[turn_pt] = FIELD_GET(SVSB_VOPS_FLD_VOP0_4, vop30);
|
||||||
shift_byte++;
|
shift_byte++;
|
||||||
for (i = j; i < svsb->opp_count; i++) {
|
for (i = j; i < svsb->opp_count; i++) {
|
||||||
b_sft = BITS8 * (shift_byte % REG_BYTES);
|
b_sft = BITS8 * (shift_byte % REG_BYTES);
|
||||||
|
@ -852,7 +907,7 @@ static void svs_get_bank_volts_v3(struct svs_platform *svsp)
|
||||||
if (svsb->type == SVSB_HIGH) {
|
if (svsb->type == SVSB_HIGH) {
|
||||||
/* volt[0] + volt[j] ~ volt[turn_pt - 1] */
|
/* volt[0] + volt[j] ~ volt[turn_pt - 1] */
|
||||||
j = turn_pt - 7;
|
j = turn_pt - 7;
|
||||||
svsb->volt[0] = vop30 & GENMASK(7, 0);
|
svsb->volt[0] = FIELD_GET(SVSB_VOPS_FLD_VOP0_4, vop30);
|
||||||
shift_byte++;
|
shift_byte++;
|
||||||
for (i = j; i < turn_pt; i++) {
|
for (i = j; i < turn_pt; i++) {
|
||||||
b_sft = BITS8 * (shift_byte % REG_BYTES);
|
b_sft = BITS8 * (shift_byte % REG_BYTES);
|
||||||
|
@ -983,16 +1038,16 @@ static void svs_get_bank_volts_v2(struct svs_platform *svsp)
|
||||||
u32 temp, i;
|
u32 temp, i;
|
||||||
|
|
||||||
temp = svs_readl_relaxed(svsp, VOP74);
|
temp = svs_readl_relaxed(svsp, VOP74);
|
||||||
svsb->volt[14] = (temp >> 24) & GENMASK(7, 0);
|
svsb->volt[14] = FIELD_GET(SVSB_VOPS_FLD_VOP3_7, temp);
|
||||||
svsb->volt[12] = (temp >> 16) & GENMASK(7, 0);
|
svsb->volt[12] = FIELD_GET(SVSB_VOPS_FLD_VOP2_6, temp);
|
||||||
svsb->volt[10] = (temp >> 8) & GENMASK(7, 0);
|
svsb->volt[10] = FIELD_GET(SVSB_VOPS_FLD_VOP1_5, temp);
|
||||||
svsb->volt[8] = (temp & GENMASK(7, 0));
|
svsb->volt[8] = FIELD_GET(SVSB_VOPS_FLD_VOP0_4, temp);
|
||||||
|
|
||||||
temp = svs_readl_relaxed(svsp, VOP30);
|
temp = svs_readl_relaxed(svsp, VOP30);
|
||||||
svsb->volt[6] = (temp >> 24) & GENMASK(7, 0);
|
svsb->volt[6] = FIELD_GET(SVSB_VOPS_FLD_VOP3_7, temp);
|
||||||
svsb->volt[4] = (temp >> 16) & GENMASK(7, 0);
|
svsb->volt[4] = FIELD_GET(SVSB_VOPS_FLD_VOP2_6, temp);
|
||||||
svsb->volt[2] = (temp >> 8) & GENMASK(7, 0);
|
svsb->volt[2] = FIELD_GET(SVSB_VOPS_FLD_VOP1_5, temp);
|
||||||
svsb->volt[0] = (temp & GENMASK(7, 0));
|
svsb->volt[0] = FIELD_GET(SVSB_VOPS_FLD_VOP0_4, temp);
|
||||||
|
|
||||||
for (i = 0; i <= 12; i += 2)
|
for (i = 0; i <= 12; i += 2)
|
||||||
svsb->volt[i + 1] = interpolate(svsb->freq_pct[i],
|
svsb->volt[i + 1] = interpolate(svsb->freq_pct[i],
|
||||||
|
@ -1014,20 +1069,20 @@ static void svs_get_bank_volts_v2(struct svs_platform *svsp)
|
||||||
static void svs_set_bank_freq_pct_v2(struct svs_platform *svsp)
|
static void svs_set_bank_freq_pct_v2(struct svs_platform *svsp)
|
||||||
{
|
{
|
||||||
struct svs_bank *svsb = svsp->pbank;
|
struct svs_bank *svsb = svsp->pbank;
|
||||||
|
u32 freqpct74_val, freqpct30_val;
|
||||||
|
|
||||||
svs_writel_relaxed(svsp,
|
freqpct74_val = FIELD_PREP(SVSB_FREQPCTS_FLD_PCT0_4, svsb->freq_pct[8]) |
|
||||||
(svsb->freq_pct[14] << 24) |
|
FIELD_PREP(SVSB_FREQPCTS_FLD_PCT1_5, svsb->freq_pct[10]) |
|
||||||
(svsb->freq_pct[12] << 16) |
|
FIELD_PREP(SVSB_FREQPCTS_FLD_PCT2_6, svsb->freq_pct[12]) |
|
||||||
(svsb->freq_pct[10] << 8) |
|
FIELD_PREP(SVSB_FREQPCTS_FLD_PCT3_7, svsb->freq_pct[14]);
|
||||||
svsb->freq_pct[8],
|
|
||||||
FREQPCT74);
|
|
||||||
|
|
||||||
svs_writel_relaxed(svsp,
|
freqpct30_val = FIELD_PREP(SVSB_FREQPCTS_FLD_PCT0_4, svsb->freq_pct[0]) |
|
||||||
(svsb->freq_pct[6] << 24) |
|
FIELD_PREP(SVSB_FREQPCTS_FLD_PCT1_5, svsb->freq_pct[2]) |
|
||||||
(svsb->freq_pct[4] << 16) |
|
FIELD_PREP(SVSB_FREQPCTS_FLD_PCT2_6, svsb->freq_pct[4]) |
|
||||||
(svsb->freq_pct[2] << 8) |
|
FIELD_PREP(SVSB_FREQPCTS_FLD_PCT3_7, svsb->freq_pct[6]);
|
||||||
svsb->freq_pct[0],
|
|
||||||
FREQPCT30);
|
svs_writel_relaxed(svsp, freqpct74_val, FREQPCT74);
|
||||||
|
svs_writel_relaxed(svsp, freqpct30_val, FREQPCT30);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void svs_set_bank_phase(struct svs_platform *svsp,
|
static void svs_set_bank_phase(struct svs_platform *svsp,
|
||||||
|
@ -1038,13 +1093,17 @@ static void svs_set_bank_phase(struct svs_platform *svsp,
|
||||||
|
|
||||||
svs_switch_bank(svsp);
|
svs_switch_bank(svsp);
|
||||||
|
|
||||||
des_char = (svsb->bdes << 8) | svsb->mdes;
|
des_char = FIELD_PREP(SVSB_DESCHAR_FLD_BDES, svsb->bdes) |
|
||||||
|
FIELD_PREP(SVSB_DESCHAR_FLD_MDES, svsb->mdes);
|
||||||
svs_writel_relaxed(svsp, des_char, DESCHAR);
|
svs_writel_relaxed(svsp, des_char, DESCHAR);
|
||||||
|
|
||||||
temp_char = (svsb->vco << 16) | (svsb->mtdes << 8) | svsb->dvt_fixed;
|
temp_char = FIELD_PREP(SVSB_TEMPCHAR_FLD_VCO, svsb->vco) |
|
||||||
|
FIELD_PREP(SVSB_TEMPCHAR_FLD_MTDES, svsb->mtdes) |
|
||||||
|
FIELD_PREP(SVSB_TEMPCHAR_FLD_DVT_FIXED, svsb->dvt_fixed);
|
||||||
svs_writel_relaxed(svsp, temp_char, TEMPCHAR);
|
svs_writel_relaxed(svsp, temp_char, TEMPCHAR);
|
||||||
|
|
||||||
det_char = (svsb->dcbdet << 8) | svsb->dcmdet;
|
det_char = FIELD_PREP(SVSB_DETCHAR_FLD_DCBDET, svsb->dcbdet) |
|
||||||
|
FIELD_PREP(SVSB_DETCHAR_FLD_DCMDET, svsb->dcmdet);
|
||||||
svs_writel_relaxed(svsp, det_char, DETCHAR);
|
svs_writel_relaxed(svsp, det_char, DETCHAR);
|
||||||
|
|
||||||
svs_writel_relaxed(svsp, svsb->dc_config, DCCONFIG);
|
svs_writel_relaxed(svsp, svsb->dc_config, DCCONFIG);
|
||||||
|
@ -1053,33 +1112,37 @@ static void svs_set_bank_phase(struct svs_platform *svsp,
|
||||||
|
|
||||||
svsb->set_freq_pct(svsp);
|
svsb->set_freq_pct(svsp);
|
||||||
|
|
||||||
limit_vals = (svsb->vmax << 24) | (svsb->vmin << 16) |
|
limit_vals = FIELD_PREP(SVSB_LIMITVALS_FLD_DTLO, SVSB_VAL_DTLO) |
|
||||||
(SVSB_DTHI << 8) | SVSB_DTLO;
|
FIELD_PREP(SVSB_LIMITVALS_FLD_DTHI, SVSB_VAL_DTHI) |
|
||||||
|
FIELD_PREP(SVSB_LIMITVALS_FLD_VMIN, svsb->vmin) |
|
||||||
|
FIELD_PREP(SVSB_LIMITVALS_FLD_VMAX, svsb->vmax);
|
||||||
svs_writel_relaxed(svsp, limit_vals, LIMITVALS);
|
svs_writel_relaxed(svsp, limit_vals, LIMITVALS);
|
||||||
|
|
||||||
svs_writel_relaxed(svsp, SVSB_DET_WINDOW, DETWINDOW);
|
svs_writel_relaxed(svsp, SVSB_DET_WINDOW, DETWINDOW);
|
||||||
svs_writel_relaxed(svsp, SVSB_DET_MAX, CONFIG);
|
svs_writel_relaxed(svsp, SVSB_DET_MAX, CONFIG);
|
||||||
svs_writel_relaxed(svsp, svsb->chk_shift, CHKSHIFT);
|
svs_writel_relaxed(svsp, svsb->chk_shift, CHKSHIFT);
|
||||||
svs_writel_relaxed(svsp, svsb->ctl0, CTL0);
|
svs_writel_relaxed(svsp, svsb->ctl0, CTL0);
|
||||||
svs_writel_relaxed(svsp, SVSB_INTSTS_CLEAN, INTSTS);
|
svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
|
||||||
|
|
||||||
switch (target_phase) {
|
switch (target_phase) {
|
||||||
case SVSB_PHASE_INIT01:
|
case SVSB_PHASE_INIT01:
|
||||||
svs_writel_relaxed(svsp, svsb->vboot, VBOOT);
|
svs_writel_relaxed(svsp, svsb->vboot, VBOOT);
|
||||||
svs_writel_relaxed(svsp, SVSB_INTEN_INIT0x, INTEN);
|
svs_writel_relaxed(svsp, SVSB_INTEN_INIT0x, INTEN);
|
||||||
svs_writel_relaxed(svsp, SVSB_EN_INIT01, SVSEN);
|
svs_writel_relaxed(svsp, SVSB_PTPEN_INIT01, SVSEN);
|
||||||
break;
|
break;
|
||||||
case SVSB_PHASE_INIT02:
|
case SVSB_PHASE_INIT02:
|
||||||
|
init2vals = FIELD_PREP(SVSB_INIT2VALS_FLD_AGEVOFFSETIN, svsb->age_voffset_in) |
|
||||||
|
FIELD_PREP(SVSB_INIT2VALS_FLD_DCVOFFSETIN, svsb->dc_voffset_in);
|
||||||
svs_writel_relaxed(svsp, SVSB_INTEN_INIT0x, INTEN);
|
svs_writel_relaxed(svsp, SVSB_INTEN_INIT0x, INTEN);
|
||||||
init2vals = (svsb->age_voffset_in << 16) | svsb->dc_voffset_in;
|
|
||||||
svs_writel_relaxed(svsp, init2vals, INIT2VALS);
|
svs_writel_relaxed(svsp, init2vals, INIT2VALS);
|
||||||
svs_writel_relaxed(svsp, SVSB_EN_INIT02, SVSEN);
|
svs_writel_relaxed(svsp, SVSB_PTPEN_INIT02, SVSEN);
|
||||||
break;
|
break;
|
||||||
case SVSB_PHASE_MON:
|
case SVSB_PHASE_MON:
|
||||||
ts_calcs = (svsb->bts << 12) | svsb->mts;
|
ts_calcs = FIELD_PREP(SVSB_TSCALCS_FLD_BTS, svsb->bts) |
|
||||||
|
FIELD_PREP(SVSB_TSCALCS_FLD_MTS, svsb->mts);
|
||||||
svs_writel_relaxed(svsp, ts_calcs, TSCALCS);
|
svs_writel_relaxed(svsp, ts_calcs, TSCALCS);
|
||||||
svs_writel_relaxed(svsp, SVSB_INTEN_MONVOPEN, INTEN);
|
svs_writel_relaxed(svsp, SVSB_INTEN_MONVOPEN, INTEN);
|
||||||
svs_writel_relaxed(svsp, SVSB_EN_MON, SVSEN);
|
svs_writel_relaxed(svsp, SVSB_PTPEN_MON, SVSEN);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
dev_err(svsb->dev, "requested unknown target phase: %u\n",
|
dev_err(svsb->dev, "requested unknown target phase: %u\n",
|
||||||
|
@ -1115,8 +1178,8 @@ static inline void svs_error_isr_handler(struct svs_platform *svsp)
|
||||||
svs_save_bank_register_data(svsp, SVSB_PHASE_ERROR);
|
svs_save_bank_register_data(svsp, SVSB_PHASE_ERROR);
|
||||||
|
|
||||||
svsb->phase = SVSB_PHASE_ERROR;
|
svsb->phase = SVSB_PHASE_ERROR;
|
||||||
svs_writel_relaxed(svsp, SVSB_EN_OFF, SVSEN);
|
svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
|
||||||
svs_writel_relaxed(svsp, SVSB_INTSTS_CLEAN, INTSTS);
|
svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void svs_init01_isr_handler(struct svs_platform *svsp)
|
static inline void svs_init01_isr_handler(struct svs_platform *svsp)
|
||||||
|
@ -1141,8 +1204,8 @@ static inline void svs_init01_isr_handler(struct svs_platform *svsp)
|
||||||
svsb->age_voffset_in = svs_readl_relaxed(svsp, AGEVALUES) &
|
svsb->age_voffset_in = svs_readl_relaxed(svsp, AGEVALUES) &
|
||||||
GENMASK(15, 0);
|
GENMASK(15, 0);
|
||||||
|
|
||||||
svs_writel_relaxed(svsp, SVSB_EN_OFF, SVSEN);
|
svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
|
||||||
svs_writel_relaxed(svsp, SVSB_INTSTS_COMPLETE, INTSTS);
|
svs_writel_relaxed(svsp, SVSB_INTSTS_F0_COMPLETE, INTSTS);
|
||||||
svsb->core_sel &= ~SVSB_DET_CLK_EN;
|
svsb->core_sel &= ~SVSB_DET_CLK_EN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1160,8 +1223,8 @@ static inline void svs_init02_isr_handler(struct svs_platform *svsp)
|
||||||
svsb->phase = SVSB_PHASE_INIT02;
|
svsb->phase = SVSB_PHASE_INIT02;
|
||||||
svsb->get_volts(svsp);
|
svsb->get_volts(svsp);
|
||||||
|
|
||||||
svs_writel_relaxed(svsp, SVSB_EN_OFF, SVSEN);
|
svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
|
||||||
svs_writel_relaxed(svsp, SVSB_INTSTS_COMPLETE, INTSTS);
|
svs_writel_relaxed(svsp, SVSB_INTSTS_F0_COMPLETE, INTSTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void svs_mon_mode_isr_handler(struct svs_platform *svsp)
|
static inline void svs_mon_mode_isr_handler(struct svs_platform *svsp)
|
||||||
|
@ -1174,7 +1237,7 @@ static inline void svs_mon_mode_isr_handler(struct svs_platform *svsp)
|
||||||
svsb->get_volts(svsp);
|
svsb->get_volts(svsp);
|
||||||
|
|
||||||
svsb->temp = svs_readl_relaxed(svsp, TEMP) & GENMASK(7, 0);
|
svsb->temp = svs_readl_relaxed(svsp, TEMP) & GENMASK(7, 0);
|
||||||
svs_writel_relaxed(svsp, SVSB_INTSTS_MONVOP, INTSTS);
|
svs_writel_relaxed(svsp, SVSB_INTSTS_FLD_MONVOP, INTSTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
static irqreturn_t svs_isr(int irq, void *data)
|
static irqreturn_t svs_isr(int irq, void *data)
|
||||||
|
@ -1201,13 +1264,13 @@ static irqreturn_t svs_isr(int irq, void *data)
|
||||||
int_sts = svs_readl_relaxed(svsp, INTSTS);
|
int_sts = svs_readl_relaxed(svsp, INTSTS);
|
||||||
svs_en = svs_readl_relaxed(svsp, SVSEN);
|
svs_en = svs_readl_relaxed(svsp, SVSEN);
|
||||||
|
|
||||||
if (int_sts == SVSB_INTSTS_COMPLETE &&
|
if (int_sts == SVSB_INTSTS_F0_COMPLETE &&
|
||||||
svs_en == SVSB_EN_INIT01)
|
svs_en == SVSB_PTPEN_INIT01)
|
||||||
svs_init01_isr_handler(svsp);
|
svs_init01_isr_handler(svsp);
|
||||||
else if (int_sts == SVSB_INTSTS_COMPLETE &&
|
else if (int_sts == SVSB_INTSTS_F0_COMPLETE &&
|
||||||
svs_en == SVSB_EN_INIT02)
|
svs_en == SVSB_PTPEN_INIT02)
|
||||||
svs_init02_isr_handler(svsp);
|
svs_init02_isr_handler(svsp);
|
||||||
else if (int_sts & SVSB_INTSTS_MONVOP)
|
else if (int_sts & SVSB_INTSTS_FLD_MONVOP)
|
||||||
svs_mon_mode_isr_handler(svsp);
|
svs_mon_mode_isr_handler(svsp);
|
||||||
else
|
else
|
||||||
svs_error_isr_handler(svsp);
|
svs_error_isr_handler(svsp);
|
||||||
|
@ -1493,8 +1556,8 @@ static int svs_suspend(struct device *dev)
|
||||||
spin_lock_irqsave(&svs_lock, flags);
|
spin_lock_irqsave(&svs_lock, flags);
|
||||||
svsp->pbank = svsb;
|
svsp->pbank = svsb;
|
||||||
svs_switch_bank(svsp);
|
svs_switch_bank(svsp);
|
||||||
svs_writel_relaxed(svsp, SVSB_EN_OFF, SVSEN);
|
svs_writel_relaxed(svsp, SVSB_PTPEN_OFF, SVSEN);
|
||||||
svs_writel_relaxed(svsp, SVSB_INTSTS_CLEAN, INTSTS);
|
svs_writel_relaxed(svsp, SVSB_INTSTS_VAL_CLEAN, INTSTS);
|
||||||
spin_unlock_irqrestore(&svs_lock, flags);
|
spin_unlock_irqrestore(&svs_lock, flags);
|
||||||
|
|
||||||
svsb->phase = SVSB_PHASE_ERROR;
|
svsb->phase = SVSB_PHASE_ERROR;
|
||||||
|
@ -1589,7 +1652,7 @@ static int svs_bank_resource_setup(struct svs_platform *svsp)
|
||||||
|
|
||||||
dev_set_drvdata(svsb->dev, svsp);
|
dev_set_drvdata(svsb->dev, svsp);
|
||||||
|
|
||||||
ret = dev_pm_opp_of_add_table(svsb->opp_dev);
|
ret = devm_pm_opp_of_add_table(svsb->opp_dev);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(svsb->dev, "add opp table fail: %d\n", ret);
|
dev_err(svsb->dev, "add opp table fail: %d\n", ret);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1644,11 +1707,36 @@ static int svs_bank_resource_setup(struct svs_platform *svsp)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int svs_thermal_efuse_get_data(struct svs_platform *svsp)
|
||||||
|
{
|
||||||
|
struct nvmem_cell *cell;
|
||||||
|
|
||||||
|
/* Thermal efuse parsing */
|
||||||
|
cell = nvmem_cell_get(svsp->dev, "t-calibration-data");
|
||||||
|
if (IS_ERR_OR_NULL(cell)) {
|
||||||
|
dev_err(svsp->dev, "no \"t-calibration-data\"? %ld\n", PTR_ERR(cell));
|
||||||
|
return PTR_ERR(cell);
|
||||||
|
}
|
||||||
|
|
||||||
|
svsp->tefuse = nvmem_cell_read(cell, &svsp->tefuse_max);
|
||||||
|
if (IS_ERR(svsp->tefuse)) {
|
||||||
|
dev_err(svsp->dev, "cannot read thermal efuse: %ld\n",
|
||||||
|
PTR_ERR(svsp->tefuse));
|
||||||
|
nvmem_cell_put(cell);
|
||||||
|
return PTR_ERR(svsp->tefuse);
|
||||||
|
}
|
||||||
|
|
||||||
|
svsp->tefuse_max /= sizeof(u32);
|
||||||
|
nvmem_cell_put(cell);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static bool svs_mt8192_efuse_parsing(struct svs_platform *svsp)
|
static bool svs_mt8192_efuse_parsing(struct svs_platform *svsp)
|
||||||
{
|
{
|
||||||
struct svs_bank *svsb;
|
struct svs_bank *svsb;
|
||||||
struct nvmem_cell *cell;
|
|
||||||
u32 idx, i, vmin, golden_temp;
|
u32 idx, i, vmin, golden_temp;
|
||||||
|
int ret;
|
||||||
|
|
||||||
for (i = 0; i < svsp->efuse_max; i++)
|
for (i = 0; i < svsp->efuse_max; i++)
|
||||||
if (svsp->efuse[i])
|
if (svsp->efuse[i])
|
||||||
|
@ -1686,24 +1774,9 @@ static bool svs_mt8192_efuse_parsing(struct svs_platform *svsp)
|
||||||
svsb->vmax += svsb->dvt_fixed;
|
svsb->vmax += svsb->dvt_fixed;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Thermal efuse parsing */
|
ret = svs_thermal_efuse_get_data(svsp);
|
||||||
cell = nvmem_cell_get(svsp->dev, "t-calibration-data");
|
if (ret)
|
||||||
if (IS_ERR_OR_NULL(cell)) {
|
|
||||||
dev_err(svsp->dev, "no \"t-calibration-data\"? %ld\n",
|
|
||||||
PTR_ERR(cell));
|
|
||||||
return false;
|
return false;
|
||||||
}
|
|
||||||
|
|
||||||
svsp->tefuse = nvmem_cell_read(cell, &svsp->tefuse_max);
|
|
||||||
if (IS_ERR(svsp->tefuse)) {
|
|
||||||
dev_err(svsp->dev, "cannot read thermal efuse: %ld\n",
|
|
||||||
PTR_ERR(svsp->tefuse));
|
|
||||||
nvmem_cell_put(cell);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
svsp->tefuse_max /= sizeof(u32);
|
|
||||||
nvmem_cell_put(cell);
|
|
||||||
|
|
||||||
for (i = 0; i < svsp->tefuse_max; i++)
|
for (i = 0; i < svsp->tefuse_max; i++)
|
||||||
if (svsp->tefuse[i] != 0)
|
if (svsp->tefuse[i] != 0)
|
||||||
|
@ -1726,11 +1799,11 @@ static bool svs_mt8192_efuse_parsing(struct svs_platform *svsp)
|
||||||
static bool svs_mt8183_efuse_parsing(struct svs_platform *svsp)
|
static bool svs_mt8183_efuse_parsing(struct svs_platform *svsp)
|
||||||
{
|
{
|
||||||
struct svs_bank *svsb;
|
struct svs_bank *svsb;
|
||||||
struct nvmem_cell *cell;
|
|
||||||
int format[6], x_roomt[6], o_vtsmcu[5], o_vtsabb, tb_roomt = 0;
|
int format[6], x_roomt[6], o_vtsmcu[5], o_vtsabb, tb_roomt = 0;
|
||||||
int adc_ge_t, adc_oe_t, ge, oe, gain, degc_cali, adc_cali_en_t;
|
int adc_ge_t, adc_oe_t, ge, oe, gain, degc_cali, adc_cali_en_t;
|
||||||
int o_slope, o_slope_sign, ts_id;
|
int o_slope, o_slope_sign, ts_id;
|
||||||
u32 idx, i, ft_pgm, mts, temp0, temp1, temp2;
|
u32 idx, i, ft_pgm, mts, temp0, temp1, temp2;
|
||||||
|
int ret;
|
||||||
|
|
||||||
for (i = 0; i < svsp->efuse_max; i++)
|
for (i = 0; i < svsp->efuse_max; i++)
|
||||||
if (svsp->efuse[i])
|
if (svsp->efuse[i])
|
||||||
|
@ -1806,24 +1879,9 @@ static bool svs_mt8183_efuse_parsing(struct svs_platform *svsp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get thermal efuse by nvmem */
|
ret = svs_thermal_efuse_get_data(svsp);
|
||||||
cell = nvmem_cell_get(svsp->dev, "t-calibration-data");
|
if (ret)
|
||||||
if (IS_ERR(cell)) {
|
return false;
|
||||||
dev_err(svsp->dev, "no \"t-calibration-data\"? %ld\n",
|
|
||||||
PTR_ERR(cell));
|
|
||||||
goto remove_mt8183_svsb_mon_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
svsp->tefuse = nvmem_cell_read(cell, &svsp->tefuse_max);
|
|
||||||
if (IS_ERR(svsp->tefuse)) {
|
|
||||||
dev_err(svsp->dev, "cannot read thermal efuse: %ld\n",
|
|
||||||
PTR_ERR(svsp->tefuse));
|
|
||||||
nvmem_cell_put(cell);
|
|
||||||
goto remove_mt8183_svsb_mon_mode;
|
|
||||||
}
|
|
||||||
|
|
||||||
svsp->tefuse_max /= sizeof(u32);
|
|
||||||
nvmem_cell_put(cell);
|
|
||||||
|
|
||||||
/* Thermal efuse parsing */
|
/* Thermal efuse parsing */
|
||||||
adc_ge_t = (svsp->tefuse[1] >> 22) & GENMASK(9, 0);
|
adc_ge_t = (svsp->tefuse[1] >> 22) & GENMASK(9, 0);
|
||||||
|
@ -2244,7 +2302,6 @@ static const struct svs_platform_data svs_mt8192_platform_data = {
|
||||||
.banks = svs_mt8192_banks,
|
.banks = svs_mt8192_banks,
|
||||||
.efuse_parsing = svs_mt8192_efuse_parsing,
|
.efuse_parsing = svs_mt8192_efuse_parsing,
|
||||||
.probe = svs_mt8192_platform_probe,
|
.probe = svs_mt8192_platform_probe,
|
||||||
.irqflags = IRQF_TRIGGER_HIGH,
|
|
||||||
.regs = svs_regs_v2,
|
.regs = svs_regs_v2,
|
||||||
.bank_max = ARRAY_SIZE(svs_mt8192_banks),
|
.bank_max = ARRAY_SIZE(svs_mt8192_banks),
|
||||||
};
|
};
|
||||||
|
@ -2254,7 +2311,6 @@ static const struct svs_platform_data svs_mt8183_platform_data = {
|
||||||
.banks = svs_mt8183_banks,
|
.banks = svs_mt8183_banks,
|
||||||
.efuse_parsing = svs_mt8183_efuse_parsing,
|
.efuse_parsing = svs_mt8183_efuse_parsing,
|
||||||
.probe = svs_mt8183_platform_probe,
|
.probe = svs_mt8183_platform_probe,
|
||||||
.irqflags = IRQF_TRIGGER_LOW,
|
|
||||||
.regs = svs_regs_v2,
|
.regs = svs_regs_v2,
|
||||||
.bank_max = ARRAY_SIZE(svs_mt8183_banks),
|
.bank_max = ARRAY_SIZE(svs_mt8183_banks),
|
||||||
};
|
};
|
||||||
|
@ -2292,7 +2348,6 @@ static struct svs_platform *svs_platform_probe(struct platform_device *pdev)
|
||||||
svsp->banks = svsp_data->banks;
|
svsp->banks = svsp_data->banks;
|
||||||
svsp->efuse_parsing = svsp_data->efuse_parsing;
|
svsp->efuse_parsing = svsp_data->efuse_parsing;
|
||||||
svsp->probe = svsp_data->probe;
|
svsp->probe = svsp_data->probe;
|
||||||
svsp->irqflags = svsp_data->irqflags;
|
|
||||||
svsp->regs = svsp_data->regs;
|
svsp->regs = svsp_data->regs;
|
||||||
svsp->bank_max = svsp_data->bank_max;
|
svsp->bank_max = svsp_data->bank_max;
|
||||||
|
|
||||||
|
@ -2306,8 +2361,7 @@ static struct svs_platform *svs_platform_probe(struct platform_device *pdev)
|
||||||
static int svs_probe(struct platform_device *pdev)
|
static int svs_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct svs_platform *svsp;
|
struct svs_platform *svsp;
|
||||||
unsigned int svsp_irq;
|
int svsp_irq, ret;
|
||||||
int ret;
|
|
||||||
|
|
||||||
svsp = svs_platform_probe(pdev);
|
svsp = svs_platform_probe(pdev);
|
||||||
if (IS_ERR(svsp))
|
if (IS_ERR(svsp))
|
||||||
|
@ -2325,10 +2379,14 @@ static int svs_probe(struct platform_device *pdev)
|
||||||
goto svs_probe_free_resource;
|
goto svs_probe_free_resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
svsp_irq = irq_of_parse_and_map(svsp->dev->of_node, 0);
|
svsp_irq = platform_get_irq(pdev, 0);
|
||||||
|
if (svsp_irq < 0) {
|
||||||
|
ret = svsp_irq;
|
||||||
|
goto svs_probe_free_resource;
|
||||||
|
}
|
||||||
|
|
||||||
ret = devm_request_threaded_irq(svsp->dev, svsp_irq, NULL, svs_isr,
|
ret = devm_request_threaded_irq(svsp->dev, svsp_irq, NULL, svs_isr,
|
||||||
svsp->irqflags | IRQF_ONESHOT,
|
IRQF_ONESHOT, svsp->name, svsp);
|
||||||
svsp->name, svsp);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
dev_err(svsp->dev, "register irq(%d) failed: %d\n",
|
dev_err(svsp->dev, "register irq(%d) failed: %d\n",
|
||||||
svsp_irq, ret);
|
svsp_irq, ret);
|
||||||
|
@ -2392,7 +2450,7 @@ static struct platform_driver svs_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = "mtk-svs",
|
.name = "mtk-svs",
|
||||||
.pm = &svs_pm_ops,
|
.pm = &svs_pm_ops,
|
||||||
.of_match_table = of_match_ptr(svs_of_match),
|
.of_match_table = svs_of_match,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -129,7 +129,7 @@ config QCOM_RPMHPD
|
||||||
|
|
||||||
config QCOM_RPMPD
|
config QCOM_RPMPD
|
||||||
tristate "Qualcomm RPM Power domain driver"
|
tristate "Qualcomm RPM Power domain driver"
|
||||||
depends on PM
|
depends on PM && OF
|
||||||
depends on QCOM_SMD_RPM
|
depends on QCOM_SMD_RPM
|
||||||
select PM_GENERIC_DOMAINS
|
select PM_GENERIC_DOMAINS
|
||||||
select PM_GENERIC_DOMAINS_OF
|
select PM_GENERIC_DOMAINS_OF
|
||||||
|
|
|
@ -5,6 +5,8 @@
|
||||||
* Author: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>, based on
|
* Author: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>, based on
|
||||||
* previous work of Thara Gopinath and msm-4.9 downstream sources.
|
* previous work of Thara Gopinath and msm-4.9 downstream sources.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <linux/err.h>
|
||||||
#include <linux/interconnect.h>
|
#include <linux/interconnect.h>
|
||||||
#include <linux/interrupt.h>
|
#include <linux/interrupt.h>
|
||||||
#include <linux/io.h>
|
#include <linux/io.h>
|
||||||
|
@ -13,6 +15,7 @@
|
||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/platform_device.h>
|
#include <linux/platform_device.h>
|
||||||
#include <linux/pm_opp.h>
|
#include <linux/pm_opp.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
#include <linux/sizes.h>
|
#include <linux/sizes.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -31,33 +34,44 @@
|
||||||
/* Internal sampling clock frequency */
|
/* Internal sampling clock frequency */
|
||||||
#define HW_TIMER_HZ 19200000
|
#define HW_TIMER_HZ 19200000
|
||||||
|
|
||||||
#define BWMON_GLOBAL_IRQ_STATUS 0x0
|
#define BWMON_V4_GLOBAL_IRQ_CLEAR 0x008
|
||||||
#define BWMON_GLOBAL_IRQ_CLEAR 0x8
|
#define BWMON_V4_GLOBAL_IRQ_ENABLE 0x00c
|
||||||
#define BWMON_GLOBAL_IRQ_ENABLE 0xc
|
/*
|
||||||
#define BWMON_GLOBAL_IRQ_ENABLE_ENABLE BIT(0)
|
* All values here and further are matching regmap fields, so without absolute
|
||||||
|
* register offsets.
|
||||||
|
*/
|
||||||
|
#define BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE BIT(0)
|
||||||
|
|
||||||
#define BWMON_IRQ_STATUS 0x100
|
#define BWMON_V4_IRQ_STATUS 0x100
|
||||||
#define BWMON_IRQ_STATUS_ZONE_SHIFT 4
|
#define BWMON_V4_IRQ_CLEAR 0x108
|
||||||
#define BWMON_IRQ_CLEAR 0x108
|
|
||||||
#define BWMON_IRQ_ENABLE 0x10c
|
|
||||||
#define BWMON_IRQ_ENABLE_ZONE1_SHIFT 5
|
|
||||||
#define BWMON_IRQ_ENABLE_ZONE2_SHIFT 6
|
|
||||||
#define BWMON_IRQ_ENABLE_ZONE3_SHIFT 7
|
|
||||||
#define BWMON_IRQ_ENABLE_MASK (BIT(BWMON_IRQ_ENABLE_ZONE1_SHIFT) | \
|
|
||||||
BIT(BWMON_IRQ_ENABLE_ZONE3_SHIFT))
|
|
||||||
|
|
||||||
#define BWMON_ENABLE 0x2a0
|
#define BWMON_V4_IRQ_ENABLE 0x10c
|
||||||
|
#define BWMON_IRQ_ENABLE_MASK (BIT(1) | BIT(3))
|
||||||
|
#define BWMON_V5_IRQ_STATUS 0x000
|
||||||
|
#define BWMON_V5_IRQ_CLEAR 0x008
|
||||||
|
#define BWMON_V5_IRQ_ENABLE 0x00c
|
||||||
|
|
||||||
|
#define BWMON_V4_ENABLE 0x2a0
|
||||||
|
#define BWMON_V5_ENABLE 0x010
|
||||||
#define BWMON_ENABLE_ENABLE BIT(0)
|
#define BWMON_ENABLE_ENABLE BIT(0)
|
||||||
|
|
||||||
#define BWMON_CLEAR 0x2a4
|
#define BWMON_V4_CLEAR 0x2a4
|
||||||
|
#define BWMON_V5_CLEAR 0x014
|
||||||
#define BWMON_CLEAR_CLEAR BIT(0)
|
#define BWMON_CLEAR_CLEAR BIT(0)
|
||||||
|
#define BWMON_CLEAR_CLEAR_ALL BIT(1)
|
||||||
|
|
||||||
#define BWMON_SAMPLE_WINDOW 0x2a8
|
#define BWMON_V4_SAMPLE_WINDOW 0x2a8
|
||||||
#define BWMON_THRESHOLD_HIGH 0x2ac
|
#define BWMON_V5_SAMPLE_WINDOW 0x020
|
||||||
#define BWMON_THRESHOLD_MED 0x2b0
|
|
||||||
#define BWMON_THRESHOLD_LOW 0x2b4
|
|
||||||
|
|
||||||
#define BWMON_ZONE_ACTIONS 0x2b8
|
#define BWMON_V4_THRESHOLD_HIGH 0x2ac
|
||||||
|
#define BWMON_V4_THRESHOLD_MED 0x2b0
|
||||||
|
#define BWMON_V4_THRESHOLD_LOW 0x2b4
|
||||||
|
#define BWMON_V5_THRESHOLD_HIGH 0x024
|
||||||
|
#define BWMON_V5_THRESHOLD_MED 0x028
|
||||||
|
#define BWMON_V5_THRESHOLD_LOW 0x02c
|
||||||
|
|
||||||
|
#define BWMON_V4_ZONE_ACTIONS 0x2b8
|
||||||
|
#define BWMON_V5_ZONE_ACTIONS 0x030
|
||||||
/*
|
/*
|
||||||
* Actions to perform on some zone 'z' when current zone hits the threshold:
|
* Actions to perform on some zone 'z' when current zone hits the threshold:
|
||||||
* Increment counter of zone 'z'
|
* Increment counter of zone 'z'
|
||||||
|
@ -83,55 +97,244 @@
|
||||||
BWMON_ZONE_ACTIONS_CLEAR(2) | \
|
BWMON_ZONE_ACTIONS_CLEAR(2) | \
|
||||||
BWMON_ZONE_ACTIONS_CLEAR(1) | \
|
BWMON_ZONE_ACTIONS_CLEAR(1) | \
|
||||||
BWMON_ZONE_ACTIONS_CLEAR(0))
|
BWMON_ZONE_ACTIONS_CLEAR(0))
|
||||||
/* Value for BWMON_ZONE_ACTIONS */
|
|
||||||
#define BWMON_ZONE_ACTIONS_DEFAULT (BWMON_ZONE_ACTIONS_ZONE0 | \
|
|
||||||
BWMON_ZONE_ACTIONS_ZONE1 << 8 | \
|
|
||||||
BWMON_ZONE_ACTIONS_ZONE2 << 16 | \
|
|
||||||
BWMON_ZONE_ACTIONS_ZONE3 << 24)
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* There is no clear documentation/explanation of BWMON_THRESHOLD_COUNT
|
* There is no clear documentation/explanation of BWMON_V4_THRESHOLD_COUNT
|
||||||
* register. Based on observations, this is number of times one threshold has to
|
* register. Based on observations, this is number of times one threshold has to
|
||||||
* be reached, to trigger interrupt in given zone.
|
* be reached, to trigger interrupt in given zone.
|
||||||
*
|
*
|
||||||
* 0xff are maximum values meant to ignore the zones 0 and 2.
|
* 0xff are maximum values meant to ignore the zones 0 and 2.
|
||||||
*/
|
*/
|
||||||
#define BWMON_THRESHOLD_COUNT 0x2bc
|
#define BWMON_V4_THRESHOLD_COUNT 0x2bc
|
||||||
#define BWMON_THRESHOLD_COUNT_ZONE1_SHIFT 8
|
#define BWMON_V5_THRESHOLD_COUNT 0x034
|
||||||
#define BWMON_THRESHOLD_COUNT_ZONE2_SHIFT 16
|
|
||||||
#define BWMON_THRESHOLD_COUNT_ZONE3_SHIFT 24
|
|
||||||
#define BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT 0xff
|
#define BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT 0xff
|
||||||
#define BWMON_THRESHOLD_COUNT_ZONE2_DEFAULT 0xff
|
#define BWMON_THRESHOLD_COUNT_ZONE2_DEFAULT 0xff
|
||||||
|
|
||||||
/* BWMONv4 count registers use count unit of 64 kB */
|
#define BWMON_V4_ZONE_MAX(zone) (0x2e0 + 4 * (zone))
|
||||||
#define BWMON_COUNT_UNIT_KB 64
|
#define BWMON_V5_ZONE_MAX(zone) (0x044 + 4 * (zone))
|
||||||
#define BWMON_ZONE_COUNT 0x2d8
|
|
||||||
#define BWMON_ZONE_MAX(zone) (0x2e0 + 4 * (zone))
|
/* Quirks for specific BWMON types */
|
||||||
|
#define BWMON_HAS_GLOBAL_IRQ BIT(0)
|
||||||
|
#define BWMON_NEEDS_FORCE_CLEAR BIT(1)
|
||||||
|
|
||||||
|
enum bwmon_fields {
|
||||||
|
F_GLOBAL_IRQ_CLEAR,
|
||||||
|
F_GLOBAL_IRQ_ENABLE,
|
||||||
|
F_IRQ_STATUS,
|
||||||
|
F_IRQ_CLEAR,
|
||||||
|
F_IRQ_ENABLE,
|
||||||
|
F_ENABLE,
|
||||||
|
F_CLEAR,
|
||||||
|
F_SAMPLE_WINDOW,
|
||||||
|
F_THRESHOLD_HIGH,
|
||||||
|
F_THRESHOLD_MED,
|
||||||
|
F_THRESHOLD_LOW,
|
||||||
|
F_ZONE_ACTIONS_ZONE0,
|
||||||
|
F_ZONE_ACTIONS_ZONE1,
|
||||||
|
F_ZONE_ACTIONS_ZONE2,
|
||||||
|
F_ZONE_ACTIONS_ZONE3,
|
||||||
|
F_THRESHOLD_COUNT_ZONE0,
|
||||||
|
F_THRESHOLD_COUNT_ZONE1,
|
||||||
|
F_THRESHOLD_COUNT_ZONE2,
|
||||||
|
F_THRESHOLD_COUNT_ZONE3,
|
||||||
|
F_ZONE0_MAX,
|
||||||
|
F_ZONE1_MAX,
|
||||||
|
F_ZONE2_MAX,
|
||||||
|
F_ZONE3_MAX,
|
||||||
|
|
||||||
|
F_NUM_FIELDS
|
||||||
|
};
|
||||||
|
|
||||||
struct icc_bwmon_data {
|
struct icc_bwmon_data {
|
||||||
unsigned int sample_ms;
|
unsigned int sample_ms;
|
||||||
|
unsigned int count_unit_kb; /* kbytes */
|
||||||
unsigned int default_highbw_kbps;
|
unsigned int default_highbw_kbps;
|
||||||
unsigned int default_medbw_kbps;
|
unsigned int default_medbw_kbps;
|
||||||
unsigned int default_lowbw_kbps;
|
unsigned int default_lowbw_kbps;
|
||||||
u8 zone1_thres_count;
|
u8 zone1_thres_count;
|
||||||
u8 zone3_thres_count;
|
u8 zone3_thres_count;
|
||||||
|
unsigned int quirks;
|
||||||
|
|
||||||
|
const struct regmap_config *regmap_cfg;
|
||||||
|
const struct reg_field *regmap_fields;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct icc_bwmon {
|
struct icc_bwmon {
|
||||||
struct device *dev;
|
struct device *dev;
|
||||||
void __iomem *base;
|
const struct icc_bwmon_data *data;
|
||||||
int irq;
|
int irq;
|
||||||
|
|
||||||
unsigned int default_lowbw_kbps;
|
struct regmap *regmap;
|
||||||
unsigned int sample_ms;
|
struct regmap_field *regs[F_NUM_FIELDS];
|
||||||
|
|
||||||
unsigned int max_bw_kbps;
|
unsigned int max_bw_kbps;
|
||||||
unsigned int min_bw_kbps;
|
unsigned int min_bw_kbps;
|
||||||
unsigned int target_kbps;
|
unsigned int target_kbps;
|
||||||
unsigned int current_kbps;
|
unsigned int current_kbps;
|
||||||
};
|
};
|
||||||
|
|
||||||
static void bwmon_clear_counters(struct icc_bwmon *bwmon)
|
/* BWMON v4 */
|
||||||
|
static const struct reg_field msm8998_bwmon_reg_fields[] = {
|
||||||
|
[F_GLOBAL_IRQ_CLEAR] = REG_FIELD(BWMON_V4_GLOBAL_IRQ_CLEAR, 0, 0),
|
||||||
|
[F_GLOBAL_IRQ_ENABLE] = REG_FIELD(BWMON_V4_GLOBAL_IRQ_ENABLE, 0, 0),
|
||||||
|
[F_IRQ_STATUS] = REG_FIELD(BWMON_V4_IRQ_STATUS, 4, 7),
|
||||||
|
[F_IRQ_CLEAR] = REG_FIELD(BWMON_V4_IRQ_CLEAR, 4, 7),
|
||||||
|
[F_IRQ_ENABLE] = REG_FIELD(BWMON_V4_IRQ_ENABLE, 4, 7),
|
||||||
|
/* F_ENABLE covers entire register to disable other features */
|
||||||
|
[F_ENABLE] = REG_FIELD(BWMON_V4_ENABLE, 0, 31),
|
||||||
|
[F_CLEAR] = REG_FIELD(BWMON_V4_CLEAR, 0, 1),
|
||||||
|
[F_SAMPLE_WINDOW] = REG_FIELD(BWMON_V4_SAMPLE_WINDOW, 0, 23),
|
||||||
|
[F_THRESHOLD_HIGH] = REG_FIELD(BWMON_V4_THRESHOLD_HIGH, 0, 11),
|
||||||
|
[F_THRESHOLD_MED] = REG_FIELD(BWMON_V4_THRESHOLD_MED, 0, 11),
|
||||||
|
[F_THRESHOLD_LOW] = REG_FIELD(BWMON_V4_THRESHOLD_LOW, 0, 11),
|
||||||
|
[F_ZONE_ACTIONS_ZONE0] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 0, 7),
|
||||||
|
[F_ZONE_ACTIONS_ZONE1] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 8, 15),
|
||||||
|
[F_ZONE_ACTIONS_ZONE2] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 16, 23),
|
||||||
|
[F_ZONE_ACTIONS_ZONE3] = REG_FIELD(BWMON_V4_ZONE_ACTIONS, 24, 31),
|
||||||
|
[F_THRESHOLD_COUNT_ZONE0] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 0, 7),
|
||||||
|
[F_THRESHOLD_COUNT_ZONE1] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 8, 15),
|
||||||
|
[F_THRESHOLD_COUNT_ZONE2] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 16, 23),
|
||||||
|
[F_THRESHOLD_COUNT_ZONE3] = REG_FIELD(BWMON_V4_THRESHOLD_COUNT, 24, 31),
|
||||||
|
[F_ZONE0_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(0), 0, 11),
|
||||||
|
[F_ZONE1_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(1), 0, 11),
|
||||||
|
[F_ZONE2_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(2), 0, 11),
|
||||||
|
[F_ZONE3_MAX] = REG_FIELD(BWMON_V4_ZONE_MAX(3), 0, 11),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_range msm8998_bwmon_reg_noread_ranges[] = {
|
||||||
|
regmap_reg_range(BWMON_V4_GLOBAL_IRQ_CLEAR, BWMON_V4_GLOBAL_IRQ_CLEAR),
|
||||||
|
regmap_reg_range(BWMON_V4_IRQ_CLEAR, BWMON_V4_IRQ_CLEAR),
|
||||||
|
regmap_reg_range(BWMON_V4_CLEAR, BWMON_V4_CLEAR),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_access_table msm8998_bwmon_reg_read_table = {
|
||||||
|
.no_ranges = msm8998_bwmon_reg_noread_ranges,
|
||||||
|
.n_no_ranges = ARRAY_SIZE(msm8998_bwmon_reg_noread_ranges),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_range msm8998_bwmon_reg_volatile_ranges[] = {
|
||||||
|
regmap_reg_range(BWMON_V4_IRQ_STATUS, BWMON_V4_IRQ_STATUS),
|
||||||
|
regmap_reg_range(BWMON_V4_ZONE_MAX(0), BWMON_V4_ZONE_MAX(3)),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_access_table msm8998_bwmon_reg_volatile_table = {
|
||||||
|
.yes_ranges = msm8998_bwmon_reg_volatile_ranges,
|
||||||
|
.n_yes_ranges = ARRAY_SIZE(msm8998_bwmon_reg_volatile_ranges),
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill the cache for non-readable registers only as rest does not really
|
||||||
|
* matter and can be read from the device.
|
||||||
|
*/
|
||||||
|
static const struct reg_default msm8998_bwmon_reg_defaults[] = {
|
||||||
|
{ BWMON_V4_GLOBAL_IRQ_CLEAR, 0x0 },
|
||||||
|
{ BWMON_V4_IRQ_CLEAR, 0x0 },
|
||||||
|
{ BWMON_V4_CLEAR, 0x0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_config msm8998_bwmon_regmap_cfg = {
|
||||||
|
.reg_bits = 32,
|
||||||
|
.reg_stride = 4,
|
||||||
|
.val_bits = 32,
|
||||||
|
/*
|
||||||
|
* No concurrent access expected - driver has one interrupt handler,
|
||||||
|
* regmap is not shared, no driver or user-space API.
|
||||||
|
*/
|
||||||
|
.disable_locking = true,
|
||||||
|
.rd_table = &msm8998_bwmon_reg_read_table,
|
||||||
|
.volatile_table = &msm8998_bwmon_reg_volatile_table,
|
||||||
|
.reg_defaults = msm8998_bwmon_reg_defaults,
|
||||||
|
.num_reg_defaults = ARRAY_SIZE(msm8998_bwmon_reg_defaults),
|
||||||
|
/*
|
||||||
|
* Cache is necessary for using regmap fields with non-readable
|
||||||
|
* registers.
|
||||||
|
*/
|
||||||
|
.cache_type = REGCACHE_RBTREE,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* BWMON v5 */
|
||||||
|
static const struct reg_field sdm845_llcc_bwmon_reg_fields[] = {
|
||||||
|
[F_GLOBAL_IRQ_CLEAR] = {},
|
||||||
|
[F_GLOBAL_IRQ_ENABLE] = {},
|
||||||
|
[F_IRQ_STATUS] = REG_FIELD(BWMON_V5_IRQ_STATUS, 0, 3),
|
||||||
|
[F_IRQ_CLEAR] = REG_FIELD(BWMON_V5_IRQ_CLEAR, 0, 3),
|
||||||
|
[F_IRQ_ENABLE] = REG_FIELD(BWMON_V5_IRQ_ENABLE, 0, 3),
|
||||||
|
/* F_ENABLE covers entire register to disable other features */
|
||||||
|
[F_ENABLE] = REG_FIELD(BWMON_V5_ENABLE, 0, 31),
|
||||||
|
[F_CLEAR] = REG_FIELD(BWMON_V5_CLEAR, 0, 1),
|
||||||
|
[F_SAMPLE_WINDOW] = REG_FIELD(BWMON_V5_SAMPLE_WINDOW, 0, 19),
|
||||||
|
[F_THRESHOLD_HIGH] = REG_FIELD(BWMON_V5_THRESHOLD_HIGH, 0, 11),
|
||||||
|
[F_THRESHOLD_MED] = REG_FIELD(BWMON_V5_THRESHOLD_MED, 0, 11),
|
||||||
|
[F_THRESHOLD_LOW] = REG_FIELD(BWMON_V5_THRESHOLD_LOW, 0, 11),
|
||||||
|
[F_ZONE_ACTIONS_ZONE0] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 0, 7),
|
||||||
|
[F_ZONE_ACTIONS_ZONE1] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 8, 15),
|
||||||
|
[F_ZONE_ACTIONS_ZONE2] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 16, 23),
|
||||||
|
[F_ZONE_ACTIONS_ZONE3] = REG_FIELD(BWMON_V5_ZONE_ACTIONS, 24, 31),
|
||||||
|
[F_THRESHOLD_COUNT_ZONE0] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 0, 7),
|
||||||
|
[F_THRESHOLD_COUNT_ZONE1] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 8, 15),
|
||||||
|
[F_THRESHOLD_COUNT_ZONE2] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 16, 23),
|
||||||
|
[F_THRESHOLD_COUNT_ZONE3] = REG_FIELD(BWMON_V5_THRESHOLD_COUNT, 24, 31),
|
||||||
|
[F_ZONE0_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(0), 0, 11),
|
||||||
|
[F_ZONE1_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(1), 0, 11),
|
||||||
|
[F_ZONE2_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(2), 0, 11),
|
||||||
|
[F_ZONE3_MAX] = REG_FIELD(BWMON_V5_ZONE_MAX(3), 0, 11),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_range sdm845_llcc_bwmon_reg_noread_ranges[] = {
|
||||||
|
regmap_reg_range(BWMON_V5_IRQ_CLEAR, BWMON_V5_IRQ_CLEAR),
|
||||||
|
regmap_reg_range(BWMON_V5_CLEAR, BWMON_V5_CLEAR),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_access_table sdm845_llcc_bwmon_reg_read_table = {
|
||||||
|
.no_ranges = sdm845_llcc_bwmon_reg_noread_ranges,
|
||||||
|
.n_no_ranges = ARRAY_SIZE(sdm845_llcc_bwmon_reg_noread_ranges),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_range sdm845_llcc_bwmon_reg_volatile_ranges[] = {
|
||||||
|
regmap_reg_range(BWMON_V5_IRQ_STATUS, BWMON_V5_IRQ_STATUS),
|
||||||
|
regmap_reg_range(BWMON_V5_ZONE_MAX(0), BWMON_V5_ZONE_MAX(3)),
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_access_table sdm845_llcc_bwmon_reg_volatile_table = {
|
||||||
|
.yes_ranges = sdm845_llcc_bwmon_reg_volatile_ranges,
|
||||||
|
.n_yes_ranges = ARRAY_SIZE(sdm845_llcc_bwmon_reg_volatile_ranges),
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Fill the cache for non-readable registers only as rest does not really
|
||||||
|
* matter and can be read from the device.
|
||||||
|
*/
|
||||||
|
static const struct reg_default sdm845_llcc_bwmon_reg_defaults[] = {
|
||||||
|
{ BWMON_V5_IRQ_CLEAR, 0x0 },
|
||||||
|
{ BWMON_V5_CLEAR, 0x0 },
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct regmap_config sdm845_llcc_bwmon_regmap_cfg = {
|
||||||
|
.reg_bits = 32,
|
||||||
|
.reg_stride = 4,
|
||||||
|
.val_bits = 32,
|
||||||
|
/*
|
||||||
|
* No concurrent access expected - driver has one interrupt handler,
|
||||||
|
* regmap is not shared, no driver or user-space API.
|
||||||
|
*/
|
||||||
|
.disable_locking = true,
|
||||||
|
.rd_table = &sdm845_llcc_bwmon_reg_read_table,
|
||||||
|
.volatile_table = &sdm845_llcc_bwmon_reg_volatile_table,
|
||||||
|
.reg_defaults = sdm845_llcc_bwmon_reg_defaults,
|
||||||
|
.num_reg_defaults = ARRAY_SIZE(sdm845_llcc_bwmon_reg_defaults),
|
||||||
|
/*
|
||||||
|
* Cache is necessary for using regmap fields with non-readable
|
||||||
|
* registers.
|
||||||
|
*/
|
||||||
|
.cache_type = REGCACHE_RBTREE,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void bwmon_clear_counters(struct icc_bwmon *bwmon, bool clear_all)
|
||||||
{
|
{
|
||||||
|
unsigned int val = BWMON_CLEAR_CLEAR;
|
||||||
|
|
||||||
|
if (clear_all)
|
||||||
|
val |= BWMON_CLEAR_CLEAR_ALL;
|
||||||
/*
|
/*
|
||||||
* Clear counters. The order and barriers are
|
* Clear counters. The order and barriers are
|
||||||
* important. Quoting downstream Qualcomm msm-4.9 tree:
|
* important. Quoting downstream Qualcomm msm-4.9 tree:
|
||||||
|
@ -140,7 +343,9 @@ static void bwmon_clear_counters(struct icc_bwmon *bwmon)
|
||||||
* region. So, we need to make sure the counter clear is completed
|
* region. So, we need to make sure the counter clear is completed
|
||||||
* before we try to clear the IRQ or do any other counter operations.
|
* before we try to clear the IRQ or do any other counter operations.
|
||||||
*/
|
*/
|
||||||
writel(BWMON_CLEAR_CLEAR, bwmon->base + BWMON_CLEAR);
|
regmap_field_force_write(bwmon->regs[F_CLEAR], val);
|
||||||
|
if (bwmon->data->quirks & BWMON_NEEDS_FORCE_CLEAR)
|
||||||
|
regmap_field_force_write(bwmon->regs[F_CLEAR], 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bwmon_clear_irq(struct icc_bwmon *bwmon)
|
static void bwmon_clear_irq(struct icc_bwmon *bwmon)
|
||||||
|
@ -161,76 +366,91 @@ static void bwmon_clear_irq(struct icc_bwmon *bwmon)
|
||||||
* clearing here so that local writes don't happen before the
|
* clearing here so that local writes don't happen before the
|
||||||
* interrupt is cleared.
|
* interrupt is cleared.
|
||||||
*/
|
*/
|
||||||
writel(BWMON_IRQ_ENABLE_MASK, bwmon->base + BWMON_IRQ_CLEAR);
|
regmap_field_force_write(bwmon->regs[F_IRQ_CLEAR], BWMON_IRQ_ENABLE_MASK);
|
||||||
writel(BIT(0), bwmon->base + BWMON_GLOBAL_IRQ_CLEAR);
|
if (bwmon->data->quirks & BWMON_NEEDS_FORCE_CLEAR)
|
||||||
|
regmap_field_force_write(bwmon->regs[F_IRQ_CLEAR], 0);
|
||||||
|
if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
|
||||||
|
regmap_field_force_write(bwmon->regs[F_GLOBAL_IRQ_CLEAR],
|
||||||
|
BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bwmon_disable(struct icc_bwmon *bwmon)
|
static void bwmon_disable(struct icc_bwmon *bwmon)
|
||||||
{
|
{
|
||||||
/* Disable interrupts. Strict ordering, see bwmon_clear_irq(). */
|
/* Disable interrupts. Strict ordering, see bwmon_clear_irq(). */
|
||||||
writel(0x0, bwmon->base + BWMON_GLOBAL_IRQ_ENABLE);
|
if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
|
||||||
writel(0x0, bwmon->base + BWMON_IRQ_ENABLE);
|
regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE], 0x0);
|
||||||
|
regmap_field_write(bwmon->regs[F_IRQ_ENABLE], 0x0);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Disable bwmon. Must happen before bwmon_clear_irq() to avoid spurious
|
* Disable bwmon. Must happen before bwmon_clear_irq() to avoid spurious
|
||||||
* IRQ.
|
* IRQ.
|
||||||
*/
|
*/
|
||||||
writel(0x0, bwmon->base + BWMON_ENABLE);
|
regmap_field_write(bwmon->regs[F_ENABLE], 0x0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bwmon_enable(struct icc_bwmon *bwmon, unsigned int irq_enable)
|
static void bwmon_enable(struct icc_bwmon *bwmon, unsigned int irq_enable)
|
||||||
{
|
{
|
||||||
/* Enable interrupts */
|
/* Enable interrupts */
|
||||||
writel(BWMON_GLOBAL_IRQ_ENABLE_ENABLE,
|
if (bwmon->data->quirks & BWMON_HAS_GLOBAL_IRQ)
|
||||||
bwmon->base + BWMON_GLOBAL_IRQ_ENABLE);
|
regmap_field_write(bwmon->regs[F_GLOBAL_IRQ_ENABLE],
|
||||||
writel(irq_enable, bwmon->base + BWMON_IRQ_ENABLE);
|
BWMON_V4_GLOBAL_IRQ_ENABLE_ENABLE);
|
||||||
|
regmap_field_write(bwmon->regs[F_IRQ_ENABLE], irq_enable);
|
||||||
|
|
||||||
/* Enable bwmon */
|
/* Enable bwmon */
|
||||||
writel(BWMON_ENABLE_ENABLE, bwmon->base + BWMON_ENABLE);
|
regmap_field_write(bwmon->regs[F_ENABLE], BWMON_ENABLE_ENABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static unsigned int bwmon_kbps_to_count(unsigned int kbps)
|
static unsigned int bwmon_kbps_to_count(struct icc_bwmon *bwmon,
|
||||||
|
unsigned int kbps)
|
||||||
{
|
{
|
||||||
return kbps / BWMON_COUNT_UNIT_KB;
|
return kbps / bwmon->data->count_unit_kb;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bwmon_set_threshold(struct icc_bwmon *bwmon, unsigned int reg,
|
static void bwmon_set_threshold(struct icc_bwmon *bwmon,
|
||||||
unsigned int kbps)
|
struct regmap_field *reg, unsigned int kbps)
|
||||||
{
|
{
|
||||||
unsigned int thres;
|
unsigned int thres;
|
||||||
|
|
||||||
thres = mult_frac(bwmon_kbps_to_count(kbps), bwmon->sample_ms,
|
thres = mult_frac(bwmon_kbps_to_count(bwmon, kbps),
|
||||||
MSEC_PER_SEC);
|
bwmon->data->sample_ms, MSEC_PER_SEC);
|
||||||
writel_relaxed(thres, bwmon->base + reg);
|
regmap_field_write(reg, thres);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bwmon_start(struct icc_bwmon *bwmon,
|
static void bwmon_start(struct icc_bwmon *bwmon)
|
||||||
const struct icc_bwmon_data *data)
|
|
||||||
{
|
{
|
||||||
unsigned int thres_count;
|
const struct icc_bwmon_data *data = bwmon->data;
|
||||||
int window;
|
int window;
|
||||||
|
|
||||||
bwmon_clear_counters(bwmon);
|
bwmon_clear_counters(bwmon, true);
|
||||||
|
|
||||||
window = mult_frac(bwmon->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
|
window = mult_frac(bwmon->data->sample_ms, HW_TIMER_HZ, MSEC_PER_SEC);
|
||||||
/* Maximum sampling window: 0xfffff */
|
/* Maximum sampling window: 0xffffff for v4 and 0xfffff for v5 */
|
||||||
writel_relaxed(window, bwmon->base + BWMON_SAMPLE_WINDOW);
|
regmap_field_write(bwmon->regs[F_SAMPLE_WINDOW], window);
|
||||||
|
|
||||||
bwmon_set_threshold(bwmon, BWMON_THRESHOLD_HIGH,
|
bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_HIGH],
|
||||||
data->default_highbw_kbps);
|
data->default_highbw_kbps);
|
||||||
bwmon_set_threshold(bwmon, BWMON_THRESHOLD_MED,
|
bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_MED],
|
||||||
data->default_medbw_kbps);
|
data->default_medbw_kbps);
|
||||||
bwmon_set_threshold(bwmon, BWMON_THRESHOLD_LOW,
|
bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_LOW],
|
||||||
data->default_lowbw_kbps);
|
data->default_lowbw_kbps);
|
||||||
|
|
||||||
thres_count = data->zone3_thres_count << BWMON_THRESHOLD_COUNT_ZONE3_SHIFT |
|
regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE0],
|
||||||
BWMON_THRESHOLD_COUNT_ZONE2_DEFAULT << BWMON_THRESHOLD_COUNT_ZONE2_SHIFT |
|
BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT);
|
||||||
data->zone1_thres_count << BWMON_THRESHOLD_COUNT_ZONE1_SHIFT |
|
regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE1],
|
||||||
BWMON_THRESHOLD_COUNT_ZONE0_DEFAULT;
|
data->zone1_thres_count);
|
||||||
writel_relaxed(thres_count, bwmon->base + BWMON_THRESHOLD_COUNT);
|
regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE2],
|
||||||
writel_relaxed(BWMON_ZONE_ACTIONS_DEFAULT,
|
BWMON_THRESHOLD_COUNT_ZONE2_DEFAULT);
|
||||||
bwmon->base + BWMON_ZONE_ACTIONS);
|
regmap_field_write(bwmon->regs[F_THRESHOLD_COUNT_ZONE3],
|
||||||
/* Write barriers in bwmon_clear_irq() */
|
data->zone3_thres_count);
|
||||||
|
|
||||||
|
regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE0],
|
||||||
|
BWMON_ZONE_ACTIONS_ZONE0);
|
||||||
|
regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE1],
|
||||||
|
BWMON_ZONE_ACTIONS_ZONE1);
|
||||||
|
regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE2],
|
||||||
|
BWMON_ZONE_ACTIONS_ZONE2);
|
||||||
|
regmap_field_write(bwmon->regs[F_ZONE_ACTIONS_ZONE3],
|
||||||
|
BWMON_ZONE_ACTIONS_ZONE3);
|
||||||
|
|
||||||
bwmon_clear_irq(bwmon);
|
bwmon_clear_irq(bwmon);
|
||||||
bwmon_enable(bwmon, BWMON_IRQ_ENABLE_MASK);
|
bwmon_enable(bwmon, BWMON_IRQ_ENABLE_MASK);
|
||||||
|
@ -242,7 +462,9 @@ static irqreturn_t bwmon_intr(int irq, void *dev_id)
|
||||||
unsigned int status, max;
|
unsigned int status, max;
|
||||||
int zone;
|
int zone;
|
||||||
|
|
||||||
status = readl(bwmon->base + BWMON_IRQ_STATUS);
|
if (regmap_field_read(bwmon->regs[F_IRQ_STATUS], &status))
|
||||||
|
return IRQ_NONE;
|
||||||
|
|
||||||
status &= BWMON_IRQ_ENABLE_MASK;
|
status &= BWMON_IRQ_ENABLE_MASK;
|
||||||
if (!status) {
|
if (!status) {
|
||||||
/*
|
/*
|
||||||
|
@ -259,15 +481,18 @@ static irqreturn_t bwmon_intr(int irq, void *dev_id)
|
||||||
|
|
||||||
bwmon_disable(bwmon);
|
bwmon_disable(bwmon);
|
||||||
|
|
||||||
zone = get_bitmask_order(status >> BWMON_IRQ_STATUS_ZONE_SHIFT) - 1;
|
zone = get_bitmask_order(status) - 1;
|
||||||
/*
|
/*
|
||||||
* Zone max bytes count register returns count units within sampling
|
* Zone max bytes count register returns count units within sampling
|
||||||
* window. Downstream kernel for BWMONv4 (called BWMON type 2 in
|
* window. Downstream kernel for BWMONv4 (called BWMON type 2 in
|
||||||
* downstream) always increments the max bytes count by one.
|
* downstream) always increments the max bytes count by one.
|
||||||
*/
|
*/
|
||||||
max = readl(bwmon->base + BWMON_ZONE_MAX(zone)) + 1;
|
if (regmap_field_read(bwmon->regs[F_ZONE0_MAX + zone], &max))
|
||||||
max *= BWMON_COUNT_UNIT_KB;
|
return IRQ_NONE;
|
||||||
bwmon->target_kbps = mult_frac(max, MSEC_PER_SEC, bwmon->sample_ms);
|
|
||||||
|
max += 1;
|
||||||
|
max *= bwmon->data->count_unit_kb;
|
||||||
|
bwmon->target_kbps = mult_frac(max, MSEC_PER_SEC, bwmon->data->sample_ms);
|
||||||
|
|
||||||
return IRQ_WAKE_THREAD;
|
return IRQ_WAKE_THREAD;
|
||||||
}
|
}
|
||||||
|
@ -297,16 +522,17 @@ static irqreturn_t bwmon_intr_thread(int irq, void *dev_id)
|
||||||
up_kbps = bwmon->target_kbps + 1;
|
up_kbps = bwmon->target_kbps + 1;
|
||||||
|
|
||||||
if (bwmon->target_kbps >= bwmon->max_bw_kbps)
|
if (bwmon->target_kbps >= bwmon->max_bw_kbps)
|
||||||
irq_enable = BIT(BWMON_IRQ_ENABLE_ZONE1_SHIFT);
|
irq_enable = BIT(1);
|
||||||
else if (bwmon->target_kbps <= bwmon->min_bw_kbps)
|
else if (bwmon->target_kbps <= bwmon->min_bw_kbps)
|
||||||
irq_enable = BIT(BWMON_IRQ_ENABLE_ZONE3_SHIFT);
|
irq_enable = BIT(3);
|
||||||
else
|
else
|
||||||
irq_enable = BWMON_IRQ_ENABLE_MASK;
|
irq_enable = BWMON_IRQ_ENABLE_MASK;
|
||||||
|
|
||||||
bwmon_set_threshold(bwmon, BWMON_THRESHOLD_HIGH, up_kbps);
|
bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_HIGH],
|
||||||
bwmon_set_threshold(bwmon, BWMON_THRESHOLD_MED, down_kbps);
|
up_kbps);
|
||||||
/* Write barriers in bwmon_clear_counters() */
|
bwmon_set_threshold(bwmon, bwmon->regs[F_THRESHOLD_MED],
|
||||||
bwmon_clear_counters(bwmon);
|
down_kbps);
|
||||||
|
bwmon_clear_counters(bwmon, false);
|
||||||
bwmon_clear_irq(bwmon);
|
bwmon_clear_irq(bwmon);
|
||||||
bwmon_enable(bwmon, irq_enable);
|
bwmon_enable(bwmon, irq_enable);
|
||||||
|
|
||||||
|
@ -324,25 +550,47 @@ out:
|
||||||
return IRQ_HANDLED;
|
return IRQ_HANDLED;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int bwmon_init_regmap(struct platform_device *pdev,
|
||||||
|
struct icc_bwmon *bwmon)
|
||||||
|
{
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
void __iomem *base;
|
||||||
|
struct regmap *map;
|
||||||
|
|
||||||
|
base = devm_platform_ioremap_resource(pdev, 0);
|
||||||
|
if (IS_ERR(base))
|
||||||
|
return dev_err_probe(dev, PTR_ERR(base),
|
||||||
|
"failed to map bwmon registers\n");
|
||||||
|
|
||||||
|
map = devm_regmap_init_mmio(dev, base, bwmon->data->regmap_cfg);
|
||||||
|
if (IS_ERR(map))
|
||||||
|
return dev_err_probe(dev, PTR_ERR(map),
|
||||||
|
"failed to initialize regmap\n");
|
||||||
|
|
||||||
|
BUILD_BUG_ON(ARRAY_SIZE(msm8998_bwmon_reg_fields) != F_NUM_FIELDS);
|
||||||
|
BUILD_BUG_ON(ARRAY_SIZE(sdm845_llcc_bwmon_reg_fields) != F_NUM_FIELDS);
|
||||||
|
|
||||||
|
return devm_regmap_field_bulk_alloc(dev, map, bwmon->regs,
|
||||||
|
bwmon->data->regmap_fields,
|
||||||
|
F_NUM_FIELDS);
|
||||||
|
}
|
||||||
|
|
||||||
static int bwmon_probe(struct platform_device *pdev)
|
static int bwmon_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct dev_pm_opp *opp;
|
struct dev_pm_opp *opp;
|
||||||
struct icc_bwmon *bwmon;
|
struct icc_bwmon *bwmon;
|
||||||
const struct icc_bwmon_data *data;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
bwmon = devm_kzalloc(dev, sizeof(*bwmon), GFP_KERNEL);
|
bwmon = devm_kzalloc(dev, sizeof(*bwmon), GFP_KERNEL);
|
||||||
if (!bwmon)
|
if (!bwmon)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
data = of_device_get_match_data(dev);
|
bwmon->data = of_device_get_match_data(dev);
|
||||||
|
|
||||||
bwmon->base = devm_platform_ioremap_resource(pdev, 0);
|
ret = bwmon_init_regmap(pdev, bwmon);
|
||||||
if (IS_ERR(bwmon->base)) {
|
if (ret)
|
||||||
dev_err(dev, "failed to map bwmon registers\n");
|
return ret;
|
||||||
return PTR_ERR(bwmon->base);
|
|
||||||
}
|
|
||||||
|
|
||||||
bwmon->irq = platform_get_irq(pdev, 0);
|
bwmon->irq = platform_get_irq(pdev, 0);
|
||||||
if (bwmon->irq < 0)
|
if (bwmon->irq < 0)
|
||||||
|
@ -362,8 +610,6 @@ static int bwmon_probe(struct platform_device *pdev)
|
||||||
if (IS_ERR(opp))
|
if (IS_ERR(opp))
|
||||||
return dev_err_probe(dev, ret, "failed to find min peak bandwidth\n");
|
return dev_err_probe(dev, ret, "failed to find min peak bandwidth\n");
|
||||||
|
|
||||||
bwmon->sample_ms = data->sample_ms;
|
|
||||||
bwmon->default_lowbw_kbps = data->default_lowbw_kbps;
|
|
||||||
bwmon->dev = dev;
|
bwmon->dev = dev;
|
||||||
|
|
||||||
bwmon_disable(bwmon);
|
bwmon_disable(bwmon);
|
||||||
|
@ -374,7 +620,7 @@ static int bwmon_probe(struct platform_device *pdev)
|
||||||
return dev_err_probe(dev, ret, "failed to request IRQ\n");
|
return dev_err_probe(dev, ret, "failed to request IRQ\n");
|
||||||
|
|
||||||
platform_set_drvdata(pdev, bwmon);
|
platform_set_drvdata(pdev, bwmon);
|
||||||
bwmon_start(bwmon, data);
|
bwmon_start(bwmon);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -388,18 +634,55 @@ static int bwmon_remove(struct platform_device *pdev)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* BWMON v4 */
|
|
||||||
static const struct icc_bwmon_data msm8998_bwmon_data = {
|
static const struct icc_bwmon_data msm8998_bwmon_data = {
|
||||||
.sample_ms = 4,
|
.sample_ms = 4,
|
||||||
|
.count_unit_kb = 64,
|
||||||
.default_highbw_kbps = 4800 * 1024, /* 4.8 GBps */
|
.default_highbw_kbps = 4800 * 1024, /* 4.8 GBps */
|
||||||
.default_medbw_kbps = 512 * 1024, /* 512 MBps */
|
.default_medbw_kbps = 512 * 1024, /* 512 MBps */
|
||||||
.default_lowbw_kbps = 0,
|
.default_lowbw_kbps = 0,
|
||||||
.zone1_thres_count = 16,
|
.zone1_thres_count = 16,
|
||||||
.zone3_thres_count = 1,
|
.zone3_thres_count = 1,
|
||||||
|
.quirks = BWMON_HAS_GLOBAL_IRQ,
|
||||||
|
.regmap_fields = msm8998_bwmon_reg_fields,
|
||||||
|
.regmap_cfg = &msm8998_bwmon_regmap_cfg,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct icc_bwmon_data sdm845_llcc_bwmon_data = {
|
||||||
|
.sample_ms = 4,
|
||||||
|
.count_unit_kb = 1024,
|
||||||
|
.default_highbw_kbps = 800 * 1024, /* 800 MBps */
|
||||||
|
.default_medbw_kbps = 256 * 1024, /* 256 MBps */
|
||||||
|
.default_lowbw_kbps = 0,
|
||||||
|
.zone1_thres_count = 16,
|
||||||
|
.zone3_thres_count = 1,
|
||||||
|
.regmap_fields = sdm845_llcc_bwmon_reg_fields,
|
||||||
|
.regmap_cfg = &sdm845_llcc_bwmon_regmap_cfg,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct icc_bwmon_data sc7280_llcc_bwmon_data = {
|
||||||
|
.sample_ms = 4,
|
||||||
|
.count_unit_kb = 64,
|
||||||
|
.default_highbw_kbps = 800 * 1024, /* 800 MBps */
|
||||||
|
.default_medbw_kbps = 256 * 1024, /* 256 MBps */
|
||||||
|
.default_lowbw_kbps = 0,
|
||||||
|
.zone1_thres_count = 16,
|
||||||
|
.zone3_thres_count = 1,
|
||||||
|
.quirks = BWMON_NEEDS_FORCE_CLEAR,
|
||||||
|
.regmap_fields = sdm845_llcc_bwmon_reg_fields,
|
||||||
|
.regmap_cfg = &sdm845_llcc_bwmon_regmap_cfg,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct of_device_id bwmon_of_match[] = {
|
static const struct of_device_id bwmon_of_match[] = {
|
||||||
{ .compatible = "qcom,msm8998-bwmon", .data = &msm8998_bwmon_data },
|
{
|
||||||
|
.compatible = "qcom,msm8998-bwmon",
|
||||||
|
.data = &msm8998_bwmon_data
|
||||||
|
}, {
|
||||||
|
.compatible = "qcom,sdm845-llcc-bwmon",
|
||||||
|
.data = &sdm845_llcc_bwmon_data
|
||||||
|
}, {
|
||||||
|
.compatible = "qcom,sc7280-llcc-bwmon",
|
||||||
|
.data = &sc7280_llcc_bwmon_data
|
||||||
|
},
|
||||||
{}
|
{}
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, bwmon_of_match);
|
MODULE_DEVICE_TABLE(of, bwmon_of_match);
|
||||||
|
|
|
@ -104,6 +104,7 @@ struct qcom_llcc_config {
|
||||||
int size;
|
int size;
|
||||||
bool need_llcc_cfg;
|
bool need_llcc_cfg;
|
||||||
const u32 *reg_offset;
|
const u32 *reg_offset;
|
||||||
|
const struct llcc_edac_reg_offset *edac_reg_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum llcc_reg_offset {
|
enum llcc_reg_offset {
|
||||||
|
@ -296,12 +297,68 @@ static const struct llcc_slice_config sm8450_data[] = {
|
||||||
{LLCC_AENPU, 8, 2048, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 },
|
{LLCC_AENPU, 8, 2048, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u32 llcc_v1_2_reg_offset[] = {
|
static const struct llcc_edac_reg_offset llcc_v1_edac_reg_offset = {
|
||||||
|
.trp_ecc_error_status0 = 0x20344,
|
||||||
|
.trp_ecc_error_status1 = 0x20348,
|
||||||
|
.trp_ecc_sb_err_syn0 = 0x2304c,
|
||||||
|
.trp_ecc_db_err_syn0 = 0x20370,
|
||||||
|
.trp_ecc_error_cntr_clear = 0x20440,
|
||||||
|
.trp_interrupt_0_status = 0x20480,
|
||||||
|
.trp_interrupt_0_clear = 0x20484,
|
||||||
|
.trp_interrupt_0_enable = 0x20488,
|
||||||
|
|
||||||
|
/* LLCC Common registers */
|
||||||
|
.cmn_status0 = 0x3000c,
|
||||||
|
.cmn_interrupt_0_enable = 0x3001c,
|
||||||
|
.cmn_interrupt_2_enable = 0x3003c,
|
||||||
|
|
||||||
|
/* LLCC DRP registers */
|
||||||
|
.drp_ecc_error_cfg = 0x40000,
|
||||||
|
.drp_ecc_error_cntr_clear = 0x40004,
|
||||||
|
.drp_interrupt_status = 0x41000,
|
||||||
|
.drp_interrupt_clear = 0x41008,
|
||||||
|
.drp_interrupt_enable = 0x4100c,
|
||||||
|
.drp_ecc_error_status0 = 0x42044,
|
||||||
|
.drp_ecc_error_status1 = 0x42048,
|
||||||
|
.drp_ecc_sb_err_syn0 = 0x4204c,
|
||||||
|
.drp_ecc_db_err_syn0 = 0x42070,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct llcc_edac_reg_offset llcc_v2_1_edac_reg_offset = {
|
||||||
|
.trp_ecc_error_status0 = 0x20344,
|
||||||
|
.trp_ecc_error_status1 = 0x20348,
|
||||||
|
.trp_ecc_sb_err_syn0 = 0x2034c,
|
||||||
|
.trp_ecc_db_err_syn0 = 0x20370,
|
||||||
|
.trp_ecc_error_cntr_clear = 0x20440,
|
||||||
|
.trp_interrupt_0_status = 0x20480,
|
||||||
|
.trp_interrupt_0_clear = 0x20484,
|
||||||
|
.trp_interrupt_0_enable = 0x20488,
|
||||||
|
|
||||||
|
/* LLCC Common registers */
|
||||||
|
.cmn_status0 = 0x3400c,
|
||||||
|
.cmn_interrupt_0_enable = 0x3401c,
|
||||||
|
.cmn_interrupt_2_enable = 0x3403c,
|
||||||
|
|
||||||
|
/* LLCC DRP registers */
|
||||||
|
.drp_ecc_error_cfg = 0x50000,
|
||||||
|
.drp_ecc_error_cntr_clear = 0x50004,
|
||||||
|
.drp_interrupt_status = 0x50020,
|
||||||
|
.drp_interrupt_clear = 0x50028,
|
||||||
|
.drp_interrupt_enable = 0x5002c,
|
||||||
|
.drp_ecc_error_status0 = 0x520f4,
|
||||||
|
.drp_ecc_error_status1 = 0x520f8,
|
||||||
|
.drp_ecc_sb_err_syn0 = 0x520fc,
|
||||||
|
.drp_ecc_db_err_syn0 = 0x52120,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* LLCC register offset starting from v1.0.0 */
|
||||||
|
static const u32 llcc_v1_reg_offset[] = {
|
||||||
[LLCC_COMMON_HW_INFO] = 0x00030000,
|
[LLCC_COMMON_HW_INFO] = 0x00030000,
|
||||||
[LLCC_COMMON_STATUS0] = 0x0003000c,
|
[LLCC_COMMON_STATUS0] = 0x0003000c,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const u32 llcc_v21_reg_offset[] = {
|
/* LLCC register offset starting from v2.0.1 */
|
||||||
|
static const u32 llcc_v2_1_reg_offset[] = {
|
||||||
[LLCC_COMMON_HW_INFO] = 0x00034000,
|
[LLCC_COMMON_HW_INFO] = 0x00034000,
|
||||||
[LLCC_COMMON_STATUS0] = 0x0003400c,
|
[LLCC_COMMON_STATUS0] = 0x0003400c,
|
||||||
};
|
};
|
||||||
|
@ -310,70 +367,80 @@ static const struct qcom_llcc_config sc7180_cfg = {
|
||||||
.sct_data = sc7180_data,
|
.sct_data = sc7180_data,
|
||||||
.size = ARRAY_SIZE(sc7180_data),
|
.size = ARRAY_SIZE(sc7180_data),
|
||||||
.need_llcc_cfg = true,
|
.need_llcc_cfg = true,
|
||||||
.reg_offset = llcc_v1_2_reg_offset,
|
.reg_offset = llcc_v1_reg_offset,
|
||||||
|
.edac_reg_offset = &llcc_v1_edac_reg_offset,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct qcom_llcc_config sc7280_cfg = {
|
static const struct qcom_llcc_config sc7280_cfg = {
|
||||||
.sct_data = sc7280_data,
|
.sct_data = sc7280_data,
|
||||||
.size = ARRAY_SIZE(sc7280_data),
|
.size = ARRAY_SIZE(sc7280_data),
|
||||||
.need_llcc_cfg = true,
|
.need_llcc_cfg = true,
|
||||||
.reg_offset = llcc_v1_2_reg_offset,
|
.reg_offset = llcc_v1_reg_offset,
|
||||||
|
.edac_reg_offset = &llcc_v1_edac_reg_offset,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct qcom_llcc_config sc8180x_cfg = {
|
static const struct qcom_llcc_config sc8180x_cfg = {
|
||||||
.sct_data = sc8180x_data,
|
.sct_data = sc8180x_data,
|
||||||
.size = ARRAY_SIZE(sc8180x_data),
|
.size = ARRAY_SIZE(sc8180x_data),
|
||||||
.need_llcc_cfg = true,
|
.need_llcc_cfg = true,
|
||||||
.reg_offset = llcc_v1_2_reg_offset,
|
.reg_offset = llcc_v1_reg_offset,
|
||||||
|
.edac_reg_offset = &llcc_v1_edac_reg_offset,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct qcom_llcc_config sc8280xp_cfg = {
|
static const struct qcom_llcc_config sc8280xp_cfg = {
|
||||||
.sct_data = sc8280xp_data,
|
.sct_data = sc8280xp_data,
|
||||||
.size = ARRAY_SIZE(sc8280xp_data),
|
.size = ARRAY_SIZE(sc8280xp_data),
|
||||||
.need_llcc_cfg = true,
|
.need_llcc_cfg = true,
|
||||||
.reg_offset = llcc_v1_2_reg_offset,
|
.reg_offset = llcc_v1_reg_offset,
|
||||||
|
.edac_reg_offset = &llcc_v1_edac_reg_offset,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct qcom_llcc_config sdm845_cfg = {
|
static const struct qcom_llcc_config sdm845_cfg = {
|
||||||
.sct_data = sdm845_data,
|
.sct_data = sdm845_data,
|
||||||
.size = ARRAY_SIZE(sdm845_data),
|
.size = ARRAY_SIZE(sdm845_data),
|
||||||
.need_llcc_cfg = false,
|
.need_llcc_cfg = false,
|
||||||
.reg_offset = llcc_v1_2_reg_offset,
|
.reg_offset = llcc_v1_reg_offset,
|
||||||
|
.edac_reg_offset = &llcc_v1_edac_reg_offset,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct qcom_llcc_config sm6350_cfg = {
|
static const struct qcom_llcc_config sm6350_cfg = {
|
||||||
.sct_data = sm6350_data,
|
.sct_data = sm6350_data,
|
||||||
.size = ARRAY_SIZE(sm6350_data),
|
.size = ARRAY_SIZE(sm6350_data),
|
||||||
.need_llcc_cfg = true,
|
.need_llcc_cfg = true,
|
||||||
.reg_offset = llcc_v1_2_reg_offset,
|
.reg_offset = llcc_v1_reg_offset,
|
||||||
|
.edac_reg_offset = &llcc_v1_edac_reg_offset,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct qcom_llcc_config sm8150_cfg = {
|
static const struct qcom_llcc_config sm8150_cfg = {
|
||||||
.sct_data = sm8150_data,
|
.sct_data = sm8150_data,
|
||||||
.size = ARRAY_SIZE(sm8150_data),
|
.size = ARRAY_SIZE(sm8150_data),
|
||||||
.need_llcc_cfg = true,
|
.need_llcc_cfg = true,
|
||||||
.reg_offset = llcc_v1_2_reg_offset,
|
.reg_offset = llcc_v1_reg_offset,
|
||||||
|
.edac_reg_offset = &llcc_v1_edac_reg_offset,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct qcom_llcc_config sm8250_cfg = {
|
static const struct qcom_llcc_config sm8250_cfg = {
|
||||||
.sct_data = sm8250_data,
|
.sct_data = sm8250_data,
|
||||||
.size = ARRAY_SIZE(sm8250_data),
|
.size = ARRAY_SIZE(sm8250_data),
|
||||||
.need_llcc_cfg = true,
|
.need_llcc_cfg = true,
|
||||||
.reg_offset = llcc_v1_2_reg_offset,
|
.reg_offset = llcc_v1_reg_offset,
|
||||||
|
.edac_reg_offset = &llcc_v1_edac_reg_offset,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct qcom_llcc_config sm8350_cfg = {
|
static const struct qcom_llcc_config sm8350_cfg = {
|
||||||
.sct_data = sm8350_data,
|
.sct_data = sm8350_data,
|
||||||
.size = ARRAY_SIZE(sm8350_data),
|
.size = ARRAY_SIZE(sm8350_data),
|
||||||
.need_llcc_cfg = true,
|
.need_llcc_cfg = true,
|
||||||
.reg_offset = llcc_v1_2_reg_offset,
|
.reg_offset = llcc_v1_reg_offset,
|
||||||
|
.edac_reg_offset = &llcc_v1_edac_reg_offset,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct qcom_llcc_config sm8450_cfg = {
|
static const struct qcom_llcc_config sm8450_cfg = {
|
||||||
.sct_data = sm8450_data,
|
.sct_data = sm8450_data,
|
||||||
.size = ARRAY_SIZE(sm8450_data),
|
.size = ARRAY_SIZE(sm8450_data),
|
||||||
.need_llcc_cfg = true,
|
.need_llcc_cfg = true,
|
||||||
.reg_offset = llcc_v21_reg_offset,
|
.reg_offset = llcc_v2_1_reg_offset,
|
||||||
|
.edac_reg_offset = &llcc_v2_1_edac_reg_offset,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
|
static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER;
|
||||||
|
@ -774,6 +841,7 @@ static int qcom_llcc_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
drv_data->cfg = llcc_cfg;
|
drv_data->cfg = llcc_cfg;
|
||||||
drv_data->cfg_size = sz;
|
drv_data->cfg_size = sz;
|
||||||
|
drv_data->edac_reg_offset = cfg->edac_reg_offset;
|
||||||
mutex_init(&drv_data->lock);
|
mutex_init(&drv_data->lock);
|
||||||
platform_set_drvdata(pdev, drv_data);
|
platform_set_drvdata(pdev, drv_data);
|
||||||
|
|
||||||
|
|
|
@ -246,6 +246,14 @@ static const struct stats_config rpm_data_dba0 = {
|
||||||
.subsystem_stats_in_smem = false,
|
.subsystem_stats_in_smem = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct stats_config rpmh_data_sdm845 = {
|
||||||
|
.stats_offset = 0x48,
|
||||||
|
.num_records = 2,
|
||||||
|
.appended_stats_avail = false,
|
||||||
|
.dynamic_offset = false,
|
||||||
|
.subsystem_stats_in_smem = true,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct stats_config rpmh_data = {
|
static const struct stats_config rpmh_data = {
|
||||||
.stats_offset = 0x48,
|
.stats_offset = 0x48,
|
||||||
.num_records = 3,
|
.num_records = 3,
|
||||||
|
@ -261,6 +269,7 @@ static const struct of_device_id qcom_stats_table[] = {
|
||||||
{ .compatible = "qcom,msm8974-rpm-stats", .data = &rpm_data_dba0 },
|
{ .compatible = "qcom,msm8974-rpm-stats", .data = &rpm_data_dba0 },
|
||||||
{ .compatible = "qcom,rpm-stats", .data = &rpm_data },
|
{ .compatible = "qcom,rpm-stats", .data = &rpm_data },
|
||||||
{ .compatible = "qcom,rpmh-stats", .data = &rpmh_data },
|
{ .compatible = "qcom,rpmh-stats", .data = &rpmh_data },
|
||||||
|
{ .compatible = "qcom,sdm845-rpmh-stats", .data = &rpmh_data_sdm845 },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, qcom_stats_table);
|
MODULE_DEVICE_TABLE(of, qcom_stats_table);
|
||||||
|
|
|
@ -57,11 +57,11 @@ do { \
|
||||||
#define TLV_TYPE_SIZE sizeof(u8)
|
#define TLV_TYPE_SIZE sizeof(u8)
|
||||||
#define OPTIONAL_TLV_TYPE_START 0x10
|
#define OPTIONAL_TLV_TYPE_START 0x10
|
||||||
|
|
||||||
static int qmi_encode(struct qmi_elem_info *ei_array, void *out_buf,
|
static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf,
|
||||||
const void *in_c_struct, u32 out_buf_len,
|
const void *in_c_struct, u32 out_buf_len,
|
||||||
int enc_level);
|
int enc_level);
|
||||||
|
|
||||||
static int qmi_decode(struct qmi_elem_info *ei_array, void *out_c_struct,
|
static int qmi_decode(const struct qmi_elem_info *ei_array, void *out_c_struct,
|
||||||
const void *in_buf, u32 in_buf_len, int dec_level);
|
const void *in_buf, u32 in_buf_len, int dec_level);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -76,10 +76,10 @@ static int qmi_decode(struct qmi_elem_info *ei_array, void *out_c_struct,
|
||||||
*
|
*
|
||||||
* Return: struct info of the next element that can be encoded.
|
* Return: struct info of the next element that can be encoded.
|
||||||
*/
|
*/
|
||||||
static struct qmi_elem_info *skip_to_next_elem(struct qmi_elem_info *ei_array,
|
static const struct qmi_elem_info *
|
||||||
int level)
|
skip_to_next_elem(const struct qmi_elem_info *ei_array, int level)
|
||||||
{
|
{
|
||||||
struct qmi_elem_info *temp_ei = ei_array;
|
const struct qmi_elem_info *temp_ei = ei_array;
|
||||||
u8 tlv_type;
|
u8 tlv_type;
|
||||||
|
|
||||||
if (level > 1) {
|
if (level > 1) {
|
||||||
|
@ -101,11 +101,11 @@ static struct qmi_elem_info *skip_to_next_elem(struct qmi_elem_info *ei_array,
|
||||||
*
|
*
|
||||||
* Return: Expected minimum length of the QMI message or 0 on error.
|
* Return: Expected minimum length of the QMI message or 0 on error.
|
||||||
*/
|
*/
|
||||||
static int qmi_calc_min_msg_len(struct qmi_elem_info *ei_array,
|
static int qmi_calc_min_msg_len(const struct qmi_elem_info *ei_array,
|
||||||
int level)
|
int level)
|
||||||
{
|
{
|
||||||
int min_msg_len = 0;
|
int min_msg_len = 0;
|
||||||
struct qmi_elem_info *temp_ei = ei_array;
|
const struct qmi_elem_info *temp_ei = ei_array;
|
||||||
|
|
||||||
if (!ei_array)
|
if (!ei_array)
|
||||||
return min_msg_len;
|
return min_msg_len;
|
||||||
|
@ -194,13 +194,13 @@ static int qmi_encode_basic_elem(void *buf_dst, const void *buf_src,
|
||||||
* Return: The number of bytes of encoded information on success or negative
|
* Return: The number of bytes of encoded information on success or negative
|
||||||
* errno on error.
|
* errno on error.
|
||||||
*/
|
*/
|
||||||
static int qmi_encode_struct_elem(struct qmi_elem_info *ei_array,
|
static int qmi_encode_struct_elem(const struct qmi_elem_info *ei_array,
|
||||||
void *buf_dst, const void *buf_src,
|
void *buf_dst, const void *buf_src,
|
||||||
u32 elem_len, u32 out_buf_len,
|
u32 elem_len, u32 out_buf_len,
|
||||||
int enc_level)
|
int enc_level)
|
||||||
{
|
{
|
||||||
int i, rc, encoded_bytes = 0;
|
int i, rc, encoded_bytes = 0;
|
||||||
struct qmi_elem_info *temp_ei = ei_array;
|
const struct qmi_elem_info *temp_ei = ei_array;
|
||||||
|
|
||||||
for (i = 0; i < elem_len; i++) {
|
for (i = 0; i < elem_len; i++) {
|
||||||
rc = qmi_encode(temp_ei->ei_array, buf_dst, buf_src,
|
rc = qmi_encode(temp_ei->ei_array, buf_dst, buf_src,
|
||||||
|
@ -233,13 +233,13 @@ static int qmi_encode_struct_elem(struct qmi_elem_info *ei_array,
|
||||||
* Return: The number of bytes of encoded information on success or negative
|
* Return: The number of bytes of encoded information on success or negative
|
||||||
* errno on error.
|
* errno on error.
|
||||||
*/
|
*/
|
||||||
static int qmi_encode_string_elem(struct qmi_elem_info *ei_array,
|
static int qmi_encode_string_elem(const struct qmi_elem_info *ei_array,
|
||||||
void *buf_dst, const void *buf_src,
|
void *buf_dst, const void *buf_src,
|
||||||
u32 out_buf_len, int enc_level)
|
u32 out_buf_len, int enc_level)
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
int encoded_bytes = 0;
|
int encoded_bytes = 0;
|
||||||
struct qmi_elem_info *temp_ei = ei_array;
|
const struct qmi_elem_info *temp_ei = ei_array;
|
||||||
u32 string_len = 0;
|
u32 string_len = 0;
|
||||||
u32 string_len_sz = 0;
|
u32 string_len_sz = 0;
|
||||||
|
|
||||||
|
@ -289,11 +289,11 @@ static int qmi_encode_string_elem(struct qmi_elem_info *ei_array,
|
||||||
* Return: The number of bytes of encoded information on success or negative
|
* Return: The number of bytes of encoded information on success or negative
|
||||||
* errno on error.
|
* errno on error.
|
||||||
*/
|
*/
|
||||||
static int qmi_encode(struct qmi_elem_info *ei_array, void *out_buf,
|
static int qmi_encode(const struct qmi_elem_info *ei_array, void *out_buf,
|
||||||
const void *in_c_struct, u32 out_buf_len,
|
const void *in_c_struct, u32 out_buf_len,
|
||||||
int enc_level)
|
int enc_level)
|
||||||
{
|
{
|
||||||
struct qmi_elem_info *temp_ei = ei_array;
|
const struct qmi_elem_info *temp_ei = ei_array;
|
||||||
u8 opt_flag_value = 0;
|
u8 opt_flag_value = 0;
|
||||||
u32 data_len_value = 0, data_len_sz;
|
u32 data_len_value = 0, data_len_sz;
|
||||||
u8 *buf_dst = (u8 *)out_buf;
|
u8 *buf_dst = (u8 *)out_buf;
|
||||||
|
@ -468,13 +468,13 @@ static int qmi_decode_basic_elem(void *buf_dst, const void *buf_src,
|
||||||
* Return: The total size of the decoded data elements on success, negative
|
* Return: The total size of the decoded data elements on success, negative
|
||||||
* errno on error.
|
* errno on error.
|
||||||
*/
|
*/
|
||||||
static int qmi_decode_struct_elem(struct qmi_elem_info *ei_array,
|
static int qmi_decode_struct_elem(const struct qmi_elem_info *ei_array,
|
||||||
void *buf_dst, const void *buf_src,
|
void *buf_dst, const void *buf_src,
|
||||||
u32 elem_len, u32 tlv_len,
|
u32 elem_len, u32 tlv_len,
|
||||||
int dec_level)
|
int dec_level)
|
||||||
{
|
{
|
||||||
int i, rc, decoded_bytes = 0;
|
int i, rc, decoded_bytes = 0;
|
||||||
struct qmi_elem_info *temp_ei = ei_array;
|
const struct qmi_elem_info *temp_ei = ei_array;
|
||||||
|
|
||||||
for (i = 0; i < elem_len && decoded_bytes < tlv_len; i++) {
|
for (i = 0; i < elem_len && decoded_bytes < tlv_len; i++) {
|
||||||
rc = qmi_decode(temp_ei->ei_array, buf_dst, buf_src,
|
rc = qmi_decode(temp_ei->ei_array, buf_dst, buf_src,
|
||||||
|
@ -514,7 +514,7 @@ static int qmi_decode_struct_elem(struct qmi_elem_info *ei_array,
|
||||||
* Return: The total size of the decoded data elements on success, negative
|
* Return: The total size of the decoded data elements on success, negative
|
||||||
* errno on error.
|
* errno on error.
|
||||||
*/
|
*/
|
||||||
static int qmi_decode_string_elem(struct qmi_elem_info *ei_array,
|
static int qmi_decode_string_elem(const struct qmi_elem_info *ei_array,
|
||||||
void *buf_dst, const void *buf_src,
|
void *buf_dst, const void *buf_src,
|
||||||
u32 tlv_len, int dec_level)
|
u32 tlv_len, int dec_level)
|
||||||
{
|
{
|
||||||
|
@ -522,7 +522,7 @@ static int qmi_decode_string_elem(struct qmi_elem_info *ei_array,
|
||||||
int decoded_bytes = 0;
|
int decoded_bytes = 0;
|
||||||
u32 string_len = 0;
|
u32 string_len = 0;
|
||||||
u32 string_len_sz = 0;
|
u32 string_len_sz = 0;
|
||||||
struct qmi_elem_info *temp_ei = ei_array;
|
const struct qmi_elem_info *temp_ei = ei_array;
|
||||||
|
|
||||||
if (dec_level == 1) {
|
if (dec_level == 1) {
|
||||||
string_len = tlv_len;
|
string_len = tlv_len;
|
||||||
|
@ -564,10 +564,10 @@ static int qmi_decode_string_elem(struct qmi_elem_info *ei_array,
|
||||||
*
|
*
|
||||||
* Return: Pointer to struct info, if found
|
* Return: Pointer to struct info, if found
|
||||||
*/
|
*/
|
||||||
static struct qmi_elem_info *find_ei(struct qmi_elem_info *ei_array,
|
static const struct qmi_elem_info *find_ei(const struct qmi_elem_info *ei_array,
|
||||||
u32 type)
|
u32 type)
|
||||||
{
|
{
|
||||||
struct qmi_elem_info *temp_ei = ei_array;
|
const struct qmi_elem_info *temp_ei = ei_array;
|
||||||
|
|
||||||
while (temp_ei->data_type != QMI_EOTI) {
|
while (temp_ei->data_type != QMI_EOTI) {
|
||||||
if (temp_ei->tlv_type == (u8)type)
|
if (temp_ei->tlv_type == (u8)type)
|
||||||
|
@ -590,11 +590,11 @@ static struct qmi_elem_info *find_ei(struct qmi_elem_info *ei_array,
|
||||||
* Return: The number of bytes of decoded information on success, negative
|
* Return: The number of bytes of decoded information on success, negative
|
||||||
* errno on error.
|
* errno on error.
|
||||||
*/
|
*/
|
||||||
static int qmi_decode(struct qmi_elem_info *ei_array, void *out_c_struct,
|
static int qmi_decode(const struct qmi_elem_info *ei_array, void *out_c_struct,
|
||||||
const void *in_buf, u32 in_buf_len,
|
const void *in_buf, u32 in_buf_len,
|
||||||
int dec_level)
|
int dec_level)
|
||||||
{
|
{
|
||||||
struct qmi_elem_info *temp_ei = ei_array;
|
const struct qmi_elem_info *temp_ei = ei_array;
|
||||||
u8 opt_flag_value = 1;
|
u8 opt_flag_value = 1;
|
||||||
u32 data_len_value = 0, data_len_sz = 0;
|
u32 data_len_value = 0, data_len_sz = 0;
|
||||||
u8 *buf_dst = out_c_struct;
|
u8 *buf_dst = out_c_struct;
|
||||||
|
@ -713,7 +713,7 @@ static int qmi_decode(struct qmi_elem_info *ei_array, void *out_c_struct,
|
||||||
* Return: Buffer with encoded message, or negative ERR_PTR() on error
|
* Return: Buffer with encoded message, or negative ERR_PTR() on error
|
||||||
*/
|
*/
|
||||||
void *qmi_encode_message(int type, unsigned int msg_id, size_t *len,
|
void *qmi_encode_message(int type, unsigned int msg_id, size_t *len,
|
||||||
unsigned int txn_id, struct qmi_elem_info *ei,
|
unsigned int txn_id, const struct qmi_elem_info *ei,
|
||||||
const void *c_struct)
|
const void *c_struct)
|
||||||
{
|
{
|
||||||
struct qmi_header *hdr;
|
struct qmi_header *hdr;
|
||||||
|
@ -767,7 +767,7 @@ EXPORT_SYMBOL(qmi_encode_message);
|
||||||
* errno on error.
|
* errno on error.
|
||||||
*/
|
*/
|
||||||
int qmi_decode_message(const void *buf, size_t len,
|
int qmi_decode_message(const void *buf, size_t len,
|
||||||
struct qmi_elem_info *ei, void *c_struct)
|
const struct qmi_elem_info *ei, void *c_struct)
|
||||||
{
|
{
|
||||||
if (!ei)
|
if (!ei)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -781,7 +781,7 @@ int qmi_decode_message(const void *buf, size_t len,
|
||||||
EXPORT_SYMBOL(qmi_decode_message);
|
EXPORT_SYMBOL(qmi_decode_message);
|
||||||
|
|
||||||
/* Common header in all QMI responses */
|
/* Common header in all QMI responses */
|
||||||
struct qmi_elem_info qmi_response_type_v01_ei[] = {
|
const struct qmi_elem_info qmi_response_type_v01_ei[] = {
|
||||||
{
|
{
|
||||||
.data_type = QMI_SIGNED_2_BYTE_ENUM,
|
.data_type = QMI_SIGNED_2_BYTE_ENUM,
|
||||||
.elem_len = 1,
|
.elem_len = 1,
|
||||||
|
|
|
@ -305,7 +305,7 @@ EXPORT_SYMBOL(qmi_add_server);
|
||||||
* Return: Transaction id on success, negative errno on failure.
|
* Return: Transaction id on success, negative errno on failure.
|
||||||
*/
|
*/
|
||||||
int qmi_txn_init(struct qmi_handle *qmi, struct qmi_txn *txn,
|
int qmi_txn_init(struct qmi_handle *qmi, struct qmi_txn *txn,
|
||||||
struct qmi_elem_info *ei, void *c_struct)
|
const struct qmi_elem_info *ei, void *c_struct)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
|
@ -736,7 +736,8 @@ EXPORT_SYMBOL(qmi_handle_release);
|
||||||
static ssize_t qmi_send_message(struct qmi_handle *qmi,
|
static ssize_t qmi_send_message(struct qmi_handle *qmi,
|
||||||
struct sockaddr_qrtr *sq, struct qmi_txn *txn,
|
struct sockaddr_qrtr *sq, struct qmi_txn *txn,
|
||||||
int type, int msg_id, size_t len,
|
int type, int msg_id, size_t len,
|
||||||
struct qmi_elem_info *ei, const void *c_struct)
|
const struct qmi_elem_info *ei,
|
||||||
|
const void *c_struct)
|
||||||
{
|
{
|
||||||
struct msghdr msghdr = {};
|
struct msghdr msghdr = {};
|
||||||
struct kvec iv;
|
struct kvec iv;
|
||||||
|
@ -787,7 +788,7 @@ static ssize_t qmi_send_message(struct qmi_handle *qmi,
|
||||||
*/
|
*/
|
||||||
ssize_t qmi_send_request(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
|
ssize_t qmi_send_request(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
|
||||||
struct qmi_txn *txn, int msg_id, size_t len,
|
struct qmi_txn *txn, int msg_id, size_t len,
|
||||||
struct qmi_elem_info *ei, const void *c_struct)
|
const struct qmi_elem_info *ei, const void *c_struct)
|
||||||
{
|
{
|
||||||
return qmi_send_message(qmi, sq, txn, QMI_REQUEST, msg_id, len, ei,
|
return qmi_send_message(qmi, sq, txn, QMI_REQUEST, msg_id, len, ei,
|
||||||
c_struct);
|
c_struct);
|
||||||
|
@ -808,7 +809,7 @@ EXPORT_SYMBOL(qmi_send_request);
|
||||||
*/
|
*/
|
||||||
ssize_t qmi_send_response(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
|
ssize_t qmi_send_response(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
|
||||||
struct qmi_txn *txn, int msg_id, size_t len,
|
struct qmi_txn *txn, int msg_id, size_t len,
|
||||||
struct qmi_elem_info *ei, const void *c_struct)
|
const struct qmi_elem_info *ei, const void *c_struct)
|
||||||
{
|
{
|
||||||
return qmi_send_message(qmi, sq, txn, QMI_RESPONSE, msg_id, len, ei,
|
return qmi_send_message(qmi, sq, txn, QMI_RESPONSE, msg_id, len, ei,
|
||||||
c_struct);
|
c_struct);
|
||||||
|
@ -827,7 +828,8 @@ EXPORT_SYMBOL(qmi_send_response);
|
||||||
* Return: 0 on success, negative errno on failure.
|
* Return: 0 on success, negative errno on failure.
|
||||||
*/
|
*/
|
||||||
ssize_t qmi_send_indication(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
|
ssize_t qmi_send_indication(struct qmi_handle *qmi, struct sockaddr_qrtr *sq,
|
||||||
int msg_id, size_t len, struct qmi_elem_info *ei,
|
int msg_id, size_t len,
|
||||||
|
const struct qmi_elem_info *ei,
|
||||||
const void *c_struct)
|
const void *c_struct)
|
||||||
{
|
{
|
||||||
struct qmi_txn txn;
|
struct qmi_txn txn;
|
||||||
|
|
|
@ -29,6 +29,7 @@
|
||||||
#define RPMPD_RWLM 0x6d6c7772
|
#define RPMPD_RWLM 0x6d6c7772
|
||||||
#define RPMPD_RWSC 0x63737772
|
#define RPMPD_RWSC 0x63737772
|
||||||
#define RPMPD_RWSM 0x6d737772
|
#define RPMPD_RWSM 0x6d737772
|
||||||
|
#define RPMPD_RWGX 0x78677772
|
||||||
|
|
||||||
/* Operation Keys */
|
/* Operation Keys */
|
||||||
#define KEY_CORNER 0x6e726f63 /* corn */
|
#define KEY_CORNER 0x6e726f63 /* corn */
|
||||||
|
@ -433,6 +434,26 @@ static const struct rpmpd_desc sm6125_desc = {
|
||||||
.max_state = RPM_SMD_LEVEL_BINNING,
|
.max_state = RPM_SMD_LEVEL_BINNING,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
DEFINE_RPMPD_PAIR(sm6375, vddgx, vddgx_ao, RWGX, LEVEL, 0);
|
||||||
|
static struct rpmpd *sm6375_rpmpds[] = {
|
||||||
|
[SM6375_VDDCX] = &sm6125_vddcx,
|
||||||
|
[SM6375_VDDCX_AO] = &sm6125_vddcx_ao,
|
||||||
|
[SM6375_VDDCX_VFL] = &sm6125_vddcx_vfl,
|
||||||
|
[SM6375_VDDMX] = &sm6125_vddmx,
|
||||||
|
[SM6375_VDDMX_AO] = &sm6125_vddmx_ao,
|
||||||
|
[SM6375_VDDMX_VFL] = &sm6125_vddmx_vfl,
|
||||||
|
[SM6375_VDDGX] = &sm6375_vddgx,
|
||||||
|
[SM6375_VDDGX_AO] = &sm6375_vddgx_ao,
|
||||||
|
[SM6375_VDD_LPI_CX] = &sm6115_vdd_lpi_cx,
|
||||||
|
[SM6375_VDD_LPI_MX] = &sm6115_vdd_lpi_mx,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct rpmpd_desc sm6375_desc = {
|
||||||
|
.rpmpds = sm6375_rpmpds,
|
||||||
|
.num_pds = ARRAY_SIZE(sm6375_rpmpds),
|
||||||
|
.max_state = RPM_SMD_LEVEL_TURBO_NO_CPR,
|
||||||
|
};
|
||||||
|
|
||||||
static struct rpmpd *qcm2290_rpmpds[] = {
|
static struct rpmpd *qcm2290_rpmpds[] = {
|
||||||
[QCM2290_VDDCX] = &sm6115_vddcx,
|
[QCM2290_VDDCX] = &sm6115_vddcx,
|
||||||
[QCM2290_VDDCX_AO] = &sm6115_vddcx_ao,
|
[QCM2290_VDDCX_AO] = &sm6115_vddcx_ao,
|
||||||
|
@ -466,6 +487,7 @@ static const struct of_device_id rpmpd_match_table[] = {
|
||||||
{ .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc },
|
{ .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc },
|
||||||
{ .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc },
|
{ .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc },
|
||||||
{ .compatible = "qcom,sm6125-rpmpd", .data = &sm6125_desc },
|
{ .compatible = "qcom,sm6125-rpmpd", .data = &sm6125_desc },
|
||||||
|
{ .compatible = "qcom,sm6375-rpmpd", .data = &sm6375_desc },
|
||||||
{ }
|
{ }
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, rpmpd_match_table);
|
MODULE_DEVICE_TABLE(of, rpmpd_match_table);
|
||||||
|
|
|
@ -136,6 +136,7 @@ static void qcom_smem_state_release(struct kref *ref)
|
||||||
struct qcom_smem_state *state = container_of(ref, struct qcom_smem_state, refcount);
|
struct qcom_smem_state *state = container_of(ref, struct qcom_smem_state, refcount);
|
||||||
|
|
||||||
list_del(&state->list);
|
list_del(&state->list);
|
||||||
|
of_node_put(state->of_node);
|
||||||
kfree(state);
|
kfree(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,7 +206,7 @@ struct qcom_smem_state *qcom_smem_state_register(struct device_node *of_node,
|
||||||
|
|
||||||
kref_init(&state->refcount);
|
kref_init(&state->refcount);
|
||||||
|
|
||||||
state->of_node = of_node;
|
state->of_node = of_node_get(of_node);
|
||||||
state->ops = *ops;
|
state->ops = *ops;
|
||||||
state->priv = priv;
|
state->priv = priv;
|
||||||
|
|
||||||
|
|
|
@ -526,7 +526,7 @@ static int qcom_smsm_probe(struct platform_device *pdev)
|
||||||
for (id = 0; id < smsm->num_hosts; id++) {
|
for (id = 0; id < smsm->num_hosts; id++) {
|
||||||
ret = smsm_parse_ipc(smsm, id);
|
ret = smsm_parse_ipc(smsm, id);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
goto out_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Acquire the main SMSM state vector */
|
/* Acquire the main SMSM state vector */
|
||||||
|
@ -534,13 +534,14 @@ static int qcom_smsm_probe(struct platform_device *pdev)
|
||||||
smsm->num_entries * sizeof(u32));
|
smsm->num_entries * sizeof(u32));
|
||||||
if (ret < 0 && ret != -EEXIST) {
|
if (ret < 0 && ret != -EEXIST) {
|
||||||
dev_err(&pdev->dev, "unable to allocate shared state entry\n");
|
dev_err(&pdev->dev, "unable to allocate shared state entry\n");
|
||||||
return ret;
|
goto out_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
states = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_SHARED_STATE, NULL);
|
states = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_SHARED_STATE, NULL);
|
||||||
if (IS_ERR(states)) {
|
if (IS_ERR(states)) {
|
||||||
dev_err(&pdev->dev, "Unable to acquire shared state entry\n");
|
dev_err(&pdev->dev, "Unable to acquire shared state entry\n");
|
||||||
return PTR_ERR(states);
|
ret = PTR_ERR(states);
|
||||||
|
goto out_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Acquire the list of interrupt mask vectors */
|
/* Acquire the list of interrupt mask vectors */
|
||||||
|
@ -548,13 +549,14 @@ static int qcom_smsm_probe(struct platform_device *pdev)
|
||||||
ret = qcom_smem_alloc(QCOM_SMEM_HOST_ANY, SMEM_SMSM_CPU_INTR_MASK, size);
|
ret = qcom_smem_alloc(QCOM_SMEM_HOST_ANY, SMEM_SMSM_CPU_INTR_MASK, size);
|
||||||
if (ret < 0 && ret != -EEXIST) {
|
if (ret < 0 && ret != -EEXIST) {
|
||||||
dev_err(&pdev->dev, "unable to allocate smsm interrupt mask\n");
|
dev_err(&pdev->dev, "unable to allocate smsm interrupt mask\n");
|
||||||
return ret;
|
goto out_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
intr_mask = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_CPU_INTR_MASK, NULL);
|
intr_mask = qcom_smem_get(QCOM_SMEM_HOST_ANY, SMEM_SMSM_CPU_INTR_MASK, NULL);
|
||||||
if (IS_ERR(intr_mask)) {
|
if (IS_ERR(intr_mask)) {
|
||||||
dev_err(&pdev->dev, "unable to acquire shared memory interrupt mask\n");
|
dev_err(&pdev->dev, "unable to acquire shared memory interrupt mask\n");
|
||||||
return PTR_ERR(intr_mask);
|
ret = PTR_ERR(intr_mask);
|
||||||
|
goto out_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup the reference to the local state bits */
|
/* Setup the reference to the local state bits */
|
||||||
|
@ -565,7 +567,8 @@ static int qcom_smsm_probe(struct platform_device *pdev)
|
||||||
smsm->state = qcom_smem_state_register(local_node, &smsm_state_ops, smsm);
|
smsm->state = qcom_smem_state_register(local_node, &smsm_state_ops, smsm);
|
||||||
if (IS_ERR(smsm->state)) {
|
if (IS_ERR(smsm->state)) {
|
||||||
dev_err(smsm->dev, "failed to register qcom_smem_state\n");
|
dev_err(smsm->dev, "failed to register qcom_smem_state\n");
|
||||||
return PTR_ERR(smsm->state);
|
ret = PTR_ERR(smsm->state);
|
||||||
|
goto out_put;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Register handlers for remote processor entries of interest. */
|
/* Register handlers for remote processor entries of interest. */
|
||||||
|
@ -595,16 +598,19 @@ static int qcom_smsm_probe(struct platform_device *pdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
platform_set_drvdata(pdev, smsm);
|
platform_set_drvdata(pdev, smsm);
|
||||||
|
of_node_put(local_node);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
unwind_interfaces:
|
unwind_interfaces:
|
||||||
|
of_node_put(node);
|
||||||
for (id = 0; id < smsm->num_entries; id++)
|
for (id = 0; id < smsm->num_entries; id++)
|
||||||
if (smsm->entries[id].domain)
|
if (smsm->entries[id].domain)
|
||||||
irq_domain_remove(smsm->entries[id].domain);
|
irq_domain_remove(smsm->entries[id].domain);
|
||||||
|
|
||||||
qcom_smem_state_unregister(smsm->state);
|
qcom_smem_state_unregister(smsm->state);
|
||||||
|
out_put:
|
||||||
|
of_node_put(local_node);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -104,6 +104,7 @@ static const char *const pmic_models[] = {
|
||||||
[36] = "PM8009",
|
[36] = "PM8009",
|
||||||
[38] = "PM8150C",
|
[38] = "PM8150C",
|
||||||
[41] = "SMB2351",
|
[41] = "SMB2351",
|
||||||
|
[45] = "PM6125",
|
||||||
[47] = "PMK8350",
|
[47] = "PMK8350",
|
||||||
[48] = "PM8350",
|
[48] = "PM8350",
|
||||||
[49] = "PM8350C",
|
[49] = "PM8350C",
|
||||||
|
@ -334,6 +335,7 @@ static const struct soc_id soc_id[] = {
|
||||||
{ 482, "SM8450" },
|
{ 482, "SM8450" },
|
||||||
{ 487, "SC7280" },
|
{ 487, "SC7280" },
|
||||||
{ 495, "SC7180P" },
|
{ 495, "SC7180P" },
|
||||||
|
{ 507, "SM6375" },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *socinfo_machine(struct device *dev, unsigned int id)
|
static const char *socinfo_machine(struct device *dev, unsigned int id)
|
||||||
|
|
|
@ -44,6 +44,7 @@ config ARCH_RZG2L
|
||||||
bool
|
bool
|
||||||
select PM
|
select PM
|
||||||
select PM_GENERIC_DOMAINS
|
select PM_GENERIC_DOMAINS
|
||||||
|
select RENESAS_RZG2L_IRQC
|
||||||
|
|
||||||
config ARCH_RZN1
|
config ARCH_RZN1
|
||||||
bool
|
bool
|
||||||
|
@ -332,6 +333,16 @@ config ARCH_R9A09G011
|
||||||
|
|
||||||
endif # ARM64
|
endif # ARM64
|
||||||
|
|
||||||
|
if RISCV
|
||||||
|
|
||||||
|
config ARCH_R9A07G043
|
||||||
|
bool "RISC-V Platform support for RZ/Five"
|
||||||
|
select ARCH_RZG2L
|
||||||
|
help
|
||||||
|
This enables support for the Renesas RZ/Five SoC.
|
||||||
|
|
||||||
|
endif # RISCV
|
||||||
|
|
||||||
config RST_RCAR
|
config RST_RCAR
|
||||||
bool "Reset Controller support for R-Car" if COMPILE_TEST
|
bool "Reset Controller support for R-Car" if COMPILE_TEST
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,10 @@ static const struct renesas_family fam_rza2 __initconst __maybe_unused = {
|
||||||
.name = "RZ/A2",
|
.name = "RZ/A2",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct renesas_family fam_rzfive __initconst __maybe_unused = {
|
||||||
|
.name = "RZ/Five",
|
||||||
|
};
|
||||||
|
|
||||||
static const struct renesas_family fam_rzg1 __initconst __maybe_unused = {
|
static const struct renesas_family fam_rzg1 __initconst __maybe_unused = {
|
||||||
.name = "RZ/G1",
|
.name = "RZ/G1",
|
||||||
.reg = 0xff000044, /* PRR (Product Register) */
|
.reg = 0xff000044, /* PRR (Product Register) */
|
||||||
|
@ -102,6 +106,11 @@ static const struct renesas_soc soc_rmobile_a1 __initconst __maybe_unused = {
|
||||||
.id = 0x40,
|
.id = 0x40,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct renesas_soc soc_rz_five __initconst __maybe_unused = {
|
||||||
|
.family = &fam_rzfive,
|
||||||
|
.id = 0x847c447,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct renesas_soc soc_rz_g1h __initconst __maybe_unused = {
|
static const struct renesas_soc soc_rz_g1h __initconst __maybe_unused = {
|
||||||
.family = &fam_rzg1,
|
.family = &fam_rzg1,
|
||||||
.id = 0x45,
|
.id = 0x45,
|
||||||
|
@ -320,6 +329,7 @@ static const struct of_device_id renesas_socs[] __initconst = {
|
||||||
{ .compatible = "renesas,r8a779m0", .data = &soc_rcar_h3 },
|
{ .compatible = "renesas,r8a779m0", .data = &soc_rcar_h3 },
|
||||||
{ .compatible = "renesas,r8a779m1", .data = &soc_rcar_h3 },
|
{ .compatible = "renesas,r8a779m1", .data = &soc_rcar_h3 },
|
||||||
{ .compatible = "renesas,r8a779m8", .data = &soc_rcar_h3 },
|
{ .compatible = "renesas,r8a779m8", .data = &soc_rcar_h3 },
|
||||||
|
{ .compatible = "renesas,r8a779mb", .data = &soc_rcar_h3 },
|
||||||
#endif
|
#endif
|
||||||
#ifdef CONFIG_ARCH_R8A77960
|
#ifdef CONFIG_ARCH_R8A77960
|
||||||
{ .compatible = "renesas,r8a7796", .data = &soc_rcar_m3_w },
|
{ .compatible = "renesas,r8a7796", .data = &soc_rcar_m3_w },
|
||||||
|
@ -358,8 +368,12 @@ static const struct of_device_id renesas_socs[] __initconst = {
|
||||||
{ .compatible = "renesas,r8a779g0", .data = &soc_rcar_v4h },
|
{ .compatible = "renesas,r8a779g0", .data = &soc_rcar_v4h },
|
||||||
#endif
|
#endif
|
||||||
#if defined(CONFIG_ARCH_R9A07G043)
|
#if defined(CONFIG_ARCH_R9A07G043)
|
||||||
|
#ifdef CONFIG_RISCV
|
||||||
|
{ .compatible = "renesas,r9a07g043", .data = &soc_rz_five },
|
||||||
|
#else
|
||||||
{ .compatible = "renesas,r9a07g043", .data = &soc_rz_g2ul },
|
{ .compatible = "renesas,r9a07g043", .data = &soc_rz_g2ul },
|
||||||
#endif
|
#endif
|
||||||
|
#endif
|
||||||
#if defined(CONFIG_ARCH_R9A07G044)
|
#if defined(CONFIG_ARCH_R9A07G044)
|
||||||
{ .compatible = "renesas,r9a07g044", .data = &soc_rz_g2l },
|
{ .compatible = "renesas,r9a07g044", .data = &soc_rz_g2l },
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -491,6 +491,22 @@ static const struct rockchip_iodomain_soc_data soc_data_rv1108_pmu = {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct rockchip_iodomain_soc_data soc_data_rv1126_pmu = {
|
||||||
|
.grf_offset = 0x140,
|
||||||
|
.supply_names = {
|
||||||
|
NULL,
|
||||||
|
"vccio1",
|
||||||
|
"vccio2",
|
||||||
|
"vccio3",
|
||||||
|
"vccio4",
|
||||||
|
"vccio5",
|
||||||
|
"vccio6",
|
||||||
|
"vccio7",
|
||||||
|
"pmuio0",
|
||||||
|
"pmuio1",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
static const struct of_device_id rockchip_iodomain_match[] = {
|
static const struct of_device_id rockchip_iodomain_match[] = {
|
||||||
{
|
{
|
||||||
.compatible = "rockchip,px30-io-voltage-domain",
|
.compatible = "rockchip,px30-io-voltage-domain",
|
||||||
|
@ -544,6 +560,10 @@ static const struct of_device_id rockchip_iodomain_match[] = {
|
||||||
.compatible = "rockchip,rv1108-pmu-io-voltage-domain",
|
.compatible = "rockchip,rv1108-pmu-io-voltage-domain",
|
||||||
.data = &soc_data_rv1108_pmu
|
.data = &soc_data_rv1108_pmu
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.compatible = "rockchip,rv1126-pmu-io-voltage-domain",
|
||||||
|
.data = &soc_data_rv1126_pmu
|
||||||
|
},
|
||||||
{ /* sentinel */ },
|
{ /* sentinel */ },
|
||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, rockchip_iodomain_match);
|
MODULE_DEVICE_TABLE(of, rockchip_iodomain_match);
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <linux/mfd/syscon.h>
|
#include <linux/mfd/syscon.h>
|
||||||
#include <soc/rockchip/pm_domains.h>
|
#include <soc/rockchip/pm_domains.h>
|
||||||
#include <dt-bindings/power/px30-power.h>
|
#include <dt-bindings/power/px30-power.h>
|
||||||
|
#include <dt-bindings/power/rockchip,rv1126-power.h>
|
||||||
#include <dt-bindings/power/rk3036-power.h>
|
#include <dt-bindings/power/rk3036-power.h>
|
||||||
#include <dt-bindings/power/rk3066-power.h>
|
#include <dt-bindings/power/rk3066-power.h>
|
||||||
#include <dt-bindings/power/rk3128-power.h>
|
#include <dt-bindings/power/rk3128-power.h>
|
||||||
|
@ -30,6 +31,7 @@
|
||||||
#include <dt-bindings/power/rk3368-power.h>
|
#include <dt-bindings/power/rk3368-power.h>
|
||||||
#include <dt-bindings/power/rk3399-power.h>
|
#include <dt-bindings/power/rk3399-power.h>
|
||||||
#include <dt-bindings/power/rk3568-power.h>
|
#include <dt-bindings/power/rk3568-power.h>
|
||||||
|
#include <dt-bindings/power/rk3588-power.h>
|
||||||
|
|
||||||
struct rockchip_domain_info {
|
struct rockchip_domain_info {
|
||||||
const char *name;
|
const char *name;
|
||||||
|
@ -41,6 +43,9 @@ struct rockchip_domain_info {
|
||||||
bool active_wakeup;
|
bool active_wakeup;
|
||||||
int pwr_w_mask;
|
int pwr_w_mask;
|
||||||
int req_w_mask;
|
int req_w_mask;
|
||||||
|
int repair_status_mask;
|
||||||
|
u32 pwr_offset;
|
||||||
|
u32 req_offset;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rockchip_pmu_info {
|
struct rockchip_pmu_info {
|
||||||
|
@ -49,6 +54,7 @@ struct rockchip_pmu_info {
|
||||||
u32 req_offset;
|
u32 req_offset;
|
||||||
u32 idle_offset;
|
u32 idle_offset;
|
||||||
u32 ack_offset;
|
u32 ack_offset;
|
||||||
|
u32 repair_status_offset;
|
||||||
|
|
||||||
u32 core_pwrcnt_offset;
|
u32 core_pwrcnt_offset;
|
||||||
u32 gpu_pwrcnt_offset;
|
u32 gpu_pwrcnt_offset;
|
||||||
|
@ -113,6 +119,22 @@ struct rockchip_pmu {
|
||||||
.active_wakeup = wakeup, \
|
.active_wakeup = wakeup, \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define DOMAIN_M_O_R(_name, p_offset, pwr, status, r_status, r_offset, req, idle, ack, wakeup) \
|
||||||
|
{ \
|
||||||
|
.name = _name, \
|
||||||
|
.pwr_offset = p_offset, \
|
||||||
|
.pwr_w_mask = (pwr) << 16, \
|
||||||
|
.pwr_mask = (pwr), \
|
||||||
|
.status_mask = (status), \
|
||||||
|
.repair_status_mask = (r_status), \
|
||||||
|
.req_offset = r_offset, \
|
||||||
|
.req_w_mask = (req) << 16, \
|
||||||
|
.req_mask = (req), \
|
||||||
|
.idle_mask = (idle), \
|
||||||
|
.ack_mask = (ack), \
|
||||||
|
.active_wakeup = wakeup, \
|
||||||
|
}
|
||||||
|
|
||||||
#define DOMAIN_RK3036(_name, req, ack, idle, wakeup) \
|
#define DOMAIN_RK3036(_name, req, ack, idle, wakeup) \
|
||||||
{ \
|
{ \
|
||||||
.name = _name, \
|
.name = _name, \
|
||||||
|
@ -126,6 +148,9 @@ struct rockchip_pmu {
|
||||||
#define DOMAIN_PX30(name, pwr, status, req, wakeup) \
|
#define DOMAIN_PX30(name, pwr, status, req, wakeup) \
|
||||||
DOMAIN_M(name, pwr, status, req, (req) << 16, req, wakeup)
|
DOMAIN_M(name, pwr, status, req, (req) << 16, req, wakeup)
|
||||||
|
|
||||||
|
#define DOMAIN_RV1126(name, pwr, req, idle, wakeup) \
|
||||||
|
DOMAIN_M(name, pwr, pwr, req, idle, idle, wakeup)
|
||||||
|
|
||||||
#define DOMAIN_RK3288(name, pwr, status, req, wakeup) \
|
#define DOMAIN_RK3288(name, pwr, status, req, wakeup) \
|
||||||
DOMAIN(name, pwr, status, req, req, (req) << 16, wakeup)
|
DOMAIN(name, pwr, status, req, req, (req) << 16, wakeup)
|
||||||
|
|
||||||
|
@ -244,6 +269,9 @@ void rockchip_pmu_unblock(void)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(rockchip_pmu_unblock);
|
EXPORT_SYMBOL_GPL(rockchip_pmu_unblock);
|
||||||
|
|
||||||
|
#define DOMAIN_RK3588(name, p_offset, pwr, status, r_status, r_offset, req, idle, wakeup) \
|
||||||
|
DOMAIN_M_O_R(name, p_offset, pwr, status, r_status, r_offset, req, idle, idle, wakeup)
|
||||||
|
|
||||||
static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
|
static bool rockchip_pmu_domain_is_idle(struct rockchip_pm_domain *pd)
|
||||||
{
|
{
|
||||||
struct rockchip_pmu *pmu = pd->pmu;
|
struct rockchip_pmu *pmu = pd->pmu;
|
||||||
|
@ -268,6 +296,7 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
|
||||||
const struct rockchip_domain_info *pd_info = pd->info;
|
const struct rockchip_domain_info *pd_info = pd->info;
|
||||||
struct generic_pm_domain *genpd = &pd->genpd;
|
struct generic_pm_domain *genpd = &pd->genpd;
|
||||||
struct rockchip_pmu *pmu = pd->pmu;
|
struct rockchip_pmu *pmu = pd->pmu;
|
||||||
|
u32 pd_req_offset = pd_info->req_offset;
|
||||||
unsigned int target_ack;
|
unsigned int target_ack;
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
bool is_idle;
|
bool is_idle;
|
||||||
|
@ -276,11 +305,11 @@ static int rockchip_pmu_set_idle_request(struct rockchip_pm_domain *pd,
|
||||||
if (pd_info->req_mask == 0)
|
if (pd_info->req_mask == 0)
|
||||||
return 0;
|
return 0;
|
||||||
else if (pd_info->req_w_mask)
|
else if (pd_info->req_w_mask)
|
||||||
regmap_write(pmu->regmap, pmu->info->req_offset,
|
regmap_write(pmu->regmap, pmu->info->req_offset + pd_req_offset,
|
||||||
idle ? (pd_info->req_mask | pd_info->req_w_mask) :
|
idle ? (pd_info->req_mask | pd_info->req_w_mask) :
|
||||||
pd_info->req_w_mask);
|
pd_info->req_w_mask);
|
||||||
else
|
else
|
||||||
regmap_update_bits(pmu->regmap, pmu->info->req_offset,
|
regmap_update_bits(pmu->regmap, pmu->info->req_offset + pd_req_offset,
|
||||||
pd_info->req_mask, idle ? -1U : 0);
|
pd_info->req_mask, idle ? -1U : 0);
|
||||||
|
|
||||||
wmb();
|
wmb();
|
||||||
|
@ -363,6 +392,12 @@ static bool rockchip_pmu_domain_is_on(struct rockchip_pm_domain *pd)
|
||||||
struct rockchip_pmu *pmu = pd->pmu;
|
struct rockchip_pmu *pmu = pd->pmu;
|
||||||
unsigned int val;
|
unsigned int val;
|
||||||
|
|
||||||
|
if (pd->info->repair_status_mask) {
|
||||||
|
regmap_read(pmu->regmap, pmu->info->repair_status_offset, &val);
|
||||||
|
/* 1'b1: power on, 1'b0: power off */
|
||||||
|
return val & pd->info->repair_status_mask;
|
||||||
|
}
|
||||||
|
|
||||||
/* check idle status for idle-only domains */
|
/* check idle status for idle-only domains */
|
||||||
if (pd->info->status_mask == 0)
|
if (pd->info->status_mask == 0)
|
||||||
return !rockchip_pmu_domain_is_idle(pd);
|
return !rockchip_pmu_domain_is_idle(pd);
|
||||||
|
@ -378,16 +413,17 @@ static void rockchip_do_pmu_set_power_domain(struct rockchip_pm_domain *pd,
|
||||||
{
|
{
|
||||||
struct rockchip_pmu *pmu = pd->pmu;
|
struct rockchip_pmu *pmu = pd->pmu;
|
||||||
struct generic_pm_domain *genpd = &pd->genpd;
|
struct generic_pm_domain *genpd = &pd->genpd;
|
||||||
|
u32 pd_pwr_offset = pd->info->pwr_offset;
|
||||||
bool is_on;
|
bool is_on;
|
||||||
|
|
||||||
if (pd->info->pwr_mask == 0)
|
if (pd->info->pwr_mask == 0)
|
||||||
return;
|
return;
|
||||||
else if (pd->info->pwr_w_mask)
|
else if (pd->info->pwr_w_mask)
|
||||||
regmap_write(pmu->regmap, pmu->info->pwr_offset,
|
regmap_write(pmu->regmap, pmu->info->pwr_offset + pd_pwr_offset,
|
||||||
on ? pd->info->pwr_w_mask :
|
on ? pd->info->pwr_w_mask :
|
||||||
(pd->info->pwr_mask | pd->info->pwr_w_mask));
|
(pd->info->pwr_mask | pd->info->pwr_w_mask));
|
||||||
else
|
else
|
||||||
regmap_update_bits(pmu->regmap, pmu->info->pwr_offset,
|
regmap_update_bits(pmu->regmap, pmu->info->pwr_offset + pd_pwr_offset,
|
||||||
pd->info->pwr_mask, on ? 0 : -1U);
|
pd->info->pwr_mask, on ? 0 : -1U);
|
||||||
|
|
||||||
wmb();
|
wmb();
|
||||||
|
@ -514,6 +550,9 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
|
||||||
node, id);
|
node, id);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
/* RK3588 has domains with two parents (RKVDEC0/RKVDEC1) */
|
||||||
|
if (pmu->genpd_data.domains[id])
|
||||||
|
return 0;
|
||||||
|
|
||||||
pd_info = &pmu->info->domain_info[id];
|
pd_info = &pmu->info->domain_info[id];
|
||||||
if (!pd_info) {
|
if (!pd_info) {
|
||||||
|
@ -595,14 +634,6 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
error = rockchip_pd_power(pd, true);
|
|
||||||
if (error) {
|
|
||||||
dev_err(pmu->dev,
|
|
||||||
"failed to power on domain '%pOFn': %d\n",
|
|
||||||
node, error);
|
|
||||||
goto err_unprepare_clocks;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pd->info->name)
|
if (pd->info->name)
|
||||||
pd->genpd.name = pd->info->name;
|
pd->genpd.name = pd->info->name;
|
||||||
else
|
else
|
||||||
|
@ -614,7 +645,7 @@ static int rockchip_pm_add_one_domain(struct rockchip_pmu *pmu,
|
||||||
pd->genpd.flags = GENPD_FLAG_PM_CLK;
|
pd->genpd.flags = GENPD_FLAG_PM_CLK;
|
||||||
if (pd_info->active_wakeup)
|
if (pd_info->active_wakeup)
|
||||||
pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
|
pd->genpd.flags |= GENPD_FLAG_ACTIVE_WAKEUP;
|
||||||
pm_genpd_init(&pd->genpd, NULL, false);
|
pm_genpd_init(&pd->genpd, NULL, !rockchip_pmu_domain_is_on(pd));
|
||||||
|
|
||||||
pmu->genpd_data.domains[id] = &pd->genpd;
|
pmu->genpd_data.domains[id] = &pd->genpd;
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -855,6 +886,16 @@ static const struct rockchip_domain_info px30_pm_domains[] = {
|
||||||
[PX30_PD_GPU] = DOMAIN_PX30("gpu", BIT(15), BIT(15), BIT(2), false),
|
[PX30_PD_GPU] = DOMAIN_PX30("gpu", BIT(15), BIT(15), BIT(2), false),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct rockchip_domain_info rv1126_pm_domains[] = {
|
||||||
|
[RV1126_PD_VEPU] = DOMAIN_RV1126("vepu", BIT(2), BIT(9), BIT(9), false),
|
||||||
|
[RV1126_PD_VI] = DOMAIN_RV1126("vi", BIT(4), BIT(6), BIT(6), false),
|
||||||
|
[RV1126_PD_ISPP] = DOMAIN_RV1126("ispp", BIT(1), BIT(8), BIT(8), false),
|
||||||
|
[RV1126_PD_VDPU] = DOMAIN_RV1126("vdpu", BIT(3), BIT(10), BIT(10), false),
|
||||||
|
[RV1126_PD_NVM] = DOMAIN_RV1126("nvm", BIT(7), BIT(11), BIT(11), false),
|
||||||
|
[RV1126_PD_SDIO] = DOMAIN_RV1126("sdio", BIT(8), BIT(13), BIT(13), false),
|
||||||
|
[RV1126_PD_USB] = DOMAIN_RV1126("usb", BIT(9), BIT(15), BIT(15), false),
|
||||||
|
};
|
||||||
|
|
||||||
static const struct rockchip_domain_info rk3036_pm_domains[] = {
|
static const struct rockchip_domain_info rk3036_pm_domains[] = {
|
||||||
[RK3036_PD_MSCH] = DOMAIN_RK3036("msch", BIT(14), BIT(23), BIT(30), true),
|
[RK3036_PD_MSCH] = DOMAIN_RK3036("msch", BIT(14), BIT(23), BIT(30), true),
|
||||||
[RK3036_PD_CORE] = DOMAIN_RK3036("core", BIT(13), BIT(17), BIT(24), false),
|
[RK3036_PD_CORE] = DOMAIN_RK3036("core", BIT(13), BIT(17), BIT(24), false),
|
||||||
|
@ -982,6 +1023,38 @@ static const struct rockchip_domain_info rk3568_pm_domains[] = {
|
||||||
[RK3568_PD_PIPE] = DOMAIN_RK3568("pipe", BIT(8), BIT(11), false),
|
[RK3568_PD_PIPE] = DOMAIN_RK3568("pipe", BIT(8), BIT(11), false),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct rockchip_domain_info rk3588_pm_domains[] = {
|
||||||
|
[RK3588_PD_GPU] = DOMAIN_RK3588("gpu", 0x0, BIT(0), 0, BIT(1), 0x0, BIT(0), BIT(0), false),
|
||||||
|
[RK3588_PD_NPU] = DOMAIN_RK3588("npu", 0x0, BIT(1), BIT(1), 0, 0x0, 0, 0, false),
|
||||||
|
[RK3588_PD_VCODEC] = DOMAIN_RK3588("vcodec", 0x0, BIT(2), BIT(2), 0, 0x0, 0, 0, false),
|
||||||
|
[RK3588_PD_NPUTOP] = DOMAIN_RK3588("nputop", 0x0, BIT(3), 0, BIT(2), 0x0, BIT(1), BIT(1), false),
|
||||||
|
[RK3588_PD_NPU1] = DOMAIN_RK3588("npu1", 0x0, BIT(4), 0, BIT(3), 0x0, BIT(2), BIT(2), false),
|
||||||
|
[RK3588_PD_NPU2] = DOMAIN_RK3588("npu2", 0x0, BIT(5), 0, BIT(4), 0x0, BIT(3), BIT(3), false),
|
||||||
|
[RK3588_PD_VENC0] = DOMAIN_RK3588("venc0", 0x0, BIT(6), 0, BIT(5), 0x0, BIT(4), BIT(4), false),
|
||||||
|
[RK3588_PD_VENC1] = DOMAIN_RK3588("venc1", 0x0, BIT(7), 0, BIT(6), 0x0, BIT(5), BIT(5), false),
|
||||||
|
[RK3588_PD_RKVDEC0] = DOMAIN_RK3588("rkvdec0", 0x0, BIT(8), 0, BIT(7), 0x0, BIT(6), BIT(6), false),
|
||||||
|
[RK3588_PD_RKVDEC1] = DOMAIN_RK3588("rkvdec1", 0x0, BIT(9), 0, BIT(8), 0x0, BIT(7), BIT(7), false),
|
||||||
|
[RK3588_PD_VDPU] = DOMAIN_RK3588("vdpu", 0x0, BIT(10), 0, BIT(9), 0x0, BIT(8), BIT(8), false),
|
||||||
|
[RK3588_PD_RGA30] = DOMAIN_RK3588("rga30", 0x0, BIT(11), 0, BIT(10), 0x0, 0, 0, false),
|
||||||
|
[RK3588_PD_AV1] = DOMAIN_RK3588("av1", 0x0, BIT(12), 0, BIT(11), 0x0, BIT(9), BIT(9), false),
|
||||||
|
[RK3588_PD_VI] = DOMAIN_RK3588("vi", 0x0, BIT(13), 0, BIT(12), 0x0, BIT(10), BIT(10), false),
|
||||||
|
[RK3588_PD_FEC] = DOMAIN_RK3588("fec", 0x0, BIT(14), 0, BIT(13), 0x0, 0, 0, false),
|
||||||
|
[RK3588_PD_ISP1] = DOMAIN_RK3588("isp1", 0x0, BIT(15), 0, BIT(14), 0x0, BIT(11), BIT(11), false),
|
||||||
|
[RK3588_PD_RGA31] = DOMAIN_RK3588("rga31", 0x4, BIT(0), 0, BIT(15), 0x0, BIT(12), BIT(12), false),
|
||||||
|
[RK3588_PD_VOP] = DOMAIN_RK3588("vop", 0x4, BIT(1), 0, BIT(16), 0x0, BIT(13) | BIT(14), BIT(13) | BIT(14), false),
|
||||||
|
[RK3588_PD_VO0] = DOMAIN_RK3588("vo0", 0x4, BIT(2), 0, BIT(17), 0x0, BIT(15), BIT(15), false),
|
||||||
|
[RK3588_PD_VO1] = DOMAIN_RK3588("vo1", 0x4, BIT(3), 0, BIT(18), 0x4, BIT(0), BIT(16), false),
|
||||||
|
[RK3588_PD_AUDIO] = DOMAIN_RK3588("audio", 0x4, BIT(4), 0, BIT(19), 0x4, BIT(1), BIT(17), false),
|
||||||
|
[RK3588_PD_PHP] = DOMAIN_RK3588("php", 0x4, BIT(5), 0, BIT(20), 0x4, BIT(5), BIT(21), false),
|
||||||
|
[RK3588_PD_GMAC] = DOMAIN_RK3588("gmac", 0x4, BIT(6), 0, BIT(21), 0x0, 0, 0, false),
|
||||||
|
[RK3588_PD_PCIE] = DOMAIN_RK3588("pcie", 0x4, BIT(7), 0, BIT(22), 0x0, 0, 0, true),
|
||||||
|
[RK3588_PD_NVM] = DOMAIN_RK3588("nvm", 0x4, BIT(8), BIT(24), 0, 0x4, BIT(2), BIT(18), false),
|
||||||
|
[RK3588_PD_NVM0] = DOMAIN_RK3588("nvm0", 0x4, BIT(9), 0, BIT(23), 0x0, 0, 0, false),
|
||||||
|
[RK3588_PD_SDIO] = DOMAIN_RK3588("sdio", 0x4, BIT(10), 0, BIT(24), 0x4, BIT(3), BIT(19), false),
|
||||||
|
[RK3588_PD_USB] = DOMAIN_RK3588("usb", 0x4, BIT(11), 0, BIT(25), 0x4, BIT(4), BIT(20), true),
|
||||||
|
[RK3588_PD_SDMMC] = DOMAIN_RK3588("sdmmc", 0x4, BIT(13), 0, BIT(26), 0x0, 0, 0, false),
|
||||||
|
};
|
||||||
|
|
||||||
static const struct rockchip_pmu_info px30_pmu = {
|
static const struct rockchip_pmu_info px30_pmu = {
|
||||||
.pwr_offset = 0x18,
|
.pwr_offset = 0x18,
|
||||||
.status_offset = 0x20,
|
.status_offset = 0x20,
|
||||||
|
@ -1128,6 +1201,29 @@ static const struct rockchip_pmu_info rk3568_pmu = {
|
||||||
.domain_info = rk3568_pm_domains,
|
.domain_info = rk3568_pm_domains,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct rockchip_pmu_info rk3588_pmu = {
|
||||||
|
.pwr_offset = 0x14c,
|
||||||
|
.status_offset = 0x180,
|
||||||
|
.req_offset = 0x10c,
|
||||||
|
.idle_offset = 0x120,
|
||||||
|
.ack_offset = 0x118,
|
||||||
|
.repair_status_offset = 0x290,
|
||||||
|
|
||||||
|
.num_domains = ARRAY_SIZE(rk3588_pm_domains),
|
||||||
|
.domain_info = rk3588_pm_domains,
|
||||||
|
};
|
||||||
|
|
||||||
|
static const struct rockchip_pmu_info rv1126_pmu = {
|
||||||
|
.pwr_offset = 0x110,
|
||||||
|
.status_offset = 0x108,
|
||||||
|
.req_offset = 0xc0,
|
||||||
|
.idle_offset = 0xd8,
|
||||||
|
.ack_offset = 0xd0,
|
||||||
|
|
||||||
|
.num_domains = ARRAY_SIZE(rv1126_pm_domains),
|
||||||
|
.domain_info = rv1126_pm_domains,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct of_device_id rockchip_pm_domain_dt_match[] = {
|
static const struct of_device_id rockchip_pm_domain_dt_match[] = {
|
||||||
{
|
{
|
||||||
.compatible = "rockchip,px30-power-controller",
|
.compatible = "rockchip,px30-power-controller",
|
||||||
|
@ -1177,6 +1273,14 @@ static const struct of_device_id rockchip_pm_domain_dt_match[] = {
|
||||||
.compatible = "rockchip,rk3568-power-controller",
|
.compatible = "rockchip,rk3568-power-controller",
|
||||||
.data = (void *)&rk3568_pmu,
|
.data = (void *)&rk3568_pmu,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.compatible = "rockchip,rk3588-power-controller",
|
||||||
|
.data = (void *)&rk3588_pmu,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.compatible = "rockchip,rv1126-power-controller",
|
||||||
|
.data = (void *)&rv1126_pmu,
|
||||||
|
},
|
||||||
{ /* sentinel */ },
|
{ /* sentinel */ },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -261,30 +261,29 @@ int sunxi_sram_claim(struct device *dev)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sunxi_sram_claim);
|
EXPORT_SYMBOL(sunxi_sram_claim);
|
||||||
|
|
||||||
int sunxi_sram_release(struct device *dev)
|
void sunxi_sram_release(struct device *dev)
|
||||||
{
|
{
|
||||||
const struct sunxi_sram_data *sram_data;
|
const struct sunxi_sram_data *sram_data;
|
||||||
struct sunxi_sram_desc *sram_desc;
|
struct sunxi_sram_desc *sram_desc;
|
||||||
|
|
||||||
if (!dev || !dev->of_node)
|
if (!dev || !dev->of_node)
|
||||||
return -EINVAL;
|
return;
|
||||||
|
|
||||||
sram_data = sunxi_sram_of_parse(dev->of_node, NULL);
|
sram_data = sunxi_sram_of_parse(dev->of_node, NULL);
|
||||||
if (IS_ERR(sram_data))
|
if (IS_ERR(sram_data))
|
||||||
return -EINVAL;
|
return;
|
||||||
|
|
||||||
sram_desc = to_sram_desc(sram_data);
|
sram_desc = to_sram_desc(sram_data);
|
||||||
|
|
||||||
spin_lock(&sram_lock);
|
spin_lock(&sram_lock);
|
||||||
sram_desc->claimed = false;
|
sram_desc->claimed = false;
|
||||||
spin_unlock(&sram_lock);
|
spin_unlock(&sram_lock);
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(sunxi_sram_release);
|
EXPORT_SYMBOL(sunxi_sram_release);
|
||||||
|
|
||||||
struct sunxi_sramc_variant {
|
struct sunxi_sramc_variant {
|
||||||
int num_emac_clocks;
|
int num_emac_clocks;
|
||||||
|
bool has_ldo_ctrl;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
|
static const struct sunxi_sramc_variant sun4i_a10_sramc_variant = {
|
||||||
|
@ -295,6 +294,11 @@ static const struct sunxi_sramc_variant sun8i_h3_sramc_variant = {
|
||||||
.num_emac_clocks = 1,
|
.num_emac_clocks = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const struct sunxi_sramc_variant sun20i_d1_sramc_variant = {
|
||||||
|
.num_emac_clocks = 1,
|
||||||
|
.has_ldo_ctrl = true,
|
||||||
|
};
|
||||||
|
|
||||||
static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = {
|
static const struct sunxi_sramc_variant sun50i_a64_sramc_variant = {
|
||||||
.num_emac_clocks = 1,
|
.num_emac_clocks = 1,
|
||||||
};
|
};
|
||||||
|
@ -304,27 +308,28 @@ static const struct sunxi_sramc_variant sun50i_h616_sramc_variant = {
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SUNXI_SRAM_EMAC_CLOCK_REG 0x30
|
#define SUNXI_SRAM_EMAC_CLOCK_REG 0x30
|
||||||
|
#define SUNXI_SYS_LDO_CTRL_REG 0x150
|
||||||
|
|
||||||
static bool sunxi_sram_regmap_accessible_reg(struct device *dev,
|
static bool sunxi_sram_regmap_accessible_reg(struct device *dev,
|
||||||
unsigned int reg)
|
unsigned int reg)
|
||||||
{
|
{
|
||||||
const struct sunxi_sramc_variant *variant;
|
const struct sunxi_sramc_variant *variant = dev_get_drvdata(dev);
|
||||||
|
|
||||||
variant = of_device_get_match_data(dev);
|
if (reg >= SUNXI_SRAM_EMAC_CLOCK_REG &&
|
||||||
|
reg < SUNXI_SRAM_EMAC_CLOCK_REG + variant->num_emac_clocks * 4)
|
||||||
|
return true;
|
||||||
|
if (reg == SUNXI_SYS_LDO_CTRL_REG && variant->has_ldo_ctrl)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (reg < SUNXI_SRAM_EMAC_CLOCK_REG)
|
return false;
|
||||||
return false;
|
|
||||||
if (reg > SUNXI_SRAM_EMAC_CLOCK_REG + variant->num_emac_clocks * 4)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct regmap_config sunxi_sram_emac_clock_regmap = {
|
static struct regmap_config sunxi_sram_regmap_config = {
|
||||||
.reg_bits = 32,
|
.reg_bits = 32,
|
||||||
.val_bits = 32,
|
.val_bits = 32,
|
||||||
.reg_stride = 4,
|
.reg_stride = 4,
|
||||||
/* last defined register */
|
/* last defined register */
|
||||||
.max_register = SUNXI_SRAM_EMAC_CLOCK_REG + 4,
|
.max_register = SUNXI_SYS_LDO_CTRL_REG,
|
||||||
/* other devices have no business accessing other registers */
|
/* other devices have no business accessing other registers */
|
||||||
.readable_reg = sunxi_sram_regmap_accessible_reg,
|
.readable_reg = sunxi_sram_regmap_accessible_reg,
|
||||||
.writeable_reg = sunxi_sram_regmap_accessible_reg,
|
.writeable_reg = sunxi_sram_regmap_accessible_reg,
|
||||||
|
@ -332,9 +337,9 @@ static struct regmap_config sunxi_sram_emac_clock_regmap = {
|
||||||
|
|
||||||
static int __init sunxi_sram_probe(struct platform_device *pdev)
|
static int __init sunxi_sram_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
struct regmap *emac_clock;
|
|
||||||
const struct sunxi_sramc_variant *variant;
|
const struct sunxi_sramc_variant *variant;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
|
struct regmap *regmap;
|
||||||
|
|
||||||
sram_dev = &pdev->dev;
|
sram_dev = &pdev->dev;
|
||||||
|
|
||||||
|
@ -342,16 +347,16 @@ static int __init sunxi_sram_probe(struct platform_device *pdev)
|
||||||
if (!variant)
|
if (!variant)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
dev_set_drvdata(dev, (struct sunxi_sramc_variant *)variant);
|
||||||
|
|
||||||
base = devm_platform_ioremap_resource(pdev, 0);
|
base = devm_platform_ioremap_resource(pdev, 0);
|
||||||
if (IS_ERR(base))
|
if (IS_ERR(base))
|
||||||
return PTR_ERR(base);
|
return PTR_ERR(base);
|
||||||
|
|
||||||
if (variant->num_emac_clocks > 0) {
|
if (variant->num_emac_clocks || variant->has_ldo_ctrl) {
|
||||||
emac_clock = devm_regmap_init_mmio(&pdev->dev, base,
|
regmap = devm_regmap_init_mmio(dev, base, &sunxi_sram_regmap_config);
|
||||||
&sunxi_sram_emac_clock_regmap);
|
if (IS_ERR(regmap))
|
||||||
|
return PTR_ERR(regmap);
|
||||||
if (IS_ERR(emac_clock))
|
|
||||||
return PTR_ERR(emac_clock);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
of_platform_populate(dev->of_node, NULL, NULL, dev);
|
of_platform_populate(dev->of_node, NULL, NULL, dev);
|
||||||
|
@ -382,6 +387,10 @@ static const struct of_device_id sunxi_sram_dt_match[] = {
|
||||||
.compatible = "allwinner,sun8i-h3-system-control",
|
.compatible = "allwinner,sun8i-h3-system-control",
|
||||||
.data = &sun8i_h3_sramc_variant,
|
.data = &sun8i_h3_sramc_variant,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.compatible = "allwinner,sun20i-d1-system-control",
|
||||||
|
.data = &sun20i_d1_sramc_variant,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
.compatible = "allwinner,sun50i-a64-sram-controller",
|
.compatible = "allwinner,sun50i-a64-sram-controller",
|
||||||
.data = &sun50i_a64_sramc_variant,
|
.data = &sun50i_a64_sramc_variant,
|
||||||
|
|
|
@ -136,7 +136,6 @@ config SOC_TEGRA_FUSE
|
||||||
def_bool y
|
def_bool y
|
||||||
depends on ARCH_TEGRA
|
depends on ARCH_TEGRA
|
||||||
select SOC_BUS
|
select SOC_BUS
|
||||||
select TEGRA20_APB_DMA if ARCH_TEGRA_2x_SOC
|
|
||||||
|
|
||||||
config SOC_TEGRA_FLOWCTRL
|
config SOC_TEGRA_FLOWCTRL
|
||||||
bool
|
bool
|
||||||
|
@ -162,3 +161,12 @@ config SOC_TEGRA30_VOLTAGE_COUPLER
|
||||||
bool "Voltage scaling support for Tegra30 SoCs"
|
bool "Voltage scaling support for Tegra30 SoCs"
|
||||||
depends on ARCH_TEGRA_3x_SOC || COMPILE_TEST
|
depends on ARCH_TEGRA_3x_SOC || COMPILE_TEST
|
||||||
depends on REGULATOR
|
depends on REGULATOR
|
||||||
|
|
||||||
|
config SOC_TEGRA_CBB
|
||||||
|
tristate "Tegra driver to handle error from CBB"
|
||||||
|
depends on ARCH_TEGRA_194_SOC || ARCH_TEGRA_234_SOC
|
||||||
|
default y
|
||||||
|
help
|
||||||
|
Support for handling error from Tegra Control Backbone(CBB).
|
||||||
|
This driver handles the errors from CBB and prints debug
|
||||||
|
information about the failed transactions.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
# SPDX-License-Identifier: GPL-2.0
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
obj-y += fuse/
|
obj-y += fuse/
|
||||||
|
obj-y += cbb/
|
||||||
|
|
||||||
obj-y += common.o
|
obj-y += common.o
|
||||||
obj-$(CONFIG_SOC_TEGRA_FLOWCTRL) += flowctrl.o
|
obj-$(CONFIG_SOC_TEGRA_FLOWCTRL) += flowctrl.o
|
||||||
|
|
9
drivers/soc/tegra/cbb/Makefile
Normal file
9
drivers/soc/tegra/cbb/Makefile
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
#
|
||||||
|
# Control Backbone Driver code.
|
||||||
|
#
|
||||||
|
ifdef CONFIG_SOC_TEGRA_CBB
|
||||||
|
obj-y += tegra-cbb.o
|
||||||
|
obj-$(CONFIG_ARCH_TEGRA_194_SOC) += tegra194-cbb.o
|
||||||
|
obj-$(CONFIG_ARCH_TEGRA_234_SOC) += tegra234-cbb.o
|
||||||
|
endif
|
190
drivers/soc/tegra/cbb/tegra-cbb.c
Normal file
190
drivers/soc/tegra/cbb/tegra-cbb.c
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/cpufeature.h>
|
||||||
|
#include <linux/debugfs.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_device.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/of_irq.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/ioport.h>
|
||||||
|
#include <linux/version.h>
|
||||||
|
#include <soc/tegra/fuse.h>
|
||||||
|
#include <soc/tegra/tegra-cbb.h>
|
||||||
|
|
||||||
|
void tegra_cbb_print_err(struct seq_file *file, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
struct va_format vaf;
|
||||||
|
va_list args;
|
||||||
|
|
||||||
|
va_start(args, fmt);
|
||||||
|
|
||||||
|
if (file) {
|
||||||
|
seq_vprintf(file, fmt, args);
|
||||||
|
} else {
|
||||||
|
vaf.fmt = fmt;
|
||||||
|
vaf.va = &args;
|
||||||
|
pr_crit("%pV", &vaf);
|
||||||
|
}
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tegra_cbb_print_cache(struct seq_file *file, u32 cache)
|
||||||
|
{
|
||||||
|
const char *buff_str, *mod_str, *rd_str, *wr_str;
|
||||||
|
|
||||||
|
buff_str = (cache & BIT(0)) ? "Bufferable " : "";
|
||||||
|
mod_str = (cache & BIT(1)) ? "Modifiable " : "";
|
||||||
|
rd_str = (cache & BIT(2)) ? "Read-Allocate " : "";
|
||||||
|
wr_str = (cache & BIT(3)) ? "Write-Allocate" : "";
|
||||||
|
|
||||||
|
if (cache == 0x0)
|
||||||
|
buff_str = "Device Non-Bufferable";
|
||||||
|
|
||||||
|
tegra_cbb_print_err(file, "\t Cache\t\t\t: 0x%x -- %s%s%s%s\n",
|
||||||
|
cache, buff_str, mod_str, rd_str, wr_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tegra_cbb_print_prot(struct seq_file *file, u32 prot)
|
||||||
|
{
|
||||||
|
const char *data_str, *secure_str, *priv_str;
|
||||||
|
|
||||||
|
data_str = (prot & 0x4) ? "Instruction" : "Data";
|
||||||
|
secure_str = (prot & 0x2) ? "Non-Secure" : "Secure";
|
||||||
|
priv_str = (prot & 0x1) ? "Privileged" : "Unprivileged";
|
||||||
|
|
||||||
|
tegra_cbb_print_err(file, "\t Protection\t\t: 0x%x -- %s, %s, %s Access\n",
|
||||||
|
prot, priv_str, secure_str, data_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_cbb_err_show(struct seq_file *file, void *data)
|
||||||
|
{
|
||||||
|
struct tegra_cbb *cbb = file->private;
|
||||||
|
|
||||||
|
return cbb->ops->debugfs_show(cbb, file, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int tegra_cbb_err_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
return single_open(file, tegra_cbb_err_show, inode->i_private);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct file_operations tegra_cbb_err_fops = {
|
||||||
|
.open = tegra_cbb_err_open,
|
||||||
|
.read = seq_read,
|
||||||
|
.llseek = seq_lseek,
|
||||||
|
.release = single_release
|
||||||
|
};
|
||||||
|
|
||||||
|
static int tegra_cbb_err_debugfs_init(struct tegra_cbb *cbb)
|
||||||
|
{
|
||||||
|
static struct dentry *root;
|
||||||
|
|
||||||
|
if (!root) {
|
||||||
|
root = debugfs_create_file("tegra_cbb_err", 0444, NULL, cbb, &tegra_cbb_err_fops);
|
||||||
|
if (IS_ERR_OR_NULL(root)) {
|
||||||
|
pr_err("%s(): could not create debugfs node\n", __func__);
|
||||||
|
return PTR_ERR(root);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void tegra_cbb_stall_enable(struct tegra_cbb *cbb)
|
||||||
|
{
|
||||||
|
if (cbb->ops->stall_enable)
|
||||||
|
cbb->ops->stall_enable(cbb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tegra_cbb_fault_enable(struct tegra_cbb *cbb)
|
||||||
|
{
|
||||||
|
if (cbb->ops->fault_enable)
|
||||||
|
cbb->ops->fault_enable(cbb);
|
||||||
|
}
|
||||||
|
|
||||||
|
void tegra_cbb_error_clear(struct tegra_cbb *cbb)
|
||||||
|
{
|
||||||
|
if (cbb->ops->error_clear)
|
||||||
|
cbb->ops->error_clear(cbb);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 tegra_cbb_get_status(struct tegra_cbb *cbb)
|
||||||
|
{
|
||||||
|
if (cbb->ops->get_status)
|
||||||
|
return cbb->ops->get_status(cbb);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tegra_cbb_get_irq(struct platform_device *pdev, unsigned int *nonsec_irq,
|
||||||
|
unsigned int *sec_irq)
|
||||||
|
{
|
||||||
|
unsigned int index = 0;
|
||||||
|
int num_intr = 0, irq;
|
||||||
|
|
||||||
|
num_intr = platform_irq_count(pdev);
|
||||||
|
if (!num_intr)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (num_intr == 2) {
|
||||||
|
irq = platform_get_irq(pdev, index);
|
||||||
|
if (irq <= 0) {
|
||||||
|
dev_err(&pdev->dev, "failed to get non-secure IRQ: %d\n", irq);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
*nonsec_irq = irq;
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
|
||||||
|
irq = platform_get_irq(pdev, index);
|
||||||
|
if (irq <= 0) {
|
||||||
|
dev_err(&pdev->dev, "failed to get secure IRQ: %d\n", irq);
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
*sec_irq = irq;
|
||||||
|
|
||||||
|
if (num_intr == 1)
|
||||||
|
dev_dbg(&pdev->dev, "secure IRQ: %u\n", *sec_irq);
|
||||||
|
|
||||||
|
if (num_intr == 2)
|
||||||
|
dev_dbg(&pdev->dev, "secure IRQ: %u, non-secure IRQ: %u\n", *sec_irq, *nonsec_irq);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int tegra_cbb_register(struct tegra_cbb *cbb)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (IS_ENABLED(CONFIG_DEBUG_FS)) {
|
||||||
|
ret = tegra_cbb_err_debugfs_init(cbb);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(cbb->dev, "failed to create debugfs\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* register interrupt handler for errors due to different initiators */
|
||||||
|
ret = cbb->ops->interrupt_enable(cbb);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(cbb->dev, "Failed to register CBB Interrupt ISR");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
cbb->ops->error_enable(cbb);
|
||||||
|
dsb(sy);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
2364
drivers/soc/tegra/cbb/tegra194-cbb.c
Normal file
2364
drivers/soc/tegra/cbb/tegra194-cbb.c
Normal file
File diff suppressed because it is too large
Load diff
1113
drivers/soc/tegra/cbb/tegra234-cbb.c
Normal file
1113
drivers/soc/tegra/cbb/tegra234-cbb.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -568,6 +568,7 @@ static int __init tegra_init_fuse(void)
|
||||||
np = of_find_matching_node(NULL, car_match);
|
np = of_find_matching_node(NULL, car_match);
|
||||||
if (np) {
|
if (np) {
|
||||||
void __iomem *base = of_iomap(np, 0);
|
void __iomem *base = of_iomap(np, 0);
|
||||||
|
of_node_put(np);
|
||||||
if (base) {
|
if (base) {
|
||||||
tegra_enable_fuse_clk(base);
|
tegra_enable_fuse_clk(base);
|
||||||
iounmap(base);
|
iounmap(base);
|
||||||
|
|
|
@ -16,12 +16,16 @@
|
||||||
|
|
||||||
#define FUSE_SKU_INFO 0x10
|
#define FUSE_SKU_INFO 0x10
|
||||||
|
|
||||||
|
#define ERD_ERR_CONFIG 0x120c
|
||||||
|
#define ERD_MASK_INBAND_ERR 0x1
|
||||||
|
|
||||||
#define PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT 4
|
#define PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT 4
|
||||||
#define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG \
|
#define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_LONG \
|
||||||
(0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT)
|
(0xf << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT)
|
||||||
#define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT \
|
#define PMC_STRAPPING_OPT_A_RAM_CODE_MASK_SHORT \
|
||||||
(0x3 << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT)
|
(0x3 << PMC_STRAPPING_OPT_A_RAM_CODE_SHIFT)
|
||||||
|
|
||||||
|
static void __iomem *apbmisc_base;
|
||||||
static bool long_ram_code;
|
static bool long_ram_code;
|
||||||
static u32 strapping;
|
static u32 strapping;
|
||||||
static u32 chipid;
|
static u32 chipid;
|
||||||
|
@ -93,6 +97,28 @@ u32 tegra_read_ram_code(void)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(tegra_read_ram_code);
|
EXPORT_SYMBOL_GPL(tegra_read_ram_code);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The function sets ERD(Error Response Disable) bit.
|
||||||
|
* This allows to mask inband errors and always send an
|
||||||
|
* OKAY response from CBB to the master which caused error.
|
||||||
|
*/
|
||||||
|
int tegra194_miscreg_mask_serror(void)
|
||||||
|
{
|
||||||
|
if (!apbmisc_base)
|
||||||
|
return -EPROBE_DEFER;
|
||||||
|
|
||||||
|
if (!of_machine_is_compatible("nvidia,tegra194")) {
|
||||||
|
WARN(1, "Only supported for Tegra194 devices!\n");
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
}
|
||||||
|
|
||||||
|
writel_relaxed(ERD_MASK_INBAND_ERR,
|
||||||
|
apbmisc_base + ERD_ERR_CONFIG);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(tegra194_miscreg_mask_serror);
|
||||||
|
|
||||||
static const struct of_device_id apbmisc_match[] __initconst = {
|
static const struct of_device_id apbmisc_match[] __initconst = {
|
||||||
{ .compatible = "nvidia,tegra20-apbmisc", },
|
{ .compatible = "nvidia,tegra20-apbmisc", },
|
||||||
{ .compatible = "nvidia,tegra186-misc", },
|
{ .compatible = "nvidia,tegra186-misc", },
|
||||||
|
@ -134,7 +160,7 @@ void __init tegra_init_revision(void)
|
||||||
|
|
||||||
void __init tegra_init_apbmisc(void)
|
void __init tegra_init_apbmisc(void)
|
||||||
{
|
{
|
||||||
void __iomem *apbmisc_base, *strapping_base;
|
void __iomem *strapping_base;
|
||||||
struct resource apbmisc, straps;
|
struct resource apbmisc, straps;
|
||||||
struct device_node *np;
|
struct device_node *np;
|
||||||
|
|
||||||
|
@ -182,12 +208,12 @@ void __init tegra_init_apbmisc(void)
|
||||||
*/
|
*/
|
||||||
if (of_address_to_resource(np, 0, &apbmisc) < 0) {
|
if (of_address_to_resource(np, 0, &apbmisc) < 0) {
|
||||||
pr_err("failed to get APBMISC registers\n");
|
pr_err("failed to get APBMISC registers\n");
|
||||||
return;
|
goto put;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (of_address_to_resource(np, 1, &straps) < 0) {
|
if (of_address_to_resource(np, 1, &straps) < 0) {
|
||||||
pr_err("failed to get strapping options registers\n");
|
pr_err("failed to get strapping options registers\n");
|
||||||
return;
|
goto put;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -196,7 +222,6 @@ void __init tegra_init_apbmisc(void)
|
||||||
pr_err("failed to map APBMISC registers\n");
|
pr_err("failed to map APBMISC registers\n");
|
||||||
} else {
|
} else {
|
||||||
chipid = readl_relaxed(apbmisc_base + 4);
|
chipid = readl_relaxed(apbmisc_base + 4);
|
||||||
iounmap(apbmisc_base);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
strapping_base = ioremap(straps.start, resource_size(&straps));
|
strapping_base = ioremap(straps.start, resource_size(&straps));
|
||||||
|
@ -208,4 +233,7 @@ void __init tegra_init_apbmisc(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
long_ram_code = of_property_read_bool(np, "nvidia,long-ram-code");
|
long_ram_code = of_property_read_bool(np, "nvidia,long-ram-code");
|
||||||
|
|
||||||
|
put:
|
||||||
|
of_node_put(np);
|
||||||
}
|
}
|
||||||
|
|
|
@ -296,6 +296,17 @@ struct tegra_wake_event {
|
||||||
} gpio;
|
} gpio;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define TEGRA_WAKE_SIMPLE(_name, _id) \
|
||||||
|
{ \
|
||||||
|
.name = _name, \
|
||||||
|
.id = _id, \
|
||||||
|
.irq = 0, \
|
||||||
|
.gpio = { \
|
||||||
|
.instance = UINT_MAX, \
|
||||||
|
.pin = UINT_MAX, \
|
||||||
|
}, \
|
||||||
|
}
|
||||||
|
|
||||||
#define TEGRA_WAKE_IRQ(_name, _id, _irq) \
|
#define TEGRA_WAKE_IRQ(_name, _id, _irq) \
|
||||||
{ \
|
{ \
|
||||||
.name = _name, \
|
.name = _name, \
|
||||||
|
@ -2239,6 +2250,7 @@ static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq,
|
||||||
for (i = 0; i < soc->num_wake_events; i++) {
|
for (i = 0; i < soc->num_wake_events; i++) {
|
||||||
const struct tegra_wake_event *event = &soc->wake_events[i];
|
const struct tegra_wake_event *event = &soc->wake_events[i];
|
||||||
|
|
||||||
|
/* IRQ and simple wake events */
|
||||||
if (fwspec->param_count == 2) {
|
if (fwspec->param_count == 2) {
|
||||||
struct irq_fwspec spec;
|
struct irq_fwspec spec;
|
||||||
|
|
||||||
|
@ -2251,6 +2263,12 @@ static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq,
|
||||||
if (err < 0)
|
if (err < 0)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
/* simple hierarchies stop at the PMC level */
|
||||||
|
if (event->irq == 0) {
|
||||||
|
err = irq_domain_disconnect_hierarchy(domain->parent, virq);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
spec.fwnode = &pmc->dev->of_node->fwnode;
|
spec.fwnode = &pmc->dev->of_node->fwnode;
|
||||||
spec.param_count = 3;
|
spec.param_count = 3;
|
||||||
spec.param[0] = GIC_SPI;
|
spec.param[0] = GIC_SPI;
|
||||||
|
@ -2263,6 +2281,7 @@ static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* GPIO wake events */
|
||||||
if (fwspec->param_count == 3) {
|
if (fwspec->param_count == 3) {
|
||||||
if (event->gpio.instance != fwspec->param[0] ||
|
if (event->gpio.instance != fwspec->param[0] ||
|
||||||
event->gpio.pin != fwspec->param[1])
|
event->gpio.pin != fwspec->param[1])
|
||||||
|
@ -2274,7 +2293,7 @@ static int tegra_pmc_irq_alloc(struct irq_domain *domain, unsigned int virq,
|
||||||
|
|
||||||
/* GPIO hierarchies stop at the PMC level */
|
/* GPIO hierarchies stop at the PMC level */
|
||||||
if (!err && domain->parent)
|
if (!err && domain->parent)
|
||||||
err = irq_domain_disconnect_hierarchy(domain->parent,
|
err = irq_domain_disconnect_hierarchy(domain->parent,
|
||||||
virq);
|
virq);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -2885,17 +2904,10 @@ static int tegra_pmc_probe(struct platform_device *pdev)
|
||||||
pmc->scratch = base;
|
pmc->scratch = base;
|
||||||
}
|
}
|
||||||
|
|
||||||
pmc->clk = devm_clk_get(&pdev->dev, "pclk");
|
pmc->clk = devm_clk_get_optional(&pdev->dev, "pclk");
|
||||||
if (IS_ERR(pmc->clk)) {
|
if (IS_ERR(pmc->clk))
|
||||||
err = PTR_ERR(pmc->clk);
|
return dev_err_probe(&pdev->dev, PTR_ERR(pmc->clk),
|
||||||
|
"failed to get pclk\n");
|
||||||
if (err != -ENOENT) {
|
|
||||||
dev_err(&pdev->dev, "failed to get pclk: %d\n", err);
|
|
||||||
return err;
|
|
||||||
}
|
|
||||||
|
|
||||||
pmc->clk = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* PMC should be last resort for restarting since it soft-resets
|
* PMC should be last resort for restarting since it soft-resets
|
||||||
|
@ -3757,6 +3769,13 @@ static const struct tegra_wake_event tegra194_wake_events[] = {
|
||||||
TEGRA_WAKE_IRQ("pmu", 24, 209),
|
TEGRA_WAKE_IRQ("pmu", 24, 209),
|
||||||
TEGRA_WAKE_GPIO("power", 29, 1, TEGRA194_AON_GPIO(EE, 4)),
|
TEGRA_WAKE_GPIO("power", 29, 1, TEGRA194_AON_GPIO(EE, 4)),
|
||||||
TEGRA_WAKE_IRQ("rtc", 73, 10),
|
TEGRA_WAKE_IRQ("rtc", 73, 10),
|
||||||
|
TEGRA_WAKE_SIMPLE("usb3-port-0", 76),
|
||||||
|
TEGRA_WAKE_SIMPLE("usb3-port-1", 77),
|
||||||
|
TEGRA_WAKE_SIMPLE("usb3-port-2-3", 78),
|
||||||
|
TEGRA_WAKE_SIMPLE("usb2-port-0", 79),
|
||||||
|
TEGRA_WAKE_SIMPLE("usb2-port-1", 80),
|
||||||
|
TEGRA_WAKE_SIMPLE("usb2-port-2", 81),
|
||||||
|
TEGRA_WAKE_SIMPLE("usb2-port-3", 82),
|
||||||
};
|
};
|
||||||
|
|
||||||
static const struct tegra_pmc_soc tegra194_pmc_soc = {
|
static const struct tegra_pmc_soc tegra194_pmc_soc = {
|
||||||
|
@ -4025,7 +4044,7 @@ static int __init tegra_pmc_early_init(void)
|
||||||
return -ENXIO;
|
return -ENXIO;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (np) {
|
if (of_device_is_available(np)) {
|
||||||
pmc->soc = match->data;
|
pmc->soc = match->data;
|
||||||
|
|
||||||
if (pmc->soc->maybe_tz_only)
|
if (pmc->soc->maybe_tz_only)
|
||||||
|
|
|
@ -271,8 +271,8 @@ static int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm,
|
||||||
unsigned long start)
|
unsigned long start)
|
||||||
{
|
{
|
||||||
struct optee *optee = tee_get_drvdata(ctx->teedev);
|
struct optee *optee = tee_get_drvdata(ctx->teedev);
|
||||||
const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops;
|
|
||||||
struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
|
struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
|
||||||
|
const struct ffa_mem_ops *mem_ops = ffa_dev->ops->mem_ops;
|
||||||
struct ffa_mem_region_attributes mem_attr = {
|
struct ffa_mem_region_attributes mem_attr = {
|
||||||
.receiver = ffa_dev->vm_id,
|
.receiver = ffa_dev->vm_id,
|
||||||
.attrs = FFA_MEM_RW,
|
.attrs = FFA_MEM_RW,
|
||||||
|
@ -294,14 +294,14 @@ static int optee_ffa_shm_register(struct tee_context *ctx, struct tee_shm *shm,
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
args.sg = sgt.sgl;
|
args.sg = sgt.sgl;
|
||||||
rc = ffa_ops->memory_share(ffa_dev, &args);
|
rc = mem_ops->memory_share(&args);
|
||||||
sg_free_table(&sgt);
|
sg_free_table(&sgt);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
rc = optee_shm_add_ffa_handle(optee, shm, args.g_handle);
|
rc = optee_shm_add_ffa_handle(optee, shm, args.g_handle);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
ffa_ops->memory_reclaim(args.g_handle, 0);
|
mem_ops->memory_reclaim(args.g_handle, 0);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -314,8 +314,9 @@ static int optee_ffa_shm_unregister(struct tee_context *ctx,
|
||||||
struct tee_shm *shm)
|
struct tee_shm *shm)
|
||||||
{
|
{
|
||||||
struct optee *optee = tee_get_drvdata(ctx->teedev);
|
struct optee *optee = tee_get_drvdata(ctx->teedev);
|
||||||
const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops;
|
|
||||||
struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
|
struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
|
||||||
|
const struct ffa_msg_ops *msg_ops = ffa_dev->ops->msg_ops;
|
||||||
|
const struct ffa_mem_ops *mem_ops = ffa_dev->ops->mem_ops;
|
||||||
u64 global_handle = shm->sec_world_id;
|
u64 global_handle = shm->sec_world_id;
|
||||||
struct ffa_send_direct_data data = {
|
struct ffa_send_direct_data data = {
|
||||||
.data0 = OPTEE_FFA_UNREGISTER_SHM,
|
.data0 = OPTEE_FFA_UNREGISTER_SHM,
|
||||||
|
@ -327,11 +328,11 @@ static int optee_ffa_shm_unregister(struct tee_context *ctx,
|
||||||
optee_shm_rem_ffa_handle(optee, global_handle);
|
optee_shm_rem_ffa_handle(optee, global_handle);
|
||||||
shm->sec_world_id = 0;
|
shm->sec_world_id = 0;
|
||||||
|
|
||||||
rc = ffa_ops->sync_send_receive(ffa_dev, &data);
|
rc = msg_ops->sync_send_receive(ffa_dev, &data);
|
||||||
if (rc)
|
if (rc)
|
||||||
pr_err("Unregister SHM id 0x%llx rc %d\n", global_handle, rc);
|
pr_err("Unregister SHM id 0x%llx rc %d\n", global_handle, rc);
|
||||||
|
|
||||||
rc = ffa_ops->memory_reclaim(global_handle, 0);
|
rc = mem_ops->memory_reclaim(global_handle, 0);
|
||||||
if (rc)
|
if (rc)
|
||||||
pr_err("mem_reclaim: 0x%llx %d", global_handle, rc);
|
pr_err("mem_reclaim: 0x%llx %d", global_handle, rc);
|
||||||
|
|
||||||
|
@ -342,7 +343,7 @@ static int optee_ffa_shm_unregister_supp(struct tee_context *ctx,
|
||||||
struct tee_shm *shm)
|
struct tee_shm *shm)
|
||||||
{
|
{
|
||||||
struct optee *optee = tee_get_drvdata(ctx->teedev);
|
struct optee *optee = tee_get_drvdata(ctx->teedev);
|
||||||
const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops;
|
const struct ffa_mem_ops *mem_ops;
|
||||||
u64 global_handle = shm->sec_world_id;
|
u64 global_handle = shm->sec_world_id;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
|
@ -353,7 +354,8 @@ static int optee_ffa_shm_unregister_supp(struct tee_context *ctx,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
optee_shm_rem_ffa_handle(optee, global_handle);
|
optee_shm_rem_ffa_handle(optee, global_handle);
|
||||||
rc = ffa_ops->memory_reclaim(global_handle, 0);
|
mem_ops = optee->ffa.ffa_dev->ops->mem_ops;
|
||||||
|
rc = mem_ops->memory_reclaim(global_handle, 0);
|
||||||
if (rc)
|
if (rc)
|
||||||
pr_err("mem_reclaim: 0x%llx %d", global_handle, rc);
|
pr_err("mem_reclaim: 0x%llx %d", global_handle, rc);
|
||||||
|
|
||||||
|
@ -529,8 +531,8 @@ static int optee_ffa_yielding_call(struct tee_context *ctx,
|
||||||
struct optee_msg_arg *rpc_arg)
|
struct optee_msg_arg *rpc_arg)
|
||||||
{
|
{
|
||||||
struct optee *optee = tee_get_drvdata(ctx->teedev);
|
struct optee *optee = tee_get_drvdata(ctx->teedev);
|
||||||
const struct ffa_dev_ops *ffa_ops = optee->ffa.ffa_ops;
|
|
||||||
struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
|
struct ffa_device *ffa_dev = optee->ffa.ffa_dev;
|
||||||
|
const struct ffa_msg_ops *msg_ops = ffa_dev->ops->msg_ops;
|
||||||
struct optee_call_waiter w;
|
struct optee_call_waiter w;
|
||||||
u32 cmd = data->data0;
|
u32 cmd = data->data0;
|
||||||
u32 w4 = data->data1;
|
u32 w4 = data->data1;
|
||||||
|
@ -541,7 +543,7 @@ static int optee_ffa_yielding_call(struct tee_context *ctx,
|
||||||
/* Initialize waiter */
|
/* Initialize waiter */
|
||||||
optee_cq_wait_init(&optee->call_queue, &w);
|
optee_cq_wait_init(&optee->call_queue, &w);
|
||||||
while (true) {
|
while (true) {
|
||||||
rc = ffa_ops->sync_send_receive(ffa_dev, data);
|
rc = msg_ops->sync_send_receive(ffa_dev, data);
|
||||||
if (rc)
|
if (rc)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
@ -576,7 +578,7 @@ static int optee_ffa_yielding_call(struct tee_context *ctx,
|
||||||
* OP-TEE has returned with a RPC request.
|
* OP-TEE has returned with a RPC request.
|
||||||
*
|
*
|
||||||
* Note that data->data4 (passed in register w7) is already
|
* Note that data->data4 (passed in register w7) is already
|
||||||
* filled in by ffa_ops->sync_send_receive() returning
|
* filled in by ffa_mem_ops->sync_send_receive() returning
|
||||||
* above.
|
* above.
|
||||||
*/
|
*/
|
||||||
cond_resched();
|
cond_resched();
|
||||||
|
@ -652,14 +654,15 @@ static int optee_ffa_do_call_with_arg(struct tee_context *ctx,
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev,
|
static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev,
|
||||||
const struct ffa_dev_ops *ops)
|
const struct ffa_ops *ops)
|
||||||
{
|
{
|
||||||
|
const struct ffa_msg_ops *msg_ops = ops->msg_ops;
|
||||||
struct ffa_send_direct_data data = { OPTEE_FFA_GET_API_VERSION };
|
struct ffa_send_direct_data data = { OPTEE_FFA_GET_API_VERSION };
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
ops->mode_32bit_set(ffa_dev);
|
msg_ops->mode_32bit_set(ffa_dev);
|
||||||
|
|
||||||
rc = ops->sync_send_receive(ffa_dev, &data);
|
rc = msg_ops->sync_send_receive(ffa_dev, &data);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("Unexpected error %d\n", rc);
|
pr_err("Unexpected error %d\n", rc);
|
||||||
return false;
|
return false;
|
||||||
|
@ -672,7 +675,7 @@ static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
data = (struct ffa_send_direct_data){ OPTEE_FFA_GET_OS_VERSION };
|
data = (struct ffa_send_direct_data){ OPTEE_FFA_GET_OS_VERSION };
|
||||||
rc = ops->sync_send_receive(ffa_dev, &data);
|
rc = msg_ops->sync_send_receive(ffa_dev, &data);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("Unexpected error %d\n", rc);
|
pr_err("Unexpected error %d\n", rc);
|
||||||
return false;
|
return false;
|
||||||
|
@ -687,14 +690,14 @@ static bool optee_ffa_api_is_compatbile(struct ffa_device *ffa_dev,
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev,
|
static bool optee_ffa_exchange_caps(struct ffa_device *ffa_dev,
|
||||||
const struct ffa_dev_ops *ops,
|
const struct ffa_ops *ops,
|
||||||
u32 *sec_caps,
|
u32 *sec_caps,
|
||||||
unsigned int *rpc_param_count)
|
unsigned int *rpc_param_count)
|
||||||
{
|
{
|
||||||
struct ffa_send_direct_data data = { OPTEE_FFA_EXCHANGE_CAPABILITIES };
|
struct ffa_send_direct_data data = { OPTEE_FFA_EXCHANGE_CAPABILITIES };
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
rc = ops->sync_send_receive(ffa_dev, &data);
|
rc = ops->msg_ops->sync_send_receive(ffa_dev, &data);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("Unexpected error %d", rc);
|
pr_err("Unexpected error %d", rc);
|
||||||
return false;
|
return false;
|
||||||
|
@ -783,7 +786,7 @@ static void optee_ffa_remove(struct ffa_device *ffa_dev)
|
||||||
|
|
||||||
static int optee_ffa_probe(struct ffa_device *ffa_dev)
|
static int optee_ffa_probe(struct ffa_device *ffa_dev)
|
||||||
{
|
{
|
||||||
const struct ffa_dev_ops *ffa_ops;
|
const struct ffa_ops *ffa_ops;
|
||||||
unsigned int rpc_param_count;
|
unsigned int rpc_param_count;
|
||||||
struct tee_shm_pool *pool;
|
struct tee_shm_pool *pool;
|
||||||
struct tee_device *teedev;
|
struct tee_device *teedev;
|
||||||
|
@ -793,11 +796,7 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
|
||||||
u32 sec_caps;
|
u32 sec_caps;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
ffa_ops = ffa_dev_ops_get(ffa_dev);
|
ffa_ops = ffa_dev->ops;
|
||||||
if (!ffa_ops) {
|
|
||||||
pr_warn("failed \"method\" init: ffa\n");
|
|
||||||
return -ENOENT;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!optee_ffa_api_is_compatbile(ffa_dev, ffa_ops))
|
if (!optee_ffa_api_is_compatbile(ffa_dev, ffa_ops))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
@ -821,7 +820,6 @@ static int optee_ffa_probe(struct ffa_device *ffa_dev)
|
||||||
|
|
||||||
optee->ops = &optee_ffa_ops;
|
optee->ops = &optee_ffa_ops;
|
||||||
optee->ffa.ffa_dev = ffa_dev;
|
optee->ffa.ffa_dev = ffa_dev;
|
||||||
optee->ffa.ffa_ops = ffa_ops;
|
|
||||||
optee->rpc_param_count = rpc_param_count;
|
optee->rpc_param_count = rpc_param_count;
|
||||||
|
|
||||||
teedev = tee_device_alloc(&optee_ffa_clnt_desc, NULL, optee->pool,
|
teedev = tee_device_alloc(&optee_ffa_clnt_desc, NULL, optee->pool,
|
||||||
|
|
|
@ -111,7 +111,6 @@ struct optee_smc {
|
||||||
*/
|
*/
|
||||||
struct optee_ffa {
|
struct optee_ffa {
|
||||||
struct ffa_device *ffa_dev;
|
struct ffa_device *ffa_dev;
|
||||||
const struct ffa_dev_ops *ffa_ops;
|
|
||||||
/* Serializes access to @global_ids */
|
/* Serializes access to @global_ids */
|
||||||
struct mutex mutex;
|
struct mutex mutex;
|
||||||
struct rhashtable global_ids;
|
struct rhashtable global_ids;
|
||||||
|
|
|
@ -1083,8 +1083,8 @@ config SERIAL_TIMBERDALE
|
||||||
config SERIAL_BCM63XX
|
config SERIAL_BCM63XX
|
||||||
tristate "Broadcom BCM63xx/BCM33xx UART support"
|
tristate "Broadcom BCM63xx/BCM33xx UART support"
|
||||||
select SERIAL_CORE
|
select SERIAL_CORE
|
||||||
depends on ARCH_BCM4908 || ARCH_BCMBCA || BCM63XX || BMIPS_GENERIC || COMPILE_TEST
|
depends on ARCH_BCMBCA || BCM63XX || BMIPS_GENERIC || COMPILE_TEST
|
||||||
default ARCH_BCM4908 || ARCH_BCMBCA || BCM63XX || BMIPS_GENERIC
|
default ARCH_BCMBCA || BCM63XX || BMIPS_GENERIC
|
||||||
help
|
help
|
||||||
This enables the driver for the onchip UART core found on
|
This enables the driver for the onchip UART core found on
|
||||||
the following chipsets:
|
the following chipsets:
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue