Merge branch 'ptrp-ocp-next'
Jonathan Lemon says: ==================== ptp: ocp: update devlink information Both of these patches update the information displayed via devlink. v1 -> v2: remove board.manufacture information ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
ce7ec1b8ec
@ -11,12 +11,14 @@
|
||||
#include <linux/clkdev.h>
|
||||
#include <linux/clk-provider.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/platform_data/i2c-xiic.h>
|
||||
#include <linux/ptp_clock_kernel.h>
|
||||
#include <linux/spi/spi.h>
|
||||
#include <linux/spi/xilinx_spi.h>
|
||||
#include <net/devlink.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/mtd/mtd.h>
|
||||
#include <linux/nvmem-consumer.h>
|
||||
|
||||
#ifndef PCI_VENDOR_ID_FACEBOOK
|
||||
#define PCI_VENDOR_ID_FACEBOOK 0x1d9b
|
||||
@ -204,6 +206,9 @@ struct ptp_ocp_ext_src {
|
||||
int irq_vec;
|
||||
};
|
||||
|
||||
#define OCP_BOARD_ID_LEN 13
|
||||
#define OCP_SERIAL_LEN 6
|
||||
|
||||
struct ptp_ocp {
|
||||
struct pci_dev *pdev;
|
||||
struct device dev;
|
||||
@ -230,6 +235,7 @@ struct ptp_ocp {
|
||||
struct platform_device *spi_flash;
|
||||
struct clk_hw *i2c_clk;
|
||||
struct timer_list watchdog;
|
||||
const struct ptp_ocp_eeprom_map *eeprom_map;
|
||||
struct dentry *debug_root;
|
||||
time64_t gnss_lost;
|
||||
int id;
|
||||
@ -238,8 +244,10 @@ struct ptp_ocp {
|
||||
int gnss2_port;
|
||||
int mac_port; /* miniature atomic clock */
|
||||
int nmea_port;
|
||||
u8 serial[6];
|
||||
bool has_serial;
|
||||
u32 fw_version;
|
||||
u8 board_id[OCP_BOARD_ID_LEN];
|
||||
u8 serial[OCP_SERIAL_LEN];
|
||||
bool has_eeprom_data;
|
||||
u32 pps_req_map;
|
||||
int flash_start;
|
||||
u32 utc_tai_offset;
|
||||
@ -268,6 +276,28 @@ 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);
|
||||
|
||||
struct ptp_ocp_eeprom_map {
|
||||
u16 off;
|
||||
u16 len;
|
||||
u32 bp_offset;
|
||||
const void * const tag;
|
||||
};
|
||||
|
||||
#define EEPROM_ENTRY(addr, member) \
|
||||
.off = addr, \
|
||||
.len = sizeof_field(struct ptp_ocp, member), \
|
||||
.bp_offset = offsetof(struct ptp_ocp, member)
|
||||
|
||||
#define BP_MAP_ENTRY_ADDR(bp, map) ({ \
|
||||
(void *)((uintptr_t)(bp) + (map)->bp_offset); \
|
||||
})
|
||||
|
||||
static struct ptp_ocp_eeprom_map fb_eeprom_map[] = {
|
||||
{ EEPROM_ENTRY(0x43, board_id) },
|
||||
{ EEPROM_ENTRY(0x00, serial), .tag = "mac" },
|
||||
{ }
|
||||
};
|
||||
|
||||
#define bp_assign_entry(bp, res, val) ({ \
|
||||
uintptr_t addr = (uintptr_t)(bp) + (res)->bp_offset; \
|
||||
*(typeof(val) *)addr = val; \
|
||||
@ -396,6 +426,15 @@ static struct ocp_resource ocp_fb_resource[] = {
|
||||
.extra = &(struct ptp_ocp_i2c_info) {
|
||||
.name = "xiic-i2c",
|
||||
.fixed_rate = 50000000,
|
||||
.data_size = sizeof(struct xiic_i2c_platform_data),
|
||||
.data = &(struct xiic_i2c_platform_data) {
|
||||
.num_devices = 2,
|
||||
.devices = (struct i2c_board_info[]) {
|
||||
{ I2C_BOARD_INFO("24c02", 0x50) },
|
||||
{ I2C_BOARD_INFO("24mac402", 0x58),
|
||||
.platform_data = "mac" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -919,78 +958,88 @@ ptp_ocp_tod_gnss_name(int idx)
|
||||
return gnss_name[idx];
|
||||
}
|
||||
|
||||
static int
|
||||
ptp_ocp_firstchild(struct device *dev, void *data)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
struct ptp_ocp_nvmem_match_info {
|
||||
struct ptp_ocp *bp;
|
||||
const void * const tag;
|
||||
};
|
||||
|
||||
static int
|
||||
ptp_ocp_read_i2c(struct i2c_adapter *adap, u8 addr, u8 reg, u8 sz, u8 *data)
|
||||
ptp_ocp_nvmem_match(struct device *dev, const void *data)
|
||||
{
|
||||
struct i2c_msg msgs[2] = {
|
||||
{
|
||||
.addr = addr,
|
||||
.len = 1,
|
||||
.buf = ®,
|
||||
},
|
||||
{
|
||||
.addr = addr,
|
||||
.flags = I2C_M_RD,
|
||||
.len = 2,
|
||||
.buf = data,
|
||||
},
|
||||
};
|
||||
int err;
|
||||
u8 len;
|
||||
const struct ptp_ocp_nvmem_match_info *info = data;
|
||||
|
||||
/* xiic-i2c for some stupid reason only does 2 byte reads. */
|
||||
while (sz) {
|
||||
len = min_t(u8, sz, 2);
|
||||
msgs[1].len = len;
|
||||
err = i2c_transfer(adap, msgs, 2);
|
||||
if (err != msgs[1].len)
|
||||
return err;
|
||||
msgs[1].buf += len;
|
||||
reg += len;
|
||||
sz -= len;
|
||||
}
|
||||
dev = dev->parent;
|
||||
if (!i2c_verify_client(dev) || info->tag != dev->platform_data)
|
||||
return 0;
|
||||
|
||||
while ((dev = dev->parent))
|
||||
if (dev->driver && !strcmp(dev->driver->name, KBUILD_MODNAME))
|
||||
return info->bp == dev_get_drvdata(dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ptp_ocp_get_serial_number(struct ptp_ocp *bp)
|
||||
static inline struct nvmem_device *
|
||||
ptp_ocp_nvmem_device_get(struct ptp_ocp *bp, const void * const tag)
|
||||
{
|
||||
struct i2c_adapter *adap;
|
||||
struct device *dev;
|
||||
int err;
|
||||
struct ptp_ocp_nvmem_match_info info = { .bp = bp, .tag = tag };
|
||||
|
||||
return nvmem_device_find(&info, ptp_ocp_nvmem_match);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ptp_ocp_nvmem_device_put(struct nvmem_device **nvmemp)
|
||||
{
|
||||
if (*nvmemp != NULL) {
|
||||
nvmem_device_put(*nvmemp);
|
||||
*nvmemp = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ptp_ocp_read_eeprom(struct ptp_ocp *bp)
|
||||
{
|
||||
const struct ptp_ocp_eeprom_map *map;
|
||||
struct nvmem_device *nvmem;
|
||||
const void *tag;
|
||||
int ret;
|
||||
|
||||
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");
|
||||
return;
|
||||
tag = NULL;
|
||||
nvmem = NULL;
|
||||
|
||||
for (map = bp->eeprom_map; map->len; map++) {
|
||||
if (map->tag != tag) {
|
||||
tag = map->tag;
|
||||
ptp_ocp_nvmem_device_put(&nvmem);
|
||||
}
|
||||
if (!nvmem) {
|
||||
nvmem = ptp_ocp_nvmem_device_get(bp, tag);
|
||||
if (!nvmem)
|
||||
goto out;
|
||||
}
|
||||
ret = nvmem_device_read(nvmem, map->off, map->len,
|
||||
BP_MAP_ENTRY_ADDR(bp, map));
|
||||
if (ret != map->len)
|
||||
goto read_fail;
|
||||
}
|
||||
|
||||
adap = i2c_verify_adapter(dev);
|
||||
if (!adap) {
|
||||
dev_err(&bp->pdev->dev, "device '%s' isn't an I2C adapter\n",
|
||||
dev_name(dev));
|
||||
goto out;
|
||||
}
|
||||
|
||||
err = ptp_ocp_read_i2c(adap, 0x58, 0x9A, 6, bp->serial);
|
||||
if (err) {
|
||||
dev_err(&bp->pdev->dev, "could not read eeprom: %d\n", err);
|
||||
goto out;
|
||||
}
|
||||
|
||||
bp->has_serial = true;
|
||||
bp->has_eeprom_data = true;
|
||||
|
||||
out:
|
||||
put_device(dev);
|
||||
ptp_ocp_nvmem_device_put(&nvmem);
|
||||
return;
|
||||
|
||||
read_fail:
|
||||
dev_err(&bp->pdev->dev, "could not read eeprom: %d\n", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int
|
||||
ptp_ocp_firstchild(struct device *dev, void *data)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static struct device *
|
||||
@ -1091,33 +1140,32 @@ ptp_ocp_devlink_info_get(struct devlink *devlink, struct devlink_info_req *req,
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (bp->image) {
|
||||
u32 ver = ioread32(&bp->image->version);
|
||||
if (bp->fw_version & 0xffff) {
|
||||
sprintf(buf, "%d", bp->fw_version);
|
||||
err = devlink_info_version_running_put(req, "fw", buf);
|
||||
} else {
|
||||
sprintf(buf, "%d", bp->fw_version >> 16);
|
||||
err = devlink_info_version_running_put(req, "loader", buf);
|
||||
}
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (ver & 0xffff) {
|
||||
sprintf(buf, "%d", ver);
|
||||
err = devlink_info_version_running_put(req,
|
||||
"fw",
|
||||
buf);
|
||||
} else {
|
||||
sprintf(buf, "%d", ver >> 16);
|
||||
err = devlink_info_version_running_put(req,
|
||||
"loader",
|
||||
buf);
|
||||
}
|
||||
if (err)
|
||||
return err;
|
||||
if (!bp->has_eeprom_data) {
|
||||
ptp_ocp_read_eeprom(bp);
|
||||
if (!bp->has_eeprom_data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!bp->has_serial)
|
||||
ptp_ocp_get_serial_number(bp);
|
||||
sprintf(buf, "%pM", bp->serial);
|
||||
err = devlink_info_serial_number_put(req, buf);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
if (bp->has_serial) {
|
||||
sprintf(buf, "%pM", bp->serial);
|
||||
err = devlink_info_serial_number_put(req, buf);
|
||||
if (err)
|
||||
return err;
|
||||
}
|
||||
err = devlink_info_version_fixed_put(req,
|
||||
DEVLINK_INFO_VERSION_GENERIC_BOARD_ID,
|
||||
bp->board_id);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -1412,6 +1460,8 @@ static int
|
||||
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);
|
||||
|
||||
ptp_ocp_tod_init(bp);
|
||||
ptp_ocp_nmea_out_init(bp);
|
||||
@ -1810,8 +1860,8 @@ serialnum_show(struct device *dev, struct device_attribute *attr, char *buf)
|
||||
{
|
||||
struct ptp_ocp *bp = dev_get_drvdata(dev);
|
||||
|
||||
if (!bp->has_serial)
|
||||
ptp_ocp_get_serial_number(bp);
|
||||
if (!bp->has_eeprom_data)
|
||||
ptp_ocp_read_eeprom(bp);
|
||||
|
||||
return sysfs_emit(buf, "%pM\n", bp->serial);
|
||||
}
|
||||
@ -2520,17 +2570,14 @@ ptp_ocp_info(struct ptp_ocp *bp)
|
||||
|
||||
ptp_ocp_phc_info(bp);
|
||||
|
||||
if (bp->image) {
|
||||
u32 ver = ioread32(&bp->image->version);
|
||||
dev_info(dev, "version %x\n", bp->fw_version);
|
||||
if (bp->fw_version & 0xffff)
|
||||
dev_info(dev, "regular image, version %d\n",
|
||||
bp->fw_version & 0xffff);
|
||||
else
|
||||
dev_info(dev, "golden image, version %d\n",
|
||||
bp->fw_version >> 16);
|
||||
|
||||
dev_info(dev, "version %x\n", ver);
|
||||
if (ver & 0xffff)
|
||||
dev_info(dev, "regular image, version %d\n",
|
||||
ver & 0xffff);
|
||||
else
|
||||
dev_info(dev, "golden image, version %d\n",
|
||||
ver >> 16);
|
||||
}
|
||||
ptp_ocp_serial_info(dev, "GNSS", bp->gnss_port, 115200);
|
||||
ptp_ocp_serial_info(dev, "GNSS2", bp->gnss2_port, 115200);
|
||||
ptp_ocp_serial_info(dev, "MAC", bp->mac_port, 57600);
|
||||
|
Loading…
Reference in New Issue
Block a user