diff options
Diffstat (limited to 'drivers/i2c/busses/i2c-octeon.c')
| -rw-r--r-- | drivers/i2c/busses/i2c-octeon.c | 131 | 
1 files changed, 58 insertions, 73 deletions
diff --git a/drivers/i2c/busses/i2c-octeon.c b/drivers/i2c/busses/i2c-octeon.c index 56dbe54e881..81042b08a94 100644 --- a/drivers/i2c/busses/i2c-octeon.c +++ b/drivers/i2c/busses/i2c-octeon.c @@ -2,7 +2,7 @@   * (C) Copyright 2009-2010   * Nokia Siemens Networks, michael.lawnick.ext@nsn.com   * - * Portions Copyright (C) 2010 Cavium Networks, Inc. + * Portions Copyright (C) 2010, 2011 Cavium Networks, Inc.   *   * This is a driver for the i2c adapter in Cavium Networks' OCTEON processors.   * @@ -11,17 +11,16 @@   * warranty of any kind, whether express or implied.   */ +#include <linux/platform_device.h> +#include <linux/interrupt.h>  #include <linux/kernel.h>  #include <linux/module.h> +#include <linux/delay.h>  #include <linux/sched.h>  #include <linux/slab.h> -#include <linux/init.h> - -#include <linux/io.h>  #include <linux/i2c.h> -#include <linux/interrupt.h> -#include <linux/delay.h> -#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/of.h>  #include <asm/octeon/octeon.h> @@ -65,7 +64,7 @@ struct octeon_i2c {  	wait_queue_head_t queue;  	struct i2c_adapter adap;  	int irq; -	int twsi_freq; +	u32 twsi_freq;  	int sys_freq;  	resource_size_t twsi_phys;  	void __iomem *twsi_base; @@ -121,10 +120,8 @@ static u8 octeon_i2c_read_sw(struct octeon_i2c *i2c, u64 eop_reg)   */  static void octeon_i2c_write_int(struct octeon_i2c *i2c, u64 data)  { -	u64 tmp; -  	__raw_writeq(data, i2c->twsi_base + TWSI_INT); -	tmp = __raw_readq(i2c->twsi_base + TWSI_INT); +	__raw_readq(i2c->twsi_base + TWSI_INT);  }  /** @@ -184,7 +181,7 @@ static irqreturn_t octeon_i2c_isr(int irq, void *dev_id)  	struct octeon_i2c *i2c = dev_id;  	octeon_i2c_int_disable(i2c); -	wake_up_interruptible(&i2c->queue); +	wake_up(&i2c->queue);  	return IRQ_HANDLED;  } @@ -207,9 +204,9 @@ static int octeon_i2c_wait(struct octeon_i2c *i2c)  	octeon_i2c_int_enable(i2c); -	result = wait_event_interruptible_timeout(i2c->queue, -						  octeon_i2c_test_iflg(i2c), -						  i2c->adap.timeout); +	result = wait_event_timeout(i2c->queue, +					octeon_i2c_test_iflg(i2c), +					i2c->adap.timeout);  	octeon_i2c_int_disable(i2c); @@ -441,13 +438,13 @@ static struct i2c_adapter octeon_i2c_ops = {  	.owner = THIS_MODULE,  	.name = "OCTEON adapter",  	.algo = &octeon_i2c_algo, -	.timeout = 2, +	.timeout = HZ / 50,  };  /**   * octeon_i2c_setclock - Calculate and set clock divisors.   */ -static int __devinit octeon_i2c_setclock(struct octeon_i2c *i2c) +static int octeon_i2c_setclock(struct octeon_i2c *i2c)  {  	int tclk, thp_base, inc, thp_idx, mdiv_idx, ndiv_idx, foscl, diff;  	int thp = 0x18, mdiv = 2, ndiv = 0, delta_hz = 1000000; @@ -490,7 +487,7 @@ static int __devinit octeon_i2c_setclock(struct octeon_i2c *i2c)  	return 0;  } -static int __devinit octeon_i2c_initlowlevel(struct octeon_i2c *i2c) +static int octeon_i2c_initlowlevel(struct octeon_i2c *i2c)  {  	u8 status;  	int tries; @@ -511,11 +508,10 @@ static int __devinit octeon_i2c_initlowlevel(struct octeon_i2c *i2c)  	return -EIO;  } -static int __devinit octeon_i2c_probe(struct platform_device *pdev) +static int octeon_i2c_probe(struct platform_device *pdev)  {  	int irq, result = 0;  	struct octeon_i2c *i2c; -	struct octeon_i2c_data *i2c_data;  	struct resource *res_mem;  	/* All adaptors have an irq.  */ @@ -523,130 +519,119 @@ static int __devinit octeon_i2c_probe(struct platform_device *pdev)  	if (irq < 0)  		return irq; -	i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); +	i2c = devm_kzalloc(&pdev->dev, sizeof(*i2c), GFP_KERNEL);  	if (!i2c) {  		dev_err(&pdev->dev, "kzalloc failed\n");  		result = -ENOMEM;  		goto out;  	}  	i2c->dev = &pdev->dev; -	i2c_data = pdev->dev.platform_data;  	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	if (res_mem == NULL) {  		dev_err(i2c->dev, "found no memory resource\n");  		result = -ENXIO; -		goto fail_region; +		goto out;  	} +	i2c->twsi_phys = res_mem->start; +	i2c->regsize = resource_size(res_mem); -	if (i2c_data == NULL) { -		dev_err(i2c->dev, "no I2C frequency data\n"); +	/* +	 * "clock-rate" is a legacy binding, the official binding is +	 * "clock-frequency".  Try the official one first and then +	 * fall back if it doesn't exist. +	 */ +	if (of_property_read_u32(pdev->dev.of_node, +				 "clock-frequency", &i2c->twsi_freq) && +	    of_property_read_u32(pdev->dev.of_node, +				 "clock-rate", &i2c->twsi_freq)) { +		dev_err(i2c->dev, +			"no I2C 'clock-rate' or 'clock-frequency' property\n");  		result = -ENXIO; -		goto fail_region; +		goto out;  	} -	i2c->twsi_phys = res_mem->start; -	i2c->regsize = resource_size(res_mem); -	i2c->twsi_freq = i2c_data->i2c_freq; -	i2c->sys_freq = i2c_data->sys_freq; +	i2c->sys_freq = octeon_get_io_clock_rate(); -	if (!request_mem_region(i2c->twsi_phys, i2c->regsize, res_mem->name)) { +	if (!devm_request_mem_region(&pdev->dev, i2c->twsi_phys, i2c->regsize, +				      res_mem->name)) {  		dev_err(i2c->dev, "request_mem_region failed\n"); -		goto fail_region; +		goto out;  	} -	i2c->twsi_base = ioremap(i2c->twsi_phys, i2c->regsize); +	i2c->twsi_base = devm_ioremap(&pdev->dev, i2c->twsi_phys, i2c->regsize);  	init_waitqueue_head(&i2c->queue);  	i2c->irq = irq; -	result = request_irq(i2c->irq, octeon_i2c_isr, 0, DRV_NAME, i2c); +	result = devm_request_irq(&pdev->dev, i2c->irq, +				  octeon_i2c_isr, 0, DRV_NAME, i2c);  	if (result < 0) {  		dev_err(i2c->dev, "failed to attach interrupt\n"); -		goto fail_irq; +		goto out;  	}  	result = octeon_i2c_initlowlevel(i2c);  	if (result) {  		dev_err(i2c->dev, "init low level failed\n"); -		goto  fail_add; +		goto  out;  	}  	result = octeon_i2c_setclock(i2c);  	if (result) {  		dev_err(i2c->dev, "clock init failed\n"); -		goto  fail_add; +		goto  out;  	}  	i2c->adap = octeon_i2c_ops;  	i2c->adap.dev.parent = &pdev->dev; -	i2c->adap.nr = pdev->id >= 0 ? pdev->id : 0; +	i2c->adap.dev.of_node = pdev->dev.of_node;  	i2c_set_adapdata(&i2c->adap, i2c);  	platform_set_drvdata(pdev, i2c); -	result = i2c_add_numbered_adapter(&i2c->adap); +	result = i2c_add_adapter(&i2c->adap);  	if (result < 0) {  		dev_err(i2c->dev, "failed to add adapter\n"); -		goto fail_add; +		goto out;  	} -  	dev_info(i2c->dev, "version %s\n", DRV_VERSION); -	return result; +	return 0; -fail_add: -	platform_set_drvdata(pdev, NULL); -	free_irq(i2c->irq, i2c); -fail_irq: -	iounmap(i2c->twsi_base); -	release_mem_region(i2c->twsi_phys, i2c->regsize); -fail_region: -	kfree(i2c);  out:  	return result;  }; -static int __devexit octeon_i2c_remove(struct platform_device *pdev) +static int octeon_i2c_remove(struct platform_device *pdev)  {  	struct octeon_i2c *i2c = platform_get_drvdata(pdev);  	i2c_del_adapter(&i2c->adap); -	platform_set_drvdata(pdev, NULL); -	free_irq(i2c->irq, i2c); -	iounmap(i2c->twsi_base); -	release_mem_region(i2c->twsi_phys, i2c->regsize); -	kfree(i2c);  	return 0;  }; +static struct of_device_id octeon_i2c_match[] = { +	{ +		.compatible = "cavium,octeon-3860-twsi", +	}, +	{}, +}; +MODULE_DEVICE_TABLE(of, octeon_i2c_match); +  static struct platform_driver octeon_i2c_driver = {  	.probe		= octeon_i2c_probe, -	.remove		= __devexit_p(octeon_i2c_remove), +	.remove		= octeon_i2c_remove,  	.driver		= {  		.owner	= THIS_MODULE,  		.name	= DRV_NAME, +		.of_match_table = octeon_i2c_match,  	},  }; -static int __init octeon_i2c_init(void) -{ -	int rv; - -	rv = platform_driver_register(&octeon_i2c_driver); -	return rv; -} - -static void __exit octeon_i2c_exit(void) -{ -	platform_driver_unregister(&octeon_i2c_driver); -} +module_platform_driver(octeon_i2c_driver);  MODULE_AUTHOR("Michael Lawnick <michael.lawnick.ext@nsn.com>");  MODULE_DESCRIPTION("I2C-Bus adapter for Cavium OCTEON processors");  MODULE_LICENSE("GPL");  MODULE_VERSION(DRV_VERSION); -MODULE_ALIAS("platform:" DRV_NAME); - -module_init(octeon_i2c_init); -module_exit(octeon_i2c_exit);  | 
