18a6b7e2bSNikita Shubin // SPDX-License-Identifier: GPL-2.0-or-later
28a6b7e2bSNikita Shubin /*
38a6b7e2bSNikita Shubin * Clock control for Cirrus EP93xx chips.
48a6b7e2bSNikita Shubin * Copyright (C) 2021 Nikita Shubin <nikita.shubin@maquefel.me>
58a6b7e2bSNikita Shubin *
68a6b7e2bSNikita Shubin * Based on a rewrite of arch/arm/mach-ep93xx/clock.c:
78a6b7e2bSNikita Shubin * Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
88a6b7e2bSNikita Shubin */
98a6b7e2bSNikita Shubin #define pr_fmt(fmt) "ep93xx " KBUILD_MODNAME ": " fmt
108a6b7e2bSNikita Shubin
118a6b7e2bSNikita Shubin #include <linux/bits.h>
128a6b7e2bSNikita Shubin #include <linux/cleanup.h>
138a6b7e2bSNikita Shubin #include <linux/clk-provider.h>
148a6b7e2bSNikita Shubin #include <linux/math.h>
158a6b7e2bSNikita Shubin #include <linux/platform_device.h>
168a6b7e2bSNikita Shubin #include <linux/regmap.h>
178a6b7e2bSNikita Shubin #include <linux/spinlock.h>
188a6b7e2bSNikita Shubin
198a6b7e2bSNikita Shubin #include <linux/soc/cirrus/ep93xx.h>
208a6b7e2bSNikita Shubin #include <dt-bindings/clock/cirrus,ep9301-syscon.h>
218a6b7e2bSNikita Shubin
228a6b7e2bSNikita Shubin #include <asm/div64.h>
238a6b7e2bSNikita Shubin
248a6b7e2bSNikita Shubin #define EP93XX_EXT_CLK_RATE 14745600
258a6b7e2bSNikita Shubin #define EP93XX_EXT_RTC_RATE 32768
268a6b7e2bSNikita Shubin
278a6b7e2bSNikita Shubin #define EP93XX_SYSCON_POWER_STATE 0x00
288a6b7e2bSNikita Shubin #define EP93XX_SYSCON_PWRCNT 0x04
298a6b7e2bSNikita Shubin #define EP93XX_SYSCON_PWRCNT_UARTBAUD BIT(29)
308a6b7e2bSNikita Shubin #define EP93XX_SYSCON_PWRCNT_USH_EN 28
318a6b7e2bSNikita Shubin #define EP93XX_SYSCON_PWRCNT_DMA_M2M1 27
328a6b7e2bSNikita Shubin #define EP93XX_SYSCON_PWRCNT_DMA_M2M0 26
338a6b7e2bSNikita Shubin #define EP93XX_SYSCON_PWRCNT_DMA_M2P8 25
348a6b7e2bSNikita Shubin #define EP93XX_SYSCON_PWRCNT_DMA_M2P9 24
358a6b7e2bSNikita Shubin #define EP93XX_SYSCON_PWRCNT_DMA_M2P6 23
368a6b7e2bSNikita Shubin #define EP93XX_SYSCON_PWRCNT_DMA_M2P7 22
378a6b7e2bSNikita Shubin #define EP93XX_SYSCON_PWRCNT_DMA_M2P4 21
388a6b7e2bSNikita Shubin #define EP93XX_SYSCON_PWRCNT_DMA_M2P5 20
398a6b7e2bSNikita Shubin #define EP93XX_SYSCON_PWRCNT_DMA_M2P2 19
408a6b7e2bSNikita Shubin #define EP93XX_SYSCON_PWRCNT_DMA_M2P3 18
418a6b7e2bSNikita Shubin #define EP93XX_SYSCON_PWRCNT_DMA_M2P0 17
428a6b7e2bSNikita Shubin #define EP93XX_SYSCON_PWRCNT_DMA_M2P1 16
438a6b7e2bSNikita Shubin #define EP93XX_SYSCON_CLKSET1 0x20
448a6b7e2bSNikita Shubin #define EP93XX_SYSCON_CLKSET1_NBYP1 BIT(23)
458a6b7e2bSNikita Shubin #define EP93XX_SYSCON_CLKSET2 0x24
468a6b7e2bSNikita Shubin #define EP93XX_SYSCON_CLKSET2_NBYP2 BIT(19)
478a6b7e2bSNikita Shubin #define EP93XX_SYSCON_CLKSET2_PLL2_EN BIT(18)
488a6b7e2bSNikita Shubin #define EP93XX_SYSCON_DEVCFG 0x80
498a6b7e2bSNikita Shubin #define EP93XX_SYSCON_DEVCFG_U3EN 24
508a6b7e2bSNikita Shubin #define EP93XX_SYSCON_DEVCFG_U2EN 20
518a6b7e2bSNikita Shubin #define EP93XX_SYSCON_DEVCFG_U1EN 18
528a6b7e2bSNikita Shubin #define EP93XX_SYSCON_VIDCLKDIV 0x84
538a6b7e2bSNikita Shubin #define EP93XX_SYSCON_CLKDIV_ENABLE 15
548a6b7e2bSNikita Shubin #define EP93XX_SYSCON_CLKDIV_ESEL BIT(14)
558a6b7e2bSNikita Shubin #define EP93XX_SYSCON_CLKDIV_PSEL BIT(13)
568a6b7e2bSNikita Shubin #define EP93XX_SYSCON_CLKDIV_MASK GENMASK(14, 13)
578a6b7e2bSNikita Shubin #define EP93XX_SYSCON_CLKDIV_PDIV_SHIFT 8
588a6b7e2bSNikita Shubin #define EP93XX_SYSCON_I2SCLKDIV 0x8c
598a6b7e2bSNikita Shubin #define EP93XX_SYSCON_I2SCLKDIV_SENA 31
608a6b7e2bSNikita Shubin #define EP93XX_SYSCON_I2SCLKDIV_ORIDE BIT(29)
618a6b7e2bSNikita Shubin #define EP93XX_SYSCON_I2SCLKDIV_SPOL BIT(19)
628a6b7e2bSNikita Shubin #define EP93XX_SYSCON_KEYTCHCLKDIV 0x90
638a6b7e2bSNikita Shubin #define EP93XX_SYSCON_KEYTCHCLKDIV_TSEN 31
648a6b7e2bSNikita Shubin #define EP93XX_SYSCON_KEYTCHCLKDIV_ADIV 16
658a6b7e2bSNikita Shubin #define EP93XX_SYSCON_KEYTCHCLKDIV_KEN 15
668a6b7e2bSNikita Shubin #define EP93XX_SYSCON_KEYTCHCLKDIV_KDIV 0
678a6b7e2bSNikita Shubin #define EP93XX_SYSCON_CHIPID 0x94
688a6b7e2bSNikita Shubin #define EP93XX_SYSCON_CHIPID_ID 0x9213
698a6b7e2bSNikita Shubin
708a6b7e2bSNikita Shubin #define EP93XX_FIXED_CLK_COUNT 21
718a6b7e2bSNikita Shubin
728a6b7e2bSNikita Shubin static const char ep93xx_adc_divisors[] = { 16, 4 };
738a6b7e2bSNikita Shubin static const char ep93xx_sclk_divisors[] = { 2, 4 };
748a6b7e2bSNikita Shubin static const char ep93xx_lrclk_divisors[] = { 32, 64, 128 };
758a6b7e2bSNikita Shubin
768a6b7e2bSNikita Shubin struct ep93xx_clk {
778a6b7e2bSNikita Shubin struct clk_hw hw;
788a6b7e2bSNikita Shubin u16 idx;
798a6b7e2bSNikita Shubin u16 reg;
808a6b7e2bSNikita Shubin u32 mask;
818a6b7e2bSNikita Shubin u8 bit_idx;
828a6b7e2bSNikita Shubin u8 shift;
838a6b7e2bSNikita Shubin u8 width;
848a6b7e2bSNikita Shubin u8 num_div;
858a6b7e2bSNikita Shubin const char *div;
868a6b7e2bSNikita Shubin };
878a6b7e2bSNikita Shubin
888a6b7e2bSNikita Shubin struct ep93xx_clk_priv {
898a6b7e2bSNikita Shubin spinlock_t lock;
908a6b7e2bSNikita Shubin struct ep93xx_regmap_adev *aux_dev;
918a6b7e2bSNikita Shubin struct device *dev;
928a6b7e2bSNikita Shubin void __iomem *base;
938a6b7e2bSNikita Shubin struct regmap *map;
948a6b7e2bSNikita Shubin struct clk_hw *fixed[EP93XX_FIXED_CLK_COUNT];
958a6b7e2bSNikita Shubin struct ep93xx_clk reg[];
968a6b7e2bSNikita Shubin };
978a6b7e2bSNikita Shubin
ep93xx_clk_from(struct clk_hw * hw)988a6b7e2bSNikita Shubin static struct ep93xx_clk *ep93xx_clk_from(struct clk_hw *hw)
998a6b7e2bSNikita Shubin {
1008a6b7e2bSNikita Shubin return container_of(hw, struct ep93xx_clk, hw);
1018a6b7e2bSNikita Shubin }
1028a6b7e2bSNikita Shubin
ep93xx_priv_from(struct ep93xx_clk * clk)1038a6b7e2bSNikita Shubin static struct ep93xx_clk_priv *ep93xx_priv_from(struct ep93xx_clk *clk)
1048a6b7e2bSNikita Shubin {
1058a6b7e2bSNikita Shubin return container_of(clk, struct ep93xx_clk_priv, reg[clk->idx]);
1068a6b7e2bSNikita Shubin }
1078a6b7e2bSNikita Shubin
ep93xx_clk_write(struct ep93xx_clk_priv * priv,unsigned int reg,unsigned int val)1088a6b7e2bSNikita Shubin static void ep93xx_clk_write(struct ep93xx_clk_priv *priv, unsigned int reg, unsigned int val)
1098a6b7e2bSNikita Shubin {
1108a6b7e2bSNikita Shubin struct ep93xx_regmap_adev *aux = priv->aux_dev;
1118a6b7e2bSNikita Shubin
1128a6b7e2bSNikita Shubin aux->write(aux->map, aux->lock, reg, val);
1138a6b7e2bSNikita Shubin }
1148a6b7e2bSNikita Shubin
ep93xx_clk_is_enabled(struct clk_hw * hw)1158a6b7e2bSNikita Shubin static int ep93xx_clk_is_enabled(struct clk_hw *hw)
1168a6b7e2bSNikita Shubin {
1178a6b7e2bSNikita Shubin struct ep93xx_clk *clk = ep93xx_clk_from(hw);
1188a6b7e2bSNikita Shubin struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
1198a6b7e2bSNikita Shubin u32 val;
1208a6b7e2bSNikita Shubin
1218a6b7e2bSNikita Shubin regmap_read(priv->map, clk->reg, &val);
1228a6b7e2bSNikita Shubin
1238a6b7e2bSNikita Shubin return !!(val & BIT(clk->bit_idx));
1248a6b7e2bSNikita Shubin }
1258a6b7e2bSNikita Shubin
ep93xx_clk_enable(struct clk_hw * hw)1268a6b7e2bSNikita Shubin static int ep93xx_clk_enable(struct clk_hw *hw)
1278a6b7e2bSNikita Shubin {
1288a6b7e2bSNikita Shubin struct ep93xx_clk *clk = ep93xx_clk_from(hw);
1298a6b7e2bSNikita Shubin struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
1308a6b7e2bSNikita Shubin u32 val;
1318a6b7e2bSNikita Shubin
1328a6b7e2bSNikita Shubin guard(spinlock_irqsave)(&priv->lock);
1338a6b7e2bSNikita Shubin
1348a6b7e2bSNikita Shubin regmap_read(priv->map, clk->reg, &val);
1358a6b7e2bSNikita Shubin val |= BIT(clk->bit_idx);
1368a6b7e2bSNikita Shubin
1378a6b7e2bSNikita Shubin ep93xx_clk_write(priv, clk->reg, val);
1388a6b7e2bSNikita Shubin
1398a6b7e2bSNikita Shubin return 0;
1408a6b7e2bSNikita Shubin }
1418a6b7e2bSNikita Shubin
ep93xx_clk_disable(struct clk_hw * hw)1428a6b7e2bSNikita Shubin static void ep93xx_clk_disable(struct clk_hw *hw)
1438a6b7e2bSNikita Shubin {
1448a6b7e2bSNikita Shubin struct ep93xx_clk *clk = ep93xx_clk_from(hw);
1458a6b7e2bSNikita Shubin struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
1468a6b7e2bSNikita Shubin u32 val;
1478a6b7e2bSNikita Shubin
1488a6b7e2bSNikita Shubin guard(spinlock_irqsave)(&priv->lock);
1498a6b7e2bSNikita Shubin
1508a6b7e2bSNikita Shubin regmap_read(priv->map, clk->reg, &val);
1518a6b7e2bSNikita Shubin val &= ~BIT(clk->bit_idx);
1528a6b7e2bSNikita Shubin
1538a6b7e2bSNikita Shubin ep93xx_clk_write(priv, clk->reg, val);
1548a6b7e2bSNikita Shubin }
1558a6b7e2bSNikita Shubin
1568a6b7e2bSNikita Shubin static const struct clk_ops clk_ep93xx_gate_ops = {
1578a6b7e2bSNikita Shubin .enable = ep93xx_clk_enable,
1588a6b7e2bSNikita Shubin .disable = ep93xx_clk_disable,
1598a6b7e2bSNikita Shubin .is_enabled = ep93xx_clk_is_enabled,
1608a6b7e2bSNikita Shubin };
1618a6b7e2bSNikita Shubin
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)1628a6b7e2bSNikita Shubin static int ep93xx_clk_register_gate(struct ep93xx_clk *clk,
1638a6b7e2bSNikita Shubin const char *name,
1648a6b7e2bSNikita Shubin struct clk_parent_data *parent_data,
1658a6b7e2bSNikita Shubin unsigned long flags,
1668a6b7e2bSNikita Shubin unsigned int reg,
1678a6b7e2bSNikita Shubin u8 bit_idx)
1688a6b7e2bSNikita Shubin {
1698a6b7e2bSNikita Shubin struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
1708a6b7e2bSNikita Shubin struct clk_init_data init = { };
1718a6b7e2bSNikita Shubin
1728a6b7e2bSNikita Shubin init.name = name;
1738a6b7e2bSNikita Shubin init.ops = &clk_ep93xx_gate_ops;
1748a6b7e2bSNikita Shubin init.flags = flags;
1758a6b7e2bSNikita Shubin init.parent_data = parent_data;
1768a6b7e2bSNikita Shubin init.num_parents = 1;
1778a6b7e2bSNikita Shubin
1788a6b7e2bSNikita Shubin clk->reg = reg;
1798a6b7e2bSNikita Shubin clk->bit_idx = bit_idx;
1808a6b7e2bSNikita Shubin clk->hw.init = &init;
1818a6b7e2bSNikita Shubin
1828a6b7e2bSNikita Shubin return devm_clk_hw_register(priv->dev, &clk->hw);
1838a6b7e2bSNikita Shubin }
1848a6b7e2bSNikita Shubin
ep93xx_mux_get_parent(struct clk_hw * hw)1858a6b7e2bSNikita Shubin static u8 ep93xx_mux_get_parent(struct clk_hw *hw)
1868a6b7e2bSNikita Shubin {
1878a6b7e2bSNikita Shubin struct ep93xx_clk *clk = ep93xx_clk_from(hw);
1888a6b7e2bSNikita Shubin struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
1898a6b7e2bSNikita Shubin u32 val;
1908a6b7e2bSNikita Shubin
1918a6b7e2bSNikita Shubin regmap_read(priv->map, clk->reg, &val);
1928a6b7e2bSNikita Shubin
1938a6b7e2bSNikita Shubin val &= EP93XX_SYSCON_CLKDIV_MASK;
1948a6b7e2bSNikita Shubin
1958a6b7e2bSNikita Shubin switch (val) {
1968a6b7e2bSNikita Shubin case EP93XX_SYSCON_CLKDIV_ESEL:
1978a6b7e2bSNikita Shubin return 1; /* PLL1 */
1988a6b7e2bSNikita Shubin case EP93XX_SYSCON_CLKDIV_MASK:
1998a6b7e2bSNikita Shubin return 2; /* PLL2 */
2008a6b7e2bSNikita Shubin default:
2018a6b7e2bSNikita Shubin return 0; /* XTALI */
2028a6b7e2bSNikita Shubin };
2038a6b7e2bSNikita Shubin }
2048a6b7e2bSNikita Shubin
ep93xx_mux_set_parent_lock(struct clk_hw * hw,u8 index)2058a6b7e2bSNikita Shubin static int ep93xx_mux_set_parent_lock(struct clk_hw *hw, u8 index)
2068a6b7e2bSNikita Shubin {
2078a6b7e2bSNikita Shubin struct ep93xx_clk *clk = ep93xx_clk_from(hw);
2088a6b7e2bSNikita Shubin struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
2098a6b7e2bSNikita Shubin u32 val;
2108a6b7e2bSNikita Shubin
2118a6b7e2bSNikita Shubin if (index >= 3)
2128a6b7e2bSNikita Shubin return -EINVAL;
2138a6b7e2bSNikita Shubin
2148a6b7e2bSNikita Shubin guard(spinlock_irqsave)(&priv->lock);
2158a6b7e2bSNikita Shubin
2168a6b7e2bSNikita Shubin regmap_read(priv->map, clk->reg, &val);
2178a6b7e2bSNikita Shubin val &= ~(EP93XX_SYSCON_CLKDIV_MASK);
2188a6b7e2bSNikita Shubin val |= index > 0 ? EP93XX_SYSCON_CLKDIV_ESEL : 0;
2198a6b7e2bSNikita Shubin val |= index > 1 ? EP93XX_SYSCON_CLKDIV_PSEL : 0;
2208a6b7e2bSNikita Shubin
2218a6b7e2bSNikita Shubin ep93xx_clk_write(priv, clk->reg, val);
2228a6b7e2bSNikita Shubin
2238a6b7e2bSNikita Shubin return 0;
2248a6b7e2bSNikita Shubin }
2258a6b7e2bSNikita Shubin
is_best(unsigned long rate,unsigned long now,unsigned long best)2268a6b7e2bSNikita Shubin static bool is_best(unsigned long rate, unsigned long now,
2278a6b7e2bSNikita Shubin unsigned long best)
2288a6b7e2bSNikita Shubin {
2298a6b7e2bSNikita Shubin return abs_diff(rate, now) < abs_diff(rate, best);
2308a6b7e2bSNikita Shubin }
2318a6b7e2bSNikita Shubin
ep93xx_mux_determine_rate(struct clk_hw * hw,struct clk_rate_request * req)2328a6b7e2bSNikita Shubin static int ep93xx_mux_determine_rate(struct clk_hw *hw,
2338a6b7e2bSNikita Shubin struct clk_rate_request *req)
2348a6b7e2bSNikita Shubin {
2358a6b7e2bSNikita Shubin unsigned long best_rate = 0, actual_rate, mclk_rate;
2368a6b7e2bSNikita Shubin unsigned long rate = req->rate;
2378a6b7e2bSNikita Shubin struct clk_hw *parent_best = NULL;
2388a6b7e2bSNikita Shubin unsigned long parent_rate_best;
2398a6b7e2bSNikita Shubin unsigned long parent_rate;
2408a6b7e2bSNikita Shubin int div, pdiv;
2418a6b7e2bSNikita Shubin unsigned int i;
2428a6b7e2bSNikita Shubin
2438a6b7e2bSNikita Shubin /*
2448a6b7e2bSNikita Shubin * Try the two pll's and the external clock,
2458a6b7e2bSNikita Shubin * because the valid predividers are 2, 2.5 and 3, we multiply
2468a6b7e2bSNikita Shubin * all the clocks by 2 to avoid floating point math.
2478a6b7e2bSNikita Shubin *
2488a6b7e2bSNikita Shubin * This is based on the algorithm in the ep93xx raster guide:
2498a6b7e2bSNikita Shubin * http://be-a-maverick.com/en/pubs/appNote/AN269REV1.pdf
2508a6b7e2bSNikita Shubin *
2518a6b7e2bSNikita Shubin */
2528a6b7e2bSNikita Shubin for (i = 0; i < clk_hw_get_num_parents(hw); i++) {
2538a6b7e2bSNikita Shubin struct clk_hw *parent = clk_hw_get_parent_by_index(hw, i);
2548a6b7e2bSNikita Shubin
2558a6b7e2bSNikita Shubin parent_rate = clk_hw_get_rate(parent);
2568a6b7e2bSNikita Shubin mclk_rate = parent_rate * 2;
2578a6b7e2bSNikita Shubin
2588a6b7e2bSNikita Shubin /* Try each predivider value */
2598a6b7e2bSNikita Shubin for (pdiv = 4; pdiv <= 6; pdiv++) {
2608a6b7e2bSNikita Shubin div = DIV_ROUND_CLOSEST(mclk_rate, rate * pdiv);
2618a6b7e2bSNikita Shubin if (!in_range(div, 1, 127))
2628a6b7e2bSNikita Shubin continue;
2638a6b7e2bSNikita Shubin
2648a6b7e2bSNikita Shubin actual_rate = DIV_ROUND_CLOSEST(mclk_rate, pdiv * div);
2658a6b7e2bSNikita Shubin if (is_best(rate, actual_rate, best_rate)) {
2668a6b7e2bSNikita Shubin best_rate = actual_rate;
2678a6b7e2bSNikita Shubin parent_rate_best = parent_rate;
2688a6b7e2bSNikita Shubin parent_best = parent;
2698a6b7e2bSNikita Shubin }
2708a6b7e2bSNikita Shubin }
2718a6b7e2bSNikita Shubin }
2728a6b7e2bSNikita Shubin
2738a6b7e2bSNikita Shubin if (!parent_best)
2748a6b7e2bSNikita Shubin return -EINVAL;
2758a6b7e2bSNikita Shubin
2768a6b7e2bSNikita Shubin req->best_parent_rate = parent_rate_best;
2778a6b7e2bSNikita Shubin req->best_parent_hw = parent_best;
2788a6b7e2bSNikita Shubin req->rate = best_rate;
2798a6b7e2bSNikita Shubin
2808a6b7e2bSNikita Shubin return 0;
2818a6b7e2bSNikita Shubin }
2828a6b7e2bSNikita Shubin
ep93xx_ddiv_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)2838a6b7e2bSNikita Shubin static unsigned long ep93xx_ddiv_recalc_rate(struct clk_hw *hw,
2848a6b7e2bSNikita Shubin unsigned long parent_rate)
2858a6b7e2bSNikita Shubin {
2868a6b7e2bSNikita Shubin struct ep93xx_clk *clk = ep93xx_clk_from(hw);
2878a6b7e2bSNikita Shubin struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
2888a6b7e2bSNikita Shubin unsigned int pdiv, div;
2898a6b7e2bSNikita Shubin u32 val;
2908a6b7e2bSNikita Shubin
2918a6b7e2bSNikita Shubin regmap_read(priv->map, clk->reg, &val);
2928a6b7e2bSNikita Shubin pdiv = (val >> EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) & GENMASK(1, 0);
2938a6b7e2bSNikita Shubin div = val & GENMASK(6, 0);
2948a6b7e2bSNikita Shubin if (!div)
2958a6b7e2bSNikita Shubin return 0;
2968a6b7e2bSNikita Shubin
2978a6b7e2bSNikita Shubin return DIV_ROUND_CLOSEST(parent_rate * 2, (pdiv + 3) * div);
2988a6b7e2bSNikita Shubin }
2998a6b7e2bSNikita Shubin
ep93xx_ddiv_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)3008a6b7e2bSNikita Shubin static int ep93xx_ddiv_set_rate(struct clk_hw *hw, unsigned long rate,
3018a6b7e2bSNikita Shubin unsigned long parent_rate)
3028a6b7e2bSNikita Shubin {
3038a6b7e2bSNikita Shubin struct ep93xx_clk *clk = ep93xx_clk_from(hw);
3048a6b7e2bSNikita Shubin struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
3058a6b7e2bSNikita Shubin int pdiv, div, npdiv, ndiv;
3068a6b7e2bSNikita Shubin unsigned long actual_rate, mclk_rate, rate_err = ULONG_MAX;
3078a6b7e2bSNikita Shubin u32 val;
3088a6b7e2bSNikita Shubin
3098a6b7e2bSNikita Shubin regmap_read(priv->map, clk->reg, &val);
3108a6b7e2bSNikita Shubin mclk_rate = parent_rate * 2;
3118a6b7e2bSNikita Shubin
3128a6b7e2bSNikita Shubin for (pdiv = 4; pdiv <= 6; pdiv++) {
3138a6b7e2bSNikita Shubin div = DIV_ROUND_CLOSEST(mclk_rate, rate * pdiv);
3148a6b7e2bSNikita Shubin if (!in_range(div, 1, 127))
3158a6b7e2bSNikita Shubin continue;
3168a6b7e2bSNikita Shubin
3178a6b7e2bSNikita Shubin actual_rate = DIV_ROUND_CLOSEST(mclk_rate, pdiv * div);
3188a6b7e2bSNikita Shubin if (abs(actual_rate - rate) < rate_err) {
3198a6b7e2bSNikita Shubin npdiv = pdiv - 3;
3208a6b7e2bSNikita Shubin ndiv = div;
3218a6b7e2bSNikita Shubin rate_err = abs(actual_rate - rate);
3228a6b7e2bSNikita Shubin }
3238a6b7e2bSNikita Shubin }
3248a6b7e2bSNikita Shubin
3258a6b7e2bSNikita Shubin if (rate_err == ULONG_MAX)
3268a6b7e2bSNikita Shubin return -EINVAL;
3278a6b7e2bSNikita Shubin
3288a6b7e2bSNikita Shubin /*
3298a6b7e2bSNikita Shubin * Clear old dividers.
3308a6b7e2bSNikita Shubin * Bit 7 is reserved bit in all ClkDiv registers.
3318a6b7e2bSNikita Shubin */
3328a6b7e2bSNikita Shubin val &= ~(GENMASK(9, 0) & ~BIT(7));
3338a6b7e2bSNikita Shubin
3348a6b7e2bSNikita Shubin /* Set the new pdiv and div bits for the new clock rate */
3358a6b7e2bSNikita Shubin val |= (npdiv << EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | ndiv;
3368a6b7e2bSNikita Shubin
3378a6b7e2bSNikita Shubin ep93xx_clk_write(priv, clk->reg, val);
3388a6b7e2bSNikita Shubin
3398a6b7e2bSNikita Shubin return 0;
3408a6b7e2bSNikita Shubin }
3418a6b7e2bSNikita Shubin
3428a6b7e2bSNikita Shubin static const struct clk_ops clk_ddiv_ops = {
3438a6b7e2bSNikita Shubin .enable = ep93xx_clk_enable,
3448a6b7e2bSNikita Shubin .disable = ep93xx_clk_disable,
3458a6b7e2bSNikita Shubin .is_enabled = ep93xx_clk_is_enabled,
3468a6b7e2bSNikita Shubin .get_parent = ep93xx_mux_get_parent,
3478a6b7e2bSNikita Shubin .set_parent = ep93xx_mux_set_parent_lock,
3488a6b7e2bSNikita Shubin .determine_rate = ep93xx_mux_determine_rate,
3498a6b7e2bSNikita Shubin .recalc_rate = ep93xx_ddiv_recalc_rate,
3508a6b7e2bSNikita Shubin .set_rate = ep93xx_ddiv_set_rate,
3518a6b7e2bSNikita Shubin };
3528a6b7e2bSNikita Shubin
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)3538a6b7e2bSNikita Shubin static int ep93xx_clk_register_ddiv(struct ep93xx_clk *clk,
3548a6b7e2bSNikita Shubin const char *name,
3558a6b7e2bSNikita Shubin struct clk_parent_data *parent_data,
3568a6b7e2bSNikita Shubin u8 num_parents,
3578a6b7e2bSNikita Shubin unsigned int reg,
3588a6b7e2bSNikita Shubin u8 bit_idx)
3598a6b7e2bSNikita Shubin {
3608a6b7e2bSNikita Shubin struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
3618a6b7e2bSNikita Shubin struct clk_init_data init = { };
3628a6b7e2bSNikita Shubin
3638a6b7e2bSNikita Shubin init.name = name;
3648a6b7e2bSNikita Shubin init.ops = &clk_ddiv_ops;
3658a6b7e2bSNikita Shubin init.flags = 0;
3668a6b7e2bSNikita Shubin init.parent_data = parent_data;
3678a6b7e2bSNikita Shubin init.num_parents = num_parents;
3688a6b7e2bSNikita Shubin
3698a6b7e2bSNikita Shubin clk->reg = reg;
3708a6b7e2bSNikita Shubin clk->bit_idx = bit_idx;
3718a6b7e2bSNikita Shubin clk->hw.init = &init;
3728a6b7e2bSNikita Shubin
3738a6b7e2bSNikita Shubin return devm_clk_hw_register(priv->dev, &clk->hw);
3748a6b7e2bSNikita Shubin }
3758a6b7e2bSNikita Shubin
ep93xx_div_recalc_rate(struct clk_hw * hw,unsigned long parent_rate)3768a6b7e2bSNikita Shubin static unsigned long ep93xx_div_recalc_rate(struct clk_hw *hw,
3778a6b7e2bSNikita Shubin unsigned long parent_rate)
3788a6b7e2bSNikita Shubin {
3798a6b7e2bSNikita Shubin struct ep93xx_clk *clk = ep93xx_clk_from(hw);
3808a6b7e2bSNikita Shubin struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
3818a6b7e2bSNikita Shubin u32 val;
3828a6b7e2bSNikita Shubin u8 index;
3838a6b7e2bSNikita Shubin
3848a6b7e2bSNikita Shubin regmap_read(priv->map, clk->reg, &val);
3858a6b7e2bSNikita Shubin index = (val & clk->mask) >> clk->shift;
386*53cf1dc4SDan Carpenter if (index >= clk->num_div)
3878a6b7e2bSNikita Shubin return 0;
3888a6b7e2bSNikita Shubin
3898a6b7e2bSNikita Shubin return DIV_ROUND_CLOSEST(parent_rate, clk->div[index]);
3908a6b7e2bSNikita Shubin }
3918a6b7e2bSNikita Shubin
ep93xx_div_round_rate(struct clk_hw * hw,unsigned long rate,unsigned long * parent_rate)3928a6b7e2bSNikita Shubin static long ep93xx_div_round_rate(struct clk_hw *hw, unsigned long rate,
3938a6b7e2bSNikita Shubin unsigned long *parent_rate)
3948a6b7e2bSNikita Shubin {
3958a6b7e2bSNikita Shubin struct ep93xx_clk *clk = ep93xx_clk_from(hw);
3968a6b7e2bSNikita Shubin unsigned long best = 0, now;
3978a6b7e2bSNikita Shubin unsigned int i;
3988a6b7e2bSNikita Shubin
3998a6b7e2bSNikita Shubin for (i = 0; i < clk->num_div; i++) {
4008a6b7e2bSNikita Shubin if ((rate * clk->div[i]) == *parent_rate)
4018a6b7e2bSNikita Shubin return rate;
4028a6b7e2bSNikita Shubin
4038a6b7e2bSNikita Shubin now = DIV_ROUND_CLOSEST(*parent_rate, clk->div[i]);
4048a6b7e2bSNikita Shubin if (!best || is_best(rate, now, best))
4058a6b7e2bSNikita Shubin best = now;
4068a6b7e2bSNikita Shubin }
4078a6b7e2bSNikita Shubin
4088a6b7e2bSNikita Shubin return best;
4098a6b7e2bSNikita Shubin }
4108a6b7e2bSNikita Shubin
ep93xx_div_set_rate(struct clk_hw * hw,unsigned long rate,unsigned long parent_rate)4118a6b7e2bSNikita Shubin static int ep93xx_div_set_rate(struct clk_hw *hw, unsigned long rate,
4128a6b7e2bSNikita Shubin unsigned long parent_rate)
4138a6b7e2bSNikita Shubin {
4148a6b7e2bSNikita Shubin struct ep93xx_clk *clk = ep93xx_clk_from(hw);
4158a6b7e2bSNikita Shubin struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
4168a6b7e2bSNikita Shubin unsigned int i;
4178a6b7e2bSNikita Shubin u32 val;
4188a6b7e2bSNikita Shubin
4198a6b7e2bSNikita Shubin regmap_read(priv->map, clk->reg, &val);
4208a6b7e2bSNikita Shubin val &= ~clk->mask;
4218a6b7e2bSNikita Shubin for (i = 0; i < clk->num_div; i++)
4228a6b7e2bSNikita Shubin if (rate == DIV_ROUND_CLOSEST(parent_rate, clk->div[i]))
4238a6b7e2bSNikita Shubin break;
4248a6b7e2bSNikita Shubin
4258a6b7e2bSNikita Shubin if (i == clk->num_div)
4268a6b7e2bSNikita Shubin return -EINVAL;
4278a6b7e2bSNikita Shubin
4288a6b7e2bSNikita Shubin val |= i << clk->shift;
4298a6b7e2bSNikita Shubin
4308a6b7e2bSNikita Shubin ep93xx_clk_write(priv, clk->reg, val);
4318a6b7e2bSNikita Shubin
4328a6b7e2bSNikita Shubin return 0;
4338a6b7e2bSNikita Shubin }
4348a6b7e2bSNikita Shubin
4358a6b7e2bSNikita Shubin static const struct clk_ops ep93xx_div_ops = {
4368a6b7e2bSNikita Shubin .enable = ep93xx_clk_enable,
4378a6b7e2bSNikita Shubin .disable = ep93xx_clk_disable,
4388a6b7e2bSNikita Shubin .is_enabled = ep93xx_clk_is_enabled,
4398a6b7e2bSNikita Shubin .recalc_rate = ep93xx_div_recalc_rate,
4408a6b7e2bSNikita Shubin .round_rate = ep93xx_div_round_rate,
4418a6b7e2bSNikita Shubin .set_rate = ep93xx_div_set_rate,
4428a6b7e2bSNikita Shubin };
4438a6b7e2bSNikita Shubin
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)4448a6b7e2bSNikita Shubin static int ep93xx_register_div(struct ep93xx_clk *clk,
4458a6b7e2bSNikita Shubin const char *name,
4468a6b7e2bSNikita Shubin const struct clk_parent_data *parent_data,
4478a6b7e2bSNikita Shubin unsigned int reg,
4488a6b7e2bSNikita Shubin u8 enable_bit,
4498a6b7e2bSNikita Shubin u8 shift,
4508a6b7e2bSNikita Shubin u8 width,
4518a6b7e2bSNikita Shubin const char *clk_divisors,
4528a6b7e2bSNikita Shubin u8 num_div)
4538a6b7e2bSNikita Shubin {
4548a6b7e2bSNikita Shubin struct ep93xx_clk_priv *priv = ep93xx_priv_from(clk);
4558a6b7e2bSNikita Shubin struct clk_init_data init = { };
4568a6b7e2bSNikita Shubin
4578a6b7e2bSNikita Shubin init.name = name;
4588a6b7e2bSNikita Shubin init.ops = &ep93xx_div_ops;
4598a6b7e2bSNikita Shubin init.flags = 0;
4608a6b7e2bSNikita Shubin init.parent_data = parent_data;
4618a6b7e2bSNikita Shubin init.num_parents = 1;
4628a6b7e2bSNikita Shubin
4638a6b7e2bSNikita Shubin clk->reg = reg;
4648a6b7e2bSNikita Shubin clk->bit_idx = enable_bit;
4658a6b7e2bSNikita Shubin clk->mask = GENMASK(shift + width - 1, shift);
4668a6b7e2bSNikita Shubin clk->shift = shift;
4678a6b7e2bSNikita Shubin clk->div = clk_divisors;
4688a6b7e2bSNikita Shubin clk->num_div = num_div;
4698a6b7e2bSNikita Shubin clk->hw.init = &init;
4708a6b7e2bSNikita Shubin
4718a6b7e2bSNikita Shubin return devm_clk_hw_register(priv->dev, &clk->hw);
4728a6b7e2bSNikita Shubin }
4738a6b7e2bSNikita Shubin
4748a6b7e2bSNikita Shubin struct ep93xx_gate {
4758a6b7e2bSNikita Shubin unsigned int idx;
4768a6b7e2bSNikita Shubin unsigned int bit;
4778a6b7e2bSNikita Shubin const char *name;
4788a6b7e2bSNikita Shubin };
4798a6b7e2bSNikita Shubin
4808a6b7e2bSNikita Shubin static const struct ep93xx_gate ep93xx_uarts[] = {
4818a6b7e2bSNikita Shubin { EP93XX_CLK_UART1, EP93XX_SYSCON_DEVCFG_U1EN, "uart1" },
4828a6b7e2bSNikita Shubin { EP93XX_CLK_UART2, EP93XX_SYSCON_DEVCFG_U2EN, "uart2" },
4838a6b7e2bSNikita Shubin { EP93XX_CLK_UART3, EP93XX_SYSCON_DEVCFG_U3EN, "uart3" },
4848a6b7e2bSNikita Shubin };
4858a6b7e2bSNikita Shubin
ep93xx_uart_clock_init(struct ep93xx_clk_priv * priv)4868a6b7e2bSNikita Shubin static int ep93xx_uart_clock_init(struct ep93xx_clk_priv *priv)
4878a6b7e2bSNikita Shubin {
4888a6b7e2bSNikita Shubin struct clk_parent_data parent_data = { };
4898a6b7e2bSNikita Shubin unsigned int i, idx, ret, clk_uart_div;
4908a6b7e2bSNikita Shubin struct ep93xx_clk *clk;
4918a6b7e2bSNikita Shubin u32 val;
4928a6b7e2bSNikita Shubin
4938a6b7e2bSNikita Shubin regmap_read(priv->map, EP93XX_SYSCON_PWRCNT, &val);
4948a6b7e2bSNikita Shubin if (val & EP93XX_SYSCON_PWRCNT_UARTBAUD)
4958a6b7e2bSNikita Shubin clk_uart_div = 1;
4968a6b7e2bSNikita Shubin else
4978a6b7e2bSNikita Shubin clk_uart_div = 2;
4988a6b7e2bSNikita Shubin
4998a6b7e2bSNikita Shubin priv->fixed[EP93XX_CLK_UART] =
5008a6b7e2bSNikita Shubin devm_clk_hw_register_fixed_factor_index(priv->dev, "uart",
5018a6b7e2bSNikita Shubin 0, /* XTALI external clock */
5028a6b7e2bSNikita Shubin 0, 1, clk_uart_div);
5038a6b7e2bSNikita Shubin parent_data.hw = priv->fixed[EP93XX_CLK_UART];
5048a6b7e2bSNikita Shubin
5058a6b7e2bSNikita Shubin /* parenting uart gate clocks to uart clock */
5068a6b7e2bSNikita Shubin for (i = 0; i < ARRAY_SIZE(ep93xx_uarts); i++) {
5078a6b7e2bSNikita Shubin idx = ep93xx_uarts[i].idx - EP93XX_CLK_UART1;
5088a6b7e2bSNikita Shubin clk = &priv->reg[idx];
5098a6b7e2bSNikita Shubin clk->idx = idx;
5108a6b7e2bSNikita Shubin ret = ep93xx_clk_register_gate(clk,
5118a6b7e2bSNikita Shubin ep93xx_uarts[i].name,
5128a6b7e2bSNikita Shubin &parent_data, CLK_SET_RATE_PARENT,
5138a6b7e2bSNikita Shubin EP93XX_SYSCON_DEVCFG,
5148a6b7e2bSNikita Shubin ep93xx_uarts[i].bit);
5158a6b7e2bSNikita Shubin if (ret)
5168a6b7e2bSNikita Shubin return dev_err_probe(priv->dev, ret,
5178a6b7e2bSNikita Shubin "failed to register uart[%d] clock\n", i);
5188a6b7e2bSNikita Shubin }
5198a6b7e2bSNikita Shubin
5208a6b7e2bSNikita Shubin return 0;
5218a6b7e2bSNikita Shubin }
5228a6b7e2bSNikita Shubin
5238a6b7e2bSNikita Shubin static const struct ep93xx_gate ep93xx_dmas[] = {
5248a6b7e2bSNikita Shubin { EP93XX_CLK_M2M0, EP93XX_SYSCON_PWRCNT_DMA_M2M0, "m2m0" },
5258a6b7e2bSNikita Shubin { EP93XX_CLK_M2M1, EP93XX_SYSCON_PWRCNT_DMA_M2M1, "m2m1" },
5268a6b7e2bSNikita Shubin { EP93XX_CLK_M2P0, EP93XX_SYSCON_PWRCNT_DMA_M2P0, "m2p0" },
5278a6b7e2bSNikita Shubin { EP93XX_CLK_M2P1, EP93XX_SYSCON_PWRCNT_DMA_M2P1, "m2p1" },
5288a6b7e2bSNikita Shubin { EP93XX_CLK_M2P2, EP93XX_SYSCON_PWRCNT_DMA_M2P2, "m2p2" },
5298a6b7e2bSNikita Shubin { EP93XX_CLK_M2P3, EP93XX_SYSCON_PWRCNT_DMA_M2P3, "m2p3" },
5308a6b7e2bSNikita Shubin { EP93XX_CLK_M2P4, EP93XX_SYSCON_PWRCNT_DMA_M2P4, "m2p4" },
5318a6b7e2bSNikita Shubin { EP93XX_CLK_M2P5, EP93XX_SYSCON_PWRCNT_DMA_M2P5, "m2p5" },
5328a6b7e2bSNikita Shubin { EP93XX_CLK_M2P6, EP93XX_SYSCON_PWRCNT_DMA_M2P6, "m2p6" },
5338a6b7e2bSNikita Shubin { EP93XX_CLK_M2P7, EP93XX_SYSCON_PWRCNT_DMA_M2P7, "m2p7" },
5348a6b7e2bSNikita Shubin { EP93XX_CLK_M2P8, EP93XX_SYSCON_PWRCNT_DMA_M2P8, "m2p8" },
5358a6b7e2bSNikita Shubin { EP93XX_CLK_M2P9, EP93XX_SYSCON_PWRCNT_DMA_M2P9, "m2p9" },
5368a6b7e2bSNikita Shubin };
5378a6b7e2bSNikita Shubin
ep93xx_dma_clock_init(struct ep93xx_clk_priv * priv)5388a6b7e2bSNikita Shubin static int ep93xx_dma_clock_init(struct ep93xx_clk_priv *priv)
5398a6b7e2bSNikita Shubin {
5408a6b7e2bSNikita Shubin struct clk_parent_data parent_data = { };
5418a6b7e2bSNikita Shubin unsigned int i, idx;
5428a6b7e2bSNikita Shubin
5438a6b7e2bSNikita Shubin parent_data.hw = priv->fixed[EP93XX_CLK_HCLK];
5448a6b7e2bSNikita Shubin for (i = 0; i < ARRAY_SIZE(ep93xx_dmas); i++) {
5458a6b7e2bSNikita Shubin idx = ep93xx_dmas[i].idx;
5468a6b7e2bSNikita Shubin priv->fixed[idx] = devm_clk_hw_register_gate_parent_data(priv->dev,
5478a6b7e2bSNikita Shubin ep93xx_dmas[i].name,
5488a6b7e2bSNikita Shubin &parent_data, 0,
5498a6b7e2bSNikita Shubin priv->base + EP93XX_SYSCON_PWRCNT,
5508a6b7e2bSNikita Shubin ep93xx_dmas[i].bit,
5518a6b7e2bSNikita Shubin 0,
5528a6b7e2bSNikita Shubin &priv->lock);
5538a6b7e2bSNikita Shubin if (IS_ERR(priv->fixed[idx]))
5548a6b7e2bSNikita Shubin return PTR_ERR(priv->fixed[idx]);
5558a6b7e2bSNikita Shubin }
5568a6b7e2bSNikita Shubin
5578a6b7e2bSNikita Shubin return 0;
5588a6b7e2bSNikita Shubin }
5598a6b7e2bSNikita Shubin
of_clk_ep93xx_get(struct of_phandle_args * clkspec,void * data)5608a6b7e2bSNikita Shubin static struct clk_hw *of_clk_ep93xx_get(struct of_phandle_args *clkspec, void *data)
5618a6b7e2bSNikita Shubin {
5628a6b7e2bSNikita Shubin struct ep93xx_clk_priv *priv = data;
5638a6b7e2bSNikita Shubin unsigned int idx = clkspec->args[0];
5648a6b7e2bSNikita Shubin
5658a6b7e2bSNikita Shubin if (idx < EP93XX_CLK_UART1)
5668a6b7e2bSNikita Shubin return priv->fixed[idx];
5678a6b7e2bSNikita Shubin
5688a6b7e2bSNikita Shubin if (idx <= EP93XX_CLK_I2S_LRCLK)
5698a6b7e2bSNikita Shubin return &priv->reg[idx - EP93XX_CLK_UART1].hw;
5708a6b7e2bSNikita Shubin
5718a6b7e2bSNikita Shubin return ERR_PTR(-EINVAL);
5728a6b7e2bSNikita Shubin }
5738a6b7e2bSNikita Shubin
5748a6b7e2bSNikita Shubin /*
5758a6b7e2bSNikita Shubin * PLL rate = 14.7456 MHz * (X1FBD + 1) * (X2FBD + 1) / (X2IPD + 1) / 2^PS
5768a6b7e2bSNikita Shubin */
calc_pll_rate(u64 rate,u32 config_word)5778a6b7e2bSNikita Shubin static unsigned long calc_pll_rate(u64 rate, u32 config_word)
5788a6b7e2bSNikita Shubin {
5798a6b7e2bSNikita Shubin rate *= ((config_word >> 11) & GENMASK(4, 0)) + 1; /* X1FBD */
5808a6b7e2bSNikita Shubin rate *= ((config_word >> 5) & GENMASK(5, 0)) + 1; /* X2FBD */
5818a6b7e2bSNikita Shubin do_div(rate, (config_word & GENMASK(4, 0)) + 1); /* X2IPD */
5828a6b7e2bSNikita Shubin rate >>= (config_word >> 16) & GENMASK(1, 0); /* PS */
5838a6b7e2bSNikita Shubin
5848a6b7e2bSNikita Shubin return rate;
5858a6b7e2bSNikita Shubin }
5868a6b7e2bSNikita Shubin
ep93xx_plls_init(struct ep93xx_clk_priv * priv)5878a6b7e2bSNikita Shubin static int ep93xx_plls_init(struct ep93xx_clk_priv *priv)
5888a6b7e2bSNikita Shubin {
5898a6b7e2bSNikita Shubin const char fclk_divisors[] = { 1, 2, 4, 8, 16, 1, 1, 1 };
5908a6b7e2bSNikita Shubin const char hclk_divisors[] = { 1, 2, 4, 5, 6, 8, 16, 32 };
5918a6b7e2bSNikita Shubin const char pclk_divisors[] = { 1, 2, 4, 8 };
5928a6b7e2bSNikita Shubin struct clk_parent_data xtali = { .index = 0 };
5938a6b7e2bSNikita Shubin unsigned int clk_f_div, clk_h_div, clk_p_div;
5948a6b7e2bSNikita Shubin unsigned long clk_pll1_rate, clk_pll2_rate;
5958a6b7e2bSNikita Shubin struct device *dev = priv->dev;
5968a6b7e2bSNikita Shubin struct clk_hw *hw, *pll1;
5978a6b7e2bSNikita Shubin u32 value;
5988a6b7e2bSNikita Shubin
5998a6b7e2bSNikita Shubin /* Determine the bootloader configured pll1 rate */
6008a6b7e2bSNikita Shubin regmap_read(priv->map, EP93XX_SYSCON_CLKSET1, &value);
6018a6b7e2bSNikita Shubin
6028a6b7e2bSNikita Shubin if (value & EP93XX_SYSCON_CLKSET1_NBYP1)
6038a6b7e2bSNikita Shubin clk_pll1_rate = calc_pll_rate(EP93XX_EXT_CLK_RATE, value);
6048a6b7e2bSNikita Shubin else
6058a6b7e2bSNikita Shubin clk_pll1_rate = EP93XX_EXT_CLK_RATE;
6068a6b7e2bSNikita Shubin
6078a6b7e2bSNikita Shubin pll1 = devm_clk_hw_register_fixed_rate_parent_data(dev, "pll1", &xtali,
6088a6b7e2bSNikita Shubin 0, clk_pll1_rate);
6098a6b7e2bSNikita Shubin if (IS_ERR(pll1))
6108a6b7e2bSNikita Shubin return PTR_ERR(pll1);
6118a6b7e2bSNikita Shubin
6128a6b7e2bSNikita Shubin priv->fixed[EP93XX_CLK_PLL1] = pll1;
6138a6b7e2bSNikita Shubin
6148a6b7e2bSNikita Shubin /* Initialize the pll1 derived clocks */
6158a6b7e2bSNikita Shubin clk_f_div = fclk_divisors[(value >> 25) & GENMASK(2, 0)];
6168a6b7e2bSNikita Shubin clk_h_div = hclk_divisors[(value >> 20) & GENMASK(2, 0)];
6178a6b7e2bSNikita Shubin clk_p_div = pclk_divisors[(value >> 18) & GENMASK(1, 0)];
6188a6b7e2bSNikita Shubin
6198a6b7e2bSNikita Shubin hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, "fclk", pll1, 0, 1, clk_f_div);
6208a6b7e2bSNikita Shubin if (IS_ERR(hw))
6218a6b7e2bSNikita Shubin return PTR_ERR(hw);
6228a6b7e2bSNikita Shubin
6238a6b7e2bSNikita Shubin priv->fixed[EP93XX_CLK_FCLK] = hw;
6248a6b7e2bSNikita Shubin
6258a6b7e2bSNikita Shubin hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, "hclk", pll1, 0, 1, clk_h_div);
6268a6b7e2bSNikita Shubin if (IS_ERR(hw))
6278a6b7e2bSNikita Shubin return PTR_ERR(hw);
6288a6b7e2bSNikita Shubin
6298a6b7e2bSNikita Shubin priv->fixed[EP93XX_CLK_HCLK] = hw;
6308a6b7e2bSNikita Shubin
6318a6b7e2bSNikita Shubin hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, "pclk", hw, 0, 1, clk_p_div);
6328a6b7e2bSNikita Shubin if (IS_ERR(hw))
6338a6b7e2bSNikita Shubin return PTR_ERR(hw);
6348a6b7e2bSNikita Shubin
6358a6b7e2bSNikita Shubin priv->fixed[EP93XX_CLK_PCLK] = hw;
6368a6b7e2bSNikita Shubin
6378a6b7e2bSNikita Shubin /* Determine the bootloader configured pll2 rate */
6388a6b7e2bSNikita Shubin regmap_read(priv->map, EP93XX_SYSCON_CLKSET2, &value);
6398a6b7e2bSNikita Shubin if (!(value & EP93XX_SYSCON_CLKSET2_NBYP2))
6408a6b7e2bSNikita Shubin clk_pll2_rate = EP93XX_EXT_CLK_RATE;
6418a6b7e2bSNikita Shubin else if (value & EP93XX_SYSCON_CLKSET2_PLL2_EN)
6428a6b7e2bSNikita Shubin clk_pll2_rate = calc_pll_rate(EP93XX_EXT_CLK_RATE, value);
6438a6b7e2bSNikita Shubin else
6448a6b7e2bSNikita Shubin clk_pll2_rate = 0;
6458a6b7e2bSNikita Shubin
6468a6b7e2bSNikita Shubin hw = devm_clk_hw_register_fixed_rate_parent_data(dev, "pll2", &xtali,
6478a6b7e2bSNikita Shubin 0, clk_pll2_rate);
6488a6b7e2bSNikita Shubin if (IS_ERR(hw))
6498a6b7e2bSNikita Shubin return PTR_ERR(hw);
6508a6b7e2bSNikita Shubin
6518a6b7e2bSNikita Shubin priv->fixed[EP93XX_CLK_PLL2] = hw;
6528a6b7e2bSNikita Shubin
6538a6b7e2bSNikita Shubin return 0;
6548a6b7e2bSNikita Shubin }
6558a6b7e2bSNikita Shubin
ep93xx_clk_probe(struct auxiliary_device * adev,const struct auxiliary_device_id * id)6568a6b7e2bSNikita Shubin static int ep93xx_clk_probe(struct auxiliary_device *adev,
6578a6b7e2bSNikita Shubin const struct auxiliary_device_id *id)
6588a6b7e2bSNikita Shubin {
6598a6b7e2bSNikita Shubin struct ep93xx_regmap_adev *rdev = to_ep93xx_regmap_adev(adev);
6608a6b7e2bSNikita Shubin struct clk_parent_data xtali = { .index = 0 };
6618a6b7e2bSNikita Shubin struct clk_parent_data ddiv_pdata[3] = { };
6628a6b7e2bSNikita Shubin unsigned int clk_spi_div, clk_usb_div;
6638a6b7e2bSNikita Shubin struct clk_parent_data pdata = {};
6648a6b7e2bSNikita Shubin struct device *dev = &adev->dev;
6658a6b7e2bSNikita Shubin struct ep93xx_clk_priv *priv;
6668a6b7e2bSNikita Shubin struct ep93xx_clk *clk;
6678a6b7e2bSNikita Shubin struct clk_hw *hw;
6688a6b7e2bSNikita Shubin unsigned int idx;
6698a6b7e2bSNikita Shubin int ret;
6708a6b7e2bSNikita Shubin u32 value;
6718a6b7e2bSNikita Shubin
6728a6b7e2bSNikita Shubin priv = devm_kzalloc(dev, struct_size(priv, reg, 10), GFP_KERNEL);
6738a6b7e2bSNikita Shubin if (!priv)
6748a6b7e2bSNikita Shubin return -ENOMEM;
6758a6b7e2bSNikita Shubin
6768a6b7e2bSNikita Shubin spin_lock_init(&priv->lock);
6778a6b7e2bSNikita Shubin priv->dev = dev;
6788a6b7e2bSNikita Shubin priv->aux_dev = rdev;
6798a6b7e2bSNikita Shubin priv->map = rdev->map;
6808a6b7e2bSNikita Shubin priv->base = rdev->base;
6818a6b7e2bSNikita Shubin
6828a6b7e2bSNikita Shubin ret = ep93xx_plls_init(priv);
6838a6b7e2bSNikita Shubin if (ret)
6848a6b7e2bSNikita Shubin return ret;
6858a6b7e2bSNikita Shubin
6868a6b7e2bSNikita Shubin regmap_read(priv->map, EP93XX_SYSCON_CLKSET2, &value);
6878a6b7e2bSNikita Shubin clk_usb_div = (value >> 28 & GENMASK(3, 0)) + 1;
6888a6b7e2bSNikita Shubin hw = devm_clk_hw_register_fixed_factor_parent_hw(dev, "usb_clk",
6898a6b7e2bSNikita Shubin priv->fixed[EP93XX_CLK_PLL2], 0, 1,
6908a6b7e2bSNikita Shubin clk_usb_div);
6918a6b7e2bSNikita Shubin if (IS_ERR(hw))
6928a6b7e2bSNikita Shubin return PTR_ERR(hw);
6938a6b7e2bSNikita Shubin
6948a6b7e2bSNikita Shubin priv->fixed[EP93XX_CLK_USB] = hw;
6958a6b7e2bSNikita Shubin
6968a6b7e2bSNikita Shubin ret = ep93xx_uart_clock_init(priv);
6978a6b7e2bSNikita Shubin if (ret)
6988a6b7e2bSNikita Shubin return ret;
6998a6b7e2bSNikita Shubin
7008a6b7e2bSNikita Shubin ret = ep93xx_dma_clock_init(priv);
7018a6b7e2bSNikita Shubin if (ret)
7028a6b7e2bSNikita Shubin return ret;
7038a6b7e2bSNikita Shubin
7048a6b7e2bSNikita Shubin clk_spi_div = id->driver_data;
7058a6b7e2bSNikita Shubin hw = devm_clk_hw_register_fixed_factor_index(dev, "ep93xx-spi.0",
7068a6b7e2bSNikita Shubin 0, /* XTALI external clock */
7078a6b7e2bSNikita Shubin 0, 1, clk_spi_div);
7088a6b7e2bSNikita Shubin if (IS_ERR(hw))
7098a6b7e2bSNikita Shubin return PTR_ERR(hw);
7108a6b7e2bSNikita Shubin
7118a6b7e2bSNikita Shubin priv->fixed[EP93XX_CLK_SPI] = hw;
7128a6b7e2bSNikita Shubin
7138a6b7e2bSNikita Shubin /* PWM clock */
7148a6b7e2bSNikita Shubin hw = devm_clk_hw_register_fixed_factor_index(dev, "pwm_clk", 0, /* XTALI external clock */
7158a6b7e2bSNikita Shubin 0, 1, 1);
7168a6b7e2bSNikita Shubin if (IS_ERR(hw))
7178a6b7e2bSNikita Shubin return PTR_ERR(hw);
7188a6b7e2bSNikita Shubin
7198a6b7e2bSNikita Shubin priv->fixed[EP93XX_CLK_PWM] = hw;
7208a6b7e2bSNikita Shubin
7218a6b7e2bSNikita Shubin /* USB clock */
7228a6b7e2bSNikita Shubin pdata.hw = priv->fixed[EP93XX_CLK_USB];
7238a6b7e2bSNikita Shubin hw = devm_clk_hw_register_gate_parent_data(priv->dev, "ohci-platform", &pdata,
7248a6b7e2bSNikita Shubin 0, priv->base + EP93XX_SYSCON_PWRCNT,
7258a6b7e2bSNikita Shubin EP93XX_SYSCON_PWRCNT_USH_EN, 0,
7268a6b7e2bSNikita Shubin &priv->lock);
7278a6b7e2bSNikita Shubin if (IS_ERR(hw))
7288a6b7e2bSNikita Shubin return PTR_ERR(hw);
7298a6b7e2bSNikita Shubin
7308a6b7e2bSNikita Shubin priv->fixed[EP93XX_CLK_USB] = hw;
7318a6b7e2bSNikita Shubin
7328a6b7e2bSNikita Shubin ddiv_pdata[0].index = 0; /* XTALI external clock */
7338a6b7e2bSNikita Shubin ddiv_pdata[1].hw = priv->fixed[EP93XX_CLK_PLL1];
7348a6b7e2bSNikita Shubin ddiv_pdata[2].hw = priv->fixed[EP93XX_CLK_PLL2];
7358a6b7e2bSNikita Shubin
7368a6b7e2bSNikita Shubin /* touchscreen/ADC clock */
7378a6b7e2bSNikita Shubin idx = EP93XX_CLK_ADC - EP93XX_CLK_UART1;
7388a6b7e2bSNikita Shubin clk = &priv->reg[idx];
7398a6b7e2bSNikita Shubin clk->idx = idx;
7408a6b7e2bSNikita Shubin ret = ep93xx_register_div(clk, "ep93xx-adc", &xtali,
7418a6b7e2bSNikita Shubin EP93XX_SYSCON_KEYTCHCLKDIV,
7428a6b7e2bSNikita Shubin EP93XX_SYSCON_KEYTCHCLKDIV_TSEN,
7438a6b7e2bSNikita Shubin EP93XX_SYSCON_KEYTCHCLKDIV_ADIV,
7448a6b7e2bSNikita Shubin 1,
7458a6b7e2bSNikita Shubin ep93xx_adc_divisors,
7468a6b7e2bSNikita Shubin ARRAY_SIZE(ep93xx_adc_divisors));
7478a6b7e2bSNikita Shubin
7488a6b7e2bSNikita Shubin
7498a6b7e2bSNikita Shubin /* keypad clock */
7508a6b7e2bSNikita Shubin idx = EP93XX_CLK_KEYPAD - EP93XX_CLK_UART1;
7518a6b7e2bSNikita Shubin clk = &priv->reg[idx];
7528a6b7e2bSNikita Shubin clk->idx = idx;
7538a6b7e2bSNikita Shubin ret = ep93xx_register_div(clk, "ep93xx-keypad", &xtali,
7548a6b7e2bSNikita Shubin EP93XX_SYSCON_KEYTCHCLKDIV,
7558a6b7e2bSNikita Shubin EP93XX_SYSCON_KEYTCHCLKDIV_KEN,
7568a6b7e2bSNikita Shubin EP93XX_SYSCON_KEYTCHCLKDIV_KDIV,
7578a6b7e2bSNikita Shubin 1,
7588a6b7e2bSNikita Shubin ep93xx_adc_divisors,
7598a6b7e2bSNikita Shubin ARRAY_SIZE(ep93xx_adc_divisors));
7608a6b7e2bSNikita Shubin
7618a6b7e2bSNikita Shubin /*
7628a6b7e2bSNikita Shubin * On reset PDIV and VDIV is set to zero, while PDIV zero
7638a6b7e2bSNikita Shubin * means clock disable, VDIV shouldn't be zero.
7648a6b7e2bSNikita Shubin * So we set both video and i2s dividers to minimum.
7658a6b7e2bSNikita Shubin * ENA - Enable CLK divider.
7668a6b7e2bSNikita Shubin * PDIV - 00 - Disable clock
7678a6b7e2bSNikita Shubin * VDIV - at least 2
7688a6b7e2bSNikita Shubin */
7698a6b7e2bSNikita Shubin
7708a6b7e2bSNikita Shubin /* Check and enable video clk registers */
7718a6b7e2bSNikita Shubin regmap_read(priv->map, EP93XX_SYSCON_VIDCLKDIV, &value);
7728a6b7e2bSNikita Shubin value |= BIT(EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2;
7738a6b7e2bSNikita Shubin ep93xx_clk_write(priv, EP93XX_SYSCON_VIDCLKDIV, value);
7748a6b7e2bSNikita Shubin
7758a6b7e2bSNikita Shubin /* Check and enable i2s clk registers */
7768a6b7e2bSNikita Shubin regmap_read(priv->map, EP93XX_SYSCON_I2SCLKDIV, &value);
7778a6b7e2bSNikita Shubin value |= BIT(EP93XX_SYSCON_CLKDIV_PDIV_SHIFT) | 2;
7788a6b7e2bSNikita Shubin
7798a6b7e2bSNikita Shubin /*
7808a6b7e2bSNikita Shubin * Override the SAI_MSTR_CLK_CFG from the I2S block and use the
7818a6b7e2bSNikita Shubin * I2SClkDiv Register settings. LRCLK transitions on the falling SCLK
7828a6b7e2bSNikita Shubin * edge.
7838a6b7e2bSNikita Shubin */
7848a6b7e2bSNikita Shubin value |= EP93XX_SYSCON_I2SCLKDIV_ORIDE | EP93XX_SYSCON_I2SCLKDIV_SPOL;
7858a6b7e2bSNikita Shubin ep93xx_clk_write(priv, EP93XX_SYSCON_I2SCLKDIV, value);
7868a6b7e2bSNikita Shubin
7878a6b7e2bSNikita Shubin /* video clk */
7888a6b7e2bSNikita Shubin idx = EP93XX_CLK_VIDEO - EP93XX_CLK_UART1;
7898a6b7e2bSNikita Shubin clk = &priv->reg[idx];
7908a6b7e2bSNikita Shubin clk->idx = idx;
7918a6b7e2bSNikita Shubin ret = ep93xx_clk_register_ddiv(clk, "ep93xx-fb",
7928a6b7e2bSNikita Shubin ddiv_pdata, ARRAY_SIZE(ddiv_pdata),
7938a6b7e2bSNikita Shubin EP93XX_SYSCON_VIDCLKDIV,
7948a6b7e2bSNikita Shubin EP93XX_SYSCON_CLKDIV_ENABLE);
7958a6b7e2bSNikita Shubin
7968a6b7e2bSNikita Shubin /* i2s clk */
7978a6b7e2bSNikita Shubin idx = EP93XX_CLK_I2S_MCLK - EP93XX_CLK_UART1;
7988a6b7e2bSNikita Shubin clk = &priv->reg[idx];
7998a6b7e2bSNikita Shubin clk->idx = idx;
8008a6b7e2bSNikita Shubin ret = ep93xx_clk_register_ddiv(clk, "mclk",
8018a6b7e2bSNikita Shubin ddiv_pdata, ARRAY_SIZE(ddiv_pdata),
8028a6b7e2bSNikita Shubin EP93XX_SYSCON_I2SCLKDIV,
8038a6b7e2bSNikita Shubin EP93XX_SYSCON_CLKDIV_ENABLE);
8048a6b7e2bSNikita Shubin
8058a6b7e2bSNikita Shubin /* i2s sclk */
8068a6b7e2bSNikita Shubin idx = EP93XX_CLK_I2S_SCLK - EP93XX_CLK_UART1;
8078a6b7e2bSNikita Shubin clk = &priv->reg[idx];
8088a6b7e2bSNikita Shubin clk->idx = idx;
8098a6b7e2bSNikita Shubin pdata.hw = &priv->reg[EP93XX_CLK_I2S_MCLK - EP93XX_CLK_UART1].hw;
8108a6b7e2bSNikita Shubin ret = ep93xx_register_div(clk, "sclk", &pdata,
8118a6b7e2bSNikita Shubin EP93XX_SYSCON_I2SCLKDIV,
8128a6b7e2bSNikita Shubin EP93XX_SYSCON_I2SCLKDIV_SENA,
8138a6b7e2bSNikita Shubin 16, /* EP93XX_I2SCLKDIV_SDIV_SHIFT */
8148a6b7e2bSNikita Shubin 1, /* EP93XX_I2SCLKDIV_SDIV_WIDTH */
8158a6b7e2bSNikita Shubin ep93xx_sclk_divisors,
8168a6b7e2bSNikita Shubin ARRAY_SIZE(ep93xx_sclk_divisors));
8178a6b7e2bSNikita Shubin
8188a6b7e2bSNikita Shubin /* i2s lrclk */
8198a6b7e2bSNikita Shubin idx = EP93XX_CLK_I2S_LRCLK - EP93XX_CLK_UART1;
8208a6b7e2bSNikita Shubin clk = &priv->reg[idx];
8218a6b7e2bSNikita Shubin clk->idx = idx;
8228a6b7e2bSNikita Shubin pdata.hw = &priv->reg[EP93XX_CLK_I2S_SCLK - EP93XX_CLK_UART1].hw;
8238a6b7e2bSNikita Shubin ret = ep93xx_register_div(clk, "lrclk", &pdata,
8248a6b7e2bSNikita Shubin EP93XX_SYSCON_I2SCLKDIV,
8258a6b7e2bSNikita Shubin EP93XX_SYSCON_I2SCLKDIV_SENA,
8268a6b7e2bSNikita Shubin 17, /* EP93XX_I2SCLKDIV_LRDIV32_SHIFT */
8278a6b7e2bSNikita Shubin 2, /* EP93XX_I2SCLKDIV_LRDIV32_WIDTH */
8288a6b7e2bSNikita Shubin ep93xx_lrclk_divisors,
8298a6b7e2bSNikita Shubin ARRAY_SIZE(ep93xx_lrclk_divisors));
8308a6b7e2bSNikita Shubin
8318a6b7e2bSNikita Shubin /* IrDa clk uses same pattern but no init code presents in original clock driver */
8328a6b7e2bSNikita Shubin return devm_of_clk_add_hw_provider(priv->dev, of_clk_ep93xx_get, priv);
8338a6b7e2bSNikita Shubin }
8348a6b7e2bSNikita Shubin
8358a6b7e2bSNikita Shubin static const struct auxiliary_device_id ep93xx_clk_ids[] = {
8368a6b7e2bSNikita Shubin { .name = "soc_ep93xx.clk-ep93xx", .driver_data = 2, },
8378a6b7e2bSNikita Shubin { .name = "soc_ep93xx.clk-ep93xx.e2", .driver_data = 1, },
8388a6b7e2bSNikita Shubin { /* sentinel */ }
8398a6b7e2bSNikita Shubin };
8408a6b7e2bSNikita Shubin MODULE_DEVICE_TABLE(auxiliary, ep93xx_clk_ids);
8418a6b7e2bSNikita Shubin
8428a6b7e2bSNikita Shubin static struct auxiliary_driver ep93xx_clk_driver = {
8438a6b7e2bSNikita Shubin .probe = ep93xx_clk_probe,
8448a6b7e2bSNikita Shubin .id_table = ep93xx_clk_ids,
8458a6b7e2bSNikita Shubin };
8468a6b7e2bSNikita Shubin module_auxiliary_driver(ep93xx_clk_driver);
847e2a79105SArnd Bergmann
848e2a79105SArnd Bergmann MODULE_LICENSE("GPL");
849e2a79105SArnd Bergmann MODULE_AUTHOR("Nikita Shubin <nikita.shubin@maquefel.me>");
850e2a79105SArnd Bergmann MODULE_DESCRIPTION("Clock control for Cirrus EP93xx chips");
851