aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/boot/dts/p1022ds.dtsi16
-rw-r--r--arch/powerpc/platforms/85xx/p1022_ds.c106
2 files changed, 93 insertions, 29 deletions
diff --git a/arch/powerpc/boot/dts/p1022ds.dtsi b/arch/powerpc/boot/dts/p1022ds.dtsi
index 28c36377f9b9..c3344b04d8ff 100644
--- a/arch/powerpc/boot/dts/p1022ds.dtsi
+++ b/arch/powerpc/boot/dts/p1022ds.dtsi
@@ -33,22 +33,6 @@
33 */ 33 */
34 34
35&board_lbc { 35&board_lbc {
36 /*
37 * This node is used to access the pixis via "indirect" mode,
38 * which is done by writing the pixis register index to chip
39 * select 0 and the value to/from chip select 1. Indirect
40 * mode is the only way to access the pixis when DIU video
41 * is enabled. Note that this assumes that the first column
42 * of the 'ranges' property above is the chip select number.
43 */
44 board-control@0,0 {
45 compatible = "fsl,p1022ds-indirect-pixis";
46 reg = <0x0 0x0 1 /* CS0 */
47 0x1 0x0 1>; /* CS1 */
48 interrupt-parent = <&mpic>;
49 interrupts = <8 0 0 0>;
50 };
51
52 nor@0,0 { 36 nor@0,0 {
53 #address-cells = <1>; 37 #address-cells = <1>;
54 #size-cells = <1>; 38 #size-cells = <1>;
diff --git a/arch/powerpc/platforms/85xx/p1022_ds.c b/arch/powerpc/platforms/85xx/p1022_ds.c
index 74e310b4b460..b4437ca3d2c4 100644
--- a/arch/powerpc/platforms/85xx/p1022_ds.c
+++ b/arch/powerpc/platforms/85xx/p1022_ds.c
@@ -27,6 +27,7 @@
27#include <sysdev/fsl_pci.h> 27#include <sysdev/fsl_pci.h>
28#include <asm/udbg.h> 28#include <asm/udbg.h>
29#include <asm/fsl_guts.h> 29#include <asm/fsl_guts.h>
30#include <asm/fsl_lbc.h>
30#include "smp.h" 31#include "smp.h"
31 32
32#include "mpc85xx.h" 33#include "mpc85xx.h"
@@ -142,17 +143,73 @@ static void p1022ds_set_gamma_table(enum fsl_diu_monitor_port port,
142{ 143{
143} 144}
144 145
146struct fsl_law {
147 u32 lawbar;
148 u32 reserved1;
149 u32 lawar;
150 u32 reserved[5];
151};
152
153#define LAWBAR_MASK 0x00F00000
154#define LAWBAR_SHIFT 12
155
156#define LAWAR_EN 0x80000000
157#define LAWAR_TGT_MASK 0x01F00000
158#define LAW_TRGT_IF_LBC (0x04 << 20)
159
160#define LAWAR_MASK (LAWAR_EN | LAWAR_TGT_MASK)
161#define LAWAR_MATCH (LAWAR_EN | LAW_TRGT_IF_LBC)
162
163#define BR_BA 0xFFFF8000
164
165/*
166 * Map a BRx value to a physical address
167 *
168 * The localbus BRx registers only store the lower 32 bits of the address. To
169 * obtain the upper four bits, we need to scan the LAW table. The entry which
170 * maps to the localbus will contain the upper four bits.
171 */
172static phys_addr_t lbc_br_to_phys(const void *ecm, unsigned int count, u32 br)
173{
174#ifndef CONFIG_PHYS_64BIT
175 /*
176 * If we only have 32-bit addressing, then the BRx address *is* the
177 * physical address.
178 */
179 return br & BR_BA;
180#else
181 const struct fsl_law *law = ecm + 0xc08;
182 unsigned int i;
183
184 for (i = 0; i < count; i++) {
185 u64 lawbar = in_be32(&law[i].lawbar);
186 u32 lawar = in_be32(&law[i].lawar);
187
188 if ((lawar & LAWAR_MASK) == LAWAR_MATCH)
189 /* Extract the upper four bits */
190 return (br & BR_BA) | ((lawbar & LAWBAR_MASK) << 12);
191 }
192
193 return 0;
194#endif
195}
196
145/** 197/**
146 * p1022ds_set_monitor_port: switch the output to a different monitor port 198 * p1022ds_set_monitor_port: switch the output to a different monitor port
147 *
148 */ 199 */
149static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port) 200static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
150{ 201{
151 struct device_node *guts_node; 202 struct device_node *guts_node;
152 struct device_node *indirect_node = NULL; 203 struct device_node *lbc_node = NULL;
204 struct device_node *law_node = NULL;
153 struct ccsr_guts __iomem *guts; 205 struct ccsr_guts __iomem *guts;
206 struct fsl_lbc_regs *lbc = NULL;
207 void *ecm = NULL;
154 u8 __iomem *lbc_lcs0_ba = NULL; 208 u8 __iomem *lbc_lcs0_ba = NULL;
155 u8 __iomem *lbc_lcs1_ba = NULL; 209 u8 __iomem *lbc_lcs1_ba = NULL;
210 phys_addr_t cs0_addr, cs1_addr;
211 const __be32 *iprop;
212 unsigned int num_laws;
156 u8 b; 213 u8 b;
157 214
158 /* Map the global utilities registers. */ 215 /* Map the global utilities registers. */
@@ -168,25 +225,43 @@ static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
168 goto exit; 225 goto exit;
169 } 226 }
170 227
171 indirect_node = of_find_compatible_node(NULL, NULL, 228 lbc_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc");
172 "fsl,p1022ds-indirect-pixis"); 229 if (!lbc_node) {
173 if (!indirect_node) { 230 pr_err("p1022ds: missing localbus node\n");
174 pr_err("p1022ds: missing pixis indirect mode node\n");
175 goto exit; 231 goto exit;
176 } 232 }
177 233
178 lbc_lcs0_ba = of_iomap(indirect_node, 0); 234 lbc = of_iomap(lbc_node, 0);
179 if (!lbc_lcs0_ba) { 235 if (!lbc) {
180 pr_err("p1022ds: could not map localbus chip select 0\n"); 236 pr_err("p1022ds: could not map localbus node\n");
181 goto exit; 237 goto exit;
182 } 238 }
183 239
184 lbc_lcs1_ba = of_iomap(indirect_node, 1); 240 law_node = of_find_compatible_node(NULL, NULL, "fsl,ecm-law");
185 if (!lbc_lcs1_ba) { 241 if (!law_node) {
186 pr_err("p1022ds: could not map localbus chip select 1\n"); 242 pr_err("p1022ds: missing local access window node\n");
187 goto exit; 243 goto exit;
188 } 244 }
189 245
246 ecm = of_iomap(law_node, 0);
247 if (!ecm) {
248 pr_err("p1022ds: could not map local access window node\n");
249 goto exit;
250 }
251
252 iprop = of_get_property(law_node, "fsl,num-laws", 0);
253 if (!iprop) {
254 pr_err("p1022ds: LAW node is missing fsl,num-laws property\n");
255 goto exit;
256 }
257 num_laws = be32_to_cpup(iprop);
258
259 cs0_addr = lbc_br_to_phys(ecm, num_laws, in_be32(&lbc->bank[0].br));
260 cs1_addr = lbc_br_to_phys(ecm, num_laws, in_be32(&lbc->bank[1].br));
261
262 lbc_lcs0_ba = ioremap(cs0_addr, 1);
263 lbc_lcs1_ba = ioremap(cs1_addr, 1);
264
190 /* Make sure we're in indirect mode first. */ 265 /* Make sure we're in indirect mode first. */
191 if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) != 266 if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) !=
192 PMUXCR_ELBCDIU_DIU) { 267 PMUXCR_ELBCDIU_DIU) {
@@ -254,10 +329,15 @@ exit:
254 iounmap(lbc_lcs1_ba); 329 iounmap(lbc_lcs1_ba);
255 if (lbc_lcs0_ba) 330 if (lbc_lcs0_ba)
256 iounmap(lbc_lcs0_ba); 331 iounmap(lbc_lcs0_ba);
332 if (lbc)
333 iounmap(lbc);
334 if (ecm)
335 iounmap(ecm);
257 if (guts) 336 if (guts)
258 iounmap(guts); 337 iounmap(guts);
259 338
260 of_node_put(indirect_node); 339 of_node_put(law_node);
340 of_node_put(lbc_node);
261 of_node_put(guts_node); 341 of_node_put(guts_node);
262} 342}
263 343