Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/paulus/powerpc: (408 commits) [POWERPC] Add memchr() to the bootwrapper [POWERPC] Implement logging of unhandled signals [POWERPC] Add legacy serial support for OPB with flattened device tree [POWERPC] Use 1TB segments [POWERPC] XilinxFB: Allow fixed framebuffer base address [POWERPC] XilinxFB: Add support for custom screen resolution [POWERPC] XilinxFB: Use pdata to pass around framebuffer parameters [POWERPC] PCI: Add 64-bit physical address support to setup_indirect_pci [POWERPC] 4xx: Kilauea defconfig file [POWERPC] 4xx: Kilauea DTS [POWERPC] 4xx: Add AMCC Kilauea eval board support to platforms/40x [POWERPC] 4xx: Add AMCC 405EX support to cputable.c [POWERPC] Adjust TASK_SIZE on ppc32 systems to 3GB that are capable [POWERPC] Use PAGE_OFFSET to tell if an address is user/kernel in SW TLB handlers [POWERPC] 85xx: Enable FP emulation in MPC8560 ADS defconfig [POWERPC] 85xx: Killed <asm/mpc85xx.h> [POWERPC] 85xx: Add cpm nodes for 8541/8555 CDS [POWERPC] 85xx: Convert mpc8560ads to the new CPM binding. [POWERPC] mpc8272ads: Remove muram from the CPM reg property. [POWERPC] Make clockevents work on PPC601 processors ... Fixed up conflict in Documentation/powerpc/booting-without-of.txt manually.
This commit is contained in:
@@ -986,6 +986,31 @@ config SERIAL_PMACZILOG
|
||||
PowerMac machines.
|
||||
Say Y or M if you want to be able to these serial ports.
|
||||
|
||||
config SERIAL_PMACZILOG_TTYS
|
||||
bool "Use ttySn device nodes for Zilog z85c30"
|
||||
depends on SERIAL_PMACZILOG
|
||||
help
|
||||
The pmac_zilog driver for the z85C30 chip on many powermacs
|
||||
historically used the device numbers for /dev/ttySn. The
|
||||
8250 serial port driver also uses these numbers, which means
|
||||
the two drivers being unable to coexist; you could not use
|
||||
both z85C30 and 8250 type ports at the same time.
|
||||
|
||||
If this option is not selected, the pmac_zilog driver will
|
||||
use the device numbers allocated for /dev/ttyPZn. This allows
|
||||
the pmac_zilog and 8250 drivers to co-exist, but may cause
|
||||
existing userspace setups to break. Programs that need to
|
||||
access the built-in serial ports on powermacs will need to
|
||||
be reconfigured to use /dev/ttyPZn instead of /dev/ttySn.
|
||||
|
||||
If you enable this option, any z85c30 ports in the system will
|
||||
be registered as ttyS0 onwards as in the past, and you will be
|
||||
unable to use the 8250 module for PCMCIA or other 16C550-style
|
||||
UARTs.
|
||||
|
||||
Say N unless you need the z85c30 ports on your powermac
|
||||
to appear as /dev/ttySn.
|
||||
|
||||
config SERIAL_PMACZILOG_CONSOLE
|
||||
bool "Console on PowerMac z85c30 serial port"
|
||||
depends on SERIAL_PMACZILOG=y
|
||||
|
@@ -56,21 +56,21 @@ struct uart_cpm_port {
|
||||
u16 rx_fifosize;
|
||||
u16 tx_nrfifos;
|
||||
u16 tx_fifosize;
|
||||
smc_t *smcp;
|
||||
smc_uart_t *smcup;
|
||||
scc_t *sccp;
|
||||
scc_uart_t *sccup;
|
||||
volatile cbd_t *rx_bd_base;
|
||||
volatile cbd_t *rx_cur;
|
||||
volatile cbd_t *tx_bd_base;
|
||||
volatile cbd_t *tx_cur;
|
||||
smc_t __iomem *smcp;
|
||||
smc_uart_t __iomem *smcup;
|
||||
scc_t __iomem *sccp;
|
||||
scc_uart_t __iomem *sccup;
|
||||
cbd_t __iomem *rx_bd_base;
|
||||
cbd_t __iomem *rx_cur;
|
||||
cbd_t __iomem *tx_bd_base;
|
||||
cbd_t __iomem *tx_cur;
|
||||
unsigned char *tx_buf;
|
||||
unsigned char *rx_buf;
|
||||
u32 flags;
|
||||
void (*set_lineif)(struct uart_cpm_port *);
|
||||
u8 brg;
|
||||
uint dp_addr;
|
||||
void *mem_addr;
|
||||
void *mem_addr;
|
||||
dma_addr_t dma_addr;
|
||||
u32 mem_size;
|
||||
/* helpers */
|
||||
@@ -80,14 +80,18 @@ struct uart_cpm_port {
|
||||
int is_portb;
|
||||
/* wait on close if needed */
|
||||
int wait_closing;
|
||||
/* value to combine with opcode to form cpm command */
|
||||
u32 command;
|
||||
};
|
||||
|
||||
#ifndef CONFIG_PPC_CPM_NEW_BINDING
|
||||
extern int cpm_uart_port_map[UART_NR];
|
||||
#endif
|
||||
extern int cpm_uart_nr;
|
||||
extern struct uart_cpm_port cpm_uart_ports[UART_NR];
|
||||
|
||||
/* these are located in their respective files */
|
||||
void cpm_line_cr_cmd(int line, int cmd);
|
||||
void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd);
|
||||
int cpm_uart_init_portdesc(void);
|
||||
int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con);
|
||||
void cpm_uart_freebuf(struct uart_cpm_port *pinfo);
|
||||
@@ -102,34 +106,36 @@ void scc4_lineif(struct uart_cpm_port *pinfo);
|
||||
/*
|
||||
virtual to phys transtalion
|
||||
*/
|
||||
static inline unsigned long cpu2cpm_addr(void* addr, struct uart_cpm_port *pinfo)
|
||||
static inline unsigned long cpu2cpm_addr(void *addr,
|
||||
struct uart_cpm_port *pinfo)
|
||||
{
|
||||
int offset;
|
||||
u32 val = (u32)addr;
|
||||
u32 mem = (u32)pinfo->mem_addr;
|
||||
/* sane check */
|
||||
if (likely((val >= (u32)pinfo->mem_addr)) &&
|
||||
(val<((u32)pinfo->mem_addr + pinfo->mem_size))) {
|
||||
offset = val - (u32)pinfo->mem_addr;
|
||||
return pinfo->dma_addr+offset;
|
||||
if (likely(val >= mem && val < mem + pinfo->mem_size)) {
|
||||
offset = val - mem;
|
||||
return pinfo->dma_addr + offset;
|
||||
}
|
||||
/* something nasty happened */
|
||||
BUG();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void *cpm2cpu_addr(unsigned long addr, struct uart_cpm_port *pinfo)
|
||||
static inline void *cpm2cpu_addr(unsigned long addr,
|
||||
struct uart_cpm_port *pinfo)
|
||||
{
|
||||
int offset;
|
||||
u32 val = addr;
|
||||
u32 dma = (u32)pinfo->dma_addr;
|
||||
/* sane check */
|
||||
if (likely((val >= pinfo->dma_addr) &&
|
||||
(val<(pinfo->dma_addr + pinfo->mem_size)))) {
|
||||
offset = val - (u32)pinfo->dma_addr;
|
||||
return (void*)(pinfo->mem_addr+offset);
|
||||
if (likely(val >= dma && val < dma + pinfo->mem_size)) {
|
||||
offset = val - dma;
|
||||
return pinfo->mem_addr + offset;
|
||||
}
|
||||
/* something nasty happened */
|
||||
BUG();
|
||||
return 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -10,7 +10,7 @@
|
||||
* Maintainer: Kumar Gala (galak@kernel.crashing.org) (CPM2)
|
||||
* Pantelis Antoniou (panto@intracom.gr) (CPM1)
|
||||
*
|
||||
* Copyright (C) 2004 Freescale Semiconductor, Inc.
|
||||
* Copyright (C) 2004, 2007 Freescale Semiconductor, Inc.
|
||||
* (C) 2004 Intracom, S.A.
|
||||
* (C) 2005-2006 MontaVista Software, Inc.
|
||||
* Vitaly Bordug <vbordug@ru.mvista.com>
|
||||
@@ -47,6 +47,11 @@
|
||||
#include <asm/irq.h>
|
||||
#include <asm/delay.h>
|
||||
#include <asm/fs_pd.h>
|
||||
#include <asm/udbg.h>
|
||||
|
||||
#ifdef CONFIG_PPC_CPM_NEW_BINDING
|
||||
#include <linux/of_platform.h>
|
||||
#endif
|
||||
|
||||
#if defined(CONFIG_SERIAL_CPM_CONSOLE) && defined(CONFIG_MAGIC_SYSRQ)
|
||||
#define SUPPORT_SYSRQ
|
||||
@@ -57,12 +62,6 @@
|
||||
|
||||
#include "cpm_uart.h"
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
/* Track which ports are configured as uarts */
|
||||
int cpm_uart_port_map[UART_NR];
|
||||
/* How many ports did we config as uarts */
|
||||
int cpm_uart_nr = 0;
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
@@ -73,6 +72,11 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo);
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
#ifndef CONFIG_PPC_CPM_NEW_BINDING
|
||||
/* Track which ports are configured as uarts */
|
||||
int cpm_uart_port_map[UART_NR];
|
||||
/* How many ports did we config as uarts */
|
||||
int cpm_uart_nr;
|
||||
|
||||
/* Place-holder for board-specific stuff */
|
||||
struct platform_device* __attribute__ ((weak)) __init
|
||||
@@ -119,6 +123,7 @@ static int cpm_uart_id2nr(int id)
|
||||
/* not found or invalid argument */
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Check, if transmit buffers are processed
|
||||
@@ -126,14 +131,14 @@ static int cpm_uart_id2nr(int id)
|
||||
static unsigned int cpm_uart_tx_empty(struct uart_port *port)
|
||||
{
|
||||
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||
volatile cbd_t *bdp = pinfo->tx_bd_base;
|
||||
cbd_t __iomem *bdp = pinfo->tx_bd_base;
|
||||
int ret = 0;
|
||||
|
||||
while (1) {
|
||||
if (bdp->cbd_sc & BD_SC_READY)
|
||||
if (in_be16(&bdp->cbd_sc) & BD_SC_READY)
|
||||
break;
|
||||
|
||||
if (bdp->cbd_sc & BD_SC_WRAP) {
|
||||
if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP) {
|
||||
ret = TIOCSER_TEMT;
|
||||
break;
|
||||
}
|
||||
@@ -162,15 +167,15 @@ static unsigned int cpm_uart_get_mctrl(struct uart_port *port)
|
||||
static void cpm_uart_stop_tx(struct uart_port *port)
|
||||
{
|
||||
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||
volatile smc_t *smcp = pinfo->smcp;
|
||||
volatile scc_t *sccp = pinfo->sccp;
|
||||
smc_t __iomem *smcp = pinfo->smcp;
|
||||
scc_t __iomem *sccp = pinfo->sccp;
|
||||
|
||||
pr_debug("CPM uart[%d]:stop tx\n", port->line);
|
||||
|
||||
if (IS_SMC(pinfo))
|
||||
smcp->smc_smcm &= ~SMCM_TX;
|
||||
clrbits8(&smcp->smc_smcm, SMCM_TX);
|
||||
else
|
||||
sccp->scc_sccm &= ~UART_SCCM_TX;
|
||||
clrbits16(&sccp->scc_sccm, UART_SCCM_TX);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -179,24 +184,24 @@ static void cpm_uart_stop_tx(struct uart_port *port)
|
||||
static void cpm_uart_start_tx(struct uart_port *port)
|
||||
{
|
||||
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||
volatile smc_t *smcp = pinfo->smcp;
|
||||
volatile scc_t *sccp = pinfo->sccp;
|
||||
smc_t __iomem *smcp = pinfo->smcp;
|
||||
scc_t __iomem *sccp = pinfo->sccp;
|
||||
|
||||
pr_debug("CPM uart[%d]:start tx\n", port->line);
|
||||
|
||||
if (IS_SMC(pinfo)) {
|
||||
if (smcp->smc_smcm & SMCM_TX)
|
||||
if (in_8(&smcp->smc_smcm) & SMCM_TX)
|
||||
return;
|
||||
} else {
|
||||
if (sccp->scc_sccm & UART_SCCM_TX)
|
||||
if (in_be16(&sccp->scc_sccm) & UART_SCCM_TX)
|
||||
return;
|
||||
}
|
||||
|
||||
if (cpm_uart_tx_pump(port) != 0) {
|
||||
if (IS_SMC(pinfo)) {
|
||||
smcp->smc_smcm |= SMCM_TX;
|
||||
setbits8(&smcp->smc_smcm, SMCM_TX);
|
||||
} else {
|
||||
sccp->scc_sccm |= UART_SCCM_TX;
|
||||
setbits16(&sccp->scc_sccm, UART_SCCM_TX);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -207,15 +212,15 @@ static void cpm_uart_start_tx(struct uart_port *port)
|
||||
static void cpm_uart_stop_rx(struct uart_port *port)
|
||||
{
|
||||
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||
volatile smc_t *smcp = pinfo->smcp;
|
||||
volatile scc_t *sccp = pinfo->sccp;
|
||||
smc_t __iomem *smcp = pinfo->smcp;
|
||||
scc_t __iomem *sccp = pinfo->sccp;
|
||||
|
||||
pr_debug("CPM uart[%d]:stop rx\n", port->line);
|
||||
|
||||
if (IS_SMC(pinfo))
|
||||
smcp->smc_smcm &= ~SMCM_RX;
|
||||
clrbits8(&smcp->smc_smcm, SMCM_RX);
|
||||
else
|
||||
sccp->scc_sccm &= ~UART_SCCM_RX;
|
||||
clrbits16(&sccp->scc_sccm, UART_SCCM_RX);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -232,15 +237,14 @@ static void cpm_uart_enable_ms(struct uart_port *port)
|
||||
static void cpm_uart_break_ctl(struct uart_port *port, int break_state)
|
||||
{
|
||||
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||
int line = pinfo - cpm_uart_ports;
|
||||
|
||||
pr_debug("CPM uart[%d]:break ctrl, break_state: %d\n", port->line,
|
||||
break_state);
|
||||
|
||||
if (break_state)
|
||||
cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
|
||||
cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
|
||||
else
|
||||
cpm_line_cr_cmd(line, CPM_CR_RESTART_TX);
|
||||
cpm_line_cr_cmd(pinfo, CPM_CR_RESTART_TX);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -259,10 +263,11 @@ static void cpm_uart_int_tx(struct uart_port *port)
|
||||
static void cpm_uart_int_rx(struct uart_port *port)
|
||||
{
|
||||
int i;
|
||||
unsigned char ch, *cp;
|
||||
unsigned char ch;
|
||||
u8 *cp;
|
||||
struct tty_struct *tty = port->info->tty;
|
||||
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||
volatile cbd_t *bdp;
|
||||
cbd_t __iomem *bdp;
|
||||
u16 status;
|
||||
unsigned int flg;
|
||||
|
||||
@@ -274,13 +279,13 @@ static void cpm_uart_int_rx(struct uart_port *port)
|
||||
bdp = pinfo->rx_cur;
|
||||
for (;;) {
|
||||
/* get status */
|
||||
status = bdp->cbd_sc;
|
||||
status = in_be16(&bdp->cbd_sc);
|
||||
/* If this one is empty, return happy */
|
||||
if (status & BD_SC_EMPTY)
|
||||
break;
|
||||
|
||||
/* get number of characters, and check spce in flip-buffer */
|
||||
i = bdp->cbd_datlen;
|
||||
i = in_be16(&bdp->cbd_datlen);
|
||||
|
||||
/* If we have not enough room in tty flip buffer, then we try
|
||||
* later, which will be the next rx-interrupt or a timeout
|
||||
@@ -291,7 +296,7 @@ static void cpm_uart_int_rx(struct uart_port *port)
|
||||
}
|
||||
|
||||
/* get pointer */
|
||||
cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
|
||||
cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
|
||||
|
||||
/* loop through the buffer */
|
||||
while (i-- > 0) {
|
||||
@@ -311,10 +316,11 @@ static void cpm_uart_int_rx(struct uart_port *port)
|
||||
} /* End while (i--) */
|
||||
|
||||
/* This BD is ready to be used again. Clear status. get next */
|
||||
bdp->cbd_sc &= ~(BD_SC_BR | BD_SC_FR | BD_SC_PR | BD_SC_OV | BD_SC_ID);
|
||||
bdp->cbd_sc |= BD_SC_EMPTY;
|
||||
clrbits16(&bdp->cbd_sc, BD_SC_BR | BD_SC_FR | BD_SC_PR |
|
||||
BD_SC_OV | BD_SC_ID);
|
||||
setbits16(&bdp->cbd_sc, BD_SC_EMPTY);
|
||||
|
||||
if (bdp->cbd_sc & BD_SC_WRAP)
|
||||
if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
|
||||
bdp = pinfo->rx_bd_base;
|
||||
else
|
||||
bdp++;
|
||||
@@ -322,7 +328,7 @@ static void cpm_uart_int_rx(struct uart_port *port)
|
||||
} /* End for (;;) */
|
||||
|
||||
/* Write back buffer pointer */
|
||||
pinfo->rx_cur = (volatile cbd_t *) bdp;
|
||||
pinfo->rx_cur = bdp;
|
||||
|
||||
/* activate BH processing */
|
||||
tty_flip_buffer_push(tty);
|
||||
@@ -376,14 +382,14 @@ static irqreturn_t cpm_uart_int(int irq, void *data)
|
||||
u8 events;
|
||||
struct uart_port *port = (struct uart_port *)data;
|
||||
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||
volatile smc_t *smcp = pinfo->smcp;
|
||||
volatile scc_t *sccp = pinfo->sccp;
|
||||
smc_t __iomem *smcp = pinfo->smcp;
|
||||
scc_t __iomem *sccp = pinfo->sccp;
|
||||
|
||||
pr_debug("CPM uart[%d]:IRQ\n", port->line);
|
||||
|
||||
if (IS_SMC(pinfo)) {
|
||||
events = smcp->smc_smce;
|
||||
smcp->smc_smce = events;
|
||||
events = in_8(&smcp->smc_smce);
|
||||
out_8(&smcp->smc_smce, events);
|
||||
if (events & SMCM_BRKE)
|
||||
uart_handle_break(port);
|
||||
if (events & SMCM_RX)
|
||||
@@ -391,8 +397,8 @@ static irqreturn_t cpm_uart_int(int irq, void *data)
|
||||
if (events & SMCM_TX)
|
||||
cpm_uart_int_tx(port);
|
||||
} else {
|
||||
events = sccp->scc_scce;
|
||||
sccp->scc_scce = events;
|
||||
events = in_be16(&sccp->scc_scce);
|
||||
out_be16(&sccp->scc_scce, events);
|
||||
if (events & UART_SCCM_BRKE)
|
||||
uart_handle_break(port);
|
||||
if (events & UART_SCCM_RX)
|
||||
@@ -407,7 +413,6 @@ static int cpm_uart_startup(struct uart_port *port)
|
||||
{
|
||||
int retval;
|
||||
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||
int line = pinfo - cpm_uart_ports;
|
||||
|
||||
pr_debug("CPM uart[%d]:startup\n", port->line);
|
||||
|
||||
@@ -418,15 +423,15 @@ static int cpm_uart_startup(struct uart_port *port)
|
||||
|
||||
/* Startup rx-int */
|
||||
if (IS_SMC(pinfo)) {
|
||||
pinfo->smcp->smc_smcm |= SMCM_RX;
|
||||
pinfo->smcp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
|
||||
setbits8(&pinfo->smcp->smc_smcm, SMCM_RX);
|
||||
setbits16(&pinfo->smcp->smc_smcmr, (SMCMR_REN | SMCMR_TEN));
|
||||
} else {
|
||||
pinfo->sccp->scc_sccm |= UART_SCCM_RX;
|
||||
pinfo->sccp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
setbits16(&pinfo->sccp->scc_sccm, UART_SCCM_RX);
|
||||
setbits32(&pinfo->sccp->scc_gsmrl, (SCC_GSMRL_ENR | SCC_GSMRL_ENT));
|
||||
}
|
||||
|
||||
if (!(pinfo->flags & FLAG_CONSOLE))
|
||||
cpm_line_cr_cmd(line,CPM_CR_INIT_TRX);
|
||||
cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -442,7 +447,6 @@ inline void cpm_uart_wait_until_send(struct uart_cpm_port *pinfo)
|
||||
static void cpm_uart_shutdown(struct uart_port *port)
|
||||
{
|
||||
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||
int line = pinfo - cpm_uart_ports;
|
||||
|
||||
pr_debug("CPM uart[%d]:shutdown\n", port->line);
|
||||
|
||||
@@ -462,20 +466,20 @@ static void cpm_uart_shutdown(struct uart_port *port)
|
||||
|
||||
/* Stop uarts */
|
||||
if (IS_SMC(pinfo)) {
|
||||
volatile smc_t *smcp = pinfo->smcp;
|
||||
smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
|
||||
smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
|
||||
smc_t __iomem *smcp = pinfo->smcp;
|
||||
clrbits16(&smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
|
||||
clrbits8(&smcp->smc_smcm, SMCM_RX | SMCM_TX);
|
||||
} else {
|
||||
volatile scc_t *sccp = pinfo->sccp;
|
||||
sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
|
||||
scc_t __iomem *sccp = pinfo->sccp;
|
||||
clrbits32(&sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
clrbits16(&sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
|
||||
}
|
||||
|
||||
/* Shut them really down and reinit buffer descriptors */
|
||||
if (IS_SMC(pinfo))
|
||||
cpm_line_cr_cmd(line, CPM_CR_STOP_TX);
|
||||
cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
|
||||
else
|
||||
cpm_line_cr_cmd(line, CPM_CR_GRA_STOP_TX);
|
||||
cpm_line_cr_cmd(pinfo, CPM_CR_GRA_STOP_TX);
|
||||
|
||||
cpm_uart_initbd(pinfo);
|
||||
}
|
||||
@@ -490,8 +494,8 @@ static void cpm_uart_set_termios(struct uart_port *port,
|
||||
u16 cval, scval, prev_mode;
|
||||
int bits, sbits;
|
||||
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||
volatile smc_t *smcp = pinfo->smcp;
|
||||
volatile scc_t *sccp = pinfo->sccp;
|
||||
smc_t __iomem *smcp = pinfo->smcp;
|
||||
scc_t __iomem *sccp = pinfo->sccp;
|
||||
|
||||
pr_debug("CPM uart[%d]:set_termios\n", port->line);
|
||||
|
||||
@@ -586,16 +590,15 @@ static void cpm_uart_set_termios(struct uart_port *port,
|
||||
* enables, because we want to put them back if they were
|
||||
* present.
|
||||
*/
|
||||
prev_mode = smcp->smc_smcmr;
|
||||
smcp->smc_smcmr = smcr_mk_clen(bits) | cval | SMCMR_SM_UART;
|
||||
smcp->smc_smcmr |= (prev_mode & (SMCMR_REN | SMCMR_TEN));
|
||||
prev_mode = in_be16(&smcp->smc_smcmr);
|
||||
out_be16(&smcp->smc_smcmr, smcr_mk_clen(bits) | cval | SMCMR_SM_UART);
|
||||
setbits16(&smcp->smc_smcmr, (prev_mode & (SMCMR_REN | SMCMR_TEN)));
|
||||
} else {
|
||||
sccp->scc_psmr = (sbits << 12) | scval;
|
||||
out_be16(&sccp->scc_psmr, (sbits << 12) | scval);
|
||||
}
|
||||
|
||||
cpm_set_brg(pinfo->brg - 1, baud);
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
|
||||
}
|
||||
|
||||
static const char *cpm_uart_type(struct uart_port *port)
|
||||
@@ -629,8 +632,8 @@ static int cpm_uart_verify_port(struct uart_port *port,
|
||||
*/
|
||||
static int cpm_uart_tx_pump(struct uart_port *port)
|
||||
{
|
||||
volatile cbd_t *bdp;
|
||||
unsigned char *p;
|
||||
cbd_t __iomem *bdp;
|
||||
u8 *p;
|
||||
int count;
|
||||
struct uart_cpm_port *pinfo = (struct uart_cpm_port *)port;
|
||||
struct circ_buf *xmit = &port->info->xmit;
|
||||
@@ -640,13 +643,14 @@ static int cpm_uart_tx_pump(struct uart_port *port)
|
||||
/* Pick next descriptor and fill from buffer */
|
||||
bdp = pinfo->tx_cur;
|
||||
|
||||
p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
|
||||
p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
|
||||
|
||||
*p++ = port->x_char;
|
||||
bdp->cbd_datlen = 1;
|
||||
bdp->cbd_sc |= BD_SC_READY;
|
||||
|
||||
out_be16(&bdp->cbd_datlen, 1);
|
||||
setbits16(&bdp->cbd_sc, BD_SC_READY);
|
||||
/* Get next BD. */
|
||||
if (bdp->cbd_sc & BD_SC_WRAP)
|
||||
if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
|
||||
bdp = pinfo->tx_bd_base;
|
||||
else
|
||||
bdp++;
|
||||
@@ -665,9 +669,10 @@ static int cpm_uart_tx_pump(struct uart_port *port)
|
||||
/* Pick next descriptor and fill from buffer */
|
||||
bdp = pinfo->tx_cur;
|
||||
|
||||
while (!(bdp->cbd_sc & BD_SC_READY) && (xmit->tail != xmit->head)) {
|
||||
while (!(in_be16(&bdp->cbd_sc) & BD_SC_READY) &&
|
||||
xmit->tail != xmit->head) {
|
||||
count = 0;
|
||||
p = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
|
||||
p = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
|
||||
while (count < pinfo->tx_fifosize) {
|
||||
*p++ = xmit->buf[xmit->tail];
|
||||
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
|
||||
@@ -676,11 +681,10 @@ static int cpm_uart_tx_pump(struct uart_port *port)
|
||||
if (xmit->head == xmit->tail)
|
||||
break;
|
||||
}
|
||||
bdp->cbd_datlen = count;
|
||||
bdp->cbd_sc |= BD_SC_READY;
|
||||
eieio();
|
||||
out_be16(&bdp->cbd_datlen, count);
|
||||
setbits16(&bdp->cbd_sc, BD_SC_READY);
|
||||
/* Get next BD. */
|
||||
if (bdp->cbd_sc & BD_SC_WRAP)
|
||||
if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
|
||||
bdp = pinfo->tx_bd_base;
|
||||
else
|
||||
bdp++;
|
||||
@@ -705,7 +709,7 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
int i;
|
||||
u8 *mem_addr;
|
||||
volatile cbd_t *bdp;
|
||||
cbd_t __iomem *bdp;
|
||||
|
||||
pr_debug("CPM uart[%d]:initbd\n", pinfo->port.line);
|
||||
|
||||
@@ -716,13 +720,13 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
|
||||
mem_addr = pinfo->mem_addr;
|
||||
bdp = pinfo->rx_cur = pinfo->rx_bd_base;
|
||||
for (i = 0; i < (pinfo->rx_nrfifos - 1); i++, bdp++) {
|
||||
bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
|
||||
bdp->cbd_sc = BD_SC_EMPTY | BD_SC_INTRPT;
|
||||
out_be32(&bdp->cbd_bufaddr, cpu2cpm_addr(mem_addr, pinfo));
|
||||
out_be16(&bdp->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT);
|
||||
mem_addr += pinfo->rx_fifosize;
|
||||
}
|
||||
|
||||
bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
|
||||
bdp->cbd_sc = BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT;
|
||||
out_be32(&bdp->cbd_bufaddr, cpu2cpm_addr(mem_addr, pinfo));
|
||||
out_be16(&bdp->cbd_sc, BD_SC_WRAP | BD_SC_EMPTY | BD_SC_INTRPT);
|
||||
|
||||
/* Set the physical address of the host memory
|
||||
* buffers in the buffer descriptors, and the
|
||||
@@ -731,20 +735,19 @@ static void cpm_uart_initbd(struct uart_cpm_port *pinfo)
|
||||
mem_addr = pinfo->mem_addr + L1_CACHE_ALIGN(pinfo->rx_nrfifos * pinfo->rx_fifosize);
|
||||
bdp = pinfo->tx_cur = pinfo->tx_bd_base;
|
||||
for (i = 0; i < (pinfo->tx_nrfifos - 1); i++, bdp++) {
|
||||
bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
|
||||
bdp->cbd_sc = BD_SC_INTRPT;
|
||||
out_be32(&bdp->cbd_bufaddr, cpu2cpm_addr(mem_addr, pinfo));
|
||||
out_be16(&bdp->cbd_sc, BD_SC_INTRPT);
|
||||
mem_addr += pinfo->tx_fifosize;
|
||||
}
|
||||
|
||||
bdp->cbd_bufaddr = cpu2cpm_addr(mem_addr, pinfo);
|
||||
bdp->cbd_sc = BD_SC_WRAP | BD_SC_INTRPT;
|
||||
out_be32(&bdp->cbd_bufaddr, cpu2cpm_addr(mem_addr, pinfo));
|
||||
out_be16(&bdp->cbd_sc, BD_SC_WRAP | BD_SC_INTRPT);
|
||||
}
|
||||
|
||||
static void cpm_uart_init_scc(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
int line = pinfo - cpm_uart_ports;
|
||||
volatile scc_t *scp;
|
||||
volatile scc_uart_t *sup;
|
||||
scc_t __iomem *scp;
|
||||
scc_uart_t __iomem *sup;
|
||||
|
||||
pr_debug("CPM uart[%d]:init_scc\n", pinfo->port.line);
|
||||
|
||||
@@ -752,8 +755,10 @@ static void cpm_uart_init_scc(struct uart_cpm_port *pinfo)
|
||||
sup = pinfo->sccup;
|
||||
|
||||
/* Store address */
|
||||
pinfo->sccup->scc_genscc.scc_rbase = (unsigned char *)pinfo->rx_bd_base - DPRAM_BASE;
|
||||
pinfo->sccup->scc_genscc.scc_tbase = (unsigned char *)pinfo->tx_bd_base - DPRAM_BASE;
|
||||
out_be16(&pinfo->sccup->scc_genscc.scc_rbase,
|
||||
(u8 __iomem *)pinfo->rx_bd_base - DPRAM_BASE);
|
||||
out_be16(&pinfo->sccup->scc_genscc.scc_tbase,
|
||||
(u8 __iomem *)pinfo->tx_bd_base - DPRAM_BASE);
|
||||
|
||||
/* Set up the uart parameters in the
|
||||
* parameter ram.
|
||||
@@ -761,51 +766,50 @@ static void cpm_uart_init_scc(struct uart_cpm_port *pinfo)
|
||||
|
||||
cpm_set_scc_fcr(sup);
|
||||
|
||||
sup->scc_genscc.scc_mrblr = pinfo->rx_fifosize;
|
||||
sup->scc_maxidl = pinfo->rx_fifosize;
|
||||
sup->scc_brkcr = 1;
|
||||
sup->scc_parec = 0;
|
||||
sup->scc_frmec = 0;
|
||||
sup->scc_nosec = 0;
|
||||
sup->scc_brkec = 0;
|
||||
sup->scc_uaddr1 = 0;
|
||||
sup->scc_uaddr2 = 0;
|
||||
sup->scc_toseq = 0;
|
||||
sup->scc_char1 = 0x8000;
|
||||
sup->scc_char2 = 0x8000;
|
||||
sup->scc_char3 = 0x8000;
|
||||
sup->scc_char4 = 0x8000;
|
||||
sup->scc_char5 = 0x8000;
|
||||
sup->scc_char6 = 0x8000;
|
||||
sup->scc_char7 = 0x8000;
|
||||
sup->scc_char8 = 0x8000;
|
||||
sup->scc_rccm = 0xc0ff;
|
||||
out_be16(&sup->scc_genscc.scc_mrblr, pinfo->rx_fifosize);
|
||||
out_be16(&sup->scc_maxidl, pinfo->rx_fifosize);
|
||||
out_be16(&sup->scc_brkcr, 1);
|
||||
out_be16(&sup->scc_parec, 0);
|
||||
out_be16(&sup->scc_frmec, 0);
|
||||
out_be16(&sup->scc_nosec, 0);
|
||||
out_be16(&sup->scc_brkec, 0);
|
||||
out_be16(&sup->scc_uaddr1, 0);
|
||||
out_be16(&sup->scc_uaddr2, 0);
|
||||
out_be16(&sup->scc_toseq, 0);
|
||||
out_be16(&sup->scc_char1, 0x8000);
|
||||
out_be16(&sup->scc_char2, 0x8000);
|
||||
out_be16(&sup->scc_char3, 0x8000);
|
||||
out_be16(&sup->scc_char4, 0x8000);
|
||||
out_be16(&sup->scc_char5, 0x8000);
|
||||
out_be16(&sup->scc_char6, 0x8000);
|
||||
out_be16(&sup->scc_char7, 0x8000);
|
||||
out_be16(&sup->scc_char8, 0x8000);
|
||||
out_be16(&sup->scc_rccm, 0xc0ff);
|
||||
|
||||
/* Send the CPM an initialize command.
|
||||
*/
|
||||
cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
|
||||
cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
|
||||
|
||||
/* Set UART mode, 8 bit, no parity, one stop.
|
||||
* Enable receive and transmit.
|
||||
*/
|
||||
scp->scc_gsmrh = 0;
|
||||
scp->scc_gsmrl =
|
||||
(SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
|
||||
out_be32(&scp->scc_gsmrh, 0);
|
||||
out_be32(&scp->scc_gsmrl,
|
||||
SCC_GSMRL_MODE_UART | SCC_GSMRL_TDCR_16 | SCC_GSMRL_RDCR_16);
|
||||
|
||||
/* Enable rx interrupts and clear all pending events. */
|
||||
scp->scc_sccm = 0;
|
||||
scp->scc_scce = 0xffff;
|
||||
scp->scc_dsr = 0x7e7e;
|
||||
scp->scc_psmr = 0x3000;
|
||||
out_be16(&scp->scc_sccm, 0);
|
||||
out_be16(&scp->scc_scce, 0xffff);
|
||||
out_be16(&scp->scc_dsr, 0x7e7e);
|
||||
out_be16(&scp->scc_psmr, 0x3000);
|
||||
|
||||
scp->scc_gsmrl |= (SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
setbits32(&scp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
}
|
||||
|
||||
static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
|
||||
{
|
||||
int line = pinfo - cpm_uart_ports;
|
||||
volatile smc_t *sp;
|
||||
volatile smc_uart_t *up;
|
||||
smc_t __iomem *sp;
|
||||
smc_uart_t __iomem *up;
|
||||
|
||||
pr_debug("CPM uart[%d]:init_smc\n", pinfo->port.line);
|
||||
|
||||
@@ -813,19 +817,21 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
|
||||
up = pinfo->smcup;
|
||||
|
||||
/* Store address */
|
||||
pinfo->smcup->smc_rbase = (u_char *)pinfo->rx_bd_base - DPRAM_BASE;
|
||||
pinfo->smcup->smc_tbase = (u_char *)pinfo->tx_bd_base - DPRAM_BASE;
|
||||
out_be16(&pinfo->smcup->smc_rbase,
|
||||
(u8 __iomem *)pinfo->rx_bd_base - DPRAM_BASE);
|
||||
out_be16(&pinfo->smcup->smc_tbase,
|
||||
(u8 __iomem *)pinfo->tx_bd_base - DPRAM_BASE);
|
||||
|
||||
/*
|
||||
* In case SMC1 is being relocated...
|
||||
*/
|
||||
#if defined (CONFIG_I2C_SPI_SMC1_UCODE_PATCH)
|
||||
up->smc_rbptr = pinfo->smcup->smc_rbase;
|
||||
up->smc_tbptr = pinfo->smcup->smc_tbase;
|
||||
up->smc_rstate = 0;
|
||||
up->smc_tstate = 0;
|
||||
up->smc_brkcr = 1; /* number of break chars */
|
||||
up->smc_brkec = 0;
|
||||
out_be16(&up->smc_rbptr, in_be16(&pinfo->smcup->smc_rbase));
|
||||
out_be16(&up->smc_tbptr, in_be16(&pinfo->smcup->smc_tbase));
|
||||
out_be32(&up->smc_rstate, 0);
|
||||
out_be32(&up->smc_tstate, 0);
|
||||
out_be16(&up->smc_brkcr, 1); /* number of break chars */
|
||||
out_be16(&up->smc_brkec, 0);
|
||||
#endif
|
||||
|
||||
/* Set up the uart parameters in the
|
||||
@@ -834,24 +840,24 @@ static void cpm_uart_init_smc(struct uart_cpm_port *pinfo)
|
||||
cpm_set_smc_fcr(up);
|
||||
|
||||
/* Using idle charater time requires some additional tuning. */
|
||||
up->smc_mrblr = pinfo->rx_fifosize;
|
||||
up->smc_maxidl = pinfo->rx_fifosize;
|
||||
up->smc_brklen = 0;
|
||||
up->smc_brkec = 0;
|
||||
up->smc_brkcr = 1;
|
||||
out_be16(&up->smc_mrblr, pinfo->rx_fifosize);
|
||||
out_be16(&up->smc_maxidl, pinfo->rx_fifosize);
|
||||
out_be16(&up->smc_brklen, 0);
|
||||
out_be16(&up->smc_brkec, 0);
|
||||
out_be16(&up->smc_brkcr, 1);
|
||||
|
||||
cpm_line_cr_cmd(line, CPM_CR_INIT_TRX);
|
||||
cpm_line_cr_cmd(pinfo, CPM_CR_INIT_TRX);
|
||||
|
||||
/* Set UART mode, 8 bit, no parity, one stop.
|
||||
* Enable receive and transmit.
|
||||
*/
|
||||
sp->smc_smcmr = smcr_mk_clen(9) | SMCMR_SM_UART;
|
||||
out_be16(&sp->smc_smcmr, smcr_mk_clen(9) | SMCMR_SM_UART);
|
||||
|
||||
/* Enable only rx interrupts clear all pending events. */
|
||||
sp->smc_smcm = 0;
|
||||
sp->smc_smce = 0xff;
|
||||
out_8(&sp->smc_smcm, 0);
|
||||
out_8(&sp->smc_smce, 0xff);
|
||||
|
||||
sp->smc_smcmr |= (SMCMR_REN | SMCMR_TEN);
|
||||
setbits16(&sp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -869,11 +875,11 @@ static int cpm_uart_request_port(struct uart_port *port)
|
||||
return 0;
|
||||
|
||||
if (IS_SMC(pinfo)) {
|
||||
pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
|
||||
pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
|
||||
clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX | SMCM_TX);
|
||||
clrbits16(&pinfo->smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
|
||||
} else {
|
||||
pinfo->sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
|
||||
pinfo->sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
|
||||
clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
}
|
||||
|
||||
ret = cpm_uart_allocbuf(pinfo, 0);
|
||||
@@ -929,6 +935,86 @@ static struct uart_ops cpm_uart_pops = {
|
||||
.verify_port = cpm_uart_verify_port,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PPC_CPM_NEW_BINDING
|
||||
struct uart_cpm_port cpm_uart_ports[UART_NR];
|
||||
|
||||
static int cpm_uart_init_port(struct device_node *np,
|
||||
struct uart_cpm_port *pinfo)
|
||||
{
|
||||
const u32 *data;
|
||||
void __iomem *mem, *pram;
|
||||
int len;
|
||||
int ret;
|
||||
|
||||
data = of_get_property(np, "fsl,cpm-brg", &len);
|
||||
if (!data || len != 4) {
|
||||
printk(KERN_ERR "CPM UART %s has no/invalid "
|
||||
"fsl,cpm-brg property.\n", np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
pinfo->brg = *data;
|
||||
|
||||
data = of_get_property(np, "fsl,cpm-command", &len);
|
||||
if (!data || len != 4) {
|
||||
printk(KERN_ERR "CPM UART %s has no/invalid "
|
||||
"fsl,cpm-command property.\n", np->name);
|
||||
return -EINVAL;
|
||||
}
|
||||
pinfo->command = *data;
|
||||
|
||||
mem = of_iomap(np, 0);
|
||||
if (!mem)
|
||||
return -ENOMEM;
|
||||
|
||||
pram = of_iomap(np, 1);
|
||||
if (!pram) {
|
||||
ret = -ENOMEM;
|
||||
goto out_mem;
|
||||
}
|
||||
|
||||
if (of_device_is_compatible(np, "fsl,cpm1-scc-uart") ||
|
||||
of_device_is_compatible(np, "fsl,cpm2-scc-uart")) {
|
||||
pinfo->sccp = mem;
|
||||
pinfo->sccup = pram;
|
||||
} else if (of_device_is_compatible(np, "fsl,cpm1-smc-uart") ||
|
||||
of_device_is_compatible(np, "fsl,cpm2-smc-uart")) {
|
||||
pinfo->flags |= FLAG_SMC;
|
||||
pinfo->smcp = mem;
|
||||
pinfo->smcup = pram;
|
||||
} else {
|
||||
ret = -ENODEV;
|
||||
goto out_pram;
|
||||
}
|
||||
|
||||
pinfo->tx_nrfifos = TX_NUM_FIFO;
|
||||
pinfo->tx_fifosize = TX_BUF_SIZE;
|
||||
pinfo->rx_nrfifos = RX_NUM_FIFO;
|
||||
pinfo->rx_fifosize = RX_BUF_SIZE;
|
||||
|
||||
pinfo->port.uartclk = ppc_proc_freq;
|
||||
pinfo->port.mapbase = (unsigned long)mem;
|
||||
pinfo->port.type = PORT_CPM;
|
||||
pinfo->port.ops = &cpm_uart_pops,
|
||||
pinfo->port.iotype = UPIO_MEM;
|
||||
spin_lock_init(&pinfo->port.lock);
|
||||
|
||||
pinfo->port.irq = of_irq_to_resource(np, 0, NULL);
|
||||
if (pinfo->port.irq == NO_IRQ) {
|
||||
ret = -EINVAL;
|
||||
goto out_pram;
|
||||
}
|
||||
|
||||
return cpm_uart_request_port(&pinfo->port);
|
||||
|
||||
out_pram:
|
||||
iounmap(pram);
|
||||
out_mem:
|
||||
iounmap(mem);
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
struct uart_cpm_port cpm_uart_ports[UART_NR] = {
|
||||
[UART_SMC1] = {
|
||||
.port = {
|
||||
@@ -1072,6 +1158,7 @@ int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SERIAL_CPM_CONSOLE
|
||||
/*
|
||||
@@ -1083,11 +1170,15 @@ int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
|
||||
static void cpm_uart_console_write(struct console *co, const char *s,
|
||||
u_int count)
|
||||
{
|
||||
#ifdef CONFIG_PPC_CPM_NEW_BINDING
|
||||
struct uart_cpm_port *pinfo = &cpm_uart_ports[co->index];
|
||||
#else
|
||||
struct uart_cpm_port *pinfo =
|
||||
&cpm_uart_ports[cpm_uart_port_map[co->index]];
|
||||
#endif
|
||||
unsigned int i;
|
||||
volatile cbd_t *bdp, *bdbase;
|
||||
volatile unsigned char *cp;
|
||||
cbd_t __iomem *bdp, *bdbase;
|
||||
unsigned char *cp;
|
||||
|
||||
/* Get the address of the host memory buffer.
|
||||
*/
|
||||
@@ -1105,37 +1196,36 @@ static void cpm_uart_console_write(struct console *co, const char *s,
|
||||
* Ready indicates output is ready, and xmt is doing
|
||||
* that, not that it is ready for us to send.
|
||||
*/
|
||||
while ((bdp->cbd_sc & BD_SC_READY) != 0)
|
||||
while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
|
||||
;
|
||||
|
||||
/* Send the character out.
|
||||
* If the buffer address is in the CPM DPRAM, don't
|
||||
* convert it.
|
||||
*/
|
||||
cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
|
||||
|
||||
cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
|
||||
*cp = *s;
|
||||
|
||||
bdp->cbd_datlen = 1;
|
||||
bdp->cbd_sc |= BD_SC_READY;
|
||||
out_be16(&bdp->cbd_datlen, 1);
|
||||
setbits16(&bdp->cbd_sc, BD_SC_READY);
|
||||
|
||||
if (bdp->cbd_sc & BD_SC_WRAP)
|
||||
if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
|
||||
bdp = bdbase;
|
||||
else
|
||||
bdp++;
|
||||
|
||||
/* if a LF, also do CR... */
|
||||
if (*s == 10) {
|
||||
while ((bdp->cbd_sc & BD_SC_READY) != 0)
|
||||
while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
|
||||
;
|
||||
|
||||
cp = cpm2cpu_addr(bdp->cbd_bufaddr, pinfo);
|
||||
|
||||
cp = cpm2cpu_addr(in_be32(&bdp->cbd_bufaddr), pinfo);
|
||||
*cp = 13;
|
||||
bdp->cbd_datlen = 1;
|
||||
bdp->cbd_sc |= BD_SC_READY;
|
||||
|
||||
if (bdp->cbd_sc & BD_SC_WRAP)
|
||||
out_be16(&bdp->cbd_datlen, 1);
|
||||
setbits16(&bdp->cbd_sc, BD_SC_READY);
|
||||
|
||||
if (in_be16(&bdp->cbd_sc) & BD_SC_WRAP)
|
||||
bdp = bdbase;
|
||||
else
|
||||
bdp++;
|
||||
@@ -1146,22 +1236,56 @@ static void cpm_uart_console_write(struct console *co, const char *s,
|
||||
* Finally, Wait for transmitter & holding register to empty
|
||||
* and restore the IER
|
||||
*/
|
||||
while ((bdp->cbd_sc & BD_SC_READY) != 0)
|
||||
while ((in_be16(&bdp->cbd_sc) & BD_SC_READY) != 0)
|
||||
;
|
||||
|
||||
pinfo->tx_cur = (volatile cbd_t *) bdp;
|
||||
pinfo->tx_cur = bdp;
|
||||
}
|
||||
|
||||
|
||||
static int __init cpm_uart_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *port;
|
||||
struct uart_cpm_port *pinfo;
|
||||
int baud = 38400;
|
||||
int bits = 8;
|
||||
int parity = 'n';
|
||||
int flow = 'n';
|
||||
int ret;
|
||||
struct uart_cpm_port *pinfo;
|
||||
struct uart_port *port;
|
||||
|
||||
#ifdef CONFIG_PPC_CPM_NEW_BINDING
|
||||
struct device_node *np = NULL;
|
||||
int i = 0;
|
||||
|
||||
if (co->index >= UART_NR) {
|
||||
printk(KERN_ERR "cpm_uart: console index %d too high\n",
|
||||
co->index);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
do {
|
||||
np = of_find_node_by_type(np, "serial");
|
||||
if (!np)
|
||||
return -ENODEV;
|
||||
|
||||
if (!of_device_is_compatible(np, "fsl,cpm1-smc-uart") &&
|
||||
!of_device_is_compatible(np, "fsl,cpm1-scc-uart") &&
|
||||
!of_device_is_compatible(np, "fsl,cpm2-smc-uart") &&
|
||||
!of_device_is_compatible(np, "fsl,cpm2-scc-uart"))
|
||||
i--;
|
||||
} while (i++ != co->index);
|
||||
|
||||
pinfo = &cpm_uart_ports[co->index];
|
||||
|
||||
pinfo->flags |= FLAG_CONSOLE;
|
||||
port = &pinfo->port;
|
||||
|
||||
ret = cpm_uart_init_port(np, pinfo);
|
||||
of_node_put(np);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
#else
|
||||
|
||||
struct fs_uart_platform_info *pdata;
|
||||
struct platform_device* pdev = early_uart_get_pdev(co->index);
|
||||
@@ -1188,6 +1312,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
|
||||
}
|
||||
|
||||
pinfo->flags |= FLAG_CONSOLE;
|
||||
#endif
|
||||
|
||||
if (options) {
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
@@ -1196,12 +1321,18 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
|
||||
baud = 9600;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_PPC_EARLY_DEBUG_CPM
|
||||
udbg_putc = NULL;
|
||||
#endif
|
||||
|
||||
cpm_line_cr_cmd(pinfo, CPM_CR_STOP_TX);
|
||||
|
||||
if (IS_SMC(pinfo)) {
|
||||
pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
|
||||
pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
|
||||
clrbits8(&pinfo->smcp->smc_smcm, SMCM_RX | SMCM_TX);
|
||||
clrbits16(&pinfo->smcp->smc_smcmr, SMCMR_REN | SMCMR_TEN);
|
||||
} else {
|
||||
pinfo->sccp->scc_sccm &= ~(UART_SCCM_TX | UART_SCCM_RX);
|
||||
pinfo->sccp->scc_gsmrl &= ~(SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
clrbits16(&pinfo->sccp->scc_sccm, UART_SCCM_TX | UART_SCCM_RX);
|
||||
clrbits32(&pinfo->sccp->scc_gsmrl, SCC_GSMRL_ENR | SCC_GSMRL_ENT);
|
||||
}
|
||||
|
||||
ret = cpm_uart_allocbuf(pinfo, 1);
|
||||
@@ -1217,6 +1348,7 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
|
||||
cpm_uart_init_scc(pinfo);
|
||||
|
||||
uart_set_options(port, co, baud, parity, bits, flow);
|
||||
cpm_line_cr_cmd(pinfo, CPM_CR_RESTART_TX);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1232,7 +1364,7 @@ static struct console cpm_scc_uart_console = {
|
||||
.data = &cpm_reg,
|
||||
};
|
||||
|
||||
int __init cpm_uart_console_init(void)
|
||||
static int __init cpm_uart_console_init(void)
|
||||
{
|
||||
register_console(&cpm_scc_uart_console);
|
||||
return 0;
|
||||
@@ -1252,7 +1384,81 @@ static struct uart_driver cpm_reg = {
|
||||
.major = SERIAL_CPM_MAJOR,
|
||||
.minor = SERIAL_CPM_MINOR,
|
||||
.cons = CPM_UART_CONSOLE,
|
||||
.nr = UART_NR,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_PPC_CPM_NEW_BINDING
|
||||
static int probe_index;
|
||||
|
||||
static int __devinit cpm_uart_probe(struct of_device *ofdev,
|
||||
const struct of_device_id *match)
|
||||
{
|
||||
int index = probe_index++;
|
||||
struct uart_cpm_port *pinfo = &cpm_uart_ports[index];
|
||||
int ret;
|
||||
|
||||
pinfo->port.line = index;
|
||||
|
||||
if (index >= UART_NR)
|
||||
return -ENODEV;
|
||||
|
||||
dev_set_drvdata(&ofdev->dev, pinfo);
|
||||
|
||||
ret = cpm_uart_init_port(ofdev->node, pinfo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return uart_add_one_port(&cpm_reg, &pinfo->port);
|
||||
}
|
||||
|
||||
static int __devexit cpm_uart_remove(struct of_device *ofdev)
|
||||
{
|
||||
struct uart_cpm_port *pinfo = dev_get_drvdata(&ofdev->dev);
|
||||
return uart_remove_one_port(&cpm_reg, &pinfo->port);
|
||||
}
|
||||
|
||||
static struct of_device_id cpm_uart_match[] = {
|
||||
{
|
||||
.compatible = "fsl,cpm1-smc-uart",
|
||||
},
|
||||
{
|
||||
.compatible = "fsl,cpm1-scc-uart",
|
||||
},
|
||||
{
|
||||
.compatible = "fsl,cpm2-smc-uart",
|
||||
},
|
||||
{
|
||||
.compatible = "fsl,cpm2-scc-uart",
|
||||
},
|
||||
{}
|
||||
};
|
||||
|
||||
static struct of_platform_driver cpm_uart_driver = {
|
||||
.name = "cpm_uart",
|
||||
.match_table = cpm_uart_match,
|
||||
.probe = cpm_uart_probe,
|
||||
.remove = cpm_uart_remove,
|
||||
};
|
||||
|
||||
static int __init cpm_uart_init(void)
|
||||
{
|
||||
int ret = uart_register_driver(&cpm_reg);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = of_register_platform_driver(&cpm_uart_driver);
|
||||
if (ret)
|
||||
uart_unregister_driver(&cpm_reg);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit cpm_uart_exit(void)
|
||||
{
|
||||
of_unregister_platform_driver(&cpm_uart_driver);
|
||||
uart_unregister_driver(&cpm_reg);
|
||||
}
|
||||
#else
|
||||
static int cpm_uart_drv_probe(struct device *dev)
|
||||
{
|
||||
struct platform_device *pdev = to_platform_device(dev);
|
||||
@@ -1380,6 +1586,7 @@ static void __exit cpm_uart_exit(void)
|
||||
driver_unregister(&cpm_smc_uart_driver);
|
||||
uart_unregister_driver(&cpm_reg);
|
||||
}
|
||||
#endif
|
||||
|
||||
module_init(cpm_uart_init);
|
||||
module_exit(cpm_uart_exit);
|
||||
|
@@ -49,9 +49,20 @@
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
void cpm_line_cr_cmd(int line, int cmd)
|
||||
#ifdef CONFIG_PPC_CPM_NEW_BINDING
|
||||
void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
|
||||
{
|
||||
u16 __iomem *cpcr = &cpmp->cp_cpcr;
|
||||
|
||||
out_be16(cpcr, port->command | (cmd << 8) | CPM_CR_FLG);
|
||||
while (in_be16(cpcr) & CPM_CR_FLG)
|
||||
;
|
||||
}
|
||||
#else
|
||||
void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
|
||||
{
|
||||
ushort val;
|
||||
int line = port - cpm_uart_ports;
|
||||
volatile cpm8xx_t *cp = cpmp;
|
||||
|
||||
switch (line) {
|
||||
@@ -114,6 +125,7 @@ void scc4_lineif(struct uart_cpm_port *pinfo)
|
||||
/* XXX SCC4: insert port configuration here */
|
||||
pinfo->brg = 4;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allocate DP-Ram and memory buffers. We need to allocate a transmit and
|
||||
@@ -167,7 +179,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
|
||||
pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
|
||||
* pinfo->rx_fifosize);
|
||||
|
||||
pinfo->rx_bd_base = (volatile cbd_t *)dp_mem;
|
||||
pinfo->rx_bd_base = (cbd_t __iomem __force *)dp_mem;
|
||||
pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;
|
||||
|
||||
return 0;
|
||||
@@ -184,6 +196,7 @@ void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
|
||||
cpm_dpfree(pinfo->dp_addr);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PPC_CPM_NEW_BINDING
|
||||
/* Setup any dynamic params in the uart desc */
|
||||
int cpm_uart_init_portdesc(void)
|
||||
{
|
||||
@@ -279,3 +292,4 @@ int cpm_uart_init_portdesc(void)
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@@ -13,30 +13,32 @@
|
||||
#include <asm/commproc.h>
|
||||
|
||||
/* defines for IRQs */
|
||||
#ifndef CONFIG_PPC_CPM_NEW_BINDING
|
||||
#define SMC1_IRQ (CPM_IRQ_OFFSET + CPMVEC_SMC1)
|
||||
#define SMC2_IRQ (CPM_IRQ_OFFSET + CPMVEC_SMC2)
|
||||
#define SCC1_IRQ (CPM_IRQ_OFFSET + CPMVEC_SCC1)
|
||||
#define SCC2_IRQ (CPM_IRQ_OFFSET + CPMVEC_SCC2)
|
||||
#define SCC3_IRQ (CPM_IRQ_OFFSET + CPMVEC_SCC3)
|
||||
#define SCC4_IRQ (CPM_IRQ_OFFSET + CPMVEC_SCC4)
|
||||
#endif
|
||||
|
||||
static inline void cpm_set_brg(int brg, int baud)
|
||||
{
|
||||
cpm_setbrg(brg, baud);
|
||||
}
|
||||
|
||||
static inline void cpm_set_scc_fcr(volatile scc_uart_t * sup)
|
||||
static inline void cpm_set_scc_fcr(scc_uart_t __iomem * sup)
|
||||
{
|
||||
sup->scc_genscc.scc_rfcr = SMC_EB;
|
||||
sup->scc_genscc.scc_tfcr = SMC_EB;
|
||||
out_8(&sup->scc_genscc.scc_rfcr, SMC_EB);
|
||||
out_8(&sup->scc_genscc.scc_tfcr, SMC_EB);
|
||||
}
|
||||
|
||||
static inline void cpm_set_smc_fcr(volatile smc_uart_t * up)
|
||||
static inline void cpm_set_smc_fcr(smc_uart_t __iomem * up)
|
||||
{
|
||||
up->smc_rfcr = SMC_EB;
|
||||
up->smc_tfcr = SMC_EB;
|
||||
out_8(&up->smc_rfcr, SMC_EB);
|
||||
out_8(&up->smc_tfcr, SMC_EB);
|
||||
}
|
||||
|
||||
#define DPRAM_BASE ((unsigned char *)cpm_dpram_addr(0))
|
||||
#define DPRAM_BASE ((u8 __iomem __force *)cpm_dpram_addr(0))
|
||||
|
||||
#endif
|
||||
|
@@ -49,9 +49,22 @@
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
void cpm_line_cr_cmd(int line, int cmd)
|
||||
#ifdef CONFIG_PPC_CPM_NEW_BINDING
|
||||
void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
|
||||
{
|
||||
cpm_cpm2_t __iomem *cp = cpm2_map(im_cpm);
|
||||
|
||||
out_be32(&cp->cp_cpcr, port->command | cmd | CPM_CR_FLG);
|
||||
while (in_be32(&cp->cp_cpcr) & CPM_CR_FLG)
|
||||
;
|
||||
|
||||
cpm2_unmap(cp);
|
||||
}
|
||||
#else
|
||||
void cpm_line_cr_cmd(struct uart_cpm_port *port, int cmd)
|
||||
{
|
||||
ulong val;
|
||||
int line = port - cpm_uart_ports;
|
||||
volatile cpm_cpm2_t *cp = cpm2_map(im_cpm);
|
||||
|
||||
|
||||
@@ -211,6 +224,7 @@ void scc4_lineif(struct uart_cpm_port *pinfo)
|
||||
cpm2_unmap(cpmux);
|
||||
cpm2_unmap(io);
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Allocate DP-Ram and memory buffers. We need to allocate a transmit and
|
||||
@@ -221,7 +235,7 @@ void scc4_lineif(struct uart_cpm_port *pinfo)
|
||||
int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
|
||||
{
|
||||
int dpmemsz, memsz;
|
||||
u8 *dp_mem;
|
||||
u8 __iomem *dp_mem;
|
||||
unsigned long dp_offset;
|
||||
u8 *mem_addr;
|
||||
dma_addr_t dma_addr = 0;
|
||||
@@ -264,7 +278,7 @@ int cpm_uart_allocbuf(struct uart_cpm_port *pinfo, unsigned int is_con)
|
||||
pinfo->tx_buf = pinfo->rx_buf + L1_CACHE_ALIGN(pinfo->rx_nrfifos
|
||||
* pinfo->rx_fifosize);
|
||||
|
||||
pinfo->rx_bd_base = (volatile cbd_t *)dp_mem;
|
||||
pinfo->rx_bd_base = (cbd_t __iomem *)dp_mem;
|
||||
pinfo->tx_bd_base = pinfo->rx_bd_base + pinfo->rx_nrfifos;
|
||||
|
||||
return 0;
|
||||
@@ -275,12 +289,13 @@ void cpm_uart_freebuf(struct uart_cpm_port *pinfo)
|
||||
dma_free_coherent(NULL, L1_CACHE_ALIGN(pinfo->rx_nrfifos *
|
||||
pinfo->rx_fifosize) +
|
||||
L1_CACHE_ALIGN(pinfo->tx_nrfifos *
|
||||
pinfo->tx_fifosize), pinfo->mem_addr,
|
||||
pinfo->tx_fifosize), (void __force *)pinfo->mem_addr,
|
||||
pinfo->dma_addr);
|
||||
|
||||
cpm_dpfree(pinfo->dp_addr);
|
||||
}
|
||||
|
||||
#ifndef CONFIG_PPC_CPM_NEW_BINDING
|
||||
/* Setup any dynamic params in the uart desc */
|
||||
int cpm_uart_init_portdesc(void)
|
||||
{
|
||||
@@ -386,3 +401,4 @@ int cpm_uart_init_portdesc(void)
|
||||
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
@@ -13,30 +13,32 @@
|
||||
#include <asm/cpm2.h>
|
||||
|
||||
/* defines for IRQs */
|
||||
#ifndef CONFIG_PPC_CPM_NEW_BINDING
|
||||
#define SMC1_IRQ SIU_INT_SMC1
|
||||
#define SMC2_IRQ SIU_INT_SMC2
|
||||
#define SCC1_IRQ SIU_INT_SCC1
|
||||
#define SCC2_IRQ SIU_INT_SCC2
|
||||
#define SCC3_IRQ SIU_INT_SCC3
|
||||
#define SCC4_IRQ SIU_INT_SCC4
|
||||
#endif
|
||||
|
||||
static inline void cpm_set_brg(int brg, int baud)
|
||||
{
|
||||
cpm_setbrg(brg, baud);
|
||||
}
|
||||
|
||||
static inline void cpm_set_scc_fcr(volatile scc_uart_t * sup)
|
||||
static inline void cpm_set_scc_fcr(scc_uart_t __iomem *sup)
|
||||
{
|
||||
sup->scc_genscc.scc_rfcr = CPMFCR_GBL | CPMFCR_EB;
|
||||
sup->scc_genscc.scc_tfcr = CPMFCR_GBL | CPMFCR_EB;
|
||||
out_8(&sup->scc_genscc.scc_rfcr, CPMFCR_GBL | CPMFCR_EB);
|
||||
out_8(&sup->scc_genscc.scc_tfcr, CPMFCR_GBL | CPMFCR_EB);
|
||||
}
|
||||
|
||||
static inline void cpm_set_smc_fcr(volatile smc_uart_t * up)
|
||||
static inline void cpm_set_smc_fcr(smc_uart_t __iomem *up)
|
||||
{
|
||||
up->smc_rfcr = CPMFCR_GBL | CPMFCR_EB;
|
||||
up->smc_tfcr = CPMFCR_GBL | CPMFCR_EB;
|
||||
out_8(&up->smc_rfcr, CPMFCR_GBL | CPMFCR_EB);
|
||||
out_8(&up->smc_tfcr, CPMFCR_GBL | CPMFCR_EB);
|
||||
}
|
||||
|
||||
#define DPRAM_BASE ((unsigned char *)cpm_dpram_addr(0))
|
||||
#define DPRAM_BASE ((u8 __iomem __force *)cpm_dpram_addr(0))
|
||||
|
||||
#endif
|
||||
|
@@ -1051,7 +1051,7 @@ mpc52xx_uart_of_assign(struct device_node *np, int idx)
|
||||
/* If the slot is already occupied, then swap slots */
|
||||
if (mpc52xx_uart_nodes[idx] && (free_idx != -1))
|
||||
mpc52xx_uart_nodes[free_idx] = mpc52xx_uart_nodes[idx];
|
||||
mpc52xx_uart_nodes[i] = np;
|
||||
mpc52xx_uart_nodes[idx] = np;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@@ -88,6 +88,16 @@ MODULE_LICENSE("GPL");
|
||||
|
||||
#define PWRDBG(fmt, arg...) printk(KERN_DEBUG fmt , ## arg)
|
||||
|
||||
#ifdef CONFIG_SERIAL_PMACZILOG_TTYS
|
||||
#define PMACZILOG_MAJOR TTY_MAJOR
|
||||
#define PMACZILOG_MINOR 64
|
||||
#define PMACZILOG_NAME "ttyS"
|
||||
#else
|
||||
#define PMACZILOG_MAJOR 204
|
||||
#define PMACZILOG_MINOR 192
|
||||
#define PMACZILOG_NAME "ttyPZ"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
* For the sake of early serial console, we can do a pre-probe
|
||||
@@ -99,9 +109,10 @@ static DEFINE_MUTEX(pmz_irq_mutex);
|
||||
|
||||
static struct uart_driver pmz_uart_reg = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "ttyS",
|
||||
.dev_name = "ttyS",
|
||||
.major = TTY_MAJOR,
|
||||
.driver_name = PMACZILOG_NAME,
|
||||
.dev_name = PMACZILOG_NAME,
|
||||
.major = PMACZILOG_MAJOR,
|
||||
.minor = PMACZILOG_MINOR,
|
||||
};
|
||||
|
||||
|
||||
@@ -1587,7 +1598,7 @@ static int pmz_suspend(struct macio_dev *mdev, pm_message_t pm_state)
|
||||
if (pm_state.event == mdev->ofdev.dev.power.power_state.event)
|
||||
return 0;
|
||||
|
||||
pmz_debug("suspend, switching to state %d\n", pm_state);
|
||||
pmz_debug("suspend, switching to state %d\n", pm_state.event);
|
||||
|
||||
state = pmz_uart_reg.state + uap->port.line;
|
||||
|
||||
@@ -1778,7 +1789,7 @@ static void pmz_console_write(struct console *con, const char *s, unsigned int c
|
||||
static int __init pmz_console_setup(struct console *co, char *options);
|
||||
|
||||
static struct console pmz_console = {
|
||||
.name = "ttyS",
|
||||
.name = PMACZILOG_NAME,
|
||||
.write = pmz_console_write,
|
||||
.device = uart_console_device,
|
||||
.setup = pmz_console_setup,
|
||||
@@ -1802,7 +1813,6 @@ static int __init pmz_register(void)
|
||||
|
||||
pmz_uart_reg.nr = pmz_ports_count;
|
||||
pmz_uart_reg.cons = PMACZILOG_CONSOLE;
|
||||
pmz_uart_reg.minor = 64;
|
||||
|
||||
/*
|
||||
* Register this driver with the serial core
|
||||
|
@@ -1,7 +1,8 @@
|
||||
/*
|
||||
* uartlite.c: Serial driver for Xilinx uartlite serial controller
|
||||
*
|
||||
* Peter Korsgaard <jacmet@sunsite.dk>
|
||||
* Copyright (C) 2006 Peter Korsgaard <jacmet@sunsite.dk>
|
||||
* Copyright (C) 2007 Secret Lab Technologies Ltd.
|
||||
*
|
||||
* This file is licensed under the terms of the GNU General Public License
|
||||
* version 2. This program is licensed "as is" without any warranty of any
|
||||
@@ -17,14 +18,23 @@
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <asm/io.h>
|
||||
#if defined(CONFIG_OF)
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/of_platform.h>
|
||||
#endif
|
||||
|
||||
#define ULITE_NAME "ttyUL"
|
||||
#define ULITE_MAJOR 204
|
||||
#define ULITE_MINOR 187
|
||||
#define ULITE_NR_UARTS 4
|
||||
|
||||
/* For register details see datasheet:
|
||||
http://www.xilinx.com/bvdocs/ipcenter/data_sheet/opb_uartlite.pdf
|
||||
*/
|
||||
/* ---------------------------------------------------------------------
|
||||
* Register definitions
|
||||
*
|
||||
* For register details see datasheet:
|
||||
* http://www.xilinx.com/bvdocs/ipcenter/data_sheet/opb_uartlite.pdf
|
||||
*/
|
||||
|
||||
#define ULITE_RX 0x00
|
||||
#define ULITE_TX 0x04
|
||||
#define ULITE_STATUS 0x08
|
||||
@@ -46,7 +56,11 @@
|
||||
#define ULITE_CONTROL_IE 0x10
|
||||
|
||||
|
||||
static struct uart_port ports[ULITE_NR_UARTS];
|
||||
static struct uart_port ulite_ports[ULITE_NR_UARTS];
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Core UART driver operations
|
||||
*/
|
||||
|
||||
static int ulite_receive(struct uart_port *port, int stat)
|
||||
{
|
||||
@@ -307,6 +321,10 @@ static struct uart_ops ulite_ops = {
|
||||
.verify_port = ulite_verify_port
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Console driver operations
|
||||
*/
|
||||
|
||||
#ifdef CONFIG_SERIAL_UARTLITE_CONSOLE
|
||||
static void ulite_console_wait_tx(struct uart_port *port)
|
||||
{
|
||||
@@ -329,7 +347,7 @@ static void ulite_console_putchar(struct uart_port *port, int ch)
|
||||
static void ulite_console_write(struct console *co, const char *s,
|
||||
unsigned int count)
|
||||
{
|
||||
struct uart_port *port = &ports[co->index];
|
||||
struct uart_port *port = &ulite_ports[co->index];
|
||||
unsigned long flags;
|
||||
unsigned int ier;
|
||||
int locked = 1;
|
||||
@@ -355,6 +373,31 @@ static void ulite_console_write(struct console *co, const char *s,
|
||||
spin_unlock_irqrestore(&port->lock, flags);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_OF)
|
||||
static inline void __init ulite_console_of_find_device(int id)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct resource res;
|
||||
const unsigned int *of_id;
|
||||
int rc;
|
||||
|
||||
for_each_compatible_node(np, NULL, "xilinx,uartlite") {
|
||||
of_id = of_get_property(np, "port-number", NULL);
|
||||
if ((!of_id) || (*of_id != id))
|
||||
continue;
|
||||
|
||||
rc = of_address_to_resource(np, 0, &res);
|
||||
if (rc)
|
||||
continue;
|
||||
|
||||
ulite_ports[id].mapbase = res.start;
|
||||
return;
|
||||
}
|
||||
}
|
||||
#else /* CONFIG_OF */
|
||||
static inline void __init ulite_console_of_find_device(int id) { /* do nothing */ }
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
static int __init ulite_console_setup(struct console *co, char *options)
|
||||
{
|
||||
struct uart_port *port;
|
||||
@@ -366,11 +409,23 @@ static int __init ulite_console_setup(struct console *co, char *options)
|
||||
if (co->index < 0 || co->index >= ULITE_NR_UARTS)
|
||||
return -EINVAL;
|
||||
|
||||
port = &ports[co->index];
|
||||
port = &ulite_ports[co->index];
|
||||
|
||||
/* Check if it is an OF device */
|
||||
if (!port->mapbase)
|
||||
ulite_console_of_find_device(co->index);
|
||||
|
||||
/* Do we have a device now? */
|
||||
if (!port->mapbase) {
|
||||
pr_debug("console on ttyUL%i not present\n", co->index);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
/* not initialized yet? */
|
||||
if (!port->membase)
|
||||
return -ENODEV;
|
||||
if (!port->membase) {
|
||||
if (ulite_request_port(port))
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
if (options)
|
||||
uart_parse_options(options, &baud, &parity, &bits, &flow);
|
||||
@@ -381,7 +436,7 @@ static int __init ulite_console_setup(struct console *co, char *options)
|
||||
static struct uart_driver ulite_uart_driver;
|
||||
|
||||
static struct console ulite_console = {
|
||||
.name = "ttyUL",
|
||||
.name = ULITE_NAME,
|
||||
.write = ulite_console_write,
|
||||
.device = uart_console_device,
|
||||
.setup = ulite_console_setup,
|
||||
@@ -403,7 +458,7 @@ console_initcall(ulite_console_init);
|
||||
static struct uart_driver ulite_uart_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.driver_name = "uartlite",
|
||||
.dev_name = "ttyUL",
|
||||
.dev_name = ULITE_NAME,
|
||||
.major = ULITE_MAJOR,
|
||||
.minor = ULITE_MINOR,
|
||||
.nr = ULITE_NR_UARTS,
|
||||
@@ -412,16 +467,96 @@ static struct uart_driver ulite_uart_driver = {
|
||||
#endif
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Port assignment functions (mapping devices to uart_port structures)
|
||||
*/
|
||||
|
||||
/** ulite_assign: register a uartlite device with the driver
|
||||
*
|
||||
* @dev: pointer to device structure
|
||||
* @id: requested id number. Pass -1 for automatic port assignment
|
||||
* @base: base address of uartlite registers
|
||||
* @irq: irq number for uartlite
|
||||
*
|
||||
* Returns: 0 on success, <0 otherwise
|
||||
*/
|
||||
static int __devinit ulite_assign(struct device *dev, int id, u32 base, int irq)
|
||||
{
|
||||
struct uart_port *port;
|
||||
int rc;
|
||||
|
||||
/* if id = -1; then scan for a free id and use that */
|
||||
if (id < 0) {
|
||||
for (id = 0; id < ULITE_NR_UARTS; id++)
|
||||
if (ulite_ports[id].mapbase == 0)
|
||||
break;
|
||||
}
|
||||
if (id < 0 || id >= ULITE_NR_UARTS) {
|
||||
dev_err(dev, "%s%i too large\n", ULITE_NAME, id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if ((ulite_ports[id].mapbase) && (ulite_ports[id].mapbase != base)) {
|
||||
dev_err(dev, "cannot assign to %s%i; it is already in use\n",
|
||||
ULITE_NAME, id);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
port = &ulite_ports[id];
|
||||
|
||||
spin_lock_init(&port->lock);
|
||||
port->fifosize = 16;
|
||||
port->regshift = 2;
|
||||
port->iotype = UPIO_MEM;
|
||||
port->iobase = 1; /* mark port in use */
|
||||
port->mapbase = base;
|
||||
port->membase = NULL;
|
||||
port->ops = &ulite_ops;
|
||||
port->irq = irq;
|
||||
port->flags = UPF_BOOT_AUTOCONF;
|
||||
port->dev = dev;
|
||||
port->type = PORT_UNKNOWN;
|
||||
port->line = id;
|
||||
|
||||
dev_set_drvdata(dev, port);
|
||||
|
||||
/* Register the port */
|
||||
rc = uart_add_one_port(&ulite_uart_driver, port);
|
||||
if (rc) {
|
||||
dev_err(dev, "uart_add_one_port() failed; err=%i\n", rc);
|
||||
port->mapbase = 0;
|
||||
dev_set_drvdata(dev, NULL);
|
||||
return rc;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** ulite_release: register a uartlite device with the driver
|
||||
*
|
||||
* @dev: pointer to device structure
|
||||
*/
|
||||
static int __devinit ulite_release(struct device *dev)
|
||||
{
|
||||
struct uart_port *port = dev_get_drvdata(dev);
|
||||
int rc = 0;
|
||||
|
||||
if (port) {
|
||||
rc = uart_remove_one_port(&ulite_uart_driver, port);
|
||||
dev_set_drvdata(dev, NULL);
|
||||
port->mapbase = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Platform bus binding
|
||||
*/
|
||||
|
||||
static int __devinit ulite_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct resource *res, *res2;
|
||||
struct uart_port *port;
|
||||
|
||||
if (pdev->id < 0 || pdev->id >= ULITE_NR_UARTS)
|
||||
return -EINVAL;
|
||||
|
||||
if (ports[pdev->id].membase)
|
||||
return -EBUSY;
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res)
|
||||
@@ -431,40 +566,12 @@ static int __devinit ulite_probe(struct platform_device *pdev)
|
||||
if (!res2)
|
||||
return -ENODEV;
|
||||
|
||||
port = &ports[pdev->id];
|
||||
|
||||
port->fifosize = 16;
|
||||
port->regshift = 2;
|
||||
port->iotype = UPIO_MEM;
|
||||
port->iobase = 1; /* mark port in use */
|
||||
port->mapbase = res->start;
|
||||
port->membase = NULL;
|
||||
port->ops = &ulite_ops;
|
||||
port->irq = res2->start;
|
||||
port->flags = UPF_BOOT_AUTOCONF;
|
||||
port->dev = &pdev->dev;
|
||||
port->type = PORT_UNKNOWN;
|
||||
port->line = pdev->id;
|
||||
|
||||
uart_add_one_port(&ulite_uart_driver, port);
|
||||
platform_set_drvdata(pdev, port);
|
||||
|
||||
return 0;
|
||||
return ulite_assign(&pdev->dev, pdev->id, res->start, res2->start);
|
||||
}
|
||||
|
||||
static int ulite_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct uart_port *port = platform_get_drvdata(pdev);
|
||||
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
if (port)
|
||||
uart_remove_one_port(&ulite_uart_driver, port);
|
||||
|
||||
/* mark port as free */
|
||||
port->membase = NULL;
|
||||
|
||||
return 0;
|
||||
return ulite_release(&pdev->dev);
|
||||
}
|
||||
|
||||
static struct platform_driver ulite_platform_driver = {
|
||||
@@ -476,24 +583,109 @@ static struct platform_driver ulite_platform_driver = {
|
||||
},
|
||||
};
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* OF bus bindings
|
||||
*/
|
||||
#if defined(CONFIG_OF)
|
||||
static int __devinit
|
||||
ulite_of_probe(struct of_device *op, const struct of_device_id *match)
|
||||
{
|
||||
struct resource res;
|
||||
const unsigned int *id;
|
||||
int irq, rc;
|
||||
|
||||
dev_dbg(&op->dev, "%s(%p, %p)\n", __FUNCTION__, op, match);
|
||||
|
||||
rc = of_address_to_resource(op->node, 0, &res);
|
||||
if (rc) {
|
||||
dev_err(&op->dev, "invalid address\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
irq = irq_of_parse_and_map(op->node, 0);
|
||||
|
||||
id = of_get_property(op->node, "port-number", NULL);
|
||||
|
||||
return ulite_assign(&op->dev, id ? *id : -1, res.start+3, irq);
|
||||
}
|
||||
|
||||
static int __devexit ulite_of_remove(struct of_device *op)
|
||||
{
|
||||
return ulite_release(&op->dev);
|
||||
}
|
||||
|
||||
/* Match table for of_platform binding */
|
||||
static struct of_device_id __devinit ulite_of_match[] = {
|
||||
{ .type = "serial", .compatible = "xilinx,uartlite", },
|
||||
{},
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, ulite_of_match);
|
||||
|
||||
static struct of_platform_driver ulite_of_driver = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "uartlite",
|
||||
.match_table = ulite_of_match,
|
||||
.probe = ulite_of_probe,
|
||||
.remove = __devexit_p(ulite_of_remove),
|
||||
.driver = {
|
||||
.name = "uartlite",
|
||||
},
|
||||
};
|
||||
|
||||
/* Registration helpers to keep the number of #ifdefs to a minimum */
|
||||
static inline int __init ulite_of_register(void)
|
||||
{
|
||||
pr_debug("uartlite: calling of_register_platform_driver()\n");
|
||||
return of_register_platform_driver(&ulite_of_driver);
|
||||
}
|
||||
|
||||
static inline void __exit ulite_of_unregister(void)
|
||||
{
|
||||
of_unregister_platform_driver(&ulite_of_driver);
|
||||
}
|
||||
#else /* CONFIG_OF */
|
||||
/* CONFIG_OF not enabled; do nothing helpers */
|
||||
static inline int __init ulite_of_register(void) { return 0; }
|
||||
static inline void __exit ulite_of_unregister(void) { }
|
||||
#endif /* CONFIG_OF */
|
||||
|
||||
/* ---------------------------------------------------------------------
|
||||
* Module setup/teardown
|
||||
*/
|
||||
|
||||
int __init ulite_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
pr_debug("uartlite: calling uart_register_driver()\n");
|
||||
ret = uart_register_driver(&ulite_uart_driver);
|
||||
if (ret)
|
||||
return ret;
|
||||
goto err_uart;
|
||||
|
||||
ret = ulite_of_register();
|
||||
if (ret)
|
||||
goto err_of;
|
||||
|
||||
pr_debug("uartlite: calling platform_driver_register()\n");
|
||||
ret = platform_driver_register(&ulite_platform_driver);
|
||||
if (ret)
|
||||
uart_unregister_driver(&ulite_uart_driver);
|
||||
goto err_plat;
|
||||
|
||||
return 0;
|
||||
|
||||
err_plat:
|
||||
ulite_of_unregister();
|
||||
err_of:
|
||||
uart_unregister_driver(&ulite_uart_driver);
|
||||
err_uart:
|
||||
printk(KERN_ERR "registering uartlite driver failed: err=%i", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void __exit ulite_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&ulite_platform_driver);
|
||||
ulite_of_unregister();
|
||||
uart_unregister_driver(&ulite_uart_driver);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user