Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

leds: Add driver for Sunfire UltraSPARC server LEDs.

Signed-off-by: David S. Miller <davem@davemloft.net>

+282
+8
drivers/leds/Kconfig
··· 96 96 help 97 97 This option enables support for the Cobalt Raq series LEDs. 98 98 99 + config LEDS_SUNFIRE 100 + tristate "LED support for SunFire servers." 101 + depends on LEDS_CLASS && SPARC64 102 + select LEDS_TRIGGERS 103 + help 104 + This option enables support for the Left, Middle, and Right 105 + LEDs on the I/O and CPU boards of SunFire UltraSPARC servers. 106 + 99 107 config LEDS_HP6XX 100 108 tristate "LED Support for the HP Jornada 6xx" 101 109 depends on LEDS_CLASS && SH_HP6XX
+1
drivers/leds/Makefile
··· 16 16 obj-$(CONFIG_LEDS_H1940) += leds-h1940.o 17 17 obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o 18 18 obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o 19 + obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o 19 20 obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o 20 21 obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o 21 22 obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o
+273
drivers/leds/leds-sunfire.c
··· 1 + /* leds-sunfire.c: SUNW,Ultra-Enterprise LED driver. 2 + * 3 + * Copyright (C) 2008 David S. Miller <davem@davemloft.net> 4 + */ 5 + 6 + #include <linux/kernel.h> 7 + #include <linux/module.h> 8 + #include <linux/init.h> 9 + #include <linux/leds.h> 10 + #include <linux/io.h> 11 + #include <linux/platform_device.h> 12 + 13 + #include <asm/fhc.h> 14 + #include <asm/upa.h> 15 + 16 + #define DRIVER_NAME "leds-sunfire" 17 + #define PFX DRIVER_NAME ": " 18 + 19 + MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); 20 + MODULE_DESCRIPTION("Sun Fire LED driver"); 21 + MODULE_LICENSE("GPL"); 22 + 23 + struct sunfire_led { 24 + struct led_classdev led_cdev; 25 + void __iomem *reg; 26 + }; 27 + #define to_sunfire_led(d) container_of(d, struct sunfire_led, led_cdev) 28 + 29 + static void __clockboard_set(struct led_classdev *led_cdev, 30 + enum led_brightness led_val, u8 bit) 31 + { 32 + struct sunfire_led *p = to_sunfire_led(led_cdev); 33 + u8 reg = upa_readb(p->reg); 34 + 35 + switch (bit) { 36 + case CLOCK_CTRL_LLED: 37 + if (led_val) 38 + reg &= ~bit; 39 + else 40 + reg |= bit; 41 + break; 42 + 43 + default: 44 + if (led_val) 45 + reg |= bit; 46 + else 47 + reg &= ~bit; 48 + break; 49 + } 50 + upa_writeb(reg, p->reg); 51 + } 52 + 53 + static void clockboard_left_set(struct led_classdev *led_cdev, 54 + enum led_brightness led_val) 55 + { 56 + __clockboard_set(led_cdev, led_val, CLOCK_CTRL_LLED); 57 + } 58 + 59 + static void clockboard_middle_set(struct led_classdev *led_cdev, 60 + enum led_brightness led_val) 61 + { 62 + __clockboard_set(led_cdev, led_val, CLOCK_CTRL_MLED); 63 + } 64 + 65 + static void clockboard_right_set(struct led_classdev *led_cdev, 66 + enum led_brightness led_val) 67 + { 68 + __clockboard_set(led_cdev, led_val, CLOCK_CTRL_RLED); 69 + } 70 + 71 + static void __fhc_set(struct led_classdev *led_cdev, 72 + enum led_brightness led_val, u32 bit) 73 + { 74 + struct sunfire_led *p = to_sunfire_led(led_cdev); 75 + u32 reg = upa_readl(p->reg); 76 + 77 + switch (bit) { 78 + case FHC_CONTROL_LLED: 79 + if (led_val) 80 + reg &= ~bit; 81 + else 82 + reg |= bit; 83 + break; 84 + 85 + default: 86 + if (led_val) 87 + reg |= bit; 88 + else 89 + reg &= ~bit; 90 + break; 91 + } 92 + upa_writel(reg, p->reg); 93 + } 94 + 95 + static void fhc_left_set(struct led_classdev *led_cdev, 96 + enum led_brightness led_val) 97 + { 98 + __fhc_set(led_cdev, led_val, FHC_CONTROL_LLED); 99 + } 100 + 101 + static void fhc_middle_set(struct led_classdev *led_cdev, 102 + enum led_brightness led_val) 103 + { 104 + __fhc_set(led_cdev, led_val, FHC_CONTROL_MLED); 105 + } 106 + 107 + static void fhc_right_set(struct led_classdev *led_cdev, 108 + enum led_brightness led_val) 109 + { 110 + __fhc_set(led_cdev, led_val, FHC_CONTROL_RLED); 111 + } 112 + 113 + typedef void (*set_handler)(struct led_classdev *, enum led_brightness); 114 + struct led_type { 115 + const char *name; 116 + set_handler handler; 117 + const char *default_trigger; 118 + }; 119 + 120 + #define NUM_LEDS_PER_BOARD 3 121 + struct sunfire_drvdata { 122 + struct sunfire_led leds[NUM_LEDS_PER_BOARD]; 123 + }; 124 + 125 + static int __devinit sunfire_led_generic_probe(struct platform_device *pdev, 126 + struct led_type *types) 127 + { 128 + struct sunfire_drvdata *p; 129 + int i, err = -EINVAL; 130 + 131 + if (pdev->num_resources != 1) { 132 + printk(KERN_ERR PFX "Wrong number of resources %d, should be 1\n", 133 + pdev->num_resources); 134 + goto out; 135 + } 136 + 137 + p = kzalloc(sizeof(*p), GFP_KERNEL); 138 + if (!p) { 139 + printk(KERN_ERR PFX "Could not allocate struct sunfire_drvdata\n"); 140 + goto out; 141 + } 142 + 143 + for (i = 0; i < NUM_LEDS_PER_BOARD; i++) { 144 + struct led_classdev *lp = &p->leds[i].led_cdev; 145 + 146 + p->leds[i].reg = (void __iomem *) pdev->resource[0].start; 147 + lp->name = types[i].name; 148 + lp->brightness = LED_FULL; 149 + lp->brightness_set = types[i].handler; 150 + lp->default_trigger = types[i].default_trigger; 151 + 152 + err = led_classdev_register(&pdev->dev, lp); 153 + if (err) { 154 + printk(KERN_ERR PFX "Could not register %s LED\n", 155 + lp->name); 156 + goto out_unregister_led_cdevs; 157 + } 158 + } 159 + 160 + dev_set_drvdata(&pdev->dev, p); 161 + 162 + err = 0; 163 + out: 164 + return err; 165 + 166 + out_unregister_led_cdevs: 167 + for (i--; i >= 0; i--) 168 + led_classdev_unregister(&p->leds[i].led_cdev); 169 + goto out; 170 + } 171 + 172 + static int __devexit sunfire_led_generic_remove(struct platform_device *pdev) 173 + { 174 + struct sunfire_drvdata *p = dev_get_drvdata(&pdev->dev); 175 + int i; 176 + 177 + for (i = 0; i < NUM_LEDS_PER_BOARD; i++) 178 + led_classdev_unregister(&p->leds[i].led_cdev); 179 + 180 + kfree(p); 181 + 182 + return 0; 183 + } 184 + 185 + static struct led_type clockboard_led_types[NUM_LEDS_PER_BOARD] = { 186 + { 187 + .name = "clockboard-left", 188 + .handler = clockboard_left_set, 189 + }, 190 + { 191 + .name = "clockboard-middle", 192 + .handler = clockboard_middle_set, 193 + }, 194 + { 195 + .name = "clockboard-right", 196 + .handler = clockboard_right_set, 197 + .default_trigger= "heartbeat", 198 + }, 199 + }; 200 + 201 + static int __devinit sunfire_clockboard_led_probe(struct platform_device *pdev) 202 + { 203 + return sunfire_led_generic_probe(pdev, clockboard_led_types); 204 + } 205 + 206 + static struct led_type fhc_led_types[NUM_LEDS_PER_BOARD] = { 207 + { 208 + .name = "fhc-left", 209 + .handler = fhc_left_set, 210 + }, 211 + { 212 + .name = "fhc-middle", 213 + .handler = fhc_middle_set, 214 + }, 215 + { 216 + .name = "fhc-right", 217 + .handler = fhc_right_set, 218 + .default_trigger= "heartbeat", 219 + }, 220 + }; 221 + 222 + static int __devinit sunfire_fhc_led_probe(struct platform_device *pdev) 223 + { 224 + return sunfire_led_generic_probe(pdev, fhc_led_types); 225 + } 226 + 227 + MODULE_ALIAS("platform:sunfire-clockboard-leds"); 228 + MODULE_ALIAS("platform:sunfire-fhc-leds"); 229 + 230 + static struct platform_driver sunfire_clockboard_led_driver = { 231 + .probe = sunfire_clockboard_led_probe, 232 + .remove = __devexit_p(sunfire_led_generic_remove), 233 + .driver = { 234 + .name = "sunfire-clockboard-leds", 235 + .owner = THIS_MODULE, 236 + }, 237 + }; 238 + 239 + static struct platform_driver sunfire_fhc_led_driver = { 240 + .probe = sunfire_fhc_led_probe, 241 + .remove = __devexit_p(sunfire_led_generic_remove), 242 + .driver = { 243 + .name = "sunfire-fhc-leds", 244 + .owner = THIS_MODULE, 245 + }, 246 + }; 247 + 248 + static int __init sunfire_leds_init(void) 249 + { 250 + int err = platform_driver_register(&sunfire_clockboard_led_driver); 251 + 252 + if (err) { 253 + printk(KERN_ERR PFX "Could not register clock board LED driver\n"); 254 + return err; 255 + } 256 + 257 + err = platform_driver_register(&sunfire_fhc_led_driver); 258 + if (err) { 259 + printk(KERN_ERR PFX "Could not register FHC LED driver\n"); 260 + platform_driver_unregister(&sunfire_clockboard_led_driver); 261 + } 262 + 263 + return err; 264 + } 265 + 266 + static void __exit sunfire_leds_exit(void) 267 + { 268 + platform_driver_unregister(&sunfire_clockboard_led_driver); 269 + platform_driver_unregister(&sunfire_fhc_led_driver); 270 + } 271 + 272 + module_init(sunfire_leds_init); 273 + module_exit(sunfire_leds_exit);