diff options
Diffstat (limited to 'drivers/serial/sh-sci.c')
-rw-r--r-- | drivers/serial/sh-sci.c | 57 |
1 files changed, 37 insertions, 20 deletions
diff --git a/drivers/serial/sh-sci.c b/drivers/serial/sh-sci.c index 980f39449ee5..054a8427c739 100644 --- a/drivers/serial/sh-sci.c +++ b/drivers/serial/sh-sci.c | |||
@@ -83,8 +83,8 @@ struct sci_port { | |||
83 | 83 | ||
84 | /* Interface clock */ | 84 | /* Interface clock */ |
85 | struct clk *iclk; | 85 | struct clk *iclk; |
86 | /* Data clock */ | 86 | /* Function clock */ |
87 | struct clk *dclk; | 87 | struct clk *fclk; |
88 | 88 | ||
89 | struct list_head node; | 89 | struct list_head node; |
90 | struct dma_chan *chan_tx; | 90 | struct dma_chan *chan_tx; |
@@ -803,7 +803,7 @@ static int sci_notifier(struct notifier_block *self, | |||
803 | (phase == CPUFREQ_RESUMECHANGE)) { | 803 | (phase == CPUFREQ_RESUMECHANGE)) { |
804 | spin_lock_irqsave(&priv->lock, flags); | 804 | spin_lock_irqsave(&priv->lock, flags); |
805 | list_for_each_entry(sci_port, &priv->ports, node) | 805 | list_for_each_entry(sci_port, &priv->ports, node) |
806 | sci_port->port.uartclk = clk_get_rate(sci_port->dclk); | 806 | sci_port->port.uartclk = clk_get_rate(sci_port->iclk); |
807 | spin_unlock_irqrestore(&priv->lock, flags); | 807 | spin_unlock_irqrestore(&priv->lock, flags); |
808 | } | 808 | } |
809 | 809 | ||
@@ -814,21 +814,17 @@ static void sci_clk_enable(struct uart_port *port) | |||
814 | { | 814 | { |
815 | struct sci_port *sci_port = to_sci_port(port); | 815 | struct sci_port *sci_port = to_sci_port(port); |
816 | 816 | ||
817 | clk_enable(sci_port->dclk); | 817 | clk_enable(sci_port->iclk); |
818 | sci_port->port.uartclk = clk_get_rate(sci_port->dclk); | 818 | sci_port->port.uartclk = clk_get_rate(sci_port->iclk); |
819 | 819 | clk_enable(sci_port->fclk); | |
820 | if (sci_port->iclk) | ||
821 | clk_enable(sci_port->iclk); | ||
822 | } | 820 | } |
823 | 821 | ||
824 | static void sci_clk_disable(struct uart_port *port) | 822 | static void sci_clk_disable(struct uart_port *port) |
825 | { | 823 | { |
826 | struct sci_port *sci_port = to_sci_port(port); | 824 | struct sci_port *sci_port = to_sci_port(port); |
827 | 825 | ||
828 | if (sci_port->iclk) | 826 | clk_disable(sci_port->fclk); |
829 | clk_disable(sci_port->iclk); | 827 | clk_disable(sci_port->iclk); |
830 | |||
831 | clk_disable(sci_port->dclk); | ||
832 | } | 828 | } |
833 | 829 | ||
834 | static int sci_request_irq(struct sci_port *port) | 830 | static int sci_request_irq(struct sci_port *port) |
@@ -1557,10 +1553,10 @@ static struct uart_ops sci_uart_ops = { | |||
1557 | #endif | 1553 | #endif |
1558 | }; | 1554 | }; |
1559 | 1555 | ||
1560 | static void __devinit sci_init_single(struct platform_device *dev, | 1556 | static int __devinit sci_init_single(struct platform_device *dev, |
1561 | struct sci_port *sci_port, | 1557 | struct sci_port *sci_port, |
1562 | unsigned int index, | 1558 | unsigned int index, |
1563 | struct plat_sci_port *p) | 1559 | struct plat_sci_port *p) |
1564 | { | 1560 | { |
1565 | struct uart_port *port = &sci_port->port; | 1561 | struct uart_port *port = &sci_port->port; |
1566 | 1562 | ||
@@ -1581,8 +1577,23 @@ static void __devinit sci_init_single(struct platform_device *dev, | |||
1581 | } | 1577 | } |
1582 | 1578 | ||
1583 | if (dev) { | 1579 | if (dev) { |
1584 | sci_port->iclk = p->clk ? clk_get(&dev->dev, p->clk) : NULL; | 1580 | sci_port->iclk = clk_get(&dev->dev, "sci_ick"); |
1585 | sci_port->dclk = clk_get(&dev->dev, "peripheral_clk"); | 1581 | if (IS_ERR(sci_port->iclk)) { |
1582 | sci_port->iclk = clk_get(&dev->dev, "peripheral_clk"); | ||
1583 | if (IS_ERR(sci_port->iclk)) { | ||
1584 | dev_err(&dev->dev, "can't get iclk\n"); | ||
1585 | return PTR_ERR(sci_port->iclk); | ||
1586 | } | ||
1587 | } | ||
1588 | |||
1589 | /* | ||
1590 | * The function clock is optional, ignore it if we can't | ||
1591 | * find it. | ||
1592 | */ | ||
1593 | sci_port->fclk = clk_get(&dev->dev, "sci_fck"); | ||
1594 | if (IS_ERR(sci_port->fclk)) | ||
1595 | sci_port->fclk = NULL; | ||
1596 | |||
1586 | sci_port->enable = sci_clk_enable; | 1597 | sci_port->enable = sci_clk_enable; |
1587 | sci_port->disable = sci_clk_disable; | 1598 | sci_port->disable = sci_clk_disable; |
1588 | port->dev = &dev->dev; | 1599 | port->dev = &dev->dev; |
@@ -1609,6 +1620,7 @@ static void __devinit sci_init_single(struct platform_device *dev, | |||
1609 | #endif | 1620 | #endif |
1610 | 1621 | ||
1611 | memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs)); | 1622 | memcpy(&sci_port->irqs, &p->irqs, sizeof(p->irqs)); |
1623 | return 0; | ||
1612 | } | 1624 | } |
1613 | 1625 | ||
1614 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE | 1626 | #ifdef CONFIG_SERIAL_SH_SCI_CONSOLE |
@@ -1758,8 +1770,11 @@ static int sci_remove(struct platform_device *dev) | |||
1758 | cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER); | 1770 | cpufreq_unregister_notifier(&priv->clk_nb, CPUFREQ_TRANSITION_NOTIFIER); |
1759 | 1771 | ||
1760 | spin_lock_irqsave(&priv->lock, flags); | 1772 | spin_lock_irqsave(&priv->lock, flags); |
1761 | list_for_each_entry(p, &priv->ports, node) | 1773 | list_for_each_entry(p, &priv->ports, node) { |
1762 | uart_remove_one_port(&sci_uart_driver, &p->port); | 1774 | uart_remove_one_port(&sci_uart_driver, &p->port); |
1775 | clk_put(p->iclk); | ||
1776 | clk_put(p->fclk); | ||
1777 | } | ||
1763 | spin_unlock_irqrestore(&priv->lock, flags); | 1778 | spin_unlock_irqrestore(&priv->lock, flags); |
1764 | 1779 | ||
1765 | kfree(priv); | 1780 | kfree(priv); |
@@ -1785,7 +1800,9 @@ static int __devinit sci_probe_single(struct platform_device *dev, | |||
1785 | return 0; | 1800 | return 0; |
1786 | } | 1801 | } |
1787 | 1802 | ||
1788 | sci_init_single(dev, sciport, index, p); | 1803 | ret = sci_init_single(dev, sciport, index, p); |
1804 | if (ret) | ||
1805 | return ret; | ||
1789 | 1806 | ||
1790 | ret = uart_add_one_port(&sci_uart_driver, &sciport->port); | 1807 | ret = uart_add_one_port(&sci_uart_driver, &sciport->port); |
1791 | if (ret) | 1808 | if (ret) |