power-domains:

- add support for new power domain driver.
 - add support for mt8183 and mt8192
 
 devapc:
 - add support for the devapc device found on mt6779 to identify of
   malicious bus accesses from a controller to a device
 
 mmsys:
 - move DDP routing IDs into the driver
 
 cmdq:
 - drop timeout handler support as not usefull
 
 scpsys:
 - print warning on theoretical error
 -----BEGIN PGP SIGNATURE-----
 
 iQJLBAABCAA1FiEEUdvKHhzqrUYPB/u8L21+TfbCqH4FAl/EDZoXHG1hdHRoaWFz
 LmJnZ0BnbWFpbC5jb20ACgkQL21+TfbCqH7zEw/8DW7/eqjvP71tJG7qvlhASy1R
 S6YYrnmx8R/A41um3tAYcfgPCm+xPGeqIsBRFWOxmLmw71ebu/EQyuuvGFx6qY2c
 p4pZdafkM7IrNYD0JLpLIpFZAqikPtz2WefzPqHD8WTaGKqQ+neoNWS2twVIpiTz
 N0wpkl3BuFTcjirDaeME8BY31UxhP2E9LK+IMSZmfnhfIJjgw4/A5/pbAVM+EUhC
 LqqSRn1uGmvibAQXVFDyhk/tLZJCe4X3OLkgXwlTKCIcd0qpVCWT+2xoxIV7r30G
 Ldddt8LwVVuebSaY5NTtQQy4t0ZBx79a+17eTDt/+cIc6k3F5Bucnl/dKssWS9dO
 /lXs5jpJvcmeWNgvYhbGhXj42CrekY3I3aZpZnJDCl6dG74NWbWSe+xAxxH417s0
 9t5cNDLW9L21NhkMGXFX+a8LbMiT1s+UeM4UXHnCGHX2Mx2cQoP/ATr7d5ED+Jr6
 3xdKO6r7YnJANZ4UAvIVhbbak2pMT5BUhU/jM1LAMZ/JkEscfjyvdOyorAMFR5Ka
 hUFcfaJJ0hcVkfSEbF0LPsoNI8XHIY1i0bar4ZIKYr6asTgtVyHHh/BHfO25LW+4
 T4Vpr3ugj7znuomFuPCYXfy/3NN1TlFWfTtI8GwGCAdX6gihdoJ/We8KRqoCWrdp
 bEefKIDJxFWMNMA48j0=
 =mQNT
 -----END PGP SIGNATURE-----

Merge tag 'v5.10-next-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/matthias.bgg/linux into arm/drivers

power-domains:
- add support for new power domain driver.
- add support for mt8183 and mt8192

devapc:
- add support for the devapc device found on mt6779 to identify of
  malicious bus accesses from a controller to a device

mmsys:
- move DDP routing IDs into the driver

cmdq:
- drop timeout handler support as not usefull

scpsys:
- print warning on theoretical error

* tag 'v5.10-next-soc' of git://git.kernel.org/pub/scm/linux/kernel/git/matthias.bgg/linux: (21 commits)
  soc: mediatek: mmsys: Use devm_platform_ioremap_resource()
  soc / drm: mediatek: Move DDP component defines into mtk-mmsys.h
  soc: mediatek: add mt6779 devapc driver
  dt-bindings: devapc: add bindings for mtk-devapc
  soc / drm: mediatek: cmdq: Remove timeout handler in helper function
  soc: mediatek: pm-domains: Add support for mt8192
  soc: mediatek: pm-domains: Add default power off flag
  soc: mediatek: pm-domains: Add support for mt8183
  soc: mediatek: pm-domains: Allow bus protection to ignore clear ack
  soc: mediatek: pm-domains: Add subsystem clocks
  soc: mediatek: pm-domains: Add extra sram control
  soc: mediatek: pm-domains: Add SMI block as bus protection block
  soc: mediatek: pm_domains: Make bus protection generic
  soc: mediatek: pm-domains: Add bus protection protocol
  soc: mediatek: Add MediaTek SCPSYS power domains
  dt-bindings: power: Add MT8192 power domains
  dt-bindings: power: Add MT8183 power domains
  dt-bindings: power: Add bindings for the Mediatek SCPSYS power domains controller
  mfd: syscon: Add syscon_regmap_lookup_by_phandle_optional() function.
  MAINTAINERS: change mediatek wiki page
  ...

Link: https://lore.kernel.org/r/b03fe343-e183-c6f3-f2dc-4c58aae3146b@gmail.com
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Arnd Bergmann 2020-11-30 17:22:02 +01:00
commit bbecede458
24 changed files with 2243 additions and 100 deletions

View file

@ -0,0 +1,293 @@
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/power/mediatek,power-controller.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title: Mediatek Power Domains Controller
maintainers:
- Weiyi Lu <weiyi.lu@mediatek.com>
- Matthias Brugger <mbrugger@suse.com>
description: |
Mediatek processors include support for multiple power domains which can be
powered up/down by software based on different application scenes to save power.
IP cores belonging to a power domain should contain a 'power-domains'
property that is a phandle for SCPSYS node representing the domain.
properties:
$nodename:
const: power-controller
compatible:
enum:
- mediatek,mt8173-power-controller
- mediatek,mt8183-power-controller
- mediatek,mt8192-power-controller
'#power-domain-cells':
const: 1
'#address-cells':
const: 1
'#size-cells':
const: 0
patternProperties:
"^power-domain@[0-9a-f]+$":
type: object
description: |
Represents the power domains within the power controller node as documented
in Documentation/devicetree/bindings/power/power-domain.yaml.
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:
description: |
Power domain index. Valid values are defined in:
"include/dt-bindings/power/mt8173-power.h" - for MT8173 type power domain.
"include/dt-bindings/power/mt8183-power.h" - for MT8183 type power domain.
"include/dt-bindings/power/mt8192-power.h" - for MT8192 type power domain.
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.
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.
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.
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:
- reg
additionalProperties: false
required:
- compatible
additionalProperties: false
examples:
- |
#include <dt-bindings/clock/mt8173-clk.h>
#include <dt-bindings/power/mt8173-power.h>
soc {
#address-cells = <2>;
#size-cells = <2>;
scpsys: syscon@10006000 {
compatible = "syscon", "simple-mfd";
reg = <0 0x10006000 0 0x1000>;
spm: power-controller {
compatible = "mediatek,mt8173-power-controller";
#address-cells = <1>;
#size-cells = <0>;
#power-domain-cells = <1>;
/* power domains of the SoC */
power-domain@MT8173_POWER_DOMAIN_VDEC {
reg = <MT8173_POWER_DOMAIN_VDEC>;
clocks = <&topckgen CLK_TOP_MM_SEL>;
clock-names = "mm";
#power-domain-cells = <0>;
};
power-domain@MT8173_POWER_DOMAIN_VENC {
reg = <MT8173_POWER_DOMAIN_VENC>;
clocks = <&topckgen CLK_TOP_MM_SEL>,
<&topckgen CLK_TOP_VENC_SEL>;
clock-names = "mm", "venc";
#power-domain-cells = <0>;
};
power-domain@MT8173_POWER_DOMAIN_ISP {
reg = <MT8173_POWER_DOMAIN_ISP>;
clocks = <&topckgen CLK_TOP_MM_SEL>;
clock-names = "mm";
#power-domain-cells = <0>;
};
power-domain@MT8173_POWER_DOMAIN_MM {
reg = <MT8173_POWER_DOMAIN_MM>;
clocks = <&topckgen CLK_TOP_MM_SEL>;
clock-names = "mm";
#power-domain-cells = <0>;
mediatek,infracfg = <&infracfg>;
};
power-domain@MT8173_POWER_DOMAIN_VENC_LT {
reg = <MT8173_POWER_DOMAIN_VENC_LT>;
clocks = <&topckgen CLK_TOP_MM_SEL>,
<&topckgen CLK_TOP_VENC_LT_SEL>;
clock-names = "mm", "venclt";
#power-domain-cells = <0>;
};
power-domain@MT8173_POWER_DOMAIN_AUDIO {
reg = <MT8173_POWER_DOMAIN_AUDIO>;
#power-domain-cells = <0>;
};
power-domain@MT8173_POWER_DOMAIN_USB {
reg = <MT8173_POWER_DOMAIN_USB>;
#power-domain-cells = <0>;
};
power-domain@MT8173_POWER_DOMAIN_MFG_ASYNC {
reg = <MT8173_POWER_DOMAIN_MFG_ASYNC>;
clocks = <&clk26m>;
clock-names = "mfg";
#address-cells = <1>;
#size-cells = <0>;
#power-domain-cells = <1>;
power-domain@MT8173_POWER_DOMAIN_MFG_2D {
reg = <MT8173_POWER_DOMAIN_MFG_2D>;
#address-cells = <1>;
#size-cells = <0>;
#power-domain-cells = <1>;
power-domain@MT8173_POWER_DOMAIN_MFG {
reg = <MT8173_POWER_DOMAIN_MFG>;
#power-domain-cells = <0>;
mediatek,infracfg = <&infracfg>;
};
};
};
};
};
};

View file

@ -0,0 +1,58 @@
# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
# # Copyright 2020 MediaTek Inc.
%YAML 1.2
---
$id: "http://devicetree.org/schemas/soc/mediatek/devapc.yaml#"
$schema: "http://devicetree.org/meta-schemas/core.yaml#"
title: MediaTek Device Access Permission Control driver
description: |
MediaTek bus fabric provides TrustZone security support and data
protection to prevent slaves from being accessed by unexpected masters.
The security violation is logged and sent to the processor for further
analysis and countermeasures.
maintainers:
- Neal Liu <neal.liu@mediatek.com>
properties:
compatible:
enum:
- mediatek,mt6779-devapc
reg:
description: The base address of devapc register bank
maxItems: 1
interrupts:
description: A single interrupt specifier
maxItems: 1
clocks:
description: Contains module clock source and clock names
maxItems: 1
clock-names:
description: Names of the clocks list in clocks property
maxItems: 1
required:
- compatible
- reg
- interrupts
- clocks
- clock-names
examples:
- |
#include <dt-bindings/interrupt-controller/arm-gic.h>
#include <dt-bindings/clock/mt6779-clk.h>
devapc: devapc@10207000 {
compatible = "mediatek,mt6779-devapc";
reg = <0x10207000 0x1000>;
interrupts = <GIC_SPI 168 IRQ_TYPE_LEVEL_LOW>;
clocks = <&infracfg_ao CLK_INFRA_DEVICE_APC>;
clock-names = "devapc-infra-clock";
};

View file

@ -2067,7 +2067,7 @@ M: Matthias Brugger <matthias.bgg@gmail.com>
L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
L: linux-mediatek@lists.infradead.org (moderated for non-subscribers)
S: Maintained
W: https://mtk.bcnfs.org/
W: https://mtk.wiki.kernel.org/
C: irc://chat.freenode.net/linux-mediatek
F: arch/arm/boot/dts/mt6*
F: arch/arm/boot/dts/mt7*

View file

