uboot/drivers/ata/sata_ceva.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * (C) Copyright 2015 - 2016 Xilinx, Inc.
   4 * Michal Simek <michal.simek@xilinx.com>
   5 */
   6#include <common.h>
   7#include <dm.h>
   8#include <ahci.h>
   9#include <scsi.h>
  10#include <asm/io.h>
  11#include <linux/ioport.h>
  12
  13/* Vendor Specific Register Offsets */
  14#define AHCI_VEND_PCFG  0xA4
  15#define AHCI_VEND_PPCFG 0xA8
  16#define AHCI_VEND_PP2C  0xAC
  17#define AHCI_VEND_PP3C  0xB0
  18#define AHCI_VEND_PP4C  0xB4
  19#define AHCI_VEND_PP5C  0xB8
  20#define AHCI_VEND_AXICC 0xBc
  21#define AHCI_VEND_PAXIC 0xC0
  22#define AHCI_VEND_PTC   0xC8
  23
  24/* Vendor Specific Register bit definitions */
  25#define PAXIC_ADBW_BW64 0x1
  26#define PAXIC_MAWIDD    (1 << 8)
  27#define PAXIC_MARIDD    (1 << 16)
  28#define PAXIC_OTL       (0x4 << 20)
  29
  30#define PCFG_TPSS_VAL   (0x32 << 16)
  31#define PCFG_TPRS_VAL   (0x2 << 12)
  32#define PCFG_PAD_VAL    0x2
  33
  34#define PPCFG_TTA       0x1FFFE
  35#define PPCFG_PSSO_EN   (1 << 28)
  36#define PPCFG_PSS_EN    (1 << 29)
  37#define PPCFG_ESDF_EN   (1 << 31)
  38
  39#define PP2C_CIBGMN     0x0F
  40#define PP2C_CIBGMX     (0x25 << 8)
  41#define PP2C_CIBGN      (0x18 << 16)
  42#define PP2C_CINMP      (0x29 << 24)
  43
  44#define PP3C_CWBGMN     0x04
  45#define PP3C_CWBGMX     (0x0B << 8)
  46#define PP3C_CWBGN      (0x08 << 16)
  47#define PP3C_CWNMP      (0x0F << 24)
  48
  49#define PP4C_BMX        0x0a
  50#define PP4C_BNM        (0x08 << 8)
  51#define PP4C_SFD        (0x4a << 16)
  52#define PP4C_PTST       (0x06 << 24)
  53
  54#define PP5C_RIT        0x60216
  55#define PP5C_RCT        (0x7f0 << 20)
  56
  57#define PTC_RX_WM_VAL   0x40
  58#define PTC_RSVD        (1 << 27)
  59
  60#define PORT0_BASE      0x100
  61#define PORT1_BASE      0x180
  62
  63/* Port Control Register Bit Definitions */
  64#define PORT_SCTL_SPD_GEN3      (0x3 << 4)
  65#define PORT_SCTL_SPD_GEN2      (0x2 << 4)
  66#define PORT_SCTL_SPD_GEN1      (0x1 << 4)
  67#define PORT_SCTL_IPM           (0x3 << 8)
  68
  69#define PORT_BASE       0x100
  70#define PORT_OFFSET     0x80
  71#define NR_PORTS        2
  72#define DRV_NAME        "ahci-ceva"
  73#define CEVA_FLAG_BROKEN_GEN2   1
  74
  75/* flag bit definition */
  76#define FLAG_COHERENT   1
  77
  78/* register config value */
  79#define CEVA_PHY1_CFG   0xa003fffe
  80#define CEVA_PHY2_CFG   0x28184d1f
  81#define CEVA_PHY3_CFG   0x0e081509
  82#define CEVA_TRANS_CFG  0x08000029
  83#define CEVA_AXICC_CFG  0x3fffffff
  84
  85/* for ls1021a */
  86#define LS1021_AHCI_VEND_AXICC  0xC0
  87#define LS1021_CEVA_PHY2_CFG    0x28183414
  88#define LS1021_CEVA_PHY3_CFG    0x0e080e06
  89#define LS1021_CEVA_PHY4_CFG    0x064a080b
  90#define LS1021_CEVA_PHY5_CFG    0x2aa86470
  91
  92/* ecc val pair */
  93#define ECC_DIS_VAL_CH1         0x00020000
  94#define ECC_DIS_VAL_CH2         0x80000000
  95#define ECC_DIS_VAL_CH3         0x40000000
  96
  97enum ceva_soc {
  98        CEVA_1V84,
  99        CEVA_LS1012A,
 100        CEVA_LS1021A,
 101        CEVA_LS1028A,
 102        CEVA_LS1043A,
 103        CEVA_LS1046A,
 104        CEVA_LS1088A,
 105        CEVA_LS2080A,
 106};
 107
 108struct ceva_sata_priv {
 109        ulong base;
 110        ulong ecc_base;
 111        enum ceva_soc soc;
 112        ulong flag;
 113};
 114
 115static int ceva_init_sata(struct ceva_sata_priv *priv)
 116{
 117        ulong ecc_addr = priv->ecc_base;
 118        ulong base = priv->base;
 119        ulong tmp;
 120
 121        switch (priv->soc) {
 122        case CEVA_1V84:
 123                tmp = PAXIC_ADBW_BW64 | PAXIC_MAWIDD | PAXIC_MARIDD | PAXIC_OTL;
 124                writel(tmp, base + AHCI_VEND_PAXIC);
 125                tmp = PCFG_TPSS_VAL | PCFG_TPRS_VAL | PCFG_PAD_VAL;
 126                writel(tmp, base + AHCI_VEND_PCFG);
 127                tmp = PPCFG_TTA | PPCFG_PSS_EN | PPCFG_ESDF_EN;
 128                writel(tmp, base + AHCI_VEND_PPCFG);
 129                tmp = PTC_RX_WM_VAL | PTC_RSVD;
 130                writel(tmp, base + AHCI_VEND_PTC);
 131                break;
 132
 133        case CEVA_LS1021A:
 134                if (!ecc_addr)
 135                        return -EINVAL;
 136                writel(ECC_DIS_VAL_CH1, ecc_addr);
 137                writel(CEVA_PHY1_CFG, base + AHCI_VEND_PPCFG);
 138                writel(LS1021_CEVA_PHY2_CFG, base + AHCI_VEND_PP2C);
 139                writel(LS1021_CEVA_PHY3_CFG, base + AHCI_VEND_PP3C);
 140                writel(LS1021_CEVA_PHY4_CFG, base + AHCI_VEND_PP4C);
 141                writel(LS1021_CEVA_PHY5_CFG, base + AHCI_VEND_PP5C);
 142                writel(CEVA_TRANS_CFG, base + AHCI_VEND_PTC);
 143                break;
 144
 145        case CEVA_LS1012A:
 146        case CEVA_LS1043A:
 147        case CEVA_LS1046A:
 148                if (!ecc_addr)
 149                        return -EINVAL;
 150                writel(ECC_DIS_VAL_CH2, ecc_addr);
 151                /* fallthrough */
 152        case CEVA_LS2080A:
 153                writel(CEVA_PHY1_CFG, base + AHCI_VEND_PPCFG);
 154                writel(CEVA_TRANS_CFG, base + AHCI_VEND_PTC);
 155                break;
 156
 157        case CEVA_LS1028A:
 158        case CEVA_LS1088A:
 159                if (!ecc_addr)
 160                        return -EINVAL;
 161                writel(ECC_DIS_VAL_CH3, ecc_addr);
 162                writel(CEVA_PHY1_CFG, base + AHCI_VEND_PPCFG);
 163                writel(CEVA_TRANS_CFG, base + AHCI_VEND_PTC);
 164                break;
 165        }
 166
 167        if (priv->flag & FLAG_COHERENT)
 168                writel(CEVA_AXICC_CFG, base + AHCI_VEND_AXICC);
 169
 170        return 0;
 171}
 172
 173static int sata_ceva_bind(struct udevice *dev)
 174{
 175        struct udevice *scsi_dev;
 176
 177        return ahci_bind_scsi(dev, &scsi_dev);
 178}
 179
 180static int sata_ceva_probe(struct udevice *dev)
 181{
 182        struct ceva_sata_priv *priv = dev_get_priv(dev);
 183
 184        ceva_init_sata(priv);
 185
 186        return ahci_probe_scsi(dev, priv->base);
 187}
 188
 189static const struct udevice_id sata_ceva_ids[] = {
 190        { .compatible = "ceva,ahci-1v84", .data = CEVA_1V84 },
 191        { .compatible = "fsl,ls1012a-ahci", .data = CEVA_LS1012A },
 192        { .compatible = "fsl,ls1021a-ahci", .data = CEVA_LS1021A },
 193        { .compatible = "fsl,ls1028a-ahci", .data = CEVA_LS1028A },
 194        { .compatible = "fsl,ls1043a-ahci", .data = CEVA_LS1043A },
 195        { .compatible = "fsl,ls1046a-ahci", .data = CEVA_LS1046A },
 196        { .compatible = "fsl,ls1088a-ahci", .data = CEVA_LS1088A },
 197        { .compatible = "fsl,ls2080a-ahci", .data = CEVA_LS2080A },
 198        { }
 199};
 200
 201static int sata_ceva_ofdata_to_platdata(struct udevice *dev)
 202{
 203        struct ceva_sata_priv *priv = dev_get_priv(dev);
 204        struct resource res_regs;
 205        int ret;
 206
 207        if (dev_read_bool(dev, "dma-coherent"))
 208                priv->flag |= FLAG_COHERENT;
 209
 210        priv->base = dev_read_addr(dev);
 211        if (priv->base == FDT_ADDR_T_NONE)
 212                return -EINVAL;
 213
 214        ret = dev_read_resource_byname(dev, "ecc-addr", &res_regs);
 215        if (ret)
 216                priv->ecc_base = 0;
 217        else
 218                priv->ecc_base = res_regs.start;
 219
 220        priv->soc = dev_get_driver_data(dev);
 221
 222        debug("ccsr-sata-base %lx\t ecc-base %lx\n",
 223              priv->base,
 224              priv->ecc_base);
 225
 226        return 0;
 227}
 228
 229U_BOOT_DRIVER(ceva_host_blk) = {
 230        .name = "ceva_sata",
 231        .id = UCLASS_AHCI,
 232        .of_match = sata_ceva_ids,
 233        .bind = sata_ceva_bind,
 234        .ops = &scsi_ops,
 235        .priv_auto_alloc_size = sizeof(struct ceva_sata_priv),
 236        .probe = sata_ceva_probe,
 237        .ofdata_to_platdata = sata_ceva_ofdata_to_platdata,
 238};
 239