diff options
author | Jonathan Lemon <jonathan.lemon@gmail.com> | 2022-03-10 23:19:07 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2022-03-11 14:54:45 +0300 |
commit | c205d53c4923e4b32b4a2a2773618f08e176a250 (patch) | |
tree | cb8c842d2c78581efeb2ce9a50cd41920b3fb70b /drivers/ptp | |
parent | cd09193ffbf86026c490798a6db0f67a53bec333 (diff) | |
download | linux-c205d53c4923e4b32b4a2a2773618f08e176a250.tar.xz |
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>
Diffstat (limited to 'drivers/ptp')
-rw-r--r-- | drivers/ptp/ptp_ocp.c | 38 |
1 files changed, 33 insertions, 5 deletions
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c index 1a4a284749eb..0b43aaaf5286 100644 --- a/drivers/ptp/ptp_ocp.c +++ b/drivers/ptp/ptp_ocp.c @@ -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 |