This patch set introduces preliminary support for Cavium Networks'
OCTEON processor family. More information about these processors may
be obtained here:
http://www.caviumnetworks.com/OCTEON_MIPS64.html
This initial patch set adds support for booting an initramfs to a
serial console. Follow-on patch sets will add support for the on-chip
ethernet, USB, PCI, PCIe, I2c and other peripherals.
With this second version of the patches I think we have fixed or
removed the parts flagged as objectionable in the first round of
reviews. In addition to more general cleanups I fixed the following
issues:
* externs declared in mm/fault.c moved to fpu_emulator.h
* Corrected spelling of hazard in patch commentary.
* Useless checking in pmd_none removed.
* ebase calculation generalized.
* ST0_KX setting for 32bit kernel removed (there is now no 32bit
kernel support)
Without further ado, I will reply with the following 36 patches (5 of
which will also go to linux-serial):
01 - Add Cavium OCTEON processor support files to arch/mips/cavium-octeon.
02 - Add Cavium OCTEON files to arch/mips/include/asm/mach-cavium-octeon
03 - Add Cavium OCTEON processor support files to arch/mips/kernel.
04 - Add Cavium OCTEON processor support files to arch/mips/mm.
05 - Add Cavium OCTEON processor support files to and
arch/mips/cavium-octeon/executive
06 - Add Cavium OCTEON processor CSR definitions
07 - Don't assume boot CPU is CPU0 if MIPS_DISABLE_BOOT_CPU_ZERO set.
08 - For Cavium OCTEON handle hazards as per the R10000 handling.
09 - Enable mips32 style bitops for Cavium OCTEON.
10 - Cavium OCTEON: Set hwrena and lazily restore CP2 state.
11 - MIPSR2 ebase isn't just CAC_BASE
12 - Add Cavium OCTEON to arch/mips/Kconfig
13 - Add Cavium OCTEON processor constants.
14 - Rewrite cpu_to_name so it has one statement per line.
15 - Probe for Cavium OCTEON CPUs.
16 - MIPS: Hook Cavium OCTEON cache init into cache.c
17 - cavium: Hook Cavium specifics into main arch/mips dir
18 - Cavium OCTEON modify core io.h macros to account for the Octeon
Errata Core-301.
19 - Cavium OCTEON: increase MAX_DMA address.
20 - Cavium OCTEON: add in icache and dcache error functions.
21 - Cavium OCTEON: Add cop2/cvmseg state entries to processor.h.
22 - Add Cavium OCTEON specific registers to ptrace.h and asm-offsets.c
23 - Add SMP_ICACHE_FLUSH for the Cavium CPU family.
24 - Cavium OCTEON: PT vs MFC0 reorder, multiplier state preservation.
25 - Add Cavium OCTEON irq hazard in asmmacro.h.
26 - Compute branch returns for Cavium OCTEON specific branch
instructions.
27 - Add Cavium OCTEON slot into proper tlb category.
28 - MIPS: move FPU emulator externs to fpu_emulator.h
29 - Cavium OCTEON FPU EMU exception as TLB exception
These five to linux-serial, linux-kernel, and akpm as well:
30 - Don't clobber spinlocks in 8250.
31 - Generic 8250 serial driver changes to support future OCTEON serial
patches.
32 - Allow port type to be specified when calling
serial8250_register_port.
33 - Allow port type to specify bugs that are not probed for.
34 - 8250 serial driver changes for Cavium OCTEON.
35 - Adjust the dma-common.c platform hooks.
36 - Add defconfig for Cavium OCTEON.
arch/mips/Kconfig | 74 +-
arch/mips/Makefile | 13 +
arch/mips/cavium-octeon/Kconfig | 85 +
arch/mips/cavium-octeon/Makefile | 21 +
arch/mips/cavium-octeon/console.c | 34 +
arch/mips/cavium-octeon/dma-octeon.c | 324 +
arch/mips/cavium-octeon/executive/Makefile | 26 +
arch/mips/cavium-octeon/executive/cvmx-asm.h | 427 +
arch/mips/cavium-octeon/executive/cvmx-bootinfo.h | 238 +
arch/mips/cavium-octeon/executive/cvmx-bootmem.c | 897 +
arch/mips/cavium-octeon/executive/cvmx-bootmem.h | 403 +
.../cavium-octeon/executive/cvmx-csr-addresses.h | 8391 ++++++
arch/mips/cavium-octeon/executive/cvmx-csr-enums.h | 86 +
.../cavium-octeon/executive/cvmx-csr-typedefs.h |27517 ++++++++++++++++++++
arch/mips/cavium-octeon/executive/cvmx-csr.h | 199 +
arch/mips/cavium-octeon/executive/cvmx-interrupt.h | 255 +
arch/mips/cavium-octeon/executive/cvmx-l2c.c | 711 +
arch/mips/cavium-octeon/executive/cvmx-l2c.h | 328 +
.../executive/cvmx-linux-kernel-exports.c | 30 +
arch/mips/cavium-octeon/executive/cvmx-packet.h | 64 +
arch/mips/cavium-octeon/executive/cvmx-platform.h | 56 +
arch/mips/cavium-octeon/executive/cvmx-spinlock.h | 376 +
arch/mips/cavium-octeon/executive/cvmx-sysinfo.c | 113 +
arch/mips/cavium-octeon/executive/cvmx-sysinfo.h | 144 +
arch/mips/cavium-octeon/executive/cvmx-warn.c | 44 +
arch/mips/cavium-octeon/executive/cvmx-warn.h | 46 +
arch/mips/cavium-octeon/executive/cvmx.h | 772 +
arch/mips/cavium-octeon/executive/octeon-feature.h | 120 +
arch/mips/cavium-octeon/executive/octeon-model.c | 328 +
arch/mips/cavium-octeon/executive/octeon-model.h | 225 +
arch/mips/cavium-octeon/flash_setup.c | 76 +
arch/mips/cavium-octeon/hal.c | 496 +
arch/mips/cavium-octeon/hal.h | 190 +
arch/mips/cavium-octeon/i8259.c | 180 +
arch/mips/cavium-octeon/irq.c | 61 +
arch/mips/cavium-octeon/octeon-memcpy.S | 521 +
arch/mips/cavium-octeon/serial.c | 187 +
arch/mips/cavium-octeon/setup.c | 387 +
arch/mips/cavium-octeon/smp.c | 231 +
arch/mips/cavium-octeon/userio.c | 156 +
arch/mips/configs/cavium-octeon_defconfig | 1160 +
arch/mips/include/asm/asmmacro.h | 10 +
arch/mips/include/asm/bitops.h | 3 +-
arch/mips/include/asm/cpu-features.h | 7 +
arch/mips/include/asm/cpu.h | 14 +
arch/mips/include/asm/dma.h | 7 +
arch/mips/include/asm/fpu_emulator.h | 5 +
arch/mips/include/asm/hazards.h | 4 +-
arch/mips/include/asm/io.h | 14 +
.../asm/mach-cavium-octeon/cpu-feature-overrides.h | 63 +
.../include/asm/mach-cavium-octeon/dma-coherence.h | 64 +
arch/mips/include/asm/mach-cavium-octeon/irq.h | 253 +
.../asm/mach-cavium-octeon/kernel-entry-init.h | 140 +
.../asm/mach-cavium-octeon/octeon-hal-read-write.h | 38 +
arch/mips/include/asm/mach-cavium-octeon/war.h | 26 +
arch/mips/include/asm/mach-generic/dma-coherence.h | 26 +-
arch/mips/include/asm/mach-ip27/dma-coherence.h | 26 +-
arch/mips/include/asm/mach-ip32/dma-coherence.h | 26 +-
arch/mips/include/asm/mach-jazz/dma-coherence.h | 26 +-
arch/mips/include/asm/mach-lemote/dma-coherence.h | 26 +-
arch/mips/include/asm/mipsregs.h | 5 +
arch/mips/include/asm/module.h | 2 +
arch/mips/include/asm/processor.h | 69 +
arch/mips/include/asm/ptrace.h | 4 +
arch/mips/include/asm/smp.h | 3 +
arch/mips/include/asm/stackframe.h | 46 +
arch/mips/kernel/Makefile | 9 +
arch/mips/kernel/asm-offsets.c | 31 +
arch/mips/kernel/branch.c | 33 +
arch/mips/kernel/cpu-probe.c | 182 +-
arch/mips/kernel/irq-octeon.c | 464 +
arch/mips/kernel/octeon_switch.S | 506 +
arch/mips/kernel/smp.c | 2 +
arch/mips/kernel/traps.c | 34 +-
arch/mips/kernel/unaligned.c | 2 +-
arch/mips/lib/Makefile | 1 +
arch/mips/math-emu/dsemul.h | 1 -
arch/mips/mm/Makefile | 5 +
arch/mips/mm/c-octeon.c | 309 +
arch/mips/mm/cache.c | 6 +
arch/mips/mm/cex-oct.S | 70 +
arch/mips/mm/dma-default.c | 24 +-
arch/mips/mm/fault.c | 16 +
arch/mips/mm/tlbex.c | 1 +
drivers/serial/8250.c | 233 +-
drivers/serial/8250.h | 3 +
drivers/serial/serial_core.c | 7 +-
include/linux/serial_8250.h | 2 +
include/linux/serial_core.h | 7 +-
include/linux/serial_reg.h | 6 +
90 files changed, 48682 insertions(+), 171 deletions(-)
create mode 100644 arch/mips/cavium-octeon/Kconfig
create mode 100644 arch/mips/cavium-octeon/Makefile
create mode 100644 arch/mips/cavium-octeon/console.c
create mode 100644 arch/mips/cavium-octeon/dma-octeon.c
create mode 100644 arch/mips/cavium-octeon/executive/Makefile
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-asm.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-bootinfo.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-bootmem.c
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-bootmem.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-csr-addresses.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-csr-enums.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-csr-typedefs.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-csr.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-interrupt.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-l2c.c
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-l2c.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-linux-kernel-exports.c
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-packet.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-platform.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-spinlock.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-sysinfo.c
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-sysinfo.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-warn.c
create mode 100644 arch/mips/cavium-octeon/executive/cvmx-warn.h
create mode 100644 arch/mips/cavium-octeon/executive/cvmx.h
create mode 100644 arch/mips/cavium-octeon/executive/octeon-feature.h
create mode 100644 arch/mips/cavium-octeon/executive/octeon-model.c
create mode 100644 arch/mips/cavium-octeon/executive/octeon-model.h
create mode 100644 arch/mips/cavium-octeon/flash_setup.c
create mode 100644 arch/mips/cavium-octeon/hal.c
create mode 100644 arch/mips/cavium-octeon/hal.h
create mode 100644 arch/mips/cavium-octeon/i8259.c
create mode 100644 arch/mips/cavium-octeon/irq.c
create mode 100644 arch/mips/cavium-octeon/octeon-memcpy.S
create mode 100644 arch/mips/cavium-octeon/serial.c
create mode 100644 arch/mips/cavium-octeon/setup.c
create mode 100644 arch/mips/cavium-octeon/smp.c
create mode 100644 arch/mips/cavium-octeon/userio.c
create mode 100644 arch/mips/configs/cavium-octeon_defconfig
create mode 100644 arch/mips/include/asm/mach-cavium-octeon/cpu-feature-overrides.h
create mode 100644 arch/mips/include/asm/mach-cavium-octeon/dma-coherence.h
create mode 100644 arch/mips/include/asm/mach-cavium-octeon/irq.h
create mode 100644 arch/mips/include/asm/mach-cavium-octeon/kernel-entry-init.h
create mode 100644 arch/mips/include/asm/mach-cavium-octeon/octeon-hal-read-write.h
create mode 100644 arch/mips/include/asm/mach-cavium-octeon/war.h
create mode 100644 arch/mips/kernel/irq-octeon.c
create mode 100644 arch/mips/kernel/octeon_switch.S
create mode 100644 arch/mips/mm/c-octeon.c
create mode 100644 arch/mips/mm/cex-oct.S
Add a bugs field to the serial8250_config and propagate it to the
port's bugs field when the port is registered and configured.
Signed-off-by: David Daney <[email protected]>
---
drivers/serial/8250.c | 2 ++
drivers/serial/8250.h | 1 +
2 files changed, 3 insertions(+), 0 deletions(-)
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 9d16abb..474ab89 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -1212,6 +1212,7 @@ static void autoconfig(struct uart_8250_port *up, unsigned int probeflags)
up->port.fifosize = uart_config[up->port.type].fifo_size;
up->capabilities = uart_config[up->port.type].flags;
up->tx_loadsz = uart_config[up->port.type].tx_loadsz;
+ up->bugs |= uart_config[up->port.type].bugs;
if (up->port.type == PORT_UNKNOWN)
goto out;
@@ -3062,6 +3063,7 @@ int serial8250_register_port(struct uart_port *port)
uart->port.fifosize = uart_config[port->type].fifo_size;
uart->capabilities = uart_config[port->type].flags;
uart->tx_loadsz = uart_config[port->type].tx_loadsz;
+ uart->bugs = uart_config[port->type].bugs;
}
set_io_fns_from_upio(&uart->port);
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
index 5202603..c9b3002 100644
--- a/drivers/serial/8250.h
+++ b/drivers/serial/8250.h
@@ -34,6 +34,7 @@ struct serial8250_config {
const char *name;
unsigned short fifo_size;
unsigned short tx_loadsz;
+ unsigned short bugs;
unsigned char fcr;
unsigned int flags;
};
--
1.5.6.5
In serial8250_isa_init_ports(), the port's lock is initialized. We
should not overwrite it. Only copy in the fields we need.
Signed-off-by: David Daney <[email protected]>
Signed-off-by: Tomaso Paoletti <[email protected]>
---
drivers/serial/8250.c | 15 +++++++++++++--
1 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 303272a..8e28750 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -2752,12 +2752,23 @@ static struct uart_driver serial8250_reg = {
*/
int __init early_serial_setup(struct uart_port *port)
{
+ struct uart_port *p;
+
if (port->line >= ARRAY_SIZE(serial8250_ports))
return -ENODEV;
serial8250_isa_init_ports();
- serial8250_ports[port->line].port = *port;
- serial8250_ports[port->line].port.ops = &serial8250_pops;
+ p = &serial8250_ports[port->line].port;
+ p->iobase = port->iobase;
+ p->membase = port->membase;
+ p->irq = port->irq;
+ p->uartclk = port->uartclk;
+ p->fifosize = port->fifosize;
+ p->regshift = port->regshift;
+ p->iotype = port->iotype;
+ p->flags = port->flags;
+ p->mapbase = port->mapbase;
+ p->private_data = port->private_data;
return 0;
}
--
1.5.6.5
In order to use Cavium OCTEON specific serial i/o drivers, we first patch
the 8250 driver to use replaceable i/o functions.
Signed-off-by: David Daney <[email protected]>
Signed-off-by: Tomaso Paoletti <[email protected]>
---
drivers/serial/8250.c | 192 ++++++++++++++++++++++++++++++-------------
include/linux/serial_8250.h | 2 +
include/linux/serial_core.h | 2 +
3 files changed, 138 insertions(+), 58 deletions(-)
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 8e28750..410478f 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -303,16 +303,16 @@ static const u8 au_io_out_map[] = {
};
/* sane hardware needs no mapping */
-static inline int map_8250_in_reg(struct uart_8250_port *up, int offset)
+static inline int map_8250_in_reg(struct uart_port *p, int offset)
{
- if (up->port.iotype != UPIO_AU)
+ if (p->iotype != UPIO_AU)
return offset;
return au_io_in_map[offset];
}
-static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
+static inline int map_8250_out_reg(struct uart_port *p, int offset)
{
- if (up->port.iotype != UPIO_AU)
+ if (p->iotype != UPIO_AU)
return offset;
return au_io_out_map[offset];
}
@@ -341,16 +341,16 @@ static const u8
[UART_SCR] = 0x2c
};
-static inline int map_8250_in_reg(struct uart_8250_port *up, int offset)
+static inline int map_8250_in_reg(struct uart_port *p, int offset)
{
- if (up->port.iotype != UPIO_RM9000)
+ if (p->iotype != UPIO_RM9000)
return offset;
return regmap_in[offset];
}
-static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
+static inline int map_8250_out_reg(struct uart_port *p, int offset)
{
- if (up->port.iotype != UPIO_RM9000)
+ if (p->iotype != UPIO_RM9000)
return offset;
return regmap_out[offset];
}
@@ -363,108 +363,170 @@ static inline int map_8250_out_reg(struct uart_8250_port *up, int offset)
#endif
-static unsigned int serial_in(struct uart_8250_port *up, int offset)
+static unsigned int hub6_serial_in_fn(struct uart_port *p, int offset)
{
- unsigned int tmp;
- offset = map_8250_in_reg(up, offset) << up->port.regshift;
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ outb(p->hub6 - 1 + offset, p->iobase);
+ return inb(p->iobase + 1);
+}
- switch (up->port.iotype) {
- case UPIO_HUB6:
- outb(up->port.hub6 - 1 + offset, up->port.iobase);
- return inb(up->port.iobase + 1);
+static void hub6_serial_out_fn(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ outb(p->hub6 - 1 + offset, p->iobase);
+ outb(value, p->iobase + 1);
+}
- case UPIO_MEM:
- case UPIO_DWAPB:
- return readb(up->port.membase + offset);
+static unsigned int mem_serial_in_fn(struct uart_port *p, int offset)
+{
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ return readb(p->membase + offset);
+}
- case UPIO_RM9000:
- case UPIO_MEM32:
- return readl(up->port.membase + offset);
+static void mem_serial_out_fn(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ writeb(value, p->membase + offset);
+}
+
+static void mem32_serial_out_fn(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ writel(value, p->membase + offset);
+}
+
+static unsigned int mem32_serial_in_fn(struct uart_port *p, int offset)
+{
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ return readl(p->membase + offset);
+}
#ifdef CONFIG_SERIAL_8250_AU1X00
- case UPIO_AU:
- return __raw_readl(up->port.membase + offset);
+static unsigned int au_serial_in_fn(struct uart_port *p, int offset)
+{
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ return __raw_readl(p->membase + offset);
+}
+
+static void au_serial_out_fn(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ __raw_writel(value, p->membase + offset);
+}
#endif
- case UPIO_TSI:
- if (offset == UART_IIR) {
- tmp = readl(up->port.membase + (UART_IIR & ~3));
- return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
- } else
- return readb(up->port.membase + offset);
+static unsigned int tsi_serial_in_fn(struct uart_port *p, int offset)
+{
+ unsigned int tmp;
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ if (offset == UART_IIR) {
+ tmp = readl(p->membase + (UART_IIR & ~3));
+ return (tmp >> 16) & 0xff; /* UART_IIR % 4 == 2 */
+ } else
+ return readb(p->membase + offset);
+}
- default:
- return inb(up->port.iobase + offset);
- }
+static void tsi_serial_out_fn(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ if (!((offset == UART_IER) && (value & UART_IER_UUE)))
+ writeb(value, p->membase + offset);
}
-static void
-serial_out(struct uart_8250_port *up, int offset, int value)
+static void dwapb_serial_out_fn(struct uart_port *p, int offset, int value)
{
- /* Save the offset before it's remapped */
int save_offset = offset;
- offset = map_8250_out_reg(up, offset) << up->port.regshift;
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ /* Save the LCR value so it can be re-written when a
+ * Busy Detect interrupt occurs. */
+ if (save_offset == UART_LCR) {
+ struct uart_8250_port *up = (struct uart_8250_port *)p;
+ up->lcr = value;
+ }
+ writeb(value, p->membase + offset);
+ /* Read the IER to ensure any interrupt is cleared before
+ * returning from ISR. */
+ if (save_offset == UART_TX || save_offset == UART_IER)
+ value = p->serial_in_fn(p, UART_IER);
+}
- switch (up->port.iotype) {
+static unsigned int io_serial_in_fn(struct uart_port *p, int offset)
+{
+ offset = map_8250_in_reg(p, offset) << p->regshift;
+ return inb(p->iobase + offset);
+}
+
+static void io_serial_out_fn(struct uart_port *p, int offset, int value)
+{
+ offset = map_8250_out_reg(p, offset) << p->regshift;
+ outb(value, p->iobase + offset);
+}
+
+static void set_io_fns_from_upio(struct uart_port *p)
+{
+ switch (p->iotype) {
case UPIO_HUB6:
- outb(up->port.hub6 - 1 + offset, up->port.iobase);
- outb(value, up->port.iobase + 1);
+ p->serial_in_fn = hub6_serial_in_fn;
+ p->serial_out_fn = hub6_serial_out_fn;
break;
case UPIO_MEM:
- writeb(value, up->port.membase + offset);
+ p->serial_in_fn = mem_serial_in_fn;
+ p->serial_out_fn = mem_serial_out_fn;
break;
case UPIO_RM9000:
case UPIO_MEM32:
- writel(value, up->port.membase + offset);
+ p->serial_in_fn = mem32_serial_in_fn;
+ p->serial_out_fn = mem32_serial_out_fn;
break;
#ifdef CONFIG_SERIAL_8250_AU1X00
case UPIO_AU:
- __raw_writel(value, up->port.membase + offset);
+ p->serial_in_fn = au_serial_in_fn;
+ p->serial_out_fn = au_serial_out_fn;
break;
#endif
case UPIO_TSI:
- if (!((offset == UART_IER) && (value & UART_IER_UUE)))
- writeb(value, up->port.membase + offset);
+ p->serial_in_fn = tsi_serial_in_fn;
+ p->serial_out_fn = tsi_serial_out_fn;
break;
case UPIO_DWAPB:
- /* Save the LCR value so it can be re-written when a
- * Busy Detect interrupt occurs. */
- if (save_offset == UART_LCR)
- up->lcr = value;
- writeb(value, up->port.membase + offset);
- /* Read the IER to ensure any interrupt is cleared before
- * returning from ISR. */
- if (save_offset == UART_TX || save_offset == UART_IER)
- value = serial_in(up, UART_IER);
+ p->serial_in_fn = mem_serial_in_fn;
+ p->serial_out_fn = dwapb_serial_out_fn;
break;
default:
- outb(value, up->port.iobase + offset);
+ p->serial_in_fn = io_serial_in_fn;
+ p->serial_out_fn = io_serial_out_fn;
+ break;
}
}
static void
serial_out_sync(struct uart_8250_port *up, int offset, int value)
{
- switch (up->port.iotype) {
+ struct uart_port *p = &up->port;
+ switch (p->iotype) {
case UPIO_MEM:
case UPIO_MEM32:
#ifdef CONFIG_SERIAL_8250_AU1X00
case UPIO_AU:
#endif
case UPIO_DWAPB:
- serial_out(up, offset, value);
- serial_in(up, UART_LCR); /* safe, no side-effects */
+ p->serial_out_fn(p, offset, value);
+ p->serial_in_fn(p, UART_LCR); /* safe, no side-effects */
break;
default:
- serial_out(up, offset, value);
+ p->serial_out_fn(p, offset, value);
}
}
+#define serial_in(up, offset) \
+ (up->port.serial_in_fn(&(up)->port, (offset)))
+#define serial_out(up, offset, value) \
+ (up->port.serial_out_fn(&(up)->port, (offset), (value)))
/*
* We used to support using pause I/O for certain machines. We
* haven't supported this for a while, but just in case it's badly
@@ -2576,6 +2638,7 @@ static void __init serial8250_isa_init_ports(void)
up->port.membase = old_serial_port[i].iomem_base;
up->port.iotype = old_serial_port[i].io_type;
up->port.regshift = old_serial_port[i].iomem_reg_shift;
+ set_io_fns_from_upio(&up->port);
if (share_irqs)
up->port.flags |= UPF_SHARE_IRQ;
}
@@ -2769,6 +2832,13 @@ int __init early_serial_setup(struct uart_port *port)
p->flags = port->flags;
p->mapbase = port->mapbase;
p->private_data = port->private_data;
+
+ set_io_fns_from_upio(p);
+ if (port->serial_in_fn)
+ p->serial_in_fn = port->serial_in_fn;
+ if (port->serial_out_fn)
+ p->serial_out_fn = port->serial_out_fn;
+
return 0;
}
@@ -2986,6 +3056,12 @@ int serial8250_register_port(struct uart_port *port)
uart->port.private_data = port->private_data;
if (port->dev)
uart->port.dev = port->dev;
+ set_io_fns_from_upio(&uart->port);
+ /* Possibly override default I/O functions. */
+ if (port->serial_in_fn)
+ uart->port.serial_in_fn = port->serial_in_fn;
+ if (port->serial_out_fn)
+ uart->port.serial_out_fn = port->serial_out_fn;
ret = uart_add_one_port(&serial8250_reg, &uart->port);
if (ret == 0)
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index 3d37c94..eb08b04 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -28,6 +28,8 @@ struct plat_serial8250_port {
unsigned char iotype; /* UPIO_* */
unsigned char hub6;
upf_t flags; /* UPF_* flags */
+ unsigned int (*serial_in_fn)(struct uart_port *, int);
+ void (*serial_out_fn)(struct uart_port *, int, int);
};
/*
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index e27f216..40509b0 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -243,6 +243,8 @@ struct uart_port {
spinlock_t lock; /* port lock */
unsigned long iobase; /* in/out[bwl] */
unsigned char __iomem *membase; /* read/write[bwl] */
+ unsigned int (*serial_in_fn)(struct uart_port *, int);
+ void (*serial_out_fn)(struct uart_port *, int, int);
unsigned int irq; /* irq number */
unsigned int uartclk; /* base uart clock */
unsigned int fifosize; /* tx fifo size */
--
1.5.6.5
Add flag value UPF_FIXED_TYPE which specifies that the UART type is
known and should not be probed. For this case the UARTs properties
are just copied out of the uart_config entry.
Signed-off-by: David Daney <[email protected]>
---
drivers/serial/8250.c | 8 ++++++++
drivers/serial/serial_core.c | 7 +++++--
include/linux/serial_core.h | 2 ++
3 files changed, 15 insertions(+), 2 deletions(-)
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 410478f..9d16abb 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -3056,6 +3056,14 @@ int serial8250_register_port(struct uart_port *port)
uart->port.private_data = port->private_data;
if (port->dev)
uart->port.dev = port->dev;
+
+ if (port->flags & UPF_FIXED_TYPE) {
+ uart->port.type = port->type;
+ uart->port.fifosize = uart_config[port->type].fifo_size;
+ uart->capabilities = uart_config[port->type].flags;
+ uart->tx_loadsz = uart_config[port->type].tx_loadsz;
+ }
+
set_io_fns_from_upio(&uart->port);
/* Possibly override default I/O functions. */
if (port->serial_in_fn)
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 874786a..7fef45e 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -2198,11 +2198,14 @@ uart_configure_port(struct uart_driver *drv, struct uart_state *state,
* Now do the auto configuration stuff. Note that config_port
* is expected to claim the resources and map the port for us.
*/
- flags = UART_CONFIG_TYPE;
+ flags = 0;
if (port->flags & UPF_AUTO_IRQ)
flags |= UART_CONFIG_IRQ;
if (port->flags & UPF_BOOT_AUTOCONF) {
- port->type = PORT_UNKNOWN;
+ if (!(port->flags & UPF_FIXED_TYPE)) {
+ port->type = PORT_UNKNOWN;
+ flags |= UART_CONFIG_TYPE;
+ }
port->ops->config_port(port, flags);
}
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 40509b0..54e0dce 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -290,6 +290,8 @@ struct uart_port {
#define UPF_MAGIC_MULTIPLIER ((__force upf_t) (1 << 16))
#define UPF_CONS_FLOW ((__force upf_t) (1 << 23))
#define UPF_SHARE_IRQ ((__force upf_t) (1 << 24))
+/* The exact UART type is known and should not be probed. */
+#define UPF_FIXED_TYPE ((__force upf_t) (1 << 27))
#define UPF_BOOT_AUTOCONF ((__force upf_t) (1 << 28))
#define UPF_FIXED_PORT ((__force upf_t) (1 << 29))
#define UPF_DEAD ((__force upf_t) (1 << 30))
--
1.5.6.5
Cavium UART implementation won't work with the standard 8250 driver
as-is. Define a new uart_config (PORT_OCTEON) and use it to enable
special handling required by the OCTEON's serial port.
Signed-off-by: Tomaso Paoletti <[email protected]>
Signed-off-by: Paul Gortmaker <[email protected]>
Signed-off-by: David Daney <[email protected]>
---
drivers/serial/8250.c | 16 +++++++++++++++-
drivers/serial/8250.h | 2 ++
include/linux/serial_core.h | 3 ++-
include/linux/serial_reg.h | 6 ++++++
4 files changed, 25 insertions(+), 2 deletions(-)
diff --git a/drivers/serial/8250.c b/drivers/serial/8250.c
index 474ab89..f274e94 100644
--- a/drivers/serial/8250.c
+++ b/drivers/serial/8250.c
@@ -279,6 +279,14 @@ static const struct serial8250_config uart_config[] = {
.fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
.flags = UART_CAP_FIFO,
},
+ [PORT_OCTEON] = {
+ .name = "OCTEON",
+ .fifo_size = 64,
+ .tx_loadsz = 64,
+ .bugs = UART_BUG_TIMEOUT | UART_BUG_OCTEON_IIR,
+ .fcr = UART_FCR_ENABLE_FIFO | UART_FCR_R_TRIG_10,
+ .flags = UART_CAP_FIFO,
+ },
};
#if defined (CONFIG_SERIAL_8250_AU1X00)
@@ -1554,6 +1562,12 @@ static irqreturn_t serial8250_interrupt(int irq, void *dev_id)
up = list_entry(l, struct uart_8250_port, list);
iir = serial_in(up, UART_IIR);
+ if ((up->bugs & UART_BUG_OCTEON_IIR) && (iir & 0xf) == 7) {
+ /* Busy interrupt */
+ serial_in(up, UART_OCTEON_USR);
+ iir = serial_in(up, UART_IIR);
+ }
+
if (!(iir & UART_IIR_NO_INT)) {
serial8250_handle_port(up);
@@ -1714,7 +1728,7 @@ static void serial8250_timeout(unsigned long data)
unsigned int iir;
iir = serial_in(up, UART_IIR);
- if (!(iir & UART_IIR_NO_INT))
+ if (!(iir & UART_IIR_NO_INT) || (up->bugs & UART_BUG_TIMEOUT))
serial8250_handle_port(up);
mod_timer(&up->timer, jiffies + poll_timeout(up->port.timeout));
}
diff --git a/drivers/serial/8250.h b/drivers/serial/8250.h
index c9b3002..56b3cb7 100644
--- a/drivers/serial/8250.h
+++ b/drivers/serial/8250.h
@@ -49,6 +49,8 @@ struct serial8250_config {
#define UART_BUG_TXEN (1 << 1) /* UART has buggy TX IIR status */
#define UART_BUG_NOMSR (1 << 2) /* UART has buggy MSR status bits (Au1x00) */
#define UART_BUG_THRE (1 << 3) /* UART has buggy THRE reassertion */
+#define UART_BUG_TIMEOUT (1 << 4) /* UART should always handle timeout */
+#define UART_BUG_OCTEON_IIR (1 << 5) /* UART OCTEON IIR workaround */
#define PROBE_RSA (1 << 0)
#define PROBE_ANY (~0)
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 54e0dce..c6c7faa 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -40,7 +40,8 @@
#define PORT_NS16550A 14
#define PORT_XSCALE 15
#define PORT_RM9000 16 /* PMC-Sierra RM9xxx internal UART */
-#define PORT_MAX_8250 16 /* max port ID */
+#define PORT_OCTEON 17 /* Cavium OCTEON internal UART */
+#define PORT_MAX_8250 17 /* max port ID */
/*
* ARM specific type numbers. These are not currently guaranteed
diff --git a/include/linux/serial_reg.h b/include/linux/serial_reg.h
index 96c0d93..a96bd50 100644
--- a/include/linux/serial_reg.h
+++ b/include/linux/serial_reg.h
@@ -324,5 +324,11 @@
#define UART_OMAP_SYSC 0x15 /* System configuration register */
#define UART_OMAP_SYSS 0x16 /* System status register */
+/*
+ * Extra serial register definitions for the internal UARTs in Cavium
+ * Networks OCTEON processors.
+ */
+#define UART_OCTEON_USR 0x27 /* UART Status Register */
+
#endif /* _LINUX_SERIAL_REG_H */
--
1.5.6.5
On Mon, 27 Oct 2008, David Daney wrote:
> This patch set introduces preliminary support for Cavium Networks'
> OCTEON processor family. More information about these processors may
> be obtained here:
>
> http://www.caviumnetworks.com/OCTEON_MIPS64.html
Well, in the context of a technical mailing list there isn't much more
information available at the link you've quoted; although I do understand
you might not be the most appropriate person to point it to. Honestly,
stating: "The family comprises SOC devices built around MIPS64 cores"
would provide about as much (little) information as the web site does. :(
Maciej
Maciej W. Rozycki wrote:
> On Mon, 27 Oct 2008, David Daney wrote:
>
>
>>This patch set introduces preliminary support for Cavium Networks'
>>OCTEON processor family. More information about these processors may
>>be obtained here:
>>
>>http://www.caviumnetworks.com/OCTEON_MIPS64.html
>
>
> Well, in the context of a technical mailing list there isn't much more
> information available at the link you've quoted; although I do understand
> you might not be the most appropriate person to point it to. Honestly,
> stating: "The family comprises SOC devices built around MIPS64 cores"
> would provide about as much (little) information as the web site does. :(
You can register for free at http://www.cnusers.org and they have a bit more
information there as well as existing SDKs with full linux source for
older versions. However, it looks like the really gory details are
available only after signing an NDA.
Chris
On Thu, 30 Oct 2008, Chris Friesen wrote:
> > Well, in the context of a technical mailing list there isn't much more
> > information available at the link you've quoted; although I do understand
> > you might not be the most appropriate person to point it to. Honestly,
> > stating: "The family comprises SOC devices built around MIPS64 cores" would
> > provide about as much (little) information as the web site does. :(
>
> You can register for free at http://www.cnusers.org and they have a bit more
> information there as well as existing SDKs with full linux source for older
> versions. However, it looks like the really gory details are available only
> after signing an NDA.
Thanks. However I am not *that* desperate yet and registering for access
to all the chips released out there just in case it might be useful for
something does not seem terribly attractive to me.
Maciej