cregit-Linux how code gets into the kernel

Release 4.7 drivers/staging/iio/accel/lis3l02dq_ring.c

#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/mutex.h>
#include <linux/kernel.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <linux/export.h>

#include <linux/iio/iio.h>
#include <linux/iio/kfifo_buf.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include "lis3l02dq.h"

/**
 * combine_8_to_16() utility function to munge two u8s into u16
 **/

static inline u16 combine_8_to_16(u8 lower, u8 upper) { u16 _lower = lower; u16 _upper = upper; return _lower | (_upper << 8); }

Contributors

PersonTokensPropCommitsCommitProp
jonathan cameronjonathan cameron32100.00%1100.00%
Total32100.00%1100.00%

/** * lis3l02dq_data_rdy_trig_poll() the event handler for the data rdy trig **/
irqreturn_t lis3l02dq_data_rdy_trig_poll(int irq, void *private) { struct iio_dev *indio_dev = private; struct lis3l02dq_state *st = iio_priv(indio_dev); if (st->trigger_on) { iio_trigger_poll(st->trig); return IRQ_HANDLED; } return IRQ_WAKE_THREAD; }

Contributors

PersonTokensPropCommitsCommitProp
jonathan cameronjonathan cameron50100.00%2100.00%
Total50100.00%2100.00%

