Merge branch 'ptp-ocp-fixes'

Jonathan Lemon says:

====================
ptp: ocp: assorted fixes.

Assorted fixes for the ocp timecard.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2021-08-06 10:41:28 +01:00
commit 370cb73a38
1 changed files with 35 additions and 118 deletions

View File

@ -113,6 +113,8 @@ struct ts_reg {
struct pps_reg {
u32 ctrl;
u32 status;
u32 __pad0[6];
u32 cable_delay;
};
#define PPS_STATUS_FILTER_ERR BIT(0)
@ -149,7 +151,8 @@ struct ptp_ocp {
spinlock_t lock;
struct ocp_reg __iomem *reg;
struct tod_reg __iomem *tod;
struct pps_reg __iomem *pps_monitor;
struct pps_reg __iomem *pps_to_ext;
struct pps_reg __iomem *pps_to_clk;
struct ptp_ocp_ext_src *pps;
struct ptp_ocp_ext_src *ts0;
struct ptp_ocp_ext_src *ts1;
@ -159,17 +162,15 @@ struct ptp_ocp {
struct platform_device *i2c_ctrl;
struct platform_device *spi_flash;
struct clk_hw *i2c_clk;
struct devlink_health_reporter *health;
struct timer_list watchdog;
time64_t gps_lost;
time64_t gnss_lost;
int id;
int n_irqs;
int gps_port;
int gnss_port;
int mac_port; /* miniature atomic clock */
u8 serial[6];
int flash_start;
bool has_serial;
bool pending_image;
};
struct ocp_resource {
@ -181,7 +182,6 @@ struct ocp_resource {
unsigned long bp_offset;
};
static void ptp_ocp_health_update(struct ptp_ocp *bp);
static int ptp_ocp_register_mem(struct ptp_ocp *bp, struct ocp_resource *r);
static int ptp_ocp_register_i2c(struct ptp_ocp *bp, struct ocp_resource *r);
static int ptp_ocp_register_spi(struct ptp_ocp *bp, struct ocp_resource *r);
@ -251,7 +251,11 @@ static struct ocp_resource ocp_fb_resource[] = {
},
},
{
OCP_MEM_RESOURCE(pps_monitor),
OCP_MEM_RESOURCE(pps_to_ext),
.offset = 0x01030000, .size = 0x10000,
},
{
OCP_MEM_RESOURCE(pps_to_clk),
.offset = 0x01040000, .size = 0x10000,
},
{
@ -267,7 +271,7 @@ static struct ocp_resource ocp_fb_resource[] = {
.offset = 0x00150000, .size = 0x10000, .irq_vec = 7,
},
{
OCP_SERIAL_RESOURCE(gps_port),
OCP_SERIAL_RESOURCE(gnss_port),
.offset = 0x00160000 + 0x1000, .irq_vec = 3,
},
{
@ -537,21 +541,19 @@ ptp_ocp_watchdog(struct timer_list *t)
unsigned long flags;
u32 status;
status = ioread32(&bp->pps_monitor->status);
status = ioread32(&bp->pps_to_clk->status);
if (status & PPS_STATUS_SUPERV_ERR) {
iowrite32(status, &bp->pps_monitor->status);
if (!bp->gps_lost) {
iowrite32(status, &bp->pps_to_clk->status);
if (!bp->gnss_lost) {
spin_lock_irqsave(&bp->lock, flags);
__ptp_ocp_clear_drift_locked(bp);
spin_unlock_irqrestore(&bp->lock, flags);
bp->gps_lost = ktime_get_real_seconds();
ptp_ocp_health_update(bp);
bp->gnss_lost = ktime_get_real_seconds();
}
} else if (bp->gps_lost) {
bp->gps_lost = 0;
ptp_ocp_health_update(bp);
} else if (bp->gnss_lost) {
bp->gnss_lost = 0;
}
mod_timer(&bp->watchdog, jiffies + HZ);
@ -733,14 +735,6 @@ ptp_ocp_info(struct ptp_ocp *bp)
ptp_ocp_tod_info(bp);
}
static const struct devlink_param ptp_ocp_devlink_params[] = {
};
static void
ptp_ocp_devlink_set_params_init_values(struct devlink *devlink)
{
}
static int
ptp_ocp_devlink_register(struct devlink *devlink, struct device *dev)
{
@ -750,25 +744,12 @@ ptp_ocp_devlink_register(struct devlink *devlink, struct device *dev)
if (err)
return err;
err = devlink_params_register(devlink, ptp_ocp_devlink_params,
ARRAY_SIZE(ptp_ocp_devlink_params));
ptp_ocp_devlink_set_params_init_values(devlink);
if (err)
goto out;
devlink_params_publish(devlink);
return 0;
out:
devlink_unregister(devlink);
return err;
}
static void
ptp_ocp_devlink_unregister(struct devlink *devlink)
{
devlink_params_unregister(devlink, ptp_ocp_devlink_params,
ARRAY_SIZE(ptp_ocp_devlink_params));
devlink_unregister(devlink);
}
@ -854,8 +835,6 @@ ptp_ocp_devlink_flash_update(struct devlink *devlink,
msg = err ? "Flash error" : "Flash complete";
devlink_flash_update_status_notify(devlink, msg, NULL, 0, 0);
bp->pending_image = true;
put_device(dev);
return err;
}
@ -872,25 +851,18 @@ ptp_ocp_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
if (err)
return err;
if (bp->pending_image) {
err = devlink_info_version_stored_put(req,
"timecard", "pending");
if (err)
return err;
}
if (bp->image) {
u32 ver = ioread32(&bp->image->version);
if (ver & 0xffff) {
sprintf(buf, "%d", ver);
err = devlink_info_version_running_put(req,
"timecard",
"fw",
buf);
} else {
sprintf(buf, "%d", ver >> 16);
err = devlink_info_version_running_put(req,
"golden flash",
"loader",
buf);
}
if (err)
@ -915,58 +887,6 @@ static const struct devlink_ops ptp_ocp_devlink_ops = {
.info_get = ptp_ocp_devlink_info_get,
};
static int
ptp_ocp_health_diagnose(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg,
struct netlink_ext_ack *extack)
{
struct ptp_ocp *bp = devlink_health_reporter_priv(reporter);
char buf[32];
int err;
if (!bp->gps_lost)
return 0;
sprintf(buf, "%ptT", &bp->gps_lost);
err = devlink_fmsg_string_pair_put(fmsg, "Lost sync at", buf);
if (err)
return err;
return 0;
}
static void
ptp_ocp_health_update(struct ptp_ocp *bp)
{
int state;
state = bp->gps_lost ? DEVLINK_HEALTH_REPORTER_STATE_ERROR
: DEVLINK_HEALTH_REPORTER_STATE_HEALTHY;
if (bp->gps_lost)
devlink_health_report(bp->health, "No GPS signal", NULL);
devlink_health_reporter_state_update(bp->health, state);
}
static const struct devlink_health_reporter_ops ptp_ocp_health_ops = {
.name = "gps_sync",
.diagnose = ptp_ocp_health_diagnose,
};
static void
ptp_ocp_devlink_health_register(struct devlink *devlink)
{
struct ptp_ocp *bp = devlink_priv(devlink);
struct devlink_health_reporter *r;
r = devlink_health_reporter_create(devlink, &ptp_ocp_health_ops, 0, bp);
if (IS_ERR(r))
dev_err(&bp->pdev->dev, "Failed to create reporter, err %ld\n",
PTR_ERR(r));
bp->health = r;
}
static void __iomem *
__ptp_ocp_get_mem(struct ptp_ocp *bp, unsigned long start, int size)
{
@ -1265,19 +1185,19 @@ serialnum_show(struct device *dev, struct device_attribute *attr, char *buf)
static DEVICE_ATTR_RO(serialnum);
static ssize_t
gps_sync_show(struct device *dev, struct device_attribute *attr, char *buf)
gnss_sync_show(struct device *dev, struct device_attribute *attr, char *buf)
{
struct ptp_ocp *bp = dev_get_drvdata(dev);
ssize_t ret;
if (bp->gps_lost)
ret = sysfs_emit(buf, "LOST @ %ptT\n", &bp->gps_lost);
if (bp->gnss_lost)
ret = sysfs_emit(buf, "LOST @ %ptT\n", &bp->gnss_lost);
else
ret = sysfs_emit(buf, "SYNC\n");
return ret;
}
static DEVICE_ATTR_RO(gps_sync);
static DEVICE_ATTR_RO(gnss_sync);
static ssize_t
clock_source_show(struct device *dev, struct device_attribute *attr, char *buf)
@ -1334,7 +1254,7 @@ static DEVICE_ATTR_RO(available_clock_sources);
static struct attribute *timecard_attrs[] = {
&dev_attr_serialnum.attr,
&dev_attr_gps_sync.attr,
&dev_attr_gnss_sync.attr,
&dev_attr_clock_source.attr,
&dev_attr_available_clock_sources.attr,
NULL,
@ -1367,7 +1287,7 @@ ptp_ocp_device_init(struct ptp_ocp *bp, struct pci_dev *pdev)
bp->ptp_info = ptp_ocp_clock_info;
spin_lock_init(&bp->lock);
bp->gps_port = -1;
bp->gnss_port = -1;
bp->mac_port = -1;
bp->pdev = pdev;
@ -1381,7 +1301,6 @@ ptp_ocp_device_init(struct ptp_ocp *bp, struct pci_dev *pdev)
err = device_add(&bp->dev);
if (err) {
dev_err(&bp->dev, "device add failed: %d\n", err);
put_device(&bp->dev);
goto out;
}
@ -1391,6 +1310,7 @@ ptp_ocp_device_init(struct ptp_ocp *bp, struct pci_dev *pdev)
out:
ptp_ocp_dev_release(&bp->dev);
put_device(&bp->dev);
return err;
}
@ -1426,9 +1346,9 @@ ptp_ocp_complete(struct ptp_ocp *bp)
struct pps_device *pps;
char buf[32];
if (bp->gps_port != -1) {
sprintf(buf, "ttyS%d", bp->gps_port);
ptp_ocp_link_child(bp, buf, "ttyGPS");
if (bp->gnss_port != -1) {
sprintf(buf, "ttyS%d", bp->gnss_port);
ptp_ocp_link_child(bp, buf, "ttyGNSS");
}
if (bp->mac_port != -1) {
sprintf(buf, "ttyS%d", bp->mac_port);
@ -1463,8 +1383,8 @@ ptp_ocp_resource_summary(struct ptp_ocp *bp)
dev_info(dev, "golden image, version %d\n",
ver >> 16);
}
if (bp->gps_port != -1)
dev_info(dev, "GPS @ /dev/ttyS%d 115200\n", bp->gps_port);
if (bp->gnss_port != -1)
dev_info(dev, "GNSS @ /dev/ttyS%d 115200\n", bp->gnss_port);
if (bp->mac_port != -1)
dev_info(dev, "MAC @ /dev/ttyS%d 57600\n", bp->mac_port);
}
@ -1474,7 +1394,7 @@ ptp_ocp_detach_sysfs(struct ptp_ocp *bp)
{
struct device *dev = &bp->dev;
sysfs_remove_link(&dev->kobj, "ttyGPS");
sysfs_remove_link(&dev->kobj, "ttyGNSS");
sysfs_remove_link(&dev->kobj, "ttyMAC");
sysfs_remove_link(&dev->kobj, "ptp");
sysfs_remove_link(&dev->kobj, "pps");
@ -1493,8 +1413,8 @@ ptp_ocp_detach(struct ptp_ocp *bp)
ptp_ocp_unregister_ext(bp->ts1);
if (bp->pps)
ptp_ocp_unregister_ext(bp->pps);
if (bp->gps_port != -1)
serial8250_unregister_port(bp->gps_port);
if (bp->gnss_port != -1)
serial8250_unregister_port(bp->gnss_port);
if (bp->mac_port != -1)
serial8250_unregister_port(bp->mac_port);
if (bp->spi_flash)
@ -1507,8 +1427,6 @@ ptp_ocp_detach(struct ptp_ocp *bp)
pci_free_irq_vectors(bp->pdev);
if (bp->ptp)
ptp_clock_unregister(bp->ptp);
if (bp->health)
devlink_health_reporter_destroy(bp->health);
device_unregister(&bp->dev);
}
@ -1571,7 +1489,6 @@ ptp_ocp_probe(struct pci_dev *pdev, const struct pci_device_id *id)
ptp_ocp_info(bp);
ptp_ocp_resource_summary(bp);
ptp_ocp_devlink_health_register(devlink);
return 0;