sh: pci: clock framework support for SH7786 PCIe.

This gets each port handling its MSTP bit, as well as moving the PHY
clock management in to the clock framework.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c
index b0ef380..8ec4af1 100644
--- a/arch/sh/drivers/pci/pcie-sh7786.c
+++ b/arch/sh/drivers/pci/pcie-sh7786.c
@@ -13,11 +13,15 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/sh_clk.h>
 #include "pcie-sh7786.h"
 #include <asm/sizes.h>
+#include <asm/clock.h>
 
 struct sh7786_pcie_port {
 	struct pci_channel	*hose;
+	struct clk		*fclk, phy_clk;
 	unsigned int		index;
 	int			endpoint;
 	int			link;
@@ -121,6 +125,10 @@
 	DEFINE_CONTROLLER(0xfcc00000, 2),
 };
 
+static struct clk fixed_pciexclkp = {
+	.rate = 100000000,	/* 100 MHz reference clock */
+};
+
 static void __devinit sh7786_pci_fixup(struct pci_dev *dev)
 {
 	/*
@@ -139,7 +147,7 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_SH7786,
 			 sh7786_pci_fixup);
 
-static int phy_wait_for_ack(struct pci_channel *chan)
+static int __init phy_wait_for_ack(struct pci_channel *chan)
 {
 	unsigned int timeout = 100;
 
@@ -153,7 +161,7 @@
 	return -ETIMEDOUT;
 }
 
-static int pci_wait_for_irq(struct pci_channel *chan, unsigned int mask)
+static int __init pci_wait_for_irq(struct pci_channel *chan, unsigned int mask)
 {
 	unsigned int timeout = 100;
 
@@ -167,8 +175,8 @@
 	return -ETIMEDOUT;
 }
 
-static void phy_write_reg(struct pci_channel *chan, unsigned int addr,
-			  unsigned int lane, unsigned int data)
+static void __init phy_write_reg(struct pci_channel *chan, unsigned int addr,
+				 unsigned int lane, unsigned int data)
 {
 	unsigned long phyaddr;
 
@@ -188,15 +196,67 @@
 	phy_wait_for_ack(chan);
 }
 
-static int phy_init(struct pci_channel *chan)
+static int __init pcie_clk_init(struct sh7786_pcie_port *port)
 {
-	unsigned long ctrl;
+	struct pci_channel *chan = port->hose;
+	struct clk *clk;
+	char fclk_name[16];
+	int ret;
+
+	/*
+	 * First register the fixed clock
+	 */
+	ret = clk_register(&fixed_pciexclkp);
+	if (unlikely(ret != 0))
+		return ret;
+
+	/*
+	 * Grab the port's function clock, which the PHY clock depends
+	 * on. clock lookups don't help us much at this point, since no
+	 * dev_id is available this early. Lame.
+	 */
+	snprintf(fclk_name, sizeof(fclk_name), "pcie%d_fck", port->index);
+
+	port->fclk = clk_get(NULL, fclk_name);
+	if (IS_ERR(port->fclk)) {
+		ret = PTR_ERR(port->fclk);
+		goto err_fclk;
+	}
+
+	clk_enable(port->fclk);
+
+	/*
+	 * And now, set up the PHY clock
+	 */
+	clk = &port->phy_clk;
+
+	memset(clk, 0, sizeof(struct clk));
+
+	clk->parent = &fixed_pciexclkp;
+	clk->enable_reg = (void __iomem *)(chan->reg_base + SH4A_PCIEPHYCTLR);
+	clk->enable_bit = BITS_CKE;
+
+	ret = sh_clk_mstp32_register(clk, 1);
+	if (unlikely(ret < 0))
+		goto err_phy;
+
+	return 0;
+
+err_phy:
+	clk_disable(port->fclk);
+	clk_put(port->fclk);
+err_fclk:
+	clk_unregister(&fixed_pciexclkp);
+
+	return ret;
+}
+
+static int __init phy_init(struct sh7786_pcie_port *port)
+{
+	struct pci_channel *chan = port->hose;
 	unsigned int timeout = 100;
 
-	/* Enable clock */
-	ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR);
-	ctrl |= (1 << BITS_CKE);
-	pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR);
+	clk_enable(&port->phy_clk);
 
 	/* Initialize the phy */
 	phy_write_reg(chan, 0x60, 0xf, 0x004b008b);
@@ -212,9 +272,7 @@
 	phy_write_reg(chan, 0x67, 0x1, 0x00000400);
 
 	/* Disable clock */
-	ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR);
-	ctrl &= ~(1 << BITS_CKE);
-	pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR);
+	clk_disable(&port->phy_clk);
 
 	while (timeout--) {
 		if (pci_read_reg(chan, SH4A_PCIEPHYSR))
@@ -226,7 +284,7 @@
 	return -ETIMEDOUT;
 }
 
-static void pcie_reset(struct sh7786_pcie_port *port)
+static void __init pcie_reset(struct sh7786_pcie_port *port)
 {
 	struct pci_channel *chan = port->hose;
 
@@ -236,7 +294,7 @@
 	pci_write_reg(chan, 0, SH4A_PCIETXVC0SR);
 }
 
-static int pcie_init(struct sh7786_pcie_port *port)
+static int __init pcie_init(struct sh7786_pcie_port *port)
 {
 	struct pci_channel *chan = port->hose;
 	unsigned int data;
@@ -411,26 +469,33 @@
         return 71;
 }
 
-static int sh7786_pcie_core_init(void)
+static int __init sh7786_pcie_core_init(void)
 {
 	/* Return the number of ports */
 	return test_mode_pin(MODE_PIN12) ? 3 : 2;
 }
 
-static int __devinit sh7786_pcie_init_hw(struct sh7786_pcie_port *port)
+static int __init sh7786_pcie_init_hw(struct sh7786_pcie_port *port)
 {
 	int ret;
 
-	ret = phy_init(port->hose);
-	if (unlikely(ret < 0))
-		return ret;
-
 	/*
 	 * Check if we are configured in endpoint or root complex mode,
 	 * this is a fixed pin setting that applies to all PCIe ports.
 	 */
 	port->endpoint = test_mode_pin(MODE_PIN11);
 
+	/*
+	 * Setup clocks, needed both for PHY and PCIe registers.
+	 */
+	ret = pcie_clk_init(port);
+	if (unlikely(ret < 0))
+		return ret;
+
+	ret = phy_init(port);
+	if (unlikely(ret < 0))
+		return ret;
+
 	ret = pcie_init(port);
 	if (unlikely(ret < 0))
 		return ret;