Skip to content

Commit

Permalink
IT WORKS!
Browse files Browse the repository at this point in the history
buildroot login: root
login[66]: root login on 'console'
system type             : Montage LZ SoC
machine                 : HS1168-8001-02B
processor               : 0
cpu model               : MIPS 24KEc V5.5
BogoMIPS                : 395.26
wait instruction        : yes
microsecond timers      : yes
tlb_entries             : 64
extra interrupt vector  : yes
hardware watchpoint     : yes, count: 4, address/irw mask: [0x0ffc, 0x0ffc, 0x0ffb, 0x0ffb]
isa                     : mips1 mips2 mips32r1 mips32r2
ASEs implemented        : mips16 dsp
Options implemented     : tlb 4kex 4k_cache 32fpr prefetch mcheck ejtag llsc userlocal vint perf_cntr_intr_bit nan_legacy nan_2008 perf mm_full
shadow register sets    : 1
kscratch registers      : 0
package                 : 0
core                    : 0
VCED exceptions         : not available
VCEI exceptions         : not available

Linux buildroot 6.1.0-rc6-00011-gb439a09415a7-dirty torvalds#149 Sun Nov 27 22:17:41 CET 2022 mips GNU/Linux
  • Loading branch information
neuschaefer committed Nov 27, 2022
1 parent 14a3676 commit b4b79f4
Show file tree
Hide file tree
Showing 11 changed files with 214 additions and 40 deletions.
4 changes: 0 additions & 4 deletions arch/mips/boot/dts/montage/hs1168-8001-02b.dts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,6 @@
stdout-path = "serial0";
};

aliases {
serial0 = <&serial0>;
};

memory@0 {
device_type = "memory";
reg = <0 0x04000000>;
Expand Down
2 changes: 2 additions & 0 deletions arch/mips/boot/dts/montage/m88cs8001b.dtsi
Original file line number Diff line number Diff line change
Expand Up @@ -89,12 +89,14 @@
serial0: serial@1f540000 {
compatible = "montage,m88cs8001b-uart";
reg = <0x1f540000 0x1000>;
interrupts = <26>;
status = "disabled";
};

serial1: serial@1f550000 {
compatible = "montage,m88cs8001b-uart";
reg = <0x1f550000 0x1000>;
interrupts = <27>;
status = "disabled";
};
};
Expand Down
41 changes: 33 additions & 8 deletions arch/mips/montage/irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ static struct montage_intc *intc;

static void montage_intc_init_hw(void)
{
// Clear modes
for (int i = 0; i < 6; i++)
writel(0x77777777, intc->regs + MONTAGE_MODE(i));

// Mask all interrupts
writel(0xffffffff, intc->regs + MONTAGE_MASK(0));
writel(0xffffffff, intc->regs + MONTAGE_MASK(1));
Expand All @@ -46,10 +50,9 @@ static void montage_intc_irq_unmask(struct irq_data *d)
int shift = hwirq % 32;
u32 val;

pr_info("%s: hwirq=%lu\n", __func__, irqd_to_hwirq(d));
pr_info("%s: hwirq=%d\n", __func__, hwirq);

pr_info("%s: skip!\n", __func__);
return;
//pr_info("%s: skip!\n", __func__); return;

montage_intc_set_mode(hwirq, 3);

Expand All @@ -65,7 +68,7 @@ static void montage_intc_irq_mask(struct irq_data *d)
int shift = hwirq % 32;
u32 val;

pr_info("%s: hwirq=%lu\n", __func__, irqd_to_hwirq(d));
pr_info("%s: hwirq=%d\n", __func__, hwirq);

val = readl(intc->regs + MONTAGE_MASK(index));
val |= BIT(shift);
Expand All @@ -79,24 +82,44 @@ static void montage_intc_ack(void)
cpu_relax();
}

#if 0
static void montage_intc_irq_ack(struct irq_data *d)
{
pr_info("%s: hwirq=%lu\n", __func__, irqd_to_hwirq(d));

montage_intc_ack();
}
#endif

static void montage_intc_irq_eoi(struct irq_data *d)
{
//pr_info("%s: hwirq=%lu\n", __func__, irqd_to_hwirq(d));
//montage_intc_ack();
}

static int montage_intc_set_type(struct irq_data *d, unsigned int flow_type)
{
if ((flow_type & IRQ_TYPE_SENSE_MASK) != IRQ_TYPE_LEVEL_HIGH)
return -EINVAL;

return 0;
}

