Loading drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c +1 −0 Original line number Diff line number Diff line Loading @@ -1004,6 +1004,7 @@ static int msm_bus_dev_init_qos(struct device *dev, void *data) bus_node_info->fabdev->noc_ops.qos_init( node_dev, bus_node_info, bus_node_info->fabdev->qos_base, bus_node_info->fabdev->base_offset, bus_node_info->fabdev->qos_off, Loading drivers/soc/qcom/msm_bus/msm_bus_noc_rpmh.c +122 −18 Original line number Diff line number Diff line Loading @@ -15,10 +15,14 @@ #include <linux/slab.h> #include <linux/io.h> #include <linux/msm-bus-board.h> #include <linux/msm-bus.h> #include <linux/spinlock.h> #include "msm_bus_core.h" #include "msm_bus_noc.h" #include "msm_bus_rpmh.h" static DEFINE_SPINLOCK(noc_lock); /* NOC_QOS generic */ #define __CLZ(x) ((8 * sizeof(uint32_t)) - 1 - __fls(x)) #define SAT_SCALE 16 /* 16 bytes minimum for saturation */ Loading @@ -29,6 +33,7 @@ #define MAX_SAT_FIELD (NOC_QOS_SATn_SAT_BMSK >> NOC_QOS_SATn_SAT_SHFT) #define MIN_SAT_FIELD 1 #define MIN_BW_FIELD 1 #define MSM_BUS_FAB_MEM_NOC 6152 #define NOC_QOS_REG_BASE(b, o) ((b) + (o)) Loading Loading @@ -102,6 +107,8 @@ enum noc_qos_id_saturationn { NOC_QOS_SATn_SAT_SHFT = 0x0, }; static void __iomem *memnoc_qos_base; static int noc_div(uint64_t *a, uint32_t b) { if ((*a > 0) && (*a < b)) { Loading Loading @@ -169,46 +176,59 @@ static void noc_set_qos_dflt_prio(void __iomem *base, uint32_t qos_off, wmb(); } static void noc_set_qos_limiter(void __iomem *base, uint32_t qos_off, uint32_t mport, uint32_t qos_delta, struct msm_bus_noc_limiter *lim, uint32_t lim_en) static void noc_enable_qos_limiter(void __iomem *base, uint32_t qos_off, uint32_t mport, uint32_t qos_delta, uint32_t lim_en) { uint32_t reg_val, val; reg_val = readl_relaxed(NOC_QOS_MAINCTL_LOWn_ADDR(base, qos_off, mport, qos_delta)); writel_relaxed((reg_val & (~(NOC_QOS_MCTL_LIMIT_ENn_BMSK))), val = lim_en << NOC_QOS_MCTL_LIMIT_ENn_SHFT; writel_relaxed(((reg_val & (~(NOC_QOS_MCTL_LIMIT_ENn_BMSK))) | (val & NOC_QOS_MCTL_LIMIT_ENn_BMSK)), NOC_QOS_MAINCTL_LOWn_ADDR(base, qos_off, mport, qos_delta)); /* Ensure we disable limiter before config*/ /* Ensure we disable/enable limiter before exiting*/ wmb(); } static void noc_set_qos_limit_bw(void __iomem *base, uint32_t qos_off, uint32_t mport, uint32_t qos_delta, uint32_t bw) { uint32_t reg_val, val; reg_val = readl_relaxed(NOC_QOS_LIMITBWn_ADDR(base, qos_off, mport, qos_delta)); val = lim->bw << NOC_QOS_LIMITBW_BWn_SHFT; val = bw << NOC_QOS_LIMITBW_BWn_SHFT; writel_relaxed(((reg_val & (~(NOC_QOS_LIMITBW_BWn_BMSK))) | (val & NOC_QOS_LIMITBW_BWn_BMSK)), NOC_QOS_LIMITBWn_ADDR(base, qos_off, mport, qos_delta)); /* Ensure we set limiter bw before exiting*/ wmb(); } static void noc_set_qos_limit_sat(void __iomem *base, uint32_t qos_off, uint32_t mport, uint32_t qos_delta, uint32_t sat) { uint32_t reg_val, val; reg_val = readl_relaxed(NOC_QOS_LIMITBWn_ADDR(base, qos_off, mport, qos_delta)); val = lim->sat << NOC_QOS_LIMITBW_SATn_SHFT; val = sat << NOC_QOS_LIMITBW_SATn_SHFT; writel_relaxed(((reg_val & (~(NOC_QOS_LIMITBW_SATn_BMSK))) | (val & NOC_QOS_LIMITBW_SATn_BMSK)), NOC_QOS_LIMITBWn_ADDR(base, qos_off, mport, qos_delta)); /* Ensure qos limiter settings in place before possibly enabling */ /* Ensure we set limiter sat before exiting*/ wmb(); } reg_val = readl_relaxed(NOC_QOS_MAINCTL_LOWn_ADDR(base, qos_off, mport, qos_delta)); val = lim_en << NOC_QOS_MCTL_LIMIT_ENn_SHFT; writel_relaxed(((reg_val & (~(NOC_QOS_MCTL_LIMIT_ENn_BMSK))) | (val & NOC_QOS_MCTL_LIMIT_ENn_BMSK)), NOC_QOS_MAINCTL_LOWn_ADDR(base, qos_off, mport, qos_delta)); wmb(); static void noc_set_qos_limiter(void __iomem *base, uint32_t qos_off, uint32_t mport, uint32_t qos_delta, struct msm_bus_noc_limiter *lim, uint32_t lim_en) { noc_enable_qos_limiter(base, qos_off, mport, qos_delta, 0); noc_set_qos_limit_bw(base, qos_off, mport, qos_delta, lim->bw); noc_set_qos_limit_sat(base, qos_off, mport, qos_delta, lim->sat); noc_enable_qos_limiter(base, qos_off, mport, qos_delta, lim_en); } static void noc_set_qos_regulator(void __iomem *base, uint32_t qos_off, Loading Loading @@ -317,6 +337,7 @@ void msm_bus_noc_get_qos_bw(void __iomem *base, uint32_t qos_off, } static int msm_bus_noc_qos_init(struct msm_bus_node_device_type *info, struct msm_bus_node_device_type *fabdev, void __iomem *qos_base, uint32_t qos_off, uint32_t qos_delta, uint32_t qos_freq) Loading @@ -324,6 +345,7 @@ static int msm_bus_noc_qos_init(struct msm_bus_node_device_type *info, struct msm_bus_noc_qos_params *qos_params; int ret = 0; int i; unsigned long flags; qos_params = &info->node_info->qos_params; Loading @@ -333,6 +355,11 @@ static int msm_bus_noc_qos_init(struct msm_bus_node_device_type *info, goto err_qos_init; } spin_lock_irqsave(&noc_lock, flags); if (fabdev->node_info->id == MSM_BUS_FAB_MEM_NOC) memnoc_qos_base = qos_base; for (i = 0; i < info->node_info->num_qports; i++) { noc_set_qos_dflt_prio(qos_base, qos_off, info->node_info->qport[i], Loading @@ -356,10 +383,87 @@ static int msm_bus_noc_qos_init(struct msm_bus_node_device_type *info, qos_delta, qos_params->urg_fwd_en); } spin_unlock_irqrestore(&noc_lock, flags); err_qos_init: return ret; } int msm_bus_noc_throttle_wa(bool enable) { unsigned long flags; spin_lock_irqsave(&noc_lock, flags); if (!memnoc_qos_base) { MSM_BUS_ERR("Memnoc QoS Base address not found!"); goto noc_throttle_exit; } if (enable) { noc_set_qos_limit_bw(memnoc_qos_base, 0x10000, 2, 0x1000, 0x1B); noc_set_qos_limit_bw(memnoc_qos_base, 0x10000, 3, 0x1000, 0x1B); noc_set_qos_limit_bw(memnoc_qos_base, 0x10000, 10, 0x1000, 0x30); noc_set_qos_limit_bw(memnoc_qos_base, 0x10000, 11, 0x1000, 0x30); noc_enable_qos_limiter(memnoc_qos_base, 0x10000, 10, 0x1000, 1); noc_enable_qos_limiter(memnoc_qos_base, 0x10000, 11, 0x1000, 1); noc_enable_qos_limiter(memnoc_qos_base, 0x10000, 2, 0x1000, 1); noc_enable_qos_limiter(memnoc_qos_base, 0x10000, 3, 0x1000, 1); } else { noc_enable_qos_limiter(memnoc_qos_base, 0x10000, 2, 0x1000, 0); noc_enable_qos_limiter(memnoc_qos_base, 0x10000, 3, 0x1000, 0); noc_enable_qos_limiter(memnoc_qos_base, 0x10000, 10, 0x1000, 0); noc_enable_qos_limiter(memnoc_qos_base, 0x10000, 11, 0x1000, 0); noc_set_qos_limit_bw(memnoc_qos_base, 0x10000, 2, 0x1000, 0); noc_set_qos_limit_bw(memnoc_qos_base, 0x10000, 3, 0x1000, 0); noc_set_qos_limit_bw(memnoc_qos_base, 0x10000, 10, 0x1000, 0); noc_set_qos_limit_bw(memnoc_qos_base, 0x10000, 11, 0x1000, 0); } noc_throttle_exit: spin_unlock_irqrestore(&noc_lock, flags); return 0; } EXPORT_SYMBOL(msm_bus_noc_throttle_wa); int msm_bus_noc_priority_wa(bool enable) { unsigned long flags; spin_lock_irqsave(&noc_lock, flags); if (!memnoc_qos_base) { MSM_BUS_ERR("Memnoc QoS Base address not found!"); goto noc_priority_exit; } if (enable) noc_set_qos_dflt_prio(memnoc_qos_base, 0x10000, 0, 0x1000, 7); else noc_set_qos_dflt_prio(memnoc_qos_base, 0x10000, 0, 0x1000, 6); noc_priority_exit: spin_unlock_irqrestore(&noc_lock, flags); return 0; } EXPORT_SYMBOL(msm_bus_noc_priority_wa); int msm_bus_noc_set_ops(struct msm_bus_node_device_type *bus_dev) { if (!bus_dev) Loading drivers/soc/qcom/msm_bus/msm_bus_rpmh.h +1 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ struct link_node { /* New types introduced for adhoc topology */ struct msm_bus_noc_ops { int (*qos_init)(struct msm_bus_node_device_type *dev, struct msm_bus_node_device_type *fabdev, void __iomem *qos_base, uint32_t qos_off, uint32_t qos_delta, uint32_t qos_freq); int (*set_bw)(struct msm_bus_node_device_type *dev, Loading include/linux/msm-bus.h +12 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,8 @@ int msm_bus_scale_query_tcs_cmd(struct msm_bus_tcs_usecase *tcs_usecase, uint32_t cl, unsigned int index); int msm_bus_scale_query_tcs_cmd_all(struct msm_bus_tcs_handle *tcs_handle, uint32_t cl); int msm_bus_noc_throttle_wa(bool enable); int msm_bus_noc_priority_wa(bool enable); /* AXI Port configuration APIs */ int msm_bus_axi_porthalt(int master_port); Loading Loading @@ -211,6 +213,16 @@ static inline int msm_bus_scale_query_tcs_cmd_all(struct msm_bus_tcs_handle return 0; } static inline int msm_bus_noc_throttle_wa(bool enable) { return 0; } static inline int msm_bus_noc_priority_wa(bool enable) { return 0; } #endif #if defined(CONFIG_OF) && defined(CONFIG_QCOM_BUS_SCALING) Loading Loading
drivers/soc/qcom/msm_bus/msm_bus_fabric_rpmh.c +1 −0 Original line number Diff line number Diff line Loading @@ -1004,6 +1004,7 @@ static int msm_bus_dev_init_qos(struct device *dev, void *data) bus_node_info->fabdev->noc_ops.qos_init( node_dev, bus_node_info, bus_node_info->fabdev->qos_base, bus_node_info->fabdev->base_offset, bus_node_info->fabdev->qos_off, Loading
drivers/soc/qcom/msm_bus/msm_bus_noc_rpmh.c +122 −18 Original line number Diff line number Diff line Loading @@ -15,10 +15,14 @@ #include <linux/slab.h> #include <linux/io.h> #include <linux/msm-bus-board.h> #include <linux/msm-bus.h> #include <linux/spinlock.h> #include "msm_bus_core.h" #include "msm_bus_noc.h" #include "msm_bus_rpmh.h" static DEFINE_SPINLOCK(noc_lock); /* NOC_QOS generic */ #define __CLZ(x) ((8 * sizeof(uint32_t)) - 1 - __fls(x)) #define SAT_SCALE 16 /* 16 bytes minimum for saturation */ Loading @@ -29,6 +33,7 @@ #define MAX_SAT_FIELD (NOC_QOS_SATn_SAT_BMSK >> NOC_QOS_SATn_SAT_SHFT) #define MIN_SAT_FIELD 1 #define MIN_BW_FIELD 1 #define MSM_BUS_FAB_MEM_NOC 6152 #define NOC_QOS_REG_BASE(b, o) ((b) + (o)) Loading Loading @@ -102,6 +107,8 @@ enum noc_qos_id_saturationn { NOC_QOS_SATn_SAT_SHFT = 0x0, }; static void __iomem *memnoc_qos_base; static int noc_div(uint64_t *a, uint32_t b) { if ((*a > 0) && (*a < b)) { Loading Loading @@ -169,46 +176,59 @@ static void noc_set_qos_dflt_prio(void __iomem *base, uint32_t qos_off, wmb(); } static void noc_set_qos_limiter(void __iomem *base, uint32_t qos_off, uint32_t mport, uint32_t qos_delta, struct msm_bus_noc_limiter *lim, uint32_t lim_en) static void noc_enable_qos_limiter(void __iomem *base, uint32_t qos_off, uint32_t mport, uint32_t qos_delta, uint32_t lim_en) { uint32_t reg_val, val; reg_val = readl_relaxed(NOC_QOS_MAINCTL_LOWn_ADDR(base, qos_off, mport, qos_delta)); writel_relaxed((reg_val & (~(NOC_QOS_MCTL_LIMIT_ENn_BMSK))), val = lim_en << NOC_QOS_MCTL_LIMIT_ENn_SHFT; writel_relaxed(((reg_val & (~(NOC_QOS_MCTL_LIMIT_ENn_BMSK))) | (val & NOC_QOS_MCTL_LIMIT_ENn_BMSK)), NOC_QOS_MAINCTL_LOWn_ADDR(base, qos_off, mport, qos_delta)); /* Ensure we disable limiter before config*/ /* Ensure we disable/enable limiter before exiting*/ wmb(); } static void noc_set_qos_limit_bw(void __iomem *base, uint32_t qos_off, uint32_t mport, uint32_t qos_delta, uint32_t bw) { uint32_t reg_val, val; reg_val = readl_relaxed(NOC_QOS_LIMITBWn_ADDR(base, qos_off, mport, qos_delta)); val = lim->bw << NOC_QOS_LIMITBW_BWn_SHFT; val = bw << NOC_QOS_LIMITBW_BWn_SHFT; writel_relaxed(((reg_val & (~(NOC_QOS_LIMITBW_BWn_BMSK))) | (val & NOC_QOS_LIMITBW_BWn_BMSK)), NOC_QOS_LIMITBWn_ADDR(base, qos_off, mport, qos_delta)); /* Ensure we set limiter bw before exiting*/ wmb(); } static void noc_set_qos_limit_sat(void __iomem *base, uint32_t qos_off, uint32_t mport, uint32_t qos_delta, uint32_t sat) { uint32_t reg_val, val; reg_val = readl_relaxed(NOC_QOS_LIMITBWn_ADDR(base, qos_off, mport, qos_delta)); val = lim->sat << NOC_QOS_LIMITBW_SATn_SHFT; val = sat << NOC_QOS_LIMITBW_SATn_SHFT; writel_relaxed(((reg_val & (~(NOC_QOS_LIMITBW_SATn_BMSK))) | (val & NOC_QOS_LIMITBW_SATn_BMSK)), NOC_QOS_LIMITBWn_ADDR(base, qos_off, mport, qos_delta)); /* Ensure qos limiter settings in place before possibly enabling */ /* Ensure we set limiter sat before exiting*/ wmb(); } reg_val = readl_relaxed(NOC_QOS_MAINCTL_LOWn_ADDR(base, qos_off, mport, qos_delta)); val = lim_en << NOC_QOS_MCTL_LIMIT_ENn_SHFT; writel_relaxed(((reg_val & (~(NOC_QOS_MCTL_LIMIT_ENn_BMSK))) | (val & NOC_QOS_MCTL_LIMIT_ENn_BMSK)), NOC_QOS_MAINCTL_LOWn_ADDR(base, qos_off, mport, qos_delta)); wmb(); static void noc_set_qos_limiter(void __iomem *base, uint32_t qos_off, uint32_t mport, uint32_t qos_delta, struct msm_bus_noc_limiter *lim, uint32_t lim_en) { noc_enable_qos_limiter(base, qos_off, mport, qos_delta, 0); noc_set_qos_limit_bw(base, qos_off, mport, qos_delta, lim->bw); noc_set_qos_limit_sat(base, qos_off, mport, qos_delta, lim->sat); noc_enable_qos_limiter(base, qos_off, mport, qos_delta, lim_en); } static void noc_set_qos_regulator(void __iomem *base, uint32_t qos_off, Loading Loading @@ -317,6 +337,7 @@ void msm_bus_noc_get_qos_bw(void __iomem *base, uint32_t qos_off, } static int msm_bus_noc_qos_init(struct msm_bus_node_device_type *info, struct msm_bus_node_device_type *fabdev, void __iomem *qos_base, uint32_t qos_off, uint32_t qos_delta, uint32_t qos_freq) Loading @@ -324,6 +345,7 @@ static int msm_bus_noc_qos_init(struct msm_bus_node_device_type *info, struct msm_bus_noc_qos_params *qos_params; int ret = 0; int i; unsigned long flags; qos_params = &info->node_info->qos_params; Loading @@ -333,6 +355,11 @@ static int msm_bus_noc_qos_init(struct msm_bus_node_device_type *info, goto err_qos_init; } spin_lock_irqsave(&noc_lock, flags); if (fabdev->node_info->id == MSM_BUS_FAB_MEM_NOC) memnoc_qos_base = qos_base; for (i = 0; i < info->node_info->num_qports; i++) { noc_set_qos_dflt_prio(qos_base, qos_off, info->node_info->qport[i], Loading @@ -356,10 +383,87 @@ static int msm_bus_noc_qos_init(struct msm_bus_node_device_type *info, qos_delta, qos_params->urg_fwd_en); } spin_unlock_irqrestore(&noc_lock, flags); err_qos_init: return ret; } int msm_bus_noc_throttle_wa(bool enable) { unsigned long flags; spin_lock_irqsave(&noc_lock, flags); if (!memnoc_qos_base) { MSM_BUS_ERR("Memnoc QoS Base address not found!"); goto noc_throttle_exit; } if (enable) { noc_set_qos_limit_bw(memnoc_qos_base, 0x10000, 2, 0x1000, 0x1B); noc_set_qos_limit_bw(memnoc_qos_base, 0x10000, 3, 0x1000, 0x1B); noc_set_qos_limit_bw(memnoc_qos_base, 0x10000, 10, 0x1000, 0x30); noc_set_qos_limit_bw(memnoc_qos_base, 0x10000, 11, 0x1000, 0x30); noc_enable_qos_limiter(memnoc_qos_base, 0x10000, 10, 0x1000, 1); noc_enable_qos_limiter(memnoc_qos_base, 0x10000, 11, 0x1000, 1); noc_enable_qos_limiter(memnoc_qos_base, 0x10000, 2, 0x1000, 1); noc_enable_qos_limiter(memnoc_qos_base, 0x10000, 3, 0x1000, 1); } else { noc_enable_qos_limiter(memnoc_qos_base, 0x10000, 2, 0x1000, 0); noc_enable_qos_limiter(memnoc_qos_base, 0x10000, 3, 0x1000, 0); noc_enable_qos_limiter(memnoc_qos_base, 0x10000, 10, 0x1000, 0); noc_enable_qos_limiter(memnoc_qos_base, 0x10000, 11, 0x1000, 0); noc_set_qos_limit_bw(memnoc_qos_base, 0x10000, 2, 0x1000, 0); noc_set_qos_limit_bw(memnoc_qos_base, 0x10000, 3, 0x1000, 0); noc_set_qos_limit_bw(memnoc_qos_base, 0x10000, 10, 0x1000, 0); noc_set_qos_limit_bw(memnoc_qos_base, 0x10000, 11, 0x1000, 0); } noc_throttle_exit: spin_unlock_irqrestore(&noc_lock, flags); return 0; } EXPORT_SYMBOL(msm_bus_noc_throttle_wa); int msm_bus_noc_priority_wa(bool enable) { unsigned long flags; spin_lock_irqsave(&noc_lock, flags); if (!memnoc_qos_base) { MSM_BUS_ERR("Memnoc QoS Base address not found!"); goto noc_priority_exit; } if (enable) noc_set_qos_dflt_prio(memnoc_qos_base, 0x10000, 0, 0x1000, 7); else noc_set_qos_dflt_prio(memnoc_qos_base, 0x10000, 0, 0x1000, 6); noc_priority_exit: spin_unlock_irqrestore(&noc_lock, flags); return 0; } EXPORT_SYMBOL(msm_bus_noc_priority_wa); int msm_bus_noc_set_ops(struct msm_bus_node_device_type *bus_dev) { if (!bus_dev) Loading
drivers/soc/qcom/msm_bus/msm_bus_rpmh.h +1 −0 Original line number Diff line number Diff line Loading @@ -42,6 +42,7 @@ struct link_node { /* New types introduced for adhoc topology */ struct msm_bus_noc_ops { int (*qos_init)(struct msm_bus_node_device_type *dev, struct msm_bus_node_device_type *fabdev, void __iomem *qos_base, uint32_t qos_off, uint32_t qos_delta, uint32_t qos_freq); int (*set_bw)(struct msm_bus_node_device_type *dev, Loading
include/linux/msm-bus.h +12 −0 Original line number Diff line number Diff line Loading @@ -130,6 +130,8 @@ int msm_bus_scale_query_tcs_cmd(struct msm_bus_tcs_usecase *tcs_usecase, uint32_t cl, unsigned int index); int msm_bus_scale_query_tcs_cmd_all(struct msm_bus_tcs_handle *tcs_handle, uint32_t cl); int msm_bus_noc_throttle_wa(bool enable); int msm_bus_noc_priority_wa(bool enable); /* AXI Port configuration APIs */ int msm_bus_axi_porthalt(int master_port); Loading Loading @@ -211,6 +213,16 @@ static inline int msm_bus_scale_query_tcs_cmd_all(struct msm_bus_tcs_handle return 0; } static inline int msm_bus_noc_throttle_wa(bool enable) { return 0; } static inline int msm_bus_noc_priority_wa(bool enable) { return 0; } #endif #if defined(CONFIG_OF) && defined(CONFIG_QCOM_BUS_SCALING) Loading