Commit 6e49557b authored by Greg Kroah-Hartman's avatar Greg Kroah-Hartman

Merge tag 'iio-for-3.20a_take2' of...

Merge tag 'iio-for-3.20a_take2' of git://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio into staging-testing

Jonathan writes:

First round of IIO new drivers, cleanups and functionality for the 3.20 cycle take 2

Updated pull request with Daniel's fix on top for the power management
Kconfig changes that had snuck in since last update of the IIO tree
worked it's way through from mainline.

Original pull message

New device support
* jsa1212 proxmity / ambient light sensor
* SM08500 supported added to the kxcjk-1013 accelerometer driver
* KMX61 Accelerometer/Magnetometer.  This took a somewhat rocky path
  being first merged, then reverted for a rewrite after a discussion of
  how to support additional functionality and finally being merged prior
  to some last reviews coming in, with resultant follow up patches.
* Freescale mma9551l driver (minor follow up warning supression patch).
* Semtech SX9500 proximity device driver.
* ak8975 gains support for ak09911 and ak09912 and drop the standalone driver
  for the ak09911.

New functionality
 * Dummy driver gains some virtual registers making it more flexible.
 * IIO_ACTIVITY channel types, with modifiers running, walking etc.  This is
   to support on chip motion clasifiers.  As such it is in the form of a
   confidence percentage.  The only devices so far only do binary decisions
   but this gives us room when other devices give more nuanced clasification.
 * IIO_EV_DIR_NONE type for events where there is no obvious direction.
   First case is step detection.
 * IIO_STEPS channel type for pedometers.
 * ENABLE mask element used to control turning on counting types such as
   the pedometer that need a 'start point'.
 * INSTANCE event type to support things that happen once.
 * info element for height calibration (used in various motion estimation
   algorithms). Note heigh tof use
 * dummy driver demonstration of the use of all the new bits above.
 * event monitor support for the new events.
 * inv_mpu6050 gains an i2c mux to allow bypassing the device to access
   additional devices connected on the other side of it.  Note that in
   Windows these are handled by firmware on the device and not exposed
   directly.
 * inv_mpu6050 gains ACPI enumeration.
 * inkern interface gains iio_write_channel_raw to allow in kernel users
   of DAC functionality via a simple wrapper.
 * Document input current readings in the ABI docs.
 * Add an error message when we get an out of range error in device tree
   processing for the in kernel interfaces.  Basically a device tree debugging
   aid.
 * Add a sanity check that a scan index for a channel is unique during
   registration.  There to help catch bugs as this should never happen
   in a bug free driver.

Cleanups and fixlets

 A rework of buffer registration from Lars - a precursor to some other
 upcoming new stuff (a few patches from others rolled in here as well).
 * Ensure all drivers register the same channels for the device and buffer.
 * Move buffer registration into the core rather than using the old
   two step approach.  Now we have simple ways of using a unified set channels
   for both without requiring channels be exposed by both interface, this
   removes a fair bit of boilerplate.
 * Stop sca3000 and ad5933 (both in staging) enabling buffer channels by
   default. It has long be convention in IIO to startup with no channels
   enabled and leave it up to userspace to say what goes in the buffer.
   Getting rid of these allows us to drop export of iio_scan_mask_set.
 * Drop get_bytes_per_datum from iio_buffer_access_funcs as not been used
   for a while.
 * Allocate standard buffer attributes in the core rather than in every
   driver with a buffer.
 * Make the length attribute read only when a driver is not able to set
   the length.
 * Drop the get_length callback for buffers as it is already available in
   struct iio_buffer.
 * Drop an unused arguement form iio_kfifo_allocate and add devm allocator
   for it.
 * some kconfig entries gain anotation with the resulting module name.
 * Fix a resulting compile issue in dummy driver due to a stub taking
   wrong parameters as a result of the above rework.
 * Fix an off by 2 error in copying the core assigned buffer attributes.

Other cleanups,
 * Trivial space before comma fixups.
 * ak8975 fixlets - none critical.  Rework to allow more device support.
 * Drop unnecessary sizeof(u8) calls.
 * bmp280 - refactor the compensation code to reduce copy operations and
   code length.  A second patch futher optimized this and performed some
   other minor cleanups.
 * kxcjk-1013 - various power control cleanups to avoid unnecessary enable
   / disable of device.  Make sure it is only controlled at all if CONFIG_PM
   is enabled.  Also som cleanups of error paths.
 * Small cleanups in adf4530 driver - pointless message and unnecessary braces.
 * Clarifiy the proximity ABI docs to make it clear it should get bigger
   as we move futher away.
 * Drop a misleading comment form industrialio-core.c
 * Trivial white space cleanups.
 * sca3000 looses an unused debug function.
 * Fix char unsigned ordering in ad8366
 * Increase the sleep time in ad9523 to make it predictable (value didn't
   really matter so make it more than 20 msecs)
 * mxs-lradc touchscreen property cleanups in device tree are fixed to ensure
   the meet all the 'interesting' documentation.
 * A couple of cleanups for the staging ad5933 driver to avoid unnecessary
   conversion to a processed temperature vlaue in kernel and remove
   platform data form the state structure as not needed after probe.
 * Fix a wrong scale factor in the docs.

Misc
 * Add IIO include files to the maintainers entry.
