counter.h 15.2 KB
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454
/* SPDX-License-Identifier: GPL-2.0 */
/*
 * Counter interface
 * Copyright (C) 2018 William Breathitt Gray
 */
#ifndef _COUNTER_H_
#define _COUNTER_H_

#include <linux/counter_enum.h>
#include <linux/device.h>
#include <linux/types.h>

enum counter_count_direction {
	COUNTER_COUNT_DIRECTION_FORWARD = 0,
	COUNTER_COUNT_DIRECTION_BACKWARD
};
extern const char *const counter_count_direction_str[2];

enum counter_count_mode {
	COUNTER_COUNT_MODE_NORMAL = 0,
	COUNTER_COUNT_MODE_RANGE_LIMIT,
	COUNTER_COUNT_MODE_NON_RECYCLE,
	COUNTER_COUNT_MODE_MODULO_N
};
extern const char *const counter_count_mode_str[4];

struct counter_device;
struct counter_signal;

/**
 * struct counter_signal_ext - Counter Signal extensions
 * @name:	attribute name
 * @read:	read callback for this attribute; may be NULL
 * @write:	write callback for this attribute; may be NULL
 * @priv:	data private to the driver
 */
struct counter_signal_ext {
	const char *name;
	ssize_t (*read)(struct counter_device *counter,
			struct counter_signal *signal, void *priv, char *buf);
	ssize_t (*write)(struct counter_device *counter,
			 struct counter_signal *signal, void *priv,
			 const char *buf, size_t len);
	void *priv;
};

/**
 * struct counter_signal - Counter Signal node
 * @id:		unique ID used to identify signal
 * @name:	device-specific Signal name; ideally, this should match the name
 *		as it appears in the datasheet documentation
 * @ext:	optional array of Counter Signal extensions
 * @num_ext:	number of Counter Signal extensions specified in @ext
 * @priv:	optional private data supplied by driver
 */
struct counter_signal {
	int id;
	const char *name;

	const struct counter_signal_ext *ext;
	size_t num_ext;

	void *priv;
};

/**
 * struct counter_signal_enum_ext - Signal enum extension attribute
 * @items:	Array of strings
 * @num_items:	Number of items specified in @items
 * @set:	Set callback function; may be NULL
 * @get:	Get callback function; may be NULL
 *
 * The counter_signal_enum_ext structure can be used to implement enum style
 * Signal extension attributes. Enum style attributes are those which have a set
 * of strings that map to unsigned integer values. The Generic Counter Signal
 * enum extension helper code takes care of mapping between value and string, as
 * well as generating a "_available" file which contains a list of all available
 * items. The get callback is used to query the currently active item; the index
 * of the item within the respective items array is returned via the 'item'
 * parameter. The set callback is called when the attribute is updated; the
 * 'item' parameter contains the index of the newly activated item within the
 * respective items array.
 */
struct counter_signal_enum_ext {
	const char * const *items;
	size_t num_items;
	int (*get)(struct counter_device *counter,
		   struct counter_signal *signal, size_t *item);
	int (*set)(struct counter_device *counter,
		   struct counter_signal *signal, size_t item);
};

/**
 * COUNTER_SIGNAL_ENUM() - Initialize Signal enum extension
 * @_name:	Attribute name
 * @_e:		Pointer to a counter_signal_enum_ext structure
 *
 * This should usually be used together with COUNTER_SIGNAL_ENUM_AVAILABLE()
 */
#define COUNTER_SIGNAL_ENUM(_name, _e) \
{ \
	.name = (_name), \
	.read = counter_signal_enum_read, \
	.write = counter_signal_enum_write, \
	.priv = (_e) \
}

/**
 * COUNTER_SIGNAL_ENUM_AVAILABLE() - Initialize Signal enum available extension
 * @_name:	Attribute name ("_available" will be appended to the name)
 * @_e:		Pointer to a counter_signal_enum_ext structure
 *
 * Creates a read only attribute that lists all the available enum items in a
 * newline separated list. This should usually be used together with
 * COUNTER_SIGNAL_ENUM()
 */
