| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850 |
- // SPDX-License-Identifier: GPL-2.0-or-later
- /*
- * Clock control for Cirrus EP93xx chips.
- * Copyright (C) 2021 Nikita Shubin <nikita.shubin@maquefel.me>
- *
- * Based on a rewrite of arch/arm/mach-ep93xx/clock.c:
- * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
- */
- #define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
- #include <linux/bits.h>
- #include <linux/cleanup.h>
- #include <linux/clk-provider.h>
- #include <linux/math.h>
- #include <linux/platform_device.h>
- #include <linux/regmap.h>
- #include <linux/spinlock.h>
- #include <linux/soc/cirrus/ep93xx.h>
- #include <dt-bindings/clock/cirrus,ep9301-syscon.h>
- #include <asm/div64.h>
- #define EP93XX_EXT_CLK_RATE 14745600
- #define EP93XX_EXT_RTC_RATE 32768
- #define EP93XX_SYSCON_POWER_STATE 0x00
- #define EP93XX_SYSCON_PWRCNT 0x04
- #define EP93XX_SYSCON_PWRCNT_UARTBAUD BIT(29)
- #define EP93XX_SYSCON_PWRCNT_USH_EN 28
- #define EP93XX_SYSCON_PWRCNT_DMA_M2M1 27
- #define EP93XX_SYSCON_PWRCNT_DMA_M2M0 26
- #define EP93XX_SYSCON_PWRCNT_DMA_M2P8 25
- #define EP93XX_SYSCON_PWRCNT_DMA_M2P9 24
- #define EP93XX_SYSCON_PWRCNT_DMA_M2P6 23
- #define EP93XX_SYSCON_PWRCNT_DMA_M2P7 22
- #define EP93XX_SYSCON_PWRCNT_DMA_M2P4 21
- #define EP93XX_SYSCON_PWRCNT_DMA_M2P5 20
- #define EP93XX_SYSCON_PWRCNT_DMA_M2P2 19
- #define EP93XX_SYSCON_PWRCNT_DMA_M2P3 18
- #define EP93XX_SYSCON_PWRCNT_DMA_M2P0 17
- #define EP93XX_SYSCON_PWRCNT_DMA_M2P1 16
- #define EP93XX_SYSCON_CLKSET1 0x20
- #define EP93XX_SYSCON_CLKSET1_NBYP1 BIT(23)
- #define EP93XX_SYSCON_CLKSET2 0x24
- #define EP93XX_SYSCON_CLKSET2_NBYP2 BIT(19)
- #define EP93XX_SYSCON_CLKSET2_PLL2_EN BIT(18)
- #define EP93XX_SYSCON_DEVCFG 0x80
- #define EP93XX_SYSCON_DEVCFG_U3EN 24
- #define EP93XX_SYSCON_DEVCFG_U2EN 20
- #define EP93XX_SYSCON_DEVCFG_U1EN 18
- #define EP93XX_SYSCON_VIDCLKDIV 0x84
- #define EP93XX_SYSCON_CLKDIV_ENABLE 15
- #define EP93XX_SYSCON_CLKDIV_ESEL BIT(14)
- #define EP93XX_SYSCON_CLKDIV_PSEL BIT(13)
- #define EP93XX_SYSCON_CLKDIV_MASK GENMASK(14, 13)
- #define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8
- #define EP93XX_SYSCON_I2SCLKDIV 0x8c
- #define EP93XX_SYSCON_I2SCLKDIV_SENA 31
- #define EP93XX_SYSCON_I2SCLKDIV_ORIDE BIT(29)
- #define EP93XX_SYSCON_I2SCLKDIV_SPOL BIT(19)
- #define EP93XX_SYSCON_KEYTCHCLKDIV 0x90
- #define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN 31
- #define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV 16
- #define EP93XX_SYSCON_KEYTCHCLKDIV_KEN 15
- #define EP93XX_SYSCON_KEYTCHCLKDIV_KDIV 0
- #define EP93XX_SYSCON_CHIPID 0x94
- #define EP93XX_SYSCON_CHIPID_ID 0x9213
- #define EP93XX_FIXED_CLK_COUNT 21
- static const char ep93xx_adc_divisors[] = { 16, 4 };
- static const char ep93xx_sclk_divisors[] = { 2, 4 };
- static const char ep93xx_lrclk_divisors[] = { 32, 64, 128 };
- struct ep93xx_clk {
- struct clk_hw hw;
- u16 idx;
- u16 reg;
- u32 mask;
- u8 bit_idx;
- u8 shift;
- u8 width;
- u8 num_div;
- const char *div;
- };
- struct ep93xx_clk_priv {
- spinlock_t lock;
- struct ep93xx_regmap_adev *aux_dev;
- struct device *dev;
- void __iomem *base;
- struct regmap *map;
- struct clk_hw *fixed[EP93XX_FIXED_CLK_COUNT];
- struct ep93xx_clk reg[];
- };
- static struct ep93xx_clk *ep93xx_clk_from(struct clk_hw *hw)
- {
- return container_of(hw, struct ep93xx_clk, hw);
- }
- static struct ep93xx_clk_priv *ep93xx_priv_from(struct ep93xx_clk *clk)
- {
- return container_of(clk, struct ep93xx_clk_priv, reg[clk->idx]);
- }
- static void ep93xx_clk_write(struct ep93xx_clk_priv *priv, unsigned int reg, unsigned int val)
- {
- struct ep93xx_regmap_adev *aux = priv->aux_dev;
- aux->write(aux->map, aux->lock, reg, val);
- }
- static int ep93xx_clk_is_enabled(struct clk_hw *hw)
- {
- struct ep93xx_clk *clk = ep93xx_clk_from(hw);
- struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
- u32 val;
- regmap_read(priv->map, clk->reg, &val);
- return !!(val & BIT(clk->bit_idx));
- }
- static int ep93xx_clk_enable(struct clk_hw *hw)
- {
- struct ep93xx_clk *clk = ep93xx_clk_from(hw);
- struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
- u32 val;
- guard(spinlock_irqsave)(&priv->lock);
- regmap_read(priv->map, clk->reg, &val);
- val |= BIT(clk->bit_idx);
- ep93xx_clk_write(priv, clk->reg, val);
- return 0;
- }
- static void ep93xx_clk_disable(struct clk_hw *hw)
- {
- struct ep93xx_clk *clk = ep93xx_clk_from(hw);
- struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
- u32 val;
- guard(spinlock_irqsave)(&priv->lock);
- regmap_read(priv->map, clk->reg, &val);
- val &= ~BIT(clk->bit_idx);
- ep93xx_clk_write(priv, clk->reg, val);
- }
- static const struct clk_ops clk_ep93xx_gate_ops = {
- .enable = ep93xx_clk_enable,
- .disable = ep93xx_clk_disable,
- .is_enabled = ep93xx_clk_is_enabled,
- };
- static int ep93xx_clk_register_gate(struct ep93xx_clk *clk,
- const char *name,
- struct clk_parent_data *parent_data,
- unsigned long flags,
- unsigned int reg,
- u8 bit_idx)
- {
- struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
- struct clk_init_data init = { };
- init.name = name;
- init.ops = &clk_ep93xx_gate_ops;
- init.flags = flags;
- init.parent_data = parent_data;
- init.num_parents = 1;
- clk->reg = reg;
- clk->bit_idx = bit_idx;
- clk->hw.init = &init;
- return devm_clk_hw_register(priv->dev, &clk->hw);
- }
- static u8 ep93xx_mux_get_parent(struct clk_hw *hw)
- {
- struct ep93xx_clk *clk = ep93xx_clk_from(hw);
- struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
- u32 val;
- regmap_read(priv->map, clk->reg, &val);
- val &= EP93XX_SYSCON_CLKDIV_MASK;
- switch (val) {
- case EP93XX_SYSCON_CLKDIV_ESEL:
- return 1; /* PLL1 */
- case EP93XX_SYSCON_CLKDIV_MASK:
- return 2; /* PLL2 */
- default:
- return 0; /* XTALI */
- };
- }
- static int ep93xx_mux_set_parent_lock(struct clk_hw *hw, u8 index)
- {
- struct ep93xx_clk *clk = ep93xx_clk_from(hw);
- struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
- u32 val;
- if (index >= 3)
- return -EINVAL;
- guard(spinlock_irqsave)(&priv->lock);
- regmap_read(priv->map, clk->reg, &val);
- val &= ~(EP93XX_SYSCON_CLKDIV_MASK);
- val |= index > 0 ? EP93XX_SYSCON_CLKDIV_ESEL : 0;
- val |= index > 1 ? EP93XX_SYSCON_CLKDIV_PSEL : 0;
- ep93xx_clk_write(priv, clk->reg, val);
- return 0;
- }
- static bool is_best(unsigned long rate, unsigned long now,
- unsigned long best)
- {
- return abs_diff(rate, now) < abs_diff(rate, best);
- }
- static int ep93xx_mux_determine_rate(struct clk_hw *hw,
- struct clk_rate_request *req)
- {
- unsigned long best_rate = 0, actual_rate, mclk_rate;
- unsigned long rate = req->rate;
- struct clk_hw *parent_best = NULL;
- unsigned long parent_rate_best;
- unsigned long parent_rate;
- int div, pdiv;
- unsigned int i;
- /*
- * Try the two pll's and the external clock,
- * because the valid predividers are 2, 2.5 and 3, we multiply
- * all the clocks by 2 to avoid floating point math.
- *
- * This is based on the algorithm in the ep93xx raster guide:
- * http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf
- *
- */
- for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
- struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i);
- parent_rate = clk_hw_get_rate(parent);
- mclk_rate = parent_rate * 2;
- /* Try each predivider value */
- for (pdiv = 4; pdiv <= 6; pdiv++) {
- div = DIV_ROUND_CLOSEST(mclk_rate, rate * pdiv);
- if (!in_range(div, 1, 127))
- continue;
- actual_rate = DIV_ROUND_CLOSEST(mclk_rate, pdiv * div);
- if (is_best(rate, actual_rate, best_rate)) {
- best_rate = actual_rate;
- parent_rate_best = parent_rate;
- parent_best = parent;
- }
- }
- }
- if (!parent_best)
- return -EINVAL;
- req->best_parent_rate = parent_rate_best;
- req->best_parent_hw = parent_best;
- req->rate = best_rate;
- return 0;
- }
- static unsigned long ep93xx_ddiv_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
- {
- struct ep93xx_clk *clk = ep93xx_clk_from(hw);
- struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
- unsigned int pdiv, div;
- u32 val;
- regmap_read(priv->map, clk->reg, &val);
- pdiv = (val >> EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) & GENMASK(1, 0);
- div = val & GENMASK(6, 0);
- if (!div)
- return 0;
- return DIV_ROUND_CLOSEST(parent_rate * 2, (pdiv + 3) * div);
- }
- static int ep93xx_ddiv_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
- {
- struct ep93xx_clk *clk = ep93xx_clk_from(hw);
- struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
- int pdiv, div, npdiv, ndiv;
- unsigned long actual_rate, mclk_rate, rate_err = ULONG_MAX;
- u32 val;
- regmap_read(priv->map, clk->reg, &val);
- mclk_rate = parent_rate * 2;
- for (pdiv = 4; pdiv <= 6; pdiv++) {
- div = DIV_ROUND_CLOSEST(mclk_rate, rate * pdiv);
- if (!in_range(div, 1, 127))
- continue;
- actual_rate = DIV_ROUND_CLOSEST(mclk_rate, pdiv * div);
- if (abs(actual_rate - rate) < rate_err) {
- npdiv = pdiv - 3;
- ndiv = div;
- rate_err = abs(actual_rate - rate);
- }
- }
- if (rate_err == ULONG_MAX)
- return -EINVAL;
- /*
- * Clear old dividers.
- * Bit 7 is reserved bit in all ClkDiv registers.
- */
- val &= ~(GENMASK(9, 0) & ~BIT(7));
- /* Set the new pdiv and div bits for the new clock rate */
- val |= (npdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | ndiv;
- ep93xx_clk_write(priv, clk->reg, val);
- return 0;
- }
- static const struct clk_ops clk_ddiv_ops = {
- .enable = ep93xx_clk_enable,
- .disable = ep93xx_clk_disable,
- .is_enabled = ep93xx_clk_is_enabled,
- .get_parent = ep93xx_mux_get_parent,
- .set_parent = ep93xx_mux_set_parent_lock,
- .determine_rate = ep93xx_mux_determine_rate,
- .recalc_rate = ep93xx_ddiv_recalc_rate,
- .set_rate = ep93xx_ddiv_set_rate,
- };
- static int ep93xx_clk_register_ddiv(struct ep93xx_clk *clk,
- const char *name,
- struct clk_parent_data *parent_data,
- u8 num_parents,
- unsigned int reg,
- u8 bit_idx)
- {
- struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
- struct clk_init_data init = { };
- init.name = name;
- init.ops = &clk_ddiv_ops;
- init.flags = 0;
- init.parent_data = parent_data;
- init.num_parents = num_parents;
- clk->reg = reg;
- clk->bit_idx = bit_idx;
- clk->hw.init = &init;
- return devm_clk_hw_register(priv->dev, &clk->hw);
- }
- static unsigned long ep93xx_div_recalc_rate(struct clk_hw *hw,
- unsigned long parent_rate)
- {
- struct ep93xx_clk *clk = ep93xx_clk_from(hw);
- struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
- u32 val;
- u8 index;
- regmap_read(priv->map, clk->reg, &val);
- index = (val & clk->mask) >> clk->shift;
- if (index >= clk->num_div)
- return 0;
- return DIV_ROUND_CLOSEST(parent_rate, clk->div[index]);
- }
- static long ep93xx_div_round_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long *parent_rate)
- {
- struct ep93xx_clk *clk = ep93xx_clk_from(hw);
- unsigned long best = 0, now;
- unsigned int i;
- for (i = 0; i < clk->num_div; i++) {
- if ((rate * clk->div[i]) == *parent_rate)
- return rate;
- now = DIV_ROUND_CLOSEST(*parent_rate, clk->div[i]);
- if (!best || is_best(rate, now, best))
- best = now;
- }
- return best;
- }
- static int ep93xx_div_set_rate(struct clk_hw *hw, unsigned long rate,
- unsigned long parent_rate)
- {
- struct ep93xx_clk *clk = ep93xx_clk_from(hw);
- struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
- unsigned int i;
- u32 val;
- regmap_read(priv->map, clk->reg, &val);
- val &= ~clk->mask;
- for (i = 0; i < clk->num_div; i++)
- if (rate == DIV_ROUND_CLOSEST(parent_rate, clk->div[i]))
- break;
- if (i == clk->num_div)
- return -EINVAL;
- val |= i << clk->shift;
- ep93xx_clk_write(priv, clk->reg, val);
- return 0;
- }
- static const struct clk_ops ep93xx_div_ops = {
- .enable = ep93xx_clk_enable,
- .disable = ep93xx_clk_disable,
- .is_enabled = ep93xx_clk_is_enabled,
- .recalc_rate = ep93xx_div_recalc_rate,
- .round_rate = ep93xx_div_round_rate,
- .set_rate = ep93xx_div_set_rate,
- };
- static int ep93xx_register_div(struct ep93xx_clk *clk,
- const char *name,
- const struct clk_parent_data *parent_data,
- unsigned int reg,
- u8 enable_bit,
- u8 shift,
- u8 width,
- const char *clk_divisors,
- u8 num_div)
- {
- struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
- struct clk_init_data init = { };
- init.name = name;
- init.ops = &ep93xx_div_ops;
- init.flags = 0;
- init.parent_data = parent_data;
- init.num_parents = 1;
- clk->reg = reg;
- clk->bit_idx = enable_bit;
- clk->mask = GENMASK(shift + width - 1, shift);
- clk->shift = shift;
- clk->div = clk_divisors;
- clk->num_div = num_div;
- clk->hw.init = &init;
- return devm_clk_hw_register(priv->dev, &clk->hw);
- }
- struct ep93xx_gate {
- unsigned int idx;
- unsigned int bit;
- const char *name;
- };
- static const struct ep93xx_gate ep93xx_uarts[] = {
- { EP93XX_CLK_UART1, EP93XX_SYSCON_DEVCFG_U1EN, "uart1" },
- { EP93XX_CLK_UART2, EP93XX_SYSCON_DEVCFG_U2EN, "uart2" },
- { EP93XX_CLK_UART3, EP93XX_SYSCON_DEVCFG_U3EN, "uart3" },
- };
- static int ep93xx_uart_clock_init(struct ep93xx_clk_priv *priv)
- {
- struct clk_parent_data parent_data = { };
- unsigned int i, idx, ret, clk_uart_div;
- struct ep93xx_clk *clk;
- u32 val;
- regmap_read(priv->map, EP93XX_SYSCON_PWRCNT, &val);
- if (val & EP93XX_SYSCON_PWRCNT_UARTBAUD)
- clk_uart_div = 1;
- else
- clk_uart_div = 2;
- priv->fixed[EP93XX_CLK_UART] =
- devm_clk_hw_register_fixed_factor_index(priv->dev, "uart",
- 0, /* XTALI external clock */
- 0, 1, clk_uart_div);
- parent_data.hw = priv->fixed[EP93XX_CLK_UART];
- /* parenting uart gate clocks to uart clock */
- for (i = 0; i < ARRAY_SIZE(ep93xx_uarts); i++) {
- idx = ep93xx_uarts[i].idx - EP93XX_CLK_UART1;
- clk = &priv->reg[idx];
- clk->idx = idx;
- ret = ep93xx_clk_register_gate(clk,
- ep93xx_uarts[i].name,
- &parent_data, CLK_SET_RATE_PARENT,
- EP93XX_SYSCON_DEVCFG,
- ep93xx_uarts[i].bit);
- if (ret)
- return dev_err_probe(priv->dev, ret,
- "failed to register uart[%d] clock\n", i);
- }
- return 0;
- }
- static const struct ep93xx_gate ep93xx_dmas[] = {
- { EP93XX_CLK_M2M0, EP93XX_SYSCON_PWRCNT_DMA_M2M0, "m2m0" },
- { EP93XX_CLK_M2M1, EP93XX_SYSCON_PWRCNT_DMA_M2M1, "m2m1" },
- { EP93XX_CLK_M2P0, EP93XX_SYSCON_PWRCNT_DMA_M2P0, "m2p0" },
- { EP93XX_CLK_M2P1, EP93XX_SYSCON_PWRCNT_DMA_M2P1, "m2p1" },
- { EP93XX_CLK_M2P2, EP93XX_SYSCON_PWRCNT_DMA_M2P2, "m2p2" },
- { EP93XX_CLK_M2P3, EP93XX_SYSCON_PWRCNT_DMA_M2P3, "m2p3" },
- { EP93XX_CLK_M2P4, EP93XX_SYSCON_PWRCNT_DMA_M2P4, "m2p4" },
- { EP93XX_CLK_M2P5, EP93XX_SYSCON_PWRCNT_DMA_M2P5, "m2p5" },
- { EP93XX_CLK_M2P6, EP93XX_SYSCON_PWRCNT_DMA_M2P6, "m2p6" },
- { EP93XX_CLK_M2P7, EP93XX_SYSCON_PWRCNT_DMA_M2P7, "m2p7" },
- { EP93XX_CLK_M2P8, EP93XX_SYSCON_PWRCNT_DMA_M2P8, "m2p8" },
- { EP93XX_CLK_M2P9, EP93XX_SYSCON_PWRCNT_DMA_M2P9, "m2p9" },
- };
- static int ep93xx_dma_clock_init(struct ep93xx_clk_priv *priv)
- {
- struct clk_parent_data parent_data = { };
- unsigned int i, idx;
- parent_data.hw = priv->fixed[EP93XX_CLK_HCLK];
- for (i = 0; i < ARRAY_SIZE(ep93xx_dmas); i++) {
- idx = ep93xx_dmas[i].idx;
- priv->fixed[idx] = devm_clk_hw_register_gate_parent_data(priv->dev,
- ep93xx_dmas[i].name,
- &parent_data, 0,
- priv->base + EP93XX_SYSCON_PWRCNT,
- ep93xx_dmas[i].bit,
- 0,
- &priv->lock);
- if (IS_ERR(priv->fixed[idx]))
- return PTR_ERR(priv->fixed[idx]);
- }
- return 0;
- }
- static struct clk_hw *of_clk_ep93xx_get(struct of_phandle_args *clkspec, void *data)
- {
- struct ep93xx_clk_priv *priv = data;
- unsigned int idx = clkspec->args[0];
- if (idx < EP93XX_CLK_UART1)
- return priv->fixed[idx];
- if (idx <= EP93XX_CLK_I2S_LRCLK)
- return &priv->reg[idx - EP93XX_CLK_UART1].hw;
- return ERR_PTR(-EINVAL);
- }
- /*
- * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
- */
- static unsigned long calc_pll_rate(u64 rate, u32 config_word)
- {
- rate *= ((config_word >> 11) & GENMASK(4, 0)) + 1; /* X1FBD */
- rate *= ((config_word >> 5) & GENMASK(5, 0)) + 1; /* X2FBD */
- do_div(rate, (config_word & GENMASK(4, 0)) + 1); /* X2IPD */
- rate >>= (config_word >> 16) & GENMASK(1, 0); /* PS */
- return rate;
- }
- static int ep93xx_plls_init(struct ep93xx_clk_priv *priv)
- {
- const char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
- const char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
- const char pclk_divisors[] = { 1, 2, 4, 8 };
- struct clk_parent_data xtali = { .index = 0 };
- unsigned int clk_f_div, clk_h_div, clk_p_div;
- unsigned long clk_pll1_rate, clk_pll2_rate;
- struct device *dev = priv->dev;
- struct clk_hw *hw, *pll1;
- u32 value;
- /* Determine the bootloader configured pll1 rate */
- regmap_read(priv->map, EP93XX_SYSCON_CLKSET1, &value);
- if (value & EP93XX_SYSCON_CLKSET1_NBYP1)
- clk_pll1_rate = calc_pll_rate(EP93XX_EXT_CLK_RATE, value);
- else
- clk_pll1_rate = EP93XX_EXT_CLK_RATE;
- pll1 = devm_clk_hw_register_fixed_rate_parent_data(dev, "pll1", &xtali,
- 0, clk_pll1_rate);
- if (IS_ERR(pll1))
- return PTR_ERR(pll1);
- priv->fixed[EP93XX_CLK_PLL1] = pll1;
- /* Initialize the pll1 derived clocks */
- clk_f_div = fclk_divisors[(value >> 25) & GENMASK(2, 0)];
- clk_h_div = hclk_divisors[(value >> 20) & GENMASK(2, 0)];
- clk_p_div = pclk_divisors[(value >> 18) & GENMASK(1, 0)];
- hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, "fclk", pll1, 0, 1, clk_f_div);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
- priv->fixed[EP93XX_CLK_FCLK] = hw;
- hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, "hclk", pll1, 0, 1, clk_h_div);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
- priv->fixed[EP93XX_CLK_HCLK] = hw;
- hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, "pclk", hw, 0, 1, clk_p_div);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
- priv->fixed[EP93XX_CLK_PCLK] = hw;
- /* Determine the bootloader configured pll2 rate */
- regmap_read(priv->map, EP93XX_SYSCON_CLKSET2, &value);
- if (!(value & EP93XX_SYSCON_CLKSET2_NBYP2))
- clk_pll2_rate = EP93XX_EXT_CLK_RATE;
- else if (value & EP93XX_SYSCON_CLKSET2_PLL2_EN)
- clk_pll2_rate = calc_pll_rate(EP93XX_EXT_CLK_RATE, value);
- else
- clk_pll2_rate = 0;
- hw = devm_clk_hw_register_fixed_rate_parent_data(dev, "pll2", &xtali,
- 0, clk_pll2_rate);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
- priv->fixed[EP93XX_CLK_PLL2] = hw;
- return 0;
- }
- static int ep93xx_clk_probe(struct auxiliary_device *adev,
- const struct auxiliary_device_id *id)
- {
- struct ep93xx_regmap_adev *rdev = to_ep93xx_regmap_adev(adev);
- struct clk_parent_data xtali = { .index = 0 };
- struct clk_parent_data ddiv_pdata[3] = { };
- unsigned int clk_spi_div, clk_usb_div;
- struct clk_parent_data pdata = {};
- struct device *dev = &adev->dev;
- struct ep93xx_clk_priv *priv;
- struct ep93xx_clk *clk;
- struct clk_hw *hw;
- unsigned int idx;
- int ret;
- u32 value;
- priv = devm_kzalloc(dev, struct_size(priv, reg, 10), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
- spin_lock_init(&priv->lock);
- priv->dev = dev;
- priv->aux_dev = rdev;
- priv->map = rdev->map;
- priv->base = rdev->base;
- ret = ep93xx_plls_init(priv);
- if (ret)
- return ret;
- regmap_read(priv->map, EP93XX_SYSCON_CLKSET2, &value);
- clk_usb_div = (value >> 28 & GENMASK(3, 0)) + 1;
- hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, "usb_clk",
- priv->fixed[EP93XX_CLK_PLL2], 0, 1,
- clk_usb_div);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
- priv->fixed[EP93XX_CLK_USB] = hw;
- ret = ep93xx_uart_clock_init(priv);
- if (ret)
- return ret;
- ret = ep93xx_dma_clock_init(priv);
- if (ret)
- return ret;
- clk_spi_div = id->driver_data;
- hw = devm_clk_hw_register_fixed_factor_index(dev, "ep93xx-spi.0",
- 0, /* XTALI external clock */
- 0, 1, clk_spi_div);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
- priv->fixed[EP93XX_CLK_SPI] = hw;
- /* PWM clock */
- hw = devm_clk_hw_register_fixed_factor_index(dev, "pwm_clk", 0, /* XTALI external clock */
- 0, 1, 1);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
- priv->fixed[EP93XX_CLK_PWM] = hw;
- /* USB clock */
- pdata.hw = priv->fixed[EP93XX_CLK_USB];
- hw = devm_clk_hw_register_gate_parent_data(priv->dev, "ohci-platform", &pdata,
- 0, priv->base + EP93XX_SYSCON_PWRCNT,
- EP93XX_SYSCON_PWRCNT_USH_EN, 0,
- &priv->lock);
- if (IS_ERR(hw))
- return PTR_ERR(hw);
- priv->fixed[EP93XX_CLK_USB] = hw;
- ddiv_pdata[0].index = 0; /* XTALI external clock */
- ddiv_pdata[1].hw = priv->fixed[EP93XX_CLK_PLL1];
- ddiv_pdata[2].hw = priv->fixed[EP93XX_CLK_PLL2];
- /* touchscreen/ADC clock */
- idx = EP93XX_CLK_ADC - EP93XX_CLK_UART1;
- clk = &priv->reg[idx];
- clk->idx = idx;
- ret = ep93xx_register_div(clk, "ep93xx-adc", &xtali,
- EP93XX_SYSCON_KEYTCHCLKDIV,
- EP93XX_SYSCON_KEYTCHCLKDIV_TSEN,
- EP93XX_SYSCON_KEYTCHCLKDIV_ADIV,
- 1,
- ep93xx_adc_divisors,
- ARRAY_SIZE(ep93xx_adc_divisors));
- /* keypad clock */
- idx = EP93XX_CLK_KEYPAD - EP93XX_CLK_UART1;
- clk = &priv->reg[idx];
- clk->idx = idx;
- ret = ep93xx_register_div(clk, "ep93xx-keypad", &xtali,
- EP93XX_SYSCON_KEYTCHCLKDIV,
- EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
- EP93XX_SYSCON_KEYTCHCLKDIV_KDIV,
- 1,
- ep93xx_adc_divisors,
- ARRAY_SIZE(ep93xx_adc_divisors));
- /*
- * On reset PDIV and VDIV is set to zero, while PDIV zero
- * means clock disable, VDIV shouldn't be zero.
- * So we set both video and i2s dividers to minimum.
- * ENA - Enable CLK divider.
- * PDIV - 00 - Disable clock
- * VDIV - at least 2
- */
- /* Check and enable video clk registers */
- regmap_read(priv->map, EP93XX_SYSCON_VIDCLKDIV, &value);
- value |= BIT(EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2;
- ep93xx_clk_write(priv, EP93XX_SYSCON_VIDCLKDIV, value);
- /* Check and enable i2s clk registers */
- regmap_read(priv->map, EP93XX_SYSCON_I2SCLKDIV, &value);
- value |= BIT(EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2;
- /*
- * Override the SAI_MSTR_CLK_CFG from the I2S block and use the
- * I2SClkDiv Register settings. LRCLK transitions on the falling SCLK
- * edge.
- */
- value |= EP93XX_SYSCON_I2SCLKDIV_ORIDE | EP93XX_SYSCON_I2SCLKDIV_SPOL;
- ep93xx_clk_write(priv, EP93XX_SYSCON_I2SCLKDIV, value);
- /* video clk */
- idx = EP93XX_CLK_VIDEO - EP93XX_CLK_UART1;
- clk = &priv->reg[idx];
- clk->idx = idx;
- ret = ep93xx_clk_register_ddiv(clk, "ep93xx-fb",
- ddiv_pdata, ARRAY_SIZE(ddiv_pdata),
- EP93XX_SYSCON_VIDCLKDIV,
- EP93XX_SYSCON_CLKDIV_ENABLE);
- /* i2s clk */
- idx = EP93XX_CLK_I2S_MCLK - EP93XX_CLK_UART1;
- clk = &priv->reg[idx];
- clk->idx = idx;
- ret = ep93xx_clk_register_ddiv(clk, "mclk",
- ddiv_pdata, ARRAY_SIZE(ddiv_pdata),
- EP93XX_SYSCON_I2SCLKDIV,
- EP93XX_SYSCON_CLKDIV_ENABLE);
- /* i2s sclk */
- idx = EP93XX_CLK_I2S_SCLK - EP93XX_CLK_UART1;
- clk = &priv->reg[idx];
- clk->idx = idx;
- pdata.hw = &priv->reg[EP93XX_CLK_I2S_MCLK - EP93XX_CLK_UART1].hw;
- ret = ep93xx_register_div(clk, "sclk", &pdata,
- EP93XX_SYSCON_I2SCLKDIV,
- EP93XX_SYSCON_I2SCLKDIV_SENA,
- 16, /* EP93XX_I2SCLKDIV_SDIV_SHIFT */
- 1, /* EP93XX_I2SCLKDIV_SDIV_WIDTH */
- ep93xx_sclk_divisors,
- ARRAY_SIZE(ep93xx_sclk_divisors));
- /* i2s lrclk */
- idx = EP93XX_CLK_I2S_LRCLK - EP93XX_CLK_UART1;
- clk = &priv->reg[idx];
- clk->idx = idx;
- pdata.hw = &priv->reg[EP93XX_CLK_I2S_SCLK - EP93XX_CLK_UART1].hw;
- ret = ep93xx_register_div(clk, "lrclk", &pdata,
- EP93XX_SYSCON_I2SCLKDIV,
- EP93XX_SYSCON_I2SCLKDIV_SENA,
- 17, /* EP93XX_I2SCLKDIV_LRDIV32_SHIFT */
- 2, /* EP93XX_I2SCLKDIV_LRDIV32_WIDTH */
- ep93xx_lrclk_divisors,
- ARRAY_SIZE(ep93xx_lrclk_divisors));
- /* IrDa clk uses same pattern but no init code presents in original clock driver */
- return devm_of_clk_add_hw_provider(priv->dev, of_clk_ep93xx_get, priv);
- }
- static const struct auxiliary_device_id ep93xx_clk_ids[] = {
- { .name = "soc_ep93xx.clk-ep93xx", .driver_data = 2, },
- { .name = "soc_ep93xx.clk-ep93xx.e2", .driver_data = 1, },
- { /* sentinel */ }
- };
- MODULE_DEVICE_TABLE(auxiliary, ep93xx_clk_ids);
- static struct auxiliary_driver ep93xx_clk_driver = {
- .probe = ep93xx_clk_probe,
- .id_table = ep93xx_clk_ids,
- };
- module_auxiliary_driver(ep93xx_clk_driver);
- MODULE_LICENSE("GPL");
- MODULE_AUTHOR("Nikita Shubin <nikita.shubin@maquefel.me>");
- MODULE_DESCRIPTION("Clock control for Cirrus EP93xx chips");
|