Skip to content

Commit 1851774

Browse files
committed
Merge tag 'qcom-drivers-for-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux into arm/drivers
Qualcomm driver updates for v5.9 For RPMh this fixes an issue where ktime was used during suspend, allows the driver to be used on ARM targets and some minor cleanups. It adds support for the latest format version in the socinfo driver and adds identifiers for SM8250 and SDM630. SMD-RPM gains compatibles for MSM8994 and MSM8936 and the Qualcomm SCM gains compatibles MSM8994 and IPQ8074. The GENI core code gains interconnect path voting and performance level support, with subsequent patches integrating this with the SPI, I2C, UART and QSPI drivers. Following this the KGDB support for the GENI serial driver is improved, the performance related to chip-select is improved for SPI and QSPI. * tag 'qcom-drivers-for-5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/qcom/linux: (35 commits) soc: qcom: geni: Fix NULL pointer dereference tty: serial: qcom-geni-serial: Drop the icc bw votes in suspend for console serial: qcom_geni_serial: Always use 4 bytes per TX FIFO word serial: qcom_geni_serial: Make kgdb work even if UART isn't console spi: spi-geni-qcom: Get rid of most overhead in prepare_message() spi: spi-geni-qcom: Set the clock properly at runtime resume spi: spi-geni-qcom: Avoid clock setting if not needed spi: spi-qcom-qspi: Set an autosuspend delay of 250 ms spi: spi-qcom-qspi: Avoid clock setting if not needed spi: spi-qcom-qspi: Use OPP API to set clk/perf state firmware: qcom_scm: Add msm8994 compatible firmware: qcom_scm: Fix legacy convention SCM accessors <linux/of.h>: add stub for of_get_next_parent() to fix qcom build error dt-bindings: firmware: qcom: Add compatible for IPQ8074 SoC spi: spi-geni-qcom: Use OPP API to set clk/perf state tty: serial: qcom_geni_serial: Use OPP API to set clk/perf state spi: spi-qcom-qspi: Add interconnect support spi: spi-geni-qcom: Add interconnect support spi: spi-geni-qcom: Combine the clock setting code tty: serial: qcom_geni_serial: Add interconnect support ... Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Arnd Bergmann <[email protected]>
2 parents e2837df + 03c900b commit 1851774

File tree

17 files changed

+729
-149
lines changed

17 files changed

+729
-149
lines changed

Documentation/devicetree/bindings/firmware/qcom,scm.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ Required properties:
1111
* "qcom,scm-apq8084"
1212
* "qcom,scm-ipq4019"
1313
* "qcom,scm-ipq806x"
14+
* "qcom,scm-ipq8074"
1415
* "qcom,scm-msm8660"
1516
* "qcom,scm-msm8916"
1617
* "qcom,scm-msm8960"
1718
* "qcom,scm-msm8974"
19+
* "qcom,scm-msm8994"
1820
* "qcom,scm-msm8996"
1921
* "qcom,scm-msm8998"
2022
* "qcom,scm-sc7180"

Documentation/devicetree/bindings/soc/qcom/qcom,smd-rpm.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,10 @@ resources.
2121
Definition: must be one of:
2222
"qcom,rpm-apq8084"
2323
"qcom,rpm-msm8916"
24+
"qcom,rpm-msm8936"
2425
"qcom,rpm-msm8974"
2526
"qcom,rpm-msm8976"
27+
"qcom,rpm-msm8994"
2628
"qcom,rpm-msm8998"
2729
"qcom,rpm-sdm660"
2830
"qcom,rpm-qcs404"

drivers/firmware/qcom_scm.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ static int __qcom_scm_set_dload_mode(struct device *dev, bool enable)
391391

392392
desc.args[1] = enable ? QCOM_SCM_BOOT_SET_DLOAD_MODE : 0;
393393

394-
return qcom_scm_call(__scm->dev, &desc, NULL);
394+
return qcom_scm_call_atomic(__scm->dev, &desc, NULL);
395395
}
396396

