From patchwork Sun Aug 26 12:38:12 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jagan Teki X-Patchwork-Id: 962228 X-Patchwork-Delegate: jagannadh.teki@gmail.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.denx.de (client-ip=81.169.180.215; helo=lists.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=amarulasolutions.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=amarulasolutions.com header.i=@amarulasolutions.com header.b="di3oE/bX"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 41yvk411Ptz9s7X for ; Sun, 26 Aug 2018 22:40:12 +1000 (AEST) Received: by lists.denx.de (Postfix, from userid 105) id C3C53C21E1B; Sun, 26 Aug 2018 12:39:42 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on lists.denx.de X-Spam-Level: X-Spam-Status: No, score=-0.0 required=5.0 tests=RCVD_IN_MSPIKE_H3, RCVD_IN_MSPIKE_WL, T_DKIM_INVALID autolearn=unavailable autolearn_force=no version=3.4.0 Received: from lists.denx.de (localhost [IPv6:::1]) by lists.denx.de (Postfix) with ESMTP id 8F8F6C21E76; Sun, 26 Aug 2018 12:39:08 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id 621F2C21E31; Sun, 26 Aug 2018 12:39:02 +0000 (UTC) Received: from mail-pl1-f193.google.com (mail-pl1-f193.google.com [209.85.214.193]) by lists.denx.de (Postfix) with ESMTPS id 7D64BC21E6C for ; Sun, 26 Aug 2018 12:38:56 +0000 (UTC) Received: by mail-pl1-f193.google.com with SMTP id d9-v6so2943395plr.2 for ; Sun, 26 Aug 2018 05:38:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amarulasolutions.com; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=JePAW7JHWcVrxLQYHaidfnXsCq6vizCl24f2GJuqQz0=; b=di3oE/bXzg04/1vcXx4u85/ryKKursc79HGO1TwpbixHnLlbvIhN9fThFGN7ZP6oE5 wDBvmuV4UlyjryWgdkkxz0NSsVErCiWzIDclbjecypkLBPlmxkrOYGJ9d1TdjkZDW5jr 1JdhYJgdojWSFqubNLv/aCYJgO+/SIZpmHo5M= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=JePAW7JHWcVrxLQYHaidfnXsCq6vizCl24f2GJuqQz0=; b=BvrZqcKOAX3G+PrOQfkFHMvJrQ6ws94wz9CU0mwGVKSWdwCR3DVbG8ROFKdz5WWmMU uJEfBgoOlxe7dIXuzePu6OvQTeekcw3KcWkWH9JZxQqoBCgvn9TcBINi10msTXnXi40x 4JGBQ6S0EX5+JMZ/REHEsIrBrWS+JVWN4nj3PbcJQ03DdSxFDwMDdtaeVQftvAHTwes8 BhzGnRR4W29mTu3FiFbxm2YxN2jNLzVq7MCiWLa0ztdo1TGK29+FUGtMB2Tzjj/ebclv tk4LgAFpq1oTcE5syGbOc6FVYA7UDwU+bJ5PasIR3HqpKCe0Xv0xpHUzi6+TEM0kOvVl IvwA== X-Gm-Message-State: APzg51AaHYUaARU4gpg1vd+vTNCtEWaNJ16k8yIoO3WuWKDPKnmmoJGX sKdCFopgCCeq5fSEVoAkAyg3iQ== X-Google-Smtp-Source: ANB0VdaR+MZ4jQQblfOUw/CvdnxhV1fYBTF37aHe1SFmIt2jnSW23D1KPePEgFdCl/iP2417c8THrQ== X-Received: by 2002:a17:902:a24:: with SMTP id 33-v6mr8841559plo.293.1535287134949; Sun, 26 Aug 2018 05:38:54 -0700 (PDT) Received: from localhost.localdomain ([106.208.74.208]) by smtp.gmail.com with ESMTPSA id d2-v6sm21390075pfg.172.2018.08.26.05.38.51 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 26 Aug 2018 05:38:54 -0700 (PDT) From: Jagan Teki To: Maxime Ripard , Andre Przywara , Chen-Yu Tsai , Icenowy Zheng Date: Sun, 26 Aug 2018 18:08:12 +0530 Message-Id: <20180826123826.19243-4-jagan@amarulasolutions.com> X-Mailer: git-send-email 2.18.0.321.gffc6fa0e3 In-Reply-To: <20180826123826.19243-1-jagan@amarulasolutions.com> References: <20180826123826.19243-1-jagan@amarulasolutions.com> MIME-Version: 1.0 Cc: Tom Rini , u-boot@lists.denx.de Subject: [U-Boot] [PATCH v4 03/17] reset: Add Allwinner RESET driver X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.18 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" Add common reset driver for all Allwinner SoC's. Since CLK and RESET share common DT compatible, it is CLK driver job is to bind the reset driver. So add CLK bind call on respective SoC driver by passing ccu map descriptor so-that reset deassert, deassert operations held based on reset register map defined by CLK driver. Select DM_RESET via CLK_SUNXI, this make hidden section of RESET since CLK and RESET share common DT compatible and code. Tested-by: Jagan Teki # BPI-M64 Signed-off-by: Jagan Teki Acked-by: Maxime Ripard --- arch/arm/include/asm/arch-sunxi/ccu.h | 25 ++++++ drivers/clk/sunxi/Kconfig | 1 + drivers/clk/sunxi/clk_a64.c | 22 +++++ drivers/reset/Kconfig | 8 ++ drivers/reset/Makefile | 1 + drivers/reset/reset-sunxi.c | 125 ++++++++++++++++++++++++++ 6 files changed, 182 insertions(+) create mode 100644 drivers/reset/reset-sunxi.c diff --git a/arch/arm/include/asm/arch-sunxi/ccu.h b/arch/arm/include/asm/arch-sunxi/ccu.h index 998ab38bf2..3e322a7655 100644 --- a/arch/arm/include/asm/arch-sunxi/ccu.h +++ b/arch/arm/include/asm/arch-sunxi/ccu.h @@ -20,15 +20,31 @@ struct ccu_clk_map { int (*ccu_clk_set_rate)(void *base, u32 bit, ulong rate); }; +/** + * ccu_reset_map - common clock unit reset map + * + * @off: ccu reset offset + * @bit: ccu reset bit value + */ +struct ccu_reset_map { + u16 off; + u32 bit; +}; + /** * struct ccu_desc - common clock unit descriptor * * @clks: mapping clocks descriptor * @num_clks: number of mapped clocks + * @resets: mapping resets descriptor + * @num_resets: number of mapped resets */ struct ccu_desc { struct ccu_clk_map *clks; unsigned long num_clks; + + struct ccu_reset_map *resets; + unsigned long num_resets; }; /** @@ -44,4 +60,13 @@ struct sunxi_clk_priv { extern struct clk_ops sunxi_clk_ops; +/** + * sunxi_reset_bind() - reset binding + * + * @dev: reset device + * @count: reset count + * @return 0 success, or error value + */ +int sunxi_reset_bind(struct udevice *dev, ulong count); + #endif /* _ASM_ARCH_CCU_H */ diff --git a/drivers/clk/sunxi/Kconfig b/drivers/clk/sunxi/Kconfig index bf5ecb3801..041d711e58 100644 --- a/drivers/clk/sunxi/Kconfig +++ b/drivers/clk/sunxi/Kconfig @@ -1,6 +1,7 @@ config CLK_SUNXI bool "Clock support for Allwinner SoCs" depends on CLK && ARCH_SUNXI + select DM_RESET default y help This enables support for common clock driver API on Allwinner diff --git a/drivers/clk/sunxi/clk_a64.c b/drivers/clk/sunxi/clk_a64.c index 8966472c2d..13b58aa57f 100644 --- a/drivers/clk/sunxi/clk_a64.c +++ b/drivers/clk/sunxi/clk_a64.c @@ -10,6 +10,7 @@ #include #include #include +#include static struct ccu_clk_map a64_clks[] = { [CLK_BUS_OTG] = { 0x060, BIT(23), NULL }, @@ -26,9 +27,24 @@ static struct ccu_clk_map a64_clks[] = { [CLK_USB_OHCI1] = { 0x0cc, BIT(17), NULL }, }; +static struct ccu_reset_map a64_resets[] = { + [RST_USB_PHY0] = { 0x0cc, BIT(0) }, + [RST_USB_PHY1] = { 0x0cc, BIT(1) }, + [RST_USB_HSIC] = { 0x0cc, BIT(2) }, + + [RST_BUS_OTG] = { 0x2c0, BIT(23) }, + [RST_BUS_EHCI0] = { 0x2c0, BIT(24) }, + [RST_BUS_EHCI1] = { 0x2c0, BIT(25) }, + [RST_BUS_OHCI0] = { 0x2c0, BIT(28) }, + [RST_BUS_OHCI1] = { 0x2c0, BIT(29) }, +}; + static const struct ccu_desc sun50i_a64_ccu_desc = { .clks = a64_clks, .num_clks = ARRAY_SIZE(a64_clks), + + .resets = a64_resets, + .num_resets = ARRAY_SIZE(a64_resets), }; static int a64_clk_probe(struct udevice *dev) @@ -46,6 +62,11 @@ static int a64_clk_probe(struct udevice *dev) return 0; } +static int a64_clk_bind(struct udevice *dev) +{ + return sunxi_reset_bind(dev, 50); +} + static const struct udevice_id a64_clk_ids[] = { { .compatible = "allwinner,sun50i-a64-ccu", .data = (ulong)&sun50i_a64_ccu_desc }, @@ -59,4 +80,5 @@ U_BOOT_DRIVER(clk_sun50i_a64) = { .priv_auto_alloc_size = sizeof(struct sunxi_clk_priv), .ops = &sunxi_clk_ops, .probe = a64_clk_probe, + .bind = a64_clk_bind, }; diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig index 33c39b7fb6..bdc06564a0 100644 --- a/drivers/reset/Kconfig +++ b/drivers/reset/Kconfig @@ -98,4 +98,12 @@ config RESET_SOCFPGA help Support for reset controller on SoCFPGA platform. +config RESET_SUNXI + bool "RESET support for Allwinner SoCs" + depends on DM_RESET && ARCH_SUNXI + default y + help + This enables support for common reset driver for + Allwinner SoCs. + endmenu diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile index ad08be4c8c..698d15a0e0 100644 --- a/drivers/reset/Makefile +++ b/drivers/reset/Makefile @@ -15,3 +15,4 @@ obj-$(CONFIG_AST2500_RESET) += ast2500-reset.o obj-$(CONFIG_RESET_ROCKCHIP) += reset-rockchip.o obj-$(CONFIG_RESET_MESON) += reset-meson.o obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o +obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o diff --git a/drivers/reset/reset-sunxi.c b/drivers/reset/reset-sunxi.c new file mode 100644 index 0000000000..293297e98c --- /dev/null +++ b/drivers/reset/reset-sunxi.c @@ -0,0 +1,125 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (C) 2018 Amarula Solutions. + * Author: Jagan Teki + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +struct sunxi_reset_priv { + void *base; + ulong count; + const struct ccu_desc *desc; +}; + +static int sunxi_reset_request(struct reset_ctl *reset_ctl) +{ + struct sunxi_reset_priv *priv = dev_get_priv(reset_ctl->dev); + + debug("%s (RST#%ld)\n", __func__, reset_ctl->id); + + /* check dt-bindings/reset/sun8i-h3-ccu.h for max id */ + if (reset_ctl->id >= priv->count) + return -EINVAL; + + return 0; +} + +static int sunxi_reset_free(struct reset_ctl *reset_ctl) +{ + debug("%s (RST#%ld)\n", __func__, reset_ctl->id); + + return 0; +} + +static int sunxi_reset_assert(struct reset_ctl *reset_ctl) +{ + struct sunxi_reset_priv *priv = dev_get_priv(reset_ctl->dev); + struct ccu_reset_map *map = &priv->desc->resets[reset_ctl->id]; + u32 reg; + + if (!map->off || !map->bit) { + debug("%s (RST#%ld) unhandled\n", __func__, reset_ctl->id); + return 0; + } + + debug("%s(#%ld) off#0x%x, BIT(%d)\n", __func__, + reset_ctl->id, map->off, ilog2(map->bit)); + + reg = readl(priv->base + map->off); + writel(reg & ~map->bit, priv->base + map->off); + + return 0; +} + +static int sunxi_reset_deassert(struct reset_ctl *reset_ctl) +{ + struct sunxi_reset_priv *priv = dev_get_priv(reset_ctl->dev); + struct ccu_reset_map *map = &priv->desc->resets[reset_ctl->id]; + u32 reg; + + if (!map->off || !map->bit) { + debug("%s (RST#%ld) unhandled\n", __func__, reset_ctl->id); + return 0; + } + + debug("%s(#%ld) off#0x%x, BIT(%d)\n", __func__, + reset_ctl->id, map->off, ilog2(map->bit)); + + reg = readl(priv->base + map->off); + writel(reg | map->bit, priv->base + map->off); + + return 0; +} + +struct reset_ops sunxi_reset_ops = { + .request = sunxi_reset_request, + .free = sunxi_reset_free, + .rst_assert = sunxi_reset_assert, + .rst_deassert = sunxi_reset_deassert, +}; + +static int sunxi_reset_probe(struct udevice *dev) +{ + struct sunxi_reset_priv *priv = dev_get_priv(dev); + + priv->base = dev_read_addr_ptr(dev); + + return 0; +} + +int sunxi_reset_bind(struct udevice *dev, ulong count) +{ + struct udevice *rst_dev; + struct sunxi_reset_priv *priv; + int ret; + + ret = device_bind_driver_to_node(dev, "sunxi_reset", "reset", + dev_ofnode(dev), &rst_dev); + if (ret) { + debug("Warning: failed to bind sunxi_reset driver (ret=%d)\n", + ret); + return ret; + } + priv = malloc(sizeof(struct sunxi_reset_priv)); + priv->count = count; + priv->desc = (const struct ccu_desc *)dev_get_driver_data(dev); + rst_dev->priv = priv; + + return 0; +} + +U_BOOT_DRIVER(reset_sun8i_h3) = { + .name = "sunxi_reset", + .id = UCLASS_RESET, + .ops = &sunxi_reset_ops, + .probe = sunxi_reset_probe, + .priv_auto_alloc_size = sizeof(struct sunxi_reset_priv), +};