diff options
Diffstat (limited to 'drivers/soc')
-rw-r--r-- | drivers/soc/qcom/Kconfig | 2 | ||||
-rw-r--r-- | drivers/soc/qcom/llcc-qcom.c | 166 | ||||
-rw-r--r-- | drivers/soc/qcom/rpmh-internal.h | 11 | ||||
-rw-r--r-- | drivers/soc/qcom/rpmh-rsc.c | 181 | ||||
-rw-r--r-- | drivers/soc/qcom/rpmh.c | 10 | ||||
-rw-r--r-- | drivers/soc/qcom/rpmhpd.c | 24 | ||||
-rw-r--r-- | drivers/soc/qcom/rpmpd.c | 18 | ||||
-rw-r--r-- | drivers/soc/qcom/socinfo.c | 9 | ||||
-rw-r--r-- | drivers/soc/qcom/trace-rpmh.h | 11 |
9 files changed, 331 insertions, 101 deletions
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig index 024e420f1bb7..ae504c43d9e7 100644 --- a/drivers/soc/qcom/Kconfig +++ b/drivers/soc/qcom/Kconfig @@ -63,6 +63,7 @@ config QCOM_GSBI config QCOM_LLCC tristate "Qualcomm Technologies, Inc. LLCC driver" depends on ARCH_QCOM || COMPILE_TEST + select REGMAP_MMIO help Qualcomm Technologies, Inc. platform specific Last Level Cache Controller(LLCC) driver for platforms such as, @@ -236,6 +237,7 @@ config QCOM_ICC_BWMON tristate "QCOM Interconnect Bandwidth Monitor driver" depends on ARCH_QCOM || COMPILE_TEST select PM_OPP + select REGMAP_MMIO help Sets up driver monitoring bandwidth on various interconnects and based on that voting for interconnect bandwidth, adjusting their diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c index 82c3cfdcc560..23ce2f78c4ed 100644 --- a/drivers/soc/qcom/llcc-qcom.c +++ b/drivers/soc/qcom/llcc-qcom.c @@ -21,6 +21,8 @@ #define ACTIVATE BIT(0) #define DEACTIVATE BIT(1) +#define ACT_CLEAR BIT(0) +#define ACT_COMPLETE BIT(4) #define ACT_CTRL_OPCODE_ACTIVATE BIT(0) #define ACT_CTRL_OPCODE_DEACTIVATE BIT(1) #define ACT_CTRL_ACT_TRIG BIT(0) @@ -41,19 +43,30 @@ #define MAX_CAP_TO_BYTES(n) (n * SZ_1K) #define LLCC_TRP_ACT_CTRLn(n) (n * SZ_4K) +#define LLCC_TRP_ACT_CLEARn(n) (8 + n * SZ_4K) #define LLCC_TRP_STATUSn(n) (4 + n * SZ_4K) #define LLCC_TRP_ATTR0_CFGn(n) (0x21000 + SZ_8 * n) #define LLCC_TRP_ATTR1_CFGn(n) (0x21004 + SZ_8 * n) +#define LLCC_TRP_ATTR2_CFGn(n) (0x21100 + SZ_8 * n) #define LLCC_TRP_SCID_DIS_CAP_ALLOC 0x21f00 #define LLCC_TRP_PCB_ACT 0x21f04 +#define LLCC_TRP_ALGO_CFG1 0x21f0c +#define LLCC_TRP_ALGO_CFG2 0x21f10 +#define LLCC_TRP_ALGO_CFG3 0x21f14 +#define LLCC_TRP_ALGO_CFG4 0x21f18 +#define LLCC_TRP_ALGO_CFG5 0x21f1c #define LLCC_TRP_WRSC_EN 0x21f20 +#define LLCC_TRP_ALGO_CFG6 0x21f24 +#define LLCC_TRP_ALGO_CFG7 0x21f28 #define LLCC_TRP_WRSC_CACHEABLE_EN 0x21f2c +#define LLCC_TRP_ALGO_CFG8 0x21f30 #define BANK_OFFSET_STRIDE 0x80000 #define LLCC_VERSION_2_0_0_0 0x02000000 #define LLCC_VERSION_2_1_0_0 0x02010000 +#define LLCC_VERSION_4_1_0_0 0x04010000 /** * struct llcc_slice_config - Data associated with the llcc slice @@ -97,6 +110,14 @@ struct llcc_slice_config { bool activate_on_init; bool write_scid_en; bool write_scid_cacheable_en; + bool stale_en; + bool stale_cap_en; + bool mru_uncap_en; + bool mru_rollover; + bool alloc_oneway_en; + bool ovcap_en; + bool ovcap_prio; + bool vict_prio; }; struct qcom_llcc_config { @@ -297,6 +318,38 @@ static const struct llcc_slice_config sm8450_data[] = { {LLCC_AENPU, 8, 2048, 1, 1, 0xFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0 }, }; +static const struct llcc_slice_config sm8550_data[] = { + {LLCC_CPUSS, 1, 5120, 1, 0, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_VIDSC0, 2, 512, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_AUDIO, 6, 1024, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_MDMHPGRW, 25, 1024, 4, 0, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_MODHW, 26, 1024, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CMPT, 10, 4096, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_GPUHTW, 11, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_GPU, 9, 3096, 1, 0, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_MMUHWT, 18, 768, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_DISP, 16, 6144, 1, 1, 0xFFFFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_MDMPNG, 27, 1024, 0, 1, 0xF00000, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_AUDHW, 22, 1024, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CVP, 8, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_MODPE, 29, 64, 1, 1, 0xF00000, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, }, + {LLCC_WRCACHE, 31, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CAMEXP0, 4, 256, 4, 1, 0xF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CPUHWT, 5, 512, 1, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CAMEXP1, 7, 3200, 3, 1, 0xFFFFF0, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CMPTHCP, 17, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_LCPDARE, 30, 128, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, }, + {LLCC_AENPU, 3, 3072, 1, 1, 0xFE01FF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_ISLAND1, 12, 1792, 7, 1, 0xFE00, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_ISLAND4, 15, 256, 7, 1, 0x10000, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CAMEXP2, 19, 3200, 3, 1, 0xFFFFF0, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CAMEXP3, 20, 3200, 2, 1, 0xFFFFF0, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_CAMEXP4, 21, 3200, 2, 1, 0xFFFFF0, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_DISP_WB, 23, 1024, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_DISP_1, 24, 6144, 1, 1, 0xFFFFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, + {LLCC_VIDVSP, 28, 256, 4, 1, 0xFFFFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, +}; + static const struct llcc_edac_reg_offset llcc_v1_edac_reg_offset = { .trp_ecc_error_status0 = 0x20344, .trp_ecc_error_status1 = 0x20348, @@ -443,6 +496,14 @@ static const struct qcom_llcc_config sm8450_cfg = { .edac_reg_offset = &llcc_v2_1_edac_reg_offset, }; +static const struct qcom_llcc_config sm8550_cfg = { + .sct_data = sm8550_data, + .size = ARRAY_SIZE(sm8550_data), + .need_llcc_cfg = true, + .reg_offset = llcc_v2_1_reg_offset, + .edac_reg_offset = &llcc_v2_1_edac_reg_offset, +}; + static struct llcc_drv_data *drv_data = (void *) -EPROBE_DEFER; /** @@ -497,6 +558,7 @@ static int llcc_update_act_ctrl(u32 sid, u32 act_ctrl_reg_val, u32 status) { u32 act_ctrl_reg; + u32 act_clear_reg; u32 status_reg; u32 slice_status; int ret; @@ -505,6 +567,7 @@ static int llcc_update_act_ctrl(u32 sid, return PTR_ERR(drv_data); act_ctrl_reg = LLCC_TRP_ACT_CTRLn(sid); + act_clear_reg = LLCC_TRP_ACT_CLEARn(sid); status_reg = LLCC_TRP_STATUSn(sid); /* Set the ACTIVE trigger */ @@ -521,9 +584,22 @@ static int llcc_update_act_ctrl(u32 sid, if (ret) return ret; + if (drv_data->version >= LLCC_VERSION_4_1_0_0) { + ret = regmap_read_poll_timeout(drv_data->bcast_regmap, status_reg, + slice_status, (slice_status & ACT_COMPLETE), + 0, LLCC_STATUS_READ_DELAY); + if (ret) + return ret; + } + ret = regmap_read_poll_timeout(drv_data->bcast_regmap, status_reg, slice_status, !(slice_status & status), 0, LLCC_STATUS_READ_DELAY); + + if (drv_data->version >= LLCC_VERSION_4_1_0_0) + ret = regmap_write(drv_data->bcast_regmap, act_clear_reg, + ACT_CLEAR); + return ret; } @@ -636,8 +712,10 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, const struct qcom_llcc_config *cfg) { int ret; + u32 attr2_cfg; u32 attr1_cfg; u32 attr0_cfg; + u32 attr2_val; u32 attr1_val; u32 attr0_val; u32 max_cap_cacheline; @@ -667,8 +745,14 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, if (ret) return ret; - attr0_val = config->res_ways & ATTR0_RES_WAYS_MASK; - attr0_val |= config->bonus_ways << ATTR0_BONUS_WAYS_SHIFT; + if (drv_data->version >= LLCC_VERSION_4_1_0_0) { + attr2_cfg = LLCC_TRP_ATTR2_CFGn(config->slice_id); + attr0_val = config->res_ways; + attr2_val = config->bonus_ways; + } else { + attr0_val = config->res_ways & ATTR0_RES_WAYS_MASK; + attr0_val |= config->bonus_ways << ATTR0_BONUS_WAYS_SHIFT; + } attr0_cfg = LLCC_TRP_ATTR0_CFGn(config->slice_id); @@ -676,6 +760,12 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, if (ret) return ret; + if (drv_data->version >= LLCC_VERSION_4_1_0_0) { + ret = regmap_write(drv_data->bcast_regmap, attr2_cfg, attr2_val); + if (ret) + return ret; + } + if (cfg->need_llcc_cfg) { u32 disable_cap_alloc, retain_pc; @@ -685,11 +775,13 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, if (ret) return ret; - retain_pc = config->retain_on_pc << config->slice_id; - ret = regmap_write(drv_data->bcast_regmap, - LLCC_TRP_PCB_ACT, retain_pc); - if (ret) - return ret; + if (drv_data->version < LLCC_VERSION_4_1_0_0) { + retain_pc = config->retain_on_pc << config->slice_id; + ret = regmap_write(drv_data->bcast_regmap, + LLCC_TRP_PCB_ACT, retain_pc); + if (ret) + return ret; + } } if (drv_data->version >= LLCC_VERSION_2_0_0_0) { @@ -712,6 +804,65 @@ static int _qcom_llcc_cfg_program(const struct llcc_slice_config *config, return ret; } + if (drv_data->version >= LLCC_VERSION_4_1_0_0) { + u32 stale_en; + u32 stale_cap_en; + u32 mru_uncap_en; + u32 mru_rollover; + u32 alloc_oneway_en; + u32 ovcap_en; + u32 ovcap_prio; + u32 vict_prio; + + stale_en = config->stale_en << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_ALGO_CFG1, + BIT(config->slice_id), stale_en); + if (ret) + return ret; + + stale_cap_en = config->stale_cap_en << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_ALGO_CFG2, + BIT(config->slice_id), stale_cap_en); + if (ret) + return ret; + + mru_uncap_en = config->mru_uncap_en << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_ALGO_CFG3, + BIT(config->slice_id), mru_uncap_en); + if (ret) + return ret; + + mru_rollover = config->mru_rollover << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_ALGO_CFG4, + BIT(config->slice_id), mru_rollover); + if (ret) + return ret; + + alloc_oneway_en = config->alloc_oneway_en << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_ALGO_CFG5, + BIT(config->slice_id), alloc_oneway_en); + if (ret) + return ret; + + ovcap_en = config->ovcap_en << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_ALGO_CFG6, + BIT(config->slice_id), ovcap_en); + if (ret) + return ret; + + ovcap_prio = config->ovcap_prio << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_ALGO_CFG7, + BIT(config->slice_id), ovcap_prio); + if (ret) + return ret; + + vict_prio = config->vict_prio << config->slice_id; + ret = regmap_update_bits(drv_data->bcast_regmap, LLCC_TRP_ALGO_CFG8, + BIT(config->slice_id), vict_prio); + if (ret) + return ret; + } + if (config->activate_on_init) { desc.slice_id = config->slice_id; ret = llcc_slice_activate(&desc); @@ -875,6 +1026,7 @@ static const struct of_device_id qcom_llcc_of_match[] = { { .compatible = "qcom,sm8250-llcc", .data = &sm8250_cfg }, { .compatible = "qcom,sm8350-llcc", .data = &sm8350_cfg }, { .compatible = "qcom,sm8450-llcc", .data = &sm8450_cfg }, + { .compatible = "qcom,sm8550-llcc", .data = &sm8550_cfg }, { } }; MODULE_DEVICE_TABLE(of, qcom_llcc_of_match); diff --git a/drivers/soc/qcom/rpmh-internal.h b/drivers/soc/qcom/rpmh-internal.h index 39f53586f724..e3cf1beff803 100644 --- a/drivers/soc/qcom/rpmh-internal.h +++ b/drivers/soc/qcom/rpmh-internal.h @@ -59,7 +59,6 @@ struct tcs_group { * @cmd: the payload that will be part of the @msg * @completion: triggered when request is done * @dev: the device making the request - * @err: err return from the controller * @needs_free: check to free dynamically allocated request object */ struct rpmh_request { @@ -67,7 +66,6 @@ struct rpmh_request { struct tcs_cmd cmd[MAX_RPMH_PAYLOAD]; struct completion *completion; const struct device *dev; - int err; bool needs_free; }; @@ -86,6 +84,11 @@ struct rpmh_ctrlr { struct list_head batch_cache; }; +struct rsc_ver { + u32 major; + u32 minor; +}; + /** * struct rsc_drv: the Direct Resource Voter (DRV) of the * Resource State Coordinator controller (RSC) @@ -129,6 +132,8 @@ struct rsc_drv { wait_queue_head_t tcs_wait; struct rpmh_ctrlr client; struct device *dev; + struct rsc_ver ver; + u32 *regs; }; int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg); @@ -137,7 +142,7 @@ int rpmh_rsc_write_ctrl_data(struct rsc_drv *drv, void rpmh_rsc_invalidate(struct rsc_drv *drv); void rpmh_rsc_write_next_wakeup(struct rsc_drv *drv); -void rpmh_tx_done(const struct tcs_request *msg, int r); +void rpmh_tx_done(const struct tcs_request *msg); int rpmh_flush(struct rpmh_ctrlr *ctrlr); #endif /* __RPM_INTERNAL_H__ */ diff --git a/drivers/soc/qcom/rpmh-rsc.c b/drivers/soc/qcom/rpmh-rsc.c index c51567b778ef..0f8b2249f889 100644 --- a/drivers/soc/qcom/rpmh-rsc.c +++ b/drivers/soc/qcom/rpmh-rsc.c @@ -36,16 +36,38 @@ #define CREATE_TRACE_POINTS #include "trace-rpmh.h" -#define RSC_DRV_TCS_OFFSET 672 -#define RSC_DRV_CMD_OFFSET 20 + +#define RSC_DRV_ID 0 + +#define MAJOR_VER_MASK 0xFF +#define MAJOR_VER_SHIFT 16 +#define MINOR_VER_MASK 0xFF +#define MINOR_VER_SHIFT 8 + +enum { + RSC_DRV_TCS_OFFSET, + RSC_DRV_CMD_OFFSET, + DRV_SOLVER_CONFIG, + DRV_PRNT_CHLD_CONFIG, + RSC_DRV_IRQ_ENABLE, + RSC_DRV_IRQ_STATUS, + RSC_DRV_IRQ_CLEAR, + RSC_DRV_CMD_WAIT_FOR_CMPL, + RSC_DRV_CONTROL, + RSC_DRV_STATUS, + RSC_DRV_CMD_ENABLE, + RSC_DRV_CMD_MSGID, + RSC_DRV_CMD_ADDR, + RSC_DRV_CMD_DATA, + RSC_DRV_CMD_STATUS, + RSC_DRV_CMD_RESP_DATA, +}; /* DRV HW Solver Configuration Information Register */ -#define DRV_SOLVER_CONFIG 0x04 #define DRV_HW_SOLVER_MASK 1 #define DRV_HW_SOLVER_SHIFT 24 /* DRV TCS Configuration Information Register */ -#define DRV_PRNT_CHLD_CONFIG 0x0C #define DRV_NUM_TCS_MASK 0x3F #define DRV_NUM_TCS_SHIFT 6 #define DRV_NCPT_MASK 0x1F @@ -59,35 +81,6 @@ #define RSC_DRV_CTL_TCS_DATA_LO_MASK 0xFFFFFFFF #define RSC_DRV_CTL_TCS_DATA_SIZE 32 -/* Offsets for common TCS Registers, one bit per TCS */ -#define RSC_DRV_IRQ_ENABLE 0x00 -#define RSC_DRV_IRQ_STATUS 0x04 -#define RSC_DRV_IRQ_CLEAR 0x08 /* w/o; write 1 to clear */ - -/* - * Offsets for per TCS Registers. - * - * TCSes start at 0x10 from tcs_base and are stored one after another. - * Multiply tcs_id by RSC_DRV_TCS_OFFSET to find a given TCS and add one - * of the below to find a register. - */ -#define RSC_DRV_CMD_WAIT_FOR_CMPL 0x10 /* 1 bit per command */ -#define RSC_DRV_CONTROL 0x14 -#define RSC_DRV_STATUS 0x18 /* zero if tcs is busy */ -#define RSC_DRV_CMD_ENABLE 0x1C /* 1 bit per command */ - -/* - * Offsets for per command in a TCS. - * - * Commands (up to 16) start at 0x30 in a TCS; multiply command index - * by RSC_DRV_CMD_OFFSET and add one of the below to find a register. - */ -#define RSC_DRV_CMD_MSGID 0x30 -#define RSC_DRV_CMD_ADDR 0x34 -#define RSC_DRV_CMD_DATA 0x38 -#define RSC_DRV_CMD_STATUS 0x3C -#define RSC_DRV_CMD_RESP_DATA 0x40 - #define TCS_AMC_MODE_ENABLE BIT(16) #define TCS_AMC_MODE_TRIGGER BIT(24) @@ -160,16 +153,54 @@ static inline unsigned long xloops_to_cycles(u64 xloops) return (xloops * loops_per_jiffy * HZ) >> 32; } +static u32 rpmh_rsc_reg_offset_ver_2_7[] = { + [RSC_DRV_TCS_OFFSET] = 672, + [RSC_DRV_CMD_OFFSET] = 20, + [DRV_SOLVER_CONFIG] = 0x04, + [DRV_PRNT_CHLD_CONFIG] = 0x0C, + [RSC_DRV_IRQ_ENABLE] = 0x00, + [RSC_DRV_IRQ_STATUS] = 0x04, + [RSC_DRV_IRQ_CLEAR] = 0x08, + [RSC_DRV_CMD_WAIT_FOR_CMPL] = 0x10, + [RSC_DRV_CONTROL] = 0x14, + [RSC_DRV_STATUS] = 0x18, + [RSC_DRV_CMD_ENABLE] = 0x1C, + [RSC_DRV_CMD_MSGID] = 0x30, + [RSC_DRV_CMD_ADDR] = 0x34, + [RSC_DRV_CMD_DATA] = 0x38, + [RSC_DRV_CMD_STATUS] = 0x3C, + [RSC_DRV_CMD_RESP_DATA] = 0x40, +}; + +static u32 rpmh_rsc_reg_offset_ver_3_0[] = { + [RSC_DRV_TCS_OFFSET] = 672, + [RSC_DRV_CMD_OFFSET] = 24, + [DRV_SOLVER_CONFIG] = 0x04, + [DRV_PRNT_CHLD_CONFIG] = 0x0C, + [RSC_DRV_IRQ_ENABLE] = 0x00, + [RSC_DRV_IRQ_STATUS] = 0x04, + [RSC_DRV_IRQ_CLEAR] = 0x08, + [RSC_DRV_CMD_WAIT_FOR_CMPL] = 0x20, + [RSC_DRV_CONTROL] = 0x24, + [RSC_DRV_STATUS] = 0x28, + [RSC_DRV_CMD_ENABLE] = 0x2C, + [RSC_DRV_CMD_MSGID] = 0x34, + [RSC_DRV_CMD_ADDR] = 0x38, + [RSC_DRV_CMD_DATA] = 0x3C, + [RSC_DRV_CMD_STATUS] = 0x40, + [RSC_DRV_CMD_RESP_DATA] = 0x44, +}; + static inline void __iomem * tcs_reg_addr(const struct rsc_drv *drv, int reg, int tcs_id) { - return drv->tcs_base + RSC_DRV_TCS_OFFSET * tcs_id + reg; + return drv->tcs_base + drv->regs[RSC_DRV_TCS_OFFSET] * tcs_id + reg; } static inline void __iomem * tcs_cmd_addr(const struct rsc_drv *drv, int reg, int tcs_id, int cmd_id) { - return tcs_reg_addr(drv, reg, tcs_id) + RSC_DRV_CMD_OFFSET * cmd_id; + return tcs_reg_addr(drv, reg, tcs_id) + drv->regs[RSC_DRV_CMD_OFFSET] * cmd_id; } static u32 read_tcs_cmd(const struct rsc_drv *drv, int reg, int tcs_id, @@ -237,7 +268,7 @@ static void tcs_invalidate(struct rsc_drv *drv, int type) return; for (m = tcs->offset; m < tcs->offset + tcs->num_tcs; m++) - write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, m, 0); + write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_ENABLE], m, 0); bitmap_zero(tcs->slots, MAX_TCS_SLOTS); } @@ -351,24 +382,25 @@ static const struct tcs_request *get_req_from_tcs(struct rsc_drv *drv, static void __tcs_set_trigger(struct rsc_drv *drv, int tcs_id, bool trigger) { u32 enable; + u32 reg = drv->regs[RSC_DRV_CONTROL]; /* * HW req: Clear the DRV_CONTROL and enable TCS again * While clearing ensure that the AMC mode trigger is cleared * and then the mode enable is cleared. */ - enable = read_tcs_reg(drv, RSC_DRV_CONTROL, tcs_id); + enable = read_tcs_reg(drv, reg, tcs_id); enable &= ~TCS_AMC_MODE_TRIGGER; - write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable); + write_tcs_reg_sync(drv, reg, tcs_id, enable); enable &= ~TCS_AMC_MODE_ENABLE; - write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable); + write_tcs_reg_sync(drv, reg, tcs_id, enable); if (trigger) { /* Enable the AMC mode on the TCS and then trigger the TCS */ enable = TCS_AMC_MODE_ENABLE; - write_tcs_reg_sync(drv, RSC_DRV_CONTROL, tcs_id, enable); + write_tcs_reg_sync(drv, reg, tcs_id, enable); enable |= TCS_AMC_MODE_TRIGGER; - write_tcs_reg(drv, RSC_DRV_CONTROL, tcs_id, enable); + write_tcs_reg(drv, reg, tcs_id, enable); } } @@ -384,13 +416,14 @@ static void __tcs_set_trigger(struct rsc_drv *drv, int tcs_id, bool trigger) static void enable_tcs_irq(struct rsc_drv *drv, int tcs_id, bool enable) { u32 data; + u32 reg = drv->regs[RSC_DRV_IRQ_ENABLE]; - data = readl_relaxed(drv->tcs_base + RSC_DRV_IRQ_ENABLE); + data = readl_relaxed(drv->tcs_base + reg); if (enable) data |= BIT(tcs_id); else data &= ~BIT(tcs_id); - writel_relaxed(data, drv->tcs_base + RSC_DRV_IRQ_ENABLE); + writel_relaxed(data, drv->tcs_base + reg); } /** @@ -406,34 +439,18 @@ static void enable_tcs_irq(struct rsc_drv *drv, int tcs_id, bool enable) static irqreturn_t tcs_tx_done(int irq, void *p) { struct rsc_drv *drv = p; - int i, j, err = 0; + int i; unsigned long irq_status; const struct tcs_request *req; - struct tcs_cmd *cmd; - irq_status = readl_relaxed(drv->tcs_base + RSC_DRV_IRQ_STATUS); + irq_status = readl_relaxed(drv->tcs_base + drv->regs[RSC_DRV_IRQ_STATUS]); for_each_set_bit(i, &irq_status, BITS_PER_TYPE(u32)) { req = get_req_from_tcs(drv, i); if (WARN_ON(!req)) goto skip; - err = 0; - for (j = 0; j < req->num_cmds; j++) { - u32 sts; - - cmd = &req->cmds[j]; - sts = read_tcs_cmd(drv, RSC_DRV_CMD_STATUS, i, j); - if (!(sts & CMD_STATUS_ISSUED) || - ((req->wait_for_compl || cmd->wait) && - !(sts & CMD_STATUS_COMPL))) { - pr_err("Incomplete request: %s: addr=%#x data=%#x", - drv->name, cmd->addr, cmd->data); - err = -EIO; - } - } - - trace_rpmh_tx_done(drv, i, req, err); + trace_rpmh_tx_done(drv, i, req); /* * If wake tcs was re-purposed for sending active @@ -444,8 +461,8 @@ static irqreturn_t tcs_tx_done(int irq, void *p) __tcs_set_trigger(drv, i, false); skip: /* Reclaim the TCS */ - write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, i, 0); - writel_relaxed(BIT(i), drv->tcs_base + RSC_DRV_IRQ_CLEAR); + write_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], i, 0); + writel_relaxed(BIT(i), drv->tcs_base + drv->regs[RSC_DRV_IRQ_CLEAR]); spin_lock(&drv->lock); clear_bit(i, drv->tcs_in_use); /* @@ -458,7 +475,7 @@ skip: spin_unlock(&drv->lock); wake_up(&drv->tcs_wait); if (req) - rpmh_tx_done(req, err); + rpmh_tx_done(req); } return IRQ_HANDLED; @@ -496,14 +513,14 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id, */ msgid |= cmd->wait ? CMD_MSGID_RESP_REQ : 0; - write_tcs_cmd(drv, RSC_DRV_CMD_MSGID, tcs_id, j, msgid); - write_tcs_cmd(drv, RSC_DRV_CMD_ADDR, tcs_id, j, cmd->addr); - write_tcs_cmd(drv, RSC_DRV_CMD_DATA, tcs_id, j, cmd->data); + write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_MSGID], tcs_id, j, msgid); + write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_ADDR], tcs_id, j, cmd->addr); + write_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_DATA], tcs_id, j, cmd->data); trace_rpmh_send_msg(drv, tcs_id, j, msgid, cmd); } - cmd_enable |= read_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id); - write_tcs_reg(drv, RSC_DRV_CMD_ENABLE, tcs_id, cmd_enable); + cmd_enable |= read_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id); + write_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, cmd_enable); } /** @@ -535,10 +552,10 @@ static int check_for_req_inflight(struct rsc_drv *drv, struct tcs_group *tcs, int i = tcs->offset; for_each_set_bit_from(i, drv->tcs_in_use, tcs->offset + tcs->num_tcs) { - curr_enabled = read_tcs_reg(drv, RSC_DRV_CMD_ENABLE, i); + curr_enabled = read_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], i); for_each_set_bit(j, &curr_enabled, MAX_CMDS_PER_TCS) { - addr = read_tcs_cmd(drv, RSC_DRV_CMD_ADDR, i, j); + addr = read_tcs_cmd(drv, drv->regs[RSC_DRV_CMD_ADDR], i, j); for (k = 0; k < msg->num_cmds; k++) { if (addr == msg->cmds[k].addr) return -EBUSY; @@ -649,7 +666,7 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg) * repurposed TCS to avoid triggering them. tcs->slots will be * cleaned from rpmh_flush() by invoking rpmh_rsc_invalidate() */ - write_tcs_reg_sync(drv, RSC_DRV_CMD_ENABLE, tcs_id, 0); + write_tcs_reg_sync(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, 0); enable_tcs_irq(drv, tcs_id, true); } spin_unlock_irqrestore(&drv->lock, flags); @@ -957,7 +974,7 @@ static int rpmh_probe_tcs_config(struct platform_device *pdev, struct rsc_drv *d return ret; drv->tcs_base = drv->base + offset; - config = readl_relaxed(drv->base + DRV_PRNT_CHLD_CONFIG); + config = readl_relaxed(drv->base + drv->regs[DRV_PRNT_CHLD_CONFIG]); max_tcs = config; max_tcs &= DRV_NUM_TCS_MASK << (DRV_NUM_TCS_SHIFT * drv->id); @@ -1019,6 +1036,7 @@ static int rpmh_rsc_probe(struct platform_device *pdev) char drv_id[10] = {0}; int ret, irq; u32 solver_config; + u32 rsc_id; /* * Even though RPMh doesn't directly use cmd-db, all of its children @@ -1049,6 +1067,17 @@ static int rpmh_rsc_probe(struct platform_device *pdev) if (IS_ERR(drv->base)) return PTR_ERR(drv->base); + rsc_id = readl_relaxed(drv->base + RSC_DRV_ID); + drv->ver.major = rsc_id & (MAJOR_VER_MASK << MAJOR_VER_SHIFT); + drv->ver.major >>= MAJOR_VER_SHIFT; + drv->ver.minor = rsc_id & (MINOR_VER_MASK << MINOR_VER_SHIFT); + drv->ver.minor >>= MINOR_VER_SHIFT; + + if (drv->ver.major == 3 && drv->ver.minor == 0) + drv->regs = rpmh_rsc_reg_offset_ver_3_0; + else + drv->regs = rpmh_rsc_reg_offset_ver_2_7; + ret = rpmh_probe_tcs_config(pdev, drv); if (ret) return ret; @@ -1072,7 +1101,7 @@ static int rpmh_rsc_probe(struct platform_device *pdev) * 'HW solver' mode where they can be in autonomous mode executing low * power mode to power down. */ - solver_config = readl_relaxed(drv->base + DRV_SOLVER_CONFIG); + solver_config = readl_relaxed(drv->base + drv->regs[DRV_SOLVER_CONFIG]); solver_config &= DRV_HW_SOLVER_MASK << DRV_HW_SOLVER_SHIFT; solver_config = solver_config >> DRV_HW_SOLVER_SHIFT; if (!solver_config) { @@ -1088,7 +1117,7 @@ static int rpmh_rsc_probe(struct platform_device *pdev) /* Enable the active TCS to send requests immediately */ writel_relaxed(drv->tcs[ACTIVE_TCS].mask, - drv->tcs_base + RSC_DRV_IRQ_ENABLE); + drv->tcs_base + drv->regs[RSC_DRV_IRQ_ENABLE]); spin_lock_init(&drv->client.cache_lock); INIT_LIST_HEAD(&drv->client.cache); diff --git a/drivers/soc/qcom/rpmh.c b/drivers/soc/qcom/rpmh.c index 3a53ed99d03c..08e09642d7f5 100644 --- a/drivers/soc/qcom/rpmh.c +++ b/drivers/soc/qcom/rpmh.c @@ -76,19 +76,13 @@ static struct rpmh_ctrlr *get_rpmh_ctrlr(const struct device *dev) return &drv->client; } -void rpmh_tx_done(const struct tcs_request *msg, int r) +void rpmh_tx_done(const struct tcs_request *msg) { struct rpmh_request *rpm_msg = container_of(msg, struct rpmh_request, msg); struct completion *compl = rpm_msg->completion; bool free = rpm_msg->needs_free; - rpm_msg->err = r; - - if (r) - dev_err(rpm_msg->dev, "RPMH TX fail in msg addr=%#x, err=%d\n", - rpm_msg->msg.cmds[0].addr, r); - if (!compl) goto exit; @@ -194,7 +188,7 @@ static int __rpmh_write(const struct device *dev, enum rpmh_state state, } else { /* Clean up our call by spoofing tx_done */ ret = 0; - rpmh_tx_done(&rpm_msg->msg, ret); + rpmh_tx_done(&rpm_msg->msg); } return ret; diff --git a/drivers/soc/qcom/rpmhpd.c b/drivers/soc/qcom/rpmhpd.c index 7af68cd720f5..4c2d2c296790 100644 --- a/drivers/soc/qcom/rpmhpd.c +++ b/drivers/soc/qcom/rpmhpd.c @@ -372,6 +372,29 @@ static const struct rpmhpd_desc sm8450_desc = { .num_pds = ARRAY_SIZE(sm8450_rpmhpds), }; +/* SM8550 RPMH powerdomains */ +static struct rpmhpd *sm8550_rpmhpds[] = { + [SM8550_CX] = &cx, + [SM8550_CX_AO] = &cx_ao, + [SM8550_EBI] = &ebi, + [SM8550_GFX] = &gfx, + [SM8550_LCX] = &lcx, + [SM8550_LMX] = &lmx, + [SM8550_MMCX] = &mmcx_w_cx_parent, + [SM8550_MMCX_AO] = &mmcx_ao_w_cx_parent, + [SM8550_MSS] = &mss, + [SM8550_MX] = &mx, + [SM8550_MX_AO] = &mx_ao, + [SM8550_MXC] = &mxc, + [SM8550_MXC_AO] = &mxc_ao, + [SM8550_NSP] = &nsp, +}; + +static const struct rpmhpd_desc sm8550_desc = { + .rpmhpds = sm8550_rpmhpds, + .num_pds = ARRAY_SIZE(sm8550_rpmhpds), +}; + /* QDU1000/QRU1000 RPMH powerdomains */ static struct rpmhpd *qdu1000_rpmhpds[] = { [QDU1000_CX] = &cx, @@ -477,6 +500,7 @@ static const struct of_device_id rpmhpd_match_table[] = { { .compatible = "qcom,sm8250-rpmhpd", .data = &sm8250_desc }, { .compatible = "qcom,sm8350-rpmhpd", .data = &sm8350_desc }, { .compatible = "qcom,sm8450-rpmhpd", .data = &sm8450_desc }, + { .compatible = "qcom,sm8550-rpmhpd", .data = &sm8550_desc }, { } }; MODULE_DEVICE_TABLE(of, rpmhpd_match_table); diff --git a/drivers/soc/qcom/rpmpd.c b/drivers/soc/qcom/rpmpd.c index 337b1ad1cd3b..f0db6a10cf4e 100644 --- a/drivers/soc/qcom/rpmpd.c +++ b/drivers/soc/qcom/rpmpd.c @@ -471,6 +471,23 @@ static const struct rpmpd_desc qcm2290_desc = { .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR, }; +static struct rpmpd *sm4250_rpmpds[] = { + [SM4250_VDDCX] = &sm6115_vddcx, + [SM4250_VDDCX_AO] = &sm6115_vddcx_ao, + [SM4250_VDDCX_VFL] = &sm6115_vddcx_vfl, + [SM4250_VDDMX] = &sm6115_vddmx, + [SM4250_VDDMX_AO] = &sm6115_vddmx_ao, + [SM4250_VDDMX_VFL] = &sm6115_vddmx_vfl, + [SM4250_VDD_LPI_CX] = &sm6115_vdd_lpi_cx, + [SM4250_VDD_LPI_MX] = &sm6115_vdd_lpi_mx, +}; + +static const struct rpmpd_desc sm4250_desc = { + .rpmpds = sm4250_rpmpds, + .num_pds = ARRAY_SIZE(sm4250_rpmpds), + .max_state = RPM_SMD_LEVEL_TURBO_NO_CPR, +}; + static const struct of_device_id rpmpd_match_table[] = { { .compatible = "qcom,mdm9607-rpmpd", .data = &mdm9607_desc }, { .compatible = "qcom,msm8226-rpmpd", .data = &msm8226_desc }, @@ -485,6 +502,7 @@ static const struct of_device_id rpmpd_match_table[] = { { .compatible = "qcom,qcm2290-rpmpd", .data = &qcm2290_desc }, { .compatible = "qcom,qcs404-rpmpd", .data = &qcs404_desc }, { .compatible = "qcom,sdm660-rpmpd", .data = &sdm660_desc }, + { .compatible = "qcom,sm4250-rpmpd", .data = &sm4250_desc }, { .compatible = "qcom,sm6115-rpmpd", .data = &sm6115_desc }, { .compatible = "qcom,sm6125-rpmpd", .data = &sm6125_desc }, { .compatible = "qcom,sm6375-rpmpd", .data = &sm6375_desc }, diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c index 545934aead43..ebcbf9b9c18b 100644 --- a/drivers/soc/qcom/socinfo.c +++ b/drivers/soc/qcom/socinfo.c @@ -250,6 +250,8 @@ static const struct soc_id soc_id[] = { { qcom_board_id(MSM8926) }, { qcom_board_id(MSM8326) }, { qcom_board_id(MSM8916) }, + { qcom_board_id(MSM8956) }, + { qcom_board_id(MSM8976) }, { qcom_board_id(MSM8994) }, { qcom_board_id_named(APQ8074PRO_AA, "APQ8074PRO-AA") }, { qcom_board_id_named(APQ8074PRO_AB, "APQ8074PRO-AB") }, @@ -305,6 +307,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(SDA658) }, { qcom_board_id(SDA630) }, { qcom_board_id(SDM450) }, + { qcom_board_id(SM8150) }, { qcom_board_id(SDA845) }, { qcom_board_id(IPQ8072) }, { qcom_board_id(IPQ8076) }, @@ -315,6 +318,7 @@ static const struct soc_id soc_id[] = { { qcom_board_id(SDA632) }, { qcom_board_id(SDA450) }, { qcom_board_id(SM8250) }, + { qcom_board_id(SA8155) }, { qcom_board_id(IPQ8070) }, { qcom_board_id(IPQ8071) }, { qcom_board_id(IPQ8072A) }, @@ -326,18 +330,23 @@ static const struct soc_id soc_id[] = { { qcom_board_id(IPQ8071A) }, { qcom_board_id(IPQ6018) }, { qcom_board_id(IPQ6028) }, + { qcom_board_id(SM4250) }, { qcom_board_id(IPQ6000) }, { qcom_board_id(IPQ6010) }, { qcom_board_id(SC7180) }, { qcom_board_id(SM6350) }, { qcom_board_id(SM8350) }, + { qcom_board_id(SM6115) }, { qcom_board_id(SC8280XP) }, { qcom_board_id(IPQ6005) }, { qcom_board_id(QRB5165) }, { qcom_board_id(SM8450) }, + { qcom_board_id(SM8550) }, { qcom_board_id(SM7225) }, { qcom_board_id(SA8295P) }, { qcom_board_id(SA8540P) }, + { qcom_board_id(QCM4290) }, + { qcom_board_id(QCS4290) }, { qcom_board_id_named(SM8450_2, "SM8450") }, { qcom_board_id_named(SM8450_3, "SM8450") }, { qcom_board_id(SC7280) }, diff --git a/drivers/soc/qcom/trace-rpmh.h b/drivers/soc/qcom/trace-rpmh.h index feb0cb455e37..12b676b20cb2 100644 --- a/drivers/soc/qcom/trace-rpmh.h +++ b/drivers/soc/qcom/trace-rpmh.h @@ -14,16 +14,15 @@ TRACE_EVENT(rpmh_tx_done, - TP_PROTO(struct rsc_drv *d, int m, const struct tcs_request *r, int e), + TP_PROTO(struct rsc_drv *d, int m, const struct tcs_request *r), - TP_ARGS(d, m, r, e), + TP_ARGS(d, m, r), TP_STRUCT__entry( __string(name, d->name) __field(int, m) __field(u32, addr) __field(u32, data) - __field(int, err) ), TP_fast_assign( @@ -31,12 +30,10 @@ TRACE_EVENT(rpmh_tx_done, __entry->m = m; __entry->addr = r->cmds[0].addr; __entry->data = r->cmds[0].data; - __entry->err = e; ), - TP_printk("%s: ack: tcs-m: %d addr: %#x data: %#x errno: %d", - __get_str(name), __entry->m, __entry->addr, __entry->data, - __entry->err) + TP_printk("%s: ack: tcs-m: %d addr: %#x data: %#x", + __get_str(name), __entry->m, __entry->addr, __entry->data) ); TRACE_EVENT(rpmh_send_msg, |