183d290c5STom Rini // SPDX-License-Identifier: GPL-2.0+
2f2105c61SSimon Glass /*
3f2105c61SSimon Glass * Copyright (C) Freescale Semiconductor, Inc. 2006.
4f2105c61SSimon Glass * Author: Jason Jin<Jason.jin@freescale.com>
5f2105c61SSimon Glass * Zhang Wei<wei.zhang@freescale.com>
6f2105c61SSimon Glass *
7f2105c61SSimon Glass * with the reference on libata and ahci drvier in kernel
87cf1afceSSimon Glass *
97cf1afceSSimon Glass * This driver provides a SCSI interface to SATA.
10f2105c61SSimon Glass */
11f2105c61SSimon Glass #include <common.h>
12f2105c61SSimon Glass
13f2105c61SSimon Glass #include <command.h>
14f2105c61SSimon Glass #include <dm.h>
15f2105c61SSimon Glass #include <pci.h>
16f2105c61SSimon Glass #include <asm/processor.h>
17f2105c61SSimon Glass #include <linux/errno.h>
18f2105c61SSimon Glass #include <asm/io.h>
19f2105c61SSimon Glass #include <malloc.h>
20f2105c61SSimon Glass #include <memalign.h>
21681357ffSSimon Glass #include <pci.h>
22f2105c61SSimon Glass #include <scsi.h>
23f2105c61SSimon Glass #include <libata.h>
24f2105c61SSimon Glass #include <linux/ctype.h>
25f2105c61SSimon Glass #include <ahci.h>
26681357ffSSimon Glass #include <dm/device-internal.h>
27681357ffSSimon Glass #include <dm/lists.h>
28f2105c61SSimon Glass
29225b1da7SSimon Glass static int ata_io_flush(struct ahci_uc_priv *uc_priv, u8 port);
30f2105c61SSimon Glass
314682c8a1SSimon Glass #ifndef CONFIG_DM_SCSI
322c9f9efbSSimon Glass struct ahci_uc_priv *probe_ent = NULL;
334682c8a1SSimon Glass #endif
34f2105c61SSimon Glass
35f2105c61SSimon Glass #define writel_with_flush(a,b) do { writel(a,b); readl(b); } while (0)
36f2105c61SSimon Glass
37f2105c61SSimon Glass /*
38f2105c61SSimon Glass * Some controllers limit number of blocks they can read/write at once.
39f2105c61SSimon Glass * Contemporary SSD devices work much faster if the read/write size is aligned
40f2105c61SSimon Glass * to a power of 2. Let's set default to 128 and allowing to be overwritten if
41f2105c61SSimon Glass * needed.
42f2105c61SSimon Glass */
43f2105c61SSimon Glass #ifndef MAX_SATA_BLOCKS_READ_WRITE
44f2105c61SSimon Glass #define MAX_SATA_BLOCKS_READ_WRITE 0x80
45f2105c61SSimon Glass #endif
46f2105c61SSimon Glass
47f2105c61SSimon Glass /* Maximum timeouts for each event */
48f2105c61SSimon Glass #define WAIT_MS_SPINUP 20000
49f2105c61SSimon Glass #define WAIT_MS_DATAIO 10000
50f2105c61SSimon Glass #define WAIT_MS_FLUSH 5000
51f2105c61SSimon Glass #define WAIT_MS_LINKUP 200
52f2105c61SSimon Glass
ahci_port_base(void __iomem * base,u32 port)53f2105c61SSimon Glass __weak void __iomem *ahci_port_base(void __iomem *base, u32 port)
54f2105c61SSimon Glass {
55f2105c61SSimon Glass return base + 0x100 + (port * 0x80);
56f2105c61SSimon Glass }
57f2105c61SSimon Glass
58f2105c61SSimon Glass
ahci_setup_port(struct ahci_ioports * port,void __iomem * base,unsigned int port_idx)59f2105c61SSimon Glass static void ahci_setup_port(struct ahci_ioports *port, void __iomem *base,
60f2105c61SSimon Glass unsigned int port_idx)
61f2105c61SSimon Glass {
62f2105c61SSimon Glass base = ahci_port_base(base, port_idx);
63f2105c61SSimon Glass
64f2105c61SSimon Glass port->cmd_addr = base;
65f2105c61SSimon Glass port->scr_addr = base + PORT_SCR;
66f2105c61SSimon Glass }
67f2105c61SSimon Glass
68f2105c61SSimon Glass
69f2105c61SSimon Glass #define msleep(a) udelay(a * 1000)
70f2105c61SSimon Glass
ahci_dcache_flush_range(unsigned long begin,unsigned long len)71f2105c61SSimon Glass static void ahci_dcache_flush_range(unsigned long begin, unsigned long len)
72f2105c61SSimon Glass {
73f2105c61SSimon Glass const unsigned long start = begin;
74f2105c61SSimon Glass const unsigned long end = start + len;
75f2105c61SSimon Glass
76f2105c61SSimon Glass debug("%s: flush dcache: [%#lx, %#lx)\n", __func__, start, end);
77f2105c61SSimon Glass flush_dcache_range(start, end);
78f2105c61SSimon Glass }
79f2105c61SSimon Glass
80f2105c61SSimon Glass /*
81f2105c61SSimon Glass * SATA controller DMAs to physical RAM. Ensure data from the
82f2105c61SSimon Glass * controller is invalidated from dcache; next access comes from
83f2105c61SSimon Glass * physical RAM.
84f2105c61SSimon Glass */
ahci_dcache_invalidate_range(unsigned long begin,unsigned long len)85f2105c61SSimon Glass static void ahci_dcache_invalidate_range(unsigned long begin, unsigned long len)
86f2105c61SSimon Glass {
87f2105c61SSimon Glass const unsigned long start = begin;
88f2105c61SSimon Glass const unsigned long end = start + len;
89f2105c61SSimon Glass
90f2105c61SSimon Glass debug("%s: invalidate dcache: [%#lx, %#lx)\n", __func__, start, end);
91f2105c61SSimon Glass invalidate_dcache_range(start, end);
92f2105c61SSimon Glass }
93f2105c61SSimon Glass
94f2105c61SSimon Glass /*
95f2105c61SSimon Glass * Ensure data for SATA controller is flushed out of dcache and
96f2105c61SSimon Glass * written to physical memory.
97f2105c61SSimon Glass */
ahci_dcache_flush_sata_cmd(struct ahci_ioports * pp)98f2105c61SSimon Glass static void ahci_dcache_flush_sata_cmd(struct ahci_ioports *pp)
99f2105c61SSimon Glass {
100f2105c61SSimon Glass ahci_dcache_flush_range((unsigned long)pp->cmd_slot,
101f2105c61SSimon Glass AHCI_PORT_PRIV_DMA_SZ);
102f2105c61SSimon Glass }
103f2105c61SSimon Glass
waiting_for_cmd_completed(void __iomem * offset,int timeout_msec,u32 sign)104f2105c61SSimon Glass static int waiting_for_cmd_completed(void __iomem *offset,
105f2105c61SSimon Glass int timeout_msec,
106f2105c61SSimon Glass u32 sign)
107f2105c61SSimon Glass {
108f2105c61SSimon Glass int i;
109f2105c61SSimon Glass u32 status;
110f2105c61SSimon Glass
111f2105c61SSimon Glass for (i = 0; ((status = readl(offset)) & sign) && i < timeout_msec; i++)
112f2105c61SSimon Glass msleep(1);
113f2105c61SSimon Glass
114f2105c61SSimon Glass return (i < timeout_msec) ? 0 : -1;
115f2105c61SSimon Glass }
116f2105c61SSimon Glass
ahci_link_up(struct ahci_uc_priv * uc_priv,u8 port)1174b62b2ffSSimon Glass int __weak ahci_link_up(struct ahci_uc_priv *uc_priv, u8 port)
118f2105c61SSimon Glass {
119f2105c61SSimon Glass u32 tmp;
120f2105c61SSimon Glass int j = 0;
1214b62b2ffSSimon Glass void __iomem *port_mmio = uc_priv->port[port].port_mmio;
122f2105c61SSimon Glass
123f2105c61SSimon Glass /*
124f2105c61SSimon Glass * Bring up SATA link.
125f2105c61SSimon Glass * SATA link bringup time is usually less than 1 ms; only very
126f2105c61SSimon Glass * rarely has it taken between 1-2 ms. Never seen it above 2 ms.
127f2105c61SSimon Glass */
128f2105c61SSimon Glass while (j < WAIT_MS_LINKUP) {
129f2105c61SSimon Glass tmp = readl(port_mmio + PORT_SCR_STAT);
130f2105c61SSimon Glass tmp &= PORT_SCR_STAT_DET_MASK;
131f2105c61SSimon Glass if (tmp == PORT_SCR_STAT_DET_PHYRDY)
132f2105c61SSimon Glass return 0;
133f2105c61SSimon Glass udelay(1000);
134f2105c61SSimon Glass j++;
135f2105c61SSimon Glass }
136f2105c61SSimon Glass return 1;
137f2105c61SSimon Glass }
138f2105c61SSimon Glass
139f2105c61SSimon Glass #ifdef CONFIG_SUNXI_AHCI
140f2105c61SSimon Glass /* The sunxi AHCI controller requires this undocumented setup */
sunxi_dma_init(void __iomem * port_mmio)141f2105c61SSimon Glass static void sunxi_dma_init(void __iomem *port_mmio)
142f2105c61SSimon Glass {
143f2105c61SSimon Glass clrsetbits_le32(port_mmio + PORT_P0DMACR, 0x0000ff00, 0x00004400);
144f2105c61SSimon Glass }
145f2105c61SSimon Glass #endif
146f2105c61SSimon Glass
ahci_reset(void __iomem * base)147f2105c61SSimon Glass int ahci_reset(void __iomem *base)
148f2105c61SSimon Glass {
149f2105c61SSimon Glass int i = 1000;
150f2105c61SSimon Glass u32 __iomem *host_ctl_reg = base + HOST_CTL;
151f2105c61SSimon Glass u32 tmp = readl(host_ctl_reg); /* global controller reset */
152f2105c61SSimon Glass
153f2105c61SSimon Glass if ((tmp & HOST_RESET) == 0)
154f2105c61SSimon Glass writel_with_flush(tmp | HOST_RESET, host_ctl_reg);
155f2105c61SSimon Glass
156f2105c61SSimon Glass /*
157f2105c61SSimon Glass * reset must complete within 1 second, or
158f2105c61SSimon Glass * the hardware should be considered fried.
159f2105c61SSimon Glass */
160f2105c61SSimon Glass do {
161f2105c61SSimon Glass udelay(1000);
162f2105c61SSimon Glass tmp = readl(host_ctl_reg);
163f2105c61SSimon Glass i--;
164f2105c61SSimon Glass } while ((i > 0) && (tmp & HOST_RESET));
165f2105c61SSimon Glass
166f2105c61SSimon Glass if (i == 0) {
167f2105c61SSimon Glass printf("controller reset failed (0x%x)\n", tmp);
168f2105c61SSimon Glass return -1;
169f2105c61SSimon Glass }
170f2105c61SSimon Glass
171f2105c61SSimon Glass return 0;
172f2105c61SSimon Glass }
173f2105c61SSimon Glass
ahci_host_init(struct ahci_uc_priv * uc_priv)174225b1da7SSimon Glass static int ahci_host_init(struct ahci_uc_priv *uc_priv)
175f2105c61SSimon Glass {
176f2105c61SSimon Glass #if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI)
177f2105c61SSimon Glass # ifdef CONFIG_DM_PCI
178225b1da7SSimon Glass struct udevice *dev = uc_priv->dev;
179f2105c61SSimon Glass struct pci_child_platdata *pplat = dev_get_parent_platdata(dev);
180f2105c61SSimon Glass # else
181225b1da7SSimon Glass pci_dev_t pdev = uc_priv->dev;
182f2105c61SSimon Glass unsigned short vendor;
183f2105c61SSimon Glass # endif
184f2105c61SSimon Glass u16 tmp16;
185f2105c61SSimon Glass #endif
186225b1da7SSimon Glass void __iomem *mmio = uc_priv->mmio_base;
187f2105c61SSimon Glass u32 tmp, cap_save, cmd;
188f2105c61SSimon Glass int i, j, ret;
189f2105c61SSimon Glass void __iomem *port_mmio;
190f2105c61SSimon Glass u32 port_map;
191f2105c61SSimon Glass
192f2105c61SSimon Glass debug("ahci_host_init: start\n");
193f2105c61SSimon Glass
194f2105c61SSimon Glass cap_save = readl(mmio + HOST_CAP);
195f2105c61SSimon Glass cap_save &= ((1 << 28) | (1 << 17));
196f2105c61SSimon Glass cap_save |= (1 << 27); /* Staggered Spin-up. Not needed. */
197f2105c61SSimon Glass
198225b1da7SSimon Glass ret = ahci_reset(uc_priv->mmio_base);
199f2105c61SSimon Glass if (ret)
200f2105c61SSimon Glass return ret;
201f2105c61SSimon Glass
202f2105c61SSimon Glass writel_with_flush(HOST_AHCI_EN, mmio + HOST_CTL);
203f2105c61SSimon Glass writel(cap_save, mmio + HOST_CAP);
204f2105c61SSimon Glass writel_with_flush(0xf, mmio + HOST_PORTS_IMPL);
205f2105c61SSimon Glass
206f2105c61SSimon Glass #if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI)
207f2105c61SSimon Glass # ifdef CONFIG_DM_PCI
208f2105c61SSimon Glass if (pplat->vendor == PCI_VENDOR_ID_INTEL) {
209f2105c61SSimon Glass u16 tmp16;
210f2105c61SSimon Glass
211f2105c61SSimon Glass dm_pci_read_config16(dev, 0x92, &tmp16);
212f2105c61SSimon Glass dm_pci_write_config16(dev, 0x92, tmp16 | 0xf);
213f2105c61SSimon Glass }
214f2105c61SSimon Glass # else
215f2105c61SSimon Glass pci_read_config_word(pdev, PCI_VENDOR_ID, &vendor);
216f2105c61SSimon Glass
217f2105c61SSimon Glass if (vendor == PCI_VENDOR_ID_INTEL) {
218f2105c61SSimon Glass u16 tmp16;
219f2105c61SSimon Glass pci_read_config_word(pdev, 0x92, &tmp16);
220f2105c61SSimon Glass tmp16 |= 0xf;
221f2105c61SSimon Glass pci_write_config_word(pdev, 0x92, tmp16);
222f2105c61SSimon Glass }
223f2105c61SSimon Glass # endif
224f2105c61SSimon Glass #endif
225225b1da7SSimon Glass uc_priv->cap = readl(mmio + HOST_CAP);
226225b1da7SSimon Glass uc_priv->port_map = readl(mmio + HOST_PORTS_IMPL);
227225b1da7SSimon Glass port_map = uc_priv->port_map;
228225b1da7SSimon Glass uc_priv->n_ports = (uc_priv->cap & 0x1f) + 1;
229f2105c61SSimon Glass
230f2105c61SSimon Glass debug("cap 0x%x port_map 0x%x n_ports %d\n",
231225b1da7SSimon Glass uc_priv->cap, uc_priv->port_map, uc_priv->n_ports);
232f2105c61SSimon Glass
233*0545ac98STuomas Tynkkynen #if !defined(CONFIG_DM_SCSI)
234225b1da7SSimon Glass if (uc_priv->n_ports > CONFIG_SYS_SCSI_MAX_SCSI_ID)
235225b1da7SSimon Glass uc_priv->n_ports = CONFIG_SYS_SCSI_MAX_SCSI_ID;
236*0545ac98STuomas Tynkkynen #endif
237f2105c61SSimon Glass
238225b1da7SSimon Glass for (i = 0; i < uc_priv->n_ports; i++) {
239f2105c61SSimon Glass if (!(port_map & (1 << i)))
240f2105c61SSimon Glass continue;
241225b1da7SSimon Glass uc_priv->port[i].port_mmio = ahci_port_base(mmio, i);
242225b1da7SSimon Glass port_mmio = (u8 *)uc_priv->port[i].port_mmio;
243225b1da7SSimon Glass ahci_setup_port(&uc_priv->port[i], mmio, i);
244f2105c61SSimon Glass
245f2105c61SSimon Glass /* make sure port is not active */
246f2105c61SSimon Glass tmp = readl(port_mmio + PORT_CMD);
247f2105c61SSimon Glass if (tmp & (PORT_CMD_LIST_ON | PORT_CMD_FIS_ON |
248f2105c61SSimon Glass PORT_CMD_FIS_RX | PORT_CMD_START)) {
249f2105c61SSimon Glass debug("Port %d is active. Deactivating.\n", i);
250f2105c61SSimon Glass tmp &= ~(PORT_CMD_LIST_ON | PORT_CMD_FIS_ON |
251f2105c61SSimon Glass PORT_CMD_FIS_RX | PORT_CMD_START);
252f2105c61SSimon Glass writel_with_flush(tmp, port_mmio + PORT_CMD);
253f2105c61SSimon Glass
254f2105c61SSimon Glass /* spec says 500 msecs for each bit, so
255f2105c61SSimon Glass * this is slightly incorrect.
256f2105c61SSimon Glass */
257f2105c61SSimon Glass msleep(500);
258f2105c61SSimon Glass }
259f2105c61SSimon Glass
260f2105c61SSimon Glass #ifdef CONFIG_SUNXI_AHCI
261f2105c61SSimon Glass sunxi_dma_init(port_mmio);
262f2105c61SSimon Glass #endif
263f2105c61SSimon Glass
264f2105c61SSimon Glass /* Add the spinup command to whatever mode bits may
265f2105c61SSimon Glass * already be on in the command register.
266f2105c61SSimon Glass */
267f2105c61SSimon Glass cmd = readl(port_mmio + PORT_CMD);
268f2105c61SSimon Glass cmd |= PORT_CMD_SPIN_UP;
269f2105c61SSimon Glass writel_with_flush(cmd, port_mmio + PORT_CMD);
270f2105c61SSimon Glass
271f2105c61SSimon Glass /* Bring up SATA link. */
272225b1da7SSimon Glass ret = ahci_link_up(uc_priv, i);
273f2105c61SSimon Glass if (ret) {
274f2105c61SSimon Glass printf("SATA link %d timeout.\n", i);
275f2105c61SSimon Glass continue;
276f2105c61SSimon Glass } else {
277f2105c61SSimon Glass debug("SATA link ok.\n");
278f2105c61SSimon Glass }
279f2105c61SSimon Glass
280f2105c61SSimon Glass /* Clear error status */
281f2105c61SSimon Glass tmp = readl(port_mmio + PORT_SCR_ERR);
282f2105c61SSimon Glass if (tmp)
283f2105c61SSimon Glass writel(tmp, port_mmio + PORT_SCR_ERR);
284f2105c61SSimon Glass
285f2105c61SSimon Glass debug("Spinning up device on SATA port %d... ", i);
286f2105c61SSimon Glass
287f2105c61SSimon Glass j = 0;
288f2105c61SSimon Glass while (j < WAIT_MS_SPINUP) {
289f2105c61SSimon Glass tmp = readl(port_mmio + PORT_TFDATA);
290f2105c61SSimon Glass if (!(tmp & (ATA_BUSY | ATA_DRQ)))
291f2105c61SSimon Glass break;
292f2105c61SSimon Glass udelay(1000);
293f2105c61SSimon Glass tmp = readl(port_mmio + PORT_SCR_STAT);
294f2105c61SSimon Glass tmp &= PORT_SCR_STAT_DET_MASK;
295f2105c61SSimon Glass if (tmp == PORT_SCR_STAT_DET_PHYRDY)
296f2105c61SSimon Glass break;
297f2105c61SSimon Glass j++;
298f2105c61SSimon Glass }
299f2105c61SSimon Glass
300f2105c61SSimon Glass tmp = readl(port_mmio + PORT_SCR_STAT) & PORT_SCR_STAT_DET_MASK;
301f2105c61SSimon Glass if (tmp == PORT_SCR_STAT_DET_COMINIT) {
302f2105c61SSimon Glass debug("SATA link %d down (COMINIT received), retrying...\n", i);
303f2105c61SSimon Glass i--;
304f2105c61SSimon Glass continue;
305f2105c61SSimon Glass }
306f2105c61SSimon Glass
307f2105c61SSimon Glass printf("Target spinup took %d ms.\n", j);
308f2105c61SSimon Glass if (j == WAIT_MS_SPINUP)
309f2105c61SSimon Glass debug("timeout.\n");
310f2105c61SSimon Glass else
311f2105c61SSimon Glass debug("ok.\n");
312f2105c61SSimon Glass
313f2105c61SSimon Glass tmp = readl(port_mmio + PORT_SCR_ERR);
314f2105c61SSimon Glass debug("PORT_SCR_ERR 0x%x\n", tmp);
315f2105c61SSimon Glass writel(tmp, port_mmio + PORT_SCR_ERR);
316f2105c61SSimon Glass
317f2105c61SSimon Glass /* ack any pending irq events for this port */
318f2105c61SSimon Glass tmp = readl(port_mmio + PORT_IRQ_STAT);
319f2105c61SSimon Glass debug("PORT_IRQ_STAT 0x%x\n", tmp);
320f2105c61SSimon Glass if (tmp)
321f2105c61SSimon Glass writel(tmp, port_mmio + PORT_IRQ_STAT);
322f2105c61SSimon Glass
323f2105c61SSimon Glass writel(1 << i, mmio + HOST_IRQ_STAT);
324f2105c61SSimon Glass
325f2105c61SSimon Glass /* register linkup ports */
326f2105c61SSimon Glass tmp = readl(port_mmio + PORT_SCR_STAT);
327f2105c61SSimon Glass debug("SATA port %d status: 0x%x\n", i, tmp);
328f2105c61SSimon Glass if ((tmp & PORT_SCR_STAT_DET_MASK) == PORT_SCR_STAT_DET_PHYRDY)
329225b1da7SSimon Glass uc_priv->link_port_map |= (0x01 << i);
330f2105c61SSimon Glass }
331f2105c61SSimon Glass
332f2105c61SSimon Glass tmp = readl(mmio + HOST_CTL);
333f2105c61SSimon Glass debug("HOST_CTL 0x%x\n", tmp);
334f2105c61SSimon Glass writel(tmp | HOST_IRQ_EN, mmio + HOST_CTL);
335f2105c61SSimon Glass tmp = readl(mmio + HOST_CTL);
336f2105c61SSimon Glass debug("HOST_CTL 0x%x\n", tmp);
337f2105c61SSimon Glass #if !defined(CONFIG_DM_SCSI)
338f2105c61SSimon Glass #ifndef CONFIG_SCSI_AHCI_PLAT
339f2105c61SSimon Glass # ifdef CONFIG_DM_PCI
340f2105c61SSimon Glass dm_pci_read_config16(dev, PCI_COMMAND, &tmp16);
341f2105c61SSimon Glass tmp |= PCI_COMMAND_MASTER;
342f2105c61SSimon Glass dm_pci_write_config16(dev, PCI_COMMAND, tmp16);
343f2105c61SSimon Glass # else
344f2105c61SSimon Glass pci_read_config_word(pdev, PCI_COMMAND, &tmp16);
345f2105c61SSimon Glass tmp |= PCI_COMMAND_MASTER;
346f2105c61SSimon Glass pci_write_config_word(pdev, PCI_COMMAND, tmp16);
347f2105c61SSimon Glass # endif
348f2105c61SSimon Glass #endif
349f2105c61SSimon Glass #endif
350f2105c61SSimon Glass return 0;
351f2105c61SSimon Glass }
352f2105c61SSimon Glass
353f2105c61SSimon Glass
ahci_print_info(struct ahci_uc_priv * uc_priv)354225b1da7SSimon Glass static void ahci_print_info(struct ahci_uc_priv *uc_priv)
355f2105c61SSimon Glass {
356f2105c61SSimon Glass #if !defined(CONFIG_SCSI_AHCI_PLAT) && !defined(CONFIG_DM_SCSI)
357f2105c61SSimon Glass # if defined(CONFIG_DM_PCI)
358225b1da7SSimon Glass struct udevice *dev = uc_priv->dev;
359f2105c61SSimon Glass # else
360225b1da7SSimon Glass pci_dev_t pdev = uc_priv->dev;
361f2105c61SSimon Glass # endif
362f2105c61SSimon Glass u16 cc;
363f2105c61SSimon Glass #endif
364225b1da7SSimon Glass void __iomem *mmio = uc_priv->mmio_base;
365f2105c61SSimon Glass u32 vers, cap, cap2, impl, speed;
366f2105c61SSimon Glass const char *speed_s;
367f2105c61SSimon Glass const char *scc_s;
368f2105c61SSimon Glass
369f2105c61SSimon Glass vers = readl(mmio + HOST_VERSION);
370225b1da7SSimon Glass cap = uc_priv->cap;
371f2105c61SSimon Glass cap2 = readl(mmio + HOST_CAP2);
372225b1da7SSimon Glass impl = uc_priv->port_map;
373f2105c61SSimon Glass
374f2105c61SSimon Glass speed = (cap >> 20) & 0xf;
375f2105c61SSimon Glass if (speed == 1)
376f2105c61SSimon Glass speed_s = "1.5";
377f2105c61SSimon Glass else if (speed == 2)
378f2105c61SSimon Glass speed_s = "3";
379f2105c61SSimon Glass else if (speed == 3)
380f2105c61SSimon Glass speed_s = "6";
381f2105c61SSimon Glass else
382f2105c61SSimon Glass speed_s = "?";
383f2105c61SSimon Glass
384f2105c61SSimon Glass #if defined(CONFIG_SCSI_AHCI_PLAT) || defined(CONFIG_DM_SCSI)
385f2105c61SSimon Glass scc_s = "SATA";
386f2105c61SSimon Glass #else
387f2105c61SSimon Glass # ifdef CONFIG_DM_PCI
388f2105c61SSimon Glass dm_pci_read_config16(dev, 0x0a, &cc);
389f2105c61SSimon Glass # else
390f2105c61SSimon Glass pci_read_config_word(pdev, 0x0a, &cc);
391f2105c61SSimon Glass # endif
392f2105c61SSimon Glass if (cc == 0x0101)
393f2105c61SSimon Glass scc_s = "IDE";
394f2105c61SSimon Glass else if (cc == 0x0106)
395f2105c61SSimon Glass scc_s = "SATA";
396f2105c61SSimon Glass else if (cc == 0x0104)
397f2105c61SSimon Glass scc_s = "RAID";
398f2105c61SSimon Glass else
399f2105c61SSimon Glass scc_s = "unknown";
400f2105c61SSimon Glass #endif
401f2105c61SSimon Glass printf("AHCI %02x%02x.%02x%02x "
402f2105c61SSimon Glass "%u slots %u ports %s Gbps 0x%x impl %s mode\n",
403f2105c61SSimon Glass (vers >> 24) & 0xff,
404f2105c61SSimon Glass (vers >> 16) & 0xff,
405f2105c61SSimon Glass (vers >> 8) & 0xff,
406f2105c61SSimon Glass vers & 0xff,
407f2105c61SSimon Glass ((cap >> 8) & 0x1f) + 1, (cap & 0x1f) + 1, speed_s, impl, scc_s);
408f2105c61SSimon Glass
409f2105c61SSimon Glass printf("flags: "
410f2105c61SSimon Glass "%s%s%s%s%s%s%s"
411f2105c61SSimon Glass "%s%s%s%s%s%s%s"
412f2105c61SSimon Glass "%s%s%s%s%s%s\n",
413f2105c61SSimon Glass cap & (1 << 31) ? "64bit " : "",
414f2105c61SSimon Glass cap & (1 << 30) ? "ncq " : "",
415f2105c61SSimon Glass cap & (1 << 28) ? "ilck " : "",
416f2105c61SSimon Glass cap & (1 << 27) ? "stag " : "",
417f2105c61SSimon Glass cap & (1 << 26) ? "pm " : "",
418f2105c61SSimon Glass cap & (1 << 25) ? "led " : "",
419f2105c61SSimon Glass cap & (1 << 24) ? "clo " : "",
420f2105c61SSimon Glass cap & (1 << 19) ? "nz " : "",
421f2105c61SSimon Glass cap & (1 << 18) ? "only " : "",
422f2105c61SSimon Glass cap & (1 << 17) ? "pmp " : "",
423f2105c61SSimon Glass cap & (1 << 16) ? "fbss " : "",
424f2105c61SSimon Glass cap & (1 << 15) ? "pio " : "",
425f2105c61SSimon Glass cap & (1 << 14) ? "slum " : "",
426f2105c61SSimon Glass cap & (1 << 13) ? "part " : "",
427f2105c61SSimon Glass cap & (1 << 7) ? "ccc " : "",
428f2105c61SSimon Glass cap & (1 << 6) ? "ems " : "",
429f2105c61SSimon Glass cap & (1 << 5) ? "sxs " : "",
430f2105c61SSimon Glass cap2 & (1 << 2) ? "apst " : "",
431f2105c61SSimon Glass cap2 & (1 << 1) ? "nvmp " : "",
432f2105c61SSimon Glass cap2 & (1 << 0) ? "boh " : "");
433f2105c61SSimon Glass }
434f2105c61SSimon Glass
435745a94f3SSimon Glass #if defined(CONFIG_DM_SCSI) || !defined(CONFIG_SCSI_AHCI_PLAT)
436f2105c61SSimon Glass # if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI)
ahci_init_one(struct ahci_uc_priv * uc_priv,struct udevice * dev)4374279efc4SSimon Glass static int ahci_init_one(struct ahci_uc_priv *uc_priv, struct udevice *dev)
438f2105c61SSimon Glass # else
4394279efc4SSimon Glass static int ahci_init_one(struct ahci_uc_priv *uc_priv, pci_dev_t dev)
440f2105c61SSimon Glass # endif
441f2105c61SSimon Glass {
442f2105c61SSimon Glass #if !defined(CONFIG_DM_SCSI)
443f2105c61SSimon Glass u16 vendor;
444f2105c61SSimon Glass #endif
445f2105c61SSimon Glass int rc;
446f2105c61SSimon Glass
447225b1da7SSimon Glass uc_priv->dev = dev;
448f2105c61SSimon Glass
449225b1da7SSimon Glass uc_priv->host_flags = ATA_FLAG_SATA
450f2105c61SSimon Glass | ATA_FLAG_NO_LEGACY
451f2105c61SSimon Glass | ATA_FLAG_MMIO
452f2105c61SSimon Glass | ATA_FLAG_PIO_DMA
453f2105c61SSimon Glass | ATA_FLAG_NO_ATAPI;
454225b1da7SSimon Glass uc_priv->pio_mask = 0x1f;
455225b1da7SSimon Glass uc_priv->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */
456f2105c61SSimon Glass
457f2105c61SSimon Glass #if !defined(CONFIG_DM_SCSI)
458f2105c61SSimon Glass #ifdef CONFIG_DM_PCI
459225b1da7SSimon Glass uc_priv->mmio_base = dm_pci_map_bar(dev, PCI_BASE_ADDRESS_5,
460f2105c61SSimon Glass PCI_REGION_MEM);
461f2105c61SSimon Glass
462f2105c61SSimon Glass /* Take from kernel:
463f2105c61SSimon Glass * JMicron-specific fixup:
464f2105c61SSimon Glass * make sure we're in AHCI mode
465f2105c61SSimon Glass */
466f2105c61SSimon Glass dm_pci_read_config16(dev, PCI_VENDOR_ID, &vendor);
467f2105c61SSimon Glass if (vendor == 0x197b)
468f2105c61SSimon Glass dm_pci_write_config8(dev, 0x41, 0xa1);
469f2105c61SSimon Glass #else
470225b1da7SSimon Glass uc_priv->mmio_base = pci_map_bar(dev, PCI_BASE_ADDRESS_5,
471f2105c61SSimon Glass PCI_REGION_MEM);
472f2105c61SSimon Glass
473f2105c61SSimon Glass /* Take from kernel:
474f2105c61SSimon Glass * JMicron-specific fixup:
475f2105c61SSimon Glass * make sure we're in AHCI mode
476f2105c61SSimon Glass */
477f2105c61SSimon Glass pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
478f2105c61SSimon Glass if (vendor == 0x197b)
479f2105c61SSimon Glass pci_write_config_byte(dev, 0x41, 0xa1);
480f2105c61SSimon Glass #endif
481f2105c61SSimon Glass #else
4821dc64f6cSSimon Glass struct scsi_platdata *plat = dev_get_uclass_platdata(dev);
483225b1da7SSimon Glass uc_priv->mmio_base = (void *)plat->base;
484f2105c61SSimon Glass #endif
485f2105c61SSimon Glass
486225b1da7SSimon Glass debug("ahci mmio_base=0x%p\n", uc_priv->mmio_base);
487f2105c61SSimon Glass /* initialize adapter */
488225b1da7SSimon Glass rc = ahci_host_init(uc_priv);
489f2105c61SSimon Glass if (rc)
490f2105c61SSimon Glass goto err_out;
491f2105c61SSimon Glass
492225b1da7SSimon Glass ahci_print_info(uc_priv);
493f2105c61SSimon Glass
494f2105c61SSimon Glass return 0;
495f2105c61SSimon Glass
496f2105c61SSimon Glass err_out:
497f2105c61SSimon Glass return rc;
498f2105c61SSimon Glass }
499f2105c61SSimon Glass #endif
500f2105c61SSimon Glass
501f2105c61SSimon Glass #define MAX_DATA_BYTE_COUNT (4*1024*1024)
502f2105c61SSimon Glass
ahci_fill_sg(struct ahci_uc_priv * uc_priv,u8 port,unsigned char * buf,int buf_len)503225b1da7SSimon Glass static int ahci_fill_sg(struct ahci_uc_priv *uc_priv, u8 port,
504225b1da7SSimon Glass unsigned char *buf, int buf_len)
505f2105c61SSimon Glass {
506225b1da7SSimon Glass struct ahci_ioports *pp = &(uc_priv->port[port]);
507f2105c61SSimon Glass struct ahci_sg *ahci_sg = pp->cmd_tbl_sg;
508f2105c61SSimon Glass u32 sg_count;
509f2105c61SSimon Glass int i;
510f2105c61SSimon Glass
511f2105c61SSimon Glass sg_count = ((buf_len - 1) / MAX_DATA_BYTE_COUNT) + 1;
512f2105c61SSimon Glass if (sg_count > AHCI_MAX_SG) {
513f2105c61SSimon Glass printf("Error:Too much sg!\n");
514f2105c61SSimon Glass return -1;
515f2105c61SSimon Glass }
516f2105c61SSimon Glass
517f2105c61SSimon Glass for (i = 0; i < sg_count; i++) {
518f2105c61SSimon Glass ahci_sg->addr =
519f2105c61SSimon Glass cpu_to_le32((unsigned long) buf + i * MAX_DATA_BYTE_COUNT);
520f2105c61SSimon Glass ahci_sg->addr_hi = 0;
521f2105c61SSimon Glass ahci_sg->flags_size = cpu_to_le32(0x3fffff &
522f2105c61SSimon Glass (buf_len < MAX_DATA_BYTE_COUNT
523f2105c61SSimon Glass ? (buf_len - 1)
524f2105c61SSimon Glass : (MAX_DATA_BYTE_COUNT - 1)));
525f2105c61SSimon Glass ahci_sg++;
526f2105c61SSimon Glass buf_len -= MAX_DATA_BYTE_COUNT;
527f2105c61SSimon Glass }
528f2105c61SSimon Glass
529f2105c61SSimon Glass return sg_count;
530f2105c61SSimon Glass }
531f2105c61SSimon Glass
532f2105c61SSimon Glass
ahci_fill_cmd_slot(struct ahci_ioports * pp,u32 opts)533f2105c61SSimon Glass static void ahci_fill_cmd_slot(struct ahci_ioports *pp, u32 opts)
534f2105c61SSimon Glass {
535f2105c61SSimon Glass pp->cmd_slot->opts = cpu_to_le32(opts);
536f2105c61SSimon Glass pp->cmd_slot->status = 0;
537f2105c61SSimon Glass pp->cmd_slot->tbl_addr = cpu_to_le32((u32)pp->cmd_tbl & 0xffffffff);
538f2105c61SSimon Glass #ifdef CONFIG_PHYS_64BIT
539f2105c61SSimon Glass pp->cmd_slot->tbl_addr_hi =
540f2105c61SSimon Glass cpu_to_le32((u32)(((pp->cmd_tbl) >> 16) >> 16));
541f2105c61SSimon Glass #endif
542f2105c61SSimon Glass }
543f2105c61SSimon Glass
wait_spinup(void __iomem * port_mmio)544f2105c61SSimon Glass static int wait_spinup(void __iomem *port_mmio)
545f2105c61SSimon Glass {
546f2105c61SSimon Glass ulong start;
547f2105c61SSimon Glass u32 tf_data;
548f2105c61SSimon Glass
549f2105c61SSimon Glass start = get_timer(0);
550f2105c61SSimon Glass do {
551f2105c61SSimon Glass tf_data = readl(port_mmio + PORT_TFDATA);
552f2105c61SSimon Glass if (!(tf_data & ATA_BUSY))
553f2105c61SSimon Glass return 0;
554f2105c61SSimon Glass } while (get_timer(start) < WAIT_MS_SPINUP);
555f2105c61SSimon Glass
556f2105c61SSimon Glass return -ETIMEDOUT;
557f2105c61SSimon Glass }
558f2105c61SSimon Glass
ahci_port_start(struct ahci_uc_priv * uc_priv,u8 port)559225b1da7SSimon Glass static int ahci_port_start(struct ahci_uc_priv *uc_priv, u8 port)
560f2105c61SSimon Glass {
561225b1da7SSimon Glass struct ahci_ioports *pp = &(uc_priv->port[port]);
562f2105c61SSimon Glass void __iomem *port_mmio = pp->port_mmio;
563f2105c61SSimon Glass u32 port_status;
564f2105c61SSimon Glass void __iomem *mem;
565f2105c61SSimon Glass
566f2105c61SSimon Glass debug("Enter start port: %d\n", port);
567f2105c61SSimon Glass port_status = readl(port_mmio + PORT_SCR_STAT);
568f2105c61SSimon Glass debug("Port %d status: %x\n", port, port_status);
569f2105c61SSimon Glass if ((port_status & 0xf) != 0x03) {
570f2105c61SSimon Glass printf("No Link on this port!\n");
571f2105c61SSimon Glass return -1;
572f2105c61SSimon Glass }
573f2105c61SSimon Glass
574f2105c61SSimon Glass mem = malloc(AHCI_PORT_PRIV_DMA_SZ + 2048);
575f2105c61SSimon Glass if (!mem) {
576f2105c61SSimon Glass free(pp);
577f2105c61SSimon Glass printf("%s: No mem for table!\n", __func__);
578f2105c61SSimon Glass return -ENOMEM;
579f2105c61SSimon Glass }
580f2105c61SSimon Glass
581f2105c61SSimon Glass /* Aligned to 2048-bytes */
582f2105c61SSimon Glass mem = memalign(2048, AHCI_PORT_PRIV_DMA_SZ);
583f2105c61SSimon Glass memset(mem, 0, AHCI_PORT_PRIV_DMA_SZ);
584f2105c61SSimon Glass
585f2105c61SSimon Glass /*
586f2105c61SSimon Glass * First item in chunk of DMA memory: 32-slot command table,
587f2105c61SSimon Glass * 32 bytes each in size
588f2105c61SSimon Glass */
589f2105c61SSimon Glass pp->cmd_slot =
590f2105c61SSimon Glass (struct ahci_cmd_hdr *)(uintptr_t)virt_to_phys((void *)mem);
591f2105c61SSimon Glass debug("cmd_slot = %p\n", pp->cmd_slot);
592f2105c61SSimon Glass mem += (AHCI_CMD_SLOT_SZ + 224);
593f2105c61SSimon Glass
594f2105c61SSimon Glass /*
595f2105c61SSimon Glass * Second item: Received-FIS area
596f2105c61SSimon Glass */
597f2105c61SSimon Glass pp->rx_fis = virt_to_phys((void *)mem);
598f2105c61SSimon Glass mem += AHCI_RX_FIS_SZ;
599f2105c61SSimon Glass
600f2105c61SSimon Glass /*
601f2105c61SSimon Glass * Third item: data area for storing a single command
602f2105c61SSimon Glass * and its scatter-gather table
603f2105c61SSimon Glass */
604f2105c61SSimon Glass pp->cmd_tbl = virt_to_phys((void *)mem);
605f2105c61SSimon Glass debug("cmd_tbl_dma = %lx\n", pp->cmd_tbl);
606f2105c61SSimon Glass
607f2105c61SSimon Glass mem += AHCI_CMD_TBL_HDR;
608f2105c61SSimon Glass pp->cmd_tbl_sg =
609f2105c61SSimon Glass (struct ahci_sg *)(uintptr_t)virt_to_phys((void *)mem);
610f2105c61SSimon Glass
611f2105c61SSimon Glass writel_with_flush((unsigned long)pp->cmd_slot,
612f2105c61SSimon Glass port_mmio + PORT_LST_ADDR);
613f2105c61SSimon Glass
614f2105c61SSimon Glass writel_with_flush(pp->rx_fis, port_mmio + PORT_FIS_ADDR);
615f2105c61SSimon Glass
616f2105c61SSimon Glass #ifdef CONFIG_SUNXI_AHCI
617f2105c61SSimon Glass sunxi_dma_init(port_mmio);
618f2105c61SSimon Glass #endif
619f2105c61SSimon Glass
620f2105c61SSimon Glass writel_with_flush(PORT_CMD_ICC_ACTIVE | PORT_CMD_FIS_RX |
621f2105c61SSimon Glass PORT_CMD_POWER_ON | PORT_CMD_SPIN_UP |
622f2105c61SSimon Glass PORT_CMD_START, port_mmio + PORT_CMD);
623f2105c61SSimon Glass
624f2105c61SSimon Glass debug("Exit start port %d\n", port);
625f2105c61SSimon Glass
626f2105c61SSimon Glass /*
627f2105c61SSimon Glass * Make sure interface is not busy based on error and status
628f2105c61SSimon Glass * information from task file data register before proceeding
629f2105c61SSimon Glass */
630f2105c61SSimon Glass return wait_spinup(port_mmio);
631f2105c61SSimon Glass }
632f2105c61SSimon Glass
633f2105c61SSimon Glass
ahci_device_data_io(struct ahci_uc_priv * uc_priv,u8 port,u8 * fis,int fis_len,u8 * buf,int buf_len,u8 is_write)634225b1da7SSimon Glass static int ahci_device_data_io(struct ahci_uc_priv *uc_priv, u8 port, u8 *fis,
635225b1da7SSimon Glass int fis_len, u8 *buf, int buf_len, u8 is_write)
636f2105c61SSimon Glass {
637f2105c61SSimon Glass
638225b1da7SSimon Glass struct ahci_ioports *pp = &(uc_priv->port[port]);
639f2105c61SSimon Glass void __iomem *port_mmio = pp->port_mmio;
640f2105c61SSimon Glass u32 opts;
641f2105c61SSimon Glass u32 port_status;
642f2105c61SSimon Glass int sg_count;
643f2105c61SSimon Glass
644f2105c61SSimon Glass debug("Enter %s: for port %d\n", __func__, port);
645f2105c61SSimon Glass
646225b1da7SSimon Glass if (port > uc_priv->n_ports) {
647f2105c61SSimon Glass printf("Invalid port number %d\n", port);
648f2105c61SSimon Glass return -1;
649f2105c61SSimon Glass }
650f2105c61SSimon Glass
651f2105c61SSimon Glass port_status = readl(port_mmio + PORT_SCR_STAT);
652f2105c61SSimon Glass if ((port_status & 0xf) != 0x03) {
653f2105c61SSimon Glass debug("No Link on port %d!\n", port);
654f2105c61SSimon Glass return -1;
655f2105c61SSimon Glass }
656f2105c61SSimon Glass
657f2105c61SSimon Glass memcpy((unsigned char *)pp->cmd_tbl, fis, fis_len);
658f2105c61SSimon Glass
659225b1da7SSimon Glass sg_count = ahci_fill_sg(uc_priv, port, buf, buf_len);
660f2105c61SSimon Glass opts = (fis_len >> 2) | (sg_count << 16) | (is_write << 6);
661f2105c61SSimon Glass ahci_fill_cmd_slot(pp, opts);
662f2105c61SSimon Glass
663f2105c61SSimon Glass ahci_dcache_flush_sata_cmd(pp);
664f2105c61SSimon Glass ahci_dcache_flush_range((unsigned long)buf, (unsigned long)buf_len);
665f2105c61SSimon Glass
666f2105c61SSimon Glass writel_with_flush(1, port_mmio + PORT_CMD_ISSUE);
667f2105c61SSimon Glass
668f2105c61SSimon Glass if (waiting_for_cmd_completed(port_mmio + PORT_CMD_ISSUE,
669f2105c61SSimon Glass WAIT_MS_DATAIO, 0x1)) {
670f2105c61SSimon Glass printf("timeout exit!\n");
671f2105c61SSimon Glass return -1;
672f2105c61SSimon Glass }
673f2105c61SSimon Glass
674f2105c61SSimon Glass ahci_dcache_invalidate_range((unsigned long)buf,
675f2105c61SSimon Glass (unsigned long)buf_len);
676f2105c61SSimon Glass debug("%s: %d byte transferred.\n", __func__, pp->cmd_slot->status);
677f2105c61SSimon Glass
678f2105c61SSimon Glass return 0;
679f2105c61SSimon Glass }
680f2105c61SSimon Glass
681f2105c61SSimon Glass
ata_id_strcpy(u16 * target,u16 * src,int len)682f2105c61SSimon Glass static char *ata_id_strcpy(u16 *target, u16 *src, int len)
683f2105c61SSimon Glass {
684f2105c61SSimon Glass int i;
685f2105c61SSimon Glass for (i = 0; i < len / 2; i++)
686f2105c61SSimon Glass target[i] = swab16(src[i]);
687f2105c61SSimon Glass return (char *)target;
688f2105c61SSimon Glass }
689f2105c61SSimon Glass
690f2105c61SSimon Glass /*
691f2105c61SSimon Glass * SCSI INQUIRY command operation.
692f2105c61SSimon Glass */
ata_scsiop_inquiry(struct ahci_uc_priv * uc_priv,struct scsi_cmd * pccb)6934b62b2ffSSimon Glass static int ata_scsiop_inquiry(struct ahci_uc_priv *uc_priv,
6944b62b2ffSSimon Glass struct scsi_cmd *pccb)
695f2105c61SSimon Glass {
696f2105c61SSimon Glass static const u8 hdr[] = {
697f2105c61SSimon Glass 0,
698f2105c61SSimon Glass 0,
699f2105c61SSimon Glass 0x5, /* claim SPC-3 version compatibility */
700f2105c61SSimon Glass 2,
701f2105c61SSimon Glass 95 - 4,
702f2105c61SSimon Glass };
703f2105c61SSimon Glass u8 fis[20];
704f2105c61SSimon Glass u16 *idbuf;
705f2105c61SSimon Glass ALLOC_CACHE_ALIGN_BUFFER(u16, tmpid, ATA_ID_WORDS);
706f2105c61SSimon Glass u8 port;
707f2105c61SSimon Glass
708f2105c61SSimon Glass /* Clean ccb data buffer */
709f2105c61SSimon Glass memset(pccb->pdata, 0, pccb->datalen);
710f2105c61SSimon Glass
711f2105c61SSimon Glass memcpy(pccb->pdata, hdr, sizeof(hdr));
712f2105c61SSimon Glass
713f2105c61SSimon Glass if (pccb->datalen <= 35)
714f2105c61SSimon Glass return 0;
715f2105c61SSimon Glass
716f2105c61SSimon Glass memset(fis, 0, sizeof(fis));
717f2105c61SSimon Glass /* Construct the FIS */
718f2105c61SSimon Glass fis[0] = 0x27; /* Host to device FIS. */
719f2105c61SSimon Glass fis[1] = 1 << 7; /* Command FIS. */
720f2105c61SSimon Glass fis[2] = ATA_CMD_ID_ATA; /* Command byte. */
721f2105c61SSimon Glass
722f2105c61SSimon Glass /* Read id from sata */
723f2105c61SSimon Glass port = pccb->target;
724f2105c61SSimon Glass
725225b1da7SSimon Glass if (ahci_device_data_io(uc_priv, port, (u8 *)&fis, sizeof(fis),
726225b1da7SSimon Glass (u8 *)tmpid, ATA_ID_WORDS * 2, 0)) {
727f2105c61SSimon Glass debug("scsi_ahci: SCSI inquiry command failure.\n");
728f2105c61SSimon Glass return -EIO;
729f2105c61SSimon Glass }
730f2105c61SSimon Glass
7314b62b2ffSSimon Glass if (!uc_priv->ataid[port]) {
7324b62b2ffSSimon Glass uc_priv->ataid[port] = malloc(ATA_ID_WORDS * 2);
7334b62b2ffSSimon Glass if (!uc_priv->ataid[port]) {
734f2105c61SSimon Glass printf("%s: No memory for ataid[port]\n", __func__);
735f2105c61SSimon Glass return -ENOMEM;
736f2105c61SSimon Glass }
737f2105c61SSimon Glass }
738f2105c61SSimon Glass
7394b62b2ffSSimon Glass idbuf = uc_priv->ataid[port];
740f2105c61SSimon Glass
741f2105c61SSimon Glass memcpy(idbuf, tmpid, ATA_ID_WORDS * 2);
742f2105c61SSimon Glass ata_swap_buf_le16(idbuf, ATA_ID_WORDS);
743f2105c61SSimon Glass
744f2105c61SSimon Glass memcpy(&pccb->pdata[8], "ATA ", 8);
745f2105c61SSimon Glass ata_id_strcpy((u16 *)&pccb->pdata[16], &idbuf[ATA_ID_PROD], 16);
746f2105c61SSimon Glass ata_id_strcpy((u16 *)&pccb->pdata[32], &idbuf[ATA_ID_FW_REV], 4);
747f2105c61SSimon Glass
748f2105c61SSimon Glass #ifdef DEBUG
749f2105c61SSimon Glass ata_dump_id(idbuf);
750f2105c61SSimon Glass #endif
751f2105c61SSimon Glass return 0;
752f2105c61SSimon Glass }
753f2105c61SSimon Glass
754f2105c61SSimon Glass
755f2105c61SSimon Glass /*
756f2105c61SSimon Glass * SCSI READ10/WRITE10 command operation.
757f2105c61SSimon Glass */
ata_scsiop_read_write(struct ahci_uc_priv * uc_priv,struct scsi_cmd * pccb,u8 is_write)758225b1da7SSimon Glass static int ata_scsiop_read_write(struct ahci_uc_priv *uc_priv,
759225b1da7SSimon Glass struct scsi_cmd *pccb, u8 is_write)
760f2105c61SSimon Glass {
761f2105c61SSimon Glass lbaint_t lba = 0;
762f2105c61SSimon Glass u16 blocks = 0;
763f2105c61SSimon Glass u8 fis[20];
764f2105c61SSimon Glass u8 *user_buffer = pccb->pdata;
765f2105c61SSimon Glass u32 user_buffer_size = pccb->datalen;
766f2105c61SSimon Glass
767f2105c61SSimon Glass /* Retrieve the base LBA number from the ccb structure. */
768f2105c61SSimon Glass if (pccb->cmd[0] == SCSI_READ16) {
769f2105c61SSimon Glass memcpy(&lba, pccb->cmd + 2, 8);
770f2105c61SSimon Glass lba = be64_to_cpu(lba);
771f2105c61SSimon Glass } else {
772f2105c61SSimon Glass u32 temp;
773f2105c61SSimon Glass memcpy(&temp, pccb->cmd + 2, 4);
774f2105c61SSimon Glass lba = be32_to_cpu(temp);
775f2105c61SSimon Glass }
776f2105c61SSimon Glass
777f2105c61SSimon Glass /*
778f2105c61SSimon Glass * Retrieve the base LBA number and the block count from
779f2105c61SSimon Glass * the ccb structure.
780f2105c61SSimon Glass *
781f2105c61SSimon Glass * For 10-byte and 16-byte SCSI R/W commands, transfer
782f2105c61SSimon Glass * length 0 means transfer 0 block of data.
783f2105c61SSimon Glass * However, for ATA R/W commands, sector count 0 means
784f2105c61SSimon Glass * 256 or 65536 sectors, not 0 sectors as in SCSI.
785f2105c61SSimon Glass *
786f2105c61SSimon Glass * WARNING: one or two older ATA drives treat 0 as 0...
787f2105c61SSimon Glass */
788f2105c61SSimon Glass if (pccb->cmd[0] == SCSI_READ16)
789f2105c61SSimon Glass blocks = (((u16)pccb->cmd[13]) << 8) | ((u16) pccb->cmd[14]);
790f2105c61SSimon Glass else
791f2105c61SSimon Glass blocks = (((u16)pccb->cmd[7]) << 8) | ((u16) pccb->cmd[8]);
792f2105c61SSimon Glass
793f2105c61SSimon Glass debug("scsi_ahci: %s %u blocks starting from lba 0x" LBAFU "\n",
794f2105c61SSimon Glass is_write ? "write" : "read", blocks, lba);
795f2105c61SSimon Glass
796f2105c61SSimon Glass /* Preset the FIS */
797f2105c61SSimon Glass memset(fis, 0, sizeof(fis));
798f2105c61SSimon Glass fis[0] = 0x27; /* Host to device FIS. */
799f2105c61SSimon Glass fis[1] = 1 << 7; /* Command FIS. */
800f2105c61SSimon Glass /* Command byte (read/write). */
801f2105c61SSimon Glass fis[2] = is_write ? ATA_CMD_WRITE_EXT : ATA_CMD_READ_EXT;
802f2105c61SSimon Glass
803f2105c61SSimon Glass while (blocks) {
804f2105c61SSimon Glass u16 now_blocks; /* number of blocks per iteration */
805f2105c61SSimon Glass u32 transfer_size; /* number of bytes per iteration */
806f2105c61SSimon Glass
807f2105c61SSimon Glass now_blocks = min((u16)MAX_SATA_BLOCKS_READ_WRITE, blocks);
808f2105c61SSimon Glass
809f2105c61SSimon Glass transfer_size = ATA_SECT_SIZE * now_blocks;
810f2105c61SSimon Glass if (transfer_size > user_buffer_size) {
811f2105c61SSimon Glass printf("scsi_ahci: Error: buffer too small.\n");
812f2105c61SSimon Glass return -EIO;
813f2105c61SSimon Glass }
814f2105c61SSimon Glass
815f2105c61SSimon Glass /*
816f2105c61SSimon Glass * LBA48 SATA command but only use 32bit address range within
817f2105c61SSimon Glass * that (unless we've enabled 64bit LBA support). The next
818f2105c61SSimon Glass * smaller command range (28bit) is too small.
819f2105c61SSimon Glass */
820f2105c61SSimon Glass fis[4] = (lba >> 0) & 0xff;
821f2105c61SSimon Glass fis[5] = (lba >> 8) & 0xff;
822f2105c61SSimon Glass fis[6] = (lba >> 16) & 0xff;
823f2105c61SSimon Glass fis[7] = 1 << 6; /* device reg: set LBA mode */
824f2105c61SSimon Glass fis[8] = ((lba >> 24) & 0xff);
825f2105c61SSimon Glass #ifdef CONFIG_SYS_64BIT_LBA
826f2105c61SSimon Glass if (pccb->cmd[0] == SCSI_READ16) {
827f2105c61SSimon Glass fis[9] = ((lba >> 32) & 0xff);
828f2105c61SSimon Glass fis[10] = ((lba >> 40) & 0xff);
829f2105c61SSimon Glass }
830f2105c61SSimon Glass #endif
831f2105c61SSimon Glass
832f2105c61SSimon Glass fis[3] = 0xe0; /* features */
833f2105c61SSimon Glass
834f2105c61SSimon Glass /* Block (sector) count */
835f2105c61SSimon Glass fis[12] = (now_blocks >> 0) & 0xff;
836f2105c61SSimon Glass fis[13] = (now_blocks >> 8) & 0xff;
837f2105c61SSimon Glass
838f2105c61SSimon Glass /* Read/Write from ahci */
839225b1da7SSimon Glass if (ahci_device_data_io(uc_priv, pccb->target, (u8 *)&fis,
840225b1da7SSimon Glass sizeof(fis), user_buffer, transfer_size,
841f2105c61SSimon Glass is_write)) {
842f2105c61SSimon Glass debug("scsi_ahci: SCSI %s10 command failure.\n",
843f2105c61SSimon Glass is_write ? "WRITE" : "READ");
844f2105c61SSimon Glass return -EIO;
845f2105c61SSimon Glass }
846f2105c61SSimon Glass
847f2105c61SSimon Glass /* If this transaction is a write, do a following flush.
848f2105c61SSimon Glass * Writes in u-boot are so rare, and the logic to know when is
849f2105c61SSimon Glass * the last write and do a flush only there is sufficiently
850f2105c61SSimon Glass * difficult. Just do a flush after every write. This incurs,
851f2105c61SSimon Glass * usually, one extra flush when the rare writes do happen.
852f2105c61SSimon Glass */
853f2105c61SSimon Glass if (is_write) {
854225b1da7SSimon Glass if (-EIO == ata_io_flush(uc_priv, pccb->target))
855f2105c61SSimon Glass return -EIO;
856f2105c61SSimon Glass }
857f2105c61SSimon Glass user_buffer += transfer_size;
858f2105c61SSimon Glass user_buffer_size -= transfer_size;
859f2105c61SSimon Glass blocks -= now_blocks;
860f2105c61SSimon Glass lba += now_blocks;
861f2105c61SSimon Glass }
862f2105c61SSimon Glass
863f2105c61SSimon Glass return 0;
864f2105c61SSimon Glass }
865f2105c61SSimon Glass
866f2105c61SSimon Glass
867f2105c61SSimon Glass /*
868f2105c61SSimon Glass * SCSI READ CAPACITY10 command operation.
869f2105c61SSimon Glass */
ata_scsiop_read_capacity10(struct ahci_uc_priv * uc_priv,struct scsi_cmd * pccb)8704b62b2ffSSimon Glass static int ata_scsiop_read_capacity10(struct ahci_uc_priv *uc_priv,
8714b62b2ffSSimon Glass struct scsi_cmd *pccb)
872f2105c61SSimon Glass {
873f2105c61SSimon Glass u32 cap;
874f2105c61SSimon Glass u64 cap64;
875f2105c61SSimon Glass u32 block_size;
876f2105c61SSimon Glass
8774b62b2ffSSimon Glass if (!uc_priv->ataid[pccb->target]) {
878f2105c61SSimon Glass printf("scsi_ahci: SCSI READ CAPACITY10 command failure. "
879f2105c61SSimon Glass "\tNo ATA info!\n"
880f2105c61SSimon Glass "\tPlease run SCSI command INQUIRY first!\n");
881f2105c61SSimon Glass return -EPERM;
882f2105c61SSimon Glass }
883f2105c61SSimon Glass
8844b62b2ffSSimon Glass cap64 = ata_id_n_sectors(uc_priv->ataid[pccb->target]);
885f2105c61SSimon Glass if (cap64 > 0x100000000ULL)
886f2105c61SSimon Glass cap64 = 0xffffffff;
887f2105c61SSimon Glass
888f2105c61SSimon Glass cap = cpu_to_be32(cap64);
889f2105c61SSimon Glass memcpy(pccb->pdata, &cap, sizeof(cap));
890f2105c61SSimon Glass
891f2105c61SSimon Glass block_size = cpu_to_be32((u32)512);
892f2105c61SSimon Glass memcpy(&pccb->pdata[4], &block_size, 4);
893f2105c61SSimon Glass
894f2105c61SSimon Glass return 0;
895f2105c61SSimon Glass }
896f2105c61SSimon Glass
897f2105c61SSimon Glass
898f2105c61SSimon Glass /*
899f2105c61SSimon Glass * SCSI READ CAPACITY16 command operation.
900f2105c61SSimon Glass */
ata_scsiop_read_capacity16(struct ahci_uc_priv * uc_priv,struct scsi_cmd * pccb)9014b62b2ffSSimon Glass static int ata_scsiop_read_capacity16(struct ahci_uc_priv *uc_priv,
9024b62b2ffSSimon Glass struct scsi_cmd *pccb)
903f2105c61SSimon Glass {
904f2105c61SSimon Glass u64 cap;
905f2105c61SSimon Glass u64 block_size;
906f2105c61SSimon Glass
9074b62b2ffSSimon Glass if (!uc_priv->ataid[pccb->target]) {
908f2105c61SSimon Glass printf("scsi_ahci: SCSI READ CAPACITY16 command failure. "
909f2105c61SSimon Glass "\tNo ATA info!\n"
910f2105c61SSimon Glass "\tPlease run SCSI command INQUIRY first!\n");
911f2105c61SSimon Glass return -EPERM;
912f2105c61SSimon Glass }
913f2105c61SSimon Glass
9144b62b2ffSSimon Glass cap = ata_id_n_sectors(uc_priv->ataid[pccb->target]);
915f2105c61SSimon Glass cap = cpu_to_be64(cap);
916f2105c61SSimon Glass memcpy(pccb->pdata, &cap, sizeof(cap));
917f2105c61SSimon Glass
918f2105c61SSimon Glass block_size = cpu_to_be64((u64)512);
919f2105c61SSimon Glass memcpy(&pccb->pdata[8], &block_size, 8);
920f2105c61SSimon Glass
921f2105c61SSimon Glass return 0;
922f2105c61SSimon Glass }
923f2105c61SSimon Glass
924f2105c61SSimon Glass
925f2105c61SSimon Glass /*
926f2105c61SSimon Glass * SCSI TEST UNIT READY command operation.
927f2105c61SSimon Glass */
ata_scsiop_test_unit_ready(struct ahci_uc_priv * uc_priv,struct scsi_cmd * pccb)9284b62b2ffSSimon Glass static int ata_scsiop_test_unit_ready(struct ahci_uc_priv *uc_priv,
9294b62b2ffSSimon Glass struct scsi_cmd *pccb)
930f2105c61SSimon Glass {
9314b62b2ffSSimon Glass return (uc_priv->ataid[pccb->target]) ? 0 : -EPERM;
932f2105c61SSimon Glass }
933f2105c61SSimon Glass
934f2105c61SSimon Glass
ahci_scsi_exec(struct udevice * dev,struct scsi_cmd * pccb)9354e749014SSimon Glass static int ahci_scsi_exec(struct udevice *dev, struct scsi_cmd *pccb)
936f2105c61SSimon Glass {
9374682c8a1SSimon Glass struct ahci_uc_priv *uc_priv;
9384682c8a1SSimon Glass #ifdef CONFIG_DM_SCSI
939bfc1c6b4SSimon Glass uc_priv = dev_get_uclass_priv(dev->parent);
9404682c8a1SSimon Glass #else
9414682c8a1SSimon Glass uc_priv = probe_ent;
9424682c8a1SSimon Glass #endif
943f2105c61SSimon Glass int ret;
944f2105c61SSimon Glass
945f2105c61SSimon Glass switch (pccb->cmd[0]) {
946f2105c61SSimon Glass case SCSI_READ16:
947f2105c61SSimon Glass case SCSI_READ10:
948225b1da7SSimon Glass ret = ata_scsiop_read_write(uc_priv, pccb, 0);
949f2105c61SSimon Glass break;
950f2105c61SSimon Glass case SCSI_WRITE10:
951225b1da7SSimon Glass ret = ata_scsiop_read_write(uc_priv, pccb, 1);
952f2105c61SSimon Glass break;
953f2105c61SSimon Glass case SCSI_RD_CAPAC10:
9544b62b2ffSSimon Glass ret = ata_scsiop_read_capacity10(uc_priv, pccb);
955f2105c61SSimon Glass break;
956f2105c61SSimon Glass case SCSI_RD_CAPAC16:
9574b62b2ffSSimon Glass ret = ata_scsiop_read_capacity16(uc_priv, pccb);
958f2105c61SSimon Glass break;
959f2105c61SSimon Glass case SCSI_TST_U_RDY:
9604b62b2ffSSimon Glass ret = ata_scsiop_test_unit_ready(uc_priv, pccb);
961f2105c61SSimon Glass break;
962f2105c61SSimon Glass case SCSI_INQUIRY:
9634b62b2ffSSimon Glass ret = ata_scsiop_inquiry(uc_priv, pccb);
964f2105c61SSimon Glass break;
965f2105c61SSimon Glass default:
966f2105c61SSimon Glass printf("Unsupport SCSI command 0x%02x\n", pccb->cmd[0]);
967f6580ef3SSimon Glass return -ENOTSUPP;
968f2105c61SSimon Glass }
969f2105c61SSimon Glass
970f2105c61SSimon Glass if (ret) {
971f2105c61SSimon Glass debug("SCSI command 0x%02x ret errno %d\n", pccb->cmd[0], ret);
972f6580ef3SSimon Glass return ret;
973f2105c61SSimon Glass }
974f6580ef3SSimon Glass return 0;
975f2105c61SSimon Glass
976f2105c61SSimon Glass }
977f2105c61SSimon Glass
ahci_start_ports(struct ahci_uc_priv * uc_priv)97862b4ec8eSSimon Glass static int ahci_start_ports(struct ahci_uc_priv *uc_priv)
97962b4ec8eSSimon Glass {
98062b4ec8eSSimon Glass u32 linkmap;
98162b4ec8eSSimon Glass int i;
98262b4ec8eSSimon Glass
98362b4ec8eSSimon Glass linkmap = uc_priv->link_port_map;
98462b4ec8eSSimon Glass
9858bf207d2STuomas Tynkkynen for (i = 0; i < uc_priv->n_ports; i++) {
98662b4ec8eSSimon Glass if (((linkmap >> i) & 0x01)) {
98762b4ec8eSSimon Glass if (ahci_port_start(uc_priv, (u8) i)) {
98862b4ec8eSSimon Glass printf("Can not start port %d\n", i);
98962b4ec8eSSimon Glass continue;
99062b4ec8eSSimon Glass }
99162b4ec8eSSimon Glass }
99262b4ec8eSSimon Glass }
99362b4ec8eSSimon Glass
99462b4ec8eSSimon Glass return 0;
99562b4ec8eSSimon Glass }
99662b4ec8eSSimon Glass
9977cf1afceSSimon Glass #ifndef CONFIG_DM_SCSI
scsi_low_level_init(int busdevfunc)998f2105c61SSimon Glass void scsi_low_level_init(int busdevfunc)
999f2105c61SSimon Glass {
1000225b1da7SSimon Glass struct ahci_uc_priv *uc_priv;
1001f2105c61SSimon Glass
1002f2105c61SSimon Glass #ifndef CONFIG_SCSI_AHCI_PLAT
10034279efc4SSimon Glass probe_ent = calloc(1, sizeof(struct ahci_uc_priv));
10044279efc4SSimon Glass if (!probe_ent) {
10054279efc4SSimon Glass printf("%s: No memory for uc_priv\n", __func__);
10064279efc4SSimon Glass return;
10074279efc4SSimon Glass }
10084279efc4SSimon Glass uc_priv = probe_ent;
1009f2105c61SSimon Glass # if defined(CONFIG_DM_PCI)
1010f2105c61SSimon Glass struct udevice *dev;
1011f2105c61SSimon Glass int ret;
1012f2105c61SSimon Glass
1013f2105c61SSimon Glass ret = dm_pci_bus_find_bdf(busdevfunc, &dev);
1014f2105c61SSimon Glass if (ret)
1015f2105c61SSimon Glass return;
10164279efc4SSimon Glass ahci_init_one(uc_priv, dev);
1017f2105c61SSimon Glass # else
10184279efc4SSimon Glass ahci_init_one(uc_priv, busdevfunc);
1019f2105c61SSimon Glass # endif
10204279efc4SSimon Glass #else
1021225b1da7SSimon Glass uc_priv = probe_ent;
10224279efc4SSimon Glass #endif
1023f2105c61SSimon Glass
102462b4ec8eSSimon Glass ahci_start_ports(uc_priv);
1025f2105c61SSimon Glass }
10267cf1afceSSimon Glass #endif
10277cf1afceSSimon Glass
10287cf1afceSSimon Glass #ifndef CONFIG_SCSI_AHCI_PLAT
10297cf1afceSSimon Glass # if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI)
ahci_init_one_dm(struct udevice * dev)1030e81589eaSMichal Simek int ahci_init_one_dm(struct udevice *dev)
10317cf1afceSSimon Glass {
10324279efc4SSimon Glass struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev);
10334279efc4SSimon Glass
10344279efc4SSimon Glass return ahci_init_one(uc_priv, dev);
10357cf1afceSSimon Glass }
10367cf1afceSSimon Glass #endif
10377cf1afceSSimon Glass #endif
10387cf1afceSSimon Glass
ahci_start_ports_dm(struct udevice * dev)1039e81589eaSMichal Simek int ahci_start_ports_dm(struct udevice *dev)
10407cf1afceSSimon Glass {
10414279efc4SSimon Glass struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev);
10427cf1afceSSimon Glass
10437cf1afceSSimon Glass return ahci_start_ports(uc_priv);
10447cf1afceSSimon Glass }
1045f2105c61SSimon Glass
1046f2105c61SSimon Glass #ifdef CONFIG_SCSI_AHCI_PLAT
ahci_init_common(struct ahci_uc_priv * uc_priv,void __iomem * base)10474279efc4SSimon Glass static int ahci_init_common(struct ahci_uc_priv *uc_priv, void __iomem *base)
1048f2105c61SSimon Glass {
10494279efc4SSimon Glass int rc;
1050f2105c61SSimon Glass
1051225b1da7SSimon Glass uc_priv->host_flags = ATA_FLAG_SATA
1052f2105c61SSimon Glass | ATA_FLAG_NO_LEGACY
1053f2105c61SSimon Glass | ATA_FLAG_MMIO
1054f2105c61SSimon Glass | ATA_FLAG_PIO_DMA
1055f2105c61SSimon Glass | ATA_FLAG_NO_ATAPI;
1056225b1da7SSimon Glass uc_priv->pio_mask = 0x1f;
1057225b1da7SSimon Glass uc_priv->udma_mask = 0x7f; /*Fixme,assume to support UDMA6 */
1058f2105c61SSimon Glass
1059225b1da7SSimon Glass uc_priv->mmio_base = base;
1060f2105c61SSimon Glass
1061f2105c61SSimon Glass /* initialize adapter */
1062225b1da7SSimon Glass rc = ahci_host_init(uc_priv);
1063f2105c61SSimon Glass if (rc)
1064f2105c61SSimon Glass goto err_out;
1065f2105c61SSimon Glass
1066225b1da7SSimon Glass ahci_print_info(uc_priv);
1067f2105c61SSimon Glass
106862b4ec8eSSimon Glass rc = ahci_start_ports(uc_priv);
1069f2105c61SSimon Glass
1070f2105c61SSimon Glass err_out:
1071f2105c61SSimon Glass return rc;
1072f2105c61SSimon Glass }
1073f2105c61SSimon Glass
10744279efc4SSimon Glass #ifndef CONFIG_DM_SCSI
ahci_init(void __iomem * base)10754279efc4SSimon Glass int ahci_init(void __iomem *base)
10764279efc4SSimon Glass {
10774279efc4SSimon Glass struct ahci_uc_priv *uc_priv;
10784279efc4SSimon Glass
10794279efc4SSimon Glass probe_ent = malloc(sizeof(struct ahci_uc_priv));
10804279efc4SSimon Glass if (!probe_ent) {
10814279efc4SSimon Glass printf("%s: No memory for uc_priv\n", __func__);
10824279efc4SSimon Glass return -ENOMEM;
10834279efc4SSimon Glass }
10844279efc4SSimon Glass
10854279efc4SSimon Glass uc_priv = probe_ent;
10864279efc4SSimon Glass memset(uc_priv, 0, sizeof(struct ahci_uc_priv));
10874279efc4SSimon Glass
10884279efc4SSimon Glass return ahci_init_common(uc_priv, base);
10894279efc4SSimon Glass }
10904279efc4SSimon Glass #endif
10914279efc4SSimon Glass
ahci_init_dm(struct udevice * dev,void __iomem * base)10924279efc4SSimon Glass int ahci_init_dm(struct udevice *dev, void __iomem *base)
10934279efc4SSimon Glass {
10944279efc4SSimon Glass struct ahci_uc_priv *uc_priv = dev_get_uclass_priv(dev);
10954279efc4SSimon Glass
10964279efc4SSimon Glass return ahci_init_common(uc_priv, base);
10974279efc4SSimon Glass }
10984279efc4SSimon Glass
scsi_init(void)1099f2105c61SSimon Glass void __weak scsi_init(void)
1100f2105c61SSimon Glass {
1101f2105c61SSimon Glass }
1102f2105c61SSimon Glass
11034279efc4SSimon Glass #endif /* CONFIG_SCSI_AHCI_PLAT */
1104f2105c61SSimon Glass
1105f2105c61SSimon Glass /*
1106f2105c61SSimon Glass * In the general case of generic rotating media it makes sense to have a
1107f2105c61SSimon Glass * flush capability. It probably even makes sense in the case of SSDs because
1108f2105c61SSimon Glass * one cannot always know for sure what kind of internal cache/flush mechanism
1109f2105c61SSimon Glass * is embodied therein. At first it was planned to invoke this after the last
1110f2105c61SSimon Glass * write to disk and before rebooting. In practice, knowing, a priori, which
1111f2105c61SSimon Glass * is the last write is difficult. Because writing to the disk in u-boot is
1112f2105c61SSimon Glass * very rare, this flush command will be invoked after every block write.
1113f2105c61SSimon Glass */
ata_io_flush(struct ahci_uc_priv * uc_priv,u8 port)1114225b1da7SSimon Glass static int ata_io_flush(struct ahci_uc_priv *uc_priv, u8 port)
1115f2105c61SSimon Glass {
1116f2105c61SSimon Glass u8 fis[20];
1117225b1da7SSimon Glass struct ahci_ioports *pp = &(uc_priv->port[port]);
1118f2105c61SSimon Glass void __iomem *port_mmio = pp->port_mmio;
1119f2105c61SSimon Glass u32 cmd_fis_len = 5; /* five dwords */
1120f2105c61SSimon Glass
1121f2105c61SSimon Glass /* Preset the FIS */
1122f2105c61SSimon Glass memset(fis, 0, 20);
1123f2105c61SSimon Glass fis[0] = 0x27; /* Host to device FIS. */
1124f2105c61SSimon Glass fis[1] = 1 << 7; /* Command FIS. */
1125f2105c61SSimon Glass fis[2] = ATA_CMD_FLUSH_EXT;
1126f2105c61SSimon Glass
1127f2105c61SSimon Glass memcpy((unsigned char *)pp->cmd_tbl, fis, 20);
1128f2105c61SSimon Glass ahci_fill_cmd_slot(pp, cmd_fis_len);
1129f2105c61SSimon Glass ahci_dcache_flush_sata_cmd(pp);
1130f2105c61SSimon Glass writel_with_flush(1, port_mmio + PORT_CMD_ISSUE);
1131f2105c61SSimon Glass
1132f2105c61SSimon Glass if (waiting_for_cmd_completed(port_mmio + PORT_CMD_ISSUE,
1133f2105c61SSimon Glass WAIT_MS_FLUSH, 0x1)) {
1134f2105c61SSimon Glass debug("scsi_ahci: flush command timeout on port %d.\n", port);
1135f2105c61SSimon Glass return -EIO;
1136f2105c61SSimon Glass }
1137f2105c61SSimon Glass
1138f2105c61SSimon Glass return 0;
1139f2105c61SSimon Glass }
1140f2105c61SSimon Glass
ahci_scsi_bus_reset(struct udevice * dev)11414e749014SSimon Glass static int ahci_scsi_bus_reset(struct udevice *dev)
11424e749014SSimon Glass {
11434e749014SSimon Glass /* Not implemented */
11444e749014SSimon Glass
11454e749014SSimon Glass return 0;
11464e749014SSimon Glass }
11474e749014SSimon Glass
1148f6ab5a92SSimon Glass #ifdef CONFIG_DM_SCSI
ahci_bind_scsi(struct udevice * ahci_dev,struct udevice ** devp)1149681357ffSSimon Glass int ahci_bind_scsi(struct udevice *ahci_dev, struct udevice **devp)
1150681357ffSSimon Glass {
1151681357ffSSimon Glass struct udevice *dev;
1152681357ffSSimon Glass int ret;
1153681357ffSSimon Glass
1154681357ffSSimon Glass ret = device_bind_driver(ahci_dev, "ahci_scsi", "ahci_scsi", &dev);
1155681357ffSSimon Glass if (ret)
1156681357ffSSimon Glass return ret;
1157681357ffSSimon Glass *devp = dev;
1158681357ffSSimon Glass
1159681357ffSSimon Glass return 0;
1160681357ffSSimon Glass }
1161681357ffSSimon Glass
ahci_probe_scsi(struct udevice * ahci_dev,ulong base)1162745a94f3SSimon Glass int ahci_probe_scsi(struct udevice *ahci_dev, ulong base)
1163681357ffSSimon Glass {
1164681357ffSSimon Glass struct ahci_uc_priv *uc_priv;
1165681357ffSSimon Glass struct scsi_platdata *uc_plat;
1166681357ffSSimon Glass struct udevice *dev;
1167681357ffSSimon Glass int ret;
1168681357ffSSimon Glass
1169681357ffSSimon Glass device_find_first_child(ahci_dev, &dev);
1170681357ffSSimon Glass if (!dev)
1171681357ffSSimon Glass return -ENODEV;
1172681357ffSSimon Glass uc_plat = dev_get_uclass_platdata(dev);
1173745a94f3SSimon Glass uc_plat->base = base;
1174681357ffSSimon Glass uc_plat->max_lun = 1;
1175681357ffSSimon Glass uc_plat->max_id = 2;
1176745a94f3SSimon Glass
1177745a94f3SSimon Glass uc_priv = dev_get_uclass_priv(ahci_dev);
1178681357ffSSimon Glass ret = ahci_init_one(uc_priv, dev);
1179681357ffSSimon Glass if (ret)
1180681357ffSSimon Glass return ret;
1181681357ffSSimon Glass ret = ahci_start_ports(uc_priv);
1182681357ffSSimon Glass if (ret)
1183681357ffSSimon Glass return ret;
1184681357ffSSimon Glass
1185681357ffSSimon Glass return 0;
1186681357ffSSimon Glass }
1187681357ffSSimon Glass
1188745a94f3SSimon Glass #ifdef CONFIG_DM_PCI
ahci_probe_scsi_pci(struct udevice * ahci_dev)1189745a94f3SSimon Glass int ahci_probe_scsi_pci(struct udevice *ahci_dev)
1190745a94f3SSimon Glass {
1191745a94f3SSimon Glass ulong base;
1192745a94f3SSimon Glass
1193745a94f3SSimon Glass base = (ulong)dm_pci_map_bar(ahci_dev, PCI_BASE_ADDRESS_5,
1194745a94f3SSimon Glass PCI_REGION_MEM);
1195745a94f3SSimon Glass
1196745a94f3SSimon Glass return ahci_probe_scsi(ahci_dev, base);
1197745a94f3SSimon Glass }
1198745a94f3SSimon Glass #endif
1199745a94f3SSimon Glass
1200f6ab5a92SSimon Glass struct scsi_ops scsi_ops = {
1201f6ab5a92SSimon Glass .exec = ahci_scsi_exec,
1202f6ab5a92SSimon Glass .bus_reset = ahci_scsi_bus_reset,
1203f6ab5a92SSimon Glass };
1204681357ffSSimon Glass
1205681357ffSSimon Glass U_BOOT_DRIVER(ahci_scsi) = {
1206681357ffSSimon Glass .name = "ahci_scsi",
1207681357ffSSimon Glass .id = UCLASS_SCSI,
1208681357ffSSimon Glass .ops = &scsi_ops,
1209681357ffSSimon Glass };
1210f6ab5a92SSimon Glass #else
scsi_exec(struct udevice * dev,struct scsi_cmd * pccb)12114e749014SSimon Glass int scsi_exec(struct udevice *dev, struct scsi_cmd *pccb)
12124e749014SSimon Glass {
12134e749014SSimon Glass return ahci_scsi_exec(dev, pccb);
12144e749014SSimon Glass }
1215f2105c61SSimon Glass
scsi_bus_reset(struct udevice * dev)12164682c8a1SSimon Glass __weak int scsi_bus_reset(struct udevice *dev)
1217f2105c61SSimon Glass {
12184e749014SSimon Glass return ahci_scsi_bus_reset(dev);
12194682c8a1SSimon Glass
12204682c8a1SSimon Glass return 0;
1221f2105c61SSimon Glass }
1222f6ab5a92SSimon Glass #endif
1223