Search
lxdream.org :: lxdream/test/dmac.c
lxdream 0.9.1
released Jun 29
Download Now
filename test/dmac.c
changeset 812:8cc61d5ea1f8
prev753:1fe39c3a9bbc
next815:866c103d72cd
author nkeynes
date Wed Aug 13 10:32:00 2008 +0000 (13 years ago)
permissions -rw-r--r--
last change Add ARM test harness (not quite working on DC but almost...)
file annotate diff log raw
nkeynes@185
     1
/**
nkeynes@561
     2
 * $Id$
nkeynes@185
     3
 * 
nkeynes@185
     4
 * DMA support code
nkeynes@185
     5
 *
nkeynes@185
     6
 * Copyright (c) 2006 Nathan Keynes.
nkeynes@185
     7
 *
nkeynes@185
     8
 * This program is free software; you can redistribute it and/or modify
nkeynes@185
     9
 * it under the terms of the GNU General Public License as published by
nkeynes@185
    10
 * the Free Software Foundation; either version 2 of the License, or
nkeynes@185
    11
 * (at your option) any later version.
nkeynes@185
    12
 *
nkeynes@185
    13
 * This program is distributed in the hope that it will be useful,
nkeynes@185
    14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
nkeynes@185
    15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
nkeynes@185
    16
 * GNU General Public License for more details.
nkeynes@185
    17
 */
nkeynes@185
    18
nkeynes@185
    19
#include "dma.h"
nkeynes@185
    20
#include "asic.h"
nkeynes@185
    21
nkeynes@185
    22
#define DMA_BASE 0xFFA00000
nkeynes@185
    23
nkeynes@185
    24
#define DMA_SAR(c) (DMA_BASE+0x00+(c<<4))
nkeynes@185
    25
#define DMA_DAR(c) (DMA_BASE+0x04+(c<<4))
nkeynes@185
    26
#define DMA_TCR(c) (DMA_BASE+0x08+(c<<4))
nkeynes@185
    27
#define DMA_CHCR(c) (DMA_BASE+0x0C+(c<<4))
nkeynes@185
    28
#define DMA_OR (DMA_BASE+0x40)
nkeynes@185
    29
nkeynes@185
    30
#define ASIC_BASE 0xA05F6000
nkeynes@185
    31
#define PVR_DMA_DEST  (ASIC_BASE+0x800)
nkeynes@185
    32
#define PVR_DMA_COUNT (ASIC_BASE+0x804)
nkeynes@185
    33
#define PVR_DMA_CTL   (ASIC_BASE+0x808)
nkeynes@185
    34
#define PVR_DMA_REGION (ASIC_BASE+0x884)
nkeynes@185
    35
nkeynes@753
    36
#define SORT_DMA_TABLE (ASIC_BASE+0x810)
nkeynes@753
    37
#define SORT_DMA_DATA  (ASIC_BASE+0x814)
nkeynes@753
    38
#define SORT_DMA_TABLEBITS (ASIC_BASE+0x818)
nkeynes@753
    39
#define SORT_DMA_DATASIZE (ASIC_BASE+0x81C)
nkeynes@753
    40
#define SORT_DMA_CTL   (ASIC_BASE+0x820)
nkeynes@753
    41
#define SORT_DMA_COUNT (ASIC_BASE+0x860)
nkeynes@753
    42
nkeynes@812
    43
#define G2BASERAM 0x00800000
nkeynes@812
    44
nkeynes@812
    45
#define G2DMABASE 0xA05F7800
nkeynes@812
    46
#define G2DMATIMEOUT (G2DMABASE+0x90)
nkeynes@812
    47
#define G2DMAMAGIC (G2DMABASE+0xBC)
nkeynes@812
    48
#define G2DMAEXT(x) (G2DMABASE+(0x20*(x)))
nkeynes@812
    49
#define G2DMAHOST(x) (G2DMABASE+(0x20*(x))+0x04)
nkeynes@812
    50