397397
static void qcom_scm_set_download_mode(bool enable)
@@ -650,7 +650,7 @@ int qcom_scm_io_readl(phys_addr_t addr, unsigned int *val)
650650
int ret;
651651

652652

653-
ret = qcom_scm_call(__scm->dev, &desc, &res);
653+
ret = qcom_scm_call_atomic(__scm->dev, &desc, &res);
654654
if (ret >= 0)
655655
*val = res.result[0];
656656

@@ -669,8 +669,7 @@ int qcom_scm_io_writel(phys_addr_t addr, unsigned int val)
669669
.owner = ARM_SMCCC_OWNER_SIP,
670670
};
671671

672-
673-
return qcom_scm_call(__scm->dev, &desc, NULL);
672+
return qcom_scm_call_atomic(__scm->dev, &desc, NULL);
674673
}
675674
EXPORT_SYMBOL(qcom_scm_io_writel);
676675

@@ -1151,6 +1150,7 @@ static const struct of_device_id qcom_scm_dt_match[] = {
11511150
SCM_HAS_IFACE_CLK |
11521151
SCM_HAS_BUS_CLK)
11531152
},
1153+
{ .compatible = "qcom,scm-msm8994" },
11541154
{ .compatible = "qcom,scm-msm8996" },
11551155
{ .compatible = "qcom,scm" },
11561156
{}

drivers/i2c/busses/i2c-qcom-geni.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,22 @@ static int geni_i2c_probe(struct platform_device *pdev)
557557
gi2c->adap.dev.of_node = dev->of_node;
558558
strlcpy(gi2c->adap.name, "Geni-I2C", sizeof(gi2c->adap.name));
559559

560+
ret = geni_icc_get(&gi2c->se, "qup-memory");
561+
if (ret)
562+
return ret;
563+
/*
564+
* Set the bus quota for core and cpu to a reasonable value for
565+
* register access.
566+
* Set quota for DDR based on bus speed.
567+
*/
568+
gi2c->se.icc_paths[GENI_TO_CORE].avg_bw = GENI_DEFAULT_BW;
569+
gi2c->se.icc_paths[CPU_TO_GENI].avg_bw = GENI_DEFAULT_BW;
570+
gi2c->se.icc_paths[GENI_TO_DDR].avg_bw = Bps_to_icc(gi2c->clk_freq_out);
571+
572+
ret = geni_icc_set_bw(&gi2c->se);
573+
if (ret)
574+
return ret;
575+
560576
ret = geni_se_resources_on(&gi2c->se);
561577
if (ret) {
562578
dev_err(dev, "Error turning on resources %d\n", ret);
@@ -579,6 +595,10 @@ static int geni_i2c_probe(struct platform_device *pdev)
579595
return ret;
580596
}
581597

598+
ret = geni_icc_disable(&gi2c->se);
599+
if (ret)
600+
return ret;
601+
582602
dev_dbg(dev, "i2c fifo/se-dma mode. fifo depth:%d\n", tx_depth);
583603

584604
gi2c->suspended = 1;
@@ -623,14 +643,18 @@ static int __maybe_unused geni_i2c_runtime_suspend(struct device *dev)
623643
gi2c->suspended = 1;
624644
}
625645

626-
return 0;
646+
return geni_icc_disable(&gi2c->se);
627647
}
628648