@ -824,8 +824,7 @@ int mtk_drm_crtc_create(struct drm_device *drm_dev,
#if IS_REACHABLE(CONFIG_MTK_CMDQ)
mtk_crtc->cmdq_client =
cmdq_mbox_create(mtk_crtc->mmsys_dev,
drm_crtc_index(&mtk_crtc->base),
2000);
drm_crtc_index(&mtk_crtc->base));
if (IS_ERR(mtk_crtc->cmdq_client)) {
dev_dbg(dev, "mtk_crtc %d failed to create mailbox client, writing register by CPU now\n",
drm_crtc_index(&mtk_crtc->base));

View file

@ -7,6 +7,7 @@
#define MTK_DRM_DDP_COMP_H
#include <linux/io.h>
#include <linux/soc/mediatek/mtk-mmsys.h>
struct device;
struct device_node;
@ -35,39 +36,6 @@ enum mtk_ddp_comp_type {
MTK_DDP_COMP_TYPE_MAX,
};
enum mtk_ddp_comp_id {
DDP_COMPONENT_AAL0,
DDP_COMPONENT_AAL1,
DDP_COMPONENT_BLS,
DDP_COMPONENT_CCORR,
DDP_COMPONENT_COLOR0,
DDP_COMPONENT_COLOR1,
DDP_COMPONENT_DITHER,
DDP_COMPONENT_DPI0,
DDP_COMPONENT_DPI1,
DDP_COMPONENT_DSI0,
DDP_COMPONENT_DSI1,
DDP_COMPONENT_DSI2,
DDP_COMPONENT_DSI3,
DDP_COMPONENT_GAMMA,
DDP_COMPONENT_OD0,
DDP_COMPONENT_OD1,
DDP_COMPONENT_OVL0,
DDP_COMPONENT_OVL_2L0,
DDP_COMPONENT_OVL_2L1,
DDP_COMPONENT_OVL1,
DDP_COMPONENT_PWM0,
DDP_COMPONENT_PWM1,
DDP_COMPONENT_PWM2,
DDP_COMPONENT_RDMA0,
DDP_COMPONENT_RDMA1,
DDP_COMPONENT_RDMA2,
DDP_COMPONENT_UFOE,
DDP_COMPONENT_WDMA0,
DDP_COMPONENT_WDMA1,
DDP_COMPONENT_ID_MAX,
};
struct mtk_ddp_comp;
struct cmdq_pkt;
struct mtk_ddp_comp_funcs {

View file

@ -255,6 +255,24 @@ struct regmap *syscon_regmap_lookup_by_phandle_args(struct device_node *np,
}
EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle_args);
/*
* It behaves the same as syscon_regmap_lookup_by_phandle() except where
* there is no regmap phandle. In this case, instead of returning -ENODEV,
* the function returns NULL.
*/
struct regmap *syscon_regmap_lookup_by_phandle_optional(struct device_node *np,
const char *property)
{
struct regmap *regmap;
regmap = syscon_regmap_lookup_by_phandle(np, property);
if (IS_ERR(regmap) && PTR_ERR(regmap) == -ENODEV)
return NULL;
return regmap;
}
EXPORT_SYMBOL_GPL(syscon_regmap_lookup_by_phandle_optional);
static int syscon_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;

View file

@ -17,6 +17,15 @@ config MTK_CMDQ
time limitation, such as updating display configuration during the
vblank.
config MTK_DEVAPC
tristate "Mediatek Device APC Support"
help
Say yes here to enable support for Mediatek Device APC driver.
This driver is mainly used to handle the violation which catches
unexpected transaction.
The violation information is logged for further analysis or
countermeasures.
config MTK_INFRACFG
bool "MediaTek INFRACFG Support"
select REGMAP
@ -44,6 +53,18 @@ config MTK_SCPSYS
Say yes here to add support for the MediaTek SCPSYS power domain
driver.
config MTK_SCPSYS_PM_DOMAINS
bool "MediaTek SCPSYS generic power domain"
default ARCH_MEDIATEK
depends on PM
select PM_GENERIC_DOMAINS
select REGMAP
help
Say y here to enable power domain support.
In order to meet high performance and low power requirements, the System
Control Processor System (SCPSYS) has several power management related
tasks in the system.
config MTK_MMSYS
bool "MediaTek MMSYS Support"
default ARCH_MEDIATEK

View file

@ -1,6 +1,8 @@
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_MTK_CMDQ) += mtk-cmdq-helper.o
obj-$(CONFIG_MTK_DEVAPC) += mtk-devapc.o
obj-$(CONFIG_MTK_INFRACFG) += mtk-infracfg.o
obj-$(CONFIG_MTK_PMIC_WRAP) += mtk-pmic-wrap.o
obj-$(CONFIG_MTK_SCPSYS) += mtk-scpsys.o
obj-$(CONFIG_MTK_SCPSYS_PM_DOMAINS) += mtk-pm-domains.o
obj-$(CONFIG_MTK_MMSYS) += mtk-mmsys.o

View file

@ -0,0 +1,94 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __SOC_MEDIATEK_MT8173_PM_DOMAINS_H
#define __SOC_MEDIATEK_MT8173_PM_DOMAINS_H
#include "mtk-pm-domains.h"
#include <dt-bindings/power/mt8173-power.h>
/*
* MT8173 power domain support
*/
static const struct scpsys_domain_data scpsys_domain_data_mt8173[] = {
[MT8173_POWER_DOMAIN_VDEC] = {
.sta_mask = PWR_STATUS_VDEC,
.ctl_offs = SPM_VDE_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
},
[MT8173_POWER_DOMAIN_VENC] = {
.sta_mask = PWR_STATUS_VENC,
.ctl_offs = SPM_VEN_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
},
[MT8173_POWER_DOMAIN_ISP] = {
.sta_mask = PWR_STATUS_ISP,
.ctl_offs = SPM_ISP_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
},
[MT8173_POWER_DOMAIN_MM] = {
.sta_mask = PWR_STATUS_DISP,
.ctl_offs = SPM_DIS_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.bp_infracfg = {
BUS_PROT_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MM_M0 |
MT8173_TOP_AXI_PROT_EN_MM_M1),
},
},
[MT8173_POWER_DOMAIN_VENC_LT] = {
.sta_mask = PWR_STATUS_VENC_LT,
.ctl_offs = SPM_VEN2_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
},
[MT8173_POWER_DOMAIN_AUDIO] = {
.sta_mask = PWR_STATUS_AUDIO,
.ctl_offs = SPM_AUDIO_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
},
[MT8173_POWER_DOMAIN_USB] = {
.sta_mask = PWR_STATUS_USB,
.ctl_offs = SPM_USB_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
.caps = MTK_SCPD_ACTIVE_WAKEUP,
},
[MT8173_POWER_DOMAIN_MFG_ASYNC] = {
.sta_mask = PWR_STATUS_MFG_ASYNC,
.ctl_offs = SPM_MFG_ASYNC_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = 0,
},
[MT8173_POWER_DOMAIN_MFG_2D] = {
.sta_mask = PWR_STATUS_MFG_2D,
.ctl_offs = SPM_MFG_2D_PWR_CON,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
},
[MT8173_POWER_DOMAIN_MFG] = {
.sta_mask = PWR_STATUS_MFG,
.ctl_offs = SPM_MFG_PWR_CON,
.sram_pdn_bits = GENMASK(13, 8),
.sram_pdn_ack_bits = GENMASK(21, 16),
.bp_infracfg = {
BUS_PROT_UPDATE_TOPAXI(MT8173_TOP_AXI_PROT_EN_MFG_S |
MT8173_TOP_AXI_PROT_EN_MFG_M0 |
MT8173_TOP_AXI_PROT_EN_MFG_M1 |
MT8173_TOP_AXI_PROT_EN_MFG_SNOOP_OUT),
},
},
};
static const struct scpsys_soc_data mt8173_scpsys_data = {
.domains_data = scpsys_domain_data_mt8173,
.num_domains = ARRAY_SIZE(scpsys_domain_data_mt8173),
.pwr_sta_offs = SPM_PWR_STATUS,
.pwr_sta2nd_offs = SPM_PWR_STATUS_2ND,
};
#endif /* __SOC_MEDIATEK_MT8173_PM_DOMAINS_H */

View file