parents e6008857 df1fad80
......@@ -92,6 +92,18 @@ Description:
is required is a consistent labeling. Units after application
of scale and offset are millivolts.
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_raw
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_supply_raw
KernelVersion: 3.17
Contact: linux-iio@vger.kernel.org
Description:
Raw (unscaled no bias removal etc.) current measurement from
channel Y. In special cases where the channel does not
correspond to externally available input one of the named
versions may be used. The number must always be specified and
unique to allow association with event codes. Units after
application of scale and offset are milliamps.
What: /sys/bus/iio/devices/iio:deviceX/in_capacitanceY_raw
KernelVersion: 3.2
Contact: linux-iio@vger.kernel.org
......@@ -234,6 +246,8 @@ What: /sys/bus/iio/devices/iio:deviceX/in_accel_y_offset
What: /sys/bus/iio/devices/iio:deviceX/in_accel_z_offset
What: /sys/bus/iio/devices/iio:deviceX/in_voltageY_offset
What: /sys/bus/iio/devices/iio:deviceX/in_voltage_offset
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_offset
What: /sys/bus/iio/devices/iio:deviceX/in_current_offset
What: /sys/bus/iio/devices/iio:deviceX/in_tempY_offset
What: /sys/bus/iio/devices/iio:deviceX/in_temp_offset
What: /sys/bus/iio/devices/iio:deviceX/in_pressureY_offset
......@@ -262,6 +276,9 @@ What: /sys/bus/iio/devices/iio:deviceX/in_voltage_scale
What: /sys/bus/iio/devices/iio:deviceX/in_voltage-voltage_scale
What: /sys/bus/iio/devices/iio:deviceX/out_voltageY_scale
What: /sys/bus/iio/devices/iio:deviceX/out_altvoltageY_scale
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_scale
What: /sys/bus/iio/devices/iio:deviceX/in_currentY_supply_scale
What: /sys/bus/iio/devices/iio:deviceX/in_current_scale
What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale
What: /sys/bus/iio/devices/iio:deviceX/in_accel_peak_scale
What: /sys/bus/iio/devices/iio:deviceX/in_anglvel_scale
......@@ -323,6 +340,14 @@ Description:
production inaccuracies). If shared across all channels,
<type>_calibscale is used.
What: /sys/bus/iio/devices/iio:deviceX/in_steps_calibheight
KernelVersion: 3.19
Contact: linux-iio@vger.kernel.org
Description:
Height of the user (in centimeters) used by some pedometers
to compute the stride length, distance, speed and activity
type.
What: /sys/bus/iio/devices/iio:deviceX/in_accel_scale_available
What: /sys/.../iio:deviceX/in_voltageX_scale_available
What: /sys/.../iio:deviceX/in_voltage-voltage_scale_available
......@@ -790,6 +815,40 @@ Description:
met before an event is generated. If direction is not
specified then this period applies to both directions.
What: /sys/.../events/in_activity_still_thresh_rising_en
What: /sys/.../events/in_activity_still_thresh_falling_en
What: /sys/.../events/in_activity_walking_thresh_rising_en
What: /sys/.../events/in_activity_walking_thresh_falling_en
What: /sys/.../events/in_activity_jogging_thresh_rising_en
What: /sys/.../events/in_activity_jogging_thresh_falling_en
What: /sys/.../events/in_activity_running_thresh_rising_en
What: /sys/.../events/in_activity_running_thresh_falling_en
KernelVersion: 3.19
Contact: linux-iio@vger.kernel.org
Description:
Enables or disables activitity events. Depending on direction
an event is generated when sensor ENTERS or LEAVES a given state.
What: /sys/.../events/in_activity_still_thresh_rising_value
What: /sys/.../events/in_activity_still_thresh_falling_value
What: /sys/.../events/in_activity_walking_thresh_rising_value
What: /sys/.../events/in_activity_walking_thresh_falling_value
What: /sys/.../events/in_activity_jogging_thresh_rising_value
What: /sys/.../events/in_activity_jogging_thresh_falling_value
What: /sys/.../events/in_activity_running_thresh_rising_value
What: /sys/.../events/in_activity_running_thresh_falling_value
KernelVersion: 3.19
Contact: linux-iio@vger.kernel.org
Description:
Confidence value (in units as percentage) to be used
for deciding when an event should be generated. E.g for
running: If the confidence value reported by the sensor
is greater than in_activity_running_thresh_rising_value
then the sensor ENTERS running state. Conversely, if the
confidence value reported by the sensor is lower than
in_activity_running_thresh_falling_value then the sensor
is LEAVING running state.
What: /sys/.../iio:deviceX/events/in_accel_mag_en
What: /sys/.../iio:deviceX/events/in_accel_mag_rising_en
What: /sys/.../iio:deviceX/events/in_accel_mag_falling_en
......@@ -822,6 +881,13 @@ Description:
number or direction is not specified, applies to all channels of
this type.
What: /sys/.../events/in_steps_instance_en
KernelVersion: 3.19
Contact: linux-iio@vger.kernel.org
Description:
Enables or disables step detection. Each time the user takes a step an
event of this type will be generated.
What: /sys/bus/iio/devices/iio:deviceX/trigger/current_trigger
KernelVersion: 2.6.35
Contact: linux-iio@vger.kernel.org
......@@ -956,6 +1022,16 @@ Description:
and the relevant _type attributes to establish the data storage
format.
What: /sys/.../iio:deviceX/in_activity_still_input
What: /sys/.../iio:deviceX/in_activity_walking_input
What: /sys/.../iio:deviceX/in_activity_jogging_input
What: /sys/.../iio:deviceX/in_activity_running_input
KernelVersion: 3.19
Contact: linux-iio@vger.kernel.org
Description:
This attribute is used to read the confidence for an activity
expressed in units as percentage.
What: /sys/.../iio:deviceX/in_anglvel_z_quadrature_correction_raw
KernelVersion: 2.6.38
Contact: linux-iio@vger.kernel.org
......@@ -992,7 +1068,9 @@ Description:
reflectivity of infrared or ultrasound emitted.
Often these sensors are unit less and as such conversion
to SI units is not possible. Where it is, the units should
be meters.
be meters. If such a conversion is not possible, the reported
values should behave in the same way as a distance, i.e. lower
values indicate something is closer to the sensor.
What: /sys/.../iio:deviceX/in_illuminanceY_input
What: /sys/.../iio:deviceX/in_illuminanceY_raw
......@@ -1051,3 +1129,18 @@ Description:
after application of scale and offset. If no offset or scale is
present, output should be considered as processed with the
unit in milliamps.
What: /sys/.../iio:deviceX/in_steps_en
KernelVersion: 3.19
Contact: linux-iio@vger.kernel.org
Description:
Activates the step counter. After activation, the number of steps
taken by the user will be counted in hardware and exported through
in_steps_input.
What: /sys/.../iio:deviceX/in_steps_input
KernelVersion: 3.19
Contact: linux-iio@vger.kernel.org
Description:
This attribute is used to read the number of steps taken by the user
since the last reboot while activated.
......@@ -12,9 +12,9 @@ Optional properties:
property is not present, then the touchscreen is
disabled. 5 wires is valid for i.MX28 SoC only.
- fsl,ave-ctrl: number of samples per direction to calculate an average value.
Allowed value is 1 ... 31, default is 4
Allowed value is 1 ... 32, default is 4
- fsl,ave-delay: delay between consecutive samples. Allowed value is
1 ... 2047. It is used if 'fsl,ave-ctrl' > 1, counts at
2 ... 2048. It is used if 'fsl,ave-ctrl' > 1, counts at
2 kHz and its default is 2 (= 1 ms)
- fsl,settling: delay between plate switch to next sample. Allowed value is
1 ... 2047. It counts at 2 kHz and its default is
......
......@@ -258,6 +258,8 @@ IIO
devm_iio_device_free()
devm_iio_device_register()
devm_iio_device_unregister()
devm_iio_kfifo_allocate()
devm_iio_kfifo_free()
devm_iio_trigger_alloc()
devm_iio_trigger_free()
......
......@@ -43,6 +43,9 @@ config HID_SENSOR_ACCEL_3D
Say yes here to build support for the HID SENSOR
accelerometers 3D.
To compile this driver as a module, choose M here: the
module will be called hid-sensor-accel-3d.
config IIO_ST_ACCEL_3AXIS
tristate "STMicroelectronics accelerometers 3-Axis Driver"
depends on (I2C || SPI_MASTER) && SYSFS
......@@ -80,6 +83,9 @@ config KXSD9
Say yes here to build support for the Kionix KXSD9 accelerometer.
Currently this only supports the device via an SPI interface.
To compile this driver as a module, choose M here: the module
will be called kxsd9.
config MMA8452
tristate "Freescale MMA8452Q Accelerometer Driver"
depends on I2C
......@@ -105,4 +111,14 @@ config KXCJK1013
To compile this driver as a module, choose M here: the module will
be called kxcjk-1013.
config MMA9551
tristate "Freescale MMA9551L Intelligent Motion-Sensing Platform Driver"
depends on I2C
help
Say yes here to build support for the Freescale MMA9551L
Intelligent Motion-Sensing Platform Driver.
To compile this driver as a module, choose M here: the module
will be called mma9551.
endmenu
......@@ -9,6 +9,7 @@ obj-$(CONFIG_HID_SENSOR_ACCEL_3D) += hid-sensor-accel-3d.o
obj-$(CONFIG_KXCJK1013) += kxcjk-1013.o
obj-$(CONFIG_KXSD9) += kxsd9.o
obj-$(CONFIG_MMA8452) += mma8452.o
obj-$(CONFIG_MMA9551) += mma9551.o
obj-$(CONFIG_IIO_ST_ACCEL_3AXIS) += st_accel.o
st_accel-y := st_accel_core.o
......
......@@ -108,6 +108,7 @@ struct kxcjk1013_data {
bool motion_trigger_on;
int64_t timestamp;
enum kx_chipset chipset;
bool is_smo8500_device;
};
enum kxcjk1013_axis {
......@@ -377,6 +378,7 @@ static int kxcjk1013_get_startup_times(struct kxcjk1013_data *data)
static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on)
{
#ifdef CONFIG_PM
int ret;
if (on)
......@@ -388,8 +390,11 @@ static int kxcjk1013_set_power_state(struct kxcjk1013_data *data, bool on)
if (ret < 0) {
dev_err(&data->client->dev,
"Failed: kxcjk1013_set_power_state for %d\n", on);
if (on)
pm_runtime_put_noidle(&data->client->dev);
return ret;
}
#endif
return 0;
}
......@@ -858,6 +863,8 @@ static int kxcjk1013_write_event_config(struct iio_dev *indio_dev,
ret = kxcjk1013_setup_any_motion_interrupt(data, state);
if (ret < 0) {
kxcjk1013_set_power_state(data, false);
data->ev_enable_state = 0;
mutex_unlock(&data->mutex);
return ret;
}
......@@ -1008,6 +1015,7 @@ static int kxcjk1013_data_rdy_trigger_set_state(struct iio_trigger *trig,
else
ret = kxcjk1013_setup_new_data_interrupt(data, state);
if (ret < 0) {
kxcjk1013_set_power_state(data, false);
mutex_unlock(&data->mutex);
return ret;
}
......@@ -1131,12 +1139,16 @@ static irqreturn_t kxcjk1013_data_rdy_trig_poll(int irq, void *private)
}
static const char *kxcjk1013_match_acpi_device(struct device *dev,
enum kx_chipset *chipset)
enum kx_chipset *chipset,
bool *is_smo8500_device)
{
const struct acpi_device_id *id;
id = acpi_match_device(dev->driver->acpi_match_table, dev);
if (!id)
return NULL;
if (strcmp(id->id, "SMO8500") == 0)
*is_smo8500_device = true;
*chipset = (enum kx_chipset)id->driver_data;
return dev_name(dev);
......@@ -1151,6 +1163,8 @@ static int kxcjk1013_gpio_probe(struct i2c_client *client,
if (!client)
return -EINVAL;
if (data->is_smo8500_device)
return -ENOTSUPP;
dev = &client->dev;
......@@ -1200,7 +1214,8 @@ static int kxcjk1013_probe(struct i2c_client *client,
name = id->name;
} else if (ACPI_HANDLE(&client->dev)) {
name = kxcjk1013_match_acpi_device(&client->dev,
&data->chipset);
&data->chipset,
&data->is_smo8500_device);
} else
return -ENODEV;
......@@ -1228,21 +1243,25 @@ static int kxcjk1013_probe(struct i2c_client *client,
KXCJK1013_IRQ_NAME,
indio_dev);
if (ret)
return ret;
goto err_poweroff;
data->dready_trig = devm_iio_trigger_alloc(&client->dev,
"%s-dev%d",
indio_dev->name,
indio_dev->id);
if (!data->dready_trig)
return -ENOMEM;
if (!data->dready_trig) {
ret = -ENOMEM;
goto err_poweroff;
}
data->motion_trig = devm_iio_trigger_alloc(&client->dev,
"%s-any-motion-dev%d",
indio_dev->name,
indio_dev->id);
if (!data->motion_trig)
return -ENOMEM;
if (!data->motion_trig) {
ret = -ENOMEM;
goto err_poweroff;
}
data->dready_trig->dev.parent = &client->dev;
data->dready_trig->ops = &kxcjk1013_trigger_ops;
......@@ -1251,7 +1270,7 @@ static int kxcjk1013_probe(struct i2c_client *client,
iio_trigger_get(indio_dev->trig);
ret = iio_trigger_register(data->dready_trig);
if (ret)
return ret;
goto err_poweroff;
data->motion_trig->dev.parent = &client->dev;
data->motion_trig->ops = &kxcjk1013_trigger_ops;
......@@ -1300,6 +1319,8 @@ static int kxcjk1013_probe(struct i2c_client *client,
iio_trigger_unregister(data->dready_trig);
if (data->motion_trig)
iio_trigger_unregister(data->motion_trig);
err_poweroff:
kxcjk1013_set_mode(data, STANDBY);
return ret;
}
......@@ -1349,10 +1370,7 @@ static int kxcjk1013_resume(struct device *dev)
int ret = 0;
mutex_lock(&data->mutex);
/* Check, if the suspend occured while active */
if (data->dready_trigger_on || data->motion_trigger_on ||
data->ev_enable_state)
ret = kxcjk1013_set_mode(data, OPERATION);
ret = kxcjk1013_set_mode(data, OPERATION);
mutex_unlock(&data->mutex);
return ret;
......@@ -1364,8 +1382,14 @@ static int kxcjk1013_runtime_suspend(struct device *dev)
{
struct iio_dev *indio_dev = i2c_get_clientdata(to_i2c_client(dev));
struct kxcjk1013_data *data = iio_priv(indio_dev);
int ret;
return kxcjk1013_set_mode(data, STANDBY);
ret = kxcjk1013_set_mode(data, STANDBY);
if (ret < 0) {
dev_err(&data->client->dev, "powering off device failed\n");
return -EAGAIN;
}
return 0;
}
static int kxcjk1013_runtime_resume(struct device *dev)
......@@ -1399,6 +1423,7 @@ static const struct acpi_device_id kx_acpi_match[] = {
{"KXCJ1013", KXCJK1013},
{"KXCJ1008", KXCJ91008},
{"KXTJ1009", KXTJ21009},
{"SMO8500", KXCJ91008},
{ },
};
MODULE_DEVICE_TABLE(acpi, kx_acpi_match);
......@@ -1407,6 +1432,7 @@ static const struct i2c_device_id kxcjk1013_id[] = {
{"kxcjk1013", KXCJK1013},
{"kxcj91008", KXCJ91008},
{"kxtj21009", KXTJ21009},
{"SMO8500", KXCJ91008},
{}
};
......
......@@ -111,7 +111,7 @@ static const int mma8452_samp_freq[8][2] = {
{6, 250000}, {1, 560000}
};
/*
/*
* Hardware has fullscale of -2G, -4G, -8G corresponding to raw value -2048
* The userspace interface uses m/s^2 and we declare micro units
* So scale factor is given by:
......
This diff is collapsed.
......@@ -250,7 +250,7 @@ static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev,
struct iio_buffer *buffer;
int ret;
buffer = iio_kfifo_allocate(indio_dev);
buffer = iio_kfifo_allocate();
if (!buffer)
return -ENOMEM;
......@@ -264,16 +264,8 @@ static int tiadc_iio_buffered_hardware_setup(struct iio_dev *indio_dev,
indio_dev->setup_ops = setup_ops;
indio_dev->modes |= INDIO_BUFFER_HARDWARE;
ret = iio_buffer_register(indio_dev,
indio_dev->channels,
indio_dev->num_channels);
if (ret)
goto error_free_irq;
return 0;
error_free_irq:
free_irq(irq, indio_dev);
error_kfifo_free:
iio_kfifo_free(indio_dev->buffer);
return ret;
......@@ -285,7 +277,6 @@ static void tiadc_iio_buffered_hardware_remove(struct iio_dev *indio_dev)
free_irq(adc_dev->mfd_tscadc->irq, indio_dev);
iio_kfifo_free(indio_dev->buffer);
iio_buffer_unregister(indio_dev);
}
......
......@@ -31,7 +31,7 @@ struct ad8366_state {
};
static int ad8366_write(struct iio_dev *indio_dev,
unsigned char ch_a, char unsigned ch_b)
unsigned char ch_a, unsigned char ch_b)
{
struct ad8366_state *st = iio_priv(indio_dev);
int ret;
......@@ -166,7 +166,7 @@ static int ad8366_probe(struct spi_device *spi)
if (ret)
goto error_disable_reg;
ad8366_write(indio_dev, 0 , 0);
ad8366_write(indio_dev, 0, 0);
return 0;
......
......@@ -54,7 +54,7 @@ static int st_sensors_spi_read(struct st_sensor_transfer_buffer *tb,
if (err)
goto acc_spi_read_error;
memcpy(data, tb->rx_buf, len*sizeof(u8));
memcpy(data, tb->rx_buf, len);
mutex_unlock(&tb->buf_lock);
return len;
......
......@@ -445,7 +445,7 @@ static int ad9523_store_eeprom(struct iio_dev *indio_dev)
tmp = 4;
do {
msleep(16);
msleep(20);
ret = ad9523_read(indio_dev,
AD9523_EEPROM_DATA_XFER_STATUS);
if (ret < 0)
......
......@@ -387,10 +387,8 @@ static struct adf4350_platform_data *adf4350_parse_dt(struct device *dev)
int ret;
pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
if (!pdata) {
dev_err(dev, "could not allocate memory for platform data\n");
if (!pdata)
return NULL;
}
strncpy(&pdata->name[0], np->name, SPI_NAME_SIZE - 1);
......@@ -613,9 +611,8 @@ static int adf4350_remove(struct spi_device *spi)
if (st->clk)
clk_disable_unprepare(st->clk);
if (!IS_ERR(reg)) {
if (!IS_ERR(reg))
regulator_disable(reg);
}
return 0;
}
......
......@@ -48,6 +48,8 @@ unsigned int iio_buffer_poll(struct file *filp,
ssize_t iio_buffer_read_first_n_outer(struct file *filp, char __user *buf,
size_t n, loff_t *f_ps);
int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev);
void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev);
#define iio_buffer_poll_addr (&iio_buffer_poll)
#define iio_buffer_read_first_n_outer_addr (&iio_buffer_read_first_n_outer)
......@@ -60,6 +62,13 @@ void iio_buffer_wakeup_poll(struct iio_dev *indio_dev);
#define iio_buffer_poll_addr NULL
#define iio_buffer_read_first_n_outer_addr NULL
static inline int iio_buffer_alloc_sysfs_and_mask(struct iio_dev *indio_dev)
{
return 0;
}
static inline void iio_buffer_free_sysfs_and_mask(struct iio_dev *indio_dev) {}
static inline void iio_disable_all_buffers(struct iio_dev *indio_dev) {}
static inline void iio_buffer_wakeup_poll(struct iio_dev *indio_dev) {}
......
......@@ -25,6 +25,17 @@ config ADIS16480
Say yes here to build support for Analog Devices ADIS16375, ADIS16480,
ADIS16485, ADIS16488 inertial sensors.
config KMX61
tristate "Kionix KMX61 6-axis accelerometer and magnetometer"
depends on I2C
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
help
Say Y here if you want to build a driver for Kionix KMX61 6-axis
accelerometer and magnetometer.
To compile this driver as module, choose M here: the module will
be called kmx61.
source "drivers/iio/imu/inv_mpu6050/Kconfig"
endmenu
......
......@@ -14,3 +14,5 @@ adis_lib-$(CONFIG_IIO_ADIS_LIB_BUFFER) += adis_buffer.o
obj-$(CONFIG_IIO_ADIS_LIB) += adis_lib.o
obj-y += inv_mpu6050/
obj-$(CONFIG_KMX61) += kmx61.o
......@@ -7,6 +7,7 @@ config INV_MPU6050_IIO
depends on I2C && SYSFS
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select I2C_MUX
help
This driver supports the Invensense MPU6050 devices.
This driver can also support MPU6500 in MPU6050 compatibility mode
......
......@@ -23,6 +23,8 @@
#include <linux/kfifo.h>
#include <linux/spinlock.h>
#include <linux/iio/iio.h>
#include <linux/i2c-mux.h>
#include <linux/acpi.h>
#include "inv_mpu_iio.h"
/*
......@@ -52,6 +54,7 @@ static const struct inv_mpu6050_reg_map reg_set_6050 = {
.int_enable = INV_MPU6050_REG_INT_ENABLE,
.pwr_mgmt_1 = INV_MPU6050_REG_PWR_MGMT_1,
.pwr_mgmt_2 = INV_MPU6050_REG_PWR_MGMT_2,
.int_pin_cfg = INV_MPU6050_REG_INT_PIN_CFG,
};
static const struct inv_mpu6050_chip_config chip_config_6050 = {
......@@ -77,6 +80,83 @@ int inv_mpu6050_write_reg(struct inv_mpu6050_state *st, int reg, u8 d)
return i2c_smbus_write_i2c_block_data(st->client, reg, 1, &d);
}
/*
* The i2c read/write needs to happen in unlocked mode. As the parent
* adapter is common. If we use locked versions, it will fail as
* the mux adapter will lock the parent i2c adapter, while calling
* select/deselect functions.
*/
static int inv_mpu6050_write_reg_unlocked(struct inv_mpu6050_state *st,
u8 reg, u8 d)
{
int ret;
u8 buf[2];
struct i2c_msg msg[1] = {
{
.addr = st->client->addr,
.flags = 0,
.len = sizeof(buf),
.buf = buf,
}
};
buf[0] = reg;
buf[1] = d;
ret = __i2c_transfer(st->client->adapter, msg, 1);
if (ret != 1)
return ret;
return 0;
}
static int inv_mpu6050_select_bypass(struct i2c_adapter *adap, void *mux_priv,
u32 chan_id)
{
struct iio_dev *indio_dev = mux_priv;
struct inv_mpu6050_state *st = iio_priv(indio_dev);
int ret = 0;
/* Use the same mutex which was used everywhere to protect power-op */
mutex_lock(&indio_dev->mlock);
if (!st->powerup_count) {
ret = inv_mpu6050_write_reg_unlocked(st, st->reg->pwr_mgmt_1,
0);
if (ret)
goto write_error;
msleep(INV_MPU6050_REG_UP_TIME);
}
if (!ret) {
st->powerup_count++;
ret = inv_mpu6050_write_reg_unlocked(st, st->reg->int_pin_cfg,
st->client->irq |
INV_MPU6050_BIT_BYPASS_EN);
}
write_error:
mutex_unlock(&indio_dev->mlock);
return ret;
}
static int inv_mpu6050_deselect_bypass(struct i2c_adapter *adap,
void *mux_priv, u32 chan_id)
{
struct iio_dev *indio_dev = mux_priv;
struct inv_mpu6050_state *st = iio_priv(indio_dev);
mutex_lock(&indio_dev->mlock);
/* It doesn't really mattter, if any of the calls fails */
inv_mpu6050_write_reg_unlocked(st, st->reg->int_pin_cfg,
st->client->irq);
st->powerup_count--;
if (!st->powerup_count)
inv_mpu6050_write_reg_unlocked(st, st->reg->pwr_mgmt_1,
INV_MPU6050_BIT_SLEEP);
mutex_unlock(&indio_dev->mlock);
return 0;
}
int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
{
u8 d, mgmt_1;
......@@ -133,13 +213,22 @@ int inv_mpu6050_switch_engine(struct inv_mpu6050_state *st, bool en, u32 mask)
int inv_mpu6050_set_power_itg(struct inv_mpu6050_state *st, bool power_on)
{
int result;
int result = 0;
if (power_on) {
/* Already under indio-dev->mlock mutex */
if (!st->powerup_count)
result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1,
0);
if (!result)
st->powerup_count++;
} else {
st->powerup_count--;
if (!st->powerup_count)
result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1,
INV_MPU6050_BIT_SLEEP);
}
if (power_on)
result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1, 0);
else
result = inv_mpu6050_write_reg(st, st->reg->pwr_mgmt_1,
INV_MPU6050_BIT_SLEEP);
if (result)
return result;
......@@ -673,6 +762,7 @@ static int inv_mpu_probe(struct i2c_client *client,
st = iio_priv(indio_dev);
st->client = client;
st->powerup_count = 0;
pdata = dev_get_platdata(&client->dev);
if (pdata)
st->plat_data = *pdata;
......@@ -720,8 +810,21 @@ static int inv_mpu_probe(struct i2c_client *client,
goto out_remove_trigger;
}
st->mux_adapter = i2c_add_mux_adapter(client->adapter,
&client->dev,
indio_dev,
0, 0, 0,
inv_mpu6050_select_bypass,
inv_mpu6050_deselect_bypass);
if (!st->mux_adapter) {
result = -ENODEV;
goto out_unreg_device;
}
return 0;
out_unreg_device:
iio_device_unregister(indio_dev);
out_remove_trigger:
inv_mpu6050_remove_trigger(st);
out_unreg_ring:
......@@ -734,6 +837,7 @@ static int inv_mpu_remove(struct i2c_client *client)
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct inv_mpu6050_state *st = iio_priv(indio_dev);
i2c_del_mux_adapter(st->mux_adapter);
iio_device_unregister(indio_dev);
inv_mpu6050_remove_trigger(st);
iio_triggered_buffer_cleanup(indio_dev);
......@@ -772,6 +876,13 @@ static const struct i2c_device_id inv_mpu_id[] = {
MODULE_DEVICE_TABLE(i2c, inv_mpu_id);
static const struct acpi_device_id inv_acpi_match[] = {
{"INVN6500", 0},
{ },
};
MODULE_DEVICE_TABLE(acpi, inv_acpi_match);
static struct i2c_driver inv_mpu_driver = {
.probe = inv_mpu_probe,
.remove = inv_mpu_remove,
......@@ -780,6 +891,7 @@ static struct i2c_driver inv_mpu_driver = {
.owner = THIS_MODULE,
.name = "inv-mpu6050",
.pm = INV_MPU6050_PMOPS,
.acpi_match_table = ACPI_PTR(inv_acpi_match),
},
};
......
......@@ -54,6 +54,7 @@ struct inv_mpu6050_reg_map {
u8 int_enable;
u8 pwr_mgmt_1;
u8 pwr_mgmt_2;
u8 int_pin_cfg;
};
/*device enum */
......@@ -119,6 +120,8 @@ struct inv_mpu6050_state {
enum inv_devices chip_type;
spinlock_t time_stamp_lock;
struct i2c_client *client;
struct i2c_adapter *mux_adapter;
unsigned int powerup_count;
struct inv_mpu6050_platform_data plat_data;
DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
};
......@@ -179,6 +182,9 @@ struct inv_mpu6050_state {
/* 6 + 6 round up and plus 8 */
#define INV_MPU6050_OUTPUT_DATA_SIZE 24
#define INV_MPU6050_REG_INT_PIN_CFG 0x37
#define INV_MPU6050_BIT_BYPASS_EN 0x2
/* init parameters */
#define INV_MPU6050_INIT_FIFO_RATE 50
#define INV_MPU6050_TIME_STAMP_TOR 5
......
This diff is collapsed.
This diff is collapsed.
......@@ -70,6 +70,8 @@ static const char * const iio_chan_type_name_spec[] = {
[IIO_CCT] = "cct",
[IIO_PRESSURE] = "pressure",
[IIO_HUMIDITYRELATIVE] = "humidityrelative",
[IIO_ACTIVITY] = "activity",
[IIO_STEPS] = "steps",
};
static const char * const iio_modifier_names[] = {
......@@ -91,6 +93,10 @@ static const char * const iio_modifier_names[] = {
[IIO_MOD_NORTH_TRUE] = "from_north_true",
[IIO_MOD_NORTH_MAGN_TILT_COMP] = "from_north_magnetic_tilt_comp",
[IIO_MOD_NORTH_TRUE_TILT_COMP] = "from_north_true_tilt_comp",
[IIO_MOD_RUNNING] = "running",
[IIO_MOD_JOGGING] = "jogging",
[IIO_MOD_WALKING] = "walking",
[IIO_MOD_STILL] = "still",
};
/* relies on pairs of these shared then separate */
......@@ -113,6 +119,8 @@ static const char * const iio_chan_info_postfix[] = {
[IIO_CHAN_INFO_HARDWAREGAIN] = "hardwaregain",
[IIO_CHAN_INFO_HYSTERESIS] = "hysteresis",
[IIO_CHAN_INFO_INT_TIME] = "integration_time",
[IIO_CHAN_INFO_ENABLE] = "en",
[IIO_CHAN_INFO_CALIBHEIGHT] = "calibheight",
};
/**
......@@ -1035,7 +1043,6 @@ struct iio_dev *devm_iio_device_alloc(struct device *dev, int sizeof_priv)
if (!ptr)
return NULL;
/* use raw alloc_dr for kmalloc caller tracing */
iio_dev = iio_device_alloc(sizeof_priv);
if (iio_dev) {
*ptr = iio_dev;
......@@ -1127,6 +1134,29 @@ static const struct file_operations iio_buffer_fileops = {
.compat_ioctl = iio_ioctl,
};
static int iio_check_unique_scan_index(struct iio_dev *indio_dev)
{
int i, j;
const struct iio_chan_spec *channels = indio_dev->channels;
if (!(indio_dev->modes & INDIO_ALL_BUFFER_MODES))
return 0;
for (i = 0; i < indio_dev->num_channels - 1; i++) {
if (channels[i].scan_index < 0)
continue;
for (j = i + 1; j < indio_dev->num_channels; j++)
if (channels[i].scan_index == channels[j].scan_index) {
dev_err(&indio_dev->dev,
"Duplicate scan index %d\n",
channels[i].scan_index);
return -EINVAL;
}
}
return 0;
}
static const struct iio_buffer_setup_ops noop_ring_setup_ops;
/**
......@@ -1141,6 +1171,10 @@ int iio_device_register(struct iio_dev *indio_dev)
if (!indio_dev->dev.of_node && indio_dev->dev.parent)
indio_dev->dev.of_node = indio_dev->dev.parent->of_node;
ret = iio_check_unique_scan_index(indio_dev);
if (ret < 0)
return ret;
/* configure elements for the chrdev */
indio_dev->dev.devt = MKDEV(MAJOR(iio_devt), indio_dev->id);
......@@ -1150,11 +1184,19 @@ int iio_device_register(struct iio_dev *indio_dev)
"Failed to register debugfs interfaces\n");
return ret;
}
ret = iio_buffer_alloc_sysfs_and_mask(indio_dev);
if (ret) {
dev_err(indio_dev->dev.parent,
"Failed to create buffer sysfs interfaces\n");
goto error_unreg_debugfs;
}
ret = iio_device_register_sysfs(indio_dev);
if (ret) {
dev_err(indio_dev->dev.parent,
"Failed to register sysfs interfaces\n");
goto error_unreg_debugfs;
goto error_buffer_free_sysfs;
}
ret = iio_device_register_eventset(indio_dev);
if (ret) {
......@@ -1187,6 +1229,8 @@ int iio_device_register(struct iio_dev *indio_dev)
iio_device_unregister_eventset(indio_dev);
error_free_sysfs:
iio_device_unregister_sysfs(indio_dev);
error_buffer_free_sysfs:
iio_buffer_free_sysfs_and_mask(indio_dev);
error_unreg_debugfs:
iio_device_unregister_debugfs(indio_dev);
return ret;
......@@ -1215,6 +1259,8 @@ void iio_device_unregister(struct iio_dev *indio_dev)
iio_buffer_wakeup_poll(indio_dev);
mutex_unlock(&indio_dev->info_exist_lock);
iio_buffer_free_sysfs_and_mask(indio_dev);
}
EXPORT_SYMBOL(iio_device_unregister);
......
......@@ -197,6 +197,7 @@ static const char * const iio_ev_type_text[] = {
[IIO_EV_TYPE_ROC] = "roc",
[IIO_EV_TYPE_THRESH_ADAPTIVE] = "thresh_adaptive",
[IIO_EV_TYPE_MAG_ADAPTIVE] = "mag_adaptive",
[IIO_EV_TYPE_INSTANCE] = "instance",
};
static const char * const iio_ev_dir_text[] = {
......@@ -327,9 +328,15 @@ static int iio_device_add_event(struct iio_dev *indio_dev,
for_each_set_bit(i, mask, sizeof(*mask)*8) {
if (i >= ARRAY_SIZE(iio_ev_info_text))
return -EINVAL;
postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
iio_ev_type_text[type], iio_ev_dir_text[dir],
iio_ev_info_text[i]);
if (dir != IIO_EV_DIR_NONE)
postfix = kasprintf(GFP_KERNEL, "%s_%s_%s",
iio_ev_type_text[type],
iio_ev_dir_text[dir],
iio_ev_info_text[i]);
else
postfix = kasprintf(GFP_KERNEL, "%s_%s",
iio_ev_type_text[type],
iio_ev_info_text[i]);
if (postfix == NULL)
return -ENOMEM;
......
......@@ -32,7 +32,7 @@ static const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
*
* This function combines some common tasks which will normally be performed
* when setting up a triggered buffer. It will allocate the buffer and the
* pollfunc, as well as register the buffer with the IIO core.
* pollfunc.
*
* Before calling this function the indio_dev structure should already be
* completely initialized, but not yet registered. In practice this means that
......@@ -49,7 +49,7 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev,
struct iio_buffer *buffer;
int ret;
buffer = iio_kfifo_allocate(indio_dev);
buffer = iio_kfifo_allocate();
if (!buffer) {
ret = -ENOMEM;
goto error_ret;
......@@ -78,16 +78,8 @@ int iio_triggered_buffer_setup(struct iio_dev *indio_dev,
/* Flag that polled ring buffering is possible */
indio_dev->modes |= INDIO_BUFFER_TRIGGERED;
ret = iio_buffer_register(indio_dev,
indio_dev->channels,
indio_dev->num_channels);
if (ret)
goto error_dealloc_pollfunc;
return 0;
error_dealloc_pollfunc:
iio_dealloc_pollfunc(indio_dev->pollfunc);
error_kfifo_free:
iio_kfifo_free(indio_dev->buffer);
error_ret:
......@@ -101,7 +93,6 @@ EXPORT_SYMBOL(iio_triggered_buffer_setup);
*/
void iio_triggered_buffer_cleanup(struct iio_dev *indio_dev)
{
iio_buffer_unregister(indio_dev);
iio_dealloc_pollfunc(indio_dev->pollfunc);
iio_kfifo_free(indio_dev->buffer);
}
......
......@@ -116,8 +116,11 @@ static int __of_iio_simple_xlate(struct iio_dev *indio_dev,
if (!iiospec->args_count)
return 0;
if (iiospec->args[0] >= indio_dev->num_channels)
if (iiospec->args[0] >= indio_dev->num_channels) {
dev_err(&indio_dev->dev, "invalid channel index %u\n",
iiospec->args[0]);
return -EINVAL;
}
return iiospec->args[0];
}
......@@ -634,3 +637,28 @@ int iio_get_channel_type(struct iio_channel *chan, enum iio_chan_type *type)
return ret;
}
EXPORT_SYMBOL_GPL(iio_get_channel_type);
static int iio_channel_write(struct iio_channel *chan, int val, int val2,
enum iio_chan_info_enum info)
{
return chan->indio_dev->info->write_raw(chan->indio_dev,
chan->channel, val, val2, info);
}
int iio_write_channel_raw(struct iio_channel *chan, int val)
{
int ret;
mutex_lock(&chan->indio_dev->info_exist_lock);
if (chan->indio_dev->info == NULL) {
ret = -ENODEV;
goto err_unlock;
}
ret = iio_channel_write(chan, val, 0, IIO_CHAN_INFO_RAW);
err_unlock:
mutex_unlock(&chan->indio_dev->info_exist_lock);
return ret;
}
EXPORT_SYMBOL_GPL(iio_write_channel_raw);
......@@ -47,30 +47,6 @@ static int iio_request_update_kfifo(struct iio_buffer *r)
return ret;
}
static int iio_get_length_kfifo(struct iio_buffer *r)
{
return r->length;
}
static IIO_BUFFER_ENABLE_ATTR;
static IIO_BUFFER_LENGTH_ATTR;
static struct attribute *iio_kfifo_attributes[] = {
&dev_attr_length.attr,
&dev_attr_enable.attr,
NULL,
};
static struct attribute_group iio_kfifo_attribute_group = {
.attrs = iio_kfifo_attributes,
.name = "buffer",
};
static int iio_get_bytes_per_datum_kfifo(struct iio_buffer *r)
{
return r->bytes_per_datum;
}
static int iio_mark_update_needed_kfifo(struct iio_buffer *r)
{
struct iio_kfifo *kf = iio_to_kfifo(r);
......@@ -159,26 +135,25 @@ static const struct iio_buffer_access_funcs kfifo_access_funcs = {
.read_first_n = &iio_read_first_n_kfifo,
.data_available = iio_kfifo_buf_data_available,
.request_update = &iio_request_update_kfifo,
.get_bytes_per_datum = &iio_get_bytes_per_datum_kfifo,
.set_bytes_per_datum = &iio_set_bytes_per_datum_kfifo,
.get_length = &iio_get_length_kfifo,
.set_length = &iio_set_length_kfifo,
.release = &iio_kfifo_buffer_release,
};
struct iio_buffer *iio_kfifo_allocate(struct iio_dev *indio_dev)
struct iio_buffer *iio_kfifo_allocate(void)
{
struct iio_kfifo *kf;
kf = kzalloc(sizeof *kf, GFP_KERNEL);
kf = kzalloc(sizeof(*kf), GFP_KERNEL);
if (!kf)
return NULL;
kf->update_needed = true;
iio_buffer_init(&kf->buffer);
kf->buffer.attrs = &iio_kfifo_attribute_group;
kf->buffer.access = &kfifo_access_funcs;
kf->buffer.length = 2;
mutex_init(&kf->user_lock);
return &kf->buffer;
}
EXPORT_SYMBOL(iio_kfifo_allocate);
......@@ -189,4 +164,58 @@ void iio_kfifo_free(struct iio_buffer *r)
}
EXPORT_SYMBOL(iio_kfifo_free);
static void devm_iio_kfifo_release(struct device *dev, void *res)
{
iio_kfifo_free(*(struct iio_buffer **)res);
}
static int devm_iio_kfifo_match(struct device *dev, void *res, void *data)
{
struct iio_buffer **r = res;
if (WARN_ON(!r || !*r))
return 0;
return *r == data;
}
/**
* devm_iio_fifo_allocate - Resource-managed iio_kfifo_allocate()
* @dev: Device to allocate kfifo buffer for
*
* RETURNS:
* Pointer to allocated iio_buffer on success, NULL on failure.
*/
struct iio_buffer *devm_iio_kfifo_allocate(struct device *dev)
{
struct iio_buffer **ptr, *r;
ptr = devres_alloc(devm_iio_kfifo_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return NULL;
r = iio_kfifo_allocate();
if (r) {
*ptr = r;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return r;
}
EXPORT_SYMBOL(devm_iio_kfifo_allocate);
/**
* devm_iio_fifo_free - Resource-managed iio_kfifo_free()
* @dev: Device the buffer belongs to
* @r: The buffer associated with the device
*/
void devm_iio_kfifo_free(struct device *dev, struct iio_buffer *r)
{
WARN_ON(devres_release(dev, devm_iio_kfifo_release,
devm_iio_kfifo_match, r));
}
EXPORT_SYMBOL(devm_iio_kfifo_free);
MODULE_LICENSE("GPL");
......@@ -95,6 +95,9 @@ config HID_SENSOR_ALS
Say yes here to build support for the HID SENSOR
Ambient light sensor.
To compile this driver as a module, choose M here: the
module will be called hid-sensor-als.
config HID_SENSOR_PROX
depends on HID_SENSOR_HUB
select IIO_BUFFER
......@@ -109,6 +112,16 @@ config HID_SENSOR_PROX
To compile this driver as a module, choose M here: the
module will be called hid-sensor-prox.
config JSA1212
tristate "JSA1212 ALS and proximity sensor driver"
depends on I2C
help
Say Y here if you want to build a IIO driver for JSA1212
proximity & ALS sensor device.
To compile this driver as a module, choose M here:
the module will be called jsa1212.
config SENSORS_LM3533
tristate "LM3533 ambient light sensor"
depends on MFD_LM3533
......
......@@ -12,6 +12,7 @@ obj-$(CONFIG_GP2AP020A00F) += gp2ap020a00f.o
obj-$(CONFIG_HID_SENSOR_ALS) += hid-sensor-als.o
obj-$(CONFIG_HID_SENSOR_PROX) += hid-sensor-prox.o
obj-$(CONFIG_ISL29125) += isl29125.o
obj-$(CONFIG_JSA1212) += jsa1212.o
obj-$(CONFIG_SENSORS_LM3533) += lm3533-als.o
obj-$(CONFIG_LTR501) += ltr501.o
obj-$(CONFIG_SENSORS_TSL2563) += tsl2563.o
......
This diff is collapsed.
......@@ -657,7 +657,7 @@ static ALS_HYSTERESIS_ATTR_RO(3);
#define ILLUMINANCE_ATTR_RO(_name) \
DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO, show_##_name, NULL)
#define ILLUMINANCE_ATTR_RW(_name) \
DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO | S_IWUSR , \
DEVICE_ATTR(in_illuminance0_##_name, S_IRUGO | S_IWUSR, \
show_##_name, store_##_name)
/*
* ALS Zone threshold-event enable
......
......@@ -6,26 +6,21 @@
menu "Magnetometer sensors"
config AK8975
tristate "Asahi Kasei AK8975 3-Axis Magnetometer"
tristate "Asahi Kasei AK 3-Axis Magnetometer"
depends on I2C
depends on GPIOLIB
help
Say yes here to build support for Asahi Kasei AK8975 3-Axis
Magnetometer. This driver can also support AK8963, if i2c
device name is identified as ak8963.
Say yes here to build support for Asahi Kasei AK8975, AK8963,
AK09911 or AK09912 3-Axis Magnetometer.
To compile this driver as a module, choose M here: the module
will be called ak8975.
config AK09911
tristate "Asahi Kasei AK09911 3-axis Compass"
depends on I2C
select AK8975
help
Say yes here to build support for Asahi Kasei AK09911 3-Axis
Magnetometer.
To compile this driver as a module, choose M here: the module
will be called ak09911.
Deprecated: AK09911 is now supported by AK8975 driver.
config MAG3110
tristate "Freescale MAG3110 3-Axis Magnetometer"
......
......@@ -3,7 +3,6 @@
#
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_AK09911) += ak09911.o
obj-$(CONFIG_AK8975) += ak8975.o
obj-$(CONFIG_MAG3110) += mag3110.o
obj-$(CONFIG_HID_SENSOR_MAGNETOMETER_3D) += hid-sensor-magn-3d.o
......
/*
* AK09911 3-axis compass driver
* Copyright (c) 2014, Intel Corporation.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
*
* This program is distributed in the hope it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/acpi.h>
#include <linux/iio/iio.h>
#define AK09911_REG_WIA1 0x00
#define AK09911_REG_WIA2 0x01
#define AK09911_WIA1_VALUE 0x48
#define AK09911_WIA2_VALUE 0x05
#define AK09911_REG_ST1 0x10
#define AK09911_REG_HXL 0x11
#define AK09911_REG_HXH 0x12
#define AK09911_REG_HYL 0x13
#define AK09911_REG_HYH 0x14
#define AK09911_REG_HZL 0x15
#define AK09911_REG_HZH 0x16
#define AK09911_REG_ASAX 0x60
#define AK09911_REG_ASAY 0x61
#define AK09911_REG_ASAZ 0x62
#define AK09911_REG_CNTL1 0x30
#define AK09911_REG_CNTL2 0x31
#define AK09911_REG_CNTL3 0x32
#define AK09911_MODE_SNG_MEASURE 0x01
#define AK09911_MODE_SELF_TEST 0x10
#define AK09911_MODE_FUSE_ACCESS 0x1F
#define AK09911_MODE_POWERDOWN 0x00
#define AK09911_RESET_DATA 0x01
#define AK09911_REG_CNTL1 0x30
#define AK09911_REG_CNTL2 0x31
#define AK09911_REG_CNTL3 0x32
#define AK09911_RAW_TO_GAUSS(asa) ((((asa) + 128) * 6000) / 256)
#define AK09911_MAX_CONVERSION_TIMEOUT_MS 500
#define AK09911_CONVERSION_DONE_POLL_TIME_MS 10
struct ak09911_data {
struct i2c_client *client;
struct mutex lock;
u8 asa[3];
long raw_to_gauss[3];
};
static const int ak09911_index_to_reg[] = {
AK09911_REG_HXL, AK09911_REG_HYL, AK09911_REG_HZL,
};
static int ak09911_set_mode(struct i2c_client *client, u8 mode)
{
int ret;
switch (mode) {
case AK09911_MODE_SNG_MEASURE:
case AK09911_MODE_SELF_TEST:
case AK09911_MODE_FUSE_ACCESS:
case AK09911_MODE_POWERDOWN:
ret = i2c_smbus_write_byte_data(client,
AK09911_REG_CNTL2, mode);
if (ret < 0) {
dev_err(&client->dev, "set_mode error\n");
return ret;
}
/* After mode change wait atleast 100us */
usleep_range(100, 500);
break;
default:
dev_err(&client->dev,
"%s: Unknown mode(%d).", __func__, mode);
return -EINVAL;
}
return ret;
}
/* Get Sensitivity Adjustment value */
static int ak09911_get_asa(struct i2c_client *client)
{
struct iio_dev *indio_dev = i2c_get_clientdata(client);
struct ak09911_data *data = iio_priv(indio_dev);
int ret;
ret = ak09911_set_mode(client, AK09911_MODE_FUSE_ACCESS);
if (ret < 0)
return ret;
/* Get asa data and store in the device data. */
ret = i2c_smbus_read_i2c_block_data(client, AK09911_REG_ASAX,
3, data->asa);
if (ret < 0) {
dev_err(&client->dev, "Not able to read asa data\n");
return ret;
}
ret = ak09911_set_mode(client, AK09911_MODE_POWERDOWN);
if (ret < 0)
return ret;
data->raw_to_gauss[0] = AK09911_RAW_TO_GAUSS(data->asa[0]);
data->raw_to_gauss[1] = AK09911_RAW_TO_GAUSS(data->asa[1]);
data->raw_to_gauss[2] = AK09911_RAW_TO_GAUSS(data->asa[2]);
return 0;
}
static int ak09911_verify_chip_id(struct i2c_client *client)
{
u8 wia_val[2];
int ret;
ret = i2c_smbus_read_i2c_block_data(client, AK09911_REG_WIA1,
2, wia_val);
if (ret < 0) {
dev_err(&client->dev, "Error reading WIA\n");
return ret;
}
dev_dbg(&client->dev, "WIA %02x %02x\n", wia_val[0], wia_val[1]);
if (wia_val[0] != AK09911_WIA1_VALUE ||
wia_val[1] != AK09911_WIA2_VALUE) {
dev_err(&client->dev, "Device ak09911 not found\n");
return -ENODEV;
}
return 0;
}
static int wait_conversion_complete_polled(struct ak09911_data *data)
{
struct i2c_client *client = data->client;
u8 read_status;
u32 timeout_ms = AK09911_MAX_CONVERSION_TIMEOUT_MS;
int ret;
/* Wait for the conversion to complete. */
while (timeout_ms) {
msleep_interruptible(AK09911_CONVERSION_DONE_POLL_TIME_MS);
ret = i2c_smbus_read_byte_data(client, AK09911_REG_ST1);
if (ret < 0) {
dev_err(&client->dev, "Error in reading ST1\n");
return ret;
}
read_status = ret & 0x01;
if (read_status)
break;
timeout_ms -= AK09911_CONVERSION_DONE_POLL_TIME_MS;
}
if (!timeout_ms) {
dev_err(&client->dev, "Conversion timeout happened\n");
return -EIO;
}
return read_status;
}
static int ak09911_read_axis(struct iio_dev *indio_dev, int index, int *val)
{
struct ak09911_data *data = iio_priv(indio_dev);
struct i2c_client *client = data->client;
int ret;
mutex_lock(&data->lock);
ret = ak09911_set_mode(client, AK09911_MODE_SNG_MEASURE);
if (ret < 0)
goto fn_exit;
ret = wait_conversion_complete_polled(data);
if (ret < 0)
goto fn_exit;
/* Read data */
ret = i2c_smbus_read_word_data(client, ak09911_index_to_reg[index]);
if (ret < 0) {
dev_err(&client->dev, "Read axis data fails\n");
goto fn_exit;
}
mutex_unlock(&data->lock);
/* Clamp to valid range. */
*val = sign_extend32(clamp_t(s16, ret, -8192, 8191), 13);
return IIO_VAL_INT;
fn_exit:
mutex_unlock(&data->lock);
return ret;
}
static int ak09911_read_raw(struct iio_dev *indio_dev,
struct iio_chan_spec const *chan,
int *val, int *val2,
long mask)
{
struct ak09911_data *data = iio_priv(indio_dev);
switch (mask) {
case IIO_CHAN_INFO_RAW:
return ak09911_read_axis(indio_dev, chan->address, val);
case IIO_CHAN_INFO_SCALE:
*val = 0;
*val2 = data->raw_to_gauss[chan->address];
return IIO_VAL_INT_PLUS_MICRO;
}
return -EINVAL;
}
#define AK09911_CHANNEL(axis, index) \
{ \
.type = IIO_MAGN, \
.modified = 1, \
.channel2 = IIO_MOD_##axis, \
.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) | \
BIT(IIO_CHAN_INFO_SCALE), \
.address = index, \
}
static const struct iio_chan_spec ak09911_channels[] = {
AK09911_CHANNEL(X, 0), AK09911_CHANNEL(Y, 1), AK09911_CHANNEL(Z, 2),
};
static const struct iio_info ak09911_info = {
.read_raw = &ak09911_read_raw,
.driver_module = THIS_MODULE,
};
static const struct acpi_device_id ak_acpi_match[] = {
{"AK009911", 0},
{ },
};
MODULE_DEVICE_TABLE(acpi, ak_acpi_match);
static int ak09911_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct iio_dev *indio_dev;
struct ak09911_data *data;
const char *name;
int ret;
ret = ak09911_verify_chip_id(client);
if (ret) {
dev_err(&client->dev, "AK00911 not detected\n");
return -ENODEV;
}
indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*data));
if (indio_dev == NULL)
return -ENOMEM;
data = iio_priv(indio_dev);
i2c_set_clientdata(client, indio_dev);
data->client = client;
mutex_init(&data->lock);
ret = ak09911_get_asa(client);
if (ret)
return ret;
if (id)
name = id->name;
else if (ACPI_HANDLE(&client->dev))
name = dev_name(&client->dev);
else
return -ENODEV;
dev_dbg(&client->dev, "Asahi compass chip %s\n", name);
indio_dev->dev.parent = &client->dev;
indio_dev->channels = ak09911_channels;
indio_dev->num_channels = ARRAY_SIZE(ak09911_channels);
indio_dev->info = &ak09911_info;
indio_dev->modes = INDIO_DIRECT_MODE;
indio_dev->name = name;
return devm_iio_device_register(&client->dev, indio_dev);
}
static const struct i2c_device_id ak09911_id[] = {
{"ak09911", 0},
{}
};
MODULE_DEVICE_TABLE(i2c, ak09911_id);
static struct i2c_driver ak09911_driver = {
.driver = {
.name = "ak09911",
.acpi_match_table = ACPI_PTR(ak_acpi_match),
},
.probe = ak09911_probe,
.id_table = ak09911_id,
};
module_i2c_driver(ak09911_driver);
MODULE_AUTHOR("Srinivas Pandruvada <srinivas.pandruvada@linux.intel.com>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("AK09911 Compass driver");
This diff is collapsed.
This diff is collapsed.
......@@ -17,3 +17,20 @@ config AS3935
module will be called as3935
endmenu
menu "Proximity sensors"
config SX9500
tristate "SX9500 Semtech proximity sensor"
select IIO_BUFFER
select IIO_TRIGGERED_BUFFER
select REGMAP_I2C
depends on I2C
help
Say Y here to build a driver for Semtech's SX9500 capacitive
proximity/button sensor.
To compile this driver as a module, choose M here: the
module will be called sx9500.
endmenu
......@@ -4,3 +4,4 @@
# When adding new entries keep the list in alphabetical order
obj-$(CONFIG_AS3935) += as3935.o
obj-$(CONFIG_SX9500) += sx9500.o
This diff is collapsed.
......@@ -135,6 +135,7 @@ static int iio_sysfs_trigger_probe(int id)
struct iio_sysfs_trig *t;
int ret;
bool foundit = false;
mutex_lock(&iio_sysfs_trig_list_mut);
list_for_each_entry(t, &iio_sysfs_trig_list, l)
if (id == t->id) {
......@@ -185,6 +186,7 @@ static int iio_sysfs_trigger_remove(int id)
{
bool foundit = false;
struct iio_sysfs_trig *t;
mutex_lock(&iio_sysfs_trig_list_mut);
list_for_each_entry(t, &iio_sysfs_trig_list, l)
if (id == t->id) {
......
......@@ -39,9 +39,9 @@ request_update
If parameters have changed that require reinitialization or configuration of
the buffer this will trigger it.
get_bytes_per_datum, set_bytes_per_datum
Get/set the number of bytes for a complete scan. (All samples + timestamp)
set_bytes_per_datum
Set the number of bytes for a complete scan. (All samples + timestamp)
get_length / set_length
Get/set the number of complete scans that may be held by the buffer.
set_length
Set the number of complete scans that may be held by the buffer.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment