| 1 | |
| 2 |
|
| 3 | #include <linux/array_size.h>
|
| 4 | #include <linux/bitmap.h>
|
| 5 | #include <linux/bits.h>
|
| 6 | #include <linux/clk.h>
|
| 7 | #include <linux/delay.h>
|
| 8 | #include <linux/device.h>
|
| 9 | #include <linux/devm-helpers.h>
|
| 10 | #include <linux/err.h>
|
| 11 | #include <linux/gpio/consumer.h>
|
| 12 | #include <linux/i2c.h>
|
| 13 | #include <linux/input.h>
|
| 14 | #include <linux/kernel.h>
|
| 15 | #include <linux/module.h>
|
| 16 | #include <linux/property.h>
|
| 17 | #include <linux/pwm.h>
|
| 18 | #include <linux/regmap.h>
|
| 19 | #include <linux/regulator/consumer.h>
|
| 20 | #include <linux/units.h>
|
| 21 |
|
| 22 | |
| 23 | * System control (LDO regulator)
|
| 24 | *
|
| 25 | * LDO voltage to register mapping is linear, but it is split in two parts:
|
| 26 | * 2.3V - 3.0V map to 0x08 - 0x0f; 3.1V - 3.8V map to 0x00 - 0x7
|
| 27 |
|
| 28 |
|
| 29 | #define ISA1200_SCTRL 0x00
|
| 30 | #define ISA1200_LDO_VOLTAGE_BASE 0x08
|
| 31 | #define ISA1200_LDO_VOLTAGE_STEP 100000
|
| 32 | #define ISA1200_LDO_VOLTAGE_2V3 23
|
| 33 | #define ISA1200_LDO_VOLTAGE_3V1 31
|
| 34 | #define ISA1200_LDO_VOLTAGE_MIN 2300000
|
| 35 | #define ISA1200_LDO_VOLTAGE_MAX 3800000
|
| 36 |
|
| 37 | |
| 38 | * The output frequency is calculated with this formula:
|
| 39 | *
|
| 40 | * base clock frequency
|
| 41 | * fout = -----------------------------------------
|
| 42 | * (128 - PWM_FREQ) * 2 * PLLDIV * PWM_PERIOD
|
| 43 | *
|
| 44 | * The base clock frequency is the clock frequency provided on the
|
| 45 | * clock input to the chip, divided by the value in HCTRL0
|
| 46 | *
|
| 47 | * PWM_FREQ is configured in register HCTRL4, it is common to set this
|
| 48 | * to 0 to get only two variables to calculate.
|
| 49 | *
|
| 50 | * PLLDIV is configured in register HCTRL3 (bits 7..4, so 0..15)
|
| 51 | * PWM_PERIOD is configured in register HCTRL6
|
| 52 | * Further the duty cycle can be configured in HCTRL5
|
| 53 |
|
| 54 |
|
| 55 | |
| 56 | * HCTRL0 configures clock or PWM input and selects the divider for
|
| 57 | * the clock input.
|
| 58 |
|
| 59 | #define ISA1200_HCTRL0 0x30
|
| 60 | #define ISA1200_HCTRL0_HAP_ENABLE BIT(7)
|
| 61 | #define ISA1200_HCTRL0_PWM_GEN_MODE BIT(4)
|
| 62 | #define ISA1200_HCTRL0_PWM_INPUT_MODE BIT(3)
|
| 63 | #define ISA1200_HCTRL0_CLKDIV_128 128
|
| 64 |
|
| 65 | |
| 66 | * HCTRL1 configures the motor type and clock sourse
|
| 67 |
|
| 68 | #define ISA1200_HCTRL1 0x31
|
| 69 | #define ISA1200_HCTRL1_EXT_CLOCK BIT(7)
|
| 70 | #define ISA1200_HCTRL1_DAC_INVERT BIT(6)
|
| 71 | #define ISA1200_HCTRL1_MODE(n) (((n) & 1) << 5)
|
| 72 |
|
| 73 |
|
| 74 | #define ISA1200_HCTRL2 0x32
|
| 75 | #define ISA1200_HCTRL2_SW_RESET BIT(0)
|
| 76 |
|
| 77 | |
| 78 | * HCTRL3 controls the PLL divisor
|
| 79 | *
|
| 80 | * Bits [0,1] are always set to 1 (we don't know what they are
|
| 81 | * used for) and bit 4 and upward control the PLL divisor.
|
| 82 |
|
| 83 | #define ISA1200_HCTRL3 0x33
|
| 84 | #define ISA1200_HCTRL3_DEFAULT 0x03
|
| 85 | #define ISA1200_HCTRL3_PLLDIV(n) (((n) & 0xf) << 4)
|
| 86 |
|
| 87 |
|
| 88 | #define ISA1200_HCTRL4 0x34
|
| 89 |
|
| 90 |
|
| 91 | #define ISA1200_HCTRL5 0x35
|
| 92 |
|
| 93 |
|
| 94 | #define ISA1200_HCTRL6 0x36
|
| 95 | #define ISA1200_HCTRL6_PERIOD_SCALE 100
|
| 96 |
|
| 97 |
|
| 98 | #define ISA1200_HCTRL7 0x37
|
| 99 | #define ISA1200_HCTRL8 0x38
|
| 100 | #define ISA1200_HCTRL9 0x39
|
| 101 | #define ISA1200_HCTRLA 0x3a
|
| 102 | #define ISA1200_HCTRLB 0x3b
|
| 103 | #define ISA1200_HCTRLC 0x3c
|
| 104 | #define ISA1200_HCTRLD 0x3d
|
| 105 |
|
| 106 | #define ISA1200_EN_PINS_MAX 2
|
| 107 |
|
| 108 | static const struct regulator_bulk_data isa1200_supplies[] = {
|
| 109 | { .supply = "vdd" }, { .supply = "vddp" },
|
| 110 | };
|
| 111 |
|
| 112 | struct isa1200_config {
|
| 113 | u32 ldo_voltage;
|
| 114 | u32 mode;
|
| 115 | u32 clkdiv;
|
| 116 | u32 plldiv;
|
| 117 | u32 freq;
|
| 118 | u32 period;
|
| 119 | u32 duty;
|
| 120 | };
|
| 121 |
|
| 122 | struct isa1200 {
|
| 123 | struct input_dev *input;
|
| 124 | struct regmap *map;
|
| 125 |
|
| 126 | struct clk *clk;
|
| 127 | struct pwm_device *pwm;
|
| 128 | struct gpio_descs *enable_gpios;
|
| 129 | struct regulator_bulk_data *supplies;
|
| 130 |
|
| 131 | struct work_struct play_work;
|
| 132 | struct isa1200_config config;
|
| 133 |
|
| 134 | int level;
|
| 135 | bool suspended;
|
| 136 | bool active;
|
| 137 | };
|
| 138 |
|
| 139 | static const struct regmap_config isa1200_regmap_config = {
|
| 140 | .reg_bits = 8,
|
| 141 | .val_bits = 8,
|
| 142 | .max_register = ISA1200_HCTRLD,
|
| 143 | };
|
| 144 |
|
| 145 | static void isa1200_start(struct isa1200 *isa)
|
| 146 | {
|
| 147 | struct isa1200_config *config = &isa->config;
|
| 148 | struct device *dev = &isa->input->dev;
|
| 149 | struct pwm_state state;
|
| 150 | u8 hctrl0 = 0, hctrl1 = 0;
|
| 151 | DECLARE_BITMAP(values, ISA1200_EN_PINS_MAX);
|
| 152 | int err;
|
| 153 |
|
| 154 | if (!isa->active) {
|
| 155 | err = regulator_bulk_enable(ARRAY_SIZE(isa1200_supplies),
|
| 156 | isa->supplies);
|
| 157 | if (err) {
|
| 158 | dev_err(dev, "failed to enable supplies (%d)\n", err);
|
| 159 | return;
|
| 160 | }
|
| 161 |
|
| 162 | err = clk_prepare_enable(isa->clk);
|
| 163 | if (err) {
|
| 164 | dev_err(dev, "failed to enable clock (%d)\n", err);
|
| 165 | regulator_bulk_disable(ARRAY_SIZE(isa1200_supplies),
|
| 166 | isa->supplies);
|
| 167 | return;
|
| 168 | }
|
| 169 |
|
| 170 | bitmap_fill(values, ISA1200_EN_PINS_MAX);
|
| 171 | gpiod_multi_set_value_cansleep(isa->enable_gpios, values);
|
| 172 |
|
| 173 | usleep_range(200, 300);
|
| 174 | }
|
| 175 |
|
| 176 | regmap_write(isa->map, ISA1200_SCTRL, config->ldo_voltage);
|
| 177 |
|
| 178 | if (isa->clk) {
|
| 179 | hctrl0 = ISA1200_HCTRL0_PWM_GEN_MODE;
|
| 180 | hctrl1 = ISA1200_HCTRL1_EXT_CLOCK;
|
| 181 | }
|
| 182 |
|
| 183 | if (isa->pwm) {
|
| 184 | hctrl0 = ISA1200_HCTRL0_PWM_INPUT_MODE;
|
| 185 | hctrl1 = 0;
|
| 186 | }
|
| 187 |
|
| 188 | hctrl0 |= __ffs(config->clkdiv / ISA1200_HCTRL0_CLKDIV_128);
|
| 189 | hctrl1 |= ISA1200_HCTRL1_DAC_INVERT;
|
| 190 | hctrl1 |= ISA1200_HCTRL1_MODE(config->mode);
|
| 191 |
|
| 192 | regmap_write(isa->map, ISA1200_HCTRL0, hctrl0);
|
| 193 | regmap_write(isa->map, ISA1200_HCTRL1, hctrl1);
|
| 194 |
|
| 195 |
|
| 196 | regmap_write(isa->map, ISA1200_HCTRL2, 0x00);
|
| 197 |
|
| 198 |
|
| 199 | regmap_write(isa->map, ISA1200_HCTRL3,
|
| 200 | ISA1200_HCTRL3_PLLDIV(config->plldiv) |
|
| 201 | ISA1200_HCTRL3_DEFAULT);
|
| 202 |
|
| 203 |
|
| 204 | regmap_write(isa->map, ISA1200_HCTRL4, config->freq);
|
| 205 |
|
| 206 | regmap_write(isa->map, ISA1200_HCTRL5, config->period >> 1);
|
| 207 |
|
| 208 | regmap_write(isa->map, ISA1200_HCTRL6, config->period);
|
| 209 |
|
| 210 | hctrl0 |= ISA1200_HCTRL0_HAP_ENABLE;
|
| 211 | regmap_write(isa->map, ISA1200_HCTRL0, hctrl0);
|
| 212 |
|
| 213 | if (isa->clk)
|
| 214 | regmap_write(isa->map, ISA1200_HCTRL5, config->duty);
|
| 215 |
|
| 216 | if (isa->pwm) {
|
| 217 | pwm_get_state(isa->pwm, &state);
|
| 218 | state.duty_cycle = config->duty;
|
| 219 | state.enabled = true;
|
| 220 | pwm_apply_might_sleep(isa->pwm, &state);
|
| 221 | }
|
| 222 |
|
| 223 | isa->active = true;
|
| 224 | }
|
| 225 |
|
| 226 | static void isa1200_stop(struct isa1200 *isa)
|
| 227 | {
|
| 228 | struct pwm_state state;
|
| 229 | DECLARE_BITMAP(values, ISA1200_EN_PINS_MAX);
|
| 230 |
|
| 231 | if (!isa->active)
|
| 232 | return;
|
| 233 |
|
| 234 | if (isa->pwm) {
|
| 235 | pwm_get_state(isa->pwm, &state);
|
| 236 | state.duty_cycle = 0;
|
| 237 | state.enabled = false;
|
| 238 | pwm_apply_might_sleep(isa->pwm, &state);
|
| 239 | }
|
| 240 |
|
| 241 | regmap_write(isa->map, ISA1200_HCTRL0, 0x00);
|
| 242 |
|
| 243 | bitmap_zero(values, ISA1200_EN_PINS_MAX);
|
| 244 | gpiod_multi_set_value_cansleep(isa->enable_gpios, values);
|
| 245 |
|
| 246 | clk_disable_unprepare(isa->clk);
|
| 247 | regulator_bulk_disable(ARRAY_SIZE(isa1200_supplies),
|
| 248 | isa->supplies);
|
| 249 |
|
| 250 | isa->active = false;
|
| 251 | }
|
| 252 |
|
| 253 | static void isa1200_play_work(struct work_struct *work)
|
| 254 | {
|
| 255 | struct isa1200 *isa = container_of(work, struct isa1200, play_work);
|
| 256 |
|
| 257 | if (!READ_ONCE(isa->suspended)) {
|
| 258 | if (isa->level)
|
| 259 | isa1200_start(isa);
|
| 260 | else
|
| 261 | isa1200_stop(isa);
|
| 262 | }
|
| 263 | }
|
| 264 |
|
| 265 | static int isa1200_vibrator_play_effect(struct input_dev *input, void *data,
|
| 266 | struct ff_effect *effect)
|
| 267 | {
|
| 268 | struct isa1200 *isa = input_get_drvdata(input);
|
| 269 | int level;
|
| 270 |
|
| 271 | |
| 272 | * TODO: we currently only support rumble.
|
| 273 | * The ISA1200 can control two motors and some devices
|
| 274 | * also have two motors mounted.
|
| 275 |
|
| 276 | level = effect->u.rumble.strong_magnitude;
|
| 277 | if (!level)
|
| 278 | level = effect->u.rumble.weak_magnitude;
|
| 279 |
|
| 280 | dev_dbg(&input->dev, "FF effect type %d level %d\n",
|
| 281 | effect->type, level);
|
| 282 |
|
| 283 | if (isa->level != level) {
|
| 284 | isa->level = level;
|
| 285 | if (!READ_ONCE(isa->suspended))
|
| 286 | schedule_work(&isa->play_work);
|
| 287 | }
|
| 288 |
|
| 289 | return 0;
|
| 290 | }
|
| 291 |
|
| 292 | static void isa1200_vibrator_close(struct input_dev *input)
|
| 293 | {
|
| 294 | struct isa1200 *isa = input_get_drvdata(input);
|
| 295 |
|
| 296 | cancel_work_sync(&isa->play_work);
|
| 297 | isa1200_stop(isa);
|
| 298 | isa->level = 0;
|
| 299 | }
|
| 300 |
|
| 301 | static int isa1200_of_probe(struct i2c_client *client)
|
| 302 | {
|
| 303 | struct isa1200 *isa = i2c_get_clientdata(client);
|
| 304 | struct isa1200_config *config = &isa->config;
|
| 305 | struct device *dev = &client->dev;
|
| 306 | struct fwnode_handle *ldo_node;
|
| 307 | int err;
|
| 308 |
|
| 309 | isa->clk = devm_clk_get_optional(dev, NULL);
|
| 310 | if (IS_ERR(isa->clk))
|
| 311 | return dev_err_probe(dev, PTR_ERR(isa->clk),
|
| 312 | "failed to get clock\n");
|
| 313 |
|
| 314 | isa->pwm = devm_pwm_get(dev, NULL);
|
| 315 | if (IS_ERR(isa->pwm)) {
|
| 316 | err = PTR_ERR(isa->pwm);
|
| 317 | if (err == -ENODEV || err == -EINVAL)
|
| 318 | isa->pwm = NULL;
|
| 319 | else
|
| 320 | return dev_err_probe(dev, err, "getting PWM\n");
|
| 321 | }
|
| 322 |
|
| 323 | if (!isa->clk && !isa->pwm)
|
| 324 | return dev_err_probe(dev, -EINVAL,
|
| 325 | "clock or PWM are required, none were provided\n");
|
| 326 |
|
| 327 | err = devm_regulator_bulk_get_const(dev, ARRAY_SIZE(isa1200_supplies),
|
| 328 | isa1200_supplies, &isa->supplies);
|
| 329 | if (err)
|
| 330 | return dev_err_probe(dev, err, "failed to get supplies\n");
|
| 331 |
|
| 332 | isa->enable_gpios = devm_gpiod_get_array_optional(dev, "control",
|
| 333 | GPIOD_OUT_LOW);
|
| 334 | if (IS_ERR(isa->enable_gpios))
|
| 335 | return dev_err_probe(dev, PTR_ERR(isa->enable_gpios),
|
| 336 | "failed to get enable gpios\n");
|
| 337 |
|
| 338 | if (isa->enable_gpios && isa->enable_gpios->ndescs > ISA1200_EN_PINS_MAX)
|
| 339 | return dev_err_probe(dev, -EINVAL, "too many enable gpios\n");
|
| 340 |
|
| 341 | ldo_node = device_get_named_child_node(dev, "ldo");
|
| 342 | if (!ldo_node)
|
| 343 | return dev_err_probe(dev, -ENODEV,
|
| 344 | "failed to get embedded LDO node\n");
|
| 345 |
|
| 346 | err = fwnode_property_read_u32(ldo_node, "regulator-min-microvolt",
|
| 347 | &config->ldo_voltage);
|
| 348 | fwnode_handle_put(ldo_node);
|
| 349 | if (err)
|
| 350 | return dev_err_probe(dev, err,
|
| 351 | "failed to get ldo voltage\n");
|
| 352 |
|
| 353 | config->ldo_voltage = clamp(config->ldo_voltage,
|
| 354 | ISA1200_LDO_VOLTAGE_MIN,
|
| 355 | ISA1200_LDO_VOLTAGE_MAX);
|
| 356 |
|
| 357 | config->ldo_voltage /= ISA1200_LDO_VOLTAGE_STEP;
|
| 358 | if (config->ldo_voltage < ISA1200_LDO_VOLTAGE_3V1)
|
| 359 | config->ldo_voltage = config->ldo_voltage -
|
| 360 | ISA1200_LDO_VOLTAGE_2V3 +
|
| 361 | ISA1200_LDO_VOLTAGE_BASE;
|
| 362 | else
|
| 363 | config->ldo_voltage -= ISA1200_LDO_VOLTAGE_3V1;
|
| 364 |
|
| 365 | config->mode = 0;
|
| 366 | device_property_read_u32(dev, "imagis,mode", &config->mode);
|
| 367 |
|
| 368 | config->clkdiv = ISA1200_HCTRL0_CLKDIV_128;
|
| 369 | device_property_read_u32(dev, "imagis,clk-div", &config->clkdiv);
|
| 370 | if (!config->clkdiv)
|
| 371 | return dev_err_probe(dev, -EINVAL, "clk-div cannot be zero\n");
|
| 372 |
|
| 373 | config->clkdiv = clamp(config->clkdiv, ISA1200_HCTRL0_CLKDIV_128,
|
| 374 | ISA1200_HCTRL0_CLKDIV_128 << 3);
|
| 375 |
|
| 376 | err = device_property_read_u32(dev, "imagis,pll-div", &config->plldiv);
|
| 377 | if (err || !config->plldiv)
|
| 378 | config->plldiv = 1;
|
| 379 |
|
| 380 | config->period = 0;
|
| 381 | config->freq = 0;
|
| 382 | config->duty = 0;
|
| 383 |
|
| 384 | if (isa->clk) {
|
| 385 | err = device_property_read_u32(dev, "imagis,period-ns",
|
| 386 | &config->period);
|
| 387 | if (err)
|
| 388 | return dev_err_probe(dev, err,
|
| 389 | "failed to get period\n");
|
| 390 |
|
| 391 | |
| 392 | * TODO: The scale value is arbitrary, but it fits observations
|
| 393 | * quite well, and the exact conversion method is unknown.
|
| 394 | * The period property value returned above is the HCTRL6
|
| 395 | * register value set by the vendor code, multiplied by 100.
|
| 396 |
|
| 397 | config->period /= ISA1200_HCTRL6_PERIOD_SCALE;
|
| 398 | config->duty = config->period >> 1;
|
| 399 | }
|
| 400 |
|
| 401 | if (isa->pwm) {
|
| 402 | struct pwm_state state;
|
| 403 |
|
| 404 | pwm_init_state(isa->pwm, &state);
|
| 405 |
|
| 406 | if (!state.period)
|
| 407 | return dev_err_probe(dev, -EINVAL,
|
| 408 | "PWM period cannot be zero\n");
|
| 409 |
|
| 410 | config->freq = div64_u64(NANO, state.period * config->clkdiv);
|
| 411 | config->duty = state.period >> 1;
|
| 412 |
|
| 413 | err = pwm_apply_might_sleep(isa->pwm, &state);
|
| 414 | if (err)
|
| 415 | return dev_err_probe(dev, err,
|
| 416 | "failed to apply initial PWM state\n");
|
| 417 | }
|
| 418 |
|
| 419 | |
| 420 | * TODO: If device is using a clock, this property should return the
|
| 421 | * value written to the HCTRL5 register by downstrem code. It likely
|
| 422 | * needs to be converted into a meaningful duty cycle value, though
|
| 423 | * unfortunately the exact conversion mechanism is unknown. If the
|
| 424 | * device uses PWM, this property will return the correct duty cycle
|
| 425 | * in nanoseconds.
|
| 426 |
|
| 427 | device_property_read_u32(dev, "imagis,duty-cycle-ns", &config->duty);
|
| 428 |
|
| 429 | return 0;
|
| 430 | }
|
| 431 |
|
| 432 | static int isa1200_probe(struct i2c_client *client)
|
| 433 | {
|
| 434 | struct isa1200 *isa;
|
| 435 | struct device *dev = &client->dev;
|
| 436 | int err;
|
| 437 |
|
| 438 | isa = devm_kzalloc(dev, sizeof(*isa), GFP_KERNEL);
|
| 439 | if (!isa)
|
| 440 | return -ENOMEM;
|
| 441 |
|
| 442 | isa->input = devm_input_allocate_device(dev);
|
| 443 | if (!isa->input)
|
| 444 | return -ENOMEM;
|
| 445 |
|
| 446 | i2c_set_clientdata(client, isa);
|
| 447 |
|
| 448 | err = isa1200_of_probe(client);
|
| 449 | if (err)
|
| 450 | return err;
|
| 451 |
|
| 452 | isa->map = devm_regmap_init_i2c(client, &isa1200_regmap_config);
|
| 453 | if (IS_ERR(isa->map))
|
| 454 | return dev_err_probe(dev, PTR_ERR(isa->map),
|
| 455 | "failed to initialize register map\n");
|
| 456 |
|
| 457 | INIT_WORK(&isa->play_work, isa1200_play_work);
|
| 458 |
|
| 459 | isa->input->name = "isa1200-haptic";
|
| 460 | isa->input->id.bustype = BUS_I2C;
|
| 461 | isa->input->close = isa1200_vibrator_close;
|
| 462 |
|
| 463 | isa->active = false;
|
| 464 |
|
| 465 | input_set_drvdata(isa->input, isa);
|
| 466 |
|
| 467 |
|
| 468 | input_set_capability(isa->input, EV_FF, FF_RUMBLE);
|
| 469 |
|
| 470 | err = input_ff_create_memless(isa->input, NULL,
|
| 471 | isa1200_vibrator_play_effect);
|
| 472 | if (err)
|
| 473 | return dev_err_probe(dev, err, "failed to create FF dev\n");
|
| 474 |
|
| 475 | err = input_register_device(isa->input);
|
| 476 | if (err)
|
| 477 | return dev_err_probe(dev, err, "failed to register input dev\n");
|
| 478 |
|
| 479 | return 0;
|
| 480 | }
|
| 481 |
|
| 482 | static int isa1200_suspend(struct device *dev)
|
| 483 | {
|
| 484 | struct isa1200 *isa = dev_get_drvdata(dev);
|
| 485 |
|
| 486 | guard(mutex)(&isa->input->mutex);
|
| 487 |
|
| 488 | if (input_device_enabled(isa->input)) {
|
| 489 | WRITE_ONCE(isa->suspended, true);
|
| 490 | cancel_work_sync(&isa->play_work);
|
| 491 | isa1200_stop(isa);
|
| 492 | }
|
| 493 |
|
| 494 | return 0;
|
| 495 | }
|
| 496 |
|
| 497 | static int isa1200_resume(struct device *dev)
|
| 498 | {
|
| 499 | struct isa1200 *isa = dev_get_drvdata(dev);
|
| 500 |
|
| 501 | guard(mutex)(&isa->input->mutex);
|
| 502 |
|
| 503 | if (input_device_enabled(isa->input)) {
|
| 504 | WRITE_ONCE(isa->suspended, false);
|
| 505 | if (isa->level)
|
| 506 | schedule_work(&isa->play_work);
|
| 507 | }
|
| 508 |
|
| 509 | return 0;
|
| 510 | }
|
| 511 |
|
| 512 | static DEFINE_SIMPLE_DEV_PM_OPS(isa1200_pm_ops, isa1200_suspend, isa1200_resume);
|
| 513 |
|
| 514 | static const struct of_device_id isa1200_of_match[] = {
|
| 515 | { .compatible = "imagis,isa1200" },
|
| 516 | { }
|
| 517 | };
|
| 518 | MODULE_DEVICE_TABLE(of, isa1200_of_match);
|
| 519 |
|
| 520 | static struct i2c_driver isa1200_i2c_driver = {
|
| 521 | .driver = {
|
| 522 | .name = "isa1200",
|
| 523 | .of_match_table = isa1200_of_match,
|
| 524 | .pm = pm_sleep_ptr(&isa1200_pm_ops),
|
| 525 | },
|
| 526 | .probe = isa1200_probe,
|
| 527 | };
|
| 528 | module_i2c_driver(isa1200_i2c_driver);
|
| 529 |
|
| 530 | MODULE_AUTHOR("Linus Walleij <[email protected]>");
|
| 531 | MODULE_AUTHOR("Svyatoslav Ryhel <[email protected]>");
|
| 532 | MODULE_DESCRIPTION("Imagis ISA1200 haptic feedback unit");
|
| 533 | MODULE_LICENSE("GPL");
|