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; |