[U-Boot] [PATCH 3/3] ahci: provide sunxi SATA driver using AHCI platform framework

Hans de Goede hdegoede at redhat.com
Sat Jul 19 14:34:08 CEST 2014


Hi,

On 07/18/2014 09:38 PM, Ian Campbell 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 PHY setup is derived from the Alwinner releases and Linux, but is mostly
> undocumented.
>
> The Allwinner AHCI controller also requires some magic (and, again,
> undocumented) DMA initialisation when starting a port.  This is added under a
> suitable ifdef.
>
> This option is enabled for Cubieboard, Cubieboard2 and Cubietruck based on
> contents of Linux DTS files, including SATA power pin config taken from the
> DTS. All build tested, but runtime tested on Cubieboard2 and Cubietruck only.
>
> Signed-off-by: Ian Campbell <ijc at hellion.org.uk>

Looks good to me:

Acked-by: Hans de Goede <hdegoede at redhat.com>

Regards,

Hans

> ---
>   arch/arm/cpu/armv7/sunxi/clock_sun4i.c        |  4 ++
>   arch/arm/include/asm/arch-sunxi/clock_sun4i.h | 11 ++--
>   board/sunxi/Makefile                          |  1 +
>   board/sunxi/ahci.c                            | 84 +++++++++++++++++++++++++++
>   boards.cfg                                    | 10 ++--
>   drivers/block/ahci.c                          | 16 +++++
>   include/ahci.h                                |  4 ++
>   include/configs/sunxi-common.h                | 12 ++++
>   8 files changed, 133 insertions(+), 9 deletions(-)
>   create mode 100644 board/sunxi/ahci.c
>
> diff --git a/arch/arm/cpu/armv7/sunxi/clock_sun4i.c b/arch/arm/cpu/armv7/sunxi/clock_sun4i.c
> index b8b16cf..ecbdb01 100644
> --- a/arch/arm/cpu/armv7/sunxi/clock_sun4i.c
> +++ b/arch/arm/cpu/armv7/sunxi/clock_sun4i.c
> @@ -39,6 +39,10 @@ void clock_init_safe(void)
>   	setbits_le32(&ccm->ahb_gate0, 0x1 << AHB_GATE_OFFSET_DMA);
>   #endif
>   	writel(PLL6_CFG_DEFAULT, &ccm->pll6_cfg);
> +#ifdef CONFIG_SUNXI_AHCI
> +	setbits_le32(&ccm->ahb_gate0, 0x1 << AHB_GATE_OFFSET_SATA);
> +	setbits_le32(&ccm->pll6_cfg, 0x1 << CCM_PLL6_CTRL_SATA_EN_SHIFT);
> +#endif
>   }
>   #endif
>
> diff --git a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
> index 928f3f2..2531cbd 100644
> --- a/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
> +++ b/arch/arm/include/asm/arch-sunxi/clock_sun4i.h
> @@ -218,10 +218,13 @@ struct sunxi_ccm_reg {
>   #define CCM_PLL5_CTRL_BYPASS (0x1 << 30)
>   #define CCM_PLL5_CTRL_EN (0x1 << 31)
>
> -#define CCM_PLL6_CTRL_N_SHIFT	8
> -#define CCM_PLL6_CTRL_N_MASK	(0x1f << CCM_PLL6_CTRL_N_SHIFT)
> -#define CCM_PLL6_CTRL_K_SHIFT	4
> -#define CCM_PLL6_CTRL_K_MASK	(0x3 << CCM_PLL6_CTRL_K_SHIFT)
> +#define CCM_PLL6_CTRL_EN		31
> +#define CCM_PLL6_CTRL_BYPASS_EN		30
> +#define CCM_PLL6_CTRL_SATA_EN_SHIFT	14
> +#define CCM_PLL6_CTRL_N_SHIFT		8
> +#define CCM_PLL6_CTRL_N_MASK		(0x1f << CCM_PLL6_CTRL_N_SHIFT)
> +#define CCM_PLL6_CTRL_K_SHIFT		4
> +#define CCM_PLL6_CTRL_K_MASK		(0x3 << CCM_PLL6_CTRL_K_SHIFT)
>
>   #define CCM_GPS_CTRL_RESET (0x1 << 0)
>   #define CCM_GPS_CTRL_GATE (0x1 << 1)
> diff --git a/board/sunxi/Makefile b/board/sunxi/Makefile
> index 62acb8f..03f55cc 100644
> --- a/board/sunxi/Makefile
> +++ b/board/sunxi/Makefile
> @@ -10,6 +10,7 @@
>   #
>   obj-y	+= board.o
>   obj-$(CONFIG_SUNXI_GMAC)	+= gmac.o
> +obj-$(CONFIG_SUNXI_AHCI)	+= ahci.o
>   obj-$(CONFIG_A13_OLINUXINOM)	+= dram_a13_oli_micro.o
>   obj-$(CONFIG_CUBIEBOARD)	+= dram_cubieboard.o
>   obj-$(CONFIG_CUBIEBOARD2)	+= dram_cubieboard2.o
> diff --git a/board/sunxi/ahci.c b/board/sunxi/ahci.c
> new file mode 100644
> index 0000000..0c262ea
> --- /dev/null
> +++ b/board/sunxi/ahci.c
> @@ -0,0 +1,84 @@
> +#include <common.h>
> +#include <ahci.h>
> +#include <scsi.h>
> +#include <errno.h>
> +#include <asm/io.h>
> +#include <asm/gpio.h>
> +
> +#define AHCI_PHYCS0R 0x00c0
> +#define AHCI_PHYCS1R 0x00c4
> +#define AHCI_PHYCS2R 0x00c8
> +#define AHCI_RWCR    0x00fc
> +
> +/* This magic PHY initialisation was taken from the Allwinner releases
> + * and Linux driver, but is completely undocumented.
> + */
> +static int sunxi_ahci_phy_init(u32 base)
> +{
> +	u8 *reg_base = (u8 *)base;
> +	u32 reg_val;
> +	int timeout;
> +
> +	writel(0, reg_base + AHCI_RWCR);
> +	mdelay(5);
> +
> +	setbits_le32(reg_base + AHCI_PHYCS1R, 0x1 << 19);
> +	clrsetbits_le32(reg_base + AHCI_PHYCS0R,
> +			(0x7 << 24),
> +			(0x5 << 24) | (0x1 << 23) | (0x1 << 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, (0x1 << 28) | (0x1 << 15));
> +	clrbits_le32(reg_base + AHCI_PHYCS1R, (0x1 << 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 = 250; /* Power up takes approx 50 us */
> +	for (;;) {
> +		reg_val = readl(reg_base + AHCI_PHYCS0R) & (0x7 << 28);
> +		if (reg_val == (0x2 << 28))
> +			break;
> +		if (--timeout == 0) {
> +			printf("AHCI PHY power up failed.\n");
> +			return -EIO;
> +		}
> +		udelay(1);
> +	};
> +
> +	setbits_le32(reg_base + AHCI_PHYCS2R, (0x1 << 24));
> +
> +	timeout = 100; /* Calibration takes approx 10 us */
> +	for (;;) {
> +		reg_val = readl(reg_base + AHCI_PHYCS2R) & (0x1 << 24);
> +		if (reg_val == 0x0)
> +			break;
> +		if (--timeout == 0) {
> +			printf("AHCI PHY calibration failed.\n");
> +			return -EIO;
> +		}
> +		udelay(1);
> +	}
> +
> +	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
> +
> +	if (sunxi_ahci_phy_init(SUNXI_SATA_BASE) < 0)
> +		return;
> +
> +	ahci_init(SUNXI_SATA_BASE);
> +}
> diff --git a/boards.cfg b/boards.cfg
> index 035b5c7..f69bd32 100644
> --- a/boards.cfg
> +++ b/boards.cfg
> @@ -378,11 +378,11 @@ Active  arm         armv7          s5pc1xx     samsung         goni
>   Active  arm         armv7          s5pc1xx     samsung         smdkc100            smdkc100                              -                                                                                                                                 Minkyu Kang <mk7.kang at samsung.com>
>   Active  arm         armv7          socfpga     altera          socfpga             socfpga_cyclone5                      -                                                                                                                                 -
>   Active  arm         armv7          sunxi       -               sunxi               A13-OLinuXinoM                        sun5i:A13_OLINUXINOM,SPL,CONS_INDEX=2                                                                                             Hans de Goede <hdegoede at redhat.com>
> -Active  arm         armv7          sunxi       -               sunxi               Cubieboard                            sun4i:CUBIEBOARD,SPL,AXP209_POWER,SUNXI_EMAC                                                                                      Hans de Goede <hdegoede at redhat.com>
> -Active  arm         armv7          sunxi       -               sunxi               Cubieboard2                           sun7i:CUBIEBOARD2,SPL,SUNXI_GMAC                                                                                                  Ian Campbell <ijc at hellion.org.uk>:Hans de Goede <hdegoede at redhat.com>
> -Active  arm         armv7          sunxi       -               sunxi               Cubieboard2_FEL                       sun7i:CUBIEBOARD2,SPL_FEL,SUNXI_GMAC                                                                                              Ian Campbell <ijc at hellion.org.uk>:Hans de Goede <hdegoede at redhat.com>
> -Active  arm         armv7          sunxi       -               sunxi               Cubietruck                            sun7i:CUBIETRUCK,SPL,AXP209_POWER,SUNXI_GMAC,RGMII                                                                                Ian Campbell <ijc at hellion.org.uk>:Hans de Goede <hdegoede at redhat.com>
> -Active  arm         armv7          sunxi       -               sunxi               Cubietruck_FEL                        sun7i:CUBIETRUCK,SPL_FEL,AXP209_POWER,SUNXI_GMAC,RGMII                                                                            Ian Campbell <ijc at hellion.org.uk>:Hans de Goede <hdegoede at redhat.com>
> +Active  arm         armv7          sunxi       -               sunxi               Cubieboard                            sun4i:CUBIEBOARD,SPL,AXP209_POWER,SUNXI_EMAC,AHCI,SATAPWR=SUNXI_GPB(8)                                                            Hans de Goede <hdegoede at redhat.com>
> +Active  arm         armv7          sunxi       -               sunxi               Cubieboard2                           sun7i:CUBIEBOARD2,SPL,SUNXI_GMAC,AHCI,SATAPWR=SUNXI_GPB(8)                                                                        Ian Campbell <ijc at hellion.org.uk>:Hans de Goede <hdegoede at redhat.com>
> +Active  arm         armv7          sunxi       -               sunxi               Cubieboard2_FEL                       sun7i:CUBIEBOARD2,SPL_FEL,SUNXI_GMAC,AHCI,SATAPWR=SUNXI_GPB(8)                                                                    Ian Campbell <ijc at hellion.org.uk>:Hans de Goede <hdegoede at redhat.com>
> +Active  arm         armv7          sunxi       -               sunxi               Cubietruck                            sun7i:CUBIETRUCK,SPL,AXP209_POWER,SUNXI_GMAC,RGMII,AHCI,SATAPWR=SUNXI_GPH(12)                                                     Ian Campbell <ijc at hellion.org.uk>:Hans de Goede <hdegoede at redhat.com>
> +Active  arm         armv7          sunxi       -               sunxi               Cubietruck_FEL                        sun7i:CUBIETRUCK,SPL_FEL,AXP209_POWER,SUNXI_GMAC,RGMII,AHCI,SATAPWR=SUNXI_GPH(12)                                                 Ian Campbell <ijc at hellion.org.uk>:Hans de Goede <hdegoede at redhat.com>
>   Active  arm         armv7          sunxi       -               sunxi               r7-tv-dongle                          sun5i:R7DONGLE,SPL,AXP152_POWER                                                                                                   Hans de Goede <hdegoede at redhat.com>
>   Active  arm         armv7          u8500       st-ericsson     snowball            snowball                              -                                                                                                                                 Mathieu Poirier <mathieu.poirier at linaro.org>
>   Active  arm         armv7          u8500       st-ericsson     u8500               u8500_href                            -                                                                                                                                 -
> diff --git a/drivers/block/ahci.c b/drivers/block/ahci.c
> index 4df8046..dce99ad 100644
> --- a/drivers/block/ahci.c
> +++ b/drivers/block/ahci.c
> @@ -129,6 +129,14 @@ int __weak ahci_link_up(struct ahci_probe_ent *probe_ent, u8 port)
>   	return 1;
>   }
>
> +#ifdef CONFIG_SUNXI_AHCI
> +/* The sunxi AHCI controller requires this undocumented setup */
> +static void sunxi_dma_init(volatile u8 *port_mmio)
> +{
> +	clrsetbits_le32(port_mmio + PORT_P0DMACR, 0x0000ff00, 0x00004400);
> +}
> +#endif
> +
>   static int ahci_host_init(struct ahci_probe_ent *probe_ent)
>   {
>   #ifndef CONFIG_SCSI_AHCI_PLAT
> @@ -213,6 +221,10 @@ static int ahci_host_init(struct ahci_probe_ent *probe_ent)
>   			msleep(500);
>   		}
>
> +#ifdef CONFIG_SUNXI_AHCI
> +		sunxi_dma_init(port_mmio);
> +#endif
> +
>   		/* Add the spinup command to whatever mode bits may
>   		 * already be on in the command register.
>   		 */
> @@ -545,6 +557,10 @@ static int ahci_port_start(u8 port)
>
>   	writel_with_flush(pp->rx_fis, port_mmio + PORT_FIS_ADDR);
>
> +#ifdef CONFIG_SUNXI_AHCI
> +	sunxi_dma_init(port_mmio);
> +#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/include/ahci.h b/include/ahci.h
> index 90e8509..35b8a8c 100644
> --- a/include/ahci.h
> +++ b/include/ahci.h
> @@ -58,6 +58,10 @@
>   #define PORT_SCR_ERR		0x30 /* SATA phy register: SError */
>   #define PORT_SCR_ACT		0x34 /* SATA phy register: SActive */
>
> +#ifdef CONFIG_SUNXI_AHCI
> +#define PORT_P0DMACR		0x70 /* SUNXI specific "DMA register" */
> +#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 845b004..43eb718 100644
> --- a/include/configs/sunxi-common.h
> +++ b/include/configs/sunxi-common.h
> @@ -57,6 +57,18 @@
>   #define PHYS_SDRAM_0			CONFIG_SYS_SDRAM_BASE
>   #define PHYS_SDRAM_0_SIZE		0x80000000 /* 2 GiB */
>
> +#ifdef CONFIG_AHCI
> +#define CONFIG_LIBATA
> +#define CONFIG_SCSI_AHCI
> +#define CONFIG_SCSI_AHCI_PLAT
> +#define CONFIG_SUNXI_AHCI
> +#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
>
>


More information about the U-Boot mailing list