summaryrefslogtreecommitdiff
path: root/drivers/soc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/soc')
-rw-r--r--drivers/soc/Kconfig1
-rw-r--r--drivers/soc/Makefile3
-rw-r--r--drivers/soc/amlogic/meson-gx-socinfo.c10
-rw-r--r--drivers/soc/atmel/soc.c23
-rw-r--r--drivers/soc/atmel/soc.h9
-rw-r--r--drivers/soc/cirrus/Kconfig17
-rw-r--r--drivers/soc/cirrus/Makefile2
-rw-r--r--drivers/soc/cirrus/soc-ep93xx.c252
-rw-r--r--drivers/soc/fsl/qbman/qman.c5
-rw-r--r--drivers/soc/fsl/qbman/qman_ccsr.c2
-rw-r--r--drivers/soc/fsl/qbman/qman_portal.c5
-rw-r--r--drivers/soc/fsl/qe/Kconfig17
-rw-r--r--drivers/soc/fsl/qe/qe_common.c80
-rw-r--r--drivers/soc/fsl/qe/qmc.c667
-rw-r--r--drivers/soc/fsl/qe/tsa.c659
-rw-r--r--drivers/soc/fsl/qe/tsa.h3
-rw-r--r--drivers/soc/fsl/qe/ucc.c1
-rw-r--r--drivers/soc/mediatek/mtk-mutex.c52
-rw-r--r--drivers/soc/mediatek/mtk-pmic-wrap.c118
-rw-r--r--drivers/soc/qcom/Kconfig2
-rw-r--r--drivers/soc/qcom/Makefile1
-rw-r--r--drivers/soc/qcom/apr.c5
-rw-r--r--drivers/soc/qcom/cmd-db.c2
-rw-r--r--drivers/soc/qcom/icc-bwmon.c6
-rw-r--r--drivers/soc/qcom/ice.c14
-rw-r--r--drivers/soc/qcom/llcc-qcom.c32
-rw-r--r--drivers/soc/qcom/ocmem.c7
-rw-r--r--drivers/soc/qcom/pmic_glink.c40
-rw-r--r--drivers/soc/qcom/pmic_glink_altmode.c17
-rw-r--r--drivers/soc/qcom/qcom-pbs.c16
-rw-r--r--drivers/soc/qcom/qcom_aoss.c8
-rw-r--r--drivers/soc/qcom/qcom_pd_mapper.c19
-rw-r--r--drivers/soc/qcom/smd-rpm.c41
-rw-r--r--drivers/soc/qcom/smp2p.c25
-rw-r--r--drivers/soc/qcom/socinfo.c4
-rw-r--r--drivers/soc/qcom/trace-smp2p.h98
-rw-r--r--drivers/soc/qcom/trace_icc-bwmon.h48
-rw-r--r--drivers/soc/rockchip/grf.c32
-rw-r--r--drivers/soc/rockchip/io-domain.c40
-rw-r--r--drivers/soc/tegra/pmc.c12
-rw-r--r--drivers/soc/ti/k3-ringacc.c12
-rw-r--r--drivers/soc/ti/knav_dma.c22
-rw-r--r--drivers/soc/ti/knav_qmss_queue.c105
-rw-r--r--drivers/soc/ti/pm33xx.c52
-rw-r--r--drivers/soc/ti/pruss.c176
-rw-r--r--drivers/soc/versatile/Kconfig4
-rw-r--r--drivers/soc/versatile/soc-integrator.c1
-rw-r--r--drivers/soc/versatile/soc-realview.c20
48 files changed, 2031 insertions, 756 deletions
diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig
index 5d924e946507..6a8daeb8c4b9 100644
--- a/drivers/soc/Kconfig
+++ b/drivers/soc/Kconfig
@@ -7,6 +7,7 @@ source "drivers/soc/aspeed/Kconfig"
source "drivers/soc/atmel/Kconfig"
source "drivers/soc/bcm/Kconfig"
source "drivers/soc/canaan/Kconfig"
+source "drivers/soc/cirrus/Kconfig"
source "drivers/soc/fsl/Kconfig"
source "drivers/soc/fujitsu/Kconfig"
source "drivers/soc/hisilicon/Kconfig"
diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile
index fb2bd31387d0..2037a8695cb2 100644
--- a/drivers/soc/Makefile
+++ b/drivers/soc/Makefile
@@ -8,6 +8,7 @@ obj-y += aspeed/
obj-$(CONFIG_ARCH_AT91) += atmel/
obj-y += bcm/
obj-$(CONFIG_ARCH_CANAAN) += canaan/
+obj-$(CONFIG_EP93XX_SOC) += cirrus/
obj-$(CONFIG_ARCH_DOVE) += dove/
obj-$(CONFIG_MACH_DOVE) += dove/
obj-y += fsl/
@@ -32,5 +33,5 @@ obj-y += sunxi/
obj-$(CONFIG_ARCH_TEGRA) += tegra/
obj-y += ti/
obj-$(CONFIG_ARCH_U8500) += ux500/
-obj-$(CONFIG_PLAT_VERSATILE) += versatile/
+obj-y += versatile/
obj-y += xilinx/
diff --git a/drivers/soc/amlogic/meson-gx-socinfo.c b/drivers/soc/amlogic/meson-gx-socinfo.c
index 8809a948201a..7549f1644e5e 100644
--- a/drivers/soc/amlogic/meson-gx-socinfo.c
+++ b/drivers/soc/amlogic/meson-gx-socinfo.c
@@ -41,6 +41,11 @@ static const struct meson_gx_soc_id {
{ "G12B", 0x29 },
{ "SM1", 0x2b },
{ "A1", 0x2c },
+ { "T7", 0x36 },
+ { "S4", 0x37 },
+ { "A5", 0x3c },
+ { "C3", 0x3d },
+ { "A4", 0x40 },
};
static const struct meson_gx_package_id {
@@ -76,6 +81,11 @@ static const struct meson_gx_package_id {
{ "S905X3", 0x2b, 0x10, 0x3f },
{ "S905D3", 0x2b, 0x30, 0x3f },
{ "A113L", 0x2c, 0x0, 0xf8 },
+ { "S805X2", 0x37, 0x2, 0xf },
+ { "C308L", 0x3d, 0x1, 0xf },
+ { "A311D2", 0x36, 0x1, 0xf },
+ { "A113X2", 0x3c, 0x1, 0xf },
+ { "A113L2", 0x40, 0x1, 0xf },
};
static inline unsigned int socinfo_to_major(u32 socinfo)
diff --git a/drivers/soc/atmel/soc.c b/drivers/soc/atmel/soc.c
index cc9a3e107479..2a42b28931c9 100644
--- a/drivers/soc/atmel/soc.c
+++ b/drivers/soc/atmel/soc.c
@@ -101,6 +101,29 @@ static const struct at91_soc socs[] __initconst = {
AT91_CIDR_VERSION_MASK, SAM9X60_D6K_EXID_MATCH,
"sam9x60 8MiB SDRAM SiP", "sam9x60"),
#endif
+#ifdef CONFIG_SOC_SAM9X7
+ AT91_SOC(SAM9X7_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
+ AT91_CIDR_VERSION_MASK, SAM9X70_EXID_MATCH,
+ "sam9x70", "sam9x7"),
+ AT91_SOC(SAM9X7_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
+ AT91_CIDR_VERSION_MASK, SAM9X72_EXID_MATCH,
+ "sam9x72", "sam9x7"),
+ AT91_SOC(SAM9X7_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
+ AT91_CIDR_VERSION_MASK, SAM9X75_EXID_MATCH,
+ "sam9x75", "sam9x7"),
+ AT91_SOC(SAM9X7_CIDR_MATCH, SAM9X75_D1M_EXID_MATCH,
+ AT91_CIDR_VERSION_MASK, SAM9X75_EXID_MATCH,
+ "sam9x75 16MB DDR2 SiP", "sam9x7"),
+ AT91_SOC(SAM9X7_CIDR_MATCH, SAM9X75_D5M_EXID_MATCH,
+ AT91_CIDR_VERSION_MASK, SAM9X75_EXID_MATCH,
+ "sam9x75 64MB DDR2 SiP", "sam9x7"),
+ AT91_SOC(SAM9X7_CIDR_MATCH, SAM9X75_D1G_EXID_MATCH,
+ AT91_CIDR_VERSION_MASK, SAM9X75_EXID_MATCH,
+ "sam9x75 125MB DDR3L SiP ", "sam9x7"),
+ AT91_SOC(SAM9X7_CIDR_MATCH, SAM9X75_D2G_EXID_MATCH,
+ AT91_CIDR_VERSION_MASK, SAM9X75_EXID_MATCH,
+ "sam9x75 250MB DDR3L SiP", "sam9x7"),
+#endif
#ifdef CONFIG_SOC_SAMA5
AT91_SOC(SAMA5D2_CIDR_MATCH, AT91_CIDR_MATCH_MASK,
AT91_CIDR_VERSION_MASK, SAMA5D21CU_EXID_MATCH,
diff --git a/drivers/soc/atmel/soc.h b/drivers/soc/atmel/soc.h
index 7a9f47ce85fb..2c78e54255f7 100644
--- a/drivers/soc/atmel/soc.h
+++ b/drivers/soc/atmel/soc.h
@@ -44,6 +44,7 @@ at91_soc_init(const struct at91_soc *socs);
#define AT91SAM9X5_CIDR_MATCH 0x019a05a0
#define AT91SAM9N12_CIDR_MATCH 0x019a07a0
#define SAM9X60_CIDR_MATCH 0x019b35a0
+#define SAM9X7_CIDR_MATCH 0x09750020
#define SAMA7G5_CIDR_MATCH 0x00162100
#define AT91SAM9M11_EXID_MATCH 0x00000001
@@ -66,6 +67,14 @@ at91_soc_init(const struct at91_soc *socs);
#define SAM9X60_D1G_EXID_MATCH 0x00000010
#define SAM9X60_D6K_EXID_MATCH 0x00000011
+#define SAM9X70_EXID_MATCH 0x00000005
+#define SAM9X72_EXID_MATCH 0x00000004
+#define SAM9X75_D1G_EXID_MATCH 0x00000018
+#define SAM9X75_D2G_EXID_MATCH 0x00000020
+#define SAM9X75_D1M_EXID_MATCH 0x00000003
+#define SAM9X75_D5M_EXID_MATCH 0x00000010
+#define SAM9X75_EXID_MATCH 0x00000000
+
#define SAMA7G51_EXID_MATCH 0x3
#define SAMA7G52_EXID_MATCH 0x2
#define SAMA7G53_EXID_MATCH 0x1
diff --git a/drivers/soc/cirrus/Kconfig b/drivers/soc/cirrus/Kconfig
new file mode 100644
index 000000000000..d8b3b1e68998
--- /dev/null
+++ b/drivers/soc/cirrus/Kconfig
@@ -0,0 +1,17 @@
+# SPDX-License-Identifier: GPL-2.0-only
+
+if ARCH_EP93XX
+
+config EP93XX_SOC
+ bool "Cirrus EP93xx chips SoC"
+ select SOC_BUS
+ select AUXILIARY_BUS
+ default y
+ help
+ Enable support SoC for Cirrus EP93xx chips.
+
+ Cirrus EP93xx chips have several swlocked registers,
+ this driver provides locked access for reset, pinctrl
+ and clk devices implemented as auxiliary devices.
+
+endif
diff --git a/drivers/soc/cirrus/Makefile b/drivers/soc/cirrus/Makefile
new file mode 100644
index 000000000000..9e6608b67f76
--- /dev/null
+++ b/drivers/soc/cirrus/Makefile
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0-only
+obj-y += soc-ep93xx.o
diff --git a/drivers/soc/cirrus/soc-ep93xx.c b/drivers/soc/cirrus/soc-ep93xx.c
new file mode 100644
index 000000000000..3e79b3b13aef
--- /dev/null
+++ b/drivers/soc/cirrus/soc-ep93xx.c
@@ -0,0 +1,252 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * SoC driver for Cirrus EP93xx chips.
+ * Copyright (C) 2022 Nikita Shubin <nikita.shubin@maquefel.me>
+ *
+ * Based on a rewrite of arch/arm/mach-ep93xx/core.c
+ * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Copyright (C) 2007 Herbert Valerio Riedel <hvr@gnu.org>
+ *
+ * Thanks go to Michael Burian and Ray Lehtiniemi for their key
+ * role in the ep93xx Linux community.
+ */
+
+#include <linux/bits.h>
+#include <linux/cleanup.h>
+#include <linux/init.h>
+#include <linux/mfd/syscon.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/sys_soc.h>
+
+#include <linux/soc/cirrus/ep93xx.h>
+
+#define EP93XX_SYSCON_DEVCFG 0x80
+
+#define EP93XX_SWLOCK_MAGICK 0xaa
+#define EP93XX_SYSCON_SWLOCK 0xc0
+#define EP93XX_SYSCON_SYSCFG 0x9c
+#define EP93XX_SYSCON_SYSCFG_REV_MASK GENMASK(31, 28)
+#define EP93XX_SYSCON_SYSCFG_REV_SHIFT 28
+
+struct ep93xx_map_info {
+ spinlock_t lock;
+ void __iomem *base;
+ struct regmap *map;
+};
+
+/*
+ * EP93xx System Controller software locked register write
+ *
+ * Logic safeguards are included to condition the control signals for
+ * power connection to the matrix to prevent part damage. In addition, a
+ * software lock register is included that must be written with 0xAA
+ * before each register write to change the values of the four switch
+ * matrix control registers.
+ */
+static void ep93xx_regmap_write(struct regmap *map, spinlock_t *lock,
+ unsigned int reg, unsigned int val)
+{
+ guard(spinlock_irqsave)(lock);
+
+ regmap_write(map, EP93XX_SYSCON_SWLOCK, EP93XX_SWLOCK_MAGICK);
+ regmap_write(map, reg, val);
+}
+
+static void ep93xx_regmap_update_bits(struct regmap *map, spinlock_t *lock,
+ unsigned int reg, unsigned int mask,
+ unsigned int val)
+{
+ guard(spinlock_irqsave)(lock);
+
+ regmap_write(map, EP93XX_SYSCON_SWLOCK, EP93XX_SWLOCK_MAGICK);
+ /* force write is required to clear swlock if no changes are made */
+ regmap_update_bits_base(map, reg, mask, val, NULL, false, true);
+}
+
+static void ep93xx_unregister_adev(void *_adev)
+{
+ struct auxiliary_device *adev = _adev;
+
+ auxiliary_device_delete(adev);
+ auxiliary_device_uninit(adev);
+}
+
+static void ep93xx_adev_release(struct device *dev)
+{
+ struct auxiliary_device *adev = to_auxiliary_dev(dev);
+ struct ep93xx_regmap_adev *rdev = to_ep93xx_regmap_adev(adev);
+
+ kfree(rdev);
+}
+
+static struct auxiliary_device __init *ep93xx_adev_alloc(struct device *parent,
+ const char *name,
+ struct ep93xx_map_info *info)
+{
+ struct ep93xx_regmap_adev *rdev __free(kfree) = NULL;
+ struct auxiliary_device *adev;
+ int ret;
+
+ rdev = kzalloc(sizeof(*rdev), GFP_KERNEL);
+ if (!rdev)
+ return ERR_PTR(-ENOMEM);
+
+ rdev->map = info->map;
+ rdev->base = info->base;
+ rdev->lock = &info->lock;
+ rdev->write = ep93xx_regmap_write;
+ rdev->update_bits = ep93xx_regmap_update_bits;
+
+ adev = &rdev->adev;
+ adev->name = name;
+ adev->dev.parent = parent;
+ adev->dev.release = ep93xx_adev_release;
+
+ ret = auxiliary_device_init(adev);
+ if (ret)
+ return ERR_PTR(ret);
+
+ return &no_free_ptr(rdev)->adev;
+}
+
+static int __init ep93xx_controller_register(struct device *parent, const char *name,
+ struct ep93xx_map_info *info)
+{
+ struct auxiliary_device *adev;
+ int ret;
+
+ adev = ep93xx_adev_alloc(parent, name, info);
+ if (IS_ERR(adev))
+ return PTR_ERR(adev);
+
+ ret = auxiliary_device_add(adev);
+ if (ret) {
+ auxiliary_device_uninit(adev);
+ return ret;
+ }
+
+ return devm_add_action_or_reset(parent, ep93xx_unregister_adev, adev);
+}
+
+static unsigned int __init ep93xx_soc_revision(struct regmap *map)
+{
+ unsigned int val;
+
+ regmap_read(map, EP93XX_SYSCON_SYSCFG, &val);
+ val &= EP93XX_SYSCON_SYSCFG_REV_MASK;
+ val >>= EP93XX_SYSCON_SYSCFG_REV_SHIFT;
+ return val;
+}
+
+static const char __init *ep93xx_get_soc_rev(unsigned int rev)
+{
+ switch (rev) {
+ case EP93XX_CHIP_REV_D0:
+ return "D0";
+ case EP93XX_CHIP_REV_D1:
+ return "D1";
+ case EP93XX_CHIP_REV_E0:
+ return "E0";
+ case EP93XX_CHIP_REV_E1:
+ return "E1";
+ case EP93XX_CHIP_REV_E2:
+ return "E2";
+ default:
+ return "unknown";
+ }
+}
+
+static const char *pinctrl_names[] __initconst = {
+ "pinctrl-ep9301", /* EP93XX_9301_SOC */
+ "pinctrl-ep9307", /* EP93XX_9307_SOC */
+ "pinctrl-ep9312", /* EP93XX_9312_SOC */
+};
+
+static int __init ep93xx_syscon_probe(struct platform_device *pdev)
+{
+ enum ep93xx_soc_model model;
+ struct ep93xx_map_info *map_info;
+ struct soc_device_attribute *attrs;
+ struct soc_device *soc_dev;
+ struct device *dev = &pdev->dev;
+ struct regmap *map;
+ void __iomem *base;
+ unsigned int rev;
+ int ret;
+
+ model = (enum ep93xx_soc_model)(uintptr_t)device_get_match_data(dev);
+
+ map = device_node_to_regmap(dev->of_node);
+ if (IS_ERR(map))
+ return PTR_ERR(map);
+
+ base = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(base))
+ return PTR_ERR(base);
+
+ attrs = devm_kzalloc(dev, sizeof(*attrs), GFP_KERNEL);
+ if (!attrs)
+ return -ENOMEM;
+
+ rev = ep93xx_soc_revision(map);
+
+ attrs->machine = of_flat_dt_get_machine_name();
+ attrs->family = "Cirrus Logic EP93xx";
+ attrs->revision = ep93xx_get_soc_rev(rev);
+
+ soc_dev = soc_device_register(attrs);
+ if (IS_ERR(soc_dev))
+ return PTR_ERR(soc_dev);
+
+ map_info = devm_kzalloc(dev, sizeof(*map_info), GFP_KERNEL);
+ if (!map_info)
+ return -ENOMEM;
+
+ spin_lock_init(&map_info->lock);
+ map_info->map = map;
+ map_info->base = base;
+
+ ret = ep93xx_controller_register(dev, pinctrl_names[model], map_info);
+ if (ret)
+ dev_err(dev, "registering pinctrl controller failed\n");
+
+ /*
+ * EP93xx SSP clock rate was doubled in version E2. For more information
+ * see section 6 "2x SSP (Synchronous Serial Port) Clock – Revision E2 only":
+ * http://www.cirrus.com/en/pubs/appNote/AN273REV4.pdf
+ */
+ if (rev == EP93XX_CHIP_REV_E2)
+ ret = ep93xx_controller_register(dev, "clk-ep93xx.e2", map_info);
+ else
+ ret = ep93xx_controller_register(dev, "clk-ep93xx", map_info);
+ if (ret)
+ dev_err(dev, "registering clock controller failed\n");
+
+ ret = ep93xx_controller_register(dev, "reset-ep93xx", map_info);
+ if (ret)
+ dev_err(dev, "registering reset controller failed\n");
+
+ return 0;
+}
+
+static const struct of_device_id ep9301_syscon_of_device_ids[] = {
+ { .compatible = "cirrus,ep9301-syscon", .data = (void *)EP93XX_9301_SOC },
+ { .compatible = "cirrus,ep9302-syscon", .data = (void *)EP93XX_9301_SOC },
+ { .compatible = "cirrus,ep9307-syscon", .data = (void *)EP93XX_9307_SOC },
+ { .compatible = "cirrus,ep9312-syscon", .data = (void *)EP93XX_9312_SOC },
+ { .compatible = "cirrus,ep9315-syscon", .data = (void *)EP93XX_9312_SOC },
+ { /* sentinel */ }
+};
+
+static struct platform_driver ep9301_syscon_driver = {
+ .driver = {
+ .name = "ep9301-syscon",
+ .of_match_table = ep9301_syscon_of_device_ids,
+ },
+};
+builtin_platform_driver_probe(ep9301_syscon_driver, ep93xx_syscon_probe);
diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c
index 7e9074519ad2..4dc8aba33d9b 100644
--- a/drivers/soc/fsl/qbman/qman.c
+++ b/drivers/soc/fsl/qbman/qman.c
@@ -2546,11 +2546,6 @@ release_lock:
}
EXPORT_SYMBOL(qman_delete_cgr);
-struct cgr_comp {
- struct qman_cgr *cgr;
- struct completion completion;
-};
-
static void qman_delete_cgr_smp_call(void *p)
{
qman_delete_cgr((struct qman_cgr *)p);
diff --git a/drivers/soc/fsl/qbman/qman_ccsr.c b/drivers/soc/fsl/qbman/qman_ccsr.c
index 392e54f14dbe..aa5348f4902f 100644
--- a/drivers/soc/fsl/qbman/qman_ccsr.c
+++ b/drivers/soc/fsl/qbman/qman_ccsr.c
@@ -791,8 +791,6 @@ static int fsl_qman_probe(struct platform_device *pdev)
* FQD memory MUST be zero'd by software
*/
zero_priv_mem(fqd_a, fqd_sz);
-#else
- WARN(1, "Unexpected architecture using non shared-dma-mem reservations");
#endif
dev_dbg(dev, "Allocated FQD 0x%llx 0x%zx\n", fqd_a, fqd_sz);
diff --git a/drivers/soc/fsl/qbman/qman_portal.c b/drivers/soc/fsl/qbman/qman_portal.c
index e23b60618c1a..456ef5d5c199 100644
--- a/drivers/soc/fsl/qbman/qman_portal.c
+++ b/drivers/soc/fsl/qbman/qman_portal.c
@@ -48,9 +48,10 @@ static void portal_set_cpu(struct qm_portal_config *pcfg, int cpu)
struct device *dev = pcfg->dev;
int ret;
- pcfg->iommu_domain = iommu_domain_alloc(&platform_bus_type);
- if (!pcfg->iommu_domain) {
+ pcfg->iommu_domain = iommu_paging_domain_alloc(dev);
+ if (IS_ERR(pcfg->iommu_domain)) {
dev_err(dev, "%s(): iommu_domain_alloc() failed", __func__);
+ pcfg->iommu_domain = NULL;
goto no_iommu;
}
ret = fsl_pamu_configure_l1_stash(pcfg->iommu_domain, cpu);
diff --git a/drivers/soc/fsl/qe/Kconfig b/drivers/soc/fsl/qe/Kconfig
index fa9ffbed0e92..eb03f42ab978 100644
--- a/drivers/soc/fsl/qe/Kconfig
+++ b/drivers/soc/fsl/qe/Kconfig
@@ -17,7 +17,7 @@ config QUICC_ENGINE
config UCC_SLOW
bool
- default y if SERIAL_QE
+ default y if SERIAL_QE || (CPM_QMC && QUICC_ENGINE)
help
This option provides qe_lib support to UCC slow
protocols: UART, BISYNC, QMC
@@ -31,26 +31,27 @@ config UCC_FAST
config UCC
bool
- default y if UCC_FAST || UCC_SLOW
+ default y if UCC_FAST || UCC_SLOW || (CPM_TSA && QUICC_ENGINE)
config CPM_TSA
- tristate "CPM TSA support"
+ tristate "CPM/QE TSA support"
depends on OF && HAS_IOMEM
- depends on CPM1 || (CPM && COMPILE_TEST)
+ depends on CPM1 || QUICC_ENGINE || \
+ ((CPM || QUICC_ENGINE) && COMPILE_TEST)
help
- Freescale CPM Time Slot Assigner (TSA)
+ Freescale CPM/QE Time Slot Assigner (TSA)
controller.
This option enables support for this
controller
config CPM_QMC
- tristate "CPM QMC support"
+ tristate "CPM/QE QMC support"
depends on OF && HAS_IOMEM
- depends on CPM1 || (FSL_SOC && CPM && COMPILE_TEST)
+ depends on FSL_SOC
depends on CPM_TSA
help
- Freescale CPM QUICC Multichannel Controller
+ Freescale CPM/QE QUICC Multichannel Controller
(QMC)
This option enables support for this
diff --git a/drivers/soc/fsl/qe/qe_common.c b/drivers/soc/fsl/qe/qe_common.c
index a877347d37d3..02c29f5f86d3 100644
--- a/drivers/soc/fsl/qe/qe_common.c
+++ b/drivers/soc/fsl/qe/qe_common.c
@@ -13,6 +13,7 @@
* 2006 (c) MontaVista Software, Inc.
* Vitaly Bordug <vbordug@ru.mvista.com>
*/
+#include <linux/device.h>
#include <linux/genalloc.h>
#include <linux/init.h>
#include <linux/list.h>
@@ -187,6 +188,49 @@ void cpm_muram_free(s32 offset)
}
EXPORT_SYMBOL(cpm_muram_free);
+static void devm_cpm_muram_release(struct device *dev, void *res)
+{
+ s32 *info = res;
+
+ cpm_muram_free(*info);
+}
+
+/**
+ * devm_cpm_muram_alloc - Resource-managed cpm_muram_alloc
+ * @dev: Device to allocate memory for
+ * @size: number of bytes to allocate
+ * @align: requested alignment, in bytes
+ *
+ * This function returns a non-negative offset into the muram area, or
+ * a negative errno on failure as cpm_muram_alloc() does.
+ * Use cpm_muram_addr() to get the virtual address of the area.
+ *
+ * Compare against cpm_muram_alloc(), the memory allocated by this
+ * resource-managed version is automatically freed on driver detach and so,
+ * cpm_muram_free() must not be called to release the allocated memory.
+ */
+s32 devm_cpm_muram_alloc(struct device *dev, unsigned long size,
+ unsigned long align)
+{
+ s32 info;
+ s32 *dr;
+
+ dr = devres_alloc(devm_cpm_muram_release, sizeof(*dr), GFP_KERNEL);
+ if (!dr)
+ return -ENOMEM;
+
+ info = cpm_muram_alloc(size, align);
+ if (info >= 0) {
+ *dr = info;
+ devres_add(dev, dr);
+ } else {
+ devres_free(dr);
+ }
+
+ return info;
+}
+EXPORT_SYMBOL(devm_cpm_muram_alloc);
+
/*
* cpm_muram_alloc_fixed - reserve a specific region of multi-user ram
* @offset: offset of allocation start address
@@ -212,6 +256,42 @@ s32 cpm_muram_alloc_fixed(unsigned long offset, unsigned long size)
EXPORT_SYMBOL(cpm_muram_alloc_fixed);
/**
+ * devm_cpm_muram_alloc_fixed - Resource-managed cpm_muram_alloc_fixed
+ * @dev: Device to allocate memory for
+ * @offset: offset of allocation start address
+ * @size: number of bytes to allocate
+ *
+ * This function returns a non-negative offset into the muram area, or
+ * a negative errno on failure as cpm_muram_alloc_fixed() does.
+ * Use cpm_muram_addr() to get the virtual address of the area.
+ *
+ * Compare against cpm_muram_alloc_fixed(), the memory allocated by this
+ * resource-managed version is automatically freed on driver detach and so,
+ * cpm_muram_free() must not be called to release the allocated memory.
+ */
+s32 devm_cpm_muram_alloc_fixed(struct device *dev, unsigned long offset,
+ unsigned long size)
+{
+ s32 info;
+ s32 *dr;
+
+ dr = devres_alloc(devm_cpm_muram_release, sizeof(*dr), GFP_KERNEL);
+ if (!dr)
+ return -ENOMEM;
+
+ info = cpm_muram_alloc_fixed(offset, size);
+ if (info >= 0) {
+ *dr = info;
+ devres_add(dev, dr);
+ } else {
+ devres_free(dr);
+ }
+
+ return info;
+}
+EXPORT_SYMBOL(devm_cpm_muram_alloc_fixed);
+
+/**
* cpm_muram_addr - turn a muram offset into a virtual address
* @offset: muram offset to convert
*/
diff --git a/drivers/soc/fsl/qe/qmc.c b/drivers/soc/fsl/qe/qmc.c
index 76bb496305a0..3dffebb48b0d 100644
--- a/drivers/soc/fsl/qe/qmc.c
+++ b/drivers/soc/fsl/qe/qmc.c
@@ -8,7 +8,9 @@
*/
#include <soc/fsl/qe/qmc.h>
+#include <linux/bitfield.h>
#include <linux/dma-mapping.h>
+#include <linux/firmware.h>
#include <linux/hdlc.h>
#include <linux/interrupt.h>
#include <linux/io.h>
@@ -18,31 +20,41 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <soc/fsl/cpm.h>
+#include <soc/fsl/qe/ucc_slow.h>
+#include <soc/fsl/qe/qe.h>
#include <sysdev/fsl_soc.h>
#include "tsa.h"
-/* SCC general mode register high (32 bits) */
+/* SCC general mode register low (32 bits) (GUMR_L in QE) */
#define SCC_GSMRL 0x00
-#define SCC_GSMRL_ENR (1 << 5)
-#define SCC_GSMRL_ENT (1 << 4)
-#define SCC_GSMRL_MODE_QMC (0x0A << 0)
+#define SCC_GSMRL_ENR BIT(5)
+#define SCC_GSMRL_ENT BIT(4)
+#define SCC_GSMRL_MODE_MASK GENMASK(3, 0)
+#define SCC_CPM1_GSMRL_MODE_QMC FIELD_PREP_CONST(SCC_GSMRL_MODE_MASK, 0x0A)
+#define SCC_QE_GSMRL_MODE_QMC FIELD_PREP_CONST(SCC_GSMRL_MODE_MASK, 0x02)
-/* SCC general mode register low (32 bits) */
+/* SCC general mode register high (32 bits) (identical to GUMR_H in QE) */
#define SCC_GSMRH 0x04
-#define SCC_GSMRH_CTSS (1 << 7)
-#define SCC_GSMRH_CDS (1 << 8)
-#define SCC_GSMRH_CTSP (1 << 9)
-#define SCC_GSMRH_CDP (1 << 10)
-
-/* SCC event register (16 bits) */
+#define SCC_GSMRH_CTSS BIT(7)
+#define SCC_GSMRH_CDS BIT(8)
+#define SCC_GSMRH_CTSP BIT(9)
+#define SCC_GSMRH_CDP BIT(10)
+#define SCC_GSMRH_TTX BIT(11)
+#define SCC_GSMRH_TRX BIT(12)
+
+/* SCC event register (16 bits) (identical to UCCE in QE) */
#define SCC_SCCE 0x10
-#define SCC_SCCE_IQOV (1 << 3)
-#define SCC_SCCE_GINT (1 << 2)
-#define SCC_SCCE_GUN (1 << 1)
-#define SCC_SCCE_GOV (1 << 0)
+#define SCC_SCCE_IQOV BIT(3)
+#define SCC_SCCE_GINT BIT(2)
+#define SCC_SCCE_GUN BIT(1)
+#define SCC_SCCE_GOV BIT(0)
/* SCC mask register (16 bits) */
#define SCC_SCCM 0x14
+
+/* UCC Extended Mode Register (8 bits, QE only) */
+#define SCC_QE_UCC_GUEMR 0x90
+
/* Multichannel base pointer (32 bits) */
#define QMC_GBL_MCBASE 0x00
/* Multichannel controller state (16 bits) */
@@ -73,27 +85,42 @@
#define QMC_GBL_TSATTX 0x60
/* CRC constant (16 bits) */
#define QMC_GBL_C_MASK16 0xA0
+/* Rx framer base pointer (16 bits, QE only) */
+#define QMC_QE_GBL_RX_FRM_BASE 0xAC
+/* Tx framer base pointer (16 bits, QE only) */
+#define QMC_QE_GBL_TX_FRM_BASE 0xAE
+/* A reserved area (0xB0 -> 0xC3) that must be initialized to 0 (QE only) */
+#define QMC_QE_GBL_RSV_B0_START 0xB0
+#define QMC_QE_GBL_RSV_B0_SIZE 0x14
+/* QMC Global Channel specific base (32 bits, QE only) */
+#define QMC_QE_GBL_GCSBASE 0xC4
/* TSA entry (16bit entry in TSATRX and TSATTX) */
-#define QMC_TSA_VALID (1 << 15)
-#define QMC_TSA_WRAP (1 << 14)
-#define QMC_TSA_MASK (0x303F)
-#define QMC_TSA_CHANNEL(x) ((x) << 6)
+#define QMC_TSA_VALID BIT(15)
+#define QMC_TSA_WRAP BIT(14)
+#define QMC_TSA_MASK_MASKH GENMASK(13, 12)
+#define QMC_TSA_MASK_MASKL GENMASK(5, 0)
+#define QMC_TSA_MASK_8BIT (FIELD_PREP_CONST(QMC_TSA_MASK_MASKH, 0x3) | \
+ FIELD_PREP_CONST(QMC_TSA_MASK_MASKL, 0x3F))
+#define QMC_TSA_CHANNEL_MASK GENMASK(11, 6)
+#define QMC_TSA_CHANNEL(x) FIELD_PREP(QMC_TSA_CHANNEL_MASK, x)
/* Tx buffer descriptor base address (16 bits, offset from MCBASE) */
#define QMC_SPE_TBASE 0x00
/* Channel mode register (16 bits) */
#define QMC_SPE_CHAMR 0x02
-#define QMC_SPE_CHAMR_MODE_HDLC (1 << 15)
-#define QMC_SPE_CHAMR_MODE_TRANSP ((0 << 15) | (1 << 13))
-#define QMC_SPE_CHAMR_ENT (1 << 12)
-#define QMC_SPE_CHAMR_POL (1 << 8)
-#define QMC_SPE_CHAMR_HDLC_IDLM (1 << 13)
-#define QMC_SPE_CHAMR_HDLC_CRC (1 << 7)
-#define QMC_SPE_CHAMR_HDLC_NOF (0x0f << 0)
-#define QMC_SPE_CHAMR_TRANSP_RD (1 << 14)
-#define QMC_SPE_CHAMR_TRANSP_SYNC (1 << 10)
+#define QMC_SPE_CHAMR_MODE_MASK GENMASK(15, 15)
+#define QMC_SPE_CHAMR_MODE_HDLC FIELD_PREP_CONST(QMC_SPE_CHAMR_MODE_MASK, 1)
+#define QMC_SPE_CHAMR_MODE_TRANSP (FIELD_PREP_CONST(QMC_SPE_CHAMR_MODE_MASK, 0) | BIT(13))
+#define QMC_SPE_CHAMR_ENT BIT(12)
+#define QMC_SPE_CHAMR_POL BIT(8)
+#define QMC_SPE_CHAMR_HDLC_IDLM BIT(13)
+#define QMC_SPE_CHAMR_HDLC_CRC BIT(7)
+#define QMC_SPE_CHAMR_HDLC_NOF_MASK GENMASK(3, 0)
+#define QMC_SPE_CHAMR_HDLC_NOF(x) FIELD_PREP(QMC_SPE_CHAMR_HDLC_NOF_MASK, x)
+#define QMC_SPE_CHAMR_TRANSP_RD BIT(14)
+#define QMC_SPE_CHAMR_TRANSP_SYNC BIT(10)
/* Tx internal state (32 bits) */
#define QMC_SPE_TSTATE 0x04
@@ -120,43 +147,47 @@
/* Transparent synchronization (16 bits) */
#define QMC_SPE_TRNSYNC 0x3C
-#define QMC_SPE_TRNSYNC_RX(x) ((x) << 8)
-#define QMC_SPE_TRNSYNC_TX(x) ((x) << 0)
+#define QMC_SPE_TRNSYNC_RX_MASK GENMASK(15, 8)
+#define QMC_SPE_TRNSYNC_RX(x) FIELD_PREP(QMC_SPE_TRNSYNC_RX_MASK, x)
+#define QMC_SPE_TRNSYNC_TX_MASK GENMASK(7, 0)
+#define QMC_SPE_TRNSYNC_TX(x) FIELD_PREP(QMC_SPE_TRNSYNC_TX_MASK, x)
/* Interrupt related registers bits */
-#define QMC_INT_V (1 << 15)
-#define QMC_INT_W (1 << 14)
-#define QMC_INT_NID (1 << 13)
-#define QMC_INT_IDL (1 << 12)
-#define QMC_INT_GET_CHANNEL(x) (((x) & 0x0FC0) >> 6)
-#define QMC_INT_MRF (1 << 5)
-#define QMC_INT_UN (1 << 4)
-#define QMC_INT_RXF (1 << 3)
-#define QMC_INT_BSY (1 << 2)
-#define QMC_INT_TXB (1 << 1)
-#define QMC_INT_RXB (1 << 0)
+#define QMC_INT_V BIT(15)
+#define QMC_INT_W BIT(14)
+#define QMC_INT_NID BIT(13)
+#define QMC_INT_IDL BIT(12)
+#define QMC_INT_CHANNEL_MASK GENMASK(11, 6)
+#define QMC_INT_GET_CHANNEL(x) FIELD_GET(QMC_INT_CHANNEL_MASK, x)
+#define QMC_INT_MRF BIT(5)
+#define QMC_INT_UN BIT(4)
+#define QMC_INT_RXF BIT(3)
+#define QMC_INT_BSY BIT(2)
+#define QMC_INT_TXB BIT(1)
+#define QMC_INT_RXB BIT(0)
/* BD related registers bits */
-#define QMC_BD_RX_E (1 << 15)
-#define QMC_BD_RX_W (1 << 13)
-#define QMC_BD_RX_I (1 << 12)
-#define QMC_BD_RX_L (1 << 11)
-#define QMC_BD_RX_F (1 << 10)
-#define QMC_BD_RX_CM (1 << 9)
-#define QMC_BD_RX_UB (1 << 7)
-#define QMC_BD_RX_LG (1 << 5)
-#define QMC_BD_RX_NO (1 << 4)
-#define QMC_BD_RX_AB (1 << 3)
-#define QMC_BD_RX_CR (1 << 2)
-
-#define QMC_BD_TX_R (1 << 15)
-#define QMC_BD_TX_W (1 << 13)
-#define QMC_BD_TX_I (1 << 12)
-#define QMC_BD_TX_L (1 << 11)
-#define QMC_BD_TX_TC (1 << 10)
-#define QMC_BD_TX_CM (1 << 9)
-#define QMC_BD_TX_UB (1 << 7)
-#define QMC_BD_TX_PAD (0x0f << 0)
+#define QMC_BD_RX_E BIT(15)
+#define QMC_BD_RX_W BIT(13)
+#define QMC_BD_RX_I BIT(12)
+#define QMC_BD_RX_L BIT(11)
+#define QMC_BD_RX_F BIT(10)
+#define QMC_BD_RX_CM BIT(9)
+#define QMC_BD_RX_UB BIT(7)
+#define QMC_BD_RX_LG BIT(5)
+#define QMC_BD_RX_NO BIT(4)
+#define QMC_BD_RX_AB BIT(3)
+#define QMC_BD_RX_CR BIT(2)
+
+#define QMC_BD_TX_R BIT(15)
+#define QMC_BD_TX_W BIT(13)
+#define QMC_BD_TX_I BIT(12)
+#define QMC_BD_TX_L BIT(11)
+#define QMC_BD_TX_TC BIT(10)
+#define QMC_BD_TX_CM BIT(9)
+#define QMC_BD_TX_UB BIT(7)
+#define QMC_BD_TX_PAD_MASK GENMASK(3, 0)
+#define QMC_BD_TX_PAD(x) FIELD_PREP(QMC_BD_TX_PAD_MASK, x)
/* Numbers of BDs and interrupt items */
#define QMC_NB_TXBDS 8
@@ -184,7 +215,7 @@ struct qmc_chan {
u64 rx_ts_mask;
bool is_reverse_data;
- spinlock_t tx_lock;
+ spinlock_t tx_lock; /* Protect Tx related data */
cbd_t __iomem *txbds;
cbd_t __iomem *txbd_free;
cbd_t __iomem *txbd_done;
@@ -192,7 +223,7 @@ struct qmc_chan {
u64 nb_tx_underrun;
bool is_tx_stopped;
- spinlock_t rx_lock;
+ spinlock_t rx_lock; /* Protect Rx related data */
cbd_t __iomem *rxbds;
cbd_t __iomem *rxbd_free;
cbd_t __iomem *rxbd_done;
@@ -203,13 +234,31 @@ struct qmc_chan {
bool is_rx_stopped;
};
+enum qmc_version {
+ QMC_CPM1,
+ QMC_QE,
+};
+
+struct qmc_data {
+ enum qmc_version version;
+ u32 tstate; /* Initial TSTATE value */
+ u32 rstate; /* Initial RSTATE value */
+ u32 zistate; /* Initial ZISTATE value */
+ u32 zdstate_hdlc; /* Initial ZDSTATE value (HDLC mode) */
+ u32 zdstate_transp; /* Initial ZDSTATE value (Transparent mode) */
+ u32 rpack; /* Initial RPACK value */
+};
+
struct qmc {
struct device *dev;
+ const struct qmc_data *data;
struct tsa_serial *tsa_serial;
void __iomem *scc_regs;
void __iomem *scc_pram;
void __iomem *dpram;
u16 scc_pram_offset;
+ u32 dpram_offset;
+ u32 qe_subblock;
cbd_t __iomem *bd_table;
dma_addr_t bd_dma_addr;
size_t bd_size;
@@ -222,6 +271,11 @@ struct qmc {
struct qmc_chan *chans[64];
};
+static void qmc_write8(void __iomem *addr, u8 val)
+{
+ iowrite8(val, addr);
+}
+
static void qmc_write16(void __iomem *addr, u16 val)
{
iowrite16be(val, addr);
@@ -262,6 +316,13 @@ static void qmc_setbits32(void __iomem *addr, u32 set)
qmc_write32(addr, qmc_read32(addr) | set);
}
+static bool qmc_is_qe(const struct qmc *qmc)
+{
+ if (IS_ENABLED(CONFIG_QUICC_ENGINE) && IS_ENABLED(CONFIG_CPM))
+ return qmc->data->version == QMC_QE;
+
+ return IS_ENABLED(CONFIG_QUICC_ENGINE);
+}
int qmc_chan_get_info(struct qmc_chan *chan, struct qmc_chan_info *info)
{
@@ -348,8 +409,8 @@ int qmc_chan_set_param(struct qmc_chan *chan, const struct qmc_chan_param *param
switch (param->mode) {
case QMC_HDLC:
- if ((param->hdlc.max_rx_buf_size % 4) ||
- (param->hdlc.max_rx_buf_size < 8))
+ if (param->hdlc.max_rx_buf_size % 4 ||
+ param->hdlc.max_rx_buf_size < 8)
return -EINVAL;
qmc_write16(chan->qmc->scc_pram + QMC_GBL_MRBLR,
@@ -532,11 +593,12 @@ int qmc_chan_read_submit(struct qmc_chan *chan, dma_addr_t addr, size_t length,
/* Restart receiver if needed */
if (chan->is_rx_halted && !chan->is_rx_stopped) {
/* Restart receiver */
- if (chan->mode == QMC_TRANSPARENT)
- qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080);
- else
- qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x00000080);
- qmc_write32(chan->s_param + QMC_SPE_RSTATE, 0x31000000);
+ qmc_write32(chan->s_param + QMC_SPE_RPACK, chan->qmc->data->rpack);
+ qmc_write32(chan->s_param + QMC_SPE_ZDSTATE,
+ chan->mode == QMC_TRANSPARENT ?
+ chan->qmc->data->zdstate_transp :
+ chan->qmc->data->zdstate_hdlc);
+ qmc_write32(chan->s_param + QMC_SPE_RSTATE, chan->qmc->data->rstate);
chan->is_rx_halted = false;
}
chan->rx_pending++;
@@ -641,7 +703,7 @@ static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan *chan, const struct tsa_ser
return -EINVAL;
}
- val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id);
+ val = QMC_TSA_VALID | QMC_TSA_MASK_8BIT | QMC_TSA_CHANNEL(chan->id);
/* Check entries based on Rx stuff*/
for (i = 0; i < info->nb_rx_ts; i++) {
@@ -662,7 +724,7 @@ static int qmc_chan_setup_tsa_64rxtx(struct qmc_chan *chan, const struct tsa_ser
continue;
qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2),
- ~QMC_TSA_WRAP, enable ? val : 0x0000);
+ (u16)~QMC_TSA_WRAP, enable ? val : 0x0000);
}
return 0;
@@ -677,7 +739,7 @@ static int qmc_chan_setup_tsa_32rx(struct qmc_chan *chan, const struct tsa_seria
/* Use a Rx 32 entries table */
- val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id);
+ val = QMC_TSA_VALID | QMC_TSA_MASK_8BIT | QMC_TSA_CHANNEL(chan->id);
/* Check entries based on Rx stuff */
for (i = 0; i < info->nb_rx_ts; i++) {
@@ -698,7 +760,7 @@ static int qmc_chan_setup_tsa_32rx(struct qmc_chan *chan, const struct tsa_seria
continue;
qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATRX + (i * 2),
- ~QMC_TSA_WRAP, enable ? val : 0x0000);
+ (u16)~QMC_TSA_WRAP, enable ? val : 0x0000);
}
return 0;
@@ -713,7 +775,7 @@ static int qmc_chan_setup_tsa_32tx(struct qmc_chan *chan, const struct tsa_seria
/* Use a Tx 32 entries table */
- val = QMC_TSA_VALID | QMC_TSA_MASK | QMC_TSA_CHANNEL(chan->id);
+ val = QMC_TSA_VALID | QMC_TSA_MASK_8BIT | QMC_TSA_CHANNEL(chan->id);
/* Check entries based on Tx stuff */
for (i = 0; i < info->nb_tx_ts; i++) {
@@ -734,7 +796,7 @@ static int qmc_chan_setup_tsa_32tx(struct qmc_chan *chan, const struct tsa_seria
continue;
qmc_clrsetbits16(chan->qmc->scc_pram + QMC_GBL_TSATTX + (i * 2),
- ~QMC_TSA_WRAP, enable ? val : 0x0000);
+ (u16)~QMC_TSA_WRAP, enable ? val : 0x0000);
}
return 0;
@@ -774,11 +836,18 @@ static int qmc_chan_setup_tsa_rx(struct qmc_chan *chan, bool enable)
return qmc_chan_setup_tsa_32rx(chan, &info, enable);
}
-static int qmc_chan_command(struct qmc_chan *chan, u8 qmc_opcode)
+static int qmc_chan_cpm1_command(struct qmc_chan *chan, u8 qmc_opcode)
{
return cpm_command(chan->id << 2, (qmc_opcode << 4) | 0x0E);
}
+static int qmc_chan_qe_command(struct qmc_chan *chan, u32 cmd)
+{
+ if (!qe_issue_cmd(cmd, chan->qmc->qe_subblock, chan->id, 0))
+ return -EIO;
+ return 0;
+}
+
static int qmc_chan_stop_rx(struct qmc_chan *chan)
{
unsigned long flags;
@@ -793,7 +862,9 @@ static int qmc_chan_stop_rx(struct qmc_chan *chan)
}
/* Send STOP RECEIVE command */
- ret = qmc_chan_command(chan, 0x0);
+ ret = qmc_is_qe(chan->qmc) ?
+ qmc_chan_qe_command(chan, QE_QMC_STOP_RX) :
+ qmc_chan_cpm1_command(chan, 0x0);
if (ret) {
dev_err(chan->qmc->dev, "chan %u: Send STOP RECEIVE failed (%d)\n",
chan->id, ret);
@@ -830,7 +901,9 @@ static int qmc_chan_stop_tx(struct qmc_chan *chan)
}
/* Send STOP TRANSMIT command */
- ret = qmc_chan_command(chan, 0x1);
+ ret = qmc_is_qe(chan->qmc) ?
+ qmc_chan_qe_command(chan, QE_QMC_STOP_TX) :
+ qmc_chan_cpm1_command(chan, 0x1);
if (ret) {
dev_err(chan->qmc->dev, "chan %u: Send STOP TRANSMIT failed (%d)\n",
chan->id, ret);
@@ -889,6 +962,7 @@ EXPORT_SYMBOL(qmc_chan_stop);
static int qmc_setup_chan_trnsync(struct qmc *qmc, struct qmc_chan *chan)
{
struct tsa_serial_info info;
+ unsigned int w_rx, w_tx;
u16 first_rx, last_tx;
u16 trnsync;
int ret;
@@ -898,6 +972,14 @@ static int qmc_setup_chan_trnsync(struct qmc *qmc, struct qmc_chan *chan)
if (ret)
return ret;
+ w_rx = hweight64(chan->rx_ts_mask);
+ w_tx = hweight64(chan->tx_ts_mask);
+ if (w_rx <= 1 && w_tx <= 1) {
+ dev_dbg(qmc->dev, "only one or zero ts -> disable trnsync\n");
+ qmc_clrbits16(chan->s_param + QMC_SPE_CHAMR, QMC_SPE_CHAMR_TRANSP_SYNC);
+ return 0;
+ }
+
/* Find the first Rx TS allocated to the channel */
first_rx = chan->rx_ts_mask ? __ffs64(chan->rx_ts_mask) + 1 : 0;
@@ -911,6 +993,7 @@ static int qmc_setup_chan_trnsync(struct qmc *qmc, struct qmc_chan *chan)
trnsync |= QMC_SPE_TRNSYNC_TX((last_tx % info.nb_tx_ts) * 2);
qmc_write16(chan->s_param + QMC_SPE_TRNSYNC, trnsync);
+ qmc_setbits16(chan->s_param + QMC_SPE_CHAMR, QMC_SPE_CHAMR_TRANSP_SYNC);
dev_dbg(qmc->dev, "chan %u: trnsync=0x%04x, rx %u/%u 0x%llx, tx %u/%u 0x%llx\n",
chan->id, trnsync,
@@ -940,19 +1023,22 @@ static int qmc_chan_start_rx(struct qmc_chan *chan)
goto end;
}
- ret = qmc_setup_chan_trnsync(chan->qmc, chan);
- if (ret) {
- dev_err(chan->qmc->dev, "chan %u: setup TRNSYNC failed (%d)\n",
- chan->id, ret);
- goto end;
+ if (chan->mode == QMC_TRANSPARENT) {
+ ret = qmc_setup_chan_trnsync(chan->qmc, chan);
+ if (ret) {
+ dev_err(chan->qmc->dev, "chan %u: setup TRNSYNC failed (%d)\n",
+ chan->id, ret);
+ goto end;
+ }
}
/* Restart the receiver */
- if (chan->mode == QMC_TRANSPARENT)
- qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080);
- else
- qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x00000080);
- qmc_write32(chan->s_param + QMC_SPE_RSTATE, 0x31000000);
+ qmc_write32(chan->s_param + QMC_SPE_RPACK, chan->qmc->data->rpack);
+ qmc_write32(chan->s_param + QMC_SPE_ZDSTATE,
+ chan->mode == QMC_TRANSPARENT ?
+ chan->qmc->data->zdstate_transp :
+ chan->qmc->data->zdstate_hdlc);
+ qmc_write32(chan->s_param + QMC_SPE_RSTATE, chan->qmc->data->rstate);
chan->is_rx_halted = false;
chan->is_rx_stopped = false;
@@ -982,11 +1068,13 @@ static int qmc_chan_start_tx(struct qmc_chan *chan)
goto end;
}
- ret = qmc_setup_chan_trnsync(chan->qmc, chan);
- if (ret) {
- dev_err(chan->qmc->dev, "chan %u: setup TRNSYNC failed (%d)\n",
- chan->id, ret);
- goto end;
+ if (chan->mode == QMC_TRANSPARENT) {
+ ret = qmc_setup_chan_trnsync(chan->qmc, chan);
+ if (ret) {
+ dev_err(chan->qmc->dev, "chan %u: setup TRNSYNC failed (%d)\n",
+ chan->id, ret);
+ goto end;
+ }
}
/*
@@ -1096,8 +1184,8 @@ static void qmc_chan_reset_tx(struct qmc_chan *chan)
qmc_read16(chan->s_param + QMC_SPE_TBASE));
/* Reset TSTATE and ZISTATE to their initial value */
- qmc_write32(chan->s_param + QMC_SPE_TSTATE, 0x30000000);
- qmc_write32(chan->s_param + QMC_SPE_ZISTATE, 0x00000100);
+ qmc_write32(chan->s_param + QMC_SPE_TSTATE, chan->qmc->data->tstate);
+ qmc_write32(chan->s_param + QMC_SPE_ZISTATE, chan->qmc->data->zistate);
spin_unlock_irqrestore(&chan->tx_lock, flags);
}
@@ -1127,7 +1215,7 @@ static int qmc_check_chans(struct qmc *qmc)
if (ret)
return ret;
- if ((info.nb_tx_ts > 64) || (info.nb_rx_ts > 64)) {
+ if (info.nb_tx_ts > 64 || info.nb_rx_ts > 64) {
dev_err(qmc->dev, "Number of TSA Tx/Rx TS assigned not supported\n");
return -EINVAL;
}
@@ -1136,7 +1224,7 @@ static int qmc_check_chans(struct qmc *qmc)
* If more than 32 TS are assigned to this serial, one common table is
* used for Tx and Rx and so masks must be equal for all channels.
*/
- if ((info.nb_tx_ts > 32) || (info.nb_rx_ts > 32)) {
+ if (info.nb_tx_ts > 32 || info.nb_rx_ts > 32) {
if (info.nb_tx_ts != info.nb_rx_ts) {
dev_err(qmc->dev, "Number of TSA Tx/Rx TS assigned are not equal\n");
return -EINVAL;
@@ -1368,13 +1456,14 @@ static int qmc_setup_chan(struct qmc *qmc, struct qmc_chan *chan)
val = ((chan->id * (QMC_NB_TXBDS + QMC_NB_RXBDS)) + QMC_NB_TXBDS) * sizeof(cbd_t);
qmc_write16(chan->s_param + QMC_SPE_RBASE, val);
qmc_write16(chan->s_param + QMC_SPE_RBPTR, val);
- qmc_write32(chan->s_param + QMC_SPE_TSTATE, 0x30000000);
- qmc_write32(chan->s_param + QMC_SPE_RSTATE, 0x31000000);
- qmc_write32(chan->s_param + QMC_SPE_ZISTATE, 0x00000100);
+ qmc_write32(chan->s_param + QMC_SPE_TSTATE, chan->qmc->data->tstate);
+ qmc_write32(chan->s_param + QMC_SPE_RSTATE, chan->qmc->data->rstate);
+ qmc_write32(chan->s_param + QMC_SPE_ZISTATE, chan->qmc->data->zistate);
+ qmc_write32(chan->s_param + QMC_SPE_RPACK, chan->qmc->data->rpack);
if (chan->mode == QMC_TRANSPARENT) {
- qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080);
+ qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, chan->qmc->data->zdstate_transp);
qmc_write16(chan->s_param + QMC_SPE_TMRBLR, 60);
- val = QMC_SPE_CHAMR_MODE_TRANSP | QMC_SPE_CHAMR_TRANSP_SYNC;
+ val = QMC_SPE_CHAMR_MODE_TRANSP;
if (chan->is_reverse_data)
val |= QMC_SPE_CHAMR_TRANSP_RD;
qmc_write16(chan->s_param + QMC_SPE_CHAMR, val);
@@ -1382,10 +1471,10 @@ static int qmc_setup_chan(struct qmc *qmc, struct qmc_chan *chan)
if (ret)
return ret;
} else {
- qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x00000080);
+ qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, chan->qmc->data->zdstate_hdlc);
qmc_write16(chan->s_param + QMC_SPE_MFLR, 60);
qmc_write16(chan->s_param + QMC_SPE_CHAMR,
- QMC_SPE_CHAMR_MODE_HDLC | QMC_SPE_CHAMR_HDLC_IDLM);
+ QMC_SPE_CHAMR_MODE_HDLC | QMC_SPE_CHAMR_HDLC_IDLM);
}
/* Do not enable interrupts now. They will be enabled later */
@@ -1510,11 +1599,14 @@ static void qmc_irq_gint(struct qmc *qmc)
/* Restart the receiver if needed */
spin_lock_irqsave(&chan->rx_lock, flags);
if (chan->rx_pending && !chan->is_rx_stopped) {
- if (chan->mode == QMC_TRANSPARENT)
- qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x18000080);
- else
- qmc_write32(chan->s_param + QMC_SPE_ZDSTATE, 0x00000080);
- qmc_write32(chan->s_param + QMC_SPE_RSTATE, 0x31000000);
+ qmc_write32(chan->s_param + QMC_SPE_RPACK,
+ chan->qmc->data->rpack);
+ qmc_write32(chan->s_param + QMC_SPE_ZDSTATE,
+ chan->mode == QMC_TRANSPARENT ?
+ chan->qmc->data->zdstate_transp :
+ chan->qmc->data->zdstate_hdlc);
+ qmc_write32(chan->s_param + QMC_SPE_RSTATE,
+ chan->qmc->data->rstate);
chan->is_rx_halted = false;
} else {
chan->is_rx_halted = true;
@@ -1558,27 +1650,74 @@ static irqreturn_t qmc_irq_handler(int irq, void *priv)
return IRQ_HANDLED;
}
-static int qmc_probe(struct platform_device *pdev)
+static int qmc_qe_soft_qmc_init(struct qmc *qmc, struct device_node *np)
{
- struct device_node *np = pdev->dev.of_node;
- unsigned int nb_chans;
- struct resource *res;
- struct qmc *qmc;
- int irq;
+ struct qe_firmware_info *qe_fw_info;
+ const struct qe_firmware *qe_fw;
+ const struct firmware *fw;
+ const char *filename;
int ret;
- qmc = devm_kzalloc(&pdev->dev, sizeof(*qmc), GFP_KERNEL);
- if (!qmc)
- return -ENOMEM;
+ ret = of_property_read_string(np, "fsl,soft-qmc", &filename);
+ switch (ret) {
+ case 0:
+ break;
+ case -EINVAL:
+ /* fsl,soft-qmc property not set -> Simply do nothing */
+ return 0;
+ default:
+ dev_err(qmc->dev, "%pOF: failed to read fsl,soft-qmc\n",
+ np);
+ return ret;
+ }
- qmc->dev = &pdev->dev;
- INIT_LIST_HEAD(&qmc->chan_head);
+ qe_fw_info = qe_get_firmware_info();
+ if (qe_fw_info) {
+ if (!strstr(qe_fw_info->id, "Soft-QMC")) {
+ dev_err(qmc->dev, "Another Firmware is already loaded\n");
+ return -EALREADY;
+ }
+ dev_info(qmc->dev, "Firmware already loaded\n");
+ return 0;
+ }
+
+ dev_info(qmc->dev, "Using firmware %s\n", filename);
+
+ ret = request_firmware(&fw, filename, qmc->dev);
+ if (ret) {
+ dev_err(qmc->dev, "Failed to request firmware %s\n", filename);
+ return ret;
+ }
+
+ qe_fw = (const struct qe_firmware *)fw->data;
+
+ if (fw->size < sizeof(qe_fw->header) ||
+ be32_to_cpu(qe_fw->header.length) != fw->size) {
+ dev_err(qmc->dev, "Invalid firmware %s\n", filename);
+ ret = -EINVAL;
+ goto end;
+ }
+
+ ret = qe_upload_firmware(qe_fw);
+ if (ret) {
+ dev_err(qmc->dev, "Failed to load firmware %s\n", filename);
+ goto end;
+ }
+
+ ret = 0;
+end:
+ release_firmware(fw);
+ return ret;
+}
+
+static int qmc_cpm1_init_resources(struct qmc *qmc, struct platform_device *pdev)
+{
+ struct resource *res;
qmc->scc_regs = devm_platform_ioremap_resource_byname(pdev, "scc_regs");
if (IS_ERR(qmc->scc_regs))
return PTR_ERR(qmc->scc_regs);
-
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "scc_pram");
if (!res)
return -EINVAL;
@@ -1591,44 +1730,215 @@ static int qmc_probe(struct platform_device *pdev)
if (IS_ERR(qmc->dpram))
return PTR_ERR(qmc->dpram);
+ return 0;
+}
+
+static int qmc_qe_init_resources(struct qmc *qmc, struct platform_device *pdev)
+{
+ struct resource *res;
+ int ucc_num;
+ s32 info;
+
+ qmc->scc_regs = devm_platform_ioremap_resource_byname(pdev, "ucc_regs");
+ if (IS_ERR(qmc->scc_regs))
+ return PTR_ERR(qmc->scc_regs);
+
+ ucc_num = tsa_serial_get_num(qmc->tsa_serial);
+ if (ucc_num < 0)
+ return dev_err_probe(qmc->dev, ucc_num, "Failed to get UCC num\n");
+
+ qmc->qe_subblock = ucc_slow_get_qe_cr_subblock(ucc_num);
+ if (qmc->qe_subblock == QE_CR_SUBBLOCK_INVALID) {
+ dev_err(qmc->dev, "Unsupported ucc num %u\n", ucc_num);
+ return -EINVAL;
+ }
+ /* Allocate the 'Global Multichannel Parameters' and the
+ * 'Framer parameters' areas. The 'Framer parameters' area
+ * is located right after the 'Global Multichannel Parameters'.
+ * The 'Framer parameters' need 1 byte per receive and transmit
+ * channel. The maximum number of receive or transmit channel
+ * is 64. So reserve 2 * 64 bytes for the 'Framer parameters'.
+ */
+ info = devm_qe_muram_alloc(qmc->dev, UCC_SLOW_PRAM_SIZE + 2 * 64,
+ ALIGNMENT_OF_UCC_SLOW_PRAM);
+ if (IS_ERR_VALUE(info)) {
+ dev_err(qmc->dev, "cannot allocate MURAM for PRAM");
+ return -ENOMEM;
+ }
+ if (!qe_issue_cmd(QE_ASSIGN_PAGE_TO_DEVICE, qmc->qe_subblock,
+ QE_CR_PROTOCOL_UNSPECIFIED, info)) {
+ dev_err(qmc->dev, "QE_ASSIGN_PAGE_TO_DEVICE cmd failed");
+ return -EIO;
+ }
+ qmc->scc_pram = qe_muram_addr(info);
+ qmc->scc_pram_offset = info;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dpram");
+ if (!res)
+ return -EINVAL;
+ qmc->dpram_offset = res->start - qe_muram_dma(qe_muram_addr(0));
+ qmc->dpram = devm_ioremap_resource(qmc->dev, res);
+ if (IS_ERR(qmc->scc_pram))
+ return PTR_ERR(qmc->scc_pram);
+
+ return 0;
+}
+
+static int qmc_init_resources(struct qmc *qmc, struct platform_device *pdev)
+{
+ return qmc_is_qe(qmc) ?
+ qmc_qe_init_resources(qmc, pdev) :
+ qmc_cpm1_init_resources(qmc, pdev);
+}
+
+static int qmc_cpm1_init_scc(struct qmc *qmc)
+{
+ u32 val;
+ int ret;
+
+ /* Connect the serial (SCC) to TSA */
+ ret = tsa_serial_connect(qmc->tsa_serial);
+ if (ret)
+ return dev_err_probe(qmc->dev, ret, "Failed to connect TSA serial\n");
+
+ /* Init GMSR_H and GMSR_L registers */
+ val = SCC_GSMRH_CDS | SCC_GSMRH_CTSS | SCC_GSMRH_CDP | SCC_GSMRH_CTSP;
+ qmc_write32(qmc->scc_regs + SCC_GSMRH, val);
+
+ /* enable QMC mode */
+ qmc_write32(qmc->scc_regs + SCC_GSMRL, SCC_CPM1_GSMRL_MODE_QMC);
+
+ /* Disable and clear interrupts */
+ qmc_write16(qmc->scc_regs + SCC_SCCM, 0x0000);
+ qmc_write16(qmc->scc_regs + SCC_SCCE, 0x000F);
+
+ return 0;
+}
+
+static int qmc_qe_init_ucc(struct qmc *qmc)
+{
+ u32 val;
+ int ret;
+
+ /* Set the UCC in slow mode */
+ qmc_write8(qmc->scc_regs + SCC_QE_UCC_GUEMR,
+ UCC_GUEMR_SET_RESERVED3 | UCC_GUEMR_MODE_SLOW_RX | UCC_GUEMR_MODE_SLOW_TX);
+
+ /* Connect the serial (UCC) to TSA */
+ ret = tsa_serial_connect(qmc->tsa_serial);
+ if (ret)
+ return dev_err_probe(qmc->dev, ret, "Failed to connect TSA serial\n");
+
+ /* Initialize the QMC tx startup addresses */
+ if (!qe_issue_cmd(QE_PUSHSCHED, qmc->qe_subblock,
+ QE_CR_PROTOCOL_UNSPECIFIED, 0x80)) {
+ dev_err(qmc->dev, "QE_CMD_PUSH_SCHED tx cmd failed");
+ ret = -EIO;
+ goto err_tsa_serial_disconnect;
+ }
+
+ /* Initialize the QMC rx startup addresses */
+ if (!qe_issue_cmd(QE_PUSHSCHED, qmc->qe_subblock | 0x00020000,
+ QE_CR_PROTOCOL_UNSPECIFIED, 0x82)) {
+ dev_err(qmc->dev, "QE_CMD_PUSH_SCHED rx cmd failed");
+ ret = -EIO;
+ goto err_tsa_serial_disconnect;
+ }
+
+ /* Re-init RXPTR and TXPTR with the content of RX_S_PTR and
+ * TX_S_PTR (RX_S_PTR and TX_S_PTR are initialized during
+ * qmc_setup_tsa() call
+ */
+ val = qmc_read16(qmc->scc_pram + QMC_GBL_RX_S_PTR);
+ qmc_write16(qmc->scc_pram + QMC_GBL_RXPTR, val);
+ val = qmc_read16(qmc->scc_pram + QMC_GBL_TX_S_PTR);
+ qmc_write16(qmc->scc_pram + QMC_GBL_TXPTR, val);
+
+ /* Init GUMR_H and GUMR_L registers (SCC GSMR_H and GSMR_L) */
+ val = SCC_GSMRH_CDS | SCC_GSMRH_CTSS | SCC_GSMRH_CDP | SCC_GSMRH_CTSP |
+ SCC_GSMRH_TRX | SCC_GSMRH_TTX;
+ qmc_write32(qmc->scc_regs + SCC_GSMRH, val);
+
+ /* enable QMC mode */
+ qmc_write32(qmc->scc_regs + SCC_GSMRL, SCC_QE_GSMRL_MODE_QMC);
+
+ /* Disable and clear interrupts */
+ qmc_write16(qmc->scc_regs + SCC_SCCM, 0x0000);
+ qmc_write16(qmc->scc_regs + SCC_SCCE, 0x000F);
+
+ return 0;
+
+err_tsa_serial_disconnect:
+ tsa_serial_disconnect(qmc->tsa_serial);
+ return ret;
+}
+
+static int qmc_init_xcc(struct qmc *qmc)
+{
+ return qmc_is_qe(qmc) ?
+ qmc_qe_init_ucc(qmc) :
+ qmc_cpm1_init_scc(qmc);
+}
+
+static void qmc_exit_xcc(struct qmc *qmc)
+{
+ /* Disconnect the serial from TSA */
+ tsa_serial_disconnect(qmc->tsa_serial);
+}
+
+static int qmc_probe(struct platform_device *pdev)
+{
+ struct device_node *np = pdev->dev.of_node;
+ unsigned int nb_chans;
+ struct qmc *qmc;
+ int irq;
+ int ret;
+
+ qmc = devm_kzalloc(&pdev->dev, sizeof(*qmc), GFP_KERNEL);
+ if (!qmc)
+ return -ENOMEM;
+
+ qmc->dev = &pdev->dev;
+ qmc->data = of_device_get_match_data(&pdev->dev);
+ if (!qmc->data) {
+ dev_err(qmc->dev, "Missing match data\n");
+ return -EINVAL;
+ }
+ INIT_LIST_HEAD(&qmc->chan_head);
+
qmc->tsa_serial = devm_tsa_serial_get_byphandle(qmc->dev, np, "fsl,tsa-serial");
if (IS_ERR(qmc->tsa_serial)) {
return dev_err_probe(qmc->dev, PTR_ERR(qmc->tsa_serial),
"Failed to get TSA serial\n");
}
- /* Connect the serial (SCC) to TSA */
- ret = tsa_serial_connect(qmc->tsa_serial);
- if (ret) {
- dev_err(qmc->dev, "Failed to connect TSA serial\n");
+ ret = qmc_init_resources(qmc, pdev);
+ if (ret)
return ret;
+
+ if (qmc_is_qe(qmc)) {
+ ret = qmc_qe_soft_qmc_init(qmc, np);
+ if (ret)
+ return ret;
}
/* Parse channels informationss */
ret = qmc_of_parse_chans(qmc, np);
if (ret)
- goto err_tsa_serial_disconnect;
+ return ret;
nb_chans = qmc_nb_chans(qmc);
- /* Init GMSR_H and GMSR_L registers */
- qmc_write32(qmc->scc_regs + SCC_GSMRH,
- SCC_GSMRH_CDS | SCC_GSMRH_CTSS | SCC_GSMRH_CDP | SCC_GSMRH_CTSP);
-
- /* enable QMC mode */
- qmc_write32(qmc->scc_regs + SCC_GSMRL, SCC_GSMRL_MODE_QMC);
-
/*
* Allocate the buffer descriptor table
* 8 rx and 8 tx descriptors per channel
*/
qmc->bd_size = (nb_chans * (QMC_NB_TXBDS + QMC_NB_RXBDS)) * sizeof(cbd_t);
qmc->bd_table = dmam_alloc_coherent(qmc->dev, qmc->bd_size,
- &qmc->bd_dma_addr, GFP_KERNEL);
+ &qmc->bd_dma_addr, GFP_KERNEL);
if (!qmc->bd_table) {
dev_err(qmc->dev, "Failed to allocate bd table\n");
- ret = -ENOMEM;
- goto err_tsa_serial_disconnect;
+ return -ENOMEM;
}
memset(qmc->bd_table, 0, qmc->bd_size);
@@ -1637,11 +1947,10 @@ static int qmc_probe(struct platform_device *pdev)
/* Allocate the interrupt table */
qmc->int_size = QMC_NB_INTS * sizeof(u16);
qmc->int_table = dmam_alloc_coherent(qmc->dev, qmc->int_size,
- &qmc->int_dma_addr, GFP_KERNEL);
+ &qmc->int_dma_addr, GFP_KERNEL);
if (!qmc->int_table) {
dev_err(qmc->dev, "Failed to allocate interrupt table\n");
- ret = -ENOMEM;
- goto err_tsa_serial_disconnect;
+ return -ENOMEM;
}
memset(qmc->int_table, 0, qmc->int_size);
@@ -1658,40 +1967,59 @@ static int qmc_probe(struct platform_device *pdev)
qmc_write32(qmc->scc_pram + QMC_GBL_C_MASK32, 0xDEBB20E3);
qmc_write16(qmc->scc_pram + QMC_GBL_C_MASK16, 0xF0B8);
+ if (qmc_is_qe(qmc)) {
+ /* Zeroed the reserved area */
+ memset_io(qmc->scc_pram + QMC_QE_GBL_RSV_B0_START, 0,
+ QMC_QE_GBL_RSV_B0_SIZE);
+
+ qmc_write32(qmc->scc_pram + QMC_QE_GBL_GCSBASE, qmc->dpram_offset);
+
+ /* Init 'framer parameters' area and set the base addresses */
+ memset_io(qmc->scc_pram + UCC_SLOW_PRAM_SIZE, 0x01, 64);
+ memset_io(qmc->scc_pram + UCC_SLOW_PRAM_SIZE + 64, 0x01, 64);
+ qmc_write16(qmc->scc_pram + QMC_QE_GBL_RX_FRM_BASE,
+ qmc->scc_pram_offset + UCC_SLOW_PRAM_SIZE);
+ qmc_write16(qmc->scc_pram + QMC_QE_GBL_TX_FRM_BASE,
+ qmc->scc_pram_offset + UCC_SLOW_PRAM_SIZE + 64);
+ }
+
ret = qmc_init_tsa(qmc);
if (ret)
- goto err_tsa_serial_disconnect;
+ return ret;
qmc_write16(qmc->scc_pram + QMC_GBL_QMCSTATE, 0x8000);
ret = qmc_setup_chans(qmc);
if (ret)
- goto err_tsa_serial_disconnect;
+ return ret;
/* Init interrupts table */
ret = qmc_setup_ints(qmc);
if (ret)
- goto err_tsa_serial_disconnect;
+ return ret;
- /* Disable and clear interrupts, set the irq handler */
- qmc_write16(qmc->scc_regs + SCC_SCCM, 0x0000);
- qmc_write16(qmc->scc_regs + SCC_SCCE, 0x000F);
+ /* Init SCC (CPM1) or UCC (QE) */
+ ret = qmc_init_xcc(qmc);
+ if (ret)
+ return ret;
+
+ /* Set the irq handler */
irq = platform_get_irq(pdev, 0);
if (irq < 0)
- goto err_tsa_serial_disconnect;
+ goto err_exit_xcc;
ret = devm_request_irq(qmc->dev, irq, qmc_irq_handler, 0, "qmc", qmc);
if (ret < 0)
- goto err_tsa_serial_disconnect;
+ goto err_exit_xcc;
/* Enable interrupts */
qmc_write16(qmc->scc_regs + SCC_SCCM,
- SCC_SCCE_IQOV | SCC_SCCE_GINT | SCC_SCCE_GUN | SCC_SCCE_GOV);
+ SCC_SCCE_IQOV | SCC_SCCE_GINT | SCC_SCCE_GUN | SCC_SCCE_GOV);
ret = qmc_finalize_chans(qmc);
if (ret < 0)
goto err_disable_intr;
- /* Enable transmiter and receiver */
+ /* Enable transmitter and receiver */
qmc_setbits32(qmc->scc_regs + SCC_GSMRL, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
platform_set_drvdata(pdev, qmc);
@@ -1709,8 +2037,8 @@ err_disable_txrx:
err_disable_intr:
qmc_write16(qmc->scc_regs + SCC_SCCM, 0);
-err_tsa_serial_disconnect:
- tsa_serial_disconnect(qmc->tsa_serial);
+err_exit_xcc:
+ qmc_exit_xcc(qmc);
return ret;
}
@@ -1718,18 +2046,43 @@ static void qmc_remove(struct platform_device *pdev)
{
struct qmc *qmc = platform_get_drvdata(pdev);
- /* Disable transmiter and receiver */
+ /* Disable transmitter and receiver */
qmc_setbits32(qmc->scc_regs + SCC_GSMRL, 0);
/* Disable interrupts */
qmc_write16(qmc->scc_regs + SCC_SCCM, 0);
- /* Disconnect the serial from TSA */
- tsa_serial_disconnect(qmc->tsa_serial);
+ /* Exit SCC (CPM1) or UCC (QE) */
+ qmc_exit_xcc(qmc);
}
+static const struct qmc_data qmc_data_cpm1 = {
+ .version = QMC_CPM1,
+ .tstate = 0x30000000,
+ .rstate = 0x31000000,
+ .zistate = 0x00000100,
+ .zdstate_hdlc = 0x00000080,
+ .zdstate_transp = 0x18000080,
+ .rpack = 0x00000000,
+};
+
+static const struct qmc_data qmc_data_qe = {
+ .version = QMC_QE,
+ .tstate = 0x30000000,
+ .rstate = 0x30000000,
+ .zistate = 0x00000200,
+ .zdstate_hdlc = 0x80FFFFE0,
+ .zdstate_transp = 0x003FFFE2,
+ .rpack = 0x80000000,
+};
+
static const struct of_device_id qmc_id_table[] = {
- { .compatible = "fsl,cpm1-scc-qmc" },
+#if IS_ENABLED(CONFIG_CPM1)
+ { .compatible = "fsl,cpm1-scc-qmc", .data = &qmc_data_cpm1 },
+#endif
+#if IS_ENABLED(CONFIG_QUICC_ENGINE)
+ { .compatible = "fsl,qe-ucc-qmc", .data = &qmc_data_qe },
+#endif
{} /* sentinel */
};
MODULE_DEVICE_TABLE(of, qmc_id_table);
@@ -1889,5 +2242,5 @@ struct qmc_chan *devm_qmc_chan_get_bychild(struct device *dev,
EXPORT_SYMBOL(devm_qmc_chan_get_bychild);
MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
-MODULE_DESCRIPTION("CPM QMC driver");
+MODULE_DESCRIPTION("CPM/QE QMC driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/soc/fsl/qe/tsa.c b/drivers/soc/fsl/qe/tsa.c
index 6c5741cf5e9d..f0889b3fcaf2 100644
--- a/drivers/soc/fsl/qe/tsa.c
+++ b/drivers/soc/fsl/qe/tsa.c
@@ -9,6 +9,8 @@
#include "tsa.h"
#include <dt-bindings/soc/cpm1-fsl,tsa.h>
+#include <dt-bindings/soc/qe-fsl,tsa.h>
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -16,86 +18,116 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <soc/fsl/qe/ucc.h>
+
+/* TSA SI RAM routing tables entry (CPM1) */
+#define TSA_CPM1_SIRAM_ENTRY_LAST BIT(16)
+#define TSA_CPM1_SIRAM_ENTRY_BYTE BIT(17)
+#define TSA_CPM1_SIRAM_ENTRY_CNT_MASK GENMASK(21, 18)
+#define TSA_CPM1_SIRAM_ENTRY_CNT(x) FIELD_PREP(TSA_CPM1_SIRAM_ENTRY_CNT_MASK, x)
+#define TSA_CPM1_SIRAM_ENTRY_CSEL_MASK GENMASK(24, 22)
+#define TSA_CPM1_SIRAM_ENTRY_CSEL_NU FIELD_PREP_CONST(TSA_CPM1_SIRAM_ENTRY_CSEL_MASK, 0x0)
+#define TSA_CPM1_SIRAM_ENTRY_CSEL_SCC2 FIELD_PREP_CONST(TSA_CPM1_SIRAM_ENTRY_CSEL_MASK, 0x2)
+#define TSA_CPM1_SIRAM_ENTRY_CSEL_SCC3 FIELD_PREP_CONST(TSA_CPM1_SIRAM_ENTRY_CSEL_MASK, 0x3)
+#define TSA_CPM1_SIRAM_ENTRY_CSEL_SCC4 FIELD_PREP_CONST(TSA_CPM1_SIRAM_ENTRY_CSEL_MASK, 0x4)
+#define TSA_CPM1_SIRAM_ENTRY_CSEL_SMC1 FIELD_PREP_CONST(TSA_CPM1_SIRAM_ENTRY_CSEL_MASK, 0x5)
+#define TSA_CPM1_SIRAM_ENTRY_CSEL_SMC2 FIELD_PREP_CONST(TSA_CPM1_SIRAM_ENTRY_CSEL_MASK, 0x6)
+
+/* TSA SI RAM routing tables entry (QE) */
+#define TSA_QE_SIRAM_ENTRY_LAST BIT(0)
+#define TSA_QE_SIRAM_ENTRY_BYTE BIT(1)
+#define TSA_QE_SIRAM_ENTRY_CNT_MASK GENMASK(4, 2)
+#define TSA_QE_SIRAM_ENTRY_CNT(x) FIELD_PREP(TSA_QE_SIRAM_ENTRY_CNT_MASK, x)
+#define TSA_QE_SIRAM_ENTRY_CSEL_MASK GENMASK(8, 5)
+#define TSA_QE_SIRAM_ENTRY_CSEL_NU FIELD_PREP_CONST(TSA_QE_SIRAM_ENTRY_CSEL_MASK, 0x0)
+#define TSA_QE_SIRAM_ENTRY_CSEL_UCC5 FIELD_PREP_CONST(TSA_QE_SIRAM_ENTRY_CSEL_MASK, 0x1)
+#define TSA_QE_SIRAM_ENTRY_CSEL_UCC1 FIELD_PREP_CONST(TSA_QE_SIRAM_ENTRY_CSEL_MASK, 0x9)
+#define TSA_QE_SIRAM_ENTRY_CSEL_UCC2 FIELD_PREP_CONST(TSA_QE_SIRAM_ENTRY_CSEL_MASK, 0xa)
+#define TSA_QE_SIRAM_ENTRY_CSEL_UCC3 FIELD_PREP_CONST(TSA_QE_SIRAM_ENTRY_CSEL_MASK, 0xb)
+#define TSA_QE_SIRAM_ENTRY_CSEL_UCC4 FIELD_PREP_CONST(TSA_QE_SIRAM_ENTRY_CSEL_MASK, 0xc)
-
-/* TSA SI RAM routing tables entry */
-#define TSA_SIRAM_ENTRY_LAST (1 << 16)
-#define TSA_SIRAM_ENTRY_BYTE (1 << 17)
-#define TSA_SIRAM_ENTRY_CNT(x) (((x) & 0x0f) << 18)
-#define TSA_SIRAM_ENTRY_CSEL_MASK (0x7 << 22)
-#define TSA_SIRAM_ENTRY_CSEL_NU (0x0 << 22)
-#define TSA_SIRAM_ENTRY_CSEL_SCC2 (0x2 << 22)
-#define TSA_SIRAM_ENTRY_CSEL_SCC3 (0x3 << 22)
-#define TSA_SIRAM_ENTRY_CSEL_SCC4 (0x4 << 22)
-#define TSA_SIRAM_ENTRY_CSEL_SMC1 (0x5 << 22)
-#define TSA_SIRAM_ENTRY_CSEL_SMC2 (0x6 << 22)
-
-/* SI mode register (32 bits) */
-#define TSA_SIMODE 0x00
-#define TSA_SIMODE_SMC2 0x80000000
-#define TSA_SIMODE_SMC1 0x00008000
-#define TSA_SIMODE_TDMA(x) ((x) << 0)
-#define TSA_SIMODE_TDMB(x) ((x) << 16)
-#define TSA_SIMODE_TDM_MASK 0x0fff
-#define TSA_SIMODE_TDM_SDM_MASK 0x0c00
-#define TSA_SIMODE_TDM_SDM_NORM 0x0000
-#define TSA_SIMODE_TDM_SDM_ECHO 0x0400
-#define TSA_SIMODE_TDM_SDM_INTL_LOOP 0x0800
-#define TSA_SIMODE_TDM_SDM_LOOP_CTRL 0x0c00
-#define TSA_SIMODE_TDM_RFSD(x) ((x) << 8)
-#define TSA_SIMODE_TDM_DSC 0x0080
-#define TSA_SIMODE_TDM_CRT 0x0040
-#define TSA_SIMODE_TDM_STZ 0x0020
-#define TSA_SIMODE_TDM_CE 0x0010
-#define TSA_SIMODE_TDM_FE 0x0008
-#define TSA_SIMODE_TDM_GM 0x0004
-#define TSA_SIMODE_TDM_TFSD(x) ((x) << 0)
-
-/* SI global mode register (8 bits) */
-#define TSA_SIGMR 0x04
-#define TSA_SIGMR_ENB (1<<3)
-#define TSA_SIGMR_ENA (1<<2)
-#define TSA_SIGMR_RDM_MASK 0x03
-#define TSA_SIGMR_RDM_STATIC_TDMA 0x00
-#define TSA_SIGMR_RDM_DYN_TDMA 0x01
-#define TSA_SIGMR_RDM_STATIC_TDMAB 0x02
-#define TSA_SIGMR_RDM_DYN_TDMAB 0x03
-
-/* SI status register (8 bits) */
-#define TSA_SISTR 0x06
-
-/* SI command register (8 bits) */
-#define TSA_SICMR 0x07
+/*
+ * SI mode register :
+ * - CPM1: 32bit register split in 2*16bit (16bit TDM)
+ * - QE: 4x16bit registers, one per TDM
+ */
+#define TSA_CPM1_SIMODE 0x00
+#define TSA_QE_SIAMR 0x00
+#define TSA_QE_SIBMR 0x02
+#define TSA_QE_SICMR 0x04
+#define TSA_QE_SIDMR 0x06
+#define TSA_CPM1_SIMODE_SMC2 BIT(31)
+#define TSA_CPM1_SIMODE_SMC1 BIT(15)
+#define TSA_CPM1_SIMODE_TDMA_MASK GENMASK(11, 0)
+#define TSA_CPM1_SIMODE_TDMA(x) FIELD_PREP(TSA_CPM1_SIMODE_TDMA_MASK, x)
+#define TSA_CPM1_SIMODE_TDMB_MASK GENMASK(27, 16)
+#define TSA_CPM1_SIMODE_TDMB(x) FIELD_PREP(TSA_CPM1_SIMODE_TDMB_MASK, x)
+#define TSA_QE_SIMODE_TDM_SAD_MASK GENMASK(15, 12)
+#define TSA_QE_SIMODE_TDM_SAD(x) FIELD_PREP(TSA_QE_SIMODE_TDM_SAD_MASK, x)
+#define TSA_CPM1_SIMODE_TDM_MASK GENMASK(11, 0)
+#define TSA_SIMODE_TDM_SDM_MASK GENMASK(11, 10)
+#define TSA_SIMODE_TDM_SDM_NORM FIELD_PREP_CONST(TSA_SIMODE_TDM_SDM_MASK, 0x0)
+#define TSA_SIMODE_TDM_SDM_ECHO FIELD_PREP_CONST(TSA_SIMODE_TDM_SDM_MASK, 0x1)
+#define TSA_SIMODE_TDM_SDM_INTL_LOOP FIELD_PREP_CONST(TSA_SIMODE_TDM_SDM_MASK, 0x2)
+#define TSA_SIMODE_TDM_SDM_LOOP_CTRL FIELD_PREP_CONST(TSA_SIMODE_TDM_SDM_MASK, 0x3)
+#define TSA_SIMODE_TDM_RFSD_MASK GENMASK(9, 8)
+#define TSA_SIMODE_TDM_RFSD(x) FIELD_PREP(TSA_SIMODE_TDM_RFSD_MASK, x)
+#define TSA_SIMODE_TDM_DSC BIT(7)
+#define TSA_SIMODE_TDM_CRT BIT(6)
+#define TSA_CPM1_SIMODE_TDM_STZ BIT(5) /* bit 5: STZ in CPM1 */
+#define TSA_QE_SIMODE_TDM_SL BIT(5) /* bit 5: SL in QE */
+#define TSA_SIMODE_TDM_CE BIT(4)
+#define TSA_SIMODE_TDM_FE BIT(3)
+#define TSA_SIMODE_TDM_GM BIT(2)
+#define TSA_SIMODE_TDM_TFSD_MASK GENMASK(1, 0)
+#define TSA_SIMODE_TDM_TFSD(x) FIELD_PREP(TSA_SIMODE_TDM_TFSD_MASK, x)
+
+/* CPM SI global mode register (8 bits) */
+#define TSA_CPM1_SIGMR 0x04
+#define TSA_CPM1_SIGMR_ENB BIT(3)
+#define TSA_CPM1_SIGMR_ENA BIT(2)
+#define TSA_CPM1_SIGMR_RDM_MASK GENMASK(1, 0)
+#define TSA_CPM1_SIGMR_RDM_STATIC_TDMA FIELD_PREP_CONST(TSA_CPM1_SIGMR_RDM_MASK, 0x0)
+#define TSA_CPM1_SIGMR_RDM_DYN_TDMA FIELD_PREP_CONST(TSA_CPM1_SIGMR_RDM_MASK, 0x1)
+#define TSA_CPM1_SIGMR_RDM_STATIC_TDMAB FIELD_PREP_CONST(TSA_CPM1_SIGMR_RDM_MASK, 0x2)
+#define TSA_CPM1_SIGMR_RDM_DYN_TDMAB FIELD_PREP_CONST(TSA_CPM1_SIGMR_RDM_MASK, 0x3)
+
+/* QE SI global mode register high (8 bits) */
+#define TSA_QE_SIGLMRH 0x08
+#define TSA_QE_SIGLMRH_END BIT(3)
+#define TSA_QE_SIGLMRH_ENC BIT(2)
+#define TSA_QE_SIGLMRH_ENB BIT(1)
+#define TSA_QE_SIGLMRH_ENA BIT(0)
/* SI clock route register (32 bits) */
-#define TSA_SICR 0x0C
-#define TSA_SICR_SCC2(x) ((x) << 8)
-#define TSA_SICR_SCC3(x) ((x) << 16)
-#define TSA_SICR_SCC4(x) ((x) << 24)
-#define TSA_SICR_SCC_MASK 0x0ff
-#define TSA_SICR_SCC_GRX (1 << 7)
-#define TSA_SICR_SCC_SCX_TSA (1 << 6)
-#define TSA_SICR_SCC_RXCS_MASK (0x7 << 3)
-#define TSA_SICR_SCC_RXCS_BRG1 (0x0 << 3)
-#define TSA_SICR_SCC_RXCS_BRG2 (0x1 << 3)
-#define TSA_SICR_SCC_RXCS_BRG3 (0x2 << 3)
-#define TSA_SICR_SCC_RXCS_BRG4 (0x3 << 3)
-#define TSA_SICR_SCC_RXCS_CLK15 (0x4 << 3)
-#define TSA_SICR_SCC_RXCS_CLK26 (0x5 << 3)
-#define TSA_SICR_SCC_RXCS_CLK37 (0x6 << 3)
-#define TSA_SICR_SCC_RXCS_CLK48 (0x7 << 3)
-#define TSA_SICR_SCC_TXCS_MASK (0x7 << 0)
-#define TSA_SICR_SCC_TXCS_BRG1 (0x0 << 0)
-#define TSA_SICR_SCC_TXCS_BRG2 (0x1 << 0)
-#define TSA_SICR_SCC_TXCS_BRG3 (0x2 << 0)
-#define TSA_SICR_SCC_TXCS_BRG4 (0x3 << 0)
-#define TSA_SICR_SCC_TXCS_CLK15 (0x4 << 0)
-#define TSA_SICR_SCC_TXCS_CLK26 (0x5 << 0)
-#define TSA_SICR_SCC_TXCS_CLK37 (0x6 << 0)
-#define TSA_SICR_SCC_TXCS_CLK48 (0x7 << 0)
-
-/* Serial interface RAM pointer register (32 bits) */
-#define TSA_SIRP 0x10
+#define TSA_CPM1_SICR 0x0C
+#define TSA_CPM1_SICR_SCC2_MASK GENMASK(15, 8)
+#define TSA_CPM1_SICR_SCC2(x) FIELD_PREP(TSA_CPM1_SICR_SCC2_MASK, x)
+#define TSA_CPM1_SICR_SCC3_MASK GENMASK(23, 16)
+#define TSA_CPM1_SICR_SCC3(x) FIELD_PREP(TSA_CPM1_SICR_SCC3_MASK, x)
+#define TSA_CPM1_SICR_SCC4_MASK GENMASK(31, 24)
+#define TSA_CPM1_SICR_SCC4(x) FIELD_PREP(TSA_CPM1_SICR_SCC4_MASK, x)
+#define TSA_CPM1_SICR_SCC_MASK GENMASK(7, 0)
+#define TSA_CPM1_SICR_SCC_GRX BIT(7)
+#define TSA_CPM1_SICR_SCC_SCX_TSA BIT(6)
+#define TSA_CPM1_SICR_SCC_RXCS_MASK GENMASK(5, 3)
+#define TSA_CPM1_SICR_SCC_RXCS_BRG1 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_RXCS_MASK, 0x0)
+#define TSA_CPM1_SICR_SCC_RXCS_BRG2 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_RXCS_MASK, 0x1)
+#define TSA_CPM1_SICR_SCC_RXCS_BRG3 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_RXCS_MASK, 0x2)
+#define TSA_CPM1_SICR_SCC_RXCS_BRG4 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_RXCS_MASK, 0x3)
+#define TSA_CPM1_SICR_SCC_RXCS_CLK15 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_RXCS_MASK, 0x4)
+#define TSA_CPM1_SICR_SCC_RXCS_CLK26 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_RXCS_MASK, 0x5)
+#define TSA_CPM1_SICR_SCC_RXCS_CLK37 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_RXCS_MASK, 0x6)
+#define TSA_CPM1_SICR_SCC_RXCS_CLK48 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_RXCS_MASK, 0x7)
+#define TSA_CPM1_SICR_SCC_TXCS_MASK GENMASK(2, 0)
+#define TSA_CPM1_SICR_SCC_TXCS_BRG1 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_TXCS_MASK, 0x0)
+#define TSA_CPM1_SICR_SCC_TXCS_BRG2 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_TXCS_MASK, 0x1)
+#define TSA_CPM1_SICR_SCC_TXCS_BRG3 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_TXCS_MASK, 0x2)
+#define TSA_CPM1_SICR_SCC_TXCS_BRG4 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_TXCS_MASK, 0x3)
+#define TSA_CPM1_SICR_SCC_TXCS_CLK15 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_TXCS_MASK, 0x4)
+#define TSA_CPM1_SICR_SCC_TXCS_CLK26 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_TXCS_MASK, 0x5)
+#define TSA_CPM1_SICR_SCC_TXCS_CLK37 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_TXCS_MASK, 0x6)
+#define TSA_CPM1_SICR_SCC_TXCS_CLK48 FIELD_PREP_CONST(TSA_CPM1_SICR_SCC_TXCS_MASK, 0x7)
struct tsa_entries_area {
void __iomem *entries_start;
@@ -114,15 +146,31 @@ struct tsa_tdm {
#define TSA_TDMA 0
#define TSA_TDMB 1
+#define TSA_TDMC 2 /* QE implementation only */
+#define TSA_TDMD 3 /* QE implementation only */
+
+enum tsa_version {
+ TSA_CPM1 = 1, /* Avoid 0 value */
+ TSA_QE,
+};
struct tsa {
struct device *dev;
void __iomem *si_regs;
void __iomem *si_ram;
resource_size_t si_ram_sz;
- spinlock_t lock;
+ spinlock_t lock; /* Lock for read/modify/write sequence */
+ enum tsa_version version;
int tdms; /* TSA_TDMx ORed */
+#if IS_ENABLED(CONFIG_QUICC_ENGINE)
+ struct tsa_tdm tdm[4]; /* TDMa, TDMb, TDMc and TDMd */
+#else
struct tsa_tdm tdm[2]; /* TDMa and TDMb */
+#endif
+ /* Same number of serials for CPM1 and QE:
+ * CPM1: NU, 3 SCCs and 2 SMCs
+ * QE: NU and 5 UCCs
+ */
struct tsa_serial {
unsigned int id;
struct tsa_serial_info info;
@@ -140,7 +188,12 @@ static inline void tsa_write32(void __iomem *addr, u32 val)
iowrite32be(val, addr);
}
-static inline void tsa_write8(void __iomem *addr, u32 val)
+static inline void tsa_write16(void __iomem *addr, u16 val)
+{
+ iowrite16be(val, addr);
+}
+
+static inline void tsa_write8(void __iomem *addr, u8 val)
{
iowrite8(val, addr);
}
@@ -150,17 +203,68 @@ static inline u32 tsa_read32(void __iomem *addr)
return ioread32be(addr);
}
+static inline u16 tsa_read16(void __iomem *addr)
+{
+ return ioread16be(addr);
+}
+
static inline void tsa_clrbits32(void __iomem *addr, u32 clr)
{
tsa_write32(addr, tsa_read32(addr) & ~clr);
}
+static inline void tsa_clrbits16(void __iomem *addr, u16 clr)
+{
+ tsa_write16(addr, tsa_read16(addr) & ~clr);
+}
+
static inline void tsa_clrsetbits32(void __iomem *addr, u32 clr, u32 set)
{
tsa_write32(addr, (tsa_read32(addr) & ~clr) | set);
}
-int tsa_serial_connect(struct tsa_serial *tsa_serial)
+static bool tsa_is_qe(const struct tsa *tsa)
+{
+ if (IS_ENABLED(CONFIG_QUICC_ENGINE) && IS_ENABLED(CONFIG_CPM))
+ return tsa->version == TSA_QE;
+
+ return IS_ENABLED(CONFIG_QUICC_ENGINE);
+}
+
+static int tsa_qe_serial_get_num(struct tsa_serial *tsa_serial)
+{
+ struct tsa *tsa = tsa_serial_get_tsa(tsa_serial);
+
+ switch (tsa_serial->id) {
+ case FSL_QE_TSA_UCC1: return 0;
+ case FSL_QE_TSA_UCC2: return 1;
+ case FSL_QE_TSA_UCC3: return 2;
+ case FSL_QE_TSA_UCC4: return 3;
+ case FSL_QE_TSA_UCC5: return 4;
+ default:
+ break;
+ }
+
+ dev_err(tsa->dev, "Unsupported serial id %u\n", tsa_serial->id);
+ return -EINVAL;
+}
+
+int tsa_serial_get_num(struct tsa_serial *tsa_serial)
+{
+ struct tsa *tsa = tsa_serial_get_tsa(tsa_serial);
+
+ /*
+ * There is no need to get the serial num out of the TSA driver in the
+ * CPM case.
+ * Further more, in CPM, we can have 2 types of serial SCCs and FCCs.
+ * What kind of numbering to use that can be global to both SCCs and
+ * FCCs ?
+ */
+ return tsa_is_qe(tsa) ? tsa_qe_serial_get_num(tsa_serial) : -EOPNOTSUPP;
+}
+EXPORT_SYMBOL(tsa_serial_get_num);
+
+static int tsa_cpm1_serial_connect(struct tsa_serial *tsa_serial, bool connect)
{
struct tsa *tsa = tsa_serial_get_tsa(tsa_serial);
unsigned long flags;
@@ -169,16 +273,16 @@ int tsa_serial_connect(struct tsa_serial *tsa_serial)
switch (tsa_serial->id) {
case FSL_CPM_TSA_SCC2:
- clear = TSA_SICR_SCC2(TSA_SICR_SCC_MASK);
- set = TSA_SICR_SCC2(TSA_SICR_SCC_SCX_TSA);
+ clear = TSA_CPM1_SICR_SCC2(TSA_CPM1_SICR_SCC_MASK);
+ set = TSA_CPM1_SICR_SCC2(TSA_CPM1_SICR_SCC_SCX_TSA);
break;
case FSL_CPM_TSA_SCC3:
- clear = TSA_SICR_SCC3(TSA_SICR_SCC_MASK);
- set = TSA_SICR_SCC3(TSA_SICR_SCC_SCX_TSA);
+ clear = TSA_CPM1_SICR_SCC3(TSA_CPM1_SICR_SCC_MASK);
+ set = TSA_CPM1_SICR_SCC3(TSA_CPM1_SICR_SCC_SCX_TSA);
break;
case FSL_CPM_TSA_SCC4:
- clear = TSA_SICR_SCC4(TSA_SICR_SCC_MASK);
- set = TSA_SICR_SCC4(TSA_SICR_SCC_SCX_TSA);
+ clear = TSA_CPM1_SICR_SCC4(TSA_CPM1_SICR_SCC_MASK);
+ set = TSA_CPM1_SICR_SCC4(TSA_CPM1_SICR_SCC_SCX_TSA);
break;
default:
dev_err(tsa->dev, "Unsupported serial id %u\n", tsa_serial->id);
@@ -186,40 +290,53 @@ int tsa_serial_connect(struct tsa_serial *tsa_serial)
}
spin_lock_irqsave(&tsa->lock, flags);
- tsa_clrsetbits32(tsa->si_regs + TSA_SICR, clear, set);
+ tsa_clrsetbits32(tsa->si_regs + TSA_CPM1_SICR, clear,
+ connect ? set : 0);
spin_unlock_irqrestore(&tsa->lock, flags);
return 0;
}
-EXPORT_SYMBOL(tsa_serial_connect);
-int tsa_serial_disconnect(struct tsa_serial *tsa_serial)
+static int tsa_qe_serial_connect(struct tsa_serial *tsa_serial, bool connect)
{
struct tsa *tsa = tsa_serial_get_tsa(tsa_serial);
unsigned long flags;
- u32 clear;
+ int ucc_num;
+ int ret;
- switch (tsa_serial->id) {
- case FSL_CPM_TSA_SCC2:
- clear = TSA_SICR_SCC2(TSA_SICR_SCC_MASK);
- break;
- case FSL_CPM_TSA_SCC3:
- clear = TSA_SICR_SCC3(TSA_SICR_SCC_MASK);
- break;
- case FSL_CPM_TSA_SCC4:
- clear = TSA_SICR_SCC4(TSA_SICR_SCC_MASK);
- break;
- default:
- dev_err(tsa->dev, "Unsupported serial id %u\n", tsa_serial->id);
- return -EINVAL;
- }
+ ucc_num = tsa_qe_serial_get_num(tsa_serial);
+ if (ucc_num < 0)
+ return ucc_num;
spin_lock_irqsave(&tsa->lock, flags);
- tsa_clrsetbits32(tsa->si_regs + TSA_SICR, clear, 0);
+ ret = ucc_set_qe_mux_tsa(ucc_num, connect);
spin_unlock_irqrestore(&tsa->lock, flags);
-
+ if (ret) {
+ dev_err(tsa->dev, "Connect serial id %u to TSA failed (%d)\n",
+ tsa_serial->id, ret);
+ return ret;
+ }
return 0;
}
+
+int tsa_serial_connect(struct tsa_serial *tsa_serial)
+{
+ struct tsa *tsa = tsa_serial_get_tsa(tsa_serial);
+
+ return tsa_is_qe(tsa) ?
+ tsa_qe_serial_connect(tsa_serial, true) :
+ tsa_cpm1_serial_connect(tsa_serial, true);
+}
+EXPORT_SYMBOL(tsa_serial_connect);
+
+int tsa_serial_disconnect(struct tsa_serial *tsa_serial)
+{
+ struct tsa *tsa = tsa_serial_get_tsa(tsa_serial);
+
+ return tsa_is_qe(tsa) ?
+ tsa_qe_serial_connect(tsa_serial, false) :
+ tsa_cpm1_serial_connect(tsa_serial, false);
+}
EXPORT_SYMBOL(tsa_serial_disconnect);
int tsa_serial_get_info(struct tsa_serial *tsa_serial, struct tsa_serial_info *info)
@@ -229,14 +346,14 @@ int tsa_serial_get_info(struct tsa_serial *tsa_serial, struct tsa_serial_info *i
}
EXPORT_SYMBOL(tsa_serial_get_info);
-static void tsa_init_entries_area(struct tsa *tsa, struct tsa_entries_area *area,
- u32 tdms, u32 tdm_id, bool is_rx)
+static void tsa_cpm1_init_entries_area(struct tsa *tsa, struct tsa_entries_area *area,
+ u32 tdms, u32 tdm_id, bool is_rx)
{
resource_size_t quarter;
resource_size_t half;
- quarter = tsa->si_ram_sz/4;
- half = tsa->si_ram_sz/2;
+ quarter = tsa->si_ram_sz / 4;
+ half = tsa->si_ram_sz / 2;
if (tdms == BIT(TSA_TDMA)) {
/* Only TDMA */
@@ -281,7 +398,42 @@ static void tsa_init_entries_area(struct tsa *tsa, struct tsa_entries_area *area
}
}
-static const char *tsa_serial_id2name(struct tsa *tsa, u32 serial_id)
+static void tsa_qe_init_entries_area(struct tsa *tsa, struct tsa_entries_area *area,
+ u32 tdms, u32 tdm_id, bool is_rx)
+{
+ resource_size_t eighth;
+ resource_size_t half;
+
+ eighth = tsa->si_ram_sz / 8;
+ half = tsa->si_ram_sz / 2;
+
+ /*
+ * One half of the SI RAM used for Tx, the other one for Rx.
+ * In each half, 1/4 of the area is assigned to each TDM.
+ */
+ if (is_rx) {
+ /* Rx: Second half of si_ram */
+ area->entries_start = tsa->si_ram + half + (eighth * tdm_id);
+ area->entries_next = area->entries_start + eighth;
+ area->last_entry = NULL;
+ } else {
+ /* Tx: First half of si_ram */
+ area->entries_start = tsa->si_ram + (eighth * tdm_id);
+ area->entries_next = area->entries_start + eighth;
+ area->last_entry = NULL;
+ }
+}
+
+static void tsa_init_entries_area(struct tsa *tsa, struct tsa_entries_area *area,
+ u32 tdms, u32 tdm_id, bool is_rx)
+{
+ if (tsa_is_qe(tsa))
+ tsa_qe_init_entries_area(tsa, area, tdms, tdm_id, is_rx);
+ else
+ tsa_cpm1_init_entries_area(tsa, area, tdms, tdm_id, is_rx);
+}
+
+static const char *tsa_cpm1_serial_id2name(struct tsa *tsa, u32 serial_id)
{
switch (serial_id) {
case FSL_CPM_TSA_NU: return "Not used";
@@ -296,22 +448,44 @@ static const char *tsa_serial_id2name(struct tsa *tsa, u32 serial_id)
return NULL;
}
-static u32 tsa_serial_id2csel(struct tsa *tsa, u32 serial_id)
+static const char *tsa_qe_serial_id2name(struct tsa *tsa, u32 serial_id)
{
switch (serial_id) {
- case FSL_CPM_TSA_SCC2: return TSA_SIRAM_ENTRY_CSEL_SCC2;
- case FSL_CPM_TSA_SCC3: return TSA_SIRAM_ENTRY_CSEL_SCC3;
- case FSL_CPM_TSA_SCC4: return TSA_SIRAM_ENTRY_CSEL_SCC4;
- case FSL_CPM_TSA_SMC1: return TSA_SIRAM_ENTRY_CSEL_SMC1;
- case FSL_CPM_TSA_SMC2: return TSA_SIRAM_ENTRY_CSEL_SMC2;
+ case FSL_QE_TSA_NU: return "Not used";
+ case FSL_QE_TSA_UCC1: return "UCC1";
+ case FSL_QE_TSA_UCC2: return "UCC2";
+ case FSL_QE_TSA_UCC3: return "UCC3";
+ case FSL_QE_TSA_UCC4: return "UCC4";
+ case FSL_QE_TSA_UCC5: return "UCC5";
default:
break;
}
- return TSA_SIRAM_ENTRY_CSEL_NU;
+ return NULL;
}
-static int tsa_add_entry(struct tsa *tsa, struct tsa_entries_area *area,
- u32 count, u32 serial_id)
+static const char *tsa_serial_id2name(struct tsa *tsa, u32 serial_id)
+{
+ return tsa_is_qe(tsa) ?
+ tsa_qe_serial_id2name(tsa, serial_id) :
+ tsa_cpm1_serial_id2name(tsa, serial_id);
+}
+
+static u32 tsa_cpm1_serial_id2csel(struct tsa *tsa, u32 serial_id)
+{
+ switch (serial_id) {
+ case FSL_CPM_TSA_SCC2: return TSA_CPM1_SIRAM_ENTRY_CSEL_SCC2;
+ case FSL_CPM_TSA_SCC3: return TSA_CPM1_SIRAM_ENTRY_CSEL_SCC3;
+ case FSL_CPM_TSA_SCC4: return TSA_CPM1_SIRAM_ENTRY_CSEL_SCC4;
+ case FSL_CPM_TSA_SMC1: return TSA_CPM1_SIRAM_ENTRY_CSEL_SMC1;
+ case FSL_CPM_TSA_SMC2: return TSA_CPM1_SIRAM_ENTRY_CSEL_SMC2;
+ default:
+ break;
+ }
+ return TSA_CPM1_SIRAM_ENTRY_CSEL_NU;
+}
+
+static int tsa_cpm1_add_entry(struct tsa *tsa, struct tsa_entries_area *area,
+ u32 count, u32 serial_id)
{
void __iomem *addr;
u32 left;
@@ -329,21 +503,21 @@ static int tsa_add_entry(struct tsa *tsa, struct tsa_entries_area *area,
if (area->last_entry) {
/* Clear last flag */
- tsa_clrbits32(area->last_entry, TSA_SIRAM_ENTRY_LAST);
+ tsa_clrbits32(area->last_entry, TSA_CPM1_SIRAM_ENTRY_LAST);
}
left = count;
while (left) {
- val = TSA_SIRAM_ENTRY_BYTE | tsa_serial_id2csel(tsa, serial_id);
+ val = TSA_CPM1_SIRAM_ENTRY_BYTE | tsa_cpm1_serial_id2csel(tsa, serial_id);
if (left > 16) {
cnt = 16;
} else {
cnt = left;
- val |= TSA_SIRAM_ENTRY_LAST;
+ val |= TSA_CPM1_SIRAM_ENTRY_LAST;
area->last_entry = addr;
}
- val |= TSA_SIRAM_ENTRY_CNT(cnt - 1);
+ val |= TSA_CPM1_SIRAM_ENTRY_CNT(cnt - 1);
tsa_write32(addr, val);
addr += 4;
@@ -353,6 +527,71 @@ static int tsa_add_entry(struct tsa *tsa, struct tsa_entries_area *area,
return 0;
}
+static u32 tsa_qe_serial_id2csel(struct tsa *tsa, u32 serial_id)
+{
+ switch (serial_id) {
+ case FSL_QE_TSA_UCC1: return TSA_QE_SIRAM_ENTRY_CSEL_UCC1;
+ case FSL_QE_TSA_UCC2: return TSA_QE_SIRAM_ENTRY_CSEL_UCC2;
+ case FSL_QE_TSA_UCC3: return TSA_QE_SIRAM_ENTRY_CSEL_UCC3;
+ case FSL_QE_TSA_UCC4: return TSA_QE_SIRAM_ENTRY_CSEL_UCC4;
+ case FSL_QE_TSA_UCC5: return TSA_QE_SIRAM_ENTRY_CSEL_UCC5;
+ default:
+ break;
+ }
+ return TSA_QE_SIRAM_ENTRY_CSEL_NU;
+}
+
+static int tsa_qe_add_entry(struct tsa *tsa, struct tsa_entries_area *area,
+ u32 count, u32 serial_id)
+{
+ void __iomem *addr;
+ u32 left;
+ u32 val;
+ u32 cnt;
+ u32 nb;
+
+ addr = area->last_entry ? area->last_entry + 2 : area->entries_start;
+
+ nb = DIV_ROUND_UP(count, 8);
+ if ((addr + (nb * 2)) > area->entries_next) {
+ dev_err(tsa->dev, "si ram area full\n");
+ return -ENOSPC;
+ }
+
+ if (area->last_entry) {
+ /* Clear last flag */
+ tsa_clrbits16(area->last_entry, TSA_QE_SIRAM_ENTRY_LAST);
+ }
+
+ left = count;
+ while (left) {
+ val = TSA_QE_SIRAM_ENTRY_BYTE | tsa_qe_serial_id2csel(tsa, serial_id);
+
+ if (left > 8) {
+ cnt = 8;
+ } else {
+ cnt = left;
+ val |= TSA_QE_SIRAM_ENTRY_LAST;
+ area->last_entry = addr;
+ }
+ val |= TSA_QE_SIRAM_ENTRY_CNT(cnt - 1);
+
+ tsa_write16(addr, val);
+ addr += 2;
+ left -= cnt;
+ }
+
+ return 0;
+}
+
+static int tsa_add_entry(struct tsa *tsa, struct tsa_entries_area *area,
+ u32 count, u32 serial_id)
+{
+ return tsa_is_qe(tsa) ?
+ tsa_qe_add_entry(tsa, area, count, serial_id) :
+ tsa_cpm1_add_entry(tsa, area, count, serial_id);
+}
+
static int tsa_of_parse_tdm_route(struct tsa *tsa, struct device_node *tdm_np,
u32 tdms, u32 tdm_id, bool is_rx)
{
@@ -399,7 +638,7 @@ static int tsa_of_parse_tdm_route(struct tsa *tsa, struct device_node *tdm_np,
}
dev_dbg(tsa->dev, "tdm_id=%u, %s ts %u..%u -> %s\n",
- tdm_id, route_name, ts, ts+count-1, serial_name);
+ tdm_id, route_name, ts, ts + count - 1, serial_name);
ts += count;
ret = tsa_add_entry(tsa, &area, count, serial_id);
@@ -449,8 +688,8 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np)
int i;
tsa->tdms = 0;
- tsa->tdm[0].is_enable = false;
- tsa->tdm[1].is_enable = false;
+ for (i = 0; i < ARRAY_SIZE(tsa->tdm); i++)
+ tsa->tdm[i].is_enable = false;
for_each_available_child_of_node(np, tdm_np) {
ret = of_property_read_u32(tdm_np, "reg", &tdm_id);
@@ -466,7 +705,18 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np)
case 1:
tsa->tdms |= BIT(TSA_TDMB);
break;
+ case 2:
+ if (!tsa_is_qe(tsa))
+ goto invalid_tdm; /* Not available on CPM1 */
+ tsa->tdms |= BIT(TSA_TDMC);
+ break;
+ case 3:
+ if (!tsa_is_qe(tsa))
+ goto invalid_tdm; /* Not available on CPM1 */
+ tsa->tdms |= BIT(TSA_TDMD);
+ break;
default:
+invalid_tdm:
dev_err(tsa->dev, "%pOF: Invalid tdm_id (%u)\n", tdm_np,
tdm_id);
of_node_put(tdm_np);
@@ -532,10 +782,14 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np)
if (of_property_read_bool(tdm_np, "fsl,fsync-rising-edge"))
tdm->simode_tdm |= TSA_SIMODE_TDM_FE;
+ if (tsa_is_qe(tsa) &&
+ of_property_read_bool(tdm_np, "fsl,fsync-active-low"))
+ tdm->simode_tdm |= TSA_QE_SIMODE_TDM_SL;
+
if (of_property_read_bool(tdm_np, "fsl,double-speed-clock"))
tdm->simode_tdm |= TSA_SIMODE_TDM_DSC;
- clk = of_clk_get_by_name(tdm_np, "l1rsync");
+ clk = of_clk_get_by_name(tdm_np, tsa_is_qe(tsa) ? "rsync" : "l1rsync");
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
of_node_put(tdm_np);
@@ -549,7 +803,7 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np)
}
tdm->l1rsync_clk = clk;
- clk = of_clk_get_by_name(tdm_np, "l1rclk");
+ clk = of_clk_get_by_name(tdm_np, tsa_is_qe(tsa) ? "rclk" : "l1rclk");
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
of_node_put(tdm_np);
@@ -564,7 +818,7 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np)
tdm->l1rclk_clk = clk;
if (!(tdm->simode_tdm & TSA_SIMODE_TDM_CRT)) {
- clk = of_clk_get_by_name(tdm_np, "l1tsync");
+ clk = of_clk_get_by_name(tdm_np, tsa_is_qe(tsa) ? "tsync" : "l1tsync");
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
of_node_put(tdm_np);
@@ -578,7 +832,7 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np)
}
tdm->l1tsync_clk = clk;
- clk = of_clk_get_by_name(tdm_np, "l1tclk");
+ clk = of_clk_get_by_name(tdm_np, tsa_is_qe(tsa) ? "tclk" : "l1tclk");
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
of_node_put(tdm_np);
@@ -593,6 +847,17 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np)
tdm->l1tclk_clk = clk;
}
+ if (tsa_is_qe(tsa)) {
+ /*
+ * The starting address for TSA table must be set.
+ * 512 entries for Tx and 512 entries for Rx are
+ * available for 4 TDMs.
+ * We assign entries equally -> 128 Rx/Tx entries per
+ * TDM. In other words, 4 blocks of 32 entries per TDM.
+ */
+ tdm->simode_tdm |= TSA_QE_SIMODE_TDM_SAD(4 * tdm_id);
+ }
+
ret = tsa_of_parse_tdm_rx_route(tsa, tdm_np, tsa->tdms, tdm_id);
if (ret) {
of_node_put(tdm_np);
@@ -610,7 +875,7 @@ static int tsa_of_parse_tdms(struct tsa *tsa, struct device_node *np)
return 0;
err:
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < ARRAY_SIZE(tsa->tdm); i++) {
if (tsa->tdm[i].l1rsync_clk) {
clk_disable_unprepare(tsa->tdm[i].l1rsync_clk);
clk_put(tsa->tdm[i].l1rsync_clk);
@@ -636,8 +901,87 @@ static void tsa_init_si_ram(struct tsa *tsa)
resource_size_t i;
/* Fill all entries as the last one */
- for (i = 0; i < tsa->si_ram_sz; i += 4)
- tsa_write32(tsa->si_ram + i, TSA_SIRAM_ENTRY_LAST);
+ if (tsa_is_qe(tsa)) {
+ for (i = 0; i < tsa->si_ram_sz; i += 2)
+ tsa_write16(tsa->si_ram + i, TSA_QE_SIRAM_ENTRY_LAST);
+ } else {
+ for (i = 0; i < tsa->si_ram_sz; i += 4)
+ tsa_write32(tsa->si_ram + i, TSA_CPM1_SIRAM_ENTRY_LAST);
+ }
+}
+
+static int tsa_cpm1_setup(struct tsa *tsa)
+{
+ u32 val;
+
+ /* Set SIMODE */
+ val = 0;
+ if (tsa->tdm[0].is_enable)
+ val |= TSA_CPM1_SIMODE_TDMA(tsa->tdm[0].simode_tdm);
+ if (tsa->tdm[1].is_enable)
+ val |= TSA_CPM1_SIMODE_TDMB(tsa->tdm[1].simode_tdm);
+
+ tsa_clrsetbits32(tsa->si_regs + TSA_CPM1_SIMODE,
+ TSA_CPM1_SIMODE_TDMA(TSA_CPM1_SIMODE_TDM_MASK) |
+ TSA_CPM1_SIMODE_TDMB(TSA_CPM1_SIMODE_TDM_MASK),
+ val);
+
+ /* Set SIGMR */
+ val = (tsa->tdms == BIT(TSA_TDMA)) ?
+ TSA_CPM1_SIGMR_RDM_STATIC_TDMA : TSA_CPM1_SIGMR_RDM_STATIC_TDMAB;
+ if (tsa->tdms & BIT(TSA_TDMA))
+ val |= TSA_CPM1_SIGMR_ENA;
+ if (tsa->tdms & BIT(TSA_TDMB))
+ val |= TSA_CPM1_SIGMR_ENB;
+ tsa_write8(tsa->si_regs + TSA_CPM1_SIGMR, val);
+
+ return 0;
+}
+
+static int tsa_qe_setup(struct tsa *tsa)
+{
+ unsigned int sixmr;
+ u8 siglmrh = 0;
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(tsa->tdm); i++) {
+ if (!tsa->tdm[i].is_enable)
+ continue;
+
+ switch (i) {
+ case 0:
+ sixmr = TSA_QE_SIAMR;
+ siglmrh |= TSA_QE_SIGLMRH_ENA;
+ break;
+ case 1:
+ sixmr = TSA_QE_SIBMR;
+ siglmrh |= TSA_QE_SIGLMRH_ENB;
+ break;
+ case 2:
+ sixmr = TSA_QE_SICMR;
+ siglmrh |= TSA_QE_SIGLMRH_ENC;
+ break;
+ case 3:
+ sixmr = TSA_QE_SIDMR;
+ siglmrh |= TSA_QE_SIGLMRH_END;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Set SI mode register */
+ tsa_write16(tsa->si_regs + sixmr, tsa->tdm[i].simode_tdm);
+ }
+
+ /* Enable TDMs */
+ tsa_write8(tsa->si_regs + TSA_QE_SIGLMRH, siglmrh);
+
+ return 0;
+}
+
+static int tsa_setup(struct tsa *tsa)
+{
+ return tsa_is_qe(tsa) ? tsa_qe_setup(tsa) : tsa_cpm1_setup(tsa);
}
static int tsa_probe(struct platform_device *pdev)
@@ -646,7 +990,6 @@ static int tsa_probe(struct platform_device *pdev)
struct resource *res;
struct tsa *tsa;
unsigned int i;
- u32 val;
int ret;
tsa = devm_kzalloc(&pdev->dev, sizeof(*tsa), GFP_KERNEL);
@@ -654,6 +997,18 @@ static int tsa_probe(struct platform_device *pdev)
return -ENOMEM;
tsa->dev = &pdev->dev;
+ tsa->version = (enum tsa_version)(uintptr_t)of_device_get_match_data(&pdev->dev);
+ switch (tsa->version) {
+ case TSA_CPM1:
+ dev_info(tsa->dev, "CPM1 version\n");
+ break;
+ case TSA_QE:
+ dev_info(tsa->dev, "QE version\n");
+ break;
+ default:
+ dev_err(tsa->dev, "Unknown version (%d)\n", tsa->version);
+ return -EINVAL;
+ }
for (i = 0; i < ARRAY_SIZE(tsa->serials); i++)
tsa->serials[i].id = i;
@@ -680,26 +1035,9 @@ static int tsa_probe(struct platform_device *pdev)
if (ret)
return ret;
- /* Set SIMODE */
- val = 0;
- if (tsa->tdm[0].is_enable)
- val |= TSA_SIMODE_TDMA(tsa->tdm[0].simode_tdm);
- if (tsa->tdm[1].is_enable)
- val |= TSA_SIMODE_TDMB(tsa->tdm[1].simode_tdm);
-
- tsa_clrsetbits32(tsa->si_regs + TSA_SIMODE,
- TSA_SIMODE_TDMA(TSA_SIMODE_TDM_MASK) |
- TSA_SIMODE_TDMB(TSA_SIMODE_TDM_MASK),
- val);
-
- /* Set SIGMR */
- val = (tsa->tdms == BIT(TSA_TDMA)) ?
- TSA_SIGMR_RDM_STATIC_TDMA : TSA_SIGMR_RDM_STATIC_TDMAB;
- if (tsa->tdms & BIT(TSA_TDMA))
- val |= TSA_SIGMR_ENA;
- if (tsa->tdms & BIT(TSA_TDMB))
- val |= TSA_SIGMR_ENB;
- tsa_write8(tsa->si_regs + TSA_SIGMR, val);
+ ret = tsa_setup(tsa);
+ if (ret)
+ return ret;
platform_set_drvdata(pdev, tsa);
@@ -711,7 +1049,7 @@ static void tsa_remove(struct platform_device *pdev)
struct tsa *tsa = platform_get_drvdata(pdev);
int i;
- for (i = 0; i < 2; i++) {
+ for (i = 0; i < ARRAY_SIZE(tsa->tdm); i++) {
if (tsa->tdm[i].l1rsync_clk) {
clk_disable_unprepare(tsa->tdm[i].l1rsync_clk);
clk_put(tsa->tdm[i].l1rsync_clk);
@@ -732,7 +1070,12 @@ static void tsa_remove(struct platform_device *pdev)
}
static const struct of_device_id tsa_id_table[] = {
- { .compatible = "fsl,cpm1-tsa" },
+#if IS_ENABLED(CONFIG_CPM1)
+ { .compatible = "fsl,cpm1-tsa", .data = (void *)TSA_CPM1 },
+#endif
+#if IS_ENABLED(CONFIG_QUICC_ENGINE)
+ { .compatible = "fsl,qe-tsa", .data = (void *)TSA_QE },
+#endif
{} /* sentinel */
};
MODULE_DEVICE_TABLE(of, tsa_id_table);
@@ -841,5 +1184,5 @@ struct tsa_serial *devm_tsa_serial_get_byphandle(struct device *dev,
EXPORT_SYMBOL(devm_tsa_serial_get_byphandle);
MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
-MODULE_DESCRIPTION("CPM TSA driver");
+MODULE_DESCRIPTION("CPM/QE TSA driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/soc/fsl/qe/tsa.h b/drivers/soc/fsl/qe/tsa.h
index d9df89b6da3e..da137bc0f49b 100644
--- a/drivers/soc/fsl/qe/tsa.h
+++ b/drivers/soc/fsl/qe/tsa.h
@@ -39,4 +39,7 @@ struct tsa_serial_info {
/* Get information */
int tsa_serial_get_info(struct tsa_serial *tsa_serial, struct tsa_serial_info *info);
+/* Get serial number */
+int tsa_serial_get_num(struct tsa_serial *tsa_serial);
+
#endif /* __SOC_FSL_TSA_H__ */
diff --git a/drivers/soc/fsl/qe/ucc.c b/drivers/soc/fsl/qe/ucc.c
index 21dbcd787cd5..892aa5931d5b 100644
--- a/drivers/soc/fsl/qe/ucc.c
+++ b/drivers/soc/fsl/qe/ucc.c
@@ -114,6 +114,7 @@ int ucc_mux_set_grant_tsa_bkpt(unsigned int ucc_num, int set, u32 mask)
return 0;
}
+EXPORT_SYMBOL(ucc_mux_set_grant_tsa_bkpt);
int ucc_set_qe_mux_rxtx(unsigned int ucc_num, enum qe_clock clock,
enum comm_dir mode)
diff --git a/drivers/soc/mediatek/mtk-mutex.c b/drivers/soc/mediatek/mtk-mutex.c
index 01b129caf1eb..5250c1d702eb 100644
--- a/drivers/soc/mediatek/mtk-mutex.c
+++ b/drivers/soc/mediatek/mtk-mutex.c
@@ -327,11 +327,11 @@ enum mtk_mutex_sof_id {
};
struct mtk_mutex_data {
- const unsigned int *mutex_mod;
- const unsigned int *mutex_sof;
- const unsigned int mutex_mod_reg;
- const unsigned int mutex_sof_reg;
- const unsigned int *mutex_table_mod;
+ const u8 *mutex_mod;
+ const u8 *mutex_table_mod;
+ const u16 *mutex_sof;
+ const u16 mutex_mod_reg;
+ const u16 mutex_sof_reg;
const bool no_clk;
};
@@ -345,7 +345,7 @@ struct mtk_mutex_ctx {
struct cmdq_client_reg cmdq_reg;
};
-static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_BLS] = MT2701_MUTEX_MOD_DISP_BLS,
[DDP_COMPONENT_COLOR0] = MT2701_MUTEX_MOD_DISP_COLOR,
[DDP_COMPONENT_OVL0] = MT2701_MUTEX_MOD_DISP_OVL,
@@ -354,7 +354,7 @@ static const unsigned int mt2701_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_WDMA0] = MT2701_MUTEX_MOD_DISP_WDMA,
};
-static const unsigned int mt2712_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt2712_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT2712_MUTEX_MOD_DISP_AAL0,
[DDP_COMPONENT_AAL1] = MT2712_MUTEX_MOD2_DISP_AAL1,
[DDP_COMPONENT_COLOR0] = MT2712_MUTEX_MOD_DISP_COLOR0,
@@ -374,7 +374,7 @@ static const unsigned int mt2712_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_WDMA1] = MT2712_MUTEX_MOD_DISP_WDMA1,
};
-static const unsigned int mt8167_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt8167_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT8167_MUTEX_MOD_DISP_AAL,
[DDP_COMPONENT_CCORR] = MT8167_MUTEX_MOD_DISP_CCORR,
[DDP_COMPONENT_COLOR0] = MT8167_MUTEX_MOD_DISP_COLOR,
@@ -389,7 +389,7 @@ static const unsigned int mt8167_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_WDMA0] = MT8167_MUTEX_MOD_DISP_WDMA0,
};
-static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT8173_MUTEX_MOD_DISP_AAL,
[DDP_COMPONENT_COLOR0] = MT8173_MUTEX_MOD_DISP_COLOR0,
[DDP_COMPONENT_COLOR1] = MT8173_MUTEX_MOD_DISP_COLOR1,
@@ -407,7 +407,7 @@ static const unsigned int mt8173_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_WDMA1] = MT8173_MUTEX_MOD_DISP_WDMA1,
};
-static const unsigned int mt8183_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt8183_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT8183_MUTEX_MOD_DISP_AAL0,
[DDP_COMPONENT_CCORR] = MT8183_MUTEX_MOD_DISP_CCORR0,
[DDP_COMPONENT_COLOR0] = MT8183_MUTEX_MOD_DISP_COLOR0,
@@ -421,7 +421,7 @@ static const unsigned int mt8183_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_WDMA0] = MT8183_MUTEX_MOD_DISP_WDMA0,
};
-static const unsigned int mt8183_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
+static const u8 mt8183_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_RDMA0] = MT8183_MUTEX_MOD_MDP_RDMA0,
[MUTEX_MOD_IDX_MDP_RSZ0] = MT8183_MUTEX_MOD_MDP_RSZ0,
[MUTEX_MOD_IDX_MDP_RSZ1] = MT8183_MUTEX_MOD_MDP_RSZ1,
@@ -432,7 +432,7 @@ static const unsigned int mt8183_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_CCORR0] = MT8183_MUTEX_MOD_MDP_CCORR0,
};
-static const unsigned int mt8186_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt8186_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT8186_MUTEX_MOD_DISP_AAL0,
[DDP_COMPONENT_CCORR] = MT8186_MUTEX_MOD_DISP_CCORR0,
[DDP_COMPONENT_COLOR0] = MT8186_MUTEX_MOD_DISP_COLOR0,
@@ -445,7 +445,7 @@ static const unsigned int mt8186_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_RDMA1] = MT8186_MUTEX_MOD_DISP_RDMA1,
};
-static const unsigned int mt8186_mdp_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
+static const u8 mt8186_mdp_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_RDMA0] = MT8186_MUTEX_MOD_MDP_RDMA0,
[MUTEX_MOD_IDX_MDP_RSZ0] = MT8186_MUTEX_MOD_MDP_RSZ0,
[MUTEX_MOD_IDX_MDP_RSZ1] = MT8186_MUTEX_MOD_MDP_RSZ1,
@@ -456,7 +456,7 @@ static const unsigned int mt8186_mdp_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_COLOR0] = MT8186_MUTEX_MOD_MDP_COLOR0,
};
-static const unsigned int mt8188_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt8188_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_OVL0] = MT8188_MUTEX_MOD_DISP_OVL0,
[DDP_COMPONENT_WDMA0] = MT8188_MUTEX_MOD_DISP_WDMA0,
[DDP_COMPONENT_RDMA0] = MT8188_MUTEX_MOD_DISP_RDMA0,
@@ -496,7 +496,7 @@ static const unsigned int mt8188_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_MERGE5] = MT8188_MUTEX_MOD_DISP1_VPP_MERGE4,
};
-static const unsigned int mt8188_mdp_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
+static const u8 mt8188_mdp_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_RDMA0] = MT8195_MUTEX_MOD_MDP_RDMA0,
[MUTEX_MOD_IDX_MDP_RDMA2] = MT8195_MUTEX_MOD_MDP_RDMA2,
[MUTEX_MOD_IDX_MDP_RDMA3] = MT8195_MUTEX_MOD_MDP_RDMA3,
@@ -530,7 +530,7 @@ static const unsigned int mt8188_mdp_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_WROT3] = MT8195_MUTEX_MOD_MDP_WROT3,
};
-static const unsigned int mt8192_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt8192_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT8192_MUTEX_MOD_DISP_AAL0,
[DDP_COMPONENT_CCORR] = MT8192_MUTEX_MOD_DISP_CCORR0,
[DDP_COMPONENT_COLOR0] = MT8192_MUTEX_MOD_DISP_COLOR0,
@@ -544,7 +544,7 @@ static const unsigned int mt8192_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_RDMA4] = MT8192_MUTEX_MOD_DISP_RDMA4,
};
-static const unsigned int mt8195_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt8195_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_OVL0] = MT8195_MUTEX_MOD_DISP_OVL0,
[DDP_COMPONENT_WDMA0] = MT8195_MUTEX_MOD_DISP_WDMA0,
[DDP_COMPONENT_RDMA0] = MT8195_MUTEX_MOD_DISP_RDMA0,
@@ -575,7 +575,7 @@ static const unsigned int mt8195_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_DP_INTF1] = MT8195_MUTEX_MOD_DISP1_DP_INTF0,
};
-static const unsigned int mt8195_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
+static const u8 mt8195_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_RDMA0] = MT8195_MUTEX_MOD_MDP_RDMA0,
[MUTEX_MOD_IDX_MDP_RDMA1] = MT8195_MUTEX_MOD_MDP_RDMA1,
[MUTEX_MOD_IDX_MDP_RDMA2] = MT8195_MUTEX_MOD_MDP_RDMA2,
@@ -621,7 +621,7 @@ static const unsigned int mt8195_mutex_table_mod[MUTEX_MOD_IDX_MAX] = {
[MUTEX_MOD_IDX_MDP_WROT3] = MT8195_MUTEX_MOD_MDP_WROT3,
};
-static const unsigned int mt8365_mutex_mod[DDP_COMPONENT_ID_MAX] = {
+static const u8 mt8365_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_AAL0] = MT8365_MUTEX_MOD_DISP_AAL,
[DDP_COMPONENT_CCORR] = MT8365_MUTEX_MOD_DISP_CCORR,
[DDP_COMPONENT_COLOR0] = MT8365_MUTEX_MOD_DISP_COLOR0,
@@ -637,7 +637,7 @@ static const unsigned int mt8365_mutex_mod[DDP_COMPONENT_ID_MAX] = {
[DDP_COMPONENT_WDMA0] = MT8365_MUTEX_MOD_DISP_WDMA0,
};
-static const unsigned int mt2712_mutex_sof[DDP_MUTEX_SOF_MAX] = {
+static const u16 mt2712_mutex_sof[DDP_MUTEX_SOF_MAX] = {
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
[MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
[MUTEX_SOF_DSI1] = MUTEX_SOF_DSI1,
@@ -647,14 +647,14 @@ static const unsigned int mt2712_mutex_sof[DDP_MUTEX_SOF_MAX] = {
[MUTEX_SOF_DSI3] = MUTEX_SOF_DSI3,
};
-static const unsigned int mt6795_mutex_sof[DDP_MUTEX_SOF_MAX] = {
+static const u16 mt6795_mutex_sof[DDP_MUTEX_SOF_MAX] = {
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
[MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
[MUTEX_SOF_DSI1] = MUTEX_SOF_DSI1,
[MUTEX_SOF_DPI0] = MUTEX_SOF_DPI0,
};
-static const unsigned int mt8167_mutex_sof[DDP_MUTEX_SOF_MAX] = {
+static const u16 mt8167_mutex_sof[DDP_MUTEX_SOF_MAX] = {
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
[MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0,
[MUTEX_SOF_DPI0] = MT8167_MUTEX_SOF_DPI0,
@@ -662,13 +662,13 @@ static const unsigned int mt8167_mutex_sof[DDP_MUTEX_SOF_MAX] = {
};
/* Add EOF setting so overlay hardware can receive frame done irq */
-static const unsigned int mt8183_mutex_sof[DDP_MUTEX_SOF_MAX] = {
+static const u16 mt8183_mutex_sof[DDP_MUTEX_SOF_MAX] = {
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
[MUTEX_SOF_DSI0] = MUTEX_SOF_DSI0 | MT8183_MUTEX_EOF_DSI0,
[MUTEX_SOF_DPI0] = MT8183_MUTEX_SOF_DPI0 | MT8183_MUTEX_EOF_DPI0,
};
-static const unsigned int mt8186_mutex_sof[MUTEX_SOF_DSI3 + 1] = {
+static const u16 mt8186_mutex_sof[MUTEX_SOF_DSI3 + 1] = {
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
[MUTEX_SOF_DSI0] = MT8186_MUTEX_SOF_DSI0 | MT8186_MUTEX_EOF_DSI0,
[MUTEX_SOF_DPI0] = MT8186_MUTEX_SOF_DPI0 | MT8186_MUTEX_EOF_DPI0,
@@ -682,7 +682,7 @@ static const unsigned int mt8186_mutex_sof[MUTEX_SOF_DSI3 + 1] = {
* but also detect the error at end of frame(EAEOF) when EOF signal
* arrives.
*/
-static const unsigned int mt8188_mutex_sof[DDP_MUTEX_SOF_MAX] = {
+static const u16 mt8188_mutex_sof[DDP_MUTEX_SOF_MAX] = {
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
[MUTEX_SOF_DSI0] =
MT8188_MUTEX_SOF_DSI0 | MT8188_MUTEX_EOF_DSI0,
@@ -692,7 +692,7 @@ static const unsigned int mt8188_mutex_sof[DDP_MUTEX_SOF_MAX] = {
MT8188_MUTEX_SOF_DP_INTF1 | MT8188_MUTEX_EOF_DP_INTF1,
};
-static const unsigned int mt8195_mutex_sof[DDP_MUTEX_SOF_MAX] = {
+static const u16 mt8195_mutex_sof[DDP_MUTEX_SOF_MAX] = {
[MUTEX_SOF_SINGLE_MODE] = MUTEX_SOF_SINGLE_MODE,
[MUTEX_SOF_DSI0] = MT8195_MUTEX_SOF_DSI0 | MT8195_MUTEX_EOF_DSI0,
[MUTEX_SOF_DSI1] = MT8195_MUTEX_SOF_DSI1 | MT8195_MUTEX_EOF_DSI1,
diff --git a/drivers/soc/mediatek/mtk-pmic-wrap.c b/drivers/soc/mediatek/mtk-pmic-wrap.c
index efd9cae212dc..9fdc0ef79202 100644
--- a/drivers/soc/mediatek/mtk-pmic-wrap.c
+++ b/drivers/soc/mediatek/mtk-pmic-wrap.c
@@ -483,7 +483,7 @@ enum pwrap_regs {
PWRAP_MSB_FIRST,
};
-static int mt2701_regs[] = {
+static const int mt2701_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -569,7 +569,7 @@ static int mt2701_regs[] = {
[PWRAP_ADC_RDATA_ADDR2] = 0x154,
};
-static int mt6765_regs[] = {
+static const int mt6765_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -601,7 +601,7 @@ static int mt6765_regs[] = {
[PWRAP_DCM_DBC_PRD] = 0x1E0,
};
-static int mt6779_regs[] = {
+static const int mt6779_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -640,7 +640,7 @@ static int mt6779_regs[] = {
[PWRAP_WACS2_VLDCLR] = 0xC28,
};
-static int mt6795_regs[] = {
+static const int mt6795_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -725,7 +725,7 @@ static int mt6795_regs[] = {
[PWRAP_EXT_CK] = 0x14c,
};
-static int mt6797_regs[] = {
+static const int mt6797_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -758,7 +758,7 @@ static int mt6797_regs[] = {
[PWRAP_DCM_DBC_PRD] = 0x1D4,
};
-static int mt6873_regs[] = {
+static const int mt6873_regs[] = {
[PWRAP_INIT_DONE2] = 0x0,
[PWRAP_TIMER_EN] = 0x3E0,
[PWRAP_INT_EN] = 0x448,
@@ -769,7 +769,7 @@ static int mt6873_regs[] = {
[PWRAP_WACS2_RDATA] = 0xCA8,
};
-static int mt7622_regs[] = {
+static const int mt7622_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -881,7 +881,7 @@ static int mt7622_regs[] = {
[PWRAP_SPI2_CTRL] = 0x244,
};
-static int mt8135_regs[] = {
+static const int mt8135_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -954,7 +954,7 @@ static int mt8135_regs[] = {
[PWRAP_DCM_DBC_PRD] = 0x160,
};
-static int mt8173_regs[] = {
+static const int mt8173_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -1036,7 +1036,7 @@ static int mt8173_regs[] = {
[PWRAP_DCM_DBC_PRD] = 0x148,
};
-static int mt8183_regs[] = {
+static const int mt8183_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -1087,7 +1087,7 @@ static int mt8183_regs[] = {
[PWRAP_WACS2_VLDCLR] = 0xC28,
};
-static int mt8195_regs[] = {
+static const int mt8195_regs[] = {
[PWRAP_INIT_DONE2] = 0x0,
[PWRAP_STAUPD_CTRL] = 0x4C,
[PWRAP_TIMER_EN] = 0x3E4,
@@ -1104,7 +1104,7 @@ static int mt8195_regs[] = {
[PWRAP_WACS2_RDATA] = 0x8A8,
};
-static int mt8365_regs[] = {
+static const int mt8365_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -1166,7 +1166,7 @@ static int mt8365_regs[] = {
[PWRAP_WDT_SRC_EN_1] = 0xf8,
};
-static int mt8516_regs[] = {
+static const int mt8516_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -1251,7 +1251,7 @@ static int mt8516_regs[] = {
[PWRAP_MSB_FIRST] = 0x170,
};
-static int mt8186_regs[] = {
+static const int mt8186_regs[] = {
[PWRAP_MUX_SEL] = 0x0,
[PWRAP_WRAP_EN] = 0x4,
[PWRAP_DIO_EN] = 0x8,
@@ -1366,10 +1366,6 @@ struct pmic_wrapper {
struct regmap *regmap;
const struct pmic_wrapper_type *master;
const struct pwrap_slv_type *slave;
- struct clk *clk_spi;
- struct clk *clk_wrap;
- struct clk *clk_sys;
- struct clk *clk_tmr;
struct reset_control *rstc;
struct reset_control *rstc_bridge;
@@ -1377,7 +1373,7 @@ struct pmic_wrapper {
};
struct pmic_wrapper_type {
- int *regs;
+ const int *regs;
enum pwrap_type type;
u32 arb_en_all;
u32 int_en_all;
@@ -2397,7 +2393,7 @@ static const struct pmic_wrapper_type pwrap_mt8183 = {
.init_soc_specific = pwrap_mt8183_init_soc_specific,
};
-static struct pmic_wrapper_type pwrap_mt8195 = {
+static const struct pmic_wrapper_type pwrap_mt8195 = {
.regs = mt8195_regs,
.type = PWRAP_MT8195,
.arb_en_all = 0x777f, /* NEED CONFIRM */
@@ -2423,7 +2419,7 @@ static const struct pmic_wrapper_type pwrap_mt8365 = {
.init_soc_specific = NULL,
};
-static struct pmic_wrapper_type pwrap_mt8516 = {
+static const struct pmic_wrapper_type pwrap_mt8516 = {
.regs = mt8516_regs,
.type = PWRAP_MT8516,
.arb_en_all = 0xff,
@@ -2435,7 +2431,7 @@ static struct pmic_wrapper_type pwrap_mt8516 = {
.init_soc_specific = NULL,
};
-static struct pmic_wrapper_type pwrap_mt8186 = {
+static const struct pmic_wrapper_type pwrap_mt8186 = {
.regs = mt8186_regs,
.type = PWRAP_MT8186,
.arb_en_all = 0xfb27f,
@@ -2472,6 +2468,7 @@ static int pwrap_probe(struct platform_device *pdev)
int ret, irq;
u32 mask_done;
struct pmic_wrapper *wrp;
+ struct clk_bulk_data *clk;
struct device_node *np = pdev->dev.of_node;
const struct of_device_id *of_slave_id = NULL;
@@ -2521,49 +2518,10 @@ static int pwrap_probe(struct platform_device *pdev)
}
}
- wrp->clk_spi = devm_clk_get(wrp->dev, "spi");
- if (IS_ERR(wrp->clk_spi)) {
- dev_dbg(wrp->dev, "failed to get clock: %ld\n",
- PTR_ERR(wrp->clk_spi));
- return PTR_ERR(wrp->clk_spi);
- }
-
- wrp->clk_wrap = devm_clk_get(wrp->dev, "wrap");
- if (IS_ERR(wrp->clk_wrap)) {
- dev_dbg(wrp->dev, "failed to get clock: %ld\n",
- PTR_ERR(wrp->clk_wrap));
- return PTR_ERR(wrp->clk_wrap);
- }
-
- wrp->clk_sys = devm_clk_get_optional(wrp->dev, "sys");
- if (IS_ERR(wrp->clk_sys)) {
- return dev_err_probe(wrp->dev, PTR_ERR(wrp->clk_sys),
- "failed to get clock: %pe\n",
- wrp->clk_sys);
- }
-
- wrp->clk_tmr = devm_clk_get_optional(wrp->dev, "tmr");
- if (IS_ERR(wrp->clk_tmr)) {
- return dev_err_probe(wrp->dev, PTR_ERR(wrp->clk_tmr),
- "failed to get clock: %pe\n",
- wrp->clk_tmr);
- }
-
- ret = clk_prepare_enable(wrp->clk_spi);
- if (ret)
- return ret;
-
- ret = clk_prepare_enable(wrp->clk_wrap);
+ ret = devm_clk_bulk_get_all_enable(wrp->dev, &clk);
if (ret)
- goto err_out1;
-
- ret = clk_prepare_enable(wrp->clk_sys);
- if (ret)
- goto err_out2;
-
- ret = clk_prepare_enable(wrp->clk_tmr);
- if (ret)
- goto err_out3;
+ return dev_err_probe(wrp->dev, ret,
+ "failed to get clocks\n");
/* Enable internal dynamic clock */
if (HAS_CAP(wrp->master->caps, PWRAP_CAP_DCM)) {
@@ -2579,7 +2537,7 @@ static int pwrap_probe(struct platform_device *pdev)
ret = pwrap_init(wrp);
if (ret) {
dev_dbg(wrp->dev, "init failed with %d\n", ret);
- goto err_out4;
+ return ret;
}
}
@@ -2592,8 +2550,7 @@ static int pwrap_probe(struct platform_device *pdev)
if (!(pwrap_readl(wrp, PWRAP_WACS2_RDATA) & mask_done)) {
dev_dbg(wrp->dev, "initialization isn't finished\n");
- ret = -ENODEV;
- goto err_out4;
+ return -ENODEV;
}
/* Initialize watchdog, may not be done by the bootloader */
@@ -2622,42 +2579,27 @@ static int pwrap_probe(struct platform_device *pdev)
pwrap_writel(wrp, wrp->master->int1_en_all, PWRAP_INT1_EN);
irq = platform_get_irq(pdev, 0);
- if (irq < 0) {
- ret = irq;
- goto err_out2;
- }
+ if (irq < 0)
+ return irq;
ret = devm_request_irq(wrp->dev, irq, pwrap_interrupt,
IRQF_TRIGGER_HIGH,
"mt-pmic-pwrap", wrp);
if (ret)
- goto err_out4;
+ return ret;
wrp->regmap = devm_regmap_init(wrp->dev, NULL, wrp, wrp->slave->regops->regmap);
- if (IS_ERR(wrp->regmap)) {
- ret = PTR_ERR(wrp->regmap);
- goto err_out2;
- }
+ if (IS_ERR(wrp->regmap))
+ return PTR_ERR(wrp->regmap);
ret = of_platform_populate(np, NULL, NULL, wrp->dev);
if (ret) {
dev_dbg(wrp->dev, "failed to create child devices at %pOF\n",
np);
- goto err_out4;
+ return ret;
}
return 0;
-
-err_out4:
- clk_disable_unprepare(wrp->clk_tmr);
-err_out3:
- clk_disable_unprepare(wrp->clk_sys);
-err_out2:
- clk_disable_unprepare(wrp->clk_wrap);
-err_out1:
- clk_disable_unprepare(wrp->clk_spi);
-
- return ret;
}
static struct platform_driver pwrap_drv = {
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index 7f02f0525933..74b9121240f8 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -77,7 +77,7 @@ config QCOM_PD_MAPPER
select QCOM_QMI_HELPERS
select QCOM_PDR_MSG
select AUXILIARY_BUS
- depends on NET && QRTR
+ depends on NET && QRTR && (ARCH_QCOM || COMPILE_TEST)
default QCOM_RPROC_COMMON
help
The Protection Domain Mapper maps registered services to the domains
diff --git a/drivers/soc/qcom/Makefile b/drivers/soc/qcom/Makefile
index d3560f861085..acbca2ab5cc2 100644
--- a/drivers/soc/qcom/Makefile
+++ b/drivers/soc/qcom/Makefile
@@ -25,6 +25,7 @@ qcom_rpmh-y += rpmh.o
obj-$(CONFIG_QCOM_SMD_RPM) += rpm-proc.o smd-rpm.o
obj-$(CONFIG_QCOM_SMEM) += smem.o
obj-$(CONFIG_QCOM_SMEM_STATE) += smem_state.o
+CFLAGS_smp2p.o := -I$(src)
obj-$(CONFIG_QCOM_SMP2P) += smp2p.o
obj-$(CONFIG_QCOM_SMSM) += smsm.o
obj-$(CONFIG_QCOM_SOCINFO) += socinfo.o
diff --git a/drivers/soc/qcom/apr.c b/drivers/soc/qcom/apr.c
index 4fbff3a890e2..a956c407ce03 100644
--- a/drivers/soc/qcom/apr.c
+++ b/drivers/soc/qcom/apr.c
@@ -485,11 +485,10 @@ static int of_apr_add_pd_lookups(struct device *dev)
{
const char *service_name, *service_path;
struct packet_router *apr = dev_get_drvdata(dev);
- struct device_node *node;
struct pdr_service *pds;
int ret;
- for_each_child_of_node(dev->of_node, node) {
+ for_each_child_of_node_scoped(dev->of_node, node) {
ret = of_property_read_string_index(node, "qcom,protection-domain",
0, &service_name);
if (ret < 0)
@@ -499,14 +498,12 @@ static int of_apr_add_pd_lookups(struct device *dev)
1, &service_path);
if (ret < 0) {
dev_err(dev, "pdr service path missing: %d\n", ret);
- of_node_put(node);
return ret;
}
pds = pdr_add_lookup(apr->pdr, service_name, service_path);
if (IS_ERR(pds) && PTR_ERR(pds) != -EALREADY) {
dev_err(dev, "pdr add lookup failed: %ld\n", PTR_ERR(pds));
- of_node_put(node);
return PTR_ERR(pds);
}
}
diff --git a/drivers/soc/qcom/cmd-db.c b/drivers/soc/qcom/cmd-db.c
index d84572662017..ae66c2623d25 100644
--- a/drivers/soc/qcom/cmd-db.c
+++ b/drivers/soc/qcom/cmd-db.c
@@ -349,7 +349,7 @@ static int cmd_db_dev_probe(struct platform_device *pdev)
return -EINVAL;
}
- cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WB);
+ cmd_db_header = memremap(rmem->base, rmem->size, MEMREMAP_WC);
if (!cmd_db_header) {
ret = -ENOMEM;
cmd_db_header = NULL;
diff --git a/drivers/soc/qcom/icc-bwmon.c b/drivers/soc/qcom/icc-bwmon.c
index e7851974084b..f9235bc3aa3b 100644
--- a/drivers/soc/qcom/icc-bwmon.c
+++ b/drivers/soc/qcom/icc-bwmon.c
@@ -17,6 +17,8 @@
#include <linux/pm_opp.h>
#include <linux/regmap.h>
#include <linux/sizes.h>
+#define CREATE_TRACE_POINTS
+#include "trace_icc-bwmon.h"
/*
* The BWMON samples data throughput within 'sample_ms' time. With three
@@ -645,9 +647,10 @@ static irqreturn_t bwmon_intr_thread(int irq, void *dev_id)
struct icc_bwmon *bwmon = dev_id;
unsigned int irq_enable = 0;
struct dev_pm_opp *opp, *target_opp;
- unsigned int bw_kbps, up_kbps, down_kbps;
+ unsigned int bw_kbps, up_kbps, down_kbps, meas_kbps;
bw_kbps = bwmon->target_kbps;
+ meas_kbps = bwmon->target_kbps;
target_opp = dev_pm_opp_find_bw_ceil(bwmon->dev, &bw_kbps, 0);
if (IS_ERR(target_opp) && PTR_ERR(target_opp) == -ERANGE)
@@ -679,6 +682,7 @@ static irqreturn_t bwmon_intr_thread(int irq, void *dev_id)
bwmon_clear_irq(bwmon);
bwmon_enable(bwmon, irq_enable);
+ trace_qcom_bwmon_update(dev_name(bwmon->dev), meas_kbps, up_kbps, down_kbps);
if (bwmon->target_kbps == bwmon->current_kbps)
goto out;
diff --git a/drivers/soc/qcom/ice.c b/drivers/soc/qcom/ice.c
index fbab7fe5c652..50be7a9274a1 100644
--- a/drivers/soc/qcom/ice.c
+++ b/drivers/soc/qcom/ice.c
@@ -8,6 +8,7 @@
*/
#include <linux/bitfield.h>
+#include <linux/cleanup.h>
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/iopoll.h>
@@ -265,7 +266,6 @@ struct qcom_ice *of_qcom_ice_get(struct device *dev)
{
struct platform_device *pdev = to_platform_device(dev);
struct qcom_ice *ice;
- struct device_node *node;
struct resource *res;
void __iomem *base;
@@ -292,15 +292,15 @@ struct qcom_ice *of_qcom_ice_get(struct device *dev)
* (legacy DT binding), then it must at least provide a phandle
* to the ICE devicetree node, otherwise ICE is not supported.
*/
- node = of_parse_phandle(dev->of_node, "qcom,ice", 0);
+ struct device_node *node __free(device_node) = of_parse_phandle(dev->of_node,
+ "qcom,ice", 0);
if (!node)
return NULL;
pdev = of_find_device_by_node(node);
if (!pdev) {
dev_err(dev, "Cannot find device node %s\n", node->name);
- ice = ERR_PTR(-EPROBE_DEFER);
- goto out;
+ return ERR_PTR(-EPROBE_DEFER);
}
ice = platform_get_drvdata(pdev);
@@ -308,8 +308,7 @@ struct qcom_ice *of_qcom_ice_get(struct device *dev)
dev_err(dev, "Cannot get ice instance from %s\n",
dev_name(&pdev->dev));
platform_device_put(pdev);
- ice = ERR_PTR(-EPROBE_DEFER);
- goto out;
+ return ERR_PTR(-EPROBE_DEFER);
}
ice->link = device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER);
@@ -321,9 +320,6 @@ struct qcom_ice *of_qcom_ice_get(struct device *dev)
ice = ERR_PTR(-EINVAL);
}
-out:
- of_node_put(node);
-
return ice;
}
EXPORT_SYMBOL_GPL(of_qcom_ice_get);
diff --git a/drivers/soc/qcom/llcc-qcom.c b/drivers/soc/qcom/llcc-qcom.c
index 37e11e501728..8fa4ffd3a9b5 100644
--- a/drivers/soc/qcom/llcc-qcom.c
+++ b/drivers/soc/qcom/llcc-qcom.c
@@ -453,26 +453,24 @@ static const struct llcc_slice_config qdu1000_data_8ch[] = {
};
static const struct llcc_slice_config x1e80100_data[] = {
- {LLCC_CPUSS, 1, 6144, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_VIDSC0, 2, 512, 3, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_AUDIO, 6, 3072, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_CPUSS, 1, 6144, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_VIDSC0, 2, 512, 4, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_AUDIO, 6, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{LLCC_CMPT, 10, 6144, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_GPUHTW, 11, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_GPU, 9, 4096, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_MMUHWT, 18, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_GPUHTW, 11, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_GPU, 9, 4608, 1, 0, 0xFFF, 0x0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_MMUHWT, 18, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{LLCC_AUDHW, 22, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_CVP, 8, 512, 3, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_WRCACHE, 31, 512, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_CAMEXP1, 7, 3072, 2, 1, 0xFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_LCPDARE, 30, 512, 3, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_CVP, 8, 512, 4, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_WRCACHE, 31, 1024, 1, 1, 0xFFF, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_CAMEXP0, 4, 256, 4, 1, 0x3, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_CAMEXP1, 7, 3072, 3, 1, 0xFFC, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_LCPDARE, 30, 512, 3, 1, 0xFFF, 0x0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0},
{LLCC_AENPU, 3, 3072, 1, 1, 0xFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_ISLAND1, 12, 512, 7, 1, 0x1, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_ISLAND2, 13, 512, 7, 1, 0x2, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_ISLAND3, 14, 512, 7, 1, 0x3, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_ISLAND4, 15, 512, 7, 1, 0x4, 0x0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_CAMEXP2, 19, 3072, 3, 1, 0xFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_CAMEXP3, 20, 3072, 3, 1, 0xFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
- {LLCC_CAMEXP4, 21, 3072, 3, 1, 0xFFF, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_ISLAND1, 12, 2048, 7, 1, 0x0, 0xF, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_CAMEXP2, 19, 3072, 3, 1, 0xFFC, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_CAMEXP3, 20, 3072, 2, 1, 0xFFC, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
+ {LLCC_CAMEXP4, 21, 3072, 2, 1, 0xFFC, 0x0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
};
static const struct llcc_edac_reg_offset llcc_v1_edac_reg_offset = {
diff --git a/drivers/soc/qcom/ocmem.c b/drivers/soc/qcom/ocmem.c
index 6b6dd80cbc0f..ff8df7d75d6b 100644
--- a/drivers/soc/qcom/ocmem.c
+++ b/drivers/soc/qcom/ocmem.c
@@ -186,23 +186,20 @@ static void update_range(struct ocmem *ocmem, struct ocmem_buf *buf,
struct ocmem *of_get_ocmem(struct device *dev)
{
struct platform_device *pdev;
- struct device_node *devnode;
struct ocmem *ocmem;
- devnode = of_parse_phandle(dev->of_node, "sram", 0);
+ struct device_node *devnode __free(device_node) = of_parse_phandle(dev->of_node,
+ "sram", 0);
if (!devnode || !devnode->parent) {
dev_err(dev, "Cannot look up sram phandle\n");
- of_node_put(devnode);
return ERR_PTR(-ENODEV);
}
pdev = of_find_device_by_node(devnode->parent);
if (!pdev) {
dev_err(dev, "Cannot find device node %s\n", devnode->name);
- of_node_put(devnode);
return ERR_PTR(-EPROBE_DEFER);
}
- of_node_put(devnode);
ocmem = platform_get_drvdata(pdev);
if (!ocmem) {
diff --git a/drivers/soc/qcom/pmic_glink.c b/drivers/soc/qcom/pmic_glink.c
index 9ebc0ba35947..9606222993fd 100644
--- a/drivers/soc/qcom/pmic_glink.c
+++ b/drivers/soc/qcom/pmic_glink.c
@@ -66,15 +66,14 @@ static void _devm_pmic_glink_release_client(struct device *dev, void *res)
spin_unlock_irqrestore(&pg->client_lock, flags);
}
-struct pmic_glink_client *devm_pmic_glink_register_client(struct device *dev,
- unsigned int id,
- void (*cb)(const void *, size_t, void *),
- void (*pdr)(void *, int),
- void *priv)
+struct pmic_glink_client *devm_pmic_glink_client_alloc(struct device *dev,
+ unsigned int id,
+ void (*cb)(const void *, size_t, void *),
+ void (*pdr)(void *, int),
+ void *priv)
{
struct pmic_glink_client *client;
struct pmic_glink *pg = dev_get_drvdata(dev->parent);
- unsigned long flags;
client = devres_alloc(_devm_pmic_glink_release_client, sizeof(*client), GFP_KERNEL);
if (!client)
@@ -85,6 +84,18 @@ struct pmic_glink_client *devm_pmic_glink_register_client(struct device *dev,
client->cb = cb;
client->pdr_notify = pdr;
client->priv = priv;
+ INIT_LIST_HEAD(&client->node);
+
+ devres_add(dev, client);
+
+ return client;
+}
+EXPORT_SYMBOL_GPL(devm_pmic_glink_client_alloc);
+
+void pmic_glink_client_register(struct pmic_glink_client *client)
+{
+ struct pmic_glink *pg = client->pg;
+ unsigned long flags;
mutex_lock(&pg->state_lock);
spin_lock_irqsave(&pg->client_lock, flags);
@@ -95,17 +106,22 @@ struct pmic_glink_client *devm_pmic_glink_register_client(struct device *dev,
spin_unlock_irqrestore(&pg->client_lock, flags);
mutex_unlock(&pg->state_lock);
- devres_add(dev, client);
-
- return client;
}
-EXPORT_SYMBOL_GPL(devm_pmic_glink_register_client);
+EXPORT_SYMBOL_GPL(pmic_glink_client_register);
int pmic_glink_send(struct pmic_glink_client *client, void *data, size_t len)
{
struct pmic_glink *pg = client->pg;
+ int ret;
- return rpmsg_send(pg->ept, data, len);
+ mutex_lock(&pg->state_lock);
+ if (!pg->ept)
+ ret = -ECONNRESET;
+ else
+ ret = rpmsg_send(pg->ept, data, len);
+ mutex_unlock(&pg->state_lock);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(pmic_glink_send);
@@ -175,7 +191,7 @@ static void pmic_glink_state_notify_clients(struct pmic_glink *pg)
if (pg->pdr_state == SERVREG_SERVICE_STATE_UP && pg->ept)
new_state = SERVREG_SERVICE_STATE_UP;
} else {
- if (pg->pdr_state == SERVREG_SERVICE_STATE_UP && pg->ept)
+ if (pg->pdr_state == SERVREG_SERVICE_STATE_DOWN || !pg->ept)
new_state = SERVREG_SERVICE_STATE_DOWN;
}
diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c
index 1e0808b3cb93..463b1c528831 100644
--- a/drivers/soc/qcom/pmic_glink_altmode.c
+++ b/drivers/soc/qcom/pmic_glink_altmode.c
@@ -520,12 +520,17 @@ static int pmic_glink_altmode_probe(struct auxiliary_device *adev,
return ret;
}
- altmode->client = devm_pmic_glink_register_client(dev,
- altmode->owner_id,
- pmic_glink_altmode_callback,
- pmic_glink_altmode_pdr_notify,
- altmode);
- return PTR_ERR_OR_ZERO(altmode->client);
+ altmode->client = devm_pmic_glink_client_alloc(dev,
+ altmode->owner_id,
+ pmic_glink_altmode_callback,
+ pmic_glink_altmode_pdr_notify,
+ altmode);
+ if (IS_ERR(altmode->client))
+ return PTR_ERR(altmode->client);
+
+ pmic_glink_client_register(altmode->client);
+
+ return 0;
}
static const struct auxiliary_device_id pmic_glink_altmode_id_table[] = {
diff --git a/drivers/soc/qcom/qcom-pbs.c b/drivers/soc/qcom/qcom-pbs.c
index 6af49b5060e5..77a70d3d0d0b 100644
--- a/drivers/soc/qcom/qcom-pbs.c
+++ b/drivers/soc/qcom/qcom-pbs.c
@@ -3,6 +3,7 @@
* Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
*/
+#include <linux/cleanup.h>
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/module.h>
@@ -148,11 +149,11 @@ EXPORT_SYMBOL_GPL(qcom_pbs_trigger_event);
*/
struct pbs_dev *get_pbs_client_device(struct device *dev)
{
- struct device_node *pbs_dev_node;
struct platform_device *pdev;
struct pbs_dev *pbs;
- pbs_dev_node = of_parse_phandle(dev->of_node, "qcom,pbs", 0);
+ struct device_node *pbs_dev_node __free(device_node) = of_parse_phandle(dev->of_node,
+ "qcom,pbs", 0);
if (!pbs_dev_node) {
dev_err(dev, "Missing qcom,pbs property\n");
return ERR_PTR(-ENODEV);
@@ -161,28 +162,23 @@ struct pbs_dev *get_pbs_client_device(struct device *dev)
pdev = of_find_device_by_node(pbs_dev_node);
if (!pdev) {
dev_err(dev, "Unable to find PBS dev_node\n");
- pbs = ERR_PTR(-EPROBE_DEFER);
- goto out;
+ return ERR_PTR(-EPROBE_DEFER);
}
pbs = platform_get_drvdata(pdev);
if (!pbs) {
dev_err(dev, "Cannot get pbs instance from %s\n", dev_name(&pdev->dev));
platform_device_put(pdev);
- pbs = ERR_PTR(-EPROBE_DEFER);
- goto out;
+ return ERR_PTR(-EPROBE_DEFER);
}
pbs->link = device_link_add(dev, &pdev->dev, DL_FLAG_AUTOREMOVE_SUPPLIER);
if (!pbs->link) {
dev_err(&pdev->dev, "Failed to create device link to consumer %s\n", dev_name(dev));
platform_device_put(pdev);
- pbs = ERR_PTR(-EINVAL);
- goto out;
+ return ERR_PTR(-EINVAL);
}
-out:
- of_node_put(pbs_dev_node);
return pbs;
}
EXPORT_SYMBOL_GPL(get_pbs_client_device);
diff --git a/drivers/soc/qcom/qcom_aoss.c b/drivers/soc/qcom/qcom_aoss.c
index ca2f6b7629ce..60af26667bce 100644
--- a/drivers/soc/qcom/qcom_aoss.c
+++ b/drivers/soc/qcom/qcom_aoss.c
@@ -394,7 +394,7 @@ static int qmp_cooling_device_add(struct qmp *qmp,
static int qmp_cooling_devices_register(struct qmp *qmp)
{
- struct device_node *np, *child;
+ struct device_node *np;
int count = 0;
int ret;
@@ -407,15 +407,13 @@ static int qmp_cooling_devices_register(struct qmp *qmp)
if (!qmp->cooling_devs)
return -ENOMEM;
- for_each_available_child_of_node(np, child) {
+ for_each_available_child_of_node_scoped(np, child) {
if (!of_property_present(child, "#cooling-cells"))
continue;
ret = qmp_cooling_device_add(qmp, &qmp->cooling_devs[count++],
child);
- if (ret) {
- of_node_put(child);
+ if (ret)
goto unroll;
- }
}
if (!count)
diff --git a/drivers/soc/qcom/qcom_pd_mapper.c b/drivers/soc/qcom/qcom_pd_mapper.c
index a4c007080665..c940f4da28ed 100644
--- a/drivers/soc/qcom/qcom_pd_mapper.c
+++ b/drivers/soc/qcom/qcom_pd_mapper.c
@@ -517,12 +517,25 @@ static const struct qcom_pdm_domain_data *sm8550_domains[] = {
NULL,
};
-static const struct of_device_id qcom_pdm_domains[] = {
+static const struct qcom_pdm_domain_data *x1e80100_domains[] = {
+ &adsp_audio_pd,
+ &adsp_root_pd,
+ &adsp_charger_pd,
+ &adsp_sensor_pd,
+ &cdsp_root_pd,
+ NULL,
+};
+
+static const struct of_device_id qcom_pdm_domains[] __maybe_unused = {
+ { .compatible = "qcom,apq8016", .data = NULL, },
{ .compatible = "qcom,apq8064", .data = NULL, },
{ .compatible = "qcom,apq8074", .data = NULL, },
{ .compatible = "qcom,apq8084", .data = NULL, },
{ .compatible = "qcom,apq8096", .data = msm8996_domains, },
{ .compatible = "qcom,msm8226", .data = NULL, },
+ { .compatible = "qcom,msm8909", .data = NULL, },
+ { .compatible = "qcom,msm8916", .data = NULL, },
+ { .compatible = "qcom,msm8939", .data = NULL, },
{ .compatible = "qcom,msm8974", .data = NULL, },
{ .compatible = "qcom,msm8996", .data = msm8996_domains, },
{ .compatible = "qcom,msm8998", .data = msm8998_domains, },
@@ -539,12 +552,14 @@ static const struct of_device_id qcom_pdm_domains[] = {
{ .compatible = "qcom,sm4250", .data = sm6115_domains, },
{ .compatible = "qcom,sm6115", .data = sm6115_domains, },
{ .compatible = "qcom,sm6350", .data = sm6350_domains, },
+ { .compatible = "qcom,sm7325", .data = sc7280_domains, },
{ .compatible = "qcom,sm8150", .data = sm8150_domains, },
{ .compatible = "qcom,sm8250", .data = sm8250_domains, },
{ .compatible = "qcom,sm8350", .data = sm8350_domains, },
{ .compatible = "qcom,sm8450", .data = sm8350_domains, },
{ .compatible = "qcom,sm8550", .data = sm8550_domains, },
{ .compatible = "qcom,sm8650", .data = sm8550_domains, },
+ { .compatible = "qcom,x1e80100", .data = x1e80100_domains, },
{},
};
@@ -635,6 +650,8 @@ static int qcom_pdm_probe(struct auxiliary_device *auxdev,
ret = PTR_ERR(data);
else
__qcom_pdm_data = data;
+ } else {
+ refcount_inc(&__qcom_pdm_data->refcnt);
}
auxiliary_set_drvdata(auxdev, __qcom_pdm_data);
diff --git a/drivers/soc/qcom/smd-rpm.c b/drivers/soc/qcom/smd-rpm.c
index b7056aed4c7d..f2b3e02abdf1 100644
--- a/drivers/soc/qcom/smd-rpm.c
+++ b/drivers/soc/qcom/smd-rpm.c
@@ -196,9 +196,6 @@ static int qcom_smd_rpm_probe(struct rpmsg_device *rpdev)
{
struct qcom_smd_rpm *rpm;
- if (!rpdev->dev.of_node)
- return -EINVAL;
-
rpm = devm_kzalloc(&rpdev->dev, sizeof(*rpm), GFP_KERNEL);
if (!rpm)
return -ENOMEM;
@@ -218,18 +215,44 @@ static void qcom_smd_rpm_remove(struct rpmsg_device *rpdev)
of_platform_depopulate(&rpdev->dev);
}
-static const struct rpmsg_device_id qcom_smd_rpm_id_table[] = {
- { .name = "rpm_requests", },
- { /* sentinel */ }
+static const struct of_device_id qcom_smd_rpm_of_match[] = {
+ { .compatible = "qcom,glink-smd-rpm" },
+ { .compatible = "qcom,smd-rpm" },
+ /*
+ * Don't add any more compatibles to the list, two previous entryes
+ * should match all defined devices.
+ */
+ { .compatible = "qcom,rpm-apq8084" },
+ { .compatible = "qcom,rpm-ipq6018" },
+ { .compatible = "qcom,rpm-ipq9574" },
+ { .compatible = "qcom,rpm-msm8226" },
+ { .compatible = "qcom,rpm-msm8909" },
+ { .compatible = "qcom,rpm-msm8916" },
+ { .compatible = "qcom,rpm-msm8936" },
+ { .compatible = "qcom,rpm-msm8953" },
+ { .compatible = "qcom,rpm-msm8974" },
+ { .compatible = "qcom,rpm-msm8976" },
+ { .compatible = "qcom,rpm-msm8994" },
+ { .compatible = "qcom,rpm-msm8996" },
+ { .compatible = "qcom,rpm-msm8998" },
+ { .compatible = "qcom,rpm-sdm660" },
+ { .compatible = "qcom,rpm-sm6115" },
+ { .compatible = "qcom,rpm-sm6125" },
+ { .compatible = "qcom,rpm-sm6375" },
+ { .compatible = "qcom,rpm-qcm2290" },
+ { .compatible = "qcom,rpm-qcs404" },
+ {}
};
-MODULE_DEVICE_TABLE(rpmsg, qcom_smd_rpm_id_table);
+MODULE_DEVICE_TABLE(of, qcom_smd_rpm_of_match);
static struct rpmsg_driver qcom_smd_rpm_driver = {
.probe = qcom_smd_rpm_probe,
.remove = qcom_smd_rpm_remove,
.callback = qcom_smd_rpm_callback,
- .id_table = qcom_smd_rpm_id_table,
- .drv.name = "qcom_smd_rpm",
+ .drv = {
+ .name = "qcom_smd_rpm",
+ .of_match_table = qcom_smd_rpm_of_match,
+ },
};
static int __init qcom_smd_rpm_init(void)
diff --git a/drivers/soc/qcom/smp2p.c b/drivers/soc/qcom/smp2p.c
index 696c2a8387d0..cefcbd61c628 100644
--- a/drivers/soc/qcom/smp2p.c
+++ b/drivers/soc/qcom/smp2p.c
@@ -161,6 +161,9 @@ struct qcom_smp2p {
struct list_head outbound;
};
+#define CREATE_TRACE_POINTS
+#include "trace-smp2p.h"
+
static void qcom_smp2p_kick(struct qcom_smp2p *smp2p)
{
/* Make sure any updated data is written before the kick */
@@ -192,6 +195,7 @@ static void qcom_smp2p_do_ssr_ack(struct qcom_smp2p *smp2p)
struct smp2p_smem_item *out = smp2p->out;
u32 val;
+ trace_smp2p_ssr_ack(smp2p->dev);
smp2p->ssr_ack = !smp2p->ssr_ack;
val = out->flags & ~BIT(SMP2P_FLAGS_RESTART_ACK_BIT);
@@ -214,6 +218,7 @@ static void qcom_smp2p_negotiate(struct qcom_smp2p *smp2p)
smp2p->ssr_ack_enabled = true;
smp2p->negotiation_done = true;
+ trace_smp2p_negotiate(smp2p->dev, out->features);
}
}
@@ -252,6 +257,8 @@ static void qcom_smp2p_notify_in(struct qcom_smp2p *smp2p)
status = val ^ entry->last_value;
entry->last_value = val;
+ trace_smp2p_notify_in(entry, status, val);
+
/* No changes of this entry? */
if (!status)
continue;
@@ -415,6 +422,8 @@ static int smp2p_update_bits(void *data, u32 mask, u32 value)
writel(val, entry->value);
spin_unlock_irqrestore(&entry->lock, flags);
+ trace_smp2p_update_bits(entry, orig, val);
+
if (val != orig)
qcom_smp2p_kick(entry->smp2p);
@@ -530,7 +539,6 @@ static int smp2p_parse_ipc(struct qcom_smp2p *smp2p)
static int qcom_smp2p_probe(struct platform_device *pdev)
{
struct smp2p_entry *entry;
- struct device_node *node;
struct qcom_smp2p *smp2p;
const char *key;
int irq;
@@ -584,11 +592,10 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
if (ret < 0)
goto release_mbox;
- for_each_available_child_of_node(pdev->dev.of_node, node) {
+ for_each_available_child_of_node_scoped(pdev->dev.of_node, node) {
entry = devm_kzalloc(&pdev->dev, sizeof(*entry), GFP_KERNEL);
if (!entry) {
ret = -ENOMEM;
- of_node_put(node);
goto unwind_interfaces;
}
@@ -596,25 +603,19 @@ static int qcom_smp2p_probe(struct platform_device *pdev)
spin_lock_init(&entry->lock);
ret = of_property_read_string(node, "qcom,entry-name", &entry->name);
- if (ret < 0) {
- of_node_put(node);
+ if (ret < 0)
goto unwind_interfaces;
- }
if (of_property_read_bool(node, "interrupt-controller")) {
ret = qcom_smp2p_inbound_entry(smp2p, entry, node);
- if (ret < 0) {
- of_node_put(node);
+ if (ret < 0)
goto unwind_interfaces;
- }
list_add(&entry->node, &smp2p->inbound);
} else {
ret = qcom_smp2p_outbound_entry(smp2p, entry, node);
- if (ret < 0) {
- of_node_put(node);
+ if (ret < 0)
goto unwind_interfaces;
- }
list_add(&entry->node, &smp2p->outbound);
}
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index d7359a235e3c..24c3971f2ef1 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -401,11 +401,13 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(SA8540P) },
{ qcom_board_id(QCM4290) },
{ qcom_board_id(QCS4290) },
+ { qcom_board_id(SM7325) },
{ qcom_board_id_named(SM8450_2, "SM8450") },
{ qcom_board_id_named(SM8450_3, "SM8450") },
{ qcom_board_id(SC7280) },
{ qcom_board_id(SC7180P) },
{ qcom_board_id(QCM6490) },
+ { qcom_board_id(SM7325P) },
{ qcom_board_id(IPQ5000) },
{ qcom_board_id(IPQ0509) },
{ qcom_board_id(IPQ0518) },
@@ -441,6 +443,8 @@ static const struct soc_id soc_id[] = {
{ qcom_board_id(QCM8550) },
{ qcom_board_id(IPQ5300) },
{ qcom_board_id(IPQ5321) },
+ { qcom_board_id(QCS8300) },
+ { qcom_board_id(QCS8275) },
};
static const char *socinfo_machine(struct device *dev, unsigned int id)
diff --git a/drivers/soc/qcom/trace-smp2p.h b/drivers/soc/qcom/trace-smp2p.h
new file mode 100644
index 000000000000..9a6392043f10
--- /dev/null
+++ b/drivers/soc/qcom/trace-smp2p.h
@@ -0,0 +1,98 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM qcom_smp2p
+
+#if !defined(__QCOM_SMP2P_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ)
+#define __QCOM_SMP2P_TRACE_H__
+
+#include <linux/device.h>
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(smp2p_ssr_ack,
+ TP_PROTO(const struct device *dev),
+ TP_ARGS(dev),
+ TP_STRUCT__entry(
+ __string(dev_name, dev_name(dev))
+ ),
+ TP_fast_assign(
+ __assign_str(dev_name);
+ ),
+ TP_printk("%s: SSR detected", __get_str(dev_name))
+);
+
+TRACE_EVENT(smp2p_negotiate,
+ TP_PROTO(const struct device *dev, unsigned int features),
+ TP_ARGS(dev, features),
+ TP_STRUCT__entry(
+ __string(dev_name, dev_name(dev))
+ __field(u32, out_features)
+ ),
+ TP_fast_assign(
+ __assign_str(dev_name);
+ __entry->out_features = features;
+ ),
+ TP_printk("%s: state=open out_features=%s", __get_str(dev_name),
+ __print_flags(__entry->out_features, "|",
+ {SMP2P_FEATURE_SSR_ACK, "SMP2P_FEATURE_SSR_ACK"})
+ )
+);
+
+TRACE_EVENT(smp2p_notify_in,
+ TP_PROTO(struct smp2p_entry *smp2p_entry, unsigned long status, u32 val),
+ TP_ARGS(smp2p_entry, status, val),
+ TP_STRUCT__entry(
+ __string(dev_name, dev_name(smp2p_entry->smp2p->dev))
+ __string(client_name, smp2p_entry->name)
+ __field(unsigned long, status)
+ __field(u32, val)
+ ),
+ TP_fast_assign(
+ __assign_str(dev_name);
+ __assign_str(client_name);
+ __entry->status = status;
+ __entry->val = val;
+ ),
+ TP_printk("%s: %s: status:0x%0lx val:0x%0x",
+ __get_str(dev_name),
+ __get_str(client_name),
+ __entry->status,
+ __entry->val
+ )
+);
+
+TRACE_EVENT(smp2p_update_bits,
+ TP_PROTO(struct smp2p_entry *smp2p_entry, u32 orig, u32 val),
+ TP_ARGS(smp2p_entry, orig, val),
+ TP_STRUCT__entry(
+ __string(dev_name, dev_name(smp2p_entry->smp2p->dev))
+ __string(client_name, smp2p_entry->name)
+ __field(u32, orig)
+ __field(u32, val)
+ ),
+ TP_fast_assign(
+ __assign_str(dev_name);
+ __assign_str(client_name);
+ __entry->orig = orig;
+ __entry->val = val;
+ ),
+ TP_printk("%s: %s: orig:0x%0x new:0x%0x",
+ __get_str(dev_name),
+ __get_str(client_name),
+ __entry->orig,
+ __entry->val
+ )
+);
+
+#endif /* __QCOM_SMP2P_TRACE_H__ */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace-smp2p
+
+#include <trace/define_trace.h>
diff --git a/drivers/soc/qcom/trace_icc-bwmon.h b/drivers/soc/qcom/trace_icc-bwmon.h
new file mode 100644
index 000000000000..beb8e6b485a9
--- /dev/null
+++ b/drivers/soc/qcom/trace_icc-bwmon.h
@@ -0,0 +1,48 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (c) 2024 Qualcomm Innovation Center, Inc. All rights reserved.
+ */
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM icc_bwmon
+
+#if !defined(_TRACE_ICC_BWMON_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_ICC_BWMON_H
+#include <linux/tracepoint.h>
+
+TRACE_EVENT(qcom_bwmon_update,
+ TP_PROTO(const char *name,
+ unsigned int meas_kbps, unsigned int up_kbps, unsigned int down_kbps),
+
+ TP_ARGS(name, meas_kbps, up_kbps, down_kbps),
+
+ TP_STRUCT__entry(
+ __string(name, name)
+ __field(unsigned int, meas_kbps)
+ __field(unsigned int, up_kbps)
+ __field(unsigned int, down_kbps)
+ ),
+
+ TP_fast_assign(
+ __assign_str(name);
+ __entry->meas_kbps = meas_kbps;
+ __entry->up_kbps = up_kbps;
+ __entry->down_kbps = down_kbps;
+ ),
+
+ TP_printk("name=%s meas_kbps=%u up_kbps=%u down_kbps=%u",
+ __get_str(name),
+ __entry->meas_kbps,
+ __entry->up_kbps,
+ __entry->down_kbps)
+);
+
+#endif /* _TRACE_ICC_BWMON_H */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH ../../drivers/soc/qcom/
+
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace_icc-bwmon
+
+#include <trace/define_trace.h>
diff --git a/drivers/soc/rockchip/grf.c b/drivers/soc/rockchip/grf.c
index 5fd62046b28a..1eab4bb0eacf 100644
--- a/drivers/soc/rockchip/grf.c
+++ b/drivers/soc/rockchip/grf.c
@@ -41,9 +41,11 @@ static const struct rockchip_grf_info rk3036_grf __initconst = {
};
#define RK3128_GRF_SOC_CON0 0x140
+#define RK3128_GRF_SOC_CON1 0x144
static const struct rockchip_grf_value rk3128_defaults[] __initconst = {
{ "jtag switching", RK3128_GRF_SOC_CON0, HIWORD_UPDATE(0, 1, 8) },
+ { "vpu main clock", RK3128_GRF_SOC_CON1, HIWORD_UPDATE(0, 1, 10) },
};
static const struct rockchip_grf_info rk3128_grf __initconst = {
@@ -121,6 +123,29 @@ static const struct rockchip_grf_info rk3566_pipegrf __initconst = {
.num_values = ARRAY_SIZE(rk3566_defaults),
};
+#define RK3576_SYSGRF_SOC_CON1 0x0004
+
+static const struct rockchip_grf_value rk3576_defaults_sys_grf[] __initconst = {
+ { "i3c0 weakpull", RK3576_SYSGRF_SOC_CON1, HIWORD_UPDATE(3, 3, 6) },
+ { "i3c1 weakpull", RK3576_SYSGRF_SOC_CON1, HIWORD_UPDATE(3, 3, 8) },
+};
+
+static const struct rockchip_grf_info rk3576_sysgrf __initconst = {
+ .values = rk3576_defaults_sys_grf,
+ .num_values = ARRAY_SIZE(rk3576_defaults_sys_grf),
+};
+
+#define RK3576_IOCGRF_MISC_CON 0x04F0
+
+static const struct rockchip_grf_value rk3576_defaults_ioc_grf[] __initconst = {
+ { "jtag switching", RK3576_IOCGRF_MISC_CON, HIWORD_UPDATE(0, 1, 1) },
+};
+
+static const struct rockchip_grf_info rk3576_iocgrf __initconst = {
+ .values = rk3576_defaults_ioc_grf,
+ .num_values = ARRAY_SIZE(rk3576_defaults_ioc_grf),
+};
+
#define RK3588_GRF_SOC_CON6 0x0318
static const struct rockchip_grf_value rk3588_defaults[] __initconst = {
@@ -132,7 +157,6 @@ static const struct rockchip_grf_info rk3588_sysgrf __initconst = {
.num_values = ARRAY_SIZE(rk3588_defaults),
};
-
static const struct of_device_id rockchip_grf_dt_match[] __initconst = {
{
.compatible = "rockchip,rk3036-grf",
@@ -159,6 +183,12 @@ static const struct of_device_id rockchip_grf_dt_match[] __initconst = {
.compatible = "rockchip,rk3566-pipe-grf",
.data = (void *)&rk3566_pipegrf,
}, {
+ .compatible = "rockchip,rk3576-sys-grf",
+ .data = (void *)&rk3576_sysgrf,
+ }, {
+ .compatible = "rockchip,rk3576-ioc-grf",
+ .data = (void *)&rk3576_iocgrf,
+ }, {
.compatible = "rockchip,rk3588-sys-grf",
.data = (void *)&rk3588_sysgrf,
},
diff --git a/drivers/soc/rockchip/io-domain.c b/drivers/soc/rockchip/io-domain.c
index 18f809c160a7..fd9fd31f71c2 100644
--- a/drivers/soc/rockchip/io-domain.c
+++ b/drivers/soc/rockchip/io-domain.c
@@ -39,6 +39,10 @@
#define RK3288_SOC_CON2_FLASH0 BIT(7)
#define RK3288_SOC_FLASH_SUPPLY_NUM 2
+#define RK3308_SOC_CON0 0x300
+#define RK3308_SOC_CON0_VCCIO3 BIT(8)
+#define RK3308_SOC_VCCIO3_SUPPLY_NUM 3
+
#define RK3328_SOC_CON4 0x410
#define RK3328_SOC_CON4_VCCIO2 BIT(7)
#define RK3328_SOC_VCCIO2_SUPPLY_NUM 1
@@ -229,6 +233,25 @@ static void rk3288_iodomain_init(struct rockchip_iodomain *iod)
dev_warn(iod->dev, "couldn't update flash0 ctrl\n");
}
+static void rk3308_iodomain_init(struct rockchip_iodomain *iod)
+{
+ int ret;
+ u32 val;
+
+ /* if no vccio3 supply we should leave things alone */
+ if (!iod->supplies[RK3308_SOC_VCCIO3_SUPPLY_NUM].reg)
+ return;
+
+ /*
+ * set vccio3 iodomain to also use this framework
+ * instead of a special gpio.
+ */
+ val = RK3308_SOC_CON0_VCCIO3 | (RK3308_SOC_CON0_VCCIO3 << 16);
+ ret = regmap_write(iod->grf, RK3308_SOC_CON0, val);
+ if (ret < 0)
+ dev_warn(iod->dev, "couldn't update vccio3 vsel ctrl\n");
+}
+
static void rk3328_iodomain_init(struct rockchip_iodomain *iod)
{
int ret;
@@ -376,6 +399,19 @@ static const struct rockchip_iodomain_soc_data soc_data_rk3288 = {
.init = rk3288_iodomain_init,
};
+static const struct rockchip_iodomain_soc_data soc_data_rk3308 = {
+ .grf_offset = 0x300,
+ .supply_names = {
+ "vccio0",
+ "vccio1",
+ "vccio2",
+ "vccio3",
+ "vccio4",
+ "vccio5",
+ },
+ .init = rk3308_iodomain_init,
+};
+
static const struct rockchip_iodomain_soc_data soc_data_rk3328 = {
.grf_offset = 0x410,
.supply_names = {
@@ -529,6 +565,10 @@ static const struct of_device_id rockchip_iodomain_match[] = {
.data = &soc_data_rk3288
},
{
+ .compatible = "rockchip,rk3308-io-voltage-domain",
+ .data = &soc_data_rk3308
+ },
+ {
.compatible = "rockchip,rk3328-io-voltage-domain",
.data = &soc_data_rk3328
},
diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c
index 6c37d6eb8b49..a08c377933c5 100644
--- a/drivers/soc/tegra/pmc.c
+++ b/drivers/soc/tegra/pmc.c
@@ -1438,7 +1438,7 @@ static int tegra_powergate_init(struct tegra_pmc *pmc,
struct device_node *parent)
{
struct of_phandle_args child_args, parent_args;
- struct device_node *np, *child;
+ struct device_node *np;
int err = 0;
/*
@@ -1457,12 +1457,10 @@ static int tegra_powergate_init(struct tegra_pmc *pmc,
if (!np)
return 0;
- for_each_child_of_node(np, child) {
+ for_each_child_of_node_scoped(np, child) {
err = tegra_powergate_add(pmc, child);
- if (err < 0) {
- of_node_put(child);
+ if (err < 0)
break;
- }
if (of_parse_phandle_with_args(child, "power-domains",
"#power-domain-cells",
@@ -1474,10 +1472,8 @@ static int tegra_powergate_init(struct tegra_pmc *pmc,
err = of_genpd_add_subdomain(&parent_args, &child_args);
of_node_put(parent_args.np);
- if (err) {
- of_node_put(child);
+ if (err)
break;
- }
}
of_node_put(np);
diff --git a/drivers/soc/ti/k3-ringacc.c b/drivers/soc/ti/k3-ringacc.c
index fd4251d75935..8c0102968351 100644
--- a/drivers/soc/ti/k3-ringacc.c
+++ b/drivers/soc/ti/k3-ringacc.c
@@ -161,7 +161,7 @@ struct k3_ring {
struct k3_ringacc_proxy_target_regs __iomem *proxy;
dma_addr_t ring_mem_dma;
void *ring_mem_virt;
- struct k3_ring_ops *ops;
+ const struct k3_ring_ops *ops;
u32 size;
enum k3_ring_size elm_size;
enum k3_ring_mode mode;
@@ -268,17 +268,17 @@ static int k3_ringacc_ring_pop_mem(struct k3_ring *ring, void *elem);
static int k3_dmaring_fwd_pop(struct k3_ring *ring, void *elem);
static int k3_dmaring_reverse_pop(struct k3_ring *ring, void *elem);
-static struct k3_ring_ops k3_ring_mode_ring_ops = {
+static const struct k3_ring_ops k3_ring_mode_ring_ops = {
.push_tail = k3_ringacc_ring_push_mem,
.pop_head = k3_ringacc_ring_pop_mem,
};
-static struct k3_ring_ops k3_dmaring_fwd_ops = {
+static const struct k3_ring_ops k3_dmaring_fwd_ops = {
.push_tail = k3_ringacc_ring_push_mem,
.pop_head = k3_dmaring_fwd_pop,
};
-static struct k3_ring_ops k3_dmaring_reverse_ops = {
+static const struct k3_ring_ops k3_dmaring_reverse_ops = {
/* Reverse side of the DMA ring can only be popped by SW */
.pop_head = k3_dmaring_reverse_pop,
};
@@ -288,7 +288,7 @@ static int k3_ringacc_ring_pop_io(struct k3_ring *ring, void *elem);
static int k3_ringacc_ring_push_head_io(struct k3_ring *ring, void *elem);
static int k3_ringacc_ring_pop_tail_io(struct k3_ring *ring, void *elem);
-static struct k3_ring_ops k3_ring_mode_msg_ops = {
+static const struct k3_ring_ops k3_ring_mode_msg_ops = {
.push_tail = k3_ringacc_ring_push_io,
.push_head = k3_ringacc_ring_push_head_io,
.pop_tail = k3_ringacc_ring_pop_tail_io,
@@ -300,7 +300,7 @@ static int k3_ringacc_ring_push_tail_proxy(struct k3_ring *ring, void *elem);
static int k3_ringacc_ring_pop_head_proxy(struct k3_ring *ring, void *elem);
static int k3_ringacc_ring_pop_tail_proxy(struct k3_ring *ring, void *elem);
-static struct k3_ring_ops k3_ring_mode_proxy_ops = {
+static const struct k3_ring_ops k3_ring_mode_proxy_ops = {
.push_tail = k3_ringacc_ring_push_tail_proxy,
.push_head = k3_ringacc_ring_push_head_proxy,
.pop_tail = k3_ringacc_ring_pop_tail_proxy,
diff --git a/drivers/soc/ti/knav_dma.c b/drivers/soc/ti/knav_dma.c
index 6023006685fc..fb0746d8caad 100644
--- a/drivers/soc/ti/knav_dma.c
+++ b/drivers/soc/ti/knav_dma.c
@@ -602,7 +602,7 @@ static int dma_init(struct device_node *cloud, struct device_node *dma_node)
unsigned max_tx_chan, max_rx_chan, max_rx_flow, max_tx_sched;
struct device_node *node = dma_node;
struct knav_dma_device *dma;
- int ret, len, num_chan = 0;
+ int ret, num_chan = 0;
resource_size_t size;
u32 timeout;
u32 i;
@@ -615,25 +615,13 @@ static int dma_init(struct device_node *cloud, struct device_node *dma_node)
INIT_LIST_HEAD(&dma->list);
INIT_LIST_HEAD(&dma->chan_list);
- if (!of_find_property(cloud, "ti,navigator-cloud-address", &len)) {
- dev_err(kdev->dev, "unspecified navigator cloud addresses\n");
- return -ENODEV;
- }
-
- dma->logical_queue_managers = len / sizeof(u32);
- if (dma->logical_queue_managers > DMA_MAX_QMS) {
- dev_warn(kdev->dev, "too many queue mgrs(>%d) rest ignored\n",
- dma->logical_queue_managers);
- dma->logical_queue_managers = DMA_MAX_QMS;
- }
-
- ret = of_property_read_u32_array(cloud, "ti,navigator-cloud-address",
- dma->qm_base_address,
- dma->logical_queue_managers);
- if (ret) {
+ ret = of_property_read_variable_u32_array(cloud, "ti,navigator-cloud-address",
+ dma->qm_base_address, 1, DMA_MAX_QMS);
+ if (ret < 0) {
dev_err(kdev->dev, "invalid navigator cloud addresses\n");
return -ENODEV;
}
+ dma->logical_queue_managers = ret;
dma->reg_global = pktdma_get_regs(dma, node, 0, &size);
if (IS_ERR(dma->reg_global))
diff --git a/drivers/soc/ti/knav_qmss_queue.c b/drivers/soc/ti/knav_qmss_queue.c
index f2055a76f84c..6c98738e548a 100644
--- a/drivers/soc/ti/knav_qmss_queue.c
+++ b/drivers/soc/ti/knav_qmss_queue.c
@@ -1076,14 +1076,20 @@ static const char *knav_queue_find_name(struct device_node *node)
}
static int knav_queue_setup_regions(struct knav_device *kdev,
- struct device_node *regions)
+ struct device_node *node)
{
struct device *dev = kdev->dev;
+ struct device_node *regions __free(device_node) =
+ of_get_child_by_name(node, "descriptor-regions");
struct knav_region *region;
struct device_node *child;
u32 temp[2];
int ret;
+ if (!regions)
+ return dev_err_probe(dev, -ENODEV,
+ "descriptor-regions not specified\n");
+
for_each_child_of_node(regions, child) {
region = devm_kzalloc(dev, sizeof(*region), GFP_KERNEL);
if (!region) {
@@ -1104,11 +1110,6 @@ static int knav_queue_setup_regions(struct knav_device *kdev,
continue;
}
- if (!of_get_property(child, "link-index", NULL)) {
- dev_err(dev, "No link info for %s\n", region->name);
- devm_kfree(dev, region);
- continue;
- }
ret = of_property_read_u32(child, "link-index",
&region->link_index);
if (ret) {
@@ -1121,10 +1122,9 @@ static int knav_queue_setup_regions(struct knav_device *kdev,
INIT_LIST_HEAD(&region->pools);
list_add_tail(&region->list, &kdev->regions);
}
- if (list_empty(&kdev->regions)) {
- dev_err(dev, "no valid region information found\n");
- return -ENODEV;
- }
+ if (list_empty(&kdev->regions))
+ return dev_err_probe(dev, -ENODEV,
+ "no valid region information found\n");
/* Next, we run through the regions and set things up */
for_each_region(kdev, region)
@@ -1306,10 +1306,16 @@ static int knav_setup_queue_range(struct knav_device *kdev,
}
static int knav_setup_queue_pools(struct knav_device *kdev,
- struct device_node *queue_pools)
+ struct device_node *node)
{
+ struct device_node *queue_pools __free(device_node) =
+ of_get_child_by_name(node, "queue-pools");
struct device_node *type, *range;
+ if (!queue_pools)
+ return dev_err_probe(kdev->dev, -ENODEV,
+ "queue-pools not specified\n");
+
for_each_child_of_node(queue_pools, type) {
for_each_child_of_node(type, range) {
/* return value ignored, we init the rest... */
@@ -1318,10 +1324,9 @@ static int knav_setup_queue_pools(struct knav_device *kdev,
}
/* ... and barf if they all failed! */
- if (list_empty(&kdev->queue_ranges)) {
- dev_err(kdev->dev, "no valid queue range found\n");
- return -ENODEV;
- }
+ if (list_empty(&kdev->queue_ranges))
+ return dev_err_probe(kdev->dev, -ENODEV,
+ "no valid queue range found\n");
return 0;
}
@@ -1389,14 +1394,20 @@ static void __iomem *knav_queue_map_reg(struct knav_device *kdev,
}
static int knav_queue_init_qmgrs(struct knav_device *kdev,
- struct device_node *qmgrs)
+ struct device_node *node)
{
struct device *dev = kdev->dev;
+ struct device_node *qmgrs __free(device_node) =
+ of_get_child_by_name(node, "qmgrs");
struct knav_qmgr_info *qmgr;
struct device_node *child;
u32 temp[2];
int ret;
+ if (!qmgrs)
+ return dev_err_probe(dev, -ENODEV,
+ "queue manager info not specified\n");
+
for_each_child_of_node(qmgrs, child) {
qmgr = devm_kzalloc(dev, sizeof(*qmgr), GFP_KERNEL);
if (!qmgr) {
@@ -1668,6 +1679,26 @@ static int knav_queue_start_pdsps(struct knav_device *kdev)
return 0;
}
+static int knav_queue_setup_pdsps(struct knav_device *kdev,
+ struct device_node *node)
+{
+ struct device_node *pdsps __free(device_node) =
+ of_get_child_by_name(node, "pdsps");
+
+ if (pdsps) {
+ int ret;
+
+ ret = knav_queue_init_pdsps(kdev, pdsps);
+ if (ret)
+ return ret;
+
+ ret = knav_queue_start_pdsps(kdev);
+ if (ret)
+ return ret;
+ }
+ return 0;
+}
+
static inline struct knav_qmgr_info *knav_find_qmgr(unsigned id)
{
struct knav_qmgr_info *qmgr;
@@ -1755,7 +1786,6 @@ MODULE_DEVICE_TABLE(of, keystone_qmss_of_match);
static int knav_queue_probe(struct platform_device *pdev)
{
struct device_node *node = pdev->dev.of_node;
- struct device_node *qmgrs, *queue_pools, *regions, *pdsps;
struct device *dev = &pdev->dev;
u32 temp[2];
int ret;
@@ -1799,39 +1829,17 @@ static int knav_queue_probe(struct platform_device *pdev)
kdev->num_queues = temp[1];
/* Initialize queue managers using device tree configuration */
- qmgrs = of_get_child_by_name(node, "qmgrs");
- if (!qmgrs) {
- dev_err(dev, "queue manager info not specified\n");
- ret = -ENODEV;
- goto err;
- }
- ret = knav_queue_init_qmgrs(kdev, qmgrs);
- of_node_put(qmgrs);
+ ret = knav_queue_init_qmgrs(kdev, node);
if (ret)
goto err;
/* get pdsp configuration values from device tree */
- pdsps = of_get_child_by_name(node, "pdsps");
- if (pdsps) {
- ret = knav_queue_init_pdsps(kdev, pdsps);
- if (ret)
- goto err;
-
- ret = knav_queue_start_pdsps(kdev);
- if (ret)
- goto err;
- }
- of_node_put(pdsps);
+ ret = knav_queue_setup_pdsps(kdev, node);
+ if (ret)
+ goto err;
/* get usable queue range values from device tree */
- queue_pools = of_get_child_by_name(node, "queue-pools");
- if (!queue_pools) {
- dev_err(dev, "queue-pools not specified\n");
- ret = -ENODEV;
- goto err;
- }
- ret = knav_setup_queue_pools(kdev, queue_pools);
- of_node_put(queue_pools);
+ ret = knav_setup_queue_pools(kdev, node);
if (ret)
goto err;
@@ -1853,14 +1861,7 @@ static int knav_queue_probe(struct platform_device *pdev)
if (ret)
goto err;
- regions = of_get_child_by_name(node, "descriptor-regions");
- if (!regions) {
- dev_err(dev, "descriptor-regions not specified\n");
- ret = -ENODEV;
- goto err;
- }
- ret = knav_queue_setup_regions(kdev, regions);
- of_node_put(regions);
+ ret = knav_queue_setup_regions(kdev, node);
if (ret)
goto err;
diff --git a/drivers/soc/ti/pm33xx.c b/drivers/soc/ti/pm33xx.c
index 3a56bbf3268a..8169885ab1e0 100644
--- a/drivers/soc/ti/pm33xx.c
+++ b/drivers/soc/ti/pm33xx.c
@@ -383,54 +383,44 @@ static void am33xx_pm_free_sram(void)
*/
static int am33xx_pm_alloc_sram(void)
{
- struct device_node *np;
- int ret = 0;
+ struct device_node *np __free(device_node) =
+ of_find_compatible_node(NULL, NULL, "ti,omap3-mpu");
- np = of_find_compatible_node(NULL, NULL, "ti,omap3-mpu");
if (!np) {
np = of_find_compatible_node(NULL, NULL, "ti,omap4-mpu");
- if (!np) {
- dev_err(pm33xx_dev, "PM: %s: Unable to find device node for mpu\n",
- __func__);
- return -ENODEV;
- }
+ if (!np)
+ return dev_err_probe(pm33xx_dev, -ENODEV,
+ "PM: %s: Unable to find device node for mpu\n",
+ __func__);
}
sram_pool = of_gen_pool_get(np, "pm-sram", 0);
- if (!sram_pool) {
- dev_err(pm33xx_dev, "PM: %s: Unable to get sram pool for ocmcram\n",
- __func__);
- ret = -ENODEV;
- goto mpu_put_node;
- }
+ if (!sram_pool)
+ return dev_err_probe(pm33xx_dev, -ENODEV,
+ "PM: %s: Unable to get sram pool for ocmcram\n",
+ __func__);
sram_pool_data = of_gen_pool_get(np, "pm-sram", 1);
- if (!sram_pool_data) {
- dev_err(pm33xx_dev, "PM: %s: Unable to get sram data pool for ocmcram\n",
- __func__);
- ret = -ENODEV;
- goto mpu_put_node;
- }
+ if (!sram_pool_data)
+ return dev_err_probe(pm33xx_dev, -ENODEV,
+ "PM: %s: Unable to get sram data pool for ocmcram\n",
+ __func__);
ocmcram_location = gen_pool_alloc(sram_pool, *pm_sram->do_wfi_sz);
- if (!ocmcram_location) {
- dev_err(pm33xx_dev, "PM: %s: Unable to allocate memory from ocmcram\n",
- __func__);
- ret = -ENOMEM;
- goto mpu_put_node;
- }
+ if (!ocmcram_location)
+ return dev_err_probe(pm33xx_dev, -ENOMEM,
+ "PM: %s: Unable to allocate memory from ocmcram\n",
+ __func__);
ocmcram_location_data = gen_pool_alloc(sram_pool_data,
sizeof(struct emif_regs_amx3));
if (!ocmcram_location_data) {
- dev_err(pm33xx_dev, "PM: Unable to allocate memory from ocmcram\n");
gen_pool_free(sram_pool, ocmcram_location, *pm_sram->do_wfi_sz);
- ret = -ENOMEM;
+ return dev_err_probe(pm33xx_dev, -ENOMEM,
+ "PM: Unable to allocate memory from ocmcram\n");
}
-mpu_put_node:
- of_node_put(np);
- return ret;
+ return 0;
}
static int am33xx_pm_rtc_setup(void)
diff --git a/drivers/soc/ti/pruss.c b/drivers/soc/ti/pruss.c
index 24a42e0b645c..3ec758f50e24 100644
--- a/drivers/soc/ti/pruss.c
+++ b/drivers/soc/ti/pruss.c
@@ -380,39 +380,81 @@ put_clk_mux_np:
static int pruss_clk_init(struct pruss *pruss, struct device_node *cfg_node)
{
- const struct pruss_private_data *data;
- struct device_node *clks_np;
struct device *dev = pruss->dev;
- int ret = 0;
-
- data = of_device_get_match_data(dev);
+ struct device_node *clks_np __free(device_node) =
+ of_get_child_by_name(cfg_node, "clocks");
+ const struct pruss_private_data *data = of_device_get_match_data(dev);
+ int ret;
- clks_np = of_get_child_by_name(cfg_node, "clocks");
- if (!clks_np) {
- dev_err(dev, "%pOF is missing its 'clocks' node\n", cfg_node);
- return -ENODEV;
- }
+ if (!clks_np)
+ return dev_err_probe(dev, -ENODEV,
+ "%pOF is missing its 'clocks' node\n",
+ cfg_node);
if (data && data->has_core_mux_clock) {
ret = pruss_clk_mux_setup(pruss, pruss->core_clk_mux,
"coreclk-mux", clks_np);
- if (ret) {
- dev_err(dev, "failed to setup coreclk-mux\n");
- goto put_clks_node;
- }
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to setup coreclk-mux\n");
}
ret = pruss_clk_mux_setup(pruss, pruss->iep_clk_mux, "iepclk-mux",
clks_np);
- if (ret) {
- dev_err(dev, "failed to setup iepclk-mux\n");
- goto put_clks_node;
- }
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to setup iepclk-mux\n");
-put_clks_node:
- of_node_put(clks_np);
+ return 0;
+}
- return ret;
+static int pruss_of_setup_memories(struct device *dev, struct pruss *pruss)
+{
+ struct device_node *np = dev_of_node(dev);
+ struct device_node *child __free(device_node) =
+ of_get_child_by_name(np, "memories");
+ const struct pruss_private_data *data = of_device_get_match_data(dev);
+ const char *mem_names[PRUSS_MEM_MAX] = { "dram0", "dram1", "shrdram2" };
+ int i;
+
+ if (!child)
+ return dev_err_probe(dev, -ENODEV,
+ "%pOF is missing its 'memories' node\n",
+ child);
+
+ for (i = 0; i < PRUSS_MEM_MAX; i++) {
+ struct resource res;
+ int index;
+
+ /*
+ * On AM437x one of two PRUSS units don't contain Shared RAM,
+ * skip it
+ */
+ if (data && data->has_no_sharedram && i == PRUSS_MEM_SHRD_RAM2)
+ continue;
+
+ index = of_property_match_string(child, "reg-names",
+ mem_names[i]);
+ if (index < 0)
+ return index;
+
+ if (of_address_to_resource(child, index, &res))
+ return -EINVAL;
+
+ pruss->mem_regions[i].va = devm_ioremap(dev, res.start,
+ resource_size(&res));
+ if (!pruss->mem_regions[i].va)
+ return dev_err_probe(dev, -ENOMEM,
+ "failed to parse and map memory resource %d %s\n",
+ i, mem_names[i]);
+ pruss->mem_regions[i].pa = res.start;
+ pruss->mem_regions[i].size = resource_size(&res);
+
+ dev_dbg(dev, "memory %8s: pa %pa size 0x%zx va %pK\n",
+ mem_names[i], &pruss->mem_regions[i].pa,
+ pruss->mem_regions[i].size, pruss->mem_regions[i].va);
+ }
+
+ return 0;
}
static struct regmap_config regmap_conf = {
@@ -424,26 +466,21 @@ static struct regmap_config regmap_conf = {
static int pruss_cfg_of_init(struct device *dev, struct pruss *pruss)
{
struct device_node *np = dev_of_node(dev);
- struct device_node *child;
+ struct device_node *child __free(device_node) =
+ of_get_child_by_name(np, "cfg");
struct resource res;
int ret;
- child = of_get_child_by_name(np, "cfg");
- if (!child) {
- dev_err(dev, "%pOF is missing its 'cfg' node\n", child);
- return -ENODEV;
- }
+ if (!child)
+ return dev_err_probe(dev, -ENODEV,
+ "%pOF is missing its 'cfg' node\n", child);
- if (of_address_to_resource(child, 0, &res)) {
- ret = -ENOMEM;
- goto node_put;
- }
+ if (of_address_to_resource(child, 0, &res))
+ return -ENOMEM;
pruss->cfg_base = devm_ioremap(dev, res.start, resource_size(&res));
- if (!pruss->cfg_base) {
- ret = -ENOMEM;
- goto node_put;
- }
+ if (!pruss->cfg_base)
+ return -ENOMEM;
regmap_conf.name = kasprintf(GFP_KERNEL, "%pOFn@%llx", child,
(u64)res.start);
@@ -452,34 +489,22 @@ static int pruss_cfg_of_init(struct device *dev, struct pruss *pruss)
pruss->cfg_regmap = devm_regmap_init_mmio(dev, pruss->cfg_base,
&regmap_conf);
kfree(regmap_conf.name);
- if (IS_ERR(pruss->cfg_regmap)) {
- dev_err(dev, "regmap_init_mmio failed for cfg, ret = %ld\n",
- PTR_ERR(pruss->cfg_regmap));
- ret = PTR_ERR(pruss->cfg_regmap);
- goto node_put;
- }
+ if (IS_ERR(pruss->cfg_regmap))
+ return dev_err_probe(dev, PTR_ERR(pruss->cfg_regmap),
+ "regmap_init_mmio failed for cfg\n");
ret = pruss_clk_init(pruss, child);
if (ret)
- dev_err(dev, "pruss_clk_init failed, ret = %d\n", ret);
+ return dev_err_probe(dev, ret, "pruss_clk_init failed\n");
-node_put:
- of_node_put(child);
- return ret;
+ return 0;
}
static int pruss_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct device_node *np = dev_of_node(dev);
- struct device_node *child;
struct pruss *pruss;
- struct resource res;
- int ret, i, index;
- const struct pruss_private_data *data;
- const char *mem_names[PRUSS_MEM_MAX] = { "dram0", "dram1", "shrdram2" };
-
- data = of_device_get_match_data(&pdev->dev);
+ int ret;
ret = dma_set_coherent_mask(dev, DMA_BIT_MASK(32));
if (ret) {
@@ -494,48 +519,9 @@ static int pruss_probe(struct platform_device *pdev)
pruss->dev = dev;
mutex_init(&pruss->lock);
- child = of_get_child_by_name(np, "memories");
- if (!child) {
- dev_err(dev, "%pOF is missing its 'memories' node\n", child);
- return -ENODEV;
- }
-
- for (i = 0; i < PRUSS_MEM_MAX; i++) {
- /*
- * On AM437x one of two PRUSS units don't contain Shared RAM,
- * skip it
- */
- if (data && data->has_no_sharedram && i == PRUSS_MEM_SHRD_RAM2)
- continue;
-
- index = of_property_match_string(child, "reg-names",
- mem_names[i]);
- if (index < 0) {
- of_node_put(child);
- return index;
- }
-
- if (of_address_to_resource(child, index, &res)) {
- of_node_put(child);
- return -EINVAL;
- }
-
- pruss->mem_regions[i].va = devm_ioremap(dev, res.start,
- resource_size(&res));
- if (!pruss->mem_regions[i].va) {
- dev_err(dev, "failed to parse and map memory resource %d %s\n",
- i, mem_names[i]);
- of_node_put(child);
- return -ENOMEM;
- }
- pruss->mem_regions[i].pa = res.start;
- pruss->mem_regions[i].size = resource_size(&res);
-
- dev_dbg(dev, "memory %8s: pa %pa size 0x%zx va %pK\n",
- mem_names[i], &pruss->mem_regions[i].pa,
- pruss->mem_regions[i].size, pruss->mem_regions[i].va);
- }
- of_node_put(child);
+ ret = pruss_of_setup_memories(dev, pruss);
+ if (ret < 0)
+ return ret;
platform_set_drvdata(pdev, pruss);
diff --git a/drivers/soc/versatile/Kconfig b/drivers/soc/versatile/Kconfig
index c3792c0a84ac..7bbf54a8d879 100644
--- a/drivers/soc/versatile/Kconfig
+++ b/drivers/soc/versatile/Kconfig
@@ -4,7 +4,7 @@
#
config SOC_INTEGRATOR_CM
bool "SoC bus device for the ARM Integrator platform core modules"
- depends on ARCH_INTEGRATOR
+ depends on ARCH_INTEGRATOR || COMPILE_TEST
select SOC_BUS
help
Include support for the SoC bus on the ARM Integrator platform
@@ -13,7 +13,7 @@ config SOC_INTEGRATOR_CM
config SOC_REALVIEW
bool "SoC bus device for the ARM RealView platforms"
- depends on ARCH_REALVIEW
+ depends on ARCH_REALVIEW || COMPILE_TEST
select SOC_BUS
help
Include support for the SoC bus on the ARM RealView platforms
diff --git a/drivers/soc/versatile/soc-integrator.c b/drivers/soc/versatile/soc-integrator.c
index bab4ad87aa75..d5099a3386b4 100644
--- a/drivers/soc/versatile/soc-integrator.c
+++ b/drivers/soc/versatile/soc-integrator.c
@@ -113,6 +113,7 @@ static int __init integrator_soc_init(void)
return -ENODEV;
syscon_regmap = syscon_node_to_regmap(np);
+ of_node_put(np);
if (IS_ERR(syscon_regmap))
return PTR_ERR(syscon_regmap);
diff --git a/drivers/soc/versatile/soc-realview.c b/drivers/soc/versatile/soc-realview.c
index c6876d232d8f..cf91abe07d38 100644
--- a/drivers/soc/versatile/soc-realview.c
+++ b/drivers/soc/versatile/soc-realview.c
@@ -4,6 +4,7 @@
*
* Author: Linus Walleij <linus.walleij@linaro.org>
*/
+#include <linux/device.h>
#include <linux/init.h>
#include <linux/io.h>
#include <linux/slab.h>
@@ -81,6 +82,13 @@ static struct attribute *realview_attrs[] = {
ATTRIBUTE_GROUPS(realview);
+static void realview_soc_socdev_release(void *data)
+{
+ struct soc_device *soc_dev = data;
+
+ soc_device_unregister(soc_dev);
+}
+
static int realview_soc_probe(struct platform_device *pdev)
{
struct regmap *syscon_regmap;
@@ -93,7 +101,7 @@ static int realview_soc_probe(struct platform_device *pdev)
if (IS_ERR(syscon_regmap))
return PTR_ERR(syscon_regmap);
- soc_dev_attr = kzalloc(sizeof(*soc_dev_attr), GFP_KERNEL);
+ soc_dev_attr = devm_kzalloc(&pdev->dev, sizeof(*soc_dev_attr), GFP_KERNEL);
if (!soc_dev_attr)
return -ENOMEM;
@@ -106,10 +114,14 @@ static int realview_soc_probe(struct platform_device *pdev)
soc_dev_attr->family = "Versatile";
soc_dev_attr->custom_attr_group = realview_groups[0];
soc_dev = soc_device_register(soc_dev_attr);
- if (IS_ERR(soc_dev)) {
- kfree(soc_dev_attr);
+ if (IS_ERR(soc_dev))
return -ENODEV;
- }
+
+ ret = devm_add_action_or_reset(&pdev->dev, realview_soc_socdev_release,
+ soc_dev);
+ if (ret)
+ return ret;
+
ret = regmap_read(syscon_regmap, REALVIEW_SYS_ID_OFFSET,
&realview_coreid);
if (ret)