162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * PLL clock descriptions for TI DA850/OMAP-L138/AM18XX 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2018 David Lechner <david@lechnology.com> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/bitops.h> 962306a36Sopenharmony_ci#include <linux/clk-provider.h> 1062306a36Sopenharmony_ci#include <linux/clk/davinci.h> 1162306a36Sopenharmony_ci#include <linux/clkdev.h> 1262306a36Sopenharmony_ci#include <linux/device.h> 1362306a36Sopenharmony_ci#include <linux/init.h> 1462306a36Sopenharmony_ci#include <linux/io.h> 1562306a36Sopenharmony_ci#include <linux/kernel.h> 1662306a36Sopenharmony_ci#include <linux/mfd/da8xx-cfgchip.h> 1762306a36Sopenharmony_ci#include <linux/mfd/syscon.h> 1862306a36Sopenharmony_ci#include <linux/of_address.h> 1962306a36Sopenharmony_ci#include <linux/of.h> 2062306a36Sopenharmony_ci#include <linux/types.h> 2162306a36Sopenharmony_ci 2262306a36Sopenharmony_ci#include "pll.h" 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#define OCSEL_OCSRC_OSCIN 0x14 2562306a36Sopenharmony_ci#define OCSEL_OCSRC_PLL0_SYSCLK(n) (0x16 + (n)) 2662306a36Sopenharmony_ci#define OCSEL_OCSRC_PLL1_OBSCLK 0x1e 2762306a36Sopenharmony_ci#define OCSEL_OCSRC_PLL1_SYSCLK(n) (0x16 + (n)) 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_cistatic const struct davinci_pll_clk_info da850_pll0_info = { 3062306a36Sopenharmony_ci .name = "pll0", 3162306a36Sopenharmony_ci .unlock_reg = CFGCHIP(0), 3262306a36Sopenharmony_ci .unlock_mask = CFGCHIP0_PLL_MASTER_LOCK, 3362306a36Sopenharmony_ci .pllm_mask = GENMASK(4, 0), 3462306a36Sopenharmony_ci .pllm_min = 4, 3562306a36Sopenharmony_ci .pllm_max = 32, 3662306a36Sopenharmony_ci .pllout_min_rate = 300000000, 3762306a36Sopenharmony_ci .pllout_max_rate = 600000000, 3862306a36Sopenharmony_ci .flags = PLL_HAS_CLKMODE | PLL_HAS_PREDIV | PLL_HAS_POSTDIV | 3962306a36Sopenharmony_ci PLL_HAS_EXTCLKSRC, 4062306a36Sopenharmony_ci}; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci/* 4362306a36Sopenharmony_ci * NB: Technically, the clocks flagged as SYSCLK_FIXED_DIV are "fixed ratio", 4462306a36Sopenharmony_ci * meaning that we could change the divider as long as we keep the correct 4562306a36Sopenharmony_ci * ratio between all of the clocks, but we don't support that because there is 4662306a36Sopenharmony_ci * currently not a need for it. 4762306a36Sopenharmony_ci */ 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ciSYSCLK(1, pll0_sysclk1, pll0_pllen, 5, SYSCLK_FIXED_DIV); 5062306a36Sopenharmony_ciSYSCLK(2, pll0_sysclk2, pll0_pllen, 5, SYSCLK_FIXED_DIV); 5162306a36Sopenharmony_ciSYSCLK(3, pll0_sysclk3, pll0_pllen, 5, 0); 5262306a36Sopenharmony_ciSYSCLK(4, pll0_sysclk4, pll0_pllen, 5, SYSCLK_FIXED_DIV); 5362306a36Sopenharmony_ciSYSCLK(5, pll0_sysclk5, pll0_pllen, 5, 0); 5462306a36Sopenharmony_ciSYSCLK(6, pll0_sysclk6, pll0_pllen, 5, SYSCLK_ARM_RATE | SYSCLK_FIXED_DIV); 5562306a36Sopenharmony_ciSYSCLK(7, pll0_sysclk7, pll0_pllen, 5, 0); 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_cistatic const char * const da850_pll0_obsclk_parent_names[] = { 5862306a36Sopenharmony_ci "oscin", 5962306a36Sopenharmony_ci "pll0_sysclk1", 6062306a36Sopenharmony_ci "pll0_sysclk2", 6162306a36Sopenharmony_ci "pll0_sysclk3", 6262306a36Sopenharmony_ci "pll0_sysclk4", 6362306a36Sopenharmony_ci "pll0_sysclk5", 6462306a36Sopenharmony_ci "pll0_sysclk6", 6562306a36Sopenharmony_ci "pll0_sysclk7", 6662306a36Sopenharmony_ci "pll1_obsclk", 6762306a36Sopenharmony_ci}; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_cistatic u32 da850_pll0_obsclk_table[] = { 7062306a36Sopenharmony_ci OCSEL_OCSRC_OSCIN, 7162306a36Sopenharmony_ci OCSEL_OCSRC_PLL0_SYSCLK(1), 7262306a36Sopenharmony_ci OCSEL_OCSRC_PLL0_SYSCLK(2), 7362306a36Sopenharmony_ci OCSEL_OCSRC_PLL0_SYSCLK(3), 7462306a36Sopenharmony_ci OCSEL_OCSRC_PLL0_SYSCLK(4), 7562306a36Sopenharmony_ci OCSEL_OCSRC_PLL0_SYSCLK(5), 7662306a36Sopenharmony_ci OCSEL_OCSRC_PLL0_SYSCLK(6), 7762306a36Sopenharmony_ci OCSEL_OCSRC_PLL0_SYSCLK(7), 7862306a36Sopenharmony_ci OCSEL_OCSRC_PLL1_OBSCLK, 7962306a36Sopenharmony_ci}; 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_cistatic const struct davinci_pll_obsclk_info da850_pll0_obsclk_info = { 8262306a36Sopenharmony_ci .name = "pll0_obsclk", 8362306a36Sopenharmony_ci .parent_names = da850_pll0_obsclk_parent_names, 8462306a36Sopenharmony_ci .num_parents = ARRAY_SIZE(da850_pll0_obsclk_parent_names), 8562306a36Sopenharmony_ci .table = da850_pll0_obsclk_table, 8662306a36Sopenharmony_ci .ocsrc_mask = GENMASK(4, 0), 8762306a36Sopenharmony_ci}; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ciint da850_pll0_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) 9062306a36Sopenharmony_ci{ 9162306a36Sopenharmony_ci struct clk *clk; 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci davinci_pll_clk_register(dev, &da850_pll0_info, "ref_clk", base, cfgchip); 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci clk = davinci_pll_sysclk_register(dev, &pll0_sysclk1, base); 9662306a36Sopenharmony_ci clk_register_clkdev(clk, "pll0_sysclk1", "da850-psc0"); 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci clk = davinci_pll_sysclk_register(dev, &pll0_sysclk2, base); 9962306a36Sopenharmony_ci clk_register_clkdev(clk, "pll0_sysclk2", "da850-psc0"); 10062306a36Sopenharmony_ci clk_register_clkdev(clk, "pll0_sysclk2", "da850-psc1"); 10162306a36Sopenharmony_ci clk_register_clkdev(clk, "pll0_sysclk2", "da850-async3-clksrc"); 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci clk = davinci_pll_sysclk_register(dev, &pll0_sysclk3, base); 10462306a36Sopenharmony_ci clk_register_clkdev(clk, "pll0_sysclk3", "da850-async1-clksrc"); 10562306a36Sopenharmony_ci 10662306a36Sopenharmony_ci clk = davinci_pll_sysclk_register(dev, &pll0_sysclk4, base); 10762306a36Sopenharmony_ci clk_register_clkdev(clk, "pll0_sysclk4", "da850-psc0"); 10862306a36Sopenharmony_ci clk_register_clkdev(clk, "pll0_sysclk4", "da850-psc1"); 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ci davinci_pll_sysclk_register(dev, &pll0_sysclk5, base); 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_ci clk = davinci_pll_sysclk_register(dev, &pll0_sysclk6, base); 11362306a36Sopenharmony_ci clk_register_clkdev(clk, "pll0_sysclk6", "da850-psc0"); 11462306a36Sopenharmony_ci 11562306a36Sopenharmony_ci davinci_pll_sysclk_register(dev, &pll0_sysclk7, base); 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci davinci_pll_auxclk_register(dev, "pll0_auxclk", base); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci clk = clk_register_fixed_factor(dev, "async2", "pll0_auxclk", 12062306a36Sopenharmony_ci CLK_IS_CRITICAL, 1, 1); 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci clk_register_clkdev(clk, NULL, "i2c_davinci.1"); 12362306a36Sopenharmony_ci clk_register_clkdev(clk, "timer0", NULL); 12462306a36Sopenharmony_ci clk_register_clkdev(clk, NULL, "davinci-wdt"); 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci davinci_pll_obsclk_register(dev, &da850_pll0_obsclk_info, base); 12762306a36Sopenharmony_ci 12862306a36Sopenharmony_ci return 0; 12962306a36Sopenharmony_ci} 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_cistatic const struct davinci_pll_sysclk_info *da850_pll0_sysclk_info[] = { 13262306a36Sopenharmony_ci &pll0_sysclk1, 13362306a36Sopenharmony_ci &pll0_sysclk2, 13462306a36Sopenharmony_ci &pll0_sysclk3, 13562306a36Sopenharmony_ci &pll0_sysclk4, 13662306a36Sopenharmony_ci &pll0_sysclk5, 13762306a36Sopenharmony_ci &pll0_sysclk6, 13862306a36Sopenharmony_ci &pll0_sysclk7, 13962306a36Sopenharmony_ci NULL 14062306a36Sopenharmony_ci}; 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_civoid of_da850_pll0_init(struct device_node *node) 14362306a36Sopenharmony_ci{ 14462306a36Sopenharmony_ci void __iomem *base; 14562306a36Sopenharmony_ci struct regmap *cfgchip; 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ci base = of_iomap(node, 0); 14862306a36Sopenharmony_ci if (!base) { 14962306a36Sopenharmony_ci pr_err("%s: ioremap failed\n", __func__); 15062306a36Sopenharmony_ci return; 15162306a36Sopenharmony_ci } 15262306a36Sopenharmony_ci 15362306a36Sopenharmony_ci cfgchip = syscon_regmap_lookup_by_compatible("ti,da830-cfgchip"); 15462306a36Sopenharmony_ci 15562306a36Sopenharmony_ci of_davinci_pll_init(NULL, node, &da850_pll0_info, 15662306a36Sopenharmony_ci &da850_pll0_obsclk_info, 15762306a36Sopenharmony_ci da850_pll0_sysclk_info, 7, base, cfgchip); 15862306a36Sopenharmony_ci} 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_cistatic const struct davinci_pll_clk_info da850_pll1_info = { 16162306a36Sopenharmony_ci .name = "pll1", 16262306a36Sopenharmony_ci .unlock_reg = CFGCHIP(3), 16362306a36Sopenharmony_ci .unlock_mask = CFGCHIP3_PLL1_MASTER_LOCK, 16462306a36Sopenharmony_ci .pllm_mask = GENMASK(4, 0), 16562306a36Sopenharmony_ci .pllm_min = 4, 16662306a36Sopenharmony_ci .pllm_max = 32, 16762306a36Sopenharmony_ci .pllout_min_rate = 300000000, 16862306a36Sopenharmony_ci .pllout_max_rate = 600000000, 16962306a36Sopenharmony_ci .flags = PLL_HAS_POSTDIV, 17062306a36Sopenharmony_ci}; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ciSYSCLK(1, pll1_sysclk1, pll1_pllen, 5, SYSCLK_ALWAYS_ENABLED); 17362306a36Sopenharmony_ciSYSCLK(2, pll1_sysclk2, pll1_pllen, 5, 0); 17462306a36Sopenharmony_ciSYSCLK(3, pll1_sysclk3, pll1_pllen, 5, 0); 17562306a36Sopenharmony_ci 17662306a36Sopenharmony_cistatic const char * const da850_pll1_obsclk_parent_names[] = { 17762306a36Sopenharmony_ci "oscin", 17862306a36Sopenharmony_ci "pll1_sysclk1", 17962306a36Sopenharmony_ci "pll1_sysclk2", 18062306a36Sopenharmony_ci "pll1_sysclk3", 18162306a36Sopenharmony_ci}; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_cistatic u32 da850_pll1_obsclk_table[] = { 18462306a36Sopenharmony_ci OCSEL_OCSRC_OSCIN, 18562306a36Sopenharmony_ci OCSEL_OCSRC_PLL1_SYSCLK(1), 18662306a36Sopenharmony_ci OCSEL_OCSRC_PLL1_SYSCLK(2), 18762306a36Sopenharmony_ci OCSEL_OCSRC_PLL1_SYSCLK(3), 18862306a36Sopenharmony_ci}; 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cistatic const struct davinci_pll_obsclk_info da850_pll1_obsclk_info = { 19162306a36Sopenharmony_ci .name = "pll1_obsclk", 19262306a36Sopenharmony_ci .parent_names = da850_pll1_obsclk_parent_names, 19362306a36Sopenharmony_ci .num_parents = ARRAY_SIZE(da850_pll1_obsclk_parent_names), 19462306a36Sopenharmony_ci .table = da850_pll1_obsclk_table, 19562306a36Sopenharmony_ci .ocsrc_mask = GENMASK(4, 0), 19662306a36Sopenharmony_ci}; 19762306a36Sopenharmony_ci 19862306a36Sopenharmony_ciint da850_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) 19962306a36Sopenharmony_ci{ 20062306a36Sopenharmony_ci struct clk *clk; 20162306a36Sopenharmony_ci 20262306a36Sopenharmony_ci davinci_pll_clk_register(dev, &da850_pll1_info, "oscin", base, cfgchip); 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci davinci_pll_sysclk_register(dev, &pll1_sysclk1, base); 20562306a36Sopenharmony_ci 20662306a36Sopenharmony_ci clk = davinci_pll_sysclk_register(dev, &pll1_sysclk2, base); 20762306a36Sopenharmony_ci clk_register_clkdev(clk, "pll1_sysclk2", "da850-async3-clksrc"); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci davinci_pll_sysclk_register(dev, &pll1_sysclk3, base); 21062306a36Sopenharmony_ci 21162306a36Sopenharmony_ci davinci_pll_obsclk_register(dev, &da850_pll1_obsclk_info, base); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci return 0; 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistatic const struct davinci_pll_sysclk_info *da850_pll1_sysclk_info[] = { 21762306a36Sopenharmony_ci &pll1_sysclk1, 21862306a36Sopenharmony_ci &pll1_sysclk2, 21962306a36Sopenharmony_ci &pll1_sysclk3, 22062306a36Sopenharmony_ci NULL 22162306a36Sopenharmony_ci}; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ciint of_da850_pll1_init(struct device *dev, void __iomem *base, struct regmap *cfgchip) 22462306a36Sopenharmony_ci{ 22562306a36Sopenharmony_ci return of_davinci_pll_init(dev, dev->of_node, &da850_pll1_info, 22662306a36Sopenharmony_ci &da850_pll1_obsclk_info, 22762306a36Sopenharmony_ci da850_pll1_sysclk_info, 3, base, cfgchip); 22862306a36Sopenharmony_ci} 229