Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 617b925f authored by Kevin Hilman's avatar Kevin Hilman
Browse files

davinci: serial: generalize for more SoCs

parent f9337405
Loading
Loading
Loading
Loading
+18 −3
Original line number Diff line number Diff line
@@ -13,8 +13,23 @@

#include <mach/io.h>

#define DAVINCI_MAX_NR_UARTS	3
#define DAVINCI_UART0_BASE	(IO_PHYS + 0x20000)
#define DAVINCI_UART1_BASE	(IO_PHYS + 0x20400)
#define DAVINCI_UART2_BASE	(IO_PHYS + 0x20800)

#define DM355_UART2_BASE	(IO_PHYS + 0x206000)

/* DaVinci UART register offsets */
#define UART_DAVINCI_PWREMU		0x0c
#define UART_DM646X_SCR			0x10
#define UART_DM646X_SCR_TX_WATERMARK	0x08

struct davinci_uart_config {
	/* Bit field of UARTs present; bit 0 --> UART1 */
	unsigned int enabled_uarts;
};

extern void davinci_serial_init(struct davinci_uart_config *);

#endif /* __ASM_ARCH_SERIAL_H */
+78 −17
Original line number Diff line number Diff line
@@ -32,32 +32,47 @@
#include <mach/hardware.h>
#include <mach/serial.h>
#include <mach/irqs.h>
#include <mach/cputype.h>
#include "clock.h"

#define UART_DAVINCI_PWREMU 0x0c

static inline unsigned int davinci_serial_in(struct plat_serial8250_port *up,
static inline unsigned int serial_read_reg(struct plat_serial8250_port *up,
					   int offset)
{
	offset <<= up->regshift;
	return (unsigned int)__raw_readb(up->membase + offset);
	return (unsigned int)__raw_readl(IO_ADDRESS(up->mapbase) + offset);
}

static inline void davinci_serial_outp(struct plat_serial8250_port *p,
				       int offset, int value)
static inline void serial_write_reg(struct plat_serial8250_port *p, int offset,
				    int value)
{
	offset <<= p->regshift;
	__raw_writeb(value, p->membase + offset);
	__raw_writel(value, IO_ADDRESS(p->mapbase) + offset);
}

static struct plat_serial8250_port serial_platform_data[] = {
	{
		.membase	= (char *)IO_ADDRESS(DAVINCI_UART0_BASE),
		.mapbase	= (unsigned long)DAVINCI_UART0_BASE,
		.mapbase	= DAVINCI_UART0_BASE,
		.irq		= IRQ_UARTINT0,
		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST,
		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
				  UPF_IOREMAP,
		.iotype		= UPIO_MEM,
		.regshift	= 2,
	},
	{
		.mapbase	= DAVINCI_UART1_BASE,
		.irq		= IRQ_UARTINT1,
		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
				  UPF_IOREMAP,
		.iotype		= UPIO_MEM,
		.regshift	= 2,
	},
	{
		.mapbase	= DAVINCI_UART2_BASE,
		.irq		= IRQ_UARTINT2,
		.flags		= UPF_BOOT_AUTOCONF | UPF_SKIP_TEST |
				  UPF_IOREMAP,
		.iotype		= UPIO_MEM,
		.regshift	= 2,
		.uartclk	= 27000000,
	},
	{
		.flags		= 0
@@ -74,22 +89,68 @@ static struct platform_device serial_device = {

static void __init davinci_serial_reset(struct plat_serial8250_port *p)
{
	/* reset both transmitter and receiver: bits 14,13 = UTRST, URRST */
	unsigned int pwremu = 0;

	davinci_serial_outp(p, UART_IER, 0);  /* disable all interrupts */
	serial_write_reg(p, UART_IER, 0);  /* disable all interrupts */

	davinci_serial_outp(p, UART_DAVINCI_PWREMU, pwremu);
	/* reset both transmitter and receiver: bits 14,13 = UTRST, URRST */
	serial_write_reg(p, UART_DAVINCI_PWREMU, pwremu);
	mdelay(10);

	pwremu |= (0x3 << 13);
	pwremu |= 0x1;
	davinci_serial_outp(p, UART_DAVINCI_PWREMU, pwremu);
	serial_write_reg(p, UART_DAVINCI_PWREMU, pwremu);

	if (cpu_is_davinci_dm646x())
		serial_write_reg(p, UART_DM646X_SCR,
				 UART_DM646X_SCR_TX_WATERMARK);
}

void __init davinci_serial_init(struct davinci_uart_config *info)
{
	int i;
	char name[16];
	struct clk *uart_clk;
	struct device *dev = &serial_device.dev;

	/*
	 * Make sure the serial ports are muxed on at this point.
	 * You have to mux them off in device drivers later on
	 * if not needed.
	 */
	for (i = 0; i < DAVINCI_MAX_NR_UARTS; i++) {
		struct plat_serial8250_port *p = serial_platform_data + i;

		if (!(info->enabled_uarts & (1 << i))) {
			p->flags = 0;
			continue;
		}

		if (cpu_is_davinci_dm646x())
			p->iotype = UPIO_MEM32;

		if (cpu_is_davinci_dm355()) {
			if (i == 2) {
				p->mapbase = (unsigned long)DM355_UART2_BASE;
				p->irq = IRQ_DM355_UARTINT2;
			}
		}

		sprintf(name, "uart%d", i);
		uart_clk = clk_get(dev, name);
		if (IS_ERR(uart_clk))
			printk(KERN_ERR "%s:%d: failed to get UART%d clock\n",
					__func__, __LINE__, i);
		else {
			clk_enable(uart_clk);
			p->uartclk = clk_get_rate(uart_clk);
			davinci_serial_reset(p);
		}
	}
}

static int __init davinci_init(void)
{
	davinci_serial_reset(&serial_platform_data[0]);
	return platform_device_register(&serial_device);
}