diff options
author | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
---|---|---|
committer | Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com> | 2023-10-10 14:33:42 +0000 |
commit | af1a266670d040d2f4083ff309d732d648afba2a (patch) | |
tree | 2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/u-boot/drivers/ata/sata_ceva.c | |
parent | e02cda008591317b1625707ff8e115a4841aa889 (diff) |
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/u-boot/drivers/ata/sata_ceva.c')
-rw-r--r-- | roms/u-boot/drivers/ata/sata_ceva.c | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/roms/u-boot/drivers/ata/sata_ceva.c b/roms/u-boot/drivers/ata/sata_ceva.c new file mode 100644 index 000000000..87e6a90f7 --- /dev/null +++ b/roms/u-boot/drivers/ata/sata_ceva.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * (C) Copyright 2015 - 2016 Xilinx, Inc. + * Michal Simek <michal.simek@xilinx.com> + */ +#include <common.h> +#include <dm.h> +#include <ahci.h> +#include <log.h> +#include <scsi.h> +#include <asm/io.h> +#include <linux/ioport.h> + +/* Vendor Specific Register Offsets */ +#define AHCI_VEND_PCFG 0xA4 +#define AHCI_VEND_PPCFG 0xA8 +#define AHCI_VEND_PP2C 0xAC +#define AHCI_VEND_PP3C 0xB0 +#define AHCI_VEND_PP4C 0xB4 +#define AHCI_VEND_PP5C 0xB8 +#define AHCI_VEND_AXICC 0xBc +#define AHCI_VEND_PAXIC 0xC0 +#define AHCI_VEND_PTC 0xC8 + +/* Vendor Specific Register bit definitions */ +#define PAXIC_ADBW_BW64 0x1 +#define PAXIC_MAWIDD (1 << 8) +#define PAXIC_MARIDD (1 << 16) +#define PAXIC_OTL (0x4 << 20) + +#define PCFG_TPSS_VAL (0x32 << 16) +#define PCFG_TPRS_VAL (0x2 << 12) +#define PCFG_PAD_VAL 0x2 + +#define PPCFG_TTA 0x1FFFE +#define PPCFG_PSSO_EN (1 << 28) +#define PPCFG_PSS_EN (1 << 29) +#define PPCFG_ESDF_EN (1 << 31) + +#define PP2C_CIBGMN 0x0F +#define PP2C_CIBGMX (0x25 << 8) +#define PP2C_CIBGN (0x18 << 16) +#define PP2C_CINMP (0x29 << 24) + +#define PP3C_CWBGMN 0x04 +#define PP3C_CWBGMX (0x0B << 8) +#define PP3C_CWBGN (0x08 << 16) +#define PP3C_CWNMP (0x0F << 24) + +#define PP4C_BMX 0x0a +#define PP4C_BNM (0x08 << 8) +#define PP4C_SFD (0x4a << 16) +#define PP4C_PTST (0x06 << 24) + +#define PP5C_RIT 0x60216 +#define PP5C_RCT (0x7f0 << 20) + +#define PTC_RX_WM_VAL 0x40 +#define PTC_RSVD (1 << 27) + +#define PORT0_BASE 0x100 +#define PORT1_BASE 0x180 + +/* Port Control Register Bit Definitions */ +#define PORT_SCTL_SPD_GEN3 (0x3 << 4) +#define PORT_SCTL_SPD_GEN2 (0x2 << 4) +#define PORT_SCTL_SPD_GEN1 (0x1 << 4) +#define PORT_SCTL_IPM (0x3 << 8) + +#define PORT_BASE 0x100 +#define PORT_OFFSET 0x80 +#define NR_PORTS 2 +#define DRV_NAME "ahci-ceva" +#define CEVA_FLAG_BROKEN_GEN2 1 + +/* flag bit definition */ +#define FLAG_COHERENT 1 + +/* register config value */ +#define CEVA_PHY1_CFG 0xa003fffe +#define CEVA_PHY2_CFG 0x28184d1f +#define CEVA_PHY3_CFG 0x0e081509 +#define CEVA_TRANS_CFG 0x08000029 +#define CEVA_AXICC_CFG 0x3fffffff + +/* for ls1021a */ +#define LS1021_AHCI_VEND_AXICC 0xC0 +#define LS1021_CEVA_PHY2_CFG 0x28183414 +#define LS1021_CEVA_PHY3_CFG 0x0e080e06 +#define LS1021_CEVA_PHY4_CFG 0x064a080b +#define LS1021_CEVA_PHY5_CFG 0x2aa86470 + +/* ecc val pair */ +#define ECC_DIS_VAL_CH1 0x00020000 +#define ECC_DIS_VAL_CH2 0x80000000 +#define ECC_DIS_VAL_CH3 0x40000000 + +enum ceva_soc { + CEVA_1V84, + CEVA_LS1012A, + CEVA_LS1021A, + CEVA_LS1028A, + CEVA_LS1043A, + CEVA_LS1046A, + CEVA_LS1088A, + CEVA_LS2080A, +}; + +struct ceva_sata_priv { + ulong base; + ulong ecc_base; + enum ceva_soc soc; + ulong flag; +}; + +static int ceva_init_sata(struct ceva_sata_priv *priv) +{ + ulong ecc_addr = priv->ecc_base; + ulong base = priv->base; + ulong tmp; + + switch (priv->soc) { + case CEVA_1V84: + tmp = PAXIC_ADBW_BW64 | PAXIC_MAWIDD | PAXIC_MARIDD | PAXIC_OTL; + writel(tmp, base + AHCI_VEND_PAXIC); + tmp = PCFG_TPSS_VAL | PCFG_TPRS_VAL | PCFG_PAD_VAL; + writel(tmp, base + AHCI_VEND_PCFG); + tmp = PPCFG_TTA | PPCFG_PSS_EN | PPCFG_ESDF_EN; + writel(tmp, base + AHCI_VEND_PPCFG); + tmp = PTC_RX_WM_VAL | PTC_RSVD; + writel(tmp, base + AHCI_VEND_PTC); + break; + + case CEVA_LS1021A: + if (!ecc_addr) + return -EINVAL; + writel(ECC_DIS_VAL_CH1, ecc_addr); + writel(CEVA_PHY1_CFG, base + AHCI_VEND_PPCFG); + writel(LS1021_CEVA_PHY2_CFG, base + AHCI_VEND_PP2C); + writel(LS1021_CEVA_PHY3_CFG, base + AHCI_VEND_PP3C); + writel(LS1021_CEVA_PHY4_CFG, base + AHCI_VEND_PP4C); + writel(LS1021_CEVA_PHY5_CFG, base + AHCI_VEND_PP5C); + writel(CEVA_TRANS_CFG, base + AHCI_VEND_PTC); + break; + + case CEVA_LS1012A: + case CEVA_LS1043A: + case CEVA_LS1046A: + if (!ecc_addr) + return -EINVAL; + writel(ECC_DIS_VAL_CH2, ecc_addr); + /* fallthrough */ + case CEVA_LS2080A: + writel(CEVA_PHY1_CFG, base + AHCI_VEND_PPCFG); + writel(CEVA_TRANS_CFG, base + AHCI_VEND_PTC); + break; + + case CEVA_LS1028A: + case CEVA_LS1088A: + if (!ecc_addr) + return -EINVAL; + writel(ECC_DIS_VAL_CH3, ecc_addr); + writel(CEVA_PHY1_CFG, base + AHCI_VEND_PPCFG); + writel(CEVA_TRANS_CFG, base + AHCI_VEND_PTC); + break; + } + + if (priv->flag & FLAG_COHERENT) + writel(CEVA_AXICC_CFG, base + AHCI_VEND_AXICC); + + return 0; +} + +static int sata_ceva_bind(struct udevice *dev) +{ + struct udevice *scsi_dev; + + return ahci_bind_scsi(dev, &scsi_dev); +} + +static int sata_ceva_probe(struct udevice *dev) +{ + struct ceva_sata_priv *priv = dev_get_priv(dev); + + ceva_init_sata(priv); + + return ahci_probe_scsi(dev, priv->base); +} + +static const struct udevice_id sata_ceva_ids[] = { + { .compatible = "ceva,ahci-1v84", .data = CEVA_1V84 }, + { .compatible = "fsl,ls1012a-ahci", .data = CEVA_LS1012A }, + { .compatible = "fsl,ls1021a-ahci", .data = CEVA_LS1021A }, + { .compatible = "fsl,ls1028a-ahci", .data = CEVA_LS1028A }, + { .compatible = "fsl,ls1043a-ahci", .data = CEVA_LS1043A }, + { .compatible = "fsl,ls1046a-ahci", .data = CEVA_LS1046A }, + { .compatible = "fsl,ls1088a-ahci", .data = CEVA_LS1088A }, + { .compatible = "fsl,ls2080a-ahci", .data = CEVA_LS2080A }, + { } +}; + +static int sata_ceva_of_to_plat(struct udevice *dev) +{ + struct ceva_sata_priv *priv = dev_get_priv(dev); + struct resource res_regs; + int ret; + + if (dev_read_bool(dev, "dma-coherent")) + priv->flag |= FLAG_COHERENT; + + priv->base = dev_read_addr(dev); + if (priv->base == FDT_ADDR_T_NONE) + return -EINVAL; + + ret = dev_read_resource_byname(dev, "ecc-addr", &res_regs); + if (ret) + priv->ecc_base = 0; + else + priv->ecc_base = res_regs.start; + + priv->soc = dev_get_driver_data(dev); + + debug("ccsr-sata-base %lx\t ecc-base %lx\n", + priv->base, + priv->ecc_base); + + return 0; +} + +U_BOOT_DRIVER(ceva_host_blk) = { + .name = "ceva_sata", + .id = UCLASS_AHCI, + .of_match = sata_ceva_ids, + .bind = sata_ceva_bind, + .ops = &scsi_ops, + .priv_auto = sizeof(struct ceva_sata_priv), + .probe = sata_ceva_probe, + .of_to_plat = sata_ceva_of_to_plat, +}; |