uboot/drivers/serial/arm_dcc.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Copyright (C) 2004-2007 ARM Limited.
   4 * Copyright (C) 2008 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
   5 * Copyright (C) 2015 - 2016 Xilinx, Inc, Michal Simek
   6 *
   7 * As a special exception, if other files instantiate templates or use macros
   8 * or inline functions from this file, or you compile this file and link it
   9 * with other works to produce a work based on this file, this file does not
  10 * by itself cause the resulting work to be covered by the GNU General Public
  11 * License. However the source code for this file must still be made available
  12 * in accordance with section (3) of the GNU General Public License.
  13
  14 * This exception does not invalidate any other reasons why a work based on
  15 * this file might be covered by the GNU General Public License.
  16 */
  17
  18#include <common.h>
  19#include <dm.h>
  20#include <serial.h>
  21
  22#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V7A) || defined(CONFIG_CPU_V7R)
  23/*
  24 * ARMV6 & ARMV7
  25 */
  26#define DCC_RBIT        (1 << 30)
  27#define DCC_WBIT        (1 << 29)
  28
  29#define write_dcc(x)    \
  30                __asm__ volatile ("mcr p14, 0, %0, c0, c5, 0\n" : : "r" (x))
  31
  32#define read_dcc(x)     \
  33                __asm__ volatile ("mrc p14, 0, %0, c0, c5, 0\n" : "=r" (x))
  34
  35#define status_dcc(x)   \
  36                __asm__ volatile ("mrc p14, 0, %0, c0, c1, 0\n" : "=r" (x))
  37
  38#elif defined(CONFIG_CPU_XSCALE)
  39/*
  40 * XSCALE
  41 */
  42#define DCC_RBIT        (1 << 31)
  43#define DCC_WBIT        (1 << 28)
  44
  45#define write_dcc(x)    \
  46                __asm__ volatile ("mcr p14, 0, %0, c8, c0, 0\n" : : "r" (x))
  47
  48#define read_dcc(x)     \
  49                __asm__ volatile ("mrc p14, 0, %0, c9, c0, 0\n" : "=r" (x))
  50
  51#define status_dcc(x)   \
  52                __asm__ volatile ("mrc p14, 0, %0, c14, c0, 0\n" : "=r" (x))
  53
  54#elif defined(CONFIG_ARM64)
  55/*
  56 * ARMV8
  57 */
  58#define DCC_RBIT        (1 << 30)
  59#define DCC_WBIT        (1 << 29)
  60
  61#define write_dcc(x)   \
  62                __asm__ volatile ("msr dbgdtrtx_el0, %0\n" : : "r" (x))
  63
  64#define read_dcc(x)    \
  65                __asm__ volatile ("mrs %0, dbgdtrrx_el0\n" : "=r" (x))
  66
  67#define status_dcc(x)  \
  68                __asm__ volatile ("mrs %0, mdccsr_el0\n" : "=r" (x))
  69
  70#else
  71#define DCC_RBIT        (1 << 0)
  72#define DCC_WBIT        (1 << 1)
  73
  74#define write_dcc(x)    \
  75                __asm__ volatile ("mcr p14, 0, %0, c1, c0, 0\n" : : "r" (x))
  76
  77#define read_dcc(x)     \
  78                __asm__ volatile ("mrc p14, 0, %0, c1, c0, 0\n" : "=r" (x))
  79
  80#define status_dcc(x)   \
  81                __asm__ volatile ("mrc p14, 0, %0, c0, c0, 0\n" : "=r" (x))
  82
  83#endif
  84
  85#define can_read_dcc(x) do {    \
  86                status_dcc(x);  \
  87                x &= DCC_RBIT;  \
  88                } while (0);
  89
  90#define can_write_dcc(x) do {   \
  91                status_dcc(x);  \
  92                x &= DCC_WBIT;  \
  93                x = (x == 0);   \
  94                } while (0);
  95
  96#define TIMEOUT_COUNT 0x4000000
  97
  98static int arm_dcc_getc(struct udevice *dev)
  99{
 100        int ch;
 101        register unsigned int reg;
 102
 103        do {
 104                can_read_dcc(reg);
 105        } while (!reg);
 106        read_dcc(ch);
 107
 108        return ch;
 109}
 110
 111static int arm_dcc_putc(struct udevice *dev, char ch)
 112{
 113        register unsigned int reg;
 114        unsigned int timeout_count = TIMEOUT_COUNT;
 115
 116        while (--timeout_count) {
 117                can_write_dcc(reg);
 118                if (reg)
 119                        break;
 120        }
 121        if (timeout_count == 0)
 122                return -EAGAIN;
 123        else
 124                write_dcc(ch);
 125
 126        return 0;
 127}
 128
 129static int arm_dcc_pending(struct udevice *dev, bool input)
 130{
 131        register unsigned int reg;
 132
 133        if (input) {
 134                can_read_dcc(reg);
 135        } else {
 136                can_write_dcc(reg);
 137        }
 138
 139        return reg;
 140}
 141
 142static const struct dm_serial_ops arm_dcc_ops = {
 143        .putc = arm_dcc_putc,
 144        .pending = arm_dcc_pending,
 145        .getc = arm_dcc_getc,
 146};
 147
 148static const struct udevice_id arm_dcc_ids[] = {
 149        { .compatible = "arm,dcc", },
 150        { }
 151};
 152
 153U_BOOT_DRIVER(serial_dcc) = {
 154        .name   = "arm_dcc",
 155        .id     = UCLASS_SERIAL,
 156        .of_match = arm_dcc_ids,
 157        .ops    = &arm_dcc_ops,
 158};
 159
 160#ifdef CONFIG_DEBUG_UART_ARM_DCC
 161
 162#include <debug_uart.h>
 163
 164static inline void _debug_uart_init(void)
 165{
 166}
 167
 168static inline void _debug_uart_putc(int ch)
 169{
 170        arm_dcc_putc(NULL, ch);
 171}
 172
 173DEBUG_UART_FUNCS
 174#endif
 175