#define COUNTER_SIGNAL_ENUM_AVAILABLE(_name, _e) \
{ \
	.name = (_name "_available"), \
	.read = counter_signal_enum_available_read, \
	.priv = (_e) \
}

enum counter_synapse_action {
	COUNTER_SYNAPSE_ACTION_NONE = 0,
	COUNTER_SYNAPSE_ACTION_RISING_EDGE,
	COUNTER_SYNAPSE_ACTION_FALLING_EDGE,
	COUNTER_SYNAPSE_ACTION_BOTH_EDGES
};

/**
 * struct counter_synapse - Counter Synapse node
 * @action:		index of current action mode
 * @actions_list:	array of available action modes
 * @num_actions:	number of action modes specified in @actions_list
 * @signal:		pointer to associated signal
 */
struct counter_synapse {
	size_t action;
	const enum counter_synapse_action *actions_list;
	size_t num_actions;

	struct counter_signal *signal;
};

struct counter_count;

/**
 * struct counter_count_ext - Counter Count extension
 * @name:	attribute name
 * @read:	read callback for this attribute; may be NULL
 * @write:	write callback for this attribute; may be NULL
 * @priv:	data private to the driver
 */
struct counter_count_ext {
	const char *name;
	ssize_t (*read)(struct counter_device *counter,
			struct counter_count *count, void *priv, char *buf);
	ssize_t (*write)(struct counter_device *counter,
			 struct counter_count *count, void *priv,
			 const char *buf, size_t len);
	void *priv;
};

enum counter_count_function {
	COUNTER_COUNT_FUNCTION_INCREASE = 0,
	COUNTER_COUNT_FUNCTION_DECREASE,
	COUNTER_COUNT_FUNCTION_PULSE_DIRECTION,
	COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A,
	COUNTER_COUNT_FUNCTION_QUADRATURE_X1_B,
	COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A,
	COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B,
	COUNTER_COUNT_FUNCTION_QUADRATURE_X4
};

/**
 * struct counter_count - Counter Count node
 * @id:			unique ID used to identify Count
 * @name:		device-specific Count name; ideally, this should match
 *			the name as it appears in the datasheet documentation
 * @function:		index of current function mode
 * @functions_list:	array available function modes
 * @num_functions:	number of function modes specified in @functions_list
 * @synapses:		array of synapses for initialization
 * @num_synapses:	number of synapses specified in @synapses
 * @ext:		optional array of Counter Count extensions
 * @num_ext:		number of Counter Count extensions specified in @ext
 * @priv:		optional private data supplied by driver
 */
struct counter_count {
	int id;
	const char *name;

	size_t function;
	const enum counter_count_function *functions_list;
	size_t num_functions;

	struct counter_synapse *synapses;
	size_t num_synapses;

	const struct counter_count_ext *ext;
	size_t num_ext;

	void *priv;
};

/**
 * struct counter_count_enum_ext - Count enum extension attribute
 * @items:	Array of strings
 * @num_items:	Number of items specified in @items
 * @set:	Set callback function; may be NULL
 * @get:	Get callback function; may be NULL
 *
 * The counter_count_enum_ext structure can be used to implement enum style
 * Count extension attributes. Enum style attributes are those which have a set
 * of strings that map to unsigned integer values. The Generic Counter Count
 * enum extension helper code takes care of mapping between value and string, as
 * well as generating a "_available" file which contains a list of all available
 * items. The get callback is used to query the currently active item; the index
 * of the item within the respective items array is returned via the 'item'
 * parameter. The set callback is called when the attribute is updated; the
 * 'item' parameter contains the index of the newly activated item within the
 * respective items array.
 */
struct counter_count_enum_ext {
	const char * const *items;
	size_t num_items;
	int (*get)(struct counter_device *counter, struct counter_count *count,
		   size_t *item);
	int (*set)(struct counter_device *counter, struct counter_count *count,
		   size_t item);
};

