aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGwendal Grignou <gwendal@chromium.org>2014-11-21 13:45:48 -0500
committerJonathan Cameron <jic23@kernel.org>2014-12-12 07:25:14 -0500
commit286f74c2533ac44419819bb3c885ab9f6291d2c3 (patch)
tree182e483d9a23e7ff057a4a914052e749ce40d4f4
parent71222bf5412c78d96bf73d09475d3077ce0789f8 (diff)
iio: ak8975: add definition structure per compass type
For each type of compass supported (AK8975 and AK8963), add a definition structure for register masks, important registers, raw data interpretation. This change will make integrating new type of devices easier. Remove i2c register cache. It is only used for one single register. Signed-off-by: Gwendal Grignou <gwendal@chromium.org> Signed-off-by: Jonathan Cameron <jic23@kernel.org>
-rw-r--r--drivers/iio/magnetometer/ak8975.c281
1 files changed, 186 insertions, 95 deletions
diff --git a/drivers/iio/magnetometer/ak8975.c b/drivers/iio/magnetometer/ak8975.c
index 4e69480e67b5..0f86a8e72034 100644
--- a/drivers/iio/magnetometer/ak8975.c
+++ b/drivers/iio/magnetometer/ak8975.c
@@ -86,13 +86,155 @@
86#define AK8975_MAX_CONVERSION_TIMEOUT 500 86#define AK8975_MAX_CONVERSION_TIMEOUT 500
87#define AK8975_CONVERSION_DONE_POLL_TIME 10 87#define AK8975_CONVERSION_DONE_POLL_TIME 10
88#define AK8975_DATA_READY_TIMEOUT ((100*HZ)/1000) 88#define AK8975_DATA_READY_TIMEOUT ((100*HZ)/1000)
89#define RAW_TO_GAUSS_8975(asa) ((((asa) + 128) * 3000) / 256) 89
90#define RAW_TO_GAUSS_8963(asa) ((((asa) + 128) * 6000) / 256) 90/*
91 * Precalculate scale factor (in Gauss units) for each axis and
92 * store in the device data.
93 *
94 * This scale factor is axis-dependent, and is derived from 3 calibration
95 * factors ASA(x), ASA(y), and ASA(z).
96 *
97 * These ASA values are read from the sensor device at start of day, and
98 * cached in the device context struct.
99 *
100 * Adjusting the flux value with the sensitivity adjustment value should be
101 * done via the following formula:
102 *
103 * Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 )
104 * where H is the raw value, ASA is the sensitivity adjustment, and Hadj
105 * is the resultant adjusted value.
106 *
107 * We reduce the formula to:
108 *
109 * Hadj = H * (ASA + 128) / 256
110 *
111 * H is in the range of -4096 to 4095. The magnetometer has a range of
112 * +-1229uT. To go from the raw value to uT is:
113 *
114 * HuT = H * 1229/4096, or roughly, 3/10.
115 *
116 * Since 1uT = 0.01 gauss, our final scale factor becomes:
117 *
118 * Hadj = H * ((ASA + 128) / 256) * 3/10 * 1/100
119 * Hadj = H * ((ASA + 128) * 0.003) / 256
120 *
121 * Since ASA doesn't change, we cache the resultant scale factor into the
122 * device context in ak8975_setup().
123 *
124 * Given we use IIO_VAL_INT_PLUS_MICRO bit when displaying the scale, we
125 * multiply the stored scale value by 1e6.
126 */
127static long ak8975_raw_to_gauss(u16 data)
128{
129 return (((long)data + 128) * 3000) / 256;
130}
131
132/*
133 * For AK8963, same calculation, but the device is less sensitive:
134 *
135 * H is in the range of +-8190. The magnetometer has a range of
136 * +-4912uT. To go from the raw value to uT is:
137 *
138 * HuT = H * 4912/8190, or roughly, 6/10, instead of 3/10.
139 */
140static long ak8963_raw_to_gauss(u16 data)
141{
142 return (((long)data + 128) * 6000) / 256;
143}
91 144
92/* Compatible Asahi Kasei Compass parts */ 145/* Compatible Asahi Kasei Compass parts */
93enum asahi_compass_chipset { 146enum asahi_compass_chipset {
94 AK8975, 147 AK8975,
95 AK8963, 148 AK8963,
149 AK_MAX_TYPE
150};
151
152enum ak_ctrl_reg_addr {
153 ST1,
154 ST2,
155 CNTL,
156 ASA_BASE,
157 MAX_REGS,
158 REGS_END,
159};
160
161enum ak_ctrl_reg_mask {
162 ST1_DRDY,
163 ST2_HOFL,
164 ST2_DERR,
165 CNTL_MODE,
166 MASK_END,
167};
168
169enum ak_ctrl_mode {
170 POWER_DOWN,
171 MODE_ONCE,
172 SELF_TEST,
173 FUSE_ROM,
174 MODE_END,
175};
176
177struct ak_def {
178 enum asahi_compass_chipset type;
179 long (*raw_to_gauss)(u16 data);
180 u16 range;
181 u8 ctrl_regs[REGS_END];
182 u8 ctrl_masks[MASK_END];
183 u8 ctrl_modes[MODE_END];
184 u8 data_regs[3];
185};
186
187static struct ak_def ak_def_array[AK_MAX_TYPE] = {
188 {
189 .type = AK8975,
190 .raw_to_gauss = ak8975_raw_to_gauss,
191 .range = 4096,
192 .ctrl_regs = {
193 AK8975_REG_ST1,
194 AK8975_REG_ST2,
195 AK8975_REG_CNTL,
196 AK8975_REG_ASAX,
197 AK8975_MAX_REGS},
198 .ctrl_masks = {
199 AK8975_REG_ST1_DRDY_MASK,
200 AK8975_REG_ST2_HOFL_MASK,
201 AK8975_REG_ST2_DERR_MASK,
202 AK8975_REG_CNTL_MODE_MASK},
203 .ctrl_modes = {
204 AK8975_REG_CNTL_MODE_POWER_DOWN,
205 AK8975_REG_CNTL_MODE_ONCE,
206 AK8975_REG_CNTL_MODE_SELF_TEST,
207 AK8975_REG_CNTL_MODE_FUSE_ROM},
208 .data_regs = {
209 AK8975_REG_HXL,
210 AK8975_REG_HYL,
211 AK8975_REG_HZL},
212 },
213 {
214 .type = AK8963,
215 .raw_to_gauss = ak8963_raw_to_gauss,
216 .range = 8190,
217 .ctrl_regs = {
218 AK8975_REG_ST1,
219 AK8975_REG_ST2,
220 AK8975_REG_CNTL,
221 AK8975_REG_ASAX,
222 AK8975_MAX_REGS},
223 .ctrl_masks = {
224 AK8975_REG_ST1_DRDY_MASK,
225 AK8975_REG_ST2_HOFL_MASK,
226 0,
227 AK8975_REG_CNTL_MODE_MASK},
228 .ctrl_modes = {
229 AK8975_REG_CNTL_MODE_POWER_DOWN,
230 AK8975_REG_CNTL_MODE_ONCE,
231 AK8975_REG_CNTL_MODE_SELF_TEST,
232 AK8975_REG_CNTL_MODE_FUSE_ROM},
233 .data_regs = {
234 AK8975_REG_HXL,
235 AK8975_REG_HYL,
236 AK8975_REG_HZL},
237 },
96}; 238};
97 239
98/* 240/*
@@ -100,40 +242,36 @@ enum asahi_compass_chipset {
100 */ 242 */
101struct ak8975_data { 243struct ak8975_data {
102 struct i2c_client *client; 244 struct i2c_client *client;
245 struct ak_def *def;
103 struct attribute_group attrs; 246 struct attribute_group attrs;
104 struct mutex lock; 247 struct mutex lock;
105 u8 asa[3]; 248 u8 asa[3];
106 long raw_to_gauss[3]; 249 long raw_to_gauss[3];
107 u8 reg_cache[AK8975_MAX_REGS];
108 int eoc_gpio; 250 int eoc_gpio;
109 int eoc_irq; 251 int eoc_irq;
110 wait_queue_head_t data_ready_queue; 252 wait_queue_head_t data_ready_queue;
111 unsigned long flags; 253 unsigned long flags;
112 enum asahi_compass_chipset chipset; 254 u8 cntl_cache;
113};
114
115static const int ak8975_index_to_reg[] = {
116 AK8975_REG_HXL, AK8975_REG_HYL, AK8975_REG_HZL,
117}; 255};
118 256
119/* 257/*
120 * Helper function to write to the I2C device's registers. 258 * Helper function to write to CNTL register.
121 */ 259 */
122static int ak8975_write_data(struct i2c_client *client, 260static int ak8975_set_mode(struct ak8975_data *data, enum ak_ctrl_mode mode)
123 u8 reg, u8 val, u8 mask, u8 shift)
124{ 261{
125 struct iio_dev *indio_dev = i2c_get_clientdata(client);
126 struct ak8975_data *data = iio_priv(indio_dev);
127 u8 regval; 262 u8 regval;
128 int ret; 263 int ret;
129 264
130 regval = (data->reg_cache[reg] & ~mask) | (val << shift); 265 regval = (data->cntl_cache & ~data->def->ctrl_masks[CNTL_MODE]) |
131 ret = i2c_smbus_write_byte_data(client, reg, regval); 266 data->def->ctrl_modes[mode];
267 ret = i2c_smbus_write_byte_data(data->client,
268 data->def->ctrl_regs[CNTL], regval);
132 if (ret < 0) { 269 if (ret < 0) {
133 dev_err(&client->dev, "Write to device fails status %x\n", ret);
134 return ret; 270 return ret;
135 } 271 }
136 data->reg_cache[reg] = regval; 272 data->cntl_cache = regval;
273 /* After mode change wait atleast 100us */
274 usleep_range(100, 500);
137 275
138 return 0; 276 return 0;
139} 277}
@@ -207,18 +345,15 @@ static int ak8975_setup(struct i2c_client *client)
207 } 345 }
208 346
209 /* Write the fused rom access mode. */ 347 /* Write the fused rom access mode. */
210 ret = ak8975_write_data(client, 348 ret = ak8975_set_mode(data, FUSE_ROM);
211 AK8975_REG_CNTL,
212 AK8975_REG_CNTL_MODE_FUSE_ROM,
213 AK8975_REG_CNTL_MODE_MASK,
214 AK8975_REG_CNTL_MODE_SHIFT);
215 if (ret < 0) { 349 if (ret < 0) {
216 dev_err(&client->dev, "Error in setting fuse access mode\n"); 350 dev_err(&client->dev, "Error in setting fuse access mode\n");
217 return ret; 351 return ret;
218 } 352 }
219 353
220 /* Get asa data and store in the device data. */ 354 /* Get asa data and store in the device data. */
221 ret = i2c_smbus_read_i2c_block_data(client, AK8975_REG_ASAX, 355 ret = i2c_smbus_read_i2c_block_data(client,
356 data->def->ctrl_regs[ASA_BASE],
222 3, data->asa); 357 3, data->asa);
223 if (ret < 0) { 358 if (ret < 0) {
224 dev_err(&client->dev, "Not able to read asa data\n"); 359 dev_err(&client->dev, "Not able to read asa data\n");
@@ -226,11 +361,7 @@ static int ak8975_setup(struct i2c_client *client)
226 } 361 }
227 362
228 /* After reading fuse ROM data set power-down mode */ 363 /* After reading fuse ROM data set power-down mode */
229 ret = ak8975_write_data(client, 364 ret = ak8975_set_mode(data, POWER_DOWN);
230 AK8975_REG_CNTL,
231 AK8975_REG_CNTL_MODE_POWER_DOWN,
232 AK8975_REG_CNTL_MODE_MASK,
233 AK8975_REG_CNTL_MODE_SHIFT);
234 if (ret < 0) { 365 if (ret < 0) {
235 dev_err(&client->dev, "Error in setting power-down mode\n"); 366 dev_err(&client->dev, "Error in setting power-down mode\n");
236 return ret; 367 return ret;
@@ -245,56 +376,9 @@ static int ak8975_setup(struct i2c_client *client)
245 } 376 }
246 } 377 }
247 378
248/* 379 data->raw_to_gauss[0] = data->def->raw_to_gauss(data->asa[0]);
249 * Precalculate scale factor (in Gauss units) for each axis and 380 data->raw_to_gauss[1] = data->def->raw_to_gauss(data->asa[1]);
250 * store in the device data. 381 data->raw_to_gauss[2] = data->def->raw_to_gauss(data->asa[2]);
251 *
252 * This scale factor is axis-dependent, and is derived from 3 calibration
253 * factors ASA(x), ASA(y), and ASA(z).
254 *
255 * These ASA values are read from the sensor device at start of day, and
256 * cached in the device context struct.
257 *
258 * Adjusting the flux value with the sensitivity adjustment value should be
259 * done via the following formula:
260 *
261 * Hadj = H * ( ( ( (ASA-128)*0.5 ) / 128 ) + 1 )
262 *
263 * where H is the raw value, ASA is the sensitivity adjustment, and Hadj
264 * is the resultant adjusted value.
265 *
266 * We reduce the formula to:
267 *
268 * Hadj = H * (ASA + 128) / 256
269 *
270 * H is in the range of -4096 to 4095. The magnetometer has a range of
271 * +-1229uT. To go from the raw value to uT is:
272 *
273 * HuT = H * 1229/4096, or roughly, 3/10.
274 *
275 * Since 1uT = 0.01 gauss, our final scale factor becomes:
276 *
277 * Hadj = H * ((ASA + 128) / 256) * 3/10 * 1/100
278 * Hadj = H * ((ASA + 128) * 0.003) / 256
279 *
280 * Since ASA doesn't change, we cache the resultant scale factor into the
281 * device context in ak8975_setup().
282 */
283 if (data->chipset == AK8963) {
284 /*
285 * H range is +-8190 and magnetometer range is +-4912.
286 * So HuT using the above explanation for 8975,
287 * 4912/8190 = ~ 6/10.
288 * So the Hadj should use 6/10 instead of 3/10.
289 */
290 data->raw_to_gauss[0] = RAW_TO_GAUSS_8963(data->asa[0]);
291 data->raw_to_gauss[1] = RAW_TO_GAUSS_8963(data->asa[1]);
292 data->raw_to_gauss[2] = RAW_TO_GAUSS_8963(data->asa[2]);
293 } else {
294 data->raw_to_gauss[0] = RAW_TO_GAUSS_8975(data->asa[0]);
295 data->raw_to_gauss[1] = RAW_TO_GAUSS_8975(data->asa[1]);
296 data->raw_to_gauss[2] = RAW_TO_GAUSS_8975(data->asa[2]);
297 }
298 382
299 return 0; 383 return 0;
300} 384}
@@ -317,7 +401,7 @@ static int wait_conversion_complete_gpio(struct ak8975_data *data)
317 return -EINVAL; 401 return -EINVAL;
318 } 402 }
319 403
320 ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST1); 404 ret = i2c_smbus_read_byte_data(client, data->def->ctrl_regs[ST1]);
321 if (ret < 0) 405 if (ret < 0)
322 dev_err(&client->dev, "Error in reading ST1\n"); 406 dev_err(&client->dev, "Error in reading ST1\n");
323 407
@@ -334,7 +418,8 @@ static int wait_conversion_complete_polled(struct ak8975_data *data)
334 /* Wait for the conversion to complete. */ 418 /* Wait for the conversion to complete. */
335 while (timeout_ms) { 419 while (timeout_ms) {
336 msleep(AK8975_CONVERSION_DONE_POLL_TIME); 420 msleep(AK8975_CONVERSION_DONE_POLL_TIME);
337 ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST1); 421 ret = i2c_smbus_read_byte_data(client,
422 data->def->ctrl_regs[ST1]);
338 if (ret < 0) { 423 if (ret < 0) {
339 dev_err(&client->dev, "Error in reading ST1\n"); 424 dev_err(&client->dev, "Error in reading ST1\n");
340 return ret; 425 return ret;
@@ -377,11 +462,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
377 mutex_lock(&data->lock); 462 mutex_lock(&data->lock);
378 463
379 /* Set up the device for taking a sample. */ 464 /* Set up the device for taking a sample. */
380 ret = ak8975_write_data(client, 465 ret = ak8975_set_mode(data, MODE_ONCE);
381 AK8975_REG_CNTL,
382 AK8975_REG_CNTL_MODE_ONCE,
383 AK8975_REG_CNTL_MODE_MASK,
384 AK8975_REG_CNTL_MODE_SHIFT);
385 if (ret < 0) { 466 if (ret < 0) {
386 dev_err(&client->dev, "Error in setting operating mode\n"); 467 dev_err(&client->dev, "Error in setting operating mode\n");
387 goto exit; 468 goto exit;
@@ -398,14 +479,15 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
398 goto exit; 479 goto exit;
399 480
400 /* This will be executed only for non-interrupt based waiting case */ 481 /* This will be executed only for non-interrupt based waiting case */
401 if (ret & AK8975_REG_ST1_DRDY_MASK) { 482 if (ret & data->def->ctrl_masks[ST1_DRDY]) {
402 ret = i2c_smbus_read_byte_data(client, AK8975_REG_ST2); 483 ret = i2c_smbus_read_byte_data(client,
484 data->def->ctrl_regs[ST2]);
403 if (ret < 0) { 485 if (ret < 0) {
404 dev_err(&client->dev, "Error in reading ST2\n"); 486 dev_err(&client->dev, "Error in reading ST2\n");
405 goto exit; 487 goto exit;
406 } 488 }
407 if (ret & (AK8975_REG_ST2_DERR_MASK | 489 if (ret & (data->def->ctrl_masks[ST2_DERR] |
408 AK8975_REG_ST2_HOFL_MASK)) { 490 data->def->ctrl_masks[ST2_HOFL])) {
409 dev_err(&client->dev, "ST2 status error 0x%x\n", ret); 491 dev_err(&client->dev, "ST2 status error 0x%x\n", ret);
410 ret = -EINVAL; 492 ret = -EINVAL;
411 goto exit; 493 goto exit;
@@ -414,7 +496,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
414 496
415 /* Read the flux value from the appropriate register 497 /* Read the flux value from the appropriate register
416 (the register is specified in the iio device attributes). */ 498 (the register is specified in the iio device attributes). */
417 ret = i2c_smbus_read_word_data(client, ak8975_index_to_reg[index]); 499 ret = i2c_smbus_read_word_data(client, data->def->data_regs[index]);
418 if (ret < 0) { 500 if (ret < 0) {
419 dev_err(&client->dev, "Read axis data fails\n"); 501 dev_err(&client->dev, "Read axis data fails\n");
420 goto exit; 502 goto exit;
@@ -423,7 +505,7 @@ static int ak8975_read_axis(struct iio_dev *indio_dev, int index, int *val)
423 mutex_unlock(&data->lock); 505 mutex_unlock(&data->lock);
424 506
425 /* Clamp to valid range. */ 507 /* Clamp to valid range. */
426 *val = clamp_t(s16, ret, -4096, 4095); 508 *val = clamp_t(s16, ret, -data->def->range, data->def->range);
427 return IIO_VAL_INT; 509 return IIO_VAL_INT;
428 510
429exit: 511exit:
@@ -497,6 +579,7 @@ static int ak8975_probe(struct i2c_client *client,
497 int eoc_gpio; 579 int eoc_gpio;
498 int err; 580 int err;
499 const char *name = NULL; 581 const char *name = NULL;
582 enum asahi_compass_chipset chipset;
500 583
501 /* Grab and set up the supplied GPIO. */ 584 /* Grab and set up the supplied GPIO. */
502 if (client->dev.platform_data) 585 if (client->dev.platform_data)
@@ -536,14 +619,20 @@ static int ak8975_probe(struct i2c_client *client,
536 619
537 /* id will be NULL when enumerated via ACPI */ 620 /* id will be NULL when enumerated via ACPI */
538 if (id) { 621 if (id) {
539 data->chipset = 622 chipset = (enum asahi_compass_chipset)(id->driver_data);
540 (enum asahi_compass_chipset)(id->driver_data);
541 name = id->name; 623 name = id->name;
542 } else if (ACPI_HANDLE(&client->dev)) 624 } else if (ACPI_HANDLE(&client->dev))
543 name = ak8975_match_acpi_device(&client->dev, &data->chipset); 625 name = ak8975_match_acpi_device(&client->dev, &chipset);
544 else 626 else
545 return -ENOSYS; 627 return -ENOSYS;
546 628
629 if (chipset >= AK_MAX_TYPE) {
630 dev_err(&client->dev, "AKM device type unsupported: %d\n",
631 chipset);
632 return -ENODEV;
633 }
634
635 data->def = &ak_def_array[chipset];
547 dev_dbg(&client->dev, "Asahi compass chip %s\n", name); 636 dev_dbg(&client->dev, "Asahi compass chip %s\n", name);
548 637
549 /* Perform some basic start-of-day setup of the device. */ 638 /* Perform some basic start-of-day setup of the device. */
@@ -574,7 +663,9 @@ MODULE_DEVICE_TABLE(i2c, ak8975_id);
574static const struct of_device_id ak8975_of_match[] = { 663static const struct of_device_id ak8975_of_match[] = {
575 { .compatible = "asahi-kasei,ak8975", }, 664 { .compatible = "asahi-kasei,ak8975", },
576 { .compatible = "ak8975", }, 665 { .compatible = "ak8975", },
577 { } 666 { .compatible = "asahi-kasei,ak8963", },
667 { .compatible = "ak8963", },
668 {}
578}; 669};
579MODULE_DEVICE_TABLE(of, ak8975_of_match); 670MODULE_DEVICE_TABLE(of, ak8975_of_match);
580 671