File Index
Files and directories
Sign in
FILE

clk-sg2042-clkgen.c

File preview with syntax highlighting.

linux-6.19.14/drivers/clk/sophgo/clk-sg2042-clkgen.c C
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Sophgo SG2042 Clock Generator Driver
   4 *
   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/bits.h>
  11#include <linux/clk.h>
  12#include <linux/clk-provider.h>
  13#include <linux/io.h>
  14#include <linux/platform_device.h>
  15#include <asm/div64.h>
  16
  17#include <dt-bindings/clock/sophgo,sg2042-clkgen.h>
  18
  19#include "clk-sg2042.h"
  20
  21/* Registers defined in SYS_CTRL */
  22#define R_PLL_BEGIN		0xC0
  23#define R_PLL_STAT		(0xC0 - R_PLL_BEGIN)
  24#define R_PLL_CLKEN_CONTROL	(0xC4 - R_PLL_BEGIN)
  25#define R_MPLL_CONTROL		(0xE8 - R_PLL_BEGIN)
  26#define R_FPLL_CONTROL		(0xF4 - R_PLL_BEGIN)
  27#define R_DPLL0_CONTROL		(0xF8 - R_PLL_BEGIN)
  28#define R_DPLL1_CONTROL		(0xFC - R_PLL_BEGIN)
  29
  30/* Registers defined in CLOCK */
  31#define R_CLKENREG0		0x00
  32#define R_CLKENREG1		0x04
  33#define R_CLKSELREG0		0x20
  34#define R_CLKDIVREG0		0x40
  35#define R_CLKDIVREG1		0x44
  36#define R_CLKDIVREG2		0x48
  37#define R_CLKDIVREG3		0x4C
  38#define R_CLKDIVREG4		0x50
  39#define R_CLKDIVREG5		0x54
  40#define R_CLKDIVREG6		0x58
  41#define R_CLKDIVREG7		0x5C
  42#define R_CLKDIVREG8		0x60
  43#define R_CLKDIVREG9		0x64
  44#define R_CLKDIVREG10		0x68
  45#define R_CLKDIVREG11		0x6C
  46#define R_CLKDIVREG12		0x70
  47#define R_CLKDIVREG13		0x74
  48#define R_CLKDIVREG14		0x78
  49#define R_CLKDIVREG15		0x7C
  50#define R_CLKDIVREG16		0x80
  51#define R_CLKDIVREG17		0x84
  52#define R_CLKDIVREG18		0x88
  53#define R_CLKDIVREG19		0x8C
  54#define R_CLKDIVREG20		0x90
  55#define R_CLKDIVREG21		0x94
  56#define R_CLKDIVREG22		0x98
  57#define R_CLKDIVREG23		0x9C
  58#define R_CLKDIVREG24		0xA0
  59#define R_CLKDIVREG25		0xA4
  60#define R_CLKDIVREG26		0xA8
  61#define R_CLKDIVREG27		0xAC
  62#define R_CLKDIVREG28		0xB0
  63#define R_CLKDIVREG29		0xB4
  64#define R_CLKDIVREG30		0xB8
  65
  66/* All following shift value are the same for all DIV registers */
  67#define SHIFT_DIV_RESET_CTRL	0
  68#define SHIFT_DIV_FACTOR_SEL	3
  69#define SHIFT_DIV_FACTOR	16
  70
  71/**
  72 * struct sg2042_divider_clock - Divider clock
  73 * @hw:			clk_hw for initialization
  74 * @id:			used to map clk_onecell_data
  75 * @reg:		used for readl/writel.
  76 *			**NOTE**: DIV registers are ALL in CLOCK!
  77 * @lock:		spinlock to protect register access, modification of
  78 *			frequency can only be served one at the time
  79 * @offset_ctrl:	offset of divider control registers
  80 * @shift:		shift of "Clock Divider Factor" in divider control register
  81 * @width:		width of "Clock Divider Factor" in divider control register
  82 * @div_flags:		private flags for this clock, not for framework-specific
  83 * @initval:		In the divider control register, we can configure whether
  84 *			to use the value of "Clock Divider Factor" or just use
  85 *			the initial value pre-configured by IC. BIT[3] controls
  86 *			this and by default (value is 0), means initial value
  87 *			is used.
  88 *			**NOTE** that we cannot read the initial value (default
  89 *			value when poweron) and default value of "Clock Divider
  90 *			Factor" is zero, which I think is a hardware design flaw
  91 *			and should be sync-ed with the initial value. So in
  92 *			software we have to add a configuration item (initval)
  93 *			to manually configure this value and use it when BIT[3]
  94 *			is zero.
  95 */
  96struct sg2042_divider_clock {
  97	struct clk_hw hw;
  98
  99	unsigned int id;
 100
 101	void __iomem *reg;
 102	/* protect register access */
 103	spinlock_t *lock;
 104
 105	u32 offset_ctrl;
 106	u8 shift;
 107	u8 width;
 108	u8 div_flags;
 109	u32 initval;
 110};
 111
 112#define to_sg2042_clk_divider(_hw)	\
 113	container_of(_hw, struct sg2042_divider_clock, hw)
 114
 115/**
 116 * struct sg2042_gate_clock - Gate clock
 117 * @hw:			clk_hw for initialization
 118 * @id:			used to map clk_onecell_data
 119 * @offset_enable:	offset of gate enable registers
 120 * @bit_idx:		which bit in the register controls gating of this clock
 121 */
 122struct sg2042_gate_clock {
 123	struct clk_hw hw;
 124
 125	unsigned int id;
 126
 127	u32 offset_enable;
 128	u8 bit_idx;
 129};
 130
 131/**
 132 * struct sg2042_mux_clock - Mux clock
 133 * @hw:			clk_hw for initialization
 134 * @id:			used to map clk_onecell_data
 135 * @offset_select:	offset of mux selection registers
 136 *			**NOTE**: MUX registers are ALL in CLOCK!
 137 * @shift:		shift of "Clock Select" in mux selection register
 138 * @width:		width of "Clock Select" in mux selection register
 139 * @clk_nb:		used for notification
 140 * @original_index:	set by notifier callback
 141 */
 142struct sg2042_mux_clock {
 143	struct clk_hw hw;
 144
 145	unsigned int id;
 146
 147	u32 offset_select;
 148	u8 shift;
 149	u8 width;
 150
 151	struct notifier_block clk_nb;
 152	u8 original_index;
 153};
 154
 155#define to_sg2042_mux_nb(_nb) container_of(_nb, struct sg2042_mux_clock, clk_nb)
 156
 157static unsigned long sg2042_clk_divider_recalc_rate(struct clk_hw *hw,
 158						    unsigned long parent_rate)
 159{
 160	struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw);
 161	unsigned long ret_rate;
 162	u32 val;
 163
 164	if (!(readl(divider->reg) & BIT(SHIFT_DIV_FACTOR_SEL))) {
 165		val = divider->initval;
 166	} else {
 167		val = readl(divider->reg) >> divider->shift;
 168		val &= clk_div_mask(divider->width);
 169	}
 170
 171	ret_rate = divider_recalc_rate(hw, parent_rate, val, NULL,
 172				       divider->div_flags, divider->width);
 173
 174	pr_debug("--> %s: divider_recalc_rate: ret_rate = %ld\n",
 175		 clk_hw_get_name(hw), ret_rate);
 176	return ret_rate;
 177}
 178
 179static int sg2042_clk_divider_determine_rate(struct clk_hw *hw,
 180					     struct clk_rate_request *req)
 181{
 182	struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw);
 183	u32 bestdiv;
 184
 185	/* if read only, just return current value */
 186	if (divider->div_flags & CLK_DIVIDER_READ_ONLY) {
 187		if (!(readl(divider->reg) & BIT(SHIFT_DIV_FACTOR_SEL))) {
 188			bestdiv = divider->initval;
 189		} else {
 190			bestdiv = readl(divider->reg) >> divider->shift;
 191			bestdiv &= clk_div_mask(divider->width);
 192		}
 193		req->rate = DIV_ROUND_UP_ULL((u64)req->best_parent_rate, bestdiv);
 194
 195		return 0;
 196	}
 197
 198	return divider_determine_rate(hw, req, NULL, divider->width,
 199				      divider->div_flags);
 200}
 201
 202static int sg2042_clk_divider_set_rate(struct clk_hw *hw,
 203				       unsigned long rate,
 204				       unsigned long parent_rate)
 205{
 206	struct sg2042_divider_clock *divider = to_sg2042_clk_divider(hw);
 207	unsigned long flags = 0;
 208	u32 val, val2, value;
 209
 210	value = divider_get_val(rate, parent_rate, NULL,
 211				divider->width, divider->div_flags);
 212
 213	if (divider->lock)
 214		spin_lock_irqsave(divider->lock, flags);
 215	else
 216		__acquire(divider->lock);
 217
 218	/*
 219	 * The sequence of clock frequency modification is:
 220	 * Assert to reset divider.
 221	 * Modify the value of Clock Divide Factor (and High Wide if needed).
 222	 * De-assert to restore divided clock with new frequency.
 223	 */
 224	val = readl(divider->reg);
 225
 226	/* assert */
 227	val &= ~BIT(SHIFT_DIV_RESET_CTRL);
 228	writel(val, divider->reg);
 229
 230	if (divider->div_flags & CLK_DIVIDER_HIWORD_MASK) {
 231		val = clk_div_mask(divider->width) << (divider->shift + 16);
 232	} else {
 233		val = readl(divider->reg);
 234		val &= ~(clk_div_mask(divider->width) << divider->shift);
 235	}
 236	val |= value << divider->shift;
 237	val |= BIT(SHIFT_DIV_FACTOR_SEL);
 238	writel(val, divider->reg);
 239	val2 = val;
 240
 241	/* de-assert */
 242	val |= BIT(SHIFT_DIV_RESET_CTRL);
 243	writel(val, divider->reg);
 244
 245	if (divider->lock)
 246		spin_unlock_irqrestore(divider->lock, flags);
 247	else
 248		__release(divider->lock);
 249
 250	pr_debug("--> %s: divider_set_rate: register val = 0x%x\n",
 251		 clk_hw_get_name(hw), val2);
 252	return 0;
 253}
 254
 255static const struct clk_ops sg2042_clk_divider_ops = {
 256	.recalc_rate = sg2042_clk_divider_recalc_rate,
 257	.determine_rate = sg2042_clk_divider_determine_rate,
 258	.set_rate = sg2042_clk_divider_set_rate,
 259};
 260
 261static const struct clk_ops sg2042_clk_divider_ro_ops = {
 262	.recalc_rate = sg2042_clk_divider_recalc_rate,
 263	.determine_rate = sg2042_clk_divider_determine_rate,
 264};
 265
 266/*
 267 * Clock initialization macro naming rules:
 268 * FW: use CLK_HW_INIT_FW_NAME
 269 * HW: use CLK_HW_INIT_HW
 270 * HWS: use CLK_HW_INIT_HWS
 271 * RO: means Read-Only
 272 */
 273#define SG2042_DIV_FW(_id, _name, _parent,				\
 274		      _r_ctrl, _shift, _width,				\
 275		      _div_flag, _initval) {				\
 276		.id = _id,						\
 277		.hw.init = CLK_HW_INIT_FW_NAME(				\
 278				_name,					\
 279				_parent,				\
 280				&sg2042_clk_divider_ops,		\
 281				0),					\
 282		.offset_ctrl = _r_ctrl,					\
 283		.shift = _shift,					\
 284		.width = _width,					\
 285		.div_flags = _div_flag,					\
 286		.initval = _initval,					\
 287	}
 288
 289#define SG2042_DIV_FW_RO(_id, _name, _parent,				\
 290		  _r_ctrl, _shift, _width,				\
 291		  _div_flag, _initval) {				\
 292		.id = _id,						\
 293		.hw.init = CLK_HW_INIT_FW_NAME(				\
 294				_name,					\
 295				_parent,				\
 296				&sg2042_clk_divider_ro_ops,		\
 297				0),					\
 298		.offset_ctrl = _r_ctrl,					\
 299		.shift = _shift,					\
 300		.width = _width,					\
 301		.div_flags = (_div_flag) | CLK_DIVIDER_READ_ONLY,	\
 302		.initval = _initval,					\
 303	}
 304
 305#define SG2042_DIV_HW(_id, _name, _parent,				\
 306		      _r_ctrl, _shift, _width,				\
 307		      _div_flag, _initval) {				\
 308		.id = _id,						\
 309		.hw.init = CLK_HW_INIT_HW(				\
 310				_name,					\
 311				_parent,				\
 312				&sg2042_clk_divider_ops,		\
 313				0),					\
 314		.offset_ctrl = _r_ctrl,					\
 315		.shift = _shift,					\
 316		.width = _width,					\
 317		.div_flags = _div_flag,					\
 318		.initval = _initval,					\
 319	}
 320
 321#define SG2042_DIV_HW_RO(_id, _name, _parent,				\
 322			 _r_ctrl, _shift, _width,			\
 323			 _div_flag, _initval) {				\
 324		.id = _id,						\
 325		.hw.init = CLK_HW_INIT_HW(				\
 326				_name,					\
 327				_parent,				\
 328				&sg2042_clk_divider_ro_ops,		\
 329				0),					\
 330		.offset_ctrl = _r_ctrl,					\
 331		.shift = _shift,					\
 332		.width = _width,					\
 333		.div_flags = (_div_flag) | CLK_DIVIDER_READ_ONLY,	\
 334		.initval = _initval,					\
 335	}
 336
 337#define SG2042_DIV_HWS(_id, _name, _parent,				\
 338		       _r_ctrl, _shift, _width,				\
 339		       _div_flag, _initval) {				\
 340		.id = _id,						\
 341		.hw.init = CLK_HW_INIT_HWS(				\
 342				_name,					\
 343				_parent,				\
 344				&sg2042_clk_divider_ops,		\
 345				0),					\
 346		.offset_ctrl = _r_ctrl,					\
 347		.shift = _shift,					\
 348		.width = _width,					\
 349		.div_flags = _div_flag,					\
 350		.initval = _initval,					\
 351	}
 352
 353#define SG2042_DIV_HWS_RO(_id, _name, _parent,				\
 354			  _r_ctrl, _shift, _width,			\
 355			  _div_flag, _initval) {			\
 356		.id = _id,						\
 357		.hw.init = CLK_HW_INIT_HWS(				\
 358				_name,					\
 359				_parent,				\
 360				&sg2042_clk_divider_ro_ops,		\
 361				0),					\
 362		.offset_ctrl = _r_ctrl,					\
 363		.shift = _shift,					\
 364		.width = _width,					\
 365		.div_flags = (_div_flag) | CLK_DIVIDER_READ_ONLY,	\
 366		.initval = _initval,					\
 367	}
 368
 369#define SG2042_GATE_HWS(_id, _name, _parent, _flags,	\
 370			_r_enable, _bit_idx) {		\
 371		.id = _id,				\
 372		.hw.init = CLK_HW_INIT_HWS(		\
 373				_name,			\
 374				_parent,		\
 375				NULL,			\
 376				_flags),		\
 377		.offset_enable = _r_enable,		\
 378		.bit_idx = _bit_idx,			\
 379	}
 380
 381#define SG2042_GATE_HW(_id, _name, _parent, _flags,	\
 382		       _r_enable, _bit_idx) {		\
 383		.id = _id,				\
 384		.hw.init = CLK_HW_INIT_HW(		\
 385				_name,			\
 386				_parent,		\
 387				NULL,			\
 388				_flags),		\
 389		.offset_enable = _r_enable,		\
 390		.bit_idx = _bit_idx,			\
 391	}
 392
 393#define SG2042_GATE_FW(_id, _name, _parent, _flags,	\
 394		       _r_enable, _bit_idx) {		\
 395		.id = _id,				\
 396		.hw.init = CLK_HW_INIT_FW_NAME(		\
 397				_name,			\
 398				_parent,		\
 399				NULL,			\
 400				_flags),		\
 401		.offset_enable = _r_enable,		\
 402		.bit_idx = _bit_idx,			\
 403	}
 404
 405#define SG2042_MUX(_id, _name, _parents, _flags, _r_select, _shift, _width) { \
 406		.id = _id,					\
 407		.hw.init = CLK_HW_INIT_PARENTS_HW(		\
 408				_name,				\
 409				_parents,			\
 410				NULL,				\
 411				_flags),			\
 412		.offset_select = _r_select,			\
 413		.shift = _shift,				\
 414		.width = _width,				\
 415	}
 416
 417/*
 418 * Clock items in the array are sorted according to the clock-tree diagram,
 419 * from top to bottom, from upstream to downstream. Read TRM for details.
 420 */
 421
 422/* updated during probe/registration */
 423static const struct clk_hw *clk_gate_ddr01_div0[] = { NULL };
 424static const struct clk_hw *clk_gate_ddr01_div1[] = { NULL };
 425static const struct clk_hw *clk_gate_ddr23_div0[] = { NULL };
 426static const struct clk_hw *clk_gate_ddr23_div1[] = { NULL };
 427static const struct clk_hw *clk_gate_rp_cpu_normal_div0[] = { NULL };
 428static const struct clk_hw *clk_gate_rp_cpu_normal_div1[] = { NULL };
 429static const struct clk_hw *clk_gate_axi_ddr_div0[] = { NULL };
 430static const struct clk_hw *clk_gate_axi_ddr_div1[] = { NULL };
 431
 432static const struct sg2042_gate_clock sg2042_gate_clks_level_1[] = {
 433	SG2042_GATE_FW(GATE_CLK_DDR01_DIV0, "clk_gate_ddr01_div0", "dpll0",
 434		       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
 435		       R_CLKDIVREG27, 4),
 436	SG2042_GATE_FW(GATE_CLK_DDR01_DIV1, "clk_gate_ddr01_div1", "fpll",
 437		       CLK_IS_CRITICAL,
 438		       R_CLKDIVREG28, 4),
 439
 440	SG2042_GATE_FW(GATE_CLK_DDR23_DIV0, "clk_gate_ddr23_div0", "dpll1",
 441		       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
 442		       R_CLKDIVREG29, 4),
 443	SG2042_GATE_FW(GATE_CLK_DDR23_DIV1, "clk_gate_ddr23_div1", "fpll",
 444		       CLK_IS_CRITICAL,
 445		       R_CLKDIVREG30, 4),
 446
 447	SG2042_GATE_FW(GATE_CLK_RP_CPU_NORMAL_DIV0,
 448		       "clk_gate_rp_cpu_normal_div0", "mpll",
 449		       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
 450		       R_CLKDIVREG0, 4),
 451	SG2042_GATE_FW(GATE_CLK_RP_CPU_NORMAL_DIV1,
 452		       "clk_gate_rp_cpu_normal_div1", "fpll",
 453		       CLK_IS_CRITICAL,
 454		       R_CLKDIVREG1, 4),
 455
 456	SG2042_GATE_FW(GATE_CLK_AXI_DDR_DIV0, "clk_gate_axi_ddr_div0", "mpll",
 457		       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
 458		       R_CLKDIVREG25, 4),
 459	SG2042_GATE_FW(GATE_CLK_AXI_DDR_DIV1, "clk_gate_axi_ddr_div1", "fpll",
 460		       CLK_IS_CRITICAL,
 461		       R_CLKDIVREG26, 4),
 462};
 463
 464#define DEF_DIVFLAG (CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO)
 465
 466static struct sg2042_divider_clock sg2042_div_clks_level_1[] = {
 467	SG2042_DIV_HWS_RO(DIV_CLK_DPLL0_DDR01_0,
 468			  "clk_div_ddr01_0", clk_gate_ddr01_div0,
 469			  R_CLKDIVREG27, 16, 5, DEF_DIVFLAG, 1),
 470	SG2042_DIV_HWS_RO(DIV_CLK_FPLL_DDR01_1,
 471			  "clk_div_ddr01_1", clk_gate_ddr01_div1,
 472			  R_CLKDIVREG28, 16, 5, DEF_DIVFLAG, 1),
 473
 474	SG2042_DIV_HWS_RO(DIV_CLK_DPLL1_DDR23_0,
 475			  "clk_div_ddr23_0", clk_gate_ddr23_div0,
 476			  R_CLKDIVREG29, 16, 5, DEF_DIVFLAG, 1),
 477	SG2042_DIV_HWS_RO(DIV_CLK_FPLL_DDR23_1,
 478			  "clk_div_ddr23_1", clk_gate_ddr23_div1,
 479			  R_CLKDIVREG30, 16, 5, DEF_DIVFLAG, 1),
 480
 481	SG2042_DIV_HWS(DIV_CLK_MPLL_RP_CPU_NORMAL_0,
 482		       "clk_div_rp_cpu_normal_0", clk_gate_rp_cpu_normal_div0,
 483		       R_CLKDIVREG0, 16, 5, DEF_DIVFLAG, 1),
 484	SG2042_DIV_HWS(DIV_CLK_FPLL_RP_CPU_NORMAL_1,
 485		       "clk_div_rp_cpu_normal_1", clk_gate_rp_cpu_normal_div1,
 486		       R_CLKDIVREG1, 16, 5, DEF_DIVFLAG, 1),
 487
 488	SG2042_DIV_HWS(DIV_CLK_MPLL_AXI_DDR_0,
 489		       "clk_div_axi_ddr_0", clk_gate_axi_ddr_div0,
 490		       R_CLKDIVREG25, 16, 5, DEF_DIVFLAG, 2),
 491	SG2042_DIV_HWS(DIV_CLK_FPLL_AXI_DDR_1,
 492		       "clk_div_axi_ddr_1", clk_gate_axi_ddr_div1,
 493		       R_CLKDIVREG26, 16, 5, DEF_DIVFLAG, 1),
 494};
 495
 496/*
 497 * Note: regarding names for mux clock, "0/1" or "div0/div1" means the
 498 * first/second parent input source, not the register value.
 499 * For example:
 500 * "clk_div_ddr01_0" is the name of Clock divider 0 control of DDR01, and
 501 * "clk_gate_ddr01_div0" is the gate clock in front of the "clk_div_ddr01_0",
 502 * they are both controlled by register CLKDIVREG27;
 503 * "clk_div_ddr01_1" is the name of Clock divider 1 control of DDR01, and
 504 * "clk_gate_ddr01_div1" is the gate clock in front of the "clk_div_ddr01_1",
 505 * they are both controlled by register CLKDIVREG28;
 506 * While for register value of mux selection, use Clock Select for DDR01’s clock
 507 * as example, see CLKSELREG0, bit[2].
 508 * 1: Select in_dpll0_clk as clock source, correspondng to the parent input
 509 *    source from "clk_div_ddr01_0".
 510 * 0: Select in_fpll_clk as clock source, corresponding to the parent input
 511 *    source from "clk_div_ddr01_1".
 512 * So we need a table to define the array of register values corresponding to
 513 * the parent index and tell CCF about this when registering mux clock.
 514 */
 515static const u32 sg2042_mux_table[] = {1, 0};
 516
 517/* Aliases just for easy reading */
 518#define clk_div_ddr01_0		(&sg2042_div_clks_level_1[0].hw)
 519#define clk_div_ddr01_1		(&sg2042_div_clks_level_1[1].hw)
 520#define clk_div_ddr23_0		(&sg2042_div_clks_level_1[2].hw)
 521#define clk_div_ddr23_1		(&sg2042_div_clks_level_1[3].hw)
 522#define clk_div_rp_cpu_normal_0	(&sg2042_div_clks_level_1[4].hw)
 523#define clk_div_rp_cpu_normal_1	(&sg2042_div_clks_level_1[5].hw)
 524#define clk_div_axi_ddr_0	(&sg2042_div_clks_level_1[6].hw)
 525#define clk_div_axi_ddr_1	(&sg2042_div_clks_level_1[7].hw)
 526
 527static const struct clk_hw *clk_mux_ddr01_p[] = {
 528	clk_div_ddr01_0,
 529	clk_div_ddr01_1,
 530};
 531
 532static const struct clk_hw *clk_mux_ddr23_p[] = {
 533	clk_div_ddr23_0,
 534	clk_div_ddr23_1,
 535};
 536
 537static const struct clk_hw *clk_mux_rp_cpu_normal_p[] = {
 538	clk_div_rp_cpu_normal_0,
 539	clk_div_rp_cpu_normal_1,
 540};
 541
 542static const struct clk_hw *clk_mux_axi_ddr_p[] = {
 543	clk_div_axi_ddr_0,
 544	clk_div_axi_ddr_1,
 545};
 546
 547/* Mux clocks to be updated during probe/registration */
 548static const struct clk_hw *clk_mux_ddr01[] = { NULL };
 549static const struct clk_hw *clk_mux_ddr23[] = { NULL };
 550static const struct clk_hw *clk_mux_rp_cpu_normal[] = { NULL };
 551static const struct clk_hw *clk_mux_axi_ddr[] = { NULL };
 552
 553static struct sg2042_mux_clock sg2042_mux_clks[] = {
 554	SG2042_MUX(MUX_CLK_DDR01, "clk_mux_ddr01", clk_mux_ddr01_p,
 555		   CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT | CLK_MUX_READ_ONLY,
 556		   R_CLKSELREG0, 2, 1),
 557	SG2042_MUX(MUX_CLK_DDR23, "clk_mux_ddr23", clk_mux_ddr23_p,
 558		   CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT | CLK_MUX_READ_ONLY,
 559		   R_CLKSELREG0, 3, 1),
 560	SG2042_MUX(MUX_CLK_RP_CPU_NORMAL, "clk_mux_rp_cpu_normal", clk_mux_rp_cpu_normal_p,
 561		   CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
 562		   R_CLKSELREG0, 0, 1),
 563	SG2042_MUX(MUX_CLK_AXI_DDR, "clk_mux_axi_ddr", clk_mux_axi_ddr_p,
 564		   CLK_SET_RATE_PARENT | CLK_SET_RATE_NO_REPARENT,
 565		   R_CLKSELREG0, 1, 1),
 566};
 567
 568/* Aliases just for easy reading */
 569#define clk_div_top_rp_cmn_div2	(&sg2042_div_clks_level_2[0].hw)
 570#define clk_div_50m_a53		(&sg2042_div_clks_level_2[1].hw)
 571#define clk_div_timer1		(&sg2042_div_clks_level_2[2].hw)
 572#define clk_div_timer2		(&sg2042_div_clks_level_2[3].hw)
 573#define clk_div_timer3		(&sg2042_div_clks_level_2[4].hw)
 574#define clk_div_timer4		(&sg2042_div_clks_level_2[5].hw)
 575#define clk_div_timer5		(&sg2042_div_clks_level_2[6].hw)
 576#define clk_div_timer6		(&sg2042_div_clks_level_2[7].hw)
 577#define clk_div_timer7		(&sg2042_div_clks_level_2[8].hw)
 578#define clk_div_timer8		(&sg2042_div_clks_level_2[9].hw)
 579#define clk_div_uart_500m	(&sg2042_div_clks_level_2[10].hw)
 580#define clk_div_ahb_lpc		(&sg2042_div_clks_level_2[11].hw)
 581#define clk_div_efuse		(&sg2042_div_clks_level_2[12].hw)
 582#define clk_div_tx_eth0		(&sg2042_div_clks_level_2[13].hw)
 583#define clk_div_ptp_ref_i_eth0	(&sg2042_div_clks_level_2[14].hw)
 584#define clk_div_ref_eth0	(&sg2042_div_clks_level_2[15].hw)
 585#define clk_div_emmc		(&sg2042_div_clks_level_2[16].hw)
 586#define clk_div_sd		(&sg2042_div_clks_level_2[17].hw)
 587#define clk_div_top_axi0	(&sg2042_div_clks_level_2[18].hw)
 588#define clk_div_100k_emmc	(&sg2042_div_clks_level_2[19].hw)
 589#define clk_div_100k_sd		(&sg2042_div_clks_level_2[20].hw)
 590#define clk_div_gpio_db		(&sg2042_div_clks_level_2[21].hw)
 591#define clk_div_top_axi_hsperi	(&sg2042_div_clks_level_2[22].hw)
 592
 593static struct sg2042_divider_clock sg2042_div_clks_level_2[] = {
 594	SG2042_DIV_HWS(DIV_CLK_FPLL_TOP_RP_CMN_DIV2,
 595		       "clk_div_top_rp_cmn_div2", clk_mux_rp_cpu_normal,
 596		       R_CLKDIVREG3, 16, 16, DEF_DIVFLAG, 2),
 597
 598	SG2042_DIV_FW(DIV_CLK_FPLL_50M_A53, "clk_div_50m_a53", "fpll",
 599		      R_CLKDIVREG2, 16, 8, DEF_DIVFLAG, 20),
 600	/* downstream of div_50m_a53 */
 601	SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER1, "clk_div_timer1", clk_div_50m_a53,
 602		      R_CLKDIVREG6, 16, 16, DEF_DIVFLAG, 1),
 603	SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER2, "clk_div_timer2", clk_div_50m_a53,
 604		      R_CLKDIVREG7, 16, 16, DEF_DIVFLAG, 1),
 605	SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER3, "clk_div_timer3", clk_div_50m_a53,
 606		      R_CLKDIVREG8, 16, 16, DEF_DIVFLAG, 1),
 607	SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER4, "clk_div_timer4", clk_div_50m_a53,
 608		      R_CLKDIVREG9, 16, 16, DEF_DIVFLAG, 1),
 609	SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER5, "clk_div_timer5", clk_div_50m_a53,
 610		      R_CLKDIVREG10, 16, 16, DEF_DIVFLAG, 1),
 611	SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER6, "clk_div_timer6", clk_div_50m_a53,
 612		      R_CLKDIVREG11, 16, 16, DEF_DIVFLAG, 1),
 613	SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER7, "clk_div_timer7", clk_div_50m_a53,
 614		      R_CLKDIVREG12, 16, 16, DEF_DIVFLAG, 1),
 615	SG2042_DIV_HW(DIV_CLK_FPLL_DIV_TIMER8, "clk_div_timer8", clk_div_50m_a53,
 616		      R_CLKDIVREG13, 16, 16, DEF_DIVFLAG, 1),
 617
 618	/*
 619	 * Set clk_div_uart_500m as RO, because the width of CLKDIVREG4 is too
 620	 * narrow for us to produce 115200. Use UART internal divider directly.
 621	 */
 622	SG2042_DIV_FW_RO(DIV_CLK_FPLL_UART_500M, "clk_div_uart_500m", "fpll",
 623			 R_CLKDIVREG4, 16, 7, DEF_DIVFLAG, 2),
 624	SG2042_DIV_FW(DIV_CLK_FPLL_AHB_LPC, "clk_div_ahb_lpc", "fpll",
 625		      R_CLKDIVREG5, 16, 16, DEF_DIVFLAG, 5),
 626	SG2042_DIV_FW(DIV_CLK_FPLL_EFUSE, "clk_div_efuse", "fpll",
 627		      R_CLKDIVREG14, 16, 7, DEF_DIVFLAG, 40),
 628	SG2042_DIV_FW(DIV_CLK_FPLL_TX_ETH0, "clk_div_tx_eth0", "fpll",
 629		      R_CLKDIVREG16, 16, 11, DEF_DIVFLAG, 8),
 630	SG2042_DIV_FW(DIV_CLK_FPLL_PTP_REF_I_ETH0,
 631		      "clk_div_ptp_ref_i_eth0", "fpll",
 632		      R_CLKDIVREG17, 16, 8, DEF_DIVFLAG, 20),
 633	SG2042_DIV_FW(DIV_CLK_FPLL_REF_ETH0, "clk_div_ref_eth0", "fpll",
 634		      R_CLKDIVREG18, 16, 8, DEF_DIVFLAG, 40),
 635	SG2042_DIV_FW(DIV_CLK_FPLL_EMMC, "clk_div_emmc", "fpll",
 636		      R_CLKDIVREG19, 16, 5, DEF_DIVFLAG, 10),
 637	SG2042_DIV_FW(DIV_CLK_FPLL_SD, "clk_div_sd", "fpll",
 638		      R_CLKDIVREG21, 16, 5, DEF_DIVFLAG, 10),
 639
 640	SG2042_DIV_FW(DIV_CLK_FPLL_TOP_AXI0, "clk_div_top_axi0", "fpll",
 641		      R_CLKDIVREG23, 16, 5, DEF_DIVFLAG, 10),
 642	/* downstream of div_top_axi0 */
 643	SG2042_DIV_HW(DIV_CLK_FPLL_100K_EMMC, "clk_div_100k_emmc", clk_div_top_axi0,
 644		      R_CLKDIVREG20, 16, 16, DEF_DIVFLAG, 1000),
 645	SG2042_DIV_HW(DIV_CLK_FPLL_100K_SD, "clk_div_100k_sd", clk_div_top_axi0,
 646		      R_CLKDIVREG22, 16, 16, DEF_DIVFLAG, 1000),
 647	SG2042_DIV_HW(DIV_CLK_FPLL_GPIO_DB, "clk_div_gpio_db", clk_div_top_axi0,
 648		      R_CLKDIVREG15, 16, 16, DEF_DIVFLAG, 1000),
 649
 650	SG2042_DIV_FW(DIV_CLK_FPLL_TOP_AXI_HSPERI,
 651		      "clk_div_top_axi_hsperi", "fpll",
 652		      R_CLKDIVREG24, 16, 5, DEF_DIVFLAG, 4),
 653};
 654
 655/* Gate clocks to be updated during probe/registration */
 656static const struct clk_hw *clk_gate_rp_cpu_normal[] = { NULL };
 657static const struct clk_hw *clk_gate_top_rp_cmn_div2[] = { NULL };
 658
 659static const struct sg2042_gate_clock sg2042_gate_clks_level_2[] = {
 660	SG2042_GATE_HWS(GATE_CLK_DDR01, "clk_gate_ddr01", clk_mux_ddr01,
 661			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
 662			R_CLKENREG1, 14),
 663
 664	SG2042_GATE_HWS(GATE_CLK_DDR23, "clk_gate_ddr23", clk_mux_ddr23,
 665			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
 666			R_CLKENREG1, 15),
 667
 668	SG2042_GATE_HWS(GATE_CLK_RP_CPU_NORMAL,
 669			"clk_gate_rp_cpu_normal", clk_mux_rp_cpu_normal,
 670			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
 671			R_CLKENREG0, 0),
 672
 673	SG2042_GATE_HWS(GATE_CLK_AXI_DDR, "clk_gate_axi_ddr", clk_mux_axi_ddr,
 674			CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
 675			R_CLKENREG1, 13),
 676
 677	/* upon are gate clocks directly downstream of muxes */
 678
 679	/* downstream of clk_div_top_rp_cmn_div2 */
 680	SG2042_GATE_HW(GATE_CLK_TOP_RP_CMN_DIV2,
 681		       "clk_gate_top_rp_cmn_div2", clk_div_top_rp_cmn_div2,
 682		       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 2),
 683	SG2042_GATE_HWS(GATE_CLK_HSDMA, "clk_gate_hsdma", clk_gate_top_rp_cmn_div2,
 684			CLK_SET_RATE_PARENT, R_CLKENREG1, 10),
 685
 686	/*
 687	 * downstream of clk_gate_rp_cpu_normal
 688	 *
 689	 * FIXME: there should be one 1/2 DIV between clk_gate_rp_cpu_normal
 690	 * and clk_gate_axi_pcie0/clk_gate_axi_pcie1.
 691	 * But the 1/2 DIV is fixed and no configurable register exported, so
 692	 * when reading from these two clocks, the rate value are still the
 693	 * same as that of clk_gate_rp_cpu_normal, it's not correct.
 694	 * This just affects the value read.
 695	 */
 696	SG2042_GATE_HWS(GATE_CLK_AXI_PCIE0,
 697			"clk_gate_axi_pcie0", clk_gate_rp_cpu_normal,
 698			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG1, 8),
 699	SG2042_GATE_HWS(GATE_CLK_AXI_PCIE1,
 700			"clk_gate_axi_pcie1", clk_gate_rp_cpu_normal,
 701			CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG1, 9),
 702
 703	/* downstream of div_50m_a53 */
 704	SG2042_GATE_HW(GATE_CLK_A53_50M, "clk_gate_a53_50m", clk_div_50m_a53,
 705		       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 1),
 706	SG2042_GATE_HW(GATE_CLK_TIMER1, "clk_gate_timer1", clk_div_timer1,
 707		       CLK_SET_RATE_PARENT, R_CLKENREG0, 12),
 708	SG2042_GATE_HW(GATE_CLK_TIMER2, "clk_gate_timer2", clk_div_timer2,
 709		       CLK_SET_RATE_PARENT, R_CLKENREG0, 13),
 710	SG2042_GATE_HW(GATE_CLK_TIMER3, "clk_gate_timer3", clk_div_timer3,
 711		       CLK_SET_RATE_PARENT, R_CLKENREG0, 14),
 712	SG2042_GATE_HW(GATE_CLK_TIMER4, "clk_gate_timer4", clk_div_timer4,
 713		       CLK_SET_RATE_PARENT, R_CLKENREG0, 15),
 714	SG2042_GATE_HW(GATE_CLK_TIMER5, "clk_gate_timer5", clk_div_timer5,
 715		       CLK_SET_RATE_PARENT, R_CLKENREG0, 16),
 716	SG2042_GATE_HW(GATE_CLK_TIMER6, "clk_gate_timer6", clk_div_timer6,
 717		       CLK_SET_RATE_PARENT, R_CLKENREG0, 17),
 718	SG2042_GATE_HW(GATE_CLK_TIMER7, "clk_gate_timer7", clk_div_timer7,
 719		       CLK_SET_RATE_PARENT, R_CLKENREG0, 18),
 720	SG2042_GATE_HW(GATE_CLK_TIMER8, "clk_gate_timer8", clk_div_timer8,
 721		       CLK_SET_RATE_PARENT, R_CLKENREG0, 19),
 722
 723	/* gate clocks downstream from div clocks one-to-one */
 724	SG2042_GATE_HW(GATE_CLK_UART_500M, "clk_gate_uart_500m", clk_div_uart_500m,
 725		       CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED, R_CLKENREG0, 4),
 726	SG2042_GATE_HW(GATE_CLK_AHB_LPC, "clk_gate_ahb_lpc", clk_div_ahb_lpc,
 727		       CLK_SET_RATE_PARENT, R_CLKENREG0, 7),
 728	SG2042_GATE_HW(GATE_CLK_EFUSE, "clk_gate_efuse", clk_div_efuse,
 729		       CLK_SET_RATE_PARENT, R_CLKENREG0, 20),
 730	SG2042_GATE_HW(GATE_CLK_TX_ETH0, "clk_gate_tx_eth0", clk_div_tx_eth0,
 731		       CLK_SET_RATE_PARENT, R_CLKENREG0, 30),
 732	SG2042_GATE_HW(GATE_CLK_PTP_REF_I_ETH0,
 733		       "clk_gate_ptp_ref_i_eth0", clk_div_ptp_ref_i_eth0,
 734		       CLK_SET_RATE_PARENT, R_CLKENREG1, 0),
 735	SG2042_GATE_HW(GATE_CLK_REF_ETH0, "clk_gate_ref_eth0", clk_div_ref_eth0,
 736		       CLK_SET_RATE_PARENT, R_CLKENREG1, 1),
 737	SG2042_GATE_HW(GATE_CLK_EMMC_100M, "clk_gate_emmc", clk_div_emmc,
 738		       CLK_SET_RATE_PARENT, R_CLKENREG1, 3),
 739	SG2042_GATE_HW(GATE_CLK_SD_100M, "clk_gate_sd", clk_div_sd,
 740		       CLK_SET_RATE_PARENT, R_CLKENREG1, 6),
 741
 742	/* downstream of clk_div_top_axi0 */
 743	SG2042_GATE_HW(GATE_CLK_AHB_ROM, "clk_gate_ahb_rom", clk_div_top_axi0,
 744		       0, R_CLKENREG0, 8),
 745	SG2042_GATE_HW(GATE_CLK_AHB_SF, "clk_gate_ahb_sf", clk_div_top_axi0,
 746		       0, R_CLKENREG0, 9),
 747	SG2042_GATE_HW(GATE_CLK_AXI_SRAM, "clk_gate_axi_sram", clk_div_top_axi0,
 748		       CLK_IGNORE_UNUSED, R_CLKENREG0, 10),
 749	SG2042_GATE_HW(GATE_CLK_APB_TIMER, "clk_gate_apb_timer", clk_div_top_axi0,
 750		       CLK_IGNORE_UNUSED, R_CLKENREG0, 11),
 751	SG2042_GATE_HW(GATE_CLK_APB_EFUSE, "clk_gate_apb_efuse", clk_div_top_axi0,
 752		       0, R_CLKENREG0, 21),
 753	SG2042_GATE_HW(GATE_CLK_APB_GPIO, "clk_gate_apb_gpio", clk_div_top_axi0,
 754		       0, R_CLKENREG0, 22),
 755	SG2042_GATE_HW(GATE_CLK_APB_GPIO_INTR,
 756		       "clk_gate_apb_gpio_intr", clk_div_top_axi0,
 757		       CLK_IS_CRITICAL, R_CLKENREG0, 23),
 758	SG2042_GATE_HW(GATE_CLK_APB_I2C, "clk_gate_apb_i2c", clk_div_top_axi0,
 759		       0, R_CLKENREG0, 26),
 760	SG2042_GATE_HW(GATE_CLK_APB_WDT, "clk_gate_apb_wdt", clk_div_top_axi0,
 761		       0, R_CLKENREG0, 27),
 762	SG2042_GATE_HW(GATE_CLK_APB_PWM, "clk_gate_apb_pwm", clk_div_top_axi0,
 763		       0, R_CLKENREG0, 28),
 764	SG2042_GATE_HW(GATE_CLK_APB_RTC, "clk_gate_apb_rtc", clk_div_top_axi0,
 765		       0, R_CLKENREG0, 29),
 766	SG2042_GATE_HW(GATE_CLK_TOP_AXI0, "clk_gate_top_axi0", clk_div_top_axi0,
 767		       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
 768		       R_CLKENREG1, 11),
 769	/* downstream of DIV clocks which are sourced from clk_div_top_axi0 */
 770	SG2042_GATE_HW(GATE_CLK_GPIO_DB, "clk_gate_gpio_db", clk_div_gpio_db,
 771		       CLK_SET_RATE_PARENT, R_CLKENREG0, 24),
 772	SG2042_GATE_HW(GATE_CLK_100K_EMMC, "clk_gate_100k_emmc", clk_div_100k_emmc,
 773		       CLK_SET_RATE_PARENT, R_CLKENREG1, 4),
 774	SG2042_GATE_HW(GATE_CLK_100K_SD, "clk_gate_100k_sd", clk_div_100k_sd,
 775		       CLK_SET_RATE_PARENT, R_CLKENREG1, 7),
 776
 777	/* downstream of clk_div_top_axi_hsperi */
 778	SG2042_GATE_HW(GATE_CLK_SYSDMA_AXI,
 779		       "clk_gate_sysdma_axi", clk_div_top_axi_hsperi,
 780		       CLK_SET_RATE_PARENT, R_CLKENREG0, 3),
 781	SG2042_GATE_HW(GATE_CLK_APB_UART,
 782		       "clk_gate_apb_uart", clk_div_top_axi_hsperi,
 783		       CLK_SET_RATE_PARENT, R_CLKENREG0, 5),
 784	SG2042_GATE_HW(GATE_CLK_AXI_DBG_I2C,
 785		       "clk_gate_axi_dbg_i2c", clk_div_top_axi_hsperi,
 786		       CLK_SET_RATE_PARENT, R_CLKENREG0, 6),
 787	SG2042_GATE_HW(GATE_CLK_APB_SPI,
 788		       "clk_gate_apb_spi", clk_div_top_axi_hsperi,
 789		       CLK_SET_RATE_PARENT, R_CLKENREG0, 25),
 790	SG2042_GATE_HW(GATE_CLK_AXI_ETH0,
 791		       "clk_gate_axi_eth0", clk_div_top_axi_hsperi,
 792		       CLK_SET_RATE_PARENT, R_CLKENREG0, 31),
 793	SG2042_GATE_HW(GATE_CLK_AXI_EMMC,
 794		       "clk_gate_axi_emmc", clk_div_top_axi_hsperi,
 795		       CLK_SET_RATE_PARENT, R_CLKENREG1, 2),
 796	SG2042_GATE_HW(GATE_CLK_AXI_SD,
 797		       "clk_gate_axi_sd", clk_div_top_axi_hsperi,
 798		       CLK_SET_RATE_PARENT, R_CLKENREG1, 5),
 799	SG2042_GATE_HW(GATE_CLK_TOP_AXI_HSPERI,
 800		       "clk_gate_top_axi_hsperi", clk_div_top_axi_hsperi,
 801		       CLK_SET_RATE_PARENT | CLK_IS_CRITICAL,
 802		       R_CLKENREG1, 12),
 803};
 804
 805static DEFINE_SPINLOCK(sg2042_clk_lock);
 806
 807static int sg2042_clk_register_divs(struct device *dev,
 808				    struct sg2042_clk_data *clk_data,
 809				    struct sg2042_divider_clock div_clks[],
 810				    int num_div_clks)
 811{
 812	struct sg2042_divider_clock *div;
 813	struct clk_hw *hw;
 814	int i, ret = 0;
 815
 816	for (i = 0; i < num_div_clks; i++) {
 817		div = &div_clks[i];
 818
 819		if (div->div_flags & CLK_DIVIDER_HIWORD_MASK) {
 820			if (div->width + div->shift > 16) {
 821				pr_warn("divider value exceeds LOWORD field\n");
 822				ret = -EINVAL;
 823				break;
 824			}
 825		}
 826
 827		div->reg = clk_data->iobase + div->offset_ctrl;
 828		div->lock = &sg2042_clk_lock;
 829
 830		hw = &div->hw;
 831		ret = devm_clk_hw_register(dev, hw);
 832		if (ret) {
 833			pr_err("failed to register clock %s\n", div->hw.init->name);
 834			break;
 835		}
 836
 837		clk_data->onecell_data.hws[div->id] = hw;
 838	}
 839
 840	return ret;
 841}
 842
 843static int sg2042_clk_register_gates(struct device *dev,
 844				     struct sg2042_clk_data *clk_data,
 845				     const struct sg2042_gate_clock gate_clks[],
 846				     int num_gate_clks)
 847{
 848	const struct sg2042_gate_clock *gate;
 849	struct clk_hw *hw;
 850	int i, ret = 0;
 851
 852	for (i = 0; i < num_gate_clks; i++) {
 853		gate = &gate_clks[i];
 854		hw = __devm_clk_hw_register_gate
 855			(dev,
 856			 NULL,
 857			 gate->hw.init->name,
 858			 NULL,
 859			 gate->hw.init->parent_hws[0],
 860			 NULL,
 861			 gate->hw.init->flags,
 862			 clk_data->iobase + gate->offset_enable,
 863			 gate->bit_idx,
 864			 0,
 865			 &sg2042_clk_lock);
 866		if (IS_ERR(hw)) {
 867			pr_err("failed to register clock %s\n", gate->hw.init->name);
 868			ret = PTR_ERR(hw);
 869			break;
 870		}
 871
 872		clk_data->onecell_data.hws[gate->id] = hw;
 873
 874		/* Updated some clocks which take the role of parent */
 875		switch (gate->id) {
 876		case GATE_CLK_RP_CPU_NORMAL:
 877			*clk_gate_rp_cpu_normal = hw;
 878			break;
 879		case GATE_CLK_TOP_RP_CMN_DIV2:
 880			*clk_gate_top_rp_cmn_div2 = hw;
 881			break;
 882		}
 883	}
 884
 885	return ret;
 886}
 887
 888static int sg2042_clk_register_gates_fw(struct device *dev,
 889					struct sg2042_clk_data *clk_data,
 890					const struct sg2042_gate_clock gate_clks[],
 891					int num_gate_clks)
 892{
 893	const struct sg2042_gate_clock *gate;
 894	struct clk_hw *hw;
 895	int i, ret = 0;
 896
 897	for (i = 0; i < num_gate_clks; i++) {
 898		gate = &gate_clks[i];
 899		hw = devm_clk_hw_register_gate_parent_data
 900			(dev,
 901			 gate->hw.init->name,
 902			 gate->hw.init->parent_data,
 903			 gate->hw.init->flags,
 904			 clk_data->iobase + gate->offset_enable,
 905			 gate->bit_idx,
 906			 0,
 907			 &sg2042_clk_lock);
 908		if (IS_ERR(hw)) {
 909			pr_err("failed to register clock %s\n", gate->hw.init->name);
 910			ret = PTR_ERR(hw);
 911			break;
 912		}
 913
 914		clk_data->onecell_data.hws[gate->id] = hw;
 915
 916		/* Updated some clocks which take the role of parent */
 917		switch (gate->id) {
 918		case GATE_CLK_DDR01_DIV0:
 919			*clk_gate_ddr01_div0 = hw;
 920			break;
 921		case GATE_CLK_DDR01_DIV1:
 922			*clk_gate_ddr01_div1 = hw;
 923			break;
 924		case GATE_CLK_DDR23_DIV0:
 925			*clk_gate_ddr23_div0 = hw;
 926			break;
 927		case GATE_CLK_DDR23_DIV1:
 928			*clk_gate_ddr23_div1 = hw;
 929			break;
 930		case GATE_CLK_RP_CPU_NORMAL_DIV0:
 931			*clk_gate_rp_cpu_normal_div0 = hw;
 932			break;
 933		case GATE_CLK_RP_CPU_NORMAL_DIV1:
 934			*clk_gate_rp_cpu_normal_div1 = hw;
 935			break;
 936		case GATE_CLK_AXI_DDR_DIV0:
 937			*clk_gate_axi_ddr_div0 = hw;
 938			break;
 939		case GATE_CLK_AXI_DDR_DIV1:
 940			*clk_gate_axi_ddr_div1 = hw;
 941			break;
 942		}
 943	}
 944
 945	return ret;
 946}
 947
 948static int sg2042_mux_notifier_cb(struct notifier_block *nb,
 949				  unsigned long event,
 950				  void *data)
 951{
 952	struct sg2042_mux_clock *mux = to_sg2042_mux_nb(nb);
 953	const struct clk_ops *ops = &clk_mux_ops;
 954	struct clk_notifier_data *ndata = data;
 955	struct clk_hw *hw;
 956	int ret = 0;
 957
 958	hw = __clk_get_hw(ndata->clk);
 959
 960	/* To switch to fpll before changing rate and restore after that */
 961	if (event == PRE_RATE_CHANGE) {
 962		mux->original_index = ops->get_parent(hw);
 963
 964		/*
 965		 * "1" is the array index of the second parent input source of
 966		 * mux. For SG2042, it's fpll for all mux clocks.
 967		 * "0" is the array index of the first parent input source of
 968		 * mux, For SG2042, it's mpll.
 969		 * FIXME, any good idea to avoid magic number?
 970		 */
 971		if (mux->original_index == 0)
 972			ret = ops->set_parent(hw, 1);
 973	} else if (event == POST_RATE_CHANGE) {
 974		ret = ops->set_parent(hw, mux->original_index);
 975	}
 976
 977	return notifier_from_errno(ret);
 978}
 979
 980static int sg2042_clk_register_muxs(struct device *dev,
 981				    struct sg2042_clk_data *clk_data,
 982				    struct sg2042_mux_clock mux_clks[],
 983				    int num_mux_clks)
 984{
 985	struct sg2042_mux_clock *mux;
 986	struct clk_hw *hw;
 987	int i, ret = 0;
 988
 989	for (i = 0; i < num_mux_clks; i++) {
 990		mux = &mux_clks[i];
 991
 992		hw = __devm_clk_hw_register_mux
 993			(dev,
 994			 NULL,
 995			 mux->hw.init->name,
 996			 mux->hw.init->num_parents,
 997			 NULL,
 998			 mux->hw.init->parent_hws,
 999			 NULL,
1000			 mux->hw.init->flags,
1001			 clk_data->iobase + mux->offset_select,
1002			 mux->shift,
1003			 BIT(mux->width) - 1,
1004			 0,
1005			 sg2042_mux_table,
1006			 &sg2042_clk_lock);
1007		if (IS_ERR(hw)) {
1008			pr_err("failed to register clock %s\n", mux->hw.init->name);
1009			ret = PTR_ERR(hw);
1010			break;
1011		}
1012
1013		clk_data->onecell_data.hws[mux->id] = hw;
1014
1015		/* Updated some clocks which takes the role of parent */
1016		switch (mux->id) {
1017		case MUX_CLK_DDR01:
1018			*clk_mux_ddr01 = hw;
1019			break;
1020		case MUX_CLK_DDR23:
1021			*clk_mux_ddr23 = hw;
1022			break;
1023		case MUX_CLK_RP_CPU_NORMAL:
1024			*clk_mux_rp_cpu_normal = hw;
1025			break;
1026		case MUX_CLK_AXI_DDR:
1027			*clk_mux_axi_ddr = hw;
1028			break;
1029		}
1030
1031		/*
1032		 * FIXME: Theoretically, we should set parent for the
1033		 * mux, but seems hardware has done this for us with
1034		 * default value, so we don't set parent again here.
1035		 */
1036
1037		if (!(mux->hw.init->flags & CLK_MUX_READ_ONLY)) {
1038			mux->clk_nb.notifier_call = sg2042_mux_notifier_cb;
1039			ret = devm_clk_notifier_register(dev, hw->clk, &mux->clk_nb);
1040			if (ret) {
1041				pr_err("failed to register clock notifier for %s\n",
1042				       mux->hw.init->name);
1043				break;
1044			}
1045		}
1046	}
1047
1048	return ret;
1049}
1050
1051static int sg2042_init_clkdata(struct platform_device *pdev,
1052			       int num_clks,
1053			       struct sg2042_clk_data **pp_clk_data)
1054{
1055	struct sg2042_clk_data *clk_data = NULL;
1056
1057	clk_data = devm_kzalloc(&pdev->dev,
1058				struct_size(clk_data, onecell_data.hws, num_clks),
1059				GFP_KERNEL);
1060	if (!clk_data)
1061		return -ENOMEM;
1062
1063	clk_data->iobase = devm_platform_ioremap_resource(pdev, 0);
1064	if (WARN_ON(IS_ERR(clk_data->iobase)))
1065		return PTR_ERR(clk_data->iobase);
1066
1067	clk_data->onecell_data.num = num_clks;
1068
1069	*pp_clk_data = clk_data;
1070
1071	return 0;
1072}
1073
1074static int sg2042_clkgen_probe(struct platform_device *pdev)
1075{
1076	struct sg2042_clk_data *clk_data = NULL;
1077	int num_clks;
1078	int ret;
1079
1080	num_clks = ARRAY_SIZE(sg2042_div_clks_level_1) +
1081		   ARRAY_SIZE(sg2042_div_clks_level_2) +
1082		   ARRAY_SIZE(sg2042_gate_clks_level_1) +
1083		   ARRAY_SIZE(sg2042_gate_clks_level_2) +
1084		   ARRAY_SIZE(sg2042_mux_clks);
1085
1086	ret = sg2042_init_clkdata(pdev, num_clks, &clk_data);
1087	if (ret)
1088		goto error_out;
1089
1090	/* level-1 gates */
1091	ret = sg2042_clk_register_gates_fw(&pdev->dev, clk_data,
1092					   sg2042_gate_clks_level_1,
1093					   ARRAY_SIZE(sg2042_gate_clks_level_1));
1094	if (ret)
1095		goto error_out;
1096
1097	/* level-1 div */
1098	ret = sg2042_clk_register_divs(&pdev->dev, clk_data, sg2042_div_clks_level_1,
1099				       ARRAY_SIZE(sg2042_div_clks_level_1));
1100	if (ret)
1101		goto error_out;
1102
1103	/* mux */
1104	ret = sg2042_clk_register_muxs(&pdev->dev, clk_data, sg2042_mux_clks,
1105				       ARRAY_SIZE(sg2042_mux_clks));
1106	if (ret)
1107		goto error_out;
1108
1109	/* level 2 div */
1110	ret = sg2042_clk_register_divs(&pdev->dev, clk_data, sg2042_div_clks_level_2,
1111				       ARRAY_SIZE(sg2042_div_clks_level_2));
1112	if (ret)
1113		goto error_out;
1114
1115	/* level 2 gate */
1116	ret = sg2042_clk_register_gates(&pdev->dev, clk_data, sg2042_gate_clks_level_2,
1117					ARRAY_SIZE(sg2042_gate_clks_level_2));
1118	if (ret)
1119		goto error_out;
1120
1121	return devm_of_clk_add_hw_provider(&pdev->dev,
1122					   of_clk_hw_onecell_get,
1123					   &clk_data->onecell_data);
1124
1125error_out:
1126	pr_err("%s failed error number %d\n", __func__, ret);
1127	return ret;
1128}
1129
1130static const struct of_device_id sg2042_clkgen_match[] = {
1131	{ .compatible = "sophgo,sg2042-clkgen" },
1132	{ /* sentinel */ }
1133};
1134MODULE_DEVICE_TABLE(of, sg2042_clkgen_match);
1135
1136static struct platform_driver sg2042_clkgen_driver = {
1137	.probe = sg2042_clkgen_probe,
1138	.driver = {
1139		.name = "clk-sophgo-sg2042-clkgen",
1140		.of_match_table = sg2042_clkgen_match,
1141		.suppress_bind_attrs = true,
1142	},
1143};
1144module_platform_driver(sg2042_clkgen_driver);
1145
1146MODULE_AUTHOR("Chen Wang");
1147MODULE_DESCRIPTION("Sophgo SG2042 clock generator driver");
1148MODULE_LICENSE("GPL");
~/ Read-only file preview.