From patchwork Sun Jan 1 17:57:35 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dario Binacchi X-Patchwork-Id: 2599 Return-Path: X-Original-To: linux-amarula@patchwork.amarulasolutions.com Delivered-To: linux-amarula@patchwork.amarulasolutions.com Received: from mail-ed1-f69.google.com (mail-ed1-f69.google.com [209.85.208.69]) by ganimede.amarulasolutions.com (Postfix) with ESMTPS id E321540F49 for ; Sun, 1 Jan 2023 18:57:56 +0100 (CET) Received: by mail-ed1-f69.google.com with SMTP id w18-20020a05640234d200b0048cc3aa4993sf1436749edc.7 for ; Sun, 01 Jan 2023 09:57:56 -0800 (PST) ARC-Seal: i=2; a=rsa-sha256; t=1672595876; cv=pass; d=google.com; s=arc-20160816; b=SkCodNYzBuFt7XaJNS3Z5MxVjFM4XMoY2VlMW8stxy/RxDbQbxsRb1mSE3bQMdDxNf pCQffnZBv5bGNBGNa9QOz2QVeiSnlL9ptrvsfNZ5tjzoIMUmx69J+Z2DEa36b5WQGJFH h+OJi0fXseYYL6/vSwj4Z6ATuaUM2r04//Rptodz5Qvr8tkPJz5wwLHM/vjuOssrmC22 cqgdKDvAK5SI29ecsMnJ0aPsWVP2x3LrI9M2evg6i6dc5y73loQl9mElWwPWSp/4KzQk v5IK5GBkh2Lmiw81BawLEsRWhfrr2KoEhWEdUaBiXquJKl9YfjfPI7U4YJ2khAnbbVuV fINg== 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=+19LNr2TmHtC+7kCqTM1LXlZt7axM08EJ57jSahMhkA=; b=J38K/u4lVe+AuRjd2zg76os1HKSdHMdKi2EwRfgSi8KvQtYaJ+ms6eIDA7hN0wKaXY kD9rB7TVKfYKNDaPxB++GJrlHO31nNuaHSpI5a3wO0sE2NISD4chlgvm0pcpB3QH9ZBM AcY1eF5+uBSxS9qhhLEbXZhwG3rSVL/47N7ybMlOCOxb7votDclBw/ECsKbZnNdwjD0v zq+d+yezklXjPGUQ+mSZLnbevmn3ERvU4CnA6iCFpRmQl3snupFIKO+6+PzrCorESDeF /LVq397zJo0lt0HKJdsB8sxUWMGGD9kLEQBKgEINsHqMBv61Gr6NJUzOxCN3pzBHisYQ zHmg== ARC-Authentication-Results: i=2; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=O4SyjwrR; spf=pass (google.com: domain of dario.binacchi@amarulasolutions.com designates 209.85.220.65 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=+19LNr2TmHtC+7kCqTM1LXlZt7axM08EJ57jSahMhkA=; b=irDlpIYwaZJ8LbX36hszeAVyTSXIvOUCtFKy9m/LOPOXCj5sdLhMGGmjH5FAv7bzAL qfxd7msM5V2VEfDKg4Un5/9aNGWNIUeZiE1D+xosqJqGXKdLJfp5fRtXm8ukgTlFGG08 Il34mnh6YMj2piyuj0sZeEQgZy51fpIpiDUEE= 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=+19LNr2TmHtC+7kCqTM1LXlZt7axM08EJ57jSahMhkA=; b=covt+aDeXK3UK4CkAQVMoZxyj6sUksmMMyfzaZmUPjKO45f/qhkXbXXrgYj3jKIgrV ahpoYigKUiKs59XeawdiWApDK4Wb4OzQ+4uZsvKChGAE2ttnzcnj36uJPjZmYmckQQ5x 1KBdZsVfPo7DwC9Mgo/VgIGS5AuLnw9xGSA7/mYgn5FQDw65/wwx2/tEJBWM68GjRYz0 zdZVJZwueEL4+vxCcTUpBEv3xkn6s+VhzyxgXOMEMmjax60gh1AeoOCUAi1lw4edHQpw N06TS1Q85mRSdEOuXX41fa4FQmoiMwfe8/9+ANDlI6Xi0tu8GRZNshCrFgxN7vSVP9sl p1sQ== X-Gm-Message-State: AFqh2krldajXHNoEanCAJySsgynmJGtPbdB6mE5iUQ0Ve78LZNDvlgmM +6uwcw8C/co2zcrz6XGViKDt3J4R X-Google-Smtp-Source: AMrXdXtqV5GrBuO4bfMhVsAh6crHeBtssS6yuIo+GT7qVamW+/N116tHBXtiubshzTMvqAhoXXcoag== X-Received: by 2002:a17:906:280d:b0:7c1:4f24:98a4 with SMTP id r13-20020a170906280d00b007c14f2498a4mr3209430ejc.41.1672595876742; Sun, 01 Jan 2023 09:57:56 -0800 (PST) X-BeenThere: linux-amarula@amarulasolutions.com Received: by 2002:a17:906:2ed7:b0:7ae:83f4:3bed with SMTP id s23-20020a1709062ed700b007ae83f43bedls2016490eji.2.-pod-prod-gmail; Sun, 01 Jan 2023 09:57:55 -0800 (PST) X-Received: by 2002:a17:907:a08d:b0:7c0:dac7:36d8 with SMTP id hu13-20020a170907a08d00b007c0dac736d8mr34264691ejc.10.1672595875715; Sun, 01 Jan 2023 09:57:55 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1672595875; cv=none; d=google.com; s=arc-20160816; b=HB1MMIC9Z92PXIxE27NqL2DH3QyJs5jpLSkWt2eeVXK3Q24baHuu6nMaDJZZvHqXnf YMb7C6v9EmpOD8XxwQMBBElthi8lqTj6UDlYtdLVt2eNROSwUhCsLoCRJucGKknkgYxJ JJ69sZtgYY5TPm+azfcicDhrjsgYcuhtWr+Mq8JT/rEU9MbJ1qQNPZhwmTfZR4sFc8mE mSRcxF1J2LhgZZX4s+VT93zcM0k3z74OmP4LBTi2sFO7FZ3zKZC1d+jxmbEN/pg81EeN OuR2zagwAz9eMxqLpB62qCMtKrAz1IjoT2E7s8EyvVCCvwi0LrgfGZEiS8ztBg+wmne+ kxZg== 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=zrbxkXpog4qNAkw1QjCrHsgv8afYOfm6Gannx3KUosE=; b=dNnVxdcUxX50EkN7tdnD/B0UbFz2BAyYLHY3O6vjRQJ5oF1a0dX3NvaBYIqCSCMqsg 3ar9+aOnV5sF4O1ryjOVyDSIzQ/W3LtmDACq2ur0yM51+FU14yPdcpkksUjA6uWUJHjK +9B3E22rj1COaZZHtYidU/Z7sIDOgKJvYJEOOmrPWpPg9Wm6gKDYDR4SZtq6uedYdIia 35KK5lVqWjLc9xPxd8lBHwOqoWhLLNDUEXI0ZUGUx7RWM/rOxNixagpNs9ZIeh2S8NGY UF2dTxzaTzpg/uzz36Q1S3pAXga1aKKSoThcF/YnPZRuLTZdr9My2cIKYxJ6OikZ5WRq dMtg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@amarulasolutions.com header.s=google header.b=O4SyjwrR; spf=pass (google.com: domain of dario.binacchi@amarulasolutions.com designates 209.85.220.65 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-f65.google.com (mail-sor-f65.google.com. [209.85.220.65]) by mx.google.com with SMTPS id o22-20020a170906601600b007c4ec3563c2sor11641184ejj.34.2023.01.01.09.57.55 for (Google Transport Security); Sun, 01 Jan 2023 09:57:55 -0800 (PST) Received-SPF: pass (google.com: domain of dario.binacchi@amarulasolutions.com designates 209.85.220.65 as permitted sender) client-ip=209.85.220.65; X-Received: by 2002:a17:907:3e96:b0:7c4:f501:e5b1 with SMTP id hs22-20020a1709073e9600b007c4f501e5b1mr44824314ejc.51.1672595875491; Sun, 01 Jan 2023 09:57:55 -0800 (PST) Received: from dario-ThinkPad-T14s-Gen-2i.homenet.telecomitalia.it (host-80-180-23-57.retail.telecomitalia.it. [80.180.23.57]) by smtp.gmail.com with ESMTPSA id q2-20020a1709063d4200b0082ddfb47d06sm12273018ejf.148.2023.01.01.09.57.54 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 01 Jan 2023 09:57:55 -0800 (PST) From: Dario Binacchi To: linux-kernel@vger.kernel.org Cc: angelo@amarulasolutions.com, michael@amarulasolutions.com, tommaso.merciai@amarulasolutions.com, Chen-Yu Tsai , linux-amarula@amarulasolutions.com, anthony@amarulasolutions.com, jagan@amarulasolutions.com, Dario Binacchi , Abel Vesa , Fabio Estevam , Michael Turquette , NXP Linux Team , Pengutronix Kernel Team , Sascha Hauer , Shawn Guo , Stephen Boyd , linux-arm-kernel@lists.infradead.org, linux-clk@vger.kernel.org Subject: [RFC PATCH v2 06/11] clk: imx: pll14xx: add device tree support Date: Sun, 1 Jan 2023 18:57:35 +0100 Message-Id: <20230101175740.1010258-7-dario.binacchi@amarulasolutions.com> X-Mailer: git-send-email 2.32.0 In-Reply-To: <20230101175740.1010258-1-dario.binacchi@amarulasolutions.com> References: <20230101175740.1010258-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=O4SyjwrR; spf=pass (google.com: domain of dario.binacchi@amarulasolutions.com designates 209.85.220.65 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 initialize the clock directly from the device tree. Signed-off-by: Dario Binacchi --- (no changes since v1) drivers/clk/imx/clk-pll14xx.c | 220 +++++++++++++++++++++++++++------- 1 file changed, 176 insertions(+), 44 deletions(-) diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c index 828336873a98..6503005b885a 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_reg gnrl_ctl; + struct imx_clk_reg div_ctl0; + struct imx_clk_reg div_ctl1; enum imx_pll14xx_type type; const struct imx_pll14xx_rate_table *rate_table; int rate_count; @@ -90,6 +96,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_reg *reg) +{ + if (reg->base) + writel_relaxed(val, reg->base + 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_reg *reg) +{ + u32 val = 0; + + if (reg->base) + val = readl_relaxed(reg->base + 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) { @@ -161,11 +191,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); @@ -249,13 +279,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; @@ -277,10 +307,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_reg *reg = &pll->gnrl_ctl; u32 val; - return readl_poll_timeout(pll->base + GNRL_CTL, val, val & LOCK_STATUS, 0, - LOCK_TIMEOUT_US); + if (reg->base) + return readl_poll_timeout(reg->base + 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, @@ -298,32 +340,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 @@ -335,7 +377,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); @@ -344,7 +386,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; } @@ -359,35 +401,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 @@ -399,7 +441,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); @@ -408,7 +450,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; } @@ -423,20 +465,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; } @@ -446,7 +488,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; } @@ -460,9 +502,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 = { @@ -487,13 +529,24 @@ 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_node *node, const char *name, + const char *parent_name, + struct imx_clk_reg *iomap, + const struct imx_pll14xx_clk *pll_clk) +{ + struct clk_parent_data pdata = { .index = 0 }; + struct clk_init_data init = { NULL }; struct clk_pll14xx *pll; struct clk_hw *hw; - struct clk_init_data init; int ret; u32 val; @@ -503,7 +556,8 @@ struct clk_hw *imx_dev_clk_hw_pll14xx(struct device *dev, const char *name, init.name = name; init.flags = pll_clk->flags; - init.parent_names = &parent_name; + init.parent_names = parent_name ? &parent_name : NULL; + init.parent_data = &pdata; init.num_parents = 1; switch (pll_clk->type) { @@ -522,19 +576,24 @@ 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); + ret = of_clk_hw_register(node, hw); if (ret) { pr_err("failed to register pll %s %d\n", name, ret); kfree(pll); @@ -543,4 +602,77 @@ 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_reg iomap = {}; + + iomap.base = base; + return imx_clk_hw_register_pll14xx(dev_of_node(dev), name, parent_name, + &iomap, pll_clk); +} EXPORT_SYMBOL_GPL(imx_dev_clk_hw_pll14xx); + +/** + * of_imx_pll14xx_clk_setup() - Setup function for imx pll14xx clock + * @node: device node for the clock + */ +static void __init of_imx_pll14xx_clk_setup(struct device_node *node) +{ + struct clk_hw *hw; + struct imx_clk_reg iomap = {}; + const char *name = node->name; + const struct imx_pll14xx_clk *pll_clk; + const char *pll_type; + u32 val; + + iomap.regmap = syscon_regmap_lookup_by_phandle(node, "fsl,anatop"); + if (IS_ERR(iomap.regmap)) { + pr_err("missing regmap for %pOFn\n", node); + return; + } + + if (of_property_read_u32_index(node, "fsl,anatop", 1, &val)) { + pr_err("missing register offset for %pOFn\n", node); + return; + } + + iomap.offset = val; + if (of_clk_get_parent_count(node) != 1) { + pr_err("%pOFn must have 1 parent clock\n", node); + return; + } + + of_property_read_string(node, "clock-output-names", &name); + if (of_property_read_string(node, "fsl,type", &pll_type)) { + pr_err("missing 'fsl,type' for %pOFn\n", node); + return; + } + + 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("failed to get pll clock for %pOFn\n", node); + return; + } + + hw = imx_clk_hw_register_pll14xx(node, name, NULL, &iomap, pll_clk); + if (IS_ERR(hw)) + return; + + if (of_clk_add_hw_provider(node, of_clk_hw_simple_get, hw)) { + imx_clk_hw_unregister_pll14xx(hw); + return; + } + + pr_debug("name: %s, offset: 0x%x, pll_type: %s\n", name, iomap.offset, + pll_type); +} +CLK_OF_DECLARE(fsl_pll14xx_clk, "fsl,pll14xx-clock", of_imx_pll14xx_clk_setup);