@ -0,0 +1,221 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __SOC_MEDIATEK_MT8183_PM_DOMAINS_H
#define __SOC_MEDIATEK_MT8183_PM_DOMAINS_H
#include "mtk-pm-domains.h"
#include <dt-bindings/power/mt8183-power.h>
/*
* MT8183 power domain support
*/
static const struct scpsys_domain_data scpsys_domain_data_mt8183[] = {
[MT8183_POWER_DOMAIN_AUDIO] = {
.sta_mask = PWR_STATUS_AUDIO,
.ctl_offs = 0x0314,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
},
[MT8183_POWER_DOMAIN_CONN] = {
.sta_mask = PWR_STATUS_CONN,
.ctl_offs = 0x032c,
.sram_pdn_bits = 0,
.sram_pdn_ack_bits = 0,
.bp_infracfg = {
BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_CONN, MT8183_TOP_AXI_PROT_EN_SET,
MT8183_TOP_AXI_PROT_EN_CLR, MT8183_TOP_AXI_PROT_EN_STA1),
},
},
[MT8183_POWER_DOMAIN_MFG_ASYNC] = {
.sta_mask = PWR_STATUS_MFG_ASYNC,
.ctl_offs = 0x0334,
.sram_pdn_bits = 0,
.sram_pdn_ack_bits = 0,
},
[MT8183_POWER_DOMAIN_MFG] = {
.sta_mask = PWR_STATUS_MFG,
.ctl_offs = 0x0338,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
},
[MT8183_POWER_DOMAIN_MFG_CORE0] = {
.sta_mask = BIT(7),
.ctl_offs = 0x034c,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
},
[MT8183_POWER_DOMAIN_MFG_CORE1] = {
.sta_mask = BIT(20),
.ctl_offs = 0x0310,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
},
[MT8183_POWER_DOMAIN_MFG_2D] = {
.sta_mask = PWR_STATUS_MFG_2D,
.ctl_offs = 0x0348,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.bp_infracfg = {
BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_1_MFG, MT8183_TOP_AXI_PROT_EN_1_SET,
MT8183_TOP_AXI_PROT_EN_1_CLR, MT8183_TOP_AXI_PROT_EN_STA1_1),
BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MFG, MT8183_TOP_AXI_PROT_EN_SET,
MT8183_TOP_AXI_PROT_EN_CLR, MT8183_TOP_AXI_PROT_EN_STA1),
},
},
[MT8183_POWER_DOMAIN_DISP] = {
.sta_mask = PWR_STATUS_DISP,
.ctl_offs = 0x030c,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.bp_infracfg = {
BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_1_DISP, MT8183_TOP_AXI_PROT_EN_1_SET,
MT8183_TOP_AXI_PROT_EN_1_CLR, MT8183_TOP_AXI_PROT_EN_STA1_1),
BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_DISP, MT8183_TOP_AXI_PROT_EN_SET,
MT8183_TOP_AXI_PROT_EN_CLR, MT8183_TOP_AXI_PROT_EN_STA1),
},
.bp_smi = {
BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_DISP,
MT8183_SMI_COMMON_CLAMP_EN_SET,
MT8183_SMI_COMMON_CLAMP_EN_CLR,
MT8183_SMI_COMMON_CLAMP_EN),
},
},
[MT8183_POWER_DOMAIN_CAM] = {
.sta_mask = BIT(25),
.ctl_offs = 0x0344,
.sram_pdn_bits = GENMASK(9, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
.bp_infracfg = {
BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MM_CAM, MT8183_TOP_AXI_PROT_EN_MM_SET,
MT8183_TOP_AXI_PROT_EN_MM_CLR, MT8183_TOP_AXI_PROT_EN_MM_STA1),
BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_CAM, MT8183_TOP_AXI_PROT_EN_SET,
MT8183_TOP_AXI_PROT_EN_CLR, MT8183_TOP_AXI_PROT_EN_STA1),
BUS_PROT_WR_IGN(MT8183_TOP_AXI_PROT_EN_MM_CAM_2ND,
MT8183_TOP_AXI_PROT_EN_MM_SET,
MT8183_TOP_AXI_PROT_EN_MM_CLR,
MT8183_TOP_AXI_PROT_EN_MM_STA1),
},
.bp_smi = {
BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_CAM,
MT8183_SMI_COMMON_CLAMP_EN_SET,
MT8183_SMI_COMMON_CLAMP_EN_CLR,
MT8183_SMI_COMMON_CLAMP_EN),
},
},
[MT8183_POWER_DOMAIN_ISP] = {
.sta_mask = PWR_STATUS_ISP,
.ctl_offs = 0x0308,
.sram_pdn_bits = GENMASK(9, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
.bp_infracfg = {
BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MM_ISP,
MT8183_TOP_AXI_PROT_EN_MM_SET,
MT8183_TOP_AXI_PROT_EN_MM_CLR,
MT8183_TOP_AXI_PROT_EN_MM_STA1),
BUS_PROT_WR_IGN(MT8183_TOP_AXI_PROT_EN_MM_ISP_2ND,
MT8183_TOP_AXI_PROT_EN_MM_SET,
MT8183_TOP_AXI_PROT_EN_MM_CLR,
MT8183_TOP_AXI_PROT_EN_MM_STA1),
},
.bp_smi = {
BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_ISP,
MT8183_SMI_COMMON_CLAMP_EN_SET,
MT8183_SMI_COMMON_CLAMP_EN_CLR,
MT8183_SMI_COMMON_CLAMP_EN),
},
},
[MT8183_POWER_DOMAIN_VDEC] = {
.sta_mask = BIT(31),
.ctl_offs = 0x0300,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.bp_smi = {
BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_VDEC,
MT8183_SMI_COMMON_CLAMP_EN_SET,
MT8183_SMI_COMMON_CLAMP_EN_CLR,
MT8183_SMI_COMMON_CLAMP_EN),
},
},
[MT8183_POWER_DOMAIN_VENC] = {
.sta_mask = PWR_STATUS_VENC,
.ctl_offs = 0x0304,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(15, 12),
.bp_smi = {
BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_VENC,
MT8183_SMI_COMMON_CLAMP_EN_SET,
MT8183_SMI_COMMON_CLAMP_EN_CLR,
MT8183_SMI_COMMON_CLAMP_EN),
},
},
[MT8183_POWER_DOMAIN_VPU_TOP] = {
.sta_mask = BIT(26),
.ctl_offs = 0x0324,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.bp_infracfg = {
BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MM_VPU_TOP,
MT8183_TOP_AXI_PROT_EN_MM_SET,
MT8183_TOP_AXI_PROT_EN_MM_CLR,
MT8183_TOP_AXI_PROT_EN_MM_STA1),
BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_VPU_TOP,
MT8183_TOP_AXI_PROT_EN_SET,
MT8183_TOP_AXI_PROT_EN_CLR,
MT8183_TOP_AXI_PROT_EN_STA1),
BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MM_VPU_TOP_2ND,
MT8183_TOP_AXI_PROT_EN_MM_SET,
MT8183_TOP_AXI_PROT_EN_MM_CLR,
MT8183_TOP_AXI_PROT_EN_MM_STA1),
},
.bp_smi = {
BUS_PROT_WR(MT8183_SMI_COMMON_SMI_CLAMP_VPU_TOP,
MT8183_SMI_COMMON_CLAMP_EN_SET,
MT8183_SMI_COMMON_CLAMP_EN_CLR,
MT8183_SMI_COMMON_CLAMP_EN),
},
},
[MT8183_POWER_DOMAIN_VPU_CORE0] = {
.sta_mask = BIT(27),
.ctl_offs = 0x33c,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
.bp_infracfg = {
BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE0,
MT8183_TOP_AXI_PROT_EN_MCU_SET,
MT8183_TOP_AXI_PROT_EN_MCU_CLR,
MT8183_TOP_AXI_PROT_EN_MCU_STA1),
BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE0_2ND,
MT8183_TOP_AXI_PROT_EN_MCU_SET,
MT8183_TOP_AXI_PROT_EN_MCU_CLR,
MT8183_TOP_AXI_PROT_EN_MCU_STA1),
},
.caps = MTK_SCPD_SRAM_ISO,
},
[MT8183_POWER_DOMAIN_VPU_CORE1] = {
.sta_mask = BIT(28),
.ctl_offs = 0x0340,
.sram_pdn_bits = GENMASK(11, 8),
.sram_pdn_ack_bits = GENMASK(13, 12),
.bp_infracfg = {
BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE1,
MT8183_TOP_AXI_PROT_EN_MCU_SET,
MT8183_TOP_AXI_PROT_EN_MCU_CLR,
MT8183_TOP_AXI_PROT_EN_MCU_STA1),
BUS_PROT_WR(MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE1_2ND,
MT8183_TOP_AXI_PROT_EN_MCU_SET,
MT8183_TOP_AXI_PROT_EN_MCU_CLR,
MT8183_TOP_AXI_PROT_EN_MCU_STA1),
},
.caps = MTK_SCPD_SRAM_ISO,
},
};
static const struct scpsys_soc_data mt8183_scpsys_data = {
.domains_data = scpsys_domain_data_mt8183,
.num_domains = ARRAY_SIZE(scpsys_domain_data_mt8183),
.pwr_sta_offs = 0x0180,
.pwr_sta2nd_offs = 0x0184
};
#endif /* __SOC_MEDIATEK_MT8183_PM_DOMAINS_H */

View file

@ -0,0 +1,292 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __SOC_MEDIATEK_MT8192_PM_DOMAINS_H
#define __SOC_MEDIATEK_MT8192_PM_DOMAINS_H
#include "mtk-pm-domains.h"
#include <dt-bindings/power/mt8192-power.h>
/*
* MT8192 power domain support
*/
static const struct scpsys_domain_data scpsys_domain_data_mt8192[] = {
[MT8192_POWER_DOMAIN_AUDIO] = {
.sta_mask = BIT(21),
.ctl_offs = 0x0354,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.bp_infracfg = {
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_AUDIO,
MT8192_TOP_AXI_PROT_EN_2_SET,
MT8192_TOP_AXI_PROT_EN_2_CLR,
MT8192_TOP_AXI_PROT_EN_2_STA1),
},
},
[MT8192_POWER_DOMAIN_CONN] = {
.sta_mask = PWR_STATUS_CONN,
.ctl_offs = 0x0304,
.sram_pdn_bits = 0,
.sram_pdn_ack_bits = 0,
.bp_infracfg = {
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_CONN,
MT8192_TOP_AXI_PROT_EN_SET,
MT8192_TOP_AXI_PROT_EN_CLR,
MT8192_TOP_AXI_PROT_EN_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_CONN_2ND,
MT8192_TOP_AXI_PROT_EN_SET,
MT8192_TOP_AXI_PROT_EN_CLR,
MT8192_TOP_AXI_PROT_EN_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_1_CONN,
MT8192_TOP_AXI_PROT_EN_1_SET,
MT8192_TOP_AXI_PROT_EN_1_CLR,
MT8192_TOP_AXI_PROT_EN_1_STA1),
},
.caps = MTK_SCPD_KEEP_DEFAULT_OFF,
},
[MT8192_POWER_DOMAIN_MFG0] = {
.sta_mask = BIT(2),
.ctl_offs = 0x0308,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
},
[MT8192_POWER_DOMAIN_MFG1] = {
.sta_mask = BIT(3),
.ctl_offs = 0x030c,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.bp_infracfg = {
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_1_MFG1,
MT8192_TOP_AXI_PROT_EN_1_SET,
MT8192_TOP_AXI_PROT_EN_1_CLR,
MT8192_TOP_AXI_PROT_EN_1_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_MFG1,
MT8192_TOP_AXI_PROT_EN_2_SET,
MT8192_TOP_AXI_PROT_EN_2_CLR,
MT8192_TOP_AXI_PROT_EN_2_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MFG1,
MT8192_TOP_AXI_PROT_EN_SET,
MT8192_TOP_AXI_PROT_EN_CLR,
MT8192_TOP_AXI_PROT_EN_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_MFG1_2ND,
MT8192_TOP_AXI_PROT_EN_2_SET,
MT8192_TOP_AXI_PROT_EN_2_CLR,
MT8192_TOP_AXI_PROT_EN_2_STA1),
},
},
[MT8192_POWER_DOMAIN_MFG2] = {
.sta_mask = BIT(4),
.ctl_offs = 0x0310,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
},
[MT8192_POWER_DOMAIN_MFG3] = {
.sta_mask = BIT(5),
.ctl_offs = 0x0314,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
},
[MT8192_POWER_DOMAIN_MFG4] = {
.sta_mask = BIT(6),
.ctl_offs = 0x0318,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
},
[MT8192_POWER_DOMAIN_MFG5] = {
.sta_mask = BIT(7),
.ctl_offs = 0x031c,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
},
[MT8192_POWER_DOMAIN_MFG6] = {
.sta_mask = BIT(8),
.ctl_offs = 0x0320,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
},
[MT8192_POWER_DOMAIN_DISP] = {
.sta_mask = BIT(20),
.ctl_offs = 0x0350,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.bp_infracfg = {
BUS_PROT_WR_IGN(MT8192_TOP_AXI_PROT_EN_MM_DISP,
MT8192_TOP_AXI_PROT_EN_MM_SET,
MT8192_TOP_AXI_PROT_EN_MM_CLR,
MT8192_TOP_AXI_PROT_EN_MM_STA1),
BUS_PROT_WR_IGN(MT8192_TOP_AXI_PROT_EN_MM_2_DISP,
MT8192_TOP_AXI_PROT_EN_MM_2_SET,
MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_DISP,
MT8192_TOP_AXI_PROT_EN_SET,
MT8192_TOP_AXI_PROT_EN_CLR,
MT8192_TOP_AXI_PROT_EN_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_DISP_2ND,
MT8192_TOP_AXI_PROT_EN_MM_SET,
MT8192_TOP_AXI_PROT_EN_MM_CLR,
MT8192_TOP_AXI_PROT_EN_MM_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_DISP_2ND,
MT8192_TOP_AXI_PROT_EN_MM_2_SET,
MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
},
},
[MT8192_POWER_DOMAIN_IPE] = {
.sta_mask = BIT(14),
.ctl_offs = 0x0338,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.bp_infracfg = {
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_IPE,
MT8192_TOP_AXI_PROT_EN_MM_SET,
MT8192_TOP_AXI_PROT_EN_MM_CLR,
MT8192_TOP_AXI_PROT_EN_MM_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_IPE_2ND,
MT8192_TOP_AXI_PROT_EN_MM_SET,
MT8192_TOP_AXI_PROT_EN_MM_CLR,
MT8192_TOP_AXI_PROT_EN_MM_STA1),
},
},
[MT8192_POWER_DOMAIN_ISP] = {
.sta_mask = BIT(12),
.ctl_offs = 0x0330,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.bp_infracfg = {
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_ISP,
MT8192_TOP_AXI_PROT_EN_MM_2_SET,
MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_ISP_2ND,
MT8192_TOP_AXI_PROT_EN_MM_2_SET,
MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
},
},
[MT8192_POWER_DOMAIN_ISP2] = {
.sta_mask = BIT(13),
.ctl_offs = 0x0334,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.bp_infracfg = {
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_ISP2,
MT8192_TOP_AXI_PROT_EN_MM_SET,
MT8192_TOP_AXI_PROT_EN_MM_CLR,
MT8192_TOP_AXI_PROT_EN_MM_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_ISP2_2ND,
MT8192_TOP_AXI_PROT_EN_MM_SET,
MT8192_TOP_AXI_PROT_EN_MM_CLR,
MT8192_TOP_AXI_PROT_EN_MM_STA1),
},
},
[MT8192_POWER_DOMAIN_MDP] = {
.sta_mask = BIT(19),
.ctl_offs = 0x034c,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.bp_infracfg = {
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_MDP,
MT8192_TOP_AXI_PROT_EN_MM_2_SET,
MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_2_MDP_2ND,
MT8192_TOP_AXI_PROT_EN_MM_2_SET,
MT8192_TOP_AXI_PROT_EN_MM_2_CLR,
MT8192_TOP_AXI_PROT_EN_MM_2_STA1),
},
},
[MT8192_POWER_DOMAIN_VENC] = {
.sta_mask = BIT(17),
.ctl_offs = 0x0344,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.bp_infracfg = {
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VENC,
MT8192_TOP_AXI_PROT_EN_MM_SET,
MT8192_TOP_AXI_PROT_EN_MM_CLR,
MT8192_TOP_AXI_PROT_EN_MM_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VENC_2ND,
MT8192_TOP_AXI_PROT_EN_MM_SET,
MT8192_TOP_AXI_PROT_EN_MM_CLR,
MT8192_TOP_AXI_PROT_EN_MM_STA1),
},
},
[MT8192_POWER_DOMAIN_VDEC] = {
.sta_mask = BIT(15),
.ctl_offs = 0x033c,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.bp_infracfg = {
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VDEC,
MT8192_TOP_AXI_PROT_EN_MM_SET,
MT8192_TOP_AXI_PROT_EN_MM_CLR,
MT8192_TOP_AXI_PROT_EN_MM_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_VDEC_2ND,
MT8192_TOP_AXI_PROT_EN_MM_SET,
MT8192_TOP_AXI_PROT_EN_MM_CLR,
MT8192_TOP_AXI_PROT_EN_MM_STA1),
},
},
[MT8192_POWER_DOMAIN_VDEC2] = {
.sta_mask = BIT(16),
.ctl_offs = 0x0340,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
},
[MT8192_POWER_DOMAIN_CAM] = {
.sta_mask = BIT(23),
.ctl_offs = 0x035c,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
.bp_infracfg = {
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_2_CAM,
MT8192_TOP_AXI_PROT_EN_2_SET,
MT8192_TOP_AXI_PROT_EN_2_CLR,
MT8192_TOP_AXI_PROT_EN_2_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_CAM,
MT8192_TOP_AXI_PROT_EN_MM_SET,
MT8192_TOP_AXI_PROT_EN_MM_CLR,
MT8192_TOP_AXI_PROT_EN_MM_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_1_CAM,
MT8192_TOP_AXI_PROT_EN_1_SET,
MT8192_TOP_AXI_PROT_EN_1_CLR,
MT8192_TOP_AXI_PROT_EN_1_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_MM_CAM_2ND,
MT8192_TOP_AXI_PROT_EN_MM_SET,
MT8192_TOP_AXI_PROT_EN_MM_CLR,
MT8192_TOP_AXI_PROT_EN_MM_STA1),
BUS_PROT_WR(MT8192_TOP_AXI_PROT_EN_VDNR_CAM,
MT8192_TOP_AXI_PROT_EN_VDNR_SET,
MT8192_TOP_AXI_PROT_EN_VDNR_CLR,
MT8192_TOP_AXI_PROT_EN_VDNR_STA1),
},
},
[MT8192_POWER_DOMAIN_CAM_RAWA] = {
.sta_mask = BIT(24),
.ctl_offs = 0x0360,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
},
[MT8192_POWER_DOMAIN_CAM_RAWB] = {
.sta_mask = BIT(25),
.ctl_offs = 0x0364,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
},
[MT8192_POWER_DOMAIN_CAM_RAWC] = {
.sta_mask = BIT(26),
.ctl_offs = 0x0368,
.sram_pdn_bits = GENMASK(8, 8),
.sram_pdn_ack_bits = GENMASK(12, 12),
},
};
static const struct scpsys_soc_data mt8192_scpsys_data = {
.domains_data = scpsys_domain_data_mt8192,
.num_domains = ARRAY_SIZE(scpsys_domain_data_mt8192),
.pwr_sta_offs = 0x016c,
.pwr_sta2nd_offs = 0x0170,
};
#endif /* __SOC_MEDIATEK_MT8192_PM_DOMAINS_H */

