summaryrefslogtreecommitdiffstats
path: root/arch/arm/boards/zii-common/pn-fixup.h
blob: 39b848bd00d3d6f8296caffa2563b8c7d970f89d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/*
 * Copyright (C) 2019 Zodiac Inflight Innovation
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 */

#ifndef __ZII_PN_FIXUP__
#define __ZII_PN_FIXUP__

struct zii_pn_fixup {
	const char *pn;
	void (*callback) (const struct zii_pn_fixup *fixup);
};

char *zii_read_part_number(const char *, size_t);
/**
 * __zii_process_fixups - Process array of ZII part number based fixups
 *
 * @__fixups: Array of part number base fixups
 * @__cell_name: Name of the NVMEM cell containing the part number
 * @__cell_size: Size of the NVMEM cell containing the part number
 *
 * NOTE: Keeping this code as a marcro allows us to avoid restricting
 * the type of __fixups to an array of struct zii_pn_fixup. This is
 * really convenient becuase it allows us to do things like
 *
 * struct zii_foo_fixup {
 * 	struct zii_pn_fixup parent;
 *	type1 custom_field_1
 *	type2 custom_field_2
 *      ...
 * };
 *
 * ...
 *
 * const struct zii_foo_fixup foo_fixups[] = {
 * 	{ fixup1 },
 * 	{ fixup2 },
 * 	{ fixup3 },
 * };
 *
 * ...
 *
 * __zii_process_fixups(foo_fixups, "blah", BLAH_LENGTH);
 *
 * which allows us to have the most compact definition of array of
 * fixups
 */
#define __zii_process_fixups(__fixups, __cell_name, __cell_size)	\
	do {								\
		char *__pn = zii_read_part_number(__cell_name,		\
						  __cell_size);		\
		const struct zii_pn_fixup *__fixup;			\
		unsigned int __i;					\
		bool __match_found = false;				\
									\
		if (WARN_ON(IS_ERR(__pn)))				\
			break;						\
									\
		for (__i = 0; __i < ARRAY_SIZE(__fixups); __i++) {	\
			__fixup =					\
			  (const struct zii_pn_fixup *) &__fixups[__i]; \
									\
			if (strstr(__pn, __fixup->pn)) {		\
				pr_debug("%s->%pS\n", __func__,		\
					 __fixup->callback);		\
				__match_found = true;			\
				__fixup->callback(__fixup);		\
			}						\
		}							\
		if (!__match_found)					\
			pr_err("No config fixups found for P/N %s!\n", __pn); \
		free(__pn);						\
	} while (0)

#define DDS_PART_NUMBER_SIZE	15
#define LRU_PART_NUMBER_SIZE	15

#define zii_process_dds_fixups(_fixups)		\
	__zii_process_fixups(_fixups, "dds-part-number", DDS_PART_NUMBER_SIZE)

#define zii_process_lru_fixups(_fixups)		\
	__zii_process_fixups(_fixups, "lru-part-number", LRU_PART_NUMBER_SIZE)

#endif	/* __ZII_PN_FIXUP__ */