Blame view

drivers/leds/leds-sunfire.c 5.49 KB
09c434b8a   Thomas Gleixner   treewide: Add SPD...
1
  // SPDX-License-Identifier: GPL-2.0-only
5843492cc   David S. Miller   leds: Add driver ...
2
3
4
5
  /* leds-sunfire.c: SUNW,Ultra-Enterprise LED driver.
   *
   * Copyright (C) 2008 David S. Miller <davem@davemloft.net>
   */
4b07c5d51   Jingoo Han   leds: leds-sunfir...
6
  #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
5843492cc   David S. Miller   leds: Add driver ...
7
8
9
10
11
12
  #include <linux/kernel.h>
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/leds.h>
  #include <linux/io.h>
  #include <linux/platform_device.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
13
  #include <linux/slab.h>
5843492cc   David S. Miller   leds: Add driver ...
14
15
16
  
  #include <asm/fhc.h>
  #include <asm/upa.h>
5843492cc   David S. Miller   leds: Add driver ...
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
  MODULE_AUTHOR("David S. Miller (davem@davemloft.net)");
  MODULE_DESCRIPTION("Sun Fire LED driver");
  MODULE_LICENSE("GPL");
  
  struct sunfire_led {
  	struct led_classdev	led_cdev;
  	void __iomem		*reg;
  };
  #define	to_sunfire_led(d) container_of(d, struct sunfire_led, led_cdev)
  
  static void __clockboard_set(struct led_classdev *led_cdev,
  			     enum led_brightness led_val, u8 bit)
  {
  	struct sunfire_led *p = to_sunfire_led(led_cdev);
  	u8 reg = upa_readb(p->reg);
  
  	switch (bit) {
  	case CLOCK_CTRL_LLED:
  		if (led_val)
  			reg &= ~bit;
  		else
  			reg |= bit;
  		break;
  
  	default:
  		if (led_val)
  			reg |= bit;
  		else
  			reg &= ~bit;
  		break;
  	}
  	upa_writeb(reg, p->reg);
  }
  
  static void clockboard_left_set(struct led_classdev *led_cdev,
  				enum led_brightness led_val)
  {
  	__clockboard_set(led_cdev, led_val, CLOCK_CTRL_LLED);
  }
  
  static void clockboard_middle_set(struct led_classdev *led_cdev,
  				  enum led_brightness led_val)
  {
  	__clockboard_set(led_cdev, led_val, CLOCK_CTRL_MLED);
  }
  
  static void clockboard_right_set(struct led_classdev *led_cdev,
  				 enum led_brightness led_val)
  {
  	__clockboard_set(led_cdev, led_val, CLOCK_CTRL_RLED);
  }
  
  static void __fhc_set(struct led_classdev *led_cdev,
  			     enum led_brightness led_val, u32 bit)
  {
  	struct sunfire_led *p = to_sunfire_led(led_cdev);
  	u32 reg = upa_readl(p->reg);
  
  	switch (bit) {
  	case FHC_CONTROL_LLED:
  		if (led_val)
  			reg &= ~bit;
  		else
  			reg |= bit;
  		break;
  
  	default:
  		if (led_val)
  			reg |= bit;
  		else
  			reg &= ~bit;
  		break;
  	}
  	upa_writel(reg, p->reg);
  }
  
  static void fhc_left_set(struct led_classdev *led_cdev,
  			 enum led_brightness led_val)
  {
  	__fhc_set(led_cdev, led_val, FHC_CONTROL_LLED);
  }
  
  static void fhc_middle_set(struct led_classdev *led_cdev,
  			   enum led_brightness led_val)
  {
  	__fhc_set(led_cdev, led_val, FHC_CONTROL_MLED);
  }
  
  static void fhc_right_set(struct led_classdev *led_cdev,
  			  enum led_brightness led_val)
  {
  	__fhc_set(led_cdev, led_val, FHC_CONTROL_RLED);
  }
  
  typedef void (*set_handler)(struct led_classdev *, enum led_brightness);
  struct led_type {
  	const char	*name;
  	set_handler	handler;
  	const char	*default_trigger;
  };
  
  #define NUM_LEDS_PER_BOARD	3
  struct sunfire_drvdata {
  	struct sunfire_led	leds[NUM_LEDS_PER_BOARD];
  };
