brintos

brintos / linux-shallow public Read only

0
0
Text · 8.1 KiB · 0975ac5 Raw
272 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * Copyright (c) 2016 Chen-Yu Tsai. All rights reserved.4 */5 6#include <linux/clk.h>7#include <linux/clk-provider.h>8#include <linux/module.h>9#include <linux/platform_device.h>10#include <linux/reset.h>11 12#include "ccu_common.h"13#include "ccu_div.h"14#include "ccu_gate.h"15#include "ccu_reset.h"16 17#include "ccu-sun9i-a80-de.h"18 19static SUNXI_CCU_GATE(fe0_clk,		"fe0",		"fe0-div",20		      0x00, BIT(0), 0);21static SUNXI_CCU_GATE(fe1_clk,		"fe1",		"fe1-div",22		      0x00, BIT(1), 0);23static SUNXI_CCU_GATE(fe2_clk,		"fe2",		"fe2-div",24		      0x00, BIT(2), 0);25static SUNXI_CCU_GATE(iep_deu0_clk,	"iep-deu0",	"de",26		      0x00, BIT(4), 0);27static SUNXI_CCU_GATE(iep_deu1_clk,	"iep-deu1",	"de",28		      0x00, BIT(5), 0);29static SUNXI_CCU_GATE(be0_clk,		"be0",		"be0-div",30		      0x00, BIT(8), 0);31static SUNXI_CCU_GATE(be1_clk,		"be1",		"be1-div",32		      0x00, BIT(9), 0);33static SUNXI_CCU_GATE(be2_clk,		"be2",		"be2-div",34		      0x00, BIT(10), 0);35static SUNXI_CCU_GATE(iep_drc0_clk,	"iep-drc0",	"de",36		      0x00, BIT(12), 0);37static SUNXI_CCU_GATE(iep_drc1_clk,	"iep-drc1",	"de",38		      0x00, BIT(13), 0);39static SUNXI_CCU_GATE(merge_clk,	"merge",	"de",40		      0x00, BIT(20), 0);41 42static SUNXI_CCU_GATE(dram_fe0_clk,	"dram-fe0",	"sdram",43		      0x04, BIT(0), 0);44static SUNXI_CCU_GATE(dram_fe1_clk,	"dram-fe1",	"sdram",45		      0x04, BIT(1), 0);46static SUNXI_CCU_GATE(dram_fe2_clk,	"dram-fe2",	"sdram",47		      0x04, BIT(2), 0);48static SUNXI_CCU_GATE(dram_deu0_clk,	"dram-deu0",	"sdram",49		      0x04, BIT(4), 0);50static SUNXI_CCU_GATE(dram_deu1_clk,	"dram-deu1",	"sdram",51		      0x04, BIT(5), 0);52static SUNXI_CCU_GATE(dram_be0_clk,	"dram-be0",	"sdram",53		      0x04, BIT(8), 0);54static SUNXI_CCU_GATE(dram_be1_clk,	"dram-be1",	"sdram",55		      0x04, BIT(9), 0);56static SUNXI_CCU_GATE(dram_be2_clk,	"dram-be2",	"sdram",57		      0x04, BIT(10), 0);58static SUNXI_CCU_GATE(dram_drc0_clk,	"dram-drc0",	"sdram",59		      0x04, BIT(12), 0);60static SUNXI_CCU_GATE(dram_drc1_clk,	"dram-drc1",	"sdram",61		      0x04, BIT(13), 0);62 63static SUNXI_CCU_GATE(bus_fe0_clk,	"bus-fe0",	"bus-de",64		      0x08, BIT(0), 0);65static SUNXI_CCU_GATE(bus_fe1_clk,	"bus-fe1",	"bus-de",66		      0x08, BIT(1), 0);67static SUNXI_CCU_GATE(bus_fe2_clk,	"bus-fe2",	"bus-de",68		      0x08, BIT(2), 0);69static SUNXI_CCU_GATE(bus_deu0_clk,	"bus-deu0",	"bus-de",70		      0x08, BIT(4), 0);71static SUNXI_CCU_GATE(bus_deu1_clk,	"bus-deu1",	"bus-de",72		      0x08, BIT(5), 0);73static SUNXI_CCU_GATE(bus_be0_clk,	"bus-be0",	"bus-de",74		      0x08, BIT(8), 0);75static SUNXI_CCU_GATE(bus_be1_clk,	"bus-be1",	"bus-de",76		      0x08, BIT(9), 0);77static SUNXI_CCU_GATE(bus_be2_clk,	"bus-be2",	"bus-de",78		      0x08, BIT(10), 0);79static SUNXI_CCU_GATE(bus_drc0_clk,	"bus-drc0",	"bus-de",80		      0x08, BIT(12), 0);81static SUNXI_CCU_GATE(bus_drc1_clk,	"bus-drc1",	"bus-de",82		      0x08, BIT(13), 0);83 84static SUNXI_CCU_M(fe0_div_clk, "fe0-div", "de", 0x20, 0, 4, 0);85static SUNXI_CCU_M(fe1_div_clk, "fe1-div", "de", 0x20, 4, 4, 0);86static SUNXI_CCU_M(fe2_div_clk, "fe2-div", "de", 0x20, 8, 4, 0);87static SUNXI_CCU_M(be0_div_clk, "be0-div", "de", 0x20, 16, 4, 0);88static SUNXI_CCU_M(be1_div_clk, "be1-div", "de", 0x20, 20, 4, 0);89static SUNXI_CCU_M(be2_div_clk, "be2-div", "de", 0x20, 24, 4, 0);90 91static struct ccu_common *sun9i_a80_de_clks[] = {92	&fe0_clk.common,93	&fe1_clk.common,94	&fe2_clk.common,95	&iep_deu0_clk.common,96	&iep_deu1_clk.common,97	&be0_clk.common,98	&be1_clk.common,99	&be2_clk.common,100	&iep_drc0_clk.common,101	&iep_drc1_clk.common,102	&merge_clk.common,103 104	&dram_fe0_clk.common,105	&dram_fe1_clk.common,106	&dram_fe2_clk.common,107	&dram_deu0_clk.common,108	&dram_deu1_clk.common,109	&dram_be0_clk.common,110	&dram_be1_clk.common,111	&dram_be2_clk.common,112	&dram_drc0_clk.common,113	&dram_drc1_clk.common,114 115	&bus_fe0_clk.common,116	&bus_fe1_clk.common,117	&bus_fe2_clk.common,118	&bus_deu0_clk.common,119	&bus_deu1_clk.common,120	&bus_be0_clk.common,121	&bus_be1_clk.common,122	&bus_be2_clk.common,123	&bus_drc0_clk.common,124	&bus_drc1_clk.common,125 126	&fe0_div_clk.common,127	&fe1_div_clk.common,128	&fe2_div_clk.common,129	&be0_div_clk.common,130	&be1_div_clk.common,131	&be2_div_clk.common,132};133 134static struct clk_hw_onecell_data sun9i_a80_de_hw_clks = {135	.hws	= {136		[CLK_FE0]	= &fe0_clk.common.hw,137		[CLK_FE1]	= &fe1_clk.common.hw,138		[CLK_FE2]	= &fe2_clk.common.hw,139		[CLK_IEP_DEU0]	= &iep_deu0_clk.common.hw,140		[CLK_IEP_DEU1]	= &iep_deu1_clk.common.hw,141		[CLK_BE0]	= &be0_clk.common.hw,142		[CLK_BE1]	= &be1_clk.common.hw,143		[CLK_BE2]	= &be2_clk.common.hw,144		[CLK_IEP_DRC0]	= &iep_drc0_clk.common.hw,145		[CLK_IEP_DRC1]	= &iep_drc1_clk.common.hw,146		[CLK_MERGE]	= &merge_clk.common.hw,147 148		[CLK_DRAM_FE0]	= &dram_fe0_clk.common.hw,149		[CLK_DRAM_FE1]	= &dram_fe1_clk.common.hw,150		[CLK_DRAM_FE2]	= &dram_fe2_clk.common.hw,151		[CLK_DRAM_DEU0]	= &dram_deu0_clk.common.hw,152		[CLK_DRAM_DEU1]	= &dram_deu1_clk.common.hw,153		[CLK_DRAM_BE0]	= &dram_be0_clk.common.hw,154		[CLK_DRAM_BE1]	= &dram_be1_clk.common.hw,155		[CLK_DRAM_BE2]	= &dram_be2_clk.common.hw,156		[CLK_DRAM_DRC0]	= &dram_drc0_clk.common.hw,157		[CLK_DRAM_DRC1]	= &dram_drc1_clk.common.hw,158 159		[CLK_BUS_FE0]	= &bus_fe0_clk.common.hw,160		[CLK_BUS_FE1]	= &bus_fe1_clk.common.hw,161		[CLK_BUS_FE2]	= &bus_fe2_clk.common.hw,162		[CLK_BUS_DEU0]	= &bus_deu0_clk.common.hw,163		[CLK_BUS_DEU1]	= &bus_deu1_clk.common.hw,164		[CLK_BUS_BE0]	= &bus_be0_clk.common.hw,165		[CLK_BUS_BE1]	= &bus_be1_clk.common.hw,166		[CLK_BUS_BE2]	= &bus_be2_clk.common.hw,167		[CLK_BUS_DRC0]	= &bus_drc0_clk.common.hw,168		[CLK_BUS_DRC1]	= &bus_drc1_clk.common.hw,169 170		[CLK_FE0_DIV]	= &fe0_div_clk.common.hw,171		[CLK_FE1_DIV]	= &fe1_div_clk.common.hw,172		[CLK_FE2_DIV]	= &fe2_div_clk.common.hw,173		[CLK_BE0_DIV]	= &be0_div_clk.common.hw,174		[CLK_BE1_DIV]	= &be1_div_clk.common.hw,175		[CLK_BE2_DIV]	= &be2_div_clk.common.hw,176	},177	.num	= CLK_NUMBER,178};179 180static struct ccu_reset_map sun9i_a80_de_resets[] = {181	[RST_FE0]	= { 0x0c, BIT(0) },182	[RST_FE1]	= { 0x0c, BIT(1) },183	[RST_FE2]	= { 0x0c, BIT(2) },184	[RST_DEU0]	= { 0x0c, BIT(4) },185	[RST_DEU1]	= { 0x0c, BIT(5) },186	[RST_BE0]	= { 0x0c, BIT(8) },187	[RST_BE1]	= { 0x0c, BIT(9) },188	[RST_BE2]	= { 0x0c, BIT(10) },189	[RST_DRC0]	= { 0x0c, BIT(12) },190	[RST_DRC1]	= { 0x0c, BIT(13) },191	[RST_MERGE]	= { 0x0c, BIT(20) },192};193 194static const struct sunxi_ccu_desc sun9i_a80_de_clk_desc = {195	.ccu_clks	= sun9i_a80_de_clks,196	.num_ccu_clks	= ARRAY_SIZE(sun9i_a80_de_clks),197 198	.hw_clks	= &sun9i_a80_de_hw_clks,199 200	.resets		= sun9i_a80_de_resets,201	.num_resets	= ARRAY_SIZE(sun9i_a80_de_resets),202};203 204static int sun9i_a80_de_clk_probe(struct platform_device *pdev)205{206	struct clk *bus_clk;207	struct reset_control *rstc;208	void __iomem *reg;209	int ret;210 211	reg = devm_platform_ioremap_resource(pdev, 0);212	if (IS_ERR(reg))213		return PTR_ERR(reg);214 215	bus_clk = devm_clk_get(&pdev->dev, "bus");216	if (IS_ERR(bus_clk))217		return dev_err_probe(&pdev->dev, PTR_ERR(bus_clk),218				     "Couldn't get bus clk\n");219 220	rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL);221	if (IS_ERR(rstc))222		return dev_err_probe(&pdev->dev, PTR_ERR(rstc),223				     "Couldn't get reset control\n");224 225	/* The bus clock needs to be enabled for us to access the registers */226	ret = clk_prepare_enable(bus_clk);227	if (ret) {228		dev_err(&pdev->dev, "Couldn't enable bus clk: %d\n", ret);229		return ret;230	}231 232	/* The reset control needs to be asserted for the controls to work */233	ret = reset_control_deassert(rstc);234	if (ret) {235		dev_err(&pdev->dev,236			"Couldn't deassert reset control: %d\n", ret);237		goto err_disable_clk;238	}239 240	ret = devm_sunxi_ccu_probe(&pdev->dev, reg, &sun9i_a80_de_clk_desc);241	if (ret)242		goto err_assert_reset;243 244	return 0;245 246err_assert_reset:247	reset_control_assert(rstc);248err_disable_clk:249	clk_disable_unprepare(bus_clk);250	return ret;251}252 253static const struct of_device_id sun9i_a80_de_clk_ids[] = {254	{ .compatible = "allwinner,sun9i-a80-de-clks" },255	{ }256};257MODULE_DEVICE_TABLE(of, sun9i_a80_de_clk_ids);258 259static struct platform_driver sun9i_a80_de_clk_driver = {260	.probe	= sun9i_a80_de_clk_probe,261	.driver	= {262		.name	= "sun9i-a80-de-clks",263		.suppress_bind_attrs = true,264		.of_match_table	= sun9i_a80_de_clk_ids,265	},266};267module_platform_driver(sun9i_a80_de_clk_driver);268 269MODULE_IMPORT_NS(SUNXI_CCU);270MODULE_DESCRIPTION("Support for the Allwinner A80 Display Engine CCU");271MODULE_LICENSE("GPL");272