2019-05-27 09:55:06 +03:00
// SPDX-License-Identifier: GPL-2.0-or-later
2015-10-22 12:11:42 +03:00
/* -------------------------------------------------------------------------
* Copyright ( C ) 2014 - 2016 , Intel Corporation
*
* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
*/
# include <linux/module.h>
# include <linux/acpi.h>
# include <linux/i2c.h>
# include <linux/interrupt.h>
# include <linux/nfc.h>
# include <linux/delay.h>
# include <linux/gpio/consumer.h>
# include <net/nfc/nfc.h>
# include <net/nfc/nci_core.h>
# include "fdp.h"
# define FDP_I2C_DRIVER_NAME "fdp_nci_i2c"
# define FDP_DP_CLOCK_TYPE_NAME "clock-type"
# define FDP_DP_CLOCK_FREQ_NAME "clock-freq"
# define FDP_DP_FW_VSC_CFG_NAME "fw-vsc-cfg"
# define FDP_FRAME_HEADROOM 2
# define FDP_FRAME_TAILROOM 1
# define FDP_NCI_I2C_MIN_PAYLOAD 5
# define FDP_NCI_I2C_MAX_PAYLOAD 261
# define FDP_POWER_OFF 0
# define FDP_POWER_ON 1
# define fdp_nci_i2c_dump_skb(dev, prefix, skb) \
print_hex_dump ( KERN_DEBUG , prefix " : " , DUMP_PREFIX_OFFSET , \
16 , 1 , ( skb ) - > data , ( skb ) - > len , 0 )
static void fdp_nci_i2c_reset ( struct fdp_i2c_phy * phy )
{
/* Reset RST/WakeUP for at least 100 micro-second */
gpiod_set_value_cansleep ( phy - > power_gpio , FDP_POWER_OFF ) ;
usleep_range ( 1000 , 4000 ) ;
gpiod_set_value_cansleep ( phy - > power_gpio , FDP_POWER_ON ) ;
usleep_range ( 10000 , 14000 ) ;
}
static int fdp_nci_i2c_enable ( void * phy_id )
{
struct fdp_i2c_phy * phy = phy_id ;
dev_dbg ( & phy - > i2c_dev - > dev , " %s \n " , __func__ ) ;
fdp_nci_i2c_reset ( phy ) ;
return 0 ;
}
static void fdp_nci_i2c_disable ( void * phy_id )
{
struct fdp_i2c_phy * phy = phy_id ;
dev_dbg ( & phy - > i2c_dev - > dev , " %s \n " , __func__ ) ;
fdp_nci_i2c_reset ( phy ) ;
}
static void fdp_nci_i2c_add_len_lrc ( struct sk_buff * skb )
{
u8 lrc = 0 ;
u16 len , i ;
/* Add length header */
len = skb - > len ;
networking: make skb_push & __skb_push return void pointers
It seems like a historic accident that these return unsigned char *,
and in many places that means casts are required, more often than not.
Make these functions return void * and remove all the casts across
the tree, adding a (u8 *) cast only where the unsigned char pointer
was used directly, all done with the following spatch:
@@
expression SKB, LEN;
typedef u8;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
@@
- *(fn(SKB, LEN))
+ *(u8 *)fn(SKB, LEN)
@@
expression E, SKB, LEN;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
type T;
@@
- E = ((T *)(fn(SKB, LEN)))
+ E = fn(SKB, LEN)
@@
expression SKB, LEN;
identifier fn = { skb_push, __skb_push, skb_push_rcsum };
@@
- fn(SKB, LEN)[0]
+ *(u8 *)fn(SKB, LEN)
Note that the last part there converts from push(...)[0] to the
more idiomatic *(u8 *)push(...).
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:23 +03:00
* ( u8 * ) skb_push ( skb , 1 ) = len & 0xff ;
* ( u8 * ) skb_push ( skb , 1 ) = len > > 8 ;
2015-10-22 12:11:42 +03:00
/* Compute and add lrc */
for ( i = 0 ; i < len + 2 ; i + + )
lrc ^ = skb - > data [ i ] ;
networking: add and use skb_put_u8()
Joe and Bjørn suggested that it'd be nicer to not have the
cast in the fairly common case of doing
*(u8 *)skb_put(skb, 1) = c;
Add skb_put_u8() for this case, and use it across the code,
using the following spatch:
@@
expression SKB, C, S;
typedef u8;
identifier fn = {skb_put};
fresh identifier fn2 = fn ## "_u8";
@@
- *(u8 *)fn(SKB, S) = C;
+ fn2(SKB, C);
Note that due to the "S", the spatch isn't perfect, it should
have checked that S is 1, but there's also places that use a
sizeof expression like sizeof(var) or sizeof(u8) etc. Turns
out that nobody ever did something like
*(u8 *)skb_put(skb, 2) = c;
which would be wrong anyway since the second byte wouldn't be
initialized.
Suggested-by: Joe Perches <joe@perches.com>
Suggested-by: Bjørn Mork <bjorn@mork.no>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:24 +03:00
skb_put_u8 ( skb , lrc ) ;
2015-10-22 12:11:42 +03:00
}
static void fdp_nci_i2c_remove_len_lrc ( struct sk_buff * skb )
{
skb_pull ( skb , FDP_FRAME_HEADROOM ) ;
skb_trim ( skb , skb - > len - FDP_FRAME_TAILROOM ) ;
}
static int fdp_nci_i2c_write ( void * phy_id , struct sk_buff * skb )
{
struct fdp_i2c_phy * phy = phy_id ;
struct i2c_client * client = phy - > i2c_dev ;
int r ;
if ( phy - > hard_fault ! = 0 )
return phy - > hard_fault ;
fdp_nci_i2c_add_len_lrc ( skb ) ;
fdp_nci_i2c_dump_skb ( & client - > dev , " fdp_wr " , skb ) ;
r = i2c_master_send ( client , skb - > data , skb - > len ) ;
if ( r = = - EREMOTEIO ) { /* Retry, chip was in standby */
usleep_range ( 1000 , 4000 ) ;
r = i2c_master_send ( client , skb - > data , skb - > len ) ;
}
if ( r < 0 | | r ! = skb - > len )
dev_dbg ( & client - > dev , " %s: error err=%d len=%d \n " ,
__func__ , r , skb - > len ) ;
if ( r > = 0 ) {
if ( r ! = skb - > len ) {
phy - > hard_fault = r ;
r = - EREMOTEIO ;
} else {
r = 0 ;
}
}
fdp_nci_i2c_remove_len_lrc ( skb ) ;
return r ;
}
static struct nfc_phy_ops i2c_phy_ops = {
. write = fdp_nci_i2c_write ,
. enable = fdp_nci_i2c_enable ,
. disable = fdp_nci_i2c_disable ,
} ;
static int fdp_nci_i2c_read ( struct fdp_i2c_phy * phy , struct sk_buff * * skb )
{
int r , len ;
u8 tmp [ FDP_NCI_I2C_MAX_PAYLOAD ] , lrc , k ;
u16 i ;
struct i2c_client * client = phy - > i2c_dev ;
* skb = NULL ;
/* Read the length packet and the data packet */
for ( k = 0 ; k < 2 ; k + + ) {
len = phy - > next_read_size ;
r = i2c_master_recv ( client , tmp , len ) ;
if ( r ! = len ) {
dev_dbg ( & client - > dev , " %s: i2c recv err: %d \n " ,
__func__ , r ) ;
goto flush ;
}
/* Check packet integruty */
for ( lrc = i = 0 ; i < r ; i + + )
lrc ^ = tmp [ i ] ;
/*
* LRC check failed . This may due to transmission error or
2021-01-23 10:48:35 +03:00
* desynchronization between driver and FDP . Drop the packet
2015-10-22 12:11:42 +03:00
* and force resynchronization
*/
if ( lrc ) {
dev_dbg ( & client - > dev , " %s: corrupted packet \n " ,
__func__ ) ;
phy - > next_read_size = 5 ;
goto flush ;
}
/* Packet that contains a length */
if ( tmp [ 0 ] = = 0 & & tmp [ 1 ] = = 0 ) {
phy - > next_read_size = ( tmp [ 2 ] < < 8 ) + tmp [ 3 ] + 3 ;
} else {
phy - > next_read_size = FDP_NCI_I2C_MIN_PAYLOAD ;
* skb = alloc_skb ( len , GFP_KERNEL ) ;
if ( * skb = = NULL ) {
r = - ENOMEM ;
goto flush ;
}
networking: introduce and use skb_put_data()
A common pattern with skb_put() is to just want to memcpy()
some data into the new space, introduce skb_put_data() for
this.
An spatch similar to the one for skb_put_zero() converts many
of the places using it:
@@
identifier p, p2;
expression len, skb, data;
type t, t2;
@@
(
-p = skb_put(skb, len);
+p = skb_put_data(skb, data, len);
|
-p = (t)skb_put(skb, len);
+p = skb_put_data(skb, data, len);
)
(
p2 = (t2)p;
-memcpy(p2, data, len);
|
-memcpy(p, data, len);
)
@@
type t, t2;
identifier p, p2;
expression skb, data;
@@
t *p;
...
(
-p = skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
|
-p = (t *)skb_put(skb, sizeof(t));
+p = skb_put_data(skb, data, sizeof(t));
)
(
p2 = (t2)p;
-memcpy(p2, data, sizeof(*p));
|
-memcpy(p, data, sizeof(*p));
)
@@
expression skb, len, data;
@@
-memcpy(skb_put(skb, len), data, len);
+skb_put_data(skb, data, len);
(again, manually post-processed to retain some comments)
Reviewed-by: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2017-06-16 15:29:20 +03:00
skb_put_data ( * skb , tmp , len ) ;
2015-10-22 12:11:42 +03:00
fdp_nci_i2c_dump_skb ( & client - > dev , " fdp_rd " , * skb ) ;
fdp_nci_i2c_remove_len_lrc ( * skb ) ;
}
}
return 0 ;
flush :
/* Flush the remaining data */
if ( i2c_master_recv ( client , tmp , sizeof ( tmp ) ) < 0 )
r = - EREMOTEIO ;
return r ;
}
static irqreturn_t fdp_nci_i2c_irq_thread_fn ( int irq , void * phy_id )
{
struct fdp_i2c_phy * phy = phy_id ;
struct i2c_client * client ;
struct sk_buff * skb ;
int r ;
if ( ! phy | | irq ! = phy - > i2c_dev - > irq ) {
WARN_ON_ONCE ( 1 ) ;
return IRQ_NONE ;
}
2016-12-21 00:09:04 +03:00
client = phy - > i2c_dev ;
dev_dbg ( & client - > dev , " %s \n " , __func__ ) ;
2015-10-22 12:11:42 +03:00
r = fdp_nci_i2c_read ( phy , & skb ) ;
if ( r = = - EREMOTEIO )
return IRQ_HANDLED ;
else if ( r = = - ENOMEM | | r = = - EBADMSG )
return IRQ_HANDLED ;
if ( skb ! = NULL )
fdp_nci_recv_frame ( phy - > ndev , skb ) ;
return IRQ_HANDLED ;
}
static void fdp_nci_i2c_read_device_properties ( struct device * dev ,
u8 * clock_type , u32 * clock_freq ,
u8 * * fw_vsc_cfg )
{
int r ;
u8 len ;
r = device_property_read_u8 ( dev , FDP_DP_CLOCK_TYPE_NAME , clock_type ) ;
if ( r ) {
dev_dbg ( dev , " Using default clock type " ) ;
* clock_type = 0 ;
}
r = device_property_read_u32 ( dev , FDP_DP_CLOCK_FREQ_NAME , clock_freq ) ;
if ( r ) {
dev_dbg ( dev , " Using default clock frequency \n " ) ;
* clock_freq = 26000 ;
}
if ( device_property_present ( dev , FDP_DP_FW_VSC_CFG_NAME ) ) {
r = device_property_read_u8 ( dev , FDP_DP_FW_VSC_CFG_NAME ,
& len ) ;
if ( r | | len < = 0 )
goto vsc_read_err ;
/* Add 1 to the length to inclue the length byte itself */
len + + ;
treewide: devm_kmalloc() -> devm_kmalloc_array()
The devm_kmalloc() function has a 2-factor argument form,
devm_kmalloc_array(). This patch replaces cases of:
devm_kmalloc(handle, a * b, gfp)
with:
devm_kmalloc_array(handle, a * b, gfp)
as well as handling cases of:
devm_kmalloc(handle, a * b * c, gfp)
with:
devm_kmalloc(handle, array3_size(a, b, c), gfp)
as it's slightly less ugly than:
devm_kmalloc_array(handle, array_size(a, b), c, gfp)
This does, however, attempt to ignore constant size factors like:
devm_kmalloc(handle, 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.
Some manual whitespace fixes were needed in this patch, as Coccinelle
really liked to write "=devm_kmalloc..." instead of "= devm_kmalloc...".
The Coccinelle script used for this was:
// Fix redundant parens around sizeof().
@@
expression HANDLE;
type TYPE;
expression THING, E;
@@
(
devm_kmalloc(HANDLE,
- (sizeof(TYPE)) * E
+ sizeof(TYPE) * E
, ...)
|
devm_kmalloc(HANDLE,
- (sizeof(THING)) * E
+ sizeof(THING) * E
, ...)
)
// Drop single-byte sizes and redundant parens.
@@
expression HANDLE;
expression COUNT;
typedef u8;
typedef __u8;
@@
(
devm_kmalloc(HANDLE,
- sizeof(u8) * (COUNT)
+ COUNT
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(__u8) * (COUNT)
+ COUNT
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(char) * (COUNT)
+ COUNT
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(unsigned char) * (COUNT)
+ COUNT
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(u8) * COUNT
+ COUNT
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(__u8) * COUNT
+ COUNT
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(char) * COUNT
+ COUNT
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(unsigned char) * COUNT
+ COUNT
, ...)
)
// 2-factor product with sizeof(type/expression) and identifier or constant.
@@
expression HANDLE;
type TYPE;
expression THING;
identifier COUNT_ID;
constant COUNT_CONST;
@@
(
- devm_kmalloc
+ devm_kmalloc_array
(HANDLE,
- sizeof(TYPE) * (COUNT_ID)
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kmalloc
+ devm_kmalloc_array
(HANDLE,
- sizeof(TYPE) * COUNT_ID
+ COUNT_ID, sizeof(TYPE)
, ...)
|
- devm_kmalloc
+ devm_kmalloc_array
(HANDLE,
- sizeof(TYPE) * (COUNT_CONST)
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kmalloc
+ devm_kmalloc_array
(HANDLE,
- sizeof(TYPE) * COUNT_CONST
+ COUNT_CONST, sizeof(TYPE)
, ...)
|
- devm_kmalloc
+ devm_kmalloc_array
(HANDLE,
- sizeof(THING) * (COUNT_ID)
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kmalloc
+ devm_kmalloc_array
(HANDLE,
- sizeof(THING) * COUNT_ID
+ COUNT_ID, sizeof(THING)
, ...)
|
- devm_kmalloc
+ devm_kmalloc_array
(HANDLE,
- sizeof(THING) * (COUNT_CONST)
+ COUNT_CONST, sizeof(THING)
, ...)
|
- devm_kmalloc
+ devm_kmalloc_array
(HANDLE,
- sizeof(THING) * COUNT_CONST
+ COUNT_CONST, sizeof(THING)
, ...)
)
// 2-factor product, only identifiers.
@@
expression HANDLE;
identifier SIZE, COUNT;
@@
- devm_kmalloc
+ devm_kmalloc_array
(HANDLE,
- SIZE * COUNT
+ COUNT, SIZE
, ...)
// 3-factor product with 1 sizeof(type) or sizeof(expression), with
// redundant parens removed.
@@
expression HANDLE;
expression THING;
identifier STRIDE, COUNT;
type TYPE;
@@
(
devm_kmalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(TYPE) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(TYPE) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(TYPE) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(TYPE))
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(THING) * (COUNT) * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(THING) * (COUNT) * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(THING) * COUNT * (STRIDE)
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(THING) * COUNT * STRIDE
+ array3_size(COUNT, STRIDE, sizeof(THING))
, ...)
)
// 3-factor product with 2 sizeof(variable), with redundant parens removed.
@@
expression HANDLE;
expression THING1, THING2;
identifier COUNT;
type TYPE1, TYPE2;
@@
(
devm_kmalloc(HANDLE,
- sizeof(TYPE1) * sizeof(TYPE2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(TYPE2))
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(THING1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(THING1), sizeof(THING2))
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * COUNT
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
|
devm_kmalloc(HANDLE,
- sizeof(TYPE1) * sizeof(THING2) * (COUNT)
+ array3_size(COUNT, sizeof(TYPE1), sizeof(THING2))
, ...)
)
// 3-factor product, only identifiers, with redundant parens removed.
@@
expression HANDLE;
identifier STRIDE, SIZE, COUNT;
@@
(
devm_kmalloc(HANDLE,
- (COUNT) * STRIDE * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kmalloc(HANDLE,
- COUNT * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kmalloc(HANDLE,
- COUNT * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kmalloc(HANDLE,
- (COUNT) * (STRIDE) * SIZE
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kmalloc(HANDLE,
- COUNT * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kmalloc(HANDLE,
- (COUNT) * STRIDE * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kmalloc(HANDLE,
- (COUNT) * (STRIDE) * (SIZE)
+ array3_size(COUNT, STRIDE, SIZE)
, ...)
|
devm_kmalloc(HANDLE,
- 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 HANDLE;
expression E1, E2, E3;
constant C1, C2, C3;
@@
(
devm_kmalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kmalloc(HANDLE,
- (E1) * E2 * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kmalloc(HANDLE,
- (E1) * (E2) * E3
+ array3_size(E1, E2, E3)
, ...)
|
devm_kmalloc(HANDLE,
- (E1) * (E2) * (E3)
+ array3_size(E1, E2, E3)
, ...)
|
devm_kmalloc(HANDLE,
- 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 HANDLE;
expression THING, E1, E2;
type TYPE;
constant C1, C2, C3;
@@
(
devm_kmalloc(HANDLE, sizeof(THING) * C2, ...)
|
devm_kmalloc(HANDLE, sizeof(TYPE) * C2, ...)
|
devm_kmalloc(HANDLE, C1 * C2 * C3, ...)
|
devm_kmalloc(HANDLE, C1 * C2, ...)
|
- devm_kmalloc
+ devm_kmalloc_array
(HANDLE,
- sizeof(TYPE) * (E2)
+ E2, sizeof(TYPE)
, ...)
|
- devm_kmalloc
+ devm_kmalloc_array
(HANDLE,
- sizeof(TYPE) * E2
+ E2, sizeof(TYPE)
, ...)
|
- devm_kmalloc
+ devm_kmalloc_array
(HANDLE,
- sizeof(THING) * (E2)
+ E2, sizeof(THING)
, ...)
|
- devm_kmalloc
+ devm_kmalloc_array
(HANDLE,
- sizeof(THING) * E2
+ E2, sizeof(THING)
, ...)
|
- devm_kmalloc
+ devm_kmalloc_array
(HANDLE,
- (E1) * E2
+ E1, E2
, ...)
|
- devm_kmalloc
+ devm_kmalloc_array
(HANDLE,
- (E1) * (E2)
+ E1, E2
, ...)
|
- devm_kmalloc
+ devm_kmalloc_array
(HANDLE,
- E1 * E2
+ E1, E2
, ...)
)
Signed-off-by: Kees Cook <keescook@chromium.org>
2018-06-13 00:04:57 +03:00
* fw_vsc_cfg = devm_kmalloc_array ( dev ,
len , sizeof ( * * fw_vsc_cfg ) ,
2015-10-22 12:11:42 +03:00
GFP_KERNEL ) ;
r = device_property_read_u8_array ( dev , FDP_DP_FW_VSC_CFG_NAME ,
* fw_vsc_cfg , len ) ;
if ( r ) {
2019-11-05 11:34:07 +03:00
devm_kfree ( dev , * fw_vsc_cfg ) ;
2015-10-22 12:11:42 +03:00
goto vsc_read_err ;
}
} else {
vsc_read_err :
dev_dbg ( dev , " FW vendor specific commands not present \n " ) ;
* fw_vsc_cfg = NULL ;
}
dev_dbg ( dev , " Clock type: %d, clock frequency: %d, VSC: %s " ,
* clock_type , * clock_freq , * fw_vsc_cfg ! = NULL ? " yes " : " no " ) ;
}
2017-06-19 13:08:51 +03:00
static const struct acpi_gpio_params power_gpios = { 0 , 0 , false } ;
static const struct acpi_gpio_mapping acpi_fdp_gpios [ ] = {
{ " power-gpios " , & power_gpios , 1 } ,
{ } ,
} ;
2017-06-19 13:08:49 +03:00
static int fdp_nci_i2c_probe ( struct i2c_client * client )
2015-10-22 12:11:42 +03:00
{
struct fdp_i2c_phy * phy ;
struct device * dev = & client - > dev ;
u8 * fw_vsc_cfg ;
u8 clock_type ;
u32 clock_freq ;
int r = 0 ;
dev_dbg ( dev , " %s \n " , __func__ ) ;
if ( ! i2c_check_functionality ( client - > adapter , I2C_FUNC_I2C ) ) {
nfc_err ( dev , " No I2C_FUNC_I2C support \n " ) ;
return - ENODEV ;
}
2015-12-24 01:45:22 +03:00
/* Checking if we have an irq */
if ( client - > irq < = 0 ) {
nfc_err ( dev , " IRQ not present \n " ) ;
return - ENODEV ;
}
2017-06-19 13:08:50 +03:00
phy = devm_kzalloc ( dev , sizeof ( struct fdp_i2c_phy ) , GFP_KERNEL ) ;
2015-10-22 12:11:42 +03:00
if ( ! phy )
return - ENOMEM ;
phy - > i2c_dev = client ;
phy - > next_read_size = FDP_NCI_I2C_MIN_PAYLOAD ;
i2c_set_clientdata ( client , phy ) ;
2017-06-19 13:08:50 +03:00
r = devm_request_threaded_irq ( dev , client - > irq ,
NULL , fdp_nci_i2c_irq_thread_fn ,
IRQF_TRIGGER_RISING | IRQF_ONESHOT ,
FDP_I2C_DRIVER_NAME , phy ) ;
2015-10-22 12:11:42 +03:00
if ( r < 0 ) {
nfc_err ( & client - > dev , " Unable to register IRQ handler \n " ) ;
return r ;
}
2017-06-19 13:08:51 +03:00
r = devm_acpi_dev_add_driver_gpios ( dev , acpi_fdp_gpios ) ;
if ( r )
dev_dbg ( dev , " Unable to add GPIO mapping table \n " ) ;
2015-10-22 12:11:42 +03:00
2017-06-19 13:08:51 +03:00
/* Requesting the power gpio */
phy - > power_gpio = devm_gpiod_get ( dev , " power " , GPIOD_OUT_LOW ) ;
2015-10-22 12:11:42 +03:00
if ( IS_ERR ( phy - > power_gpio ) ) {
nfc_err ( dev , " Power GPIO request failed \n " ) ;
return PTR_ERR ( phy - > power_gpio ) ;
}
/* read device properties to get the clock and production settings */
fdp_nci_i2c_read_device_properties ( dev , & clock_type , & clock_freq ,
& fw_vsc_cfg ) ;
/* Call the NFC specific probe function */
r = fdp_nci_probe ( phy , & i2c_phy_ops , & phy - > ndev ,
FDP_FRAME_HEADROOM , FDP_FRAME_TAILROOM ,
clock_type , clock_freq , fw_vsc_cfg ) ;
if ( r < 0 ) {
nfc_err ( dev , " NCI probing error \n " ) ;
return r ;
}
dev_dbg ( dev , " I2C driver loaded \n " ) ;
return 0 ;
}
static int fdp_nci_i2c_remove ( struct i2c_client * client )
{
struct fdp_i2c_phy * phy = i2c_get_clientdata ( client ) ;
dev_dbg ( & client - > dev , " %s \n " , __func__ ) ;
fdp_nci_remove ( phy - > ndev ) ;
fdp_nci_i2c_disable ( phy ) ;
return 0 ;
}
static const struct acpi_device_id fdp_nci_i2c_acpi_match [ ] = {
{ " INT339A " , 0 } ,
{ }
} ;
MODULE_DEVICE_TABLE ( acpi , fdp_nci_i2c_acpi_match ) ;
static struct i2c_driver fdp_nci_i2c_driver = {
. driver = {
. name = FDP_I2C_DRIVER_NAME ,
. acpi_match_table = ACPI_PTR ( fdp_nci_i2c_acpi_match ) ,
} ,
2017-06-19 13:08:49 +03:00
. probe_new = fdp_nci_i2c_probe ,
2015-10-22 12:11:42 +03:00
. remove = fdp_nci_i2c_remove ,
} ;
module_i2c_driver ( fdp_nci_i2c_driver ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_DESCRIPTION ( " I2C driver for Intel Fields Peak NFC controller " ) ;
MODULE_AUTHOR ( " Robert Dolca <robert.dolca@intel.com> " ) ;