From 386cb76681ca6248878c7b76d3d5aa0e8b8a07bb Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Fri, 22 Mar 2019 07:49:30 -0700 Subject: bus: ti-sysc: Handle missed no-idle property in addition to no-idle-on-init We have ti,no-idle in use in addition to ti,no-idle-on-init but we're missing handling for it in the ti-sysc interconnect target module driver. Let's also group the idle defines together and update the binding documentation for it. Cc: devicetree@vger.kernel.org Reviewed-by: Rob Herring Signed-off-by: Tony Lindgren --- include/linux/platform_data/ti-sysc.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index 1ea3aab972b4..fa97b8c5d26d 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -46,8 +46,9 @@ struct sysc_regbits { s8 emufree_shift; }; -#define SYSC_QUIRK_LEGACY_IDLE BIT(8) -#define SYSC_QUIRK_RESET_STATUS BIT(7) +#define SYSC_QUIRK_LEGACY_IDLE BIT(9) +#define SYSC_QUIRK_RESET_STATUS BIT(8) +#define SYSC_QUIRK_NO_IDLE BIT(7) #define SYSC_QUIRK_NO_IDLE_ON_INIT BIT(6) #define SYSC_QUIRK_NO_RESET_ON_INIT BIT(5) #define SYSC_QUIRK_OPT_CLKS_NEEDED BIT(4) -- cgit v1.2.3 From a54275f4ab204137c9995c686c7f1cd2682cc0a4 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 21 Mar 2019 11:00:21 -0700 Subject: bus: ti-sysc: Add quirk handling for external optional functional clock We cannot access mcpdm registers at all unless there is an optional pdmclk configured. As this is currently only needed for mcpdm, let's check for mcpdm in sysc_get_clocks(). If it turns out to be needed for other modules too, we can add more flags to the quirks table for this. Signed-off-by: Tony Lindgren --- drivers/bus/ti-sysc.c | 91 ++++++++++++++++++++++++++++++++++- include/linux/platform_data/ti-sysc.h | 1 + 2 files changed, 91 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index c7e0896929bb..778bd0fffec0 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -47,7 +47,10 @@ enum sysc_clocks { SYSC_MAX_CLOCKS, }; -static const char * const clock_names[SYSC_ICK + 1] = { "fck", "ick", }; +static const char * const clock_names[SYSC_MAX_CLOCKS] = { + "fck", "ick", "opt0", "opt1", "opt2", "opt3", "opt4", + "opt5", "opt6", "opt7", +}; #define SYSC_IDLEMODE_MASK 3 #define SYSC_CLOCKACTIVITY_MASK 3 @@ -129,6 +132,81 @@ static u32 sysc_read_revision(struct sysc *ddata) return sysc_read(ddata, offset); } +static int sysc_add_named_clock_from_child(struct sysc *ddata, + const char *name, + const char *optfck_name) +{ + struct device_node *np = ddata->dev->of_node; + struct device_node *child; + struct clk_lookup *cl; + struct clk *clock; + const char *n; + + if (name) + n = name; + else + n = optfck_name; + + /* Does the clock alias already exist? */ + clock = of_clk_get_by_name(np, n); + if (!IS_ERR(clock)) { + clk_put(clock); + + return 0; + } + + child = of_get_next_available_child(np, NULL); + if (!child) + return -ENODEV; + + clock = devm_get_clk_from_child(ddata->dev, child, name); + if (IS_ERR(clock)) + return PTR_ERR(clock); + + /* + * Use clkdev_add() instead of clkdev_alloc() to avoid the MAX_DEV_ID + * limit for clk_get(). If cl ever needs to be freed, it should be done + * with clkdev_drop(). + */ + cl = kcalloc(1, sizeof(*cl), GFP_KERNEL); + if (!cl) + return -ENOMEM; + + cl->con_id = n; + cl->dev_id = dev_name(ddata->dev); + cl->clk = clock; + clkdev_add(cl); + + clk_put(clock); + + return 0; +} + +static int sysc_init_ext_opt_clock(struct sysc *ddata, const char *name) +{ + const char *optfck_name; + int error, index; + + if (ddata->nr_clocks < SYSC_OPTFCK0) + index = SYSC_OPTFCK0; + else + index = ddata->nr_clocks; + + if (name) + optfck_name = name; + else + optfck_name = clock_names[index]; + + error = sysc_add_named_clock_from_child(ddata, name, optfck_name); + if (error) + return error; + + ddata->clock_roles[index] = optfck_name; + ddata->nr_clocks++; + + return 0; +} + static int sysc_get_one_clock(struct sysc *ddata, const char *name) { int error, i, index = -ENODEV; @@ -200,6 +278,12 @@ static int sysc_get_clocks(struct sysc *ddata) if (ddata->nr_clocks < 1) return 0; + if ((ddata->cfg.quirks & SYSC_QUIRK_EXT_OPT_CLOCK)) { + error = sysc_init_ext_opt_clock(ddata, NULL); + if (error) + return error; + } + if (ddata->nr_clocks > SYSC_MAX_CLOCKS) { dev_err(ddata->dev, "too many clocks for %pOF\n", np); @@ -901,6 +985,11 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47422e03, 0xffffffff, SYSC_QUIRK_LEGACY_IDLE), + /* Quirks that need to be set based on the module address */ + SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -1, 0x50000800, 0xffffffff, + SYSC_QUIRK_EXT_OPT_CLOCK | SYSC_QUIRK_NO_RESET_ON_INIT | + SYSC_QUIRK_SWSUP_SIDLE), + #ifdef DEBUG SYSC_QUIRK("adc", 0, 0, 0x10, -1, 0x47300001, 0xffffffff, 0), SYSC_QUIRK("atl", 0, 0, -1, -1, 0x0a070100, 0xffffffff, 0), diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index fa97b8c5d26d..1384e5cdd310 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -46,6 +46,7 @@ struct sysc_regbits { s8 emufree_shift; }; +#define SYSC_QUIRK_EXT_OPT_CLOCK BIT(10) #define SYSC_QUIRK_LEGACY_IDLE BIT(9) #define SYSC_QUIRK_RESET_STATUS BIT(8) #define SYSC_QUIRK_NO_IDLE BIT(7) -- cgit v1.2.3 From b4a9a7a38917e9f947b5e69f7e8d4138d4c82845 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Thu, 21 Mar 2019 13:27:08 -0700 Subject: bus: ti-sysc: Handle swsup idle mode quirks In preparation of dropping interconnect target module platform data in favor of devicetree based data, we must pass swsup idle quirks to the platform data functions. For now, let's only tag the UART modules with the SWSUP_SIDLE_ACT quirk. The other modules will get tagged with swsup quirks as we drop the platform data and test the changes. Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap_hwmod.c | 6 ++++++ drivers/bus/ti-sysc.c | 6 +++--- include/linux/platform_data/ti-sysc.h | 3 +++ 3 files changed, 12 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c index 4a924e444f8d..4af2e9f0966d 100644 --- a/arch/arm/mach-omap2/omap_hwmod.c +++ b/arch/arm/mach-omap2/omap_hwmod.c @@ -3683,6 +3683,12 @@ int omap_hwmod_init_module(struct device *dev, oh->flags |= HWMOD_INIT_NO_RESET; if (data->cfg->quirks & SYSC_QUIRK_USE_CLOCKACT) oh->flags |= HWMOD_SET_DEFAULT_CLOCKACT; + if (data->cfg->quirks & SYSC_QUIRK_SWSUP_SIDLE) + oh->flags |= HWMOD_SWSUP_SIDLE; + if (data->cfg->quirks & SYSC_QUIRK_SWSUP_SIDLE_ACT) + oh->flags |= HWMOD_SWSUP_SIDLE_ACT; + if (data->cfg->quirks & SYSC_QUIRK_SWSUP_MSTANDBY) + oh->flags |= HWMOD_SWSUP_MSTANDBY; error = omap_hwmod_check_module(dev, oh, data, sysc_fields, rev_offs, sysc_offs, syss_offs, diff --git a/drivers/bus/ti-sysc.c b/drivers/bus/ti-sysc.c index 778bd0fffec0..d10460c0b15a 100644 --- a/drivers/bus/ti-sysc.c +++ b/drivers/bus/ti-sysc.c @@ -978,12 +978,12 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = { SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffff00ff, 0), SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff, - SYSC_QUIRK_LEGACY_IDLE), + SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE), /* Uarts on omap4 and later */ SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x50411e03, 0xffff00ff, - SYSC_QUIRK_LEGACY_IDLE), + SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE), SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x47422e03, 0xffffffff, - SYSC_QUIRK_LEGACY_IDLE), + SYSC_QUIRK_SWSUP_SIDLE_ACT | SYSC_QUIRK_LEGACY_IDLE), /* Quirks that need to be set based on the module address */ SYSC_QUIRK("mcpdm", 0x40132000, 0, 0x10, -1, 0x50000800, 0xffffffff, diff --git a/include/linux/platform_data/ti-sysc.h b/include/linux/platform_data/ti-sysc.h index 1384e5cdd310..9256c0305968 100644 --- a/include/linux/platform_data/ti-sysc.h +++ b/include/linux/platform_data/ti-sysc.h @@ -46,6 +46,9 @@ struct sysc_regbits { s8 emufree_shift; }; +#define SYSC_QUIRK_SWSUP_MSTANDBY BIT(13) +#define SYSC_QUIRK_SWSUP_SIDLE_ACT BIT(12) +#define SYSC_QUIRK_SWSUP_SIDLE BIT(11) #define SYSC_QUIRK_EXT_OPT_CLOCK BIT(10) #define SYSC_QUIRK_LEGACY_IDLE BIT(9) #define SYSC_QUIRK_RESET_STATUS BIT(8) -- cgit v1.2.3 From 4cb5d9eca143f7fbf8cc457be19a91914f978a00 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 10 Apr 2019 10:47:28 +0200 Subject: firmware: Move Trusted Foundations support Move the Trusted Foundations support out of arch/arm/firmware and into drivers/firmware where most other firmware support implementations are located. Signed-off-by: Thierry Reding --- arch/arm/Kconfig | 2 - arch/arm/Makefile | 1 - arch/arm/firmware/Kconfig | 29 ----- arch/arm/firmware/Makefile | 4 - arch/arm/firmware/trusted_foundations.c | 174 -------------------------- arch/arm/include/asm/trusted_foundations.h | 96 --------------- arch/arm/mach-tegra/Kconfig | 1 - arch/arm/mach-tegra/cpuidle-tegra114.c | 3 +- arch/arm/mach-tegra/pm.c | 3 +- arch/arm/mach-tegra/reset.c | 3 +- arch/arm/mach-tegra/tegra.c | 3 +- drivers/firmware/Kconfig | 16 +++ drivers/firmware/Makefile | 1 + drivers/firmware/trusted_foundations.c | 176 +++++++++++++++++++++++++++ include/linux/firmware/trusted_foundations.h | 96 +++++++++++++++ 15 files changed, 297 insertions(+), 311 deletions(-) delete mode 100644 arch/arm/firmware/Kconfig delete mode 100644 arch/arm/firmware/Makefile delete mode 100644 arch/arm/firmware/trusted_foundations.c delete mode 100644 arch/arm/include/asm/trusted_foundations.h create mode 100644 drivers/firmware/trusted_foundations.c create mode 100644 include/linux/firmware/trusted_foundations.h (limited to 'include/linux') diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 054ead960f98..f006b3c69247 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -899,8 +899,6 @@ config PLAT_PXA config PLAT_VERSATILE bool -source "arch/arm/firmware/Kconfig" - source "arch/arm/mm/Kconfig" config IWMMXT diff --git a/arch/arm/Makefile b/arch/arm/Makefile index 807a7d06c2a0..05ecc004de86 100644 --- a/arch/arm/Makefile +++ b/arch/arm/Makefile @@ -290,7 +290,6 @@ core-y += arch/arm/kernel/ arch/arm/mm/ arch/arm/common/ core-y += arch/arm/probes/ core-y += arch/arm/net/ core-y += arch/arm/crypto/ -core-y += arch/arm/firmware/ core-y += $(machdirs) $(platdirs) drivers-$(CONFIG_OPROFILE) += arch/arm/oprofile/ diff --git a/arch/arm/firmware/Kconfig b/arch/arm/firmware/Kconfig deleted file mode 100644 index ad396af68e47..000000000000 --- a/arch/arm/firmware/Kconfig +++ /dev/null @@ -1,29 +0,0 @@ -config ARCH_SUPPORTS_FIRMWARE - bool - -config ARCH_SUPPORTS_TRUSTED_FOUNDATIONS - bool - select ARCH_SUPPORTS_FIRMWARE - -menu "Firmware options" - depends on ARCH_SUPPORTS_FIRMWARE - -config TRUSTED_FOUNDATIONS - bool "Trusted Foundations secure monitor support" - depends on ARCH_SUPPORTS_TRUSTED_FOUNDATIONS - default y - help - Some devices (including most Tegra-based consumer devices on the - market) are booted with the Trusted Foundations secure monitor - active, requiring some core operations to be performed by the secure - monitor instead of the kernel. - - This option allows the kernel to invoke the secure monitor whenever - required on devices using Trusted Foundations. See - arch/arm/include/asm/trusted_foundations.h or the - tlm,trusted-foundations device tree binding documentation for details - on how to use it. - - Say n if you don't know what this is about. - -endmenu diff --git a/arch/arm/firmware/Makefile b/arch/arm/firmware/Makefile deleted file mode 100644 index 6e41336b0bc4..000000000000 --- a/arch/arm/firmware/Makefile +++ /dev/null @@ -1,4 +0,0 @@ -obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o - -# tf_generic_smc() fails to build with -fsanitize-coverage=trace-pc -KCOV_INSTRUMENT := n diff --git a/arch/arm/firmware/trusted_foundations.c b/arch/arm/firmware/trusted_foundations.c deleted file mode 100644 index bb2ee73d9e02..000000000000 --- a/arch/arm/firmware/trusted_foundations.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Trusted Foundations support for ARM CPUs - * - * Copyright (c) 2013, NVIDIA Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -#include -#include -#include -#include -#include -#include -#include - -#define TF_CACHE_MAINT 0xfffff100 - -#define TF_CACHE_ENABLE 1 -#define TF_CACHE_DISABLE 2 - -#define TF_SET_CPU_BOOT_ADDR_SMC 0xfffff200 - -#define TF_CPU_PM 0xfffffffc -#define TF_CPU_PM_S3 0xffffffe3 -#define TF_CPU_PM_S2 0xffffffe6 -#define TF_CPU_PM_S2_NO_MC_CLK 0xffffffe5 -#define TF_CPU_PM_S1 0xffffffe4 -#define TF_CPU_PM_S1_NOFLUSH_L2 0xffffffe7 - -static unsigned long cpu_boot_addr; - -static void tf_generic_smc(u32 type, u32 arg1, u32 arg2) -{ - register u32 r0 asm("r0") = type; - register u32 r1 asm("r1") = arg1; - register u32 r2 asm("r2") = arg2; - - asm volatile( - ".arch_extension sec\n\t" - "stmfd sp!, {r4 - r11}\n\t" - __asmeq("%0", "r0") - __asmeq("%1", "r1") - __asmeq("%2", "r2") - "mov r3, #0\n\t" - "mov r4, #0\n\t" - "smc #0\n\t" - "ldmfd sp!, {r4 - r11}\n\t" - : - : "r" (r0), "r" (r1), "r" (r2) - : "memory", "r3", "r12", "lr"); -} - -static int tf_set_cpu_boot_addr(int cpu, unsigned long boot_addr) -{ - cpu_boot_addr = boot_addr; - tf_generic_smc(TF_SET_CPU_BOOT_ADDR_SMC, cpu_boot_addr, 0); - - return 0; -} - -static int tf_prepare_idle(unsigned long mode) -{ - switch (mode) { - case TF_PM_MODE_LP0: - tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S3, cpu_boot_addr); - break; - - case TF_PM_MODE_LP1: - tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S2, cpu_boot_addr); - break; - - case TF_PM_MODE_LP1_NO_MC_CLK: - tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S2_NO_MC_CLK, - cpu_boot_addr); - break; - - case TF_PM_MODE_LP2: - tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S1, cpu_boot_addr); - break; - - case TF_PM_MODE_LP2_NOFLUSH_L2: - tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S1_NOFLUSH_L2, - cpu_boot_addr); - break; - - default: - return -EINVAL; - } - - return 0; -} - -#ifdef CONFIG_CACHE_L2X0 -static void tf_cache_write_sec(unsigned long val, unsigned int reg) -{ - u32 l2x0_way_mask = 0xff; - - switch (reg) { - case L2X0_CTRL: - if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_ASSOCIATIVITY_16) - l2x0_way_mask = 0xffff; - - if (val == L2X0_CTRL_EN) - tf_generic_smc(TF_CACHE_MAINT, TF_CACHE_ENABLE, - l2x0_saved_regs.aux_ctrl); - else - tf_generic_smc(TF_CACHE_MAINT, TF_CACHE_DISABLE, - l2x0_way_mask); - break; - - default: - break; - } -} - -static int tf_init_cache(void) -{ - outer_cache.write_sec = tf_cache_write_sec; - - return 0; -} -#endif /* CONFIG_CACHE_L2X0 */ - -static const struct firmware_ops trusted_foundations_ops = { - .set_cpu_boot_addr = tf_set_cpu_boot_addr, - .prepare_idle = tf_prepare_idle, -#ifdef CONFIG_CACHE_L2X0 - .l2x0_init = tf_init_cache, -#endif -}; - -void register_trusted_foundations(struct trusted_foundations_platform_data *pd) -{ - /* - * we are not using version information for now since currently - * supported SMCs are compatible with all TF releases - */ - register_firmware_ops(&trusted_foundations_ops); -} - -void of_register_trusted_foundations(void) -{ - struct device_node *node; - struct trusted_foundations_platform_data pdata; - int err; - - node = of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations"); - if (!node) - return; - - err = of_property_read_u32(node, "tlm,version-major", - &pdata.version_major); - if (err != 0) - panic("Trusted Foundation: missing version-major property\n"); - err = of_property_read_u32(node, "tlm,version-minor", - &pdata.version_minor); - if (err != 0) - panic("Trusted Foundation: missing version-minor property\n"); - register_trusted_foundations(&pdata); -} - -bool trusted_foundations_registered(void) -{ - return firmware_ops == &trusted_foundations_ops; -} diff --git a/arch/arm/include/asm/trusted_foundations.h b/arch/arm/include/asm/trusted_foundations.h deleted file mode 100644 index 54513c533811..000000000000 --- a/arch/arm/include/asm/trusted_foundations.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2013, NVIDIA Corporation. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -/* - * Support for the Trusted Foundations secure monitor. - * - * Trusted Foundation comes active on some ARM consumer devices (most - * Tegra-based devices sold on the market are concerned). Such devices can only - * perform some basic operations, like setting the CPU reset vector, through - * SMC calls to the secure monitor. The calls are completely specific to - * Trusted Foundations, and do *not* follow the SMC calling convention or the - * PSCI standard. - */ - -#ifndef __ASM_ARM_TRUSTED_FOUNDATIONS_H -#define __ASM_ARM_TRUSTED_FOUNDATIONS_H - -#include -#include -#include -#include -#include -#include - -#include -#include - -#define TF_PM_MODE_LP0 0 -#define TF_PM_MODE_LP1 1 -#define TF_PM_MODE_LP1_NO_MC_CLK 2 -#define TF_PM_MODE_LP2 3 -#define TF_PM_MODE_LP2_NOFLUSH_L2 4 - -struct trusted_foundations_platform_data { - unsigned int version_major; - unsigned int version_minor; -}; - -#if IS_ENABLED(CONFIG_TRUSTED_FOUNDATIONS) - -void register_trusted_foundations(struct trusted_foundations_platform_data *pd); -void of_register_trusted_foundations(void); -bool trusted_foundations_registered(void); - -#else /* CONFIG_TRUSTED_FOUNDATIONS */ -static inline void tf_dummy_write_sec(unsigned long val, unsigned int reg) -{ -} - -static inline void register_trusted_foundations( - struct trusted_foundations_platform_data *pd) -{ - /* - * If the system requires TF and we cannot provide it, continue booting - * but disable features that cannot be provided. - */ - pr_err("No support for Trusted Foundations, continuing in degraded mode.\n"); - pr_err("Secondary processors as well as CPU PM will be disabled.\n"); -#if IS_ENABLED(CONFIG_CACHE_L2X0) - pr_err("L2X0 cache will be kept disabled.\n"); - outer_cache.write_sec = tf_dummy_write_sec; -#endif -#if IS_ENABLED(CONFIG_SMP) - setup_max_cpus = 0; -#endif - cpu_idle_poll_ctrl(true); -} - -static inline void of_register_trusted_foundations(void) -{ - /* - * If we find the target should enable TF but does not support it, - * fail as the system won't be able to do much anyway - */ - if (of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations")) - register_trusted_foundations(NULL); -} - -static inline bool trusted_foundations_registered(void) -{ - return false; -} -#endif /* CONFIG_TRUSTED_FOUNDATIONS */ - -#endif diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig index 7b3fd0995a16..63e89e75639b 100644 --- a/arch/arm/mach-tegra/Kconfig +++ b/arch/arm/mach-tegra/Kconfig @@ -3,7 +3,6 @@ menuconfig ARCH_TEGRA bool "NVIDIA Tegra" depends on ARCH_MULTI_V7 select ARCH_HAS_RESET_CONTROLLER - select ARCH_SUPPORTS_TRUSTED_FOUNDATIONS select ARM_AMBA select ARM_GIC select CLKSRC_MMIO diff --git a/arch/arm/mach-tegra/cpuidle-tegra114.c b/arch/arm/mach-tegra/cpuidle-tegra114.c index 3b9af4766cdf..43c695d83f03 100644 --- a/arch/arm/mach-tegra/cpuidle-tegra114.c +++ b/arch/arm/mach-tegra/cpuidle-tegra114.c @@ -21,10 +21,11 @@ #include #include +#include + #include #include #include -#include #include #include "cpuidle.h" diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c index abf5f88778f4..1b0ade06f204 100644 --- a/arch/arm/mach-tegra/pm.c +++ b/arch/arm/mach-tegra/pm.c @@ -27,6 +27,8 @@ #include #include +#include + #include #include #include @@ -39,7 +41,6 @@ #include #include #include -#include #include "iomap.h" #include "pm.h" diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c index b02ae7699842..35dc5d419b6f 100644 --- a/arch/arm/mach-tegra/reset.c +++ b/arch/arm/mach-tegra/reset.c @@ -19,12 +19,13 @@ #include #include +#include + #include #include #include #include -#include #include "iomap.h" #include "irammap.h" diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c index 1e89cfefbf68..3e88f67dd521 100644 --- a/arch/arm/mach-tegra/tegra.c +++ b/arch/arm/mach-tegra/tegra.c @@ -35,6 +35,8 @@ #include #include +#include + #include #include @@ -44,7 +46,6 @@ #include #include #include -#include #include "board.h" #include "common.h" diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig index cac16c4b0df3..f0646ac75868 100644 --- a/drivers/firmware/Kconfig +++ b/drivers/firmware/Kconfig @@ -267,6 +267,22 @@ config TI_SCI_PROTOCOL This protocol library is used by client drivers to use the features provided by the system controller. +config TRUSTED_FOUNDATIONS + bool "Trusted Foundations secure monitor support" + depends on ARM + help + Some devices (including most early Tegra-based consumer devices on + the market) are booted with the Trusted Foundations secure monitor + active, requiring some core operations to be performed by the secure + monitor instead of the kernel. + + This option allows the kernel to invoke the secure monitor whenever + required on devices using Trusted Foundations. See the functions and + comments in linux/firmware/trusted_foundations.h or the device tree + bindings for "tlm,trusted-foundations" for details on how to use it. + + Choose N if you don't know what this is about. + config HAVE_ARM_SMCCC bool diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile index 80feb635120f..745f4907e69b 100644 --- a/drivers/firmware/Makefile +++ b/drivers/firmware/Makefile @@ -23,6 +23,7 @@ obj-$(CONFIG_QCOM_SCM_64) += qcom_scm-64.o obj-$(CONFIG_QCOM_SCM_32) += qcom_scm-32.o CFLAGS_qcom_scm-32.o :=$(call as-instr,.arch armv7-a\n.arch_extension sec,-DREQUIRES_SEC=1) -march=armv7-a obj-$(CONFIG_TI_SCI_PROTOCOL) += ti_sci.o +obj-$(CONFIG_TRUSTED_FOUNDATIONS) += trusted_foundations.o obj-$(CONFIG_ARM_SCMI_PROTOCOL) += arm_scmi/ obj-y += broadcom/ diff --git a/drivers/firmware/trusted_foundations.c b/drivers/firmware/trusted_foundations.c new file mode 100644 index 000000000000..fd4999388ff1 --- /dev/null +++ b/drivers/firmware/trusted_foundations.c @@ -0,0 +1,176 @@ +/* + * Trusted Foundations support for ARM CPUs + * + * Copyright (c) 2013, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include +#include +#include + +#include + +#include +#include +#include + +#define TF_CACHE_MAINT 0xfffff100 + +#define TF_CACHE_ENABLE 1 +#define TF_CACHE_DISABLE 2 + +#define TF_SET_CPU_BOOT_ADDR_SMC 0xfffff200 + +#define TF_CPU_PM 0xfffffffc +#define TF_CPU_PM_S3 0xffffffe3 +#define TF_CPU_PM_S2 0xffffffe6 +#define TF_CPU_PM_S2_NO_MC_CLK 0xffffffe5 +#define TF_CPU_PM_S1 0xffffffe4 +#define TF_CPU_PM_S1_NOFLUSH_L2 0xffffffe7 + +static unsigned long cpu_boot_addr; + +static void tf_generic_smc(u32 type, u32 arg1, u32 arg2) +{ + register u32 r0 asm("r0") = type; + register u32 r1 asm("r1") = arg1; + register u32 r2 asm("r2") = arg2; + + asm volatile( + ".arch_extension sec\n\t" + "stmfd sp!, {r4 - r11}\n\t" + __asmeq("%0", "r0") + __asmeq("%1", "r1") + __asmeq("%2", "r2") + "mov r3, #0\n\t" + "mov r4, #0\n\t" + "smc #0\n\t" + "ldmfd sp!, {r4 - r11}\n\t" + : + : "r" (r0), "r" (r1), "r" (r2) + : "memory", "r3", "r12", "lr"); +} + +static int tf_set_cpu_boot_addr(int cpu, unsigned long boot_addr) +{ + cpu_boot_addr = boot_addr; + tf_generic_smc(TF_SET_CPU_BOOT_ADDR_SMC, cpu_boot_addr, 0); + + return 0; +} + +static int tf_prepare_idle(unsigned long mode) +{ + switch (mode) { + case TF_PM_MODE_LP0: + tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S3, cpu_boot_addr); + break; + + case TF_PM_MODE_LP1: + tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S2, cpu_boot_addr); + break; + + case TF_PM_MODE_LP1_NO_MC_CLK: + tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S2_NO_MC_CLK, + cpu_boot_addr); + break; + + case TF_PM_MODE_LP2: + tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S1, cpu_boot_addr); + break; + + case TF_PM_MODE_LP2_NOFLUSH_L2: + tf_generic_smc(TF_CPU_PM, TF_CPU_PM_S1_NOFLUSH_L2, + cpu_boot_addr); + break; + + default: + return -EINVAL; + } + + return 0; +} + +#ifdef CONFIG_CACHE_L2X0 +static void tf_cache_write_sec(unsigned long val, unsigned int reg) +{ + u32 l2x0_way_mask = 0xff; + + switch (reg) { + case L2X0_CTRL: + if (l2x0_saved_regs.aux_ctrl & L310_AUX_CTRL_ASSOCIATIVITY_16) + l2x0_way_mask = 0xffff; + + if (val == L2X0_CTRL_EN) + tf_generic_smc(TF_CACHE_MAINT, TF_CACHE_ENABLE, + l2x0_saved_regs.aux_ctrl); + else + tf_generic_smc(TF_CACHE_MAINT, TF_CACHE_DISABLE, + l2x0_way_mask); + break; + + default: + break; + } +} + +static int tf_init_cache(void) +{ + outer_cache.write_sec = tf_cache_write_sec; + + return 0; +} +#endif /* CONFIG_CACHE_L2X0 */ + +static const struct firmware_ops trusted_foundations_ops = { + .set_cpu_boot_addr = tf_set_cpu_boot_addr, + .prepare_idle = tf_prepare_idle, +#ifdef CONFIG_CACHE_L2X0 + .l2x0_init = tf_init_cache, +#endif +}; + +void register_trusted_foundations(struct trusted_foundations_platform_data *pd) +{ + /* + * we are not using version information for now since currently + * supported SMCs are compatible with all TF releases + */ + register_firmware_ops(&trusted_foundations_ops); +} + +void of_register_trusted_foundations(void) +{ + struct device_node *node; + struct trusted_foundations_platform_data pdata; + int err; + + node = of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations"); + if (!node) + return; + + err = of_property_read_u32(node, "tlm,version-major", + &pdata.version_major); + if (err != 0) + panic("Trusted Foundation: missing version-major property\n"); + err = of_property_read_u32(node, "tlm,version-minor", + &pdata.version_minor); + if (err != 0) + panic("Trusted Foundation: missing version-minor property\n"); + register_trusted_foundations(&pdata); +} + +bool trusted_foundations_registered(void) +{ + return firmware_ops == &trusted_foundations_ops; +} diff --git a/include/linux/firmware/trusted_foundations.h b/include/linux/firmware/trusted_foundations.h new file mode 100644 index 000000000000..4064e7c74715 --- /dev/null +++ b/include/linux/firmware/trusted_foundations.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2013, NVIDIA Corporation. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +/* + * Support for the Trusted Foundations secure monitor. + * + * Trusted Foundation comes active on some ARM consumer devices (most + * Tegra-based devices sold on the market are concerned). Such devices can only + * perform some basic operations, like setting the CPU reset vector, through + * SMC calls to the secure monitor. The calls are completely specific to + * Trusted Foundations, and do *not* follow the SMC calling convention or the + * PSCI standard. + */ + +#ifndef __FIRMWARE_TRUSTED_FOUNDATIONS_H +#define __FIRMWARE_TRUSTED_FOUNDATIONS_H + +#include +#include +#include +#include +#include +#include + +#include +#include + +#define TF_PM_MODE_LP0 0 +#define TF_PM_MODE_LP1 1 +#define TF_PM_MODE_LP1_NO_MC_CLK 2 +#define TF_PM_MODE_LP2 3 +#define TF_PM_MODE_LP2_NOFLUSH_L2 4 + +struct trusted_foundations_platform_data { + unsigned int version_major; + unsigned int version_minor; +}; + +#if IS_ENABLED(CONFIG_TRUSTED_FOUNDATIONS) + +void register_trusted_foundations(struct trusted_foundations_platform_data *pd); +void of_register_trusted_foundations(void); +bool trusted_foundations_registered(void); + +#else /* CONFIG_TRUSTED_FOUNDATIONS */ +static inline void tf_dummy_write_sec(unsigned long val, unsigned int reg) +{ +} + +static inline void register_trusted_foundations( + struct trusted_foundations_platform_data *pd) +{ + /* + * If the system requires TF and we cannot provide it, continue booting + * but disable features that cannot be provided. + */ + pr_err("No support for Trusted Foundations, continuing in degraded mode.\n"); + pr_err("Secondary processors as well as CPU PM will be disabled.\n"); +#if IS_ENABLED(CONFIG_CACHE_L2X0) + pr_err("L2X0 cache will be kept disabled.\n"); + outer_cache.write_sec = tf_dummy_write_sec; +#endif +#if IS_ENABLED(CONFIG_SMP) + setup_max_cpus = 0; +#endif + cpu_idle_poll_ctrl(true); +} + +static inline void of_register_trusted_foundations(void) +{ + /* + * If we find the target should enable TF but does not support it, + * fail as the system won't be able to do much anyway + */ + if (of_find_compatible_node(NULL, NULL, "tlm,trusted-foundations")) + register_trusted_foundations(NULL); +} + +static inline bool trusted_foundations_registered(void) +{ + return false; +} +#endif /* CONFIG_TRUSTED_FOUNDATIONS */ + +#endif -- cgit v1.2.3 From 5b978c10665973d8ee7050b03ef6e97013066b03 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Fri, 25 Jan 2019 16:41:25 +0100 Subject: irqchip: Add driver for IXP4xx The IXP4xx (arch/arm/mach-ixp4xx) is an old Intel XScale platform that has very wide deployment and use. As part of modernizing the platform, we need to implement a proper irqchip in the irqchip subsystem. The IXP4xx irqchip is tightly jotted together with the GPIO controller, and whereas in the past we would deal with this complex logic by adding necessarily different code, we can nowadays modernize it using a hierarchical irqchip. The actual IXP4 irqchip is a simple active low level IRQ controller, whereas the GPIO functionality resides in a different memory area and adds edge trigger support for the interrupts. The interrupts from GPIO lines 0..12 are 1:1 mapped to a fixed set of hardware IRQs on this IRQchip, so we expect the child GPIO interrupt controller to go in and allocate descriptors for these interrupts. For the other interrupts, as we do not yet have DT support for this platform, we create a linear irqdomain and then go in and allocate the IRQs that the legacy boards use. This code will be removed on the DT probe path when we add DT support to the platform. We add some translation code for supporting DT translations for the fwnodes, but we leave most of that for later. Cc: Marc Zyngier Cc: Jason Cooper Acked-by: Marc Zyngier Signed-off-by: Linus Walleij --- MAINTAINERS | 2 + drivers/irqchip/Kconfig | 6 + drivers/irqchip/Makefile | 1 + drivers/irqchip/irq-ixp4xx.c | 362 +++++++++++++++++++++++++++++++++++++ include/linux/irqchip/irq-ixp4xx.h | 12 ++ 5 files changed, 383 insertions(+) create mode 100644 drivers/irqchip/irq-ixp4xx.c create mode 100644 include/linux/irqchip/irq-ixp4xx.h (limited to 'include/linux') diff --git a/MAINTAINERS b/MAINTAINERS index 0508cf8ed022..e12f7fc21b2b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1691,6 +1691,8 @@ M: Krzysztof Halasa L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-ixp4xx/ +F: drivers/irqchip/irq-ixp4xx.c +F: include/linux/irqchip/irq-ixp4xx.h ARM/INTEL RESEARCH IMOTE/STARGATE 2 MACHINE SUPPORT M: Jonathan Cameron diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index 5438abb1baba..cf7984991062 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -160,6 +160,12 @@ config IMGPDC_IRQ select GENERIC_IRQ_CHIP select IRQ_DOMAIN +config IXP4XX_IRQ + bool + select IRQ_DOMAIN + select GENERIC_IRQ_MULTI_HANDLER + select SPARSE_IRQ + config MADERA_IRQ tristate diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 85972ae1bd7f..f8c66e958a64 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -43,6 +43,7 @@ obj-$(CONFIG_ATMEL_AIC5_IRQ) += irq-atmel-aic-common.o irq-atmel-aic5.o obj-$(CONFIG_I8259) += irq-i8259.o obj-$(CONFIG_IMGPDC_IRQ) += irq-imgpdc.o obj-$(CONFIG_IRQ_MIPS_CPU) += irq-mips-cpu.o +obj-$(CONFIG_IXP4XX_IRQ) += irq-ixp4xx.o obj-$(CONFIG_SIRF_IRQ) += irq-sirfsoc.o obj-$(CONFIG_JCORE_AIC) += irq-jcore-aic.o obj-$(CONFIG_RDA_INTC) += irq-rda-intc.o diff --git a/drivers/irqchip/irq-ixp4xx.c b/drivers/irqchip/irq-ixp4xx.c new file mode 100644 index 000000000000..89c80ce047a7 --- /dev/null +++ b/drivers/irqchip/irq-ixp4xx.c @@ -0,0 +1,362 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * irqchip for the IXP4xx interrupt controller + * Copyright (C) 2019 Linus Walleij + * + * Based on arch/arm/mach-ixp4xx/common.c + * Copyright 2002 (C) Intel Corporation + * Copyright 2003-2004 (C) MontaVista, Software, Inc. + * Copyright (C) Deepak Saxena + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define IXP4XX_ICPR 0x00 /* Interrupt Status */ +#define IXP4XX_ICMR 0x04 /* Interrupt Enable */ +#define IXP4XX_ICLR 0x08 /* Interrupt IRQ/FIQ Select */ +#define IXP4XX_ICIP 0x0C /* IRQ Status */ +#define IXP4XX_ICFP 0x10 /* FIQ Status */ +#define IXP4XX_ICHR 0x14 /* Interrupt Priority */ +#define IXP4XX_ICIH 0x18 /* IRQ Highest Pri Int */ +#define IXP4XX_ICFH 0x1C /* FIQ Highest Pri Int */ + +/* IXP43x and IXP46x-only */ +#define IXP4XX_ICPR2 0x20 /* Interrupt Status 2 */ +#define IXP4XX_ICMR2 0x24 /* Interrupt Enable 2 */ +#define IXP4XX_ICLR2 0x28 /* Interrupt IRQ/FIQ Select 2 */ +#define IXP4XX_ICIP2 0x2C /* IRQ Status */ +#define IXP4XX_ICFP2 0x30 /* FIQ Status */ +#define IXP4XX_ICEEN 0x34 /* Error High Pri Enable */ + +/** + * struct ixp4xx_irq - state container for the Faraday IRQ controller + * @irqbase: IRQ controller memory base in virtual memory + * @is_356: if this is an IXP43x, IXP45x or IX46x SoC (with 64 IRQs) + * @irqchip: irqchip for this instance + * @domain: IRQ domain for this instance + */ +struct ixp4xx_irq { + void __iomem *irqbase; + bool is_356; + struct irq_chip irqchip; + struct irq_domain *domain; +}; + +/* Local static state container */ +static struct ixp4xx_irq ixirq; + +/* GPIO Clocks */ +#define IXP4XX_GPIO_CLK_0 14 +#define IXP4XX_GPIO_CLK_1 15 + +static int ixp4xx_set_irq_type(struct irq_data *d, unsigned int type) +{ + /* All are level active high (asserted) here */ + if (type != IRQ_TYPE_LEVEL_HIGH) + return -EINVAL; + return 0; +} + +static void ixp4xx_irq_mask(struct irq_data *d) +{ + struct ixp4xx_irq *ixi = irq_data_get_irq_chip_data(d); + u32 val; + + if (ixi->is_356 && d->hwirq >= 32) { + val = __raw_readl(ixi->irqbase + IXP4XX_ICMR2); + val &= ~BIT(d->hwirq - 32); + __raw_writel(val, ixi->irqbase + IXP4XX_ICMR2); + } else { + val = __raw_readl(ixi->irqbase + IXP4XX_ICMR); + val &= ~BIT(d->hwirq); + __raw_writel(val, ixi->irqbase + IXP4XX_ICMR); + } +} + +/* + * Level triggered interrupts on GPIO lines can only be cleared when the + * interrupt condition disappears. + */ +static void ixp4xx_irq_unmask(struct irq_data *d) +{ + struct ixp4xx_irq *ixi = irq_data_get_irq_chip_data(d); + u32 val; + + if (ixi->is_356 && d->hwirq >= 32) { + val = __raw_readl(ixi->irqbase + IXP4XX_ICMR2); + val |= BIT(d->hwirq - 32); + __raw_writel(val, ixi->irqbase + IXP4XX_ICMR2); + } else { + val = __raw_readl(ixi->irqbase + IXP4XX_ICMR); + val |= BIT(d->hwirq); + __raw_writel(val, ixi->irqbase + IXP4XX_ICMR); + } +} + +asmlinkage void __exception_irq_entry ixp4xx_handle_irq(struct pt_regs *regs) +{ + struct ixp4xx_irq *ixi = &ixirq; + unsigned long status; + int i; + + status = __raw_readl(ixi->irqbase + IXP4XX_ICIP); + for_each_set_bit(i, &status, 32) + handle_domain_irq(ixi->domain, i, regs); + + /* + * IXP465/IXP435 has an upper IRQ status register + */ + if (ixi->is_356) { + status = __raw_readl(ixi->irqbase + IXP4XX_ICIP2); + for_each_set_bit(i, &status, 32) + handle_domain_irq(ixi->domain, i + 32, regs); + } +} + +static int ixp4xx_irq_domain_translate(struct irq_domain *domain, + struct irq_fwspec *fwspec, + unsigned long *hwirq, + unsigned int *type) +{ + /* We support standard DT translation */ + if (is_of_node(fwspec->fwnode) && fwspec->param_count == 2) { + *hwirq = fwspec->param[0]; + *type = fwspec->param[1]; + return 0; + } + + if (is_fwnode_irqchip(fwspec->fwnode)) { + if (fwspec->param_count != 2) + return -EINVAL; + *hwirq = fwspec->param[0]; + *type = fwspec->param[1]; + WARN_ON(*type == IRQ_TYPE_NONE); + return 0; + } + + return -EINVAL; +} + +static int ixp4xx_irq_domain_alloc(struct irq_domain *d, + unsigned int irq, unsigned int nr_irqs, + void *data) +{ + struct ixp4xx_irq *ixi = d->host_data; + irq_hw_number_t hwirq; + unsigned int type = IRQ_TYPE_NONE; + struct irq_fwspec *fwspec = data; + int ret; + int i; + + ret = ixp4xx_irq_domain_translate(d, fwspec, &hwirq, &type); + if (ret) + return ret; + + for (i = 0; i < nr_irqs; i++) { + /* + * TODO: after converting IXP4xx to only device tree, set + * handle_bad_irq as default handler and assume all consumers + * call .set_type() as this is provided in the second cell in + * the device tree phandle. + */ + irq_domain_set_info(d, + irq + i, + hwirq + i, + &ixi->irqchip, + ixi, + handle_level_irq, + NULL, NULL); + irq_set_probe(irq + i); + } + + return 0; +} + +/* + * This needs to be a hierarchical irqdomain to work well with the + * GPIO irqchip (which is lower in the hierarchy) + */ +static const struct irq_domain_ops ixp4xx_irqdomain_ops = { + .translate = ixp4xx_irq_domain_translate, + .alloc = ixp4xx_irq_domain_alloc, + .free = irq_domain_free_irqs_common, +}; + +/** + * ixp4xx_get_irq_domain() - retrieve the ixp4xx irq domain + * + * This function will go away when we transition to DT probing. + */ +struct irq_domain *ixp4xx_get_irq_domain(void) +{ + struct ixp4xx_irq *ixi = &ixirq; + + return ixi->domain; +} +EXPORT_SYMBOL_GPL(ixp4xx_get_irq_domain); + +/* + * This is the Linux IRQ to hwirq mapping table. This goes away when + * we have DT support as all IRQ resources are defined in the device + * tree. It will register all the IRQs that are not used by the hierarchical + * GPIO IRQ chip. The "holes" inbetween these IRQs will be requested by + * the GPIO driver using . This is a step-gap solution. + */ +struct ixp4xx_irq_chunk { + int irq; + int hwirq; + int nr_irqs; +}; + +static const struct ixp4xx_irq_chunk ixp4xx_irq_chunks[] = { + { + .irq = 16, + .hwirq = 0, + .nr_irqs = 6, + }, + { + .irq = 24, + .hwirq = 8, + .nr_irqs = 11, + }, + { + .irq = 46, + .hwirq = 30, + .nr_irqs = 2, + }, + /* Only on the 436 variants */ + { + .irq = 48, + .hwirq = 32, + .nr_irqs = 10, + }, +}; + +/** + * ixp4x_irq_setup() - Common setup code for the IXP4xx interrupt controller + * @ixi: State container + * @irqbase: Virtual memory base for the interrupt controller + * @fwnode: Corresponding fwnode abstraction for this controller + * @is_356: if this is an IXP43x, IXP45x or IXP46x SoC variant + */ +static int ixp4xx_irq_setup(struct ixp4xx_irq *ixi, + void __iomem *irqbase, + struct fwnode_handle *fwnode, + bool is_356) +{ + int nr_irqs; + + ixi->irqbase = irqbase; + ixi->is_356 = is_356; + + /* Route all sources to IRQ instead of FIQ */ + __raw_writel(0x0, ixi->irqbase + IXP4XX_ICLR); + + /* Disable all interrupts */ + __raw_writel(0x0, ixi->irqbase + IXP4XX_ICMR); + + if (is_356) { + /* Route upper 32 sources to IRQ instead of FIQ */ + __raw_writel(0x0, ixi->irqbase + IXP4XX_ICLR2); + + /* Disable upper 32 interrupts */ + __raw_writel(0x0, ixi->irqbase + IXP4XX_ICMR2); + + nr_irqs = 64; + } else { + nr_irqs = 32; + } + + ixi->irqchip.name = "IXP4xx"; + ixi->irqchip.irq_mask = ixp4xx_irq_mask; + ixi->irqchip.irq_unmask = ixp4xx_irq_unmask; + ixi->irqchip.irq_set_type = ixp4xx_set_irq_type; + + ixi->domain = irq_domain_create_linear(fwnode, nr_irqs, + &ixp4xx_irqdomain_ops, + ixi); + if (!ixi->domain) { + pr_crit("IXP4XX: can not add primary irqdomain\n"); + return -ENODEV; + } + + set_handle_irq(ixp4xx_handle_irq); + + return 0; +} + +/** + * ixp4xx_irq_init() - Function to initialize the irqchip from boardfiles + * @irqbase: physical base for the irq controller + * @is_356: if this is an IXP43x, IXP45x or IXP46x SoC variant + */ +void __init ixp4xx_irq_init(resource_size_t irqbase, + bool is_356) +{ + struct ixp4xx_irq *ixi = &ixirq; + void __iomem *base; + struct fwnode_handle *fwnode; + struct irq_fwspec fwspec; + int nr_chunks; + int ret; + int i; + + base = ioremap(irqbase, 0x100); + if (!base) { + pr_crit("IXP4XX: could not ioremap interrupt controller\n"); + return; + } + fwnode = irq_domain_alloc_fwnode(base); + if (!fwnode) { + pr_crit("IXP4XX: no domain handle\n"); + return; + } + ret = ixp4xx_irq_setup(ixi, base, fwnode, is_356); + if (ret) { + pr_crit("IXP4XX: failed to set up irqchip\n"); + irq_domain_free_fwnode(fwnode); + } + + nr_chunks = ARRAY_SIZE(ixp4xx_irq_chunks); + if (!is_356) + nr_chunks--; + + /* + * After adding OF support, this is no longer needed: irqs + * will be allocated for the respective fwnodes. + */ + for (i = 0; i < nr_chunks; i++) { + const struct ixp4xx_irq_chunk *chunk = &ixp4xx_irq_chunks[i]; + + pr_info("Allocate Linux IRQs %d..%d HW IRQs %d..%d\n", + chunk->irq, chunk->irq + chunk->nr_irqs - 1, + chunk->hwirq, chunk->hwirq + chunk->nr_irqs - 1); + fwspec.fwnode = fwnode; + fwspec.param[0] = chunk->hwirq; + fwspec.param[1] = IRQ_TYPE_LEVEL_HIGH; + fwspec.param_count = 2; + ret = __irq_domain_alloc_irqs(ixi->domain, + chunk->irq, + chunk->nr_irqs, + NUMA_NO_NODE, + &fwspec, + false, + NULL); + if (ret < 0) { + pr_crit("IXP4XX: can not allocate irqs in hierarchy %d\n", + ret); + return; + } + } +} +EXPORT_SYMBOL_GPL(ixp4xx_irq_init); diff --git a/include/linux/irqchip/irq-ixp4xx.h b/include/linux/irqchip/irq-ixp4xx.h new file mode 100644 index 000000000000..9395917d6936 --- /dev/null +++ b/include/linux/irqchip/irq-ixp4xx.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __IRQ_IXP4XX_H +#define __IRQ_IXP4XX_H + +#include +struct irq_domain; + +void ixp4xx_irq_init(resource_size_t irqbase, + bool is_356); +struct irq_domain *ixp4xx_get_irq_domain(void); + +#endif /* __IRQ_IXP4XX_H */ -- cgit v1.2.3 From 13e0b4059b984a1c63cae5604e1f665472751ea1 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sat, 26 Jan 2019 00:49:19 +0100 Subject: clocksource/drivers/ixp4xx: Add driver This adds a new slightly rewritten timer driver for the Intel IXP4xx clocksource, clockevent and delay timer. Cc: Daniel Lezcano Cc: Thomas Gleixner Signed-off-by: Linus Walleij --- MAINTAINERS | 2 + drivers/clocksource/Kconfig | 7 + drivers/clocksource/Makefile | 1 + drivers/clocksource/timer-ixp4xx.c | 249 +++++++++++++++++++++++++++++ include/linux/platform_data/timer-ixp4xx.h | 11 ++ 5 files changed, 270 insertions(+) create mode 100644 drivers/clocksource/timer-ixp4xx.c create mode 100644 include/linux/platform_data/timer-ixp4xx.h (limited to 'include/linux') diff --git a/MAINTAINERS b/MAINTAINERS index 353821fdc700..bc918f318797 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1691,9 +1691,11 @@ M: Krzysztof Halasa L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained F: arch/arm/mach-ixp4xx/ +F: drivers/clocksource/timer-ixp4xx.c F: drivers/gpio/gpio-ixp4xx.c F: drivers/irqchip/irq-ixp4xx.c F: include/linux/irqchip/irq-ixp4xx.h +F: include/linux/platform_data/timer-ixp4xx.h ARM/INTEL RESEARCH IMOTE/STARGATE 2 MACHINE SUPPORT M: Jonathan Cameron diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig index 171502a356aa..6d2b0d821c27 100644 --- a/drivers/clocksource/Kconfig +++ b/drivers/clocksource/Kconfig @@ -69,6 +69,13 @@ config FTTMR010_TIMER Enables support for the Faraday Technology timer block FTTMR010. +config IXP4XX_TIMER + bool "Intel XScale IXP4xx timer driver" if COMPILE_TEST + depends on HAS_IOMEM + select CLKSRC_MMIO + help + Enables support for the Intel XScale IXP4xx SoC timer. + config ROCKCHIP_TIMER bool "Rockchip timer driver" if COMPILE_TEST depends on ARM || ARM64 diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile index be6e0fbc7489..dba4eff880de 100644 --- a/drivers/clocksource/Makefile +++ b/drivers/clocksource/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_OMAP_DM_TIMER) += timer-ti-dm.o obj-$(CONFIG_DW_APB_TIMER) += dw_apb_timer.o obj-$(CONFIG_DW_APB_TIMER_OF) += dw_apb_timer_of.o obj-$(CONFIG_FTTMR010_TIMER) += timer-fttmr010.o +obj-$(CONFIG_IXP4XX_TIMER) += timer-ixp4xx.o obj-$(CONFIG_ROCKCHIP_TIMER) += timer-rockchip.o obj-$(CONFIG_CLKSRC_NOMADIK_MTU) += nomadik-mtu.o obj-$(CONFIG_CLKSRC_DBX500_PRCMU) += clksrc-dbx500-prcmu.o diff --git a/drivers/clocksource/timer-ixp4xx.c b/drivers/clocksource/timer-ixp4xx.c new file mode 100644 index 000000000000..fa78f80792db --- /dev/null +++ b/drivers/clocksource/timer-ixp4xx.c @@ -0,0 +1,249 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * IXP4 timer driver + * Copyright (C) 2019 Linus Walleij + * + * Based on arch/arm/mach-ixp4xx/common.c + * Copyright 2002 (C) Intel Corporation + * Copyright 2003-2004 (C) MontaVista, Software, Inc. + * Copyright (C) Deepak Saxena + */ +#include +#include +#include +#include +#include +#include +#include +#include +/* Goes away with OF conversion */ +#include + +/* + * Constants to make it easy to access Timer Control/Status registers + */ +#define IXP4XX_OSTS_OFFSET 0x00 /* Continuous Timestamp */ +#define IXP4XX_OST1_OFFSET 0x04 /* Timer 1 Timestamp */ +#define IXP4XX_OSRT1_OFFSET 0x08 /* Timer 1 Reload */ +#define IXP4XX_OST2_OFFSET 0x0C /* Timer 2 Timestamp */ +#define IXP4XX_OSRT2_OFFSET 0x10 /* Timer 2 Reload */ +#define IXP4XX_OSWT_OFFSET 0x14 /* Watchdog Timer */ +#define IXP4XX_OSWE_OFFSET 0x18 /* Watchdog Enable */ +#define IXP4XX_OSWK_OFFSET 0x1C /* Watchdog Key */ +#define IXP4XX_OSST_OFFSET 0x20 /* Timer Status */ + +/* + * Timer register values and bit definitions + */ +#define IXP4XX_OST_ENABLE 0x00000001 +#define IXP4XX_OST_ONE_SHOT 0x00000002 +/* Low order bits of reload value ignored */ +#define IXP4XX_OST_RELOAD_MASK 0x00000003 +#define IXP4XX_OST_DISABLED 0x00000000 +#define IXP4XX_OSST_TIMER_1_PEND 0x00000001 +#define IXP4XX_OSST_TIMER_2_PEND 0x00000002 +#define IXP4XX_OSST_TIMER_TS_PEND 0x00000004 +#define IXP4XX_OSST_TIMER_WDOG_PEND 0x00000008 +#define IXP4XX_OSST_TIMER_WARM_RESET 0x00000010 + +#define IXP4XX_WDT_KEY 0x0000482E +#define IXP4XX_WDT_RESET_ENABLE 0x00000001 +#define IXP4XX_WDT_IRQ_ENABLE 0x00000002 +#define IXP4XX_WDT_COUNT_ENABLE 0x00000004 + +struct ixp4xx_timer { + void __iomem *base; + unsigned int tick_rate; + u32 latch; + struct clock_event_device clkevt; +#ifdef CONFIG_ARM + struct delay_timer delay_timer; +#endif +}; + +/* + * A local singleton used by sched_clock and delay timer reads, which are + * fast and stateless + */ +static struct ixp4xx_timer *local_ixp4xx_timer; + +static inline struct ixp4xx_timer * +to_ixp4xx_timer(struct clock_event_device *evt) +{ + return container_of(evt, struct ixp4xx_timer, clkevt); +} + +static u64 notrace ixp4xx_read_sched_clock(void) +{ + return __raw_readl(local_ixp4xx_timer->base + IXP4XX_OSTS_OFFSET); +} + +static u64 ixp4xx_clocksource_read(struct clocksource *c) +{ + return __raw_readl(local_ixp4xx_timer->base + IXP4XX_OSTS_OFFSET); +} + +static irqreturn_t ixp4xx_timer_interrupt(int irq, void *dev_id) +{ + struct ixp4xx_timer *tmr = dev_id; + struct clock_event_device *evt = &tmr->clkevt; + + /* Clear Pending Interrupt */ + __raw_writel(IXP4XX_OSST_TIMER_1_PEND, + tmr->base + IXP4XX_OSST_OFFSET); + + evt->event_handler(evt); + + return IRQ_HANDLED; +} + +static int ixp4xx_set_next_event(unsigned long cycles, + struct clock_event_device *evt) +{ + struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt); + u32 val; + + val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET); + /* Keep enable/oneshot bits */ + val &= IXP4XX_OST_RELOAD_MASK; + __raw_writel((cycles & ~IXP4XX_OST_RELOAD_MASK) | val, + tmr->base + IXP4XX_OSRT1_OFFSET); + + return 0; +} + +static int ixp4xx_shutdown(struct clock_event_device *evt) +{ + struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt); + u32 val; + + val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET); + val &= ~IXP4XX_OST_ENABLE; + __raw_writel(val, tmr->base + IXP4XX_OSRT1_OFFSET); + + return 0; +} + +static int ixp4xx_set_oneshot(struct clock_event_device *evt) +{ + struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt); + + __raw_writel(IXP4XX_OST_ENABLE | IXP4XX_OST_ONE_SHOT, + tmr->base + IXP4XX_OSRT1_OFFSET); + + return 0; +} + +static int ixp4xx_set_periodic(struct clock_event_device *evt) +{ + struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt); + u32 val; + + val = tmr->latch & ~IXP4XX_OST_RELOAD_MASK; + val |= IXP4XX_OST_ENABLE; + __raw_writel(val, tmr->base + IXP4XX_OSRT1_OFFSET); + + return 0; +} + +static int ixp4xx_resume(struct clock_event_device *evt) +{ + struct ixp4xx_timer *tmr = to_ixp4xx_timer(evt); + u32 val; + + val = __raw_readl(tmr->base + IXP4XX_OSRT1_OFFSET); + val |= IXP4XX_OST_ENABLE; + __raw_writel(val, tmr->base + IXP4XX_OSRT1_OFFSET); + + return 0; +} + +/* + * IXP4xx timer tick + * We use OS timer1 on the CPU for the timer tick and the timestamp + * counter as a source of real clock ticks to account for missed jiffies. + */ +static __init int ixp4xx_timer_register(void __iomem *base, + int timer_irq, + unsigned int timer_freq) +{ + struct ixp4xx_timer *tmr; + int ret; + + tmr = kzalloc(sizeof(*tmr), GFP_KERNEL); + if (!tmr) + return -ENOMEM; + tmr->base = base; + tmr->tick_rate = timer_freq; + + /* + * The timer register doesn't allow to specify the two least + * significant bits of the timeout value and assumes them being zero. + * So make sure the latch is the best value with the two least + * significant bits unset. + */ + tmr->latch = DIV_ROUND_CLOSEST(timer_freq, + (IXP4XX_OST_RELOAD_MASK + 1) * HZ) + * (IXP4XX_OST_RELOAD_MASK + 1); + + local_ixp4xx_timer = tmr; + + /* Reset/disable counter */ + __raw_writel(0, tmr->base + IXP4XX_OSRT1_OFFSET); + + /* Clear any pending interrupt on timer 1 */ + __raw_writel(IXP4XX_OSST_TIMER_1_PEND, + tmr->base + IXP4XX_OSST_OFFSET); + + /* Reset time-stamp counter */ + __raw_writel(0, tmr->base + IXP4XX_OSTS_OFFSET); + + clocksource_mmio_init(NULL, "OSTS", timer_freq, 200, 32, + ixp4xx_clocksource_read); + + tmr->clkevt.name = "ixp4xx timer1"; + tmr->clkevt.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT; + tmr->clkevt.rating = 200; + tmr->clkevt.set_state_shutdown = ixp4xx_shutdown; + tmr->clkevt.set_state_periodic = ixp4xx_set_periodic; + tmr->clkevt.set_state_oneshot = ixp4xx_set_oneshot; + tmr->clkevt.tick_resume = ixp4xx_resume; + tmr->clkevt.set_next_event = ixp4xx_set_next_event; + tmr->clkevt.cpumask = cpumask_of(0); + tmr->clkevt.irq = timer_irq; + ret = request_irq(timer_irq, ixp4xx_timer_interrupt, + IRQF_TIMER, "IXP4XX-TIMER1", tmr); + if (ret) { + pr_crit("no timer IRQ\n"); + return -ENODEV; + } + clockevents_config_and_register(&tmr->clkevt, timer_freq, + 0xf, 0xfffffffe); + +#ifdef CONFIG_ARM + sched_clock_register(ixp4xx_read_sched_clock, 32, timer_freq); +#endif + + return 0; +} + +/** + * ixp4xx_timer_setup() - Timer setup function to be called from boardfiles + * @timerbase: physical base of timer block + * @timer_irq: Linux IRQ number for the timer + * @timer_freq: Fixed frequency of the timer + */ +void __init ixp4xx_timer_setup(resource_size_t timerbase, + int timer_irq, + unsigned int timer_freq) +{ + void __iomem *base; + + base = ioremap(timerbase, 0x100); + if (!base) { + pr_crit("IXP4xx: can't remap timer\n"); + return; + } + ixp4xx_timer_register(base, timer_irq, timer_freq); +} +EXPORT_SYMBOL_GPL(ixp4xx_timer_setup); diff --git a/include/linux/platform_data/timer-ixp4xx.h b/include/linux/platform_data/timer-ixp4xx.h new file mode 100644 index 000000000000..ee92ae7edaed --- /dev/null +++ b/include/linux/platform_data/timer-ixp4xx.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __TIMER_IXP4XX_H +#define __TIMER_IXP4XX_H + +#include + +void __init ixp4xx_timer_setup(resource_size_t timerbase, + int timer_irq, + unsigned int timer_freq); + +#endif -- cgit v1.2.3 From 4af20dc583b364fad45df6fb81873606af8b70fb Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 10 Feb 2019 14:55:58 +0100 Subject: ARM: ixp4xx: Move IXP4xx QMGR and NPE headers This moves the IXP4xx Queue Manager and Network Processing Engine headers out of the include path as that is incompatible with multiplatform. Signed-off-by: Linus Walleij --- MAINTAINERS | 4 +- arch/arm/mach-ixp4xx/include/mach/npe.h | 40 ------ arch/arm/mach-ixp4xx/include/mach/qmgr.h | 204 ------------------------------- drivers/crypto/ixp4xx_crypto.c | 4 +- drivers/net/ethernet/xscale/ixp4xx_eth.c | 4 +- drivers/net/wan/ixp4xx_hss.c | 4 +- drivers/soc/ixp4xx/ixp4xx-npe.c | 2 +- drivers/soc/ixp4xx/ixp4xx-qmgr.c | 2 +- include/linux/soc/ixp4xx/npe.h | 40 ++++++ include/linux/soc/ixp4xx/qmgr.h | 204 +++++++++++++++++++++++++++++++ 10 files changed, 254 insertions(+), 254 deletions(-) delete mode 100644 arch/arm/mach-ixp4xx/include/mach/npe.h delete mode 100644 arch/arm/mach-ixp4xx/include/mach/qmgr.h create mode 100644 include/linux/soc/ixp4xx/npe.h create mode 100644 include/linux/soc/ixp4xx/qmgr.h (limited to 'include/linux') diff --git a/MAINTAINERS b/MAINTAINERS index dbbd7594a9b8..fb5911d46c2d 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7886,8 +7886,8 @@ F: Documentation/media/v4l-drivers/ipu3.rst INTEL IXP4XX QMGR, NPE, ETHERNET and HSS SUPPORT M: Krzysztof Halasa S: Maintained -F: arch/arm/mach-ixp4xx/include/mach/qmgr.h -F: arch/arm/mach-ixp4xx/include/mach/npe.h +F: include/linux/soc/ixp4xx/qmgr.h +F: include/linux/soc/ixp4xx/npe.h F: drivers/soc/ixp4xx/ixp4xx-qmgr.c F: drivers/soc/ixp4xx/ixp4xx-npe.c F: drivers/net/ethernet/xscale/ixp4xx_eth.c diff --git a/arch/arm/mach-ixp4xx/include/mach/npe.h b/arch/arm/mach-ixp4xx/include/mach/npe.h deleted file mode 100644 index 3a980845e557..000000000000 --- a/arch/arm/mach-ixp4xx/include/mach/npe.h +++ /dev/null @@ -1,40 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __IXP4XX_NPE_H -#define __IXP4XX_NPE_H - -#include - -extern const char *npe_names[]; - -struct npe_regs { - u32 exec_addr, exec_data, exec_status_cmd, exec_count; - u32 action_points[4]; - u32 watchpoint_fifo, watch_count; - u32 profile_count; - u32 messaging_status, messaging_control; - u32 mailbox_status, /*messaging_*/ in_out_fifo; -}; - -struct npe { - struct resource *mem_res; - struct npe_regs __iomem *regs; - u32 regs_phys; - int id; - int valid; -}; - - -static inline const char *npe_name(struct npe *npe) -{ - return npe_names[npe->id]; -} - -int npe_running(struct npe *npe); -int npe_send_message(struct npe *npe, const void *msg, const char *what); -int npe_recv_message(struct npe *npe, void *msg, const char *what); -int npe_send_recv_message(struct npe *npe, void *msg, const char *what); -int npe_load_firmware(struct npe *npe, const char *name, struct device *dev); -struct npe *npe_request(unsigned id); -void npe_release(struct npe *npe); - -#endif /* __IXP4XX_NPE_H */ diff --git a/arch/arm/mach-ixp4xx/include/mach/qmgr.h b/arch/arm/mach-ixp4xx/include/mach/qmgr.h deleted file mode 100644 index 4de8da536dbb..000000000000 --- a/arch/arm/mach-ixp4xx/include/mach/qmgr.h +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright (C) 2007 Krzysztof Halasa - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License - * as published by the Free Software Foundation. - */ - -#ifndef IXP4XX_QMGR_H -#define IXP4XX_QMGR_H - -#include -#include - -#define DEBUG_QMGR 0 - -#define HALF_QUEUES 32 -#define QUEUES 64 -#define MAX_QUEUE_LENGTH 4 /* in dwords */ - -#define QUEUE_STAT1_EMPTY 1 /* queue status bits */ -#define QUEUE_STAT1_NEARLY_EMPTY 2 -#define QUEUE_STAT1_NEARLY_FULL 4 -#define QUEUE_STAT1_FULL 8 -#define QUEUE_STAT2_UNDERFLOW 1 -#define QUEUE_STAT2_OVERFLOW 2 - -#define QUEUE_WATERMARK_0_ENTRIES 0 -#define QUEUE_WATERMARK_1_ENTRY 1 -#define QUEUE_WATERMARK_2_ENTRIES 2 -#define QUEUE_WATERMARK_4_ENTRIES 3 -#define QUEUE_WATERMARK_8_ENTRIES 4 -#define QUEUE_WATERMARK_16_ENTRIES 5 -#define QUEUE_WATERMARK_32_ENTRIES 6 -#define QUEUE_WATERMARK_64_ENTRIES 7 - -/* queue interrupt request conditions */ -#define QUEUE_IRQ_SRC_EMPTY 0 -#define QUEUE_IRQ_SRC_NEARLY_EMPTY 1 -#define QUEUE_IRQ_SRC_NEARLY_FULL 2 -#define QUEUE_IRQ_SRC_FULL 3 -#define QUEUE_IRQ_SRC_NOT_EMPTY 4 -#define QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY 5 -#define QUEUE_IRQ_SRC_NOT_NEARLY_FULL 6 -#define QUEUE_IRQ_SRC_NOT_FULL 7 - -struct qmgr_regs { - u32 acc[QUEUES][MAX_QUEUE_LENGTH]; /* 0x000 - 0x3FF */ - u32 stat1[4]; /* 0x400 - 0x40F */ - u32 stat2[2]; /* 0x410 - 0x417 */ - u32 statne_h; /* 0x418 - queue nearly empty */ - u32 statf_h; /* 0x41C - queue full */ - u32 irqsrc[4]; /* 0x420 - 0x42F IRC source */ - u32 irqen[2]; /* 0x430 - 0x437 IRQ enabled */ - u32 irqstat[2]; /* 0x438 - 0x43F - IRQ access only */ - u32 reserved[1776]; - u32 sram[2048]; /* 0x2000 - 0x3FFF - config and buffer */ -}; - -void qmgr_set_irq(unsigned int queue, int src, - void (*handler)(void *pdev), void *pdev); -void qmgr_enable_irq(unsigned int queue); -void qmgr_disable_irq(unsigned int queue); - -/* request_ and release_queue() must be called from non-IRQ context */ - -#if DEBUG_QMGR -extern char qmgr_queue_descs[QUEUES][32]; - -int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, - unsigned int nearly_empty_watermark, - unsigned int nearly_full_watermark, - const char *desc_format, const char* name); -#else -int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, - unsigned int nearly_empty_watermark, - unsigned int nearly_full_watermark); -#define qmgr_request_queue(queue, len, nearly_empty_watermark, \ - nearly_full_watermark, desc_format, name) \ - __qmgr_request_queue(queue, len, nearly_empty_watermark, \ - nearly_full_watermark) -#endif - -void qmgr_release_queue(unsigned int queue); - - -static inline void qmgr_put_entry(unsigned int queue, u32 val) -{ - struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; -#if DEBUG_QMGR - BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */ - - printk(KERN_DEBUG "Queue %s(%i) put %X\n", - qmgr_queue_descs[queue], queue, val); -#endif - __raw_writel(val, &qmgr_regs->acc[queue][0]); -} - -static inline u32 qmgr_get_entry(unsigned int queue) -{ - u32 val; - const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; - val = __raw_readl(&qmgr_regs->acc[queue][0]); -#if DEBUG_QMGR - BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */ - - printk(KERN_DEBUG "Queue %s(%i) get %X\n", - qmgr_queue_descs[queue], queue, val); -#endif - return val; -} - -static inline int __qmgr_get_stat1(unsigned int queue) -{ - const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; - return (__raw_readl(&qmgr_regs->stat1[queue >> 3]) - >> ((queue & 7) << 2)) & 0xF; -} - -static inline int __qmgr_get_stat2(unsigned int queue) -{ - const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; - BUG_ON(queue >= HALF_QUEUES); - return (__raw_readl(&qmgr_regs->stat2[queue >> 4]) - >> ((queue & 0xF) << 1)) & 0x3; -} - -/** - * qmgr_stat_empty() - checks if a hardware queue is empty - * @queue: queue number - * - * Returns non-zero value if the queue is empty. - */ -static inline int qmgr_stat_empty(unsigned int queue) -{ - BUG_ON(queue >= HALF_QUEUES); - return __qmgr_get_stat1(queue) & QUEUE_STAT1_EMPTY; -} - -/** - * qmgr_stat_below_low_watermark() - checks if a queue is below low watermark - * @queue: queue number - * - * Returns non-zero value if the queue is below low watermark. - */ -static inline int qmgr_stat_below_low_watermark(unsigned int queue) -{ - const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; - if (queue >= HALF_QUEUES) - return (__raw_readl(&qmgr_regs->statne_h) >> - (queue - HALF_QUEUES)) & 0x01; - return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY; -} - -/** - * qmgr_stat_above_high_watermark() - checks if a queue is above high watermark - * @queue: queue number - * - * Returns non-zero value if the queue is above high watermark - */ -static inline int qmgr_stat_above_high_watermark(unsigned int queue) -{ - BUG_ON(queue >= HALF_QUEUES); - return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_FULL; -} - -/** - * qmgr_stat_full() - checks if a hardware queue is full - * @queue: queue number - * - * Returns non-zero value if the queue is full. - */ -static inline int qmgr_stat_full(unsigned int queue) -{ - const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; - if (queue >= HALF_QUEUES) - return (__raw_readl(&qmgr_regs->statf_h) >> - (queue - HALF_QUEUES)) & 0x01; - return __qmgr_get_stat1(queue) & QUEUE_STAT1_FULL; -} - -/** - * qmgr_stat_underflow() - checks if a hardware queue experienced underflow - * @queue: queue number - * - * Returns non-zero value if the queue experienced underflow. - */ -static inline int qmgr_stat_underflow(unsigned int queue) -{ - return __qmgr_get_stat2(queue) & QUEUE_STAT2_UNDERFLOW; -} - -/** - * qmgr_stat_overflow() - checks if a hardware queue experienced overflow - * @queue: queue number - * - * Returns non-zero value if the queue experienced overflow. - */ -static inline int qmgr_stat_overflow(unsigned int queue) -{ - return __qmgr_get_stat2(queue) & QUEUE_STAT2_OVERFLOW; -} - -#endif diff --git a/drivers/crypto/ixp4xx_crypto.c b/drivers/crypto/ixp4xx_crypto.c index 5c4659b04d70..5522d64ecfda 100644 --- a/drivers/crypto/ixp4xx_crypto.c +++ b/drivers/crypto/ixp4xx_crypto.c @@ -30,8 +30,8 @@ #include #include -#include -#include +#include +#include #define MAX_KEYLEN 32 diff --git a/drivers/net/ethernet/xscale/ixp4xx_eth.c b/drivers/net/ethernet/xscale/ixp4xx_eth.c index 05d27fa9835f..319db3ece263 100644 --- a/drivers/net/ethernet/xscale/ixp4xx_eth.c +++ b/drivers/net/ethernet/xscale/ixp4xx_eth.c @@ -38,8 +38,8 @@ #include #include #include -#include -#include +#include +#include #define DEBUG_DESC 0 #define DEBUG_RX 0 diff --git a/drivers/net/wan/ixp4xx_hss.c b/drivers/net/wan/ixp4xx_hss.c index 5c60dc60a8e6..46a05b6540b8 100644 --- a/drivers/net/wan/ixp4xx_hss.c +++ b/drivers/net/wan/ixp4xx_hss.c @@ -22,8 +22,8 @@ #include #include #include -#include -#include +#include +#include #define DEBUG_DESC 0 #define DEBUG_RX 0 diff --git a/drivers/soc/ixp4xx/ixp4xx-npe.c b/drivers/soc/ixp4xx/ixp4xx-npe.c index e0ce22cd9bfc..1f6e01369d54 100644 --- a/drivers/soc/ixp4xx/ixp4xx-npe.c +++ b/drivers/soc/ixp4xx/ixp4xx-npe.c @@ -21,7 +21,7 @@ #include #include #include -#include +#include #define DEBUG_MSG 0 #define DEBUG_FW 0 diff --git a/drivers/soc/ixp4xx/ixp4xx-qmgr.c b/drivers/soc/ixp4xx/ixp4xx-qmgr.c index 2e6d33534afe..1bed048924bb 100644 --- a/drivers/soc/ixp4xx/ixp4xx-qmgr.c +++ b/drivers/soc/ixp4xx/ixp4xx-qmgr.c @@ -13,7 +13,7 @@ #include #include #include -#include +#include /* FIXME: get rid of these static assigments */ #define IRQ_IXP4XX_BASE 16 diff --git a/include/linux/soc/ixp4xx/npe.h b/include/linux/soc/ixp4xx/npe.h new file mode 100644 index 000000000000..3a980845e557 --- /dev/null +++ b/include/linux/soc/ixp4xx/npe.h @@ -0,0 +1,40 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __IXP4XX_NPE_H +#define __IXP4XX_NPE_H + +#include + +extern const char *npe_names[]; + +struct npe_regs { + u32 exec_addr, exec_data, exec_status_cmd, exec_count; + u32 action_points[4]; + u32 watchpoint_fifo, watch_count; + u32 profile_count; + u32 messaging_status, messaging_control; + u32 mailbox_status, /*messaging_*/ in_out_fifo; +}; + +struct npe { + struct resource *mem_res; + struct npe_regs __iomem *regs; + u32 regs_phys; + int id; + int valid; +}; + + +static inline const char *npe_name(struct npe *npe) +{ + return npe_names[npe->id]; +} + +int npe_running(struct npe *npe); +int npe_send_message(struct npe *npe, const void *msg, const char *what); +int npe_recv_message(struct npe *npe, void *msg, const char *what); +int npe_send_recv_message(struct npe *npe, void *msg, const char *what); +int npe_load_firmware(struct npe *npe, const char *name, struct device *dev); +struct npe *npe_request(unsigned id); +void npe_release(struct npe *npe); + +#endif /* __IXP4XX_NPE_H */ diff --git a/include/linux/soc/ixp4xx/qmgr.h b/include/linux/soc/ixp4xx/qmgr.h new file mode 100644 index 000000000000..4de8da536dbb --- /dev/null +++ b/include/linux/soc/ixp4xx/qmgr.h @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2007 Krzysztof Halasa + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of version 2 of the GNU General Public License + * as published by the Free Software Foundation. + */ + +#ifndef IXP4XX_QMGR_H +#define IXP4XX_QMGR_H + +#include +#include + +#define DEBUG_QMGR 0 + +#define HALF_QUEUES 32 +#define QUEUES 64 +#define MAX_QUEUE_LENGTH 4 /* in dwords */ + +#define QUEUE_STAT1_EMPTY 1 /* queue status bits */ +#define QUEUE_STAT1_NEARLY_EMPTY 2 +#define QUEUE_STAT1_NEARLY_FULL 4 +#define QUEUE_STAT1_FULL 8 +#define QUEUE_STAT2_UNDERFLOW 1 +#define QUEUE_STAT2_OVERFLOW 2 + +#define QUEUE_WATERMARK_0_ENTRIES 0 +#define QUEUE_WATERMARK_1_ENTRY 1 +#define QUEUE_WATERMARK_2_ENTRIES 2 +#define QUEUE_WATERMARK_4_ENTRIES 3 +#define QUEUE_WATERMARK_8_ENTRIES 4 +#define QUEUE_WATERMARK_16_ENTRIES 5 +#define QUEUE_WATERMARK_32_ENTRIES 6 +#define QUEUE_WATERMARK_64_ENTRIES 7 + +/* queue interrupt request conditions */ +#define QUEUE_IRQ_SRC_EMPTY 0 +#define QUEUE_IRQ_SRC_NEARLY_EMPTY 1 +#define QUEUE_IRQ_SRC_NEARLY_FULL 2 +#define QUEUE_IRQ_SRC_FULL 3 +#define QUEUE_IRQ_SRC_NOT_EMPTY 4 +#define QUEUE_IRQ_SRC_NOT_NEARLY_EMPTY 5 +#define QUEUE_IRQ_SRC_NOT_NEARLY_FULL 6 +#define QUEUE_IRQ_SRC_NOT_FULL 7 + +struct qmgr_regs { + u32 acc[QUEUES][MAX_QUEUE_LENGTH]; /* 0x000 - 0x3FF */ + u32 stat1[4]; /* 0x400 - 0x40F */ + u32 stat2[2]; /* 0x410 - 0x417 */ + u32 statne_h; /* 0x418 - queue nearly empty */ + u32 statf_h; /* 0x41C - queue full */ + u32 irqsrc[4]; /* 0x420 - 0x42F IRC source */ + u32 irqen[2]; /* 0x430 - 0x437 IRQ enabled */ + u32 irqstat[2]; /* 0x438 - 0x43F - IRQ access only */ + u32 reserved[1776]; + u32 sram[2048]; /* 0x2000 - 0x3FFF - config and buffer */ +}; + +void qmgr_set_irq(unsigned int queue, int src, + void (*handler)(void *pdev), void *pdev); +void qmgr_enable_irq(unsigned int queue); +void qmgr_disable_irq(unsigned int queue); + +/* request_ and release_queue() must be called from non-IRQ context */ + +#if DEBUG_QMGR +extern char qmgr_queue_descs[QUEUES][32]; + +int qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, + unsigned int nearly_empty_watermark, + unsigned int nearly_full_watermark, + const char *desc_format, const char* name); +#else +int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, + unsigned int nearly_empty_watermark, + unsigned int nearly_full_watermark); +#define qmgr_request_queue(queue, len, nearly_empty_watermark, \ + nearly_full_watermark, desc_format, name) \ + __qmgr_request_queue(queue, len, nearly_empty_watermark, \ + nearly_full_watermark) +#endif + +void qmgr_release_queue(unsigned int queue); + + +static inline void qmgr_put_entry(unsigned int queue, u32 val) +{ + struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; +#if DEBUG_QMGR + BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */ + + printk(KERN_DEBUG "Queue %s(%i) put %X\n", + qmgr_queue_descs[queue], queue, val); +#endif + __raw_writel(val, &qmgr_regs->acc[queue][0]); +} + +static inline u32 qmgr_get_entry(unsigned int queue) +{ + u32 val; + const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; + val = __raw_readl(&qmgr_regs->acc[queue][0]); +#if DEBUG_QMGR + BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */ + + printk(KERN_DEBUG "Queue %s(%i) get %X\n", + qmgr_queue_descs[queue], queue, val); +#endif + return val; +} + +static inline int __qmgr_get_stat1(unsigned int queue) +{ + const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; + return (__raw_readl(&qmgr_regs->stat1[queue >> 3]) + >> ((queue & 7) << 2)) & 0xF; +} + +static inline int __qmgr_get_stat2(unsigned int queue) +{ + const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; + BUG_ON(queue >= HALF_QUEUES); + return (__raw_readl(&qmgr_regs->stat2[queue >> 4]) + >> ((queue & 0xF) << 1)) & 0x3; +} + +/** + * qmgr_stat_empty() - checks if a hardware queue is empty + * @queue: queue number + * + * Returns non-zero value if the queue is empty. + */ +static inline int qmgr_stat_empty(unsigned int queue) +{ + BUG_ON(queue >= HALF_QUEUES); + return __qmgr_get_stat1(queue) & QUEUE_STAT1_EMPTY; +} + +/** + * qmgr_stat_below_low_watermark() - checks if a queue is below low watermark + * @queue: queue number + * + * Returns non-zero value if the queue is below low watermark. + */ +static inline int qmgr_stat_below_low_watermark(unsigned int queue) +{ + const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; + if (queue >= HALF_QUEUES) + return (__raw_readl(&qmgr_regs->statne_h) >> + (queue - HALF_QUEUES)) & 0x01; + return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY; +} + +/** + * qmgr_stat_above_high_watermark() - checks if a queue is above high watermark + * @queue: queue number + * + * Returns non-zero value if the queue is above high watermark + */ +static inline int qmgr_stat_above_high_watermark(unsigned int queue) +{ + BUG_ON(queue >= HALF_QUEUES); + return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_FULL; +} + +/** + * qmgr_stat_full() - checks if a hardware queue is full + * @queue: queue number + * + * Returns non-zero value if the queue is full. + */ +static inline int qmgr_stat_full(unsigned int queue) +{ + const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; + if (queue >= HALF_QUEUES) + return (__raw_readl(&qmgr_regs->statf_h) >> + (queue - HALF_QUEUES)) & 0x01; + return __qmgr_get_stat1(queue) & QUEUE_STAT1_FULL; +} + +/** + * qmgr_stat_underflow() - checks if a hardware queue experienced underflow + * @queue: queue number + * + * Returns non-zero value if the queue experienced underflow. + */ +static inline int qmgr_stat_underflow(unsigned int queue) +{ + return __qmgr_get_stat2(queue) & QUEUE_STAT2_UNDERFLOW; +} + +/** + * qmgr_stat_overflow() - checks if a hardware queue experienced overflow + * @queue: queue number + * + * Returns non-zero value if the queue experienced overflow. + */ +static inline int qmgr_stat_overflow(unsigned int queue) +{ + return __qmgr_get_stat2(queue) & QUEUE_STAT2_OVERFLOW; +} + +#endif -- cgit v1.2.3 From 0b458d7b10f83eb34b84957e6cf47cee2a97bc49 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 10 Feb 2019 19:35:08 +0100 Subject: soc: ixp4xx: npe: Pass addresses as resources Instead of using hardcoded base addresses implicitly obtained through , pass the physical base for the three NPE blocks as memory resources and remap these in the driver. Drop the memory request region business, this will anyways be done by devm_* remapping functions. Signed-off-by: Linus Walleij --- arch/arm/mach-ixp4xx/common.c | 21 +++++++++++++++ arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h | 3 --- drivers/soc/ixp4xx/ixp4xx-npe.c | 36 ++++++++++++++----------- include/linux/soc/ixp4xx/npe.h | 2 -- 4 files changed, 41 insertions(+), 21 deletions(-) (limited to 'include/linux') diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c index cdcd6d6b6d3d..07c3cb312a92 100644 --- a/arch/arm/mach-ixp4xx/common.c +++ b/arch/arm/mach-ixp4xx/common.c @@ -150,9 +150,30 @@ static struct platform_device ixp4xx_udc_device = { }, }; +static struct resource ixp4xx_npe_resources[] = { + { + .start = IXP4XX_NPEA_BASE_PHYS, + .end = IXP4XX_NPEA_BASE_PHYS + 0xfff, + .flags = IORESOURCE_MEM, + }, + { + .start = IXP4XX_NPEB_BASE_PHYS, + .end = IXP4XX_NPEB_BASE_PHYS + 0xfff, + .flags = IORESOURCE_MEM, + }, + { + .start = IXP4XX_NPEC_BASE_PHYS, + .end = IXP4XX_NPEC_BASE_PHYS + 0xfff, + .flags = IORESOURCE_MEM, + }, + +}; + static struct platform_device ixp4xx_npe_device = { .name = "ixp4xx-npe", .id = -1, + .num_resources = ARRAY_SIZE(ixp4xx_npe_resources), + .resource = ixp4xx_npe_resources, }; static struct platform_device ixp4xx_qmgr_device = { diff --git a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h index 459abe2eb4b5..f5d5b258c3f7 100644 --- a/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h +++ b/arch/arm/mach-ixp4xx/include/mach/ixp4xx-regs.h @@ -132,9 +132,6 @@ #define IXP4XX_INTC_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x3000) #define IXP4XX_GPIO_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x4000) #define IXP4XX_TIMER_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x5000) -#define IXP4XX_NPEA_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x6000) -#define IXP4XX_NPEB_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x7000) -#define IXP4XX_NPEC_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x8000) #define IXP4XX_EthB_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0x9000) #define IXP4XX_EthC_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0xA000) #define IXP4XX_USB_BASE_VIRT (IXP4XX_PERIPHERAL_BASE_VIRT + 0xB000) diff --git a/drivers/soc/ixp4xx/ixp4xx-npe.c b/drivers/soc/ixp4xx/ixp4xx-npe.c index e3294457b5de..d2dd916816d4 100644 --- a/drivers/soc/ixp4xx/ixp4xx-npe.c +++ b/drivers/soc/ixp4xx/ixp4xx-npe.c @@ -155,16 +155,10 @@ static struct { static struct npe npe_tab[NPE_COUNT] = { { .id = 0, - .regs = (struct npe_regs __iomem *)IXP4XX_NPEA_BASE_VIRT, - .regs_phys = IXP4XX_NPEA_BASE_PHYS, }, { .id = 1, - .regs = (struct npe_regs __iomem *)IXP4XX_NPEB_BASE_VIRT, - .regs_phys = IXP4XX_NPEB_BASE_PHYS, }, { .id = 2, - .regs = (struct npe_regs __iomem *)IXP4XX_NPEC_BASE_VIRT, - .regs_phys = IXP4XX_NPEC_BASE_PHYS, } }; @@ -687,23 +681,34 @@ void npe_release(struct npe *npe) static int ixp4xx_npe_probe(struct platform_device *pdev) { int i, found = 0; + struct device *dev = &pdev->dev; + struct resource *res; for (i = 0; i < NPE_COUNT; i++) { struct npe *npe = &npe_tab[i]; + + res = platform_get_resource(pdev, IORESOURCE_MEM, i); + if (!res) + return -ENODEV; + if (!(ixp4xx_read_feature_bits() & - (IXP4XX_FEATURE_RESET_NPEA << i))) + (IXP4XX_FEATURE_RESET_NPEA << i))) { + dev_info(dev, "NPE%d at 0x%08x-0x%08x not available\n", + i, res->start, res->end); continue; /* NPE already disabled or not present */ - if (!(npe->mem_res = request_mem_region(npe->regs_phys, - REGS_SIZE, - npe_name(npe)))) { - print_npe(KERN_ERR, npe, - "failed to request memory region\n"); - continue; } + npe->regs = devm_ioremap_resource(dev, res); + if (!npe->regs) + return -ENOMEM; - if (npe_reset(npe)) + if (npe_reset(npe)) { + dev_info(dev, "NPE%d at 0x%08x-0x%08x does not reset\n", + i, res->start, res->end); continue; + } npe->valid = 1; + dev_info(dev, "NPE%d at 0x%08x-0x%08x registered\n", + i, res->start, res->end); found++; } @@ -717,9 +722,8 @@ static int ixp4xx_npe_remove(struct platform_device *pdev) int i; for (i = 0; i < NPE_COUNT; i++) - if (npe_tab[i].mem_res) { + if (npe_tab[i].regs) { npe_reset(&npe_tab[i]); - release_resource(npe_tab[i].mem_res); } return 0; diff --git a/include/linux/soc/ixp4xx/npe.h b/include/linux/soc/ixp4xx/npe.h index 3a980845e557..2a91f465d456 100644 --- a/include/linux/soc/ixp4xx/npe.h +++ b/include/linux/soc/ixp4xx/npe.h @@ -16,9 +16,7 @@ struct npe_regs { }; struct npe { - struct resource *mem_res; struct npe_regs __iomem *regs; - u32 regs_phys; int id; int valid; }; -- cgit v1.2.3 From d08502f245f985df54be57eaac13c72907b0a3a7 Mon Sep 17 00:00:00 2001 From: Linus Walleij Date: Sun, 10 Feb 2019 20:15:11 +0100 Subject: soc: ixp4xx: Uninline several functions These inline functions immediately exploit the static ioremaps for the queue manager memory region. This does not work with multiplatform where everything need to be dynamically remapped, so get rid of these inlines and create new exports for those used by other drivers. Signed-off-by: Linus Walleij --- drivers/soc/ixp4xx/ixp4xx-qmgr.c | 117 ++++++++++++++++++++++++++++++++++++ include/linux/soc/ixp4xx/qmgr.h | 127 +++------------------------------------ 2 files changed, 124 insertions(+), 120 deletions(-) (limited to 'include/linux') diff --git a/drivers/soc/ixp4xx/ixp4xx-qmgr.c b/drivers/soc/ixp4xx/ixp4xx-qmgr.c index 133914e99aeb..412a346136d8 100644 --- a/drivers/soc/ixp4xx/ixp4xx-qmgr.c +++ b/drivers/soc/ixp4xx/ixp4xx-qmgr.c @@ -32,6 +32,117 @@ static void *irq_pdevs[QUEUES]; char qmgr_queue_descs[QUEUES][32]; #endif +void qmgr_put_entry(unsigned int queue, u32 val) +{ +#if DEBUG_QMGR + BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */ + + printk(KERN_DEBUG "Queue %s(%i) put %X\n", + qmgr_queue_descs[queue], queue, val); +#endif + __raw_writel(val, &qmgr_regs->acc[queue][0]); +} + +u32 qmgr_get_entry(unsigned int queue) +{ + u32 val; + val = __raw_readl(&qmgr_regs->acc[queue][0]); +#if DEBUG_QMGR + BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */ + + printk(KERN_DEBUG "Queue %s(%i) get %X\n", + qmgr_queue_descs[queue], queue, val); +#endif + return val; +} + +static int __qmgr_get_stat1(unsigned int queue) +{ + return (__raw_readl(&qmgr_regs->stat1[queue >> 3]) + >> ((queue & 7) << 2)) & 0xF; +} + +static int __qmgr_get_stat2(unsigned int queue) +{ + BUG_ON(queue >= HALF_QUEUES); + return (__raw_readl(&qmgr_regs->stat2[queue >> 4]) + >> ((queue & 0xF) << 1)) & 0x3; +} + +/** + * qmgr_stat_empty() - checks if a hardware queue is empty + * @queue: queue number + * + * Returns non-zero value if the queue is empty. + */ +int qmgr_stat_empty(unsigned int queue) +{ + BUG_ON(queue >= HALF_QUEUES); + return __qmgr_get_stat1(queue) & QUEUE_STAT1_EMPTY; +} + +/** + * qmgr_stat_below_low_watermark() - checks if a queue is below low watermark + * @queue: queue number + * + * Returns non-zero value if the queue is below low watermark. + */ +int qmgr_stat_below_low_watermark(unsigned int queue) +{ + if (queue >= HALF_QUEUES) + return (__raw_readl(&qmgr_regs->statne_h) >> + (queue - HALF_QUEUES)) & 0x01; + return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY; +} + +/** + * qmgr_stat_above_high_watermark() - checks if a queue is above high watermark + * @queue: queue number + * + * Returns non-zero value if the queue is above high watermark + */ +static int qmgr_stat_above_high_watermark(unsigned int queue) +{ + BUG_ON(queue >= HALF_QUEUES); + return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_FULL; +} + +/** + * qmgr_stat_full() - checks if a hardware queue is full + * @queue: queue number + * + * Returns non-zero value if the queue is full. + */ +int qmgr_stat_full(unsigned int queue) +{ + if (queue >= HALF_QUEUES) + return (__raw_readl(&qmgr_regs->statf_h) >> + (queue - HALF_QUEUES)) & 0x01; + return __qmgr_get_stat1(queue) & QUEUE_STAT1_FULL; +} + +/** + * qmgr_stat_underflow() - checks if a hardware queue experienced underflow + * @queue: queue number + * + * Returns non-zero value if the queue experienced underflow. + */ +static int qmgr_stat_underflow(unsigned int queue) +{ + return __qmgr_get_stat2(queue) & QUEUE_STAT2_UNDERFLOW; +} + +/** + * qmgr_stat_overflow() - checks if a hardware queue experienced overflow + * @queue: queue number + * + * Returns non-zero value if the queue experienced overflow. + */ +int qmgr_stat_overflow(unsigned int queue) +{ + return __qmgr_get_stat2(queue) & QUEUE_STAT2_OVERFLOW; +} + void qmgr_set_irq(unsigned int queue, int src, void (*handler)(void *pdev), void *pdev) { @@ -375,6 +486,12 @@ module_platform_driver(ixp4xx_qmgr_driver); MODULE_LICENSE("GPL v2"); MODULE_AUTHOR("Krzysztof Halasa"); +EXPORT_SYMBOL(qmgr_put_entry); +EXPORT_SYMBOL(qmgr_get_entry); +EXPORT_SYMBOL(qmgr_stat_empty); +EXPORT_SYMBOL(qmgr_stat_below_low_watermark); +EXPORT_SYMBOL(qmgr_stat_full); +EXPORT_SYMBOL(qmgr_stat_overflow); EXPORT_SYMBOL(qmgr_set_irq); EXPORT_SYMBOL(qmgr_enable_irq); EXPORT_SYMBOL(qmgr_disable_irq); diff --git a/include/linux/soc/ixp4xx/qmgr.h b/include/linux/soc/ixp4xx/qmgr.h index 4de8da536dbb..bed8ee94fa57 100644 --- a/include/linux/soc/ixp4xx/qmgr.h +++ b/include/linux/soc/ixp4xx/qmgr.h @@ -57,6 +57,13 @@ struct qmgr_regs { u32 sram[2048]; /* 0x2000 - 0x3FFF - config and buffer */ }; +void qmgr_put_entry(unsigned int queue, u32 val); +u32 qmgr_get_entry(unsigned int queue); +int qmgr_stat_empty(unsigned int queue); +int qmgr_stat_below_low_watermark(unsigned int queue); +int qmgr_stat_full(unsigned int queue); +int qmgr_stat_overflow(unsigned int queue); +void qmgr_release_queue(unsigned int queue); void qmgr_set_irq(unsigned int queue, int src, void (*handler)(void *pdev), void *pdev); void qmgr_enable_irq(unsigned int queue); @@ -81,124 +88,4 @@ int __qmgr_request_queue(unsigned int queue, unsigned int len /* dwords */, nearly_full_watermark) #endif -void qmgr_release_queue(unsigned int queue); - - -static inline void qmgr_put_entry(unsigned int queue, u32 val) -{ - struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; -#if DEBUG_QMGR - BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */ - - printk(KERN_DEBUG "Queue %s(%i) put %X\n", - qmgr_queue_descs[queue], queue, val); -#endif - __raw_writel(val, &qmgr_regs->acc[queue][0]); -} - -static inline u32 qmgr_get_entry(unsigned int queue) -{ - u32 val; - const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; - val = __raw_readl(&qmgr_regs->acc[queue][0]); -#if DEBUG_QMGR - BUG_ON(!qmgr_queue_descs[queue]); /* not yet requested */ - - printk(KERN_DEBUG "Queue %s(%i) get %X\n", - qmgr_queue_descs[queue], queue, val); -#endif - return val; -} - -static inline int __qmgr_get_stat1(unsigned int queue) -{ - const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; - return (__raw_readl(&qmgr_regs->stat1[queue >> 3]) - >> ((queue & 7) << 2)) & 0xF; -} - -static inline int __qmgr_get_stat2(unsigned int queue) -{ - const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; - BUG_ON(queue >= HALF_QUEUES); - return (__raw_readl(&qmgr_regs->stat2[queue >> 4]) - >> ((queue & 0xF) << 1)) & 0x3; -} - -/** - * qmgr_stat_empty() - checks if a hardware queue is empty - * @queue: queue number - * - * Returns non-zero value if the queue is empty. - */ -static inline int qmgr_stat_empty(unsigned int queue) -{ - BUG_ON(queue >= HALF_QUEUES); - return __qmgr_get_stat1(queue) & QUEUE_STAT1_EMPTY; -} - -/** - * qmgr_stat_below_low_watermark() - checks if a queue is below low watermark - * @queue: queue number - * - * Returns non-zero value if the queue is below low watermark. - */ -static inline int qmgr_stat_below_low_watermark(unsigned int queue) -{ - const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; - if (queue >= HALF_QUEUES) - return (__raw_readl(&qmgr_regs->statne_h) >> - (queue - HALF_QUEUES)) & 0x01; - return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_EMPTY; -} - -/** - * qmgr_stat_above_high_watermark() - checks if a queue is above high watermark - * @queue: queue number - * - * Returns non-zero value if the queue is above high watermark - */ -static inline int qmgr_stat_above_high_watermark(unsigned int queue) -{ - BUG_ON(queue >= HALF_QUEUES); - return __qmgr_get_stat1(queue) & QUEUE_STAT1_NEARLY_FULL; -} - -/** - * qmgr_stat_full() - checks if a hardware queue is full - * @queue: queue number - * - * Returns non-zero value if the queue is full. - */ -static inline int qmgr_stat_full(unsigned int queue) -{ - const struct qmgr_regs __iomem *qmgr_regs = IXP4XX_QMGR_BASE_VIRT; - if (queue >= HALF_QUEUES) - return (__raw_readl(&qmgr_regs->statf_h) >> - (queue - HALF_QUEUES)) & 0x01; - return __qmgr_get_stat1(queue) & QUEUE_STAT1_FULL; -} - -/** - * qmgr_stat_underflow() - checks if a hardware queue experienced underflow - * @queue: queue number - * - * Returns non-zero value if the queue experienced underflow. - */ -static inline int qmgr_stat_underflow(unsigned int queue) -{ - return __qmgr_get_stat2(queue) & QUEUE_STAT2_UNDERFLOW; -} - -/** - * qmgr_stat_overflow() - checks if a hardware queue experienced overflow - * @queue: queue number - * - * Returns non-zero value if the queue experienced overflow. - */ -static inline int qmgr_stat_overflow(unsigned int queue) -{ - return __qmgr_get_stat2(queue) & QUEUE_STAT2_OVERFLOW; -} - #endif -- cgit v1.2.3 From 1b8c813695dcff87b58ad1916bff2299dcf01c7f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 15 Apr 2019 22:17:09 +0200 Subject: ARM: ep93xx: move network platform data to separate header The header file is the only thing preventing us from building the driver in a cross-platform configuration, so move the structure we are interested in to the global platform_data location and enable compile testing. Acked-by: Alexander Sverdlin Acked-by: H Hartley Sweeten Signed-off-by: Arnd Bergmann Signed-off-by: Olof Johansson --- arch/arm/mach-ep93xx/include/mach/platform.h | 7 +------ drivers/net/ethernet/cirrus/Kconfig | 2 +- drivers/net/ethernet/cirrus/ep93xx_eth.c | 2 +- include/linux/platform_data/eth-ep93xx.h | 10 ++++++++++ 4 files changed, 13 insertions(+), 8 deletions(-) create mode 100644 include/linux/platform_data/eth-ep93xx.h (limited to 'include/linux') diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h index 6c41c794bed5..43446f33c2be 100644 --- a/arch/arm/mach-ep93xx/include/mach/platform.h +++ b/arch/arm/mach-ep93xx/include/mach/platform.h @@ -5,6 +5,7 @@ #ifndef __ASSEMBLY__ +#include #include struct device; @@ -15,12 +16,6 @@ struct ep93xxfb_mach_info; struct ep93xx_keypad_platform_data; struct ep93xx_spi_info; -struct ep93xx_eth_data -{ - unsigned char dev_addr[6]; - unsigned char phy_id; -}; - void ep93xx_map_io(void); void ep93xx_init_irq(void); diff --git a/drivers/net/ethernet/cirrus/Kconfig b/drivers/net/ethernet/cirrus/Kconfig index e9a0213b08c4..6238e6951336 100644 --- a/drivers/net/ethernet/cirrus/Kconfig +++ b/drivers/net/ethernet/cirrus/Kconfig @@ -41,7 +41,7 @@ config CS89x0_PLATFORM config EP93XX_ETH tristate "EP93xx Ethernet support" - depends on ARM && ARCH_EP93XX + depends on (ARM && ARCH_EP93XX) || COMPILE_TEST select MII help This is a driver for the ethernet hardware included in EP93xx CPUs. diff --git a/drivers/net/ethernet/cirrus/ep93xx_eth.c b/drivers/net/ethernet/cirrus/ep93xx_eth.c index 13dfdfca49fc..a6da9873570b 100644 --- a/drivers/net/ethernet/cirrus/ep93xx_eth.c +++ b/drivers/net/ethernet/cirrus/ep93xx_eth.c @@ -25,7 +25,7 @@ #include #include -#include +#include #define DRV_MODULE_NAME "ep93xx-eth" #define DRV_MODULE_VERSION "0.1" diff --git a/include/linux/platform_data/eth-ep93xx.h b/include/linux/platform_data/eth-ep93xx.h new file mode 100644 index 000000000000..8eef637a804d --- /dev/null +++ b/include/linux/platform_data/eth-ep93xx.h @@ -0,0 +1,10 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _LINUX_PLATFORM_DATA_ETH_EP93XX +#define _LINUX_PLATFORM_DATA_ETH_EP93XX + +struct ep93xx_eth_data { + unsigned char dev_addr[6]; + unsigned char phy_id; +}; + +#endif -- cgit v1.2.3 From dfb6db007a56998e53e5ba5fb798b2e830b7feca Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 15 Apr 2019 22:17:10 +0200 Subject: ARM: ep93xx: keypad: stop using mach/platform.h We can communicate the clock rate using platform data rather than setting a flag to use a particular value in the driver, which is cleaner and avoids the dependency. No platform in the kernel currently defines the ep93xx keypad device structure, so this is a rather pointless excercise. Any out of tree users are probably dead now, but if not, they have to change their platform code to match the new platform_data structure. Acked-by: H Hartley Sweeten Signed-off-by: Arnd Bergmann Signed-off-by: Olof Johansson --- drivers/input/keyboard/Kconfig | 2 +- drivers/input/keyboard/ep93xx_keypad.c | 5 +---- include/linux/platform_data/keypad-ep93xx.h | 4 ++-- 3 files changed, 4 insertions(+), 7 deletions(-) (limited to 'include/linux') diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig index a878351f1643..b373f3274542 100644 --- a/drivers/input/keyboard/Kconfig +++ b/drivers/input/keyboard/Kconfig @@ -194,7 +194,7 @@ config KEYBOARD_LKKBD config KEYBOARD_EP93XX tristate "EP93xx Matrix Keypad support" - depends on ARCH_EP93XX + depends on ARCH_EP93XX || COMPILE_TEST select INPUT_MATRIXKMAP help Say Y here to enable the matrix keypad on the Cirrus EP93XX. diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index f77b295e0123..71472f6257c0 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c @@ -137,10 +137,7 @@ static void ep93xx_keypad_config(struct ep93xx_keypad *keypad) struct ep93xx_keypad_platform_data *pdata = keypad->pdata; unsigned int val = 0; - if (pdata->flags & EP93XX_KEYPAD_KDIV) - clk_set_rate(keypad->clk, EP93XX_KEYTCHCLK_DIV4); - else - clk_set_rate(keypad->clk, EP93XX_KEYTCHCLK_DIV16); + clk_set_rate(keypad->clk, pdata->clk_rate); if (pdata->flags & EP93XX_KEYPAD_DISABLE_3_KEY) val |= KEY_INIT_DIS3KY; diff --git a/include/linux/platform_data/keypad-ep93xx.h b/include/linux/platform_data/keypad-ep93xx.h index 0e36818e3680..3054fced8509 100644 --- a/include/linux/platform_data/keypad-ep93xx.h +++ b/include/linux/platform_data/keypad-ep93xx.h @@ -9,8 +9,7 @@ struct matrix_keymap_data; #define EP93XX_KEYPAD_DIAG_MODE (1<<1) /* diagnostic mode */ #define EP93XX_KEYPAD_BACK_DRIVE (1<<2) /* back driving mode */ #define EP93XX_KEYPAD_TEST_MODE (1<<3) /* scan only column 0 */ -#define EP93XX_KEYPAD_KDIV (1<<4) /* 1/4 clock or 1/16 clock */ -#define EP93XX_KEYPAD_AUTOREPEAT (1<<5) /* enable key autorepeat */ +#define EP93XX_KEYPAD_AUTOREPEAT (1<<4) /* enable key autorepeat */ /** * struct ep93xx_keypad_platform_data - platform specific device structure @@ -24,6 +23,7 @@ struct ep93xx_keypad_platform_data { unsigned int debounce; unsigned int prescale; unsigned int flags; + unsigned int clk_rate; }; #define EP93XX_MATRIX_ROWS (8) -- cgit v1.2.3 From 67e38f578aaebf34fc1278bbe45a78ee8c73dd33 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 15 Apr 2019 22:17:11 +0200 Subject: ARM: ep93xx: move pinctrl interfaces into include/linux/soc ep93xx does not have a proper pinctrl driver, but does things ad-hoc through mach/platform.h, which is also used for setting up the boards. To avoid using mach/*.h headers completely, let's move the interfaces into include/linux/soc/. This is far from great, but gets the job done here, without the need for a proper pinctrl driver. Acked-by: Alexander Sverdlin Acked-by: H Hartley Sweeten Signed-off-by: Arnd Bergmann Signed-off-by: Olof Johansson --- arch/arm/mach-ep93xx/clock.c | 1 + arch/arm/mach-ep93xx/core.c | 2 ++ arch/arm/mach-ep93xx/include/mach/platform.h | 16 ------------ drivers/ata/pata_ep93xx.c | 2 +- drivers/input/keyboard/ep93xx_keypad.c | 3 +-- drivers/pwm/pwm-ep93xx.c | 2 +- include/linux/soc/cirrus/ep93xx.h | 37 ++++++++++++++++++++++++++++ sound/soc/cirrus/edb93xx.c | 2 +- sound/soc/cirrus/ep93xx-ac97.c | 1 + sound/soc/cirrus/ep93xx-i2s.c | 3 +-- sound/soc/cirrus/simone.c | 2 +- sound/soc/cirrus/snappercl15.c | 2 +- 12 files changed, 48 insertions(+), 25 deletions(-) create mode 100644 include/linux/soc/cirrus/ep93xx.h (limited to 'include/linux') diff --git a/arch/arm/mach-ep93xx/clock.c b/arch/arm/mach-ep93xx/clock.c index d2eee707d27f..9f43362eb62d 100644 --- a/arch/arm/mach-ep93xx/clock.c +++ b/arch/arm/mach-ep93xx/clock.c @@ -20,6 +20,7 @@ #include #include #include +#include #include diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c index 706515faee06..3d245668846d 100644 --- a/arch/arm/mach-ep93xx/core.c +++ b/arch/arm/mach-ep93xx/core.c @@ -43,6 +43,8 @@ #include #include #include +#include + #include #include diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h index 43446f33c2be..b4045a186239 100644 --- a/arch/arm/mach-ep93xx/include/mach/platform.h +++ b/arch/arm/mach-ep93xx/include/mach/platform.h @@ -19,14 +19,6 @@ struct ep93xx_spi_info; void ep93xx_map_io(void); void ep93xx_init_irq(void); -#define EP93XX_CHIP_REV_D0 3 -#define EP93XX_CHIP_REV_D1 4 -#define EP93XX_CHIP_REV_E0 5 -#define EP93XX_CHIP_REV_E1 6 -#define EP93XX_CHIP_REV_E2 7 - -unsigned int ep93xx_chip_revision(void); - void ep93xx_register_flash(unsigned int width, resource_size_t start, resource_size_t size); @@ -36,19 +28,11 @@ void ep93xx_register_spi(struct ep93xx_spi_info *info, struct spi_board_info *devices, int num); void ep93xx_register_fb(struct ep93xxfb_mach_info *data); void ep93xx_register_pwm(int pwm0, int pwm1); -int ep93xx_pwm_acquire_gpio(struct platform_device *pdev); -void ep93xx_pwm_release_gpio(struct platform_device *pdev); void ep93xx_register_keypad(struct ep93xx_keypad_platform_data *data); -int ep93xx_keypad_acquire_gpio(struct platform_device *pdev); -void ep93xx_keypad_release_gpio(struct platform_device *pdev); void ep93xx_register_i2s(void); -int ep93xx_i2s_acquire(void); -void ep93xx_i2s_release(void); void ep93xx_register_ac97(void); void ep93xx_register_ide(void); void ep93xx_register_adc(void); -int ep93xx_ide_acquire_gpio(struct platform_device *pdev); -void ep93xx_ide_release_gpio(struct platform_device *pdev); struct device *ep93xx_init_devices(void); extern void ep93xx_timer_init(void); diff --git a/drivers/ata/pata_ep93xx.c b/drivers/ata/pata_ep93xx.c index cc6d06c1b2c7..db271b705529 100644 --- a/drivers/ata/pata_ep93xx.c +++ b/drivers/ata/pata_ep93xx.c @@ -44,7 +44,7 @@ #include #include -#include +#include #define DRV_NAME "ep93xx-ide" #define DRV_VERSION "1.0" diff --git a/drivers/input/keyboard/ep93xx_keypad.c b/drivers/input/keyboard/ep93xx_keypad.c index 71472f6257c0..575dac52f7b4 100644 --- a/drivers/input/keyboard/ep93xx_keypad.c +++ b/drivers/input/keyboard/ep93xx_keypad.c @@ -27,8 +27,7 @@ #include #include #include - -#include +#include #include /* diff --git a/drivers/pwm/pwm-ep93xx.c b/drivers/pwm/pwm-ep93xx.c index bbf10ae02f0e..fa168581e6b8 100644 --- a/drivers/pwm/pwm-ep93xx.c +++ b/drivers/pwm/pwm-ep93xx.c @@ -35,7 +35,7 @@ #include -#include /* for ep93xx_pwm_{acquire,release}_gpio() */ +#include /* for ep93xx_pwm_{acquire,release}_gpio() */ #define EP93XX_PWMx_TERM_COUNT 0x00 #define EP93XX_PWMx_DUTY_CYCLE 0x04 diff --git a/include/linux/soc/cirrus/ep93xx.h b/include/linux/soc/cirrus/ep93xx.h new file mode 100644 index 000000000000..56fbe2dc59b1 --- /dev/null +++ b/include/linux/soc/cirrus/ep93xx.h @@ -0,0 +1,37 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _SOC_EP93XX_H +#define _SOC_EP93XX_H + +struct platform_device; + +#define EP93XX_CHIP_REV_D0 3 +#define EP93XX_CHIP_REV_D1 4 +#define EP93XX_CHIP_REV_E0 5 +#define EP93XX_CHIP_REV_E1 6 +#define EP93XX_CHIP_REV_E2 7 + +#ifdef CONFIG_ARCH_EP93XX +int ep93xx_pwm_acquire_gpio(struct platform_device *pdev); +void ep93xx_pwm_release_gpio(struct platform_device *pdev); +int ep93xx_ide_acquire_gpio(struct platform_device *pdev); +void ep93xx_ide_release_gpio(struct platform_device *pdev); +int ep93xx_keypad_acquire_gpio(struct platform_device *pdev); +void ep93xx_keypad_release_gpio(struct platform_device *pdev); +int ep93xx_i2s_acquire(void); +void ep93xx_i2s_release(void); +unsigned int ep93xx_chip_revision(void); + +#else +static inline int ep93xx_pwm_acquire_gpio(struct platform_device *pdev) { return 0; } +static inline void ep93xx_pwm_release_gpio(struct platform_device *pdev) {} +static inline int ep93xx_ide_acquire_gpio(struct platform_device *pdev) { return 0; } +static inline void ep93xx_ide_release_gpio(struct platform_device *pdev) {} +static inline int ep93xx_keypad_acquire_gpio(struct platform_device *pdev) { return 0; } +static inline void ep93xx_keypad_release_gpio(struct platform_device *pdev) {} +static inline int ep93xx_i2s_acquire(void) { return 0; } +static inline void ep93xx_i2s_release(void) {} +static inline unsigned int ep93xx_chip_revision(void) { return 0; } + +#endif + +#endif diff --git a/sound/soc/cirrus/edb93xx.c b/sound/soc/cirrus/edb93xx.c index 3d011abaa266..f678b4c1514a 100644 --- a/sound/soc/cirrus/edb93xx.c +++ b/sound/soc/cirrus/edb93xx.c @@ -22,11 +22,11 @@ #include #include #include +#include #include #include #include #include -#include static int edb93xx_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index cd5a939ad608..c6bc447429af 100644 --- a/sound/soc/cirrus/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c @@ -24,6 +24,7 @@ #include #include +#include #include "ep93xx-pcm.h" diff --git a/sound/soc/cirrus/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 0918c5da575a..beab7c516855 100644 --- a/sound/soc/cirrus/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c @@ -27,9 +27,8 @@ #include #include -#include -#include #include +#include #include "ep93xx-pcm.h" diff --git a/sound/soc/cirrus/simone.c b/sound/soc/cirrus/simone.c index 1ec661834e5a..cb850530331b 100644 --- a/sound/soc/cirrus/simone.c +++ b/sound/soc/cirrus/simone.c @@ -13,13 +13,13 @@ #include #include #include +#include #include #include #include #include -#include static struct snd_soc_dai_link simone_dai = { .name = "AC97", diff --git a/sound/soc/cirrus/snappercl15.c b/sound/soc/cirrus/snappercl15.c index 11ff7b2672b2..dea4909154c8 100644 --- a/sound/soc/cirrus/snappercl15.c +++ b/sound/soc/cirrus/snappercl15.c @@ -13,12 +13,12 @@ #include #include +#include #include #include #include #include -#include #include "../codecs/tlv320aic23.h" -- cgit v1.2.3