brintos

brintos / linux-shallow public Read only

0
0
Text · 10.6 KiB · bbacd7f Raw
472 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2014, The Linux Foundation. All rights reserved.4 */5 6#include <linux/kernel.h>7#include <linux/bitops.h>8#include <linux/err.h>9#include <linux/platform_device.h>10#include <linux/module.h>11#include <linux/of.h>12#include <linux/clk-provider.h>13#include <linux/regmap.h>14 15#include <dt-bindings/clock/qcom,lcc-ipq806x.h>16 17#include "common.h"18#include "clk-regmap.h"19#include "clk-pll.h"20#include "clk-rcg.h"21#include "clk-branch.h"22#include "clk-regmap-divider.h"23#include "clk-regmap-mux.h"24#include "reset.h"25 26static struct clk_pll pll4 = {27	.l_reg = 0x4,28	.m_reg = 0x8,29	.n_reg = 0xc,30	.config_reg = 0x14,31	.mode_reg = 0x0,32	.status_reg = 0x18,33	.status_bit = 16,34	.clkr.hw.init = &(struct clk_init_data){35		.name = "pll4",36		.parent_data = &(const struct clk_parent_data) {37			.fw_name = "pxo", .name = "pxo_board",38		},39		.num_parents = 1,40		.ops = &clk_pll_ops,41	},42};43 44static const struct pll_config pll4_config = {45	.l = 0xf,46	.m = 0x91,47	.n = 0xc7,48	.vco_val = 0x0,49	.vco_mask = BIT(17) | BIT(16),50	.pre_div_val = 0x0,51	.pre_div_mask = BIT(19),52	.post_div_val = 0x0,53	.post_div_mask = BIT(21) | BIT(20),54	.mn_ena_mask = BIT(22),55	.main_output_mask = BIT(23),56};57 58enum {59	P_PXO,60	P_PLL4,61};62 63static const struct parent_map lcc_pxo_pll4_map[] = {64	{ P_PXO, 0 },65	{ P_PLL4, 2 }66};67 68static const struct clk_parent_data lcc_pxo_pll4[] = {69	{ .fw_name = "pxo", .name = "pxo_board" },70	{ .fw_name = "pll4_vote", .name = "pll4_vote" },71};72 73static const struct freq_tbl clk_tbl_aif_mi2s[] = {74	{  1024000, P_PLL4, 4,  1,  96 },75	{  1411200, P_PLL4, 4,  2, 139 },76	{  1536000, P_PLL4, 4,  1,  64 },77	{  2048000, P_PLL4, 4,  1,  48 },78	{  2116800, P_PLL4, 4,  2,  93 },79	{  2304000, P_PLL4, 4,  2,  85 },80	{  2822400, P_PLL4, 4,  6, 209 },81	{  3072000, P_PLL4, 4,  1,  32 },82	{  3175200, P_PLL4, 4,  1,  31 },83	{  4096000, P_PLL4, 4,  1,  24 },84	{  4233600, P_PLL4, 4,  9, 209 },85	{  4608000, P_PLL4, 4,  3,  64 },86	{  5644800, P_PLL4, 4, 12, 209 },87	{  6144000, P_PLL4, 4,  1,  16 },88	{  6350400, P_PLL4, 4,  2,  31 },89	{  8192000, P_PLL4, 4,  1,  12 },90	{  8467200, P_PLL4, 4, 18, 209 },91	{  9216000, P_PLL4, 4,  3,  32 },92	{ 11289600, P_PLL4, 4, 24, 209 },93	{ 12288000, P_PLL4, 4,  1,   8 },94	{ 12700800, P_PLL4, 4, 27, 209 },95	{ 13824000, P_PLL4, 4,  9,  64 },96	{ 16384000, P_PLL4, 4,  1,   6 },97	{ 16934400, P_PLL4, 4, 41, 238 },98	{ 18432000, P_PLL4, 4,  3,  16 },99	{ 22579200, P_PLL4, 2, 24, 209 },100	{ 24576000, P_PLL4, 4,  1,   4 },101	{ 27648000, P_PLL4, 4,  9,  32 },102	{ 33868800, P_PLL4, 4, 41, 119 },103	{ 36864000, P_PLL4, 4,  3,   8 },104	{ 45158400, P_PLL4, 1, 24, 209 },105	{ 49152000, P_PLL4, 4,  1,   2 },106	{ 50803200, P_PLL4, 1, 27, 209 },107	{ }108};109 110static struct clk_rcg mi2s_osr_src = {111	.ns_reg = 0x48,112	.md_reg = 0x4c,113	.mn = {114		.mnctr_en_bit = 8,115		.mnctr_reset_bit = 7,116		.mnctr_mode_shift = 5,117		.n_val_shift = 24,118		.m_val_shift = 8,119		.width = 8,120	},121	.p = {122		.pre_div_shift = 3,123		.pre_div_width = 2,124	},125	.s = {126		.src_sel_shift = 0,127		.parent_map = lcc_pxo_pll4_map,128	},129	.freq_tbl = clk_tbl_aif_mi2s,130	.clkr = {131		.enable_reg = 0x48,132		.enable_mask = BIT(9),133		.hw.init = &(struct clk_init_data){134			.name = "mi2s_osr_src",135			.parent_data = lcc_pxo_pll4,136			.num_parents = ARRAY_SIZE(lcc_pxo_pll4),137			.ops = &clk_rcg_ops,138			.flags = CLK_SET_RATE_GATE,139		},140	},141};142 143static struct clk_branch mi2s_osr_clk = {144	.halt_reg = 0x50,145	.halt_bit = 1,146	.halt_check = BRANCH_HALT_ENABLE,147	.clkr = {148		.enable_reg = 0x48,149		.enable_mask = BIT(17),150		.hw.init = &(struct clk_init_data){151			.name = "mi2s_osr_clk",152			.parent_hws = (const struct clk_hw*[]) {153				&mi2s_osr_src.clkr.hw,154			},155			.num_parents = 1,156			.ops = &clk_branch_ops,157			.flags = CLK_SET_RATE_PARENT,158		},159	},160};161 162static struct clk_regmap_div mi2s_div_clk = {163	.reg = 0x48,164	.shift = 10,165	.width = 4,166	.clkr = {167		.hw.init = &(struct clk_init_data){168			.name = "mi2s_div_clk",169			.parent_hws = (const struct clk_hw*[]) {170				&mi2s_osr_src.clkr.hw,171			},172			.num_parents = 1,173			.ops = &clk_regmap_div_ops,174		},175	},176};177 178static struct clk_branch mi2s_bit_div_clk = {179	.halt_reg = 0x50,180	.halt_bit = 0,181	.halt_check = BRANCH_HALT_ENABLE,182	.clkr = {183		.enable_reg = 0x48,184		.enable_mask = BIT(15),185		.hw.init = &(struct clk_init_data){186			.name = "mi2s_bit_div_clk",187			.parent_hws = (const struct clk_hw*[]) {188				&mi2s_div_clk.clkr.hw,189			},190			.num_parents = 1,191			.ops = &clk_branch_ops,192			.flags = CLK_SET_RATE_PARENT,193		},194	},195};196 197static const struct clk_parent_data lcc_mi2s_bit_div_codec_clk[] = {198	{ .hw = &mi2s_bit_div_clk.clkr.hw, },199	{ .fw_name = "mi2s_codec", .name = "mi2s_codec_clk" },200};201 202static struct clk_regmap_mux mi2s_bit_clk = {203	.reg = 0x48,204	.shift = 14,205	.width = 1,206	.clkr = {207		.hw.init = &(struct clk_init_data){208			.name = "mi2s_bit_clk",209			.parent_data = lcc_mi2s_bit_div_codec_clk,210			.num_parents = ARRAY_SIZE(lcc_mi2s_bit_div_codec_clk),211			.ops = &clk_regmap_mux_closest_ops,212			.flags = CLK_SET_RATE_PARENT,213		},214	},215};216 217static const struct freq_tbl clk_tbl_pcm[] = {218	{   64000, P_PLL4, 4, 1, 1536 },219	{  128000, P_PLL4, 4, 1,  768 },220	{  256000, P_PLL4, 4, 1,  384 },221	{  512000, P_PLL4, 4, 1,  192 },222	{ 1024000, P_PLL4, 4, 1,   96 },223	{ 2048000, P_PLL4, 4, 1,   48 },224	{ },225};226 227static struct clk_rcg pcm_src = {228	.ns_reg = 0x54,229	.md_reg = 0x58,230	.mn = {231		.mnctr_en_bit = 8,232		.mnctr_reset_bit = 7,233		.mnctr_mode_shift = 5,234		.n_val_shift = 16,235		.m_val_shift = 16,236		.width = 16,237	},238	.p = {239		.pre_div_shift = 3,240		.pre_div_width = 2,241	},242	.s = {243		.src_sel_shift = 0,244		.parent_map = lcc_pxo_pll4_map,245	},246	.freq_tbl = clk_tbl_pcm,247	.clkr = {248		.enable_reg = 0x54,249		.enable_mask = BIT(9),250		.hw.init = &(struct clk_init_data){251			.name = "pcm_src",252			.parent_data = lcc_pxo_pll4,253			.num_parents = ARRAY_SIZE(lcc_pxo_pll4),254			.ops = &clk_rcg_ops,255			.flags = CLK_SET_RATE_GATE,256		},257	},258};259 260static struct clk_branch pcm_clk_out = {261	.halt_reg = 0x5c,262	.halt_bit = 0,263	.halt_check = BRANCH_HALT_ENABLE,264	.clkr = {265		.enable_reg = 0x54,266		.enable_mask = BIT(11),267		.hw.init = &(struct clk_init_data){268			.name = "pcm_clk_out",269			.parent_hws = (const struct clk_hw*[]) {270				&pcm_src.clkr.hw,271			},272			.num_parents = 1,273			.ops = &clk_branch_ops,274			.flags = CLK_SET_RATE_PARENT,275		},276	},277};278 279static const struct clk_parent_data lcc_pcm_clk_out_codec_clk[] = {280	{ .hw = &pcm_clk_out.clkr.hw, },281	{ .fw_name = "pcm_codec_clk", .name = "pcm_codec_clk" },282};283 284static struct clk_regmap_mux pcm_clk = {285	.reg = 0x54,286	.shift = 10,287	.width = 1,288	.clkr = {289		.hw.init = &(struct clk_init_data){290			.name = "pcm_clk",291			.parent_data = lcc_pcm_clk_out_codec_clk,292			.num_parents = ARRAY_SIZE(lcc_pcm_clk_out_codec_clk),293			.ops = &clk_regmap_mux_closest_ops,294			.flags = CLK_SET_RATE_PARENT,295		},296	},297};298 299static const struct freq_tbl clk_tbl_aif_osr[] = {300	{  2822400, P_PLL4, 1, 147, 20480 },301	{  4096000, P_PLL4, 1,   1,    96 },302	{  5644800, P_PLL4, 1, 147, 10240 },303	{  6144000, P_PLL4, 1,   1,    64 },304	{ 11289600, P_PLL4, 1, 147,  5120 },305	{ 12288000, P_PLL4, 1,   1,    32 },306	{ 22579200, P_PLL4, 1, 147,  2560 },307	{ 24576000, P_PLL4, 1,   1,    16 },308	{ },309};310 311static struct clk_rcg spdif_src = {312	.ns_reg = 0xcc,313	.md_reg = 0xd0,314	.mn = {315		.mnctr_en_bit = 8,316		.mnctr_reset_bit = 7,317		.mnctr_mode_shift = 5,318		.n_val_shift = 16,319		.m_val_shift = 16,320		.width = 8,321	},322	.p = {323		.pre_div_shift = 3,324		.pre_div_width = 2,325	},326	.s = {327		.src_sel_shift = 0,328		.parent_map = lcc_pxo_pll4_map,329	},330	.freq_tbl = clk_tbl_aif_osr,331	.clkr = {332		.enable_reg = 0xcc,333		.enable_mask = BIT(9),334		.hw.init = &(struct clk_init_data){335			.name = "spdif_src",336			.parent_data = lcc_pxo_pll4,337			.num_parents = ARRAY_SIZE(lcc_pxo_pll4),338			.ops = &clk_rcg_ops,339			.flags = CLK_SET_RATE_GATE,340		},341	},342};343 344static struct clk_branch spdif_clk = {345	.halt_reg = 0xd4,346	.halt_bit = 1,347	.halt_check = BRANCH_HALT_ENABLE,348	.clkr = {349		.enable_reg = 0xcc,350		.enable_mask = BIT(12),351		.hw.init = &(struct clk_init_data){352			.name = "spdif_clk",353			.parent_hws = (const struct clk_hw*[]) {354				&spdif_src.clkr.hw,355			},356			.num_parents = 1,357			.ops = &clk_branch_ops,358			.flags = CLK_SET_RATE_PARENT,359		},360	},361};362 363static const struct freq_tbl clk_tbl_ahbix[] = {364	{ 131072000, P_PLL4, 1, 1, 3 },365	{ },366};367 368static struct clk_rcg ahbix_clk = {369	.ns_reg = 0x38,370	.md_reg = 0x3c,371	.mn = {372		.mnctr_en_bit = 8,373		.mnctr_reset_bit = 7,374		.mnctr_mode_shift = 5,375		.n_val_shift = 24,376		.m_val_shift = 8,377		.width = 8,378	},379	.p = {380		.pre_div_shift = 3,381		.pre_div_width = 2,382	},383	.s = {384		.src_sel_shift = 0,385		.parent_map = lcc_pxo_pll4_map,386	},387	.freq_tbl = clk_tbl_ahbix,388	.clkr = {389		.enable_reg = 0x38,390		.enable_mask = BIT(11),391		.hw.init = &(struct clk_init_data){392			.name = "ahbix",393			.parent_data = lcc_pxo_pll4,394			.num_parents = ARRAY_SIZE(lcc_pxo_pll4),395			.ops = &clk_rcg_lcc_ops,396		},397	},398};399 400static struct clk_regmap *lcc_ipq806x_clks[] = {401	[PLL4] = &pll4.clkr,402	[MI2S_OSR_SRC] = &mi2s_osr_src.clkr,403	[MI2S_OSR_CLK] = &mi2s_osr_clk.clkr,404	[MI2S_DIV_CLK] = &mi2s_div_clk.clkr,405	[MI2S_BIT_DIV_CLK] = &mi2s_bit_div_clk.clkr,406	[MI2S_BIT_CLK] = &mi2s_bit_clk.clkr,407	[PCM_SRC] = &pcm_src.clkr,408	[PCM_CLK_OUT] = &pcm_clk_out.clkr,409	[PCM_CLK] = &pcm_clk.clkr,410	[SPDIF_SRC] = &spdif_src.clkr,411	[SPDIF_CLK] = &spdif_clk.clkr,412	[AHBIX_CLK] = &ahbix_clk.clkr,413};414 415static const struct qcom_reset_map lcc_ipq806x_resets[] = {416	[LCC_PCM_RESET] = { 0x54, 13 },417};418 419static const struct regmap_config lcc_ipq806x_regmap_config = {420	.reg_bits	= 32,421	.reg_stride	= 4,422	.val_bits	= 32,423	.max_register	= 0xfc,424	.fast_io	= true,425};426 427static const struct qcom_cc_desc lcc_ipq806x_desc = {428	.config = &lcc_ipq806x_regmap_config,429	.clks = lcc_ipq806x_clks,430	.num_clks = ARRAY_SIZE(lcc_ipq806x_clks),431	.resets = lcc_ipq806x_resets,432	.num_resets = ARRAY_SIZE(lcc_ipq806x_resets),433};434 435static const struct of_device_id lcc_ipq806x_match_table[] = {436	{ .compatible = "qcom,lcc-ipq8064" },437	{ }438};439MODULE_DEVICE_TABLE(of, lcc_ipq806x_match_table);440 441static int lcc_ipq806x_probe(struct platform_device *pdev)442{443	u32 val;444	struct regmap *regmap;445 446	regmap = qcom_cc_map(pdev, &lcc_ipq806x_desc);447	if (IS_ERR(regmap))448		return PTR_ERR(regmap);449 450	/* Configure the rate of PLL4 if the bootloader hasn't already */451	regmap_read(regmap, 0x0, &val);452	if (!val)453		clk_pll_configure_sr(&pll4, regmap, &pll4_config, true);454	/* Enable PLL4 source on the LPASS Primary PLL Mux */455	regmap_write(regmap, 0xc4, 0x1);456 457	return qcom_cc_really_probe(&pdev->dev, &lcc_ipq806x_desc, regmap);458}459 460static struct platform_driver lcc_ipq806x_driver = {461	.probe		= lcc_ipq806x_probe,462	.driver		= {463		.name	= "lcc-ipq806x",464		.of_match_table = lcc_ipq806x_match_table,465	},466};467module_platform_driver(lcc_ipq806x_driver);468 469MODULE_DESCRIPTION("QCOM LCC IPQ806x Driver");470MODULE_LICENSE("GPL v2");471MODULE_ALIAS("platform:lcc-ipq806x");472