linux/drivers/net/ipa/ipa_main.c

// SPDX-License-Identifier: GPL-2.0

/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
 * Copyright (C) 2018-2024 Linaro Ltd.
 */

#include <linux/bug.h>
#include <linux/firmware.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/types.h>

#include <linux/firmware/qcom/qcom_scm.h>
#include <linux/soc/qcom/mdt_loader.h>

#include "ipa.h"
#include "ipa_cmd.h"
#include "ipa_data.h"
#include "ipa_endpoint.h"
#include "ipa_interrupt.h"
#include "ipa_mem.h"
#include "ipa_modem.h"
#include "ipa_power.h"
#include "ipa_reg.h"
#include "ipa_resource.h"
#include "ipa_smp2p.h"
#include "ipa_sysfs.h"
#include "ipa_table.h"
#include "ipa_uc.h"
#include "ipa_version.h"

/**
 * DOC: The IP Accelerator
 *
 * This driver supports the Qualcomm IP Accelerator (IPA), which is a
 * networking component found in many Qualcomm SoCs.  The IPA is connected
 * to the application processor (AP), but is also connected (and partially
 * controlled by) other "execution environments" (EEs), such as a modem.
 *
 * The IPA is the conduit between the AP and the modem that carries network
 * traffic.  This driver presents a network interface representing the
 * connection of the modem to external (e.g. LTE) networks.
 *
 * The IPA provides protocol checksum calculation, offloading this work
 * from the AP.  The IPA offers additional functionality, including routing,
 * filtering, and NAT support, but that more advanced functionality is not
 * currently supported.  Despite that, some resources--including routing
 * tables and filter tables--are defined in this driver because they must
 * be initialized even when the advanced hardware features are not used.
 *
 * There are two distinct layers that implement the IPA hardware, and this
 * is reflected in the organization of the driver.  The generic software
 * interface (GSI) is an integral component of the IPA, providing a
 * well-defined communication layer between the AP subsystem and the IPA
 * core.  The GSI implements a set of "channels" used for communication
 * between the AP and the IPA.
 *
 * The IPA layer uses GSI channels to implement its "endpoints".  And while
 * a GSI channel carries data between the AP and the IPA, a pair of IPA
 * endpoints is used to carry traffic between two EEs.  Specifically, the main
 * modem network interface is implemented by two pairs of endpoints:  a TX
 * endpoint on the AP coupled with an RX endpoint on the modem; and another
 * RX endpoint on the AP receiving data from a TX endpoint on the modem.
 */

/* The name of the GSI firmware file relative to /lib/firmware */
#define IPA_FW_PATH_DEFAULT
#define IPA_PAS_ID

/* Shift of 19.2 MHz timestamp to achieve lower resolution timestamps */
/* IPA v5.5+ does not specify Qtime timestamp config for DPL */
#define DPL_TIMESTAMP_SHIFT
#define TAG_TIMESTAMP_SHIFT
#define NAT_TIMESTAMP_SHIFT

/* Divider for 19.2 MHz crystal oscillator clock to get common timer clock */
#define IPA_XO_CLOCK_DIVIDER

/**
 * 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_setup() - Set up IPA hardware
 * @ipa:	IPA pointer
 *
 * Perform initialization that requires issuing immediate commands on
 * the command TX endpoint.  If the modem is doing GSI firmware load
 * and initialization, this function will be called when an SMP2P
 * interrupt has been signaled by the modem.  Otherwise it will be
 * called from ipa_probe() after GSI firmware has been successfully
 * loaded, authenticated, and started by Trust Zone.
 */
int ipa_setup(struct ipa *ipa)
{}

/**
 * ipa_teardown() - Inverse of ipa_setup()
 * @ipa:	IPA pointer
 */
static void ipa_teardown(struct ipa *ipa)
{}

static void
ipa_hardware_config_bcr(struct ipa *ipa, const struct ipa_data *data)
{}

static void ipa_hardware_config_tx(struct ipa *ipa)
{}

static void ipa_hardware_config_clkon(struct ipa *ipa)
{}

/* Configure bus access behavior for IPA components */
static void ipa_hardware_config_comp(struct ipa *ipa)
{}

/* Configure DDR and (possibly) PCIe max read/write QSB values */
static void
ipa_hardware_config_qsb(struct ipa *ipa, const struct ipa_data *data)
{}

/* The internal inactivity timer clock is used for the aggregation timer */
#define TIMER_FREQUENCY

/* Compute the value to use in the COUNTER_CFG register AGGR_GRANULARITY
 * field to represent the given number of microseconds.  The value is one
 * less than the number of timer ticks in the requested period.  0 is not
 * a valid granularity value (so for example @usec must be at least 16 for
 * a TIMER_FREQUENCY of 32000).
 */
