diff options
| author | Paul Mundt <lethal@linux-sh.org> | 2010-09-20 05:45:11 -0400 |
|---|---|---|
| committer | Paul Mundt <lethal@linux-sh.org> | 2010-09-20 05:45:11 -0400 |
| commit | c524ebf5a6b78d25219d64a05b3876cde719b5ff (patch) | |
| tree | 6cbc83e8a54e45a936ce65189b2c27de9d87004f /arch/sh/drivers | |
| parent | cecf48e23fd9270053850643a56e8e791322e3d5 (diff) | |
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>
Diffstat (limited to 'arch/sh/drivers')
| -rw-r--r-- | arch/sh/drivers/pci/pcie-sh7786.c | 107 |
1 files changed, 86 insertions, 21 deletions
diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c index b0ef380eff28..8ec4af197388 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.c +++ b/arch/sh/drivers/pci/pcie-sh7786.c | |||
| @@ -13,11 +13,15 @@ | |||
| 13 | #include <linux/io.h> | 13 | #include <linux/io.h> |
| 14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
| 15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
| 16 | #include <linux/clk.h> | ||
| 17 | #include <linux/sh_clk.h> | ||
| 16 | #include "pcie-sh7786.h" | 18 | #include "pcie-sh7786.h" |
| 17 | #include <asm/sizes.h> | 19 | #include <asm/sizes.h> |
| 20 | #include <asm/clock.h> | ||
| 18 | 21 | ||
| 19 | struct sh7786_pcie_port { | 22 | struct sh7786_pcie_port { |
| 20 | struct pci_channel *hose; | 23 | struct pci_channel *hose; |
| 24 | struct clk *fclk, phy_clk; | ||
| 21 | unsigned int index; | 25 | unsigned int index; |
| 22 | int endpoint; | 26 | int endpoint; |
| 23 | int link; | 27 | int link; |
| @@ -121,6 +125,10 @@ static struct pci_channel sh7786_pci_channels[] = { | |||
| 121 | DEFINE_CONTROLLER(0xfcc00000, 2), | 125 | DEFINE_CONTROLLER(0xfcc00000, 2), |
| 122 | }; | 126 | }; |
| 123 | 127 | ||
| 128 | static struct clk fixed_pciexclkp = { | ||
| 129 | .rate = 100000000, /* 100 MHz reference clock */ | ||
| 130 | }; | ||
| 131 | |||
| 124 | static void __devinit sh7786_pci_fixup(struct pci_dev *dev) | 132 | static void __devinit sh7786_pci_fixup(struct pci_dev *dev) |
| 125 | { | 133 | { |
| 126 | /* | 134 | /* |
| @@ -139,7 +147,7 @@ static void __devinit sh7786_pci_fixup(struct pci_dev *dev) | |||
| 139 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_SH7786, | 147 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_RENESAS, PCI_DEVICE_ID_RENESAS_SH7786, |
| 140 | sh7786_pci_fixup); | 148 | sh7786_pci_fixup); |
| 141 | 149 | ||
| 142 | static int phy_wait_for_ack(struct pci_channel *chan) | 150 | static int __init phy_wait_for_ack(struct pci_channel *chan) |
| 143 | { | 151 | { |
| 144 | unsigned int timeout = 100; | 152 | unsigned int timeout = 100; |
| 145 | 153 | ||
| @@ -153,7 +161,7 @@ static int phy_wait_for_ack(struct pci_channel *chan) | |||
| 153 | return -ETIMEDOUT; | 161 | return -ETIMEDOUT; |
| 154 | } | 162 | } |
| 155 | 163 | ||
| 156 | static int pci_wait_for_irq(struct pci_channel *chan, unsigned int mask) | 164 | static int __init pci_wait_for_irq(struct pci_channel *chan, unsigned int mask) |
| 157 | { | 165 | { |
| 158 | unsigned int timeout = 100; | 166 | unsigned int timeout = 100; |
| 159 | 167 | ||
| @@ -167,8 +175,8 @@ static int pci_wait_for_irq(struct pci_channel *chan, unsigned int mask) | |||
| 167 | return -ETIMEDOUT; | 175 | return -ETIMEDOUT; |
| 168 | } | 176 | } |
| 169 | 177 | ||
| 170 | static void phy_write_reg(struct pci_channel *chan, unsigned int addr, | 178 | static void __init phy_write_reg(struct pci_channel *chan, unsigned int addr, |
| 171 | unsigned int lane, unsigned int data) | 179 | unsigned int lane, unsigned int data) |
| 172 | { | 180 | { |
| 173 | unsigned long phyaddr; | 181 | unsigned long phyaddr; |
| 174 | 182 | ||
| @@ -188,15 +196,67 @@ static void phy_write_reg(struct pci_channel *chan, unsigned int addr, | |||
| 188 | phy_wait_for_ack(chan); | 196 | phy_wait_for_ack(chan); |
| 189 | } | 197 | } |
| 190 | 198 | ||
| 191 | static int phy_init(struct pci_channel *chan) | 199 | static int __init pcie_clk_init(struct sh7786_pcie_port *port) |
| 200 | { | ||
| 201 | struct pci_channel *chan = port->hose; | ||
| 202 | struct clk *clk; | ||
| 203 | char fclk_name[16]; | ||
| 204 | int ret; | ||
| 205 | |||
| 206 | /* | ||
| 207 | * First register the fixed clock | ||
| 208 | */ | ||
| 209 | ret = clk_register(&fixed_pciexclkp); | ||
| 210 | if (unlikely(ret != 0)) | ||
| 211 | return ret; | ||
| 212 | |||
| 213 | /* | ||
| 214 | * Grab the port's function clock, which the PHY clock depends | ||
| 215 | * on. clock lookups don't help us much at this point, since no | ||
| 216 | * dev_id is available this early. Lame. | ||
| 217 | */ | ||
| 218 | snprintf(fclk_name, sizeof(fclk_name), "pcie%d_fck", port->index); | ||
| 219 | |||
| 220 | port->fclk = clk_get(NULL, fclk_name); | ||
| 221 | if (IS_ERR(port->fclk)) { | ||
| 222 | ret = PTR_ERR(port->fclk); | ||
| 223 | goto err_fclk; | ||
| 224 | } | ||
| 225 | |||
| 226 | clk_enable(port->fclk); | ||
| 227 | |||
| 228 | /* | ||
| 229 | * And now, set up the PHY clock | ||
| 230 | */ | ||
| 231 | clk = &port->phy_clk; | ||
| 232 | |||
| 233 | memset(clk, 0, sizeof(struct clk)); | ||
| 234 | |||
| 235 | clk->parent = &fixed_pciexclkp; | ||
| 236 | clk->enable_reg = (void __iomem *)(chan->reg_base + SH4A_PCIEPHYCTLR); | ||
| 237 | clk->enable_bit = BITS_CKE; | ||
| 238 | |||
| 239 | ret = sh_clk_mstp32_register(clk, 1); | ||
| 240 | if (unlikely(ret < 0)) | ||
| 241 | goto err_phy; | ||
| 242 | |||
| 243 | return 0; | ||
| 244 | |||
| 245 | err_phy: | ||
| 246 | clk_disable(port->fclk); | ||
| 247 | clk_put(port->fclk); | ||
| 248 | err_fclk: | ||
| 249 | clk_unregister(&fixed_pciexclkp); | ||
| 250 | |||
| 251 | return ret; | ||
| 252 | } | ||
| 253 | |||
| 254 | static int __init phy_init(struct sh7786_pcie_port *port) | ||
| 192 | { | 255 | { |
| 193 | unsigned long ctrl; | 256 | struct pci_channel *chan = port->hose; |
| 194 | unsigned int timeout = 100; | 257 | unsigned int timeout = 100; |
| 195 | 258 | ||
| 196 | /* Enable clock */ | 259 | clk_enable(&port->phy_clk); |
| 197 | ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR); | ||
| 198 | ctrl |= (1 << BITS_CKE); | ||
| 199 | pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR); | ||
| 200 | 260 | ||
| 201 | /* Initialize the phy */ | 261 | /* Initialize the phy */ |
| 202 | phy_write_reg(chan, 0x60, 0xf, 0x004b008b); | 262 | phy_write_reg(chan, 0x60, 0xf, 0x004b008b); |
| @@ -212,9 +272,7 @@ static int phy_init(struct pci_channel *chan) | |||
| 212 | phy_write_reg(chan, 0x67, 0x1, 0x00000400); | 272 | phy_write_reg(chan, 0x67, 0x1, 0x00000400); |
| 213 | 273 | ||
| 214 | /* Disable clock */ | 274 | /* Disable clock */ |
| 215 | ctrl = pci_read_reg(chan, SH4A_PCIEPHYCTLR); | 275 | clk_disable(&port->phy_clk); |
| 216 | ctrl &= ~(1 << BITS_CKE); | ||
| 217 | pci_write_reg(chan, ctrl, SH4A_PCIEPHYCTLR); | ||
| 218 | 276 | ||
| 219 | while (timeout--) { | 277 | while (timeout--) { |
| 220 | if (pci_read_reg(chan, SH4A_PCIEPHYSR)) | 278 | if (pci_read_reg(chan, SH4A_PCIEPHYSR)) |
| @@ -226,7 +284,7 @@ static int phy_init(struct pci_channel *chan) | |||
| 226 | return -ETIMEDOUT; | 284 | return -ETIMEDOUT; |
| 227 | } | 285 | } |
| 228 | 286 | ||
| 229 | static void pcie_reset(struct sh7786_pcie_port *port) | 287 | static void __init pcie_reset(struct sh7786_pcie_port *port) |
| 230 | { | 288 | { |
| 231 | struct pci_channel *chan = port->hose; | 289 | struct pci_channel *chan = port->hose; |
| 232 | 290 | ||
| @@ -236,7 +294,7 @@ static void pcie_reset(struct sh7786_pcie_port *port) | |||
| 236 | pci_write_reg(chan, 0, SH4A_PCIETXVC0SR); | 294 | pci_write_reg(chan, 0, SH4A_PCIETXVC0SR); |
| 237 | } | 295 | } |
| 238 | 296 | ||
| 239 | static int pcie_init(struct sh7786_pcie_port *port) | 297 | static int __init pcie_init(struct sh7786_pcie_port *port) |
| 240 | { | 298 | { |
| 241 | struct pci_channel *chan = port->hose; | 299 | struct pci_channel *chan = port->hose; |
| 242 | unsigned int data; | 300 | unsigned int data; |
| @@ -411,26 +469,33 @@ int __init pcibios_map_platform_irq(struct pci_dev *pdev, u8 slot, u8 pin) | |||
| 411 | return 71; | 469 | return 71; |
| 412 | } | 470 | } |
| 413 | 471 | ||
| 414 | static int sh7786_pcie_core_init(void) | 472 | static int __init sh7786_pcie_core_init(void) |
| 415 | { | 473 | { |
| 416 | /* Return the number of ports */ | 474 | /* Return the number of ports */ |
| 417 | return test_mode_pin(MODE_PIN12) ? 3 : 2; | 475 | return test_mode_pin(MODE_PIN12) ? 3 : 2; |
| 418 | } | 476 | } |
| 419 | 477 | ||
| 420 | static int __devinit sh7786_pcie_init_hw(struct sh7786_pcie_port *port) | 478 | static int __init sh7786_pcie_init_hw(struct sh7786_pcie_port *port) |
| 421 | { | 479 | { |
| 422 | int ret; | 480 | int ret; |
| 423 | 481 | ||
| 424 | ret = phy_init(port->hose); | ||
| 425 | if (unlikely(ret < 0)) | ||
| 426 | return ret; | ||
| 427 | |||
| 428 | /* | 482 | /* |
| 429 | * Check if we are configured in endpoint or root complex mode, | 483 | * Check if we are configured in endpoint or root complex mode, |
| 430 | * this is a fixed pin setting that applies to all PCIe ports. | 484 | * this is a fixed pin setting that applies to all PCIe ports. |
| 431 | */ | 485 | */ |
| 432 | port->endpoint = test_mode_pin(MODE_PIN11); | 486 | port->endpoint = test_mode_pin(MODE_PIN11); |
| 433 | 487 | ||
| 488 | /* | ||
| 489 | * Setup clocks, needed both for PHY and PCIe registers. | ||
| 490 | */ | ||
| 491 | ret = pcie_clk_init(port); | ||
| 492 | if (unlikely(ret < 0)) | ||
| 493 | return ret; | ||
| 494 | |||
| 495 | ret = phy_init(port); | ||
| 496 | if (unlikely(ret < 0)) | ||
| 497 | return ret; | ||
| 498 | |||
| 434 | ret = pcie_init(port); | 499 | ret = pcie_init(port); |
| 435 | if (unlikely(ret < 0)) | 500 | if (unlikely(ret < 0)) |
| 436 | return ret; | 501 | return ret; |
