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

Commit e27987cd authored by Vitaly Bordug's avatar Vitaly Bordug Committed by Paul Mackerras
Browse files

[PATCH] ppc32 CPM_UART: Convert to use platform devices



This is intended to make the driver code more generic and flexible,
to get rid of board-specific layouts within driver, and generic rehaul,
yet keeping compatibility with the existing stuff utilizing it, being
compatible with legacy behavior (but with complaints that legacy mode
used).

Signed-off-by: default avatarVitaly Bordug <vbordug@ru.mvista.com>
Signed-off-by: default avatarPaul Mackerras <paulus@samba.org>
parent a73c87bf
Loading
Loading
Loading
Loading
+9 −7
Original line number Diff line number Diff line
@@ -10,6 +10,8 @@
#define CPM_UART_H

#include <linux/config.h>
#include <linux/platform_device.h>
#include <linux/fs_uart_pd.h>

#if defined(CONFIG_CPM2)
#include "cpm_uart_cpm2.h"
@@ -26,14 +28,14 @@
#define FLAG_SMC	0x00000002
#define FLAG_CONSOLE	0x00000001

#define UART_SMC1	0
#define UART_SMC2	1
#define UART_SCC1	2
#define UART_SCC2	3
#define UART_SCC3	4
#define UART_SCC4	5
#define UART_SMC1	fsid_smc1_uart
#define UART_SMC2	fsid_smc2_uart
#define UART_SCC1	fsid_scc1_uart
#define UART_SCC2	fsid_scc2_uart
#define UART_SCC3	fsid_scc3_uart
#define UART_SCC4	fsid_scc4_uart

#define UART_NR	6
#define UART_NR		fs_uart_nr

#define RX_NUM_FIFO	4
#define RX_BUF_SIZE	32
+211 −48
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
#include <linux/device.h>
#include <linux/bootmem.h>
#include <linux/dma-mapping.h>
#include <linux/fs_uart_pd.h>

#include <asm/io.h>
#include <asm/irq.h>
@@ -60,7 +61,7 @@
/* 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;
int cpm_uart_nr = 0;

/**************************************************************/

@@ -85,6 +86,37 @@ static inline void *cpm2cpu_addr(unsigned long addr)
	return bus_to_virt(addr);
}

/* Place-holder for board-specific stuff */
struct platform_device* __attribute__ ((weak)) __init
early_uart_get_pdev(int index)
{
	return NULL;
}


void cpm_uart_count(void)
{
	cpm_uart_nr = 0;
#ifdef CONFIG_SERIAL_CPM_SMC1
	cpm_uart_port_map[cpm_uart_nr++] = UART_SMC1;
#endif
#ifdef CONFIG_SERIAL_CPM_SMC2
	cpm_uart_port_map[cpm_uart_nr++] = UART_SMC2;
#endif
#ifdef CONFIG_SERIAL_CPM_SCC1
	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC1;
#endif
#ifdef CONFIG_SERIAL_CPM_SCC2
	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC2;
#endif
#ifdef CONFIG_SERIAL_CPM_SCC3
	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC3;
#endif
#ifdef CONFIG_SERIAL_CPM_SCC4
	cpm_uart_port_map[cpm_uart_nr++] = UART_SCC4;
#endif
}

/*
 * Check, if transmit buffers are processed
*/
@@ -829,14 +861,6 @@ static int cpm_uart_request_port(struct uart_port *port)
	if (pinfo->flags & FLAG_CONSOLE)
		return 0;

	/*
	 * Setup any port IO, connect any baud rate generators,
	 * etc.  This is expected to be handled by board
	 * dependant code
	 */
	if (pinfo->set_lineif)
		pinfo->set_lineif(pinfo);

	if (IS_SMC(pinfo)) {
		pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
		pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
@@ -988,6 +1012,54 @@ struct uart_cpm_port cpm_uart_ports[UART_NR] = {
	},
};

int cpm_uart_drv_get_platform_data(struct platform_device *pdev, int is_con)
{
	struct resource *r;
	struct fs_uart_platform_info *pdata = pdev->dev.platform_data;
	int idx = pdata->fs_no;	/* It is UART_SMCx or UART_SCCx index */
	struct uart_cpm_port *pinfo;
	int line;
	u32 mem, pram;

	for (line=0; line<UART_NR && cpm_uart_port_map[line]!=pdata->fs_no; line++);

	pinfo = (struct uart_cpm_port *) &cpm_uart_ports[idx];

	pinfo->brg = pdata->brg;

	if (!is_con) {
		pinfo->port.line = line;
		pinfo->port.flags = UPF_BOOT_AUTOCONF;
	}

	if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs")))
		return -EINVAL;
	mem = r->start;

	if (!(r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "pram")))
		return -EINVAL;
	pram = r->start;

	if(idx > fsid_smc2_uart) {
		pinfo->sccp = (scc_t *)mem;
		pinfo->sccup = (scc_uart_t *)pram;
	} else {
		pinfo->smcp = (smc_t *)mem;
		pinfo->smcup = (smc_uart_t *)pram;
	}
	pinfo->tx_nrfifos = pdata->tx_num_fifo;
	pinfo->tx_fifosize = pdata->tx_buf_size;

	pinfo->rx_nrfifos = pdata->rx_num_fifo;
	pinfo->rx_fifosize = pdata->rx_buf_size;

	pinfo->port.uartclk = pdata->uart_clk;
	pinfo->port.mapbase = (unsigned long)mem;
	pinfo->port.irq = platform_get_irq(pdev, 0);

	return 0;
}