98ea1ea20   Bill Pemberton   leds: remove use ...
122
  static int sunfire_led_generic_probe(struct platform_device *pdev,
5843492cc   David S. Miller   leds: Add driver ...
123
124
125
  					       struct led_type *types)
  {
  	struct sunfire_drvdata *p;
e179840ba   Axel Lin   drivers/leds/leds...
126
  	int i, err;
5843492cc   David S. Miller   leds: Add driver ...
127
128
  
  	if (pdev->num_resources != 1) {
4b07c5d51   Jingoo Han   leds: leds-sunfir...
129
130
  		dev_err(&pdev->dev, "Wrong number of resources %d, should be 1
  ",
5843492cc   David S. Miller   leds: Add driver ...
131
  		       pdev->num_resources);
234699a8f   Bryan Wu   leds: convert Sun...
132
  		return -EINVAL;
5843492cc   David S. Miller   leds: Add driver ...
133
  	}
234699a8f   Bryan Wu   leds: convert Sun...
134
  	p = devm_kzalloc(&pdev->dev, sizeof(*p), GFP_KERNEL);
0c9a03b68   Xiubo Li   leds: Remove dupl...
135
  	if (!p)
234699a8f   Bryan Wu   leds: convert Sun...
136
  		return -ENOMEM;
5843492cc   David S. Miller   leds: Add driver ...
137
138
139
140
141
142
143
144
145
146
147
148
  
  	for (i = 0; i < NUM_LEDS_PER_BOARD; i++) {
  		struct led_classdev *lp = &p->leds[i].led_cdev;
  
  		p->leds[i].reg = (void __iomem *) pdev->resource[0].start;
  		lp->name = types[i].name;
  		lp->brightness = LED_FULL;
  		lp->brightness_set = types[i].handler;
  		lp->default_trigger = types[i].default_trigger;
  
  		err = led_classdev_register(&pdev->dev, lp);
  		if (err) {
4b07c5d51   Jingoo Han   leds: leds-sunfir...
149
150
  			dev_err(&pdev->dev, "Could not register %s LED
  ",
5843492cc   David S. Miller   leds: Add driver ...
151
  			       lp->name);
234699a8f   Bryan Wu   leds: convert Sun...
152
153
154
  			for (i--; i >= 0; i--)
  				led_classdev_unregister(&p->leds[i].led_cdev);
  			return err;
5843492cc   David S. Miller   leds: Add driver ...
155
156
  		}
  	}
84196a2ff   Jingoo Han   leds: use platfor...
157
  	platform_set_drvdata(pdev, p);
5843492cc   David S. Miller   leds: Add driver ...
158

e179840ba   Axel Lin   drivers/leds/leds...
159
  	return 0;
5843492cc   David S. Miller   leds: Add driver ...
160
  }
678e8a6be   Bill Pemberton   leds: remove use ...
161
  static int sunfire_led_generic_remove(struct platform_device *pdev)
