[U-Boot] [PATCH v2] exynos5250/arndale: Enable SATA/AHCI support.

Simon Glass sjg at chromium.org
Mon Dec 8 23:24:07 CET 2014


Hi Ian,

On 8 December 2014 at 07:54, Ian Campbell <ian.campbell at citrix.com> wrote:
> This is based on some old patches from the chromeos-v2011.12 branch of
> http://git.chromium.org/chromiumos/third_party/u-boot.git by Taylor Hutt.
> Specifically:
>
> http://git.chromium.org/gitweb/?p=chromiumos/third_party/u-boot.git;a=commit;h=26f6c570b5deb37c52306920ae049203c68f014a
>     exynos: sata: on-board controller initialization
>     Signed-off-by: Taylor Hutt <thutt at chromium.org>
>
> http://git.chromium.org/gitweb/?p=chromiumos/third_party/u-boot.git;a=commit;h=d8cac5cf0b63df00d2d6ac7df814613e4b60b9d1
>     exynos: sata: Add sata_initialize() interface
>     Signed-off-by: Taylor Hutt <thutt at chromium.org>
>
> http://git.chromium.org/gitweb/?p=chromiumos/third_party/u-boot.git;a=commit;h=dd32462453d6328bc5770859d1b56501f7920d7d
>     exynos: sata: SATA self-configuration for when SATA device is enabled
>     Signed-off-by: Taylor Hutt <thutt at chromium.org>

Thanks for cleaning this up and submitting it.

