PageRenderTime 67ms CodeModel.GetById 19ms app.highlight 31ms RepoModel.GetById 1ms app.codeStats 0ms

/drivers/staging/iio/adc/max1363_ring.c

https://bitbucket.org/wisechild/galaxy-nexus
C | 209 lines | 152 code | 27 blank | 30 comment | 29 complexity | d121b13ce3867a0ab013d5fbe7b0622e MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.0, AGPL-1.0
  1/*
  2 * Copyright (C) 2008 Jonathan Cameron
  3 *
  4 * This program is free software; you can redistribute it and/or modify
  5 * it under the terms of the GNU General Public License version 2 as
  6 * published by the Free Software Foundation.
  7 *
  8 * max1363_ring.c
  9 */
 10
 11#include <linux/interrupt.h>
 12#include <linux/device.h>
 13#include <linux/slab.h>
 14#include <linux/kernel.h>
 15#include <linux/sysfs.h>
 16#include <linux/list.h>
 17#include <linux/i2c.h>
 18#include <linux/bitops.h>
 19
 20#include "../iio.h"
 21#include "../ring_generic.h"
 22#include "../ring_sw.h"
 23#include "../trigger.h"
 24#include "../sysfs.h"
 25
 26#include "max1363.h"
 27
 28int max1363_single_channel_from_ring(long mask, struct max1363_state *st)
 29{
 30	struct iio_ring_buffer *ring = iio_priv_to_dev(st)->ring;
 31	int count = 0, ret;
 32	u8 *ring_data;
 33	if (!(st->current_mode->modemask & mask)) {
 34		ret = -EBUSY;
 35		goto error_ret;
 36	}
 37
 38	ring_data = kmalloc(ring->access->get_bytes_per_datum(ring),
 39			    GFP_KERNEL);
 40	if (ring_data == NULL) {
 41		ret = -ENOMEM;
 42		goto error_ret;
 43	}
 44	ret = ring->access->read_last(ring, ring_data);
 45	if (ret)
 46		goto error_free_ring_data;
 47	/* Need a count of channels prior to this one */
 48	mask >>= 1;
 49	while (mask) {
 50		if (mask & st->current_mode->modemask)
 51			count++;
 52		mask >>= 1;
 53	}
 54	if (st->chip_info->bits != 8)
 55		ret = ((int)(ring_data[count*2 + 0] & 0x0F) << 8)
 56			+ (int)(ring_data[count*2 + 1]);
 57	else
 58		ret = ring_data[count];
 59
 60error_free_ring_data:
 61	kfree(ring_data);
 62error_ret:
 63	return ret;
 64}
 65
 66
 67/**
 68 * max1363_ring_preenable() - setup the parameters of the ring before enabling
 69 *
 70 * The complex nature of the setting of the nuber of bytes per datum is due
 71 * to this driver currently ensuring that the timestamp is stored at an 8
 72 * byte boundary.
 73 **/
 74static int max1363_ring_preenable(struct iio_dev *indio_dev)
 75{
 76	struct max1363_state *st = iio_priv(indio_dev);
 77	struct iio_ring_buffer *ring = indio_dev->ring;
 78	size_t d_size = 0;
 79	unsigned long numvals;
 80
 81	/*
 82	 * Need to figure out the current mode based upon the requested
 83	 * scan mask in iio_dev
 84	 */
 85	st->current_mode = max1363_match_mode(ring->scan_mask,
 86					st->chip_info);
 87	if (!st->current_mode)
 88		return -EINVAL;
 89
 90	max1363_set_scan_mode(st);
 91
 92	numvals = hweight_long(st->current_mode->modemask);
 93	if (ring->access->set_bytes_per_datum) {
 94		if (ring->scan_timestamp)
 95			d_size += sizeof(s64);
 96		if (st->chip_info->bits != 8)
 97			d_size += numvals*2;
 98		else
 99			d_size += numvals;
100		if (ring->scan_timestamp && (d_size % 8))
101			d_size += 8 - (d_size % 8);
102		ring->access->set_bytes_per_datum(ring, d_size);
103	}
104
105	return 0;
106}
107
108static irqreturn_t max1363_trigger_handler(int irq, void *p)
109{
110	struct iio_poll_func *pf = p;
111	struct iio_dev *indio_dev = pf->private_data;
112	struct max1363_state *st = iio_priv(indio_dev);
113	s64 time_ns;
114	__u8 *rxbuf;
115	int b_sent;
116	size_t d_size;
117	unsigned long numvals = hweight_long(st->current_mode->modemask);
118
119	/* Ensure the timestamp is 8 byte aligned */
120	if (st->chip_info->bits != 8)
121		d_size = numvals*2 + sizeof(s64);
122	else
123		d_size = numvals + sizeof(s64);
124	if (d_size % sizeof(s64))
125		d_size += sizeof(s64) - (d_size % sizeof(s64));
126
127	/* Monitor mode prevents reading. Whilst not currently implemented
128	 * might as well have this test in here in the meantime as it does
129	 * no harm.
130	 */
131	if (numvals == 0)
132		return IRQ_HANDLED;
133
134	rxbuf = kmalloc(d_size,	GFP_KERNEL);
135	if (rxbuf == NULL)
136		return -ENOMEM;
137	if (st->chip_info->bits != 8)
138		b_sent = i2c_master_recv(st->client, rxbuf, numvals*2);
139	else
140		b_sent = i2c_master_recv(st->client, rxbuf, numvals);
141	if (b_sent < 0)
142		goto done;
143
144	time_ns = iio_get_time_ns();
145
146	memcpy(rxbuf + d_size - sizeof(s64), &time_ns, sizeof(time_ns));
147
148	indio_dev->ring->access->store_to(indio_dev->ring, rxbuf, time_ns);
149done:
150	iio_trigger_notify_done(indio_dev->trig);
151	kfree(rxbuf);
152
153	return IRQ_HANDLED;
154}
155
156static const struct iio_ring_setup_ops max1363_ring_setup_ops = {
157	.postenable = &iio_triggered_ring_postenable,
158	.preenable = &max1363_ring_preenable,
159	.predisable = &iio_triggered_ring_predisable,
160};
161
162int max1363_register_ring_funcs_and_init(struct iio_dev *indio_dev)
163{
164	struct max1363_state *st = iio_priv(indio_dev);
165	int ret = 0;
166
167	indio_dev->ring = iio_sw_rb_allocate(indio_dev);
168	if (!indio_dev->ring) {
169		ret = -ENOMEM;
170		goto error_ret;
171	}
172	indio_dev->pollfunc = iio_alloc_pollfunc(NULL,
173						 &max1363_trigger_handler,
174						 IRQF_ONESHOT,
175						 indio_dev,
176						 "%s_consumer%d",
177						 st->client->name,
178						 indio_dev->id);
179	if (indio_dev->pollfunc == NULL) {
180		ret = -ENOMEM;
181		goto error_deallocate_sw_rb;
182	}
183	/* Effectively select the ring buffer implementation */
184	indio_dev->ring->access = &ring_sw_access_funcs;
185	/* Ring buffer functions - here trigger setup related */
186	indio_dev->ring->setup_ops = &max1363_ring_setup_ops;
187
188	/* Flag that polled ring buffering is possible */
189	indio_dev->modes |= INDIO_RING_TRIGGERED;
190
191	return 0;
192
193error_deallocate_sw_rb:
194	iio_sw_rb_free(indio_dev->ring);
195error_ret:
196	return ret;
197}
198
199void max1363_ring_cleanup(struct iio_dev *indio_dev)
200{
201	/* ensure that the trigger has been detached */
202	if (indio_dev->trig) {
203		iio_put_trigger(indio_dev->trig);
204		iio_trigger_dettach_poll_func(indio_dev->trig,
205					      indio_dev->pollfunc);
206	}
207	iio_dealloc_pollfunc(indio_dev->pollfunc);
208	iio_sw_rb_free(indio_dev->ring);
209}