Netdev Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH net-next 00/11] ocp timecard updates
@ 2021-08-30 23:52 Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 01/11] ptp: ocp: parameterize the i2c driver used Jonathan Lemon
` (10 more replies)
0 siblings, 11 replies; 21+ messages in thread
From: Jonathan Lemon @ 2021-08-30 23:52 UTC (permalink / raw)
To: davem, kuba, richardcochran; +Cc: netdev, kernel-team, abyagowi
This update mainly deals with features for the TimeCard v10 firmware.
The signals provided from the external SMA connectors can be steered
to different locations, and the generated SMA signals can be chosen.
The update also adds support for IRIG-B and DCF formats.
Jonathan Lemon (11):
ptp: ocp: parameterize the i2c driver used
ptp: ocp: Parameterize the TOD information display.
ptp: ocp: Skip I2C flash read when there is no controller.
ptp: ocp: Skip resources with out of range irqs
ptp: ocp: Add third timestamper
ptp: ocp: Add SMA selector and controls
ptp: ocp: Add IRIG-B and DCF blocks
ptp: ocp: Add sysfs attribute utc_tai_offset
ptp: ocp: Add debugfs entry for timecard
ptp: ocp: Add IRIG-B output mode control
docs: ABI: Add sysfs documentation for timecard
Documentation/ABI/testing/sysfs-timecard | 141 ++++
drivers/ptp/ptp_ocp.c | 855 +++++++++++++++++++++--
2 files changed, 929 insertions(+), 67 deletions(-)
create mode 100644 Documentation/ABI/testing/sysfs-timecard
--
2.31.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH net-next 01/11] ptp: ocp: parameterize the i2c driver used
2021-08-30 23:52 [PATCH net-next 00/11] ocp timecard updates Jonathan Lemon
@ 2021-08-30 23:52 ` Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 02/11] ptp: ocp: Parameterize the TOD information display Jonathan Lemon
` (9 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Jonathan Lemon @ 2021-08-30 23:52 UTC (permalink / raw)
To: davem, kuba, richardcochran; +Cc: netdev, kernel-team, abyagowi
Move the xilinx i2c driver parameters to the resource block instead
of hardcoding things in the registration functions.
Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
---
drivers/ptp/ptp_ocp.c | 25 +++++++++++++++++++++----
1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index caf9b37c5eb1..d37eac69150a 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -131,6 +131,13 @@ struct ptp_ocp_flash_info {
void *data;
};
+struct ptp_ocp_i2c_info {
+ const char *name;
+ unsigned long fixed_rate;
+ size_t data_size;
+ void *data;
+};
+
struct ptp_ocp_ext_info {
const char *name;
int index;
@@ -269,6 +276,10 @@ static struct ocp_resource ocp_fb_resource[] = {
{
OCP_I2C_RESOURCE(i2c_ctrl),
.offset = 0x00150000, .size = 0x10000, .irq_vec = 7,
+ .extra = &(struct ptp_ocp_i2c_info) {
+ .name = "xiic-i2c",
+ .fixed_rate = 50000000,
+ },
},
{
OCP_SERIAL_RESOURCE(gnss_port),
@@ -944,21 +955,25 @@ ptp_ocp_register_spi(struct ptp_ocp *bp, struct ocp_resource *r)
static struct platform_device *
ptp_ocp_i2c_bus(struct pci_dev *pdev, struct ocp_resource *r, int id)
{
+ struct ptp_ocp_i2c_info *info;
struct resource res[2];
unsigned long start;
+ info = r->extra;
start = pci_resource_start(pdev, 0) + r->offset;
ptp_ocp_set_mem_resource(&res[0], start, r->size);
ptp_ocp_set_irq_resource(&res[1], pci_irq_vector(pdev, r->irq_vec));
- return platform_device_register_resndata(&pdev->dev, "xiic-i2c",
- id, res, 2, NULL, 0);
+ return platform_device_register_resndata(&pdev->dev, info->name,
+ id, res, 2,
+ info->data, info->data_size);
}
static int
ptp_ocp_register_i2c(struct ptp_ocp *bp, struct ocp_resource *r)
{
struct pci_dev *pdev = bp->pdev;
+ struct ptp_ocp_i2c_info *info;
struct platform_device *p;
struct clk_hw *clk;
char buf[32];
@@ -970,15 +985,17 @@ ptp_ocp_register_i2c(struct ptp_ocp *bp, struct ocp_resource *r)
return 0;
}
+ info = r->extra;
id = pci_dev_id(bp->pdev);
sprintf(buf, "AXI.%d", id);
- clk = clk_hw_register_fixed_rate(&pdev->dev, buf, NULL, 0, 50000000);
+ clk = clk_hw_register_fixed_rate(&pdev->dev, buf, NULL, 0,
+ info->fixed_rate);
if (IS_ERR(clk))
return PTR_ERR(clk);
bp->i2c_clk = clk;
- sprintf(buf, "xiic-i2c.%d", id);
+ sprintf(buf, "%s.%d", info->name, id);
devm_clk_hw_register_clkdev(&pdev->dev, clk, NULL, buf);
p = ptp_ocp_i2c_bus(bp->pdev, r, id);
if (IS_ERR(p))
--
2.31.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH net-next 02/11] ptp: ocp: Parameterize the TOD information display.
2021-08-30 23:52 [PATCH net-next 00/11] ocp timecard updates Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 01/11] ptp: ocp: parameterize the i2c driver used Jonathan Lemon
@ 2021-08-30 23:52 ` Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 03/11] ptp: ocp: Skip I2C flash read when there is no controller Jonathan Lemon
` (8 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Jonathan Lemon @ 2021-08-30 23:52 UTC (permalink / raw)
To: davem, kuba, richardcochran; +Cc: netdev, kernel-team, abyagowi
Only display the TOD information if there is a corresponding
TOD resource.
Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
---
drivers/ptp/ptp_ocp.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index d37eac69150a..2a6cc762c60e 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -743,7 +743,8 @@ ptp_ocp_info(struct ptp_ocp *bp)
ptp_ocp_clock_name_from_val(select >> 16),
ptp_clock_index(bp->ptp));
- ptp_ocp_tod_info(bp);
+ if (bp->tod)
+ ptp_ocp_tod_info(bp);
}
static struct device *
--
2.31.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH net-next 03/11] ptp: ocp: Skip I2C flash read when there is no controller.
2021-08-30 23:52 [PATCH net-next 00/11] ocp timecard updates Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 01/11] ptp: ocp: parameterize the i2c driver used Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 02/11] ptp: ocp: Parameterize the TOD information display Jonathan Lemon
@ 2021-08-30 23:52 ` Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 04/11] ptp: ocp: Skip resources with out of range irqs Jonathan Lemon
` (7 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Jonathan Lemon @ 2021-08-30 23:52 UTC (permalink / raw)
To: davem, kuba, richardcochran; +Cc: netdev, kernel-team, abyagowi
If an I2C controller isn't present, don't try and read the I2C flash.
Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
---
drivers/ptp/ptp_ocp.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index 2a6cc762c60e..196a457929f0 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -228,8 +228,8 @@ static int ptp_ocp_ts_enable(void *priv, bool enable);
* 3: GPS
* 4: GPS2 (n/c)
* 5: MAC
- * 6: SPI IMU (inertial measurement unit)
- * 7: I2C oscillator
+ * 6: N/C
+ * 7: I2C controller
* 8: HWICAP
* 9: SPI Flash
*/
@@ -706,6 +706,9 @@ ptp_ocp_get_serial_number(struct ptp_ocp *bp)
struct device *dev;
int err;
+ if (!bp->i2c_ctrl)
+ return;
+
dev = device_find_child(&bp->i2c_ctrl->dev, NULL, ptp_ocp_firstchild);
if (!dev) {
dev_err(&bp->pdev->dev, "Can't find I2C adapter\n");
--
2.31.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH net-next 04/11] ptp: ocp: Skip resources with out of range irqs
2021-08-30 23:52 [PATCH net-next 00/11] ocp timecard updates Jonathan Lemon
` (2 preceding siblings ...)
2021-08-30 23:52 ` [PATCH net-next 03/11] ptp: ocp: Skip I2C flash read when there is no controller Jonathan Lemon
@ 2021-08-30 23:52 ` Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 05/11] ptp: ocp: Add third timestamper Jonathan Lemon
` (6 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Jonathan Lemon @ 2021-08-30 23:52 UTC (permalink / raw)
To: davem, kuba, richardcochran; +Cc: netdev, kernel-team, abyagowi
The TimeCard exposes different resources, which may have their
own irqs. Space for the irqs is allocated through a MSI or MSI-X
interrupt vector. On some platforms, the interrupt allocation
fails.
Rather than making this fatal, just skip exposing those resources.
The main timecard functionality (that of a PTP clock) will work
without the additional resources.
Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
---
drivers/ptp/ptp_ocp.c | 47 +++++++++++++++++--------------------------
1 file changed, 18 insertions(+), 29 deletions(-)
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index 196a457929f0..ad8b794fa7e6 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -139,7 +139,6 @@ struct ptp_ocp_i2c_info {
};
struct ptp_ocp_ext_info {
- const char *name;
int index;
irqreturn_t (*irq_fcn)(int irq, void *priv);
int (*enable)(void *priv, bool enable);
@@ -187,6 +186,7 @@ struct ocp_resource {
int (*setup)(struct ptp_ocp *bp, struct ocp_resource *r);
void *extra;
unsigned long bp_offset;
+ const char * const name;
};
static int ptp_ocp_register_mem(struct ptp_ocp *bp, struct ocp_resource *r);
@@ -204,7 +204,7 @@ static int ptp_ocp_ts_enable(void *priv, bool enable);
})
#define OCP_RES_LOCATION(member) \
- .bp_offset = offsetof(struct ptp_ocp, member)
+ .name = #member, .bp_offset = offsetof(struct ptp_ocp, member)
#define OCP_MEM_RESOURCE(member) \
OCP_RES_LOCATION(member), .setup = ptp_ocp_register_mem
@@ -243,7 +243,7 @@ static struct ocp_resource ocp_fb_resource[] = {
OCP_EXT_RESOURCE(ts0),
.offset = 0x01010000, .size = 0x10000, .irq_vec = 1,
.extra = &(struct ptp_ocp_ext_info) {
- .name = "ts0", .index = 0,
+ .index = 0,
.irq_fcn = ptp_ocp_ts_irq,
.enable = ptp_ocp_ts_enable,
},
@@ -252,7 +252,7 @@ static struct ocp_resource ocp_fb_resource[] = {
OCP_EXT_RESOURCE(ts1),
.offset = 0x01020000, .size = 0x10000, .irq_vec = 2,
.extra = &(struct ptp_ocp_ext_info) {
- .name = "ts1", .index = 1,
+ .index = 1,
.irq_fcn = ptp_ocp_ts_irq,
.enable = ptp_ocp_ts_enable,
},
@@ -925,18 +925,6 @@ ptp_ocp_register_spi(struct ptp_ocp *bp, struct ocp_resource *r)
unsigned long start;
int id;
- /* XXX hack to work around old FPGA */
- if (bp->n_irqs < 10) {
- dev_err(&bp->pdev->dev, "FPGA does not have SPI devices\n");
- return 0;
- }
-
- if (r->irq_vec > bp->n_irqs) {
- dev_err(&bp->pdev->dev, "spi device irq %d out of range\n",
- r->irq_vec);
- return 0;
- }
-
start = pci_resource_start(pdev, 0) + r->offset;
ptp_ocp_set_mem_resource(&res[0], start, r->size);
ptp_ocp_set_irq_resource(&res[1], pci_irq_vector(pdev, r->irq_vec));
@@ -983,12 +971,6 @@ ptp_ocp_register_i2c(struct ptp_ocp *bp, struct ocp_resource *r)
char buf[32];
int id;
- if (r->irq_vec > bp->n_irqs) {
- dev_err(&bp->pdev->dev, "i2c device irq %d out of range\n",
- r->irq_vec);
- return 0;
- }
-
info = r->extra;
id = pci_dev_id(bp->pdev);
@@ -1080,7 +1062,7 @@ ptp_ocp_register_ext(struct ptp_ocp *bp, struct ocp_resource *r)
ext->irq_vec = r->irq_vec;
err = pci_request_irq(pdev, r->irq_vec, ext->info->irq_fcn, NULL,
- ext, "ocp%d.%s", bp->id, ext->info->name);
+ ext, "ocp%d.%s", bp->id, r->name);
if (err) {
dev_err(&pdev->dev, "Could not get irq %d\n", r->irq_vec);
goto out;
@@ -1122,12 +1104,6 @@ ptp_ocp_register_serial(struct ptp_ocp *bp, struct ocp_resource *r)
{
int port;
- if (r->irq_vec > bp->n_irqs) {
- dev_err(&bp->pdev->dev, "serial device irq %d out of range\n",
- r->irq_vec);
- return 0;
- }
-
port = ptp_ocp_serial_line(bp, r);
if (port < 0)
return port;
@@ -1160,6 +1136,17 @@ ptp_ocp_fb_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
return ptp_ocp_init_clock(bp);
}
+static bool
+ptp_ocp_allow_irq(struct ptp_ocp *bp, struct ocp_resource *r)
+{
+ bool allow = !r->irq_vec || r->irq_vec < bp->n_irqs;
+
+ if (!allow)
+ dev_err(&bp->pdev->dev, "irq %d out of range, skipping %s\n",
+ r->irq_vec, r->name);
+ return allow;
+}
+
static int
ptp_ocp_register_resources(struct ptp_ocp *bp, kernel_ulong_t driver_data)
{
@@ -1168,6 +1155,8 @@ ptp_ocp_register_resources(struct ptp_ocp *bp, kernel_ulong_t driver_data)
table = (struct ocp_resource *)driver_data;
for (r = table; r->setup; r++) {
+ if (!ptp_ocp_allow_irq(bp, r))
+ continue;
err = r->setup(bp, r);
if (err)
break;
--
2.31.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH net-next 05/11] ptp: ocp: Add third timestamper
2021-08-30 23:52 [PATCH net-next 00/11] ocp timecard updates Jonathan Lemon
` (3 preceding siblings ...)
2021-08-30 23:52 ` [PATCH net-next 04/11] ptp: ocp: Skip resources with out of range irqs Jonathan Lemon
@ 2021-08-30 23:52 ` Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 06/11] ptp: ocp: Add SMA selector and controls Jonathan Lemon
` (5 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Jonathan Lemon @ 2021-08-30 23:52 UTC (permalink / raw)
To: davem, kuba, richardcochran; +Cc: netdev, kernel-team, abyagowi
The firmware may provide a third signal timestamper, so make it
available for use.
Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
---
drivers/ptp/ptp_ocp.c | 19 +++++++++++++++++--
1 file changed, 17 insertions(+), 2 deletions(-)
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index ad8b794fa7e6..c5fbccab57a8 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -162,6 +162,7 @@ struct ptp_ocp {
struct ptp_ocp_ext_src *pps;
struct ptp_ocp_ext_src *ts0;
struct ptp_ocp_ext_src *ts1;
+ struct ptp_ocp_ext_src *ts2;
struct img_reg __iomem *image;
struct ptp_clock *ptp;
struct ptp_clock_info ptp_info;
@@ -228,7 +229,7 @@ static int ptp_ocp_ts_enable(void *priv, bool enable);
* 3: GPS
* 4: GPS2 (n/c)
* 5: MAC
- * 6: N/C
+ * 6: TS2
* 7: I2C controller
* 8: HWICAP
* 9: SPI Flash
@@ -257,6 +258,15 @@ static struct ocp_resource ocp_fb_resource[] = {
.enable = ptp_ocp_ts_enable,
},
},
+ {
+ OCP_EXT_RESOURCE(ts2),
+ .offset = 0x01060000, .size = 0x10000, .irq_vec = 6,
+ .extra = &(struct ptp_ocp_ext_info) {
+ .index = 2,
+ .irq_fcn = ptp_ocp_ts_irq,
+ .enable = ptp_ocp_ts_enable,
+ },
+ },
{
OCP_MEM_RESOURCE(pps_to_ext),
.offset = 0x01030000, .size = 0x10000,
@@ -497,6 +507,9 @@ ptp_ocp_enable(struct ptp_clock_info *ptp_info, struct ptp_clock_request *rq,
case 1:
ext = bp->ts1;
break;
+ case 2:
+ ext = bp->ts2;
+ break;
}
break;
case PTP_CLK_REQ_PPS:
@@ -524,7 +537,7 @@ static const struct ptp_clock_info ptp_ocp_clock_info = {
.adjphase = ptp_ocp_adjphase,
.enable = ptp_ocp_enable,
.pps = true,
- .n_ext_ts = 2,
+ .n_ext_ts = 3,
};
static void
@@ -1403,6 +1416,8 @@ ptp_ocp_detach(struct ptp_ocp *bp)
ptp_ocp_unregister_ext(bp->ts0);
if (bp->ts1)
ptp_ocp_unregister_ext(bp->ts1);
+ if (bp->ts2)
+ ptp_ocp_unregister_ext(bp->ts2);
if (bp->pps)
ptp_ocp_unregister_ext(bp->pps);
if (bp->gnss_port != -1)
--
2.31.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH net-next 06/11] ptp: ocp: Add SMA selector and controls
2021-08-30 23:52 [PATCH net-next 00/11] ocp timecard updates Jonathan Lemon
` (4 preceding siblings ...)
2021-08-30 23:52 ` [PATCH net-next 05/11] ptp: ocp: Add third timestamper Jonathan Lemon
@ 2021-08-30 23:52 ` Jonathan Lemon
2021-09-01 23:56 ` Jakub Kicinski
2021-08-30 23:52 ` [PATCH net-next 07/11] ptp: ocp: Add IRIG-B and DCF blocks Jonathan Lemon
` (4 subsequent siblings)
10 siblings, 1 reply; 21+ messages in thread
From: Jonathan Lemon @ 2021-08-30 23:52 UTC (permalink / raw)
To: davem, kuba, richardcochran; +Cc: netdev, kernel-team, abyagowi
The v10 firmware for the TimeCard adds selectable signals for
the SMA input/outputs. Add support for SMA selectors, and the
GPIO controls needed for steering signals.
Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
---
drivers/ptp/ptp_ocp.c | 315 ++++++++++++++++++++++++++++++++++++++----
1 file changed, 287 insertions(+), 28 deletions(-)
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index c5fbccab57a8..3920bdb1977a 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -124,6 +124,13 @@ struct img_reg {
u32 version;
};
+struct gpio_reg {
+ u32 gpio1;
+ u32 __pad0;
+ u32 gpio2;
+ u32 __pad1;
+};
+
struct ptp_ocp_flash_info {
const char *name;
int pci_offset;
@@ -159,6 +166,7 @@ struct ptp_ocp {
struct tod_reg __iomem *tod;
struct pps_reg __iomem *pps_to_ext;
struct pps_reg __iomem *pps_to_clk;
+ struct gpio_reg __iomem *sma;
struct ptp_ocp_ext_src *pps;
struct ptp_ocp_ext_src *ts0;
struct ptp_ocp_ext_src *ts1;
@@ -283,6 +291,10 @@ static struct ocp_resource ocp_fb_resource[] = {
OCP_MEM_RESOURCE(image),
.offset = 0x00020000, .size = 0x1000,
},
+ {
+ OCP_MEM_RESOURCE(sma),
+ .offset = 0x00140000, .size = 0x1000,
+ },
{
OCP_I2C_RESOURCE(i2c_ctrl),
.offset = 0x00150000, .size = 0x10000, .irq_vec = 7,
@@ -330,10 +342,12 @@ MODULE_DEVICE_TABLE(pci, ptp_ocp_pcidev_id);
static DEFINE_MUTEX(ptp_ocp_lock);
static DEFINE_IDR(ptp_ocp_idr);
-static struct {
+struct ocp_selector {
const char *name;
int value;
-} ptp_ocp_clock[] = {
+};
+
+static struct ocp_selector ptp_ocp_clock[] = {
{ .name = "NONE", .value = 0 },
{ .name = "TOD", .value = 1 },
{ .name = "IRIG", .value = 2 },
@@ -343,33 +357,71 @@ static struct {
{ .name = "DCF", .value = 6 },
{ .name = "REGS", .value = 0xfe },
{ .name = "EXT", .value = 0xff },
+ { }
+};
+
+static struct ocp_selector ptp_ocp_sma_in[] = {
+ { .name = "10Mhz", .value = 0x00 },
+ { .name = "PPS1", .value = 0x01 },
+ { .name = "PPS2", .value = 0x02 },
+ { .name = "TS1", .value = 0x04 },
+ { .name = "TS2", .value = 0x08 },
+ { .name = "IRIG", .value = 0x10 },
+ { .name = "DCF", .value = 0x20 },
+ { }
+};
+
+static struct ocp_selector ptp_ocp_sma_out[] = {
+ { .name = "10Mhz", .value = 0x00 },
+ { .name = "PHC", .value = 0x01 },
+ { .name = "MAC", .value = 0x02 },
+ { .name = "GNSS", .value = 0x04 },
+ { .name = "GNSS2", .value = 0x08 },
+ { .name = "IRIG", .value = 0x10 },
+ { .name = "DCF", .value = 0x20 },
+ { }
};
static const char *
-ptp_ocp_clock_name_from_val(int val)
+select_name_from_val(struct ocp_selector *tbl, int val)
{
int i;
- for (i = 0; i < ARRAY_SIZE(ptp_ocp_clock); i++)
- if (ptp_ocp_clock[i].value == val)
- return ptp_ocp_clock[i].name;
+ for (i = 0; tbl[i].name; i++)
+ if (tbl[i].value == val)
+ return tbl[i].name;
return NULL;
}
static int
-ptp_ocp_clock_val_from_name(const char *name)
+select_val_from_name(struct ocp_selector *tbl, const char *name)
{
- const char *clk;
+ const char *select;
int i;
- for (i = 0; i < ARRAY_SIZE(ptp_ocp_clock); i++) {
- clk = ptp_ocp_clock[i].name;
- if (!strncasecmp(name, clk, strlen(clk)))
- return ptp_ocp_clock[i].value;
+ for (i = 0; tbl[i].name; i++) {
+ select = tbl[i].name;
+ if (!strncasecmp(name, select, strlen(select)))
+ return tbl[i].value;
}
return -EINVAL;
}
+static ssize_t
+select_table_show(struct ocp_selector *tbl, char *buf)
+{
+ ssize_t count;
+ int i;
+
+ count = 0;
+ for (i = 0; tbl[i].name; i++)
+ count += sysfs_emit_at(buf, count, "%s ", tbl[i].name);
+ if (count)
+ count--;
+ count += sysfs_emit_at(buf, count, "\n");
+ return count;
+}
+
static int
__ptp_ocp_gettime_locked(struct ptp_ocp *bp, struct timespec64 *ts,
struct ptp_system_timestamp *sts)
@@ -756,7 +808,7 @@ ptp_ocp_info(struct ptp_ocp *bp)
select = ioread32(&bp->reg->select);
dev_info(&bp->pdev->dev, "Version %d.%d.%d, clock %s, device ptp%d\n",
version >> 24, (version >> 16) & 0xff, version & 0xffff,
- ptp_ocp_clock_name_from_val(select >> 16),
+ select_name_from_val(ptp_ocp_clock, select >> 16),
ptp_clock_index(bp->ptp));
if (bp->tod)
@@ -1204,6 +1256,219 @@ gnss_sync_show(struct device *dev, struct device_attribute *attr, char *buf)
}
static DEVICE_ATTR_RO(gnss_sync);
+/*
+ * In the schematic, pins are ANTx, these map to the external connectors:
+ * ANT1 == sma2
+ * ANT2 == sma1
+ * ANT3 == sma4
+ * ANT4 == sma3
+ */
+
+static ssize_t
+sma_show_output(u32 val, char *buf, int default_idx)
+{
+ const char *name;
+
+ name = select_name_from_val(ptp_ocp_sma_out, val);
+ if (!name)
+ name = ptp_ocp_sma_out[default_idx].name;
+ return sysfs_emit(buf, "%s\n", name);
+}
+
+static ssize_t
+sma_show_inputs(u32 val, char *buf)
+{
+ const char *name;
+ ssize_t count;
+ int i;
+
+ count = 0;
+ for (i = 0; i < ARRAY_SIZE(ptp_ocp_sma_in); i++) {
+ if (val & ptp_ocp_sma_in[i].value) {
+ name = ptp_ocp_sma_in[i].name;
+ count += sysfs_emit_at(buf, count, "%s ", name);
+ }
+ }
+ if (count)
+ count--;
+ count += sysfs_emit_at(buf, count, "\n");
+ return count;
+}
+
+static int
+sma_parse_inputs(const char *buf)
+{
+ int i, count;
+ char **argv;
+ int ret;
+
+ argv = argv_split(GFP_KERNEL, buf, &count);
+ if (!argv)
+ return -ENOMEM;
+
+ ret = -EINVAL;
+ if (!count)
+ goto out;
+
+ ret = 0;
+ for (i = 0; i < count; i++)
+ ret |= select_val_from_name(ptp_ocp_sma_in, argv[i]);
+
+out:
+ argv_free(argv);
+ return ret;
+}
+
+static ssize_t
+sma2_out_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ u32 val;
+
+ val = ioread32(&bp->sma->gpio2) & 0x3f;
+ return sma_show_output(val, buf, 0);
+}
+
+static ssize_t
+sma1_out_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ u32 val;
+
+ val = (ioread32(&bp->sma->gpio2) >> 16) & 0x3f;
+ return sma_show_output(val, buf, 1);
+}
+
+static ssize_t
+sma2_out_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ unsigned long flags;
+ u32 gpio;
+ int val;
+
+ val = select_val_from_name(ptp_ocp_sma_out, buf);
+ if (val < 0)
+ return val;
+
+ spin_lock_irqsave(&bp->lock, flags);
+ gpio = ioread32(&bp->sma->gpio2);
+ gpio = (gpio & 0xffff0000) | val;
+ iowrite32(gpio, &bp->sma->gpio2);
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ return count;
+}
+static DEVICE_ATTR_RW(sma2_out);
+
+static ssize_t
+sma1_out_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ unsigned long flags;
+ u32 gpio;
+ int val;
+
+ val = select_val_from_name(ptp_ocp_sma_out, buf);
+ if (val < 0)
+ return val;
+
+ spin_lock_irqsave(&bp->lock, flags);
+ gpio = ioread32(&bp->sma->gpio2);
+ gpio = (gpio & 0xffff) | (val << 16);
+ iowrite32(gpio, &bp->sma->gpio2);
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ return count;
+}
+static DEVICE_ATTR_RW(sma1_out);
+
+static ssize_t
+sma4_in_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ u32 val;
+
+ val = ioread32(&bp->sma->gpio1) & 0x3f;
+ if (val == 0)
+ return sysfs_emit(buf, "%s\n", ptp_ocp_sma_in[0].name);
+ return sma_show_inputs(val, buf);
+}
+
+static ssize_t
+sma3_in_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ u32 val;
+
+ val = (ioread32(&bp->sma->gpio1) >> 16) & 0x3f;
+ return sma_show_inputs(val, buf);
+}
+
+static ssize_t
+sma4_in_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ unsigned long flags;
+ u32 gpio;
+ int val;
+
+ val = sma_parse_inputs(buf);
+ if (val < 0)
+ return val;
+
+ spin_lock_irqsave(&bp->lock, flags);
+ gpio = ioread32(&bp->sma->gpio1);
+ gpio = (gpio & 0xffff0000) | val;
+ iowrite32(gpio, &bp->sma->gpio1);
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ return count;
+}
+static DEVICE_ATTR_RW(sma4_in);
+
+static ssize_t
+sma3_in_store(struct device *dev, struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ unsigned long flags;
+ u32 gpio;
+ int val;
+
+ val = sma_parse_inputs(buf);
+ if (val < 0)
+ return val;
+
+ spin_lock_irqsave(&bp->lock, flags);
+ gpio = ioread32(&bp->sma->gpio1);
+ gpio = (gpio & 0xffff) | (val << 16);
+ iowrite32(gpio, &bp->sma->gpio1);
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ return count;
+}
+static DEVICE_ATTR_RW(sma3_in);
+
+static ssize_t
+available_sma_inputs_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return select_table_show(ptp_ocp_sma_in, buf);
+}
+static DEVICE_ATTR_RO(available_sma_inputs);
+
+static ssize_t
+available_sma_outputs_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ return select_table_show(ptp_ocp_sma_out, buf);
+}
+static DEVICE_ATTR_RO(available_sma_outputs);
+
static ssize_t
clock_source_show(struct device *dev, struct device_attribute *attr, char *buf)
{
@@ -1212,7 +1477,7 @@ clock_source_show(struct device *dev, struct device_attribute *attr, char *buf)
u32 select;
select = ioread32(&bp->reg->select);
- p = ptp_ocp_clock_name_from_val(select >> 16);
+ p = select_name_from_val(ptp_ocp_clock, select >> 16);
return sysfs_emit(buf, "%s\n", p);
}
@@ -1225,7 +1490,7 @@ clock_source_store(struct device *dev, struct device_attribute *attr,
unsigned long flags;
int val;
- val = ptp_ocp_clock_val_from_name(buf);
+ val = select_val_from_name(ptp_ocp_clock, buf);
if (val < 0)
return val;
@@ -1241,19 +1506,7 @@ static ssize_t
available_clock_sources_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- const char *clk;
- ssize_t count;
- int i;
-
- count = 0;
- for (i = 0; i < ARRAY_SIZE(ptp_ocp_clock); i++) {
- clk = ptp_ocp_clock[i].name;
- count += sysfs_emit_at(buf, count, "%s ", clk);
- }
- if (count)
- count--;
- count += sysfs_emit_at(buf, count, "\n");
- return count;
+ return select_table_show(ptp_ocp_clock, buf);
}
static DEVICE_ATTR_RO(available_clock_sources);
@@ -1262,6 +1515,12 @@ static struct attribute *timecard_attrs[] = {
&dev_attr_gnss_sync.attr,
&dev_attr_clock_source.attr,
&dev_attr_available_clock_sources.attr,
+ &dev_attr_sma1_out.attr,
+ &dev_attr_sma2_out.attr,
+ &dev_attr_sma3_in.attr,
+ &dev_attr_sma4_in.attr,
+ &dev_attr_available_sma_inputs.attr,
+ &dev_attr_available_sma_outputs.attr,
NULL,
};
ATTRIBUTE_GROUPS(timecard);
--
2.31.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH net-next 07/11] ptp: ocp: Add IRIG-B and DCF blocks
2021-08-30 23:52 [PATCH net-next 00/11] ocp timecard updates Jonathan Lemon
` (5 preceding siblings ...)
2021-08-30 23:52 ` [PATCH net-next 06/11] ptp: ocp: Add SMA selector and controls Jonathan Lemon
@ 2021-08-30 23:52 ` Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 08/11] ptp: ocp: Add sysfs attribute utc_tai_offset Jonathan Lemon
` (3 subsequent siblings)
10 siblings, 0 replies; 21+ messages in thread
From: Jonathan Lemon @ 2021-08-30 23:52 UTC (permalink / raw)
To: davem, kuba, richardcochran; +Cc: netdev, kernel-team, abyagowi
IRIG (Inter-range Instrumentation Group) timecode format on
one of the SMA output channels is provided by the IRIG master
FPGA block. Enable the master when the IRIG output format is
selected on either one of the output channels.
By default, the output is in B007 format.
DCF output format is provided by the DCF master block.
Also enable the IRIG and DCF slaves, which parse an incoming
signal from the external SMA connectors, and may be used to
adjust the PHC.
Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
---
drivers/ptp/ptp_ocp.c | 123 ++++++++++++++++++++++++++++++++++++++++++
1 file changed, 123 insertions(+)
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index 3920bdb1977a..fceeee380d9f 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -131,6 +131,48 @@ struct gpio_reg {
u32 __pad1;
};
+struct irig_master_reg {
+ u32 ctrl;
+ u32 status;
+ u32 __pad0;
+ u32 version;
+ u32 adj_sec;
+ u32 mode_ctrl;
+};
+
+#define IRIG_M_CTRL_ENABLE BIT(0)
+
+struct irig_slave_reg {
+ u32 ctrl;
+ u32 status;
+ u32 __pad0;
+ u32 version;
+ u32 adj_sec;
+ u32 mode_ctrl;
+};
+
+#define IRIG_S_CTRL_ENABLE BIT(0)
+
+struct dcf_master_reg {
+ u32 ctrl;
+ u32 status;
+ u32 __pad0;
+ u32 version;
+ u32 adj_sec;
+};
+
+#define DCF_M_CTRL_ENABLE BIT(0)
+
+struct dcf_slave_reg {
+ u32 ctrl;
+ u32 status;
+ u32 __pad0;
+ u32 version;
+ u32 adj_sec;
+};
+
+#define DCF_S_CTRL_ENABLE BIT(0)
+
struct ptp_ocp_flash_info {
const char *name;
int pci_offset;
@@ -167,6 +209,10 @@ struct ptp_ocp {
struct pps_reg __iomem *pps_to_ext;
struct pps_reg __iomem *pps_to_clk;
struct gpio_reg __iomem *sma;
+ struct irig_master_reg __iomem *irig_out;
+ struct irig_slave_reg __iomem *irig_in;
+ struct dcf_master_reg __iomem *dcf_out;
+ struct dcf_slave_reg __iomem *dcf_in;
struct ptp_ocp_ext_src *pps;
struct ptp_ocp_ext_src *ts0;
struct ptp_ocp_ext_src *ts1;
@@ -287,6 +333,22 @@ static struct ocp_resource ocp_fb_resource[] = {
OCP_MEM_RESOURCE(tod),
.offset = 0x01050000, .size = 0x10000,
},
+ {
+ OCP_MEM_RESOURCE(irig_in),
+ .offset = 0x01070000, .size = 0x10000,
+ },
+ {
+ OCP_MEM_RESOURCE(irig_out),
+ .offset = 0x01080000, .size = 0x10000,
+ },
+ {
+ OCP_MEM_RESOURCE(dcf_in),
+ .offset = 0x01090000, .size = 0x10000,
+ },
+ {
+ OCP_MEM_RESOURCE(dcf_out),
+ .offset = 0x010A0000, .size = 0x10000,
+ },
{
OCP_MEM_RESOURCE(image),
.offset = 0x00020000, .size = 0x1000,
@@ -1295,6 +1357,49 @@ sma_show_inputs(u32 val, char *buf)
return count;
}
+static void
+ptp_ocp_enable_fpga(u32 __iomem *reg, u32 bit, bool enable)
+{
+ u32 ctrl;
+ bool on;
+
+ ctrl = ioread32(reg);
+ on = ctrl & bit;
+ if (on ^ enable) {
+ ctrl &= ~bit;
+ ctrl |= enable ? bit : 0;
+ iowrite32(ctrl, reg);
+ }
+}
+
+static void
+ptp_ocp_irig_out(struct ptp_ocp *bp, bool enable)
+{
+ return ptp_ocp_enable_fpga(&bp->irig_out->ctrl,
+ IRIG_M_CTRL_ENABLE, enable);
+}
+
+static void
+ptp_ocp_irig_in(struct ptp_ocp *bp, bool enable)
+{
+ return ptp_ocp_enable_fpga(&bp->irig_in->ctrl,
+ IRIG_S_CTRL_ENABLE, enable);
+}
+
+static void
+ptp_ocp_dcf_out(struct ptp_ocp *bp, bool enable)
+{
+ return ptp_ocp_enable_fpga(&bp->dcf_out->ctrl,
+ DCF_M_CTRL_ENABLE, enable);
+}
+
+static void
+ptp_ocp_dcf_in(struct ptp_ocp *bp, bool enable)
+{
+ return ptp_ocp_enable_fpga(&bp->dcf_in->ctrl,
+ DCF_S_CTRL_ENABLE, enable);
+}
+
static int
sma_parse_inputs(const char *buf)
{
@@ -1319,6 +1424,20 @@ sma_parse_inputs(const char *buf)
return ret;
}
+static void
+__handle_signal_outputs(struct ptp_ocp *bp, u32 val)
+{
+ ptp_ocp_irig_out(bp, val & 0x00100010);
+ ptp_ocp_dcf_out(bp, val & 0x00200020);
+}
+
+static void
+__handle_signal_inputs(struct ptp_ocp *bp, u32 val)
+{
+ ptp_ocp_irig_in(bp, val & 0x00100010);
+ ptp_ocp_dcf_in(bp, val & 0x00200020);
+}
+
static ssize_t
sma2_out_show(struct device *dev, struct device_attribute *attr, char *buf)
{
@@ -1355,6 +1474,7 @@ sma2_out_store(struct device *dev, struct device_attribute *attr,
spin_lock_irqsave(&bp->lock, flags);
gpio = ioread32(&bp->sma->gpio2);
gpio = (gpio & 0xffff0000) | val;
+ __handle_signal_outputs(bp, gpio);
iowrite32(gpio, &bp->sma->gpio2);
spin_unlock_irqrestore(&bp->lock, flags);
@@ -1378,6 +1498,7 @@ sma1_out_store(struct device *dev, struct device_attribute *attr,
spin_lock_irqsave(&bp->lock, flags);
gpio = ioread32(&bp->sma->gpio2);
gpio = (gpio & 0xffff) | (val << 16);
+ __handle_signal_outputs(bp, gpio);
iowrite32(gpio, &bp->sma->gpio2);
spin_unlock_irqrestore(&bp->lock, flags);
@@ -1423,6 +1544,7 @@ sma4_in_store(struct device *dev, struct device_attribute *attr,
spin_lock_irqsave(&bp->lock, flags);
gpio = ioread32(&bp->sma->gpio1);
gpio = (gpio & 0xffff0000) | val;
+ __handle_signal_inputs(bp, gpio);
iowrite32(gpio, &bp->sma->gpio1);
spin_unlock_irqrestore(&bp->lock, flags);
@@ -1446,6 +1568,7 @@ sma3_in_store(struct device *dev, struct device_attribute *attr,
spin_lock_irqsave(&bp->lock, flags);
gpio = ioread32(&bp->sma->gpio1);
gpio = (gpio & 0xffff) | (val << 16);
+ __handle_signal_inputs(bp, gpio);
iowrite32(gpio, &bp->sma->gpio1);
spin_unlock_irqrestore(&bp->lock, flags);
--
2.31.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH net-next 08/11] ptp: ocp: Add sysfs attribute utc_tai_offset
2021-08-30 23:52 [PATCH net-next 00/11] ocp timecard updates Jonathan Lemon
` (6 preceding siblings ...)
2021-08-30 23:52 ` [PATCH net-next 07/11] ptp: ocp: Add IRIG-B and DCF blocks Jonathan Lemon
@ 2021-08-30 23:52 ` Jonathan Lemon
2021-09-01 23:56 ` Jakub Kicinski
2021-08-30 23:52 ` [PATCH net-next 09/11] ptp: ocp: Add debugfs entry for timecard Jonathan Lemon
` (2 subsequent siblings)
10 siblings, 1 reply; 21+ messages in thread
From: Jonathan Lemon @ 2021-08-30 23:52 UTC (permalink / raw)
To: davem, kuba, richardcochran; +Cc: netdev, kernel-team, abyagowi
IRIG and DCF output time in UTC, but the timecard operates
on TAI internally. Add an attribute node which allows adding
an offset to these modes before output.
Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
---
drivers/ptp/ptp_ocp.c | 38 +++++++++++++++++++++++++++++++++++++-
1 file changed, 37 insertions(+), 1 deletion(-)
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index fceeee380d9f..093385c6fed0 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -230,8 +230,9 @@ struct ptp_ocp {
int gnss_port;
int mac_port; /* miniature atomic clock */
u8 serial[6];
- int flash_start;
bool has_serial;
+ int flash_start;
+ s32 utc_tai_offset;
};
struct ocp_resource {
@@ -1592,6 +1593,40 @@ available_sma_outputs_show(struct device *dev,
}
static DEVICE_ATTR_RO(available_sma_outputs);
+static ssize_t
+utc_tai_offset_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+
+ return sysfs_emit(buf, "%d\n", bp->utc_tai_offset);
+}
+
+static ssize_t
+utc_tai_offset_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ unsigned long flags;
+ int err;
+ s32 val;
+
+ err = kstrtos32(buf, 0, &val);
+ if (err)
+ return err;
+
+ bp->utc_tai_offset = val;
+
+ spin_lock_irqsave(&bp->lock, flags);
+ iowrite32(val, &bp->irig_out->adj_sec);
+ iowrite32(val, &bp->dcf_out->adj_sec);
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ return count;
+}
+static DEVICE_ATTR_RW(utc_tai_offset);
+
static ssize_t
clock_source_show(struct device *dev, struct device_attribute *attr, char *buf)
{
@@ -1644,6 +1679,7 @@ static struct attribute *timecard_attrs[] = {
&dev_attr_sma4_in.attr,
&dev_attr_available_sma_inputs.attr,
&dev_attr_available_sma_outputs.attr,
+ &dev_attr_utc_tai_offset.attr,
NULL,
};
ATTRIBUTE_GROUPS(timecard);
--
2.31.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH net-next 09/11] ptp: ocp: Add debugfs entry for timecard
2021-08-30 23:52 [PATCH net-next 00/11] ocp timecard updates Jonathan Lemon
` (7 preceding siblings ...)
2021-08-30 23:52 ` [PATCH net-next 08/11] ptp: ocp: Add sysfs attribute utc_tai_offset Jonathan Lemon
@ 2021-08-30 23:52 ` Jonathan Lemon
2021-09-02 0:06 ` Jakub Kicinski
2021-08-30 23:52 ` [PATCH net-next 10/11] ptp: ocp: Add IRIG-B output mode control Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 11/11] docs: ABI: Add sysfs documentation for timecard Jonathan Lemon
10 siblings, 1 reply; 21+ messages in thread
From: Jonathan Lemon @ 2021-08-30 23:52 UTC (permalink / raw)
To: davem, kuba, richardcochran; +Cc: netdev, kernel-team, abyagowi
Provide a view into the timecard internals for debugging.
Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
---
drivers/ptp/ptp_ocp.c | 238 +++++++++++++++++++++++++++++++++++++++++-
1 file changed, 237 insertions(+), 1 deletion(-)
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index 093385c6fed0..daa95f48c39f 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -4,6 +4,7 @@
#include <linux/err.h>
#include <linux/kernel.h>
#include <linux/module.h>
+#include <linux/debugfs.h>
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/serial_8250.h>
@@ -208,6 +209,7 @@ struct ptp_ocp {
struct tod_reg __iomem *tod;
struct pps_reg __iomem *pps_to_ext;
struct pps_reg __iomem *pps_to_clk;
+ struct gpio_reg __iomem *pps_select;
struct gpio_reg __iomem *sma;
struct irig_master_reg __iomem *irig_out;
struct irig_slave_reg __iomem *irig_in;
@@ -224,6 +226,7 @@ struct ptp_ocp {
struct platform_device *spi_flash;
struct clk_hw *i2c_clk;
struct timer_list watchdog;
+ struct dentry *debug_root;
time64_t gnss_lost;
int id;
int n_irqs;
@@ -354,6 +357,10 @@ static struct ocp_resource ocp_fb_resource[] = {
OCP_MEM_RESOURCE(image),
.offset = 0x00020000, .size = 0x1000,
},
+ {
+ OCP_MEM_RESOURCE(pps_select),
+ .offset = 0x00130000, .size = 0x1000,
+ },
{
OCP_MEM_RESOURCE(sma),
.offset = 0x00140000, .size = 0x1000,
@@ -1684,6 +1691,223 @@ static struct attribute *timecard_attrs[] = {
};
ATTRIBUTE_GROUPS(timecard);
+#ifdef CONFIG_DEBUG_FS
+#define gpio_map(gpio, bit, pri, sec, def) ({ \
+ char *_ans; \
+ if (gpio & (1 << bit)) \
+ _ans = pri; \
+ else if (gpio & (1 << (bit + 16))) \
+ _ans = sec; \
+ else \
+ _ans = def; \
+ _ans; \
+})
+
+#define gpio_multi_map(buf, gpio, bit, pri, sec, def) ({ \
+ char *_ans; \
+ _ans = buf; \
+ strcpy(buf, def); \
+ if (gpio & (1 << (bit + 16))) \
+ _ans += sprintf(_ans, "%s ", pri); \
+ if (gpio & (1 << bit)) \
+ _ans += sprintf(_ans, "%s ", sec); \
+})
+
+static int
+ptp_ocp_summary_show(struct seq_file *s, void *data)
+{
+ struct device *dev = s->private;
+ struct ts_reg __iomem *ts_reg;
+ u32 sma_in, sma_out, val;
+ struct timespec64 ts;
+ struct ptp_ocp *bp;
+ char *buf, *src;
+ bool on;
+
+ buf = (char *)__get_free_page(GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ sma1_out_show(dev, NULL, buf);
+ seq_printf(s, " sma1: out from %s", buf);
+
+ sma2_out_show(dev, NULL, buf);
+ seq_printf(s, " sma2: out from %s", buf);
+
+ sma3_in_show(dev, NULL, buf);
+ seq_printf(s, " sma3: input to %s", buf);
+
+ sma4_in_show(dev, NULL, buf);
+ seq_printf(s, " sma4: input to %s", buf);
+
+ bp = dev_get_drvdata(dev);
+ sma_in = ioread32(&bp->sma->gpio1);
+ sma_out = ioread32(&bp->sma->gpio2);
+
+ if (bp->ts0) {
+ ts_reg = bp->ts0->mem;
+ on = ioread32(&ts_reg->enable);
+ src = "GNSS";
+ seq_printf(s, "%7s: %s, src: %s\n", "TS0",
+ on ? " ON" : "OFF", src);
+ }
+
+ if (bp->ts1) {
+ ts_reg = bp->ts1->mem;
+ on = ioread32(&ts_reg->enable);
+ src = gpio_map(sma_in, 2, "sma4", "sma3", "----");
+ seq_printf(s, "%7s: %s, src: %s\n", "TS1",
+ on ? " ON" : "OFF", src);
+ }
+
+ if (bp->ts2) {
+ ts_reg = bp->ts2->mem;
+ on = ioread32(&ts_reg->enable);
+ src = gpio_map(sma_in, 3, "sma4", "sma3", "----");
+ seq_printf(s, "%7s: %s, src: %s\n", "TS2",
+ on ? " ON" : "OFF", src);
+ }
+
+ if (bp->irig_out) {
+ on = ioread32(&bp->irig_out->ctrl) & IRIG_M_CTRL_ENABLE;
+ val = ioread32(&bp->irig_out->status);
+ gpio_multi_map(buf, sma_out, 4, "sma1", "sma2", "----");
+ seq_printf(s, "%7s: %s, error: %d, out: %s\n", "IRIG",
+ on ? " ON" : "OFF", val, buf);
+ }
+
+ if (bp->irig_in) {
+ on = ioread32(&bp->irig_in->ctrl) & IRIG_S_CTRL_ENABLE;
+ val = ioread32(&bp->irig_in->status);
+ src = gpio_map(sma_in, 4, "sma4", "sma3", "----");
+ seq_printf(s, "%7s: %s, error: %d, src: %s\n", "IRIG in",
+ on ? " ON" : "OFF", val, src);
+ }
+
+ if (bp->dcf_out) {
+ on = ioread32(&bp->dcf_out->ctrl) & DCF_M_CTRL_ENABLE;
+ val = ioread32(&bp->dcf_out->status);
+ gpio_multi_map(buf, sma_out, 5, "sma1", "sma2", "----");
+ seq_printf(s, "%7s: %s, error: %d, out: %s\n", "DCF",
+ on ? " ON" : "OFF", val, buf);
+ }
+
+ if (bp->dcf_in) {
+ on = ioread32(&bp->dcf_in->ctrl) & DCF_S_CTRL_ENABLE;
+ val = ioread32(&bp->dcf_in->status);
+ src = gpio_map(sma_in, 5, "sma4", "sma3", "----");
+ seq_printf(s, "%7s: %s, error: %d, src: %s\n", "DCF in",
+ on ? " ON" : "OFF", val, src);
+ }
+
+ src = gpio_map(sma_in, 2, "sma4", "sma3", "GNSS");
+ sprintf(buf, "%s via PPS2", src);
+ seq_printf(s, " MAC PPS src: %s\n", buf);
+
+ /* assumes automatic switchover/selection */
+ val = ioread32(&bp->reg->select);
+ switch (val >> 16) {
+ case 0:
+ sprintf(buf, "----");
+ break;
+ case 2:
+ sprintf(buf, "IRIG");
+ break;
+ case 3:
+ if (bp->pps_select) {
+ val = ioread32(&bp->pps_select->gpio1);
+ if (val & 0x01) {
+ src = gpio_map(sma_in, 1,
+ "sma4", "sma3", "----");
+ } else if (val & 0x02)
+ src = "MAC";
+ else if (val & 0x04)
+ src = "GNSS";
+ else
+ src = "----";
+ sprintf(buf, "%s via PPS1", src);
+ } else {
+ strcpy(buf, "PPS1");
+ }
+ break;
+ case 6:
+ sprintf(buf, "DCF");
+ break;
+ default:
+ strcpy(buf, "unknown");
+ break;
+ }
+ val = ioread32(&bp->reg->status);
+ seq_printf(s, "%7s: %s, state: %s\n", "PHC src", buf,
+ val & OCP_STATUS_IN_SYNC ? "sync" : "unsynced");
+
+ if (!ptp_ocp_gettimex(&bp->ptp_info, &ts, NULL))
+ seq_printf(s, "%7s: %lld.%ld == %ptT\n", "PHC",
+ ts.tv_sec, ts.tv_nsec, &ts);
+
+ free_page((unsigned long)buf);
+ return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(ptp_ocp_summary);
+
+static struct dentry *ptp_ocp_debugfs_root;
+
+static int
+ptp_ocp_debugfs_add_device(struct ptp_ocp *bp)
+{
+ struct dentry *d;
+
+ d = debugfs_create_dir(dev_name(&bp->dev), ptp_ocp_debugfs_root);
+ if (IS_ERR(d))
+ return PTR_ERR(d);
+ bp->debug_root = d;
+
+ d = debugfs_create_file("summary", 0444, bp->debug_root,
+ &bp->dev, &ptp_ocp_summary_fops);
+ if (IS_ERR(d))
+ goto fail;
+
+ return 0;
+
+fail:
+ debugfs_remove_recursive(bp->debug_root);
+ bp->debug_root = NULL;
+
+ return PTR_ERR(d);
+}
+
+static void
+ptp_ocp_debugfs_remove_device(struct ptp_ocp *bp)
+{
+ debugfs_remove_recursive(bp->debug_root);
+}
+
+static int
+ptp_ocp_debugfs_init(void)
+{
+ struct dentry *d;
+
+ d = debugfs_create_dir("timecard", NULL);
+ if (IS_ERR(d))
+ return PTR_ERR(d);
+
+ ptp_ocp_debugfs_root = d;
+
+ return 0;
+}
+
+static void
+ptp_ocp_debugfs_fini(void)
+{
+ debugfs_remove_recursive(ptp_ocp_debugfs_root);
+}
+#else
+#define ptp_ocp_debugfs_init() 0
+#define ptp_ocp_debugfs_fini()
+#define ptp_ocp_debugfs_add_device(bp) 0
+#define ptp_ocp_debugfs_remove_device(bp)
+#endif
+
static void
ptp_ocp_dev_release(struct device *dev)
{
@@ -1787,6 +2011,9 @@ ptp_ocp_complete(struct ptp_ocp *bp)
if (device_add_groups(&bp->dev, timecard_groups))
pr_err("device add groups failed\n");
+ if (ptp_ocp_debugfs_add_device(bp))
+ pr_err("debugfs add device failed\n");
+
return 0;
}
@@ -1827,6 +2054,7 @@ ptp_ocp_detach_sysfs(struct ptp_ocp *bp)
static void
ptp_ocp_detach(struct ptp_ocp *bp)
{
+ ptp_ocp_debugfs_remove_device(bp);
ptp_ocp_detach_sysfs(bp);
if (timer_pending(&bp->watchdog))
del_timer_sync(&bp->watchdog);
@@ -1997,10 +2225,15 @@ ptp_ocp_init(void)
const char *what;
int err;
+ what = "debugfs entry";
+ err = ptp_ocp_debugfs_init();
+ if (err)
+ goto out;
+
what = "timecard class";
err = class_register(&timecard_class);
if (err)
- goto out;
+ goto out_debug;
what = "i2c notifier";
err = bus_register_notifier(&i2c_bus_type, &ptp_ocp_i2c_notifier);
@@ -2018,6 +2251,8 @@ ptp_ocp_init(void)
bus_unregister_notifier(&i2c_bus_type, &ptp_ocp_i2c_notifier);
out_notifier:
class_unregister(&timecard_class);
+out_debug:
+ ptp_ocp_debugfs_fini();
out:
pr_err(KBUILD_MODNAME ": failed to register %s: %d\n", what, err);
return err;
@@ -2029,6 +2264,7 @@ ptp_ocp_fini(void)
bus_unregister_notifier(&i2c_bus_type, &ptp_ocp_i2c_notifier);
pci_unregister_driver(&ptp_ocp_driver);
class_unregister(&timecard_class);
+ ptp_ocp_debugfs_fini();
}
module_init(ptp_ocp_init);
--
2.31.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH net-next 10/11] ptp: ocp: Add IRIG-B output mode control
2021-08-30 23:52 [PATCH net-next 00/11] ocp timecard updates Jonathan Lemon
` (8 preceding siblings ...)
2021-08-30 23:52 ` [PATCH net-next 09/11] ptp: ocp: Add debugfs entry for timecard Jonathan Lemon
@ 2021-08-30 23:52 ` Jonathan Lemon
2021-09-02 0:07 ` Jakub Kicinski
2021-08-30 23:52 ` [PATCH net-next 11/11] docs: ABI: Add sysfs documentation for timecard Jonathan Lemon
10 siblings, 1 reply; 21+ messages in thread
From: Jonathan Lemon @ 2021-08-30 23:52 UTC (permalink / raw)
To: davem, kuba, richardcochran; +Cc: netdev, kernel-team, abyagowi
IRIG-B has several different output formats, the timecard defaults
to using B007. Add a control which selects different output modes.
Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
---
drivers/ptp/ptp_ocp.c | 50 +++++++++++++++++++++++++++++++++++++++----
1 file changed, 46 insertions(+), 4 deletions(-)
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index daa95f48c39f..3cc1b5e661af 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -1634,6 +1634,46 @@ utc_tai_offset_store(struct device *dev,
}
static DEVICE_ATTR_RW(utc_tai_offset);
+static ssize_t
+irig_b_mode_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ u32 val;
+
+ val = ioread32(&bp->irig_out->ctrl);
+ val = (val >> 16) & 0x07;
+ return sysfs_emit(buf, "%d\n", val);
+}
+
+static ssize_t
+irig_b_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct ptp_ocp *bp = dev_get_drvdata(dev);
+ unsigned long flags;
+ int err;
+ u32 reg;
+ u8 val;
+
+ err = kstrtou8(buf, 0, &val);
+ if (err)
+ return err;
+ if (val > 7)
+ return -EINVAL;
+
+ reg = ((val & 0x7) << 16);
+
+ spin_lock_irqsave(&bp->lock, flags);
+ iowrite32(0, &bp->irig_out->ctrl); /* disable */
+ iowrite32(reg, &bp->irig_out->ctrl); /* change mode */
+ iowrite32(reg | IRIG_M_CTRL_ENABLE, &bp->irig_out->ctrl);
+ spin_unlock_irqrestore(&bp->lock, flags);
+
+ return count;
+}
+static DEVICE_ATTR_RW(irig_b_mode);
+
static ssize_t
clock_source_show(struct device *dev, struct device_attribute *attr, char *buf)
{
@@ -1687,6 +1727,7 @@ static struct attribute *timecard_attrs[] = {
&dev_attr_available_sma_inputs.attr,
&dev_attr_available_sma_outputs.attr,
&dev_attr_utc_tai_offset.attr,
+ &dev_attr_irig_b_mode.attr,
NULL,
};
ATTRIBUTE_GROUPS(timecard);
@@ -1718,7 +1759,7 @@ ptp_ocp_summary_show(struct seq_file *s, void *data)
{
struct device *dev = s->private;
struct ts_reg __iomem *ts_reg;
- u32 sma_in, sma_out, val;
+ u32 sma_in, sma_out, ctrl, val;
struct timespec64 ts;
struct ptp_ocp *bp;
char *buf, *src;
@@ -1769,11 +1810,12 @@ ptp_ocp_summary_show(struct seq_file *s, void *data)
}
if (bp->irig_out) {
- on = ioread32(&bp->irig_out->ctrl) & IRIG_M_CTRL_ENABLE;
+ ctrl = ioread32(&bp->irig_out->ctrl);
+ on = ctrl & IRIG_M_CTRL_ENABLE;
val = ioread32(&bp->irig_out->status);
gpio_multi_map(buf, sma_out, 4, "sma1", "sma2", "----");
- seq_printf(s, "%7s: %s, error: %d, out: %s\n", "IRIG",
- on ? " ON" : "OFF", val, buf);
+ seq_printf(s, "%7s: %s, error: %d, mode %d, out: %s\n", "IRIG",
+ on ? " ON" : "OFF", val, (ctrl >> 16), buf);
}
if (bp->irig_in) {
--
2.31.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* [PATCH net-next 11/11] docs: ABI: Add sysfs documentation for timecard
2021-08-30 23:52 [PATCH net-next 00/11] ocp timecard updates Jonathan Lemon
` (9 preceding siblings ...)
2021-08-30 23:52 ` [PATCH net-next 10/11] ptp: ocp: Add IRIG-B output mode control Jonathan Lemon
@ 2021-08-30 23:52 ` Jonathan Lemon
10 siblings, 0 replies; 21+ messages in thread
From: Jonathan Lemon @ 2021-08-30 23:52 UTC (permalink / raw)
To: davem, kuba, richardcochran; +Cc: netdev, kernel-team, abyagowi
This patch describes the sysfs interface implemented by the
ptp_ocp driver, under /sys/class/timecard.
Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
---
Documentation/ABI/testing/sysfs-timecard | 141 +++++++++++++++++++++++
1 file changed, 141 insertions(+)
create mode 100644 Documentation/ABI/testing/sysfs-timecard
diff --git a/Documentation/ABI/testing/sysfs-timecard b/Documentation/ABI/testing/sysfs-timecard
new file mode 100644
index 000000000000..a473b953b4d3
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-timecard
@@ -0,0 +1,141 @@
+What: /sys/class/timecard/
+Date: September 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: This directory contains files and directories
+ providing a standardized interface to the ancillary
+ features of the OpenCompute timecard.
+
+What: /sys/class/timecard/ocpN/
+Date: September 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: This directory contains the attributes of the Nth timecard
+ registered.
+
+What: /sys/class/timecard/ocpN/available_clock_sources
+Date: September 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: (RO) The list of available time sources that the PHC
+ uses for clock adjustments.
+
+ ==== =================================================
+ NONE no adjustments
+ PPS adjustments come from the PPS1 selector (default)
+ TOD adjustments from the GNSS/TOD module
+ IRIG adjustments from external IRIG-B signal
+ DCF adjustments from external DCF signal
+ ==== =================================================
+
+What: /sys/class/timecard/ocpN/available_sma_inputs
+Date: September 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: (RO) Set of available destinations (sinks) for a SMA
+ input signal.
+
+ ===== ================================================
+ 10Mhz signal is used as the 10Mhz reference clock
+ PPS1 signal is sent to the PPS1 selector
+ PPS2 signal is sent to the PPS2 selector
+ TS1 signal is sent to timestamper 1
+ TS2 signal is sent to timestamper 2
+ IRIG signal is sent to the IRIG-B module
+ DCF signal is sent to the DCF module
+ ===== ================================================
+
+What: /sys/class/timecard/ocpN/available_sma_outputs
+Date: May 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: (RO) Set of available sources for a SMA output signal.
+
+ ===== ================================================
+ 10Mhz output is from the 10Mhz reference clock
+ PHC output PPS is from the PHC clock
+ MAC output PPS is from the Miniature Atomic Clock
+ GNSS output PPS is from the GNSS module
+ GNSS2 output PPS is from the second GNSS module
+ IRIG output is from the PHC, in IRIG-B format
+ DCF output is from the PHC, in DCF format
+ ===== ================================================
+
+What: /sys/class/timecard/ocpN/clock_source
+Date: September 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: (RW) Contains the current synchronization source used by
+ the PHC. May be changed by writing one of the listed
+ values from the available_clock_sources attribute set.
+
+What: /sys/class/timecard/ocpN/gnss_sync
+Date: September 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: (RO) Indicates whether a valid GNSS signal is received,
+ or when the signal was lost.
+
+What: /sys/class/timecard/ocpN/i2c
+Date: September 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: This optional attribute links to the associated i2c device.
+
+What: /sys/class/timecard/ocpN/irig_b_mode
+Date: September 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: (RW) An integer from 0-7 indicating the timecode format
+ of the IRIG-B output signal: B00<n>
+
+What: /sys/class/timecard/ocpN/pps
+Date: September 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: This optional attribute links to the associated PPS device.
+
+What: /sys/class/timecard/ocpN/ptp
+Date: September 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: This attribute links to the associated PTP device.
+
+What: /sys/class/timecard/ocpN/serialnum
+Date: September 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: (RO) Provides the serial number of the timecard.
+
+What: /sys/class/timecard/ocpN/sma1_out
+What: /sys/class/timecard/ocpN/sma2_out
+Date: September 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: (RW) These attributes specify the signal present on the
+ associated SMA connectors. May be changed by writing one of
+ the listed values from the available_sma_outputs attribute set.
+
+What: /sys/class/timecard/ocpN/sma3_in
+What: /sys/class/timecard/ocpN/sma4_in
+Date: September 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: (RW) These attributes specify where the input signal on the
+ associated connector should be sent. May be changed by writing
+ multiple values from the available_sma_outputs attribute set,
+ separated by spaces. If there are duplicated destinations
+ between the two connectors, SMA4 is given priority.
+
+ Note that not all combinations may make sense.
+
+ The 10Mhz reference clock is only valid on SMA4 and may not
+ be combined with other destination sinks.
+
+What: /sys/class/timecard/ocpN/ttyGNSS
+Date: September 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: This optional attribute links to the TTY serial port
+ associated with the GNSS device.
+
+What: /sys/class/timecard/ocpN/ttyMAC
+Date: September 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: This optional attribute links to the TTY serial port
+ associated with the Miniature Atomic Clock.
+
+What: /sys/class/timecard/ocpN/utc_tai_offset
+Date: September 2021
+Contact: Jonathan Lemon <jonathan.lemon@gmail.com>
+Description: (RW) The DCF and IRIG output signals are in UTC, while the
+ TimeCard operates on TAI. This attribute allows setting the
+ offset in seconds, which is added to the TAI timebase for
+ these formats.
+
+ The offset may be changed by writing a signed integer.
--
2.31.1
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH net-next 06/11] ptp: ocp: Add SMA selector and controls
2021-08-30 23:52 ` [PATCH net-next 06/11] ptp: ocp: Add SMA selector and controls Jonathan Lemon
@ 2021-09-01 23:56 ` Jakub Kicinski
2021-09-02 16:55 ` Jonathan Lemon
0 siblings, 1 reply; 21+ messages in thread
From: Jakub Kicinski @ 2021-09-01 23:56 UTC (permalink / raw)
To: Jonathan Lemon; +Cc: davem, richardcochran, netdev, kernel-team, abyagowi
On Mon, 30 Aug 2021 16:52:31 -0700 Jonathan Lemon wrote:
> static int
> -ptp_ocp_clock_val_from_name(const char *name)
> +select_val_from_name(struct ocp_selector *tbl, const char *name)
Why not prefix the helpers with ptp_ocp_ ? Makes code easier to follow
IMHO.
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH net-next 08/11] ptp: ocp: Add sysfs attribute utc_tai_offset
2021-08-30 23:52 ` [PATCH net-next 08/11] ptp: ocp: Add sysfs attribute utc_tai_offset Jonathan Lemon
@ 2021-09-01 23:56 ` Jakub Kicinski
2021-09-02 16:57 ` Jonathan Lemon
0 siblings, 1 reply; 21+ messages in thread
From: Jakub Kicinski @ 2021-09-01 23:56 UTC (permalink / raw)
To: Jonathan Lemon; +Cc: davem, richardcochran, netdev, kernel-team, abyagowi
On Mon, 30 Aug 2021 16:52:33 -0700 Jonathan Lemon wrote:
> +static ssize_t
> +utc_tai_offset_show(struct device *dev,
> + struct device_attribute *attr, char *buf)
> +{
> + struct ptp_ocp *bp = dev_get_drvdata(dev);
> +
> + return sysfs_emit(buf, "%d\n", bp->utc_tai_offset);
> +}
> +
> +static ssize_t
> +utc_tai_offset_store(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf, size_t count)
> +{
> + struct ptp_ocp *bp = dev_get_drvdata(dev);
> + unsigned long flags;
> + int err;
> + s32 val;
> +
> + err = kstrtos32(buf, 0, &val);
> + if (err)
> + return err;
> +
> + bp->utc_tai_offset = val;
This line should probably be under the lock.
> + spin_lock_irqsave(&bp->lock, flags);
> + iowrite32(val, &bp->irig_out->adj_sec);
> + iowrite32(val, &bp->dcf_out->adj_sec);
> + spin_unlock_irqrestore(&bp->lock, flags);
> +
> + return count;
> +}
> +static DEVICE_ATTR_RW(utc_tai_offset);
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH net-next 09/11] ptp: ocp: Add debugfs entry for timecard
2021-08-30 23:52 ` [PATCH net-next 09/11] ptp: ocp: Add debugfs entry for timecard Jonathan Lemon
@ 2021-09-02 0:06 ` Jakub Kicinski
2021-09-02 17:00 ` Jonathan Lemon
0 siblings, 1 reply; 21+ messages in thread
From: Jakub Kicinski @ 2021-09-02 0:06 UTC (permalink / raw)
To: Jonathan Lemon; +Cc: davem, richardcochran, netdev, kernel-team, abyagowi
On Mon, 30 Aug 2021 16:52:34 -0700 Jonathan Lemon wrote:
> Provide a view into the timecard internals for debugging.
>
> Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
> +#ifdef CONFIG_DEBUG_FS
> +#define gpio_map(gpio, bit, pri, sec, def) ({ \
> + char *_ans; \
> + if (gpio & (1 << bit)) \
> + _ans = pri; \
> + else if (gpio & (1 << (bit + 16))) \
> + _ans = sec; \
> + else \
> + _ans = def; \
> + _ans; \
> +})
> +
> +#define gpio_multi_map(buf, gpio, bit, pri, sec, def) ({ \
> + char *_ans; \
> + _ans = buf; \
> + strcpy(buf, def); \
> + if (gpio & (1 << (bit + 16))) \
> + _ans += sprintf(_ans, "%s ", pri); \
> + if (gpio & (1 << bit)) \
> + _ans += sprintf(_ans, "%s ", sec); \
> +})
These can't be static inlines?
> +static int
> +ptp_ocp_summary_show(struct seq_file *s, void *data)
> +{
> + struct device *dev = s->private;
> + struct ts_reg __iomem *ts_reg;
> + u32 sma_in, sma_out, val;
> + struct timespec64 ts;
> + struct ptp_ocp *bp;
> + char *buf, *src;
> + bool on;
> +
> + buf = (char *)__get_free_page(GFP_KERNEL);
> + if (!buf)
> + return -ENOMEM;
> +
> + sma1_out_show(dev, NULL, buf);
> + seq_printf(s, " sma1: out from %s", buf);
> +
> + sma2_out_show(dev, NULL, buf);
> + seq_printf(s, " sma2: out from %s", buf);
> +
> + sma3_in_show(dev, NULL, buf);
> + seq_printf(s, " sma3: input to %s", buf);
> +
> + sma4_in_show(dev, NULL, buf);
> + seq_printf(s, " sma4: input to %s", buf);
Why duplicate the data already available via sysfs?
> +static int
> +ptp_ocp_debugfs_add_device(struct ptp_ocp *bp)
> +{
> + struct dentry *d;
> +
> + d = debugfs_create_dir(dev_name(&bp->dev), ptp_ocp_debugfs_root);
> + if (IS_ERR(d))
> + return PTR_ERR(d);
Driver's are not supposed to depend on debugfs, you should be able to
carry on and all debugfs functions you pass an error pointer as a
parent will just return the same error right back.
> + bp->debug_root = d;
> +
> + d = debugfs_create_file("summary", 0444, bp->debug_root,
> + &bp->dev, &ptp_ocp_summary_fops);
> + if (IS_ERR(d))
> + goto fail;
> +
> + return 0;
> +
> +fail:
> + debugfs_remove_recursive(bp->debug_root);
> + bp->debug_root = NULL;
> +
> + return PTR_ERR(d);
> +}
> +
> +static void
> +ptp_ocp_debugfs_remove_device(struct ptp_ocp *bp)
> +{
> + debugfs_remove_recursive(bp->debug_root);
> +}
> +
> +static int
> +ptp_ocp_debugfs_init(void)
> +{
> + struct dentry *d;
> +
> + d = debugfs_create_dir("timecard", NULL);
> + if (IS_ERR(d))
> + return PTR_ERR(d);
> +
> + ptp_ocp_debugfs_root = d;
> +
> + return 0;
> +}
> +
> +static void
> +ptp_ocp_debugfs_fini(void)
> +{
> + debugfs_remove_recursive(ptp_ocp_debugfs_root);
> +}
> +#else
> +#define ptp_ocp_debugfs_init() 0
> +#define ptp_ocp_debugfs_fini()
> +#define ptp_ocp_debugfs_add_device(bp) 0
> +#define ptp_ocp_debugfs_remove_device(bp)
> +#endif
This should not be necessary. Compiler should remove all those
functions as dead code when debugfs is not compiled in.
> static void
> ptp_ocp_dev_release(struct device *dev)
> {
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH net-next 10/11] ptp: ocp: Add IRIG-B output mode control
2021-08-30 23:52 ` [PATCH net-next 10/11] ptp: ocp: Add IRIG-B output mode control Jonathan Lemon
@ 2021-09-02 0:07 ` Jakub Kicinski
2021-09-02 17:02 ` Jonathan Lemon
0 siblings, 1 reply; 21+ messages in thread
From: Jakub Kicinski @ 2021-09-02 0:07 UTC (permalink / raw)
To: Jonathan Lemon; +Cc: davem, richardcochran, netdev, kernel-team, abyagowi
On Mon, 30 Aug 2021 16:52:35 -0700 Jonathan Lemon wrote:
> + err = kstrtou8(buf, 0, &val);
> + if (err)
> + return err;
> + if (val > 7)
> + return -EINVAL;
> +
> + reg = ((val & 0x7) << 16);
> +
> + spin_lock_irqsave(&bp->lock, flags);
> + iowrite32(0, &bp->irig_out->ctrl); /* disable */
> + iowrite32(reg, &bp->irig_out->ctrl); /* change mode */
> + iowrite32(reg | IRIG_M_CTRL_ENABLE, &bp->irig_out->ctrl);
> + spin_unlock_irqrestore(&bp->lock, flags);
locking
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH net-next 06/11] ptp: ocp: Add SMA selector and controls
2021-09-01 23:56 ` Jakub Kicinski
@ 2021-09-02 16:55 ` Jonathan Lemon
0 siblings, 0 replies; 21+ messages in thread
From: Jonathan Lemon @ 2021-09-02 16:55 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: davem, richardcochran, netdev, kernel-team, abyagowi
On Wed, Sep 01, 2021 at 04:56:12PM -0700, Jakub Kicinski wrote:
> On Mon, 30 Aug 2021 16:52:31 -0700 Jonathan Lemon wrote:
> > static int
> > -ptp_ocp_clock_val_from_name(const char *name)
> > +select_val_from_name(struct ocp_selector *tbl, const char *name)
>
> Why not prefix the helpers with ptp_ocp_ ? Makes code easier to follow
> IMHO.
Will fix. Was adding these for use by the DEVICE_ATTR functions, and
those don't have prefixes, so I neglected to namespace them.
--
Jonathan
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH net-next 08/11] ptp: ocp: Add sysfs attribute utc_tai_offset
2021-09-01 23:56 ` Jakub Kicinski
@ 2021-09-02 16:57 ` Jonathan Lemon
0 siblings, 0 replies; 21+ messages in thread
From: Jonathan Lemon @ 2021-09-02 16:57 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: davem, richardcochran, netdev, kernel-team, abyagowi
On Wed, Sep 01, 2021 at 04:56:42PM -0700, Jakub Kicinski wrote:
> On Mon, 30 Aug 2021 16:52:33 -0700 Jonathan Lemon wrote:
> > +static ssize_t
> > +utc_tai_offset_show(struct device *dev,
> > + struct device_attribute *attr, char *buf)
> > +{
> > + struct ptp_ocp *bp = dev_get_drvdata(dev);
> > +
> > + return sysfs_emit(buf, "%d\n", bp->utc_tai_offset);
> > +}
> > +
> > +static ssize_t
> > +utc_tai_offset_store(struct device *dev,
> > + struct device_attribute *attr,
> > + const char *buf, size_t count)
> > +{
> > + struct ptp_ocp *bp = dev_get_drvdata(dev);
> > + unsigned long flags;
> > + int err;
> > + s32 val;
> > +
> > + err = kstrtos32(buf, 0, &val);
> > + if (err)
> > + return err;
> > +
> > + bp->utc_tai_offset = val;
>
> This line should probably be under the lock.
Ack.
BTW, I hate this entire function - but don't really
see a better way to handle it. One suggestion was
to automatically get the offset from the NMEA parser,
but I can't depend on GNSS being available.
--
Jonathan
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH net-next 09/11] ptp: ocp: Add debugfs entry for timecard
2021-09-02 0:06 ` Jakub Kicinski
@ 2021-09-02 17:00 ` Jonathan Lemon
0 siblings, 0 replies; 21+ messages in thread
From: Jonathan Lemon @ 2021-09-02 17:00 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: davem, richardcochran, netdev, kernel-team, abyagowi
On Wed, Sep 01, 2021 at 05:06:41PM -0700, Jakub Kicinski wrote:
> On Mon, 30 Aug 2021 16:52:34 -0700 Jonathan Lemon wrote:
> > Provide a view into the timecard internals for debugging.
> >
> > Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
>
> > +#ifdef CONFIG_DEBUG_FS
> > +#define gpio_map(gpio, bit, pri, sec, def) ({ \
> > + char *_ans; \
> > + if (gpio & (1 << bit)) \
> > + _ans = pri; \
> > + else if (gpio & (1 << (bit + 16))) \
> > + _ans = sec; \
> > + else \
> > + _ans = def; \
> > + _ans; \
> > +})
> > +
> > +#define gpio_multi_map(buf, gpio, bit, pri, sec, def) ({ \
> > + char *_ans; \
> > + _ans = buf; \
> > + strcpy(buf, def); \
> > + if (gpio & (1 << (bit + 16))) \
> > + _ans += sprintf(_ans, "%s ", pri); \
> > + if (gpio & (1 << bit)) \
> > + _ans += sprintf(_ans, "%s ", sec); \
> > +})
>
> These can't be static inlines?
Fixed - old habit of writing macros.
> > +static int
> > +ptp_ocp_summary_show(struct seq_file *s, void *data)
> > +{
> > + struct device *dev = s->private;
> > + struct ts_reg __iomem *ts_reg;
> > + u32 sma_in, sma_out, val;
> > + struct timespec64 ts;
> > + struct ptp_ocp *bp;
> > + char *buf, *src;
> > + bool on;
> > +
> > + buf = (char *)__get_free_page(GFP_KERNEL);
> > + if (!buf)
> > + return -ENOMEM;
> > +
> > + sma1_out_show(dev, NULL, buf);
> > + seq_printf(s, " sma1: out from %s", buf);
> > +
> > + sma2_out_show(dev, NULL, buf);
> > + seq_printf(s, " sma2: out from %s", buf);
> > +
> > + sma3_in_show(dev, NULL, buf);
> > + seq_printf(s, " sma3: input to %s", buf);
> > +
> > + sma4_in_show(dev, NULL, buf);
> > + seq_printf(s, " sma4: input to %s", buf);
>
> Why duplicate the data already available via sysfs?
It is convenient to have all the information on
one page when trying to understand where the signals
are being steered.
[ snip ]
> Driver's are not supposed to depend on debugfs, you should be able to
> carry on and all debugfs functions you pass an error pointer as a
> parent will just return the same error right back.
Ack.
> This should not be necessary. Compiler should remove all those
> functions as dead code when debugfs is not compiled in.
Removed #ifdef - now the _summary function is left in
and the compiler removes it in the dead code pass.
--
Jonathan
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH net-next 10/11] ptp: ocp: Add IRIG-B output mode control
2021-09-02 0:07 ` Jakub Kicinski
@ 2021-09-02 17:02 ` Jonathan Lemon
2021-09-02 22:41 ` Jakub Kicinski
0 siblings, 1 reply; 21+ messages in thread
From: Jonathan Lemon @ 2021-09-02 17:02 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: davem, richardcochran, netdev, kernel-team, abyagowi
On Wed, Sep 01, 2021 at 05:07:00PM -0700, Jakub Kicinski wrote:
> On Mon, 30 Aug 2021 16:52:35 -0700 Jonathan Lemon wrote:
> > + err = kstrtou8(buf, 0, &val);
> > + if (err)
> > + return err;
> > + if (val > 7)
> > + return -EINVAL;
> > +
> > + reg = ((val & 0x7) << 16);
> > +
> > + spin_lock_irqsave(&bp->lock, flags);
> > + iowrite32(0, &bp->irig_out->ctrl); /* disable */
> > + iowrite32(reg, &bp->irig_out->ctrl); /* change mode */
> > + iowrite32(reg | IRIG_M_CTRL_ENABLE, &bp->irig_out->ctrl);
> > + spin_unlock_irqrestore(&bp->lock, flags);
>
> locking
Not sure what you mean - all register manipulations are
already done under the lock here.
--
Jonathan
^ permalink raw reply [flat|nested] 21+ messages in thread
* Re: [PATCH net-next 10/11] ptp: ocp: Add IRIG-B output mode control
2021-09-02 17:02 ` Jonathan Lemon
@ 2021-09-02 22:41 ` Jakub Kicinski
0 siblings, 0 replies; 21+ messages in thread
From: Jakub Kicinski @ 2021-09-02 22:41 UTC (permalink / raw)
To: Jonathan Lemon; +Cc: davem, richardcochran, netdev, kernel-team, abyagowi
On Thu, 2 Sep 2021 10:02:16 -0700 Jonathan Lemon wrote:
> On Wed, Sep 01, 2021 at 05:07:00PM -0700, Jakub Kicinski wrote:
> > On Mon, 30 Aug 2021 16:52:35 -0700 Jonathan Lemon wrote:
> > > + err = kstrtou8(buf, 0, &val);
> > > + if (err)
> > > + return err;
> > > + if (val > 7)
> > > + return -EINVAL;
> > > +
> > > + reg = ((val & 0x7) << 16);
> > > +
> > > + spin_lock_irqsave(&bp->lock, flags);
> > > + iowrite32(0, &bp->irig_out->ctrl); /* disable */
> > > + iowrite32(reg, &bp->irig_out->ctrl); /* change mode */
> > > + iowrite32(reg | IRIG_M_CTRL_ENABLE, &bp->irig_out->ctrl);
> > > + spin_unlock_irqrestore(&bp->lock, flags);
> >
> > locking
>
> Not sure what you mean - all register manipulations are
> already done under the lock here.
I must have misread and thought it has the same problem as patch 8,
ignore, sorry.
^ permalink raw reply [flat|nested] 21+ messages in thread
end of thread, other threads:[~2021-09-02 22:41 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-08-30 23:52 [PATCH net-next 00/11] ocp timecard updates Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 01/11] ptp: ocp: parameterize the i2c driver used Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 02/11] ptp: ocp: Parameterize the TOD information display Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 03/11] ptp: ocp: Skip I2C flash read when there is no controller Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 04/11] ptp: ocp: Skip resources with out of range irqs Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 05/11] ptp: ocp: Add third timestamper Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 06/11] ptp: ocp: Add SMA selector and controls Jonathan Lemon
2021-09-01 23:56 ` Jakub Kicinski
2021-09-02 16:55 ` Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 07/11] ptp: ocp: Add IRIG-B and DCF blocks Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 08/11] ptp: ocp: Add sysfs attribute utc_tai_offset Jonathan Lemon
2021-09-01 23:56 ` Jakub Kicinski
2021-09-02 16:57 ` Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 09/11] ptp: ocp: Add debugfs entry for timecard Jonathan Lemon
2021-09-02 0:06 ` Jakub Kicinski
2021-09-02 17:00 ` Jonathan Lemon
2021-08-30 23:52 ` [PATCH net-next 10/11] ptp: ocp: Add IRIG-B output mode control Jonathan Lemon
2021-09-02 0:07 ` Jakub Kicinski
2021-09-02 17:02 ` Jonathan Lemon
2021-09-02 22:41 ` Jakub Kicinski
2021-08-30 23:52 ` [PATCH net-next 11/11] docs: ABI: Add sysfs documentation for timecard Jonathan Lemon
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).