1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
|
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2011 by Amaury Pouly
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#ifndef __DMA_IMX233_H__
#define __DMA_IMX233_H__
#include "cpu.h"
#include "system.h"
#include "system-target.h"
/************
* CHANNELS *
************/
#define APBH_DMA_CHANNEL(i) i
#define APBX_DMA_CHANNEL(i) ((i) | 0x10)
#define APB_IS_APBX_CHANNEL(x) ((x) & 0x10)
#define APB_GET_DMA_CHANNEL(x) ((x) & 0xf)
#if IMX233_SUBTARGET >= 3700
// NOTE: although undocumented, the iMX233 channel 0 is actually the LCDIF one
#define APB_LCDIF APBH_DMA_CHANNEL(0)
#else
#define APB_LCDIF APBX_DMA_CHANNEL(4)
#endif
#define APB_SSP(ssp) APBH_DMA_CHANNEL(ssp)
#define APB_GPMI(dev) APBH_DMA_CHANNEL(4 + (dev))
#define APB_AUDIO_ADC APBX_DMA_CHANNEL(0)
#define APB_AUDIO_DAC APBX_DMA_CHANNEL(1)
#define APB_I2C APBX_DMA_CHANNEL(3)
// NOTE: although undocumented, the IMX233 channel 5 is actually the DRI one
#define APB_DRI APBX_DMA_CHANNEL(5)
/**********
* COMMON *
**********/
/* DMA structures should be cache aligned and be padded so that their size
* is a multiple of a cache line size. Otherwise some nasty side effects
* could occur with adjacents data fields.
* The same apply to DMA buffers for the same reasons */
struct apb_dma_command_t
{
struct apb_dma_command_t *next;
uint32_t cmd;
void *buffer;
/* PIO words follow */
} __attribute__((packed));
#define DMA_INFO_CURCMDADDR (1 << 0)
#define DMA_INFO_NXTCMDADDR (1 << 1)
#define DMA_INFO_CMD (1 << 2)
#define DMA_INFO_BAR (1 << 3)
#define DMA_INFO_APB_BYTES (1 << 4)
#define DMA_INFO_AHB_BYTES (1 << 5)
#define DMA_INFO_FROZEN (1 << 6)
#define DMA_INFO_GATED (1 << 7)
#define DMA_INFO_INTERRUPT (1 << 8)
#define DMA_INFO_ALL 0x1ff
struct imx233_dma_info_t
{
unsigned long cur_cmd_addr;
unsigned long nxt_cmd_addr;
unsigned long cmd;
unsigned long bar;
unsigned apb_bytes;
unsigned ahb_bytes;
bool frozen;
bool gated;
bool int_enabled;
bool int_cmdcomplt;
bool int_error;
int nr_unaligned;
};
#define BM_APB_CHx_CMD_COMMAND 0x3
#define BP_APB_CHx_CMD_COMMAND 0
#define BF_APB_CHx_CMD_COMMAND(v) ((v) & 0x3)
#define BF_APB_CHx_CMD_COMMAND_V(v) BF_APB_CHx_CMD_COMMAND(BV_APB_CHx_CMD_COMMAND__##v)
#define BV_APB_CHx_CMD_COMMAND__NO_XFER 0
#define BV_APB_CHx_CMD_COMMAND__WRITE 1
#define BV_APB_CHx_CMD_COMMAND__READ 2
#define BV_APB_CHx_CMD_COMMAND__SENSE 3
#define BM_APB_CHx_CMD_CHAIN (1 << 2)
#define BP_APB_CHx_CMD_CHAIN 2
#define BF_APB_CHx_CMD_CHAIN(v) (((v) & 1) << 2)
#define BM_APB_CHx_CMD_IRQONCMPLT (1 << 3)
#define BP_APB_CHx_CMD_IRQONCMPLT 3
#define BF_APB_CHx_CMD_IRQONCMPLT(v) (((v) & 1) << 3)
/* those two are only available on APHB */
#define BM_APBH_CHx_CMD_NANDLOCK (1 << 4)
#define BP_APBH_CHx_CMD_NANDLOCK 4
#define BF_APBH_CHx_CMD_NANDLOCK(v) (((v) & 1) << 4)
#define BM_APBH_CHx_CMD_NANDWAIT4READY (1 << 5)
#define BP_APBH_CHx_CMD_NANDWAIT4READY 5
#define BF_APBH_CHx_CMD_NANDWAIT4READY(v) (((v) & 1) << 5)
#define BM_APB_CHx_CMD_SEMAPHORE (1 << 6)
#define BP_APB_CHx_CMD_SEMAPHORE 6
#define BF_APB_CHx_CMD_SEMAPHORE(v) (((v) & 1) << 6)
#define BM_APB_CHx_CMD_WAIT4ENDCMD (1 << 7)
#define BP_APB_CHx_CMD_WAIT4ENDCMD 7
#define BF_APB_CHx_CMD_WAIT4ENDCMD(v) (((v) & 1) << 7)
/** WARNING: An errata advise not to use it */
#define BM_APB_CHx_CMD_HALTONTERMINATE (1 << 8)
#define BP_APB_CHx_CMD_HALTONTERMINATE 8
#define BF_APB_CHx_CMD_HALTONTERMINATE(v) (((v) & 1) << 8)
#define BM_APB_CHx_CMD_CMDWORDS 0xf000
#define BP_APB_CHx_CMD_CMDWORDS 12
#define BF_APB_CHx_CMD_CMDWORDS(v) (((v) & 0xf) << 12)
#define BM_APB_CHx_CMD_XFER_COUNT 0xffff0000
#define BP_APB_CHx_CMD_XFER_COUNT 16
#define BF_APB_CHx_CMD_XFER_COUNT(v) (((v) & 0xffff) << 16)
/* For software use */
#define BP_APB_CHx_CMD_UNUSED 8
#define BM_APB_CHx_CMD_UNUSED (0xf << 8)
#define BF_APB_CHx_CMD_UNUSED(v) (((v) & 0xf) << 8)
#define BF_APB_CHx_CMD_UNUSED_V(n) BF_APB_CHx_CMD_UNUSED(BV_APB_CHx_CMD_UNUSED__##n)
#define BFM_APB_CHx_CMD_UNUSED(v) BM_APB_CHx_CMD_UNUSED
#define BV_APB_CHx_CMD_UNUSED__MAGIC 0xa
#define BFM_APB_CHx_CMD_UNUSED_V(v) BM_APB_CHx_CMD_UNUSED
/* A single descriptor cannot transfer more than 2^16 bytes but because of the
* weird 0=64KiB, it's safer to restrict to 2^15 */
#define IMX233_MAX_SINGLE_DMA_XFER_SIZE (1 << 16)
void imx233_dma_init(void);
void imx233_dma_reset_channel(unsigned chan);
/* only apbh channel have clkgate control */
void imx233_dma_clkgate_channel(unsigned chan, bool enable_clock);
void imx233_dma_freeze_channel(unsigned chan, bool freeze);
void imx233_dma_enable_channel_interrupt(unsigned chan, bool enable);
/* clear both channel complete and error bits */
void imx233_dma_clear_channel_interrupt(unsigned chan);
bool imx233_dma_is_channel_error_irq(unsigned chan);
/* assume no command is in progress */
void imx233_dma_prepare_command(unsigned chan, struct apb_dma_command_t *cmd);
void imx233_dma_set_next_command(unsigned chan, struct apb_dma_command_t *cmd);
void imx233_dma_inc_sema(unsigned chan, unsigned amount);
/* wrapper around prepare_command, set_next_command, inc_sema(1) */
void imx233_dma_start_command(unsigned chan, struct apb_dma_command_t *cmd);
/* return value of the semaphore */
int imx233_dma_wait_completion(unsigned chan, unsigned tmo);
/* get some info
* WARNING: if channel is not freezed, data might not be coherent ! */
struct imx233_dma_info_t imx233_dma_get_info(unsigned chan, unsigned flags);
#endif // __DMA_IMX233_H__
|