This enables the necessary clocks, in AHB0 and in PLL6_CFG.

The bulk of the code is taken from the Linux ahci sunxi platform driver
patches, adjusted for u-boot.

This adds the "PORT_DMA" tweaks to the core driver, under a suitable
ifdef.

Tested on and enabled for the cubietruck.

Signed-off-by: Ian Campbell <[email protected]>
---
 arch/arm/cpu/armv7/sunxi/clock.c |  4 ++
 boards.cfg                       |  4 +-
 drivers/block/Makefile           |  1 +
 drivers/block/ahci.c             | 15 ++++++-
 drivers/block/ahci_sunxi.c       | 95 ++++++++++++++++++++++++++++++++++++++++
 include/ahci.h                   |  9 ++++
 include/configs/sunxi-common.h   | 10 +++++
 7 files changed, 135 insertions(+), 3 deletions(-)
 create mode 100644 drivers/block/ahci_sunxi.c

diff --git a/arch/arm/cpu/armv7/sunxi/clock.c b/arch/arm/cpu/armv7/sunxi/clock.c
index 06bc283..2cc274b 100644
--- a/arch/arm/cpu/armv7/sunxi/clock.c
+++ b/arch/arm/cpu/armv7/sunxi/clock.c
@@ -51,6 +51,10 @@ static void clock_init_safe(void)
 #ifdef CONFIG_SUN7I
        writel(0x1 << 6 | readl(&ccm->ahb_gate0), &ccm->ahb_gate0);
        writel(0x1 << 31 | readl(&ccm->pll6_cfg), &ccm->pll6_cfg);
+#ifdef CONFIG_SCSI_AHCI_SUNXI
+       writel(0x1 << 25 |readl(&ccm->ahb_gate0), &ccm->ahb_gate0);
+       writel(0x1 << 14 | readl(&ccm->pll6_cfg), &ccm->pll6_cfg);
+#endif
 #endif
 }
 #endif
diff --git a/boards.cfg b/boards.cfg
index 100acc8..c94d3f2 100644
--- a/boards.cfg
+++ b/boards.cfg
@@ -366,8 +366,8 @@ Active  arm         armv7          sunxi       -            
   sunxi
 Active  arm         armv7          sunxi       -               sunxi           
    Cubieboard                           
sun4i:CUBIEBOARD,SPL,SUNXI_EMAC,STATUSLED=244,STATUSLED1=245                    
                                                  -
 Active  arm         armv7          sunxi       -               sunxi           
    Cubieboard2                          
sun7i:CUBIEBOARD2,SPL,SUNXI_GMAC,STATUSLED=244,STATUSLED1=245,FAST_MBUS         
                                                  -
 Active  arm         armv7          sunxi       -               sunxi           
    Cubieboard2_FEL                      
sun7i:CUBIEBOARD2,SPL_FEL,SUNXI_GMAC,STATUSLED=244,STATUSLED1=245,FAST_MBUS     
                                                  -
-Active  arm         armv7          sunxi       -               sunxi           
    Cubietruck                           
sun7i:CUBIETRUCK,SPL,SUNXI_GMAC,RGMII,STATUSLED=245,STATUSLED1=244,STATUSLED2=235,STATUSLED3=231,FAST_MBUS
                        -
-Active  arm         armv7          sunxi       -               sunxi           
    Cubietruck_FEL                       
sun7i:CUBIETRUCK,SPL_FEL,SUNXI_GMAC,RGMII,STATUSLED=245,STATUSLED1=244,STATUSLED2=235,STATUSLED3=231,FAST_MBUS
                    -
+Active  arm         armv7          sunxi       -               sunxi           
    Cubietruck                           
sun7i:CUBIETRUCK,SPL,SUNXI_GMAC,RGMII,STATUSLED=245,STATUSLED1=244,STATUSLED2=235,STATUSLED3=231,FAST_MBUS,SATAPWR=SUNXI_GPH(12)
                        -
+Active  arm         armv7          sunxi       -               sunxi           
    Cubietruck_FEL                       
sun7i:CUBIETRUCK,SPL_FEL,SUNXI_GMAC,RGMII,STATUSLED=245,STATUSLED1=244,STATUSLED2=235,STATUSLED3=231,FAST_MBUS,SATAPWR=SUNXI_GPH(12)
                    -
 Active  arm         armv7          sunxi       -               sunxi           
    Cubieboard_512                       
sun4i:CUBIEBOARD_512,SPL,SUNXI_EMAC,STATUSLED=244,STATUSLED1=245                
                                                  -
 Active  arm         armv7          sunxi       -               sunxi           
    Cubieboard_FEL                       
