* [PATCH 0/2] support config of U-Blox Zed-F9P GNSS @ 2023-04-29 22:43 alison 2023-04-29 22:43 ` [PATCH 1/2] gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud alison 2023-04-29 22:43 ` [PATCH 2/2] dt-bindings: gnss: Add U-Blox Zed-F9 alison 0 siblings, 2 replies; 8+ messages in thread From: alison @ 2023-04-29 22:43 UTC (permalink / raw) To: johan; +Cc: linux-kernel, alison, achaiken From: Alison Chaiken <achaiken@aurora.tech> Add generalized support for setting arbitrary configuration of the U-Blox Zed-F9P GNSS. Employ the new functionality to set the baud rate of the Zed-F9P if the devicetree specifies a non-default value. Tested with 6.1.22, only on a U-Blox Zed-F9P GNSS. Alison Chaiken (2): gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud dt-bindings: gnss: Add U-Blox Zed-F9 .../bindings/gnss/u-blox,neo-6m.yaml | 1 + drivers/gnss/ubx.c | 198 +++++++++++++++++- 2 files changed, 197 insertions(+), 2 deletions(-) -- 2.39.2 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/2] gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud 2023-04-29 22:43 [PATCH 0/2] support config of U-Blox Zed-F9P GNSS alison @ 2023-04-29 22:43 ` alison 2023-04-30 0:20 ` kernel test robot 2023-05-09 3:09 ` kernel test robot 2023-04-29 22:43 ` [PATCH 2/2] dt-bindings: gnss: Add U-Blox Zed-F9 alison 1 sibling, 2 replies; 8+ messages in thread From: alison @ 2023-04-29 22:43 UTC (permalink / raw) To: johan; +Cc: linux-kernel, alison, achaiken From: Alison Chaiken <achaiken@aurora.tech> Add support for setting the baud rate of U-Blox Zed-F9P GNSS devices. Provide functions that support writing of arbitrary configuration messages to the device plus one that specifically configures the baud rate. Override the default gnss_serial_open() with a new method that writes the configuration message to the GNSS if the devicetree declares it to be a Zed F9P and requests a non-default baud. Add a boolean flag to the ubx_data private data of the GNSS driver in order to track whether the configuration message has already been written. Set the Zed F9P to its default port speed if the devicetree does not specify a value. Signed-off-by: Alison Chaiken <achaiken@aurora.tech> --- drivers/gnss/ubx.c | 198 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 196 insertions(+), 2 deletions(-) diff --git a/drivers/gnss/ubx.c b/drivers/gnss/ubx.c index c951be202ca2..cdaf910c52a7 100644 --- a/drivers/gnss/ubx.c +++ b/drivers/gnss/ubx.c @@ -9,18 +9,202 @@ #include <linux/gnss.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/kstrtox.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/pm.h> +#include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> #include <linux/serdev.h> #include "serial.h" +/* Total configuration message length = PREAMBLE_LEN + MESSAGE_CLASS_LEN + + * MESSAGE_LENGTH_LEN + payload length + CHECKSUM_LEN + */ +const int32_t PREAMBLE_LEN = 2; +const int32_t MESSAGE_CLASS_LEN = 2; +const int32_t MESSAGE_LENGTH_LEN = 2; +const int32_t CHECKSUM_LEN = 2; +const size_t FIRST_CONFIG_REGISTER_BYTE = 10U; +const size_t FIRST_VALUE_BYTE = 14U; +const size_t FIRST_CHECKSUM_BYTE = 18U; +const size_t CFG_MSG_TOTAL_LEN = 20U; + +uint8_t ZED_F9P_CFG_VALSET_MSG[] = { + 0xB5, 0x62, /* 0-1 preamble */ + 0x06, 0x8A, /* 2-3 CFG_VALSET command */ + 0x0C, 0x00, /* 4-5 payload length = 12 for one key-value pair */ + 0x00, /* 6 U-Blox API version */ + 0x01, /* 7 Write to RAM */ + 0x00, 0x00, /* 8-9 Reserved */ + 0x00, 0x00, 0x00, 0x00, /* 10-13 Placeholder for configuration register */ + 0x00, 0x00, 0x00, 0x00, /* 14-17 Placeholder for baud value */ + 0x00, 0x00 /* 18-19 Placeholder for checksum */ +}; + +const speed_t ZED_F9P_MIN_BAUD = 9600; +const speed_t ZED_F9P_DEFAULT_BAUD = 38400; +const speed_t ZED_F9P_MAX_BAUD = 921600; +const uint32_t ZED_F9P_BAUD_CONFIG_REGISTER = 0x40520001; + struct ubx_data { struct regulator *v_bckp; struct regulator *vcc; + unsigned long is_configured; +}; + +union message_length { + uint16_t ml; + uint8_t bytes[2]; +}; + +union int_to_bytes { + uint32_t int_val; + uint8_t bytes[4]; }; +/* Payload length is contained in bytes 0-2 after message class and ID. + * While the checksum includes the Message class and ID plus message length, the + * payload does not. + */ +static uint16_t get_payload_length(const uint8_t msg[]) +{ + union message_length hs_msg_len; + + hs_msg_len.bytes[0] = msg[PREAMBLE_LEN + MESSAGE_CLASS_LEN]; + hs_msg_len.bytes[1] = msg[PREAMBLE_LEN + MESSAGE_CLASS_LEN + 1U]; + return hs_msg_len.ml; +} + +static int32_t get_msg_total_len(const uint8_t msg[]) +{ + const size_t payload_len = get_payload_length(msg); + + return PREAMBLE_LEN + MESSAGE_CLASS_LEN + MESSAGE_LENGTH_LEN + payload_len + + CHECKSUM_LEN; +} + +/* The checksum is calculated on message class, message ID, message length and + * payload. + */ +static void calc_ubx_checksum(const uint8_t msg[], uint8_t checksum[], + const uint16_t total_len) +{ + uint8_t CK_A = 0; + uint8_t CK_B = 0; + int i; + + for (i = PREAMBLE_LEN; i < (total_len - CHECKSUM_LEN); i++) { + CK_A += msg[i]; + CK_B += CK_A; + } + checksum[0] = CK_A; + checksum[1] = CK_B; +} + +static uint32_t check_baud(speed_t speed, const struct device *dev) +{ + if ((speed < ZED_F9P_MIN_BAUD) || (speed > ZED_F9P_MAX_BAUD)) { + dev_warn(dev, "Baud rate specification %d out of range\n", speed); + speed = ZED_F9P_DEFAULT_BAUD; + } + return speed; +} + +static int prepare_zedf9p_config_msg(const speed_t speed, + const struct device *dev, const size_t msg_register) +{ + union int_to_bytes cfg_val, cfg_register; + int i = 0; + uint8_t checksum[2]; + const size_t total_len = get_msg_total_len(ZED_F9P_CFG_VALSET_MSG); + + if (total_len != CFG_MSG_TOTAL_LEN) + goto bad_msg; + + cfg_val.int_val = check_baud(speed, dev); + cfg_register.int_val = msg_register; + for (i = 0; i < 4; i++) { + ZED_F9P_CFG_VALSET_MSG[FIRST_VALUE_BYTE + i] = cfg_val.bytes[i]; + ZED_F9P_CFG_VALSET_MSG[FIRST_CONFIG_REGISTER_BYTE + i] = cfg_register.bytes[i]; + } + calc_ubx_checksum(ZED_F9P_CFG_VALSET_MSG, checksum, total_len); + ZED_F9P_CFG_VALSET_MSG[FIRST_CHECKSUM_BYTE] = checksum[0]; + ZED_F9P_CFG_VALSET_MSG[FIRST_CHECKSUM_BYTE + 1U] = checksum[1]; + return 0; + + bad_msg: + dev_err(dev, "Malformed UBX-CFG-VALSET message\n"); + return -EINVAL; +} + +/* Configure the Zed F9P baud rate via the UBX-CFG-VALSET message. */ +static int set_zedf9p_baud(struct gnss_device *gdev, + struct serdev_device *serdev, const speed_t speed) +{ + size_t count = 0U; + int ret; + + if (speed == ZED_F9P_DEFAULT_BAUD) + return 0; + + ret = prepare_zedf9p_config_msg(speed, &gdev->dev, ZED_F9P_BAUD_CONFIG_REGISTER); + if (ret) + return ret; + /* Initially set the UART to the default speed to match the GNSS' power-on value. */ + serdev_device_set_baudrate(serdev, ZED_F9P_DEFAULT_BAUD); + /* Now set the new baud rate. */ + count = gdev->ops->write_raw(gdev, ZED_F9P_CFG_VALSET_MSG, CFG_MSG_TOTAL_LEN); + if (count != CFG_MSG_TOTAL_LEN) + return count; + + pr_info("Setting Zed F9P GNSS speed to %u\n", speed); + return 0; +} + +static int ubx_serial_open(struct gnss_device *gdev) +{ + struct gnss_serial *gserial = gnss_get_drvdata(gdev); + struct serdev_device *serdev = gserial->serdev; + struct ubx_data *data = gnss_serial_get_drvdata(gserial); + struct device_node *np; + int ret; + + ret = serdev_device_open(serdev); + if (ret) + return ret; + + serdev_device_set_flow_control(serdev, false); + + np = serdev->dev.of_node; + if ((of_device_is_compatible(np, "u-blox,zed-f9p")) && (!data->is_configured)) { + /* 4800 is the default value set by gnss_serial_parse_dt() */ + if (gserial->speed == 4800) { + /* Fall back instead to Zed F9P default */ + gserial->speed = ZED_F9P_DEFAULT_BAUD; + } else { + ret = set_zedf9p_baud(gdev, serdev, gserial->speed); + if (ret) + return ret; + } + data->is_configured = 1; + } + serdev_device_set_baudrate(serdev, gserial->speed); + + ret = pm_runtime_get_sync(&serdev->dev); + if (ret < 0) { + pm_runtime_put_noidle(&serdev->dev); + goto err_close; + } + return 0; + +err_close: + serdev_device_close(serdev); + + return ret; +} + static int ubx_set_active(struct gnss_serial *gserial) { struct ubx_data *data = gnss_serial_get_drvdata(gserial); @@ -67,6 +251,7 @@ static int ubx_probe(struct serdev_device *serdev) { struct gnss_serial *gserial; struct ubx_data *data; + struct gnss_operations *ubx_gnss_ops; int ret; gserial = gnss_serial_allocate(serdev, sizeof(*data)); @@ -74,12 +259,20 @@ static int ubx_probe(struct serdev_device *serdev) ret = PTR_ERR(gserial); return ret; } - - gserial->ops = &ubx_gserial_ops; + ubx_gnss_ops = kzalloc(sizeof(struct gnss_operations), GFP_KERNEL); + if (IS_ERR(ubx_gnss_ops)) { + ret = PTR_ERR(ubx_gnss_ops); + return ret; + } gserial->gdev->type = GNSS_TYPE_UBX; + ubx_gnss_ops->open = &ubx_serial_open; + ubx_gnss_ops->close = gserial->gdev->ops->close; + ubx_gnss_ops->write_raw = gserial->gdev->ops->write_raw; + gserial->gdev->ops = ubx_gnss_ops; data = gnss_serial_get_drvdata(gserial); + data->is_configured = 0; data->vcc = devm_regulator_get(&serdev->dev, "vcc"); if (IS_ERR(data->vcc)) { @@ -133,6 +326,7 @@ static const struct of_device_id ubx_of_match[] = { { .compatible = "u-blox,neo-6m" }, { .compatible = "u-blox,neo-8" }, { .compatible = "u-blox,neo-m8" }, + { .compatible = "u-blox,zed-f9p" }, {}, }; MODULE_DEVICE_TABLE(of, ubx_of_match); -- 2.39.2 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud 2023-04-29 22:43 ` [PATCH 1/2] gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud alison @ 2023-04-30 0:20 ` kernel test robot 2023-05-09 3:09 ` kernel test robot 1 sibling, 0 replies; 8+ messages in thread From: kernel test robot @ 2023-04-30 0:20 UTC (permalink / raw) To: alison, johan; +Cc: oe-kbuild-all, linux-kernel, alison, achaiken Hi, kernel test robot noticed the following build warnings: [auto build test WARNING on robh/for-next] [also build test WARNING on linus/master v6.3 next-20230428] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/alison-she-devel-com/gnss-ubx-customize-serial-device-open-to-set-U-Blox-Zed-F9P-baud/20230430-065242 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next patch link: https://lore.kernel.org/r/20230429224349.1935029-2-alison%40she-devel.com patch subject: [PATCH 1/2] gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud config: i386-randconfig-a001 (https://download.01.org/0day-ci/archive/20230430/202304300819.u0hfUj33-lkp@intel.com/config) compiler: gcc-11 (Debian 11.3.0-12) 11.3.0 reproduce (this is a W=1 build): # https://github.com/intel-lab-lkp/linux/commit/743f5061f999abbdc0b6f366cf4b85a5a8685014 git remote add linux-review https://github.com/intel-lab-lkp/linux git fetch --no-tags linux-review alison-she-devel-com/gnss-ubx-customize-serial-device-open-to-set-U-Blox-Zed-F9P-baud/20230430-065242 git checkout 743f5061f999abbdc0b6f366cf4b85a5a8685014 # save the config file mkdir build_dir && cp config build_dir/.config make W=1 O=build_dir ARCH=i386 olddefconfig make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash drivers/gnss/ If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> | Link: https://lore.kernel.org/oe-kbuild-all/202304300819.u0hfUj33-lkp@intel.com/ All warnings (new ones prefixed by >>): >> drivers/gnss/ubx.c:246:37: warning: 'ubx_gserial_ops' defined but not used [-Wunused-const-variable=] 246 | static const struct gnss_serial_ops ubx_gserial_ops = { | ^~~~~~~~~~~~~~~ vim +/ubx_gserial_ops +246 drivers/gnss/ubx.c 1ad69f10e3a58d Johan Hovold 2018-06-01 245 55570f1a441787 Colin Ian King 2018-07-16 @246 static const struct gnss_serial_ops ubx_gserial_ops = { 1ad69f10e3a58d Johan Hovold 2018-06-01 247 .set_power = ubx_set_power, 1ad69f10e3a58d Johan Hovold 2018-06-01 248 }; 1ad69f10e3a58d Johan Hovold 2018-06-01 249 -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests ^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud 2023-04-29 22:43 ` [PATCH 1/2] gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud alison 2023-04-30 0:20 ` kernel test robot @ 2023-05-09 3:09 ` kernel test robot 1 sibling, 0 replies; 8+ messages in thread From: kernel test robot @ 2023-05-09 3:09 UTC (permalink / raw) To: alison, johan; +Cc: oe-kbuild-all, linux-kernel, alison, achaiken Hi, kernel test robot noticed the following build warnings: [auto build test WARNING on robh/for-next] [also build test WARNING on linus/master v6.4-rc1 next-20230508] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch#_base_tree_information] url: https://github.com/intel-lab-lkp/linux/commits/alison-she-devel-com/gnss-ubx-customize-serial-device-open-to-set-U-Blox-Zed-F9P-baud/20230430-065242 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next patch link: https://lore.kernel.org/r/20230429224349.1935029-2-alison%40she-devel.com patch subject: [PATCH 1/2] gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud config: mips-randconfig-c004-20230507 (https://download.01.org/0day-ci/archive/20230509/202305091016.ekHtVcRp-lkp@intel.com/config) compiler: mipsel-linux-gcc (GCC) 12.1.0 If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <lkp@intel.com> | Link: https://lore.kernel.org/oe-kbuild-all/202305091016.ekHtVcRp-lkp@intel.com/ cocci warnings: (new ones prefixed by >>) >> drivers/gnss/ubx.c:263:5-11: ERROR: allocation function on line 262 returns NULL not ERR_PTR on failure -- 0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 2/2] dt-bindings: gnss: Add U-Blox Zed-F9 2023-04-29 22:43 [PATCH 0/2] support config of U-Blox Zed-F9P GNSS alison 2023-04-29 22:43 ` [PATCH 1/2] gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud alison @ 2023-04-29 22:43 ` alison 2023-04-30 12:17 ` Krzysztof Kozlowski 1 sibling, 1 reply; 8+ messages in thread From: alison @ 2023-04-29 22:43 UTC (permalink / raw) To: johan; +Cc: linux-kernel, alison, achaiken From: Alison Chaiken <achaiken@aurora.tech> Add support for the U-Blox Zed-F9P GNSS device. Signed-off-by: Alison Chaiken <achaiken@aurora.tech> --- Documentation/devicetree/bindings/gnss/u-blox,neo-6m.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/gnss/u-blox,neo-6m.yaml b/Documentation/devicetree/bindings/gnss/u-blox,neo-6m.yaml index 4835a280b3bf..86b65d4d9266 100644 --- a/Documentation/devicetree/bindings/gnss/u-blox,neo-6m.yaml +++ b/Documentation/devicetree/bindings/gnss/u-blox,neo-6m.yaml @@ -21,6 +21,7 @@ properties: - u-blox,neo-6m - u-blox,neo-8 - u-blox,neo-m8 + - u-blox,zed-f9p reg: description: > -- 2.39.2 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 2/2] dt-bindings: gnss: Add U-Blox Zed-F9 2023-04-29 22:43 ` [PATCH 2/2] dt-bindings: gnss: Add U-Blox Zed-F9 alison @ 2023-04-30 12:17 ` Krzysztof Kozlowski 0 siblings, 0 replies; 8+ messages in thread From: Krzysztof Kozlowski @ 2023-04-30 12:17 UTC (permalink / raw) To: alison, johan; +Cc: linux-kernel, achaiken On 30/04/2023 00:43, alison@she-devel.com wrote: > From: Alison Chaiken <achaiken@aurora.tech> > > Add support for the U-Blox Zed-F9P GNSS device. Please use scripts/get_maintainers.pl to get a list of necessary people and lists to CC. It might happen, that command when run on an older kernel, gives you outdated entries. Therefore please be sure you base your patches on recent Linux kernel. Due to missed all possible entries, this won't be even tested. You must resend. Best regards, Krzysztof ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v3 0/2] support config of U-Blox Zed-F9P GNSS @ 2023-05-01 17:01 alison 2023-05-01 17:01 ` [PATCH 1/2] gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud alison 0 siblings, 1 reply; 8+ messages in thread From: alison @ 2023-05-01 17:01 UTC (permalink / raw) To: johan Cc: robh+dt, krzysztof.kozlowski+dt, devicetree, linux-kernel, alison, achaiken, kernel test robot From: Alison Chaiken <alison@she-devel.com> Add generalized support for setting arbitrary configuration of the U-Blox Zed-F9P GNSS. Employ the new functionality to set the baud rate of the Zed-F9P if the devicetree specifies a non-default value. Tested with 6.1.22, only on a U-Blox Zed-F9P GNSS. V2 -> V3 Add email recipients whom I foolishly missed the first two times. V1 -> V2 Fixes error identified by kernel test robot: Reported-by: kernel test robot <lkp@intel.com> Closes: https://lore.kernel.org/oe-kbuild-all/202304300819.u0hfUj33-lkp@intel.com/ Alison Chaiken (2): gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud dt-bindings: gnss: Add U-Blox Zed-F9 .../bindings/gnss/u-blox,neo-6m.yaml | 1 + drivers/gnss/ubx.c | 195 ++++++++++++++++++ 2 files changed, 196 insertions(+) base-commit: 58390c8ce1bddb6c623f62e7ed36383e7fa5c02f -- 2.39.2 ^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH 1/2] gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud 2023-05-01 17:01 [PATCH v3 0/2] support config of U-Blox Zed-F9P GNSS alison @ 2023-05-01 17:01 ` alison 2023-05-01 17:40 ` Krzysztof Kozlowski 0 siblings, 1 reply; 8+ messages in thread From: alison @ 2023-05-01 17:01 UTC (permalink / raw) To: johan Cc: robh+dt, krzysztof.kozlowski+dt, devicetree, linux-kernel, alison, achaiken From: Alison Chaiken <achaiken@aurora.tech> Add support for setting the baud rate of U-Blox Zed-F9P GNSS devices. Provide functions that support writing of arbitrary configuration messages to the device plus one that specifically configures the baud rate. Override the default gnss_serial_open() with a new method that writes the configuration message to the GNSS if the devicetree declares it to be a Zed F9P and requests a non-default baud. Add a boolean flag to the ubx_data private data of the GNSS driver in order to track whether the configuration message has already been written. Set the Zed F9P to its default port speed if the devicetree does not specify a value. Signed-off-by: Alison Chaiken <achaiken@aurora.tech> --- drivers/gnss/ubx.c | 195 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) diff --git a/drivers/gnss/ubx.c b/drivers/gnss/ubx.c index c951be202ca2..1d59a11f5360 100644 --- a/drivers/gnss/ubx.c +++ b/drivers/gnss/ubx.c @@ -9,18 +9,201 @@ #include <linux/gnss.h> #include <linux/init.h> #include <linux/kernel.h> +#include <linux/kstrtox.h> #include <linux/module.h> #include <linux/of.h> +#include <linux/pm.h> +#include <linux/pm_runtime.h> #include <linux/regulator/consumer.h> #include <linux/serdev.h> #include "serial.h" +/* Total configuration message length = PREAMBLE_LEN + MESSAGE_CLASS_LEN + + * MESSAGE_LENGTH_LEN + payload length + CHECKSUM_LEN + */ +const int32_t PREAMBLE_LEN = 2; +const int32_t MESSAGE_CLASS_LEN = 2; +const int32_t MESSAGE_LENGTH_LEN = 2; +const int32_t CHECKSUM_LEN = 2; +const size_t FIRST_CONFIG_REGISTER_BYTE = 10U; +const size_t FIRST_VALUE_BYTE = 14U; +const size_t FIRST_CHECKSUM_BYTE = 18U; +const size_t CFG_MSG_TOTAL_LEN = 20U; + +uint8_t ZED_F9P_CFG_VALSET_MSG[] = { + 0xB5, 0x62, /* 0-1 preamble */ + 0x06, 0x8A, /* 2-3 CFG_VALSET command */ + 0x0C, 0x00, /* 4-5 payload length = 12 for one key-value pair */ + 0x00, /* 6 U-Blox API version */ + 0x01, /* 7 Write to RAM */ + 0x00, 0x00, /* 8-9 Reserved */ + 0x00, 0x00, 0x00, 0x00, /* 10-13 Placeholder for configuration register */ + 0x00, 0x00, 0x00, 0x00, /* 14-17 Placeholder for baud value */ + 0x00, 0x00 /* 18-19 Placeholder for checksum */ +}; + +const speed_t ZED_F9P_MIN_BAUD = 9600; +const speed_t ZED_F9P_DEFAULT_BAUD = 38400; +const speed_t ZED_F9P_MAX_BAUD = 921600; +const uint32_t ZED_F9P_BAUD_CONFIG_REGISTER = 0x40520001; + struct ubx_data { struct regulator *v_bckp; struct regulator *vcc; + unsigned long is_configured; +}; + +union message_length { + uint16_t ml; + uint8_t bytes[2]; +}; + +union int_to_bytes { + uint32_t int_val; + uint8_t bytes[4]; }; +/* Payload length is contained in bytes 0-2 after message class and ID. + * While the checksum includes the Message class and ID plus message length, the + * payload does not. + */ +static uint16_t get_payload_length(const uint8_t msg[]) +{ + union message_length hs_msg_len; + + hs_msg_len.bytes[0] = msg[PREAMBLE_LEN + MESSAGE_CLASS_LEN]; + hs_msg_len.bytes[1] = msg[PREAMBLE_LEN + MESSAGE_CLASS_LEN + 1U]; + return hs_msg_len.ml; +} + +static int32_t get_msg_total_len(const uint8_t msg[]) +{ + const size_t payload_len = get_payload_length(msg); + + return PREAMBLE_LEN + MESSAGE_CLASS_LEN + MESSAGE_LENGTH_LEN + payload_len + + CHECKSUM_LEN; +} + +/* The checksum is calculated on message class, message ID, message length and + * payload. + */ +static void calc_ubx_checksum(const uint8_t msg[], uint8_t checksum[], + const uint16_t total_len) +{ + uint8_t CK_A = 0; + uint8_t CK_B = 0; + int i; + + for (i = PREAMBLE_LEN; i < (total_len - CHECKSUM_LEN); i++) { + CK_A += msg[i]; + CK_B += CK_A; + } + checksum[0] = CK_A; + checksum[1] = CK_B; +} + +static uint32_t check_baud(speed_t speed, const struct device *dev) +{ + if ((speed < ZED_F9P_MIN_BAUD) || (speed > ZED_F9P_MAX_BAUD)) { + dev_warn(dev, "Baud rate specification %d out of range\n", speed); + speed = ZED_F9P_DEFAULT_BAUD; + } + return speed; +} + +static int prepare_zedf9p_config_msg(const speed_t speed, + const struct device *dev, const size_t msg_register) +{ + union int_to_bytes cfg_val, cfg_register; + int i = 0; + uint8_t checksum[2]; + const size_t total_len = get_msg_total_len(ZED_F9P_CFG_VALSET_MSG); + + if (total_len != CFG_MSG_TOTAL_LEN) + goto bad_msg; + + cfg_val.int_val = check_baud(speed, dev); + cfg_register.int_val = msg_register; + for (i = 0; i < 4; i++) { + ZED_F9P_CFG_VALSET_MSG[FIRST_VALUE_BYTE + i] = cfg_val.bytes[i]; + ZED_F9P_CFG_VALSET_MSG[FIRST_CONFIG_REGISTER_BYTE + i] = cfg_register.bytes[i]; + } + calc_ubx_checksum(ZED_F9P_CFG_VALSET_MSG, checksum, total_len); + ZED_F9P_CFG_VALSET_MSG[FIRST_CHECKSUM_BYTE] = checksum[0]; + ZED_F9P_CFG_VALSET_MSG[FIRST_CHECKSUM_BYTE + 1U] = checksum[1]; + return 0; + + bad_msg: + dev_err(dev, "Malformed UBX-CFG-VALSET message\n"); + return -EINVAL; +} + +/* Configure the Zed F9P baud rate via the UBX-CFG-VALSET message. */ +static int set_zedf9p_baud(struct gnss_device *gdev, + struct serdev_device *serdev, const speed_t speed) +{ + size_t count = 0U; + int ret; + + if (speed == ZED_F9P_DEFAULT_BAUD) + return 0; + + ret = prepare_zedf9p_config_msg(speed, &gdev->dev, ZED_F9P_BAUD_CONFIG_REGISTER); + if (ret) + return ret; + /* Initially set the UART to the default speed to match the GNSS' power-on value. */ + serdev_device_set_baudrate(serdev, ZED_F9P_DEFAULT_BAUD); + /* Now set the new baud rate. */ + count = gdev->ops->write_raw(gdev, ZED_F9P_CFG_VALSET_MSG, CFG_MSG_TOTAL_LEN); + if (count != CFG_MSG_TOTAL_LEN) + return count; + + return 0; +} + +static int ubx_serial_open(struct gnss_device *gdev) +{ + struct gnss_serial *gserial = gnss_get_drvdata(gdev); + struct serdev_device *serdev = gserial->serdev; + struct ubx_data *data = gnss_serial_get_drvdata(gserial); + struct device_node *np; + int ret; + + ret = serdev_device_open(serdev); + if (ret) + return ret; + + serdev_device_set_flow_control(serdev, false); + + np = serdev->dev.of_node; + if ((of_device_is_compatible(np, "u-blox,zed-f9p")) && (!data->is_configured)) { + /* 4800 is the default value set by gnss_serial_parse_dt() */ + if (gserial->speed == 4800) { + /* Fall back instead to Zed F9P default */ + gserial->speed = ZED_F9P_DEFAULT_BAUD; + } else { + ret = set_zedf9p_baud(gdev, serdev, gserial->speed); + if (ret) + return ret; + } + data->is_configured = 1; + } + serdev_device_set_baudrate(serdev, gserial->speed); + + ret = pm_runtime_get_sync(&serdev->dev); + if (ret < 0) { + pm_runtime_put_noidle(&serdev->dev); + goto err_close; + } + return 0; + +err_close: + serdev_device_close(serdev); + + return ret; +} + static int ubx_set_active(struct gnss_serial *gserial) { struct ubx_data *data = gnss_serial_get_drvdata(gserial); @@ -67,6 +250,7 @@ static int ubx_probe(struct serdev_device *serdev) { struct gnss_serial *gserial; struct ubx_data *data; + struct gnss_operations *ubx_gnss_ops; int ret; gserial = gnss_serial_allocate(serdev, sizeof(*data)); @@ -74,12 +258,22 @@ static int ubx_probe(struct serdev_device *serdev) ret = PTR_ERR(gserial); return ret; } + ubx_gnss_ops = kzalloc(sizeof(struct gnss_operations), GFP_KERNEL); + if (IS_ERR(ubx_gnss_ops)) { + ret = PTR_ERR(ubx_gnss_ops); + return ret; + } gserial->ops = &ubx_gserial_ops; gserial->gdev->type = GNSS_TYPE_UBX; + ubx_gnss_ops->open = &ubx_serial_open; + ubx_gnss_ops->close = gserial->gdev->ops->close; + ubx_gnss_ops->write_raw = gserial->gdev->ops->write_raw; + gserial->gdev->ops = ubx_gnss_ops; data = gnss_serial_get_drvdata(gserial); + data->is_configured = 0; data->vcc = devm_regulator_get(&serdev->dev, "vcc"); if (IS_ERR(data->vcc)) { @@ -133,6 +327,7 @@ static const struct of_device_id ubx_of_match[] = { { .compatible = "u-blox,neo-6m" }, { .compatible = "u-blox,neo-8" }, { .compatible = "u-blox,neo-m8" }, + { .compatible = "u-blox,zed-f9p" }, {}, }; MODULE_DEVICE_TABLE(of, ubx_of_match); -- 2.39.2 ^ permalink raw reply related [flat|nested] 8+ messages in thread
* Re: [PATCH 1/2] gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud 2023-05-01 17:01 ` [PATCH 1/2] gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud alison @ 2023-05-01 17:40 ` Krzysztof Kozlowski 0 siblings, 0 replies; 8+ messages in thread From: Krzysztof Kozlowski @ 2023-05-01 17:40 UTC (permalink / raw) To: alison, johan Cc: robh+dt, krzysztof.kozlowski+dt, devicetree, linux-kernel, achaiken On 01/05/2023 19:01, alison@she-devel.com wrote: > From: Alison Chaiken <achaiken@aurora.tech> > > Add support for setting the baud rate of U-Blox Zed-F9P GNSS devices. > Provide functions that support writing of arbitrary configuration > messages to the device plus one that specifically configures the baud > rate. Override the default gnss_serial_open() with a new method that > writes the configuration message to the GNSS if the devicetree declares > it to be a Zed F9P and requests a non-default baud. Add a boolean flag > to the ubx_data private data of the GNSS driver in order to track > whether the configuration message has already been written. Set the Zed > F9P to its default port speed if the devicetree does not specify a > value. > > Signed-off-by: Alison Chaiken <achaiken@aurora.tech> > --- > drivers/gnss/ubx.c | 195 +++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 195 insertions(+) > Thank you for your patch. There is something to discuss/improve. > +/* Configure the Zed F9P baud rate via the UBX-CFG-VALSET message. */ > +static int set_zedf9p_baud(struct gnss_device *gdev, > + struct serdev_device *serdev, const speed_t speed) > +{ > + size_t count = 0U; > + int ret; > + > + if (speed == ZED_F9P_DEFAULT_BAUD) > + return 0; > + > + ret = prepare_zedf9p_config_msg(speed, &gdev->dev, ZED_F9P_BAUD_CONFIG_REGISTER); > + if (ret) > + return ret; > + /* Initially set the UART to the default speed to match the GNSS' power-on value. */ > + serdev_device_set_baudrate(serdev, ZED_F9P_DEFAULT_BAUD); > + /* Now set the new baud rate. */ > + count = gdev->ops->write_raw(gdev, ZED_F9P_CFG_VALSET_MSG, CFG_MSG_TOTAL_LEN); > + if (count != CFG_MSG_TOTAL_LEN) > + return count; > + > + return 0; > +} > + > +static int ubx_serial_open(struct gnss_device *gdev) > +{ > + struct gnss_serial *gserial = gnss_get_drvdata(gdev); > + struct serdev_device *serdev = gserial->serdev; > + struct ubx_data *data = gnss_serial_get_drvdata(gserial); > + struct device_node *np; > + int ret; > + > + ret = serdev_device_open(serdev); > + if (ret) > + return ret; > + > + serdev_device_set_flow_control(serdev, false); > + > + np = serdev->dev.of_node; > + if ((of_device_is_compatible(np, "u-blox,zed-f9p")) && (!data->is_configured)) { Use driver data/match data for such customizations. compatibles sprinkled over the driver code do not scale, make code unreadable. They also obfuscate a but compatibility - based on your of_device_id I would claim devices are compatible and you can remove all the entries except one. ... > @@ -133,6 +327,7 @@ static const struct of_device_id ubx_of_match[] = { > { .compatible = "u-blox,neo-6m" }, > { .compatible = "u-blox,neo-8" }, > { .compatible = "u-blox,neo-m8" }, > + { .compatible = "u-blox,zed-f9p" }, Looks compatible with previous, right? > {}, > }; > MODULE_DEVICE_TABLE(of, ubx_of_match); Best regards, Krzysztof ^ permalink raw reply [flat|nested] 8+ messages in thread
end of thread, other threads:[~2023-05-09 3:10 UTC | newest] Thread overview: 8+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2023-04-29 22:43 [PATCH 0/2] support config of U-Blox Zed-F9P GNSS alison 2023-04-29 22:43 ` [PATCH 1/2] gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud alison 2023-04-30 0:20 ` kernel test robot 2023-05-09 3:09 ` kernel test robot 2023-04-29 22:43 ` [PATCH 2/2] dt-bindings: gnss: Add U-Blox Zed-F9 alison 2023-04-30 12:17 ` Krzysztof Kozlowski -- strict thread matches above, loose matches on Subject: below -- 2023-05-01 17:01 [PATCH v3 0/2] support config of U-Blox Zed-F9P GNSS alison 2023-05-01 17:01 ` [PATCH 1/2] gnss: ubx: customize serial device open to set U-Blox Zed-F9P baud alison 2023-05-01 17:40 ` Krzysztof Kozlowski
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox