Example #1
0
static int rkclk_set_pll(struct rk3288_cru *cru, enum rk_clk_id clk_id,
			 const struct pll_div *div)
{
	int pll_id = rk_pll_id(clk_id);
	struct rk3288_pll *pll = &cru->pll[pll_id];
	/* All PLLs have same VCO and output frequency range restrictions. */
	uint vco_hz = OSC_HZ / 1000 * div->nf / div->nr * 1000;
	uint output_hz = vco_hz / div->no;

	debug("PLL at %x: nf=%d, nr=%d, no=%d, vco=%u Hz, output=%u Hz\n",
	      (uint)pll, div->nf, div->nr, div->no, vco_hz, output_hz);
	assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
	       output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ &&
	       (div->no == 1 || !(div->no % 2)));

	/* enter reset */
	rk_setreg(&pll->con3, 1 << PLL_RESET_SHIFT);

	rk_clrsetreg(&pll->con0,
		     CLKR_MASK << CLKR_SHIFT | PLL_OD_MASK,
		     ((div->nr - 1) << CLKR_SHIFT) | (div->no - 1));
	rk_clrsetreg(&pll->con1, CLKF_MASK, div->nf - 1);
	rk_clrsetreg(&pll->con2, PLL_BWADJ_MASK, (div->nf >> 1) - 1);

	udelay(10);

	/* return from reset */
	rk_clrreg(&pll->con3, 1 << PLL_RESET_SHIFT);

	return 0;
}
Example #2
0
static int rkclk_set_pll(struct rk3036_cru *cru, enum rk_clk_id clk_id,
			 const struct pll_div *div)
{
	int pll_id = rk_pll_id(clk_id);
	struct rk3036_pll *pll = &cru->pll[pll_id];

	/* All PLLs have same VCO and output frequency range restrictions. */
	uint vco_hz = OSC_HZ / 1000 * div->fbdiv / div->refdiv * 1000;
	uint output_hz = vco_hz / div->postdiv1 / div->postdiv2;

	debug("PLL at %p: fbdiv=%d, refdiv=%d, postdiv1=%d, postdiv2=%d,\
		 vco=%u Hz, output=%u Hz\n",
			pll, div->fbdiv, div->refdiv, div->postdiv1,
			div->postdiv2, vco_hz, output_hz);
	assert(vco_hz >= VCO_MIN_HZ && vco_hz <= VCO_MAX_HZ &&
	       output_hz >= OUTPUT_MIN_HZ && output_hz <= OUTPUT_MAX_HZ);

	/* use integer mode */
	rk_setreg(&pll->con1, 1 << PLL_DSMPD_SHIFT);

	rk_clrsetreg(&pll->con0,
		     PLL_POSTDIV1_MASK | PLL_FBDIV_MASK,
		     (div->postdiv1 << PLL_POSTDIV1_SHIFT) | div->fbdiv);
	rk_clrsetreg(&pll->con1, PLL_POSTDIV2_MASK | PLL_REFDIV_MASK,
		     (div->postdiv2 << PLL_POSTDIV2_SHIFT |
		     div->refdiv << PLL_REFDIV_SHIFT));

	/* waiting for pll lock */
	while (readl(&pll->con1) & (1 << PLL_LOCK_STATUS_SHIFT))
		udelay(1);

	return 0;
}
Example #3
0
int board_early_init_f(void)
{
	const uintptr_t GRF_SOC_CON0 = 0xff770244;
	const uintptr_t GRF_SOC_CON2 = 0xff77024c;
	struct udevice *dev;
	int ret;

	/*
	 * This init is done in SPL, but when chain-loading U-Boot SPL will
	 * have been skipped. Allow the clock driver to check if it needs
	 * setting up.
	 */
	ret = rockchip_get_clk(&dev);
	if (ret) {
		debug("CLK init failed: %d\n", ret);
		return ret;
	}

	rk_setreg(GRF_SOC_CON2, 1 << 0);

	/*
	 * Disable JTAG on sdmmc0 IO. The SDMMC won't work until this bit is
	 * cleared
	 */
	rk_clrreg(GRF_SOC_CON0, 1 << 12);

	return 0;
}
Example #4
0
static void rk3288_set_io_vsel(struct udevice *dev)
{
	struct rk3288_grf *grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);

	/* lcdc(vop) iodomain select 1.8V */
	rk_setreg(&grf->io_vsel, 1 << 0);
}
Example #5
0
static void setup_iodomain(void)
{
	const u32 GRF_IO_VSEL_GPIO4CD_SHIFT = 3;
	struct rk3399_grf_regs *grf =
	    syscon_get_first_range(ROCKCHIP_SYSCON_GRF);

	/*
	 * Set bit 3 in GRF_IO_VSEL so PCIE_RST# works (pin GPIO4_C6).
	 * Linux assumes that PCIE_RST# works out of the box as it probes
	 * PCIe before loading the iodomain driver.
	 */
	rk_setreg(&grf->io_vsel, 1 << GRF_IO_VSEL_GPIO4CD_SHIFT);
}
Example #6
0
static int rockchip_reset_assert(struct reset_ctl *reset_ctl)
{
	struct rockchip_reset_priv *priv = dev_get_priv(reset_ctl->dev);
	int bank =  reset_ctl->id / ROCKCHIP_RESET_NUM_IN_REG;
	int offset =  reset_ctl->id % ROCKCHIP_RESET_NUM_IN_REG;

	debug("%s(reset_ctl=%p) (dev=%p, id=%lu) (reg_addr=%p)\n", __func__,
	      reset_ctl, reset_ctl->dev, reset_ctl->id,
	      priv->base + (bank * 4));

	rk_setreg(priv->base + (bank * 4), BIT(offset));

	return 0;
}
Example #7
0
static int rk3288_hdmi_enable(struct udevice *dev, int panel_bpp,
			      const struct display_timing *edid)
{
	struct rk_hdmi_priv *priv = dev_get_priv(dev);
	struct display_plat *uc_plat = dev_get_uclass_platdata(dev);
	int vop_id = uc_plat->source_id;
	struct rk3288_grf *grf = priv->grf;

	/* hdmi source select hdmi controller */
	rk_setreg(&grf->soc_con6, 1 << 15);

	/* hdmi data from vop id */
	rk_clrsetreg(&grf->soc_con6, 1 << 4, (vop_id == 1) ? (1 << 4) : 0);

	return 0;
}
int rk_lvds_enable(struct udevice *dev, int panel_bpp,
		   const struct display_timing *edid)
{
	struct rk_lvds_priv *priv = dev_get_priv(dev);
	struct display_plat *uc_plat = dev_get_uclass_platdata(dev);
	int ret = 0;
	unsigned int val = 0;

	ret = panel_enable_backlight(priv->panel);
	if (ret) {
		debug("%s: backlight error: %d\n", __func__, ret);
		return ret;
	}

	/* Select the video source */
	if (uc_plat->source_id)
		val = RK3288_LVDS_SOC_CON6_SEL_VOP_LIT |
		    (RK3288_LVDS_SOC_CON6_SEL_VOP_LIT << 16);
	else
		val = RK3288_LVDS_SOC_CON6_SEL_VOP_LIT << 16;
	rk_setreg(&priv->grf->soc_con6, val);

	/* Select data transfer format */
	val = priv->format;
	if (priv->output == LVDS_OUTPUT_DUAL)
		val |= LVDS_DUAL | LVDS_CH0_EN | LVDS_CH1_EN;
	else if (priv->output == LVDS_OUTPUT_SINGLE)
		val |= LVDS_CH0_EN;
	else if (priv->output == LVDS_OUTPUT_RGB)
		val |= LVDS_TTL_EN | LVDS_CH0_EN | LVDS_CH1_EN;
	val |= (0xffff << 16);
	rk_setreg(&priv->grf->soc_con7, val);

	/* Enable LVDS PHY */
	if (priv->output == LVDS_OUTPUT_RGB) {
		lvds_writel(priv, RK3288_LVDS_CH0_REG0,
			    RK3288_LVDS_CH0_REG0_TTL_EN |
			    RK3288_LVDS_CH0_REG0_LANECK_EN |
			    RK3288_LVDS_CH0_REG0_LANE4_EN |
			    RK3288_LVDS_CH0_REG0_LANE3_EN |
			    RK3288_LVDS_CH0_REG0_LANE2_EN |
			    RK3288_LVDS_CH0_REG0_LANE1_EN |
			    RK3288_LVDS_CH0_REG0_LANE0_EN);
		lvds_writel(priv, RK3288_LVDS_CH0_REG2,
			    RK3288_LVDS_PLL_FBDIV_REG2(0x46));

		lvds_writel(priv, RK3288_LVDS_CH0_REG3,
			    RK3288_LVDS_PLL_FBDIV_REG3(0x46));
		lvds_writel(priv, RK3288_LVDS_CH0_REG4,
			    RK3288_LVDS_CH0_REG4_LANECK_TTL_MODE |
			    RK3288_LVDS_CH0_REG4_LANE4_TTL_MODE |
			    RK3288_LVDS_CH0_REG4_LANE3_TTL_MODE |
			    RK3288_LVDS_CH0_REG4_LANE2_TTL_MODE |
			    RK3288_LVDS_CH0_REG4_LANE1_TTL_MODE |
			    RK3288_LVDS_CH0_REG4_LANE0_TTL_MODE);
		lvds_writel(priv, RK3288_LVDS_CH0_REG5,
			    RK3288_LVDS_CH0_REG5_LANECK_TTL_DATA |
			    RK3288_LVDS_CH0_REG5_LANE4_TTL_DATA |
			    RK3288_LVDS_CH0_REG5_LANE3_TTL_DATA |
			    RK3288_LVDS_CH0_REG5_LANE2_TTL_DATA |
			    RK3288_LVDS_CH0_REG5_LANE1_TTL_DATA |
			    RK3288_LVDS_CH0_REG5_LANE0_TTL_DATA);
		lvds_writel(priv, RK3288_LVDS_CH0_REGD,
			    RK3288_LVDS_PLL_PREDIV_REGD(0x0a));
		lvds_writel(priv, RK3288_LVDS_CH0_REG20,
			    RK3288_LVDS_CH0_REG20_LSB);
	} else {
		lvds_writel(priv, RK3288_LVDS_CH0_REG0,
			    RK3288_LVDS_CH0_REG0_LVDS_EN |
			    RK3288_LVDS_CH0_REG0_LANECK_EN |
			    RK3288_LVDS_CH0_REG0_LANE4_EN |
			    RK3288_LVDS_CH0_REG0_LANE3_EN |
			    RK3288_LVDS_CH0_REG0_LANE2_EN |
			    RK3288_LVDS_CH0_REG0_LANE1_EN |
			    RK3288_LVDS_CH0_REG0_LANE0_EN);
		lvds_writel(priv, RK3288_LVDS_CH0_REG1,
			    RK3288_LVDS_CH0_REG1_LANECK_BIAS |
			    RK3288_LVDS_CH0_REG1_LANE4_BIAS |
			    RK3288_LVDS_CH0_REG1_LANE3_BIAS |
			    RK3288_LVDS_CH0_REG1_LANE2_BIAS |
			    RK3288_LVDS_CH0_REG1_LANE1_BIAS |
			    RK3288_LVDS_CH0_REG1_LANE0_BIAS);
		lvds_writel(priv, RK3288_LVDS_CH0_REG2,
			    RK3288_LVDS_CH0_REG2_RESERVE_ON |
			    RK3288_LVDS_CH0_REG2_LANECK_LVDS_MODE |
			    RK3288_LVDS_CH0_REG2_LANE4_LVDS_MODE |
			    RK3288_LVDS_CH0_REG2_LANE3_LVDS_MODE |
			    RK3288_LVDS_CH0_REG2_LANE2_LVDS_MODE |
			    RK3288_LVDS_CH0_REG2_LANE1_LVDS_MODE |
			    RK3288_LVDS_CH0_REG2_LANE0_LVDS_MODE |
			    RK3288_LVDS_PLL_FBDIV_REG2(0x46));
		lvds_writel(priv, RK3288_LVDS_CH0_REG3,
			    RK3288_LVDS_PLL_FBDIV_REG3(0x46));
		lvds_writel(priv, RK3288_LVDS_CH0_REG4, 0x00);
		lvds_writel(priv, RK3288_LVDS_CH0_REG5, 0x00);
		lvds_writel(priv, RK3288_LVDS_CH0_REGD,
			    RK3288_LVDS_PLL_PREDIV_REGD(0x0a));
		lvds_writel(priv, RK3288_LVDS_CH0_REG20,
			    RK3288_LVDS_CH0_REG20_LSB);
	}

	/* Power on */
	writel(RK3288_LVDS_CFG_REGC_PLL_ENABLE,
	       priv->regs + RK3288_LVDS_CFG_REGC);

	writel(RK3288_LVDS_CFG_REG21_TX_ENABLE,
	       priv->regs + RK3288_LVDS_CFG_REG21);

	return 0;
}
static int rk_vop_probe(struct udevice *dev)
{
	struct video_uc_platdata *plat = dev_get_uclass_platdata(dev);
	const void *blob = gd->fdt_blob;
	struct rk_vop_priv *priv = dev_get_priv(dev);
	struct udevice *reg;
	int ret, port, node;

	/* Before relocation we don't need to do anything */
	if (!(gd->flags & GD_FLG_RELOC))
		return 0;

	priv->grf = syscon_get_first_range(ROCKCHIP_SYSCON_GRF);
	priv->regs = (struct rk3288_vop *)dev_get_addr(dev);

	/* lcdc(vop) iodomain select 1.8V */
	rk_setreg(&priv->grf->io_vsel, 1 << 0);

	/*
	 * Try some common regulators. We should really get these from the
	 * device tree somehow.
	 */
	ret = regulator_autoset_by_name("vcc18_lcd", &reg);
	if (ret)
		debug("%s: Cannot autoset regulator vcc18_lcd\n", __func__);
	ret = regulator_autoset_by_name("VCC18_LCD", &reg);
	if (ret)
		debug("%s: Cannot autoset regulator VCC18_LCD\n", __func__);
	ret = regulator_autoset_by_name("vdd10_lcd_pwren_h", &reg);
	if (ret) {
		debug("%s: Cannot autoset regulator vdd10_lcd_pwren_h\n",
		      __func__);
	}
	ret = regulator_autoset_by_name("vdd10_lcd", &reg);
	if (ret) {
		debug("%s: Cannot autoset regulator vdd10_lcd\n",
		      __func__);
	}
	ret = regulator_autoset_by_name("VDD10_LCD", &reg);
	if (ret) {
		debug("%s: Cannot autoset regulator VDD10_LCD\n",
		      __func__);
	}
	ret = regulator_autoset_by_name("vcc33_lcd", &reg);
	if (ret)
		debug("%s: Cannot autoset regulator vcc33_lcd\n", __func__);

	/*
	 * Try all the ports until we find one that works. In practice this
	 * tries EDP first if available, then HDMI.
	 */
	port = fdt_subnode_offset(blob, dev->of_offset, "port");
	if (port < 0)
		return -EINVAL;
	for (node = fdt_first_subnode(blob, port);
	     node > 0;
	     node = fdt_next_subnode(blob, node)) {
		ret = rk_display_init(dev, plat->base, VIDEO_BPP16, node);
		if (ret)
			debug("Device failed: ret=%d\n", ret);
		if (!ret)
			break;
	}

	return ret;
}