static const u8 read_all_tx_array[] = { LIS3L02DQ_READ_REG(LIS3L02DQ_REG_OUT_X_L_ADDR), 0, LIS3L02DQ_READ_REG(LIS3L02DQ_REG_OUT_X_H_ADDR), 0, LIS3L02DQ_READ_REG(LIS3L02DQ_REG_OUT_Y_L_ADDR), 0, LIS3L02DQ_READ_REG(LIS3L02DQ_REG_OUT_Y_H_ADDR), 0, LIS3L02DQ_READ_REG(LIS3L02DQ_REG_OUT_Z_L_ADDR), 0, LIS3L02DQ_READ_REG(LIS3L02DQ_REG_OUT_Z_H_ADDR), 0, }; /** * lis3l02dq_read_all() Reads all channels currently selected * @indio_dev: IIO device state * @rx_array: (dma capable) receive array, must be at least * 4*number of channels **/
static int lis3l02dq_read_all(struct iio_dev *indio_dev, u8 *rx_array) { struct lis3l02dq_state *st = iio_priv(indio_dev); struct spi_transfer *xfers; struct spi_message msg; int ret, i, j = 0; xfers = kcalloc(bitmap_weight(indio_dev->active_scan_mask, indio_dev->masklength) * 2, sizeof(*xfers), GFP_KERNEL); if (!xfers) return -ENOMEM; mutex_lock(&st->buf_lock); for (i = 0; i < ARRAY_SIZE(read_all_tx_array) / 4; i++) if (test_bit(i, indio_dev->active_scan_mask)) { /* lower byte */ xfers[j].tx_buf = st->tx + (2 * j); st->tx[2 * j] = read_all_tx_array[i * 4]; st->tx[2 * j + 1] = 0; if (rx_array) xfers[j].rx_buf = rx_array + (j * 2); xfers[j].bits_per_word = 8; xfers[j].len = 2; xfers[j].cs_change = 1; j++; /* upper byte */ xfers[j].tx_buf = st->tx + (2 * j); st->tx[2 * j] = read_all_tx_array[i * 4 + 2]; st->tx[2 * j + 1] = 0; if (rx_array) xfers[j].rx_buf = rx_array + (j * 2); xfers[j].bits_per_word = 8; xfers[j].len = 2; xfers[j].cs_change = 1; j++; } /* After these are transmitted, the rx_buff should have * values in alternate bytes */ spi_message_init(&msg); for (j = 0; j < bitmap_weight(indio_dev->active_scan_mask, indio_dev->masklength) * 2; j++) spi_message_add_tail(&xfers[j], &msg); ret = spi_sync(st->us, &msg); mutex_unlock(&st->buf_lock); kfree(xfers); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
jonathan cameronjonathan cameron37197.12%457.14%
ioana ciorneiioana ciornei82.09%114.29%
thomas meyerthomas meyer20.52%114.29%
greg kroah-hartmangreg kroah-hartman10.26%114.29%
Total382100.00%7100.00%


static int lis3l02dq_get_buffer_element(struct iio_dev *indio_dev, u8 *buf) { int ret, i; u8 *rx_array; s16 *data = (s16 *)buf; int scan_count = bitmap_weight(indio_dev->active_scan_mask, indio_dev->masklength); rx_array = kcalloc(4, scan_count, GFP_KERNEL); if (!rx_array) return -ENOMEM; ret = lis3l02dq_read_all(indio_dev, rx_array); if (ret < 0) { kfree(rx_array); return ret; } for (i = 0; i < scan_count; i++) data[i] = combine_8_to_16(rx_array[i * 4 + 1], rx_array[i * 4 + 3]); kfree(rx_array); return i * sizeof(data[0]); }

Contributors

PersonTokensPropCommitsCommitProp
jonathan cameronjonathan cameron13893.24%562.50%
peter meerwaldpeter meerwald74.73%112.50%
navya sri nizamkarinavya sri nizamkari21.35%112.50%
cristina opriceanacristina opriceana10.68%112.50%
Total148100.00%8100.00%


static irqreturn_t lis3l02dq_trigger_handler(int irq, void *p) { struct iio_poll_func *pf = p; struct iio_dev *indio_dev = pf->indio_dev; int len = 0; char *data; data = kmalloc(indio_dev->scan_bytes, GFP_KERNEL); if (!data) goto done; if (!bitmap_empty(indio_dev->active_scan_mask, indio_dev->masklength)) len = lis3l02dq_get_buffer_element(indio_dev, data); iio_push_to_buffers_with_timestamp(indio_dev, data, pf->timestamp); kfree(data); done: iio_trigger_notify_done(indio_dev->trig); return IRQ_HANDLED; }

Contributors

PersonTokensPropCommitsCommitProp
jonathan cameronjonathan cameron9386.11%660.00%
lars-peter clausenlars-peter clausen1312.04%220.00%
cristina opriceanacristina opriceana10.93%110.00%
peter meerwaldpeter meerwald10.93%110.00%
Total108100.00%10100.00%

/* Caller responsible for locking as necessary. */
static int __lis3l02dq_write_data_ready_config(struct iio_dev *indio_dev, bool state) { int ret; u8 valold; bool currentlyset; struct lis3l02dq_state *st = iio_priv(indio_dev); /* Get the current event mask register */ ret = lis3l02dq_spi_read_reg_8(indio_dev, LIS3L02DQ_REG_CTRL_2_ADDR, &valold); if (ret) goto error_ret; /* Find out if data ready is already on */ currentlyset = valold & LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION; /* Disable requested */ if (!state && currentlyset) { /* Disable the data ready signal */ valold &= ~LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION; /* The double write is to overcome a hardware bug? */ ret = lis3l02dq_spi_write_reg_8(indio_dev, LIS3L02DQ_REG_CTRL_2_ADDR, valold); if (ret) goto error_ret; ret = lis3l02dq_spi_write_reg_8(indio_dev, LIS3L02DQ_REG_CTRL_2_ADDR, valold); if (ret) goto error_ret; st->trigger_on = false; /* Enable requested */ } else if (state && !currentlyset) { /* If not set, enable requested * first disable all events */ ret = lis3l02dq_disable_all_events(indio_dev); if (ret < 0) goto error_ret; valold = ret | LIS3L02DQ_REG_CTRL_2_ENABLE_DATA_READY_GENERATION; st->trigger_on = true; ret = lis3l02dq_spi_write_reg_8(indio_dev, LIS3L02DQ_REG_CTRL_2_ADDR, valold); if (ret) goto error_ret; } return 0; error_ret: return ret; }

Contributors

PersonTokensPropCommitsCommitProp
jonathan cameronjonathan cameron18097.30%562.50%
lars-peter clausenlars-peter clausen21.08%112.50%
peter meerwaldpeter meerwald21.08%112.50%
cristina morarucristina moraru10.54%112.50%
Total185100.00%8100.00%

/** * lis3l02dq_data_rdy_trigger_set_state() set datardy interrupt state * * If disabling the interrupt also does a final read to ensure it is clear. * This is only important in some cases where the scan enable elements are * switched before the buffer is reenabled. **/
static int lis3l02dq_data_rdy_trigger_set_state(struct iio_trigger *trig, bool state) { struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); int ret = 0; u8 t; __lis3l02dq_write_data_ready_config(indio_dev, state); if (!state) { /* * A possible quirk with the handler is currently worked around * by ensuring outstanding read events are cleared. */ ret = lis3l02dq_read_all(indio_dev, NULL); } lis3l02dq_spi_read_reg_8(indio_dev, LIS3L02DQ_REG_WAKE_UP_SRC_ADDR, &t); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
jonathan cameronjonathan cameron6492.75%240.00%
lars-peter clausenlars-peter clausen45.80%240.00%
peter meerwaldpeter meerwald11.45%120.00%
Total69100.00%5100.00%

/** * lis3l02dq_trig_try_reen() try reenabling irq for data rdy trigger * @trig: the datardy trigger */
static int lis3l02dq_trig_try_reen(struct iio_trigger *trig) { struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig); struct lis3l02dq_state *st = iio_priv(indio_dev); int i; /* If gpio still high (or high again) * In theory possible we will need to do this several times */ for (i = 0; i < 5; i++) if (gpio_get_value(st->gpio)) lis3l02dq_read_all(indio_dev, NULL); else break; if (i == 5) pr_info("Failed to clear the interrupt for lis3l02dq\n"); /* irq reenabled so success! */ return 0; }

