Commit a5b2f0e1 authored by Federico Vaga's avatar Federico Vaga

sw:drv: add PLL dump in debugfs

Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent 8b817c18
......@@ -34,6 +34,7 @@ fmc-fine-delay-objs = fd-zio.o fd-irq.o fd-core.o
fmc-fine-delay-objs += onewire.o spi.o gpio.o
fmc-fine-delay-objs += acam.o calibrate.o pll.o time.o
fmc-fine-delay-objs += calibration.o
fmc-fine-delay-objs += fd-debug.o
fmc-fine-delay-spec-objs := fmc-fine-delay-spec-core.o
fmc-fine-delay-svec-objs := fmc-fine-delay-svec-core.o
\ No newline at end of file
......@@ -317,6 +317,8 @@ int fd_probe(struct platform_device *pdev)
for (ch = 1; ch <= FD_CH_NUMBER; ch++)
fd_gpio_set(fd, FD_GPIO_OUTPUT_EN(ch));
fd_debug_init(fd);
return 0;
err:
......@@ -347,6 +349,7 @@ int fd_remove(struct platform_device *pdev)
if (!test_bit(FD_FLAG_INITED, &fd->flags)) /* FIXME: ditch this */
return 0; /* No init, no exit */
fd_debug_exit(fd);
fd_irq_exit(fd);
while (--i >= 0) {
m = mods + i;
......
// SPDX-License-Identifier: GPL-2.0-or-later
/*
* Copyright CERN 2020
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/debugfs.h>
#include "fine-delay.h"
#include "hw/pll_config.h"
static void fd_spi_seq_printf(struct fd_dev *fd, int reg, struct seq_file *s)
{
uint32_t rx;
int err;
err = fd_spi_xfer(fd, FD_CS_PLL, 24, (reg << 8) | BIT(23), &rx);
rx &= 0xFF; /* the value is 8bit */
if (err)
seq_printf(s, "%03xh read failure!\n",
reg);
else
seq_printf(s, "%03xh 0x%02x\n",
reg, rx);
}
static int fd_regdump_pll_seq_read(struct seq_file *s, void *data)
{
struct fd_dev *fd = s->private;
int i;
seq_printf(s, "PLL SPI registers\n");
seq_printf(s, "Address Data\n");
for (i = 0; i < __9516_regs_n; ++i)
fd_spi_seq_printf(fd, __9516_regs[i].reg, s);
return 0;
}
static int fd_regdump_pll_open(struct inode *inode, struct file *file)
{
return single_open(file, fd_regdump_pll_seq_read, inode->i_private);
}
static const struct file_operations fd_regdump_pll_ops = {
.owner = THIS_MODULE,
.open = fd_regdump_pll_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
int fd_debug_init(struct fd_dev *fd)
{
int err;
fd->dbg_dir = debugfs_create_dir(dev_name(&fd->pdev->dev), NULL);
if (IS_ERR_OR_NULL(fd->dbg_dir)) {
err = PTR_ERR(fd->dbg_dir);
dev_err(&fd->pdev->dev,
"Cannot create debugfs directory \"%s\" (%d)\n",
dev_name(&fd->pdev->dev), err);
return err;
}
fd->dbg_reg_spi_pll = debugfs_create_file("spi-regs-pll", 0444,
fd->dbg_dir, fd,
&fd_regdump_pll_ops);
if (IS_ERR_OR_NULL(fd->dbg_reg_spi_pll)) {
dev_warn(&fd->pdev->dev,
"Cannot create regdump PLL debugfs file\n");
}
return 0;
}
void fd_debug_exit(struct fd_dev *fd)
{
debugfs_remove_recursive(fd->dbg_dir);
}
......@@ -247,6 +247,9 @@ struct fd_dev {
int32_t tdc_user_offset;
int32_t ch_user_offset[4];
int32_t tdc_flags;
struct dentry *dbg_dir;
struct dentry *dbg_reg_spi_pll;
};
/* We act on flags using atomic ops, so flag is the number, not the mask */
......@@ -424,5 +427,8 @@ extern void fd_spec_exit(void);
extern int fd_calib_init(struct fd_dev *fd);
extern void fd_calib_exit(struct fd_dev *fd);
extern struct bin_attribute dev_attr_calibration;
extern int fd_debug_init(struct fd_dev *fd);
extern void fd_debug_exit(struct fd_dev *fd);
#endif /* __KERNEL__ */
#endif /* __FINE_DELAY_H__ */
#ifndef __PLL_CONFIG_H__
#define __PLL_CONFIG_H__
struct ad9516_reg {
int reg;
int val;
};
const struct ad9516_reg __9516_regs[] = {
{0x0000, 0x99}, /* Config SPI */
{0x0001, 0x00},
{0x0002, 0x10},
{0x0003, 0xC3},
{0x0004, 0x00},
/* PLL */
{0x0010, 0x7C}, /* PFD and charge pump */
{0x0011, 0x05}, /* R divider (1) */
{0x0012, 0x00}, /* R divider (2) */
{0x0013, 0x0C}, /* A counter */
{0x0014, 0x12}, /* B counter (1) */
{0x0015, 0x00}, /* B counter (2) */
{0x0016, 0x05}, /* PLL control (1) */
{0x0017, 0xb4}, /* PLL control (2) PLL_STATUS = Lock Detect */
{0x0018, 0x07}, /* PLL control (3) */
{0x0019, 0x00}, /* PLL control (4) */
{0x001A, 0x00}, /* PLL control (5) */
{0x001B, 0xE0}, /* PLL control (6) */
{0x001C, 0x02}, /* PLL control (7) */
{0x001D, 0x00}, /* PLL control (8) */
{0x001E, 0x00}, /* PLL control (9) */
{0x001F, 0x0E}, /* PLL readback */
/* Fine Delay */
{0x00A0, 0x01}, /* OUT6 Delay bypass */
{0x00A1, 0x00}, /* OUT6 Delay full-scale */
{0x00A2, 0x00}, /* OUT6 Delay fraction */
{0x00A3, 0x01}, /* OUT7 Delay bypass */
{0x00A4, 0x00}, /* OUT7 Delay full-scale */
{0x00A5, 0x00}, /* OUT7 Delay fraction */
{0x00A6, 0x01}, /* OUT8 Delay bypass */
{0x00A7, 0x00}, /* OUT8 Delay full-scale */
{0x00A8, 0x00}, /* OUT8 Delay fraction */
{0x00A9, 0x01}, /* OUT9 Delay bypass */
{0x00AA, 0x00}, /* OUT9 Delay full-scale */
{0x00AB, 0x00}, /* OUT9 Delay fraction */
/* LVPECL */
{0x00F0, 0x08}, /* OUT0 */
{0x00F1, 0x08}, /* OUT1 */
{0x00F2, 0x08}, /* OUT2 */
{0x00F3, 0x18}, /* OUT3, inverted */
{0x00F4, 0x00}, /* OUT4 */
{0x00F5, 0x08}, /* OUT5 */
/* LVDS/CMOS */
{0x0140, 0x5A}, /* OUT6 */
{0x0141, 0x5A}, /* OUT7 */
{0x0142, 0x5B}, /* OUT8 */
{0x0143, 0x42}, /* OUT9 */
/* LVPECL Channel divider */
{0x0190, 0x00}, /* Divider 0 (1) */
{0x0191, 0x80}, /* Divider 0 (2) */
{0x0192, 0x00}, /* Divider 0 (3) */
{0x0193, 0x00}, /* Divider 1 (1) */
{0x0194, 0x80}, /* Divider 1 (2) */
{0x0195, 0x00}, /* Divider 1 (3) */
{0x0196, 0xFF}, /* Divider 2 (1) */
{0x0197, 0x00}, /* Divider 2 (2) */
{0x0198, 0x00}, /* Divider 2 (3) */
/* LVDS/CMOS Channel divider */
{0x0199, 0x33}, /* Divider 3 (1) */
{0x019A, 0x00}, /* Divider 3 (2) */
{0x019B, 0x11}, /* Divider 3 (3) */
{0x019C, 0x20}, /* Divider 3 (4) */
{0x019D, 0x00}, /* Divider 3 (5) */
{0x019E, 0x00}, /* Divider 4 (1) */
{0x019F, 0x00}, /* Divider 4 (2) */
{0x01A0, 0x11}, /* Divider 4 (3) */
{0x01A1, 0x20}, /* Divider 4 (4) */
{0x01A2, 0x00}, /* Divider 4 (5) */
{0x01A3, 0x00},
/* VCO Divider and CLK Input */
{0x01E0, 0x04}, /* VCO divider VCODIV = 6 */
{0x01E1, 0x02}, /* Input Clock */
/* System */
{0x0230, 0x00}, /* Power down and sync */
{0x0231, 0x00},
/* Update All registers */
{0x0232, 0x00}, /* Update All registers */
};
extern const struct ad9516_reg __9516_regs[];
extern const unsigned int __9516_regs_n;
#endif
......@@ -18,6 +18,88 @@
#include "fine-delay.h"
#include "hw/pll_config.h" /* the table to be written */
const struct ad9516_reg __9516_regs[] = {
{0x0000, 0x99}, /* Config SPI */
{0x0001, 0x00},
{0x0002, 0x10},
{0x0003, 0xC3},
{0x0004, 0x00},
/* PLL */
{0x0010, 0x7C}, /* PFD and charge pump */
{0x0011, 0x05}, /* R divider (1) */
{0x0012, 0x00}, /* R divider (2) */
{0x0013, 0x0C}, /* A counter */
{0x0014, 0x12}, /* B counter (1) */
{0x0015, 0x00}, /* B counter (2) */
{0x0016, 0x05}, /* PLL control (1) */
{0x0017, 0xb4}, /* PLL control (2) PLL_STATUS = Lock Detect */
{0x0018, 0x07}, /* PLL control (3) */
{0x0019, 0x00}, /* PLL control (4) */
{0x001A, 0x00}, /* PLL control (5) */
{0x001B, 0xE0}, /* PLL control (6) */
{0x001C, 0x02}, /* PLL control (7) */
{0x001D, 0x00}, /* PLL control (8) */
{0x001E, 0x00}, /* PLL control (9) */
{0x001F, 0x0E}, /* PLL readback */
/* Fine Delay */
{0x00A0, 0x01}, /* OUT6 Delay bypass */
{0x00A1, 0x00}, /* OUT6 Delay full-scale */
{0x00A2, 0x00}, /* OUT6 Delay fraction */
{0x00A3, 0x01}, /* OUT7 Delay bypass */
{0x00A4, 0x00}, /* OUT7 Delay full-scale */
{0x00A5, 0x00}, /* OUT7 Delay fraction */
{0x00A6, 0x01}, /* OUT8 Delay bypass */
{0x00A7, 0x00}, /* OUT8 Delay full-scale */
{0x00A8, 0x00}, /* OUT8 Delay fraction */
{0x00A9, 0x01}, /* OUT9 Delay bypass */
{0x00AA, 0x00}, /* OUT9 Delay full-scale */
{0x00AB, 0x00}, /* OUT9 Delay fraction */
/* LVPECL */
{0x00F0, 0x08}, /* OUT0 */
{0x00F1, 0x08}, /* OUT1 */
{0x00F2, 0x08}, /* OUT2 */
{0x00F3, 0x18}, /* OUT3, inverted */
{0x00F4, 0x00}, /* OUT4 */
{0x00F5, 0x08}, /* OUT5 */
/* LVDS/CMOS */
{0x0140, 0x5A}, /* OUT6 */
{0x0141, 0x5A}, /* OUT7 */
{0x0142, 0x5B}, /* OUT8 */
{0x0143, 0x42}, /* OUT9 */
/* LVPECL Channel divider */
{0x0190, 0x00}, /* Divider 0 (1) */
{0x0191, 0x80}, /* Divider 0 (2) */
{0x0192, 0x00}, /* Divider 0 (3) */
{0x0193, 0x00}, /* Divider 1 (1) */
{0x0194, 0x80}, /* Divider 1 (2) */
{0x0195, 0x00}, /* Divider 1 (3) */
{0x0196, 0xFF}, /* Divider 2 (1) */
{0x0197, 0x00}, /* Divider 2 (2) */
{0x0198, 0x00}, /* Divider 2 (3) */
/* LVDS/CMOS Channel divider */
{0x0199, 0x33}, /* Divider 3 (1) */
{0x019A, 0x00}, /* Divider 3 (2) */
{0x019B, 0x11}, /* Divider 3 (3) */
{0x019C, 0x20}, /* Divider 3 (4) */
{0x019D, 0x00}, /* Divider 3 (5) */
{0x019E, 0x00}, /* Divider 4 (1) */
{0x019F, 0x00}, /* Divider 4 (2) */
{0x01A0, 0x11}, /* Divider 4 (3) */
{0x01A1, 0x20}, /* Divider 4 (4) */
{0x01A2, 0x00}, /* Divider 4 (5) */
{0x01A3, 0x00},
/* VCO Divider and CLK Input */
{0x01E0, 0x04}, /* VCO divider VCODIV = 6 */
{0x01E1, 0x02}, /* Input Clock */
/* System */
{0x0230, 0x00}, /* Power down and sync */
{0x0231, 0x00},
/* Update All registers */
{0x0232, 0x00}, /* Update All registers */
};
const unsigned int __9516_regs_n = ARRAY_SIZE(__9516_regs);
static int pll_writel(struct fd_dev *fd, int val, int reg)
{
return fd_spi_xfer(fd, FD_CS_PLL, 24, (reg << 8) | val, NULL);
......@@ -55,7 +137,7 @@ int fd_pll_init(struct fd_dev *fd)
}
/* Write the magic config */
for (i = 0, r = __9516_regs; i < ARRAY_SIZE(__9516_regs); i++, r++) {
for (i = 0, r = __9516_regs; i < __9516_regs_n; i++, r++) {
if (pll_writel(fd, r->val, r->reg) < 0) {
dev_err(dev, "Error in configuring PLL (step %i)\n", i);
return -EIO;
......@@ -103,4 +185,3 @@ void fd_pll_exit(struct fd_dev *fd)
{
/* nothing to do */
}
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