Merge branch 'net-ipa-change-gsi-firmware-load-specification'

Alex Elder says:

====================
net: ipa: change GSI firmware load specification

Currently, GSI firmware must be loaded for IPA before it can be
used--either by the modem, or by the AP.  New hardware supports a
third option, with the bootloader taking responsibility for loading
GSI firmware.  In that case, neither the AP nor the modem needs to
do that.

The first patch in this series deprecates the "modem-init" Device
Tree property in the IPA binding, using a new "qcom,gsi-loader"
property instead.  The second and third implement logic in the code
to support either the "old" or the "new" way of specifying how GSI
firmware is loaded.

The last two patches implement a new value for the "qcom,gsi-loader"
property.  If the value is "skip", neither the AP nor modem needs to
load the GSI firmware.  The first of these patches implements the
change in the IPA binding; the second implements it in the code.
====================

Link: https://lore.kernel.org/r/20221116073257.34010-1-elder@linaro.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Jakub Kicinski 2022-11-17 21:46:58 -08:00
commit a452d30f3f
2 changed files with 135 additions and 38 deletions

View file

@ -124,19 +124,31 @@ properties:
- const: ipa-clock-enabled-valid
- const: ipa-clock-enabled
qcom,gsi-loader:
enum:
- self
- modem
- skip
description:
Indicates how GSI firmware should be loaded. If the AP loads
and validates GSI firmware, this property has value "self".
If the modem does this, this property has value "modem".
Otherwise, "skip" means GSI firmware loading is not required.
modem-init:
deprecated: true
type: boolean
description:
If present, it indicates that the modem is responsible for
performing early IPA initialization, including loading and
validating firwmare used by the GSI.
This is the older (deprecated) way of indicating how GSI firmware
should be loaded. If present, the modem loads GSI firmware; if
absent, the AP loads GSI firmware.
memory-region:
maxItems: 1
description:
If present, a phandle for a reserved memory area that holds
the firmware passed to Trust Zone for authentication. Required
when Trust Zone (not the modem) performs early initialization.
when the AP (not the modem) performs early initialization.
firmware-name:
$ref: /schemas/types.yaml#/definitions/string
@ -155,15 +167,36 @@ required:
- interconnects
- qcom,smem-states
# If modem-init is not present, the AP loads GSI firmware, and
# memory-region must be specified
if:
not:
required:
- modem-init
then:
required:
- memory-region
allOf:
# If qcom,gsi-loader is present, modem-init must not be present
- if:
required:
- qcom,gsi-loader
then:
properties:
modem-init: false
# If qcom,gsi-loader is "self", the AP loads GSI firmware, and
# memory-region must be specified
if:
properties:
qcom,gsi-loader:
contains:
const: self
then:
required:
- memory-region
else:
# If qcom,gsi-loader is not present, we use deprecated behavior.
# If modem-init is not present, the AP loads GSI firmware, and
# memory-region must be specified.
if:
not:
required:
- modem-init
then:
required:
- memory-region
additionalProperties: false
@ -194,14 +227,17 @@ examples:
};
ipa@1e40000 {
compatible = "qcom,sdm845-ipa";
compatible = "qcom,sc7180-ipa";
modem-init;
qcom,gsi-loader = "self";
memory-region = <&ipa_fw_mem>;
firmware-name = "qcom/sc7180-trogdor/modem/modem.mdt";
iommus = <&apps_smmu 0x720 0x3>;
iommus = <&apps_smmu 0x440 0x0>,
<&apps_smmu 0x442 0x0>;
reg = <0x1e40000 0x7000>,
<0x1e47000 0x2000>,
<0x1e04000 0x2c000>;
<0x1e47000 0x2000>,
<0x1e04000 0x2c000>;
reg-names = "ipa-reg",
"ipa-shared",
"gsi";
@ -219,9 +255,9 @@ examples:
clock-names = "core";
interconnects =
<&rsc_hlos MASTER_IPA &rsc_hlos SLAVE_EBI1>,
<&rsc_hlos MASTER_IPA &rsc_hlos SLAVE_IMEM>,
<&rsc_hlos MASTER_APPSS_PROC &rsc_hlos SLAVE_IPA_CFG>;
<&aggre2_noc MASTER_IPA 0 &mc_virt SLAVE_EBI1 0>,
<&aggre2_noc MASTER_IPA 0 &system_noc SLAVE_IMEM 0>,
<&gem_noc MASTER_APPSS_PROC 0 &config_noc SLAVE_IPA_CFG 0>;
interconnect-names = "memory",
"imem",
"config";

View file

@ -81,6 +81,23 @@
/* Divider for 19.2 MHz crystal oscillator clock to get common timer clock */
#define IPA_XO_CLOCK_DIVIDER 192 /* 1 is subtracted where used */
/**
* enum ipa_firmware_loader: How GSI firmware gets loaded
*
* @IPA_LOADER_DEFER: System not ready; try again later
* @IPA_LOADER_SELF: AP loads GSI firmware
* @IPA_LOADER_MODEM: Modem loads GSI firmware, signals when done
* @IPA_LOADER_SKIP: Neither AP nor modem need to load GSI firmware
* @IPA_LOADER_INVALID: GSI firmware loader specification is invalid
*/
enum ipa_firmware_loader {
IPA_LOADER_DEFER,
IPA_LOADER_SELF,
IPA_LOADER_MODEM,
IPA_LOADER_SKIP,
IPA_LOADER_INVALID,
};
/**
* ipa_setup() - Set up IPA hardware
* @ipa: IPA pointer
@ -696,6 +713,50 @@ static void ipa_validate_build(void)
BUILD_BUG_ON(!ipa_aggr_granularity_val(IPA_AGGR_GRANULARITY));
}
static enum ipa_firmware_loader ipa_firmware_loader(struct device *dev)
{
bool modem_init;
const char *str;
int ret;
/* Look up the old and new properties by name */
modem_init = of_property_read_bool(dev->of_node, "modem-init");
ret = of_property_read_string(dev->of_node, "qcom,gsi-loader", &str);
/* If the new property doesn't exist, it's legacy behavior */
if (ret == -EINVAL) {
if (modem_init)
return IPA_LOADER_MODEM;
goto out_self;
}
/* Any other error on the new property means it's poorly defined */
if (ret)
return IPA_LOADER_INVALID;
/* New property value exists; if old one does too, that's invalid */
if (modem_init)
return IPA_LOADER_INVALID;
/* Modem loads GSI firmware for "modem" */
if (!strcmp(str, "modem"))
return IPA_LOADER_MODEM;
/* No GSI firmware load is needed for "skip" */
if (!strcmp(str, "skip"))
return IPA_LOADER_SKIP;
/* Any value other than "self" is an error */
if (strcmp(str, "self"))
return IPA_LOADER_INVALID;
out_self:
/* We need Trust Zone to load firmware; make sure it's available */
if (qcom_scm_is_available())
return IPA_LOADER_SELF;
return IPA_LOADER_DEFER;
}
/**
* ipa_probe() - IPA platform driver probe function
* @pdev: Platform device pointer
@ -722,9 +783,9 @@ static void ipa_validate_build(void)
static int ipa_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
enum ipa_firmware_loader loader;
const struct ipa_data *data;
struct ipa_power *power;
bool modem_init;
struct ipa *ipa;
int ret;
@ -747,11 +808,11 @@ static int ipa_probe(struct platform_device *pdev)
return -EINVAL;
}
/* If we need Trust Zone, make sure it's available */
modem_init = of_property_read_bool(dev->of_node, "modem-init");
if (!modem_init)
if (!qcom_scm_is_available())
return -EPROBE_DEFER;
loader = ipa_firmware_loader(dev);
if (loader == IPA_LOADER_INVALID)
return -EINVAL;
if (loader == IPA_LOADER_DEFER)
return -EPROBE_DEFER;
/* The clock and interconnects might not be ready when we're
* probed, so might return -EPROBE_DEFER.
@ -796,7 +857,7 @@ static int ipa_probe(struct platform_device *pdev)
if (ret)
goto err_endpoint_exit;
ret = ipa_smp2p_init(ipa, modem_init);
ret = ipa_smp2p_init(ipa, loader == IPA_LOADER_MODEM);
if (ret)
goto err_table_exit;
@ -811,20 +872,20 @@ static int ipa_probe(struct platform_device *pdev)
dev_info(dev, "IPA driver initialized");
/* If the modem is doing early initialization, it will trigger a
* call to ipa_setup() when it has finished. In that case we're
* done here.
/* If the modem is loading GSI firmware, it will trigger a call to
* ipa_setup() when it has finished. In that case we're done here.
*/
if (modem_init)
if (loader == IPA_LOADER_MODEM)
goto done;
/* Otherwise we need to load the firmware and have Trust Zone validate
* and install it. If that succeeds we can proceed with setup.
*/
ret = ipa_firmware_load(dev);
if (ret)
goto err_deconfig;
if (loader == IPA_LOADER_SELF) {
/* The AP is loading GSI firmware; do so now */
ret = ipa_firmware_load(dev);
if (ret)
goto err_deconfig;
} /* Otherwise loader == IPA_LOADER_SKIP */
/* GSI firmware is loaded; proceed to setup */
ret = ipa_setup(ipa);
if (ret)
goto err_deconfig;