linux/drivers/tty/hvc/hvc_dcc.c
<<
>>
Prefs
   1/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
   2 *
   3 * This program is free software; you can redistribute it and/or modify
   4 * it under the terms of the GNU General Public License version 2 and
   5 * only version 2 as published by the Free Software Foundation.
   6 *
   7 * This program is distributed in the hope that it will be useful,
   8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
   9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  10 * GNU General Public License for more details.
  11 *
  12 * You should have received a copy of the GNU General Public License
  13 * along with this program; if not, write to the Free Software
  14 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  15 * 02110-1301, USA.
  16 */
  17
  18#include <linux/console.h>
  19#include <linux/delay.h>
  20#include <linux/err.h>
  21#include <linux/init.h>
  22#include <linux/moduleparam.h>
  23#include <linux/types.h>
  24
  25#include <asm/processor.h>
  26
  27#include "hvc_console.h"
  28
  29/* DCC Status Bits */
  30#define DCC_STATUS_RX           (1 << 30)
  31#define DCC_STATUS_TX           (1 << 29)
  32
  33static inline u32 __dcc_getstatus(void)
  34{
  35        u32 __ret;
  36        asm volatile("mrc p14, 0, %0, c0, c1, 0 @ read comms ctrl reg"
  37                : "=r" (__ret) : : "cc");
  38
  39        return __ret;
  40}
  41
  42
  43static inline char __dcc_getchar(void)
  44{
  45        char __c;
  46
  47        asm volatile("mrc p14, 0, %0, c0, c5, 0 @ read comms data reg"
  48                : "=r" (__c));
  49        isb();
  50
  51        return __c;
  52}
  53
  54static inline void __dcc_putchar(char c)
  55{
  56        asm volatile("mcr p14, 0, %0, c0, c5, 0 @ write a char"
  57                : /* no output register */
  58                : "r" (c));
  59        isb();
  60}
  61
  62static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count)
  63{
  64        int i;
  65
  66        for (i = 0; i < count; i++) {
  67                while (__dcc_getstatus() & DCC_STATUS_TX)
  68                        cpu_relax();
  69
  70                __dcc_putchar(buf[i]);
  71        }
  72
  73        return count;
  74}
  75
  76static int hvc_dcc_get_chars(uint32_t vt, char *buf, int count)
  77{
  78        int i;
  79
  80        for (i = 0; i < count; ++i)
  81                if (__dcc_getstatus() & DCC_STATUS_RX)
  82                        buf[i] = __dcc_getchar();
  83                else
  84                        break;
  85
  86        return i;
  87}
  88
  89static const struct hv_ops hvc_dcc_get_put_ops = {
  90        .get_chars = hvc_dcc_get_chars,
  91        .put_chars = hvc_dcc_put_chars,
  92};
  93
  94static int __init hvc_dcc_console_init(void)
  95{
  96        hvc_instantiate(0, 0, &hvc_dcc_get_put_ops);
  97        return 0;
  98}
  99console_initcall(hvc_dcc_console_init);
 100
 101static int __init hvc_dcc_init(void)
 102{
 103        hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
 104        return 0;
 105}
 106device_initcall(hvc_dcc_init);
 107