Skip to content

Commit

Permalink
new time/early_printk/uart drivers compiling, untested
Browse files Browse the repository at this point in the history
Sebastien Bourdeauducq committed May 22, 2012
1 parent aa07145 commit 3faaf7a
Showing 8 changed files with 122 additions and 238 deletions.
6 changes: 2 additions & 4 deletions arch/lm32/Kconfig.cpu
Original file line number Diff line number Diff line change
@@ -20,6 +20,7 @@ config CPU_MICO32
bool "mico32"
help
LatticeMico32 processor.

endchoice

choice
@@ -29,15 +30,12 @@ choice
config BOARD_MILKYMIST_ONE
bool "Milkymist One"

config BOARD_MILKYMIST_SOC
bool "Milkymist SoC"
endchoice
endif

config CPU_CLOCK
int "CPU Clock [Hz] (integer)"
default "80000000" if BOARD_MILKYMIST_ONE
default "100000000" if BOARD_MILKYMIST_SOC
default "83333333" if BOARD_MILKYMIST_ONE

config KERNEL_BASE_ADDR
hex "Physical address where Linux Kernel is"
42 changes: 15 additions & 27 deletions arch/lm32/boot/dts/milkymist_one.dts
Original file line number Diff line number Diff line change
@@ -23,7 +23,7 @@
device_type = "cpu";
compatible = "lattice,mico32";
reg = <0>;
clock-frequency = <80000000>; /* 80 MHz */
clock-frequency = <83333333>;
i-cache-line-size = <16>;
d-cache-line-size = <16>;
i-cache-size = <4096>;
@@ -43,46 +43,34 @@
reg = <0x40000000 0x08000000>; /* 128MB */
};

flash@0 {
compatible = "cfi-flash";
reg = <0x80000000 0x02000000>; /* 32MB */
bank-width = <4>;
device-width = <1>;
#address-cells = <1>;
#size-cells = <1>;
partition@0 {
label = "bitstream";
reg = <0x00000000 0x00180000>;
read-only;
};
partition@180000 {
label = "unused";
reg = <0x000a0000 0x02360000>;
read-only;
};
};

