1 /* 2 * Copyright (C) ST-Ericsson SA 2010 3 * 4 * Author: Arun R Murthy <arun.murthy@stericsson.com> 5 * License terms: GNU General Public License (GPL) version 2 6 */ 7 #include <linux/err.h> 8 #include <linux/platform_device.h> 9 #include <linux/slab.h> 10 #include <linux/pwm.h> 11 #include <linux/mfd/abx500.h> 12 #include <linux/mfd/abx500/ab8500.h> 13 #include <linux/module.h> 14 15 /* 16 * PWM Out generators 17 * Bank: 0x10 18 */ 19 #define AB8500_PWM_OUT_CTRL1_REG 0x60 20 #define AB8500_PWM_OUT_CTRL2_REG 0x61 21 #define AB8500_PWM_OUT_CTRL7_REG 0x66 22 23 /* backlight driver constants */ 24 #define ENABLE_PWM 1 25 #define DISABLE_PWM 0 26 27 struct ab8500_pwm_chip { 28 struct pwm_chip chip; 29 }; 30 31 static int ab8500_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, 32 int duty_ns, int period_ns) 33 { 34 int ret = 0; 35 unsigned int higher_val, lower_val; 36 u8 reg; 37 38 /* 39 * get the first 8 bits that are be written to 40 * AB8500_PWM_OUT_CTRL1_REG[0:7] 41 */ 42 lower_val = duty_ns & 0x00FF; 43 /* 44 * get bits [9:10] that are to be written to 45 * AB8500_PWM_OUT_CTRL2_REG[0:1] 46 */ 47 higher_val = ((duty_ns & 0x0300) >> 8); 48 49 reg = AB8500_PWM_OUT_CTRL1_REG + ((chip->base - 1) * 2); 50 51 ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC, 52 reg, (u8)lower_val); 53 if (ret < 0) 54 return ret; 55 ret = abx500_set_register_interruptible(chip->dev, AB8500_MISC, 56 (reg + 1), (u8)higher_val); 57 58 return ret; 59 } 60 61 static int ab8500_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) 62 { 63 int ret; 64 65 ret = abx500_mask_and_set_register_interruptible(chip->dev, 66 AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG, 67 1 << (chip->base - 1), ENABLE_PWM); 68 if (ret < 0) 69 dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n", 70 pwm->label, ret); 71 return ret; 72 } 73 74 static void ab8500_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) 75 { 76 int ret; 77 78 ret = abx500_mask_and_set_register_interruptible(chip->dev, 79 AB8500_MISC, AB8500_PWM_OUT_CTRL7_REG, 80 1 << (chip->base - 1), DISABLE_PWM); 81 if (ret < 0) 82 dev_err(chip->dev, "%s: Failed to disable PWM, Error %d\n", 83 pwm->label, ret); 84 return; 85 } 86 87 static const struct pwm_ops ab8500_pwm_ops = { 88 .config = ab8500_pwm_config, 89 .enable = ab8500_pwm_enable, 90 .disable = ab8500_pwm_disable, 91 }; 92 93 static int __devinit ab8500_pwm_probe(struct platform_device *pdev) 94 { 95 struct ab8500_pwm_chip *ab8500; 96 int err; 97 98 /* 99 * Nothing to be done in probe, this is required to get the 100 * device which is required for ab8500 read and write 101 */ 102 ab8500 = kzalloc(sizeof(*ab8500), GFP_KERNEL); 103 if (ab8500 == NULL) { 104 dev_err(&pdev->dev, "failed to allocate memory\n"); 105 return -ENOMEM; 106 } 107 108 ab8500->chip.dev = &pdev->dev; 109 ab8500->chip.ops = &ab8500_pwm_ops; 110 ab8500->chip.base = pdev->id; 111 ab8500->chip.npwm = 1; 112 113 err = pwmchip_add(&ab8500->chip); 114 if (err < 0) { 115 kfree(ab8500); 116 return err; 117 } 118 119 dev_dbg(&pdev->dev, "pwm probe successful\n"); 120 platform_set_drvdata(pdev, ab8500); 121 122 return 0; 123 } 124 125 static int __devexit ab8500_pwm_remove(struct platform_device *pdev) 126 { 127 struct ab8500_pwm_chip *ab8500 = platform_get_drvdata(pdev); 128 int err; 129 130 err = pwmchip_remove(&ab8500->chip); 131 if (err < 0) 132 return err; 133 134 dev_dbg(&pdev->dev, "pwm driver removed\n"); 135 kfree(ab8500); 136 137 return 0; 138 } 139 140 static struct platform_driver ab8500_pwm_driver = { 141 .driver = { 142 .name = "ab8500-pwm", 143 .owner = THIS_MODULE, 144 }, 145 .probe = ab8500_pwm_probe, 146 .remove = __devexit_p(ab8500_pwm_remove), 147 }; 148 module_platform_driver(ab8500_pwm_driver); 149 150 MODULE_AUTHOR("Arun MURTHY <arun.murthy@stericsson.com>"); 151 MODULE_DESCRIPTION("AB8500 Pulse Width Modulation Driver"); 152 MODULE_ALIAS("platform:ab8500-pwm"); 153 MODULE_LICENSE("GPL v2"); 154