Commit ee6439aa authored by Vadim Fedorenko's avatar Vadim Fedorenko Committed by David S. Miller
Browse files

ptp: ocp: expose config and temperature for ART card



Orolia card has disciplining configuration and temperature table
stored in EEPROM. This patch exposes them as binary attributes to
have read and write access.

Acked-by: default avatarJonathan Lemon <jonathan.lemon@gmail.com>
Co-developed-by: default avatarCharles Parent <charles.parent@orolia2s.com>
Signed-off-by: default avatarJonathan Lemon <jonathan.lemon@gmail.com>
Signed-off-by: default avatarVadim Fedorenko <vadfed@fb.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 9c44a7ac
Loading
Loading
Loading
Loading
+136 −0
Original line number Diff line number Diff line
@@ -690,6 +690,9 @@ static struct ocp_resource ocp_fb_resource[] = {
	{ }
};

#define OCP_ART_CONFIG_SIZE		144
#define OCP_ART_TEMP_TABLE_SIZE		368

struct ocp_art_gpio_reg {
	struct {
		u32	gpio;
@@ -3334,6 +3337,130 @@ DEVICE_FREQ_GROUP(freq2, 1);
DEVICE_FREQ_GROUP(freq3, 2);
DEVICE_FREQ_GROUP(freq4, 3);

static ssize_t
disciplining_config_read(struct file *filp, struct kobject *kobj,
			 struct bin_attribute *bin_attr, char *buf,
			 loff_t off, size_t count)
{
	struct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj));
	size_t size = OCP_ART_CONFIG_SIZE;
	struct nvmem_device *nvmem;
	ssize_t err;

	nvmem = ptp_ocp_nvmem_device_get(bp, NULL);
	if (IS_ERR(nvmem))
		return PTR_ERR(nvmem);

	if (off > size) {
		err = 0;
		goto out;
	}

	if (off + count > size)
		count = size - off;

	// the configuration is in the very beginning of the EEPROM
	err = nvmem_device_read(nvmem, off, count, buf);
	if (err != count) {
		err = -EFAULT;
		goto out;
	}

out:
	ptp_ocp_nvmem_device_put(&nvmem);

	return err;
}

static ssize_t
disciplining_config_write(struct file *filp, struct kobject *kobj,
			  struct bin_attribute *bin_attr, char *buf,
			  loff_t off, size_t count)
{
	struct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj));
	struct nvmem_device *nvmem;
	ssize_t err;

	/* Allow write of the whole area only */
	if (off || count != OCP_ART_CONFIG_SIZE)
		return -EFAULT;

	nvmem = ptp_ocp_nvmem_device_get(bp, NULL);
	if (IS_ERR(nvmem))
		return PTR_ERR(nvmem);

	err = nvmem_device_write(nvmem, 0x00, count, buf);
	if (err != count)
		err = -EFAULT;

	ptp_ocp_nvmem_device_put(&nvmem);

	return err;
}
static BIN_ATTR_RW(disciplining_config, OCP_ART_CONFIG_SIZE);

static ssize_t
temperature_table_read(struct file *filp, struct kobject *kobj,
		       struct bin_attribute *bin_attr, char *buf,
		       loff_t off, size_t count)
{
	struct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj));
	size_t size = OCP_ART_TEMP_TABLE_SIZE;
	struct nvmem_device *nvmem;
	ssize_t err;

	nvmem = ptp_ocp_nvmem_device_get(bp, NULL);
	if (IS_ERR(nvmem))
		return PTR_ERR(nvmem);

	if (off > size) {
		err = 0;
		goto out;
	}

	if (off + count > size)
		count = size - off;

	// the configuration is in the very beginning of the EEPROM
	err = nvmem_device_read(nvmem, 0x90 + off, count, buf);
	if (err != count) {
		err = -EFAULT;
		goto out;
	}

out:
	ptp_ocp_nvmem_device_put(&nvmem);

	return err;
}

static ssize_t
temperature_table_write(struct file *filp, struct kobject *kobj,
			struct bin_attribute *bin_attr, char *buf,
			loff_t off, size_t count)
{
	struct ptp_ocp *bp = dev_get_drvdata(kobj_to_dev(kobj));
	struct nvmem_device *nvmem;
	ssize_t err;

	/* Allow write of the whole area only */
	if (off || count != OCP_ART_TEMP_TABLE_SIZE)
		return -EFAULT;

	nvmem = ptp_ocp_nvmem_device_get(bp, NULL);
	if (IS_ERR(nvmem))
		return PTR_ERR(nvmem);

	err = nvmem_device_write(nvmem, 0x90, count, buf);
	if (err != count)
		err = -EFAULT;

	ptp_ocp_nvmem_device_put(&nvmem);

	return err;
}
static BIN_ATTR_RW(temperature_table, OCP_ART_TEMP_TABLE_SIZE);

static struct attribute *fb_timecard_attrs[] = {
	&dev_attr_serialnum.attr,
	&dev_attr_gnss_sync.attr,
@@ -3353,9 +3480,11 @@ static struct attribute *fb_timecard_attrs[] = {
	&dev_attr_tod_correction.attr,
	NULL,
};

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 },
	{ .cap = OCP_CAP_SIGNAL,    .group = &fb_timecard_signal0_group },
@@ -3384,8 +3513,15 @@ static struct attribute *art_timecard_attrs[] = {
	NULL,
};

static struct bin_attribute *bin_art_timecard_attrs[] = {
	&bin_attr_disciplining_config,
	&bin_attr_temperature_table,
	NULL,
};

static const struct attribute_group art_timecard_group = {
	.attrs = art_timecard_attrs,
	.bin_attrs = bin_art_timecard_attrs,
};

static const struct ocp_attr_group art_timecard_groups[] = {