drivers/clk/rockchip/clk-mmc-phase.c
Source file repositories/reference/linux-study-clean/drivers/clk/rockchip/clk-mmc-phase.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/clk/rockchip/clk-mmc-phase.c- Extension
.c- Size
- 7142 bytes
- Lines
- 248
- 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.
- 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.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/slab.hlinux/clk.hlinux/clk-provider.hlinux/io.hlinux/kernel.hlinux/regmap.hclk.h
Detected Declarations
struct rockchip_mmc_clockfunction rockchip_mmc_recalcfunction rockchip_mmc_get_phasefunction rockchip_mmc_set_phasefunction rockchip_mmc_clk_rate_notify
Annotated Snippet
struct rockchip_mmc_clock {
struct clk_hw hw;
void __iomem *reg;
struct regmap *grf;
int grf_reg;
int shift;
int cached_phase;
struct notifier_block clk_rate_change_nb;
};
#define to_mmc_clock(_hw) container_of(_hw, struct rockchip_mmc_clock, hw)
#define RK3288_MMC_CLKGEN_DIV 2
static unsigned long rockchip_mmc_recalc(struct clk_hw *hw,
unsigned long parent_rate)
{
return parent_rate / RK3288_MMC_CLKGEN_DIV;
}
#define ROCKCHIP_MMC_DELAY_SEL BIT(10)
#define ROCKCHIP_MMC_DEGREE_MASK 0x3
#define ROCKCHIP_MMC_DELAYNUM_OFFSET 2
#define ROCKCHIP_MMC_DELAYNUM_MASK (0xff << ROCKCHIP_MMC_DELAYNUM_OFFSET)
#define PSECS_PER_SEC 1000000000000LL
/*
* Each fine delay is between 44ps-77ps. Assume each fine delay is 60ps to
* simplify calculations. So 45degs could be anywhere between 33deg and 57.8deg.
*/
#define ROCKCHIP_MMC_DELAY_ELEMENT_PSEC 60
static int rockchip_mmc_get_phase(struct clk_hw *hw)
{
struct rockchip_mmc_clock *mmc_clock = to_mmc_clock(hw);
unsigned long rate = clk_hw_get_rate(hw);
u32 raw_value;
u16 degrees;
u32 delay_num = 0;
/* Constant signal, no measurable phase shift */
if (!rate)
return 0;
if (mmc_clock->grf)
regmap_read(mmc_clock->grf, mmc_clock->grf_reg, &raw_value);
else
raw_value = readl(mmc_clock->reg);
raw_value >>= mmc_clock->shift;
degrees = (raw_value & ROCKCHIP_MMC_DEGREE_MASK) * 90;
if (raw_value & ROCKCHIP_MMC_DELAY_SEL) {
/* degrees/delaynum * 1000000 */
unsigned long factor = (ROCKCHIP_MMC_DELAY_ELEMENT_PSEC / 10) *
36 * (rate / 10000);
delay_num = (raw_value & ROCKCHIP_MMC_DELAYNUM_MASK);
delay_num >>= ROCKCHIP_MMC_DELAYNUM_OFFSET;
degrees += DIV_ROUND_CLOSEST(delay_num * factor, 1000000);
}
return degrees % 360;
}
static int rockchip_mmc_set_phase(struct clk_hw *hw, int degrees)
{
struct rockchip_mmc_clock *mmc_clock = to_mmc_clock(hw);
unsigned long rate = clk_hw_get_rate(hw);
u8 nineties, remainder;
u8 delay_num;
u32 raw_value;
u32 delay;
/*
* The below calculation is based on the output clock from
* MMC host to the card, which expects the phase clock inherits
* the clock rate from its parent, namely the output clock
* provider of MMC host. However, things may go wrong if
* (1) It is orphan.
* (2) It is assigned to the wrong parent.
*
* This check help debug the case (1), which seems to be the
* most likely problem we often face and which makes it difficult
* for people to debug unstable mmc tuning results.
*/
if (!rate) {
pr_err("%s: invalid clk rate\n", __func__);
Annotation
- Immediate include surface: `linux/slab.h`, `linux/clk.h`, `linux/clk-provider.h`, `linux/io.h`, `linux/kernel.h`, `linux/regmap.h`, `clk.h`.
- Detected declarations: `struct rockchip_mmc_clock`, `function rockchip_mmc_recalc`, `function rockchip_mmc_get_phase`, `function rockchip_mmc_set_phase`, `function rockchip_mmc_clk_rate_notify`.
- Atlas domain: Driver Families / drivers/clk.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.