365 lines
11 KiB
C
Executable file
365 lines
11 KiB
C
Executable file
/****************************************************************************
|
|
*
|
|
* Copyright (c) 2014 - 2016 Samsung Electronics Co., Ltd. All rights reserved
|
|
*
|
|
****************************************************************************/
|
|
|
|
#include <linux/uaccess.h>
|
|
#include <scsc/scsc_logring.h>
|
|
#include "pcie_proc.h"
|
|
#include "pcie_mif.h"
|
|
|
|
static struct proc_dir_entry *procfs_dir;
|
|
static bool pcie_val;
|
|
|
|
/* singleton */
|
|
struct pcie_mif *pcie_global;
|
|
|
|
static int pcie_procfs_open_file_generic(struct inode *inode, struct file *file)
|
|
{
|
|
file->private_data = PCIE_PDE_DATA(inode);
|
|
return 0;
|
|
}
|
|
|
|
PCIE_PROCFS_RW_FILE_OPS(pcie_trg);
|
|
#ifdef CONFIG_SCSC_PCIE_MBOX_EMULATION
|
|
PCIE_PROCFS_SEQ_FILE_OPS(pcie_dbg);
|
|
#endif
|
|
|
|
static ssize_t pcie_procfs_pcie_trg_read(struct file *file, char __user *user_buf, size_t count, loff_t *ppos)
|
|
{
|
|
char buf[128];
|
|
int pos = 0;
|
|
const size_t bufsz = sizeof(buf);
|
|
|
|
pos += scnprintf(buf + pos, bufsz - pos, "%d\n", (pcie_val ? 1 : 0));
|
|
|
|
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
|
|
}
|
|
|
|
#define ROW 52
|
|
#define COL 2
|
|
char *lookup_regs[ROW][COL] = {
|
|
{ "NEWMSG", "0" },
|
|
{ "SIGNATURE", "4" },
|
|
{ "OFFSET", "8" },
|
|
{ "RUNEN", "12" },
|
|
{ "DEBUG", "16" },
|
|
{ "AXIWCNT", "20" },
|
|
{ "AXIRCNT", "24" },
|
|
{ "AXIWADDR", "28" },
|
|
{ "AXIRADDR", "32" },
|
|
{ "TBD", "36" },
|
|
{ "AXICTRL", "40" },
|
|
{ "AXIDATA", "44" },
|
|
{ "AXIRDBP", "48" },
|
|
{ "IFAXIWCNT", "52" },
|
|
{ "IFAXIRCNT", "56" },
|
|
{ "IFAXIWADDR", "60" },
|
|
{ "IFAXIRADDR", "64" },
|
|
{ "IFAXICTRL", "68" },
|
|
{ "GRST", "72" },
|
|
{ "AMBA2TRANSAXIWCNT", "76" },
|
|
{ "AMBA2TRANSAXIRCNT", "80" },
|
|
{ "AMBA2TRANSAXIWADDR", "84" },
|
|
{ "AMBA2TRANSAXIRADDR", "88" },
|
|
{ "AMBA2TRANSAXICTR", "92" },
|
|
{ "TRANS2PCIEREADALIGNAXIWCNT", "96" },
|
|
{ "TRANS2PCIEREADALIGNAXIRCNT", "100" },
|
|
{ "TRANS2PCIEREADALIGNAXIWADDR", "104" },
|
|
{ "TRANS2PCIEREADALIGNAXIRADDR", "108" },
|
|
{ "TRANS2PCIEREADALIGNAXICTRL", "112" },
|
|
{ "READROUNDTRIPMIN", "116" },
|
|
{ "READROUNDTRIPMAX", "120" },
|
|
{ "READROUNDTRIPLAST", "124" },
|
|
{ "CPTAW0", "128" },
|
|
{ "CPTAW1", "132" },
|
|
{ "CPTAR0", "136" },
|
|
{ "CPTAR1", "140" },
|
|
{ "CPTB0", "144" },
|
|
{ "CPTW0", "148" },
|
|
{ "CPTW1", "152" },
|
|
{ "CPTW2", "156" },
|
|
{ "CPTR0", "160" },
|
|
{ "CPTR1", "164" },
|
|
{ "CPTR2", "168" },
|
|
{ "CPTRES", "172" },
|
|
{ "CPTAWDELAY", "176" },
|
|
{ "CPTARDELAY", "180" },
|
|
{ "CPTSRTADDR", "184" },
|
|
{ "CPTENDADDR", "188" },
|
|
{ "CPTSZLTHID", "192" },
|
|
{ "CPTPHSEL", "196" },
|
|
{ "CPTRUN", "200" },
|
|
{ "FPGAVER", "204" },
|
|
};
|
|
|
|
/* Trigger boot of Curator over SDIO without Chip Power Manager present */
|
|
static ssize_t pcie_procfs_pcie_trg_write(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos)
|
|
{
|
|
char buf[128];
|
|
char *sptr, *token;
|
|
unsigned int len = 0, pass = 0;
|
|
u32 address = 0;
|
|
u32 size;
|
|
u8 unit;
|
|
void *mem;
|
|
|
|
(void)file;
|
|
(void)ppos;
|
|
|
|
len = min(count, sizeof(buf) - 1);
|
|
if (copy_from_user(buf, user_buf, len))
|
|
return -EFAULT;
|
|
|
|
buf[len] = '\0';
|
|
sptr = buf;
|
|
|
|
while ((token = strsep(&sptr, " ")) != NULL) {
|
|
switch (pass) {
|
|
/* address */
|
|
case 0:
|
|
if ((token[0] == '0') && (token[1] == 'x')) {
|
|
if (kstrtou32(token, 16, &address)) {
|
|
SCSC_TAG_INFO(MIF, "Incorrect format,,,address should start by 0x\n");
|
|
SCSC_TAG_INFO(MIF, "Example: \"0xaaaabbbb 256 8\"\n");
|
|
goto error;
|
|
}
|
|
SCSC_TAG_INFO(MIF, "address %d 0x%x\n", address, address);
|
|
} else {
|
|
SCSC_TAG_INFO(MIF, "Incorrect format,,,address should start by 0x\n");
|
|
SCSC_TAG_INFO(MIF, "Example: \"0xaaaabbbb 256 8\"\n");
|
|
goto error;
|
|
}
|
|
break;
|
|
/* size */
|
|
case 1:
|
|
if (kstrtou32(token, 0, &size)) {
|
|
SCSC_TAG_INFO(MIF, "Incorrect format,,, for size\n");
|
|
goto error;
|
|
}
|
|
SCSC_TAG_INFO(MIF, "size: %d\n", size);
|
|
break;
|
|
|
|
/* unit */
|
|
case 2:
|
|
if (kstrtou8(token, 0, &unit)) {
|
|
SCSC_TAG_INFO(MIF, "Incorrect format,,, for unit\n");
|
|
goto error;
|
|
}
|
|
if ((unit != 8) && (unit != 16) && (unit != 32)) {
|
|
SCSC_TAG_INFO(MIF, "Unit %d should be 8/16/32\n", unit);
|
|
goto error;
|
|
}
|
|
SCSC_TAG_INFO(MIF, "unit: %d\n", unit);
|
|
break;
|
|
}
|
|
pass++;
|
|
}
|
|
if (pass != 3) {
|
|
SCSC_TAG_INFO(MIF, "Wrong format: <start_address> <size> <unit>\n");
|
|
SCSC_TAG_INFO(MIF, "Example: \"0xaaaabbbb 256 8\"\n");
|
|
goto error;
|
|
}
|
|
|
|
mem = pcie_mif_get_mem(pcie_global);
|
|
if (!mem) {
|
|
SCSC_TAG_INFO(MIF, "Mem not allocated\n");
|
|
goto error;
|
|
}
|
|
|
|
/* Add offset */
|
|
mem = mem + address;
|
|
|
|
SCSC_TAG_INFO(MIF, "Phy addr :%x ref addr :%x\n", mem, address);
|
|
SCSC_TAG_INFO(MIF, "------------------------------------------------------------------------\n");
|
|
print_hex_dump(KERN_WARNING, "ref addr offset: ", DUMP_PREFIX_OFFSET, 16, unit/8, mem, size, 1);
|
|
SCSC_TAG_INFO(MIF, "------------------------------------------------------------------------\n");
|
|
error:
|
|
return count;
|
|
#if 0
|
|
char buf[128];
|
|
char *sptr, *token;
|
|
unsigned int len = 0, pass = 0;
|
|
u32 value = 0;
|
|
int i = 0;
|
|
int rc;
|
|
|
|
int match = 0, offset = 0;
|
|
|
|
len = min(count, sizeof(buf) - 1);
|
|
if (copy_from_user(buf, user_buf, len))
|
|
return -EFAULT;
|
|
|
|
buf[len] = '\0';
|
|
sptr = buf;
|
|
|
|
while ((token = strsep(&sptr, " ")) != NULL) {
|
|
switch (pass) {
|
|
/* register */
|
|
case 0:
|
|
SCSC_TAG_INFO(PCIE_MIF, "str %s\n", lookup_regs[0][0]);
|
|
SCSC_TAG_INFO(PCIE_MIF, "token %s\n", token);
|
|
SCSC_TAG_INFO(PCIE_MIF, "len %d\n", len);
|
|
for (i = 0; i < ROW; i++)
|
|
if (!strncmp(lookup_regs[i][0], token, len)) {
|
|
rc = kstrtou32(lookup_regs[i][1], 0, &offset);
|
|
if (rc)
|
|
match = 0;
|
|
else
|
|
match = 1;
|
|
break;
|
|
}
|
|
|
|
if (!match) {
|
|
SCSC_TAG_INFO(PCIE_MIF, "Register %s not Found!!\n", token);
|
|
SCSC_TAG_INFO(PCIE_MIF, "Type 'cat /proc/driver/pcie_ctrl/pcie_dbg' to get register names\n");
|
|
}
|
|
break;
|
|
/* value */
|
|
case 1:
|
|
if ((token[0] == '0') && (token[1] == 'x')) {
|
|
if (kstrtou32(token, 16, &value)) {
|
|
SCSC_TAG_INFO(PCIE_MIF, "Incorrect format,,,address should start by 0x\n");
|
|
SCSC_TAG_INFO(PCIE_MIF, "Example: \"0xaaaabbbb 256 8\"\n");
|
|
goto error;
|
|
}
|
|
} else {
|
|
SCSC_TAG_INFO(PCIE_MIF, "Incorrect format,,,address should start by 0x\n");
|
|
SCSC_TAG_INFO(PCIE_MIF, "Example: \"0xaaaabbbb 256 8\"\n");
|
|
goto error;
|
|
}
|
|
break;
|
|
}
|
|
pass++;
|
|
}
|
|
if (pass != 2 && !match) {
|
|
SCSC_TAG_INFO(PCIE_MIF, "Wrong format: <register> <value (hex)>\n");
|
|
SCSC_TAG_INFO(PCIE_MIF, "Example: \"DEBUGADDR 0xaaaabbbb\"\n");
|
|
goto error;
|
|
}
|
|
SCSC_TAG_INFO(PCIE_MIF, "Setting value 0x%x to register %s offset %d\n", value, lookup_regs[i][0], offset);
|
|
pcie_mif_set_bar0_register(pcie_global, value, offset);
|
|
error:
|
|
return count;
|
|
#endif
|
|
}
|
|
|
|
#ifdef CONFIG_SCSC_PCIE_MBOX_EMULATION
|
|
static int pcie_procfs_pcie_dbg_show(struct seq_file *m, void *v)
|
|
{
|
|
struct scsc_bar0_reg bar0;
|
|
|
|
if (!pcie_global) {
|
|
seq_puts(m, "endpoint not registered");
|
|
return 0;
|
|
}
|
|
|
|
pcie_mif_get_bar0(pcie_global, &bar0);
|
|
|
|
seq_puts(m, "\n---------BAR0---------\n");
|
|
|
|
seq_printf(m, "NEWMSG 0x%08X\n", bar0.NEWMSG);
|
|
seq_printf(m, "SIGNATURE 0x%08X\n", bar0.SIGNATURE);
|
|
seq_printf(m, "OFFSET 0x%08X\n", bar0.OFFSET);
|
|
seq_printf(m, "RUNEN 0x%08X\n", bar0.RUNEN);
|
|
seq_printf(m, "DEBUG 0x%08X\n", bar0.DEBUG);
|
|
seq_printf(m, "AXIWCNT 0x%08X\n", bar0.AXIWCNT);
|
|
seq_printf(m, "AXIRCNT 0x%08X\n", bar0.AXIRCNT);
|
|
seq_printf(m, "AXIWADDR 0x%08X\n", bar0.AXIWADDR);
|
|
seq_printf(m, "AXIRADDR 0x%08X\n", bar0.AXIRADDR);
|
|
seq_printf(m, "TBD 0x%08X\n", bar0.TBD);
|
|
seq_printf(m, "AXICTRL 0x%08X\n", bar0.AXICTRL);
|
|
seq_printf(m, "AXIDATA 0x%08X\n", bar0.AXIDATA);
|
|
seq_printf(m, "AXIRDBP 0x%08X\n", bar0.AXIRDBP);
|
|
seq_printf(m, "IFAXIWCNT 0x%08X\n", bar0.IFAXIWCNT);
|
|
seq_printf(m, "IFAXIRCNT 0x%08X\n", bar0.IFAXIRCNT);
|
|
seq_printf(m, "IFAXIWADDR 0x%08X\n", bar0.IFAXIWADDR);
|
|
seq_printf(m, "IFAXIRADDR 0x%08X\n", bar0.IFAXIRADDR);
|
|
seq_printf(m, "IFAXICTRL 0x%08X\n", bar0.IFAXICTRL);
|
|
seq_printf(m, "GRST 0x%08X\n", bar0.GRST);
|
|
seq_printf(m, "AMBA2TRANSAXIWCNT 0x%08X\n", bar0.AMBA2TRANSAXIWCNT);
|
|
seq_printf(m, "AMBA2TRANSAXIRCNT 0x%08X\n", bar0.AMBA2TRANSAXIRCNT);
|
|
seq_printf(m, "AMBA2TRANSAXIWADDR 0x%08X\n", bar0.AMBA2TRANSAXIWADDR);
|
|
seq_printf(m, "AMBA2TRANSAXIRADDR 0x%08X\n", bar0.AMBA2TRANSAXIRADDR);
|
|
seq_printf(m, "AMBA2TRANSAXICTR 0x%08X\n", bar0.AMBA2TRANSAXICTR);
|
|
seq_printf(m, "TRANS2PCIEREADALIGNAXIWCNT 0x%08X\n", bar0.TRANS2PCIEREADALIGNAXIWCNT);
|
|
seq_printf(m, "TRANS2PCIEREADALIGNAXIRCNT 0x%08X\n", bar0.TRANS2PCIEREADALIGNAXIRCNT);
|
|
seq_printf(m, "TRANS2PCIEREADALIGNAXIWADDR 0x%08X\n", bar0.TRANS2PCIEREADALIGNAXIWADDR);
|
|
seq_printf(m, "TRANS2PCIEREADALIGNAXIRADDR 0x%08X\n", bar0.TRANS2PCIEREADALIGNAXIRADDR);
|
|
seq_printf(m, "TRANS2PCIEREADALIGNAXICTRL 0x%08X\n", bar0.TRANS2PCIEREADALIGNAXICTRL);
|
|
seq_printf(m, "READROUNDTRIPMIN 0x%08X\n", bar0.READROUNDTRIPMIN);
|
|
seq_printf(m, "READROUNDTRIPMAX 0x%08X\n", bar0.READROUNDTRIPMAX);
|
|
seq_printf(m, "READROUNDTRIPLAST 0x%08X\n", bar0.READROUNDTRIPLAST);
|
|
seq_printf(m, "CPTAW0 0x%08X\n", bar0.CPTAW0);
|
|
seq_printf(m, "CPTAW1 0x%08X\n", bar0.CPTAW1);
|
|
seq_printf(m, "CPTAR0 0x%08X\n", bar0.CPTAR0);
|
|
seq_printf(m, "CPTAR1 0x%08X\n", bar0.CPTAR1);
|
|
seq_printf(m, "CPTB0 0x%08X\n", bar0.CPTB0);
|
|
seq_printf(m, "CPTW0 0x%08X\n", bar0.CPTW0);
|
|
seq_printf(m, "CPTW1 0x%08X\n", bar0.CPTW1);
|
|
seq_printf(m, "CPTW2 0x%08X\n", bar0.CPTW2);
|
|
seq_printf(m, "CPTR0 0x%08X\n", bar0.CPTR0);
|
|
seq_printf(m, "CPTR1 0x%08X\n", bar0.CPTR1);
|
|
seq_printf(m, "CPTR2 0x%08X\n", bar0.CPTR2);
|
|
seq_printf(m, "CPTRES 0x%08X\n", bar0.CPTRES);
|
|
seq_printf(m, "CPTAWDELAY 0x%08X\n", bar0.CPTAWDELAY);
|
|
seq_printf(m, "CPTARDELAY 0x%08X\n", bar0.CPTARDELAY);
|
|
seq_printf(m, "CPTSRTADDR 0x%08X\n", bar0.CPTSRTADDR);
|
|
seq_printf(m, "CPTENDADDR 0x%08X\n", bar0.CPTENDADDR);
|
|
seq_printf(m, "CPTSZLTHID 0x%08X\n", bar0.CPTSZLTHID);
|
|
seq_printf(m, "CPTPHSEL 0x%08X\n", bar0.CPTPHSEL);
|
|
seq_printf(m, "CPTRUN 0x%08X\n", bar0.CPTRUN);
|
|
seq_printf(m, "FPGAVER 0x%08X\n", bar0.FPGAVER);
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static const char *procdir = "driver/pcie_ctrl";
|
|
|
|
#define PCIE_DIRLEN 128
|
|
|
|
|
|
int pcie_create_proc_dir(struct pcie_mif *pcie)
|
|
{
|
|
char dir[PCIE_DIRLEN];
|
|
struct proc_dir_entry *parent;
|
|
|
|
(void)snprintf(dir, sizeof(dir), "%s", procdir);
|
|
parent = proc_mkdir(dir, NULL);
|
|
if (parent) {
|
|
#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 4, 0))
|
|
parent->data = NULL;
|
|
#endif
|
|
procfs_dir = parent;
|
|
PCIE_PROCFS_ADD_FILE(NULL, pcie_trg, parent, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
|
|
#ifdef CONFIG_SCSC_PCIE_MBOX_EMULATION
|
|
PCIE_PROCFS_SEQ_ADD_FILE(NULL, pcie_dbg, parent, S_IRUSR | S_IRGRP | S_IROTH);
|
|
#endif
|
|
} else {
|
|
SCSC_TAG_INFO(PCIE_MIF, "failed to create /proc dir\n");
|
|
return -EINVAL;
|
|
}
|
|
|
|
pcie_global = pcie;
|
|
|
|
return 0;
|
|
}
|
|
|
|
void pcie_remove_proc_dir(void)
|
|
{
|
|
if (procfs_dir) {
|
|
char dir[PCIE_DIRLEN];
|
|
|
|
PCIE_PROCFS_REMOVE_FILE(pcie_trg, procfs_dir);
|
|
#ifdef CONFIG_SCSC_PCIE_MBOX_EMULATION
|
|
PCIE_PROCFS_REMOVE_FILE(pcie_dbg, procfs_dir);
|
|
#endif
|
|
|
|
(void)snprintf(dir, sizeof(dir), "%s", procdir);
|
|
remove_proc_entry(dir, NULL);
|
|
procfs_dir = NULL;
|
|
}
|
|
|
|
pcie_global = NULL;
|
|
}
|