162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * MTMIPS SoCs Clock Driver 462306a36Sopenharmony_ci * Author: Sergio Paracuellos <sergio.paracuellos@gmail.com> 562306a36Sopenharmony_ci */ 662306a36Sopenharmony_ci 762306a36Sopenharmony_ci#include <linux/bitops.h> 862306a36Sopenharmony_ci#include <linux/clk-provider.h> 962306a36Sopenharmony_ci#include <linux/mfd/syscon.h> 1062306a36Sopenharmony_ci#include <linux/platform_device.h> 1162306a36Sopenharmony_ci#include <linux/regmap.h> 1262306a36Sopenharmony_ci#include <linux/reset-controller.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci/* Configuration registers */ 1662306a36Sopenharmony_ci#define SYSC_REG_SYSTEM_CONFIG 0x10 1762306a36Sopenharmony_ci#define SYSC_REG_CLKCFG0 0x2c 1862306a36Sopenharmony_ci#define SYSC_REG_RESET_CTRL 0x34 1962306a36Sopenharmony_ci#define SYSC_REG_CPU_SYS_CLKCFG 0x3c 2062306a36Sopenharmony_ci#define SYSC_REG_CPLL_CONFIG0 0x54 2162306a36Sopenharmony_ci#define SYSC_REG_CPLL_CONFIG1 0x58 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* RT2880 SoC */ 2462306a36Sopenharmony_ci#define RT2880_CONFIG_CPUCLK_SHIFT 20 2562306a36Sopenharmony_ci#define RT2880_CONFIG_CPUCLK_MASK 0x3 2662306a36Sopenharmony_ci#define RT2880_CONFIG_CPUCLK_250 0x0 2762306a36Sopenharmony_ci#define RT2880_CONFIG_CPUCLK_266 0x1 2862306a36Sopenharmony_ci#define RT2880_CONFIG_CPUCLK_280 0x2 2962306a36Sopenharmony_ci#define RT2880_CONFIG_CPUCLK_300 0x3 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/* RT305X SoC */ 3262306a36Sopenharmony_ci#define RT305X_SYSCFG_CPUCLK_SHIFT 18 3362306a36Sopenharmony_ci#define RT305X_SYSCFG_CPUCLK_MASK 0x1 3462306a36Sopenharmony_ci#define RT305X_SYSCFG_CPUCLK_LOW 0x0 3562306a36Sopenharmony_ci#define RT305X_SYSCFG_CPUCLK_HIGH 0x1 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* RT3352 SoC */ 3862306a36Sopenharmony_ci#define RT3352_SYSCFG0_CPUCLK_SHIFT 8 3962306a36Sopenharmony_ci#define RT3352_SYSCFG0_CPUCLK_MASK 0x1 4062306a36Sopenharmony_ci#define RT3352_SYSCFG0_CPUCLK_LOW 0x0 4162306a36Sopenharmony_ci#define RT3352_SYSCFG0_CPUCLK_HIGH 0x1 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci/* RT3383 SoC */ 4462306a36Sopenharmony_ci#define RT3883_SYSCFG0_DRAM_TYPE_DDR2 BIT(17) 4562306a36Sopenharmony_ci#define RT3883_SYSCFG0_CPUCLK_SHIFT 8 4662306a36Sopenharmony_ci#define RT3883_SYSCFG0_CPUCLK_MASK 0x3 4762306a36Sopenharmony_ci#define RT3883_SYSCFG0_CPUCLK_250 0x0 4862306a36Sopenharmony_ci#define RT3883_SYSCFG0_CPUCLK_384 0x1 4962306a36Sopenharmony_ci#define RT3883_SYSCFG0_CPUCLK_480 0x2 5062306a36Sopenharmony_ci#define RT3883_SYSCFG0_CPUCLK_500 0x3 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci/* RT5350 SoC */ 5362306a36Sopenharmony_ci#define RT5350_CLKCFG0_XTAL_SEL BIT(20) 5462306a36Sopenharmony_ci#define RT5350_SYSCFG0_CPUCLK_SHIFT 8 5562306a36Sopenharmony_ci#define RT5350_SYSCFG0_CPUCLK_MASK 0x3 5662306a36Sopenharmony_ci#define RT5350_SYSCFG0_CPUCLK_360 0x0 5762306a36Sopenharmony_ci#define RT5350_SYSCFG0_CPUCLK_320 0x2 5862306a36Sopenharmony_ci#define RT5350_SYSCFG0_CPUCLK_300 0x3 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci/* MT7620 and MT76x8 SoCs */ 6162306a36Sopenharmony_ci#define MT7620_XTAL_FREQ_SEL BIT(6) 6262306a36Sopenharmony_ci#define CPLL_CFG0_SW_CFG BIT(31) 6362306a36Sopenharmony_ci#define CPLL_CFG0_PLL_MULT_RATIO_SHIFT 16 6462306a36Sopenharmony_ci#define CPLL_CFG0_PLL_MULT_RATIO_MASK 0x7 6562306a36Sopenharmony_ci#define CPLL_CFG0_LC_CURFCK BIT(15) 6662306a36Sopenharmony_ci#define CPLL_CFG0_BYPASS_REF_CLK BIT(14) 6762306a36Sopenharmony_ci#define CPLL_CFG0_PLL_DIV_RATIO_SHIFT 10 6862306a36Sopenharmony_ci#define CPLL_CFG0_PLL_DIV_RATIO_MASK 0x3 6962306a36Sopenharmony_ci#define CPLL_CFG1_CPU_AUX1 BIT(25) 7062306a36Sopenharmony_ci#define CPLL_CFG1_CPU_AUX0 BIT(24) 7162306a36Sopenharmony_ci#define CLKCFG0_PERI_CLK_SEL BIT(4) 7262306a36Sopenharmony_ci#define CPU_SYS_CLKCFG_OCP_RATIO_SHIFT 16 7362306a36Sopenharmony_ci#define CPU_SYS_CLKCFG_OCP_RATIO_MASK 0xf 7462306a36Sopenharmony_ci#define CPU_SYS_CLKCFG_OCP_RATIO_1 0 /* 1:1 (Reserved) */ 7562306a36Sopenharmony_ci#define CPU_SYS_CLKCFG_OCP_RATIO_1_5 1 /* 1:1.5 (Reserved) */ 7662306a36Sopenharmony_ci#define CPU_SYS_CLKCFG_OCP_RATIO_2 2 /* 1:2 */ 7762306a36Sopenharmony_ci#define CPU_SYS_CLKCFG_OCP_RATIO_2_5 3 /* 1:2.5 (Reserved) */ 7862306a36Sopenharmony_ci#define CPU_SYS_CLKCFG_OCP_RATIO_3 4 /* 1:3 */ 7962306a36Sopenharmony_ci#define CPU_SYS_CLKCFG_OCP_RATIO_3_5 5 /* 1:3.5 (Reserved) */ 8062306a36Sopenharmony_ci#define CPU_SYS_CLKCFG_OCP_RATIO_4 6 /* 1:4 */ 8162306a36Sopenharmony_ci#define CPU_SYS_CLKCFG_OCP_RATIO_5 7 /* 1:5 */ 8262306a36Sopenharmony_ci#define CPU_SYS_CLKCFG_OCP_RATIO_10 8 /* 1:10 */ 8362306a36Sopenharmony_ci#define CPU_SYS_CLKCFG_CPU_FDIV_SHIFT 8 8462306a36Sopenharmony_ci#define CPU_SYS_CLKCFG_CPU_FDIV_MASK 0x1f 8562306a36Sopenharmony_ci#define CPU_SYS_CLKCFG_CPU_FFRAC_SHIFT 0 8662306a36Sopenharmony_ci#define CPU_SYS_CLKCFG_CPU_FFRAC_MASK 0x1f 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci/* clock scaling */ 8962306a36Sopenharmony_ci#define CLKCFG_FDIV_MASK 0x1f00 9062306a36Sopenharmony_ci#define CLKCFG_FDIV_USB_VAL 0x0300 9162306a36Sopenharmony_ci#define CLKCFG_FFRAC_MASK 0x001f 9262306a36Sopenharmony_ci#define CLKCFG_FFRAC_USB_VAL 0x0003 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_cistruct mtmips_clk; 9562306a36Sopenharmony_cistruct mtmips_clk_fixed; 9662306a36Sopenharmony_cistruct mtmips_clk_factor; 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_cistruct mtmips_clk_data { 9962306a36Sopenharmony_ci struct mtmips_clk *clk_base; 10062306a36Sopenharmony_ci size_t num_clk_base; 10162306a36Sopenharmony_ci struct mtmips_clk_fixed *clk_fixed; 10262306a36Sopenharmony_ci size_t num_clk_fixed; 10362306a36Sopenharmony_ci struct mtmips_clk_factor *clk_factor; 10462306a36Sopenharmony_ci size_t num_clk_factor; 10562306a36Sopenharmony_ci struct mtmips_clk *clk_periph; 10662306a36Sopenharmony_ci size_t num_clk_periph; 10762306a36Sopenharmony_ci}; 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_cistruct mtmips_clk_priv { 11062306a36Sopenharmony_ci struct regmap *sysc; 11162306a36Sopenharmony_ci const struct mtmips_clk_data *data; 11262306a36Sopenharmony_ci}; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_cistruct mtmips_clk { 11562306a36Sopenharmony_ci struct clk_hw hw; 11662306a36Sopenharmony_ci struct mtmips_clk_priv *priv; 11762306a36Sopenharmony_ci}; 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistruct mtmips_clk_fixed { 12062306a36Sopenharmony_ci const char *name; 12162306a36Sopenharmony_ci const char *parent; 12262306a36Sopenharmony_ci unsigned long rate; 12362306a36Sopenharmony_ci struct clk_hw *hw; 12462306a36Sopenharmony_ci}; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_cistruct mtmips_clk_factor { 12762306a36Sopenharmony_ci const char *name; 12862306a36Sopenharmony_ci const char *parent; 12962306a36Sopenharmony_ci int mult; 13062306a36Sopenharmony_ci int div; 13162306a36Sopenharmony_ci unsigned long flags; 13262306a36Sopenharmony_ci struct clk_hw *hw; 13362306a36Sopenharmony_ci}; 13462306a36Sopenharmony_ci 13562306a36Sopenharmony_cistatic unsigned long mtmips_pherip_clk_rate(struct clk_hw *hw, 13662306a36Sopenharmony_ci unsigned long parent_rate) 13762306a36Sopenharmony_ci{ 13862306a36Sopenharmony_ci return parent_rate; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic const struct clk_ops mtmips_periph_clk_ops = { 14262306a36Sopenharmony_ci .recalc_rate = mtmips_pherip_clk_rate, 14362306a36Sopenharmony_ci}; 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci#define CLK_PERIPH(_name, _parent) { \ 14662306a36Sopenharmony_ci .init = &(const struct clk_init_data) { \ 14762306a36Sopenharmony_ci .name = _name, \ 14862306a36Sopenharmony_ci .ops = &mtmips_periph_clk_ops, \ 14962306a36Sopenharmony_ci .parent_data = &(const struct clk_parent_data) {\ 15062306a36Sopenharmony_ci .name = _parent, \ 15162306a36Sopenharmony_ci .fw_name = _parent \ 15262306a36Sopenharmony_ci }, \ 15362306a36Sopenharmony_ci .num_parents = 1, \ 15462306a36Sopenharmony_ci /* \ 15562306a36Sopenharmony_ci * There are drivers for these SoCs that are \ 15662306a36Sopenharmony_ci * older than clock driver and are not prepared \ 15762306a36Sopenharmony_ci * for the clock. We don't want the kernel to \ 15862306a36Sopenharmony_ci * disable anything so we add CLK_IS_CRITICAL \ 15962306a36Sopenharmony_ci * flag here. \ 16062306a36Sopenharmony_ci */ \ 16162306a36Sopenharmony_ci .flags = CLK_SET_RATE_PARENT | CLK_IS_CRITICAL \ 16262306a36Sopenharmony_ci }, \ 16362306a36Sopenharmony_ci} 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic struct mtmips_clk rt2880_pherip_clks[] = { 16662306a36Sopenharmony_ci { CLK_PERIPH("300100.timer", "bus") }, 16762306a36Sopenharmony_ci { CLK_PERIPH("300120.watchdog", "bus") }, 16862306a36Sopenharmony_ci { CLK_PERIPH("300500.uart", "bus") }, 16962306a36Sopenharmony_ci { CLK_PERIPH("300900.i2c", "bus") }, 17062306a36Sopenharmony_ci { CLK_PERIPH("300c00.uartlite", "bus") }, 17162306a36Sopenharmony_ci { CLK_PERIPH("400000.ethernet", "bus") }, 17262306a36Sopenharmony_ci { CLK_PERIPH("480000.wmac", "xtal") } 17362306a36Sopenharmony_ci}; 17462306a36Sopenharmony_ci 17562306a36Sopenharmony_cistatic struct mtmips_clk rt305x_pherip_clks[] = { 17662306a36Sopenharmony_ci { CLK_PERIPH("10000100.timer", "bus") }, 17762306a36Sopenharmony_ci { CLK_PERIPH("10000120.watchdog", "bus") }, 17862306a36Sopenharmony_ci { CLK_PERIPH("10000500.uart", "bus") }, 17962306a36Sopenharmony_ci { CLK_PERIPH("10000900.i2c", "bus") }, 18062306a36Sopenharmony_ci { CLK_PERIPH("10000a00.i2s", "bus") }, 18162306a36Sopenharmony_ci { CLK_PERIPH("10000b00.spi", "bus") }, 18262306a36Sopenharmony_ci { CLK_PERIPH("10000b40.spi", "bus") }, 18362306a36Sopenharmony_ci { CLK_PERIPH("10000c00.uartlite", "bus") }, 18462306a36Sopenharmony_ci { CLK_PERIPH("10100000.ethernet", "bus") }, 18562306a36Sopenharmony_ci { CLK_PERIPH("10180000.wmac", "xtal") } 18662306a36Sopenharmony_ci}; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_cistatic struct mtmips_clk rt5350_pherip_clks[] = { 18962306a36Sopenharmony_ci { CLK_PERIPH("10000100.timer", "bus") }, 19062306a36Sopenharmony_ci { CLK_PERIPH("10000120.watchdog", "bus") }, 19162306a36Sopenharmony_ci { CLK_PERIPH("10000500.uart", "periph") }, 19262306a36Sopenharmony_ci { CLK_PERIPH("10000900.i2c", "periph") }, 19362306a36Sopenharmony_ci { CLK_PERIPH("10000a00.i2s", "periph") }, 19462306a36Sopenharmony_ci { CLK_PERIPH("10000b00.spi", "bus") }, 19562306a36Sopenharmony_ci { CLK_PERIPH("10000b40.spi", "bus") }, 19662306a36Sopenharmony_ci { CLK_PERIPH("10000c00.uartlite", "periph") }, 19762306a36Sopenharmony_ci { CLK_PERIPH("10100000.ethernet", "bus") }, 19862306a36Sopenharmony_ci { CLK_PERIPH("10180000.wmac", "xtal") } 19962306a36Sopenharmony_ci}; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_cistatic struct mtmips_clk mt7620_pherip_clks[] = { 20262306a36Sopenharmony_ci { CLK_PERIPH("10000100.timer", "periph") }, 20362306a36Sopenharmony_ci { CLK_PERIPH("10000120.watchdog", "periph") }, 20462306a36Sopenharmony_ci { CLK_PERIPH("10000500.uart", "periph") }, 20562306a36Sopenharmony_ci { CLK_PERIPH("10000900.i2c", "periph") }, 20662306a36Sopenharmony_ci { CLK_PERIPH("10000a00.i2s", "periph") }, 20762306a36Sopenharmony_ci { CLK_PERIPH("10000b00.spi", "bus") }, 20862306a36Sopenharmony_ci { CLK_PERIPH("10000b40.spi", "bus") }, 20962306a36Sopenharmony_ci { CLK_PERIPH("10000c00.uartlite", "periph") }, 21062306a36Sopenharmony_ci { CLK_PERIPH("10180000.wmac", "xtal") } 21162306a36Sopenharmony_ci}; 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_cistatic struct mtmips_clk mt76x8_pherip_clks[] = { 21462306a36Sopenharmony_ci { CLK_PERIPH("10000100.timer", "periph") }, 21562306a36Sopenharmony_ci { CLK_PERIPH("10000120.watchdog", "periph") }, 21662306a36Sopenharmony_ci { CLK_PERIPH("10000900.i2c", "periph") }, 21762306a36Sopenharmony_ci { CLK_PERIPH("10000a00.i2s", "pcmi2s") }, 21862306a36Sopenharmony_ci { CLK_PERIPH("10000b00.spi", "bus") }, 21962306a36Sopenharmony_ci { CLK_PERIPH("10000b40.spi", "bus") }, 22062306a36Sopenharmony_ci { CLK_PERIPH("10000c00.uart0", "periph") }, 22162306a36Sopenharmony_ci { CLK_PERIPH("10000d00.uart1", "periph") }, 22262306a36Sopenharmony_ci { CLK_PERIPH("10000e00.uart2", "periph") }, 22362306a36Sopenharmony_ci { CLK_PERIPH("10300000.wmac", "xtal") } 22462306a36Sopenharmony_ci}; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_cistatic int mtmips_register_pherip_clocks(struct device_node *np, 22762306a36Sopenharmony_ci struct clk_hw_onecell_data *clk_data, 22862306a36Sopenharmony_ci struct mtmips_clk_priv *priv) 22962306a36Sopenharmony_ci{ 23062306a36Sopenharmony_ci struct clk_hw **hws = clk_data->hws; 23162306a36Sopenharmony_ci struct mtmips_clk *sclk; 23262306a36Sopenharmony_ci size_t idx_start = priv->data->num_clk_base + priv->data->num_clk_fixed + 23362306a36Sopenharmony_ci priv->data->num_clk_factor; 23462306a36Sopenharmony_ci int ret, i; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci for (i = 0; i < priv->data->num_clk_periph; i++) { 23762306a36Sopenharmony_ci int idx = idx_start + i; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci sclk = &priv->data->clk_periph[i]; 24062306a36Sopenharmony_ci ret = of_clk_hw_register(np, &sclk->hw); 24162306a36Sopenharmony_ci if (ret) { 24262306a36Sopenharmony_ci pr_err("Couldn't register peripheral clock %d\n", idx); 24362306a36Sopenharmony_ci goto err_clk_unreg; 24462306a36Sopenharmony_ci } 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci hws[idx] = &sclk->hw; 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci 24962306a36Sopenharmony_ci return 0; 25062306a36Sopenharmony_ci 25162306a36Sopenharmony_cierr_clk_unreg: 25262306a36Sopenharmony_ci while (--i >= 0) { 25362306a36Sopenharmony_ci sclk = &priv->data->clk_periph[i]; 25462306a36Sopenharmony_ci clk_hw_unregister(&sclk->hw); 25562306a36Sopenharmony_ci } 25662306a36Sopenharmony_ci return ret; 25762306a36Sopenharmony_ci} 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci#define CLK_FIXED(_name, _parent, _rate) \ 26062306a36Sopenharmony_ci { \ 26162306a36Sopenharmony_ci .name = _name, \ 26262306a36Sopenharmony_ci .parent = _parent, \ 26362306a36Sopenharmony_ci .rate = _rate \ 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_cistatic struct mtmips_clk_fixed rt305x_fixed_clocks[] = { 26762306a36Sopenharmony_ci CLK_FIXED("xtal", NULL, 40000000) 26862306a36Sopenharmony_ci}; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic struct mtmips_clk_fixed rt3352_fixed_clocks[] = { 27162306a36Sopenharmony_ci CLK_FIXED("periph", "xtal", 40000000) 27262306a36Sopenharmony_ci}; 27362306a36Sopenharmony_ci 27462306a36Sopenharmony_cistatic struct mtmips_clk_fixed mt76x8_fixed_clocks[] = { 27562306a36Sopenharmony_ci CLK_FIXED("pcmi2s", "xtal", 480000000), 27662306a36Sopenharmony_ci CLK_FIXED("periph", "xtal", 40000000) 27762306a36Sopenharmony_ci}; 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_cistatic int mtmips_register_fixed_clocks(struct clk_hw_onecell_data *clk_data, 28062306a36Sopenharmony_ci struct mtmips_clk_priv *priv) 28162306a36Sopenharmony_ci{ 28262306a36Sopenharmony_ci struct clk_hw **hws = clk_data->hws; 28362306a36Sopenharmony_ci struct mtmips_clk_fixed *sclk; 28462306a36Sopenharmony_ci size_t idx_start = priv->data->num_clk_base; 28562306a36Sopenharmony_ci int ret, i; 28662306a36Sopenharmony_ci 28762306a36Sopenharmony_ci for (i = 0; i < priv->data->num_clk_fixed; i++) { 28862306a36Sopenharmony_ci int idx = idx_start + i; 28962306a36Sopenharmony_ci 29062306a36Sopenharmony_ci sclk = &priv->data->clk_fixed[i]; 29162306a36Sopenharmony_ci sclk->hw = clk_hw_register_fixed_rate(NULL, sclk->name, 29262306a36Sopenharmony_ci sclk->parent, 0, 29362306a36Sopenharmony_ci sclk->rate); 29462306a36Sopenharmony_ci if (IS_ERR(sclk->hw)) { 29562306a36Sopenharmony_ci ret = PTR_ERR(sclk->hw); 29662306a36Sopenharmony_ci pr_err("Couldn't register fixed clock %d\n", idx); 29762306a36Sopenharmony_ci goto err_clk_unreg; 29862306a36Sopenharmony_ci } 29962306a36Sopenharmony_ci 30062306a36Sopenharmony_ci hws[idx] = sclk->hw; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci return 0; 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_cierr_clk_unreg: 30662306a36Sopenharmony_ci while (--i >= 0) { 30762306a36Sopenharmony_ci sclk = &priv->data->clk_fixed[i]; 30862306a36Sopenharmony_ci clk_hw_unregister_fixed_rate(sclk->hw); 30962306a36Sopenharmony_ci } 31062306a36Sopenharmony_ci return ret; 31162306a36Sopenharmony_ci} 31262306a36Sopenharmony_ci 31362306a36Sopenharmony_ci#define CLK_FACTOR(_name, _parent, _mult, _div) \ 31462306a36Sopenharmony_ci { \ 31562306a36Sopenharmony_ci .name = _name, \ 31662306a36Sopenharmony_ci .parent = _parent, \ 31762306a36Sopenharmony_ci .mult = _mult, \ 31862306a36Sopenharmony_ci .div = _div, \ 31962306a36Sopenharmony_ci .flags = CLK_SET_RATE_PARENT \ 32062306a36Sopenharmony_ci } 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_cistatic struct mtmips_clk_factor rt2880_factor_clocks[] = { 32362306a36Sopenharmony_ci CLK_FACTOR("bus", "cpu", 1, 2) 32462306a36Sopenharmony_ci}; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_cistatic struct mtmips_clk_factor rt305x_factor_clocks[] = { 32762306a36Sopenharmony_ci CLK_FACTOR("bus", "cpu", 1, 3) 32862306a36Sopenharmony_ci}; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_cistatic int mtmips_register_factor_clocks(struct clk_hw_onecell_data *clk_data, 33162306a36Sopenharmony_ci struct mtmips_clk_priv *priv) 33262306a36Sopenharmony_ci{ 33362306a36Sopenharmony_ci struct clk_hw **hws = clk_data->hws; 33462306a36Sopenharmony_ci struct mtmips_clk_factor *sclk; 33562306a36Sopenharmony_ci size_t idx_start = priv->data->num_clk_base + priv->data->num_clk_fixed; 33662306a36Sopenharmony_ci int ret, i; 33762306a36Sopenharmony_ci 33862306a36Sopenharmony_ci for (i = 0; i < priv->data->num_clk_factor; i++) { 33962306a36Sopenharmony_ci int idx = idx_start + i; 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci sclk = &priv->data->clk_factor[i]; 34262306a36Sopenharmony_ci sclk->hw = clk_hw_register_fixed_factor(NULL, sclk->name, 34362306a36Sopenharmony_ci sclk->parent, sclk->flags, 34462306a36Sopenharmony_ci sclk->mult, sclk->div); 34562306a36Sopenharmony_ci if (IS_ERR(sclk->hw)) { 34662306a36Sopenharmony_ci ret = PTR_ERR(sclk->hw); 34762306a36Sopenharmony_ci pr_err("Couldn't register factor clock %d\n", idx); 34862306a36Sopenharmony_ci goto err_clk_unreg; 34962306a36Sopenharmony_ci } 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci hws[idx] = sclk->hw; 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci return 0; 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_cierr_clk_unreg: 35762306a36Sopenharmony_ci while (--i >= 0) { 35862306a36Sopenharmony_ci sclk = &priv->data->clk_factor[i]; 35962306a36Sopenharmony_ci clk_hw_unregister_fixed_factor(sclk->hw); 36062306a36Sopenharmony_ci } 36162306a36Sopenharmony_ci return ret; 36262306a36Sopenharmony_ci} 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_cistatic inline struct mtmips_clk *to_mtmips_clk(struct clk_hw *hw) 36562306a36Sopenharmony_ci{ 36662306a36Sopenharmony_ci return container_of(hw, struct mtmips_clk, hw); 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic unsigned long rt5350_xtal_recalc_rate(struct clk_hw *hw, 37062306a36Sopenharmony_ci unsigned long parent_rate) 37162306a36Sopenharmony_ci{ 37262306a36Sopenharmony_ci struct mtmips_clk *clk = to_mtmips_clk(hw); 37362306a36Sopenharmony_ci struct regmap *sysc = clk->priv->sysc; 37462306a36Sopenharmony_ci u32 val; 37562306a36Sopenharmony_ci 37662306a36Sopenharmony_ci regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &val); 37762306a36Sopenharmony_ci if (!(val & RT5350_CLKCFG0_XTAL_SEL)) 37862306a36Sopenharmony_ci return 20000000; 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci return 40000000; 38162306a36Sopenharmony_ci} 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_cistatic unsigned long rt5350_cpu_recalc_rate(struct clk_hw *hw, 38462306a36Sopenharmony_ci unsigned long xtal_clk) 38562306a36Sopenharmony_ci{ 38662306a36Sopenharmony_ci struct mtmips_clk *clk = to_mtmips_clk(hw); 38762306a36Sopenharmony_ci struct regmap *sysc = clk->priv->sysc; 38862306a36Sopenharmony_ci u32 t; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); 39162306a36Sopenharmony_ci t = (t >> RT5350_SYSCFG0_CPUCLK_SHIFT) & RT5350_SYSCFG0_CPUCLK_MASK; 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci switch (t) { 39462306a36Sopenharmony_ci case RT5350_SYSCFG0_CPUCLK_360: 39562306a36Sopenharmony_ci return 360000000; 39662306a36Sopenharmony_ci case RT5350_SYSCFG0_CPUCLK_320: 39762306a36Sopenharmony_ci return 320000000; 39862306a36Sopenharmony_ci case RT5350_SYSCFG0_CPUCLK_300: 39962306a36Sopenharmony_ci return 300000000; 40062306a36Sopenharmony_ci default: 40162306a36Sopenharmony_ci BUG(); 40262306a36Sopenharmony_ci } 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_cistatic unsigned long rt5350_bus_recalc_rate(struct clk_hw *hw, 40662306a36Sopenharmony_ci unsigned long parent_rate) 40762306a36Sopenharmony_ci{ 40862306a36Sopenharmony_ci if (parent_rate == 320000000) 40962306a36Sopenharmony_ci return parent_rate / 4; 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci return parent_rate / 3; 41262306a36Sopenharmony_ci} 41362306a36Sopenharmony_ci 41462306a36Sopenharmony_cistatic unsigned long rt3352_cpu_recalc_rate(struct clk_hw *hw, 41562306a36Sopenharmony_ci unsigned long xtal_clk) 41662306a36Sopenharmony_ci{ 41762306a36Sopenharmony_ci struct mtmips_clk *clk = to_mtmips_clk(hw); 41862306a36Sopenharmony_ci struct regmap *sysc = clk->priv->sysc; 41962306a36Sopenharmony_ci u32 t; 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); 42262306a36Sopenharmony_ci t = (t >> RT3352_SYSCFG0_CPUCLK_SHIFT) & RT3352_SYSCFG0_CPUCLK_MASK; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci switch (t) { 42562306a36Sopenharmony_ci case RT3352_SYSCFG0_CPUCLK_LOW: 42662306a36Sopenharmony_ci return 384000000; 42762306a36Sopenharmony_ci case RT3352_SYSCFG0_CPUCLK_HIGH: 42862306a36Sopenharmony_ci return 400000000; 42962306a36Sopenharmony_ci default: 43062306a36Sopenharmony_ci BUG(); 43162306a36Sopenharmony_ci } 43262306a36Sopenharmony_ci} 43362306a36Sopenharmony_ci 43462306a36Sopenharmony_cistatic unsigned long rt305x_cpu_recalc_rate(struct clk_hw *hw, 43562306a36Sopenharmony_ci unsigned long xtal_clk) 43662306a36Sopenharmony_ci{ 43762306a36Sopenharmony_ci struct mtmips_clk *clk = to_mtmips_clk(hw); 43862306a36Sopenharmony_ci struct regmap *sysc = clk->priv->sysc; 43962306a36Sopenharmony_ci u32 t; 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); 44262306a36Sopenharmony_ci t = (t >> RT305X_SYSCFG_CPUCLK_SHIFT) & RT305X_SYSCFG_CPUCLK_MASK; 44362306a36Sopenharmony_ci 44462306a36Sopenharmony_ci switch (t) { 44562306a36Sopenharmony_ci case RT305X_SYSCFG_CPUCLK_LOW: 44662306a36Sopenharmony_ci return 320000000; 44762306a36Sopenharmony_ci case RT305X_SYSCFG_CPUCLK_HIGH: 44862306a36Sopenharmony_ci return 384000000; 44962306a36Sopenharmony_ci default: 45062306a36Sopenharmony_ci BUG(); 45162306a36Sopenharmony_ci } 45262306a36Sopenharmony_ci} 45362306a36Sopenharmony_ci 45462306a36Sopenharmony_cistatic unsigned long rt3883_cpu_recalc_rate(struct clk_hw *hw, 45562306a36Sopenharmony_ci unsigned long xtal_clk) 45662306a36Sopenharmony_ci{ 45762306a36Sopenharmony_ci struct mtmips_clk *clk = to_mtmips_clk(hw); 45862306a36Sopenharmony_ci struct regmap *sysc = clk->priv->sysc; 45962306a36Sopenharmony_ci u32 t; 46062306a36Sopenharmony_ci 46162306a36Sopenharmony_ci regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); 46262306a36Sopenharmony_ci t = (t >> RT3883_SYSCFG0_CPUCLK_SHIFT) & RT3883_SYSCFG0_CPUCLK_MASK; 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci switch (t) { 46562306a36Sopenharmony_ci case RT3883_SYSCFG0_CPUCLK_250: 46662306a36Sopenharmony_ci return 250000000; 46762306a36Sopenharmony_ci case RT3883_SYSCFG0_CPUCLK_384: 46862306a36Sopenharmony_ci return 384000000; 46962306a36Sopenharmony_ci case RT3883_SYSCFG0_CPUCLK_480: 47062306a36Sopenharmony_ci return 480000000; 47162306a36Sopenharmony_ci case RT3883_SYSCFG0_CPUCLK_500: 47262306a36Sopenharmony_ci return 500000000; 47362306a36Sopenharmony_ci default: 47462306a36Sopenharmony_ci BUG(); 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci} 47762306a36Sopenharmony_ci 47862306a36Sopenharmony_cistatic unsigned long rt3883_bus_recalc_rate(struct clk_hw *hw, 47962306a36Sopenharmony_ci unsigned long parent_rate) 48062306a36Sopenharmony_ci{ 48162306a36Sopenharmony_ci struct mtmips_clk *clk = to_mtmips_clk(hw); 48262306a36Sopenharmony_ci struct regmap *sysc = clk->priv->sysc; 48362306a36Sopenharmony_ci u32 ddr2; 48462306a36Sopenharmony_ci u32 t; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); 48762306a36Sopenharmony_ci ddr2 = t & RT3883_SYSCFG0_DRAM_TYPE_DDR2; 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci switch (parent_rate) { 49062306a36Sopenharmony_ci case 250000000: 49162306a36Sopenharmony_ci return (ddr2) ? 125000000 : 83000000; 49262306a36Sopenharmony_ci case 384000000: 49362306a36Sopenharmony_ci return (ddr2) ? 128000000 : 96000000; 49462306a36Sopenharmony_ci case 480000000: 49562306a36Sopenharmony_ci return (ddr2) ? 160000000 : 120000000; 49662306a36Sopenharmony_ci case 500000000: 49762306a36Sopenharmony_ci return (ddr2) ? 166000000 : 125000000; 49862306a36Sopenharmony_ci default: 49962306a36Sopenharmony_ci WARN_ON_ONCE(parent_rate == 0); 50062306a36Sopenharmony_ci return parent_rate / 4; 50162306a36Sopenharmony_ci } 50262306a36Sopenharmony_ci} 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_cistatic unsigned long rt2880_cpu_recalc_rate(struct clk_hw *hw, 50562306a36Sopenharmony_ci unsigned long xtal_clk) 50662306a36Sopenharmony_ci{ 50762306a36Sopenharmony_ci struct mtmips_clk *clk = to_mtmips_clk(hw); 50862306a36Sopenharmony_ci struct regmap *sysc = clk->priv->sysc; 50962306a36Sopenharmony_ci u32 t; 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); 51262306a36Sopenharmony_ci t = (t >> RT2880_CONFIG_CPUCLK_SHIFT) & RT2880_CONFIG_CPUCLK_MASK; 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci switch (t) { 51562306a36Sopenharmony_ci case RT2880_CONFIG_CPUCLK_250: 51662306a36Sopenharmony_ci return 250000000; 51762306a36Sopenharmony_ci case RT2880_CONFIG_CPUCLK_266: 51862306a36Sopenharmony_ci return 266000000; 51962306a36Sopenharmony_ci case RT2880_CONFIG_CPUCLK_280: 52062306a36Sopenharmony_ci return 280000000; 52162306a36Sopenharmony_ci case RT2880_CONFIG_CPUCLK_300: 52262306a36Sopenharmony_ci return 300000000; 52362306a36Sopenharmony_ci default: 52462306a36Sopenharmony_ci BUG(); 52562306a36Sopenharmony_ci } 52662306a36Sopenharmony_ci} 52762306a36Sopenharmony_ci 52862306a36Sopenharmony_cistatic u32 mt7620_calc_rate(u32 ref_rate, u32 mul, u32 div) 52962306a36Sopenharmony_ci{ 53062306a36Sopenharmony_ci u64 t; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci t = ref_rate; 53362306a36Sopenharmony_ci t *= mul; 53462306a36Sopenharmony_ci t = div_u64(t, div); 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_ci return t; 53762306a36Sopenharmony_ci} 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_cistatic unsigned long mt7620_pll_recalc_rate(struct clk_hw *hw, 54062306a36Sopenharmony_ci unsigned long parent_rate) 54162306a36Sopenharmony_ci{ 54262306a36Sopenharmony_ci static const u32 clk_divider[] = { 2, 3, 4, 8 }; 54362306a36Sopenharmony_ci struct mtmips_clk *clk = to_mtmips_clk(hw); 54462306a36Sopenharmony_ci struct regmap *sysc = clk->priv->sysc; 54562306a36Sopenharmony_ci unsigned long cpu_pll; 54662306a36Sopenharmony_ci u32 t; 54762306a36Sopenharmony_ci u32 mul; 54862306a36Sopenharmony_ci u32 div; 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_ci regmap_read(sysc, SYSC_REG_CPLL_CONFIG0, &t); 55162306a36Sopenharmony_ci if (t & CPLL_CFG0_BYPASS_REF_CLK) { 55262306a36Sopenharmony_ci cpu_pll = parent_rate; 55362306a36Sopenharmony_ci } else if ((t & CPLL_CFG0_SW_CFG) == 0) { 55462306a36Sopenharmony_ci cpu_pll = 600000000; 55562306a36Sopenharmony_ci } else { 55662306a36Sopenharmony_ci mul = (t >> CPLL_CFG0_PLL_MULT_RATIO_SHIFT) & 55762306a36Sopenharmony_ci CPLL_CFG0_PLL_MULT_RATIO_MASK; 55862306a36Sopenharmony_ci mul += 24; 55962306a36Sopenharmony_ci if (t & CPLL_CFG0_LC_CURFCK) 56062306a36Sopenharmony_ci mul *= 2; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci div = (t >> CPLL_CFG0_PLL_DIV_RATIO_SHIFT) & 56362306a36Sopenharmony_ci CPLL_CFG0_PLL_DIV_RATIO_MASK; 56462306a36Sopenharmony_ci 56562306a36Sopenharmony_ci WARN_ON_ONCE(div >= ARRAY_SIZE(clk_divider)); 56662306a36Sopenharmony_ci 56762306a36Sopenharmony_ci cpu_pll = mt7620_calc_rate(parent_rate, mul, clk_divider[div]); 56862306a36Sopenharmony_ci } 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci regmap_read(sysc, SYSC_REG_CPLL_CONFIG1, &t); 57162306a36Sopenharmony_ci if (t & CPLL_CFG1_CPU_AUX1) 57262306a36Sopenharmony_ci return parent_rate; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci if (t & CPLL_CFG1_CPU_AUX0) 57562306a36Sopenharmony_ci return 480000000; 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci return cpu_pll; 57862306a36Sopenharmony_ci} 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_cistatic unsigned long mt7620_cpu_recalc_rate(struct clk_hw *hw, 58162306a36Sopenharmony_ci unsigned long parent_rate) 58262306a36Sopenharmony_ci{ 58362306a36Sopenharmony_ci struct mtmips_clk *clk = to_mtmips_clk(hw); 58462306a36Sopenharmony_ci struct regmap *sysc = clk->priv->sysc; 58562306a36Sopenharmony_ci u32 t; 58662306a36Sopenharmony_ci u32 mul; 58762306a36Sopenharmony_ci u32 div; 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci regmap_read(sysc, SYSC_REG_CPU_SYS_CLKCFG, &t); 59062306a36Sopenharmony_ci mul = t & CPU_SYS_CLKCFG_CPU_FFRAC_MASK; 59162306a36Sopenharmony_ci div = (t >> CPU_SYS_CLKCFG_CPU_FDIV_SHIFT) & 59262306a36Sopenharmony_ci CPU_SYS_CLKCFG_CPU_FDIV_MASK; 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci return mt7620_calc_rate(parent_rate, mul, div); 59562306a36Sopenharmony_ci} 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_cistatic unsigned long mt7620_bus_recalc_rate(struct clk_hw *hw, 59862306a36Sopenharmony_ci unsigned long parent_rate) 59962306a36Sopenharmony_ci{ 60062306a36Sopenharmony_ci static const u32 ocp_dividers[16] = { 60162306a36Sopenharmony_ci [CPU_SYS_CLKCFG_OCP_RATIO_2] = 2, 60262306a36Sopenharmony_ci [CPU_SYS_CLKCFG_OCP_RATIO_3] = 3, 60362306a36Sopenharmony_ci [CPU_SYS_CLKCFG_OCP_RATIO_4] = 4, 60462306a36Sopenharmony_ci [CPU_SYS_CLKCFG_OCP_RATIO_5] = 5, 60562306a36Sopenharmony_ci [CPU_SYS_CLKCFG_OCP_RATIO_10] = 10, 60662306a36Sopenharmony_ci }; 60762306a36Sopenharmony_ci struct mtmips_clk *clk = to_mtmips_clk(hw); 60862306a36Sopenharmony_ci struct regmap *sysc = clk->priv->sysc; 60962306a36Sopenharmony_ci u32 t; 61062306a36Sopenharmony_ci u32 ocp_ratio; 61162306a36Sopenharmony_ci u32 div; 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci regmap_read(sysc, SYSC_REG_CPU_SYS_CLKCFG, &t); 61462306a36Sopenharmony_ci ocp_ratio = (t >> CPU_SYS_CLKCFG_OCP_RATIO_SHIFT) & 61562306a36Sopenharmony_ci CPU_SYS_CLKCFG_OCP_RATIO_MASK; 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_ci if (WARN_ON_ONCE(ocp_ratio >= ARRAY_SIZE(ocp_dividers))) 61862306a36Sopenharmony_ci return parent_rate; 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci div = ocp_dividers[ocp_ratio]; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci if (WARN(!div, "invalid divider for OCP ratio %u", ocp_ratio)) 62362306a36Sopenharmony_ci return parent_rate; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci return parent_rate / div; 62662306a36Sopenharmony_ci} 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_cistatic unsigned long mt7620_periph_recalc_rate(struct clk_hw *hw, 62962306a36Sopenharmony_ci unsigned long parent_rate) 63062306a36Sopenharmony_ci{ 63162306a36Sopenharmony_ci struct mtmips_clk *clk = to_mtmips_clk(hw); 63262306a36Sopenharmony_ci struct regmap *sysc = clk->priv->sysc; 63362306a36Sopenharmony_ci u32 t; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci regmap_read(sysc, SYSC_REG_CLKCFG0, &t); 63662306a36Sopenharmony_ci if (t & CLKCFG0_PERI_CLK_SEL) 63762306a36Sopenharmony_ci return parent_rate; 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_ci return 40000000; 64062306a36Sopenharmony_ci} 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_cistatic unsigned long mt76x8_xtal_recalc_rate(struct clk_hw *hw, 64362306a36Sopenharmony_ci unsigned long parent_rate) 64462306a36Sopenharmony_ci{ 64562306a36Sopenharmony_ci struct mtmips_clk *clk = to_mtmips_clk(hw); 64662306a36Sopenharmony_ci struct regmap *sysc = clk->priv->sysc; 64762306a36Sopenharmony_ci u32 t; 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci regmap_read(sysc, SYSC_REG_SYSTEM_CONFIG, &t); 65062306a36Sopenharmony_ci if (t & MT7620_XTAL_FREQ_SEL) 65162306a36Sopenharmony_ci return 40000000; 65262306a36Sopenharmony_ci 65362306a36Sopenharmony_ci return 20000000; 65462306a36Sopenharmony_ci} 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_cistatic unsigned long mt76x8_cpu_recalc_rate(struct clk_hw *hw, 65762306a36Sopenharmony_ci unsigned long xtal_clk) 65862306a36Sopenharmony_ci{ 65962306a36Sopenharmony_ci if (xtal_clk == 40000000) 66062306a36Sopenharmony_ci return 580000000; 66162306a36Sopenharmony_ci 66262306a36Sopenharmony_ci return 575000000; 66362306a36Sopenharmony_ci} 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci#define CLK_BASE(_name, _parent, _recalc) { \ 66662306a36Sopenharmony_ci .init = &(const struct clk_init_data) { \ 66762306a36Sopenharmony_ci .name = _name, \ 66862306a36Sopenharmony_ci .ops = &(const struct clk_ops) { \ 66962306a36Sopenharmony_ci .recalc_rate = _recalc, \ 67062306a36Sopenharmony_ci }, \ 67162306a36Sopenharmony_ci .parent_data = &(const struct clk_parent_data) { \ 67262306a36Sopenharmony_ci .name = _parent, \ 67362306a36Sopenharmony_ci .fw_name = _parent \ 67462306a36Sopenharmony_ci }, \ 67562306a36Sopenharmony_ci .num_parents = _parent ? 1 : 0 \ 67662306a36Sopenharmony_ci }, \ 67762306a36Sopenharmony_ci} 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_cistatic struct mtmips_clk rt2880_clks_base[] = { 68062306a36Sopenharmony_ci { CLK_BASE("cpu", "xtal", rt2880_cpu_recalc_rate) } 68162306a36Sopenharmony_ci}; 68262306a36Sopenharmony_ci 68362306a36Sopenharmony_cistatic struct mtmips_clk rt305x_clks_base[] = { 68462306a36Sopenharmony_ci { CLK_BASE("cpu", "xtal", rt305x_cpu_recalc_rate) } 68562306a36Sopenharmony_ci}; 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_cistatic struct mtmips_clk rt3352_clks_base[] = { 68862306a36Sopenharmony_ci { CLK_BASE("xtal", NULL, rt5350_xtal_recalc_rate) }, 68962306a36Sopenharmony_ci { CLK_BASE("cpu", "xtal", rt3352_cpu_recalc_rate) } 69062306a36Sopenharmony_ci}; 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_cistatic struct mtmips_clk rt3883_clks_base[] = { 69362306a36Sopenharmony_ci { CLK_BASE("cpu", "xtal", rt3883_cpu_recalc_rate) }, 69462306a36Sopenharmony_ci { CLK_BASE("bus", "cpu", rt3883_bus_recalc_rate) } 69562306a36Sopenharmony_ci}; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_cistatic struct mtmips_clk rt5350_clks_base[] = { 69862306a36Sopenharmony_ci { CLK_BASE("xtal", NULL, rt5350_xtal_recalc_rate) }, 69962306a36Sopenharmony_ci { CLK_BASE("cpu", "xtal", rt5350_cpu_recalc_rate) }, 70062306a36Sopenharmony_ci { CLK_BASE("bus", "cpu", rt5350_bus_recalc_rate) } 70162306a36Sopenharmony_ci}; 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_cistatic struct mtmips_clk mt7620_clks_base[] = { 70462306a36Sopenharmony_ci { CLK_BASE("xtal", NULL, mt76x8_xtal_recalc_rate) }, 70562306a36Sopenharmony_ci { CLK_BASE("pll", "xtal", mt7620_pll_recalc_rate) }, 70662306a36Sopenharmony_ci { CLK_BASE("cpu", "pll", mt7620_cpu_recalc_rate) }, 70762306a36Sopenharmony_ci { CLK_BASE("periph", "xtal", mt7620_periph_recalc_rate) }, 70862306a36Sopenharmony_ci { CLK_BASE("bus", "cpu", mt7620_bus_recalc_rate) } 70962306a36Sopenharmony_ci}; 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_cistatic struct mtmips_clk mt76x8_clks_base[] = { 71262306a36Sopenharmony_ci { CLK_BASE("xtal", NULL, mt76x8_xtal_recalc_rate) }, 71362306a36Sopenharmony_ci { CLK_BASE("cpu", "xtal", mt76x8_cpu_recalc_rate) } 71462306a36Sopenharmony_ci}; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_cistatic int mtmips_register_clocks(struct device_node *np, 71762306a36Sopenharmony_ci struct clk_hw_onecell_data *clk_data, 71862306a36Sopenharmony_ci struct mtmips_clk_priv *priv) 71962306a36Sopenharmony_ci{ 72062306a36Sopenharmony_ci struct clk_hw **hws = clk_data->hws; 72162306a36Sopenharmony_ci struct mtmips_clk *sclk; 72262306a36Sopenharmony_ci int ret, i; 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_ci for (i = 0; i < priv->data->num_clk_base; i++) { 72562306a36Sopenharmony_ci sclk = &priv->data->clk_base[i]; 72662306a36Sopenharmony_ci sclk->priv = priv; 72762306a36Sopenharmony_ci ret = of_clk_hw_register(np, &sclk->hw); 72862306a36Sopenharmony_ci if (ret) { 72962306a36Sopenharmony_ci pr_err("Couldn't register top clock %i\n", i); 73062306a36Sopenharmony_ci goto err_clk_unreg; 73162306a36Sopenharmony_ci } 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci hws[i] = &sclk->hw; 73462306a36Sopenharmony_ci } 73562306a36Sopenharmony_ci 73662306a36Sopenharmony_ci return 0; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_cierr_clk_unreg: 73962306a36Sopenharmony_ci while (--i >= 0) { 74062306a36Sopenharmony_ci sclk = &priv->data->clk_base[i]; 74162306a36Sopenharmony_ci clk_hw_unregister(&sclk->hw); 74262306a36Sopenharmony_ci } 74362306a36Sopenharmony_ci return ret; 74462306a36Sopenharmony_ci} 74562306a36Sopenharmony_ci 74662306a36Sopenharmony_cistatic const struct mtmips_clk_data rt2880_clk_data = { 74762306a36Sopenharmony_ci .clk_base = rt2880_clks_base, 74862306a36Sopenharmony_ci .num_clk_base = ARRAY_SIZE(rt2880_clks_base), 74962306a36Sopenharmony_ci .clk_fixed = rt305x_fixed_clocks, 75062306a36Sopenharmony_ci .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks), 75162306a36Sopenharmony_ci .clk_factor = rt2880_factor_clocks, 75262306a36Sopenharmony_ci .num_clk_factor = ARRAY_SIZE(rt2880_factor_clocks), 75362306a36Sopenharmony_ci .clk_periph = rt2880_pherip_clks, 75462306a36Sopenharmony_ci .num_clk_periph = ARRAY_SIZE(rt2880_pherip_clks), 75562306a36Sopenharmony_ci}; 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_cistatic const struct mtmips_clk_data rt305x_clk_data = { 75862306a36Sopenharmony_ci .clk_base = rt305x_clks_base, 75962306a36Sopenharmony_ci .num_clk_base = ARRAY_SIZE(rt305x_clks_base), 76062306a36Sopenharmony_ci .clk_fixed = rt305x_fixed_clocks, 76162306a36Sopenharmony_ci .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks), 76262306a36Sopenharmony_ci .clk_factor = rt305x_factor_clocks, 76362306a36Sopenharmony_ci .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks), 76462306a36Sopenharmony_ci .clk_periph = rt305x_pherip_clks, 76562306a36Sopenharmony_ci .num_clk_periph = ARRAY_SIZE(rt305x_pherip_clks), 76662306a36Sopenharmony_ci}; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_cistatic const struct mtmips_clk_data rt3352_clk_data = { 76962306a36Sopenharmony_ci .clk_base = rt3352_clks_base, 77062306a36Sopenharmony_ci .num_clk_base = ARRAY_SIZE(rt3352_clks_base), 77162306a36Sopenharmony_ci .clk_fixed = rt3352_fixed_clocks, 77262306a36Sopenharmony_ci .num_clk_fixed = ARRAY_SIZE(rt3352_fixed_clocks), 77362306a36Sopenharmony_ci .clk_factor = rt305x_factor_clocks, 77462306a36Sopenharmony_ci .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks), 77562306a36Sopenharmony_ci .clk_periph = rt5350_pherip_clks, 77662306a36Sopenharmony_ci .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks), 77762306a36Sopenharmony_ci}; 77862306a36Sopenharmony_ci 77962306a36Sopenharmony_cistatic const struct mtmips_clk_data rt3883_clk_data = { 78062306a36Sopenharmony_ci .clk_base = rt3883_clks_base, 78162306a36Sopenharmony_ci .num_clk_base = ARRAY_SIZE(rt3883_clks_base), 78262306a36Sopenharmony_ci .clk_fixed = rt305x_fixed_clocks, 78362306a36Sopenharmony_ci .num_clk_fixed = ARRAY_SIZE(rt305x_fixed_clocks), 78462306a36Sopenharmony_ci .clk_factor = NULL, 78562306a36Sopenharmony_ci .num_clk_factor = 0, 78662306a36Sopenharmony_ci .clk_periph = rt5350_pherip_clks, 78762306a36Sopenharmony_ci .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks), 78862306a36Sopenharmony_ci}; 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_cistatic const struct mtmips_clk_data rt5350_clk_data = { 79162306a36Sopenharmony_ci .clk_base = rt5350_clks_base, 79262306a36Sopenharmony_ci .num_clk_base = ARRAY_SIZE(rt5350_clks_base), 79362306a36Sopenharmony_ci .clk_fixed = rt3352_fixed_clocks, 79462306a36Sopenharmony_ci .num_clk_fixed = ARRAY_SIZE(rt3352_fixed_clocks), 79562306a36Sopenharmony_ci .clk_factor = NULL, 79662306a36Sopenharmony_ci .num_clk_factor = 0, 79762306a36Sopenharmony_ci .clk_periph = rt5350_pherip_clks, 79862306a36Sopenharmony_ci .num_clk_periph = ARRAY_SIZE(rt5350_pherip_clks), 79962306a36Sopenharmony_ci}; 80062306a36Sopenharmony_ci 80162306a36Sopenharmony_cistatic const struct mtmips_clk_data mt7620_clk_data = { 80262306a36Sopenharmony_ci .clk_base = mt7620_clks_base, 80362306a36Sopenharmony_ci .num_clk_base = ARRAY_SIZE(mt7620_clks_base), 80462306a36Sopenharmony_ci .clk_fixed = NULL, 80562306a36Sopenharmony_ci .num_clk_fixed = 0, 80662306a36Sopenharmony_ci .clk_factor = NULL, 80762306a36Sopenharmony_ci .num_clk_factor = 0, 80862306a36Sopenharmony_ci .clk_periph = mt7620_pherip_clks, 80962306a36Sopenharmony_ci .num_clk_periph = ARRAY_SIZE(mt7620_pherip_clks), 81062306a36Sopenharmony_ci}; 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_cistatic const struct mtmips_clk_data mt76x8_clk_data = { 81362306a36Sopenharmony_ci .clk_base = mt76x8_clks_base, 81462306a36Sopenharmony_ci .num_clk_base = ARRAY_SIZE(mt76x8_clks_base), 81562306a36Sopenharmony_ci .clk_fixed = mt76x8_fixed_clocks, 81662306a36Sopenharmony_ci .num_clk_fixed = ARRAY_SIZE(mt76x8_fixed_clocks), 81762306a36Sopenharmony_ci .clk_factor = rt305x_factor_clocks, 81862306a36Sopenharmony_ci .num_clk_factor = ARRAY_SIZE(rt305x_factor_clocks), 81962306a36Sopenharmony_ci .clk_periph = mt76x8_pherip_clks, 82062306a36Sopenharmony_ci .num_clk_periph = ARRAY_SIZE(mt76x8_pherip_clks), 82162306a36Sopenharmony_ci}; 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_cistatic const struct of_device_id mtmips_of_match[] = { 82462306a36Sopenharmony_ci { 82562306a36Sopenharmony_ci .compatible = "ralink,rt2880-reset", 82662306a36Sopenharmony_ci .data = NULL, 82762306a36Sopenharmony_ci }, 82862306a36Sopenharmony_ci { 82962306a36Sopenharmony_ci .compatible = "ralink,rt2880-sysc", 83062306a36Sopenharmony_ci .data = &rt2880_clk_data, 83162306a36Sopenharmony_ci }, 83262306a36Sopenharmony_ci { 83362306a36Sopenharmony_ci .compatible = "ralink,rt3050-sysc", 83462306a36Sopenharmony_ci .data = &rt305x_clk_data, 83562306a36Sopenharmony_ci }, 83662306a36Sopenharmony_ci { 83762306a36Sopenharmony_ci .compatible = "ralink,rt3052-sysc", 83862306a36Sopenharmony_ci .data = &rt305x_clk_data, 83962306a36Sopenharmony_ci }, 84062306a36Sopenharmony_ci { 84162306a36Sopenharmony_ci .compatible = "ralink,rt3352-sysc", 84262306a36Sopenharmony_ci .data = &rt3352_clk_data, 84362306a36Sopenharmony_ci }, 84462306a36Sopenharmony_ci { 84562306a36Sopenharmony_ci .compatible = "ralink,rt3883-sysc", 84662306a36Sopenharmony_ci .data = &rt3883_clk_data, 84762306a36Sopenharmony_ci }, 84862306a36Sopenharmony_ci { 84962306a36Sopenharmony_ci .compatible = "ralink,rt5350-sysc", 85062306a36Sopenharmony_ci .data = &rt5350_clk_data, 85162306a36Sopenharmony_ci }, 85262306a36Sopenharmony_ci { 85362306a36Sopenharmony_ci .compatible = "ralink,mt7620-sysc", 85462306a36Sopenharmony_ci .data = &mt7620_clk_data, 85562306a36Sopenharmony_ci }, 85662306a36Sopenharmony_ci { 85762306a36Sopenharmony_ci .compatible = "ralink,mt7628-sysc", 85862306a36Sopenharmony_ci .data = &mt76x8_clk_data, 85962306a36Sopenharmony_ci }, 86062306a36Sopenharmony_ci { 86162306a36Sopenharmony_ci .compatible = "ralink,mt7688-sysc", 86262306a36Sopenharmony_ci .data = &mt76x8_clk_data, 86362306a36Sopenharmony_ci }, 86462306a36Sopenharmony_ci {} 86562306a36Sopenharmony_ci}; 86662306a36Sopenharmony_ci 86762306a36Sopenharmony_cistatic void __init mtmips_clk_regs_init(struct device_node *node, 86862306a36Sopenharmony_ci struct mtmips_clk_priv *priv) 86962306a36Sopenharmony_ci{ 87062306a36Sopenharmony_ci u32 t; 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci if (!of_device_is_compatible(node, "ralink,mt7620-sysc")) 87362306a36Sopenharmony_ci return; 87462306a36Sopenharmony_ci 87562306a36Sopenharmony_ci /* 87662306a36Sopenharmony_ci * When the CPU goes into sleep mode, the BUS 87762306a36Sopenharmony_ci * clock will be too low for USB to function properly. 87862306a36Sopenharmony_ci * Adjust the busses fractional divider to fix this 87962306a36Sopenharmony_ci */ 88062306a36Sopenharmony_ci regmap_read(priv->sysc, SYSC_REG_CPU_SYS_CLKCFG, &t); 88162306a36Sopenharmony_ci t &= ~(CLKCFG_FDIV_MASK | CLKCFG_FFRAC_MASK); 88262306a36Sopenharmony_ci t |= CLKCFG_FDIV_USB_VAL | CLKCFG_FFRAC_USB_VAL; 88362306a36Sopenharmony_ci regmap_write(priv->sysc, SYSC_REG_CPU_SYS_CLKCFG, t); 88462306a36Sopenharmony_ci} 88562306a36Sopenharmony_ci 88662306a36Sopenharmony_cistatic void __init mtmips_clk_init(struct device_node *node) 88762306a36Sopenharmony_ci{ 88862306a36Sopenharmony_ci const struct of_device_id *match; 88962306a36Sopenharmony_ci const struct mtmips_clk_data *data; 89062306a36Sopenharmony_ci struct mtmips_clk_priv *priv; 89162306a36Sopenharmony_ci struct clk_hw_onecell_data *clk_data; 89262306a36Sopenharmony_ci int ret, i, count; 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci priv = kzalloc(sizeof(*priv), GFP_KERNEL); 89562306a36Sopenharmony_ci if (!priv) 89662306a36Sopenharmony_ci return; 89762306a36Sopenharmony_ci 89862306a36Sopenharmony_ci priv->sysc = syscon_node_to_regmap(node); 89962306a36Sopenharmony_ci if (IS_ERR(priv->sysc)) { 90062306a36Sopenharmony_ci pr_err("Could not get sysc syscon regmap\n"); 90162306a36Sopenharmony_ci goto free_clk_priv; 90262306a36Sopenharmony_ci } 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci mtmips_clk_regs_init(node, priv); 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci match = of_match_node(mtmips_of_match, node); 90762306a36Sopenharmony_ci if (WARN_ON(!match)) 90862306a36Sopenharmony_ci return; 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci data = match->data; 91162306a36Sopenharmony_ci priv->data = data; 91262306a36Sopenharmony_ci count = priv->data->num_clk_base + priv->data->num_clk_fixed + 91362306a36Sopenharmony_ci priv->data->num_clk_factor + priv->data->num_clk_periph; 91462306a36Sopenharmony_ci clk_data = kzalloc(struct_size(clk_data, hws, count), GFP_KERNEL); 91562306a36Sopenharmony_ci if (!clk_data) 91662306a36Sopenharmony_ci goto free_clk_priv; 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci ret = mtmips_register_clocks(node, clk_data, priv); 91962306a36Sopenharmony_ci if (ret) { 92062306a36Sopenharmony_ci pr_err("Couldn't register top clocks\n"); 92162306a36Sopenharmony_ci goto free_clk_data; 92262306a36Sopenharmony_ci } 92362306a36Sopenharmony_ci 92462306a36Sopenharmony_ci ret = mtmips_register_fixed_clocks(clk_data, priv); 92562306a36Sopenharmony_ci if (ret) { 92662306a36Sopenharmony_ci pr_err("Couldn't register fixed clocks\n"); 92762306a36Sopenharmony_ci goto unreg_clk_top; 92862306a36Sopenharmony_ci } 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_ci ret = mtmips_register_factor_clocks(clk_data, priv); 93162306a36Sopenharmony_ci if (ret) { 93262306a36Sopenharmony_ci pr_err("Couldn't register factor clocks\n"); 93362306a36Sopenharmony_ci goto unreg_clk_fixed; 93462306a36Sopenharmony_ci } 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci ret = mtmips_register_pherip_clocks(node, clk_data, priv); 93762306a36Sopenharmony_ci if (ret) { 93862306a36Sopenharmony_ci pr_err("Couldn't register peripheral clocks\n"); 93962306a36Sopenharmony_ci goto unreg_clk_factor; 94062306a36Sopenharmony_ci } 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_ci clk_data->num = count; 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci ret = of_clk_add_hw_provider(node, of_clk_hw_onecell_get, clk_data); 94562306a36Sopenharmony_ci if (ret) { 94662306a36Sopenharmony_ci pr_err("Couldn't add clk hw provider\n"); 94762306a36Sopenharmony_ci goto unreg_clk_periph; 94862306a36Sopenharmony_ci } 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci return; 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ciunreg_clk_periph: 95362306a36Sopenharmony_ci for (i = 0; i < priv->data->num_clk_periph; i++) { 95462306a36Sopenharmony_ci struct mtmips_clk *sclk = &priv->data->clk_periph[i]; 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci clk_hw_unregister(&sclk->hw); 95762306a36Sopenharmony_ci } 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ciunreg_clk_factor: 96062306a36Sopenharmony_ci for (i = 0; i < priv->data->num_clk_factor; i++) { 96162306a36Sopenharmony_ci struct mtmips_clk_factor *sclk = &priv->data->clk_factor[i]; 96262306a36Sopenharmony_ci 96362306a36Sopenharmony_ci clk_hw_unregister_fixed_factor(sclk->hw); 96462306a36Sopenharmony_ci } 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ciunreg_clk_fixed: 96762306a36Sopenharmony_ci for (i = 0; i < priv->data->num_clk_fixed; i++) { 96862306a36Sopenharmony_ci struct mtmips_clk_fixed *sclk = &priv->data->clk_fixed[i]; 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci clk_hw_unregister_fixed_rate(sclk->hw); 97162306a36Sopenharmony_ci } 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ciunreg_clk_top: 97462306a36Sopenharmony_ci for (i = 0; i < priv->data->num_clk_base; i++) { 97562306a36Sopenharmony_ci struct mtmips_clk *sclk = &priv->data->clk_base[i]; 97662306a36Sopenharmony_ci 97762306a36Sopenharmony_ci clk_hw_unregister(&sclk->hw); 97862306a36Sopenharmony_ci } 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_cifree_clk_data: 98162306a36Sopenharmony_ci kfree(clk_data); 98262306a36Sopenharmony_ci 98362306a36Sopenharmony_cifree_clk_priv: 98462306a36Sopenharmony_ci kfree(priv); 98562306a36Sopenharmony_ci} 98662306a36Sopenharmony_ciCLK_OF_DECLARE_DRIVER(rt2880_clk, "ralink,rt2880-sysc", mtmips_clk_init); 98762306a36Sopenharmony_ciCLK_OF_DECLARE_DRIVER(rt3050_clk, "ralink,rt3050-sysc", mtmips_clk_init); 98862306a36Sopenharmony_ciCLK_OF_DECLARE_DRIVER(rt3052_clk, "ralink,rt3052-sysc", mtmips_clk_init); 98962306a36Sopenharmony_ciCLK_OF_DECLARE_DRIVER(rt3352_clk, "ralink,rt3352-sysc", mtmips_clk_init); 99062306a36Sopenharmony_ciCLK_OF_DECLARE_DRIVER(rt3883_clk, "ralink,rt3883-sysc", mtmips_clk_init); 99162306a36Sopenharmony_ciCLK_OF_DECLARE_DRIVER(rt5350_clk, "ralink,rt5350-sysc", mtmips_clk_init); 99262306a36Sopenharmony_ciCLK_OF_DECLARE_DRIVER(mt7620_clk, "ralink,mt7620-sysc", mtmips_clk_init); 99362306a36Sopenharmony_ciCLK_OF_DECLARE_DRIVER(mt7628_clk, "ralink,mt7628-sysc", mtmips_clk_init); 99462306a36Sopenharmony_ciCLK_OF_DECLARE_DRIVER(mt7688_clk, "ralink,mt7688-sysc", mtmips_clk_init); 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_cistruct mtmips_rst { 99762306a36Sopenharmony_ci struct reset_controller_dev rcdev; 99862306a36Sopenharmony_ci struct regmap *sysc; 99962306a36Sopenharmony_ci}; 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_cistatic struct mtmips_rst *to_mtmips_rst(struct reset_controller_dev *dev) 100262306a36Sopenharmony_ci{ 100362306a36Sopenharmony_ci return container_of(dev, struct mtmips_rst, rcdev); 100462306a36Sopenharmony_ci} 100562306a36Sopenharmony_ci 100662306a36Sopenharmony_cistatic int mtmips_assert_device(struct reset_controller_dev *rcdev, 100762306a36Sopenharmony_ci unsigned long id) 100862306a36Sopenharmony_ci{ 100962306a36Sopenharmony_ci struct mtmips_rst *data = to_mtmips_rst(rcdev); 101062306a36Sopenharmony_ci struct regmap *sysc = data->sysc; 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci return regmap_update_bits(sysc, SYSC_REG_RESET_CTRL, BIT(id), BIT(id)); 101362306a36Sopenharmony_ci} 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_cistatic int mtmips_deassert_device(struct reset_controller_dev *rcdev, 101662306a36Sopenharmony_ci unsigned long id) 101762306a36Sopenharmony_ci{ 101862306a36Sopenharmony_ci struct mtmips_rst *data = to_mtmips_rst(rcdev); 101962306a36Sopenharmony_ci struct regmap *sysc = data->sysc; 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci return regmap_update_bits(sysc, SYSC_REG_RESET_CTRL, BIT(id), 0); 102262306a36Sopenharmony_ci} 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_cistatic int mtmips_reset_device(struct reset_controller_dev *rcdev, 102562306a36Sopenharmony_ci unsigned long id) 102662306a36Sopenharmony_ci{ 102762306a36Sopenharmony_ci int ret; 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci ret = mtmips_assert_device(rcdev, id); 103062306a36Sopenharmony_ci if (ret < 0) 103162306a36Sopenharmony_ci return ret; 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci return mtmips_deassert_device(rcdev, id); 103462306a36Sopenharmony_ci} 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_cistatic int mtmips_rst_xlate(struct reset_controller_dev *rcdev, 103762306a36Sopenharmony_ci const struct of_phandle_args *reset_spec) 103862306a36Sopenharmony_ci{ 103962306a36Sopenharmony_ci unsigned long id = reset_spec->args[0]; 104062306a36Sopenharmony_ci 104162306a36Sopenharmony_ci if (id == 0 || id >= rcdev->nr_resets) 104262306a36Sopenharmony_ci return -EINVAL; 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_ci return id; 104562306a36Sopenharmony_ci} 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_cistatic const struct reset_control_ops reset_ops = { 104862306a36Sopenharmony_ci .reset = mtmips_reset_device, 104962306a36Sopenharmony_ci .assert = mtmips_assert_device, 105062306a36Sopenharmony_ci .deassert = mtmips_deassert_device 105162306a36Sopenharmony_ci}; 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_cistatic int mtmips_reset_init(struct device *dev, struct regmap *sysc) 105462306a36Sopenharmony_ci{ 105562306a36Sopenharmony_ci struct mtmips_rst *rst_data; 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci rst_data = devm_kzalloc(dev, sizeof(*rst_data), GFP_KERNEL); 105862306a36Sopenharmony_ci if (!rst_data) 105962306a36Sopenharmony_ci return -ENOMEM; 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci rst_data->sysc = sysc; 106262306a36Sopenharmony_ci rst_data->rcdev.ops = &reset_ops; 106362306a36Sopenharmony_ci rst_data->rcdev.owner = THIS_MODULE; 106462306a36Sopenharmony_ci rst_data->rcdev.nr_resets = 32; 106562306a36Sopenharmony_ci rst_data->rcdev.of_reset_n_cells = 1; 106662306a36Sopenharmony_ci rst_data->rcdev.of_xlate = mtmips_rst_xlate; 106762306a36Sopenharmony_ci rst_data->rcdev.of_node = dev_of_node(dev); 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci return devm_reset_controller_register(dev, &rst_data->rcdev); 107062306a36Sopenharmony_ci} 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_cistatic int mtmips_clk_probe(struct platform_device *pdev) 107362306a36Sopenharmony_ci{ 107462306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 107562306a36Sopenharmony_ci struct device *dev = &pdev->dev; 107662306a36Sopenharmony_ci struct mtmips_clk_priv *priv; 107762306a36Sopenharmony_ci int ret; 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_ci priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); 108062306a36Sopenharmony_ci if (!priv) 108162306a36Sopenharmony_ci return -ENOMEM; 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci priv->sysc = syscon_node_to_regmap(np); 108462306a36Sopenharmony_ci if (IS_ERR(priv->sysc)) 108562306a36Sopenharmony_ci return dev_err_probe(dev, PTR_ERR(priv->sysc), 108662306a36Sopenharmony_ci "Could not get sysc syscon regmap\n"); 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci ret = mtmips_reset_init(dev, priv->sysc); 108962306a36Sopenharmony_ci if (ret) 109062306a36Sopenharmony_ci return dev_err_probe(dev, ret, "Could not init reset controller\n"); 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci return 0; 109362306a36Sopenharmony_ci} 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_cistatic struct platform_driver mtmips_clk_driver = { 109662306a36Sopenharmony_ci .probe = mtmips_clk_probe, 109762306a36Sopenharmony_ci .driver = { 109862306a36Sopenharmony_ci .name = "mtmips-clk", 109962306a36Sopenharmony_ci .of_match_table = mtmips_of_match, 110062306a36Sopenharmony_ci }, 110162306a36Sopenharmony_ci}; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_cistatic int __init mtmips_clk_reset_init(void) 110462306a36Sopenharmony_ci{ 110562306a36Sopenharmony_ci return platform_driver_register(&mtmips_clk_driver); 110662306a36Sopenharmony_ci} 110762306a36Sopenharmony_ciarch_initcall(mtmips_clk_reset_init); 1108