[U-Boot] [PATCH v2 3/3] ahci: provide sunxi SATA driver using AHCI platform framework
Rob Herring
robherring2 at gmail.com
Thu Feb 20 16:24:55 CET 2014
On Thu, Feb 20, 2014 at 8:48 AM, Ian Campbell <ijc at hellion.org.uk> wrote:
> 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 <ijc at hellion.org.uk>
> ---
> 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 | 95 ++++++++++++++++++++++++++++++++++++++++
> include/ahci.h | 9 ++++
> include/configs/sunxi-common.h | 12 +++++
> 7 files changed, 144 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..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
These registers are not sunxi specific, but part of a certain vendor's
IP found in several SOCs. I can't tell you who, but it shouldn't be
too hard to figure out.
> +
> +#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);
> +
I would guess this code or something very similar already exists in u-boot.
Rob
More information about the U-Boot
mailing list