static int sx9500_init_chip(struct device *dev) { struct sx9500_data *data = (struct sx9500_data *) dev->driver_data; u8_t val; if (i2c_write(data->i2c_master, sx9500_reg_defaults, sizeof(sx9500_reg_defaults), data->i2c_slave_addr) < 0) { return -EIO; } /* No interrupts active. We only activate them when an * application registers a trigger. */ if (i2c_reg_write_byte(data->i2c_master, data->i2c_slave_addr, SX9500_REG_IRQ_MSK, 0) < 0) { return -EIO; } /* Read irq source reg to clear reset status. */ if (i2c_reg_read_byte(data->i2c_master, data->i2c_slave_addr, SX9500_REG_IRQ_SRC, &val) < 0) { return -EIO; } return i2c_reg_write_byte(data->i2c_master, data->i2c_slave_addr, SX9500_REG_PROX_CTRL0, 1 << CONFIG_SX9500_PROX_CHANNEL); }
static int pca9633_led_set_brightness(struct device *dev, u32_t led, u8_t value) { struct pca9633_data *data = dev->driver_data; struct led_data *dev_data = &data->dev_data; u8_t val; if (value < dev_data->min_brightness || value > dev_data->max_brightness) { return -EINVAL; } /* Set the LED brightness value */ val = (value * 255) / dev_data->max_brightness; if (i2c_reg_write_byte(data->i2c, CONFIG_PCA9633_I2C_ADDRESS, PCA9633_PWM_BASE + led, val)) { LOG_ERR("LED reg write failed"); return -EIO; } /* Set the LED driver to be controlled through its PWMx register. */ if (i2c_reg_update_byte(data->i2c, CONFIG_PCA9633_I2C_ADDRESS, PCA9633_LEDOUT, PCA9633_MASK << (led << 1), PCA9633_LED_PWM << (led << 1))) { LOG_ERR("LED reg update failed"); return -EIO; } return 0; }
static int ak8975_sample_fetch(struct device *dev, enum sensor_channel chan) { struct ak8975_data *drv_data = dev->driver_data; u8_t buf[6]; __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL); if (i2c_reg_write_byte(drv_data->i2c, CONFIG_AK8975_I2C_ADDR, AK8975_REG_CNTL, AK8975_MODE_MEASURE) < 0) { LOG_ERR("Failed to start measurement."); return -EIO; } k_busy_wait(AK8975_MEASURE_TIME_US); if (i2c_burst_read(drv_data->i2c, CONFIG_AK8975_I2C_ADDR, AK8975_REG_DATA_START, buf, 6) < 0) { LOG_ERR("Failed to read sample data."); return -EIO; } drv_data->x_sample = sys_le16_to_cpu(buf[0] | (buf[1] << 8)); drv_data->y_sample = sys_le16_to_cpu(buf[2] | (buf[3] << 8)); drv_data->z_sample = sys_le16_to_cpu(buf[4] | (buf[5] << 8)); return 0; }
int lis3dh_init(struct device *dev) { struct lis3dh_data *drv_data = dev->driver_data; int rc; drv_data->i2c = device_get_binding(CONFIG_LIS3DH_I2C_MASTER_DEV_NAME); if (drv_data->i2c == NULL) { SYS_LOG_DBG("Could not get pointer to %s device", CONFIG_LIS3DH_I2C_MASTER_DEV_NAME); return -EINVAL; } /* enable accel measurements and set power mode and data rate */ rc = i2c_reg_write_byte(drv_data->i2c, LIS3DH_I2C_ADDRESS, LIS3DH_REG_CTRL1, LIS3DH_ACCEL_EN_BITS | LIS3DH_LP_EN_BIT | LIS3DH_ODR_BITS); if (rc != 0) { SYS_LOG_DBG("Failed to configure chip."); } /* set full scale range */ rc = i2c_reg_write_byte(drv_data->i2c, LIS3DH_I2C_ADDRESS, LIS3DH_REG_CTRL4, LIS3DH_FS_BITS); if (rc != 0) { SYS_LOG_DBG("Failed to set full scale range."); return -EIO; } #ifdef CONFIG_LIS3DH_TRIGGER rc = lis3dh_init_interrupt(dev); if (rc != 0) { SYS_LOG_DBG("Failed to initialize interrupts."); return -EIO; } #endif dev->driver_api = &lis3dh_driver_api; return 0; }
int mpu6050_init_interrupt(struct device *dev) { struct mpu6050_data *drv_data = dev->driver_data; /* setup data ready gpio interrupt */ drv_data->gpio = device_get_binding(CONFIG_MPU6050_GPIO_DEV_NAME); if (drv_data->gpio == NULL) { SYS_LOG_ERR("Failed to get pointer to %s device", CONFIG_MPU6050_GPIO_DEV_NAME); return -EINVAL; } gpio_pin_configure(drv_data->gpio, CONFIG_MPU6050_GPIO_PIN_NUM, GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_INT_ACTIVE_HIGH | GPIO_INT_DEBOUNCE); gpio_init_callback(&drv_data->gpio_cb, mpu6050_gpio_callback, BIT(CONFIG_MPU6050_GPIO_PIN_NUM)); if (gpio_add_callback(drv_data->gpio, &drv_data->gpio_cb) < 0) { SYS_LOG_ERR("Failed to set gpio callback"); return -EIO; } /* enable data ready interrupt */ if (i2c_reg_write_byte(drv_data->i2c, CONFIG_MPU6050_I2C_ADDR, MPU6050_REG_INT_EN, MPU6050_DRDY_EN) < 0) { SYS_LOG_ERR("Failed to enable data ready interrupt."); return -EIO; } #if defined(CONFIG_MPU6050_TRIGGER_OWN_THREAD) k_sem_init(&drv_data->gpio_sem, 0, UINT_MAX); k_thread_create(&drv_data->thread, drv_data->thread_stack, CONFIG_MPU6050_THREAD_STACK_SIZE, (k_thread_entry_t)mpu6050_thread, dev, 0, NULL, K_PRIO_COOP(CONFIG_MPU6050_THREAD_PRIORITY), 0, 0); #elif defined(CONFIG_MPU6050_TRIGGER_GLOBAL_THREAD) drv_data->work.handler = mpu6050_work_cb; drv_data->dev = dev; #endif gpio_pin_enable_callback(drv_data->gpio, CONFIG_MPU6050_GPIO_PIN_NUM); return 0; }
int hts221_init_interrupt(struct device *dev) { struct hts221_data *drv_data = dev->driver_data; /* setup data ready gpio interrupt */ drv_data->gpio = device_get_binding(CONFIG_HTS221_GPIO_DEV_NAME); if (drv_data->gpio == NULL) { SYS_LOG_ERR("Cannot get pointer to %s device.", CONFIG_HTS221_GPIO_DEV_NAME); return -EINVAL; } gpio_pin_configure(drv_data->gpio, CONFIG_HTS221_GPIO_PIN_NUM, GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_INT_ACTIVE_HIGH | GPIO_INT_DEBOUNCE); gpio_init_callback(&drv_data->gpio_cb, hts221_gpio_callback, BIT(CONFIG_HTS221_GPIO_PIN_NUM)); if (gpio_add_callback(drv_data->gpio, &drv_data->gpio_cb) < 0) { SYS_LOG_ERR("Could not set gpio callback."); return -EIO; } /* enable data-ready interrupt */ if (i2c_reg_write_byte(drv_data->i2c, HTS221_I2C_ADDR, HTS221_REG_CTRL3, HTS221_DRDY_EN) < 0) { SYS_LOG_ERR("Could not enable data-ready interrupt."); return -EIO; } #if defined(CONFIG_HTS221_TRIGGER_OWN_THREAD) k_sem_init(&drv_data->gpio_sem, 0, UINT_MAX); k_thread_spawn(drv_data->thread_stack, CONFIG_HTS221_THREAD_STACK_SIZE, (k_thread_entry_t)hts221_thread, POINTER_TO_INT(dev), 0, NULL, K_PRIO_COOP(CONFIG_HTS221_THREAD_PRIORITY), 0, 0); #elif defined(CONFIG_HTS221_TRIGGER_GLOBAL_THREAD) drv_data->work.handler = hts221_work_cb; drv_data->dev = dev; #endif gpio_pin_enable_callback(drv_data->gpio, CONFIG_HTS221_GPIO_PIN_NUM); return 0; }
static int apds9960_ambient_setup(struct device *dev, int gain) { struct apds9960_data *data = dev->driver_data; u16_t th; /* ADC value */ if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_ATIME_REG, APDS9960_DEFAULT_ATIME)) { LOG_ERR("Default integration time not set for ADC"); return -EIO; } /* ALS Gain */ if (i2c_reg_update_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_CONTROL_REG, APDS9960_CONTROL_AGAIN, (gain & APDS9960_AGAIN_64X))) { LOG_ERR("Ambient Gain is not set"); return -EIO; } th = sys_cpu_to_le16(APDS9960_DEFAULT_AILT); if (i2c_burst_write(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_INT_AILTL_REG, (u8_t *)&th, sizeof(th))) { LOG_ERR("ALS low threshold not set"); return -EIO; } th = sys_cpu_to_le16(APDS9960_DEFAULT_AIHT); if (i2c_burst_write(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_INT_AIHTL_REG, (u8_t *)&th, sizeof(th))) { LOG_ERR("ALS low threshold not set"); return -EIO; } /* Enable ALS */ if (i2c_reg_update_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_ENABLE_REG, APDS9960_ENABLE_AEN, APDS9960_ENABLE_AEN)) { LOG_ERR("ALS is not enabled"); return -EIO; } return 0; }
static int ak8975_read_adjustment_data(struct ak8975_data *drv_data) { u8_t buf[3]; if (i2c_reg_write_byte(drv_data->i2c, CONFIG_AK8975_I2C_ADDR, AK8975_REG_CNTL, AK8975_MODE_FUSE_ACCESS) < 0) { LOG_ERR("Failed to set chip in fuse access mode."); return -EIO; } if (i2c_burst_read(drv_data->i2c, CONFIG_AK8975_I2C_ADDR, AK8975_REG_ADJ_DATA_START, buf, 3) < 0) { LOG_ERR("Failed to read adjustment data."); return -EIO; } drv_data->x_adj = buf[0]; drv_data->y_adj = buf[1]; drv_data->z_adj = buf[2]; return 0; }
static int apds9960_device_ctrl(struct device *dev, u32_t ctrl_command, void *context) { struct apds9960_data *data = dev->driver_data; if (ctrl_command == DEVICE_PM_SET_POWER_STATE) { u32_t device_pm_state = *(u32_t *)context; if (device_pm_state == DEVICE_PM_ACTIVE_STATE) { if (i2c_reg_update_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_ENABLE_REG, APDS9960_ENABLE_PON, APDS9960_ENABLE_PON)) { return -EIO; } return 0; } if (i2c_reg_update_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_ENABLE_REG, APDS9960_ENABLE_PON, 0)) { return -EIO; } if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_AICLEAR_REG, 0)) { return -EIO; } return 0; } else if (ctrl_command == DEVICE_PM_GET_POWER_STATE) { *((u32_t *)context) = DEVICE_PM_ACTIVE_STATE; } return 0; }
int bma280_attr_set(struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, const struct sensor_value *val) { struct bma280_data *drv_data = dev->driver_data; uint64_t slope_th; int rc; if (chan != SENSOR_CHAN_ACCEL_ANY) { return -ENOTSUP; } if (attr == SENSOR_ATTR_SLOPE_TH) { /* slope_th = (val * 10^6 * 2^10) / BMA280_PMU_FULL_RAGE */ slope_th = (uint64_t)val->val1 * 1000000 + (uint64_t)val->val2; slope_th = (slope_th * (1 << 10)) / BMA280_PMU_FULL_RANGE; rc = i2c_reg_write_byte(drv_data->i2c, BMA280_I2C_ADDRESS, BMA280_REG_SLOPE_TH, (uint8_t)slope_th); if (rc != 0) { SYS_LOG_DBG("Could not set slope threshold"); return -EIO; } } else if (attr == SENSOR_ATTR_SLOPE_DUR) { rc = i2c_reg_update_byte(drv_data->i2c, BMA280_I2C_ADDRESS, BMA280_REG_INT_5, BMA280_SLOPE_DUR_MASK, val->val1 << BMA280_SLOPE_DUR_SHIFT); if (rc != 0) { SYS_LOG_DBG("Could not set slope duration"); return -EIO; } } else { return -ENOTSUP; } return 0; }
static int fxos8700_init(struct device *dev) { const struct fxos8700_config *config = dev->config->config_info; struct fxos8700_data *data = dev->driver_data; struct sensor_value odr = {.val1 = 6, .val2 = 250000}; /* Get the I2C device */ data->i2c = device_get_binding(config->i2c_name); if (data->i2c == NULL) { LOG_ERR("Could not find I2C device"); return -EINVAL; } /* * Read the WHOAMI register to make sure we are talking to FXOS8700 or * compatible device and not some other type of device that happens to * have the same I2C address. */ if (i2c_reg_read_byte(data->i2c, config->i2c_address, FXOS8700_REG_WHOAMI, &data->whoami)) { LOG_ERR("Could not get WHOAMI value"); return -EIO; } switch (data->whoami) { case WHOAMI_ID_MMA8451: case WHOAMI_ID_MMA8652: case WHOAMI_ID_MMA8653: if (config->mode != FXOS8700_MODE_ACCEL) { LOG_ERR("Device 0x%x supports only " "accelerometer mode", data->whoami); return -EIO; } case WHOAMI_ID_FXOS8700: LOG_DBG("Device ID 0x%x", data->whoami); break; default: LOG_ERR("Unknown Device ID 0x%x", data->whoami); return -EIO; } /* Reset the sensor. Upon issuing a software reset command over the I2C * interface, the sensor immediately resets and does not send any * acknowledgment (ACK) of the written byte to the master. Therefore, * do not check the return code of the I2C transaction. */ i2c_reg_write_byte(data->i2c, config->i2c_address, FXOS8700_REG_CTRLREG2, FXOS8700_CTRLREG2_RST_MASK); /* The sensor requires us to wait 1 ms after a software reset before * attempting further communications. */ k_busy_wait(USEC_PER_MSEC); if (fxos8700_set_odr(dev, &odr)) { LOG_ERR("Could not set default data rate"); return -EIO; } if (i2c_reg_update_byte(data->i2c, config->i2c_address, FXOS8700_REG_CTRLREG2, FXOS8700_CTRLREG2_MODS_MASK, config->power_mode)) { LOG_ERR("Could not set power scheme"); return -EIO; } /* Set the mode (accel-only, mag-only, or hybrid) */ if (i2c_reg_update_byte(data->i2c, config->i2c_address, FXOS8700_REG_M_CTRLREG1, FXOS8700_M_CTRLREG1_MODE_MASK, config->mode)) { LOG_ERR("Could not set mode"); return -EIO; } /* Set hybrid autoincrement so we can read accel and mag channels in * one I2C transaction. */ if (i2c_reg_update_byte(data->i2c, config->i2c_address, FXOS8700_REG_M_CTRLREG2, FXOS8700_M_CTRLREG2_AUTOINC_MASK, FXOS8700_M_CTRLREG2_AUTOINC_MASK)) { LOG_ERR("Could not set hybrid autoincrement"); return -EIO; } /* Set the full-scale range */ if (i2c_reg_update_byte(data->i2c, config->i2c_address, FXOS8700_REG_XYZ_DATA_CFG, FXOS8700_XYZ_DATA_CFG_FS_MASK, config->range)) { LOG_ERR("Could not set range"); return -EIO; } k_sem_init(&data->sem, 0, UINT_MAX); #if CONFIG_FXOS8700_TRIGGER if (fxos8700_trigger_init(dev)) { LOG_ERR("Could not initialize interrupts"); return -EIO; } #endif /* Set active */ if (fxos8700_set_power(dev, FXOS8700_POWER_ACTIVE)) { LOG_ERR("Could not set active"); return -EIO; } k_sem_give(&data->sem); LOG_DBG("Init complete"); return 0; } static const struct sensor_driver_api fxos8700_driver_api = { .sample_fetch = fxos8700_sample_fetch, .channel_get = fxos8700_channel_get, .attr_set = fxos8700_attr_set, #if CONFIG_FXOS8700_TRIGGER .trigger_set = fxos8700_trigger_set, #endif }; static const struct fxos8700_config fxos8700_config = { .i2c_name = CONFIG_FXOS8700_I2C_NAME, .i2c_address = CONFIG_FXOS8700_I2C_ADDRESS, #ifdef CONFIG_FXOS8700_MODE_ACCEL .mode = FXOS8700_MODE_ACCEL, .start_addr = FXOS8700_REG_OUTXMSB, .start_channel = FXOS8700_CHANNEL_ACCEL_X, .num_channels = FXOS8700_NUM_ACCEL_CHANNELS, #elif CONFIG_FXOS8700_MODE_MAGN .mode = FXOS8700_MODE_MAGN, .start_addr = FXOS8700_REG_M_OUTXMSB, .start_channel = FXOS8700_CHANNEL_MAGN_X, .num_channels = FXOS8700_NUM_MAG_CHANNELS, #else .mode = FXOS8700_MODE_HYBRID, .start_addr = FXOS8700_REG_OUTXMSB, .start_channel = FXOS8700_CHANNEL_ACCEL_X, .num_channels = FXOS8700_NUM_HYBRID_CHANNELS, #endif #if CONFIG_FXOS8700_PM_NORMAL .power_mode = FXOS8700_PM_NORMAL, #elif CONFIG_FXOS8700_PM_LOW_NOISE_LOW_POWER .power_mode = FXOS8700_PM_LOW_NOISE_LOW_POWER, #elif CONFIG_FXOS8700_PM_HIGH_RESOLUTION .power_mode = FXOS8700_PM_HIGH_RESOLUTION, #else .power_mode = FXOS8700_PM_LOW_POWER, #endif #if CONFIG_FXOS8700_RANGE_8G .range = FXOS8700_RANGE_8G, #elif CONFIG_FXOS8700_RANGE_4G .range = FXOS8700_RANGE_4G, #else .range = FXOS8700_RANGE_2G, #endif #ifdef CONFIG_FXOS8700_TRIGGER .gpio_name = CONFIG_FXOS8700_GPIO_NAME, .gpio_pin = CONFIG_FXOS8700_GPIO_PIN, #endif #ifdef CONFIG_FXOS8700_PULSE .pulse_cfg = CONFIG_FXOS8700_PULSE_CFG, .pulse_ths[0] = CONFIG_FXOS8700_PULSE_THSX, .pulse_ths[1] = CONFIG_FXOS8700_PULSE_THSY, .pulse_ths[2] = CONFIG_FXOS8700_PULSE_THSZ, .pulse_tmlt = CONFIG_FXOS8700_PULSE_TMLT, .pulse_ltcy = CONFIG_FXOS8700_PULSE_LTCY, .pulse_wind = CONFIG_FXOS8700_PULSE_WIND, #endif }; static struct fxos8700_data fxos8700_data; DEVICE_AND_API_INIT(fxos8700, CONFIG_FXOS8700_NAME, fxos8700_init, &fxos8700_data, &fxos8700_config, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &fxos8700_driver_api);
static int adt7420_temp_reg_write(struct device *dev, u8_t reg, s16_t val) { struct adt7420_data *drv_data = dev->driver_data; const struct adt7420_dev_config *cfg = dev->config->config_info; u8_t buf[3] = {reg, val >> 8, val & 0xFF}; return i2c_write(drv_data->i2c, buf, sizeof(buf), cfg->i2c_addr); } static int adt7420_attr_set(struct device *dev, enum sensor_channel chan, enum sensor_attribute attr, const struct sensor_value *val) { struct adt7420_data *drv_data = dev->driver_data; const struct adt7420_dev_config *cfg = dev->config->config_info; u8_t val8, reg = 0; u16_t rate; s64_t value; if (chan != SENSOR_CHAN_AMBIENT_TEMP) { return -ENOTSUP; } switch (attr) { case SENSOR_ATTR_SAMPLING_FREQUENCY: rate = val->val1 * 1000 + val->val2 / 1000; /* rate in mHz */ switch (rate) { case 240: val8 = ADT7420_OP_MODE_CONT_CONV; break; case 1000: val8 = ADT7420_OP_MODE_1_SPS; break; default: return -EINVAL; } if (i2c_reg_update_byte(drv_data->i2c, cfg->i2c_addr, ADT7420_REG_CONFIG, ADT7420_CONFIG_OP_MODE(~0), ADT7420_CONFIG_OP_MODE(val8)) < 0) { LOG_DBG("Failed to set attribute!"); return -EIO; } return 0; case SENSOR_ATTR_UPPER_THRESH: reg = ADT7420_REG_T_HIGH_MSB; /* Fallthrough */ case SENSOR_ATTR_LOWER_THRESH: if (!reg) { reg = ADT7420_REG_T_LOW_MSB; } if ((val->val1 > 150) || (val->val1 < -40)) { return -EINVAL; } value = (s64_t)val->val1 * 1000000 + val->val2; value = (value / ADT7420_TEMP_SCALE) << 1; if (adt7420_temp_reg_write(dev, reg, value) < 0) { LOG_DBG("Failed to set attribute!"); return -EIO; } return 0; default: return -ENOTSUP; } return 0; } static int adt7420_sample_fetch(struct device *dev, enum sensor_channel chan) { struct adt7420_data *drv_data = dev->driver_data; s16_t value; __ASSERT_NO_MSG(chan == SENSOR_CHAN_ALL || chan == SENSOR_CHAN_AMBIENT_TEMP); if (adt7420_temp_reg_read(dev, ADT7420_REG_TEMP_MSB, &value) < 0) { return -EIO; } drv_data->sample = value >> 1; /* use 15-bit only */ return 0; } static int adt7420_channel_get(struct device *dev, enum sensor_channel chan, struct sensor_value *val) { struct adt7420_data *drv_data = dev->driver_data; s32_t value; if (chan != SENSOR_CHAN_AMBIENT_TEMP) { return -ENOTSUP; } value = (s32_t)drv_data->sample * ADT7420_TEMP_SCALE; val->val1 = value / 1000000; val->val2 = value % 1000000; return 0; } static const struct sensor_driver_api adt7420_driver_api = { .attr_set = adt7420_attr_set, .sample_fetch = adt7420_sample_fetch, .channel_get = adt7420_channel_get, #ifdef CONFIG_ADT7420_TRIGGER .trigger_set = adt7420_trigger_set, #endif }; static int adt7420_probe(struct device *dev) { struct adt7420_data *drv_data = dev->driver_data; const struct adt7420_dev_config *cfg = dev->config->config_info; u8_t value; int ret; ret = i2c_reg_read_byte(drv_data->i2c, cfg->i2c_addr, ADT7420_REG_ID, &value); if (ret) { return ret; } if (value != ADT7420_DEFAULT_ID) return -ENODEV; ret = i2c_reg_write_byte(drv_data->i2c, cfg->i2c_addr, ADT7420_REG_CONFIG, ADT7420_CONFIG_RESOLUTION | ADT7420_CONFIG_OP_MODE(ADT7420_OP_MODE_CONT_CONV)); if (ret) { return ret; } ret = i2c_reg_write_byte(drv_data->i2c, cfg->i2c_addr, ADT7420_REG_HIST, CONFIG_ADT7420_TEMP_HYST); if (ret) { return ret; } ret = adt7420_temp_reg_write(dev, ADT7420_REG_T_CRIT_MSB, (CONFIG_ADT7420_TEMP_CRIT * 1000000 / ADT7420_TEMP_SCALE) << 1); if (ret) { return ret; } #ifdef CONFIG_ADT7420_TRIGGER if (adt7420_init_interrupt(dev) < 0) { LOG_ERR("Failed to initialize interrupt!"); return -EIO; } #endif return 0; } static int adt7420_init(struct device *dev) { struct adt7420_data *drv_data = dev->driver_data; const struct adt7420_dev_config *cfg = dev->config->config_info; drv_data->i2c = device_get_binding(cfg->i2c_port); if (drv_data->i2c == NULL) { LOG_DBG("Failed to get pointer to %s device!", cfg->i2c_port); return -EINVAL; } return adt7420_probe(dev); } static struct adt7420_data adt7420_driver; static const struct adt7420_dev_config adt7420_config = { .i2c_port = CONFIG_ADT7420_I2C_MASTER_DEV_NAME, .i2c_addr = CONFIG_ADT7420_I2C_ADDR, #ifdef CONFIG_ADT7420_TRIGGER .gpio_port = CONFIG_ADT7420_GPIO_DEV_NAME, .int_gpio = CONFIG_ADT7420_GPIO_PIN_NUM, #endif }; DEVICE_AND_API_INIT(adt7420, CONFIG_ADT7420_NAME, adt7420_init, &adt7420_driver, &adt7420_config, POST_KERNEL, CONFIG_SENSOR_INIT_PRIORITY, &adt7420_driver_api);
static int fxas21002_init(struct device *dev) { const struct fxas21002_config *config = dev->config->config_info; struct fxas21002_data *data = dev->driver_data; u32_t transition_time; u8_t whoami; u8_t ctrlreg1; /* Get the I2C device */ data->i2c = device_get_binding(config->i2c_name); if (data->i2c == NULL) { SYS_LOG_ERR("Could not find I2C device"); return -EINVAL; } /* Read the WHOAMI register to make sure we are talking to FXAS21002 * and not some other type of device that happens to have the same I2C * address. */ if (i2c_reg_read_byte(data->i2c, config->i2c_address, FXAS21002_REG_WHOAMI, &whoami)) { SYS_LOG_ERR("Could not get WHOAMI value"); return -EIO; } if (whoami != config->whoami) { SYS_LOG_ERR("WHOAMI value received 0x%x, expected 0x%x", whoami, config->whoami); return -EIO; } /* Reset the sensor. Upon issuing a software reset command over the I2C * interface, the sensor immediately resets and does not send any * acknowledgment (ACK) of the written byte to the master. Therefore, * do not check the return code of the I2C transaction. */ i2c_reg_write_byte(data->i2c, config->i2c_address, FXAS21002_REG_CTRLREG1, FXAS21002_CTRLREG1_RST_MASK); /* Wait for the reset sequence to complete */ do { if (i2c_reg_read_byte(data->i2c, config->i2c_address, FXAS21002_REG_CTRLREG1, &ctrlreg1)) { SYS_LOG_ERR("Could not get ctrlreg1 value"); return -EIO; } } while (ctrlreg1 & FXAS21002_CTRLREG1_RST_MASK); /* Set the full-scale range */ if (i2c_reg_update_byte(data->i2c, config->i2c_address, FXAS21002_REG_CTRLREG0, FXAS21002_CTRLREG0_FS_MASK, config->range)) { SYS_LOG_ERR("Could not set range"); return -EIO; } /* Set the output data rate */ if (i2c_reg_update_byte(data->i2c, config->i2c_address, FXAS21002_REG_CTRLREG1, FXAS21002_CTRLREG1_DR_MASK, config->dr << FXAS21002_CTRLREG1_DR_SHIFT)) { SYS_LOG_ERR("Could not set output data rate"); return -EIO; } k_sem_init(&data->sem, 0, UINT_MAX); #if CONFIG_FXAS21002_TRIGGER if (fxas21002_trigger_init(dev)) { SYS_LOG_ERR("Could not initialize interrupts"); return -EIO; } #endif /* Set active */ if (fxas21002_set_power(dev, FXAS21002_POWER_ACTIVE)) { SYS_LOG_ERR("Could not set active"); return -EIO; } /* Wait the transition time from standby to active mode */ transition_time = fxas21002_get_transition_time(FXAS21002_POWER_STANDBY, FXAS21002_POWER_ACTIVE, config->dr); k_busy_wait(transition_time); k_sem_give(&data->sem); SYS_LOG_DBG("Init complete"); return 0; }
static int pca9633_led_blink(struct device *dev, u32_t led, u32_t delay_on, u32_t delay_off) { struct pca9633_data *data = dev->driver_data; struct led_data *dev_data = &data->dev_data; u8_t gdc, gfrq; u32_t period; period = delay_on + delay_off; if (period < dev_data->min_period || period > dev_data->max_period) { return -EINVAL; } /* * From manual: * duty cycle = (GDC / 256) -> * (time_on / period) = (GDC / 256) -> * GDC = ((time_on * 256) / period) */ gdc = delay_on * 256 / period; if (i2c_reg_write_byte(data->i2c, CONFIG_PCA9633_I2C_ADDRESS, PCA9633_GRPPWM, gdc)) { LOG_ERR("LED reg write failed"); return -EIO; } /* * From manual: * period = ((GFRQ + 1) / 24) in seconds. * So, period (in ms) = (((GFRQ + 1) / 24) * 1000) -> * GFRQ = ((period * 24 / 1000) - 1) */ gfrq = (period * 24 / 1000) - 1; if (i2c_reg_write_byte(data->i2c, CONFIG_PCA9633_I2C_ADDRESS, PCA9633_GRPFREQ, gfrq)) { LOG_ERR("LED reg write failed"); return -EIO; } /* Enable blinking mode */ if (i2c_reg_update_byte(data->i2c, CONFIG_PCA9633_I2C_ADDRESS, PCA9633_MODE2, PCA9633_MODE2_DMBLNK, PCA9633_MODE2_DMBLNK)) { LOG_ERR("LED reg update failed"); return -EIO; } /* Select the GRPPWM source to drive the LED outpout */ if (i2c_reg_update_byte(data->i2c, CONFIG_PCA9633_I2C_ADDRESS, PCA9633_LEDOUT, PCA9633_MASK << (led << 1), PCA9633_LED_GRP_PWM << (led << 1))) { LOG_ERR("LED reg update failed"); return -EIO; } return 0; }
static int apds9960_sample_fetch(struct device *dev, enum sensor_channel chan) { struct apds9960_data *data = dev->driver_data; u8_t status; if (chan != SENSOR_CHAN_ALL) { LOG_ERR("Unsupported sensor channel"); return -ENOTSUP; } #ifndef CONFIG_APDS9960_TRIGGER gpio_pin_enable_callback(data->gpio, DT_AVAGO_APDS9960_0_INT_GPIOS_PIN); if (i2c_reg_update_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_ENABLE_REG, APDS9960_ENABLE_PON | APDS9960_ENABLE_AIEN, APDS9960_ENABLE_PON | APDS9960_ENABLE_AIEN)) { LOG_ERR("Power on bit not set."); return -EIO; } k_sem_take(&data->data_sem, K_FOREVER); #endif if (i2c_reg_read_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_STATUS_REG, &status)) { return -EIO; } LOG_DBG("status: 0x%x", status); if (status & APDS9960_STATUS_PINT) { if (i2c_reg_read_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_PDATA_REG, &data->pdata)) { return -EIO; } } if (status & APDS9960_STATUS_AINT) { if (i2c_burst_read(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_CDATAL_REG, (u8_t *)&data->sample_crgb, sizeof(data->sample_crgb))) { return -EIO; } } #ifndef CONFIG_APDS9960_TRIGGER if (i2c_reg_update_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_ENABLE_REG, APDS9960_ENABLE_PON, 0)) { return -EIO; } #endif if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_AICLEAR_REG, 0)) { return -EIO; } return 0; }
static int apds9960_sensor_setup(struct device *dev) { struct apds9960_data *data = dev->driver_data; u8_t chip_id; if (i2c_reg_read_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_ID_REG, &chip_id)) { LOG_ERR("Failed reading chip id"); return -EIO; } if (!((chip_id == APDS9960_ID_1) || (chip_id == APDS9960_ID_2))) { LOG_ERR("Invalid chip id 0x%x", chip_id); return -EIO; } /* Disable all functions and interrupts */ if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_ENABLE_REG, 0)) { LOG_ERR("ENABLE register is not cleared"); return -EIO; } if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_AICLEAR_REG, 0)) { return -EIO; } /* Disable gesture interrupt */ if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_GCONFIG4_REG, 0)) { LOG_ERR("GCONFIG4 register is not cleared"); return -EIO; } if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_WTIME_REG, APDS9960_DEFAULT_WTIME)) { LOG_ERR("Default wait time not set"); return -EIO; } if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_CONFIG1_REG, APDS9960_DEFAULT_CONFIG1)) { LOG_ERR("Default WLONG not set"); return -EIO; } if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_CONFIG2_REG, APDS9960_DEFAULT_CONFIG2)) { LOG_ERR("Configuration Register Two not set"); return -EIO; } if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_CONFIG3_REG, APDS9960_DEFAULT_CONFIG3)) { LOG_ERR("Configuration Register Three not set"); return -EIO; } if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_PERS_REG, APDS9960_DEFAULT_PERS)) { LOG_ERR("Interrupt persistence not set"); return -EIO; } if (apds9960_proxy_setup(dev, APDS9960_DEFAULT_PGAIN)) { LOG_ERR("Failed to setup proximity functionality"); return -EIO; } if (apds9960_ambient_setup(dev, APDS9960_DEFAULT_AGAIN)) { LOG_ERR("Failed to setup ambient light functionality"); return -EIO; } return 0; }
static int apds9960_proxy_setup(struct device *dev, int gain) { struct apds9960_data *data = dev->driver_data; if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_POFFSET_UR_REG, APDS9960_DEFAULT_POFFSET_UR)) { LOG_ERR("Default offset UR not set "); return -EIO; } if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_POFFSET_DL_REG, APDS9960_DEFAULT_POFFSET_DL)) { LOG_ERR("Default offset DL not set "); return -EIO; } if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_PPULSE_REG, APDS9960_DEFAULT_PROX_PPULSE)) { LOG_ERR("Default pulse count not set "); return -EIO; } if (i2c_reg_update_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_CONTROL_REG, APDS9960_CONTROL_LDRIVE, APDS9960_DEFAULT_LDRIVE)) { LOG_ERR("LED Drive Strength not set"); return -EIO; } if (i2c_reg_update_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_CONTROL_REG, APDS9960_CONTROL_PGAIN, (gain & APDS9960_PGAIN_8X))) { LOG_ERR("Gain is not set"); return -EIO; } if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_PILT_REG, APDS9960_DEFAULT_PILT)) { LOG_ERR("Low threshold not set"); return -EIO; } if (i2c_reg_write_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_PIHT_REG, APDS9960_DEFAULT_PIHT)) { LOG_ERR("High threshold not set"); return -EIO; } if (i2c_reg_update_byte(data->i2c, APDS9960_I2C_ADDRESS, APDS9960_ENABLE_REG, APDS9960_ENABLE_PEN, APDS9960_ENABLE_PEN)) { LOG_ERR("Proximity mode is not enabled"); return -EIO; } return 0; }
int bma280_init_interrupt(struct device *dev) { struct bma280_data *drv_data = dev->driver_data; int rc; /* set latched interrupts */ rc = i2c_reg_write_byte(drv_data->i2c, BMA280_I2C_ADDRESS, BMA280_REG_INT_RST_LATCH, BMA280_BIT_INT_LATCH_RESET | BMA280_INT_MODE_LATCH); if (rc != 0) { SYS_LOG_DBG("Could not set latched interrupts"); return -EIO; } /* setup data ready gpio interrupt */ drv_data->gpio = device_get_binding(CONFIG_BMA280_GPIO_DEV_NAME); if (drv_data->gpio == NULL) { SYS_LOG_DBG("Cannot get pointer to %s device", CONFIG_BMA280_GPIO_DEV_NAME); return -EINVAL; } gpio_pin_configure(drv_data->gpio, CONFIG_BMA280_GPIO_PIN_NUM, GPIO_DIR_IN | GPIO_INT | GPIO_INT_LEVEL | GPIO_INT_ACTIVE_HIGH | GPIO_INT_DEBOUNCE); gpio_init_callback(&drv_data->gpio_cb, bma280_gpio_callback, BIT(CONFIG_BMA280_GPIO_PIN_NUM)); rc = gpio_add_callback(drv_data->gpio, &drv_data->gpio_cb); if (rc != 0) { SYS_LOG_DBG("Could not set gpio callback"); return -EIO; } /* map data ready interrupt to INT1 */ rc = i2c_reg_update_byte(drv_data->i2c, BMA280_I2C_ADDRESS, BMA280_REG_INT_MAP_1, BMA280_INT_MAP_1_BIT_DATA, BMA280_INT_MAP_1_BIT_DATA); if (rc != 0) { SYS_LOG_DBG("Could not map data ready interrupt pin"); return -EIO; } /* map any-motion interrupt to INT1 */ rc = i2c_reg_update_byte(drv_data->i2c, BMA280_I2C_ADDRESS, BMA280_REG_INT_MAP_0, BMA280_INT_MAP_0_BIT_SLOPE, BMA280_INT_MAP_0_BIT_SLOPE); if (rc != 0) { SYS_LOG_DBG("Could not map any-motion interrupt pin"); return -EIO; } /* disable data ready interrupt */ rc = i2c_reg_update_byte(drv_data->i2c, BMA280_I2C_ADDRESS, BMA280_REG_INT_EN_1, BMA280_BIT_DATA_EN, 0); if (rc != 0) { SYS_LOG_DBG("Could not disable data ready interrupt"); return -EIO; } /* disable any-motion interrupt */ rc = i2c_reg_update_byte(drv_data->i2c, BMA280_I2C_ADDRESS, BMA280_REG_INT_EN_0, BMA280_SLOPE_EN_XYZ, 0); if (rc != 0) { SYS_LOG_DBG("Could not disable data ready interrupt"); return -EIO; } #if defined(CONFIG_BMA280_TRIGGER_OWN_FIBER) nano_sem_init(&drv_data->gpio_sem); fiber_start(drv_data->fiber_stack, CONFIG_BMA280_FIBER_STACK_SIZE, (nano_fiber_entry_t)bma280_fiber, POINTER_TO_INT(dev), 0, CONFIG_BMA280_FIBER_PRIORITY, 0); #elif defined(CONFIG_BMA280_TRIGGER_GLOBAL_FIBER) drv_data->work.handler = bma280_fiber_cb; drv_data->work.arg = dev; #endif gpio_pin_enable_callback(drv_data->gpio, CONFIG_BMA280_GPIO_PIN_NUM); return 0; }
int mpu6050_init(struct device *dev) { struct mpu6050_data *drv_data = dev->driver_data; u8_t id, i; drv_data->i2c = device_get_binding(CONFIG_MPU6050_I2C_MASTER_DEV_NAME); if (drv_data->i2c == NULL) { SYS_LOG_ERR("Failed to get pointer to %s device", CONFIG_MPU6050_I2C_MASTER_DEV_NAME); return -EINVAL; } /* check chip ID */ if (i2c_reg_read_byte(drv_data->i2c, CONFIG_MPU6050_I2C_ADDR, MPU6050_REG_CHIP_ID, &id) < 0) { SYS_LOG_ERR("Failed to read chip ID."); return -EIO; } if (id != MPU6050_CHIP_ID) { SYS_LOG_ERR("Invalid chip ID."); return -EINVAL; } /* wake up chip */ if (i2c_reg_update_byte(drv_data->i2c, CONFIG_MPU6050_I2C_ADDR, MPU6050_REG_PWR_MGMT1, MPU6050_SLEEP_EN, 0) < 0) { SYS_LOG_ERR("Failed to wake up chip."); return -EIO; } /* set accelerometer full-scale range */ for (i = 0; i < 4; i++) { if (BIT(i+1) == CONFIG_MPU6050_ACCEL_FS) { break; } } if (i == 4) { SYS_LOG_ERR("Invalid value for accel full-scale range."); return -EINVAL; } if (i2c_reg_write_byte(drv_data->i2c, CONFIG_MPU6050_I2C_ADDR, MPU6050_REG_ACCEL_CFG, i << MPU6050_ACCEL_FS_SHIFT) < 0) { SYS_LOG_ERR("Failed to write accel full-scale range."); return -EIO; } drv_data->accel_sensitivity_shift = 14 - i; /* set gyroscope full-scale range */ for (i = 0; i < 4; i++) { if (BIT(i) * 250 == CONFIG_MPU6050_GYRO_FS) { break; } } if (i == 4) { SYS_LOG_ERR("Invalid value for gyro full-scale range."); return -EINVAL; } if (i2c_reg_write_byte(drv_data->i2c, CONFIG_MPU6050_I2C_ADDR, MPU6050_REG_GYRO_CFG, i << MPU6050_GYRO_FS_SHIFT) < 0) { SYS_LOG_ERR("Failed to write gyro full-scale range."); return -EIO; } drv_data->gyro_sensitivity_x10 = mpu6050_gyro_sensitivity_x10[i]; #ifdef CONFIG_MPU6050_TRIGGER if (mpu6050_init_interrupt(dev) < 0) { SYS_LOG_DBG("Failed to initialize interrupts."); return -EIO; } #endif return 0; }
static int fxos8700_init(struct device *dev) { const struct fxos8700_config *config = dev->config->config_info; struct fxos8700_data *data = dev->driver_data; u8_t whoami; /* Get the I2C device */ data->i2c = device_get_binding(config->i2c_name); if (data->i2c == NULL) { SYS_LOG_ERR("Could not find I2C device"); return -EINVAL; } /* Read the WHOAMI register to make sure we are talking to FXOS8700 and * not some other type of device that happens to have the same I2C * address. */ if (i2c_reg_read_byte(data->i2c, config->i2c_address, FXOS8700_REG_WHOAMI, &whoami)) { SYS_LOG_ERR("Could not get WHOAMI value"); return -EIO; } if (whoami != config->whoami) { SYS_LOG_ERR("WHOAMI value received 0x%x, expected 0x%x", whoami, FXOS8700_REG_WHOAMI); return -EIO; } /* Reset the sensor. Upon issuing a software reset command over the I2C * interface, the sensor immediately resets and does not send any * acknowledgment (ACK) of the written byte to the master. Therefore, * do not check the return code of the I2C transaction. */ i2c_reg_write_byte(data->i2c, config->i2c_address, FXOS8700_REG_CTRLREG2, FXOS8700_CTRLREG2_RST_MASK); /* The sensor requires us to wait 1 ms after a software reset before * attempting further communications. */ k_busy_wait(USEC_PER_MSEC); /* Set the mode (accel-only, mag-only, or hybrid) */ if (i2c_reg_update_byte(data->i2c, config->i2c_address, FXOS8700_REG_M_CTRLREG1, FXOS8700_M_CTRLREG1_MODE_MASK, config->mode)) { SYS_LOG_ERR("Could not set mode"); return -EIO; } /* Set hybrid autoincrement so we can read accel and mag channels in * one I2C transaction. */ if (i2c_reg_update_byte(data->i2c, config->i2c_address, FXOS8700_REG_M_CTRLREG2, FXOS8700_M_CTRLREG2_AUTOINC_MASK, FXOS8700_M_CTRLREG2_AUTOINC_MASK)) { SYS_LOG_ERR("Could not set hybrid autoincrement"); return -EIO; } /* Set the full-scale range */ if (i2c_reg_update_byte(data->i2c, config->i2c_address, FXOS8700_REG_XYZ_DATA_CFG, FXOS8700_XYZ_DATA_CFG_FS_MASK, config->range)) { SYS_LOG_ERR("Could not set range"); return -EIO; } #if CONFIG_FXOS8700_TRIGGER if (fxos8700_trigger_init(dev)) { SYS_LOG_ERR("Could not initialize interrupts"); return -EIO; } #endif /* Set active */ if (fxos8700_set_power(dev, FXOS8700_POWER_ACTIVE)) { SYS_LOG_ERR("Could not set active"); return -EIO; } k_sem_init(&data->sem, 1, UINT_MAX); SYS_LOG_DBG("Init complete"); return 0; }