19f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature/*
29f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature * drivers/w1/masters/omap_hdq.c
39f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature *
4c354a86484b61e32100eb94c1f3f0aa512958ceePaul Walmsley * Copyright (C) 2007,2012 Texas Instruments, Inc.
59f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature *
69f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature * This file is licensed under the terms of the GNU General Public License
79f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature * version 2. This program is licensed "as is" without any warranty of any
89f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature * kind, whether express or implied.
99f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature *
109f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature */
119f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#include <linux/kernel.h>
129f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#include <linux/module.h>
139f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#include <linux/platform_device.h>
149f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#include <linux/interrupt.h>
155a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h>
169f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#include <linux/err.h>
179f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#include <linux/io.h>
1881fa08f25bd24fc51557a2d2364fa1ab5e7407b4Amit Kucheria#include <linux/sched.h>
19c354a86484b61e32100eb94c1f3f0aa512958ceePaul Walmsley#include <linux/pm_runtime.h>
209f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
219f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#include "../w1.h"
229f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#include "../w1_int.h"
239f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
249f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define	MOD_NAME	"OMAP_HDQ:"
259f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
269f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_REVISION			0x00
279f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_TX_DATA			0x04
289f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_RX_DATA			0x08
299f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_CTRL_STATUS			0x0c
309f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK	(1<<6)
319f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_CTRL_STATUS_CLOCKENABLE	(1<<5)
329f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_CTRL_STATUS_GO			(1<<4)
339f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_CTRL_STATUS_INITIALIZATION	(1<<2)
349f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_CTRL_STATUS_DIR		(1<<1)
359f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_CTRL_STATUS_MODE		(1<<0)
369f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_INT_STATUS			0x10
379f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_INT_STATUS_TXCOMPLETE		(1<<2)
389f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_INT_STATUS_RXCOMPLETE		(1<<1)
399f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_INT_STATUS_TIMEOUT		(1<<0)
409f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_SYSCONFIG			0x14
419f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_SYSCONFIG_SOFTRESET		(1<<1)
429f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_SYSCONFIG_AUTOIDLE		(1<<0)
439f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_SYSSTATUS			0x18
449f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_SYSSTATUS_RESETDONE		(1<<0)
459f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
469f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_FLAG_CLEAR			0
479f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_FLAG_SET			1
489f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_TIMEOUT			(HZ/5)
499f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
509f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature#define OMAP_HDQ_MAX_USER			4
519f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
529f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic DECLARE_WAIT_QUEUE_HEAD(hdq_wait_queue);
539f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic int w1_id;
549f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
559f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestruct hdq_data {
569f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	struct device		*dev;
579f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	void __iomem		*hdq_base;
589f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* lock status update */
599f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	struct  mutex		hdq_mutex;
609f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	int			hdq_usecount;
619f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	u8			hdq_irqstatus;
629f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* device lock */
639f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	spinlock_t		hdq_spinlock;
649f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/*
659f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	 * Used to control the call to omap_hdq_get and omap_hdq_put.
669f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	 * HDQ Protocol: Write the CMD|REG_address first, followed by
679f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	 * the data wrire or read.
689f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	 */
699f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	int			init_trans;
709f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature};
719f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
72479e2bcecdf19ae44940d38248a3e2f9fd8f2c44Bill Pembertonstatic int omap_hdq_probe(struct platform_device *pdev);
7382849a93aad04c5a438d811081341b245fdade8cBill Pembertonstatic int omap_hdq_remove(struct platform_device *pdev);
749f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
759f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic struct platform_driver omap_hdq_driver = {
769f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	.probe =	omap_hdq_probe,
77f91a66c97b38a504827803bb93f83a7b85e50e5aBill Pemberton	.remove =	omap_hdq_remove,
789f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	.driver =	{
799f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		.name =	"omap_hdq",
809f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	},
819f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature};
829f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
839f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic u8 omap_w1_read_byte(void *_hdq);
849f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic void omap_w1_write_byte(void *_hdq, u8 byte);
859f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic u8 omap_w1_reset_bus(void *_hdq);
8606b0d4dc14a44dd9b57321c24f7eeb10b345abd8Stanley.Miaostatic void omap_w1_search_bus(void *_hdq, struct w1_master *master_dev,
8706b0d4dc14a44dd9b57321c24f7eeb10b345abd8Stanley.Miao		u8 search_type,	w1_slave_found_callback slave_found);
889f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
899f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
909f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic struct w1_bus_master omap_w1_master = {
919f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	.read_byte	= omap_w1_read_byte,
929f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	.write_byte	= omap_w1_write_byte,
939f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	.reset_bus	= omap_w1_reset_bus,
949f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	.search		= omap_w1_search_bus,
959f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature};
969f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
979f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature/* HDQ register I/O routines */
989f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic inline u8 hdq_reg_in(struct hdq_data *hdq_data, u32 offset)
999f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
1002acd089471d93373e051c6b1f9f9e0d9e51a76bcPaul Walmsley	return __raw_readl(hdq_data->hdq_base + offset);
1019f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
1029f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
1039f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic inline void hdq_reg_out(struct hdq_data *hdq_data, u32 offset, u8 val)
1049f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
1052acd089471d93373e051c6b1f9f9e0d9e51a76bcPaul Walmsley	__raw_writel(val, hdq_data->hdq_base + offset);
1069f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
1079f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
1089f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic inline u8 hdq_reg_merge(struct hdq_data *hdq_data, u32 offset,
1099f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			u8 val, u8 mask)
1109f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
1112acd089471d93373e051c6b1f9f9e0d9e51a76bcPaul Walmsley	u8 new_val = (__raw_readl(hdq_data->hdq_base + offset) & ~mask)
1129f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			| (val & mask);
1132acd089471d93373e051c6b1f9f9e0d9e51a76bcPaul Walmsley	__raw_writel(new_val, hdq_data->hdq_base + offset);
1149f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
1159f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	return new_val;
1169f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
1179f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
1189f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature/*
1199f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature * Wait for one or more bits in flag change.
1209f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature * HDQ_FLAG_SET: wait until any bit in the flag is set.
1219f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature * HDQ_FLAG_CLEAR: wait until all bits in the flag are cleared.
1229f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature * return 0 on success and -ETIMEDOUT in the case of timeout.
1239f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature */
1249f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic int hdq_wait_for_flag(struct hdq_data *hdq_data, u32 offset,
1259f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		u8 flag, u8 flag_set, u8 *status)
1269f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
1279f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	int ret = 0;
1289f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	unsigned long timeout = jiffies + OMAP_HDQ_TIMEOUT;
1299f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
1309f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (flag_set == OMAP_HDQ_FLAG_CLEAR) {
1319f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		/* wait for the flag clear */
1329f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		while (((*status = hdq_reg_in(hdq_data, offset)) & flag)
1339f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			&& time_before(jiffies, timeout)) {
1349f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			schedule_timeout_uninterruptible(1);
1359f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		}
1369f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		if (*status & flag)
1379f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			ret = -ETIMEDOUT;
1389f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	} else if (flag_set == OMAP_HDQ_FLAG_SET) {
1399f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		/* wait for the flag set */
1409f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		while (!((*status = hdq_reg_in(hdq_data, offset)) & flag)
1419f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			&& time_before(jiffies, timeout)) {
1429f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			schedule_timeout_uninterruptible(1);
1439f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		}
1449f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		if (!(*status & flag))
1459f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			ret = -ETIMEDOUT;
1469f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	} else
1479f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		return -EINVAL;
1489f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
1499f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	return ret;
1509f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
1519f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
1529f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature/* write out a byte and fill *status with HDQ_INT_STATUS */
1539f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic int hdq_write_byte(struct hdq_data *hdq_data, u8 val, u8 *status)
1549f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
1559f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	int ret;
1569f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	u8 tmp_status;
1579f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	unsigned long irqflags;
1589f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
1599f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	*status = 0;
1609f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
1619f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
1629f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* clear interrupt flags via a dummy read */
1639f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS);
1649f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* ISR loads it with new INT_STATUS */
1659f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	hdq_data->hdq_irqstatus = 0;
1669f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
1679f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
1689f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	hdq_reg_out(hdq_data, OMAP_HDQ_TX_DATA, val);
1699f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
1709f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* set the GO bit */
1719f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, OMAP_HDQ_CTRL_STATUS_GO,
1729f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO);
1739f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* wait for the TXCOMPLETE bit */
1749f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	ret = wait_event_timeout(hdq_wait_queue,
1759f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT);
1769f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (ret == 0) {
1779f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		dev_dbg(hdq_data->dev, "TX wait elapsed\n");
1787b5362a603a1ecc9a25b97dafd702b8098090f41NeilBrown		ret = -ETIMEDOUT;
1799f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		goto out;
1809f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
1819f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
1829f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	*status = hdq_data->hdq_irqstatus;
1839f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* check irqstatus */
1849f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (!(*status & OMAP_HDQ_INT_STATUS_TXCOMPLETE)) {
1859f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		dev_dbg(hdq_data->dev, "timeout waiting for"
1867b5362a603a1ecc9a25b97dafd702b8098090f41NeilBrown			" TXCOMPLETE/RXCOMPLETE, %x", *status);
1879f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		ret = -ETIMEDOUT;
1889f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		goto out;
1899f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
1909f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
1919f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* wait for the GO bit return to zero */
1929f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	ret = hdq_wait_for_flag(hdq_data, OMAP_HDQ_CTRL_STATUS,
1939f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			OMAP_HDQ_CTRL_STATUS_GO,
1949f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			OMAP_HDQ_FLAG_CLEAR, &tmp_status);
1959f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (ret) {
1969f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		dev_dbg(hdq_data->dev, "timeout waiting GO bit"
1977b5362a603a1ecc9a25b97dafd702b8098090f41NeilBrown			" return to zero, %x", tmp_status);
1989f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
1999f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
2009f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkatureout:
2019f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	return ret;
2029f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
2039f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
2049f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature/* HDQ Interrupt service routine */
2059f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic irqreturn_t hdq_isr(int irq, void *_hdq)
2069f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
2079f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	struct hdq_data *hdq_data = _hdq;
2089f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	unsigned long irqflags;
2099f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
2109f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
2119f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	hdq_data->hdq_irqstatus = hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS);
2129f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
2139f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	dev_dbg(hdq_data->dev, "hdq_isr: %x", hdq_data->hdq_irqstatus);
2149f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
2159f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (hdq_data->hdq_irqstatus &
2169f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		(OMAP_HDQ_INT_STATUS_TXCOMPLETE | OMAP_HDQ_INT_STATUS_RXCOMPLETE
2179f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		| OMAP_HDQ_INT_STATUS_TIMEOUT)) {
2189f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		/* wake up sleeping process */
2199f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		wake_up(&hdq_wait_queue);
2209f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
2219f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
2229f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	return IRQ_HANDLED;
2239f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
2249f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
2259f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature/* HDQ Mode: always return success */
2269f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic u8 omap_w1_reset_bus(void *_hdq)
2279f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
2289f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	return 0;
2299f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
2309f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
2319f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature/* W1 search callback function */
23206b0d4dc14a44dd9b57321c24f7eeb10b345abd8Stanley.Miaostatic void omap_w1_search_bus(void *_hdq, struct w1_master *master_dev,
23306b0d4dc14a44dd9b57321c24f7eeb10b345abd8Stanley.Miao		u8 search_type, w1_slave_found_callback slave_found)
2349f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
2359f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	u64 module_id, rn_le, cs, id;
2369f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
2379f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (w1_id)
2389f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		module_id = w1_id;
2399f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	else
2409f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		module_id = 0x1;
2419f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
2429f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	rn_le = cpu_to_le64(module_id);
2439f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/*
2449f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	 * HDQ might not obey truly the 1-wire spec.
2459f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	 * So calculate CRC based on module parameter.
2469f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	 */
2479f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	cs = w1_calc_crc8((u8 *)&rn_le, 7);
2489f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	id = (cs << 56) | module_id;
2499f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
25006b0d4dc14a44dd9b57321c24f7eeb10b345abd8Stanley.Miao	slave_found(master_dev, id);
2519f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
2529f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
2539f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic int _omap_hdq_reset(struct hdq_data *hdq_data)
2549f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
2559f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	int ret;
2569f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	u8 tmp_status;
2579f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
2589f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG, OMAP_HDQ_SYSCONFIG_SOFTRESET);
2599f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/*
2609f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	 * Select HDQ mode & enable clocks.
2619f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	 * It is observed that INT flags can't be cleared via a read and GO/INIT
2629f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	 * won't return to zero if interrupt is disabled. So we always enable
2639f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	 * interrupt.
2649f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	 */
2659f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS,
2669f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		OMAP_HDQ_CTRL_STATUS_CLOCKENABLE |
2679f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK);
2689f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
2699f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* wait for reset to complete */
2709f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	ret = hdq_wait_for_flag(hdq_data, OMAP_HDQ_SYSSTATUS,
2719f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		OMAP_HDQ_SYSSTATUS_RESETDONE, OMAP_HDQ_FLAG_SET, &tmp_status);
2729f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (ret)
2739f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		dev_dbg(hdq_data->dev, "timeout waiting HDQ reset, %x",
2749f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature				tmp_status);
2759f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	else {
2769f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS,
2779f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			OMAP_HDQ_CTRL_STATUS_CLOCKENABLE |
2789f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK);
2799f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG,
2809f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			OMAP_HDQ_SYSCONFIG_AUTOIDLE);
2819f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
2829f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
2839f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	return ret;
2849f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
2859f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
2869f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature/* Issue break pulse to the device */
2879f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic int omap_hdq_break(struct hdq_data *hdq_data)
2889f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
2899f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	int ret = 0;
2909f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	u8 tmp_status;
2919f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	unsigned long irqflags;
2929f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
2939f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
2949f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (ret < 0) {
2959f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		dev_dbg(hdq_data->dev, "Could not acquire mutex\n");
2969f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		ret = -EINTR;
2979f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		goto rtn;
2989f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
2999f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
3009f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	spin_lock_irqsave(&hdq_data->hdq_spinlock, irqflags);
3019f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* clear interrupt flags via a dummy read */
3029f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS);
3039f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* ISR loads it with new INT_STATUS */
3049f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	hdq_data->hdq_irqstatus = 0;
3059f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	spin_unlock_irqrestore(&hdq_data->hdq_spinlock, irqflags);
3069f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
3079f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* set the INIT and GO bit */
3089f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS,
3099f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		OMAP_HDQ_CTRL_STATUS_INITIALIZATION | OMAP_HDQ_CTRL_STATUS_GO,
3109f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_INITIALIZATION |
3119f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		OMAP_HDQ_CTRL_STATUS_GO);
3129f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
3139f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* wait for the TIMEOUT bit */
3149f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	ret = wait_event_timeout(hdq_wait_queue,
3159f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		hdq_data->hdq_irqstatus, OMAP_HDQ_TIMEOUT);
3169f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (ret == 0) {
3179f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		dev_dbg(hdq_data->dev, "break wait elapsed\n");
3189f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		ret = -EINTR;
3199f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		goto out;
3209f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
3219f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
3229f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	tmp_status = hdq_data->hdq_irqstatus;
3239f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* check irqstatus */
3249f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (!(tmp_status & OMAP_HDQ_INT_STATUS_TIMEOUT)) {
3259f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		dev_dbg(hdq_data->dev, "timeout waiting for TIMEOUT, %x",
3269f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature				tmp_status);
3279f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		ret = -ETIMEDOUT;
3289f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		goto out;
3299f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
3309f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/*
3319f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	 * wait for both INIT and GO bits rerurn to zero.
3329f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	 * zero wait time expected for interrupt mode.
3339f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	 */
3349f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	ret = hdq_wait_for_flag(hdq_data, OMAP_HDQ_CTRL_STATUS,
3359f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			OMAP_HDQ_CTRL_STATUS_INITIALIZATION |
3369f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			OMAP_HDQ_CTRL_STATUS_GO, OMAP_HDQ_FLAG_CLEAR,
3379f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			&tmp_status);
3389f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (ret)
3399f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		dev_dbg(hdq_data->dev, "timeout waiting INIT&GO bits"
3407b5362a603a1ecc9a25b97dafd702b8098090f41NeilBrown			" return to zero, %x", tmp_status);
3419f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
3429f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkatureout:
3439f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	mutex_unlock(&hdq_data->hdq_mutex);
3449f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturertn:
3459f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	return ret;
3469f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
3479f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
3489f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic int hdq_read_byte(struct hdq_data *hdq_data, u8 *val)
3499f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
3509f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	int ret = 0;
3519f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	u8 status;
3529f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
3539f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
3549f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (ret < 0) {
3559f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		ret = -EINTR;
3569f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		goto rtn;
3579f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
3589f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
3599f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (!hdq_data->hdq_usecount) {
3609f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		ret = -EINVAL;
3619f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		goto out;
3629f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
3639f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
3649f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (!(hdq_data->hdq_irqstatus & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) {
3659f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS,
3669f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO,
3679f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			OMAP_HDQ_CTRL_STATUS_DIR | OMAP_HDQ_CTRL_STATUS_GO);
3689f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		/*
369b7e938d06d0de43bdbee8844a8736c81480c1031NeilBrown		 * The RX comes immediately after TX.
3709f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		 */
371b7e938d06d0de43bdbee8844a8736c81480c1031NeilBrown		wait_event_timeout(hdq_wait_queue,
372b7e938d06d0de43bdbee8844a8736c81480c1031NeilBrown				   (hdq_data->hdq_irqstatus
373b7e938d06d0de43bdbee8844a8736c81480c1031NeilBrown				    & OMAP_HDQ_INT_STATUS_RXCOMPLETE),
374b7e938d06d0de43bdbee8844a8736c81480c1031NeilBrown				   OMAP_HDQ_TIMEOUT);
375b7e938d06d0de43bdbee8844a8736c81480c1031NeilBrown
3769f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		hdq_reg_merge(hdq_data, OMAP_HDQ_CTRL_STATUS, 0,
3779f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			OMAP_HDQ_CTRL_STATUS_DIR);
3789f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		status = hdq_data->hdq_irqstatus;
3799f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		/* check irqstatus */
3809f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		if (!(status & OMAP_HDQ_INT_STATUS_RXCOMPLETE)) {
3819f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			dev_dbg(hdq_data->dev, "timeout waiting for"
3827b5362a603a1ecc9a25b97dafd702b8098090f41NeilBrown				" RXCOMPLETE, %x", status);
3839f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			ret = -ETIMEDOUT;
3849f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			goto out;
3859f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		}
3869f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
3879f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* the data is ready. Read it in! */
3889f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	*val = hdq_reg_in(hdq_data, OMAP_HDQ_RX_DATA);
3899f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkatureout:
3909f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	mutex_unlock(&hdq_data->hdq_mutex);
3919f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturertn:
3927b5362a603a1ecc9a25b97dafd702b8098090f41NeilBrown	return ret;
3939f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
3949f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
3959f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
3969f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature/* Enable clocks and set the controller to HDQ mode */
3979f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic int omap_hdq_get(struct hdq_data *hdq_data)
3989f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
3999f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	int ret = 0;
4009f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
4019f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
4029f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (ret < 0) {
4039f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		ret = -EINTR;
4049f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		goto rtn;
4059f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
4069f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
4079f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (OMAP_HDQ_MAX_USER == hdq_data->hdq_usecount) {
4089f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		dev_dbg(hdq_data->dev, "attempt to exceed the max use count");
4099f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		ret = -EINVAL;
4109f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		goto out;
4119f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	} else {
4129f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		hdq_data->hdq_usecount++;
4139f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		try_module_get(THIS_MODULE);
4149f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		if (1 == hdq_data->hdq_usecount) {
415c354a86484b61e32100eb94c1f3f0aa512958ceePaul Walmsley
416c354a86484b61e32100eb94c1f3f0aa512958ceePaul Walmsley			pm_runtime_get_sync(hdq_data->dev);
4179f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
4189f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			/* make sure HDQ is out of reset */
4199f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			if (!(hdq_reg_in(hdq_data, OMAP_HDQ_SYSSTATUS) &
4209f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature				OMAP_HDQ_SYSSTATUS_RESETDONE)) {
4219f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature				ret = _omap_hdq_reset(hdq_data);
4229f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature				if (ret)
4239f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature					/* back up the count */
4249f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature					hdq_data->hdq_usecount--;
4259f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			} else {
4269f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature				/* select HDQ mode & enable clocks */
4279f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature				hdq_reg_out(hdq_data, OMAP_HDQ_CTRL_STATUS,
4289f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature					OMAP_HDQ_CTRL_STATUS_CLOCKENABLE |
4299f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature					OMAP_HDQ_CTRL_STATUS_INTERRUPTMASK);
4309f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature				hdq_reg_out(hdq_data, OMAP_HDQ_SYSCONFIG,
4319f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature					OMAP_HDQ_SYSCONFIG_AUTOIDLE);
4329f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature				hdq_reg_in(hdq_data, OMAP_HDQ_INT_STATUS);
4339f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			}
4349f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		}
4359f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
4369f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
4379f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkatureout:
4389f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	mutex_unlock(&hdq_data->hdq_mutex);
4399f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturertn:
4409f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	return ret;
4419f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
4429f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
4439f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature/* Disable clocks to the module */
4449f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic int omap_hdq_put(struct hdq_data *hdq_data)
4459f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
4469f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	int ret = 0;
4479f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
4489f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
4499f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (ret < 0)
4509f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		return -EINTR;
4519f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
4529f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (0 == hdq_data->hdq_usecount) {
4539f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		dev_dbg(hdq_data->dev, "attempt to decrement use count"
4547b5362a603a1ecc9a25b97dafd702b8098090f41NeilBrown			" when it is zero");
4559f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		ret = -EINVAL;
4569f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	} else {
4579f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		hdq_data->hdq_usecount--;
4589f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		module_put(THIS_MODULE);
459c354a86484b61e32100eb94c1f3f0aa512958ceePaul Walmsley		if (0 == hdq_data->hdq_usecount)
460c354a86484b61e32100eb94c1f3f0aa512958ceePaul Walmsley			pm_runtime_put_sync(hdq_data->dev);
4619f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
4629f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	mutex_unlock(&hdq_data->hdq_mutex);
4639f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
4649f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	return ret;
4659f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
4669f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
4679f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature/* Read a byte of data from the device */
4689f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic u8 omap_w1_read_byte(void *_hdq)
4699f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
4709f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	struct hdq_data *hdq_data = _hdq;
4719f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	u8 val = 0;
4729f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	int ret;
4739f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
4749f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	ret = hdq_read_byte(hdq_data, &val);
4759f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (ret) {
4769f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
4779f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		if (ret < 0) {
4789f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			dev_dbg(hdq_data->dev, "Could not acquire mutex\n");
4799f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			return -EINTR;
4809f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		}
4819f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		hdq_data->init_trans = 0;
4829f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		mutex_unlock(&hdq_data->hdq_mutex);
4839f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		omap_hdq_put(hdq_data);
4849f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		return -1;
4859f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
4869f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
4879f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* Write followed by a read, release the module */
4889f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (hdq_data->init_trans) {
4899f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
4909f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		if (ret < 0) {
4919f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			dev_dbg(hdq_data->dev, "Could not acquire mutex\n");
4929f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			return -EINTR;
4939f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		}
4949f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		hdq_data->init_trans = 0;
4959f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		mutex_unlock(&hdq_data->hdq_mutex);
4969f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		omap_hdq_put(hdq_data);
4979f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
4989f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
4999f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	return val;
5009f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
5019f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
5029f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature/* Write a byte of data to the device */
5039f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturestatic void omap_w1_write_byte(void *_hdq, u8 byte)
5049f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
5059f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	struct hdq_data *hdq_data = _hdq;
5069f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	int ret;
5079f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	u8 status;
5089f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
5099f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* First write to initialize the transfer */
5109f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (hdq_data->init_trans == 0)
5119f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		omap_hdq_get(hdq_data);
5129f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
5139f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
5149f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (ret < 0) {
5159f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		dev_dbg(hdq_data->dev, "Could not acquire mutex\n");
5169f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		return;
5179f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
5189f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	hdq_data->init_trans++;
5199f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	mutex_unlock(&hdq_data->hdq_mutex);
5209f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
5219f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	ret = hdq_write_byte(hdq_data, byte, &status);
5227b5362a603a1ecc9a25b97dafd702b8098090f41NeilBrown	if (ret < 0) {
5239f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		dev_dbg(hdq_data->dev, "TX failure:Ctrl status %x\n", status);
5249f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		return;
5259f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
5269f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
52725985edcedea6396277003854657b5f3cb31a628Lucas De Marchi	/* Second write, data transferred. Release the module */
5289f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (hdq_data->init_trans > 1) {
5299f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		omap_hdq_put(hdq_data);
5309f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		ret = mutex_lock_interruptible(&hdq_data->hdq_mutex);
5319f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		if (ret < 0) {
5329f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			dev_dbg(hdq_data->dev, "Could not acquire mutex\n");
5339f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature			return;
5349f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		}
5359f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		hdq_data->init_trans = 0;
5369f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		mutex_unlock(&hdq_data->hdq_mutex);
5379f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
5389f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
5399f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
540479e2bcecdf19ae44940d38248a3e2f9fd8f2c44Bill Pembertonstatic int omap_hdq_probe(struct platform_device *pdev)
5419f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
54219afea50f12b2dc5e2aaca488d1733188d06a619Felipe Balbi	struct device *dev = &pdev->dev;
5439f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	struct hdq_data *hdq_data;
5449f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	struct resource *res;
5459f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	int ret, irq;
5469f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	u8 rev;
5479f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
54819afea50f12b2dc5e2aaca488d1733188d06a619Felipe Balbi	hdq_data = devm_kzalloc(dev, sizeof(*hdq_data), GFP_KERNEL);
5499f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (!hdq_data) {
5509f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		dev_dbg(&pdev->dev, "unable to allocate memory\n");
55119afea50f12b2dc5e2aaca488d1733188d06a619Felipe Balbi		return -ENOMEM;
5529f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
5539f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
55419afea50f12b2dc5e2aaca488d1733188d06a619Felipe Balbi	hdq_data->dev = dev;
5559f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	platform_set_drvdata(pdev, hdq_data);
5569f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
5579f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
5584d6dc3a73543336be8d81ba748772c09730cf557Thierry Reding	hdq_data->hdq_base = devm_ioremap_resource(dev, res);
5594d6dc3a73543336be8d81ba748772c09730cf557Thierry Reding	if (IS_ERR(hdq_data->hdq_base))
5604d6dc3a73543336be8d81ba748772c09730cf557Thierry Reding		return PTR_ERR(hdq_data->hdq_base);
5619f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
5629f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	hdq_data->hdq_usecount = 0;
5639f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	mutex_init(&hdq_data->hdq_mutex);
5649f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
565c354a86484b61e32100eb94c1f3f0aa512958ceePaul Walmsley	pm_runtime_enable(&pdev->dev);
566c354a86484b61e32100eb94c1f3f0aa512958ceePaul Walmsley	pm_runtime_get_sync(&pdev->dev);
5679f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
5689f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	rev = hdq_reg_in(hdq_data, OMAP_HDQ_REVISION);
5699f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	dev_info(&pdev->dev, "OMAP HDQ Hardware Rev %c.%c. Driver in %s mode\n",
5709f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		(rev >> 4) + '0', (rev & 0x0f) + '0', "Interrupt");
5719f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
5729f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	spin_lock_init(&hdq_data->hdq_spinlock);
5739f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
5749f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	irq = platform_get_irq(pdev, 0);
5759f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (irq	< 0) {
5769f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		ret = -ENXIO;
5779f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		goto err_irq;
5789f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
5799f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
580fe576a580f2a62c43bb81b18700576a66b332c8fMichael Opdenacker	ret = devm_request_irq(dev, irq, hdq_isr, 0, "omap_hdq", hdq_data);
5819f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (ret < 0) {
5829f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		dev_dbg(&pdev->dev, "could not request irq\n");
5839f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		goto err_irq;
5849f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
5859f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
5869f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	omap_hdq_break(hdq_data);
5879f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
588c354a86484b61e32100eb94c1f3f0aa512958ceePaul Walmsley	pm_runtime_put_sync(&pdev->dev);
5899f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
5909f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	omap_w1_master.data = hdq_data;
5919f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
5929f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	ret = w1_add_master_device(&omap_w1_master);
5939f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (ret) {
5949f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		dev_dbg(&pdev->dev, "Failure in registering w1 master\n");
5959f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		goto err_w1;
5969f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
5979f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
5989f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	return 0;
5999f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
6009f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkatureerr_irq:
601c354a86484b61e32100eb94c1f3f0aa512958ceePaul Walmsley	pm_runtime_put_sync(&pdev->dev);
602c354a86484b61e32100eb94c1f3f0aa512958ceePaul Walmsleyerr_w1:
603c354a86484b61e32100eb94c1f3f0aa512958ceePaul Walmsley	pm_runtime_disable(&pdev->dev);
60480d02d273641d515269c016d9e8da5882e4432e4Julia Lawall
6059f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	return ret;
6069f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
6079f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
60882849a93aad04c5a438d811081341b245fdade8cBill Pembertonstatic int omap_hdq_remove(struct platform_device *pdev)
6099f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature{
6109f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	struct hdq_data *hdq_data = platform_get_drvdata(pdev);
6119f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
6129f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	mutex_lock(&hdq_data->hdq_mutex);
6139f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
6149f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	if (hdq_data->hdq_usecount) {
6159f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		dev_dbg(&pdev->dev, "removed when use count is not zero\n");
6162020002a878403a6858868d85a43623f74859dbaStoyan Gaydarov		mutex_unlock(&hdq_data->hdq_mutex);
6179f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature		return -EBUSY;
6189f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	}
6199f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
6209f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	mutex_unlock(&hdq_data->hdq_mutex);
6219f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
6229f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	/* remove module dependency */
623c354a86484b61e32100eb94c1f3f0aa512958ceePaul Walmsley	pm_runtime_disable(&pdev->dev);
6249f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
6259f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature	return 0;
6269f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature}
6279f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
6288650bbb58062f183ce5d983b6ba4ddd1e9b67f4aFelipe Balbimodule_platform_driver(omap_hdq_driver);
6299f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
6309f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkaturemodule_param(w1_id, int, S_IRUSR);
6319f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan ChikkatureMODULE_PARM_DESC(w1_id, "1-wire id for the slave detection");
6329f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan Chikkature
6339f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan ChikkatureMODULE_AUTHOR("Texas Instruments");
6349f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan ChikkatureMODULE_DESCRIPTION("HDQ driver Library");
6359f2bc79f7dd04adda1fc3be510c9b3d436f846c7Madhusudhan ChikkatureMODULE_LICENSE("GPL");
636