#ifdef CONFIG_SERIAL_CPM_CONSOLE
/*
 *	Print a string to the serial port trying not to disturb
@@ -1067,9 +1139,7 @@ static void cpm_uart_console_write(struct console *co, const char *s,
	pinfo->tx_cur = (volatile cbd_t *) bdp;
}

/*
 * Setup console. Be careful is called early !
 */

static int __init cpm_uart_console_setup(struct console *co, char *options)
{
	struct uart_port *port;
@@ -1080,9 +1150,27 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
	int flow = 'n';
	int ret;

	struct fs_uart_platform_info *pdata;
	struct platform_device* pdev = early_uart_get_pdev(co->index);

	port =
	    (struct uart_port *)&cpm_uart_ports[cpm_uart_port_map[co->index]];
	pinfo = (struct uart_cpm_port *)port;
	if (!pdev) {
		pr_info("cpm_uart: console: compat mode\n");
		/* compatibility - will be cleaned up */
		cpm_uart_init_portdesc();

		if (pinfo->set_lineif)
			pinfo->set_lineif(pinfo);
	} else {
		pdata = pdev->dev.platform_data;
		if (pdata)
			if (pdata->init_ioports)
    	                	pdata->init_ioports();

		cpm_uart_drv_get_platform_data(pdev, 1);
	}

	pinfo->flags |= FLAG_CONSOLE;

@@ -1097,14 +1185,6 @@ static int __init cpm_uart_console_setup(struct console *co, char *options)
			baud = 9600;
	}

	/*
	 * Setup any port IO, connect any baud rate generators,
	 * etc.  This is expected to be handled by board
	 * dependant code
	 */
	if (pinfo->set_lineif)
		pinfo->set_lineif(pinfo);

	if (IS_SMC(pinfo)) {
		pinfo->smcp->smc_smcm &= ~(SMCM_RX | SMCM_TX);
		pinfo->smcp->smc_smcmr &= ~(SMCMR_REN | SMCMR_TEN);
@@ -1143,11 +1223,8 @@ static struct console cpm_scc_uart_console = {

int __init cpm_uart_console_init(void)
{
	int ret = cpm_uart_init_portdesc();

	if (!ret)
	register_console(&cpm_scc_uart_console);
	return ret;
	return 0;
}

console_initcall(cpm_uart_console_init);
@@ -1165,13 +1242,103 @@ static struct uart_driver cpm_reg = {
	.minor		= SERIAL_CPM_MINOR,
	.cons		= CPM_UART_CONSOLE,
};
static int cpm_uart_drv_probe(struct device *dev)
{
	struct platform_device  *pdev = to_platform_device(dev);
	struct fs_uart_platform_info *pdata;
	int ret = -ENODEV;

	if(!pdev) {
		printk(KERN_ERR"CPM UART: platform data missing!\n");
		return ret;
	}

	pdata = pdev->dev.platform_data;
	pr_debug("cpm_uart_drv_probe: Adding CPM UART %d\n",
			cpm_uart_port_map[pdata->fs_no]);

	if ((ret = cpm_uart_drv_get_platform_data(pdev, 0)))
		return ret;

	if (pdata->init_ioports)
                pdata->init_ioports();

	ret = uart_add_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);

        return ret;
}

static int __init cpm_uart_init(void)
static int cpm_uart_drv_remove(struct device *dev)
{
	int ret, i;
	struct platform_device  *pdev = to_platform_device(dev);
	struct fs_uart_platform_info *pdata = pdev->dev.platform_data;

	pr_debug("cpm_uart_drv_remove: Removing CPM UART %d\n",
			cpm_uart_port_map[pdata->fs_no]);

	printk(KERN_INFO "Serial: CPM driver $Revision: 0.01 $\n");
        uart_remove_one_port(&cpm_reg, &cpm_uart_ports[pdata->fs_no].port);
        return 0;
}

static struct device_driver cpm_smc_uart_driver = {
        .name   = "fsl-cpm-smc:uart",
        .bus    = &platform_bus_type,
        .probe  = cpm_uart_drv_probe,
        .remove = cpm_uart_drv_remove,
};

static struct device_driver cpm_scc_uart_driver = {
        .name   = "fsl-cpm-scc:uart",
        .bus    = &platform_bus_type,
        .probe  = cpm_uart_drv_probe,
        .remove = cpm_uart_drv_remove,
};

/*
   This is supposed to match uart devices on platform bus,
   */
static int match_is_uart (struct device* dev, void* data)
{
	struct platform_device* pdev = container_of(dev, struct platform_device, dev);
	int ret = 0;
	/* this was setfunc as uart */
	if(strstr(pdev->name,":uart")) {
		ret = 1;
	}
	return ret;
}


static int cpm_uart_init(void) {

	int ret;
	int i;
	struct device *dev;
	printk(KERN_INFO "Serial: CPM driver $Revision: 0.02 $\n");

	/* lookup the bus for uart devices */
	dev = bus_find_device(&platform_bus_type, NULL, 0, match_is_uart);

	/* There are devices on the bus - all should be OK  */
	if (dev) {
		cpm_uart_count();
		cpm_reg.nr = cpm_uart_nr;

		if (!(ret = uart_register_driver(&cpm_reg))) {
			if ((ret = driver_register(&cpm_smc_uart_driver))) {
				uart_unregister_driver(&cpm_reg);
				return ret;
			}
			if ((ret = driver_register(&cpm_scc_uart_driver))) {
				driver_unregister(&cpm_scc_uart_driver);
				uart_unregister_driver(&cpm_reg);
			}
		}
	} else {
	/* No capable platform devices found - falling back to legacy mode */
		pr_info("cpm_uart: WARNING: no UART devices found on platform bus!\n");
		pr_info(
		"cpm_uart: the driver will guess configuration, but this mode is no longer supported.\n");
#ifndef CONFIG_SERIAL_CPM_CONSOLE
		ret = cpm_uart_init_portdesc();
		if (ret)
@@ -1191,18 +1358,14 @@ static int __init cpm_uart_init(void)
			uart_add_one_port(&cpm_reg, &cpm_uart_ports[con].port);
		}

	}
	return ret;
}

