1/* 2 * drivers/pwm/gpio.c 3 * 4 * Models a single-channel PWM device using a timer and a GPIO pin. 5 * 6 * Copyright (C) 2010 Bill Gatliff <bgat@billgatliff.com> 7 * 8 * This program is free software; you may redistribute and/or modify 9 * it under the terms of the GNU General Public License Version 2, as 10 * published by the Free Software Foundation. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 20 * USA 21 */ 22 23#include <linux/module.h> 24#include <linux/init.h> 25#include <linux/hrtimer.h> 26#include <linux/err.h> 27#include <linux/platform_device.h> 28#include <linux/workqueue.h> 29#include <linux/gpio.h> 30#include <linux/slab.h> 31#include <linux/pwm/pwm.h> 32 33struct gpio_pwm { 34 struct pwm_device pwm; 35 struct hrtimer timer; 36 struct work_struct work; 37 pwm_callback_t callback; 38 int gpio; 39 unsigned long polarity : 1; 40 unsigned long active : 1; 41}; 42 43static inline struct gpio_pwm *to_gpio_pwm(const struct pwm_channel *p) 44{ 45 return container_of(p->pwm, struct gpio_pwm, pwm); 46} 47 48static void 49gpio_pwm_work (struct work_struct *work) 50{ 51 struct gpio_pwm *gp = container_of(work, struct gpio_pwm, work); 52 53 if (gp->active) 54 gpio_direction_output(gp->gpio, gp->polarity ? 1 : 0); 55 else 56 gpio_direction_output(gp->gpio, gp->polarity ? 0 : 1); 57} 58 59static enum hrtimer_restart 60gpio_pwm_timeout(struct hrtimer *t) 61{ 62 struct gpio_pwm *gp = container_of(t, struct gpio_pwm, timer); 63 ktime_t tnew; 64 65 if (unlikely(gp->pwm.channels[0].duty_ticks == 0)) 66 gp->active = 0; 67 else if (unlikely(gp->pwm.channels[0].duty_ticks 68 == gp->pwm.channels[0].period_ticks)) 69 gp->active = 1; 70 else 71 gp->active ^= 1; 72 73 if (gpio_cansleep(gp->gpio)) 74 schedule_work(&gp->work); 75 else 76 gpio_pwm_work(&gp->work); 77 78 if (!gp->active && gp->pwm.channels[0].callback) 79 gp->pwm.channels[0].callback(&gp->pwm.channels[0]); 80 81 if (unlikely(!gp->active && 82 (gp->pwm.channels[0].flags & BIT(FLAG_STOP)))) { 83 clear_bit(FLAG_STOP, &gp->pwm.channels[0].flags); 84 complete_all(&gp->pwm.channels[0].complete); 85 return HRTIMER_NORESTART; 86 } 87 88 if (gp->active) 89 tnew = ktime_set(0, gp->pwm.channels[0].duty_ticks); 90 else 91 tnew = ktime_set(0, gp->pwm.channels[0].period_ticks 92 - gp->pwm.channels[0].duty_ticks); 93 hrtimer_start(&gp->timer, tnew, HRTIMER_MODE_REL); 94 95 return HRTIMER_NORESTART; 96} 97 98static void gpio_pwm_start(struct pwm_channel *p) 99{ 100 struct gpio_pwm *gp = to_gpio_pwm(p); 101 102 gp->active = 0; 103 gpio_pwm_timeout(&gp->timer); 104} 105 106static int 107gpio_pwm_config_nosleep(struct pwm_channel *p, 108 struct pwm_channel_config *c) 109{ 110 struct gpio_pwm *gp = to_gpio_pwm(p); 111 int ret = 0; 112 unsigned long flags; 113 114 spin_lock_irqsave(&p->lock, flags); 115 116 switch (c->config_mask) { 117 118 case PWM_CONFIG_DUTY_TICKS: 119 p->duty_ticks = c->duty_ticks; 120 break; 121 122 case PWM_CONFIG_START: 123 if (!hrtimer_active(&gp->timer)) { 124 gpio_pwm_start(p); 125 } 126 break; 127 default: 128 ret = -EINVAL; 129 break; 130 } 131 132 spin_unlock_irqrestore(&p->lock, flags); 133 return ret; 134} 135 136static int 137gpio_pwm_stop_sync(struct pwm_channel *p) 138{ 139 struct gpio_pwm *gp = to_gpio_pwm(p); 140 int ret; 141 int was_on = hrtimer_active(&gp->timer); 142 143 if (was_on) { 144 do { 145 init_completion(&p->complete); 146 set_bit(FLAG_STOP, &p->flags); 147 ret = wait_for_completion_interruptible(&p->complete); 148 if (ret) 149 return ret; 150 } while (p->flags & BIT(FLAG_STOP)); 151 } 152 153 return was_on; 154} 155 156static int 157gpio_pwm_config(struct pwm_channel *p, 158 struct pwm_channel_config *c) 159{ 160 struct gpio_pwm *gp = to_gpio_pwm(p); 161 int was_on = 0; 162 163 if (p->pwm->config_nosleep) { 164 if (!p->pwm->config_nosleep(p, c)) 165 return 0; 166 } 167 168 might_sleep(); 169 170 was_on = gpio_pwm_stop_sync(p); 171 if (was_on < 0) 172 return was_on; 173 174 if (c->config_mask & PWM_CONFIG_PERIOD_TICKS) 175 p->period_ticks = c->period_ticks; 176 177 if (c->config_mask & PWM_CONFIG_DUTY_TICKS) 178 p->duty_ticks = c->duty_ticks; 179 180 if (c->config_mask & PWM_CONFIG_POLARITY) { 181 gp->polarity = c->polarity ? 1 : 0; 182 p->active_high = gp->polarity; 183 } 184 185 if ((c->config_mask & PWM_CONFIG_START) 186 || (was_on && !(c->config_mask & PWM_CONFIG_STOP))) 187 gpio_pwm_start(p); 188 189 return 0; 190} 191 192static int 193gpio_pwm_set_callback(struct pwm_channel *p, 194 pwm_callback_t callback) 195{ 196 struct gpio_pwm *gp = to_gpio_pwm(p); 197 gp->callback = callback; 198 return 0; 199} 200 201static int 202gpio_pwm_request(struct pwm_channel *p) 203{ 204 p->tick_hz = 1000000000UL; 205 return 0; 206} 207 208static int __devinit 209gpio_pwm_probe(struct platform_device *pdev) 210{ 211 struct gpio_pwm *gp; 212 struct gpio_pwm_platform_data *gpd = pdev->dev.platform_data; 213 int ret = 0; 214 215 /* TODO: create configfs entries, so users can assign GPIOs to 216 * PWMs at runtime instead of creating a platform_device 217 * specification and rebuilding their kernel */ 218 219 if (!gpd || gpio_request(gpd->gpio, dev_name(&pdev->dev))) 220 return -EINVAL; 221 222 gp = kzalloc(sizeof(*gp), GFP_KERNEL); 223 if (!gp) { 224 ret = -ENOMEM; 225 goto err_alloc; 226 } 227 228 platform_set_drvdata(pdev, gp); 229 230 gp->pwm.dev = &pdev->dev; 231 gp->pwm.bus_id = dev_name(&pdev->dev); 232 gp->pwm.nchan = 1; 233 gp->gpio = gpd->gpio; 234 235 INIT_WORK(&gp->work, gpio_pwm_work); 236 237 hrtimer_init(&gp->timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); 238 gp->timer.function = gpio_pwm_timeout; 239 240 gp->pwm.owner = THIS_MODULE; 241 gp->pwm.config_nosleep = gpio_pwm_config_nosleep; 242 gp->pwm.config = gpio_pwm_config; 243 gp->pwm.request = gpio_pwm_request; 244 gp->pwm.set_callback = gpio_pwm_set_callback; 245 246 ret = pwm_register(&gp->pwm); 247 if (ret) 248 goto err_pwm_register; 249 250 return 0; 251 252err_pwm_register: 253 platform_set_drvdata(pdev, 0); 254 kfree(gp); 255err_alloc: 256 return ret; 257} 258 259static int __devexit 260gpio_pwm_remove(struct platform_device *pdev) 261{ 262 struct gpio_pwm *gp = platform_get_drvdata(pdev); 263 int ret; 264 265 ret = pwm_unregister(&gp->pwm); 266 hrtimer_cancel(&gp->timer); 267 cancel_work_sync(&gp->work); 268 platform_set_drvdata(pdev, 0); 269 kfree(gp); 270 271 return 0; 272} 273 274static struct platform_driver gpio_pwm_driver = { 275 .driver = { 276 .name = "gpio_pwm", 277 .owner = THIS_MODULE, 278 }, 279 .probe = gpio_pwm_probe, 280 .remove = __devexit_p(gpio_pwm_remove), 281}; 282 283static int __init gpio_pwm_init(void) 284{ 285 return platform_driver_register(&gpio_pwm_driver); 286} 287module_init(gpio_pwm_init); 288 289static void __exit gpio_pwm_exit(void) 290{ 291 platform_driver_unregister(&gpio_pwm_driver); 292} 293module_exit(gpio_pwm_exit); 294 295MODULE_AUTHOR("Bill Gatliff <bgat@billgatliff.com>"); 296MODULE_DESCRIPTION("PWM output using GPIO and a high-resolution timer"); 297MODULE_LICENSE("GPL"); 298MODULE_ALIAS("platform:gpio_pwm"); 299