--- /dev/null
+/*\r
+ *\r
+ * Copyright (C) 2011 liuyixing <lyx@rock-chips.com>\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ *\r
+ *note: serial driver for IrDA(SIR and FIR) device\r
+ *\r
+ */\r
+\r
+#include <linux/delay.h>\r
+#include <linux/slab.h>\r
+#include <linux/device.h>\r
+#include <linux/serial_core.h>\r
+#include <linux/serial.h>\r
+#include <linux/freezer.h>\r
+#include <mach/board.h>\r
+#include <linux/irq.h>\r
+#include <mach/gpio.h>\r
+\r
+#include "bu92725guw.h"\r
+\r
+struct bu92747_port {\r
+ struct device *dev;\r
+ struct irda_info *pdata;\r
+ struct uart_port port;\r
+ \r
+ int cts; /* last CTS received for flow ctrl */\r
+ int tx_empty; /* last TX empty bit */\r
+\r
+ spinlock_t conf_lock; /* shared data */\r
+ int conf_commit; /* need to make changes */\r
+ int conf; /* configuration for the MAX31000\r
+ * (bits 0-7, bits 8-11 are irqs) */\r
+ int rts_commit; /* need to change rts */\r
+ int rts; /* rts status */\r
+ int baud; /* current baud rate */\r
+\r
+ int parity; /* keeps track if we should send parity */\r
+ int rx_enabled; /* if we should rx chars */\r
+\r
+ int irq; /* irq assigned to the bu92747 */\r
+\r
+ int minor; /* minor number */\r
+ int crystal; /* 1 if 3.6864Mhz crystal 0 for 1.8432 */\r
+ int loopback; /* 1 if we are in loopback mode */\r
+\r
+ /* for handling irqs: need workqueue since we do spi_sync */\r
+ struct workqueue_struct *workqueue;\r
+ struct work_struct work;\r
+ /* set to 1 to make the workhandler exit as soon as possible */\r
+ int force_end_work;\r
+ /* need to know we are suspending to avoid deadlock on workqueue */\r
+ int suspending;\r
+\r
+ /* poll time (in ms) for ctrl lines */\r
+ int poll_time;\r
+ /* and its timer */\r
+ struct timer_list timer;\r
+};\r
+\r
+#define MAX_BU92747 1\r
+#define BU92747_MAJOR 204\r
+#define BU92747_MINOR 209\r
+\r
+static struct bu92747_port *bu92747s[MAX_BU92747]; /* the chips */\r
+static DEFINE_MUTEX(bu92747s_lock); /* race on probe */\r
+#define IS_FIR(s) ((s)->baud >= 4000000)\r
+static int max_rate = 4000000; \r
+static u8 g_receive_buf[BU92725GUW_FIFO_SIZE];\r
+\r
+#if 0\r
+#define BU92747_IRDA_DBG(x...) printk(x)\r
+#else\r
+#define BU92747_IRDA_DBG(x...)\r
+#endif\r
+\r
+static int bu92747_irda_do_rx(struct bu92747_port *s)\r
+{\r
+ int i;\r
+ unsigned int ch, flag;\r
+ int len;\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+\r
+ if (s->rx_enabled == 0) {\r
+ BU92725GUW_clr_fifo();\r
+ BU92725GUW_reset();\r
+ return 0;\r
+ }\r
+ \r
+ len = BU92725GUW_get_data(g_receive_buf);\r
+ flag = TTY_NORMAL;\r
+ //printk("receive data:\n");\r
+ for (i=0;i<len;i++) {\r
+ ch = g_receive_buf[i];\r
+ uart_insert_char(&s->port, 0, 0, ch, flag);\r
+ s->port.icount.rx++;\r
+ //printk("%d ", ch);\r
+ }\r
+ //printk("\n");\r
+ \r
+ return len;\r
+ }\r
+\r
+static int bu92747_irda_do_tx(struct bu92747_port *s)\r
+{\r
+ int i;\r
+ struct circ_buf *xmit = &s->port.state->xmit;\r
+ int len = uart_circ_chars_pending(xmit);\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ \r
+ if (IS_FIR(s)) {\r
+ //printk("fir sending.....\n");\r
+ irda_hw_tx_enable_irq(BU92725GUW_FIR);\r
+ }\r
+ else { \r
+ //printk("sir sending.....\n");\r
+ irda_hw_tx_enable_irq(BU92725GUW_SIR);\r
+ }\r
+\r
+ BU92747_IRDA_DBG("data:\n");\r
+ for (i=0; i<len; i++) {\r
+ BU92747_IRDA_DBG("%d ", xmit->buf[xmit->tail+i]);\r
+ }\r
+ BU92747_IRDA_DBG("\n");\r
+ \r
+ BU92725GUW_send_data(xmit->buf+xmit->tail, len, NULL, 0);\r
+ s->port.icount.tx += len;\r
+ xmit->tail = (xmit->tail + len) & (UART_XMIT_SIZE - 1);\r
+\r
+ if (len>0) \r
+ s->tx_empty = 0;\r
+ \r
+ if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)\r
+ uart_write_wakeup(&s->port);\r
+\r
+ return len;\r
+}\r
+\r
+static void bu92747_irda_dowork(struct bu92747_port *s)\r
+{\r
+ if (!s->force_end_work && !work_pending(&s->work) &&\r
+ !freezing(current) && !s->suspending)\r
+ queue_work(s->workqueue, &s->work);\r
+}\r
+\r
+static void bu92747_irda_work(struct work_struct *w)\r
+{\r
+ struct bu92747_port *s = container_of(w, struct bu92747_port, work);\r
+ u32 irq_src = 0; \r
+ struct circ_buf *xmit = &s->port.state->xmit;\r
+\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+\r
+ if (!s->force_end_work && !freezing(current)) {\r
+ //BU92725GUW_dump_register();\r
+\r
+ if (!uart_circ_empty(xmit) && !uart_tx_stopped(&s->port)) {\r
+ if (s->tx_empty)\r
+ bu92747_irda_do_tx(s);\r
+ else \r
+ bu92747_irda_dowork(s);\r
+ }\r
+ }\r
+}\r
+\r
+static irqreturn_t bu92747_irda_irq(int irqno, void *dev_id)\r
+{\r
+ struct bu92747_port *s = dev_id;\r
+ u32 irq_src = 0; \r
+\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ irq_src = irda_hw_get_irqsrc();\r
+ printk("[%s][%d], 0x%x\n",__FUNCTION__,__LINE__, irq_src);\r
+ /* error */\r
+ if (irq_src & (REG_INT_TO| REG_INT_CRC | REG_INT_OE | REG_INT_FE\r
+ | REG_INT_AC | REG_INT_DECE | REG_INT_RDOE | REG_INT_DEX)) {\r
+ BU92747_IRDA_DBG("[%s][%d]: do err\n", __FUNCTION__, __LINE__);\r
+ //BU92725GUW_dump_register();\r
+ //BU92725GUW_clr_fifo();\r
+ BU92725GUW_reset();\r
+ }\r
+ \r
+ if (irq_src & (REG_INT_DRX | FRM_EVT_RX_EOFRX | FRM_EVT_RX_RDE)) {\r
+ bu92747_irda_do_rx(s);\r
+ tty_flip_buffer_push(s->port.state->port.tty);\r
+ }\r
+ \r
+ if ((irq_src & REG_INT_EOF) && (s->port.state->port.tty != NULL)) {\r
+ tty_flip_buffer_push(s->port.state->port.tty);\r
+ }\r
+ \r
+ if (irq_src & (FRM_EVT_TX_TXE | FRM_EVT_TX_WRE)) {\r
+ s->tx_empty = 1;\r
+ irda_hw_set_moderx();\r
+ }\r
+ \r
+ return IRQ_HANDLED;\r
+}\r
+\r
+\r
+static void bu92747_irda_stop_tx(struct uart_port *port)\r
+{\r
+ struct bu92747_port *s = container_of(port,\r
+ struct bu92747_port,\r
+ port);\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+}\r
+\r
+static void bu92747_irda_start_tx(struct uart_port *port)\r
+{\r
+ struct bu92747_port *s = container_of(port,\r
+ struct bu92747_port,\r
+ port);\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+\r
+ if (s->tx_empty)\r
+ bu92747_irda_do_tx(s);\r
+ else \r
+ bu92747_irda_dowork(s);\r
+}\r
+\r
+static void bu92747_irda_stop_rx(struct uart_port *port)\r
+{\r
+ struct bu92747_port *s = container_of(port,\r
+ struct bu92747_port,\r
+ port);\r
+\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+\r
+ s->rx_enabled = 0;\r
+\r
+ bu92747_irda_dowork(s);\r
+}\r
+\r
+static unsigned int bu92747_irda_tx_empty(struct uart_port *port)\r
+{\r
+ struct bu92747_port *s = container_of(port,\r
+ struct bu92747_port,\r
+ port);\r
+\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+\r
+ /* may not be truly up-to-date */\r
+ bu92747_irda_dowork(s);\r
+ return s->tx_empty;\r
+}\r
+\r
+static const char *bu92747_irda_type(struct uart_port *port)\r
+{\r
+ struct bu92747_port *s = container_of(port,\r
+ struct bu92747_port,\r
+ port);\r
+\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+\r
+ return s->port.type == PORT_IRDA ? "BU92747" : NULL;\r
+}\r
+\r
+static void bu92747_irda_release_port(struct uart_port *port)\r
+{\r
+ struct bu92747_port *s = container_of(port,\r
+ struct bu92747_port,\r
+ port);\r
+\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+}\r
+\r
+static void bu92747_irda_config_port(struct uart_port *port, int flags)\r
+{\r
+ struct bu92747_port *s = container_of(port,\r
+ struct bu92747_port,\r
+ port);\r
+\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+\r
+ if (flags & UART_CONFIG_TYPE)\r
+ s->port.type = PORT_IRDA;\r
+}\r
+\r
+static int bu92747_irda_verify_port(struct uart_port *port,\r
+ struct serial_struct *ser)\r
+{\r
+ struct bu92747_port *s = container_of(port,\r
+ struct bu92747_port,\r
+ port);\r
+ int ret = -EINVAL;\r
+\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+\r
+ if (ser->type == PORT_UNKNOWN || ser->type == PORT_IRDA)\r
+ ret = 0;\r
+ \r
+ return ret;\r
+}\r
+\r
+static void bu92747_irda_shutdown(struct uart_port *port)\r
+{\r
+ struct bu92747_port *s = container_of(port,\r
+ struct bu92747_port,\r
+ port);\r
+\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+\r
+ if (s->suspending)\r
+ return;\r
+\r
+ s->force_end_work = 1;\r
+\r
+ if (s->workqueue) {\r
+ flush_workqueue(s->workqueue);\r
+ destroy_workqueue(s->workqueue);\r
+ s->workqueue = NULL;\r
+ }\r
+ if (s->irq)\r
+ free_irq(s->irq, s);\r
+ \r
+ irda_hw_shutdown();\r
+ if (s->pdata->irda_pwr_ctl)\r
+ s->pdata->irda_pwr_ctl(0);\r
+\r
+}\r
+\r
+static int bu92747_irda_startup(struct uart_port *port)\r
+{\r
+ struct bu92747_port *s = container_of(port,\r
+ struct bu92747_port,\r
+ port);\r
+ char b[32];\r
+\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+\r
+ s->baud = 9600;\r
+ s->rx_enabled = 1;\r
+\r
+ if (s->suspending)\r
+ return 0;\r
+\r
+ s->tx_empty = 1;\r
+ s->force_end_work = 0;\r
+\r
+ sprintf(b, "bu92747_irda-%d", s->minor);\r
+ s->workqueue = create_freezeable_workqueue(b);\r
+ if (!s->workqueue) {\r
+ dev_warn(s->dev, "cannot create workqueue\n");\r
+ return -EBUSY;\r
+ }\r
+ INIT_WORK(&s->work, bu92747_irda_work);\r
+\r
+ if (request_irq(s->irq, bu92747_irda_irq,\r
+ IRQ_TYPE_EDGE_FALLING, "bu92747_irda", s) < 0) {\r
+ dev_warn(s->dev, "cannot allocate irq %d\n", s->irq);\r
+ s->irq = 0;\r
+ destroy_workqueue(s->workqueue);\r
+ s->workqueue = NULL;\r
+ return -EBUSY;\r
+ }\r
+\r
+ disable_irq(s->irq);\r
+\r
+ if (s->pdata->irda_pwr_ctl)\r
+ s->pdata->irda_pwr_ctl(1);\r
+\r
+ irda_hw_startup();\r
+ irda_hw_set_moderx();\r
+\r
+ enable_irq(s->irq);\r
+\r
+ return 0;\r
+}\r
+\r
+static int bu92747_irda_request_port(struct uart_port *port)\r
+{\r
+ struct bu92747_port *s = container_of(port,\r
+ struct bu92747_port,\r
+ port);\r
+\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+ return 0;\r
+}\r
+\r
+static void bu92747_irda_break_ctl(struct uart_port *port, int break_state)\r
+{\r
+ struct bu92747_port *s = container_of(port,\r
+ struct bu92747_port,\r
+ port);\r
+\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+}\r
+\r
+static unsigned int bu92747_irda_get_mctrl(struct uart_port *port)\r
+{\r
+ struct bu92747_port *s = container_of(port,\r
+ struct bu92747_port,\r
+ port);\r
+\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+\r
+ return TIOCM_DSR | TIOCM_CAR;\r
+}\r
+\r
+static void bu92747_irda_set_mctrl(struct uart_port *port, unsigned int mctrl)\r
+{\r
+ struct bu92747_port *s = container_of(port,\r
+ struct bu92747_port,\r
+ port);\r
+ int rts;\r
+\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+}\r
+\r
+static void\r
+bu92747_irda_set_termios(struct uart_port *port, struct ktermios *termios,\r
+ struct ktermios *old)\r
+{\r
+ struct bu92747_port *s = container_of(port,\r
+ struct bu92747_port,\r
+ port);\r
+ int baud = 0;\r
+ unsigned cflag;\r
+ struct tty_struct *tty = s->port.state->port.tty;\r
+\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+ if (!tty)\r
+ return;\r
+\r
+ cflag = termios->c_cflag;\r
+ baud = uart_get_baud_rate(port, termios, old, 0, max_rate);\r
+\r
+ switch (baud) {\r
+ case 9600:\r
+ case 19200:\r
+ case 38400:\r
+ case 57600:\r
+ case 115200:\r
+ case 4000000:\r
+ if (s->baud!=baud) {\r
+ irda_hw_set_speed(baud);\r
+ s->baud = baud;\r
+ }\r
+ break;\r
+\r
+ default:\r
+ break;\r
+ }\r
+ \r
+ uart_update_timeout(port, termios->c_cflag, baud);\r
+\r
+}\r
+\r
+static struct uart_ops bu92747_irda_ops = {\r
+ .tx_empty = bu92747_irda_tx_empty,\r
+ .set_mctrl = bu92747_irda_set_mctrl,\r
+ .get_mctrl = bu92747_irda_get_mctrl,\r
+ .stop_tx = bu92747_irda_stop_tx,\r
+ .start_tx = bu92747_irda_start_tx,\r
+ .stop_rx = bu92747_irda_stop_rx,\r
+ //.enable_ms = bu92747_irda_enable_ms,\r
+ .break_ctl = bu92747_irda_break_ctl,\r
+ .startup = bu92747_irda_startup,\r
+ .shutdown = bu92747_irda_shutdown,\r
+ .set_termios = bu92747_irda_set_termios,\r
+ .type = bu92747_irda_type,\r
+ .release_port = bu92747_irda_release_port,\r
+ .request_port = bu92747_irda_request_port,\r
+ .config_port = bu92747_irda_config_port,\r
+ .verify_port = bu92747_irda_verify_port,\r
+};\r
+\r
+static struct uart_driver bu92747_irda_uart_driver = {\r
+ .owner = THIS_MODULE,\r
+ .driver_name = "ttyIr",\r
+ .dev_name = "ttyIr",\r
+ .major = BU92747_MAJOR,\r
+ .minor = BU92747_MINOR,\r
+ .nr = MAX_BU92747,\r
+};\r
+\r
+static int uart_driver_registered;\r
+static int __devinit bu92747_irda_probe(struct platform_device *pdev)\r
+{\r
+ int i, retval;\r
+ struct irda_info *platdata = pdev->dev.platform_data;\r
+\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ if (!platdata) {\r
+ dev_warn(&pdev->dev, "no platform data info\n");\r
+ return -1;\r
+ }\r
+\r
+ mutex_lock(&bu92747s_lock);\r
+\r
+ if (!uart_driver_registered) {\r
+ uart_driver_registered = 1;\r
+ retval = uart_register_driver(&bu92747_irda_uart_driver);\r
+ if (retval) {\r
+ printk(KERN_ERR "Couldn't register bu92747 uart driver\n");\r
+ mutex_unlock(&bu92747s_lock);\r
+ return retval;\r
+ }\r
+ }\r
+\r
+ for (i = 0; i < MAX_BU92747; i++)\r
+ if (!bu92747s[i])\r
+ break;\r
+ if (i == MAX_BU92747) {\r
+ dev_warn(&pdev->dev, "too many bu92747 chips\n");\r
+ mutex_unlock(&bu92747s_lock);\r
+ return -ENOMEM;\r
+ }\r
+\r
+ bu92747s[i] = kzalloc(sizeof(struct bu92747_port), GFP_KERNEL);\r
+ if (!bu92747s[i]) {\r
+ dev_warn(&pdev->dev,\r
+ "kmalloc for bu92747 structure %d failed!\n", i);\r
+ mutex_unlock(&bu92747s_lock);\r
+ return -ENOMEM;\r
+ }\r
+ bu92747s[i]->dev = &pdev->dev;\r
+ bu92747s[i]->irq = gpio_to_irq(platdata->intr_pin);\r
+ if (platdata->iomux_init)\r
+ platdata->iomux_init();\r
+ bu92747s[i]->pdata = platdata;\r
+ spin_lock_init(&bu92747s[i]->conf_lock);\r
+ dev_set_drvdata(&pdev->dev, bu92747s[i]);\r
+ bu92747s[i]->minor = i;\r
+ dev_dbg(&pdev->dev, "%s: adding port %d\n", __func__, i);\r
+ bu92747s[i]->port.irq = bu92747s[i]->irq;\r
+ bu92747s[i]->port.fifosize = BU92725GUW_FIFO_SIZE;\r
+ bu92747s[i]->port.ops = &bu92747_irda_ops;\r
+ bu92747s[i]->port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;\r
+ bu92747s[i]->port.line = i;\r
+ bu92747s[i]->port.type = PORT_IRDA;\r
+ bu92747s[i]->port.dev = &pdev->dev;\r
+ retval = uart_add_one_port(&bu92747_irda_uart_driver, &bu92747s[i]->port);\r
+ if (retval < 0)\r
+ dev_warn(&pdev->dev,\r
+ "uart_add_one_port failed for line %d with error %d\n",\r
+ i, retval);\r
+\r
+ /* set shutdown mode to save power. Will be woken-up on open */\r
+ if (bu92747s[i]->pdata->irda_pwr_ctl)\r
+ bu92747s[i]->pdata->irda_pwr_ctl(0);\r
+\r
+ mutex_unlock(&bu92747s_lock);\r
+ \r
+ return 0;\r
+}\r
+\r
+static int __devexit bu92747_irda_remove(struct platform_device *pdev)\r
+{\r
+ struct bu92747_port *s = dev_get_drvdata(&pdev->dev);\r
+ int i;\r
+\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ mutex_lock(&bu92747s_lock);\r
+\r
+ /* find out the index for the chip we are removing */\r
+ for (i = 0; i < MAX_BU92747; i++)\r
+ if (bu92747s[i] == s)\r
+ break;\r
+\r
+ dev_dbg(&pdev->dev, "%s: removing port %d\n", __func__, i);\r
+ uart_remove_one_port(&bu92747_irda_uart_driver, &bu92747s[i]->port);\r
+ kfree(bu92747s[i]);\r
+ bu92747s[i] = NULL;\r
+\r
+ /* check if this is the last chip we have */\r
+ for (i = 0; i < MAX_BU92747; i++)\r
+ if (bu92747s[i]) {\r
+ mutex_unlock(&bu92747s_lock);\r
+ return 0;\r
+ }\r
+ pr_debug("removing bu92747 driver\n");\r
+ uart_unregister_driver(&bu92747_irda_uart_driver);\r
+\r
+ mutex_unlock(&bu92747s_lock);\r
+ return 0;\r
+}\r
+\r
+\r
+#ifdef CONFIG_PM\r
+static int bu92747_irda_suspend(struct platform_device *pdev, pm_message_t state)\r
+{\r
+ struct bu92747_port *s = dev_get_drvdata(&pdev->dev);\r
+\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ disable_irq(s->irq);\r
+\r
+ s->suspending = 1;\r
+ uart_suspend_port(&bu92747_irda_uart_driver, &s->port);\r
+\r
+ irda_hw_shutdown();\r
+ if (s->pdata->irda_pwr_ctl)\r
+ s->pdata->irda_pwr_ctl(0);\r
+\r
+ return 0;\r
+}\r
+\r
+static int bu92747_irda_resume(struct platform_device *pdev)\r
+{\r
+ struct bu92747_port *s = dev_get_drvdata(&pdev->dev);\r
+\r
+ dev_dbg(s->dev, "%s\n", __func__);\r
+\r
+ BU92747_IRDA_DBG("line %d, enter %s \n", __LINE__, __FUNCTION__);\r
+ if (s->pdata->irda_pwr_ctl)\r
+ s->pdata->irda_pwr_ctl(1);\r
+ \r
+ irda_hw_startup();\r
+\r
+ uart_resume_port(&bu92747_irda_uart_driver, &s->port);\r
+ s->suspending = 0;\r
+\r
+ enable_irq(s->irq);\r
+ \r
+ if (s->workqueue)\r
+ bu92747_irda_dowork(s);\r
+\r
+ return 0;\r
+}\r
+#else\r
+#define bu92747_irda_suspend NULL\r
+#define bu92747_irda_resume NULL\r
+#endif\r
+\r
+static struct platform_driver bu92747_irda_driver = {\r
+ .driver = {\r
+ .name = "bu92747_irda",\r
+ .owner = THIS_MODULE,\r
+ },\r
+ .probe = bu92747_irda_probe,\r
+ .remove = bu92747_irda_remove,\r
+ .suspend = bu92747_irda_suspend,\r
+ .resume = bu92747_irda_resume,\r
+};\r
+\r
+static int __init bu92747_irda_init(void)\r
+{\r
+ if (platform_driver_register(&bu92747_irda_driver) != 0) {\r
+ printk("Could not register irda driver\n");\r
+ return -EINVAL;\r
+ }\r
+ return 0;\r
+}\r
+\r
+static void __exit bu92747_irda_exit(void)\r
+{\r
+ platform_driver_unregister(&bu92747_irda_driver);\r
+}\r
+\r
+module_init(bu92747_irda_init);\r
+module_exit(bu92747_irda_exit);\r
+MODULE_DESCRIPTION("BU92747 irda driver");\r
+MODULE_AUTHOR("liuyixing <lyx@rock-chips.com>");\r
+MODULE_LICENSE("GPL");\r
+\r