162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright 2013 Emilio López 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Emilio López <emilio@elopez.com.ar> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/clk.h> 962306a36Sopenharmony_ci#include <linux/clk-provider.h> 1062306a36Sopenharmony_ci#include <linux/io.h> 1162306a36Sopenharmony_ci#include <linux/of_address.h> 1262306a36Sopenharmony_ci#include <linux/platform_device.h> 1362306a36Sopenharmony_ci#include <linux/slab.h> 1462306a36Sopenharmony_ci 1562306a36Sopenharmony_ci#include "clk-factors.h" 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* 1862306a36Sopenharmony_ci * sun4i_a10_get_mod0_factors() - calculates m, n factors for MOD0-style clocks 1962306a36Sopenharmony_ci * MOD0 rate is calculated as follows 2062306a36Sopenharmony_ci * rate = (parent_rate >> p) / (m + 1); 2162306a36Sopenharmony_ci */ 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_cistatic void sun4i_a10_get_mod0_factors(struct factors_request *req) 2462306a36Sopenharmony_ci{ 2562306a36Sopenharmony_ci u8 div, calcm, calcp; 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci /* These clocks can only divide, so we will never be able to achieve 2862306a36Sopenharmony_ci * frequencies higher than the parent frequency */ 2962306a36Sopenharmony_ci if (req->rate > req->parent_rate) 3062306a36Sopenharmony_ci req->rate = req->parent_rate; 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci div = DIV_ROUND_UP(req->parent_rate, req->rate); 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci if (div < 16) 3562306a36Sopenharmony_ci calcp = 0; 3662306a36Sopenharmony_ci else if (div / 2 < 16) 3762306a36Sopenharmony_ci calcp = 1; 3862306a36Sopenharmony_ci else if (div / 4 < 16) 3962306a36Sopenharmony_ci calcp = 2; 4062306a36Sopenharmony_ci else 4162306a36Sopenharmony_ci calcp = 3; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci calcm = DIV_ROUND_UP(div, 1 << calcp); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci req->rate = (req->parent_rate >> calcp) / calcm; 4662306a36Sopenharmony_ci req->m = calcm - 1; 4762306a36Sopenharmony_ci req->p = calcp; 4862306a36Sopenharmony_ci} 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_ci/* user manual says "n" but it's really "p" */ 5162306a36Sopenharmony_cistatic const struct clk_factors_config sun4i_a10_mod0_config = { 5262306a36Sopenharmony_ci .mshift = 0, 5362306a36Sopenharmony_ci .mwidth = 4, 5462306a36Sopenharmony_ci .pshift = 16, 5562306a36Sopenharmony_ci .pwidth = 2, 5662306a36Sopenharmony_ci}; 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_cistatic const struct factors_data sun4i_a10_mod0_data = { 5962306a36Sopenharmony_ci .enable = 31, 6062306a36Sopenharmony_ci .mux = 24, 6162306a36Sopenharmony_ci .muxmask = BIT(1) | BIT(0), 6262306a36Sopenharmony_ci .table = &sun4i_a10_mod0_config, 6362306a36Sopenharmony_ci .getter = sun4i_a10_get_mod0_factors, 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_cistatic DEFINE_SPINLOCK(sun4i_a10_mod0_lock); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_cistatic void __init sun4i_a10_mod0_setup(struct device_node *node) 6962306a36Sopenharmony_ci{ 7062306a36Sopenharmony_ci void __iomem *reg; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci reg = of_iomap(node, 0); 7362306a36Sopenharmony_ci if (!reg) { 7462306a36Sopenharmony_ci /* 7562306a36Sopenharmony_ci * This happens with mod0 clk nodes instantiated through 7662306a36Sopenharmony_ci * mfd, as those do not have their resources assigned at 7762306a36Sopenharmony_ci * CLK_OF_DECLARE time yet, so do not print an error. 7862306a36Sopenharmony_ci */ 7962306a36Sopenharmony_ci return; 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci sunxi_factors_register(node, &sun4i_a10_mod0_data, 8362306a36Sopenharmony_ci &sun4i_a10_mod0_lock, reg); 8462306a36Sopenharmony_ci} 8562306a36Sopenharmony_ciCLK_OF_DECLARE_DRIVER(sun4i_a10_mod0, "allwinner,sun4i-a10-mod0-clk", 8662306a36Sopenharmony_ci sun4i_a10_mod0_setup); 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_cistatic int sun4i_a10_mod0_clk_probe(struct platform_device *pdev) 8962306a36Sopenharmony_ci{ 9062306a36Sopenharmony_ci struct device_node *np = pdev->dev.of_node; 9162306a36Sopenharmony_ci void __iomem *reg; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci if (!np) 9462306a36Sopenharmony_ci return -ENODEV; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci reg = devm_platform_ioremap_resource(pdev, 0); 9762306a36Sopenharmony_ci if (IS_ERR(reg)) 9862306a36Sopenharmony_ci return PTR_ERR(reg); 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci sunxi_factors_register(np, &sun4i_a10_mod0_data, 10162306a36Sopenharmony_ci &sun4i_a10_mod0_lock, reg); 10262306a36Sopenharmony_ci return 0; 10362306a36Sopenharmony_ci} 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic const struct of_device_id sun4i_a10_mod0_clk_dt_ids[] = { 10662306a36Sopenharmony_ci { .compatible = "allwinner,sun4i-a10-mod0-clk" }, 10762306a36Sopenharmony_ci { /* sentinel */ } 10862306a36Sopenharmony_ci}; 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_cistatic struct platform_driver sun4i_a10_mod0_clk_driver = { 11162306a36Sopenharmony_ci .driver = { 11262306a36Sopenharmony_ci .name = "sun4i-a10-mod0-clk", 11362306a36Sopenharmony_ci .of_match_table = sun4i_a10_mod0_clk_dt_ids, 11462306a36Sopenharmony_ci }, 11562306a36Sopenharmony_ci .probe = sun4i_a10_mod0_clk_probe, 11662306a36Sopenharmony_ci}; 11762306a36Sopenharmony_cibuiltin_platform_driver(sun4i_a10_mod0_clk_driver); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_cistatic const struct factors_data sun9i_a80_mod0_data __initconst = { 12062306a36Sopenharmony_ci .enable = 31, 12162306a36Sopenharmony_ci .mux = 24, 12262306a36Sopenharmony_ci .muxmask = BIT(3) | BIT(2) | BIT(1) | BIT(0), 12362306a36Sopenharmony_ci .table = &sun4i_a10_mod0_config, 12462306a36Sopenharmony_ci .getter = sun4i_a10_get_mod0_factors, 12562306a36Sopenharmony_ci}; 12662306a36Sopenharmony_ci 12762306a36Sopenharmony_cistatic void __init sun9i_a80_mod0_setup(struct device_node *node) 12862306a36Sopenharmony_ci{ 12962306a36Sopenharmony_ci void __iomem *reg; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 13262306a36Sopenharmony_ci if (IS_ERR(reg)) { 13362306a36Sopenharmony_ci pr_err("Could not get registers for mod0-clk: %pOFn\n", 13462306a36Sopenharmony_ci node); 13562306a36Sopenharmony_ci return; 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci sunxi_factors_register(node, &sun9i_a80_mod0_data, 13962306a36Sopenharmony_ci &sun4i_a10_mod0_lock, reg); 14062306a36Sopenharmony_ci} 14162306a36Sopenharmony_ciCLK_OF_DECLARE(sun9i_a80_mod0, "allwinner,sun9i-a80-mod0-clk", sun9i_a80_mod0_setup); 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_cistatic DEFINE_SPINLOCK(sun5i_a13_mbus_lock); 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_cistatic void __init sun5i_a13_mbus_setup(struct device_node *node) 14662306a36Sopenharmony_ci{ 14762306a36Sopenharmony_ci void __iomem *reg; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci reg = of_iomap(node, 0); 15062306a36Sopenharmony_ci if (!reg) { 15162306a36Sopenharmony_ci pr_err("Could not get registers for a13-mbus-clk\n"); 15262306a36Sopenharmony_ci return; 15362306a36Sopenharmony_ci } 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci /* The MBUS clocks needs to be always enabled */ 15662306a36Sopenharmony_ci sunxi_factors_register_critical(node, &sun4i_a10_mod0_data, 15762306a36Sopenharmony_ci &sun5i_a13_mbus_lock, reg); 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ciCLK_OF_DECLARE(sun5i_a13_mbus, "allwinner,sun5i-a13-mbus-clk", sun5i_a13_mbus_setup); 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_cistruct mmc_phase { 16262306a36Sopenharmony_ci struct clk_hw hw; 16362306a36Sopenharmony_ci u8 offset; 16462306a36Sopenharmony_ci void __iomem *reg; 16562306a36Sopenharmony_ci spinlock_t *lock; 16662306a36Sopenharmony_ci}; 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_ci#define to_mmc_phase(_hw) container_of(_hw, struct mmc_phase, hw) 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_cistatic int mmc_get_phase(struct clk_hw *hw) 17162306a36Sopenharmony_ci{ 17262306a36Sopenharmony_ci struct clk *mmc, *mmc_parent, *clk = hw->clk; 17362306a36Sopenharmony_ci struct mmc_phase *phase = to_mmc_phase(hw); 17462306a36Sopenharmony_ci unsigned int mmc_rate, mmc_parent_rate; 17562306a36Sopenharmony_ci u16 step, mmc_div; 17662306a36Sopenharmony_ci u32 value; 17762306a36Sopenharmony_ci u8 delay; 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci value = readl(phase->reg); 18062306a36Sopenharmony_ci delay = (value >> phase->offset) & 0x3; 18162306a36Sopenharmony_ci 18262306a36Sopenharmony_ci if (!delay) 18362306a36Sopenharmony_ci return 180; 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci /* Get the main MMC clock */ 18662306a36Sopenharmony_ci mmc = clk_get_parent(clk); 18762306a36Sopenharmony_ci if (!mmc) 18862306a36Sopenharmony_ci return -EINVAL; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci /* And its rate */ 19162306a36Sopenharmony_ci mmc_rate = clk_get_rate(mmc); 19262306a36Sopenharmony_ci if (!mmc_rate) 19362306a36Sopenharmony_ci return -EINVAL; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci /* Now, get the MMC parent (most likely some PLL) */ 19662306a36Sopenharmony_ci mmc_parent = clk_get_parent(mmc); 19762306a36Sopenharmony_ci if (!mmc_parent) 19862306a36Sopenharmony_ci return -EINVAL; 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci /* And its rate */ 20162306a36Sopenharmony_ci mmc_parent_rate = clk_get_rate(mmc_parent); 20262306a36Sopenharmony_ci if (!mmc_parent_rate) 20362306a36Sopenharmony_ci return -EINVAL; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci /* Get MMC clock divider */ 20662306a36Sopenharmony_ci mmc_div = mmc_parent_rate / mmc_rate; 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_ci step = DIV_ROUND_CLOSEST(360, mmc_div); 20962306a36Sopenharmony_ci return delay * step; 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ci 21262306a36Sopenharmony_cistatic int mmc_set_phase(struct clk_hw *hw, int degrees) 21362306a36Sopenharmony_ci{ 21462306a36Sopenharmony_ci struct clk *mmc, *mmc_parent, *clk = hw->clk; 21562306a36Sopenharmony_ci struct mmc_phase *phase = to_mmc_phase(hw); 21662306a36Sopenharmony_ci unsigned int mmc_rate, mmc_parent_rate; 21762306a36Sopenharmony_ci unsigned long flags; 21862306a36Sopenharmony_ci u32 value; 21962306a36Sopenharmony_ci u8 delay; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci /* Get the main MMC clock */ 22262306a36Sopenharmony_ci mmc = clk_get_parent(clk); 22362306a36Sopenharmony_ci if (!mmc) 22462306a36Sopenharmony_ci return -EINVAL; 22562306a36Sopenharmony_ci 22662306a36Sopenharmony_ci /* And its rate */ 22762306a36Sopenharmony_ci mmc_rate = clk_get_rate(mmc); 22862306a36Sopenharmony_ci if (!mmc_rate) 22962306a36Sopenharmony_ci return -EINVAL; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci /* Now, get the MMC parent (most likely some PLL) */ 23262306a36Sopenharmony_ci mmc_parent = clk_get_parent(mmc); 23362306a36Sopenharmony_ci if (!mmc_parent) 23462306a36Sopenharmony_ci return -EINVAL; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci /* And its rate */ 23762306a36Sopenharmony_ci mmc_parent_rate = clk_get_rate(mmc_parent); 23862306a36Sopenharmony_ci if (!mmc_parent_rate) 23962306a36Sopenharmony_ci return -EINVAL; 24062306a36Sopenharmony_ci 24162306a36Sopenharmony_ci if (degrees != 180) { 24262306a36Sopenharmony_ci u16 step, mmc_div; 24362306a36Sopenharmony_ci 24462306a36Sopenharmony_ci /* Get MMC clock divider */ 24562306a36Sopenharmony_ci mmc_div = mmc_parent_rate / mmc_rate; 24662306a36Sopenharmony_ci 24762306a36Sopenharmony_ci /* 24862306a36Sopenharmony_ci * We can only outphase the clocks by multiple of the 24962306a36Sopenharmony_ci * PLL's period. 25062306a36Sopenharmony_ci * 25162306a36Sopenharmony_ci * Since the MMC clock in only a divider, and the 25262306a36Sopenharmony_ci * formula to get the outphasing in degrees is deg = 25362306a36Sopenharmony_ci * 360 * delta / period 25462306a36Sopenharmony_ci * 25562306a36Sopenharmony_ci * If we simplify this formula, we can see that the 25662306a36Sopenharmony_ci * only thing that we're concerned about is the number 25762306a36Sopenharmony_ci * of period we want to outphase our clock from, and 25862306a36Sopenharmony_ci * the divider set by the MMC clock. 25962306a36Sopenharmony_ci */ 26062306a36Sopenharmony_ci step = DIV_ROUND_CLOSEST(360, mmc_div); 26162306a36Sopenharmony_ci delay = DIV_ROUND_CLOSEST(degrees, step); 26262306a36Sopenharmony_ci } else { 26362306a36Sopenharmony_ci delay = 0; 26462306a36Sopenharmony_ci } 26562306a36Sopenharmony_ci 26662306a36Sopenharmony_ci spin_lock_irqsave(phase->lock, flags); 26762306a36Sopenharmony_ci value = readl(phase->reg); 26862306a36Sopenharmony_ci value &= ~GENMASK(phase->offset + 3, phase->offset); 26962306a36Sopenharmony_ci value |= delay << phase->offset; 27062306a36Sopenharmony_ci writel(value, phase->reg); 27162306a36Sopenharmony_ci spin_unlock_irqrestore(phase->lock, flags); 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci return 0; 27462306a36Sopenharmony_ci} 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_cistatic const struct clk_ops mmc_clk_ops = { 27762306a36Sopenharmony_ci .get_phase = mmc_get_phase, 27862306a36Sopenharmony_ci .set_phase = mmc_set_phase, 27962306a36Sopenharmony_ci}; 28062306a36Sopenharmony_ci 28162306a36Sopenharmony_ci/* 28262306a36Sopenharmony_ci * sunxi_mmc_setup - Common setup function for mmc module clocks 28362306a36Sopenharmony_ci * 28462306a36Sopenharmony_ci * The only difference between module clocks on different platforms is the 28562306a36Sopenharmony_ci * width of the mux register bits and the valid values, which are passed in 28662306a36Sopenharmony_ci * through struct factors_data. The phase clocks parts are identical. 28762306a36Sopenharmony_ci */ 28862306a36Sopenharmony_cistatic void __init sunxi_mmc_setup(struct device_node *node, 28962306a36Sopenharmony_ci const struct factors_data *data, 29062306a36Sopenharmony_ci spinlock_t *lock) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci struct clk_onecell_data *clk_data; 29362306a36Sopenharmony_ci const char *parent; 29462306a36Sopenharmony_ci void __iomem *reg; 29562306a36Sopenharmony_ci int i; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci reg = of_io_request_and_map(node, 0, of_node_full_name(node)); 29862306a36Sopenharmony_ci if (IS_ERR(reg)) { 29962306a36Sopenharmony_ci pr_err("Couldn't map the %pOFn clock registers\n", node); 30062306a36Sopenharmony_ci return; 30162306a36Sopenharmony_ci } 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ci clk_data = kmalloc(sizeof(*clk_data), GFP_KERNEL); 30462306a36Sopenharmony_ci if (!clk_data) 30562306a36Sopenharmony_ci return; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci clk_data->clks = kcalloc(3, sizeof(*clk_data->clks), GFP_KERNEL); 30862306a36Sopenharmony_ci if (!clk_data->clks) 30962306a36Sopenharmony_ci goto err_free_data; 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci clk_data->clk_num = 3; 31262306a36Sopenharmony_ci clk_data->clks[0] = sunxi_factors_register(node, data, lock, reg); 31362306a36Sopenharmony_ci if (!clk_data->clks[0]) 31462306a36Sopenharmony_ci goto err_free_clks; 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci parent = __clk_get_name(clk_data->clks[0]); 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci for (i = 1; i < 3; i++) { 31962306a36Sopenharmony_ci struct clk_init_data init = { 32062306a36Sopenharmony_ci .num_parents = 1, 32162306a36Sopenharmony_ci .parent_names = &parent, 32262306a36Sopenharmony_ci .ops = &mmc_clk_ops, 32362306a36Sopenharmony_ci }; 32462306a36Sopenharmony_ci struct mmc_phase *phase; 32562306a36Sopenharmony_ci 32662306a36Sopenharmony_ci phase = kmalloc(sizeof(*phase), GFP_KERNEL); 32762306a36Sopenharmony_ci if (!phase) 32862306a36Sopenharmony_ci continue; 32962306a36Sopenharmony_ci 33062306a36Sopenharmony_ci phase->hw.init = &init; 33162306a36Sopenharmony_ci phase->reg = reg; 33262306a36Sopenharmony_ci phase->lock = lock; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci if (i == 1) 33562306a36Sopenharmony_ci phase->offset = 8; 33662306a36Sopenharmony_ci else 33762306a36Sopenharmony_ci phase->offset = 20; 33862306a36Sopenharmony_ci 33962306a36Sopenharmony_ci if (of_property_read_string_index(node, "clock-output-names", 34062306a36Sopenharmony_ci i, &init.name)) 34162306a36Sopenharmony_ci init.name = node->name; 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci clk_data->clks[i] = clk_register(NULL, &phase->hw); 34462306a36Sopenharmony_ci if (IS_ERR(clk_data->clks[i])) { 34562306a36Sopenharmony_ci kfree(phase); 34662306a36Sopenharmony_ci continue; 34762306a36Sopenharmony_ci } 34862306a36Sopenharmony_ci } 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci of_clk_add_provider(node, of_clk_src_onecell_get, clk_data); 35162306a36Sopenharmony_ci 35262306a36Sopenharmony_ci return; 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_cierr_free_clks: 35562306a36Sopenharmony_ci kfree(clk_data->clks); 35662306a36Sopenharmony_cierr_free_data: 35762306a36Sopenharmony_ci kfree(clk_data); 35862306a36Sopenharmony_ci} 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_cistatic DEFINE_SPINLOCK(sun4i_a10_mmc_lock); 36162306a36Sopenharmony_ci 36262306a36Sopenharmony_cistatic void __init sun4i_a10_mmc_setup(struct device_node *node) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci sunxi_mmc_setup(node, &sun4i_a10_mod0_data, &sun4i_a10_mmc_lock); 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ciCLK_OF_DECLARE(sun4i_a10_mmc, "allwinner,sun4i-a10-mmc-clk", sun4i_a10_mmc_setup); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_cistatic DEFINE_SPINLOCK(sun9i_a80_mmc_lock); 36962306a36Sopenharmony_ci 37062306a36Sopenharmony_cistatic void __init sun9i_a80_mmc_setup(struct device_node *node) 37162306a36Sopenharmony_ci{ 37262306a36Sopenharmony_ci sunxi_mmc_setup(node, &sun9i_a80_mod0_data, &sun9i_a80_mmc_lock); 37362306a36Sopenharmony_ci} 37462306a36Sopenharmony_ciCLK_OF_DECLARE(sun9i_a80_mmc, "allwinner,sun9i-a80-mmc-clk", sun9i_a80_mmc_setup); 375