static void __exit cpm_uart_exit(void)
{
	int i;

	for (i = 0; i < cpm_uart_nr; i++) {
		int con = cpm_uart_port_map[i];
		uart_remove_one_port(&cpm_reg, &cpm_uart_ports[con].port);
	}

	driver_unregister(&cpm_scc_uart_driver);
	driver_unregister(&cpm_smc_uart_driver);
	uart_unregister_driver(&cpm_reg);
}

+0 −47
Original line number Diff line number Diff line
@@ -81,58 +81,11 @@ void cpm_line_cr_cmd(int line, int cmd)

void smc1_lineif(struct uart_cpm_port *pinfo)
{
	volatile cpm8xx_t *cp = cpmp;

	(void)cp;	/* fix warning */
#if defined (CONFIG_MPC885ADS)
	/* Enable SMC1 transceivers */
	{
		cp->cp_pepar |= 0x000000c0;
		cp->cp_pedir &= ~0x000000c0;
		cp->cp_peso &= ~0x00000040;
		cp->cp_peso |= 0x00000080;
	}
#elif defined (CONFIG_MPC86XADS)
	unsigned int iobits = 0x000000c0;

	if (!pinfo->is_portb) {
		cp->cp_pbpar |= iobits;
		cp->cp_pbdir &= ~iobits;
		cp->cp_pbodr &= ~iobits;
	} else {
		((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits;
		((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
		((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
	}
#endif
	pinfo->brg = 1;
}

void smc2_lineif(struct uart_cpm_port *pinfo)
{
	volatile cpm8xx_t *cp = cpmp;

	(void)cp;	/* fix warning */
#if defined (CONFIG_MPC885ADS)
	cp->cp_pepar |= 0x00000c00;
	cp->cp_pedir &= ~0x00000c00;
	cp->cp_peso &= ~0x00000400;
	cp->cp_peso |= 0x00000800;
#elif defined (CONFIG_MPC86XADS)
	unsigned int iobits = 0x00000c00;

	if (!pinfo->is_portb) {
		cp->cp_pbpar |= iobits;
		cp->cp_pbdir &= ~iobits;
		cp->cp_pbodr &= ~iobits;
	} else {
		((immap_t *)IMAP_ADDR)->im_ioport.iop_papar |= iobits;
		((immap_t *)IMAP_ADDR)->im_ioport.iop_padir &= ~iobits;
		((immap_t *)IMAP_ADDR)->im_ioport.iop_paodr &= ~iobits;
	}

#endif

	pinfo->brg = 2;
}

+0 −9
Original line number Diff line number Diff line
@@ -142,21 +142,12 @@ void scc2_lineif(struct uart_cpm_port *pinfo)
	 * be supported in a sane fashion.
	 */
#ifndef CONFIG_STX_GP3
#ifdef CONFIG_MPC8560_ADS
	volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
	io->iop_ppard |= 0x00000018;
	io->iop_psord &= ~0x00000008;	/* Rx */
	io->iop_psord &= ~0x00000010;	/* Tx */
	io->iop_pdird &= ~0x00000008;	/* Rx */
	io->iop_pdird |= 0x00000010;	/* Tx */
#else
	volatile iop_cpm2_t *io = &cpm2_immr->im_ioport;
	io->iop_pparb |= 0x008b0000;
	io->iop_pdirb |= 0x00880000;
	io->iop_psorb |= 0x00880000;
	io->iop_pdirb &= ~0x00030000;
	io->iop_psorb &= ~0x00030000;
#endif
#endif
	cpm2_immr->im_cpmux.cmx_scr &= 0xff00ffff;
	cpm2_immr->im_cpmux.cmx_scr |= 0x00090000;