629649
static int __maybe_unused geni_i2c_runtime_resume(struct device *dev)
630650
{
631651
int ret;
632652
struct geni_i2c_dev *gi2c = dev_get_drvdata(dev);
633653

654+
ret = geni_icc_enable(&gi2c->se);
655+
if (ret)
656+
return ret;
657+
634658
ret = geni_se_resources_on(&gi2c->se);
635659
if (ret)
636660
return ret;

drivers/interconnect/qcom/bcm-voter.c

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -266,11 +266,7 @@ int qcom_icc_bcm_voter_commit(struct bcm_voter *voter)
266266
if (!commit_idx[0])
267267
goto out;
268268

269-
ret = rpmh_invalidate(voter->dev);
270-
if (ret) {
271-
pr_err("Error invalidating RPMH client (%d)\n", ret);
272-
goto out;
273-
}
269+
rpmh_invalidate(voter->dev);
274270

275271
ret = rpmh_write_batch(voter->dev, RPMH_ACTIVE_ONLY_STATE,
276272
cmds, commit_idx);

drivers/soc/qcom/Kconfig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ config QCOM_RMTFS_MEM
8989

9090
config QCOM_RPMH
9191
bool "Qualcomm RPM-Hardened (RPMH) Communication"
92-
depends on ARCH_QCOM && ARM64 || COMPILE_TEST
92+
depends on ARCH_QCOM || COMPILE_TEST
9393
help
9494
Support for communication with the hardened-RPM blocks in
9595
Qualcomm Technologies Inc (QTI) SoCs. RPMH communication uses an

drivers/soc/qcom/qcom-geni-se.c

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include <linux/acpi.h>
55
#include <linux/clk.h>
6+
#include <linux/console.h>
67
#include <linux/slab.h>
78
#include <linux/dma-mapping.h>
89
#include <linux/io.h>
@@ -90,8 +91,14 @@ struct geni_wrapper {
9091
struct device *dev;
9192
void __iomem *base;
9293
struct clk_bulk_data ahb_clks[NUM_AHB_CLKS];
94+
struct geni_icc_path to_core;
9395
};
9496

97+
static const char * const icc_path_names[] = {"qup-core", "qup-config",
98+
"qup-memory"};
99+
100+
static struct geni_wrapper *earlycon_wrapper;
101+
95102
#define QUP_HW_VER_REG 0x4
96103

97104
/* Common SE registers */
@@ -720,11 +727,132 @@ void geni_se_rx_dma_unprep(struct geni_se *se, dma_addr_t iova, size_t len)
720727
}
721728
EXPORT_SYMBOL(geni_se_rx_dma_unprep);
722729

