blob: 839ac66ad1d5942721d77205e5ac53cc438bb1f5 [file]
// SPDX-License-Identifier: (GPL-2.0+ OR MIT)
/*
* Copyright (c) 2019 Amlogic, Inc. All rights reserved.
*/
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/interrupt.h>
#include <linux/fs.h>
#include <linux/dma-mapping.h>
#include <linux/string.h>
#include <linux/io.h>
#include <linux/mm.h>
#include <linux/err.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/ctype.h>
#include <linux/sched.h>
#include <linux/poll.h>
#include <linux/clk.h>
#include <linux/kthread.h>
#include <linux/slab.h>
#include <linux/of.h>
#include <linux/of_fdt.h>
#include <linux/reset.h>
#include <linux/sched/clock.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/of_irq.h>
#include <linux/of_device.h>
#include <linux/types.h>
#include <linux/of_address.h>
#include <linux/of_reserved_mem.h>
#include <linux/dma-map-ops.h>
#include <linux/cma.h>
#include <linux/genalloc.h>
#include <linux/amlogic/media/frc/frc_reg.h>
#include "frc_drv.h"
#include "frc_rdma.h"
#include "frc_hw.h"
// #include "frc_regs_table.h"
struct reg_test regs_table_test[REG_TEST_NUM] = {
{0x60, 0x0}, {0x61, 0x1}, {0x62, 0x2}, {0x63, 0x3},
{0x64, 0x4}, {0x65, 0x5}, {0x66, 0x6}, {0x67, 0x7},
{0x68, 0x8}, {0x69, 0x9}, {0x6a, 0xa}, {0x6b, 0xb},
{0x6c, 0xc}, {0x6d, 0xd}, {0x6e, 0xe}, {0x6f, 0xf},
{0x3210, 0x10}, {0x3211, 0x11}, {0x3212, 0x12}, {0x3213, 0x13},
{0x3214, 0x14}, {0x3215, 0x15}, {0x3216, 0x16}, {0x3217, 0x17},
{0x3218, 0x18}, {0x3219, 0x19}, {0x321a, 0x1a}, {0x321b, 0x1b},
{0x321c, 0x1c}, {0x321d, 0x1d}, {0x321e, 0x1e}, {0x321f, 0x1f},
};
static struct rdma_regadr_s rdma_regadr_t3[RDMA_NUM] = {
{
FRC_RDMA_AHB_START_ADDR_MAN,
FRC_RDMA_AHB_START_ADDR_MAN_MSB,
FRC_RDMA_AHB_END_ADDR_MAN,
FRC_RDMA_AHB_END_ADDR_MAN_MSB,
0, 0,
FRC_RDMA_ACCESS_MAN, 1,
FRC_RDMA_ACCESS_MAN, 2,
24, 24
},
{
FRC_RDMA_AHB_START_ADDR_1,
FRC_RDMA_AHB_START_ADDR_1_MSB,
FRC_RDMA_AHB_END_ADDR_1,
FRC_RDMA_AHB_END_ADDR_1_MSB,
FRC_RDMA_AUTO_SRC1_SEL, 1,
FRC_RDMA_ACCESS_AUTO, 1,
FRC_RDMA_ACCESS_AUTO, 5,
25, 25
},
{
FRC_RDMA_AHB_START_ADDR_2,
FRC_RDMA_AHB_START_ADDR_2_MSB,
FRC_RDMA_AHB_END_ADDR_2,
FRC_RDMA_AHB_END_ADDR_2_MSB,
FRC_RDMA_AUTO_SRC2_SEL, 0,
FRC_RDMA_ACCESS_AUTO, 2,
FRC_RDMA_ACCESS_AUTO, 6,
26, 26
},
{
FRC_RDMA_AHB_START_ADDR_3,
FRC_RDMA_AHB_START_ADDR_3_MSB,
FRC_RDMA_AHB_END_ADDR_3,
FRC_RDMA_AHB_END_ADDR_3_MSB,
FRC_RDMA_AUTO_SRC3_SEL, 0,
FRC_RDMA_ACCESS_AUTO, 3,
FRC_RDMA_ACCESS_AUTO, 7,
27, 27
},
{
FRC_RDMA_AHB_START_ADDR_4,
FRC_RDMA_AHB_START_ADDR_4_MSB,
FRC_RDMA_AHB_END_ADDR_4,
FRC_RDMA_AHB_END_ADDR_4_MSB,
FRC_RDMA_AUTO_SRC4_SEL, 0,
FRC_RDMA_ACCESS_AUTO2, 0,
FRC_RDMA_ACCESS_AUTO2, 4,
28, 28
},
{
FRC_RDMA_AHB_START_ADDR_5,
FRC_RDMA_AHB_START_ADDR_5_MSB,
FRC_RDMA_AHB_END_ADDR_5,
FRC_RDMA_AHB_END_ADDR_5_MSB,
FRC_RDMA_AUTO_SRC5_SEL, 0,
FRC_RDMA_ACCESS_AUTO2, 1,
FRC_RDMA_ACCESS_AUTO2, 5,
29, 29
},
{
FRC_RDMA_AHB_START_ADDR_6,
FRC_RDMA_AHB_START_ADDR_6_MSB,
FRC_RDMA_AHB_END_ADDR_6,
FRC_RDMA_AHB_END_ADDR_6_MSB,
FRC_RDMA_AUTO_SRC6_SEL, 0,
FRC_RDMA_ACCESS_AUTO2, 2,
FRC_RDMA_ACCESS_AUTO2, 6,
30, 30
},
{
FRC_RDMA_AHB_START_ADDR_7,
FRC_RDMA_AHB_START_ADDR_7_MSB,
FRC_RDMA_AHB_END_ADDR_7,
FRC_RDMA_AHB_END_ADDR_7_MSB,
FRC_RDMA_AUTO_SRC7_SEL, 0,
FRC_RDMA_ACCESS_AUTO2, 3,
FRC_RDMA_ACCESS_AUTO2, 7,
31, 31
}
};
static int rdma_cnt;
int frc_rdma_debug;
module_param(frc_rdma_debug, int, 0664);
MODULE_PARM_DESC(frc_rdma_debug, "frc rdma debug");
int frc_rdma_enable;
module_param(frc_rdma_enable, int, 0664);
MODULE_PARM_DESC(frc_rdma_enable, "frc rdma enable ctrl");
struct frc_rdma_info frc_rdma_s;
struct frc_rdma_info frc_rdma_s2;
struct frc_rdma_info *frc_get_rdma_info(void)
{
return &frc_rdma_s;
}
EXPORT_SYMBOL(frc_get_rdma_info);
struct frc_rdma_info *frc_get_rdma_info_2(void)
{
return &frc_rdma_s2;
}
EXPORT_SYMBOL(frc_get_rdma_info_2);
int is_rdma_enable(void)
{
struct frc_dev_s *devp;
struct frc_fw_data_s *fw_data;
devp = get_frc_devp();
fw_data = (struct frc_fw_data_s *)devp->fw_data;
if (frc_rdma_enable && fw_data->frc_top_type.rdma_en)
return 1;
return 0;
}
void frc_rdma_write_test(dma_addr_t phy_addr, u32 size)
{
int i;
// data32 = 0;
// data32 |= 1 << 10;
// data32 |= 1 << 8;
// data32 |= 1 << 7; /* write ddr urgent */
// data32 |= 1 << 6; /* read ddr urgent */
// data32 |= 1 << 4;
// data32 |= 1 << 2;
// data32 |= 0 << 1;
// data32 |= 0 << 0;
// WRITE_FRC_REG_BY_CPU(FRC_RDMA_CTRL, 0x5d4); //ctrl sw reset
//
// timestamp = sched_clock();
WRITE_FRC_REG_BY_CPU(FRC_RDMA_AHB_START_ADDR_MAN, phy_addr); //rdma start address
WRITE_FRC_REG_BY_CPU(FRC_RDMA_AHB_END_ADDR_MAN, phy_addr + size);
//WRITE_FRC_REG_BY_CPU(FRC_RDMA_ACCESS_MAN, 0x4); //man rdma start to work
// WRITE_FRC_REG_BY_CPU (FRC_RDMA_ACCESS_MAN, 0x101);
//WRITE_FRC_BITS(FRC_RDMA_ACCESS_MAN, 1, 0, 1);
// WRITE_FRC_REG_BY_CPU(FRC_RDMA_CTRL, 0x1 << 24);
for (i = 0x3b00; i < 0x3b3f; ++i)
pr_frc(0, "addr[%x]=%x\n", i, READ_FRC_REG(i));
}
void frc_rdma_alloc_buf(void)
{
dma_addr_t dma_handle;
struct frc_dev_s *devp = get_frc_devp();
struct frc_rdma_info *frc_rdma = frc_get_rdma_info();
struct frc_rdma_info *frc_rdma2 = &frc_rdma_s2;
if (frc_rdma->buf_status)
return;
frc_rdma->rdma_table_size = FRC_RDMA_SIZE;
frc_rdma->rdma_table_addr = dma_alloc_coherent(&devp->pdev->dev,
FRC_RDMA_SIZE / 2, &dma_handle, GFP_KERNEL);
frc_rdma->rdma_table_phy_addr = (ulong)(dma_handle);
frc_rdma2->rdma_table_addr = dma_alloc_coherent(&devp->pdev->dev,
FRC_RDMA_SIZE / 2, &dma_handle, GFP_KERNEL);
frc_rdma2->rdma_table_phy_addr = (ulong)(dma_handle);
pr_frc(0, "%s rdma_table_addr: %lx phy:%lx size:%lx\n",
__func__, (unsigned long)frc_rdma->rdma_table_addr,
frc_rdma->rdma_table_phy_addr, FRC_RDMA_SIZE / 2);
pr_frc(0, "%s rdma_table_addr2: %lx phy2:%lx size2:%lx\n",
__func__, (unsigned long)frc_rdma2->rdma_table_addr,
frc_rdma2->rdma_table_phy_addr, FRC_RDMA_SIZE / 2);
if (frc_rdma->rdma_table_addr && frc_rdma2->rdma_table_addr)
frc_rdma->buf_status = 1;
}
void frc_rdma_release_buf(void)
{
struct frc_dev_s *devp = get_frc_devp();
struct frc_rdma_info *frc_rdma = frc_get_rdma_info();
struct frc_rdma_info *frc_rdma2 = &frc_rdma_s2;
dma_free_coherent(&devp->pdev->dev, FRC_RDMA_SIZE / 2,
frc_rdma->rdma_table_addr, (dma_addr_t)frc_rdma->rdma_table_phy_addr);
dma_free_coherent(&devp->pdev->dev, FRC_RDMA_SIZE / 2,
frc_rdma2->rdma_table_addr, (dma_addr_t)frc_rdma2->rdma_table_phy_addr);
frc_rdma->buf_status = 0;
pr_frc(0, "%s rdma buffer released\n", __func__);
}
void frc_rdma_reg_status(void)
{
int i;
for (i = 0x3b00; i < 0x3b3f; ++i)
pr_frc(0, "addr[%x]=%x\n", i, READ_FRC_REG(i));
}
void frc_rdma_read_test_reg(void)
{
int i;
for (i = 0x0; i < 0x10; i++)
pr_frc(0, "addr[%x]:%x\n", i + 0x60, READ_FRC_REG(i + 0x60));
for (i = 0x0; i < 0x10; i++)
pr_frc(0, "addr[%x]:%x\n", i + 0x3210, READ_FRC_REG(i + 0x3210));
}
void frc_rdma_reset_test_reg(void)
{
int i, sum = 0;
for (i = 0x0; i < 0x10; i++)
WRITE_FRC_REG_BY_CPU(i + 0x60, 0);
for (i = 0x0; i < 0x10; i++)
sum += READ_FRC_REG(i + 0x60);
if (sum == 0)
pr_frc(0, "reset test reg pass\n");
else
pr_frc(0, "reset failed\n");
}
void frc_read_table(void)
{
int i, temp, temp2;
struct frc_rdma_info *frc_rdma = &frc_rdma_s;
struct frc_rdma_info *frc_rdma2 = &frc_rdma_s2;
temp = frc_rdma->rdma_item_count;
temp2 = frc_rdma2->rdma_item_count;
pr_frc(0, "--------------table1----------------\n");
for (i = 0; i < temp; i++) {
// if (frc_rdma->rdma_table_addr[i * 2] != 0)
pr_frc(0, "addr:0x%04x, value:0x%08x\n",
frc_rdma->rdma_table_addr[i * 2],
frc_rdma->rdma_table_addr[i * 2 + 1]);
// else
// break;
}
pr_frc(0, "--------------table2----------------\n");
for (i = 0; i < temp2; i++) {
// if (frc_rdma->rdma_table_addr[i * 2] != 0)
pr_frc(0, "addr:0x%04x, value:0x%08x\n",
frc_rdma2->rdma_table_addr[i * 2],
frc_rdma2->rdma_table_addr[i * 2 + 1]);
// else
// break;
}
pr_frc(0, "--------------table2 done----------------\n");
}
void frc_read_table2_clear(void)
{
int i, count;
struct frc_rdma_info *frc_rdma2 = &frc_rdma_s2;
// memset(frc_rdma2->rdma_table_addr[0], 0,
// sizeof(frc_rdma2->rdma_table_addr[0]) * frc_rdma2->rdma_item_count);
count = frc_rdma2->rdma_item_count;
for (i = 0; i < count; i++) {
frc_rdma2->rdma_table_addr[i * 2] = 0;
frc_rdma2->rdma_table_addr[i * 2 + 1] = 0;
}
frc_rdma2->rdma_item_count = 0;
pr_frc(0, "clear table2 done\n");
}
int frc_check_table(u32 addr)
{
int i;
int index = -1;
struct frc_rdma_info *frc_rdma = &frc_rdma_s;
if (frc_rdma->rdma_item_count == 0)
return -1;
pr_frc(21, "rdma_item_count:%d addr:%x\n",
frc_rdma->rdma_item_count, addr);
for (i = (frc_rdma->rdma_item_count - 1) * 2; i >= 0; i -= 2) {
pr_frc(21, "i:%d, table_addr[%d]=%x, table_value[%d]=%x",
i, i, frc_rdma->rdma_table_addr[i], i + 1,
frc_rdma->rdma_table_addr[i + 1]);
if (frc_rdma->rdma_table_addr[i] == addr) {
//value = frc_rdma->rdma_table_addr[i+1];
index = i / 2 + 1;
break;
}
}
pr_frc(21, "%s index:%d\n", __func__, index);
return index;
}
/*
* interrupt call
*/
int frc_rdma_config(int handle, u32 trigger_type)
{
int i, j;
int flag = 30;
u32 count = 0;
int debug_flag = 32;
struct frc_rdma_info *frc_rdma = &frc_rdma_s;
struct frc_rdma_info *frc_rdma2 = &frc_rdma_s2;
// for debug_tool when rdma on
if (frc_rdma2->rdma_item_count > 0) {
i = frc_rdma->rdma_item_count;
count = frc_rdma2->rdma_item_count;
for (j = 0; j < count; j++) {
frc_rdma->rdma_table_addr[i * 2] =
frc_rdma2->rdma_table_addr[j * 2];
frc_rdma->rdma_table_addr[i * 2 + 1] =
frc_rdma2->rdma_table_addr[j * 2 + 1];
pr_frc(debug_flag, "addr:0x%04x, value:0x%08x\n",
frc_rdma->rdma_table_addr[i * 2],
frc_rdma->rdma_table_addr[i * 2 + 1]);
frc_rdma->rdma_item_count = ++i;
}
frc_rdma2->rdma_item_count = 0;
}
if (frc_rdma->rdma_item_count > 0 && handle == 0) {
// manual RDMA
struct rdma_regadr_s *man_ins = &rdma_regadr_t3[0];
WRITE_FRC_REG_BY_CPU(FRC_RDMA_ACCESS_MAN,
READ_FRC_REG(FRC_RDMA_ACCESS_MAN) & (~1));
WRITE_FRC_REG_BY_CPU(man_ins->rdma_ahb_start_addr,
frc_rdma->rdma_table_phy_addr & 0xffffffff);
WRITE_FRC_REG_BY_CPU(man_ins->rdma_ahb_end_addr,
(frc_rdma->rdma_table_phy_addr & 0xffffffff) +
frc_rdma->rdma_item_count * 8 - 1);
WRITE_FRC_BITS(man_ins->addr_inc_reg, 0,
man_ins->addr_inc_reg_bitpos, 1);
WRITE_FRC_BITS(man_ins->rw_flag_reg, 1, //1:write
man_ins->rw_flag_reg_bitpos, 1);
WRITE_FRC_REG_BY_CPU(FRC_RDMA_ACCESS_MAN,
READ_FRC_REG(FRC_RDMA_ACCESS_MAN) | 1);
//rdma_status = READ_FRC_REG(FRC_RDMA_STATUS);
pr_frc(flag, "config manual write done\n");
// frc_rdma->rdma_item_count = 0;
} else if (frc_rdma->rdma_item_count > 0 && handle == 1) {
//auto RDMA
struct rdma_regadr_s *man_ins = &rdma_regadr_t3[1];
WRITE_FRC_BITS(man_ins->trigger_mask_reg, 0,
man_ins->trigger_mask_reg_bitpos, 1);
WRITE_FRC_REG_BY_CPU(man_ins->rdma_ahb_start_addr,
frc_rdma->rdma_table_phy_addr & 0xffffffff);
WRITE_FRC_REG_BY_CPU(man_ins->rdma_ahb_end_addr,
(frc_rdma->rdma_table_phy_addr & 0xffffffff) +
frc_rdma->rdma_item_count * 8 - 1);
WRITE_FRC_BITS(man_ins->addr_inc_reg, 0,
man_ins->addr_inc_reg_bitpos, 1);
WRITE_FRC_BITS(man_ins->rw_flag_reg, 1, // 1:write
man_ins->rw_flag_reg_bitpos, 1);
WRITE_FRC_BITS(man_ins->trigger_mask_reg, handle,
man_ins->trigger_mask_reg_bitpos, 1);
pr_frc(flag, "config auto write done\n");
} else if (frc_rdma->rdma_item_count > 0 && handle == 2) {
//auto2 RDMA
struct rdma_regadr_s *man_ins = &rdma_regadr_t3[2];
WRITE_FRC_BITS(man_ins->trigger_mask_reg, 0,
man_ins->trigger_mask_reg_bitpos, 1);
//
WRITE_FRC_REG_BY_CPU(man_ins->rdma_ahb_start_addr,
frc_rdma->rdma_table_phy_addr & 0xffffffff);
WRITE_FRC_REG_BY_CPU(man_ins->rdma_ahb_end_addr,
(frc_rdma->rdma_table_phy_addr & 0xffffffff) +
frc_rdma->rdma_item_count * 8 - 1);
WRITE_FRC_BITS(man_ins->addr_inc_reg, 0,
man_ins->addr_inc_reg_bitpos, 1);
WRITE_FRC_BITS(man_ins->rw_flag_reg, 1, // 1:write
man_ins->rw_flag_reg_bitpos, 1);
WRITE_FRC_BITS(man_ins->trigger_mask_reg, 1,
man_ins->trigger_mask_reg_bitpos, 1);
pr_frc(flag, "config auto2 write done\n");
}
// memset(frc_rdma->rdma_table_addr, 0,
// sizeof(u32) * frc_rdma->rdma_item_count);
pr_frc(flag, "write rdma_item_count: %d\n", frc_rdma->rdma_item_count);
frc_rdma->rdma_item_count = 0;
// rdma_cnt = 0;
// pr_frc(flag, "rdma_cnt:%d, count:%d\n", rdma_cnt, count);
return 0;
}
void frc_rdma_table_config(u32 addr, u32 val)
{
int i;
struct frc_rdma_info *frc_rdma = &frc_rdma_s;
// struct frc_rdma_info *frc_rdma2 = &frc_rdma_s2;
i = frc_rdma->rdma_item_count;
pr_frc(8, "i:%d, addr:%x, val:%x\n", i, addr, val);
if ((i + 1) * 8 > frc_rdma->rdma_table_size) {
pr_frc(0, "frc rdma buffer overflow\n");
return;
}
frc_rdma->rdma_table_addr[i * 2] = addr & 0xffffffff;
frc_rdma->rdma_table_addr[i * 2 + 1] = val & 0xffffffff;
// frc_rdma2->rdma_table_addr[frc_rdma2->rdma_item_count * 2] = addr & 0xffffffff;
// frc_rdma2->rdma_table_addr[frc_rdma2->rdma_item_count * 2 + 1] = val & 0xffffffff;
frc_rdma->rdma_item_count++;
// frc_rdma2->rdma_item_count++;
pr_frc(8, "addr:%04x, value:%08x\n",
frc_rdma->rdma_table_addr[i * 2], frc_rdma->rdma_table_addr[i * 2 + 1]);
rdma_cnt++;
}
int frc_rdma_write_reg(u32 addr, u32 val)
{
// int ret;
int flag = 31;
// u32 write_val;
// ret = frc_check_table(addr);
// if (ret == -1)
// write_val = readl(frc_base + (addr << 2));
// else
// write_val = ret;
pr_frc(flag, "addr:0x%x write_val:0x%x\n", addr, val);
frc_rdma_table_config(addr, val);
return 0;
}
int frc_rdma_write_bits(u32 addr, u32 val, u32 start, u32 len)
{
int ret;
int flag = 31;
u32 read_val, write_val, mask;
// read_val = READ_FRC_REG(addr);
ret = frc_check_table(addr);
if (ret == -1)
read_val = readl(frc_base + (addr << 2));
else
read_val = ret;
mask = (((1L << len) - 1) << start);
write_val = read_val & ~mask;
write_val |= (val << start) & mask;
pr_frc(flag, "addr:0x%x read_val:0x%x write_val:0x%x\n",
addr, read_val, write_val);
frc_rdma_table_config(addr, write_val);
return 0;
}
int frc_rdma_update_reg_bits(u32 addr, u32 val, u32 mask)
{
int flag = 31;
// int index = -1;
u32 read_val, write_val;
// struct frc_rdma_info *frc_rdma = &frc_rdma_s;
/*check rdma_table reg value*/
if (mask == 0xFFFFFFFF) {
// WRITE_FRC_REG_BY_CPU(addr, val);
frc_rdma_table_config(addr, val);
} else {
// index = frc_check_table(addr);
// if (index == -1) {
read_val = readl(frc_base + (addr << 2));
val &= mask;
write_val = read_val & ~mask;
write_val |= val;
pr_frc(flag, "addr:0x%04x read_val:0x%x write_val:0x%x\n",
addr, read_val, write_val);
frc_rdma_table_config(addr, write_val);
// } else {
// read_val = (u32)ret;
// read_val = frc_rdma->rdma_table_addr[(index - 1) * 2 + 1];
// val &= mask;
// write_val = read_val & ~mask;
// write_val |= val;
// frc_rdma->rdma_table_addr[(index - 1) * 2 + 1] = write_val & 0xffffffff;
// pr_frc(flag, "addr:0x%04x re-addr0x%x read_val:0x%x write_val:0x%x\n",
// addr, frc_rdma->rdma_table_addr[(index - 1) * 2],
// read_val, write_val);
}
// val &= mask;
// write_val = read_val & ~mask;
// write_val |= val;
// pr_frc(flag, "addr:0x%04x read_val:0x%x write_val:0x%x\n",
// addr, read_val, write_val);
// frc_rdma_table_config(addr, write_val);
return 0;
}
int FRC_RDMA_VSYNC_WR_REG(u32 addr, u32 val)
{
int flag = 31;
if (get_frc_devp()->power_on_flag == 0)
return 0;
pr_frc(flag, "in: addr:0x%08x, val:0x%x\n", addr, val);
if (is_rdma_enable()) {
//frc_rdma_table_config(addr, val);
frc_rdma_write_reg(addr, val);
} else {
writel(val, (frc_base + (addr << 2)));
}
return 0;
}
EXPORT_SYMBOL(FRC_RDMA_VSYNC_WR_REG);
int FRC_RDMA_VSYNC_WR_BITS(u32 addr, u32 val, u32 start, u32 len)
{
if (get_frc_devp()->power_on_flag == 0)
return 0;
if (is_rdma_enable()) {
frc_rdma_write_bits(addr, val, start, len);
} else {
u32 write_val, mask;
u32 read_val = readl(frc_base + (addr << 2));
// write_val = (write_val & ~(((1L << (len)) - 1) << (start))) |
// ((u32)(val) << (start));
mask = (((1L << len) - 1) << start);
write_val = read_val & ~mask;
write_val |= (val << start) & mask;
writel(write_val, (frc_base + (addr << 2)));
}
return 0;
}
EXPORT_SYMBOL(FRC_RDMA_VSYNC_WR_BITS);
int FRC_RDMA_VSYNC_REG_UPDATE(u32 addr, u32 val, u32 mask)
{
int flag = 31;
if (get_frc_devp()->power_on_flag == 0)
return 0;
pr_frc(flag, "in: addr:0x%08x, val:0x%x, mask:0x%x\n", addr, val, mask);
if (is_rdma_enable()) {
frc_rdma_update_reg_bits(addr, val, mask);
} else {
if (mask == 0xFFFFFFFF) {
writel(val, (frc_base + (addr << 2)));
//frc_rdma_table_config(addr, val);
} else {
u32 write_val = readl(frc_base + (addr << 2));
val &= mask;
write_val &= ~mask;
write_val |= val;
// writel(write_val, (frc_base + (addr << 2)));
frc_rdma_table_config(addr, write_val);
}
}
return 0;
}
EXPORT_SYMBOL(FRC_RDMA_VSYNC_REG_UPDATE);
void frc_rdma_reg_list(void)
{
int i, temp;
struct frc_rdma_info *frc_rdma = frc_get_rdma_info();
temp = frc_rdma->rdma_item_count;
for (i = 0; i < temp; i++) {
pr_frc(0, "reg list: addr:0x%04x, value:0x%08x\n",
frc_rdma->rdma_table_addr[i * 2],
frc_rdma->rdma_table_addr[i * 2 + 1]);
}
pr_frc(0, "---------------------------------------\n");
}
/*val 30*/
void frc_rdma_cpu_test(int num)
{
int i;
u64 timestamp1, timestamp2;
struct frc_dev_s *devp = get_frc_devp();
devp->rdma_time = sched_clock();
timestamp1 = devp->rdma_time;
for (i = 0x0; i < num; i++)
WRITE_FRC_REG_BY_CPU(regs_table_test[i].addr, regs_table_test[i].value);
timestamp2 = sched_clock();
pr_frc(0, "CPU interrupt time:%lld\n", timestamp2 - timestamp1);
}
/*val 31*/
void frc_rdma_int_test(void)
{
int i;
u64 timestamp1;
struct frc_dev_s *devp = get_frc_devp();
devp->rdma_time = sched_clock();
timestamp1 = devp->rdma_time;
for (i = 0; i < REG_TEST_NUM; i++)
FRC_RDMA_VSYNC_WR_REG(regs_table_test[i].addr, regs_table_test[i].value);
// pr_frc(0, "test rdma interrupt time:%lld\n", timestamp2 - timestamp1);
}
/*val 20*/
void frc_rdma_speed_test(int num)
{
int i;
u64 timestamp1, timestamp2;
struct frc_rdma_info *frc_rdma = frc_get_rdma_info();
frc_rdma->rdma_item_count = 0;
timestamp1 = sched_clock();
for (i = 0x0; i < num; i++) {
frc_rdma->rdma_table_addr[i * 2] = regs_table_test[i].addr & 0xffff;
frc_rdma->rdma_table_addr[i * 2 + 1] = 0xffffffff - i;
frc_rdma->rdma_item_count++;
pr_frc(2, "addr:%04x, value:%08x\n",
frc_rdma->rdma_table_addr[i * 2], frc_rdma->rdma_table_addr[i * 2 + 1]);
}
// frc_rdma_write_test(frc_rdma->rdma_table_phy_addr,
// sizeof(frc_rdma->rdma_table_addr[1]) * REG_NUM);
WRITE_FRC_REG_BY_CPU(FRC_RDMA_ACCESS_MAN,
READ_FRC_REG(FRC_RDMA_ACCESS_MAN) & (~1));
WRITE_FRC_REG_BY_CPU(FRC_RDMA_AHB_START_ADDR_MAN, frc_rdma->rdma_table_phy_addr);
WRITE_FRC_REG_BY_CPU(FRC_RDMA_AHB_END_ADDR_MAN,
frc_rdma->rdma_table_phy_addr +
sizeof(u32) * frc_rdma->rdma_item_count * 2 - 1);
//WRITE_FRC_BITS(FRC_RDMA_ACCESS_MAN, 0, 1, 1); // 0 no-inc
WRITE_FRC_BITS(FRC_RDMA_ACCESS_MAN, 1, 2, 1); // 1 write
WRITE_FRC_REG_BY_CPU(FRC_RDMA_ACCESS_MAN,
READ_FRC_REG(FRC_RDMA_ACCESS_MAN) | 1);
while (1) {
if ((READ_FRC_REG(FRC_RDMA_STATUS) >> 24 & 0x1) == 1) {
WRITE_FRC_REG_BY_CPU(FRC_RDMA_CTRL, 0x1 << 24);
break;
}
}
timestamp2 = sched_clock();
pr_frc(0, "%sRDMA MANUAL time:%lld\n", __func__, timestamp2 - timestamp1);
}
/*val 40*/
void frc_auto_limit_test(int num)
{
int i;
u64 timestamp1, timestamp2;
struct frc_rdma_info *frc_rdma = frc_get_rdma_info();
struct frc_dev_s *devp = get_frc_devp();
frc_rdma->rdma_item_count = 0;
timestamp1 = sched_clock();
devp->rdma_time = timestamp1;
for (i = 0x0; i < num; i++) {
frc_rdma->rdma_table_addr[i * 2] = regs_table_test[i].addr & 0xffff;
frc_rdma->rdma_table_addr[i * 2 + 1] = regs_table_test[i].value & 0xffffffff;
frc_rdma->rdma_item_count++;
pr_frc(2, "addr:%04x\n", frc_rdma->rdma_table_addr[i]);
}
WRITE_FRC_BITS(FRC_RDMA_AUTO_SRC1_SEL, 0x0, 5, 1);
WRITE_FRC_REG_BY_CPU(FRC_RDMA_AHB_START_ADDR_1, frc_rdma->rdma_table_phy_addr);
WRITE_FRC_REG_BY_CPU(FRC_RDMA_AHB_END_ADDR_1,
frc_rdma->rdma_table_phy_addr + sizeof(u32) * frc_rdma->rdma_item_count * 2 - 1);
WRITE_FRC_BITS(FRC_RDMA_ACCESS_AUTO, 0x0, 1, 1); // 0: non-incremental reg access
WRITE_FRC_BITS(FRC_RDMA_ACCESS_AUTO, 0x1, 5, 1); // auto write
WRITE_FRC_BITS(FRC_RDMA_AUTO_SRC1_SEL, 0x1, 5, 1);
//frc_rdma->rdma_item_count = 0;
while (1) {
if ((READ_FRC_REG(FRC_RDMA_STATUS) >> 25 & 0x1) == 1)
//WRITE_FRC_REG_BY_CPU(FRC_RDMA_CTRL, 0x1 << 24);
break;
}
timestamp2 = sched_clock();
pr_frc(0, "%sRDMA MANUAL time:%lld\n", __func__, timestamp2 - timestamp1);
}
int frc_auto_test(int val, int val2)
{
if (val == 1)
frc_auto_limit_test(val2);
else if (val == 2)
frc_rdma_cpu_test(val2);
else if (val == 3)
frc_rdma_speed_test(val2);
return 0;
}
int frc_rdma_test_write(u32 handle, u32 addr, u32 val, u32 start, u32 len)
{
if (handle == 0) {
/* code */
FRC_RDMA_VSYNC_WR_REG(addr, val);
} else if (handle == 1) {
/* code */
// start -> mask
FRC_RDMA_VSYNC_REG_UPDATE(addr, val, start);
} else if (handle == 2) {
/*code */
FRC_RDMA_VSYNC_WR_BITS(addr, val, start, len);
}
return 0;
}
int frc_rdma_process(u32 val)
{
int i;
struct frc_rdma_info *frc_rdma = &frc_rdma_s;
if (is_rdma_enable()) {
if (!frc_rdma->buf_status) {
pr_frc(0, "rdma buffer is null\n");
return 0;
}
//frc_rdma_alloc_buf(frc_rdma);
}
// val 1: add
// val 2: rdma reg status
// val 3: manual non-incremental write start
// val 4:
// val 5: manual non-incremental read start
// val 10: read test reg
// val 11: reset test reg
if (val == 1) {
for (i = 0x0; i < 0x10; i++) {
frc_rdma->rdma_table_addr[i * 2] = (0x60 + i) & 0xffff;
frc_rdma->rdma_table_addr[i * 2 + 1] = 0xffffffff - i;
pr_frc(0, "addr:%04x, value:%08x\n",
frc_rdma->rdma_table_addr[i * 2],
frc_rdma->rdma_table_addr[i * 2 + 1]);
}
frc_rdma_write_test(frc_rdma->rdma_table_phy_addr, 0x7f);
} else if (val == 2) {
frc_rdma_reg_status();
} else if (val == 3) {
WRITE_FRC_REG_BY_CPU(FRC_RDMA_ACCESS_MAN, 0x5);
} else if (val == 4) {
for (i = 0x0; i < 0x10; i++) {
frc_rdma->rdma_table_addr[i] = (0x60 + i) & 0xffff;
pr_frc(0, "addr:%04x\n", frc_rdma->rdma_table_addr[i]);
}
frc_rdma_write_test(frc_rdma->rdma_table_phy_addr, 0x7f);
} else if (val == 5) {
WRITE_FRC_REG_BY_CPU(FRC_RDMA_ACCESS_MAN, 0x1);
pr_frc(0, "read done");
} else if (val == 6) {
frc_read_table();
} else if (val == 7) {
frc_read_table2_clear();
// pr_frc(0, "incremental write done\n");
} else if (val == 8) {
WRITE_FRC_REG_BY_CPU(FRC_RDMA_ACCESS_MAN, 0x7);
pr_frc(0, "incremental write done\n");
} else if (val == 9) {
frc_rdma->rdma_item_count = 0;
for (i = 0x0; i < 0x10; i++) {
frc_rdma->rdma_table_addr[i * 2] = (0x60 + i) & 0xffff;
frc_rdma->rdma_table_addr[i * 2 + 1] = 0xffffffff - i * i;
frc_rdma->rdma_item_count++;
pr_frc(0, "addr:%04x, value:%08x\n",
frc_rdma->rdma_table_addr[i * 2],
frc_rdma->rdma_table_addr[i * 2 + 1]);
}
WRITE_FRC_REG_BY_CPU(FRC_RDMA_AUTO_SRC1_SEL, 0x0);
WRITE_FRC_REG_BY_CPU(FRC_RDMA_AHB_START_ADDR_1, frc_rdma->rdma_table_phy_addr);
WRITE_FRC_REG_BY_CPU(FRC_RDMA_AHB_END_ADDR_1,
frc_rdma->rdma_table_phy_addr + frc_rdma->rdma_item_count * 8 - 1);
WRITE_FRC_BITS(FRC_RDMA_ACCESS_AUTO, 0x0, 1, 1); // 0: non-inc reg access
WRITE_FRC_BITS(FRC_RDMA_ACCESS_AUTO, 0x1, 5, 1); // auto write
WRITE_FRC_REG_BY_CPU(FRC_RDMA_AUTO_SRC1_SEL, 0x20);
} else if (val == 10) {
frc_rdma_read_test_reg();
} else if (val == 11) {
frc_rdma_reset_test_reg();
} else if (val == 20) {
//manual write speed test
frc_rdma_speed_test(REG_TEST_NUM);
} else if (val == 21) {
;
} else if (val == 22) {
;
//read_regs_tables();
} else if (val == 23) {
frc_rdma->rdma_item_count = 0;
for (i = 0x0; i < 0x10; i++) {
frc_rdma->rdma_table_addr[i * 2] = (0x60 + i) & 0xffff;
frc_rdma->rdma_table_addr[i * 2 + 1] = 0xfffffff - i * i;
frc_rdma->rdma_item_count++;
pr_frc(2, "addr:%04x\n", frc_rdma->rdma_table_addr[i]);
}
WRITE_FRC_REG_BY_CPU(FRC_RDMA_AHB_START_ADDR_1, frc_rdma->rdma_table_phy_addr);
WRITE_FRC_REG_BY_CPU(FRC_RDMA_AHB_END_ADDR_1,
frc_rdma->rdma_table_phy_addr + frc_rdma->rdma_item_count * 8 - 1);
WRITE_FRC_BITS(FRC_RDMA_ACCESS_AUTO, 0x0, 1, 1); // 0: non-inc reg access
WRITE_FRC_BITS(FRC_RDMA_ACCESS_AUTO, 0x1, 5, 1); // auto write
WRITE_FRC_BITS(FRC_RDMA_AUTO_SRC1_SEL, 0x1, 0, 1);
} else if (val == 24) {
//manual trigger
frc_rdma_config(0, 0);
} else if (val == 25) {
//auto trigger
frc_rdma_config(1, 0);
} else if (val == 26) {
//auto2 trigger
frc_rdma_config(2, 0);
} else if (val == 30) {
frc_rdma_cpu_test(REG_TEST_NUM);
} else if (val == 31) {
frc_rdma_int_test();
} else if (val == 40) {
WRITE_FRC_BITS(FRC_RDMA_AUTO_SRC1_SEL, 0x1, 5, 1);
// frc_auto_limit_test();
}
return 0;
}
irqreturn_t frc_rdma_isr(int irq, void *dev_id)
{
int i;
u32 rdma_status;
// struct frc_dev_s *devp = (struct frc_dev_s *)dev_id;
// u64 timestamp;
// if (frc_rdma_debug & 0x1)
// return IRQ_HANDLED;
rdma_status = READ_FRC_REG(FRC_RDMA_STATUS);
pr_frc(9, "%s frc isr frc_rdma status[1/2/3]:[%x][%x][%0x] rdma_cnt:%d\n",
__func__, READ_FRC_REG(FRC_RDMA_STATUS),
READ_FRC_REG(FRC_RDMA_STATUS2), READ_FRC_REG(FRC_RDMA_STATUS3), rdma_cnt);
for (i = 0; i < RDMA_NUM; i++) {
if (rdma_status & (0x1 << 24)) {
// pr_frc(2, "manual write done\n");
// timestamp = sched_clock() - devp->rdma_time;
pr_frc(9, "rdma manual int\n");
WRITE_FRC_BITS(FRC_RDMA_CTRL, 0x1, 24, 1);
rdma_cnt = 0;
break;
} else if (rdma_status & (0x1 << 25)) {
// WRITE_FRC_REG_BY_CPU(FRC_RDMA_CTRL, 0x1 << 25);
WRITE_FRC_BITS(FRC_RDMA_CTRL, 0x1, 25, 1);
// WRITE_FRC_REG_BY_CPU(FRC_RDMA_AUTO_SRC1_SEL, 0x0);
pr_frc(9, "rdma auto1 int\n");
rdma_cnt = 0;
//pr_frc(0, "auto write done cnt:%d\n", rdma_cnt);
break;
} else if (rdma_status & (0x1 << 26)) {
// WRITE_FRC_REG_BY_CPU(FRC_RDMA_CTRL, 0x1 << 26);
WRITE_FRC_BITS(FRC_RDMA_CTRL, 0x1, 26, 1);
// WRITE_FRC_REG_BY_CPU(FRC_RDMA_AUTO_SRC2_SEL, 0x0);
// timestamp = sched_clock() - devp->rdma_time;
pr_frc(0, "rdma auto2 int\n");
//pr_frc(0, "auto write done cnt:%d\n", rdma_cnt);
break;
} else if (rdma_status & (0x1 << 27)) {
// WRITE_FRC_REG_BY_CPU(FRC_RDMA_CTRL, 0x1 << 26);
WRITE_FRC_BITS(FRC_RDMA_CTRL, 0x1, 27, 1);
// WRITE_FRC_REG_BY_CPU(FRC_RDMA_AUTO_SRC3_SEL, 0x0);
// timestamp = sched_clock() - devp->rdma_time;
pr_frc(0, "rdma auto3 int\n");
//pr_frc(0, "auto write done cnt:%d\n", rdma_cnt);
break;
}
}
return IRQ_HANDLED;
}
int frc_rdma_init(void)
{
u32 data32;
struct frc_dev_s *devp;
struct frc_fw_data_s *fw_data;
struct frc_rdma_info *frc_rdma = &frc_rdma_s;
devp = get_frc_devp();
fw_data = (struct frc_fw_data_s *)devp->fw_data;
// struct frc_rdma_info *frc_rdma2 = &frc_rdma_s2;
data32 = 0;
data32 |= 0 << 7; /* write ddr urgent */
data32 |= 0 << 6; /* read ddr urgent */
data32 |= 0 << 4;
data32 |= 0 << 2;
data32 |= 0 << 1;
data32 |= 0 << 0;
// init clk
WRITE_FRC_BITS(FRC_RDMA_SYNC_CTRL, 1, 2, 1);
WRITE_FRC_BITS(FRC_RDMA_SYNC_CTRL, 1, 6, 1);
// rdma config
WRITE_FRC_REG_BY_CPU(FRC_RDMA_CTRL, data32);
// alloc buf
frc_rdma->rdma_table_size = FRC_RDMA_SIZE / 2;
// debug buf reserved
// frc_rdma2->rdma_table_size = FRC_RDMA_SIZE / 2;
//frc_rdma_alloc_buf(frc_rdma);
if (frc_rdma->buf_status) {
//RDMA buf ready
frc_rdma_enable = 1; // 0:closed 1:open
fw_data->frc_top_type.rdma_en = 0; // init rdma off
if (frc_rdma_enable && fw_data->frc_top_type.rdma_en)
pr_frc(0, "frc rdma ready.\n");
else
pr_frc(0, "frc rdma disable.\n");
} else {
PR_ERR("alloc frc rdma buffer failed\n");
return 0;
}
return 1;
}