brintos

brintos / linux-shallow public Read only

0
0
Text · 10.2 KiB · 5b38d4f Raw
292 lines · c
1// SPDX-License-Identifier: GPL-2.02/*3 * Sophgo SG2042 RP clock Driver4 *5 * Copyright (C) 2024 Sophgo Technology Inc.6 * Copyright (C) 2024 Chen Wang <unicorn_wang@outlook.com>7 */8 9#include <linux/array_size.h>10#include <linux/clk-provider.h>11#include <linux/platform_device.h>12 13#include <dt-bindings/clock/sophgo,sg2042-rpgate.h>14 15#include "clk-sg2042.h"16 17#define R_SYSGATE_BEGIN		0x036818#define R_RP_RXU_CLK_ENABLE	(0x0368 - R_SYSGATE_BEGIN)19#define R_MP0_STATUS_REG	(0x0380 - R_SYSGATE_BEGIN)20#define R_MP0_CONTROL_REG	(0x0384 - R_SYSGATE_BEGIN)21#define R_MP1_STATUS_REG	(0x0388 - R_SYSGATE_BEGIN)22#define R_MP1_CONTROL_REG	(0x038C - R_SYSGATE_BEGIN)23#define R_MP2_STATUS_REG	(0x0390 - R_SYSGATE_BEGIN)24#define R_MP2_CONTROL_REG	(0x0394 - R_SYSGATE_BEGIN)25#define R_MP3_STATUS_REG	(0x0398 - R_SYSGATE_BEGIN)26#define R_MP3_CONTROL_REG	(0x039C - R_SYSGATE_BEGIN)27#define R_MP4_STATUS_REG	(0x03A0 - R_SYSGATE_BEGIN)28#define R_MP4_CONTROL_REG	(0x03A4 - R_SYSGATE_BEGIN)29#define R_MP5_STATUS_REG	(0x03A8 - R_SYSGATE_BEGIN)30#define R_MP5_CONTROL_REG	(0x03AC - R_SYSGATE_BEGIN)31#define R_MP6_STATUS_REG	(0x03B0 - R_SYSGATE_BEGIN)32#define R_MP6_CONTROL_REG	(0x03B4 - R_SYSGATE_BEGIN)33#define R_MP7_STATUS_REG	(0x03B8 - R_SYSGATE_BEGIN)34#define R_MP7_CONTROL_REG	(0x03BC - R_SYSGATE_BEGIN)35#define R_MP8_STATUS_REG	(0x03C0 - R_SYSGATE_BEGIN)36#define R_MP8_CONTROL_REG	(0x03C4 - R_SYSGATE_BEGIN)37#define R_MP9_STATUS_REG	(0x03C8 - R_SYSGATE_BEGIN)38#define R_MP9_CONTROL_REG	(0x03CC - R_SYSGATE_BEGIN)39#define R_MP10_STATUS_REG	(0x03D0 - R_SYSGATE_BEGIN)40#define R_MP10_CONTROL_REG	(0x03D4 - R_SYSGATE_BEGIN)41#define R_MP11_STATUS_REG	(0x03D8 - R_SYSGATE_BEGIN)42#define R_MP11_CONTROL_REG	(0x03DC - R_SYSGATE_BEGIN)43#define R_MP12_STATUS_REG	(0x03E0 - R_SYSGATE_BEGIN)44#define R_MP12_CONTROL_REG	(0x03E4 - R_SYSGATE_BEGIN)45#define R_MP13_STATUS_REG	(0x03E8 - R_SYSGATE_BEGIN)46#define R_MP13_CONTROL_REG	(0x03EC - R_SYSGATE_BEGIN)47#define R_MP14_STATUS_REG	(0x03F0 - R_SYSGATE_BEGIN)48#define R_MP14_CONTROL_REG	(0x03F4 - R_SYSGATE_BEGIN)49#define R_MP15_STATUS_REG	(0x03F8 - R_SYSGATE_BEGIN)50#define R_MP15_CONTROL_REG	(0x03FC - R_SYSGATE_BEGIN)51 52/**53 * struct sg2042_rpgate_clock - Gate clock for RP(riscv processors) subsystem54 * @hw:			clk_hw for initialization55 * @id:			used to map clk_onecell_data56 * @offset_enable:	offset of gate enable registers57 * @bit_idx:		which bit in the register controls gating of this clock58 */59struct sg2042_rpgate_clock {60	struct clk_hw hw;61 62	unsigned int id;63 64	u32 offset_enable;65	u8 bit_idx;66};67 68/*69 * Clock initialization macro naming rules:70 * FW: use CLK_HW_INIT_FW_NAME71 */72#define SG2042_GATE_FW(_id, _name, _parent, _flags,	\73		       _r_enable, _bit_idx) {		\74		.hw.init = CLK_HW_INIT_FW_NAME(		\75				_name,			\76				_parent,		\77				NULL,			\78				_flags),		\79		.id = _id,				\80		.offset_enable = _r_enable,		\81		.bit_idx = _bit_idx,			\82	}83 84/*85 * Gate clocks for RP subsystem (including the MP subsystem), which control86 * registers are defined in SYS_CTRL.87 */88static const struct sg2042_rpgate_clock sg2042_gate_rp[] = {89	/* downstream of clk_gate_rp_cpu_normal about rxu */90	SG2042_GATE_FW(GATE_CLK_RXU0, "clk_gate_rxu0", "rpgate",91		       0, R_RP_RXU_CLK_ENABLE, 0),92	SG2042_GATE_FW(GATE_CLK_RXU1, "clk_gate_rxu1", "rpgate",93		       0, R_RP_RXU_CLK_ENABLE, 1),94	SG2042_GATE_FW(GATE_CLK_RXU2, "clk_gate_rxu2", "rpgate",95		       0, R_RP_RXU_CLK_ENABLE, 2),96	SG2042_GATE_FW(GATE_CLK_RXU3, "clk_gate_rxu3", "rpgate",97		       0, R_RP_RXU_CLK_ENABLE, 3),98	SG2042_GATE_FW(GATE_CLK_RXU4, "clk_gate_rxu4", "rpgate",99		       0, R_RP_RXU_CLK_ENABLE, 4),100	SG2042_GATE_FW(GATE_CLK_RXU5, "clk_gate_rxu5", "rpgate",101		       0, R_RP_RXU_CLK_ENABLE, 5),102	SG2042_GATE_FW(GATE_CLK_RXU6, "clk_gate_rxu6", "rpgate",103		       0, R_RP_RXU_CLK_ENABLE, 6),104	SG2042_GATE_FW(GATE_CLK_RXU7, "clk_gate_rxu7", "rpgate",105		       0, R_RP_RXU_CLK_ENABLE, 7),106	SG2042_GATE_FW(GATE_CLK_RXU8, "clk_gate_rxu8", "rpgate",107		       0, R_RP_RXU_CLK_ENABLE, 8),108	SG2042_GATE_FW(GATE_CLK_RXU9, "clk_gate_rxu9", "rpgate",109		       0, R_RP_RXU_CLK_ENABLE, 9),110	SG2042_GATE_FW(GATE_CLK_RXU10, "clk_gate_rxu10", "rpgate",111		       0, R_RP_RXU_CLK_ENABLE, 10),112	SG2042_GATE_FW(GATE_CLK_RXU11, "clk_gate_rxu11", "rpgate",113		       0, R_RP_RXU_CLK_ENABLE, 11),114	SG2042_GATE_FW(GATE_CLK_RXU12, "clk_gate_rxu12", "rpgate",115		       0, R_RP_RXU_CLK_ENABLE, 12),116	SG2042_GATE_FW(GATE_CLK_RXU13, "clk_gate_rxu13", "rpgate",117		       0, R_RP_RXU_CLK_ENABLE, 13),118	SG2042_GATE_FW(GATE_CLK_RXU14, "clk_gate_rxu14", "rpgate",119		       0, R_RP_RXU_CLK_ENABLE, 14),120	SG2042_GATE_FW(GATE_CLK_RXU15, "clk_gate_rxu15", "rpgate",121		       0, R_RP_RXU_CLK_ENABLE, 15),122	SG2042_GATE_FW(GATE_CLK_RXU16, "clk_gate_rxu16", "rpgate",123		       0, R_RP_RXU_CLK_ENABLE, 16),124	SG2042_GATE_FW(GATE_CLK_RXU17, "clk_gate_rxu17", "rpgate",125		       0, R_RP_RXU_CLK_ENABLE, 17),126	SG2042_GATE_FW(GATE_CLK_RXU18, "clk_gate_rxu18", "rpgate",127		       0, R_RP_RXU_CLK_ENABLE, 18),128	SG2042_GATE_FW(GATE_CLK_RXU19, "clk_gate_rxu19", "rpgate",129		       0, R_RP_RXU_CLK_ENABLE, 19),130	SG2042_GATE_FW(GATE_CLK_RXU20, "clk_gate_rxu20", "rpgate",131		       0, R_RP_RXU_CLK_ENABLE, 20),132	SG2042_GATE_FW(GATE_CLK_RXU21, "clk_gate_rxu21", "rpgate",133		       0, R_RP_RXU_CLK_ENABLE, 21),134	SG2042_GATE_FW(GATE_CLK_RXU22, "clk_gate_rxu22", "rpgate",135		       0, R_RP_RXU_CLK_ENABLE, 22),136	SG2042_GATE_FW(GATE_CLK_RXU23, "clk_gate_rxu23", "rpgate",137		       0, R_RP_RXU_CLK_ENABLE, 23),138	SG2042_GATE_FW(GATE_CLK_RXU24, "clk_gate_rxu24", "rpgate",139		       0, R_RP_RXU_CLK_ENABLE, 24),140	SG2042_GATE_FW(GATE_CLK_RXU25, "clk_gate_rxu25", "rpgate",141		       0, R_RP_RXU_CLK_ENABLE, 25),142	SG2042_GATE_FW(GATE_CLK_RXU26, "clk_gate_rxu26", "rpgate",143		       0, R_RP_RXU_CLK_ENABLE, 26),144	SG2042_GATE_FW(GATE_CLK_RXU27, "clk_gate_rxu27", "rpgate",145		       0, R_RP_RXU_CLK_ENABLE, 27),146	SG2042_GATE_FW(GATE_CLK_RXU28, "clk_gate_rxu28", "rpgate",147		       0, R_RP_RXU_CLK_ENABLE, 28),148	SG2042_GATE_FW(GATE_CLK_RXU29, "clk_gate_rxu29", "rpgate",149		       0, R_RP_RXU_CLK_ENABLE, 29),150	SG2042_GATE_FW(GATE_CLK_RXU30, "clk_gate_rxu30", "rpgate",151		       0, R_RP_RXU_CLK_ENABLE, 30),152	SG2042_GATE_FW(GATE_CLK_RXU31, "clk_gate_rxu31", "rpgate",153		       0, R_RP_RXU_CLK_ENABLE, 31),154 155	/* downstream of clk_gate_rp_cpu_normal about mp */156	SG2042_GATE_FW(GATE_CLK_MP0, "clk_gate_mp0", "rpgate",157		       CLK_IS_CRITICAL, R_MP0_CONTROL_REG, 0),158	SG2042_GATE_FW(GATE_CLK_MP1, "clk_gate_mp1", "rpgate",159		       CLK_IS_CRITICAL, R_MP1_CONTROL_REG, 0),160	SG2042_GATE_FW(GATE_CLK_MP2, "clk_gate_mp2", "rpgate",161		       CLK_IS_CRITICAL, R_MP2_CONTROL_REG, 0),162	SG2042_GATE_FW(GATE_CLK_MP3, "clk_gate_mp3", "rpgate",163		       CLK_IS_CRITICAL, R_MP3_CONTROL_REG, 0),164	SG2042_GATE_FW(GATE_CLK_MP4, "clk_gate_mp4", "rpgate",165		       CLK_IS_CRITICAL, R_MP4_CONTROL_REG, 0),166	SG2042_GATE_FW(GATE_CLK_MP5, "clk_gate_mp5", "rpgate",167		       CLK_IS_CRITICAL, R_MP5_CONTROL_REG, 0),168	SG2042_GATE_FW(GATE_CLK_MP6, "clk_gate_mp6", "rpgate",169		       CLK_IS_CRITICAL, R_MP6_CONTROL_REG, 0),170	SG2042_GATE_FW(GATE_CLK_MP7, "clk_gate_mp7", "rpgate",171		       CLK_IS_CRITICAL, R_MP7_CONTROL_REG, 0),172	SG2042_GATE_FW(GATE_CLK_MP8, "clk_gate_mp8", "rpgate",173		       CLK_IS_CRITICAL, R_MP8_CONTROL_REG, 0),174	SG2042_GATE_FW(GATE_CLK_MP9, "clk_gate_mp9", "rpgate",175		       CLK_IS_CRITICAL, R_MP9_CONTROL_REG, 0),176	SG2042_GATE_FW(GATE_CLK_MP10, "clk_gate_mp10", "rpgate",177		       CLK_IS_CRITICAL, R_MP10_CONTROL_REG, 0),178	SG2042_GATE_FW(GATE_CLK_MP11, "clk_gate_mp11", "rpgate",179		       CLK_IS_CRITICAL, R_MP11_CONTROL_REG, 0),180	SG2042_GATE_FW(GATE_CLK_MP12, "clk_gate_mp12", "rpgate",181		       CLK_IS_CRITICAL, R_MP12_CONTROL_REG, 0),182	SG2042_GATE_FW(GATE_CLK_MP13, "clk_gate_mp13", "rpgate",183		       CLK_IS_CRITICAL, R_MP13_CONTROL_REG, 0),184	SG2042_GATE_FW(GATE_CLK_MP14, "clk_gate_mp14", "rpgate",185		       CLK_IS_CRITICAL, R_MP14_CONTROL_REG, 0),186	SG2042_GATE_FW(GATE_CLK_MP15, "clk_gate_mp15", "rpgate",187		       CLK_IS_CRITICAL, R_MP15_CONTROL_REG, 0),188};189 190static DEFINE_SPINLOCK(sg2042_clk_lock);191 192static int sg2042_clk_register_rpgates(struct device *dev,193				       struct sg2042_clk_data *clk_data,194				       const struct sg2042_rpgate_clock gate_clks[],195				       int num_gate_clks)196{197	const struct sg2042_rpgate_clock *gate;198	struct clk_hw *hw;199	int i, ret = 0;200 201	for (i = 0; i < num_gate_clks; i++) {202		gate = &gate_clks[i];203		hw = devm_clk_hw_register_gate_parent_data204			(dev,205			 gate->hw.init->name,206			 gate->hw.init->parent_data,207			 gate->hw.init->flags,208			 clk_data->iobase + gate->offset_enable,209			 gate->bit_idx,210			 0,211			 &sg2042_clk_lock);212		if (IS_ERR(hw)) {213			pr_err("failed to register clock %s\n", gate->hw.init->name);214			ret = PTR_ERR(hw);215			break;216		}217 218		clk_data->onecell_data.hws[gate->id] = hw;219	}220 221	return ret;222}223 224static int sg2042_init_clkdata(struct platform_device *pdev,225			       int num_clks,226			       struct sg2042_clk_data **pp_clk_data)227{228	struct sg2042_clk_data *clk_data;229 230	clk_data = devm_kzalloc(&pdev->dev,231				struct_size(clk_data, onecell_data.hws, num_clks),232				GFP_KERNEL);233	if (!clk_data)234		return -ENOMEM;235 236	clk_data->iobase = devm_platform_ioremap_resource(pdev, 0);237	if (WARN_ON(IS_ERR(clk_data->iobase)))238		return PTR_ERR(clk_data->iobase);239 240	clk_data->onecell_data.num = num_clks;241 242	*pp_clk_data = clk_data;243 244	return 0;245}246 247static int sg2042_rpgate_probe(struct platform_device *pdev)248{249	struct sg2042_clk_data *clk_data = NULL;250	int num_clks;251	int ret;252 253	num_clks = ARRAY_SIZE(sg2042_gate_rp);254 255	ret = sg2042_init_clkdata(pdev, num_clks, &clk_data);256	if (ret)257		goto error_out;258 259	ret = sg2042_clk_register_rpgates(&pdev->dev, clk_data, sg2042_gate_rp,260					  num_clks);261	if (ret)262		goto error_out;263 264	return devm_of_clk_add_hw_provider(&pdev->dev,265					   of_clk_hw_onecell_get,266					   &clk_data->onecell_data);267 268error_out:269	pr_err("%s failed error number %d\n", __func__, ret);270	return ret;271}272 273static const struct of_device_id sg2042_rpgate_match[] = {274	{ .compatible = "sophgo,sg2042-rpgate" },275	{ /* sentinel */ }276};277MODULE_DEVICE_TABLE(of, sg2042_rpgate_match);278 279static struct platform_driver sg2042_rpgate_driver = {280	.probe = sg2042_rpgate_probe,281	.driver = {282		.name = "clk-sophgo-sg2042-rpgate",283		.of_match_table = sg2042_rpgate_match,284		.suppress_bind_attrs = true,285	},286};287module_platform_driver(sg2042_rpgate_driver);288 289MODULE_AUTHOR("Chen Wang");290MODULE_DESCRIPTION("Sophgo SG2042 rp subsystem clock driver");291MODULE_LICENSE("GPL");292