Commit 9b13ff43 authored by Robert Hancock's avatar Robert Hancock Committed by Stephen Boyd

clk: si5341: Add sysfs properties to allow checking/resetting device faults

Add sysfs property files to allow viewing the current and latched states of
the input present and PLL lock bits, and allow resetting the latched fault
state. This allows manual checks or automated userspace polling for faults
occurring after initialization.
Signed-off-by: default avatarRobert Hancock <robert.hancock@calian.com>
Link: https://lore.kernel.org/r/20210325192643.2190069-10-robert.hancock@calian.comSigned-off-by: default avatarStephen Boyd <sboyd@kernel.org>
parent 2f02c5e4
......@@ -1457,6 +1457,94 @@ static int si5341_clk_select_active_input(struct clk_si5341 *data)
return res;
}
static ssize_t input_present_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct clk_si5341 *data = dev_get_drvdata(dev);
u32 status;
int res = regmap_read(data->regmap, SI5341_STATUS, &status);
if (res < 0)
return res;
res = !(status & SI5341_STATUS_LOSREF);
return snprintf(buf, PAGE_SIZE, "%d\n", res);
}
static DEVICE_ATTR_RO(input_present);
static ssize_t input_present_sticky_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct clk_si5341 *data = dev_get_drvdata(dev);
u32 status;
int res = regmap_read(data->regmap, SI5341_STATUS_STICKY, &status);
if (res < 0)
return res;
res = !(status & SI5341_STATUS_LOSREF);
return snprintf(buf, PAGE_SIZE, "%d\n", res);
}
static DEVICE_ATTR_RO(input_present_sticky);
static ssize_t pll_locked_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct clk_si5341 *data = dev_get_drvdata(dev);
u32 status;
int res = regmap_read(data->regmap, SI5341_STATUS, &status);
if (res < 0)
return res;
res = !(status & SI5341_STATUS_LOL);
return snprintf(buf, PAGE_SIZE, "%d\n", res);
}
static DEVICE_ATTR_RO(pll_locked);
static ssize_t pll_locked_sticky_show(struct device *dev,
struct device_attribute *attr,
char *buf)
{
struct clk_si5341 *data = dev_get_drvdata(dev);
u32 status;
int res = regmap_read(data->regmap, SI5341_STATUS_STICKY, &status);
if (res < 0)
return res;
res = !(status & SI5341_STATUS_LOL);
return snprintf(buf, PAGE_SIZE, "%d\n", res);
}
static DEVICE_ATTR_RO(pll_locked_sticky);
static ssize_t clear_sticky_store(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
struct clk_si5341 *data = dev_get_drvdata(dev);
long val;
if (kstrtol(buf, 10, &val))
return -EINVAL;
if (val) {
int res = regmap_write(data->regmap, SI5341_STATUS_STICKY, 0);
if (res < 0)
return res;
}
return count;
}
static DEVICE_ATTR_WO(clear_sticky);
static const struct attribute *si5341_attributes[] = {
&dev_attr_input_present.attr,
&dev_attr_input_present_sticky.attr,
&dev_attr_pll_locked.attr,
&dev_attr_pll_locked_sticky.attr,
&dev_attr_clear_sticky.attr,
NULL
};
static int si5341_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
......@@ -1687,6 +1775,12 @@ static int si5341_probe(struct i2c_client *client,
goto cleanup;
}
err = sysfs_create_files(&client->dev.kobj, si5341_attributes);
if (err) {
dev_err(&client->dev, "unable to create sysfs files\n");
goto cleanup;
}
/* Free the names, clk framework makes copies */
for (i = 0; i < data->num_synth; ++i)
devm_kfree(&client->dev, (void *)synth_clock_names[i]);
......@@ -1706,6 +1800,8 @@ static int si5341_remove(struct i2c_client *client)
struct clk_si5341 *data = i2c_get_clientdata(client);
int i;
sysfs_remove_files(&client->dev.kobj, si5341_attributes);
for (i = 0; i < SI5341_MAX_NUM_OUTPUTS; ++i) {
if (data->clk[i].vddo_reg)
regulator_disable(data->clk[i].vddo_reg);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment