diff options
author | Johan Hovold <johan@kernel.org> | 2018-06-01 04:22:59 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2018-06-28 07:32:51 -0400 |
commit | 10f146639fee5ffaf7cf0081c1af518f7d0c533c (patch) | |
tree | 1fdc31ab3bf22339c89db3b7ba134c6aad9579cf | |
parent | d2efbbd18b1e26ac79401841089e4a4b97d745c3 (diff) |
gnss: add receiver type support
Add a "type" device attribute and a "GNSS_TYPE" uevent variable which
can be used to determine the type of a GNSS receiver. The currently
identified types reflect the protocol(s) supported by a receiver:
"NMEA" NMEA 0183
"SiRF" SiRF Binary
"UBX" UBX
Note that both SiRF and UBX type receivers typically support a subset of
NMEA 0183 with vendor extensions (e.g. to allow switching to the vendor
protocol).
Signed-off-by: Johan Hovold <johan@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | Documentation/ABI/testing/sysfs-class-gnss | 15 | ||||
-rw-r--r-- | MAINTAINERS | 1 | ||||
-rw-r--r-- | drivers/gnss/core.c | 49 | ||||
-rw-r--r-- | drivers/gnss/sirf.c | 1 | ||||
-rw-r--r-- | drivers/gnss/ubx.c | 2 | ||||
-rw-r--r-- | include/linux/gnss.h | 9 |
6 files changed, 77 insertions, 0 deletions
diff --git a/Documentation/ABI/testing/sysfs-class-gnss b/Documentation/ABI/testing/sysfs-class-gnss new file mode 100644 index 000000000000..2467b6900eae --- /dev/null +++ b/Documentation/ABI/testing/sysfs-class-gnss | |||
@@ -0,0 +1,15 @@ | |||
1 | What: /sys/class/gnss/gnssN/type | ||
2 | Date: May 2018 | ||
3 | KernelVersion: 4.18 | ||
4 | Contact: Johan Hovold <johan@kernel.org> | ||
5 | Description: | ||
6 | The GNSS receiver type. The currently identified types reflect | ||
7 | the protocol(s) supported by the receiver: | ||
8 | |||
9 | "NMEA" NMEA 0183 | ||
10 | "SiRF" SiRF Binary | ||
11 | "UBX" UBX | ||
12 | |||
13 | Note that also non-"NMEA" type receivers typically support a | ||
14 | subset of NMEA 0183 with vendor extensions (e.g. to allow | ||
15 | switching to a vendor protocol). | ||
diff --git a/MAINTAINERS b/MAINTAINERS index f980c6186094..e01d220a6f05 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -6041,6 +6041,7 @@ F: include/uapi/linux/gigaset_dev.h | |||
6041 | GNSS SUBSYSTEM | 6041 | GNSS SUBSYSTEM |
6042 | M: Johan Hovold <johan@kernel.org> | 6042 | M: Johan Hovold <johan@kernel.org> |
6043 | S: Maintained | 6043 | S: Maintained |
6044 | F: Documentation/ABI/testing/sysfs-class-gnss | ||
6044 | F: Documentation/devicetree/bindings/gnss/ | 6045 | F: Documentation/devicetree/bindings/gnss/ |
6045 | F: drivers/gnss/ | 6046 | F: drivers/gnss/ |
6046 | F: include/linux/gnss.h | 6047 | F: include/linux/gnss.h |
diff --git a/drivers/gnss/core.c b/drivers/gnss/core.c index 307894ca2725..f30ef8338b3a 100644 --- a/drivers/gnss/core.c +++ b/drivers/gnss/core.c | |||
@@ -330,6 +330,52 @@ int gnss_insert_raw(struct gnss_device *gdev, const unsigned char *buf, | |||
330 | } | 330 | } |
331 | EXPORT_SYMBOL_GPL(gnss_insert_raw); | 331 | EXPORT_SYMBOL_GPL(gnss_insert_raw); |
332 | 332 | ||
333 | static const char * const gnss_type_names[GNSS_TYPE_COUNT] = { | ||
334 | [GNSS_TYPE_NMEA] = "NMEA", | ||
335 | [GNSS_TYPE_SIRF] = "SiRF", | ||
336 | [GNSS_TYPE_UBX] = "UBX", | ||
337 | }; | ||
338 | |||
339 | static const char *gnss_type_name(struct gnss_device *gdev) | ||
340 | { | ||
341 | const char *name = NULL; | ||
342 | |||
343 | if (gdev->type < GNSS_TYPE_COUNT) | ||
344 | name = gnss_type_names[gdev->type]; | ||
345 | |||
346 | if (!name) | ||
347 | dev_WARN(&gdev->dev, "type name not defined\n"); | ||
348 | |||
349 | return name; | ||
350 | } | ||
351 | |||
352 | static ssize_t type_show(struct device *dev, struct device_attribute *attr, | ||
353 | char *buf) | ||
354 | { | ||
355 | struct gnss_device *gdev = to_gnss_device(dev); | ||
356 | |||
357 | return sprintf(buf, "%s\n", gnss_type_name(gdev)); | ||
358 | } | ||
359 | static DEVICE_ATTR_RO(type); | ||
360 | |||
361 | static struct attribute *gnss_attrs[] = { | ||
362 | &dev_attr_type.attr, | ||
363 | NULL, | ||
364 | }; | ||
365 | ATTRIBUTE_GROUPS(gnss); | ||
366 | |||
367 | static int gnss_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
368 | { | ||
369 | struct gnss_device *gdev = to_gnss_device(dev); | ||
370 | int ret; | ||
371 | |||
372 | ret = add_uevent_var(env, "GNSS_TYPE=%s", gnss_type_name(gdev)); | ||
373 | if (ret) | ||
374 | return ret; | ||
375 | |||
376 | return 0; | ||
377 | } | ||
378 | |||
333 | static int __init gnss_module_init(void) | 379 | static int __init gnss_module_init(void) |
334 | { | 380 | { |
335 | int ret; | 381 | int ret; |
@@ -347,6 +393,9 @@ static int __init gnss_module_init(void) | |||
347 | goto err_unregister_chrdev; | 393 | goto err_unregister_chrdev; |
348 | } | 394 | } |
349 | 395 | ||
396 | gnss_class->dev_groups = gnss_groups; | ||
397 | gnss_class->dev_uevent = gnss_uevent; | ||
398 | |||
350 | pr_info("GNSS driver registered with major %d\n", MAJOR(gnss_first)); | 399 | pr_info("GNSS driver registered with major %d\n", MAJOR(gnss_first)); |
351 | 400 | ||
352 | return 0; | 401 | return 0; |
diff --git a/drivers/gnss/sirf.c b/drivers/gnss/sirf.c index 5fb0f730db48..79cb98950013 100644 --- a/drivers/gnss/sirf.c +++ b/drivers/gnss/sirf.c | |||
@@ -267,6 +267,7 @@ static int sirf_probe(struct serdev_device *serdev) | |||
267 | if (!gdev) | 267 | if (!gdev) |
268 | return -ENOMEM; | 268 | return -ENOMEM; |
269 | 269 | ||
270 | gdev->type = GNSS_TYPE_SIRF; | ||
270 | gdev->ops = &sirf_gnss_ops; | 271 | gdev->ops = &sirf_gnss_ops; |
271 | gnss_set_drvdata(gdev, data); | 272 | gnss_set_drvdata(gdev, data); |
272 | 273 | ||
diff --git a/drivers/gnss/ubx.c b/drivers/gnss/ubx.c index ecddfb362a6f..902b6854b7db 100644 --- a/drivers/gnss/ubx.c +++ b/drivers/gnss/ubx.c | |||
@@ -77,6 +77,8 @@ static int ubx_probe(struct serdev_device *serdev) | |||
77 | 77 | ||
78 | gserial->ops = &ubx_gserial_ops; | 78 | gserial->ops = &ubx_gserial_ops; |
79 | 79 | ||
80 | gserial->gdev->type = GNSS_TYPE_UBX; | ||
81 | |||
80 | data = gnss_serial_get_drvdata(gserial); | 82 | data = gnss_serial_get_drvdata(gserial); |
81 | 83 | ||
82 | data->vcc = devm_regulator_get(&serdev->dev, "vcc"); | 84 | data->vcc = devm_regulator_get(&serdev->dev, "vcc"); |
diff --git a/include/linux/gnss.h b/include/linux/gnss.h index e26aeac1e0e2..43546977098c 100644 --- a/include/linux/gnss.h +++ b/include/linux/gnss.h | |||
@@ -18,6 +18,14 @@ | |||
18 | 18 | ||
19 | struct gnss_device; | 19 | struct gnss_device; |
20 | 20 | ||
21 | enum gnss_type { | ||
22 | GNSS_TYPE_NMEA = 0, | ||
23 | GNSS_TYPE_SIRF, | ||
24 | GNSS_TYPE_UBX, | ||
25 | |||
26 | GNSS_TYPE_COUNT | ||
27 | }; | ||
28 | |||
21 | struct gnss_operations { | 29 | struct gnss_operations { |
22 | int (*open)(struct gnss_device *gdev); | 30 | int (*open)(struct gnss_device *gdev); |
23 | void (*close)(struct gnss_device *gdev); | 31 | void (*close)(struct gnss_device *gdev); |
@@ -30,6 +38,7 @@ struct gnss_device { | |||
30 | struct cdev cdev; | 38 | struct cdev cdev; |
31 | int id; | 39 | int id; |
32 | 40 | ||
41 | enum gnss_type type; | ||
33 | unsigned long flags; | 42 | unsigned long flags; |
34 | 43 | ||
35 | struct rw_semaphore rwsem; | 44 | struct rw_semaphore rwsem; |