xref: /OK3568_Linux_fs/u-boot/include/ahci.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Copyright (C) Freescale Semiconductor, Inc. 2006.
3*4882a593Smuzhiyun  * Author: Jason Jin<Jason.jin@freescale.com>
4*4882a593Smuzhiyun  *         Zhang Wei<wei.zhang@freescale.com>
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * SPDX-License-Identifier:	GPL-2.0+
7*4882a593Smuzhiyun  */
8*4882a593Smuzhiyun #ifndef _AHCI_H_
9*4882a593Smuzhiyun #define _AHCI_H_
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include <pci.h>
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #define AHCI_PCI_BAR		0x24
14*4882a593Smuzhiyun #define AHCI_MAX_SG		56 /* hardware max is 64K */
15*4882a593Smuzhiyun #define AHCI_CMD_SLOT_SZ	32
16*4882a593Smuzhiyun #define AHCI_MAX_CMD_SLOT	32
17*4882a593Smuzhiyun #define AHCI_RX_FIS_SZ		256
18*4882a593Smuzhiyun #define AHCI_CMD_TBL_HDR	0x80
19*4882a593Smuzhiyun #define AHCI_CMD_TBL_CDB	0x40
20*4882a593Smuzhiyun #define AHCI_CMD_TBL_SZ		AHCI_CMD_TBL_HDR + (AHCI_MAX_SG * 16)
21*4882a593Smuzhiyun #define AHCI_PORT_PRIV_DMA_SZ	(AHCI_CMD_SLOT_SZ * AHCI_MAX_CMD_SLOT + \
22*4882a593Smuzhiyun 				AHCI_CMD_TBL_SZ	+ AHCI_RX_FIS_SZ)
23*4882a593Smuzhiyun #define AHCI_CMD_ATAPI		(1 << 5)
24*4882a593Smuzhiyun #define AHCI_CMD_WRITE		(1 << 6)
25*4882a593Smuzhiyun #define AHCI_CMD_PREFETCH	(1 << 7)
26*4882a593Smuzhiyun #define AHCI_CMD_RESET		(1 << 8)
27*4882a593Smuzhiyun #define AHCI_CMD_CLR_BUSY	(1 << 10)
28*4882a593Smuzhiyun 
29*4882a593Smuzhiyun #define RX_FIS_D2H_REG		0x40	/* offset of D2H Register FIS data */
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun /* Global controller registers */
32*4882a593Smuzhiyun #define HOST_CAP		0x00 /* host capabilities */
33*4882a593Smuzhiyun #define HOST_CTL		0x04 /* global host control */
34*4882a593Smuzhiyun #define HOST_IRQ_STAT		0x08 /* interrupt status */
35*4882a593Smuzhiyun #define HOST_PORTS_IMPL		0x0c /* bitmap of implemented ports */
36*4882a593Smuzhiyun #define HOST_VERSION		0x10 /* AHCI spec. version compliancy */
37*4882a593Smuzhiyun #define HOST_CAP2		0x24 /* host capabilities, extended */
38*4882a593Smuzhiyun 
39*4882a593Smuzhiyun /* HOST_CTL bits */
40*4882a593Smuzhiyun #define HOST_RESET		(1 << 0)  /* reset controller; self-clear */
41*4882a593Smuzhiyun #define HOST_IRQ_EN		(1 << 1)  /* global IRQ enable */
42*4882a593Smuzhiyun #define HOST_AHCI_EN		(1 << 31) /* AHCI enabled */
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun /* Registers for each SATA port */
45*4882a593Smuzhiyun #define PORT_LST_ADDR		0x00 /* command list DMA addr */
46*4882a593Smuzhiyun #define PORT_LST_ADDR_HI	0x04 /* command list DMA addr hi */
47*4882a593Smuzhiyun #define PORT_FIS_ADDR		0x08 /* FIS rx buf addr */
48*4882a593Smuzhiyun #define PORT_FIS_ADDR_HI	0x0c /* FIS rx buf addr hi */
49*4882a593Smuzhiyun #define PORT_IRQ_STAT		0x10 /* interrupt status */
50*4882a593Smuzhiyun #define PORT_IRQ_MASK		0x14 /* interrupt enable/disable mask */
51*4882a593Smuzhiyun #define PORT_CMD		0x18 /* port command */
52*4882a593Smuzhiyun #define PORT_TFDATA		0x20 /* taskfile data */
53*4882a593Smuzhiyun #define PORT_SIG		0x24 /* device TF signature */
54*4882a593Smuzhiyun #define PORT_CMD_ISSUE		0x38 /* command issue */
55*4882a593Smuzhiyun #define PORT_SCR		0x28 /* SATA phy register block */
56*4882a593Smuzhiyun #define PORT_SCR_STAT		0x28 /* SATA phy register: SStatus */
57*4882a593Smuzhiyun #define PORT_SCR_CTL		0x2c /* SATA phy register: SControl */
58*4882a593Smuzhiyun #define PORT_SCR_ERR		0x30 /* SATA phy register: SError */
59*4882a593Smuzhiyun #define PORT_SCR_ACT		0x34 /* SATA phy register: SActive */
60*4882a593Smuzhiyun 
61*4882a593Smuzhiyun #ifdef CONFIG_SUNXI_AHCI
62*4882a593Smuzhiyun #define PORT_P0DMACR		0x70 /* SUNXI specific "DMA register" */
63*4882a593Smuzhiyun #endif
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun /* PORT_IRQ_{STAT,MASK} bits */
66*4882a593Smuzhiyun #define PORT_IRQ_COLD_PRES	(1 << 31) /* cold presence detect */
67*4882a593Smuzhiyun #define PORT_IRQ_TF_ERR		(1 << 30) /* task file error */
68*4882a593Smuzhiyun #define PORT_IRQ_HBUS_ERR	(1 << 29) /* host bus fatal error */
69*4882a593Smuzhiyun #define PORT_IRQ_HBUS_DATA_ERR	(1 << 28) /* host bus data error */
70*4882a593Smuzhiyun #define PORT_IRQ_IF_ERR		(1 << 27) /* interface fatal error */
71*4882a593Smuzhiyun #define PORT_IRQ_IF_NONFATAL	(1 << 26) /* interface non-fatal error */
72*4882a593Smuzhiyun #define PORT_IRQ_OVERFLOW	(1 << 24) /* xfer exhausted available S/G */
73*4882a593Smuzhiyun #define PORT_IRQ_BAD_PMP	(1 << 23) /* incorrect port multiplier */
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun #define PORT_IRQ_PHYRDY		(1 << 22) /* PhyRdy changed */
76*4882a593Smuzhiyun #define PORT_IRQ_DEV_ILCK	(1 << 7) /* device interlock */
77*4882a593Smuzhiyun #define PORT_IRQ_CONNECT	(1 << 6) /* port connect change status */
78*4882a593Smuzhiyun #define PORT_IRQ_SG_DONE	(1 << 5) /* descriptor processed */
79*4882a593Smuzhiyun #define PORT_IRQ_UNK_FIS	(1 << 4) /* unknown FIS rx'd */
80*4882a593Smuzhiyun #define PORT_IRQ_SDB_FIS	(1 << 3) /* Set Device Bits FIS rx'd */
81*4882a593Smuzhiyun #define PORT_IRQ_DMAS_FIS	(1 << 2) /* DMA Setup FIS rx'd */
82*4882a593Smuzhiyun #define PORT_IRQ_PIOS_FIS	(1 << 1) /* PIO Setup FIS rx'd */
83*4882a593Smuzhiyun #define PORT_IRQ_D2H_REG_FIS	(1 << 0) /* D2H Register FIS rx'd */
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun #define PORT_IRQ_FATAL		PORT_IRQ_TF_ERR | PORT_IRQ_HBUS_ERR	\
86*4882a593Smuzhiyun 				| PORT_IRQ_HBUS_DATA_ERR | PORT_IRQ_IF_ERR
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun #define DEF_PORT_IRQ		PORT_IRQ_FATAL | PORT_IRQ_PHYRDY	\
89*4882a593Smuzhiyun 				| PORT_IRQ_CONNECT | PORT_IRQ_SG_DONE	\
90*4882a593Smuzhiyun 				| PORT_IRQ_UNK_FIS | PORT_IRQ_SDB_FIS	\
91*4882a593Smuzhiyun 				| PORT_IRQ_DMAS_FIS | PORT_IRQ_PIOS_FIS	\
92*4882a593Smuzhiyun 				| PORT_IRQ_D2H_REG_FIS
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun /* PORT_SCR_STAT bits */
95*4882a593Smuzhiyun #define PORT_SCR_STAT_DET_MASK	0x3
96*4882a593Smuzhiyun #define PORT_SCR_STAT_DET_COMINIT 0x1
97*4882a593Smuzhiyun #define PORT_SCR_STAT_DET_PHYRDY 0x3
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun /* PORT_CMD bits */
100*4882a593Smuzhiyun #define PORT_CMD_ATAPI		(1 << 24) /* Device is ATAPI */
101*4882a593Smuzhiyun #define PORT_CMD_LIST_ON	(1 << 15) /* cmd list DMA engine running */
102*4882a593Smuzhiyun #define PORT_CMD_FIS_ON		(1 << 14) /* FIS DMA engine running */
103*4882a593Smuzhiyun #define PORT_CMD_FIS_RX		(1 << 4) /* Enable FIS receive DMA engine */
104*4882a593Smuzhiyun #define PORT_CMD_CLO		(1 << 3) /* Command list override */
105*4882a593Smuzhiyun #define PORT_CMD_POWER_ON	(1 << 2) /* Power up device */
106*4882a593Smuzhiyun #define PORT_CMD_SPIN_UP	(1 << 1) /* Spin up device */
107*4882a593Smuzhiyun #define PORT_CMD_START		(1 << 0) /* Enable port DMA engine */
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun #define PORT_CMD_ICC_ACTIVE	(0x1 << 28) /* Put i/f in active state */
110*4882a593Smuzhiyun #define PORT_CMD_ICC_PARTIAL	(0x2 << 28) /* Put i/f in partial state */
111*4882a593Smuzhiyun #define PORT_CMD_ICC_SLUMBER	(0x6 << 28) /* Put i/f in slumber state */
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun #define AHCI_MAX_PORTS		32
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun #define ATA_FLAG_SATA		(1 << 3)
116*4882a593Smuzhiyun #define ATA_FLAG_NO_LEGACY	(1 << 4) /* no legacy mode check */
117*4882a593Smuzhiyun #define ATA_FLAG_MMIO		(1 << 6) /* use MMIO, not PIO */
118*4882a593Smuzhiyun #define ATA_FLAG_SATA_RESET	(1 << 7) /* (obsolete) use COMRESET */
119*4882a593Smuzhiyun #define ATA_FLAG_PIO_DMA	(1 << 8) /* PIO cmds via DMA */
120*4882a593Smuzhiyun #define ATA_FLAG_NO_ATAPI	(1 << 11) /* No ATAPI support */
121*4882a593Smuzhiyun 
122*4882a593Smuzhiyun struct ahci_cmd_hdr {
123*4882a593Smuzhiyun 	u32	opts;
124*4882a593Smuzhiyun 	u32	status;
125*4882a593Smuzhiyun 	u32	tbl_addr;
126*4882a593Smuzhiyun 	u32	tbl_addr_hi;
127*4882a593Smuzhiyun 	u32	reserved[4];
128*4882a593Smuzhiyun };
129*4882a593Smuzhiyun 
130*4882a593Smuzhiyun struct ahci_sg {
131*4882a593Smuzhiyun 	u32	addr;
132*4882a593Smuzhiyun 	u32	addr_hi;
133*4882a593Smuzhiyun 	u32	reserved;
134*4882a593Smuzhiyun 	u32	flags_size;
135*4882a593Smuzhiyun };
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun struct ahci_ioports {
138*4882a593Smuzhiyun 	void __iomem	*cmd_addr;
139*4882a593Smuzhiyun 	void __iomem	*scr_addr;
140*4882a593Smuzhiyun 	void __iomem	*port_mmio;
141*4882a593Smuzhiyun 	struct ahci_cmd_hdr	*cmd_slot;
142*4882a593Smuzhiyun 	struct ahci_sg		*cmd_tbl_sg;
143*4882a593Smuzhiyun 	ulong	cmd_tbl;
144*4882a593Smuzhiyun 	u32	rx_fis;
145*4882a593Smuzhiyun };
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun /**
148*4882a593Smuzhiyun  * struct ahci_uc_priv - information about an AHCI controller
149*4882a593Smuzhiyun  *
150*4882a593Smuzhiyun  * When driver model is used, this is accessible using dev_get_uclass_priv(dev)
151*4882a593Smuzhiyun  * where dev is the controller (although at present it sometimes stands alone).
152*4882a593Smuzhiyun  */
153*4882a593Smuzhiyun struct ahci_uc_priv {
154*4882a593Smuzhiyun #if defined(CONFIG_DM_PCI) || defined(CONFIG_DM_SCSI)
155*4882a593Smuzhiyun 	/*
156*4882a593Smuzhiyun 	 * TODO(sjg@chromium.org): Drop this once this structure is only used
157*4882a593Smuzhiyun 	 * in a driver-model context (i.e. attached to a device with
158*4882a593Smuzhiyun 	 * dev_get_uclass_priv()
159*4882a593Smuzhiyun 	 */
160*4882a593Smuzhiyun 	struct udevice *dev;
161*4882a593Smuzhiyun #else
162*4882a593Smuzhiyun 	pci_dev_t	dev;
163*4882a593Smuzhiyun #endif
164*4882a593Smuzhiyun 	struct ahci_ioports	port[AHCI_MAX_PORTS];
165*4882a593Smuzhiyun 	u16 *ataid[AHCI_MAX_PORTS];
166*4882a593Smuzhiyun 	u32	n_ports;
167*4882a593Smuzhiyun 	u32	hard_port_no;
168*4882a593Smuzhiyun 	u32	host_flags;
169*4882a593Smuzhiyun 	u32	host_set_flags;
170*4882a593Smuzhiyun 	void __iomem *mmio_base;
171*4882a593Smuzhiyun 	u32     pio_mask;
172*4882a593Smuzhiyun 	u32	udma_mask;
173*4882a593Smuzhiyun 	u32	flags;
174*4882a593Smuzhiyun 	u32	cap;	/* cache of HOST_CAP register */
175*4882a593Smuzhiyun 	u32	port_map; /* cache of HOST_PORTS_IMPL reg */
176*4882a593Smuzhiyun 	u32	link_port_map; /*linkup port map*/
177*4882a593Smuzhiyun };
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun struct ahci_ops {
180*4882a593Smuzhiyun 	/**
181*4882a593Smuzhiyun 	 * reset() - reset the controller
182*4882a593Smuzhiyun 	 *
183*4882a593Smuzhiyun 	 * @dev:	Controller to reset
184*4882a593Smuzhiyun 	 * @return 0 if OK, -ve on error
185*4882a593Smuzhiyun 	 */
186*4882a593Smuzhiyun 	int (*reset)(struct udevice *dev);
187*4882a593Smuzhiyun 
188*4882a593Smuzhiyun 	/**
189*4882a593Smuzhiyun 	 * port_status() - get the status of a SATA port
190*4882a593Smuzhiyun 	 *
191*4882a593Smuzhiyun 	 * @dev:	Controller to reset
192*4882a593Smuzhiyun 	 * @port:	Port number to check (0 for first)
193*4882a593Smuzhiyun 	 * @return 0 if detected, -ENXIO if nothing on port, other -ve on error
194*4882a593Smuzhiyun 	 */
195*4882a593Smuzhiyun 	int (*port_status)(struct udevice *dev, int port);
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	/**
198*4882a593Smuzhiyun 	 * scan() - scan SATA ports
199*4882a593Smuzhiyun 	 *
200*4882a593Smuzhiyun 	 * @dev:	Controller to scan
201*4882a593Smuzhiyun 	 * @return 0 if OK, -ve on error
202*4882a593Smuzhiyun 	 */
203*4882a593Smuzhiyun 	int (*scan)(struct udevice *dev);
204*4882a593Smuzhiyun };
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun #define ahci_get_ops(dev)        ((struct ahci_ops *)(dev)->driver->ops)
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun /**
209*4882a593Smuzhiyun  * sata_reset() - reset the controller
210*4882a593Smuzhiyun  *
211*4882a593Smuzhiyun  * @dev:	Controller to reset
212*4882a593Smuzhiyun  * @return 0 if OK, -ve on error
213*4882a593Smuzhiyun  */
214*4882a593Smuzhiyun int sata_reset(struct udevice *dev);
215*4882a593Smuzhiyun 
216*4882a593Smuzhiyun /**
217*4882a593Smuzhiyun  * sata_port_status() - get the status of a SATA port
218*4882a593Smuzhiyun  *
219*4882a593Smuzhiyun  * @dev:	Controller to reset
220*4882a593Smuzhiyun  * @port:	Port number to check (0 for first)
221*4882a593Smuzhiyun  * @return 0 if detected, -ENXIO if nothin on port, other -ve on error
222*4882a593Smuzhiyun  */
223*4882a593Smuzhiyun int sata_dm_port_status(struct udevice *dev, int port);
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun /**
226*4882a593Smuzhiyun  * sata_scan() - scan SATA ports
227*4882a593Smuzhiyun  *
228*4882a593Smuzhiyun  * @dev:	Controller to scan
229*4882a593Smuzhiyun  * @return 0 if OK, -ve on error
230*4882a593Smuzhiyun  */
231*4882a593Smuzhiyun int sata_scan(struct udevice *dev);
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun int ahci_init(void __iomem *base);
234*4882a593Smuzhiyun int ahci_reset(void __iomem *base);
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun /**
237*4882a593Smuzhiyun  * achi_init_one_dm() - set up a single AHCI port
238*4882a593Smuzhiyun  *
239*4882a593Smuzhiyun  * @dev: Controller to init
240*4882a593Smuzhiyun  */
241*4882a593Smuzhiyun int achi_init_one_dm(struct udevice *dev);
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun /**
244*4882a593Smuzhiyun  * achi_start_ports_dm() - start all AHCI ports for a controller
245*4882a593Smuzhiyun  *
246*4882a593Smuzhiyun  * @dev: Controller containing ports to start
247*4882a593Smuzhiyun  */
248*4882a593Smuzhiyun int achi_start_ports_dm(struct udevice *dev);
249*4882a593Smuzhiyun 
250*4882a593Smuzhiyun /**
251*4882a593Smuzhiyun  * ahci_init_dm() - init AHCI for a controller, finding all ports
252*4882a593Smuzhiyun  *
253*4882a593Smuzhiyun  * @dev: Device to init
254*4882a593Smuzhiyun  */
255*4882a593Smuzhiyun int ahci_init_dm(struct udevice *dev, void __iomem *base);
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun /**
258*4882a593Smuzhiyun  * ahci_bind_scsi() - bind a new SCSI bus as a child
259*4882a593Smuzhiyun  *
260*4882a593Smuzhiyun  * Note that the SCSI bus device will itself bind block devices
261*4882a593Smuzhiyun  *
262*4882a593Smuzhiyun  * @ahci_dev: AHCI parent device
263*4882a593Smuzhiyun  * @devp: Returns new SCSI bus device
264*4882a593Smuzhiyun  * @return 0 if OK, -ve on error
265*4882a593Smuzhiyun  */
266*4882a593Smuzhiyun int ahci_bind_scsi(struct udevice *ahci_dev, struct udevice **devp);
267*4882a593Smuzhiyun 
268*4882a593Smuzhiyun /**
269*4882a593Smuzhiyun  * ahci_probe_scsi() - probe and scan the attached SCSI bus
270*4882a593Smuzhiyun  *
271*4882a593Smuzhiyun  * Note that the SCSI device will itself bind block devices for any storage
272*4882a593Smuzhiyun  * devices it finds.
273*4882a593Smuzhiyun  *
274*4882a593Smuzhiyun  * @ahci_dev: AHCI parent device
275*4882a593Smuzhiyun  * @base: Base address of AHCI port
276*4882a593Smuzhiyun  * @return 0 if OK, -ve on error
277*4882a593Smuzhiyun  */
278*4882a593Smuzhiyun int ahci_probe_scsi(struct udevice *ahci_dev, ulong base);
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun /**
281*4882a593Smuzhiyun  * ahci_probe_scsi_pci() - probe and scan the attached SCSI bus on PCI
282*4882a593Smuzhiyun  *
283*4882a593Smuzhiyun  * Note that the SCSI device will itself bind block devices for any storage
284*4882a593Smuzhiyun  * devices it finds.
285*4882a593Smuzhiyun  *
286*4882a593Smuzhiyun  * @ahci_dev: AHCI parent device
287*4882a593Smuzhiyun  * @return 0 if OK, -ve on error
288*4882a593Smuzhiyun  */
289*4882a593Smuzhiyun int ahci_probe_scsi_pci(struct udevice *ahci_dev);
290*4882a593Smuzhiyun 
291*4882a593Smuzhiyun #endif
292