From patchwork Fri Oct 11 13:12:19 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Neil Armstrong X-Patchwork-Id: 1175163 X-Patchwork-Delegate: narmstrong@baylibre.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=baylibre.com Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=baylibre-com.20150623.gappssmtp.com header.i=@baylibre-com.20150623.gappssmtp.com header.b="sAhbK2jR"; dkim-atps=neutral Received: from lists.denx.de (dione.denx.de [81.169.180.215]) by ozlabs.org (Postfix) with ESMTP id 46qT0k5qx8z9sPF for ; Sat, 12 Oct 2019 00:13:26 +1100 (AEDT) Received: by lists.denx.de (Postfix, from userid 105) id 1EEB2C21DFB; Fri, 11 Oct 2019 13:13:01 +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_H2, 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 68B0BC21DD9; Fri, 11 Oct 2019 13:12:50 +0000 (UTC) Received: by lists.denx.de (Postfix, from userid 105) id C391BC21E42; Fri, 11 Oct 2019 13:12:28 +0000 (UTC) Received: from mail-wr1-f67.google.com (mail-wr1-f67.google.com [209.85.221.67]) by lists.denx.de (Postfix) with ESMTPS id D0AA8C21BE5 for ; Fri, 11 Oct 2019 13:12:25 +0000 (UTC) Received: by mail-wr1-f67.google.com with SMTP id r5so11844634wrm.12 for ; Fri, 11 Oct 2019 06:12:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=baylibre-com.20150623.gappssmtp.com; s=20150623; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=p+OJbDDzu2A2/ixSQrDrhLhfEEocGdxVapl8ksZZyUk=; b=sAhbK2jRnSp4sCTql44WFcxztJXUWIQbWVGYNNVaF7nfbch25Uwtm+vky9YyvNs2q/ 0kQDIkbAnWPWpFwp+jSxtoOX7UddyLXk7BDK4UIULdIBZ2p8WBeq7WpQ5uTkFTMuizqd M7PtVSB4L80DNyCFQfbpF+3Gv5vMlMfX5NN7APBWgo1AloLcf6Ux89Tepx9wxZ4AuOBi ugY2/rmr0g6i/fMgqerKGhNMJGUhqDpzWs6zI1Z92DszNS59/WvdqqNJkHwHXPJGbbVl Lwx0PqFebBjdFVvJva9xOpYelCApZPMTu56+P5rTgcS2d3BIq7Teqw3ucQCHrmmmZk/b i8Qw== 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=p+OJbDDzu2A2/ixSQrDrhLhfEEocGdxVapl8ksZZyUk=; b=ZUCn7+tUtLUqQR43DG6Nh6W+95srRQ+xp2SJmDBljUNxssHQZSHcRvg1XGpvDBMEIq FXh+nrxpk3D3l46Xh9l0IkiUjwU9P9az/zhHKoHreYEMNm8QKjc2qRieoNRMwnxgGpNM /ycVS7FnQqLPO6+61Pl6tHXVsLr8XYWdQ1dGx74Fq0EnQvAvsfpV6f73LLby4UtETT6T iPV931VkEX9DE7HLHbdNATpwmBU3fGwyBF3+SK2EDzYNuD1fYAc4HSm7o9dyoSvJYIwM DmuuxqK8qknZtHoWheLr1s8SkhyaZ0diDG1CmLGYQqzBsEkdxsr3Kz7GdhSfjJPw0ZaD C/PQ== X-Gm-Message-State: APjAAAWTjWseUQr8ZpQDZri84kJ4UbEAVMLMv4x+uQSH/dkjLaovvv8R mfhlnIOtrEu8LcuksivuzpsqA6R+uqVGqQ== X-Google-Smtp-Source: APXvYqwLmwe+98dij09Z5ntNY49zcaRweQMYmMa/lDdqArKlDeisau4QXiglL7A2e2jXwgE7M8oTog== X-Received: by 2002:a5d:4a03:: with SMTP id m3mr1627686wrq.359.1570799544946; Fri, 11 Oct 2019 06:12:24 -0700 (PDT) Received: from bender.baylibre.local (lmontsouris-657-1-212-31.w90-63.abo.wanadoo.fr. [90.63.244.31]) by smtp.gmail.com with ESMTPSA id r12sm9662919wrq.88.2019.10.11.06.12.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Fri, 11 Oct 2019 06:12:24 -0700 (PDT) From: Neil Armstrong To: u-boot@lists.denx.de Date: Fri, 11 Oct 2019 15:12:19 +0200 Message-Id: <20191011131220.10873-2-narmstrong@baylibre.com> X-Mailer: git-send-email 2.22.0 In-Reply-To: <20191011131220.10873-1-narmstrong@baylibre.com> References: <20191011131220.10873-1-narmstrong@baylibre.com> MIME-Version: 1.0 Cc: u-boot-amlogic@groups.io Subject: [U-Boot] [PATCH 1/2] power: domain: add Amlogic Everything-Else power domain 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" Based on the 54ecb8f7028c ("Linux 5.4-rc1") Everything-Else power domain driver for Amlogic SoCs. This driver handles the VPU Power domain and other domains from the Everything-Else part of the SM1 and G12A SoCs. Signed-off-by: Neil Armstrong --- drivers/power/domain/Kconfig | 7 + drivers/power/domain/Makefile | 1 + drivers/power/domain/meson-ee-pwrc.c | 430 +++++++++++++++++++++++++++ 3 files changed, 438 insertions(+) create mode 100644 drivers/power/domain/meson-ee-pwrc.c diff --git a/drivers/power/domain/Kconfig b/drivers/power/domain/Kconfig index 06bba6220b..f5e428b3f5 100644 --- a/drivers/power/domain/Kconfig +++ b/drivers/power/domain/Kconfig @@ -37,6 +37,13 @@ config MESON_GX_VPU_POWER_DOMAIN Enable support for manipulating Amlogic Meson GX Video Processing Unit power domain. +config MESON_EE_POWER_DOMAIN + bool "Enable Amlogic Everything-Else power domain driver" + depends on POWER_DOMAIN && ARCH_MESON + help + Enable support for manipulating Amlogic Meson Everything-Else power + domains. + config SANDBOX_POWER_DOMAIN bool "Enable the sandbox power domain test driver" depends on POWER_DOMAIN && SANDBOX diff --git a/drivers/power/domain/Makefile b/drivers/power/domain/Makefile index 695aafe17d..91e4ca9d29 100644 --- a/drivers/power/domain/Makefile +++ b/drivers/power/domain/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_BCM6328_POWER_DOMAIN) += bcm6328-power-domain.o obj-$(CONFIG_IMX8_POWER_DOMAIN) += imx8-power-domain.o obj-$(CONFIG_MTK_POWER_DOMAIN) += mtk-power-domain.o obj-$(CONFIG_MESON_GX_VPU_POWER_DOMAIN) += meson-gx-pwrc-vpu.o +obj-$(CONFIG_MESON_EE_POWER_DOMAIN) += meson-ee-pwrc.o obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain.o obj-$(CONFIG_SANDBOX_POWER_DOMAIN) += sandbox-power-domain-test.o obj-$(CONFIG_TEGRA186_POWER_DOMAIN) += tegra186-power-domain.o diff --git a/drivers/power/domain/meson-ee-pwrc.c b/drivers/power/domain/meson-ee-pwrc.c new file mode 100644 index 0000000000..21d4c9d4dd --- /dev/null +++ b/drivers/power/domain/meson-ee-pwrc.c @@ -0,0 +1,430 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Copyright (c) 2019 BayLibre, SAS + * Author: Neil Armstrong + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* AO Offsets */ + +#define AO_RTI_GEN_PWR_SLEEP0 (0x3a << 2) +#define AO_RTI_GEN_PWR_ISO0 (0x3b << 2) + +/* HHI Offsets */ + +#define HHI_MEM_PD_REG0 (0x40 << 2) +#define HHI_VPU_MEM_PD_REG0 (0x41 << 2) +#define HHI_VPU_MEM_PD_REG1 (0x42 << 2) +#define HHI_VPU_MEM_PD_REG3 (0x43 << 2) +#define HHI_VPU_MEM_PD_REG4 (0x44 << 2) +#define HHI_AUDIO_MEM_PD_REG0 (0x45 << 2) +#define HHI_NANOQ_MEM_PD_REG0 (0x46 << 2) +#define HHI_NANOQ_MEM_PD_REG1 (0x47 << 2) +#define HHI_VPU_MEM_PD_REG2 (0x4d << 2) + +struct meson_ee_pwrc; +struct meson_ee_pwrc_domain; + +struct meson_ee_pwrc_mem_domain { + unsigned int reg; + unsigned int mask; +}; + +struct meson_ee_pwrc_top_domain { + unsigned int sleep_reg; + unsigned int sleep_mask; + unsigned int iso_reg; + unsigned int iso_mask; +}; + +struct meson_ee_pwrc_domain_desc { + char *name; + unsigned int reset_names_count; + unsigned int clk_names_count; + struct meson_ee_pwrc_top_domain *top_pd; + unsigned int mem_pd_count; + struct meson_ee_pwrc_mem_domain *mem_pd; + bool (*get_power)(struct power_domain *power_domain); +}; + +struct meson_ee_pwrc_domain_data { + unsigned int count; + struct meson_ee_pwrc_domain_desc *domains; +}; + +/* TOP Power Domains */ + +static struct meson_ee_pwrc_top_domain g12a_pwrc_vpu = { + .sleep_reg = AO_RTI_GEN_PWR_SLEEP0, + .sleep_mask = BIT(8), + .iso_reg = AO_RTI_GEN_PWR_SLEEP0, + .iso_mask = BIT(9), +}; + +#define SM1_EE_PD(__bit) \ + { \ + .sleep_reg = AO_RTI_GEN_PWR_SLEEP0, \ + .sleep_mask = BIT(__bit), \ + .iso_reg = AO_RTI_GEN_PWR_ISO0, \ + .iso_mask = BIT(__bit), \ + } + +static struct meson_ee_pwrc_top_domain sm1_pwrc_vpu = SM1_EE_PD(8); +static struct meson_ee_pwrc_top_domain sm1_pwrc_nna = SM1_EE_PD(16); +static struct meson_ee_pwrc_top_domain sm1_pwrc_usb = SM1_EE_PD(17); +static struct meson_ee_pwrc_top_domain sm1_pwrc_pci = SM1_EE_PD(18); +static struct meson_ee_pwrc_top_domain sm1_pwrc_ge2d = SM1_EE_PD(19); + +/* Memory PD Domains */ + +#define VPU_MEMPD(__reg) \ + { __reg, GENMASK(1, 0) }, \ + { __reg, GENMASK(3, 2) }, \ + { __reg, GENMASK(5, 4) }, \ + { __reg, GENMASK(7, 6) }, \ + { __reg, GENMASK(9, 8) }, \ + { __reg, GENMASK(11, 10) }, \ + { __reg, GENMASK(13, 12) }, \ + { __reg, GENMASK(15, 14) }, \ + { __reg, GENMASK(17, 16) }, \ + { __reg, GENMASK(19, 18) }, \ + { __reg, GENMASK(21, 20) }, \ + { __reg, GENMASK(23, 22) }, \ + { __reg, GENMASK(25, 24) }, \ + { __reg, GENMASK(27, 26) }, \ + { __reg, GENMASK(29, 28) }, \ + { __reg, GENMASK(31, 30) } + +#define VPU_HHI_MEMPD(__reg) \ + { __reg, BIT(8) }, \ + { __reg, BIT(9) }, \ + { __reg, BIT(10) }, \ + { __reg, BIT(11) }, \ + { __reg, BIT(12) }, \ + { __reg, BIT(13) }, \ + { __reg, BIT(14) }, \ + { __reg, BIT(15) } + +static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_vpu[] = { + VPU_MEMPD(HHI_VPU_MEM_PD_REG0), + VPU_MEMPD(HHI_VPU_MEM_PD_REG1), + VPU_MEMPD(HHI_VPU_MEM_PD_REG2), + VPU_HHI_MEMPD(HHI_MEM_PD_REG0), +}; + +static struct meson_ee_pwrc_mem_domain g12a_pwrc_mem_eth[] = { + { HHI_MEM_PD_REG0, GENMASK(3, 2) }, +}; + +static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_vpu[] = { + VPU_MEMPD(HHI_VPU_MEM_PD_REG0), + VPU_MEMPD(HHI_VPU_MEM_PD_REG1), + VPU_MEMPD(HHI_VPU_MEM_PD_REG2), + VPU_MEMPD(HHI_VPU_MEM_PD_REG3), + { HHI_VPU_MEM_PD_REG4, GENMASK(1, 0) }, + { HHI_VPU_MEM_PD_REG4, GENMASK(3, 2) }, + { HHI_VPU_MEM_PD_REG4, GENMASK(5, 4) }, + { HHI_VPU_MEM_PD_REG4, GENMASK(7, 6) }, + VPU_HHI_MEMPD(HHI_MEM_PD_REG0), +}; + +static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_nna[] = { + { HHI_NANOQ_MEM_PD_REG0, 0xff }, + { HHI_NANOQ_MEM_PD_REG1, 0xff }, +}; + +static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_usb[] = { + { HHI_MEM_PD_REG0, GENMASK(31, 30) }, +}; + +static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_pcie[] = { + { HHI_MEM_PD_REG0, GENMASK(29, 26) }, +}; + +static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_ge2d[] = { + { HHI_MEM_PD_REG0, GENMASK(25, 18) }, +}; + +static struct meson_ee_pwrc_mem_domain sm1_pwrc_mem_audio[] = { + { HHI_MEM_PD_REG0, GENMASK(5, 4) }, + { HHI_AUDIO_MEM_PD_REG0, GENMASK(1, 0) }, + { HHI_AUDIO_MEM_PD_REG0, GENMASK(3, 2) }, + { HHI_AUDIO_MEM_PD_REG0, GENMASK(5, 4) }, + { HHI_AUDIO_MEM_PD_REG0, GENMASK(7, 6) }, + { HHI_AUDIO_MEM_PD_REG0, GENMASK(13, 12) }, + { HHI_AUDIO_MEM_PD_REG0, GENMASK(15, 14) }, + { HHI_AUDIO_MEM_PD_REG0, GENMASK(17, 16) }, + { HHI_AUDIO_MEM_PD_REG0, GENMASK(19, 18) }, + { HHI_AUDIO_MEM_PD_REG0, GENMASK(21, 20) }, + { HHI_AUDIO_MEM_PD_REG0, GENMASK(23, 22) }, + { HHI_AUDIO_MEM_PD_REG0, GENMASK(25, 24) }, + { HHI_AUDIO_MEM_PD_REG0, GENMASK(27, 26) }, +}; + +#define VPU_PD(__name, __top_pd, __mem, __get_power, __resets, __clks) \ + { \ + .name = __name, \ + .reset_names_count = __resets, \ + .clk_names_count = __clks, \ + .top_pd = __top_pd, \ + .mem_pd_count = ARRAY_SIZE(__mem), \ + .mem_pd = __mem, \ + .get_power = __get_power, \ + } + +#define TOP_PD(__name, __top_pd, __mem, __get_power) \ + { \ + .name = __name, \ + .top_pd = __top_pd, \ + .mem_pd_count = ARRAY_SIZE(__mem), \ + .mem_pd = __mem, \ + .get_power = __get_power, \ + } + +#define MEM_PD(__name, __mem) \ + TOP_PD(__name, NULL, __mem, NULL) + +static bool pwrc_ee_get_power(struct power_domain *power_domain); + +static struct meson_ee_pwrc_domain_desc g12a_pwrc_domains[] = { + [PWRC_G12A_VPU_ID] = VPU_PD("VPU", &g12a_pwrc_vpu, g12a_pwrc_mem_vpu, + pwrc_ee_get_power, 11, 2), + [PWRC_G12A_ETH_ID] = MEM_PD("ETH", g12a_pwrc_mem_eth), +}; + +static struct meson_ee_pwrc_domain_desc sm1_pwrc_domains[] = { + [PWRC_SM1_VPU_ID] = VPU_PD("VPU", &sm1_pwrc_vpu, sm1_pwrc_mem_vpu, + pwrc_ee_get_power, 11, 2), + [PWRC_SM1_NNA_ID] = TOP_PD("NNA", &sm1_pwrc_nna, sm1_pwrc_mem_nna, + pwrc_ee_get_power), + [PWRC_SM1_USB_ID] = TOP_PD("USB", &sm1_pwrc_usb, sm1_pwrc_mem_usb, + pwrc_ee_get_power), + [PWRC_SM1_PCIE_ID] = TOP_PD("PCI", &sm1_pwrc_pci, sm1_pwrc_mem_pcie, + pwrc_ee_get_power), + [PWRC_SM1_GE2D_ID] = TOP_PD("GE2D", &sm1_pwrc_ge2d, sm1_pwrc_mem_ge2d, + pwrc_ee_get_power), + [PWRC_SM1_AUDIO_ID] = MEM_PD("AUDIO", sm1_pwrc_mem_audio), + [PWRC_SM1_ETH_ID] = MEM_PD("ETH", g12a_pwrc_mem_eth), +}; + +struct meson_ee_pwrc_priv { + struct regmap *regmap_ao; + struct regmap *regmap_hhi; + struct reset_ctl_bulk resets; + struct clk_bulk clks; + const struct meson_ee_pwrc_domain_data *data; +}; + +static bool pwrc_ee_get_power(struct power_domain *power_domain) +{ + struct meson_ee_pwrc_priv *priv = dev_get_priv(power_domain->dev); + struct meson_ee_pwrc_domain_desc *pwrc_domain; + u32 reg; + + pwrc_domain = &priv->data->domains[power_domain->id]; + + regmap_read(priv->regmap_ao, + pwrc_domain->top_pd->sleep_reg, ®); + + return (reg & pwrc_domain->top_pd->sleep_mask); +} + +static int meson_ee_pwrc_request(struct power_domain *power_domain) +{ + return 0; +} + +static int meson_ee_pwrc_free(struct power_domain *power_domain) +{ + return 0; +} + +static int meson_ee_pwrc_off(struct power_domain *power_domain) +{ + struct meson_ee_pwrc_priv *priv = dev_get_priv(power_domain->dev); + struct meson_ee_pwrc_domain_desc *pwrc_domain; + int i; + + pwrc_domain = &priv->data->domains[power_domain->id]; + + if (pwrc_domain->top_pd) + regmap_update_bits(priv->regmap_ao, + pwrc_domain->top_pd->sleep_reg, + pwrc_domain->top_pd->sleep_mask, + pwrc_domain->top_pd->sleep_mask); + udelay(20); + + for (i = 0 ; i < pwrc_domain->mem_pd_count ; ++i) + regmap_update_bits(priv->regmap_hhi, + pwrc_domain->mem_pd[i].reg, + pwrc_domain->mem_pd[i].mask, + pwrc_domain->mem_pd[i].mask); + + udelay(20); + + if (pwrc_domain->top_pd) + regmap_update_bits(priv->regmap_ao, + pwrc_domain->top_pd->iso_reg, + pwrc_domain->top_pd->iso_mask, + pwrc_domain->top_pd->iso_mask); + + if (pwrc_domain->clk_names_count) { + mdelay(20); + clk_disable_bulk(&priv->clks); + } + + return 0; +} + +static int meson_ee_pwrc_on(struct power_domain *power_domain) +{ + struct meson_ee_pwrc_priv *priv = dev_get_priv(power_domain->dev); + struct meson_ee_pwrc_domain_desc *pwrc_domain; + int i, ret; + + pwrc_domain = &priv->data->domains[power_domain->id]; + + if (pwrc_domain->top_pd) + regmap_update_bits(priv->regmap_ao, + pwrc_domain->top_pd->sleep_reg, + pwrc_domain->top_pd->sleep_mask, 0); + udelay(20); + + for (i = 0 ; i < pwrc_domain->mem_pd_count ; ++i) + regmap_update_bits(priv->regmap_hhi, + pwrc_domain->mem_pd[i].reg, + pwrc_domain->mem_pd[i].mask, 0); + + udelay(20); + + if (pwrc_domain->reset_names_count) { + ret = reset_assert_bulk(&priv->resets); + if (ret) + return ret; + } + + if (pwrc_domain->top_pd) + regmap_update_bits(priv->regmap_ao, + pwrc_domain->top_pd->iso_reg, + pwrc_domain->top_pd->iso_mask, 0); + + if (pwrc_domain->reset_names_count) { + ret = reset_deassert_bulk(&priv->resets); + if (ret) + return ret; + } + + if (pwrc_domain->clk_names_count) + return clk_enable_bulk(&priv->clks); + + return 0; +} + +static int meson_ee_pwrc_of_xlate(struct power_domain *power_domain, + struct ofnode_phandle_args *args) +{ + struct meson_ee_pwrc_priv *priv = dev_get_priv(power_domain->dev); + + /* #power-domain-cells is 1 */ + + if (args->args_count < 1) { + debug("Invalid args_count: %d\n", args->args_count); + return -EINVAL; + } + + power_domain->id = args->args[0]; + + if (power_domain->id >= priv->data->count) { + debug("Invalid domain ID: %lu\n", power_domain->id); + return -EINVAL; + } + + return 0; +} + +struct power_domain_ops meson_ee_pwrc_ops = { + .free = meson_ee_pwrc_free, + .off = meson_ee_pwrc_off, + .on = meson_ee_pwrc_on, + .request = meson_ee_pwrc_request, + .of_xlate = meson_ee_pwrc_of_xlate, +}; + +static struct meson_ee_pwrc_domain_data meson_ee_g12a_pwrc_data = { + .count = ARRAY_SIZE(g12a_pwrc_domains), + .domains = g12a_pwrc_domains, +}; + +static struct meson_ee_pwrc_domain_data meson_ee_sm1_pwrc_data = { + .count = ARRAY_SIZE(sm1_pwrc_domains), + .domains = sm1_pwrc_domains, +}; + +static const struct udevice_id meson_ee_pwrc_ids[] = { + { + .compatible = "amlogic,meson-g12a-pwrc", + .data = (unsigned long)&meson_ee_g12a_pwrc_data, + }, + { + .compatible = "amlogic,meson-sm1-pwrc", + .data = (unsigned long)&meson_ee_sm1_pwrc_data, + }, + { } +}; + +static int meson_ee_pwrc_probe(struct udevice *dev) +{ + struct meson_ee_pwrc_priv *priv = dev_get_priv(dev); + u32 ao_phandle; + ofnode ao_node; + int ret; + + priv->data = (void *)dev_get_driver_data(dev); + if (!priv->data) + return -EINVAL; + + priv->regmap_hhi = syscon_node_to_regmap(dev_get_parent(dev)->node); + if (IS_ERR(priv->regmap_hhi)) + return PTR_ERR(priv->regmap_hhi); + + ret = ofnode_read_u32(dev->node, "amlogic,ao-sysctrl", + &ao_phandle); + if (ret) + return ret; + + ao_node = ofnode_get_by_phandle(ao_phandle); + if (!ofnode_valid(ao_node)) + return -EINVAL; + + priv->regmap_ao = syscon_node_to_regmap(ao_node); + if (IS_ERR(priv->regmap_ao)) + return PTR_ERR(priv->regmap_ao); + + ret = reset_get_bulk(dev, &priv->resets); + if (ret) + return ret; + + ret = clk_get_bulk(dev, &priv->clks); + if (ret) + return ret; + + return 0; +} + +U_BOOT_DRIVER(meson_ee_pwrc) = { + .name = "meson_ee_pwrc", + .id = UCLASS_POWER_DOMAIN, + .of_match = meson_ee_pwrc_ids, + .probe = meson_ee_pwrc_probe, + .ops = &meson_ee_pwrc_ops, + .priv_auto_alloc_size = sizeof(struct meson_ee_pwrc_priv), +};