Contributors

PersonTokensPropCommitsCommitProp
jonathan cameronjonathan cameron7592.59%342.86%
lars-peter clausenlars-peter clausen33.70%114.29%
cristina morarucristina moraru11.23%114.29%
arnd bergmannarnd bergmann11.23%114.29%
ebru akagunduzebru akagunduz11.23%114.29%
Total81100.00%7100.00%

static const struct iio_trigger_ops lis3l02dq_trigger_ops = { .owner = THIS_MODULE, .set_trigger_state = &lis3l02dq_data_rdy_trigger_set_state, .try_reenable = &lis3l02dq_trig_try_reen, };
int lis3l02dq_probe_trigger(struct iio_dev *indio_dev) { int ret; struct lis3l02dq_state *st = iio_priv(indio_dev); st->trig = iio_trigger_alloc("lis3l02dq-dev%d", indio_dev->id); if (!st->trig) { ret = -ENOMEM; goto error_ret; } st->trig->dev.parent = &st->us->dev; st->trig->ops = &lis3l02dq_trigger_ops; iio_trigger_set_drvdata(st->trig, indio_dev); ret = iio_trigger_register(st->trig); if (ret) goto error_free_trig; return 0; error_free_trig: iio_trigger_free(st->trig); error_ret: return ret; }

Contributors

PersonTokensPropCommitsCommitProp
jonathan cameronjonathan cameron11193.28%770.00%
lars-peter clausenlars-peter clausen65.04%220.00%
dan carpenterdan carpenter21.68%110.00%
Total119100.00%10100.00%


void lis3l02dq_remove_trigger(struct iio_dev *indio_dev) { struct lis3l02dq_state *st = iio_priv(indio_dev); iio_trigger_unregister(st->trig); iio_trigger_free(st->trig); }

Contributors

PersonTokensPropCommitsCommitProp
jonathan cameronjonathan cameron3397.06%375.00%
lars-peter clausenlars-peter clausen12.94%125.00%
Total34100.00%4100.00%


void lis3l02dq_unconfigure_buffer(struct iio_dev *indio_dev) { iio_dealloc_pollfunc(indio_dev->pollfunc); iio_kfifo_free(indio_dev->buffer); }

Contributors

PersonTokensPropCommitsCommitProp
jonathan cameronjonathan cameron24100.00%6100.00%
Total24100.00%6100.00%


static int lis3l02dq_buffer_postenable(struct iio_dev *indio_dev) { /* Disable unwanted channels otherwise the interrupt will not clear */ u8 t; int ret; bool oneenabled = false; ret = lis3l02dq_spi_read_reg_8(indio_dev, LIS3L02DQ_REG_CTRL_1_ADDR, &t); if (ret) goto error_ret; if (test_bit(0, indio_dev->active_scan_mask)) { t |= LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE; oneenabled = true; } else { t &= ~LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE; } if (test_bit(1, indio_dev->active_scan_mask)) { t |= LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE; oneenabled = true; } else { t &= ~LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE; } if (test_bit(2, indio_dev->active_scan_mask)) { t |= LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE; oneenabled = true; } else { t &= ~LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE; } if (!oneenabled) /* what happens in this case is unknown */ return -EINVAL; ret = lis3l02dq_spi_write_reg_8(indio_dev, LIS3L02DQ_REG_CTRL_1_ADDR, t); if (ret) goto error_ret; return iio_triggered_buffer_postenable(indio_dev); error_ret: return ret; }

