static int rockchip_cpuclk_pre_rate_change(struct rockchip_cpuclk *cpuclk, struct clk_notifier_data *ndata) { const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data; unsigned long alt_prate, alt_div; unsigned long flags; alt_prate = clk_get_rate(cpuclk->alt_parent); spin_lock_irqsave(cpuclk->lock, flags); /* * If the old parent clock speed is less than the clock speed * of the alternate parent, then it should be ensured that at no point * the armclk speed is more than the old_rate until the dividers are * set. */ if (alt_prate > ndata->old_rate) { /* calculate dividers */ alt_div = DIV_ROUND_UP(alt_prate, ndata->old_rate) - 1; if (alt_div > reg_data->div_core_mask) { pr_warn("%s: limiting alt-divider %lu to %d\n", __func__, alt_div, reg_data->div_core_mask); alt_div = reg_data->div_core_mask; } /* * Change parents and add dividers in a single transaction. * * NOTE: we do this in a single transaction so we're never * dividing the primary parent by the extra dividers that were * needed for the alt. */ pr_debug("%s: setting div %lu as alt-rate %lu > old-rate %lu\n", __func__, alt_div, alt_prate, ndata->old_rate); writel(HIWORD_UPDATE(alt_div, reg_data->div_core_mask, reg_data->div_core_shift) | HIWORD_UPDATE(reg_data->mux_core_alt, reg_data->mux_core_mask, reg_data->mux_core_shift), cpuclk->reg_base + reg_data->core_reg); } else { /* select alternate parent */ writel(HIWORD_UPDATE(reg_data->mux_core_alt, reg_data->mux_core_mask, reg_data->mux_core_shift), cpuclk->reg_base + reg_data->core_reg); } spin_unlock_irqrestore(cpuclk->lock, flags); return 0; }
static enum drm_connector_status dw_hdmi_rk3328_read_hpd(struct dw_hdmi *dw_hdmi, void *data) { struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; enum drm_connector_status status; status = dw_hdmi_phy_read_hpd(dw_hdmi, data); if (status == connector_status_connected) regmap_write(hdmi->regmap, RK3328_GRF_SOC_CON4, HIWORD_UPDATE(RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V, RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V)); else regmap_write(hdmi->regmap, RK3328_GRF_SOC_CON4, HIWORD_UPDATE(0, RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V)); return status; }
static int rockchip_cpuclk_post_rate_change(struct rockchip_cpuclk *cpuclk, struct clk_notifier_data *ndata) { const struct rockchip_cpuclk_reg_data *reg_data = cpuclk->reg_data; const struct rockchip_cpuclk_rate_table *rate; unsigned long flags; rate = rockchip_get_cpuclk_settings(cpuclk, ndata->new_rate); if (!rate) { pr_err("%s: Invalid rate : %lu for cpuclk\n", __func__, ndata->new_rate); return -EINVAL; } spin_lock_irqsave(cpuclk->lock, flags); if (ndata->old_rate < ndata->new_rate) rockchip_cpuclk_set_dividers(cpuclk, rate); /* * post-rate change event, re-mux to primary parent and remove dividers. * * NOTE: we do this in a single transaction so we're never dividing the * primary parent by the extra dividers that were needed for the alt. */ writel(HIWORD_UPDATE(0, reg_data->div_core_mask, reg_data->div_core_shift) | HIWORD_UPDATE(reg_data->mux_core_main, reg_data->mux_core_mask, reg_data->mux_core_shift), cpuclk->reg_base + reg_data->core_reg); if (ndata->old_rate > ndata->new_rate) rockchip_cpuclk_set_dividers(cpuclk, rate); spin_unlock_irqrestore(cpuclk->lock, flags); return 0; }
static void __init rk3036_clk_init(struct device_node *np) { struct rockchip_clk_provider *ctx; void __iomem *reg_base; struct clk *clk; reg_base = of_iomap(np, 0); if (!reg_base) { pr_err("%s: could not map cru region\n", __func__); return; } /* * Make uart_pll_clk a child of the gpll, as all other sources are * not that usable / stable. */ writel_relaxed(HIWORD_UPDATE(0x2, 0x3, 10), reg_base + RK2928_CLKSEL_CON(13)); ctx = rockchip_clk_init(np, reg_base, CLK_NR_CLKS); if (IS_ERR(ctx)) { pr_err("%s: rockchip clk init failed\n", __func__); iounmap(reg_base); return; } clk = clk_register_fixed_factor(NULL, "usb480m", "xin24m", 0, 20, 1); if (IS_ERR(clk)) pr_warn("%s: could not register clock usb480m: %ld\n", __func__, PTR_ERR(clk)); rockchip_clk_register_plls(ctx, rk3036_pll_clks, ARRAY_SIZE(rk3036_pll_clks), RK3036_GRF_SOC_STATUS0); rockchip_clk_register_branches(ctx, rk3036_clk_branches, ARRAY_SIZE(rk3036_clk_branches)); rockchip_clk_protect_critical(rk3036_critical_clocks, ARRAY_SIZE(rk3036_critical_clocks)); rockchip_clk_register_armclk(ctx, ARMCLK, "armclk", mux_armclk_p, ARRAY_SIZE(mux_armclk_p), &rk3036_cpuclk_data, rk3036_cpuclk_rates, ARRAY_SIZE(rk3036_cpuclk_rates)); rockchip_register_softrst(np, 9, reg_base + RK2928_SOFTRST_CON(0), ROCKCHIP_SOFTRST_HIWORD_MASK); rockchip_register_restart_notifier(ctx, RK2928_GLB_SRST_FST, NULL); rockchip_clk_of_add_provider(np, ctx); }
static void dw_hdmi_rk3328_setup_hpd(struct dw_hdmi *dw_hdmi, void *data) { struct rockchip_hdmi *hdmi = (struct rockchip_hdmi *)data; dw_hdmi_phy_setup_hpd(dw_hdmi, data); /* Enable and map pins to 3V grf-controlled io-voltage */ regmap_write(hdmi->regmap, RK3328_GRF_SOC_CON4, HIWORD_UPDATE(0, RK3328_HDMI_HPD_SARADC | RK3328_HDMI_CEC_5V | RK3328_HDMI_SDA_5V | RK3328_HDMI_SCL_5V | RK3328_HDMI_HPD_5V)); regmap_write(hdmi->regmap, RK3328_GRF_SOC_CON3, HIWORD_UPDATE(0, RK3328_HDMI_SDA5V_GRF | RK3328_HDMI_SCL5V_GRF | RK3328_HDMI_HPD5V_GRF | RK3328_HDMI_CEC5V_GRF)); regmap_write(hdmi->regmap, RK3328_GRF_SOC_CON2, HIWORD_UPDATE(RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK, RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK | RK3328_HDMI_HPD_IOE)); }
RK3328_HDMI_HPD_5V)); regmap_write(hdmi->regmap, RK3328_GRF_SOC_CON3, HIWORD_UPDATE(0, RK3328_HDMI_SDA5V_GRF | RK3328_HDMI_SCL5V_GRF | RK3328_HDMI_HPD5V_GRF | RK3328_HDMI_CEC5V_GRF)); regmap_write(hdmi->regmap, RK3328_GRF_SOC_CON2, HIWORD_UPDATE(RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK, RK3328_HDMI_SDAIN_MSK | RK3328_HDMI_SCLIN_MSK | RK3328_HDMI_HPD_IOE)); } static struct rockchip_hdmi_chip_data rk3288_chip_data = { .lcdsel_grf_reg = RK3288_GRF_SOC_CON6, .lcdsel_big = HIWORD_UPDATE(0, RK3288_HDMI_LCDC_SEL), .lcdsel_lit = HIWORD_UPDATE(RK3288_HDMI_LCDC_SEL, RK3288_HDMI_LCDC_SEL), }; static const struct dw_hdmi_plat_data rk3288_hdmi_drv_data = { .mode_valid = dw_hdmi_rockchip_mode_valid, .mpll_cfg = rockchip_mpll_cfg, .cur_ctr = rockchip_cur_ctr, .phy_config = rockchip_phy_config, .phy_data = &rk3288_chip_data, }; static const struct dw_hdmi_phy_ops rk3328_hdmi_phy_ops = { .init = dw_hdmi_rockchip_genphy_init, .disable = dw_hdmi_rockchip_genphy_disable, .read_hpd = dw_hdmi_rk3328_read_hpd,