static struct irq_chip montage_intc_irq_chip = {
.name = "montage intc",
.irq_set_type = montage_intc_set_type,
.irq_unmask = montage_intc_irq_unmask,
.irq_mask = montage_intc_irq_mask,
.irq_ack = montage_intc_irq_ack,
// .irq_ack = montage_intc_irq_ack,
.irq_eoi = montage_intc_irq_eoi,
};

static int montage_intc_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
{
pr_info("%s %d!\n", __func__, d->hwirq);
irq_set_chip_and_handler(irq, &montage_intc_irq_chip, handle_level_irq);
pr_info("%s %u/%lu!\n", __func__, irq, hw);
irq_set_chip_and_handler(irq, &montage_intc_irq_chip, handle_fasteoi_irq);
irq_set_chip_data(irq, intc);
irq_set_probe(irq);

return 0;
}
Expand All @@ -112,10 +135,12 @@ static void montage_intc_irq_handler(struct irq_desc *desc)
u32 cause;

cause = readl(intc->regs + MONTAGE_CAUSE);
pr_info("%s: cause=%d\n", __func__, cause);
//pr_info("%s: cause=%d\n", __func__, cause);

hwirq = cause;
generic_handle_domain_irq(intc->domain, hwirq);

montage_intc_ack();
}

static int __init montage_intc_of_init(struct device_node *np,
Expand Down
1 change: 1 addition & 0 deletions drivers/of/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1918,6 +1918,7 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
&name);
if (IS_ENABLED(CONFIG_PPC) && !name)
of_property_read_string(of_aliases, "stdout", &name);
pr_info("%s: stdout path is %s\n", __func__, name);
if (name)
of_stdout = of_find_node_opts_by_path(name, &of_stdout_options);
if (of_stdout)
Expand Down
130 changes: 111 additions & 19 deletions drivers/tty/serial/montage-uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include <linux/serial_core.h>
#include <linux/tty_flip.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/platform_device.h>

#define REG_TXLVL 0x0010 /* transmit FIFO level (max. 64) */
Expand All @@ -17,14 +18,14 @@

#define NUM_PORTS 8

struct montage_port {
struct montage_uart {
struct uart_port port;
struct timer_list timer;
};

static struct montage_port *montage_uarts[NUM_PORTS];
static struct montage_uart *montage_uarts[NUM_PORTS];

#define to_montage_port(port) container_of(port, struct montage_port, port)
#define to_montage_uart(port) container_of(port, struct montage_uart, port)

#ifdef CONFIG_SERIAL_MONTAGE_CONSOLE
static struct console montage_console;
Expand Down Expand Up @@ -65,9 +66,10 @@ static int montage_rx(struct uart_port *port)
return ioread16(port->membase + REG_RX) & 0xff;
}

#if 0
static void montage_timer(struct timer_list *t)
{
struct montage_port *uart = from_timer(uart, t, timer);
struct montage_uart *uart = from_timer(uart, t, timer);
struct uart_port *port = &uart->port;
unsigned int flg = TTY_NORMAL;
int ch;
Expand All @@ -86,6 +88,7 @@ static void montage_timer(struct timer_list *t)

mod_timer(&uart->timer, jiffies + uart_poll_timeout(port));
}
#endif

static unsigned int montage_tx_empty(struct uart_port *port)
{
Expand All @@ -100,56 +103,143 @@ static const char *montage_type(struct uart_port *port)
return "montage-uart";
}

static irqreturn_t montage_irq_handler(int irq, void *priv)
{
struct uart_port *port = priv;
unsigned int flg = TTY_NORMAL;
unsigned long status;
int ch;

while (montage_can_rx(port)) {
ch = montage_rx(port);
port->icount.rx++;

if (uart_handle_sysrq_char(port, ch))
continue;

uart_insert_char(port, status, 0, ch, flg);
}
tty_flip_buffer_push(&port->state->port);

return IRQ_HANDLED;
}

static int montage_startup(struct uart_port *port)
{
pr_info("%s!\n", __func__);
return 0;
pr_info("%s: [0x08] = %08x, [0x24] = %08x\n", __func__,
readl(port->membase + 0x08), readl(port->membase + 0x24));

return request_irq(port->irq, montage_irq_handler, IRQF_TRIGGER_HIGH, "montage-uart", port);
}

static void montage_shutdown(struct uart_port *port)
{
pr_info("%s!\n", __func__);
}

static void montage_config_port(struct uart_port *port, int type)
{
pr_info("%s lol\n", __func__);
port->type = PORT_MONTAGE;
}

static void montage_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
pr_info("%s lol\n", __func__);
}

