mmc: core: Add helper for parsing clock phase properties
Drivers for MMC hosts that accept phase corrections can take advantage of the helper by embedding an instance of struct mmc_clk_phase_map in their private data and invoking mmc_of_parse_clk_phase() to extract phase parameters. It is the responsibility of the host driver to translate and apply the extracted values to hardware as required. Signed-off-by: Andrew Jeffery <andrew@aj.id.au> Link: https://lore.kernel.org/r/20210114031433.2388532-2-andrew@aj.id.au Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org>
This commit is contained in:
Родитель
7c7905df68
Коммит
3561afa026
|
@ -163,6 +163,50 @@ static void mmc_retune_timer(struct timer_list *t)
|
|||
mmc_retune_needed(host);
|
||||
}
|
||||
|
||||
static void mmc_of_parse_timing_phase(struct device *dev, const char *prop,
|
||||
struct mmc_clk_phase *phase)
|
||||
{
|
||||
int degrees[2] = {0};
|
||||
int rc;
|
||||
|
||||
rc = device_property_read_u32_array(dev, prop, degrees, 2);
|
||||
phase->valid = !rc;
|
||||
if (phase->valid) {
|
||||
phase->in_deg = degrees[0];
|
||||
phase->out_deg = degrees[1];
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mmc_of_parse_clk_phase(struct mmc_host *host, struct mmc_clk_phase_map *map)
|
||||
{
|
||||
struct device *dev = host->parent;
|
||||
|
||||
mmc_of_parse_timing_phase(dev, "clk-phase-legacy",
|
||||
&map->phase[MMC_TIMING_LEGACY]);
|
||||
mmc_of_parse_timing_phase(dev, "clk-phase-mmc-hs",
|
||||
&map->phase[MMC_TIMING_MMC_HS]);
|
||||
mmc_of_parse_timing_phase(dev, "clk-phase-sd-hs",
|
||||
&map->phase[MMC_TIMING_SD_HS]);
|
||||
mmc_of_parse_timing_phase(dev, "clk-phase-uhs-sdr12",
|
||||
&map->phase[MMC_TIMING_UHS_SDR12]);
|
||||
mmc_of_parse_timing_phase(dev, "clk-phase-uhs-sdr25",
|
||||
&map->phase[MMC_TIMING_UHS_SDR25]);
|
||||
mmc_of_parse_timing_phase(dev, "clk-phase-uhs-sdr50",
|
||||
&map->phase[MMC_TIMING_UHS_SDR50]);
|
||||
mmc_of_parse_timing_phase(dev, "clk-phase-uhs-sdr104",
|
||||
&map->phase[MMC_TIMING_UHS_SDR104]);
|
||||
mmc_of_parse_timing_phase(dev, "clk-phase-uhs-ddr50",
|
||||
&map->phase[MMC_TIMING_UHS_DDR50]);
|
||||
mmc_of_parse_timing_phase(dev, "clk-phase-mmc-ddr52",
|
||||
&map->phase[MMC_TIMING_MMC_DDR52]);
|
||||
mmc_of_parse_timing_phase(dev, "clk-phase-mmc-hs200",
|
||||
&map->phase[MMC_TIMING_MMC_HS200]);
|
||||
mmc_of_parse_timing_phase(dev, "clk-phase-mmc-hs400",
|
||||
&map->phase[MMC_TIMING_MMC_HS400]);
|
||||
}
|
||||
EXPORT_SYMBOL(mmc_of_parse_clk_phase);
|
||||
|
||||
/**
|
||||
* mmc_of_parse() - parse host's device-tree node
|
||||
* @host: host whose node should be parsed.
|
||||
|
|
|
@ -79,6 +79,17 @@ struct mmc_ios {
|
|||
bool enhanced_strobe; /* hs400es selection */
|
||||
};
|
||||
|
||||
struct mmc_clk_phase {
|
||||
bool valid;
|
||||
u16 in_deg;
|
||||
u16 out_deg;
|
||||
};
|
||||
|
||||
#define MMC_NUM_CLK_PHASES (MMC_TIMING_MMC_HS400 + 1)
|
||||
struct mmc_clk_phase_map {
|
||||
struct mmc_clk_phase phase[MMC_NUM_CLK_PHASES];
|
||||
};
|
||||
|
||||
struct mmc_host;
|
||||
|
||||
struct mmc_host_ops {
|
||||
|
@ -490,6 +501,8 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *);
|
|||
int mmc_add_host(struct mmc_host *);
|
||||
void mmc_remove_host(struct mmc_host *);
|
||||
void mmc_free_host(struct mmc_host *);
|
||||
void mmc_of_parse_clk_phase(struct mmc_host *host,
|
||||
struct mmc_clk_phase_map *map);
|
||||
int mmc_of_parse(struct mmc_host *host);
|
||||
int mmc_of_parse_voltage(struct device_node *np, u32 *mask);
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче