From patchwork Thu Sep 12 18:24:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802423 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 2F38DEEE245 for ; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id 03D7EC4CED1; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id CB15AC4CEC6; Thu, 12 Sep 2024 18:20:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165214; bh=ptTHhO/RSXSVsdindc7EjYTMDmcxjcELqNQXSlU/WQA=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=ZuS+NloUOWC1hdVfV3Hozm0tjAA1nB956c2hevr9vIm0C0ISQE9/cr2cbguNOR97M M72BetG0IohcgdLKfKu4LJnx2+01ROhoc6NYkWiGjAfwTHIv1OuxMs7OEV3HFv8uAm 2+H9uYtpH4SAxsmFNzRzUtjmF7phFiziAarx7PfHxSE4xOKFDoovXyzLO4+TnC21Ci tYrwOK2fukTG+gSpYIlXJE63yZCH8VE3XoNLxpGE0Wrqm56aY4n/0taXRagxdgO98+ XJcEp2oA8sgE8tGhVwMzwNEMvS3ZAxD1iGtSS1vo5sjp9N1h+H5Fwbb7LyLM/Y4OHi jQH4eaJoVkeQA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id B41F5EED63A; Thu, 12 Sep 2024 18:20:14 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:24:46 +0100 Subject: [PATCH 01/21] arm64: Add ADI ADSP-SC598 SoC MIME-Version: 1.0 Message-Id: <20240912-test-v1-1-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=26356; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=LYT5+VmMP/U1fC/g6+IzHvlKcGV3qIp7V9gWae5WAHA=; b=y0h1jzbMaKVmcovyu8O2NA2tLm9dnK2uobllgPapan8BjluS6i+jIWqUlo3UyhZwSaqoG6fdn jFKM8/BAoaCBalrpRKV9iaxzKqgX7NBMtyknkyJXwBijs693Fhn2kbL X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Add ADSP-SC598 platform. Signed-off-by: Arturs Artamonovs Co-developed-by: Utsav Agarwal Signed-off-by: Utsav Agarwal Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- arch/arm64/Kconfig.platforms | 13 ++ drivers/soc/Makefile | 1 + drivers/soc/adi/Makefile | 5 + drivers/soc/adi/system.c | 257 +++++++++++++++++++++++++++++++++ include/linux/soc/adi/adsp-gpio-port.h | 85 +++++++++++ include/linux/soc/adi/cpu.h | 107 ++++++++++++++ include/linux/soc/adi/rcu.h | 55 +++++++ include/linux/soc/adi/sc59x.h | 147 +++++++++++++++++++ include/linux/soc/adi/system_config.h | 65 +++++++++ 9 files changed, 735 insertions(+) diff --git a/arch/arm64/Kconfig.platforms b/arch/arm64/Kconfig.platforms index 6c6d11536b42ec6e878db8d355c17994c2500d7b..b9ea22ecddfcbff98486a314143e52934f26df44 100644 --- a/arch/arm64/Kconfig.platforms +++ b/arch/arm64/Kconfig.platforms @@ -292,6 +292,19 @@ config ARCH_ROCKCHIP This enables support for the ARMv8 based Rockchip chipsets, like the RK3368. +config ARCH_SC59X_64 + bool "ADI 64-bit SC59X Platforms" + select TIMER_OF + select GPIOLIB + select PINCTRL + select COMMON_CLK_ADI_SC598 + select PINCTRL_ADSP + select ADI_ADSP_IRQ + select COUNTER + help + This enables support for Analog Devices Incorporated's + Family of ARM64 DSP processors + config ARCH_SEATTLE bool "AMD Seattle SoC Family" help diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index fb2bd31387d070387fcf8a579f618dc2b25bdc69..af518539185563a96e37a2d42ad5535e7366c5fa 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -3,6 +3,7 @@ # Makefile for the Linux Kernel SOC specific device drivers. # +obj-$(CONFIG_ARCH_SC59X_64) += adi/ obj-y += apple/ obj-y += aspeed/ obj-$(CONFIG_ARCH_AT91) += atmel/ diff --git a/drivers/soc/adi/Makefile b/drivers/soc/adi/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..113720192d462e833da69214ce91a7b84aec141b --- /dev/null +++ b/drivers/soc/adi/Makefile @@ -0,0 +1,5 @@ +# SPDX-License-Identifier: GPL-2.0 + +# todo modularize; already depends on CONFIG_ARCH_SC59X_64 though + +obj-y += system.o diff --git a/drivers/soc/adi/system.c b/drivers/soc/adi/system.c new file mode 100644 index 0000000000000000000000000000000000000000..42cd157bc68af8819e2a2d2fc5be009b4753bd29 --- /dev/null +++ b/drivers/soc/adi/system.c @@ -0,0 +1,257 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright 2022-2024 - Analog Devices Inc. + */ + +#include +#include + +#define ADI_SYSREG_BITS(_id, _offset, _width, _shift) \ + { \ + .id = ADI_SYSTEM_REG_##_id, \ + .offset = _offset, \ + .mask = GENMASK(_width-1, 0) << _shift, \ + .shift = _shift, \ + .is_bits = true, \ + } + +#define ADI_SYSREG(_id, _offset) \ + { \ + .id = ADI_SYSTEM_REG_##_id, \ + .offset = _offset, \ + .is_bits = false, \ + } + +#define devm_regmap_init_adi_system_config(dev, config) \ + __regmap_lockdep_wrapper(__devm_regmap_init_adi_system_config, \ + #config, dev, config) + +struct adi_system_context { + /* underlying regmap_mmio */ + struct regmap *regmap; + /* tree of register definitions by index */ + struct radix_tree_root tree; + /* configuration we were created with */ + struct adi_system_config *config; +}; + +/* + * Fields in PADS CFG0 at offset +0x04 + */ +static struct adi_system_register adi_pads_regs[] = { + ADI_SYSREG_BITS(EMAC0_PTPCLK0, 0x04, 2, 0), + ADI_SYSREG_BITS(EMAC0_EMACRESET, 0x04, 1, 2), + ADI_SYSREG_BITS(EMAC0_PHYISEL, 0x04, 2, 3), + ADI_SYSREG_BITS(CNT0UDSEL, 0x04, 2, 6), + ADI_SYSREG_BITS(CNT0DGSEL, 0x04, 2, 7), + ADI_SYSREG_BITS(PUTMS, 0x04, 2, 16), + ADI_SYSREG_BITS(EMAC0_AUXIE, 0x04, 1, 17), + ADI_SYSREG_BITS(FAULT_DIS, 0x04, 1, 18), + ADI_SYSREG_BITS(EMAC0_ENDIANNESS, 0x04, 1, 19), + ADI_SYSREG_BITS(EMAC1_ENDIANNESS, 0x04, 1, 20), + ADI_SYSREG_BITS(MSHC_CCLK_DIV_EN, 0x04, 1, 22), + ADI_SYSREG(DAI0_IE, 0x90), + ADI_SYSREG(DAI1_IE, 0x94), +}; + +static struct adi_system_config adi_pads_config = { + .registers = adi_pads_regs, + .len = ARRAY_SIZE(adi_pads_regs), + .max_register = __ADI_SYSTEM_REG_COUNT, +}; + +static int regmap_system_read(void *context, unsigned int reg, + unsigned int *val) +{ + struct adi_system_context *ctx = context; + struct adi_system_register *sreg = + radix_tree_lookup(&ctx->tree, reg); + int ret; + + if (!sreg) + return -EIO; + + if (sreg->is_bits) { + uint32_t tmp; + + ret = regmap_read(ctx->regmap, sreg->offset, &tmp); + if (ret) + return ret; + + tmp = (tmp & sreg->mask) >> sreg->shift; + *val = tmp; + return 0; + } + + return regmap_read(ctx->regmap, sreg->offset, val); +} + +static int regmap_system_write(void *context, unsigned int reg, + unsigned int val) +{ + struct adi_system_context *ctx = context; + struct adi_system_register *sreg = radix_tree_lookup(&ctx->tree, reg); + + if (!sreg) + return -EIO; + + if (sreg->is_bits) { + return regmap_update_bits(ctx->regmap, sreg->offset, + sreg->mask, + (val << sreg->shift) & sreg->mask); + } + + return regmap_write(ctx->regmap, sreg->offset, val); +} + +static struct adi_system_context *create_context +(struct adi_system_config *config) +{ + struct regmap *regmap = config->mmio_regmap; + struct adi_system_context *ctx; + size_t i; + int ret; + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (!ctx) + return ERR_PTR(-ENOMEM); + + ctx->regmap = regmap; + INIT_RADIX_TREE(&ctx->tree, GFP_KERNEL); + + for (i = 0; i < config->len; ++i) { + struct adi_system_register *sreg = &config->registers[i]; + + ret = radix_tree_insert(&ctx->tree, sreg->id, sreg); + if (ret) + return ERR_PTR(ret); + } + + config->config.max_register = config->max_register; + config->config.reg_bits = 8 * sizeof(uint32_t); + config->config.val_bits = 8 * sizeof(uint32_t); + config->config.reg_stride = 1; + + return ctx; +} + +static void regmap_system_free_context(void *context) +{ + struct adi_system_context *ctx = context; + unsigned int i; + + for (i = 0; i < ctx->config->len; ++i) + radix_tree_delete(&ctx->tree, + ctx->config->registers[i].id); + + kfree(ctx); +} + +static const struct regmap_bus regmap_system_bus = { + .fast_io = true, + .reg_write = regmap_system_write, + .reg_read = regmap_system_read, + .free_context = regmap_system_free_context, + .val_format_endian_default = REGMAP_ENDIAN_LITTLE, +}; + +static struct regmap *__devm_regmap_init_adi_system_config(struct device *dev, + struct adi_system_config *config, + struct lock_class_key *lock_key, const char *lock_name) +{ + struct adi_system_context *ctx = create_context(config); + + if (IS_ERR(ctx)) + return ERR_PTR(PTR_ERR(ctx)); + + return __devm_regmap_init(dev, ®map_system_bus, ctx, + &config->config, + lock_key, lock_name); +} + +static DEFINE_SPINLOCK(adi_system_config_lock); +static LIST_HEAD(adi_system_config_list); + +static int adi_system_config_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct adi_system_config *config = &adi_pads_config; + struct device_node *np = dev->of_node; + struct regmap *regmap_mmio; + struct regmap *regmap_system; + struct resource *res; + void __iomem *base; + unsigned long flags; + + struct regmap_config mmio_config = { + .reg_bits = 8 * sizeof(uint32_t), + .val_bits = 8 * sizeof(uint32_t), + .reg_stride = sizeof(uint32_t), + }; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + + base = devm_ioremap(dev, res->start, resource_size(res)); + if (IS_ERR(base)) + return PTR_ERR(base); + + mmio_config.name = dev_name(dev); + mmio_config.max_register = resource_size(res) - sizeof(uint32_t); + + regmap_mmio = devm_regmap_init_mmio(dev, base, &mmio_config); + if (IS_ERR(regmap_mmio)) { + dev_err(dev, "mmio regmap initialization failed\n"); + return PTR_ERR(regmap_mmio); + } + + config->mmio_regmap = regmap_mmio; + regmap_system = devm_regmap_init_adi_system_config(dev, config); + if (IS_ERR(regmap_system)) { + dev_err(dev, "system config regmap initialization failed\n"); + return PTR_ERR(regmap_system); + } + + config->np = np; + config->system_regmap = regmap_system; + platform_set_drvdata(pdev, config); + + spin_lock_irqsave(&adi_system_config_lock, flags); + list_add_tail(&config->list, &adi_system_config_list); + spin_unlock_irqrestore(&adi_system_config_lock, flags); + return 0; +} + +static void adi_system_config_remove(struct platform_device *pdev) +{ + struct adi_system_config *config = platform_get_drvdata(pdev); + unsigned long flags; + + spin_lock_irqsave(&adi_system_config_lock, flags); + list_del(&config->list); + spin_unlock_irqrestore(&adi_system_config_lock, flags); +} + +/* + * PADs configuration registers are required to configure peripherals, + * and by extension the system. Hence the driver focuses on driving them while + * also setting up the remaining system. + */ +static const struct of_device_id pads_dt_ids[] = { + { .compatible = "adi,pads-peripheral-config", }, + { } +}; +MODULE_DEVICE_TABLE(of, pads_dt_ids); + +static struct platform_driver pads_driver = { + .driver = { + .name = "adi-system-config", + .of_match_table = pads_dt_ids, + }, + .probe = adi_system_config_probe, + .remove = adi_system_config_remove, +}; +module_platform_driver(pads_driver); + +MODULE_AUTHOR("Greg Malysa "); +MODULE_DESCRIPTION("ADI ADSP PADS CFG-based System Configuration Driver"); +MODULE_LICENSE("GPL v2"); \ No newline at end of file diff --git a/include/linux/soc/adi/adsp-gpio-port.h b/include/linux/soc/adi/adsp-gpio-port.h new file mode 100644 index 0000000000000000000000000000000000000000..6466ded03ec6092149a2abfc56a305f9124ac695 --- /dev/null +++ b/include/linux/soc/adi/adsp-gpio-port.h @@ -0,0 +1,85 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2022-2024 - Analog Devices Inc. + */ + +#ifndef GPIO_ADI_ADSP_PORT_H +#define GPIO_ADI_ADSP_PORT_H + +#include + +/* Number of GPIOs per port instance */ +#define ADSP_PORT_NGPIO 16 + +/* PORT memory layout */ +#define ADSP_PORT_REG_FER 0x00 +#define ADSP_PORT_REG_FER_SET 0x04 +#define ADSP_PORT_REG_FER_CLEAR 0x08 +#define ADSP_PORT_REG_DATA 0x0c +#define ADSP_PORT_REG_DATA_SET 0x10 +#define ADSP_PORT_REG_DATA_CLEAR 0x14 +#define ADSP_PORT_REG_DIR 0x18 +#define ADSP_PORT_REG_DIR_SET 0x1c +#define ADSP_PORT_REG_DIR_CLEAR 0x20 +#define ADSP_PORT_REG_INEN 0x24 +#define ADSP_PORT_REG_INEN_SET 0x28 +#define ADSP_PORT_REG_INEN_CLEAR 0x2c +#define ADSP_PORT_REG_PORT_MUX 0x30 +#define ADSP_PORT_REG_DATA_TGL 0x34 +#define ADSP_PORT_REG_POLAR 0x38 +#define ADSP_PORT_REG_POLAR_SET 0x3c +#define ADSP_PORT_REG_POLAR_CLEAR 0x40 +#define ADSP_PORT_REG_LOCK 0x44 +#define ADSP_PORT_REG_TRIG_TGL 0x48 + +/* + * One gpio instance per PORT instance in the hardware, provides the per-PORT + * interface to the hardware. Referenced in GPIO and PINCTRL drivers + */ +struct adsp_gpio_port { + struct device *dev; + void __iomem *regs; + struct gpio_chip gpio; + struct irq_domain *irq_domain; + uint32_t irq_offset; + uint32_t open_drain; + spinlock_t lock; +}; + +/* may need lock depending on register */ +static inline uint32_t __adsp_gpio_readl(struct adsp_gpio_port *port, + size_t offset) +{ + return readl(port->regs + offset); +} + +/* may need lock depending on register */ +static inline void __adsp_gpio_writel(struct adsp_gpio_port *port, uint32_t val, + size_t offset) +{ + writel(val, port->regs + offset); +} + +/* may need lock depending on register */ +static inline u16 __adsp_gpio_readw(struct adsp_gpio_port *port, + size_t offset) +{ + return readw(port->regs + offset); +} + +/* may need lock depending on register */ +static inline void __adsp_gpio_writew(struct adsp_gpio_port *port, u16 val, + size_t offset) +{ + writew(val, port->regs + offset); +} + +static inline struct adsp_gpio_port *to_adsp_gpio_port(struct gpio_chip + *chip) +{ + return container_of(chip, struct adsp_gpio_port, gpio); +} + +int adsp_attach_pint_to_gpio(struct adsp_gpio_port *port); + +#endif diff --git a/include/linux/soc/adi/cpu.h b/include/linux/soc/adi/cpu.h new file mode 100644 index 0000000000000000000000000000000000000000..0ddb30619b423ce70e9b8018ed6404cfd4ef6039 --- /dev/null +++ b/include/linux/soc/adi/cpu.h @@ -0,0 +1,107 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2022-2024 - Analog Devices Inc. + */ + +#ifndef __MACH_CPU_H +#define __MACH_CPU_H + +#define SYS_L2_START 0x20080000 +#define SYS_SRAM_BASE (0x20080000 + SZ_16K) + +#define SYS_SRAM_SIZE (SZ_16K + SZ_32K * 3) +#define SYS_SRAM_ICC_SIZE SZ_4K +#define SYS_MMR_BASE 0x31000000 +#define SYS_MMR_SIZE SZ_1M +#define SYS_SMC_BANK1 0x44000000 + +#define SC59X_GIC_PORT0 0x310B2000 +#define SC59X_GIC_PORT1 0x310B4000 + +/* + * Timer Configuration Register Bits + */ +#define TIMER_EMU_RUN 0x8000 +#define TIMER_BPER_EN 0x4000 +#define TIMER_BWID_EN 0x2000 +#define TIMER_BDLY_EN 0x1000 +#define TIMER_OUT_DIS 0x0800 +#define TIMER_TIN_SEL 0x0400 +#define TIMER_CLK_SEL 0x0300 +#define TIMER_CLK_SCLK 0x0000 +#define TIMER_CLK_ALT_CLK0 0x0100 +#define TIMER_CLK_ALT_CLK1 0x0300 +#define TIMER_PULSE_HI 0x0080 +#define TIMER_SLAVE_TRIG 0x0040 +#define TIMER_IRQ_MODE 0x0030 +#define TIMER_IRQ_ACT_EDGE 0x0000 +#define TIMER_IRQ_DLY 0x0010 +#define TIMER_IRQ_WID_DLY 0x0020 +#define TIMER_IRQ_PER 0x0030 +#define TIMER_MODE 0x000f +#define TIMER_MODE_WDOG_P 0x0008 +#define TIMER_MODE_WDOG_W 0x0009 +#define TIMER_MODE_PWM_CONT 0x000c +#define TIMER_MODE_PWM 0x000d +#define TIMER_MODE_WDTH 0x000a +#define TIMER_MODE_WDTH_D 0x000b +#define TIMER_MODE_EXT_CLK 0x000e +#define TIMER_MODE_PININT 0x000f + +#define __BFP(m) u16 m; u16 __pad_##m + +struct gptimer3 { + __BFP(config); + uint32_t counter; + uint32_t period; + uint32_t width; + uint32_t delay; +}; + +struct sc5xx_gptimer { + int id; + int irq; + int reserved; + int int_enable; + void __iomem *io_base; + void __iomem *cgu0_ctl; + unsigned long isr_count; + struct platform_device *pdev; + struct list_head node; +}; + +struct gptimer3_group_regs { + __BFP(run); + __BFP(enable); + __BFP(disable); + __BFP(stop_cfg); + __BFP(stop_cfg_set); + __BFP(stop_cfg_clr); + __BFP(data_imsk); + __BFP(stat_imsk); + __BFP(tr_msk); + __BFP(tr_ie); + __BFP(data_ilat); + __BFP(stat_ilat); + __BFP(err_status); + __BFP(bcast_per); + __BFP(bcast_wid); + __BFP(bcast_dly); +}; + +/* The actual gptimer API */ +struct sc5xx_gptimer *gptimer_request(int id); +int gptimer_free(struct sc5xx_gptimer *timer); +void set_gptimer_pwidth(struct sc5xx_gptimer *timer, uint32_t width); +void set_gptimer_period(struct sc5xx_gptimer *timer, uint32_t period); +uint32_t get_gptimer_count(struct sc5xx_gptimer *timer); +void set_gptimer_config(struct sc5xx_gptimer *timer, uint16_t config); +void enable_gptimers(uint16_t mask); +void disable_gptimers(uint16_t mask); +void map_gptimers(void); +uint16_t get_gptimer_status(void); +void set_gptimer_status(uint16_t value); +void set_spu_securep_msec(uint16_t n, bool msec); +void platform_ipi_init(void); + +#endif /* __MACH_CPU_H */ diff --git a/include/linux/soc/adi/rcu.h b/include/linux/soc/adi/rcu.h new file mode 100644 index 0000000000000000000000000000000000000000..929989ff8f142609d5aecaffe0e8aa659875c47e --- /dev/null +++ b/include/linux/soc/adi/rcu.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2022-2024 - Analog Devices Inc. + */ + +#ifndef SOC_ADI_RCU_H +#define SOC_ADI_RCU_H + +/* Register offsets */ +#define ADI_RCU_REG_CTL 0x00 +#define ADI_RCU_REG_STAT 0x04 +#define ADI_RCU_REG_CRCTL 0x08 +#define ADI_RCU_REG_CRSTAT 0x0c + +#ifdef CONFIG_ARCH_SC58X +#define ADI_RCU_REG_SIDIS 0x10 +#define ADI_RCU_REG_SISTAT 0x14 +#define ADI_RCU_REG_SVECT_LCK 0x18 +#define ADI_RCU_REG_BCODE 0x1c +#define ADI_RCU_REG_SVECT0 0x20 +#define ADI_RCU_REG_SVECT1 0x24 +#define ADI_RCU_REG_SVECT2 0x28 +#define ADI_RCU_REG_MSG 0x60 +#define ADI_RCU_REG_MSG_SET 0x64 +#define ADI_RCU_REG_MSG_CLR 0x68 +#else +#define ADI_RCU_REG_SRRQSTAT 0x18 +#define ADI_RCU_REG_SIDIS 0x1c +#define ADI_RCU_REG_SISTAT 0x20 +#define ADI_RCU_REG_BCODE 0x28 +#define ADI_RCU_REG_SVECT0 0x2c +#define ADI_RCU_REG_SVECT1 0x30 +#define ADI_RCU_REG_SVECT2 0x34 +#define ADI_RCU_REG_MSG 0x6c +#define ADI_RCU_REG_MSG_SET 0x70 +#define ADI_RCU_REG_MSG_CLR 0x74 +#endif + + +/* Register bit definitions */ +#define ADI_RCU_CTL_SYSRST BIT(0) + +/* Bit values for the RCU0_MSG register */ +#define RCU0_MSG_C0IDLE 0x00000100 /* Core 0 Idle */ +#define RCU0_MSG_C1IDLE 0x00000200 /* Core 1 Idle */ +#define RCU0_MSG_C2IDLE 0x00000400 /* Core 2 Idle */ +#define RCU0_MSG_CRR0 0x00001000 /* Core 0 reset request */ +#define RCU0_MSG_CRR1 0x00002000 /* Core 1 reset request */ +#define RCU0_MSG_CRR2 0x00004000 /* Core 2 reset request */ +#define RCU0_MSG_C1ACTIVATE 0x00080000 /* Core 1 Activated */ +#define RCU0_MSG_C2ACTIVATE 0x00100000 /* Core 2 Activated */ + +struct adi_rcu; +struct adi_sec; +#endif diff --git a/include/linux/soc/adi/sc59x.h b/include/linux/soc/adi/sc59x.h new file mode 100644 index 0000000000000000000000000000000000000000..95655886478cda8cd6798a243781e39dc31baacf --- /dev/null +++ b/include/linux/soc/adi/sc59x.h @@ -0,0 +1,147 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2022-2024 - Analog Devices Inc. + */ + +#ifndef SOC_ADI_SC59X_H +#define SOC_ADI_SC59X_H + +#define SC59x_SYSTEM_L2_VIRT_BASE 0xFF020000 +#define SC59x_SYSTEM_L2_SIZE 0x2C0000 + +// General Purpose Timer Block Registers +#define TIMER_GROUP 0x31018004 + +// TIMER0 +#define TIMER0_CONFIG 0x31018060 + +// CGU0 +#define REG_CGU0_CTL 0x3108D000 // CGU0 Control Register +#define REG_CGU0_STAT 0x3108D008 // CGU0 Status Register +#define REG_CGU0_DIV 0x3108D00C // CGU0 Clocks Divisor Register + +// UART0 +#define UART0_REVID 0x31003000 // UART0 Revision ID Register + +// UART1 +#define UART1_REVID 0x31003400 // UART1 Revision ID Register + +// UART2 +#define UART2_REVID 0x31003800 // UART2 Revision ID Register + +// WDOG0 +#define REG_WDOG0_CTL 0x31008000 // WDOG0 Control Register + +// WDOG1 +#define REG_WDOG1_CTL 0x31008800 // WDOG1 Control Register + +// CRC0 MMR +#define REG_CRC0_CTL 0x310A5000 // CRC0 Control Register +#define REG_CRC0_DCNT 0x310A5004 // CRC0 Data Word Count Register +#define REG_CRC0_FILLVAL 0x310A5018 // CRC0 Fill Value Register + +// DMA Channel Registers +#define REG_DMA18_DSCPTR_NXT 0x310A7000 // DMA8 Pointer to Next Initial Descriptor +#define REG_DMA8_CFG 0x310A7008 // DMA8 Configuration Register +#define REG_DMA9_DSCPTR_NXT 0x310A7080 // DMA9 Pointer to Next Initial Descriptor +#define REG_DMA9_CFG 0x310A7088 // DMA9 Configuration Register +#define REG_DMA9_STAT 0x310A70B0 // DMA9 Status Register +#define REG_DMA18_DSCPTR_NXT 0x310A7100 // DMA18 Pointer to Next Initial Descriptor +#define REG_DMA18_CFG 0x310A7108 // DMA18 Configuration Register +#define REG_DMA19_DSCPTR_NXT 0x310A7180 // DMA19 Pointer to Next Initial Descriptor +#define REG_DMA19_CFG 0x310A7188 // DMA19 Configuration Register +#define REG_DMA19_STAT 0x310A71B0 // DMA19 Status Register + +// L2CTL0 +#define L2CTL0_CTL 0x31080000 // L2CTL0 Control Register +#define L2CTL0_STAT 0x31080010 // L2CTL0 Status Register +#define L2CTL0_ERRADDR0 0x31080040 // L2CTL0 ECC Error Address 0 Register +#define L2CTL0_ET0 0x31080080 // L2CTL0 Error Type 0 Register +#define L2CTL0_EADDR0 0x31080084 // L2CTL0 Error Type 0 Address Register +#define L2CTL0_ET1 0x31080088 // L2CTL0 Error Type 1 Register +#define L2CTL0_EADDR1 0x3108008C // L2CTL0 Error Type 1 Address Register + +// SEC Core Interface (SCI) Register Definitions +#define SEC_COMMON_BASE 0x31089000 +#define SEC_SCI_BASE 0x31089440 +#define SEC_SSI_BASE 0x31089800 + +#define SEC_SCI_OFF 0x00000040 +#define SEC_CCTL 0x00000000 // SEC Core Control Register n +#define SEC_CSID 0x0000001C // SEC Core IRQ Source ID Register n + +#define SEC_CCTL_EN 0x00000001 // SEC Core Control Register Enable bit + +// SEC Fault Management Interface (SFI) Register Definitions +#define SEC_FCTL 0x00000010 // SEC Fault Control Register + +// SEC Global Register Definitions +#define SEC_GCTL 0x00000000 // SEC Global Control Register +#define SEC_RAISE 0x00000008 // SEC Global Raise Register +#define SEC_END 0x0000000C // SEC Global End Register + +// SEC_SCTL +#define SEC_SCTL_CTG 0x0F000000 // Core Target Select + +// SEC Source Interface (SSI) Register Definitions +#define SEC_SCTL0 0x00000000 // SEC Source Control Register n + + +// SEC_SCTL +#define SEC_SCTL_SRC_EN 0x00000004 // SEN: Enable +#define SEC_SCTL_FAULT_EN 0x00000002 // FEN: Enable +#define SEC_SCTL_INT_EN 0x00000001 // IEN: Enable + + +// TRU0 +// 0x3108A000 + (0x4 * n) +#define REG_TRU0_SSR160 0x3108A280 // TRU0 Slave Select Register +#define REG_TRU0_SSR164 0x3108A290 // TRU0 Slave Select Register +#define REG_TRU0_SSR168 0x3108A2A0 // TRU0 Slave Select Register +#define REG_TRU0_MTR 0x3108A7E0 // TRU0 Master Trigger Register +#define REG_TRU0_GCTL 0x3108A7F4 // TRU0 Global Control Register + +// Trigger Master Definitions +#define TRGM_SOFT0 136 // Software-driven Trigger 3 +#define TRGM_SOFT1 137 // Software-driven Trigger 3 +#define TRGM_SOFT2 138 // Software-driven Trigger 4 +#define TRGM_SOFT3 139 // Software-driven Trigger 3 +#define TRGM_SOFT4 140 // Software-driven Trigger 4 +#define TRGM_SOFT5 141 // Software-driven Trigger 5 + +// RCU0 +#define REG_RCU0_CTL 0x3108C000 // RCU0 Control Register +#define REG_RCU0_STAT 0x3108C004 // RCU0 Status Register +#define REG_RCU0_CRCTL 0x3108C008 // RCU0 Core Reset Control Register +#define REG_RCU0_CRSTAT 0x3108C00C // RCU0 Core Reset Status Register +#define REG_RCU0_SIDIS 0x3108C01C // RCU0 System Interface Disable Register +#define REG_RCU0_SISTAT 0x3108C020 // RCU0 System Interface Status Register +#define REG_RCU0_BCODE 0x3108C028 // RCU0 Boot Code Register +#define REG_RCU0_MSG_SET 0x3108C070 // RCU0 Message Set Bits Register +#define REG_RCU0_SVECT1 0x3108C030 // Software Vector Register 1 +#define REG_RCU0_SVECT2 0x3108C034 // Software Vector Register 2 + +// SPU0 +#define REG_SPU0_CTL 0x3108B000 // SPU0 Control Register + +// LP0 +#define LP0_CTL 0x30FFE000 // LP0 Control Register + +// LP1 +#define LP1_CTL 0x30FFE100 // LP1 Control Register + +// PADS0 +#define REG_PADS0_BASE 0x31004600 // PADS Base Register +#define REG_PADS0_PCFG0 0x31004604 // PADS0 Peripheral Configuration0 Register +#define REG_PADS0_DAI0_IE 0x31004690 // PADS DAI0 IE Register +#define REG_PADS0_DAI1_IE 0x31004694 // PADS DAI1 IE Register +#define BITM_PADS_PCFG0_EMACRESET 0x00000004 // Reset Enable for RGMII +#define ENUM_PADS_PCFG0_EMACPHY_MII 0x00000000 // EMACPHYISEL: MII Interface +#define ENUM_PADS_PCFG0_EMACPHY_RGMII 0x00000008 // EMACPHYISEL: RGMII Interface +#define ENUM_PADS_PCFG0_EMACPHY_RMII 0x00000010 // EMACPHYISEL: RMII Interface +#define ENUM_PADS_PCFG0_EMAC0_RMII_CLK 0x00000000 // EMAC0: EMAC0_RMII CLK +#define ENUM_PADS_PCFG0_EMAC0_SCLK1 0x00000001 // EMAC0: SCLK +#define ENUM_PADS_PCFG0_EMAC0_EXT_CLK 0x00000002 // EMAC0: External Clock +#define ENUM_PADS_PCFG0_EMAC0_SCLK3 0x00000003 // EMAC0: SCLK + +#endif diff --git a/include/linux/soc/adi/system_config.h b/include/linux/soc/adi/system_config.h new file mode 100644 index 0000000000000000000000000000000000000000..788d39f0c0d36f233a7b48ef4e2f0a3f4750f711 --- /dev/null +++ b/include/linux/soc/adi/system_config.h @@ -0,0 +1,65 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Implementation of adi_system_config, potential replacement for syscon that + * generalizes it to support arbitrary regmap registration and requires the + * driver to be initialized first + * + * Copyright 2022-2024 - Analog Devices Inc. + */ + +#ifndef SOC_ADI_SYSTEM_CONFIG_H +#define SOC_ADI_SYSTEM_CONFIG_H + +#include +#include +#include + +struct adi_system_register { + uint32_t id; + uint32_t offset; + uint32_t mask; + uint8_t shift; + bool is_bits; +}; + +struct adi_system_config { + /* User configured */ + struct adi_system_register *registers; + unsigned int max_register; + size_t len; + + /* Internal data populated during usage */ + struct regmap_config config; + struct regmap *mmio_regmap; + struct device_node *np; + struct list_head list; + struct regmap *system_regmap; +}; + +/* + * All possible system register IDs across all platforms supported by this + * driver. + */ +enum adi_system_reg_id { + ADI_SYSTEM_REG_EMAC0_PTPCLK0 = 0, + ADI_SYSTEM_REG_EMAC0_EMACRESET, + ADI_SYSTEM_REG_EMAC0_PHYISEL, + ADI_SYSTEM_REG_CNT0UDSEL, + ADI_SYSTEM_REG_CNT0DGSEL, + ADI_SYSTEM_REG_TWI0VSEL, + ADI_SYSTEM_REG_TWI1VSEL, + ADI_SYSTEM_REG_TWI2VSEL, + ADI_SYSTEM_REG_PUMSIDLC, + ADI_SYSTEM_REG_PUMSIHL, + ADI_SYSTEM_REG_PUTMS, + ADI_SYSTEM_REG_EMAC0_AUXIE, + ADI_SYSTEM_REG_FAULT_DIS, + ADI_SYSTEM_REG_EMAC0_ENDIANNESS, + ADI_SYSTEM_REG_EMAC1_ENDIANNESS, + ADI_SYSTEM_REG_MSHC_CCLK_DIV_EN, + ADI_SYSTEM_REG_DAI0_IE, + ADI_SYSTEM_REG_DAI1_IE, + __ADI_SYSTEM_REG_COUNT +}; + +#endif From patchwork Thu Sep 12 18:24:47 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802426 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 46021EEE24B for ; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id 0B878C4CED3; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id DCB0CC4CECC; Thu, 12 Sep 2024 18:20:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165214; bh=8dLWDvRZuiv72Q6TAOn6fVt/7YqsuabBUo+o+OGlMyU=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=VqbMc3sSe8XPTG4aKjwtiE7Ni38ETDWMg2YaoyQj7Ap+AW4yBW3ayi7HRhFroDntm UUj2V4/FktWKGOjQwHeJCWz045YFBknAMWUsHrn/XnjE0+HsDdz7rzHJd9/OLCgXtr q90ZrDsheE67UQeZrZ9jWZivro2/1ud8zeRFV993OPZShptIbUWs4qbHRhcFycZRup q/YRQxYfdk0Gyv3lVZyuHI6KXM5NigLBVeitSvHP/5iY/2QVFvTeOkUOvfrs2RbwWq zfO51uwg4F+NWYmvAVexw2j+KGwoxWb2nsoJUptPgbbd3LWfBoDI6XuV58xMFwHy1x UFg7epqSnfPfg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id CC2E4EED63C; Thu, 12 Sep 2024 18:20:14 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:24:47 +0100 Subject: [PATCH 02/21] reset: Add driver for ADI ADSP-SC5xx reset controller MIME-Version: 1.0 Message-Id: <20240912-test-v1-2-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=1107; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=6HpYjgEvmaMOI/Jb3fHri0mjaXqIkqikV6XKYOwo4UI=; b=IH2NvBCHpRs5VQkod2iVyDR1RXm8CLNExn4siWAW8bwa8goIT5CiqggFT6fdO8v5CDutT0SE6 WCDnOQOeLYoANdKpXf80tUdcgMKb+KnMrk8RHqJ8/Q6xePGfmRj1xJJ X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Adding support for ADI ADSP reset controller. This driver allows trigger a software reset. Signed-off-by: Arturs Artamonovs Co-developed-by: Utsav Agarwal Signed-off-by: Utsav Agarwal Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- drivers/reset/Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index 27b0bbdfcc044ba58de9df09725ddef7b601c3ea..4d9e83b7ab38287336175d3804f9d2d4d2894595 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -4,6 +4,7 @@ obj-y += hisilicon/ obj-y += starfive/ obj-y += sti/ obj-y += tegra/ +obj-$(CONFIG_RESET_SC5XX) += reset-sc5xx.o obj-$(CONFIG_RESET_A10SR) += reset-a10sr.o obj-$(CONFIG_RESET_ATH79) += reset-ath79.o obj-$(CONFIG_RESET_AXS10X) += reset-axs10x.o From patchwork Thu Sep 12 18:24:48 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802424 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 43CD0EED63A for ; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id 282CBC4CED9; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id EDEFFC4CECF; Thu, 12 Sep 2024 18:20:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165215; bh=v/JKn3gZXUVsA3y1aAYS1Zs+qQ+FmLETkgfXkSxZq4w=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=lAwr0nJHscmkQPKJFkZwmbN3d58Z6g5GSxtJRwwW/TxBZFI1xAMWh2ov8FDk/XffI RuDyKAj7NFEa7l3Eq4KoKeaArG8RnocBC91iGMguqeWKiH7h+MGeS249SfJcl1ge4G Ygoi+ujwlnFX0CV6wkda4ppVAyasryIb7y15YxCSpknniVcYTYcBSgnJCTNKF6S9dQ RxL/Mk2iBvaeYc06sn9q4Y30+hpgPDsljUd/s7Ek6SBpVeOsY/vZY10/Dk9wJN/ipd 8kVmULd5wOQVinP8KQ2aMacAUtQAqZf4HYKwmAmquM10yyk1NjVCDR0j8HO3WOzZsH tPTzaQ94s4ojA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id DEFB1EED63F; Thu, 12 Sep 2024 18:20:14 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:24:48 +0100 Subject: [PATCH 03/21] dt-bindigs: arm64: adi,sc598 bindings MIME-Version: 1.0 Message-Id: <20240912-test-v1-3-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=1844; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=Oi5xgxW+vpOrfKsaRdGPlzsPaJn9xUo9SU1Q4oMSXZ8=; b=n14btFQRrorCCXsLphS1xj8VeFGWTdUV7UquRTRapHFoqbQL0L1h3/qkuUAr68TwMJSpzM7OS oeNnb/6FXwVDmqU7DayurCAzLZ1F5Xt2iNmuE/jKV0Ixq7kYAB18b49 X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Bindigs for ADI ADSP-SC5xx reset controller Signed-off-by: Arturs Artamonovs Co-developed-by: Utsav Agarwal Signed-off-by: Utsav Agarwal Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- .../bindings/soc/adi/adi,reset-controller.yaml | 38 ++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/Documentation/devicetree/bindings/soc/adi/adi,reset-controller.yaml b/Documentation/devicetree/bindings/soc/adi/adi,reset-controller.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7a6df1cfb709d818d5e3dbcd202938d6aaaaaa9b --- /dev/null +++ b/Documentation/devicetree/bindings/soc/adi/adi,reset-controller.yaml @@ -0,0 +1,38 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/soc/adi/adi,reset-controller.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices Reset Controller for SC5XX processor family + +maintainers: + - Arturs Artamonovs + - Utsav Agarwal + +description: | + SHARC and ARM core reset control unit for starting/stopping/resetting + processors + +properties: + compatible: + enum: + - adi,reset-controller + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + rcu: rcu@3108c000 { + compatible = "adi,reset-controller"; + reg = <0x3108c000 0x1000>; + status = "okay"; + }; + From patchwork Thu Sep 12 18:24:49 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802427 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6A32EEEE250 for ; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id 2D015C4CEE0; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id 09CB5C4CED6; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165215; bh=ak6ugCgePWMuuhlzPto+EIgq5Wrvc9n4HiCJ3WjxHWQ=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=DUGaqXxKWQ2MyRKhDWTrsqb+VrBv8RZ11ecnbCzhgP7f8KSEmrTbAEpxnIVj+myoh i6vJvOJ3h0DJ8k/Yqhzvd93jJ15bvbF40c3v9SwoIZLKrxkoT3GwEjr0fY6OOTNl1j QahLrP7nr+COk9hi5X1cSksbR0qPCU9+hpoHbTjbBEUj7Jm1ZlmTR5dCzEGLVMBEnq 6q3Qf/6LsmPC4HjFOnHw0Pd1kj+QeAWvUuBu+fp19HOUoSWP+nI16dMDhTM8fZkQgX M32Hjuz9y0MEgl+yUFIL4hY4TTmg6/b/Vm/1+ccHHKPCWuTwsz9dyNiffmKtapk8JN wR1KeZA7BuItQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 00AB1EED63D; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:24:49 +0100 Subject: [PATCH 04/21] dt-bindings: arm64: adi,sc598: Add ADSP-SC598 SoC bindings MIME-Version: 1.0 Message-Id: <20240912-test-v1-4-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=1623; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=J/EuJUpRixtiC/Xhn+9Y770N03I2X4hm7a/3wJC2XVg=; b=R9KdkvfGVHCd5bCvdZq8qKxmeajLuKI+hlHTFb+pbWAQDWDoXhfEOnOZ5i5NTWG/+O7XX5yRE y6kVkSWYiyfBVn1snKVwFxUZTDwNmRMmpVlpC0KLbcw86AkHCFcMMrz X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs add SoC ADSP-SC5xx Signed-off-by: Arturs Artamonovs Signed-off-by: Utsav Agarwal Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- .../devicetree/bindings/arm/analog/adi,sc5xx.yaml | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Documentation/devicetree/bindings/arm/analog/adi,sc5xx.yaml b/Documentation/devicetree/bindings/arm/analog/adi,sc5xx.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fc37242b32b9ca9b82fd5b3e0288642e8c4fd9f0 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/analog/adi,sc5xx.yaml @@ -0,0 +1,24 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/arm/analog/adi,sc5xx.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices SC59X 64-Bit ARM-based Processor Families + +maintainers: + - Arturs Artamonovs + - Utsav Agarwal + +properties: + $nodename: + const: '/' + compatible: + description: SC59X 64-Bit Boards + items: + - enum: + - adi,sc598-som-ezkit # Analog Devices SC598 EZKit + - adi,sc598-som-ezlite # Analog Devices SC598 EZLite + - const: adi,sc59x-64 + +additionalProperties: true From patchwork Thu Sep 12 18:24:50 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802425 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 4F837EED63F for ; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id 3A96AC4CEE6; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id 1BC91C4CEDA; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165215; bh=WvuwUE3VkVrJz1HbbjLyC5fbTxNBjf8aLWKIvGiS8ZI=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=b+YSqrPxZMaWAWsU7bwfST26nLi93Ml85js3T7Ir1g2oMK7q33Lmw8NbN/YkR1fLv S3Ajsi1PYZH22+NgsRDq13/lFT4WEzn1cPZIF1oukpRfpwHp+uDk5HkhC4bLQ3p0tb 8aL3QRCQaZ1U30kHN2FjT7GSIZyzjSvvWSH9u+5mwpWRLEu3HWLkl4qLBNQs+hzYr0 xkOLjgIUp7P5MqZh8C2Jk+dhmHPMwaII8ibWBMwesssmZEpzs01+Tk1RGpPJHGpTtD +jErwxUBqSZVALuJlGvl/Y6xojm3IObwvs5v6HlzvDThMHw0lXZD6E41BYCKXNVyVL GVH5SLLgTFMnw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1369DEEE240; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:24:50 +0100 Subject: [PATCH 05/21] clock:Add driver for ADI ADSP-SC5xx PLL MIME-Version: 1.0 Message-Id: <20240912-test-v1-5-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=7757; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=kKwWyaM2Blr339gT53LjtoBsxg/6T1Q1BsxHjj63Pk0=; b=J7Br682QHi9UgPDIRSCY68wh2/Zg7TIwYyngp7ewWcshD/o13+AQ7Ebd+zKvBFcOqD1LLjSHb obWccR+jIskA5qWU4GP7vAE8q8I9icPmqNtPJy6OZA0E52BtDddhgpK X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Implements clock tree, no dynamic pll rate change. Signed-off-by: Arturs Artamonovs Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- drivers/clk/adi/clk-adi-pll.c | 151 ++++++++++++++++++++++++++++++++++++++++++ drivers/clk/adi/clk.h | 99 +++++++++++++++++++++++++++ 2 files changed, 250 insertions(+) diff --git a/drivers/clk/adi/clk-adi-pll.c b/drivers/clk/adi/clk-adi-pll.c new file mode 100644 index 0000000000000000000000000000000000000000..39fcc78b3170c0aa5962af5268f499082efb3686 --- /dev/null +++ b/drivers/clk/adi/clk-adi-pll.c @@ -0,0 +1,151 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * CGU PLL driver for ADI SC59X processors + * + * Copyright 2022-2024 - Analog Devices Inc. + */ + +#include +#include +#include +#include + +#include "clk.h" + +struct clk_sc5xx_cgu_pll { + struct clk_hw hw; + void __iomem *base; + spinlock_t *lock; + int prepared; + u32 mask; + u32 msel; + u32 m_offset; + u8 shift; +}; + +struct clk_sc5xx_cgu_pll *to_clk_sc5xx_cgu_pll(struct clk_hw *hw) +{ + return container_of(hw, struct clk_sc5xx_cgu_pll, hw); +} + +static long sc5xx_cgu_pll_round_rate(struct clk_hw *hw, unsigned long rate, + unsigned long *parent_rate) +{ + struct clk_sc5xx_cgu_pll *pll = to_clk_sc5xx_cgu_pll(hw); + unsigned long m, m2, new_rate, nr2, prate2; + unsigned long prate = *parent_rate; + struct clk_hw *parent_hw; + int parent_inc; + + parent_hw = clk_hw_get_parent(hw); + + m = rate / prate; + + if (m > pll->msel) { + /* cannot scale this far, need bigger input */ + parent_inc = m / pll->msel; + prate = clk_hw_round_rate(parent_hw, prate * (parent_inc + 1)); + } else if (m == 0) { + pr_err("%s: Cannot use VCO to reduce parent clock rate, requested %lu, clamping to %lu\n", + __func__, rate, prate); + return prate; + } + + new_rate = prate * m; + + if (new_rate != rate) { + /* + * Check if we could get an integer match by halving parent rate since we + * know at least about the DF bit before the VCO, although we don't know + * if we're already using it or not + */ + prate2 = clk_hw_round_rate(parent_hw, prate / 2); + m2 = rate / prate2; + nr2 = prate * m2; + if (m2 <= pll->msel && nr2 == rate) { + m = m2; + new_rate = nr2; + prate = prate2; + } + } + + *parent_rate = prate; + return new_rate; +} + +static unsigned long sc5xx_cgu_pll_recalc_rate(struct clk_hw *hw, + unsigned long parent_rate) +{ + struct clk_sc5xx_cgu_pll *pll = to_clk_sc5xx_cgu_pll(hw); + u32 reg = readl(pll->base); + u32 m = ((reg & pll->mask) >> pll->shift) + pll->m_offset; + + if (m == 0) + m = pll->msel; + + return parent_rate * m; + +} + +static int sc5xx_cgu_pll_set_rate(struct clk_hw *hw, unsigned long rate, + unsigned long parent_rate) +{ + struct clk_sc5xx_cgu_pll *pll = to_clk_sc5xx_cgu_pll(hw); + u32 m; + + m = (rate / parent_rate) - pll->m_offset; + + if (m >= pll->msel) + m = 0; + + /* reminder for implementation: lock around read/modify to control reg */ + pr_err("%s: set_rate not permitted yet, but we would write %d to m\n", __func__, + m); + return -ENOENT; +} + +static const struct clk_ops clk_sc5xx_cgu_pll_ops = { + .recalc_rate = sc5xx_cgu_pll_recalc_rate, + .round_rate = sc5xx_cgu_pll_round_rate, + .set_rate = sc5xx_cgu_pll_set_rate, +}; + +struct clk *sc5xx_cgu_pll(const char *name, const char *parent_name, + void __iomem *base, u8 shift, u8 width, u32 m_offset, + spinlock_t *lock) +{ + struct clk_sc5xx_cgu_pll *pll; + struct clk *clk; + struct clk_init_data init; + + pll = kzalloc(sizeof(*pll), GFP_KERNEL); + if (!pll) + return ERR_PTR(-ENOMEM); + + init.name = name; + init.flags = CLK_SET_RATE_PARENT; + init.parent_names = &parent_name; + init.num_parents = 1; + init.ops = &clk_sc5xx_cgu_pll_ops; + + pll->base = base; + pll->hw.init = &init; + pll->lock = lock; + pll->shift = shift; + pll->mask = GENMASK(width-1, 0) << shift; + pll->msel = pll->mask + 1; + pll->m_offset = m_offset; + + clk = clk_register(NULL, &pll->hw); + if (IS_ERR(clk)) { + pr_err("%s: Failed to register, code %lu\n", __func__, + PTR_ERR(clk)); + } + + return clk; +} + +MODULE_DESCRIPTION("Analog Devices CLock PLL driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Greg Malysa "); + diff --git a/drivers/clk/adi/clk.h b/drivers/clk/adi/clk.h new file mode 100644 index 0000000000000000000000000000000000000000..e17aa719c2170149a6a1a60dd4390a29f06e7296 --- /dev/null +++ b/drivers/clk/adi/clk.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Clock support for ADI processors + * + * Copyright 2022-2024 - Analog Devices Inc. + */ + +#ifndef CLK_ADI_CLK_H +#define CLK_ADI_CLK_H + +#include + +#define CGU_CTL 0x00 +#define CGU_PLLCTL 0x04 +#define CGU_STAT 0x08 +#define CGU_DIV 0x0C +#define CGU_CLKOUTSEL 0x10 +#define CGU_OSCWDCTL 0x14 +#define CGU_TSCTL 0x18 +#define CGU_TSVALUE0 0x1C +#define CGU_TSVALUE1 0x20 +#define CGU_TSCOUNT0 0x24 +#define CGU_TSCOUNT1 0x28 +#define CGU_CCBF_DIS 0x2C +#define CGU_CCBF_STAT 0x30 +#define CGU_SCBF_DIS 0x38 +#define CGU_SCBF_STAT 0x3C +#define CGU_DIVEX 0x40 +#define CGU_REVID 0x48 + +#define CDU_CFG0 0x00 +#define CDU_CFG1 0x04 +#define CDU_CFG2 0x08 +#define CDU_CFG3 0x0C +#define CDU_CFG4 0x10 +#define CDU_CFG5 0x14 +#define CDU_CFG6 0x18 +#define CDU_CFG7 0x1C +#define CDU_CFG8 0x20 +#define CDU_CFG9 0x24 +#define CDU_CFG10 0x28 +#define CDU_CFG11 0x2C +#define CDU_CFG12 0x30 +#define CDU_CFG13 0x34 +#define CDU_CFG14 0x38 + +#define PLL3_OFFSET 0x2c + +#define CDU_CLKINSEL 0x44 + +#define CGU_MSEL_SHIFT 8 +#define CGU_MSEL_WIDTH 7 + +#define PLL3_MSEL_SHIFT 4 +#define PLL3_MSEL_WIDTH 7 + +#define CDU_MUX_SIZE 4 +#define CDU_MUX_SHIFT 1 +#define CDU_MUX_WIDTH 2 +#define CDU_EN_BIT 0 + +struct clk_sc5xx_cgu_pll *to_clk_sc5xx_cgu_pll(struct clk_hw *hw); + +struct clk *sc5xx_cgu_pll(const char *name, const char *parent_name, + void __iomem *base, u8 shift, u8 width, u32 m_offset, spinlock_t *lock); + +/** + * All CDU clock muxes are the same size + */ +static inline struct clk *cdu_mux(const char *name, void __iomem *reg, + const char * const *parents, spinlock_t *cdu_lock) +{ + return clk_register_mux(NULL, name, parents, CDU_MUX_SIZE, + CLK_SET_RATE_PARENT, reg, CDU_MUX_SHIFT, CDU_MUX_WIDTH, 0, + cdu_lock); +} + +static inline struct clk *cgu_divider(const char *name, const char *parent, + void __iomem *reg, u8 shift, u8 width, u8 extra_flags, spinlock_t *cdu_lock) +{ + return clk_register_divider(NULL, name, parent, CLK_SET_RATE_PARENT, + reg, shift, width, CLK_DIVIDER_MAX_AT_ZERO | extra_flags, cdu_lock); +} + +static inline struct clk *cdu_gate(const char *name, const char *parent, + void __iomem *reg, u32 flags, spinlock_t *cdu_lock) +{ + return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT | flags, + reg, CDU_EN_BIT, 0, cdu_lock); +} + +static inline struct clk *cgu_gate(const char *name, const char *parent, + void __iomem *reg, u8 bit, spinlock_t *cdu_lock) +{ + return clk_register_gate(NULL, name, parent, CLK_SET_RATE_PARENT, reg, bit, + CLK_GATE_SET_TO_DISABLE, cdu_lock); +} + +#endif From patchwork Thu Sep 12 18:24:51 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802428 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 67C03EEE24E for ; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id 4F7FBC4CEE9; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id 328ABC4CEE1; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165215; bh=TAvj/gNZj1rstVTZNHKfYn84bNB1hLFim2lMkTFzOnk=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=qv9AJUHwkYur1gjCRGsv4tTxfn5YYyY4BVHZSsoXaPBbm0jV9HIqbHErixfD6VJ4l NqtoRb+pRbm81twqsYF90bX5GqvH5up4wFFdJXO0hUAGqG8d7KnPV0zv7gSmWdWN1G FHxcafjYelE5ikDwCIcR1qi8nu7Zbnj99ahnNJY5DYCJB2ZKKQRJ4v3SKXu+nhrBqt 5nvMeluC/zizqOLeEsw1OfX3nAFkC4NahNMNljKPEUfcMm+pZBrJ5ilIwc/L4ZNF29 OF54cEGmW0rXc0x6200EvB+ksyX+Q/I7XFYi/Sm+stkXRv1xbwFoSYnvI1quTUTXio CPhTPVyY6gdvQ== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 281A5EED63F; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:24:51 +0100 Subject: [PATCH 06/21] include: dt-binding: clock: add adi clock header file MIME-Version: 1.0 Message-Id: <20240912-test-v1-6-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=4153; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=tPiF/DaY6UORa5f5iyBwG+k45QdAa3ZySrbsiRLF6Cc=; b=r71K9MzY6ONZnGXOuRJSwoTdhK0WXTFZ4S0T+uvezlfMOqM9MA/kGKSJMD86VcBBnyFCLjBBD JduICltZI6lA9QAIMLZjzW9gVzn4gOIYm0i3WCY9uEggXoVCd8M7dTZ X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Add adi clock driver header file Signed-off-by: Arturs Artamonovs Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- include/dt-bindings/clock/adi-sc5xx-clock.h | 93 +++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) diff --git a/include/dt-bindings/clock/adi-sc5xx-clock.h b/include/dt-bindings/clock/adi-sc5xx-clock.h new file mode 100644 index 0000000000000000000000000000000000000000..723c11dc44f9741cff49dc2cb6c5232022abf00c --- /dev/null +++ b/include/dt-bindings/clock/adi-sc5xx-clock.h @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * ADSP SC5xx clock device tree bindings + * + * Copyright 2022-2024 - Analog Devices Inc. + */ + +#ifndef DT_BINDINGS_CLOCK_ADI_SC5XX_CLOCK_H +#define DT_BINDINGS_CLOCK_ADI_SC5XX_CLOCK_H + +#define ADSP_SC598_CLK_DUMMY 0 +#define ADSP_SC598_CLK_SYS_CLKIN0 1 +#define ADSP_SC598_CLK_SYS_CLKIN1 2 +#define ADSP_SC598_CLK_CGU0_PLL_IN 3 +#define ADSP_SC598_CLK_CGU0_VCO_OUT 4 +#define ADSP_SC598_CLK_CGU0_PLLCLK 5 +#define ADSP_SC598_CLK_CGU1_IN 6 +#define ADSP_SC598_CLK_CGU1_PLL_IN 7 +#define ADSP_SC598_CLK_CGU1_VCO_OUT 8 +#define ADSP_SC598_CLK_CGU1_PLLCLK 9 +#define ADSP_SC598_CLK_CGU0_CDIV 10 +#define ADSP_SC598_CLK_CGU0_SYSCLK 11 +#define ADSP_SC598_CLK_CGU0_DDIV 12 +#define ADSP_SC598_CLK_CGU0_ODIV 13 +#define ADSP_SC598_CLK_CGU0_S0SELDIV 14 +#define ADSP_SC598_CLK_CGU0_S1SELDIV 15 +#define ADSP_SC598_CLK_CGU0_S1SELEXDIV 16 +#define ADSP_SC598_CLK_CGU0_S1SEL 17 +#define ADSP_SC598_CLK_CGU1_CDIV 18 +#define ADSP_SC598_CLK_CGU1_SYSCLK 19 +#define ADSP_SC598_CLK_CGU1_DDIV 20 +#define ADSP_SC598_CLK_CGU1_ODIV 21 +#define ADSP_SC598_CLK_CGU1_S0SELDIV 22 +#define ADSP_SC598_CLK_CGU1_S1SELDIV 23 +#define ADSP_SC598_CLK_CGU1_S0SELEXDIV 24 +#define ADSP_SC598_CLK_CGU1_S1SELEXDIV 25 +#define ADSP_SC598_CLK_CGU1_S0SEL 26 +#define ADSP_SC598_CLK_CGU1_S1SEL 27 +#define ADSP_SC598_CLK_CGU0_CCLK2 28 +#define ADSP_SC598_CLK_CGU0_CCLK0 29 +#define ADSP_SC598_CLK_CGU0_OCLK 30 +#define ADSP_SC598_CLK_CGU0_DCLK 31 +#define ADSP_SC598_CLK_CGU0_SCLK1 32 +#define ADSP_SC598_CLK_CGU0_SCLK0 33 +#define ADSP_SC598_CLK_CGU1_CCLK0 34 +#define ADSP_SC598_CLK_CGU1_OCLK 35 +#define ADSP_SC598_CLK_CGU1_DCLK 36 +#define ADSP_SC598_CLK_CGU1_SCLK1 37 +#define ADSP_SC598_CLK_CGU1_SCLK0 38 +#define ADSP_SC598_CLK_CGU1_CCLK2 39 +#define ADSP_SC598_CLK_DCLK0_HALF 40 +#define ADSP_SC598_CLK_DCLK1_HALF 41 +#define ADSP_SC598_CLK_CGU1_SCLK1_HALF 42 +#define ADSP_SC598_CLK_SHARC0_SEL 43 +#define ADSP_SC598_CLK_SHARC1_SEL 44 +#define ADSP_SC598_CLK_ARM_SEL 45 +#define ADSP_SC598_CLK_CDU_DDR_SEL 46 +#define ADSP_SC598_CLK_CAN_SEL 47 +#define ADSP_SC598_CLK_SPDIF_SEL 48 +#define ADSP_SC598_CLK_SPI_SEL 49 +#define ADSP_SC598_CLK_GIGE_SEL 50 +#define ADSP_SC598_CLK_LP_SEL 51 +#define ADSP_SC598_CLK_LP_DDR_SEL 52 +#define ADSP_SC598_CLK_OSPI_REFCLK_SEL 53 +#define ADSP_SC598_CLK_TRACE_SEL 54 +#define ADSP_SC598_CLK_EMMC_SEL 55 +#define ADSP_SC598_CLK_EMMC_TIMER_QMC_SEL 56 +#define ADSP_SC598_CLK_SHARC0 57 +#define ADSP_SC598_CLK_SHARC1 58 +#define ADSP_SC598_CLK_ARM 59 +#define ADSP_SC598_CLK_CDU_DDR 60 +#define ADSP_SC598_CLK_CAN 61 +#define ADSP_SC598_CLK_SPDIF 62 +#define ADSP_SC598_CLK_SPI 63 +#define ADSP_SC598_CLK_GIGE 64 +#define ADSP_SC598_CLK_LP 65 +#define ADSP_SC598_CLK_LP_DDR 66 +#define ADSP_SC598_CLK_OSPI_REFCLK 67 +#define ADSP_SC598_CLK_TRACE 68 +#define ADSP_SC598_CLK_EMMC 69 +#define ADSP_SC598_CLK_EMMC_TIMER_QMC 70 +#define ADSP_SC598_CLK_3PLL_PLL_IN 71 +#define ADSP_SC598_CLK_3PLL_VCO_OUT 72 +#define ADSP_SC598_CLK_3PLL_PLLCLK 73 +#define ADSP_SC598_CLK_3PLL_DDIV 74 +#define ADSP_SC598_CLK_DDR_SEL 75 +#define ADSP_SC598_CLK_DDR 76 +#define ADSP_SC598_CLK_CGU0_VCO_2_OUT 77 +#define ADSP_SC598_CLK_CGU1_VCO_2_OUT 78 +#define ADSP_SC598_CLK_3PLL_VCO_2_OUT 79 +#define ADSP_SC598_CLK_END 80 + +#endif From patchwork Thu Sep 12 18:24:52 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802433 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 9AD43EEE249 for ; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id 6F47BC4AF65; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id 4CC40C4CEE8; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165215; bh=ShQ/LProzO9Hm4NwCG67p9rw+RFa0AA/In63K50o89w=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=Ziscm7wa/lpA8bnPlLQotGEH/cq8TOCA3FVLWzCkW0fwtKsoK3rQVm0l30CqKsO0C lgxiyPlOuPgZl6cKYH311I5VsJVft+fYT5bUofCvWdjGOVxmt+bI1ekpyzLzB16dIy +09gOls6ra1/e+zX0t3tbA6VSFAW8g9iypUwJVQF69NqqX2DL6hXX0RcnQT9VFdAAM 5juciC4ejeJv2rZOCwHOTss84ATa3n9KF4VsEdFKVokwvXkYeEH8Alj7rDxAqY/kL0 AG3bXL+0sTuFzFlVChAC72N2eH/IbbGMabEAKtKxEwct7BpQzju8XXxXYUsNDB5RnV NBv5PSAvuSYEw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 40536EEE240; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:24:52 +0100 Subject: [PATCH 07/21] clock: Add driver for ADI ADSP-SC5xx clock MIME-Version: 1.0 Message-Id: <20240912-test-v1-7-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=17101; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=LJfzHgjxAEXxENnyA4nkGwc9Qp/oj6ODq57mjKreJaQ=; b=jXDXV3Qh6baJWv1oojfxLBfGcsFXKJpvJDrmGyIwjeJt9yLfrxH8oWaueZVvEgLKHFHP0klV/ FC74DghtWOCAmJIaIOe7dwfeokRV8Yn91cVHdxeS86xurBZEHUhgIPN X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Add ADSP-SC5xx clock driver Signed-off-by: Arturs Artamonovs Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- drivers/clk/Kconfig | 9 ++ drivers/clk/Makefile | 1 + drivers/clk/adi/Makefile | 4 + drivers/clk/adi/clk-adi-sc598.c | 329 ++++++++++++++++++++++++++++++++++++++++ 4 files changed, 343 insertions(+) diff --git a/drivers/clk/Kconfig b/drivers/clk/Kconfig index 983ef4f36d8c4387556d6b5d32f01dd4afa815a3..a3a076294c285d820f1c6922b872ff73174192c0 100644 --- a/drivers/clk/Kconfig +++ b/drivers/clk/Kconfig @@ -42,6 +42,15 @@ config COMMON_CLK_WM831X source "drivers/clk/versatile/Kconfig" +config COMMON_CLK_ADI_SC598 + bool "Clock driver for ADI SC598 SoCs" + depends on OF && ARCH_SC59X_64 + help + This driver supports the system clocks on Analog Devices SC598-series + SoCs. It includes CGU and CDU clocks and supports gating unused clocks. + Modifying PLL configuration is not supported; that must be done prior + to booting the kernel. Clock dividers after the PLLs may be configured. + config CLK_HSDK bool "PLL Driver for HSDK platform" depends on ARC_SOC_HSDK || COMPILE_TEST diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile index f793a16cad40bfff0d06989179e5401d7f3e69cc..9f48f81b9285ab19027cc287e62547a3c1332517 100644 --- a/drivers/clk/Makefile +++ b/drivers/clk/Makefile @@ -84,6 +84,7 @@ obj-$(CONFIG_COMMON_CLK_XGENE) += clk-xgene.o # please keep this section sorted lexicographically by directory path name obj-y += actions/ +obj-y += adi/ obj-y += analogbits/ obj-$(CONFIG_COMMON_CLK_AT91) += at91/ obj-$(CONFIG_ARCH_ARTPEC) += axis/ diff --git a/drivers/clk/adi/Makefile b/drivers/clk/adi/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..2a83dff54adaddd81f3f33bd962fe6302e14a8a7 --- /dev/null +++ b/drivers/clk/adi/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 +#SC598 +obj-$(CONFIG_COMMON_CLK_ADI_SC598) += clk-adi-pll.o +obj-$(CONFIG_COMMON_CLK_ADI_SC598) += clk-adi-sc598.o diff --git a/drivers/clk/adi/clk-adi-sc598.c b/drivers/clk/adi/clk-adi-sc598.c new file mode 100644 index 0000000000000000000000000000000000000000..9d0b01b813a0aa44bbeb35bb4deaa3b38ca90834 --- /dev/null +++ b/drivers/clk/adi/clk-adi-sc598.c @@ -0,0 +1,329 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Clock support for ADI processor + * + * Copyright 2022-2024 - Analog Devices Inc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "clk.h" + +struct clk_core { + const char *name; + const struct clk_ops *ops; + struct clk_hw *hw; + struct module *owner; + struct device *dev; + struct hlist_node rpm_node; + struct device_node *of_node; + struct clk_core *parent; + struct clk_parent_map *parents; + u8 num_parents; + u8 new_parent_index; + unsigned long rate; + unsigned long req_rate; + unsigned long new_rate; + struct clk_core *new_parent; + struct clk_core *new_child; + unsigned long flags; + bool orphan; + bool rpm_enabled; + unsigned int enable_count; + unsigned int prepare_count; + unsigned int protect_count; + unsigned long min_rate; + unsigned long max_rate; + unsigned long accuracy; + int phase; + struct clk_duty duty; + struct hlist_head children; + struct hlist_node child_node; + struct hlist_head clks; + unsigned int notifier_count; +#ifdef CONFIG_DEBUG_FS + struct dentry *dentry; + struct hlist_node debug_node; +#endif + struct kref ref; +}; + +struct clk { + struct clk_core *core; + struct device *dev; + const char *dev_id; + const char *con_id; + unsigned long min_rate; + unsigned long max_rate; + unsigned int exclusive_count; + struct hlist_node clks_node; +}; + +static DEFINE_SPINLOCK(cdu_lock); + +static struct clk *clks[ADSP_SC598_CLK_END]; +static struct clk_onecell_data clk_data; + +static const char * const cgu1_in_sels[] = {"sys_clkin0", "sys_clkin1"}; +static const char * const cgu0_s1sels[] = {"cgu0_s1seldiv", "cgu0_s1selexdiv"}; +static const char * const cgu1_s0sels[] = {"cgu1_s0seldiv", "cgu1_s0selexdiv"}; +static const char * const cgu1_s1sels[] = {"cgu1_s1seldiv", "cgu1_s1selexdiv"}; +static const char * const sharc0_sels[] = {"cclk0_0", "dummy", "dummy", "dummy"}; +static const char * const sharc1_sels[] = {"cclk0_0", "dummy", "dummy", "dummy"}; +static const char * const arm_sels[] = {"dummy", "dummy", "cclk2_0", "cclk2_1"}; +static const char * const cdu_ddr_sels[] = {"dclk_0", "dclk_1", "dummy", "dummy"}; +static const char * const can_sels[] = {"dummy", "oclk_1", "dummy", "dummy"}; +static const char * const spdif_sels[] = {"sclk1_0", "dummy", "dummy", "dummy"}; +static const char * const spi_sels[] = {"sclk0_0", "oclk_0", "dummy", "dummy"}; +static const char * const gige_sels[] = {"sclk0_0", "sclk0_1", "dummy", "dummy"}; +static const char * const lp_sels[] = {"oclk_0", "sclk0_0", "cclk0_1", "dummy"}; +static const char * const lp_ddr_sels[] = {"oclk_0", "dclk_0", "sysclk_1", "dummy"}; +static const char * const ospi_refclk_sels[] = {"sysclk_0", "sclk0_0", "sclk1_1", "dummy"}; +static const char * const trace_sels[] = {"sclk0_0", "dummy", "dummy", "dummy"}; +static const char * const emmc_sels[] = {"oclk_0", "sclk0_1", "dclk_0_half", "dclk_1_half"}; +static const char * const emmc_timer_sels[] = {"dummy", "sclk1_1_half", "dummy", "dummy"}; + +static const char * const ddr_sels[] = {"cdu_ddr", "3pll_ddiv"}; + +static void sc598_clock_setup(struct device_node *np) +{ + void __iomem *cgu0; + void __iomem *cgu1; + void __iomem *cdu; + void __iomem *pll3; + int i; + + cgu0 = of_iomap(np, 0); + if (IS_ERR(cgu0)) { + pr_err("Unable to remap CGU0 address (resource 0)\n"); + return; + } + + cgu1 = of_iomap(np, 1); + if (IS_ERR(cgu1)) { + pr_err("Unable to remap CGU1 address (resource 1)\n"); + return; + } + + cdu = of_iomap(np, 2); + if (IS_ERR(cdu)) { + pr_err("Unable to remap CDU address (resource 2)\n"); + return; + } + + pll3 = of_iomap(np, 3); + if (IS_ERR(pll3)) { + pr_err("Unable to remap PLL3 control register (resource 3)\n"); + return; + } + + // We only access this one register for pll3 + pll3 = pll3 + PLL3_OFFSET; + + // Input clock configuration + clks[ADSP_SC598_CLK_DUMMY] = clk_register_fixed_rate(NULL, "dummy", NULL, 0, 0); + clks[ADSP_SC598_CLK_SYS_CLKIN0] = of_clk_get_by_name(np, "sys_clkin0"); + clks[ADSP_SC598_CLK_SYS_CLKIN1] = of_clk_get_by_name(np, "sys_clkin1"); + clks[ADSP_SC598_CLK_CGU1_IN] = clk_register_mux(NULL, "cgu1_in_sel", + cgu1_in_sels, 2, CLK_SET_RATE_PARENT, cdu + CDU_CLKINSEL, 0, 1, 0, + &cdu_lock); + + // 3rd pll reuses cgu1 clk in selection, feeds directly into 3pll df + // changing the cgu1 in sel mux will affect 3pll so reuse the same clocks + + // CGU configuration and internal clocks + clks[ADSP_SC598_CLK_CGU0_PLL_IN] = clk_register_divider(NULL, "cgu0_df", + "sys_clkin0", CLK_SET_RATE_PARENT, cgu0 + CGU_CTL, 0, 1, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU1_PLL_IN] = clk_register_divider(NULL, "cgu1_df", + "cgu1_in_sel", CLK_SET_RATE_PARENT, cgu1 + CGU_CTL, 0, 1, 0, &cdu_lock); + clks[ADSP_SC598_CLK_3PLL_PLL_IN] = clk_register_divider(NULL, "3pll_df", + "cgu1_in_sel", CLK_SET_RATE_PARENT, pll3, 3, 1, 0, &cdu_lock); + + // VCO output inside PLL + clks[ADSP_SC598_CLK_CGU0_VCO_OUT] = sc5xx_cgu_pll("cgu0_vco_msel", "cgu0_df", + cgu0 + CGU_CTL, CGU_MSEL_SHIFT, CGU_MSEL_WIDTH, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU1_VCO_OUT] = sc5xx_cgu_pll("cgu1_vco_msel", "cgu1_df", + cgu1 + CGU_CTL, CGU_MSEL_SHIFT, CGU_MSEL_WIDTH, 0, &cdu_lock); + clks[ADSP_SC598_CLK_3PLL_VCO_OUT] = sc5xx_cgu_pll("3pll_vco_msel", "3pll_df", + pll3, PLL3_MSEL_SHIFT, PLL3_MSEL_WIDTH, 1, &cdu_lock); + + //MSEL constant factor + clks[ADSP_SC598_CLK_CGU0_VCO_2_OUT] = clk_register_fixed_factor(NULL, + "cgu0_vco", "cgu0_vco_msel", CLK_SET_RATE_PARENT, 2, 1); + clks[ADSP_SC598_CLK_CGU1_VCO_2_OUT] = clk_register_fixed_factor(NULL, + "cgu1_vco", "cgu0_vco_msel", CLK_SET_RATE_PARENT, 2, 1); + clks[ADSP_SC598_CLK_3PLL_VCO_2_OUT] = clk_register_fixed_factor(NULL, + "3pll_vco", "cgu0_vco_msel", CLK_SET_RATE_PARENT, 2, 1); + + // Final PLL output + clks[ADSP_SC598_CLK_CGU0_PLLCLK] = clk_register_fixed_factor(NULL, + "cgu0_pllclk", "cgu0_vco", CLK_SET_RATE_PARENT, 1, 2); + clks[ADSP_SC598_CLK_CGU1_PLLCLK] = clk_register_fixed_factor(NULL, + "cgu1_pllclk", "cgu1_vco", CLK_SET_RATE_PARENT, 1, 2); + clks[ADSP_SC598_CLK_3PLL_PLLCLK] = clk_register_fixed_factor(NULL, + "3pll_pllclk", "3pll_vco", CLK_SET_RATE_PARENT, 1, 2); + + // Dividers from pll output + clks[ADSP_SC598_CLK_CGU0_CDIV] = cgu_divider("cgu0_cdiv", "cgu0_pllclk", + cgu0 + CGU_DIV, 0, 5, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU0_SYSCLK] = cgu_divider("sysclk_0", "cgu0_pllclk", + cgu0 + CGU_DIV, 8, 5, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU0_DDIV] = cgu_divider("cgu0_ddiv", "cgu0_pllclk", + cgu0 + CGU_DIV, 16, 5, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU0_ODIV] = cgu_divider("cgu0_odiv", "cgu0_pllclk", + cgu0 + CGU_DIV, 22, 7, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU0_S0SELDIV] = cgu_divider("cgu0_s0seldiv", + "sysclk_0", cgu0 + CGU_DIV, 5, 3, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU0_S1SELDIV] = cgu_divider("cgu0_s1seldiv", + "sysclk_0", cgu0 + CGU_DIV, 13, 3, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU0_S1SELEXDIV] = cgu_divider("cgu0_s1selexdiv", + "cgu0_pllclk", cgu0 + CGU_DIVEX, 16, 8, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU0_S1SEL] = clk_register_mux(NULL, "cgu0_sclk1sel", + cgu0_s1sels, 2, CLK_SET_RATE_PARENT, cgu0 + CGU_CTL, 17, 1, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU0_CCLK2] = clk_register_fixed_factor(NULL, + "cclk2_0", "cgu0_vco", CLK_SET_RATE_PARENT, 1, 3); + + clks[ADSP_SC598_CLK_CGU1_CDIV] = cgu_divider("cgu1_cdiv", "cgu1_pllclk", + cgu1 + CGU_DIV, 0, 5, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU1_SYSCLK] = cgu_divider("sysclk_1", "cgu1_pllclk", + cgu1 + CGU_DIV, 8, 5, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU1_DDIV] = cgu_divider("cgu1_ddiv", "cgu1_pllclk", + cgu1 + CGU_DIV, 16, 5, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU1_ODIV] = cgu_divider("cgu1_odiv", "cgu1_pllclk", + cgu1 + CGU_DIV, 22, 7, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU1_S0SELDIV] = cgu_divider("cgu1_s0seldiv", + "sysclk_1", cgu1 + CGU_DIV, 5, 3, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU1_S1SELDIV] = cgu_divider("cgu1_s1seldiv", + "sysclk_1", cgu1 + CGU_DIV, 13, 3, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU1_S0SELEXDIV] = cgu_divider("cgu1_s0selexdiv", + "cgu1_pllclk", cgu1 + CGU_DIVEX, 0, 8, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU1_S1SELEXDIV] = cgu_divider("cgu1_s1selexdiv", + "cgu1_pllclk", cgu1 + CGU_DIVEX, 16, 8, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU1_S0SEL] = clk_register_mux(NULL, "cgu1_sclk0sel", + cgu1_s0sels, 2, CLK_SET_RATE_PARENT, cgu1 + CGU_CTL, 16, 1, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU1_S1SEL] = clk_register_mux(NULL, "cgu1_sclk1sel", + cgu1_s1sels, 2, CLK_SET_RATE_PARENT, cgu1 + CGU_CTL, 17, 1, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU1_CCLK2] = clk_register_fixed_factor(NULL, + "cclk2_1", "cgu1_vco", CLK_SET_RATE_PARENT, 1, 3); + + clks[ADSP_SC598_CLK_3PLL_DDIV] = clk_register_divider(NULL, "3pll_ddiv", + "3pll_pllclk", CLK_SET_RATE_PARENT, pll3, 12, 5, 0, &cdu_lock); + + // Gates to enable CGU outputs + clks[ADSP_SC598_CLK_CGU0_CCLK0] = cgu_gate("cclk0_0", "cgu0_cdiv", + cgu0 + CGU_CCBF_DIS, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU0_OCLK] = cgu_gate("oclk_0", "cgu0_odiv", + cgu0 + CGU_SCBF_DIS, 3, &cdu_lock); + clks[ADSP_SC598_CLK_CGU0_DCLK] = cgu_gate("dclk_0", "cgu0_ddiv", + cgu0 + CGU_SCBF_DIS, 2, &cdu_lock); + clks[ADSP_SC598_CLK_CGU0_SCLK1] = cgu_gate("sclk1_0", "cgu0_sclk1sel", + cgu0 + CGU_SCBF_DIS, 1, &cdu_lock); + clks[ADSP_SC598_CLK_CGU0_SCLK0] = cgu_gate("sclk0_0", "cgu0_s0seldiv", + cgu0 + CGU_SCBF_DIS, 0, &cdu_lock); + + clks[ADSP_SC598_CLK_CGU1_CCLK0] = cgu_gate("cclk0_1", "cgu1_cdiv", + cgu1 + CGU_CCBF_DIS, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CGU1_OCLK] = cgu_gate("oclk_1", "cgu1_odiv", + cgu1 + CGU_SCBF_DIS, 3, &cdu_lock); + clks[ADSP_SC598_CLK_CGU1_DCLK] = cgu_gate("dclk_1", "cgu1_ddiv", + cgu1 + CGU_SCBF_DIS, 2, &cdu_lock); + clks[ADSP_SC598_CLK_CGU1_SCLK1] = cgu_gate("sclk1_1", "cgu1_sclk1sel", + cgu1 + CGU_SCBF_DIS, 1, &cdu_lock); + clks[ADSP_SC598_CLK_CGU1_SCLK0] = cgu_gate("sclk0_1", "cgu1_sclk0sel", + cgu1 + CGU_SCBF_DIS, 0, &cdu_lock); + + // Extra half rate clocks generated in the CDU + clks[ADSP_SC598_CLK_DCLK0_HALF] = clk_register_fixed_factor(NULL, "dclk_0_half", + "dclk_0", CLK_SET_RATE_PARENT, 1, 2); + clks[ADSP_SC598_CLK_DCLK1_HALF] = clk_register_fixed_factor(NULL, "dclk_1_half", + "dclk_1", CLK_SET_RATE_PARENT, 1, 2); + clks[ADSP_SC598_CLK_CGU1_SCLK1_HALF] = clk_register_fixed_factor(NULL, + "sclk1_1_half", "sclk1_1", CLK_SET_RATE_PARENT, 1, 2); + + // CDU output muxes + clks[ADSP_SC598_CLK_SHARC0_SEL] = cdu_mux("sharc0_sel", cdu + CDU_CFG0, + sharc0_sels, &cdu_lock); + clks[ADSP_SC598_CLK_SHARC1_SEL] = cdu_mux("sharc1_sel", cdu + CDU_CFG1, + sharc1_sels, &cdu_lock); + clks[ADSP_SC598_CLK_ARM_SEL] = cdu_mux("arm_sel", cdu + CDU_CFG2, + arm_sels, &cdu_lock); + clks[ADSP_SC598_CLK_CDU_DDR_SEL] = cdu_mux("cdu_ddr_sel", cdu + CDU_CFG3, + cdu_ddr_sels, &cdu_lock); + clks[ADSP_SC598_CLK_CAN_SEL] = cdu_mux("can_sel", cdu + CDU_CFG4, + can_sels, &cdu_lock); + clks[ADSP_SC598_CLK_SPDIF_SEL] = cdu_mux("spdif_sel", cdu + CDU_CFG5, + spdif_sels, &cdu_lock); + clks[ADSP_SC598_CLK_SPI_SEL] = cdu_mux("spi_sel", cdu + CDU_CFG6, + spi_sels, &cdu_lock); + clks[ADSP_SC598_CLK_GIGE_SEL] = cdu_mux("gige_sel", cdu + CDU_CFG7, + gige_sels, &cdu_lock); + clks[ADSP_SC598_CLK_LP_SEL] = cdu_mux("lp_sel", cdu + CDU_CFG8, lp_sels, + &cdu_lock); + clks[ADSP_SC598_CLK_LP_DDR_SEL] = cdu_mux("lp_ddr_sel", cdu + CDU_CFG9, + lp_ddr_sels, &cdu_lock); + clks[ADSP_SC598_CLK_OSPI_REFCLK_SEL] = cdu_mux("ospi_refclk_sel", + cdu + CDU_CFG10, ospi_refclk_sels, &cdu_lock); + clks[ADSP_SC598_CLK_TRACE_SEL] = cdu_mux("trace_sel", cdu + CDU_CFG12, + trace_sels, &cdu_lock); + clks[ADSP_SC598_CLK_EMMC_SEL] = cdu_mux("emmc_sel", cdu + CDU_CFG13, + emmc_sels, &cdu_lock); + clks[ADSP_SC598_CLK_EMMC_TIMER_QMC_SEL] = cdu_mux("emmc_timer_qmc_sel", + cdu + CDU_CFG14, emmc_timer_sels, &cdu_lock); + + // CDU output enable gates + clks[ADSP_SC598_CLK_SHARC0] = cdu_gate("sharc0", "sharc0_sel", + cdu + CDU_CFG0, CLK_IS_CRITICAL, &cdu_lock); + clks[ADSP_SC598_CLK_SHARC1] = cdu_gate("sharc1", "sharc1_sel", + cdu + CDU_CFG1, CLK_IS_CRITICAL, &cdu_lock); + clks[ADSP_SC598_CLK_ARM] = cdu_gate("arm", "arm_sel", cdu + CDU_CFG2, + CLK_IS_CRITICAL, &cdu_lock); + clks[ADSP_SC598_CLK_CDU_DDR] = cdu_gate("cdu_ddr", "cdu_ddr_sel", + cdu + CDU_CFG3, 0, &cdu_lock); + clks[ADSP_SC598_CLK_CAN] = cdu_gate("can", "can_sel", cdu + CDU_CFG4, 0, + &cdu_lock); + clks[ADSP_SC598_CLK_SPDIF] = cdu_gate("spdif", "spdif_sel", cdu + CDU_CFG5, + 0, &cdu_lock); + clks[ADSP_SC598_CLK_SPI] = cdu_gate("spi", "spi_sel", cdu + CDU_CFG6, 0, + &cdu_lock); + clks[ADSP_SC598_CLK_GIGE] = cdu_gate("gige", "gige_sel", cdu + CDU_CFG7, 0, + &cdu_lock); + clks[ADSP_SC598_CLK_LP] = cdu_gate("lp", "lp_sel", cdu + CDU_CFG8, 0, &cdu_lock); + clks[ADSP_SC598_CLK_LP_DDR] = cdu_gate("lp_ddr", "lp_ddr_sel", + cdu + CDU_CFG9, 0, &cdu_lock); + clks[ADSP_SC598_CLK_OSPI_REFCLK] = cdu_gate("ospi_refclk", "ospi_refclk_sel", + cdu + CDU_CFG10, 0, &cdu_lock); + clks[ADSP_SC598_CLK_TRACE] = cdu_gate("trace", "trace_sel", cdu + CDU_CFG12, + 0, &cdu_lock); + clks[ADSP_SC598_CLK_EMMC] = cdu_gate("emmc", "emmc_sel", cdu + CDU_CFG13, 0, + &cdu_lock); + clks[ADSP_SC598_CLK_EMMC_TIMER_QMC] = cdu_gate("emmc_timer_qmc", + "emmc_timer_qmc_sel", cdu + CDU_CFG14, 0, &cdu_lock); + + // Dedicated DDR output mux + clks[ADSP_SC598_CLK_DDR] = clk_register_mux(NULL, "ddr", ddr_sels, 2, + CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, pll3, 11, 1, 0, &cdu_lock); + + for (i = 0; i < ARRAY_SIZE(clks); i++) { + if (IS_ERR(clks[i])) { + pr_err("Zynq clk %d: register failed with %ld\n", + i, PTR_ERR(clks[i])); + BUG(); + } + } + + clk_data.clks = clks; + clk_data.clk_num = ARRAY_SIZE(clks); + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); +} + +CLK_OF_DECLARE(sc598_clocks, "adi,sc598-clocks", sc598_clock_setup); + +MODULE_AUTHOR("Greg Malysa "); +MODULE_DESCRIPTION("Analog Devices Clock driver"); +MODULE_LICENSE("GPL v2"); \ No newline at end of file From patchwork Thu Sep 12 18:24:53 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802429 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id B0F0FEEE253 for ; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id 9505EC4CEF1; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id 728C1C4CEEB; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165215; bh=XLB5gYmYmYt1/pzwpQI2EzPtJ4lJYhpSRMjF4adIEI0=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=nxyh3iQBMDqitWf0A2v06aU5QKuSIbEwzxnTTimC7D3X1BkWubdsQ4q8jVbEryGbi rUBWqb+TkokzJfPJNkXheYGOrYsEtyo0lg60+lAeo3Qa8TPHq5WCp2YhLe4NLN4YFb bxKtX67dDWamAtMecKA6XNCnyEY69ectATX+f1V6xPH/GwffFNFWEAn988OPKYYL5z 0QYNDJNYF42W5C6f839u//EGx84uoVXGzR9mXPZ5NTMeqql4sptMZR/dej82135fqT kWR1BO97MTgLx2nzSo66CRRKvWH22E+0cvGMdmTnWrUrZacvBRTIvRp9P1mUgl2ZFD 8eBg8TV/VJ/iA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 60B9BEEE249; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:24:53 +0100 Subject: [PATCH 08/21] dt-bindings: clock: adi,sc5xx-clocks: add bindings MIME-Version: 1.0 Message-Id: <20240912-test-v1-8-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=2454; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=FK1wS84c2c1JDb4uWuVca0i/beOgHv9nSZqxSxH0SWg=; b=w9Z7BRtwc4qeUvwgaNEz4dzqKZcH31enCAS4yvArHHPswdjADO8AxrRW0gyDV2QCF3wcyNrPw j4K3L4sgrtNCmK2g91XXJ+PsJqO7i2uu1EE2pvYlXMzGPgxvJ1TDhsJ X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Add ADSP-SC5xx clock bindings. Signed-off-by: Arturs Artamonovs Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- .../bindings/clock/adi,sc5xx-clocks.yaml | 65 ++++++++++++++++++++++ 1 file changed, 65 insertions(+) diff --git a/Documentation/devicetree/bindings/clock/adi,sc5xx-clocks.yaml b/Documentation/devicetree/bindings/clock/adi,sc5xx-clocks.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a092ebdefdcf89a635cdcf1073921efd28a38386 --- /dev/null +++ b/Documentation/devicetree/bindings/clock/adi,sc5xx-clocks.yaml @@ -0,0 +1,65 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/clock/adi,sc5xx-clocks.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Clock Tree Drivers for Analog Devices ADSP-SC5XX Processors + +maintainers: + - Arturs Artamonovs + - Utsav Agarwal + +description: | + These drivers read in the processors CDU (clock distribution unit) + and CGU (clock generation unit) values to determine various clock + rates + +properties: + compatible: + enum: + - adi,sc598-clocks # 64-Bit SC598 processor + + '#clock-cells': + const: 1 + + reg: + minItems: 3 + maxItems: 4 + + clocks: + description: + Specifies the CLKIN0 and CLKIN1 reference clock(s) from which the + output frequencies are derived via CDU+CGU + minItems: 2 + maxItems: 2 + + clock-names: + description: + String reference names for CLKIN0 and CLKIN1 + minItems: 2 + maxItems: 2 + +required: + - compatible + - reg + - clocks + - '#clock-cells' + - clock-names + +additionalProperties: false + +examples: + - | + clk3: clocks@3108d000 { + compatible = "adi,sc598-clocks"; + reg = <0x3108d000 0x1000>, + <0x3108e000 0x1000>, + <0x3108f000 0x1000>, + <0x310a9000 0x1000>; + #clock-cells = <1>; + clocks = <&sys_clkin0>, <&sys_clkin1>; + clock-names = "sys_clkin0", "sys_clkin1"; + status = "okay"; + }; + From patchwork Thu Sep 12 18:24:54 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802431 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C33E2EEE254 for ; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id B71E2C4DDE2; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id 99D4EC4CEF3; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165215; bh=ma0M6+PSeSs6NrF5GY9lsajWNo/5Y0T4538wWHpKmFY=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=jlJl3F6KAOfncNXb89pBFIh+3EXjEBExntUue6uMKDp8+emjnr1DSPP7VSdCqt+k0 noOCGb5bUdwLKHGrMuWGLNwUl2DtxIbiD63npZ6JnZ8CF0F4O4rTIBXON6VvtBJLe0 MrZ2luo43vHbM0TgSvl+pqRW/0NATzTRfII24bnEd5lwpSuDosOWfkL5wuiBR7inV2 OTBO4xOP3PGC4S8yCKsemqPJxtOOXWnVOwtyrh1cXSbMMGlVgEWPgn7IV+pWMPc5cw RQKGGAughbqKp7vh+0A6Df4oNw/563rF/UbOZVV3F9DrYp0NkzbfTujYIccb4t4Xgg 9UhcDt1IPSU9A== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8C639EEE246; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:24:54 +0100 Subject: [PATCH 09/21] gpio: add driver for ADI ADSP-SC5xx platform MIME-Version: 1.0 Message-Id: <20240912-test-v1-9-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=6581; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=sIIGNtLwPRf3aETR4KIKQxLT7TsNXZDYorDVrxz6kPU=; b=CuyIITaHzPiP638ncfNKDHNkpBfqHvmmcTvXrLK2YXfWUbPCGduwTVFTMgybu65hKq1KAP9Zl N73JQEXbShnCT5+hudPmH2qYIJ2d4MFvfvtIe3KNW39sM8vDeUDcuUV X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Add ADSP-SC5xx GPIO driver. - Support all GPIO ports - Each gpio support seperate PINT interrupt controller Signed-off-by: Arturs Artamonovs Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- drivers/gpio/Kconfig | 8 +++ drivers/gpio/Makefile | 1 + drivers/gpio/gpio-adi-adsp-port.c | 145 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 154 insertions(+) diff --git a/drivers/gpio/Kconfig b/drivers/gpio/Kconfig index 58f43bcced7c1f29fad5960771817f500ef67ce1..b02693f5b4cec95a59f19aa1bacf7ed72236865a 100644 --- a/drivers/gpio/Kconfig +++ b/drivers/gpio/Kconfig @@ -147,6 +147,14 @@ config GPIO_74XX_MMIO 8 bits: 74244 (Input), 74273 (Output) 16 bits: 741624 (Input), 7416374 (Output) +config GPIO_ADI_ADSP_PORT + bool "ADI ADSP PORT GPIO driver" + depends on OF_GPIO + select GPIO_GENERIC + help + Say Y to enable the ADSP PORT-based GPIO driver for Analog Devices + ADSP chips. + config GPIO_ALTERA tristate "Altera GPIO" depends on OF_GPIO diff --git a/drivers/gpio/Makefile b/drivers/gpio/Makefile index 64dd6d9d730d5a22564821df71375113e31fe057..fb02c7807a674c8a38d1128e6a25bb7c7f1f4aab 100644 --- a/drivers/gpio/Makefile +++ b/drivers/gpio/Makefile @@ -24,6 +24,7 @@ obj-$(CONFIG_GPIO_104_IDI_48) += gpio-104-idi-48.o obj-$(CONFIG_GPIO_104_IDIO_16) += gpio-104-idio-16.o obj-$(CONFIG_GPIO_74X164) += gpio-74x164.o obj-$(CONFIG_GPIO_74XX_MMIO) += gpio-74xx-mmio.o +obj-$(CONFIG_GPIO_ADI_ADSP_PORT) += gpio-adi-adsp-port.o obj-$(CONFIG_GPIO_ADNP) += gpio-adnp.o obj-$(CONFIG_GPIO_ADP5520) += gpio-adp5520.o obj-$(CONFIG_GPIO_AGGREGATOR) += gpio-aggregator.o diff --git a/drivers/gpio/gpio-adi-adsp-port.c b/drivers/gpio/gpio-adi-adsp-port.c new file mode 100644 index 0000000000000000000000000000000000000000..a7a1867495bbdd121cda9b99991865a035dfa117 --- /dev/null +++ b/drivers/gpio/gpio-adi-adsp-port.c @@ -0,0 +1,145 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ADSP PORT gpio driver + * + * (C) Copyright 2022-2024 - Analog Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include "gpiolib.h" + +static int adsp_gpio_direction_input(struct gpio_chip *chip, unsigned int offset) +{ + struct adsp_gpio_port *port = to_adsp_gpio_port(chip); + + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_DIR_CLEAR); + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_INEN_SET); + return 0; +} + +static int adsp_gpio_direction_output(struct gpio_chip *chip, unsigned int offset, + int value) +{ + struct adsp_gpio_port *port = to_adsp_gpio_port(chip); + + /* + * For open drain ports, they've already been configured by pinctrl and + * we should not modify their output characteristics + */ + if (port->open_drain & BIT(offset)) + return 0; + + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_INEN_CLEAR); + + if (value) + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_DATA_SET); + else + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_DATA_CLEAR); + + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_DIR_SET); + return 0; +} + +static void adsp_gpio_set_value(struct gpio_chip *chip, unsigned int offset, int value) +{ + struct adsp_gpio_port *port = to_adsp_gpio_port(chip); + + /* + * For open drain ports, set as input if driving a 1, set as output + * if driving a 0 + */ + if (port->open_drain & BIT(offset)) { + if (value) { + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_DIR_CLEAR); + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_INEN_SET); + } else { + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_INEN_CLEAR); + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_DATA_CLEAR); + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_DIR_SET); + } + } else { + if (value) + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_DATA_SET); + else + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_DATA_CLEAR); + } +} + +static int adsp_gpio_get_value(struct gpio_chip *chip, unsigned int offset) +{ + struct adsp_gpio_port *port = to_adsp_gpio_port(chip); + + return !!(__adsp_gpio_readw(port, ADSP_PORT_REG_DATA) & BIT(offset)); +} + +static int adsp_gpio_to_irq(struct gpio_chip *chip, unsigned int offset) +{ + struct adsp_gpio_port *port = to_adsp_gpio_port(chip); + irq_hw_number_t irq = offset + port->irq_offset; + int map = irq_find_mapping(port->irq_domain, irq); + + if (map) + return map; + + return irq_create_mapping(port->irq_domain, irq); +} + +static int adsp_gpio_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct adsp_gpio_port *gpio; + int ret; + + gpio = devm_kzalloc(dev, sizeof(*gpio), GFP_KERNEL); + if (!gpio) + return -ENOMEM; + + gpio->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(gpio->regs)) + return PTR_ERR(gpio->regs); + + gpio->dev = dev; + + ret = adsp_attach_pint_to_gpio(gpio); + if (ret) + dev_err_probe(gpio->dev, ret, "error attaching interupt to gpio pin\n"); + + spin_lock_init(&gpio->lock); + + gpio->gpio.label = "adsp-gpio"; + gpio->gpio.direction_input = adsp_gpio_direction_input; + gpio->gpio.direction_output = adsp_gpio_direction_output; + gpio->gpio.get = adsp_gpio_get_value; + gpio->gpio.set = adsp_gpio_set_value; + gpio->gpio.to_irq = adsp_gpio_to_irq; + gpio->gpio.request = gpiochip_generic_request; + gpio->gpio.free = gpiochip_generic_free; + gpio->gpio.ngpio = ADSP_PORT_NGPIO; + gpio->gpio.parent = dev; + gpio->gpio.base = -1; + return devm_gpiochip_add_data(dev, &gpio->gpio, gpio); +} + +static const struct of_device_id adsp_gpio_of_match[] = { + { .compatible = "adi,adsp-port-gpio", }, + { }, +}; +MODULE_DEVICE_TABLE(of, adsp_gpio_of_match); + +static struct platform_driver adsp_gpio_driver = { + .driver = { + .name = "adsp-port-gpio", + .of_match_table = adsp_gpio_of_match, + }, + .probe = adsp_gpio_probe, +}; + +module_platform_driver(adsp_gpio_driver); + +MODULE_AUTHOR("Greg Malysa "); +MODULE_DESCRIPTION("Analog Devices GPIO driver"); +MODULE_LICENSE("GPL v2"); \ No newline at end of file From patchwork Thu Sep 12 18:24:55 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802430 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id DFBC0EEE25B for ; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id C9438C4DDEB; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id AB3FDC4CEF7; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165215; bh=zo8Goznet6ybriL8A1oNytPyx903mkSFkDLvialibwA=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=uMZri+oKwmTs5eBoAMUzB+ve580v9zqiyg9chdR/CRax+PpAdAhFG8bLV+n4AefGk a03JxdrOsPPHvg8M7McvFzOE8YUH0WHTScLQQV4rn6CsSA/EwZNDHkymPI0TnZ+0+n I7OJ5/JZ7ERndhzU5oulxnSguoIc/TZz+cqOHtxwkYRAv3KpRuFuPdrtqc+x12hNAx da7WmOZ/rS7H9LQJkPvqmU8qnuCNz5zrccwuP3osud1gdxFEIW5jrTVee1RNKMb2d8 KNhtRtyoyvAsg08gOpn7xTH4/O2VI7asQreGvZIhQpbDpxvjJdw1U3GRkXuQ79bIo8 3VbA+wSIYy7Hg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id A30B9EEE240; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:24:55 +0100 Subject: [PATCH 10/21] dt-bindings: gpio: adi,adsp-port-gpio: add bindings MIME-Version: 1.0 Message-Id: <20240912-test-v1-10-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=2563; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=cfOfuzOPLZMfuiN15jp5jl3DQDp54rB8wtv1oWhiCQQ=; b=sCywtZ4XrQYa/PO5ZEQL4TN0cv+Zg4tyhTVMbmf3ThpCbmUIkz2SdELt230uY5LEcIXMW/KtL jeBKoWMuk8dAQE3Ql2FcLeK81laxlcnGLBAVzEhv+u8dGAgfPzQM8be X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Add ADSP-SC5xx GPIO driver bindings. Signed-off-by: Arturs Artamonovs Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- .../bindings/gpio/adi,adsp-port-gpio.yaml | 69 ++++++++++++++++++++++ 1 file changed, 69 insertions(+) diff --git a/Documentation/devicetree/bindings/gpio/adi,adsp-port-gpio.yaml b/Documentation/devicetree/bindings/gpio/adi,adsp-port-gpio.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3d7899ce759193296ce787d09d742824277f37f8 --- /dev/null +++ b/Documentation/devicetree/bindings/gpio/adi,adsp-port-gpio.yaml @@ -0,0 +1,69 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/gpio/adi,adsp-port-gpio.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices GPIO Port Driver for SC5XX-family processors + +maintainers: + - Arturs Artamonovs + - Utsav Agarwal + +description: | + Analog Devices GPIO Port Driver for SC5XX-family processors + +properties: + compatible: + enum: + - adi,adsp-port-gpio + + gpio-controller: true + + "#gpio-cells": + const: 2 + + gpio-ranges: + description: Associated pinmux controller and the GPIO range values + + adi,pint: + $ref: /schemas/types.yaml#/definitions/phandle-array + description: Associated pin interrupt controller driver + items: + - items: + - description: phandle to pin interrupt controller driver + - description: interrupt value + + reg: + description: PORT GPIO control registers + +required: + - compatible + - reg + - "#gpio-cells" + - gpio-controller + - gpio-ranges + - adi,pint + +additionalProperties: false + +examples: + - | + gpa: gport@31004000 { + compatible = "adi,adsp-port-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x31004000 0x7F>; + gpio-ranges = <&pinctrl0 0 0 16>; + adi,pint = <&pint0 1>; + }; + + gpb: gport@31004080 { + compatible = "adi,adsp-port-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x31004080 0x7F>; + gpio-ranges = <&pinctrl0 0 16 16>; + adi,pint = <&pint0 0>; + }; +... From patchwork Thu Sep 12 18:24:56 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802437 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 05A9CEEE258 for ; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id D72E1C4AF10; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id BA6E7C32782; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165215; bh=wVb2LXhtvUg6DF3hJthXlyWEU5vK2OELZFVCqaVVgRI=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=j8mHMuSYOT3KXGkGEZfLlOTlBmqcPVgpmPUhppUnVq5UlLobi7NWGDN/d1yH8y2II 656n4eIJyaRPZk/oZMQM0pipEPkXSqm+EFi+b7BppMf0wki79NP4reYLItx8++XYcS 96HtshdV7bIbtoBt3jaIAkYTJiiDgJ9iReLruAzKZiCOO4Wm1mVwuP3EL2JWggDix7 O5cRsP7I7WjaSb8LmXvjEx/hyKK66gcSpOHARMzg5LUwzIh22KsPlPD9m/65ulhEb4 7DEO2VFjonMr5CSUyaOCn8z+oAf5Tdpn8jOVgQFrulgD39kAGz5w0pEk6S8WipvtJA CZIHTNiDKu/zg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id B2FA7EEE258; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:24:56 +0100 Subject: [PATCH 11/21] irqchip: Add irqchip for ADI ADSP-SC5xx platform MIME-Version: 1.0 Message-Id: <20240912-test-v1-11-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=10414; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=kfES6vjl8NkFU8R7RYQVCofDuP57K6JhH4VbJu5VdjU=; b=GZAR3QoQnY/atWwNsrGN30hsZ3O6rcojIz2qEwsg1/6LiolmjTGdLKJ2tumZqv0eTZ0XfMGri j/MKGX10ejkCylAEIgL27zdVsR3W273JUnxIVmTLSJPeqMoJJdgK8l/ X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Support seting extra indepdendent interrupt on pin activity. Signed-off-by: Arturs Artamonovs Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- drivers/irqchip/Kconfig | 9 ++ drivers/irqchip/Makefile | 2 + drivers/irqchip/irq-adi-adsp.c | 310 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 321 insertions(+) diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig index d078bdc48c38f13af9a129974f3b637dfee0e40f..1bc8f1bd45b3d2f69d2d0e6c8fa01b17b12ce241 100644 --- a/drivers/irqchip/Kconfig +++ b/drivers/irqchip/Kconfig @@ -91,6 +91,15 @@ config ALPINE_MSI select PCI_MSI select GENERIC_IRQ_CHIP +config ADI_ADSP_IRQ + bool "ADI PORT PINT Driver" + depends on OF + depends on (ARCH_SC59X_64 || ARCH_SC59X) + select IRQ_DOMAIN + help + Say Y to enable the PORT-based PINT interrupt controller for + Analog Devices ADSP devices. + config AL_FIC bool "Amazon's Annapurna Labs Fabric Interrupt Controller" depends on OF diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile index 15635812b2d6605a2dd3bb0e5fb3170ab2cb0f77..258a188676fd97e713f3cebe16e3d563add095f3 100644 --- a/drivers/irqchip/Makefile +++ b/drivers/irqchip/Makefile @@ -1,6 +1,8 @@ # SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_IRQCHIP) += irqchip.o + +obj-$(CONFIG_ADI_ADSP_IRQ) += irq-adi-adsp.o obj-$(CONFIG_AL_FIC) += irq-al-fic.o obj-$(CONFIG_ALPINE_MSI) += irq-alpine-msi.o obj-$(CONFIG_ATH79) += irq-ath79-cpu.o diff --git a/drivers/irqchip/irq-adi-adsp.c b/drivers/irqchip/irq-adi-adsp.c new file mode 100644 index 0000000000000000000000000000000000000000..75e10575ca80216b8baf5cb8daf1f62efae5f23b --- /dev/null +++ b/drivers/irqchip/irq-adi-adsp.c @@ -0,0 +1,310 @@ +// SPDX-License-Identifier: GPL-2.0 +/** + * ADSP PINT PORT driver. + * + * The default mapping is used for all PINTs, refer to the HRM to identify + * PORT mapping to PINTs. For example, PINT0 has PORT B (0-15) and PORT A + * (16-31). + * + * Copyright (C) 2022-2024, Analog Devices, Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define ADSP_PINT_IRQS 32 + +/* Register offsets in a single PINT */ +#define ADSP_PINT_REG_MASK_SET 0x00 +#define ADSP_PINT_REG_MASK_CLEAR 0x04 +#define ADSP_PINT_REG_REQUEST 0x08 +#define ADSP_PINT_REG_ASSIGN 0x0c +#define ADSP_PINT_REG_EDGE_SET 0x10 +#define ADSP_PINT_REG_EDGE_CLEAR 0x14 +#define ADSP_PINT_REG_INVERT_SET 0x18 +#define ADSP_PINT_REG_INVERT_CLEAR 0x1c +#define ADSP_PINT_REG_PINSTATE 0x20 +#define ADSP_PINT_REG_LATCH 0x24 + +struct adsp_pint { + struct irq_chip chip; + void __iomem *regs; + struct irq_domain *domain; + unsigned int irq; +}; + +static struct adsp_pint *to_adsp_pint(struct irq_chip *chip) +{ + return container_of(chip, struct adsp_pint, chip); +} + +/** + * Each gpio device should be connected to one of the two valid pints with an + * indicator of which half it is connected to: + * + * pint0 { + * ... + * }; + * gpa { + * adi,pint = <&pint0 1>; + * }; + * gpb { + * adi,pint = <&pint0 0>; + * }; + * + * This relies on the default configuration of the hardware, which we do not + * expose an interface to change. + */ +int adsp_attach_pint_to_gpio(struct adsp_gpio_port *port) +{ + struct platform_device *pint_pdev; + struct device_node *pint_node; + struct adsp_pint *pint; + struct of_phandle_args args; + int ret; + + ret = of_parse_phandle_with_fixed_args(port->dev->of_node, "adi,pint", 1, 0, + &args); + if (ret) { + dev_err(port->dev, "Missing or invalid adi,pint connection for %pOFn; " + "attach a pint instance with one argument for port assignment\n", + port->dev->of_node); + return ret; + } + + pint_node = args.np; + + pint_pdev = of_find_device_by_node(pint_node); + if (!pint_pdev) { + ret = -EPROBE_DEFER; + goto cleanup; + } + + pint = dev_get_drvdata(&pint_pdev->dev); + if (!pint) { + ret = -EPROBE_DEFER; + goto cleanup; + } + + port->irq_domain = pint->domain; + + if (args.args[0]) + port->irq_offset = 16; + else + port->irq_offset = 0; + +cleanup: + of_node_put(pint_node); + return ret; +} + +static void adsp_pint_dispatch_irq(struct irq_desc *desc) +{ + struct irq_chip *chip = irq_desc_get_chip(desc); + struct adsp_pint *pint = to_adsp_pint(chip); + unsigned int type = irqd_get_trigger_type(&desc->irq_data); + u32 pos = BIT(desc->irq_data.hwirq); + + /* for both edge interrupt, toggle invert bit to catch next edge */ + if (type == IRQ_TYPE_EDGE_BOTH) { + u32 invert = readl(pint->regs + ADSP_PINT_REG_INVERT_SET) & pos; + + if (invert) + writel(pos, pint->regs + ADSP_PINT_REG_INVERT_CLEAR); + else + writel(pos, pint->regs + ADSP_PINT_REG_INVERT_SET); + } + + writel(pos, pint->regs + ADSP_PINT_REG_REQUEST); + + /* either edge is set */ + if (type & IRQ_TYPE_EDGE_BOTH) + handle_edge_irq(desc); + else + handle_level_irq(desc); +} + +static int adsp_pint_irq_map(struct irq_domain *domain, unsigned int irq, + irq_hw_number_t hwirq) +{ + struct adsp_pint *pint = domain->host_data; + + irq_set_chip_data(irq, pint); + irq_set_chip_and_handler(irq, &pint->chip, adsp_pint_dispatch_irq); + return 0; +} + +static const struct irq_domain_ops adsp_irq_domain_ops = { + .map = adsp_pint_irq_map, + .xlate = irq_domain_xlate_onecell, +}; + +/** + * This handles the GIC interrupt associated with this PINT being activated. + * It chains the interrupt associated with a particular pin + */ +static void adsp_pint_irq_handler(struct irq_desc *desc) +{ + struct adsp_pint *pint = irq_desc_get_handler_data(desc); + struct irq_chip *chip = irq_desc_get_chip(desc); + unsigned long req; + int pos; + + chained_irq_enter(chip, desc); + + req = readl(pint->regs + ADSP_PINT_REG_REQUEST); + + for_each_set_bit(pos, &req, 32) { + unsigned int virq = irq_find_mapping(pint->domain, pos); + + if (virq) + generic_handle_irq(virq); + } + + chained_irq_exit(chip, desc); +} + +static void adsp_pint_irq_ack(struct irq_data *d) +{ + /* this is required for edge type irqs unconditionally */ +} + +static void adsp_pint_irq_mask(struct irq_data *d) +{ + struct adsp_pint *pint = irq_data_get_irq_chip_data(d); + + writel(BIT(d->hwirq), pint->regs + ADSP_PINT_REG_MASK_CLEAR); +} + +static void adsp_pint_irq_unmask(struct irq_data *d) +{ + struct adsp_pint *pint = irq_data_get_irq_chip_data(d); + + writel(BIT(d->hwirq), pint->regs + ADSP_PINT_REG_MASK_SET); +} + +static int adsp_pint_irq_set_type(struct irq_data *d, unsigned int type) +{ + struct adsp_pint *pint = irq_data_get_irq_chip_data(d); + unsigned int pos = BIT(d->hwirq); + + switch (type) { + case IRQ_TYPE_PROBE: + type = IRQ_TYPE_EDGE_BOTH; + fallthrough; + case IRQ_TYPE_EDGE_BOTH: + /* start by looking for rising edge */ + writel(pos, pint->regs + ADSP_PINT_REG_INVERT_CLEAR); + writel(pos, pint->regs + ADSP_PINT_REG_EDGE_SET); + return 0; + + case IRQ_TYPE_EDGE_FALLING: + writel(pos, pint->regs + ADSP_PINT_REG_INVERT_SET); + writel(pos, pint->regs + ADSP_PINT_REG_EDGE_SET); + return 0; + + case IRQ_TYPE_EDGE_RISING: + writel(pos, pint->regs + ADSP_PINT_REG_INVERT_CLEAR); + writel(pos, pint->regs + ADSP_PINT_REG_EDGE_SET); + return 0; + + case IRQ_TYPE_LEVEL_HIGH: + writel(pos, pint->regs + ADSP_PINT_REG_INVERT_CLEAR); + writel(pos, pint->regs + ADSP_PINT_REG_EDGE_CLEAR); + return 0; + + case IRQ_TYPE_LEVEL_LOW: + writel(pos, pint->regs + ADSP_PINT_REG_INVERT_SET); + writel(pos, pint->regs + ADSP_PINT_REG_EDGE_CLEAR); + return 0; + + default: + return -EINVAL; + } + +} + +static int adsp_pint_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct adsp_pint *pint; + + pint = devm_kzalloc(dev, sizeof(*pint), GFP_KERNEL); + if (!pint) + return -ENOMEM; + + pint->regs = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(pint->regs)) + return PTR_ERR(pint->regs); + + pint->chip.name = "adsp-pint"; + pint->chip.irq_ack = adsp_pint_irq_ack; + pint->chip.irq_mask = adsp_pint_irq_mask; + pint->chip.irq_unmask = adsp_pint_irq_unmask; + pint->chip.irq_set_type = adsp_pint_irq_set_type; + // @todo potentially only SEC supports wake options, not gic + + // @todo determine if we actually need a raw spinlock + + pint->domain = irq_domain_add_linear(np, ADSP_PINT_IRQS, + &adsp_irq_domain_ops, pint); + if (!pint->domain) { + dev_err(dev, "Could not create irq domain\n"); + return -EINVAL; + } + + pint->irq = platform_get_irq(pdev, 0); + if (!pint->irq) { + dev_err(dev, "Could not find parent interrupt for port\n"); + return -EINVAL; + } + + irq_set_chained_handler_and_data(pint->irq, adsp_pint_irq_handler, pint); + platform_set_drvdata(pdev, pint); + + return 0; +} + +static void adsp_pint_remove(struct platform_device *pdev) +{ + struct adsp_pint *pint = platform_get_drvdata(pdev); + + irq_set_chained_handler_and_data(pint->irq, NULL, NULL); + irq_domain_remove(pint->domain); +} + +static const struct of_device_id adsp_pint_of_match[] = { + { .compatible = "adi,adsp-pint" }, + { } +}; +MODULE_DEVICE_TABLE(of, adsp_pint_of_match); + +static struct platform_driver adsp_pint_driver = { + .driver = { + .name = "adsp-port-pint", + .of_match_table = adsp_pint_of_match, + }, + .probe = adsp_pint_probe, + .remove = adsp_pint_remove, +}; + +static int __init adsp_pint_init(void) +{ + return platform_driver_register(&adsp_pint_driver); +} + +arch_initcall(adsp_pint_init); + +MODULE_DESCRIPTION("Analog Devices IRQChip driver"); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR("Greg Malysa "); \ No newline at end of file From patchwork Thu Sep 12 18:24:57 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802432 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 0C1B5EEE261 for ; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id EF4FBC4DDFF; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id D2BBAC4DDEC; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165215; bh=xc1lcmQyKnVJeXtN66l/4Vl3EAntmlIX7k9RsQ6PtVM=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=KOWLQ65kuaEmRmfLrM9+bOzLuSuu37845a8u7Y3Li24eY808rv/KMElP5ssgaK6RD htaDdGikLm/hrJK23yuSkvCvDv8KFwipc8vokpcoF3TZtRlSWaTlIhscm5IZtQwhy2 wuV+Z74ruCYqPrpm/Y6N2X6vv3D2pkCv2qlp7kkU/8GM0vI2Ib4v5nqP91SXKTz+jL xSWOqZzai+qNPcBh5qDsxBwvgecjgaKo9XggQcv9bNix03Y2mZ6LoYd/C1MXstoNoL OaKXDowdFENzGmN5jW8YE9RzHHRZ5BcMYqXDCRLLE21a95Zthl0kBKd+iGN2a7bkmk wY6SJXyCybOkA== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id C7BDEEEE25C; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:24:57 +0100 Subject: [PATCH 12/21] dt-bindings: irqchip: adi,adsp-pint: add binding MIME-Version: 1.0 Message-Id: <20240912-test-v1-12-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=2105; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=yHl99Y8TQ8P5xVbR7jYO25v3GpFZA0Gk4gbAg09z/m8=; b=S/iXG0SAWPve55YA1NYgR6TtW3/vsk79y+hhbkQT4ASvfW8R3SxBPGVZaHLMhi2HbC5h6WHdI pSMyLq0La/wADQ21ECoDMhIf5J0qLhEtLm5UIu+6LZ+u+JQ6QKEswok X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Signed-off-by: Arturs Artamonovs Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- .../interrupt-controller/adi,adsp-pint.yaml | 51 ++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/Documentation/devicetree/bindings/interrupt-controller/adi,adsp-pint.yaml b/Documentation/devicetree/bindings/interrupt-controller/adi,adsp-pint.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b5ecf0cf1d2ceb580f45467ffe1550ae3280d1a3 --- /dev/null +++ b/Documentation/devicetree/bindings/interrupt-controller/adi,adsp-pint.yaml @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/interrupt-controller/adi,adsp-pint.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices Port Pin Interrupt for SC5XX-family processors + +maintainers: + - Arturs Artamonovs + - Utsav Agarwal + +description: | + Analog Devices Port Pin Interrupt driver for SC5XX-family processors + +properties: + compatible: + enum: + - adi,adsp-pint + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + +required: + - compatible + - reg + - interrupts + +additionalProperties: false + +examples: + - | + #include + #include + #include + + pint0: pint@31005000 { + compatible = "adi,adsp-pint"; + reg = <0x31005000 0xFF>; + interrupts = ; + }; + + pint1: pint@31005100 { + compatible = "adi,adsp-pint"; + reg = <0x31005100 0xFF>; + interrupts = ; + }; +... From patchwork Thu Sep 12 18:24:58 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802441 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 76C3EEEE25F for ; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id 2AD1BC4E671; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id F1D39C4DE09; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165216; bh=8dglV35vXsS56WaqjDfOErmL3gBQcYZfYc41JKx0CZY=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=a/FMMgWZnAfOevYv8VZ5xuo6wb7rOnkmAgiyborp47SLyRN4TjrZjBkTTxa6QD2m/ X6W8xJP9qpHTqMZ1RQzNiPEzffOELQ7spZ0OhvjO6IsCLcBRUlRNqgOVU7rxGiRxii Hv9vmdKcQmdpXz8c2lDkbHkzGMDki3MQG1yVmx2zuoAEAsH3b3Azs0Y/Pq9eF/j0nR 4GheDbvPtIqy1MNqikzfNaTkzHLqGNrCwYh29ePKWkmxWA/9DlSYrv4JjH0JJg4MoL vRSqbdQzngPrm1hJukVPX5GhDWpsNfn5MlbRmcn9gpHn/La4JRluNKph2Xo1I+p7N8 CwBYp/U26rZ9w== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id E54AEEEE25E; Thu, 12 Sep 2024 18:20:15 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:24:58 +0100 Subject: [PATCH 13/21] pinctrl: Add drivers for ADI ADSP-SC5xx platform MIME-Version: 1.0 Message-Id: <20240912-test-v1-13-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=29319; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=GfxjQyaWdYihVTbmYZ8dKtXQxxhTt6kZCTW4eIPAJo8=; b=zU6rjIlKSsjPtuH6NdYWdBwgPpnIdUtfa9gVkK3cZ7u4PLhzAukEglamykqFZw7ApY9Cfx3+2 It5Yp2iMV2rAd9LiruUBX0WregtYH77bbVy5fdt8vbuKDYe0U/ufjg6 X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Add ADSP-SC5xx pinctrler: - Support switching GPIO pin functions. Signed-off-by: Arturs Artamonovs Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- drivers/pinctrl/Kconfig | 12 + drivers/pinctrl/Makefile | 1 + drivers/pinctrl/pinctrl-adsp.c | 919 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 932 insertions(+) diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig index 7e4f93a3bc7ac9bcafc92ddb795569d7cca6474d..ffc0946c5b416c29803e195016867aee8f09afe1 100644 --- a/drivers/pinctrl/Kconfig +++ b/drivers/pinctrl/Kconfig @@ -31,6 +31,18 @@ config DEBUG_PINCTRL help Say Y here to add some extra checks and diagnostics to PINCTRL calls. +config PINCTRL_ADSP + bool "ADSP-SC5XX pinctrl driver" + depends on ARCH_SC59X_64 + depends on OF + select PINMUX + select GPIOLIB + select GENERIC_PINCONF + help + Say Y here to enable the ADSP-SC5XX pinctrl driver. This is required for + correct peripheral functionality on the SoC. + + config PINCTRL_AMD bool "AMD GPIO pin control" depends on HAS_IOMEM diff --git a/drivers/pinctrl/Makefile b/drivers/pinctrl/Makefile index cc809669405ab6c6905fe0b2380f91b211a2d470..6b340bf0ee8c0267cbbdee3d14db605a340433c6 100644 --- a/drivers/pinctrl/Makefile +++ b/drivers/pinctrl/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_PINCONF) += pinconf.o obj-$(CONFIG_GENERIC_PINCONF) += pinconf-generic.o obj-$(CONFIG_OF) += devicetree.o +obj-$(CONFIG_PINCTRL_ADSP) += pinctrl-adsp.o obj-$(CONFIG_PINCTRL_AMD) += pinctrl-amd.o obj-$(CONFIG_PINCTRL_APPLE_GPIO) += pinctrl-apple-gpio.o obj-$(CONFIG_PINCTRL_ARTPEC6) += pinctrl-artpec6.o diff --git a/drivers/pinctrl/pinctrl-adsp.c b/drivers/pinctrl/pinctrl-adsp.c new file mode 100644 index 0000000000000000000000000000000000000000..ce86e579e5601203a446c09b5b5f7f60aba6d02a --- /dev/null +++ b/drivers/pinctrl/pinctrl-adsp.c @@ -0,0 +1,919 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Analog Devices ADSP family pinctrl driver. + * + * Copyright 2022-2024 - Analog Devices Inc. + */ + +#include +#include +#include +#include +#include +#include + +#include "core.h" +#include "pinconf.h" +#include "pinctrl-utils.h" + +/* Convert from pinmux constants in device tree to actual settings */ +#define ADSP_PINMUX_PIN(p) ((p & 0xffffff00) >> 8) +#define ADSP_PINMUX_FUNC(p) (p & 0xff) + +/* Details of the PORT_MUX register */ +#define ADSP_PORT_PORT_MUX_BITS 2 +#define ADSP_PORT_PORT_MUX_MASK GENMASK(1, 0) + +/* Number of pin alternate functions, see pin_functions array */ +#define ADSP_NUMBER_OF_PIN_FUNCTIONS ARRAY_SIZE(pin_functions) + +/* Information for drive strength registers */ +#define ADSP_PADS_DS_BITS 3 +#define ADSP_PADS_DS_PINS_PER_REG 8 +#define ADSP_PADS_DS_HIGH 2 +#define ADSP_PADS_DS_LOW 1 + +/* Information for pull up/pull down enable registers */ +#define ADSP_PADS_PUD_PINS_PER_REG 16 + +#define ADSP_PADS_REG_PCFG0 0x04 +#define ADSP_PADS_REG_PCFG1 0x08 +/* Convert from pin number (e.g. 0-143) to drive strength register offset */ +#define ADSP_PADS_PORTx_DS(p) (0x0c + 0x04*(p/ADSP_PADS_DS_PINS_PER_REG)) +#define ADSP_PADS_NONPORTS_DS 0x50 +/* Convert from pin number to pull up enable register offset */ +#define ADSP_PADS_PORTx_PUE(p) (0x98 + 0x04*(p/ADSP_PADS_PUD_PINS_PER_REG)) +/* Convert from pin number to pull down enable register offset */ +#define ADSP_PADS_PORTx_PDE(p) (0xc4 + 0x04*(p/ADSP_PADS_PUD_PINS_PER_REG)) + +/* Non GPIO PORT drive strength settings */ +#define ADSP_NONPORTS_DS_CKOUT 0 +#define ADSP_NONPORTS_DS_RESOUTB 1 +#define ADSP_NONPORTS_DS_FAULTB 2 +#define ADSP_NONPORTS_DS_LP1CK 3 +#define ADSP_NONPORTS_DS_LP0CK 4 +#define ADSP_NONPORTS_DS_OSPI 5 + +/* DAI pad configuration offsets */ +#define ADSP_PADS_REG_DAI0_0_DS 0x78 +#define ADSP_PADS_REG_DAI0_1_DS 0x7c +#define ADSP_PADS_REG_DAI1_0_DS 0x80 +#define ADSP_PADS_REG_DAI1_1_DS 0x84 + +#define ADSP_PADS_REG_DAI0_PUE 0xbc +#define ADSP_PADS_REG_DAI1_PUE 0xc0 +#define ADSP_PADS_REG_DAI0_PDE 0xfc +#define ADSP_PADS_REG_DAI1_PDE 0x100 + +/* + * Represents a function setting for pins, controls the mux modes essentially + */ +struct adsp_pin_function { + const char *name; + /* 0 for gpio, 1-4 for alt functions 0-3 */ + uint8_t mode; +}; + +/* + * Available pin function settings in the pin mux for GPIO-associated pins + */ +static const struct adsp_pin_function pin_functions[] = { + { + .name = "gpio", + .mode = 0, + }, { + .name = "alt0", + .mode = 1, + }, { + .name = "alt1", + .mode = 2, + }, { + .name = "alt2", + .mode = 3, + }, { + .name = "alt3", + .mode = 4, + } +}; + +/* + * One pinctrl instance per chip, unifies the interface to the port mux and pad + * conf registers in the PORT instances + * @todo pads registers should be routed through system configuration abstraction + * to remove the need for feature testing/listing "missing" registers here + */ +struct adsp_pinctrl { + struct device *dev; + struct pinctrl_dev *pin_dev; + void __iomem *regs; + const char **group_names; + unsigned int *pins; + spinlock_t lock; + size_t num_ports; + uint32_t *pin_counts; + uint32_t total_pins; + + /* Are the drive strength registers missing on this part? */ + bool ds_missing; + + /* Are the pull up/down enable registers missing on this part? */ + bool pude_missing; +}; + +/* + * Custom pinconf properties + */ +#define ADSP_PIN_CONFIG_TRU_TOGGLE (PIN_CONFIG_END+1) + +static const struct pinconf_generic_params adsp_custom_bindings[] = { + /* Configure this pin as a toggle pin which flip each time a trigger event + * is received by the pin controller from the TRU + */ + {"adi,tru-toggle", ADSP_PIN_CONFIG_TRU_TOGGLE, 0} +}; + +static const struct pin_config_item adsp_conf_items[] = { + PCONFDUMP(ADSP_PIN_CONFIG_TRU_TOGGLE, "tru-toggle", NULL, false), +}; + +/* does not need lock */ +static void adsp_set_pin_gpio(struct adsp_gpio_port *port, unsigned int offset, bool gpio) +{ + if (gpio) + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_FER_CLEAR); + else + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_FER_SET); +} + +/* + * Configure a pin either for gpio or an alternate function + */ +static void adsp_portmux_setup(struct adsp_gpio_port *port, unsigned int offset, + const struct adsp_pin_function *func) +{ + if (func->mode == 0) { + adsp_set_pin_gpio(port, offset, true); + } else { + unsigned long flags; + u32 val; + u32 f = (func->mode - 1) & ADSP_PORT_PORT_MUX_MASK; + + spin_lock_irqsave(&port->lock, flags); + + val = __adsp_gpio_readl(port, ADSP_PORT_REG_PORT_MUX); + val &= ~(ADSP_PORT_PORT_MUX_MASK << (ADSP_PORT_PORT_MUX_BITS * offset)); + val |= f << (ADSP_PORT_PORT_MUX_BITS * offset); + __adsp_gpio_writel(port, val, ADSP_PORT_REG_PORT_MUX); + + spin_unlock_irqrestore(&port->lock, flags); + + adsp_set_pin_gpio(port, offset, false); + } +} + +/* pin control operations */ +static int adsp_pinctrl_get_groups_count(struct pinctrl_dev *pctldev) +{ + struct adsp_pinctrl *adsp_pinctrl = pinctrl_dev_get_drvdata(pctldev); + + return adsp_pinctrl->total_pins; +} + +static const char *adsp_pinctrl_get_group_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + struct adsp_pinctrl *adsp_pinctrl = pinctrl_dev_get_drvdata(pctldev); + + return adsp_pinctrl->group_names[selector]; +} + +static int adsp_pinctrl_get_group_pins(struct pinctrl_dev *pctldev, unsigned int selector, + const unsigned int **pins, unsigned int *num_pins) +{ + struct adsp_pinctrl *adsp_pinctrl = pinctrl_dev_get_drvdata(pctldev); + *pins = &adsp_pinctrl->pins[selector]; + *num_pins = 1; + return 0; +} + +static int adsp_pinctrl_dt_subnode_to_map(struct pinctrl_dev *pctldev, + struct device_node *np, struct pinctrl_map **map, unsigned int *reserved_maps, + unsigned int *num_maps) +{ + struct adsp_pinctrl *adsp_pinctrl = pinctrl_dev_get_drvdata(pctldev); + //struct property *prop; + const char *group; + unsigned long *configs; + unsigned int num_configs, num_pins; + unsigned int reserve = 0; + //uint32_t pinmux; + //const __be32 *p; + u32 array[2]; + int sz, i; + int ret; + + num_pins = of_property_count_u32_elems(np, "pinmux"); + if (num_pins <= 0) { + dev_err(adsp_pinctrl->dev, "Must have at least one `pinmux` entry in %pOFn.\n", + np); + return -EINVAL; + } + + ret = pinconf_generic_parse_dt_config(np, pctldev, &configs, &num_configs); + if (ret) + return ret; + + /* One configuration for the whole group, potentially */ + reserve = num_pins; + if (num_configs) + reserve = reserve * 2; + + ret = pinctrl_utils_reserve_map(pctldev, map, reserved_maps, num_maps, reserve); + if (ret) + goto exit; + + sz = of_property_read_variable_u32_array(np, "pinmux", array, 2, 2); + sz = (sz == -EINVAL) ? 0 : sz; /* Missing property is OK */ + if (sz < 0) + return dev_err_probe(adsp_pinctrl->dev, sz, "invalid pinmux\n"); + + + for (i = 0; i < sz; i += 2) { + u32 pin = array[i]; + u32 func = array[i + 1]; + + if (func >= ADSP_NUMBER_OF_PIN_FUNCTIONS) { + dev_err(adsp_pinctrl->dev, + "Function number %d is not available for pin %d in %pOFn.n\n", + func, pin, np); + goto exit; + } + + group = adsp_pinctrl->group_names[pin]; + ret = pinctrl_utils_add_map_mux(pctldev, map, reserved_maps, num_maps, + group, pin_functions[func].name); + if (ret) + goto exit; + + if (num_configs) { + ret = pinctrl_utils_add_map_configs(pctldev, map, reserved_maps, num_maps, + group, configs, num_configs, PIN_MAP_TYPE_CONFIGS_GROUP); + if (ret) + goto exit; + } + } + + ret = 0; +exit: + kfree(configs); + return ret; +} + +/** + * Handle device tree structures like: + * + * pinctrl_uart0_hwflow: uart0_hwflow_pins { + * pins_rxtx_ { + * pinmux = <1>, <2>; + * some-padconf-flag; + * }; + * pins_hwflow { + * pinmux = <3>, <4>; + * some-other-padconf-flag; + * }; + * }; + * + * where &pinctrl_uart0_hwflow is passed as an entry in pinctrl-0 on uart driver and + * enables all sub-pins at once + */ +static int adsp_pinctrl_dt_node_to_map(struct pinctrl_dev *pctldev, + struct device_node *np, struct pinctrl_map **map, unsigned int *num_maps) +{ + unsigned int reserved_maps; + struct device_node *child_np; + int ret; + + reserved_maps = 0; + *map = NULL; + *num_maps = 0; + + for_each_child_of_node(np, child_np) { + ret = adsp_pinctrl_dt_subnode_to_map(pctldev, child_np, map, + &reserved_maps, num_maps); + if (ret < 0) + goto exit; + } + return 0; + +exit: + pinctrl_utils_free_map(pctldev, *map, *num_maps); + return ret; +} + +static const struct pinctrl_ops adsp_pctlops = { + .get_groups_count = adsp_pinctrl_get_groups_count, + .get_group_name = adsp_pinctrl_get_group_name, + .get_group_pins = adsp_pinctrl_get_group_pins, + .dt_node_to_map = adsp_pinctrl_dt_node_to_map, + .dt_free_map = pinconf_generic_dt_free_map, +}; + +/* pin mux operations */ +static int adsp_pinmux_get_functions_count(struct pinctrl_dev *pctldev) +{ + return ADSP_NUMBER_OF_PIN_FUNCTIONS; +} + +static const char *adsp_pinmux_get_function_name(struct pinctrl_dev *pctldev, + unsigned int selector) +{ + return pin_functions[selector].name; +} + +static int adsp_pinmux_get_function_groups(struct pinctrl_dev *pctldev, + unsigned int selector, const char * const **groups, unsigned * const num_groups) +{ + struct adsp_pinctrl *adsp_pinctrl = pinctrl_dev_get_drvdata(pctldev); + + *groups = adsp_pinctrl->group_names; + *num_groups = adsp_pinctrl->total_pins; + return 0; +} + +/* Each group is exactly 1 pin and group id == pin id */ +static int adsp_pinmux_set_mux(struct pinctrl_dev *pctldev, unsigned int func, + unsigned int group) +{ + struct adsp_gpio_port *port; + struct pinctrl_gpio_range *range; + u32 offset; + + range = pinctrl_find_gpio_range_from_pin(pctldev, group); + if (!range || !range->gc) + return -EPROBE_DEFER; + + offset = group - range->pin_base; + + port = to_adsp_gpio_port(range->gc); + adsp_portmux_setup(port, offset, &pin_functions[func]); + + return 0; +} + +static int adsp_pinmux_request_gpio(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, unsigned int pin) +{ + struct adsp_gpio_port *port = to_adsp_gpio_port(range->gc); + u32 offset = pin - range->pin_base; + + adsp_set_pin_gpio(port, offset, true); + return 0; +} + +static void adsp_pinmux_release_gpio(struct pinctrl_dev *pctldev, + struct pinctrl_gpio_range *range, unsigned int pin) +{ + struct adsp_gpio_port *port = to_adsp_gpio_port(range->gc); + u32 offset = pin - range->pin_base; + + adsp_set_pin_gpio(port, offset, false); +} + +static const struct pinmux_ops adsp_pmxops = { + .get_functions_count = adsp_pinmux_get_functions_count, + .get_function_name = adsp_pinmux_get_function_name, + .get_function_groups = adsp_pinmux_get_function_groups, + .set_mux = adsp_pinmux_set_mux, + .gpio_request_enable = adsp_pinmux_request_gpio, + .gpio_disable_free = adsp_pinmux_release_gpio, +}; + +/* pin configuration operations */ +static bool __adsp_pinconf_is_pue(struct adsp_pinctrl *p, unsigned int pin) +{ + u32 offset = ADSP_PADS_PORTx_PUE(pin); + u32 val, bit; + + if (p->pude_missing) + return 0; + + val = readl(p->regs + offset); + bit = BIT(pin & (ADSP_PADS_PUD_PINS_PER_REG-1)); + return !!(val & bit); +} + +static bool __adsp_pinconf_is_pde(struct adsp_pinctrl *p, unsigned int pin) +{ + u32 offset = ADSP_PADS_PORTx_PDE(pin); + u32 val, bit; + + if (p->pude_missing) + return 0; + + val = readl(p->regs + offset); + bit = BIT(pin & (ADSP_PADS_PUD_PINS_PER_REG-1)); + return !!(val & bit); +} + +static u32 __adsp_pinconf_get_ds(struct adsp_pinctrl *p, unsigned int pin) +{ + u32 offset = ADSP_PADS_PORTx_DS(pin); + u32 val, shift, mask; + + if (p->ds_missing) + return 0; + + val = readl(p->regs + offset); + shift = (pin & (ADSP_PADS_DS_PINS_PER_REG-1)) * ADSP_PADS_DS_BITS; + mask = GENMASK(ADSP_PADS_DS_BITS-1, 0) << shift; + val = val & mask; + + if (val == ADSP_PADS_DS_HIGH) + return 1; + return 0; +} + +/* seems we return -EINVAL for disabled static option, -ENOTSUPP for not supported, + * and otherwise the argument is included in config + */ +static int adsp_pinconf_get(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *config) +{ + struct adsp_pinctrl *adsp_pinctrl = pinctrl_dev_get_drvdata(pctldev); + struct pinctrl_gpio_range *range; + struct adsp_gpio_port *port; + u32 offset, val; + u32 param = pinconf_to_config_param(*config); + u32 arg = 0; + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + if (__adsp_pinconf_is_pue(adsp_pinctrl, pin) || + __adsp_pinconf_is_pde(adsp_pinctrl, pin)) + return -EINVAL; + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + if (!__adsp_pinconf_is_pde(adsp_pinctrl, pin)) + return -EINVAL; + break; + case PIN_CONFIG_BIAS_PULL_UP: + if (!__adsp_pinconf_is_pue(adsp_pinctrl, pin)) + return -EINVAL; + break; + case PIN_CONFIG_DRIVE_STRENGTH: + arg = __adsp_pinconf_get_ds(adsp_pinctrl, pin); + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin); + offset = pin - range->pin_base; + port = to_adsp_gpio_port(range->gc); + + if (!(port->open_drain & BIT(offset))) + return -EINVAL; + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin); + offset = pin - range->pin_base; + port = to_adsp_gpio_port(range->gc); + + if (port->open_drain & BIT(offset)) + return -EINVAL; + break; + case ADSP_PIN_CONFIG_TRU_TOGGLE: + range = pinctrl_find_gpio_range_from_pin_nolock(pctldev, pin); + offset = pin - range->pin_base; + port = to_adsp_gpio_port(range->gc); + + val = __adsp_gpio_readl(port, ADSP_PORT_REG_TRIG_TGL); + if (!(val & BIT(offset))) + return -EINVAL; + break; + default: + return -EOPNOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + + return 0; +} + +static void __adsp_pinconf_pue(struct adsp_pinctrl *p, unsigned int pin, bool state) +{ + u32 offset = ADSP_PADS_PORTx_PUE(pin); + u32 val, bit; + + if (p->pude_missing) { + dev_warn(p->dev, + "Pull Up Enable is not supported by this PADS HW (tried to set PUE for pin %d)\n", + pin); + return; + } + + val = readl(p->regs + offset); + bit = BIT(pin & (ADSP_PADS_PUD_PINS_PER_REG-1)); + + if (state) + writel(val | bit, p->regs + offset); + else + writel(val & ~bit, p->regs + offset); +} + +static void __adsp_pinconf_pde(struct adsp_pinctrl *p, unsigned int pin, bool state) +{ + u32 offset = ADSP_PADS_PORTx_PDE(pin); + u32 val, bit; + + if (p->pude_missing) { + dev_warn(p->dev, + "Pull Down Enable is not supported by this PADS HW (tried to set PDE for pin %d)\n", + pin); + return; + } + + val = readl(p->regs + offset); + bit = BIT(pin & (ADSP_PADS_PUD_PINS_PER_REG-1)); + + if (state) + writel(val | bit, p->regs + offset); + else + writel(val & ~bit, p->regs + offset); +} + +static void __adsp_pinconf_ds(struct adsp_pinctrl *p, unsigned int pin, bool high) +{ + u32 offset = ADSP_PADS_PORTx_DS(pin); + u32 val, shift, mask; + + if (p->ds_missing) { + dev_warn(p->dev, + "Drive strength is not supported by this PADS HW (tried to set drive strength for pin %d)\n", + pin); + return; + } + + val = readl(p->regs + offset); + shift = (pin & (ADSP_PADS_DS_PINS_PER_REG-1)) * ADSP_PADS_DS_BITS; + mask = GENMASK(ADSP_PADS_DS_BITS-1, 0) << shift; + val = val & ~mask; + + if (high) + writel(val | (ADSP_PADS_DS_HIGH << shift), p->regs + offset); + else + writel(val | (ADSP_PADS_DS_LOW << shift), p->regs + offset); +} + +static int adsp_pinconf_set(struct pinctrl_dev *pctldev, unsigned int pin, + unsigned long *config, unsigned int num_configs) +{ + struct adsp_pinctrl *adsp_pinctrl = pinctrl_dev_get_drvdata(pctldev); + struct pinctrl_gpio_range *range; + struct adsp_gpio_port *port; + u32 param, arg, val; + u32 offset; + int cfg; + int ret = 0; + unsigned long flags; + + spin_lock_irqsave(&adsp_pinctrl->lock, flags); + + for (cfg = 0; cfg < num_configs; ++cfg) { + param = pinconf_to_config_param(config[cfg]); + arg = pinconf_to_config_argument(config[cfg]); + + switch (param) { + case PIN_CONFIG_BIAS_DISABLE: + __adsp_pinconf_pue(adsp_pinctrl, pin, false); + __adsp_pinconf_pde(adsp_pinctrl, pin, false); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + __adsp_pinconf_pde(adsp_pinctrl, pin, !!arg); + break; + case PIN_CONFIG_BIAS_PULL_UP: + __adsp_pinconf_pue(adsp_pinctrl, pin, !!arg); + break; + case PIN_CONFIG_DRIVE_STRENGTH: + /* This only supports high/low-speed drive strength (see HRM) + * so assume any positive value means we would like high-speed strength + */ + __adsp_pinconf_ds(adsp_pinctrl, pin, !!arg); + break; + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + range = pinctrl_find_gpio_range_from_pin(pctldev, pin); + offset = pin - range->pin_base; + port = to_adsp_gpio_port(range->gc); + + spin_lock(&port->lock); + val = __adsp_gpio_readw(port, ADSP_PORT_REG_DATA); + val &= BIT(offset); + + if (val) { + /* open drain with value of 1 => configure as input */ + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_DIR_CLEAR); + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_INEN_SET); + } else { + /* open drain with value of 0 => configure as output, drive 0 */ + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_INEN_CLEAR); + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_DATA_CLEAR); + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_DIR_SET); + } + + port->open_drain |= BIT(offset); + spin_unlock(&port->lock); + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + range = pinctrl_find_gpio_range_from_pin(pctldev, pin); + offset = pin - range->pin_base; + port = to_adsp_gpio_port(range->gc); + + spin_lock(&port->lock); + + /* + * by default make the pin an input when exiting open drain mode; + * user can correct later with GPIO in/out configuration + */ + if (port->open_drain & BIT(offset)) { + port->open_drain &= ~BIT(offset); + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_DIR_CLEAR); + __adsp_gpio_writew(port, BIT(offset), ADSP_PORT_REG_INEN_SET); + } + + spin_unlock(&port->lock); + break; + case ADSP_PIN_CONFIG_TRU_TOGGLE: + range = pinctrl_find_gpio_range_from_pin(pctldev, pin); + offset = pin - range->pin_base; + port = to_adsp_gpio_port(range->gc); + + spin_lock(&port->lock); + val = __adsp_gpio_readl(port, ADSP_PORT_REG_TRIG_TGL); + val |= BIT(offset); + __adsp_gpio_writel(port, val, ADSP_PORT_REG_TRIG_TGL); + spin_unlock(&port->lock); + break; + default: + ret = -EOPNOTSUPP; + goto end; + } + } + +end: + spin_unlock_irqrestore(&adsp_pinctrl->lock, flags); + return ret; +} + +/* Config for all pins must match or we have an error regarding group structure */ +static int adsp_pinconf_group_get(struct pinctrl_dev *pctldev, unsigned int group, + unsigned long *config) +{ + const unsigned int *pins; + unsigned int npins, i; + unsigned long first; + int ret; + + ret = adsp_pinctrl_get_group_pins(pctldev, group, &pins, &npins); + if (ret) + return ret; + + for (i = 0; i < npins; ++i) { + ret = adsp_pinconf_get(pctldev, pins[i], config); + if (ret) + return ret; + + if (i == 0) + first = *config; + + if (first != *config) + return -EOPNOTSUPP; + } + + return 0; +} + +static int adsp_pinconf_group_set(struct pinctrl_dev *pctldev, unsigned int group, + unsigned long *configs, unsigned int num_configs) +{ + const unsigned int *pins; + unsigned int npins, i; + int ret; + + ret = adsp_pinctrl_get_group_pins(pctldev, group, &pins, &npins); + if (ret) + return ret; + + for (i = 0; i < npins; ++i) { + ret = adsp_pinconf_set(pctldev, pins[i], configs, num_configs); + if (ret) + return ret; + } + + return 0; +} + +static const struct pinconf_ops adsp_confops = { + .is_generic = true, + .pin_config_get = adsp_pinconf_get, + .pin_config_set = adsp_pinconf_set, + .pin_config_group_get = adsp_pinconf_group_get, + .pin_config_group_set = adsp_pinconf_group_set, +#ifdef CONFIG_DEBUG_FS + .pin_config_config_dbg_show = pinconf_generic_dump_config, +#endif +}; + +/* + * We want to make one group per pin so that we can refer to the pins by group + * later on when mux assignments are made + */ +static int adsp_pinctrl_init_groups(struct adsp_pinctrl *adsp_pinctrl, + struct pinctrl_desc *desc) +{ + struct device *dev = adsp_pinctrl->dev; + struct pinctrl_pin_desc *all_pins; + size_t port, pin; + unsigned int i, pin_total; + int num_ports; + int ret; + + num_ports = of_property_count_u32_elems(dev->of_node, "adi,port-sizes"); + + if (num_ports < 0) + return num_ports; + + if (num_ports == 0) { + dev_err(dev, "pinctrl missing `adi,port-sizes` port size definition\n"); + return -ENOENT; + } + + adsp_pinctrl->num_ports = num_ports; + + adsp_pinctrl->pin_counts = devm_kcalloc(dev, sizeof(*adsp_pinctrl->pin_counts), + num_ports, GFP_KERNEL); + if (!adsp_pinctrl->pin_counts) + return -ENOMEM; + + ret = of_property_read_u32_array(dev->of_node, "adi,port-sizes", + adsp_pinctrl->pin_counts, num_ports); + if (ret) + return ret; + + pin_total = 0; + + for (i = 0; i < num_ports; ++i) + pin_total += adsp_pinctrl->pin_counts[i]; + + adsp_pinctrl->total_pins = pin_total; + + all_pins = devm_kcalloc(dev, sizeof(*all_pins), adsp_pinctrl->total_pins, + GFP_KERNEL); + + adsp_pinctrl->pins = devm_kcalloc(dev, sizeof(adsp_pinctrl->pins), + adsp_pinctrl->total_pins, GFP_KERNEL); + if (!adsp_pinctrl->pins) + return -ENOMEM; + + adsp_pinctrl->group_names = devm_kcalloc(dev, sizeof(*adsp_pinctrl->group_names), + adsp_pinctrl->total_pins, GFP_KERNEL); + if (!adsp_pinctrl->group_names) + return -ENOMEM; + + i = 0; + for (port = 0; port < adsp_pinctrl->num_ports; ++port) { + for (pin = 0; pin < adsp_pinctrl->pin_counts[port]; ++pin) { + adsp_pinctrl->group_names[i] = devm_kasprintf(dev, GFP_KERNEL, + "p%c%zu", (char) ('A' + port), pin); + adsp_pinctrl->pins[i] = i; + + all_pins[i].name = adsp_pinctrl->group_names[i]; + all_pins[i].number = i; + i += 1; + } + } + + desc->pins = all_pins; + desc->npins = adsp_pinctrl->total_pins; + + return 0; +} + +static void adsp_set_nongpio_ds(struct adsp_pinctrl *p, int type, bool high) +{ + u32 val = readl(p->regs + ADSP_PADS_NONPORTS_DS); + u32 shift = ADSP_PADS_DS_BITS * type; + u32 mask = GENMASK(ADSP_PADS_DS_BITS-1, 0) << shift; + + val = val & ~mask; + + if (high) + writel(val | (ADSP_PADS_DS_HIGH << shift), p->regs + ADSP_PADS_NONPORTS_DS); + else + writel(val | (ADSP_PADS_DS_LOW << shift), p->regs + ADSP_PADS_NONPORTS_DS); +} + +static int adsp_pinctrl_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct adsp_pinctrl *adsp_pinctrl; + struct pinctrl_desc *pnctrl_desc; + struct resource *res; + u32 val; + int ret; + + adsp_pinctrl = devm_kzalloc(dev, sizeof(*adsp_pinctrl), GFP_KERNEL); + if (!adsp_pinctrl) + return -ENOMEM; + + adsp_pinctrl->dev = dev; + pnctrl_desc = devm_kzalloc(dev, sizeof(*pnctrl_desc), GFP_KERNEL); + if (!pnctrl_desc) + return -ENOMEM; + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + adsp_pinctrl->regs = devm_ioremap_resource(dev, res); + if (IS_ERR(adsp_pinctrl->regs)) + return PTR_ERR(adsp_pinctrl->regs); + + /* Different features are available in different hw revisions; no way to read this + * from an ID register so the missing features need to be specified in dts + */ + adsp_pinctrl->ds_missing = of_property_read_bool(np, "adi,no-drive-strength"); + adsp_pinctrl->pude_missing = of_property_read_bool(np, "adi,no-pull-up-down"); + + /* Only if requested, adjust non-port drive strengths */ + ret = of_property_read_u32(np, "adi,clkout-drive-strength", &val); + if (!ret) + adsp_set_nongpio_ds(adsp_pinctrl, ADSP_NONPORTS_DS_CKOUT, !!val); + + ret = of_property_read_u32(np, "adi,resoutb-drive-strength", &val); + if (!ret) + adsp_set_nongpio_ds(adsp_pinctrl, ADSP_NONPORTS_DS_RESOUTB, !!val); + + ret = of_property_read_u32(np, "adi,faultb-drive-strength", &val); + if (!ret) + adsp_set_nongpio_ds(adsp_pinctrl, ADSP_NONPORTS_DS_FAULTB, !!val); + + ret = of_property_read_u32(np, "adi,lp1ck-drive-strength", &val); + if (!ret) + adsp_set_nongpio_ds(adsp_pinctrl, ADSP_NONPORTS_DS_LP1CK, !!val); + + ret = of_property_read_u32(np, "adi,lp0ck-drive-strength", &val); + if (!ret) + adsp_set_nongpio_ds(adsp_pinctrl, ADSP_NONPORTS_DS_LP0CK, !!val); + + ret = of_property_read_u32(np, "adi,ospi-drive-strength", &val); + if (!ret) + adsp_set_nongpio_ds(adsp_pinctrl, ADSP_NONPORTS_DS_OSPI, !!val); + + pnctrl_desc->name = dev_name(dev); + pnctrl_desc->pctlops = &adsp_pctlops; + pnctrl_desc->confops = &adsp_confops; + pnctrl_desc->pmxops = &adsp_pmxops; + pnctrl_desc->owner = THIS_MODULE; + pnctrl_desc->num_custom_params = ARRAY_SIZE(adsp_custom_bindings); + pnctrl_desc->custom_params = adsp_custom_bindings; + pnctrl_desc->custom_conf_items = adsp_conf_items; + + spin_lock_init(&adsp_pinctrl->lock); + ret = adsp_pinctrl_init_groups(adsp_pinctrl, pnctrl_desc); + if (ret) + return ret; + + ret = devm_pinctrl_register_and_init(dev, pnctrl_desc, adsp_pinctrl, + &adsp_pinctrl->pin_dev); + if (ret) + return ret; + + platform_set_drvdata(pdev, adsp_pinctrl); + ret = pinctrl_enable(adsp_pinctrl->pin_dev); + return ret; +} + +static const struct of_device_id adsp_pinctrl_of_match[] = { + { .compatible = "adi,adsp-pinctrl", }, + { }, +}; +MODULE_DEVICE_TABLE(of, adsp_pinctrl_of_match); + +static struct platform_driver adsp_pinctrl_driver = { + .driver = { + .name = "adsp-pinctrl", + .of_match_table = adsp_pinctrl_of_match, + .suppress_bind_attrs = true, + }, + .probe = adsp_pinctrl_probe, +}; + +static int __init adsp_pinctrl_init(void) +{ + return platform_driver_register(&adsp_pinctrl_driver); +} + +/* + * We want the pinctrl driver to be available at arch init time not at the + * later device init time + */ +arch_initcall(adsp_pinctrl_init); + +MODULE_AUTHOR("Greg Malysa "); +MODULE_DESCRIPTION("Analog Devices Pinctrl driver"); +MODULE_LICENSE("GPL v2"); \ No newline at end of file From patchwork Thu Sep 12 18:24:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802434 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 22804EEE241 for ; Thu, 12 Sep 2024 18:20:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id 38FE8C4E690; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id 0F8A2C4DE0D; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165216; bh=aZKeGq4p5ipcsfiHoGVqu/Fn0FE33lt6G4aL/LyS4+0=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=fK1Pb8cG3z+/8jCD4Mx4QxLB2vLsDp7cG37wm+XmXsYjUIffIMwGIL8/mAL7q6K9d XKTWOIKPPQRk4EsWs/55sfQJgYY7vdD7f2yJF2VLk3YtC6DYQSz3E/xSNsHvutGuok GObHbJ+mgfV3e6TBGFgrCh7RnDRwMqiI0ILPg8qTfuWlNfaRCTj2V04EgEDdozfAQ+ OZvLp4naGYz6DqDGAemV1taZpFZqMl1x5pp1WGbzV0FQHIs46lm0VJ/lTbiaY1v6gu j9LJJvQZkj1EMHeIbsd0AfTSEcR4R15imLc9RlnlGbDNVmZguJf6AicsvkNZ0kCMuZ GsJu3myD73mlg== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 07F27EEE240; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:24:59 +0100 Subject: [PATCH 14/21] dt-bindings: pinctrl: adi,adsp-pinctrl: add bindings MIME-Version: 1.0 Message-Id: <20240912-test-v1-14-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=3857; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=8cIHFW2VHjXFP2WdC7ohf0MOYH4XA2BareGL3V29WFU=; b=fK46p873AmYdSJ17NDk9Nq0m1iWXpEzwV7H2MptZzhNyghpOJrlmoWDjpnQS17mhBhGwihE3U SVtUZ+iSYzCB+MHGX3zfxt3/UF5DP84N3NJOWd5Mmeie3LXzznZn1XN X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Add PINCTRL driver bindings. Signed-off-by: Arturs Artamonovs Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- .../bindings/pinctrl/adi,adsp-pinctrl.yaml | 83 ++++++++++++++++++++++ include/dt-bindings/pinctrl/adi-adsp.h | 19 +++++ 2 files changed, 102 insertions(+) diff --git a/Documentation/devicetree/bindings/pinctrl/adi,adsp-pinctrl.yaml b/Documentation/devicetree/bindings/pinctrl/adi,adsp-pinctrl.yaml new file mode 100644 index 0000000000000000000000000000000000000000..073442b4f680bf536f631b4c17a1d3195c2233d6 --- /dev/null +++ b/Documentation/devicetree/bindings/pinctrl/adi,adsp-pinctrl.yaml @@ -0,0 +1,83 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/pinctrl/adi,adsp-pinctrl.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices Pinmuxing Control for SC5XX Processor Family + +maintainers: + - Arturs Artamonovs + - Utsav Agarwal + +description: | + Pinmuxing Control Driver for Configuring Processor Pins/Pads + +properties: + compatible: + enum: + - adi,adsp-pinctrl + + "#address-cells": + const: 1 + + "#size-cells": + const: 1 + + reg: + maxItems: 1 + + "adi,port-sizes": + $ref: /schemas/types.yaml#/definitions/uint32-array + maxItems: 9 + description: Space delimited integer list denoting number of pins per port + Ports A-I exist, so this is up to 9 items long + + "adi,no-drive-strength": + type: boolean + description: Indicate missing drive strength registers + + "adi,no-pull-up-down": + type: boolean + description: Indicate missing pull up/down enable registers + +patternProperties: + '-pins$': + type: object + additionalProperties: false + + properties: + pins: + type: object + description: | + A pinctrl node should contain a pin property, specifying the actual + pins to use. + + properties: + pinmux: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: | + pinmux is used to specify which of the available functionalities + for a given pin are actually used. + + additionalProperties: false + +required: + - compatible + - "#address-cells" + - "#size-cells" + - reg + - "adi,port-sizes" + +additionalProperties: false + +examples: + - | + pinctrl0: pinctrl@31004600 { + compatible = "adi,adsp-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x31004600 0x400>; + adi,port-sizes = <16 16 16 16 16 16 16 16 7>; + }; + diff --git a/include/dt-bindings/pinctrl/adi-adsp.h b/include/dt-bindings/pinctrl/adi-adsp.h new file mode 100644 index 0000000000000000000000000000000000000000..dc5b86a0d9190acdd242a6ba4972c3aac7a61821 --- /dev/null +++ b/include/dt-bindings/pinctrl/adi-adsp.h @@ -0,0 +1,19 @@ +/* SPDX-License-Identifier: GPL-2.0*/ +/* + * Macros for populating pinmux properties on the pincontroller + * + * Copyright 2022-2024 - Analog Devices Inc. + */ + +#ifndef DT_BINDINGS_PINCTRL_ADI_ADSP_H +#define DT_BINDINGS_PINCTRL_ADI_ADSP_H + +#define ADI_ADSP_PINFUNC_GPIO 0 +#define ADI_ADSP_PINFUNC_ALT0 1 +#define ADI_ADSP_PINFUNC_ALT1 2 +#define ADI_ADSP_PINFUNC_ALT2 3 +#define ADI_ADSP_PINFUNC_ALT3 4 + +#define ADI_ADSP_PINMUX(port, pin, func) ((((port - 'A')*16 + pin) << 8) + func) + +#endif From patchwork Thu Sep 12 18:25:00 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802440 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 6B0B4EEE25E for ; Thu, 12 Sep 2024 18:20:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id 5AA9FC4FDE8; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id 2A5D9C4DE1D; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165216; bh=oSjrrK3HqKhPT33RcO6IzP0otSDj5oLxA3L//E5mLLM=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=ZBgovuk4Hmeg31duJmpMD5IkpfU1yqAXvOUqprtaGW7lnQ/i4A7hMLDuaVdTTfmdl xm0uyrsh6hsIHwYn7AjuDjUi8POBe3jhXSUomB0l5MbYL3d3hrzR0S649xhYSdcBHD zgihQ9G35kZ6Ax5wrDNHT7LNKuUK/CCtIZUQInDl4d4oe3QttARxl315wZDlTPCXjC Sxg77EdYyLhxzuyZrI3D0hot7hsgXJIRguMhvA2gL69DuwauG8twOk1SR65NMBaL2+ Og4tAeP6bVsSKEDED4ea3Ecft9pU2rAGTcxgsxZzjQ7soFrR4SqRUftBIeHvID5/EW R0J+i569YU2zw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1E269EEE25C; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:25:00 +0100 Subject: [PATCH 15/21] i2c: Add driver for ADI ADSP-SC5xx platforms MIME-Version: 1.0 Message-Id: <20240912-test-v1-15-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=30323; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=3JNx5RiekCNc4Kpql+FHMF5vouOGWncXg0juhBgUj+k=; b=6/RCpfUMh/Zue+vifS5T5HepAnaEA6vIxJmq7ObeaWwcWW79yzW3TpgFjeP61ysJTAof/L/un UNPr8cBh6ohDBn4LpmAAXKg0qKhzapdh46srJPDla/DB9jGsu4Dn4mn X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Add support for I2C on SC5xx Signed-off-by: Arturs Artamonovs Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- drivers/i2c/busses/Kconfig | 17 + drivers/i2c/busses/Makefile | 1 + drivers/i2c/busses/i2c-adi-twi.c | 940 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 958 insertions(+) diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig index a22f9125322a723b31925fd86b26ef0b8d3b8a19..f672a2c715ca15ece74ee694596318976da88dfd 100644 --- a/drivers/i2c/busses/Kconfig +++ b/drivers/i2c/busses/Kconfig @@ -518,6 +518,23 @@ config I2C_BRCMSTB If you do not need I2C interface, say N. +config I2C_ADI_TWI + tristate "ADI TWI I2C support" + depends on ARCH_SC59X_64 || ARCH_SC59X + help + This is the I2C bus driver for ADI on-chip TWI interface. + + This driver can also be built as a module. If so, the module + will be called i2c-adi-twi. + +config I2C_ADI_TWI_CLK_KHZ + int "ADI TWI I2C clock (kHz)" + depends on I2C_ADI_TWI + range 21 400 + default 50 + help + The unit of the TWI clock is kHz. + config I2C_CADENCE tristate "Cadence I2C Controller" depends on ARCH_ZYNQ || ARM64 || XTENSA || RISCV || COMPILE_TEST diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile index 78d0561339e5beadcb810196be1139a4248469b4..421d637cfbc91af5a69895e76a255b2ef47f4081 100644 --- a/drivers/i2c/busses/Makefile +++ b/drivers/i2c/busses/Makefile @@ -48,6 +48,7 @@ obj-$(CONFIG_I2C_AU1550) += i2c-au1550.o obj-$(CONFIG_I2C_AXXIA) += i2c-axxia.o obj-$(CONFIG_I2C_BCM2835) += i2c-bcm2835.o obj-$(CONFIG_I2C_BCM_IPROC) += i2c-bcm-iproc.o +obj-$(CONFIG_I2C_ADI_TWI) += i2c-adi-twi.o obj-$(CONFIG_I2C_CADENCE) += i2c-cadence.o obj-$(CONFIG_I2C_CBUS_GPIO) += i2c-cbus-gpio.o obj-$(CONFIG_I2C_CPM) += i2c-cpm.o diff --git a/drivers/i2c/busses/i2c-adi-twi.c b/drivers/i2c/busses/i2c-adi-twi.c new file mode 100644 index 0000000000000000000000000000000000000000..4af3991f5fc8709df196f58816ed7a96fd1dac2d --- /dev/null +++ b/drivers/i2c/busses/i2c-adi-twi.c @@ -0,0 +1,940 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ADI On-Chip Two Wire Interface Driver + * + * Copyright 2022-2024 - Analog Devices Inc. + */ + +#include +#include +#include +#include +#include +#include + + +/* TWI_PRESCALE Masks */ +#define TWI_ENA 0x0080 /* TWI Enable */ + +/* TWI_MASTER_CTL Masks */ +#define MEN 0x0001 /* Master Mode Enable */ +#define MDIR 0x0004 /* Master Transmit Direction (RX/TX*) */ +#define FAST 0x0008 /* Use Fast Mode Timing Specs */ +#define STOP 0x0010 /* Issue Stop Condition */ +#define RSTART 0x0020 /* Repeat Start or Stop* At End Of Transfer */ +#define SDAOVR 0x4000 /* Serial Data Override */ +#define SCLOVR 0x8000 /* Serial Clock Override */ + +/* TWI_MASTER_STAT Masks */ +#define LOSTARB 0x0002 /* Lost Arbitration Indicator (Xfer Aborted) */ +#define ANAK 0x0004 /* Address Not Acknowledged */ +#define DNAK 0x0008 /* Data Not Acknowledged */ +#define BUFRDERR 0x0010 /* Buffer Read Error */ +#define BUFWRERR 0x0020 /* Buffer Write Error */ +#define SDASEN 0x0040 /* Serial Data Sense */ +#define BUSBUSY 0x0100 /* Bus Busy Indicator */ + +/* TWI_INT_SRC and TWI_INT_ENABLE Masks */ +#define MCOMP 0x0010 /* Master Transfer Complete */ +#define MERR 0x0020 /* Master Transfer Error */ +#define XMTSERV 0x0040 /* Transmit FIFO Service */ +#define RCVSERV 0x0080 /* Receive FIFO Service */ + +/* TWI_FIFO_STAT Masks */ +#define XMTSTAT 0x0003 /* Transmit FIFO Status */ +#define XMT_FULL 0x0003 /* Transmit FIFO Full (2 Bytes To Write) */ +#define RCVSTAT 0x000C /* Receive FIFO Status */ + +/* SMBus mode*/ +#define TWI_I2C_MODE_STANDARD 1 +#define TWI_I2C_MODE_STANDARDSUB 2 +#define TWI_I2C_MODE_COMBINED 3 +#define TWI_I2C_MODE_REPEAT 4 + +/* + * ADI twi registers layout + */ +struct adi_twi_regs { + u16 clkdiv; + u16 dummy1; + u16 control; + u16 dummy2; + u16 slave_ctl; + u16 dummy3; + u16 slave_stat; + u16 dummy4; + u16 slave_addr; + u16 dummy5; + u16 master_ctl; + u16 dummy6; + u16 master_stat; + u16 dummy7; + u16 master_addr; + u16 dummy8; + u16 int_stat; + u16 dummy9; + u16 int_mask; + u16 dummy10; + u16 fifo_ctl; + u16 dummy11; + u16 fifo_stat; + u16 dummy12; + u32 __pad[20]; + u16 xmt_data8; + u16 dummy13; + u16 xmt_data16; + u16 dummy14; + u16 rcv_data8; + u16 dummy15; + u16 rcv_data16; + u16 dummy16; +}; + +struct adi_twi_iface { + int irq; + spinlock_t lock; + char read_write; + u8 command; + u8 *transPtr; + int readNum; + int writeNum; + int cur_mode; + int manual_stop; + int result; + unsigned int twi_clk; + struct i2c_adapter adap; + struct completion complete; + struct i2c_msg *pmsg; + int msg_num; + int cur_msg; + u16 saved_clkdiv; + u16 saved_control; + struct adi_twi_regs __iomem *regs_base; + struct clk *sclk; +}; + +static void adi_twi_handle_interrupt(struct adi_twi_iface *iface, + unsigned short twi_int_status, + bool polling) +{ + u16 writeValue; + unsigned short mast_stat = ioread16(&iface->regs_base->master_stat); + + if (twi_int_status & XMTSERV) { + if (iface->writeNum <= 0) { + /* start receive immediately after complete sending in + * combine mode. + */ + if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { + writeValue = ioread16(&iface->regs_base->master_ctl) | MDIR; + iowrite16(writeValue, &iface->regs_base->master_ctl); + } else if (iface->manual_stop) { + writeValue = ioread16(&iface->regs_base->master_ctl) | STOP; + iowrite16(writeValue, &iface->regs_base->master_ctl); + } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && + iface->cur_msg + 1 < iface->msg_num) { + + if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) { + writeValue = ioread16(&iface->regs_base->master_ctl) + | MDIR; + iowrite16(writeValue, &iface->regs_base->master_ctl); + } else { + writeValue = ioread16(&iface->regs_base->master_ctl) + & ~MDIR; + iowrite16(writeValue, &iface->regs_base->master_ctl); + } + + } + } + /* Transmit next data */ + while (iface->writeNum > 0 && + (ioread16(&iface->regs_base->fifo_stat) & XMTSTAT) != XMT_FULL) { + iowrite16(*(iface->transPtr++), &iface->regs_base->xmt_data8); + iface->writeNum--; + } + } + if (twi_int_status & RCVSERV) { + while (iface->readNum > 0 && + (ioread16(&iface->regs_base->fifo_stat) & RCVSTAT)) { + /* Receive next data */ + *(iface->transPtr) = ioread16(&iface->regs_base->rcv_data8); + if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { + /* Change combine mode into sub mode after + * read first data. + */ + iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; + /* Get read number from first byte in block + * combine mode. + */ + if (iface->readNum == 1 && iface->manual_stop) + iface->readNum = *iface->transPtr + 1; + } + iface->transPtr++; + iface->readNum--; + } + + if (iface->readNum == 0) { + if (iface->manual_stop) { + /* Temporary workaround to avoid possible bus stall - + * Flush FIFO before issuing the STOP condition + */ + ioread16(&iface->regs_base->rcv_data16); + writeValue = ioread16(&iface->regs_base->master_ctl) | STOP; + iowrite16(writeValue, &iface->regs_base->master_ctl); + } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && + iface->cur_msg + 1 < iface->msg_num) { + if (iface->pmsg[iface->cur_msg + 1].flags & I2C_M_RD) { + writeValue = ioread16(&iface->regs_base->master_ctl) | + MDIR; + iowrite16(writeValue, &iface->regs_base->master_ctl); + } else { + writeValue = ioread16(&iface->regs_base->master_ctl) & + ~MDIR; + iowrite16(writeValue, &iface->regs_base->master_ctl); + } + } + } + } + if (twi_int_status & MERR) { + iowrite16(0, &iface->regs_base->int_mask); + iowrite16(0x3e, &iface->regs_base->master_stat); + iowrite16(0, &iface->regs_base->master_ctl); + iface->result = -EIO; + + if (mast_stat & LOSTARB) + dev_dbg(&iface->adap.dev, "Lost Arbitration\n"); + if (mast_stat & ANAK) + dev_dbg(&iface->adap.dev, "Address Not Acknowledged\n"); + if (mast_stat & DNAK) + dev_dbg(&iface->adap.dev, "Data Not Acknowledged\n"); + if (mast_stat & BUFRDERR) + dev_dbg(&iface->adap.dev, "Buffer Read Error\n"); + if (mast_stat & BUFWRERR) + dev_dbg(&iface->adap.dev, "Buffer Write Error\n"); + + /* Faulty slave devices, may drive SDA low after a transfer + * finishes. To release the bus this code generates up to 9 + * extra clocks until SDA is released. + */ + + if (ioread16(&iface->regs_base->master_stat) & SDASEN) { + int cnt = 9; + + do { + iowrite16(SCLOVR, &iface->regs_base->master_ctl); + udelay(6); + iowrite16(0, &iface->regs_base->master_ctl); + udelay(6); + } while ((ioread16(&iface->regs_base->master_stat) & SDASEN) && cnt--); + + iowrite16(SDAOVR | SCLOVR, &iface->regs_base->master_ctl); + udelay(6); + iowrite16(SDAOVR, &iface->regs_base->master_ctl); + udelay(6); + iowrite16(0, &iface->regs_base->master_ctl); + } + + /* If it is a quick transfer, only address without data, + * not an err, return 1. + */ + if (iface->cur_mode == TWI_I2C_MODE_STANDARD && + iface->transPtr == NULL && + (twi_int_status & MCOMP) && (mast_stat & DNAK)) + iface->result = 1; + + if (!polling) + complete(&iface->complete); + return; + } + if (twi_int_status & MCOMP) { + if (twi_int_status & (XMTSERV | RCVSERV) && + (ioread16(&iface->regs_base->master_ctl) & MEN) == 0 && + (iface->cur_mode == TWI_I2C_MODE_REPEAT || + iface->cur_mode == TWI_I2C_MODE_COMBINED)) { + iface->result = -1; + iowrite16(0, &iface->regs_base->int_mask); + iowrite16(0, &iface->regs_base->master_ctl); + } else if (iface->cur_mode == TWI_I2C_MODE_COMBINED) { + if (iface->readNum == 0) { + /* set the read number to 1 and ask for manual + * stop in block combine mode + */ + iface->readNum = 1; + iface->manual_stop = 1; + writeValue = ioread16(&iface->regs_base->master_ctl) | (0xff << 6); + iowrite16(writeValue, &iface->regs_base->master_ctl); + } else { + /* set the readd number in other + * combine mode. + */ + writeValue = (ioread16(&iface->regs_base->master_ctl) + & (~(0xff << 6))) | (iface->readNum << 6); + iowrite16(writeValue, &iface->regs_base->master_ctl); + } + /* remove restart bit and enable master receive */ + writeValue = ioread16(&iface->regs_base->master_ctl) & ~RSTART; + iowrite16(writeValue, &iface->regs_base->master_ctl); + } else if (iface->cur_mode == TWI_I2C_MODE_REPEAT && + iface->cur_msg + 1 < iface->msg_num) { + iface->cur_msg++; + iface->transPtr = iface->pmsg[iface->cur_msg].buf; + iface->writeNum = iface->readNum = + iface->pmsg[iface->cur_msg].len; + /* Set Transmit device address */ + iowrite16(iface->pmsg[iface->cur_msg].addr, &iface->regs_base->master_addr); + if (iface->pmsg[iface->cur_msg].flags & I2C_M_RD) + iface->read_write = I2C_SMBUS_READ; + else { + iface->read_write = I2C_SMBUS_WRITE; + /* Transmit first data */ + if (iface->writeNum > 0) { + iowrite16(*(iface->transPtr++), + &iface->regs_base->xmt_data8); + iface->writeNum--; + } + } + + if (iface->pmsg[iface->cur_msg].len <= 255) { + writeValue = (ioread16(&iface->regs_base->master_ctl) + & (~(0xff << 6))) + | (iface->pmsg[iface->cur_msg].len << 6); + iowrite16(writeValue, &iface->regs_base->master_ctl); + iface->manual_stop = 0; + } else { + writeValue = (ioread16(&iface->regs_base->master_ctl) + | (0xff << 6)); + iowrite16(writeValue, &iface->regs_base->master_ctl); + iface->manual_stop = 1; + } + + /* remove restart bit before last message */ + if (iface->cur_msg + 1 == iface->msg_num) { + writeValue = ioread16(&iface->regs_base->master_ctl) & ~RSTART; + iowrite16(writeValue, &iface->regs_base->master_ctl); + } + + } else { + iface->result = 1; + iowrite16(0, &iface->regs_base->int_mask); + iowrite16(0, &iface->regs_base->master_ctl); + } + if (!polling) + complete(&iface->complete); + } +} + +/* Interrupt handler */ +static irqreturn_t adi_twi_handle_all_interrupts(struct adi_twi_iface *iface, + bool polling) +{ + irqreturn_t handled = IRQ_NONE; + unsigned short twi_int_status; + + while (1) { + twi_int_status = ioread16(&iface->regs_base->int_stat); + if (!twi_int_status) + return handled; + /* Clear interrupt status */ + iowrite16(twi_int_status, &iface->regs_base->int_stat); + adi_twi_handle_interrupt(iface, twi_int_status, polling); + handled = IRQ_HANDLED; + } +} + +static irqreturn_t adi_twi_interrupt_entry(int irq, void *dev_id) +{ + struct adi_twi_iface *iface = dev_id; + unsigned long flags; + irqreturn_t handled; + + spin_lock_irqsave(&iface->lock, flags); + handled = adi_twi_handle_all_interrupts(iface, false); + spin_unlock_irqrestore(&iface->lock, flags); + return handled; +} + +/* + * One i2c master transfer + */ +static int adi_twi_do_master_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num, bool polling) +{ + struct adi_twi_iface *iface = adap->algo_data; + struct i2c_msg *pmsg; + int rc = 0; + u16 writeValue; + + if (!(ioread16(&iface->regs_base->control) & TWI_ENA)) + return -ENXIO; + + if (ioread16(&iface->regs_base->master_stat) & BUSBUSY) + return -EAGAIN; + + iface->pmsg = msgs; + iface->msg_num = num; + iface->cur_msg = 0; + + pmsg = &msgs[0]; + if (pmsg->flags & I2C_M_TEN) { + dev_err(&adap->dev, "10 bits addr not supported!\n"); + return -EINVAL; + } + + if (iface->msg_num > 1) + iface->cur_mode = TWI_I2C_MODE_REPEAT; + iface->manual_stop = 0; + iface->transPtr = pmsg->buf; + iface->writeNum = iface->readNum = pmsg->len; + iface->result = 0; + if (!polling) + init_completion(&(iface->complete)); + /* Set Transmit device address */ + iowrite16(pmsg->addr, &iface->regs_base->master_addr); + + /* FIFO Initiation. Data in FIFO should be + * discarded before start a new operation. + */ + iowrite16(0x3, &iface->regs_base->fifo_ctl); + iowrite16(0, &iface->regs_base->fifo_ctl); + + if (pmsg->flags & I2C_M_RD) + iface->read_write = I2C_SMBUS_READ; + else { + iface->read_write = I2C_SMBUS_WRITE; + /* Transmit first data */ + if (iface->writeNum > 0) { + iowrite16(*(iface->transPtr++), &iface->regs_base->xmt_data8); + iface->writeNum--; + } + } + + /* clear int stat */ + iowrite16(MERR | MCOMP | XMTSERV | RCVSERV, &iface->regs_base->int_stat); + + /* Interrupt mask . Enable XMT, RCV interrupt */ + iowrite16(MCOMP | MERR | RCVSERV | XMTSERV, &iface->regs_base->int_mask); + + if (pmsg->len <= 255) + iowrite16(pmsg->len << 6, &iface->regs_base->master_ctl); + else { + iowrite16(0xff << 6, &iface->regs_base->master_ctl); + iface->manual_stop = 1; + } + + /* Master enable */ + writeValue = ioread16(&iface->regs_base->master_ctl) | + MEN | + ((iface->msg_num > 1) ? RSTART : 0) | + ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | + ((iface->twi_clk > 100) ? FAST : 0); + + iowrite16(writeValue, &iface->regs_base->master_ctl); + + if (polling) { + int timeout = 50000; + + for (;;) { + irqreturn_t handled = adi_twi_handle_all_interrupts( + iface, true); + if (handled == IRQ_HANDLED && iface->result) + break; + if (--timeout == 0) { + iface->result = -1; + dev_err(&adap->dev, "master polling timeout"); + break; + } + } + } else { /* interrupt driven */ + while (!iface->result) { + if (!wait_for_completion_timeout(&iface->complete, + adap->timeout)) { + iface->result = -1; + dev_err(&adap->dev, "master transfer timeout"); + } + } + } + + if (iface->result == 1) + rc = iface->cur_msg + 1; + else + rc = iface->result; + + return rc; +} + +/* + * Generic i2c master transfer entrypoint + */ +static int adi_twi_master_xfer(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + return adi_twi_do_master_xfer(adap, msgs, num, false); +} + +static int adi_twi_master_xfer_atomic(struct i2c_adapter *adap, + struct i2c_msg *msgs, int num) +{ + return adi_twi_do_master_xfer(adap, msgs, num, true); +} + +/* + * One I2C SMBus transfer + */ +static int adi_twi_do_smbus_xfer(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data *data, + bool polling) +{ + struct adi_twi_iface *iface = adap->algo_data; + int rc = 0; + u16 writeValue; + + if (!(ioread16(&iface->regs_base->control) & TWI_ENA)) + return -ENXIO; + + if (ioread16(&iface->regs_base->master_stat) & BUSBUSY) + return -EAGAIN; + + iface->writeNum = 0; + iface->readNum = 0; + + /* Prepare datas & select mode */ + switch (size) { + case I2C_SMBUS_QUICK: + iface->transPtr = NULL; + iface->cur_mode = TWI_I2C_MODE_STANDARD; + break; + case I2C_SMBUS_BYTE: + if (data == NULL) + iface->transPtr = NULL; + else { + if (read_write == I2C_SMBUS_READ) + iface->readNum = 1; + else + iface->writeNum = 1; + iface->transPtr = &data->byte; + } + iface->cur_mode = TWI_I2C_MODE_STANDARD; + break; + case I2C_SMBUS_BYTE_DATA: + if (read_write == I2C_SMBUS_READ) { + iface->readNum = 1; + iface->cur_mode = TWI_I2C_MODE_COMBINED; + } else { + iface->writeNum = 1; + iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; + } + iface->transPtr = &data->byte; + break; + case I2C_SMBUS_WORD_DATA: + if (read_write == I2C_SMBUS_READ) { + iface->readNum = 2; + iface->cur_mode = TWI_I2C_MODE_COMBINED; + } else { + iface->writeNum = 2; + iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; + } + iface->transPtr = (u8 *)&data->word; + break; + case I2C_SMBUS_PROC_CALL: + iface->writeNum = 2; + iface->readNum = 2; + iface->cur_mode = TWI_I2C_MODE_COMBINED; + iface->transPtr = (u8 *)&data->word; + break; + case I2C_SMBUS_BLOCK_DATA: + if (read_write == I2C_SMBUS_READ) { + iface->readNum = 0; + iface->cur_mode = TWI_I2C_MODE_COMBINED; + } else { + iface->writeNum = data->block[0] + 1; + iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; + } + iface->transPtr = data->block; + break; + case I2C_SMBUS_I2C_BLOCK_DATA: + if (read_write == I2C_SMBUS_READ) { + iface->readNum = data->block[0]; + iface->cur_mode = TWI_I2C_MODE_COMBINED; + } else { + iface->writeNum = data->block[0]; + iface->cur_mode = TWI_I2C_MODE_STANDARDSUB; + } + iface->transPtr = (u8 *)&data->block[1]; + break; + default: + return -1; + } + + iface->result = 0; + iface->manual_stop = 0; + iface->read_write = read_write; + iface->command = command; + if (!polling) + init_completion(&(iface->complete)); + + /* FIFO Initiation. Data in FIFO should be discarded before + * start a new operation. + */ + iowrite16(0x3, &iface->regs_base->fifo_ctl); + iowrite16(0, &iface->regs_base->fifo_ctl); + + /* clear int stat */ + iowrite16(MERR | MCOMP | XMTSERV | RCVSERV, &iface->regs_base->int_stat); + + /* Set Transmit device address */ + iowrite16(addr, &iface->regs_base->master_addr); + + switch (iface->cur_mode) { + case TWI_I2C_MODE_STANDARDSUB: + iowrite16(iface->command, &iface->regs_base->xmt_data8); + + writeValue = MCOMP | MERR; + if (iface->read_write == I2C_SMBUS_READ) + writeValue |= RCVSERV; + else + writeValue |= XMTSERV; + + iowrite16(writeValue, &iface->regs_base->int_mask); + + if (iface->writeNum + 1 <= 255) + iowrite16((iface->writeNum + 1) << 6, &iface->regs_base->master_ctl); + else { + iowrite16(0xff << 6, &iface->regs_base->master_ctl); + iface->manual_stop = 1; + } + /* Master enable */ + writeValue = ioread16(&iface->regs_base->master_ctl) | MEN; + if (iface->twi_clk > 100) + writeValue |= FAST; + iowrite16(writeValue, &iface->regs_base->master_ctl); + break; + case TWI_I2C_MODE_COMBINED: + iowrite16(iface->command, &iface->regs_base->xmt_data8); + iowrite16(MCOMP | MERR | RCVSERV | XMTSERV, &iface->regs_base->int_mask); + + if (iface->writeNum > 0) + iowrite16((iface->writeNum + 1) << 6, &iface->regs_base->master_ctl); + else + iowrite16(0x1 << 6, &iface->regs_base->master_ctl); + /* Master enable */ + writeValue = ioread16(&iface->regs_base->master_ctl) | MEN | RSTART; + if (iface->twi_clk > 100) + writeValue |= FAST; + iowrite16(writeValue, &iface->regs_base->master_ctl); + break; + default: + iowrite16(0, &iface->regs_base->master_ctl); + if (size != I2C_SMBUS_QUICK) { + /* Don't access xmit data register when this is a + * read operation. + */ + if (iface->read_write != I2C_SMBUS_READ) { + if (iface->writeNum > 0) { + iowrite16(*(iface->transPtr++), + &iface->regs_base->xmt_data8); + if (iface->writeNum <= 255) + iowrite16(iface->writeNum << 6, + &iface->regs_base->master_ctl); + else { + iowrite16(0xff << 6, &iface->regs_base->master_ctl); + iface->manual_stop = 1; + } + iface->writeNum--; + } else { + iowrite16(iface->command, &iface->regs_base->xmt_data8); + iowrite16(1 << 6, &iface->regs_base->master_ctl); + } + } else { + if (iface->readNum > 0 && iface->readNum <= 255) + iowrite16(iface->readNum << 6, + &iface->regs_base->master_ctl); + else if (iface->readNum > 255) { + iowrite16(0xff << 6, &iface->regs_base->master_ctl); + iface->manual_stop = 1; + } else + break; + } + } + writeValue = MCOMP | MERR; + if (iface->read_write == I2C_SMBUS_READ) + writeValue |= RCVSERV; + else + writeValue |= XMTSERV; + iowrite16(writeValue, &iface->regs_base->int_mask); + + /* Master enable */ + writeValue = ioread16(&iface->regs_base->master_ctl) | MEN | + ((iface->read_write == I2C_SMBUS_READ) ? MDIR : 0) | + ((iface->twi_clk > 100) ? FAST : 0); + iowrite16(writeValue, &iface->regs_base->master_ctl); + break; + } + + if (polling) { + int timeout = 50000; + + for (;;) { + irqreturn_t handled = adi_twi_handle_all_interrupts( + iface, true); + if (handled == IRQ_HANDLED && iface->result) + break; + if (--timeout == 0) { + iface->result = -1; + dev_err(&adap->dev, "smbus polling timeout"); + break; + } + } + } else { /* interrupt driven */ + while (!iface->result) { + if (!wait_for_completion_timeout(&iface->complete, + adap->timeout)) { + iface->result = -1; + dev_err(&adap->dev, "smbus transfer timeout"); + } + } + } + + rc = (iface->result >= 0) ? 0 : -1; + + return rc; +} + +/* + * Generic I2C SMBus transfer entrypoint + */ +static int adi_twi_smbus_xfer(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data *data) +{ + return adi_twi_do_smbus_xfer(adap, addr, flags, + read_write, command, size, data, false); +} + +static int adi_twi_smbus_xfer_atomic(struct i2c_adapter *adap, u16 addr, + unsigned short flags, char read_write, + u8 command, int size, union i2c_smbus_data *data) +{ + return adi_twi_do_smbus_xfer(adap, addr, flags, + read_write, command, size, data, true); +} + +/* + * Return what the adapter supports + */ +static u32 adi_twi_functionality(struct i2c_adapter *adap) +{ + return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE | + I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA | + I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL | + I2C_FUNC_I2C | I2C_FUNC_SMBUS_I2C_BLOCK; +} + +static const struct i2c_algorithm adi_twi_algorithm = { + .master_xfer = adi_twi_master_xfer, + .master_xfer_atomic = adi_twi_master_xfer_atomic, + .smbus_xfer = adi_twi_smbus_xfer, + .smbus_xfer_atomic = adi_twi_smbus_xfer_atomic, + .functionality = adi_twi_functionality, +}; + +#ifdef CONFIG_PM_SLEEP +static int i2c_adi_twi_suspend(struct device *dev) +{ + struct adi_twi_iface *iface = dev_get_drvdata(dev); + + iface->saved_clkdiv = ioread16(&iface->regs_base->clkdiv); + iface->saved_control = ioread16(&iface->regs_base->control); + + free_irq(iface->irq, iface); + + /* Disable TWI */ + iowrite16(iface->saved_control & ~TWI_ENA, &iface->regs_base->control); + + return 0; +} + +static int i2c_adi_twi_resume(struct device *dev) +{ + struct adi_twi_iface *iface = dev_get_drvdata(dev); + + int rc = request_irq(iface->irq, adi_twi_interrupt_entry, + 0, to_platform_device(dev)->name, iface); + if (rc) { + dev_err(dev, "Can't get IRQ %d !\n", iface->irq); + return -ENODEV; + } + + /* Resume TWI interface clock as specified */ + iowrite16(iface->saved_clkdiv, &iface->regs_base->clkdiv); + + /* Resume TWI */ + iowrite16(iface->saved_control, &iface->regs_base->control); + + return 0; +} + +static SIMPLE_DEV_PM_OPS(i2c_adi_twi_pm, + i2c_adi_twi_suspend, i2c_adi_twi_resume); +#define I2C_ADI_TWI_PM_OPS (&i2c_adi_twi_pm) +#else +#define I2C_ADI_TWI_PM_OPS NULL +#endif + +#ifdef CONFIG_OF +static const struct of_device_id adi_twi_of_match[] = { + { + .compatible = "adi,twi", + }, + {}, +}; +MODULE_DEVICE_TABLE(of, adi_twi_of_match); +#endif + +static int i2c_adi_twi_probe(struct platform_device *pdev) +{ + struct adi_twi_iface *iface; + struct i2c_adapter *p_adap; + struct resource *res; + const struct of_device_id *match; + struct device_node *node = pdev->dev.of_node; + int rc; + unsigned int clkhilow; + u16 writeValue; + + iface = devm_kzalloc(&pdev->dev, sizeof(*iface), GFP_KERNEL); + if (!iface) + return -ENOMEM; + + spin_lock_init(&(iface->lock)); + + match = of_match_device(of_match_ptr(adi_twi_of_match), &pdev->dev); + if (match) { + if (of_property_read_u32(node, "clock-khz", + &iface->twi_clk)) + iface->twi_clk = 50; + } else + iface->twi_clk = CONFIG_I2C_ADI_TWI_CLK_KHZ; + + iface->sclk = devm_clk_get(&pdev->dev, "sclk0"); + if (IS_ERR(iface->sclk)) { + if (PTR_ERR(iface->sclk) != -EPROBE_DEFER) + dev_err(&pdev->dev, "Missing i2c clock\n"); + return PTR_ERR(iface->sclk); + } + + /* Find and map our resources */ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "Cannot get IORESOURCE_MEM\n"); + return -ENOENT; + } + + iface->regs_base = devm_ioremap_resource(&pdev->dev, res); + if (IS_ERR(iface->regs_base)) { + dev_err(&pdev->dev, "Cannot map IO\n"); + return PTR_ERR(iface->regs_base); + } + + iface->irq = platform_get_irq(pdev, 0); + if (iface->irq < 0) { + dev_err(&pdev->dev, "No IRQ specified\n"); + return -ENOENT; + } + + p_adap = &iface->adap; + p_adap->nr = pdev->id; + strscpy(p_adap->name, pdev->name, sizeof(p_adap->name)); + p_adap->algo = &adi_twi_algorithm; + p_adap->algo_data = iface; + p_adap->class = I2C_CLASS_DEPRECATED; + p_adap->dev.parent = &pdev->dev; + p_adap->dev.of_node = node; + p_adap->timeout = 5 * HZ; + p_adap->retries = 3; + + rc = devm_request_irq(&pdev->dev, iface->irq, adi_twi_interrupt_entry, + 0, pdev->name, iface); + if (rc) { + dev_err(&pdev->dev, "Can't get IRQ %d !\n", iface->irq); + rc = -ENODEV; + goto out_error; + } + + /* Set TWI internal clock as 10MHz */ + clk_prepare_enable(iface->sclk); + if (rc) { + dev_err(&pdev->dev, "Could not enable sclk\n"); + goto out_error; + } + + writeValue = ((clk_get_rate(iface->sclk) / 1000 / 1000 + 5) / 10) & 0x7F; + iowrite16(writeValue, &iface->regs_base->control); + + /* + * We will not end up with a CLKDIV=0 because no one will specify + * 20kHz SCL or less in Kconfig now. (5 * 1000 / 20 = 250) + */ + clkhilow = ((10 * 1000 / iface->twi_clk) + 1) / 2; + + /* Set Twi interface clock as specified */ + writeValue = (clkhilow << 8) | clkhilow; + iowrite16(writeValue, &iface->regs_base->clkdiv); + + /* Enable TWI */ + writeValue = ioread16(&iface->regs_base->control) | TWI_ENA; + iowrite16(writeValue, &iface->regs_base->control); + + rc = i2c_add_numbered_adapter(p_adap); + if (rc < 0) + goto disable_clk; + + platform_set_drvdata(pdev, iface); + + dev_info(&pdev->dev, "ADI on-chip I2C TWI Controller, regs_base@%p\n", + iface->regs_base); + + return 0; + +disable_clk: + clk_disable_unprepare(iface->sclk); + +out_error: + return rc; +} + +static void i2c_adi_twi_remove(struct platform_device *pdev) +{ + struct adi_twi_iface *iface = platform_get_drvdata(pdev); + + clk_disable_unprepare(iface->sclk); + i2c_del_adapter(&(iface->adap)); +} + +static struct platform_driver i2c_adi_twi_driver = { + .probe = i2c_adi_twi_probe, + .remove = i2c_adi_twi_remove, + .driver = { + .name = "i2c-adi-twi", + .pm = I2C_ADI_TWI_PM_OPS, + .of_match_table = of_match_ptr(adi_twi_of_match), + }, +}; + +static int __init i2c_adi_twi_init(void) +{ + return platform_driver_register(&i2c_adi_twi_driver); +} + +static void __exit i2c_adi_twi_exit(void) +{ + platform_driver_unregister(&i2c_adi_twi_driver); +} + +subsys_initcall(i2c_adi_twi_init); +module_exit(i2c_adi_twi_exit); + +MODULE_AUTHOR("Bryan Wu, Sonic Zhang"); +MODULE_DESCRIPTION("ADI on-chip I2C TWI Controller Driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS("platform:i2c-adi-twi"); \ No newline at end of file From patchwork Thu Sep 12 18:25:01 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802435 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 8DD75EEE25C for ; Thu, 12 Sep 2024 18:20:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id 70EC4C4FDFB; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id 44DE0C4E697; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165216; bh=hqLKfdHAqsp9ubtvrEhSZkll8xQwV4IE1tn0OaSzusw=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=TuNxeGlgwVKz/YJpZgUWMzbRDtDYEboaVjUlEKcS2+wgLqz6ztXfxtPMRGFZqVbCH FB+LRvTghTeBCuVTpItqFOwLWAJQ2zLuVjA7AlekNdJLKITvPN9OAv8wjixp6TTApb G6dPauL0xsbsCxgHuUGhub98eMkgCC1M/RhbPYQLjl03VxLc1i7Hn+Ile6nfJhAH+V ZWaHu7cAz0Dn9T0nnxoKfc+xlD6CXjQ+Rlge+JRtL8afAVLk8Bin0hH+Q4UVTDAv5S QifGt/AbVtR3gnHUORcEolBkDzwwXMX0gRzPM2w5xjAZVzvT2uPyZKDtplhhFj/9Pb atvsp9pAD618g== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 380BBEEE25E; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:25:01 +0100 Subject: [PATCH 16/21] dt-bindings: i2c: add i2c/twi driver documentation MIME-Version: 1.0 Message-Id: <20240912-test-v1-16-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=2351; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=NgI2mAXMr6wvtJUHYjzwLK7MgsJEKL9nzTeZkQleGms=; b=vhXEAs59UNXXy2CwczdwdKItNi03+ogGqzUK0a77UzJPEDl1pzu4/spYs4pnuCUKynl1Z68j+ HK1C/dGXcNECHVI1d4QCirnLQUyMOWAsGojtV0CO7eu/mjENPi367XQ X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Add I2C driver bindings. Signed-off-by: Arturs Artamonovs Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- Documentation/devicetree/bindings/i2c/adi,twi.yaml | 71 ++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/Documentation/devicetree/bindings/i2c/adi,twi.yaml b/Documentation/devicetree/bindings/i2c/adi,twi.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e935b09066cf806c89a796fdd5fe73ee0b644432 --- /dev/null +++ b/Documentation/devicetree/bindings/i2c/adi,twi.yaml @@ -0,0 +1,71 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/i2c/adi,twi.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices I2C Peripheral for SC5XX Processor Family + +maintainers: + - Arturs Artamonovs + - Utsav Agarwal + +description: | + Analog Devices I2C Peripheral driver for SC5XX Processor Family + +properties: + compatible: + enum: + - adi,twi + + "#address-cells": + const: 1 + + "#size-cells": + const: 0 + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clock-khz: + $ref: /schemas/types.yaml#/definitions/uint32 + + clocks: + maxItems: 1 + + clock-names: + maxItems: 1 + +required: + - compatible + - "#address-cells" + - "#size-cells" + - reg + - interrupts + - clock-khz + - clocks + - clock-names + +additionalProperties: false + +examples: + - | + #include + #include + #include + + i2c0: twi@31001400 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "adi,twi"; + reg = <0x31001400 0xFF>; + interrupts = ; + clock-khz = <100>; + clocks = <&clk ADSP_SC598_CLK_CGU0_SCLK0>; + clock-names = "sclk0"; + status = "disabled"; + }; + From patchwork Thu Sep 12 18:25:02 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802443 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id A41E5EEE265 for ; Thu, 12 Sep 2024 18:20:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id 8914BC4FE06; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id 5C727C4FDF1; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165216; bh=08rrGrrtrIaYM4CMpLN0nNY+AYSy4V4IJi7+yk9IBFw=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=fJ9QlbYbHRLnMHPULtEOJ0e2dyh8bCG1lLkgzCKHvx2+4ItG+e5GwqSvK0gGC6Dvz MWV9l6ZJnTiM97tOQNE4x+yvbE5jgAZIDZMb+7n2Jbm5kWSIQeemelT8/CyzL8odhU mlM82PnoyR5Ua7aNXSpDZFUeDoPLcjAmhLW1+XYSCpeg5u+4nJ4fN5h3Hp3ZxJ160c C4JvkWQer15nFtFsmjj9pqcWgscSOj6/YdvoOsKyH8m8so5PKB3z/6A0ty4459gqha ADwgCQh5GXdefElXCaNe9Ubm2rtKmELuXegZWbCgrjqVpiYuJ5RWUzEcKdRORoxqaY NzDxUcFsGLWUw== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 515D9EEE262; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:25:02 +0100 Subject: [PATCH 17/21] serial: adi,uart: Add driver for ADI ADSP-SC5xx MIME-Version: 1.0 Message-Id: <20240912-test-v1-17-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=33930; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=DvfU37hVhNRYyO5LsqnmjnpDiC1h7qtXUog11TyP7jU=; b=0KuNbaB56olmWmG84P2NmiyQHkuKcGe6oUbE6QlhJ6tbw60h0Ep2p2GQW6yt33YyWU77NGXeL UFpsqgEJ09RAZ0Stfq1t/07WCFGtWNpHsTAJ3zAg+gmy3x+Mvqc83Ns X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Adding UART driver,supports all ADSP-SC5xx SoC family - Support FIFO mode - Support earlyprintk - Support Enable Divide By One support, for higher clock resolutions. Signed-off-by: Arturs Artamonovs Signed-off-by: Utsav Agarwal Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- drivers/tty/serial/Kconfig | 19 +- drivers/tty/serial/Makefile | 1 + drivers/tty/serial/adi_uart.c | 1045 ++++++++++++++++++++++++++++++++++++++ include/uapi/linux/serial_core.h | 3 + 4 files changed, 1067 insertions(+), 1 deletion(-) diff --git a/drivers/tty/serial/Kconfig b/drivers/tty/serial/Kconfig index 28e4beeabf8f373fc76e09ea7d1c9d55a66f4964..1d1d8fc808969c721d5931127d9294fb17d9c249 100644 --- a/drivers/tty/serial/Kconfig +++ b/drivers/tty/serial/Kconfig @@ -471,6 +471,23 @@ config SERIAL_SA1100_CONSOLE your boot loader (lilo or loadlin) about how to pass options to the kernel at boot time.) +config SERIAL_ADI_UART + tristate "ADI uart serial port support" + depends on ARCH_SC59X = y || ARCH_SC59X_64 = y + select SERIAL_CORE + select SERIAL_CORE_CONSOLE + help + Add support for the built-in adi uart driver. + +config SERIAL_ADI_UART_CONSOLE + bool "Console on ADI uart serial port" + depends on SERIAL_ADI_UART + default y + select SERIAL_CORE_CONSOLE + help + If you have enabled the ADI UART serial port, you can + make it the console by answering Y to this option. + config SERIAL_IMX tristate "IMX serial port support" depends on ARCH_MXC || COMPILE_TEST @@ -771,7 +788,7 @@ config SERIAL_CPM depends on CPM2 || CPM1 select SERIAL_CORE help - This driver supports the SCC and SMC serial ports on Motorola + This driver supports the SCC and SMC serial ports on Motorola embedded PowerPC that contain a CPM1 (8xx) or CPM2 (8xxx) config SERIAL_CPM_CONSOLE diff --git a/drivers/tty/serial/Makefile b/drivers/tty/serial/Makefile index 6ff74f0a9530c4f6e058a848f74084f3b63a730a..9d4920b51b55af70c285d9bcaef53cc01a69b898 100644 --- a/drivers/tty/serial/Makefile +++ b/drivers/tty/serial/Makefile @@ -49,6 +49,7 @@ obj-$(CONFIG_SERIAL_JSM) += jsm/ obj-$(CONFIG_SERIAL_LANTIQ) += lantiq.o obj-$(CONFIG_SERIAL_LITEUART) += liteuart.o obj-$(CONFIG_SERIAL_HS_LPC32XX) += lpc32xx_hs.o +obj-$(CONFIG_SERIAL_ADI_UART) += adi_uart.o obj-$(CONFIG_SERIAL_MAX3100) += max3100.o obj-$(CONFIG_SERIAL_MAX310X) += max310x.o obj-$(CONFIG_SERIAL_MCF) += mcf.o diff --git a/drivers/tty/serial/adi_uart.c b/drivers/tty/serial/adi_uart.c new file mode 100644 index 0000000000000000000000000000000000000000..dfbc7dcfd6169a299d4b1580e56f5ba0a3d8cc12 --- /dev/null +++ b/drivers/tty/serial/adi_uart.c @@ -0,0 +1,1045 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * ADI On-Chip Two Wire Interface Driver + * + * Copyright 2022-2024 - Analog Devices Inc. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(CONFIG_SERIAL_ADI_UART_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ) +#define SUPPORT_SYSRQ +#endif + +#define DRIVER_NAME "adi-uart" + +struct adi_uart_serial_port { + struct uart_port port; + struct device *dev; + unsigned int old_status; + int tx_irq; + int rx_irq; + int status_irq; + unsigned int lsr; + unsigned int hwflow_mode; + struct gpio_desc *hwflow_en_pin; + bool hwflow_en; + /* Use enable-divide-by-one in divisor? */ + bool edbo; + struct clk *clk; +}; + +#define ADI_UART_NO_HWFLOW 0 +#define ADI_UART_HWFLOW_PERI 1 + +#define ADI_UART_NR_PORTS 4 +static struct adi_uart_serial_port *adi_uart_serial_ports[ADI_UART_NR_PORTS]; + +/* UART_CTL Masks */ +#define UCEN 0x1 /* Enable UARTx Clocks */ +#define LOOP_ENA 0x2 /* Loopback Mode Enable */ +#define UMOD_MDB 0x10 /* Enable MDB Mode */ +#define UMOD_IRDA 0x20 /* Enable IrDA Mode */ +#define UMOD_MASK 0x30 /* Uart Mode Mask */ +#define WLS(x) (((x-5) & 0x03) << 8) /* Word Length Select */ +#define WLS_MASK 0x300 /* Word length Select Mask */ +#define WLS_OFFSET 8 /* Word length Select Offset */ +#define STB 0x1000 /* Stop Bits */ +#define STBH 0x2000 /* Half Stop Bits */ +#define PEN 0x4000 /* Parity Enable */ +#define EPS 0x8000 /* Even Parity Select */ +#define STP 0x10000 /* Stick Parity */ +#define FPE 0x20000 /* Force Parity Error On Transmit */ +#define FFE 0x40000 /* Force Framing Error On Transmit */ +#define SB 0x80000 /* Set Break */ +#define LCR_MASK (SB | STP | EPS | PEN | STB | WLS_MASK) +#define FCPOL 0x400000 /* Flow Control Pin Polarity */ +#define RPOLC 0x800000 /* IrDA RX Polarity Change */ +#define TPOLC 0x1000000 /* IrDA TX Polarity Change */ +#define MRTS 0x2000000 /* Manual Request To Send */ +#define XOFF 0x4000000 /* Transmitter Off */ +#define ARTS 0x8000000 /* Automatic Request To Send */ +#define ACTS 0x10000000 /* Automatic Clear To Send */ +#define RFIT 0x20000000 /* Receive FIFO IRQ Threshold */ +#define RFRT 0x40000000 /* Receive FIFO RTS Threshold */ + +/* UART_STAT Masks */ +#define DR 0x01 /* Data Ready */ +#define OE 0x02 /* Overrun Error */ +#define PE 0x04 /* Parity Error */ +#define FE 0x08 /* Framing Error */ +#define BI 0x10 /* Break Interrupt */ +#define THRE 0x20 /* THR Empty */ +#define TEMT 0x80 /* TSR and UART_THR Empty */ +#define TFI 0x100 /* Transmission Finished Indicator */ + +#define ASTKY 0x200 /* Address Sticky */ +#define ADDR 0x400 /* Address bit status */ +#define RO 0x800 /* Reception Ongoing */ +#define SCTS 0x1000 /* Sticky CTS */ +#define CTS 0x10000 /* Clear To Send */ +#define RFCS 0x20000 /* Receive FIFO Count Status */ + +/* UART_CLOCK Masks */ +#define EDBO 0x80000000 /* Enable Devide by One */ + +/* UART_IER Masks */ +#define ERBFI 0x01 /* Enable Receive Buffer Full Interrupt */ +#define ETBEI 0x02 /* Enable Transmit Buffer Empty Interrupt */ +#define ELSI 0x04 /* Enable RX Status Interrupt */ +#define EDSSI 0x08 /* Enable Modem Status Interrupt */ +#define EDTPTI 0x10 /* Enable DMA Transmit PIRQ Interrupt */ +#define ETFI 0x20 /* Enable Transmission Finished Interrupt */ +#define ERFCI 0x40 /* Enable Receive FIFO Count Interrupt */ + +# define OFFSET_REDIV 0x00 /* Version ID Register */ +# define OFFSET_CTL 0x04 /* Control Register */ +# define OFFSET_STAT 0x08 /* Status Register */ +# define OFFSET_SCR 0x0C /* SCR Scratch Register */ +# define OFFSET_CLK 0x10 /* Clock Rate Register */ +# define OFFSET_IER 0x14 /* Interrupt Enable Register */ +# define OFFSET_IER_SET 0x18 /* Set Interrupt Enable Register */ +# define OFFSET_IER_CLEAR 0x1C /* Clear Interrupt Enable Register */ +# define OFFSET_RBR 0x20 /* Receive Buffer register */ +# define OFFSET_THR 0x24 /* Transmit Holding register */ + +#define UART_GET_CHAR(p) readl(p->port.membase + OFFSET_RBR) +#define UART_GET_CLK(p) readl(p->port.membase + OFFSET_CLK) +#define UART_GET_CTL(p) readl(p->port.membase + OFFSET_CTL) +#define UART_GET_GCTL(p) UART_GET_CTL(p) +#define UART_GET_LCR(p) UART_GET_CTL(p) +#define UART_GET_MCR(p) UART_GET_CTL(p) +#define UART_GET_STAT(p) readl(p->port.membase + OFFSET_STAT) +#define UART_GET_MSR(p) UART_GET_STAT(p) + +#define UART_PUT_CHAR(p, v) writel(v, p->port.membase + OFFSET_THR) +#define UART_PUT_CLK(p, v) writel(v, p->port.membase + OFFSET_CLK) +#define UART_PUT_CTL(p, v) writel(v, p->port.membase + OFFSET_CTL) +#define UART_PUT_GCTL(p, v) UART_PUT_CTL(p, v) +#define UART_PUT_LCR(p, v) UART_PUT_CTL(p, v) +#define UART_PUT_MCR(p, v) UART_PUT_CTL(p, v) +#define UART_PUT_STAT(p, v) writel(v, p->port.membase + OFFSET_STAT) + +#define UART_CLEAR_IER(p, v) writel(v, p->port.membase + OFFSET_IER_CLEAR) +#define UART_GET_IER(p) readl(p->port.membase + OFFSET_IER) +#define UART_SET_IER(p, v) writel(v, p->port.membase + OFFSET_IER_SET) + +#define UART_CLEAR_LSR(p) UART_PUT_STAT(p, -1) +#define UART_GET_LSR(p) UART_GET_STAT(p) +#define UART_PUT_LSR(p, v) UART_PUT_STAT(p, v) + +/* This handles hard CTS/RTS */ +#define UART_CLEAR_SCTS(p) UART_PUT_STAT(p, SCTS) +#define UART_GET_CTS(x) (UART_GET_MSR(x) & CTS) +#define UART_DISABLE_RTS(x) UART_PUT_MCR(x, UART_GET_MCR(x) & ~(ARTS | MRTS)) +#define UART_ENABLE_RTS(x) UART_PUT_MCR(x, UART_GET_MCR(x) | MRTS | ARTS) +#define UART_ENABLE_INTS(x, v) UART_SET_IER(x, v) +#define UART_DISABLE_INTS(x) UART_CLEAR_IER(x, 0xF) + +#define DMA_RX_XCOUNT 512 +#define DMA_RX_YCOUNT (PAGE_SIZE / DMA_RX_XCOUNT) + +#define DMA_RX_FLUSH_JIFFIES (msecs_to_jiffies(50)) + + +static void adi_uart_serial_tx_chars(struct adi_uart_serial_port *uart); +static void adi_uart_serial_reset_irda(struct uart_port *port); + + +static struct adi_uart_serial_port *to_adi_serial_port(struct uart_port *port) +{ + return container_of(port, struct adi_uart_serial_port, port); +} + +static unsigned int adi_uart_serial_get_mctrl(struct uart_port *port) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + + if (!uart->hwflow_mode || !uart->hwflow_en) + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; + + /* CTS PIN is negative assertive. */ + if (UART_GET_CTS(uart)) + return TIOCM_CTS | TIOCM_DSR | TIOCM_CAR; + else + return TIOCM_DSR | TIOCM_CAR; +} + +static void adi_uart_serial_set_mctrl(struct uart_port *port, + unsigned int mctrl) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + + if (!uart->hwflow_mode || !uart->hwflow_en) + return; + + /* RTS PIN is negative assertive. */ + if (mctrl & TIOCM_RTS) + UART_ENABLE_RTS(uart); + else + UART_DISABLE_RTS(uart); +} + +/* + * Handle any change of modem status signal. + */ +static irqreturn_t adi_uart_serial_mctrl_cts_int(int irq, void *dev_id) +{ + struct adi_uart_serial_port *uart = dev_id; + unsigned int status = adi_uart_serial_get_mctrl(&uart->port); + struct tty_struct *tty = uart->port.state->port.tty; + + if (uart->hwflow_mode == ADI_UART_HWFLOW_PERI) { + UART_CLEAR_SCTS(uart); + if (tty->hw_stopped) { + if (status) { + tty->hw_stopped = 0; + uart_write_wakeup(&uart->port); + } + } else { + if (!status) + tty->hw_stopped = 1; + } + } + + uart_handle_cts_change(&uart->port, status & TIOCM_CTS); + + return IRQ_HANDLED; +} + +/* + * interrupts are disabled on entry + */ +static void adi_uart_serial_stop_tx(struct uart_port *port) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + + while (!(UART_GET_LSR(uart) & TEMT)) + cpu_relax(); + + UART_PUT_LSR(uart, TFI); + UART_CLEAR_IER(uart, ETBEI); +} + +/* + * port is locked and interrupts are disabled + */ +static void adi_uart_serial_start_tx(struct uart_port *port) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + struct tty_struct *tty = uart->port.state->port.tty; + + /* + * To avoid losting RX interrupt, we reset IR function + * before sending data. + */ + if (tty->termios.c_line == N_IRDA) + adi_uart_serial_reset_irda(port); + + UART_SET_IER(uart, ETBEI); + adi_uart_serial_tx_chars(uart); +} + +/* + * Interrupts are enabled + */ +static void adi_uart_serial_stop_rx(struct uart_port *port) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + + UART_CLEAR_IER(uart, ERBFI); +} + +/* + * Set the modem control timer to fire immediately. + */ +static void adi_uart_serial_enable_ms(struct uart_port *port) +{ +} + +static void adi_uart_serial_rx_chars(struct adi_uart_serial_port *uart) +{ + unsigned int status, ch, flg; + + status = UART_GET_LSR(uart); + UART_CLEAR_LSR(uart); + + ch = UART_GET_CHAR(uart); + uart->port.icount.rx++; + + if (status & BI) { + uart->port.icount.brk++; + if (uart_handle_break(&uart->port)) + goto ignore_char; + status &= ~(PE | FE); + } + if (status & PE) + uart->port.icount.parity++; + if (status & OE) + uart->port.icount.overrun++; + if (status & FE) + uart->port.icount.frame++; + + status &= uart->port.read_status_mask; + + if (status & BI) + flg = TTY_BREAK; + else if (status & PE) + flg = TTY_PARITY; + else if (status & FE) + flg = TTY_FRAME; + else + flg = TTY_NORMAL; + + if (uart_handle_sysrq_char(&uart->port, ch)) + goto ignore_char; + + uart_insert_char(&uart->port, status, OE, ch, flg); + + ignore_char: + tty_flip_buffer_push(&uart->port.state->port); +} + +static void adi_uart_serial_tx_chars(struct adi_uart_serial_port *uart) +{ + struct tty_port *tport = &uart->port.state->port; + unsigned char c; + + if (kfifo_is_empty(&tport->xmit_fifo) || uart_tx_stopped(&uart->port)) { + /* Clear TFI bit */ + UART_PUT_LSR(uart, TFI); + /* Anomaly notes: + * 05000215 - we always clear ETBEI within last UART TX + * interrupt to end a string. It is always set + * when start a new tx. + */ + UART_CLEAR_IER(uart, ETBEI); + return; + } + + if (uart->port.x_char) { + UART_PUT_CHAR(uart, uart->port.x_char); + uart->port.icount.tx++; + uart->port.x_char = 0; + } + + if (UART_GET_LSR(uart) & THRE) { + /* pop data from fifo */ + if (kfifo_get(&tport->xmit_fifo, &c)) { + UART_PUT_CHAR(uart, c); + uart->port.icount.tx++; + } + } + + if (kfifo_len(&tport->xmit_fifo) < WAKEUP_CHARS) + uart_write_wakeup(&uart->port); +} + +static irqreturn_t adi_uart_serial_rx_int(int irq, void *dev_id) +{ + struct adi_uart_serial_port *uart = dev_id; + + while (UART_GET_LSR(uart) & DR) + adi_uart_serial_rx_chars(uart); + + return IRQ_HANDLED; +} + +static irqreturn_t adi_uart_serial_tx_int(int irq, void *dev_id) +{ + struct adi_uart_serial_port *uart = dev_id; + + spin_lock(&uart->port.lock); + if (UART_GET_LSR(uart) & THRE) + adi_uart_serial_tx_chars(uart); + spin_unlock(&uart->port.lock); + + return IRQ_HANDLED; +} + +/* + * Return TIOCSER_TEMT when transmitter is not busy. + */ +static unsigned int adi_uart_serial_tx_empty(struct uart_port *port) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + unsigned int lsr; + + lsr = UART_GET_LSR(uart); + if (lsr & TEMT) + return TIOCSER_TEMT; + else + return 0; +} + +static void adi_uart_serial_break_ctl(struct uart_port *port, int break_state) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + u32 lcr = UART_GET_LCR(uart); + + if (break_state) + lcr |= SB; + else + lcr &= ~SB; + UART_PUT_LCR(uart, lcr); +} + +static int adi_uart_serial_startup(struct uart_port *port) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + int ret; + + ret = clk_prepare_enable(uart->clk); + if (ret) + return ret; + + if (uart->hwflow_mode == ADI_UART_HWFLOW_PERI) { + /* CTS RTS PINs are negative assertive. */ + UART_PUT_MCR(uart, UART_GET_MCR(uart) | ACTS); + UART_SET_IER(uart, EDSSI); + } + + UART_SET_IER(uart, ERBFI); + return 0; +} + +static void adi_uart_serial_shutdown(struct uart_port *port) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + + dev_dbg(uart->dev, "in serial_shutdown\n"); + + clk_disable_unprepare(uart->clk); +} + +static void adi_uart_serial_set_termios(struct uart_port *port, + struct ktermios *termios, const struct ktermios *old) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + unsigned long flags; + unsigned int baud, quot; + unsigned int ier, lcr = 0; + unsigned long timeout; + + if (uart->hwflow_mode == ADI_UART_HWFLOW_PERI) + termios->c_cflag |= CRTSCTS; + + switch (termios->c_cflag & CSIZE) { + case CS8: + lcr = WLS(8); + break; + case CS7: + lcr = WLS(7); + break; + case CS6: + lcr = WLS(6); + break; + case CS5: + lcr = WLS(5); + break; + default: + dev_err(port->dev, "%s: word length not supported\n", + __func__); + } + + if (termios->c_cflag & CSTOPB) + lcr |= STB; + if (termios->c_cflag & PARENB) + lcr |= PEN; + if (!(termios->c_cflag & PARODD)) + lcr |= EPS; + if (termios->c_cflag & CMSPAR) + lcr |= STP; + if (termios->c_cflag & CRTSCTS) + uart->hwflow_en = true; + else + uart->hwflow_en = false; + + spin_lock_irqsave(&uart->port.lock, flags); + + port->read_status_mask = OE; + if (termios->c_iflag & INPCK) + port->read_status_mask |= (FE | PE); + if (termios->c_iflag & (BRKINT | PARMRK)) + port->read_status_mask |= BI; + + /* + * Characters to ignore + */ + port->ignore_status_mask = 0; + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= FE | PE; + if (termios->c_iflag & IGNBRK) { + port->ignore_status_mask |= BI; + /* + * If we're ignoring parity and break indicators, + * ignore overruns too (for real raw support). + */ + if (termios->c_iflag & IGNPAR) + port->ignore_status_mask |= OE; + } + + /* + * uart_get_divisor has a hardcoded /16 factor that will cause integer + * round off errors if we're in divide-by-one mode + */ + if (uart->edbo) { + baud = uart_get_baud_rate(port, termios, old, 0, + port->uartclk); + quot = EDBO | DIV_ROUND_CLOSEST(port->uartclk, baud); + } else { + baud = uart_get_baud_rate(port, termios, old, 0, + port->uartclk/16); + quot = uart_get_divisor(port, baud); + } + + /* Wait till the transfer buffer is empty */ + timeout = jiffies + msecs_to_jiffies(10); + while (UART_GET_GCTL(uart) & UCEN && !(UART_GET_LSR(uart) & TEMT)) + if (time_after(jiffies, timeout)) { + dev_warn(port->dev, + "timeout waiting for TX buffer empty\n"); + break; + } + + /* Wait till the transfer buffer is empty */ + timeout = jiffies + msecs_to_jiffies(10); + while (UART_GET_GCTL(uart) & UCEN && !(UART_GET_LSR(uart) & TEMT)) + if (time_after(jiffies, timeout)) { + dev_warn(port->dev, + "timeout waiting for TX buffer empty\n"); + break; + } + + /* Disable UART */ + ier = UART_GET_IER(uart); + UART_PUT_GCTL(uart, UART_GET_GCTL(uart) & ~UCEN); + UART_DISABLE_INTS(uart); + + UART_PUT_CLK(uart, quot); + + UART_PUT_LCR(uart, (UART_GET_LCR(uart) & ~LCR_MASK) | lcr); + + /* Enable UART */ + UART_ENABLE_INTS(uart, ier); + UART_PUT_GCTL(uart, UART_GET_GCTL(uart) | UCEN); + + /* Port speed changed, update the per-port timeout. */ + uart_update_timeout(port, termios->c_cflag, baud); + + spin_unlock_irqrestore(&uart->port.lock, flags); +} + +static const char *adi_uart_serial_type(struct uart_port *port) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + + return uart->port.type == PORT_BFIN ? "ADI-UART" : NULL; +} + +/* + * Release the memory region(s) being used by 'port'. + */ +static void adi_uart_serial_release_port(struct uart_port *port) +{ +} + +/* + * Request the memory region(s) being used by 'port'. + */ +static int adi_uart_serial_request_port(struct uart_port *port) +{ + return 0; +} + +/* + * Configure/autoconfigure the port. + */ +static void adi_uart_serial_config_port(struct uart_port *port, int flags) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + + if (flags & UART_CONFIG_TYPE && + adi_uart_serial_request_port(&uart->port) == 0) + uart->port.type = PORT_BFIN; +} + +/* + * Verify the new serial_struct (for TIOCSSERIAL). + * The only change we allow are to the flags and type, and + * even then only between PORT_BFIN and PORT_UNKNOWN + */ +static int +adi_uart_serial_verify_port(struct uart_port *port, struct serial_struct *ser) +{ + return 0; +} + +/* + * Enable the IrDA function if tty->ldisc.num is N_IRDA. + * In other cases, disable IrDA function. + */ +static void adi_uart_serial_set_ldisc(struct uart_port *port, + struct ktermios *termios) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + unsigned int val; + + switch (termios->c_line) { + case N_IRDA: + val = UART_GET_GCTL(uart); + val |= (UMOD_IRDA | RPOLC); + UART_PUT_GCTL(uart, val); + break; + default: + val = UART_GET_GCTL(uart); + val &= ~(UMOD_MASK | RPOLC); + UART_PUT_GCTL(uart, val); + } +} + +static void adi_uart_serial_reset_irda(struct uart_port *port) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + unsigned int val; + + val = UART_GET_GCTL(uart); + val &= ~(UMOD_MASK | RPOLC); + UART_PUT_GCTL(uart, val); + val |= (UMOD_IRDA | RPOLC); + UART_PUT_GCTL(uart, val); +} + +#ifdef CONFIG_CONSOLE_POLL +static void adi_uart_serial_poll_put_char(struct uart_port *port, + unsigned char chr) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + + while (!(UART_GET_LSR(uart) & THRE)) + cpu_relax(); + + UART_PUT_CHAR(uart, (unsigned char)chr); +} + +static int adi_uart_serial_poll_get_char(struct uart_port *port) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + unsigned char chr; + + while (!(UART_GET_LSR(uart) & DR)) + cpu_relax(); + + chr = UART_GET_CHAR(uart); + + return chr; +} +#endif + + +static const struct uart_ops adi_uart_serial_pops = { + .tx_empty = adi_uart_serial_tx_empty, + .set_mctrl = adi_uart_serial_set_mctrl, + .get_mctrl = adi_uart_serial_get_mctrl, + .stop_tx = adi_uart_serial_stop_tx, + .start_tx = adi_uart_serial_start_tx, + .stop_rx = adi_uart_serial_stop_rx, + .enable_ms = adi_uart_serial_enable_ms, + .break_ctl = adi_uart_serial_break_ctl, + .startup = adi_uart_serial_startup, + .shutdown = adi_uart_serial_shutdown, + .set_termios = adi_uart_serial_set_termios, + .set_ldisc = adi_uart_serial_set_ldisc, + .type = adi_uart_serial_type, + .release_port = adi_uart_serial_release_port, + .request_port = adi_uart_serial_request_port, + .config_port = adi_uart_serial_config_port, + .verify_port = adi_uart_serial_verify_port, +#ifdef CONFIG_CONSOLE_POLL + .poll_put_char = adi_uart_serial_poll_put_char, + .poll_get_char = adi_uart_serial_poll_get_char, +#endif +}; + +#ifdef CONFIG_SERIAL_ADI_UART_CONSOLE +static void adi_uart_serial_console_putchar(struct uart_port *port, + unsigned char ch) +{ + struct adi_uart_serial_port *uart = to_adi_serial_port(port); + + while (!(UART_GET_LSR(uart) & THRE)) + barrier(); + UART_PUT_CHAR(uart, ch); +} + +static void __init +adi_uart_serial_console_get_options(struct adi_uart_serial_port *uart, + int *baud, int *parity, int *bits) +{ + unsigned int status; + + status = UART_GET_IER(uart) & (ERBFI | ETBEI); + if (status == (ERBFI | ETBEI)) { + /* ok, the port was enabled */ + u32 lcr, clk; + + lcr = UART_GET_LCR(uart); + + *parity = 'n'; + if (lcr & PEN) { + if (lcr & EPS) + *parity = 'e'; + else + *parity = 'o'; + } + *bits = ((lcr & WLS_MASK) >> WLS_OFFSET) + 5; + + clk = UART_GET_CLK(uart); + + /* Only the lowest 16 bits are the divisor */ + if (clk & EDBO) + *baud = uart->port.uartclk / (clk & 0xffff); + else + *baud = uart->port.uartclk / (16*clk); + } + pr_debug("%s:baud = %d, parity = %c, bits= %d\n", __func__, + *baud, *parity, *bits); +} + +static void +adi_uart_serial_console_write(struct console *co, const char *s, + unsigned int count) +{ + struct adi_uart_serial_port *uart = adi_uart_serial_ports[co->index]; + unsigned long flags; + + spin_lock_irqsave(&uart->port.lock, flags); + uart_console_write(&uart->port, s, count, + adi_uart_serial_console_putchar); + spin_unlock_irqrestore(&uart->port.lock, flags); + +} + +static int __init +adi_uart_serial_console_setup(struct console *co, char *options) +{ + struct adi_uart_serial_port *uart; + int baud = 115200; + int bits = 8; + int parity = 'n'; + int flow = 'n'; + + /* + * Check whether an invalid uart number has been specified, and + * if so, search for the first available port that does have + * console support. + */ + if (co->index < 0 || co->index >= ADI_UART_NR_PORTS) + return -ENODEV; + + uart = adi_uart_serial_ports[co->index]; + if (!uart) + return -ENODEV; + + if (uart->hwflow_mode == ADI_UART_HWFLOW_PERI) + flow = 'r'; + + if (options) + uart_parse_options(options, &baud, &parity, &bits, &flow); + else + adi_uart_serial_console_get_options(uart, &baud, &parity, + &bits); + + return uart_set_options(&uart->port, co, baud, parity, bits, flow); +} + +static struct uart_driver adi_uart_serial_reg; + +static struct console adi_uart_serial_console = { + .name = "ttySC", + .write = adi_uart_serial_console_write, + .device = uart_console_device, + .setup = adi_uart_serial_console_setup, + .flags = CON_PRINTBUFFER, + .index = -1, + .data = &adi_uart_serial_reg, +}; + + +#define ADI_SERIAL_UART_CONSOLE (&adi_uart_serial_console) +#else +#define ADI_SERIAL_UART_CONSOLE NULL +#endif + +static struct uart_driver adi_uart_serial_reg = { + .owner = THIS_MODULE, + .driver_name = DRIVER_NAME, + .dev_name = "ttySC", + .major = TTY_MAJOR, +#ifdef CONFIG_ARCH_SC59X_64 + // Other serial drivers are using 64 -- + // Can probably disable in the future and set this back to 64 + .minor = 74, +#else + .minor = 64, +#endif + .nr = ADI_UART_NR_PORTS, + .cons = ADI_SERIAL_UART_CONSOLE, +}; + +static int adi_uart_serial_suspend(struct platform_device *pdev, + pm_message_t state) +{ + struct adi_uart_serial_port *uart = platform_get_drvdata(pdev); + + clk_disable(uart->clk); + return uart_suspend_port(&adi_uart_serial_reg, &uart->port); +} + +static int adi_uart_serial_resume(struct platform_device *pdev) +{ + struct adi_uart_serial_port *uart = platform_get_drvdata(pdev); + int ret; + + ret = clk_enable(uart->clk); + if (ret) + return ret; + + return uart_resume_port(&adi_uart_serial_reg, &uart->port); +} + +static int adi_uart_serial_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct adi_uart_serial_port *uart = NULL; + int ret = 0; + int uartid; + dev_info(dev, "Serial probe\n"); + + uartid = of_alias_get_id(np, "serial"); + + if (uartid < 0) { + dev_err(&pdev->dev, "failed to get alias/pdev id, errno %d\n", + uartid); + ret = -ENODEV; + return ret; + } + + if (adi_uart_serial_ports[uartid] == NULL) { + uart = kzalloc(sizeof(*uart), GFP_KERNEL); + if (!uart) + return -ENOMEM; + + adi_uart_serial_ports[uartid] = uart; + uart->dev = &pdev->dev; + + uart->clk = devm_clk_get(dev, "sclk0"); + if (IS_ERR(uart->clk)) + return -ENODEV; + + spin_lock_init(&uart->port.lock); + uart->port.uartclk = clk_get_rate(uart->clk); + uart->port.fifosize = 8; + uart->port.ops = &adi_uart_serial_pops; + uart->port.line = uartid; + uart->port.iotype = UPIO_MEM; + uart->port.flags = UPF_BOOT_AUTOCONF; + + uart->port.membase = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(uart->port.membase)) + return PTR_ERR(uart->port.membase); + + uart->tx_irq = platform_get_irq_byname(pdev, "tx"); + uart->rx_irq = platform_get_irq_byname(pdev, "rx"); + uart->status_irq = + platform_get_irq_byname(pdev, "status"); + uart->port.irq = uart->rx_irq;// + ret = devm_request_threaded_irq(dev, uart->rx_irq, + adi_uart_serial_rx_int, NULL, 0, "ADI UART RX", + uart); + if (ret) { + dev_err(dev, "Unable to attach UART RX int\n"); + return ret; + } + + ret = devm_request_threaded_irq(dev, uart->tx_irq, + adi_uart_serial_tx_int, NULL, 0, "ADI UART TX", + uart); + if (ret) { + dev_err(dev, "Unable to attach UART TX int\n"); + return ret; + } + + /* adi,uart-has-rtscts is deprecated */ + if (of_property_read_bool(np, "uart-has-rtscts") || + of_property_read_bool(np, "adi,uart-has-rtscts")) { + uart->hwflow_mode = ADI_UART_HWFLOW_PERI; + ret = devm_request_threaded_irq(dev, uart->status_irq, + adi_uart_serial_mctrl_cts_int, NULL, 0, + "ADI UART Modem Status", + uart); + if (ret) { + uart->hwflow_mode = ADI_UART_NO_HWFLOW; + dev_info(dev, + "Unable to attach UART Modem Status int.\n"); + } + } else + uart->hwflow_mode = ADI_UART_NO_HWFLOW; + + uart->edbo = false; + if (of_property_read_bool(np, "adi,use-edbo")) + uart->edbo = true; + + if (uart->hwflow_mode == ADI_UART_HWFLOW_PERI) { + uart->hwflow_en_pin = devm_gpiod_get(dev, "hwflow-en", + GPIOD_OUT_HIGH); + if (IS_ERR(uart->hwflow_en_pin)) { + dev_err(dev, + "hwflow-en required in peripheral hwflow mode\n"); + return PTR_ERR(uart->hwflow_en_pin); + } + } + } + + uart = adi_uart_serial_ports[uartid]; + uart->port.dev = &pdev->dev; + dev_set_drvdata(&pdev->dev, uart); + + ret = uart_add_one_port(&adi_uart_serial_reg, &uart->port); + if (!ret) + return 0; + + if (uart) { + adi_uart_serial_ports[uartid] = NULL; + kfree(uart); + } + + return ret; +} + +static void adi_uart_serial_remove(struct platform_device *pdev) +{ + struct adi_uart_serial_port *uart = platform_get_drvdata(pdev); + + dev_set_drvdata(&pdev->dev, NULL); + + if (uart) { + uart_remove_one_port(&adi_uart_serial_reg, &uart->port); + adi_uart_serial_ports[uart->port.line] = NULL; + kfree(uart); + } +} + +static const struct of_device_id adi_uart_dt_match[] = { + { .compatible = "adi,uart"}, + {}, +}; +MODULE_DEVICE_TABLE(of, adi_uart_dt_match); + +static struct platform_driver adi_uart_serial_driver = { + .probe = adi_uart_serial_probe, + .remove = adi_uart_serial_remove, + .suspend = adi_uart_serial_suspend, + .resume = adi_uart_serial_resume, + .driver = { + .name = DRIVER_NAME, + .owner = THIS_MODULE, + .of_match_table = adi_uart_dt_match, + }, +}; + +static int __init adi_uart_serial_init(void) +{ + int ret; + + pr_info("ADI serial driver\n"); + + ret = uart_register_driver(&adi_uart_serial_reg); + if (ret) { + pr_err("failed to register %s:%d\n", + adi_uart_serial_reg.driver_name, ret); + } + + ret = platform_driver_register(&adi_uart_serial_driver); + if (ret) { + pr_err("fail to register ADI uart\n"); + uart_unregister_driver(&adi_uart_serial_reg); + } + + return ret; +} + +static void __exit adi_uart_serial_exit(void) +{ + platform_driver_unregister(&adi_uart_serial_driver); + uart_unregister_driver(&adi_uart_serial_reg); +} + +module_init(adi_uart_serial_init); +module_exit(adi_uart_serial_exit); + +/* Early Console Support */ +static inline u32 adi_uart_read(struct uart_port *port, u32 off) +{ + return readl(port->membase + off); +} + +static inline void adi_uart_write(struct uart_port *port, u32 val, + u32 off) +{ + writel(val, port->membase + off); +} + + +static void adi_uart_wait_bit_set(struct uart_port *port, unsigned int offset, + u32 bit) +{ + while (!(adi_uart_read(port, offset) & bit)) + cpu_relax(); +} + + +static void adi_uart_console_putchar(struct uart_port *port, unsigned char ch) +{ + /* wait for the hardware fifo to clear up */ + adi_uart_wait_bit_set(port, OFFSET_STAT, THRE); + + /* queue the character for transmission */ + adi_uart_write(port, ch, OFFSET_THR); +} + + +static void adi_uart_early_write(struct console *con, const char *s, + unsigned int n) +{ + struct earlycon_device *dev = con->data; + + uart_console_write(&dev->port, s, n, adi_uart_console_putchar); +} + + +static int __init adi_uart_early_console_setup(struct earlycon_device *device, + const char *opt) +{ + if (!device->port.membase) + return -ENODEV; + + device->con->write = adi_uart_early_write; + return 0; +} + +EARLYCON_DECLARE(adi_uart, adi_uart_early_console_setup); + +MODULE_AUTHOR("Sonic Zhang, Aubrey Li"); +MODULE_DESCRIPTION("Blackfin/ADSP generic serial port driver"); +MODULE_LICENSE("GPL v2"); +MODULE_ALIAS_CHARDEV_MAJOR(BFIN_SERIAL_MAJOR); \ No newline at end of file diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h index 9c007a106330b90b92cbcf60a9ac806b290d6d44..ce3c50dfa5cacd09eb30e93e408c2d92992ac755 100644 --- a/include/uapi/linux/serial_core.h +++ b/include/uapi/linux/serial_core.h @@ -109,6 +109,9 @@ /* Xilinx uartlite */ #define PORT_UARTLITE 74 +/* Blackfin */ +#define PORT_BFIN 75 + /* Broadcom BCM7271 UART */ #define PORT_BCM7271 76 From patchwork Thu Sep 12 18:25:03 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802438 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id AD82FEEE268 for ; Thu, 12 Sep 2024 18:20:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id B9D65C4FE8D; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id 78E6CC4FE02; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165216; bh=XyPBNJcfsateLZqZDmqJXaqUGmKQFBsDRF55C4LG0T0=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=TcCXaNCYW0BDNvMJHeqsLBHwik+5OsspXU5I71ENbZi2qdd52UN/hiTye4I/r6+06 BczIjQodK0HLtfegCi4WuhflNmfDloWMv7XpXvjk4SBjTQ68LZUOc9U92ecOGMwZLK BQayujEvoKmTa8tSxPRemXhec1hi2arbm+F3PATppFX1oSnpekdCH5Ifsd+n9yPdGC 5Em6vfyV/tVj3IiFmZZW3EfAFtONgfOe0aPMOf6lmtFGI3gtbrVUFI+WT1YrJjwfKI lY41wq8Rz4q/N1sO7S519s+9CPl0fPqUVFKqzXZDNpt7Xw+bPJGbLP2Np4IFGILmn7 r4rI4NG8EyY4Q== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 675A5EEE265; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:25:03 +0100 Subject: [PATCH 18/21] dt-bindings: serial: adi,uart4: add adi,uart4 driver documentation MIME-Version: 1.0 Message-Id: <20240912-test-v1-18-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=2919; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=oBF3dIbaQwuAcAPatmm8KzhpEcd5bQSZY83uCgqBwSQ=; b=6j/X3JDP4zFMAEkkyqLnHXSrm0oSB9HRqbPcKNXW4rw81mCvOqQoSN+pNHFxk+ahdUEzGmu5D 5MfHyd0g+Q/DvdFqQ+DrXNJjkag80B9sLtGo27C10DPMpx3J/zt0gBB X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Add serial driver bindings. Signed-off-by: Arturs Artamonovs Signed-off-by: Utsav Agarwal Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- .../devicetree/bindings/serial/adi,uart.yaml | 85 ++++++++++++++++++++++ 1 file changed, 85 insertions(+) diff --git a/Documentation/devicetree/bindings/serial/adi,uart.yaml b/Documentation/devicetree/bindings/serial/adi,uart.yaml new file mode 100644 index 0000000000000000000000000000000000000000..de58059efa7e21acaa5b7f4984ffadca18f7f53a --- /dev/null +++ b/Documentation/devicetree/bindings/serial/adi,uart.yaml @@ -0,0 +1,85 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/serial/adi,uart4.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Analog Devices UART Driver for SC5XX-family processors + +maintainers: + - Arturs Artamonovs + - Utsav Agarwal + +description: | + Analog Devices UART Driver for SC59X-family processors + +properties: + compatible: + enum: + - adi,uart + + reg: + maxItems: 1 + + dmas: + maxItems: 2 + minItems: 2 + description: TX and RX DMA cluster numbers + + dma-names: + maxItems: 2 + minItems: 2 + description: DMA channel names (tx and rx) + + clocks: + maxItems: 1 + description: Clock being used for UART + + clock-names: + maxItems: 1 + description: Clock name (sclk0) + + interrupt-names: + minItems: 3 + maxItems: 3 + description: Interrupt names (tx + rx + status) + + interrupts: + minItems: 3 + maxItems: 3 + description: GIC interrupt numbers + + adi,use-edbo: + type: boolean + description: Enable divide by one in divisor + +required: + - compatible + - reg + - clocks + - clock-names + - interrupt-names + - interrupts + +additionalProperties: false + +examples: + - | + #include + #include + #include + + uart0: uart@31003000 { + compatible = "adi,uart"; + reg = <0x31003000 0x40>; + clocks = <&clk ADSP_SC598_CLK_CGU0_SCLK0>; + clock-names = "sclk0"; + interrupt-parent = <&gic>; + interrupt-names = "tx", "rx", "status"; + interrupts = , + , + ; + adi,use-edbo; + status = "disabled"; + }; + From patchwork Thu Sep 12 18:25:04 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802442 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id BA3D0EEE269 for ; Thu, 12 Sep 2024 18:20:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id C1F32C4FE13; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id 875F0C4CED6; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165216; bh=Uy8WNAx6IRK53oIlJahJOHkFJeKhttmrw7rJBLYAZg4=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=KCbvWJvQXBKPt/3N6EJK395t1RFtsSgRBrbMorNTTVWcNwHAjmpmLUhPmPuHWvlfJ OMzclv8El/nh5ANu123HtdMwDbE2se3siQAYnBnaGKo3Rod+687Xo46Anq5CPV+Rdz h34gHP+A+5DJBUMvt9POIJqglP4ymBe139il8bZFJVjehSg7wE/VdVbpDQFmBf+q/7 +8y/4+4vPtJlBq+4ZfWyujgh0YH2fY4rYTMZ/FaGjlaN9nPLqgOIPBwTYqtNc6MNLH cmrt9Ws2ISwAR3ghT4YJnVt5uJ396pbVMmMArmFf9WPHY8MLKyv8RsQeFY/gI+3tXX AeB/6cXncqD3w== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 7A251EEE25E; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:25:04 +0100 Subject: [PATCH 19/21] arm64: dts: adi: sc598: add device tree MIME-Version: 1.0 Message-Id: <20240912-test-v1-19-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=13434; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=gZ+wPY1K1a7sq4LeaCpBlN6tpl7SEpOopm4S3bwpUQA=; b=LellgcuHUtjW5aI+l3dgRIs3S8FDlJkEZjSmYdG+kzYhFaNnnbVyTz8Cs6grSon5O4P3Heoak xbl6R7IXYa/BBGSIf3jYe9dA5WvlAmmLt0gDUViR3rYOnukCVcGIfNP X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Add ADI SC598-EZKIT device tree. Support UART console as output. Signed-off-by: Arturs Artamonovs Signed-off-by: Utsav Agarwal Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- arch/arm64/boot/dts/Makefile | 1 + arch/arm64/boot/dts/adi/Makefile | 2 + arch/arm64/boot/dts/adi/sc598-som-ezkit.dts | 14 ++ arch/arm64/boot/dts/adi/sc598-som.dtsi | 58 +++++ arch/arm64/boot/dts/adi/sc59x-64.dtsi | 367 ++++++++++++++++++++++++++++ 5 files changed, 442 insertions(+) diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile index 21cd3a87f385309c3a655a67a3bee5f0abed7545..9b3996a8e01d8e7d264c44c075d7a50ee350ba44 100644 --- a/arch/arm64/boot/dts/Makefile +++ b/arch/arm64/boot/dts/Makefile @@ -1,5 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 subdir-y += actions +subdir-y += adi subdir-y += airoha subdir-y += allwinner subdir-y += altera diff --git a/arch/arm64/boot/dts/adi/Makefile b/arch/arm64/boot/dts/adi/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..1bf54bc97095e1ea3577953d379746fbc0ea02a9 --- /dev/null +++ b/arch/arm64/boot/dts/adi/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +dtb-$(CONFIG_ARCH_SC59X_64) += sc598-som-ezkit.dtb diff --git a/arch/arm64/boot/dts/adi/sc598-som-ezkit.dts b/arch/arm64/boot/dts/adi/sc598-som-ezkit.dts new file mode 100644 index 0000000000000000000000000000000000000000..a8db6d5ea764f917faa6839d3d4f0b5217b927b8 --- /dev/null +++ b/arch/arm64/boot/dts/adi/sc598-som-ezkit.dts @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2021-2024 - Analog Devices Inc. + * Author: Nathan Barrett-Morrison + */ + +/dts-v1/; + +#include "sc598-som.dtsi" + +/ { + model = "ADI 64-bit SC598 SOM EZ Kit"; + compatible = "adi,sc598-som-ezkit", "adi,sc59x-64"; +}; diff --git a/arch/arm64/boot/dts/adi/sc598-som.dtsi b/arch/arm64/boot/dts/adi/sc598-som.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..3b90f367db1a24de1e1dddc4db3c219736c5b90f --- /dev/null +++ b/arch/arm64/boot/dts/adi/sc598-som.dtsi @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2021-2024 - Analog Devices Inc. + * Author: Nathan Barrett-Morrison + */ + +/dts-v1/; + +#include +#include +#include "sc59x-64.dtsi" + +/ { + chosen { + stdout-path = &uart1; + bootargs = "earlycon=adi_uart,0x31003000 console=ttySC0,115200 mem=224M"; + }; + + memory@90000000 { + device_type = "memory"; + reg = <0x90000000 0x0e000000>; + }; + + memory@20040000 { + device_type = "memory"; + reg = <0x20040000 0x40000>; + }; + + scb: scb-bus { + sec: sec@31089000 { + adi,sharc-cores = <2>; + }; + }; + +}; + +&uart0 { + pinctrl-0 = <&uart0_default>; + pinctrl-names = "default"; + status = "okay"; +}; + +&i2c0 { + status = "okay"; +}; + +&i2c1 { + status = "disabled"; +}; + +&pinctrl0 { + uart0_default: uart0-default-pins { + pins { + pinmux = , + ; + }; + }; +}; diff --git a/arch/arm64/boot/dts/adi/sc59x-64.dtsi b/arch/arm64/boot/dts/adi/sc59x-64.dtsi new file mode 100644 index 0000000000000000000000000000000000000000..4a9aa08b4acb0936c97e683562e05da063a4e193 --- /dev/null +++ b/arch/arm64/boot/dts/adi/sc59x-64.dtsi @@ -0,0 +1,367 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR MIT) +/* + * Copyright 2021-2024 - Analog Devices Inc. + * Author: Nathan Barrett-Morrison + */ + +#include +#include +#include + +/ { + model = "ADI 64-bit SC59X"; + compatible = "adi,sc59x-64"; + + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + chosen { }; + + aliases { + serial0 = &uart0; + serial2 = &uart2; + serial3 = &uart3; + }; + + cpus { + #address-cells = <0x2>; + #size-cells = <0x0>; + + cpu0: cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a55"; + reg = <0x0 0x0>; + enable-method = "spin-table"; + cpu-release-addr = <0x0 0xdeadbeef>; + clocks = <&clk ADSP_SC598_CLK_ARM>, <&clk ADSP_SC598_CLK_DDR>; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = ; + interrupt-parent = <&gic>; + }; + + gic: interrupt-controller@31200000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0x31200000 0x40000>, /* GIC Dist */ + <0x31240000 0x40000>; /* GICR */ + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , /* Physical Secure */ + , /* Physical Non-Secure */ + , /* Virtual */ + ; /* Hypervisor */ + }; + + clocks { + sys_clkin0: oscillator@1 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + clock-output-names = "sys_clkin0"; + }; + + sys_clkin1: oscillator@2 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25000000>; + clock-output-names = "sys_clkin1"; + }; + }; + + clk: clocks@3108d000 { + compatible = "adi,sc598-clocks"; + reg = <0x3108d000 0x1000>, + <0x3108e000 0x1000>, + <0x3108f000 0x1000>, + <0x310a9000 0x1000>; + #clock-cells = <1>; + clocks = <&sys_clkin0>, <&sys_clkin1>; + clock-names = "sys_clkin0", "sys_clkin1"; + status = "okay"; + }; + + scb: scb-bus { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + rcu: rcu@3108c000 { + compatible = "adi,reset-controller"; + reg = <0x3108c000 0x1000>; + status = "okay"; + }; + + sec: sec@31089000 { + compatible = "adi,system-event-controller"; + reg = <0x31089000 0x1000>; + adi,rcu = <&rcu>; + status = "okay"; + }; + + uart0: uart@31003000 { + compatible = "adi,uart"; + reg = <0x31003000 0x40>; + clocks = <&clk ADSP_SC598_CLK_CGU0_SCLK0>; + clock-names = "sclk0"; + interrupt-parent = <&gic>; + interrupt-names = "tx", "rx", "status"; + interrupts = , + , + ; + adi,use-edbo; + status = "disabled"; + }; + + uart1: uart@31003400 { + compatible = "adi,uart"; + reg = <0x31003400 0x40>; + clocks = <&clk ADSP_SC598_CLK_CGU0_SCLK0>; + clock-names = "sclk0"; + interrupt-parent = <&gic>; + interrupt-names = "tx", "rx", "status"; + interrupts = , + , + ; + adi,use-edbo; + status = "disabled"; + }; + + uart2: uart@31003800 { + compatible = "adi,uart"; + reg = <0x31003800 0x40>; + clocks = <&clk ADSP_SC598_CLK_CGU0_SCLK0>; + clock-names = "sclk0"; + interrupt-parent = <&gic>; + interrupt-names = "tx", "rx", "status"; + interrupts = , + , + ; + adi,use-edbo; + status = "disabled"; + }; + + uart3: uart@31003c00 { + compatible = "adi,uart"; + reg = <0x31003C00 0x40>; + clocks = <&clk ADSP_SC598_CLK_CGU0_SCLK0>; + clock-names = "sclk0"; + interrupt-parent = <&gic>; + interrupt-names = "tx", "rx", "status"; + interrupts = , + , + ; + adi,use-edbo; + status = "disabled"; + }; + + i2c0: twi@31001400 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "adi,twi"; + reg = <0x31001400 0xFF>; + interrupts = ; + clock-khz = <100>; + clocks = <&clk ADSP_SC598_CLK_CGU0_SCLK0>; + clock-names = "sclk0"; + status = "disabled"; + }; + + i2c1: twi@31001500 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "adi,twi"; + reg = <0x31001500 0xFF>; + interrupts = ; + clock-khz = <100>; + clocks = <&clk ADSP_SC598_CLK_CGU0_SCLK0>; + clock-names = "sclk0"; + status = "disabled"; + }; + + i2c3: twi@31001000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "adi,twi"; + reg = <0x31001000 0xFF>; + interrupts = ; + clock-khz = <100>; + clocks = <&clk ADSP_SC598_CLK_CGU0_SCLK0>; + clock-names = "sclk0"; + status = "disabled"; + }; + + i2c4: twi@31001100 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "adi,twi"; + reg = <0x31001100 0xFF>; + interrupts = ; + clock-khz = <100>; + clocks = <&clk ADSP_SC598_CLK_CGU0_SCLK0>; + clock-names = "sclk0"; + status = "disabled"; + }; + + i2c5: twi@31001200 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "adi,twi"; + reg = <0x31001200 0xFF>; + interrupts = ; + clock-khz = <100>; + clocks = <&clk ADSP_SC598_CLK_CGU0_SCLK0>; + clock-names = "sclk0"; + status = "disabled"; + }; + + pinctrl0: pinctrl@31004600 { + compatible = "adi,adsp-pinctrl"; + #address-cells = <1>; + #size-cells = <1>; + reg = <0x31004600 0x400>; + adi,port-sizes = <16 16 16 16 16 16 16 16 7>; + }; + + pint0: pint@31005000 { + compatible = "adi,adsp-pint"; + reg = <0x31005000 0xFF>; + interrupts = ; + }; + + pint1: pint@31005100 { + compatible = "adi,adsp-pint"; + reg = <0x31005100 0xFF>; + interrupts = ; + }; + + pint2: pint@31005200 { + compatible = "adi,adsp-pint"; + reg = <0x31005200 0xFF>; + interrupts = ; + }; + + pint3: pint@31005300 { + compatible = "adi,adsp-pint"; + reg = <0x31005300 0xFF>; + interrupts = ; + }; + + pint4: pint@31005400 { + compatible = "adi,adsp-pint"; + reg = <0x31005400 0xFF>; + interrupts = ; + }; + + pint5: pint@31005500 { + compatible = "adi,adsp-pint"; + reg = <0x31005500 0xFF>; + interrupts = ; + }; + + pint6: pint@31005600 { + compatible = "adi,adsp-pint"; + reg = <0x31005600 0xFF>; + interrupts = ; + }; + + pint7: pint@31005700 { + compatible = "adi,adsp-pint"; + reg = <0x31005700 0xFF>; + interrupts = ; + }; + + gpa: gport@31004000 { + compatible = "adi,adsp-port-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x31004000 0x7F>; + gpio-ranges = <&pinctrl0 0 0 16>; + adi,pint = <&pint0 1>; + status = "okay"; + }; + + gpb: gport@31004080 { + compatible = "adi,adsp-port-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x31004080 0x7F>; + gpio-ranges = <&pinctrl0 0 16 16>; + adi,pint = <&pint0 0>; + status = "okay"; + }; + + gpc: gport@31004100 { + compatible = "adi,adsp-port-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x31004100 0x7F>; + gpio-ranges = <&pinctrl0 0 32 16>; + adi,pint = <&pint2 1>; + status = "okay"; + }; + + gpd: gport@31004180 { + compatible = "adi,adsp-port-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x31004180 0x7F>; + gpio-ranges = <&pinctrl0 0 48 16>; + adi,pint = <&pint2 0>; + }; + + gpe: gport@31004200 { + compatible = "adi,adsp-port-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x31004200 0x7F>; + gpio-ranges = <&pinctrl0 0 64 16>; + adi,pint = <&pint4 1>; + }; + + gpf: gport@31004280 { + compatible = "adi,adsp-port-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x31004280 0x7F>; + gpio-ranges = <&pinctrl0 0 80 16>; + adi,pint = <&pint4 0>; + }; + + gpg: gport@31004300 { + compatible = "adi,adsp-port-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x31004300 0x7F>; + gpio-ranges = <&pinctrl0 0 96 16>; + adi,pint = <&pint6 1>; + }; + + gph: gport@31004380 { + compatible = "adi,adsp-port-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x31004380 0x7F>; + gpio-ranges = <&pinctrl0 0 112 16>; + adi,pint = <&pint6 0>; + }; + + gpi: gport@31004400 { + compatible = "adi,adsp-port-gpio"; + gpio-controller; + #gpio-cells = <2>; + reg = <0x31004400 0x7F>; + gpio-ranges = <&pinctrl0 0 128 7>; + adi,pint = <&pint7 1>; + }; + + }; +}; From patchwork Thu Sep 12 18:25:05 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802436 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id C563DEEE266 for ; Thu, 12 Sep 2024 18:20:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id CE200C4CEDB; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id 9A9EFC4FE14; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165216; bh=OpMw8H1Uy7VJPtjkQlzz7ECyPIAIof/IYlkKaagHA0A=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=G4O9Ae/lhd1rutXXY24q0dKWpQIomRNl4m214Bfu2bgdMVx9xfHnb+6c3TUJBevKd mzZS/aoukhzlJ9KJko4M4o9GMvySthPWYCYNudpA5CKbr1K+kD2bR9fmojrUCka/CE TB/JhSMymx2DDrOu4xq9lmrY4UU+CXM/R4CesDogkazfKSGGiTyIWWDGcuf4dus1EL QCj194O54v1+mKNXilv+3ZFCHWpn3A9wHw5l8owgjyzYwSnxkuzVdAAFY8XT5U/R1b HgilmUrTGjYdX3WB3V6WsKvK8UeNwmM97+PxBku2AjqmrXkCB0XslEVr8Vsue5+CQE NiY0Ny6lhEUng== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id 90CB5EEE25C; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:25:05 +0100 Subject: [PATCH 20/21] arm64: defconfig: sc598 add minimal changes MIME-Version: 1.0 Message-Id: <20240912-test-v1-20-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs , Nathan Barrett-Morrison X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=2190; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=MHsHd+C/PIZW+6c/4XvADztERNqdGgexUrpmw/8Uj1o=; b=ckE38LhnghBiz6ehY1LUpgPtxnhxp0i91l16hEWoTdfUkJhwgYv0et/QDYoVF7isUu1LLusPS 15YeKF/PimUDG9n6SDxoWDjeMljd29/pxhd07rkP9NiynxSaD1LZVEI X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Add ADSP-SC598 defconfig Signed-off-by: Arturs Artamonovs Co-developed-by: Utsav Agarwal Signed-off-by: Utsav Agarwal Co-developed-by: Nathan Barrett-Morrison Signed-off-by: Nathan Barrett-Morrison Co-developed-by: Greg Malysa Signed-off-by: Greg Malysa --- arch/arm64/configs/defconfig | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/arch/arm64/configs/defconfig b/arch/arm64/configs/defconfig index 362df939026383a26ee23485d1ec25b252b90d5d..7801dd7d7d65bc504dc6e2945f92f261f2911115 100644 --- a/arch/arm64/configs/defconfig +++ b/arch/arm64/configs/defconfig @@ -67,6 +67,7 @@ CONFIG_ARCH_SEATTLE=y CONFIG_ARCH_INTEL_SOCFPGA=y CONFIG_ARCH_STM32=y CONFIG_ARCH_SYNQUACER=y +CONFIG_ARCH_SC59X_64=y CONFIG_ARCH_TEGRA=y CONFIG_ARCH_TESLA_FSD=y CONFIG_ARCH_SPRD=y @@ -473,6 +474,7 @@ CONFIG_SERIAL_8250_OMAP=y CONFIG_SERIAL_8250_MT6577=y CONFIG_SERIAL_8250_UNIPHIER=y CONFIG_SERIAL_OF_PLATFORM=y +CONFIG_SERIAL_ADI_UART=y CONFIG_SERIAL_AMBA_PL011=y CONFIG_SERIAL_AMBA_PL011_CONSOLE=y CONFIG_SERIAL_MESON=y @@ -513,6 +515,7 @@ CONFIG_TCG_TIS_I2C_CR50=m CONFIG_TCG_TIS_I2C_INFINEON=y CONFIG_I2C_CHARDEV=y CONFIG_I2C_MUX=y +CONFIG_I2C_ADI_TWI=y CONFIG_I2C_MUX_PCA954x=y CONFIG_I2C_BCM2835=m CONFIG_I2C_CADENCE=m @@ -539,6 +542,7 @@ CONFIG_I2C_UNIPHIER_F=y CONFIG_I2C_RCAR=y CONFIG_I2C_CROS_EC_TUNNEL=y CONFIG_SPI=y +CONFIG_SPI_ADI=y CONFIG_SPI_ARMADA_3700=y CONFIG_SPI_BCM2835=m CONFIG_SPI_BCM2835AUX=m @@ -637,6 +641,7 @@ CONFIG_PINCTRL_SM8450_LPASS_LPI=m CONFIG_PINCTRL_SC8280XP_LPASS_LPI=m CONFIG_PINCTRL_SM8550_LPASS_LPI=m CONFIG_PINCTRL_SM8650_LPASS_LPI=m +CONFIG_GPIO_ADI_ADSP_PORT=y CONFIG_GPIO_ALTERA=m CONFIG_GPIO_DAVINCI=y CONFIG_GPIO_DWAPB=y @@ -1512,6 +1517,7 @@ CONFIG_RESET_QCOM_AOSS=y CONFIG_RESET_QCOM_PDC=m CONFIG_RESET_RZG2L_USBPHY_CTRL=y CONFIG_RESET_TI_SCI=y +CONFIG_RESET_SC5XX=y CONFIG_PHY_XGENE=y CONFIG_PHY_CAN_TRANSCEIVER=m CONFIG_PHY_SUN4I_USB=y From patchwork Thu Sep 12 18:25:06 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Arturs Artamonovs via B4 Relay X-Patchwork-Id: 13802439 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from smtp.kernel.org (aws-us-west-2-korg-mail-1.web.codeaurora.org [10.30.226.201]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id CF614EEE26B for ; Thu, 12 Sep 2024 18:20:18 +0000 (UTC) Received: by smtp.kernel.org (Postfix) id E45D1C4FEAD; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) Received: by smtp.kernel.org (Postfix) with ESMTPS id B8BEAC4CEE3; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1726165216; bh=jlvQUaKEx+59D4zMJ2VEo/4rnH6uQhVLJwiDjIYuoc8=; h=From:Date:Subject:References:In-Reply-To:List-Id:To:Cc:Reply-To: From; b=YwEi/qWyNVN03erS9kYbYazeMREWmBKVEmXOBTumGhNZ1nMji0X0pt6foalxNjUBI NzOEj0z6eaBJeGDgdEIL+5Oq36IO4v1G+Bm5PW+CFi3UF7bvJaprD5HsHLJ7WFIjhU vOcavCR98i2SS2fiSqMhlq4ixsMM8ToWaRxpE6N0REgWw3wkymsTq2KiDLwH5kfNIS LE5b9T1EzXe9ggaM5DHcIRcFBAlBv9N1zI0xBQI4LsFncxwJgD+Nntor+3fWpwwmRp YtzL9fLQb39TsDpoqd8lFJKofQzcbz9otwNikSSYz0XEIEVeNtmSxyIKi5KCD9EcP4 Q+fd5UAjEoF0Q== Received: from aws-us-west-2-korg-lkml-1.web.codeaurora.org (localhost.localdomain [127.0.0.1]) by smtp.lore.kernel.org (Postfix) with ESMTP id A7FC4EEE266; Thu, 12 Sep 2024 18:20:16 +0000 (UTC) From: Arturs Artamonovs via B4 Relay Date: Thu, 12 Sep 2024 19:25:06 +0100 Subject: [PATCH 21/21] MAINTAINERS: add adi sc5xx maintainers MIME-Version: 1.0 Message-Id: <20240912-test-v1-21-458fa57c8ccf@analog.com> References: <20240912-test-v1-0-458fa57c8ccf@analog.com> In-Reply-To: <20240912-test-v1-0-458fa57c8ccf@analog.com> List-Id: To: Catalin Marinas , Will Deacon , Greg Malysa , Philipp Zabel , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Utsav Agarwal , Michael Turquette , Stephen Boyd , Linus Walleij , Bartosz Golaszewski , Thomas Gleixner , Andi Shyti , Greg Kroah-Hartman , Jiri Slaby , Arnd Bergmann , Olof Johansson , soc@kernel.org Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, devicetree@vger.kernel.org, linux-clk@vger.kernel.org, linux-gpio@vger.kernel.org, linux-i2c@vger.kernel.org, linux-serial@vger.kernel.org, Arturs Artamonovs , adsp-linux@analog.com, Arturs Artamonovs X-Mailer: b4 0.15-dev-7be4f X-Developer-Signature: v=1; a=ed25519-sha256; t=1726165513; l=1504; i=arturs.artamonovs@analog.com; s=20240909; h=from:subject:message-id; bh=ZX6op8Gl0ef751bz5sRIH6+njR4ucuUIQX34HP/CQPA=; b=pw/W2wutLhh9kjOUSW6Xi3shvGEIMdgfhziVLJ7XQep5S3spWFWEsh5/dHPurSL35z/aVl4R/ CbMlfycTJiNBWb3FgLJgU0x5+zMcX0/B+lU1ZvH6q/u84D7efC3RSP0 X-Developer-Key: i=arturs.artamonovs@analog.com; a=ed25519; pk=UXODIid/MrmBXvqkX4PeEfetDaNAw9xKMINHIc5oZCk= X-Endpoint-Received: by B4 Relay for arturs.artamonovs@analog.com/20240909 with auth_id=206 X-Original-From: Arturs Artamonovs Reply-To: arturs.artamonovs@analog.com From: Arturs Artamonovs Add ADSP-SC598 maitaniners Signed-off-by: Arturs Artamonovs --- MAINTAINERS | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 10430778c998b57944c1a6c5f07d676127e47faa..a838a5392321602034755fafed720f68d3798c0b 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1934,6 +1934,28 @@ S: Odd Fixes F: arch/arm/boot/dts/airoha/ F: arch/arm64/boot/dts/airoha/ +ARM/ADI SoC Support +M: Arturs Artamonovs +M: Greg Malysa +S: Maintained +F: Documentation/devicetree/bindings/arm/analog/adi,sc5xx.yaml +F: Documentation/devicetree/bindings/clock/adi,sc5xx-clocks.yaml +F: Documentation/devicetree/bindings/gpio/adi,adsp-port-gpio.yaml +F: Documentation/devicetree/bindings/i2c/adi,twi.yaml +F: Documentation/devicetree/bindings/interrupt-controller/adi,adsp-pint.yaml +F: Documentation/devicetree/bindings/pinctrl/adi,adsp-pinctrl.yaml +F: Documentation/devicetree/bindings/serial/adi,uart.yaml +F: Documentation/devicetree/bindings/serial/adi,uart.yaml +F: Documentation/devicetree/bindings/soc/adi/* +F: arch/arm64/boot/dts/adi/* +F: drivers/clk/adi/* +F: drivers/gpio/gpio-adi-adsp-port.c +F: drivers/i2c/busses/i2c-adi-twi.c +F: drivers/irqchip/irq-adi-adsp.c +F: drivers/soc/adi/* +F: drivers/tty/serial/adi_uart.c + + ARM/Allwinner SoC Clock Support M: Emilio López S: Maintained