ptp: ocp: Add firmware capability bits for feature gating

Add the ability to group sysfs nodes behind a firmware feature
check.  This way non-present sysfs attributes are omitted on
older firmware, which does not have newer features.

This will be used in the upcoming patches which adds more
features to the timecard.

Signed-off-by: Jonathan Lemon <jonathan.lemon@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Jonathan Lemon 2022-03-10 12:19:07 -08:00 committed by David S. Miller
parent cd09193ffb
commit c205d53c49
1 changed files with 33 additions and 5 deletions

View File

@ -218,6 +218,13 @@ struct ptp_ocp_sma_connector {
bool disabled;
};
struct ocp_attr_group {
u64 cap;
const struct attribute_group *group;
};
#define OCP_CAP_BASIC BIT(0)
#define OCP_BOARD_ID_LEN 13
#define OCP_SERIAL_LEN 6
@ -248,6 +255,7 @@ struct ptp_ocp {
struct platform_device *spi_flash;
struct clk_hw *i2c_clk;
struct timer_list watchdog;
const struct ocp_attr_group *attr_tbl;
const struct ptp_ocp_eeprom_map *eeprom_map;
struct dentry *debug_root;
time64_t gnss_lost;
@ -265,6 +273,7 @@ struct ptp_ocp {
int flash_start;
u32 utc_tai_offset;
u32 ts_window_adjust;
u64 fw_cap;
struct ptp_ocp_sma_connector sma[4];
};
@ -290,6 +299,8 @@ static int ptp_ocp_fb_board_init(struct ptp_ocp *bp, struct ocp_resource *r);
static irqreturn_t ptp_ocp_ts_irq(int irq, void *priv);
static int ptp_ocp_ts_enable(void *priv, u32 req, bool enable);
static const struct ocp_attr_group fb_timecard_groups[];
struct ptp_ocp_eeprom_map {
u16 off;
u16 len;
@ -1526,6 +1537,8 @@ ptp_ocp_fb_board_init(struct ptp_ocp *bp, struct ocp_resource *r)
bp->flash_start = 1024 * 4096;
bp->eeprom_map = fb_eeprom_map;
bp->fw_version = ioread32(&bp->image->version);
bp->attr_tbl = fb_timecard_groups;
bp->fw_cap = OCP_CAP_BASIC;
ptp_ocp_tod_init(bp);
ptp_ocp_nmea_out_init(bp);
@ -2167,7 +2180,7 @@ tod_correction_store(struct device *dev, struct device_attribute *attr,
}
static DEVICE_ATTR_RW(tod_correction);
static struct attribute *timecard_attrs[] = {
static struct attribute *fb_timecard_attrs[] = {
&dev_attr_serialnum.attr,
&dev_attr_gnss_sync.attr,
&dev_attr_clock_source.attr,
@ -2186,7 +2199,13 @@ static struct attribute *timecard_attrs[] = {
&dev_attr_tod_correction.attr,
NULL,
};
ATTRIBUTE_GROUPS(timecard);
static const struct attribute_group fb_timecard_group = {
.attrs = fb_timecard_attrs,
};
static const struct ocp_attr_group fb_timecard_groups[] = {
{ .cap = OCP_CAP_BASIC, .group = &fb_timecard_group },
{ },
};
static void
gpio_input_map(char *buf, struct ptp_ocp *bp, u16 map[][2], u16 bit,
@ -2605,6 +2624,7 @@ ptp_ocp_complete(struct ptp_ocp *bp)
{
struct pps_device *pps;
char buf[32];
int i, err;
if (bp->gnss_port != -1) {
sprintf(buf, "ttyS%d", bp->gnss_port);
@ -2629,8 +2649,13 @@ ptp_ocp_complete(struct ptp_ocp *bp)
if (pps)
ptp_ocp_symlink(bp, pps->dev, "pps");
if (device_add_groups(&bp->dev, timecard_groups))
pr_err("device add groups failed\n");
for (i = 0; bp->attr_tbl[i].cap; i++) {
if (!(bp->attr_tbl[i].cap & bp->fw_cap))
continue;
err = sysfs_create_group(&bp->dev.kobj, bp->attr_tbl[i].group);
if (err)
return err;
}
ptp_ocp_debugfs_add_device(bp);
@ -2703,12 +2728,15 @@ static void
ptp_ocp_detach_sysfs(struct ptp_ocp *bp)
{
struct device *dev = &bp->dev;
int i;
sysfs_remove_link(&dev->kobj, "ttyGNSS");
sysfs_remove_link(&dev->kobj, "ttyMAC");
sysfs_remove_link(&dev->kobj, "ptp");
sysfs_remove_link(&dev->kobj, "pps");
device_remove_groups(dev, timecard_groups);
if (bp->attr_tbl)
for (i = 0; bp->attr_tbl[i].cap; i++)
sysfs_remove_group(&dev->kobj, bp->attr_tbl[i].group);
}
static void