drivers/clk/sunxi-ng/ccu-sun50i-a100.c

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

File Facts

System
Linux kernel
Corpus path
drivers/clk/sunxi-ng/ccu-sun50i-a100.c
Extension
.c
Size
40197 bytes
Lines
1282
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) 2020 Yangtao Li <frank@allwinnertech.com>
 */

#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_mult.h"
#include "ccu_nk.h"
#include "ccu_nkm.h"
#include "ccu_nkmp.h"
#include "ccu_nm.h"

#include "ccu-sun50i-a100.h"

#define SUN50I_A100_PLL_SDM_ENABLE		BIT(24)
#define SUN50I_A100_PLL_OUTPUT_ENABLE		BIT(27)
#define SUN50I_A100_PLL_LOCK			BIT(28)
#define SUN50I_A100_PLL_LOCK_ENABLE		BIT(29)
#define SUN50I_A100_PLL_ENABLE			BIT(31)

#define SUN50I_A100_PLL_PERIPH1_PATTERN0	0xd1303333

/*
 * The CPU PLL is actually NP clock, with P being /1, /2 or /4. However
 * P should only be used for output frequencies lower than 288 MHz.
 *
 * For now we can just model it as a multiplier clock, and force P to /1.
 *
 * The M factor is present in the register's description, but not in the
 * frequency formula, and it's documented as "M is only used for backdoor
 * testing", so it's not modelled and then force to 0.
 */
#define SUN50I_A100_PLL_CPUX_REG		0x000
static struct ccu_mult pll_cpux_clk = {
	.enable		= SUN50I_A100_PLL_OUTPUT_ENABLE,
	.lock		= SUN50I_A100_PLL_LOCK,
	.mult		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
	.common		= {
		.reg		= 0x000,
		.hw.init	= CLK_HW_INIT("pll-cpux", "dcxo24M",
					      &ccu_mult_ops,
					      CLK_SET_RATE_UNGATE),
	},
};

/* Some PLLs are input * N / div1 / P. Model them as NKMP with no K */
#define SUN50I_A100_PLL_DDR0_REG		0x010
static struct ccu_nkmp pll_ddr0_clk = {
	.enable		= SUN50I_A100_PLL_OUTPUT_ENABLE,
	.lock		= SUN50I_A100_PLL_LOCK,
	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
	.p		= _SUNXI_CCU_DIV(0, 1), /* output divider */
	.common		= {
		.reg		= 0x010,
		.hw.init	= CLK_HW_INIT("pll-ddr0", "dcxo24M",
					      &ccu_nkmp_ops,
					      CLK_SET_RATE_UNGATE |
					      CLK_IS_CRITICAL),
	},
};

#define SUN50I_A100_PLL_PERIPH0_REG	0x020
static struct ccu_nkmp pll_periph0_clk = {
	.enable		= SUN50I_A100_PLL_OUTPUT_ENABLE,
	.lock		= SUN50I_A100_PLL_LOCK,
	.n		= _SUNXI_CCU_MULT_MIN(8, 8, 12),
	.m		= _SUNXI_CCU_DIV(1, 1), /* input divider */
	.p		= _SUNXI_CCU_DIV(0, 1), /* output divider */
	.fixed_post_div	= 2,
	.common		= {
		.reg		= 0x020,
		.features	= CCU_FEATURE_FIXED_POSTDIV,
		.hw.init	= CLK_HW_INIT("pll-periph0", "dcxo24M",
					      &ccu_nkmp_ops,
					      CLK_SET_RATE_UNGATE),
	},
};

#define SUN50I_A100_PLL_PERIPH1_REG	0x028

Annotation

Implementation Notes