162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Definitions for using the Apple Descriptor-Based DMA controller
462306a36Sopenharmony_ci * in Power Macintosh computers.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 1996 Paul Mackerras.
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#ifdef __KERNEL__
1062306a36Sopenharmony_ci#ifndef _ASM_DBDMA_H_
1162306a36Sopenharmony_ci#define _ASM_DBDMA_H_
1262306a36Sopenharmony_ci/*
1362306a36Sopenharmony_ci * DBDMA control/status registers.  All little-endian.
1462306a36Sopenharmony_ci */
1562306a36Sopenharmony_cistruct dbdma_regs {
1662306a36Sopenharmony_ci    unsigned int control;	/* lets you change bits in status */
1762306a36Sopenharmony_ci    unsigned int status;	/* DMA and device status bits (see below) */
1862306a36Sopenharmony_ci    unsigned int cmdptr_hi;	/* upper 32 bits of command address */
1962306a36Sopenharmony_ci    unsigned int cmdptr;	/* (lower 32 bits of) command address (phys) */
2062306a36Sopenharmony_ci    unsigned int intr_sel;	/* select interrupt condition bit */
2162306a36Sopenharmony_ci    unsigned int br_sel;	/* select branch condition bit */
2262306a36Sopenharmony_ci    unsigned int wait_sel;	/* select wait condition bit */
2362306a36Sopenharmony_ci    unsigned int xfer_mode;
2462306a36Sopenharmony_ci    unsigned int data2ptr_hi;
2562306a36Sopenharmony_ci    unsigned int data2ptr;
2662306a36Sopenharmony_ci    unsigned int res1;
2762306a36Sopenharmony_ci    unsigned int address_hi;
2862306a36Sopenharmony_ci    unsigned int br_addr_hi;
2962306a36Sopenharmony_ci    unsigned int res2[3];
3062306a36Sopenharmony_ci};
3162306a36Sopenharmony_ci
3262306a36Sopenharmony_ci/* Bits in control and status registers */
3362306a36Sopenharmony_ci#define RUN	0x8000
3462306a36Sopenharmony_ci#define PAUSE	0x4000
3562306a36Sopenharmony_ci#define FLUSH	0x2000
3662306a36Sopenharmony_ci#define WAKE	0x1000
3762306a36Sopenharmony_ci#define DEAD	0x0800
3862306a36Sopenharmony_ci#define ACTIVE	0x0400
3962306a36Sopenharmony_ci#define BT	0x0100
4062306a36Sopenharmony_ci#define DEVSTAT	0x00ff
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci/*
4362306a36Sopenharmony_ci * DBDMA command structure.  These fields are all little-endian!
4462306a36Sopenharmony_ci */
4562306a36Sopenharmony_cistruct dbdma_cmd {
4662306a36Sopenharmony_ci	__le16 req_count;	/* requested byte transfer count */
4762306a36Sopenharmony_ci	__le16 command;		/* command word (has bit-fields) */
4862306a36Sopenharmony_ci	__le32 phy_addr;	/* physical data address */
4962306a36Sopenharmony_ci	__le32 cmd_dep;		/* command-dependent field */
5062306a36Sopenharmony_ci	__le16 res_count;	/* residual count after completion */
5162306a36Sopenharmony_ci	__le16 xfer_status;	/* transfer status */
5262306a36Sopenharmony_ci};
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci/* DBDMA command values in command field */
5562306a36Sopenharmony_ci#define OUTPUT_MORE	0	/* transfer memory data to stream */
5662306a36Sopenharmony_ci#define OUTPUT_LAST	0x1000	/* ditto followed by end marker */
5762306a36Sopenharmony_ci#define INPUT_MORE	0x2000	/* transfer stream data to memory */
5862306a36Sopenharmony_ci#define INPUT_LAST	0x3000	/* ditto, expect end marker */
5962306a36Sopenharmony_ci#define STORE_WORD	0x4000	/* write word (4 bytes) to device reg */
6062306a36Sopenharmony_ci#define LOAD_WORD	0x5000	/* read word (4 bytes) from device reg */
6162306a36Sopenharmony_ci#define DBDMA_NOP	0x6000	/* do nothing */
6262306a36Sopenharmony_ci#define DBDMA_STOP	0x7000	/* suspend processing */
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci/* Key values in command field */
6562306a36Sopenharmony_ci#define KEY_STREAM0	0	/* usual data stream */
6662306a36Sopenharmony_ci#define KEY_STREAM1	0x100	/* control/status stream */
6762306a36Sopenharmony_ci#define KEY_STREAM2	0x200	/* device-dependent stream */
6862306a36Sopenharmony_ci#define KEY_STREAM3	0x300	/* device-dependent stream */
6962306a36Sopenharmony_ci#define KEY_REGS	0x500	/* device register space */
7062306a36Sopenharmony_ci#define KEY_SYSTEM	0x600	/* system memory-mapped space */
7162306a36Sopenharmony_ci#define KEY_DEVICE	0x700	/* device memory-mapped space */
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci/* Interrupt control values in command field */
7462306a36Sopenharmony_ci#define INTR_NEVER	0	/* don't interrupt */
7562306a36Sopenharmony_ci#define INTR_IFSET	0x10	/* intr if condition bit is 1 */
7662306a36Sopenharmony_ci#define INTR_IFCLR	0x20	/* intr if condition bit is 0 */
7762306a36Sopenharmony_ci#define INTR_ALWAYS	0x30	/* always interrupt */
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci/* Branch control values in command field */
8062306a36Sopenharmony_ci#define BR_NEVER	0	/* don't branch */
8162306a36Sopenharmony_ci#define BR_IFSET	0x4	/* branch if condition bit is 1 */
8262306a36Sopenharmony_ci#define BR_IFCLR	0x8	/* branch if condition bit is 0 */
8362306a36Sopenharmony_ci#define BR_ALWAYS	0xc	/* always branch */
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci/* Wait control values in command field */
8662306a36Sopenharmony_ci#define WAIT_NEVER	0	/* don't wait */
8762306a36Sopenharmony_ci#define WAIT_IFSET	1	/* wait if condition bit is 1 */
8862306a36Sopenharmony_ci#define WAIT_IFCLR	2	/* wait if condition bit is 0 */
8962306a36Sopenharmony_ci#define WAIT_ALWAYS	3	/* always wait */
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci/* Align an address for a DBDMA command structure */
9262306a36Sopenharmony_ci#define DBDMA_ALIGN(x)	(((unsigned long)(x) + sizeof(struct dbdma_cmd) - 1) \
9362306a36Sopenharmony_ci			 & -sizeof(struct dbdma_cmd))
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci/* Useful macros */
9662306a36Sopenharmony_ci#define DBDMA_DO_STOP(regs) do {				\
9762306a36Sopenharmony_ci	out_le32(&((regs)->control), (RUN|FLUSH)<<16);		\
9862306a36Sopenharmony_ci	while(in_le32(&((regs)->status)) & (ACTIVE|FLUSH))	\
9962306a36Sopenharmony_ci		; \
10062306a36Sopenharmony_ci} while(0)
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci#define DBDMA_DO_RESET(regs) do {				\
10362306a36Sopenharmony_ci	out_le32(&((regs)->control), (ACTIVE|DEAD|WAKE|FLUSH|PAUSE|RUN)<<16);\
10462306a36Sopenharmony_ci	while(in_le32(&((regs)->status)) & (RUN)) \
10562306a36Sopenharmony_ci		; \
10662306a36Sopenharmony_ci} while(0)
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_ci#endif /* _ASM_DBDMA_H_ */
10962306a36Sopenharmony_ci#endif /* __KERNEL__ */
110