sun4i:CUBIEBOARD,SPL_FEL,SUNXI_EMAC,STATUSLED=244,STATUSLED1=245                
                                                  -
 Active  arm         armv7          sunxi       -               sunxi           
    DNS_M82                              sun4i:DNS_M82,SPL                      
                                                                                
           -
diff --git a/drivers/block/Makefile b/drivers/block/Makefile
index 4e94378..e77188b 100644
--- a/drivers/block/Makefile
+++ b/drivers/block/Makefile
@@ -6,6 +6,7 @@
 #
 
 obj-$(CONFIG_SCSI_AHCI) += ahci.o
+obj-$(CONFIG_SCSI_AHCI_SUNXI) += ahci_sunxi.o
 obj-$(CONFIG_ATA_PIIX) += ata_piix.o
 obj-$(CONFIG_DWC_AHSATA) += dwc_ahsata.o
 obj-$(CONFIG_FSL_SATA) += fsl_sata.o
diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c
index 90a0719..32be726 100644
--- a/drivers/block/ahci.c
+++ b/drivers/block/ahci.c
@@ -213,6 +213,13 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
                        msleep(500);
                }
 
+#ifdef CONFIG_SCSI_AHCI_SUNXI
+               tmp = readl(port_mmio + PORT_DMA);
+               tmp &= ~PORT_DMA_SETUP_MASK;
+               tmp |= PORT_DMA_SETUP_INIT;
+               writel_with_flush(tmp, port_mmio + PORT_DMA);
+#endif
+
                /* Add the spinup command to whatever mode bits may
                 * already be on in the command register.
                 */
@@ -490,7 +497,7 @@ static int ahci_port_start(u8 port)
        struct ahci_ioports *pp = &(probe_ent->port[port]);
        volatile u8 *port_mmio = (volatile u8 *)pp->port_mmio;
        u32 port_status;
-       u32 mem;
+       u32 mem, tmp;
 
        debug("Enter start port: %d\n", port);
        port_status = readl(port_mmio + PORT_SCR_STAT);
@@ -540,6 +547,12 @@ static int ahci_port_start(u8 port)
 
        writel_with_flush(pp->rx_fis, port_mmio + PORT_FIS_ADDR);
 
+#ifdef CONFIG_SCSI_AHCI_SUNXI
+       tmp = readl(port_mmio + PORT_DMA);
+       tmp &= ~PORT_DMA_SETUP_MASK;
+        tmp |= PORT_DMA_SETUP_INIT;
+       writel_with_flush(tmp, port_mmio + PORT_DMA);
+#endif
        writel_with_flush(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
                          PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
                          PORT_CMD_START, port_mmio + PORT_CMD);
