root/drivers/input/joystick/as5011.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. as5011_i2c_write
  2. as5011_i2c_read
  3. as5011_button_interrupt
  4. as5011_axis_interrupt
  5. as5011_configure_chip
  6. as5011_probe
  7. as5011_remove

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

/* [<][>][^][v][top][bottom][index][help] */