/* These are the addresses we want.. */ #define WINDOW_ADDR_0 0x08800000 #define WINDOW_ADDR_1 0x09000000 #define WINDOW_ADDR_2 0x09800000
/* .. and these are the addresses the BIOS gives us */ #define WINDOW_ADDR_0_BIOS 0x08400000 #define WINDOW_ADDR_1_BIOS 0x08c00000 #define WINDOW_ADDR_2_BIOS 0x09400000
staticconststruct sc520_par_table par_table[NUM_FLASH_BANKS] =
{
{ /* Flash Bank #0: selected by ROMCS0 */
SC520_PAR_ROMCS0,
SC520_PAR_ENTRY(SC520_PAR_ROMCS0, WINDOW_ADDR_0, WINDOW_SIZE_0),
WINDOW_ADDR_0_BIOS
},
{ /* Flash Bank #1: selected by ROMCS1 */
SC520_PAR_ROMCS1,
SC520_PAR_ENTRY(SC520_PAR_ROMCS1, WINDOW_ADDR_1, WINDOW_SIZE_1),
WINDOW_ADDR_1_BIOS
},
{ /* DIL (BIOS) Flash: selected by BOOTCS */
SC520_PAR_BOOTCS,
SC520_PAR_ENTRY(SC520_PAR_BOOTCS, WINDOW_ADDR_2, WINDOW_SIZE_2),
WINDOW_ADDR_2_BIOS
}
};
staticvoid sc520cdp_setup_par(void)
{ unsignedlong __iomem *mmcr; unsignedlong mmcr_val; int i, j;
/* map in SC520's MMCR area */
mmcr = ioremap(SC520_MMCR_BASE, SC520_MMCR_EXTENT); if(!mmcr) { /* ioremap failed: skip the PAR reprogramming */ /* force physical address fields to BIOS defaults: */ for(i = 0; i < NUM_FLASH_BANKS; i++)
sc520cdp_map[i].phys = par_table[i].default_address; return;
}
/* **FindthePARxxregistersthatareresponsibleforactivating **ROMCS0,ROMCS1andBOOTCS.Reprogrameachofthesewitha **newvaluefromthetable.
*/ for(i = 0; i < NUM_FLASH_BANKS; i++) { /* for each par_table entry */ for(j = 0; j < NUM_SC520_PAR; j++) { /* for each PAR register */
mmcr_val = readl(&mmcr[SC520_PAR(j)]); /* if target device field matches, reprogram the PAR */ if((mmcr_val & SC520_PAR_TRGDEV) == par_table[i].trgdev)
{
writel(par_table[i].new_par, &mmcr[SC520_PAR(j)]); break;
}
} if(j == NUM_SC520_PAR)
{ /* no matching PAR found: try default BIOS address */
printk(KERN_NOTICE "Could not find PAR responsible for %s\n",
sc520cdp_map[i].name);
printk(KERN_NOTICE "Trying default address 0x%lx\n",
par_table[i].default_address);
sc520cdp_map[i].phys = par_table[i].default_address;
}
}
iounmap(mmcr);
} #endif
staticint __init init_sc520cdp(void)
{ int i, j, devices_found = 0;
#ifdef REPROGRAM_PAR /* reprogram PAR registers so flash appears at the desired addresses */
sc520cdp_setup_par(); #endif
for (i = 0; i < NUM_FLASH_BANKS; i++) {
printk(KERN_NOTICE "SC520 CDP flash device: 0x%Lx at 0x%Lx\n",
(unsignedlonglong)sc520cdp_map[i].size,
(unsignedlonglong)sc520cdp_map[i].phys);
if (mymtd[i]) {
mymtd[i]->owner = THIS_MODULE;
++devices_found;
} else {
iounmap(sc520cdp_map[i].virt);
}
} if(devices_found >= 2) { /* Combine the two flash banks into a single MTD device & register it: */
merged_mtd = mtd_concat_create(mymtd, 2, "SC520CDP Flash Banks #0 and #1"); if(merged_mtd)
mtd_device_register(merged_mtd, NULL, 0);
} if(devices_found == 3) /* register the third (DIL-Flash) device */
mtd_device_register(mymtd[2], NULL, 0); return(devices_found ? 0 : -ENXIO);
}
staticvoid __exit cleanup_sc520cdp(void)
{ int i;
if (merged_mtd) {
mtd_device_unregister(merged_mtd);
mtd_concat_destroy(merged_mtd);
} if (mymtd[2])
mtd_device_unregister(mymtd[2]);
for (i = 0; i < NUM_FLASH_BANKS; i++) { if (mymtd[i])
map_destroy(mymtd[i]); if (sc520cdp_map[i].virt) {
iounmap(sc520cdp_map[i].virt);
sc520cdp_map[i].virt = NULL;
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.