blob: 1544097c52c8e238a63a1a2b53168ce4d0864db0 [file] [log] [blame]
Tom Rini83d290c2018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Michal Simek679b9942015-09-30 17:26:55 +02002/*
3 * (C) Copyright 2015 - 2016 Xilinx, Inc.
4 * Michal Simek <michal.simek@xilinx.com>
Michal Simek679b9942015-09-30 17:26:55 +02005 */
6#include <common.h>
Michal Simek49c4c782016-09-08 15:06:22 +02007#include <dm.h>
Michal Simek679b9942015-09-30 17:26:55 +02008#include <ahci.h>
9#include <scsi.h>
10#include <asm/arch/hardware.h>
11
12#include <asm/io.h>
13
14/* Vendor Specific Register Offsets */
15#define AHCI_VEND_PCFG 0xA4
16#define AHCI_VEND_PPCFG 0xA8
17#define AHCI_VEND_PP2C 0xAC
18#define AHCI_VEND_PP3C 0xB0
19#define AHCI_VEND_PP4C 0xB4
20#define AHCI_VEND_PP5C 0xB8
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
Michal Simek49c4c782016-09-08 15:06:22 +020075static int ceva_init_sata(ulong mmio)
Michal Simek679b9942015-09-30 17:26:55 +020076{
77 ulong tmp;
Michal Simek679b9942015-09-30 17:26:55 +020078 int i;
79
80 /*
81 * AXI Data bus width to 64
82 * Set Mem Addr Read, Write ID for data transfers
83 * Transfer limit to 72 DWord
84 */
85 tmp = PAXIC_ADBW_BW64 | PAXIC_MAWIDD | PAXIC_MARIDD | PAXIC_OTL;
86 writel(tmp, mmio + AHCI_VEND_PAXIC);
87
88 /* Set AHCI Enable */
89 tmp = readl(mmio + HOST_CTL);
90 tmp |= HOST_AHCI_EN;
91 writel(tmp, mmio + HOST_CTL);
92
93 for (i = 0; i < NR_PORTS; i++) {
94 /* TPSS TPRS scalars, CISE and Port Addr */
95 tmp = PCFG_TPSS_VAL | PCFG_TPRS_VAL | (PCFG_PAD_VAL + i);
96 writel(tmp, mmio + AHCI_VEND_PCFG);
97
98 /* Port Phy Cfg register enables */
99 tmp = PPCFG_TTA | PPCFG_PSS_EN | PPCFG_ESDF_EN;
100 writel(tmp, mmio + AHCI_VEND_PPCFG);
101
102 /* Rx Watermark setting */
103 tmp = PTC_RX_WM_VAL | PTC_RSVD;
104 writel(tmp, mmio + AHCI_VEND_PTC);
105
106 /* Default to Gen 2 Speed and Gen 1 if Gen2 is broken */
107 tmp = PORT_SCTL_SPD_GEN3 | PORT_SCTL_IPM;
108 writel(tmp, mmio + PORT_SCR_CTL + PORT_BASE + PORT_OFFSET * i);
109 }
110 return 0;
111}
Michal Simek49c4c782016-09-08 15:06:22 +0200112
113static int sata_ceva_probe(struct udevice *dev)
114{
Michal Simekcba64a22017-11-02 15:45:34 +0100115 int ret;
Simon Glass1dc64f62017-06-14 21:28:31 -0600116 struct scsi_platdata *plat = dev_get_uclass_platdata(dev);
Michal Simek49c4c782016-09-08 15:06:22 +0200117
118 ceva_init_sata(plat->base);
Simon Glass7cf1afc2017-06-14 21:28:37 -0600119
Michal Simeke81589e2017-11-02 15:53:56 +0100120 ret = ahci_init_one_dm(dev);
Michal Simekcba64a22017-11-02 15:45:34 +0100121 if (ret)
122 return ret;
123
Michal Simeke81589e2017-11-02 15:53:56 +0100124 return ahci_start_ports_dm(dev);
Michal Simek49c4c782016-09-08 15:06:22 +0200125}
126
127static const struct udevice_id sata_ceva_ids[] = {
128 { .compatible = "ceva,ahci-1v84" },
129 { }
130};
131
132static int sata_ceva_ofdata_to_platdata(struct udevice *dev)
133{
Simon Glass1dc64f62017-06-14 21:28:31 -0600134 struct scsi_platdata *plat = dev_get_uclass_platdata(dev);
Michal Simek49c4c782016-09-08 15:06:22 +0200135
Simon Glassa821c4a2017-05-17 17:18:05 -0600136 plat->base = devfdt_get_addr(dev);
Michal Simek49c4c782016-09-08 15:06:22 +0200137 if (plat->base == FDT_ADDR_T_NONE)
138 return -EINVAL;
139
140 /* Hardcode number for ceva sata controller */
141 plat->max_lun = 1; /* Actually two but untested */
142 plat->max_id = 2;
143
144 return 0;
145}
146
147U_BOOT_DRIVER(ceva_host_blk) = {
148 .name = "ceva_sata",
149 .id = UCLASS_SCSI,
150 .of_match = sata_ceva_ids,
Simon Glassf6ab5a92017-06-14 21:28:43 -0600151 .ops = &scsi_ops,
Michal Simek49c4c782016-09-08 15:06:22 +0200152 .probe = sata_ceva_probe,
153 .ofdata_to_platdata = sata_ceva_ofdata_to_platdata,
Michal Simek49c4c782016-09-08 15:06:22 +0200154};