From patchwork Fri Mar 7 01:20:59 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Campbell X-Patchwork-Id: 327696 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from theia.denx.de (theia.denx.de [85.214.87.163]) by ozlabs.org (Postfix) with ESMTP id 213C52C0323 for ; Fri, 7 Mar 2014 12:21:48 +1100 (EST) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id DB8AE4B60B; Fri, 7 Mar 2014 02:21:40 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id dXpzVYGJ4Ggy; Fri, 7 Mar 2014 02:21:40 +0100 (CET) Received: from theia.denx.de (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id 4275B4B61F; Fri, 7 Mar 2014 02:21:39 +0100 (CET) Received: from localhost (localhost [127.0.0.1]) by theia.denx.de (Postfix) with ESMTP id ADE784B61F for ; Fri, 7 Mar 2014 02:21:37 +0100 (CET) X-Virus-Scanned: Debian amavisd-new at theia.denx.de Received: from theia.denx.de ([127.0.0.1]) by localhost (theia.denx.de [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id RRL7+k6z4a8i for ; Fri, 7 Mar 2014 02:21:36 +0100 (CET) X-policyd-weight: NOT_IN_SBL_XBL_SPAMHAUS=-1.5 NOT_IN_SPAMCOP=-1.5 NOT_IN_BL_NJABL=-1.5 (only DNSBL check requested) Received: from benson.vm.bytemark.co.uk (benson.vm.bytemark.co.uk [212.110.190.137]) by theia.denx.de (Postfix) with ESMTPS id 52D284B60B for ; Fri, 7 Mar 2014 02:21:30 +0100 (CET) Received: from z88l218.static.ctm.net ([202.175.88.218] helo=hastur.hellion.org.uk) by benson.vm.bytemark.co.uk with esmtpsa (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.72) (envelope-from ) id 1WLjTb-0000LW-JS; Fri, 07 Mar 2014 01:21:29 +0000 Received: by hastur.hellion.org.uk (sSMTP sendmail emulation); Fri, 07 Mar 2014 01:21:21 +0000 From: Ian Campbell To: linux-sunxi@googlegroups.com, u-boot@lists.denx.de Date: Fri, 7 Mar 2014 01:20:59 +0000 Message-Id: <1394155259-21897-4-git-send-email-ijc@hellion.org.uk> X-Mailer: git-send-email 1.8.5.3 In-Reply-To: <1394155172.13270.18.camel@hastur.hellion.org.uk> References: <1394155172.13270.18.camel@hastur.hellion.org.uk> Cc: Tom Rini , rob.herring@linaro.org, ijc@hellion.org.uk Subject: [U-Boot] [PATCH v3 4/4] ahci: provide sunxi SATA driver using AHCI platform framework X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.11 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: u-boot-bounces@lists.denx.de Errors-To: u-boot-bounces@lists.denx.de This enables the necessary clocks, in AHB0 and in PLL6_CFG. This is done for sun7i only since I don't have access to any other sunxi platforms with sata included. 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. This option is enabled for Cubieboard, Cubieboard2, Cubietruck and Olinuxino Micro based on contents of Linux DTS files, including SATA power pin config taken from the DTS. All build tested, but runtime tested on cubietruck (FEL) only. Signed-off-by: Ian Campbell --- v3: Drop unused register definitions v2: make AHCI configurable per board, enabled for cubieboard, cubieboard2, cubietruck and Olinuxino Micro. --- arch/arm/cpu/armv7/sunxi/clock.c | 4 +++ boards.cfg | 18 +++++----- drivers/block/Makefile | 1 + drivers/block/ahci.c | 15 +++++++- drivers/block/ahci_sunxi.c | 77 ++++++++++++++++++++++++++++++++++++++++ include/ahci.h | 9 +++++ include/configs/sunxi-common.h | 12 +++++++ 7 files changed, 126 insertions(+), 10 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..987bc54 100644 --- a/boards.cfg +++ b/boards.cfg @@ -354,8 +354,8 @@ Active arm armv7 sunxi - sunxi Active arm armv7 sunxi - sunxi A13-OLinuXinoM sun5i:A13_OLINUXINOM,SPL,NO_AXP,STATUSLED=201,CONS_INDEX=2 - Active arm armv7 sunxi - sunxi A13-OLinuXinoM_FEL sun5i:A13_OLINUXINOM,SPL_FEL,NO_AXP,STATUSLED=201,CONS_INDEX=2 - Active arm armv7 sunxi - sunxi A13_MID sun5i:A13_MID,SPL,CONS_INDEX=2 - -Active arm armv7 sunxi - sunxi A20-OLinuXino_MICRO sun7i:A20_OLINUXINO_M,CONS_INDEX=1,STATUSLED=226,SPL,SUNXI_EMAC - -Active arm armv7 sunxi - sunxi A20-OLinuXino_MICRO_FEL sun7i:A20_OLINUXINO_M,CONS_INDEX=1,STATUSLED=226,SPL_FEL,SUNXI_EMAC - +Active arm armv7 sunxi - sunxi A20-OLinuXino_MICRO sun7i:A20_OLINUXINO_M,CONS_INDEX=1,STATUSLED=226,SPL,SUNXI_EMAC,AHCI,SATAPWR=SUNXI_GPB(8) - +Active arm armv7 sunxi - sunxi A20-OLinuXino_MICRO_FEL sun7i:A20_OLINUXINO_M,CONS_INDEX=1,STATUSLED=226,SPL_FEL,SUNXI_EMAC,AHCI,SATAPWR=SUNXI_GPB(8) - Active arm armv7 sunxi - sunxi Auxtek-T003 sun5i:AUXTEK_T003,SPL,AXP152_POWER,STATUSLED=34 - Active arm armv7 sunxi - sunxi Auxtek-T004 sun5i:AUXTEK_T004,SPL,AXP152_POWER,STATUSLED=34 - Active arm armv7 sunxi - sunxi ba10_tv_box sun4i:BA10_TV_BOX,SPL,SUNXI_EMAC - @@ -363,13 +363,13 @@ Active arm armv7 sunxi - sunxi Active arm armv7 sunxi - sunxi Coby_MID8042 sun4i:COBY_MID8042,SPL - Active arm armv7 sunxi - sunxi Coby_MID9742 sun4i:COBY_MID9742,SPL - Active arm armv7 sunxi - sunxi Colombus sun6i:COLOMBUS - -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 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 Cubieboard sun4i:CUBIEBOARD,SPL,SUNXI_EMAC,STATUSLED=244,STATUSLED1=245,AHCI,SATAPWR=SUNXI_GPB(8) - +Active arm armv7 sunxi - sunxi Cubieboard2 sun7i:CUBIEBOARD2,SPL,SUNXI_GMAC,STATUSLED=244,STATUSLED1=245,FAST_MBUS,AHCI,SATAPWR=SUNXI_GPB(8) - +Active arm armv7 sunxi - sunxi Cubieboard2_FEL sun7i:CUBIEBOARD2,SPL_FEL,SUNXI_GMAC,STATUSLED=244,STATUSLED1=245,FAST_MBUS,AHCI,SATAPWR=SUNXI_GPB(8) - +Active arm armv7 sunxi - sunxi Cubietruck sun7i:CUBIETRUCK,SPL,SUNXI_GMAC,RGMII,STATUSLED=245,STATUSLED1=244,STATUSLED2=235,STATUSLED3=231,FAST_MBUS,AHCI,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,AHCI,SATAPWR=SUNXI_GPH(12) - +Active arm armv7 sunxi - sunxi Cubieboard_512 sun4i:CUBIEBOARD_512,SPL,SUNXI_EMAC,STATUSLED=244,STATUSLED1=245,AHCI,SATAPWR=SUNXI_GPB(8) - +Active arm armv7 sunxi - sunxi Cubieboard_FEL sun4i:CUBIEBOARD,SPL_FEL,SUNXI_EMAC,STATUSLED=244,STATUSLED1=245,AHCI,SATAPWR=SUNXI_GPB(8) - Active arm armv7 sunxi - sunxi DNS_M82 sun4i:DNS_M82,SPL - Active arm armv7 sunxi - sunxi EOMA68_A10 sun4i:EOMA68_A10,SPL,MMC_SUNXI_SLOT=3,SUNXI_EMAC - Active arm armv7 sunxi - sunxi EOMA68_A10_FEL sun4i:EOMA68_A10,SPL_FEL,MMC_SUNXI_SLOT=3,SUNXI_EMAC - 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..6bffc76 --- /dev/null +++ b/drivers/block/ahci_sunxi.c @@ -0,0 +1,77 @@ +#include +#include +#include +#include +#include + +#define AHCI_PHYCS0R 0x00c0 +#define AHCI_PHYCS1R 0x00c4 +#define AHCI_PHYCS2R 0x00c8 +#define AHCI_RWCR 0x00fc + +#define BIT(x) (1<> 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..be4c6b5 100644 --- a/include/configs/sunxi-common.h +++ b/include/configs/sunxi-common.h @@ -88,6 +88,18 @@ #define CONFIG_SYS_NAND_BASE 0x00 #endif +#ifdef CONFIG_AHCI +#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 +#endif + #define CONFIG_CMD_MEMORY #define CONFIG_CMD_SETEXPR