123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- /*
- * udbg serial input/output routines for the Marvell MV64x60 (Discovery).
- *
- * Author: Dale Farnsworth <dale@farnsworth.org>
- *
- * 2007 (c) MontaVista Software, Inc. 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 kind, whether express
- * or implied.
- */
- #include <asm/io.h>
- #include <asm/prom.h>
- #include <asm/udbg.h>
- #include <sysdev/mv64x60.h>
- #define MPSC_0_CR1_OFFSET 0x000c
- #define MPSC_0_CR2_OFFSET 0x0010
- #define MPSC_CHR_2_TCS (1 << 9)
- #define MPSC_0_CHR_10_OFFSET 0x0030
- #define MPSC_INTR_CAUSE_OFF_0 0x0004
- #define MPSC_INTR_CAUSE_OFF_1 0x000c
- #define MPSC_INTR_CAUSE_RCC (1<<6)
- static void __iomem *mpsc_base;
- static void __iomem *mpsc_intr_cause;
- static void mv64x60_udbg_putc(char c)
- {
- if (c == '\n')
- mv64x60_udbg_putc('\r');
- while(in_le32(mpsc_base + MPSC_0_CR2_OFFSET) & MPSC_CHR_2_TCS)
- ;
- out_le32(mpsc_base + MPSC_0_CR1_OFFSET, c);
- out_le32(mpsc_base + MPSC_0_CR2_OFFSET, MPSC_CHR_2_TCS);
- }
- static int mv64x60_udbg_testc(void)
- {
- return (in_le32(mpsc_intr_cause) & MPSC_INTR_CAUSE_RCC) != 0;
- }
- static int mv64x60_udbg_getc(void)
- {
- int cause = 0;
- int c;
- while (!mv64x60_udbg_testc())
- ;
- c = in_8(mpsc_base + MPSC_0_CHR_10_OFFSET + 2);
- out_8(mpsc_base + MPSC_0_CHR_10_OFFSET + 2, c);
- out_le32(mpsc_intr_cause, cause & ~MPSC_INTR_CAUSE_RCC);
- return c;
- }
- static int mv64x60_udbg_getc_poll(void)
- {
- if (!mv64x60_udbg_testc())
- return -1;
- return mv64x60_udbg_getc();
- }
- static void mv64x60_udbg_init(void)
- {
- struct device_node *np, *mpscintr, *stdout = NULL;
- const char *path;
- const phandle *ph;
- struct resource r[2];
- const int *block_index;
- int intr_cause_offset;
- int err;
- path = of_get_property(of_chosen, "linux,stdout-path", NULL);
- if (!path)
- return;
- stdout = of_find_node_by_path(path);
- if (!stdout)
- return;
- for_each_compatible_node(np, NULL, "marvell,mv64360-mpsc") {
- if (np == stdout)
- break;
- }
- of_node_put(stdout);
- if (!np)
- return;
- block_index = of_get_property(np, "cell-index", NULL);
- if (!block_index)
- goto error;
- switch (*block_index) {
- case 0:
- intr_cause_offset = MPSC_INTR_CAUSE_OFF_0;
- break;
- case 1:
- intr_cause_offset = MPSC_INTR_CAUSE_OFF_1;
- break;
- default:
- goto error;
- }
- err = of_address_to_resource(np, 0, &r[0]);
- if (err)
- goto error;
- ph = of_get_property(np, "mpscintr", NULL);
- mpscintr = of_find_node_by_phandle(*ph);
- if (!mpscintr)
- goto error;
- err = of_address_to_resource(mpscintr, 0, &r[1]);
- of_node_put(mpscintr);
- if (err)
- goto error;
- of_node_put(np);
- mpsc_base = ioremap(r[0].start, resource_size(&r[0]));
- if (!mpsc_base)
- return;
- mpsc_intr_cause = ioremap(r[1].start, resource_size(&r[1]));
- if (!mpsc_intr_cause) {
- iounmap(mpsc_base);
- return;
- }
- mpsc_intr_cause += intr_cause_offset;
- udbg_putc = mv64x60_udbg_putc;
- udbg_getc = mv64x60_udbg_getc;
- udbg_getc_poll = mv64x60_udbg_getc_poll;
- return;
- error:
- of_node_put(np);
- }
- void mv64x60_init_early(void)
- {
- mv64x60_udbg_init();
- }
|