Skip to content

Commit

Permalink
[POWERPC] mpc512x: Add MPC512x PSC support to MPC52xx psc driver
Browse files Browse the repository at this point in the history
Add 512x support using the psc_ops framework established
with the previous patch.

All 512x PSCs share the same interrupt so add
IRQF_SHARED to irq flags.

Signed-off-by: John Rigby <jrigby@freescale.com>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
  • Loading branch information
John Rigby authored and Grant Likely committed Feb 6, 2008
1 parent 599f030 commit 25ae3a0
Show file tree
Hide file tree
Showing 3 changed files with 225 additions and 12 deletions.
12 changes: 6 additions & 6 deletions drivers/serial/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -1114,25 +1114,25 @@ config SERIAL_SGI_L1_CONSOLE
say Y. Otherwise, say N.

config SERIAL_MPC52xx
tristate "Freescale MPC52xx family PSC serial support"
depends on PPC_MPC52xx
tristate "Freescale MPC52xx/MPC512x family PSC serial support"
depends on PPC_MPC52xx || PPC_MPC512x
select SERIAL_CORE
help
This drivers support the MPC52xx PSC serial ports. If you would
like to use them, you must answer Y or M to this option. Not that
This driver supports MPC52xx and MPC512x PSC serial ports. If you would
like to use them, you must answer Y or M to this option. Note that
for use as console, it must be included in kernel and not as a
module.

config SERIAL_MPC52xx_CONSOLE
bool "Console on a Freescale MPC52xx family PSC serial port"
bool "Console on a Freescale MPC52xx/MPC512x family PSC serial port"
depends on SERIAL_MPC52xx=y
select SERIAL_CORE_CONSOLE
help
Select this options if you'd like to use one of the PSC serial port
of the Freescale MPC52xx family as a console.

config SERIAL_MPC52xx_CONSOLE_BAUD
int "Freescale MPC52xx family PSC serial port baud"
int "Freescale MPC52xx/MPC512x family PSC serial port baud"
depends on SERIAL_MPC52xx_CONSOLE=y
default "9600"
help
Expand Down
177 changes: 171 additions & 6 deletions drivers/serial/mpc52xx_uart.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
* Some of the code has been inspired/copied from the 2.4 code written
* by Dale Farnsworth <dfarnsworth@mvista.com>.
*
* Copyright (C) 2008 Freescale Semiconductor Inc.
* John Rigby <jrigby@gmail.com>
* Added support for MPC5121
* Copyright (C) 2006 Secret Lab Technologies Ltd.
* Grant Likely <grant.likely@secretlab.ca>
* Copyright (C) 2004-2006 Sylvain Munaut <tnt@246tNt.com>
Expand Down Expand Up @@ -78,6 +81,7 @@
#endif

#include <asm/mpc52xx.h>
#include <asm/mpc512x.h>
#include <asm/mpc52xx_psc.h>

#if defined(CONFIG_SERIAL_MPC52xx_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
Expand Down Expand Up @@ -129,13 +133,29 @@ static irqreturn_t mpc52xx_uart_int(int irq, void *dev_id);

