Linux Audio

Check our new training course

Loading...
v5.9
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Generic Counter interface
   4 * Copyright (C) 2018 William Breathitt Gray
   5 */
   6#include <linux/counter.h>
   7#include <linux/device.h>
   8#include <linux/err.h>
   9#include <linux/export.h>
  10#include <linux/fs.h>
  11#include <linux/gfp.h>
  12#include <linux/idr.h>
  13#include <linux/init.h>
  14#include <linux/kernel.h>
  15#include <linux/list.h>
  16#include <linux/module.h>
  17#include <linux/printk.h>
  18#include <linux/slab.h>
  19#include <linux/string.h>
  20#include <linux/sysfs.h>
  21#include <linux/types.h>
  22
  23const char *const counter_count_direction_str[2] = {
  24	[COUNTER_COUNT_DIRECTION_FORWARD] = "forward",
  25	[COUNTER_COUNT_DIRECTION_BACKWARD] = "backward"
  26};
  27EXPORT_SYMBOL_GPL(counter_count_direction_str);
  28
  29const char *const counter_count_mode_str[4] = {
  30	[COUNTER_COUNT_MODE_NORMAL] = "normal",
  31	[COUNTER_COUNT_MODE_RANGE_LIMIT] = "range limit",
  32	[COUNTER_COUNT_MODE_NON_RECYCLE] = "non-recycle",
  33	[COUNTER_COUNT_MODE_MODULO_N] = "modulo-n"
  34};
  35EXPORT_SYMBOL_GPL(counter_count_mode_str);
  36
  37ssize_t counter_signal_enum_read(struct counter_device *counter,
  38				 struct counter_signal *signal, void *priv,
  39				 char *buf)
  40{
  41	const struct counter_signal_enum_ext *const e = priv;
  42	int err;
  43	size_t index;
  44
  45	if (!e->get)
  46		return -EINVAL;
  47
  48	err = e->get(counter, signal, &index);
  49	if (err)
  50		return err;
  51
  52	if (index >= e->num_items)
  53		return -EINVAL;
  54
  55	return sprintf(buf, "%s\n", e->items[index]);
  56}
  57EXPORT_SYMBOL_GPL(counter_signal_enum_read);
  58
  59ssize_t counter_signal_enum_write(struct counter_device *counter,
  60				  struct counter_signal *signal, void *priv,
  61				  const char *buf, size_t len)
  62{
  63	const struct counter_signal_enum_ext *const e = priv;
  64	ssize_t index;
  65	int err;
  66
  67	if (!e->set)
  68		return -EINVAL;
  69
  70	index = __sysfs_match_string(e->items, e->num_items, buf);
  71	if (index < 0)
  72		return index;
  73
  74	err = e->set(counter, signal, index);
  75	if (err)
  76		return err;
  77
  78	return len;
  79}
  80EXPORT_SYMBOL_GPL(counter_signal_enum_write);
  81
  82ssize_t counter_signal_enum_available_read(struct counter_device *counter,
  83					   struct counter_signal *signal,
  84					   void *priv, char *buf)
  85{
  86	const struct counter_signal_enum_ext *const e = priv;
  87	size_t i;
  88	size_t len = 0;
  89
  90	if (!e->num_items)
  91		return 0;
  92
  93	for (i = 0; i < e->num_items; i++)
  94		len += sprintf(buf + len, "%s\n", e->items[i]);
  95
  96	return len;
  97}
  98EXPORT_SYMBOL_GPL(counter_signal_enum_available_read);
  99
 100ssize_t counter_count_enum_read(struct counter_device *counter,
 101				struct counter_count *count, void *priv,
 102				char *buf)
 103{
 104	const struct counter_count_enum_ext *const e = priv;
 105	int err;
 106	size_t index;
 107
 108	if (!e->get)
 109		return -EINVAL;
 110
 111	err = e->get(counter, count, &index);
 112	if (err)
 113		return err;
 114
 115	if (index >= e->num_items)
 116		return -EINVAL;
 117
 118	return sprintf(buf, "%s\n", e->items[index]);
 119}
 120EXPORT_SYMBOL_GPL(counter_count_enum_read);
 121
 122ssize_t counter_count_enum_write(struct counter_device *counter,
 123				 struct counter_count *count, void *priv,
 124				 const char *buf, size_t len)
 125{
 126	const struct counter_count_enum_ext *const e = priv;
 127	ssize_t index;
 128	int err;
 129
 130	if (!e->set)
 131		return -EINVAL;
 132
 133	index = __sysfs_match_string(e->items, e->num_items, buf);
 134	if (index < 0)
 135		return index;
 136
 137	err = e->set(counter, count, index);
 138	if (err)
 139		return err;
 140
 141	return len;
 142}
 143EXPORT_SYMBOL_GPL(counter_count_enum_write);
 144
 145ssize_t counter_count_enum_available_read(struct counter_device *counter,
 146					  struct counter_count *count,
 147					  void *priv, char *buf)
 148{
 149	const struct counter_count_enum_ext *const e = priv;
 150	size_t i;
 151	size_t len = 0;
 152
 153	if (!e->num_items)
 154		return 0;
 155
 156	for (i = 0; i < e->num_items; i++)
 157		len += sprintf(buf + len, "%s\n", e->items[i]);
 158
 159	return len;
 160}
 161EXPORT_SYMBOL_GPL(counter_count_enum_available_read);
 162
 163ssize_t counter_device_enum_read(struct counter_device *counter, void *priv,
 164				 char *buf)
 165{
 166	const struct counter_device_enum_ext *const e = priv;
 167	int err;
 168	size_t index;
 169
 170	if (!e->get)
 171		return -EINVAL;
 172
 173	err = e->get(counter, &index);
 174	if (err)
 175		return err;
 176
 177	if (index >= e->num_items)
 178		return -EINVAL;
 179
 180	return sprintf(buf, "%s\n", e->items[index]);
 181}
 182EXPORT_SYMBOL_GPL(counter_device_enum_read);
 183
 184ssize_t counter_device_enum_write(struct counter_device *counter, void *priv,
 185				  const char *buf, size_t len)
 186{
 187	const struct counter_device_enum_ext *const e = priv;
 188	ssize_t index;
 189	int err;
 190
 191	if (!e->set)
 192		return -EINVAL;
 193
 194	index = __sysfs_match_string(e->items, e->num_items, buf);
 195	if (index < 0)
 196		return index;
 197
 198	err = e->set(counter, index);
 199	if (err)
 200		return err;
 201
 202	return len;
 203}
 204EXPORT_SYMBOL_GPL(counter_device_enum_write);
 205
 206ssize_t counter_device_enum_available_read(struct counter_device *counter,
 207					   void *priv, char *buf)
 208{
 209	const struct counter_device_enum_ext *const e = priv;
 210	size_t i;
 211	size_t len = 0;
 212
 213	if (!e->num_items)
 214		return 0;
 215
 216	for (i = 0; i < e->num_items; i++)
 217		len += sprintf(buf + len, "%s\n", e->items[i]);
 218
 219	return len;
 220}
 221EXPORT_SYMBOL_GPL(counter_device_enum_available_read);
 222
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 223struct counter_attr_parm {
 224	struct counter_device_attr_group *group;
 225	const char *prefix;
 226	const char *name;
 227	ssize_t (*show)(struct device *dev, struct device_attribute *attr,
 228			char *buf);
 229	ssize_t (*store)(struct device *dev, struct device_attribute *attr,
 230			 const char *buf, size_t len);
 231	void *component;
 232};
 233
 234struct counter_device_attr {
 235	struct device_attribute dev_attr;
 236	struct list_head l;
 237	void *component;
 238};
 239
 240static int counter_attribute_create(const struct counter_attr_parm *const parm)
 241{
 242	struct counter_device_attr *counter_attr;
 243	struct device_attribute *dev_attr;
 244	int err;
 245	struct list_head *const attr_list = &parm->group->attr_list;
 246
 247	/* Allocate a Counter device attribute */
 248	counter_attr = kzalloc(sizeof(*counter_attr), GFP_KERNEL);
 249	if (!counter_attr)
 250		return -ENOMEM;
 251	dev_attr = &counter_attr->dev_attr;
 252
 253	sysfs_attr_init(&dev_attr->attr);
 254
 255	/* Configure device attribute */
 256	dev_attr->attr.name = kasprintf(GFP_KERNEL, "%s%s", parm->prefix,
 257					parm->name);
 258	if (!dev_attr->attr.name) {
 259		err = -ENOMEM;
 260		goto err_free_counter_attr;
 261	}
 262	if (parm->show) {
 263		dev_attr->attr.mode |= 0444;
 264		dev_attr->show = parm->show;
 265	}
 266	if (parm->store) {
 267		dev_attr->attr.mode |= 0200;
 268		dev_attr->store = parm->store;
 269	}
 270
 271	/* Store associated Counter component with attribute */
 272	counter_attr->component = parm->component;
 273
 274	/* Keep track of the attribute for later cleanup */
 275	list_add(&counter_attr->l, attr_list);
 276	parm->group->num_attr++;
 277
 278	return 0;
 279
 280err_free_counter_attr:
 281	kfree(counter_attr);
 282	return err;
 283}
 284
 285#define to_counter_attr(_dev_attr) \
 286	container_of(_dev_attr, struct counter_device_attr, dev_attr)
 287
 288struct counter_signal_unit {
 289	struct counter_signal *signal;
 290};
 291
 292static const char *const counter_signal_value_str[] = {
 293	[COUNTER_SIGNAL_LOW] = "low",
 294	[COUNTER_SIGNAL_HIGH] = "high"
 295};
 296
 297static ssize_t counter_signal_show(struct device *dev,
 298				   struct device_attribute *attr, char *buf)
 299{
 300	struct counter_device *const counter = dev_get_drvdata(dev);
 301	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 302	const struct counter_signal_unit *const component = devattr->component;
 303	struct counter_signal *const signal = component->signal;
 304	int err;
 305	enum counter_signal_value val;
 306
 307	err = counter->ops->signal_read(counter, signal, &val);
 308	if (err)
 309		return err;
 310
 311	return sprintf(buf, "%s\n", counter_signal_value_str[val]);
 312}
 313
 314struct counter_name_unit {
 315	const char *name;
 316};
 317
 318static ssize_t counter_device_attr_name_show(struct device *dev,
 319					     struct device_attribute *attr,
 320					     char *buf)
 321{
 322	const struct counter_name_unit *const comp = to_counter_attr(attr)->component;
 323
 324	return sprintf(buf, "%s\n", comp->name);
 325}
 326
 327static int counter_name_attribute_create(
 328	struct counter_device_attr_group *const group,
 329	const char *const name)
 330{
 331	struct counter_name_unit *name_comp;
 332	struct counter_attr_parm parm;
 333	int err;
 334
 335	/* Skip if no name */
 336	if (!name)
 337		return 0;
 338
 339	/* Allocate name attribute component */
 340	name_comp = kmalloc(sizeof(*name_comp), GFP_KERNEL);
 341	if (!name_comp)
 342		return -ENOMEM;
 343	name_comp->name = name;
 344
 345	/* Allocate Signal name attribute */
 346	parm.group = group;
 347	parm.prefix = "";
 348	parm.name = "name";
 349	parm.show = counter_device_attr_name_show;
 350	parm.store = NULL;
 351	parm.component = name_comp;
 352	err = counter_attribute_create(&parm);
 353	if (err)
 354		goto err_free_name_comp;
 355
 356	return 0;
 357
 358err_free_name_comp:
 359	kfree(name_comp);
 360	return err;
 361}
 362
 363struct counter_signal_ext_unit {
 364	struct counter_signal *signal;
 365	const struct counter_signal_ext *ext;
 366};
 367
 368static ssize_t counter_signal_ext_show(struct device *dev,
 369				       struct device_attribute *attr, char *buf)
 370{
 371	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 372	const struct counter_signal_ext_unit *const comp = devattr->component;
 373	const struct counter_signal_ext *const ext = comp->ext;
 374
 375	return ext->read(dev_get_drvdata(dev), comp->signal, ext->priv, buf);
 376}
 377
 378static ssize_t counter_signal_ext_store(struct device *dev,
 379					struct device_attribute *attr,
 380					const char *buf, size_t len)
 381{
 382	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 383	const struct counter_signal_ext_unit *const comp = devattr->component;
 384	const struct counter_signal_ext *const ext = comp->ext;
 385
 386	return ext->write(dev_get_drvdata(dev), comp->signal, ext->priv, buf,
 387		len);
 388}
 389
 390static void counter_device_attr_list_free(struct list_head *attr_list)
 391{
 392	struct counter_device_attr *p, *n;
 393
 394	list_for_each_entry_safe(p, n, attr_list, l) {
 395		/* free attribute name and associated component memory */
 396		kfree(p->dev_attr.attr.name);
 397		kfree(p->component);
 398		list_del(&p->l);
 399		kfree(p);
 400	}
 401}
 402
 403static int counter_signal_ext_register(
 404	struct counter_device_attr_group *const group,
 405	struct counter_signal *const signal)
 406{
 407	const size_t num_ext = signal->num_ext;
 408	size_t i;
 409	const struct counter_signal_ext *ext;
 410	struct counter_signal_ext_unit *signal_ext_comp;
 411	struct counter_attr_parm parm;
 412	int err;
 413
 414	/* Create an attribute for each extension */
 415	for (i = 0 ; i < num_ext; i++) {
 416		ext = signal->ext + i;
 417
 418		/* Allocate signal_ext attribute component */
 419		signal_ext_comp = kmalloc(sizeof(*signal_ext_comp), GFP_KERNEL);
 420		if (!signal_ext_comp) {
 421			err = -ENOMEM;
 422			goto err_free_attr_list;
 423		}
 424		signal_ext_comp->signal = signal;
 425		signal_ext_comp->ext = ext;
 426
 427		/* Allocate a Counter device attribute */
 428		parm.group = group;
 429		parm.prefix = "";
 430		parm.name = ext->name;
 431		parm.show = (ext->read) ? counter_signal_ext_show : NULL;
 432		parm.store = (ext->write) ? counter_signal_ext_store : NULL;
 433		parm.component = signal_ext_comp;
 434		err = counter_attribute_create(&parm);
 435		if (err) {
 436			kfree(signal_ext_comp);
 437			goto err_free_attr_list;
 438		}
 439	}
 440
 441	return 0;
 442
 443err_free_attr_list:
 444	counter_device_attr_list_free(&group->attr_list);
 445	return err;
 446}
 447
 448static int counter_signal_attributes_create(
 449	struct counter_device_attr_group *const group,
 450	const struct counter_device *const counter,
 451	struct counter_signal *const signal)
 452{
 453	struct counter_signal_unit *signal_comp;
 454	struct counter_attr_parm parm;
 455	int err;
 456
 457	/* Allocate Signal attribute component */
 458	signal_comp = kmalloc(sizeof(*signal_comp), GFP_KERNEL);
 459	if (!signal_comp)
 460		return -ENOMEM;
 461	signal_comp->signal = signal;
 462
 463	/* Create main Signal attribute */
 464	parm.group = group;
 465	parm.prefix = "";
 466	parm.name = "signal";
 467	parm.show = (counter->ops->signal_read) ? counter_signal_show : NULL;
 468	parm.store = NULL;
 469	parm.component = signal_comp;
 470	err = counter_attribute_create(&parm);
 471	if (err) {
 472		kfree(signal_comp);
 473		return err;
 474	}
 475
 476	/* Create Signal name attribute */
 477	err = counter_name_attribute_create(group, signal->name);
 478	if (err)
 479		goto err_free_attr_list;
 480
 481	/* Register Signal extension attributes */
 482	err = counter_signal_ext_register(group, signal);
 483	if (err)
 484		goto err_free_attr_list;
 485
 486	return 0;
 487
 488err_free_attr_list:
 489	counter_device_attr_list_free(&group->attr_list);
 490	return err;
 491}
 492
 493static int counter_signals_register(
 494	struct counter_device_attr_group *const groups_list,
 495	const struct counter_device *const counter)
 496{
 497	const size_t num_signals = counter->num_signals;
 498	size_t i;
 499	struct counter_signal *signal;
 500	const char *name;
 501	int err;
 502
 503	/* Register each Signal */
 504	for (i = 0; i < num_signals; i++) {
 505		signal = counter->signals + i;
 506
 507		/* Generate Signal attribute directory name */
 508		name = kasprintf(GFP_KERNEL, "signal%d", signal->id);
 509		if (!name) {
 510			err = -ENOMEM;
 511			goto err_free_attr_groups;
 512		}
 513		groups_list[i].attr_group.name = name;
 514
 515		/* Create all attributes associated with Signal */
 516		err = counter_signal_attributes_create(groups_list + i, counter,
 517						       signal);
 518		if (err)
 519			goto err_free_attr_groups;
 520	}
 521
 522	return 0;
 523
 524err_free_attr_groups:
 525	do {
 526		kfree(groups_list[i].attr_group.name);
 527		counter_device_attr_list_free(&groups_list[i].attr_list);
 528	} while (i--);
 529	return err;
 530}
 531
 532static const char *const counter_synapse_action_str[] = {
 533	[COUNTER_SYNAPSE_ACTION_NONE] = "none",
 534	[COUNTER_SYNAPSE_ACTION_RISING_EDGE] = "rising edge",
 535	[COUNTER_SYNAPSE_ACTION_FALLING_EDGE] = "falling edge",
 536	[COUNTER_SYNAPSE_ACTION_BOTH_EDGES] = "both edges"
 537};
 538
 539struct counter_action_unit {
 540	struct counter_synapse *synapse;
 541	struct counter_count *count;
 542};
 543
 544static ssize_t counter_action_show(struct device *dev,
 545				   struct device_attribute *attr, char *buf)
 546{
 547	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 548	int err;
 549	struct counter_device *const counter = dev_get_drvdata(dev);
 550	const struct counter_action_unit *const component = devattr->component;
 551	struct counter_count *const count = component->count;
 552	struct counter_synapse *const synapse = component->synapse;
 553	size_t action_index;
 554	enum counter_synapse_action action;
 555
 556	err = counter->ops->action_get(counter, count, synapse, &action_index);
 557	if (err)
 558		return err;
 559
 560	synapse->action = action_index;
 561
 562	action = synapse->actions_list[action_index];
 563	return sprintf(buf, "%s\n", counter_synapse_action_str[action]);
 564}
 565
 566static ssize_t counter_action_store(struct device *dev,
 567				    struct device_attribute *attr,
 568				    const char *buf, size_t len)
 569{
 570	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 571	const struct counter_action_unit *const component = devattr->component;
 572	struct counter_synapse *const synapse = component->synapse;
 573	size_t action_index;
 574	const size_t num_actions = synapse->num_actions;
 575	enum counter_synapse_action action;
 576	int err;
 577	struct counter_device *const counter = dev_get_drvdata(dev);
 578	struct counter_count *const count = component->count;
 579
 580	/* Find requested action mode */
 581	for (action_index = 0; action_index < num_actions; action_index++) {
 582		action = synapse->actions_list[action_index];
 583		if (sysfs_streq(buf, counter_synapse_action_str[action]))
 584			break;
 585	}
 586	/* If requested action mode not found */
 587	if (action_index >= num_actions)
 588		return -EINVAL;
 589
 590	err = counter->ops->action_set(counter, count, synapse, action_index);
 591	if (err)
 592		return err;
 593
 594	synapse->action = action_index;
 595
 596	return len;
 597}
 598
 599struct counter_action_avail_unit {
 600	const enum counter_synapse_action *actions_list;
 601	size_t num_actions;
 602};
 603
 604static ssize_t counter_synapse_action_available_show(struct device *dev,
 605	struct device_attribute *attr, char *buf)
 606{
 607	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 608	const struct counter_action_avail_unit *const component = devattr->component;
 609	size_t i;
 610	enum counter_synapse_action action;
 611	ssize_t len = 0;
 612
 613	for (i = 0; i < component->num_actions; i++) {
 614		action = component->actions_list[i];
 615		len += sprintf(buf + len, "%s\n",
 616			       counter_synapse_action_str[action]);
 617	}
 618
 619	return len;
 620}
 621
 622static int counter_synapses_register(
 623	struct counter_device_attr_group *const group,
 624	const struct counter_device *const counter,
 625	struct counter_count *const count, const char *const count_attr_name)
 626{
 627	size_t i;
 628	struct counter_synapse *synapse;
 629	const char *prefix;
 630	struct counter_action_unit *action_comp;
 631	struct counter_attr_parm parm;
 632	int err;
 633	struct counter_action_avail_unit *avail_comp;
 634
 635	/* Register each Synapse */
 636	for (i = 0; i < count->num_synapses; i++) {
 637		synapse = count->synapses + i;
 638
 639		/* Generate attribute prefix */
 640		prefix = kasprintf(GFP_KERNEL, "signal%d_",
 641				   synapse->signal->id);
 642		if (!prefix) {
 643			err = -ENOMEM;
 644			goto err_free_attr_list;
 645		}
 646
 647		/* Allocate action attribute component */
 648		action_comp = kmalloc(sizeof(*action_comp), GFP_KERNEL);
 649		if (!action_comp) {
 650			err = -ENOMEM;
 651			goto err_free_prefix;
 652		}
 653		action_comp->synapse = synapse;
 654		action_comp->count = count;
 655
 656		/* Create action attribute */
 657		parm.group = group;
 658		parm.prefix = prefix;
 659		parm.name = "action";
 660		parm.show = (counter->ops->action_get) ? counter_action_show : NULL;
 661		parm.store = (counter->ops->action_set) ? counter_action_store : NULL;
 662		parm.component = action_comp;
 663		err = counter_attribute_create(&parm);
 664		if (err) {
 665			kfree(action_comp);
 666			goto err_free_prefix;
 667		}
 668
 669		/* Allocate action available attribute component */
 670		avail_comp = kmalloc(sizeof(*avail_comp), GFP_KERNEL);
 671		if (!avail_comp) {
 672			err = -ENOMEM;
 673			goto err_free_prefix;
 674		}
 675		avail_comp->actions_list = synapse->actions_list;
 676		avail_comp->num_actions = synapse->num_actions;
 677
 678		/* Create action_available attribute */
 679		parm.group = group;
 680		parm.prefix = prefix;
 681		parm.name = "action_available";
 682		parm.show = counter_synapse_action_available_show;
 683		parm.store = NULL;
 684		parm.component = avail_comp;
 685		err = counter_attribute_create(&parm);
 686		if (err) {
 687			kfree(avail_comp);
 688			goto err_free_prefix;
 689		}
 690
 691		kfree(prefix);
 692	}
 693
 694	return 0;
 695
 696err_free_prefix:
 697	kfree(prefix);
 698err_free_attr_list:
 699	counter_device_attr_list_free(&group->attr_list);
 700	return err;
 701}
 702
 703struct counter_count_unit {
 704	struct counter_count *count;
 705};
 706
 707static ssize_t counter_count_show(struct device *dev,
 708				  struct device_attribute *attr,
 709				  char *buf)
 710{
 711	struct counter_device *const counter = dev_get_drvdata(dev);
 712	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 713	const struct counter_count_unit *const component = devattr->component;
 714	struct counter_count *const count = component->count;
 715	int err;
 716	unsigned long val;
 717
 718	err = counter->ops->count_read(counter, count, &val);
 719	if (err)
 720		return err;
 721
 722	return sprintf(buf, "%lu\n", val);
 723}
 724
 725static ssize_t counter_count_store(struct device *dev,
 726				   struct device_attribute *attr,
 727				   const char *buf, size_t len)
 728{
 729	struct counter_device *const counter = dev_get_drvdata(dev);
 730	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 731	const struct counter_count_unit *const component = devattr->component;
 732	struct counter_count *const count = component->count;
 733	int err;
 734	unsigned long val;
 735
 736	err = kstrtoul(buf, 0, &val);
 737	if (err)
 738		return err;
 739
 740	err = counter->ops->count_write(counter, count, val);
 741	if (err)
 742		return err;
 743
 744	return len;
 745}
 746
 747static const char *const counter_count_function_str[] = {
 748	[COUNTER_COUNT_FUNCTION_INCREASE] = "increase",
 749	[COUNTER_COUNT_FUNCTION_DECREASE] = "decrease",
 750	[COUNTER_COUNT_FUNCTION_PULSE_DIRECTION] = "pulse-direction",
 751	[COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A] = "quadrature x1 a",
 752	[COUNTER_COUNT_FUNCTION_QUADRATURE_X1_B] = "quadrature x1 b",
 753	[COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A] = "quadrature x2 a",
 754	[COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B] = "quadrature x2 b",
 755	[COUNTER_COUNT_FUNCTION_QUADRATURE_X4] = "quadrature x4"
 756};
 757
 758static ssize_t counter_function_show(struct device *dev,
 759				     struct device_attribute *attr, char *buf)
 760{
 761	int err;
 762	struct counter_device *const counter = dev_get_drvdata(dev);
 763	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 764	const struct counter_count_unit *const component = devattr->component;
 765	struct counter_count *const count = component->count;
 766	size_t func_index;
 767	enum counter_count_function function;
 768
 769	err = counter->ops->function_get(counter, count, &func_index);
 770	if (err)
 771		return err;
 772
 773	count->function = func_index;
 774
 775	function = count->functions_list[func_index];
 776	return sprintf(buf, "%s\n", counter_count_function_str[function]);
 777}
 778
 779static ssize_t counter_function_store(struct device *dev,
 780				      struct device_attribute *attr,
 781				      const char *buf, size_t len)
 782{
 783	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 784	const struct counter_count_unit *const component = devattr->component;
 785	struct counter_count *const count = component->count;
 786	const size_t num_functions = count->num_functions;
 787	size_t func_index;
 788	enum counter_count_function function;
 789	int err;
 790	struct counter_device *const counter = dev_get_drvdata(dev);
 791
 792	/* Find requested Count function mode */
 793	for (func_index = 0; func_index < num_functions; func_index++) {
 794		function = count->functions_list[func_index];
 795		if (sysfs_streq(buf, counter_count_function_str[function]))
 796			break;
 797	}
 798	/* Return error if requested Count function mode not found */
 799	if (func_index >= num_functions)
 800		return -EINVAL;
 801
 802	err = counter->ops->function_set(counter, count, func_index);
 803	if (err)
 804		return err;
 805
 806	count->function = func_index;
 807
 808	return len;
 809}
 810
 811struct counter_count_ext_unit {
 812	struct counter_count *count;
 813	const struct counter_count_ext *ext;
 814};
 815
 816static ssize_t counter_count_ext_show(struct device *dev,
 817				      struct device_attribute *attr, char *buf)
 818{
 819	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 820	const struct counter_count_ext_unit *const comp = devattr->component;
 821	const struct counter_count_ext *const ext = comp->ext;
 822
 823	return ext->read(dev_get_drvdata(dev), comp->count, ext->priv, buf);
 824}
 825
 826static ssize_t counter_count_ext_store(struct device *dev,
 827				       struct device_attribute *attr,
 828				       const char *buf, size_t len)
 829{
 830	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 831	const struct counter_count_ext_unit *const comp = devattr->component;
 832	const struct counter_count_ext *const ext = comp->ext;
 833
 834	return ext->write(dev_get_drvdata(dev), comp->count, ext->priv, buf,
 835		len);
 836}
 837
 838static int counter_count_ext_register(
 839	struct counter_device_attr_group *const group,
 840	struct counter_count *const count)
 841{
 842	size_t i;
 843	const struct counter_count_ext *ext;
 844	struct counter_count_ext_unit *count_ext_comp;
 845	struct counter_attr_parm parm;
 846	int err;
 847
 848	/* Create an attribute for each extension */
 849	for (i = 0 ; i < count->num_ext; i++) {
 850		ext = count->ext + i;
 851
 852		/* Allocate count_ext attribute component */
 853		count_ext_comp = kmalloc(sizeof(*count_ext_comp), GFP_KERNEL);
 854		if (!count_ext_comp) {
 855			err = -ENOMEM;
 856			goto err_free_attr_list;
 857		}
 858		count_ext_comp->count = count;
 859		count_ext_comp->ext = ext;
 860
 861		/* Allocate count_ext attribute */
 862		parm.group = group;
 863		parm.prefix = "";
 864		parm.name = ext->name;
 865		parm.show = (ext->read) ? counter_count_ext_show : NULL;
 866		parm.store = (ext->write) ? counter_count_ext_store : NULL;
 867		parm.component = count_ext_comp;
 868		err = counter_attribute_create(&parm);
 869		if (err) {
 870			kfree(count_ext_comp);
 871			goto err_free_attr_list;
 872		}
 873	}
 874
 875	return 0;
 876
 877err_free_attr_list:
 878	counter_device_attr_list_free(&group->attr_list);
 879	return err;
 880}
 881
 882struct counter_func_avail_unit {
 883	const enum counter_count_function *functions_list;
 884	size_t num_functions;
 885};
 886
 887static ssize_t counter_count_function_available_show(struct device *dev,
 888	struct device_attribute *attr, char *buf)
 889{
 890	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 891	const struct counter_func_avail_unit *const component = devattr->component;
 892	const enum counter_count_function *const func_list = component->functions_list;
 893	const size_t num_functions = component->num_functions;
 894	size_t i;
 895	enum counter_count_function function;
 896	ssize_t len = 0;
 897
 898	for (i = 0; i < num_functions; i++) {
 899		function = func_list[i];
 900		len += sprintf(buf + len, "%s\n",
 901			       counter_count_function_str[function]);
 902	}
 903
 904	return len;
 905}
 906
 907static int counter_count_attributes_create(
 908	struct counter_device_attr_group *const group,
 909	const struct counter_device *const counter,
 910	struct counter_count *const count)
 911{
 912	struct counter_count_unit *count_comp;
 913	struct counter_attr_parm parm;
 914	int err;
 915	struct counter_count_unit *func_comp;
 916	struct counter_func_avail_unit *avail_comp;
 917
 918	/* Allocate count attribute component */
 919	count_comp = kmalloc(sizeof(*count_comp), GFP_KERNEL);
 920	if (!count_comp)
 921		return -ENOMEM;
 922	count_comp->count = count;
 923
 924	/* Create main Count attribute */
 925	parm.group = group;
 926	parm.prefix = "";
 927	parm.name = "count";
 928	parm.show = (counter->ops->count_read) ? counter_count_show : NULL;
 929	parm.store = (counter->ops->count_write) ? counter_count_store : NULL;
 930	parm.component = count_comp;
 931	err = counter_attribute_create(&parm);
 932	if (err) {
 933		kfree(count_comp);
 934		return err;
 935	}
 936
 937	/* Allocate function attribute component */
 938	func_comp = kmalloc(sizeof(*func_comp), GFP_KERNEL);
 939	if (!func_comp) {
 940		err = -ENOMEM;
 941		goto err_free_attr_list;
 942	}
 943	func_comp->count = count;
 944
 945	/* Create Count function attribute */
 946	parm.group = group;
 947	parm.prefix = "";
 948	parm.name = "function";
 949	parm.show = (counter->ops->function_get) ? counter_function_show : NULL;
 950	parm.store = (counter->ops->function_set) ? counter_function_store : NULL;
 951	parm.component = func_comp;
 952	err = counter_attribute_create(&parm);
 953	if (err) {
 954		kfree(func_comp);
 955		goto err_free_attr_list;
 956	}
 957
 958	/* Allocate function available attribute component */
 959	avail_comp = kmalloc(sizeof(*avail_comp), GFP_KERNEL);
 960	if (!avail_comp) {
 961		err = -ENOMEM;
 962		goto err_free_attr_list;
 963	}
 964	avail_comp->functions_list = count->functions_list;
 965	avail_comp->num_functions = count->num_functions;
 966
 967	/* Create Count function_available attribute */
 968	parm.group = group;
 969	parm.prefix = "";
 970	parm.name = "function_available";
 971	parm.show = counter_count_function_available_show;
 972	parm.store = NULL;
 973	parm.component = avail_comp;
 974	err = counter_attribute_create(&parm);
 975	if (err) {
 976		kfree(avail_comp);
 977		goto err_free_attr_list;
 978	}
 979
 980	/* Create Count name attribute */
 981	err = counter_name_attribute_create(group, count->name);
 982	if (err)
 983		goto err_free_attr_list;
 984
 985	/* Register Count extension attributes */
 986	err = counter_count_ext_register(group, count);
 987	if (err)
 988		goto err_free_attr_list;
 989
 990	return 0;
 991
 992err_free_attr_list:
 993	counter_device_attr_list_free(&group->attr_list);
 994	return err;
 995}
 996
 997static int counter_counts_register(
 998	struct counter_device_attr_group *const groups_list,
 999	const struct counter_device *const counter)
