static int transferToFlash(void* buffer, int size) { int controller = 0; int channel = 0; if((((uint32_t)buffer) & 0x3) != 0) { // the buffer needs to be aligned for DMA, last two bits have to be clear return ERROR_ALIGN; } SET_REG(NAND + NAND_CONFIG, GET_REG(NAND + NAND_CONFIG) | (1 << NAND_CONFIG_DMASETTINGSHIFT)); SET_REG(NAND + NAND_TRANSFERSIZE, size - 1); SET_REG(NAND + NAND_CON, 0x7F4); CleanCPUDataCache(); dma_request(DMA_MEMORY, 4, 4, DMA_NAND, 4, 4, &controller, &channel, NULL); dma_perform((uint32_t)buffer, DMA_NAND, size, 0, &controller, &channel); if(dma_finish(controller, channel, 500) != 0) { bufferPrintf("nand: dma timed out\r\n"); return ERROR_TIMEOUT; } if(wait_for_status_bit_3(500) != 0) { bufferPrintf("nand: waiting for status bit 3 timed out\r\n"); return ERROR_TIMEOUT; } SET_REG(NAND + NAND_CON, NAND_CON_SETTING1); CleanAndInvalidateCPUDataCache(); return 0; }
static int transferToFlash(void* buffer, int size) { int controller = 0; int channel = 0; if((((uint32_t)buffer) & 0x3) != 0) { // the buffer needs to be aligned for DMA, last two bits have to be clear return ERROR_ALIGN; } SET_REG(NAND + FMCTRL0, GET_REG(NAND + FMCTRL0) | (1 << FMCTRL0_DMASETTINGSHIFT)); SET_REG(NAND + FMDNUM, size - 1); SET_REG(NAND + FMCTRL1, 0x7F4); CleanCPUDataCache(); dma_request(DMA_MEMORY, 4, 4, DMA_NAND, 4, 4, &controller, &channel, NULL); dma_perform((uint32_t)buffer, DMA_NAND, size, 0, &controller, &channel); if(dma_finish(controller, channel, 500) != 0) { bufferPrintf("nand: dma timed out\r\n"); return ERROR_TIMEOUT; } if(wait_for_transfer_done(500) != 0) { bufferPrintf("nand: waiting for transfer done timed out\r\n"); return ERROR_TIMEOUT; } SET_REG(NAND + FMCTRL1, FMCTRL1_FLUSHFIFOS); CleanAndInvalidateCPUDataCache(); return 0; }
static int setup_processor() { CleanAndInvalidateCPUDataCache(); ClearCPUInstructionCache(); WriteControlRegisterConfigData(ReadControlRegisterConfigData() & ~(ARM11_Control_INSTRUCTIONCACHE)); // Disable instruction cache WriteControlRegisterConfigData(ReadControlRegisterConfigData() & ~(ARM11_Control_DATACACHE)); // Disable data cache GiveFullAccessCP10CP11(); EnableVFP(); // Map the peripheral port of size 128 MB to 0x38000000 WritePeripheralPortMemoryRemapRegister(PeripheralPort | ARM11_PeripheralPortSize128MB); InvalidateCPUDataCache(); ClearCPUInstructionCache(); WriteControlRegisterConfigData(ReadControlRegisterConfigData() | ARM11_Control_INSTRUCTIONCACHE); // Enable instruction cache WriteControlRegisterConfigData(ReadControlRegisterConfigData() | ARM11_Control_DATACACHE); // Enable data cache WriteControlRegisterConfigData((ReadControlRegisterConfigData() & ~(ARM11_Control_STRICTALIGNMENTCHECKING)) // Disable strict alignment fault checking | ARM11_Control_UNALIGNEDDATAACCESS); // Enable unaligned data access operations WriteControlRegisterConfigData(ReadControlRegisterConfigData() | ARM11_Control_BRANCHPREDICTION); // Enable branch prediction // Enable return stack, dynamic branch prediction, static branch prediction WriteAuxiliaryControlRegister(ReadAuxiliaryControlRegister() | ARM11_AuxControl_RETURNSTACK | ARM11_AuxControl_DYNAMICBRANCHPREDICTION | ARM11_AuxControl_STATICBRANCHPREDICTION); return 0; }
static void ecc_generate(int setting, int sectors, uint8_t* sectorData, uint8_t* eccData) { SET_REG(NANDECC + NANDECC_CLEARINT, 1); SET_REG(NANDECC + NANDECC_SETUP, ((sectors - 1) & 0x3) | setting); SET_REG(NANDECC + NANDECC_DATA, (uint32_t) sectorData); SET_REG(NANDECC + NANDECC_ECC, (uint32_t) eccData); CleanAndInvalidateCPUDataCache(); SET_REG(NANDECC + NANDECC_START, 2); }
static void usbTxRx(int endpoint, USBDirection direction, USBTransferType transferType, void* buffer, int bufferLen) { int packetLength; if(transferType == USBControl || transferType == USBInterrupt) { packetLength = USB_MAX_PACKETSIZE; } else { packetLength = packetsizeFromSpeed(usb_speed); } CleanAndInvalidateCPUDataCache(); if(direction == USBOut) { receive(endpoint, transferType, buffer, packetLength, bufferLen); return; } if(GNPTXFSTS_GET_TXQSPCAVAIL(GET_REG(USB + GNPTXFSTS)) == 0) { // no space available return; } // enable interrupts for this endpoint SET_REG(USB + DAINTMSK, GET_REG(USB + DAINTMSK) | ((1 << endpoint) << DAINTMSK_IN_SHIFT)); InEPRegs[endpoint].dmaAddress = buffer; if(endpoint == USB_CONTROLEP) { // we'll only send one packet at a time on CONTROLEP InEPRegs[endpoint].transferSize = ((1 & DEPTSIZ_PKTCNT_MASK) << DEPTSIZ_PKTCNT_SHIFT) | (bufferLen & DEPTSIZ0_XFERSIZ_MASK); InEPRegs[endpoint].control = USB_EPCON_CLEARNAK; return; } int packetCount = bufferLen / packetLength; if((bufferLen % packetLength) != 0) ++packetCount; InEPRegs[endpoint].transferSize = ((packetCount & DEPTSIZ_PKTCNT_MASK) << DEPTSIZ_PKTCNT_SHIFT) | (bufferLen & DEPTSIZ_XFERSIZ_MASK) | ((USB_MULTICOUNT & DIEPTSIZ_MC_MASK) << DIEPTSIZ_MC_SHIFT); InEPRegs[endpoint].control = USB_EPCON_CLEARNAK | USB_EPCON_ACTIVE | ((transferType & USB_EPCON_TYPE_MASK) << USB_EPCON_TYPE_SHIFT) | (packetLength & USB_EPCON_MPS_MASK); }
int dma_perform(uint32_t Source, uint32_t Destination, int size, int continueList, int* controller, int* channel) { uint32_t regSrcAddress; uint32_t regDestAddress; uint32_t regLLI; uint32_t regControl0; uint32_t regConfiguration; const uint32_t regControl0Mask = ~(DMAC0Control0_SIZEMASK | DMAC0Control0_SOURCEINCREMENT | DMAC0Control0_DESTINATIONINCREMENT); uint32_t regOffset = (*channel * DMAChannelRegSize); if(*controller == 1) { regOffset += DMAC0; } else if(*controller == 2) { regOffset += DMAC1; } regSrcAddress = regOffset + DMAC0SrcAddress; regDestAddress = regOffset + DMAC0DestAddress; regLLI = regOffset + DMAC0LLI; regControl0 = regOffset + DMAC0Control0; regConfiguration = regOffset + DMAC0Configuration; int transfers = size/(1 << DMAC0Control0_DWIDTH(GET_REG(regControl0))); uint32_t sourcePeripheral = 0; uint32_t destPeripheral = 0; uint32_t flowControl = 0; uint32_t sourceIncrement = 0; uint32_t destinationIncrement = 0; if(Source <= (sizeof(AddressLookupTable)/sizeof(uint32_t))) { if(Destination <= (sizeof(AddressLookupTable)/sizeof(uint32_t))) { SET_REG(regSrcAddress, AddressLookupTable[Source]); SET_REG(regDestAddress, AddressLookupTable[Destination]); sourcePeripheral = PeripheralLookupTable[Source][*controller - 1]; destPeripheral = PeripheralLookupTable[Destination][*controller - 1]; flowControl = DMAC0Configuration_FLOWCNTRL_P2P; } else { SET_REG(regSrcAddress, AddressLookupTable[Source]); SET_REG(regDestAddress, Destination); sourcePeripheral = PeripheralLookupTable[Source][*controller - 1]; destPeripheral = PeripheralLookupTable[DMA_MEMORY][*controller - 1]; flowControl = DMAC0Configuration_FLOWCNTRL_P2M; destinationIncrement = 1 << DMAC0Control0_DESTINATIONINCREMENT; } } else { if(Destination <= (sizeof(AddressLookupTable)/sizeof(uint32_t))) { SET_REG(regSrcAddress, Source); SET_REG(regDestAddress, AddressLookupTable[Destination]); sourcePeripheral = PeripheralLookupTable[DMA_MEMORY][*controller - 1]; destPeripheral = PeripheralLookupTable[Destination][*controller - 1]; flowControl = DMAC0Configuration_FLOWCNTRL_M2P; sourceIncrement = 1 << DMAC0Control0_SOURCEINCREMENT; } else { SET_REG(regSrcAddress, Source); SET_REG(regDestAddress, Destination); sourcePeripheral = PeripheralLookupTable[DMA_MEMORY][*controller - 1]; destPeripheral = PeripheralLookupTable[DMA_MEMORY][*controller - 1]; flowControl = DMAC0Configuration_FLOWCNTRL_M2M; sourceIncrement = 1 << DMAC0Control0_SOURCEINCREMENT; destinationIncrement = 1 << DMAC0Control0_DESTINATIONINCREMENT; } } if(!continueList) { uint32_t src = GET_REG(regSrcAddress); uint32_t dest = GET_REG(regDestAddress); if(transfers > 0xFFF) { SET_REG(regControl0, GET_REG(regControl0) & ~(1 << DMAC0Control0_TERMINALCOUNTINTERRUPTENABLE)); if(DMALists[*controller - 1][*channel]) free(DMALists[*controller - 1][*channel]); DMALinkedList* item = DMALists[*controller - 1][*channel] = malloc(((transfers + 0xDFF) / 0xE00) * sizeof(DMALinkedList)); SET_REG(regLLI, (uint32_t)item); do { transfers -= 0xE00; if(sourceIncrement != 0) { src += 0xE00 << DMAC0Control0_DWIDTH(GET_REG(regControl0)); } if(destinationIncrement != 0) { dest += 0xE00 << DMAC0Control0_DWIDTH(GET_REG(regControl0)); } item->source = src; item->destination = dest; if(transfers <= 0xE00) { item->control = destinationIncrement | sourceIncrement | (regControl0Mask & GET_REG(regControl0)) | (transfers & DMAC0Control0_SIZEMASK) | (1 << DMAC0Control0_TERMINALCOUNTINTERRUPTENABLE); item->next = NULL; } else { item->control = destinationIncrement | sourceIncrement | (regControl0Mask & GET_REG(regControl0)) | 0xE00; item->next = item + 1; item = item->next; } } while(transfers > 0xE00); CleanAndInvalidateCPUDataCache(); transfers = 0xE00; } else { SET_REG(regLLI, 0); } } else { StaticDMALists[*controller - 1][*channel].control = GET_REG(regControl0); SET_REG(regLLI, (uint32_t)&StaticDMALists[*controller - 1][*channel]); } SET_REG(regControl0, (GET_REG(regControl0) & regControl0Mask) | destinationIncrement | sourceIncrement | (transfers & DMAC0Control0_SIZEMASK)); SET_REG(regConfiguration, DMAC0Configuration_CHANNELENABLED | DMAC0Configuration_TERMINALCOUNTINTERRUPTMASK | (flowControl << DMAC0Configuration_FLOWCNTRLSHIFT) | (destPeripheral << DMAC0Configuration_DESTPERIPHERALSHIFT) | (sourcePeripheral << DMAC0Configuration_SRCPERIPHERALSHIFT)); return 0; }
static void receiveControl(void* buffer, int bufferLen) { CleanAndInvalidateCPUDataCache(); receive(USB_CONTROLEP, USBControl, buffer, USB_MAX_PACKETSIZE, bufferLen); }
void arm_disable_caches() { CleanAndInvalidateCPUDataCache(); ClearCPUInstructionCache(); WriteControlRegisterConfigData(ReadControlRegisterConfigData() & ~ARM11_Control_INSTRUCTIONCACHE); // Disable instruction cache WriteControlRegisterConfigData(ReadControlRegisterConfigData() & ~ARM11_Control_DATACACHE); // Disable data cache }