csr-bus@e0000000 {
#address-cells = <1>;
#size-cells = <1>;
ranges = <0x0 0xe0000000 0x100000>;
compatible = "milkymist,csr-bus";

uart@0 {
uart@0000 {
device_type = "serial";
compatible = "milkymist,uart";
clock-frequency = <80000000>;
reg = <0x0 0x1000>;
clock-frequency = <83333333>;
reg = <0x0000 0x800>;
interrupts = <0>;
interrupt-parent = <&pic>;
};

timer@1800 {
compatible = "milkymist,timer";
reg = <0x1800 0x800>;
interrupts = <1>;
interrupt-parent = <&pic>;
};

ethernet@8000 {
ethernet@2000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "milkymist,minimac2";
reg = <0x8000 0x1000>;
interrupts = <10 11>;
compatible = "milkymist,minimac3";
reg = <0x2000 0x800>;
interrupts = <2>;
interrupt-parent = <&pic>;

phy0: ethernet-phy@0 {
85 changes: 8 additions & 77 deletions arch/lm32/defconfig
Original file line number Diff line number Diff line change
@@ -161,19 +161,18 @@ CONFIG_INLINE_WRITE_UNLOCK_IRQ=y
CONFIG_PLAT_MILKYMIST=y
CONFIG_CPU_MICO32=y
CONFIG_BOARD_MILKYMIST_ONE=y
# CONFIG_BOARD_MILKYMIST_SOC is not set
CONFIG_CPU_CLOCK=80000000
CONFIG_CPU_CLOCK=83333333
CONFIG_KERNEL_BASE_ADDR=0x40000000
# CONFIG_EARLY_PRINTK is not set
CONFIG_EARLY_PRINTK=y
# CONFIG_LM32_HW_JTAG is not set
# CONFIG_NO_HZ is not set
# CONFIG_HIGH_RES_TIMERS is not set
CONFIG_GENERIC_CLOCKEVENTS_BUILD=y
# CONFIG_HZ_100 is not set
CONFIG_HZ_250=y
CONFIG_HZ_100=y
# CONFIG_HZ_250 is not set
# CONFIG_HZ_300 is not set
# CONFIG_HZ_1000 is not set
CONFIG_HZ=250
CONFIG_HZ=100
# CONFIG_SCHED_HRTICK is not set
CONFIG_FLATMEM_MANUAL=y
CONFIG_HAVE_MEMBLOCK=y
@@ -250,7 +249,6 @@ CONFIG_DEFAULT_TCP_CONG="cubic"
# CONFIG_ATM is not set
# CONFIG_L2TP is not set
# CONFIG_BRIDGE is not set
# CONFIG_NET_DSA is not set
# CONFIG_VLAN_8021Q is not set
# CONFIG_DECNET is not set
# CONFIG_LLC2 is not set
@@ -313,8 +311,6 @@ CONFIG_OF_ADDRESS=y
CONFIG_OF_IRQ=y
CONFIG_OF_DEVICE=y
CONFIG_OF_GPIO=y
CONFIG_OF_NET=y
CONFIG_OF_MDIO=y
# CONFIG_PARPORT is not set
CONFIG_BLK_DEV=y
# CONFIG_BLK_DEV_COW_COMMON is not set
@@ -346,66 +342,7 @@ CONFIG_SCSI_MOD=y
# CONFIG_SCSI_NETLINK is not set
# CONFIG_ATA is not set
# CONFIG_MD is not set
CONFIG_NETDEVICES=y
# CONFIG_DUMMY is not set
# CONFIG_BONDING is not set
# CONFIG_MACVLAN is not set
# CONFIG_EQUALIZER is not set
# CONFIG_TUN is not set
# CONFIG_VETH is not set
# CONFIG_MII is not set
CONFIG_PHYLIB=y

#
# MII PHY device drivers
#
CONFIG_MARVELL_PHY=y
# CONFIG_DAVICOM_PHY is not set
# CONFIG_QSEMI_PHY is not set
# CONFIG_LXT_PHY is not set
# CONFIG_CICADA_PHY is not set
# CONFIG_VITESSE_PHY is not set
# CONFIG_SMSC_PHY is not set
# CONFIG_BROADCOM_PHY is not set
# CONFIG_ICPLUS_PHY is not set
# CONFIG_REALTEK_PHY is not set
# CONFIG_NATIONAL_PHY is not set
# CONFIG_STE10XP is not set
# CONFIG_LSI_ET1011C_PHY is not set
CONFIG_MICREL_PHY=y
# CONFIG_FIXED_PHY is not set
CONFIG_MDIO_BITBANG=y
# CONFIG_MDIO_GPIO is not set
# CONFIG_NET_ETHERNET is not set
# CONFIG_NETDEV_1000 is not set
# CONFIG_NETDEV_10000 is not set
# CONFIG_WLAN is not set

#
# Enable WiMAX (Networking options) to see the WiMAX drivers
#
# CONFIG_WAN is not set

#
# CAIF transport drivers
#
CONFIG_PPP=y
# CONFIG_PPP_MULTILINK is not set
# CONFIG_PPP_FILTER is not set
CONFIG_PPP_ASYNC=y
CONFIG_PPP_SYNC_TTY=y
CONFIG_PPP_DEFLATE=y
CONFIG_PPP_BSDCOMP=y
# CONFIG_PPP_MPPE is not set
# CONFIG_PPPOE is not set
CONFIG_SLIP=y
CONFIG_SLIP_COMPRESSED=y
CONFIG_SLHC=y
# CONFIG_SLIP_SMART is not set
# CONFIG_SLIP_MODE_SLIP6 is not set
# CONFIG_NETCONSOLE is not set
# CONFIG_NETPOLL is not set
# CONFIG_NET_POLL_CONTROLLER is not set
# CONFIG_NETDEVICES is not set
# CONFIG_ISDN is not set
# CONFIG_PHONE is not set

@@ -555,12 +492,7 @@ CONFIG_GPIOLIB=y
# CONFIG_HWMON is not set
# CONFIG_THERMAL is not set
# CONFIG_WATCHDOG is not set
CONFIG_MFD_SUPPORT=y
# CONFIG_MFD_CORE is not set
# CONFIG_MFD_SM501 is not set
# CONFIG_HTC_PASIC3 is not set
# CONFIG_MFD_TMIO is not set
# CONFIG_ABX500_CORE is not set
# CONFIG_MFD_SUPPORT is not set
# CONFIG_REGULATOR is not set
# CONFIG_MEDIA_SUPPORT is not set

@@ -597,7 +529,7 @@ CONFIG_DUMMY_CONSOLE=y
#
# CONFIG_VIRTIO_BALLOON is not set
# CONFIG_STAGING is not set
CONFIG_IOMMU_SUPPORT=y
# CONFIG_IOMMU_SUPPORT is not set
# CONFIG_VIRT_DRIVERS is not set

#
@@ -893,7 +825,6 @@ CONFIG_CRC32=y
# CONFIG_LIBCRC32C is not set
# CONFIG_CRC8 is not set
CONFIG_ZLIB_INFLATE=y
CONFIG_ZLIB_DEFLATE=y
# CONFIG_XZ_DEC is not set
# CONFIG_XZ_DEC_BCJ is not set
CONFIG_DECOMPRESS_GZIP=y
8 changes: 3 additions & 5 deletions arch/lm32/kernel/process.c
Original file line number Diff line number Diff line change
@@ -46,7 +46,6 @@
#include <asm/traps.h>
#include <asm/setup.h>
#include <asm/pgtable.h>
#include <asm/hw/milkymist.h>

asmlinkage void ret_from_fork(void);
asmlinkage void syscall_tail(void);
@@ -93,9 +92,9 @@ void cpu_idle(void)

void machine_restart(char * __unused)
{
/* Writing to CSR_SYSTEM_ID causes a system reset */
iowrite32be(1, CSR_SYSTEM_ID);
while(1);
printk("%s:%d: machine_restart() is not possible on lm32\n", __FILE__, __LINE__);
for (;;)
cpu_relax();
}

void machine_halt(void)
@@ -259,4 +258,3 @@ void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long usp)

/*printk("start_thread: current=%lx usp=%lx\n", current, usp);*/
}

19 changes: 4 additions & 15 deletions arch/lm32/platforms/milkymist/early_printk.c
Original file line number Diff line number Diff line change
@@ -36,26 +36,15 @@
#include <asm/irq.h>
#include <linux/io.h>

#define UART_RXTX (void*)0xe0000000
#define UART_DIVISOR (void*)0xe0000004
#define UART_STAT (void*)0xe0000008
#define UART_CTRL (void*)0xe000000c
#define UART_DEBUG (void*)0xe000000c
#define UART_RXTX ((void *)0xe0000000)
#define UART_STAT ((void *)0xe000000c)

#define UART_STAT_THRE (1<<0)
#define UART_STAT_RX_EVT (1<<1)
#define UART_STAT_TX_EVT (1<<2)
#define UART_STAT_TXING (1)

static void __init early_console_putc(char c)
{
unsigned int timeout = 1000;
uint32_t stat;

iowrite32be(c, UART_RXTX);

do {
stat = ioread32be(UART_STAT);
} while (!(stat & UART_STAT_THRE) && --timeout);
while(ioread32be(UART_STAT) & UART_STAT_TXING);
}

static void __init early_console_write(struct console *con, const char *s,
1 change: 0 additions & 1 deletion arch/lm32/platforms/milkymist/setup.c
Original file line number Diff line number Diff line change
@@ -8,4 +8,3 @@ void __init plat_setup_arch(void)
milkymist_setup_early_printk();
#endif
}

118 changes: 56 additions & 62 deletions arch/lm32/platforms/milkymist/time.c
Original file line number Diff line number Diff line change
@@ -21,74 +21,73 @@
#include <linux/timex.h>
#include <linux/io.h>

#include <asm/hw/interrupts.h>
#include <asm/hw/sysctl.h>
// TODO: use the DTS?
#define TIMER0_BASE 0xe0001800

#define TIMER_CLOCKEVENT 0
#define TIMER_CLOCKSOURCE 1
#define TIMER0_CSR(x) ((void *)(TIMER0_BASE+(x)))

static uint32_t milkymist_ticks_per_jiffy;
#define CSR_TIMER0_EN TIMER0_CSR(0x00)

static inline uint32_t milkymist_timer_get_counter(unsigned int timer)
{
return ioread32be(CSR_TIMER_COUNTER(timer));
}
#define CSR_TIMER0_COUNT3 TIMER0_CSR(0x04)
#define CSR_TIMER0_COUNT2 TIMER0_CSR(0x08)
#define CSR_TIMER0_COUNT1 TIMER0_CSR(0x0C)
#define CSR_TIMER0_COUNT0 TIMER0_CSR(0x10)

static inline void milkymist_timer_set_counter(unsigned int timer, uint32_t value)
{
iowrite32be(value, CSR_TIMER_COUNTER(timer));
}
#define CSR_TIMER0_RELOAD3 TIMER0_CSR(0x14)
#define CSR_TIMER0_RELOAD2 TIMER0_CSR(0x18)
#define CSR_TIMER0_RELOAD1 TIMER0_CSR(0x1C)
#define CSR_TIMER0_RELOAD0 TIMER0_CSR(0x20)

static inline uint32_t milkymist_timer_get_compare(unsigned int timer)
{
return ioread32be(CSR_TIMER_COMPARE(timer));
}
#define CSR_TIMER0_EV_STAT TIMER0_CSR(0x24)
#define CSR_TIMER0_EV_PENDING TIMER0_CSR(0x28)
#define CSR_TIMER0_EV_ENABLE TIMER0_CSR(0x2C)

static inline void milkymist_timer_set_compare(unsigned int timer, uint32_t value)
#define TIMER0_INTERRUPT 1


static uint32_t milkymist_ticks_per_jiffy;

static inline void milkymist_timer_set_counter(uint32_t value)
{
iowrite32be(value, CSR_TIMER_COMPARE(timer));
iowrite32be((value & 0xff000000) >> 24, CSR_TIMER0_COUNT3);
iowrite32be((value & 0x00ff0000) >> 16, CSR_TIMER0_COUNT2);
iowrite32be((value & 0x0000ff00) >> 8, CSR_TIMER0_COUNT1);
iowrite32be(value & 0x000000ff, CSR_TIMER0_COUNT0);
}

static inline void milkymist_timer_disable(unsigned int timer)
static inline void milkymist_timer_set_reload(uint32_t value)
{
iowrite32be(0, CSR_TIMER_CONTROL(timer));
iowrite32be((value & 0xff000000) >> 24, CSR_TIMER0_RELOAD3);
iowrite32be((value & 0x00ff0000) >> 16, CSR_TIMER0_RELOAD2);
iowrite32be((value & 0x0000ff00) >> 8, CSR_TIMER0_RELOAD1);
iowrite32be(value & 0x000000ff, CSR_TIMER0_RELOAD0);
}

static inline void milkymist_timer_enable(unsigned int timer, bool periodic)
static inline void milkymist_timer_disable(void)
{
uint32_t val = TIMER_ENABLE;
if (periodic);
val |= TIMER_AUTORESTART;
iowrite32be(val, CSR_TIMER_CONTROL(timer));
iowrite32be(0, CSR_TIMER0_EN);
}

cycles_t get_cycles(void)
static inline void milkymist_timer_enable(void)
{
return milkymist_timer_get_counter(TIMER_CLOCKSOURCE);
iowrite32be(1, CSR_TIMER0_EN);
}

static cycle_t milkymist_clocksource_read(struct clocksource *cs)
cycles_t get_cycles(void)
{
return get_cycles();
return 0;
}

static struct clocksource milkymist_clocksource = {
.name = "milkymist-timer",
.rating = 200,
.read = milkymist_clocksource_read,
.mask = CLOCKSOURCE_MASK(32),
.flags = CLOCK_SOURCE_IS_CONTINUOUS,
};

static irqreturn_t milkymist_clockevent_irq(int irq, void *devid)
{
struct clock_event_device *cd = devid;

if (cd->mode != CLOCK_EVT_MODE_PERIODIC)
milkymist_timer_disable(TIMER_CLOCKEVENT);
milkymist_timer_disable();

cd->event_handler(cd);


iowrite32be(1, CSR_TIMER0_EV_PENDING);
return IRQ_HANDLED;
}

@@ -97,15 +96,22 @@ static void milkymist_clockevent_set_mode(enum clock_event_mode mode,
{
switch (mode) {
case CLOCK_EVT_MODE_PERIODIC:
milkymist_timer_disable(TIMER_CLOCKEVENT);
milkymist_timer_set_counter(TIMER_CLOCKEVENT, 0);
milkymist_timer_set_compare(TIMER_CLOCKEVENT, milkymist_ticks_per_jiffy);
milkymist_timer_disable();
milkymist_timer_set_counter(milkymist_ticks_per_jiffy);
milkymist_timer_set_reload(milkymist_ticks_per_jiffy);
milkymist_timer_enable();
break;
case CLOCK_EVT_MODE_RESUME:
milkymist_timer_enable(TIMER_CLOCKEVENT, true);
milkymist_timer_enable();
break;
case CLOCK_EVT_MODE_ONESHOT:
milkymist_timer_disable();
milkymist_timer_set_counter(milkymist_ticks_per_jiffy);
milkymist_timer_set_reload(0);
milkymist_timer_enable();
break;
case CLOCK_EVT_MODE_SHUTDOWN:
milkymist_timer_disable(TIMER_CLOCKEVENT);
milkymist_timer_disable();
break;
default:
break;
@@ -115,9 +121,9 @@ static void milkymist_clockevent_set_mode(enum clock_event_mode mode,
static int milkymist_clockevent_set_next(unsigned long evt,
struct clock_event_device *cd)
{
milkymist_timer_set_counter(TIMER_CLOCKEVENT, 0);
milkymist_timer_set_compare(TIMER_CLOCKEVENT, evt);
milkymist_timer_enable(TIMER_CLOCKEVENT, false);
milkymist_timer_disable();
milkymist_timer_set_counter(evt);
milkymist_timer_enable();

return 0;
}
@@ -128,7 +134,7 @@ static struct clock_event_device milkymist_clockevent = {
.set_next_event = milkymist_clockevent_set_next,
.set_mode = milkymist_clockevent_set_mode,
.rating = 200,
.irq = IRQ_TIMER0,
.irq = TIMER0_INTERRUPT,
};

static struct irqaction timer_irqaction = {
@@ -140,26 +146,14 @@ static struct irqaction timer_irqaction = {

void __init plat_time_init(void)
{
int ret;

milkymist_ticks_per_jiffy = DIV_ROUND_CLOSEST(CONFIG_CPU_CLOCK, HZ);

clockevents_calc_mult_shift(&milkymist_clockevent, CONFIG_CPU_CLOCK, 5);
milkymist_clockevent.min_delta_ns = clockevent_delta2ns(100, &milkymist_clockevent);
milkymist_clockevent.max_delta_ns = clockevent_delta2ns(0xffff, &milkymist_clockevent);
milkymist_clockevent.cpumask = cpumask_of(0);

milkymist_timer_disable(TIMER_CLOCKSOURCE);
milkymist_timer_set_compare(TIMER_CLOCKSOURCE, 0xffffffff);
milkymist_timer_set_counter(TIMER_CLOCKSOURCE, 0);
milkymist_timer_enable(TIMER_CLOCKSOURCE, true);

clockevents_register_device(&milkymist_clockevent);

ret = clocksource_register_hz(&milkymist_clocksource, CONFIG_CPU_CLOCK);

if (ret)
printk(KERN_ERR "Failed to register clocksource: %d\n", ret);

setup_irq(IRQ_TIMER0, &timer_irqaction);
setup_irq(TIMER0_INTERRUPT, &timer_irqaction);
}
81 changes: 34 additions & 47 deletions drivers/tty/serial/milkymist_uart.c
Original file line number Diff line number Diff line change
@@ -48,21 +48,17 @@

#define MILKYMIST_NR_UARTS CONFIG_SERIAL_MILKYMIST_NR_UARTS

#define UART_RXTX 0x00
#define UART_DIV 0x04
#define UART_STAT 0x08
#define UART_CTRL 0x0c
#define UART_DEBUG 0x10
#define CSR_UART_RXTX 0x00
#define CSR_UART_DIVISORH 0x04
#define CSR_UART_DIVISORL 0x08

#define UART_STAT_THRE 0x01
#define UART_STAT_RX_EVT 0x02
#define UART_STAT_TX_EVT 0x04
#define CSR_UART_EV_STAT 0x0C
#define CSR_UART_EV_PENDING 0x10
#define CSR_UART_EV_ENABLE 0x14

#define UART_CTRL_RX_INT 0x01
#define UART_CTRL_TX_INT 0x02
#define UART_CTRL_THRU 0x04
#define UART_EV_TX 0x1
#define UART_EV_RX 0x2

#define UART_DEBUG_BREAK 0x01

static struct uart_port milkymist_uart_ports[MILKYMIST_NR_UARTS];

@@ -71,7 +67,7 @@ static void milkymist_uart_tx_char(struct uart_port *port)
struct circ_buf *xmit = &port->state->xmit;

if (port->x_char) {
iowrite32be(port->x_char, port->membase + UART_RXTX);
iowrite32be(port->x_char, port->membase + CSR_UART_RXTX);
port->x_char = 0;
port->icount.tx++;
return;
@@ -80,7 +76,7 @@ static void milkymist_uart_tx_char(struct uart_port *port)
if (uart_circ_empty(xmit) || uart_tx_stopped(port))
return;

iowrite32be(xmit->buf[xmit->tail], port->membase + UART_RXTX);
iowrite32be(xmit->buf[xmit->tail], port->membase + CSR_UART_RXTX);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE-1);
port->icount.tx++;

@@ -93,7 +89,7 @@ static void milkymist_uart_rx_char(struct uart_port *port)
struct tty_struct *tty = port->state->port.tty;
unsigned char ch;

ch = ioread32be(port->membase + UART_RXTX) & 0xff;
ch = ioread32be(port->membase + CSR_UART_RXTX) & 0xff;
port->icount.rx++;

if (uart_handle_sysrq_char(port, ch))
@@ -113,12 +109,12 @@ static irqreturn_t milkymist_uart_isr(int irq, void *data)
spin_lock(&port->lock);

/* read and ack events */
stat = ioread32be(port->membase + UART_STAT) & 0xff;
iowrite32be(stat, port->membase + UART_STAT);
stat = ioread32be(port->membase + CSR_UART_EV_PENDING);
iowrite32be(stat, port->membase + CSR_UART_EV_PENDING);

if (stat & UART_STAT_RX_EVT)
if (stat & UART_EV_RX)
milkymist_uart_rx_char(port);
if (stat & UART_STAT_TX_EVT)
if (stat & UART_EV_TX)
milkymist_uart_tx_char(port);

spin_unlock(&port->lock);
@@ -129,10 +125,10 @@ static irqreturn_t milkymist_uart_isr(int irq, void *data)
static void milkymist_uart_start_tx(struct uart_port *port)
{
u8 stat;
stat = ioread32be(port->membase + UART_STAT) & 0xff;
stat = ioread32be(port->membase + CSR_UART_EV_STAT);

/* transmission is still in progress */
if (!(stat & UART_STAT_THRE))
if (stat & UART_EV_TX)
return;

milkymist_uart_tx_char(port);
@@ -176,12 +172,10 @@ static int milkymist_uart_startup(struct uart_port *port)
ret = request_irq(port->irq, milkymist_uart_isr,
IRQF_DISABLED, "milkymist_uart", port);

/* ack events */
iowrite32be(UART_STAT_TX_EVT | UART_STAT_RX_EVT,
port->membase + UART_STAT);

iowrite32be(UART_CTRL_RX_INT | UART_CTRL_TX_INT,
port->membase + UART_CTRL);
iowrite32be(UART_EV_TX | UART_EV_RX,
port->membase + CSR_UART_EV_PENDING);
iowrite32be(UART_EV_TX | UART_EV_RX,
port->membase + CSR_UART_EV_ENABLE);

if (ret) {
pr_err("milkymist_uart: unable to attach interrupt\n");
@@ -193,7 +187,7 @@ static int milkymist_uart_startup(struct uart_port *port)

static void milkymist_uart_shutdown(struct uart_port *port)
{
iowrite32be(0, port->membase + UART_CTRL);
iowrite32be(0, port->membase + CSR_UART_EV_ENABLE);
free_irq(port->irq, port);
}

@@ -252,7 +246,8 @@ static void milkymist_uart_set_termios(struct uart_port *port,

spin_lock_irqsave(&port->lock, flags);
uart_update_timeout(port, termios->c_cflag, baud);
iowrite32be(quot, port->membase + UART_DIV);
iowrite32be((quot & 0xff00) >> 8, port->membase + CSR_UART_DIVISORH);
iowrite32be(quot & 0x00ff, port->membase + CSR_UART_DIVISORL);
spin_unlock_irqrestore(&port->lock, flags);

if (tty_termios_baud_rate(termios))
@@ -287,12 +282,11 @@ static struct uart_ops milkymist_uart_ops = {
#ifdef CONFIG_SERIAL_MILKYMIST_CONSOLE
static void milkymist_uart_console_wait_tx(struct uart_port *port)
{
int i;
u8 stat;

for (i = 0; i < 100000; i++) {
stat = ioread32be(port->membase + UART_STAT) & 0xff;
if (stat & UART_STAT_THRE)
while (true) {
stat = ioread32be(port->membase + CSR_UART_EV_STAT);
if (!(stat & UART_EV_TX))
break;
cpu_relax();
}
@@ -301,14 +295,14 @@ static void milkymist_uart_console_wait_tx(struct uart_port *port)
static void milkymist_uart_console_putchar(struct uart_port *port, int ch)
{
milkymist_uart_console_wait_tx(port);
iowrite32be(ch, port->membase + UART_RXTX);
iowrite32be(ch, port->membase + CSR_UART_RXTX);
}

static void milkymist_uart_console_write(struct console *co, const char *s,
unsigned int count)
{
struct uart_port *port = &milkymist_uart_ports[co->index];
u32 ctrl;
u32 enabled;
unsigned long flags;
int locked = 1;

@@ -320,21 +314,14 @@ static void milkymist_uart_console_write(struct console *co, const char *s,
/* wait until current transmission is finished */
milkymist_uart_console_wait_tx(port);

/* save ctrl and stat */
ctrl = ioread32be(port->membase + UART_CTRL);

/* disable irqs */
iowrite32be(ctrl & ~(UART_CTRL_RX_INT | UART_CTRL_TX_INT),
port->membase + UART_CTRL);
enabled = ioread32be(port->membase + CSR_UART_EV_ENABLE);
iowrite32be(0, port->membase + CSR_UART_EV_ENABLE);

uart_console_write(port, s, count, milkymist_uart_console_putchar);
milkymist_uart_console_wait_tx(port);
iowrite32be(UART_EV_TX, port->membase + CSR_UART_EV_PENDING);

/* ack write event */
iowrite32be(UART_STAT_TX_EVT, port->membase + UART_STAT);

/* restore control register */
iowrite32be(ctrl, port->membase + UART_CTRL);
iowrite32be(enabled, port->membase + CSR_UART_EV_ENABLE);

if (locked)
spin_unlock_irqrestore(&port->lock, flags);
@@ -520,6 +507,6 @@ static void __exit milkymist_uart_exit(void)
module_init(milkymist_uart_init);
module_exit(milkymist_uart_exit);

MODULE_AUTHOR("Milkymist Project");
MODULE_AUTHOR("RTCM");
MODULE_DESCRIPTION("Milkymist UART driver");
MODULE_LICENSE("GPL");

0 comments on commit 3faaf7a

Please sign in to comment.