Linux Audio

Check our new training course

Loading...
v3.1
  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
 50	return __c;
 51}
 52
 53static inline void __dcc_putchar(char c)
 
 54{
 55	asm volatile("mcr p14, 0, %0, c0, c5, 0	@ write a char"
 56		: /* no output register */
 57		: "r" (c));
 58}
 59
 
 
 60static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count)
 61{
 62	int i;
 63
 64	for (i = 0; i < count; i++) {
 65		while (__dcc_getstatus() & DCC_STATUS_TX)
 66			cpu_relax();
 67
 68		__dcc_putchar(buf[i]);
 69	}
 70
 71	return count;
 72}
 73
 74static int hvc_dcc_get_chars(uint32_t vt, char *buf, int count)
 75{
 76	int i;
 77
 78	for (i = 0; i < count; ++i)
 79		if (__dcc_getstatus() & DCC_STATUS_RX)
 80			buf[i] = __dcc_getchar();
 81		else
 82			break;
 83
 84	return i;
 85}
 86
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 87static const struct hv_ops hvc_dcc_get_put_ops = {
 88	.get_chars = hvc_dcc_get_chars,
 89	.put_chars = hvc_dcc_put_chars,
 90};
 91
 92static int __init hvc_dcc_console_init(void)
 93{
 94	hvc_instantiate(0, 0, &hvc_dcc_get_put_ops);
 95	return 0;
 
 
 
 
 
 
 
 96}
 97console_initcall(hvc_dcc_console_init);
 98
 99static int __init hvc_dcc_init(void)
100{
101	hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
102	return 0;
 
 
 
 
 
 
103}
104device_initcall(hvc_dcc_init);
v5.14.15
  1// SPDX-License-Identifier: GPL-2.0
  2/* Copyright (c) 2010, 2014 The Linux Foundation. All rights reserved.  */
 
 
 
 
 
 
 
 
 
 
 
 
 
 
  3
  4#include <linux/console.h>
 
 
  5#include <linux/init.h>
  6#include <linux/serial.h>
  7#include <linux/serial_core.h>
  8
  9#include <asm/dcc.h>
 10#include <asm/processor.h>
 11
 12#include "hvc_console.h"
 13
 14/* DCC Status Bits */
 15#define DCC_STATUS_RX		(1 << 30)
 16#define DCC_STATUS_TX		(1 << 29)
 17
 18static void dcc_uart_console_putchar(struct uart_port *port, int ch)
 19{
 20	while (__dcc_getstatus() & DCC_STATUS_TX)
 21		cpu_relax();
 
 22
 23	__dcc_putchar(ch);
 24}
 25
 26static void dcc_early_write(struct console *con, const char *s, unsigned n)
 
 27{
 28	struct earlycon_device *dev = con->data;
 
 
 
 29
 30	uart_console_write(&dev->port, s, n, dcc_uart_console_putchar);
 31}
 32
 33static int __init dcc_early_console_setup(struct earlycon_device *device,
 34					  const char *opt)
 35{
 36	device->con->write = dcc_early_write;
 37
 38	return 0;
 39}
 40
 41EARLYCON_DECLARE(dcc, dcc_early_console_setup);
 42
 43static int hvc_dcc_put_chars(uint32_t vt, const char *buf, int count)
 44{
 45	int i;
 46
 47	for (i = 0; i < count; i++) {
 48		while (__dcc_getstatus() & DCC_STATUS_TX)
 49			cpu_relax();
 50
 51		__dcc_putchar(buf[i]);
 52	}
 53
 54	return count;
 55}
 56
 57static int hvc_dcc_get_chars(uint32_t vt, char *buf, int count)
 58{
 59	int i;
 60
 61	for (i = 0; i < count; ++i)
 62		if (__dcc_getstatus() & DCC_STATUS_RX)
 63			buf[i] = __dcc_getchar();
 64		else
 65			break;
 66
 67	return i;
 68}
 69
 70static bool hvc_dcc_check(void)
 71{
 72	unsigned long time = jiffies + (HZ / 10);
 73
 74	/* Write a test character to check if it is handled */
 75	__dcc_putchar('\n');
 76
 77	while (time_is_after_jiffies(time)) {
 78		if (!(__dcc_getstatus() & DCC_STATUS_TX))
 79			return true;
 80	}
 81
 82	return false;
 83}
 84
 85static const struct hv_ops hvc_dcc_get_put_ops = {
 86	.get_chars = hvc_dcc_get_chars,
 87	.put_chars = hvc_dcc_put_chars,
 88};
 89
 90static int __init hvc_dcc_console_init(void)
 91{
 92	int ret;
 93
 94	if (!hvc_dcc_check())
 95		return -ENODEV;
 96
 97	/* Returns -1 if error */
 98	ret = hvc_instantiate(0, 0, &hvc_dcc_get_put_ops);
 99
100	return ret < 0 ? -ENODEV : 0;
101}
102console_initcall(hvc_dcc_console_init);
103
104static int __init hvc_dcc_init(void)
105{
106	struct hvc_struct *p;
107
108	if (!hvc_dcc_check())
109		return -ENODEV;
110
111	p = hvc_alloc(0, 0, &hvc_dcc_get_put_ops, 128);
112
113	return PTR_ERR_OR_ZERO(p);
114}
115device_initcall(hvc_dcc_init);