in sata_sx4.c [1212:1354]
static unsigned int pdc20621_dimm_init(struct ata_host *host)
{
int speed, size, length;
u32 addr, spd0, pci_status;
u32 time_period = 0;
u32 tcount = 0;
u32 ticks = 0;
u32 clock = 0;
u32 fparam = 0;
void __iomem *mmio = host->iomap[PDC_MMIO_BAR];
/* hard-code chip #0 */
mmio += PDC_CHIP0_OFS;
/* Initialize PLL based upon PCI Bus Frequency */
/* Initialize Time Period Register */
writel(0xffffffff, mmio + PDC_TIME_PERIOD);
time_period = readl(mmio + PDC_TIME_PERIOD);
dev_dbg(host->dev, "Time Period Register (0x40): 0x%x\n", time_period);
/* Enable timer */
writel(PDC_TIMER_DEFAULT, mmio + PDC_TIME_CONTROL);
readl(mmio + PDC_TIME_CONTROL);
/* Wait 3 seconds */
msleep(3000);
/*
When timer is enabled, counter is decreased every internal
clock cycle.
*/
tcount = readl(mmio + PDC_TIME_COUNTER);
dev_dbg(host->dev, "Time Counter Register (0x44): 0x%x\n", tcount);
/*
If SX4 is on PCI-X bus, after 3 seconds, the timer counter
register should be >= (0xffffffff - 3x10^8).
*/
if (tcount >= PCI_X_TCOUNT) {
ticks = (time_period - tcount);
dev_dbg(host->dev, "Num counters 0x%x (%d)\n", ticks, ticks);
clock = (ticks / 300000);
dev_dbg(host->dev, "10 * Internal clk = 0x%x (%d)\n",
clock, clock);
clock = (clock * 33);
dev_dbg(host->dev, "10 * Internal clk * 33 = 0x%x (%d)\n",
clock, clock);
/* PLL F Param (bit 22:16) */
fparam = (1400000 / clock) - 2;
dev_dbg(host->dev, "PLL F Param: 0x%x (%d)\n", fparam, fparam);
/* OD param = 0x2 (bit 31:30), R param = 0x5 (bit 29:25) */
pci_status = (0x8a001824 | (fparam << 16));
} else
pci_status = PCI_PLL_INIT;
/* Initialize PLL. */
dev_dbg(host->dev, "pci_status: 0x%x\n", pci_status);
writel(pci_status, mmio + PDC_CTL_STATUS);
readl(mmio + PDC_CTL_STATUS);
/*
Read SPD of DIMM by I2C interface,
and program the DIMM Module Controller.
*/
if (!(speed = pdc20621_detect_dimm(host))) {
dev_err(host->dev, "Detect Local DIMM Fail\n");
return 1; /* DIMM error */
}
dev_dbg(host->dev, "Local DIMM Speed = %d\n", speed);
/* Programming DIMM0 Module Control Register (index_CID0:80h) */
size = pdc20621_prog_dimm0(host);
dev_dbg(host->dev, "Local DIMM Size = %dMB\n", size);
/* Programming DIMM Module Global Control Register (index_CID0:88h) */
if (pdc20621_prog_dimm_global(host)) {
dev_err(host->dev,
"Programming DIMM Module Global Control Register Fail\n");
return 1;
}
if (dimm_test) {
u8 test_parttern1[40] =
{0x55,0xAA,'P','r','o','m','i','s','e',' ',
'N','o','t',' ','Y','e','t',' ',
'D','e','f','i','n','e','d',' ',
'1','.','1','0',
'9','8','0','3','1','6','1','2',0,0};
u8 test_parttern2[40] = {0};
pdc20621_put_to_dimm(host, test_parttern2, 0x10040, 40);
pdc20621_put_to_dimm(host, test_parttern2, 0x40, 40);
pdc20621_put_to_dimm(host, test_parttern1, 0x10040, 40);
pdc20621_get_from_dimm(host, test_parttern2, 0x40, 40);
dev_info(host->dev, "DIMM test pattern 1: %x, %x, %s\n", test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
pdc20621_get_from_dimm(host, test_parttern2, 0x10040,
40);
dev_info(host->dev, "DIMM test pattern 2: %x, %x, %s\n",
test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
pdc20621_put_to_dimm(host, test_parttern1, 0x40, 40);
pdc20621_get_from_dimm(host, test_parttern2, 0x40, 40);
dev_info(host->dev, "DIMM test pattern 3: %x, %x, %s\n",
test_parttern2[0],
test_parttern2[1], &(test_parttern2[2]));
}
/* ECC initiliazation. */
if (!pdc20621_i2c_read(host, PDC_DIMM0_SPD_DEV_ADDRESS,
PDC_DIMM_SPD_TYPE, &spd0)) {
dev_err(host->dev,
"Failed in i2c read: device=%#x, subaddr=%#x\n",
PDC_DIMM0_SPD_DEV_ADDRESS, PDC_DIMM_SPD_TYPE);
return 1;
}
if (spd0 == 0x02) {
void *buf;
dev_dbg(host->dev, "Start ECC initialization\n");
addr = 0;
length = size * 1024 * 1024;
buf = kzalloc(ECC_ERASE_BUF_SZ, GFP_KERNEL);
if (!buf)
return 1;
while (addr < length) {
pdc20621_put_to_dimm(host, buf, addr,
ECC_ERASE_BUF_SZ);
addr += ECC_ERASE_BUF_SZ;
}
kfree(buf);
dev_dbg(host->dev, "Finish ECC initialization\n");
}
return 0;
}