drivers/clk/sunxi-ng/ccu-sun9i-a80.c

Source file repositories/reference/linux-study-clean/drivers/clk/sunxi-ng/ccu-sun9i-a80.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/sunxi-ng/ccu-sun9i-a80.c
Extension
.c
Size
37581 bytes
Lines
1254
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-only
/*
 * Copyright (c) 2016 Chen-Yu Tsai. All rights reserved.
 */

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

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

#include "ccu_div.h"
#include "ccu_gate.h"
#include "ccu_mp.h"
#include "ccu_nkmp.h"
#include "ccu_nm.h"
#include "ccu_phase.h"

#include "ccu-sun9i-a80.h"

#define CCU_SUN9I_LOCK_REG	0x09c

/*
 * The CPU PLLs are actually NP clocks, with P being /1 or /4. However
 * P should only be used for output frequencies lower than 228 MHz.
 * Neither mainline Linux, U-boot, nor the vendor BSPs use these.
 *
 * For now we can just model it as a multiplier clock, and force P to /1.
 */
#define SUN9I_A80_PLL_C0CPUX_REG	0x000
#define SUN9I_A80_PLL_C1CPUX_REG	0x004

static struct ccu_mult pll_c0cpux_clk = {
	.enable		= BIT(31),
	.lock		= BIT(0),
	.mult		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
	.common		= {
		.reg		= SUN9I_A80_PLL_C0CPUX_REG,
		.lock_reg	= CCU_SUN9I_LOCK_REG,
		.features	= CCU_FEATURE_LOCK_REG,
		.hw.init	= CLK_HW_INIT("pll-c0cpux", "osc24M",
					      &ccu_mult_ops,
					      CLK_SET_RATE_UNGATE),
	},
};

static struct ccu_mult pll_c1cpux_clk = {
	.enable		= BIT(31),
	.lock		= BIT(1),
	.mult		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
	.common		= {
		.reg		= SUN9I_A80_PLL_C1CPUX_REG,
		.lock_reg	= CCU_SUN9I_LOCK_REG,
		.features	= CCU_FEATURE_LOCK_REG,
		.hw.init	= CLK_HW_INIT("pll-c1cpux", "osc24M",
					      &ccu_mult_ops,
					      CLK_SET_RATE_UNGATE),
	},
};

/*
 * The Audio PLL has d1, d2 dividers in addition to the usual N, M
 * factors. Since we only need 2 frequencies from this PLL: 22.5792 MHz
 * and 24.576 MHz, ignore them for now. Enforce d1 = 0 and d2 = 0.
 */
#define SUN9I_A80_PLL_AUDIO_REG	0x008

static struct ccu_nm pll_audio_clk = {
	.enable		= BIT(31),
	.lock		= BIT(2),
	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
	.m		= _SUNXI_CCU_DIV_OFFSET(0, 6, 0),
	.common		= {
		.reg		= 0x008,
		.lock_reg	= CCU_SUN9I_LOCK_REG,
		.features	= CCU_FEATURE_LOCK_REG,
		.hw.init	= CLK_HW_INIT("pll-audio", "osc24M",
					      &ccu_nm_ops, CLK_SET_RATE_UNGATE),
	},
};

/* Some PLLs are input * N / div1 / div2. Model them as NKMP with no K */
static struct ccu_nkmp pll_periph0_clk = {
	.enable		= BIT(31),
	.lock		= BIT(3),
	.n		= _SUNXI_CCU_MULT_OFFSET_MIN_MAX(8, 8, 0, 12, 0),
	.m		= _SUNXI_CCU_DIV(16, 1), /* input divider */
	.p		= _SUNXI_CCU_DIV(18, 1), /* output divider */

Annotation

Implementation Notes