[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