uboot/board/sunxi/ahci.c
<<
>>
Prefs
   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 */
  16static 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
  73void scsi_init(void)
  74{
  75        if (sunxi_ahci_phy_init(SUNXI_SATA_BASE) < 0)
  76                return;
  77
  78        ahci_init((void __iomem *)SUNXI_SATA_BASE);
  79}
  80