drivers/clk/mmp/clk-audio.c

Source file repositories/reference/linux-study-clean/drivers/clk/mmp/clk-audio.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/mmp/clk-audio.c
Extension
.c
Size
13121 bytes
Lines
448
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

struct mmp2_audio_clk {
	void __iomem *mmio_base;

	struct clk_hw audio_pll_hw;
	struct clk_mux sspa_mux;
	struct clk_mux sspa1_mux;
	struct clk_divider sysclk_div;
	struct clk_divider sspa0_div;
	struct clk_divider sspa1_div;
	struct clk_gate sysclk_gate;
	struct clk_gate sspa0_gate;
	struct clk_gate sspa1_gate;

	u32 aud_ctrl;
	u32 aud_pll_ctrl0;
	u32 aud_pll_ctrl1;

	spinlock_t lock;

	/* Must be last */
	struct clk_hw_onecell_data clk_data;
};

static const struct {
	unsigned long parent_rate;
	unsigned long freq_vco;
	unsigned char mclk;
	unsigned char fbcclk;
	unsigned short fract;
} predivs[] = {
	{ 26000000, 135475200, 0, 0, 0x8a18 },
	{ 26000000, 147456000, 0, 1, 0x0da1 },
	{ 38400000, 135475200, 1, 2, 0x8208 },
	{ 38400000, 147456000, 1, 3, 0xaaaa },
};

static const struct {
	unsigned char divisor;
	unsigned char modulo;
	unsigned char pattern;
} postdivs[] = {
	{   1,	3,  0, },
	{   2,	5,  0, },
	{   4,	0,  0, },
	{   6,	1,  1, },
	{   8,	1,  0, },
	{   9,	1,  2, },
	{  12,	2,  1, },
	{  16,	2,  0, },
	{  18,	2,  2, },
	{  24,	4,  1, },
	{  36,	4,  2, },
	{  48,	6,  1, },
	{  72,	6,  2, },
};

static unsigned long audio_pll_recalc_rate(struct clk_hw *hw,
					   unsigned long parent_rate)
{
	struct mmp2_audio_clk *priv = container_of(hw, struct mmp2_audio_clk, audio_pll_hw);
	unsigned int prediv;
	unsigned int postdiv;
	u32 aud_pll_ctrl0;
	u32 aud_pll_ctrl1;

	aud_pll_ctrl0 = readl(priv->mmio_base + SSPA_AUD_PLL_CTRL0);
	aud_pll_ctrl0 &= SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO_MASK |
			 SSPA_AUD_PLL_CTRL0_FRACT_MASK |
			 SSPA_AUD_PLL_CTRL0_ENA_DITHER |
			 SSPA_AUD_PLL_CTRL0_DIV_FBCCLK_MASK |
			 SSPA_AUD_PLL_CTRL0_DIV_MCLK_MASK |
			 SSPA_AUD_PLL_CTRL0_PU;

	aud_pll_ctrl1 = readl(priv->mmio_base + SSPA_AUD_PLL_CTRL1);
	aud_pll_ctrl1 &= SSPA_AUD_PLL_CTRL1_CLK_SEL_MASK |
			 SSPA_AUD_PLL_CTRL1_DIV_OCLK_PATTERN_MASK;

	for (prediv = 0; prediv < ARRAY_SIZE(predivs); prediv++) {
		if (predivs[prediv].parent_rate != parent_rate)
			continue;
		for (postdiv = 0; postdiv < ARRAY_SIZE(postdivs); postdiv++) {
			unsigned long freq;
			u32 val;

			val = SSPA_AUD_PLL_CTRL0_ENA_DITHER;
			val |= SSPA_AUD_PLL_CTRL0_PU;
			val |= SSPA_AUD_PLL_CTRL0_DIV_OCLK_MODULO(postdivs[postdiv].modulo);
			val |= SSPA_AUD_PLL_CTRL0_FRACT(predivs[prediv].fract);
			val |= SSPA_AUD_PLL_CTRL0_DIV_FBCCLK(predivs[prediv].fbcclk);
			val |= SSPA_AUD_PLL_CTRL0_DIV_MCLK(predivs[prediv].mclk);

Annotation

Implementation Notes