730+
int geni_icc_get(struct geni_se *se, const char *icc_ddr)
731+
{
732+
int i, err;
733+
const char *icc_names[] = {"qup-core", "qup-config", icc_ddr};
734+
735+
for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
736+
if (!icc_names[i])
737+
continue;
738+
739+
se->icc_paths[i].path = devm_of_icc_get(se->dev, icc_names[i]);
740+
if (IS_ERR(se->icc_paths[i].path))
741+
goto err;
742+
}
743+
744+
return 0;
745+
746+
err:
747+
err = PTR_ERR(se->icc_paths[i].path);
748+
if (err != -EPROBE_DEFER)
749+
dev_err_ratelimited(se->dev, "Failed to get ICC path '%s': %d\n",
750+
icc_names[i], err);
751+
return err;
752+
753+
}
754+
EXPORT_SYMBOL(geni_icc_get);
755+
756+
int geni_icc_set_bw(struct geni_se *se)
757+
{
758+
int i, ret;
759+
760+
for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
761+
ret = icc_set_bw(se->icc_paths[i].path,
762+
se->icc_paths[i].avg_bw, se->icc_paths[i].avg_bw);
763+
if (ret) {
764+
dev_err_ratelimited(se->dev, "ICC BW voting failed on path '%s': %d\n",
765+
icc_path_names[i], ret);
766+
return ret;
767+
}
768+
}
769+
770+
return 0;
771+
}
772+
EXPORT_SYMBOL(geni_icc_set_bw);
773+
774+
void geni_icc_set_tag(struct geni_se *se, u32 tag)
775+
{
776+
int i;
777+
778+
for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++)
779+
icc_set_tag(se->icc_paths[i].path, tag);
780+
}
781+
EXPORT_SYMBOL(geni_icc_set_tag);
782+
783+
/* To do: Replace this by icc_bulk_enable once it's implemented in ICC core */
784+
int geni_icc_enable(struct geni_se *se)
785+
{
786+
int i, ret;
787+
788+
for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
789+
ret = icc_enable(se->icc_paths[i].path);
790+
if (ret) {
791+
dev_err_ratelimited(se->dev, "ICC enable failed on path '%s': %d\n",
792+
icc_path_names[i], ret);
793+
return ret;
794+
}
795+
}
796+
797+
return 0;
798+
}
799+
EXPORT_SYMBOL(geni_icc_enable);
800+
801+
int geni_icc_disable(struct geni_se *se)
802+
{
803+
int i, ret;
804+
805+
for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) {
806+
ret = icc_disable(se->icc_paths[i].path);
807+
if (ret) {
808+
dev_err_ratelimited(se->dev, "ICC disable failed on path '%s': %d\n",
809+
icc_path_names[i], ret);
810+
return ret;
811+
}
812+
}
813+
814+
return 0;
815+
}
816+
EXPORT_SYMBOL(geni_icc_disable);
817+
818+
void geni_remove_earlycon_icc_vote(void)
819+
{
820+
struct platform_device *pdev;
821+
struct geni_wrapper *wrapper;
822+
struct device_node *parent;
823+
struct device_node *child;
824+
825+
if (!earlycon_wrapper)
826+
return;
827+
828+
wrapper = earlycon_wrapper;
829+
parent = of_get_next_parent(wrapper->dev->of_node);
830+
for_each_child_of_node(parent, child) {
831+
if (!of_device_is_compatible(child, "qcom,geni-se-qup"))
832+
continue;
833+
834+
pdev = of_find_device_by_node(child);
835+
if (!pdev)
836+
continue;
837+
838+
wrapper = platform_get_drvdata(pdev);
839+
icc_put(wrapper->to_core.path);
840+
wrapper->to_core.path = NULL;
841+
842+
}
843+
of_node_put(parent);
844+
845+
earlycon_wrapper = NULL;
846+
}
847+
EXPORT_SYMBOL(geni_remove_earlycon_icc_vote);
848+
723849
static int geni_se_probe(struct platform_device *pdev)
724850
{
725851
struct device *dev = &pdev->dev;
726852
struct resource *res;
727853
struct geni_wrapper *wrapper;
854+
struct console __maybe_unused *bcon;
855+
bool __maybe_unused has_earlycon = false;
728856
int ret;
729857

730858
wrapper = devm_kzalloc(dev, sizeof(*wrapper), GFP_KERNEL);
@@ -747,6 +875,43 @@ static int geni_se_probe(struct platform_device *pdev)
747875
}
748876
}
749877

878+
#ifdef CONFIG_SERIAL_EARLYCON
879+
for_each_console(bcon) {
880+
if (!strcmp(bcon->name, "qcom_geni")) {
881+
has_earlycon = true;
882+
break;
883+
}
884+
}
885+
if (!has_earlycon)
886+
goto exit;
887+
888+
wrapper->to_core.path = devm_of_icc_get(dev, "qup-core");
889+
if (IS_ERR(wrapper->to_core.path))
890+
return PTR_ERR(wrapper->to_core.path);
891+
/*
892+
* Put minmal BW request on core clocks on behalf of early console.
893+
* The vote will be removed earlycon exit function.
894+
*
895+
* Note: We are putting vote on each QUP wrapper instead only to which
896+
* earlycon is connected because QUP core clock of different wrapper
897+
* share same voltage domain. If core1 is put to 0, then core2 will
898+
* also run at 0, if not voted. Default ICC vote will be removed ASA
899+
* we touch any of the core clock.
900+
* core1 = core2 = max(core1, core2)
901+
*/
902+
ret = icc_set_bw(wrapper->to_core.path, GENI_DEFAULT_BW,
903+
GENI_DEFAULT_BW);
904+
if (ret) {
905+
dev_err(&pdev->dev, "%s: ICC BW voting failed for core: %d\n",
906+
__func__, ret);
907+
return ret;
908+
}
909+
910+
if (of_get_compatible_child(pdev->dev.of_node, "qcom,geni-debug-uart"))
911+
earlycon_wrapper = wrapper;
912+
of_node_put(pdev->dev.of_node);
913+
#endif
914+
exit:
750915
dev_set_drvdata(dev, wrapper);
751916
dev_dbg(dev, "GENI SE Driver probed\n");
752917
return devm_of_platform_populate(dev);

