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 enable 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 .owner = THIS_MODULE, 92 }; 93 94 static int ab8500_pwm_probe(struct platform_device *pdev) 95 { 96 struct ab8500_pwm_chip *ab8500; 97 int err; 98 99 /* 100 * Nothing to be done in probe, this is required to get the 101 * device which is required for ab8500 read and write 102 */ 103 ab8500 = devm_kzalloc(&pdev->dev, sizeof(*ab8500), GFP_KERNEL); 104 if (ab8500 == NULL) { 105 dev_err(&pdev->dev, "failed to allocate memory\n"); 106 return -ENOMEM; 107 } 108 109 ab8500->chip.dev = &pdev->dev; 110 ab8500->chip.ops = &ab8500_pwm_ops; 111 ab8500->chip.base = pdev->id; 112 ab8500->chip.npwm = 1; 113 114 err = pwmchip_add(&ab8500->chip); 115 if (err < 0) 116 return err; 117 118 dev_dbg(&pdev->dev, "pwm probe successful\n"); 119 platform_set_drvdata(pdev, ab8500); 120 121 return 0; 122 } 123 124 static int ab8500_pwm_remove(struct platform_device *pdev) 125 { 126 struct ab8500_pwm_chip *ab8500 = platform_get_drvdata(pdev); 127 int err; 128 129 err = pwmchip_remove(&ab8500->chip); 130 if (err < 0) 131 return err; 132 133 dev_dbg(&pdev->dev, "pwm driver removed\n"); 134 135 return 0; 136 } 137 138 static struct platform_driver ab8500_pwm_driver = { 139 .driver = { 140 .name = "ab8500-pwm", 141 .owner = THIS_MODULE, 142 }, 143 .probe = ab8500_pwm_probe, 144 .remove = ab8500_pwm_remove, 145 }; 146 module_platform_driver(ab8500_pwm_driver); 147 148 MODULE_AUTHOR("Arun MURTHY <arun.murthy@stericsson.com>"); 149 MODULE_DESCRIPTION("AB8500 Pulse Width Modulation Driver"); 150 MODULE_ALIAS("platform:ab8500-pwm"); 151 MODULE_LICENSE("GPL v2"); 152