/**
 * COUNTER_COUNT_ENUM() - Initialize Count enum extension
 * @_name:	Attribute name
 * @_e:		Pointer to a counter_count_enum_ext structure
 *
 * This should usually be used together with COUNTER_COUNT_ENUM_AVAILABLE()
 */
#define COUNTER_COUNT_ENUM(_name, _e) \
{ \
	.name = (_name), \
	.read = counter_count_enum_read, \
	.write = counter_count_enum_write, \
	.priv = (_e) \
}

/**
 * COUNTER_COUNT_ENUM_AVAILABLE() - Initialize Count enum available extension
 * @_name:	Attribute name ("_available" will be appended to the name)
 * @_e:		Pointer to a counter_count_enum_ext structure
 *
 * Creates a read only attribute that lists all the available enum items in a
 * newline separated list. This should usually be used together with
 * COUNTER_COUNT_ENUM()
 */
#define COUNTER_COUNT_ENUM_AVAILABLE(_name, _e) \
{ \
	.name = (_name "_available"), \
	.read = counter_count_enum_available_read, \
	.priv = (_e) \
}

/**
 * struct counter_device_attr_group - internal container for attribute group
 * @attr_group:	Counter sysfs attributes group
 * @attr_list:	list to keep track of created Counter sysfs attributes
 * @num_attr:	number of Counter sysfs attributes
 */
struct counter_device_attr_group {
	struct attribute_group attr_group;
	struct list_head attr_list;
	size_t num_attr;
};

/**
 * struct counter_device_state - internal state container for a Counter device
 * @id:			unique ID used to identify the Counter
 * @dev:		internal device structure
 * @groups_list:	attribute groups list (for Signals, Counts, and ext)
 * @num_groups:		number of attribute groups containers
 * @groups:		Counter sysfs attribute groups (to populate @dev.groups)
 */
struct counter_device_state {
	int id;
	struct device dev;
	struct counter_device_attr_group *groups_list;
	size_t num_groups;
	const struct attribute_group **groups;
};

enum counter_signal_value {
	COUNTER_SIGNAL_LOW = 0,
	COUNTER_SIGNAL_HIGH
};

/**
 * struct counter_ops - Callbacks from driver
 * @signal_read:	optional read callback for Signal attribute. The read
 *			value of the respective Signal should be passed back via
 *			the val parameter.
 * @count_read:		optional read callback for Count attribute. The read
 *			value of the respective Count should be passed back via
 *			the val parameter.
 * @count_write:	optional write callback for Count attribute. The write
 *			value for the respective Count is passed in via the val
 *			parameter.
 * @function_get:	function to get the current count function mode. Returns
 *			0 on success and negative error code on error. The index
 *			of the respective Count's returned function mode should
 *			be passed back via the function parameter.
 * @function_set:	function to set the count function mode. function is the
 *			index of the requested function mode from the respective
 *			Count's functions_list array.
 * @action_get:		function to get the current action mode. Returns 0 on
 *			success and negative error code on error. The index of
 *			the respective Synapse's returned action mode should be
 *			passed back via the action parameter.
 * @action_set:		function to set the action mode. action is the index of
 *			the requested action mode from the respective Synapse's
 *			actions_list array.
 */
struct counter_ops {
	int (*signal_read)(struct counter_device *counter,
			   struct counter_signal *signal,
			   enum counter_signal_value *val);
	int (*count_read)(struct counter_device *counter,
			  struct counter_count *count, unsigned long *val);
	int (*count_write)(struct counter_device *counter,
			   struct counter_count *count, unsigned long val);
	int (*function_get)(struct counter_device *counter,
			    struct counter_count *count, size_t *function);
	int (*function_set)(struct counter_device *counter,
			    struct counter_count *count, size_t function);
	int (*action_get)(struct counter_device *counter,
			  struct counter_count *count,
			  struct counter_synapse *synapse, size_t *action);
	int (*action_set)(struct counter_device *counter,
			  struct counter_count *count,
			  struct counter_synapse *synapse, size_t action);
};

