#include <rtapi_slab.h>
#include "rtapi.h"
#include "rtapi_string.h"
#include "rtapi_math.h"
#include "hal.h"
#include "hostmot2.h"
int hm2_uart_parse_md(hostmot2_t *hm2, int md_index)
{
int i, r = -EINVAL;
hm2_module_descriptor_t *md = &hm2->md[md_index];
static int last_gtag = -1;
if (!hm2_md_is_consistent_or_complain(hm2, md_index, 0, 4, 0x10, 0x000F)) {
HM2_ERR("inconsistent Module Descriptor!\n");
return -EINVAL;
}
if (hm2->uart.num_instances > 1 && last_gtag == md->gtag) {
HM2_ERR(
"found duplicate Module Descriptor for %s (inconsistent "
"firmware), not loading driver %i %i\n",
hm2_get_general_function_name(md->gtag), md->gtag, last_gtag
);
return -EINVAL;
}
last_gtag = md->gtag;
if (hm2->config.num_uarts > md->instances) {
HM2_ERR(
"config defines %d uarts, but only %d are available, "
"not loading driver\n",
hm2->config.num_uarts,
md->instances
);
return -EINVAL;
}
if (hm2->config.num_uarts == 0) {
return 0;
}
if (hm2->uart.num_instances == 0){
if (hm2->config.num_uarts == -1) {
hm2->uart.num_instances = md->instances;
} else {
hm2->uart.num_instances = hm2->config.num_uarts;
}
hm2->uart.instance = (hm2_uart_instance_t *)hal_malloc(hm2->uart.num_instances
* sizeof(hm2_uart_instance_t));
if (hm2->uart.instance == NULL) {
HM2_ERR("out of memory!\n");
r = -ENOMEM;
goto fail0;
}
}
for (i = 0 ; i < hm2->uart.num_instances ; i++){
hm2_uart_instance_t *inst = &hm2->uart.instance[i];
if (inst->clock_freq == 0){
inst->clock_freq = md->clock_freq;
r = sprintf(inst->name, "%s.uart.%01d", hm2->llio->name, i);
HM2_PRINT("created UART Interface function %s.\n", inst->name);
}
if (md->gtag == HM2_GTAG_UART_TX){
inst->tx1_addr = md->base_address + i * md->instance_stride;
inst->tx2_addr = md->base_address + i * md->instance_stride + 0x4;
inst->tx3_addr = md->base_address + i * md->instance_stride + 0x8;
inst->tx4_addr = md->base_address + i * md->instance_stride + 0xC;
inst->tx_fifo_count_addr = (md->base_address
+ md->register_stride
+ i * md->instance_stride);
inst->tx_bitrate_addr = (md->base_address
+ 2 * md->register_stride
+ i * md->instance_stride);
inst->tx_mode_addr = (md->base_address
+ 3 * md->register_stride
+i * md->instance_stride);
}
else if (md->gtag == HM2_GTAG_UART_RX){
inst->rx1_addr = md->base_address + i * md->instance_stride;
inst->rx2_addr = md->base_address + i * md->instance_stride + 0x4;
inst->rx3_addr = md->base_address + i * md->instance_stride + 0x8;
inst->rx4_addr = md->base_address + i * md->instance_stride + 0xC;
inst->rx_fifo_count_addr = (md->base_address
+ md->register_stride
+ i * md->instance_stride);
inst->rx_bitrate_addr = (md->base_address
+ 2 * md->register_stride
+ i * md->instance_stride);
inst->rx_mode_addr = (md->base_address
+ 3 * md->register_stride
+i * md->instance_stride);
}
else{
HM2_ERR("Something very weird happened");
goto fail0;
}
}
return hm2->uart.num_instances;
fail0:
return r;
}
EXPORT_SYMBOL_GPL(hm2_uart_setup);
int hm2_uart_setup(char *name, int bitrate, rtapi_s32 tx_mode, rtapi_s32 rx_mode){
hostmot2_t *hm2;
hm2_uart_instance_t *inst = 0;
rtapi_u32 buff;
int i,r;
i = hm2_get_uart(&hm2, name);
if (i < 0){
HM2_ERR_NO_LL("Can not find UART instance %s.\n", name);
return -1;
}
inst = &hm2->uart.instance[i];
buff = (rtapi_u32)((bitrate * 1048576.0)/inst->clock_freq); r = 0;
if (buff != inst->bitrate){
inst->bitrate = buff;
r += hm2->llio->write(hm2->llio, inst->rx_bitrate_addr, &buff, sizeof(rtapi_u32));
r += hm2->llio->write(hm2->llio, inst->tx_bitrate_addr, &buff, sizeof(rtapi_u32));
buff = 0;
r += hm2->llio->write(hm2->llio, inst->rx_mode_addr, &buff, sizeof(rtapi_u32)); r += hm2->llio->write(hm2->llio, inst->rx_fifo_count_addr, &buff, sizeof(rtapi_u32)); r += hm2->llio->write(hm2->llio, inst->tx_fifo_count_addr, &buff, sizeof(rtapi_u32)); }
if (tx_mode >= 0) {
buff = ((rtapi_u32)tx_mode) & 0x7f;
r += hm2->llio->write(hm2->llio, inst->tx_mode_addr, &buff, sizeof(rtapi_u32));
}
if (rx_mode >= 0) {
buff = ((rtapi_u32)rx_mode) & 0xff;
r += hm2->llio->write(hm2->llio, inst->rx_mode_addr, &buff, sizeof(rtapi_u32));
}
if (r < 0) {
HM2_ERR("UART: hm2->llio->write failure %s\n", name);
return -1;
}
return 0;
}
EXPORT_SYMBOL_GPL(hm2_uart_send);
int hm2_uart_send(char *name, unsigned char data[], int count)
{
hostmot2_t *hm2;
rtapi_u32 buff;
int r, c;
int inst;
static int err_flag = 0;
inst = hm2_get_uart(&hm2, name);
if (inst < 0 && !err_flag){
HM2_ERR_NO_LL("Can not find UART instance %s.\n", name);
err_flag = 1;
return -1;
}
if (hm2->uart.instance[inst].bitrate == 0 && !err_flag){
HM2_ERR("The selected UART instance %s.\n"
"Has not been configured.\n", name);
err_flag = 1; return -1;
}
c = 0;
err_flag = 0;
while (c < count - 3){
buff = (data[c] +
(data[c+1] << 8) +
(data[c+2] << 16) +
(data[c+3] << 24));
r = hm2->llio->write(hm2->llio, hm2->uart.instance[inst].tx4_addr,
&buff, sizeof(rtapi_u32));
if (r < 0) {
HM2_ERR("UART WRITE: hm2->llio->write failure %s\n", name);
return r;
}
c = c + 4;
}
switch(count - c){
case 0:
return c;
case 1:
buff = data[c];
r = hm2->llio->write(hm2->llio, hm2->uart.instance[inst].tx1_addr,
&buff, sizeof(rtapi_u32));
if (r < 0){
HM2_ERR("UART WRITE: hm2->llio->write failure %s\n", name);
return r;
}else{
return c + 1;
}
case 2:
buff = (data[c] +
(data[c+1] << 8));
r = hm2->llio->write(hm2->llio, hm2->uart.instance[inst].tx2_addr,
&buff, sizeof(rtapi_u32));
if (r < 0){
HM2_ERR("UART_WRITE: hm2->llio->write failure %s\n", name);
return r;
}else{
return c + 2;
}
case 3:
buff = (data[c] +
(data[c+1] << 8) +
(data[c+2] << 16));
r = hm2->llio->write(hm2->llio, hm2->uart.instance[inst].tx3_addr,
&buff, sizeof(rtapi_u32));
if (r < 0){
HM2_ERR("UART WRITE: hm2->llio->write failure %s\n", name);
return r;
}else{
return c + 3;
}
default:
HM2_ERR("UART WRITE: Error in buffer parsing. count = %i, i = %i\n", count, c);
return -1;
}
}
EXPORT_SYMBOL_GPL(hm2_uart_read);
int hm2_uart_read(char *name, unsigned char data[])
{
hostmot2_t *hm2;
int r, c;
int count;
int inst;
rtapi_u32 buff;
static int err_flag = 0;
inst = hm2_get_uart(&hm2, name);
if (inst < 0){
HM2_ERR_NO_LL("Can not find UART instance %s.\n", name);
return -1;
}
if (hm2->uart.instance[inst].bitrate == 0 && !err_flag){
HM2_ERR("The selected UART instance %s.\n"
"Has not been configured.\n", name);
err_flag = 1;
return -1;
}
err_flag = 0;
r = hm2->llio->read(hm2->llio, hm2->uart.instance[inst].rx_fifo_count_addr,
&buff, sizeof(rtapi_u32));
count = buff & 0x1F;
c = 0;
while (c < count - 3 && c < 16){
r = hm2->llio->read(hm2->llio, hm2->uart.instance[inst].rx4_addr,
&buff, sizeof(rtapi_u32));
if (r < 0) {
HM2_ERR("UART: hm2->llio->read failure %s\n", name);
return r;
}
data[c] = (buff & 0x000000FF);
data[c+1] = (buff & 0x0000FF00) >> 8;
data[c+2] = (buff & 0x00FF0000) >> 16;
data[c+3] = (buff & 0xFF000000) >> 24;
c = c + 4;
}
switch(count - c){
case 0:
return c;
case 1:
r = hm2->llio->read(hm2->llio, hm2->uart.instance[inst].rx1_addr,
&buff, sizeof(rtapi_u32));
data[c] = (buff & 0x000000FF);
return c + 1;
case 2:
r = hm2->llio->read(hm2->llio, hm2->uart.instance[inst].rx2_addr,
&buff, sizeof(rtapi_u32));
data[c] = (buff & 0x000000FF);
data[c+1] = (buff & 0x0000FF00) >> 8;
return c + 2;
case 3:
r = hm2->llio->read(hm2->llio, hm2->uart.instance[inst].rx3_addr,
&buff, sizeof(rtapi_u32));
data[c] = (buff & 0x000000FF);
data[c+1] = (buff & 0x0000FF00) >> 8;
data[c+2] = (buff & 0x00FF0000) >> 16;
return c + 3;
default:
HM2_ERR("UART READ: Error in buffer parsing.\n");
return -EINVAL;
}
if (r < 0) {
HM2_ERR("UART READ: hm2->llio->write failure %s\n", name);
return -EINVAL;
}
}
void hm2_uart_print_module(hostmot2_t *hm2){
int i;
HM2_PRINT("UART: %d\n", hm2->uart.num_instances);
if (hm2->uart.num_instances <= 0) return;
HM2_PRINT(" version: %d\n", hm2->uart.version);
HM2_PRINT(" channel configurations\n");
for (i = 0; i < hm2->uart.num_instances; i ++) {
HM2_PRINT(" clock_frequency: %d Hz (%s MHz)\n",
hm2->uart.instance[i].clock_freq,
hm2_hz_to_mhz(hm2->uart.instance[i].clock_freq));
HM2_PRINT(" instance %d:\n", i);
HM2_PRINT(" HAL name = %s\n", hm2->uart.instance[i].name);
}
}
void hm2_uart_cleanup(hostmot2_t *hm2)
{
}
void hm2_uart_write(hostmot2_t *hm2)
{
}