misc: cec: add wait_event for CEC ops

Add wait_event to make sure that CEC functions
do not execute until CEC init completes

Bug 1283088

Change-Id: I1d26360326338f549a14cbf109a24c2935ebe472
Signed-off-by: Shridhar Rasal <srasal@nvidia.com>
Reviewed-on: http://git-master/r/232566
(cherry picked from commit 6e94e976c1e2121d81d19018b79a97d353b11d70)
Signed-off-by: Xia Yang <xiay@nvidia.com>
Reviewed-on: http://git-master/r/346039
Reviewed-on: http://git-master/r/1164139
(cherry picked from commit 794145e9f8c16c7e36119f3652dd185cf12eb5dc)
This commit is contained in:
Shridhar Rasal
2013-05-14 15:00:33 +05:30
committed by Jon Hunter
parent e5c9fb04ed
commit 263ddf4b05
2 changed files with 23 additions and 0 deletions

View File

@@ -46,6 +46,8 @@ int tegra_cec_open(struct inode *inode, struct file *file)
struct tegra_cec *cec = container_of(miscdev,
struct tegra_cec, misc_dev);
dev_dbg(cec->dev, "%s\n", __func__);
wait_event_interruptible(cec->init_waitq, cec->init_done == 1);
file->private_data = cec;
return 0;
@@ -68,6 +70,8 @@ ssize_t tegra_cec_write(struct file *file, const char __user *buffer,
count = 4;
wait_event_interruptible(cec->init_waitq, cec->init_done == 1);
if (copy_from_user(&write_buff, buffer, count))
return -EFAULT;
@@ -102,6 +106,8 @@ ssize_t tegra_cec_read(struct file *file, char __user *buffer,
struct tegra_cec *cec = file->private_data;
count = 2;
wait_event_interruptible(cec->init_waitq, cec->init_done == 1);
if (cec->rx_wake == 0)
if (file->f_flags & O_NONBLOCK)
return -EAGAIN;
@@ -122,6 +128,8 @@ static irqreturn_t tegra_cec_irq_handler(int irq, void *data)
struct tegra_cec *cec = dev_get_drvdata(dev);
unsigned long status;
wait_event_interruptible(cec->init_waitq, cec->init_done == 1);
status = readl(cec->cec_base + TEGRA_CEC_INT_STAT);
if (!status)
@@ -176,6 +184,10 @@ static const struct file_operations tegra_cec_fops = {
static void tegra_cec_init(struct tegra_cec *cec)
{
dev_notice(cec->dev, "%s started\n", __func__);
cec->init_done = 0;
writel(0x00, cec->cec_base + TEGRA_CEC_HW_CONTROL);
writel(0x00, cec->cec_base + TEGRA_CEC_INT_MASK);
writel(0xffffffff, cec->cec_base + TEGRA_CEC_INT_STAT);
@@ -232,6 +244,11 @@ static void tegra_cec_init(struct tegra_cec *cec)
TEGRA_CEC_INT_MASK_RX_REGISTER_FULL |
TEGRA_CEC_INT_MASK_RX_REGISTER_OVERRUN),
cec->cec_base + TEGRA_CEC_INT_MASK);
cec->init_done = 1;
wake_up_interruptible(&cec->init_waitq);
dev_notice(cec->dev, "%s Done.\n", __func__);
}
static void tegra_cec_init_worker(struct work_struct *work)
@@ -301,6 +318,7 @@ static int tegra_cec_probe(struct platform_device *pdev)
cec->tx_wake = 0;
init_waitqueue_head(&cec->rx_waitq);
init_waitqueue_head(&cec->tx_waitq);
init_waitqueue_head(&cec->init_waitq);
platform_set_drvdata(pdev, cec);
/* clear out the hardware. */
@@ -360,6 +378,7 @@ static int tegra_cec_suspend(struct platform_device *pdev, pm_message_t state)
clk_disable(cec->clk);
dev_notice(&pdev->dev, "suspended\n");
return 0;
}
@@ -367,6 +386,8 @@ static int tegra_cec_resume(struct platform_device *pdev)
{
struct tegra_cec *cec = platform_get_drvdata(pdev);
dev_notice(&pdev->dev, "Resuming\n");
clk_enable(cec->clk);
schedule_work(&cec->work);

View File

@@ -27,9 +27,11 @@ struct tegra_cec {
int tegra_cec_irq;
wait_queue_head_t rx_waitq;
wait_queue_head_t tx_waitq;
wait_queue_head_t init_waitq;
unsigned int rx_wake;
unsigned int tx_wake;
unsigned short rx_buffer;
unsigned int init_done;
struct work_struct work;
};
static int tegra_cec_remove(struct platform_device *pdev);