Lines Matching +full:modem +full:- +full:init

1 // SPDX-License-Identifier: GPL-2.0
3 /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
4 * Copyright (C) 2018-2020 Linaro Ltd.
41 * controlled by) other "execution environments" (EEs), such as a modem.
43 * The IPA is the conduit between the AP and the modem that carries network
45 * connection of the modem to external (e.g. LTE) networks.
50 * currently supported. Despite that, some resources--including routing
51 * tables and filter tables--are defined in this driver because they must
57 * well-defined communication layer between the AP subsystem and the IPA
64 * modem network interface is implemented by two pairs of endpoints: a TX
65 * endpoint on the AP coupled with an RX endpoint on the modem; and another
66 * RX endpoint on the AP receiving data from a TX endpoint on the modem.
74 * ipa_suspend_handler() - Handle the suspend IPA interrupt
89 if (!test_and_set_bit(IPA_FLAG_RESUMED, ipa->flags)) in ipa_suspend_handler()
90 pm_wakeup_dev_event(&ipa->pdev->dev, 0, true); in ipa_suspend_handler()
93 ipa_interrupt_suspend_clear_all(ipa->interrupt); in ipa_suspend_handler()
97 * ipa_setup() - Set up IPA hardware
101 * the command TX endpoint. If the modem is doing GSI firmware load
103 * interrupt has been signaled by the modem. Otherwise it will be
111 struct device *dev = &ipa->pdev->dev; in ipa_setup()
115 ret = gsi_setup(&ipa->gsi, ipa->version == IPA_VERSION_3_5_1); in ipa_setup()
119 ipa->interrupt = ipa_interrupt_setup(ipa); in ipa_setup()
120 if (IS_ERR(ipa->interrupt)) { in ipa_setup()
121 ret = PTR_ERR(ipa->interrupt); in ipa_setup()
124 ipa_interrupt_add(ipa->interrupt, IPA_IRQ_TX_SUSPEND, in ipa_setup()
138 command_endpoint = ipa->name_map[IPA_ENDPOINT_AP_COMMAND_TX]; in ipa_setup()
154 exception_endpoint = ipa->name_map[IPA_ENDPOINT_AP_LAN_RX]; in ipa_setup()
159 ipa_endpoint_default_route_set(ipa, exception_endpoint->endpoint_id); in ipa_setup()
161 /* We're all set. Now prepare for communication with the modem */ in ipa_setup()
166 ipa->setup_complete = true; in ipa_setup()
186 ipa_interrupt_remove(ipa->interrupt, IPA_IRQ_TX_SUSPEND); in ipa_setup()
187 ipa_interrupt_teardown(ipa->interrupt); in ipa_setup()
189 gsi_teardown(&ipa->gsi); in ipa_setup()
195 * ipa_teardown() - Inverse of ipa_setup()
205 exception_endpoint = ipa->name_map[IPA_ENDPOINT_AP_LAN_RX]; in ipa_teardown()
209 command_endpoint = ipa->name_map[IPA_ENDPOINT_AP_COMMAND_TX]; in ipa_teardown()
212 (void)device_init_wakeup(&ipa->pdev->dev, false); in ipa_teardown()
214 ipa_interrupt_remove(ipa->interrupt, IPA_IRQ_TX_SUSPEND); in ipa_teardown()
215 ipa_interrupt_teardown(ipa->interrupt); in ipa_teardown()
216 gsi_teardown(&ipa->gsi); in ipa_teardown()
225 if (ipa->version == IPA_VERSION_3_5_1) in ipa_hardware_config_comp()
228 val = ioread32(ipa->reg_virt + IPA_REG_COMP_CFG_OFFSET); in ipa_hardware_config_comp()
230 if (ipa->version == IPA_VERSION_4_0) { in ipa_hardware_config_comp()
241 iowrite32(val, ipa->reg_virt + IPA_REG_COMP_CFG_OFFSET); in ipa_hardware_config_comp()
251 if (ipa->version == IPA_VERSION_4_2) in ipa_hardware_config_qsb()
255 iowrite32(val, ipa->reg_virt + IPA_REG_QSB_MAX_WRITES_OFFSET); in ipa_hardware_config_qsb()
257 if (ipa->version == IPA_VERSION_3_5_1) { in ipa_hardware_config_qsb()
262 if (ipa->version == IPA_VERSION_4_2) in ipa_hardware_config_qsb()
269 iowrite32(val, ipa->reg_virt + IPA_REG_QSB_MAX_READS_OFFSET); in ipa_hardware_config_qsb()
284 offset = ipa_reg_idle_indication_cfg_offset(ipa->version); in ipa_idle_indication_cfg()
285 iowrite32(val, ipa->reg_virt + offset); in ipa_idle_indication_cfg()
289 * ipa_hardware_dcd_config() - Enable dynamic clock division on IPA
304 /* Power-on reset values */ in ipa_hardware_dcd_deconfig()
309 * ipa_hardware_config() - Primitive hardware initialization
317 /* Fill in backward-compatibility register, based on version */ in ipa_hardware_config()
318 val = ipa_reg_bcr_val(ipa->version); in ipa_hardware_config()
319 iowrite32(val, ipa->reg_virt + IPA_REG_BCR_OFFSET); in ipa_hardware_config()
321 if (ipa->version != IPA_VERSION_3_5_1) { in ipa_hardware_config()
325 iowrite32(val, ipa->reg_virt + IPA_REG_CLKON_CFG_OFFSET); in ipa_hardware_config()
328 val = ioread32(ipa->reg_virt + IPA_REG_TX_CFG_OFFSET); in ipa_hardware_config()
330 iowrite32(val, ipa->reg_virt + IPA_REG_TX_CFG_OFFSET); in ipa_hardware_config()
339 val = ioread32(ipa->reg_virt + IPA_REG_COUNTER_CFG_OFFSET); in ipa_hardware_config()
342 iowrite32(val, ipa->reg_virt + IPA_REG_COUNTER_CFG_OFFSET); in ipa_hardware_config()
345 if (ipa->version == IPA_VERSION_4_2) in ipa_hardware_config()
346 iowrite32(0, ipa->reg_virt + IPA_REG_FILT_ROUT_HASH_EN_OFFSET); in ipa_hardware_config()
353 * ipa_hardware_deconfig() - Inverse of ipa_hardware_config()
356 * This restores the power-on reset values (even if they aren't different)
369 switch (ipa->version) { in ipa_resource_group_count()
395 /* Return an error if a non-zero resource group limit is specified in ipa_resource_limits_valid()
398 for (i = 0; i < data->resource_src_count; i++) { in ipa_resource_limits_valid()
401 resource = &data->resource_src[i]; in ipa_resource_limits_valid()
403 if (resource->limits[j].min || resource->limits[j].max) in ipa_resource_limits_valid()
407 for (i = 0; i < data->resource_dst_count; i++) { in ipa_resource_limits_valid()
410 resource = &data->resource_dst[i]; in ipa_resource_limits_valid()
412 if (resource->limits[j].min || resource->limits[j].max) in ipa_resource_limits_valid()
436 val = u32_encode_bits(xlimits->min, X_MIN_LIM_FMASK); in ipa_resource_config_common()
437 val |= u32_encode_bits(xlimits->max, X_MAX_LIM_FMASK); in ipa_resource_config_common()
438 val |= u32_encode_bits(ylimits->min, Y_MIN_LIM_FMASK); in ipa_resource_config_common()
439 val |= u32_encode_bits(ylimits->max, Y_MAX_LIM_FMASK); in ipa_resource_config_common()
441 iowrite32(val, ipa->reg_virt + offset); in ipa_resource_config_common()
447 u32 offset = IPA_REG_SRC_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource->type); in ipa_resource_config_src_01()
450 &resource->limits[0], &resource->limits[1]); in ipa_resource_config_src_01()
456 u32 offset = IPA_REG_SRC_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource->type); in ipa_resource_config_src_23()
459 &resource->limits[2], &resource->limits[3]); in ipa_resource_config_src_23()
465 u32 offset = IPA_REG_DST_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource->type); in ipa_resource_config_dst_01()
468 &resource->limits[0], &resource->limits[1]); in ipa_resource_config_dst_01()
474 u32 offset = IPA_REG_DST_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource->type); in ipa_resource_config_dst_23()
477 &resource->limits[2], &resource->limits[3]); in ipa_resource_config_dst_23()
486 return -EINVAL; in ipa_resource_config()
488 for (i = 0; i < data->resource_src_count; i++) { in ipa_resource_config()
489 ipa_resource_config_src_01(ipa, &data->resource_src[i]); in ipa_resource_config()
490 ipa_resource_config_src_23(ipa, &data->resource_src[i]); in ipa_resource_config()
493 for (i = 0; i < data->resource_dst_count; i++) { in ipa_resource_config()
494 ipa_resource_config_dst_01(ipa, &data->resource_dst[i]); in ipa_resource_config()
495 ipa_resource_config_dst_23(ipa, &data->resource_dst[i]); in ipa_resource_config()
507 * ipa_config() - Configure IPA hardware
536 ret = ipa_resource_config(ipa, data->resource_data); in ipa_config()
561 * ipa_deconfig() - Inverse of ipa_config()
585 node = of_parse_phandle(dev->of_node, "memory-region", 0); in ipa_firmware_load()
587 dev_err(dev, "DT error getting \"memory-region\" property\n"); in ipa_firmware_load()
588 return -EINVAL; in ipa_firmware_load()
593 dev_err(dev, "error %d getting \"memory-region\" resource\n", in ipa_firmware_load()
609 ret = -ENOMEM; in ipa_firmware_load()
630 .compatible = "qcom,sdm845-ipa",
634 .compatible = "qcom,sc7180-ipa",
651 return be32_to_cpup(prop->value); in of_property_read_phandle()
661 /* We assume we're working on 64-bit hardware */ in ipa_validate_build()
676 * TLV FIFO size. A transaction structure uses 8-bit fields in ipa_validate_build()
695 * ipa_probe() - IPA platform driver probe function
703 * - The "init" stage involves activities that can be initialized without
705 * - The "config" stage requires the IPA clock to be active so IPA registers
707 * - The "setup" stage uses IPA immediate commands, and so requires the GSI
710 * A Boolean Device Tree "modem-init" property determines whether GSI
711 * initialization will be performed by the AP (Trust Zone) or the modem.
713 * this has completed successfully. Otherwise the modem initializes
719 struct device *dev = &pdev->dev; in ipa_probe()
733 modem_init = of_property_read_bool(dev->of_node, "modem-init"); in ipa_probe()
736 return -EPROBE_DEFER; in ipa_probe()
738 /* We rely on remoteproc to tell us about modem state changes */ in ipa_probe()
739 ph = of_property_read_phandle(dev->of_node, "modem-remoteproc"); in ipa_probe()
741 dev_err(dev, "DT missing \"modem-remoteproc\" property\n"); in ipa_probe()
742 return -EINVAL; in ipa_probe()
747 return -EPROBE_DEFER; in ipa_probe()
750 * probed, so might return -EPROBE_DEFER. in ipa_probe()
763 ret = -ENOTSUPP; in ipa_probe()
770 ret = -ENOMEM; in ipa_probe()
774 ipa->pdev = pdev; in ipa_probe()
776 ipa->modem_rproc = rproc; in ipa_probe()
777 ipa->clock = clock; in ipa_probe()
778 ipa->version = data->version; in ipa_probe()
784 ret = ipa_mem_init(ipa, data->mem_data); in ipa_probe()
789 prefetch = ipa->version != IPA_VERSION_3_5_1; in ipa_probe()
790 /* IPA v4.2 requires the AP to allocate channels for the modem */ in ipa_probe()
791 modem_alloc = ipa->version == IPA_VERSION_4_2; in ipa_probe()
793 ret = gsi_init(&ipa->gsi, pdev, prefetch, data->endpoint_count, in ipa_probe()
794 data->endpoint_data, modem_alloc); in ipa_probe()
798 /* Result is a non-zero mask endpoints that support filtering */ in ipa_probe()
799 ipa->filter_map = ipa_endpoint_init(ipa, data->endpoint_count, in ipa_probe()
800 data->endpoint_data); in ipa_probe()
801 if (!ipa->filter_map) { in ipa_probe()
802 ret = -EINVAL; in ipa_probe()
820 /* If the modem is doing early initialization, it will trigger a in ipa_probe()
849 gsi_exit(&ipa->gsi); in ipa_probe()
866 struct ipa *ipa = dev_get_drvdata(&pdev->dev); in ipa_remove()
867 struct rproc *rproc = ipa->modem_rproc; in ipa_remove()
868 struct ipa_clock *clock = ipa->clock; in ipa_remove()
871 if (ipa->setup_complete) { in ipa_remove()
883 gsi_exit(&ipa->gsi); in ipa_remove()
894 * ipa_suspend() - Power management system suspend callback
911 __clear_bit(IPA_FLAG_RESUMED, ipa->flags); in ipa_suspend()
921 * ipa_resume() - Power management system resume callback