From fbfb46dc21af88977f5fa9dd9fe39bb257d19a48 Mon Sep 17 00:00:00 2001 From: Vedashree Vidwans Date: Thu, 2 Dec 2021 14:16:48 -0800 Subject: [PATCH] tegra: t234: soc hwpm: add ip reg read/write support If IP driver supports register read/write mechanism then call register call back for register offset read/write. Bug 3333031 Bug 3333042 Change-Id: I37e0726edadac9b03d2a5368d0ec7b404cb6dfd3 Signed-off-by: Vedashree Vidwans Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2628129 Reviewed-by: svc_kernel_abi Reviewed-by: Seema Khowala Reviewed-by: mobile promotions Tested-by: mobile promotions GVS: Gerrit_Virtual_Submit --- tegra-soc-hwpm-io.c | 103 +++++++++++++++++++++++++++++++------------- tegra-soc-hwpm-io.h | 2 +- 2 files changed, 75 insertions(+), 30 deletions(-) diff --git a/tegra-soc-hwpm-io.c b/tegra-soc-hwpm-io.c index 1e4aa6f..6f2c327 100644 --- a/tegra-soc-hwpm-io.c +++ b/tegra-soc-hwpm-io.c @@ -27,6 +27,7 @@ #include "tegra-soc-hwpm-log.h" #include #include +#include static u32 fake_readl(struct tegra_soc_hwpm *hwpm, u64 phys_addr) { @@ -114,10 +115,6 @@ void hwpm_writel(struct tegra_soc_hwpm *hwpm, u32 dt_aperture, } } -/* - * FIXME: Remove all non-HWPM register reads from the driver. - * Replace them with inter-driver APIs? - */ u32 ip_readl(struct tegra_soc_hwpm *hwpm, u64 phys_addr) { tegra_soc_hwpm_dbg("reg read: phys_addr(0x%llx)", phys_addr); @@ -125,43 +122,91 @@ u32 ip_readl(struct tegra_soc_hwpm *hwpm, u64 phys_addr) if (hwpm->fake_registers_enabled) { return fake_readl(hwpm, phys_addr); } else { - void __iomem *ptr = NULL; - u32 val = 0; + u64 ip_start_pa = 0ULL; + u32 reg_val = 0U; + u32 dt_aperture = tegra_soc_hwpm_get_ip_aperture(hwpm, + phys_addr, &ip_start_pa); + struct tegra_soc_hwpm_ip_ops *ip_ops = + dt_aperture == TEGRA_SOC_HWPM_DT_APERTURE_INVALID ? + NULL : &hwpm->ip_info[dt_aperture]; - ptr = ioremap(phys_addr, 0x4); - if (!ptr) { - tegra_soc_hwpm_err("Failed to map register(0x%llx)", - phys_addr); - return 0; + if (ip_ops && (*ip_ops->hwpm_ip_reg_op)) { + int err = 0; + + tegra_soc_hwpm_dbg( + "aperture: %d ip_ops offset(0x%llx)", + dt_aperture, (phys_addr - ip_start_pa)); + err = (*ip_ops->hwpm_ip_reg_op)(ip_ops->ip_dev, + TEGRA_SOC_HWPM_IP_REG_OP_READ, + (phys_addr - ip_start_pa), ®_val); + if (err < 0) { + tegra_soc_hwpm_err( + "Failed to read ip register(0x%llx)", + phys_addr); + return 0U; + } + } else { + /* Fall back to un-registered IP method */ + void __iomem *ptr = NULL; + + ptr = ioremap(phys_addr, 0x4); + if (!ptr) { + tegra_soc_hwpm_err( + "Failed to map register(0x%llx)", + phys_addr); + return 0U; + } + reg_val = __raw_readl(ptr); + iounmap(ptr); } - val = __raw_readl(ptr); - iounmap(ptr); - return val; + return reg_val; } } -/* - * FIXME: Remove all non-HWPM register writes from the driver. - * Replace them with inter-driver APIs? - */ -void ip_writel(struct tegra_soc_hwpm *hwpm, u64 phys_addr, u32 val) +void ip_writel(struct tegra_soc_hwpm *hwpm, u64 phys_addr, u32 reg_val) { tegra_soc_hwpm_dbg("reg write: phys_addr(0x%llx), val(0x%x)", - phys_addr, val); + phys_addr, reg_val); if (hwpm->fake_registers_enabled) { - fake_writel(hwpm, phys_addr, val); + fake_writel(hwpm, phys_addr, reg_val); } else { - void __iomem *ptr = NULL; + u64 ip_start_pa = 0ULL; + u32 dt_aperture = tegra_soc_hwpm_get_ip_aperture(hwpm, + phys_addr, &ip_start_pa); + struct tegra_soc_hwpm_ip_ops *ip_ops = + dt_aperture == TEGRA_SOC_HWPM_DT_APERTURE_INVALID ? + NULL : &hwpm->ip_info[dt_aperture]; - ptr = ioremap(phys_addr, 0x4); - if (!ptr) { - tegra_soc_hwpm_err("Failed to map register(0x%llx)", - phys_addr); - return; + if (ip_ops && (*ip_ops->hwpm_ip_reg_op)) { + int err = 0; + + tegra_soc_hwpm_dbg( + "aperture: %d ip_ops offset(0x%llx)", + dt_aperture, (phys_addr - ip_start_pa)); + err = (*ip_ops->hwpm_ip_reg_op)(ip_ops->ip_dev, + TEGRA_SOC_HWPM_IP_REG_OP_WRITE, + (phys_addr - ip_start_pa), ®_val); + if (err < 0) { + tegra_soc_hwpm_err( + "write ip reg(0x%llx) val 0x%x failed", + phys_addr, reg_val); + return; + } + } else { + /* Fall back to un-registered IP method */ + void __iomem *ptr = NULL; + + ptr = ioremap(phys_addr, 0x4); + if (!ptr) { + tegra_soc_hwpm_err( + "Failed to map register(0x%llx)", + phys_addr); + return; + } + __raw_writel(reg_val, ptr); + iounmap(ptr); } - __raw_writel(val, ptr); - iounmap(ptr); } } diff --git a/tegra-soc-hwpm-io.h b/tegra-soc-hwpm-io.h index 8f65844..ad3304d 100644 --- a/tegra-soc-hwpm-io.h +++ b/tegra-soc-hwpm-io.h @@ -35,7 +35,7 @@ void hwpm_writel(struct tegra_soc_hwpm *hwpm, u32 dt_aperture, u32 reg_offset, u32 val); u32 ip_readl(struct tegra_soc_hwpm *hwpm, u64 phys_addr); -void ip_writel(struct tegra_soc_hwpm *hwpm, u64 phys_addr, u32 val); +void ip_writel(struct tegra_soc_hwpm *hwpm, u64 phys_addr, u32 reg_val); u32 ioctl_readl(struct tegra_soc_hwpm *hwpm, struct hwpm_resource_aperture *aperture, u64 addr);