示例#1
0
static int i2c_lpc2k_resume(struct device *dev)
{
	struct platform_device *pdev = to_platform_device(dev);
	struct lpc2k_i2c *i2c = platform_get_drvdata(pdev);

	clk_enable(i2c->clk);
	i2c_lpc2k_reset(i2c);

	return 0;
}
示例#2
0
static int i2c_lpc2k_clear_arb(struct lpc2k_i2c *i2c)
{
	unsigned long timeout = jiffies + msecs_to_jiffies(1000);

	/*
	 * If the transfer needs to abort for some reason, we'll try to
	 * force a stop condition to clear any pending bus conditions
	 */
	writel(LPC24XX_STO, i2c->base + LPC24XX_I2CONSET);

	/* Wait for status change */
	while (readl(i2c->base + LPC24XX_I2STAT) != M_I2C_IDLE) {
		if (time_after(jiffies, timeout)) {
			/* Bus was not idle, try to reset adapter */
			i2c_lpc2k_reset(i2c);
			return -EBUSY;
		}

		cpu_relax();
	}

	return 0;
}
示例#3
0
static int i2c_lpc2k_clear_arb(struct lpc2k_i2c *i2c)
{
	long timeout = jiffies + HZ;
	int ret = 0;

	/*
	 * If the transfer needs to abort for some reason, we'll try to
	 * force a stop condition to clear any pending bus conditions
	 */
	i2c_writel(LPC24XX_STO, i2c->reg_base + LPC24XX_I2CONSET);

	/* Wait for status change */
	while (jiffies < timeout &&
		(i2c_readl(i2c->reg_base + LPC24XX_I2STAT) != m_i2c_idle))
		cpu_relax();

	if (i2c_readl(i2c->reg_base + LPC24XX_I2STAT) != m_i2c_idle) {
		/* Bus was not idle, try to reset adapter */
		i2c_lpc2k_reset(i2c);
		ret = -EBUSY;
	}

	return ret;
}
示例#4
0
static int i2c_lpc2k_probe(struct platform_device *dev)
{
	struct lpc2k_i2c *i2c;
	struct resource *res;
	int ret, irq;
	unsigned long clkrate;

	res = platform_get_resource(dev, IORESOURCE_MEM, 0);
	irq = platform_get_irq(dev, 0);
	if (res == NULL || irq < 0) {
		dev_err(&dev->dev, "No resource data!\n");
		return -ENODEV;
	}

	if (dev->id < 0 || dev->id >= LPC24XX_MAX_ADAPTERS) {
		dev_err(&dev->dev, "I2C bus number invalid (%d)\n", dev->id);
		return -ENODEV;
	}

	if (!request_mem_region(res->start, resource_size(res), res->name)) {
		dev_err(&dev->dev, "Memory region already used!\n");
		return -ENOMEM;
	}

	i2c = kzalloc(sizeof(struct lpc2k_i2c), GFP_KERNEL);
	if (!i2c) {
		dev_err(&dev->dev, "Error allocating memory!\n");
		ret = -ENOMEM;
		goto emalloc;
	}

	i2c->adap.owner = THIS_MODULE;

	init_waitqueue_head(&i2c->wait);

	i2c->adap.nr = dev->id;
	snprintf(i2c->adap.name, sizeof(i2c->adap.name), MODULE_NAME ".%u",
		 i2c->adap.nr);

	i2c->clk = clk_get(&dev->dev, NULL);
	if (IS_ERR(i2c->clk)) {
		dev_err(&dev->dev, "Error getting clock!\n");
		ret = PTR_ERR(i2c->clk);
		goto eclk;
	}

	i2c->reg_base = ioremap(res->start, resource_size(res));
	if (!i2c->reg_base) {
		dev_err(&dev->dev, "Error mapping memory!\n");
		ret = -EIO;
		goto eremap;
	}
	i2c->iobase = res->start;
	i2c->iosize = resource_size(res);
	i2c->irq = irq;

	clk_enable(i2c->clk);

	i2c->adap.algo = &i2c_lpc2k_algorithm;
	ret = request_irq(irq, i2c_lpc2k_handler, IRQF_DISABLED,
		i2c->adap.name, i2c);
	if (ret)
		goto ereqirq;

	disable_irq_nosync(irq);

	i2c_lpc2k_reset(i2c);

	i2c->adap.algo_data = i2c;
	i2c->adap.dev.parent = &dev->dev;

	ret = i2c_add_numbered_adapter(&i2c->adap);
	if (ret < 0) {
		dev_err(&dev->dev, "Failed to add bus!\n");
		goto eadapt;
	}

	platform_set_drvdata(dev, i2c);

	printk(KERN_INFO "I2C: %s: LPC2K I2C adapter\n",
	       dev_name(&i2c->adap.dev));

	/* Place controller is a known state */
	i2c_lpc2k_reset(i2c);

	/* Get I2C base clock rate */
	clkrate = clk_get_rate(i2c->clk);
	if (!clkrate) {
		dev_warn(&dev->dev, "Can't get I2C base clock, using "
			"12MHz!\n");
		clkrate = 12000000;
	}

	/* Setup I2C dividers to generate clock rate with 50% duty cycle */
	clkrate = (clkrate / scl_frequency) / 2;
	i2c_writel(clkrate, i2c->reg_base + LPC24XX_I2SCLL);
	i2c_writel(clkrate, i2c->reg_base + LPC24XX_I2SCLH);

	return 0;

eadapt:
	free_irq(irq, i2c);
ereqirq:
	clk_disable(i2c->clk);
	iounmap(i2c->reg_base);
eremap:
	clk_put(i2c->clk);
eclk:
	kfree(i2c);
emalloc:
	release_mem_region(res->start, resource_size(res));
	return ret;
}
示例#5
0
static int i2c_lpc2k_probe(struct platform_device *pdev)
{
	struct lpc2k_i2c *i2c;
	struct resource *res;
	u32 bus_clk_rate;
	u32 scl_high;
	u32 clkrate;
	int ret;

	i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);
	if (!i2c)
		return -ENOMEM;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	i2c->base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(i2c->base))
		return PTR_ERR(i2c->base);

	i2c->irq = platform_get_irq(pdev, 0);
	if (i2c->irq < 0) {
		dev_err(&pdev->dev, "can't get interrupt resource\n");
		return i2c->irq;
	}

	init_waitqueue_head(&i2c->wait);

	i2c->clk = devm_clk_get(&pdev->dev, NULL);
	if (IS_ERR(i2c->clk)) {
		dev_err(&pdev->dev, "error getting clock\n");
		return PTR_ERR(i2c->clk);
	}

	ret = clk_prepare_enable(i2c->clk);
	if (ret) {
		dev_err(&pdev->dev, "unable to enable clock.\n");
		return ret;
	}

	ret = devm_request_irq(&pdev->dev, i2c->irq, i2c_lpc2k_handler, 0,
			       dev_name(&pdev->dev), i2c);
	if (ret < 0) {
		dev_err(&pdev->dev, "can't request interrupt.\n");
		goto fail_clk;
	}

	disable_irq_nosync(i2c->irq);

	/* Place controller is a known state */
	i2c_lpc2k_reset(i2c);

	ret = of_property_read_u32(pdev->dev.of_node, "clock-frequency",
				   &bus_clk_rate);
	if (ret)
		bus_clk_rate = 100000; /* 100 kHz default clock rate */

	clkrate = clk_get_rate(i2c->clk);
	if (clkrate == 0) {
		dev_err(&pdev->dev, "can't get I2C base clock\n");
		ret = -EINVAL;
		goto fail_clk;
	}

	/* Setup I2C dividers to generate clock with proper duty cycle */
	clkrate = clkrate / bus_clk_rate;
	if (bus_clk_rate <= 100000)
		scl_high = (clkrate * I2C_STD_MODE_DUTY) / 100;
	else if (bus_clk_rate <= 400000)
		scl_high = (clkrate * I2C_FAST_MODE_DUTY) / 100;
	else
		scl_high = (clkrate * I2C_FAST_MODE_PLUS_DUTY) / 100;

	writel(scl_high, i2c->base + LPC24XX_I2SCLH);
	writel(clkrate - scl_high, i2c->base + LPC24XX_I2SCLL);

	platform_set_drvdata(pdev, i2c);

	i2c_set_adapdata(&i2c->adap, i2c);
	i2c->adap.owner = THIS_MODULE;
	strlcpy(i2c->adap.name, "LPC2K I2C adapter", sizeof(i2c->adap.name));
	i2c->adap.algo = &i2c_lpc2k_algorithm;
	i2c->adap.dev.parent = &pdev->dev;
	i2c->adap.dev.of_node = pdev->dev.of_node;

	ret = i2c_add_adapter(&i2c->adap);
	if (ret < 0)
		goto fail_clk;

	dev_info(&pdev->dev, "LPC2K I2C adapter\n");

	return 0;

fail_clk:
	clk_disable_unprepare(i2c->clk);
	return ret;
}