drivers/clk/sunxi-ng/ccu-sun55i-a523-mcu.c

Source file repositories/reference/linux-study-clean/drivers/clk/sunxi-ng/ccu-sun55i-a523-mcu.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/sunxi-ng/ccu-sun55i-a523-mcu.c
Extension
.c
Size
15598 bytes
Lines
470
Domain
Driver Families
Bucket
drivers/clk
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: GPL-2.0
/*
 * Copyright (C) 2025 Chen-Yu Tsai <wens@csie.org>
 *
 * Based on the A523 CCU driver:
 *   Copyright (C) 2023-2024 Arm Ltd.
 */

#include <linux/clk-provider.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>

#include <dt-bindings/clock/sun55i-a523-mcu-ccu.h>
#include <dt-bindings/reset/sun55i-a523-mcu-ccu.h>

#include "ccu_common.h"
#include "ccu_reset.h"

#include "ccu_div.h"
#include "ccu_gate.h"
#include "ccu_mp.h"
#include "ccu_mult.h"
#include "ccu_nm.h"

static const struct clk_parent_data osc24M[] = {
	{ .fw_name = "hosc" }
};

static const struct clk_parent_data ahb[] = {
	{ .fw_name = "r-ahb" }
};

static const struct clk_parent_data apb[] = {
	{ .fw_name = "r-apb0" }
};

#define SUN55I_A523_PLL_AUDIO1_REG	0x00c
static struct ccu_sdm_setting pll_audio1_sdm_table[] = {
	{ .rate = 2167603200, .pattern = 0xa000a234, .m = 1, .n = 90 }, /* div2->22.5792 */
	{ .rate = 2359296000, .pattern = 0xa0009ba6, .m = 1, .n = 98 }, /* div2->24.576 */
	{ .rate = 1806336000, .pattern = 0xa000872b, .m = 1, .n = 75 }, /* div5->22.576 */
};

static struct ccu_nm pll_audio1_clk = {
	.enable		= BIT(27),
	.lock		= BIT(28),
	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 11),
	.m		= _SUNXI_CCU_DIV(1, 1),
	.sdm		= _SUNXI_CCU_SDM(pll_audio1_sdm_table, BIT(24),
					 0x010, BIT(31)),
	.min_rate	= 180000000U,
	.max_rate	= 3500000000U,
	.common		= {
		.reg		= 0x00c,
		.features	= CCU_FEATURE_SIGMA_DELTA_MOD,
		.hw.init	= CLK_HW_INIT_PARENTS_DATA("pll-audio1",
							   osc24M, &ccu_nm_ops,
							   CLK_SET_RATE_GATE),
	},
};

/*
 * /2 and /5 dividers are actually programmable, but we just use the
 * values from the BSP, since the audio PLL only needs to provide a
 * couple clock rates. This also matches the names given in the manual.
 */
static const struct clk_hw *pll_audio1_div_parents[] = { &pll_audio1_clk.common.hw };
static CLK_FIXED_FACTOR_HWS(pll_audio1_div2_clk, "pll-audio1-div2",
			    pll_audio1_div_parents, 2, 1,
			    CLK_SET_RATE_PARENT);
static CLK_FIXED_FACTOR_HWS(pll_audio1_div5_clk, "pll-audio1-div5",
			    pll_audio1_div_parents, 5, 1,
			    CLK_SET_RATE_PARENT);

static SUNXI_CCU_M_WITH_GATE(audio_out_clk, "audio-out",
			     "pll-audio1-div2", 0x01c,
			     0, 5, BIT(31), CLK_SET_RATE_PARENT);

static const struct clk_parent_data dsp_parents[] = {
	{ .fw_name = "hosc" },
	{ .fw_name = "losc" },
	{ .fw_name = "iosc" },
	/*
	 * The order of the following two parent is from the BSP code. It is
	 * the opposite in the manual. Testing with the DSP is required to
	 * figure out the real order.
	 */
	{ .hw = &pll_audio1_div5_clk.hw },
	{ .hw = &pll_audio1_div2_clk.hw },

Annotation

Implementation Notes