summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx233/dma-imx233.h
blob: f48fbbccf30a2a52a00fd36953d0cd5dbc1d0112 (plain)
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__