1 /* 2 * Copyright (C) 2011 Philippe Rétornaz 3 * 4 * Based on twl4030-pwrbutton driver by: 5 * Peter De Schrijver <peter.de-schrijver@nokia.com> 6 * Felipe Balbi <felipe.balbi@nokia.com> 7 * 8 * This file is subject to the terms and conditions of the GNU General 9 * Public License. See the file "COPYING" in the main directory of this 10 * archive for more details. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU 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., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA 20 */ 21 22 #include <linux/module.h> 23 #include <linux/kernel.h> 24 #include <linux/errno.h> 25 #include <linux/input.h> 26 #include <linux/interrupt.h> 27 #include <linux/platform_device.h> 28 #include <linux/mfd/mc13783.h> 29 #include <linux/sched.h> 30 #include <linux/slab.h> 31 32 struct mc13783_pwrb { 33 struct input_dev *pwr; 34 struct mc13xxx *mc13783; 35 #define MC13783_PWRB_B1_POL_INVERT (1 << 0) 36 #define MC13783_PWRB_B2_POL_INVERT (1 << 1) 37 #define MC13783_PWRB_B3_POL_INVERT (1 << 2) 38 int flags; 39 unsigned short keymap[3]; 40 }; 41 42 #define MC13783_REG_INTERRUPT_SENSE_1 5 43 #define MC13783_IRQSENSE1_ONOFD1S (1 << 3) 44 #define MC13783_IRQSENSE1_ONOFD2S (1 << 4) 45 #define MC13783_IRQSENSE1_ONOFD3S (1 << 5) 46 47 #define MC13783_REG_POWER_CONTROL_2 15 48 #define MC13783_POWER_CONTROL_2_ON1BDBNC 4 49 #define MC13783_POWER_CONTROL_2_ON2BDBNC 6 50 #define MC13783_POWER_CONTROL_2_ON3BDBNC 8 51 #define MC13783_POWER_CONTROL_2_ON1BRSTEN (1 << 1) 52 #define MC13783_POWER_CONTROL_2_ON2BRSTEN (1 << 2) 53 #define MC13783_POWER_CONTROL_2_ON3BRSTEN (1 << 3) 54 55 static irqreturn_t button_irq(int irq, void *_priv) 56 { 57 struct mc13783_pwrb *priv = _priv; 58 int val; 59 60 mc13xxx_reg_read(priv->mc13783, MC13783_REG_INTERRUPT_SENSE_1, &val); 61 62 switch (irq) { 63 case MC13783_IRQ_ONOFD1: 64 val = val & MC13783_IRQSENSE1_ONOFD1S ? 1 : 0; 65 if (priv->flags & MC13783_PWRB_B1_POL_INVERT) 66 val ^= 1; 67 input_report_key(priv->pwr, priv->keymap[0], val); 68 break; 69 70 case MC13783_IRQ_ONOFD2: 71 val = val & MC13783_IRQSENSE1_ONOFD2S ? 1 : 0; 72 if (priv->flags & MC13783_PWRB_B2_POL_INVERT) 73 val ^= 1; 74 input_report_key(priv->pwr, priv->keymap[1], val); 75 break; 76 77 case MC13783_IRQ_ONOFD3: 78 val = val & MC13783_IRQSENSE1_ONOFD3S ? 1 : 0; 79 if (priv->flags & MC13783_PWRB_B3_POL_INVERT) 80 val ^= 1; 81 input_report_key(priv->pwr, priv->keymap[2], val); 82 break; 83 } 84 85 input_sync(priv->pwr); 86 87 return IRQ_HANDLED; 88 } 89 90 static int mc13783_pwrbutton_probe(struct platform_device *pdev) 91 { 92 const struct mc13xxx_buttons_platform_data *pdata; 93 struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent); 94 struct input_dev *pwr; 95 struct mc13783_pwrb *priv; 96 int err = 0; 97 int reg = 0; 98 99 pdata = dev_get_platdata(&pdev->dev); 100 if (!pdata) { 101 dev_err(&pdev->dev, "missing platform data\n"); 102 return -ENODEV; 103 } 104 105 pwr = input_allocate_device(); 106 if (!pwr) { 107 dev_dbg(&pdev->dev, "Can't allocate power button\n"); 108 return -ENOMEM; 109 } 110 111 priv = kzalloc(sizeof(*priv), GFP_KERNEL); 112 if (!priv) { 113 err = -ENOMEM; 114 dev_dbg(&pdev->dev, "Can't allocate power button\n"); 115 goto free_input_dev; 116 } 117 118 reg |= (pdata->b1on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON1BDBNC; 119 reg |= (pdata->b2on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON2BDBNC; 120 reg |= (pdata->b3on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON3BDBNC; 121 122 priv->pwr = pwr; 123 priv->mc13783 = mc13783; 124 125 mc13xxx_lock(mc13783); 126 127 if (pdata->b1on_flags & MC13783_BUTTON_ENABLE) { 128 priv->keymap[0] = pdata->b1on_key; 129 if (pdata->b1on_key != KEY_RESERVED) 130 __set_bit(pdata->b1on_key, pwr->keybit); 131 132 if (pdata->b1on_flags & MC13783_BUTTON_POL_INVERT) 133 priv->flags |= MC13783_PWRB_B1_POL_INVERT; 134 135 if (pdata->b1on_flags & MC13783_BUTTON_RESET_EN) 136 reg |= MC13783_POWER_CONTROL_2_ON1BRSTEN; 137 138 err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD1, 139 button_irq, "b1on", priv); 140 if (err) { 141 dev_dbg(&pdev->dev, "Can't request irq\n"); 142 goto free_priv; 143 } 144 } 145 146 if (pdata->b2on_flags & MC13783_BUTTON_ENABLE) { 147 priv->keymap[1] = pdata->b2on_key; 148 if (pdata->b2on_key != KEY_RESERVED) 149 __set_bit(pdata->b2on_key, pwr->keybit); 150 151 if (pdata->b2on_flags & MC13783_BUTTON_POL_INVERT) 152 priv->flags |= MC13783_PWRB_B2_POL_INVERT; 153 154 if (pdata->b2on_flags & MC13783_BUTTON_RESET_EN) 155 reg |= MC13783_POWER_CONTROL_2_ON2BRSTEN; 156 157 err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD2, 158 button_irq, "b2on", priv); 159 if (err) { 160 dev_dbg(&pdev->dev, "Can't request irq\n"); 161 goto free_irq_b1; 162 } 163 } 164 165 if (pdata->b3on_flags & MC13783_BUTTON_ENABLE) { 166 priv->keymap[2] = pdata->b3on_key; 167 if (pdata->b3on_key != KEY_RESERVED) 168 __set_bit(pdata->b3on_key, pwr->keybit); 169 170 if (pdata->b3on_flags & MC13783_BUTTON_POL_INVERT) 171 priv->flags |= MC13783_PWRB_B3_POL_INVERT; 172 173 if (pdata->b3on_flags & MC13783_BUTTON_RESET_EN) 174 reg |= MC13783_POWER_CONTROL_2_ON3BRSTEN; 175 176 err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD3, 177 button_irq, "b3on", priv); 178 if (err) { 179 dev_dbg(&pdev->dev, "Can't request irq: %d\n", err); 180 goto free_irq_b2; 181 } 182 } 183 184 mc13xxx_reg_rmw(mc13783, MC13783_REG_POWER_CONTROL_2, 0x3FE, reg); 185 186 mc13xxx_unlock(mc13783); 187 188 pwr->name = "mc13783_pwrbutton"; 189 pwr->phys = "mc13783_pwrbutton/input0"; 190 pwr->dev.parent = &pdev->dev; 191 192 pwr->keycode = priv->keymap; 193 pwr->keycodemax = ARRAY_SIZE(priv->keymap); 194 pwr->keycodesize = sizeof(priv->keymap[0]); 195 __set_bit(EV_KEY, pwr->evbit); 196 197 err = input_register_device(pwr); 198 if (err) { 199 dev_dbg(&pdev->dev, "Can't register power button: %d\n", err); 200 goto free_irq; 201 } 202 203 platform_set_drvdata(pdev, priv); 204 205 return 0; 206 207 free_irq: 208 mc13xxx_lock(mc13783); 209 210 if (pdata->b3on_flags & MC13783_BUTTON_ENABLE) 211 mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD3, priv); 212 213 free_irq_b2: 214 if (pdata->b2on_flags & MC13783_BUTTON_ENABLE) 215 mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD2, priv); 216 217 free_irq_b1: 218 if (pdata->b1on_flags & MC13783_BUTTON_ENABLE) 219 mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD1, priv); 220 221 free_priv: 222 mc13xxx_unlock(mc13783); 223 kfree(priv); 224 225 free_input_dev: 226 input_free_device(pwr); 227 228 return err; 229 } 230 231 static void mc13783_pwrbutton_remove(struct platform_device *pdev) 232 { 233 struct mc13783_pwrb *priv = platform_get_drvdata(pdev); 234 const struct mc13xxx_buttons_platform_data *pdata; 235 236 pdata = dev_get_platdata(&pdev->dev); 237 238 mc13xxx_lock(priv->mc13783); 239 240 if (pdata->b3on_flags & MC13783_BUTTON_ENABLE) 241 mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD3, priv); 242 if (pdata->b2on_flags & MC13783_BUTTON_ENABLE) 243 mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD2, priv); 244 if (pdata->b1on_flags & MC13783_BUTTON_ENABLE) 245 mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD1, priv); 246 247 mc13xxx_unlock(priv->mc13783); 248 249 input_unregister_device(priv->pwr); 250 kfree(priv); 251 } 252 253 static struct platform_driver mc13783_pwrbutton_driver = { 254 .probe = mc13783_pwrbutton_probe, 255 .remove = mc13783_pwrbutton_remove, 256 .driver = { 257 .name = "mc13783-pwrbutton", 258 }, 259 }; 260 261 module_platform_driver(mc13783_pwrbutton_driver); 262 263 MODULE_ALIAS("platform:mc13783-pwrbutton"); 264 MODULE_DESCRIPTION("MC13783 Power Button"); 265 MODULE_LICENSE("GPL v2"); 266 MODULE_AUTHOR("Philippe Retornaz"); 267