diff options
author | Alex Elder <elder@linaro.org> | 2023-02-10 13:36:48 -0600 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2023-02-13 09:56:16 +0000 |
commit | 3c506add35c74acbe5a42d0a86963d11bef10d25 (patch) | |
tree | 958e385464f1331b54e23ad9c03ecc18e2f8739a /drivers/net/ipa | |
parent | 4fab64126891d413f207dacd5762a839b3470315 (diff) |
net: ipa: introduce gsi_reg_init()
Create a new source file "gsi_reg.c", and in it, introduce a new
function to encapsulate initializing GSI registers, including
looking up and I/O mapping their memory.
Create gsi_reg_exit() as the inverse of the init function.
Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ipa')
-rw-r--r-- | drivers/net/ipa/Makefile | 4 | ||||
-rw-r--r-- | drivers/net/ipa/gsi.c | 52 | ||||
-rw-r--r-- | drivers/net/ipa/gsi_reg.c | 71 | ||||
-rw-r--r-- | drivers/net/ipa/gsi_reg.h | 35 |
4 files changed, 103 insertions, 59 deletions
diff --git a/drivers/net/ipa/Makefile b/drivers/net/ipa/Makefile index 8cdcaaf58ae3..166ef86f7ad3 100644 --- a/drivers/net/ipa/Makefile +++ b/drivers/net/ipa/Makefile @@ -7,8 +7,8 @@ IPA_VERSIONS := 3.1 3.5.1 4.2 4.5 4.7 4.9 4.11 obj-$(CONFIG_QCOM_IPA) += ipa.o ipa-y := ipa_main.o ipa_power.o ipa_reg.o ipa_mem.o \ - ipa_table.o ipa_interrupt.o gsi.o gsi_trans.o \ - ipa_gsi.o ipa_smp2p.o ipa_uc.o \ + ipa_table.o ipa_interrupt.o gsi.o gsi_reg.o \ + gsi_trans.o ipa_gsi.o ipa_smp2p.o ipa_uc.o \ ipa_endpoint.o ipa_cmd.o ipa_modem.o \ ipa_resource.o ipa_qmi.o ipa_qmi_msg.o \ ipa_sysfs.o diff --git a/drivers/net/ipa/gsi.c b/drivers/net/ipa/gsi.c index 2cb1710f6ac3..a000bef49f8e 100644 --- a/drivers/net/ipa/gsi.c +++ b/drivers/net/ipa/gsi.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - * Copyright (C) 2018-2022 Linaro Ltd. + * Copyright (C) 2018-2023 Linaro Ltd. */ #include <linux/types.h> @@ -2241,67 +2241,37 @@ int gsi_init(struct gsi *gsi, struct platform_device *pdev, enum ipa_version version, u32 count, const struct ipa_gsi_endpoint_data *data) { - struct device *dev = &pdev->dev; - struct resource *res; - resource_size_t size; - u32 adjust; int ret; gsi_validate_build(); - gsi->dev = dev; + gsi->dev = &pdev->dev; gsi->version = version; /* GSI uses NAPI on all channels. Create a dummy network device * for the channel NAPI contexts to be associated with. */ init_dummy_netdev(&gsi->dummy_dev); - - /* Get GSI memory range and map it */ - res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gsi"); - if (!res) { - dev_err(dev, "DT error getting \"gsi\" memory property\n"); - return -ENODEV; - } - - size = resource_size(res); - if (res->start > U32_MAX || size > U32_MAX - res->start) { - dev_err(dev, "DT memory resource \"gsi\" out of range\n"); - return -EINVAL; - } - - /* Make sure we can make our pointer adjustment if necessary */ - adjust = gsi->version < IPA_VERSION_4_5 ? 0 : GSI_EE_REG_ADJUST; - if (res->start < adjust) { - dev_err(dev, "DT memory resource \"gsi\" too low (< %u)\n", - adjust); - return -EINVAL; - } - - gsi->virt_raw = ioremap(res->start, size); - if (!gsi->virt_raw) { - dev_err(dev, "unable to remap \"gsi\" memory\n"); - return -ENOMEM; - } - /* Most registers are accessed using an adjusted register range */ - gsi->virt = gsi->virt_raw - adjust; - init_completion(&gsi->completion); + ret = gsi_reg_init(gsi, pdev); + if (ret) + return ret; + ret = gsi_irq_init(gsi, pdev); /* No matching exit required */ if (ret) - goto err_iounmap; + goto err_reg_exit; ret = gsi_channel_init(gsi, count, data); if (ret) - goto err_iounmap; + goto err_reg_exit; mutex_init(&gsi->mutex); return 0; -err_iounmap: - iounmap(gsi->virt_raw); +err_reg_exit: + gsi_reg_exit(gsi); return ret; } @@ -2311,7 +2281,7 @@ void gsi_exit(struct gsi *gsi) { mutex_destroy(&gsi->mutex); gsi_channel_exit(gsi); - iounmap(gsi->virt_raw); + gsi_reg_exit(gsi); } /* The maximum number of outstanding TREs on a channel. This limits diff --git a/drivers/net/ipa/gsi_reg.c b/drivers/net/ipa/gsi_reg.c new file mode 100644 index 000000000000..48f81fc24f39 --- /dev/null +++ b/drivers/net/ipa/gsi_reg.c @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: GPL-2.0 + +/* Copyright (C) 2023 Linaro Ltd. */ + +#include <linux/platform_device.h> +#include <linux/io.h> + +#include "gsi.h" +#include "gsi_reg.h" + +/* GSI EE registers as a group are shifted downward by a fixed constant amount + * for IPA versions 4.5 and beyond. This applies to all GSI registers we use + * *except* the ones that disable inter-EE interrupts for channels and event + * channels. + * + * The "raw" (not adjusted) GSI register range is mapped, and a pointer to + * the mapped range is held in gsi->virt_raw. The inter-EE interrupt + * registers are accessed using that pointer. + * + * Most registers are accessed using gsi->virt, which is a copy of the "raw" + * pointer, adjusted downward by the fixed amount. + */ +#define GSI_EE_REG_ADJUST 0x0000d000 /* IPA v4.5+ */ + +/* Sets gsi->virt_raw and gsi->virt, and I/O maps the "gsi" memory range */ +int gsi_reg_init(struct gsi *gsi, struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct resource *res; + resource_size_t size; + u32 adjust; + + /* Get GSI memory range and map it */ + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "gsi"); + if (!res) { + dev_err(dev, "DT error getting \"gsi\" memory property\n"); + return -ENODEV; + } + + size = resource_size(res); + if (res->start > U32_MAX || size > U32_MAX - res->start) { + dev_err(dev, "DT memory resource \"gsi\" out of range\n"); + return -EINVAL; + } + + /* Make sure we can make our pointer adjustment if necessary */ + adjust = gsi->version < IPA_VERSION_4_5 ? 0 : GSI_EE_REG_ADJUST; + if (res->start < adjust) { + dev_err(dev, "DT memory resource \"gsi\" too low (< %u)\n", + adjust); + return -EINVAL; + } + + gsi->virt_raw = ioremap(res->start, size); + if (!gsi->virt_raw) { + dev_err(dev, "unable to remap \"gsi\" memory\n"); + return -ENOMEM; + } + /* Most registers are accessed using an adjusted register range */ + gsi->virt = gsi->virt_raw - adjust; + + return 0; +} + +/* Inverse of gsi_reg_init() */ +void gsi_reg_exit(struct gsi *gsi) +{ + gsi->virt = NULL; + iounmap(gsi->virt_raw); + gsi->virt_raw = NULL; +} diff --git a/drivers/net/ipa/gsi_reg.h b/drivers/net/ipa/gsi_reg.h index d171f65d4198..60071b6a4d32 100644 --- a/drivers/net/ipa/gsi_reg.h +++ b/drivers/net/ipa/gsi_reg.h @@ -1,12 +1,12 @@ /* SPDX-License-Identifier: GPL-2.0 */ /* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved. - * Copyright (C) 2018-2022 Linaro Ltd. + * Copyright (C) 2018-2023 Linaro Ltd. */ #ifndef _GSI_REG_H_ #define _GSI_REG_H_ -/* === Only "gsi.c" should include this file === */ +/* === Only "gsi.c" and "gsi_reg.c" should include this file === */ #include <linux/bits.h> @@ -38,20 +38,6 @@ * (though the actual limit is hardware-dependent). */ -/* GSI EE registers as a group are shifted downward by a fixed constant amount - * for IPA versions 4.5 and beyond. This applies to all GSI registers we use - * *except* the ones that disable inter-EE interrupts for channels and event - * channels. - * - * The "raw" (not adjusted) GSI register range is mapped, and a pointer to - * the mapped range is held in gsi->virt_raw. The inter-EE interrupt - * registers are accessed using that pointer. - * - * Most registers are accessed using gsi->virt, which is a copy of the "raw" - * pointer, adjusted downward by the fixed amount. - */ -#define GSI_EE_REG_ADJUST 0x0000d000 /* IPA v4.5+ */ - /* The inter-EE IRQ registers are relative to gsi->virt_raw (IPA v3.5+) */ #define GSI_INTER_EE_SRC_CH_IRQ_MSK_OFFSET \ @@ -400,4 +386,21 @@ enum gsi_generic_ee_result { GENERIC_EE_NO_RESOURCES = 0x7, }; +/** + * gsi_reg_init() - Perform GSI register initialization + * @gsi: GSI pointer + * @pdev: GSI (IPA) platform device + * + * Initialize GSI registers, including looking up and I/O mapping + * the "gsi" memory space. This function sets gsi->virt_raw and + * gsi->virt. + */ +int gsi_reg_init(struct gsi *gsi, struct platform_device *pdev); + +/** + * gsi_reg_exit() - Inverse of gsi_reg_init() + * @gsi: GSI pointer + */ +void gsi_reg_exit(struct gsi *gsi); + #endif /* _GSI_REG_H_ */ |