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