diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/sh/boards/mach-sdk7786/setup.c | 54 | ||||
-rw-r--r-- | arch/sh/drivers/pci/fixups-sdk7786.c | 1 | ||||
-rw-r--r-- | arch/sh/drivers/pci/pcie-sh7786.c | 23 | ||||
-rw-r--r-- | arch/sh/include/mach-sdk7786/mach/fpga.h | 2 |
4 files changed, 75 insertions, 5 deletions
diff --git a/arch/sh/boards/mach-sdk7786/setup.c b/arch/sh/boards/mach-sdk7786/setup.c index 2ec1ea5cf8ef..7e0c4e3878e0 100644 --- a/arch/sh/boards/mach-sdk7786/setup.c +++ b/arch/sh/boards/mach-sdk7786/setup.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <asm/machvec.h> | 20 | #include <asm/machvec.h> |
21 | #include <asm/heartbeat.h> | 21 | #include <asm/heartbeat.h> |
22 | #include <asm/sizes.h> | 22 | #include <asm/sizes.h> |
23 | #include <asm/clock.h> | ||
24 | #include <asm/clkdev.h> | ||
23 | #include <asm/reboot.h> | 25 | #include <asm/reboot.h> |
24 | #include <asm/smp-ops.h> | 26 | #include <asm/smp-ops.h> |
25 | 27 | ||
@@ -140,6 +142,45 @@ static int sdk7786_mode_pins(void) | |||
140 | return fpga_read_reg(MODSWR); | 142 | return fpga_read_reg(MODSWR); |
141 | } | 143 | } |
142 | 144 | ||
145 | /* | ||
146 | * FPGA-driven PCIe clocks | ||
147 | * | ||
148 | * Historically these include the oscillator, clock B (slots 2/3/4) and | ||
149 | * clock A (slot 1 and the CPU clock). Newer revs of the PCB shove | ||
150 | * everything under a single PCIe clocks enable bit that happens to map | ||
151 | * to the same bit position as the oscillator bit for earlier FPGA | ||
152 | * versions. | ||
153 | * | ||
154 | * Given that the legacy clocks have the side-effect of shutting the CPU | ||
155 | * off through the FPGA along with the PCI slots, we simply leave them in | ||
156 | * their initial state and don't bother registering them with the clock | ||
157 | * framework. | ||
158 | */ | ||
159 | static int sdk7786_pcie_clk_enable(struct clk *clk) | ||
160 | { | ||
161 | fpga_write_reg(fpga_read_reg(PCIECR) | PCIECR_CLKEN, PCIECR); | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | static void sdk7786_pcie_clk_disable(struct clk *clk) | ||
166 | { | ||
167 | fpga_write_reg(fpga_read_reg(PCIECR) & ~PCIECR_CLKEN, PCIECR); | ||
168 | } | ||
169 | |||
170 | static struct clk_ops sdk7786_pcie_clk_ops = { | ||
171 | .enable = sdk7786_pcie_clk_enable, | ||
172 | .disable = sdk7786_pcie_clk_disable, | ||
173 | }; | ||
174 | |||
175 | static struct clk sdk7786_pcie_clk = { | ||
176 | .ops = &sdk7786_pcie_clk_ops, | ||
177 | }; | ||
178 | |||
179 | static struct clk_lookup sdk7786_pcie_cl = { | ||
180 | .con_id = "pcie_plat_clk", | ||
181 | .clk = &sdk7786_pcie_clk, | ||
182 | }; | ||
183 | |||
143 | static int sdk7786_clk_init(void) | 184 | static int sdk7786_clk_init(void) |
144 | { | 185 | { |
145 | struct clk *clk; | 186 | struct clk *clk; |
@@ -158,7 +199,18 @@ static int sdk7786_clk_init(void) | |||
158 | ret = clk_set_rate(clk, 33333333); | 199 | ret = clk_set_rate(clk, 33333333); |
159 | clk_put(clk); | 200 | clk_put(clk); |
160 | 201 | ||
161 | return ret; | 202 | /* |
203 | * Setup the FPGA clocks. | ||
204 | */ | ||
205 | ret = clk_register(&sdk7786_pcie_clk); | ||
206 | if (unlikely(ret)) { | ||
207 | pr_err("FPGA clock registration failed\n"); | ||
208 | return ret; | ||
209 | } | ||
210 | |||
211 | clkdev_add(&sdk7786_pcie_cl); | ||
212 | |||
213 | return 0; | ||
162 | } | 214 | } |
163 | 215 | ||
164 | static void sdk7786_restart(char *cmd) | 216 | static void sdk7786_restart(char *cmd) |
diff --git a/arch/sh/drivers/pci/fixups-sdk7786.c b/arch/sh/drivers/pci/fixups-sdk7786.c index 058a65a1aa20..0e18ee332553 100644 --- a/arch/sh/drivers/pci/fixups-sdk7786.c +++ b/arch/sh/drivers/pci/fixups-sdk7786.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #define pr_fmt(fmt) "PCI: " fmt | 10 | #define pr_fmt(fmt) "PCI: " fmt |
11 | 11 | ||
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/clk.h> | ||
14 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
15 | #include <linux/pci.h> | 14 | #include <linux/pci.h> |
16 | #include <mach/fpga.h> | 15 | #include <mach/fpga.h> |
diff --git a/arch/sh/drivers/pci/pcie-sh7786.c b/arch/sh/drivers/pci/pcie-sh7786.c index 8ec4af197388..ae0b2c9b70a0 100644 --- a/arch/sh/drivers/pci/pcie-sh7786.c +++ b/arch/sh/drivers/pci/pcie-sh7786.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #include <linux/sh_clk.h> | 17 | #include <linux/sh_clk.h> |
18 | #include "pcie-sh7786.h" | 18 | #include "pcie-sh7786.h" |
19 | #include <asm/sizes.h> | 19 | #include <asm/sizes.h> |
20 | #include <asm/clock.h> | ||
21 | 20 | ||
22 | struct sh7786_pcie_port { | 21 | struct sh7786_pcie_port { |
23 | struct pci_channel *hose; | 22 | struct pci_channel *hose; |
@@ -510,6 +509,7 @@ static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = { | |||
510 | 509 | ||
511 | static int __init sh7786_pcie_init(void) | 510 | static int __init sh7786_pcie_init(void) |
512 | { | 511 | { |
512 | struct clk *platclk; | ||
513 | int ret = 0, i; | 513 | int ret = 0, i; |
514 | 514 | ||
515 | printk(KERN_NOTICE "PCI: Starting initialization.\n"); | 515 | printk(KERN_NOTICE "PCI: Starting initialization.\n"); |
@@ -527,6 +527,22 @@ static int __init sh7786_pcie_init(void) | |||
527 | if (unlikely(!sh7786_pcie_ports)) | 527 | if (unlikely(!sh7786_pcie_ports)) |
528 | return -ENOMEM; | 528 | return -ENOMEM; |
529 | 529 | ||
530 | /* | ||
531 | * Fetch any optional platform clock associated with this block. | ||
532 | * | ||
533 | * This is a rather nasty hack for boards with spec-mocking FPGAs | ||
534 | * that have a secondary set of clocks outside of the on-chip | ||
535 | * ones that need to be accounted for before there is any chance | ||
536 | * of touching the existing MSTP bits or CPG clocks. | ||
537 | */ | ||
538 | platclk = clk_get(NULL, "pcie_plat_clk"); | ||
539 | if (IS_ERR(platclk)) { | ||
540 | /* Sane hardware should probably get a WARN_ON.. */ | ||
541 | platclk = NULL; | ||
542 | } | ||
543 | |||
544 | clk_enable(platclk); | ||
545 | |||
530 | printk(KERN_NOTICE "PCI: probing %d ports.\n", nr_ports); | 546 | printk(KERN_NOTICE "PCI: probing %d ports.\n", nr_ports); |
531 | 547 | ||
532 | for (i = 0; i < nr_ports; i++) { | 548 | for (i = 0; i < nr_ports; i++) { |
@@ -539,8 +555,11 @@ static int __init sh7786_pcie_init(void) | |||
539 | ret |= sh7786_pcie_hwops->port_init_hw(port); | 555 | ret |= sh7786_pcie_hwops->port_init_hw(port); |
540 | } | 556 | } |
541 | 557 | ||
542 | if (unlikely(ret)) | 558 | if (unlikely(ret)) { |
559 | clk_disable(platclk); | ||
560 | clk_put(platclk); | ||
543 | return ret; | 561 | return ret; |
562 | } | ||
544 | 563 | ||
545 | return 0; | 564 | return 0; |
546 | } | 565 | } |
diff --git a/arch/sh/include/mach-sdk7786/mach/fpga.h b/arch/sh/include/mach-sdk7786/mach/fpga.h index 8cc784147b96..b7d93699b679 100644 --- a/arch/sh/include/mach-sdk7786/mach/fpga.h +++ b/arch/sh/include/mach-sdk7786/mach/fpga.h | |||
@@ -39,7 +39,7 @@ | |||
39 | #define PCIECR_PRST3 BIT(11) /* slot 3 card present */ | 39 | #define PCIECR_PRST3 BIT(11) /* slot 3 card present */ |
40 | #define PCIECR_PRST2 BIT(10) /* slot 2 card present */ | 40 | #define PCIECR_PRST2 BIT(10) /* slot 2 card present */ |
41 | #define PCIECR_PRST1 BIT(9) /* slot 1 card present */ | 41 | #define PCIECR_PRST1 BIT(9) /* slot 1 card present */ |
42 | #define PCIECR_CLKEN BIT(4) | 42 | #define PCIECR_CLKEN BIT(4) /* oscillator enable */ |
43 | 43 | ||
44 | #define FAER 0x150 | 44 | #define FAER 0x150 |
45 | #define USRGPIR 0x160 | 45 | #define USRGPIR 0x160 |