drivers/soc/qcom/rpmh-rsc.c

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -175,13 +175,21 @@ static void write_tcs_reg(const struct rsc_drv *drv, int reg, int tcs_id,
175175
static void write_tcs_reg_sync(const struct rsc_drv *drv, int reg, int tcs_id,
176176
u32 data)
177177
{
178-
u32 new_data;
178+
int i;
179179

180180
writel(data, tcs_reg_addr(drv, reg, tcs_id));
181-
if (readl_poll_timeout_atomic(tcs_reg_addr(drv, reg, tcs_id), new_data,
182-
new_data == data, 1, USEC_PER_SEC))
183-
pr_err("%s: error writing %#x to %d:%#x\n", drv->name,
184-
data, tcs_id, reg);
181+
182+
/*
183+
* Wait until we read back the same value. Use a counter rather than
184+
* ktime for timeout since this may be called after timekeeping stops.
185+
*/
186+
for (i = 0; i < USEC_PER_SEC; i++) {
187+
if (readl(tcs_reg_addr(drv, reg, tcs_id)) == data)
188+
return;
189+
udelay(1);
190+
}
191+
pr_err("%s: error writing %#x to %d:%#x\n", drv->name,
192+
data, tcs_id, reg);
185193
}
186194

187195
/**
@@ -1023,6 +1031,7 @@ static struct platform_driver rpmh_driver = {
10231031
.driver = {
10241032
.name = "rpmh",
10251033
.of_match_table = rpmh_drv_match,
1034+
.suppress_bind_attrs = true,
10261035
},
10271036
};
10281037

drivers/soc/qcom/rpmh.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -497,7 +497,7 @@ int rpmh_flush(struct rpmh_ctrlr *ctrlr)
497497
*
498498
* Invalidate the sleep and wake values in batch_cache.
499499
*/
500-
int rpmh_invalidate(const struct device *dev)
500+
void rpmh_invalidate(const struct device *dev)
501501
{
502502
struct rpmh_ctrlr *ctrlr = get_rpmh_ctrlr(dev);
503503
struct batch_cache_req *req, *tmp;
@@ -509,7 +509,5 @@ int rpmh_invalidate(const struct device *dev)
509509
INIT_LIST_HEAD(&ctrlr->batch_cache);
510510
ctrlr->dirty = true;
511511
spin_unlock_irqrestore(&ctrlr->cache_lock, flags);
512-
513-
return 0;
514512
}
515513
EXPORT_SYMBOL(rpmh_invalidate);

drivers/soc/qcom/smd-rpm.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -231,8 +231,10 @@ static void qcom_smd_rpm_remove(struct rpmsg_device *rpdev)
231231
static const struct of_device_id qcom_smd_rpm_of_match[] = {
232232
{ .compatible = "qcom,rpm-apq8084" },
233233
{ .compatible = "qcom,rpm-msm8916" },
234+
{ .compatible = "qcom,rpm-msm8936" },
234235
{ .compatible = "qcom,rpm-msm8974" },
235236
{ .compatible = "qcom,rpm-msm8976" },
237+
{ .compatible = "qcom,rpm-msm8994" },
236238
{ .compatible = "qcom,rpm-msm8996" },
237239
{ .compatible = "qcom,rpm-msm8998" },
238240
{ .compatible = "qcom,rpm-sdm660" },

0 commit comments

Comments
 (0)