#define G2DMASIZE(x) (G2DMABASE+(0x20*(x))+0x08)
nkeynes@812
    51
#define G2DMADIR(x) (G2DMABASE+(0x20*(x))+0x0C)
nkeynes@812
    52
#define G2DMAMODE(x) (G2DMABASE+(0x20*(x))+0x10)
nkeynes@812
    53
#define G2DMACTL1(x) (G2DMABASE+(0x20*(x))+0x14)
nkeynes@812
    54
#define G2DMACTL2(x) (G2DMABASE+(0x20*(x))+0x18)
nkeynes@812
    55
#define G2DMASTOP(x) (G2DMABASE+(0x20*(x))+0x1C)
nkeynes@812
    56
nkeynes@185
    57
void dmac_dump_channel( FILE *f, unsigned int channel )
nkeynes@185
    58
{
nkeynes@185
    59
    fprintf( f, "DMAC SAR: %08X  Count: %08X  Ctl: %08X  OR: %08X\n",
nkeynes@185
    60
	     long_read(DMA_SAR(channel)), long_read(DMA_TCR(channel)), 
nkeynes@185
    61
	     long_read(DMA_CHCR(channel)), long_read(DMA_OR) );
nkeynes@185
    62
}
nkeynes@185
    63
nkeynes@185
    64
nkeynes@185
    65
/**
nkeynes@185
    66
 * Setup the DMAC for a transfer. Assumes 32-byte block transfer.
nkeynes@185
    67
 * Caller is responsible for making sure no-one else is using the
nkeynes@185
    68
 * channel already. 
nkeynes@185
    69
 *
nkeynes@185
    70
 * @param channel DMA channel to use, 0 to 3
nkeynes@185
    71
 * @param source source address (if a memory source)
nkeynes@185
    72
 * @param dest   destination address (if a memory destination)
nkeynes@185
    73
 * @param length number of bytes to transfer (must be a multiple of
nkeynes@185
    74
 *               32.
nkeynes@185
    75
 * @param direction 0 = host to device, 1 = device to host
nkeynes@185
    76
 */
nkeynes@185
    77
void dmac_prepare_channel( int channel, uint32_t source, uint32_t dest,
nkeynes@185
    78
			   uint32_t length, int direction )
nkeynes@185
    79
{
nkeynes@185
    80
    uint32_t control;
nkeynes@185
    81
nkeynes@185
    82
    if( direction == 0 ) {
nkeynes@185
    83
	/* DMA Disabled, IRQ disabled, 32 byte transfer, burst mode,
nkeynes@185
    84
	 * Memory => Device, Source addr increment, dest addr fixed
nkeynes@185
    85
	 */
nkeynes@185
    86
	control = 0x000012C0;
nkeynes@185
    87
    } else {
nkeynes@185
    88
	/* DMA Disabled, IRQ disabled, 32 byte transfer, burst mode,
nkeynes@185
    89
	 * Device => Memory, Source addr fixed, dest addr increment
nkeynes@185
    90
	 */
nkeynes@185
    91
	control = 0x000043C0;
nkeynes@185
    92
    }
nkeynes@185
    93
    long_write( DMA_CHCR(channel), control );
nkeynes@185
    94
    long_write( DMA_SAR(channel), source );
nkeynes@185
    95
    long_write( DMA_DAR(channel), dest );
nkeynes@185
    96
    long_write( DMA_TCR(channel), (length >> 5) );
nkeynes@185
    97
    control |= 0x0001;
nkeynes@185
    98
    long_write( DMA_CHCR(channel), control ); /* Enable DMA channel */
nkeynes@185
    99
    long_write( DMA_OR, 0x8201 ); /* Ensure the DMAC config is set */
nkeynes@185
   100
}
nkeynes@185
   101
nkeynes@185
   102
nkeynes@185
   103
