• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * System devices follow a slightly different driver model.
3  * They don't need to do dynammic driver binding, can't be probed,
4  * and don't reside on any type of peripheral bus.
5  * So, we represent and treat them a little differently.
6  *
7  * We still have a notion of a driver for a system device, because we still
8  * want to perform basic operations on these devices.
9  *
10  * We also support auxillary drivers binding to devices of a certain class.
11  *
12  * This allows configurable drivers to register themselves for devices of
13  * a certain type. And, it allows class definitions to reside in generic
14  * code while arch-specific code can register specific drivers.
15  *
16  * Auxillary drivers registered with a NULL cls are registered as drivers
17  * for all system devices, and get notification calls for each device.
18  */
19 
20 
21 #ifndef _SYSDEV_H_
22 #define _SYSDEV_H_
23 
24 #include <linux/kobject.h>
25 #include <linux/module.h>
26 #include <linux/pm.h>
27 
28 
29 struct sys_device;
30 
31 struct sysdev_class {
32 	const char *name;
33 	struct list_head	drivers;
34 
35 	/* Default operations for these types of devices */
36 	int	(*shutdown)(struct sys_device *);
37 	int	(*suspend)(struct sys_device *, pm_message_t state);
38 	int	(*resume)(struct sys_device *);
39 	struct kset		kset;
40 };
41 
42 struct sysdev_class_attribute {
43 	struct attribute attr;
44 	ssize_t (*show)(struct sysdev_class *, char *);
45 	ssize_t (*store)(struct sysdev_class *, const char *, size_t);
46 };
47 
48 #define _SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) 		\
49 {					 			\
50 	.attr = {.name = __stringify(_name), .mode = _mode },	\
51 	.show	= _show,					\
52 	.store	= _store,					\
53 }
54 
55 #define SYSDEV_CLASS_ATTR(_name,_mode,_show,_store) 		\
56 	struct sysdev_class_attribute attr_##_name = 		\
57 		_SYSDEV_CLASS_ATTR(_name,_mode,_show,_store)
58 
59 
60 extern int sysdev_class_register(struct sysdev_class *);
61 extern void sysdev_class_unregister(struct sysdev_class *);
62 
63 extern int sysdev_class_create_file(struct sysdev_class *,
64 	struct sysdev_class_attribute *);
65 extern void sysdev_class_remove_file(struct sysdev_class *,
66 	struct sysdev_class_attribute *);
67 /**
68  * Auxillary system device drivers.
69  */
70 
71 struct sysdev_driver {
72 	struct list_head	entry;
73 	int	(*add)(struct sys_device *);
74 	int	(*remove)(struct sys_device *);
75 	int	(*shutdown)(struct sys_device *);
76 	int	(*suspend)(struct sys_device *, pm_message_t state);
77 	int	(*resume)(struct sys_device *);
78 };
79 
80 
81 extern int sysdev_driver_register(struct sysdev_class *, struct sysdev_driver *);
82 extern void sysdev_driver_unregister(struct sysdev_class *, struct sysdev_driver *);
83 
84 
85 /**
86  * sys_devices can be simplified a lot from regular devices, because they're
87  * simply not as versatile.
88  */
89 
90 struct sys_device {
91 	u32		id;
92 	struct sysdev_class	* cls;
93 	struct kobject		kobj;
94 };
95 
96 extern int sysdev_register(struct sys_device *);
97 extern void sysdev_unregister(struct sys_device *);
98 
99 
100 struct sysdev_attribute {
101 	struct attribute	attr;
102 	ssize_t (*show)(struct sys_device *, struct sysdev_attribute *, char *);
103 	ssize_t (*store)(struct sys_device *, struct sysdev_attribute *,
104 			 const char *, size_t);
105 };
106 
107 
108 #define _SYSDEV_ATTR(_name, _mode, _show, _store)		\
109 {								\
110 	.attr = { .name = __stringify(_name), .mode = _mode },	\
111 	.show	= _show,					\
112 	.store	= _store,					\
113 }
114 
115 #define SYSDEV_ATTR(_name, _mode, _show, _store)		\
116 	struct sysdev_attribute attr_##_name =			\
117 		_SYSDEV_ATTR(_name, _mode, _show, _store);
118 
119 extern int sysdev_create_file(struct sys_device *, struct sysdev_attribute *);
120 extern void sysdev_remove_file(struct sys_device *, struct sysdev_attribute *);
121 
122 struct sysdev_ext_attribute {
123 	struct sysdev_attribute attr;
124 	void *var;
125 };
126 
127 /*
128  * Support for simple variable sysdev attributes.
129  * The pointer to the variable is stored in a sysdev_ext_attribute
130  */
131 
132 /* Add more types as needed */
133 
134 extern ssize_t sysdev_show_ulong(struct sys_device *, struct sysdev_attribute *,
135 				char *);
136 extern ssize_t sysdev_store_ulong(struct sys_device *,
137 			struct sysdev_attribute *, const char *, size_t);
138 extern ssize_t sysdev_show_int(struct sys_device *, struct sysdev_attribute *,
139 				char *);
140 extern ssize_t sysdev_store_int(struct sys_device *,
141 			struct sysdev_attribute *, const char *, size_t);
142 
143 #define _SYSDEV_ULONG_ATTR(_name, _mode, _var)				\
144 	{ _SYSDEV_ATTR(_name, _mode, sysdev_show_ulong, sysdev_store_ulong), \
145 	  &(_var) }
146 #define SYSDEV_ULONG_ATTR(_name, _mode, _var)			\
147 	struct sysdev_ext_attribute attr_##_name = 		\
148 		_SYSDEV_ULONG_ATTR(_name, _mode, _var);
149 #define _SYSDEV_INT_ATTR(_name, _mode, _var)				\
150 	{ _SYSDEV_ATTR(_name, _mode, sysdev_show_int, sysdev_store_int), \
151 	  &(_var) }
152 #define SYSDEV_INT_ATTR(_name, _mode, _var)			\
153 	struct sysdev_ext_attribute attr_##_name = 		\
154 		_SYSDEV_INT_ATTR(_name, _mode, _var);
155 
156 #endif /* _SYSDEV_H_ */
157