Received: by 2002:a05:7412:40d:b0:e2:908c:2ebd with SMTP id 13csp950739rdf; Wed, 22 Nov 2023 01:05:02 -0800 (PST) X-Google-Smtp-Source: AGHT+IFp3rJDsrBenT7Dy9P96UFxCUzHELD5myzIKTf28QmoE/8fpPdoBTbrOB7PMxH4DzGc1ZQE X-Received: by 2002:a05:6a20:938c:b0:18b:8b4:2dd9 with SMTP id x12-20020a056a20938c00b0018b08b42dd9mr1762311pzh.35.1700643902124; Wed, 22 Nov 2023 01:05:02 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1700643902; cv=none; d=google.com; s=arc-20160816; b=UHEO6rUzSCoyEOKvZ6ZqAsZDJZ/kBO46wVQqIJzrqjRrOrd2oRg1bOejTs5RRnnrgH wBqEjTZcP64JivXEAHxEAf5N9gXS6hsv/2F8X/FwxzYpj5Z7v1AZqJjhA5ryiJSIbolx k05VD79Lh47MHCLCpnWnVX4wuMqzVKFuC2yUY+GwhQRRYpEjqDb+EZyLTc2LcvYi43cz IOrSStgviV3zSRcK9nUFxjz3+StxaxWbbV/p5usUwmx7q9aX5UW/Chq4VX9uftgD4KML FNfJga+99BM/HJwrmxCkN1ypVMh+/LEUewRVA4o6hOsD4Mv3xcRg2hLDpJj7WVW24fsS uS7w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:reply-to:cc:to:in-reply-to:references:message-id :content-transfer-encoding:mime-version:subject:date:from :dkim-signature; bh=TfvzEWywnB0NZ6j8shLWmFZtcn4SvP449EtrdXuq0n0=; fh=JlRzWZb9FvEKVRA6Kb6oH98r23VApwMsuo+i03AjrPc=; b=YXA2jsgdTd6/Ui3dnEt/tl+IXzHI3hqJsEJvKh6nTDLi6s8Lo+rDIc5HwgyKmtbeGH m4pa2m44KLyaUoX/I2uLepKMJrrm5z8J7HSvVnMeJKC38cL1gwWkAAdSiH/RJ28LFRG2 8kAzrjl3TPaTdHhWn5fC1gCXwqHKj+Vq6u0REdlpR60iVWSQQ1r0JDNMfjyXq77SAEMi F8LbNYAQIFpdFqdbayhGY1Ie9kOakV+TRXSmnrAY3Bh7brxRHvzdlbABSKHNrD984udK PPMz/OuABjTXhjz2BUG1cj8uOWN2yNHt9aBaBaF/R7fIMVSHjpsJlhRFn+zNx4v7/Zhx fZJg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=fRz2HLWf; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from lipwig.vger.email (lipwig.vger.email. [23.128.96.33]) by mx.google.com with ESMTPS id lt16-20020a17090b355000b00280feff8f0fsi1007141pjb.127.2023.11.22.01.05.01 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 22 Nov 2023 01:05:02 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) client-ip=23.128.96.33; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=k20201202 header.b=fRz2HLWf; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.33 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: from out1.vger.email (depot.vger.email [IPv6:2620:137:e000::3:0]) by lipwig.vger.email (Postfix) with ESMTP id B3DE4809E8FD; Wed, 22 Nov 2023 01:02:44 -0800 (PST) X-Virus-Status: Clean X-Virus-Scanned: clamav-milter 0.103.11 at lipwig.vger.email Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1343656AbjKVJB6 (ORCPT + 99 others); Wed, 22 Nov 2023 04:01:58 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47042 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S235088AbjKVJBV (ORCPT ); Wed, 22 Nov 2023 04:01:21 -0500 Received: from smtp.kernel.org (relay.kernel.org [52.25.139.140]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 021FB19D for ; Wed, 22 Nov 2023 01:01:16 -0800 (PST) Received: by smtp.kernel.org (Postfix) with ESMTPS id AF1DCC433BA; Wed, 22 Nov 2023 09:01:14 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1700643674; bh=+7OkVINihAgvy6tC1a+r9qStIpsvCKAEbAK1CyygbvM=; h=From:Date:Subject:References:In-Reply-To:To:Cc:Reply-To:From; b=fRz2HLWfIej1EUqIhkRnY9zGPSMY/AFzUTt5ogiCYs2vrrS3q+7zwYOKwym8MXUv5 CCEuzCaAjGZqgTarqImj0ou3Iz3LgXdCnzrS7ZB4vvO0lF4o8lzC1yaGVe7nk3I481 bwsPgoODHubZYkFUuuUW+msTXhouITLmwRq4slGLKrtH2SLBvazCqI2rJQNDSq4HOw 9yEGXIy/FgXr4Vi6A6rgsDjPosbxjfe9Els1sIUXqPS7JfBF8InVEOBWhMbd9G1uel 4uGPzb+hygDt+5w/gwa1RdzCHDhcdlmCsjtGFVnemKlfVU+1s0HJTtpNIB7pVORFzB cfyMV2zJSfakA== 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 9CDB7C61D96; Wed, 22 Nov 2023 09:01:14 +0000 (UTC) From: Nikita Shubin via B4 Relay Date: Wed, 22 Nov 2023 11:59:45 +0300 Subject: [PATCH v5 07/39] soc: Add SoC driver for Cirrus ep93xx MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit Message-Id: <20231122-ep93xx-v5-7-d59a76d5df29@maquefel.me> References: <20231122-ep93xx-v5-0-d59a76d5df29@maquefel.me> In-Reply-To: <20231122-ep93xx-v5-0-d59a76d5df29@maquefel.me> To: Conor Dooley , Joel Stanley , Ulf Hansson , Linus Walleij , Nikita Shubin , Huisong Li , =?utf-8?q?Jonathan_Neusch=C3=A4fer?= , Walker Chen , Arnd Bergmann , Emil Renner Berthing , Alexander Sverdlin Cc: Hal Feng , linux-kernel@vger.kernel.org, Alexander Sverdlin X-Mailer: b4 0.13-dev-e3e53 X-Developer-Signature: v=1; a=ed25519-sha256; t=1700643671; l=9535; i=nikita.shubin@maquefel.me; s=20230718; h=from:subject:message-id; bh=492Hz1SLrKJT3wrDoldgmUFnxDuoicaeq4JYJHEpza0=; =?utf-8?q?b=3DFL4Xy2kCiYoV?= =?utf-8?q?gtaTYR3NKH1VrdDE0Ys3YNcn+QPhr/tE5o1m8tN31NIEqj7TvncjJjOGoZKDpvRC?= dM6N73eoC4wjKfXIKWZ6l+8PRSfCZuzsrGn8/VpuZgji9hB+y9ve X-Developer-Key: i=nikita.shubin@maquefel.me; a=ed25519; pk=vqf5YIUJ7BJv3EJFaNNxWZgGuMgDH6rwufTLflwU9ac= X-Endpoint-Received: by B4 Relay for nikita.shubin@maquefel.me/20230718 with auth_id=65 X-Original-From: Nikita Shubin Reply-To: X-Spam-Status: No, score=-1.2 required=5.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,MAILING_LIST_MULTI, SPF_HELO_NONE,SPF_PASS,T_SCC_BODY_TEXT_LINE autolearn=unavailable autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lipwig.vger.email Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org X-Greylist: Sender passed SPF test, not delayed by milter-greylist-4.6.4 (lipwig.vger.email [0.0.0.0]); Wed, 22 Nov 2023 01:02:45 -0800 (PST) From: Nikita Shubin Add an SoC driver for the ep93xx. Currently there is only one thing not fitting into any other framework, and that is the swlock setting. Used for clock settings, pinctrl and restart. Signed-off-by: Nikita Shubin Tested-by: Alexander Sverdlin Acked-by: Alexander Sverdlin Reviewed-by: Linus Walleij --- drivers/soc/Kconfig | 1 + drivers/soc/Makefile | 1 + drivers/soc/cirrus/Kconfig | 13 +++ drivers/soc/cirrus/Makefile | 2 + drivers/soc/cirrus/soc-ep93xx.c | 247 ++++++++++++++++++++++++++++++++++++++++ 5 files changed, 264 insertions(+) diff --git a/drivers/soc/Kconfig b/drivers/soc/Kconfig index 10a9ff84ff41..47692deb68e4 100644 --- a/drivers/soc/Kconfig +++ b/drivers/soc/Kconfig @@ -7,6 +7,7 @@ source "drivers/soc/aspeed/Kconfig" source "drivers/soc/atmel/Kconfig" source "drivers/soc/bcm/Kconfig" source "drivers/soc/canaan/Kconfig" +source "drivers/soc/cirrus/Kconfig" source "drivers/soc/fsl/Kconfig" source "drivers/soc/fujitsu/Kconfig" source "drivers/soc/hisilicon/Kconfig" diff --git a/drivers/soc/Makefile b/drivers/soc/Makefile index 0706a27d13be..6bfd520c325a 100644 --- a/drivers/soc/Makefile +++ b/drivers/soc/Makefile @@ -8,6 +8,7 @@ obj-y += aspeed/ obj-$(CONFIG_ARCH_AT91) += atmel/ obj-y += bcm/ obj-$(CONFIG_SOC_CANAAN) += canaan/ +obj-$(CONFIG_EP93XX_SOC) += cirrus/ obj-$(CONFIG_ARCH_DOVE) += dove/ obj-$(CONFIG_MACH_DOVE) += dove/ obj-y += fsl/ diff --git a/drivers/soc/cirrus/Kconfig b/drivers/soc/cirrus/Kconfig new file mode 100644 index 000000000000..fea3c3c82be0 --- /dev/null +++ b/drivers/soc/cirrus/Kconfig @@ -0,0 +1,13 @@ +# SPDX-License-Identifier: GPL-2.0 + +if ARCH_EP93XX + +config EP93XX_SOC + bool "Cirrus EP93xx chips SoC" + select SOC_BUS + select AUXILIARY_BUS + default y if !EP93XX_SOC_COMMON + help + Support SoC for Cirrus EP93xx chips. + +endif diff --git a/drivers/soc/cirrus/Makefile b/drivers/soc/cirrus/Makefile new file mode 100644 index 000000000000..ed6752844c6f --- /dev/null +++ b/drivers/soc/cirrus/Makefile @@ -0,0 +1,2 @@ +# SPDX-License-Identifier: GPL-2.0 +obj-y += soc-ep93xx.o diff --git a/drivers/soc/cirrus/soc-ep93xx.c b/drivers/soc/cirrus/soc-ep93xx.c new file mode 100644 index 000000000000..47211ac1e64f --- /dev/null +++ b/drivers/soc/cirrus/soc-ep93xx.c @@ -0,0 +1,247 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * SoC driver for Cirrus EP93xx chips. + * Copyright (C) 2022 Nikita Shubin + * + * Based on a rewrite of arch/arm/mach-ep93xx/core.c + * Copyright (C) 2006 Lennert Buytenhek + * Copyright (C) 2007 Herbert Valerio Riedel + * + * Thanks go to Michael Burian and Ray Lehtiniemi for their key + * role in the ep93xx Linux community + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#define EP93XX_SYSCON_DEVCFG 0x80 + +#define EP93XX_SWLOCK_MAGICK 0xaa +#define EP93XX_SYSCON_SWLOCK 0xc0 +#define EP93XX_SYSCON_SYSCFG 0x9c +#define EP93XX_SYSCON_SYSCFG_REV_MASK GENMASK(31, 28) +#define EP93XX_SYSCON_SYSCFG_REV_SHIFT 28 + +struct ep93xx_map_info { + spinlock_t lock; + void __iomem *base; + struct regmap *map; +}; + +/* + * EP93xx System Controller software locked register write + * + * Logic safeguards are included to condition the control signals for + * power connection to the matrix to prevent part damage. In addition, a + * software lock register is included that must be written with 0xAA + * before each register write to change the values of the four switch + * matrix control registers. + */ +static void ep93xx_regmap_write(struct regmap *map, spinlock_t *lock, + unsigned int reg, unsigned int val) +{ + unsigned long flags; + + spin_lock_irqsave(lock, flags); + + regmap_write(map, EP93XX_SYSCON_SWLOCK, EP93XX_SWLOCK_MAGICK); + regmap_write(map, reg, val); + + spin_unlock_irqrestore(lock, flags); +} + +static void ep93xx_regmap_update_bits(struct regmap *map, spinlock_t *lock, + unsigned int reg, unsigned int mask, + unsigned int val) +{ + unsigned long flags; + + spin_lock_irqsave(lock, flags); + + regmap_write(map, EP93XX_SYSCON_SWLOCK, EP93XX_SWLOCK_MAGICK); + /* force write is required to clear swlock if is no changes are made */ + regmap_update_bits_base(map, reg, mask, val, NULL, false, true); + + spin_unlock_irqrestore(lock, flags); +} + +static void ep93xx_unregister_adev(void *_adev) +{ + struct auxiliary_device *adev = _adev; + + auxiliary_device_delete(adev); + auxiliary_device_uninit(adev); +} + +static void ep93xx_adev_release(struct device *dev) +{ + struct auxiliary_device *adev = to_auxiliary_dev(dev); + + kfree(adev); +} + +static struct auxiliary_device *ep93xx_adev_alloc(struct device *parent, const char *name, + struct ep93xx_map_info *info) +{ + struct ep93xx_regmap_adev *rdev; + struct auxiliary_device *adev; + int ret; + + rdev = kzalloc(sizeof(*rdev), GFP_KERNEL); + if (!rdev) + return ERR_PTR(-ENOMEM); + + rdev->map = info->map; + rdev->base = info->base; + rdev->lock = &info->lock; + rdev->write = ep93xx_regmap_write; + rdev->update_bits = ep93xx_regmap_update_bits; + + adev = &rdev->adev; + adev->name = name; + adev->dev.parent = parent; + adev->dev.release = ep93xx_adev_release; + + ret = auxiliary_device_init(adev); + if (ret) { + kfree(adev); + return ERR_PTR(ret); + } + + return adev; +} + +static int ep93xx_controller_register(struct device *parent, const char *name, + struct ep93xx_map_info *info) +{ + struct auxiliary_device *adev; + int ret; + + adev = ep93xx_adev_alloc(parent, name, info); + if (IS_ERR(adev)) + return PTR_ERR(adev); + + ret = auxiliary_device_add(adev); + if (ret) { + auxiliary_device_uninit(adev); + return ret; + } + + return devm_add_action_or_reset(parent, ep93xx_unregister_adev, adev); +} + +static unsigned int __init ep93xx_soc_revision(struct regmap *map) +{ + unsigned int val; + + regmap_read(map, EP93XX_SYSCON_SYSCFG, &val); + val &= EP93XX_SYSCON_SYSCFG_REV_MASK; + val >>= EP93XX_SYSCON_SYSCFG_REV_SHIFT; + return val; +} + +static const char __init *ep93xx_get_soc_rev(struct regmap *map) +{ + switch (ep93xx_soc_revision(map)) { + case EP93XX_CHIP_REV_D0: + return "D0"; + case EP93XX_CHIP_REV_D1: + return "D1"; + case EP93XX_CHIP_REV_E0: + return "E0"; + case EP93XX_CHIP_REV_E1: + return "E1"; + case EP93XX_CHIP_REV_E2: + return "E2"; + default: + return "unknown"; + } +} +const char *pinctrl_names[] = { + "pinctrl-ep9301", /* EP93XX_9301_SOC */ + "pinctrl-ep9307", /* EP93XX_9307_SOC */ + "pinctrl-ep9312" /* EP93XX_9312_SOC */ +}; + +static int __init ep93xx_syscon_probe(struct platform_device *pdev) +{ + enum ep93xx_soc_model model = (int)of_device_get_match_data(&pdev->dev); + struct ep93xx_map_info *map_info; + struct soc_device_attribute *attrs; + struct soc_device *soc_dev; + struct device *dev = &pdev->dev; + struct regmap *map; + void __iomem *base; + int ret; + + map = device_node_to_regmap(dev->of_node); + if (IS_ERR(map)) + return PTR_ERR(map); + + base = devm_platform_ioremap_resource(pdev, 0); + if (IS_ERR(base)) + return PTR_ERR(base); + + attrs = devm_kzalloc(dev, sizeof(*attrs), GFP_KERNEL); + if (!attrs) + return -ENOMEM; + + attrs->machine = of_flat_dt_get_machine_name(); + attrs->family = "Cirrus Logic EP93xx"; + attrs->revision = ep93xx_get_soc_rev(map); + + soc_dev = soc_device_register(attrs); + if (IS_ERR(soc_dev)) + return PTR_ERR(soc_dev); + + map_info = devm_kzalloc(dev, sizeof(*map_info), GFP_KERNEL); + if (!map_info) + return -ENOMEM; + + spin_lock_init(&map_info->lock); + map_info->map = map; + map_info->base = base; + + ret = ep93xx_controller_register(dev, pinctrl_names[model], map_info); + if (ret) + dev_err(dev, "registering pinctrl controller failed\n"); + + ret = ep93xx_controller_register(dev, "clk-ep93xx", map_info); + if (ret) + dev_err(dev, "registering clock controller failed\n"); + + ret = ep93xx_controller_register(dev, "reset-ep93xx", map_info); + if (ret) + dev_err(dev, "registering reset controller failed\n"); + + dev_info(dev, "EP93xx SoC revision %s\n", attrs->revision); + + return 0; +} + +static const struct of_device_id ep9301_syscon_of_device_ids[] = { + { .compatible = "cirrus,ep9301-syscon", .data = (void *)EP93XX_9301_SOC }, + { .compatible = "cirrus,ep9302-syscon", .data = (void *)EP93XX_9301_SOC }, + { .compatible = "cirrus,ep9307-syscon", .data = (void *)EP93XX_9307_SOC }, + { .compatible = "cirrus,ep9312-syscon", .data = (void *)EP93XX_9312_SOC }, + { .compatible = "cirrus,ep9315-syscon", .data = (void *)EP93XX_9312_SOC }, + { /* sentinel */ } +}; + +static struct platform_driver ep9301_syscon_driver = { + .driver = { + .name = "ep9301-syscon", + .of_match_table = ep9301_syscon_of_device_ids, + }, +}; +builtin_platform_driver_probe(ep9301_syscon_driver, ep93xx_syscon_probe); -- 2.41.0