Commit a328e95b82c1b8483ae5ab2f809140664d7f6c92

Authored by Dave Hansen
Committed by Richard Purdie
1 parent 8bea8672ed

leds: LED driver for Intel NAS SS4200 series (v5)

This code is based on a driver that came in the "Open-source
and GPL components" download here:

http://downloadcenter.intel.com/SearchResult.aspx?lang=eng&ProductFamily=Server+Products&ProductLine=Intel%C2%AE+Storage+Systems&ProductProduct=Intel%C2%AE+Entry+Storage+System+SS4200-E&OSVersion=OS+Independent

It was in a file called nasgpio.c inside of a second zip file
called SS4200-E_Linux_SIO_Driver-v1.4.zip and is based on this
updated to use the LED subsystem with the ioctl and hardware
monitor support removed.

I don't have any need for brightness
control, and its code is *completely* separate from the on/off
controls implemented here.  If anyone else wants it, I'd be
happy to look into adding it, but I don't care enough for now.

Except for the probe routines, I rewrote most of it.  I also
Note that I don't have any hardware documentation except for
the original driver.

Thanks go to Arjan for his help in getting the original source
for this released and for chasing down some licensing issues.

Signed-off-by: Dave Hansen <dave@sr71.net>
Signed-off-by: Richard Purdie <rpurdie@linux.intel.com>

Showing 3 changed files with 562 additions and 0 deletions Inline Diff

