예제 #1
0
static void uniphier_fi2c_hw_init(struct uniphier_fi2c_priv *priv,
				  u32 bus_speed, unsigned long clk_rate)
{
	u32 tmp;

	tmp = readl(priv->membase + UNIPHIER_FI2C_CR);
	tmp |= UNIPHIER_FI2C_CR_MST;
	writel(tmp, priv->membase + UNIPHIER_FI2C_CR);

	uniphier_fi2c_reset(priv);

	tmp = clk_rate / bus_speed;

	writel(tmp, priv->membase + UNIPHIER_FI2C_CYC);
	writel(tmp / 2, priv->membase + UNIPHIER_FI2C_LCTL);
	writel(tmp / 2, priv->membase + UNIPHIER_FI2C_SSUT);
	writel(tmp / 16, priv->membase + UNIPHIER_FI2C_DSUT);

	uniphier_fi2c_prepare_operation(priv);
}
static int uniphier_fi2c_clk_init(struct device *dev,
				  struct uniphier_fi2c_priv *priv)
{
	struct device_node *np = dev->of_node;
	unsigned long clk_rate;
	u32 bus_speed, clk_count;
	int ret;

	if (of_property_read_u32(np, "clock-frequency", &bus_speed))
		bus_speed = UNIPHIER_FI2C_DEFAULT_SPEED;

	if (bus_speed > UNIPHIER_FI2C_MAX_SPEED)
		bus_speed = UNIPHIER_FI2C_MAX_SPEED;

	/* Get input clk rate through clk driver */
	priv->clk = devm_clk_get(dev, NULL);
	if (IS_ERR(priv->clk)) {
		dev_err(dev, "failed to get clock\n");
		return PTR_ERR(priv->clk);
	}

	ret = clk_prepare_enable(priv->clk);
	if (ret)
		return ret;

	clk_rate = clk_get_rate(priv->clk);

	uniphier_fi2c_reset(priv);

	clk_count = clk_rate / bus_speed;

	writel(clk_count, priv->membase + UNIPHIER_FI2C_CYC);
	writel(clk_count / 2, priv->membase + UNIPHIER_FI2C_LCTL);
	writel(clk_count / 2, priv->membase + UNIPHIER_FI2C_SSUT);
	writel(clk_count / 16, priv->membase + UNIPHIER_FI2C_DSUT);

	uniphier_fi2c_prepare_operation(priv);

	return 0;
}
static void uniphier_fi2c_recover(struct uniphier_fi2c_priv *priv)
{
	uniphier_fi2c_reset(priv);
	i2c_recover_bus(&priv->adap);
}