aboutsummaryrefslogtreecommitdiff
path: root/include/dm/device_compat.h
blob: 8f26053b450d738cc2a6aba09f012ea9f5e52689 (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
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Copyright (C) 2020 Sean Anderson <seanga2@gmail.com>
 * Copyright (c) 2013 Google, Inc
 *
 * (C) Copyright 2012
 * Pavel Herrmann <morpheus.ibis@gmail.com>
 * Marek Vasut <marex@denx.de>
 */

#ifndef _DM_DEVICE_COMPAT_H
#define _DM_DEVICE_COMPAT_H

#include <log.h>
#include <linux/build_bug.h>
#include <linux/compat.h>

/*
 * REVISIT:
 * remove the following after resolving conflicts with <linux/compat.h>
 */
#ifdef dev_dbg
#undef dev_dbg
#endif
#ifdef dev_vdbg
#undef dev_vdbg
#endif
#ifdef dev_info
#undef dev_info
#endif
#ifdef dev_err
#undef dev_err
#endif
#ifdef dev_warn
#undef dev_warn
#endif

/*
 * Define a new identifier which can be tested on by C code. A similar
 * definition is made for DEBUG in <log.h>.
 */
#ifdef VERBOSE_DEBUG
#define _VERBOSE_DEBUG 1
#else
#define _VERBOSE_DEBUG 0
#endif

/**
 * dev_printk_emit() - Emit a formatted log message
 * @cat: Category of the message
 * @level: Log level of the message
 * @fmt: Format string
 * @...: Arguments for @fmt
 *
 * This macro logs a message through the appropriate channel. It is a macro so
 * the if statements can be optimized out (as @level should be a constant known
 * at compile-time).
 *
 * If DEBUG or VERBOSE_DEBUG is defined, then some messages are always printed
 * (through printf()). This is to match the historical behavior of the dev_xxx
 * functions.
 *
 * If LOG is enabled, use log() to emit the message, otherwise print it based on
 * the console loglevel.
 */
#define dev_printk_emit(cat, level, fmt, ...) \
({ \
	if ((_DEBUG && level == LOGL_DEBUG) || \
	    (_VERBOSE_DEBUG && level == LOGL_DEBUG_CONTENT)) \
		printf(fmt, ##__VA_ARGS__); \
	else if (CONFIG_IS_ENABLED(LOG)) \
		log(cat, level, fmt, ##__VA_ARGS__); \
	else if (level < CONFIG_VAL(LOGLEVEL)) \
		printf(fmt, ##__VA_ARGS__); \
})

/**
 * __dev_printk() - Log a message for a device
 * @level: Log level of the message
 * @dev: A &struct udevice or &struct device
 * @fmt: Format string
 * @...: Arguments for @fmt
 *
 * This macro formats and prints dev_xxx log messages. It is done as a macro
 * because working with variadic argument is much easier this way, we can
 * interrogate the type of device we are passed (and whether it *is* a &struct
 * udevice or &struct device), and dev_printk_emit() can optimize out unused if
 * branches.
 *
 * Because this is a macro, we must enforce type checks ourselves. Ideally, we
 * would only accept udevices, but there is a significant amount of code (mostly
 * USB) which calls dev_xxx with &struct device. When assigning ``__dev``, we
 * must first cast ``dev`` to ``void *`` so we don't get warned when ``dev`` is
 * a &struct device. Even though the latter branch is not taken, it will still
 * get compiled and type-checked.
 *
 * The format strings in case of a ``NULL`` ``dev`` MUST be kept the same.
 * Otherwise, @fmt will be duplicated in the data section (with slightly
 * different prefixes). This is why ``(NULL udevice *)`` is printed as two
 * string arguments, and not by string pasting.
 */
#define __dev_printk(level, dev, fmt, ...) \
({ \
	if (__same_type(dev, struct device  *)) { \
		dev_printk_emit(LOG_CATEGORY, level, fmt, ##__VA_ARGS__); \
	} else { \
		BUILD_BUG_ON(!__same_type(dev, struct udevice *)); \
		struct udevice *__dev = (void *)dev; \
		if (__dev) \
			dev_printk_emit(__dev->driver->id, level, \
					"%s %s: " fmt, \
					__dev->driver->name, __dev->name, \
					##__VA_ARGS__); \
		else \
			dev_printk_emit(LOG_CATEGORY, level, \
					"%s %s: " fmt, \
					"(NULL", "udevice *)", \
					##__VA_ARGS__); \
	} \
})

#define dev_emerg(dev, fmt, ...) \
	__dev_printk(LOGL_EMERG, dev, fmt, ##__VA_ARGS__)
#define dev_alert(dev, fmt, ...) \
	__dev_printk(LOGL_ALERT, dev, fmt, ##__VA_ARGS__)
#define dev_crit(dev, fmt, ...) \
	__dev_printk(LOGL_CRIT, dev, fmt, ##__VA_ARGS__)
#define dev_err(dev, fmt, ...) \
	__dev_printk(LOGL_ERR, dev, fmt, ##__VA_ARGS__)
#define dev_warn(dev, fmt, ...) \
	__dev_printk(LOGL_WARNING, dev, fmt, ##__VA_ARGS__)
#define dev_notice(dev, fmt, ...) \
	__dev_printk(LOGL_NOTICE, dev, fmt, ##__VA_ARGS__)
#define dev_info(dev, fmt, ...) \
	__dev_printk(LOGL_INFO, dev, fmt, ##__VA_ARGS__)
#define dev_dbg(dev, fmt, ...) \
	__dev_printk(LOGL_DEBUG, dev, fmt, ##__VA_ARGS__)
#define dev_vdbg(dev, fmt, ...) \
	__dev_printk(LOGL_DEBUG_CONTENT, dev, fmt, ##__VA_ARGS__)

#endif