int pvr_dma_write( unsigned int target, char *buf, int len, int region )
nkeynes@185
   104
{
nkeynes@185
   105
    uint32_t addr =(uint32_t)buf;
nkeynes@185
   106
    int result;
nkeynes@185
   107
    if( (addr & 0xFFFFFFE0) != addr ) {
nkeynes@185
   108
	fprintf( stderr, "Address error: Attempting DMA from %08X\n", addr );
nkeynes@185
   109
	return -1;
nkeynes@185
   110
    }
nkeynes@185
   111
    long_write( PVR_DMA_CTL, 0 ); /* Stop PVR dma if it's already running */
nkeynes@185
   112
    asic_clear();
nkeynes@185
   113
nkeynes@185
   114
    dmac_prepare_channel( 2, (uint32_t)buf, 0, len, 0 ); /* Allocate channel 2 */
nkeynes@185
   115
    long_write( PVR_DMA_DEST, target );
nkeynes@185
   116
    long_write( PVR_DMA_COUNT, len );
nkeynes@185
   117
    long_write( PVR_DMA_REGION, region );
nkeynes@185
   118
nkeynes@185
   119
    CHECK_IEQUALS( target, long_read(PVR_DMA_DEST) );
nkeynes@185
   120
    CHECK_IEQUALS( len, long_read(PVR_DMA_COUNT) );
nkeynes@185
   121
    CHECK_IEQUALS( 0, long_read(PVR_DMA_REGION) );
nkeynes@185
   122
    CHECK_IEQUALS( (uint32_t)buf, long_read(DMA_SAR(2)) );
nkeynes@185
   123
    CHECK_IEQUALS( len/32, long_read(DMA_TCR(2)) );
nkeynes@185
   124
    CHECK_IEQUALS( 0x12C1, long_read(DMA_CHCR(2)) );
nkeynes@185
   125
nkeynes@185
   126
    long_write( PVR_DMA_CTL, 1 );
nkeynes@185
   127
    result = asic_wait(EVENT_PVR_DMA);
nkeynes@185
   128
nkeynes@185
   129
    if( result != 0 ) {
nkeynes@185
   130
	fprintf( stderr, "PVR DMA failed (timeout)\n" );
nkeynes@185
   131
	asic_dump(stderr);
nkeynes@185
   132
	fprintf( stderr, "Dest: %08X  Count: %08X  Ctl: %08X\n", long_read(PVR_DMA_DEST),
nkeynes@185
   133
		 long_read(PVR_DMA_COUNT), long_read(PVR_DMA_CTL) );
nkeynes@185
   134
	dmac_dump_channel(stderr, 2);
nkeynes@185
   135
	long_write( PVR_DMA_CTL, 0 );
nkeynes@185
   136
    }
nkeynes@185
   137
nkeynes@185
   138
    CHECK_IEQUALS( 0, long_read(PVR_DMA_CTL) );
nkeynes@185
   139
    CHECK_IEQUALS( ((uint32_t)buf)+len, long_read(DMA_SAR(2))  );
nkeynes@185
   140
    CHECK_IEQUALS( 0, long_read(DMA_TCR(2)) );
nkeynes@185
   141
    CHECK_IEQUALS( 0x12C3, long_read(DMA_CHCR(2)) );
nkeynes@185
   142
    CHECK_IEQUALS( target, long_read(PVR_DMA_DEST) );
nkeynes@185
   143
    CHECK_IEQUALS( 0, long_read(PVR_DMA_COUNT) );
nkeynes@185
   144
    CHECK_IEQUALS( 0, long_read(PVR_DMA_REGION) );
nkeynes@185
   145
nkeynes@185
   146
    return result;
nkeynes@185
   147
}
nkeynes@753
   148
nkeynes@753
   149
