]>
Commit | Line | Data |
---|---|---|
a6e50a88 IC |
1 | #include <common.h> |
2 | #include <ahci.h> | |
3 | #include <scsi.h> | |
4 | #include <errno.h> | |
5 | #include <asm/io.h> | |
6 | #include <asm/gpio.h> | |
7 | ||
8 | #define AHCI_PHYCS0R 0x00c0 | |
9 | #define AHCI_PHYCS1R 0x00c4 | |
10 | #define AHCI_PHYCS2R 0x00c8 | |
11 | #define AHCI_RWCR 0x00fc | |
12 | ||
13 | /* This magic PHY initialisation was taken from the Allwinner releases | |
14 | * and Linux driver, but is completely undocumented. | |
15 | */ | |
16 | static int sunxi_ahci_phy_init(u32 base) | |
17 | { | |
18 | u8 *reg_base = (u8 *)base; | |
19 | u32 reg_val; | |
20 | int timeout; | |
21 | ||
22 | writel(0, reg_base + AHCI_RWCR); | |
23 | mdelay(5); | |
24 | ||
25 | setbits_le32(reg_base + AHCI_PHYCS1R, 0x1 << 19); | |
26 | clrsetbits_le32(reg_base + AHCI_PHYCS0R, | |
27 | (0x7 << 24), | |
28 | (0x5 << 24) | (0x1 << 23) | (0x1 << 18)); | |
29 | clrsetbits_le32(reg_base + AHCI_PHYCS1R, | |
30 | (0x3 << 16) | (0x1f << 8) | (0x3 << 6), | |
31 | (0x2 << 16) | (0x6 << 8) | (0x2 << 6)); | |
32 | setbits_le32(reg_base + AHCI_PHYCS1R, (0x1 << 28) | (0x1 << 15)); | |
33 | clrbits_le32(reg_base + AHCI_PHYCS1R, (0x1 << 19)); | |
34 | clrsetbits_le32(reg_base + AHCI_PHYCS0R, (0x7 << 20), (0x3 << 20)); | |
35 | clrsetbits_le32(reg_base + AHCI_PHYCS2R, (0x1f << 5), (0x19 << 5)); | |
36 | mdelay(5); | |
37 | ||
38 | setbits_le32(reg_base + AHCI_PHYCS0R, (0x1 << 19)); | |
39 | ||
40 | timeout = 250; /* Power up takes approx 50 us */ | |
41 | for (;;) { | |
42 | reg_val = readl(reg_base + AHCI_PHYCS0R) & (0x7 << 28); | |
43 | if (reg_val == (0x2 << 28)) | |
44 | break; | |
45 | if (--timeout == 0) { | |
46 | printf("AHCI PHY power up failed.\n"); | |
47 | return -EIO; | |
48 | } | |
49 | udelay(1); | |
50 | }; | |
51 | ||
52 | setbits_le32(reg_base + AHCI_PHYCS2R, (0x1 << 24)); | |
53 | ||
54 | timeout = 100; /* Calibration takes approx 10 us */ | |
55 | for (;;) { | |
56 | reg_val = readl(reg_base + AHCI_PHYCS2R) & (0x1 << 24); | |
57 | if (reg_val == 0x0) | |
58 | break; | |
59 | if (--timeout == 0) { | |
60 | printf("AHCI PHY calibration failed.\n"); | |
61 | return -EIO; | |
62 | } | |
63 | udelay(1); | |
64 | } | |
65 | ||
66 | mdelay(15); | |
67 | ||
68 | writel(0x7, reg_base + AHCI_RWCR); | |
69 | ||
70 | return 0; | |
71 | } | |
72 | ||
73 | void scsi_init(void) | |
74 | { | |
a6e50a88 IC |
75 | if (sunxi_ahci_phy_init(SUNXI_SATA_BASE) < 0) |
76 | return; | |
77 | ||
9efaca3e | 78 | ahci_init((void __iomem *)SUNXI_SATA_BASE); |
a6e50a88 | 79 | } |