Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/hal/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ write_register_t spi_write_register;
int (*i2c_change_addr)(int fd, unsigned char addr);
float (*hal_temperature)();
void (*hal_cleanup)();
void (*hal_enable_sensor_clock)();

#ifndef STANDALONE_LIBRARY
void (*hal_detect_ethernet)(cJSON *root);
Expand Down Expand Up @@ -223,6 +224,9 @@ void setup_hal_fallback() {
i2c_write_register = universal_i2c_write_register;
spi_write_register = universal_spi_write_register;
hal_cleanup = universal_hal_cleanup;
/* Cleared, not defaulted: most SoCs need nothing done to make the sensor
* answer, and this runs before detection picks the one that does. */
hal_enable_sensor_clock = NULL;
#ifndef STANDALONE_LIBRARY
hal_totalmem = default_totalmem;
#endif
Expand Down
6 changes: 6 additions & 0 deletions src/hal/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,12 @@ extern write_register_t spi_write_register;
extern float (*hal_temperature)();
extern void (*hal_cleanup)();

/* Put the sensor in a state where it can answer a probe, where that takes
* doing. Ingenic gates the sensor's clock, and whoever had the pipeline up
* last may well have gated it off again on the way down — so this has to run
* before every probe, not once per process. NULL where nothing is needed. */
extern void (*hal_enable_sensor_clock)();

#ifndef STANDALONE_LIBRARY
extern void (*hal_detect_ethernet)(cJSON *handle);
extern unsigned long (*hal_totalmem)(unsigned long *media_mem);
Expand Down
6 changes: 6 additions & 0 deletions src/hal/ingenic.c
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,12 @@ void setup_hal_ingenic() {
ingenic_enable_sensor_clock();
possible_i2c_addrs = ingenic_possible_i2c_addrs;
open_i2c_sensor_fd = ingenic_open_i2c_fd;
/* Also as a hook, because the call above only ever runs once: getchipname()
* caches the chip id and returns before ever reaching here again. Anything
* that gates the clock off afterwards — the vendor SDK does, on the way
* down — would otherwise leave every later probe reading an unclocked
* sensor and reporting that there is none. */
hal_enable_sensor_clock = ingenic_enable_sensor_clock;
#ifndef STANDALONE_LIBRARY
hal_totalmem = ingenic_totalmem;
#endif
Expand Down
11 changes: 11 additions & 0 deletions src/sensors.c
Original file line number Diff line number Diff line change
Expand Up @@ -1194,6 +1194,17 @@ bool getsensorid(sensor_ctx_t *ctx) {
int current_i2c_adapter_nr;
if (!getchipname())
return NULL;

/* Every probe, not just the first. getchipname() sets the HAL up once and
* then returns its cached answer forever, so anything the setup did to
* make the sensor answerable was done once too. On Ingenic that is the
* sensor's clock, and the vendor SDK gates it off when it tears a pipeline
* down: a second probe in the same process then found an unclocked sensor
* and reported that the board has none. A fresh process got it right,
* which is what made it look like the hardware rather than us. */
if (hal_enable_sensor_clock)
hal_enable_sensor_clock();

// there is no platform specific i2c/spi access layer
if (!open_i2c_sensor_fd(i2c_adapter_nr))
return NULL;
Expand Down