static int wait_conversion_complete_polled(struct ak8975_data *data) { struct i2c_client *client = data->client; u8 read_status; u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT; int ret; /* Wait for the conversion to complete. */ while (timeout_ms) { msleep(AK8975_CONVERSION_DONE_POLL_TIME); ret = ak8975_read_data(client, AK8975_REG_ST1, 1, &read_status); if (ret < 0) { dev_err(&client->dev, "Error in reading ST1\n"); return ret; } if (read_status) break; timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME; } if (!timeout_ms) { dev_err(&client->dev, "Conversion timeout happened\n"); return -EINVAL; } return read_status; }
/* * Perform some start-of-day setup, including reading the asa calibration * values and caching them. */ static int ak8975_setup(struct i2c_client *client) { struct ak8975_data *data = i2c_get_clientdata(client); u8 device_id; int ret; /* Confirm that the device we're talking to is really an AK8975. */ ret = ak8975_read_data(client, AK8975_REG_WIA, 1, &device_id); if (ret < 0) { dev_err(&client->dev, "Error reading WIA\n"); return ret; } if (device_id != AK8975_DEVICE_ID) { dev_err(&client->dev, "Device ak8975 not found\n"); return -ENODEV; } /* Write the fused rom access mode. */ ret = ak8975_write_data(client, AK8975_REG_CNTL, AK8975_REG_CNTL_MODE_FUSE_ROM, AK8975_REG_CNTL_MODE_MASK, AK8975_REG_CNTL_MODE_SHIFT); if (ret < 0) { dev_err(&client->dev, "Error in setting fuse access mode\n"); return ret; } /* Get asa data and store in the device data. */ ret = ak8975_read_data(client, AK8975_REG_ASAX, 3, data->asa); if (ret < 0) { dev_err(&client->dev, "Not able to read asa data\n"); return ret; } /* Precalculate scale factor for each axis and store in the device data. */ data->raw_to_gauss[0] = ((data->asa[0] + 128) * 30) >> 8; data->raw_to_gauss[1] = ((data->asa[1] + 128) * 30) >> 8; data->raw_to_gauss[2] = ((data->asa[2] + 128) * 30) >> 8; return 0; }
bool ak8975_get_mag(AK8975_t *structure, signed short *X_Axis, signed short *Y_Axis, signed short *Z_Axis) { if(!ak8975_start_measure(structure)) return false; timer(Timeout); timer_interval(&Timeout, 11); timer_enable(&Timeout); while(!ak8975_ready(structure)) { if(timer_tick(&Timeout)) return false; } if(!ak8975_read_data(structure, X_Axis, Y_Axis, Z_Axis)) return false; return true; }
bool ak8975_display_result(AK8975_t *structure) { signed short Xg = 0; signed short Yg = 0; signed short Zg = 0; if(!ak8975_start_measure(structure)) return false; timer(Timeout); timer_interval(&Timeout, 11); timer_enable(&Timeout); while(!ak8975_ready(structure)) { if(timer_tick(&Timeout)) return false; } if(!ak8975_read_data(structure, &Xg, &Yg, &Zg)) return false; uart.printf(DebugCom, "AK8975: Magnetometer: Xg = %d, Yg = %d, Zg = %d\n\r", Xg, Yg, Zg); return true; }
/* * Emits the raw flux value for the x, y, or z axis. */ static ssize_t show_raw(struct device *dev, struct device_attribute *devattr, char *buf) { struct iio_dev *indio_dev = dev_get_drvdata(dev); struct ak8975_data *data = indio_dev->dev_data; struct i2c_client *client = data->client; struct iio_dev_attr *this_attr = to_iio_dev_attr(devattr); u16 meas_reg; s16 raw; u8 read_status; int ret; mutex_lock(&data->lock); if (data->mode == 0) { dev_err(&client->dev, "Operating mode is in power down mode\n"); ret = -EBUSY; goto exit; } /* Set up the device for taking a sample. */ ret = ak8975_write_data(client, AK8975_REG_CNTL, AK8975_REG_CNTL_MODE_ONCE, AK8975_REG_CNTL_MODE_MASK, AK8975_REG_CNTL_MODE_SHIFT); if (ret < 0) { dev_err(&client->dev, "Error in setting operating mode\n"); goto exit; } /* Wait for the conversion to complete. */ if (data->eoc_gpio) ret = wait_conversion_complete_gpio(data); else ret = wait_conversion_complete_polled(data); if (ret < 0) goto exit; read_status = ret; if (read_status & AK8975_REG_ST1_DRDY_MASK) { ret = ak8975_read_data(client, AK8975_REG_ST2, 1, &read_status); if (ret < 0) { dev_err(&client->dev, "Error in reading ST2\n"); goto exit; } if (read_status & (AK8975_REG_ST2_DERR_MASK | AK8975_REG_ST2_HOFL_MASK)) { dev_err(&client->dev, "ST2 status error 0x%x\n", read_status); ret = -EINVAL; goto exit; } } /* Read the flux value from the appropriate register (the register is specified in the iio device attributes). */ ret = ak8975_read_data(client, this_attr->address, 2, (u8 *)&meas_reg); if (ret < 0) { dev_err(&client->dev, "Read axis data fails\n"); goto exit; } mutex_unlock(&data->lock); /* Endian conversion of the measured values. */ raw = (s16) (le16_to_cpu(meas_reg)); /* Clamp to valid range. */ raw = clamp_t(s16, raw, -4096, 4095); return sprintf(buf, "%d\n", raw); exit: mutex_unlock(&data->lock); return ret; }