struct exynos_usi_variant { enum exynos_usi_ver ver; /* USI IP-core version */ unsignedint sw_conf_mask; /* SW_CONF mask for all protocols */
size_t min_mode; /* first index in exynos_usi_modes[] */
size_t max_mode; /* last index in exynos_usi_modes[] */
size_t num_clks; /* number of clocks to assert */ constchar * const *clk_names; /* clock names to assert */
};
/** * exynos_usi_set_sw_conf - Set USI block configuration mode * @usi: USI driver object * @mode: Mode index * * Select underlying serial protocol (UART/SPI/I2C) in USI IP-core. * * Return: 0 on success, or negative error code on failure.
*/ staticint exynos_usi_set_sw_conf(struct exynos_usi *usi, size_t mode)
{ unsignedint val; int ret;
if (mode < usi->data->min_mode || mode > usi->data->max_mode) return -EINVAL;
val = exynos_usi_modes[usi->data->ver][mode].val;
ret = regmap_update_bits(usi->sysreg, usi->sw_conf,
usi->data->sw_conf_mask, val); if (ret) return ret;
/** * exynos_usi_enable - Initialize USI block * @usi: USI driver object * * USI IP-core start state is "reset" (on startup and after CPU resume). This * routine enables the USI block by clearing the reset flag. It also configures * HWACG behavior (needed e.g. for UART Rx). It should be performed before * underlying protocol becomes functional. * * Return: 0 on success, or negative error code on failure.
*/ staticint exynos_usi_enable(conststruct exynos_usi *usi)
{
u32 val; int ret;
ret = clk_bulk_prepare_enable(usi->data->num_clks, usi->clks); if (ret) return ret;
/* Enable USI block */
val = readl(usi->regs + USI_CON);
val &= ~USI_CON_RESET;
writel(val, usi->regs + USI_CON);
udelay(1);
/* Continuously provide the clock to USI IP w/o gating */ if (usi->clkreq_on) {
val = readl(usi->regs + USI_OPTION);
val &= ~USI_OPTION_CLKSTOP_ON;
val |= USI_OPTION_CLKREQ_ON;
writel(val, usi->regs + USI_OPTION);
}
staticint exynos_usi_configure(struct exynos_usi *usi)
{ int ret;
ret = exynos_usi_set_sw_conf(usi, usi->mode); if (ret) return ret;
if (usi->data->ver == USI_VER1)
ret = clk_bulk_prepare_enable(usi->data->num_clks,
usi->clks); elseif (usi->data->ver == USI_VER2)
ret = exynos_usi_enable(usi);
if (usi->data->ver == USI_VER1) {
clk_bulk_disable_unprepare(usi->data->num_clks, usi->clks); return;
}
ret = clk_bulk_prepare_enable(usi->data->num_clks, usi->clks); if (ret) return;
/* Make sure that we've stopped providing the clock to USI IP */
val = readl(usi->regs + USI_OPTION);
val &= ~USI_OPTION_CLKREQ_ON;
val |= USI_OPTION_CLKSTOP_ON;
writel(val, usi->regs + USI_OPTION);
/* Set USI block state to reset */
val = readl(usi->regs + USI_CON);
val |= USI_CON_RESET;
writel(val, usi->regs + USI_CON);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.