mirror of https://gitee.com/openkylin/linux.git
Staging: iio: oaktrail AK8975 support via IIO
Actually this is generic 'I have no GPIO' support for the AK8975, instead we have to go bus polling. Huang Liang produced an initial patch which worked by removing the support for GPIO pins. This patch instead makes GPIO support optional and Huang then fixed some bugs in it. Signed-off-by: Alan Cox <alan@linux.intel.com> Acked-by: Jonathan Cameron <jic23@cam.ac.uk> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
parent
acf0b9e819
commit
01fbb4781f
|
@ -206,7 +206,7 @@ static int ak8975_setup(struct i2c_client *client)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Precalculate scale factor for each axis and
|
/* Precalculate scale factor for each axis and
|
||||||
store in the device data. */
|
store in the device data. */
|
||||||
data->raw_to_gauss[0] = ((data->asa[0] + 128) * 30) >> 8;
|
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[1] = ((data->asa[1] + 128) * 30) >> 8;
|
||||||
data->raw_to_gauss[2] = ((data->asa[2] + 128) * 30) >> 8;
|
data->raw_to_gauss[2] = ((data->asa[2] + 128) * 30) >> 8;
|
||||||
|
@ -316,6 +316,59 @@ static ssize_t show_scale(struct device *dev, struct device_attribute *devattr,
|
||||||
return sprintf(buf, "%ld\n", data->raw_to_gauss[this_attr->address]);
|
return sprintf(buf, "%ld\n", data->raw_to_gauss[this_attr->address]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int wait_conversion_complete_gpio(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);
|
||||||
|
if (gpio_get_value(data->eoc_gpio))
|
||||||
|
break;
|
||||||
|
timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME;
|
||||||
|
}
|
||||||
|
if (!timeout_ms) {
|
||||||
|
dev_err(&client->dev, "Conversion timeout happened\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
return read_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Emits the raw flux value for the x, y, or z axis.
|
* Emits the raw flux value for the x, y, or z axis.
|
||||||
*/
|
*/
|
||||||
|
@ -326,7 +379,6 @@ static ssize_t show_raw(struct device *dev, struct device_attribute *devattr,
|
||||||
struct ak8975_data *data = indio_dev->dev_data;
|
struct ak8975_data *data = indio_dev->dev_data;
|
||||||
struct i2c_client *client = data->client;
|
struct i2c_client *client = data->client;
|
||||||
struct iio_dev_attr *this_attr = to_iio_dev_attr(devattr);
|
struct iio_dev_attr *this_attr = to_iio_dev_attr(devattr);
|
||||||
u32 timeout_ms = AK8975_MAX_CONVERSION_TIMEOUT;
|
|
||||||
u16 meas_reg;
|
u16 meas_reg;
|
||||||
s16 raw;
|
s16 raw;
|
||||||
u8 read_status;
|
u8 read_status;
|
||||||
|
@ -352,23 +404,14 @@ static ssize_t show_raw(struct device *dev, struct device_attribute *devattr,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Wait for the conversion to complete. */
|
/* Wait for the conversion to complete. */
|
||||||
while (timeout_ms) {
|
if (data->eoc_gpio)
|
||||||
msleep(AK8975_CONVERSION_DONE_POLL_TIME);
|
ret = wait_conversion_complete_gpio(data);
|
||||||
if (gpio_get_value(data->eoc_gpio))
|
else
|
||||||
break;
|
ret = wait_conversion_complete_polled(data);
|
||||||
timeout_ms -= AK8975_CONVERSION_DONE_POLL_TIME;
|
if (ret < 0)
|
||||||
}
|
|
||||||
if (!timeout_ms) {
|
|
||||||
dev_err(&client->dev, "Conversion timeout happened\n");
|
|
||||||
ret = -EINVAL;
|
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
|
||||||
|
|
||||||
ret = ak8975_read_data(client, AK8975_REG_ST1, 1, &read_status);
|
read_status = ret;
|
||||||
if (ret < 0) {
|
|
||||||
dev_err(&client->dev, "Error in reading ST1\n");
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (read_status & AK8975_REG_ST1_DRDY_MASK) {
|
if (read_status & AK8975_REG_ST1_DRDY_MASK) {
|
||||||
ret = ak8975_read_data(client, AK8975_REG_ST2, 1, &read_status);
|
ret = ak8975_read_data(client, AK8975_REG_ST2, 1, &read_status);
|
||||||
|
@ -454,25 +497,26 @@ static int ak8975_probe(struct i2c_client *client,
|
||||||
data->eoc_irq = client->irq;
|
data->eoc_irq = client->irq;
|
||||||
data->eoc_gpio = irq_to_gpio(client->irq);
|
data->eoc_gpio = irq_to_gpio(client->irq);
|
||||||
|
|
||||||
if (!data->eoc_gpio) {
|
/* We may not have a GPIO based IRQ to scan, that is fine, we will
|
||||||
dev_err(&client->dev, "failed, no valid GPIO\n");
|
poll if so */
|
||||||
err = -EINVAL;
|
if (data->eoc_gpio > 0) {
|
||||||
goto exit_free;
|
err = gpio_request(data->eoc_gpio, "ak_8975");
|
||||||
}
|
if (err < 0) {
|
||||||
|
dev_err(&client->dev,
|
||||||
|
"failed to request GPIO %d, error %d\n",
|
||||||
|
data->eoc_gpio, err);
|
||||||
|
goto exit_free;
|
||||||
|
}
|
||||||
|
|
||||||
err = gpio_request(data->eoc_gpio, "ak_8975");
|
err = gpio_direction_input(data->eoc_gpio);
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
dev_err(&client->dev, "failed to request GPIO %d, error %d\n",
|
dev_err(&client->dev,
|
||||||
data->eoc_gpio, err);
|
"Failed to configure input direction for GPIO %d, error %d\n",
|
||||||
goto exit_free;
|
data->eoc_gpio, err);
|
||||||
}
|
goto exit_gpio;
|
||||||
|
}
|
||||||
err = gpio_direction_input(data->eoc_gpio);
|
} else
|
||||||
if (err < 0) {
|
data->eoc_gpio = 0; /* No GPIO available */
|
||||||
dev_err(&client->dev, "Failed to configure input direction for"
|
|
||||||
" GPIO %d, error %d\n", data->eoc_gpio, err);
|
|
||||||
goto exit_gpio;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Perform some basic start-of-day setup of the device. */
|
/* Perform some basic start-of-day setup of the device. */
|
||||||
err = ak8975_setup(client);
|
err = ak8975_setup(client);
|
||||||
|
@ -503,7 +547,8 @@ static int ak8975_probe(struct i2c_client *client,
|
||||||
exit_free_iio:
|
exit_free_iio:
|
||||||
iio_free_device(data->indio_dev);
|
iio_free_device(data->indio_dev);
|
||||||
exit_gpio:
|
exit_gpio:
|
||||||
gpio_free(data->eoc_gpio);
|
if (data->eoc_gpio)
|
||||||
|
gpio_free(data->eoc_gpio);
|
||||||
exit_free:
|
exit_free:
|
||||||
kfree(data);
|
kfree(data);
|
||||||
exit:
|
exit:
|
||||||
|
@ -517,7 +562,8 @@ static int ak8975_remove(struct i2c_client *client)
|
||||||
iio_device_unregister(data->indio_dev);
|
iio_device_unregister(data->indio_dev);
|
||||||
iio_free_device(data->indio_dev);
|
iio_free_device(data->indio_dev);
|
||||||
|
|
||||||
gpio_free(data->eoc_gpio);
|
if (data->eoc_gpio)
|
||||||
|
gpio_free(data->eoc_gpio);
|
||||||
|
|
||||||
kfree(data);
|
kfree(data);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue