drivers/clk/mediatek/clk-fhctl.c

Source file repositories/reference/linux-study-clean/drivers/clk/mediatek/clk-fhctl.c

File Facts

System
Linux kernel
Corpus path
drivers/clk/mediatek/clk-fhctl.c
Extension
.c
Size
6921 bytes
Lines
265
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) 2022 MediaTek Inc.
 * Author: Edward-JW Yang <edward-jw.yang@mediatek.com>
 */

#include <linux/io.h>
#include <linux/iopoll.h>

#include "clk-mtk.h"
#include "clk-pllfh.h"
#include "clk-fhctl.h"

#define PERCENT_TO_DDSLMT(dds, percent_m10) \
	((((dds) * (percent_m10)) >> 5) / 100)

static const struct fhctl_offset fhctl_offset_v1 = {
	.offset_hp_en = 0x0,
	.offset_clk_con = 0x4,
	.offset_rst_con = 0x8,
	.offset_slope0 = 0xc,
	.offset_slope1 = 0x10,
	.offset_cfg = 0x0,
	.offset_updnlmt = 0x4,
	.offset_dds = 0x8,
	.offset_dvfs = 0xc,
	.offset_mon = 0x10,
};

static const struct fhctl_offset fhctl_offset_v2 = {
	.offset_hp_en = 0x0,
	.offset_clk_con = 0x8,
	.offset_rst_con = 0xc,
	.offset_slope0 = 0x10,
	.offset_slope1 = 0x14,
	.offset_cfg = 0x0,
	.offset_updnlmt = 0x4,
	.offset_dds = 0x8,
	.offset_dvfs = 0xc,
	.offset_mon = 0x10,
};

const struct fhctl_offset *fhctl_get_offset_table(enum fhctl_variant v)
{
	switch (v) {
	case FHCTL_PLLFH_V1:
		return &fhctl_offset_v1;
	case FHCTL_PLLFH_V2:
		return &fhctl_offset_v2;
	default:
		return ERR_PTR(-EINVAL);
	};
}

static void dump_hw(struct mtk_clk_pll *pll, struct fh_pll_regs *regs,
		    const struct fh_pll_data *data)
{
	pr_info("hp_en<%x>,clk_con<%x>,slope0<%x>,slope1<%x>\n",
		readl(regs->reg_hp_en), readl(regs->reg_clk_con),
		readl(regs->reg_slope0), readl(regs->reg_slope1));
	pr_info("cfg<%x>,lmt<%x>,dds<%x>,dvfs<%x>,mon<%x>\n",
		readl(regs->reg_cfg), readl(regs->reg_updnlmt),
		readl(regs->reg_dds), readl(regs->reg_dvfs),
		readl(regs->reg_mon));
	pr_info("pcw<%x>\n", readl(pll->pcw_addr));
}

static int fhctl_set_ssc_regs(struct mtk_clk_pll *pll, struct fh_pll_regs *regs,
			      const struct fh_pll_data *data, u32 rate)
{
	u32 updnlmt_val, r;

	writel((readl(regs->reg_cfg) & ~(data->frddsx_en)), regs->reg_cfg);
	writel((readl(regs->reg_cfg) & ~(data->sfstrx_en)), regs->reg_cfg);
	writel((readl(regs->reg_cfg) & ~(data->fhctlx_en)), regs->reg_cfg);

	if (rate > 0) {
		/* Set the relative parameter registers (dt/df/upbnd/downbnd) */
		r = readl(regs->reg_cfg);
		r &= ~(data->msk_frddsx_dys);
		r |= (data->df_val << (ffs(data->msk_frddsx_dys) - 1));
		writel(r, regs->reg_cfg);

		r = readl(regs->reg_cfg);
		r &= ~(data->msk_frddsx_dts);
		r |= (data->dt_val << (ffs(data->msk_frddsx_dts) - 1));
		writel(r, regs->reg_cfg);

		writel((readl(pll->pcw_addr) & data->dds_mask) | data->tgl_org,
			regs->reg_dds);

Annotation

Implementation Notes