View file

@ -70,14 +70,7 @@ int cmdq_dev_get_client_reg(struct device *dev,
}
EXPORT_SYMBOL(cmdq_dev_get_client_reg);
static void cmdq_client_timeout(struct timer_list *t)
{
struct cmdq_client *client = from_timer(client, t, timer);
dev_err(client->client.dev, "cmdq timeout!\n");
}
struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 timeout)
struct cmdq_client *cmdq_mbox_create(struct device *dev, int index)
{
struct cmdq_client *client;
@ -85,12 +78,6 @@ struct cmdq_client *cmdq_mbox_create(struct device *dev, int index, u32 timeout)
if (!client)
return (struct cmdq_client *)-ENOMEM;
client->timeout_ms = timeout;
if (timeout != CMDQ_NO_TIMEOUT) {
spin_lock_init(&client->lock);
timer_setup(&client->timer, cmdq_client_timeout, 0);
}
client->pkt_cnt = 0;
client->client.dev = dev;
client->client.tx_block = false;
client->client.knows_txdone = true;
@ -112,11 +99,6 @@ EXPORT_SYMBOL(cmdq_mbox_create);
void cmdq_mbox_destroy(struct cmdq_client *client)
{
if (client->timeout_ms != CMDQ_NO_TIMEOUT) {
spin_lock(&client->lock);
del_timer_sync(&client->timer);
spin_unlock(&client->lock);
}
mbox_free_channel(client->chan);
kfree(client);
}
@ -449,18 +431,6 @@ static void cmdq_pkt_flush_async_cb(struct cmdq_cb_data data)
struct cmdq_task_cb *cb = &pkt->cb;
struct cmdq_client *client = (struct cmdq_client *)pkt->cl;
if (client->timeout_ms != CMDQ_NO_TIMEOUT) {
unsigned long flags = 0;
spin_lock_irqsave(&client->lock, flags);
if (--client->pkt_cnt == 0)
del_timer(&client->timer);
else
mod_timer(&client->timer, jiffies +
msecs_to_jiffies(client->timeout_ms));
spin_unlock_irqrestore(&client->lock, flags);
}
dma_sync_single_for_cpu(client->chan->mbox->dev, pkt->pa_base,
pkt->cmd_buf_size, DMA_TO_DEVICE);
if (cb->cb) {
@ -473,7 +443,6 @@ int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb,
void *data)
{
int err;
unsigned long flags = 0;
struct cmdq_client *client = (struct cmdq_client *)pkt->cl;
pkt->cb.cb = cb;
@ -484,14 +453,6 @@ int cmdq_pkt_flush_async(struct cmdq_pkt *pkt, cmdq_async_flush_cb cb,
dma_sync_single_for_device(client->chan->mbox->dev, pkt->pa_base,
pkt->cmd_buf_size, DMA_TO_DEVICE);
if (client->timeout_ms != CMDQ_NO_TIMEOUT) {
spin_lock_irqsave(&client->lock, flags);
if (client->pkt_cnt++ == 0)
mod_timer(&client->timer, jiffies +
msecs_to_jiffies(client->timeout_ms));
spin_unlock_irqrestore(&client->lock, flags);
}
err = mbox_send_message(client->chan, pkt);
if (err < 0)
return err;

View file

@ -0,0 +1,308 @@
// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 MediaTek Inc.
*/
#include <linux/clk.h>
#include <linux/interrupt.h>
#include <linux/iopoll.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/of_device.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#define VIO_MOD_TO_REG_IND(m) ((m) / 32)
#define VIO_MOD_TO_REG_OFF(m) ((m) % 32)
struct mtk_devapc_vio_dbgs {
union {
u32 vio_dbg0;
struct {
u32 mstid:16;
u32 dmnid:6;
u32 vio_w:1;
u32 vio_r:1;
u32 addr_h:4;
u32 resv:4;
} dbg0_bits;
};
u32 vio_dbg1;
};
struct mtk_devapc_data {
/* numbers of violation index */
u32 vio_idx_num;
/* reg offset */
u32 vio_mask_offset;
u32 vio_sta_offset;
u32 vio_dbg0_offset;
u32 vio_dbg1_offset;
u32 apc_con_offset;
u32 vio_shift_sta_offset;
u32 vio_shift_sel_offset;
u32 vio_shift_con_offset;
};
struct mtk_devapc_context {
struct device *dev;
void __iomem *infra_base;
struct clk *infra_clk;
const struct mtk_devapc_data *data;
};
static void clear_vio_status(struct mtk_devapc_context *ctx)
{
void __iomem *reg;
int i;
reg = ctx->infra_base + ctx->data->vio_sta_offset;
for (i = 0; i < VIO_MOD_TO_REG_IND(ctx->data->vio_idx_num) - 1; i++)
writel(GENMASK(31, 0), reg + 4 * i);
writel(GENMASK(VIO_MOD_TO_REG_OFF(ctx->data->vio_idx_num) - 1, 0),
reg + 4 * i);
}
static void mask_module_irq(struct mtk_devapc_context *ctx, bool mask)
{
void __iomem *reg;
u32 val;
int i;
reg = ctx->infra_base + ctx->data->vio_mask_offset;
if (mask)
val = GENMASK(31, 0);
else
val = 0;
for (i = 0; i < VIO_MOD_TO_REG_IND(ctx->data->vio_idx_num) - 1; i++)
writel(val, reg + 4 * i);
val = readl(reg + 4 * i);
if (mask)
val |= GENMASK(VIO_MOD_TO_REG_OFF(ctx->data->vio_idx_num) - 1,
0);
else
val &= ~GENMASK(VIO_MOD_TO_REG_OFF(ctx->data->vio_idx_num) - 1,
0);
writel(val, reg + 4 * i);
}
#define PHY_DEVAPC_TIMEOUT 0x10000
/*
* devapc_sync_vio_dbg - do "shift" mechansim" to get full violation information.
* shift mechanism is depends on devapc hardware design.
* Mediatek devapc set multiple slaves as a group.
* When violation is triggered, violation info is kept
* inside devapc hardware.
* Driver should do shift mechansim to sync full violation
* info to VIO_DBGs registers.
*
*/
static int devapc_sync_vio_dbg(struct mtk_devapc_context *ctx)
{
void __iomem *pd_vio_shift_sta_reg;
void __iomem *pd_vio_shift_sel_reg;
void __iomem *pd_vio_shift_con_reg;
int min_shift_group;
int ret;
u32 val;
pd_vio_shift_sta_reg = ctx->infra_base +
ctx->data->vio_shift_sta_offset;
pd_vio_shift_sel_reg = ctx->infra_base +
ctx->data->vio_shift_sel_offset;
pd_vio_shift_con_reg = ctx->infra_base +
ctx->data->vio_shift_con_offset;
/* Find the minimum shift group which has violation */
val = readl(pd_vio_shift_sta_reg);
if (!val)
return false;
min_shift_group = __ffs(val);
/* Assign the group to sync */
writel(0x1 << min_shift_group, pd_vio_shift_sel_reg);
/* Start syncing */
writel(0x1, pd_vio_shift_con_reg);
ret = readl_poll_timeout(pd_vio_shift_con_reg, val, val == 0x3, 0,
PHY_DEVAPC_TIMEOUT);
if (ret) {
dev_err(ctx->dev, "%s: Shift violation info failed\n", __func__);
return false;
}
/* Stop syncing */
writel(0x0, pd_vio_shift_con_reg);
/* Write clear */
writel(0x1 << min_shift_group, pd_vio_shift_sta_reg);
return true;
}
/*
* devapc_extract_vio_dbg - extract full violation information after doing
* shift mechanism.
*/
static void devapc_extract_vio_dbg(struct mtk_devapc_context *ctx)
{
struct mtk_devapc_vio_dbgs vio_dbgs;
void __iomem *vio_dbg0_reg;
void __iomem *vio_dbg1_reg;
vio_dbg0_reg = ctx->infra_base + ctx->data->vio_dbg0_offset;
vio_dbg1_reg = ctx->infra_base + ctx->data->vio_dbg1_offset;
vio_dbgs.vio_dbg0 = readl(vio_dbg0_reg);
vio_dbgs.vio_dbg1 = readl(vio_dbg1_reg);
/* Print violation information */
if (vio_dbgs.dbg0_bits.vio_w)
dev_info(ctx->dev, "Write Violation\n");
else if (vio_dbgs.dbg0_bits.vio_r)
dev_info(ctx->dev, "Read Violation\n");
dev_info(ctx->dev, "Bus ID:0x%x, Dom ID:0x%x, Vio Addr:0x%x\n",
vio_dbgs.dbg0_bits.mstid, vio_dbgs.dbg0_bits.dmnid,
vio_dbgs.vio_dbg1);
}
/*
* devapc_violation_irq - the devapc Interrupt Service Routine (ISR) will dump
* violation information including which master violates
* access slave.
*/
static irqreturn_t devapc_violation_irq(int irq_number, void *data)
{
struct mtk_devapc_context *ctx = data;
while (devapc_sync_vio_dbg(ctx))
devapc_extract_vio_dbg(ctx);
clear_vio_status(ctx);
return IRQ_HANDLED;
}
/*
* start_devapc - unmask slave's irq to start receiving devapc violation.
*/
static void start_devapc(struct mtk_devapc_context *ctx)
{
writel(BIT(31), ctx->infra_base + ctx->data->apc_con_offset);
mask_module_irq(ctx, false);
}
/*
* stop_devapc - mask slave's irq to stop service.
*/
static void stop_devapc(struct mtk_devapc_context *ctx)
{
mask_module_irq(ctx, true);
writel(BIT(2), ctx->infra_base + ctx->data->apc_con_offset);
}
static const struct mtk_devapc_data devapc_mt6779 = {
.vio_idx_num = 511,
.vio_mask_offset = 0x0,
.vio_sta_offset = 0x400,
.vio_dbg0_offset = 0x900,
.vio_dbg1_offset = 0x904,
.apc_con_offset = 0xF00,
.vio_shift_sta_offset = 0xF10,
.vio_shift_sel_offset = 0xF14,
.vio_shift_con_offset = 0xF20,
};
static const struct of_device_id mtk_devapc_dt_match[] = {
{
.compatible = "mediatek,mt6779-devapc",
.data = &devapc_mt6779,
}, {
},
};
static int mtk_devapc_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
struct mtk_devapc_context *ctx;
u32 devapc_irq;
int ret;
if (IS_ERR(node))
return -ENODEV;
ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
if (!ctx)
return -ENOMEM;
ctx->data = of_device_get_match_data(&pdev->dev);
ctx->dev = &pdev->dev;
ctx->infra_base = of_iomap(node, 0);
if (!ctx->infra_base)
return -EINVAL;
devapc_irq = irq_of_parse_and_map(node, 0);
if (!devapc_irq)
return -EINVAL;
ctx->infra_clk = devm_clk_get(&pdev->dev, "devapc-infra-clock");
if (IS_ERR(ctx->infra_clk))
return -EINVAL;
if (clk_prepare_enable(ctx->infra_clk))
return -EINVAL;
ret = devm_request_irq(&pdev->dev, devapc_irq, devapc_violation_irq,
IRQF_TRIGGER_NONE, "devapc", ctx);
if (ret) {
clk_disable_unprepare(ctx->infra_clk);
return ret;
}
platform_set_drvdata(pdev, ctx);
start_devapc(ctx);
return 0;
}
static int mtk_devapc_remove(struct platform_device *pdev)
{
struct mtk_devapc_context *ctx = platform_get_drvdata(pdev);
stop_devapc(ctx);
clk_disable_unprepare(ctx->infra_clk);
return 0;
}
static struct platform_driver mtk_devapc_driver = {
.probe = mtk_devapc_probe,
.remove = mtk_devapc_remove,
.driver = {
.name = "mtk-devapc",
.of_match_table = mtk_devapc_dt_match,
},
};
module_platform_driver(mtk_devapc_driver);
MODULE_DESCRIPTION("Mediatek Device APC Driver");
MODULE_AUTHOR("Neal Liu <neal.liu@mediatek.com>");
MODULE_LICENSE("GPL");

View file

@ -12,11 +12,6 @@
#define MTK_POLL_DELAY_US 10
#define MTK_POLL_TIMEOUT (jiffies_to_usecs(HZ))
#define INFRA_TOPAXI_PROTECTEN 0x0220
#define INFRA_TOPAXI_PROTECTSTA1 0x0228
#define INFRA_TOPAXI_PROTECTEN_SET 0x0260
#define INFRA_TOPAXI_PROTECTEN_CLR 0x0264
/**
* mtk_infracfg_set_bus_protection - enable bus protection
* @infracfg: The infracfg regmap

View file

@ -5,13 +5,11 @@
*/
#include <linux/device.h>
#include <linux/io.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/soc/mediatek/mtk-mmsys.h>
#include "../../gpu/drm/mediatek/mtk_drm_ddp.h"
#include "../../gpu/drm/mediatek/mtk_drm_ddp_comp.h"
#define DISP_REG_CONFIG_DISP_OVL0_MOUT_EN 0x040
#define DISP_REG_CONFIG_DISP_OVL1_MOUT_EN 0x044
#define DISP_REG_CONFIG_DISP_OD_MOUT_EN 0x048
@ -308,15 +306,12 @@ static int mtk_mmsys_probe(struct platform_device *pdev)
struct platform_device *clks;
struct platform_device *drm;
void __iomem *config_regs;
struct resource *mem;
int ret;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
config_regs = devm_ioremap_resource(dev, mem);
config_regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(config_regs)) {
ret = PTR_ERR(config_regs);
dev_err(dev, "Failed to ioremap mmsys-config resource: %d\n",
ret);
dev_err(dev, "Failed to ioremap mmsys registers: %d\n", ret);
return ret;
}

View file

@ -0,0 +1,614 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2020 Collabora Ltd.
*/
#include <linux/clk.h>
#include <linux/clk-provider.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/iopoll.h>
#include <linux/mfd/syscon.h>
#include <linux/of_clk.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
#include <linux/pm_domain.h>
#include <linux/regmap.h>
#include <linux/soc/mediatek/infracfg.h>
#include "mt8173-pm-domains.h"
#include "mt8183-pm-domains.h"
#include "mt8192-pm-domains.h"
#define MTK_POLL_DELAY_US 10
#define MTK_POLL_TIMEOUT USEC_PER_SEC
#define PWR_RST_B_BIT BIT(0)
#define PWR_ISO_BIT BIT(1)
#define PWR_ON_BIT BIT(2)
#define PWR_ON_2ND_BIT BIT(3)
#define PWR_CLK_DIS_BIT BIT(4)
#define PWR_SRAM_CLKISO_BIT BIT(5)
#define PWR_SRAM_ISOINT_B_BIT BIT(6)
struct scpsys_domain {
struct generic_pm_domain genpd;
const struct scpsys_domain_data *data;
struct scpsys *scpsys;
int num_clks;
struct clk_bulk_data *clks;
int num_subsys_clks;
struct clk_bulk_data *subsys_clks;
struct regmap *infracfg;
struct regmap *smi;
};
struct scpsys {
struct device *dev;
struct regmap *base;
const struct scpsys_soc_data *soc_data;
struct genpd_onecell_data pd_data;
struct generic_pm_domain *domains[];
};
#define to_scpsys_domain(gpd) container_of(gpd, struct scpsys_domain, genpd)
static bool scpsys_domain_is_on(struct scpsys_domain *pd)
{
struct scpsys *scpsys = pd->scpsys;
u32 status, status2;
regmap_read(scpsys->base, scpsys->soc_data->pwr_sta_offs, &status);
status &= pd->data->sta_mask;
regmap_read(scpsys->base, scpsys->soc_data->pwr_sta2nd_offs, &status2);
status2 &= pd->data->sta_mask;
/* A domain is on when both status bits are set. */
return status && status2;
}
static int scpsys_sram_enable(struct scpsys_domain *pd)
{
u32 pdn_ack = pd->data->sram_pdn_ack_bits;
struct scpsys *scpsys = pd->scpsys;
unsigned int tmp;
int ret;
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
/* Either wait until SRAM_PDN_ACK all 1 or 0 */
ret = regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
(tmp & pdn_ack) == 0, MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
if (ret < 0)
return ret;
if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_ISO)) {
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
udelay(1);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT);
}
return 0;
}
static int scpsys_sram_disable(struct scpsys_domain *pd)
{
u32 pdn_ack = pd->data->sram_pdn_ack_bits;
struct scpsys *scpsys = pd->scpsys;
unsigned int tmp;
if (MTK_SCPD_CAPS(pd, MTK_SCPD_SRAM_ISO)) {
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_CLKISO_BIT);
udelay(1);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_SRAM_ISOINT_B_BIT);
}
regmap_set_bits(scpsys->base, pd->data->ctl_offs, pd->data->sram_pdn_bits);
/* Either wait until SRAM_PDN_ACK all 1 or 0 */
return regmap_read_poll_timeout(scpsys->base, pd->data->ctl_offs, tmp,
(tmp & pdn_ack) == pdn_ack, MTK_POLL_DELAY_US,
MTK_POLL_TIMEOUT);
}
static int _scpsys_bus_protect_enable(const struct scpsys_bus_prot_data *bpd, struct regmap *regmap)
{
int i, ret;
for (i = 0; i < SPM_MAX_BUS_PROT_DATA; i++) {
u32 val, mask = bpd[i].bus_prot_mask;
if (!mask)
break;
if (bpd[i].bus_prot_reg_update)
regmap_set_bits(regmap, bpd[i].bus_prot_set, mask);
else
regmap_write(regmap, bpd[i].bus_prot_set, mask);
ret = regmap_read_poll_timeout(regmap, bpd[i].bus_prot_sta,
val, (val & mask) == mask,
MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
if (ret)
return ret;
}
return 0;
}
static int scpsys_bus_protect_enable(struct scpsys_domain *pd)
{
int ret;
ret = _scpsys_bus_protect_enable(pd->data->bp_infracfg, pd->infracfg);
if (ret)
return ret;
return _scpsys_bus_protect_enable(pd->data->bp_smi, pd->smi);
}
static int _scpsys_bus_protect_disable(const struct scpsys_bus_prot_data *bpd,
struct regmap *regmap)
{
int i, ret;
for (i = SPM_MAX_BUS_PROT_DATA - 1; i >= 0; i--) {
u32 val, mask = bpd[i].bus_prot_mask;
if (!mask)
continue;
if (bpd[i].bus_prot_reg_update)
regmap_clear_bits(regmap, bpd[i].bus_prot_clr, mask);
else
regmap_write(regmap, bpd[i].bus_prot_clr, mask);
if (bpd[i].ignore_clr_ack)
continue;
ret = regmap_read_poll_timeout(regmap, bpd[i].bus_prot_sta,
val, !(val & mask),
MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT);
if (ret)
return ret;
}
return 0;
}
static int scpsys_bus_protect_disable(struct scpsys_domain *pd)
{
int ret;
ret = _scpsys_bus_protect_disable(pd->data->bp_smi, pd->smi);
if (ret)
return ret;
return _scpsys_bus_protect_disable(pd->data->bp_infracfg, pd->infracfg);
}
static int scpsys_power_on(struct generic_pm_domain *genpd)
{
struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
struct scpsys *scpsys = pd->scpsys;
bool tmp;
int ret;
ret = clk_bulk_enable(pd->num_clks, pd->clks);
if (ret)
return ret;
/* subsys power on */
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
/* wait until PWR_ACK = 1 */
ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, tmp, MTK_POLL_DELAY_US,
MTK_POLL_TIMEOUT);
if (ret < 0)
goto err_pwr_ack;
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
ret = clk_bulk_enable(pd->num_subsys_clks, pd->subsys_clks);
if (ret)
goto err_pwr_ack;
ret = scpsys_sram_enable(pd);
if (ret < 0)
goto err_disable_subsys_clks;
ret = scpsys_bus_protect_disable(pd);
if (ret < 0)
goto err_disable_sram;
return 0;
err_disable_sram:
scpsys_sram_disable(pd);
err_disable_subsys_clks:
clk_bulk_disable(pd->num_subsys_clks, pd->subsys_clks);
err_pwr_ack:
clk_bulk_disable(pd->num_clks, pd->clks);
return ret;
}
static int scpsys_power_off(struct generic_pm_domain *genpd)
{
struct scpsys_domain *pd = container_of(genpd, struct scpsys_domain, genpd);
struct scpsys *scpsys = pd->scpsys;
bool tmp;
int ret;
ret = scpsys_bus_protect_enable(pd);
if (ret < 0)
return ret;
ret = scpsys_sram_disable(pd);
if (ret < 0)
return ret;
clk_bulk_disable(pd->num_subsys_clks, pd->subsys_clks);
/* subsys power off */
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_RST_B_BIT);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_ISO_BIT);
regmap_set_bits(scpsys->base, pd->data->ctl_offs, PWR_CLK_DIS_BIT);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_2ND_BIT);
regmap_clear_bits(scpsys->base, pd->data->ctl_offs, PWR_ON_BIT);
/* wait until PWR_ACK = 0 */
ret = readx_poll_timeout(scpsys_domain_is_on, pd, tmp, !tmp, MTK_POLL_DELAY_US,
MTK_POLL_TIMEOUT);
if (ret < 0)
return ret;
clk_bulk_disable(pd->num_clks, pd->clks);
return 0;
}
static struct
generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_node *node)
{
const struct scpsys_domain_data *domain_data;
struct scpsys_domain *pd;
struct property *prop;
const char *clk_name;
int i, ret, num_clks;
struct clk *clk;
int clk_ind = 0;
u32 id;
ret = of_property_read_u32(node, "reg", &id);
if (ret) {
dev_err(scpsys->dev, "%pOF: failed to retrieve domain id from reg: %d\n",
node, ret);
return ERR_PTR(-EINVAL);
}
if (id >= scpsys->soc_data->num_domains) {
dev_err(scpsys->dev, "%pOF: invalid domain id %d\n", node, id);
return ERR_PTR(-EINVAL);
}
domain_data = &scpsys->soc_data->domains_data[id];
if (domain_data->sta_mask == 0) {
dev_err(scpsys->dev, "%pOF: undefined domain id %d\n", node, id);
return ERR_PTR(-EINVAL);
}
pd = devm_kzalloc(scpsys->dev, sizeof(*pd), GFP_KERNEL);
if (!pd)
return ERR_PTR(-ENOMEM);
pd->data = domain_data;
pd->scpsys = scpsys;
pd->infracfg = syscon_regmap_lookup_by_phandle_optional(node, "mediatek,infracfg");
if (IS_ERR(pd->infracfg))
return ERR_CAST(pd->infracfg);
pd->smi = syscon_regmap_lookup_by_phandle_optional(node, "mediatek,smi");
if (IS_ERR(pd->smi))
return ERR_CAST(pd->smi);
num_clks = of_clk_get_parent_count(node);
if (num_clks > 0) {
/* Calculate number of subsys_clks */
of_property_for_each_string(node, "clock-names", prop, clk_name) {
char *subsys;
subsys = strchr(clk_name, '-');
if (subsys)
pd->num_subsys_clks++;
else
pd->num_clks++;
}
pd->clks = devm_kcalloc(scpsys->dev, pd->num_clks, sizeof(*pd->clks), GFP_KERNEL);
if (!pd->clks)
return ERR_PTR(-ENOMEM);
pd->subsys_clks = devm_kcalloc(scpsys->dev, pd->num_subsys_clks,
sizeof(*pd->subsys_clks), GFP_KERNEL);
if (!pd->subsys_clks)
return ERR_PTR(-ENOMEM);
}
for (i = 0; i < pd->num_clks; i++) {
clk = of_clk_get(node, i);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
dev_err_probe(scpsys->dev, ret,
"%pOF: failed to get clk at index %d: %d\n", node, i, ret);
goto err_put_clocks;
}
pd->clks[clk_ind++].clk = clk;
}
for (i = 0; i < pd->num_subsys_clks; i++) {
clk = of_clk_get(node, i + clk_ind);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
dev_err_probe(scpsys->dev, ret,
"%pOF: failed to get clk at index %d: %d\n", node,
i + clk_ind, ret);
goto err_put_subsys_clocks;
}
pd->subsys_clks[i].clk = clk;
}
ret = clk_bulk_prepare(pd->num_clks, pd->clks);
if (ret)
goto err_put_subsys_clocks;
ret = clk_bulk_prepare(pd->num_subsys_clks, pd->subsys_clks);
if (ret)
goto err_unprepare_clocks;
/*
* Initially turn on all domains to make the domains usable
* with !CONFIG_PM and to get the hardware in sync with the
* software. The unused domains will be switched off during
* late_init time.
*/
if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF)) {
if (scpsys_domain_is_on(pd))
dev_warn(scpsys->dev,
"%pOF: A default off power domain has been ON\n", node);
} else {
ret = scpsys_power_on(&pd->genpd);
if (ret < 0) {
dev_err(scpsys->dev, "%pOF: failed to power on domain: %d\n", node, ret);
goto err_unprepare_clocks;
}
}
if (scpsys->domains[id]) {
ret = -EINVAL;
dev_err(scpsys->dev,
"power domain with id %d already exists, check your device-tree\n", id);
goto err_unprepare_subsys_clocks;
}
pd->genpd.name = node->name;
pd->genpd.power_off = scpsys_power_off;
pd->genpd.power_on = scpsys_power_on;
if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF))
pm_genpd_init(&pd->genpd, NULL, true);
else
pm_genpd_init(&pd->genpd, NULL, false);
scpsys->domains[id] = &pd->genpd;
return scpsys->pd_data.domains[id];
err_unprepare_subsys_clocks:
clk_bulk_unprepare(pd->num_subsys_clks, pd->subsys_clks);
err_unprepare_clocks:
clk_bulk_unprepare(pd->num_clks, pd->clks);
err_put_subsys_clocks:
clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
err_put_clocks:
clk_bulk_put(pd->num_clks, pd->clks);
return ERR_PTR(ret);
}
static int scpsys_add_subdomain(struct scpsys *scpsys, struct device_node *parent)
{
struct generic_pm_domain *child_pd, *parent_pd;
struct device_node *child;
int ret;
for_each_child_of_node(parent, child) {
u32 id;
ret = of_property_read_u32(parent, "reg", &id);
if (ret) {
dev_err(scpsys->dev, "%pOF: failed to get parent domain id\n", child);
goto err_put_node;
}
if (!scpsys->pd_data.domains[id]) {
ret = -EINVAL;
dev_err(scpsys->dev, "power domain with id %d does not exist\n", id);
goto err_put_node;
}
parent_pd = scpsys->pd_data.domains[id];
child_pd = scpsys_add_one_domain(scpsys, child);
if (IS_ERR(child_pd)) {
ret = PTR_ERR(child_pd);
dev_err(scpsys->dev, "%pOF: failed to get child domain id\n", child);
goto err_put_node;
}
ret = pm_genpd_add_subdomain(parent_pd, child_pd);
if (ret) {
dev_err(scpsys->dev, "failed to add %s subdomain to parent %s\n",
child_pd->name, parent_pd->name);
goto err_put_node;
} else {
dev_dbg(scpsys->dev, "%s add subdomain: %s\n", parent_pd->name,
child_pd->name);
}
/* recursive call to add all subdomains */
ret = scpsys_add_subdomain(scpsys, child);
if (ret)
goto err_put_node;
}
return 0;
err_put_node:
of_node_put(child);
return ret;
}
static void scpsys_remove_one_domain(struct scpsys_domain *pd)
{
int ret;
if (scpsys_domain_is_on(pd))
scpsys_power_off(&pd->genpd);
/*
* We're in the error cleanup already, so we only complain,
* but won't emit another error on top of the original one.
*/
ret = pm_genpd_remove(&pd->genpd);
if (ret < 0)
dev_err(pd->scpsys->dev,
"failed to remove domain '%s' : %d - state may be inconsistent\n",
pd->genpd.name, ret);
clk_bulk_unprepare(pd->num_clks, pd->clks);
clk_bulk_put(pd->num_clks, pd->clks);
clk_bulk_unprepare(pd->num_subsys_clks, pd->subsys_clks);
clk_bulk_put(pd->num_subsys_clks, pd->subsys_clks);
}
static void scpsys_domain_cleanup(struct scpsys *scpsys)
{
struct generic_pm_domain *genpd;
struct scpsys_domain *pd;
int i;
for (i = scpsys->pd_data.num_domains - 1; i >= 0; i--) {
genpd = scpsys->pd_data.domains[i];
if (genpd) {
pd = to_scpsys_domain(genpd);
scpsys_remove_one_domain(pd);
}
}
}
static const struct of_device_id scpsys_of_match[] = {
{
.compatible = "mediatek,mt8173-power-controller",
.data = &mt8173_scpsys_data,
},
{
.compatible = "mediatek,mt8183-power-controller",
.data = &mt8183_scpsys_data,
},
{
.compatible = "mediatek,mt8192-power-controller",
.data = &mt8192_scpsys_data,
},
{ }
};
static int scpsys_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct device_node *np = dev->of_node;
const struct scpsys_soc_data *soc;
struct device_node *node;
struct device *parent;
struct scpsys *scpsys;
int ret;
soc = of_device_get_match_data(&pdev->dev);
if (!soc) {
dev_err(&pdev->dev, "no power controller data\n");
return -EINVAL;
}
scpsys = devm_kzalloc(dev, struct_size(scpsys, domains, soc->num_domains), GFP_KERNEL);
if (!scpsys)
return -ENOMEM;
scpsys->dev = dev;
scpsys->soc_data = soc;
scpsys->pd_data.domains = scpsys->domains;
scpsys->pd_data.num_domains = soc->num_domains;
parent = dev->parent;
if (!parent) {
dev_err(dev, "no parent for syscon devices\n");
return -ENODEV;
}
scpsys->base = syscon_node_to_regmap(parent->of_node);
if (IS_ERR(scpsys->base)) {
dev_err(dev, "no regmap available\n");
return PTR_ERR(scpsys->base);
}
ret = -ENODEV;
for_each_available_child_of_node(np, node) {
struct generic_pm_domain *domain;
domain = scpsys_add_one_domain(scpsys, node);
if (IS_ERR(domain)) {
ret = PTR_ERR(domain);
of_node_put(node);
goto err_cleanup_domains;
}
ret = scpsys_add_subdomain(scpsys, node);
if (ret) {
of_node_put(node);
goto err_cleanup_domains;
}
}
if (ret) {
dev_dbg(dev, "no power domains present\n");
return ret;
}
ret = of_genpd_add_provider_onecell(np, &scpsys->pd_data);
if (ret) {
dev_err(dev, "failed to add provider: %d\n", ret);
goto err_cleanup_domains;
}
return 0;
err_cleanup_domains:
scpsys_domain_cleanup(scpsys);
return ret;
}
static struct platform_driver scpsys_pm_domain_driver = {
.probe = scpsys_probe,
.driver = {
.name = "mtk-power-controller",
.suppress_bind_attrs = true,
.of_match_table = scpsys_of_match,
},
};
builtin_platform_driver(scpsys_pm_domain_driver);

