linux/drivers/input/joystick/as5011.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2010, 2011 Fabien Marteau <fabien.marteau@armadeus.com>
   3 * Sponsored by ARMadeus Systems
   4 *
   5 * This program is free software; you can redistribute it and/or modify
   6 * it under the terms of the GNU General Public License as published by
   7 * the Free Software Foundation; either version 2 of the License, or
   8 * (at your option) any later version.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 *
  15 * You should have received a copy of the GNU General Public License
  16 * along with this program; if not, write to the Free Software
  17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  18 *
  19 * Driver for Austria Microsystems joysticks AS5011
  20 *
  21 * TODO:
  22 *      - Power on the chip when open() and power down when close()
  23 *      - Manage power mode
  24 */
  25
  26#include <linux/i2c.h>
  27#include <linux/interrupt.h>
  28#include <linux/input.h>
  29#include <linux/gpio.h>
  30#include <linux/delay.h>
  31#include <linux/input/as5011.h>
  32#include <linux/slab.h>
  33#include <linux/module.h>
  34
  35#define DRIVER_DESC "Driver for Austria Microsystems AS5011 joystick"
  36#define MODULE_DEVICE_ALIAS "as5011"
  37
  38MODULE_AUTHOR("Fabien Marteau <fabien.marteau@armadeus.com>");
  39MODULE_DESCRIPTION(DRIVER_DESC);
  40MODULE_LICENSE("GPL");
  41
  42/* registers */
  43#define AS5011_CTRL1            0x76
  44#define AS5011_CTRL2            0x75
  45#define AS5011_XP               0x43
  46#define AS5011_XN               0x44
  47#define AS5011_YP               0x53
  48#define AS5011_YN               0x54
  49#define AS5011_X_REG            0x41
  50#define AS5011_Y_REG            0x42
  51#define AS5011_X_RES_INT        0x51
  52#define AS5011_Y_RES_INT        0x52
  53
  54/* CTRL1 bits */
  55#define AS5011_CTRL1_LP_PULSED          0x80
  56#define AS5011_CTRL1_LP_ACTIVE          0x40
  57#define AS5011_CTRL1_LP_CONTINUE        0x20
  58#define AS5011_CTRL1_INT_WUP_EN         0x10
  59#define AS5011_CTRL1_INT_ACT_EN         0x08
  60#define AS5011_CTRL1_EXT_CLK_EN         0x04
  61#define AS5011_CTRL1_SOFT_RST           0x02
  62#define AS5011_CTRL1_DATA_VALID         0x01
  63
  64/* CTRL2 bits */
  65#define AS5011_CTRL2_EXT_SAMPLE_EN      0x08
  66#define AS5011_CTRL2_RC_BIAS_ON         0x04
  67#define AS5011_CTRL2_INV_SPINNING       0x02
  68
  69#define AS5011_MAX_AXIS 80
  70#define AS5011_MIN_AXIS (-80)
  71#define AS5011_FUZZ     8
  72#define AS5011_FLAT     40
  73
  74struct as5011_device {
  75        struct input_dev *input_dev;
  76        struct i2c_client *i2c_client;
  77        unsigned int button_gpio;
  78        unsigned int button_irq;
  79        unsigned int axis_irq;
  80};
  81
  82static int as5011_i2c_write(struct i2c_client *client,
  83                            uint8_t aregaddr,
  84                            uint8_t avalue)
  85{
  86        uint8_t data[2] = { aregaddr, avalue };
  87        struct i2c_msg msg = {
  88                .addr = client->addr,
  89                .flags = I2C_M_IGNORE_NAK,
  90                .len = 2,
  91                .buf = (uint8_t *)data
  92        };
  93        int error;
  94
  95        error = i2c_transfer(client->adapter, &msg, 1);
  96        return error < 0 ? error : 0;
  97}
  98
  99static int as5011_i2c_read(struct i2c_client *client,
 100                           uint8_t aregaddr, signed char *value)
 101{
 102        uint8_t data[2] = { aregaddr };
 103        struct i2c_msg msg_set[2] = {
 104                {
 105                        .addr = client->addr,
 106                        .flags = I2C_M_REV_DIR_ADDR,
 107                        .len = 1,
 108                        .buf = (uint8_t *)data
 109                },
 110                {
 111                        .addr = client->addr,
 112                        .flags = I2C_M_RD | I2C_M_NOSTART,
 113                        .len = 1,
 114                        .buf = (uint8_t *)data
 115                }
 116        };
 117        int error;
 118
 119        error = i2c_transfer(client->adapter, msg_set, 2);
 120        if (error < 0)
 121                return error;
 122
 123        *value = data[0] & 0x80 ? -1 * (1 + ~data[0]) : data[0];
 124        return 0;
 125}
 126
 127static irqreturn_t as5011_button_interrupt(int irq, void *dev_id)
 128{
 129        struct as5011_device *as5011 = dev_id;
 130        int val = gpio_get_value_cansleep(as5011->button_gpio);
 131
 132        input_report_key(as5011->input_dev, BTN_JOYSTICK, !val);
 133        input_sync(as5011->input_dev);
 134
 135        return IRQ_HANDLED;
 136}
 137
 138static irqreturn_t as5011_axis_interrupt(int irq, void *dev_id)
 139{
 140        struct as5011_device *as5011 = dev_id;
 141        int error;
 142        signed char x, y;
 143
 144        error = as5011_i2c_read(as5011->i2c_client, AS5011_X_RES_INT, &x);
 145        if (error < 0)
 146                goto out;
 147
 148        error = as5011_i2c_read(as5011->i2c_client, AS5011_Y_RES_INT, &y);
 149        if (error < 0)
 150                goto out;
 151
 152        input_report_abs(as5011->input_dev, ABS_X, x);
 153        input_report_abs(as5011->input_dev, ABS_Y, y);
 154        input_sync(as5011->input_dev);
 155
 156out:
 157        return IRQ_HANDLED;
 158}
 159
 160static int as5011_configure_chip(struct as5011_device *as5011,
 161                                const struct as5011_platform_data *plat_dat)
 162{
 163        struct i2c_client *client = as5011->i2c_client;
 164        int error;
 165        signed char value;
 166
 167        /* chip soft reset */
 168        error = as5011_i2c_write(client, AS5011_CTRL1,
 169                                 AS5011_CTRL1_SOFT_RST);
 170        if (error < 0) {
 171                dev_err(&client->dev, "Soft reset failed\n");
 172                return error;
 173        }
 174
 175        mdelay(10);
 176
 177        error = as5011_i2c_write(client, AS5011_CTRL1,
 178                                 AS5011_CTRL1_LP_PULSED |
 179                                 AS5011_CTRL1_LP_ACTIVE |
 180                                 AS5011_CTRL1_INT_ACT_EN);
 181        if (error < 0) {
 182                dev_err(&client->dev, "Power config failed\n");
 183                return error;
 184        }
 185
 186        error = as5011_i2c_write(client, AS5011_CTRL2,
 187                                 AS5011_CTRL2_INV_SPINNING);
 188        if (error < 0) {
 189                dev_err(&client->dev, "Can't invert spinning\n");
 190                return error;
 191        }
 192
 193        /* write threshold */
 194        error = as5011_i2c_write(client, AS5011_XP, plat_dat->xp);
 195        if (error < 0) {
 196                dev_err(&client->dev, "Can't write threshold\n");
 197                return error;
 198        }
 199
 200        error = as5011_i2c_write(client, AS5011_XN, plat_dat->xn);
 201        if (error < 0) {
 202                dev_err(&client->dev, "Can't write threshold\n");
 203                return error;
 204        }
 205
 206        error = as5011_i2c_write(client, AS5011_YP, plat_dat->yp);
 207        if (error < 0) {
 208                dev_err(&client->dev, "Can't write threshold\n");
 209                return error;
 210        }
 211
 212        error = as5011_i2c_write(client, AS5011_YN, plat_dat->yn);
 213        if (error < 0) {
 214                dev_err(&client->dev, "Can't write threshold\n");
 215                return error;
 216        }
 217
 218        /* to free irq gpio in chip */
 219        error = as5011_i2c_read(client, AS5011_X_RES_INT, &value);
 220        if (error < 0) {
 221                dev_err(&client->dev, "Can't read i2c X resolution value\n");
 222                return error;
 223        }
 224
 225        return 0;
 226}
 227
 228static int as5011_probe(struct i2c_client *client,
 229                         const struct i2c_device_id *id)
 230{
 231        const struct as5011_platform_data *plat_data;
 232        struct as5011_device *as5011;
 233        struct input_dev *input_dev;
 234        int irq;
 235        int error;
 236
 237        plat_data = dev_get_platdata(&client->dev);
 238        if (!plat_data)
 239                return -EINVAL;
 240
 241        if (!plat_data->axis_irq) {
 242                dev_err(&client->dev, "No axis IRQ?\n");
 243                return -EINVAL;
 244        }
 245
 246        if (!i2c_check_functionality(client->adapter,
 247                                     I2C_FUNC_NOSTART |
 248                                     I2C_FUNC_PROTOCOL_MANGLING)) {
 249                dev_err(&client->dev,
 250                        "need i2c bus that supports protocol mangling\n");
 251                return -ENODEV;
 252        }
 253
 254        as5011 = kmalloc(sizeof(struct as5011_device), GFP_KERNEL);
 255        input_dev = input_allocate_device();
 256        if (!as5011 || !input_dev) {
 257                dev_err(&client->dev,
 258                        "Can't allocate memory for device structure\n");
 259                error = -ENOMEM;
 260                goto err_free_mem;
 261        }
 262
 263        as5011->i2c_client = client;
 264        as5011->input_dev = input_dev;
 265        as5011->button_gpio = plat_data->button_gpio;
 266        as5011->axis_irq = plat_data->axis_irq;
 267
 268        input_dev->name = "Austria Microsystem as5011 joystick";
 269        input_dev->id.bustype = BUS_I2C;
 270        input_dev->dev.parent = &client->dev;
 271
 272        __set_bit(EV_KEY, input_dev->evbit);
 273        __set_bit(EV_ABS, input_dev->evbit);
 274        __set_bit(BTN_JOYSTICK, input_dev->keybit);
 275
 276        input_set_abs_params(input_dev, ABS_X,
 277                AS5011_MIN_AXIS, AS5011_MAX_AXIS, AS5011_FUZZ, AS5011_FLAT);
 278        input_set_abs_params(as5011->input_dev, ABS_Y,
 279                AS5011_MIN_AXIS, AS5011_MAX_AXIS, AS5011_FUZZ, AS5011_FLAT);
 280
 281        error = gpio_request(as5011->button_gpio, "AS5011 button");
 282        if (error < 0) {
 283                dev_err(&client->dev, "Failed to request button gpio\n");
 284                goto err_free_mem;
 285        }
 286
 287        irq = gpio_to_irq(as5011->button_gpio);
 288        if (irq < 0) {
 289                dev_err(&client->dev,
 290                        "Failed to get irq number for button gpio\n");
 291                error = irq;
 292                goto err_free_button_gpio;
 293        }
 294
 295        as5011->button_irq = irq;
 296
 297        error = request_threaded_irq(as5011->button_irq,
 298                                     NULL, as5011_button_interrupt,
 299                                     IRQF_TRIGGER_RISING |
 300                                        IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 301                                     "as5011_button", as5011);
 302        if (error < 0) {
 303                dev_err(&client->dev,
 304                        "Can't allocate button irq %d\n", as5011->button_irq);
 305                goto err_free_button_gpio;
 306        }
 307
 308        error = as5011_configure_chip(as5011, plat_data);
 309        if (error)
 310                goto err_free_button_irq;
 311
 312        error = request_threaded_irq(as5011->axis_irq, NULL,
 313                                     as5011_axis_interrupt,
 314                                     plat_data->axis_irqflags | IRQF_ONESHOT,
 315                                     "as5011_joystick", as5011);
 316        if (error) {
 317                dev_err(&client->dev,
 318                        "Can't allocate axis irq %d\n", plat_data->axis_irq);
 319                goto err_free_button_irq;
 320        }
 321
 322        error = input_register_device(as5011->input_dev);
 323        if (error) {
 324                dev_err(&client->dev, "Failed to register input device\n");
 325                goto err_free_axis_irq;
 326        }
 327
 328        i2c_set_clientdata(client, as5011);
 329
 330        return 0;
 331
 332err_free_axis_irq:
 333        free_irq(as5011->axis_irq, as5011);
 334err_free_button_irq:
 335        free_irq(as5011->button_irq, as5011);
 336err_free_button_gpio:
 337        gpio_free(as5011->button_gpio);
 338err_free_mem:
 339        input_free_device(input_dev);
 340        kfree(as5011);
 341
 342        return error;
 343}
 344
 345static int as5011_remove(struct i2c_client *client)
 346{
 347        struct as5011_device *as5011 = i2c_get_clientdata(client);
 348
 349        free_irq(as5011->axis_irq, as5011);
 350        free_irq(as5011->button_irq, as5011);
 351        gpio_free(as5011->button_gpio);
 352
 353        input_unregister_device(as5011->input_dev);
 354        kfree(as5011);
 355
 356        return 0;
 357}
 358
 359static const struct i2c_device_id as5011_id[] = {
 360        { MODULE_DEVICE_ALIAS, 0 },
 361        { }
 362};
 363MODULE_DEVICE_TABLE(i2c, as5011_id);
 364
 365static struct i2c_driver as5011_driver = {
 366        .driver = {
 367                .name = "as5011",
 368        },
 369        .probe          = as5011_probe,
 370        .remove         = as5011_remove,
 371        .id_table       = as5011_id,
 372};
 373
 374module_i2c_driver(as5011_driver);
 375