diff options
author | Paul Mundt <lethal@linux-sh.org> | 2010-03-10 04:35:14 -0500 |
---|---|---|
committer | Paul Mundt <lethal@linux-sh.org> | 2010-03-10 04:35:14 -0500 |
commit | c7ed1ab3f7b2fe0dedebf34cbf40bf12cb5ae48b (patch) | |
tree | 3b109353e338cf43e49b06c9d463dd929010a679 /drivers/serial/sh-sci.c | |
parent | d28c145debb1bd53cde63ac8bccc192e3e00067e (diff) |
serial: sh-sci: clkdev updates for MSTP gating.
This fixes up some of the I/D/F clock ambiguity in the sh-sci driver.
The interface clock in most cases just wraps back to the peripheral
clock, while the function clock wraps in to the MSTP bits. As the logic
was somewhat inverted, this cleans that up, and also enables all CPUs
with SCI MSTP bits to match function clocks through clkdev lookup.
As a result, this gets rid of the clk string abuse on the sh side, and
the clock string will be killed off once the ARM code has had a chance to
sync up. This also enables MSTP gating on CPUs like 7786 which had never
wired it up before. Impacted CPUs are primarily all SH-Mobiles, SH7785,
and SH7786.
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
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) |