View file

@ -0,0 +1,102 @@
/* SPDX-License-Identifier: GPL-2.0-only */
#ifndef __SOC_MEDIATEK_MTK_PM_DOMAINS_H
#define __SOC_MEDIATEK_MTK_PM_DOMAINS_H
#define MTK_SCPD_ACTIVE_WAKEUP BIT(0)
#define MTK_SCPD_FWAIT_SRAM BIT(1)
#define MTK_SCPD_SRAM_ISO BIT(2)
#define MTK_SCPD_KEEP_DEFAULT_OFF BIT(3)
#define MTK_SCPD_CAPS(_scpd, _x) ((_scpd)->data->caps & (_x))
#define SPM_VDE_PWR_CON 0x0210
#define SPM_MFG_PWR_CON 0x0214
#define SPM_VEN_PWR_CON 0x0230
#define SPM_ISP_PWR_CON 0x0238
#define SPM_DIS_PWR_CON 0x023c
#define SPM_VEN2_PWR_CON 0x0298
#define SPM_AUDIO_PWR_CON 0x029c
#define SPM_MFG_2D_PWR_CON 0x02c0
#define SPM_MFG_ASYNC_PWR_CON 0x02c4
#define SPM_USB_PWR_CON 0x02cc
#define SPM_PWR_STATUS 0x060c
#define SPM_PWR_STATUS_2ND 0x0610
#define PWR_STATUS_CONN BIT(1)
#define PWR_STATUS_DISP BIT(3)
#define PWR_STATUS_MFG BIT(4)
#define PWR_STATUS_ISP BIT(5)
#define PWR_STATUS_VDEC BIT(7)
#define PWR_STATUS_VENC_LT BIT(20)
#define PWR_STATUS_VENC BIT(21)
#define PWR_STATUS_MFG_2D BIT(22)
#define PWR_STATUS_MFG_ASYNC BIT(23)
#define PWR_STATUS_AUDIO BIT(24)
#define PWR_STATUS_USB BIT(25)
#define SPM_MAX_BUS_PROT_DATA 5
#define _BUS_PROT(_mask, _set, _clr, _sta, _update, _ignore) { \
.bus_prot_mask = (_mask), \
.bus_prot_set = _set, \
.bus_prot_clr = _clr, \
.bus_prot_sta = _sta, \
.bus_prot_reg_update = _update, \
.ignore_clr_ack = _ignore, \
}
#define BUS_PROT_WR(_mask, _set, _clr, _sta) \
_BUS_PROT(_mask, _set, _clr, _sta, false, false)
#define BUS_PROT_WR_IGN(_mask, _set, _clr, _sta) \
_BUS_PROT(_mask, _set, _clr, _sta, false, true)
#define BUS_PROT_UPDATE(_mask, _set, _clr, _sta) \
_BUS_PROT(_mask, _set, _clr, _sta, true, false)
#define BUS_PROT_UPDATE_TOPAXI(_mask) \
BUS_PROT_UPDATE(_mask, \
INFRA_TOPAXI_PROTECTEN, \
INFRA_TOPAXI_PROTECTEN_CLR, \
INFRA_TOPAXI_PROTECTSTA1)
struct scpsys_bus_prot_data {
u32 bus_prot_mask;
u32 bus_prot_set;
u32 bus_prot_clr;
u32 bus_prot_sta;
bool bus_prot_reg_update;
bool ignore_clr_ack;
};
#define MAX_SUBSYS_CLKS 10
/**
* struct scpsys_domain_data - scp domain data for power on/off flow
* @sta_mask: The mask for power on/off status bit.
* @ctl_offs: The offset for main power control register.
* @sram_pdn_bits: The mask for sram power control bits.
* @sram_pdn_ack_bits: The mask for sram power control acked bits.
* @caps: The flag for active wake-up action.
* @bp_infracfg: bus protection for infracfg subsystem
* @bp_smi: bus protection for smi subsystem
*/
struct scpsys_domain_data {
u32 sta_mask;
int ctl_offs;
u32 sram_pdn_bits;
u32 sram_pdn_ack_bits;
u8 caps;
const struct scpsys_bus_prot_data bp_infracfg[SPM_MAX_BUS_PROT_DATA];
const struct scpsys_bus_prot_data bp_smi[SPM_MAX_BUS_PROT_DATA];
};
struct scpsys_soc_data {
const struct scpsys_domain_data *domains_data;
int num_domains;
int pwr_sta_offs;
int pwr_sta2nd_offs;
};
#endif /* __SOC_MEDIATEK_MTK_PM_DOMAINS_H */

