112239Sandreas.sandberg@arm.com/* 212239Sandreas.sandberg@arm.com * Copyright (c) 2005 The Regents of The University of Michigan 312239Sandreas.sandberg@arm.com * All rights reserved. 412239Sandreas.sandberg@arm.com * 512239Sandreas.sandberg@arm.com * Redistribution and use in source and binary forms, with or without 612239Sandreas.sandberg@arm.com * modification, are permitted provided that the following conditions are 712239Sandreas.sandberg@arm.com * met: redistributions of source code must retain the above copyright 812239Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer; 912239Sandreas.sandberg@arm.com * redistributions in binary form must reproduce the above copyright 1012239Sandreas.sandberg@arm.com * notice, this list of conditions and the following disclaimer in the 1112239Sandreas.sandberg@arm.com * documentation and/or other materials provided with the distribution; 1212239Sandreas.sandberg@arm.com * neither the name of the copyright holders nor the names of its 1312239Sandreas.sandberg@arm.com * contributors may be used to endorse or promote products derived from 1412239Sandreas.sandberg@arm.com * this software without specific prior written permission. 1512239Sandreas.sandberg@arm.com * 1612239Sandreas.sandberg@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1712239Sandreas.sandberg@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1812239Sandreas.sandberg@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1912239Sandreas.sandberg@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 2012239Sandreas.sandberg@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 2112239Sandreas.sandberg@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 2212239Sandreas.sandberg@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2312239Sandreas.sandberg@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2412239Sandreas.sandberg@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2512239Sandreas.sandberg@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 2612239Sandreas.sandberg@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2712239Sandreas.sandberg@arm.com * 2812239Sandreas.sandberg@arm.com * Authors: Ali Saidi 2912239Sandreas.sandberg@arm.com */ 3012239Sandreas.sandberg@arm.com 3112239Sandreas.sandberg@arm.com/** @file 3212239Sandreas.sandberg@arm.com * Implements a 8250 UART 3312239Sandreas.sandberg@arm.com */ 3412239Sandreas.sandberg@arm.com 3512239Sandreas.sandberg@arm.com#include "dev/serial/uart8250.hh" 3612239Sandreas.sandberg@arm.com 3712239Sandreas.sandberg@arm.com#include <string> 3812239Sandreas.sandberg@arm.com#include <vector> 3912239Sandreas.sandberg@arm.com 4012239Sandreas.sandberg@arm.com#include "base/inifile.hh" 4112239Sandreas.sandberg@arm.com#include "base/trace.hh" 4212239Sandreas.sandberg@arm.com#include "config/the_isa.hh" 4312239Sandreas.sandberg@arm.com#include "debug/Uart.hh" 4412239Sandreas.sandberg@arm.com#include "dev/platform.hh" 4512239Sandreas.sandberg@arm.com#include "mem/packet.hh" 4612239Sandreas.sandberg@arm.com#include "mem/packet_access.hh" 4712239Sandreas.sandberg@arm.com 4812239Sandreas.sandberg@arm.comusing namespace std; 4912239Sandreas.sandberg@arm.com 5012239Sandreas.sandberg@arm.comvoid 5112239Sandreas.sandberg@arm.comUart8250::processIntrEvent(int intrBit) 5212239Sandreas.sandberg@arm.com{ 5312239Sandreas.sandberg@arm.com if (intrBit & IER) { 5412239Sandreas.sandberg@arm.com DPRINTF(Uart, "UART InterEvent, interrupting\n"); 5512239Sandreas.sandberg@arm.com platform->postConsoleInt(); 5612239Sandreas.sandberg@arm.com status |= intrBit; 5712239Sandreas.sandberg@arm.com lastTxInt = curTick(); 5812239Sandreas.sandberg@arm.com } 5912239Sandreas.sandberg@arm.com else 6012239Sandreas.sandberg@arm.com DPRINTF(Uart, "UART InterEvent, not interrupting\n"); 6112239Sandreas.sandberg@arm.com 6212239Sandreas.sandberg@arm.com} 6312239Sandreas.sandberg@arm.com 6412239Sandreas.sandberg@arm.com/* The linux serial driver (8250.c about line 1182) loops reading from 6512239Sandreas.sandberg@arm.com * the device until the device reports it has no more data to 6612239Sandreas.sandberg@arm.com * read. After a maximum of 255 iterations the code prints "serial8250 6712239Sandreas.sandberg@arm.com * too much work for irq X," and breaks out of the loop. Since the 6812239Sandreas.sandberg@arm.com * simulated system is so much slower than the actual system, if a 6912239Sandreas.sandberg@arm.com * user is typing on the keyboard it is very easy for them to provide 7012239Sandreas.sandberg@arm.com * input at a fast enough rate to not allow the loop to exit and thus 7112239Sandreas.sandberg@arm.com * the error to be printed. This magic number provides a delay between 7212239Sandreas.sandberg@arm.com * the time the UART receives a character to send to the simulated 7312239Sandreas.sandberg@arm.com * system and the time it actually notifies the system it has a 7412239Sandreas.sandberg@arm.com * character to send to alleviate this problem. --Ali 7512239Sandreas.sandberg@arm.com */ 7612239Sandreas.sandberg@arm.comvoid 7712239Sandreas.sandberg@arm.comUart8250::scheduleIntr(Event *event) 7812239Sandreas.sandberg@arm.com{ 7912239Sandreas.sandberg@arm.com static const Tick interval = 225 * SimClock::Int::ns; 8012239Sandreas.sandberg@arm.com DPRINTF(Uart, "Scheduling IER interrupt for %s, at cycle %lld\n", 8112239Sandreas.sandberg@arm.com event->name(), curTick() + interval); 8212239Sandreas.sandberg@arm.com if (!event->scheduled()) 8312239Sandreas.sandberg@arm.com schedule(event, curTick() + interval); 8412239Sandreas.sandberg@arm.com else 8512239Sandreas.sandberg@arm.com reschedule(event, curTick() + interval); 8612239Sandreas.sandberg@arm.com} 8712239Sandreas.sandberg@arm.com 8812239Sandreas.sandberg@arm.com 8912239Sandreas.sandberg@arm.comUart8250::Uart8250(const Params *p) 9012239Sandreas.sandberg@arm.com : Uart(p, 8), IER(0), DLAB(0), LCR(0), MCR(0), lastTxInt(0), 9112239Sandreas.sandberg@arm.com txIntrEvent([this]{ processIntrEvent(TX_INT); }, "TX"), 9212239Sandreas.sandberg@arm.com rxIntrEvent([this]{ processIntrEvent(RX_INT); }, "RX") 9312239Sandreas.sandberg@arm.com{ 9412239Sandreas.sandberg@arm.com} 9512239Sandreas.sandberg@arm.com 9612239Sandreas.sandberg@arm.comTick 9712239Sandreas.sandberg@arm.comUart8250::read(PacketPtr pkt) 9812239Sandreas.sandberg@arm.com{ 9912239Sandreas.sandberg@arm.com assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 10012239Sandreas.sandberg@arm.com assert(pkt->getSize() == 1); 10112239Sandreas.sandberg@arm.com 10212239Sandreas.sandberg@arm.com Addr daddr = pkt->getAddr() - pioAddr; 10312239Sandreas.sandberg@arm.com 10412239Sandreas.sandberg@arm.com DPRINTF(Uart, " read register %#x\n", daddr); 10512239Sandreas.sandberg@arm.com 10612239Sandreas.sandberg@arm.com switch (daddr) { 10712239Sandreas.sandberg@arm.com case 0x0: 10812239Sandreas.sandberg@arm.com if (!(LCR & 0x80)) { // read byte 10912239Sandreas.sandberg@arm.com if (device->dataAvailable()) 11013342Sgabeblack@google.com pkt->setRaw(device->readData()); 11112239Sandreas.sandberg@arm.com else { 11213342Sgabeblack@google.com pkt->setRaw((uint8_t)0); 11312239Sandreas.sandberg@arm.com // A limited amount of these are ok. 11412239Sandreas.sandberg@arm.com DPRINTF(Uart, "empty read of RX register\n"); 11512239Sandreas.sandberg@arm.com } 11612239Sandreas.sandberg@arm.com status &= ~RX_INT; 11712239Sandreas.sandberg@arm.com platform->clearConsoleInt(); 11812239Sandreas.sandberg@arm.com 11912239Sandreas.sandberg@arm.com if (device->dataAvailable() && (IER & UART_IER_RDI)) 12012239Sandreas.sandberg@arm.com scheduleIntr(&rxIntrEvent); 12112239Sandreas.sandberg@arm.com } else { // dll divisor latch 12212239Sandreas.sandberg@arm.com ; 12312239Sandreas.sandberg@arm.com } 12412239Sandreas.sandberg@arm.com break; 12512239Sandreas.sandberg@arm.com case 0x1: 12612239Sandreas.sandberg@arm.com if (!(LCR & 0x80)) { // Intr Enable Register(IER) 12713342Sgabeblack@google.com pkt->setRaw(IER); 12812239Sandreas.sandberg@arm.com } else { // DLM divisor latch MSB 12912239Sandreas.sandberg@arm.com ; 13012239Sandreas.sandberg@arm.com } 13112239Sandreas.sandberg@arm.com break; 13212239Sandreas.sandberg@arm.com case 0x2: // Intr Identification Register (IIR) 13312239Sandreas.sandberg@arm.com DPRINTF(Uart, "IIR Read, status = %#x\n", (uint32_t)status); 13412239Sandreas.sandberg@arm.com 13512239Sandreas.sandberg@arm.com if (status & RX_INT) /* Rx data interrupt has a higher priority */ 13613342Sgabeblack@google.com pkt->setRaw(IIR_RXID); 13712239Sandreas.sandberg@arm.com else if (status & TX_INT) { 13813342Sgabeblack@google.com pkt->setRaw(IIR_TXID); 13912239Sandreas.sandberg@arm.com //Tx interrupts are cleared on IIR reads 14012239Sandreas.sandberg@arm.com status &= ~TX_INT; 14112239Sandreas.sandberg@arm.com } else 14213342Sgabeblack@google.com pkt->setRaw(IIR_NOPEND); 14312239Sandreas.sandberg@arm.com 14412239Sandreas.sandberg@arm.com break; 14512239Sandreas.sandberg@arm.com case 0x3: // Line Control Register (LCR) 14613342Sgabeblack@google.com pkt->setRaw(LCR); 14712239Sandreas.sandberg@arm.com break; 14812239Sandreas.sandberg@arm.com case 0x4: // Modem Control Register (MCR) 14913342Sgabeblack@google.com pkt->setRaw(MCR); 15012239Sandreas.sandberg@arm.com break; 15112239Sandreas.sandberg@arm.com case 0x5: // Line Status Register (LSR) 15212239Sandreas.sandberg@arm.com uint8_t lsr; 15312239Sandreas.sandberg@arm.com lsr = 0; 15412239Sandreas.sandberg@arm.com // check if there are any bytes to be read 15512239Sandreas.sandberg@arm.com if (device->dataAvailable()) 15612239Sandreas.sandberg@arm.com lsr = UART_LSR_DR; 15712239Sandreas.sandberg@arm.com lsr |= UART_LSR_TEMT | UART_LSR_THRE; 15813342Sgabeblack@google.com pkt->setRaw(lsr); 15912239Sandreas.sandberg@arm.com break; 16012239Sandreas.sandberg@arm.com case 0x6: // Modem Status Register (MSR) 16113342Sgabeblack@google.com pkt->setRaw((uint8_t)0); 16212239Sandreas.sandberg@arm.com break; 16312239Sandreas.sandberg@arm.com case 0x7: // Scratch Register (SCR) 16413342Sgabeblack@google.com pkt->setRaw((uint8_t)0); // doesn't exist with at 8250. 16512239Sandreas.sandberg@arm.com break; 16612239Sandreas.sandberg@arm.com default: 16712239Sandreas.sandberg@arm.com panic("Tried to access a UART port that doesn't exist\n"); 16812239Sandreas.sandberg@arm.com break; 16912239Sandreas.sandberg@arm.com } 17012239Sandreas.sandberg@arm.com/* uint32_t d32 = *data; 17112239Sandreas.sandberg@arm.com DPRINTF(Uart, "Register read to register %#x returned %#x\n", daddr, d32); 17212239Sandreas.sandberg@arm.com*/ 17312239Sandreas.sandberg@arm.com pkt->makeAtomicResponse(); 17412239Sandreas.sandberg@arm.com return pioDelay; 17512239Sandreas.sandberg@arm.com} 17612239Sandreas.sandberg@arm.com 17712239Sandreas.sandberg@arm.comTick 17812239Sandreas.sandberg@arm.comUart8250::write(PacketPtr pkt) 17912239Sandreas.sandberg@arm.com{ 18012239Sandreas.sandberg@arm.com 18112239Sandreas.sandberg@arm.com assert(pkt->getAddr() >= pioAddr && pkt->getAddr() < pioAddr + pioSize); 18212239Sandreas.sandberg@arm.com assert(pkt->getSize() == 1); 18312239Sandreas.sandberg@arm.com 18412239Sandreas.sandberg@arm.com Addr daddr = pkt->getAddr() - pioAddr; 18512239Sandreas.sandberg@arm.com 18613342Sgabeblack@google.com DPRINTF(Uart, " write register %#x value %#x\n", daddr, 18713342Sgabeblack@google.com pkt->getRaw<uint8_t>()); 18812239Sandreas.sandberg@arm.com 18912239Sandreas.sandberg@arm.com switch (daddr) { 19012239Sandreas.sandberg@arm.com case 0x0: 19112239Sandreas.sandberg@arm.com if (!(LCR & 0x80)) { // write byte 19213342Sgabeblack@google.com device->writeData(pkt->getRaw<uint8_t>()); 19312239Sandreas.sandberg@arm.com platform->clearConsoleInt(); 19412239Sandreas.sandberg@arm.com status &= ~TX_INT; 19512239Sandreas.sandberg@arm.com if (UART_IER_THRI & IER) 19612239Sandreas.sandberg@arm.com scheduleIntr(&txIntrEvent); 19712239Sandreas.sandberg@arm.com } else { // dll divisor latch 19812239Sandreas.sandberg@arm.com ; 19912239Sandreas.sandberg@arm.com } 20012239Sandreas.sandberg@arm.com break; 20112239Sandreas.sandberg@arm.com case 0x1: 20212239Sandreas.sandberg@arm.com if (!(LCR & 0x80)) { // Intr Enable Register(IER) 20313342Sgabeblack@google.com IER = pkt->getRaw<uint8_t>(); 20412239Sandreas.sandberg@arm.com if (UART_IER_THRI & IER) 20512239Sandreas.sandberg@arm.com { 20613342Sgabeblack@google.com DPRINTF(Uart, 20713342Sgabeblack@google.com "IER: IER_THRI set, scheduling TX intrrupt\n"); 20812239Sandreas.sandberg@arm.com if (curTick() - lastTxInt > 225 * SimClock::Int::ns) { 20912239Sandreas.sandberg@arm.com DPRINTF(Uart, "-- Interrupting Immediately... %d,%d\n", 21012239Sandreas.sandberg@arm.com curTick(), lastTxInt); 21112239Sandreas.sandberg@arm.com txIntrEvent.process(); 21212239Sandreas.sandberg@arm.com } else { 21312239Sandreas.sandberg@arm.com DPRINTF(Uart, "-- Delaying interrupt... %d,%d\n", 21412239Sandreas.sandberg@arm.com curTick(), lastTxInt); 21512239Sandreas.sandberg@arm.com scheduleIntr(&txIntrEvent); 21612239Sandreas.sandberg@arm.com } 21712239Sandreas.sandberg@arm.com } 21812239Sandreas.sandberg@arm.com else 21912239Sandreas.sandberg@arm.com { 22013342Sgabeblack@google.com DPRINTF(Uart, "IER: IER_THRI cleared, " 22113342Sgabeblack@google.com "descheduling TX intrrupt\n"); 22212239Sandreas.sandberg@arm.com if (txIntrEvent.scheduled()) 22312239Sandreas.sandberg@arm.com deschedule(txIntrEvent); 22412239Sandreas.sandberg@arm.com if (status & TX_INT) 22512239Sandreas.sandberg@arm.com platform->clearConsoleInt(); 22612239Sandreas.sandberg@arm.com status &= ~TX_INT; 22712239Sandreas.sandberg@arm.com } 22812239Sandreas.sandberg@arm.com 22912239Sandreas.sandberg@arm.com if ((UART_IER_RDI & IER) && device->dataAvailable()) { 23013342Sgabeblack@google.com DPRINTF(Uart, 23113342Sgabeblack@google.com "IER: IER_RDI set, scheduling RX intrrupt\n"); 23212239Sandreas.sandberg@arm.com scheduleIntr(&rxIntrEvent); 23312239Sandreas.sandberg@arm.com } else { 23413342Sgabeblack@google.com DPRINTF(Uart, "IER: IER_RDI cleared, " 23513342Sgabeblack@google.com "descheduling RX intrrupt\n"); 23612239Sandreas.sandberg@arm.com if (rxIntrEvent.scheduled()) 23712239Sandreas.sandberg@arm.com deschedule(rxIntrEvent); 23812239Sandreas.sandberg@arm.com if (status & RX_INT) 23912239Sandreas.sandberg@arm.com platform->clearConsoleInt(); 24012239Sandreas.sandberg@arm.com status &= ~RX_INT; 24112239Sandreas.sandberg@arm.com } 24212239Sandreas.sandberg@arm.com } else { // DLM divisor latch MSB 24312239Sandreas.sandberg@arm.com ; 24412239Sandreas.sandberg@arm.com } 24512239Sandreas.sandberg@arm.com break; 24612239Sandreas.sandberg@arm.com case 0x2: // FIFO Control Register (FCR) 24712239Sandreas.sandberg@arm.com break; 24812239Sandreas.sandberg@arm.com case 0x3: // Line Control Register (LCR) 24913342Sgabeblack@google.com LCR = pkt->getRaw<uint8_t>(); 25012239Sandreas.sandberg@arm.com break; 25112239Sandreas.sandberg@arm.com case 0x4: // Modem Control Register (MCR) 25213342Sgabeblack@google.com if (pkt->getRaw<uint8_t>() == (UART_MCR_LOOP | 0x0A)) 25312239Sandreas.sandberg@arm.com MCR = 0x9A; 25412239Sandreas.sandberg@arm.com break; 25512239Sandreas.sandberg@arm.com case 0x7: // Scratch Register (SCR) 25612239Sandreas.sandberg@arm.com // We are emulating a 8250 so we don't have a scratch reg 25712239Sandreas.sandberg@arm.com break; 25812239Sandreas.sandberg@arm.com default: 25912239Sandreas.sandberg@arm.com panic("Tried to access a UART port that doesn't exist\n"); 26012239Sandreas.sandberg@arm.com break; 26112239Sandreas.sandberg@arm.com } 26212239Sandreas.sandberg@arm.com pkt->makeAtomicResponse(); 26312239Sandreas.sandberg@arm.com return pioDelay; 26412239Sandreas.sandberg@arm.com} 26512239Sandreas.sandberg@arm.com 26612239Sandreas.sandberg@arm.comvoid 26712239Sandreas.sandberg@arm.comUart8250::dataAvailable() 26812239Sandreas.sandberg@arm.com{ 26912239Sandreas.sandberg@arm.com // if the kernel wants an interrupt when we have data 27012239Sandreas.sandberg@arm.com if (IER & UART_IER_RDI) 27112239Sandreas.sandberg@arm.com { 27212239Sandreas.sandberg@arm.com platform->postConsoleInt(); 27312239Sandreas.sandberg@arm.com status |= RX_INT; 27412239Sandreas.sandberg@arm.com } 27512239Sandreas.sandberg@arm.com 27612239Sandreas.sandberg@arm.com} 27712239Sandreas.sandberg@arm.com 27812239Sandreas.sandberg@arm.comAddrRangeList 27912239Sandreas.sandberg@arm.comUart8250::getAddrRanges() const 28012239Sandreas.sandberg@arm.com{ 28112239Sandreas.sandberg@arm.com AddrRangeList ranges; 28212239Sandreas.sandberg@arm.com ranges.push_back(RangeSize(pioAddr, pioSize)); 28312239Sandreas.sandberg@arm.com return ranges; 28412239Sandreas.sandberg@arm.com} 28512239Sandreas.sandberg@arm.com 28612239Sandreas.sandberg@arm.comvoid 28712239Sandreas.sandberg@arm.comUart8250::serialize(CheckpointOut &cp) const 28812239Sandreas.sandberg@arm.com{ 28912239Sandreas.sandberg@arm.com SERIALIZE_SCALAR(status); 29012239Sandreas.sandberg@arm.com SERIALIZE_SCALAR(IER); 29112239Sandreas.sandberg@arm.com SERIALIZE_SCALAR(DLAB); 29212239Sandreas.sandberg@arm.com SERIALIZE_SCALAR(LCR); 29312239Sandreas.sandberg@arm.com SERIALIZE_SCALAR(MCR); 29412239Sandreas.sandberg@arm.com Tick rxintrwhen; 29512239Sandreas.sandberg@arm.com if (rxIntrEvent.scheduled()) 29612239Sandreas.sandberg@arm.com rxintrwhen = rxIntrEvent.when(); 29712239Sandreas.sandberg@arm.com else 29812239Sandreas.sandberg@arm.com rxintrwhen = 0; 29912239Sandreas.sandberg@arm.com Tick txintrwhen; 30012239Sandreas.sandberg@arm.com if (txIntrEvent.scheduled()) 30112239Sandreas.sandberg@arm.com txintrwhen = txIntrEvent.when(); 30212239Sandreas.sandberg@arm.com else 30312239Sandreas.sandberg@arm.com txintrwhen = 0; 30412239Sandreas.sandberg@arm.com SERIALIZE_SCALAR(rxintrwhen); 30512239Sandreas.sandberg@arm.com SERIALIZE_SCALAR(txintrwhen); 30612239Sandreas.sandberg@arm.com} 30712239Sandreas.sandberg@arm.com 30812239Sandreas.sandberg@arm.comvoid 30912239Sandreas.sandberg@arm.comUart8250::unserialize(CheckpointIn &cp) 31012239Sandreas.sandberg@arm.com{ 31112239Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(status); 31212239Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(IER); 31312239Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(DLAB); 31412239Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(LCR); 31512239Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(MCR); 31612239Sandreas.sandberg@arm.com Tick rxintrwhen; 31712239Sandreas.sandberg@arm.com Tick txintrwhen; 31812239Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(rxintrwhen); 31912239Sandreas.sandberg@arm.com UNSERIALIZE_SCALAR(txintrwhen); 32012239Sandreas.sandberg@arm.com if (rxintrwhen != 0) 32112239Sandreas.sandberg@arm.com schedule(rxIntrEvent, rxintrwhen); 32212239Sandreas.sandberg@arm.com if (txintrwhen != 0) 32312239Sandreas.sandberg@arm.com schedule(txIntrEvent, txintrwhen); 32412239Sandreas.sandberg@arm.com} 32512239Sandreas.sandberg@arm.com 32612239Sandreas.sandberg@arm.comUart8250 * 32712239Sandreas.sandberg@arm.comUart8250Params::create() 32812239Sandreas.sandberg@arm.com{ 32912239Sandreas.sandberg@arm.com return new Uart8250(this); 33012239Sandreas.sandberg@arm.com} 331