Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (C) 2011 Philippe Rétornaz
0003  *
0004  * Based on twl4030-pwrbutton driver by:
0005  *     Peter De Schrijver <peter.de-schrijver@nokia.com>
0006  *     Felipe Balbi <felipe.balbi@nokia.com>
0007  *
0008  * This file is subject to the terms and conditions of the GNU General
0009  * Public License. See the file "COPYING" in the main directory of this
0010  * archive for more details.
0011  *
0012  * This program is distributed in the hope that it will be useful,
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0015  * GNU General Public License for more details.
0016  *
0017  * You should have received a copy of the GNU General Public License
0018  * along with this program; if not, write to the Free Software
0019  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335  USA
0020  */
0021 
0022 #include <linux/module.h>
0023 #include <linux/kernel.h>
0024 #include <linux/errno.h>
0025 #include <linux/input.h>
0026 #include <linux/interrupt.h>
0027 #include <linux/platform_device.h>
0028 #include <linux/mfd/mc13783.h>
0029 #include <linux/sched.h>
0030 #include <linux/slab.h>
0031 
0032 struct mc13783_pwrb {
0033     struct input_dev *pwr;
0034     struct mc13xxx *mc13783;
0035 #define MC13783_PWRB_B1_POL_INVERT  (1 << 0)
0036 #define MC13783_PWRB_B2_POL_INVERT  (1 << 1)
0037 #define MC13783_PWRB_B3_POL_INVERT  (1 << 2)
0038     int flags;
0039     unsigned short keymap[3];
0040 };
0041 
0042 #define MC13783_REG_INTERRUPT_SENSE_1       5
0043 #define MC13783_IRQSENSE1_ONOFD1S       (1 << 3)
0044 #define MC13783_IRQSENSE1_ONOFD2S       (1 << 4)
0045 #define MC13783_IRQSENSE1_ONOFD3S       (1 << 5)
0046 
0047 #define MC13783_REG_POWER_CONTROL_2     15
0048 #define MC13783_POWER_CONTROL_2_ON1BDBNC    4
0049 #define MC13783_POWER_CONTROL_2_ON2BDBNC    6
0050 #define MC13783_POWER_CONTROL_2_ON3BDBNC    8
0051 #define MC13783_POWER_CONTROL_2_ON1BRSTEN   (1 << 1)
0052 #define MC13783_POWER_CONTROL_2_ON2BRSTEN   (1 << 2)
0053 #define MC13783_POWER_CONTROL_2_ON3BRSTEN   (1 << 3)
0054 
0055 static irqreturn_t button_irq(int irq, void *_priv)
0056 {
0057     struct mc13783_pwrb *priv = _priv;
0058     int val;
0059 
0060     mc13xxx_irq_ack(priv->mc13783, irq);
0061     mc13xxx_reg_read(priv->mc13783, MC13783_REG_INTERRUPT_SENSE_1, &val);
0062 
0063     switch (irq) {
0064     case MC13783_IRQ_ONOFD1:
0065         val = val & MC13783_IRQSENSE1_ONOFD1S ? 1 : 0;
0066         if (priv->flags & MC13783_PWRB_B1_POL_INVERT)
0067             val ^= 1;
0068         input_report_key(priv->pwr, priv->keymap[0], val);
0069         break;
0070 
0071     case MC13783_IRQ_ONOFD2:
0072         val = val & MC13783_IRQSENSE1_ONOFD2S ? 1 : 0;
0073         if (priv->flags & MC13783_PWRB_B2_POL_INVERT)
0074             val ^= 1;
0075         input_report_key(priv->pwr, priv->keymap[1], val);
0076         break;
0077 
0078     case MC13783_IRQ_ONOFD3:
0079         val = val & MC13783_IRQSENSE1_ONOFD3S ? 1 : 0;
0080         if (priv->flags & MC13783_PWRB_B3_POL_INVERT)
0081             val ^= 1;
0082         input_report_key(priv->pwr, priv->keymap[2], val);
0083         break;
0084     }
0085 
0086     input_sync(priv->pwr);
0087 
0088     return IRQ_HANDLED;
0089 }
0090 
0091 static int mc13783_pwrbutton_probe(struct platform_device *pdev)
0092 {
0093     const struct mc13xxx_buttons_platform_data *pdata;
0094     struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
0095     struct input_dev *pwr;
0096     struct mc13783_pwrb *priv;
0097     int err = 0;
0098     int reg = 0;
0099 
0100     pdata = dev_get_platdata(&pdev->dev);
0101     if (!pdata) {
0102         dev_err(&pdev->dev, "missing platform data\n");
0103         return -ENODEV;
0104     }
0105 
0106     pwr = input_allocate_device();
0107     if (!pwr) {
0108         dev_dbg(&pdev->dev, "Can't allocate power button\n");
0109         return -ENOMEM;
0110     }
0111 
0112     priv = kzalloc(sizeof(*priv), GFP_KERNEL);
0113     if (!priv) {
0114         err = -ENOMEM;
0115         dev_dbg(&pdev->dev, "Can't allocate power button\n");
0116         goto free_input_dev;
0117     }
0118 
0119     reg |= (pdata->b1on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON1BDBNC;
0120     reg |= (pdata->b2on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON2BDBNC;
0121     reg |= (pdata->b3on_flags & 0x3) << MC13783_POWER_CONTROL_2_ON3BDBNC;
0122 
0123     priv->pwr = pwr;
0124     priv->mc13783 = mc13783;
0125 
0126     mc13xxx_lock(mc13783);
0127 
0128     if (pdata->b1on_flags & MC13783_BUTTON_ENABLE) {
0129         priv->keymap[0] = pdata->b1on_key;
0130         if (pdata->b1on_key != KEY_RESERVED)
0131             __set_bit(pdata->b1on_key, pwr->keybit);
0132 
0133         if (pdata->b1on_flags & MC13783_BUTTON_POL_INVERT)
0134             priv->flags |= MC13783_PWRB_B1_POL_INVERT;
0135 
0136         if (pdata->b1on_flags & MC13783_BUTTON_RESET_EN)
0137             reg |= MC13783_POWER_CONTROL_2_ON1BRSTEN;
0138 
0139         err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD1,
0140                       button_irq, "b1on", priv);
0141         if (err) {
0142             dev_dbg(&pdev->dev, "Can't request irq\n");
0143             goto free_priv;
0144         }
0145     }
0146 
0147     if (pdata->b2on_flags & MC13783_BUTTON_ENABLE) {
0148         priv->keymap[1] = pdata->b2on_key;
0149         if (pdata->b2on_key != KEY_RESERVED)
0150             __set_bit(pdata->b2on_key, pwr->keybit);
0151 
0152         if (pdata->b2on_flags & MC13783_BUTTON_POL_INVERT)
0153             priv->flags |= MC13783_PWRB_B2_POL_INVERT;
0154 
0155         if (pdata->b2on_flags & MC13783_BUTTON_RESET_EN)
0156             reg |= MC13783_POWER_CONTROL_2_ON2BRSTEN;
0157 
0158         err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD2,
0159                       button_irq, "b2on", priv);
0160         if (err) {
0161             dev_dbg(&pdev->dev, "Can't request irq\n");
0162             goto free_irq_b1;
0163         }
0164     }
0165 
0166     if (pdata->b3on_flags & MC13783_BUTTON_ENABLE) {
0167         priv->keymap[2] = pdata->b3on_key;
0168         if (pdata->b3on_key != KEY_RESERVED)
0169             __set_bit(pdata->b3on_key, pwr->keybit);
0170 
0171         if (pdata->b3on_flags & MC13783_BUTTON_POL_INVERT)
0172             priv->flags |= MC13783_PWRB_B3_POL_INVERT;
0173 
0174         if (pdata->b3on_flags & MC13783_BUTTON_RESET_EN)
0175             reg |= MC13783_POWER_CONTROL_2_ON3BRSTEN;
0176 
0177         err = mc13xxx_irq_request(mc13783, MC13783_IRQ_ONOFD3,
0178                       button_irq, "b3on", priv);
0179         if (err) {
0180             dev_dbg(&pdev->dev, "Can't request irq: %d\n", err);
0181             goto free_irq_b2;
0182         }
0183     }
0184 
0185     mc13xxx_reg_rmw(mc13783, MC13783_REG_POWER_CONTROL_2, 0x3FE, reg);
0186 
0187     mc13xxx_unlock(mc13783);
0188 
0189     pwr->name = "mc13783_pwrbutton";
0190     pwr->phys = "mc13783_pwrbutton/input0";
0191     pwr->dev.parent = &pdev->dev;
0192 
0193     pwr->keycode = priv->keymap;
0194     pwr->keycodemax = ARRAY_SIZE(priv->keymap);
0195     pwr->keycodesize = sizeof(priv->keymap[0]);
0196     __set_bit(EV_KEY, pwr->evbit);
0197 
0198     err = input_register_device(pwr);
0199     if (err) {
0200         dev_dbg(&pdev->dev, "Can't register power button: %d\n", err);
0201         goto free_irq;
0202     }
0203 
0204     platform_set_drvdata(pdev, priv);
0205 
0206     return 0;
0207 
0208 free_irq:
0209     mc13xxx_lock(mc13783);
0210 
0211     if (pdata->b3on_flags & MC13783_BUTTON_ENABLE)
0212         mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD3, priv);
0213 
0214 free_irq_b2:
0215     if (pdata->b2on_flags & MC13783_BUTTON_ENABLE)
0216         mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD2, priv);
0217 
0218 free_irq_b1:
0219     if (pdata->b1on_flags & MC13783_BUTTON_ENABLE)
0220         mc13xxx_irq_free(mc13783, MC13783_IRQ_ONOFD1, priv);
0221 
0222 free_priv:
0223     mc13xxx_unlock(mc13783);
0224     kfree(priv);
0225 
0226 free_input_dev:
0227     input_free_device(pwr);
0228 
0229     return err;
0230 }
0231 
0232 static int mc13783_pwrbutton_remove(struct platform_device *pdev)
0233 {
0234     struct mc13783_pwrb *priv = platform_get_drvdata(pdev);
0235     const struct mc13xxx_buttons_platform_data *pdata;
0236 
0237     pdata = dev_get_platdata(&pdev->dev);
0238 
0239     mc13xxx_lock(priv->mc13783);
0240 
0241     if (pdata->b3on_flags & MC13783_BUTTON_ENABLE)
0242         mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD3, priv);
0243     if (pdata->b2on_flags & MC13783_BUTTON_ENABLE)
0244         mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD2, priv);
0245     if (pdata->b1on_flags & MC13783_BUTTON_ENABLE)
0246         mc13xxx_irq_free(priv->mc13783, MC13783_IRQ_ONOFD1, priv);
0247 
0248     mc13xxx_unlock(priv->mc13783);
0249 
0250     input_unregister_device(priv->pwr);
0251     kfree(priv);
0252 
0253     return 0;
0254 }
0255 
0256 static struct platform_driver mc13783_pwrbutton_driver = {
0257     .probe      = mc13783_pwrbutton_probe,
0258     .remove     = mc13783_pwrbutton_remove,
0259     .driver     = {
0260         .name   = "mc13783-pwrbutton",
0261     },
0262 };
0263 
0264 module_platform_driver(mc13783_pwrbutton_driver);
0265 
0266 MODULE_ALIAS("platform:mc13783-pwrbutton");
0267 MODULE_DESCRIPTION("MC13783 Power Button");
0268 MODULE_LICENSE("GPL v2");
0269 MODULE_AUTHOR("Philippe Retornaz");