gnss: ubx: use new helper to remove open coded regulator handling
[linux-2.6-microblaze.git] / drivers / gnss / ubx.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * u-blox GNSS receiver driver
4  *
5  * Copyright (C) 2018 Johan Hovold <johan@kernel.org>
6  */
7
8 #include <linux/errno.h>
9 #include <linux/gnss.h>
10 #include <linux/init.h>
11 #include <linux/kernel.h>
12 #include <linux/module.h>
13 #include <linux/of.h>
14 #include <linux/regulator/consumer.h>
15 #include <linux/serdev.h>
16
17 #include "serial.h"
18
19 struct ubx_data {
20         struct regulator *vcc;
21 };
22
23 static int ubx_set_active(struct gnss_serial *gserial)
24 {
25         struct ubx_data *data = gnss_serial_get_drvdata(gserial);
26         int ret;
27
28         ret = regulator_enable(data->vcc);
29         if (ret)
30                 return ret;
31
32         return 0;
33 }
34
35 static int ubx_set_standby(struct gnss_serial *gserial)
36 {
37         struct ubx_data *data = gnss_serial_get_drvdata(gserial);
38         int ret;
39
40         ret = regulator_disable(data->vcc);
41         if (ret)
42                 return ret;
43
44         return 0;
45 }
46
47 static int ubx_set_power(struct gnss_serial *gserial,
48                                 enum gnss_serial_pm_state state)
49 {
50         switch (state) {
51         case GNSS_SERIAL_ACTIVE:
52                 return ubx_set_active(gserial);
53         case GNSS_SERIAL_OFF:
54         case GNSS_SERIAL_STANDBY:
55                 return ubx_set_standby(gserial);
56         }
57
58         return -EINVAL;
59 }
60
61 static const struct gnss_serial_ops ubx_gserial_ops = {
62         .set_power = ubx_set_power,
63 };
64
65 static int ubx_probe(struct serdev_device *serdev)
66 {
67         struct gnss_serial *gserial;
68         struct ubx_data *data;
69         int ret;
70
71         gserial = gnss_serial_allocate(serdev, sizeof(*data));
72         if (IS_ERR(gserial)) {
73                 ret = PTR_ERR(gserial);
74                 return ret;
75         }
76
77         gserial->ops = &ubx_gserial_ops;
78
79         gserial->gdev->type = GNSS_TYPE_UBX;
80
81         data = gnss_serial_get_drvdata(gserial);
82
83         data->vcc = devm_regulator_get(&serdev->dev, "vcc");
84         if (IS_ERR(data->vcc)) {
85                 ret = PTR_ERR(data->vcc);
86                 goto err_free_gserial;
87         }
88
89         ret = devm_regulator_get_enable_optional(&serdev->dev, "v-bckp");
90         if (ret < 0 && ret != -ENODEV)
91                 goto err_free_gserial;
92
93         ret = gnss_serial_register(gserial);
94         if (ret)
95                 goto err_free_gserial;
96
97         return 0;
98
99 err_free_gserial:
100         gnss_serial_free(gserial);
101
102         return ret;
103 }
104
105 static void ubx_remove(struct serdev_device *serdev)
106 {
107         struct gnss_serial *gserial = serdev_device_get_drvdata(serdev);
108
109         gnss_serial_deregister(gserial);
110         gnss_serial_free(gserial);
111 }
112
113 #ifdef CONFIG_OF
114 static const struct of_device_id ubx_of_match[] = {
115         { .compatible = "u-blox,neo-6m" },
116         { .compatible = "u-blox,neo-8" },
117         { .compatible = "u-blox,neo-m8" },
118         {},
119 };
120 MODULE_DEVICE_TABLE(of, ubx_of_match);
121 #endif
122
123 static struct serdev_device_driver ubx_driver = {
124         .driver = {
125                 .name           = "gnss-ubx",
126                 .of_match_table = of_match_ptr(ubx_of_match),
127                 .pm             = &gnss_serial_pm_ops,
128         },
129         .probe  = ubx_probe,
130         .remove = ubx_remove,
131 };
132 module_serdev_device_driver(ubx_driver);
133
134 MODULE_AUTHOR("Johan Hovold <johan@kernel.org>");
135 MODULE_DESCRIPTION("u-blox GNSS receiver driver");
136 MODULE_LICENSE("GPL v2");