2019-06-03 08:44:46 +03:00
// SPDX-License-Identifier: GPL-2.0-only
2013-02-28 05:05:47 +04:00
/*
* w1_ds2413 . c - w1 family 3 a ( DS2413 ) driver
* based on w1_ds2408 . c by Jean - Francois Dagenais < dagenaisj @ sonatest . com >
*
* Copyright ( c ) 2013 Mariusz Bialonczyk < manio @ skyboo . net >
*/
# include <linux/kernel.h>
# include <linux/module.h>
# include <linux/moduleparam.h>
# include <linux/device.h>
# include <linux/types.h>
# include <linux/delay.h>
# include <linux/slab.h>
2017-06-05 16:52:08 +03:00
# include <linux/w1.h>
# define W1_FAMILY_DS2413 0x3A
2013-02-28 05:05:47 +04:00
# define W1_F3A_RETRIES 3
# define W1_F3A_FUNC_PIO_ACCESS_READ 0xF5
# define W1_F3A_FUNC_PIO_ACCESS_WRITE 0x5A
# define W1_F3A_SUCCESS_CONFIRM_BYTE 0xAA
2019-05-22 13:40:53 +03:00
# define W1_F3A_INVALID_PIO_STATE 0xFF
2013-02-28 05:05:47 +04:00
2013-08-22 02:44:58 +04:00
static ssize_t state_read ( struct file * filp , struct kobject * kobj ,
struct bin_attribute * bin_attr , char * buf , loff_t off ,
size_t count )
2013-02-28 05:05:47 +04:00
{
struct w1_slave * sl = kobj_to_w1_slave ( kobj ) ;
2019-05-20 10:05:56 +03:00
unsigned int retries = W1_F3A_RETRIES ;
ssize_t bytes_read = - EIO ;
2019-05-30 10:51:25 +03:00
u8 state ;
2019-05-20 10:05:56 +03:00
2013-02-28 05:05:47 +04:00
dev_dbg ( & sl - > dev ,
" Reading %s kobj: %p, off: %0#10x, count: %zu, buff addr: %p " ,
bin_attr - > attr . name , kobj , ( unsigned int ) off , count , buf ) ;
if ( off ! = 0 )
return 0 ;
if ( ! buf )
return - EINVAL ;
mutex_lock ( & sl - > master - > bus_mutex ) ;
dev_dbg ( & sl - > dev , " mutex locked " ) ;
2019-05-22 13:40:53 +03:00
next :
2019-05-20 10:05:56 +03:00
if ( w1_reset_select_slave ( sl ) )
goto out ;
2013-02-28 05:05:47 +04:00
2019-05-20 10:05:56 +03:00
while ( retries - - ) {
w1_write_8 ( sl - > master , W1_F3A_FUNC_PIO_ACCESS_READ ) ;
2013-02-28 05:05:47 +04:00
2019-05-30 10:51:25 +03:00
state = w1_read_8 ( sl - > master ) ;
if ( ( state & 0x0F ) = = ( ( ~ state > > 4 ) & 0x0F ) ) {
2019-05-22 13:40:53 +03:00
/* complement is correct */
2019-05-30 10:51:25 +03:00
* buf = state ;
2019-05-20 10:05:56 +03:00
bytes_read = 1 ;
goto out ;
2019-05-30 10:51:25 +03:00
} else if ( state = = W1_F3A_INVALID_PIO_STATE ) {
2019-05-22 13:40:53 +03:00
/* slave didn't respond, try to select it again */
dev_warn ( & sl - > dev , " slave device did not respond to PIO_ACCESS_READ, " \
" reselecting, retries left: %d \n " , retries ) ;
goto next ;
2019-05-20 10:05:56 +03:00
}
if ( w1_reset_resume_command ( sl - > master ) )
goto out ; /* unrecoverable error */
2013-02-28 05:05:47 +04:00
2019-05-20 10:05:56 +03:00
dev_warn ( & sl - > dev , " PIO_ACCESS_READ error, retries left: %d \n " , retries ) ;
}
out :
mutex_unlock ( & sl - > master - > bus_mutex ) ;
dev_dbg ( & sl - > dev , " %s, mutex unlocked, retries: %d \n " ,
( bytes_read > 0 ) ? " succeeded " : " error " , retries ) ;
return bytes_read ;
2013-02-28 05:05:47 +04:00
}
2013-08-22 02:44:58 +04:00
static BIN_ATTR_RO ( state , 1 ) ;
static ssize_t output_write ( struct file * filp , struct kobject * kobj ,
struct bin_attribute * bin_attr , char * buf ,
loff_t off , size_t count )
2013-02-28 05:05:47 +04:00
{
struct w1_slave * sl = kobj_to_w1_slave ( kobj ) ;
u8 w1_buf [ 3 ] ;
unsigned int retries = W1_F3A_RETRIES ;
2019-05-20 10:05:55 +03:00
ssize_t bytes_written = - EIO ;
2013-02-28 05:05:47 +04:00
if ( count ! = 1 | | off ! = 0 )
return - EFAULT ;
dev_dbg ( & sl - > dev , " locking mutex for write_output " ) ;
mutex_lock ( & sl - > master - > bus_mutex ) ;
dev_dbg ( & sl - > dev , " mutex locked " ) ;
if ( w1_reset_select_slave ( sl ) )
2019-05-20 10:05:55 +03:00
goto out ;
2013-02-28 05:05:47 +04:00
2023-04-15 13:42:52 +03:00
/*
* according to the DS2413 datasheet the most significant 6 bits
* should be set to " 1 " s , so do it now
*/
2013-02-28 05:05:47 +04:00
* buf = * buf | 0xFC ;
while ( retries - - ) {
w1_buf [ 0 ] = W1_F3A_FUNC_PIO_ACCESS_WRITE ;
w1_buf [ 1 ] = * buf ;
w1_buf [ 2 ] = ~ ( * buf ) ;
w1_write_block ( sl - > master , w1_buf , 3 ) ;
if ( w1_read_8 ( sl - > master ) = = W1_F3A_SUCCESS_CONFIRM_BYTE ) {
2019-05-20 10:05:55 +03:00
bytes_written = 1 ;
goto out ;
2013-02-28 05:05:47 +04:00
}
if ( w1_reset_resume_command ( sl - > master ) )
2019-05-20 10:05:55 +03:00
goto out ; /* unrecoverable error */
dev_warn ( & sl - > dev , " PIO_ACCESS_WRITE error, retries left: %d \n " , retries ) ;
2013-02-28 05:05:47 +04:00
}
2019-05-20 10:05:55 +03:00
out :
2013-02-28 05:05:47 +04:00
mutex_unlock ( & sl - > master - > bus_mutex ) ;
2019-05-20 10:05:55 +03:00
dev_dbg ( & sl - > dev , " %s, mutex unlocked, retries: %d \n " ,
( bytes_written > 0 ) ? " succeeded " : " error " , retries ) ;
return bytes_written ;
2013-02-28 05:05:47 +04:00
}
2023-04-15 13:42:54 +03:00
static BIN_ATTR ( output , 0664 , NULL , output_write , 1 ) ;
2013-08-22 02:44:58 +04:00
static struct bin_attribute * w1_f3a_bin_attrs [ ] = {
& bin_attr_state ,
& bin_attr_output ,
NULL ,
2013-02-28 05:05:47 +04:00
} ;
2013-08-22 02:44:58 +04:00
static const struct attribute_group w1_f3a_group = {
. bin_attrs = w1_f3a_bin_attrs ,
} ;
2013-02-28 05:05:47 +04:00
2013-08-22 02:44:58 +04:00
static const struct attribute_group * w1_f3a_groups [ ] = {
& w1_f3a_group ,
NULL ,
} ;
2013-02-28 05:05:47 +04:00
2020-10-04 22:32:01 +03:00
static const struct w1_family_ops w1_f3a_fops = {
2013-08-22 02:44:58 +04:00
. groups = w1_f3a_groups ,
2013-02-28 05:05:47 +04:00
} ;
static struct w1_family w1_family_3a = {
. fid = W1_FAMILY_DS2413 ,
. fops = & w1_f3a_fops ,
} ;
2016-08-03 00:07:09 +03:00
module_w1_family ( w1_family_3a ) ;
2017-05-16 23:02:12 +03:00
MODULE_AUTHOR ( " Mariusz Bialonczyk <manio@skyboo.net> " ) ;
MODULE_DESCRIPTION ( " w1 family 3a driver for DS2413 2 Pin IO " ) ;
MODULE_LICENSE ( " GPL " ) ;
MODULE_ALIAS ( " w1-family- " __stringify ( W1_FAMILY_DS2413 ) ) ;