diff --git a/drivers/platform/msm/msm-geni-se.c b/drivers/platform/msm/msm-geni-se.c index b5d5aa995cbe..83a25efdc62b 100644 --- a/drivers/platform/msm/msm-geni-se.c +++ b/drivers/platform/msm/msm-geni-se.c @@ -103,6 +103,7 @@ struct geni_se_device { struct bus_vectors *vectors; int num_paths; bool vote_for_bw; + struct se_geni_rsc wrapper_rsc; }; #define HW_VER_MAJOR_MASK GENMASK(31, 28) @@ -1642,6 +1643,34 @@ out: return NULL; } +void geni_se_remove_earlycon_icc_vote(struct device *dev) +{ + struct platform_device *pdev; + struct device_node *parent; + struct device_node *child; + struct geni_se_device *geni_se_dev; + int ret; + + parent = of_get_next_parent(dev->of_node); + for_each_child_of_node(parent, child) { + if (!of_device_is_compatible(child, "qcom,qupv3-geni-se")) + continue; + + pdev = of_find_device_by_node(child); + if (!pdev) + continue; + + geni_se_dev = platform_get_drvdata(pdev); + ret = geni_se_rmv_ab_ib(geni_se_dev, &geni_se_dev->wrapper_rsc); + + if (ret) + dev_err(dev, "%s: Error %d during bus_bw_update\n", __func__, + ret); + } + of_node_put(parent); +} +EXPORT_SYMBOL(geni_se_remove_earlycon_icc_vote); + static int geni_se_iommu_probe(struct device *dev) { struct geni_se_device *geni_se_dev; @@ -1731,6 +1760,31 @@ static int geni_se_probe(struct platform_device *pdev) dev_set_drvdata(dev, geni_se_dev); + /* + * TBD: Proxy vote on QUP core path on behalf of earlycon. + * Once the ICC sync state feature is implemented, we can make + * console UART as dummy consumer of ICC to get rid of this HACK + */ +#if IS_ENABLED(CONFIG_SERIAL_MSM_GENI_CONSOLE) + geni_se_dev->wrapper_rsc.wrapper_dev = dev; + geni_se_dev->wrapper_rsc.ctrl_dev = dev; + + ret = geni_se_resources_init(&geni_se_dev->wrapper_rsc, + UART_CONSOLE_CORE2X_VOTE, + (DEFAULT_SE_CLK * DEFAULT_BUS_WIDTH)); + if (ret) { + dev_err(dev, "Resources init failed: %d\n", ret); + return ret; + } + + ret = geni_se_add_ab_ib(geni_se_dev, &geni_se_dev->wrapper_rsc); + if (ret) { + dev_err(dev, "%s: Error %d during bus_bw_update\n", __func__, + ret); + return ret; + } +#endif + ret = of_platform_populate(dev->of_node, geni_se_dt_match, NULL, dev); if (ret) { dev_err(dev, "%s: Error populating children\n", __func__); diff --git a/drivers/tty/serial/msm_geni_serial.c b/drivers/tty/serial/msm_geni_serial.c index 37dd85279f8c..71bfd5b9811d 100644 --- a/drivers/tty/serial/msm_geni_serial.c +++ b/drivers/tty/serial/msm_geni_serial.c @@ -3168,6 +3168,16 @@ static int msm_geni_serial_probe(struct platform_device *pdev) } ret = uart_add_one_port(drv, uport); + if (ret) + dev_err(&pdev->dev, "Failed to register uart_port: %d\n", + ret); + /* + * Remove proxy vote from QUP core which was kept from common driver + * probe on behalf of earlycon + */ + if (uart_console(uport)) + geni_se_remove_earlycon_icc_vote(dev_port->wrapper_dev); + exit_geni_serial_probe: IPC_LOG_MSG(dev_port->ipc_log_misc, "%s: ret:%d\n", __func__, ret); diff --git a/include/linux/msm-geni-se.h b/include/linux/msm-geni-se.h index e8355caf1631..5b5de47d6d34 100644 --- a/include/linux/msm-geni-se.h +++ b/include/linux/msm-geni-se.h @@ -823,6 +823,12 @@ int geni_se_iommu_free_buf(struct device *wrapper_dev, dma_addr_t *iova, */ void geni_se_dump_dbg_regs(struct se_geni_rsc *rsc, void __iomem *base, void *ipc); + +/* + * This function is used to remove proxy ICC BW vote put from common driver + * probe on behalf of earlycon usecase. + */ +void geni_se_remove_earlycon_icc_vote(struct device *dev); #else static inline unsigned int geni_read_reg_nolog(void __iomem *base, int offset) {