root/arch/powerpc/platforms/powermac/udbg_scc.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. udbg_scc_putc
  2. udbg_scc_getc_poll
  3. udbg_scc_getc
  4. udbg_scc_init
  5. udbg_real_scc_putc
  6. udbg_init_pmac_realmode

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * udbg for zilog scc ports as found on Apple PowerMacs
   4  *
   5  * Copyright (C) 2001-2005 PPC 64 Team, IBM Corp
   6  */
   7 #include <linux/types.h>
   8 #include <asm/udbg.h>
   9 #include <asm/processor.h>
  10 #include <asm/io.h>
  11 #include <asm/prom.h>
  12 #include <asm/pmac_feature.h>
  13 
  14 extern u8 real_readb(volatile u8 __iomem  *addr);
  15 extern void real_writeb(u8 data, volatile u8 __iomem *addr);
  16 
  17 #define SCC_TXRDY       4
  18 #define SCC_RXRDY       1
  19 
  20 static volatile u8 __iomem *sccc;
  21 static volatile u8 __iomem *sccd;
  22 
  23 static void udbg_scc_putc(char c)
  24 {
  25         if (sccc) {
  26                 while ((in_8(sccc) & SCC_TXRDY) == 0)
  27                         ;
  28                 out_8(sccd,  c);
  29                 if (c == '\n')
  30                         udbg_scc_putc('\r');
  31         }
  32 }
  33 
  34 static int udbg_scc_getc_poll(void)
  35 {
  36         if (sccc) {
  37                 if ((in_8(sccc) & SCC_RXRDY) != 0)
  38                         return in_8(sccd);
  39                 else
  40                         return -1;
  41         }
  42         return -1;
  43 }
  44 
  45 static int udbg_scc_getc(void)
  46 {
  47         if (sccc) {
  48                 while ((in_8(sccc) & SCC_RXRDY) == 0)
  49                         ;
  50                 return in_8(sccd);
  51         }
  52         return -1;
  53 }
  54 
  55 static unsigned char scc_inittab[] = {
  56     13, 0,              /* set baud rate divisor */
  57     12, 0,
  58     14, 1,              /* baud rate gen enable, src=rtxc */
  59     11, 0x50,           /* clocks = br gen */
  60     5,  0xea,           /* tx 8 bits, assert DTR & RTS */
  61     4,  0x46,           /* x16 clock, 1 stop */
  62     3,  0xc1,           /* rx enable, 8 bits */
  63 };
  64 
  65 void udbg_scc_init(int force_scc)
  66 {
  67         const u32 *reg;
  68         unsigned long addr;
  69         struct device_node *stdout = NULL, *escc = NULL, *macio = NULL;
  70         struct device_node *ch, *ch_def = NULL, *ch_a = NULL;
  71         const char *path;
  72         int i;
  73 
  74         escc = of_find_node_by_name(NULL, "escc");
  75         if (escc == NULL)
  76                 goto bail;
  77         macio = of_get_parent(escc);
  78         if (macio == NULL)
  79                 goto bail;
  80         path = of_get_property(of_chosen, "linux,stdout-path", NULL);
  81         if (path != NULL)
  82                 stdout = of_find_node_by_path(path);
  83         for (ch = NULL; (ch = of_get_next_child(escc, ch)) != NULL;) {
  84                 if (ch == stdout)
  85                         ch_def = of_node_get(ch);
  86                 if (of_node_name_eq(ch, "ch-a"))
  87                         ch_a = of_node_get(ch);
  88         }
  89         if (ch_def == NULL && !force_scc)
  90                 goto bail;
  91 
  92         ch = ch_def ? ch_def : ch_a;
  93 
  94         /* Get address within mac-io ASIC */
  95         reg = of_get_property(escc, "reg", NULL);
  96         if (reg == NULL)
  97                 goto bail;
  98         addr = reg[0];
  99 
 100         /* Get address of mac-io PCI itself */
 101         reg = of_get_property(macio, "assigned-addresses", NULL);
 102         if (reg == NULL)
 103                 goto bail;
 104         addr += reg[2];
 105 
 106         /* Lock the serial port */
 107         pmac_call_feature(PMAC_FTR_SCC_ENABLE, ch,
 108                           PMAC_SCC_ASYNC | PMAC_SCC_FLAG_XMON, 1);
 109 
 110         if (ch == ch_a)
 111                 addr += 0x20;
 112         sccc = ioremap(addr & PAGE_MASK, PAGE_SIZE) ;
 113         sccc += addr & ~PAGE_MASK;
 114         sccd = sccc + 0x10;
 115 
 116         mb();
 117 
 118         for (i = 20000; i != 0; --i)
 119                 in_8(sccc);
 120         out_8(sccc, 0x09);              /* reset A or B side */
 121         out_8(sccc, 0xc0);
 122 
 123         /* If SCC was the OF output port, read the BRG value, else
 124          * Setup for 38400 or 57600 8N1 depending on the machine
 125          */
 126         if (ch_def != NULL) {
 127                 out_8(sccc, 13);
 128                 scc_inittab[1] = in_8(sccc);
 129                 out_8(sccc, 12);
 130                 scc_inittab[3] = in_8(sccc);
 131         } else if (of_machine_is_compatible("RackMac1,1")
 132                    || of_machine_is_compatible("RackMac1,2")
 133                    || of_machine_is_compatible("MacRISC4")) {
 134                 /* Xserves and G5s default to 57600 */
 135                 scc_inittab[1] = 0;
 136                 scc_inittab[3] = 0;
 137         } else {
 138                 /* Others default to 38400 */
 139                 scc_inittab[1] = 0;
 140                 scc_inittab[3] = 1;
 141         }
 142 
 143         for (i = 0; i < sizeof(scc_inittab); ++i)
 144                 out_8(sccc, scc_inittab[i]);
 145 
 146 
 147         udbg_putc = udbg_scc_putc;
 148         udbg_getc = udbg_scc_getc;
 149         udbg_getc_poll = udbg_scc_getc_poll;
 150 
 151         udbg_puts("Hello World !\n");
 152 
 153  bail:
 154         of_node_put(macio);
 155         of_node_put(escc);
 156         of_node_put(stdout);
 157         of_node_put(ch_def);
 158         of_node_put(ch_a);
 159 }
 160 
 161 #ifdef CONFIG_PPC64
 162 static void udbg_real_scc_putc(char c)
 163 {
 164         while ((real_readb(sccc) & SCC_TXRDY) == 0)
 165                 ;
 166         real_writeb(c, sccd);
 167         if (c == '\n')
 168                 udbg_real_scc_putc('\r');
 169 }
 170 
 171 void __init udbg_init_pmac_realmode(void)
 172 {
 173         sccc = (volatile u8 __iomem *)0x80013020ul;
 174         sccd = (volatile u8 __iomem *)0x80013030ul;
 175 
 176         udbg_putc = udbg_real_scc_putc;
 177         udbg_getc = NULL;
 178         udbg_getc_poll = NULL;
 179 }
 180 #endif /* CONFIG_PPC64 */

/* [<][>][^][v][top][bottom][index][help] */