diff options
| -rw-r--r-- | drivers/soc/mediatek/mtk-infracfg.c | 26 | ||||
| -rw-r--r-- | drivers/soc/mediatek/mtk-scpsys.c | 28 | ||||
| -rw-r--r-- | include/linux/soc/mediatek/infracfg.h | 7 |
3 files changed, 46 insertions, 15 deletions
diff --git a/drivers/soc/mediatek/mtk-infracfg.c b/drivers/soc/mediatek/mtk-infracfg.c index dba3055a9493..8c310de01e93 100644 --- a/drivers/soc/mediatek/mtk-infracfg.c +++ b/drivers/soc/mediatek/mtk-infracfg.c | |||
| @@ -19,23 +19,33 @@ | |||
| 19 | 19 | ||
| 20 | #define INFRA_TOPAXI_PROTECTEN 0x0220 | 20 | #define INFRA_TOPAXI_PROTECTEN 0x0220 |
| 21 | #define INFRA_TOPAXI_PROTECTSTA1 0x0228 | 21 | #define INFRA_TOPAXI_PROTECTSTA1 0x0228 |
| 22 | #define INFRA_TOPAXI_PROTECTEN_SET 0x0260 | ||
| 23 | #define INFRA_TOPAXI_PROTECTEN_CLR 0x0264 | ||
| 22 | 24 | ||
| 23 | /** | 25 | /** |
| 24 | * mtk_infracfg_set_bus_protection - enable bus protection | 26 | * mtk_infracfg_set_bus_protection - enable bus protection |
| 25 | * @regmap: The infracfg regmap | 27 | * @regmap: The infracfg regmap |
| 26 | * @mask: The mask containing the protection bits to be enabled. | 28 | * @mask: The mask containing the protection bits to be enabled. |
| 29 | * @reg_update: The boolean flag determines to set the protection bits | ||
| 30 | * by regmap_update_bits with enable register(PROTECTEN) or | ||
| 31 | * by regmap_write with set register(PROTECTEN_SET). | ||
| 27 | * | 32 | * |
| 28 | * This function enables the bus protection bits for disabled power | 33 | * This function enables the bus protection bits for disabled power |
| 29 | * domains so that the system does not hang when some unit accesses the | 34 | * domains so that the system does not hang when some unit accesses the |
| 30 | * bus while in power down. | 35 | * bus while in power down. |
| 31 | */ | 36 | */ |
| 32 | int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask) | 37 | int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask, |
| 38 | bool reg_update) | ||
| 33 | { | 39 | { |
| 34 | unsigned long expired; | 40 | unsigned long expired; |
| 35 | u32 val; | 41 | u32 val; |
| 36 | int ret; | 42 | int ret; |
| 37 | 43 | ||
| 38 | regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, mask); | 44 | if (reg_update) |
| 45 | regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, | ||
| 46 | mask); | ||
| 47 | else | ||
| 48 | regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_SET, mask); | ||
| 39 | 49 | ||
| 40 | expired = jiffies + HZ; | 50 | expired = jiffies + HZ; |
| 41 | 51 | ||
| @@ -59,16 +69,24 @@ int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask) | |||
| 59 | * mtk_infracfg_clear_bus_protection - disable bus protection | 69 | * mtk_infracfg_clear_bus_protection - disable bus protection |
| 60 | * @regmap: The infracfg regmap | 70 | * @regmap: The infracfg regmap |
| 61 | * @mask: The mask containing the protection bits to be disabled. | 71 | * @mask: The mask containing the protection bits to be disabled. |
| 72 | * @reg_update: The boolean flag determines to clear the protection bits | ||
| 73 | * by regmap_update_bits with enable register(PROTECTEN) or | ||
| 74 | * by regmap_write with clear register(PROTECTEN_CLR). | ||
| 62 | * | 75 | * |
| 63 | * This function disables the bus protection bits previously enabled with | 76 | * This function disables the bus protection bits previously enabled with |
| 64 | * mtk_infracfg_set_bus_protection. | 77 | * mtk_infracfg_set_bus_protection. |
| 65 | */ | 78 | */ |
| 66 | int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask) | 79 | |
| 80 | int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask, | ||
| 81 | bool reg_update) | ||
| 67 | { | 82 | { |
| 68 | unsigned long expired; | 83 | unsigned long expired; |
| 69 | int ret; | 84 | int ret; |
| 70 | 85 | ||
| 71 | regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0); | 86 | if (reg_update) |
| 87 | regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0); | ||
| 88 | else | ||
| 89 | regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_CLR, mask); | ||
| 72 | 90 | ||
| 73 | expired = jiffies + HZ; | 91 | expired = jiffies + HZ; |
| 74 | 92 | ||
diff --git a/drivers/soc/mediatek/mtk-scpsys.c b/drivers/soc/mediatek/mtk-scpsys.c index e570b6af2e6f..4c484b1d2f30 100644 --- a/drivers/soc/mediatek/mtk-scpsys.c +++ b/drivers/soc/mediatek/mtk-scpsys.c | |||
| @@ -134,6 +134,7 @@ struct scp { | |||
| 134 | void __iomem *base; | 134 | void __iomem *base; |
| 135 | struct regmap *infracfg; | 135 | struct regmap *infracfg; |
| 136 | struct scp_ctrl_reg ctrl_reg; | 136 | struct scp_ctrl_reg ctrl_reg; |
| 137 | bool bus_prot_reg_update; | ||
| 137 | }; | 138 | }; |
| 138 | 139 | ||
| 139 | struct scp_subdomain { | 140 | struct scp_subdomain { |
| @@ -147,6 +148,7 @@ struct scp_soc_data { | |||
| 147 | const struct scp_subdomain *subdomains; | 148 | const struct scp_subdomain *subdomains; |
| 148 | int num_subdomains; | 149 | int num_subdomains; |
| 149 | const struct scp_ctrl_reg regs; | 150 | const struct scp_ctrl_reg regs; |
| 151 | bool bus_prot_reg_update; | ||
| 150 | }; | 152 | }; |
| 151 | 153 | ||
| 152 | static int scpsys_domain_is_on(struct scp_domain *scpd) | 154 | static int scpsys_domain_is_on(struct scp_domain *scpd) |
| @@ -254,7 +256,8 @@ static int scpsys_power_on(struct generic_pm_domain *genpd) | |||
| 254 | 256 | ||
| 255 | if (scpd->data->bus_prot_mask) { | 257 | if (scpd->data->bus_prot_mask) { |
| 256 | ret = mtk_infracfg_clear_bus_protection(scp->infracfg, | 258 | ret = mtk_infracfg_clear_bus_protection(scp->infracfg, |
| 257 | scpd->data->bus_prot_mask); | 259 | scpd->data->bus_prot_mask, |
| 260 | scp->bus_prot_reg_update); | ||
| 258 | if (ret) | 261 | if (ret) |
| 259 | goto err_pwr_ack; | 262 | goto err_pwr_ack; |
| 260 | } | 263 | } |
| @@ -289,7 +292,8 @@ static int scpsys_power_off(struct generic_pm_domain *genpd) | |||
| 289 | 292 | ||
| 290 | if (scpd->data->bus_prot_mask) { | 293 | if (scpd->data->bus_prot_mask) { |
| 291 | ret = mtk_infracfg_set_bus_protection(scp->infracfg, | 294 | ret = mtk_infracfg_set_bus_protection(scp->infracfg, |
| 292 | scpd->data->bus_prot_mask); | 295 | scpd->data->bus_prot_mask, |
| 296 | scp->bus_prot_reg_update); | ||
| 293 | if (ret) | 297 | if (ret) |
| 294 | goto out; | 298 | goto out; |
| 295 | } | 299 | } |
| @@ -371,7 +375,8 @@ static void init_clks(struct platform_device *pdev, struct clk **clk) | |||
| 371 | 375 | ||
| 372 | static struct scp *init_scp(struct platform_device *pdev, | 376 | static struct scp *init_scp(struct platform_device *pdev, |
| 373 | const struct scp_domain_data *scp_domain_data, int num, | 377 | const struct scp_domain_data *scp_domain_data, int num, |
| 374 | const struct scp_ctrl_reg *scp_ctrl_reg) | 378 | const struct scp_ctrl_reg *scp_ctrl_reg, |
| 379 | bool bus_prot_reg_update) | ||
| 375 | { | 380 | { |
| 376 | struct genpd_onecell_data *pd_data; | 381 | struct genpd_onecell_data *pd_data; |
| 377 | struct resource *res; | 382 | struct resource *res; |
| @@ -386,6 +391,8 @@ static struct scp *init_scp(struct platform_device *pdev, | |||
| 386 | scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs; | 391 | scp->ctrl_reg.pwr_sta_offs = scp_ctrl_reg->pwr_sta_offs; |
| 387 | scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs; | 392 | scp->ctrl_reg.pwr_sta2nd_offs = scp_ctrl_reg->pwr_sta2nd_offs; |
| 388 | 393 | ||
| 394 | scp->bus_prot_reg_update = bus_prot_reg_update; | ||
| 395 | |||
| 389 | scp->dev = &pdev->dev; | 396 | scp->dev = &pdev->dev; |
| 390 | 397 | ||
| 391 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 398 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
| @@ -806,7 +813,8 @@ static const struct scp_soc_data mt2701_data = { | |||
| 806 | .regs = { | 813 | .regs = { |
| 807 | .pwr_sta_offs = SPM_PWR_STATUS, | 814 | .pwr_sta_offs = SPM_PWR_STATUS, |
| 808 | .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND | 815 | .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND |
| 809 | } | 816 | }, |
| 817 | .bus_prot_reg_update = true, | ||
| 810 | }; | 818 | }; |
| 811 | 819 | ||
| 812 | static const struct scp_soc_data mt6797_data = { | 820 | static const struct scp_soc_data mt6797_data = { |
| @@ -817,7 +825,8 @@ static const struct scp_soc_data mt6797_data = { | |||
| 817 | .regs = { | 825 | .regs = { |
| 818 | .pwr_sta_offs = SPM_PWR_STATUS_MT6797, | 826 | .pwr_sta_offs = SPM_PWR_STATUS_MT6797, |
| 819 | .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797 | 827 | .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND_MT6797 |
| 820 | } | 828 | }, |
| 829 | .bus_prot_reg_update = true, | ||
| 821 | }; | 830 | }; |
| 822 | 831 | ||
| 823 | static const struct scp_soc_data mt7622_data = { | 832 | static const struct scp_soc_data mt7622_data = { |
| @@ -826,7 +835,8 @@ static const struct scp_soc_data mt7622_data = { | |||
| 826 | .regs = { | 835 | .regs = { |
| 827 | .pwr_sta_offs = SPM_PWR_STATUS, | 836 | .pwr_sta_offs = SPM_PWR_STATUS, |
| 828 | .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND | 837 | .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND |
| 829 | } | 838 | }, |
| 839 | .bus_prot_reg_update = true, | ||
| 830 | }; | 840 | }; |
| 831 | 841 | ||
| 832 | static const struct scp_soc_data mt8173_data = { | 842 | static const struct scp_soc_data mt8173_data = { |
| @@ -837,7 +847,8 @@ static const struct scp_soc_data mt8173_data = { | |||
| 837 | .regs = { | 847 | .regs = { |
| 838 | .pwr_sta_offs = SPM_PWR_STATUS, | 848 | .pwr_sta_offs = SPM_PWR_STATUS, |
| 839 | .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND | 849 | .pwr_sta2nd_offs = SPM_PWR_STATUS_2ND |
| 840 | } | 850 | }, |
| 851 | .bus_prot_reg_update = true, | ||
| 841 | }; | 852 | }; |
| 842 | 853 | ||
| 843 | /* | 854 | /* |
| @@ -874,7 +885,8 @@ static int scpsys_probe(struct platform_device *pdev) | |||
| 874 | match = of_match_device(of_scpsys_match_tbl, &pdev->dev); | 885 | match = of_match_device(of_scpsys_match_tbl, &pdev->dev); |
| 875 | |||
