.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * mag3110.c - Support for Freescale MAG3110 magnetometer sensor |
---|
3 | 4 | * |
---|
4 | 5 | * Copyright (c) 2013 Peter Meerwald <pmeerw@pmeerw.net> |
---|
5 | | - * |
---|
6 | | - * This file is subject to the terms and conditions of version 2 of |
---|
7 | | - * the GNU General Public License. See the file COPYING in the main |
---|
8 | | - * directory of this archive for more details. |
---|
9 | 6 | * |
---|
10 | 7 | * (7-bit I2C slave address 0x0e) |
---|
11 | 8 | * |
---|
.. | .. |
---|
20 | 17 | #include <linux/iio/buffer.h> |
---|
21 | 18 | #include <linux/iio/triggered_buffer.h> |
---|
22 | 19 | #include <linux/delay.h> |
---|
| 20 | +#include <linux/regulator/consumer.h> |
---|
23 | 21 | |
---|
24 | 22 | #define MAG3110_STATUS 0x00 |
---|
25 | 23 | #define MAG3110_OUT_X 0x01 /* MSB first */ |
---|
.. | .. |
---|
56 | 54 | struct mutex lock; |
---|
57 | 55 | u8 ctrl_reg1; |
---|
58 | 56 | int sleep_val; |
---|
| 57 | + struct regulator *vdd_reg; |
---|
| 58 | + struct regulator *vddio_reg; |
---|
59 | 59 | /* Ensure natural alignment of timestamp */ |
---|
60 | 60 | struct { |
---|
61 | 61 | __be16 channels[3]; |
---|
.. | .. |
---|
474 | 474 | struct iio_dev *indio_dev; |
---|
475 | 475 | int ret; |
---|
476 | 476 | |
---|
477 | | - ret = i2c_smbus_read_byte_data(client, MAG3110_WHO_AM_I); |
---|
478 | | - if (ret < 0) |
---|
479 | | - return ret; |
---|
480 | | - if (ret != MAG3110_DEVICE_ID) |
---|
481 | | - return -ENODEV; |
---|
482 | | - |
---|
483 | 477 | indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data)); |
---|
484 | 478 | if (!indio_dev) |
---|
485 | 479 | return -ENOMEM; |
---|
486 | 480 | |
---|
487 | 481 | data = iio_priv(indio_dev); |
---|
| 482 | + |
---|
| 483 | + data->vdd_reg = devm_regulator_get(&client->dev, "vdd"); |
---|
| 484 | + if (IS_ERR(data->vdd_reg)) |
---|
| 485 | + return dev_err_probe(&client->dev, PTR_ERR(data->vdd_reg), |
---|
| 486 | + "failed to get VDD regulator!\n"); |
---|
| 487 | + |
---|
| 488 | + data->vddio_reg = devm_regulator_get(&client->dev, "vddio"); |
---|
| 489 | + if (IS_ERR(data->vddio_reg)) |
---|
| 490 | + return dev_err_probe(&client->dev, PTR_ERR(data->vddio_reg), |
---|
| 491 | + "failed to get VDDIO regulator!\n"); |
---|
| 492 | + |
---|
| 493 | + ret = regulator_enable(data->vdd_reg); |
---|
| 494 | + if (ret) { |
---|
| 495 | + dev_err(&client->dev, "failed to enable VDD regulator!\n"); |
---|
| 496 | + return ret; |
---|
| 497 | + } |
---|
| 498 | + |
---|
| 499 | + ret = regulator_enable(data->vddio_reg); |
---|
| 500 | + if (ret) { |
---|
| 501 | + dev_err(&client->dev, "failed to enable VDDIO regulator!\n"); |
---|
| 502 | + goto disable_regulator_vdd; |
---|
| 503 | + } |
---|
| 504 | + |
---|
| 505 | + ret = i2c_smbus_read_byte_data(client, MAG3110_WHO_AM_I); |
---|
| 506 | + if (ret < 0) |
---|
| 507 | + goto disable_regulators; |
---|
| 508 | + if (ret != MAG3110_DEVICE_ID) { |
---|
| 509 | + ret = -ENODEV; |
---|
| 510 | + goto disable_regulators; |
---|
| 511 | + } |
---|
| 512 | + |
---|
488 | 513 | data->client = client; |
---|
489 | 514 | mutex_init(&data->lock); |
---|
490 | 515 | |
---|
491 | 516 | i2c_set_clientdata(client, indio_dev); |
---|
492 | 517 | indio_dev->info = &mag3110_info; |
---|
493 | 518 | indio_dev->name = id->name; |
---|
494 | | - indio_dev->dev.parent = &client->dev; |
---|
495 | 519 | indio_dev->modes = INDIO_DIRECT_MODE; |
---|
496 | 520 | indio_dev->channels = mag3110_channels; |
---|
497 | 521 | indio_dev->num_channels = ARRAY_SIZE(mag3110_channels); |
---|
.. | .. |
---|
504 | 528 | |
---|
505 | 529 | ret = mag3110_change_config(data, MAG3110_CTRL_REG1, data->ctrl_reg1); |
---|
506 | 530 | if (ret < 0) |
---|
507 | | - return ret; |
---|
| 531 | + goto disable_regulators; |
---|
508 | 532 | |
---|
509 | 533 | ret = i2c_smbus_write_byte_data(client, MAG3110_CTRL_REG2, |
---|
510 | 534 | MAG3110_CTRL_AUTO_MRST_EN); |
---|
.. | .. |
---|
525 | 549 | iio_triggered_buffer_cleanup(indio_dev); |
---|
526 | 550 | standby_on_error: |
---|
527 | 551 | mag3110_standby(iio_priv(indio_dev)); |
---|
| 552 | +disable_regulators: |
---|
| 553 | + regulator_disable(data->vddio_reg); |
---|
| 554 | +disable_regulator_vdd: |
---|
| 555 | + regulator_disable(data->vdd_reg); |
---|
| 556 | + |
---|
528 | 557 | return ret; |
---|
529 | 558 | } |
---|
530 | 559 | |
---|
531 | 560 | static int mag3110_remove(struct i2c_client *client) |
---|
532 | 561 | { |
---|
533 | 562 | struct iio_dev *indio_dev = i2c_get_clientdata(client); |
---|
| 563 | + struct mag3110_data *data = iio_priv(indio_dev); |
---|
534 | 564 | |
---|
535 | 565 | iio_device_unregister(indio_dev); |
---|
536 | 566 | iio_triggered_buffer_cleanup(indio_dev); |
---|
537 | 567 | mag3110_standby(iio_priv(indio_dev)); |
---|
| 568 | + regulator_disable(data->vddio_reg); |
---|
| 569 | + regulator_disable(data->vdd_reg); |
---|
538 | 570 | |
---|
539 | 571 | return 0; |
---|
540 | 572 | } |
---|
.. | .. |
---|
542 | 574 | #ifdef CONFIG_PM_SLEEP |
---|
543 | 575 | static int mag3110_suspend(struct device *dev) |
---|
544 | 576 | { |
---|
545 | | - return mag3110_standby(iio_priv(i2c_get_clientdata( |
---|
| 577 | + struct mag3110_data *data = iio_priv(i2c_get_clientdata( |
---|
| 578 | + to_i2c_client(dev))); |
---|
| 579 | + int ret; |
---|
| 580 | + |
---|
| 581 | + ret = mag3110_standby(iio_priv(i2c_get_clientdata( |
---|
546 | 582 | to_i2c_client(dev)))); |
---|
| 583 | + if (ret) |
---|
| 584 | + return ret; |
---|
| 585 | + |
---|
| 586 | + ret = regulator_disable(data->vddio_reg); |
---|
| 587 | + if (ret) { |
---|
| 588 | + dev_err(dev, "failed to disable VDDIO regulator\n"); |
---|
| 589 | + return ret; |
---|
| 590 | + } |
---|
| 591 | + |
---|
| 592 | + ret = regulator_disable(data->vdd_reg); |
---|
| 593 | + if (ret) { |
---|
| 594 | + dev_err(dev, "failed to disable VDD regulator\n"); |
---|
| 595 | + return ret; |
---|
| 596 | + } |
---|
| 597 | + |
---|
| 598 | + return 0; |
---|
547 | 599 | } |
---|
548 | 600 | |
---|
549 | 601 | static int mag3110_resume(struct device *dev) |
---|
550 | 602 | { |
---|
551 | 603 | struct mag3110_data *data = iio_priv(i2c_get_clientdata( |
---|
552 | 604 | to_i2c_client(dev))); |
---|
| 605 | + int ret; |
---|
| 606 | + |
---|
| 607 | + ret = regulator_enable(data->vdd_reg); |
---|
| 608 | + if (ret) { |
---|
| 609 | + dev_err(dev, "failed to enable VDD regulator\n"); |
---|
| 610 | + return ret; |
---|
| 611 | + } |
---|
| 612 | + |
---|
| 613 | + ret = regulator_enable(data->vddio_reg); |
---|
| 614 | + if (ret) { |
---|
| 615 | + dev_err(dev, "failed to enable VDDIO regulator\n"); |
---|
| 616 | + regulator_disable(data->vdd_reg); |
---|
| 617 | + return ret; |
---|
| 618 | + } |
---|
553 | 619 | |
---|
554 | 620 | return i2c_smbus_write_byte_data(data->client, MAG3110_CTRL_REG1, |
---|
555 | 621 | data->ctrl_reg1); |
---|