From 7b1349cfe6681abb00c712c673239c7fcdd88953 Mon Sep 17 00:00:00 2001 From: Tom Burdick Date: Wed, 27 Oct 2021 15:07:10 -0500 Subject: [PATCH] stats: i2c: I2C stats Adds the ability for I2C drivers to report synchronous transfer stats using a I2C specific macro to define the device instance. The macro creates a container for device_state which allows for per instance device class common data structure to be used in the device class api (ex: i2c.h). This is used to maintain per driver instance stats for all i2c drivers. This is a reusable idea across other device classes as desired. Using Kconfig device class stats may be turned on/off individually this way as well, in this case I2C_STATS. Signed-off-by: Tom Burdick --- drivers/i2c/Kconfig | 6 ++ drivers/i2c/i2c_b91.c | 2 +- drivers/i2c/i2c_cc13xx_cc26xx.c | 2 +- drivers/i2c/i2c_cc32xx.c | 2 +- drivers/i2c/i2c_dw.c | 2 +- drivers/i2c/i2c_emul.c | 2 +- drivers/i2c/i2c_esp32.c | 4 +- drivers/i2c/i2c_gecko.c | 2 +- drivers/i2c/i2c_gpio.c | 2 +- drivers/i2c/i2c_imx.c | 4 +- drivers/i2c/i2c_ite_it8xxx2.c | 4 +- drivers/i2c/i2c_litex.c | 2 +- drivers/i2c/i2c_ll_stm32.c | 2 +- drivers/i2c/i2c_lpc11u6x.c | 4 +- drivers/i2c/i2c_mchp_xec_v2.c | 2 +- drivers/i2c/i2c_mcux.c | 4 +- drivers/i2c/i2c_mcux_flexcomm.c | 4 +- drivers/i2c/i2c_mcux_lpi2c.c | 2 +- drivers/i2c/i2c_nios2.c | 2 +- drivers/i2c/i2c_npcx_controller.c | 2 +- drivers/i2c/i2c_nrfx_twi.c | 2 +- drivers/i2c/i2c_nrfx_twim.c | 2 +- drivers/i2c/i2c_rcar.c | 2 +- drivers/i2c/i2c_rv32m1_lpi2c.c | 4 +- drivers/i2c/i2c_sam0.c | 4 +- drivers/i2c/i2c_sam4l_twim.c | 2 +- drivers/i2c/i2c_sam_twi.c | 2 +- drivers/i2c/i2c_sam_twihs.c | 2 +- drivers/i2c/i2c_sbcon.c | 2 +- drivers/i2c/i2c_sifive.c | 2 +- drivers/i2c/i2c_tca9546a.c | 2 +- drivers/i2c/i2c_test.c | 2 +- include/device.h | 56 ++++++---- include/drivers/i2c.h | 163 +++++++++++++++++++++++++++++- include/net/ethernet.h | 3 +- include/net/net_if.h | 11 +- include/stats/stats.h | 2 +- 37 files changed, 253 insertions(+), 66 deletions(-) diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig index 486003c8113..b9358f70b4f 100644 --- a/drivers/i2c/Kconfig +++ b/drivers/i2c/Kconfig @@ -22,6 +22,12 @@ config I2C_SHELL The I2C shell currently support scanning and bus recovery. +config I2C_STATS + bool "Enable I2C device Stats" + depends on STATS + help + Enable I2C Stats. + # Include these first so that any properties (e.g. defaults) below can be # overridden (by defining symbols in multiple locations) source "drivers/i2c/Kconfig.b91" diff --git a/drivers/i2c/i2c_b91.c b/drivers/i2c/i2c_b91.c index 2c0105e9692..0d75d801e92 100644 --- a/drivers/i2c/i2c_b91.c +++ b/drivers/i2c/i2c_b91.c @@ -177,7 +177,7 @@ BUILD_ASSERT(DT_NUM_INST_STATUS_OKAY(DT_DRV_COMPAT) <= 1, .pinctrl_list = i2c_pins_##inst \ }; \ \ - DEVICE_DT_INST_DEFINE(inst, i2c_b91_init, \ + I2C_DEVICE_DT_INST_DEFINE(inst, i2c_b91_init, \ NULL, \ &i2c_b91_data_##inst, \ &i2c_b91_cfg_##inst, \ diff --git a/drivers/i2c/i2c_cc13xx_cc26xx.c b/drivers/i2c/i2c_cc13xx_cc26xx.c index 9f29cbfc8f8..180fcf903f0 100644 --- a/drivers/i2c/i2c_cc13xx_cc26xx.c +++ b/drivers/i2c/i2c_cc13xx_cc26xx.c @@ -437,7 +437,7 @@ static struct i2c_cc13xx_cc26xx_data i2c_cc13xx_cc26xx_data = { PM_DEVICE_DT_INST_DEFINE(0, i2c_cc13xx_cc26xx_pm_action); -DEVICE_DT_INST_DEFINE(0, +I2C_DEVICE_DT_INST_DEFINE(0, i2c_cc13xx_cc26xx_init, PM_DEVICE_DT_INST_REF(0), &i2c_cc13xx_cc26xx_data, &i2c_cc13xx_cc26xx_config, diff --git a/drivers/i2c/i2c_cc32xx.c b/drivers/i2c/i2c_cc32xx.c index 5b81cbf84e1..90b11eccc96 100644 --- a/drivers/i2c/i2c_cc32xx.c +++ b/drivers/i2c/i2c_cc32xx.c @@ -382,7 +382,7 @@ static const struct i2c_cc32xx_config i2c_cc32xx_config = { static struct i2c_cc32xx_data i2c_cc32xx_data; -DEVICE_DT_INST_DEFINE(0, &i2c_cc32xx_init, NULL, +I2C_DEVICE_DT_INST_DEFINE(0, i2c_cc32xx_init, NULL, &i2c_cc32xx_data, &i2c_cc32xx_config, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &i2c_cc32xx_driver_api); diff --git a/drivers/i2c/i2c_dw.c b/drivers/i2c/i2c_dw.c index 7e79bd95826..e21507be2ae 100644 --- a/drivers/i2c/i2c_dw.c +++ b/drivers/i2c/i2c_dw.c @@ -728,7 +728,7 @@ static int i2c_dw_initialize(const struct device *dev) I2C_DW_INIT_PCIE(n) \ }; \ static struct i2c_dw_dev_config i2c_##n##_runtime; \ - DEVICE_DT_INST_DEFINE(n, &i2c_dw_initialize, NULL, \ + I2C_DEVICE_DT_INST_DEFINE(n, i2c_dw_initialize, NULL, \ &i2c_##n##_runtime, &i2c_config_dw_##n, \ POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ &funcs); \ diff --git a/drivers/i2c/i2c_emul.c b/drivers/i2c/i2c_emul.c index b7bf4ef1c58..3966d8b08ee 100644 --- a/drivers/i2c/i2c_emul.c +++ b/drivers/i2c/i2c_emul.c @@ -153,7 +153,7 @@ static struct i2c_driver_api i2c_emul_api = { .num_children = ARRAY_SIZE(emuls_##n), \ }; \ static struct i2c_emul_data i2c_emul_data_##n; \ - DEVICE_DT_INST_DEFINE(n, \ + I2C_DEVICE_DT_INST_DEFINE(n, \ i2c_emul_init, \ NULL, \ &i2c_emul_data_##n, \ diff --git a/drivers/i2c/i2c_esp32.c b/drivers/i2c/i2c_esp32.c index a78cc3eca94..8231786a7fe 100644 --- a/drivers/i2c/i2c_esp32.c +++ b/drivers/i2c/i2c_esp32.c @@ -706,8 +706,8 @@ static int IRAM_ATTR i2c_esp32_init(const struct device *dev) .bitrate = I2C_FREQUENCY(idx), \ .default_config = I2C_MODE_MASTER, \ }; \ - DEVICE_DT_DEFINE(DT_NODELABEL(i2c##idx), \ - &i2c_esp32_init, \ + I2C_DEVICE_DT_DEFINE(DT_NODELABEL(i2c##idx), \ + i2c_esp32_init, \ NULL, \ &i2c_esp32_data_##idx, \ &i2c_esp32_config_##idx, \ diff --git a/drivers/i2c/i2c_gecko.c b/drivers/i2c/i2c_gecko.c index 024c2a4640c..3149953e175 100644 --- a/drivers/i2c/i2c_gecko.c +++ b/drivers/i2c/i2c_gecko.c @@ -226,7 +226,7 @@ static const struct i2c_gecko_config i2c_gecko_config_##idx = { \ \ static struct i2c_gecko_data i2c_gecko_data_##idx; \ \ -DEVICE_DT_INST_DEFINE(idx, &i2c_gecko_init, \ +I2C_DEVICE_DT_INST_DEFINE(idx, i2c_gecko_init, \ NULL, \ &i2c_gecko_data_##idx, &i2c_gecko_config_##idx, \ POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ diff --git a/drivers/i2c/i2c_gpio.c b/drivers/i2c/i2c_gpio.c index 75ab299c363..210e5207179 100644 --- a/drivers/i2c/i2c_gpio.c +++ b/drivers/i2c/i2c_gpio.c @@ -182,7 +182,7 @@ static const struct i2c_gpio_config i2c_gpio_dev_cfg_##_num = { \ .bitrate = DT_INST_PROP(_num, clock_frequency), \ }; \ \ -DEVICE_DT_INST_DEFINE(_num, \ +I2C_DEVICE_DT_INST_DEFINE(_num, \ i2c_gpio_init, \ NULL, \ &i2c_gpio_dev_data_##_num, \ diff --git a/drivers/i2c/i2c_imx.c b/drivers/i2c/i2c_imx.c index eb1eb2279b7..a802288fa85 100644 --- a/drivers/i2c/i2c_imx.c +++ b/drivers/i2c/i2c_imx.c @@ -371,8 +371,8 @@ static const struct i2c_driver_api i2c_imx_driver_api = { \ static struct i2c_imx_data i2c_imx_data_##n; \ \ - DEVICE_DT_INST_DEFINE(n, \ - &i2c_imx_init, \ + I2C_DEVICE_DT_INST_DEFINE(n, \ + i2c_imx_init, \ NULL, \ &i2c_imx_data_##n, &i2c_imx_config_##n, \ POST_KERNEL, \ diff --git a/drivers/i2c/i2c_ite_it8xxx2.c b/drivers/i2c/i2c_ite_it8xxx2.c index 263091d6cd1..e8cec68c28f 100644 --- a/drivers/i2c/i2c_ite_it8xxx2.c +++ b/drivers/i2c/i2c_ite_it8xxx2.c @@ -1065,8 +1065,8 @@ static const struct i2c_driver_api i2c_it8xxx2_driver_api = { \ static struct i2c_it8xxx2_data i2c_it8xxx2_data_##idx; \ \ - DEVICE_DT_INST_DEFINE(idx, \ - &i2c_it8xxx2_init, NULL, \ + I2C_DEVICE_DT_INST_DEFINE(idx, \ + i2c_it8xxx2_init, NULL, \ &i2c_it8xxx2_data_##idx, \ &i2c_it8xxx2_cfg_##idx, POST_KERNEL, \ CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ diff --git a/drivers/i2c/i2c_litex.c b/drivers/i2c/i2c_litex.c index 42a2c4bb1e2..abcc51d5f93 100644 --- a/drivers/i2c/i2c_litex.c +++ b/drivers/i2c/i2c_litex.c @@ -124,7 +124,7 @@ static const struct i2c_driver_api i2c_litex_driver_api = { \ static struct i2c_bitbang i2c_bitbang_##n; \ \ - DEVICE_DT_INST_DEFINE(n, \ + I2C_DEVICE_DT_INST_DEFINE(n, \ i2c_litex_init, \ NULL, \ &i2c_bitbang_##n, \ diff --git a/drivers/i2c/i2c_ll_stm32.c b/drivers/i2c/i2c_ll_stm32.c index cf7c5197a05..942f1c2e8f3 100644 --- a/drivers/i2c/i2c_ll_stm32.c +++ b/drivers/i2c/i2c_ll_stm32.c @@ -343,7 +343,7 @@ static const struct i2c_stm32_config i2c_stm32_cfg_##name = { \ \ static struct i2c_stm32_data i2c_stm32_dev_data_##name; \ \ -DEVICE_DT_DEFINE(DT_NODELABEL(name), &i2c_stm32_init, \ +I2C_DEVICE_DT_DEFINE(DT_NODELABEL(name), i2c_stm32_init, \ NULL, &i2c_stm32_dev_data_##name, \ &i2c_stm32_cfg_##name, \ POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ diff --git a/drivers/i2c/i2c_lpc11u6x.c b/drivers/i2c/i2c_lpc11u6x.c index 7c0c8417f35..ccc0c3f3b99 100644 --- a/drivers/i2c/i2c_lpc11u6x.c +++ b/drivers/i2c/i2c_lpc11u6x.c @@ -401,8 +401,8 @@ static const struct lpc11u6x_i2c_config i2c_cfg_##idx = { \ \ static struct lpc11u6x_i2c_data i2c_data_##idx; \ \ -DEVICE_DT_INST_DEFINE(idx, \ - &lpc11u6x_i2c_init, \ +I2C_DEVICE_DT_INST_DEFINE(idx, \ + lpc11u6x_i2c_init, \ NULL, \ &i2c_data_##idx, &i2c_cfg_##idx, \ PRE_KERNEL_1, CONFIG_KERNEL_INIT_PRIORITY_OBJECTS, \ diff --git a/drivers/i2c/i2c_mchp_xec_v2.c b/drivers/i2c/i2c_mchp_xec_v2.c index f38bbd03709..c32c9b4a8ec 100644 --- a/drivers/i2c/i2c_mchp_xec_v2.c +++ b/drivers/i2c/i2c_mchp_xec_v2.c @@ -1163,7 +1163,7 @@ static int i2c_xec_init(const struct device *dev) .pcr_bitpos = DT_INST_PROP_BY_IDX(n, pcrs, 1), \ .irq_config_func = i2c_xec_irq_config_func_##n, \ }; \ - DEVICE_DT_INST_DEFINE(n, &i2c_xec_init, NULL, \ + I2C_DEVICE_DT_INST_DEFINE(n, i2c_xec_init, NULL, \ &i2c_xec_data_##n, &i2c_xec_config_##n, \ POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ &i2c_xec_driver_api); \ diff --git a/drivers/i2c/i2c_mcux.c b/drivers/i2c/i2c_mcux.c index 6b4353e4a9c..b378abd60d5 100644 --- a/drivers/i2c/i2c_mcux.c +++ b/drivers/i2c/i2c_mcux.c @@ -230,8 +230,8 @@ static const struct i2c_driver_api i2c_mcux_driver_api = { \ static struct i2c_mcux_data i2c_mcux_data_ ## n; \ \ - DEVICE_DT_INST_DEFINE(n, \ - &i2c_mcux_init, NULL, \ + I2C_DEVICE_DT_INST_DEFINE(n, \ + i2c_mcux_init, NULL, \ &i2c_mcux_data_ ## n, \ &i2c_mcux_config_ ## n, POST_KERNEL, \ CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ diff --git a/drivers/i2c/i2c_mcux_flexcomm.c b/drivers/i2c/i2c_mcux_flexcomm.c index 3921b3222aa..7efe870d2aa 100644 --- a/drivers/i2c/i2c_mcux_flexcomm.c +++ b/drivers/i2c/i2c_mcux_flexcomm.c @@ -225,8 +225,8 @@ static const struct i2c_driver_api mcux_flexcomm_driver_api = { .bitrate = DT_INST_PROP(id, clock_frequency), \ }; \ static struct mcux_flexcomm_data mcux_flexcomm_data_##id; \ - DEVICE_DT_INST_DEFINE(id, \ - &mcux_flexcomm_init, \ + I2C_DEVICE_DT_INST_DEFINE(id, \ + mcux_flexcomm_init, \ NULL, \ &mcux_flexcomm_data_##id, \ &mcux_flexcomm_config_##id, \ diff --git a/drivers/i2c/i2c_mcux_lpi2c.c b/drivers/i2c/i2c_mcux_lpi2c.c index d4107fa5726..9362420cd5a 100644 --- a/drivers/i2c/i2c_mcux_lpi2c.c +++ b/drivers/i2c/i2c_mcux_lpi2c.c @@ -260,7 +260,7 @@ static const struct i2c_driver_api mcux_lpi2c_driver_api = { \ static struct mcux_lpi2c_data mcux_lpi2c_data_##n; \ \ - DEVICE_DT_INST_DEFINE(n, &mcux_lpi2c_init, NULL, \ + I2C_DEVICE_DT_INST_DEFINE(n, mcux_lpi2c_init, NULL, \ &mcux_lpi2c_data_##n, \ &mcux_lpi2c_config_##n, POST_KERNEL, \ CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ diff --git a/drivers/i2c/i2c_nios2.c b/drivers/i2c/i2c_nios2.c index f49521dc4e5..19d3e614ca0 100644 --- a/drivers/i2c/i2c_nios2.c +++ b/drivers/i2c/i2c_nios2.c @@ -165,7 +165,7 @@ static struct i2c_nios2_config i2c_nios2_cfg = { }, }; -DEVICE_DT_INST_DEFINE(0, &i2c_nios2_init, NULL, +I2C_DEVICE_DT_INST_DEFINE(0, i2c_nios2_init, NULL, NULL, &i2c_nios2_cfg, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE, &i2c_nios2_driver_api); diff --git a/drivers/i2c/i2c_npcx_controller.c b/drivers/i2c/i2c_npcx_controller.c index 183b8bd7b99..689360a5e9b 100644 --- a/drivers/i2c/i2c_npcx_controller.c +++ b/drivers/i2c/i2c_npcx_controller.c @@ -962,7 +962,7 @@ static int i2c_ctrl_init(const struct device *dev) \ static struct i2c_ctrl_data i2c_ctrl_data_##inst; \ \ - DEVICE_DT_INST_DEFINE(inst, \ + I2C_DEVICE_DT_INST_DEFINE(inst, \ NPCX_I2C_CTRL_INIT_FUNC(inst), \ NULL, \ &i2c_ctrl_data_##inst, &i2c_ctrl_cfg_##inst, \ diff --git a/drivers/i2c/i2c_nrfx_twi.c b/drivers/i2c/i2c_nrfx_twi.c index ad9784afe0a..8412f1b9305 100644 --- a/drivers/i2c/i2c_nrfx_twi.c +++ b/drivers/i2c/i2c_nrfx_twi.c @@ -287,7 +287,7 @@ static int twi_nrfx_pm_action(const struct device *dev, } \ }; \ PM_DEVICE_DT_DEFINE(I2C(idx), twi_nrfx_pm_action); \ - DEVICE_DT_DEFINE(I2C(idx), \ + I2C_DEVICE_DT_DEFINE(I2C(idx), \ twi_##idx##_init, \ PM_DEVICE_DT_REF(I2C(idx)), \ &twi_##idx##_data, \ diff --git a/drivers/i2c/i2c_nrfx_twim.c b/drivers/i2c/i2c_nrfx_twim.c index 2db76890926..1acb52538c4 100644 --- a/drivers/i2c/i2c_nrfx_twim.c +++ b/drivers/i2c/i2c_nrfx_twim.c @@ -372,7 +372,7 @@ static int twim_nrfx_pm_action(const struct device *dev, .flash_buf_max_size = FLASH_BUF_MAX_SIZE(idx), \ }; \ PM_DEVICE_DT_DEFINE(I2C(idx), twim_nrfx_pm_action); \ - DEVICE_DT_DEFINE(I2C(idx), \ + I2C_DEVICE_DT_DEFINE(I2C(idx), \ twim_##idx##_init, \ PM_DEVICE_DT_REF(I2C(idx)), \ &twim_##idx##_data, \ diff --git a/drivers/i2c/i2c_rcar.c b/drivers/i2c/i2c_rcar.c index 22935ec5a90..26e56cbcacc 100644 --- a/drivers/i2c/i2c_rcar.c +++ b/drivers/i2c/i2c_rcar.c @@ -367,7 +367,7 @@ static const struct i2c_driver_api i2c_rcar_driver_api = { \ static struct i2c_rcar_data i2c_rcar_data_##n; \ \ - DEVICE_DT_INST_DEFINE(n, \ + I2C_DEVICE_DT_INST_DEFINE(n, \ i2c_rcar_init, \ NULL, \ &i2c_rcar_data_##n, \ diff --git a/drivers/i2c/i2c_rv32m1_lpi2c.c b/drivers/i2c/i2c_rv32m1_lpi2c.c index ae9e09c0b92..847ed783625 100644 --- a/drivers/i2c/i2c_rv32m1_lpi2c.c +++ b/drivers/i2c/i2c_rv32m1_lpi2c.c @@ -264,8 +264,8 @@ static const struct i2c_driver_api rv32m1_lpi2c_driver_api = { .completion_sync = Z_SEM_INITIALIZER( \ rv32m1_lpi2c_##id##_data.completion_sync, 0, 1), \ }; \ - DEVICE_DT_INST_DEFINE(id, \ - &rv32m1_lpi2c_init, \ + I2C_DEVICE_DT_INST_DEFINE(id, \ + rv32m1_lpi2c_init, \ NULL, \ &rv32m1_lpi2c_##id##_data, \ &rv32m1_lpi2c_##id##_config, \ diff --git a/drivers/i2c/i2c_sam0.c b/drivers/i2c/i2c_sam0.c index ee8e4796c6a..388b38e65b1 100644 --- a/drivers/i2c/i2c_sam0.c +++ b/drivers/i2c/i2c_sam0.c @@ -807,8 +807,8 @@ static const struct i2c_sam0_dev_config i2c_sam0_dev_config_##n = { \ static void i2c_sam0_irq_config_##n(const struct device *dev); \ I2C_SAM0_CONFIG(n); \ static struct i2c_sam0_dev_data i2c_sam0_dev_data_##n; \ - DEVICE_DT_INST_DEFINE(n, \ - &i2c_sam0_initialize, \ + I2C_DEVICE_DT_INST_DEFINE(n, \ + i2c_sam0_initialize, \ NULL, \ &i2c_sam0_dev_data_##n, \ &i2c_sam0_dev_config_##n, POST_KERNEL, \ diff --git a/drivers/i2c/i2c_sam4l_twim.c b/drivers/i2c/i2c_sam4l_twim.c index 2cfc3c21a86..6a4dfc58a8f 100644 --- a/drivers/i2c/i2c_sam4l_twim.c +++ b/drivers/i2c/i2c_sam4l_twim.c @@ -628,7 +628,7 @@ static const struct i2c_driver_api i2c_sam_twim_driver_api = { \ static struct i2c_sam_twim_dev_data i2c##n##_sam_data; \ \ - DEVICE_DT_INST_DEFINE(n, &i2c_sam_twim_initialize, \ + I2C_DEVICE_DT_INST_DEFINE(n, i2c_sam_twim_initialize, \ NULL, \ &i2c##n##_sam_data, &i2c##n##_sam_config, \ POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ diff --git a/drivers/i2c/i2c_sam_twi.c b/drivers/i2c/i2c_sam_twi.c index bdc414830cb..c4235054036 100644 --- a/drivers/i2c/i2c_sam_twi.c +++ b/drivers/i2c/i2c_sam_twi.c @@ -360,7 +360,7 @@ static const struct i2c_driver_api i2c_sam_twi_driver_api = { \ static struct i2c_sam_twi_dev_data i2c##n##_sam_data; \ \ - DEVICE_DT_INST_DEFINE(n, &i2c_sam_twi_initialize, \ + I2C_DEVICE_DT_INST_DEFINE(n, i2c_sam_twi_initialize, \ NULL, \ &i2c##n##_sam_data, &i2c##n##_sam_config, \ POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ diff --git a/drivers/i2c/i2c_sam_twihs.c b/drivers/i2c/i2c_sam_twihs.c index a997dd7708f..abd5c9e6b39 100644 --- a/drivers/i2c/i2c_sam_twihs.c +++ b/drivers/i2c/i2c_sam_twihs.c @@ -347,7 +347,7 @@ static const struct i2c_driver_api i2c_sam_twihs_driver_api = { \ static struct i2c_sam_twihs_dev_data i2c##n##_sam_data; \ \ - DEVICE_DT_INST_DEFINE(n, &i2c_sam_twihs_initialize, \ + I2C_DEVICE_DT_INST_DEFINE(n, i2c_sam_twihs_initialize, \ NULL, \ &i2c##n##_sam_data, &i2c##n##_sam_config, \ POST_KERNEL, CONFIG_I2C_INIT_PRIORITY, \ diff --git a/drivers/i2c/i2c_sbcon.c b/drivers/i2c/i2c_sbcon.c index 9d9024de7ce..f844cdab2ce 100644 --- a/drivers/i2c/i2c_sbcon.c +++ b/drivers/i2c/i2c_sbcon.c @@ -116,7 +116,7 @@ static const struct i2c_sbcon_config i2c_sbcon_dev_cfg_##_num = { \ .sbcon = (void *)DT_INST_REG_ADDR(_num), \ }; \ \ -DEVICE_DT_INST_DEFINE(_num, \ +I2C_DEVICE_DT_INST_DEFINE(_num, \ i2c_sbcon_init, \ NULL, \ &i2c_sbcon_dev_data_##_num, \ diff --git a/drivers/i2c/i2c_sifive.c b/drivers/i2c/i2c_sifive.c index 863cf15e195..fa8e225a73d 100644 --- a/drivers/i2c/i2c_sifive.c +++ b/drivers/i2c/i2c_sifive.c @@ -329,7 +329,7 @@ static struct i2c_driver_api i2c_sifive_api = { .f_sys = DT_INST_PROP(n, input_frequency), \ .f_bus = DT_INST_PROP(n, clock_frequency), \ }; \ - DEVICE_DT_INST_DEFINE(n, \ + I2C_DEVICE_DT_INST_DEFINE(n, \ i2c_sifive_init, \ NULL, \ NULL, \ diff --git a/drivers/i2c/i2c_tca9546a.c b/drivers/i2c/i2c_tca9546a.c index 2da2a665936..1f0d6cec9b0 100644 --- a/drivers/i2c/i2c_tca9546a.c +++ b/drivers/i2c/i2c_tca9546a.c @@ -158,7 +158,7 @@ const struct i2c_driver_api tca9546a_api_funcs = { static struct tca9546a_root_data tca9546a_data_##inst = { \ .lock = Z_MUTEX_INITIALIZER(tca9546a_data_##inst.lock), \ }; \ - DEVICE_DT_INST_DEFINE(inst, \ + I2C_DEVICE_DT_INST_DEFINE(inst, \ tca9546_root_init, NULL, \ &tca9546a_data_##inst, &tca9546a_cfg_##inst, \ POST_KERNEL, CONFIG_I2C_TCA9546_ROOT_INIT_PRIO, \ diff --git a/drivers/i2c/i2c_test.c b/drivers/i2c/i2c_test.c index fe56f0ef387..c17451c448a 100644 --- a/drivers/i2c/i2c_test.c +++ b/drivers/i2c/i2c_test.c @@ -38,7 +38,7 @@ static int vnd_i2c_init(const struct device *dev) } #define VND_I2C_INIT(n) \ - DEVICE_DT_INST_DEFINE(n, &vnd_i2c_init, NULL, \ + I2C_DEVICE_DT_INST_DEFINE(n, vnd_i2c_init, NULL, \ NULL, NULL, POST_KERNEL, \ CONFIG_KERNEL_INIT_PRIORITY_DEVICE, \ &vnd_i2c_api); diff --git a/include/device.h b/include/device.h index b505fab8a40..7a5fe33849d 100644 --- a/include/device.h +++ b/include/device.h @@ -92,6 +92,31 @@ typedef int16_t device_handle_t; DEVICE_DEFINE(Z_SYS_NAME(init_fn), drv_name, init_fn, NULL, \ NULL, NULL, level, prio, NULL) +/* Node paths can exceed the maximum size supported by device_get_binding() in user mode, + * so synthesize a unique dev_name from the devicetree node. + * + * The ordinal used in this name can be mapped to the path by + * examining zephyr/include/generated/device_extern.h header. If the + * format of this conversion changes, gen_defines should be updated to + * match it. + */ +#define Z_DEVICE_DT_DEV_NAME(node_id) _CONCAT(dts_ord_, DT_DEP_ORD(node_id)) + +/* Synthesize a unique name for the device state associated with + * dev_name. + */ +#define Z_DEVICE_STATE_NAME(dev_name) _CONCAT(__devstate_, dev_name) + +/** + * @brief Utility macro to define and initialize the device state. + * + * @param node_id Devicetree node id of the device. + * @param dev_name Device name. + */ +#define Z_DEVICE_STATE_DEFINE(node_id, dev_name) \ + static struct device_state Z_DEVICE_STATE_NAME(dev_name) \ + __attribute__((__section__(".z_devstate"))); + /** * @def DEVICE_DEFINE * @@ -129,9 +154,11 @@ typedef int16_t device_handle_t; */ #define DEVICE_DEFINE(dev_name, drv_name, init_fn, pm_device, \ data_ptr, cfg_ptr, level, prio, api_ptr) \ + Z_DEVICE_STATE_DEFINE(DT_INVALID_NODE, dev_name) \ Z_DEVICE_DEFINE(DT_INVALID_NODE, dev_name, drv_name, init_fn, \ pm_device, \ - data_ptr, cfg_ptr, level, prio, api_ptr) + data_ptr, cfg_ptr, level, prio, api_ptr, \ + &Z_DEVICE_STATE_NAME(dev_name)) /** * @def DEVICE_DT_NAME @@ -187,11 +214,14 @@ typedef int16_t device_handle_t; #define DEVICE_DT_DEFINE(node_id, init_fn, pm_device, \ data_ptr, cfg_ptr, level, prio, \ api_ptr, ...) \ + Z_DEVICE_STATE_DEFINE(node_id, Z_DEVICE_DT_DEV_NAME(node_id)) \ Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_NAME(node_id), \ DEVICE_DT_NAME(node_id), init_fn, \ pm_device, \ data_ptr, cfg_ptr, level, prio, \ - api_ptr, __VA_ARGS__) + api_ptr, \ + &Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_NAME(node_id)), \ + __VA_ARGS__) /** * @def DEVICE_DT_INST_DEFINE @@ -693,21 +723,6 @@ static inline bool device_is_ready(const struct device *dev) * @} */ -/* Node paths can exceed the maximum size supported by device_get_binding() in user mode, - * so synthesize a unique dev_name from the devicetree node. - * - * The ordinal used in this name can be mapped to the path by - * examining zephyr/include/generated/device_extern.h header. If the - * format of this conversion changes, gen_defines should be updated to - * match it. - */ -#define Z_DEVICE_DT_DEV_NAME(node_id) _CONCAT(dts_ord_, DT_DEP_ORD(node_id)) - -/* Synthesize a unique name for the device state associated with - * dev_name. - */ -#define Z_DEVICE_STATE_NAME(dev_name) _CONCAT(__devstate_, dev_name) - /** Synthesize the name of the object that holds device ordinal and * dependency data. If the object doesn't come from a devicetree * node, use dev_name. @@ -735,8 +750,7 @@ static inline bool device_is_ready(const struct device *dev) * include power management and dependency handles. */ #define Z_DEVICE_DEFINE_PRE(node_id, dev_name, ...) \ - Z_DEVICE_DEFINE_HANDLES(node_id, dev_name, __VA_ARGS__) \ - Z_DEVICE_STATE_DEFINE(node_id, dev_name) + Z_DEVICE_DEFINE_HANDLES(node_id, dev_name, __VA_ARGS__) /* Initial build provides a record that associates the device object * with its devicetree ordinal, and provides the dependency ordinals. @@ -805,7 +819,7 @@ BUILD_ASSERT(sizeof(device_handle_t) == 2, "fix the linker scripts"); * dependency handles that come from outside devicetree. */ #define Z_DEVICE_DEFINE(node_id, dev_name, drv_name, init_fn, pm_device,\ - data_ptr, cfg_ptr, level, prio, api_ptr, ...) \ + data_ptr, cfg_ptr, level, prio, api_ptr, state_ptr, ...) \ Z_DEVICE_DEFINE_PRE(node_id, dev_name, __VA_ARGS__) \ COND_CODE_1(DT_NODE_EXISTS(node_id), (), (static)) \ const Z_DECL_ALIGN(struct device) \ @@ -814,7 +828,7 @@ BUILD_ASSERT(sizeof(device_handle_t) == 2, "fix the linker scripts"); .name = drv_name, \ .config = (cfg_ptr), \ .api = (api_ptr), \ - .state = &Z_DEVICE_STATE_NAME(dev_name), \ + .state = (state_ptr), \ .data = (data_ptr), \ COND_CODE_1(CONFIG_PM_DEVICE, (.pm = pm_device,), ()) \ Z_DEVICE_DEFINE_INIT(node_id, dev_name) \ diff --git a/include/drivers/i2c.h b/include/drivers/i2c.h index 7cac9936d29..a47dcc20377 100644 --- a/include/drivers/i2c.h +++ b/include/drivers/i2c.h @@ -337,6 +337,163 @@ struct i2c_slave_config { const struct i2c_slave_callbacks *callbacks; }; +#if defined(CONFIG_I2C_STATS) || defined(__DOXYGEN__) + +#include + +/** @cond INTERNAL_HIDDEN */ + +STATS_SECT_START(i2c) +STATS_SECT_ENTRY32(bytes_read) +STATS_SECT_ENTRY32(bytes_written) +STATS_SECT_ENTRY32(message_count) +STATS_SECT_ENTRY32(transfer_call_count) +STATS_SECT_END; + +STATS_NAME_START(i2c) +STATS_NAME(i2c, bytes_read) +STATS_NAME(i2c, bytes_written) +STATS_NAME(i2c, message_count) +STATS_NAME(i2c, transfer_call_count) +STATS_NAME_END(i2c); + +/** @endcond */ + + +/** + * @brief I2C specific device state which allows for i2c device class specific additions + */ +struct i2c_device_state { + struct device_state devstate; + struct stats_i2c stats; +}; + +/** + * @brief Updates the i2c stats for i2c transfers + * + * @param dev I2C device to update stats for + * @param msgs Array of struct i2c_msg + * @param num_msgs Number of i2c_msgs + */ +static inline void i2c_xfer_stats(const struct device *dev, struct i2c_msg *msgs, + uint8_t num_msgs) +{ + struct i2c_device_state *state = + CONTAINER_OF(dev->state, struct i2c_device_state, devstate); + uint32_t bytes_read = 0U; + uint32_t bytes_written = 0U; + + STATS_INC(state->stats, transfer_call_count); + STATS_INCN(state->stats, message_count, num_msgs); + for (uint8_t i = 0U; i < num_msgs; i++) { + if (msgs[i].flags & I2C_MSG_READ) { + bytes_read += msgs[i].len; + } + if (msgs[i].flags & I2C_MSG_WRITE) { + bytes_written += msgs[i].len; + } + } + STATS_INCN(state->stats, bytes_read, bytes_read); + STATS_INCN(state->stats, bytes_written, bytes_written); +} + +/** @cond INTERNAL_HIDDEN */ + +/** + * @brief Define a statically allocated and section assigned i2c device state + */ +#define Z_I2C_DEVICE_STATE_DEFINE(node_id, dev_name) \ + static struct i2c_device_state Z_DEVICE_STATE_NAME(dev_name) \ + __attribute__((__section__(".z_devstate"))); + +/** + * @brief Define an i2c device init wrapper function + * + * This does device instance specific initialization of common data (such as stats) + * and calls the given init_fn + */ +#define Z_I2C_INIT_FN(dev_name, init_fn) \ + static inline int UTIL_CAT(dev_name, _init)(const struct device *dev) \ + { \ + struct i2c_device_state *state = \ + CONTAINER_OF(dev->state, struct i2c_device_state, devstate); \ + stats_init(&state->stats.s_hdr, STATS_SIZE_32, 4, \ + STATS_NAME_INIT_PARMS(i2c)); \ + stats_register(dev->name, &(state->stats.s_hdr)); \ + return init_fn(dev); \ + } + +/** @endcond */ + +/** + * @brief Like DEVICE_DT_DEFINE() with I2C specifics. + * + * @details Defines a device which implements the I2C API. May + * generate a custom device_state container struct and init_fn + * wrapper when needed depending on I2C @kconfig{CONFIG_I2C_STATS}. + * + * @param node_id The devicetree node identifier. + * + * @param init_fn Name of the init function of the driver. + * + * @param pm_device PM device resources reference (NULL if device does not use PM). + * + * @param data_ptr Pointer to the device's private data. + * + * @param cfg_ptr The address to the structure containing the + * configuration information for this instance of the driver. + * + * @param level The initialization level. See SYS_INIT() for + * details. + * + * @param prio Priority within the selected initialization level. See + * SYS_INIT() for details. + * + * @param api_ptr Provides an initial pointer to the API function struct + * used by the driver. Can be NULL. + */ +#define I2C_DEVICE_DT_DEFINE(node_id, init_fn, pm_device, \ + data_ptr, cfg_ptr, level, prio, \ + api_ptr, ...) \ + Z_I2C_DEVICE_STATE_DEFINE(node_id, Z_DEVICE_DT_DEV_NAME(node_id)); \ + Z_I2C_INIT_FN(Z_DEVICE_DT_DEV_NAME(node_id), init_fn) \ + Z_DEVICE_DEFINE(node_id, Z_DEVICE_DT_DEV_NAME(node_id), \ + DEVICE_DT_NAME(node_id), \ + &UTIL_CAT(Z_DEVICE_DT_DEV_NAME(node_id), _init), \ + pm_device, \ + data_ptr, cfg_ptr, level, prio, \ + api_ptr, \ + &(Z_DEVICE_STATE_NAME(Z_DEVICE_DT_DEV_NAME(node_id)).devstate), \ + __VA_ARGS__) + +#else /* CONFIG_I2C_STATS */ + +static inline void i2c_xfer_stats(const struct device *dev, struct i2c_msg *msgs, + uint8_t num_msgs) +{ +} + +#define I2C_DEVICE_DT_DEFINE(node_id, init_fn, pm_device, \ + data_ptr, cfg_ptr, level, prio, \ + api_ptr, ...) \ + DEVICE_DT_DEFINE(node_id, &init_fn, pm_device, \ + data_ptr, cfg_ptr, level, prio, \ + api_ptr, __VA_ARGS__) + +#endif /* CONFIG_I2C_STATS */ + +/** + * @brief Like I2C_DEVICE_DT_DEFINE() for an instance of a DT_DRV_COMPAT compatible + * + * @param inst instance number. This is replaced by + * DT_DRV_COMPAT(inst) in the call to I2C_DEVICE_DT_DEFINE(). + * + * @param ... other parameters as expected by I2C_DEVICE_DT_DEFINE(). + */ +#define I2C_DEVICE_DT_INST_DEFINE(inst, ...) \ + I2C_DEVICE_DT_DEFINE(DT_DRV_INST(inst), __VA_ARGS__) + + /** * @brief Configure operation of a host controller. * @@ -429,7 +586,11 @@ static inline int z_impl_i2c_transfer(const struct device *dev, const struct i2c_driver_api *api = (const struct i2c_driver_api *)dev->api; - return api->transfer(dev, msgs, num_msgs, addr); + int res = api->transfer(dev, msgs, num_msgs, addr); + + i2c_xfer_stats(dev, msgs, num_msgs); + + return res; } /** diff --git a/include/net/ethernet.h b/include/net/ethernet.h index 07b71e1e9f1..4ef20be6afe 100644 --- a/include/net/ethernet.h +++ b/include/net/ethernet.h @@ -828,9 +828,10 @@ static inline bool net_eth_get_vlan_status(struct net_if *iface) #if defined(CONFIG_NET_VLAN) #define Z_ETH_NET_DEVICE_INIT(node_id, dev_name, drv_name, init_fn, \ pm_action_cb, data, cfg, prio, api, mtu) \ + Z_DEVICE_STATE_DEFINE(node_id, dev_name) \ Z_DEVICE_DEFINE(node_id, dev_name, drv_name, init_fn, \ pm_action_cb, data, cfg, POST_KERNEL, \ - prio, api); \ + prio, api, &Z_DEVICE_STATE_NAME(dev_name)); \ NET_L2_DATA_INIT(dev_name, 0, NET_L2_GET_CTX_TYPE(ETHERNET_L2));\ NET_IF_INIT(dev_name, 0, ETHERNET_L2, mtu, NET_VLAN_MAX_COUNT) diff --git a/include/net/net_if.h b/include/net/net_if.h index 9fb1c12822e..422e67731a0 100644 --- a/include/net/net_if.h +++ b/include/net/net_if.h @@ -2250,9 +2250,11 @@ struct net_if_api { #define Z_NET_DEVICE_INIT(node_id, dev_name, drv_name, init_fn, \ pm_action_cb, data, cfg, prio, api, l2, \ l2_ctx_type, mtu) \ + Z_DEVICE_STATE_DEFINE(node_id, dev_name) \ Z_DEVICE_DEFINE(node_id, dev_name, drv_name, init_fn, \ pm_action_cb, data, \ - cfg, POST_KERNEL, prio, api); \ + cfg, POST_KERNEL, prio, api, \ + &Z_DEVICE_STATE_NAME(dev_name)); \ NET_L2_DATA_INIT(dev_name, 0, l2_ctx_type); \ NET_IF_INIT(dev_name, 0, l2, mtu, NET_IF_MAX_CONFIGS) @@ -2328,9 +2330,10 @@ struct net_if_api { instance, init_fn, pm_action_cb, \ data, cfg, prio, api, l2, \ l2_ctx_type, mtu) \ + Z_DEVICE_STATE_DEFINE(node_id, dev_name) \ Z_DEVICE_DEFINE(node_id, dev_name, drv_name, init_fn, \ pm_action_cb, data, cfg, POST_KERNEL, \ - prio, api); \ + prio, api, &Z_DEVICE_STATE_NAME(dev_name)); \ NET_L2_DATA_INIT(dev_name, instance, l2_ctx_type); \ NET_IF_INIT(dev_name, instance, l2, mtu, NET_IF_MAX_CONFIGS) @@ -2417,8 +2420,10 @@ struct net_if_api { #define Z_NET_DEVICE_OFFLOAD_INIT(node_id, dev_name, drv_name, init_fn, \ pm_action_cb, data, cfg, prio, \ api, mtu) \ + Z_DEVICE_STATE_DEFINE(node_id, dev_name) \ Z_DEVICE_DEFINE(node_id, dev_name, drv_name, init_fn, \ - pm_action_cb, data, cfg, POST_KERNEL, prio, api);\ + pm_action_cb, data, cfg, POST_KERNEL, prio, api, \ + &Z_DEVICE_STATE_NAME(dev_name)); \ NET_IF_OFFLOAD_INIT(dev_name, 0, mtu) /** diff --git a/include/stats/stats.h b/include/stats/stats.h index d3ca7141234..e4793b5c736 100644 --- a/include/stats/stats.h +++ b/include/stats/stats.h @@ -373,7 +373,7 @@ struct stats_hdr *stats_group_find(const char *name); #define STATS_NAME_MAP_NAME(sectname__) stats_map_ ## sectname__ #define STATS_NAME_START(sectname__) \ - const struct stats_name_map STATS_NAME_MAP_NAME(sectname__)[] = { + static const struct stats_name_map STATS_NAME_MAP_NAME(sectname__)[] = { #define STATS_NAME(sectname__, entry__) \ { offsetof(STATS_SECT_DECL(sectname__), entry__), #entry__ },