Contributors

PersonTokensPropCommitsCommitProp
jonathan cameronjonathan cameron16296.43%583.33%
haneen mohammedhaneen mohammed63.57%116.67%
Total168100.00%6100.00%

/* Turn all channels on again */
static int lis3l02dq_buffer_predisable(struct iio_dev *indio_dev) { u8 t; int ret; ret = iio_triggered_buffer_predisable(indio_dev); if (ret) goto error_ret; ret = lis3l02dq_spi_read_reg_8(indio_dev, LIS3L02DQ_REG_CTRL_1_ADDR, &t); if (ret) goto error_ret; t |= LIS3L02DQ_REG_CTRL_1_AXES_X_ENABLE | LIS3L02DQ_REG_CTRL_1_AXES_Y_ENABLE | LIS3L02DQ_REG_CTRL_1_AXES_Z_ENABLE; ret = lis3l02dq_spi_write_reg_8(indio_dev, LIS3L02DQ_REG_CTRL_1_ADDR, t); error_ret: return ret; }

Contributors

PersonTokensPropCommitsCommitProp
jonathan cameronjonathan cameron74100.00%4100.00%
Total74100.00%4100.00%

static const struct iio_buffer_setup_ops lis3l02dq_buffer_setup_ops = { .postenable = &lis3l02dq_buffer_postenable, .predisable = &lis3l02dq_buffer_predisable, };
int lis3l02dq_configure_buffer(struct iio_dev *indio_dev) { int ret; struct iio_buffer *buffer; buffer = iio_kfifo_allocate(); if (!buffer) return -ENOMEM; iio_device_attach_buffer(indio_dev, buffer); buffer->scan_timestamp = true; indio_dev->setup_ops = &lis3l02dq_buffer_setup_ops; /* Functions are NULL as we set handler below */ indio_dev->pollfunc = iio_alloc_pollfunc(&iio_pollfunc_store_time, &lis3l02dq_trigger_handler, 0, indio_dev, "lis3l02dq_consumer%d", indio_dev->id); if (!indio_dev->pollfunc) { ret = -ENOMEM; goto error_iio_sw_rb_free; } indio_dev->modes |= INDIO_BUFFER_TRIGGERED; return 0; error_iio_sw_rb_free: iio_kfifo_free(indio_dev->buffer); return ret; }

Contributors

PersonTokensPropCommitsCommitProp
jonathan cameronjonathan cameron9986.84%1168.75%
manuel stahlmanuel stahl97.89%212.50%
lars-peter clausenlars-peter clausen43.51%16.25%
karol wronakarol wrona10.88%16.25%
cristina opriceanacristina opriceana10.88%16.25%
Total114100.00%16100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
jonathan cameronjonathan cameron163594.73%2751.92%
lars-peter clausenlars-peter clausen331.91%713.46%
peter meerwaldpeter meerwald140.81%35.77%
manuel stahlmanuel stahl90.52%23.85%
ioana ciorneiioana ciornei80.46%11.92%
haneen mohammedhaneen mohammed60.35%11.92%
cristina opriceanacristina opriceana30.17%11.92%
tejun heotejun heo30.17%11.92%
paul gortmakerpaul gortmaker30.17%11.92%
thomas meyerthomas meyer20.12%11.92%
navya sri nizamkarinavya sri nizamkari20.12%11.92%
dan carpenterdan carpenter20.12%11.92%
cristina morarucristina moraru20.12%11.92%
greg kroah-hartmangreg kroah-hartman10.06%11.92%
ebru akagunduzebru akagunduz10.06%11.92%
karol wronakarol wrona10.06%11.92%
arnd bergmannarnd bergmann10.06%11.92%
Total1726100.00%52100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
{% endraw %}