Linux Audio

Check our new training course

Embedded Linux Audio

Check our new training course
with Creative Commons CC-BY-SA
lecture materials

Bootlin logo

Elixir Cross Referencer

Loading...
/*
 * Copyright (c) 2017 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */


#include <zephyr/kernel.h>
#include <zephyr/arch/cpu.h>
#include <zephyr/drivers/uart.h>
#include <zephyr/sys/sys_io.h>

#define DT_DRV_COMPAT   altr_jtag_uart

#define UART_ALTERA_JTAG_DATA_OFFSET    0x00        /* DATA : Register offset */
#define UART_ALTERA_JTAG_CTRL_OFFSET    0x04        /* CTRL : Register offset */
#define UART_IE_TX                      (1 << 0)    /* CTRL : TX Interrupt Enable */
#define UART_IE_RX                      (1 << 1)    /* CTRL : RX Interrupt Enable */
#define UART_DATA_MASK                  0xFF        /* DATA : Data Mask */
#define UART_WFIFO_MASK                 0xFFFF0000  /* CTRL : Transmit FIFO Mask */

#ifdef CONFIG_UART_ALTERA_JTAG_HAL
#include "altera_avalon_jtag_uart.h"
#include "altera_avalon_jtag_uart_regs.h"

extern int altera_avalon_jtag_uart_read(altera_avalon_jtag_uart_state *sp,
		char *buffer, int space, int flags);
extern int altera_avalon_jtag_uart_write(altera_avalon_jtag_uart_state *sp,
		const char *ptr, int count, int flags);
#else

/* device data */
struct uart_altera_jtag_device_data {
	struct k_spinlock lock;
};

/* device config */
struct uart_altera_jtag_device_config {
	mm_reg_t base;
};
#endif /* CONFIG_UART_ALTERA_JTAG_HAL */

static void uart_altera_jtag_poll_out(const struct device *dev,
					       unsigned char c)
{
#ifdef CONFIG_UART_ALTERA_JTAG_HAL
	altera_avalon_jtag_uart_state ustate;

	ustate.base = JTAG_UART_0_BASE;
	altera_avalon_jtag_uart_write(&ustate, &c, 1, 0);
#else
	const struct uart_altera_jtag_device_config *config = dev->config;
	struct uart_altera_jtag_device_data *data = dev->data;

	k_spinlock_key_t key = k_spin_lock(&data->lock);

	/* While TX FIFO full */
	while (!(sys_read32(config->base + UART_ALTERA_JTAG_CTRL_OFFSET) & UART_WFIFO_MASK)) {
	}

	uint32_t data_val = sys_read32(config->base + UART_ALTERA_JTAG_DATA_OFFSET);

	data_val &= ~UART_DATA_MASK;
	data_val |= c;
	sys_write32(data_val, config->base + UART_ALTERA_JTAG_DATA_OFFSET);

	k_spin_unlock(&data->lock, key);
#endif /* CONFIG_UART_ALTERA_JTAG_HAL */
}

static int uart_altera_jtag_init(const struct device *dev)
{
	/*
	 * Work around to clear interrupt enable bits
	 * as it is not being done by HAL driver explicitly.
	 */
#ifdef CONFIG_UART_ALTERA_JTAG_HAL
	IOWR_ALTERA_AVALON_JTAG_UART_CONTROL(JTAG_UART_0_BASE, 0);
#else
	const struct uart_altera_jtag_device_config *config = dev->config;
	uint32_t ctrl_val = sys_read32(config->base + UART_ALTERA_JTAG_CTRL_OFFSET);

	ctrl_val &= ~(UART_IE_TX | UART_IE_RX);
	sys_write32(ctrl_val, config->base + UART_ALTERA_JTAG_CTRL_OFFSET);
#endif /* CONFIG_UART_ALTERA_JTAG_HAL */
	return 0;
}

static const struct uart_driver_api uart_altera_jtag_driver_api = {
	.poll_in = NULL,
	.poll_out = &uart_altera_jtag_poll_out,
	.err_check = NULL,
};

#ifdef CONFIG_UART_ALTERA_JTAG_HAL
DEVICE_DT_INST_DEFINE(0, uart_altera_jtag_init, NULL, NULL, NULL, PRE_KERNEL_1,
		      CONFIG_SERIAL_INIT_PRIORITY,
		      &uart_altera_jtag_driver_api);
#else
static struct uart_altera_jtag_device_data uart_altera_jtag_dev_data_0 = {
};

static const struct uart_altera_jtag_device_config uart_altera_jtag_dev_cfg_0 = {
	.base = DT_INST_REG_ADDR(0),
};
DEVICE_DT_INST_DEFINE(0,
		      uart_altera_jtag_init,
		      NULL,
		      &uart_altera_jtag_dev_data_0,
		      &uart_altera_jtag_dev_cfg_0,
		      PRE_KERNEL_1,
		      CONFIG_SERIAL_INIT_PRIORITY,
		      &uart_altera_jtag_driver_api);
#endif /* CONFIG_UART_ALTERA_JTAG_HAL */