1000{
1001	size_t i;
1002	struct counter_count *count;
1003	const char *name;
1004	int err;
1005
1006	/* Register each Count */
1007	for (i = 0; i < counter->num_counts; i++) {
1008		count = counter->counts + i;
1009
1010		/* Generate Count attribute directory name */
1011		name = kasprintf(GFP_KERNEL, "count%d", count->id);
1012		if (!name) {
1013			err = -ENOMEM;
1014			goto err_free_attr_groups;
1015		}
1016		groups_list[i].attr_group.name = name;
1017
1018		/* Register the Synapses associated with each Count */
1019		err = counter_synapses_register(groups_list + i, counter, count,
1020						name);
1021		if (err)
1022			goto err_free_attr_groups;
1023
1024		/* Create all attributes associated with Count */
1025		err = counter_count_attributes_create(groups_list + i, counter,
1026						      count);
1027		if (err)
1028			goto err_free_attr_groups;
1029	}
1030
1031	return 0;
1032
1033err_free_attr_groups:
1034	do {
1035		kfree(groups_list[i].attr_group.name);
1036		counter_device_attr_list_free(&groups_list[i].attr_list);
1037	} while (i--);
1038	return err;
1039}
1040
1041struct counter_size_unit {
1042	size_t size;
1043};
1044
1045static ssize_t counter_device_attr_size_show(struct device *dev,
1046					     struct device_attribute *attr,
1047					     char *buf)
1048{
1049	const struct counter_size_unit *const comp = to_counter_attr(attr)->component;
1050
1051	return sprintf(buf, "%zu\n", comp->size);
1052}
1053
1054static int counter_size_attribute_create(
1055	struct counter_device_attr_group *const group,
1056	const size_t size, const char *const name)
1057{
1058	struct counter_size_unit *size_comp;
1059	struct counter_attr_parm parm;
1060	int err;
1061
1062	/* Allocate size attribute component */
1063	size_comp = kmalloc(sizeof(*size_comp), GFP_KERNEL);
1064	if (!size_comp)
1065		return -ENOMEM;
1066	size_comp->size = size;
1067
1068	parm.group = group;
1069	parm.prefix = "";
1070	parm.name = name;
1071	parm.show = counter_device_attr_size_show;
1072	parm.store = NULL;
1073	parm.component = size_comp;
1074	err = counter_attribute_create(&parm);
1075	if (err)
1076		goto err_free_size_comp;
1077
1078	return 0;
1079
1080err_free_size_comp:
1081	kfree(size_comp);
1082	return err;
1083}
1084
1085struct counter_ext_unit {
1086	const struct counter_device_ext *ext;
1087};
1088
1089static ssize_t counter_device_ext_show(struct device *dev,
1090				       struct device_attribute *attr, char *buf)
1091{
1092	const struct counter_device_attr *const devattr = to_counter_attr(attr);
1093	const struct counter_ext_unit *const component = devattr->component;
1094	const struct counter_device_ext *const ext = component->ext;
1095
1096	return ext->read(dev_get_drvdata(dev), ext->priv, buf);
1097}
1098
1099static ssize_t counter_device_ext_store(struct device *dev,
1100					struct device_attribute *attr,
1101					const char *buf, size_t len)
1102{
1103	const struct counter_device_attr *const devattr = to_counter_attr(attr);
1104	const struct counter_ext_unit *const component = devattr->component;
1105	const struct counter_device_ext *const ext = component->ext;
1106
1107	return ext->write(dev_get_drvdata(dev), ext->priv, buf, len);
1108}
1109
1110static int counter_device_ext_register(
1111	struct counter_device_attr_group *const group,
1112	struct counter_device *const counter)
1113{
1114	size_t i;
1115	struct counter_ext_unit *ext_comp;
1116	struct counter_attr_parm parm;
1117	int err;
1118
1119	/* Create an attribute for each extension */
1120	for (i = 0 ; i < counter->num_ext; i++) {
1121		/* Allocate extension attribute component */
1122		ext_comp = kmalloc(sizeof(*ext_comp), GFP_KERNEL);
1123		if (!ext_comp) {
1124			err = -ENOMEM;
1125			goto err_free_attr_list;
1126		}
1127
1128		ext_comp->ext = counter->ext + i;
1129
1130		/* Allocate extension attribute */
1131		parm.group = group;
1132		parm.prefix = "";
1133		parm.name = counter->ext[i].name;
1134		parm.show = (counter->ext[i].read) ? counter_device_ext_show : NULL;
1135		parm.store = (counter->ext[i].write) ? counter_device_ext_store : NULL;
1136		parm.component = ext_comp;
1137		err = counter_attribute_create(&parm);
1138		if (err) {
1139			kfree(ext_comp);
1140			goto err_free_attr_list;
1141		}
1142	}
1143
1144	return 0;
1145
1146err_free_attr_list:
1147	counter_device_attr_list_free(&group->attr_list);
1148	return err;
1149}
1150
1151static int counter_global_attr_register(
1152	struct counter_device_attr_group *const group,
1153	struct counter_device *const counter)
1154{
1155	int err;
1156
1157	/* Create name attribute */
1158	err = counter_name_attribute_create(group, counter->name);
1159	if (err)
1160		return err;
1161
1162	/* Create num_counts attribute */
1163	err = counter_size_attribute_create(group, counter->num_counts,
1164					    "num_counts");
1165	if (err)
1166		goto err_free_attr_list;
1167
1168	/* Create num_signals attribute */
1169	err = counter_size_attribute_create(group, counter->num_signals,
1170					    "num_signals");
1171	if (err)
1172		goto err_free_attr_list;
1173
1174	/* Register Counter device extension attributes */
1175	err = counter_device_ext_register(group, counter);
1176	if (err)
1177		goto err_free_attr_list;
1178
1179	return 0;
1180
1181err_free_attr_list:
1182	counter_device_attr_list_free(&group->attr_list);
1183	return err;
1184}
1185
1186static void counter_device_groups_list_free(
1187	struct counter_device_attr_group *const groups_list,
1188	const size_t num_groups)
1189{
1190	struct counter_device_attr_group *group;
1191	size_t i;
1192
1193	/* loop through all attribute groups (signals, counts, global, etc.) */
1194	for (i = 0; i < num_groups; i++) {
1195		group = groups_list + i;
1196
1197		/* free all attribute group and associated attributes memory */
1198		kfree(group->attr_group.name);
1199		kfree(group->attr_group.attrs);
1200		counter_device_attr_list_free(&group->attr_list);
1201	}
1202
1203	kfree(groups_list);
1204}
1205
1206static int counter_device_groups_list_prepare(
1207	struct counter_device *const counter)
1208{
1209	const size_t total_num_groups =
1210		counter->num_signals + counter->num_counts + 1;
1211	struct counter_device_attr_group *groups_list;
1212	size_t i;
1213	int err;
1214	size_t num_groups = 0;
1215
1216	/* Allocate space for attribute groups (signals, counts, and ext) */
1217	groups_list = kcalloc(total_num_groups, sizeof(*groups_list),
1218			      GFP_KERNEL);
1219	if (!groups_list)
1220		return -ENOMEM;
1221
1222	/* Initialize attribute lists */
1223	for (i = 0; i < total_num_groups; i++)
1224		INIT_LIST_HEAD(&groups_list[i].attr_list);
1225
1226	/* Register Signals */
1227	err = counter_signals_register(groups_list, counter);
1228	if (err)
1229		goto err_free_groups_list;
1230	num_groups += counter->num_signals;
1231
1232	/* Register Counts and respective Synapses */
1233	err = counter_counts_register(groups_list + num_groups, counter);
1234	if (err)
1235		goto err_free_groups_list;
1236	num_groups += counter->num_counts;
1237
1238	/* Register Counter global attributes */
1239	err = counter_global_attr_register(groups_list + num_groups, counter);
1240	if (err)
1241		goto err_free_groups_list;
1242	num_groups++;
1243
1244	/* Store groups_list in device_state */
1245	counter->device_state->groups_list = groups_list;
1246	counter->device_state->num_groups = num_groups;
1247
1248	return 0;
1249
1250err_free_groups_list:
1251	counter_device_groups_list_free(groups_list, num_groups);
1252	return err;
1253}
1254
1255static int counter_device_groups_prepare(
1256	struct counter_device_state *const device_state)
1257{
1258	size_t i, j;
1259	struct counter_device_attr_group *group;
1260	int err;
1261	struct counter_device_attr *p;
1262
1263	/* Allocate attribute groups for association with device */
1264	device_state->groups = kcalloc(device_state->num_groups + 1,
1265				       sizeof(*device_state->groups),
1266				       GFP_KERNEL);
1267	if (!device_state->groups)
1268		return -ENOMEM;
1269
1270	/* Prepare each group of attributes for association */
1271	for (i = 0; i < device_state->num_groups; i++) {
1272		group = device_state->groups_list + i;
1273
1274		/* Allocate space for attribute pointers in attribute group */
1275		group->attr_group.attrs = kcalloc(group->num_attr + 1,
1276			sizeof(*group->attr_group.attrs), GFP_KERNEL);
1277		if (!group->attr_group.attrs) {
1278			err = -ENOMEM;
1279			goto err_free_groups;
1280		}
1281
1282		/* Add attribute pointers to attribute group */
1283		j = 0;
1284		list_for_each_entry(p, &group->attr_list, l)
1285			group->attr_group.attrs[j++] = &p->dev_attr.attr;
1286
1287		/* Group attributes in attribute group */
1288		device_state->groups[i] = &group->attr_group;
1289	}
1290	/* Associate attributes with device */
1291	device_state->dev.groups = device_state->groups;
1292
1293	return 0;
1294
1295err_free_groups:
1296	do {
1297		group = device_state->groups_list + i;
1298		kfree(group->attr_group.attrs);
1299		group->attr_group.attrs = NULL;
1300	} while (i--);
1301	kfree(device_state->groups);
1302	return err;
1303}
1304
1305/* Provides a unique ID for each counter device */
1306static DEFINE_IDA(counter_ida);
1307
1308static void counter_device_release(struct device *dev)
1309{
1310	struct counter_device *const counter = dev_get_drvdata(dev);
1311	struct counter_device_state *const device_state = counter->device_state;
1312
1313	kfree(device_state->groups);
1314	counter_device_groups_list_free(device_state->groups_list,
1315					device_state->num_groups);
1316	ida_simple_remove(&counter_ida, device_state->id);
1317	kfree(device_state);
1318}
1319
1320static struct device_type counter_device_type = {
1321	.name = "counter_device",
1322	.release = counter_device_release
1323};
1324
1325static struct bus_type counter_bus_type = {
1326	.name = "counter"
1327};
1328
1329/**
1330 * counter_register - register Counter to the system
1331 * @counter:	pointer to Counter to register
1332 *
1333 * This function registers a Counter to the system. A sysfs "counter" directory
1334 * will be created and populated with sysfs attributes correlating with the
1335 * Counter Signals, Synapses, and Counts respectively.
1336 */
1337int counter_register(struct counter_device *const counter)
1338{
1339	struct counter_device_state *device_state;
1340	int err;
1341
1342	/* Allocate internal state container for Counter device */
1343	device_state = kzalloc(sizeof(*device_state), GFP_KERNEL);
1344	if (!device_state)
1345		return -ENOMEM;
1346	counter->device_state = device_state;
1347
1348	/* Acquire unique ID */
1349	device_state->id = ida_simple_get(&counter_ida, 0, 0, GFP_KERNEL);
1350	if (device_state->id < 0) {
1351		err = device_state->id;
1352		goto err_free_device_state;
1353	}
1354
1355	/* Configure device structure for Counter */
1356	device_state->dev.type = &counter_device_type;
1357	device_state->dev.bus = &counter_bus_type;
1358	if (counter->parent) {
1359		device_state->dev.parent = counter->parent;
1360		device_state->dev.of_node = counter->parent->of_node;
1361	}
1362	dev_set_name(&device_state->dev, "counter%d", device_state->id);
1363	device_initialize(&device_state->dev);
1364	dev_set_drvdata(&device_state->dev, counter);
1365
1366	/* Prepare device attributes */
1367	err = counter_device_groups_list_prepare(counter);
1368	if (err)
1369		goto err_free_id;
1370
1371	/* Organize device attributes to groups and match to device */
1372	err = counter_device_groups_prepare(device_state);
1373	if (err)
1374		goto err_free_groups_list;
1375
1376	/* Add device to system */
1377	err = device_add(&device_state->dev);
1378	if (err)
1379		goto err_free_groups;
1380
1381	return 0;
1382
1383err_free_groups:
1384	kfree(device_state->groups);
1385err_free_groups_list:
1386	counter_device_groups_list_free(device_state->groups_list,
1387					device_state->num_groups);
1388err_free_id:
1389	ida_simple_remove(&counter_ida, device_state->id);
1390err_free_device_state:
1391	kfree(device_state);
1392	return err;
1393}
1394EXPORT_SYMBOL_GPL(counter_register);
1395
1396/**
1397 * counter_unregister - unregister Counter from the system
1398 * @counter:	pointer to Counter to unregister
1399 *
1400 * The Counter is unregistered from the system; all allocated memory is freed.
1401 */
1402void counter_unregister(struct counter_device *const counter)
1403{
1404	if (counter)
1405		device_del(&counter->device_state->dev);
1406}
1407EXPORT_SYMBOL_GPL(counter_unregister);
1408
1409static void devm_counter_unreg(struct device *dev, void *res)
1410{
1411	counter_unregister(*(struct counter_device **)res);
1412}
1413
1414/**
1415 * devm_counter_register - Resource-managed counter_register
1416 * @dev:	device to allocate counter_device for
1417 * @counter:	pointer to Counter to register
1418 *
1419 * Managed counter_register. The Counter registered with this function is
1420 * automatically unregistered on driver detach. This function calls
1421 * counter_register internally. Refer to that function for more information.
1422 *
1423 * If an Counter registered with this function needs to be unregistered
1424 * separately, devm_counter_unregister must be used.
1425 *
1426 * RETURNS:
1427 * 0 on success, negative error number on failure.
1428 */
1429int devm_counter_register(struct device *dev,
1430			  struct counter_device *const counter)
1431{
1432	struct counter_device **ptr;
1433	int ret;
1434
1435	ptr = devres_alloc(devm_counter_unreg, sizeof(*ptr), GFP_KERNEL);
1436	if (!ptr)
1437		return -ENOMEM;
1438
1439	ret = counter_register(counter);
1440	if (!ret) {
1441		*ptr = counter;
1442		devres_add(dev, ptr);
1443	} else {
1444		devres_free(ptr);
1445	}
1446
1447	return ret;
1448}
1449EXPORT_SYMBOL_GPL(devm_counter_register);
1450
1451static int devm_counter_match(struct device *dev, void *res, void *data)
1452{
1453	struct counter_device **r = res;
1454
1455	if (!r || !*r) {
1456		WARN_ON(!r || !*r);
1457		return 0;
1458	}
1459
1460	return *r == data;
1461}
1462
1463/**
1464 * devm_counter_unregister - Resource-managed counter_unregister
1465 * @dev:	device this counter_device belongs to
1466 * @counter:	pointer to Counter associated with the device
1467 *
1468 * Unregister Counter registered with devm_counter_register.
1469 */
1470void devm_counter_unregister(struct device *dev,
1471			     struct counter_device *const counter)
1472{
1473	int rc;
1474
1475	rc = devres_release(dev, devm_counter_unreg, devm_counter_match,
1476			    counter);
1477	WARN_ON(rc);
1478}
1479EXPORT_SYMBOL_GPL(devm_counter_unregister);
1480
1481static int __init counter_init(void)
1482{
1483	return bus_register(&counter_bus_type);
1484}
1485
1486static void __exit counter_exit(void)
1487{
1488	bus_unregister(&counter_bus_type);
1489}
1490
1491subsys_initcall(counter_init);
1492module_exit(counter_exit);
1493
1494MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
1495MODULE_DESCRIPTION("Generic Counter interface");
1496MODULE_LICENSE("GPL v2");
v5.4
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Generic Counter interface
   4 * Copyright (C) 2018 William Breathitt Gray
   5 */
   6#include <linux/counter.h>
   7#include <linux/device.h>
   8#include <linux/err.h>
   9#include <linux/export.h>
  10#include <linux/fs.h>
  11#include <linux/gfp.h>
  12#include <linux/idr.h>
  13#include <linux/init.h>
  14#include <linux/kernel.h>
  15#include <linux/list.h>
  16#include <linux/module.h>
  17#include <linux/printk.h>
  18#include <linux/slab.h>
  19#include <linux/string.h>
  20#include <linux/sysfs.h>
  21#include <linux/types.h>
  22
  23const char *const counter_count_direction_str[2] = {
  24	[COUNTER_COUNT_DIRECTION_FORWARD] = "forward",
  25	[COUNTER_COUNT_DIRECTION_BACKWARD] = "backward"
  26};
  27EXPORT_SYMBOL_GPL(counter_count_direction_str);
  28
  29const char *const counter_count_mode_str[4] = {
  30	[COUNTER_COUNT_MODE_NORMAL] = "normal",
  31	[COUNTER_COUNT_MODE_RANGE_LIMIT] = "range limit",
  32	[COUNTER_COUNT_MODE_NON_RECYCLE] = "non-recycle",
  33	[COUNTER_COUNT_MODE_MODULO_N] = "modulo-n"
  34};
  35EXPORT_SYMBOL_GPL(counter_count_mode_str);
  36
  37ssize_t counter_signal_enum_read(struct counter_device *counter,
  38				 struct counter_signal *signal, void *priv,
  39				 char *buf)
  40{
  41	const struct counter_signal_enum_ext *const e = priv;
  42	int err;
  43	size_t index;
  44
  45	if (!e->get)
  46		return -EINVAL;
  47
  48	err = e->get(counter, signal, &index);
  49	if (err)
  50		return err;
  51
  52	if (index >= e->num_items)
  53		return -EINVAL;
  54
  55	return sprintf(buf, "%s\n", e->items[index]);
  56}
  57EXPORT_SYMBOL_GPL(counter_signal_enum_read);
  58
  59ssize_t counter_signal_enum_write(struct counter_device *counter,
  60				  struct counter_signal *signal, void *priv,
  61				  const char *buf, size_t len)
  62{
  63	const struct counter_signal_enum_ext *const e = priv;
  64	ssize_t index;
  65	int err;
  66
  67	if (!e->set)
  68		return -EINVAL;
  69
  70	index = __sysfs_match_string(e->items, e->num_items, buf);
  71	if (index < 0)
  72		return index;
  73
  74	err = e->set(counter, signal, index);
  75	if (err)
  76		return err;
  77
  78	return len;
  79}
  80EXPORT_SYMBOL_GPL(counter_signal_enum_write);
  81
  82ssize_t counter_signal_enum_available_read(struct counter_device *counter,
  83					   struct counter_signal *signal,
  84					   void *priv, char *buf)
  85{
  86	const struct counter_signal_enum_ext *const e = priv;
  87	size_t i;
  88	size_t len = 0;
  89
  90	if (!e->num_items)
  91		return 0;
  92
  93	for (i = 0; i < e->num_items; i++)
  94		len += sprintf(buf + len, "%s\n", e->items[i]);
  95
  96	return len;
  97}
  98EXPORT_SYMBOL_GPL(counter_signal_enum_available_read);
  99
 100ssize_t counter_count_enum_read(struct counter_device *counter,
 101				struct counter_count *count, void *priv,
 102				char *buf)
 103{
 104	const struct counter_count_enum_ext *const e = priv;
 105	int err;
 106	size_t index;
 107
 108	if (!e->get)
 109		return -EINVAL;
 110
 111	err = e->get(counter, count, &index);
 112	if (err)
 113		return err;
 114
 115	if (index >= e->num_items)
 116		return -EINVAL;
 117
 118	return sprintf(buf, "%s\n", e->items[index]);
 119}
 120EXPORT_SYMBOL_GPL(counter_count_enum_read);
 121
 122ssize_t counter_count_enum_write(struct counter_device *counter,
 123				 struct counter_count *count, void *priv,
 124				 const char *buf, size_t len)
 125{
 126	const struct counter_count_enum_ext *const e = priv;
 127	ssize_t index;
 128	int err;
 129
 130	if (!e->set)
 131		return -EINVAL;
 132
 133	index = __sysfs_match_string(e->items, e->num_items, buf);
 134	if (index < 0)
 135		return index;
 136
 137	err = e->set(counter, count, index);
 138	if (err)
 139		return err;
 140
 141	return len;
 142}
 143EXPORT_SYMBOL_GPL(counter_count_enum_write);
 144
 145ssize_t counter_count_enum_available_read(struct counter_device *counter,
 146					  struct counter_count *count,
 147					  void *priv, char *buf)
 148{
 149	const struct counter_count_enum_ext *const e = priv;
 150	size_t i;
 151	size_t len = 0;
 152
 153	if (!e->num_items)
 154		return 0;
 155
 156	for (i = 0; i < e->num_items; i++)
 157		len += sprintf(buf + len, "%s\n", e->items[i]);
 158
 159	return len;
 160}
 161EXPORT_SYMBOL_GPL(counter_count_enum_available_read);
 162
 163ssize_t counter_device_enum_read(struct counter_device *counter, void *priv,
 164				 char *buf)
 165{
 166	const struct counter_device_enum_ext *const e = priv;
 167	int err;
 168	size_t index;
 169
 170	if (!e->get)
 171		return -EINVAL;
 172
 173	err = e->get(counter, &index);
 174	if (err)
 175		return err;
 176
 177	if (index >= e->num_items)
 178		return -EINVAL;
 179
 180	return sprintf(buf, "%s\n", e->items[index]);
 181}
 182EXPORT_SYMBOL_GPL(counter_device_enum_read);
 183
 184ssize_t counter_device_enum_write(struct counter_device *counter, void *priv,
 185				  const char *buf, size_t len)
 186{
 187	const struct counter_device_enum_ext *const e = priv;
 188	ssize_t index;
 189	int err;
 190
 191	if (!e->set)
 192		return -EINVAL;
 193
 194	index = __sysfs_match_string(e->items, e->num_items, buf);
 195	if (index < 0)
 196		return index;
 197
 198	err = e->set(counter, index);
 199	if (err)
 200		return err;
 201
 202	return len;
 203}
 204EXPORT_SYMBOL_GPL(counter_device_enum_write);
 205
 206ssize_t counter_device_enum_available_read(struct counter_device *counter,
 207					   void *priv, char *buf)
 208{
 209	const struct counter_device_enum_ext *const e = priv;
 210	size_t i;
 211	size_t len = 0;
 212
 213	if (!e->num_items)
 214		return 0;
 215
 216	for (i = 0; i < e->num_items; i++)
 217		len += sprintf(buf + len, "%s\n", e->items[i]);
 218
 219	return len;
 220}
 221EXPORT_SYMBOL_GPL(counter_device_enum_available_read);
 222
 223static const char *const counter_signal_level_str[] = {
 224	[COUNTER_SIGNAL_LEVEL_LOW] = "low",
 225	[COUNTER_SIGNAL_LEVEL_HIGH] = "high"
 226};
 227
 228/**
 229 * counter_signal_read_value_set - set counter_signal_read_value data
 230 * @val:	counter_signal_read_value structure to set
 231 * @type:	property Signal data represents
 232 * @data:	Signal data
 233 *
 234 * This function sets an opaque counter_signal_read_value structure with the
 235 * provided Signal data.
 236 */
 237void counter_signal_read_value_set(struct counter_signal_read_value *const val,
 238				   const enum counter_signal_value_type type,
 239				   void *const data)
 240{
 241	if (type == COUNTER_SIGNAL_LEVEL)
 242		val->len = sprintf(val->buf, "%s\n",
 243				   counter_signal_level_str[*(enum counter_signal_level *)data]);
 244	else
 245		val->len = 0;
 246}
 247EXPORT_SYMBOL_GPL(counter_signal_read_value_set);
 248
 249/**
 250 * counter_count_read_value_set - set counter_count_read_value data
 251 * @val:	counter_count_read_value structure to set
 252 * @type:	property Count data represents
 253 * @data:	Count data
 254 *
 255 * This function sets an opaque counter_count_read_value structure with the
 256 * provided Count data.
 257 */
 258void counter_count_read_value_set(struct counter_count_read_value *const val,
 259				  const enum counter_count_value_type type,
 260				  void *const data)
 261{
 262	switch (type) {
 263	case COUNTER_COUNT_POSITION:
 264		val->len = sprintf(val->buf, "%lu\n", *(unsigned long *)data);
 265		break;
 266	default:
 267		val->len = 0;
 268	}
 269}
 270EXPORT_SYMBOL_GPL(counter_count_read_value_set);
 271
 272/**
 273 * counter_count_write_value_get - get counter_count_write_value data
 274 * @data:	Count data
 275 * @type:	property Count data represents
 276 * @val:	counter_count_write_value structure containing data
 277 *
 278 * This function extracts Count data from the provided opaque
 279 * counter_count_write_value structure and stores it at the address provided by
 280 * @data.
 281 *
 282 * RETURNS:
 283 * 0 on success, negative error number on failure.
 284 */
 285int counter_count_write_value_get(void *const data,
 286				  const enum counter_count_value_type type,
 287				  const struct counter_count_write_value *const val)
 288{
 289	int err;
 290
 291	switch (type) {
 292	case COUNTER_COUNT_POSITION:
 293		err = kstrtoul(val->buf, 0, data);
 294		if (err)
 295			return err;
 296		break;
 297	}
 298
 299	return 0;
 300}
 301EXPORT_SYMBOL_GPL(counter_count_write_value_get);
 302
 303struct counter_attr_parm {
 304	struct counter_device_attr_group *group;
 305	const char *prefix;
 306	const char *name;
 307	ssize_t (*show)(struct device *dev, struct device_attribute *attr,
 308			char *buf);
 309	ssize_t (*store)(struct device *dev, struct device_attribute *attr,
 310			 const char *buf, size_t len);
 311	void *component;
 312};
 313
 314struct counter_device_attr {
 315	struct device_attribute dev_attr;
 316	struct list_head l;
 317	void *component;
 318};
 319
 320static int counter_attribute_create(const struct counter_attr_parm *const parm)
 321{
 322	struct counter_device_attr *counter_attr;
 323	struct device_attribute *dev_attr;
 324	int err;
 325	struct list_head *const attr_list = &parm->group->attr_list;
 326
 327	/* Allocate a Counter device attribute */
 328	counter_attr = kzalloc(sizeof(*counter_attr), GFP_KERNEL);
 329	if (!counter_attr)
 330		return -ENOMEM;
 331	dev_attr = &counter_attr->dev_attr;
 332
 333	sysfs_attr_init(&dev_attr->attr);
 334
 335	/* Configure device attribute */
 336	dev_attr->attr.name = kasprintf(GFP_KERNEL, "%s%s", parm->prefix,
 337					parm->name);
 338	if (!dev_attr->attr.name) {
 339		err = -ENOMEM;
 340		goto err_free_counter_attr;
 341	}
 342	if (parm->show) {
 343		dev_attr->attr.mode |= 0444;
 344		dev_attr->show = parm->show;
 345	}
 346	if (parm->store) {
 347		dev_attr->attr.mode |= 0200;
 348		dev_attr->store = parm->store;
 349	}
 350
 351	/* Store associated Counter component with attribute */
 352	counter_attr->component = parm->component;
 353
 354	/* Keep track of the attribute for later cleanup */
 355	list_add(&counter_attr->l, attr_list);
 356	parm->group->num_attr++;
 357
 358	return 0;
 359
 360err_free_counter_attr:
 361	kfree(counter_attr);
 362	return err;
 363}
 364
 365#define to_counter_attr(_dev_attr) \
 366	container_of(_dev_attr, struct counter_device_attr, dev_attr)
 367
 368struct counter_signal_unit {
 369	struct counter_signal *signal;
 370};
 371
 
 
 
 
 
 372static ssize_t counter_signal_show(struct device *dev,
 373				   struct device_attribute *attr, char *buf)
 374{
 375	struct counter_device *const counter = dev_get_drvdata(dev);
 376	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 377	const struct counter_signal_unit *const component = devattr->component;
 378	struct counter_signal *const signal = component->signal;
 379	int err;
 380	struct counter_signal_read_value val = { .buf = buf };
 381
 382	err = counter->ops->signal_read(counter, signal, &val);
 383	if (err)
 384		return err;
 385
 386	return val.len;
 387}
 388
 389struct counter_name_unit {
 390	const char *name;
 391};
 392
 393static ssize_t counter_device_attr_name_show(struct device *dev,
 394					     struct device_attribute *attr,
 395					     char *buf)
 396{
 397	const struct counter_name_unit *const comp = to_counter_attr(attr)->component;
 398
 399	return sprintf(buf, "%s\n", comp->name);
 400}
 401
 402static int counter_name_attribute_create(
 403	struct counter_device_attr_group *const group,
 404	const char *const name)
 405{
 406	struct counter_name_unit *name_comp;
 407	struct counter_attr_parm parm;
 408	int err;
 409
 410	/* Skip if no name */
 411	if (!name)
 412		return 0;
 413
 414	/* Allocate name attribute component */
 415	name_comp = kmalloc(sizeof(*name_comp), GFP_KERNEL);
 416	if (!name_comp)
 417		return -ENOMEM;
 418	name_comp->name = name;
 419
 420	/* Allocate Signal name attribute */
 421	parm.group = group;
 422	parm.prefix = "";
 423	parm.name = "name";
 424	parm.show = counter_device_attr_name_show;
 425	parm.store = NULL;
 426	parm.component = name_comp;
 427	err = counter_attribute_create(&parm);
 428	if (err)
 429		goto err_free_name_comp;
 430
 431	return 0;
 432
 433err_free_name_comp:
 434	kfree(name_comp);
 435	return err;
 436}
 437
 438struct counter_signal_ext_unit {
 439	struct counter_signal *signal;
 440	const struct counter_signal_ext *ext;
 441};
 442
 443static ssize_t counter_signal_ext_show(struct device *dev,
 444				       struct device_attribute *attr, char *buf)
 445{
 446	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 447	const struct counter_signal_ext_unit *const comp = devattr->component;
 448	const struct counter_signal_ext *const ext = comp->ext;
 449
 450	return ext->read(dev_get_drvdata(dev), comp->signal, ext->priv, buf);
 451}
 452
 453static ssize_t counter_signal_ext_store(struct device *dev,
 454					struct device_attribute *attr,
 455					const char *buf, size_t len)
 456{
 457	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 458	const struct counter_signal_ext_unit *const comp = devattr->component;
 459	const struct counter_signal_ext *const ext = comp->ext;
 460
 461	return ext->write(dev_get_drvdata(dev), comp->signal, ext->priv, buf,
 462		len);
 463}
 464
 465static void counter_device_attr_list_free(struct list_head *attr_list)
 466{
 467	struct counter_device_attr *p, *n;
 468
 469	list_for_each_entry_safe(p, n, attr_list, l) {
 470		/* free attribute name and associated component memory */
 471		kfree(p->dev_attr.attr.name);
 472		kfree(p->component);
 473		list_del(&p->l);
 474		kfree(p);
 475	}
 476}
 477
 478static int counter_signal_ext_register(
 479	struct counter_device_attr_group *const group,
 480	struct counter_signal *const signal)
 481{
 482	const size_t num_ext = signal->num_ext;
 483	size_t i;
 484	const struct counter_signal_ext *ext;
 485	struct counter_signal_ext_unit *signal_ext_comp;
 486	struct counter_attr_parm parm;
 487	int err;
 488
 489	/* Create an attribute for each extension */
 490	for (i = 0 ; i < num_ext; i++) {
 491		ext = signal->ext + i;
 492
 493		/* Allocate signal_ext attribute component */
 494		signal_ext_comp = kmalloc(sizeof(*signal_ext_comp), GFP_KERNEL);
 495		if (!signal_ext_comp) {
 496			err = -ENOMEM;
 497			goto err_free_attr_list;
 498		}
 499		signal_ext_comp->signal = signal;
 500		signal_ext_comp->ext = ext;
 501
 502		/* Allocate a Counter device attribute */
 503		parm.group = group;
 504		parm.prefix = "";
 505		parm.name = ext->name;
 506		parm.show = (ext->read) ? counter_signal_ext_show : NULL;
 507		parm.store = (ext->write) ? counter_signal_ext_store : NULL;
 508		parm.component = signal_ext_comp;
 509		err = counter_attribute_create(&parm);
 510		if (err) {
 511			kfree(signal_ext_comp);
 512			goto err_free_attr_list;
 513		}
 514	}
 515
 516	return 0;
 517
 518err_free_attr_list:
 519	counter_device_attr_list_free(&group->attr_list);
 520	return err;
 521}
 522
 523static int counter_signal_attributes_create(
 524	struct counter_device_attr_group *const group,
 525	const struct counter_device *const counter,
 526	struct counter_signal *const signal)
 527{
 528	struct counter_signal_unit *signal_comp;
 529	struct counter_attr_parm parm;
 530	int err;
 531
 532	/* Allocate Signal attribute component */
 533	signal_comp = kmalloc(sizeof(*signal_comp), GFP_KERNEL);
 534	if (!signal_comp)
 535		return -ENOMEM;
 536	signal_comp->signal = signal;
 537
 538	/* Create main Signal attribute */
 539	parm.group = group;
 540	parm.prefix = "";
 541	parm.name = "signal";
 542	parm.show = (counter->ops->signal_read) ? counter_signal_show : NULL;
 543	parm.store = NULL;
 544	parm.component = signal_comp;
 545	err = counter_attribute_create(&parm);
 546	if (err) {
 547		kfree(signal_comp);
 548		return err;
 549	}
 550
 551	/* Create Signal name attribute */
 552	err = counter_name_attribute_create(group, signal->name);
 553	if (err)
 554		goto err_free_attr_list;
 555
 556	/* Register Signal extension attributes */
 557	err = counter_signal_ext_register(group, signal);
 558	if (err)
 559		goto err_free_attr_list;
 560
 561	return 0;
 562
 563err_free_attr_list:
 564	counter_device_attr_list_free(&group->attr_list);
 565	return err;
 566}
 567
 568static int counter_signals_register(
 569	struct counter_device_attr_group *const groups_list,
 570	const struct counter_device *const counter)
 571{
 572	const size_t num_signals = counter->num_signals;
 573	size_t i;
 574	struct counter_signal *signal;
 575	const char *name;
 576	int err;
 577
 578	/* Register each Signal */
 579	for (i = 0; i < num_signals; i++) {
 580		signal = counter->signals + i;
 581
 582		/* Generate Signal attribute directory name */
 583		name = kasprintf(GFP_KERNEL, "signal%d", signal->id);
 584		if (!name) {
 585			err = -ENOMEM;
 586			goto err_free_attr_groups;
 587		}
 588		groups_list[i].attr_group.name = name;
 589
 590		/* Create all attributes associated with Signal */
 591		err = counter_signal_attributes_create(groups_list + i, counter,
 592						       signal);
 593		if (err)
 594			goto err_free_attr_groups;
 595	}
 596
 597	return 0;
 598
 599err_free_attr_groups:
 600	do {
 601		kfree(groups_list[i].attr_group.name);
 602		counter_device_attr_list_free(&groups_list[i].attr_list);
 603	} while (i--);
 604	return err;
 605}
 606
 607static const char *const counter_synapse_action_str[] = {
 608	[COUNTER_SYNAPSE_ACTION_NONE] = "none",
 609	[COUNTER_SYNAPSE_ACTION_RISING_EDGE] = "rising edge",
 610	[COUNTER_SYNAPSE_ACTION_FALLING_EDGE] = "falling edge",
 611	[COUNTER_SYNAPSE_ACTION_BOTH_EDGES] = "both edges"
 612};
 613
 614struct counter_action_unit {
 615	struct counter_synapse *synapse;
 616	struct counter_count *count;
 617};
 618
 619static ssize_t counter_action_show(struct device *dev,
 620				   struct device_attribute *attr, char *buf)
 621{
 622	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 623	int err;
 624	struct counter_device *const counter = dev_get_drvdata(dev);
 625	const struct counter_action_unit *const component = devattr->component;
 626	struct counter_count *const count = component->count;
 627	struct counter_synapse *const synapse = component->synapse;
 628	size_t action_index;
 629	enum counter_synapse_action action;
 630
 631	err = counter->ops->action_get(counter, count, synapse, &action_index);
 632	if (err)
 633		return err;
 634
 635	synapse->action = action_index;
 636
 637	action = synapse->actions_list[action_index];
 638	return sprintf(buf, "%s\n", counter_synapse_action_str[action]);
 639}
 640
 641static ssize_t counter_action_store(struct device *dev,
 642				    struct device_attribute *attr,
 643				    const char *buf, size_t len)
 644{
 645	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 646	const struct counter_action_unit *const component = devattr->component;
 647	struct counter_synapse *const synapse = component->synapse;
 648	size_t action_index;
 649	const size_t num_actions = synapse->num_actions;
 650	enum counter_synapse_action action;
 651	int err;
 652	struct counter_device *const counter = dev_get_drvdata(dev);
 653	struct counter_count *const count = component->count;
 654
 655	/* Find requested action mode */
 656	for (action_index = 0; action_index < num_actions; action_index++) {
 657		action = synapse->actions_list[action_index];
 658		if (sysfs_streq(buf, counter_synapse_action_str[action]))
 659			break;
 660	}
 661	/* If requested action mode not found */
 662	if (action_index >= num_actions)
 663		return -EINVAL;
 664
 665	err = counter->ops->action_set(counter, count, synapse, action_index);
 666	if (err)
 667		return err;
 668
 669	synapse->action = action_index;
 670
 671	return len;
 672}
 673
 674struct counter_action_avail_unit {
 675	const enum counter_synapse_action *actions_list;
 676	size_t num_actions;
 677};
 678
 679static ssize_t counter_synapse_action_available_show(struct device *dev,
 680	struct device_attribute *attr, char *buf)
 681{
 682	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 683	const struct counter_action_avail_unit *const component = devattr->component;
 684	size_t i;
 685	enum counter_synapse_action action;
 686	ssize_t len = 0;
 687
 688	for (i = 0; i < component->num_actions; i++) {
 689		action = component->actions_list[i];
 690		len += sprintf(buf + len, "%s\n",
 691			       counter_synapse_action_str[action]);
 692	}
 693
 694	return len;
 695}
 696
 697static int counter_synapses_register(
 698	struct counter_device_attr_group *const group,
 699	const struct counter_device *const counter,
 700	struct counter_count *const count, const char *const count_attr_name)
 701{
 702	size_t i;
 703	struct counter_synapse *synapse;
 704	const char *prefix;
 705	struct counter_action_unit *action_comp;
 706	struct counter_attr_parm parm;
 707	int err;
 708	struct counter_action_avail_unit *avail_comp;
 709
 710	/* Register each Synapse */
 711	for (i = 0; i < count->num_synapses; i++) {
 712		synapse = count->synapses + i;
 713
 714		/* Generate attribute prefix */
 715		prefix = kasprintf(GFP_KERNEL, "signal%d_",
 716				   synapse->signal->id);
 717		if (!prefix) {
 718			err = -ENOMEM;
 719			goto err_free_attr_list;
 720		}
 721
 722		/* Allocate action attribute component */
 723		action_comp = kmalloc(sizeof(*action_comp), GFP_KERNEL);
 724		if (!action_comp) {
 725			err = -ENOMEM;
 726			goto err_free_prefix;
 727		}
 728		action_comp->synapse = synapse;
 729		action_comp->count = count;
 730
 731		/* Create action attribute */
 732		parm.group = group;
 733		parm.prefix = prefix;
 734		parm.name = "action";
 735		parm.show = (counter->ops->action_get) ? counter_action_show : NULL;
 736		parm.store = (counter->ops->action_set) ? counter_action_store : NULL;
 737		parm.component = action_comp;
 738		err = counter_attribute_create(&parm);
 739		if (err) {
 740			kfree(action_comp);
 741			goto err_free_prefix;
 742		}
 743
 744		/* Allocate action available attribute component */
 745		avail_comp = kmalloc(sizeof(*avail_comp), GFP_KERNEL);
 746		if (!avail_comp) {
 747			err = -ENOMEM;
 748			goto err_free_prefix;
 749		}
 750		avail_comp->actions_list = synapse->actions_list;
 751		avail_comp->num_actions = synapse->num_actions;
 752
 753		/* Create action_available attribute */
 754		parm.group = group;
 755		parm.prefix = prefix;
 756		parm.name = "action_available";
 757		parm.show = counter_synapse_action_available_show;
 758		parm.store = NULL;
 759		parm.component = avail_comp;
 760		err = counter_attribute_create(&parm);
 761		if (err) {
 762			kfree(avail_comp);
 763			goto err_free_prefix;
 764		}
 765
 766		kfree(prefix);
 767	}
 768
 769	return 0;
 770
 771err_free_prefix:
 772	kfree(prefix);
 773err_free_attr_list:
 774	counter_device_attr_list_free(&group->attr_list);
 775	return err;
 776}
 777
 778struct counter_count_unit {
 779	struct counter_count *count;
 780};
 781
 782static ssize_t counter_count_show(struct device *dev,
 783				  struct device_attribute *attr,
 784				  char *buf)
 785{
 786	struct counter_device *const counter = dev_get_drvdata(dev);
 787	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 788	const struct counter_count_unit *const component = devattr->component;
 789	struct counter_count *const count = component->count;
 790	int err;
 791	struct counter_count_read_value val = { .buf = buf };
 792
 793	err = counter->ops->count_read(counter, count, &val);
 794	if (err)
 795		return err;
 796
 797	return val.len;
 798}
 799
 800static ssize_t counter_count_store(struct device *dev,
 801				   struct device_attribute *attr,
 802				   const char *buf, size_t len)
 803{
 804	struct counter_device *const counter = dev_get_drvdata(dev);
 805	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 806	const struct counter_count_unit *const component = devattr->component;
 807	struct counter_count *const count = component->count;
 808	int err;
 809	struct counter_count_write_value val = { .buf = buf };
 
 
 
 
 810
 811	err = counter->ops->count_write(counter, count, &val);
 812	if (err)
 813		return err;
 814
 815	return len;
 816}
 817
 818static const char *const counter_count_function_str[] = {
 819	[COUNTER_COUNT_FUNCTION_INCREASE] = "increase",
 820	[COUNTER_COUNT_FUNCTION_DECREASE] = "decrease",
 821	[COUNTER_COUNT_FUNCTION_PULSE_DIRECTION] = "pulse-direction",
 822	[COUNTER_COUNT_FUNCTION_QUADRATURE_X1_A] = "quadrature x1 a",
 823	[COUNTER_COUNT_FUNCTION_QUADRATURE_X1_B] = "quadrature x1 b",
 824	[COUNTER_COUNT_FUNCTION_QUADRATURE_X2_A] = "quadrature x2 a",
 825	[COUNTER_COUNT_FUNCTION_QUADRATURE_X2_B] = "quadrature x2 b",
 826	[COUNTER_COUNT_FUNCTION_QUADRATURE_X4] = "quadrature x4"
 827};
 828
 829static ssize_t counter_function_show(struct device *dev,
 830				     struct device_attribute *attr, char *buf)
 831{
 832	int err;
 833	struct counter_device *const counter = dev_get_drvdata(dev);
 834	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 835	const struct counter_count_unit *const component = devattr->component;
 836	struct counter_count *const count = component->count;
 837	size_t func_index;
 838	enum counter_count_function function;
 839
 840	err = counter->ops->function_get(counter, count, &func_index);
 841	if (err)
 842		return err;
 843
 844	count->function = func_index;
 845
 846	function = count->functions_list[func_index];
 847	return sprintf(buf, "%s\n", counter_count_function_str[function]);
 848}
 849
 850static ssize_t counter_function_store(struct device *dev,
 851				      struct device_attribute *attr,
 852				      const char *buf, size_t len)
 853{
 854	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 855	const struct counter_count_unit *const component = devattr->component;
 856	struct counter_count *const count = component->count;
 857	const size_t num_functions = count->num_functions;
 858	size_t func_index;
 859	enum counter_count_function function;
 860	int err;
 861	struct counter_device *const counter = dev_get_drvdata(dev);
 862
 863	/* Find requested Count function mode */
 864	for (func_index = 0; func_index < num_functions; func_index++) {
 865		function = count->functions_list[func_index];
 866		if (sysfs_streq(buf, counter_count_function_str[function]))
 867			break;
 868	}
 869	/* Return error if requested Count function mode not found */
 870	if (func_index >= num_functions)
 871		return -EINVAL;
 872
 873	err = counter->ops->function_set(counter, count, func_index);
 874	if (err)
 875		return err;
 876
 877	count->function = func_index;
 878
 879	return len;
 880}
 881
 882struct counter_count_ext_unit {
 883	struct counter_count *count;
 884	const struct counter_count_ext *ext;
 885};
 886
 887static ssize_t counter_count_ext_show(struct device *dev,
 888				      struct device_attribute *attr, char *buf)
 889{
 890	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 891	const struct counter_count_ext_unit *const comp = devattr->component;
 892	const struct counter_count_ext *const ext = comp->ext;
 893
 894	return ext->read(dev_get_drvdata(dev), comp->count, ext->priv, buf);
 895}
 896
 897static ssize_t counter_count_ext_store(struct device *dev,
 898				       struct device_attribute *attr,
 899				       const char *buf, size_t len)
 900{
 901	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 902	const struct counter_count_ext_unit *const comp = devattr->component;
 903	const struct counter_count_ext *const ext = comp->ext;
 904
 905	return ext->write(dev_get_drvdata(dev), comp->count, ext->priv, buf,
 906		len);
 907}
 908
 909static int counter_count_ext_register(
 910	struct counter_device_attr_group *const group,
 911	struct counter_count *const count)
 912{
 913	size_t i;
 914	const struct counter_count_ext *ext;
 915	struct counter_count_ext_unit *count_ext_comp;
 916	struct counter_attr_parm parm;
 917	int err;
 918
 919	/* Create an attribute for each extension */
 920	for (i = 0 ; i < count->num_ext; i++) {
 921		ext = count->ext + i;
 922
 923		/* Allocate count_ext attribute component */
 924		count_ext_comp = kmalloc(sizeof(*count_ext_comp), GFP_KERNEL);
 925		if (!count_ext_comp) {
 926			err = -ENOMEM;
 927			goto err_free_attr_list;
 928		}
 929		count_ext_comp->count = count;
 930		count_ext_comp->ext = ext;
 931
 932		/* Allocate count_ext attribute */
 933		parm.group = group;
 934		parm.prefix = "";
 935		parm.name = ext->name;
 936		parm.show = (ext->read) ? counter_count_ext_show : NULL;
 937		parm.store = (ext->write) ? counter_count_ext_store : NULL;
 938		parm.component = count_ext_comp;
 939		err = counter_attribute_create(&parm);
 940		if (err) {
 941			kfree(count_ext_comp);
 942			goto err_free_attr_list;
 943		}
 944	}
 945
 946	return 0;
 947
 948err_free_attr_list:
 949	counter_device_attr_list_free(&group->attr_list);
 950	return err;
 951}
 952
 953struct counter_func_avail_unit {
 954	const enum counter_count_function *functions_list;
 955	size_t num_functions;
 956};
 957
 958static ssize_t counter_count_function_available_show(struct device *dev,
 959	struct device_attribute *attr, char *buf)
 960{
 961	const struct counter_device_attr *const devattr = to_counter_attr(attr);
 962	const struct counter_func_avail_unit *const component = devattr->component;
 963	const enum counter_count_function *const func_list = component->functions_list;
 964	const size_t num_functions = component->num_functions;
 965	size_t i;
 966	enum counter_count_function function;
 967	ssize_t len = 0;
 968
 969	for (i = 0; i < num_functions; i++) {
 970		function = func_list[i];
 971		len += sprintf(buf + len, "%s\n",
 972			       counter_count_function_str[function]);
 973	}
 974
 975	return len;
 976}
 977
 978static int counter_count_attributes_create(
 979	struct counter_device_attr_group *const group,
 980	const struct counter_device *const counter,
 981	struct counter_count *const count)
 982{
 983	struct counter_count_unit *count_comp;
 984	struct counter_attr_parm parm;
 985	int err;
 986	struct counter_count_unit *func_comp;
 987	struct counter_func_avail_unit *avail_comp;
 988
 989	/* Allocate count attribute component */
 990	count_comp = kmalloc(sizeof(*count_comp), GFP_KERNEL);
 991	if (!count_comp)
 992		return -ENOMEM;
 993	count_comp->count = count;
 994
 995	/* Create main Count attribute */
 996	parm.group = group;
 997	parm.prefix = "";
 998	parm.name = "count";
 999	parm.show = (counter->ops->count_read) ? counter_count_show : NULL;
1000	parm.store = (counter->ops->count_write) ? counter_count_store : NULL;
1001	parm.component = count_comp;
1002	err = counter_attribute_create(&parm);
1003	if (err) {
1004		kfree(count_comp);
1005		return err;
1006	}
1007
1008	/* Allocate function attribute component */
1009	func_comp = kmalloc(sizeof(*func_comp), GFP_KERNEL);
1010	if (!func_comp) {
1011		err = -ENOMEM;
1012		goto err_free_attr_list;
1013	}
1014	func_comp->count = count;
1015
1016	/* Create Count function attribute */
1017	parm.group = group;
1018	parm.prefix = "";
1019	parm.name = "function";
1020	parm.show = (counter->ops->function_get) ? counter_function_show : NULL;
1021	parm.store = (counter->ops->function_set) ? counter_function_store : NULL;
1022	parm.component = func_comp;
1023	err = counter_attribute_create(&parm);
1024	if (err) {
1025		kfree(func_comp);
1026		goto err_free_attr_list;
1027	}
1028
1029	/* Allocate function available attribute component */
1030	avail_comp = kmalloc(sizeof(*avail_comp), GFP_KERNEL);
1031	if (!avail_comp) {
1032		err = -ENOMEM;
1033		goto err_free_attr_list;
1034	}
1035	avail_comp->functions_list = count->functions_list;
1036	avail_comp->num_functions = count->num_functions;
1037
1038	/* Create Count function_available attribute */
1039	parm.group = group;
1040	parm.prefix = "";
1041	parm.name = "function_available";
1042	parm.show = counter_count_function_available_show;
1043	parm.store = NULL;
1044	parm.component = avail_comp;
1045	err = counter_attribute_create(&parm);
1046	if (err) {
1047		kfree(avail_comp);
1048		goto err_free_attr_list;
1049	}
1050
1051	/* Create Count name attribute */
1052	err = counter_name_attribute_create(group, count->name);
1053	if (err)
1054		goto err_free_attr_list;
1055
1056	/* Register Count extension attributes */
1057	err = counter_count_ext_register(group, count);
1058	if (err)
1059		goto err_free_attr_list;
1060
1061	return 0;
1062
1063err_free_attr_list:
1064	counter_device_attr_list_free(&group->attr_list);
1065	return err;
1066}
1067
1068static int counter_counts_register(
1069	struct counter_device_attr_group *const groups_list,
1070	const struct counter_device *const counter)
1071{
1072	size_t i;
1073	struct counter_count *count;
1074	const char *name;
1075	int err;
1076
1077	/* Register each Count */
1078	for (i = 0; i < counter->num_counts; i++) {
1079		count = counter->counts + i;
1080
1081		/* Generate Count attribute directory name */
1082		name = kasprintf(GFP_KERNEL, "count%d", count->id);
1083		if (!name) {
1084			err = -ENOMEM;
1085			goto err_free_attr_groups;
1086		}
1087		groups_list[i].attr_group.name = name;
1088
1089		/* Register the Synapses associated with each Count */
1090		err = counter_synapses_register(groups_list + i, counter, count,
1091						name);
1092		if (err)
1093			goto err_free_attr_groups;
1094
1095		/* Create all attributes associated with Count */
1096		err = counter_count_attributes_create(groups_list + i, counter,
1097						      count);
1098		if (err)
1099			goto err_free_attr_groups;
1100	}
1101
1102	return 0;
1103
1104err_free_attr_groups:
1105	do {
1106		kfree(groups_list[i].attr_group.name);
1107		counter_device_attr_list_free(&groups_list[i].attr_list);
1108	} while (i--);
1109	return err;
1110}
1111
1112struct counter_size_unit {
1113	size_t size;
1114};
1115
1116static ssize_t counter_device_attr_size_show(struct device *dev,
1117					     struct device_attribute *attr,
1118					     char *buf)
1119{
1120	const struct counter_size_unit *const comp = to_counter_attr(attr)->component;
1121
1122	return sprintf(buf, "%zu\n", comp->size);
1123}
1124
1125static int counter_size_attribute_create(
1126	struct counter_device_attr_group *const group,
1127	const size_t size, const char *const name)
1128{
1129	struct counter_size_unit *size_comp;
1130	struct counter_attr_parm parm;
1131	int err;
1132
1133	/* Allocate size attribute component */
1134	size_comp = kmalloc(sizeof(*size_comp), GFP_KERNEL);
1135	if (!size_comp)
1136		return -ENOMEM;
1137	size_comp->size = size;
1138
1139	parm.group = group;
1140	parm.prefix = "";
1141	parm.name = name;
1142	parm.show = counter_device_attr_size_show;
1143	parm.store = NULL;
1144	parm.component = size_comp;
1145	err = counter_attribute_create(&parm);
1146	if (err)
1147		goto err_free_size_comp;
1148
1149	return 0;
1150
1151err_free_size_comp:
1152	kfree(size_comp);
1153	return err;
1154}
1155
1156struct counter_ext_unit {
1157	const struct counter_device_ext *ext;
1158};
1159
1160static ssize_t counter_device_ext_show(struct device *dev,
1161				       struct device_attribute *attr, char *buf)
1162{
1163	const struct counter_device_attr *const devattr = to_counter_attr(attr);
1164	const struct counter_ext_unit *const component = devattr->component;
1165	const struct counter_device_ext *const ext = component->ext;
1166
1167	return ext->read(dev_get_drvdata(dev), ext->priv, buf);
1168}
1169
1170static ssize_t counter_device_ext_store(struct device *dev,
1171					struct device_attribute *attr,
1172					const char *buf, size_t len)
1173{
1174	const struct counter_device_attr *const devattr = to_counter_attr(attr);
1175	const struct counter_ext_unit *const component = devattr->component;
1176	const struct counter_device_ext *const ext = component->ext;
1177
1178	return ext->write(dev_get_drvdata(dev), ext->priv, buf, len);
1179}
1180
1181static int counter_device_ext_register(
1182	struct counter_device_attr_group *const group,
1183	struct counter_device *const counter)
1184{
1185	size_t i;
1186	struct counter_ext_unit *ext_comp;
1187	struct counter_attr_parm parm;
1188	int err;
1189
1190	/* Create an attribute for each extension */
1191	for (i = 0 ; i < counter->num_ext; i++) {
1192		/* Allocate extension attribute component */
1193		ext_comp = kmalloc(sizeof(*ext_comp), GFP_KERNEL);
1194		if (!ext_comp) {
1195			err = -ENOMEM;
1196			goto err_free_attr_list;
1197		}
1198
1199		ext_comp->ext = counter->ext + i;
1200
1201		/* Allocate extension attribute */
1202		parm.group = group;
1203		parm.prefix = "";
1204		parm.name = counter->ext[i].name;
1205		parm.show = (counter->ext[i].read) ? counter_device_ext_show : NULL;
1206		parm.store = (counter->ext[i].write) ? counter_device_ext_store : NULL;
1207		parm.component = ext_comp;
1208		err = counter_attribute_create(&parm);
1209		if (err) {
1210			kfree(ext_comp);
1211			goto err_free_attr_list;
1212		}
1213	}
1214
1215	return 0;
1216
1217err_free_attr_list:
1218	counter_device_attr_list_free(&group->attr_list);
1219	return err;
1220}
1221
1222static int counter_global_attr_register(
1223	struct counter_device_attr_group *const group,
1224	struct counter_device *const counter)
1225{
1226	int err;
1227
1228	/* Create name attribute */
1229	err = counter_name_attribute_create(group, counter->name);
1230	if (err)
1231		return err;
1232
1233	/* Create num_counts attribute */
1234	err = counter_size_attribute_create(group, counter->num_counts,
1235					    "num_counts");
1236	if (err)
1237		goto err_free_attr_list;
1238
1239	/* Create num_signals attribute */
1240	err = counter_size_attribute_create(group, counter->num_signals,
1241					    "num_signals");
1242	if (err)
1243		goto err_free_attr_list;
1244
1245	/* Register Counter device extension attributes */
1246	err = counter_device_ext_register(group, counter);
1247	if (err)
1248		goto err_free_attr_list;
1249
1250	return 0;
1251
1252err_free_attr_list:
1253	counter_device_attr_list_free(&group->attr_list);
1254	return err;
1255}
1256
1257static void counter_device_groups_list_free(
1258	struct counter_device_attr_group *const groups_list,
1259	const size_t num_groups)
1260{
1261	struct counter_device_attr_group *group;
1262	size_t i;
1263
1264	/* loop through all attribute groups (signals, counts, global, etc.) */
1265	for (i = 0; i < num_groups; i++) {
1266		group = groups_list + i;
1267
1268		/* free all attribute group and associated attributes memory */
1269		kfree(group->attr_group.name);
1270		kfree(group->attr_group.attrs);
1271		counter_device_attr_list_free(&group->attr_list);
1272	}
1273
1274	kfree(groups_list);
1275}
1276
1277static int counter_device_groups_list_prepare(
1278	struct counter_device *const counter)
1279{
1280	const size_t total_num_groups =
1281		counter->num_signals + counter->num_counts + 1;
1282	struct counter_device_attr_group *groups_list;
1283	size_t i;
1284	int err;
1285	size_t num_groups = 0;
1286
1287	/* Allocate space for attribute groups (signals, counts, and ext) */
1288	groups_list = kcalloc(total_num_groups, sizeof(*groups_list),
1289			      GFP_KERNEL);
1290	if (!groups_list)
1291		return -ENOMEM;
1292
1293	/* Initialize attribute lists */
1294	for (i = 0; i < total_num_groups; i++)
1295		INIT_LIST_HEAD(&groups_list[i].attr_list);
1296
1297	/* Register Signals */
1298	err = counter_signals_register(groups_list, counter);
1299	if (err)
1300		goto err_free_groups_list;
1301	num_groups += counter->num_signals;
1302
1303	/* Register Counts and respective Synapses */
1304	err = counter_counts_register(groups_list + num_groups, counter);
1305	if (err)
1306		goto err_free_groups_list;
1307	num_groups += counter->num_counts;
1308
1309	/* Register Counter global attributes */
1310	err = counter_global_attr_register(groups_list + num_groups, counter);
1311	if (err)
1312		goto err_free_groups_list;
1313	num_groups++;
1314
1315	/* Store groups_list in device_state */
1316	counter->device_state->groups_list = groups_list;
1317	counter->device_state->num_groups = num_groups;
1318
1319	return 0;
1320
1321err_free_groups_list:
1322	counter_device_groups_list_free(groups_list, num_groups);
1323	return err;
1324}
1325
1326static int counter_device_groups_prepare(
1327	struct counter_device_state *const device_state)
1328{
1329	size_t i, j;
1330	struct counter_device_attr_group *group;
1331	int err;
1332	struct counter_device_attr *p;
1333
1334	/* Allocate attribute groups for association with device */
1335	device_state->groups = kcalloc(device_state->num_groups + 1,
1336				       sizeof(*device_state->groups),
1337				       GFP_KERNEL);
1338	if (!device_state->groups)
1339		return -ENOMEM;
1340
1341	/* Prepare each group of attributes for association */
1342	for (i = 0; i < device_state->num_groups; i++) {
1343		group = device_state->groups_list + i;
1344
1345		/* Allocate space for attribute pointers in attribute group */
1346		group->attr_group.attrs = kcalloc(group->num_attr + 1,
1347			sizeof(*group->attr_group.attrs), GFP_KERNEL);
1348		if (!group->attr_group.attrs) {
1349			err = -ENOMEM;
1350			goto err_free_groups;
1351		}
1352
1353		/* Add attribute pointers to attribute group */
1354		j = 0;
1355		list_for_each_entry(p, &group->attr_list, l)
1356			group->attr_group.attrs[j++] = &p->dev_attr.attr;
1357
1358		/* Group attributes in attribute group */
1359		device_state->groups[i] = &group->attr_group;
1360	}
1361	/* Associate attributes with device */
1362	device_state->dev.groups = device_state->groups;
1363
1364	return 0;
1365
1366err_free_groups:
1367	do {
1368		group = device_state->groups_list + i;
1369		kfree(group->attr_group.attrs);
1370		group->attr_group.attrs = NULL;
1371	} while (i--);
1372	kfree(device_state->groups);
1373	return err;
1374}
1375
1376/* Provides a unique ID for each counter device */
1377static DEFINE_IDA(counter_ida);
1378
1379static void counter_device_release(struct device *dev)
1380{
1381	struct counter_device *const counter = dev_get_drvdata(dev);
1382	struct counter_device_state *const device_state = counter->device_state;
1383
1384	kfree(device_state->groups);
1385	counter_device_groups_list_free(device_state->groups_list,
1386					device_state->num_groups);
1387	ida_simple_remove(&counter_ida, device_state->id);
1388	kfree(device_state);
1389}
1390
1391static struct device_type counter_device_type = {
1392	.name = "counter_device",
1393	.release = counter_device_release
1394};
1395
1396static struct bus_type counter_bus_type = {
1397	.name = "counter"
1398};
1399
1400/**
1401 * counter_register - register Counter to the system
1402 * @counter:	pointer to Counter to register
1403 *
1404 * This function registers a Counter to the system. A sysfs "counter" directory
1405 * will be created and populated with sysfs attributes correlating with the
1406 * Counter Signals, Synapses, and Counts respectively.
1407 */
1408int counter_register(struct counter_device *const counter)
1409{
1410	struct counter_device_state *device_state;
1411	int err;
1412
1413	/* Allocate internal state container for Counter device */
1414	device_state = kzalloc(sizeof(*device_state), GFP_KERNEL);
1415	if (!device_state)
1416		return -ENOMEM;
1417	counter->device_state = device_state;
1418
1419	/* Acquire unique ID */
1420	device_state->id = ida_simple_get(&counter_ida, 0, 0, GFP_KERNEL);
1421	if (device_state->id < 0) {
1422		err = device_state->id;
1423		goto err_free_device_state;
1424	}
1425
1426	/* Configure device structure for Counter */
1427	device_state->dev.type = &counter_device_type;
1428	device_state->dev.bus = &counter_bus_type;
1429	if (counter->parent) {
1430		device_state->dev.parent = counter->parent;
1431		device_state->dev.of_node = counter->parent->of_node;
1432	}
1433	dev_set_name(&device_state->dev, "counter%d", device_state->id);
1434	device_initialize(&device_state->dev);
1435	dev_set_drvdata(&device_state->dev, counter);
1436
1437	/* Prepare device attributes */
1438	err = counter_device_groups_list_prepare(counter);
1439	if (err)
1440		goto err_free_id;
1441
1442	/* Organize device attributes to groups and match to device */
1443	err = counter_device_groups_prepare(device_state);
1444	if (err)
1445		goto err_free_groups_list;
1446
1447	/* Add device to system */
1448	err = device_add(&device_state->dev);
1449	if (err)
1450		goto err_free_groups;
1451
1452	return 0;
1453
1454err_free_groups:
1455	kfree(device_state->groups);
1456err_free_groups_list:
1457	counter_device_groups_list_free(device_state->groups_list,
1458					device_state->num_groups);
1459err_free_id:
1460	ida_simple_remove(&counter_ida, device_state->id);
1461err_free_device_state:
1462	kfree(device_state);
1463	return err;
1464}
1465EXPORT_SYMBOL_GPL(counter_register);
1466
1467/**
1468 * counter_unregister - unregister Counter from the system
1469 * @counter:	pointer to Counter to unregister
1470 *
1471 * The Counter is unregistered from the system; all allocated memory is freed.
1472 */
1473void counter_unregister(struct counter_device *const counter)
1474{
1475	if (counter)
1476		device_del(&counter->device_state->dev);
1477}
1478EXPORT_SYMBOL_GPL(counter_unregister);
1479
1480static void devm_counter_unreg(struct device *dev, void *res)
1481{
1482	counter_unregister(*(struct counter_device **)res);
1483}
1484
1485/**
1486 * devm_counter_register - Resource-managed counter_register
1487 * @dev:	device to allocate counter_device for
1488 * @counter:	pointer to Counter to register
1489 *
1490 * Managed counter_register. The Counter registered with this function is
1491 * automatically unregistered on driver detach. This function calls
1492 * counter_register internally. Refer to that function for more information.
1493 *
1494 * If an Counter registered with this function needs to be unregistered
1495 * separately, devm_counter_unregister must be used.
1496 *
1497 * RETURNS:
1498 * 0 on success, negative error number on failure.
1499 */
1500int devm_counter_register(struct device *dev,
1501			  struct counter_device *const counter)
1502{
1503	struct counter_device **ptr;
1504	int ret;
1505
1506	ptr = devres_alloc(devm_counter_unreg, sizeof(*ptr), GFP_KERNEL);
1507	if (!ptr)
1508		return -ENOMEM;
1509
1510	ret = counter_register(counter);
1511	if (!ret) {
1512		*ptr = counter;
1513		devres_add(dev, ptr);
1514	} else {
1515		devres_free(ptr);
1516	}
1517
1518	return ret;
1519}
1520EXPORT_SYMBOL_GPL(devm_counter_register);
1521
1522static int devm_counter_match(struct device *dev, void *res, void *data)
1523{
1524	struct counter_device **r = res;
1525
1526	if (!r || !*r) {
1527		WARN_ON(!r || !*r);
1528		return 0;
1529	}
1530
1531	return *r == data;
1532}
1533
1534/**
1535 * devm_counter_unregister - Resource-managed counter_unregister
1536 * @dev:	device this counter_device belongs to
1537 * @counter:	pointer to Counter associated with the device
1538 *
1539 * Unregister Counter registered with devm_counter_register.
1540 */
1541void devm_counter_unregister(struct device *dev,
1542			     struct counter_device *const counter)
1543{
1544	int rc;
1545
1546	rc = devres_release(dev, devm_counter_unreg, devm_counter_match,
1547			    counter);
1548	WARN_ON(rc);
1549}
1550EXPORT_SYMBOL_GPL(devm_counter_unregister);
1551
1552static int __init counter_init(void)
1553{
1554	return bus_register(&counter_bus_type);
1555}
1556
1557static void __exit counter_exit(void)
1558{
1559	bus_unregister(&counter_bus_type);
1560}
1561
1562subsys_initcall(counter_init);
1563module_exit(counter_exit);
1564
1565MODULE_AUTHOR("William Breathitt Gray <vilhelm.gray@gmail.com>");
1566MODULE_DESCRIPTION("Generic Counter interface");
1567MODULE_LICENSE("GPL v2");