View file

@ -524,6 +524,7 @@ static void mtk_register_power_domains(struct platform_device *pdev,
for (i = 0; i < num; i++) {
struct scp_domain *scpd = &scp->domains[i];
struct generic_pm_domain *genpd = &scpd->genpd;
bool on;
/*
* Initially turn on all domains to make the domains usable
@ -531,9 +532,9 @@ static void mtk_register_power_domains(struct platform_device *pdev,
* software. The unused domains will be switched off during
* late_init time.
*/
genpd->power_on(genpd);
on = !WARN_ON(genpd->power_on(genpd) < 0);
pm_genpd_init(genpd, NULL, false);
pm_genpd_init(genpd, NULL, !on);
}
/*

View file

@ -0,0 +1,26 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Copyright (c) 2020 MediaTek Inc.
* Author: Weiyi Lu <weiyi.lu@mediatek.com>
*/
#ifndef _DT_BINDINGS_POWER_MT8183_POWER_H
#define _DT_BINDINGS_POWER_MT8183_POWER_H
#define MT8183_POWER_DOMAIN_AUDIO 0
#define MT8183_POWER_DOMAIN_CONN 1
#define MT8183_POWER_DOMAIN_MFG_ASYNC 2
#define MT8183_POWER_DOMAIN_MFG 3
#define MT8183_POWER_DOMAIN_MFG_CORE0 4
#define MT8183_POWER_DOMAIN_MFG_CORE1 5
#define MT8183_POWER_DOMAIN_MFG_2D 6
#define MT8183_POWER_DOMAIN_DISP 7
#define MT8183_POWER_DOMAIN_CAM 8
#define MT8183_POWER_DOMAIN_ISP 9
#define MT8183_POWER_DOMAIN_VDEC 10
#define MT8183_POWER_DOMAIN_VENC 11
#define MT8183_POWER_DOMAIN_VPU_TOP 12
#define MT8183_POWER_DOMAIN_VPU_CORE0 13
#define MT8183_POWER_DOMAIN_VPU_CORE1 14
#endif /* _DT_BINDINGS_POWER_MT8183_POWER_H */

View file

@ -0,0 +1,32 @@
/* SPDX-License-Identifier: GPL-2.0
*
* Copyright (c) 2020 MediaTek Inc.
* Author: Weiyi Lu <weiyi.lu@mediatek.com>
*/
#ifndef _DT_BINDINGS_POWER_MT8192_POWER_H
#define _DT_BINDINGS_POWER_MT8192_POWER_H
#define MT8192_POWER_DOMAIN_AUDIO 0
#define MT8192_POWER_DOMAIN_CONN 1
#define MT8192_POWER_DOMAIN_MFG0 2
#define MT8192_POWER_DOMAIN_MFG1 3
#define MT8192_POWER_DOMAIN_MFG2 4
#define MT8192_POWER_DOMAIN_MFG3 5
#define MT8192_POWER_DOMAIN_MFG4 6
#define MT8192_POWER_DOMAIN_MFG5 7
#define MT8192_POWER_DOMAIN_MFG6 8
#define MT8192_POWER_DOMAIN_DISP 9
#define MT8192_POWER_DOMAIN_IPE 10
#define MT8192_POWER_DOMAIN_ISP 11
#define MT8192_POWER_DOMAIN_ISP2 12
#define MT8192_POWER_DOMAIN_MDP 13
#define MT8192_POWER_DOMAIN_VENC 14
#define MT8192_POWER_DOMAIN_VDEC 15
#define MT8192_POWER_DOMAIN_VDEC2 16
#define MT8192_POWER_DOMAIN_CAM 17
#define MT8192_POWER_DOMAIN_CAM_RAWA 18
#define MT8192_POWER_DOMAIN_CAM_RAWB 19
#define MT8192_POWER_DOMAIN_CAM_RAWC 20
#endif /* _DT_BINDINGS_POWER_MT8192_POWER_H */

View file

@ -28,6 +28,9 @@ extern struct regmap *syscon_regmap_lookup_by_phandle_args(
const char *property,
int arg_count,
unsigned int *out_args);
extern struct regmap *syscon_regmap_lookup_by_phandle_optional(
struct device_node *np,
const char *property);
#else
static inline struct regmap *device_node_to_regmap(struct device_node *np)
{
@ -59,6 +62,14 @@ static inline struct regmap *syscon_regmap_lookup_by_phandle_args(
{
return ERR_PTR(-ENOTSUPP);
}
static inline struct regmap *syscon_regmap_lookup_by_phandle_optional(
struct device_node *np,
const char *property)
{
return NULL;
}
#endif
#endif /* __LINUX_MFD_SYSCON_H__ */

View file

@ -2,6 +2,108 @@
#ifndef __SOC_MEDIATEK_INFRACFG_H
#define __SOC_MEDIATEK_INFRACFG_H
#define MT8192_TOP_AXI_PROT_EN_STA1 0x228
#define MT8192_TOP_AXI_PROT_EN_1_STA1 0x258
#define MT8192_TOP_AXI_PROT_EN_SET 0x2a0
#define MT8192_TOP_AXI_PROT_EN_CLR 0x2a4
#define MT8192_TOP_AXI_PROT_EN_1_SET 0x2a8
#define MT8192_TOP_AXI_PROT_EN_1_CLR 0x2ac
#define MT8192_TOP_AXI_PROT_EN_MM_SET 0x2d4
#define MT8192_TOP_AXI_PROT_EN_MM_CLR 0x2d8
#define MT8192_TOP_AXI_PROT_EN_MM_STA1 0x2ec
#define MT8192_TOP_AXI_PROT_EN_2_SET 0x714
#define MT8192_TOP_AXI_PROT_EN_2_CLR 0x718
#define MT8192_TOP_AXI_PROT_EN_2_STA1 0x724
#define MT8192_TOP_AXI_PROT_EN_VDNR_SET 0xb84
#define MT8192_TOP_AXI_PROT_EN_VDNR_CLR 0xb88
#define MT8192_TOP_AXI_PROT_EN_VDNR_STA1 0xb90
#define MT8192_TOP_AXI_PROT_EN_MM_2_SET 0xdcc
#define MT8192_TOP_AXI_PROT_EN_MM_2_CLR 0xdd0
#define MT8192_TOP_AXI_PROT_EN_MM_2_STA1 0xdd8
#define MT8192_TOP_AXI_PROT_EN_DISP (BIT(6) | BIT(23))
#define MT8192_TOP_AXI_PROT_EN_CONN (BIT(13) | BIT(18))
#define MT8192_TOP_AXI_PROT_EN_CONN_2ND BIT(14)
#define MT8192_TOP_AXI_PROT_EN_MFG1 GENMASK(22, 21)
#define MT8192_TOP_AXI_PROT_EN_1_CONN BIT(10)
#define MT8192_TOP_AXI_PROT_EN_1_MFG1 BIT(21)
#define MT8192_TOP_AXI_PROT_EN_1_CAM BIT(22)
#define MT8192_TOP_AXI_PROT_EN_2_CAM BIT(0)
#define MT8192_TOP_AXI_PROT_EN_2_ADSP BIT(3)
#define MT8192_TOP_AXI_PROT_EN_2_AUDIO BIT(4)
#define MT8192_TOP_AXI_PROT_EN_2_MFG1 GENMASK(6, 5)
#define MT8192_TOP_AXI_PROT_EN_2_MFG1_2ND BIT(7)
#define MT8192_TOP_AXI_PROT_EN_MM_CAM (BIT(0) | BIT(2))
#define MT8192_TOP_AXI_PROT_EN_MM_DISP (BIT(0) | BIT(2) | \
BIT(10) | BIT(12) | \
BIT(14) | BIT(16) | \
BIT(24) | BIT(26))
#define MT8192_TOP_AXI_PROT_EN_MM_CAM_2ND (BIT(1) | BIT(3))
#define MT8192_TOP_AXI_PROT_EN_MM_DISP_2ND (BIT(1) | BIT(3) | \
BIT(15) | BIT(17) | \
BIT(25) | BIT(27))
#define MT8192_TOP_AXI_PROT_EN_MM_ISP2 BIT(14)
#define MT8192_TOP_AXI_PROT_EN_MM_ISP2_2ND BIT(15)
#define MT8192_TOP_AXI_PROT_EN_MM_IPE BIT(16)
#define MT8192_TOP_AXI_PROT_EN_MM_IPE_2ND BIT(17)
#define MT8192_TOP_AXI_PROT_EN_MM_VDEC BIT(24)
#define MT8192_TOP_AXI_PROT_EN_MM_VDEC_2ND BIT(25)
#define MT8192_TOP_AXI_PROT_EN_MM_VENC BIT(26)
#define MT8192_TOP_AXI_PROT_EN_MM_VENC_2ND BIT(27)
#define MT8192_TOP_AXI_PROT_EN_MM_2_ISP BIT(8)
#define MT8192_TOP_AXI_PROT_EN_MM_2_DISP (BIT(8) | BIT(12))
#define MT8192_TOP_AXI_PROT_EN_MM_2_ISP_2ND BIT(9)
#define MT8192_TOP_AXI_PROT_EN_MM_2_DISP_2ND (BIT(9) | BIT(13))
#define MT8192_TOP_AXI_PROT_EN_MM_2_MDP BIT(12)
#define MT8192_TOP_AXI_PROT_EN_MM_2_MDP_2ND BIT(13)
#define MT8192_TOP_AXI_PROT_EN_VDNR_CAM BIT(21)
#define MT8183_TOP_AXI_PROT_EN_STA1 0x228
#define MT8183_TOP_AXI_PROT_EN_STA1_1 0x258
#define MT8183_TOP_AXI_PROT_EN_SET 0x2a0
#define MT8183_TOP_AXI_PROT_EN_CLR 0x2a4
#define MT8183_TOP_AXI_PROT_EN_1_SET 0x2a8
#define MT8183_TOP_AXI_PROT_EN_1_CLR 0x2ac
#define MT8183_TOP_AXI_PROT_EN_MCU_SET 0x2c4
#define MT8183_TOP_AXI_PROT_EN_MCU_CLR 0x2c8
#define MT8183_TOP_AXI_PROT_EN_MCU_STA1 0x2e4
#define MT8183_TOP_AXI_PROT_EN_MM_SET 0x2d4
#define MT8183_TOP_AXI_PROT_EN_MM_CLR 0x2d8
#define MT8183_TOP_AXI_PROT_EN_MM_STA1 0x2ec
#define MT8183_TOP_AXI_PROT_EN_DISP (BIT(10) | BIT(11))
#define MT8183_TOP_AXI_PROT_EN_CONN (BIT(13) | BIT(14))
#define MT8183_TOP_AXI_PROT_EN_MFG (BIT(21) | BIT(22))
#define MT8183_TOP_AXI_PROT_EN_CAM BIT(28)
#define MT8183_TOP_AXI_PROT_EN_VPU_TOP BIT(27)
#define MT8183_TOP_AXI_PROT_EN_1_DISP (BIT(16) | BIT(17))
#define MT8183_TOP_AXI_PROT_EN_1_MFG GENMASK(21, 19)
#define MT8183_TOP_AXI_PROT_EN_MM_ISP (BIT(3) | BIT(8))
#define MT8183_TOP_AXI_PROT_EN_MM_ISP_2ND BIT(10)
#define MT8183_TOP_AXI_PROT_EN_MM_CAM (BIT(4) | BIT(5) | \
BIT(9) | BIT(13))
#define MT8183_TOP_AXI_PROT_EN_MM_VPU_TOP (GENMASK(9, 6) | \
BIT(12))
#define MT8183_TOP_AXI_PROT_EN_MM_VPU_TOP_2ND (BIT(10) | BIT(11))
#define MT8183_TOP_AXI_PROT_EN_MM_CAM_2ND BIT(11)
#define MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE0_2ND (BIT(0) | BIT(2) | \
BIT(4))
#define MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE1_2ND (BIT(1) | BIT(3) | \
BIT(5))
#define MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE0 BIT(6)
#define MT8183_TOP_AXI_PROT_EN_MCU_VPU_CORE1 BIT(7)
#define MT8183_SMI_COMMON_CLAMP_EN 0x3c0
#define MT8183_SMI_COMMON_CLAMP_EN_SET 0x3c4
#define MT8183_SMI_COMMON_CLAMP_EN_CLR 0x3c8
#define MT8183_SMI_COMMON_SMI_CLAMP_DISP GENMASK(7, 0)
#define MT8183_SMI_COMMON_SMI_CLAMP_VENC BIT(1)
#define MT8183_SMI_COMMON_SMI_CLAMP_ISP BIT(2)
#define MT8183_SMI_COMMON_SMI_CLAMP_CAM (BIT(3) | BIT(4))
#define MT8183_SMI_COMMON_SMI_CLAMP_VPU_TOP (BIT(5) | BIT(6))
#define MT8183_SMI_COMMON_SMI_CLAMP_VDEC BIT(7)
#define MT8173_TOP_AXI_PROT_EN_MCI_M2 BIT(0)
#define MT8173_TOP_AXI_PROT_EN_MM_M0 BIT(1)
#define MT8173_TOP_AXI_PROT_EN_MM_M1 BIT(2)
@ -32,6 +134,11 @@
#define MT7622_TOP_AXI_PROT_EN_WB (BIT(2) | BIT(6) | \
BIT(7) | BIT(8))
#define INFRA_TOPAXI_PROTECTEN 0x0220
#define INFRA_TOPAXI_PROTECTSTA1 0x0228
#define INFRA_TOPAXI_PROTECTEN_SET 0x0260
#define INFRA_TOPAXI_PROTECTEN_CLR 0x0264
#define REG_INFRA_MISC 0xf00
#define F_DDR_4GB_SUPPORT_EN BIT(13)