#if defined(CONFIG_PPC_MERGE)
static struct of_device_id mpc52xx_uart_of_match[] = {
{ .type = "serial", .compatible = "fsl,mpc5200-psc-uart", },
{ .type = "serial", .compatible = "mpc5200-psc-uart", }, /* lite5200 */
{ .type = "serial", .compatible = "mpc5200-serial", }, /* efika */
#ifdef CONFIG_PPC_MPC52xx
{ .compatible = "fsl,mpc5200-psc-uart", .data = &mpc52xx_psc_ops, },
/* binding used by old lite5200 device trees: */
{ .compatible = "mpc5200-psc-uart", .data = &mpc52xx_psc_ops, },
/* binding used by efika: */
{ .compatible = "mpc5200-serial", .data = &mpc52xx_psc_ops, },
#endif
#ifdef CONFIG_PPC_MPC512x
{ .compatible = "fsl,mpc5121-psc-uart", .data = &mpc512x_psc_ops, },
{},
#endif
};
#if defined(CONFIG_PPC_MERGE)
static const struct of_device_id mpc52xx_uart_of_match[] = {
{.type = "serial",
.compatible = "mpc5200-psc-uart",
#endif
{},
};
#endif

#endif

/* ======================================================================== */
/* PSC fifo operations for isolating differences between 52xx and 512x */
/* ======================================================================== */
Expand All @@ -159,6 +179,7 @@ struct psc_ops {
unsigned long (*getuartclk)(void *p);
};

#ifdef CONFIG_PPC_MPC52xx
#define FIFO_52xx(port) ((struct mpc52xx_psc_fifo __iomem *)(PSC(port)+1))
static void mpc52xx_psc_fifo_init(struct uart_port *port)
{
Expand Down Expand Up @@ -291,7 +312,145 @@ static struct psc_ops mpc52xx_psc_ops = {
.getuartclk = mpc52xx_getuartclk,
};

static struct psc_ops *psc_ops = &mpc52xx_psc_ops;
#endif /* CONFIG_MPC52xx */

#ifdef CONFIG_PPC_MPC512x
#define FIFO_512x(port) ((struct mpc512x_psc_fifo __iomem *)(PSC(port)+1))
static void mpc512x_psc_fifo_init(struct uart_port *port)
{
out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_RESET_SLICE);
out_be32(&FIFO_512x(port)->txcmd, MPC512x_PSC_FIFO_ENABLE_SLICE);
out_be32(&FIFO_512x(port)->txalarm, 1);
out_be32(&FIFO_512x(port)->tximr, 0);

out_be32(&FIFO_512x(port)->rxcmd, MPC512x_PSC_FIFO_RESET_SLICE);
out_be32(&FIFO_512x(port)->rxcmd, MPC512x_PSC_FIFO_ENABLE_SLICE);
out_be32(&FIFO_512x(port)->rxalarm, 1);
out_be32(&FIFO_512x(port)->rximr, 0);

out_be32(&FIFO_512x(port)->tximr, MPC512x_PSC_FIFO_ALARM);
out_be32(&FIFO_512x(port)->rximr, MPC512x_PSC_FIFO_ALARM);
}

static int mpc512x_psc_raw_rx_rdy(struct uart_port *port)
{
return !(in_be32(&FIFO_512x(port)->rxsr) & MPC512x_PSC_FIFO_EMPTY);
}

static int mpc512x_psc_raw_tx_rdy(struct uart_port *port)
{
return !(in_be32(&FIFO_512x(port)->txsr) & MPC512x_PSC_FIFO_FULL);
}

static int mpc512x_psc_rx_rdy(struct uart_port *port)
{
return in_be32(&FIFO_512x(port)->rxsr)
& in_be32(&FIFO_512x(port)->rximr)
& MPC512x_PSC_FIFO_ALARM;
}

static int mpc512x_psc_tx_rdy(struct uart_port *port)
{
return in_be32(&FIFO_512x(port)->txsr)
& in_be32(&FIFO_512x(port)->tximr)
& MPC512x_PSC_FIFO_ALARM;
}

static int mpc512x_psc_tx_empty(struct uart_port *port)
{
return in_be32(&FIFO_512x(port)->txsr)
& MPC512x_PSC_FIFO_EMPTY;
}

static void mpc512x_psc_stop_rx(struct uart_port *port)
{
unsigned long rx_fifo_imr;

rx_fifo_imr = in_be32(&FIFO_512x(port)->rximr);
rx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM;
out_be32(&FIFO_512x(port)->rximr, rx_fifo_imr);
}

static void mpc512x_psc_start_tx(struct uart_port *port)
{
unsigned long tx_fifo_imr;

tx_fifo_imr = in_be32(&FIFO_512x(port)->tximr);
tx_fifo_imr |= MPC512x_PSC_FIFO_ALARM;
out_be32(&FIFO_512x(port)->tximr, tx_fifo_imr);
}

static void mpc512x_psc_stop_tx(struct uart_port *port)
{
unsigned long tx_fifo_imr;

tx_fifo_imr = in_be32(&FIFO_512x(port)->tximr);
tx_fifo_imr &= ~MPC512x_PSC_FIFO_ALARM;
out_be32(&FIFO_512x(port)->tximr, tx_fifo_imr);
}

static void mpc512x_psc_rx_clr_irq(struct uart_port *port)
{
out_be32(&FIFO_512x(port)->rxisr, in_be32(&FIFO_512x(port)->rxisr));
}

static void mpc512x_psc_tx_clr_irq(struct uart_port *port)
{
out_be32(&FIFO_512x(port)->txisr, in_be32(&FIFO_512x(port)->txisr));
}

static void mpc512x_psc_write_char(struct uart_port *port, unsigned char c)
{
out_8(&FIFO_512x(port)->txdata_8, c);
}

static unsigned char mpc512x_psc_read_char(struct uart_port *port)
{
return in_8(&FIFO_512x(port)->rxdata_8);
}

static void mpc512x_psc_cw_disable_ints(struct uart_port *port)
{
port->read_status_mask =
in_be32(&FIFO_512x(port)->tximr) << 16 |
in_be32(&FIFO_512x(port)->rximr);
out_be32(&FIFO_512x(port)->tximr, 0);
out_be32(&FIFO_512x(port)->rximr, 0);
}

static void mpc512x_psc_cw_restore_ints(struct uart_port *port)
{
out_be32(&FIFO_512x(port)->tximr,
(port->read_status_mask >> 16) & 0x7f);
out_be32(&FIFO_512x(port)->rximr, port->read_status_mask & 0x7f);
}

static unsigned long mpc512x_getuartclk(void *p)
{
return mpc512x_find_ips_freq(p);
}

static struct psc_ops mpc512x_psc_ops = {
.fifo_init = mpc512x_psc_fifo_init,
.raw_rx_rdy = mpc512x_psc_raw_rx_rdy,
.raw_tx_rdy = mpc512x_psc_raw_tx_rdy,
.rx_rdy = mpc512x_psc_rx_rdy,
.tx_rdy = mpc512x_psc_tx_rdy,
.tx_empty = mpc512x_psc_tx_empty,
.stop_rx = mpc512x_psc_stop_rx,
.start_tx = mpc512x_psc_start_tx,
.stop_tx = mpc512x_psc_stop_tx,
.rx_clr_irq = mpc512x_psc_rx_clr_irq,
.tx_clr_irq = mpc512x_psc_tx_clr_irq,
.write_char = mpc512x_psc_write_char,
.read_char = mpc512x_psc_read_char,
.cw_disable_ints = mpc512x_psc_cw_disable_ints,
.cw_restore_ints = mpc512x_psc_cw_restore_ints,
.getuartclk = mpc512x_getuartclk,
};
#endif

static struct psc_ops *psc_ops;

/* ======================================================================== */
/* UART operations */
Expand Down Expand Up @@ -381,7 +540,8 @@ mpc52xx_uart_startup(struct uart_port *port)

/* Request IRQ */
ret = request_irq(port->irq, mpc52xx_uart_int,
IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "mpc52xx_psc_uart", port);
IRQF_DISABLED | IRQF_SAMPLE_RANDOM | IRQF_SHARED,
"mpc52xx_psc_uart", port);
if (ret)
return ret;

