diff options
Diffstat (limited to 'drivers/tty/serial/xilinx_uartps.c')
-rw-r--r-- | drivers/tty/serial/xilinx_uartps.c | 50 |
1 files changed, 23 insertions, 27 deletions
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c index 9ab910370c56..ba451c7209fc 100644 --- a/drivers/tty/serial/xilinx_uartps.c +++ b/drivers/tty/serial/xilinx_uartps.c | |||
@@ -17,6 +17,7 @@ | |||
17 | #include <linux/tty.h> | 17 | #include <linux/tty.h> |
18 | #include <linux/tty_flip.h> | 18 | #include <linux/tty_flip.h> |
19 | #include <linux/console.h> | 19 | #include <linux/console.h> |
20 | #include <linux/clk.h> | ||
20 | #include <linux/irq.h> | 21 | #include <linux/irq.h> |
21 | #include <linux/io.h> | 22 | #include <linux/io.h> |
22 | #include <linux/of.h> | 23 | #include <linux/of.h> |
@@ -147,15 +148,11 @@ | |||
147 | static irqreturn_t xuartps_isr(int irq, void *dev_id) | 148 | static irqreturn_t xuartps_isr(int irq, void *dev_id) |
148 | { | 149 | { |
149 | struct uart_port *port = (struct uart_port *)dev_id; | 150 | struct uart_port *port = (struct uart_port *)dev_id; |
150 | struct tty_struct *tty; | ||
151 | unsigned long flags; | 151 | unsigned long flags; |
152 | unsigned int isrstatus, numbytes; | 152 | unsigned int isrstatus, numbytes; |
153 | unsigned int data; | 153 | unsigned int data; |
154 | char status = TTY_NORMAL; | 154 | char status = TTY_NORMAL; |
155 | 155 | ||
156 | /* Get the tty which could be NULL so don't assume it's valid */ | ||
157 | tty = tty_port_tty_get(&port->state->port); | ||
158 | |||
159 | spin_lock_irqsave(&port->lock, flags); | 156 | spin_lock_irqsave(&port->lock, flags); |
160 | 157 | ||
161 | /* Read the interrupt status register to determine which | 158 | /* Read the interrupt status register to determine which |
@@ -187,14 +184,11 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id) | |||
187 | } else if (isrstatus & XUARTPS_IXR_OVERRUN) | 184 | } else if (isrstatus & XUARTPS_IXR_OVERRUN) |
188 | port->icount.overrun++; | 185 | port->icount.overrun++; |
189 | 186 | ||
190 | if (tty) | 187 | uart_insert_char(port, isrstatus, XUARTPS_IXR_OVERRUN, |
191 | uart_insert_char(port, isrstatus, | 188 | data, status); |
192 | XUARTPS_IXR_OVERRUN, data, | ||
193 | status); | ||
194 | } | 189 | } |
195 | spin_unlock(&port->lock); | 190 | spin_unlock(&port->lock); |
196 | if (tty) | 191 | tty_flip_buffer_push(&port->state->port); |
197 | tty_flip_buffer_push(tty); | ||
198 | spin_lock(&port->lock); | 192 | spin_lock(&port->lock); |
199 | } | 193 | } |
200 | 194 | ||
@@ -237,7 +231,6 @@ static irqreturn_t xuartps_isr(int irq, void *dev_id) | |||
237 | 231 | ||
238 | /* be sure to release the lock and tty before leaving */ | 232 | /* be sure to release the lock and tty before leaving */ |
239 | spin_unlock_irqrestore(&port->lock, flags); | 233 | spin_unlock_irqrestore(&port->lock, flags); |
240 | tty_kref_put(tty); | ||
241 | 234 | ||
242 | return IRQ_HANDLED; | 235 | return IRQ_HANDLED; |
243 | } | 236 | } |
@@ -944,16 +937,18 @@ static int xuartps_probe(struct platform_device *pdev) | |||
944 | int rc; | 937 | int rc; |
945 | struct uart_port *port; | 938 | struct uart_port *port; |
946 | struct resource *res, *res2; | 939 | struct resource *res, *res2; |
947 | int clk = 0; | 940 | struct clk *clk; |
948 | |||
949 | const unsigned int *prop; | ||
950 | 941 | ||
951 | prop = of_get_property(pdev->dev.of_node, "clock", NULL); | 942 | clk = of_clk_get(pdev->dev.of_node, 0); |
952 | if (prop) | 943 | if (IS_ERR(clk)) { |
953 | clk = be32_to_cpup(prop); | ||
954 | if (!clk) { | ||
955 | dev_err(&pdev->dev, "no clock specified\n"); | 944 | dev_err(&pdev->dev, "no clock specified\n"); |
956 | return -ENODEV; | 945 | return PTR_ERR(clk); |
946 | } | ||
947 | |||
948 | rc = clk_prepare_enable(clk); | ||
949 | if (rc) { | ||
950 | dev_err(&pdev->dev, "could not enable clock\n"); | ||
951 | return -EBUSY; | ||
957 | } | 952 | } |
958 | 953 | ||
959 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 954 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -978,7 +973,8 @@ static int xuartps_probe(struct platform_device *pdev) | |||
978 | port->mapbase = res->start; | 973 | port->mapbase = res->start; |
979 | port->irq = res2->start; | 974 | port->irq = res2->start; |
980 | port->dev = &pdev->dev; | 975 | port->dev = &pdev->dev; |
981 | port->uartclk = clk; | 976 | port->uartclk = clk_get_rate(clk); |
977 | port->private_data = clk; | ||
982 | dev_set_drvdata(&pdev->dev, port); | 978 | dev_set_drvdata(&pdev->dev, port); |
983 | rc = uart_add_one_port(&xuartps_uart_driver, port); | 979 | rc = uart_add_one_port(&xuartps_uart_driver, port); |
984 | if (rc) { | 980 | if (rc) { |
@@ -1000,14 +996,14 @@ static int xuartps_probe(struct platform_device *pdev) | |||
1000 | static int xuartps_remove(struct platform_device *pdev) | 996 | static int xuartps_remove(struct platform_device *pdev) |
1001 | { | 997 | { |
1002 | struct uart_port *port = dev_get_drvdata(&pdev->dev); | 998 | struct uart_port *port = dev_get_drvdata(&pdev->dev); |
1003 | int rc = 0; | 999 | struct clk *clk = port->private_data; |
1000 | int rc; | ||
1004 | 1001 | ||
1005 | /* Remove the xuartps port from the serial core */ | 1002 | /* Remove the xuartps port from the serial core */ |
1006 | if (port) { | 1003 | rc = uart_remove_one_port(&xuartps_uart_driver, port); |
1007 | rc = uart_remove_one_port(&xuartps_uart_driver, port); | 1004 | dev_set_drvdata(&pdev->dev, NULL); |
1008 | dev_set_drvdata(&pdev->dev, NULL); | 1005 | port->mapbase = 0; |
1009 | port->mapbase = 0; | 1006 | clk_disable_unprepare(clk); |
1010 | } | ||
1011 | return rc; | 1007 | return rc; |
1012 | } | 1008 | } |
1013 | 1009 | ||
@@ -1048,7 +1044,7 @@ MODULE_DEVICE_TABLE(of, xuartps_of_match); | |||
1048 | 1044 | ||
1049 | static struct platform_driver xuartps_platform_driver = { | 1045 | static struct platform_driver xuartps_platform_driver = { |
1050 | .probe = xuartps_probe, /* Probe method */ | 1046 | .probe = xuartps_probe, /* Probe method */ |
1051 | .remove = __exit_p(xuartps_remove), /* Detach method */ | 1047 | .remove = xuartps_remove, /* Detach method */ |
1052 | .suspend = xuartps_suspend, /* Suspend */ | 1048 | .suspend = xuartps_suspend, /* Suspend */ |
1053 | .resume = xuartps_resume, /* Resume after a suspend */ | 1049 | .resume = xuartps_resume, /* Resume after a suspend */ |
1054 | .driver = { | 1050 | .driver = { |