drivers/leds/Kconfig
1 menuconfig NEW_LEDS 1 menuconfig NEW_LEDS
2 bool "LED Support" 2 bool "LED Support"
3 help 3 help
4 Say Y to enable Linux LED support. This allows control of supported 4 Say Y to enable Linux LED support. This allows control of supported
5 LEDs from both userspace and optionally, by kernel events (triggers). 5 LEDs from both userspace and optionally, by kernel events (triggers).
6 6
7 This is not related to standard keyboard LEDs which are controlled 7 This is not related to standard keyboard LEDs which are controlled
8 via the input system. 8 via the input system.
9 9
10 if NEW_LEDS 10 if NEW_LEDS
11 11
12 config LEDS_CLASS 12 config LEDS_CLASS
13 tristate "LED Class Support" 13 tristate "LED Class Support"
14 help 14 help
15 This option enables the led sysfs class in /sys/class/leds. You'll 15 This option enables the led sysfs class in /sys/class/leds. You'll
16 need this to do anything useful with LEDs. If unsure, say N. 16 need this to do anything useful with LEDs. If unsure, say N.
17 17
18 comment "LED drivers" 18 comment "LED drivers"
19 19
20 config LEDS_ATMEL_PWM 20 config LEDS_ATMEL_PWM
21 tristate "LED Support using Atmel PWM outputs" 21 tristate "LED Support using Atmel PWM outputs"
22 depends on LEDS_CLASS && ATMEL_PWM 22 depends on LEDS_CLASS && ATMEL_PWM
23 help 23 help
24 This option enables support for LEDs driven using outputs 24 This option enables support for LEDs driven using outputs
25 of the dedicated PWM controller found on newer Atmel SOCs. 25 of the dedicated PWM controller found on newer Atmel SOCs.
26 26
27 config LEDS_LOCOMO 27 config LEDS_LOCOMO
28 tristate "LED Support for Locomo device" 28 tristate "LED Support for Locomo device"
29 depends on LEDS_CLASS && SHARP_LOCOMO 29 depends on LEDS_CLASS && SHARP_LOCOMO
30 help 30 help
31 This option enables support for the LEDs on Sharp Locomo. 31 This option enables support for the LEDs on Sharp Locomo.
32 Zaurus models SL-5500 and SL-5600. 32 Zaurus models SL-5500 and SL-5600.
33 33
34 config LEDS_MIKROTIK_RB532 34 config LEDS_MIKROTIK_RB532
35 tristate "LED Support for Mikrotik Routerboard 532" 35 tristate "LED Support for Mikrotik Routerboard 532"
36 depends on LEDS_CLASS && MIKROTIK_RB532 36 depends on LEDS_CLASS && MIKROTIK_RB532
37 help 37 help
38 This option enables support for the so called "User LED" of 38 This option enables support for the so called "User LED" of
39 Mikrotik's Routerboard 532. 39 Mikrotik's Routerboard 532.
40 40
41 config LEDS_S3C24XX 41 config LEDS_S3C24XX
42 tristate "LED Support for Samsung S3C24XX GPIO LEDs" 42 tristate "LED Support for Samsung S3C24XX GPIO LEDs"
43 depends on LEDS_CLASS && ARCH_S3C2410 43 depends on LEDS_CLASS && ARCH_S3C2410
44 help 44 help
45 This option enables support for LEDs connected to GPIO lines 45 This option enables support for LEDs connected to GPIO lines
46 on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440. 46 on Samsung S3C24XX series CPUs, such as the S3C2410 and S3C2440.
47 47
48 config LEDS_AMS_DELTA 48 config LEDS_AMS_DELTA
49 tristate "LED Support for the Amstrad Delta (E3)" 49 tristate "LED Support for the Amstrad Delta (E3)"
50 depends on LEDS_CLASS && MACH_AMS_DELTA 50 depends on LEDS_CLASS && MACH_AMS_DELTA
51 help 51 help
52 This option enables support for the LEDs on Amstrad Delta (E3). 52 This option enables support for the LEDs on Amstrad Delta (E3).
53 53
54 config LEDS_NET48XX 54 config LEDS_NET48XX
55 tristate "LED Support for Soekris net48xx series Error LED" 55 tristate "LED Support for Soekris net48xx series Error LED"
56 depends on LEDS_CLASS && SCx200_GPIO 56 depends on LEDS_CLASS && SCx200_GPIO
57 help 57 help
58 This option enables support for the Soekris net4801 and net4826 error 58 This option enables support for the Soekris net4801 and net4826 error
59 LED. 59 LED.
60 60
61 config LEDS_FSG 61 config LEDS_FSG
62 tristate "LED Support for the Freecom FSG-3" 62 tristate "LED Support for the Freecom FSG-3"
63 depends on LEDS_CLASS && MACH_FSG 63 depends on LEDS_CLASS && MACH_FSG
64 help 64 help
65 This option enables support for the LEDs on the Freecom FSG-3. 65 This option enables support for the LEDs on the Freecom FSG-3.
66 66
67 config LEDS_WRAP 67 config LEDS_WRAP
68 tristate "LED Support for the WRAP series LEDs" 68 tristate "LED Support for the WRAP series LEDs"
69 depends on LEDS_CLASS && SCx200_GPIO 69 depends on LEDS_CLASS && SCx200_GPIO
70 help 70 help
71 This option enables support for the PCEngines WRAP programmable LEDs. 71 This option enables support for the PCEngines WRAP programmable LEDs.
72 72
73 config LEDS_ALIX2 73 config LEDS_ALIX2
74 tristate "LED Support for ALIX.2 and ALIX.3 series" 74 tristate "LED Support for ALIX.2 and ALIX.3 series"
75 depends on LEDS_CLASS && X86 && EXPERIMENTAL 75 depends on LEDS_CLASS && X86 && EXPERIMENTAL
76 help 76 help
77 This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs. 77 This option enables support for the PCEngines ALIX.2 and ALIX.3 LEDs.
78 You have to set leds-alix2.force=1 for boards with Award BIOS. 78 You have to set leds-alix2.force=1 for boards with Award BIOS.
79 79
80 config LEDS_H1940 80 config LEDS_H1940
81 tristate "LED Support for iPAQ H1940 device" 81 tristate "LED Support for iPAQ H1940 device"
82 depends on LEDS_CLASS && ARCH_H1940 82 depends on LEDS_CLASS && ARCH_H1940
83 help 83 help
84 This option enables support for the LEDs on the h1940. 84 This option enables support for the LEDs on the h1940.
85 85
86 config LEDS_COBALT_QUBE 86 config LEDS_COBALT_QUBE
87 tristate "LED Support for the Cobalt Qube series front LED" 87 tristate "LED Support for the Cobalt Qube series front LED"
88 depends on LEDS_CLASS && MIPS_COBALT 88 depends on LEDS_CLASS && MIPS_COBALT
89 help 89 help
90 This option enables support for the front LED on Cobalt Qube series 90 This option enables support for the front LED on Cobalt Qube series
91 91
92 config LEDS_COBALT_RAQ 92 config LEDS_COBALT_RAQ
93 bool "LED Support for the Cobalt Raq series" 93 bool "LED Support for the Cobalt Raq series"
94 depends on LEDS_CLASS=y && MIPS_COBALT 94 depends on LEDS_CLASS=y && MIPS_COBALT
95 select LEDS_TRIGGERS 95 select LEDS_TRIGGERS
96 help 96 help
97 This option enables support for the Cobalt Raq series LEDs. 97 This option enables support for the Cobalt Raq series LEDs.
98 98
99 config LEDS_SUNFIRE 99 config LEDS_SUNFIRE
100 tristate "LED support for SunFire servers." 100 tristate "LED support for SunFire servers."
101 depends on LEDS_CLASS && SPARC64 101 depends on LEDS_CLASS && SPARC64
102 select LEDS_TRIGGERS 102 select LEDS_TRIGGERS
103 help 103 help
104 This option enables support for the Left, Middle, and Right 104 This option enables support for the Left, Middle, and Right
105 LEDs on the I/O and CPU boards of SunFire UltraSPARC servers. 105 LEDs on the I/O and CPU boards of SunFire UltraSPARC servers.
106 106
107 config LEDS_HP6XX 107 config LEDS_HP6XX
108 tristate "LED Support for the HP Jornada 6xx" 108 tristate "LED Support for the HP Jornada 6xx"
109 depends on LEDS_CLASS && SH_HP6XX 109 depends on LEDS_CLASS && SH_HP6XX
110 help 110 help
111 This option enables LED support for the handheld 111 This option enables LED support for the handheld
112 HP Jornada 620/660/680/690. 112 HP Jornada 620/660/680/690.
113 113
114 config LEDS_PCA9532 114 config LEDS_PCA9532
115 tristate "LED driver for PCA9532 dimmer" 115 tristate "LED driver for PCA9532 dimmer"
116 depends on LEDS_CLASS && I2C && INPUT && EXPERIMENTAL 116 depends on LEDS_CLASS && I2C && INPUT && EXPERIMENTAL
117 help 117 help
118 This option enables support for NXP pca9532 118 This option enables support for NXP pca9532
119 LED controller. It is generally only useful 119 LED controller. It is generally only useful
120 as a platform driver 120 as a platform driver
121 121
122 config LEDS_GPIO 122 config LEDS_GPIO
123 tristate "LED Support for GPIO connected LEDs" 123 tristate "LED Support for GPIO connected LEDs"
124 depends on LEDS_CLASS && GENERIC_GPIO 124 depends on LEDS_CLASS && GENERIC_GPIO
125 help 125 help
126 This option enables support for the LEDs connected to GPIO 126 This option enables support for the LEDs connected to GPIO
127 outputs. To be useful the particular board must have LEDs 127 outputs. To be useful the particular board must have LEDs
128 and they must be connected to the GPIO lines. The LEDs must be 128 and they must be connected to the GPIO lines. The LEDs must be
129 defined as platform devices and/or OpenFirmware platform devices. 129 defined as platform devices and/or OpenFirmware platform devices.
130 The code to use these bindings can be selected below. 130 The code to use these bindings can be selected below.
131 131
132 config LEDS_GPIO_PLATFORM 132 config LEDS_GPIO_PLATFORM
133 bool "Platform device bindings for GPIO LEDs" 133 bool "Platform device bindings for GPIO LEDs"
134 depends on LEDS_GPIO 134 depends on LEDS_GPIO
135 default y 135 default y
136 help 136 help
137 Let the leds-gpio driver drive LEDs which have been defined as 137 Let the leds-gpio driver drive LEDs which have been defined as
138 platform devices. If you don't know what this means, say yes. 138 platform devices. If you don't know what this means, say yes.
139 139
140 config LEDS_GPIO_OF 140 config LEDS_GPIO_OF
141 bool "OpenFirmware platform device bindings for GPIO LEDs" 141 bool "OpenFirmware platform device bindings for GPIO LEDs"
142 depends on LEDS_GPIO && OF_DEVICE 142 depends on LEDS_GPIO && OF_DEVICE
143 default y 143 default y
144 help 144 help
145 Let the leds-gpio driver drive LEDs which have been defined as 145 Let the leds-gpio driver drive LEDs which have been defined as
146 of_platform devices. For instance, LEDs which are listed in a "dts" 146 of_platform devices. For instance, LEDs which are listed in a "dts"
147 file. 147 file.
148 148
149 config LEDS_LP3944 149 config LEDS_LP3944
150 tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip" 150 tristate "LED Support for N.S. LP3944 (Fun Light) I2C chip"
151 depends on LEDS_CLASS && I2C 151 depends on LEDS_CLASS && I2C
152 help 152 help
153 This option enables support for LEDs connected to the National 153 This option enables support for LEDs connected to the National
154 Semiconductor LP3944 Lighting Management Unit (LMU) also known as 154 Semiconductor LP3944 Lighting Management Unit (LMU) also known as
155 Fun Light Chip. 155 Fun Light Chip.
156 156
157 To compile this driver as a module, choose M here: the 157 To compile this driver as a module, choose M here: the
158 module will be called leds-lp3944. 158 module will be called leds-lp3944.
159 159
160 config LEDS_CLEVO_MAIL 160 config LEDS_CLEVO_MAIL
161 tristate "Mail LED on Clevo notebook" 161 tristate "Mail LED on Clevo notebook"
162 depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI 162 depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI
163 help 163 help
164 This driver makes the mail LED accessible from userspace 164 This driver makes the mail LED accessible from userspace
165 programs through the leds subsystem. This LED have three 165 programs through the leds subsystem. This LED have three
166 known mode: off, blink at 0.5Hz and blink at 1Hz. 166 known mode: off, blink at 0.5Hz and blink at 1Hz.
167 167
168 The driver supports two kinds of interface: using ledtrig-timer 168 The driver supports two kinds of interface: using ledtrig-timer
169 or through /sys/class/leds/clevo::mail/brightness. As this LED 169 or through /sys/class/leds/clevo::mail/brightness. As this LED
170 cannot change it's brightness it blinks instead. The brightness 170 cannot change it's brightness it blinks instead. The brightness
171 value 0 means off, 1..127 means blink at 0.5Hz and 128..255 means 171 value 0 means off, 1..127 means blink at 0.5Hz and 128..255 means
172 blink at 1Hz. 172 blink at 1Hz.
173 173
174 This module can drive the mail LED for the following notebooks: 174 This module can drive the mail LED for the following notebooks:
175 175
176 Clevo D400P 176 Clevo D400P
177 Clevo D410J 177 Clevo D410J
178 Clevo D410V 178 Clevo D410V
179 Clevo D400V/D470V (not tested, but might work) 179 Clevo D400V/D470V (not tested, but might work)
180 Clevo M540N 180 Clevo M540N
181 Clevo M5x0N (not tested, but might work) 181 Clevo M5x0N (not tested, but might work)
182 Positivo Mobile (Clevo M5x0V) 182 Positivo Mobile (Clevo M5x0V)
183 183
184 If your model is not listed here you can try the "nodetect" 184 If your model is not listed here you can try the "nodetect"
185 module parameter. 185 module parameter.
186 186
187 To compile this driver as a module, choose M here: the 187 To compile this driver as a module, choose M here: the
188 module will be called leds-clevo-mail. 188 module will be called leds-clevo-mail.
189 189
190 config LEDS_PCA955X 190 config LEDS_PCA955X
191 tristate "LED Support for PCA955x I2C chips" 191 tristate "LED Support for PCA955x I2C chips"
192 depends on LEDS_CLASS && I2C 192 depends on LEDS_CLASS && I2C
193 help 193 help
194 This option enables support for LEDs connected to PCA955x 194 This option enables support for LEDs connected to PCA955x
195 LED driver chips accessed via the I2C bus. Supported 195 LED driver chips accessed via the I2C bus. Supported
196 devices include PCA9550, PCA9551, PCA9552, and PCA9553. 196 devices include PCA9550, PCA9551, PCA9552, and PCA9553.
197 197
198 config LEDS_WM831X_STATUS 198 config LEDS_WM831X_STATUS
199 tristate "LED support for status LEDs on WM831x PMICs" 199 tristate "LED support for status LEDs on WM831x PMICs"
200 depends on LEDS_CLASS && MFD_WM831X 200 depends on LEDS_CLASS && MFD_WM831X
201 help 201 help
202 This option enables support for the status LEDs of the WM831x 202 This option enables support for the status LEDs of the WM831x
203 series of PMICs. 203 series of PMICs.
204 204
205 config LEDS_WM8350 205 config LEDS_WM8350
206 tristate "LED Support for WM8350 AudioPlus PMIC" 206 tristate "LED Support for WM8350 AudioPlus PMIC"
207 depends on LEDS_CLASS && MFD_WM8350 207 depends on LEDS_CLASS && MFD_WM8350
208 help 208 help
209 This option enables support for LEDs driven by the Wolfson 209 This option enables support for LEDs driven by the Wolfson
210 Microelectronics WM8350 AudioPlus PMIC. 210 Microelectronics WM8350 AudioPlus PMIC.
211 211
212 config LEDS_DA903X 212 config LEDS_DA903X
213 tristate "LED Support for DA9030/DA9034 PMIC" 213 tristate "LED Support for DA9030/DA9034 PMIC"
214 depends on LEDS_CLASS && PMIC_DA903X 214 depends on LEDS_CLASS && PMIC_DA903X
215 help 215 help
216 This option enables support for on-chip LED drivers found 216 This option enables support for on-chip LED drivers found
217 on Dialog Semiconductor DA9030/DA9034 PMICs. 217 on Dialog Semiconductor DA9030/DA9034 PMICs.
218 218
219 config LEDS_DAC124S085 219 config LEDS_DAC124S085
220 tristate "LED Support for DAC124S085 SPI DAC" 220 tristate "LED Support for DAC124S085 SPI DAC"
221 depends on LEDS_CLASS && SPI 221 depends on LEDS_CLASS && SPI
222 help 222 help
223 This option enables support for DAC124S085 SPI DAC from NatSemi, 223 This option enables support for DAC124S085 SPI DAC from NatSemi,
224 which can be used to control up to four LEDs. 224 which can be used to control up to four LEDs.
225 225
226 config LEDS_PWM 226 config LEDS_PWM
227 tristate "PWM driven LED Support" 227 tristate "PWM driven LED Support"
228 depends on LEDS_CLASS && HAVE_PWM 228 depends on LEDS_CLASS && HAVE_PWM
229 help 229 help
230 This option enables support for pwm driven LEDs 230 This option enables support for pwm driven LEDs
231 231
232 config LEDS_BD2802 232 config LEDS_BD2802
233 tristate "LED driver for BD2802 RGB LED" 233 tristate "LED driver for BD2802 RGB LED"
234 depends on LEDS_CLASS && I2C 234 depends on LEDS_CLASS && I2C
235 help 235 help
236 This option enables support for BD2802GU RGB LED driver chips 236 This option enables support for BD2802GU RGB LED driver chips
237 accessed via the I2C bus. 237 accessed via the I2C bus.
238 238
239 config LEDS_INTEL_SS4200
240 tristate "LED driver for Intel NAS SS4200 series"
241 depends on LEDS_CLASS && PCI && DMI
242 help
243 This option enables support for the Intel SS4200 series of
244 Network Attached Storage servers. You may control the hard
245 drive or power LEDs on the front panel. Using this driver
246 can stop the front LED from blinking after startup.
247
239 comment "LED Triggers" 248 comment "LED Triggers"
240 249
241 config LEDS_TRIGGERS 250 config LEDS_TRIGGERS
242 bool "LED Trigger support" 251 bool "LED Trigger support"
243 help 252 help
244 This option enables trigger support for the leds class. 253 This option enables trigger support for the leds class.
245 These triggers allow kernel events to drive the LEDs and can 254 These triggers allow kernel events to drive the LEDs and can
246 be configured via sysfs. If unsure, say Y. 255 be configured via sysfs. If unsure, say Y.
247 256
248 config LEDS_TRIGGER_TIMER 257 config LEDS_TRIGGER_TIMER
249 tristate "LED Timer Trigger" 258 tristate "LED Timer Trigger"
250 depends on LEDS_TRIGGERS 259 depends on LEDS_TRIGGERS
251 help 260 help
252 This allows LEDs to be controlled by a programmable timer 261 This allows LEDs to be controlled by a programmable timer
253 via sysfs. Some LED hardware can be programmed to start 262 via sysfs. Some LED hardware can be programmed to start
254 blinking the LED without any further software interaction. 263 blinking the LED without any further software interaction.
255 For more details read Documentation/leds-class.txt. 264 For more details read Documentation/leds-class.txt.
256 265
257 If unsure, say Y. 266 If unsure, say Y.
258 267
259 config LEDS_TRIGGER_IDE_DISK 268 config LEDS_TRIGGER_IDE_DISK
260 bool "LED IDE Disk Trigger" 269 bool "LED IDE Disk Trigger"
261 depends on LEDS_TRIGGERS && IDE_GD_ATA 270 depends on LEDS_TRIGGERS && IDE_GD_ATA
262 help 271 help
263 This allows LEDs to be controlled by IDE disk activity. 272 This allows LEDs to be controlled by IDE disk activity.
264 If unsure, say Y. 273 If unsure, say Y.
265 274
266 config LEDS_TRIGGER_HEARTBEAT 275 config LEDS_TRIGGER_HEARTBEAT
267 tristate "LED Heartbeat Trigger" 276 tristate "LED Heartbeat Trigger"
268 depends on LEDS_TRIGGERS 277 depends on LEDS_TRIGGERS
269 help 278 help
270 This allows LEDs to be controlled by a CPU load average. 279 This allows LEDs to be controlled by a CPU load average.
271 The flash frequency is a hyperbolic function of the 1-minute 280 The flash frequency is a hyperbolic function of the 1-minute
272 load average. 281 load average.
273 If unsure, say Y. 282 If unsure, say Y.
274 283
275 config LEDS_TRIGGER_BACKLIGHT 284 config LEDS_TRIGGER_BACKLIGHT
276 tristate "LED backlight Trigger" 285 tristate "LED backlight Trigger"
277 depends on LEDS_TRIGGERS 286 depends on LEDS_TRIGGERS
278 help 287 help
279 This allows LEDs to be controlled as a backlight device: they 288 This allows LEDs to be controlled as a backlight device: they
280 turn off and on when the display is blanked and unblanked. 289 turn off and on when the display is blanked and unblanked.
281 290
282 If unsure, say N. 291 If unsure, say N.
283 292
284 config LEDS_TRIGGER_GPIO 293 config LEDS_TRIGGER_GPIO
285 tristate "LED GPIO Trigger" 294 tristate "LED GPIO Trigger"
286 depends on LEDS_TRIGGERS 295 depends on LEDS_TRIGGERS
287 depends on GPIOLIB 296 depends on GPIOLIB
288 help 297 help
289 This allows LEDs to be controlled by gpio events. It's good 298 This allows LEDs to be controlled by gpio events. It's good
290 when using gpios as switches and triggering the needed LEDs 299 when using gpios as switches and triggering the needed LEDs
291 from there. One use case is n810's keypad LEDs that could 300 from there. One use case is n810's keypad LEDs that could
292 be triggered by this trigger when user slides up to show 301 be triggered by this trigger when user slides up to show
293 keypad. 302 keypad.
294 303
295 If unsure, say N. 304 If unsure, say N.
296 305
297 config LEDS_TRIGGER_DEFAULT_ON 306 config LEDS_TRIGGER_DEFAULT_ON
298 tristate "LED Default ON Trigger" 307 tristate "LED Default ON Trigger"
299 depends on LEDS_TRIGGERS 308 depends on LEDS_TRIGGERS
300 help 309 help
301 This allows LEDs to be initialised in the ON state. 310 This allows LEDs to be initialised in the ON state.
302 If unsure, say Y. 311 If unsure, say Y.
303 312
304 comment "iptables trigger is under Netfilter config (LED target)" 313 comment "iptables trigger is under Netfilter config (LED target)"
305 depends on LEDS_TRIGGERS 314 depends on LEDS_TRIGGERS
306 315
307 endif # NEW_LEDS 316 endif # NEW_LEDS
308 317
drivers/leds/Makefile
1 1
2 # LED Core 2 # LED Core
3 obj-$(CONFIG_NEW_LEDS) += led-core.o 3 obj-$(CONFIG_NEW_LEDS) += led-core.o
4 obj-$(CONFIG_LEDS_CLASS) += led-class.o 4 obj-$(CONFIG_LEDS_CLASS) += led-class.o
5 obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o 5 obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o
6 6
7 # LED Platform Drivers 7 # LED Platform Drivers
8 obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o 8 obj-$(CONFIG_LEDS_ATMEL_PWM) += leds-atmel-pwm.o
9 obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o 9 obj-$(CONFIG_LEDS_BD2802) += leds-bd2802.o
10 obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o 10 obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
11 obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o 11 obj-$(CONFIG_LEDS_MIKROTIK_RB532) += leds-rb532.o
12 obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o 12 obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
13 obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o 13 obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o
14 obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o 14 obj-$(CONFIG_LEDS_NET48XX) += leds-net48xx.o
15 obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o 15 obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o
16 obj-$(CONFIG_LEDS_ALIX2) += leds-alix2.o 16 obj-$(CONFIG_LEDS_ALIX2) += leds-alix2.o
17 obj-$(CONFIG_LEDS_H1940) += leds-h1940.o 17 obj-$(CONFIG_LEDS_H1940) += leds-h1940.o
18 obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o 18 obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o
19 obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o 19 obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o
20 obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o 20 obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o
21 obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o 21 obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o
22 obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o 22 obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
23 obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o 23 obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o
24 obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o 24 obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
25 obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o 25 obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
26 obj-$(CONFIG_LEDS_FSG) += leds-fsg.o 26 obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
27 obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o 27 obj-$(CONFIG_LEDS_PCA955X) += leds-pca955x.o
28 obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o 28 obj-$(CONFIG_LEDS_DA903X) += leds-da903x.o
29 obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o 29 obj-$(CONFIG_LEDS_WM831X_STATUS) += leds-wm831x-status.o
30 obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o 30 obj-$(CONFIG_LEDS_WM8350) += leds-wm8350.o
31 obj-$(CONFIG_LEDS_PWM) += leds-pwm.o 31 obj-$(CONFIG_LEDS_PWM) += leds-pwm.o
32 obj-$(CONFIG_LEDS_INTEL_SS4200) += leds-ss4200.o
32 33
33 # LED SPI Drivers 34 # LED SPI Drivers
34 obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o 35 obj-$(CONFIG_LEDS_DAC124S085) += leds-dac124s085.o
35 36
36 # LED Triggers 37 # LED Triggers
37 obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o 38 obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
38 obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o 39 obj-$(CONFIG_LEDS_TRIGGER_IDE_DISK) += ledtrig-ide-disk.o
39 obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o 40 obj-$(CONFIG_LEDS_TRIGGER_HEARTBEAT) += ledtrig-heartbeat.o
40 obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o 41 obj-$(CONFIG_LEDS_TRIGGER_BACKLIGHT) += ledtrig-backlight.o
41 obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o 42 obj-$(CONFIG_LEDS_TRIGGER_GPIO) += ledtrig-gpio.o
42 obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o 43 obj-$(CONFIG_LEDS_TRIGGER_DEFAULT_ON) += ledtrig-default-on.o
43 44
drivers/leds/leds-ss4200.c
File was created 1 /*
2 * SS4200-E Hardware API
3 * Copyright (c) 2009, Intel Corporation.
4 * Copyright IBM Corporation, 2009
5 *
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * more details.
14 *
15 * You should have received a copy of the GNU General Public License along with
16 * this program; if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Author: Dave Hansen <dave@sr71.net>
20 */
21
22 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
23
24 #include <linux/dmi.h>
25 #include <linux/init.h>
26 #include <linux/ioport.h>
27 #include <linux/kernel.h>
28 #include <linux/leds.h>
29 #include <linux/module.h>
30 #include <linux/pci.h>
31 #include <linux/types.h>
32 #include <linux/uaccess.h>
33
34 MODULE_AUTHOR("Rodney Girod <rgirod@confocus.com>, Dave Hansen <dave@sr71.net>");
35 MODULE_DESCRIPTION("Intel NAS/Home Server ICH7 GPIO Driver");
36 MODULE_LICENSE("GPL");
37
38 /*
39 * ICH7 LPC/GPIO PCI Config register offsets
40 */
41 #define PMBASE 0x040
42 #define GPIO_BASE 0x048
43 #define GPIO_CTRL 0x04c
44 #define GPIO_EN 0x010
45
46 /*
47 * The ICH7 GPIO register block is 64 bytes in size.
48 */
49 #define ICH7_GPIO_SIZE 64
50
51 /*
52 * Define register offsets within the ICH7 register block.
53 */
54 #define GPIO_USE_SEL 0x000
55 #define GP_IO_SEL 0x004
56 #define GP_LVL 0x00c
57 #define GPO_BLINK 0x018
58 #define GPI_INV 0x030
59 #define GPIO_USE_SEL2 0x034
60 #define GP_IO_SEL2 0x038
61 #define GP_LVL2 0x03c
62
63 /*
64 * PCI ID of the Intel ICH7 LPC Device within which the GPIO block lives.
65 */
66 static struct pci_device_id ich7_lpc_pci_id[] =
67 {
68 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_0) },
69 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_1) },
70 { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ICH7_30) },
71 { } /* NULL entry */
72 };
73
74 MODULE_DEVICE_TABLE(pci, ich7_lpc_pci_id);
75
76 static int __init ss4200_led_dmi_callback(const struct dmi_system_id *id)
77 {
78 pr_info("detected '%s'\n", id->ident);
79 return 1;
80 }
81
82 static unsigned int __initdata nodetect;
83 module_param_named(nodetect, nodetect, bool, 0);
84 MODULE_PARM_DESC(nodetect, "Skip DMI-based hardware detection");
85
86 /*
87 * struct nas_led_whitelist - List of known good models
88 *
89 * Contains the known good models this driver is compatible with.
90 * When adding a new model try to be as strict as possible. This
91 * makes it possible to keep the false positives (the model is
92 * detected as working, but in reality it is not) as low as
93 * possible.
94 */
95 static struct dmi_system_id __initdata nas_led_whitelist[] = {
96 {
97 .callback = ss4200_led_dmi_callback,
98 .ident = "Intel SS4200-E",
99 .matches = {
100 DMI_MATCH(DMI_SYS_VENDOR, "Intel"),
101 DMI_MATCH(DMI_PRODUCT_NAME, "SS4200-E"),
102 DMI_MATCH(DMI_PRODUCT_VERSION, "1.00.00")
103 }
104 },
105 };
106
107 /*
108 * Base I/O address assigned to the Power Management register block
109 */
110 static u32 g_pm_io_base;
111
112 /*
113 * Base I/O address assigned to the ICH7 GPIO register block
114 */
115 static u32 nas_gpio_io_base;
116
117 /*
118 * When we successfully register a region, we are returned a resource.
119 * We use these to identify which regions we need to release on our way
120 * back out.
121 */
122 static struct resource *gp_gpio_resource;
123
124 struct nasgpio_led {
125 char *name;
126 u32 gpio_bit;
127 struct led_classdev led_cdev;
128 };
129
130 /*
131 * gpio_bit(s) are the ICH7 GPIO bit assignments
132 */
133 static struct nasgpio_led nasgpio_leds[] = {
134 { .name = "hdd1:blue:sata", .gpio_bit = 0 },
135 { .name = "hdd1:amber:sata", .gpio_bit = 1 },
136 { .name = "hdd2:blue:sata", .gpio_bit = 2 },
137 { .name = "hdd2:amber:sata", .gpio_bit = 3 },
138 { .name = "hdd3:blue:sata", .gpio_bit = 4 },
139 { .name = "hdd3:amber:sata", .gpio_bit = 5 },
140 { .name = "hdd4:blue:sata", .gpio_bit = 6 },
141 { .name = "hdd4:amber:sata", .gpio_bit = 7 },
142 { .name = "power:blue:power", .gpio_bit = 27},
143 { .name = "power:amber:power", .gpio_bit = 28},
144 };
145
146 #define NAS_RECOVERY 0x00000400 /* GPIO10 */
147
148 static struct nasgpio_led *
149 led_classdev_to_nasgpio_led(struct led_classdev *led_cdev)
150 {
151 return container_of(led_cdev, struct nasgpio_led, led_cdev);
152 }
153
154 static struct nasgpio_led *get_led_named(char *name)
155 {
156 int i;
157 for (i = 0; i < ARRAY_SIZE(nasgpio_leds); i++) {
158 if (strcmp(nasgpio_leds[i].name, name))
159 continue;
160 return &nasgpio_leds[i];
161 }
162 return NULL;
163 }
164
165 /*
166 * This protects access to the gpio ports.
167 */
168 static DEFINE_SPINLOCK(nasgpio_gpio_lock);
169
170 /*
171 * There are two gpio ports, one for blinking and the other
172 * for power. @port tells us if we're doing blinking or
173 * power control.
174 *
175 * Caller must hold nasgpio_gpio_lock
176 */
177 static void __nasgpio_led_set_attr(struct led_classdev *led_cdev,
178 u32 port, u32 value)
179 {
180 struct nasgpio_led *led = led_classdev_to_nasgpio_led(led_cdev);
181 u32 gpio_out;
182
183 gpio_out = inl(nas_gpio_io_base + port);
184 if (value)
185 gpio_out |= (1<<led->gpio_bit);
186 else
187 gpio_out &= ~(1<<led->gpio_bit);
188
189 outl(gpio_out, nas_gpio_io_base + port);
190 }
191
192 static void nasgpio_led_set_attr(struct led_classdev *led_cdev,
193 u32 port, u32 value)
194 {
195 spin_lock(&nasgpio_gpio_lock);
196 __nasgpio_led_set_attr(led_cdev, port, value);
197 spin_unlock(&nasgpio_gpio_lock);
198 }
199
200 u32 nasgpio_led_get_attr(struct led_classdev *led_cdev, u32 port)
201 {
202 struct nasgpio_led *led = led_classdev_to_nasgpio_led(led_cdev);
203 u32 gpio_in;
204
205 spin_lock(&nasgpio_gpio_lock);
206 gpio_in = inl(nas_gpio_io_base + port);
207 spin_unlock(&nasgpio_gpio_lock);
208 if (gpio_in & (1<<led->gpio_bit))
209 return 1;
210 return 0;
211 }
212
213 /*
214 * There is actual brightness control in the hardware,
215 * but it is via smbus commands and not implemented
216 * in this driver.
217 */
218 static void nasgpio_led_set_brightness(struct led_classdev *led_cdev,
219 enum led_brightness brightness)
220 {
221 u32 setting = 0;
222 if (brightness >= LED_HALF)
223 setting = 1;
224 /*
225 * Hold the lock across both operations. This ensures
226 * consistency so that both the "turn off blinking"
227 * and "turn light off" operations complete as a set.
228 */
229 spin_lock(&nasgpio_gpio_lock);
230 /*
231 * LED class documentation asks that past blink state
232 * be disabled when brightness is turned to zero.
233 */
234 if (brightness == 0)
235 __nasgpio_led_set_attr(led_cdev, GPO_BLINK, 0);
236 __nasgpio_led_set_attr(led_cdev, GP_LVL, setting);
237 spin_unlock(&nasgpio_gpio_lock);
238 }
239
240 static int nasgpio_led_set_blink(struct led_classdev *led_cdev,
241 unsigned long *delay_on,
242 unsigned long *delay_off)
243 {
244 u32 setting = 1;
245 if (!(*delay_on == 0 && *delay_off == 0) &&
246 !(*delay_on == 500 && *delay_off == 500))
247 return -EINVAL;
248 /*
249 * These are very approximate.
250 */
251 *delay_on = 500;
252 *delay_off = 500;
253
254 nasgpio_led_set_attr(led_cdev, GPO_BLINK, setting);
255
256 return 0;
257 }
258
259
260 /*
261 * Initialize the ICH7 GPIO registers for NAS usage. The BIOS should have
262 * already taken care of this, but we will do so in a non destructive manner
263 * so that we have what we need whether the BIOS did it or not.
264 */
265 static int __devinit ich7_gpio_init(struct device *dev)
266 {
267 int i;
268 u32 config_data = 0;
269 u32 all_nas_led = 0;
270
271 for (i = 0; i < ARRAY_SIZE(nasgpio_leds); i++)
272 all_nas_led |= (1<<nasgpio_leds[i].gpio_bit);
273
274 spin_lock(&nasgpio_gpio_lock);
275 /*
276 * We need to enable all of the GPIO lines used by the NAS box,
277 * so we will read the current Use Selection and add our usage
278 * to it. This should be benign with regard to the original
279 * BIOS configuration.
280 */
281 config_data = inl(nas_gpio_io_base + GPIO_USE_SEL);
282 dev_dbg(dev, ": Data read from GPIO_USE_SEL = 0x%08x\n", config_data);
283 config_data |= all_nas_led + NAS_RECOVERY;
284 outl(config_data, nas_gpio_io_base + GPIO_USE_SEL);
285 config_data = inl(nas_gpio_io_base + GPIO_USE_SEL);
286 dev_dbg(dev, ": GPIO_USE_SEL = 0x%08x\n\n", config_data);
287
288 /*
289 * The LED GPIO outputs need to be configured for output, so we
290 * will ensure that all LED lines are cleared for output and the
291 * RECOVERY line ready for input. This too should be benign with
292 * regard to BIOS configuration.
293 */
294 config_data = inl(nas_gpio_io_base + GP_IO_SEL);
295 dev_dbg(dev, ": Data read from GP_IO_SEL = 0x%08x\n",
296 config_data);
297 config_data &= ~all_nas_led;
298 config_data |= NAS_RECOVERY;
299 outl(config_data, nas_gpio_io_base + GP_IO_SEL);
300 config_data = inl(nas_gpio_io_base + GP_IO_SEL);
301 dev_dbg(dev, ": GP_IO_SEL = 0x%08x\n", config_data);
302
303 /*
304 * In our final system, the BIOS will initialize the state of all
305 * of the LEDs. For now, we turn them all off (or Low).
306 */
307 config_data = inl(nas_gpio_io_base + GP_LVL);
308 dev_dbg(dev, ": Data read from GP_LVL = 0x%08x\n", config_data);
309 /*
310 * In our final system, the BIOS will initialize the blink state of all
311 * of the LEDs. For now, we turn blink off for all of them.
312 */
313 config_data = inl(nas_gpio_io_base + GPO_BLINK);
314 dev_dbg(dev, ": Data read from GPO_BLINK = 0x%08x\n", config_data);
315
316 /*
317 * At this moment, I am unsure if anything needs to happen with GPI_INV
318 */
319 config_data = inl(nas_gpio_io_base + GPI_INV);
320 dev_dbg(dev, ": Data read from GPI_INV = 0x%08x\n", config_data);
321
322 spin_unlock(&nasgpio_gpio_lock);
323 return 0;
324 }
325
326 static void ich7_lpc_cleanup(struct device *dev)
327 {
328 /*
329 * If we were given exclusive use of the GPIO
330 * I/O Address range, we must return it.
331 */
332 if (gp_gpio_resource) {
333 dev_dbg(dev, ": Releasing GPIO I/O addresses\n");
334 release_region(nas_gpio_io_base, ICH7_GPIO_SIZE);
335 gp_gpio_resource = NULL;
336 }
337 }
338
339 /*
340 * The OS has determined that the LPC of the Intel ICH7 Southbridge is present
341 * so we can retrive the required operational information and prepare the GPIO.
342 */
343 static struct pci_dev *nas_gpio_pci_dev;
344 static int __devinit ich7_lpc_probe(struct pci_dev *dev,
345 const struct pci_device_id *id)
346 {
347 int status = 0;
348 u32 gc = 0;
349
350 pci_enable_device(dev);
351
352 nas_gpio_pci_dev = dev;
353 status = pci_read_config_dword(dev, PMBASE, &g_pm_io_base);
354 if (status)
355 goto out;
356 g_pm_io_base &= 0x00000ff80;
357
358 status = pci_read_config_dword(dev, GPIO_CTRL, &gc);
359 if (!(GPIO_EN & gc)) {
360 status = -EEXIST;
361 dev_info(&dev->dev,
362 "ERROR: The LPC GPIO Block has not been enabled.\n");
363 goto out;
364 }
365
366 status = pci_read_config_dword(dev, GPIO_BASE, &nas_gpio_io_base);
367 if (0 > status) {
368 dev_info(&dev->dev, "Unable to read GPIOBASE.\n");
369 goto out;
370 }
371 dev_dbg(&dev->dev, ": GPIOBASE = 0x%08x\n", nas_gpio_io_base);
372 nas_gpio_io_base &= 0x00000ffc0;
373
374 /*
375 * Insure that we have exclusive access to the GPIO I/O address range.
376 */
377 gp_gpio_resource = request_region(nas_gpio_io_base, ICH7_GPIO_SIZE,
378 KBUILD_MODNAME);
379 if (NULL == gp_gpio_resource) {
380 dev_info(&dev->dev,
381 "ERROR Unable to register GPIO I/O addresses.\n");
382 status = -1;
383 goto out;
384 }
385
386 /*
387 * Initialize the GPIO for NAS/Home Server Use
388 */
389 ich7_gpio_init(&dev->dev);
390
391 out:
392 if (status) {
393 ich7_lpc_cleanup(&dev->dev);
394 pci_disable_device(dev);
395 }
396 return status;
397 }
398
399 static void ich7_lpc_remove(struct pci_dev *dev)
400 {
401 ich7_lpc_cleanup(&dev->dev);
402 pci_disable_device(dev);
403 }
404
405 /*
406 * pci_driver structure passed to the PCI modules
407 */
408 static struct pci_driver nas_gpio_pci_driver = {
409 .name = KBUILD_MODNAME,
410 .id_table = ich7_lpc_pci_id,
411 .probe = ich7_lpc_probe,
412 .remove = ich7_lpc_remove,
413 };
414
415 static struct led_classdev *get_classdev_for_led_nr(int nr)
416 {
417 struct nasgpio_led *nas_led = &nasgpio_leds[nr];
418 struct led_classdev *led = &nas_led->led_cdev;
419 return led;
420 }
421
422
423 static void set_power_light_amber_noblink(void)
424 {
425 struct nasgpio_led *amber = get_led_named("power:amber:power");
426 struct nasgpio_led *blue = get_led_named("power:blue:power");
427
428 if (!amber || !blue)
429 return;
430 /*
431 * LED_OFF implies disabling future blinking
432 */
433 pr_debug("setting blue off and amber on\n");
434
435 nasgpio_led_set_brightness(&blue->led_cdev, LED_OFF);
436 nasgpio_led_set_brightness(&amber->led_cdev, LED_FULL);
437 }
438
439 static ssize_t nas_led_blink_show(struct device *dev,
440 struct device_attribute *attr, char *buf)
441 {
442 struct led_classdev *led = dev_get_drvdata(dev);
443 int blinking = 0;
444 if (nasgpio_led_get_attr(led, GPO_BLINK))
445 blinking = 1;
446 return sprintf(buf, "%u\n", blinking);
447 }
448
449 static ssize_t nas_led_blink_store(struct device *dev,
450 struct device_attribute *attr,
451 const char *buf, size_t size)
452 {
453 int ret;
454 struct led_classdev *led = dev_get_drvdata(dev);
455 unsigned long blink_state;
456
457 ret = strict_strtoul(buf, 10, &blink_state);
458 if (ret)
459 return ret;
460
461 nasgpio_led_set_attr(led, GPO_BLINK, blink_state);
462
463 return size;
464 }
465
466 static DEVICE_ATTR(blink, 0644, nas_led_blink_show, nas_led_blink_store);
467
468 static int register_nasgpio_led(int led_nr)
469 {
470 int ret;
471 struct nasgpio_led *nas_led = &nasgpio_leds[led_nr];
472 struct led_classdev *led = get_classdev_for_led_nr(led_nr);
473
474 led->name = nas_led->name;
475 led->brightness = LED_OFF;
476 if (nasgpio_led_get_attr(led, GP_LVL))
477 led->brightness = LED_FULL;
478 led->brightness_set = nasgpio_led_set_brightness;
479 led->blink_set = nasgpio_led_set_blink;
480 ret = led_classdev_register(&nas_gpio_pci_dev->dev, led);
481 if (ret)
482 return ret;
483 ret = device_create_file(led->dev, &dev_attr_blink);
484 if (ret)
485 led_classdev_unregister(led);
486 return ret;
487 }
488
489 static void unregister_nasgpio_led(int led_nr)
490 {
491 struct led_classdev *led = get_classdev_for_led_nr(led_nr);
492 led_classdev_unregister(led);
493 device_remove_file(led->dev, &dev_attr_blink);
494 }
495 /*
496 * module load/initialization
497 */
498 static int __init nas_gpio_init(void)
499 {
500 int i;
501 int ret = 0;
502 int nr_devices = 0;
503
504 nr_devices = dmi_check_system(nas_led_whitelist);
505 if (nodetect) {
506 pr_info("skipping hardware autodetection\n");
507 pr_info("Please send 'dmidecode' output to dave@sr71.net\n");
508 nr_devices++;
509 }
510
511 if (nr_devices <= 0) {
512 pr_info("no LED devices found\n");
513 return -ENODEV;
514 }
515
516 pr_info("registering PCI driver\n");
517 ret = pci_register_driver(&nas_gpio_pci_driver);
518 if (ret)
519 return ret;
520 for (i = 0; i < ARRAY_SIZE(nasgpio_leds); i++) {
521 ret = register_nasgpio_led(i);
522 if (ret)
523 goto out_err;
524 }
525 /*
526 * When the system powers on, the BIOS leaves the power
527 * light blue and blinking. This will turn it solid
528 * amber once the driver is loaded.
529 */
530 set_power_light_amber_noblink();
531 return 0;
532 out_err:
533 for (; i >= 0; i--)
534 unregister_nasgpio_led(i);
535 pci_unregister_driver(&nas_gpio_pci_driver);
536 return ret;
537 }
538
539 /*
540 * module unload
541 */
542 static void __exit nas_gpio_exit(void)
543 {
544 int i;
545 pr_info("Unregistering driver\n");
546 for (i = 0; i < ARRAY_SIZE(nasgpio_leds); i++)
547 unregister_nasgpio_led(i);
548 pci_unregister_driver(&nas_gpio_pci_driver);
549 }
550
551 module_init(nas_gpio_init);
552 module_exit(nas_gpio_exit);
553