1*94859308SScott Alfter /* 2*94859308SScott Alfter * w1_ds2406.c - w1 family 12 (DS2406) driver 3*94859308SScott Alfter * based on w1_ds2413.c by Mariusz Bialonczyk <manio@skyboo.net> 4*94859308SScott Alfter * 5*94859308SScott Alfter * Copyright (c) 2014 Scott Alfter <scott@alfter.us> 6*94859308SScott Alfter * 7*94859308SScott Alfter * This source code is licensed under the GNU General Public License, 8*94859308SScott Alfter * Version 2. See the file COPYING for more details. 9*94859308SScott Alfter */ 10*94859308SScott Alfter 11*94859308SScott Alfter #include <linux/kernel.h> 12*94859308SScott Alfter #include <linux/module.h> 13*94859308SScott Alfter #include <linux/moduleparam.h> 14*94859308SScott Alfter #include <linux/device.h> 15*94859308SScott Alfter #include <linux/types.h> 16*94859308SScott Alfter #include <linux/delay.h> 17*94859308SScott Alfter #include <linux/slab.h> 18*94859308SScott Alfter #include <linux/crc16.h> 19*94859308SScott Alfter 20*94859308SScott Alfter #include "../w1.h" 21*94859308SScott Alfter #include "../w1_int.h" 22*94859308SScott Alfter #include "../w1_family.h" 23*94859308SScott Alfter 24*94859308SScott Alfter MODULE_LICENSE("GPL"); 25*94859308SScott Alfter MODULE_AUTHOR("Scott Alfter <scott@alfter.us>"); 26*94859308SScott Alfter MODULE_DESCRIPTION("w1 family 12 driver for DS2406 2 Pin IO"); 27*94859308SScott Alfter 28*94859308SScott Alfter #define W1_F12_FUNC_READ_STATUS 0xAA 29*94859308SScott Alfter #define W1_F12_FUNC_WRITE_STATUS 0x55 30*94859308SScott Alfter 31*94859308SScott Alfter static ssize_t w1_f12_read_state( 32*94859308SScott Alfter struct file *filp, struct kobject *kobj, 33*94859308SScott Alfter struct bin_attribute *bin_attr, 34*94859308SScott Alfter char *buf, loff_t off, size_t count) 35*94859308SScott Alfter { 36*94859308SScott Alfter u8 w1_buf[6]={W1_F12_FUNC_READ_STATUS, 7, 0, 0, 0, 0}; 37*94859308SScott Alfter struct w1_slave *sl = kobj_to_w1_slave(kobj); 38*94859308SScott Alfter u16 crc=0; 39*94859308SScott Alfter int i; 40*94859308SScott Alfter ssize_t rtnval=1; 41*94859308SScott Alfter 42*94859308SScott Alfter if (off != 0) 43*94859308SScott Alfter return 0; 44*94859308SScott Alfter if (!buf) 45*94859308SScott Alfter return -EINVAL; 46*94859308SScott Alfter 47*94859308SScott Alfter mutex_lock(&sl->master->bus_mutex); 48*94859308SScott Alfter 49*94859308SScott Alfter if (w1_reset_select_slave(sl)) { 50*94859308SScott Alfter mutex_unlock(&sl->master->bus_mutex); 51*94859308SScott Alfter return -EIO; 52*94859308SScott Alfter } 53*94859308SScott Alfter 54*94859308SScott Alfter w1_write_block(sl->master, w1_buf, 3); 55*94859308SScott Alfter w1_read_block(sl->master, w1_buf+3, 3); 56*94859308SScott Alfter for (i=0; i<6; i++) 57*94859308SScott Alfter crc=crc16_byte(crc, w1_buf[i]); 58*94859308SScott Alfter if (crc==0xb001) /* good read? */ 59*94859308SScott Alfter *buf=((w1_buf[3]>>5)&3)|0x30; 60*94859308SScott Alfter else 61*94859308SScott Alfter rtnval=-EIO; 62*94859308SScott Alfter 63*94859308SScott Alfter mutex_unlock(&sl->master->bus_mutex); 64*94859308SScott Alfter 65*94859308SScott Alfter return rtnval; 66*94859308SScott Alfter } 67*94859308SScott Alfter 68*94859308SScott Alfter static ssize_t w1_f12_write_output( 69*94859308SScott Alfter struct file *filp, struct kobject *kobj, 70*94859308SScott Alfter struct bin_attribute *bin_attr, 71*94859308SScott Alfter char *buf, loff_t off, size_t count) 72*94859308SScott Alfter { 73*94859308SScott Alfter struct w1_slave *sl = kobj_to_w1_slave(kobj); 74*94859308SScott Alfter u8 w1_buf[6]={W1_F12_FUNC_WRITE_STATUS, 7, 0, 0, 0, 0}; 75*94859308SScott Alfter u16 crc=0; 76*94859308SScott Alfter int i; 77*94859308SScott Alfter ssize_t rtnval=1; 78*94859308SScott Alfter 79*94859308SScott Alfter if (count != 1 || off != 0) 80*94859308SScott Alfter return -EFAULT; 81*94859308SScott Alfter 82*94859308SScott Alfter mutex_lock(&sl->master->bus_mutex); 83*94859308SScott Alfter 84*94859308SScott Alfter if (w1_reset_select_slave(sl)) { 85*94859308SScott Alfter mutex_unlock(&sl->master->bus_mutex); 86*94859308SScott Alfter return -EIO; 87*94859308SScott Alfter } 88*94859308SScott Alfter 89*94859308SScott Alfter w1_buf[3] = (((*buf)&3)<<5)|0x1F; 90*94859308SScott Alfter w1_write_block(sl->master, w1_buf, 4); 91*94859308SScott Alfter w1_read_block(sl->master, w1_buf+4, 2); 92*94859308SScott Alfter for (i=0; i<6; i++) 93*94859308SScott Alfter crc=crc16_byte(crc, w1_buf[i]); 94*94859308SScott Alfter if (crc==0xb001) /* good read? */ 95*94859308SScott Alfter w1_write_8(sl->master, 0xFF); 96*94859308SScott Alfter else 97*94859308SScott Alfter rtnval=-EIO; 98*94859308SScott Alfter 99*94859308SScott Alfter mutex_unlock(&sl->master->bus_mutex); 100*94859308SScott Alfter return rtnval; 101*94859308SScott Alfter } 102*94859308SScott Alfter 103*94859308SScott Alfter #define NB_SYSFS_BIN_FILES 2 104*94859308SScott Alfter static struct bin_attribute w1_f12_sysfs_bin_files[NB_SYSFS_BIN_FILES] = { 105*94859308SScott Alfter { 106*94859308SScott Alfter .attr = { 107*94859308SScott Alfter .name = "state", 108*94859308SScott Alfter .mode = S_IRUGO, 109*94859308SScott Alfter }, 110*94859308SScott Alfter .size = 1, 111*94859308SScott Alfter .read = w1_f12_read_state, 112*94859308SScott Alfter }, 113*94859308SScott Alfter { 114*94859308SScott Alfter .attr = { 115*94859308SScott Alfter .name = "output", 116*94859308SScott Alfter .mode = S_IRUGO | S_IWUSR | S_IWGRP, 117*94859308SScott Alfter }, 118*94859308SScott Alfter .size = 1, 119*94859308SScott Alfter .write = w1_f12_write_output, 120*94859308SScott Alfter } 121*94859308SScott Alfter }; 122*94859308SScott Alfter 123*94859308SScott Alfter static int w1_f12_add_slave(struct w1_slave *sl) 124*94859308SScott Alfter { 125*94859308SScott Alfter int err = 0; 126*94859308SScott Alfter int i; 127*94859308SScott Alfter 128*94859308SScott Alfter for (i = 0; i < NB_SYSFS_BIN_FILES && !err; ++i) 129*94859308SScott Alfter err = sysfs_create_bin_file( 130*94859308SScott Alfter &sl->dev.kobj, 131*94859308SScott Alfter &(w1_f12_sysfs_bin_files[i])); 132*94859308SScott Alfter if (err) 133*94859308SScott Alfter while (--i >= 0) 134*94859308SScott Alfter sysfs_remove_bin_file(&sl->dev.kobj, 135*94859308SScott Alfter &(w1_f12_sysfs_bin_files[i])); 136*94859308SScott Alfter return err; 137*94859308SScott Alfter } 138*94859308SScott Alfter 139*94859308SScott Alfter static void w1_f12_remove_slave(struct w1_slave *sl) 140*94859308SScott Alfter { 141*94859308SScott Alfter int i; 142*94859308SScott Alfter for (i = NB_SYSFS_BIN_FILES - 1; i >= 0; --i) 143*94859308SScott Alfter sysfs_remove_bin_file(&sl->dev.kobj, 144*94859308SScott Alfter &(w1_f12_sysfs_bin_files[i])); 145*94859308SScott Alfter } 146*94859308SScott Alfter 147*94859308SScott Alfter static struct w1_family_ops w1_f12_fops = { 148*94859308SScott Alfter .add_slave = w1_f12_add_slave, 149*94859308SScott Alfter .remove_slave = w1_f12_remove_slave, 150*94859308SScott Alfter }; 151*94859308SScott Alfter 152*94859308SScott Alfter static struct w1_family w1_family_12 = { 153*94859308SScott Alfter .fid = W1_FAMILY_DS2406, 154*94859308SScott Alfter .fops = &w1_f12_fops, 155*94859308SScott Alfter }; 156*94859308SScott Alfter 157*94859308SScott Alfter static int __init w1_f12_init(void) 158*94859308SScott Alfter { 159*94859308SScott Alfter return w1_register_family(&w1_family_12); 160*94859308SScott Alfter } 161*94859308SScott Alfter 162*94859308SScott Alfter static void __exit w1_f12_exit(void) 163*94859308SScott Alfter { 164*94859308SScott Alfter w1_unregister_family(&w1_family_12); 165*94859308SScott Alfter } 166*94859308SScott Alfter 167*94859308SScott Alfter module_init(w1_f12_init); 168*94859308SScott Alfter module_exit(w1_f12_exit); 169