-
Notifications
You must be signed in to change notification settings - Fork 101
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
valentyusb: Add software for liteuart console
usb_hello is a copy of hello_world but uses both consoles Signed-off-by: Matt Johnston <[email protected]>
- Loading branch information
Showing
6 changed files
with
475 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
#pragma once | ||
|
||
int usb_getchar(void); | ||
bool usb_havechar(void); | ||
int usb_putchar(int c); | ||
int usb_puts(const char *str); | ||
void usb_console_init(void); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,239 @@ | ||
#include <stdint.h> | ||
#include <stdbool.h> | ||
|
||
#include "console.h" | ||
#include "liteuart_console.h" | ||
#include "microwatt_soc.h" | ||
#include "io.h" | ||
|
||
#define UART_BAUDS 115200 | ||
|
||
static uint64_t uart_base; | ||
|
||
/* From Linux liteuart.c */ | ||
#define OFF_RXTX 0x00 | ||
#define OFF_TXFULL 0x04 | ||
#define OFF_RXEMPTY 0x08 | ||
#define OFF_EV_STATUS 0x0c | ||
#define OFF_EV_PENDING 0x10 | ||
#define OFF_EV_ENABLE 0x14 | ||
|
||
/* From litex uart.h */ | ||
#define UART_EV_TX 0x1 | ||
#define UART_EV_RX 0x2 | ||
|
||
/* Modified version of csr.h */ | ||
/* uart */ | ||
static inline uint32_t uart_rxtx_read(void) { | ||
return readl(uart_base + OFF_RXTX); | ||
} | ||
|
||
static inline void uart_rxtx_write(uint32_t v) { | ||
writel(v, uart_base + OFF_RXTX); | ||
} | ||
|
||
static inline uint32_t uart_txfull_read(void) { | ||
return readl(uart_base + OFF_TXFULL); | ||
} | ||
|
||
static inline uint32_t uart_rxempty_read(void) { | ||
return readl(uart_base + OFF_RXEMPTY); | ||
} | ||
|
||
static inline uint32_t uart_ev_status_read(void) { | ||
return readl(uart_base + OFF_EV_STATUS); | ||
} | ||
|
||
// static inline uint32_t uart_ev_status_tx_extract(uint32_t oldword) { | ||
// uint32_t mask = ((1 << 1)-1); | ||
// return ( (oldword >> 0) & mask ); | ||
// } | ||
// static inline uint32_t uart_ev_status_tx_read(void) { | ||
// uint32_t word = uart_ev_status_read(); | ||
// return uart_ev_status_tx_extract(word); | ||
// } | ||
|
||
// static inline uint32_t uart_ev_status_rx_extract(uint32_t oldword) { | ||
// uint32_t mask = ((1 << 1)-1); | ||
// return ( (oldword >> 1) & mask ); | ||
// } | ||
// static inline uint32_t uart_ev_status_rx_read(void) { | ||
// uint32_t word = uart_ev_status_read(); | ||
// return uart_ev_status_rx_extract(word); | ||
// } | ||
|
||
static inline uint32_t uart_ev_pending_read(void) { | ||
return readl(uart_base + OFF_EV_PENDING); | ||
} | ||
static inline void uart_ev_pending_write(uint32_t v) { | ||
writel(v, uart_base + OFF_EV_PENDING); | ||
} | ||
|
||
// static inline uint32_t uart_ev_pending_tx_extract(uint32_t oldword) { | ||
// uint32_t mask = ((1 << 1)-1); | ||
// return ( (oldword >> 0) & mask ); | ||
// } | ||
// static inline uint32_t uart_ev_pending_tx_read(void) { | ||
// uint32_t word = uart_ev_pending_read(); | ||
// return uart_ev_pending_tx_extract(word); | ||
// } | ||
// static inline uint32_t uart_ev_pending_tx_replace(uint32_t oldword, uint32_t plain_value) { | ||
// uint32_t mask = ((1 << 1)-1); | ||
// return (oldword & (~(mask << 0))) | (mask & plain_value)<< 0 ; | ||
// } | ||
// static inline void uart_ev_pending_tx_write(uint32_t plain_value) { | ||
// uint32_t oldword = uart_ev_pending_read(); | ||
// uint32_t newword = uart_ev_pending_tx_replace(oldword, plain_value); | ||
// uart_ev_pending_write(newword); | ||
// } | ||
// #define CSR_UART_EV_PENDING_RX_OFFSET 1 | ||
// #define CSR_UART_EV_PENDING_RX_SIZE 1 | ||
// static inline uint32_t uart_ev_pending_rx_extract(uint32_t oldword) { | ||
// uint32_t mask = ((1 << 1)-1); | ||
// return ( (oldword >> 1) & mask ); | ||
// } | ||
// static inline uint32_t uart_ev_pending_rx_read(void) { | ||
// uint32_t word = uart_ev_pending_read(); | ||
// return uart_ev_pending_rx_extract(word); | ||
// } | ||
// static inline uint32_t uart_ev_pending_rx_replace(uint32_t oldword, uint32_t plain_value) { | ||
// uint32_t mask = ((1 << 1)-1); | ||
// return (oldword & (~(mask << 1))) | (mask & plain_value)<< 1 ; | ||
// } | ||
// static inline void uart_ev_pending_rx_write(uint32_t plain_value) { | ||
// uint32_t oldword = uart_ev_pending_read(); | ||
// uint32_t newword = uart_ev_pending_rx_replace(oldword, plain_value); | ||
// uart_ev_pending_write(newword); | ||
// } | ||
// #define CSR_UART_EV_ENABLE_ADDR (CSR_BASE + 0x814L) | ||
// #define CSR_UART_EV_ENABLE_SIZE 1 | ||
// static inline uint32_t uart_ev_enable_read(void) { | ||
// return csr_read_simple(CSR_BASE + 0x814L); | ||
// } | ||
static inline void uart_ev_enable_write(uint32_t v) { | ||
writel(v, uart_base + OFF_EV_ENABLE); | ||
} | ||
// #define CSR_UART_EV_ENABLE_TX_OFFSET 0 | ||
// #define CSR_UART_EV_ENABLE_TX_SIZE 1 | ||
// static inline uint32_t uart_ev_enable_tx_extract(uint32_t oldword) { | ||
// uint32_t mask = ((1 << 1)-1); | ||
// return ( (oldword >> 0) & mask ); | ||
// } | ||
// static inline uint32_t uart_ev_enable_tx_read(void) { | ||
// uint32_t word = uart_ev_enable_read(); | ||
// return uart_ev_enable_tx_extract(word); | ||
// } | ||
// static inline uint32_t uart_ev_enable_tx_replace(uint32_t oldword, uint32_t plain_value) { | ||
// uint32_t mask = ((1 << 1)-1); | ||
// return (oldword & (~(mask << 0))) | (mask & plain_value)<< 0 ; | ||
// } | ||
// static inline void uart_ev_enable_tx_write(uint32_t plain_value) { | ||
// uint32_t oldword = uart_ev_enable_read(); | ||
// uint32_t newword = uart_ev_enable_tx_replace(oldword, plain_value); | ||
// uart_ev_enable_write(newword); | ||
// } | ||
// #define CSR_UART_EV_ENABLE_RX_OFFSET 1 | ||
// #define CSR_UART_EV_ENABLE_RX_SIZE 1 | ||
// static inline uint32_t uart_ev_enable_rx_extract(uint32_t oldword) { | ||
// uint32_t mask = ((1 << 1)-1); | ||
// return ( (oldword >> 1) & mask ); | ||
// } | ||
// static inline uint32_t uart_ev_enable_rx_read(void) { | ||
// uint32_t word = uart_ev_enable_read(); | ||
// return uart_ev_enable_rx_extract(word); | ||
// } | ||
// static inline uint32_t uart_ev_enable_rx_replace(uint32_t oldword, uint32_t plain_value) { | ||
// uint32_t mask = ((1 << 1)-1); | ||
// return (oldword & (~(mask << 1))) | (mask & plain_value)<< 1 ; | ||
// } | ||
// static inline void uart_ev_enable_rx_write(uint32_t plain_value) { | ||
// uint32_t oldword = uart_ev_enable_read(); | ||
// uint32_t newword = uart_ev_enable_rx_replace(oldword, plain_value); | ||
// uart_ev_enable_write(newword); | ||
// } | ||
// #define CSR_UART_TUNING_WORD_ADDR (CSR_BASE + 0x818L) | ||
// #define CSR_UART_TUNING_WORD_SIZE 1 | ||
// static inline uint32_t uart_tuning_word_read(void) { | ||
// return csr_read_simple(CSR_BASE + 0x818L); | ||
// } | ||
// static inline void uart_tuning_word_write(uint32_t v) { | ||
// csr_write_simple(v, CSR_BASE + 0x818L); | ||
// } | ||
// #define CSR_UART_CONFIGURED_ADDR (CSR_BASE + 0x81cL) | ||
// #define CSR_UART_CONFIGURED_SIZE 1 | ||
// static inline uint32_t uart_configured_read(void) { | ||
// return csr_read_simple(CSR_BASE + 0x81cL); | ||
// } | ||
// static inline void uart_configured_write(uint32_t v) { | ||
// csr_write_simple(v, CSR_BASE + 0x81cL); | ||
// } | ||
|
||
// end of csr code | ||
|
||
static char uart_read(void) | ||
{ | ||
char c; | ||
while (uart_rxempty_read()); | ||
c = uart_rxtx_read(); | ||
uart_ev_pending_write(UART_EV_RX); | ||
return c; | ||
} | ||
|
||
static int uart_read_nonblock(void) | ||
{ | ||
return (uart_rxempty_read() == 0); | ||
} | ||
|
||
static void uart_write(char c) | ||
{ | ||
while (uart_txfull_read()); | ||
uart_rxtx_write(c); | ||
uart_ev_pending_write(UART_EV_TX); | ||
} | ||
|
||
static void uart_init(void) | ||
{ | ||
uart_ev_pending_write(uart_ev_pending_read()); | ||
uart_ev_enable_write(UART_EV_TX | UART_EV_RX); | ||
} | ||
|
||
// static void uart_sync(void) | ||
// { | ||
// while (uart_txfull_read()); | ||
// } | ||
|
||
int usb_getchar(void) | ||
{ | ||
return uart_read(); | ||
} | ||
|
||
bool usb_havechar(void) | ||
{ | ||
return uart_read_nonblock(); | ||
} | ||
|
||
int usb_putchar(int c) | ||
{ | ||
uart_write(c); | ||
return c; | ||
} | ||
|
||
int usb_puts(const char *str) | ||
{ | ||
unsigned int i; | ||
|
||
for (i = 0; *str; i++) { | ||
char c = *(str++); | ||
if (c == 10) | ||
usb_putchar(13); | ||
usb_putchar(c); | ||
} | ||
return 0; | ||
} | ||
|
||
void usb_console_init(void) | ||
{ | ||
uart_base = UARTUSB_BASE; | ||
uart_init(); | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
ARCH = $(shell uname -m) | ||
ifneq ("$(ARCH)", "ppc64") | ||
ifneq ("$(ARCH)", "ppc64le") | ||
CROSS_COMPILE ?= powerpc64le-linux-gnu- | ||
endif | ||
endif | ||
|
||
CC = $(CROSS_COMPILE)gcc | ||
LD = $(CROSS_COMPILE)ld | ||
OBJCOPY = $(CROSS_COMPILE)objcopy | ||
|
||
CFLAGS = -Os -g -Wall -std=c99 -msoft-float -mno-string -mno-multiple -mno-vsx -mno-altivec -mlittle-endian -fno-stack-protector -mstrict-align -ffreestanding -fdata-sections -ffunction-sections -I../include | ||
CFLAGS += -Werror -Wextra | ||
ASFLAGS = $(CFLAGS) | ||
LDFLAGS = -T powerpc.lds | ||
|
||
all: usb_hello.hex | ||
|
||
console.o: ../lib/console.c | ||
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ | ||
|
||
liteuart_console.o: ../lib/liteuart_console.c | ||
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@ | ||
|
||
usb_hello.elf: usb_hello.o head.o console.o liteuart_console.o | ||
$(LD) $(LDFLAGS) -o $@ $^ | ||
|
||
usb_hello.bin: usb_hello.elf | ||
$(OBJCOPY) -O binary $^ $@ | ||
|
||
usb_hello.hex: usb_hello.bin | ||
../scripts/bin2hex.py $^ > $@ | ||
|
||
clean: | ||
@rm -f *.o usb_hello.elf usb_hello.bin usb_hello.hex | ||
distclean: clean | ||
rm -f *~ | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
/* Copyright 2013-2014 IBM Corp. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | ||
* implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#define STACK_TOP 0x2000 | ||
|
||
#define FIXUP_ENDIAN \ | ||
tdi 0,0,0x48; /* Reverse endian of b . + 8 */ \ | ||
b 191f; /* Skip trampoline if endian is good */ \ | ||
.long 0xa600607d; /* mfmsr r11 */ \ | ||
.long 0x01006b69; /* xori r11,r11,1 */ \ | ||
.long 0x05009f42; /* bcl 20,31,$+4 */ \ | ||
.long 0xa602487d; /* mflr r10 */ \ | ||
.long 0x14004a39; /* addi r10,r10,20 */ \ | ||
.long 0xa64b5a7d; /* mthsrr0 r10 */ \ | ||
.long 0xa64b7b7d; /* mthsrr1 r11 */ \ | ||
.long 0x2402004c; /* hrfid */ \ | ||
191: | ||
|
||
|
||
/* Load an immediate 64-bit value into a register */ | ||
#define LOAD_IMM64(r, e) \ | ||
lis r,(e)@highest; \ | ||
ori r,r,(e)@higher; \ | ||
rldicr r,r, 32, 31; \ | ||
oris r,r, (e)@h; \ | ||
ori r,r, (e)@l; | ||
|
||
.section ".head","ax" | ||
|
||
/* | ||
* Microwatt currently enters in LE mode at 0x0, so we don't need to | ||
* do any endian fix ups> | ||
*/ | ||
. = 0 | ||
.global _start | ||
_start: | ||
b boot_entry | ||
|
||
/* QEMU enters at 0x10 */ | ||
. = 0x10 | ||
FIXUP_ENDIAN | ||
b boot_entry | ||
|
||
. = 0x100 | ||
FIXUP_ENDIAN | ||
b boot_entry | ||
|
||
.global boot_entry | ||
boot_entry: | ||
/* setup stack */ | ||
LOAD_IMM64(%r1, STACK_TOP - 0x100) | ||
LOAD_IMM64(%r12, main) | ||
mtctr %r12, | ||
bctrl | ||
b . | ||
|
||
#define EXCEPTION(nr) \ | ||
.= nr ;\ | ||
b . | ||
|
||
/* More exception stubs */ | ||
EXCEPTION(0x300) | ||
EXCEPTION(0x380) | ||
EXCEPTION(0x400) | ||
EXCEPTION(0x480) | ||
EXCEPTION(0x500) | ||
EXCEPTION(0x600) | ||
EXCEPTION(0x700) | ||
EXCEPTION(0x800) | ||
EXCEPTION(0x900) | ||
EXCEPTION(0x980) | ||
EXCEPTION(0xa00) | ||
EXCEPTION(0xb00) | ||
EXCEPTION(0xc00) | ||
EXCEPTION(0xd00) | ||
EXCEPTION(0xe00) | ||
EXCEPTION(0xe20) | ||
EXCEPTION(0xe40) | ||
EXCEPTION(0xe60) | ||
EXCEPTION(0xe80) | ||
EXCEPTION(0xf00) | ||
EXCEPTION(0xf20) | ||
EXCEPTION(0xf40) | ||
EXCEPTION(0xf60) | ||
EXCEPTION(0xf80) | ||
#if 0 | ||
EXCEPTION(0x1000) | ||
EXCEPTION(0x1100) | ||
EXCEPTION(0x1200) | ||
EXCEPTION(0x1300) | ||
EXCEPTION(0x1400) | ||
EXCEPTION(0x1500) | ||
EXCEPTION(0x1600) | ||
#endif |
Oops, something went wrong.