in platforms/85xx/p1022_ds.c [163:365]
static void p1022ds_set_monitor_port(enum fsl_diu_monitor_port port)
{
struct device_node *guts_node;
struct device_node *lbc_node = NULL;
struct device_node *law_node = NULL;
struct ccsr_guts __iomem *guts;
struct fsl_lbc_regs *lbc = NULL;
void *ecm = NULL;
u8 __iomem *lbc_lcs0_ba = NULL;
u8 __iomem *lbc_lcs1_ba = NULL;
phys_addr_t cs0_addr, cs1_addr;
u32 br0, or0, br1, or1;
const __be32 *iprop;
unsigned int num_laws;
u8 b;
/* Map the global utilities registers. */
guts_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
if (!guts_node) {
pr_err("p1022ds: missing global utilities device node\n");
return;
}
guts = of_iomap(guts_node, 0);
if (!guts) {
pr_err("p1022ds: could not map global utilities device\n");
goto exit;
}
lbc_node = of_find_compatible_node(NULL, NULL, "fsl,p1022-elbc");
if (!lbc_node) {
pr_err("p1022ds: missing localbus node\n");
goto exit;
}
lbc = of_iomap(lbc_node, 0);
if (!lbc) {
pr_err("p1022ds: could not map localbus node\n");
goto exit;
}
law_node = of_find_compatible_node(NULL, NULL, "fsl,ecm-law");
if (!law_node) {
pr_err("p1022ds: missing local access window node\n");
goto exit;
}
ecm = of_iomap(law_node, 0);
if (!ecm) {
pr_err("p1022ds: could not map local access window node\n");
goto exit;
}
iprop = of_get_property(law_node, "fsl,num-laws", NULL);
if (!iprop) {
pr_err("p1022ds: LAW node is missing fsl,num-laws property\n");
goto exit;
}
num_laws = be32_to_cpup(iprop);
/*
* Indirect mode requires both BR0 and BR1 to be set to "GPCM",
* otherwise writes to these addresses won't actually appear on the
* local bus, and so the PIXIS won't see them.
*
* In FCM mode, writes go to the NAND controller, which does not pass
* them to the localbus directly. So we force BR0 and BR1 into GPCM
* mode, since we don't care about what's behind the localbus any
* more.
*/
br0 = in_be32(&lbc->bank[0].br);
br1 = in_be32(&lbc->bank[1].br);
or0 = in_be32(&lbc->bank[0].or);
or1 = in_be32(&lbc->bank[1].or);
/* Make sure CS0 and CS1 are programmed */
if (!(br0 & BR_V) || !(br1 & BR_V)) {
pr_err("p1022ds: CS0 and/or CS1 is not programmed\n");
goto exit;
}
/*
* Use the existing BRx/ORx values if it's already GPCM. Otherwise,
* force the values to simple 32KB GPCM windows with the most
* conservative timing.
*/
if ((br0 & BR_MSEL) != BR_MS_GPCM) {
br0 = (br0 & BR_BA) | BR_V;
or0 = 0xFFFF8000 | 0xFF7;
out_be32(&lbc->bank[0].br, br0);
out_be32(&lbc->bank[0].or, or0);
}
if ((br1 & BR_MSEL) != BR_MS_GPCM) {
br1 = (br1 & BR_BA) | BR_V;
or1 = 0xFFFF8000 | 0xFF7;
out_be32(&lbc->bank[1].br, br1);
out_be32(&lbc->bank[1].or, or1);
}
cs0_addr = lbc_br_to_phys(ecm, num_laws, br0);
if (!cs0_addr) {
pr_err("p1022ds: could not determine physical address for CS0"
" (BR0=%08x)\n", br0);
goto exit;
}
cs1_addr = lbc_br_to_phys(ecm, num_laws, br1);
if (!cs1_addr) {
pr_err("p1022ds: could not determine physical address for CS1"
" (BR1=%08x)\n", br1);
goto exit;
}
lbc_lcs0_ba = ioremap(cs0_addr, 1);
if (!lbc_lcs0_ba) {
pr_err("p1022ds: could not ioremap CS0 address %llx\n",
(unsigned long long)cs0_addr);
goto exit;
}
lbc_lcs1_ba = ioremap(cs1_addr, 1);
if (!lbc_lcs1_ba) {
pr_err("p1022ds: could not ioremap CS1 address %llx\n",
(unsigned long long)cs1_addr);
goto exit;
}
/* Make sure we're in indirect mode first. */
if ((in_be32(&guts->pmuxcr) & PMUXCR_ELBCDIU_MASK) !=
PMUXCR_ELBCDIU_DIU) {
struct device_node *pixis_node;
void __iomem *pixis;
pixis_node =
of_find_compatible_node(NULL, NULL, "fsl,p1022ds-fpga");
if (!pixis_node) {
pr_err("p1022ds: missing pixis node\n");
goto exit;
}
pixis = of_iomap(pixis_node, 0);
of_node_put(pixis_node);
if (!pixis) {
pr_err("p1022ds: could not map pixis registers\n");
goto exit;
}
/* Enable indirect PIXIS mode. */
setbits8(pixis + PX_CTL, PX_CTL_ALTACC);
iounmap(pixis);
/* Switch the board mux to the DIU */
out_8(lbc_lcs0_ba, PX_BRDCFG0); /* BRDCFG0 */
b = in_8(lbc_lcs1_ba);
b |= PX_BRDCFG0_ELBC_DIU;
out_8(lbc_lcs1_ba, b);
/* Set the chip mux to DIU mode. */
clrsetbits_be32(&guts->pmuxcr, PMUXCR_ELBCDIU_MASK,
PMUXCR_ELBCDIU_DIU);
in_be32(&guts->pmuxcr);
}
switch (port) {
case FSL_DIU_PORT_DVI:
/* Enable the DVI port, disable the DFP and the backlight */
out_8(lbc_lcs0_ba, PX_BRDCFG1);
b = in_8(lbc_lcs1_ba);
b &= ~(PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT);
b |= PX_BRDCFG1_DVIEN;
out_8(lbc_lcs1_ba, b);
break;
case FSL_DIU_PORT_LVDS:
/*
* LVDS also needs backlight enabled, otherwise the display
* will be blank.
*/
/* Enable the DFP port, disable the DVI and the backlight */
out_8(lbc_lcs0_ba, PX_BRDCFG1);
b = in_8(lbc_lcs1_ba);
b &= ~PX_BRDCFG1_DVIEN;
b |= PX_BRDCFG1_DFPEN | PX_BRDCFG1_BACKLIGHT;
out_8(lbc_lcs1_ba, b);
break;
default:
pr_err("p1022ds: unsupported monitor port %i\n", port);
}
exit:
if (lbc_lcs1_ba)
iounmap(lbc_lcs1_ba);
if (lbc_lcs0_ba)
iounmap(lbc_lcs0_ba);
if (lbc)
iounmap(lbc);
if (ecm)
iounmap(ecm);
if (guts)
iounmap(guts);
of_node_put(law_node);
of_node_put(lbc_node);
of_node_put(guts_node);
}