mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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:
		
							parent
							
								
									de65d05563
								
							
						
					
					
						commit
						954ab5cc5f
					
				
					 2 changed files with 93 additions and 0 deletions
				
			
		| 
						 | 
					@ -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
 | 
					What:		/sys/bus/counter/devices/counterX/signalY/filter_clock_prescaler
 | 
				
			||||||
KernelVersion:	5.7
 | 
					KernelVersion:	5.7
 | 
				
			||||||
Contact:	linux-iio@vger.kernel.org
 | 
					Contact:	linux-iio@vger.kernel.org
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -31,6 +31,7 @@ MODULE_PARM_DESC(base, "ACCES 104-QUAD-8 base addresses");
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * struct quad8_iio - IIO device private data structure
 | 
					 * struct quad8_iio - IIO device private data structure
 | 
				
			||||||
 * @counter:		instance of the counter_device
 | 
					 * @counter:		instance of the counter_device
 | 
				
			||||||
 | 
					 * @fck_prescaler:	array of filter clock prescaler configurations
 | 
				
			||||||
 * @preset:		array of preset values
 | 
					 * @preset:		array of preset values
 | 
				
			||||||
 * @count_mode:		array of count mode configurations
 | 
					 * @count_mode:		array of count mode configurations
 | 
				
			||||||
 * @quadrature_mode:	array of quadrature 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
 | 
					 * @preset_enable:	array of set_to_preset_on_index attribute configurations
 | 
				
			||||||
 * @synchronous_mode:	array of index function synchronous mode configurations
 | 
					 * @synchronous_mode:	array of index function synchronous mode configurations
 | 
				
			||||||
 * @index_polarity:	array of index function polarity 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
 | 
					 * @base:		base port address of the IIO device
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct quad8_iio {
 | 
					struct quad8_iio {
 | 
				
			||||||
| 
						 | 
					@ -52,11 +54,13 @@ struct quad8_iio {
 | 
				
			||||||
	unsigned int preset_enable[QUAD8_NUM_COUNTERS];
 | 
						unsigned int preset_enable[QUAD8_NUM_COUNTERS];
 | 
				
			||||||
	unsigned int synchronous_mode[QUAD8_NUM_COUNTERS];
 | 
						unsigned int synchronous_mode[QUAD8_NUM_COUNTERS];
 | 
				
			||||||
	unsigned int index_polarity[QUAD8_NUM_COUNTERS];
 | 
						unsigned int index_polarity[QUAD8_NUM_COUNTERS];
 | 
				
			||||||
 | 
						unsigned int cable_fault_enable;
 | 
				
			||||||
	unsigned int base;
 | 
						unsigned int base;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define QUAD8_REG_CHAN_OP 0x11
 | 
					#define QUAD8_REG_CHAN_OP 0x11
 | 
				
			||||||
#define QUAD8_REG_INDEX_INPUT_LEVELS 0x16
 | 
					#define QUAD8_REG_INDEX_INPUT_LEVELS 0x16
 | 
				
			||||||
 | 
					#define QUAD8_DIFF_ENCODER_CABLE_STATUS 0x17
 | 
				
			||||||
/* Borrow Toggle flip-flop */
 | 
					/* Borrow Toggle flip-flop */
 | 
				
			||||||
#define QUAD8_FLAG_BT BIT(0)
 | 
					#define QUAD8_FLAG_BT BIT(0)
 | 
				
			||||||
/* Carry Toggle flip-flop */
 | 
					/* Carry Toggle flip-flop */
 | 
				
			||||||
| 
						 | 
					@ -1143,6 +1147,66 @@ static ssize_t quad8_count_preset_enable_write(struct counter_device *counter,
 | 
				
			||||||
	return len;
 | 
						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,
 | 
					static ssize_t quad8_signal_fck_prescaler_read(struct counter_device *counter,
 | 
				
			||||||
	struct counter_signal *signal, void *private, char *buf)
 | 
						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[] = {
 | 
					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",
 | 
							.name = "filter_clock_prescaler",
 | 
				
			||||||
		.read = quad8_signal_fck_prescaler_read,
 | 
							.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 */
 | 
							/* Disable index function; negative index polarity */
 | 
				
			||||||
		outb(QUAD8_CTR_IDR, base_offset + 1);
 | 
							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 */
 | 
						/* Enable all counters */
 | 
				
			||||||
	outb(QUAD8_CHAN_OP_ENABLE_COUNTERS, base[id] + QUAD8_REG_CHAN_OP);
 | 
						outb(QUAD8_CHAN_OP_ENABLE_COUNTERS, base[id] + QUAD8_REG_CHAN_OP);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue