summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2022-11-17 21:46:58 -0800
committerJakub Kicinski <kuba@kernel.org>2022-11-17 21:46:59 -0800
commita452d30f3f17e59a585beafd015ca826a609f549 (patch)
tree7d82ae2249f0f3a7308bce9ea75211600798a385 /drivers
parent647541ea06a7bbbcf941e501c726b3e26328c102 (diff)
parent7569805ec26e9df454ed97a4521003cde53899bb (diff)
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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ipa/ipa_main.c95
1 files changed, 78 insertions, 17 deletions
diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c
index ebb6c9b311eb..8f20825675a1 100644
--- a/drivers/net/ipa/ipa_main.c
+++ b/drivers/net/ipa/ipa_main.c
@@ -82,6 +82,23 @@
#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;