2 * LED control using Renesas TPU
4 * Copyright (C) 2011 Magnus Damm
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 #include <linux/module.h>
21 #include <linux/init.h>
22 #include <linux/platform_device.h>
23 #include <linux/spinlock.h>
24 #include <linux/printk.h>
25 #include <linux/ioport.h>
27 #include <linux/clk.h>
28 #include <linux/leds.h>
29 #include <linux/platform_data/leds-renesas-tpu.h>
30 #include <linux/gpio.h>
31 #include <linux/err.h>
32 #include <linux/slab.h>
33 #include <linux/pm_runtime.h>
34 #include <linux/workqueue.h>
36 enum r_tpu_pin
{ R_TPU_PIN_UNUSED
, R_TPU_PIN_GPIO
, R_TPU_PIN_GPIO_FN
};
37 enum r_tpu_timer
{ R_TPU_TIMER_UNUSED
, R_TPU_TIMER_ON
};
40 struct led_classdev ldev
;
41 void __iomem
*mapbase
;
43 struct platform_device
*pdev
;
44 enum r_tpu_pin pin_state
;
45 enum r_tpu_timer timer_state
;
46 unsigned long min_rate
;
47 unsigned int refresh_rate
;
48 struct work_struct work
;
49 enum led_brightness new_brightness
;
52 static DEFINE_SPINLOCK(r_tpu_lock
);
54 #define TSTR -1 /* Timer start register (shared register) */
55 #define TCR 0 /* Timer control register (+0x00) */
56 #define TMDR 1 /* Timer mode register (+0x04) */
57 #define TIOR 2 /* Timer I/O control register (+0x08) */
58 #define TIER 3 /* Timer interrupt enable register (+0x0c) */
59 #define TSR 4 /* Timer status register (+0x10) */
60 #define TCNT 5 /* Timer counter (+0x14) */
61 #define TGRA 6 /* Timer general register A (+0x18) */
62 #define TGRB 7 /* Timer general register B (+0x1c) */
63 #define TGRC 8 /* Timer general register C (+0x20) */
64 #define TGRD 9 /* Timer general register D (+0x24) */
66 static inline unsigned short r_tpu_read(struct r_tpu_priv
*p
, int reg_nr
)
68 struct led_renesas_tpu_config
*cfg
= p
->pdev
->dev
.platform_data
;
69 void __iomem
*base
= p
->mapbase
;
70 unsigned long offs
= reg_nr
<< 2;
73 return ioread16(base
- cfg
->channel_offset
);
75 return ioread16(base
+ offs
);
78 static inline void r_tpu_write(struct r_tpu_priv
*p
, int reg_nr
,
81 struct led_renesas_tpu_config
*cfg
= p
->pdev
->dev
.platform_data
;
82 void __iomem
*base
= p
->mapbase
;
83 unsigned long offs
= reg_nr
<< 2;
86 iowrite16(value
, base
- cfg
->channel_offset
);
90 iowrite16(value
, base
+ offs
);
93 static void r_tpu_start_stop_ch(struct r_tpu_priv
*p
, int start
)
95 struct led_renesas_tpu_config
*cfg
= p
->pdev
->dev
.platform_data
;
96 unsigned long flags
, value
;
98 /* start stop register shared by multiple timer channels */
99 spin_lock_irqsave(&r_tpu_lock
, flags
);
100 value
= r_tpu_read(p
, TSTR
);
103 value
|= 1 << cfg
->timer_bit
;
105 value
&= ~(1 << cfg
->timer_bit
);
107 r_tpu_write(p
, TSTR
, value
);
108 spin_unlock_irqrestore(&r_tpu_lock
, flags
);
111 static int r_tpu_enable(struct r_tpu_priv
*p
, enum led_brightness brightness
)
113 struct led_renesas_tpu_config
*cfg
= p
->pdev
->dev
.platform_data
;
114 int prescaler
[] = { 1, 4, 16, 64 };
116 unsigned long rate
, tmp
;
118 if (p
->timer_state
== R_TPU_TIMER_ON
)
121 /* wake up device and enable clock */
122 pm_runtime_get_sync(&p
->pdev
->dev
);
123 ret
= clk_enable(p
->clk
);
125 dev_err(&p
->pdev
->dev
, "cannot enable clock\n");
129 /* make sure channel is disabled */
130 r_tpu_start_stop_ch(p
, 0);
132 /* get clock rate after enabling it */
133 rate
= clk_get_rate(p
->clk
);
135 /* pick the lowest acceptable rate */
136 for (k
= 0; k
< ARRAY_SIZE(prescaler
); k
++)
137 if ((rate
/ prescaler
[k
]) < p
->min_rate
)
141 dev_err(&p
->pdev
->dev
, "clock rate mismatch\n");
144 dev_dbg(&p
->pdev
->dev
, "rate = %lu, prescaler %u\n",
145 rate
, prescaler
[k
- 1]);
147 /* clear TCNT on TGRB match, count on rising edge, set prescaler */
148 r_tpu_write(p
, TCR
, 0x0040 | (k
- 1));
150 /* output 0 until TGRA, output 1 until TGRB */
151 r_tpu_write(p
, TIOR
, 0x0002);
153 rate
/= prescaler
[k
- 1] * p
->refresh_rate
;
154 r_tpu_write(p
, TGRB
, rate
);
155 dev_dbg(&p
->pdev
->dev
, "TRGB = 0x%04lx\n", rate
);
157 tmp
= (cfg
->max_brightness
- brightness
) * rate
;
158 r_tpu_write(p
, TGRA
, tmp
/ cfg
->max_brightness
);
159 dev_dbg(&p
->pdev
->dev
, "TRGA = 0x%04lx\n", tmp
/ cfg
->max_brightness
);
162 r_tpu_write(p
, TMDR
, 0x0002);
165 r_tpu_start_stop_ch(p
, 1);
167 p
->timer_state
= R_TPU_TIMER_ON
;
171 pm_runtime_put_sync(&p
->pdev
->dev
);
175 static void r_tpu_disable(struct r_tpu_priv
*p
)
177 if (p
->timer_state
== R_TPU_TIMER_UNUSED
)
180 /* disable channel */
181 r_tpu_start_stop_ch(p
, 0);
183 /* stop clock and mark device as idle */
185 pm_runtime_put_sync(&p
->pdev
->dev
);
187 p
->timer_state
= R_TPU_TIMER_UNUSED
;
190 static void r_tpu_set_pin(struct r_tpu_priv
*p
, enum r_tpu_pin new_state
,
191 enum led_brightness brightness
)
193 struct led_renesas_tpu_config
*cfg
= p
->pdev
->dev
.platform_data
;
195 if (p
->pin_state
== new_state
) {
196 if (p
->pin_state
== R_TPU_PIN_GPIO
)
197 gpio_set_value(cfg
->pin_gpio
, brightness
);
201 if (p
->pin_state
== R_TPU_PIN_GPIO
)
202 gpio_free(cfg
->pin_gpio
);
204 if (p
->pin_state
== R_TPU_PIN_GPIO_FN
)
205 gpio_free(cfg
->pin_gpio_fn
);
207 if (new_state
== R_TPU_PIN_GPIO
) {
208 gpio_request(cfg
->pin_gpio
, cfg
->name
);
209 gpio_direction_output(cfg
->pin_gpio
, !!brightness
);
211 if (new_state
== R_TPU_PIN_GPIO_FN
)
212 gpio_request(cfg
->pin_gpio_fn
, cfg
->name
);
214 p
->pin_state
= new_state
;
217 static void r_tpu_work(struct work_struct
*work
)
219 struct r_tpu_priv
*p
= container_of(work
, struct r_tpu_priv
, work
);
220 enum led_brightness brightness
= p
->new_brightness
;
224 /* off and maximum are handled as GPIO pins, in between PWM */
225 if ((brightness
== 0) || (brightness
== p
->ldev
.max_brightness
))
226 r_tpu_set_pin(p
, R_TPU_PIN_GPIO
, brightness
);
228 r_tpu_set_pin(p
, R_TPU_PIN_GPIO_FN
, 0);
229 r_tpu_enable(p
, brightness
);
233 static void r_tpu_set_brightness(struct led_classdev
*ldev
,
234 enum led_brightness brightness
)
236 struct r_tpu_priv
*p
= container_of(ldev
, struct r_tpu_priv
, ldev
);
237 p
->new_brightness
= brightness
;
238 schedule_work(&p
->work
);
241 static int __devinit
r_tpu_probe(struct platform_device
*pdev
)
243 struct led_renesas_tpu_config
*cfg
= pdev
->dev
.platform_data
;
244 struct r_tpu_priv
*p
;
245 struct resource
*res
;
249 dev_err(&pdev
->dev
, "missing platform data\n");
253 p
= kzalloc(sizeof(*p
), GFP_KERNEL
);
255 dev_err(&pdev
->dev
, "failed to allocate driver data\n");
260 res
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
262 dev_err(&pdev
->dev
, "failed to get I/O memory\n");
266 /* map memory, let mapbase point to our channel */
267 p
->mapbase
= ioremap_nocache(res
->start
, resource_size(res
));
268 if (p
->mapbase
== NULL
) {
269 dev_err(&pdev
->dev
, "failed to remap I/O memory\n");
273 /* get hold of clock */
274 p
->clk
= clk_get(&pdev
->dev
, NULL
);
275 if (IS_ERR(p
->clk
)) {
276 dev_err(&pdev
->dev
, "cannot get clock\n");
277 ret
= PTR_ERR(p
->clk
);
282 p
->pin_state
= R_TPU_PIN_UNUSED
;
283 p
->timer_state
= R_TPU_TIMER_UNUSED
;
284 p
->refresh_rate
= cfg
->refresh_rate
? cfg
->refresh_rate
: 100;
285 r_tpu_set_pin(p
, R_TPU_PIN_GPIO
, LED_OFF
);
286 platform_set_drvdata(pdev
, p
);
288 INIT_WORK(&p
->work
, r_tpu_work
);
290 p
->ldev
.name
= cfg
->name
;
291 p
->ldev
.brightness
= LED_OFF
;
292 p
->ldev
.max_brightness
= cfg
->max_brightness
;
293 p
->ldev
.brightness_set
= r_tpu_set_brightness
;
294 p
->ldev
.flags
|= LED_CORE_SUSPENDRESUME
;
295 ret
= led_classdev_register(&pdev
->dev
, &p
->ldev
);
299 /* max_brightness may be updated by the LED core code */
300 p
->min_rate
= p
->ldev
.max_brightness
* p
->refresh_rate
;
302 pm_runtime_enable(&pdev
->dev
);
306 r_tpu_set_pin(p
, R_TPU_PIN_UNUSED
, LED_OFF
);
316 static int __devexit
r_tpu_remove(struct platform_device
*pdev
)
318 struct r_tpu_priv
*p
= platform_get_drvdata(pdev
);
320 r_tpu_set_brightness(&p
->ldev
, LED_OFF
);
321 led_classdev_unregister(&p
->ldev
);
322 cancel_work_sync(&p
->work
);
324 r_tpu_set_pin(p
, R_TPU_PIN_UNUSED
, LED_OFF
);
326 pm_runtime_disable(&pdev
->dev
);
334 static struct platform_driver r_tpu_device_driver
= {
335 .probe
= r_tpu_probe
,
336 .remove
= __devexit_p(r_tpu_remove
),
338 .name
= "leds-renesas-tpu",
342 static int __init
r_tpu_init(void)
344 return platform_driver_register(&r_tpu_device_driver
);
347 static void __exit
r_tpu_exit(void)
349 platform_driver_unregister(&r_tpu_device_driver
);
352 module_init(r_tpu_init
);
353 module_exit(r_tpu_exit
);
355 MODULE_AUTHOR("Magnus Damm");
356 MODULE_DESCRIPTION("Renesas TPU LED Driver");
357 MODULE_LICENSE("GPL v2");