mirror of
https://github.com/Rockbox/rockbox.git
synced 2025-11-09 13:12:37 -05:00
This is part of the preparation to add support for iPod Nano 3G and Nano 4G. There are some optimisations left, like merging similar blocks of registers that share the same layout, but the base address have changed between SoC generations. Change-Id: I4f06727b4061977141b65d39ae19591bd5b29680
119 lines
3.7 KiB
C
119 lines
3.7 KiB
C
/***************************************************************************
|
|
* __________ __ ___.
|
|
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
|
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
|
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
|
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
|
* \/ \/ \/ \/ \/
|
|
* $Id$
|
|
*
|
|
* Copyright © 2009 Bertrik Sikken
|
|
*
|
|
* 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.
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include "config.h"
|
|
|
|
#include "s5l87xx.h"
|
|
#include "dma-target.h"
|
|
#include "panic.h"
|
|
#include "system.h"
|
|
|
|
/* Driver for the IODMA part of the s5l8700
|
|
|
|
When requesting a DMA transfer the supplied callback is stored and called
|
|
upon completion of the DMA transfer (callback runs in interrupt context).
|
|
*/
|
|
|
|
|
|
#define DMAC_BASE 0x38400000
|
|
|
|
#define DMABASE(c) (*(volatile unsigned int*)(DMAC_BASE+0x00+(0x20*c)))
|
|
#define DMACON(c) (*(volatile unsigned int*)(DMAC_BASE+0x04+(0x20*c)))
|
|
#define DMATCNT(c) (*(volatile unsigned int*)(DMAC_BASE+0x08+(0x20*c)))
|
|
#define DMACADDR(c) (*(volatile unsigned int*)(DMAC_BASE+0x0C+(0x20*c)))
|
|
#define DMACTCNT(c) (*(volatile unsigned int*)(DMAC_BASE+0x10+(0x20*c)))
|
|
#define DMACOM(c) (*(volatile unsigned int*)(DMAC_BASE+0x14+(0x20*c)))
|
|
#define DMANOFF(c) (*(volatile unsigned int*)(DMAC_BASE+0x18+(0x20*c)))
|
|
|
|
#define DMACOM_HOLD 2 /* only allowed on channel 0 */
|
|
#define DMACOM_SKIP 3 /* only allowed on channel 0 */
|
|
#define DMACOM_CHAN_ON 4
|
|
#define DMACOM_CHAN_OFF 5
|
|
#define DMACOM_CLEAR_HCOM 6
|
|
#define DMACOM_CLEAR_HCOM_WCOM 7
|
|
|
|
|
|
/* one completion callback for each channel */
|
|
static void (*dma_callback[4])(void);
|
|
|
|
|
|
void dma_init(void)
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < 4; i++) {
|
|
dma_callback[i] = NULL;
|
|
dma_disable_channel(i);
|
|
}
|
|
|
|
INTMSK |= (1 << 10);
|
|
}
|
|
|
|
/* setup a DMA transfer, but do not start it yet */
|
|
void dma_setup_channel(int channel, int sel, int dir, int dsize, int blen,
|
|
void *addr, size_t size, void (*callback)(void))
|
|
{
|
|
dma_callback[channel] = callback;
|
|
|
|
DMACON(channel) = (sel << 30) | /* DEVSEL */
|
|
(dir << 29) | /* DIR */
|
|
(0 << 24) | /* SCHCNT */
|
|
(dsize << 22) | /* DSIZE */
|
|
(blen << 19) | /* BLEN */
|
|
(0 << 18) | /* RELOAD */
|
|
(0 << 17) | /* HCOMINT */
|
|
(1 << 16) | /* WCOMINT */
|
|
(0 << 0); /* OFFSET */
|
|
DMABASE(channel) = (unsigned int)addr;
|
|
DMATCNT(channel) = size - 1;
|
|
}
|
|
|
|
void dma_enable_channel(int channel)
|
|
{
|
|
DMACOM(channel) = DMACOM_CHAN_ON;
|
|
}
|
|
|
|
void dma_disable_channel(int channel)
|
|
{
|
|
DMACOM(channel) = DMACOM_CHAN_OFF;
|
|
}
|
|
|
|
/* interrupt handler for all DMA channels */
|
|
void INT_DMA(void)
|
|
{
|
|
unsigned int mask;
|
|
int channel;
|
|
|
|
mask = (1 << 0) | /* WCOMx interrupt bit */
|
|
(1 << 1); /* HCOMx interrupt bit */
|
|
for (channel = 0; channel < 4; channel++) {
|
|
if (DMAALLST & mask) {
|
|
/* clear half and whole completion bits */
|
|
DMACOM(channel) = DMACOM_CLEAR_HCOM_WCOM;
|
|
|
|
if (dma_callback[channel]) {
|
|
dma_callback[channel]();
|
|
}
|
|
}
|
|
mask <<= 4;
|
|
}
|
|
}
|
|
|