i.MX drivers change for 6.1:
- Update i.MX8MP blk-ctrl driver to handle PCIe PHY reset bit. - Add interconnect support into i.MX8MP blk-ctrl driver, so that i.MX8MP NoC can be set up properly after related power domain is up. - Add blk-ctrl support for i.MX8MP HDMI HDCP/HRV and VPU block. - Add i.MX93 SRC power domain and MEDIA blk-ctrl driver. - Update imx8m-blk-ctrl driver to use genpd_xlate_onecell. -----BEGIN PGP SIGNATURE----- iQFIBAABCgAyFiEEFmJXigPl4LoGSz08UFdYWoewfM4FAmMlib0UHHNoYXduZ3Vv QGtlcm5lbC5vcmcACgkQUFdYWoewfM4SPAf7BOfD4bViP+/hxhucfoEYTPShXiBz Qrk63cCQlZB72L90AKx+x7TJEdikfTGQwt5xWN1E3d3EepPn4sPuS4aKierHNQZs V29ooGSbUdfpYqF+NbyOcIS8qnPJPTlN+0sh6+6eYua8LpR/GQQXH4Zqyj7FiGRE p5wPewJVr7lxhWyhmx1f4HUzptEYaNPjYCk3kjslZeyp8gupoX6JdB8zKfJbL+Ho KRRuB+dI8bI7HdUJSoz4L6/eshgsUc2WCcYxxhlE2qMrIopX+QbuKvx0ah8bm+lL Hj5VrhP5PvywA4gKk/10ESs9YFtC6qQqAf0YEg4bzTzM0LO6CVLC9KpmBQ== =DLF5 -----END PGP SIGNATURE----- gpgsig -----BEGIN PGP SIGNATURE----- iQIzBAABCgAdFiEEo6/YBQwIrVS28WGKmmx57+YAGNkFAmMt0fwACgkQmmx57+YA GNnWHQ//SdvIYsj1/U3bZVD9YzzaHablNDz8sKoOnURLRvX9DQcFDpQuLT5dlRAK 0Z/Hc3ibGpSCTTPjtpGXvLzvjSmbkPf3F4eA0l+tlEc2mNrKpSXXCcktosqDKtRP IbEw82ImD+HPa0u6oz3nCR2fV0AZk+xYftEWLDNTLDShFSKUjIJTiQ9luykGXtUd 980abC9fC4LvcI38pYhuOtS++YBbEwoIzY+GyQbZKXx/IcS1gSk+iANsO8ABvdDt 6Hmx3ox+6lQrGwlTknd/TkuseWOl1CqkLSwltsAP+0Ijz7uR7PGGuCHReP9q4n1H A8QWZ55qskzSxwmytBsgBTlZUfy+OGqOQ387RiOh96jJFX+ANnmg4/c25PX7Vvlf i50b9BTLizkL+J82ryqf7tNLtvXg2XW89ajJ0471Vl4OFmsyg4IGjVBT5kNuBF+P 7DcW6HB2ZtFve0CwIr8o8pHW3of1k6f04z2Tl+Ls73cGcD1S9izuXzBdBSOVixyR GxFVjRDbEyta+2yQxzHLIoXx8eYGCxZm1JCiEUaxD44smF82386HfO65pCS2jXZh qJg5uCYUNZY/Y6J3bXEZSobxO2jIM5rXpC5NScDf1hAOIMeB7BuPLIeZGfRbcC3l OUR3vMG0YNo/MM6VOHE8DFcH8tnEWn9ks4NsUJ1A0DhsKXl41yg= =vQBq -----END PGP SIGNATURE----- Merge tag 'imx-drivers-6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux into arm/drivers i.MX drivers change for 6.1: - Update i.MX8MP blk-ctrl driver to handle PCIe PHY reset bit. - Add interconnect support into i.MX8MP blk-ctrl driver, so that i.MX8MP NoC can be set up properly after related power domain is up. - Add blk-ctrl support for i.MX8MP HDMI HDCP/HRV and VPU block. - Add i.MX93 SRC power domain and MEDIA blk-ctrl driver. - Update imx8m-blk-ctrl driver to use genpd_xlate_onecell. * tag 'imx-drivers-6.1' of git://git.kernel.org/pub/scm/linux/kernel/git/shawnguo/linux: (26 commits) 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 dt-bindings: arm: imx: update fsl.yaml for imx8dxl dt-bindings: firmware: add missing resource IDs for imx8dxl dt-bindings: arm: Add i.MX8M Mini Gateworks GW7904 board dt-bindings: soc: add i.MX93 mediamix blk ctrl dt-bindings: soc: add i.MX93 SRC dt-bindings: mfd: syscon: Add i.MX93 blk ctrl system registers dt-bindings: arm: fsl: Add MSC SM2S-IMX8PLUS SoM and SM2-MB-EP1 Carrier dt-bindings: arm: fsl: Add Kontron BL i.MX8MM OSM-S board dt-bindings: arm: fsl: Rename compatibles for Kontron i.MX8MM SoM/board dt-bindings: soc: imx: add i.MX8MP vpu blk ctrl dt-bindings: soc: imx: add interconnect property for i.MX8MM vpu blk ctrl dt-bindings: soc: imx: drop minItems for i.MX8MM vpu blk ctrl ... Link: https://lore.kernel.org/r/20220918092806.2152700-2-shawnguo@kernel.org Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
commit
b97e1e2faa
|
@ -554,8 +554,7 @@ properties:
|
|||
- engicam,imx6ul-isiot # Engicam Is.IoT MX6UL eMMC/NAND Starter kit
|
||||
- fsl,imx6ul-14x14-evk # i.MX6 UltraLite 14x14 EVK Board
|
||||
- karo,imx6ul-tx6ul # Ka-Ro electronics TXUL-0010 Module
|
||||
- kontron,imx6ul-n6310-som # Kontron N6310 SOM
|
||||
- kontron,imx6ul-n6311-som # Kontron N6311 SOM
|
||||
- kontron,sl-imx6ul # Kontron SL i.MX6UL SoM
|
||||
- prt,prti6g # Protonic PRTI6G Board
|
||||
- technexion,imx6ul-pico-dwarf # TechNexion i.MX6UL Pico-Dwarf
|
||||
- technexion,imx6ul-pico-hobbit # TechNexion i.MX6UL Pico-Hobbit
|
||||
|
@ -591,23 +590,17 @@ properties:
|
|||
- const: phytec,imx6ul-pcl063 # PHYTEC phyCORE-i.MX 6UL
|
||||
- const: fsl,imx6ul
|
||||
|
||||
- description: Kontron N6310 S Board
|
||||
- description: Kontron BL i.MX6UL (N631X S) Board
|
||||
items:
|
||||
- const: kontron,imx6ul-n6310-s
|
||||
- const: kontron,imx6ul-n6310-som
|
||||
- const: kontron,bl-imx6ul # Kontron BL i.MX6UL Carrier Board
|
||||
- const: kontron,sl-imx6ul # Kontron SL i.MX6UL SoM
|
||||
- const: fsl,imx6ul
|
||||
|
||||
- description: Kontron N6311 S Board
|
||||
- description: Kontron BL i.MX6UL 43 (N631X S 43) Board
|
||||
items:
|
||||
- const: kontron,imx6ul-n6311-s
|
||||
- const: kontron,imx6ul-n6311-som
|
||||
- const: fsl,imx6ul
|
||||
|
||||
- description: Kontron N6310 S 43 Board
|
||||
items:
|
||||
- const: kontron,imx6ul-n6310-s-43
|
||||
- const: kontron,imx6ul-n6310-s
|
||||
- const: kontron,imx6ul-n6310-som
|
||||
- const: kontron,bl-imx6ul-43 # Kontron BL i.MX6UL Carrier Board with 4.3" Display
|
||||
- const: kontron,bl-imx6ul # Kontron BL i.MX6UL Carrier Board
|
||||
- const: kontron,sl-imx6ul # Kontron SL i.MX6UL SoM
|
||||
- const: fsl,imx6ul
|
||||
|
||||
- description: TQ-Systems TQMa6UL1 SoM on MBa6ULx board
|
||||
|
@ -637,7 +630,7 @@ properties:
|
|||
- enum:
|
||||
- fsl,imx6ull-14x14-evk # i.MX6 UltraLiteLite 14x14 EVK Board
|
||||
- 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
|
||||
- toradex,colibri-imx6ull # Colibri iMX6ULL Modules
|
||||
- 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: fsl,imx6ull
|
||||
|
||||
- description: Kontron N6411 S Board
|
||||
- description: Kontron BL i.MX6ULL (N6411 S) Board
|
||||
items:
|
||||
- const: kontron,imx6ull-n6411-s
|
||||
- const: kontron,imx6ull-n6411-som
|
||||
- const: kontron,bl-imx6ull # Kontron BL i.MX6ULL Carrier Board
|
||||
- const: kontron,sl-imx6ull # Kontron SL i.MX6ULL SoM
|
||||
- const: fsl,imx6ull
|
||||
|
||||
- description: TQ Systems TQMa6ULLx SoM on MBa6ULx board
|
||||
|
@ -825,13 +818,15 @@ properties:
|
|||
- emtrion,emcon-mx8mm-avari # emCON-MX8MM SoM on Avari Base
|
||||
- fsl,imx8mm-ddr4-evk # i.MX8MM DDR4 EVK Board
|
||||
- fsl,imx8mm-evk # i.MX8MM EVK Board
|
||||
- gateworks,imx8mm-gw7904
|
||||
- gw,imx8mm-gw71xx-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-gw7901 # i.MX8MM Gateworks Board
|
||||
- gw,imx8mm-gw7902 # 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
|
||||
- toradex,verdin-imx8mm # Verdin iMX8M Mini Modules
|
||||
- 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
|
||||
items:
|
||||
- const: kontron,imx8mm-n801x-s
|
||||
- const: kontron,imx8mm-n801x-som
|
||||
- const: kontron,imx8mm-bl
|
||||
- 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
|
||||
|
||||
- description: Toradex Boards with Verdin iMX8M Mini Modules
|
||||
|
@ -936,6 +937,13 @@ properties:
|
|||
- toradex,verdin-imx8mp-wifi # Verdin iMX8M Plus Wi-Fi / BT Modules
|
||||
- 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
|
||||
items:
|
||||
- enum:
|
||||
|
@ -1034,6 +1042,12 @@ properties:
|
|||
- toradex,colibri-imx8x # Colibri iMX8X Modules
|
||||
- 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
|
||||
items:
|
||||
- enum:
|
||||
|
|
|
@ -40,6 +40,8 @@ properties:
|
|||
- allwinner,sun50i-a64-system-controller
|
||||
- brcm,cru-clkset
|
||||
- freecom,fsg-cs2-system-controller
|
||||
- fsl,imx93-aonmix-ns-syscfg
|
||||
- fsl,imx93-wakeupmix-syscfg
|
||||
- hisilicon,dsa-subctrl
|
||||
- hisilicon,hi6220-sramctrl
|
||||
- hisilicon,pcie-sas-subctrl
|
||||
|
|
|
@ -27,25 +27,22 @@ properties:
|
|||
const: 1
|
||||
|
||||
power-domains:
|
||||
minItems: 4
|
||||
maxItems: 4
|
||||
|
||||
power-domain-names:
|
||||
items:
|
||||
- const: bus
|
||||
- const: g1
|
||||
- const: g2
|
||||
- const: h1
|
||||
maxItems: 4
|
||||
|
||||
clocks:
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
|
||||
clock-names:
|
||||
items:
|
||||
- const: g1
|
||||
- const: g2
|
||||
- const: h1
|
||||
maxItems: 3
|
||||
|
||||
interconnects:
|
||||
maxItems: 3
|
||||
|
||||
interconnect-names:
|
||||
maxItems: 3
|
||||
|
||||
required:
|
||||
- compatible
|
||||
|
@ -55,6 +52,97 @@ required:
|
|||
- clocks
|
||||
- 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
|
||||
|
||||
examples:
|
||||
|
|
|
@ -52,6 +52,15 @@ properties:
|
|||
- const: ref_266m
|
||||
- const: ref_24m
|
||||
|
||||
interconnects:
|
||||
maxItems: 3
|
||||
|
||||
interconnect-names:
|
||||
items:
|
||||
- const: hrv
|
||||
- const: lcdif-hdmi
|
||||
- const: hdcp
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
@ -48,6 +48,16 @@ properties:
|
|||
- const: usb
|
||||
- const: pcie
|
||||
|
||||
interconnects:
|
||||
maxItems: 4
|
||||
|
||||
interconnect-names:
|
||||
items:
|
||||
- const: noc-pcie
|
||||
- const: usb1
|
||||
- const: usb2
|
||||
- const: pcie
|
||||
|
||||
required:
|
||||
- compatible
|
||||
- reg
|
||||
|
|
|
@ -64,6 +64,20 @@ properties:
|
|||
- const: isp
|
||||
- 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:
|
||||
- compatible
|
||||
- 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>;
|
||||
};
|
|
@ -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>;
|
||||
};
|
||||
};
|
|
@ -20,4 +20,12 @@ config SOC_IMX8M
|
|||
support, it will provide the SoC info like SoC family,
|
||||
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
|
||||
|
|
|
@ -7,3 +7,5 @@ obj-$(CONFIG_IMX_GPCV2_PM_DOMAINS) += gpcv2.o
|
|||
obj-$(CONFIG_SOC_IMX8M) += soc-imx8m.o
|
||||
obj-$(CONFIG_SOC_IMX8M) += imx8m-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/interconnect.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
@ -37,6 +38,8 @@ struct imx8m_blk_ctrl_domain_data {
|
|||
const char *name;
|
||||
const char * const *clk_names;
|
||||
int num_clks;
|
||||
const char * const *path_names;
|
||||
int num_paths;
|
||||
const char *gpc_name;
|
||||
u32 rst_mask;
|
||||
u32 clk_mask;
|
||||
|
@ -52,13 +55,16 @@ struct imx8m_blk_ctrl_domain_data {
|
|||
};
|
||||
|
||||
#define DOMAIN_MAX_CLKS 4
|
||||
#define DOMAIN_MAX_PATHS 4
|
||||
|
||||
struct imx8m_blk_ctrl_domain {
|
||||
struct generic_pm_domain genpd;
|
||||
const struct imx8m_blk_ctrl_domain_data *data;
|
||||
struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
|
||||
struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
|
||||
struct device *power_dev;
|
||||
struct imx8m_blk_ctrl *bc;
|
||||
int num_paths;
|
||||
};
|
||||
|
||||
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)
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
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 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;
|
||||
|
||||
bc->onecell_data.num_domains = bc_data->num_domains;
|
||||
bc->onecell_data.xlate = imx8m_blk_ctrl_xlate;
|
||||
bc->onecell_data.domains =
|
||||
devm_kcalloc(dev, bc_data->num_domains,
|
||||
sizeof(struct generic_pm_domain *), GFP_KERNEL);
|
||||
|
@ -224,10 +220,29 @@ static int imx8m_blk_ctrl_probe(struct platform_device *pdev)
|
|||
int j;
|
||||
|
||||
domain->data = data;
|
||||
domain->num_paths = data->num_paths;
|
||||
|
||||
for (j = 0; j < data->num_clks; 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);
|
||||
if (ret) {
|
||||
dev_err_probe(dev, ret, "failed to get clock\n");
|
||||
|
@ -455,6 +470,46 @@ static const struct imx8m_blk_ctrl_data imx8mm_vpu_blk_ctl_dev_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,
|
||||
unsigned long action, void *data)
|
||||
{
|
||||
|
@ -650,6 +705,8 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[
|
|||
.gpc_name = "lcdif1",
|
||||
.rst_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] = {
|
||||
.name = "mediablk-isi",
|
||||
|
@ -658,6 +715,8 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[
|
|||
.gpc_name = "isi",
|
||||
.rst_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] = {
|
||||
.name = "mediablk-mipi-csi2-2",
|
||||
|
@ -675,6 +734,8 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[
|
|||
.gpc_name = "lcdif2",
|
||||
.rst_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] = {
|
||||
.name = "mediablk-isp",
|
||||
|
@ -683,6 +744,8 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[
|
|||
.gpc_name = "isp",
|
||||
.rst_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] = {
|
||||
.name = "mediablk-dwe",
|
||||
|
@ -691,6 +754,8 @@ static const struct imx8m_blk_ctrl_domain_data imx8mp_media_blk_ctl_domain_data[
|
|||
.gpc_name = "dwe",
|
||||
.rst_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] = {
|
||||
.name = "mediablk-mipi-dsi-2",
|
||||
|
@ -788,6 +853,9 @@ static const struct of_device_id imx8m_blk_ctrl_of_match[] = {
|
|||
}, {
|
||||
.compatible = "fsl,imx8mq-vpu-blk-ctrl",
|
||||
.data = &imx8mq_vpu_blk_ctl_dev_data
|
||||
}, {
|
||||
.compatible = "fsl,imx8mp-vpu-blk-ctrl",
|
||||
.data = &imx8mp_vpu_blk_ctl_dev_data
|
||||
}, {
|
||||
/* Sentinel */
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
|
@ -18,6 +19,8 @@
|
|||
#define GPR_REG0 0x0
|
||||
#define PCIE_CLOCK_MODULE_EN BIT(0)
|
||||
#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;
|
||||
|
||||
|
@ -36,17 +39,22 @@ struct imx8mp_blk_ctrl_domain_data {
|
|||
const char *name;
|
||||
const char * const *clk_names;
|
||||
int num_clks;
|
||||
const char * const *path_names;
|
||||
int num_paths;
|
||||
const char *gpc_name;
|
||||
};
|
||||
|
||||
#define DOMAIN_MAX_CLKS 2
|
||||
#define DOMAIN_MAX_PATHS 3
|
||||
|
||||
struct imx8mp_blk_ctrl_domain {
|
||||
struct generic_pm_domain genpd;
|
||||
const struct imx8mp_blk_ctrl_domain_data *data;
|
||||
struct clk_bulk_data clks[DOMAIN_MAX_CLKS];
|
||||
struct icc_bulk_data paths[DOMAIN_MAX_PATHS];
|
||||
struct device *power_dev;
|
||||
struct imx8mp_blk_ctrl *bc;
|
||||
int num_paths;
|
||||
int id;
|
||||
};
|
||||
|
||||
|
@ -75,6 +83,10 @@ static void imx8mp_hsio_blk_ctrl_power_on(struct imx8mp_blk_ctrl *bc,
|
|||
case IMX8MP_HSIOBLK_PD_PCIE:
|
||||
regmap_set_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
|
||||
break;
|
||||
case IMX8MP_HSIOBLK_PD_PCIE_PHY:
|
||||
regmap_set_bits(bc->regmap, GPR_REG0,
|
||||
PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -90,6 +102,10 @@ static void imx8mp_hsio_blk_ctrl_power_off(struct imx8mp_blk_ctrl *bc,
|
|||
case IMX8MP_HSIOBLK_PD_PCIE:
|
||||
regmap_clear_bits(bc->regmap, GPR_REG0, PCIE_CLOCK_MODULE_EN);
|
||||
break;
|
||||
case IMX8MP_HSIOBLK_PD_PCIE_PHY:
|
||||
regmap_clear_bits(bc->regmap, GPR_REG0,
|
||||
PCIE_PHY_APB_RST | PCIE_PHY_INIT_RST);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -144,6 +160,8 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hsio_domain_data[] = {
|
|||
.clk_names = (const char *[]){ "usb" },
|
||||
.num_clks = 1,
|
||||
.gpc_name = "usb",
|
||||
.path_names = (const char *[]){"usb1", "usb2"},
|
||||
.num_paths = 2,
|
||||
},
|
||||
[IMX8MP_HSIOBLK_PD_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" },
|
||||
.num_clks = 1,
|
||||
.gpc_name = "pcie",
|
||||
.path_names = (const char *[]){"noc-pcie", "pcie"},
|
||||
.num_paths = 2,
|
||||
},
|
||||
[IMX8MP_HSIOBLK_PD_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_clear_bits(bc->regmap, HDMI_TX_CONTROL0, BIT(3));
|
||||
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:
|
||||
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_CLK_CTL1, BIT(22) | BIT(24));
|
||||
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:
|
||||
break;
|
||||
}
|
||||
|
@ -322,6 +356,8 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = {
|
|||
.clk_names = (const char *[]){ "axi", "apb" },
|
||||
.num_clks = 2,
|
||||
.gpc_name = "lcdif",
|
||||
.path_names = (const char *[]){"lcdif-hdmi"},
|
||||
.num_paths = 1,
|
||||
},
|
||||
[IMX8MP_HDMIBLK_PD_PAI] = {
|
||||
.name = "hdmiblk-pai",
|
||||
|
@ -353,6 +389,22 @@ static const struct imx8mp_blk_ctrl_domain_data imx8mp_hdmi_domain_data[] = {
|
|||
.num_clks = 2,
|
||||
.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 = {
|
||||
|
@ -395,6 +447,10 @@ static int imx8mp_blk_ctrl_power_on(struct generic_pm_domain *genpd)
|
|||
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);
|
||||
|
||||
return 0;
|
||||
|
@ -434,19 +490,6 @@ static int imx8mp_blk_ctrl_power_off(struct generic_pm_domain *genpd)
|
|||
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 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;
|
||||
|
||||
bc->onecell_data.num_domains = num_domains;
|
||||
bc->onecell_data.xlate = imx8m_blk_ctrl_xlate;
|
||||
bc->onecell_data.domains =
|
||||
devm_kcalloc(dev, num_domains,
|
||||
sizeof(struct generic_pm_domain *), GFP_KERNEL);
|
||||
|
@ -510,10 +552,29 @@ static int imx8mp_blk_ctrl_probe(struct platform_device *pdev)
|
|||
int j;
|
||||
|
||||
domain->data = data;
|
||||
domain->num_paths = data->num_paths;
|
||||
|
||||
for (j = 0; j < data->num_clks; 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);
|
||||
if (ret) {
|
||||
dev_err_probe(dev, ret, "failed to get clock\n");
|
||||
|
|
|
@ -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");
|
|
@ -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");
|
|
@ -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");
|
|
@ -281,7 +281,6 @@
|
|||
#define IMX8MM_CLK_CLKOUT2_DIV 256
|
||||
#define IMX8MM_CLK_CLKOUT2 257
|
||||
|
||||
|
||||
#define IMX8MM_CLK_END 258
|
||||
|
||||
#endif
|
||||
|
|
|
@ -37,10 +37,14 @@
|
|||
#define IMX_SC_R_DC_0_BLIT2 21
|
||||
#define IMX_SC_R_DC_0_BLIT_OUT 22
|
||||
#define IMX_SC_R_PERF 23
|
||||
#define IMX_SC_R_USB_1_PHY 24
|
||||
#define IMX_SC_R_DC_0_WARP 25
|
||||
#define IMX_SC_R_V2X_MU_0 26
|
||||
#define IMX_SC_R_V2X_MU_1 27
|
||||
#define IMX_SC_R_DC_0_VIDEO0 28
|
||||
#define IMX_SC_R_DC_0_VIDEO1 29
|
||||
#define IMX_SC_R_DC_0_FRAC0 30
|
||||
#define IMX_SC_R_V2X_MU_2 31
|
||||
#define IMX_SC_R_DC_0 32
|
||||
#define IMX_SC_R_GPU_2_PID0 33
|
||||
#define IMX_SC_R_DC_0_PLL_0 34
|
||||
|
@ -49,7 +53,10 @@
|
|||
#define IMX_SC_R_DC_1_BLIT1 37
|
||||
#define IMX_SC_R_DC_1_BLIT2 38
|
||||
#define IMX_SC_R_DC_1_BLIT_OUT 39
|
||||
#define IMX_SC_R_V2X_MU_3 40
|
||||
#define IMX_SC_R_V2X_MU_4 41
|
||||
#define IMX_SC_R_DC_1_WARP 42
|
||||
#define IMX_SC_R_SECVIO 44
|
||||
#define IMX_SC_R_DC_1_VIDEO0 45
|
||||
#define IMX_SC_R_DC_1_VIDEO1 46
|
||||
#define IMX_SC_R_DC_1_FRAC0 47
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
/* SPDX-License-Identifier: (GPL-2.0 OR MIT) */
|
||||
/*
|
||||
* Copyright 2022 NXP
|
||||
*/
|
||||
|
||||
#ifndef __DT_BINDINGS_IMX93_POWER_H__
|
||||
#define __DT_BINDINGS_IMX93_POWER_H__
|
||||
|
||||
#define IMX93_MEDIABLK_PD_MIPI_DSI 0
|
||||
#define IMX93_MEDIABLK_PD_MIPI_CSI 1
|
||||
#define IMX93_MEDIABLK_PD_PXP 2
|
||||
#define IMX93_MEDIABLK_PD_LCDIF 3
|
||||
#define IMX93_MEDIABLK_PD_ISI 4
|
||||
|
||||
#endif
|
|
@ -49,5 +49,11 @@
|
|||
#define IMX8MP_HDMIBLK_PD_TRNG 4
|
||||
#define IMX8MP_HDMIBLK_PD_HDMI_TX 5
|
||||
#define IMX8MP_HDMIBLK_PD_HDMI_TX_PHY 6
|
||||
#define IMX8MP_HDMIBLK_PD_HDCP 7
|
||||
#define IMX8MP_HDMIBLK_PD_HRV 8
|
||||
|
||||
#define IMX8MP_VPUBLK_PD_G1 0
|
||||
#define IMX8MP_VPUBLK_PD_G2 1
|
||||
#define IMX8MP_VPUBLK_PD_VC8000E 2
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in New Issue