blob: a7d45e81cfdc8256054b3019c22132d3de362223 [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 Simekc3898a82018-04-06 13:32:52 +020075struct ceva_sata_priv {
76 ulong base;
77};
78
Michal Simek49c4c782016-09-08 15:06:22 +020079static int ceva_init_sata(ulong mmio)
Michal Simek679b9942015-09-30 17:26:55 +020080{
81 ulong tmp;
Michal Simek679b9942015-09-30 17:26:55 +020082 int i;
83
84 /*
85 * AXI Data bus width to 64
86 * Set Mem Addr Read, Write ID for data transfers
87 * Transfer limit to 72 DWord
88 */
89 tmp = PAXIC_ADBW_BW64 | PAXIC_MAWIDD | PAXIC_MARIDD | PAXIC_OTL;
90 writel(tmp, mmio + AHCI_VEND_PAXIC);
91
92 /* Set AHCI Enable */
93 tmp = readl(mmio + HOST_CTL);
94 tmp |= HOST_AHCI_EN;
95 writel(tmp, mmio + HOST_CTL);
96
97 for (i = 0; i < NR_PORTS; i++) {
98 /* TPSS TPRS scalars, CISE and Port Addr */
99 tmp = PCFG_TPSS_VAL | PCFG_TPRS_VAL | (PCFG_PAD_VAL + i);
100 writel(tmp, mmio + AHCI_VEND_PCFG);
101
102 /* Port Phy Cfg register enables */
103 tmp = PPCFG_TTA | PPCFG_PSS_EN | PPCFG_ESDF_EN;
104 writel(tmp, mmio + AHCI_VEND_PPCFG);
105
106 /* Rx Watermark setting */
107 tmp = PTC_RX_WM_VAL | PTC_RSVD;
108 writel(tmp, mmio + AHCI_VEND_PTC);
109
110 /* Default to Gen 2 Speed and Gen 1 if Gen2 is broken */
111 tmp = PORT_SCTL_SPD_GEN3 | PORT_SCTL_IPM;
112 writel(tmp, mmio + PORT_SCR_CTL + PORT_BASE + PORT_OFFSET * i);
113 }
114 return 0;
115}
Michal Simek49c4c782016-09-08 15:06:22 +0200116
Michal Simekc3898a82018-04-06 13:32:52 +0200117static int sata_ceva_bind(struct udevice *dev)
118{
119 struct udevice *scsi_dev;
120
121 return ahci_bind_scsi(dev, &scsi_dev);
122}
123
Michal Simek49c4c782016-09-08 15:06:22 +0200124static int sata_ceva_probe(struct udevice *dev)
125{
Michal Simekc3898a82018-04-06 13:32:52 +0200126 struct ceva_sata_priv *priv = dev_get_priv(dev);
Michal Simek49c4c782016-09-08 15:06:22 +0200127
Michal Simekc3898a82018-04-06 13:32:52 +0200128 ceva_init_sata(priv->base);
Simon Glass7cf1afc2017-06-14 21:28:37 -0600129
Michal Simekc3898a82018-04-06 13:32:52 +0200130 return ahci_probe_scsi(dev, priv->base);
Michal Simek49c4c782016-09-08 15:06:22 +0200131}
132
133static const struct udevice_id sata_ceva_ids[] = {
134 { .compatible = "ceva,ahci-1v84" },
135 { }
136};
137
138static int sata_ceva_ofdata_to_platdata(struct udevice *dev)
139{
Michal Simekc3898a82018-04-06 13:32:52 +0200140 struct ceva_sata_priv *priv = dev_get_priv(dev);
Michal Simek49c4c782016-09-08 15:06:22 +0200141
Michal Simekc3898a82018-04-06 13:32:52 +0200142 priv->base = devfdt_get_addr(dev);
143 if (priv->base == FDT_ADDR_T_NONE)
Michal Simek49c4c782016-09-08 15:06:22 +0200144 return -EINVAL;
145
Michal Simek49c4c782016-09-08 15:06:22 +0200146 return 0;
147}
148
149U_BOOT_DRIVER(ceva_host_blk) = {
150 .name = "ceva_sata",
Michal Simekc3898a82018-04-06 13:32:52 +0200151 .id = UCLASS_AHCI,
Michal Simek49c4c782016-09-08 15:06:22 +0200152 .of_match = sata_ceva_ids,
Michal Simekc3898a82018-04-06 13:32:52 +0200153 .bind = sata_ceva_bind,
Simon Glassf6ab5a92017-06-14 21:28:43 -0600154 .ops = &scsi_ops,
Michal Simekc3898a82018-04-06 13:32:52 +0200155 .priv_auto_alloc_size = sizeof(struct ceva_sata_priv),
Michal Simek49c4c782016-09-08 15:06:22 +0200156 .probe = sata_ceva_probe,
157 .ofdata_to_platdata = sata_ceva_ofdata_to_platdata,
Michal Simek49c4c782016-09-08 15:06:22 +0200158};