int sort_dma_write( char *sorttable, int tablelen, char *data, int datalen, int bitwidth, int datasize )
nkeynes@753
   150
{
nkeynes@753
   151
    int result;
nkeynes@753
   152
    uint32_t tableaddr = (uint32_t)sorttable;
nkeynes@753
   153
    uint32_t dataaddr = (uint32_t)data;
nkeynes@753
   154
    
nkeynes@753
   155
    long_write( SORT_DMA_CTL, 0 );
nkeynes@753
   156
    asic_clear();
nkeynes@753
   157
    
nkeynes@753
   158
    long_write( SORT_DMA_TABLE, tableaddr );
nkeynes@753
   159
    long_write( SORT_DMA_DATA, dataaddr );
nkeynes@753
   160
    long_write( SORT_DMA_TABLEBITS, bitwidth );
nkeynes@753
   161
    long_write( SORT_DMA_DATASIZE, datasize );
nkeynes@753
   162
    long_write( SORT_DMA_CTL, 1 );
nkeynes@753
   163
    result = asic_wait2(EVENT_SORT_DMA, EVENT_SORT_DMA_ERR);
nkeynes@753
   164
    if( result == -1 ) {
nkeynes@753
   165
        fprintf( stderr, "SORT DMA failed (timeout)\n" );
nkeynes@753
   166
        asic_dump(stderr);
nkeynes@753
   167
        fprintf( stderr, "Table: %08X Count: %08X Ctl: %08X\n", long_read(SORT_DMA_TABLE), long_read(SORT_DMA_COUNT),
nkeynes@753
   168
                 long_read(SORT_DMA_CTL) );
nkeynes@753
   169
        long_write( SORT_DMA_CTL, 0 );
nkeynes@753
   170
    }
nkeynes@753
   171
    CHECK_IEQUALS( 0, long_read(SORT_DMA_CTL) );
nkeynes@753
   172
    return result;
nkeynes@753
   173
}
nkeynes@812
   174
nkeynes@812
   175
int aica_dma_transfer( uint32_t aica_addr, char *data, uint32_t size, int writeFlag )
nkeynes@812
   176
{
nkeynes@812
   177
    long_write( G2DMATIMEOUT, 0 );
nkeynes@812
   178
    long_write( G2DMAMAGIC, 0x4659404f );
nkeynes@812
   179
    long_write( G2DMACTL1(0), 0 );
nkeynes@812
   180
    long_write( G2DMAEXT(0), aica_addr );
nkeynes@812
   181
    long_write( G2DMAHOST(0), ((uint32_t)data) );
nkeynes@812
   182
    long_write( G2DMASIZE(0), ((size+31)&0x7FFFFFE0) | 0x80000000 );
nkeynes@812
   183
    long_write( G2DMADIR(0), (writeFlag ? 0 : 1) );
nkeynes@812
   184
    long_write( G2DMAMODE(0), 0 );
nkeynes@812
   185
    
nkeynes@812
   186
    long_write( G2DMACTL1(0), 1 );
nkeynes@812
   187
    long_write( G2DMACTL2(0), 1 );
nkeynes@812
   188
    if( asic_wait( EVENT_G2_DMA0 ) != 0 ) {
nkeynes@812
   189
        fprintf( stderr, "Timeout waiting for G2 DMA event\n" );
nkeynes@812
   190
        return -1;
nkeynes@812
   191
    }
nkeynes@812
   192
    // CHECK_IEQUALS( 0, long_read( G2DMACTL1(0) ) );
nkeynes@812
   193
    CHECK_IEQUALS( 0, long_read( G2DMACTL2(0) ) );
nkeynes@812
   194
    return 0;
nkeynes@812
   195
}
nkeynes@812
   196
nkeynes@812
   197
int aica_dma_write( uint32_t aica_addr, char *data, uint32_t size )
nkeynes@812
   198
{
nkeynes@812
   199
    return aica_dma_transfer( aica_addr, data, size, 1 );
nkeynes@812
   200
}
nkeynes@812
   201
nkeynes@812
   202
int aica_dma_read( char *data, uint32_t aica_addr, uint32_t size )
nkeynes@812
   203
{
nkeynes@812
   204
    return aica_dma_transfer( aica_addr, data, size, 0 );
nkeynes@812
   205
}
.