brintos

brintos / linux-shallow public Read only

0
0
Text · 12.4 KiB · 8eabd1c Raw
401 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 * Hi3798CV200 Clock and Reset Generator Driver4 *5 * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.6 */7 8#include <dt-bindings/clock/histb-clock.h>9#include <linux/clk-provider.h>10#include <linux/module.h>11#include <linux/of.h>12#include <linux/platform_device.h>13#include "clk.h"14#include "crg.h"15#include "reset.h"16 17/* hi3798CV200 core CRG */18#define HI3798CV200_INNER_CLK_OFFSET		6419#define HI3798CV200_FIXED_24M			6520#define HI3798CV200_FIXED_25M			6621#define HI3798CV200_FIXED_50M			6722#define HI3798CV200_FIXED_75M			6823#define HI3798CV200_FIXED_100M			6924#define HI3798CV200_FIXED_150M			7025#define HI3798CV200_FIXED_200M			7126#define HI3798CV200_FIXED_250M			7227#define HI3798CV200_FIXED_300M			7328#define HI3798CV200_FIXED_400M			7429#define HI3798CV200_MMC_MUX			7530#define HI3798CV200_ETH_PUB_CLK			7631#define HI3798CV200_ETH_BUS_CLK			7732#define HI3798CV200_ETH_BUS0_CLK		7833#define HI3798CV200_ETH_BUS1_CLK		7934#define HI3798CV200_COMBPHY1_MUX		8035#define HI3798CV200_FIXED_12M			8136#define HI3798CV200_FIXED_48M			8237#define HI3798CV200_FIXED_60M			8338#define HI3798CV200_FIXED_166P5M		8439#define HI3798CV200_SDIO0_MUX			8540#define HI3798CV200_COMBPHY0_MUX		8641 42#define HI3798CV200_CRG_NR_CLKS			12843 44static const struct hisi_fixed_rate_clock hi3798cv200_fixed_rate_clks[] = {45	{ HISTB_OSC_CLK, "clk_osc", NULL, 0, 24000000, },46	{ HISTB_APB_CLK, "clk_apb", NULL, 0, 100000000, },47	{ HISTB_AHB_CLK, "clk_ahb", NULL, 0, 200000000, },48	{ HI3798CV200_FIXED_12M, "12m", NULL, 0, 12000000, },49	{ HI3798CV200_FIXED_24M, "24m", NULL, 0, 24000000, },50	{ HI3798CV200_FIXED_25M, "25m", NULL, 0, 25000000, },51	{ HI3798CV200_FIXED_48M, "48m", NULL, 0, 48000000, },52	{ HI3798CV200_FIXED_50M, "50m", NULL, 0, 50000000, },53	{ HI3798CV200_FIXED_60M, "60m", NULL, 0, 60000000, },54	{ HI3798CV200_FIXED_75M, "75m", NULL, 0, 75000000, },55	{ HI3798CV200_FIXED_100M, "100m", NULL, 0, 100000000, },56	{ HI3798CV200_FIXED_150M, "150m", NULL, 0, 150000000, },57	{ HI3798CV200_FIXED_166P5M, "166p5m", NULL, 0, 165000000, },58	{ HI3798CV200_FIXED_200M, "200m", NULL, 0, 200000000, },59	{ HI3798CV200_FIXED_250M, "250m", NULL, 0, 250000000, },60};61 62static const char *const mmc_mux_p[] = {63		"100m", "50m", "25m", "200m", "150m" };64static u32 mmc_mux_table[] = {0, 1, 2, 3, 6};65 66static const char *const comphy_mux_p[] = {67		"100m", "25m"};68static u32 comphy_mux_table[] = {2, 3};69 70static const char *const sdio_mux_p[] = {71		"100m", "50m", "150m", "166p5m" };72static u32 sdio_mux_table[] = {0, 1, 2, 3};73 74static struct hisi_mux_clock hi3798cv200_mux_clks[] = {75	{ HI3798CV200_MMC_MUX, "mmc_mux", mmc_mux_p, ARRAY_SIZE(mmc_mux_p),76		CLK_SET_RATE_PARENT, 0xa0, 8, 3, 0, mmc_mux_table, },77	{ HI3798CV200_COMBPHY0_MUX, "combphy0_mux",78		comphy_mux_p, ARRAY_SIZE(comphy_mux_p),79		CLK_SET_RATE_PARENT, 0x188, 2, 2, 0, comphy_mux_table, },80	{ HI3798CV200_COMBPHY1_MUX, "combphy1_mux",81		comphy_mux_p, ARRAY_SIZE(comphy_mux_p),82		CLK_SET_RATE_PARENT, 0x188, 10, 2, 0, comphy_mux_table, },83	{ HI3798CV200_SDIO0_MUX, "sdio0_mux", sdio_mux_p,84		ARRAY_SIZE(sdio_mux_p), CLK_SET_RATE_PARENT,85		0x9c, 8, 2, 0, sdio_mux_table, },86};87 88static u32 mmc_phase_regvals[] = {0, 1, 2, 3, 4, 5, 6, 7};89static u32 mmc_phase_degrees[] = {0, 45, 90, 135, 180, 225, 270, 315};90 91static struct hisi_phase_clock hi3798cv200_phase_clks[] = {92	{ HISTB_MMC_SAMPLE_CLK, "mmc_sample", "clk_mmc_ciu",93		CLK_SET_RATE_PARENT, 0xa0, 12, 3, mmc_phase_degrees,94		mmc_phase_regvals, ARRAY_SIZE(mmc_phase_regvals) },95	{ HISTB_MMC_DRV_CLK, "mmc_drive", "clk_mmc_ciu",96		CLK_SET_RATE_PARENT, 0xa0, 16, 3, mmc_phase_degrees,97		mmc_phase_regvals, ARRAY_SIZE(mmc_phase_regvals) },98};99 100static const struct hisi_gate_clock hi3798cv200_gate_clks[] = {101	/* UART */102	{ HISTB_UART2_CLK, "clk_uart2", "75m",103		CLK_SET_RATE_PARENT, 0x68, 4, 0, },104	/* I2C */105	{ HISTB_I2C0_CLK, "clk_i2c0", "clk_apb",106		CLK_SET_RATE_PARENT, 0x6C, 4, 0, },107	{ HISTB_I2C1_CLK, "clk_i2c1", "clk_apb",108		CLK_SET_RATE_PARENT, 0x6C, 8, 0, },109	{ HISTB_I2C2_CLK, "clk_i2c2", "clk_apb",110		CLK_SET_RATE_PARENT, 0x6C, 12, 0, },111	{ HISTB_I2C3_CLK, "clk_i2c3", "clk_apb",112		CLK_SET_RATE_PARENT, 0x6C, 16, 0, },113	{ HISTB_I2C4_CLK, "clk_i2c4", "clk_apb",114		CLK_SET_RATE_PARENT, 0x6C, 20, 0, },115	/* SPI */116	{ HISTB_SPI0_CLK, "clk_spi0", "clk_apb",117		CLK_SET_RATE_PARENT, 0x70, 0, 0, },118	/* SDIO */119	{ HISTB_SDIO0_BIU_CLK, "clk_sdio0_biu", "200m",120			CLK_SET_RATE_PARENT, 0x9c, 0, 0, },121	{ HISTB_SDIO0_CIU_CLK, "clk_sdio0_ciu", "sdio0_mux",122		CLK_SET_RATE_PARENT, 0x9c, 1, 0, },123	/* EMMC */124	{ HISTB_MMC_BIU_CLK, "clk_mmc_biu", "200m",125		CLK_SET_RATE_PARENT, 0xa0, 0, 0, },126	{ HISTB_MMC_CIU_CLK, "clk_mmc_ciu", "mmc_mux",127		CLK_SET_RATE_PARENT, 0xa0, 1, 0, },128	/* PCIE*/129	{ HISTB_PCIE_BUS_CLK, "clk_pcie_bus", "200m",130		CLK_SET_RATE_PARENT, 0x18c, 0, 0, },131	{ HISTB_PCIE_SYS_CLK, "clk_pcie_sys", "100m",132		CLK_SET_RATE_PARENT, 0x18c, 1, 0, },133	{ HISTB_PCIE_PIPE_CLK, "clk_pcie_pipe", "250m",134		CLK_SET_RATE_PARENT, 0x18c, 2, 0, },135	{ HISTB_PCIE_AUX_CLK, "clk_pcie_aux", "24m",136		CLK_SET_RATE_PARENT, 0x18c, 3, 0, },137	/* Ethernet */138	{ HI3798CV200_ETH_PUB_CLK, "clk_pub", NULL,139		CLK_SET_RATE_PARENT, 0xcc, 5, 0, },140	{ HI3798CV200_ETH_BUS_CLK, "clk_bus", "clk_pub",141		CLK_SET_RATE_PARENT, 0xcc, 0, 0, },142	{ HI3798CV200_ETH_BUS0_CLK, "clk_bus_m0", "clk_bus",143		CLK_SET_RATE_PARENT, 0xcc, 1, 0, },144	{ HI3798CV200_ETH_BUS1_CLK, "clk_bus_m1", "clk_bus",145		CLK_SET_RATE_PARENT, 0xcc, 2, 0, },146	{ HISTB_ETH0_MAC_CLK, "clk_mac0", "clk_bus_m0",147		CLK_SET_RATE_PARENT, 0xcc, 3, 0, },148	{ HISTB_ETH0_MACIF_CLK, "clk_macif0", "clk_bus_m0",149		CLK_SET_RATE_PARENT, 0xcc, 24, 0, },150	{ HISTB_ETH1_MAC_CLK, "clk_mac1", "clk_bus_m1",151		CLK_SET_RATE_PARENT, 0xcc, 4, 0, },152	{ HISTB_ETH1_MACIF_CLK, "clk_macif1", "clk_bus_m1",153		CLK_SET_RATE_PARENT, 0xcc, 25, 0, },154	/* COMBPHY0 */155	{ HISTB_COMBPHY0_CLK, "clk_combphy0", "combphy0_mux",156		CLK_SET_RATE_PARENT, 0x188, 0, 0, },157	/* COMBPHY1 */158	{ HISTB_COMBPHY1_CLK, "clk_combphy1", "combphy1_mux",159		CLK_SET_RATE_PARENT, 0x188, 8, 0, },160	/* USB2 */161	{ HISTB_USB2_BUS_CLK, "clk_u2_bus", "clk_ahb",162		CLK_SET_RATE_PARENT, 0xb8, 0, 0, },163	{ HISTB_USB2_PHY_CLK, "clk_u2_phy", "60m",164		CLK_SET_RATE_PARENT, 0xb8, 4, 0, },165	{ HISTB_USB2_12M_CLK, "clk_u2_12m", "12m",166		CLK_SET_RATE_PARENT, 0xb8, 2, 0 },167	{ HISTB_USB2_48M_CLK, "clk_u2_48m", "48m",168		CLK_SET_RATE_PARENT, 0xb8, 1, 0 },169	{ HISTB_USB2_UTMI_CLK, "clk_u2_utmi", "60m",170		CLK_SET_RATE_PARENT, 0xb8, 5, 0 },171	{ HISTB_USB2_OTG_UTMI_CLK, "clk_u2_otg_utmi", "60m",172		CLK_SET_RATE_PARENT, 0xb8, 3, 0 },173	{ HISTB_USB2_PHY1_REF_CLK, "clk_u2_phy1_ref", "24m",174		CLK_SET_RATE_PARENT, 0xbc, 0, 0 },175	{ HISTB_USB2_PHY2_REF_CLK, "clk_u2_phy2_ref", "24m",176		CLK_SET_RATE_PARENT, 0xbc, 2, 0 },177	/* USB3 */178	{ HISTB_USB3_BUS_CLK, "clk_u3_bus", NULL,179		CLK_SET_RATE_PARENT, 0xb0, 0, 0 },180	{ HISTB_USB3_UTMI_CLK, "clk_u3_utmi", NULL,181		CLK_SET_RATE_PARENT, 0xb0, 4, 0 },182	{ HISTB_USB3_PIPE_CLK, "clk_u3_pipe", NULL,183		CLK_SET_RATE_PARENT, 0xb0, 3, 0 },184	{ HISTB_USB3_SUSPEND_CLK, "clk_u3_suspend", NULL,185		CLK_SET_RATE_PARENT, 0xb0, 2, 0 },186	{ HISTB_USB3_BUS_CLK1, "clk_u3_bus1", NULL,187		CLK_SET_RATE_PARENT, 0xb0, 16, 0 },188	{ HISTB_USB3_UTMI_CLK1, "clk_u3_utmi1", NULL,189		CLK_SET_RATE_PARENT, 0xb0, 20, 0 },190	{ HISTB_USB3_PIPE_CLK1, "clk_u3_pipe1", NULL,191		CLK_SET_RATE_PARENT, 0xb0, 19, 0 },192	{ HISTB_USB3_SUSPEND_CLK1, "clk_u3_suspend1", NULL,193		CLK_SET_RATE_PARENT, 0xb0, 18, 0 },194};195 196static struct hisi_clock_data *hi3798cv200_clk_register(197				struct platform_device *pdev)198{199	struct hisi_clock_data *clk_data;200	int ret;201 202	clk_data = hisi_clk_alloc(pdev, HI3798CV200_CRG_NR_CLKS);203	if (!clk_data)204		return ERR_PTR(-ENOMEM);205 206	/* hisi_phase_clock is resource managed */207	ret = hisi_clk_register_phase(&pdev->dev,208				hi3798cv200_phase_clks,209				ARRAY_SIZE(hi3798cv200_phase_clks),210				clk_data);211	if (ret)212		return ERR_PTR(ret);213 214	ret = hisi_clk_register_fixed_rate(hi3798cv200_fixed_rate_clks,215				     ARRAY_SIZE(hi3798cv200_fixed_rate_clks),216				     clk_data);217	if (ret)218		return ERR_PTR(ret);219 220	ret = hisi_clk_register_mux(hi3798cv200_mux_clks,221				ARRAY_SIZE(hi3798cv200_mux_clks),222				clk_data);223	if (ret)224		goto unregister_fixed_rate;225 226	ret = hisi_clk_register_gate(hi3798cv200_gate_clks,227				ARRAY_SIZE(hi3798cv200_gate_clks),228				clk_data);229	if (ret)230		goto unregister_mux;231 232	ret = of_clk_add_provider(pdev->dev.of_node,233			of_clk_src_onecell_get, &clk_data->clk_data);234	if (ret)235		goto unregister_gate;236 237	return clk_data;238 239unregister_gate:240	hisi_clk_unregister_gate(hi3798cv200_gate_clks,241				ARRAY_SIZE(hi3798cv200_gate_clks),242				clk_data);243unregister_mux:244	hisi_clk_unregister_mux(hi3798cv200_mux_clks,245				ARRAY_SIZE(hi3798cv200_mux_clks),246				clk_data);247unregister_fixed_rate:248	hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,249				ARRAY_SIZE(hi3798cv200_fixed_rate_clks),250				clk_data);251	return ERR_PTR(ret);252}253 254static void hi3798cv200_clk_unregister(struct platform_device *pdev)255{256	struct hisi_crg_dev *crg = platform_get_drvdata(pdev);257 258	of_clk_del_provider(pdev->dev.of_node);259 260	hisi_clk_unregister_gate(hi3798cv200_gate_clks,261				ARRAY_SIZE(hi3798cv200_gate_clks),262				crg->clk_data);263	hisi_clk_unregister_mux(hi3798cv200_mux_clks,264				ARRAY_SIZE(hi3798cv200_mux_clks),265				crg->clk_data);266	hisi_clk_unregister_fixed_rate(hi3798cv200_fixed_rate_clks,267				ARRAY_SIZE(hi3798cv200_fixed_rate_clks),268				crg->clk_data);269}270 271static const struct hisi_crg_funcs hi3798cv200_crg_funcs = {272	.register_clks = hi3798cv200_clk_register,273	.unregister_clks = hi3798cv200_clk_unregister,274};275 276/* hi3798CV200 sysctrl CRG */277 278#define HI3798CV200_SYSCTRL_NR_CLKS 16279 280static const struct hisi_gate_clock hi3798cv200_sysctrl_gate_clks[] = {281	{ HISTB_IR_CLK, "clk_ir", "24m",282		CLK_SET_RATE_PARENT, 0x48, 4, 0, },283	{ HISTB_TIMER01_CLK, "clk_timer01", "24m",284		CLK_SET_RATE_PARENT, 0x48, 6, 0, },285	{ HISTB_UART0_CLK, "clk_uart0", "75m",286		CLK_SET_RATE_PARENT, 0x48, 10, 0, },287};288 289static struct hisi_clock_data *hi3798cv200_sysctrl_clk_register(290					struct platform_device *pdev)291{292	struct hisi_clock_data *clk_data;293	int ret;294 295	clk_data = hisi_clk_alloc(pdev, HI3798CV200_SYSCTRL_NR_CLKS);296	if (!clk_data)297		return ERR_PTR(-ENOMEM);298 299	ret = hisi_clk_register_gate(hi3798cv200_sysctrl_gate_clks,300				ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),301				clk_data);302	if (ret)303		return ERR_PTR(ret);304 305	ret = of_clk_add_provider(pdev->dev.of_node,306			of_clk_src_onecell_get, &clk_data->clk_data);307	if (ret)308		goto unregister_gate;309 310	return clk_data;311 312unregister_gate:313	hisi_clk_unregister_gate(hi3798cv200_sysctrl_gate_clks,314				ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),315				clk_data);316	return ERR_PTR(ret);317}318 319static void hi3798cv200_sysctrl_clk_unregister(struct platform_device *pdev)320{321	struct hisi_crg_dev *crg = platform_get_drvdata(pdev);322 323	of_clk_del_provider(pdev->dev.of_node);324 325	hisi_clk_unregister_gate(hi3798cv200_sysctrl_gate_clks,326				ARRAY_SIZE(hi3798cv200_sysctrl_gate_clks),327				crg->clk_data);328}329 330static const struct hisi_crg_funcs hi3798cv200_sysctrl_funcs = {331	.register_clks = hi3798cv200_sysctrl_clk_register,332	.unregister_clks = hi3798cv200_sysctrl_clk_unregister,333};334 335static const struct of_device_id hi3798cv200_crg_match_table[] = {336	{ .compatible = "hisilicon,hi3798cv200-crg",337		.data = &hi3798cv200_crg_funcs },338	{ .compatible = "hisilicon,hi3798cv200-sysctrl",339		.data = &hi3798cv200_sysctrl_funcs },340	{ }341};342MODULE_DEVICE_TABLE(of, hi3798cv200_crg_match_table);343 344static int hi3798cv200_crg_probe(struct platform_device *pdev)345{346	struct hisi_crg_dev *crg;347 348	crg = devm_kmalloc(&pdev->dev, sizeof(*crg), GFP_KERNEL);349	if (!crg)350		return -ENOMEM;351 352	crg->funcs = of_device_get_match_data(&pdev->dev);353	if (!crg->funcs)354		return -ENOENT;355 356	crg->rstc = hisi_reset_init(pdev);357	if (!crg->rstc)358		return -ENOMEM;359 360	crg->clk_data = crg->funcs->register_clks(pdev);361	if (IS_ERR(crg->clk_data)) {362		hisi_reset_exit(crg->rstc);363		return PTR_ERR(crg->clk_data);364	}365 366	platform_set_drvdata(pdev, crg);367	return 0;368}369 370static void hi3798cv200_crg_remove(struct platform_device *pdev)371{372	struct hisi_crg_dev *crg = platform_get_drvdata(pdev);373 374	hisi_reset_exit(crg->rstc);375	crg->funcs->unregister_clks(pdev);376}377 378static struct platform_driver hi3798cv200_crg_driver = {379	.probe          = hi3798cv200_crg_probe,380	.remove		= hi3798cv200_crg_remove,381	.driver         = {382		.name   = "hi3798cv200-crg",383		.of_match_table = hi3798cv200_crg_match_table,384	},385};386 387static int __init hi3798cv200_crg_init(void)388{389	return platform_driver_register(&hi3798cv200_crg_driver);390}391core_initcall(hi3798cv200_crg_init);392 393static void __exit hi3798cv200_crg_exit(void)394{395	platform_driver_unregister(&hi3798cv200_crg_driver);396}397module_exit(hi3798cv200_crg_exit);398 399MODULE_LICENSE("GPL v2");400MODULE_DESCRIPTION("HiSilicon Hi3798CV200 CRG Driver");401