162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) 2015 Pengutronix, Sascha Hauer <kernel@pengutronix.de> 462306a36Sopenharmony_ci */ 562306a36Sopenharmony_ci 662306a36Sopenharmony_ci#include <linux/export.h> 762306a36Sopenharmony_ci#include <linux/jiffies.h> 862306a36Sopenharmony_ci#include <linux/regmap.h> 962306a36Sopenharmony_ci#include <linux/mfd/syscon.h> 1062306a36Sopenharmony_ci#include <linux/soc/mediatek/infracfg.h> 1162306a36Sopenharmony_ci#include <asm/processor.h> 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define MTK_POLL_DELAY_US 10 1462306a36Sopenharmony_ci#define MTK_POLL_TIMEOUT (jiffies_to_usecs(HZ)) 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/** 1762306a36Sopenharmony_ci * mtk_infracfg_set_bus_protection - enable bus protection 1862306a36Sopenharmony_ci * @infracfg: The infracfg regmap 1962306a36Sopenharmony_ci * @mask: The mask containing the protection bits to be enabled. 2062306a36Sopenharmony_ci * @reg_update: The boolean flag determines to set the protection bits 2162306a36Sopenharmony_ci * by regmap_update_bits with enable register(PROTECTEN) or 2262306a36Sopenharmony_ci * by regmap_write with set register(PROTECTEN_SET). 2362306a36Sopenharmony_ci * 2462306a36Sopenharmony_ci * This function enables the bus protection bits for disabled power 2562306a36Sopenharmony_ci * domains so that the system does not hang when some unit accesses the 2662306a36Sopenharmony_ci * bus while in power down. 2762306a36Sopenharmony_ci */ 2862306a36Sopenharmony_ciint mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask, 2962306a36Sopenharmony_ci bool reg_update) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci u32 val; 3262306a36Sopenharmony_ci int ret; 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci if (reg_update) 3562306a36Sopenharmony_ci regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 3662306a36Sopenharmony_ci mask); 3762306a36Sopenharmony_ci else 3862306a36Sopenharmony_ci regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_SET, mask); 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci ret = regmap_read_poll_timeout(infracfg, INFRA_TOPAXI_PROTECTSTA1, 4162306a36Sopenharmony_ci val, (val & mask) == mask, 4262306a36Sopenharmony_ci MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci return ret; 4562306a36Sopenharmony_ci} 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci/** 4862306a36Sopenharmony_ci * mtk_infracfg_clear_bus_protection - disable bus protection 4962306a36Sopenharmony_ci * @infracfg: The infracfg regmap 5062306a36Sopenharmony_ci * @mask: The mask containing the protection bits to be disabled. 5162306a36Sopenharmony_ci * @reg_update: The boolean flag determines to clear the protection bits 5262306a36Sopenharmony_ci * by regmap_update_bits with enable register(PROTECTEN) or 5362306a36Sopenharmony_ci * by regmap_write with clear register(PROTECTEN_CLR). 5462306a36Sopenharmony_ci * 5562306a36Sopenharmony_ci * This function disables the bus protection bits previously enabled with 5662306a36Sopenharmony_ci * mtk_infracfg_set_bus_protection. 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_ci 5962306a36Sopenharmony_ciint mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask, 6062306a36Sopenharmony_ci bool reg_update) 6162306a36Sopenharmony_ci{ 6262306a36Sopenharmony_ci int ret; 6362306a36Sopenharmony_ci u32 val; 6462306a36Sopenharmony_ci 6562306a36Sopenharmony_ci if (reg_update) 6662306a36Sopenharmony_ci regmap_update_bits(infracfg, INFRA_TOPAXI_PROTECTEN, mask, 0); 6762306a36Sopenharmony_ci else 6862306a36Sopenharmony_ci regmap_write(infracfg, INFRA_TOPAXI_PROTECTEN_CLR, mask); 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ci ret = regmap_read_poll_timeout(infracfg, INFRA_TOPAXI_PROTECTSTA1, 7162306a36Sopenharmony_ci val, !(val & mask), 7262306a36Sopenharmony_ci MTK_POLL_DELAY_US, MTK_POLL_TIMEOUT); 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci return ret; 7562306a36Sopenharmony_ci} 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_cistatic int __init mtk_infracfg_init(void) 7862306a36Sopenharmony_ci{ 7962306a36Sopenharmony_ci struct regmap *infracfg; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci /* 8262306a36Sopenharmony_ci * MT8192 has an experimental path to route GPU traffic to the DSU's 8362306a36Sopenharmony_ci * Accelerator Coherency Port, which is inadvertently enabled by 8462306a36Sopenharmony_ci * default. It turns out not to work, so disable it to prevent spurious 8562306a36Sopenharmony_ci * GPU faults. 8662306a36Sopenharmony_ci */ 8762306a36Sopenharmony_ci infracfg = syscon_regmap_lookup_by_compatible("mediatek,mt8192-infracfg"); 8862306a36Sopenharmony_ci if (!IS_ERR(infracfg)) 8962306a36Sopenharmony_ci regmap_set_bits(infracfg, MT8192_INFRA_CTRL, 9062306a36Sopenharmony_ci MT8192_INFRA_CTRL_DISABLE_MFG2ACP); 9162306a36Sopenharmony_ci return 0; 9262306a36Sopenharmony_ci} 9362306a36Sopenharmony_cipostcore_initcall(mtk_infracfg_init); 94