aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/83xx
diff options
context:
space:
mode:
authorChristian Herzig <christian.herzig@keymile.com>2012-05-08 09:57:20 -0400
committerKumar Gala <galak@kernel.crashing.org>2012-07-10 08:07:20 -0400
commit4bfc1dd9d67492fb127cc054c7d2b8ca9c3f76f8 (patch)
tree296860069f9fa6ebb150cb1acdc085b8388e6e0d /arch/powerpc/platforms/83xx
parentf7854e72a39b10f66bcf056041d179716d59897c (diff)
powerpc/83xx: fix RGMII AC values workaround for km83xx
Fix RGMII workaround code in km83xx.c for MPC8360E and MPC8358E that it correctly identifes all affected SoC chip models and applies the workarounds appropriate for 2.0 and 2.1 revisions as per Freescale MPC8360ECE Errata document Rev.5(9/2011) item QE_ENET10. Signed-off-by: Christian Herzig <christian.herzig@keymile.com> Signed-off-by: Holger Brunck <holger.brunck@keymile.com> cc: Heiko Schocher <hs@denx.de> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/platforms/83xx')
-rw-r--r--arch/powerpc/platforms/83xx/km83xx.c98
1 files changed, 66 insertions, 32 deletions
diff --git a/arch/powerpc/platforms/83xx/km83xx.c b/arch/powerpc/platforms/83xx/km83xx.c
index e827c6cc2fea..89923d723349 100644
--- a/arch/powerpc/platforms/83xx/km83xx.c
+++ b/arch/powerpc/platforms/83xx/km83xx.c
@@ -3,7 +3,7 @@
3 * Author: Heiko Schocher <hs@denx.de> 3 * Author: Heiko Schocher <hs@denx.de>
4 * 4 *
5 * Description: 5 * Description:
6 * Keymile KMETER1 board specific routines. 6 * Keymile 83xx platform specific routines.
7 * 7 *
8 * This program is free software; you can redistribute it and/or modify it 8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the 9 * under the terms of the GNU General Public License as published by the
@@ -76,48 +76,82 @@ static void __init mpc83xx_km_setup_arch(void)
76 76
77 np = of_find_compatible_node(NULL, "network", "ucc_geth"); 77 np = of_find_compatible_node(NULL, "network", "ucc_geth");
78 if (np != NULL) { 78 if (np != NULL) {
79 uint svid; 79 /*
80 * handle mpc8360E Erratum QE_ENET10:
81 * RGMII AC values do not meet the specification
82 */
83 uint svid = mfspr(SPRN_SVR);
84 struct device_node *np_par;
85 struct resource res;
86 void __iomem *base;
87 int ret;
88
89 np_par = of_find_node_by_name(NULL, "par_io");
90 if (np_par == NULL) {
91 printk(KERN_WARNING "%s couldn;t find par_io node\n",
92 __func__);
93 return;
94 }
95 /* Map Parallel I/O ports registers */
96 ret = of_address_to_resource(np_par, 0, &res);
97 if (ret) {
98 printk(KERN_WARNING "%s couldn;t map par_io registers\n",
99 __func__);
100 return;
101 }
102
103 base = ioremap(res.start, res.end - res.start + 1);
104
105 /*
106 * set output delay adjustments to default values according
107 * table 5 in Errata Rev. 5, 9/2011:
108 *
109 * write 0b01 to UCC1 bits 18:19
110 * write 0b01 to UCC2 option 1 bits 4:5
111 * write 0b01 to UCC2 option 2 bits 16:17
112 */
113 clrsetbits_be32((base + 0xa8), 0x0c00f000, 0x04005000);
114
115 /*
116 * set output delay adjustments to default values according
117 * table 3-13 in Reference Manual Rev.3 05/2010:
118 *
119 * write 0b01 to UCC2 option 2 bits 16:17
120 * write 0b0101 to UCC1 bits 20:23
121 * write 0b0101 to UCC2 option 1 bits 24:27
122 */
123 clrsetbits_be32((base + 0xac), 0x0000cff0, 0x00004550);
80 124
81 /* handle mpc8360ea rev.2.1 erratum 2: RGMII Timing */
82 svid = mfspr(SPRN_SVR);
83 if (SVR_REV(svid) == 0x0021) { 125 if (SVR_REV(svid) == 0x0021) {
84 struct device_node *np_par; 126 /*
85 struct resource res; 127 * UCC2 option 1: write 0b1010 to bits 24:27
86 void __iomem *base; 128 * at address IMMRBAR+0x14AC
87 int ret; 129 */
88 130 clrsetbits_be32((base + 0xac), 0x000000f0, 0x000000a0);
89 np_par = of_find_node_by_name(NULL, "par_io"); 131 } else if (SVR_REV(svid) == 0x0020) {
90 if (np_par == NULL) { 132 /*
91 printk(KERN_WARNING "%s couldn;t find par_io node\n", 133 * UCC1: write 0b11 to bits 18:19
92 __func__); 134 * at address IMMRBAR+0x14A8
93 return; 135 */
94 } 136 setbits32((base + 0xa8), 0x00003000);
95 /* Map Parallel I/O ports registers */
96 ret = of_address_to_resource(np_par, 0, &res);
97 if (ret) {
98 printk(KERN_WARNING "%s couldn;t map par_io registers\n",
99 __func__);
100 return;
101 }
102 base = ioremap(res.start, resource_size(&res));
103 137
104 /* 138 /*
105 * IMMR + 0x14A8[4:5] = 11 (clk delay for UCC 2) 139 * UCC2 option 1: write 0b11 to bits 4:5
106 * IMMR + 0x14A8[18:19] = 11 (clk delay for UCC 1) 140 * at address IMMRBAR+0x14A8
107 */ 141 */
108 setbits32((base + 0xa8), 0x0c003000); 142 setbits32((base + 0xa8), 0x0c000000);
109 143
110 /* 144 /*
111 * IMMR + 0x14AC[20:27] = 10101010 145 * UCC2 option 2: write 0b11 to bits 16:17
112 * (data delay for both UCC's) 146 * at address IMMRBAR+0x14AC
113 */ 147 */
114 clrsetbits_be32((base + 0xac), 0xff0, 0xaa0); 148 setbits32((base + 0xac), 0x0000c000);
115 iounmap(base);
116 of_node_put(np_par);
117 } 149 }
150 iounmap(base);
151 of_node_put(np_par);
118 of_node_put(np); 152 of_node_put(np);
119 } 153 }
120#endif /* CONFIG_QUICC_ENGINE */ 154#endif /* CONFIG_QUICC_ENGINE */
121} 155}
122 156
123machine_device_initcall(mpc83xx_km, mpc83xx_declare_of_platform_devices); 157machine_device_initcall(mpc83xx_km, mpc83xx_declare_of_platform_devices);