162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Mediatek MT7621 Clock Driver 462306a36Sopenharmony_ci * Author: Sergio Paracuellos <sergio.paracuellos@gmail.com> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/bitfield.h> 862306a36Sopenharmony_ci#include <linux/bitops.h> 962306a36Sopenharmony_ci#include <linux/clk-provider.h> 1062306a36Sopenharmony_ci#include <linux/clk.h> 1162306a36Sopenharmony_ci#include <linux/mfd/syscon.h> 1262306a36Sopenharmony_ci#include <linux/platform_device.h> 1362306a36Sopenharmony_ci#include <linux/regmap.h> 1462306a36Sopenharmony_ci#include <linux/reset-controller.h> 1562306a36Sopenharmony_ci#include <linux/slab.h> 1662306a36Sopenharmony_ci#include <dt-bindings/clock/mt7621-clk.h> 1762306a36Sopenharmony_ci#include <dt-bindings/reset/mt7621-reset.h> 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci/* Configuration registers */ 2062306a36Sopenharmony_ci#define SYSC_REG_SYSTEM_CONFIG0 0x10 2162306a36Sopenharmony_ci#define SYSC_REG_SYSTEM_CONFIG1 0x14 2262306a36Sopenharmony_ci#define SYSC_REG_CLKCFG0 0x2c 2362306a36Sopenharmony_ci#define SYSC_REG_CLKCFG1 0x30 2462306a36Sopenharmony_ci#define SYSC_REG_RESET_CTRL 0x34 2562306a36Sopenharmony_ci#define SYSC_REG_CUR_CLK_STS 0x44 2662306a36Sopenharmony_ci#define MEMC_REG_CPU_PLL 0x648 2762306a36Sopenharmony_ci 2862306a36Sopenharmony_ci#define XTAL_MODE_SEL_MASK GENMASK(8, 6) 2962306a36Sopenharmony_ci#define CPU_CLK_SEL_MASK GENMASK(31, 30) 3062306a36Sopenharmony_ci#define CUR_CPU_FDIV_MASK GENMASK(12, 8) 3162306a36Sopenharmony_ci#define CUR_CPU_FFRAC_MASK GENMASK(4, 0) 3262306a36Sopenharmony_ci#define CPU_PLL_PREDIV_MASK GENMASK(13, 12) 3362306a36Sopenharmony_ci#define CPU_PLL_FBDIV_MASK GENMASK(10, 4) 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_cistruct mt7621_clk_priv { 3662306a36Sopenharmony_ci struct regmap *sysc; 3762306a36Sopenharmony_ci struct regmap *memc; 3862306a36Sopenharmony_ci}; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cistruct mt7621_clk { 4162306a36Sopenharmony_ci struct clk_hw hw; 4262306a36Sopenharmony_ci struct mt7621_clk_priv *priv; 4362306a36Sopenharmony_ci}; 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistruct mt7621_fixed_clk { 4662306a36Sopenharmony_ci u8 idx; 4762306a36Sopenharmony_ci const char *name; 4862306a36Sopenharmony_ci const char *parent_name; 4962306a36Sopenharmony_ci unsigned long rate; 5062306a36Sopenharmony_ci struct clk_hw *hw; 5162306a36Sopenharmony_ci}; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_cistruct mt7621_gate { 5462306a36Sopenharmony_ci u8 idx; 5562306a36Sopenharmony_ci const char *name; 5662306a36Sopenharmony_ci const char *parent_name; 5762306a36Sopenharmony_ci struct mt7621_clk_priv *priv; 5862306a36Sopenharmony_ci u32 bit_idx; 5962306a36Sopenharmony_ci struct clk_hw hw; 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci#define GATE(_id, _name, _pname, _shift) \ 6362306a36Sopenharmony_ci { \ 6462306a36Sopenharmony_ci .idx = _id, \ 6562306a36Sopenharmony_ci .name = _name, \ 6662306a36Sopenharmony_ci .parent_name = _pname, \ 6762306a36Sopenharmony_ci .bit_idx = _shift \ 6862306a36Sopenharmony_ci } 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_cistatic struct mt7621_gate mt7621_gates[] = { 7162306a36Sopenharmony_ci GATE(MT7621_CLK_HSDMA, "hsdma", "150m", BIT(5)), 7262306a36Sopenharmony_ci GATE(MT7621_CLK_FE, "fe", "250m", BIT(6)), 7362306a36Sopenharmony_ci GATE(MT7621_CLK_SP_DIVTX, "sp_divtx", "270m", BIT(7)), 7462306a36Sopenharmony_ci GATE(MT7621_CLK_TIMER, "timer", "50m", BIT(8)), 7562306a36Sopenharmony_ci GATE(MT7621_CLK_PCM, "pcm", "270m", BIT(11)), 7662306a36Sopenharmony_ci GATE(MT7621_CLK_PIO, "pio", "50m", BIT(13)), 7762306a36Sopenharmony_ci GATE(MT7621_CLK_GDMA, "gdma", "bus", BIT(14)), 7862306a36Sopenharmony_ci GATE(MT7621_CLK_NAND, "nand", "125m", BIT(15)), 7962306a36Sopenharmony_ci GATE(MT7621_CLK_I2C, "i2c", "50m", BIT(16)), 8062306a36Sopenharmony_ci GATE(MT7621_CLK_I2S, "i2s", "270m", BIT(17)), 8162306a36Sopenharmony_ci GATE(MT7621_CLK_SPI, "spi", "bus", BIT(18)), 8262306a36Sopenharmony_ci GATE(MT7621_CLK_UART1, "uart1", "50m", BIT(19)), 8362306a36Sopenharmony_ci GATE(MT7621_CLK_UART2, "uart2", "50m", BIT(20)), 8462306a36Sopenharmony_ci GATE(MT7621_CLK_UART3, "uart3", "50m", BIT(21)), 8562306a36Sopenharmony_ci GATE(MT7621_CLK_ETH, "eth", "50m", BIT(23)), 8662306a36Sopenharmony_ci GATE(MT7621_CLK_PCIE0, "pcie0", "125m", BIT(24)), 8762306a36Sopenharmony_ci GATE(MT7621_CLK_PCIE1, "pcie1", "125m", BIT(25)), 8862306a36Sopenharmony_ci GATE(MT7621_CLK_PCIE2, "pcie2", "125m", BIT(26)), 8962306a36Sopenharmony_ci GATE(MT7621_CLK_CRYPTO, "crypto", "250m", BIT(29)), 9062306a36Sopenharmony_ci GATE(MT7621_CLK_SHXC, "shxc", "50m", BIT(30)) 9162306a36Sopenharmony_ci}; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_cistatic inline struct mt7621_gate *to_mt7621_gate(struct clk_hw *hw) 9462306a36Sopenharmony_ci{ 9562306a36Sopenharmony_ci return container_of(hw, struct mt7621_gate, hw); 9662306a36Sopenharmony_ci} 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cistatic int mt7621_gate_enable(struct clk_hw *hw) 9962306a36Sopenharmony_ci{ 10062306a36Sopenharmony_ci struct mt7621_gate *clk_gate = to_mt7621_gate(hw); 10162306a36Sopenharmony_ci struct regmap *sysc = clk_gate->priv->sysc; 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci return regmap_update_bits(sysc, SYSC_REG_CLKCFG1, 10462306a36Sopenharmony_ci clk_gate->bit_idx, clk_gate->bit_idx); 10562306a36Sopenharmony_ci} 10662306a36Sopenharmony_ci 10762306a36Sopenharmony_cistatic void mt7621_gate_disable(struct clk_hw *hw) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci struct mt7621_gate *clk_gate = to_mt7621_gate(hw); 11062306a36Sopenharmony_ci struct regmap *sysc = clk_gate->priv->sysc; 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci regmap_update_bits(sysc, SYSC_REG_CLKCFG1, clk_gate->bit_idx, 0); 11362306a36Sopenharmony_ci} 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_cistatic int mt7621_gate_is_enabled(struct clk_hw *hw) 11662306a36Sopenharmony_ci{ 11762306a36Sopenharmony_ci struct mt7621_gate *clk_gate = to_mt7621_gate(hw); 11862306a36Sopenharmony_ci struct regmap *sysc = clk_gate->priv->sysc; 11962306a36Sopenharmony_ci u32 val; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci if (regmap_read(sysc, SYSC_REG_CLKCFG1, &val)) 12262306a36Sopenharmony_ci return 0; 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci return val & clk_gate->bit_idx; 12562306a36Sopenharmony_ci} 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic const struct clk_ops mt7621_gate_ops = { 12862306a36Sopenharmony_ci .enable = mt7621_gate_enable, 12962306a36Sopenharmony_ci .disable = mt7621_gate_disable, 13062306a36Sopenharmony_ci .is_enabled = mt7621_gate_is_enabled, 13162306a36Sopenharmony_ci}; 13262306a36Sopenharmony_ci 13362306a36Sopenharmony_cistatic int mt7621_gate_ops_init(struct device *dev, 13462306a36Sopenharmony_ci struct mt7621_gate *sclk) 13562306a36Sopenharmony_ci{ 13662306a36Sopenharmony_ci /* 13762306a36Sopenharmony_ci * There are drivers for this SoC that are older 13862306a36Sopenharmony_ci * than clock driver and are not prepared for the clock. 13962306a36Sopenharmony_ci * We don't want the kernel to disable anything so we 14062306a36Sopenharmony_ci * add CLK_IS_CRITICAL flag here. 14162306a36Sopenharmony_ci */ 14262306a36Sopenharmony_ci struct clk_init_data init = { 14362306a36Sopenharmony_ci .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL, 14462306a36Sopenharmony_ci .num_parents = 1, 14562306a36Sopenharmony_ci .parent_names = &sclk->parent_name, 14662306a36Sopenharmony_ci .ops = &mt7621_gate_ops, 14762306a36Sopenharmony_ci .name = sclk->name, 14862306a36Sopenharmony_ci }; 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci sclk->hw.init = &init; 15162306a36Sopenharmony_ci return devm_clk_hw_register(dev, &sclk->hw); 15262306a36Sopenharmony_ci} 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_cistatic int mt7621_register_gates(struct device *dev, 15562306a36Sopenharmony_ci struct clk_hw_onecell_data *clk_data, 15662306a36Sopenharmony_ci struct mt7621_clk_priv *priv) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci struct clk_hw **hws = clk_data->hws; 15962306a36Sopenharmony_ci struct mt7621_gate *sclk; 16062306a36Sopenharmony_ci int ret, i; 16162306a36Sopenharmony_ci 16262306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mt7621_gates); i++) { 16362306a36Sopenharmony_ci sclk = &mt7621_gates[i]; 16462306a36Sopenharmony_ci sclk->priv = priv; 16562306a36Sopenharmony_ci ret = mt7621_gate_ops_init(dev, sclk); 16662306a36Sopenharmony_ci if (ret) { 16762306a36Sopenharmony_ci dev_err(dev, "Couldn't register clock %s\n", sclk->name); 16862306a36Sopenharmony_ci goto err_clk_unreg; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci hws[sclk->idx] = &sclk->hw; 17262306a36Sopenharmony_ci } 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci return 0; 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cierr_clk_unreg: 17762306a36Sopenharmony_ci while (--i >= 0) { 17862306a36Sopenharmony_ci sclk = &mt7621_gates[i]; 17962306a36Sopenharmony_ci clk_hw_unregister(&sclk->hw); 18062306a36Sopenharmony_ci } 18162306a36Sopenharmony_ci return ret; 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci#define FIXED(_id, _name, _rate) \ 18562306a36Sopenharmony_ci { \ 18662306a36Sopenharmony_ci .idx = _id, \ 18762306a36Sopenharmony_ci .name = _name, \ 18862306a36Sopenharmony_ci .parent_name = "xtal", \ 18962306a36Sopenharmony_ci .rate = _rate \ 19062306a36Sopenharmony_ci } 19162306a36Sopenharmony_ci 19262306a36Sopenharmony_cistatic struct mt7621_fixed_clk mt7621_fixed_clks[] = { 19362306a36Sopenharmony_ci FIXED(MT7621_CLK_50M, "50m", 50000000), 19462306a36Sopenharmony_ci FIXED(MT7621_CLK_125M, "125m", 125000000), 19562306a36Sopenharmony_ci FIXED(MT7621_CLK_150M, "150m", 150000000), 19662306a36Sopenharmony_ci FIXED(MT7621_CLK_250M, "250m", 250000000), 19762306a36Sopenharmony_ci FIXED(MT7621_CLK_270M, "270m", 270000000), 19862306a36Sopenharmony_ci}; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic int mt7621_register_fixed_clocks(struct device *dev, 20162306a36Sopenharmony_ci struct clk_hw_onecell_data *clk_data) 20262306a36Sopenharmony_ci{ 20362306a36Sopenharmony_ci struct clk_hw **hws = clk_data->hws; 20462306a36Sopenharmony_ci struct mt7621_fixed_clk *sclk; 20562306a36Sopenharmony_ci int ret, i; 20662306a36Sopenharmony_ci 20762306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mt7621_fixed_clks); i++) { 20862306a36Sopenharmony_ci sclk = &mt7621_fixed_clks[i]; 20962306a36Sopenharmony_ci sclk->hw = clk_hw_register_fixed_rate(dev, sclk->name, 21062306a36Sopenharmony_ci sclk->parent_name, 0, 21162306a36Sopenharmony_ci sclk->rate); 21262306a36Sopenharmony_ci if (IS_ERR(sclk->hw)) { 21362306a36Sopenharmony_ci dev_err(dev, "Couldn't register clock %s\n", sclk->name); 21462306a36Sopenharmony_ci ret = PTR_ERR(sclk->hw); 21562306a36Sopenharmony_ci goto err_clk_unreg; 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci hws[sclk->idx] = sclk->hw; 21962306a36Sopenharmony_ci } 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci return 0; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_cierr_clk_unreg: 22462306a36Sopenharmony_ci while (--i >= 0) { 22562306a36Sopenharmony_ci sclk = &mt7621_fixed_clks[i]; 22662306a36Sopenharmony_ci clk_hw_unregister_fixed_rate(sclk->hw); 22762306a36Sopenharmony_ci } 22862306a36Sopenharmony_ci return ret; 22962306a36Sopenharmony_ci} 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_cistatic inline struct mt7621_clk *to_mt7621_clk(struct clk_hw *hw) 23262306a36Sopenharmony_ci{ 23362306a36Sopenharmony_ci return container_of(hw, struct mt7621_clk, hw); 23462306a36Sopenharmony_ci} 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_cistatic unsigned long mt7621_xtal_recalc_rate(struct clk_hw *hw, 23762306a36Sopenharmony_ci unsigned long parent_rate) 23862306a36Sopenharmony_ci{ 23962306a36Sopenharmony_ci struct mt7621_clk *clk = to_mt7621_clk(hw); 24062306a36Sopenharmony_ci struct regmap *sysc = clk->priv->sysc; 24162306a36Sopenharmony_ci u32 val; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG0, &val); 24462306a36Sopenharmony_ci val = FIELD_GET(XTAL_MODE_SEL_MASK, val); 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci if (val <= 2) 24762306a36Sopenharmony_ci return 20000000; 24862306a36Sopenharmony_ci if (val <= 5) 24962306a36Sopenharmony_ci return 40000000; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_ci return 25000000; 25262306a36Sopenharmony_ci} 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_cistatic unsigned long mt7621_cpu_recalc_rate(struct clk_hw *hw, 25562306a36Sopenharmony_ci unsigned long xtal_clk) 25662306a36Sopenharmony_ci{ 25762306a36Sopenharmony_ci static const u32 prediv_tbl[] = { 0, 1, 2, 2 }; 25862306a36Sopenharmony_ci struct mt7621_clk *clk = to_mt7621_clk(hw); 25962306a36Sopenharmony_ci struct regmap *sysc = clk->priv->sysc; 26062306a36Sopenharmony_ci struct regmap *memc = clk->priv->memc; 26162306a36Sopenharmony_ci u32 clkcfg, clk_sel, curclk, ffiv, ffrac; 26262306a36Sopenharmony_ci u32 pll, prediv, fbdiv; 26362306a36Sopenharmony_ci unsigned long cpu_clk; 26462306a36Sopenharmony_ci 26562306a36Sopenharmony_ci regmap_read(sysc, SYSC_REG_CLKCFG0, &clkcfg); 26662306a36Sopenharmony_ci clk_sel = FIELD_GET(CPU_CLK_SEL_MASK, clkcfg); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci regmap_read(sysc, SYSC_REG_CUR_CLK_STS, &curclk); 26962306a36Sopenharmony_ci ffiv = FIELD_GET(CUR_CPU_FDIV_MASK, curclk); 27062306a36Sopenharmony_ci ffrac = FIELD_GET(CUR_CPU_FFRAC_MASK, curclk); 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci switch (clk_sel) { 27362306a36Sopenharmony_ci case 0: 27462306a36Sopenharmony_ci cpu_clk = 500000000; 27562306a36Sopenharmony_ci break; 27662306a36Sopenharmony_ci case 1: 27762306a36Sopenharmony_ci regmap_read(memc, MEMC_REG_CPU_PLL, &pll); 27862306a36Sopenharmony_ci fbdiv = FIELD_GET(CPU_PLL_FBDIV_MASK, pll); 27962306a36Sopenharmony_ci prediv = FIELD_GET(CPU_PLL_PREDIV_MASK, pll); 28062306a36Sopenharmony_ci cpu_clk = ((fbdiv + 1) * xtal_clk) >> prediv_tbl[prediv]; 28162306a36Sopenharmony_ci break; 28262306a36Sopenharmony_ci default: 28362306a36Sopenharmony_ci cpu_clk = xtal_clk; 28462306a36Sopenharmony_ci } 28562306a36Sopenharmony_ci 28662306a36Sopenharmony_ci return cpu_clk / ffiv * ffrac; 28762306a36Sopenharmony_ci} 28862306a36Sopenharmony_ci 28962306a36Sopenharmony_cistatic unsigned long mt7621_bus_recalc_rate(struct clk_hw *hw, 29062306a36Sopenharmony_ci unsigned long parent_rate) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci return parent_rate / 4; 29362306a36Sopenharmony_ci} 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci#define CLK_BASE(_name, _parent, _recalc) { \ 29662306a36Sopenharmony_ci .init = &(struct clk_init_data) { \ 29762306a36Sopenharmony_ci .name = _name, \ 29862306a36Sopenharmony_ci .ops = &(const struct clk_ops) { \ 29962306a36Sopenharmony_ci .recalc_rate = _recalc, \ 30062306a36Sopenharmony_ci }, \ 30162306a36Sopenharmony_ci .parent_data = &(const struct clk_parent_data) { \ 30262306a36Sopenharmony_ci .name = _parent, \ 30362306a36Sopenharmony_ci .fw_name = _parent \ 30462306a36Sopenharmony_ci }, \ 30562306a36Sopenharmony_ci .num_parents = _parent ? 1 : 0 \ 30662306a36Sopenharmony_ci }, \ 30762306a36Sopenharmony_ci} 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_cistatic struct mt7621_clk mt7621_clks_base[] = { 31062306a36Sopenharmony_ci { CLK_BASE("xtal", NULL, mt7621_xtal_recalc_rate) }, 31162306a36Sopenharmony_ci { CLK_BASE("cpu", "xtal", mt7621_cpu_recalc_rate) }, 31262306a36Sopenharmony_ci { CLK_BASE("bus", "cpu", mt7621_bus_recalc_rate) }, 31362306a36Sopenharmony_ci}; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_cistatic struct clk_hw *mt7621_clk_early[MT7621_CLK_MAX]; 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_cistatic int mt7621_register_early_clocks(struct device_node *np, 31862306a36Sopenharmony_ci struct clk_hw_onecell_data *clk_data, 31962306a36Sopenharmony_ci struct mt7621_clk_priv *priv) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci struct clk_hw **hws = clk_data->hws; 32262306a36Sopenharmony_ci struct mt7621_clk *sclk; 32362306a36Sopenharmony_ci int ret, i, j; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mt7621_clks_base); i++) { 32662306a36Sopenharmony_ci sclk = &mt7621_clks_base[i]; 32762306a36Sopenharmony_ci sclk->priv = priv; 32862306a36Sopenharmony_ci ret = of_clk_hw_register(np, &sclk->hw); 32962306a36Sopenharmony_ci if (ret) { 33062306a36Sopenharmony_ci pr_err("Couldn't register top clock %i\n", i); 33162306a36Sopenharmony_ci goto err_clk_unreg; 33262306a36Sopenharmony_ci } 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci hws[i] = &sclk->hw; 33562306a36Sopenharmony_ci mt7621_clk_early[i] = &sclk->hw; 33662306a36Sopenharmony_ci } 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci for (j = i; j < MT7621_CLK_MAX; j++) 33962306a36Sopenharmony_ci mt7621_clk_early[j] = ERR_PTR(-EPROBE_DEFER); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci return 0; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_cierr_clk_unreg: 34462306a36Sopenharmony_ci while (--i >= 0) { 34562306a36Sopenharmony_ci sclk = &mt7621_clks_base[i]; 34662306a36Sopenharmony_ci clk_hw_unregister(&sclk->hw); 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci return ret; 34962306a36Sopenharmony_ci} 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_cistatic void __init mt7621_clk_init(struct device_node *node) 35262306a36Sopenharmony_ci{ 35362306a36Sopenharmony_ci struct mt7621_clk_priv *priv; 35462306a36Sopenharmony_ci struct clk_hw_onecell_data *clk_data; 35562306a36Sopenharmony_ci int ret, i, count; 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci priv = kzalloc(sizeof(*priv), GFP_KERNEL); 35862306a36Sopenharmony_ci if (!priv) 35962306a36Sopenharmony_ci return; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci priv->sysc = syscon_node_to_regmap(node); 36262306a36Sopenharmony_ci if (IS_ERR(priv->sysc)) { 36362306a36Sopenharmony_ci pr_err("Could not get sysc syscon regmap\n"); 36462306a36Sopenharmony_ci goto free_clk_priv; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ci priv->memc = syscon_regmap_lookup_by_phandle(node, "ralink,memctl"); 36862306a36Sopenharmony_ci if (IS_ERR(priv->memc)) { 36962306a36Sopenharmony_ci pr_err("Could not get memc syscon regmap\n"); 37062306a36Sopenharmony_ci goto free_clk_priv; 37162306a36Sopenharmony_ci } 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci count = ARRAY_SIZE(mt7621_clks_base) + 37462306a36Sopenharmony_ci ARRAY_SIZE(mt7621_fixed_clks) + ARRAY_SIZE(mt7621_gates); 37562306a36Sopenharmony_ci clk_data = kzalloc(struct_size(clk_data, hws, count), GFP_KERNEL); 37662306a36Sopenharmony_ci if (!clk_data) 37762306a36Sopenharmony_ci goto free_clk_priv; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci ret = mt7621_register_early_clocks(node, clk_data, priv); 38062306a36Sopenharmony_ci if (ret) { 38162306a36Sopenharmony_ci pr_err("Couldn't register top clocks\n"); 38262306a36Sopenharmony_ci goto free_clk_data; 38362306a36Sopenharmony_ci } 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci clk_data->num = count; 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_ci ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); 38862306a36Sopenharmony_ci if (ret) { 38962306a36Sopenharmony_ci pr_err("Couldn't add clk hw provider\n"); 39062306a36Sopenharmony_ci goto unreg_clk_top; 39162306a36Sopenharmony_ci } 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci return; 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ciunreg_clk_top: 39662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mt7621_clks_base); i++) { 39762306a36Sopenharmony_ci struct mt7621_clk *sclk = &mt7621_clks_base[i]; 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci clk_hw_unregister(&sclk->hw); 40062306a36Sopenharmony_ci } 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_cifree_clk_data: 40362306a36Sopenharmony_ci kfree(clk_data); 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cifree_clk_priv: 40662306a36Sopenharmony_ci kfree(priv); 40762306a36Sopenharmony_ci} 40862306a36Sopenharmony_ciCLK_OF_DECLARE_DRIVER(mt7621_clk, "mediatek,mt7621-sysc", mt7621_clk_init); 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_cistruct mt7621_rst { 41162306a36Sopenharmony_ci struct reset_controller_dev rcdev; 41262306a36Sopenharmony_ci struct regmap *sysc; 41362306a36Sopenharmony_ci}; 41462306a36Sopenharmony_ci 41562306a36Sopenharmony_cistatic struct mt7621_rst *to_mt7621_rst(struct reset_controller_dev *dev) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci return container_of(dev, struct mt7621_rst, rcdev); 41862306a36Sopenharmony_ci} 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cistatic int mt7621_assert_device(struct reset_controller_dev *rcdev, 42162306a36Sopenharmony_ci unsigned long id) 42262306a36Sopenharmony_ci{ 42362306a36Sopenharmony_ci struct mt7621_rst *data = to_mt7621_rst(rcdev); 42462306a36Sopenharmony_ci struct regmap *sysc = data->sysc; 42562306a36Sopenharmony_ci 42662306a36Sopenharmony_ci return regmap_update_bits(sysc, SYSC_REG_RESET_CTRL, BIT(id), BIT(id)); 42762306a36Sopenharmony_ci} 42862306a36Sopenharmony_ci 42962306a36Sopenharmony_cistatic int mt7621_deassert_device(struct reset_controller_dev *rcdev, 43062306a36Sopenharmony_ci unsigned long id) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci struct mt7621_rst *data = to_mt7621_rst(rcdev); 43362306a36Sopenharmony_ci struct regmap *sysc = data->sysc; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci return regmap_update_bits(sysc, SYSC_REG_RESET_CTRL, BIT(id), 0); 43662306a36Sopenharmony_ci} 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_cistatic int mt7621_reset_device(struct reset_controller_dev *rcdev, 43962306a36Sopenharmony_ci unsigned long id) 44062306a36Sopenharmony_ci{ 44162306a36Sopenharmony_ci int ret; 44262306a36Sopenharmony_ci 44362306a36Sopenharmony_ci ret = mt7621_assert_device(rcdev, id); 44462306a36Sopenharmony_ci if (ret < 0) 44562306a36Sopenharmony_ci return ret; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci return mt7621_deassert_device(rcdev, id); 44862306a36Sopenharmony_ci} 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_cistatic int mt7621_rst_xlate(struct reset_controller_dev *rcdev, 45162306a36Sopenharmony_ci const struct of_phandle_args *reset_spec) 45262306a36Sopenharmony_ci{ 45362306a36Sopenharmony_ci unsigned long id = reset_spec->args[0]; 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci if (id == MT7621_RST_SYS || id >= rcdev->nr_resets) 45662306a36Sopenharmony_ci return -EINVAL; 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_ci return id; 45962306a36Sopenharmony_ci} 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_cistatic const struct reset_control_ops reset_ops = { 46262306a36Sopenharmony_ci .reset = mt7621_reset_device, 46362306a36Sopenharmony_ci .assert = mt7621_assert_device, 46462306a36Sopenharmony_ci .deassert = mt7621_deassert_device 46562306a36Sopenharmony_ci}; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_cistatic int mt7621_reset_init(struct device *dev, struct regmap *sysc) 46862306a36Sopenharmony_ci{ 46962306a36Sopenharmony_ci struct mt7621_rst *rst_data; 47062306a36Sopenharmony_ci 47162306a36Sopenharmony_ci rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL); 47262306a36Sopenharmony_ci if (!rst_data) 47362306a36Sopenharmony_ci return -ENOMEM; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci rst_data->sysc = sysc; 47662306a36Sopenharmony_ci rst_data->rcdev.ops = &reset_ops; 47762306a36Sopenharmony_ci rst_data->rcdev.owner = THIS_MODULE; 47862306a36Sopenharmony_ci rst_data->rcdev.nr_resets = 32; 47962306a36Sopenharmony_ci rst_data->rcdev.of_reset_n_cells = 1; 48062306a36Sopenharmony_ci rst_data->rcdev.of_xlate = mt7621_rst_xlate; 48162306a36Sopenharmony_ci rst_data->rcdev.of_node = dev_of_node(dev); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci return devm_reset_controller_register(dev, &rst_data->rcdev); 48462306a36Sopenharmony_ci} 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_cistatic int mt7621_clk_probe(struct platform_device *pdev) 48762306a36Sopenharmony_ci{ 48862306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 48962306a36Sopenharmony_ci struct clk_hw_onecell_data *clk_data; 49062306a36Sopenharmony_ci struct device *dev = &pdev->dev; 49162306a36Sopenharmony_ci struct mt7621_clk_priv *priv; 49262306a36Sopenharmony_ci int ret, i, count; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 49562306a36Sopenharmony_ci if (!priv) 49662306a36Sopenharmony_ci return -ENOMEM; 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci priv->sysc = syscon_node_to_regmap(np); 49962306a36Sopenharmony_ci if (IS_ERR(priv->sysc)) { 50062306a36Sopenharmony_ci ret = PTR_ERR(priv->sysc); 50162306a36Sopenharmony_ci dev_err(dev, "Could not get sysc syscon regmap\n"); 50262306a36Sopenharmony_ci return ret; 50362306a36Sopenharmony_ci } 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci priv->memc = syscon_regmap_lookup_by_phandle(np, "ralink,memctl"); 50662306a36Sopenharmony_ci if (IS_ERR(priv->memc)) { 50762306a36Sopenharmony_ci ret = PTR_ERR(priv->memc); 50862306a36Sopenharmony_ci dev_err(dev, "Could not get memc syscon regmap\n"); 50962306a36Sopenharmony_ci return ret; 51062306a36Sopenharmony_ci } 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_ci ret = mt7621_reset_init(dev, priv->sysc); 51362306a36Sopenharmony_ci if (ret) { 51462306a36Sopenharmony_ci dev_err(dev, "Could not init reset controller\n"); 51562306a36Sopenharmony_ci return ret; 51662306a36Sopenharmony_ci } 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_ci count = ARRAY_SIZE(mt7621_clks_base) + 51962306a36Sopenharmony_ci ARRAY_SIZE(mt7621_fixed_clks) + ARRAY_SIZE(mt7621_gates); 52062306a36Sopenharmony_ci clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, count), 52162306a36Sopenharmony_ci GFP_KERNEL); 52262306a36Sopenharmony_ci if (!clk_data) 52362306a36Sopenharmony_ci return -ENOMEM; 52462306a36Sopenharmony_ci clk_data->num = count; 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mt7621_clks_base); i++) 52762306a36Sopenharmony_ci clk_data->hws[i] = mt7621_clk_early[i]; 52862306a36Sopenharmony_ci 52962306a36Sopenharmony_ci ret = mt7621_register_fixed_clocks(dev, clk_data); 53062306a36Sopenharmony_ci if (ret) { 53162306a36Sopenharmony_ci dev_err(dev, "Couldn't register fixed clocks\n"); 53262306a36Sopenharmony_ci return ret; 53362306a36Sopenharmony_ci } 53462306a36Sopenharmony_ci 53562306a36Sopenharmony_ci ret = mt7621_register_gates(dev, clk_data, priv); 53662306a36Sopenharmony_ci if (ret) { 53762306a36Sopenharmony_ci dev_err(dev, "Couldn't register fixed clock gates\n"); 53862306a36Sopenharmony_ci goto unreg_clk_fixed; 53962306a36Sopenharmony_ci } 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get, clk_data); 54262306a36Sopenharmony_ci if (ret) { 54362306a36Sopenharmony_ci dev_err(dev, "Couldn't add clk hw provider\n"); 54462306a36Sopenharmony_ci goto unreg_clk_gates; 54562306a36Sopenharmony_ci } 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci return 0; 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_ciunreg_clk_gates: 55062306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mt7621_gates); i++) { 55162306a36Sopenharmony_ci struct mt7621_gate *sclk = &mt7621_gates[i]; 55262306a36Sopenharmony_ci 55362306a36Sopenharmony_ci clk_hw_unregister(&sclk->hw); 55462306a36Sopenharmony_ci } 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ciunreg_clk_fixed: 55762306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mt7621_fixed_clks); i++) { 55862306a36Sopenharmony_ci struct mt7621_fixed_clk *sclk = &mt7621_fixed_clks[i]; 55962306a36Sopenharmony_ci 56062306a36Sopenharmony_ci clk_hw_unregister_fixed_rate(sclk->hw); 56162306a36Sopenharmony_ci } 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci return ret; 56462306a36Sopenharmony_ci} 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_cistatic const struct of_device_id mt7621_clk_of_match[] = { 56762306a36Sopenharmony_ci { .compatible = "mediatek,mt7621-sysc" }, 56862306a36Sopenharmony_ci {} 56962306a36Sopenharmony_ci}; 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_cistatic struct platform_driver mt7621_clk_driver = { 57262306a36Sopenharmony_ci .probe = mt7621_clk_probe, 57362306a36Sopenharmony_ci .driver = { 57462306a36Sopenharmony_ci .name = "mt7621-clk", 57562306a36Sopenharmony_ci .of_match_table = mt7621_clk_of_match, 57662306a36Sopenharmony_ci }, 57762306a36Sopenharmony_ci}; 57862306a36Sopenharmony_ci 57962306a36Sopenharmony_cistatic int __init mt7621_clk_reset_init(void) 58062306a36Sopenharmony_ci{ 58162306a36Sopenharmony_ci return platform_driver_register(&mt7621_clk_driver); 58262306a36Sopenharmony_ci} 58362306a36Sopenharmony_ciarch_initcall(mt7621_clk_reset_init); 584