root/arch/powerpc/kernel/udbg_16550.c

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

DEFINITIONS

This source file includes following definitions.
  1. udbg_uart_flush
  2. udbg_uart_putc
  3. udbg_uart_getc_poll
  4. udbg_uart_getc
  5. udbg_use_uart
  6. udbg_uart_setup
  7. udbg_probe_uart_speed
  8. udbg_uart_in_pio
  9. udbg_uart_out_pio
  10. udbg_uart_init_pio
  11. udbg_uart_in_mmio
  12. udbg_uart_out_mmio
  13. udbg_uart_init_mmio
  14. udbg_uart_in_maple
  15. udbg_uart_out_maple
  16. udbg_init_maple_realmode
  17. udbg_uart_in_pas
  18. udbg_uart_out_pas
  19. udbg_init_pas_realmode
  20. udbg_uart_in_44x_as1
  21. udbg_uart_out_44x_as1
  22. udbg_init_44x_as1
  23. udbg_uart_in_40x
  24. udbg_uart_out_40x
  25. udbg_init_40x_realmode

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * udbg for NS16550 compatible serial ports
   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/io.h>
  10 #include <asm/reg_a2.h>
  11 
  12 extern u8 real_readb(volatile u8 __iomem  *addr);
  13 extern void real_writeb(u8 data, volatile u8 __iomem *addr);
  14 extern u8 real_205_readb(volatile u8 __iomem  *addr);
  15 extern void real_205_writeb(u8 data, volatile u8 __iomem *addr);
  16 
  17 #define UART_RBR        0
  18 #define UART_IER        1
  19 #define UART_FCR        2
  20 #define UART_LCR        3
  21 #define UART_MCR        4
  22 #define UART_LSR        5
  23 #define UART_MSR        6
  24 #define UART_SCR        7
  25 #define UART_THR        UART_RBR
  26 #define UART_IIR        UART_FCR
  27 #define UART_DLL        UART_RBR
  28 #define UART_DLM        UART_IER
  29 #define UART_DLAB       UART_LCR
  30 
  31 #define LSR_DR   0x01  /* Data ready */
  32 #define LSR_OE   0x02  /* Overrun */
  33 #define LSR_PE   0x04  /* Parity error */
  34 #define LSR_FE   0x08  /* Framing error */
  35 #define LSR_BI   0x10  /* Break */
  36 #define LSR_THRE 0x20  /* Xmit holding register empty */
  37 #define LSR_TEMT 0x40  /* Xmitter empty */
  38 #define LSR_ERR  0x80  /* Error */
  39 
  40 #define LCR_DLAB 0x80
  41 
  42 static u8 (*udbg_uart_in)(unsigned int reg);
  43 static void (*udbg_uart_out)(unsigned int reg, u8 data);
  44 
  45 static void udbg_uart_flush(void)
  46 {
  47         if (!udbg_uart_in)
  48                 return;
  49 
  50         /* wait for idle */
  51         while ((udbg_uart_in(UART_LSR) & LSR_THRE) == 0)
  52                 cpu_relax();
  53 }
  54 
  55 static void udbg_uart_putc(char c)
  56 {
  57         if (!udbg_uart_out)
  58                 return;
  59 
  60         if (c == '\n')
  61                 udbg_uart_putc('\r');
  62         udbg_uart_flush();
  63         udbg_uart_out(UART_THR, c);
  64 }
  65 
  66 static int udbg_uart_getc_poll(void)
  67 {
  68         if (!udbg_uart_in)
  69                 return -1;
  70 
  71         if (!(udbg_uart_in(UART_LSR) & LSR_DR))
  72                 return udbg_uart_in(UART_RBR);
  73 
  74         return -1;
  75 }
  76 
  77 static int udbg_uart_getc(void)
  78 {
  79         if (!udbg_uart_in)
  80                 return -1;
  81         /* wait for char */
  82         while (!(udbg_uart_in(UART_LSR) & LSR_DR))
  83                 cpu_relax();
  84         return udbg_uart_in(UART_RBR);
  85 }
  86 
  87 static void udbg_use_uart(void)
  88 {
  89         udbg_putc = udbg_uart_putc;
  90         udbg_flush = udbg_uart_flush;
  91         udbg_getc = udbg_uart_getc;
  92         udbg_getc_poll = udbg_uart_getc_poll;
  93 }
  94 
  95 void udbg_uart_setup(unsigned int speed, unsigned int clock)
  96 {
  97         unsigned int dll, base_bauds;
  98 
  99         if (!udbg_uart_out)
 100                 return;
 101 
 102         if (clock == 0)
 103                 clock = 1843200;
 104         if (speed == 0)
 105                 speed = 9600;
 106 
 107         base_bauds = clock / 16;
 108         dll = base_bauds / speed;
 109 
 110         udbg_uart_out(UART_LCR, 0x00);
 111         udbg_uart_out(UART_IER, 0xff);
 112         udbg_uart_out(UART_IER, 0x00);
 113         udbg_uart_out(UART_LCR, LCR_DLAB);
 114         udbg_uart_out(UART_DLL, dll & 0xff);
 115         udbg_uart_out(UART_DLM, dll >> 8);
 116         /* 8 data, 1 stop, no parity */
 117         udbg_uart_out(UART_LCR, 0x3);
 118         /* RTS/DTR */
 119         udbg_uart_out(UART_MCR, 0x3);
 120         /* Clear & enable FIFOs */
 121         udbg_uart_out(UART_FCR, 0x7);
 122 }
 123 
 124 unsigned int udbg_probe_uart_speed(unsigned int clock)
 125 {
 126         unsigned int dll, dlm, divisor, prescaler, speed;
 127         u8 old_lcr;
 128 
 129         old_lcr = udbg_uart_in(UART_LCR);
 130 
 131         /* select divisor latch registers.  */
 132         udbg_uart_out(UART_LCR, old_lcr | LCR_DLAB);
 133 
 134         /* now, read the divisor */
 135         dll = udbg_uart_in(UART_DLL);
 136         dlm = udbg_uart_in(UART_DLM);
 137         divisor = dlm << 8 | dll;
 138 
 139         /* check prescaling */
 140         if (udbg_uart_in(UART_MCR) & 0x80)
 141                 prescaler = 4;
 142         else
 143                 prescaler = 1;
 144 
 145         /* restore the LCR */
 146         udbg_uart_out(UART_LCR, old_lcr);
 147 
 148         /* calculate speed */
 149         speed = (clock / prescaler) / (divisor * 16);
 150 
 151         /* sanity check */
 152         if (speed > (clock / 16))
 153                 speed = 9600;
 154 
 155         return speed;
 156 }
 157 
 158 static union {
 159         unsigned char __iomem *mmio_base;
 160         unsigned long pio_base;
 161 } udbg_uart;
 162 
 163 static unsigned int udbg_uart_stride = 1;
 164 
 165 static u8 udbg_uart_in_pio(unsigned int reg)
 166 {
 167         return inb(udbg_uart.pio_base + (reg * udbg_uart_stride));
 168 }
 169 
 170 static void udbg_uart_out_pio(unsigned int reg, u8 data)
 171 {
 172         outb(data, udbg_uart.pio_base + (reg * udbg_uart_stride));
 173 }
 174 
 175 void udbg_uart_init_pio(unsigned long port, unsigned int stride)
 176 {
 177         if (!port)
 178                 return;
 179         udbg_uart.pio_base = port;
 180         udbg_uart_stride = stride;
 181         udbg_uart_in = udbg_uart_in_pio;
 182         udbg_uart_out = udbg_uart_out_pio;
 183         udbg_use_uart();
 184 }
 185 
 186 static u8 udbg_uart_in_mmio(unsigned int reg)
 187 {
 188         return in_8(udbg_uart.mmio_base + (reg * udbg_uart_stride));
 189 }
 190 
 191 static void udbg_uart_out_mmio(unsigned int reg, u8 data)
 192 {
 193         out_8(udbg_uart.mmio_base + (reg * udbg_uart_stride), data);
 194 }
 195 
 196 
 197 void udbg_uart_init_mmio(void __iomem *addr, unsigned int stride)
 198 {
 199         if (!addr)
 200                 return;
 201         udbg_uart.mmio_base = addr;
 202         udbg_uart_stride = stride;
 203         udbg_uart_in = udbg_uart_in_mmio;
 204         udbg_uart_out = udbg_uart_out_mmio;
 205         udbg_use_uart();
 206 }
 207 
 208 #ifdef CONFIG_PPC_MAPLE
 209 
 210 #define UDBG_UART_MAPLE_ADDR    ((void __iomem *)0xf40003f8)
 211 
 212 static u8 udbg_uart_in_maple(unsigned int reg)
 213 {
 214         return real_readb(UDBG_UART_MAPLE_ADDR + reg);
 215 }
 216 
 217 static void udbg_uart_out_maple(unsigned int reg, u8 val)
 218 {
 219         real_writeb(val, UDBG_UART_MAPLE_ADDR + reg);
 220 }
 221 
 222 void __init udbg_init_maple_realmode(void)
 223 {
 224         udbg_uart_in = udbg_uart_in_maple;
 225         udbg_uart_out = udbg_uart_out_maple;
 226         udbg_use_uart();
 227 }
 228 
 229 #endif /* CONFIG_PPC_MAPLE */
 230 
 231 #ifdef CONFIG_PPC_PASEMI
 232 
 233 #define UDBG_UART_PAS_ADDR      ((void __iomem *)0xfcff03f8UL)
 234 
 235 static u8 udbg_uart_in_pas(unsigned int reg)
 236 {
 237         return real_205_readb(UDBG_UART_PAS_ADDR + reg);
 238 }
 239 
 240 static void udbg_uart_out_pas(unsigned int reg, u8 val)
 241 {
 242         real_205_writeb(val, UDBG_UART_PAS_ADDR + reg);
 243 }
 244 
 245 void __init udbg_init_pas_realmode(void)
 246 {
 247         udbg_uart_in = udbg_uart_in_pas;
 248         udbg_uart_out = udbg_uart_out_pas;
 249         udbg_use_uart();
 250 }
 251 
 252 #endif /* CONFIG_PPC_PASEMI */
 253 
 254 #ifdef CONFIG_PPC_EARLY_DEBUG_44x
 255 
 256 #include <platforms/44x/44x.h>
 257 
 258 static u8 udbg_uart_in_44x_as1(unsigned int reg)
 259 {
 260         return as1_readb((void __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR + reg);
 261 }
 262 
 263 static void udbg_uart_out_44x_as1(unsigned int reg, u8 val)
 264 {
 265         as1_writeb(val, (void __iomem *)PPC44x_EARLY_DEBUG_VIRTADDR + reg);
 266 }
 267 
 268 void __init udbg_init_44x_as1(void)
 269 {
 270         udbg_uart_in = udbg_uart_in_44x_as1;
 271         udbg_uart_out = udbg_uart_out_44x_as1;
 272         udbg_use_uart();
 273 }
 274 
 275 #endif /* CONFIG_PPC_EARLY_DEBUG_44x */
 276 
 277 #ifdef CONFIG_PPC_EARLY_DEBUG_40x
 278 
 279 static u8 udbg_uart_in_40x(unsigned int reg)
 280 {
 281         return real_readb((void __iomem *)CONFIG_PPC_EARLY_DEBUG_40x_PHYSADDR
 282                           + reg);
 283 }
 284 
 285 static void udbg_uart_out_40x(unsigned int reg, u8 val)
 286 {
 287         real_writeb(val, (void __iomem *)CONFIG_PPC_EARLY_DEBUG_40x_PHYSADDR
 288                     + reg);
 289 }
 290 
 291 void __init udbg_init_40x_realmode(void)
 292 {
 293         udbg_uart_in = udbg_uart_in_40x;
 294         udbg_uart_out = udbg_uart_out_40x;
 295         udbg_use_uart();
 296 }
 297 
 298 #endif /* CONFIG_PPC_EARLY_DEBUG_40x */

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