diff --git a/drivers/misc/tegra-cec/tegra_cec.c b/drivers/misc/tegra-cec/tegra_cec.c index c34f91f5..3fabac3f 100644 --- a/drivers/misc/tegra-cec/tegra_cec.c +++ b/drivers/misc/tegra-cec/tegra_cec.c @@ -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); diff --git a/drivers/misc/tegra-cec/tegra_cec.h b/drivers/misc/tegra-cec/tegra_cec.h index c94f3996..814e7ba8 100644 --- a/drivers/misc/tegra-cec/tegra_cec.h +++ b/drivers/misc/tegra-cec/tegra_cec.h @@ -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);