9 #include <linux/delay.h>
11 #define AHCI_PHYCS0R 0x00c0
12 #define AHCI_PHYCS1R 0x00c4
13 #define AHCI_PHYCS2R 0x00c8
14 #define AHCI_RWCR 0x00fc
16 /* This magic PHY initialisation was taken from the Allwinner releases
17 * and Linux driver, but is completely undocumented.
19 static int sunxi_ahci_phy_init(u8 *reg_base)
24 writel(0, reg_base + AHCI_RWCR);
27 setbits_le32(reg_base + AHCI_PHYCS1R, 0x1 << 19);
28 clrsetbits_le32(reg_base + AHCI_PHYCS0R,
30 (0x5 << 24) | (0x1 << 23) | (0x1 << 18));
31 clrsetbits_le32(reg_base + AHCI_PHYCS1R,
32 (0x3 << 16) | (0x1f << 8) | (0x3 << 6),
33 (0x2 << 16) | (0x6 << 8) | (0x2 << 6));
34 setbits_le32(reg_base + AHCI_PHYCS1R, (0x1 << 28) | (0x1 << 15));
35 clrbits_le32(reg_base + AHCI_PHYCS1R, (0x1 << 19));
36 clrsetbits_le32(reg_base + AHCI_PHYCS0R, (0x7 << 20), (0x3 << 20));
37 clrsetbits_le32(reg_base + AHCI_PHYCS2R, (0x1f << 5), (0x19 << 5));
40 setbits_le32(reg_base + AHCI_PHYCS0R, (0x1 << 19));
42 timeout = 250; /* Power up takes approx 50 us */
44 reg_val = readl(reg_base + AHCI_PHYCS0R) & (0x7 << 28);
45 if (reg_val == (0x2 << 28))
48 printf("AHCI PHY power up failed.\n");
54 setbits_le32(reg_base + AHCI_PHYCS2R, (0x1 << 24));
56 timeout = 100; /* Calibration takes approx 10 us */
58 reg_val = readl(reg_base + AHCI_PHYCS2R) & (0x1 << 24);
62 printf("AHCI PHY calibration failed.\n");
70 writel(0x7, reg_base + AHCI_RWCR);
75 static int sunxi_sata_probe(struct udevice *dev)
81 base = dev_read_addr(dev);
82 if (base == FDT_ADDR_T_NONE) {
83 debug("%s: Failed to find address\n", __func__);
87 ret = sunxi_ahci_phy_init(reg);
89 debug("%s: Failed to init phy (err=%d)\n", __func__, ret);
92 ret = ahci_probe_scsi(dev, base);
94 debug("%s: Failed to probe (err=%d)\n", __func__, ret);
101 static int sunxi_sata_bind(struct udevice *dev)
103 struct udevice *scsi_dev;
106 ret = ahci_bind_scsi(dev, &scsi_dev);
108 debug("%s: Failed to bind (err=%d)\n", __func__, ret);
115 static const struct udevice_id sunxi_ahci_ids[] = {
116 { .compatible = "allwinner,sun4i-a10-ahci" },
117 { .compatible = "allwinner,sun8i-r40-ahci" },
121 U_BOOT_DRIVER(ahci_sunxi_drv) = {
122 .name = "ahci_sunxi",
124 .of_match = sunxi_ahci_ids,
125 .bind = sunxi_sata_bind,
126 .probe = sunxi_sata_probe,