/**
 * struct counter_device_ext - Counter device extension
 * @name:	attribute name
 * @read:	read callback for this attribute; may be NULL
 * @write:	write callback for this attribute; may be NULL
 * @priv:	data private to the driver
 */
struct counter_device_ext {
	const char *name;
	ssize_t (*read)(struct counter_device *counter, void *priv, char *buf);
	ssize_t (*write)(struct counter_device *counter, void *priv,
			 const char *buf, size_t len);
	void *priv;
};

/**
 * struct counter_device_enum_ext - Counter enum extension attribute
 * @items:	Array of strings
 * @num_items:	Number of items specified in @items
 * @set:	Set callback function; may be NULL
 * @get:	Get callback function; may be NULL
 *
 * The counter_device_enum_ext structure can be used to implement enum style
 * Counter extension attributes. Enum style attributes are those which have a
 * set of strings that map to unsigned integer values. The Generic Counter enum
 * extension helper code takes care of mapping between value and string, as well
 * as generating a "_available" file which contains a list of all available
 * items. The get callback is used to query the currently active item; the index
 * of the item within the respective items array is returned via the 'item'
 * parameter. The set callback is called when the attribute is updated; the
 * 'item' parameter contains the index of the newly activated item within the
 * respective items array.
 */
struct counter_device_enum_ext {
	const char * const *items;
	size_t num_items;
	int (*get)(struct counter_device *counter, size_t *item);
	int (*set)(struct counter_device *counter, size_t item);
};

/**
 * COUNTER_DEVICE_ENUM() - Initialize Counter enum extension
 * @_name:	Attribute name
 * @_e:		Pointer to a counter_device_enum_ext structure
 *
 * This should usually be used together with COUNTER_DEVICE_ENUM_AVAILABLE()
 */
#define COUNTER_DEVICE_ENUM(_name, _e) \
{ \
	.name = (_name), \
	.read = counter_device_enum_read, \
	.write = counter_device_enum_write, \
	.priv = (_e) \
}

/**
 * COUNTER_DEVICE_ENUM_AVAILABLE() - Initialize Counter enum available extension
 * @_name:	Attribute name ("_available" will be appended to the name)
 * @_e:		Pointer to a counter_device_enum_ext structure
 *
 * Creates a read only attribute that lists all the available enum items in a
 * newline separated list. This should usually be used together with
 * COUNTER_DEVICE_ENUM()
 */
#define COUNTER_DEVICE_ENUM_AVAILABLE(_name, _e) \
{ \
	.name = (_name "_available"), \
	.read = counter_device_enum_available_read, \
	.priv = (_e) \
}

/**
 * struct counter_device - Counter data structure
 * @name:		name of the device as it appears in the datasheet
 * @parent:		optional parent device providing the counters
 * @device_state:	internal device state container
 * @ops:		callbacks from driver
 * @signals:		array of Signals
 * @num_signals:	number of Signals specified in @signals
 * @counts:		array of Counts
 * @num_counts:		number of Counts specified in @counts
 * @ext:		optional array of Counter device extensions
 * @num_ext:		number of Counter device extensions specified in @ext
 * @priv:		optional private data supplied by driver
 */
struct counter_device {
	const char *name;
	struct device *parent;
	struct counter_device_state *device_state;

	const struct counter_ops *ops;

	struct counter_signal *signals;
	size_t num_signals;
	struct counter_count *counts;
	size_t num_counts;

	const struct counter_device_ext *ext;
	size_t num_ext;

	void *priv;
};

int counter_register(struct counter_device *const counter);
void counter_unregister(struct counter_device *const counter);
int devm_counter_register(struct device *dev,
			  struct counter_device *const counter);
void devm_counter_unregister(struct device *dev,
			     struct counter_device *const counter);

#endif /* _COUNTER_H_ */