2019-05-24 12:04:09 +02:00
// SPDX-License-Identifier: GPL-2.0-or-later
2012-11-13 13:28:00 +00:00
/*
* Common library for ADIS16XXX devices
*
* Copyright 2012 Analog Devices Inc .
* Author : Lars - Peter Clausen < lars @ metafoo . de >
*/
2012-11-13 13:28:00 +00:00
# include <linux/export.h>
# include <linux/interrupt.h>
# include <linux/mutex.h>
# include <linux/kernel.h>
# include <linux/spi/spi.h>
# include <linux/slab.h>
# include <linux/iio/iio.h>
# include <linux/iio/buffer.h>
# include <linux/iio/trigger_consumer.h>
2012-11-13 13:28:00 +00:00
# include <linux/iio/triggered_buffer.h>
2012-11-13 13:28:00 +00:00
# include <linux/iio/imu/adis.h>
2012-11-13 13:28:00 +00:00
2019-03-22 22:44:40 +02:00
static int adis_update_scan_mode_burst ( struct iio_dev * indio_dev ,
2022-01-22 14:09:05 +01:00
const unsigned long * scan_mask )
2019-03-22 22:44:40 +02:00
{
struct adis * adis = iio_device_get_drvdata ( indio_dev ) ;
2020-04-13 10:24:43 +02:00
unsigned int burst_length , burst_max_length ;
2019-03-22 22:44:40 +02:00
u8 * tx ;
2020-09-17 17:52:20 +02:00
burst_length = adis - > data - > burst_len + adis - > burst_extra_len ;
2020-04-13 10:24:43 +02:00
2020-09-17 17:52:20 +02:00
if ( adis - > data - > burst_max_len )
burst_max_length = adis - > data - > burst_max_len ;
2020-04-13 10:24:43 +02:00
else
burst_max_length = burst_length ;
2019-03-22 22:44:40 +02:00
adis - > xfer = kcalloc ( 2 , sizeof ( * adis - > xfer ) , GFP_KERNEL ) ;
if ( ! adis - > xfer )
return - ENOMEM ;
2020-04-13 10:24:43 +02:00
adis - > buffer = kzalloc ( burst_max_length + sizeof ( u16 ) , GFP_KERNEL ) ;
2019-09-19 10:56:35 -05:00
if ( ! adis - > buffer ) {
kfree ( adis - > xfer ) ;
adis - > xfer = NULL ;
2019-03-22 22:44:40 +02:00
return - ENOMEM ;
2019-09-19 10:56:35 -05:00
}
2019-03-22 22:44:40 +02:00
2020-04-13 10:24:43 +02:00
tx = adis - > buffer + burst_max_length ;
2020-09-17 17:52:20 +02:00
tx [ 0 ] = ADIS_READ_REG ( adis - > data - > burst_reg_cmd ) ;
2019-03-22 22:44:40 +02:00
tx [ 1 ] = 0 ;
adis - > xfer [ 0 ] . tx_buf = tx ;
adis - > xfer [ 0 ] . bits_per_word = 8 ;
adis - > xfer [ 0 ] . len = 2 ;
2021-04-27 10:54:52 +02:00
if ( adis - > data - > burst_max_speed_hz )
adis - > xfer [ 0 ] . speed_hz = adis - > data - > burst_max_speed_hz ;
2019-03-22 22:44:40 +02:00
adis - > xfer [ 1 ] . rx_buf = adis - > buffer ;
adis - > xfer [ 1 ] . bits_per_word = 8 ;
adis - > xfer [ 1 ] . len = burst_length ;
2021-04-27 10:54:52 +02:00
if ( adis - > data - > burst_max_speed_hz )
adis - > xfer [ 1 ] . speed_hz = adis - > data - > burst_max_speed_hz ;
2019-03-22 22:44:40 +02:00
spi_message_init ( & adis - > msg ) ;
spi_message_add_tail ( & adis - > xfer [ 0 ] , & adis - > msg ) ;
spi_message_add_tail ( & adis - > xfer [ 1 ] , & adis - > msg ) ;
return 0 ;
}
2012-11-13 13:28:00 +00:00
int adis_update_scan_mode ( struct iio_dev * indio_dev ,
2022-01-22 14:09:05 +01:00
const unsigned long * scan_mask )
2012-11-13 13:28:00 +00:00
{
2012-11-13 13:28:00 +00:00
struct adis * adis = iio_device_get_drvdata ( indio_dev ) ;
const struct iio_chan_spec * chan ;
unsigned int scan_count ;
unsigned int i , j ;
__be16 * tx , * rx ;
2012-11-13 13:28:00 +00:00
2012-11-13 13:28:00 +00:00
kfree ( adis - > xfer ) ;
kfree ( adis - > buffer ) ;
2012-11-13 13:28:00 +00:00
2020-09-17 17:52:20 +02:00
if ( adis - > data - > burst_len )
2019-03-22 22:44:40 +02:00
return adis_update_scan_mode_burst ( indio_dev , scan_mask ) ;
2012-11-13 13:28:00 +00:00
scan_count = indio_dev - > scan_bytes / 2 ;
2012-11-13 13:28:00 +00:00
2012-11-13 13:28:00 +00:00
adis - > xfer = kcalloc ( scan_count + 1 , sizeof ( * adis - > xfer ) , GFP_KERNEL ) ;
if ( ! adis - > xfer )
return - ENOMEM ;
treewide: kzalloc() -> kcalloc()
The kzalloc() function has a 2-factor argument form, kcalloc(). This
patch replaces cases of:
kzalloc(a * b, gfp)
with:
kcalloc(a * b, gfp)
as well as handling cases of:
kzalloc(a * b * c, gfp)
with:
kzalloc(array3_size(a, b, c), gfp)
as it's slightly less ugly than:
kzalloc_array(array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
kzalloc(4 * 1024, gfp)
though any constants defined via macros get caught up in the conversion.
Any factors with a sizeof() of "unsigned char", "char", and "u8" were
dropped, since they're redundant.
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
type TYPE;
expression THING, E;
@@
(
kzalloc(
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
kzalloc(
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression COUNT;
typedef u8;
typedef __u8;
@@
(
kzalloc(
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
kzalloc(
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(char) * COUNT
+ COUNT
, ...)
|
kzalloc(
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
identifier SIZE, COUNT;
@@
- kzalloc
+ kcalloc
(
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
kzalloc(
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
kzalloc(
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
kzalloc(
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
kzalloc(
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
identifier STRIDE, SIZE, COUNT;
@@
(
kzalloc(
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
kzalloc(
- COUNT * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
)
// Any remaining multi-factor products, first at least 3-factor products,
// when they're not all constants...
@@
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
kzalloc(
- E1 * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
)
// And then all remaining 2 factors products when they're not all constants,
// keeping sizeof() as the second factor argument.
@@
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
kzalloc(sizeof(THING) * C2, ...)
|
kzalloc(sizeof(TYPE) * C2, ...)
|
kzalloc(C1 * C2 * C3, ...)
|
kzalloc(C1 * C2, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * E2
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- (E1) * (E2)
+ E1, E2
, ...)
|
- kzalloc
+ kcalloc
(
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-12 14:03:40 -07:00
adis - > buffer = kcalloc ( indio_dev - > scan_bytes , 2 , GFP_KERNEL ) ;
2019-09-19 10:50:02 -05:00
if ( ! adis - > buffer ) {
kfree ( adis - > xfer ) ;
adis - > xfer = NULL ;
2012-11-13 13:28:00 +00:00
return - ENOMEM ;
2019-09-19 10:50:02 -05:00
}
2012-11-13 13:28:00 +00:00
rx = adis - > buffer ;
2015-11-27 14:55:56 +01:00
tx = rx + scan_count ;
2012-11-13 13:28:00 +00:00
spi_message_init ( & adis - > msg ) ;
for ( j = 0 ; j < = scan_count ; j + + ) {
adis - > xfer [ j ] . bits_per_word = 8 ;
if ( j ! = scan_count )
adis - > xfer [ j ] . cs_change = 1 ;
adis - > xfer [ j ] . len = 2 ;
2020-02-27 14:38:59 +02:00
adis - > xfer [ j ] . delay . value = adis - > data - > read_delay ;
adis - > xfer [ j ] . delay . unit = SPI_DELAY_UNIT_USECS ;
2012-11-13 13:28:00 +00:00
if ( j < scan_count )
adis - > xfer [ j ] . tx_buf = & tx [ j ] ;
if ( j > = 1 )
adis - > xfer [ j ] . rx_buf = & rx [ j - 1 ] ;
spi_message_add_tail ( & adis - > xfer [ j ] , & adis - > msg ) ;
}
chan = indio_dev - > channels ;
for ( i = 0 ; i < indio_dev - > num_channels ; i + + , chan + + ) {
if ( ! test_bit ( chan - > scan_index , scan_mask ) )
continue ;
2012-11-20 13:36:00 +00:00
if ( chan - > scan_type . storagebits = = 32 )
* tx + + = cpu_to_be16 ( ( chan - > address + 2 ) < < 8 ) ;
2012-11-13 13:28:00 +00:00
* tx + + = cpu_to_be16 ( chan - > address < < 8 ) ;
}
return 0 ;
2012-11-13 13:28:00 +00:00
}
2022-01-30 20:56:53 +00:00
EXPORT_SYMBOL_NS_GPL ( adis_update_scan_mode , IIO_ADISLIB ) ;
2012-11-13 13:28:00 +00:00
static irqreturn_t adis_trigger_handler ( int irq , void * p )
{
struct iio_poll_func * pf = p ;
struct iio_dev * indio_dev = pf - > indio_dev ;
struct adis * adis = iio_device_get_drvdata ( indio_dev ) ;
2012-11-13 13:28:00 +00:00
int ret ;
2012-11-13 13:28:00 +00:00
2012-11-20 13:36:00 +00:00
if ( adis - > data - > has_paging ) {
2019-11-22 15:24:11 +02:00
mutex_lock ( & adis - > state_lock ) ;
2012-11-20 13:36:00 +00:00
if ( adis - > current_page ! = 0 ) {
adis - > tx [ 0 ] = ADIS_WRITE_REG ( ADIS_REG_PAGE_ID ) ;
adis - > tx [ 1 ] = 0 ;
2021-04-22 12:19:06 +02:00
ret = spi_write ( adis - > spi , adis - > tx , 2 ) ;
if ( ret ) {
dev_err ( & adis - > spi - > dev , " Failed to change device page: %d \n " , ret ) ;
mutex_unlock ( & adis - > state_lock ) ;
goto irq_done ;
}
2021-04-27 10:54:50 +02:00
adis - > current_page = 0 ;
2012-11-20 13:36:00 +00:00
}
}
2012-11-13 13:28:00 +00:00
ret = spi_sync ( adis - > spi , & adis - > msg ) ;
2021-04-27 10:54:50 +02:00
if ( adis - > data - > has_paging )
2019-11-22 15:24:11 +02:00
mutex_unlock ( & adis - > state_lock ) ;
2021-04-27 10:54:51 +02:00
if ( ret ) {
dev_err ( & adis - > spi - > dev , " Failed to read data: %d " , ret ) ;
goto irq_done ;
}
2012-11-20 13:36:00 +00:00
2013-09-19 13:59:00 +01:00
iio_push_to_buffers_with_timestamp ( indio_dev , adis - > buffer ,
2022-01-22 14:09:05 +01:00
pf - > timestamp ) ;
2012-11-13 13:28:00 +00:00
2021-04-22 12:19:06 +02:00
irq_done :
2012-11-13 13:28:00 +00:00
iio_trigger_notify_done ( indio_dev - > trig ) ;
return IRQ_HANDLED ;
}
2020-04-13 10:24:40 +02:00
static void adis_buffer_cleanup ( void * arg )
{
struct adis * adis = arg ;
kfree ( adis - > buffer ) ;
kfree ( adis - > xfer ) ;
}
/**
* devm_adis_setup_buffer_and_trigger ( ) - Sets up buffer and trigger for
* the managed adis device
* @ adis : The adis device
* @ indio_dev : The IIO device
* @ trigger_handler : Optional trigger handler , may be NULL .
*
* Returns 0 on success , a negative error code otherwise .
*
2020-09-15 14:02:58 +02:00
* This function sets up the buffer and trigger for a adis devices . If
* ' trigger_handler ' is NULL the default trigger handler will be used . The
* default trigger handler will simply read the registers assigned to the
* currently active channels .
2020-04-13 10:24:40 +02:00
*/
int
devm_adis_setup_buffer_and_trigger ( struct adis * adis , struct iio_dev * indio_dev ,
irq_handler_t trigger_handler )
{
int ret ;
if ( ! trigger_handler )
trigger_handler = adis_trigger_handler ;
ret = devm_iio_triggered_buffer_setup ( & adis - > spi - > dev , indio_dev ,
& iio_pollfunc_store_time ,
trigger_handler , NULL ) ;
if ( ret )
return ret ;
if ( adis - > spi - > irq ) {
ret = devm_adis_probe_trigger ( adis , indio_dev ) ;
if ( ret )
return ret ;
}
return devm_add_action_or_reset ( & adis - > spi - > dev , adis_buffer_cleanup ,
adis ) ;
}
2022-01-30 20:56:53 +00:00
EXPORT_SYMBOL_NS_GPL ( devm_adis_setup_buffer_and_trigger , IIO_ADISLIB ) ;
2020-04-13 10:24:40 +02:00