drivers/mmc/host/dw_mmc-rockchip.c
Source file repositories/reference/linux-study-clean/drivers/mmc/host/dw_mmc-rockchip.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/mmc/host/dw_mmc-rockchip.c- Extension
.c- Size
- 18293 bytes
- Lines
- 659
- Domain
- Driver Families
- Bucket
- drivers/mmc
- 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/module.hlinux/platform_device.hlinux/clk.hlinux/hw_bitfield.hlinux/mmc/host.hlinux/of_address.hlinux/mmc/slot-gpio.hlinux/pm_runtime.hlinux/slab.hdw_mmc.hdw_mmc-pltfm.h
Detected Declarations
struct dw_mci_rockchip_priv_datastruct range_tfunction rockchip_mmc_get_internal_phasefunction rockchip_mmc_get_phasefunction rockchip_mmc_set_internal_phasefunction rockchip_mmc_set_phasefunction dw_mci_rk3288_set_iosfunction blockfunction dw_mci_rk3288_execute_tuningfunction dw_mci_common_parse_dtfunction dw_mci_rk2928_parse_dtfunction dw_mci_rk3288_parse_dtfunction dw_mci_rk3576_parse_dtfunction dw_mci_rockchip_initfunction dw_mci_rockchip_probefunction dw_mci_rockchip_removefunction dw_mci_rockchip_runtime_suspendfunction dw_mci_rockchip_runtime_resume
Annotated Snippet
struct dw_mci_rockchip_priv_data {
struct clk *drv_clk;
struct clk *sample_clk;
int default_sample_phase;
int num_phases;
bool internal_phase;
int sample_phase;
int drv_phase;
};
/*
* 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.
*/
static int rockchip_mmc_get_internal_phase(struct dw_mci *host, bool sample)
{
unsigned long rate = clk_get_rate(host->ciu_clk) / RK3288_CLKGEN_DIV;
u32 raw_value;
u16 degrees;
u32 delay_num = 0;
/* Constant signal, no measurable phase shift */
if (!rate)
return 0;
if (sample)
raw_value = mci_readl(host, TIMING_CON1);
else
raw_value = mci_readl(host, TIMING_CON0);
raw_value >>= ROCKCHIP_MMC_DEGREE_OFFSET;
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_get_phase(struct dw_mci *host, bool sample)
{
struct dw_mci_rockchip_priv_data *priv = host->priv;
struct clk *clock = sample ? priv->sample_clk : priv->drv_clk;
if (priv->internal_phase)
return rockchip_mmc_get_internal_phase(host, sample);
else
return clk_get_phase(clock);
}
static int rockchip_mmc_set_internal_phase(struct dw_mci *host, bool sample, int degrees)
{
unsigned long rate = clk_get_rate(host->ciu_clk) / RK3288_CLKGEN_DIV;
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) {
dev_err(host->dev, "%s: invalid clk rate\n", __func__);
return -EINVAL;
}
nineties = degrees / 90;
remainder = (degrees % 90);
/*
* Due to the inexact nature of the "fine" delay, we might
* actually go non-monotonic. We don't go _too_ monotonic
* though, so we should be OK. Here are options of how we may
* work:
Annotation
- Immediate include surface: `linux/module.h`, `linux/platform_device.h`, `linux/clk.h`, `linux/hw_bitfield.h`, `linux/mmc/host.h`, `linux/of_address.h`, `linux/mmc/slot-gpio.h`, `linux/pm_runtime.h`.
- Detected declarations: `struct dw_mci_rockchip_priv_data`, `struct range_t`, `function rockchip_mmc_get_internal_phase`, `function rockchip_mmc_get_phase`, `function rockchip_mmc_set_internal_phase`, `function rockchip_mmc_set_phase`, `function dw_mci_rk3288_set_ios`, `function block`, `function dw_mci_rk3288_execute_tuning`, `function dw_mci_common_parse_dt`.
- Atlas domain: Driver Families / drivers/mmc.
- 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.