>
> As well as rebasing there have been some significant changes.
>
>  - Drop support for smdk5250, which I don't own.
>  - Implement support for arndale, which I do.
>  - Since arndale has no need to frob a GPIO on SATA init drop the associated
>    code.
>  - Initialise via the existing scsi_init hook rather than introducing
>    sata_initialize, associated build system and include/configs/*.h changes.
>  - Use set/clrbits in a bunch of places
>  - Add some #defines for some magic numbers.
>  - Use samsung_get_base_* for peripheral base addresses and structs to
>    access individual registers
>  - Lots of coding style improvements (checkpatch.pl clean) and general cleanup
>
> Before launching the OS reset the PHY, otherwise Linux cannot reliably
> detect the disk.
>
> Signed-off-by: Ian Campbell <ian.campbell at citrix.com>
> Cc: Taylor Hutt <thutt at chromium.org>
> Cc: Simon Glass <sjg at chromium.org>
> ---
> Lots of changes in v2:
> - Rebase to latest master branch.
> - use samsung_get_base_* for sata phy
> - use samsung_get_base_* for sata i2c
> - use samsung_get_base_* for sata axi
> - Lots of Coding Style improvements
> - Drop unused mmio argument to phy init
> - Move code controlling phy power to power.c
> - Remove unused SCLK_SATA_FREQ
> - Use #defines for SATA_GENERATION<N>, less fickle than enum
> - avoid non-existent BIT macro
> - Use bool more consistently in a few places
> - No uppercase variable names
> - Use SPDX License + copyright
> - Use arch_preboot_os to reset SATA controller, and do so more
>   thoroughly than in the previous HACK. It now appears to be reliable
>   in my testing.
> ---
>  arch/arm/cpu/armv7/exynos/Makefile       |   4 +
>  arch/arm/cpu/armv7/exynos/power.c        |  23 ++
>  arch/arm/cpu/armv7/exynos/sata.c         | 412 +++++++++++++++++++++++++++++++
>  arch/arm/cpu/armv7/exynos/soc.c          |   8 +
>  arch/arm/include/asm/arch-exynos/cpu.h   |  15 ++
>  arch/arm/include/asm/arch-exynos/power.h |   4 +
>  arch/arm/include/asm/arch-exynos/sata.h  |  13 +
>  arch/arm/lib/board.c                     |   1 +
>  board/samsung/arndale/arndale.c          |   9 +
>  include/configs/arndale.h                |   3 +
>  include/configs/exynos5-common.h         |  18 ++
>  11 files changed, 510 insertions(+)
>  create mode 100644 arch/arm/cpu/armv7/exynos/sata.c
>  create mode 100644 arch/arm/include/asm/arch-exynos/sata.h
>
> diff --git a/arch/arm/cpu/armv7/exynos/Makefile b/arch/arm/cpu/armv7/exynos/Makefile
> index e207bd6..c74a2d4 100644
> --- a/arch/arm/cpu/armv7/exynos/Makefile
> +++ b/arch/arm/cpu/armv7/exynos/Makefile
> @@ -7,6 +7,10 @@
>
>  obj-y  += clock.o power.o soc.o system.o pinmux.o tzpc.o
>
> +ifndef CONFIG_SPL_BUILD
> +obj-$(CONFIG_EXYNOS5250_AHCI) += sata.o
> +endif
> +
>  ifdef CONFIG_SPL_BUILD
>  obj-$(CONFIG_EXYNOS5)  += clock_init_exynos5.o
>  obj-$(CONFIG_EXYNOS5)  += dmc_common.o dmc_init_ddr3.o
> diff --git a/arch/arm/cpu/armv7/exynos/power.c b/arch/arm/cpu/armv7/exynos/power.c
> index 1520d64..8f36d10 100644
> --- a/arch/arm/cpu/armv7/exynos/power.c
> +++ b/arch/arm/cpu/armv7/exynos/power.c
> @@ -37,6 +37,29 @@ void set_mipi_phy_ctrl(unsigned int dev_index, unsigned int enable)
>                 exynos4_mipi_phy_control(dev_index, enable);
>  }
>
> +void exynos5_set_sata_phy_ctrl(unsigned int enable)
> +{
> +       struct exynos5_power *power =
> +               (struct exynos5_power *)samsung_get_base_power();
> +
> +       if (enable) {
> +               /* Enabling SATA_PHY */
> +               setbits_le32(&power->sata_phy_control,
> +                            POWER_USB_HOST_PHY_CTRL_EN);
> +       } else {
> +               /* Disabling SATA_PHY */
> +               clrbits_le32(&power->sata_phy_control,
> +                            POWER_USB_HOST_PHY_CTRL_EN);
> +       }
> +}
> +
> +void set_sata_phy_ctrl(unsigned int enable)
> +{
> +       if (cpu_is_exynos5())
> +               exynos5_set_sata_phy_ctrl(enable);
> +}
> +
> +
>  void exynos5_set_usbhost_phy_ctrl(unsigned int enable)
>  {
>         struct exynos5_power *power =
> diff --git a/arch/arm/cpu/armv7/exynos/sata.c b/arch/arm/cpu/armv7/exynos/sata.c
> new file mode 100644
> index 0000000..4e994d6
> --- /dev/null
> +++ b/arch/arm/cpu/armv7/exynos/sata.c
> @@ -0,0 +1,412 @@
> +/*
> + * Copyright (c) 2012 The Chromium OS Authors.
> + * Copyright (c) 2014 Ian Campbell
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +#include <asm/types.h>
> +#include <ahci.h>
> +#include <common.h>
> +#include <fdtdec.h>
> +#include <scsi.h>
> +#include <asm/arch/sata.h>
> +#include <asm/arch/pinmux.h>
> +#include <asm/arch/clock.h>
> +#include <asm/arch/clk.h>
> +#include <asm/arch/power.h>
> +#include <asm/errno.h>
> +#include <asm/gpio.h>
> +#include <linux/compiler.h>
> +
> +#define SATA_TIME_LIMIT                        10000
> +#define SATA_PHY_I2C_SLAVE_ADDRS       0x70
> +
> +/********************** PHY **************/
> +
> +struct sata_phy {
> +       unsigned int    res1;           /* 0x00 */
> +       unsigned int    reset;          /* 0x04 */
> +#define RESET_GLOBAL_RST_N              (1 << 0)
> +#define RESET_CMN_RST_N                        (1 << 1)
> +#define RESET_CMN_BLOCK_RST_N           (1 << 2)
> +#define RESET_CMN_I2C_RST_N             (1 << 3)
> +#define RESET_TX_RX_PIPE_RST_N          (1 << 4)
> +#define RESET_TX_RX_BLOCK_RST_N         (1 << 5)
> +#define RESET_TX_RX_I2C_RST_N           ((1 << 6) | (1 << 7))
> +#define LINK_RESET                     0xF0000
> +       unsigned int    res2;           /* 0x08 */
> +       unsigned int    res3;           /* 0x0c */
> +       unsigned int    mode0;          /* 0x10 */
> +       unsigned int    ctrl0;          /* 0x14 */
> +#define CTRL0_P0_PHY_CALIBRATED_SEL    (1 << 9)
> +#define CTRL0_P0_PHY_CALIBRATED                (1 << 8)
> +       unsigned int    res4[0x32];     /* 0x18..0xdc */
> +       unsigned int    ctrlm;          /* 0xE0 */
> +#define PHCTRLM_REF_RATE               (1 << 1)
> +#define PHCTRLM_HIGH_SPEED             (1 << 0)
> +       unsigned int    res5[0x03];     /* 0xE4..0xEF*/
> +       unsigned int    statm;          /* 0xF0 */
> +#define PHSTATM_PLL_LOCKED             (1 << 0)
> +};
> +
> +/********************** I2C **************/
> +
> +struct sata_i2c {
> +       unsigned int    con;            /* 0x00 */
> +       unsigned int    stat;           /* 0x04 */
> +       unsigned int    addr;           /* 0x08 */
> +       unsigned int    ds;             /* 0x0c */
> +       unsigned int    lc;             /* 0x10 */
> +};

Can this be structured as an I2C device using driver model? It doesn't
make sense to add new I2C drivers outside driver model.

> +
> +/* I2CCON reg */
> +#define CON_ACKEN                      (1 << 7)
> +#define CON_CLK512                     (1 << 6)
> +#define CON_CLK16                      (~CON_CLK512)
> +#define CON_INTEN                      (1 << 5)
> +#define CON_INTPND                     (1 << 4)
> +#define CON_TXCLK_PS                   (0xF)
> +
> +/* I2CSTAT reg */
> +#define STAT_MSTT                      (0x3 << 6)
> +#define STAT_BSYST                     (1 << 5)
> +#define STAT_RTEN                      (1 << 4)
> +#define STAT_LAST                      (1 << 0)
> +
> +#define LC_FLTR_EN                     (1 << 2)
> +
> +#define SATA_PHY_CON_RESET             0xF003F
> +
> +#define SATA_GENERATION1               (0)
> +#define        SATA_GENERATION2                (1 << 0)
> +#define SATA_GENERATION3               (1 << 1)
> +
> +static bool sata_is_reg(void __iomem *reg, u32 checkbit, u32 status)
> +{
> +       if ((__raw_readl(reg) & checkbit) == status)
> +               return true;
> +       else
> +               return false;
> +}
> +
> +static bool wait_for_reg_status(void __iomem *reg, u32 checkbit, u32 status)
> +{
> +       u32 time_limit_cnt = 0;
> +
> +       while (!sata_is_reg(reg, checkbit, status)) {
> +               if (time_limit_cnt == SATA_TIME_LIMIT)
> +                       return false;
> +               udelay(1000);
> +               time_limit_cnt++;
> +       }
> +       return true;
> +}
> +
> +static void sata_set_gen(u8 gen)
> +{
> +       struct sata_phy *phy =
> +               (struct sata_phy *)samsung_get_base_sata_phy();

Should pass the base address into these functions.

Also it can come from the device tree now.

> +
> +       clrsetbits_le32(&phy->mode0, 0x3, gen);
> +}
> +
> +/* Address :I2C Address */
> +static void sata_i2c_write_addrs(u8 data)
> +{
> +       struct sata_i2c *i2c =
> +               (struct sata_i2c *)samsung_get_base_sata_i2c();
> +
> +       __raw_writeb((data & 0xFE), &i2c->ds);
> +}
> +
> +static void sata_i2c_write_data(u8 data)
> +{
> +       struct sata_i2c *i2c =
> +               (struct sata_i2c *)samsung_get_base_sata_i2c();
> +
> +       __raw_writeb((data), &i2c->ds);
> +}
> +
> +static void sata_i2c_start(void)
> +{
> +       struct sata_i2c *i2c =
> +               (struct sata_i2c *)samsung_get_base_sata_i2c();
> +
> +       setbits_le32(&i2c->stat, STAT_BSYST);
> +}
> +
> +static void sata_i2c_stop(void)
> +{
> +       struct sata_i2c *i2c =
> +               (struct sata_i2c *)samsung_get_base_sata_i2c();
> +
> +       clrbits_le32(&i2c->stat, STAT_BSYST);
> +}
> +
> +static bool sata_i2c_get_int_status(void)
> +{
> +       struct sata_i2c *i2c =
> +               (struct sata_i2c *)samsung_get_base_sata_i2c();
> +
> +       if ((__raw_readl(&i2c->con)) & CON_INTPND)
> +               return true;
> +       else
> +               return false;
> +}
> +
> +static bool sata_i2c_is_tx_ack(void)
> +{
> +       struct sata_i2c *i2c =
> +               (struct sata_i2c *)samsung_get_base_sata_i2c();
> +
> +       if ((__raw_readl(&i2c->con)) & STAT_LAST)
> +               return false;
> +       else
> +               return true;
> +}
> +
> +static bool sata_i2c_is_bus_ready(void)
> +{
> +       struct sata_i2c *i2c =
> +               (struct sata_i2c *)samsung_get_base_sata_i2c();
> +
> +       if ((__raw_readl(&i2c->stat)) & STAT_BSYST)
> +               return false;
> +       else
> +               return true;
> +}
> +
> +static bool sata_i2c_wait_for_busready(u32 time_out)
> +{
> +       while (--time_out) {
> +               if (sata_i2c_is_bus_ready())
> +                       return true;
> +               udelay(100);
> +       }
> +       return false;
> +}
> +
> +static bool sata_i2c_wait_for_tx_ack(u32 time_out)
> +{
> +       while (--time_out) {
> +               if (sata_i2c_get_int_status()) {
> +                       if (sata_i2c_is_tx_ack())
> +                               return true;
> +               }
> +               udelay(100);
> +       }
> +       return false;
> +}
> +
> +static void sata_i2c_clear_int_status(void)
> +{
> +       struct sata_i2c *i2c =
> +               (struct sata_i2c *)samsung_get_base_sata_i2c();
> +
> +       clrbits_le32(&i2c->con, CON_INTPND);
> +}
> +
> +static void sata_i2c_set_ack_gen(bool enable)
> +{
> +       struct sata_i2c *i2c =
> +               (struct sata_i2c *)samsung_get_base_sata_i2c();
> +
> +       if (enable)
> +               setbits_le32(&i2c->con, CON_ACKEN);
> +       else
> +               clrbits_le32(&i2c->con, CON_ACKEN);
> +}
> +
> +static void sata_i2c_set_master_tx(void)
> +{
> +       struct sata_i2c *i2c =
> +               (struct sata_i2c *)samsung_get_base_sata_i2c();
> +
> +       /* Disable I2C */
> +       clrbits_le32(&i2c->stat, STAT_RTEN);
> +
> +       /* Clear Mode */
> +       clrbits_le32(&i2c->stat, STAT_MSTT);
> +
> +       sata_i2c_clear_int_status();
> +
> +       /* interrupt disable */
> +       clrbits_le32(&i2c->con, CON_INTEN);
> +
> +       /* Master, Send mode */
> +       setbits_le32(&i2c->stat, STAT_MSTT);
> +
> +       /* interrupt enable */
> +       setbits_le32(&i2c->con, CON_INTEN);
> +
> +       /* Enable I2C */
> +       setbits_le32(&i2c->stat, STAT_RTEN);
> +}
> +
> +static void sata_i2c_init(void)
> +{
> +       struct sata_i2c *i2c =
> +               (struct sata_i2c *)samsung_get_base_sata_i2c();
> +
> +       clrbits_le32(&i2c->con, ~CON_CLK16);
> +       clrbits_le32(&i2c->con, CON_TXCLK_PS);
> +       setbits_le32(&i2c->con, 2 & CON_TXCLK_PS);
> +       clrbits_le32(&i2c->lc, LC_FLTR_EN);
> +
> +       sata_i2c_set_ack_gen(false);
> +}
> +
> +static bool sata_i2c_send(u8 slave_addrs, u8 addrs, u8 data)

Probably better to return an error code here rather than try/false. See errno.h.

> +{
> +       struct sata_phy *phy =
> +               (struct sata_phy *)samsung_get_base_sata_phy();
> +       bool ret = false;
> +
> +       if (!sata_i2c_wait_for_busready(SATA_TIME_LIMIT))
> +               return false;
> +
> +       sata_i2c_init();
> +       sata_i2c_set_master_tx();
> +
> +       __raw_writel(SATA_PHY_CON_RESET, &phy->reset);
> +       sata_i2c_write_addrs(slave_addrs);
> +       sata_i2c_start();
> +
> +       if (!sata_i2c_wait_for_tx_ack(SATA_TIME_LIMIT))
> +               goto stop;
> +
> +       sata_i2c_write_data(addrs);
> +       sata_i2c_clear_int_status();
> +
> +       if (!sata_i2c_wait_for_tx_ack(SATA_TIME_LIMIT))
> +               goto stop;
> +
> +       sata_i2c_write_data(data);
> +       sata_i2c_clear_int_status();
> +
> +       if (!sata_i2c_wait_for_tx_ack(SATA_TIME_LIMIT))
> +               goto stop;
> +
> +       ret = true;
> +
> +stop:
> +       sata_i2c_stop();
> +       sata_i2c_clear_int_status();
> +       sata_i2c_wait_for_busready(SATA_TIME_LIMIT);

Error check here?
> +
> +       return ret;
> +}
> +
> +static bool ahci_phy_init(void)
> +{
> +       return sata_i2c_send(SATA_PHY_I2C_SLAVE_ADDRS, 0x3a, 0x0b);
> +}
> +
> +static int exynos5_ahci_init(void)
> +{
> +       struct sata_phy *phy =
> +               (struct sata_phy *)samsung_get_base_sata_phy();
> +       int ret;
> +
> +       if (sata_is_reg(&phy->ctrl0,
> +                       CTRL0_P0_PHY_CALIBRATED, CTRL0_P0_PHY_CALIBRATED)) {
> +               printf("%s: already calibrated?\n", __func__);
> +       }
> +
> +       /* Clear phy control enable. Seems to be necessary to
> +        * reinitialise on a warm reboot, at least sometimes. */
> +       set_sata_phy_ctrl(0);
> +       udelay(1000);
> +
> +       set_sata_phy_ctrl(1);
> +
> +       __raw_writel(0, &phy->reset);
> +       setbits_le32(&phy->reset,
> +                    RESET_GLOBAL_RST_N|
> +                    RESET_CMN_BLOCK_RST_N|RESET_CMN_I2C_RST_N|
> +                    RESET_TX_RX_PIPE_RST_N|RESET_TX_RX_BLOCK_RST_N);
> +
> +       setbits_le32(&phy->reset, LINK_RESET);
> +
> +       setbits_le32(&phy->reset, RESET_CMN_RST_N);
> +
> +       clrbits_le32(&phy->ctrlm, PHCTRLM_REF_RATE);
> +
> +       /* High speed enable for Gen3 */
> +       setbits_le32(&phy->ctrlm, PHCTRLM_HIGH_SPEED);
> +
> +       setbits_le32(&phy->ctrl0,
> +                    CTRL0_P0_PHY_CALIBRATED_SEL|CTRL0_P0_PHY_CALIBRATED);
> +
> +       sata_set_gen(SATA_GENERATION3);
> +
> +       ret = ahci_phy_init();

Return if there is an error?

> +
> +       /* release cmu reset */
> +       clrbits_le32(&phy->reset, RESET_CMN_RST_N);
> +
> +       setbits_le32(&phy->reset, RESET_CMN_RST_N);
> +
> +       if (wait_for_reg_status(&phy->statm,
> +                               PHSTATM_PLL_LOCKED, 1))
> +               return ret;
> +
> +       return 0;
> +}
> +
> +static void exynos5_enable_clock_gates(void)
> +{
> +       struct exynos5_clock *clk =
> +               (struct exynos5_clock *)samsung_get_base_clock();
> +
> +       /* Turn on all SATA clock gates & DMA gates.  */
> +       const unsigned sata_clocks      = (1 << 25) | (1 << 24) | (1 << 6);
> +       const unsigned dma_clocks       = (2 << 1) | (1 << 1);
> +
> +       setbits_le32(&clk->gate_ip_fsys, sata_clocks|dma_clocks);
> +}
> +
> +int exynos5_sata_init(void)
> +{
> +       BUILD_BUG_ON(offsetof(struct sata_phy, reset) != 0x04);
> +       BUILD_BUG_ON(offsetof(struct sata_phy, mode0) != 0x10);
> +       BUILD_BUG_ON(offsetof(struct sata_phy, ctrl0) != 0x14);
> +       BUILD_BUG_ON(offsetof(struct sata_phy, ctrlm) != 0xe0);
> +       BUILD_BUG_ON(offsetof(struct sata_phy, statm) != 0xf0);
> +
> +       BUILD_BUG_ON(offsetof(struct sata_i2c, con) != 0x00);
> +       BUILD_BUG_ON(offsetof(struct sata_i2c, stat) != 0x04);
> +       BUILD_BUG_ON(offsetof(struct sata_i2c, addr) != 0x08);
> +       BUILD_BUG_ON(offsetof(struct sata_i2c, ds) != 0x0c);
> +       BUILD_BUG_ON(offsetof(struct sata_i2c, lc) != 0x10);
> +
> +       exynos5_enable_clock_gates();
> +
> +       if (exynos5_ahci_init()) {

Non-zero return from this function should mean error.

> +               ahci_init(samsung_get_base_sata_axi());
> +               return 0;
> +       }
> +       return -ENODEV;
> +}
> +
> +int exynos5_sata_deinit(void)
> +{
> +       struct sata_phy *phy =
> +               (struct sata_phy *)samsung_get_base_sata_phy();
> +
> +       sata_set_gen(SATA_GENERATION1);
> +
> +       clrbits_le32(&phy->ctrl0,
> +                    CTRL0_P0_PHY_CALIBRATED_SEL|CTRL0_P0_PHY_CALIBRATED);
> +
> +       /* Disable High speed enable for Gen3 */
> +       clrbits_le32(&phy->ctrlm, PHCTRLM_HIGH_SPEED);
> +
> +       setbits_le32(&phy->ctrlm, PHCTRLM_REF_RATE);
> +
> +       __raw_writel(0, &phy->reset);
> +
> +       set_sata_phy_ctrl(0);
> +
> +       return 0;
> +}
> diff --git a/arch/arm/cpu/armv7/exynos/soc.c b/arch/arm/cpu/armv7/exynos/soc.c
> index 8c7d7d8..1cd8b7b 100644
> --- a/arch/arm/cpu/armv7/exynos/soc.c
> +++ b/arch/arm/cpu/armv7/exynos/soc.c
> @@ -8,6 +8,7 @@
>  #include <common.h>
>  #include <asm/io.h>
>  #include <asm/system.h>
> +#include <asm/arch/sata.h>
>
>  enum l2_cache_params {
>         CACHE_TAG_RAM_SETUP = (1 << 9),
> @@ -29,6 +30,13 @@ void enable_caches(void)
>  }
>  #endif
>
> +void arch_preboot_os(void)
> +{
> +#if defined(CONFIG_SCSI_AHCI)
> +       exynos5_sata_deinit();
> +#endif
> +}
> +
>  #ifndef CONFIG_SYS_L2CACHE_OFF
>  /*
>   * Set L2 cache parameters
> diff --git a/arch/arm/include/asm/arch-exynos/cpu.h b/arch/arm/include/asm/arch-exynos/cpu.h
> index 29674ad..7d53995 100644
> --- a/arch/arm/include/asm/arch-exynos/cpu.h
> +++ b/arch/arm/include/asm/arch-exynos/cpu.h
> @@ -56,6 +56,9 @@
>  #define EXYNOS4_USB_HOST_XHCI_BASE     DEVICE_NOT_AVAILABLE
>  #define EXYNOS4_USB3PHY_BASE           DEVICE_NOT_AVAILABLE
>  #define EXYNOS4_DMC_TZASC_BASE         DEVICE_NOT_AVAILABLE
> +#define EXYNOS4_SATA_PHY_BASE          DEVICE_NOT_AVAILABLE
> +#define EXYNOS4_SATA_I2C_BASE          DEVICE_NOT_AVAILABLE
> +#define EXYNOS4_SATA_AXI_BASE          DEVICE_NOT_AVAILABLE

Please we don't need these constants anymore.

>
>  /* EXYNOS4X12 */
>  #define EXYNOS4X12_GPIO_PART3_BASE     0x03860000
> @@ -102,6 +105,9 @@
>  #define EXYNOS4X12_USB_HOST_XHCI_BASE  DEVICE_NOT_AVAILABLE
>  #define EXYNOS4X12_USB3PHY_BASE                DEVICE_NOT_AVAILABLE
>  #define EXYNOS4X12_DMC_TZASC_BASE      DEVICE_NOT_AVAILABLE
> +#define EXYNOS4X12_SATA_PHY_BASE       DEVICE_NOT_AVAILABLE
> +#define EXYNOS4X12_SATA_I2C_BASE       DEVICE_NOT_AVAILABLE
> +#define EXYNOS4X12_SATA_AXI_BASE       DEVICE_NOT_AVAILABLE
>
>  /* EXYNOS5 */
>  #define EXYNOS5_I2C_SPACING            0x10000
> @@ -130,8 +136,11 @@
>  #define EXYNOS5_USB_HOST_EHCI_BASE     0x12110000
>  #define EXYNOS5_USBPHY_BASE            0x12130000
>  #define EXYNOS5_USBOTG_BASE            0x12140000
> +#define EXYNOS5_SATA_PHY_BASE          0x12170000
> +#define EXYNOS5_SATA_I2C_BASE          0x121d0000
>  #define EXYNOS5_MMC_BASE               0x12200000
>  #define EXYNOS5_SROMC_BASE             0x12250000
> +#define EXYNOS5_SATA_AXI_BASE          0x122f0000
>  #define EXYNOS5_UART_BASE              0x12C00000
>  #define EXYNOS5_I2C_BASE               0x12C60000
>  #define EXYNOS5_SPI_BASE               0x12D20000
> @@ -185,6 +194,9 @@
>  #define EXYNOS5420_MODEM_BASE          DEVICE_NOT_AVAILABLE
>  #define EXYNOS5420_USB3PHY_BASE                DEVICE_NOT_AVAILABLE
>  #define EXYNOS5420_USB_HOST_XHCI_BASE  DEVICE_NOT_AVAILABLE
> +#define EXYNOS5420_SATA_PHY_BASE       DEVICE_NOT_AVAILABLE
> +#define EXYNOS5420_SATA_I2C_BASE       DEVICE_NOT_AVAILABLE
> +#define EXYNOS5420_SATA_AXI_BASE       DEVICE_NOT_AVAILABLE
>
>  #ifndef __ASSEMBLY__
>  #include <asm/io.h>
> @@ -314,6 +326,9 @@ SAMSUNG_BASE(dmc_ctrl, DMC_CTRL_BASE)
>  SAMSUNG_BASE(dmc_phy, DMC_PHY_BASE)
>  SAMSUNG_BASE(dmc_tzasc, DMC_TZASC_BASE)
>  SAMSUNG_BASE(audio_ass, AUDIOSS_BASE)
> +SAMSUNG_BASE(sata_phy, SATA_PHY_BASE)
> +SAMSUNG_BASE(sata_i2c, SATA_I2C_BASE)
> +SAMSUNG_BASE(sata_axi, SATA_AXI_BASE)
>  #endif
>
>  #endif /* _EXYNOS4_CPU_H */
> diff --git a/arch/arm/include/asm/arch-exynos/power.h b/arch/arm/include/asm/arch-exynos/power.h
> index 3f97b31..da023ea 100644
> --- a/arch/arm/include/asm/arch-exynos/power.h
> +++ b/arch/arm/include/asm/arch-exynos/power.h
> @@ -1704,6 +1704,10 @@ void set_mipi_phy_ctrl(unsigned int dev_index, unsigned int enable);
>  #define EXYNOS_MIPI_PHY_SRESETN                (1 << 1)
>  #define EXYNOS_MIPI_PHY_MRESETN                (1 << 2)
>
> +void set_sata_phy_ctrl(unsigned int enable);

Function docs?

> +
> +#define EXYNOS_SATA_PHY_CONTROL_EN     (1 << 0)
> +
>  void set_usbhost_phy_ctrl(unsigned int enable);
>
>  /* Enables hardware tripping to power off the system when TMU fails */
> diff --git a/arch/arm/include/asm/arch-exynos/sata.h b/arch/arm/include/asm/arch-exynos/sata.h
> new file mode 100644
> index 0000000..94c7736
> --- /dev/null
> +++ b/arch/arm/include/asm/arch-exynos/sata.h
> @@ -0,0 +1,13 @@
> +/*
> + * Copyright (c) 2012 The Chromium OS Authors.
> + *
> + * SPDX-License-Identifier:    GPL-2.0+
> + */
> +#ifndef __EXYNOS5_SATA_H
> +#define __EXYNOS5_SATA_H
> +
> +int exynos5_sata_init(void);
> +int exynos5_sata_deinit(void);
> +
> +#endif
> +
> diff --git a/arch/arm/lib/board.c b/arch/arm/lib/board.c
> index f606255..0de0c76 100644
> --- a/arch/arm/lib/board.c
> +++ b/arch/arm/lib/board.c
> @@ -35,6 +35,7 @@
>  #include <mmc.h>
>  #include <scsi.h>
>  #include <status_led.h>
> +#include <sata.h>
>  #include <libfdt.h>
>  #include <fdtdec.h>
>  #include <post.h>
> diff --git a/board/samsung/arndale/arndale.c b/board/samsung/arndale/arndale.c
> index 881d080..43f4058 100644
> --- a/board/samsung/arndale/arndale.c
> +++ b/board/samsung/arndale/arndale.c
> @@ -10,6 +10,7 @@
>  #include <asm/arch/pinmux.h>
>  #include <asm/arch/dwmmc.h>
>  #include <asm/arch/power.h>
> +#include <asm/arch/sata.h>
>
>  DECLARE_GLOBAL_DATA_PTR;
>
> @@ -31,6 +32,14 @@ int board_usb_init(int index, enum usb_init_type init)
>  }
>  #endif
>
> +#ifdef CONFIG_SCSI_AHCI
> +int scsi_init(void)
> +{
> +       printf("ARNDALE SCSI INIT\n");
> +       return exynos5_sata_init();

This could go in standard Samsung board.c, there does not seem to be
anything arndale-specific.

> +}
> +#endif
> +
>  int board_init(void)
>  {
>         gd->bd->bi_boot_params = (PHYS_SDRAM_1 + 0x100UL);
> diff --git a/include/configs/arndale.h b/include/configs/arndale.h
> index 81e8a7c..85e9295 100644
> --- a/include/configs/arndale.h
> +++ b/include/configs/arndale.h
> @@ -12,6 +12,9 @@
>  #define EXYNOS_FDTFILE_SETTING \
>         "fdtfile=exynos5250-arndale.dtb\0"
>
> +/* AHCI */
> +#define CONFIG_EXYNOS5250_AHCI
> +
>  #include "exynos5250-common.h"
>
>  /* SD/MMC configuration */
> diff --git a/include/configs/exynos5-common.h b/include/configs/exynos5-common.h
> index e1f5783..3000c97 100644
> --- a/include/configs/exynos5-common.h
> +++ b/include/configs/exynos5-common.h
> @@ -163,6 +163,18 @@
>  #define CONFIG_ENV_SROM_BANK           1
>  #endif /*CONFIG_CMD_NET*/
>
> +/* SATA controller driver */
> +#ifdef CONFIG_EXYNOS5250_AHCI
> +#define CONFIG_CMD_SCSI
> +#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_LIBATA
> +#define CONFIG_SCSI_AHCI
> +#define CONFIG_SCSI_AHCI_PLAT
> +#endif
> +
>  /* SHA hashing */
>  #define CONFIG_CMD_HASH
>  #define CONFIG_HASH_VERIFY
> @@ -184,10 +196,16 @@
>  #define CONFIG_FIT
>  #define CONFIG_FIT_BEST_MATCH
>
> +#ifdef CONFIG_EXYNOS5250_AHCI
> +#define BOOT_TARGET_DEVICES_SCSI(func) func(SCSI, scsi, 0)
> +#else
> +#define BOOT_TARGET_DEVICES_SCSI(func)
> +#endif
>
>  #define BOOT_TARGET_DEVICES(func) \
>         func(MMC, mmc, 1) \
>         func(MMC, mmc, 0) \
> +       BOOT_TARGET_DEVICES_SCSI(func) \

Great!

>         func(PXE, pxe, na) \
>         func(DHCP, dhcp, na)
>
> --
> 2.1.1
>

Regards,
Simon


More information about the U-Boot mailing list