Commit 1625be9d authored by Mikhail Karpenko's avatar Mikhail Karpenko

Merge branch 'master' of https://github.com/Elphel/linux-elphel into debug

parents 7180ee47 d8d417d9
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -6,15 +6,51 @@
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
<triggers>clean,full,incremental,</triggers>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.cdt.managedbuilder.core.genmakebuilder.launch</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder.launch</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/bitbake compile [Builder].launch</value>
</dictionary>
<dictionary>
<key>incclean</key>
<value>true</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/bitbake deploy [Builder].launch</value>
</dictionary>
<dictionary>
<key>incclean</key>
<value>true</value>
</dictionary>
</arguments>
</buildCommand>
</buildSpec>
......
......@@ -19,6 +19,7 @@
#include <linux/ahci_platform.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/of_address.h>
#include <linux/slab.h>
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
......@@ -39,6 +40,7 @@ static const struct of_device_id ahci_elphel_of_match[];
struct elphel_ahci_priv {
u32 clb_offs;
u32 fb_offs;
u32 base_addr;
};
static int elphel_port_start(struct ata_port *ap)
......@@ -53,6 +55,8 @@ static int elphel_port_start(struct ata_port *ap)
libahci_debug_init(ap->host);
dev_info(dev, "starting port %d", ap->port_no);
libahci_debug_wait_flag();
pp = devm_kzalloc(dev, sizeof(struct ahci_port_priv), GFP_KERNEL);
if (!pp)
return -ENOMEM;
......@@ -68,15 +72,18 @@ static int elphel_port_start(struct ata_port *ap)
* Set predefined addresses
*/
pp->cmd_slot = hpriv->mmio + dpriv->clb_offs;
pp->cmd_slot_dma = virt_to_phys(pp->cmd_slot);
//pp->cmd_slot_dma = virt_to_phys(pp->cmd_slot);
pp->cmd_slot_dma = 0x80000000 + dpriv->clb_offs;
pp->rx_fis = hpriv->mmio + dpriv->fb_offs;
pp->rx_fis_dma = virt_to_phys(pp->rx_fis);
//pp->rx_fis_dma = virt_to_phys(pp->rx_fis);
pp->rx_fis_dma = 0x80000000 + dpriv->fb_offs;
dev_info(dev, "cmd_slot and rx_fis addresses are set");
dev_info(dev, "\tmmio address: 0x%p", hpriv->mmio);
dev_info(dev, "\tcommand slot virtual address: 0x%p", pp->cmd_slot);
dev_info(dev, "\rx fis virtual address: 0x%p", pp->rx_fis);
/*printk(KERN_DEBUG "cmd_slot: 0x%p", pp->cmd_slot);
printk(KERN_DEBUG "cmd_slot_dma: 0x%08u", pp->cmd_slot_dma);
printk(KERN_DEBUG "rx_fis: 0x%p", pp->rx_fis);
printk(KERN_DEBUG "rx_fis_dma: 0x%08u", pp->rx_fis_dma);
printk(KERN_DEBUG "base_addr: 0x%08u", dpriv->base_addr);*/
/*
* Save off initial list of interrupts to be enabled.
......@@ -93,7 +100,10 @@ static int elphel_parse_prop(const struct device_node *devn,
struct device *dev,
struct elphel_ahci_priv *dpriv)
{
u64 size;
unsigned int flags;
const __be32 *val;
struct resource res;
if (!devn) {
dev_err(dev, "device tree node is not found");
......@@ -104,6 +114,14 @@ static int elphel_parse_prop(const struct device_node *devn,
dpriv->clb_offs = be32_to_cpup(val);
val = of_get_property(devn, PROP_NAME_FB_OFFS, NULL);
dpriv->fb_offs = be32_to_cpup(val);
val = of_get_address(devn, 0, NULL, NULL);
if (val != NULL) {
dpriv->base_addr = be32_to_cpu(val);
dev_info(dev, "base_addr: 0x%08u", dpriv->base_addr);
} else {
dev_err(dev, "can not get register address");
}
//of_address_to_resource(devn, 0, &res);
return 0;
}
......@@ -120,6 +138,7 @@ static int elphel_drv_probe(struct platform_device *pdev)
unsigned int reg_val;
dev_info(&pdev->dev, "probing Elphel AHCI driver");
drv_priv = devm_kzalloc(dev, sizeof(struct elphel_ahci_priv), GFP_KERNEL);
if (!drv_priv)
return -ENOMEM;
......@@ -149,6 +168,19 @@ static int elphel_drv_probe(struct platform_device *pdev)
reg_val = readl(hpriv->mmio + HOST_VERSION);
dev_info(dev, "HOST VS register: 0x%08x", reg_val);
phys_addr_t paddr = virt_to_phys(hpriv->mmio);
void *vaddr = phys_to_virt(paddr);
dev_err(dev, "current mmio virt addr: %p\n", hpriv->mmio);
dev_err(dev, "current mmio virt addr as uint: %u\n", hpriv->mmio);
dev_err(dev, "mmio phys addr: %u\n", paddr);
dev_err(dev, "mmio phys addr as tr: %p\n", paddr);
dev_err(dev, "back converted mmio virt addr: %p\n", vaddr);
//printk(KERN_DEBUG, "current mmio virt addr: %p\n", hpriv->mmio);
//printk(KERN_DEBUG, "mmio phys addr: %u\n", paddr);
//printk(KERN_DEBUG, "back converted mmio virt addr: %p\n", vaddr);
printk(KERN_DEBUG "======");
ret = ahci_platform_init_host(pdev, hpriv, &ahci_elphel_port_info,
&ahci_platform_sht);
if (ret) {
......
......@@ -602,6 +602,7 @@ static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
int offset = ahci_scr_offset(link->ap, sc_reg);
int len;
u32 tmp;
char *msg_str = kzalloc(LIBAHCI_DEBUG_BUFSZ, GFP_KERNEL);
if (msg_str != NULL) {
len = snprintf(msg_str, LIBAHCI_DEBUG_BUFSZ, "read port %u SATA status and control registers", link->ap->port_no);
......@@ -612,7 +613,8 @@ static int ahci_scr_read(struct ata_link *link, unsigned int sc_reg, u32 *val)
*val = readl(port_mmio + offset);
if (msg_str != NULL) {
len = snprintf(msg_str, LIBAHCI_DEBUG_BUFSZ, "\tport %u offset: 0x%x, value: 0x%x", link->ap->port_no, offset, *val);
tmp = readl(port_mmio + PORT_CMD);
len = snprintf(msg_str, LIBAHCI_DEBUG_BUFSZ, "\tport %u offset: 0x%x, value: 0x%x, PxCMD: 0x%08x", link->ap->port_no, offset, *val, tmp);
libahci_debug_event(link->ap, msg_str, len);
}
......@@ -1730,7 +1732,7 @@ static int ahci_hardreset(struct ata_link *link, unsigned int *class,
ata_tf_to_fis(&tf, 0, 0, d2h_fis);
if (msg_str != NULL) {
len = snprintf(msg_str, LIBAHCI_DEBUG_BUFSZ, "\tprocced to sata_link_hardreset");
len = snprintf(msg_str, LIBAHCI_DEBUG_BUFSZ, "\tproceed to sata_link_hardreset");
libahci_debug_event(ap, msg_str, len);
}
rc = sata_link_hardreset(link, timing, deadline, &online,
......@@ -2302,6 +2304,8 @@ unsigned int ahci_qc_issue(struct ata_queued_cmd *qc)
pp->fbs_last_dev = qc->dev->link->pmp;
}
//libahci_debug_wait_flag();
writel(1 << qc->tag, port_mmio + PORT_CMD_ISSUE);
ahci_sw_activity(qc->dev->link);
......@@ -2531,7 +2535,7 @@ static void ahci_enable_fbs(struct ata_port *ap)
int len;
char *msg_str = kzalloc(LIBAHCI_DEBUG_BUFSZ, GFP_KERNEL);
if (msg_str != NULL) {
if (msg_str != NULL && pp->fbs_supported) {
len = snprintf(msg_str, LIBAHCI_DEBUG_BUFSZ, "enable port %u FIS-based switching", ap->port_no);
libahci_debug_event(ap, msg_str, len);
kfree(msg_str);
......@@ -2573,7 +2577,7 @@ static void ahci_disable_fbs(struct ata_port *ap)
int len;
char *msg_str = kzalloc(LIBAHCI_DEBUG_BUFSZ, GFP_KERNEL);
if (msg_str != NULL) {
if (msg_str != NULL && pp->fbs_supported) {
len = snprintf(msg_str, LIBAHCI_DEBUG_BUFSZ, "disable port %u FIS-based switching", ap->port_no);
libahci_debug_event(ap, msg_str, len);
kfree(msg_str);
......
......@@ -15,7 +15,8 @@
static struct dentry *debug_root = NULL;
static struct libahci_debug_list debug_list = {.debug = 0};
static struct ahci_cmd cmd;
static struct simple_buff init_buff;
static bool load_flag = false;
volatile unsigned int *mem_buff;
/*
* Print PxIS (0x10) analysis
......@@ -247,6 +248,7 @@ static int libahci_debug_host_show(struct seq_file *f, void *p)
{
struct ata_host *host = f->private;
struct host_regs hr = {0};
phys_addr_t buff_addr;
libahci_debug_read_host_regs(host, &hr);
seq_printf(f, "CAP:\t\t0x%08X\n", hr.CAP);
......@@ -261,6 +263,9 @@ static int libahci_debug_host_show(struct seq_file *f, void *p)
seq_printf(f, "EM_CTL:\t\t0x%08X\n", hr.EM_CTL);
seq_printf(f, "BOHC:\t\t0x%08X\n", hr.BOHC);
buff_addr = virt_to_phys(mem_buff);
seq_printf(f, "\nbuffer location:\t\t0x%08X\n", buff_addr);
return 0;
}
......@@ -315,7 +320,6 @@ static int libahci_debug_rdesc_open(struct inode *i_node, struct file *f)
static int libahci_debug_events_open(struct inode *i_node, struct file *f)
{
int err = 0;
int sz;
unsigned long flags;
struct libahci_debug_list *list;
struct ata_port *port = i_node->i_private;
......@@ -344,13 +348,6 @@ static int libahci_debug_events_open(struct inode *i_node, struct file *f)
// Associate debug list entry with corresponding file
f->private_data = list;
// Copy the content of init buffer to libahci_debug_buff
/*if (init_buff.tail > init_buff.head) {
sz = init_buff.tail- init_buff.head;
memcpy(list->libahci_debug_buf, init_buff.buff, sz);
list->tail = sz;
}*/
fail_handler:
return err;
}
......@@ -479,19 +476,6 @@ void libahci_debug_event(const struct ata_port *port, char *msg, size_t msg_sz)
}
kfree(format_msg);
}
} else if (init_buff.initialized) {
// debugfs file is not open, write to tmp buffer
/*format_msg = kzalloc(LIBAHCI_DEBUG_BUFSZ, GFP_KERNEL);
if (format_msg != NULL) {
spin_lock_irqsave(&pos->debug_list_lock, flags);
len = snprintf(format_msg, LIBAHCI_DEBUG_BUFSZ, "%s %s\n", EVT_MARKER, msg);
for (i = 0; i < len; i++) {
init_buff.buff[(init_buff.tail+ i) % LIBAHCI_DEBUG_BUFSZ] = format_msg[i];
}
init_buff.tail = (init_buff.tail + len) % LIBAHCI_DEBUG_BUFSZ;
spin_unlock_irqrestore(&pos->debug_list_lock, flags);
}*/
}
}
EXPORT_SYMBOL_GPL(libahci_debug_event);
......@@ -668,6 +652,70 @@ static int libahci_debug_fis_release(struct inode *i_node, struct file *f)
return 0;
}
static ssize_t libahci_debug_load(struct file *f, const char __user *buff, size_t buff_sz, loff_t *ppos)
{
load_flag = true;
return buff_sz;
}
/*
* This function waits until the loading flag is set through debugfs file.
* The state of the flag is checked every 100ms.
*/
void libahci_debug_wait_flag(void)
{
printk(KERN_DEBUG "%s Waiting for flag to be written to debugfs", MARKER);
while (load_flag == false) {
/*set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(msecs_to_jiffies(100));*/
msleep(500);
}
load_flag = false;
}
EXPORT_SYMBOL_GPL(libahci_debug_wait_flag);
/*
* Copy controller registers to buffer memory
*/
void libahci_debug_state_dump(struct device *dev)
{
static u32 page_cntr;
phys_addr_t v2p;
u32 *p2v;
int i;
if (!mem_buff) {
dev_err(dev, "dump buffer has not been allocated");
return;
}
v2p = virt_to_phys(mem_buff);
dev_info(dev, "write to buffer: 0x%08x", v2p);
mem_buff[0] = 0xdeadbeef;
for (i = 1; i < 100; i++) {
mem_buff[i] = 0xa5a5a5a5;
}
/*__cpu_flush_kern_all();
outer_flush_all();
for (i = 0; i < 100; i++) {
v2p = virt_to_phys(mem_buff + 4*i);
dev_info(dev, "read phys addr: 0x%x, data: 0x%08x", v2p, *(mem_buff + 4*i));
}*/
}
static void libahci_debug_buff_init(struct device *dev)
{
dma_addr_t dma_handle;
dev_info(dev, "trying to allocate dump buffer");
mem_buff = dmam_alloc_coherent(dev, PAGE_SIZE, &dma_handle, GFP_KERNEL);
if (!mem_buff)
dev_err(dev, "unable to allocate memory");
else
dev_info(dev, "buffer allocated at 0x%08x", dma_handle);
}
static const struct file_operations libahci_debug_host_ops = {
.open = libahci_debug_host_open,
.read = seq_read,
......@@ -703,6 +751,10 @@ static const struct file_operations libahci_debug_chdr_ops = {
.release = libahci_debug_fis_release,
};
static const struct file_operations libahci_debug_load_ops= {
.write = libahci_debug_load,
};
static int libahci_debug_init_sg(void)
{
cmd.sg_buff = kzalloc(CMD_DMA_BUFSZ, GFP_KERNEL);
......@@ -731,6 +783,9 @@ int libahci_debug_init(struct ata_host *host)
}
debugfs_create_file("rdesc_host", 0644,
debug_root, host, &libahci_debug_host_ops);
debugfs_create_file("loading", 0222,
debug_root, host, &libahci_debug_load_ops);
/* Create subdir for each port and add there several files:
* one for port registers, one for port events log and
* two files for working with FISes
......@@ -752,13 +807,8 @@ int libahci_debug_init(struct ata_host *host)
goto fail_handler;
}
/*init_buff.buff = kzalloc(LIBAHCI_DEBUG_BUFSZ, GFP_KERNEL);
if (init_buff.buff == NULL) {
kfree(cmd.sg_buff);
goto fail_handler;
}
init_buff.initialized = true;*/
libahci_debug_buff_init(host->dev);
libahci_debug_state_dump(host->dev);
return 0;
fail_handler:
......
......@@ -19,6 +19,10 @@
#define CMD_DMA_BUFSZ 512
#define PORT_RESERVED_2 40
#define PORT_VENDOR_BYTES 16
#define BUFFER_ADDRESS 0x38130000
/* Buffer is 100 Mb*/
#define BUFFER_PAGES 25600
#define SEGMENT_SIZE 0x10000
#define LIBAHCI_DEBUG_BUFSZ 16384
struct libahci_debug_list {
......@@ -33,13 +37,6 @@ struct libahci_debug_list {
spinlock_t debug_list_lock;
};
struct simple_buff {
char *buff;
int head;
int tail;
bool initialized;
};
struct ahci_cmd_fis {
__le32 dw0;
__le32 dw1;
......@@ -106,5 +103,7 @@ void libahci_debug_dump_irq(u32 status);
void libahci_debug_dump_sg(const struct ata_queued_cmd *qc, const char *prefix);
void libahci_debug_irq_notify(const struct ata_port *ap);
void libahci_debug_exec_cmd(struct ata_port *ap);
void libahci_debug_wait_flag(void);
void libahci_debug_state_dump(struct device *dev);
#endif /* _LIBAHCI_DEBUG_H_ */
/*!***************************************************************************
*! FILE NAME : elphel393-mem.c
*! DESCRIPTION: Reserve large memory range at boot time (when it is available)
*! to use as a circular video buffer
*! Copyright (C) 2015 Elphel, Inc.
*! -----------------------------------------------------------------------------**
*!
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*!****************************************************************************/
#include <linux/module.h>
#include <linux/init.h>
#include <linux/of.h>
......@@ -9,31 +29,36 @@
#include <asm/dma-mapping.h>
#include <asm/outercache.h>
#include <asm/cacheflush.h>
#include "elphel393-mem.h"
#define SYSFS_PERMISSIONS 0644 /* default permissions for sysfs files */
#define SYSFS_READONLY 0444
#define SYSFS_WRITEONLY 0222
static ssize_t get_paddr(struct device *dev, struct device_attribute *attr, char *buf);
/*
struct elphel_buf_t
{
void *vaddr;
dma_addr_t paddr;
ssize_t size;
};
static struct elphel_buf_t elphel_buf = {
*/
static struct elphel_buf_t _elphel_buf = {
.vaddr = NULL,
.paddr = 0,
.size = 0
};
struct elphel_buf_t elphel_buf; // static can not be extern
EXPORT_SYMBOL_GPL(elphel_buf);
static int __init elphelmem_init(void)
{
struct device_node *node;
const __be32 *bufsize_be;
elphel_buf = _elphel_buf; // static can not be extern
node = of_find_node_by_name(NULL, "elphel393-mem");
if (!node)
{
......@@ -42,13 +67,13 @@ static int __init elphelmem_init(void)
}
bufsize_be = (__be32 *)of_get_property(node, "memsize", NULL);
elphel_buf.size = be32_to_cpup(bufsize_be);
_elphel_buf.size = be32_to_cpup(bufsize_be);
elphel_buf.vaddr = dma_alloc_coherent(NULL,(elphel_buf.size*PAGE_SIZE),&(elphel_buf.paddr),GFP_KERNEL);
_elphel_buf.vaddr = dma_alloc_coherent(NULL,(_elphel_buf.size*PAGE_SIZE),&(_elphel_buf.paddr),GFP_KERNEL);
if(elphel_buf.paddr)
if(_elphel_buf.paddr)
{
printk("Allocated %u pages for DMA at address 0x%x\n", (u32)elphel_buf.size, (u32)elphel_buf.paddr);
printk("Allocated %u pages for DMA at address 0x%x\n", (u32)_elphel_buf.size, (u32)_elphel_buf.paddr);
}
else printk("ERROR allocating memory buffer");
......@@ -66,12 +91,12 @@ static void __exit elphelmem_exit(void)
static ssize_t get_paddr(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"0x%x\n", (u32)elphel_buf.paddr);
return sprintf(buf,"0x%x\n", (u32)_elphel_buf.paddr);
}
static ssize_t get_size(struct device *dev, struct device_attribute *attr, char *buf)
{
return sprintf(buf,"%u\n", elphel_buf.size);
return sprintf(buf,"%u\n", _elphel_buf.size);
}
static ssize_t get_cache(struct device *dev, struct device_attribute *attr, char *buf)
{
......
/*!***************************************************************************
*! FILE NAME : elphel393-mem.h
*! DESCRIPTION:
*! Copyright (C) 2015 Elphel, Inc.
*! -----------------------------------------------------------------------------**
*!
*! This program is free software: you can redistribute it and/or modify
*! it under the terms of the GNU General Public License as published by
*! the Free Software Foundation, either version 3 of the License, or
*! (at your option) any later version.
*!
*! This program is distributed in the hope that it will be useful,
*! but WITHOUT ANY WARRANTY; without even the implied warranty of
*! MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
*! GNU General Public License for more details.
*!
*! You should have received a copy of the GNU General Public License
*! along with this program. If not, see <http://www.gnu.org/licenses/>.
*!****************************************************************************/
struct elphel_buf_t
{
void *vaddr;
dma_addr_t paddr;
ssize_t size;
};
extern struct elphel_buf_t elphel_buf;
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment