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

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.32-rc7 273 lines 6.1 kB view raw
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 19MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); 20MODULE_DESCRIPTION("Sun Fire LED driver"); 21MODULE_LICENSE("GPL"); 22 23struct 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 29static 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 53static 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 59static 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 65static 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 71static 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 95static 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 101static 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 107static 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 113typedef void (*set_handler)(struct led_classdev *, enum led_brightness); 114struct led_type { 115 const char *name; 116 set_handler handler; 117 const char *default_trigger; 118}; 119 120#define NUM_LEDS_PER_BOARD 3 121struct sunfire_drvdata { 122 struct sunfire_led leds[NUM_LEDS_PER_BOARD]; 123}; 124 125static 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; 163out: 164 return err; 165 166out_unregister_led_cdevs: 167 for (i--; i >= 0; i--) 168 led_classdev_unregister(&p->leds[i].led_cdev); 169 goto out; 170} 171 172static 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 185static 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 201static int __devinit sunfire_clockboard_led_probe(struct platform_device *pdev) 202{ 203 return sunfire_led_generic_probe(pdev, clockboard_led_types); 204} 205 206static 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 222static int __devinit sunfire_fhc_led_probe(struct platform_device *pdev) 223{ 224 return sunfire_led_generic_probe(pdev, fhc_led_types); 225} 226 227MODULE_ALIAS("platform:sunfire-clockboard-leds"); 228MODULE_ALIAS("platform:sunfire-fhc-leds"); 229 230static 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 239static 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 248static 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 266static 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 272module_init(sunfire_leds_init); 273module_exit(sunfire_leds_exit);