static __always_inline u32 ipa_aggr_granularity_val(u32 usec)
{}

/* IPA uses unified Qtime starting at IPA v4.5, implementing various
 * timestamps and timers independent of the IPA core clock rate.  The
 * Qtimer is based on a 56-bit timestamp incremented at each tick of
 * a 19.2 MHz SoC crystal oscillator (XO clock).
 *
 * For IPA timestamps (tag, NAT, data path logging) a lower resolution
 * timestamp is achieved by shifting the Qtimer timestamp value right
 * some number of bits to produce the low-order bits of the coarser
 * granularity timestamp.
 *
 * For timers, a common timer clock is derived from the XO clock using
 * a divider (we use 192, to produce a 100kHz timer clock).  From
 * this common clock, three "pulse generators" are used to produce
 * timer ticks at a configurable frequency.  IPA timers (such as
 * those used for aggregation or head-of-line block handling) now
 * define their period based on one of these pulse generators.
 */
static void ipa_qtime_config(struct ipa *ipa)
{}

/* Before IPA v4.5 timing is controlled by a counter register */
static void ipa_hardware_config_counter(struct ipa *ipa)
{}

static void ipa_hardware_config_timing(struct ipa *ipa)
{}

static void ipa_hardware_config_hashing(struct ipa *ipa)
{}

static void ipa_idle_indication_cfg(struct ipa *ipa,
				    u32 enter_idle_debounce_thresh,
				    bool const_non_idle_enable)
{}

/**
 * ipa_hardware_dcd_config() - Enable dynamic clock division on IPA
 * @ipa:	IPA pointer
 *
 * Configures when the IPA signals it is idle to the global clock
 * controller, which can respond by scaling down the clock to save
 * power.
 */
static void ipa_hardware_dcd_config(struct ipa *ipa)
{}

static void ipa_hardware_dcd_deconfig(struct ipa *ipa)
{}

/**
 * ipa_hardware_config() - Primitive hardware initialization
 * @ipa:	IPA pointer
 * @data:	IPA configuration data
 */
static void ipa_hardware_config(struct ipa *ipa, const struct ipa_data *data)
{}

/**
 * ipa_hardware_deconfig() - Inverse of ipa_hardware_config()
 * @ipa:	IPA pointer
 *
 * This restores the power-on reset values (even if they aren't different)
 */
static void ipa_hardware_deconfig(struct ipa *ipa)
{}

/**
 * ipa_config() - Configure IPA hardware
 * @ipa:	IPA pointer
 * @data:	IPA configuration data
 *
 * Perform initialization requiring IPA power to be enabled.
 */
static int ipa_config(struct ipa *ipa, const struct ipa_data *data)
{}

/**
 * ipa_deconfig() - Inverse of ipa_config()
 * @ipa:	IPA pointer
 */
static void ipa_deconfig(struct ipa *ipa)
{}

static int ipa_firmware_load(struct device *dev)
{}

static const struct of_device_id ipa_match[] =;
MODULE_DEVICE_TABLE(of, ipa_match);

/* Check things that can be validated at build time.  This just
 * groups these things BUILD_BUG_ON() calls don't clutter the rest
 * of the code.
 * */
static void ipa_validate_build(void)
{}

static enum ipa_firmware_loader ipa_firmware_loader(struct device *dev)
{}

/**
 * ipa_probe() - IPA platform driver probe function
 * @pdev:	Platform device pointer
 *
 * Return:	0 if successful, or a negative error code (possibly
 *		EPROBE_DEFER)
 *
 * This is the main entry point for the IPA driver.  Initialization proceeds
 * in several stages:
 *   - The "init" stage involves activities that can be initialized without
 *     access to the IPA hardware.
 *   - The "config" stage requires IPA power to be active so IPA registers
 *     can be accessed, but does not require the use of IPA immediate commands.
 *   - The "setup" stage uses IPA immediate commands, and so requires the GSI
 *     layer to be initialized.
 *
 * A Boolean Device Tree "modem-init" property determines whether GSI
 * initialization will be performed by the AP (Trust Zone) or the modem.
 * If the AP does GSI initialization, the setup phase is entered after
 * this has completed successfully.  Otherwise the modem initializes
 * the GSI layer and signals it has finished by sending an SMP2P interrupt
 * to the AP; this triggers the start if IPA setup.
 */
static int ipa_probe(struct platform_device *pdev)
{}

static void ipa_remove(struct platform_device *pdev)
{}

static const struct attribute_group *ipa_attribute_groups[] =;

static struct platform_driver ipa_driver =;

module_platform_driver();

MODULE_LICENSE();
MODULE_DESCRIPTION();