From 2adbe4b949041fa54d35fc0f23866948d4c8d27d Mon Sep 17 00:00:00 2001 From: Dawid Niedzwiecki Date: Tue, 27 Apr 2021 10:53:36 +0200 Subject: zephyr: Add CBI SSFC support Some boards support different motion sensors based on the CBI SSFC field stored in EEPROM. The decision about which sensor is made in runtime thus all drivers have to be built-in. Define structure of the SSFC in the device tree("named-cbi-ssfc"), that allows using generic driver instead of board-specific code as it is done in CrosEC. Every SSFC field value("named-cbi-ssfc-value") is associated with an alternative sensor(or sensors) which will be used (instead of the one pointed by 'alternative-for' property) if the value in EEPROM matches. BUG=b:183990188 BRANCH=none TEST=Add alternative motion sensors to the device tree, modify CBI SSFC with 'cbi set 8 value 4', reboot EC and verify that the new sensors are used with the 'accelinfo' command. Signed-off-by: Dawid Niedzwiecki Change-Id: I3b5f3c171005885d96b1fdf14e844aaf862b6818 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/ec/+/2851896 Reviewed-by: Yuval Peress Reviewed-by: Keith Short --- include/motion_sense.h | 5 ++ zephyr/dts/bindings/cbi/named-cbi-ssfc-value.yaml | 28 +++++++ zephyr/dts/bindings/cbi/named-cbi-ssfc.yaml | 55 ++++++++++++++ zephyr/shim/include/cbi_ssfc.h | 91 +++++++++++++++++++++++ zephyr/shim/src/CMakeLists.txt | 1 + zephyr/shim/src/cbi_ssfc.c | 69 +++++++++++++++++ zephyr/shim/src/motionsense_sensors.c | 2 +- 7 files changed, 250 insertions(+), 1 deletion(-) create mode 100644 zephyr/dts/bindings/cbi/named-cbi-ssfc-value.yaml create mode 100644 zephyr/dts/bindings/cbi/named-cbi-ssfc.yaml create mode 100644 zephyr/shim/include/cbi_ssfc.h create mode 100644 zephyr/shim/src/cbi_ssfc.c diff --git a/include/motion_sense.h b/include/motion_sense.h index 29ac220395..d2f6c51e03 100644 --- a/include/motion_sense.h +++ b/include/motion_sense.h @@ -262,6 +262,11 @@ extern mutex_t g_sensor_mutex; /* Defined at board level. */ extern struct motion_sensor_t motion_sensors[]; +#ifdef CONFIG_ZEPHYR +/* Defined for alternative drivers (depends on CBI SSFC) */ +extern struct motion_sensor_t motion_sensors_alt[]; +#endif /* CONFIG_ZEPHYR */ + #ifdef CONFIG_DYNAMIC_MOTION_SENSOR_COUNT extern unsigned motion_sensor_count; #else diff --git a/zephyr/dts/bindings/cbi/named-cbi-ssfc-value.yaml b/zephyr/dts/bindings/cbi/named-cbi-ssfc-value.yaml new file mode 100644 index 0000000000..8755c8ae3d --- /dev/null +++ b/zephyr/dts/bindings/cbi/named-cbi-ssfc-value.yaml @@ -0,0 +1,28 @@ +# Copyright 2021 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +description: + Possible CBI SSFC field values. + It has to be defied as grandchild on the "named-cbi-ssfc" + +compatible: "named-cbi-ssfc-value" + +properties: + value: + type: int + required: true + description: + Unique value of CBI SSFC field + devices: + type: phandles + required: true + description: + Pointers to alternative devices which has to be used if + CBI SSFC matches the defined value + default: + type: boolean + description: + Indicates that the specified value is default for the parent + CBI SSFC field node. It should appear only once for the CBI SSFC + definition. diff --git a/zephyr/dts/bindings/cbi/named-cbi-ssfc.yaml b/zephyr/dts/bindings/cbi/named-cbi-ssfc.yaml new file mode 100644 index 0000000000..bd6c1d535b --- /dev/null +++ b/zephyr/dts/bindings/cbi/named-cbi-ssfc.yaml @@ -0,0 +1,55 @@ +# Copyright 2021 The Chromium OS Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +description: CBI Second Source Factory Cache (SSFC) + +compatible: "named-cbi-ssfc" + +child-binding: + description: + CBI SSFC fields definition. + The order of the children in this node define the order + of the SSFC bit fields from least significant bit to most + significant bit. The total size of all SSFC bit fields + must not exceed 32 bits. + properties: + enum-name: + type: string + required: true + description: + Enum values used only for description purposes + enum: + - BASE_SENSOR + - LID_SENSOR + - LIGHTBAR + - USB_SS_MUX + size: + type: int + required: true + description: The size of the field in bits. + +# Example: +# +# cbi-ssfc { +# compatible = "named-cbi-ssfc"; +# +# base_sensor { +# enum-name = "BASE_SENSOR"; +# size = <3>; +# bmi160 { +# compatible = "named-cbi-ssfc-value"; +# status = "okay"; +# +# value = <1>; +# devices = <&alt_base_accel &alt_base_gyro>; +# }; +# kx022 { +# compatible = "named-cbi-ssfc-value"; +# status = "okay"; +# +# value = <3>; +# devices = <&base_accel_kx022>; +# }; +# }; +# }; \ No newline at end of file diff --git a/zephyr/shim/include/cbi_ssfc.h b/zephyr/shim/include/cbi_ssfc.h new file mode 100644 index 0000000000..08b1223de2 --- /dev/null +++ b/zephyr/shim/include/cbi_ssfc.h @@ -0,0 +1,91 @@ +/* Copyright 2021 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef ZEPHYR_SHIM_INCLUDE_CBI_SSFC_H_ +#define ZEPHYR_SHIM_INCLUDE_CBI_SSFC_H_ + +#include +#include + +#define CBI_SSFC_NODE DT_PATH(cbi_ssfc) + +#define CBI_SSFC_UNION_ENTRY_NAME(id) DT_CAT(cbi_ssfc_, id) +#define CBI_SSFC_UNION_ENTRY(id) \ + uint32_t CBI_SSFC_UNION_ENTRY_NAME(id) \ + : DT_PROP(id, size); + +#define CBI_SSFC_PLUS_FIELD_SIZE(id) + DT_PROP(id, size) +#define CBI_SSFC_FIELDS_SIZE \ + (0 COND_CODE_1(DT_NODE_EXISTS(CBI_SSFC_NODE), \ + (DT_FOREACH_CHILD(CBI_SSFC_NODE, \ + CBI_SSFC_PLUS_FIELD_SIZE)), \ + ())) + +BUILD_ASSERT(CBI_SSFC_FIELDS_SIZE <= 32, "CBI SSFS is bigger than 32 bits"); + +/* + * Define union bit fields based on the device tree entries. Example: + * cbi-ssfc { + * compatible = "named-cbi-ssfc"; + * + * base_sensor { + * enum-name = "BASE_SENSOR"; + * size = <3>; + * bmi160 { + * compatible = "named-cbi-ssfc-value"; + * status = "okay"; + * + * value = <1>; + * devices = <>; + * }; + * }; + * lid_sensor { + * enum-name = "LID_SENSOR"; + * size = <3>; + * bma255 { + * compatible = "named-cbi-ssfc-value"; + * status = "okay"; + * + * value = <1>; + * devices = <&lid_accel>; + * }; + * }; + * lightbar { + * enum-name = "LIGHTBAR"; + * size = <2>; + * 10_led { + * compatible = "named-cbi-ssfc-value"; + * status = "okay"; + * + * value = <1>; + * devices = <>; + * }; + * }; + * }; + * Should be converted into + * union cbi_ssfc { + * struct { + * uint32_t cbi_ssfc_DT_N_S_cbi_ssfc_S_base_sensor:3 + * uint32_t cbi_ssfc_DT_N_S_cbi_ssfc_S_lid_sensor:3 + * uint32_t cbi_ssfc_DT_N_S_cbi_ssfc_S_lightbar:2 + * uint32_t reserved : 24; + * }; + * uint32_t raw_value; + * }; + */ +union cbi_ssfc { + struct { +#if DT_NODE_EXISTS(CBI_SSFC_NODE) + DT_FOREACH_CHILD(CBI_SSFC_NODE, CBI_SSFC_UNION_ENTRY) + uint32_t reserved : (32 - CBI_SSFC_FIELDS_SIZE); +#endif + }; + uint32_t raw_value; +}; + +BUILD_ASSERT(sizeof(union cbi_ssfc) == sizeof(uint32_t), + "CBI SSFS structure exceedes 32 bits"); + +#endif /* ZEPHYR_SHIM_INCLUDE_CBI_SSFC_H_ */ diff --git a/zephyr/shim/src/CMakeLists.txt b/zephyr/shim/src/CMakeLists.txt index 439ea374de..5515a103c3 100644 --- a/zephyr/shim/src/CMakeLists.txt +++ b/zephyr/shim/src/CMakeLists.txt @@ -16,6 +16,7 @@ endif() zephyr_library_sources_ifdef(no_libgcc libgcc_${ARCH}.S) zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_ADC adc.c) +zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_CBI cbi_ssfc.c) zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_ESPI espi.c) zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_FAN fan.c) zephyr_library_sources_ifdef(CONFIG_PLATFORM_EC_FLASH_CROS flash.c) diff --git a/zephyr/shim/src/cbi_ssfc.c b/zephyr/shim/src/cbi_ssfc.c new file mode 100644 index 0000000000..36f0e0eacc --- /dev/null +++ b/zephyr/shim/src/cbi_ssfc.c @@ -0,0 +1,69 @@ +/* Copyright 2021 The Chromium OS Authors. All rights reserved. + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "cbi_ssfc.h" +#include "cros_board_info.h" +#include "hooks.h" +#include "motionsense_sensors.h" +#include "motion_sense.h" +#include + +#define DT_DRV_COMPAT named_cbi_ssfc_value + +LOG_MODULE_REGISTER(cbi_ssfc_shim); + +static union cbi_ssfc cached_ssfc; + +#define REPLACE_ALT_MOTION_SENSOR(new_id, old_id) \ + motion_sensors[SENSOR_ID(old_id)] = \ + motion_sensors_alt[SENSOR_ID(new_id)]; + +#define ALT_MOTION_SENSOR_INIT_ID(id) \ + COND_CODE_1(DT_NODE_HAS_PROP(id, alternate_for), \ + (REPLACE_ALT_MOTION_SENSOR( \ + id, DT_PHANDLE(id, alternate_for))), \ + ()) + +#define ALT_MOTION_SENSOR_INIT(i, id) \ + ALT_MOTION_SENSOR_INIT_ID(DT_PHANDLE_BY_IDX(id, devices, i)) + +#define SSFC_ALT_MOTION_SENSOR_INIT_ID(id) \ + do { \ + if (DT_PROP(id, value) == \ + cached_ssfc.CBI_SSFC_UNION_ENTRY_NAME(DT_PARENT(id))) { \ + UTIL_LISTIFY(DT_PROP_LEN(id, devices), \ + ALT_MOTION_SENSOR_INIT, id) \ + } \ + } while (0); + +#define SSFC_ALT_MOTION_SENSOR_INIT(inst) \ + SSFC_ALT_MOTION_SENSOR_INIT_ID(DT_DRV_INST(inst)) + +#define SSFC_INIT_DEFAULT_ID(id) \ + do { \ + if (DT_PROP(id, default)) { \ + cached_ssfc.CBI_SSFC_UNION_ENTRY_NAME(DT_PARENT(id)) = \ + DT_PROP(id, value); \ + } \ + } while (0); + +#define SSFC_INIT_DEFAULT(inst) \ + SSFC_INIT_DEFAULT_ID(DT_DRV_INST(inst)) + +static void cbi_ssfc_init(void) +{ + if (cbi_get_ssfc(&cached_ssfc.raw_value) != EC_SUCCESS) { + /* Default to values specified in DTS */ + DT_INST_FOREACH_STATUS_OKAY(SSFC_INIT_DEFAULT) + } + + LOG_INF("Read CBI SSFC : 0x%08X \n", cached_ssfc.raw_value); + /* + * Adjust the motion_sensors array as soon as possible to initialize + * correct sensors + */ + DT_INST_FOREACH_STATUS_OKAY(SSFC_ALT_MOTION_SENSOR_INIT) +} +DECLARE_HOOK(HOOK_INIT, cbi_ssfc_init, HOOK_PRIO_FIRST); diff --git a/zephyr/shim/src/motionsense_sensors.c b/zephyr/shim/src/motionsense_sensors.c index bac92e58e8..329c7a4cbe 100644 --- a/zephyr/shim/src/motionsense_sensors.c +++ b/zephyr/shim/src/motionsense_sensors.c @@ -296,7 +296,7 @@ struct motion_sensor_t motion_sensors[] = { * The list of alternate motion sensors that may be used at runtime to replace * an entry in the motion_sensors array. */ -__maybe_unused static struct motion_sensor_t motion_sensors_alt[] = { +__maybe_unused struct motion_sensor_t motion_sensors_alt[] = { #if DT_NODE_EXISTS(SENSOR_ALT_NODE) #include "motionsense_driver/sensor_drv_list.inc" #endif -- cgit v1.2.1