diff --git a/drivers/block/ahci_sunxi.c b/drivers/block/ahci_sunxi.c
new file mode 100644
index 0000000..2ae742d
--- /dev/null
+++ b/drivers/block/ahci_sunxi.c
@@ -0,0 +1,95 @@
+#include <common.h>
+#include <ahci.h>
+#include <scsi.h>
+#include <asm/io.h>
+#include <asm/gpio.h>
+
+#define AHCI_BISTAFR 0x00a0
+#define AHCI_BISTCR 0x00a4
+#define AHCI_BISTFCTR 0x00a8
+#define AHCI_BISTSR 0x00ac
+#define AHCI_BISTDECR 0x00b0
+#define AHCI_DIAGNR0 0x00b4
+#define AHCI_DIAGNR1 0x00b8
+#define AHCI_OOBR 0x00bc
+#define AHCI_PHYCS0R 0x00c0
+#define AHCI_PHYCS1R 0x00c4
+#define AHCI_PHYCS2R 0x00c8
+#define AHCI_TIMER1MS 0x00e0
+#define AHCI_GPARAM1R 0x00e8
+#define AHCI_GPARAM2R 0x00ec
+#define AHCI_PPARAMR 0x00f0
+#define AHCI_TESTR 0x00f4
+#define AHCI_VERSIONR 0x00f8
+#define AHCI_IDR 0x00fc
+#define AHCI_RWCR 0x00fc
+#define AHCI_P0DMACR 0x0170
+#define AHCI_P0PHYCR 0x0178
+#define AHCI_P0PHYSR 0x017c
+
+#define BIT(x) (1<<x)
+static u32 sunxi_getbits(u8 *reg, u8 mask, u8 shift)
+{
+       return (readl(reg) >> shift) & mask;
+}
+
+static int sunxi_ahci_phy_init(u32 base)
+{
+       u8 *reg_base = (u8 *)base;
+       u32 reg_val;
+       int timeout;
+
+       /* This magic is from the original code */
+       writel(0, reg_base + AHCI_RWCR);
+       mdelay(5);
+
+       setbits_le32(reg_base + AHCI_PHYCS1R, BIT(19));
+       clrsetbits_le32(reg_base + AHCI_PHYCS0R,
+                       (0x7 << 24),
+                       (0x5 << 24) | BIT(23) | BIT(18));
+       clrsetbits_le32(reg_base + AHCI_PHYCS1R,
+                       (0x3 << 16) | (0x1f << 8) | (0x3 << 6),
+                       (0x2 << 16) | (0x6 << 8) | (0x2 << 6));
+       setbits_le32(reg_base + AHCI_PHYCS1R, BIT(28) | BIT(15));
+       clrbits_le32(reg_base + AHCI_PHYCS1R, BIT(19));
+       clrsetbits_le32(reg_base + AHCI_PHYCS0R,
+                       (0x7 << 20), (0x3 << 20));
+       clrsetbits_le32(reg_base + AHCI_PHYCS2R,
+                       (0x1f << 5), (0x19 << 5));
+       mdelay(5);
+
+       setbits_le32(reg_base + AHCI_PHYCS0R, (0x1 << 19));
+
+       timeout = 0x100000;
+       do {
+               reg_val = sunxi_getbits(reg_base + AHCI_PHYCS0R, 0x7, 28);
+       } while (--timeout && (reg_val != 0x2));
+       if (!timeout)
+               printf("PHY power up failed.\n");
+
+       setbits_le32(reg_base + AHCI_PHYCS2R, (0x1 << 24));
+
+       timeout = 0x100000;
+       do {
+               reg_val = sunxi_getbits(reg_base + AHCI_PHYCS2R, 0x1, 24);
+       } while (--timeout && reg_val);
+       if (!timeout)
+               printf("PHY calibration failed.\n");
+       mdelay(15);
+
+       writel(0x7, reg_base + AHCI_RWCR);
+
+       return 0;
+}
+
+void scsi_init(void)
+{
+       printf("SUNXI SCSI INIT\n");
+#ifdef CONFIG_SATAPWR
+       gpio_direction_output(CONFIG_SATAPWR, 1);
+#endif
+
+       sunxi_ahci_phy_init(SUNXI_SATA_BASE);
+
+       ahci_init(SUNXI_SATA_BASE);
+}
diff --git a/include/ahci.h b/include/ahci.h
index 90e8509..c94689c 100644
--- a/include/ahci.h
+++ b/include/ahci.h
@@ -58,6 +58,15 @@
 #define PORT_SCR_ERR           0x30 /* SATA phy register: SError */
 #define PORT_SCR_ACT           0x34 /* SATA phy register: SActive */
 
+#ifdef CONFIG_SCSI_AHCI_SUNXI
+#define PORT_DMA               0x70 /* SUNXI specific "DMA register" */
+
+#define PORT_DMA_SETUP_OFFSET 8 /* dma setup offset */
+#define PORT_DMA_SETUP_MASK   (0xff << PORT_DMA_SETUP_OFFSET) /* dma mask */
+#define PORT_DMA_SETUP_INIT   (0x44 << PORT_DMA_SETUP_OFFSET)
+#endif
+
+
 /* PORT_IRQ_{STAT,MASK} bits */
 #define PORT_IRQ_COLD_PRES     (1 << 31) /* cold presence detect */
 #define PORT_IRQ_TF_ERR                (1 << 30) /* task file error */
diff --git a/include/configs/sunxi-common.h b/include/configs/sunxi-common.h
index d46a43f..dbfbba9 100644
--- a/include/configs/sunxi-common.h
+++ b/include/configs/sunxi-common.h
@@ -88,6 +88,16 @@
 #define CONFIG_SYS_NAND_BASE            0x00
 #endif
 
+#define CONFIG_LIBATA
+#define CONFIG_SCSI_AHCI
+#define CONFIG_SCSI_AHCI_PLAT
+#define CONFIG_SCSI_AHCI_SUNXI
+#define CONFIG_SYS_SCSI_MAX_SCSI_ID    1
+#define CONFIG_SYS_SCSI_MAX_LUN                1
+#define CONFIG_SYS_SCSI_MAX_DEVICE     (CONFIG_SYS_SCSI_MAX_SCSI_ID * \
+                       CONFIG_SYS_SCSI_MAX_LUN)
+#define CONFIG_CMD_SCSI
+
 #define CONFIG_CMD_MEMORY
 #define CONFIG_CMD_SETEXPR
 
-- 
1.8.5.3

-- 
You received this message because you are subscribed to the Google Groups 
"linux-sunxi" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to