5843492cc   David S. Miller   leds: Add driver ...
162
  {
84196a2ff   Jingoo Han   leds: use platfor...
163
  	struct sunfire_drvdata *p = platform_get_drvdata(pdev);
5843492cc   David S. Miller   leds: Add driver ...
164
165
166
167
  	int i;
  
  	for (i = 0; i < NUM_LEDS_PER_BOARD; i++)
  		led_classdev_unregister(&p->leds[i].led_cdev);
5843492cc   David S. Miller   leds: Add driver ...
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
  	return 0;
  }
  
  static struct led_type clockboard_led_types[NUM_LEDS_PER_BOARD] = {
  	{
  		.name		= "clockboard-left",
  		.handler	= clockboard_left_set,
  	},
  	{
  		.name		= "clockboard-middle",
  		.handler	= clockboard_middle_set,
  	},
  	{
  		.name		= "clockboard-right",
  		.handler	= clockboard_right_set,
4b07c5d51   Jingoo Han   leds: leds-sunfir...
183
  		.default_trigger = "heartbeat",
5843492cc   David S. Miller   leds: Add driver ...
184
185
  	},
  };
98ea1ea20   Bill Pemberton   leds: remove use ...
186
  static int sunfire_clockboard_led_probe(struct platform_device *pdev)
5843492cc   David S. Miller   leds: Add driver ...
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
  {
  	return sunfire_led_generic_probe(pdev, clockboard_led_types);
  }
  
  static struct led_type fhc_led_types[NUM_LEDS_PER_BOARD] = {
  	{
  		.name		= "fhc-left",
  		.handler	= fhc_left_set,
  	},
  	{
  		.name		= "fhc-middle",
  		.handler	= fhc_middle_set,
  	},
  	{
  		.name		= "fhc-right",
  		.handler	= fhc_right_set,
4b07c5d51   Jingoo Han   leds: leds-sunfir...
203
  		.default_trigger = "heartbeat",
5843492cc   David S. Miller   leds: Add driver ...
204
205
  	},
  };
98ea1ea20   Bill Pemberton   leds: remove use ...
206
  static int sunfire_fhc_led_probe(struct platform_device *pdev)
5843492cc   David S. Miller   leds: Add driver ...
207
208
209
210
211
212
213
214
215
  {
  	return sunfire_led_generic_probe(pdev, fhc_led_types);
  }
  
  MODULE_ALIAS("platform:sunfire-clockboard-leds");
  MODULE_ALIAS("platform:sunfire-fhc-leds");
  
  static struct platform_driver sunfire_clockboard_led_driver = {
  	.probe		= sunfire_clockboard_led_probe,
df07cf812   Bill Pemberton   leds: remove use ...
216
  	.remove		= sunfire_led_generic_remove,
5843492cc   David S. Miller   leds: Add driver ...
217
218
  	.driver		= {
  		.name	= "sunfire-clockboard-leds",
5843492cc   David S. Miller   leds: Add driver ...
219
220
221
222
223
  	},
  };
  
  static struct platform_driver sunfire_fhc_led_driver = {
  	.probe		= sunfire_fhc_led_probe,
df07cf812   Bill Pemberton   leds: remove use ...
224
  	.remove		= sunfire_led_generic_remove,
5843492cc   David S. Miller   leds: Add driver ...
225
226
  	.driver		= {
  		.name	= "sunfire-fhc-leds",
5843492cc   David S. Miller   leds: Add driver ...
227
228
  	},
  };
6e25e641e   Thierry Reding   leds: sunfire: Us...
229
230
231
232
  static struct platform_driver * const drivers[] = {
  	&sunfire_clockboard_led_driver,
  	&sunfire_fhc_led_driver,
  };
5843492cc   David S. Miller   leds: Add driver ...
233
234
  static int __init sunfire_leds_init(void)
  {
6e25e641e   Thierry Reding   leds: sunfire: Us...
235
  	return platform_register_drivers(drivers, ARRAY_SIZE(drivers));
5843492cc   David S. Miller   leds: Add driver ...
236
237
238
239
  }
  
  static void __exit sunfire_leds_exit(void)
  {
6e25e641e   Thierry Reding   leds: sunfire: Us...
240
  	platform_unregister_drivers(drivers, ARRAY_SIZE(drivers));
5843492cc   David S. Miller   leds: Add driver ...
241
242
243
244
  }
  
  module_init(sunfire_leds_init);
  module_exit(sunfire_leds_exit);