181f6075eSEvgeniy Polyakov /* 281f6075eSEvgeniy Polyakov * dscore.c 381f6075eSEvgeniy Polyakov * 481f6075eSEvgeniy Polyakov * Copyright (c) 2004 Evgeniy Polyakov <johnpol@2ka.mipt.ru> 581f6075eSEvgeniy Polyakov * 681f6075eSEvgeniy Polyakov * 781f6075eSEvgeniy Polyakov * This program is free software; you can redistribute it and/or modify 881f6075eSEvgeniy Polyakov * it under the terms of the GNU General Public License as published by 981f6075eSEvgeniy Polyakov * the Free Software Foundation; either version 2 of the License, or 1081f6075eSEvgeniy Polyakov * (at your option) any later version. 1181f6075eSEvgeniy Polyakov * 1281f6075eSEvgeniy Polyakov * This program is distributed in the hope that it will be useful, 1381f6075eSEvgeniy Polyakov * but WITHOUT ANY WARRANTY; without even the implied warranty of 1481f6075eSEvgeniy Polyakov * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1581f6075eSEvgeniy Polyakov * GNU General Public License for more details. 1681f6075eSEvgeniy Polyakov * 1781f6075eSEvgeniy Polyakov * You should have received a copy of the GNU General Public License 1881f6075eSEvgeniy Polyakov * along with this program; if not, write to the Free Software 1981f6075eSEvgeniy Polyakov * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 2081f6075eSEvgeniy Polyakov */ 2181f6075eSEvgeniy Polyakov 2281f6075eSEvgeniy Polyakov #include <linux/module.h> 2381f6075eSEvgeniy Polyakov #include <linux/kernel.h> 2481f6075eSEvgeniy Polyakov #include <linux/mod_devicetable.h> 2581f6075eSEvgeniy Polyakov #include <linux/usb.h> 2681f6075eSEvgeniy Polyakov 2781f6075eSEvgeniy Polyakov #include "../w1_int.h" 2881f6075eSEvgeniy Polyakov #include "../w1.h" 2981f6075eSEvgeniy Polyakov 3081f6075eSEvgeniy Polyakov /* COMMAND TYPE CODES */ 3181f6075eSEvgeniy Polyakov #define CONTROL_CMD 0x00 3281f6075eSEvgeniy Polyakov #define COMM_CMD 0x01 3381f6075eSEvgeniy Polyakov #define MODE_CMD 0x02 3481f6075eSEvgeniy Polyakov 3581f6075eSEvgeniy Polyakov /* CONTROL COMMAND CODES */ 3681f6075eSEvgeniy Polyakov #define CTL_RESET_DEVICE 0x0000 3781f6075eSEvgeniy Polyakov #define CTL_START_EXE 0x0001 3881f6075eSEvgeniy Polyakov #define CTL_RESUME_EXE 0x0002 3981f6075eSEvgeniy Polyakov #define CTL_HALT_EXE_IDLE 0x0003 4081f6075eSEvgeniy Polyakov #define CTL_HALT_EXE_DONE 0x0004 4181f6075eSEvgeniy Polyakov #define CTL_FLUSH_COMM_CMDS 0x0007 4281f6075eSEvgeniy Polyakov #define CTL_FLUSH_RCV_BUFFER 0x0008 4381f6075eSEvgeniy Polyakov #define CTL_FLUSH_XMT_BUFFER 0x0009 4481f6075eSEvgeniy Polyakov #define CTL_GET_COMM_CMDS 0x000A 4581f6075eSEvgeniy Polyakov 4681f6075eSEvgeniy Polyakov /* MODE COMMAND CODES */ 4781f6075eSEvgeniy Polyakov #define MOD_PULSE_EN 0x0000 4881f6075eSEvgeniy Polyakov #define MOD_SPEED_CHANGE_EN 0x0001 4981f6075eSEvgeniy Polyakov #define MOD_1WIRE_SPEED 0x0002 5081f6075eSEvgeniy Polyakov #define MOD_STRONG_PU_DURATION 0x0003 5181f6075eSEvgeniy Polyakov #define MOD_PULLDOWN_SLEWRATE 0x0004 5281f6075eSEvgeniy Polyakov #define MOD_PROG_PULSE_DURATION 0x0005 5381f6075eSEvgeniy Polyakov #define MOD_WRITE1_LOWTIME 0x0006 5481f6075eSEvgeniy Polyakov #define MOD_DSOW0_TREC 0x0007 5581f6075eSEvgeniy Polyakov 5681f6075eSEvgeniy Polyakov /* COMMUNICATION COMMAND CODES */ 5781f6075eSEvgeniy Polyakov #define COMM_ERROR_ESCAPE 0x0601 5881f6075eSEvgeniy Polyakov #define COMM_SET_DURATION 0x0012 5981f6075eSEvgeniy Polyakov #define COMM_BIT_IO 0x0020 6081f6075eSEvgeniy Polyakov #define COMM_PULSE 0x0030 6181f6075eSEvgeniy Polyakov #define COMM_1_WIRE_RESET 0x0042 6281f6075eSEvgeniy Polyakov #define COMM_BYTE_IO 0x0052 6381f6075eSEvgeniy Polyakov #define COMM_MATCH_ACCESS 0x0064 6481f6075eSEvgeniy Polyakov #define COMM_BLOCK_IO 0x0074 6581f6075eSEvgeniy Polyakov #define COMM_READ_STRAIGHT 0x0080 6681f6075eSEvgeniy Polyakov #define COMM_DO_RELEASE 0x6092 6781f6075eSEvgeniy Polyakov #define COMM_SET_PATH 0x00A2 6881f6075eSEvgeniy Polyakov #define COMM_WRITE_SRAM_PAGE 0x00B2 6981f6075eSEvgeniy Polyakov #define COMM_WRITE_EPROM 0x00C4 7081f6075eSEvgeniy Polyakov #define COMM_READ_CRC_PROT_PAGE 0x00D4 7181f6075eSEvgeniy Polyakov #define COMM_READ_REDIRECT_PAGE_CRC 0x21E4 7281f6075eSEvgeniy Polyakov #define COMM_SEARCH_ACCESS 0x00F4 7381f6075eSEvgeniy Polyakov 7481f6075eSEvgeniy Polyakov /* Communication command bits */ 7581f6075eSEvgeniy Polyakov #define COMM_TYPE 0x0008 7681f6075eSEvgeniy Polyakov #define COMM_SE 0x0008 7781f6075eSEvgeniy Polyakov #define COMM_D 0x0008 7881f6075eSEvgeniy Polyakov #define COMM_Z 0x0008 7981f6075eSEvgeniy Polyakov #define COMM_CH 0x0008 8081f6075eSEvgeniy Polyakov #define COMM_SM 0x0008 8181f6075eSEvgeniy Polyakov #define COMM_R 0x0008 8281f6075eSEvgeniy Polyakov #define COMM_IM 0x0001 8381f6075eSEvgeniy Polyakov 8481f6075eSEvgeniy Polyakov #define COMM_PS 0x4000 8581f6075eSEvgeniy Polyakov #define COMM_PST 0x4000 8681f6075eSEvgeniy Polyakov #define COMM_CIB 0x4000 8781f6075eSEvgeniy Polyakov #define COMM_RTS 0x4000 8881f6075eSEvgeniy Polyakov #define COMM_DT 0x2000 8981f6075eSEvgeniy Polyakov #define COMM_SPU 0x1000 9081f6075eSEvgeniy Polyakov #define COMM_F 0x0800 9181f6075eSEvgeniy Polyakov #define COMM_NTP 0x0400 9281f6075eSEvgeniy Polyakov #define COMM_ICP 0x0200 9381f6075eSEvgeniy Polyakov #define COMM_RST 0x0100 9481f6075eSEvgeniy Polyakov 9581f6075eSEvgeniy Polyakov #define PULSE_PROG 0x01 9681f6075eSEvgeniy Polyakov #define PULSE_SPUE 0x02 9781f6075eSEvgeniy Polyakov 9881f6075eSEvgeniy Polyakov #define BRANCH_MAIN 0xCC 9981f6075eSEvgeniy Polyakov #define BRANCH_AUX 0x33 10081f6075eSEvgeniy Polyakov 10181f6075eSEvgeniy Polyakov /* Status flags */ 10281f6075eSEvgeniy Polyakov #define ST_SPUA 0x01 /* Strong Pull-up is active */ 10381f6075eSEvgeniy Polyakov #define ST_PRGA 0x02 /* 12V programming pulse is being generated */ 10481f6075eSEvgeniy Polyakov #define ST_12VP 0x04 /* external 12V programming voltage is present */ 10581f6075eSEvgeniy Polyakov #define ST_PMOD 0x08 /* DS2490 powered from USB and external sources */ 10681f6075eSEvgeniy Polyakov #define ST_HALT 0x10 /* DS2490 is currently halted */ 10781f6075eSEvgeniy Polyakov #define ST_IDLE 0x20 /* DS2490 is currently idle */ 10881f6075eSEvgeniy Polyakov #define ST_EPOF 0x80 10981f6075eSEvgeniy Polyakov 1104b9cf1bcSDavid Fries /* Result Register flags */ 1114b9cf1bcSDavid Fries #define RR_DETECT 0xA5 /* New device detected */ 1124b9cf1bcSDavid Fries #define RR_NRS 0x01 /* Reset no presence or ... */ 1134b9cf1bcSDavid Fries #define RR_SH 0x02 /* short on reset or set path */ 1144b9cf1bcSDavid Fries #define RR_APP 0x04 /* alarming presence on reset */ 1154b9cf1bcSDavid Fries #define RR_VPP 0x08 /* 12V expected not seen */ 1164b9cf1bcSDavid Fries #define RR_CMP 0x10 /* compare error */ 1174b9cf1bcSDavid Fries #define RR_CRC 0x20 /* CRC error detected */ 1184b9cf1bcSDavid Fries #define RR_RDP 0x40 /* redirected page */ 1194b9cf1bcSDavid Fries #define RR_EOS 0x80 /* end of search error */ 1204b9cf1bcSDavid Fries 12181f6075eSEvgeniy Polyakov #define SPEED_NORMAL 0x00 12281f6075eSEvgeniy Polyakov #define SPEED_FLEXIBLE 0x01 12381f6075eSEvgeniy Polyakov #define SPEED_OVERDRIVE 0x02 12481f6075eSEvgeniy Polyakov 12581f6075eSEvgeniy Polyakov #define NUM_EP 4 12681f6075eSEvgeniy Polyakov #define EP_CONTROL 0 12781f6075eSEvgeniy Polyakov #define EP_STATUS 1 12881f6075eSEvgeniy Polyakov #define EP_DATA_OUT 2 12981f6075eSEvgeniy Polyakov #define EP_DATA_IN 3 13081f6075eSEvgeniy Polyakov 13181f6075eSEvgeniy Polyakov struct ds_device 13281f6075eSEvgeniy Polyakov { 13381f6075eSEvgeniy Polyakov struct list_head ds_entry; 13481f6075eSEvgeniy Polyakov 13581f6075eSEvgeniy Polyakov struct usb_device *udev; 13681f6075eSEvgeniy Polyakov struct usb_interface *intf; 13781f6075eSEvgeniy Polyakov 13881f6075eSEvgeniy Polyakov int ep[NUM_EP]; 13981f6075eSEvgeniy Polyakov 1401f4ec2d7SDavid Fries /* Strong PullUp 1411f4ec2d7SDavid Fries * 0: pullup not active, else duration in milliseconds 1421f4ec2d7SDavid Fries */ 1431f4ec2d7SDavid Fries int spu_sleep; 1441f4ec2d7SDavid Fries 14581f6075eSEvgeniy Polyakov struct w1_bus_master master; 14681f6075eSEvgeniy Polyakov }; 14781f6075eSEvgeniy Polyakov 14881f6075eSEvgeniy Polyakov struct ds_status 14981f6075eSEvgeniy Polyakov { 15081f6075eSEvgeniy Polyakov u8 enable; 15181f6075eSEvgeniy Polyakov u8 speed; 15281f6075eSEvgeniy Polyakov u8 pullup_dur; 15381f6075eSEvgeniy Polyakov u8 ppuls_dur; 15481f6075eSEvgeniy Polyakov u8 pulldown_slew; 15581f6075eSEvgeniy Polyakov u8 write1_time; 15681f6075eSEvgeniy Polyakov u8 write0_time; 15781f6075eSEvgeniy Polyakov u8 reserved0; 15881f6075eSEvgeniy Polyakov u8 status; 15981f6075eSEvgeniy Polyakov u8 command0; 16081f6075eSEvgeniy Polyakov u8 command1; 16181f6075eSEvgeniy Polyakov u8 command_buffer_status; 16281f6075eSEvgeniy Polyakov u8 data_out_buffer_status; 16381f6075eSEvgeniy Polyakov u8 data_in_buffer_status; 16481f6075eSEvgeniy Polyakov u8 reserved1; 16581f6075eSEvgeniy Polyakov u8 reserved2; 16681f6075eSEvgeniy Polyakov 16781f6075eSEvgeniy Polyakov }; 16881f6075eSEvgeniy Polyakov 16981f6075eSEvgeniy Polyakov static struct usb_device_id ds_id_table [] = { 17081f6075eSEvgeniy Polyakov { USB_DEVICE(0x04fa, 0x2490) }, 17181f6075eSEvgeniy Polyakov { }, 17281f6075eSEvgeniy Polyakov }; 17381f6075eSEvgeniy Polyakov MODULE_DEVICE_TABLE(usb, ds_id_table); 17481f6075eSEvgeniy Polyakov 17581f6075eSEvgeniy Polyakov static int ds_probe(struct usb_interface *, const struct usb_device_id *); 17681f6075eSEvgeniy Polyakov static void ds_disconnect(struct usb_interface *); 17781f6075eSEvgeniy Polyakov 17881f6075eSEvgeniy Polyakov static int ds_send_control(struct ds_device *, u16, u16); 17981f6075eSEvgeniy Polyakov static int ds_send_control_cmd(struct ds_device *, u16, u16); 18081f6075eSEvgeniy Polyakov 18181f6075eSEvgeniy Polyakov static LIST_HEAD(ds_devices); 182abd52a13SEvgeniy Polyakov static DEFINE_MUTEX(ds_mutex); 18381f6075eSEvgeniy Polyakov 18481f6075eSEvgeniy Polyakov static struct usb_driver ds_driver = { 18581f6075eSEvgeniy Polyakov .name = "DS9490R", 18681f6075eSEvgeniy Polyakov .probe = ds_probe, 18781f6075eSEvgeniy Polyakov .disconnect = ds_disconnect, 18881f6075eSEvgeniy Polyakov .id_table = ds_id_table, 18981f6075eSEvgeniy Polyakov }; 19081f6075eSEvgeniy Polyakov 19181f6075eSEvgeniy Polyakov static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index) 19281f6075eSEvgeniy Polyakov { 19381f6075eSEvgeniy Polyakov int err; 19481f6075eSEvgeniy Polyakov 19581f6075eSEvgeniy Polyakov err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 19681f6075eSEvgeniy Polyakov CONTROL_CMD, 0x40, value, index, NULL, 0, 1000); 19781f6075eSEvgeniy Polyakov if (err < 0) { 19881f6075eSEvgeniy Polyakov printk(KERN_ERR "Failed to send command control message %x.%x: err=%d.\n", 19981f6075eSEvgeniy Polyakov value, index, err); 20081f6075eSEvgeniy Polyakov return err; 20181f6075eSEvgeniy Polyakov } 20281f6075eSEvgeniy Polyakov 20381f6075eSEvgeniy Polyakov return err; 20481f6075eSEvgeniy Polyakov } 2051f4ec2d7SDavid Fries 20681f6075eSEvgeniy Polyakov static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index) 20781f6075eSEvgeniy Polyakov { 20881f6075eSEvgeniy Polyakov int err; 20981f6075eSEvgeniy Polyakov 21081f6075eSEvgeniy Polyakov err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 21181f6075eSEvgeniy Polyakov MODE_CMD, 0x40, value, index, NULL, 0, 1000); 21281f6075eSEvgeniy Polyakov if (err < 0) { 21381f6075eSEvgeniy Polyakov printk(KERN_ERR "Failed to send mode control message %x.%x: err=%d.\n", 21481f6075eSEvgeniy Polyakov value, index, err); 21581f6075eSEvgeniy Polyakov return err; 21681f6075eSEvgeniy Polyakov } 21781f6075eSEvgeniy Polyakov 21881f6075eSEvgeniy Polyakov return err; 21981f6075eSEvgeniy Polyakov } 2201f4ec2d7SDavid Fries 22181f6075eSEvgeniy Polyakov static int ds_send_control(struct ds_device *dev, u16 value, u16 index) 22281f6075eSEvgeniy Polyakov { 22381f6075eSEvgeniy Polyakov int err; 22481f6075eSEvgeniy Polyakov 22581f6075eSEvgeniy Polyakov err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 22681f6075eSEvgeniy Polyakov COMM_CMD, 0x40, value, index, NULL, 0, 1000); 22781f6075eSEvgeniy Polyakov if (err < 0) { 22881f6075eSEvgeniy Polyakov printk(KERN_ERR "Failed to send control message %x.%x: err=%d.\n", 22981f6075eSEvgeniy Polyakov value, index, err); 23081f6075eSEvgeniy Polyakov return err; 23181f6075eSEvgeniy Polyakov } 23281f6075eSEvgeniy Polyakov 23381f6075eSEvgeniy Polyakov return err; 23481f6075eSEvgeniy Polyakov } 23581f6075eSEvgeniy Polyakov 23681f6075eSEvgeniy Polyakov static int ds_recv_status_nodump(struct ds_device *dev, struct ds_status *st, 23781f6075eSEvgeniy Polyakov unsigned char *buf, int size) 23881f6075eSEvgeniy Polyakov { 23981f6075eSEvgeniy Polyakov int count, err; 24081f6075eSEvgeniy Polyakov 241e9b5a495SLi Zefan memset(st, 0, sizeof(*st)); 24281f6075eSEvgeniy Polyakov 24381f6075eSEvgeniy Polyakov count = 0; 24481f6075eSEvgeniy Polyakov err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_STATUS]), buf, size, &count, 100); 24581f6075eSEvgeniy Polyakov if (err < 0) { 24681f6075eSEvgeniy Polyakov printk(KERN_ERR "Failed to read 1-wire data from 0x%x: err=%d.\n", dev->ep[EP_STATUS], err); 24781f6075eSEvgeniy Polyakov return err; 24881f6075eSEvgeniy Polyakov } 24981f6075eSEvgeniy Polyakov 25081f6075eSEvgeniy Polyakov if (count >= sizeof(*st)) 25181f6075eSEvgeniy Polyakov memcpy(st, buf, sizeof(*st)); 25281f6075eSEvgeniy Polyakov 25381f6075eSEvgeniy Polyakov return count; 25481f6075eSEvgeniy Polyakov } 25581f6075eSEvgeniy Polyakov 2564b9cf1bcSDavid Fries static inline void ds_print_msg(unsigned char *buf, unsigned char *str, int off) 25781f6075eSEvgeniy Polyakov { 2584b9cf1bcSDavid Fries printk(KERN_INFO "%45s: %8x\n", str, buf[off]); 2594b9cf1bcSDavid Fries } 26081f6075eSEvgeniy Polyakov 2614b9cf1bcSDavid Fries static void ds_dump_status(struct ds_device *dev, unsigned char *buf, int count) 2624b9cf1bcSDavid Fries { 2634b9cf1bcSDavid Fries int i; 26481f6075eSEvgeniy Polyakov 2654b9cf1bcSDavid Fries printk(KERN_INFO "0x%x: count=%d, status: ", dev->ep[EP_STATUS], count); 26681f6075eSEvgeniy Polyakov for (i=0; i<count; ++i) 26781f6075eSEvgeniy Polyakov printk("%02x ", buf[i]); 2684b9cf1bcSDavid Fries printk(KERN_INFO "\n"); 26981f6075eSEvgeniy Polyakov 27081f6075eSEvgeniy Polyakov if (count >= 16) { 2714b9cf1bcSDavid Fries ds_print_msg(buf, "enable flag", 0); 2724b9cf1bcSDavid Fries ds_print_msg(buf, "1-wire speed", 1); 2734b9cf1bcSDavid Fries ds_print_msg(buf, "strong pullup duration", 2); 2744b9cf1bcSDavid Fries ds_print_msg(buf, "programming pulse duration", 3); 2754b9cf1bcSDavid Fries ds_print_msg(buf, "pulldown slew rate control", 4); 2764b9cf1bcSDavid Fries ds_print_msg(buf, "write-1 low time", 5); 2774b9cf1bcSDavid Fries ds_print_msg(buf, "data sample offset/write-0 recovery time", 2784b9cf1bcSDavid Fries 6); 2794b9cf1bcSDavid Fries ds_print_msg(buf, "reserved (test register)", 7); 2804b9cf1bcSDavid Fries ds_print_msg(buf, "device status flags", 8); 2814b9cf1bcSDavid Fries ds_print_msg(buf, "communication command byte 1", 9); 2824b9cf1bcSDavid Fries ds_print_msg(buf, "communication command byte 2", 10); 2834b9cf1bcSDavid Fries ds_print_msg(buf, "communication command buffer status", 11); 2844b9cf1bcSDavid Fries ds_print_msg(buf, "1-wire data output buffer status", 12); 2854b9cf1bcSDavid Fries ds_print_msg(buf, "1-wire data input buffer status", 13); 2864b9cf1bcSDavid Fries ds_print_msg(buf, "reserved", 14); 2874b9cf1bcSDavid Fries ds_print_msg(buf, "reserved", 15); 28881f6075eSEvgeniy Polyakov } 2894b9cf1bcSDavid Fries for (i = 16; i < count; ++i) { 2904b9cf1bcSDavid Fries if (buf[i] == RR_DETECT) { 2914b9cf1bcSDavid Fries ds_print_msg(buf, "new device detect", i); 2924b9cf1bcSDavid Fries continue; 29381f6075eSEvgeniy Polyakov } 2944b9cf1bcSDavid Fries ds_print_msg(buf, "Result Register Value: ", i); 2954b9cf1bcSDavid Fries if (buf[i] & RR_NRS) 2964b9cf1bcSDavid Fries printk(KERN_INFO "NRS: Reset no presence or ...\n"); 2974b9cf1bcSDavid Fries if (buf[i] & RR_SH) 2984b9cf1bcSDavid Fries printk(KERN_INFO "SH: short on reset or set path\n"); 2994b9cf1bcSDavid Fries if (buf[i] & RR_APP) 3004b9cf1bcSDavid Fries printk(KERN_INFO "APP: alarming presence on reset\n"); 3014b9cf1bcSDavid Fries if (buf[i] & RR_VPP) 3024b9cf1bcSDavid Fries printk(KERN_INFO "VPP: 12V expected not seen\n"); 3034b9cf1bcSDavid Fries if (buf[i] & RR_CMP) 3044b9cf1bcSDavid Fries printk(KERN_INFO "CMP: compare error\n"); 3054b9cf1bcSDavid Fries if (buf[i] & RR_CRC) 3064b9cf1bcSDavid Fries printk(KERN_INFO "CRC: CRC error detected\n"); 3074b9cf1bcSDavid Fries if (buf[i] & RR_RDP) 3084b9cf1bcSDavid Fries printk(KERN_INFO "RDP: redirected page\n"); 3094b9cf1bcSDavid Fries if (buf[i] & RR_EOS) 3104b9cf1bcSDavid Fries printk(KERN_INFO "EOS: end of search error\n"); 3114b9cf1bcSDavid Fries } 31281f6075eSEvgeniy Polyakov } 31381f6075eSEvgeniy Polyakov 31481f6075eSEvgeniy Polyakov static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) 31581f6075eSEvgeniy Polyakov { 31681f6075eSEvgeniy Polyakov int count, err; 31781f6075eSEvgeniy Polyakov struct ds_status st; 31881f6075eSEvgeniy Polyakov 319*e464af24SDavid Fries /* Careful on size. If size is less than what is available in 320*e464af24SDavid Fries * the input buffer, the device fails the bulk transfer and 321*e464af24SDavid Fries * clears the input buffer. It could read the maximum size of 322*e464af24SDavid Fries * the data buffer, but then do you return the first, last, or 323*e464af24SDavid Fries * some set of the middle size bytes? As long as the rest of 324*e464af24SDavid Fries * the code is correct there will be size bytes waiting. A 325*e464af24SDavid Fries * call to ds_wait_status will wait until the device is idle 326*e464af24SDavid Fries * and any data to be received would have been available. 327*e464af24SDavid Fries */ 32881f6075eSEvgeniy Polyakov count = 0; 32981f6075eSEvgeniy Polyakov err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), 33081f6075eSEvgeniy Polyakov buf, size, &count, 1000); 33181f6075eSEvgeniy Polyakov if (err < 0) { 3324b9cf1bcSDavid Fries u8 buf[0x20]; 3334b9cf1bcSDavid Fries int count; 3344b9cf1bcSDavid Fries 33581f6075eSEvgeniy Polyakov printk(KERN_INFO "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); 33681f6075eSEvgeniy Polyakov usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN])); 3374b9cf1bcSDavid Fries 3384b9cf1bcSDavid Fries count = ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); 3394b9cf1bcSDavid Fries ds_dump_status(dev, buf, count); 34081f6075eSEvgeniy Polyakov return err; 34181f6075eSEvgeniy Polyakov } 34281f6075eSEvgeniy Polyakov 34381f6075eSEvgeniy Polyakov #if 0 34481f6075eSEvgeniy Polyakov { 34581f6075eSEvgeniy Polyakov int i; 34681f6075eSEvgeniy Polyakov 34781f6075eSEvgeniy Polyakov printk("%s: count=%d: ", __func__, count); 34881f6075eSEvgeniy Polyakov for (i=0; i<count; ++i) 34981f6075eSEvgeniy Polyakov printk("%02x ", buf[i]); 35081f6075eSEvgeniy Polyakov printk("\n"); 35181f6075eSEvgeniy Polyakov } 35281f6075eSEvgeniy Polyakov #endif 35381f6075eSEvgeniy Polyakov return count; 35481f6075eSEvgeniy Polyakov } 35581f6075eSEvgeniy Polyakov 35681f6075eSEvgeniy Polyakov static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len) 35781f6075eSEvgeniy Polyakov { 35881f6075eSEvgeniy Polyakov int count, err; 35981f6075eSEvgeniy Polyakov 36081f6075eSEvgeniy Polyakov count = 0; 36181f6075eSEvgeniy Polyakov err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000); 36281f6075eSEvgeniy Polyakov if (err < 0) { 36395cfaebfSDavid Fries printk(KERN_ERR "Failed to write 1-wire data to ep0x%x: " 36495cfaebfSDavid Fries "err=%d.\n", dev->ep[EP_DATA_OUT], err); 36581f6075eSEvgeniy Polyakov return err; 36681f6075eSEvgeniy Polyakov } 36781f6075eSEvgeniy Polyakov 36881f6075eSEvgeniy Polyakov return err; 36981f6075eSEvgeniy Polyakov } 37081f6075eSEvgeniy Polyakov 37181f6075eSEvgeniy Polyakov #if 0 37281f6075eSEvgeniy Polyakov 37381f6075eSEvgeniy Polyakov int ds_stop_pulse(struct ds_device *dev, int limit) 37481f6075eSEvgeniy Polyakov { 37581f6075eSEvgeniy Polyakov struct ds_status st; 37681f6075eSEvgeniy Polyakov int count = 0, err = 0; 37781f6075eSEvgeniy Polyakov u8 buf[0x20]; 37881f6075eSEvgeniy Polyakov 37981f6075eSEvgeniy Polyakov do { 38081f6075eSEvgeniy Polyakov err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0); 38181f6075eSEvgeniy Polyakov if (err) 38281f6075eSEvgeniy Polyakov break; 38381f6075eSEvgeniy Polyakov err = ds_send_control(dev, CTL_RESUME_EXE, 0); 38481f6075eSEvgeniy Polyakov if (err) 38581f6075eSEvgeniy Polyakov break; 38681f6075eSEvgeniy Polyakov err = ds_recv_status_nodump(dev, &st, buf, sizeof(buf)); 38781f6075eSEvgeniy Polyakov if (err) 38881f6075eSEvgeniy Polyakov break; 38981f6075eSEvgeniy Polyakov 39081f6075eSEvgeniy Polyakov if ((st.status & ST_SPUA) == 0) { 39181f6075eSEvgeniy Polyakov err = ds_send_control_mode(dev, MOD_PULSE_EN, 0); 39281f6075eSEvgeniy Polyakov if (err) 39381f6075eSEvgeniy Polyakov break; 39481f6075eSEvgeniy Polyakov } 39581f6075eSEvgeniy Polyakov } while(++count < limit); 39681f6075eSEvgeniy Polyakov 39781f6075eSEvgeniy Polyakov return err; 39881f6075eSEvgeniy Polyakov } 39981f6075eSEvgeniy Polyakov 40081f6075eSEvgeniy Polyakov int ds_detect(struct ds_device *dev, struct ds_status *st) 40181f6075eSEvgeniy Polyakov { 40281f6075eSEvgeniy Polyakov int err; 40381f6075eSEvgeniy Polyakov 40481f6075eSEvgeniy Polyakov err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); 40581f6075eSEvgeniy Polyakov if (err) 40681f6075eSEvgeniy Polyakov return err; 40781f6075eSEvgeniy Polyakov 40881f6075eSEvgeniy Polyakov err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0); 40981f6075eSEvgeniy Polyakov if (err) 41081f6075eSEvgeniy Polyakov return err; 41181f6075eSEvgeniy Polyakov 41281f6075eSEvgeniy Polyakov err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40); 41381f6075eSEvgeniy Polyakov if (err) 41481f6075eSEvgeniy Polyakov return err; 41581f6075eSEvgeniy Polyakov 41681f6075eSEvgeniy Polyakov err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG); 41781f6075eSEvgeniy Polyakov if (err) 41881f6075eSEvgeniy Polyakov return err; 41981f6075eSEvgeniy Polyakov 4204b9cf1bcSDavid Fries err = ds_dump_status(dev, st); 42181f6075eSEvgeniy Polyakov 42281f6075eSEvgeniy Polyakov return err; 42381f6075eSEvgeniy Polyakov } 42481f6075eSEvgeniy Polyakov 42581f6075eSEvgeniy Polyakov #endif /* 0 */ 42681f6075eSEvgeniy Polyakov 42781f6075eSEvgeniy Polyakov static int ds_wait_status(struct ds_device *dev, struct ds_status *st) 42881f6075eSEvgeniy Polyakov { 42981f6075eSEvgeniy Polyakov u8 buf[0x20]; 43081f6075eSEvgeniy Polyakov int err, count = 0; 43181f6075eSEvgeniy Polyakov 43281f6075eSEvgeniy Polyakov do { 43381f6075eSEvgeniy Polyakov err = ds_recv_status_nodump(dev, st, buf, sizeof(buf)); 43481f6075eSEvgeniy Polyakov #if 0 43581f6075eSEvgeniy Polyakov if (err >= 0) { 43681f6075eSEvgeniy Polyakov int i; 43781f6075eSEvgeniy Polyakov printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err); 43881f6075eSEvgeniy Polyakov for (i=0; i<err; ++i) 43981f6075eSEvgeniy Polyakov printk("%02x ", buf[i]); 44081f6075eSEvgeniy Polyakov printk("\n"); 44181f6075eSEvgeniy Polyakov } 44281f6075eSEvgeniy Polyakov #endif 44381f6075eSEvgeniy Polyakov } while(!(buf[0x08] & 0x20) && !(err < 0) && ++count < 100); 44481f6075eSEvgeniy Polyakov 4454b9cf1bcSDavid Fries if (err >= 16 && st->status & ST_EPOF) { 4464b9cf1bcSDavid Fries printk(KERN_INFO "Resetting device after ST_EPOF.\n"); 4474b9cf1bcSDavid Fries ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); 4484b9cf1bcSDavid Fries /* Always dump the device status. */ 4494b9cf1bcSDavid Fries count = 101; 4504b9cf1bcSDavid Fries } 45181f6075eSEvgeniy Polyakov 4524b9cf1bcSDavid Fries /* Dump the status for errors or if there is extended return data. 4534b9cf1bcSDavid Fries * The extended status includes new device detection (maybe someone 4544b9cf1bcSDavid Fries * can do something with it). 4554b9cf1bcSDavid Fries */ 4564b9cf1bcSDavid Fries if (err > 16 || count >= 100 || err < 0) 4574b9cf1bcSDavid Fries ds_dump_status(dev, buf, err); 4584b9cf1bcSDavid Fries 4594b9cf1bcSDavid Fries /* Extended data isn't an error. Well, a short is, but the dump 4604b9cf1bcSDavid Fries * would have already told the user that and we can't do anything 4614b9cf1bcSDavid Fries * about it in software anyway. 4624b9cf1bcSDavid Fries */ 4634b9cf1bcSDavid Fries if (count >= 100 || err < 0) 46481f6075eSEvgeniy Polyakov return -1; 4654b9cf1bcSDavid Fries else 46681f6075eSEvgeniy Polyakov return 0; 46781f6075eSEvgeniy Polyakov } 46881f6075eSEvgeniy Polyakov 4697a4b9706SDavid Fries static int ds_reset(struct ds_device *dev) 47081f6075eSEvgeniy Polyakov { 47181f6075eSEvgeniy Polyakov int err; 47281f6075eSEvgeniy Polyakov 47381f6075eSEvgeniy Polyakov //err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_F | COMM_IM | COMM_SE, SPEED_FLEXIBLE); 47481f6075eSEvgeniy Polyakov err = ds_send_control(dev, 0x43, SPEED_NORMAL); 47581f6075eSEvgeniy Polyakov if (err) 47681f6075eSEvgeniy Polyakov return err; 47781f6075eSEvgeniy Polyakov 47881f6075eSEvgeniy Polyakov return 0; 47981f6075eSEvgeniy Polyakov } 48081f6075eSEvgeniy Polyakov 48181f6075eSEvgeniy Polyakov #if 0 48281f6075eSEvgeniy Polyakov static int ds_set_speed(struct ds_device *dev, int speed) 48381f6075eSEvgeniy Polyakov { 48481f6075eSEvgeniy Polyakov int err; 48581f6075eSEvgeniy Polyakov 48681f6075eSEvgeniy Polyakov if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE) 48781f6075eSEvgeniy Polyakov return -EINVAL; 48881f6075eSEvgeniy Polyakov 48981f6075eSEvgeniy Polyakov if (speed != SPEED_OVERDRIVE) 49081f6075eSEvgeniy Polyakov speed = SPEED_FLEXIBLE; 49181f6075eSEvgeniy Polyakov 49281f6075eSEvgeniy Polyakov speed &= 0xff; 49381f6075eSEvgeniy Polyakov 49481f6075eSEvgeniy Polyakov err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed); 49581f6075eSEvgeniy Polyakov if (err) 49681f6075eSEvgeniy Polyakov return err; 49781f6075eSEvgeniy Polyakov 49881f6075eSEvgeniy Polyakov return err; 49981f6075eSEvgeniy Polyakov } 50081f6075eSEvgeniy Polyakov #endif /* 0 */ 50181f6075eSEvgeniy Polyakov 5021f4ec2d7SDavid Fries static int ds_set_pullup(struct ds_device *dev, int delay) 50381f6075eSEvgeniy Polyakov { 50481f6075eSEvgeniy Polyakov int err; 50581f6075eSEvgeniy Polyakov u8 del = 1 + (u8)(delay >> 4); 50681f6075eSEvgeniy Polyakov 5071f4ec2d7SDavid Fries dev->spu_sleep = 0; 5081f4ec2d7SDavid Fries err = ds_send_control_mode(dev, MOD_PULSE_EN, delay ? PULSE_SPUE : 0); 50981f6075eSEvgeniy Polyakov if (err) 51081f6075eSEvgeniy Polyakov return err; 51181f6075eSEvgeniy Polyakov 5121f4ec2d7SDavid Fries if (delay) { 51381f6075eSEvgeniy Polyakov err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del); 51481f6075eSEvgeniy Polyakov if (err) 51581f6075eSEvgeniy Polyakov return err; 51681f6075eSEvgeniy Polyakov 5171f4ec2d7SDavid Fries /* Just storing delay would not get the trunication and 5181f4ec2d7SDavid Fries * roundup. 5191f4ec2d7SDavid Fries */ 5201f4ec2d7SDavid Fries dev->spu_sleep = del<<4; 5211f4ec2d7SDavid Fries } 52281f6075eSEvgeniy Polyakov 52381f6075eSEvgeniy Polyakov return err; 52481f6075eSEvgeniy Polyakov } 52581f6075eSEvgeniy Polyakov 52681f6075eSEvgeniy Polyakov static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit) 52781f6075eSEvgeniy Polyakov { 5286e10f654SDavid Fries int err; 52981f6075eSEvgeniy Polyakov struct ds_status st; 53081f6075eSEvgeniy Polyakov 5316e10f654SDavid Fries err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit ? COMM_D : 0), 5326e10f654SDavid Fries 0); 53381f6075eSEvgeniy Polyakov if (err) 53481f6075eSEvgeniy Polyakov return err; 53581f6075eSEvgeniy Polyakov 5366e10f654SDavid Fries ds_wait_status(dev, &st); 53781f6075eSEvgeniy Polyakov 53881f6075eSEvgeniy Polyakov err = ds_recv_data(dev, tbit, sizeof(*tbit)); 53981f6075eSEvgeniy Polyakov if (err < 0) 54081f6075eSEvgeniy Polyakov return err; 54181f6075eSEvgeniy Polyakov 54281f6075eSEvgeniy Polyakov return 0; 54381f6075eSEvgeniy Polyakov } 54481f6075eSEvgeniy Polyakov 545a08e2d33SDavid Fries #if 0 54681f6075eSEvgeniy Polyakov static int ds_write_bit(struct ds_device *dev, u8 bit) 54781f6075eSEvgeniy Polyakov { 54881f6075eSEvgeniy Polyakov int err; 54981f6075eSEvgeniy Polyakov struct ds_status st; 55081f6075eSEvgeniy Polyakov 551e1c86d22SDavid Fries /* Set COMM_ICP to write without a readback. Note, this will 552e1c86d22SDavid Fries * produce one time slot, a down followed by an up with COMM_D 553e1c86d22SDavid Fries * only determing the timing. 554e1c86d22SDavid Fries */ 555e1c86d22SDavid Fries err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_ICP | 556e1c86d22SDavid Fries (bit ? COMM_D : 0), 0); 55781f6075eSEvgeniy Polyakov if (err) 55881f6075eSEvgeniy Polyakov return err; 55981f6075eSEvgeniy Polyakov 56081f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 56181f6075eSEvgeniy Polyakov 56281f6075eSEvgeniy Polyakov return 0; 56381f6075eSEvgeniy Polyakov } 564a08e2d33SDavid Fries #endif 56581f6075eSEvgeniy Polyakov 56681f6075eSEvgeniy Polyakov static int ds_write_byte(struct ds_device *dev, u8 byte) 56781f6075eSEvgeniy Polyakov { 56881f6075eSEvgeniy Polyakov int err; 56981f6075eSEvgeniy Polyakov struct ds_status st; 57081f6075eSEvgeniy Polyakov u8 rbyte; 57181f6075eSEvgeniy Polyakov 57281f6075eSEvgeniy Polyakov err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | COMM_SPU, byte); 57381f6075eSEvgeniy Polyakov if (err) 57481f6075eSEvgeniy Polyakov return err; 57581f6075eSEvgeniy Polyakov 5761f4ec2d7SDavid Fries if (dev->spu_sleep) 5771f4ec2d7SDavid Fries msleep(dev->spu_sleep); 5781f4ec2d7SDavid Fries 57981f6075eSEvgeniy Polyakov err = ds_wait_status(dev, &st); 58081f6075eSEvgeniy Polyakov if (err) 58181f6075eSEvgeniy Polyakov return err; 58281f6075eSEvgeniy Polyakov 58381f6075eSEvgeniy Polyakov err = ds_recv_data(dev, &rbyte, sizeof(rbyte)); 58481f6075eSEvgeniy Polyakov if (err < 0) 58581f6075eSEvgeniy Polyakov return err; 58681f6075eSEvgeniy Polyakov 58781f6075eSEvgeniy Polyakov return !(byte == rbyte); 58881f6075eSEvgeniy Polyakov } 58981f6075eSEvgeniy Polyakov 59081f6075eSEvgeniy Polyakov static int ds_read_byte(struct ds_device *dev, u8 *byte) 59181f6075eSEvgeniy Polyakov { 59281f6075eSEvgeniy Polyakov int err; 59381f6075eSEvgeniy Polyakov struct ds_status st; 59481f6075eSEvgeniy Polyakov 59581f6075eSEvgeniy Polyakov err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM , 0xff); 59681f6075eSEvgeniy Polyakov if (err) 59781f6075eSEvgeniy Polyakov return err; 59881f6075eSEvgeniy Polyakov 59981f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 60081f6075eSEvgeniy Polyakov 60181f6075eSEvgeniy Polyakov err = ds_recv_data(dev, byte, sizeof(*byte)); 60281f6075eSEvgeniy Polyakov if (err < 0) 60381f6075eSEvgeniy Polyakov return err; 60481f6075eSEvgeniy Polyakov 60581f6075eSEvgeniy Polyakov return 0; 60681f6075eSEvgeniy Polyakov } 60781f6075eSEvgeniy Polyakov 60881f6075eSEvgeniy Polyakov static int ds_read_block(struct ds_device *dev, u8 *buf, int len) 60981f6075eSEvgeniy Polyakov { 61081f6075eSEvgeniy Polyakov struct ds_status st; 61181f6075eSEvgeniy Polyakov int err; 61281f6075eSEvgeniy Polyakov 61381f6075eSEvgeniy Polyakov if (len > 64*1024) 61481f6075eSEvgeniy Polyakov return -E2BIG; 61581f6075eSEvgeniy Polyakov 61681f6075eSEvgeniy Polyakov memset(buf, 0xFF, len); 61781f6075eSEvgeniy Polyakov 61881f6075eSEvgeniy Polyakov err = ds_send_data(dev, buf, len); 61981f6075eSEvgeniy Polyakov if (err < 0) 62081f6075eSEvgeniy Polyakov return err; 62181f6075eSEvgeniy Polyakov 6221f4ec2d7SDavid Fries err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM, len); 62381f6075eSEvgeniy Polyakov if (err) 62481f6075eSEvgeniy Polyakov return err; 62581f6075eSEvgeniy Polyakov 62681f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 62781f6075eSEvgeniy Polyakov 62881f6075eSEvgeniy Polyakov memset(buf, 0x00, len); 62981f6075eSEvgeniy Polyakov err = ds_recv_data(dev, buf, len); 63081f6075eSEvgeniy Polyakov 63181f6075eSEvgeniy Polyakov return err; 63281f6075eSEvgeniy Polyakov } 63381f6075eSEvgeniy Polyakov 63481f6075eSEvgeniy Polyakov static int ds_write_block(struct ds_device *dev, u8 *buf, int len) 63581f6075eSEvgeniy Polyakov { 63681f6075eSEvgeniy Polyakov int err; 63781f6075eSEvgeniy Polyakov struct ds_status st; 63881f6075eSEvgeniy Polyakov 63981f6075eSEvgeniy Polyakov err = ds_send_data(dev, buf, len); 64081f6075eSEvgeniy Polyakov if (err < 0) 64181f6075eSEvgeniy Polyakov return err; 64281f6075eSEvgeniy Polyakov 64381f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 64481f6075eSEvgeniy Polyakov 64581f6075eSEvgeniy Polyakov err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | COMM_SPU, len); 64681f6075eSEvgeniy Polyakov if (err) 64781f6075eSEvgeniy Polyakov return err; 64881f6075eSEvgeniy Polyakov 6491f4ec2d7SDavid Fries if (dev->spu_sleep) 6501f4ec2d7SDavid Fries msleep(dev->spu_sleep); 6511f4ec2d7SDavid Fries 65281f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 65381f6075eSEvgeniy Polyakov 65481f6075eSEvgeniy Polyakov err = ds_recv_data(dev, buf, len); 65581f6075eSEvgeniy Polyakov if (err < 0) 65681f6075eSEvgeniy Polyakov return err; 65781f6075eSEvgeniy Polyakov 65881f6075eSEvgeniy Polyakov return !(err == len); 65981f6075eSEvgeniy Polyakov } 66081f6075eSEvgeniy Polyakov 66181f6075eSEvgeniy Polyakov #if 0 66281f6075eSEvgeniy Polyakov 66381f6075eSEvgeniy Polyakov static int ds_search(struct ds_device *dev, u64 init, u64 *buf, u8 id_number, int conditional_search) 66481f6075eSEvgeniy Polyakov { 66581f6075eSEvgeniy Polyakov int err; 66681f6075eSEvgeniy Polyakov u16 value, index; 66781f6075eSEvgeniy Polyakov struct ds_status st; 66881f6075eSEvgeniy Polyakov 66981f6075eSEvgeniy Polyakov memset(buf, 0, sizeof(buf)); 67081f6075eSEvgeniy Polyakov 67181f6075eSEvgeniy Polyakov err = ds_send_data(ds_dev, (unsigned char *)&init, 8); 67281f6075eSEvgeniy Polyakov if (err) 67381f6075eSEvgeniy Polyakov return err; 67481f6075eSEvgeniy Polyakov 67581f6075eSEvgeniy Polyakov ds_wait_status(ds_dev, &st); 67681f6075eSEvgeniy Polyakov 67781f6075eSEvgeniy Polyakov value = COMM_SEARCH_ACCESS | COMM_IM | COMM_SM | COMM_F | COMM_RTS; 67881f6075eSEvgeniy Polyakov index = (conditional_search ? 0xEC : 0xF0) | (id_number << 8); 67981f6075eSEvgeniy Polyakov err = ds_send_control(ds_dev, value, index); 68081f6075eSEvgeniy Polyakov if (err) 68181f6075eSEvgeniy Polyakov return err; 68281f6075eSEvgeniy Polyakov 68381f6075eSEvgeniy Polyakov ds_wait_status(ds_dev, &st); 68481f6075eSEvgeniy Polyakov 68581f6075eSEvgeniy Polyakov err = ds_recv_data(ds_dev, (unsigned char *)buf, 8*id_number); 68681f6075eSEvgeniy Polyakov if (err < 0) 68781f6075eSEvgeniy Polyakov return err; 68881f6075eSEvgeniy Polyakov 68981f6075eSEvgeniy Polyakov return err/8; 69081f6075eSEvgeniy Polyakov } 69181f6075eSEvgeniy Polyakov 69281f6075eSEvgeniy Polyakov static int ds_match_access(struct ds_device *dev, u64 init) 69381f6075eSEvgeniy Polyakov { 69481f6075eSEvgeniy Polyakov int err; 69581f6075eSEvgeniy Polyakov struct ds_status st; 69681f6075eSEvgeniy Polyakov 69781f6075eSEvgeniy Polyakov err = ds_send_data(dev, (unsigned char *)&init, sizeof(init)); 69881f6075eSEvgeniy Polyakov if (err) 69981f6075eSEvgeniy Polyakov return err; 70081f6075eSEvgeniy Polyakov 70181f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 70281f6075eSEvgeniy Polyakov 70381f6075eSEvgeniy Polyakov err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055); 70481f6075eSEvgeniy Polyakov if (err) 70581f6075eSEvgeniy Polyakov return err; 70681f6075eSEvgeniy Polyakov 70781f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 70881f6075eSEvgeniy Polyakov 70981f6075eSEvgeniy Polyakov return 0; 71081f6075eSEvgeniy Polyakov } 71181f6075eSEvgeniy Polyakov 71281f6075eSEvgeniy Polyakov static int ds_set_path(struct ds_device *dev, u64 init) 71381f6075eSEvgeniy Polyakov { 71481f6075eSEvgeniy Polyakov int err; 71581f6075eSEvgeniy Polyakov struct ds_status st; 71681f6075eSEvgeniy Polyakov u8 buf[9]; 71781f6075eSEvgeniy Polyakov 71881f6075eSEvgeniy Polyakov memcpy(buf, &init, 8); 71981f6075eSEvgeniy Polyakov buf[8] = BRANCH_MAIN; 72081f6075eSEvgeniy Polyakov 72181f6075eSEvgeniy Polyakov err = ds_send_data(dev, buf, sizeof(buf)); 72281f6075eSEvgeniy Polyakov if (err) 72381f6075eSEvgeniy Polyakov return err; 72481f6075eSEvgeniy Polyakov 72581f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 72681f6075eSEvgeniy Polyakov 72781f6075eSEvgeniy Polyakov err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0); 72881f6075eSEvgeniy Polyakov if (err) 72981f6075eSEvgeniy Polyakov return err; 73081f6075eSEvgeniy Polyakov 73181f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 73281f6075eSEvgeniy Polyakov 73381f6075eSEvgeniy Polyakov return 0; 73481f6075eSEvgeniy Polyakov } 73581f6075eSEvgeniy Polyakov 73681f6075eSEvgeniy Polyakov #endif /* 0 */ 73781f6075eSEvgeniy Polyakov 73881f6075eSEvgeniy Polyakov static u8 ds9490r_touch_bit(void *data, u8 bit) 73981f6075eSEvgeniy Polyakov { 74081f6075eSEvgeniy Polyakov u8 ret; 74181f6075eSEvgeniy Polyakov struct ds_device *dev = data; 74281f6075eSEvgeniy Polyakov 74381f6075eSEvgeniy Polyakov if (ds_touch_bit(dev, bit, &ret)) 74481f6075eSEvgeniy Polyakov return 0; 74581f6075eSEvgeniy Polyakov 74681f6075eSEvgeniy Polyakov return ret; 74781f6075eSEvgeniy Polyakov } 74881f6075eSEvgeniy Polyakov 749a08e2d33SDavid Fries #if 0 75081f6075eSEvgeniy Polyakov static void ds9490r_write_bit(void *data, u8 bit) 75181f6075eSEvgeniy Polyakov { 75281f6075eSEvgeniy Polyakov struct ds_device *dev = data; 75381f6075eSEvgeniy Polyakov 75481f6075eSEvgeniy Polyakov ds_write_bit(dev, bit); 75581f6075eSEvgeniy Polyakov } 75681f6075eSEvgeniy Polyakov 75781f6075eSEvgeniy Polyakov static u8 ds9490r_read_bit(void *data) 75881f6075eSEvgeniy Polyakov { 75981f6075eSEvgeniy Polyakov struct ds_device *dev = data; 76081f6075eSEvgeniy Polyakov int err; 76181f6075eSEvgeniy Polyakov u8 bit = 0; 76281f6075eSEvgeniy Polyakov 76381f6075eSEvgeniy Polyakov err = ds_touch_bit(dev, 1, &bit); 76481f6075eSEvgeniy Polyakov if (err) 76581f6075eSEvgeniy Polyakov return 0; 76681f6075eSEvgeniy Polyakov 76781f6075eSEvgeniy Polyakov return bit & 1; 76881f6075eSEvgeniy Polyakov } 769a08e2d33SDavid Fries #endif 770a08e2d33SDavid Fries 771a08e2d33SDavid Fries static void ds9490r_write_byte(void *data, u8 byte) 772a08e2d33SDavid Fries { 773a08e2d33SDavid Fries struct ds_device *dev = data; 774a08e2d33SDavid Fries 775a08e2d33SDavid Fries ds_write_byte(dev, byte); 776a08e2d33SDavid Fries } 77781f6075eSEvgeniy Polyakov 77881f6075eSEvgeniy Polyakov static u8 ds9490r_read_byte(void *data) 77981f6075eSEvgeniy Polyakov { 78081f6075eSEvgeniy Polyakov struct ds_device *dev = data; 78181f6075eSEvgeniy Polyakov int err; 78281f6075eSEvgeniy Polyakov u8 byte = 0; 78381f6075eSEvgeniy Polyakov 78481f6075eSEvgeniy Polyakov err = ds_read_byte(dev, &byte); 78581f6075eSEvgeniy Polyakov if (err) 78681f6075eSEvgeniy Polyakov return 0; 78781f6075eSEvgeniy Polyakov 78881f6075eSEvgeniy Polyakov return byte; 78981f6075eSEvgeniy Polyakov } 79081f6075eSEvgeniy Polyakov 79181f6075eSEvgeniy Polyakov static void ds9490r_write_block(void *data, const u8 *buf, int len) 79281f6075eSEvgeniy Polyakov { 79381f6075eSEvgeniy Polyakov struct ds_device *dev = data; 79481f6075eSEvgeniy Polyakov 79581f6075eSEvgeniy Polyakov ds_write_block(dev, (u8 *)buf, len); 79681f6075eSEvgeniy Polyakov } 79781f6075eSEvgeniy Polyakov 79881f6075eSEvgeniy Polyakov static u8 ds9490r_read_block(void *data, u8 *buf, int len) 79981f6075eSEvgeniy Polyakov { 80081f6075eSEvgeniy Polyakov struct ds_device *dev = data; 80181f6075eSEvgeniy Polyakov int err; 80281f6075eSEvgeniy Polyakov 80381f6075eSEvgeniy Polyakov err = ds_read_block(dev, buf, len); 80481f6075eSEvgeniy Polyakov if (err < 0) 80581f6075eSEvgeniy Polyakov return 0; 80681f6075eSEvgeniy Polyakov 80781f6075eSEvgeniy Polyakov return len; 80881f6075eSEvgeniy Polyakov } 80981f6075eSEvgeniy Polyakov 81081f6075eSEvgeniy Polyakov static u8 ds9490r_reset(void *data) 81181f6075eSEvgeniy Polyakov { 81281f6075eSEvgeniy Polyakov struct ds_device *dev = data; 81381f6075eSEvgeniy Polyakov int err; 81481f6075eSEvgeniy Polyakov 8157a4b9706SDavid Fries err = ds_reset(dev); 81681f6075eSEvgeniy Polyakov if (err) 81781f6075eSEvgeniy Polyakov return 1; 81881f6075eSEvgeniy Polyakov 81981f6075eSEvgeniy Polyakov return 0; 82081f6075eSEvgeniy Polyakov } 82181f6075eSEvgeniy Polyakov 8221f4ec2d7SDavid Fries static u8 ds9490r_set_pullup(void *data, int delay) 8231f4ec2d7SDavid Fries { 8241f4ec2d7SDavid Fries struct ds_device *dev = data; 8251f4ec2d7SDavid Fries 8261f4ec2d7SDavid Fries if (ds_set_pullup(dev, delay)) 8271f4ec2d7SDavid Fries return 1; 8281f4ec2d7SDavid Fries 8291f4ec2d7SDavid Fries return 0; 8301f4ec2d7SDavid Fries } 8311f4ec2d7SDavid Fries 83281f6075eSEvgeniy Polyakov static int ds_w1_init(struct ds_device *dev) 83381f6075eSEvgeniy Polyakov { 83481f6075eSEvgeniy Polyakov memset(&dev->master, 0, sizeof(struct w1_bus_master)); 83581f6075eSEvgeniy Polyakov 836*e464af24SDavid Fries /* Reset the device as it can be in a bad state. 837*e464af24SDavid Fries * This is necessary because a block write will wait for data 838*e464af24SDavid Fries * to be placed in the output buffer and block any later 839*e464af24SDavid Fries * commands which will keep accumulating and the device will 840*e464af24SDavid Fries * not be idle. Another case is removing the ds2490 module 841*e464af24SDavid Fries * while a bus search is in progress, somehow a few commands 842*e464af24SDavid Fries * get through, but the input transfers fail leaving data in 843*e464af24SDavid Fries * the input buffer. This will cause the next read to fail 844*e464af24SDavid Fries * see the note in ds_recv_data. 845*e464af24SDavid Fries */ 846*e464af24SDavid Fries ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); 847*e464af24SDavid Fries 84881f6075eSEvgeniy Polyakov dev->master.data = dev; 84981f6075eSEvgeniy Polyakov dev->master.touch_bit = &ds9490r_touch_bit; 850a08e2d33SDavid Fries /* read_bit and write_bit in w1_bus_master are expected to set and 851a08e2d33SDavid Fries * sample the line level. For write_bit that means it is expected to 852a08e2d33SDavid Fries * set it to that value and leave it there. ds2490 only supports an 853a08e2d33SDavid Fries * individual time slot at the lowest level. The requirement from 854a08e2d33SDavid Fries * pulling the bus state down to reading the state is 15us, something 855a08e2d33SDavid Fries * that isn't realistic on the USB bus anyway. 85681f6075eSEvgeniy Polyakov dev->master.read_bit = &ds9490r_read_bit; 85781f6075eSEvgeniy Polyakov dev->master.write_bit = &ds9490r_write_bit; 858a08e2d33SDavid Fries */ 85981f6075eSEvgeniy Polyakov dev->master.read_byte = &ds9490r_read_byte; 86081f6075eSEvgeniy Polyakov dev->master.write_byte = &ds9490r_write_byte; 86181f6075eSEvgeniy Polyakov dev->master.read_block = &ds9490r_read_block; 86281f6075eSEvgeniy Polyakov dev->master.write_block = &ds9490r_write_block; 86381f6075eSEvgeniy Polyakov dev->master.reset_bus = &ds9490r_reset; 8641f4ec2d7SDavid Fries dev->master.set_pullup = &ds9490r_set_pullup; 86581f6075eSEvgeniy Polyakov 86681f6075eSEvgeniy Polyakov return w1_add_master_device(&dev->master); 86781f6075eSEvgeniy Polyakov } 86881f6075eSEvgeniy Polyakov 86981f6075eSEvgeniy Polyakov static void ds_w1_fini(struct ds_device *dev) 87081f6075eSEvgeniy Polyakov { 87181f6075eSEvgeniy Polyakov w1_remove_master_device(&dev->master); 87281f6075eSEvgeniy Polyakov } 87381f6075eSEvgeniy Polyakov 87481f6075eSEvgeniy Polyakov static int ds_probe(struct usb_interface *intf, 87581f6075eSEvgeniy Polyakov const struct usb_device_id *udev_id) 87681f6075eSEvgeniy Polyakov { 87781f6075eSEvgeniy Polyakov struct usb_device *udev = interface_to_usbdev(intf); 87881f6075eSEvgeniy Polyakov struct usb_endpoint_descriptor *endpoint; 87981f6075eSEvgeniy Polyakov struct usb_host_interface *iface_desc; 88081f6075eSEvgeniy Polyakov struct ds_device *dev; 88181f6075eSEvgeniy Polyakov int i, err; 88281f6075eSEvgeniy Polyakov 88381f6075eSEvgeniy Polyakov dev = kmalloc(sizeof(struct ds_device), GFP_KERNEL); 88481f6075eSEvgeniy Polyakov if (!dev) { 88581f6075eSEvgeniy Polyakov printk(KERN_INFO "Failed to allocate new DS9490R structure.\n"); 88681f6075eSEvgeniy Polyakov return -ENOMEM; 88781f6075eSEvgeniy Polyakov } 8881f4ec2d7SDavid Fries dev->spu_sleep = 0; 88981f6075eSEvgeniy Polyakov dev->udev = usb_get_dev(udev); 89081f6075eSEvgeniy Polyakov if (!dev->udev) { 89181f6075eSEvgeniy Polyakov err = -ENOMEM; 89281f6075eSEvgeniy Polyakov goto err_out_free; 89381f6075eSEvgeniy Polyakov } 89481f6075eSEvgeniy Polyakov memset(dev->ep, 0, sizeof(dev->ep)); 89581f6075eSEvgeniy Polyakov 89681f6075eSEvgeniy Polyakov usb_set_intfdata(intf, dev); 89781f6075eSEvgeniy Polyakov 89881f6075eSEvgeniy Polyakov err = usb_set_interface(dev->udev, intf->altsetting[0].desc.bInterfaceNumber, 3); 89981f6075eSEvgeniy Polyakov if (err) { 90081f6075eSEvgeniy Polyakov printk(KERN_ERR "Failed to set alternative setting 3 for %d interface: err=%d.\n", 90181f6075eSEvgeniy Polyakov intf->altsetting[0].desc.bInterfaceNumber, err); 90281f6075eSEvgeniy Polyakov goto err_out_clear; 90381f6075eSEvgeniy Polyakov } 90481f6075eSEvgeniy Polyakov 90581f6075eSEvgeniy Polyakov err = usb_reset_configuration(dev->udev); 90681f6075eSEvgeniy Polyakov if (err) { 90781f6075eSEvgeniy Polyakov printk(KERN_ERR "Failed to reset configuration: err=%d.\n", err); 90881f6075eSEvgeniy Polyakov goto err_out_clear; 90981f6075eSEvgeniy Polyakov } 91081f6075eSEvgeniy Polyakov 91181f6075eSEvgeniy Polyakov iface_desc = &intf->altsetting[0]; 91281f6075eSEvgeniy Polyakov if (iface_desc->desc.bNumEndpoints != NUM_EP-1) { 91381f6075eSEvgeniy Polyakov printk(KERN_INFO "Num endpoints=%d. It is not DS9490R.\n", iface_desc->desc.bNumEndpoints); 91481f6075eSEvgeniy Polyakov err = -EINVAL; 91581f6075eSEvgeniy Polyakov goto err_out_clear; 91681f6075eSEvgeniy Polyakov } 91781f6075eSEvgeniy Polyakov 91881f6075eSEvgeniy Polyakov /* 91981f6075eSEvgeniy Polyakov * This loop doesn'd show control 0 endpoint, 92081f6075eSEvgeniy Polyakov * so we will fill only 1-3 endpoints entry. 92181f6075eSEvgeniy Polyakov */ 92281f6075eSEvgeniy Polyakov for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { 92381f6075eSEvgeniy Polyakov endpoint = &iface_desc->endpoint[i].desc; 92481f6075eSEvgeniy Polyakov 92581f6075eSEvgeniy Polyakov dev->ep[i+1] = endpoint->bEndpointAddress; 92681f6075eSEvgeniy Polyakov #if 0 92781f6075eSEvgeniy Polyakov printk("%d: addr=%x, size=%d, dir=%s, type=%x\n", 92881f6075eSEvgeniy Polyakov i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize), 92981f6075eSEvgeniy Polyakov (endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT", 93081f6075eSEvgeniy Polyakov endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); 93181f6075eSEvgeniy Polyakov #endif 93281f6075eSEvgeniy Polyakov } 93381f6075eSEvgeniy Polyakov 93481f6075eSEvgeniy Polyakov err = ds_w1_init(dev); 93581f6075eSEvgeniy Polyakov if (err) 93681f6075eSEvgeniy Polyakov goto err_out_clear; 93781f6075eSEvgeniy Polyakov 938abd52a13SEvgeniy Polyakov mutex_lock(&ds_mutex); 93981f6075eSEvgeniy Polyakov list_add_tail(&dev->ds_entry, &ds_devices); 940abd52a13SEvgeniy Polyakov mutex_unlock(&ds_mutex); 94181f6075eSEvgeniy Polyakov 94281f6075eSEvgeniy Polyakov return 0; 94381f6075eSEvgeniy Polyakov 94481f6075eSEvgeniy Polyakov err_out_clear: 94581f6075eSEvgeniy Polyakov usb_set_intfdata(intf, NULL); 94681f6075eSEvgeniy Polyakov usb_put_dev(dev->udev); 94781f6075eSEvgeniy Polyakov err_out_free: 94881f6075eSEvgeniy Polyakov kfree(dev); 94981f6075eSEvgeniy Polyakov return err; 95081f6075eSEvgeniy Polyakov } 95181f6075eSEvgeniy Polyakov 95281f6075eSEvgeniy Polyakov static void ds_disconnect(struct usb_interface *intf) 95381f6075eSEvgeniy Polyakov { 95481f6075eSEvgeniy Polyakov struct ds_device *dev; 95581f6075eSEvgeniy Polyakov 95681f6075eSEvgeniy Polyakov dev = usb_get_intfdata(intf); 95781f6075eSEvgeniy Polyakov if (!dev) 95881f6075eSEvgeniy Polyakov return; 95981f6075eSEvgeniy Polyakov 960abd52a13SEvgeniy Polyakov mutex_lock(&ds_mutex); 96181f6075eSEvgeniy Polyakov list_del(&dev->ds_entry); 962abd52a13SEvgeniy Polyakov mutex_unlock(&ds_mutex); 96381f6075eSEvgeniy Polyakov 96481f6075eSEvgeniy Polyakov ds_w1_fini(dev); 96581f6075eSEvgeniy Polyakov 96681f6075eSEvgeniy Polyakov usb_set_intfdata(intf, NULL); 96781f6075eSEvgeniy Polyakov 96881f6075eSEvgeniy Polyakov usb_put_dev(dev->udev); 96981f6075eSEvgeniy Polyakov kfree(dev); 97081f6075eSEvgeniy Polyakov } 97181f6075eSEvgeniy Polyakov 97281f6075eSEvgeniy Polyakov static int ds_init(void) 97381f6075eSEvgeniy Polyakov { 97481f6075eSEvgeniy Polyakov int err; 97581f6075eSEvgeniy Polyakov 97681f6075eSEvgeniy Polyakov err = usb_register(&ds_driver); 97781f6075eSEvgeniy Polyakov if (err) { 97881f6075eSEvgeniy Polyakov printk(KERN_INFO "Failed to register DS9490R USB device: err=%d.\n", err); 97981f6075eSEvgeniy Polyakov return err; 98081f6075eSEvgeniy Polyakov } 98181f6075eSEvgeniy Polyakov 98281f6075eSEvgeniy Polyakov return 0; 98381f6075eSEvgeniy Polyakov } 98481f6075eSEvgeniy Polyakov 98581f6075eSEvgeniy Polyakov static void ds_fini(void) 98681f6075eSEvgeniy Polyakov { 98781f6075eSEvgeniy Polyakov usb_deregister(&ds_driver); 98881f6075eSEvgeniy Polyakov } 98981f6075eSEvgeniy Polyakov 99081f6075eSEvgeniy Polyakov module_init(ds_init); 99181f6075eSEvgeniy Polyakov module_exit(ds_fini); 99281f6075eSEvgeniy Polyakov 99381f6075eSEvgeniy Polyakov MODULE_LICENSE("GPL"); 99481f6075eSEvgeniy Polyakov MODULE_AUTHOR("Evgeniy Polyakov <johnpol@2ka.mipt.ru>"); 99581f6075eSEvgeniy Polyakov MODULE_DESCRIPTION("DS2490 USB <-> W1 bus master driver (DS9490*)"); 996