diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/dma/MCD_dmaApi.c | 1026 | ||||
-rw-r--r-- | drivers/dma/MCD_tasks.c | 2428 | ||||
-rw-r--r-- | drivers/dma/MCD_tasksInit.c | 247 | ||||
-rw-r--r-- | drivers/dma/Makefile | 46 | ||||
-rw-r--r-- | drivers/misc/Makefile | 1 | ||||
-rw-r--r-- | drivers/misc/fsl_law.c | 70 | ||||
-rw-r--r-- | drivers/net/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/fsl_mcdmafec.c | 571 | ||||
-rw-r--r-- | drivers/net/rtl8139.c | 23 | ||||
-rw-r--r-- | drivers/net/tsec.c | 117 | ||||
-rw-r--r-- | drivers/net/tsec.h | 8 | ||||
-rw-r--r-- | drivers/qe/uec.c | 112 | ||||
-rw-r--r-- | drivers/qe/uec_phy.c | 61 | ||||
-rw-r--r-- | drivers/spi/Makefile | 46 | ||||
-rw-r--r-- | drivers/spi/mpc8xxx_spi.c | 143 |
15 files changed, 4818 insertions, 82 deletions
diff --git a/drivers/dma/MCD_dmaApi.c b/drivers/dma/MCD_dmaApi.c new file mode 100644 index 0000000..b0062b7 --- /dev/null +++ b/drivers/dma/MCD_dmaApi.c @@ -0,0 +1,1026 @@ +/* + * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/*Main C file for multi-channel DMA API. */ + +#include <common.h> + +#ifdef CONFIG_FSLDMAFEC + +#include <MCD_dma.h> +#include <MCD_tasksInit.h> +#include <MCD_progCheck.h> + +/********************************************************************/ +/* This is an API-internal pointer to the DMA's registers */ +dmaRegs *MCD_dmaBar; + +/* + * These are the real and model task tables as generated by the + * build process + */ +extern TaskTableEntry MCD_realTaskTableSrc[NCHANNELS]; +extern TaskTableEntry MCD_modelTaskTableSrc[NUMOFVARIANTS]; + +/* + * However, this (usually) gets relocated to on-chip SRAM, at which + * point we access them as these tables + */ +volatile TaskTableEntry *MCD_taskTable; +TaskTableEntry *MCD_modelTaskTable; + +/* + * MCD_chStatus[] is an array of status indicators for remembering + * whether a DMA has ever been attempted on each channel, pausing + * status, etc. + */ +static int MCD_chStatus[NCHANNELS] = { + MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, + MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, + MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, + MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA, MCD_NO_DMA +}; + +/* Prototypes for local functions */ +static void MCD_memcpy(int *dest, int *src, u32 size); +static void MCD_resmActions(int channel); + +/* + * Buffer descriptors used for storage of progress info for single Dmas + * Also used as storage for the DMA for CRCs for single DMAs + * Otherwise, the DMA does not parse these buffer descriptors + */ +#ifdef MCD_INCLUDE_EU +extern MCD_bufDesc MCD_singleBufDescs[NCHANNELS]; +#else +MCD_bufDesc MCD_singleBufDescs[NCHANNELS]; +#endif +MCD_bufDesc *MCD_relocBuffDesc; + +/* Defines for the debug control register's functions */ +#define DBG_CTL_COMP1_TASK (0x00002000) +#define DBG_CTL_ENABLE (DBG_CTL_AUTO_ARM | \ + DBG_CTL_BREAK | \ + DBG_CTL_INT_BREAK | \ + DBG_CTL_COMP1_TASK) +#define DBG_CTL_DISABLE (DBG_CTL_AUTO_ARM | \ + DBG_CTL_INT_BREAK | \ + DBG_CTL_COMP1_TASK) +#define DBG_KILL_ALL_STAT (0xFFFFFFFF) + +/* Offset to context save area where progress info is stored */ +#define CSAVE_OFFSET 10 + +/* Defines for Byte Swapping */ +#define MCD_BYTE_SWAP_KILLER 0xFFF8888F +#define MCD_NO_BYTE_SWAP_ATALL 0x00040000 + +/* Execution Unit Identifiers */ +#define MAC 0 /* legacy - not used */ +#define LUAC 1 /* legacy - not used */ +#define CRC 2 /* legacy - not used */ +#define LURC 3 /* Logic Unit with CRC */ + +/* Task Identifiers */ +#define TASK_CHAINNOEU 0 +#define TASK_SINGLENOEU 1 +#ifdef MCD_INCLUDE_EU +#define TASK_CHAINEU 2 +#define TASK_SINGLEEU 3 +#define TASK_FECRX 4 +#define TASK_FECTX 5 +#else +#define TASK_CHAINEU 0 +#define TASK_SINGLEEU 1 +#define TASK_FECRX 2 +#define TASK_FECTX 3 +#endif + +/* + * Structure to remember which variant is on which channel + * TBD- need this? + */ +typedef struct MCD_remVariants_struct MCD_remVariant; +struct MCD_remVariants_struct { + int remDestRsdIncr[NCHANNELS]; /* -1,0,1 */ + int remSrcRsdIncr[NCHANNELS]; /* -1,0,1 */ + s16 remDestIncr[NCHANNELS]; /* DestIncr */ + s16 remSrcIncr[NCHANNELS]; /* srcIncr */ + u32 remXferSize[NCHANNELS]; /* xferSize */ +}; + +/* Structure to remember the startDma parameters for each channel */ +MCD_remVariant MCD_remVariants; +/********************************************************************/ +/* Function: MCD_initDma + * Purpose: Initializes the DMA API by setting up a pointer to the DMA + * registers, relocating and creating the appropriate task + * structures, and setting up some global settings + * Arguments: + * dmaBarAddr - pointer to the multichannel DMA registers + * taskTableDest - location to move DMA task code and structs to + * flags - operational parameters + * Return Value: + * MCD_TABLE_UNALIGNED if taskTableDest is not 512-byte aligned + * MCD_OK otherwise + */ +extern u32 MCD_funcDescTab0[]; + +int MCD_initDma(dmaRegs * dmaBarAddr, void *taskTableDest, u32 flags) +{ + int i; + TaskTableEntry *entryPtr; + + /* setup the local pointer to register set */ + MCD_dmaBar = dmaBarAddr; + + /* do we need to move/create a task table */ + if ((flags & MCD_RELOC_TASKS) != 0) { + int fixedSize; + u32 *fixedPtr; + /*int *tablePtr = taskTableDest;TBD */ + int varTabsOffset, funcDescTabsOffset, contextSavesOffset; + int taskDescTabsOffset; + int taskTableSize, varTabsSize, funcDescTabsSize, + contextSavesSize; + int taskDescTabSize; + + int i; + + /* check if physical address is aligned on 512 byte boundary */ + if (((u32) taskTableDest & 0x000001ff) != 0) + return (MCD_TABLE_UNALIGNED); + + /* set up local pointer to task Table */ + MCD_taskTable = taskTableDest; + + /* + * Create a task table: + * - compute aligned base offsets for variable tables and + * function descriptor tables, then + * - loop through the task table and setup the pointers + * - copy over model task table with the the actual task + * descriptor tables + */ + + taskTableSize = NCHANNELS * sizeof(TaskTableEntry); + /* align variable tables to size */ + varTabsOffset = taskTableSize + (u32) taskTableDest; + if ((varTabsOffset & (VAR_TAB_SIZE - 1)) != 0) + varTabsOffset = + (varTabsOffset + VAR_TAB_SIZE) & (~VAR_TAB_SIZE); + /* align function descriptor tables */ + varTabsSize = NCHANNELS * VAR_TAB_SIZE; + funcDescTabsOffset = varTabsOffset + varTabsSize; + + if ((funcDescTabsOffset & (FUNCDESC_TAB_SIZE - 1)) != 0) + funcDescTabsOffset = + (funcDescTabsOffset + + FUNCDESC_TAB_SIZE) & (~FUNCDESC_TAB_SIZE); + + funcDescTabsSize = FUNCDESC_TAB_NUM * FUNCDESC_TAB_SIZE; + contextSavesOffset = funcDescTabsOffset + funcDescTabsSize; + contextSavesSize = (NCHANNELS * CONTEXT_SAVE_SIZE); + fixedSize = + taskTableSize + varTabsSize + funcDescTabsSize + + contextSavesSize; + + /* zero the thing out */ + fixedPtr = (u32 *) taskTableDest; + for (i = 0; i < (fixedSize / 4); i++) + fixedPtr[i] = 0; + + entryPtr = (TaskTableEntry *) MCD_taskTable; + /* set up fixed pointers */ + for (i = 0; i < NCHANNELS; i++) { + /* update ptr to local value */ + entryPtr[i].varTab = (u32) varTabsOffset; + entryPtr[i].FDTandFlags = + (u32) funcDescTabsOffset | MCD_TT_FLAGS_DEF; + entryPtr[i].contextSaveSpace = (u32) contextSavesOffset; + varTabsOffset += VAR_TAB_SIZE; +#ifdef MCD_INCLUDE_EU + /* if not there is only one, just point to the + same one */ + funcDescTabsOffset += FUNCDESC_TAB_SIZE; +#endif + contextSavesOffset += CONTEXT_SAVE_SIZE; + } + /* copy over the function descriptor table */ + for (i = 0; i < FUNCDESC_TAB_NUM; i++) { + MCD_memcpy((void *)(entryPtr[i]. + FDTandFlags & ~MCD_TT_FLAGS_MASK), + (void *)MCD_funcDescTab0, FUNCDESC_TAB_SIZE); + } + + /* copy model task table to where the context saves stuff + leaves off */ + MCD_modelTaskTable = (TaskTableEntry *) contextSavesOffset; + + MCD_memcpy((void *)MCD_modelTaskTable, + (void *)MCD_modelTaskTableSrc, + NUMOFVARIANTS * sizeof(TaskTableEntry)); + + /* point to local version of model task table */ + entryPtr = MCD_modelTaskTable; + taskDescTabsOffset = (u32) MCD_modelTaskTable + + (NUMOFVARIANTS * sizeof(TaskTableEntry)); + + /* copy actual task code and update TDT ptrs in local + model task table */ + for (i = 0; i < NUMOFVARIANTS; i++) { + taskDescTabSize = + entryPtr[i].TDTend - entryPtr[i].TDTstart + 4; + MCD_memcpy((void *)taskDescTabsOffset, + (void *)entryPtr[i].TDTstart, + taskDescTabSize); + entryPtr[i].TDTstart = (u32) taskDescTabsOffset; + taskDescTabsOffset += taskDescTabSize; + entryPtr[i].TDTend = (u32) taskDescTabsOffset - 4; + } +#ifdef MCD_INCLUDE_EU + /* Tack single DMA BDs onto end of code so API controls + where they are since DMA might write to them */ + MCD_relocBuffDesc = + (MCD_bufDesc *) (entryPtr[NUMOFVARIANTS - 1].TDTend + 4); +#else + /* DMA does not touch them so they can be wherever and we + don't need to waste SRAM on them */ + MCD_relocBuffDesc = MCD_singleBufDescs; +#endif + } else { + /* point the would-be relocated task tables and the + buffer descriptors to the ones the linker generated */ + + if (((u32) MCD_realTaskTableSrc & 0x000001ff) != 0) + return (MCD_TABLE_UNALIGNED); + + /* need to add code to make sure that every thing else is + aligned properly TBD. this is problematic if we init + more than once or after running tasks, need to add + variable to see if we have aleady init'd */ + entryPtr = MCD_realTaskTableSrc; + for (i = 0; i < NCHANNELS; i++) { + if (((entryPtr[i].varTab & (VAR_TAB_SIZE - 1)) != 0) || + ((entryPtr[i]. + FDTandFlags & (FUNCDESC_TAB_SIZE - 1)) != 0)) + return (MCD_TABLE_UNALIGNED); + } + + MCD_taskTable = MCD_realTaskTableSrc; + MCD_modelTaskTable = MCD_modelTaskTableSrc; + MCD_relocBuffDesc = MCD_singleBufDescs; + } + + /* Make all channels as totally inactive, and remember them as such: */ + + MCD_dmaBar->taskbar = (u32) MCD_taskTable; + for (i = 0; i < NCHANNELS; i++) { + MCD_dmaBar->taskControl[i] = 0x0; + MCD_chStatus[i] = MCD_NO_DMA; + } + + /* Set up pausing mechanism to inactive state: */ + /* no particular values yet for either comparator registers */ + MCD_dmaBar->debugComp1 = 0; + MCD_dmaBar->debugComp2 = 0; + MCD_dmaBar->debugControl = DBG_CTL_DISABLE; + MCD_dmaBar->debugStatus = DBG_KILL_ALL_STAT; + + /* enable or disable commbus prefetch, really need an ifdef or + something to keep from trying to set this in the 8220 */ + if ((flags & MCD_COMM_PREFETCH_EN) != 0) + MCD_dmaBar->ptdControl &= ~PTD_CTL_COMM_PREFETCH; + else + MCD_dmaBar->ptdControl |= PTD_CTL_COMM_PREFETCH; + + return (MCD_OK); +} + +/*********************** End of MCD_initDma() ***********************/ + +/********************************************************************/ +/* Function: MCD_dmaStatus + * Purpose: Returns the status of the DMA on the requested channel + * Arguments: channel - channel number + * Returns: Predefined status indicators + */ +int MCD_dmaStatus(int channel) +{ + u16 tcrValue; + + if ((channel < 0) || (channel >= NCHANNELS)) + return (MCD_CHANNEL_INVALID); + + tcrValue = MCD_dmaBar->taskControl[channel]; + if ((tcrValue & TASK_CTL_EN) == 0) { /* nothing running */ + /* if last reported with task enabled */ + if (MCD_chStatus[channel] == MCD_RUNNING + || MCD_chStatus[channel] == MCD_IDLE) + MCD_chStatus[channel] = MCD_DONE; + } else { /* something is running */ + + /* There are three possibilities: paused, running or idle. */ + if (MCD_chStatus[channel] == MCD_RUNNING + || MCD_chStatus[channel] == MCD_IDLE) { + MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT; + /* This register is selected to know which initiator is + actually asserted. */ + if ((MCD_dmaBar->ptdDebug >> channel) & 0x1) + MCD_chStatus[channel] = MCD_RUNNING; + else + MCD_chStatus[channel] = MCD_IDLE; + /* do not change the status if it is already paused. */ + } + } + return MCD_chStatus[channel]; +} + +/******************** End of MCD_dmaStatus() ************************/ + +/********************************************************************/ +/* Function: MCD_startDma + * Ppurpose: Starts a particular kind of DMA + * Arguments: + * srcAddr - the channel on which to run the DMA + * srcIncr - the address to move data from, or buffer-descriptor address + * destAddr - the amount to increment the source address per transfer + * destIncr - the address to move data to + * dmaSize - the amount to increment the destination address per transfer + * xferSize - the number bytes in of each data movement (1, 2, or 4) + * initiator - what device initiates the DMA + * priority - priority of the DMA + * flags - flags describing the DMA + * funcDesc - description of byte swapping, bit swapping, and CRC actions + * srcAddrVirt - virtual buffer descriptor address TBD + * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK + */ + +int MCD_startDma(int channel, s8 * srcAddr, s16 srcIncr, s8 * destAddr, + s16 destIncr, u32 dmaSize, u32 xferSize, u32 initiator, + int priority, u32 flags, u32 funcDesc +#ifdef MCD_NEED_ADDR_TRANS + s8 * srcAddrVirt +#endif + ) +{ + int srcRsdIncr, destRsdIncr; + int *cSave; + short xferSizeIncr; + int tcrCount = 0; +#ifdef MCD_INCLUDE_EU + u32 *realFuncArray; +#endif + + if ((channel < 0) || (channel >= NCHANNELS)) + return (MCD_CHANNEL_INVALID); + + /* tbd - need to determine the proper response to a bad funcDesc when + not including EU functions, for now, assign a benign funcDesc, but + maybe should return an error */ +#ifndef MCD_INCLUDE_EU + funcDesc = MCD_FUNC_NOEU1; +#endif + +#ifdef MCD_DEBUG + printf("startDma:Setting up params\n"); +#endif + /* Set us up for task-wise priority. We don't technically need to do + this on every start, but since the register involved is in the same + longword as other registers that users are in control of, setting + it more than once is probably preferable. That since the + documentation doesn't seem to be completely consistent about the + nature of the PTD control register. */ + MCD_dmaBar->ptdControl |= (u16) 0x8000; + + /* Not sure what we need to keep here rtm TBD */ +#if 1 + /* Calculate additional parameters to the regular DMA calls. */ + srcRsdIncr = srcIncr < 0 ? -1 : (srcIncr > 0 ? 1 : 0); + destRsdIncr = destIncr < 0 ? -1 : (destIncr > 0 ? 1 : 0); + + xferSizeIncr = (xferSize & 0xffff) | 0x20000000; + + /* Remember for each channel which variant is running. */ + MCD_remVariants.remSrcRsdIncr[channel] = srcRsdIncr; + MCD_remVariants.remDestRsdIncr[channel] = destRsdIncr; + MCD_remVariants.remDestIncr[channel] = destIncr; + MCD_remVariants.remSrcIncr[channel] = srcIncr; + MCD_remVariants.remXferSize[channel] = xferSize; +#endif + + cSave = + (int *)(MCD_taskTable[channel].contextSaveSpace) + CSAVE_OFFSET + + CURRBD; + +#ifdef MCD_INCLUDE_EU + /* may move this to EU specific calls */ + realFuncArray = + (u32 *) (MCD_taskTable[channel].FDTandFlags & 0xffffff00); + /* Modify the LURC's normal and byte-residue-loop functions according + to parameter. */ + realFuncArray[(LURC * 16)] = xferSize == 4 ? + funcDesc : xferSize == 2 ? + funcDesc & 0xfffff00f : funcDesc & 0xffff000f; + realFuncArray[(LURC * 16 + 1)] = + (funcDesc & MCD_BYTE_SWAP_KILLER) | MCD_NO_BYTE_SWAP_ATALL; +#endif + /* Write the initiator field in the TCR, and also set the + initiator-hold bit. Note that,due to a hardware quirk, this could + collide with an MDE access to the initiator-register file, so we + have to verify that the write reads back correctly. */ + + MCD_dmaBar->taskControl[channel] = + (initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM; + + while (((MCD_dmaBar->taskControl[channel] & 0x1fff) != + ((initiator << 8) | TASK_CTL_HIPRITSKEN | TASK_CTL_HLDINITNUM)) + && (tcrCount < 1000)) { + tcrCount++; + /*MCD_dmaBar->ptd_tcr[channel] = (initiator << 8) | 0x0020; */ + MCD_dmaBar->taskControl[channel] = + (initiator << 8) | TASK_CTL_HIPRITSKEN | + TASK_CTL_HLDINITNUM; + } + + MCD_dmaBar->priority[channel] = (u8) priority & PRIORITY_PRI_MASK; + /* should be albe to handle this stuff with only one write to ts reg + - tbd */ + if (channel < 8 && channel >= 0) { + MCD_dmaBar->taskSize0 &= ~(0xf << (7 - channel) * 4); + MCD_dmaBar->taskSize0 |= + (xferSize & 3) << (((7 - channel) * 4) + 2); + MCD_dmaBar->taskSize0 |= (xferSize & 3) << ((7 - channel) * 4); + } else { + MCD_dmaBar->taskSize1 &= ~(0xf << (15 - channel) * 4); + MCD_dmaBar->taskSize1 |= + (xferSize & 3) << (((15 - channel) * 4) + 2); + MCD_dmaBar->taskSize1 |= (xferSize & 3) << ((15 - channel) * 4); + } + + /* setup task table flags/options which mostly control the line + buffers */ + MCD_taskTable[channel].FDTandFlags &= ~MCD_TT_FLAGS_MASK; + MCD_taskTable[channel].FDTandFlags |= (MCD_TT_FLAGS_MASK & flags); + + if (flags & MCD_FECTX_DMA) { + /* TDTStart and TDTEnd */ + MCD_taskTable[channel].TDTstart = + MCD_modelTaskTable[TASK_FECTX].TDTstart; + MCD_taskTable[channel].TDTend = + MCD_modelTaskTable[TASK_FECTX].TDTend; + MCD_startDmaENetXmit(srcAddr, srcAddr, destAddr, MCD_taskTable, + channel); + } else if (flags & MCD_FECRX_DMA) { + /* TDTStart and TDTEnd */ + MCD_taskTable[channel].TDTstart = + MCD_modelTaskTable[TASK_FECRX].TDTstart; + MCD_taskTable[channel].TDTend = + MCD_modelTaskTable[TASK_FECRX].TDTend; + MCD_startDmaENetRcv(srcAddr, srcAddr, destAddr, MCD_taskTable, + channel); + } else if (flags & MCD_SINGLE_DMA) { + /* this buffer descriptor is used for storing off initial + parameters for later progress query calculation and for the + DMA to write the resulting checksum. The DMA does not use + this to determine how to operate, that info is passed with + the init routine */ + MCD_relocBuffDesc[channel].srcAddr = srcAddr; + MCD_relocBuffDesc[channel].destAddr = destAddr; + + /* definitely not its final value */ + MCD_relocBuffDesc[channel].lastDestAddr = destAddr; + + MCD_relocBuffDesc[channel].dmaSize = dmaSize; + MCD_relocBuffDesc[channel].flags = 0; /* not used */ + MCD_relocBuffDesc[channel].csumResult = 0; /* not used */ + MCD_relocBuffDesc[channel].next = 0; /* not used */ + + /* Initialize the progress-querying stuff to show no + progress: */ + ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[SRCPTR + CSAVE_OFFSET] = (int)srcAddr; + ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[DESTPTR + CSAVE_OFFSET] = (int)destAddr; + ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0; + ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[CURRBD + CSAVE_OFFSET] = +(u32) & (MCD_relocBuffDesc[channel]); + /* tbd - need to keep the user from trying to call the EU + routine when MCD_INCLUDE_EU is not defined */ + if (funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2) { + /* TDTStart and TDTEnd */ + MCD_taskTable[channel].TDTstart = + MCD_modelTaskTable[TASK_SINGLENOEU].TDTstart; + MCD_taskTable[channel].TDTend = + MCD_modelTaskTable[TASK_SINGLENOEU].TDTend; + MCD_startDmaSingleNoEu(srcAddr, srcIncr, destAddr, + destIncr, dmaSize, xferSizeIncr, + flags, (int *) + &(MCD_relocBuffDesc[channel]), + cSave, MCD_taskTable, channel); + } else { + /* TDTStart and TDTEnd */ + MCD_taskTable[channel].TDTstart = + MCD_modelTaskTable[TASK_SINGLEEU].TDTstart; + MCD_taskTable[channel].TDTend = + MCD_modelTaskTable[TASK_SINGLEEU].TDTend; + MCD_startDmaSingleEu(srcAddr, srcIncr, destAddr, + destIncr, dmaSize, xferSizeIncr, + flags, (int *) + &(MCD_relocBuffDesc[channel]), + cSave, MCD_taskTable, channel); + } + } else { /* chained DMAS */ + /* Initialize the progress-querying stuff to show no + progress: */ +#if 1 + /* (!defined(MCD_NEED_ADDR_TRANS)) */ + ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[SRCPTR + CSAVE_OFFSET] + = (int)((MCD_bufDesc *) srcAddr)->srcAddr; + ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[DESTPTR + CSAVE_OFFSET] + = (int)((MCD_bufDesc *) srcAddr)->destAddr; +#else + /* if using address translation, need the virtual addr of the + first buffdesc */ + ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[SRCPTR + CSAVE_OFFSET] + = (int)((MCD_bufDesc *) srcAddrVirt)->srcAddr; + ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[DESTPTR + CSAVE_OFFSET] + = (int)((MCD_bufDesc *) srcAddrVirt)->destAddr; +#endif + ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[DCOUNT + CSAVE_OFFSET] = 0; + ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[CURRBD + CSAVE_OFFSET] = (u32) srcAddr; + + if (funcDesc == MCD_FUNC_NOEU1 || funcDesc == MCD_FUNC_NOEU2) { + /*TDTStart and TDTEnd */ + MCD_taskTable[channel].TDTstart = + MCD_modelTaskTable[TASK_CHAINNOEU].TDTstart; + MCD_taskTable[channel].TDTend = + MCD_modelTaskTable[TASK_CHAINNOEU].TDTend; + MCD_startDmaChainNoEu((int *)srcAddr, srcIncr, + destIncr, xferSize, + xferSizeIncr, cSave, + MCD_taskTable, channel); + } else { + /*TDTStart and TDTEnd */ + MCD_taskTable[channel].TDTstart = + MCD_modelTaskTable[TASK_CHAINEU].TDTstart; + MCD_taskTable[channel].TDTend = + MCD_modelTaskTable[TASK_CHAINEU].TDTend; + MCD_startDmaChainEu((int *)srcAddr, srcIncr, destIncr, + xferSize, xferSizeIncr, cSave, + MCD_taskTable, channel); + } + } + MCD_chStatus[channel] = MCD_IDLE; + return (MCD_OK); +} + +/************************ End of MCD_startDma() *********************/ + +/********************************************************************/ +/* Function: MCD_XferProgrQuery + * Purpose: Returns progress of DMA on requested channel + * Arguments: channel - channel to retrieve progress for + * progRep - pointer to user supplied MCD_XferProg struct + * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK + * + * Notes: + * MCD_XferProgrQuery() upon completing or after aborting a DMA, or + * while the DMA is in progress, this function returns the first + * DMA-destination address not (or not yet) used in the DMA. When + * encountering a non-ready buffer descriptor, the information for + * the last completed descriptor is returned. + * + * MCD_XferProgQuery() has to avoid the possibility of getting + * partially-updated information in the event that we should happen + * to query DMA progress just as the DMA is updating it. It does that + * by taking advantage of the fact context is not saved frequently for + * the most part. We therefore read it at least twice until we get the + * same information twice in a row. + * + * Because a small, but not insignificant, amount of time is required + * to write out the progress-query information, especially upon + * completion of the DMA, it would be wise to guarantee some time lag + * between successive readings of the progress-query information. + */ + +/* How many iterations of the loop below to execute to stabilize values */ +#define STABTIME 0 + +int MCD_XferProgrQuery(int channel, MCD_XferProg * progRep) +{ + MCD_XferProg prevRep; + int again; /* true if we are to try again to ge + consistent results */ + int i; /* used as a time-waste counter */ + int destDiffBytes; /* Total no of bytes that we think actually + got xfered. */ + int numIterations; /* number of iterations */ + int bytesNotXfered; /* bytes that did not get xfered. */ + s8 *LWAlignedInitDestAddr, *LWAlignedCurrDestAddr; + int subModVal, addModVal; /* Mode values to added and subtracted + from the final destAddr */ + + if ((channel < 0) || (channel >= NCHANNELS)) + return (MCD_CHANNEL_INVALID); + + /* Read a trial value for the progress-reporting values */ + prevRep.lastSrcAddr = + (s8 *) ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[SRCPTR + CSAVE_OFFSET]; + prevRep.lastDestAddr = + (s8 *) ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[DESTPTR + CSAVE_OFFSET]; + prevRep.dmaSize = + ((volatile int *)MCD_taskTable[channel].contextSaveSpace)[DCOUNT + + CSAVE_OFFSET]; + prevRep.currBufDesc = + (MCD_bufDesc *) ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[CURRBD + CSAVE_OFFSET]; + /* Repeatedly reread those values until they match previous values: */ + do { + /* Waste a little bit of time to ensure stability: */ + for (i = 0; i < STABTIME; i++) { + /* make sure this loop does something so that it + doesn't get optimized out */ + i += i >> 2; + } + /* Check them again: */ + progRep->lastSrcAddr = + (s8 *) ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[SRCPTR + CSAVE_OFFSET]; + progRep->lastDestAddr = + (s8 *) ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[DESTPTR + CSAVE_OFFSET]; + progRep->dmaSize = + ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[DCOUNT + CSAVE_OFFSET]; + progRep->currBufDesc = + (MCD_bufDesc *) ((volatile int *)MCD_taskTable[channel]. + contextSaveSpace)[CURRBD + CSAVE_OFFSET]; + /* See if they match: */ + if (prevRep.lastSrcAddr != progRep->lastSrcAddr + || prevRep.lastDestAddr != progRep->lastDestAddr + || prevRep.dmaSize != progRep->dmaSize + || prevRep.currBufDesc != progRep->currBufDesc) { + /* If they don't match, remember previous values and + try again: */ + prevRep.lastSrcAddr = progRep->lastSrcAddr; + prevRep.lastDestAddr = progRep->lastDestAddr; + prevRep.dmaSize = progRep->dmaSize; + prevRep.currBufDesc = progRep->currBufDesc; + again = MCD_TRUE; + } else + again = MCD_FALSE; + } while (again == MCD_TRUE); + + /* Update the dCount, srcAddr and destAddr */ + /* To calculate dmaCount, we consider destination address. C + overs M1,P1,Z for destination */ + switch (MCD_remVariants.remDestRsdIncr[channel]) { + case MINUS1: + subModVal = + ((int)progRep-> + lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - + 1); + addModVal = + ((int)progRep->currBufDesc-> + destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1); + LWAlignedInitDestAddr = + (progRep->currBufDesc->destAddr) - addModVal; + LWAlignedCurrDestAddr = (progRep->lastDestAddr) - subModVal; + destDiffBytes = LWAlignedInitDestAddr - LWAlignedCurrDestAddr; + bytesNotXfered = + (destDiffBytes / MCD_remVariants.remDestIncr[channel]) * + (MCD_remVariants.remDestIncr[channel] + + MCD_remVariants.remXferSize[channel]); + progRep->dmaSize = + destDiffBytes - bytesNotXfered + addModVal - subModVal; + break; + case ZERO: + progRep->lastDestAddr = progRep->currBufDesc->destAddr; + break; + case PLUS1: + /* This value has to be subtracted from the final + calculated dCount. */ + subModVal = + ((int)progRep->currBufDesc-> + destAddr) & ((MCD_remVariants.remXferSize[channel]) - 1); + /* These bytes are already in lastDestAddr. */ + addModVal = + ((int)progRep-> + lastDestAddr) & ((MCD_remVariants.remXferSize[channel]) - + 1); + LWAlignedInitDestAddr = + (progRep->currBufDesc->destAddr) - subModVal; + LWAlignedCurrDestAddr = (progRep->lastDestAddr) - addModVal; + destDiffBytes = (progRep->lastDestAddr - LWAlignedInitDestAddr); + numIterations = + (LWAlignedCurrDestAddr - + LWAlignedInitDestAddr) / + MCD_remVariants.remDestIncr[channel]; + bytesNotXfered = + numIterations * (MCD_remVariants.remDestIncr[channel] + - MCD_remVariants.remXferSize[channel]); + progRep->dmaSize = destDiffBytes - bytesNotXfered - subModVal; + break; + default: + break; + } + + /* This covers M1,P1,Z for source */ + switch (MCD_remVariants.remSrcRsdIncr[channel]) { + case MINUS1: + progRep->lastSrcAddr = + progRep->currBufDesc->srcAddr + + (MCD_remVariants.remSrcIncr[channel] * + (progRep->dmaSize / MCD_remVariants.remXferSize[channel])); + break; + case ZERO: + progRep->lastSrcAddr = progRep->currBufDesc->srcAddr; + break; + case PLUS1: + progRep->lastSrcAddr = + progRep->currBufDesc->srcAddr + + (MCD_remVariants.remSrcIncr[channel] * + (progRep->dmaSize / MCD_remVariants.remXferSize[channel])); + break; + default: + break; + } + + return (MCD_OK); +} + +/******************* End of MCD_XferProgrQuery() ********************/ + +/********************************************************************/ +/* MCD_resmActions() does the majority of the actions of a DMA resume. + * It is called from MCD_killDma() and MCD_resumeDma(). It has to be + * a separate function because the kill function has to negate the task + * enable before resuming it, but the resume function has to do nothing + * if there is no DMA on that channel (i.e., if the enable bit is 0). + */ +static void MCD_resmActions(int channel) +{ + MCD_dmaBar->debugControl = DBG_CTL_DISABLE; + MCD_dmaBar->debugStatus = MCD_dmaBar->debugStatus; + /* This register is selected to know which initiator is + actually asserted. */ + MCD_dmaBar->ptdDebug = PTD_DBG_TSK_VLD_INIT; + + if ((MCD_dmaBar->ptdDebug >> channel) & 0x1) + MCD_chStatus[channel] = MCD_RUNNING; + else + MCD_chStatus[channel] = MCD_IDLE; +} + +/********************* End of MCD_resmActions() *********************/ + +/********************************************************************/ +/* Function: MCD_killDma + * Purpose: Halt the DMA on the requested channel, without any + * intention of resuming the DMA. + * Arguments: channel - requested channel + * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK + * + * Notes: + * A DMA may be killed from any state, including paused state, and it + * always goes to the MCD_HALTED state even if it is killed while in + * the MCD_NO_DMA or MCD_IDLE states. + */ +int MCD_killDma(int channel) +{ + /* MCD_XferProg progRep; */ + + if ((channel < 0) || (channel >= NCHANNELS)) + return (MCD_CHANNEL_INVALID); + + MCD_dmaBar->taskControl[channel] = 0x0; + MCD_resumeDma(channel); + /* + * This must be after the write to the TCR so that the task doesn't + * start up again momentarily, and before the status assignment so + * as to override whatever MCD_resumeDma() may do to the channel + * status. + */ + MCD_chStatus[channel] = MCD_HALTED; + + /* + * Update the current buffer descriptor's lastDestAddr field + * + * MCD_XferProgrQuery (channel, &progRep); + * progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr; + */ + return (MCD_OK); +} + +/************************ End of MCD_killDma() **********************/ + +/********************************************************************/ +/* Function: MCD_continDma + * Purpose: Continue a DMA which as stopped due to encountering an + * unready buffer descriptor. + * Arguments: channel - channel to continue the DMA on + * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK + * + * Notes: + * This routine does not check to see if there is a task which can + * be continued. Also this routine should not be used with single DMAs. + */ +int MCD_continDma(int channel) +{ + if ((channel < 0) || (channel >= NCHANNELS)) + return (MCD_CHANNEL_INVALID); + + MCD_dmaBar->taskControl[channel] |= TASK_CTL_EN; + MCD_chStatus[channel] = MCD_RUNNING; + + return (MCD_OK); +} + +/********************** End of MCD_continDma() **********************/ + +/********************************************************************* + * MCD_pauseDma() and MCD_resumeDma() below use the DMA's debug unit + * to freeze a task and resume it. We freeze a task by breakpointing + * on the stated task. That is, not any specific place in the task, + * but any time that task executes. In particular, when that task + * executes, we want to freeze that task and only that task. + * + * The bits of the debug control register influence interrupts vs. + * breakpoints as follows: + * - Bits 14 and 0 enable or disable debug functions. If enabled, you + * will get the interrupt but you may or may not get a breakpoint. + * - Bits 2 and 1 decide whether you also get a breakpoint in addition + * to an interrupt. + * + * The debug unit can do these actions in response to either internally + * detected breakpoint conditions from the comparators, or in response + * to the external breakpoint pin, or both. + * - Bits 14 and 1 perform the above-described functions for + * internally-generated conditions, i.e., the debug comparators. + * - Bits 0 and 2 perform the above-described functions for external + * conditions, i.e., the breakpoint external pin. + * + * Note that, although you "always" get the interrupt when you turn + * the debug functions, the interrupt can nevertheless, if desired, be + * masked by the corresponding bit in the PTD's IMR. Note also that + * this means that bits 14 and 0 must enable debug functions before + * bits 1 and 2, respectively, have any effect. + * + * NOTE: It's extremely important to not pause more than one DMA channel + * at a time. + ********************************************************************/ + +/********************************************************************/ +/* Function: MCD_pauseDma + * Purpose: Pauses the DMA on a given channel (if any DMA is running + * on that channel). + * Arguments: channel + * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK + */ +int MCD_pauseDma(int channel) +{ + /* MCD_XferProg progRep; */ + + if ((channel < 0) || (channel >= NCHANNELS)) + return (MCD_CHANNEL_INVALID); + + if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN) { + MCD_dmaBar->debugComp1 = channel; + MCD_dmaBar->debugControl = + DBG_CTL_ENABLE | (1 << (channel + 16)); + MCD_chStatus[channel] = MCD_PAUSED; + + /* + * Update the current buffer descriptor's lastDestAddr field + * + * MCD_XferProgrQuery (channel, &progRep); + * progRep.currBufDesc->lastDestAddr = progRep.lastDestAddr; + */ + } + return (MCD_OK); +} + +/************************* End of MCD_pauseDma() ********************/ + +/********************************************************************/ +/* Function: MCD_resumeDma + * Purpose: Resumes the DMA on a given channel (if any DMA is + * running on that channel). + * Arguments: channel - channel on which to resume DMA + * Returns: MCD_CHANNEL_INVALID if channel is invalid, else MCD_OK + */ +int MCD_resumeDma(int channel) +{ + if ((channel < 0) || (channel >= NCHANNELS)) + return (MCD_CHANNEL_INVALID); + + if (MCD_dmaBar->taskControl[channel] & TASK_CTL_EN) + MCD_resmActions(channel); + + return (MCD_OK); +} + +/************************ End of MCD_resumeDma() ********************/ + +/********************************************************************/ +/* Function: MCD_csumQuery + * Purpose: Provide the checksum after performing a non-chained DMA + * Arguments: channel - channel to report on + * csum - pointer to where to write the checksum/CRC + * Returns: MCD_ERROR if the channel is invalid, else MCD_OK + * + * Notes: + * + */ +int MCD_csumQuery(int channel, u32 * csum) +{ +#ifdef MCD_INCLUDE_EU + if ((channel < 0) || (channel >= NCHANNELS)) + return (MCD_CHANNEL_INVALID); + + *csum = MCD_relocBuffDesc[channel].csumResult; + return (MCD_OK); +#else + return (MCD_ERROR); +#endif +} + +/*********************** End of MCD_resumeDma() *********************/ + +/********************************************************************/ +/* Function: MCD_getCodeSize + * Purpose: Provide the size requirements of the microcoded tasks + * Returns: Size in bytes + */ +int MCD_getCodeSize(void) +{ +#ifdef MCD_INCLUDE_EU + return (0x2b5c); +#else + return (0x173c); +#endif +} + +/********************** End of MCD_getCodeSize() ********************/ + +/********************************************************************/ +/* Function: MCD_getVersion + * Purpose: Provide the version string and number + * Arguments: longVersion - user supplied pointer to a pointer to a char + * which points to the version string + * Returns: Version number and version string (by reference) + */ +char MCD_versionString[] = "Multi-channel DMA API Alpha v0.3 (2004-04-26)"; +#define MCD_REV_MAJOR 0x00 +#define MCD_REV_MINOR 0x03 + +int MCD_getVersion(char **longVersion) +{ + *longVersion = MCD_versionString; + return ((MCD_REV_MAJOR << 8) | MCD_REV_MINOR); +} + +/********************** End of MCD_getVersion() *********************/ + +/********************************************************************/ +/* Private version of memcpy() + * Note that everything this is used for is longword-aligned. + */ +static void MCD_memcpy(int *dest, int *src, u32 size) +{ + u32 i; + + for (i = 0; i < size; i += sizeof(int), dest++, src++) + *dest = *src; +} +#endif /* CONFIG_FSLDMAFEC */ diff --git a/drivers/dma/MCD_tasks.c b/drivers/dma/MCD_tasks.c new file mode 100644 index 0000000..694e780 --- /dev/null +++ b/drivers/dma/MCD_tasks.c @@ -0,0 +1,2428 @@ +/* + * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +/* Contains task code and structures for Multi-channel DMA */ + +#include <MCD_dma.h> + +u32 MCD_varTab0[]; +u32 MCD_varTab1[]; +u32 MCD_varTab2[]; +u32 MCD_varTab3[]; +u32 MCD_varTab4[]; +u32 MCD_varTab5[]; +u32 MCD_varTab6[]; +u32 MCD_varTab7[]; +u32 MCD_varTab8[]; +u32 MCD_varTab9[]; +u32 MCD_varTab10[]; +u32 MCD_varTab11[]; +u32 MCD_varTab12[]; +u32 MCD_varTab13[]; +u32 MCD_varTab14[]; +u32 MCD_varTab15[]; + +u32 MCD_funcDescTab0[]; +#ifdef MCD_INCLUDE_EU +u32 MCD_funcDescTab1[]; +u32 MCD_funcDescTab2[]; +u32 MCD_funcDescTab3[]; +u32 MCD_funcDescTab4[]; +u32 MCD_funcDescTab5[]; +u32 MCD_funcDescTab6[]; +u32 MCD_funcDescTab7[]; +u32 MCD_funcDescTab8[]; +u32 MCD_funcDescTab9[]; +u32 MCD_funcDescTab10[]; +u32 MCD_funcDescTab11[]; +u32 MCD_funcDescTab12[]; +u32 MCD_funcDescTab13[]; +u32 MCD_funcDescTab14[]; +u32 MCD_funcDescTab15[]; +#endif + +u32 MCD_contextSave0[]; +u32 MCD_contextSave1[]; +u32 MCD_contextSave2[]; +u32 MCD_contextSave3[]; +u32 MCD_contextSave4[]; +u32 MCD_contextSave5[]; +u32 MCD_contextSave6[]; +u32 MCD_contextSave7[]; +u32 MCD_contextSave8[]; +u32 MCD_contextSave9[]; +u32 MCD_contextSave10[]; +u32 MCD_contextSave11[]; +u32 MCD_contextSave12[]; +u32 MCD_contextSave13[]; +u32 MCD_contextSave14[]; +u32 MCD_contextSave15[]; + +u32 MCD_realTaskTableSrc[] = { + 0x00000000, + 0x00000000, + (u32) MCD_varTab0, /* Task 0 Variable Table */ + (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ + 0x00000000, + 0x00000000, + (u32) MCD_contextSave0, /* Task 0 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_varTab1, /* Task 1 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32) MCD_funcDescTab1, /* Task 1 Fn Desc. Table & Flags */ +#else + (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32) MCD_contextSave1, /* Task 1 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_varTab2, /* Task 2 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32) MCD_funcDescTab2, /* Task 2 Fn Desc. Table & Flags */ +#else + (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32) MCD_contextSave2, /* Task 2 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_varTab3, /* Task 3 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32) MCD_funcDescTab3, /* Task 3 Fn Desc. Table & Flags */ +#else + (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32) MCD_contextSave3, /* Task 3 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_varTab4, /* Task 4 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32) MCD_funcDescTab4, /* Task 4 Fn Desc. Table & Flags */ +#else + (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32) MCD_contextSave4, /* Task 4 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_varTab5, /* Task 5 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32) MCD_funcDescTab5, /* Task 5 Fn Desc. Table & Flags */ +#else + (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32) MCD_contextSave5, /* Task 5 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_varTab6, /* Task 6 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32) MCD_funcDescTab6, /* Task 6 Fn Desc. Table & Flags */ +#else + (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32) MCD_contextSave6, /* Task 6 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_varTab7, /* Task 7 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32) MCD_funcDescTab7, /* Task 7 Fn Desc. Table & Flags */ +#else + (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32) MCD_contextSave7, /* Task 7 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_varTab8, /* Task 8 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32) MCD_funcDescTab8, /* Task 8 Fn Desc. Table & Flags */ +#else + (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32) MCD_contextSave8, /* Task 8 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_varTab9, /* Task 9 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32) MCD_funcDescTab9, /* Task 9 Fn Desc. Table & Flags */ +#else + (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32) MCD_contextSave9, /* Task 9 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_varTab10, /* Task 10 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32) MCD_funcDescTab10, /* Task 10 Fn Desc. Table & Flags */ +#else + (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32) MCD_contextSave10, /* Task 10 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_varTab11, /* Task 11 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32) MCD_funcDescTab11, /* Task 11 Fn Desc. Table & Flags */ +#else + (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32) MCD_contextSave11, /* Task 11 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_varTab12, /* Task 12 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32) MCD_funcDescTab12, /* Task 12 Fn Desc. Table & Flags */ +#else + (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32) MCD_contextSave12, /* Task 12 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_varTab13, /* Task 13 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32) MCD_funcDescTab13, /* Task 13 Fn Desc. Table & Flags */ +#else + (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32) MCD_contextSave13, /* Task 13 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_varTab14, /* Task 14 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32) MCD_funcDescTab14, /* Task 14 Fn Desc. Table & Flags */ +#else + (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32) MCD_contextSave14, /* Task 14 context save space */ + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_varTab15, /* Task 15 Variable Table */ +#ifdef MCD_INCLUDE_EU + (u32) MCD_funcDescTab15, /* Task 15 Fn Desc. Table & Flags */ +#else + (u32) MCD_funcDescTab0, /* Task 0 Fn Desc. Table & Flags */ +#endif + 0x00000000, + 0x00000000, + (u32) MCD_contextSave15, /* Task 15 context save space */ + 0x00000000, +}; + +u32 MCD_varTab0[] = { /* Task 0 Variable Table */ + 0x00000000, /* var[0] */ + 0x00000000, /* var[1] */ + 0x00000000, /* var[2] */ + 0x00000000, /* var[3] */ + 0x00000000, /* var[4] */ + 0x00000000, /* var[5] */ + 0x00000000, /* var[6] */ + 0x00000000, /* var[7] */ + 0x00000000, /* var[8] */ + 0x00000000, /* var[9] */ + 0x00000000, /* var[10] */ + 0x00000000, /* var[11] */ + 0x00000000, /* var[12] */ + 0x00000000, /* var[13] */ + 0x00000000, /* var[14] */ + 0x00000000, /* var[15] */ + 0x00000000, /* var[16] */ + 0x00000000, /* var[17] */ + 0x00000000, /* var[18] */ + 0x00000000, /* var[19] */ + 0x00000000, /* var[20] */ + 0x00000000, /* var[21] */ + 0x00000000, /* var[22] */ + 0x00000000, /* var[23] */ + 0xe0000000, /* inc[0] */ + 0x20000000, /* inc[1] */ + 0x2000ffff, /* inc[2] */ + 0x00000000, /* inc[3] */ + 0x00000000, /* inc[4] */ + 0x00000000, /* inc[5] */ + 0x00000000, /* inc[6] */ + 0x00000000, /* inc[7] */ +}; + +u32 MCD_varTab1[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xe0000000, + 0x20000000, + 0x2000ffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +u32 MCD_varTab2[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xe0000000, + 0x20000000, + 0x2000ffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +u32 MCD_varTab3[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xe0000000, + 0x20000000, + 0x2000ffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +u32 MCD_varTab4[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xe0000000, + 0x20000000, + 0x2000ffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +u32 MCD_varTab5[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xe0000000, + 0x20000000, + 0x2000ffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +u32 MCD_varTab6[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xe0000000, + 0x20000000, + 0x2000ffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +u32 MCD_varTab7[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xe0000000, + 0x20000000, + 0x2000ffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +u32 MCD_varTab8[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xe0000000, + 0x20000000, + 0x2000ffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +u32 MCD_varTab9[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xe0000000, + 0x20000000, + 0x2000ffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +u32 MCD_varTab10[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xe0000000, + 0x20000000, + 0x2000ffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +u32 MCD_varTab11[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xe0000000, + 0x20000000, + 0x2000ffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +u32 MCD_varTab12[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xe0000000, + 0x20000000, + 0x2000ffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +u32 MCD_varTab13[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xe0000000, + 0x20000000, + 0x2000ffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +u32 MCD_varTab14[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xe0000000, + 0x20000000, + 0x2000ffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +u32 MCD_varTab15[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xe0000000, + 0x20000000, + 0x2000ffff, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +u32 MCD_funcDescTab0[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, + 0xa0000000, + 0xa0000000, + 0x20000000, + 0x21800000, + 0x21e00000, + 0x20400000, + 0x20500000, + 0x205a0000, + 0x20a00000, + 0x202fa000, + 0x202f9000, + 0x202ea000, + 0x202da000, + 0x202e2000, + 0x202f2000, +}; + +#ifdef MCD_INCLUDE_EU +u32 MCD_funcDescTab1[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, + 0xa0000000, + 0xa0000000, + 0x20000000, + 0x21800000, + 0x21e00000, + 0x20400000, + 0x20500000, + 0x205a0000, + 0x20a00000, + 0x202fa000, + 0x202f9000, + 0x202ea000, + 0x202da000, + 0x202e2000, + 0x202f2000, +}; + +u32 MCD_funcDescTab2[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, + 0xa0000000, + 0xa0000000, + 0x20000000, + 0x21800000, + 0x21e00000, + 0x20400000, + 0x20500000, + 0x205a0000, + 0x20a00000, + 0x202fa000, + 0x202f9000, + 0x202ea000, + 0x202da000, + 0x202e2000, + 0x202f2000, +}; + +u32 MCD_funcDescTab3[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, + 0xa0000000, + 0xa0000000, + 0x20000000, + 0x21800000, + 0x21e00000, + 0x20400000, + 0x20500000, + 0x205a0000, + 0x20a00000, + 0x202fa000, + 0x202f9000, + 0x202ea000, + 0x202da000, + 0x202e2000, + 0x202f2000, +}; + +u32 MCD_funcDescTab4[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, + 0xa0000000, + 0xa0000000, + 0x20000000, + 0x21800000, + 0x21e00000, + 0x20400000, + 0x20500000, + 0x205a0000, + 0x20a00000, + 0x202fa000, + 0x202f9000, + 0x202ea000, + 0x202da000, + 0x202e2000, + 0x202f2000, +}; + +u32 MCD_funcDescTab5[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, + 0xa0000000, + 0xa0000000, + 0x20000000, + 0x21800000, + 0x21e00000, + 0x20400000, + 0x20500000, + 0x205a0000, + 0x20a00000, + 0x202fa000, + 0x202f9000, + 0x202ea000, + 0x202da000, + 0x202e2000, + 0x202f2000, +}; + +u32 MCD_funcDescTab6[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, + 0xa0000000, + 0xa0000000, + 0x20000000, + 0x21800000, + 0x21e00000, + 0x20400000, + 0x20500000, + 0x205a0000, + 0x20a00000, + 0x202fa000, + 0x202f9000, + 0x202ea000, + 0x202da000, + 0x202e2000, + 0x202f2000, +}; + +u32 MCD_funcDescTab7[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, + 0xa0000000, + 0xa0000000, + 0x20000000, + 0x21800000, + 0x21e00000, + 0x20400000, + 0x20500000, + 0x205a0000, + 0x20a00000, + 0x202fa000, + 0x202f9000, + 0x202ea000, + 0x202da000, + 0x202e2000, + 0x202f2000, +}; + +u32 MCD_funcDescTab8[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, + 0xa0000000, + 0xa0000000, + 0x20000000, + 0x21800000, + 0x21e00000, + 0x20400000, + 0x20500000, + 0x205a0000, + 0x20a00000, + 0x202fa000, + 0x202f9000, + 0x202ea000, + 0x202da000, + 0x202e2000, + 0x202f2000, +}; + +u32 MCD_funcDescTab9[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, + 0xa0000000, + 0xa0000000, + 0x20000000, + 0x21800000, + 0x21e00000, + 0x20400000, + 0x20500000, + 0x205a0000, + 0x20a00000, + 0x202fa000, + 0x202f9000, + 0x202ea000, + 0x202da000, + 0x202e2000, + 0x202f2000, +}; + +u32 MCD_funcDescTab10[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, + 0xa0000000, + 0xa0000000, + 0x20000000, + 0x21800000, + 0x21e00000, + 0x20400000, + 0x20500000, + 0x205a0000, + 0x20a00000, + 0x202fa000, + 0x202f9000, + 0x202ea000, + 0x202da000, + 0x202e2000, + 0x202f2000, +}; + +u32 MCD_funcDescTab11[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, + 0xa0000000, + 0xa0000000, + 0x20000000, + 0x21800000, + 0x21e00000, + 0x20400000, + 0x20500000, + 0x205a0000, + 0x20a00000, + 0x202fa000, + 0x202f9000, + 0x202ea000, + 0x202da000, + 0x202e2000, + 0x202f2000, +}; + +u32 MCD_funcDescTab12[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, + 0xa0000000, + 0xa0000000, + 0x20000000, + 0x21800000, + 0x21e00000, + 0x20400000, + 0x20500000, + 0x205a0000, + 0x20a00000, + 0x202fa000, + 0x202f9000, + 0x202ea000, + 0x202da000, + 0x202e2000, + 0x202f2000, +}; + +u32 MCD_funcDescTab13[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, + 0xa0000000, + 0xa0000000, + 0x20000000, + 0x21800000, + 0x21e00000, + 0x20400000, + 0x20500000, + 0x205a0000, + 0x20a00000, + 0x202fa000, + 0x202f9000, + 0x202ea000, + 0x202da000, + 0x202e2000, + 0x202f2000, +}; + +u32 MCD_funcDescTab14[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, + 0xa0000000, + 0xa0000000, + 0x20000000, + 0x21800000, + 0x21e00000, + 0x20400000, + 0x20500000, + 0x205a0000, + 0x20a00000, + 0x202fa000, + 0x202f9000, + 0x202ea000, + 0x202da000, + 0x202e2000, + 0x202f2000, +}; + +u32 MCD_funcDescTab15[] = { + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0xa0045670, + 0xa0000000, + 0xa0000000, + 0x20000000, + 0x21800000, + 0x21e00000, + 0x20400000, + 0x20500000, + 0x205a0000, + 0x20a00000, + 0x202fa000, + 0x202f9000, + 0x202ea000, + 0x202da000, + 0x202e2000, + 0x202f2000, +}; +#endif /*MCD_INCLUDE_EU */ + +u32 MCD_contextSave0[128]; /* Task 0 context save space */ +u32 MCD_contextSave1[128]; /* Task 1 context save space */ +u32 MCD_contextSave2[128]; /* Task 2 context save space */ +u32 MCD_contextSave3[128]; /* Task 3 context save space */ +u32 MCD_contextSave4[128]; /* Task 4 context save space */ +u32 MCD_contextSave5[128]; /* Task 5 context save space */ +u32 MCD_contextSave6[128]; /* Task 6 context save space */ +u32 MCD_contextSave7[128]; /* Task 7 context save space */ +u32 MCD_contextSave8[128]; /* Task 8 context save space */ +u32 MCD_contextSave9[128]; /* Task 9 context save space */ +u32 MCD_contextSave10[128]; /* Task 10 context save space */ +u32 MCD_contextSave11[128]; /* Task 11 context save space */ +u32 MCD_contextSave12[128]; /* Task 12 context save space */ +u32 MCD_contextSave13[128]; /* Task 13 context save space */ +u32 MCD_contextSave14[128]; /* Task 14 context save space */ +u32 MCD_contextSave15[128]; /* Task 15 context save space */ + +u32 MCD_ChainNoEu_TDT[]; +u32 MCD_SingleNoEu_TDT[]; +#ifdef MCD_INCLUDE_EU +u32 MCD_ChainEu_TDT[]; +u32 MCD_SingleEu_TDT[]; +#endif +u32 MCD_ENetRcv_TDT[]; +u32 MCD_ENetXmit_TDT[]; + +u32 MCD_modelTaskTableSrc[] = { + (u32) MCD_ChainNoEu_TDT, + (u32) & ((u8 *) MCD_ChainNoEu_TDT)[0x0000016c], + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_SingleNoEu_TDT, + (u32) & ((u8 *) MCD_SingleNoEu_TDT)[0x000000d4], + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +#ifdef MCD_INCLUDE_EU + (u32) MCD_ChainEu_TDT, + (u32) & ((u8 *) MCD_ChainEu_TDT)[0x000001b4], + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_SingleEu_TDT, + (u32) & ((u8 *) MCD_SingleEu_TDT)[0x00000124], + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +#endif + (u32) MCD_ENetRcv_TDT, + (u32) & ((u8 *) MCD_ENetRcv_TDT)[0x0000009c], + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + (u32) MCD_ENetXmit_TDT, + (u32) & ((u8 *) MCD_ENetXmit_TDT)[0x000000d0], + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, +}; + +u32 MCD_ChainNoEu_TDT[] = { + 0x80004000, + 0x8118801b, + 0xb8c60018, + 0x10002b10, + 0x7000000d, + 0x018cf89f, + 0x6000000a, + 0x080cf89f, + 0x000001f8, + 0x98180364, + 0x8118801b, + 0xf8c6001a, + 0xb8c6601b, + 0x10002710, + 0x00000f18, + 0xb8c6001d, + 0x10001310, + 0x60000007, + 0x014cf88b, + 0x98c6001c, + 0x00000710, + 0x98c70018, + 0x10001f10, + 0x0000c818, + 0x000001f8, + 0xc1476018, + 0xc003231d, + 0x811a601b, + 0xc1862102, + 0x849be009, + 0x03fed7b8, + 0xda9b001b, + 0x9b9be01b, + 0x1000cb20, + 0x70000006, + 0x088cf88f, + 0x1000cb28, + 0x70000006, + 0x088cf88f, + 0x1000cb30, + 0x70000006, + 0x088cf88f, + 0x1000cb38, + 0x0000c728, + 0x000001f8, + 0xc1476018, + 0xc003241d, + 0x811a601b, + 0xda9b001b, + 0x9b9be01b, + 0x0000d3a0, + 0xc1862102, + 0x849be009, + 0x0bfed7b8, + 0xda9b001b, + 0x9b9be01b, + 0x1000cb20, + 0x70000006, + 0x088cf88f, + 0x1000cb28, + 0x70000006, + 0x088cf88f, + 0x1000cb30, + 0x70000006, + 0x088cf88f, + 0x1000cb38, + 0x0000c728, + 0x000001f8, + 0x8118801b, + 0xd8c60018, + 0x98c6601c, + 0x6000000b, + 0x0c8cfc9f, + 0x000001f8, + 0xa146001e, + 0x10000b08, + 0x10002050, + 0xb8c60018, + 0x10002b10, + 0x7000000a, + 0x080cf89f, + 0x6000000d, + 0x018cf89f, + 0x000001f8, + 0x8618801b, + 0x7000000e, + 0x084cf21f, + 0xd8990336, + 0x8019801b, + 0x040001f8, + 0x000001f8, + 0x000001f8, +}; + +u32 MCD_SingleNoEu_TDT[] = { + 0x8198001b, + 0x7000000d, + 0x080cf81f, + 0x8198801b, + 0x6000000e, + 0x084cf85f, + 0x000001f8, + 0x8298001b, + 0x7000000d, + 0x010cf81f, + 0x6000000e, + 0x018cf81f, + 0xc202601b, + 0xc002221c, + 0x809a601b, + 0xc10420c2, + 0x839be009, + 0x03fed7b8, + 0xda9b001b, + 0x9b9be01b, + 0x70000006, + 0x088cf889, + 0x1000cb28, + 0x70000006, + 0x088cf889, + 0x1000cb30, + 0x70000006, + 0x088cf889, + 0x0000cb38, + 0x000001f8, + 0xc202601b, + 0xc002229c, + 0x809a601b, + 0xda9b001b, + 0x9b9be01b, + 0x0000d3a0, + 0xc10420c2, + 0x839be009, + 0x0bfed7b8, + 0xda9b001b, + 0x9b9be01b, + 0x70000006, + 0x088cf889, + 0x1000cb28, + 0x70000006, + 0x088cf889, + 0x1000cb30, + 0x70000006, + 0x088cf889, + 0x0000cb38, + 0x000001f8, + 0xc318022d, + 0x8018801b, + 0x040001f8, +}; + +#ifdef MCD_INCLUDE_EU +u32 MCD_ChainEu_TDT[] = { + 0x80004000, + 0x8198801b, + 0xb8c68018, + 0x10002f10, + 0x7000000d, + 0x01ccf89f, + 0x6000000a, + 0x080cf89f, + 0x000001f8, + 0x981803a4, + 0x8198801b, + 0xf8c6801a, + 0xb8c6e01b, + 0x10002b10, + 0x00001318, + 0xb8c6801d, + 0x10001710, + 0x60000007, + 0x018cf88c, + 0x98c6801c, + 0x00000b10, + 0x98c78018, + 0x10002310, + 0x0000c820, + 0x000001f8, + 0x8698801b, + 0x7000000f, + 0x084cf2df, + 0xd899042d, + 0x8019801b, + 0x60000003, + 0x2cd7c7df, + 0xd8990364, + 0x8019801b, + 0x60000003, + 0x2c17c7df, + 0x000001f8, + 0xc1c7e018, + 0xc003a35e, + 0x819a601b, + 0xc206a142, + 0x851be009, + 0x63fe0000, + 0x0d4cfddf, + 0xda9b001b, + 0x9b9be01b, + 0x70000002, + 0x004cf81f, + 0x1000cb20, + 0x70000006, + 0x088cf891, + 0x1000cb28, + 0x70000006, + 0x088cf891, + 0x1000cb30, + 0x70000006, + 0x088cf891, + 0x1000cb38, + 0x0000c728, + 0x000001f8, + 0xc1c7e018, + 0xc003a49e, + 0x819a601b, + 0xda9b001b, + 0x9b9be01b, + 0x0000d3a0, + 0xc206a142, + 0x851be009, + 0x6bfe0000, + 0x0d4cfddf, + 0xda9b001b, + 0x9b9be01b, + 0x70000002, + 0x004cf81f, + 0x1000cb20, + 0x70000006, + 0x088cf891, + 0x1000cb28, + 0x70000006, + 0x088cf891, + 0x1000cb30, + 0x70000006, + 0x088cf891, + 0x1000cb38, + 0x0000c728, + 0x000001f8, + 0x8198801b, + 0xd8c68018, + 0x98c6e01c, + 0x6000000b, + 0x0c8cfc9f, + 0x0000cc08, + 0xa1c6801e, + 0x10000f08, + 0x10002458, + 0xb8c68018, + 0x10002f10, + 0x7000000a, + 0x080cf89f, + 0x6000000d, + 0x01ccf89f, + 0x000001f8, + 0x8698801b, + 0x7000000e, + 0x084cf25f, + 0xd899037f, + 0x8019801b, + 0x040001f8, + 0x000001f8, + 0x000001f8, +}; + +u32 MCD_SingleEu_TDT[] = { + 0x8218001b, + 0x7000000d, + 0x080cf81f, + 0x8218801b, + 0x6000000e, + 0x084cf85f, + 0x000001f8, + 0x8318001b, + 0x7000000d, + 0x014cf81f, + 0x6000000e, + 0x01ccf81f, + 0x8498001b, + 0x7000000f, + 0x080cf19f, + 0xd81882a4, + 0x8019001b, + 0x60000003, + 0x2c97c7df, + 0xd818826d, + 0x8019001b, + 0x60000003, + 0x2c17c7df, + 0x000001f8, + 0xc282e01b, + 0xc002a25e, + 0x811a601b, + 0xc184a102, + 0x841be009, + 0x63fe0000, + 0x0d4cfddf, + 0xda9b001b, + 0x9b9be01b, + 0x70000002, + 0x004cf99f, + 0x70000006, + 0x088cf88b, + 0x1000cb28, + 0x70000006, + 0x088cf88b, + 0x1000cb30, + 0x70000006, + 0x088cf88b, + 0x0000cb38, + 0x000001f8, + 0xc282e01b, + 0xc002a31e, + 0x811a601b, + 0xda9b001b, + 0x9b9be01b, + 0x0000d3a0, + 0xc184a102, + 0x841be009, + 0x6bfe0000, + 0x0d4cfddf, + 0xda9b001b, + 0x9b9be01b, + 0x70000002, + 0x004cf99f, + 0x70000006, + 0x088cf88b, + 0x1000cb28, + 0x70000006, + 0x088cf88b, + 0x1000cb30, + 0x70000006, + 0x088cf88b, + 0x0000cb38, + 0x000001f8, + 0x8144801c, + 0x0000c008, + 0xc398027f, + 0x8018801b, + 0x040001f8, +}; +#endif +u32 MCD_ENetRcv_TDT[] = { + 0x80004000, + 0x81988000, + 0x10000788, + 0x6000000a, + 0x080cf05f, + 0x98180209, + 0x81c40004, + 0x7000000e, + 0x010cf05f, + 0x7000000c, + 0x01ccf05f, + 0x70000004, + 0x014cf049, + 0x70000004, + 0x004cf04a, + 0x00000b88, + 0xc4030150, + 0x8119e012, + 0x03e0cf90, + 0x81188000, + 0x000ac788, + 0xc4030000, + 0x8199e000, + 0x70000004, + 0x084cfc8b, + 0x60000005, + 0x0cccf841, + 0x81c60000, + 0xc399021b, + 0x80198000, + 0x00008400, + 0x00000f08, + 0x81988000, + 0x10000788, + 0x6000000a, + 0x080cf05f, + 0xc2188209, + 0x80190000, + 0x040001f8, + 0x000001f8, +}; + +u32 MCD_ENetXmit_TDT[] = { + 0x80004000, + 0x81988000, + 0x10000788, + 0x6000000a, + 0x080cf05f, + 0x98180309, + 0x80004003, + 0x81c60004, + 0x7000000e, + 0x014cf05f, + 0x7000000c, + 0x028cf05f, + 0x7000000d, + 0x018cf05f, + 0x70000004, + 0x01ccf04d, + 0x10000b90, + 0x60000004, + 0x020cf0a1, + 0xc3188312, + 0x83c70000, + 0x00001f10, + 0xc583a3c3, + 0x81042325, + 0x03e0c798, + 0xd8990000, + 0x9999e000, + 0x000acf98, + 0xd8992306, + 0x9999e03f, + 0x03eac798, + 0xd8990000, + 0x9999e000, + 0x000acf98, + 0xd8990000, + 0x99832302, + 0x0beac798, + 0x81988000, + 0x6000000b, + 0x0c4cfc5f, + 0x81c80000, + 0xc5190312, + 0x80198000, + 0x00008400, + 0x00000f08, + 0x81988000, + 0x10000788, + 0x6000000a, + 0x080cf05f, + 0xc2988309, + 0x80190000, + 0x040001f8, + 0x000001f8, +}; + +#ifdef MCD_INCLUDE_EU +MCD_bufDesc MCD_singleBufDescs[NCHANNELS]; +#endif diff --git a/drivers/dma/MCD_tasksInit.c b/drivers/dma/MCD_tasksInit.c new file mode 100644 index 0000000..0d28713 --- /dev/null +++ b/drivers/dma/MCD_tasksInit.c @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2004-2007 Freescale Semiconductor, Inc. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> + +/* Functions for initializing variable tables of different types of tasks. */ + +/* + * Do not edit! + */ + +#ifdef CONFIG_FSLDMAFEC + +#include <MCD_dma.h> + +extern dmaRegs *MCD_dmaBar; + +/* Task 0 */ + +void MCD_startDmaChainNoEu(int *currBD, short srcIncr, short destIncr, + int xferSize, short xferSizeIncr, int *cSave, + volatile TaskTableEntry * taskTable, int channel) +{ + volatile TaskTableEntry *taskChan = taskTable + channel; + + MCD_SET_VAR(taskChan, 2, (u32) currBD); /* var[2] */ + MCD_SET_VAR(taskChan, 25, (u32) (0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */ + MCD_SET_VAR(taskChan, 24, (u32) (0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */ + MCD_SET_VAR(taskChan, 11, (u32) xferSize); /* var[11] */ + MCD_SET_VAR(taskChan, 26, (u32) (0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */ + MCD_SET_VAR(taskChan, 0, (u32) cSave); /* var[0] */ + MCD_SET_VAR(taskChan, 1, (u32) 0x00000000); /* var[1] */ + MCD_SET_VAR(taskChan, 3, (u32) 0x00000000); /* var[3] */ + MCD_SET_VAR(taskChan, 4, (u32) 0x00000000); /* var[4] */ + MCD_SET_VAR(taskChan, 5, (u32) 0x00000000); /* var[5] */ + MCD_SET_VAR(taskChan, 6, (u32) 0x00000000); /* var[6] */ + MCD_SET_VAR(taskChan, 7, (u32) 0x00000000); /* var[7] */ + MCD_SET_VAR(taskChan, 8, (u32) 0x00000000); /* var[8] */ + MCD_SET_VAR(taskChan, 9, (u32) 0x00000000); /* var[9] */ + MCD_SET_VAR(taskChan, 10, (u32) 0x00000000); /* var[10] */ + MCD_SET_VAR(taskChan, 12, (u32) 0x00000000); /* var[12] */ + MCD_SET_VAR(taskChan, 13, (u32) 0x80000000); /* var[13] */ + MCD_SET_VAR(taskChan, 14, (u32) 0x00000010); /* var[14] */ + MCD_SET_VAR(taskChan, 15, (u32) 0x00000004); /* var[15] */ + MCD_SET_VAR(taskChan, 16, (u32) 0x08000000); /* var[16] */ + MCD_SET_VAR(taskChan, 27, (u32) 0x00000000); /* inc[3] */ + MCD_SET_VAR(taskChan, 28, (u32) 0x80000000); /* inc[4] */ + MCD_SET_VAR(taskChan, 29, (u32) 0x80000001); /* inc[5] */ + MCD_SET_VAR(taskChan, 30, (u32) 0x40000000); /* inc[6] */ + + /* Set the task's Enable bit in its Task Control Register */ + MCD_dmaBar->taskControl[channel] |= (u16) 0x8000; +} + +/* Task 1 */ + +void MCD_startDmaSingleNoEu(char *srcAddr, short srcIncr, char *destAddr, + short destIncr, int dmaSize, short xferSizeIncr, + int flags, int *currBD, int *cSave, + volatile TaskTableEntry * taskTable, int channel) +{ + volatile TaskTableEntry *taskChan = taskTable + channel; + + MCD_SET_VAR(taskChan, 7, (u32) srcAddr); /* var[7] */ + MCD_SET_VAR(taskChan, 25, (u32) (0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */ + MCD_SET_VAR(taskChan, 2, (u32) destAddr); /* var[2] */ + MCD_SET_VAR(taskChan, 24, (u32) (0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */ + MCD_SET_VAR(taskChan, 3, (u32) dmaSize); /* var[3] */ + MCD_SET_VAR(taskChan, 26, (u32) (0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */ + MCD_SET_VAR(taskChan, 5, (u32) flags); /* var[5] */ + MCD_SET_VAR(taskChan, 1, (u32) currBD); /* var[1] */ + MCD_SET_VAR(taskChan, 0, (u32) cSave); /* var[0] */ + MCD_SET_VAR(taskChan, 4, (u32) 0x00000000); /* var[4] */ + MCD_SET_VAR(taskChan, 6, (u32) 0x00000000); /* var[6] */ + MCD_SET_VAR(taskChan, 8, (u32) 0x00000000); /* var[8] */ + MCD_SET_VAR(taskChan, 9, (u32) 0x00000004); /* var[9] */ + MCD_SET_VAR(taskChan, 10, (u32) 0x08000000); /* var[10] */ + MCD_SET_VAR(taskChan, 27, (u32) 0x00000000); /* inc[3] */ + MCD_SET_VAR(taskChan, 28, (u32) 0x80000001); /* inc[4] */ + MCD_SET_VAR(taskChan, 29, (u32) 0x40000000); /* inc[5] */ + + /* Set the task's Enable bit in its Task Control Register */ + MCD_dmaBar->taskControl[channel] |= (u16) 0x8000; +} + +/* Task 2 */ + +void MCD_startDmaChainEu(int *currBD, short srcIncr, short destIncr, + int xferSize, short xferSizeIncr, int *cSave, + volatile TaskTableEntry * taskTable, int channel) +{ + volatile TaskTableEntry *taskChan = taskTable + channel; + + MCD_SET_VAR(taskChan, 3, (u32) currBD); /* var[3] */ + MCD_SET_VAR(taskChan, 25, (u32) (0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */ + MCD_SET_VAR(taskChan, 24, (u32) (0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */ + MCD_SET_VAR(taskChan, 12, (u32) xferSize); /* var[12] */ + MCD_SET_VAR(taskChan, 26, (u32) (0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */ + MCD_SET_VAR(taskChan, 0, (u32) cSave); /* var[0] */ + MCD_SET_VAR(taskChan, 1, (u32) 0x00000000); /* var[1] */ + MCD_SET_VAR(taskChan, 2, (u32) 0x00000000); /* var[2] */ + MCD_SET_VAR(taskChan, 4, (u32) 0x00000000); /* var[4] */ + MCD_SET_VAR(taskChan, 5, (u32) 0x00000000); /* var[5] */ + MCD_SET_VAR(taskChan, 6, (u32) 0x00000000); /* var[6] */ + MCD_SET_VAR(taskChan, 7, (u32) 0x00000000); /* var[7] */ + MCD_SET_VAR(taskChan, 8, (u32) 0x00000000); /* var[8] */ + MCD_SET_VAR(taskChan, 9, (u32) 0x00000000); /* var[9] */ + MCD_SET_VAR(taskChan, 10, (u32) 0x00000000); /* var[10] */ + MCD_SET_VAR(taskChan, 11, (u32) 0x00000000); /* var[11] */ + MCD_SET_VAR(taskChan, 13, (u32) 0x00000000); /* var[13] */ + MCD_SET_VAR(taskChan, 14, (u32) 0x80000000); /* var[14] */ + MCD_SET_VAR(taskChan, 15, (u32) 0x00000010); /* var[15] */ + MCD_SET_VAR(taskChan, 16, (u32) 0x00000001); /* var[16] */ + MCD_SET_VAR(taskChan, 17, (u32) 0x00000004); /* var[17] */ + MCD_SET_VAR(taskChan, 18, (u32) 0x08000000); /* var[18] */ + MCD_SET_VAR(taskChan, 27, (u32) 0x00000000); /* inc[3] */ + MCD_SET_VAR(taskChan, 28, (u32) 0x80000000); /* inc[4] */ + MCD_SET_VAR(taskChan, 29, (u32) 0xc0000000); /* inc[5] */ + MCD_SET_VAR(taskChan, 30, (u32) 0x80000001); /* inc[6] */ + MCD_SET_VAR(taskChan, 31, (u32) 0x40000000); /* inc[7] */ + + /* Set the task's Enable bit in its Task Control Register */ + MCD_dmaBar->taskControl[channel] |= (u16) 0x8000; +} + +/* Task 3 */ + +void MCD_startDmaSingleEu(char *srcAddr, short srcIncr, char *destAddr, + short destIncr, int dmaSize, short xferSizeIncr, + int flags, int *currBD, int *cSave, + volatile TaskTableEntry * taskTable, int channel) +{ + volatile TaskTableEntry *taskChan = taskTable + channel; + + MCD_SET_VAR(taskChan, 8, (u32) srcAddr); /* var[8] */ + MCD_SET_VAR(taskChan, 25, (u32) (0xe000 << 16) | (0xffff & srcIncr)); /* inc[1] */ + MCD_SET_VAR(taskChan, 3, (u32) destAddr); /* var[3] */ + MCD_SET_VAR(taskChan, 24, (u32) (0xe000 << 16) | (0xffff & destIncr)); /* inc[0] */ + MCD_SET_VAR(taskChan, 4, (u32) dmaSize); /* var[4] */ + MCD_SET_VAR(taskChan, 26, (u32) (0x2000 << 16) | (0xffff & xferSizeIncr)); /* inc[2] */ + MCD_SET_VAR(taskChan, 6, (u32) flags); /* var[6] */ + MCD_SET_VAR(taskChan, 2, (u32) currBD); /* var[2] */ + MCD_SET_VAR(taskChan, 0, (u32) cSave); /* var[0] */ + MCD_SET_VAR(taskChan, 1, (u32) 0x00000000); /* var[1] */ + MCD_SET_VAR(taskChan, 5, (u32) 0x00000000); /* var[5] */ + MCD_SET_VAR(taskChan, 7, (u32) 0x00000000); /* var[7] */ + MCD_SET_VAR(taskChan, 9, (u32) 0x00000000); /* var[9] */ + MCD_SET_VAR(taskChan, 10, (u32) 0x00000001); /* var[10] */ + MCD_SET_VAR(taskChan, 11, (u32) 0x00000004); /* var[11] */ + MCD_SET_VAR(taskChan, 12, (u32) 0x08000000); /* var[12] */ + MCD_SET_VAR(taskChan, 27, (u32) 0x00000000); /* inc[3] */ + MCD_SET_VAR(taskChan, 28, (u32) 0xc0000000); /* inc[4] */ + MCD_SET_VAR(taskChan, 29, (u32) 0x80000000); /* inc[5] */ + MCD_SET_VAR(taskChan, 30, (u32) 0x80000001); /* inc[6] */ + MCD_SET_VAR(taskChan, 31, (u32) 0x40000000); /* inc[7] */ + + /* Set the task's Enable bit in its Task Control Register */ + MCD_dmaBar->taskControl[channel] |= (u16) 0x8000; +} + +/* Task 4 */ + +void MCD_startDmaENetRcv(char *bDBase, char *currBD, char *rcvFifoPtr, + volatile TaskTableEntry * taskTable, int channel) +{ + volatile TaskTableEntry *taskChan = taskTable + channel; + + MCD_SET_VAR(taskChan, 0, (u32) bDBase); /* var[0] */ + MCD_SET_VAR(taskChan, 3, (u32) currBD); /* var[3] */ + MCD_SET_VAR(taskChan, 6, (u32) rcvFifoPtr); /* var[6] */ + MCD_SET_VAR(taskChan, 1, (u32) 0x00000000); /* var[1] */ + MCD_SET_VAR(taskChan, 2, (u32) 0x00000000); /* var[2] */ + MCD_SET_VAR(taskChan, 4, (u32) 0x00000000); /* var[4] */ + MCD_SET_VAR(taskChan, 5, (u32) 0x00000000); /* var[5] */ + MCD_SET_VAR(taskChan, 7, (u32) 0x00000000); /* var[7] */ + MCD_SET_VAR(taskChan, 8, (u32) 0x00000000); /* var[8] */ + MCD_SET_VAR(taskChan, 9, (u32) 0x0000ffff); /* var[9] */ + MCD_SET_VAR(taskChan, 10, (u32) 0x30000000); /* var[10] */ + MCD_SET_VAR(taskChan, 11, (u32) 0x0fffffff); /* var[11] */ + MCD_SET_VAR(taskChan, 12, (u32) 0x00000008); /* var[12] */ + MCD_SET_VAR(taskChan, 24, (u32) 0x00000000); /* inc[0] */ + MCD_SET_VAR(taskChan, 25, (u32) 0x60000000); /* inc[1] */ + MCD_SET_VAR(taskChan, 26, (u32) 0x20000004); /* inc[2] */ + MCD_SET_VAR(taskChan, 27, (u32) 0x40000000); /* inc[3] */ + + /* Set the task's Enable bit in its Task Control Register */ + MCD_dmaBar->taskControl[channel] |= (u16) 0x8000; +} + +/* Task 5 */ + +void MCD_startDmaENetXmit(char *bDBase, char *currBD, char *xmitFifoPtr, + volatile TaskTableEntry * taskTable, int channel) +{ + volatile TaskTableEntry *taskChan = taskTable + channel; + + MCD_SET_VAR(taskChan, 0, (u32) bDBase); /* var[0] */ + MCD_SET_VAR(taskChan, 3, (u32) currBD); /* var[3] */ + MCD_SET_VAR(taskChan, 11, (u32) xmitFifoPtr); /* var[11] */ + MCD_SET_VAR(taskChan, 1, (u32) 0x00000000); /* var[1] */ + MCD_SET_VAR(taskChan, 2, (u32) 0x00000000); /* var[2] */ + MCD_SET_VAR(taskChan, 4, (u32) 0x00000000); /* var[4] */ + MCD_SET_VAR(taskChan, 5, (u32) 0x00000000); /* var[5] */ + MCD_SET_VAR(taskChan, 6, (u32) 0x00000000); /* var[6] */ + MCD_SET_VAR(taskChan, 7, (u32) 0x00000000); /* var[7] */ + MCD_SET_VAR(taskChan, 8, (u32) 0x00000000); /* var[8] */ + MCD_SET_VAR(taskChan, 9, (u32) 0x00000000); /* var[9] */ + MCD_SET_VAR(taskChan, 10, (u32) 0x00000000); /* var[10] */ + MCD_SET_VAR(taskChan, 12, (u32) 0x00000000); /* var[12] */ + MCD_SET_VAR(taskChan, 13, (u32) 0x0000ffff); /* var[13] */ + MCD_SET_VAR(taskChan, 14, (u32) 0xffffffff); /* var[14] */ + MCD_SET_VAR(taskChan, 15, (u32) 0x00000004); /* var[15] */ + MCD_SET_VAR(taskChan, 16, (u32) 0x00000008); /* var[16] */ + MCD_SET_VAR(taskChan, 24, (u32) 0x00000000); /* inc[0] */ + MCD_SET_VAR(taskChan, 25, (u32) 0x60000000); /* inc[1] */ + MCD_SET_VAR(taskChan, 26, (u32) 0x40000000); /* inc[2] */ + MCD_SET_VAR(taskChan, 27, (u32) 0xc000fffc); /* inc[3] */ + MCD_SET_VAR(taskChan, 28, (u32) 0xe0000004); /* inc[4] */ + MCD_SET_VAR(taskChan, 29, (u32) 0x80000000); /* inc[5] */ + MCD_SET_VAR(taskChan, 30, (u32) 0x4000ffff); /* inc[6] */ + MCD_SET_VAR(taskChan, 31, (u32) 0xe0000001); /* inc[7] */ + + /* Set the task's Enable bit in its Task Control Register */ + MCD_dmaBar->taskControl[channel] |= (u16) 0x8000; +} + +#endif /* CONFIG_FSLDMAFEC */ + diff --git a/drivers/dma/Makefile b/drivers/dma/Makefile new file mode 100644 index 0000000..2dd5a0e --- /dev/null +++ b/drivers/dma/Makefile @@ -0,0 +1,46 @@ +# +# (C) Copyright 2006 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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 program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB := $(obj)libdma.a + +COBJS-y += MCD_tasksInit.o MCD_dmaApi.o MCD_tasks.o + +COBJS := $(COBJS-y) +SRCS := $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) + +all: $(LIB) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile index 78cec21..67521720 100644 --- a/drivers/misc/Makefile +++ b/drivers/misc/Makefile @@ -28,6 +28,7 @@ LIB := $(obj)libmisc.a COBJS-y += ali512x.o COBJS-y += ns87308.o COBJS-y += status_led.o +COBJS-$(CONFIG_FSL_LAW) += fsl_law.o COBJS := $(COBJS-y) SRCS := $(COBJS:.o=.c) diff --git a/drivers/misc/fsl_law.c b/drivers/misc/fsl_law.c new file mode 100644 index 0000000..8bdf5a7 --- /dev/null +++ b/drivers/misc/fsl_law.c @@ -0,0 +1,70 @@ +/* + * Copyright 2008 Freescale Semiconductor, Inc. + * + * (C) Copyright 2000 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <asm/fsl_law.h> +#include <asm/io.h> + +#define LAWAR_EN 0x80000000 + +void set_law(u8 idx, phys_addr_t addr, enum law_size sz, enum law_trgt_if id) +{ + volatile u32 *base = (volatile u32 *)(CFG_IMMR + 0xc08); + volatile u32 *lawbar = base + 8 * idx; + volatile u32 *lawar = base + 8 * idx + 2; + + out_be32(lawbar, addr >> 12); + out_be32(lawar, LAWAR_EN | ((u32)id << 20) | (u32)sz); + + return ; +} + +void disable_law(u8 idx) +{ + volatile u32 *base = (volatile u32 *)(CFG_IMMR + 0xc08); + volatile u32 *lawbar = base + 8 * idx; + volatile u32 *lawar = base + 8 * idx + 2; + + out_be32(lawar, 0); + out_be32(lawbar, 0); + + return; +} + +void init_laws(void) +{ + int i; + u8 law_idx = 0; + + for (i = 0; i < num_law_entries; i++) { + if (law_table[i].index != -1) + law_idx = law_table[i].index; + + set_law(law_idx++, law_table[i].addr, + law_table[i].size, law_table[i].trgt_id); + } + + return ; +} diff --git a/drivers/net/Makefile b/drivers/net/Makefile index 41e1bde..b9723fa 100644 --- a/drivers/net/Makefile +++ b/drivers/net/Makefile @@ -33,6 +33,7 @@ COBJS-y += dm9000x.o COBJS-y += e1000.o COBJS-y += eepro100.o COBJS-y += enc28j60.o +COBJS-y += fsl_mcdmafec.o COBJS-y += inca-ip_sw.o COBJS-y += ks8695eth.o COBJS-y += lan91c96.o diff --git a/drivers/net/fsl_mcdmafec.c b/drivers/net/fsl_mcdmafec.c new file mode 100644 index 0000000..0c876f3 --- /dev/null +++ b/drivers/net/fsl_mcdmafec.c @@ -0,0 +1,571 @@ +/* + * (C) Copyright 2000-2004 + * Wolfgang Denk, DENX Software Engineering, wd@denx.de. + * + * (C) Copyright 2007 Freescale Semiconductor, Inc. + * TsiChung Liew (Tsi-Chung.Liew@freescale.com) + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <malloc.h> +#include <command.h> +#include <config.h> +#include <net.h> +#include <miiphy.h> + +#ifdef CONFIG_FSLDMAFEC +#undef ET_DEBUG +#undef MII_DEBUG + +/* Ethernet Transmit and Receive Buffers */ +#define DBUF_LENGTH 1520 +#define PKT_MAXBUF_SIZE 1518 +#define PKT_MINBUF_SIZE 64 +#define PKT_MAXBLR_SIZE 1536 +#define LAST_PKTBUFSRX PKTBUFSRX - 1 +#define BD_ENET_RX_W_E (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY) +#define BD_ENET_TX_RDY_LST (BD_ENET_TX_READY | BD_ENET_TX_LAST) +#define FIFO_ERRSTAT (FIFO_STAT_RXW | FIFO_STAT_UF | FIFO_STAT_OF) + +/* RxBD bits definitions */ +#define BD_ENET_RX_ERR (BD_ENET_RX_LG | BD_ENET_RX_NO | BD_ENET_RX_CR | \ + BD_ENET_RX_OV | BD_ENET_RX_TR) + +#if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) +#include <asm/immap.h> +#include <asm/fsl_mcdmafec.h> + +#include "MCD_dma.h" + +DECLARE_GLOBAL_DATA_PTR; + +struct fec_info_dma fec_info[] = { +#ifdef CFG_FEC0_IOBASE + { + 0, /* index */ + CFG_FEC0_IOBASE, /* io base */ + CFG_FEC0_PINMUX, /* gpio pin muxing */ + CFG_FEC0_MIIBASE, /* mii base */ + -1, /* phy_addr */ + 0, /* duplex and speed */ + 0, /* phy name */ + 0, /* phyname init */ + 0, /* RX BD */ + 0, /* TX BD */ + 0, /* rx Index */ + 0, /* tx Index */ + 0, /* tx buffer */ + 0, /* initialized flag */ + (struct fec_info_dma *)-1, /* next */ + FEC0_RX_TASK, /* rxTask */ + FEC0_TX_TASK, /* txTask */ + FEC0_RX_PRIORITY, /* rxPri */ + FEC0_TX_PRIORITY, /* txPri */ + FEC0_RX_INIT, /* rxInit */ + FEC0_TX_INIT, /* txInit */ + 0, /* usedTbdIndex */ + 0, /* cleanTbdNum */ + }, +#endif +#ifdef CFG_FEC1_IOBASE + { + 1, /* index */ + CFG_FEC1_IOBASE, /* io base */ + CFG_FEC1_PINMUX, /* gpio pin muxing */ + CFG_FEC1_MIIBASE, /* mii base */ + -1, /* phy_addr */ + 0, /* duplex and speed */ + 0, /* phy name */ + 0, /* phy name init */ + 0, /* RX BD */ + 0, /* TX BD */ + 0, /* rx Index */ + 0, /* tx Index */ + 0, /* tx buffer */ + 0, /* initialized flag */ + (struct fec_info_dma *)-1, /* next */ + FEC1_RX_TASK, /* rxTask */ + FEC1_TX_TASK, /* txTask */ + FEC1_RX_PRIORITY, /* rxPri */ + FEC1_TX_PRIORITY, /* txPri */ + FEC1_RX_INIT, /* rxInit */ + FEC1_TX_INIT, /* txInit */ + 0, /* usedTbdIndex */ + 0, /* cleanTbdNum */ + } +#endif +}; + +static int fec_send(struct eth_device *dev, volatile void *packet, int length); +static int fec_recv(struct eth_device *dev); +static int fec_init(struct eth_device *dev, bd_t * bd); +static void fec_halt(struct eth_device *dev); + +#ifdef ET_DEBUG +static void dbg_fec_regs(struct eth_device *dev) +{ + struct fec_info_dma *info = dev->priv; + volatile fecdma_t *fecp = (fecdma_t *) (info->iobase); + + printf("=====\n"); + printf("ievent %x - %x\n", (int)&fecp->eir, fecp->eir); + printf("imask %x - %x\n", (int)&fecp->eimr, fecp->eimr); + printf("ecntrl %x - %x\n", (int)&fecp->ecr, fecp->ecr); + printf("mii_mframe %x - %x\n", (int)&fecp->mmfr, fecp->mmfr); + printf("mii_speed %x - %x\n", (int)&fecp->mscr, fecp->mscr); + printf("mii_ctrlstat %x - %x\n", (int)&fecp->mibc, fecp->mibc); + printf("r_cntrl %x - %x\n", (int)&fecp->rcr, fecp->rcr); + printf("r hash %x - %x\n", (int)&fecp->rhr, fecp->rhr); + printf("x_cntrl %x - %x\n", (int)&fecp->tcr, fecp->tcr); + printf("padr_l %x - %x\n", (int)&fecp->palr, fecp->palr); + printf("padr_u %x - %x\n", (int)&fecp->paur, fecp->paur); + printf("op_pause %x - %x\n", (int)&fecp->opd, fecp->opd); + printf("iadr_u %x - %x\n", (int)&fecp->iaur, fecp->iaur); + printf("iadr_l %x - %x\n", (int)&fecp->ialr, fecp->ialr); + printf("gadr_u %x - %x\n", (int)&fecp->gaur, fecp->gaur); + printf("gadr_l %x - %x\n", (int)&fecp->galr, fecp->galr); + printf("x_wmrk %x - %x\n", (int)&fecp->tfwr, fecp->tfwr); + printf("r_fdata %x - %x\n", (int)&fecp->rfdr, fecp->rfdr); + printf("r_fstat %x - %x\n", (int)&fecp->rfsr, fecp->rfsr); + printf("r_fctrl %x - %x\n", (int)&fecp->rfcr, fecp->rfcr); + printf("r_flrfp %x - %x\n", (int)&fecp->rlrfp, fecp->rlrfp); + printf("r_flwfp %x - %x\n", (int)&fecp->rlwfp, fecp->rlwfp); + printf("r_frfar %x - %x\n", (int)&fecp->rfar, fecp->rfar); + printf("r_frfrp %x - %x\n", (int)&fecp->rfrp, fecp->rfrp); + printf("r_frfwp %x - %x\n", (int)&fecp->rfwp, fecp->rfwp); + printf("t_fdata %x - %x\n", (int)&fecp->tfdr, fecp->tfdr); + printf("t_fstat %x - %x\n", (int)&fecp->tfsr, fecp->tfsr); + printf("t_fctrl %x - %x\n", (int)&fecp->tfcr, fecp->tfcr); + printf("t_flrfp %x - %x\n", (int)&fecp->tlrfp, fecp->tlrfp); + printf("t_flwfp %x - %x\n", (int)&fecp->tlwfp, fecp->tlwfp); + printf("t_ftfar %x - %x\n", (int)&fecp->tfar, fecp->tfar); + printf("t_ftfrp %x - %x\n", (int)&fecp->tfrp, fecp->tfrp); + printf("t_ftfwp %x - %x\n", (int)&fecp->tfwp, fecp->tfwp); + printf("frst %x - %x\n", (int)&fecp->frst, fecp->frst); + printf("ctcwr %x - %x\n", (int)&fecp->ctcwr, fecp->ctcwr); +} +#endif + +static void set_fec_duplex_speed(volatile fecdma_t * fecp, bd_t * bd, int dup_spd) +{ + if ((dup_spd >> 16) == FULL) { + /* Set maximum frame length */ + fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) | FEC_RCR_MII_MODE | + FEC_RCR_PROM | 0x100; + fecp->tcr = FEC_TCR_FDEN; + } else { + /* Half duplex mode */ + fecp->rcr = FEC_RCR_MAX_FL(PKT_MAXBUF_SIZE) | + FEC_RCR_MII_MODE | FEC_RCR_DRT; + fecp->tcr &= ~FEC_TCR_FDEN; + } + + if ((dup_spd & 0xFFFF) == _100BASET) { +#ifdef MII_DEBUG + printf("100Mbps\n"); +#endif + bd->bi_ethspeed = 100; + } else { +#ifdef MII_DEBUG + printf("10Mbps\n"); +#endif + bd->bi_ethspeed = 10; + } +} + +static int fec_send(struct eth_device *dev, volatile void *packet, int length) +{ + struct fec_info_dma *info = dev->priv; + cbd_t *pTbd, *pUsedTbd; + u16 phyStatus; + + miiphy_read(dev->name, info->phy_addr, PHY_BMSR, &phyStatus); + + /* process all the consumed TBDs */ + while (info->cleanTbdNum < CFG_TX_ETH_BUFFER) { + pUsedTbd = &info->txbd[info->usedTbdIdx]; + if (pUsedTbd->cbd_sc & BD_ENET_TX_READY) { +#ifdef ET_DEBUG + printf("Cannot clean TBD %d, in use\n", + info->cleanTbdNum); +#endif + return 0; + } + + /* clean this buffer descriptor */ + if (info->usedTbdIdx == (CFG_TX_ETH_BUFFER - 1)) + pUsedTbd->cbd_sc = BD_ENET_TX_WRAP; + else + pUsedTbd->cbd_sc = 0; + + /* update some indeces for a correct handling of the TBD ring */ + info->cleanTbdNum++; + info->usedTbdIdx = (info->usedTbdIdx + 1) % CFG_TX_ETH_BUFFER; + } + + /* Check for valid length of data. */ + if ((length > 1500) || (length <= 0)) { + return -1; + } + + /* Check the number of vacant TxBDs. */ + if (info->cleanTbdNum < 1) { + printf("No available TxBDs ...\n"); + return -1; + } + + /* Get the first TxBD to send the mac header */ + pTbd = &info->txbd[info->txIdx]; + pTbd->cbd_datlen = length; + pTbd->cbd_bufaddr = (u32) packet; + pTbd->cbd_sc |= BD_ENET_TX_LAST | BD_ENET_TX_TC | BD_ENET_TX_READY; + info->txIdx = (info->txIdx + 1) % CFG_TX_ETH_BUFFER; + + /* Enable DMA transmit task */ + MCD_continDma(info->txTask); + + info->cleanTbdNum -= 1; + + /* wait until frame is sent . */ + while (pTbd->cbd_sc & BD_ENET_TX_READY) { + udelay(10); + } + + return (int)(info->txbd[info->txIdx].cbd_sc & BD_ENET_TX_STATS); +} + +static int fec_recv(struct eth_device *dev) +{ + struct fec_info_dma *info = dev->priv; + volatile fecdma_t *fecp = (fecdma_t *) (info->iobase); + + cbd_t *pRbd = &info->rxbd[info->rxIdx]; + u32 ievent; + int frame_length, len = 0; + + /* Check if any critical events have happened */ + ievent = fecp->eir; + if (ievent != 0) { + fecp->eir = ievent; + + if (ievent & (FEC_EIR_BABT | FEC_EIR_TXERR | FEC_EIR_RXERR)) { + printf("fec_recv: error\n"); + fec_halt(dev); + fec_init(dev, NULL); + return 0; + } + + if (ievent & FEC_EIR_HBERR) { + /* Heartbeat error */ + fecp->tcr |= FEC_TCR_GTS; + } + + if (ievent & FEC_EIR_GRA) { + /* Graceful stop complete */ + if (fecp->tcr & FEC_TCR_GTS) { + printf("fec_recv: tcr_gts\n"); + fec_halt(dev); + fecp->tcr &= ~FEC_TCR_GTS; + fec_init(dev, NULL); + } + } + } + + if (!(pRbd->cbd_sc & BD_ENET_RX_EMPTY)) { + if ((pRbd->cbd_sc & BD_ENET_RX_LAST) + && !(pRbd->cbd_sc & BD_ENET_RX_ERR) + && ((pRbd->cbd_datlen - 4) > 14)) { + + /* Get buffer address and size */ + frame_length = pRbd->cbd_datlen - 4; + + /* Fill the buffer and pass it to upper layers */ + NetReceive((volatile uchar *)pRbd->cbd_bufaddr, + frame_length); + len = frame_length; + } + + /* Reset buffer descriptor as empty */ + if ((info->rxIdx) == (PKTBUFSRX - 1)) + pRbd->cbd_sc = (BD_ENET_RX_WRAP | BD_ENET_RX_EMPTY); + else + pRbd->cbd_sc = BD_ENET_RX_EMPTY; + + pRbd->cbd_datlen = PKTSIZE_ALIGN; + + /* Now, we have an empty RxBD, restart the DMA receive task */ + MCD_continDma(info->rxTask); + + /* Increment BD count */ + info->rxIdx = (info->rxIdx + 1) % PKTBUFSRX; + } + + return len; +} + +static void fec_set_hwaddr(volatile fecdma_t * fecp, u8 * mac) +{ + u8 currByte; /* byte for which to compute the CRC */ + int byte; /* loop - counter */ + int bit; /* loop - counter */ + u32 crc = 0xffffffff; /* initial value */ + + for (byte = 0; byte < 6; byte++) { + currByte = mac[byte]; + for (bit = 0; bit < 8; bit++) { + if ((currByte & 0x01) ^ (crc & 0x01)) { + crc >>= 1; + crc = crc ^ 0xedb88320; + } else { + crc >>= 1; + } + currByte >>= 1; + } + } + + crc = crc >> 26; + + /* Set individual hash table register */ + if (crc >= 32) { + fecp->ialr = (1 << (crc - 32)); + fecp->iaur = 0; + } else { + fecp->ialr = 0; + fecp->iaur = (1 << crc); + } + + /* Set physical address */ + fecp->palr = (mac[0] << 24) + (mac[1] << 16) + (mac[2] << 8) + mac[3]; + fecp->paur = (mac[4] << 24) + (mac[5] << 16) + 0x8808; + + /* Clear multicast address hash table */ + fecp->gaur = 0; + fecp->galr = 0; +} + +static int fec_init(struct eth_device *dev, bd_t * bd) +{ + struct fec_info_dma *info = dev->priv; + volatile fecdma_t *fecp = (fecdma_t *) (info->iobase); + int i; + +#ifdef ET_DEBUG + printf("fec_init: iobase 0x%08x ...\n", info->iobase); +#endif + + fecpin_setclear(dev, 1); + + fec_halt(dev); + +#if defined(CONFIG_CMD_MII) || defined (CONFIG_MII) || \ + defined (CFG_DISCOVER_PHY) + + mii_init(); + + set_fec_duplex_speed(fecp, bd, info->dup_spd); +#else +#ifndef CFG_DISCOVER_PHY + set_fec_duplex_speed(fecp, bd, (FECDUPLEX << 16) | FECSPEED); +#endif /* ifndef CFG_DISCOVER_PHY */ +#endif /* CONFIG_CMD_MII || CONFIG_MII */ + + /* We use strictly polling mode only */ + fecp->eimr = 0; + + /* Clear any pending interrupt */ + fecp->eir = 0xffffffff; + + /* Set station address */ + if ((u32) fecp == CFG_FEC0_IOBASE) { + fec_set_hwaddr(fecp, bd->bi_enetaddr); + } else { + fec_set_hwaddr(fecp, bd->bi_enet1addr); + } + + /* Set Opcode/Pause Duration Register */ + fecp->opd = 0x00010020; + + /* Setup Buffers and Buffer Desriptors */ + info->rxIdx = 0; + info->txIdx = 0; + + /* Setup Receiver Buffer Descriptors (13.14.24.18) + * Settings: Empty, Wrap */ + for (i = 0; i < PKTBUFSRX; i++) { + info->rxbd[i].cbd_sc = BD_ENET_RX_EMPTY; + info->rxbd[i].cbd_datlen = PKTSIZE_ALIGN; + info->rxbd[i].cbd_bufaddr = (uint) NetRxPackets[i]; + } + info->rxbd[PKTBUFSRX - 1].cbd_sc |= BD_ENET_RX_WRAP; + + /* Setup Ethernet Transmitter Buffer Descriptors (13.14.24.19) + * Settings: Last, Tx CRC */ + for (i = 0; i < CFG_TX_ETH_BUFFER; i++) { + info->txbd[i].cbd_sc = 0; + info->txbd[i].cbd_datlen = 0; + info->txbd[i].cbd_bufaddr = (uint) (&info->txbuf[0]); + } + info->txbd[CFG_TX_ETH_BUFFER - 1].cbd_sc |= BD_ENET_TX_WRAP; + + info->usedTbdIdx = 0; + info->cleanTbdNum = CFG_TX_ETH_BUFFER; + + /* Set Rx FIFO alarm and granularity value */ + fecp->rfcr = 0x0c000000; + fecp->rfar = 0x0000030c; + + /* Set Tx FIFO granularity value */ + fecp->tfcr = FIFO_CTRL_FRAME | FIFO_CTRL_GR(6) | 0x00040000; + fecp->tfar = 0x00000080; + + fecp->tfwr = 0x2; + fecp->ctcwr = 0x03000000; + + /* Enable DMA receive task */ + MCD_startDma(info->rxTask, /* Dma channel */ + (s8 *) info->rxbd, /*Source Address */ + 0, /* Source increment */ + (s8 *) (&fecp->rfdr), /* dest */ + 4, /* dest increment */ + 0, /* DMA size */ + 4, /* xfer size */ + info->rxInit, /* initiator */ + info->rxPri, /* priority */ + (MCD_FECRX_DMA | MCD_TT_FLAGS_DEF), /* Flags */ + (MCD_NO_CSUM | MCD_NO_BYTE_SWAP) /* Function description */ + ); + + /* Enable DMA tx task with no ready buffer descriptors */ + MCD_startDma(info->txTask, /* Dma channel */ + (s8 *) info->txbd, /*Source Address */ + 0, /* Source increment */ + (s8 *) (&fecp->tfdr), /* dest */ + 4, /* dest incr */ + 0, /* DMA size */ + 4, /* xfer size */ + info->txInit, /* initiator */ + info->txPri, /* priority */ + (MCD_FECTX_DMA | MCD_TT_FLAGS_DEF), /* Flags */ + (MCD_NO_CSUM | MCD_NO_BYTE_SWAP) /* Function description */ + ); + + /* Now enable the transmit and receive processing */ + fecp->ecr |= FEC_ECR_ETHER_EN; + + return 1; +} + +static void fec_halt(struct eth_device *dev) +{ + struct fec_info_dma *info = dev->priv; + volatile fecdma_t *fecp = (fecdma_t *) (info->iobase); + int counter = 0xffff; + + /* issue graceful stop command to the FEC transmitter if necessary */ + fecp->tcr |= FEC_TCR_GTS; + + /* wait for graceful stop to register */ + while ((counter--) && (!(fecp->eir & FEC_EIR_GRA))) ; + + /* Disable DMA tasks */ + MCD_killDma(info->txTask); + MCD_killDma(info->rxTask);; + + /* Disable the Ethernet Controller */ + fecp->ecr &= ~FEC_ECR_ETHER_EN; + + /* Clear FIFO status registers */ + fecp->rfsr &= FIFO_ERRSTAT; + fecp->tfsr &= FIFO_ERRSTAT; + + fecp->frst = 0x01000000; + + /* Issue a reset command to the FEC chip */ + fecp->ecr |= FEC_ECR_RESET; + + /* wait at least 20 clock cycles */ + udelay(10000); + +#ifdef ET_DEBUG + printf("Ethernet task stopped\n"); +#endif +} + +int mcdmafec_initialize(bd_t * bis) +{ + struct eth_device *dev; + int i; + + for (i = 0; i < sizeof(fec_info) / sizeof(fec_info[0]); i++) { + + dev = + (struct eth_device *)memalign(CFG_CACHELINE_SIZE, + sizeof *dev); + if (dev == NULL) + hang(); + + memset(dev, 0, sizeof(*dev)); + + sprintf(dev->name, "FEC%d", fec_info[i].index); + + dev->priv = &fec_info[i]; + dev->init = fec_init; + dev->halt = fec_halt; + dev->send = fec_send; + dev->recv = fec_recv; + + /* setup Receive and Transmit buffer descriptor */ + fec_info[i].rxbd = + (cbd_t *) memalign(CFG_CACHELINE_SIZE, + (PKTBUFSRX * sizeof(cbd_t))); + fec_info[i].txbd = + (cbd_t *) memalign(CFG_CACHELINE_SIZE, + (CFG_TX_ETH_BUFFER * sizeof(cbd_t))); + fec_info[i].txbuf = + (char *)memalign(CFG_CACHELINE_SIZE, DBUF_LENGTH); + +#ifdef ET_DEBUG + printf("rxbd %x txbd %x\n", + (int)fec_info[i].rxbd, (int)fec_info[i].txbd); +#endif + + fec_info[i].phy_name = (char *)memalign(CFG_CACHELINE_SIZE, 32); + + eth_register(dev); + +#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) + miiphy_register(dev->name, + mcffec_miiphy_read, mcffec_miiphy_write); +#endif + + if (i > 0) + fec_info[i - 1].next = &fec_info[i]; + } + fec_info[i - 1].next = &fec_info[0]; + + /* default speed */ + bis->bi_ethspeed = 10; + + return 1; +} + +#endif /* CONFIG_CMD_NET && CONFIG_NET_MULTI */ +#endif /* CONFIG_FSLDMAFEC */ diff --git a/drivers/net/rtl8139.c b/drivers/net/rtl8139.c index 4c24805..097f684 100644 --- a/drivers/net/rtl8139.c +++ b/drivers/net/rtl8139.c @@ -80,10 +80,7 @@ #if defined(CONFIG_CMD_NET) && defined(CONFIG_NET_MULTI) && \ defined(CONFIG_RTL8139) -#define TICKS_PER_SEC CFG_HZ -#define TICKS_PER_MS (TICKS_PER_SEC/1000) - -#define RTL_TIMEOUT (1*TICKS_PER_SEC) +#define RTL_TIMEOUT 100000 #define ETH_FRAME_LEN 1514 #define ETH_ALEN 6 @@ -392,6 +389,7 @@ static void rtl_reset(struct eth_device *dev) #ifdef DEBUG_RX printf("rx ring address is %X\n",(unsigned long)rx_ring); #endif + flush_cache((unsigned long)rx_ring, RX_BUF_LEN); outl(phys_to_bus((int)rx_ring), ioaddr + RxBuf); /* If we add multicast support, the MAR0 register would have to be @@ -414,9 +412,10 @@ static void rtl_reset(struct eth_device *dev) static int rtl_transmit(struct eth_device *dev, volatile void *packet, int length) { - unsigned int status, to; + unsigned int status; unsigned long txstatus; unsigned int len = length; + int i = 0; ioaddr = dev->iobase; @@ -432,12 +431,11 @@ static int rtl_transmit(struct eth_device *dev, volatile void *packet, int lengt tx_buffer[len++] = '\0'; } + flush_cache((unsigned long)tx_buffer, length); outl(phys_to_bus((int)tx_buffer), ioaddr + TxAddr0 + cur_tx*4); outl(((TX_FIFO_THRESH<<11) & 0x003f0000) | len, ioaddr + TxStatus0 + cur_tx*4); - to = currticks() + RTL_TIMEOUT; - do { status = inw(ioaddr + IntrStatus); /* Only acknlowledge interrupt sources we can properly handle @@ -445,7 +443,8 @@ static int rtl_transmit(struct eth_device *dev, volatile void *packet, int lengt * rtl_poll() function. */ outw(status & (TxOK | TxErr | PCIErr), ioaddr + IntrStatus); if ((status & (TxOK | TxErr | PCIErr)) != 0) break; - } while (currticks() < to); + udelay(10); + } while (i++ < RTL_TIMEOUT); txstatus = inl(ioaddr + TxStatus0 + cur_tx*4); @@ -458,8 +457,8 @@ static int rtl_transmit(struct eth_device *dev, volatile void *packet, int lengt return length; } else { #ifdef DEBUG_TX - printf("tx timeout/error (%d ticks), status %hX txstatus %X\n", - currticks()-to, status, txstatus); + printf("tx timeout/error (%d usecs), status %hX txstatus %X\n", + 10*i, status, txstatus); #endif rtl_reset(dev); @@ -489,7 +488,8 @@ static int rtl_poll(struct eth_device *dev) #endif ring_offs = cur_rx % RX_BUF_LEN; - rx_status = *(unsigned int*)KSEG1ADDR((rx_ring + ring_offs)); + /* ring_offs is guaranteed being 4-byte aligned */ + rx_status = le32_to_cpu(*(unsigned int *)(rx_ring + ring_offs)); rx_size = rx_status >> 16; rx_status &= 0xffff; @@ -519,6 +519,7 @@ static int rtl_poll(struct eth_device *dev) printf("rx packet %d bytes", rx_size-4); #endif } + flush_cache((unsigned long)rx_ring, RX_BUF_LEN); cur_rx = (cur_rx + rx_size + 4 + 3) & ~3; outw(cur_rx - 16, ioaddr + RxBufPtr); diff --git a/drivers/net/tsec.c b/drivers/net/tsec.c index 25392f6..e91d9ea 100644 --- a/drivers/net/tsec.c +++ b/drivers/net/tsec.c @@ -241,10 +241,9 @@ int tsec_init(struct eth_device *dev, bd_t * bd) * It will wait for the write to be done (or for a timeout to * expire) before exiting */ -void write_phy_reg(struct tsec_private *priv, uint regnum, uint value) +void write_any_phy_reg(struct tsec_private *priv, uint phyid, uint regnum, uint value) { volatile tsec_t *regbase = priv->phyregs; - uint phyid = priv->phyaddr; int timeout = 1000000; regbase->miimadd = (phyid << 8) | regnum; @@ -255,17 +254,19 @@ void write_phy_reg(struct tsec_private *priv, uint regnum, uint value) while ((regbase->miimind & MIIMIND_BUSY) && timeout--) ; } +/* #define to provide old write_phy_reg functionality without duplicating code */ +#define write_phy_reg(priv, regnum, value) write_any_phy_reg(priv,priv->phyaddr,regnum,value) + /* Reads register regnum on the device's PHY through the * registers specified in priv. It lowers and raises the read * command, and waits for the data to become valid (miimind * notvalid bit cleared), and the bus to cease activity (miimind * busy bit cleared), and then returns the value */ -uint read_phy_reg(struct tsec_private *priv, uint regnum) +uint read_any_phy_reg(struct tsec_private *priv, uint phyid, uint regnum) { uint value; volatile tsec_t *regbase = priv->phyregs; - uint phyid = priv->phyaddr; /* Put the address of the phy, and the register * number into MIIMADD */ @@ -288,6 +289,9 @@ uint read_phy_reg(struct tsec_private *priv, uint regnum) return value; } +/* #define to provide old read_phy_reg functionality without duplicating code */ +#define read_phy_reg(priv,regnum) read_any_phy_reg(priv,priv->phyaddr,regnum) + /* Discover which PHY is attached to the device, and configure it * properly. If the PHY is not recognized, then return 0 * (failure). Otherwise, return 1 @@ -571,6 +575,63 @@ uint mii_parse_88E1011_psr(uint mii_reg, struct tsec_private * priv) return 0; } +/* Parse the RTL8211B's status register for speed and duplex + * information + */ +uint mii_parse_RTL8211B_sr(uint mii_reg, struct tsec_private * priv) +{ + uint speed; + + mii_reg = read_phy_reg(priv, MIIM_RTL8211B_PHY_STATUS); + if ((mii_reg & MIIM_RTL8211B_PHYSTAT_LINK) && + !(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) { + int i = 0; + + puts("Waiting for PHY realtime link"); + while (!(mii_reg & MIIM_RTL8211B_PHYSTAT_SPDDONE)) { + /* Timeout reached ? */ + if (i > PHY_AUTONEGOTIATE_TIMEOUT) { + puts(" TIMEOUT !\n"); + priv->link = 0; + break; + } + + if ((i++ % 1000) == 0) { + putc('.'); + } + udelay(1000); /* 1 ms */ + mii_reg = read_phy_reg(priv, MIIM_RTL8211B_PHY_STATUS); + } + puts(" done\n"); + udelay(500000); /* another 500 ms (results in faster booting) */ + } else { + if (mii_reg & MIIM_RTL8211B_PHYSTAT_LINK) + priv->link = 1; + else + priv->link = 0; + } + + if (mii_reg & MIIM_RTL8211B_PHYSTAT_DUPLEX) + priv->duplexity = 1; + else + priv->duplexity = 0; + + speed = (mii_reg & MIIM_RTL8211B_PHYSTAT_SPEED); + + switch (speed) { + case MIIM_RTL8211B_PHYSTAT_GBIT: + priv->speed = 1000; + break; + case MIIM_RTL8211B_PHYSTAT_100: + priv->speed = 100; + break; + default: + priv->speed = 10; + } + + return 0; +} + /* Parse the cis8201's status register for speed and duplex * information */ @@ -1361,6 +1422,33 @@ struct phy_info phy_info_dp83865 = { }, }; +struct phy_info phy_info_rtl8211b = { + 0x001cc91, + "RealTek RTL8211B", + 4, + (struct phy_cmd[]){ /* config */ + /* Reset and configure the PHY */ + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {MIIM_GBIT_CONTROL, MIIM_GBIT_CONTROL_INIT, NULL}, + {MIIM_ANAR, MIIM_ANAR_INIT, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_RESET, NULL}, + {MIIM_CONTROL, MIIM_CONTROL_INIT, &mii_cr_init}, + {miim_end,} + }, + (struct phy_cmd[]){ /* startup */ + /* Status is read once to clear old link state */ + {MIIM_STATUS, miim_read, NULL}, + /* Auto-negotiate */ + {MIIM_STATUS, miim_read, &mii_parse_sr}, + /* Read the status */ + {MIIM_RTL8211B_PHY_STATUS, miim_read, &mii_parse_RTL8211B_sr}, + {miim_end,} + }, + (struct phy_cmd[]){ /* shutdown */ + {miim_end,} + }, +}; + struct phy_info *phy_info[] = { &phy_info_cis8204, &phy_info_cis8201, @@ -1374,6 +1462,7 @@ struct phy_info *phy_info[] = { &phy_info_lxt971, &phy_info_VSC8244, &phy_info_dp83865, + &phy_info_rtl8211b, &phy_info_generic, NULL }; @@ -1497,18 +1586,6 @@ static void relocate_cmds(void) #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) \ && !defined(BITBANGMII) -struct tsec_private *get_priv_for_phy(unsigned char phyaddr) -{ - int i; - - for (i = 0; i < MAXCONTROLLERS; i++) { - if (privlist[i]->phyaddr == phyaddr) - return privlist[i]; - } - - return NULL; -} - /* * Read a MII PHY register. * @@ -1519,14 +1596,14 @@ static int tsec_miiphy_read(char *devname, unsigned char addr, unsigned char reg, unsigned short *value) { unsigned short ret; - struct tsec_private *priv = get_priv_for_phy(addr); + struct tsec_private *priv = privlist[0]; if (NULL == priv) { printf("Can't read PHY at address %d\n", addr); return -1; } - ret = (unsigned short)read_phy_reg(priv, reg); + ret = (unsigned short)read_any_phy_reg(priv, addr, reg); *value = ret; return 0; @@ -1541,14 +1618,14 @@ static int tsec_miiphy_read(char *devname, unsigned char addr, static int tsec_miiphy_write(char *devname, unsigned char addr, unsigned char reg, unsigned short value) { - struct tsec_private *priv = get_priv_for_phy(addr); + struct tsec_private *priv = privlist[0]; if (NULL == priv) { printf("Can't write PHY at address %d\n", addr); return -1; } - write_phy_reg(priv, reg, value); + write_any_phy_reg(priv, addr, reg, value); return 0; } diff --git a/drivers/net/tsec.h b/drivers/net/tsec.h index 2f0092a..d4dc15a 100644 --- a/drivers/net/tsec.h +++ b/drivers/net/tsec.h @@ -184,6 +184,14 @@ #define MIIM_88E1145_PHY_PAGE 29 #define MIIM_88E1145_PHY_CAL_OV 30 +/* RTL8211B PHY Status Register */ +#define MIIM_RTL8211B_PHY_STATUS 0x11 +#define MIIM_RTL8211B_PHYSTAT_SPEED 0xc000 +#define MIIM_RTL8211B_PHYSTAT_GBIT 0x8000 +#define MIIM_RTL8211B_PHYSTAT_100 0x4000 +#define MIIM_RTL8211B_PHYSTAT_DUPLEX 0x2000 +#define MIIM_RTL8211B_PHYSTAT_SPDDONE 0x0800 +#define MIIM_RTL8211B_PHYSTAT_LINK 0x0400 /* DM9161 Control register values */ #define MIIM_DM9161_CR_STOP 0x0400 diff --git a/drivers/qe/uec.c b/drivers/qe/uec.c index 6cb25bf..55f37cb 100644 --- a/drivers/qe/uec.c +++ b/drivers/qe/uec.c @@ -40,8 +40,13 @@ static uec_info_t eth1_uec_info = { .tx_clock = CFG_UEC1_TX_CLK, .eth_type = CFG_UEC1_ETH_TYPE, }, +#if (CFG_UEC1_ETH_TYPE == FAST_ETH) + .num_threads_tx = UEC_NUM_OF_THREADS_1, + .num_threads_rx = UEC_NUM_OF_THREADS_1, +#else .num_threads_tx = UEC_NUM_OF_THREADS_4, .num_threads_rx = UEC_NUM_OF_THREADS_4, +#endif .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, .tx_bd_ring_len = 16, @@ -58,8 +63,13 @@ static uec_info_t eth2_uec_info = { .tx_clock = CFG_UEC2_TX_CLK, .eth_type = CFG_UEC2_ETH_TYPE, }, +#if (CFG_UEC2_ETH_TYPE == FAST_ETH) + .num_threads_tx = UEC_NUM_OF_THREADS_1, + .num_threads_rx = UEC_NUM_OF_THREADS_1, +#else .num_threads_tx = UEC_NUM_OF_THREADS_4, .num_threads_rx = UEC_NUM_OF_THREADS_4, +#endif .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, .tx_bd_ring_len = 16, @@ -68,7 +78,6 @@ static uec_info_t eth2_uec_info = { .enet_interface = CFG_UEC2_INTERFACE_MODE, }; #endif - #ifdef CONFIG_UEC_ETH3 static uec_info_t eth3_uec_info = { .uf_info = { @@ -77,8 +86,13 @@ static uec_info_t eth3_uec_info = { .tx_clock = CFG_UEC3_TX_CLK, .eth_type = CFG_UEC3_ETH_TYPE, }, +#if (CFG_UEC3_ETH_TYPE == FAST_ETH) + .num_threads_tx = UEC_NUM_OF_THREADS_1, + .num_threads_rx = UEC_NUM_OF_THREADS_1, +#else .num_threads_tx = UEC_NUM_OF_THREADS_4, .num_threads_rx = UEC_NUM_OF_THREADS_4, +#endif .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, .tx_bd_ring_len = 16, @@ -87,6 +101,29 @@ static uec_info_t eth3_uec_info = { .enet_interface = CFG_UEC3_INTERFACE_MODE, }; #endif +#ifdef CONFIG_UEC_ETH4 +static uec_info_t eth4_uec_info = { + .uf_info = { + .ucc_num = CFG_UEC4_UCC_NUM, + .rx_clock = CFG_UEC4_RX_CLK, + .tx_clock = CFG_UEC4_TX_CLK, + .eth_type = CFG_UEC4_ETH_TYPE, + }, +#if (CFG_UEC4_ETH_TYPE == FAST_ETH) + .num_threads_tx = UEC_NUM_OF_THREADS_1, + .num_threads_rx = UEC_NUM_OF_THREADS_1, +#else + .num_threads_tx = UEC_NUM_OF_THREADS_4, + .num_threads_rx = UEC_NUM_OF_THREADS_4, +#endif + .riscTx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, + .riscRx = QE_RISC_ALLOCATION_RISC1_AND_RISC2, + .tx_bd_ring_len = 16, + .rx_bd_ring_len = 16, + .phy_address = CFG_UEC4_PHY_ADDR, + .enet_interface = CFG_UEC4_INTERFACE_MODE, +}; +#endif static int uec_mac_enable(uec_private_t *uec, comm_dir_e mode) { @@ -475,6 +512,8 @@ static int init_phy(struct eth_device *dev) uec->mii_info = mii_info; + qe_set_mii_clk_src(uec->uec_info->uf_info.ucc_num); + if (init_mii_management_configuration(umii_regs)) { printf("%s: The MII Bus is stuck!", dev->name); err = -1; @@ -581,21 +620,12 @@ static void adjust_link(struct eth_device *dev) static void phy_change(struct eth_device *dev) { uec_private_t *uec = (uec_private_t *)dev->priv; - uec_t *uec_regs; - int result = 0; - - uec_regs = uec->uec_regs; - - /* Delay 5s to give the PHY a chance to change the register state */ - udelay(5000000); /* Update the link, speed, duplex */ - result = uec->mii_info->phyinfo->read_status(uec->mii_info); + uec->mii_info->phyinfo->read_status(uec->mii_info); /* Adjust the interface according to speed */ - if ((0 == result) || (uec->mii_info->link == 0)) { - adjust_link(dev); - } + adjust_link(dev); } static int uec_set_mac_address(uec_private_t *uec, u8 *mac_addr) @@ -1120,27 +1150,59 @@ static int uec_startup(uec_private_t *uec) static int uec_init(struct eth_device* dev, bd_t *bd) { uec_private_t *uec; - int err; + int err, i; + struct phy_info *curphy; uec = (uec_private_t *)dev->priv; if (uec->the_first_run == 0) { - /* Set up the MAC address */ - if (dev->enetaddr[0] & 0x01) { - printf("%s: MacAddress is multcast address\n", - __FUNCTION__); - return -1; + err = init_phy(dev); + if (err) { + printf("%s: Cannot initialize PHY, aborting.\n", + dev->name); + return err; + } + + curphy = uec->mii_info->phyinfo; + + if (curphy->config_aneg) { + err = curphy->config_aneg(uec->mii_info); + if (err) { + printf("%s: Can't negotiate PHY\n", dev->name); + return err; + } } - uec_set_mac_address(uec, dev->enetaddr); + + /* Give PHYs up to 5 sec to report a link */ + i = 50; + do { + err = curphy->read_status(uec->mii_info); + udelay(100000); + } while (((i-- > 0) && !uec->mii_info->link) || err); + + if (err || i <= 0) + printf("warning: %s: timeout on PHY link\n", dev->name); + uec->the_first_run = 1; } + /* Set up the MAC address */ + if (dev->enetaddr[0] & 0x01) { + printf("%s: MacAddress is multcast address\n", + __FUNCTION__); + return -1; + } + uec_set_mac_address(uec, dev->enetaddr); + + err = uec_open(uec, COMM_DIR_RX_AND_TX); if (err) { printf("%s: cannot enable UEC device\n", dev->name); return -1; } + phy_change(dev); + return (uec->mii_info->link ? 0 : -1); } @@ -1262,6 +1324,10 @@ int uec_initialize(int index) #ifdef CONFIG_UEC_ETH3 uec_info = ð3_uec_info; #endif + } else if (index == 3) { +#ifdef CONFIG_UEC_ETH4 + uec_info = ð4_uec_info; +#endif } else { printf("%s: index is illegal.\n", __FUNCTION__); return -EINVAL; @@ -1289,14 +1355,6 @@ int uec_initialize(int index) return err; } - err = init_phy(dev); - if (err) { - printf("%s: Cannot initialize PHY, aborting.\n", dev->name); - return err; - } - - phy_change(dev); - return 1; } #endif /* CONFIG_QE */ diff --git a/drivers/qe/uec_phy.c b/drivers/qe/uec_phy.c index ca6faa6..c549b6b 100644 --- a/drivers/qe/uec_phy.c +++ b/drivers/qe/uec_phy.c @@ -28,7 +28,6 @@ #if defined(CONFIG_QE) -#define UEC_VERBOSE_DEBUG #define ugphy_printk(format, arg...) \ printf(format "\n", ## arg) @@ -77,11 +76,10 @@ void uec_write_phy_reg (struct eth_device *dev, int mii_id, int regnum, int valu /* Setting up the MII Mangement Control Register with the value */ out_be32 (&ug_regs->miimcon, (u32) value); + sync(); /* Wait till MII management write is complete */ while ((in_be32 (&ug_regs->miimind)) & MIIMIND_BUSY); - - udelay (100000); } /* Reads from register regnum in the PHY for device dev, */ @@ -101,20 +99,21 @@ int uec_read_phy_reg (struct eth_device *dev, int mii_id, int regnum) tmp_reg = ((u32) mii_id << MIIMADD_PHY_ADDRESS_SHIFT) | mii_reg; out_be32 (&ug_regs->miimadd, tmp_reg); - /* Perform an MII management read cycle */ + /* clear MII management command cycle */ out_be32 (&ug_regs->miimcom, 0); + sync(); + + /* Perform an MII management read cycle */ out_be32 (&ug_regs->miimcom, MIIMCOM_READ_CYCLE); /* Wait till MII management write is complete */ while ((in_be32 (&ug_regs->miimind)) & (MIIMIND_NOT_VALID | MIIMIND_BUSY)); - udelay (100000); - /* Read MII management status */ value = (u16) in_be32 (&ug_regs->miimstat); if (value == 0xffff) - ugphy_warn + ugphy_vdbg ("read wrong value : mii_id %d,mii_reg %d, base %08x", mii_id, mii_reg, (u32) & (ug_regs->miimcfg)); @@ -270,20 +269,38 @@ static int genmii_update_link (struct uec_mii_info *mii_info) { u16 status; - /* Do a fake read */ + /* Status is read once to clear old link state */ phy_read (mii_info, PHY_BMSR); - /* Read link and autonegotiation status */ - status = phy_read (mii_info, PHY_BMSR); - if ((status & PHY_BMSR_LS) == 0) - mii_info->link = 0; - else + /* + * Wait if the link is up, and autonegotiation is in progress + * (ie - we're capable and it's not done) + */ + status = phy_read(mii_info, PHY_BMSR); + if ((status & PHY_BMSR_LS) && (status & PHY_BMSR_AUTN_ABLE) + && !(status & PHY_BMSR_AUTN_COMP)) { + int i = 0; + + while (!(status & PHY_BMSR_AUTN_COMP)) { + /* + * Timeout reached ? + */ + if (i > UGETH_AN_TIMEOUT) { + mii_info->link = 0; + return 0; + } + + udelay(1000); /* 1 ms */ + status = phy_read(mii_info, PHY_BMSR); + } mii_info->link = 1; - - /* If we are autonegotiating, and not done, - * return an error */ - if (mii_info->autoneg && !(status & PHY_BMSR_AUTN_COMP)) - return -EAGAIN; + udelay(500000); /* another 500 ms (results in faster booting) */ + } else { + if (status & PHY_BMSR_LS) + mii_info->link = 1; + else + mii_info->link = 0; + } return 0; } @@ -389,16 +406,12 @@ static int dm9161_init (struct uec_mii_info *mii_info) /* PHY and MAC connect */ phy_write (mii_info, PHY_BMCR, phy_read (mii_info, PHY_BMCR) & ~PHY_BMCR_ISO); -#ifdef CONFIG_RMII_MODE - phy_write (mii_info, MII_DM9161_SCR, MII_DM9161_SCR_RMII_INIT); -#else + phy_write (mii_info, MII_DM9161_SCR, MII_DM9161_SCR_INIT); -#endif + config_genmii_advert (mii_info); /* Start/restart aneg */ genmii_config_aneg (mii_info); - /* Delay to wait the aneg compeleted */ - udelay (3000000); return 0; } diff --git a/drivers/spi/Makefile b/drivers/spi/Makefile new file mode 100644 index 0000000..0b7a2df --- /dev/null +++ b/drivers/spi/Makefile @@ -0,0 +1,46 @@ +# +# (C) Copyright 2000-2007 +# Wolfgang Denk, DENX Software Engineering, wd@denx.de. +# +# See file CREDITS for list of people who contributed to this +# project. +# +# 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 program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, +# MA 02111-1307 USA +# + +include $(TOPDIR)/config.mk + +LIB := $(obj)libspi.a + +COBJS-y += mpc8xxx_spi.o + +COBJS := $(COBJS-y) +SRCS := $(COBJS:.o=.c) +OBJS := $(addprefix $(obj),$(COBJS)) + +all: $(LIB) + +$(LIB): $(obj).depend $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/drivers/spi/mpc8xxx_spi.c b/drivers/spi/mpc8xxx_spi.c new file mode 100644 index 0000000..a3d1c95 --- /dev/null +++ b/drivers/spi/mpc8xxx_spi.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2006 Ben Warren, Qstreams Networks Inc. + * With help from the common/soft_spi and cpu/mpc8260 drivers + * + * See file CREDITS for list of people who contributed to this + * project. + * + * 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 program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, + * MA 02111-1307 USA + */ + +#include <common.h> +#include <spi.h> +#include <asm/mpc8xxx_spi.h> + +#ifdef CONFIG_HARD_SPI + +#define SPI_EV_NE (0x80000000 >> 22) /* Receiver Not Empty */ +#define SPI_EV_NF (0x80000000 >> 23) /* Transmitter Not Full */ + +#define SPI_MODE_LOOP (0x80000000 >> 1) /* Loopback mode */ +#define SPI_MODE_REV (0x80000000 >> 5) /* Reverse mode - MSB first */ +#define SPI_MODE_MS (0x80000000 >> 6) /* Always master */ +#define SPI_MODE_EN (0x80000000 >> 7) /* Enable interface */ + +#define SPI_TIMEOUT 1000 + +void spi_init(void) +{ + volatile spi8xxx_t *spi = &((immap_t *) (CFG_IMMR))->spi; + + /* + * SPI pins on the MPC83xx are not muxed, so all we do is initialize + * some registers + */ + spi->mode = SPI_MODE_REV | SPI_MODE_MS | SPI_MODE_EN; + spi->mode = (spi->mode & 0xfff0ffff) | (1 << 16); /* Use SYSCLK / 8 + (16.67MHz typ.) */ + spi->event = 0xffffffff; /* Clear all SPI events */ + spi->mask = 0x00000000; /* Mask all SPI interrupts */ + spi->com = 0; /* LST bit doesn't do anything, so disregard */ +} + +int spi_xfer(spi_chipsel_type chipsel, int bitlen, uchar *dout, uchar *din) +{ + volatile spi8xxx_t *spi = &((immap_t *) (CFG_IMMR))->spi; + unsigned int tmpdout, tmpdin, event; + int numBlks = bitlen / 32 + (bitlen % 32 ? 1 : 0); + int tm, isRead = 0; + unsigned char charSize = 32; + + debug("spi_xfer: chipsel %08X dout %08X din %08X bitlen %d\n", + (int)chipsel, *(uint *) dout, *(uint *) din, bitlen); + + if (chipsel != NULL) + (*chipsel) (1); /* select the target chip */ + + spi->event = 0xffffffff; /* Clear all SPI events */ + + /* handle data in 32-bit chunks */ + while (numBlks--) { + tmpdout = 0; + charSize = (bitlen >= 32 ? 32 : bitlen); + + /* Shift data so it's msb-justified */ + tmpdout = *(u32 *) dout >> (32 - charSize); + + /* The LEN field of the SPMODE register is set as follows: + * + * Bit length setting + * len <= 4 3 + * 4 < len <= 16 len - 1 + * len > 16 0 + */ + + if (bitlen <= 16) { + if (bitlen <= 4) + spi->mode = (spi->mode & 0xff0fffff) | + (3 << 20); + else + spi->mode = (spi->mode & 0xff0fffff) | + ((bitlen - 1) << 20); + } else { + spi->mode = (spi->mode & 0xff0fffff); + /* Set up the next iteration if sending > 32 bits */ + bitlen -= 32; + dout += 4; + } + + spi->tx = tmpdout; /* Write the data out */ + debug("*** spi_xfer: ... %08x written\n", tmpdout); + + /* + * Wait for SPI transmit to get out + * or time out (1 second = 1000 ms) + * The NE event must be read and cleared first + */ + for (tm = 0, isRead = 0; tm < SPI_TIMEOUT; ++tm) { + event = spi->event; + if (event & SPI_EV_NE) { + tmpdin = spi->rx; + spi->event |= SPI_EV_NE; + isRead = 1; + + *(u32 *) din = (tmpdin << (32 - charSize)); + if (charSize == 32) { + /* Advance output buffer by 32 bits */ + din += 4; + } + } + /* + * Only bail when we've had both NE and NF events. + * This will cause timeouts on RO devices, so maybe + * in the future put an arbitrary delay after writing + * the device. Arbitrary delays suck, though... + */ + if (isRead && (event & SPI_EV_NF)) + break; + } + if (tm >= SPI_TIMEOUT) + puts("*** spi_xfer: Time out during SPI transfer"); + + debug("*** spi_xfer: transfer ended. Value=%08x\n", tmpdin); + } + + if (chipsel != NULL) + (*chipsel) (0); /* deselect the target chip */ + + return 0; +} +#endif /* CONFIG_HARD_SPI */ |