@@ -218,6 +218,12 @@ 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 +254,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 +272,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 +298,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 +1536,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 +2179,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 +2198,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 +2623,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 +2648,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 +2727,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
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> --- drivers/ptp/ptp_ocp.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-)