counter: 104-quad-8: Support Differential Encoder Cable Status

The ACCES 104-QUAD-8 series provides status information about the
connection state of the differential encoder cable inputs. This patch
implements support to expose such information from these devices.

Signed-off-by: William Breathitt Gray <vilhelm.gray@gmail.com>
Signed-off-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
This commit is contained in:
William Breathitt Gray 2020-03-01 17:07:19 -05:00 committed by Jonathan Cameron
parent de65d05563
commit 954ab5cc5f
2 changed files with 93 additions and 0 deletions

View File

@ -1,3 +1,21 @@
What: /sys/bus/counter/devices/counterX/signalY/cable_fault
KernelVersion: 5.7
Contact: linux-iio@vger.kernel.org
Description:
Read-only attribute that indicates whether a differential
encoder cable fault (not connected or loose wires) is detected
for the respective channel of Signal Y. Valid attribute values
are boolean. Detection must first be enabled via the
corresponding cable_fault_enable attribute.
What: /sys/bus/counter/devices/counterX/signalY/cable_fault_enable
KernelVersion: 5.7
Contact: linux-iio@vger.kernel.org
Description:
Whether detection of differential encoder cable faults for the
respective channel of Signal Y is enabled. Valid attribute
values are boolean.
What: /sys/bus/counter/devices/counterX/signalY/filter_clock_prescaler
KernelVersion: 5.7
Contact: linux-iio@vger.kernel.org

View File

@ -31,6 +31,7 @@ MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
/**
* struct quad8_iio - IIO device private data structure
* @counter: instance of the counter_device
* @fck_prescaler: array of filter clock prescaler configurations
* @preset: array of preset values
* @count_mode: array of count mode configurations
* @quadrature_mode: array of quadrature mode configurations
@ -39,6 +40,7 @@ MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
* @preset_enable: array of set_to_preset_on_index attribute configurations
* @synchronous_mode: array of index function synchronous mode configurations
* @index_polarity: array of index function polarity configurations
* @cable_fault_enable: differential encoder cable status enable configurations
* @base: base port address of the IIO device
*/
struct quad8_iio {
@ -52,11 +54,13 @@ struct quad8_iio {
unsigned int preset_enable[QUAD8_NUM_COUNTERS];
unsigned int synchronous_mode[QUAD8_NUM_COUNTERS];
unsigned int index_polarity[QUAD8_NUM_COUNTERS];
unsigned int cable_fault_enable;
unsigned int base;
};
#define QUAD8_REG_CHAN_OP 0x11
#define QUAD8_REG_INDEX_INPUT_LEVELS 0x16
#define QUAD8_DIFF_ENCODER_CABLE_STATUS 0x17
/* Borrow Toggle flip-flop */
#define QUAD8_FLAG_BT BIT(0)
/* Carry Toggle flip-flop */
@ -1143,6 +1147,66 @@ static ssize_t quad8_count_preset_enable_write(struct counter_device *counter,
return len;
}
static ssize_t quad8_signal_cable_fault_read(struct counter_device *counter,
struct counter_signal *signal,
void *private, char *buf)
{
const struct quad8_iio *const priv = counter->priv;
const size_t channel_id = signal->id / 2;
const bool disabled = !(priv->cable_fault_enable & BIT(channel_id));
unsigned int status;
unsigned int fault;
if (disabled)
return -EINVAL;
/* Logic 0 = cable fault */
status = inb(priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
/* Mask respective channel and invert logic */
fault = !(status & BIT(channel_id));
return sprintf(buf, "%u\n", fault);
}
static ssize_t quad8_signal_cable_fault_enable_read(
struct counter_device *counter, struct counter_signal *signal,
void *private, char *buf)
{
const struct quad8_iio *const priv = counter->priv;
const size_t channel_id = signal->id / 2;
const unsigned int enb = !!(priv->cable_fault_enable & BIT(channel_id));
return sprintf(buf, "%u\n", enb);
}
static ssize_t quad8_signal_cable_fault_enable_write(
struct counter_device *counter, struct counter_signal *signal,
void *private, const char *buf, size_t len)
{
struct quad8_iio *const priv = counter->priv;
const size_t channel_id = signal->id / 2;
bool enable;
int ret;
unsigned int cable_fault_enable;
ret = kstrtobool(buf, &enable);
if (ret)
return ret;
if (enable)
priv->cable_fault_enable |= BIT(channel_id);
else
priv->cable_fault_enable &= ~BIT(channel_id);
/* Enable is active low in Differential Encoder Cable Status register */
cable_fault_enable = ~priv->cable_fault_enable;
outb(cable_fault_enable, priv->base + QUAD8_DIFF_ENCODER_CABLE_STATUS);
return len;
}
static ssize_t quad8_signal_fck_prescaler_read(struct counter_device *counter,
struct counter_signal *signal, void *private, char *buf)
{
@ -1180,6 +1244,15 @@ static ssize_t quad8_signal_fck_prescaler_write(struct counter_device *counter,
}
static const struct counter_signal_ext quad8_signal_ext[] = {
{
.name = "cable_fault",
.read = quad8_signal_cable_fault_read
},
{
.name = "cable_fault_enable",
.read = quad8_signal_cable_fault_enable_read,
.write = quad8_signal_cable_fault_enable_write
},
{
.name = "filter_clock_prescaler",
.read = quad8_signal_fck_prescaler_read,
@ -1383,6 +1456,8 @@ static int quad8_probe(struct device *dev, unsigned int id)
/* Disable index function; negative index polarity */
outb(QUAD8_CTR_IDR, base_offset + 1);
}
/* Disable Differential Encoder Cable Status for all channels */
outb(0xFF, base[id] + QUAD8_DIFF_ENCODER_CABLE_STATUS);
/* Enable all counters */
outb(QUAD8_CHAN_OP_ENABLE_COUNTERS, base[id] + QUAD8_REG_CHAN_OP);