mirror of
https://source.denx.de/u-boot/u-boot.git
synced 2026-06-13 15:03:58 +03:00
Merge branch 'qcom-next' of https://gitlab.denx.de/u-boot/custodians/u-boot-snapdragon into next
Various improvements to Snapdragon support: * Bumped up the pagetable size to handle newer SoCs with much more RAM * Made memory map parsing more robust, fixing chainloading on SM8550/SM8650 * Populate fdt_addr_r with U-Boot's FDT by default, and set $loadaddr to prevent crashes with some commands which expect it * Added initial support for SC7280/QCM6490 and the new RB3 Gen 2 board * Add debug config fragments to enable debug UART on some SoCs. * Enable RPMh regulators on SM8550/SM8650 * Map the cmd-db memory explicitly since it may not be in the memory map CI: https://source.denx.de/u-boot/custodians/u-boot-snapdragon/-/pipelines/22255
This commit is contained in:
@@ -86,6 +86,14 @@ config CLK_QCOM_SM8650
|
||||
on the Snapdragon SM8650 SoC. This driver supports the clocks
|
||||
and resets exposed by the GCC hardware block.
|
||||
|
||||
config CLK_QCOM_SC7280
|
||||
bool "Qualcomm SC7280 GCC"
|
||||
select CLK_QCOM
|
||||
help
|
||||
Say Y here to enable support for the Global Clock Controller
|
||||
on the Snapdragon SC7280 SoC. This driver supports the clocks
|
||||
and resets exposed by the GCC hardware block.
|
||||
|
||||
endmenu
|
||||
|
||||
endif
|
||||
|
||||
@@ -9,6 +9,7 @@ obj-$(CONFIG_CLK_QCOM_APQ8096) += clock-apq8096.o
|
||||
obj-$(CONFIG_CLK_QCOM_IPQ4019) += clock-ipq4019.o
|
||||
obj-$(CONFIG_CLK_QCOM_QCM2290) += clock-qcm2290.o
|
||||
obj-$(CONFIG_CLK_QCOM_QCS404) += clock-qcs404.o
|
||||
obj-$(CONFIG_CLK_QCOM_SC7280) += clock-sc7280.o
|
||||
obj-$(CONFIG_CLK_QCOM_SM6115) += clock-sm6115.o
|
||||
obj-$(CONFIG_CLK_QCOM_SM8250) += clock-sm8250.o
|
||||
obj-$(CONFIG_CLK_QCOM_SM8550) += clock-sm8550.o
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#define CFG_CLK_SRC_GPLL0 (1 << 8)
|
||||
#define CFG_CLK_SRC_GPLL0_AUX2 (2 << 8)
|
||||
#define CFG_CLK_SRC_GPLL9 (2 << 8)
|
||||
#define CFG_CLK_SRC_GPLL0_ODD (3 << 8)
|
||||
#define CFG_CLK_SRC_GPLL6 (4 << 8)
|
||||
#define CFG_CLK_SRC_GPLL7 (3 << 8)
|
||||
#define CFG_CLK_SRC_GPLL4 (5 << 8)
|
||||
|
||||
132
drivers/clk/qcom/clock-sc7280.c
Normal file
132
drivers/clk/qcom/clock-sc7280.c
Normal file
@@ -0,0 +1,132 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Clock drivers for Qualcomm sc7280
|
||||
*
|
||||
* (C) Copyright 2024 Linaro Ltd.
|
||||
*/
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <clk-uclass.h>
|
||||
#include <dm.h>
|
||||
#include <linux/delay.h>
|
||||
#include <asm/io.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/bitops.h>
|
||||
#include <dt-bindings/clock/qcom,gcc-sc7280.h>
|
||||
|
||||
#include "clock-qcom.h"
|
||||
|
||||
#define USB30_PRIM_MOCK_UTMI_CLK_CMD_RCGR 0xf038
|
||||
#define USB30_PRIM_MASTER_CLK_CMD_RCGR 0xf020
|
||||
|
||||
static ulong sc7280_set_rate(struct clk *clk, ulong rate)
|
||||
{
|
||||
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
|
||||
if (clk->id < priv->data->num_clks)
|
||||
debug("%s: %s, requested rate=%ld\n", __func__, priv->data->clks[clk->id].name, rate);
|
||||
|
||||
switch (clk->id) {
|
||||
case GCC_USB30_PRIM_MOCK_UTMI_CLK:
|
||||
WARN(rate != 19200000, "Unexpected rate for USB30_PRIM_MOCK_UTMI_CLK: %lu\n", rate);
|
||||
clk_rcg_set_rate(priv->base, USB30_PRIM_MASTER_CLK_CMD_RCGR, 0, CFG_CLK_SRC_CXO);
|
||||
return rate;
|
||||
case GCC_USB30_PRIM_MASTER_CLK:
|
||||
WARN(rate != 200000000, "Unexpected rate for USB30_PRIM_MASTER_CLK: %lu\n", rate);
|
||||
clk_rcg_set_rate_mnd(priv->base, USB30_PRIM_MASTER_CLK_CMD_RCGR,
|
||||
1, 0, 0, CFG_CLK_SRC_GPLL0_ODD, 8);
|
||||
clk_rcg_set_rate(priv->base, 0xf064, 0, 0);
|
||||
return rate;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static const struct gate_clk sc7280_clks[] = {
|
||||
GATE_CLK(GCC_CFG_NOC_USB3_PRIM_AXI_CLK, 0xf07c, 1),
|
||||
GATE_CLK(GCC_USB30_PRIM_MASTER_CLK, 0xf010, 1),
|
||||
GATE_CLK(GCC_AGGRE_USB3_PRIM_AXI_CLK, 0xf080, 1),
|
||||
GATE_CLK(GCC_USB30_PRIM_SLEEP_CLK, 0xf018, 1),
|
||||
GATE_CLK(GCC_USB30_PRIM_MOCK_UTMI_CLK, 0xf01c, 1),
|
||||
GATE_CLK(GCC_USB3_PRIM_PHY_AUX_CLK, 0xf054, 1),
|
||||
GATE_CLK(GCC_USB3_PRIM_PHY_COM_AUX_CLK, 0xf058, 1),
|
||||
};
|
||||
|
||||
static int sc7280_enable(struct clk *clk)
|
||||
{
|
||||
struct msm_clk_priv *priv = dev_get_priv(clk->dev);
|
||||
|
||||
if (priv->data->num_clks < clk->id) {
|
||||
debug("%s: unknown clk id %lu\n", __func__, clk->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
debug("%s: clk %ld: %s\n", __func__, clk->id, sc7280_clks[clk->id].name);
|
||||
|
||||
switch (clk->id) {
|
||||
case GCC_AGGRE_USB3_PRIM_AXI_CLK:
|
||||
qcom_gate_clk_en(priv, GCC_USB30_PRIM_MASTER_CLK);
|
||||
fallthrough;
|
||||
case GCC_USB30_PRIM_MASTER_CLK:
|
||||
qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_AUX_CLK);
|
||||
qcom_gate_clk_en(priv, GCC_USB3_PRIM_PHY_COM_AUX_CLK);
|
||||
break;
|
||||
}
|
||||
|
||||
qcom_gate_clk_en(priv, clk->id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct qcom_reset_map sc7280_gcc_resets[] = {
|
||||
[GCC_PCIE_0_BCR] = { 0x6b000 },
|
||||
[GCC_PCIE_0_PHY_BCR] = { 0x6c01c },
|
||||
[GCC_PCIE_1_BCR] = { 0x8d000 },
|
||||
[GCC_PCIE_1_PHY_BCR] = { 0x8e01c },
|
||||
[GCC_QUSB2PHY_PRIM_BCR] = { 0x12000 },
|
||||
[GCC_QUSB2PHY_SEC_BCR] = { 0x12004 },
|
||||
[GCC_SDCC1_BCR] = { 0x75000 },
|
||||
[GCC_SDCC2_BCR] = { 0x14000 },
|
||||
[GCC_SDCC4_BCR] = { 0x16000 },
|
||||
[GCC_UFS_PHY_BCR] = { 0x77000 },
|
||||
[GCC_USB30_PRIM_BCR] = { 0xf000 },
|
||||
[GCC_USB30_SEC_BCR] = { 0x9e000 },
|
||||
[GCC_USB3_DP_PHY_PRIM_BCR] = { 0x50008 },
|
||||
[GCC_USB3_PHY_PRIM_BCR] = { 0x50000 },
|
||||
[GCC_USB3PHY_PHY_PRIM_BCR] = { 0x50004 },
|
||||
[GCC_USB_PHY_CFG_AHB2PHY_BCR] = { 0x6a000 },
|
||||
};
|
||||
|
||||
static const struct qcom_power_map sc7280_gdscs[] = {
|
||||
[GCC_UFS_PHY_GDSC] = { 0x77004 },
|
||||
[GCC_USB30_PRIM_GDSC] = { 0xf004 },
|
||||
};
|
||||
|
||||
static struct msm_clk_data qcs404_gcc_data = {
|
||||
.resets = sc7280_gcc_resets,
|
||||
.num_resets = ARRAY_SIZE(sc7280_gcc_resets),
|
||||
.clks = sc7280_clks,
|
||||
.num_clks = ARRAY_SIZE(sc7280_clks),
|
||||
|
||||
.power_domains = sc7280_gdscs,
|
||||
.num_power_domains = ARRAY_SIZE(sc7280_gdscs),
|
||||
|
||||
.enable = sc7280_enable,
|
||||
.set_rate = sc7280_set_rate,
|
||||
};
|
||||
|
||||
static const struct udevice_id gcc_sc7280_of_match[] = {
|
||||
{
|
||||
.compatible = "qcom,gcc-sc7280",
|
||||
.data = (ulong)&qcs404_gcc_data,
|
||||
},
|
||||
{ }
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(gcc_sc7280) = {
|
||||
.name = "gcc_sc7280",
|
||||
.id = UCLASS_NOP,
|
||||
.of_match = gcc_sc7280_of_match,
|
||||
.bind = qcom_cc_bind,
|
||||
.flags = DM_FLAG_PRE_RELOC | DM_FLAG_DEFAULT_PD_CTRL_OFF,
|
||||
};
|
||||
@@ -381,6 +381,7 @@ static struct iommu_ops qcom_smmu_ops = {
|
||||
|
||||
static const struct udevice_id qcom_smmu500_ids[] = {
|
||||
{ .compatible = "qcom,sdm845-smmu-500" },
|
||||
{ .compatible = "qcom,sc7280-smmu-500" },
|
||||
{ .compatible = "qcom,smmu-500", },
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
|
||||
@@ -357,6 +357,69 @@ static const struct dm_regulator_ops rpmh_regulator_vrm_drms_ops = {
|
||||
.get_mode = rpmh_regulator_vrm_get_mode,
|
||||
};
|
||||
|
||||
static struct dm_regulator_mode pmic_mode_map_pmic5_bob[] = {
|
||||
{
|
||||
.id = REGULATOR_MODE_LPM,
|
||||
.register_value = PMIC5_BOB_MODE_PFM,
|
||||
.name = "PMIC5_BOB_MODE_PFM"
|
||||
}, {
|
||||
.id = REGULATOR_MODE_AUTO,
|
||||
.register_value = PMIC5_BOB_MODE_AUTO,
|
||||
.name = "PMIC5_BOB_MODE_AUTO"
|
||||
}, {
|
||||
.id = REGULATOR_MODE_HPM,
|
||||
.register_value = PMIC5_BOB_MODE_PWM,
|
||||
.name = "PMIC5_BOB_MODE_PWM"
|
||||
},
|
||||
};
|
||||
|
||||
static struct dm_regulator_mode pmic_mode_map_pmic5_smps[] = {
|
||||
{
|
||||
.id = REGULATOR_MODE_RETENTION,
|
||||
.register_value = PMIC5_SMPS_MODE_RETENTION,
|
||||
.name = "PMIC5_SMPS_MODE_RETENTION"
|
||||
}, {
|
||||
.id = REGULATOR_MODE_LPM,
|
||||
.register_value = PMIC5_SMPS_MODE_PFM,
|
||||
.name = "PMIC5_SMPS_MODE_PFM"
|
||||
}, {
|
||||
.id = REGULATOR_MODE_AUTO,
|
||||
.register_value = PMIC5_SMPS_MODE_AUTO,
|
||||
.name = "PMIC5_SMPS_MODE_AUTO"
|
||||
}, {
|
||||
.id = REGULATOR_MODE_HPM,
|
||||
.register_value = PMIC5_SMPS_MODE_PWM,
|
||||
.name = "PMIC5_SMPS_MODE_PWM"
|
||||
},
|
||||
};
|
||||
|
||||
static const struct rpmh_vreg_hw_data pmic5_bob = {
|
||||
.regulator_type = VRM,
|
||||
.ops = &rpmh_regulator_vrm_drms_ops,
|
||||
.voltage_range = REGULATOR_LINEAR_RANGE(3000000, 0, 31, 32000),
|
||||
.n_voltages = 32,
|
||||
.pmic_mode_map = pmic_mode_map_pmic5_bob,
|
||||
.n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_bob),
|
||||
};
|
||||
|
||||
static const struct rpmh_vreg_hw_data pmic5_ftsmps525_lv = {
|
||||
.regulator_type = VRM,
|
||||
.ops = &rpmh_regulator_vrm_drms_ops,
|
||||
.voltage_range = REGULATOR_LINEAR_RANGE(300000, 0, 267, 4000),
|
||||
.n_voltages = 268,
|
||||
.pmic_mode_map = pmic_mode_map_pmic5_smps,
|
||||
.n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_smps),
|
||||
};
|
||||
|
||||
static const struct rpmh_vreg_hw_data pmic5_ftsmps525_mv = {
|
||||
.regulator_type = VRM,
|
||||
.ops = &rpmh_regulator_vrm_drms_ops,
|
||||
.voltage_range = REGULATOR_LINEAR_RANGE(600000, 0, 267, 8000),
|
||||
.n_voltages = 268,
|
||||
.pmic_mode_map = pmic_mode_map_pmic5_smps,
|
||||
.n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_smps),
|
||||
};
|
||||
|
||||
static struct dm_regulator_mode pmic_mode_map_pmic5_ldo[] = {
|
||||
{
|
||||
.id = REGULATOR_MODE_RETENTION,
|
||||
@@ -393,6 +456,16 @@ static const struct rpmh_vreg_hw_data pmic5_pldo_lv = {
|
||||
.n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_ldo),
|
||||
};
|
||||
|
||||
static const struct rpmh_vreg_hw_data pmic5_nldo515 = {
|
||||
.regulator_type = VRM,
|
||||
.ops = &rpmh_regulator_vrm_drms_ops,
|
||||
.voltage_range = REGULATOR_LINEAR_RANGE(320000, 0, 210, 8000),
|
||||
.n_voltages = 211,
|
||||
.hpm_min_load_uA = 30000,
|
||||
.pmic_mode_map = pmic_mode_map_pmic5_ldo,
|
||||
.n_modes = ARRAY_SIZE(pmic_mode_map_pmic5_ldo),
|
||||
};
|
||||
|
||||
#define RPMH_VREG(_name, _resource_name, _hw_data, _supply_name) \
|
||||
{ \
|
||||
.name = _name, \
|
||||
@@ -412,6 +485,57 @@ static const struct rpmh_vreg_init_data pm8150l_vreg_data[] = {
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct rpmh_vreg_init_data pm8550_vreg_data[] = {
|
||||
RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo515, "vdd-l1-l4-l10"),
|
||||
RPMH_VREG("ldo2", "ldo%s2", &pmic5_pldo, "vdd-l2-l13-l14"),
|
||||
RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo515, "vdd-l3"),
|
||||
RPMH_VREG("ldo4", "ldo%s4", &pmic5_nldo515, "vdd-l1-l4-l10"),
|
||||
RPMH_VREG("ldo5", "ldo%s5", &pmic5_pldo, "vdd-l5-l16"),
|
||||
RPMH_VREG("ldo6", "ldo%s6", &pmic5_pldo, "vdd-l6-l7"),
|
||||
RPMH_VREG("ldo7", "ldo%s7", &pmic5_pldo, "vdd-l6-l7"),
|
||||
RPMH_VREG("ldo8", "ldo%s8", &pmic5_pldo, "vdd-l8-l9"),
|
||||
RPMH_VREG("ldo9", "ldo%s9", &pmic5_pldo, "vdd-l8-l9"),
|
||||
RPMH_VREG("ldo10", "ldo%s10", &pmic5_nldo515, "vdd-l1-l4-l10"),
|
||||
RPMH_VREG("ldo11", "ldo%s11", &pmic5_nldo515, "vdd-l11"),
|
||||
RPMH_VREG("ldo12", "ldo%s12", &pmic5_nldo515, "vdd-l12"),
|
||||
RPMH_VREG("ldo13", "ldo%s13", &pmic5_pldo, "vdd-l2-l13-l14"),
|
||||
RPMH_VREG("ldo14", "ldo%s14", &pmic5_pldo, "vdd-l2-l13-l14"),
|
||||
RPMH_VREG("ldo15", "ldo%s15", &pmic5_nldo515, "vdd-l15"),
|
||||
RPMH_VREG("ldo16", "ldo%s16", &pmic5_pldo, "vdd-l5-l16"),
|
||||
RPMH_VREG("ldo17", "ldo%s17", &pmic5_pldo, "vdd-l17"),
|
||||
RPMH_VREG("bob1", "bob%s1", &pmic5_bob, "vdd-bob1"),
|
||||
RPMH_VREG("bob2", "bob%s2", &pmic5_bob, "vdd-bob2"),
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct rpmh_vreg_init_data pm8550vs_vreg_data[] = {
|
||||
RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525_lv, "vdd-s1"),
|
||||
RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525_lv, "vdd-s2"),
|
||||
RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525_lv, "vdd-s3"),
|
||||
RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525_lv, "vdd-s4"),
|
||||
RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525_lv, "vdd-s5"),
|
||||
RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525_mv, "vdd-s6"),
|
||||
RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo515, "vdd-l1"),
|
||||
RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo515, "vdd-l2"),
|
||||
RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo515, "vdd-l3"),
|
||||
{}
|
||||
};
|
||||
|
||||
static const struct rpmh_vreg_init_data pm8550ve_vreg_data[] = {
|
||||
RPMH_VREG("smps1", "smp%s1", &pmic5_ftsmps525_lv, "vdd-s1"),
|
||||
RPMH_VREG("smps2", "smp%s2", &pmic5_ftsmps525_lv, "vdd-s2"),
|
||||
RPMH_VREG("smps3", "smp%s3", &pmic5_ftsmps525_lv, "vdd-s3"),
|
||||
RPMH_VREG("smps4", "smp%s4", &pmic5_ftsmps525_mv, "vdd-s4"),
|
||||
RPMH_VREG("smps5", "smp%s5", &pmic5_ftsmps525_lv, "vdd-s5"),
|
||||
RPMH_VREG("smps6", "smp%s6", &pmic5_ftsmps525_lv, "vdd-s6"),
|
||||
RPMH_VREG("smps7", "smp%s7", &pmic5_ftsmps525_lv, "vdd-s7"),
|
||||
RPMH_VREG("smps8", "smp%s8", &pmic5_ftsmps525_lv, "vdd-s8"),
|
||||
RPMH_VREG("ldo1", "ldo%s1", &pmic5_nldo515, "vdd-l1"),
|
||||
RPMH_VREG("ldo2", "ldo%s2", &pmic5_nldo515, "vdd-l2"),
|
||||
RPMH_VREG("ldo3", "ldo%s3", &pmic5_nldo515, "vdd-l3"),
|
||||
{}
|
||||
};
|
||||
|
||||
/* probe an individual regulator */
|
||||
static int rpmh_regulator_probe(struct udevice *dev)
|
||||
{
|
||||
@@ -526,6 +650,18 @@ static const struct udevice_id rpmh_regulator_ids[] = {
|
||||
.compatible = "qcom,pm8150l-rpmh-regulators",
|
||||
.data = (ulong)pm8150l_vreg_data,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,pm8550-rpmh-regulators",
|
||||
.data = (ulong)pm8550_vreg_data,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,pm8550ve-rpmh-regulators",
|
||||
.data = (ulong)pm8550ve_vreg_data,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,pm8550vs-rpmh-regulators",
|
||||
.data = (ulong)pm8550vs_vreg_data,
|
||||
},
|
||||
{ /* sentinal */ },
|
||||
};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#define pr_fmt(fmt) "cmd-db: " fmt
|
||||
|
||||
#include <asm/system.h>
|
||||
#include <dm.h>
|
||||
#include <dm/ofnode.h>
|
||||
#include <dm/device_compat.h>
|
||||
@@ -141,7 +142,7 @@ static int cmd_db_get_header(const char *id, const struct entry_header **eh,
|
||||
|
||||
ent = rsc_to_entry_header(rsc_hdr);
|
||||
for (j = 0; j < le16_to_cpu(rsc_hdr->cnt); j++, ent++) {
|
||||
if (memcmp(ent->id, query, sizeof(ent->id)) == 0) {
|
||||
if (strncmp(ent->id, query, sizeof(ent->id)) == 0) {
|
||||
if (eh)
|
||||
*eh = ent;
|
||||
if (rh)
|
||||
@@ -182,9 +183,10 @@ u32 cmd_db_read_addr(const char *id)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(cmd_db_read_addr);
|
||||
|
||||
int cmd_db_bind(struct udevice *dev)
|
||||
static int cmd_db_bind(struct udevice *dev)
|
||||
{
|
||||
void __iomem *base;
|
||||
fdt_size_t size;
|
||||
ofnode node;
|
||||
|
||||
if (cmd_db_header)
|
||||
@@ -194,12 +196,15 @@ int cmd_db_bind(struct udevice *dev)
|
||||
|
||||
debug("%s(%s)\n", __func__, ofnode_get_name(node));
|
||||
|
||||
base = (void __iomem *)ofnode_get_addr(node);
|
||||
base = (void __iomem *)ofnode_get_addr_size(node, "reg", &size);
|
||||
if ((fdt_addr_t)base == FDT_ADDR_T_NONE) {
|
||||
log_err("%s: Failed to read base address\n", __func__);
|
||||
return -ENOENT;
|
||||
}
|
||||
|
||||
/* On SM8550/SM8650 and newer SoCs cmd-db might not be mapped */
|
||||
mmu_map_region((phys_addr_t)base, (phys_size_t)size, false);
|
||||
|
||||
cmd_db_header = base;
|
||||
if (!cmd_db_magic_matches(cmd_db_header)) {
|
||||
log_err("%s: Invalid Command DB Magic\n", __func__);
|
||||
|
||||
@@ -293,6 +293,48 @@ static void __tcs_buffer_write(struct rsc_drv *drv, int tcs_id, int cmd_id,
|
||||
write_tcs_reg(drv, drv->regs[RSC_DRV_CMD_ENABLE], tcs_id, cmd_enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* __tcs_set_trigger() - Start xfer on a TCS or unset trigger on a borrowed TCS
|
||||
* @drv: The controller.
|
||||
* @tcs_id: The global ID of this TCS.
|
||||
* @trigger: If true then untrigger/retrigger. If false then just untrigger.
|
||||
*
|
||||
* In the normal case we only ever call with "trigger=true" to start a
|
||||
* transfer. That will un-trigger/disable the TCS from the last transfer
|
||||
* then trigger/enable for this transfer.
|
||||
*
|
||||
* If we borrowed a wake TCS for an active-only transfer we'll also call
|
||||
* this function with "trigger=false" to just do the un-trigger/disable
|
||||
* before using the TCS for wake purposes again.
|
||||
*
|
||||
* Note that the AP is only in charge of triggering active-only transfers.
|
||||
* The AP never triggers sleep/wake values using this function.
|
||||
*/
|
||||
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, reg, tcs_id);
|
||||
enable &= ~TCS_AMC_MODE_TRIGGER;
|
||||
write_tcs_reg_sync(drv, reg, tcs_id, enable);
|
||||
enable &= ~TCS_AMC_MODE_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, reg, tcs_id, enable);
|
||||
enable |= TCS_AMC_MODE_TRIGGER;
|
||||
write_tcs_reg(drv, reg, tcs_id, enable);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* rpmh_rsc_send_data() - Write / trigger active-only message.
|
||||
* @drv: The controller.
|
||||
@@ -348,6 +390,7 @@ int rpmh_rsc_send_data(struct rsc_drv *drv, const struct tcs_request *msg)
|
||||
* of __tcs_set_trigger() below.
|
||||
*/
|
||||
__tcs_buffer_write(drv, tcs_id, 0, msg);
|
||||
__tcs_set_trigger(drv, tcs_id, true);
|
||||
|
||||
/* U-Boot: Now wait for the TCS to be cleared, indicating that we're done */
|
||||
for (i = 0; i < USEC_PER_SEC; i++) {
|
||||
|
||||
Reference in New Issue
Block a user