Expand Down Expand Up @@ -1208,15 +1368,19 @@ mpc52xx_uart_of_enumerate(void)
static int enum_done;
struct device_node *np;
const unsigned int *devno;
const struct of_device_id *match;
int i;

if (enum_done)
return;

for_each_node_by_type(np, "serial") {
if (!of_match_node(mpc52xx_uart_of_match, np))
match = of_match_node(mpc52xx_uart_of_match, np);
if (!match)
continue;

psc_ops = match->data;

/* Is a particular device number requested? */
devno = of_get_property(np, "port-number", NULL);
mpc52xx_uart_of_assign(np, devno ? *devno : -1);
Expand Down Expand Up @@ -1277,6 +1441,7 @@ mpc52xx_uart_init(void)
return ret;
}
#else
psc_ops = &mpc52xx_psc_ops;
ret = platform_driver_register(&mpc52xx_uart_platform_driver);
if (ret) {
printk(KERN_ERR "%s: platform_driver_register failed (%i)\n",
Expand Down
48 changes: 48 additions & 0 deletions include/asm-powerpc/mpc52xx_psc.h
Original file line number Diff line number Diff line change
Expand Up @@ -190,5 +190,53 @@ struct mpc52xx_psc_fifo {
u16 tflwfptr; /* PSC + 0x9e */
};

#define MPC512x_PSC_FIFO_RESET_SLICE 0x80
#define MPC512x_PSC_FIFO_ENABLE_SLICE 0x01
#define MPC512x_PSC_FIFO_ENABLE_DMA 0x04

#define MPC512x_PSC_FIFO_EMPTY 0x1
#define MPC512x_PSC_FIFO_FULL 0x2
#define MPC512x_PSC_FIFO_ALARM 0x4
#define MPC512x_PSC_FIFO_URERR 0x8
#define MPC512x_PSC_FIFO_ORERR 0x01
#define MPC512x_PSC_FIFO_MEMERROR 0x02

struct mpc512x_psc_fifo {
u32 reserved1[10];
u32 txcmd; /* PSC + 0x80 */
u32 txalarm; /* PSC + 0x84 */
u32 txsr; /* PSC + 0x88 */
u32 txisr; /* PSC + 0x8c */
u32 tximr; /* PSC + 0x90 */
u32 txcnt; /* PSC + 0x94 */
u32 txptr; /* PSC + 0x98 */
u32 txsz; /* PSC + 0x9c */
u32 reserved2[7];
union {
u8 txdata_8;
u16 txdata_16;
u32 txdata_32;
} txdata; /* PSC + 0xbc */
#define txdata_8 txdata.txdata_8
#define txdata_16 txdata.txdata_16
#define txdata_32 txdata.txdata_32
u32 rxcmd; /* PSC + 0xc0 */
u32 rxalarm; /* PSC + 0xc4 */
u32 rxsr; /* PSC + 0xc8 */
u32 rxisr; /* PSC + 0xcc */
u32 rximr; /* PSC + 0xd0 */
u32 rxcnt; /* PSC + 0xd4 */
u32 rxptr; /* PSC + 0xd8 */
u32 rxsz; /* PSC + 0xdc */
u32 reserved3[7];
union {
u8 rxdata_8;
u16 rxdata_16;
u32 rxdata_32;
} rxdata; /* PSC + 0xfc */
#define rxdata_8 rxdata.rxdata_8
#define rxdata_16 rxdata.rxdata_16
#define rxdata_32 rxdata.rxdata_32
};

#endif /* __ASM_MPC52xx_PSC_H__ */

0 comments on commit 25ae3a0

Please sign in to comment.