View file

@ -11,7 +11,6 @@
#include <linux/mailbox/mtk-cmdq-mailbox.h>
#include <linux/timer.h>
#define CMDQ_NO_TIMEOUT 0xffffffffu
#define CMDQ_ADDR_HIGH(addr) ((u32)(((addr) >> 16) & GENMASK(31, 0)))
#define CMDQ_ADDR_LOW(addr) ((u16)(addr) | BIT(1))
@ -24,12 +23,8 @@ struct cmdq_client_reg {
};
struct cmdq_client {
spinlock_t lock;
u32 pkt_cnt;
struct mbox_client client;
struct mbox_chan *chan;
struct timer_list timer;
u32 timeout_ms; /* in unit of microsecond */
};
/**
@ -51,13 +46,10 @@ int cmdq_dev_get_client_reg(struct device *dev,
* cmdq_mbox_create() - create CMDQ mailbox client and channel
* @dev: device of CMDQ mailbox client
* @index: index of CMDQ mailbox channel
* @timeout: timeout of a pkt execution by GCE, in unit of microsecond, set
* CMDQ_NO_TIMEOUT if a timer is not used.
*
* Return: CMDQ mailbox client pointer
*/
struct cmdq_client *cmdq_mbox_create(struct device *dev, int index,
u32 timeout);
struct cmdq_client *cmdq_mbox_create(struct device *dev, int index);
/**
* cmdq_mbox_destroy() - destroy CMDQ mailbox client and channel

View file

@ -9,6 +9,39 @@
enum mtk_ddp_comp_id;
struct device;
enum mtk_ddp_comp_id {
DDP_COMPONENT_AAL0,
DDP_COMPONENT_AAL1,
DDP_COMPONENT_BLS,
DDP_COMPONENT_CCORR,
DDP_COMPONENT_COLOR0,
DDP_COMPONENT_COLOR1,
DDP_COMPONENT_DITHER,
DDP_COMPONENT_DPI0,
DDP_COMPONENT_DPI1,
DDP_COMPONENT_DSI0,
DDP_COMPONENT_DSI1,
DDP_COMPONENT_DSI2,
DDP_COMPONENT_DSI3,
DDP_COMPONENT_GAMMA,
DDP_COMPONENT_OD0,
DDP_COMPONENT_OD1,
DDP_COMPONENT_OVL0,
DDP_COMPONENT_OVL_2L0,
DDP_COMPONENT_OVL_2L1,
DDP_COMPONENT_OVL1,
DDP_COMPONENT_PWM0,
DDP_COMPONENT_PWM1,
DDP_COMPONENT_PWM2,
DDP_COMPONENT_RDMA0,
DDP_COMPONENT_RDMA1,
DDP_COMPONENT_RDMA2,
DDP_COMPONENT_UFOE,
DDP_COMPONENT_WDMA0,
DDP_COMPONENT_WDMA1,
DDP_COMPONENT_ID_MAX,
};
void mtk_mmsys_ddp_connect(struct device *dev,
enum mtk_ddp_comp_id cur,
enum mtk_ddp_comp_id next);