1/* 2 * LED control using Renesas TPU 3 * 4 * Copyright (C) 2011 Magnus Damm 5 * 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 9 * 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. 14 * 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 18 */ 19 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> 26#include <linux/io.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> 35 36enum r_tpu_pin { R_TPU_PIN_UNUSED, R_TPU_PIN_GPIO, R_TPU_PIN_GPIO_FN }; 37enum r_tpu_timer { R_TPU_TIMER_UNUSED, R_TPU_TIMER_ON }; 38 39struct r_tpu_priv { 40 struct led_classdev ldev; 41 void __iomem *mapbase; 42 struct clk *clk; 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; 50}; 51 52static DEFINE_SPINLOCK(r_tpu_lock); 53 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) */ 65 66static inline unsigned short r_tpu_read(struct r_tpu_priv *p, int reg_nr) 67{ 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; 71 72 if (reg_nr == TSTR) 73 return ioread16(base - cfg->channel_offset); 74 75 return ioread16(base + offs); 76} 77 78static inline void r_tpu_write(struct r_tpu_priv *p, int reg_nr, 79 unsigned short value) 80{ 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; 84 85 if (reg_nr == TSTR) { 86 iowrite16(value, base - cfg->channel_offset); 87 return; 88 } 89 90 iowrite16(value, base + offs); 91} 92 93static void r_tpu_start_stop_ch(struct r_tpu_priv *p, int start) 94{ 95 struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data; 96 unsigned long flags, value; 97 98 /* start stop register shared by multiple timer channels */ 99 spin_lock_irqsave(&r_tpu_lock, flags); 100 value = r_tpu_read(p, TSTR); 101 102 if (start) 103 value |= 1 << cfg->timer_bit; 104 else 105 value &= ~(1 << cfg->timer_bit); 106 107 r_tpu_write(p, TSTR, value); 108 spin_unlock_irqrestore(&r_tpu_lock, flags); 109} 110 111static int r_tpu_enable(struct r_tpu_priv *p, enum led_brightness brightness) 112{ 113 struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data; 114 int prescaler[] = { 1, 4, 16, 64 }; 115 int k, ret; 116 unsigned long rate, tmp; 117 118 if (p->timer_state == R_TPU_TIMER_ON) 119 return 0; 120 121 /* wake up device and enable clock */ 122 pm_runtime_get_sync(&p->pdev->dev); 123 ret = clk_enable(p->clk); 124 if (ret) { 125 dev_err(&p->pdev->dev, "cannot enable clock\n"); 126 return ret; 127 } 128 129 /* make sure channel is disabled */ 130 r_tpu_start_stop_ch(p, 0); 131 132 /* get clock rate after enabling it */ 133 rate = clk_get_rate(p->clk); 134 135 /* pick the lowest acceptable rate */ 136 for (k = 0; k < ARRAY_SIZE(prescaler); k++) 137 if ((rate / prescaler[k]) < p->min_rate) 138 break; 139 140 if (!k) { 141 dev_err(&p->pdev->dev, "clock rate mismatch\n"); 142 goto err0; 143 } 144 dev_dbg(&p->pdev->dev, "rate = %lu, prescaler %u\n", 145 rate, prescaler[k - 1]); 146 147 /* clear TCNT on TGRB match, count on rising edge, set prescaler */ 148 r_tpu_write(p, TCR, 0x0040 | (k - 1)); 149 150 /* output 0 until TGRA, output 1 until TGRB */ 151 r_tpu_write(p, TIOR, 0x0002); 152 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); 156 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); 160 161 /* PWM mode */ 162 r_tpu_write(p, TMDR, 0x0002); 163 164 /* enable channel */ 165 r_tpu_start_stop_ch(p, 1); 166 167 p->timer_state = R_TPU_TIMER_ON; 168 return 0; 169 err0: 170 clk_disable(p->clk); 171 pm_runtime_put_sync(&p->pdev->dev); 172 return -ENOTSUPP; 173} 174 175static void r_tpu_disable(struct r_tpu_priv *p) 176{ 177 if (p->timer_state == R_TPU_TIMER_UNUSED) 178 return; 179 180 /* disable channel */ 181 r_tpu_start_stop_ch(p, 0); 182 183 /* stop clock and mark device as idle */ 184 clk_disable(p->clk); 185 pm_runtime_put_sync(&p->pdev->dev); 186 187 p->timer_state = R_TPU_TIMER_UNUSED; 188} 189 190static void r_tpu_set_pin(struct r_tpu_priv *p, enum r_tpu_pin new_state, 191 enum led_brightness brightness) 192{ 193 struct led_renesas_tpu_config *cfg = p->pdev->dev.platform_data; 194 195 if (p->pin_state == new_state) { 196 if (p->pin_state == R_TPU_PIN_GPIO) 197 gpio_set_value(cfg->pin_gpio, brightness); 198 return; 199 } 200 201 if (p->pin_state == R_TPU_PIN_GPIO) 202 gpio_free(cfg->pin_gpio); 203 204 if (p->pin_state == R_TPU_PIN_GPIO_FN) 205 gpio_free(cfg->pin_gpio_fn); 206 207 if (new_state == R_TPU_PIN_GPIO) { 208 gpio_request(cfg->pin_gpio, cfg->name); 209 gpio_direction_output(cfg->pin_gpio, !!brightness); 210 } 211 if (new_state == R_TPU_PIN_GPIO_FN) 212 gpio_request(cfg->pin_gpio_fn, cfg->name); 213 214 p->pin_state = new_state; 215} 216 217static void r_tpu_work(struct work_struct *work) 218{ 219 struct r_tpu_priv *p = container_of(work, struct r_tpu_priv, work); 220 enum led_brightness brightness = p->new_brightness; 221 222 r_tpu_disable(p); 223 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); 227 else { 228 r_tpu_set_pin(p, R_TPU_PIN_GPIO_FN, 0); 229 r_tpu_enable(p, brightness); 230 } 231} 232 233static void r_tpu_set_brightness(struct led_classdev *ldev, 234 enum led_brightness brightness) 235{ 236 struct r_tpu_priv *p = container_of(ldev, struct r_tpu_priv, ldev); 237 p->new_brightness = brightness; 238 schedule_work(&p->work); 239} 240 241static int __devinit r_tpu_probe(struct platform_device *pdev) 242{ 243 struct led_renesas_tpu_config *cfg = pdev->dev.platform_data; 244 struct r_tpu_priv *p; 245 struct resource *res; 246 int ret = -ENXIO; 247 248 if (!cfg) { 249 dev_err(&pdev->dev, "missing platform data\n"); 250 goto err0; 251 } 252 253 p = kzalloc(sizeof(*p), GFP_KERNEL); 254 if (p == NULL) { 255 dev_err(&pdev->dev, "failed to allocate driver data\n"); 256 ret = -ENOMEM; 257 goto err0; 258 } 259 260 res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 261 if (!res) { 262 dev_err(&pdev->dev, "failed to get I/O memory\n"); 263 goto err1; 264 } 265 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"); 270 goto err1; 271 } 272 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); 278 goto err2; 279 } 280 281 p->pdev = pdev; 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); 287 288 INIT_WORK(&p->work, r_tpu_work); 289 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); 296 if (ret < 0) 297 goto err3; 298 299 /* max_brightness may be updated by the LED core code */ 300 p->min_rate = p->ldev.max_brightness * p->refresh_rate; 301 302 pm_runtime_enable(&pdev->dev); 303 return 0; 304 305 err3: 306 r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF); 307 clk_put(p->clk); 308 err2: 309 iounmap(p->mapbase); 310 err1: 311 kfree(p); 312 err0: 313 return ret; 314} 315 316static int __devexit r_tpu_remove(struct platform_device *pdev) 317{ 318 struct r_tpu_priv *p = platform_get_drvdata(pdev); 319 320 r_tpu_set_brightness(&p->ldev, LED_OFF); 321 led_classdev_unregister(&p->ldev); 322 cancel_work_sync(&p->work); 323 r_tpu_disable(p); 324 r_tpu_set_pin(p, R_TPU_PIN_UNUSED, LED_OFF); 325 326 pm_runtime_disable(&pdev->dev); 327 clk_put(p->clk); 328 329 iounmap(p->mapbase); 330 kfree(p); 331 return 0; 332} 333 334static struct platform_driver r_tpu_device_driver = { 335 .probe = r_tpu_probe, 336 .remove = __devexit_p(r_tpu_remove), 337 .driver = { 338 .name = "leds-renesas-tpu", 339 } 340}; 341 342module_platform_driver(r_tpu_device_driver); 343 344MODULE_AUTHOR("Magnus Damm"); 345MODULE_DESCRIPTION("Renesas TPU LED Driver"); 346MODULE_LICENSE("GPL v2"); 347