diff options
Diffstat (limited to 'drivers/w1/masters/omap_hdq.c')
| -rw-r--r-- | drivers/w1/masters/omap_hdq.c | 179 | 
1 files changed, 43 insertions, 136 deletions
diff --git a/drivers/w1/masters/omap_hdq.c b/drivers/w1/masters/omap_hdq.c index 3a7e9ff8a74..9900e8ec739 100644 --- a/drivers/w1/masters/omap_hdq.c +++ b/drivers/w1/masters/omap_hdq.c @@ -1,7 +1,7 @@  /*   * drivers/w1/masters/omap_hdq.c   * - * Copyright (C) 2007 Texas Instruments, Inc. + * Copyright (C) 2007,2012 Texas Instruments, Inc.   *   * This file is licensed under the terms of the GNU General Public License   * version 2. This program is licensed "as is" without any warranty of any @@ -14,12 +14,9 @@  #include <linux/interrupt.h>  #include <linux/slab.h>  #include <linux/err.h> -#include <linux/clk.h>  #include <linux/io.h>  #include <linux/sched.h> - -#include <asm/irq.h> -#include <mach/hardware.h> +#include <linux/pm_runtime.h>  #include "../w1.h"  #include "../w1_int.h" @@ -61,8 +58,6 @@ struct hdq_data {  	/* lock status update */  	struct  mutex		hdq_mutex;  	int			hdq_usecount; -	struct	clk		*hdq_ick; -	struct	clk		*hdq_fck;  	u8			hdq_irqstatus;  	/* device lock */  	spinlock_t		hdq_spinlock; @@ -74,7 +69,7 @@ struct hdq_data {  	int			init_trans;  }; -static int __devinit omap_hdq_probe(struct platform_device *pdev); +static int omap_hdq_probe(struct platform_device *pdev);  static int omap_hdq_remove(struct platform_device *pdev);  static struct platform_driver omap_hdq_driver = { @@ -102,20 +97,20 @@ static struct w1_bus_master omap_w1_master = {  /* HDQ register I/O routines */  static inline u8 hdq_reg_in(struct hdq_data *hdq_data, u32 offset)  { -	return __raw_readb(hdq_data->hdq_base + offset); +	return __raw_readl(hdq_data->hdq_base + offset);  }  static inline void hdq_reg_out(struct hdq_data *hdq_data, u32 offset, u8 val)  { -	__raw_writeb(val, hdq_data->hdq_base + offset); +	__raw_writel(val, hdq_data->hdq_base + offset);  }  static inline u8 hdq_reg_merge(struct hdq_data *hdq_data, u32 offset,  			u8 val, u8 mask)  { -	u8 new_val = (__raw_readb(hdq_data->hdq_base + offset) & ~mask) +	u8 new_val = (__raw_readl(hdq_data->hdq_base + offset) & ~mask)  			| (val & mask); -	__raw_writeb(new_val, hdq_data->hdq_base + offset); +	__raw_writel(new_val, hdq_data->hdq_base + offset);  	return new_val;  } @@ -180,6 +175,7 @@ static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status)  		hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT);  	if (ret == 0) {  		dev_dbg(hdq_data->dev, "TX wait elapsed\n"); +		ret = -ETIMEDOUT;  		goto out;  	} @@ -187,7 +183,7 @@ static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status)  	/* check irqstatus */  	if (!(*status & OMAP_HDQ_INT_STATUS_TXCOMPLETE)) {  		dev_dbg(hdq_data->dev, "timeout waiting for" -			"TXCOMPLETE/RXCOMPLETE, %x", *status); +			" TXCOMPLETE/RXCOMPLETE, %x", *status);  		ret = -ETIMEDOUT;  		goto out;  	} @@ -198,7 +194,7 @@ static int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status)  			OMAP_HDQ_FLAG_CLEAR, &tmp_status);  	if (ret) {  		dev_dbg(hdq_data->dev, "timeout waiting GO bit" -			"return to zero, %x", tmp_status); +			" return to zero, %x", tmp_status);  	}  out: @@ -341,7 +337,7 @@ static int omap_hdq_break(struct hdq_data *hdq_data)  			&tmp_status);  	if (ret)  		dev_dbg(hdq_data->dev, "timeout waiting INIT&GO bits" -			"return to zero, %x", tmp_status); +			" return to zero, %x", tmp_status);  out:  	mutex_unlock(&hdq_data->hdq_mutex); @@ -353,7 +349,6 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val)  {  	int ret = 0;  	u8 status; -	unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT;  	ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);  	if (ret < 0) { @@ -371,22 +366,20 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val)  			OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO,  			OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO);  		/* -		 * The RX comes immediately after TX. It -		 * triggers another interrupt before we -		 * sleep. So we have to wait for RXCOMPLETE bit. +		 * The RX comes immediately after TX.  		 */ -		while (!(hdq_data->hdq_irqstatus -			& OMAP_HDQ_INT_STATUS_RXCOMPLETE) -			&& time_before(jiffies, timeout)) { -			schedule_timeout_uninterruptible(1); -		} +		wait_event_timeout(hdq_wait_queue, +				   (hdq_data->hdq_irqstatus +				    & OMAP_HDQ_INT_STATUS_RXCOMPLETE), +				   OMAP_HDQ_TIMEOUT); +  		hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, 0,  			OMAP_HDQ_CTRL_STATUS_DIR);  		status = hdq_data->hdq_irqstatus;  		/* check irqstatus */  		if (!(status & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) {  			dev_dbg(hdq_data->dev, "timeout waiting for" -				"RXCOMPLETE, %x", status); +				" RXCOMPLETE, %x", status);  			ret = -ETIMEDOUT;  			goto out;  		} @@ -396,7 +389,7 @@ static int hdq_read_byte(struct hdq_data *hdq_data, u8 *val)  out:  	mutex_unlock(&hdq_data->hdq_mutex);  rtn: -	return 0; +	return ret;  } @@ -419,17 +412,8 @@ static int omap_hdq_get(struct hdq_data *hdq_data)  		hdq_data->hdq_usecount++;  		try_module_get(THIS_MODULE);  		if (1 == hdq_data->hdq_usecount) { -			if (clk_enable(hdq_data->hdq_ick)) { -				dev_dbg(hdq_data->dev, "Can not enable ick\n"); -				ret = -ENODEV; -				goto clk_err; -			} -			if (clk_enable(hdq_data->hdq_fck)) { -				dev_dbg(hdq_data->dev, "Can not enable fck\n"); -				clk_disable(hdq_data->hdq_ick); -				ret = -ENODEV; -				goto clk_err; -			} + +			pm_runtime_get_sync(hdq_data->dev);  			/* make sure HDQ is out of reset */  			if (!(hdq_reg_in(hdq_data, OMAP_HDQ_SYSSTATUS) & @@ -450,9 +434,6 @@ static int omap_hdq_get(struct hdq_data *hdq_data)  		}  	} -clk_err: -	clk_put(hdq_data->hdq_ick); -	clk_put(hdq_data->hdq_fck);  out:  	mutex_unlock(&hdq_data->hdq_mutex);  rtn: @@ -470,15 +451,13 @@ static int omap_hdq_put(struct hdq_data *hdq_data)  	if (0 == hdq_data->hdq_usecount) {  		dev_dbg(hdq_data->dev, "attempt to decrement use count" -			"when it is zero"); +			" when it is zero");  		ret = -EINVAL;  	} else {  		hdq_data->hdq_usecount--;  		module_put(THIS_MODULE); -		if (0 == hdq_data->hdq_usecount) { -			clk_disable(hdq_data->hdq_ick); -			clk_disable(hdq_data->hdq_fck); -		} +		if (0 == hdq_data->hdq_usecount) +			pm_runtime_put_sync(hdq_data->dev);  	}  	mutex_unlock(&hdq_data->hdq_mutex); @@ -540,12 +519,12 @@ static void omap_w1_write_byte(void *_hdq, u8 byte)  	mutex_unlock(&hdq_data->hdq_mutex);  	ret = hdq_write_byte(hdq_data, byte, &status); -	if (ret == 0) { +	if (ret < 0) {  		dev_dbg(hdq_data->dev, "TX failure:Ctrl status %x\n", status);  		return;  	} -	/* Second write, data transfered. Release the module */ +	/* Second write, data transferred. Release the module */  	if (hdq_data->init_trans > 1) {  		omap_hdq_put(hdq_data);  		ret = mutex_lock_interruptible(&hdq_data->hdq_mutex); @@ -556,72 +535,35 @@ static void omap_w1_write_byte(void *_hdq, u8 byte)  		hdq_data->init_trans = 0;  		mutex_unlock(&hdq_data->hdq_mutex);  	} - -	return;  } -static int __devinit omap_hdq_probe(struct platform_device *pdev) +static int omap_hdq_probe(struct platform_device *pdev)  { +	struct device *dev = &pdev->dev;  	struct hdq_data *hdq_data;  	struct resource *res;  	int ret, irq;  	u8 rev; -	hdq_data = kmalloc(sizeof(*hdq_data), GFP_KERNEL); +	hdq_data = devm_kzalloc(dev, sizeof(*hdq_data), GFP_KERNEL);  	if (!hdq_data) {  		dev_dbg(&pdev->dev, "unable to allocate memory\n"); -		ret = -ENOMEM; -		goto err_kmalloc; +		return -ENOMEM;  	} -	hdq_data->dev = &pdev->dev; +	hdq_data->dev = dev;  	platform_set_drvdata(pdev, hdq_data);  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	if (!res) { -		dev_dbg(&pdev->dev, "unable to get resource\n"); -		ret = -ENXIO; -		goto err_resource; -	} - -	hdq_data->hdq_base = ioremap(res->start, SZ_4K); -	if (!hdq_data->hdq_base) { -		dev_dbg(&pdev->dev, "ioremap failed\n"); -		ret = -EINVAL; -		goto err_ioremap; -	} - -	/* get interface & functional clock objects */ -	hdq_data->hdq_ick = clk_get(&pdev->dev, "ick"); -	hdq_data->hdq_fck = clk_get(&pdev->dev, "fck"); - -	if (IS_ERR(hdq_data->hdq_ick) || IS_ERR(hdq_data->hdq_fck)) { -		dev_dbg(&pdev->dev, "Can't get HDQ clock objects\n"); -		if (IS_ERR(hdq_data->hdq_ick)) { -			ret = PTR_ERR(hdq_data->hdq_ick); -			goto err_clk; -		} -		if (IS_ERR(hdq_data->hdq_fck)) { -			ret = PTR_ERR(hdq_data->hdq_fck); -			clk_put(hdq_data->hdq_ick); -			goto err_clk; -		} -	} +	hdq_data->hdq_base = devm_ioremap_resource(dev, res); +	if (IS_ERR(hdq_data->hdq_base)) +		return PTR_ERR(hdq_data->hdq_base);  	hdq_data->hdq_usecount = 0;  	mutex_init(&hdq_data->hdq_mutex); -	if (clk_enable(hdq_data->hdq_ick)) { -		dev_dbg(&pdev->dev, "Can not enable ick\n"); -		ret = -ENODEV; -		goto err_intfclk; -	} - -	if (clk_enable(hdq_data->hdq_fck)) { -		dev_dbg(&pdev->dev, "Can not enable fck\n"); -		ret = -ENODEV; -		goto err_fnclk; -	} +	pm_runtime_enable(&pdev->dev); +	pm_runtime_get_sync(&pdev->dev);  	rev = hdq_reg_in(hdq_data, OMAP_HDQ_REVISION);  	dev_info(&pdev->dev, "OMAP HDQ Hardware Rev %c.%c. Driver in %s mode\n", @@ -635,7 +577,7 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev)  		goto err_irq;  	} -	ret = request_irq(irq, hdq_isr, IRQF_DISABLED, "omap_hdq", hdq_data); +	ret = devm_request_irq(dev, irq, hdq_isr, 0, "omap_hdq", hdq_data);  	if (ret < 0) {  		dev_dbg(&pdev->dev, "could not request irq\n");  		goto err_irq; @@ -643,9 +585,7 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev)  	omap_hdq_break(hdq_data); -	/* don't clock the HDQ until it is needed */ -	clk_disable(hdq_data->hdq_ick); -	clk_disable(hdq_data->hdq_fck); +	pm_runtime_put_sync(&pdev->dev);  	omap_w1_master.data = hdq_data; @@ -657,28 +597,12 @@ static int __devinit omap_hdq_probe(struct platform_device *pdev)  	return 0; -err_w1:  err_irq: -	clk_disable(hdq_data->hdq_fck); - -err_fnclk: -	clk_disable(hdq_data->hdq_ick); - -err_intfclk: -	clk_put(hdq_data->hdq_ick); -	clk_put(hdq_data->hdq_fck); - -err_clk: -	iounmap(hdq_data->hdq_base); - -err_ioremap: -err_resource: -	platform_set_drvdata(pdev, NULL); -	kfree(hdq_data); +	pm_runtime_put_sync(&pdev->dev); +err_w1: +	pm_runtime_disable(&pdev->dev); -err_kmalloc:  	return ret; -  }  static int omap_hdq_remove(struct platform_device *pdev) @@ -696,29 +620,12 @@ static int omap_hdq_remove(struct platform_device *pdev)  	mutex_unlock(&hdq_data->hdq_mutex);  	/* remove module dependency */ -	clk_put(hdq_data->hdq_ick); -	clk_put(hdq_data->hdq_fck); -	free_irq(INT_24XX_HDQ_IRQ, hdq_data); -	platform_set_drvdata(pdev, NULL); -	iounmap(hdq_data->hdq_base); -	kfree(hdq_data); +	pm_runtime_disable(&pdev->dev);  	return 0;  } -static int __init -omap_hdq_init(void) -{ -	return platform_driver_register(&omap_hdq_driver); -} -module_init(omap_hdq_init); - -static void __exit -omap_hdq_exit(void) -{ -	platform_driver_unregister(&omap_hdq_driver); -} -module_exit(omap_hdq_exit); +module_platform_driver(omap_hdq_driver);  module_param(w1_id, int, S_IRUSR);  MODULE_PARM_DESC(w1_id, "1-wire id for the slave detection");  | 
