From patchwork Wed Oct 19 17:20:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dario Binacchi X-Patchwork-Id: 2452 Return-Path: X-Original-To: linux-amarula@patchwork.amarulasolutions.com Delivered-To: linux-amarula@patchwork.amarulasolutions.com Received: from mail-ed1-f71.google.com (mail-ed1-f71.google.com [209.85.208.71]) by ganimede.amarulasolutions.com (Postfix) with ESMTPS id 9A18C3F342 for ; Wed, 19 Oct 2022 19:20:30 +0200 (CEST) Received: by mail-ed1-f71.google.com with SMTP id w20-20020a05640234d400b0045d0d1afe8esf12991315edc.15 for ; Wed, 19 Oct 2022 10:20:30 -0700 (PDT) ARC-Seal: i=2; a=rsa-sha256; t=1666200030; cv=pass; d=google.com; s=arc-20160816; b=ZHqoYolWO/BZ/sQFUfrEv31zrxzTUOWlb9q/fo08jdd+YDHKvO49WHBdkyz+QDg6un lDlnvTt/NwjMy0B396k4jmUukhabZ/UE5CdXLEMbaco8a2G5uyC5AqDn+UStWHSH4EDu M1vXUFwqMzfplraio5xd17G9kfiFjR5MhONf07LnRdaE37Mngzcl4fwd9gilPpJl8V4e KeOl4bqiO3CogQgN8btKhi9ZmVrbKIgU6rKktov0H1oDFJXhWqpbFJ5gSiNrzbIjKpif icv0Mcew/1YgYTaUkIj3FRXwRQl9EUzo6qemQv4P9q+UTR91OtUp4fGHGrTlqrv16fG+ pg2Q== ARC-Message-Signature: i=2; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-unsubscribe:list-archive:list-help:list-post:list-id :mailing-list:precedence:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=nHhhHzrKrO029n00bKiZk7MqpS7svbhrovJnlHYwpMA=; b=JBmUnY9bUxYx9jkG6n7ey+2cAHbTM+eOBURXGY/PRXFRqPjOnfpKPuSR3ggwdxqlX6 bNSGhH2qbT695gYWhpsBMj9DKj6awJhUc3OKJSgej5/RzYoc44dNVLucJh8z9XjoDuGD QxcxrY0xpqw1GMYRKrZCqgCt46UfXjfID5+gsbEfztnKyzjfHmi7TtQ/A1Ba9n1mgBHi /SjMpcazX0G7B0Q5KjwKQPjXAIQ3aKD1fZ24fal2PPuzoxq5vpl+l2IwnvoIPmpeO8Hl XOHhywWk5bIabXv/RPbZnbaXine6gxX/fFKKCInVcwHaKoWdeflSfwwp/QYS6qSFCsZf lcBA== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=WrySYmte; spf=pass (google.com: domain of dario.binacchi@amarulasolutions.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=dario.binacchi@amarulasolutions.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=amarulasolutions.com DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=amarulasolutions.com; s=google; h=list-unsubscribe:list-archive:list-help:list-post:list-id :mailing-list:precedence:x-original-authentication-results :x-original-sender:mime-version:references:in-reply-to:message-id :date:subject:cc:to:from:from:to:cc:subject:date:message-id:reply-to; bh=nHhhHzrKrO029n00bKiZk7MqpS7svbhrovJnlHYwpMA=; b=KJMwMABCQETGhxmyD6uN689ij2wFzF5tnpkr1ra6XW5pvIaTJrXkhg53mxFUDsnOGR MywNuv6BKm3pEZHOJcDsaZLqQGzcOtEVbh1bRcQ5/OO0dCgH4vqEVkDe/Gnveku5tOLQ H5dmc+LIJye3Mt6JNqhW2KCqhQh+TpzlzDmVk= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=list-unsubscribe:list-archive:list-help:list-post :x-spam-checked-in-group:list-id:mailing-list:precedence :x-original-authentication-results:x-original-sender:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=nHhhHzrKrO029n00bKiZk7MqpS7svbhrovJnlHYwpMA=; b=PmK0UDIkD4SGPMjXKbErz03F7ocvAaosBwvzxH+siZp18+DiyyVe6Yw7s6DrYvVE9B Cyl7Lh8r6tHpiaV5qzsTJsuDkQGmxU/StKDSUUFVpAWjHQ9RAFX26gUTfQOD8B3ve1xh RWuWECixdkMlXt3dLPRicoq75WPCTZnt7FrpswBUTtd5hz1ySUUANGfxlS3rd3GxRFzr pfwG8V9pftPd75i7uRwFNddfv2FEcmxXFsuJYGCJcbplnGJTuWY8SkeVmcpBZXqjND0l cwWXemQYRWmpGCVSldXMC/cPTRC5EMQEIpG+entkN1QStxVEVCsZ/7jr1u1UkhZyXwQF lb5w== X-Gm-Message-State: ACrzQf2RD/Ar85cuPHwKX6Fpgb5HeOqutuyp0Yq5f3y80cl+liPX3k24 VTpYQ138TZQcv5EK0WpkhVCCWhIz X-Google-Smtp-Source: AMsMyM6kJQWVFiKU3N1VLdAtGBIn6blWhKotliFpMrqzuYy4206a2G0K5g9wi1dcgTjiiuHBs9S0nw== X-Received: by 2002:a17:907:75f5:b0:78d:fc53:7d96 with SMTP id jz21-20020a17090775f500b0078dfc537d96mr7632556ejc.718.1666200030391; Wed, 19 Oct 2022 10:20:30 -0700 (PDT) X-BeenThere: linux-amarula@amarulasolutions.com Received: by 2002:a05:6402:35c1:b0:45d:64be:d1a with SMTP id z1-20020a05640235c100b0045d64be0d1als1125874edc.1.-pod-prod-gmail; Wed, 19 Oct 2022 10:20:29 -0700 (PDT) X-Received: by 2002:aa7:dd45:0:b0:458:7474:1fbe with SMTP id o5-20020aa7dd45000000b0045874741fbemr8621015edw.334.1666200029337; Wed, 19 Oct 2022 10:20:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1666200029; cv=none; d=google.com; s=arc-20160816; b=n1cUCZGFXRjvcSncjX5uGuMQBztfu1mRdNiIydY3RMRJ+ukY9LBiVIhfko1D2m0pYn VCNnTaq2voq+hwod1h2h7REWy8cezMQq46wwX1QRgxLoRxUex8xLlpcTJryNo7ZHlfbp WldeLGBuLRnDCzXptUkZp84gVZ4tPRTEyNNY3eApGZ8s0XRAA/+xZYHoBKs0PerspsdH VTl6svSAEw8sy/iF4ooAQTlr1+OxCsKP6wujLU59BYOkErq6LdCvwq/DPSX2A5LPDajN 5vZxyOM7I96/wWQ2Pm1AuDEbX+HSVPRtKnbixUMSTI13ODn/YGXC2UMg0YMADcOAaFqa BUCg== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:dkim-signature; bh=j6YBinbSKC+VO/40fmjfnW3oBGXvu+258psQuJf/bM0=; b=SO6d3X044G2cV8jxoDq79HzbXrn3vKTn52/3cOZAxpJkHvdkignqB9RPsgLmOXcmgS h0YTZuKIZzl1890GAgTlT4SWA0OKs6rK4uGKvXPIZbYKMrQ4FDWnkns+ZuVu7ylrsZjV t+rSV5ZzprGf4zuOtKpe0STbQqe6yy1aFp0/nlbaAcaFv5fnPkxXXkFwtQpGVme1cqZ4 DMRHVoKQrxIB9/o+ZEqRo/HGrhl4psIJjGyznmtXNAQn62kzsxb52Hj09+RGbYX2eMTT j9uQ0UOao68lRE93fAxApkD3TTC2xp2pFtcWTrm7gNl1kmI4U/xk+z+CLiZH4F5dD2n8 271w== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=WrySYmte; spf=pass (google.com: domain of dario.binacchi@amarulasolutions.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=dario.binacchi@amarulasolutions.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=amarulasolutions.com Received: from mail-sor-f41.google.com (mail-sor-f41.google.com. [209.85.220.41]) by mx.google.com with SMTPS id h26-20020a1709066d9a00b0078183bda914sor7391106ejt.37.2022.10.19.10.20.29 for (Google Transport Security); Wed, 19 Oct 2022 10:20:29 -0700 (PDT) Received-SPF: pass (google.com: domain of dario.binacchi@amarulasolutions.com designates 209.85.220.41 as permitted sender) client-ip=209.85.220.41; X-Received: by 2002:a17:907:320c:b0:77b:6f08:9870 with SMTP id xg12-20020a170907320c00b0077b6f089870mr7769063ejb.249.1666200028689; Wed, 19 Oct 2022 10:20:28 -0700 (PDT) Received: from dario-ThinkPad-T14s-Gen-2i.homenet.telecomitalia.it (host-95-233-42-253.retail.telecomitalia.it. [95.233.42.253]) by smtp.gmail.com with ESMTPSA id b27-20020a17090630db00b0073dbaeb50f6sm9237983ejb.169.2022.10.19.10.20.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Oct 2022 10:20:28 -0700 (PDT) From: Dario Binacchi To: linux-amarula@amarulasolutions.com Cc: anthony@amarulasolutions.com, jagan@amarulasolutions.com, dario.binacchi@amarulasolutions.com, michael@amarulasolutions.com, tommaso.merciai@amarulasolutions.com Subject: [RFC PATCH 6/8] clk: imx: pll14xx: support driver's registration by device tree Date: Wed, 19 Oct 2022 19:20:17 +0200 Message-Id: <20221019172019.2303223-7-dario.binacchi@amarulasolutions.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20221019172019.2303223-1-dario.binacchi@amarulasolutions.com> References: <20221019172019.2303223-1-dario.binacchi@amarulasolutions.com> MIME-Version: 1.0 X-Original-Sender: dario.binacchi@amarulasolutions.com X-Original-Authentication-Results: mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=WrySYmte; spf=pass (google.com: domain of dario.binacchi@amarulasolutions.com designates 209.85.220.41 as permitted sender) smtp.mailfrom=dario.binacchi@amarulasolutions.com; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=amarulasolutions.com Content-Type: text/plain; charset="UTF-8" Precedence: list Mailing-list: list linux-amarula@amarulasolutions.com; contact linux-amarula+owners@amarulasolutions.com List-ID: X-Spam-Checked-In-Group: linux-amarula@amarulasolutions.com X-Google-Group-Id: 476853432473 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , The patch, backwards compatible, extends the driver to be able to be registered from the device tree. Signed-off-by: Dario Binacchi --- drivers/clk/imx/clk-pll14xx.c | 242 ++++++++++++++++++++++++++++------ 1 file changed, 200 insertions(+), 42 deletions(-) diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c index 1d0f79e9c346..e7404bf5f6f2 100644 --- a/drivers/clk/imx/clk-pll14xx.c +++ b/drivers/clk/imx/clk-pll14xx.c @@ -12,6 +12,10 @@ #include #include #include +#include +#include +#include +#include #include #include @@ -36,7 +40,9 @@ struct clk_pll14xx { struct clk_hw hw; - void __iomem *base; + struct imx_clk_iomap gnrl_ctl; + struct imx_clk_iomap div_ctl0; + struct imx_clk_iomap div_ctl1; enum imx_pll14xx_type type; const struct imx_pll14xx_rate_table *rate_table; int rate_count; @@ -88,6 +94,30 @@ struct imx_pll14xx_clk imx_1416x_pll = { }; EXPORT_SYMBOL_GPL(imx_1416x_pll); +static void imx_pll14xx_writel(u32 val, const struct imx_clk_iomap *reg) +{ + if (reg->mem) + writel_relaxed(val, reg->mem + reg->offset); + else if (reg->regmap) + regmap_write(reg->regmap, reg->offset, val); + else + pr_err("%s: memory address not set\n", __func__); +} + +static u32 imx_pll14xx_readl(const struct imx_clk_iomap *reg) +{ + u32 val = 0; + + if (reg->mem) + val = readl_relaxed(reg->mem + reg->offset); + else if (reg->regmap) + regmap_read(reg->regmap, reg->offset, &val); + else + pr_err("%s: memory address not set\n", __func__); + + return val; +} + static const struct imx_pll14xx_rate_table *imx_get_pll_settings( struct clk_pll14xx *pll, unsigned long rate) { @@ -159,11 +189,11 @@ static void imx_pll14xx_calc_settings(struct clk_pll14xx *pll, unsigned long rat return; } - pll_div_ctl0 = readl_relaxed(pll->base + DIV_CTL0); + pll_div_ctl0 = imx_pll14xx_readl(&pll->div_ctl0); mdiv = FIELD_GET(MDIV_MASK, pll_div_ctl0); pdiv = FIELD_GET(PDIV_MASK, pll_div_ctl0); sdiv = FIELD_GET(SDIV_MASK, pll_div_ctl0); - pll_div_ctl1 = readl_relaxed(pll->base + DIV_CTL1); + pll_div_ctl1 = imx_pll14xx_readl(&pll->div_ctl1); /* Then see if we can get the desired rate by only adjusting kdiv (glitch free) */ rate_min = pll14xx_calc_rate(pll, mdiv, pdiv, sdiv, KDIV_MIN, prate); @@ -247,13 +277,13 @@ static unsigned long clk_pll14xx_recalc_rate(struct clk_hw *hw, struct clk_pll14xx *pll = to_clk_pll14xx(hw); u32 mdiv, pdiv, sdiv, kdiv, pll_div_ctl0, pll_div_ctl1; - pll_div_ctl0 = readl_relaxed(pll->base + DIV_CTL0); + pll_div_ctl0 = imx_pll14xx_readl(&pll->div_ctl0); mdiv = FIELD_GET(MDIV_MASK, pll_div_ctl0); pdiv = FIELD_GET(PDIV_MASK, pll_div_ctl0); sdiv = FIELD_GET(SDIV_MASK, pll_div_ctl0); if (pll->type == PLL_1443X) { - pll_div_ctl1 = readl_relaxed(pll->base + DIV_CTL1); + pll_div_ctl1 = imx_pll14xx_readl(&pll->div_ctl1); kdiv = FIELD_GET(KDIV_MASK, pll_div_ctl1); } else { kdiv = 0; @@ -275,10 +305,22 @@ static inline bool clk_pll14xx_mp_change(const struct imx_pll14xx_rate_table *ra static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll) { + struct imx_clk_iomap *reg = &pll->gnrl_ctl; u32 val; - return readl_poll_timeout(pll->base + GNRL_CTL, val, val & LOCK_STATUS, 0, - LOCK_TIMEOUT_US); + if (reg->mem) + return readl_poll_timeout(reg->mem + reg->offset, val, + val & LOCK_STATUS, 0, + LOCK_TIMEOUT_US); + + if (reg->regmap) + return regmap_read_poll_timeout(reg->regmap, reg->offset, val, + val & LOCK_STATUS, 0, + LOCK_TIMEOUT_US); + + pr_err("%s: memory address not set\n", __func__); + + return -EIO; } static int clk_pll1416x_set_rate(struct clk_hw *hw, unsigned long drate, @@ -296,32 +338,32 @@ static int clk_pll1416x_set_rate(struct clk_hw *hw, unsigned long drate, return -EINVAL; } - tmp = readl_relaxed(pll->base + DIV_CTL0); + tmp = imx_pll14xx_readl(&pll->div_ctl0); if (!clk_pll14xx_mp_change(rate, tmp)) { tmp &= ~SDIV_MASK; tmp |= FIELD_PREP(SDIV_MASK, rate->sdiv); - writel_relaxed(tmp, pll->base + DIV_CTL0); + imx_pll14xx_writel(tmp, &pll->div_ctl0); return 0; } /* Bypass clock and set lock to pll output lock */ - tmp = readl_relaxed(pll->base + GNRL_CTL); + tmp = imx_pll14xx_readl(&pll->gnrl_ctl); tmp |= LOCK_SEL_MASK; - writel_relaxed(tmp, pll->base + GNRL_CTL); + imx_pll14xx_writel(tmp, &pll->gnrl_ctl); /* Enable RST */ tmp &= ~RST_MASK; - writel_relaxed(tmp, pll->base + GNRL_CTL); + imx_pll14xx_writel(tmp, &pll->gnrl_ctl); /* Enable BYPASS */ tmp |= BYPASS_MASK; - writel(tmp, pll->base + GNRL_CTL); + imx_pll14xx_writel(tmp, &pll->gnrl_ctl); div_val = FIELD_PREP(MDIV_MASK, rate->mdiv) | FIELD_PREP(PDIV_MASK, rate->pdiv) | FIELD_PREP(SDIV_MASK, rate->sdiv); - writel_relaxed(div_val, pll->base + DIV_CTL0); + imx_pll14xx_writel(div_val, &pll->div_ctl0); /* * According to SPEC, t3 - t2 need to be greater than @@ -333,7 +375,7 @@ static int clk_pll1416x_set_rate(struct clk_hw *hw, unsigned long drate, /* Disable RST */ tmp |= RST_MASK; - writel_relaxed(tmp, pll->base + GNRL_CTL); + imx_pll14xx_writel(tmp, &pll->gnrl_ctl); /* Wait Lock */ ret = clk_pll14xx_wait_lock(pll); @@ -342,7 +384,7 @@ static int clk_pll1416x_set_rate(struct clk_hw *hw, unsigned long drate, /* Bypass */ tmp &= ~BYPASS_MASK; - writel_relaxed(tmp, pll->base + GNRL_CTL); + imx_pll14xx_writel(tmp, &pll->gnrl_ctl); return 0; } @@ -357,35 +399,35 @@ static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate, imx_pll14xx_calc_settings(pll, drate, prate, &rate); - div_ctl0 = readl_relaxed(pll->base + DIV_CTL0); + div_ctl0 = imx_pll14xx_readl(&pll->div_ctl0); if (!clk_pll14xx_mp_change(&rate, div_ctl0)) { /* only sdiv and/or kdiv changed - no need to RESET PLL */ div_ctl0 &= ~SDIV_MASK; div_ctl0 |= FIELD_PREP(SDIV_MASK, rate.sdiv); - writel_relaxed(div_ctl0, pll->base + DIV_CTL0); + imx_pll14xx_writel(div_ctl0, &pll->div_ctl0); - writel_relaxed(FIELD_PREP(KDIV_MASK, rate.kdiv), - pll->base + DIV_CTL1); + imx_pll14xx_writel(FIELD_PREP(KDIV_MASK, rate.kdiv), + &pll->div_ctl1); return 0; } /* Enable RST */ - gnrl_ctl = readl_relaxed(pll->base + GNRL_CTL); + gnrl_ctl = imx_pll14xx_readl(&pll->gnrl_ctl); gnrl_ctl &= ~RST_MASK; - writel_relaxed(gnrl_ctl, pll->base + GNRL_CTL); + imx_pll14xx_writel(gnrl_ctl, &pll->gnrl_ctl); /* Enable BYPASS */ gnrl_ctl |= BYPASS_MASK; - writel_relaxed(gnrl_ctl, pll->base + GNRL_CTL); + imx_pll14xx_writel(gnrl_ctl, &pll->gnrl_ctl); div_ctl0 = FIELD_PREP(MDIV_MASK, rate.mdiv) | FIELD_PREP(PDIV_MASK, rate.pdiv) | FIELD_PREP(SDIV_MASK, rate.sdiv); - writel_relaxed(div_ctl0, pll->base + DIV_CTL0); + imx_pll14xx_writel(div_ctl0, &pll->div_ctl0); - writel_relaxed(FIELD_PREP(KDIV_MASK, rate.kdiv), pll->base + DIV_CTL1); + imx_pll14xx_writel(FIELD_PREP(KDIV_MASK, rate.kdiv), &pll->div_ctl1); /* * According to SPEC, t3 - t2 need to be greater than @@ -397,7 +439,7 @@ static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate, /* Disable RST */ gnrl_ctl |= RST_MASK; - writel_relaxed(gnrl_ctl, pll->base + GNRL_CTL); + imx_pll14xx_writel(gnrl_ctl, &pll->gnrl_ctl); /* Wait Lock*/ ret = clk_pll14xx_wait_lock(pll); @@ -406,7 +448,7 @@ static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate, /* Bypass */ gnrl_ctl &= ~BYPASS_MASK; - writel_relaxed(gnrl_ctl, pll->base + GNRL_CTL); + imx_pll14xx_writel(gnrl_ctl, &pll->gnrl_ctl); return 0; } @@ -421,20 +463,20 @@ static int clk_pll14xx_prepare(struct clk_hw *hw) * RESETB = 1 from 0, PLL starts its normal * operation after lock time */ - val = readl_relaxed(pll->base + GNRL_CTL); + val = imx_pll14xx_readl(&pll->gnrl_ctl); if (val & RST_MASK) return 0; val |= BYPASS_MASK; - writel_relaxed(val, pll->base + GNRL_CTL); + imx_pll14xx_writel(val, &pll->gnrl_ctl); val |= RST_MASK; - writel_relaxed(val, pll->base + GNRL_CTL); + imx_pll14xx_writel(val, &pll->gnrl_ctl); ret = clk_pll14xx_wait_lock(pll); if (ret) return ret; val &= ~BYPASS_MASK; - writel_relaxed(val, pll->base + GNRL_CTL); + imx_pll14xx_writel(val, &pll->gnrl_ctl); return 0; } @@ -444,7 +486,7 @@ static int clk_pll14xx_is_prepared(struct clk_hw *hw) struct clk_pll14xx *pll = to_clk_pll14xx(hw); u32 val; - val = readl_relaxed(pll->base + GNRL_CTL); + val = imx_pll14xx_readl(&pll->gnrl_ctl); return (val & RST_MASK) ? 1 : 0; } @@ -458,9 +500,9 @@ static void clk_pll14xx_unprepare(struct clk_hw *hw) * Set RST to 0, power down mode is enabled and * every digital block is reset */ - val = readl_relaxed(pll->base + GNRL_CTL); + val = imx_pll14xx_readl(&pll->gnrl_ctl); val &= ~RST_MASK; - writel_relaxed(val, pll->base + GNRL_CTL); + imx_pll14xx_writel(val, &pll->gnrl_ctl); } static const struct clk_ops clk_pll1416x_ops = { @@ -485,13 +527,23 @@ static const struct clk_ops clk_pll1443x_ops = { .set_rate = clk_pll1443x_set_rate, }; -struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name, - const char *parent_name, void __iomem *base, - const struct imx_pll14xx_clk *pll_clk) +static void imx_clk_hw_unregister_pll14xx(struct clk_hw *hw) { + struct clk_pll14xx *pll = to_clk_pll14xx(hw); + + clk_hw_unregister(hw); + kfree(pll); +} + +static struct clk_hw * +imx_clk_hw_register_pll14xx(struct device *dev, const char *name, + const char *parent_name, + struct imx_clk_iomap *iomap, + const struct imx_pll14xx_clk *pll_clk) +{ + struct clk_init_data init = { NULL }; struct clk_pll14xx *pll; struct clk_hw *hw; - struct clk_init_data init; int ret; u32 val; @@ -520,18 +572,23 @@ struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name, return ERR_PTR(-EINVAL); } - pll->base = base; + memcpy(&pll->gnrl_ctl, iomap, sizeof(*iomap)); + pll->gnrl_ctl.offset += GNRL_CTL; + memcpy(&pll->div_ctl0, iomap, sizeof(*iomap)); + pll->div_ctl0.offset += DIV_CTL0; + memcpy(&pll->div_ctl1, iomap, sizeof(*iomap)); + pll->div_ctl1.offset += DIV_CTL1; + pll->hw.init = &init; pll->type = pll_clk->type; pll->rate_table = pll_clk->rate_table; pll->rate_count = pll_clk->rate_count; - val = readl_relaxed(pll->base + GNRL_CTL); + val = imx_pll14xx_readl(&pll->gnrl_ctl); val &= ~BYPASS_MASK; - writel_relaxed(val, pll->base + GNRL_CTL); + imx_pll14xx_writel(val, &pll->gnrl_ctl); hw = &pll->hw; - ret = clk_hw_register(dev, hw); if (ret) { pr_err("failed to register pll %s %d\n", name, ret); @@ -541,4 +598,105 @@ struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name, return hw; } + +struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name, + const char *parent_name, void __iomem *base, + const struct imx_pll14xx_clk *pll_clk) +{ + struct imx_clk_iomap _base = {}; + + _base.mem = base; + return imx_clk_hw_register_pll14xx(dev, name, parent_name, &_base, + pll_clk); +} EXPORT_SYMBOL_GPL(imx_dev_clk_hw_pll14xx); + +static struct clk_hw *_of_imx_pll14xx_clk_setup(struct device_node *node) +{ + struct clk_hw *hw; + struct imx_clk_iomap io; + struct device_node *parent_node; + const char *name, *parent_name; + const struct imx_pll14xx_clk *pll_clk; + const char *pll_type; + u32 val; + int ret; + + parent_node = of_get_parent(node); + if (!parent_node) { + pr_err("%s: %pOFn must have 1 parent\n", __func__, node); + return ERR_PTR(-ENODEV); + } + + io.mem = 0; + io.regmap = syscon_node_to_regmap(parent_node); + of_node_put(parent_node); + if (IS_ERR(io.regmap)) { + pr_err("%s: missing regmap for %pOFn\n", __func__, node); + return ERR_CAST(io.regmap); + } + + if (of_property_read_u32(node, "fsl,regmap-offset", &val)) { + pr_err("%s: missing regmap offset for %pOFn\n", __func__, + node); + return ERR_PTR(-EIO); + } + + io.offset = val; + if (of_clk_get_parent_count(node) != 1) { + pr_err("%s: %pOFn must have 1 parent clock\n", __func__, node); + return ERR_PTR(-EIO); + } + + parent_name = of_clk_get_parent_name(node, 0); + name = imx_dt_clk_name(node); + if (of_property_read_string(node, "fsl,type", &pll_type)) { + pr_err("%s: missing 'fsl,type' for %pOFn\n", __func__, + node); + return ERR_PTR(-EIO); + } + + if (!strcmp(pll_type, "1443x")) { + if (of_property_read_bool(node, "fsl,get-rate-nocache")) + pll_clk = &imx_1443x_dram_pll; + else + pll_clk = &imx_1443x_pll; + } else if (!strcmp(pll_type, "1416x")) { + pll_clk = &imx_1416x_pll; + } else { + pr_err("%s: failed to get pll clock for %pOFn\n", __func__, + node); + return ERR_PTR(-EIO); + } + + hw = imx_clk_hw_register_pll14xx(NULL, name, parent_name, &io, pll_clk); + if (IS_ERR(hw)) { + /* + * Clear OF_POPULATED flag so that clock registration can be + * attempted again from probe function. + */ + of_node_clear_flag(node, OF_POPULATED); + return ERR_CAST(hw); + } + + ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw); + if (ret) { + imx_clk_hw_unregister_pll14xx(hw); + return ERR_PTR(ret); + } + + pr_debug("%s: name: %s, parent: %s, offset: 0x%x, pll_type: %s\n", + __func__, name, parent_name, io.offset, pll_type); + + return hw; +} + +/** + * of_imx_pll14xx_clk_setup() - Setup function for imx pll14xx clock + * @node: device node for the clock + */ +void __init of_imx_pll14xx_clk_setup(struct device_node *node) +{ + _of_imx_pll14xx_clk_setup(node); +} +CLK_OF_DECLARE(fsl_pll14xx_clk, "fsl,pll14xx-clock", of_imx_pll14xx_clk_setup);