static void montage_set_termios(struct uart_port *port, struct ktermios *new,
const struct ktermios *old)
{
pr_info("%s lol\n", __func__);
}

static void montage_start_tx(struct uart_port *port)
{
struct circ_buf *xmit = &port->state->xmit;
unsigned char ch;

// TODO: deal with backpressure a little better

if (unlikely(port->x_char)) {
montage_putchar(port, port->x_char);
port->icount.tx++;
port->x_char = 0;
} else if (!uart_circ_empty(xmit)) {
while (xmit->head != xmit->tail) {
ch = xmit->buf[xmit->tail];
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
montage_putchar(port, ch);
}
}

if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(port);
}

static void montage_stop_tx(struct uart_port *port)
{
pr_info("%s lol\n", __func__);
}

static const struct uart_ops montage_ops = {
.tx_empty = montage_tx_empty,
.startup = montage_startup,
.shutdown = montage_shutdown,
.type = montage_type,
.config_port = montage_config_port,
.set_mctrl = montage_set_mctrl,
.set_termios = montage_set_termios,
.start_tx = montage_start_tx,
.stop_tx = montage_stop_tx,
};

static int montage_probe(struct platform_device *pdev)
{
struct montage_port *uart;
struct montage_uart *uart;
struct uart_port *port;
struct resource *res_mem;
int dev_id;
int irq;

dev_id = of_alias_get_id(pdev->dev.of_node, "serial");
pr_info("montage_probe: dev_id=%d\n", dev_id);

uart = devm_kzalloc(&pdev->dev, sizeof(struct montage_port), GFP_KERNEL);
uart = devm_kzalloc(&pdev->dev, sizeof(struct montage_uart), GFP_KERNEL);
if (!uart)
return -ENOMEM;

port = &uart->port;

port->membase = devm_platform_get_and_ioremap_resource(pdev, 0, NULL);
if (IS_ERR(port->membase))
return PTR_ERR(port->membase);

res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res_mem)
return -ENODEV;

irq = of_irq_get(pdev->dev.of_node, 0);
if (irq < 0)
return irq;

port->irq = irq;
port->dev = &pdev->dev;
port->iotype = UPIO_MEM;
port->mapbase = res_mem->start;
port->mapsize = resource_size(res_mem);
port->membase = devm_ioremap(&pdev->dev, port->mapbase, port->mapsize);
port->flags = UPF_BOOT_AUTOCONF;
port->ops = &montage_ops;
port->regshift = 2;
port->fifosize = 16;
port->iobase = 1;
port->type = PORT_UNKNOWN;
port->line = dev_id;
port->fifosize = TXLVL_MAX;
spin_lock_init(&port->lock);

platform_set_drvdata(pdev, port);

montage_uarts[dev_id] = uart;
pr_info("%s: montage_driver=%px, port=%px\n", __func__, &montage_driver, &uart->port);
return uart_add_one_port(&montage_driver, &uart->port);
}

Expand Down Expand Up @@ -180,41 +270,43 @@ static struct platform_driver montage_platform_driver = {
static void montage_console_write(struct console *co, const char *s,
unsigned int count)
{
struct montage_port *uart = montage_uarts[co->index];
struct uart_port *port;
struct montage_uart *uart = montage_uarts[co->index];
struct uart_port *port = &uart->port;
unsigned long flags;

port = &uart->port;

spin_lock_irqsave(&port->lock, flags);
uart_console_write(port, s, count, montage_putchar);
spin_unlock_irqrestore(&port->lock, flags);
}

static int montage_console_setup(struct console *co, char *options)
{
struct montage_port *uart = montage_uarts[co->index];
struct uart_port *port;
struct montage_uart *uart = montage_uarts[co->index];
struct uart_port *port = &uart->port;
int baud = 115200;
int bits = 8;
int parity = 'n';
int flow = 'n';

pr_info("%s: entry, idx=%u, uart = %px\n", __func__, co->index, uart);
if (!uart)
return -ENODEV;

port = &uart->port;
if (!port->membase)
return -ENODEV;

pr_info("%s: [0x08] = %08x, [0x24] = %08x\n", __func__,
readl(port->membase + 0x08), readl(port->membase + 0x24));

if (options)
uart_parse_options(options, &baud, &parity, &bits, &flow);

return uart_set_options(port, co, baud, parity, bits, flow);
}

static struct console montage_console = {
.name = "montage",
.name = "ttyS",
.write = montage_console_write,
.device = uart_console_device,
.setup = montage_console_setup,
Expand Down
Loading

0 comments on commit b4b79f4

Please sign in to comment.