11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 281f6075eSEvgeniy Polyakov /* 3f28c4e1fSDavid Fries * ds2490.c USB to one wire bridge 481f6075eSEvgeniy Polyakov * 5a8018766SEvgeniy Polyakov * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net> 681f6075eSEvgeniy Polyakov */ 781f6075eSEvgeniy Polyakov 881f6075eSEvgeniy Polyakov #include <linux/module.h> 981f6075eSEvgeniy Polyakov #include <linux/kernel.h> 1081f6075eSEvgeniy Polyakov #include <linux/mod_devicetable.h> 1181f6075eSEvgeniy Polyakov #include <linux/usb.h> 125a0e3ad6STejun Heo #include <linux/slab.h> 1381f6075eSEvgeniy Polyakov 14de0d6dbdSAndrew F. Davis #include <linux/w1.h> 1581f6075eSEvgeniy Polyakov 16f28c4e1fSDavid Fries /* USB Standard */ 17f28c4e1fSDavid Fries /* USB Control request vendor type */ 18f28c4e1fSDavid Fries #define VENDOR 0x40 19f28c4e1fSDavid Fries 2081f6075eSEvgeniy Polyakov /* COMMAND TYPE CODES */ 2181f6075eSEvgeniy Polyakov #define CONTROL_CMD 0x00 2281f6075eSEvgeniy Polyakov #define COMM_CMD 0x01 2381f6075eSEvgeniy Polyakov #define MODE_CMD 0x02 2481f6075eSEvgeniy Polyakov 2581f6075eSEvgeniy Polyakov /* CONTROL COMMAND CODES */ 2681f6075eSEvgeniy Polyakov #define CTL_RESET_DEVICE 0x0000 2781f6075eSEvgeniy Polyakov #define CTL_START_EXE 0x0001 2881f6075eSEvgeniy Polyakov #define CTL_RESUME_EXE 0x0002 2981f6075eSEvgeniy Polyakov #define CTL_HALT_EXE_IDLE 0x0003 3081f6075eSEvgeniy Polyakov #define CTL_HALT_EXE_DONE 0x0004 3181f6075eSEvgeniy Polyakov #define CTL_FLUSH_COMM_CMDS 0x0007 3281f6075eSEvgeniy Polyakov #define CTL_FLUSH_RCV_BUFFER 0x0008 3381f6075eSEvgeniy Polyakov #define CTL_FLUSH_XMT_BUFFER 0x0009 3481f6075eSEvgeniy Polyakov #define CTL_GET_COMM_CMDS 0x000A 3581f6075eSEvgeniy Polyakov 3681f6075eSEvgeniy Polyakov /* MODE COMMAND CODES */ 3781f6075eSEvgeniy Polyakov #define MOD_PULSE_EN 0x0000 3881f6075eSEvgeniy Polyakov #define MOD_SPEED_CHANGE_EN 0x0001 3981f6075eSEvgeniy Polyakov #define MOD_1WIRE_SPEED 0x0002 4081f6075eSEvgeniy Polyakov #define MOD_STRONG_PU_DURATION 0x0003 4181f6075eSEvgeniy Polyakov #define MOD_PULLDOWN_SLEWRATE 0x0004 4281f6075eSEvgeniy Polyakov #define MOD_PROG_PULSE_DURATION 0x0005 4381f6075eSEvgeniy Polyakov #define MOD_WRITE1_LOWTIME 0x0006 4481f6075eSEvgeniy Polyakov #define MOD_DSOW0_TREC 0x0007 4581f6075eSEvgeniy Polyakov 4681f6075eSEvgeniy Polyakov /* COMMUNICATION COMMAND CODES */ 4781f6075eSEvgeniy Polyakov #define COMM_ERROR_ESCAPE 0x0601 4881f6075eSEvgeniy Polyakov #define COMM_SET_DURATION 0x0012 4981f6075eSEvgeniy Polyakov #define COMM_BIT_IO 0x0020 5081f6075eSEvgeniy Polyakov #define COMM_PULSE 0x0030 5181f6075eSEvgeniy Polyakov #define COMM_1_WIRE_RESET 0x0042 5281f6075eSEvgeniy Polyakov #define COMM_BYTE_IO 0x0052 5381f6075eSEvgeniy Polyakov #define COMM_MATCH_ACCESS 0x0064 5481f6075eSEvgeniy Polyakov #define COMM_BLOCK_IO 0x0074 5581f6075eSEvgeniy Polyakov #define COMM_READ_STRAIGHT 0x0080 5681f6075eSEvgeniy Polyakov #define COMM_DO_RELEASE 0x6092 5781f6075eSEvgeniy Polyakov #define COMM_SET_PATH 0x00A2 5881f6075eSEvgeniy Polyakov #define COMM_WRITE_SRAM_PAGE 0x00B2 5981f6075eSEvgeniy Polyakov #define COMM_WRITE_EPROM 0x00C4 6081f6075eSEvgeniy Polyakov #define COMM_READ_CRC_PROT_PAGE 0x00D4 6181f6075eSEvgeniy Polyakov #define COMM_READ_REDIRECT_PAGE_CRC 0x21E4 6281f6075eSEvgeniy Polyakov #define COMM_SEARCH_ACCESS 0x00F4 6381f6075eSEvgeniy Polyakov 6481f6075eSEvgeniy Polyakov /* Communication command bits */ 6581f6075eSEvgeniy Polyakov #define COMM_TYPE 0x0008 6681f6075eSEvgeniy Polyakov #define COMM_SE 0x0008 6781f6075eSEvgeniy Polyakov #define COMM_D 0x0008 6881f6075eSEvgeniy Polyakov #define COMM_Z 0x0008 6981f6075eSEvgeniy Polyakov #define COMM_CH 0x0008 7081f6075eSEvgeniy Polyakov #define COMM_SM 0x0008 7181f6075eSEvgeniy Polyakov #define COMM_R 0x0008 7281f6075eSEvgeniy Polyakov #define COMM_IM 0x0001 7381f6075eSEvgeniy Polyakov 7481f6075eSEvgeniy Polyakov #define COMM_PS 0x4000 7581f6075eSEvgeniy Polyakov #define COMM_PST 0x4000 7681f6075eSEvgeniy Polyakov #define COMM_CIB 0x4000 7781f6075eSEvgeniy Polyakov #define COMM_RTS 0x4000 7881f6075eSEvgeniy Polyakov #define COMM_DT 0x2000 7981f6075eSEvgeniy Polyakov #define COMM_SPU 0x1000 8081f6075eSEvgeniy Polyakov #define COMM_F 0x0800 8119e7184fSDavid Fries #define COMM_NTF 0x0400 8281f6075eSEvgeniy Polyakov #define COMM_ICP 0x0200 8381f6075eSEvgeniy Polyakov #define COMM_RST 0x0100 8481f6075eSEvgeniy Polyakov 8581f6075eSEvgeniy Polyakov #define PULSE_PROG 0x01 8681f6075eSEvgeniy Polyakov #define PULSE_SPUE 0x02 8781f6075eSEvgeniy Polyakov 8881f6075eSEvgeniy Polyakov #define BRANCH_MAIN 0xCC 8981f6075eSEvgeniy Polyakov #define BRANCH_AUX 0x33 9081f6075eSEvgeniy Polyakov 9181f6075eSEvgeniy Polyakov /* Status flags */ 9281f6075eSEvgeniy Polyakov #define ST_SPUA 0x01 /* Strong Pull-up is active */ 9381f6075eSEvgeniy Polyakov #define ST_PRGA 0x02 /* 12V programming pulse is being generated */ 9481f6075eSEvgeniy Polyakov #define ST_12VP 0x04 /* external 12V programming voltage is present */ 9581f6075eSEvgeniy Polyakov #define ST_PMOD 0x08 /* DS2490 powered from USB and external sources */ 9681f6075eSEvgeniy Polyakov #define ST_HALT 0x10 /* DS2490 is currently halted */ 9781f6075eSEvgeniy Polyakov #define ST_IDLE 0x20 /* DS2490 is currently idle */ 9881f6075eSEvgeniy Polyakov #define ST_EPOF 0x80 99f28c4e1fSDavid Fries /* Status transfer size, 16 bytes status, 16 byte result flags */ 100f28c4e1fSDavid Fries #define ST_SIZE 0x20 101*d605ba72SMarc Ferland /* 1-wire data i/o fifo size, 128 bytes */ 102*d605ba72SMarc Ferland #define FIFO_SIZE 0x80 10381f6075eSEvgeniy Polyakov 1044b9cf1bcSDavid Fries /* Result Register flags */ 1054b9cf1bcSDavid Fries #define RR_DETECT 0xA5 /* New device detected */ 1064b9cf1bcSDavid Fries #define RR_NRS 0x01 /* Reset no presence or ... */ 1074b9cf1bcSDavid Fries #define RR_SH 0x02 /* short on reset or set path */ 1084b9cf1bcSDavid Fries #define RR_APP 0x04 /* alarming presence on reset */ 1094b9cf1bcSDavid Fries #define RR_VPP 0x08 /* 12V expected not seen */ 1104b9cf1bcSDavid Fries #define RR_CMP 0x10 /* compare error */ 1114b9cf1bcSDavid Fries #define RR_CRC 0x20 /* CRC error detected */ 1124b9cf1bcSDavid Fries #define RR_RDP 0x40 /* redirected page */ 1134b9cf1bcSDavid Fries #define RR_EOS 0x80 /* end of search error */ 1144b9cf1bcSDavid Fries 11581f6075eSEvgeniy Polyakov #define SPEED_NORMAL 0x00 11681f6075eSEvgeniy Polyakov #define SPEED_FLEXIBLE 0x01 11781f6075eSEvgeniy Polyakov #define SPEED_OVERDRIVE 0x02 11881f6075eSEvgeniy Polyakov 11981f6075eSEvgeniy Polyakov #define NUM_EP 4 12081f6075eSEvgeniy Polyakov #define EP_CONTROL 0 12181f6075eSEvgeniy Polyakov #define EP_STATUS 1 12281f6075eSEvgeniy Polyakov #define EP_DATA_OUT 2 12381f6075eSEvgeniy Polyakov #define EP_DATA_IN 3 12481f6075eSEvgeniy Polyakov 1257b4bcbcdSHenriette Hofmeier struct ds_device { 12681f6075eSEvgeniy Polyakov struct list_head ds_entry; 12781f6075eSEvgeniy Polyakov 12881f6075eSEvgeniy Polyakov struct usb_device *udev; 12981f6075eSEvgeniy Polyakov struct usb_interface *intf; 13081f6075eSEvgeniy Polyakov 13181f6075eSEvgeniy Polyakov int ep[NUM_EP]; 13281f6075eSEvgeniy Polyakov 1331f4ec2d7SDavid Fries /* Strong PullUp 1341f4ec2d7SDavid Fries * 0: pullup not active, else duration in milliseconds 1351f4ec2d7SDavid Fries */ 1361f4ec2d7SDavid Fries int spu_sleep; 137ade6d810SDavid Fries /* spu_bit contains COMM_SPU or 0 depending on if the strong pullup 138ade6d810SDavid Fries * should be active or not for writes. 139ade6d810SDavid Fries */ 140ade6d810SDavid Fries u16 spu_bit; 1411f4ec2d7SDavid Fries 14261cd1b4cSMaciej S. Szmigiero u8 st_buf[ST_SIZE]; 14361cd1b4cSMaciej S. Szmigiero u8 byte_buf; 14461cd1b4cSMaciej S. Szmigiero 14581f6075eSEvgeniy Polyakov struct w1_bus_master master; 14681f6075eSEvgeniy Polyakov }; 14781f6075eSEvgeniy Polyakov 1487b4bcbcdSHenriette Hofmeier struct ds_status { 14981f6075eSEvgeniy Polyakov u8 enable; 15081f6075eSEvgeniy Polyakov u8 speed; 15181f6075eSEvgeniy Polyakov u8 pullup_dur; 15281f6075eSEvgeniy Polyakov u8 ppuls_dur; 15381f6075eSEvgeniy Polyakov u8 pulldown_slew; 15481f6075eSEvgeniy Polyakov u8 write1_time; 15581f6075eSEvgeniy Polyakov u8 write0_time; 15681f6075eSEvgeniy Polyakov u8 reserved0; 15781f6075eSEvgeniy Polyakov u8 status; 15881f6075eSEvgeniy Polyakov u8 command0; 15981f6075eSEvgeniy Polyakov u8 command1; 16081f6075eSEvgeniy Polyakov u8 command_buffer_status; 16181f6075eSEvgeniy Polyakov u8 data_out_buffer_status; 16281f6075eSEvgeniy Polyakov u8 data_in_buffer_status; 16381f6075eSEvgeniy Polyakov u8 reserved1; 16481f6075eSEvgeniy Polyakov u8 reserved2; 16581f6075eSEvgeniy Polyakov }; 16681f6075eSEvgeniy Polyakov 16781f6075eSEvgeniy Polyakov static LIST_HEAD(ds_devices); 168abd52a13SEvgeniy Polyakov static DEFINE_MUTEX(ds_mutex); 16981f6075eSEvgeniy Polyakov 17081f6075eSEvgeniy Polyakov static int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index) 17181f6075eSEvgeniy Polyakov { 17281f6075eSEvgeniy Polyakov int err; 17381f6075eSEvgeniy Polyakov 17481f6075eSEvgeniy Polyakov err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 175f28c4e1fSDavid Fries CONTROL_CMD, VENDOR, value, index, NULL, 0, 1000); 17681f6075eSEvgeniy Polyakov if (err < 0) { 177f76a9ae6SChristian Vogel dev_err(&dev->udev->dev, 178f76a9ae6SChristian Vogel "Failed to send command control message %x.%x: err=%d.\n", 17981f6075eSEvgeniy Polyakov value, index, err); 18081f6075eSEvgeniy Polyakov return err; 18181f6075eSEvgeniy Polyakov } 18281f6075eSEvgeniy Polyakov 18381f6075eSEvgeniy Polyakov return err; 18481f6075eSEvgeniy Polyakov } 1851f4ec2d7SDavid Fries 18681f6075eSEvgeniy Polyakov static int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index) 18781f6075eSEvgeniy Polyakov { 18881f6075eSEvgeniy Polyakov int err; 18981f6075eSEvgeniy Polyakov 19081f6075eSEvgeniy Polyakov err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 191f28c4e1fSDavid Fries MODE_CMD, VENDOR, value, index, NULL, 0, 1000); 19281f6075eSEvgeniy Polyakov if (err < 0) { 193f76a9ae6SChristian Vogel dev_err(&dev->udev->dev, 194f76a9ae6SChristian Vogel "Failed to send mode control message %x.%x: err=%d.\n", 19581f6075eSEvgeniy Polyakov value, index, err); 19681f6075eSEvgeniy Polyakov return err; 19781f6075eSEvgeniy Polyakov } 19881f6075eSEvgeniy Polyakov 19981f6075eSEvgeniy Polyakov return err; 20081f6075eSEvgeniy Polyakov } 2011f4ec2d7SDavid Fries 20281f6075eSEvgeniy Polyakov static int ds_send_control(struct ds_device *dev, u16 value, u16 index) 20381f6075eSEvgeniy Polyakov { 20481f6075eSEvgeniy Polyakov int err; 20581f6075eSEvgeniy Polyakov 20681f6075eSEvgeniy Polyakov err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 207f28c4e1fSDavid Fries COMM_CMD, VENDOR, value, index, NULL, 0, 1000); 20881f6075eSEvgeniy Polyakov if (err < 0) { 209f76a9ae6SChristian Vogel dev_err(&dev->udev->dev, 210f76a9ae6SChristian Vogel "Failed to send control message %x.%x: err=%d.\n", 21181f6075eSEvgeniy Polyakov value, index, err); 21281f6075eSEvgeniy Polyakov return err; 21381f6075eSEvgeniy Polyakov } 21481f6075eSEvgeniy Polyakov 21581f6075eSEvgeniy Polyakov return err; 21681f6075eSEvgeniy Polyakov } 21781f6075eSEvgeniy Polyakov 218f76a9ae6SChristian Vogel static void ds_dump_status(struct ds_device *ds_dev, unsigned char *buf, int count) 21981f6075eSEvgeniy Polyakov { 220f76a9ae6SChristian Vogel struct device *dev = &ds_dev->udev->dev; 2214b9cf1bcSDavid Fries int i; 22281f6075eSEvgeniy Polyakov 223f76a9ae6SChristian Vogel dev_info(dev, "ep_status=0x%x, count=%d, status=%*phC", 224f76a9ae6SChristian Vogel ds_dev->ep[EP_STATUS], count, count, buf); 22581f6075eSEvgeniy Polyakov 22681f6075eSEvgeniy Polyakov if (count >= 16) { 227f76a9ae6SChristian Vogel dev_dbg(dev, "enable flag: 0x%02x", buf[0]); 228f76a9ae6SChristian Vogel dev_dbg(dev, "1-wire speed: 0x%02x", buf[1]); 229f76a9ae6SChristian Vogel dev_dbg(dev, "strong pullup duration: 0x%02x", buf[2]); 230f76a9ae6SChristian Vogel dev_dbg(dev, "programming pulse duration: 0x%02x", buf[3]); 231f76a9ae6SChristian Vogel dev_dbg(dev, "pulldown slew rate control: 0x%02x", buf[4]); 232f76a9ae6SChristian Vogel dev_dbg(dev, "write-1 low time: 0x%02x", buf[5]); 233f76a9ae6SChristian Vogel dev_dbg(dev, "data sample offset/write-0 recovery time: 0x%02x", buf[6]); 234f76a9ae6SChristian Vogel dev_dbg(dev, "reserved (test register): 0x%02x", buf[7]); 235f76a9ae6SChristian Vogel dev_dbg(dev, "device status flags: 0x%02x", buf[8]); 236f76a9ae6SChristian Vogel dev_dbg(dev, "communication command byte 1: 0x%02x", buf[9]); 237f76a9ae6SChristian Vogel dev_dbg(dev, "communication command byte 2: 0x%02x", buf[10]); 238f76a9ae6SChristian Vogel dev_dbg(dev, "communication command buffer status: 0x%02x", buf[11]); 239f76a9ae6SChristian Vogel dev_dbg(dev, "1-wire data output buffer status: 0x%02x", buf[12]); 240f76a9ae6SChristian Vogel dev_dbg(dev, "1-wire data input buffer status: 0x%02x", buf[13]); 241f76a9ae6SChristian Vogel dev_dbg(dev, "reserved: 0x%02x", buf[14]); 242f76a9ae6SChristian Vogel dev_dbg(dev, "reserved: 0x%02x", buf[15]); 24381f6075eSEvgeniy Polyakov } 244f76a9ae6SChristian Vogel 2454b9cf1bcSDavid Fries for (i = 16; i < count; ++i) { 2464b9cf1bcSDavid Fries if (buf[i] == RR_DETECT) { 247f76a9ae6SChristian Vogel dev_dbg(dev, "New device detect.\n"); 2484b9cf1bcSDavid Fries continue; 24981f6075eSEvgeniy Polyakov } 250f76a9ae6SChristian Vogel dev_dbg(dev, "Result Register Value: 0x%02x", buf[i]); 2514b9cf1bcSDavid Fries if (buf[i] & RR_NRS) 252f76a9ae6SChristian Vogel dev_dbg(dev, "NRS: Reset no presence or ...\n"); 2534b9cf1bcSDavid Fries if (buf[i] & RR_SH) 254f76a9ae6SChristian Vogel dev_dbg(dev, "SH: short on reset or set path\n"); 2554b9cf1bcSDavid Fries if (buf[i] & RR_APP) 256f76a9ae6SChristian Vogel dev_dbg(dev, "APP: alarming presence on reset\n"); 2574b9cf1bcSDavid Fries if (buf[i] & RR_VPP) 258f76a9ae6SChristian Vogel dev_dbg(dev, "VPP: 12V expected not seen\n"); 2594b9cf1bcSDavid Fries if (buf[i] & RR_CMP) 260f76a9ae6SChristian Vogel dev_dbg(dev, "CMP: compare error\n"); 2614b9cf1bcSDavid Fries if (buf[i] & RR_CRC) 262f76a9ae6SChristian Vogel dev_dbg(dev, "CRC: CRC error detected\n"); 2634b9cf1bcSDavid Fries if (buf[i] & RR_RDP) 264f76a9ae6SChristian Vogel dev_dbg(dev, "RDP: redirected page\n"); 2654b9cf1bcSDavid Fries if (buf[i] & RR_EOS) 266f76a9ae6SChristian Vogel dev_dbg(dev, "EOS: end of search error\n"); 2674b9cf1bcSDavid Fries } 26881f6075eSEvgeniy Polyakov } 26981f6075eSEvgeniy Polyakov 270f76a9ae6SChristian Vogel static int ds_recv_status(struct ds_device *dev, struct ds_status *st) 27161cd1b4cSMaciej S. Szmigiero { 27261cd1b4cSMaciej S. Szmigiero int count, err; 27361cd1b4cSMaciej S. Szmigiero 27461cd1b4cSMaciej S. Szmigiero if (st) 27561cd1b4cSMaciej S. Szmigiero memset(st, 0, sizeof(*st)); 27661cd1b4cSMaciej S. Szmigiero 27761cd1b4cSMaciej S. Szmigiero count = 0; 27861cd1b4cSMaciej S. Szmigiero err = usb_interrupt_msg(dev->udev, 27961cd1b4cSMaciej S. Szmigiero usb_rcvintpipe(dev->udev, 28061cd1b4cSMaciej S. Szmigiero dev->ep[EP_STATUS]), 28161cd1b4cSMaciej S. Szmigiero dev->st_buf, sizeof(dev->st_buf), 28261cd1b4cSMaciej S. Szmigiero &count, 1000); 28361cd1b4cSMaciej S. Szmigiero if (err < 0) { 284f76a9ae6SChristian Vogel dev_err(&dev->udev->dev, 285f76a9ae6SChristian Vogel "Failed to read 1-wire data from 0x%x: err=%d.\n", 28661cd1b4cSMaciej S. Szmigiero dev->ep[EP_STATUS], err); 28761cd1b4cSMaciej S. Szmigiero return err; 28861cd1b4cSMaciej S. Szmigiero } 28961cd1b4cSMaciej S. Szmigiero 29061cd1b4cSMaciej S. Szmigiero if (st && count >= sizeof(*st)) 29161cd1b4cSMaciej S. Szmigiero memcpy(st, dev->st_buf, sizeof(*st)); 29261cd1b4cSMaciej S. Szmigiero 29361cd1b4cSMaciej S. Szmigiero return count; 29461cd1b4cSMaciej S. Szmigiero } 29561cd1b4cSMaciej S. Szmigiero 296ade6d810SDavid Fries static void ds_reset_device(struct ds_device *dev) 297ade6d810SDavid Fries { 298ade6d810SDavid Fries ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); 299ade6d810SDavid Fries /* Always allow strong pullup which allow individual writes to use 300ade6d810SDavid Fries * the strong pullup. 301ade6d810SDavid Fries */ 302ade6d810SDavid Fries if (ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE)) 303f76a9ae6SChristian Vogel dev_err(&dev->udev->dev, 304f76a9ae6SChristian Vogel "%s: Error allowing strong pullup\n", __func__); 305ade6d810SDavid Fries /* Chip strong pullup time was cleared. */ 306ade6d810SDavid Fries if (dev->spu_sleep) { 307ade6d810SDavid Fries /* lower 4 bits are 0, see ds_set_pullup */ 308ade6d810SDavid Fries u8 del = dev->spu_sleep>>4; 309ad9c36beSKrzysztof Kozlowski 310ade6d810SDavid Fries if (ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del)) 311f76a9ae6SChristian Vogel dev_err(&dev->udev->dev, 312f76a9ae6SChristian Vogel "%s: Error setting duration\n", __func__); 313ade6d810SDavid Fries } 314ade6d810SDavid Fries } 315ade6d810SDavid Fries 31681f6075eSEvgeniy Polyakov static int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) 31781f6075eSEvgeniy Polyakov { 31881f6075eSEvgeniy Polyakov int count, err; 31981f6075eSEvgeniy Polyakov 320e464af24SDavid Fries /* Careful on size. If size is less than what is available in 321e464af24SDavid Fries * the input buffer, the device fails the bulk transfer and 322e464af24SDavid Fries * clears the input buffer. It could read the maximum size of 323e464af24SDavid Fries * the data buffer, but then do you return the first, last, or 324e464af24SDavid Fries * some set of the middle size bytes? As long as the rest of 325e464af24SDavid Fries * the code is correct there will be size bytes waiting. A 326e464af24SDavid Fries * call to ds_wait_status will wait until the device is idle 327e464af24SDavid Fries * and any data to be received would have been available. 328e464af24SDavid Fries */ 32981f6075eSEvgeniy Polyakov count = 0; 33081f6075eSEvgeniy Polyakov err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), 33181f6075eSEvgeniy Polyakov buf, size, &count, 1000); 33281f6075eSEvgeniy Polyakov if (err < 0) { 333f76a9ae6SChristian Vogel int recv_len; 334f76a9ae6SChristian Vogel 3356caf745dSChristian Vogel dev_info(&dev->udev->dev, "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])); 337f76a9ae6SChristian Vogel 338f76a9ae6SChristian Vogel /* status might tell us why endpoint is stuck? */ 339f76a9ae6SChristian Vogel recv_len = ds_recv_status(dev, NULL); 340f76a9ae6SChristian Vogel if (recv_len >= 0) 341f76a9ae6SChristian Vogel ds_dump_status(dev, dev->st_buf, recv_len); 342f76a9ae6SChristian Vogel 34381f6075eSEvgeniy Polyakov return err; 34481f6075eSEvgeniy Polyakov } 34581f6075eSEvgeniy Polyakov 34681f6075eSEvgeniy Polyakov #if 0 34781f6075eSEvgeniy Polyakov { 34881f6075eSEvgeniy Polyakov int i; 34981f6075eSEvgeniy Polyakov 35081f6075eSEvgeniy Polyakov printk("%s: count=%d: ", __func__, count); 35181f6075eSEvgeniy Polyakov for (i = 0; i < count; ++i) 35281f6075eSEvgeniy Polyakov printk("%02x ", buf[i]); 35381f6075eSEvgeniy Polyakov printk("\n"); 35481f6075eSEvgeniy Polyakov } 35581f6075eSEvgeniy Polyakov #endif 35681f6075eSEvgeniy Polyakov return count; 35781f6075eSEvgeniy Polyakov } 35881f6075eSEvgeniy Polyakov 35981f6075eSEvgeniy Polyakov static int ds_send_data(struct ds_device *dev, unsigned char *buf, int len) 36081f6075eSEvgeniy Polyakov { 36181f6075eSEvgeniy Polyakov int count, err; 36281f6075eSEvgeniy Polyakov 36381f6075eSEvgeniy Polyakov count = 0; 36481f6075eSEvgeniy Polyakov err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000); 36581f6075eSEvgeniy Polyakov if (err < 0) { 366f76a9ae6SChristian Vogel dev_err(&dev->udev->dev, "Failed to write 1-wire data to ep0x%x: " 36795cfaebfSDavid Fries "err=%d.\n", dev->ep[EP_DATA_OUT], err); 36881f6075eSEvgeniy Polyakov return err; 36981f6075eSEvgeniy Polyakov } 37081f6075eSEvgeniy Polyakov 37181f6075eSEvgeniy Polyakov return err; 37281f6075eSEvgeniy Polyakov } 37381f6075eSEvgeniy Polyakov 37481f6075eSEvgeniy Polyakov #if 0 37581f6075eSEvgeniy Polyakov 37681f6075eSEvgeniy Polyakov int ds_stop_pulse(struct ds_device *dev, int limit) 37781f6075eSEvgeniy Polyakov { 37881f6075eSEvgeniy Polyakov struct ds_status st; 37981f6075eSEvgeniy Polyakov int count = 0, err = 0; 38081f6075eSEvgeniy Polyakov 38181f6075eSEvgeniy Polyakov do { 38281f6075eSEvgeniy Polyakov err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0); 38381f6075eSEvgeniy Polyakov if (err) 38481f6075eSEvgeniy Polyakov break; 38581f6075eSEvgeniy Polyakov err = ds_send_control(dev, CTL_RESUME_EXE, 0); 38681f6075eSEvgeniy Polyakov if (err) 38781f6075eSEvgeniy Polyakov break; 388f76a9ae6SChristian Vogel err = ds_recv_status(dev, &st); 38981f6075eSEvgeniy Polyakov if (err) 39081f6075eSEvgeniy Polyakov break; 39181f6075eSEvgeniy Polyakov 39281f6075eSEvgeniy Polyakov if ((st.status & ST_SPUA) == 0) { 39381f6075eSEvgeniy Polyakov err = ds_send_control_mode(dev, MOD_PULSE_EN, 0); 39481f6075eSEvgeniy Polyakov if (err) 39581f6075eSEvgeniy Polyakov break; 39681f6075eSEvgeniy Polyakov } 39781f6075eSEvgeniy Polyakov } while (++count < limit); 39881f6075eSEvgeniy Polyakov 39981f6075eSEvgeniy Polyakov return err; 40081f6075eSEvgeniy Polyakov } 40181f6075eSEvgeniy Polyakov 40281f6075eSEvgeniy Polyakov int ds_detect(struct ds_device *dev, struct ds_status *st) 40381f6075eSEvgeniy Polyakov { 40481f6075eSEvgeniy Polyakov int err; 40581f6075eSEvgeniy Polyakov 40681f6075eSEvgeniy Polyakov err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); 40781f6075eSEvgeniy Polyakov if (err) 40881f6075eSEvgeniy Polyakov return err; 40981f6075eSEvgeniy Polyakov 41081f6075eSEvgeniy Polyakov err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0); 41181f6075eSEvgeniy Polyakov if (err) 41281f6075eSEvgeniy Polyakov return err; 41381f6075eSEvgeniy Polyakov 41481f6075eSEvgeniy Polyakov err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40); 41581f6075eSEvgeniy Polyakov if (err) 41681f6075eSEvgeniy Polyakov return err; 41781f6075eSEvgeniy Polyakov 41881f6075eSEvgeniy Polyakov err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG); 41981f6075eSEvgeniy Polyakov if (err) 42081f6075eSEvgeniy Polyakov return err; 42181f6075eSEvgeniy Polyakov 4224b9cf1bcSDavid Fries err = ds_dump_status(dev, st); 42381f6075eSEvgeniy Polyakov 42481f6075eSEvgeniy Polyakov return err; 42581f6075eSEvgeniy Polyakov } 42681f6075eSEvgeniy Polyakov 42781f6075eSEvgeniy Polyakov #endif /* 0 */ 42881f6075eSEvgeniy Polyakov 42981f6075eSEvgeniy Polyakov static int ds_wait_status(struct ds_device *dev, struct ds_status *st) 43081f6075eSEvgeniy Polyakov { 43181f6075eSEvgeniy Polyakov int err, count = 0; 43281f6075eSEvgeniy Polyakov 43381f6075eSEvgeniy Polyakov do { 434f28c4e1fSDavid Fries st->status = 0; 435f76a9ae6SChristian Vogel err = ds_recv_status(dev, st); 43681f6075eSEvgeniy Polyakov #if 0 43781f6075eSEvgeniy Polyakov if (err >= 0) { 43881f6075eSEvgeniy Polyakov int i; 43981f6075eSEvgeniy Polyakov printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err); 44081f6075eSEvgeniy Polyakov for (i = 0; i < err; ++i) 44161cd1b4cSMaciej S. Szmigiero printk("%02x ", dev->st_buf[i]); 44281f6075eSEvgeniy Polyakov printk("\n"); 44381f6075eSEvgeniy Polyakov } 44481f6075eSEvgeniy Polyakov #endif 445f28c4e1fSDavid Fries } while (!(st->status & ST_IDLE) && !(err < 0) && ++count < 100); 44681f6075eSEvgeniy Polyakov 4474b9cf1bcSDavid Fries if (err >= 16 && st->status & ST_EPOF) { 448f76a9ae6SChristian Vogel dev_info(&dev->udev->dev, "Resetting device after ST_EPOF.\n"); 449ade6d810SDavid Fries ds_reset_device(dev); 4504b9cf1bcSDavid Fries /* Always dump the device status. */ 4514b9cf1bcSDavid Fries count = 101; 4524b9cf1bcSDavid Fries } 45381f6075eSEvgeniy Polyakov 4544b9cf1bcSDavid Fries /* Dump the status for errors or if there is extended return data. 4554b9cf1bcSDavid Fries * The extended status includes new device detection (maybe someone 4564b9cf1bcSDavid Fries * can do something with it). 4574b9cf1bcSDavid Fries */ 4584b9cf1bcSDavid Fries if (err > 16 || count >= 100 || err < 0) 45961cd1b4cSMaciej S. Szmigiero ds_dump_status(dev, dev->st_buf, err); 4604b9cf1bcSDavid Fries 4614b9cf1bcSDavid Fries /* Extended data isn't an error. Well, a short is, but the dump 4624b9cf1bcSDavid Fries * would have already told the user that and we can't do anything 4634b9cf1bcSDavid Fries * about it in software anyway. 4644b9cf1bcSDavid Fries */ 4654b9cf1bcSDavid Fries if (count >= 100 || err < 0) 46681f6075eSEvgeniy Polyakov return -1; 4674b9cf1bcSDavid Fries else 46881f6075eSEvgeniy Polyakov return 0; 46981f6075eSEvgeniy Polyakov } 47081f6075eSEvgeniy Polyakov 4717a4b9706SDavid Fries static int ds_reset(struct ds_device *dev) 47281f6075eSEvgeniy Polyakov { 47381f6075eSEvgeniy Polyakov int err; 47481f6075eSEvgeniy Polyakov 47519e7184fSDavid Fries /* Other potentionally interesting flags for reset. 47619e7184fSDavid Fries * 47719e7184fSDavid Fries * COMM_NTF: Return result register feedback. This could be used to 47819e7184fSDavid Fries * detect some conditions such as short, alarming presence, or 47919e7184fSDavid Fries * detect if a new device was detected. 48019e7184fSDavid Fries * 48119e7184fSDavid Fries * COMM_SE which allows SPEED_NORMAL, SPEED_FLEXIBLE, SPEED_OVERDRIVE: 48219e7184fSDavid Fries * Select the data transfer rate. 48319e7184fSDavid Fries */ 48419e7184fSDavid Fries err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_IM, SPEED_NORMAL); 48581f6075eSEvgeniy Polyakov if (err) 48681f6075eSEvgeniy Polyakov return err; 48781f6075eSEvgeniy Polyakov 48881f6075eSEvgeniy Polyakov return 0; 48981f6075eSEvgeniy Polyakov } 49081f6075eSEvgeniy Polyakov 49181f6075eSEvgeniy Polyakov #if 0 49281f6075eSEvgeniy Polyakov static int ds_set_speed(struct ds_device *dev, int speed) 49381f6075eSEvgeniy Polyakov { 49481f6075eSEvgeniy Polyakov int err; 49581f6075eSEvgeniy Polyakov 49681f6075eSEvgeniy Polyakov if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE) 49781f6075eSEvgeniy Polyakov return -EINVAL; 49881f6075eSEvgeniy Polyakov 49981f6075eSEvgeniy Polyakov if (speed != SPEED_OVERDRIVE) 50081f6075eSEvgeniy Polyakov speed = SPEED_FLEXIBLE; 50181f6075eSEvgeniy Polyakov 50281f6075eSEvgeniy Polyakov speed &= 0xff; 50381f6075eSEvgeniy Polyakov 50481f6075eSEvgeniy Polyakov err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed); 50581f6075eSEvgeniy Polyakov if (err) 50681f6075eSEvgeniy Polyakov return err; 50781f6075eSEvgeniy Polyakov 50881f6075eSEvgeniy Polyakov return err; 50981f6075eSEvgeniy Polyakov } 51081f6075eSEvgeniy Polyakov #endif /* 0 */ 51181f6075eSEvgeniy Polyakov 5121f4ec2d7SDavid Fries static int ds_set_pullup(struct ds_device *dev, int delay) 51381f6075eSEvgeniy Polyakov { 514ade6d810SDavid Fries int err = 0; 51581f6075eSEvgeniy Polyakov u8 del = 1 + (u8)(delay >> 4); 516ade6d810SDavid Fries /* Just storing delay would not get the trunication and roundup. */ 517ade6d810SDavid Fries int ms = del<<4; 51881f6075eSEvgeniy Polyakov 519ade6d810SDavid Fries /* Enable spu_bit if a delay is set. */ 520ade6d810SDavid Fries dev->spu_bit = delay ? COMM_SPU : 0; 521ade6d810SDavid Fries /* If delay is zero, it has already been disabled, if the time is 522ade6d810SDavid Fries * the same as the hardware was last programmed to, there is also 523ade6d810SDavid Fries * nothing more to do. Compare with the recalculated value ms 524ade6d810SDavid Fries * rather than del or delay which can have a different value. 525ade6d810SDavid Fries */ 526ade6d810SDavid Fries if (delay == 0 || ms == dev->spu_sleep) 52781f6075eSEvgeniy Polyakov return err; 52881f6075eSEvgeniy Polyakov 52981f6075eSEvgeniy Polyakov err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del); 53081f6075eSEvgeniy Polyakov if (err) 53181f6075eSEvgeniy Polyakov return err; 53281f6075eSEvgeniy Polyakov 533ade6d810SDavid Fries dev->spu_sleep = ms; 53481f6075eSEvgeniy Polyakov 53581f6075eSEvgeniy Polyakov return err; 53681f6075eSEvgeniy Polyakov } 53781f6075eSEvgeniy Polyakov 53881f6075eSEvgeniy Polyakov static int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit) 53981f6075eSEvgeniy Polyakov { 5406e10f654SDavid Fries int err; 54181f6075eSEvgeniy Polyakov struct ds_status st; 54281f6075eSEvgeniy Polyakov 5436e10f654SDavid Fries err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit ? COMM_D : 0), 5446e10f654SDavid Fries 0); 54581f6075eSEvgeniy Polyakov if (err) 54681f6075eSEvgeniy Polyakov return err; 54781f6075eSEvgeniy Polyakov 5486e10f654SDavid Fries ds_wait_status(dev, &st); 54981f6075eSEvgeniy Polyakov 55081f6075eSEvgeniy Polyakov err = ds_recv_data(dev, tbit, sizeof(*tbit)); 55181f6075eSEvgeniy Polyakov if (err < 0) 55281f6075eSEvgeniy Polyakov return err; 55381f6075eSEvgeniy Polyakov 55481f6075eSEvgeniy Polyakov return 0; 55581f6075eSEvgeniy Polyakov } 55681f6075eSEvgeniy Polyakov 557a08e2d33SDavid Fries #if 0 55881f6075eSEvgeniy Polyakov static int ds_write_bit(struct ds_device *dev, u8 bit) 55981f6075eSEvgeniy Polyakov { 56081f6075eSEvgeniy Polyakov int err; 56181f6075eSEvgeniy Polyakov struct ds_status st; 56281f6075eSEvgeniy Polyakov 563e1c86d22SDavid Fries /* Set COMM_ICP to write without a readback. Note, this will 564e1c86d22SDavid Fries * produce one time slot, a down followed by an up with COMM_D 565e1c86d22SDavid Fries * only determing the timing. 566e1c86d22SDavid Fries */ 567e1c86d22SDavid Fries err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_ICP | 568e1c86d22SDavid Fries (bit ? COMM_D : 0), 0); 56981f6075eSEvgeniy Polyakov if (err) 57081f6075eSEvgeniy Polyakov return err; 57181f6075eSEvgeniy Polyakov 57281f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 57381f6075eSEvgeniy Polyakov 57481f6075eSEvgeniy Polyakov return 0; 57581f6075eSEvgeniy Polyakov } 576a08e2d33SDavid Fries #endif 57781f6075eSEvgeniy Polyakov 57881f6075eSEvgeniy Polyakov static int ds_write_byte(struct ds_device *dev, u8 byte) 57981f6075eSEvgeniy Polyakov { 58081f6075eSEvgeniy Polyakov int err; 58181f6075eSEvgeniy Polyakov struct ds_status st; 58281f6075eSEvgeniy Polyakov 583ade6d810SDavid Fries err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | dev->spu_bit, byte); 58481f6075eSEvgeniy Polyakov if (err) 58581f6075eSEvgeniy Polyakov return err; 58681f6075eSEvgeniy Polyakov 587ade6d810SDavid Fries if (dev->spu_bit) 5881f4ec2d7SDavid Fries msleep(dev->spu_sleep); 5891f4ec2d7SDavid Fries 59081f6075eSEvgeniy Polyakov err = ds_wait_status(dev, &st); 59181f6075eSEvgeniy Polyakov if (err) 59281f6075eSEvgeniy Polyakov return err; 59381f6075eSEvgeniy Polyakov 59461cd1b4cSMaciej S. Szmigiero err = ds_recv_data(dev, &dev->byte_buf, 1); 59581f6075eSEvgeniy Polyakov if (err < 0) 59681f6075eSEvgeniy Polyakov return err; 59781f6075eSEvgeniy Polyakov 59861cd1b4cSMaciej S. Szmigiero return !(byte == dev->byte_buf); 59981f6075eSEvgeniy Polyakov } 60081f6075eSEvgeniy Polyakov 60181f6075eSEvgeniy Polyakov static int ds_read_byte(struct ds_device *dev, u8 *byte) 60281f6075eSEvgeniy Polyakov { 60381f6075eSEvgeniy Polyakov int err; 60481f6075eSEvgeniy Polyakov struct ds_status st; 60581f6075eSEvgeniy Polyakov 60681f6075eSEvgeniy Polyakov err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM, 0xff); 60781f6075eSEvgeniy Polyakov if (err) 60881f6075eSEvgeniy Polyakov return err; 60981f6075eSEvgeniy Polyakov 61081f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 61181f6075eSEvgeniy Polyakov 61281f6075eSEvgeniy Polyakov err = ds_recv_data(dev, byte, sizeof(*byte)); 61381f6075eSEvgeniy Polyakov if (err < 0) 61481f6075eSEvgeniy Polyakov return err; 61581f6075eSEvgeniy Polyakov 61681f6075eSEvgeniy Polyakov return 0; 61781f6075eSEvgeniy Polyakov } 61881f6075eSEvgeniy Polyakov 619*d605ba72SMarc Ferland static int read_block_chunk(struct ds_device *dev, u8 *buf, int len) 62081f6075eSEvgeniy Polyakov { 62181f6075eSEvgeniy Polyakov struct ds_status st; 62281f6075eSEvgeniy Polyakov int err; 62381f6075eSEvgeniy Polyakov 62481f6075eSEvgeniy Polyakov memset(buf, 0xFF, len); 62581f6075eSEvgeniy Polyakov 62681f6075eSEvgeniy Polyakov err = ds_send_data(dev, buf, len); 62781f6075eSEvgeniy Polyakov if (err < 0) 62881f6075eSEvgeniy Polyakov return err; 62981f6075eSEvgeniy Polyakov 6301f4ec2d7SDavid Fries err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM, len); 63181f6075eSEvgeniy Polyakov if (err) 63281f6075eSEvgeniy Polyakov return err; 63381f6075eSEvgeniy Polyakov 63481f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 63581f6075eSEvgeniy Polyakov 63681f6075eSEvgeniy Polyakov memset(buf, 0x00, len); 63781f6075eSEvgeniy Polyakov err = ds_recv_data(dev, buf, len); 63881f6075eSEvgeniy Polyakov 63981f6075eSEvgeniy Polyakov return err; 64081f6075eSEvgeniy Polyakov } 64181f6075eSEvgeniy Polyakov 642*d605ba72SMarc Ferland static int ds_read_block(struct ds_device *dev, u8 *buf, int len) 643*d605ba72SMarc Ferland { 644*d605ba72SMarc Ferland int err, to_read, rem = len; 645*d605ba72SMarc Ferland 646*d605ba72SMarc Ferland if (len > 64 * 1024) 647*d605ba72SMarc Ferland return -E2BIG; 648*d605ba72SMarc Ferland 649*d605ba72SMarc Ferland do { 650*d605ba72SMarc Ferland to_read = rem <= FIFO_SIZE ? rem : FIFO_SIZE; 651*d605ba72SMarc Ferland err = read_block_chunk(dev, &buf[len - rem], to_read); 652*d605ba72SMarc Ferland if (err < 0) 653*d605ba72SMarc Ferland return err; 654*d605ba72SMarc Ferland rem -= to_read; 655*d605ba72SMarc Ferland } while (rem); 656*d605ba72SMarc Ferland 657*d605ba72SMarc Ferland return err; 658*d605ba72SMarc Ferland } 659*d605ba72SMarc Ferland 66081f6075eSEvgeniy Polyakov static int ds_write_block(struct ds_device *dev, u8 *buf, int len) 66181f6075eSEvgeniy Polyakov { 66281f6075eSEvgeniy Polyakov int err; 66381f6075eSEvgeniy Polyakov struct ds_status st; 66481f6075eSEvgeniy Polyakov 66581f6075eSEvgeniy Polyakov err = ds_send_data(dev, buf, len); 66681f6075eSEvgeniy Polyakov if (err < 0) 66781f6075eSEvgeniy Polyakov return err; 66881f6075eSEvgeniy Polyakov 669ade6d810SDavid Fries err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | dev->spu_bit, len); 67081f6075eSEvgeniy Polyakov if (err) 67181f6075eSEvgeniy Polyakov return err; 67281f6075eSEvgeniy Polyakov 673ade6d810SDavid Fries if (dev->spu_bit) 6741f4ec2d7SDavid Fries msleep(dev->spu_sleep); 6751f4ec2d7SDavid Fries 67681f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 67781f6075eSEvgeniy Polyakov 67881f6075eSEvgeniy Polyakov err = ds_recv_data(dev, buf, len); 67981f6075eSEvgeniy Polyakov if (err < 0) 68081f6075eSEvgeniy Polyakov return err; 68181f6075eSEvgeniy Polyakov 68281f6075eSEvgeniy Polyakov return !(err == len); 68381f6075eSEvgeniy Polyakov } 68481f6075eSEvgeniy Polyakov 685d53f0a2cSDavid Fries static void ds9490r_search(void *data, struct w1_master *master, 686d53f0a2cSDavid Fries u8 search_type, w1_slave_found_callback callback) 68781f6075eSEvgeniy Polyakov { 688d53f0a2cSDavid Fries /* When starting with an existing id, the first id returned will 689d53f0a2cSDavid Fries * be that device (if it is still on the bus most likely). 690d53f0a2cSDavid Fries * 691d53f0a2cSDavid Fries * If the number of devices found is less than or equal to the 692d53f0a2cSDavid Fries * search_limit, that number of IDs will be returned. If there are 693d53f0a2cSDavid Fries * more, search_limit IDs will be returned followed by a non-zero 694d53f0a2cSDavid Fries * discrepency value. 695d53f0a2cSDavid Fries */ 696d53f0a2cSDavid Fries struct ds_device *dev = data; 69781f6075eSEvgeniy Polyakov int err; 69881f6075eSEvgeniy Polyakov u16 value, index; 69981f6075eSEvgeniy Polyakov struct ds_status st; 700d53f0a2cSDavid Fries int search_limit; 701d53f0a2cSDavid Fries int found = 0; 702d53f0a2cSDavid Fries int i; 70381f6075eSEvgeniy Polyakov 704d53f0a2cSDavid Fries /* DS18b20 spec, 13.16 ms per device, 75 per second, sleep for 705d53f0a2cSDavid Fries * discovering 8 devices (1 bulk transfer and 1/2 FIFO size) at a time. 706d53f0a2cSDavid Fries */ 707d53f0a2cSDavid Fries const unsigned long jtime = msecs_to_jiffies(1000*8/75); 708d53f0a2cSDavid Fries /* FIFO 128 bytes, bulk packet size 64, read a multiple of the 709d53f0a2cSDavid Fries * packet size. 710d53f0a2cSDavid Fries */ 71161cd1b4cSMaciej S. Szmigiero const size_t bufsize = 2 * 64; 712e3fe0e89SChristian Vogel u64 *buf, *found_ids; 71361cd1b4cSMaciej S. Szmigiero 71461cd1b4cSMaciej S. Szmigiero buf = kmalloc(bufsize, GFP_KERNEL); 71561cd1b4cSMaciej S. Szmigiero if (!buf) 71661cd1b4cSMaciej S. Szmigiero return; 71781f6075eSEvgeniy Polyakov 718e3fe0e89SChristian Vogel /* 719e3fe0e89SChristian Vogel * We are holding the bus mutex during the scan, but adding devices via the 720e3fe0e89SChristian Vogel * callback needs the bus to be unlocked. So we queue up found ids here. 721e3fe0e89SChristian Vogel */ 722e3fe0e89SChristian Vogel found_ids = kmalloc_array(master->max_slave_count, sizeof(u64), GFP_KERNEL); 723e3fe0e89SChristian Vogel if (!found_ids) { 724e3fe0e89SChristian Vogel kfree(buf); 725e3fe0e89SChristian Vogel return; 726e3fe0e89SChristian Vogel } 727e3fe0e89SChristian Vogel 728d3a8a9dbSDavid Fries mutex_lock(&master->bus_mutex); 729d3a8a9dbSDavid Fries 730d53f0a2cSDavid Fries /* address to start searching at */ 731d53f0a2cSDavid Fries if (ds_send_data(dev, (u8 *)&master->search_id, 8) < 0) 732d3a8a9dbSDavid Fries goto search_out; 733d53f0a2cSDavid Fries master->search_id = 0; 73481f6075eSEvgeniy Polyakov 735d53f0a2cSDavid Fries value = COMM_SEARCH_ACCESS | COMM_IM | COMM_RST | COMM_SM | COMM_F | 736d53f0a2cSDavid Fries COMM_RTS; 737d53f0a2cSDavid Fries search_limit = master->max_slave_count; 738d53f0a2cSDavid Fries if (search_limit > 255) 739d53f0a2cSDavid Fries search_limit = 0; 740d53f0a2cSDavid Fries index = search_type | (search_limit << 8); 741d53f0a2cSDavid Fries if (ds_send_control(dev, value, index) < 0) 742d3a8a9dbSDavid Fries goto search_out; 74381f6075eSEvgeniy Polyakov 744d53f0a2cSDavid Fries do { 745d53f0a2cSDavid Fries schedule_timeout(jtime); 74681f6075eSEvgeniy Polyakov 747f76a9ae6SChristian Vogel err = ds_recv_status(dev, &st); 74861cd1b4cSMaciej S. Szmigiero if (err < 0 || err < sizeof(st)) 749d53f0a2cSDavid Fries break; 75081f6075eSEvgeniy Polyakov 751d53f0a2cSDavid Fries if (st.data_in_buffer_status) { 752ad9c36beSKrzysztof Kozlowski /* 753ad9c36beSKrzysztof Kozlowski * Bulk in can receive partial ids, but when it does 754d53f0a2cSDavid Fries * they fail crc and will be discarded anyway. 755d53f0a2cSDavid Fries * That has only been seen when status in buffer 756d53f0a2cSDavid Fries * is 0 and bulk is read anyway, so don't read 757d53f0a2cSDavid Fries * bulk without first checking if status says there 758d53f0a2cSDavid Fries * is data to read. 759d53f0a2cSDavid Fries */ 76061cd1b4cSMaciej S. Szmigiero err = ds_recv_data(dev, (u8 *)buf, bufsize); 761d53f0a2cSDavid Fries if (err < 0) 762d53f0a2cSDavid Fries break; 763d53f0a2cSDavid Fries for (i = 0; i < err/8; ++i) { 764e3fe0e89SChristian Vogel found_ids[found++] = buf[i]; 765ad9c36beSKrzysztof Kozlowski /* 766ad9c36beSKrzysztof Kozlowski * can't know if there will be a discrepancy 767ad9c36beSKrzysztof Kozlowski * value after until the next id 768ad9c36beSKrzysztof Kozlowski */ 769e3fe0e89SChristian Vogel if (found == search_limit) { 770d53f0a2cSDavid Fries master->search_id = buf[i]; 771e3fe0e89SChristian Vogel break; 772e3fe0e89SChristian Vogel } 773d53f0a2cSDavid Fries } 774d53f0a2cSDavid Fries } 775d53f0a2cSDavid Fries 776d53f0a2cSDavid Fries if (test_bit(W1_ABORT_SEARCH, &master->flags)) 777d53f0a2cSDavid Fries break; 778d53f0a2cSDavid Fries } while (!(st.status & (ST_IDLE | ST_HALT))); 779d53f0a2cSDavid Fries 780d53f0a2cSDavid Fries /* only continue the search if some weren't found */ 781d53f0a2cSDavid Fries if (found <= search_limit) { 782d53f0a2cSDavid Fries master->search_id = 0; 783d53f0a2cSDavid Fries } else if (!test_bit(W1_WARN_MAX_COUNT, &master->flags)) { 784ad9c36beSKrzysztof Kozlowski /* 785ad9c36beSKrzysztof Kozlowski * Only max_slave_count will be scanned in a search, 786d53f0a2cSDavid Fries * but it will start where it left off next search 787d53f0a2cSDavid Fries * until all ids are identified and then it will start 788d53f0a2cSDavid Fries * over. A continued search will report the previous 789d53f0a2cSDavid Fries * last id as the first id (provided it is still on the 790d53f0a2cSDavid Fries * bus). 791d53f0a2cSDavid Fries */ 792d53f0a2cSDavid Fries dev_info(&dev->udev->dev, "%s: max_slave_count %d reached, " 793d53f0a2cSDavid Fries "will continue next search.\n", __func__, 794d53f0a2cSDavid Fries master->max_slave_count); 795d53f0a2cSDavid Fries set_bit(W1_WARN_MAX_COUNT, &master->flags); 796d53f0a2cSDavid Fries } 797e3fe0e89SChristian Vogel 798d3a8a9dbSDavid Fries search_out: 799d3a8a9dbSDavid Fries mutex_unlock(&master->bus_mutex); 80061cd1b4cSMaciej S. Szmigiero kfree(buf); 801e3fe0e89SChristian Vogel 802e3fe0e89SChristian Vogel for (i = 0; i < found; i++) /* run callback for all queued up IDs */ 803e3fe0e89SChristian Vogel callback(master, found_ids[i]); 804e3fe0e89SChristian Vogel kfree(found_ids); 805d53f0a2cSDavid Fries } 806d53f0a2cSDavid Fries 807d53f0a2cSDavid Fries #if 0 80861cd1b4cSMaciej S. Szmigiero /* 80961cd1b4cSMaciej S. Szmigiero * FIXME: if this disabled code is ever used in the future all ds_send_data() 81061cd1b4cSMaciej S. Szmigiero * calls must be changed to use a DMAable buffer. 81161cd1b4cSMaciej S. Szmigiero */ 81281f6075eSEvgeniy Polyakov static int ds_match_access(struct ds_device *dev, u64 init) 81381f6075eSEvgeniy Polyakov { 81481f6075eSEvgeniy Polyakov int err; 81581f6075eSEvgeniy Polyakov struct ds_status st; 81681f6075eSEvgeniy Polyakov 81781f6075eSEvgeniy Polyakov err = ds_send_data(dev, (unsigned char *)&init, sizeof(init)); 81881f6075eSEvgeniy Polyakov if (err) 81981f6075eSEvgeniy Polyakov return err; 82081f6075eSEvgeniy Polyakov 82181f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 82281f6075eSEvgeniy Polyakov 82381f6075eSEvgeniy Polyakov err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055); 82481f6075eSEvgeniy Polyakov if (err) 82581f6075eSEvgeniy Polyakov return err; 82681f6075eSEvgeniy Polyakov 82781f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 82881f6075eSEvgeniy Polyakov 82981f6075eSEvgeniy Polyakov return 0; 83081f6075eSEvgeniy Polyakov } 83181f6075eSEvgeniy Polyakov 83281f6075eSEvgeniy Polyakov static int ds_set_path(struct ds_device *dev, u64 init) 83381f6075eSEvgeniy Polyakov { 83481f6075eSEvgeniy Polyakov int err; 83581f6075eSEvgeniy Polyakov struct ds_status st; 83681f6075eSEvgeniy Polyakov u8 buf[9]; 83781f6075eSEvgeniy Polyakov 83881f6075eSEvgeniy Polyakov memcpy(buf, &init, 8); 83981f6075eSEvgeniy Polyakov buf[8] = BRANCH_MAIN; 84081f6075eSEvgeniy Polyakov 84181f6075eSEvgeniy Polyakov err = ds_send_data(dev, buf, sizeof(buf)); 84281f6075eSEvgeniy Polyakov if (err) 84381f6075eSEvgeniy Polyakov return err; 84481f6075eSEvgeniy Polyakov 84581f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 84681f6075eSEvgeniy Polyakov 84781f6075eSEvgeniy Polyakov err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0); 84881f6075eSEvgeniy Polyakov if (err) 84981f6075eSEvgeniy Polyakov return err; 85081f6075eSEvgeniy Polyakov 85181f6075eSEvgeniy Polyakov ds_wait_status(dev, &st); 85281f6075eSEvgeniy Polyakov 85381f6075eSEvgeniy Polyakov return 0; 85481f6075eSEvgeniy Polyakov } 85581f6075eSEvgeniy Polyakov 85681f6075eSEvgeniy Polyakov #endif /* 0 */ 85781f6075eSEvgeniy Polyakov 85881f6075eSEvgeniy Polyakov static u8 ds9490r_touch_bit(void *data, u8 bit) 85981f6075eSEvgeniy Polyakov { 86081f6075eSEvgeniy Polyakov struct ds_device *dev = data; 86181f6075eSEvgeniy Polyakov 86261cd1b4cSMaciej S. Szmigiero if (ds_touch_bit(dev, bit, &dev->byte_buf)) 86381f6075eSEvgeniy Polyakov return 0; 86481f6075eSEvgeniy Polyakov 86561cd1b4cSMaciej S. Szmigiero return dev->byte_buf; 86681f6075eSEvgeniy Polyakov } 86781f6075eSEvgeniy Polyakov 868a08e2d33SDavid Fries #if 0 86981f6075eSEvgeniy Polyakov static void ds9490r_write_bit(void *data, u8 bit) 87081f6075eSEvgeniy Polyakov { 87181f6075eSEvgeniy Polyakov struct ds_device *dev = data; 87281f6075eSEvgeniy Polyakov 87381f6075eSEvgeniy Polyakov ds_write_bit(dev, bit); 87481f6075eSEvgeniy Polyakov } 87581f6075eSEvgeniy Polyakov 87681f6075eSEvgeniy Polyakov static u8 ds9490r_read_bit(void *data) 87781f6075eSEvgeniy Polyakov { 87881f6075eSEvgeniy Polyakov struct ds_device *dev = data; 87981f6075eSEvgeniy Polyakov int err; 88081f6075eSEvgeniy Polyakov 88161cd1b4cSMaciej S. Szmigiero err = ds_touch_bit(dev, 1, &dev->byte_buf); 88281f6075eSEvgeniy Polyakov if (err) 88381f6075eSEvgeniy Polyakov return 0; 88481f6075eSEvgeniy Polyakov 88561cd1b4cSMaciej S. Szmigiero return dev->byte_buf & 1; 88681f6075eSEvgeniy Polyakov } 887a08e2d33SDavid Fries #endif 888a08e2d33SDavid Fries 889a08e2d33SDavid Fries static void ds9490r_write_byte(void *data, u8 byte) 890a08e2d33SDavid Fries { 891a08e2d33SDavid Fries struct ds_device *dev = data; 892a08e2d33SDavid Fries 893a08e2d33SDavid Fries ds_write_byte(dev, byte); 894a08e2d33SDavid Fries } 89581f6075eSEvgeniy Polyakov 89681f6075eSEvgeniy Polyakov static u8 ds9490r_read_byte(void *data) 89781f6075eSEvgeniy Polyakov { 89881f6075eSEvgeniy Polyakov struct ds_device *dev = data; 89981f6075eSEvgeniy Polyakov int err; 90081f6075eSEvgeniy Polyakov 90161cd1b4cSMaciej S. Szmigiero err = ds_read_byte(dev, &dev->byte_buf); 90281f6075eSEvgeniy Polyakov if (err) 90381f6075eSEvgeniy Polyakov return 0; 90481f6075eSEvgeniy Polyakov 90561cd1b4cSMaciej S. Szmigiero return dev->byte_buf; 90681f6075eSEvgeniy Polyakov } 90781f6075eSEvgeniy Polyakov 90881f6075eSEvgeniy Polyakov static void ds9490r_write_block(void *data, const u8 *buf, int len) 90981f6075eSEvgeniy Polyakov { 91081f6075eSEvgeniy Polyakov struct ds_device *dev = data; 91161cd1b4cSMaciej S. Szmigiero u8 *tbuf; 91281f6075eSEvgeniy Polyakov 91361cd1b4cSMaciej S. Szmigiero if (len <= 0) 91461cd1b4cSMaciej S. Szmigiero return; 91561cd1b4cSMaciej S. Szmigiero 91645003a1eSWei Yongjun tbuf = kmemdup(buf, len, GFP_KERNEL); 91761cd1b4cSMaciej S. Szmigiero if (!tbuf) 91861cd1b4cSMaciej S. Szmigiero return; 91961cd1b4cSMaciej S. Szmigiero 92061cd1b4cSMaciej S. Szmigiero ds_write_block(dev, tbuf, len); 92161cd1b4cSMaciej S. Szmigiero 92261cd1b4cSMaciej S. Szmigiero kfree(tbuf); 92381f6075eSEvgeniy Polyakov } 92481f6075eSEvgeniy Polyakov 92581f6075eSEvgeniy Polyakov static u8 ds9490r_read_block(void *data, u8 *buf, int len) 92681f6075eSEvgeniy Polyakov { 92781f6075eSEvgeniy Polyakov struct ds_device *dev = data; 92881f6075eSEvgeniy Polyakov int err; 92961cd1b4cSMaciej S. Szmigiero u8 *tbuf; 93081f6075eSEvgeniy Polyakov 93161cd1b4cSMaciej S. Szmigiero if (len <= 0) 93281f6075eSEvgeniy Polyakov return 0; 93381f6075eSEvgeniy Polyakov 93461cd1b4cSMaciej S. Szmigiero tbuf = kmalloc(len, GFP_KERNEL); 93561cd1b4cSMaciej S. Szmigiero if (!tbuf) 93661cd1b4cSMaciej S. Szmigiero return 0; 93761cd1b4cSMaciej S. Szmigiero 93861cd1b4cSMaciej S. Szmigiero err = ds_read_block(dev, tbuf, len); 93961cd1b4cSMaciej S. Szmigiero if (err >= 0) 94061cd1b4cSMaciej S. Szmigiero memcpy(buf, tbuf, len); 94161cd1b4cSMaciej S. Szmigiero 94261cd1b4cSMaciej S. Szmigiero kfree(tbuf); 94361cd1b4cSMaciej S. Szmigiero 94461cd1b4cSMaciej S. Szmigiero return err >= 0 ? len : 0; 94581f6075eSEvgeniy Polyakov } 94681f6075eSEvgeniy Polyakov 94781f6075eSEvgeniy Polyakov static u8 ds9490r_reset(void *data) 94881f6075eSEvgeniy Polyakov { 94981f6075eSEvgeniy Polyakov struct ds_device *dev = data; 95081f6075eSEvgeniy Polyakov int err; 95181f6075eSEvgeniy Polyakov 9527a4b9706SDavid Fries err = ds_reset(dev); 95381f6075eSEvgeniy Polyakov if (err) 95481f6075eSEvgeniy Polyakov return 1; 95581f6075eSEvgeniy Polyakov 95681f6075eSEvgeniy Polyakov return 0; 95781f6075eSEvgeniy Polyakov } 95881f6075eSEvgeniy Polyakov 9591f4ec2d7SDavid Fries static u8 ds9490r_set_pullup(void *data, int delay) 9601f4ec2d7SDavid Fries { 9611f4ec2d7SDavid Fries struct ds_device *dev = data; 9621f4ec2d7SDavid Fries 9631f4ec2d7SDavid Fries if (ds_set_pullup(dev, delay)) 9641f4ec2d7SDavid Fries return 1; 9651f4ec2d7SDavid Fries 9661f4ec2d7SDavid Fries return 0; 9671f4ec2d7SDavid Fries } 9681f4ec2d7SDavid Fries 96981f6075eSEvgeniy Polyakov static int ds_w1_init(struct ds_device *dev) 97081f6075eSEvgeniy Polyakov { 97181f6075eSEvgeniy Polyakov memset(&dev->master, 0, sizeof(struct w1_bus_master)); 97281f6075eSEvgeniy Polyakov 973e464af24SDavid Fries /* Reset the device as it can be in a bad state. 974e464af24SDavid Fries * This is necessary because a block write will wait for data 975e464af24SDavid Fries * to be placed in the output buffer and block any later 976e464af24SDavid Fries * commands which will keep accumulating and the device will 977e464af24SDavid Fries * not be idle. Another case is removing the ds2490 module 978e464af24SDavid Fries * while a bus search is in progress, somehow a few commands 979e464af24SDavid Fries * get through, but the input transfers fail leaving data in 980e464af24SDavid Fries * the input buffer. This will cause the next read to fail 981e464af24SDavid Fries * see the note in ds_recv_data. 982e464af24SDavid Fries */ 983ade6d810SDavid Fries ds_reset_device(dev); 984e464af24SDavid Fries 98581f6075eSEvgeniy Polyakov dev->master.data = dev; 98681f6075eSEvgeniy Polyakov dev->master.touch_bit = &ds9490r_touch_bit; 987a08e2d33SDavid Fries /* read_bit and write_bit in w1_bus_master are expected to set and 988a08e2d33SDavid Fries * sample the line level. For write_bit that means it is expected to 989a08e2d33SDavid Fries * set it to that value and leave it there. ds2490 only supports an 990a08e2d33SDavid Fries * individual time slot at the lowest level. The requirement from 991a08e2d33SDavid Fries * pulling the bus state down to reading the state is 15us, something 992a08e2d33SDavid Fries * that isn't realistic on the USB bus anyway. 99381f6075eSEvgeniy Polyakov dev->master.read_bit = &ds9490r_read_bit; 99481f6075eSEvgeniy Polyakov dev->master.write_bit = &ds9490r_write_bit; 995a08e2d33SDavid Fries */ 99681f6075eSEvgeniy Polyakov dev->master.read_byte = &ds9490r_read_byte; 99781f6075eSEvgeniy Polyakov dev->master.write_byte = &ds9490r_write_byte; 99881f6075eSEvgeniy Polyakov dev->master.read_block = &ds9490r_read_block; 99981f6075eSEvgeniy Polyakov dev->master.write_block = &ds9490r_write_block; 100081f6075eSEvgeniy Polyakov dev->master.reset_bus = &ds9490r_reset; 10011f4ec2d7SDavid Fries dev->master.set_pullup = &ds9490r_set_pullup; 1002d53f0a2cSDavid Fries dev->master.search = &ds9490r_search; 100381f6075eSEvgeniy Polyakov 100481f6075eSEvgeniy Polyakov return w1_add_master_device(&dev->master); 100581f6075eSEvgeniy Polyakov } 100681f6075eSEvgeniy Polyakov 100781f6075eSEvgeniy Polyakov static void ds_w1_fini(struct ds_device *dev) 100881f6075eSEvgeniy Polyakov { 100981f6075eSEvgeniy Polyakov w1_remove_master_device(&dev->master); 101081f6075eSEvgeniy Polyakov } 101181f6075eSEvgeniy Polyakov 101281f6075eSEvgeniy Polyakov static int ds_probe(struct usb_interface *intf, 101381f6075eSEvgeniy Polyakov const struct usb_device_id *udev_id) 101481f6075eSEvgeniy Polyakov { 101581f6075eSEvgeniy Polyakov struct usb_device *udev = interface_to_usbdev(intf); 101681f6075eSEvgeniy Polyakov struct usb_endpoint_descriptor *endpoint; 101781f6075eSEvgeniy Polyakov struct usb_host_interface *iface_desc; 101881f6075eSEvgeniy Polyakov struct ds_device *dev; 1019da78b7e7SDavid Fries int i, err, alt; 102081f6075eSEvgeniy Polyakov 1021d53f0a2cSDavid Fries dev = kzalloc(sizeof(struct ds_device), GFP_KERNEL); 1022f76a9ae6SChristian Vogel if (!dev) 102381f6075eSEvgeniy Polyakov return -ENOMEM; 1024f76a9ae6SChristian Vogel 102581f6075eSEvgeniy Polyakov dev->udev = usb_get_dev(udev); 102681f6075eSEvgeniy Polyakov if (!dev->udev) { 102781f6075eSEvgeniy Polyakov err = -ENOMEM; 102881f6075eSEvgeniy Polyakov goto err_out_free; 102981f6075eSEvgeniy Polyakov } 103081f6075eSEvgeniy Polyakov memset(dev->ep, 0, sizeof(dev->ep)); 103181f6075eSEvgeniy Polyakov 103281f6075eSEvgeniy Polyakov usb_set_intfdata(intf, dev); 103381f6075eSEvgeniy Polyakov 103481f6075eSEvgeniy Polyakov err = usb_reset_configuration(dev->udev); 103581f6075eSEvgeniy Polyakov if (err) { 1036da78b7e7SDavid Fries dev_err(&dev->udev->dev, 1037da78b7e7SDavid Fries "Failed to reset configuration: err=%d.\n", err); 103881f6075eSEvgeniy Polyakov goto err_out_clear; 103981f6075eSEvgeniy Polyakov } 104081f6075eSEvgeniy Polyakov 1041da78b7e7SDavid Fries /* alternative 3, 1ms interrupt (greatly speeds search), 64 byte bulk */ 1042da78b7e7SDavid Fries alt = 3; 1043da78b7e7SDavid Fries err = usb_set_interface(dev->udev, 1044c114944dSAlan Stern intf->cur_altsetting->desc.bInterfaceNumber, alt); 1045da78b7e7SDavid Fries if (err) { 1046da78b7e7SDavid Fries dev_err(&dev->udev->dev, "Failed to set alternative setting %d " 1047da78b7e7SDavid Fries "for %d interface: err=%d.\n", alt, 1048c114944dSAlan Stern intf->cur_altsetting->desc.bInterfaceNumber, err); 1049da78b7e7SDavid Fries goto err_out_clear; 1050da78b7e7SDavid Fries } 1051da78b7e7SDavid Fries 1052c114944dSAlan Stern iface_desc = intf->cur_altsetting; 105381f6075eSEvgeniy Polyakov if (iface_desc->desc.bNumEndpoints != NUM_EP-1) { 1054f76a9ae6SChristian Vogel dev_err(&dev->udev->dev, "Num endpoints=%d. It is not DS9490R.\n", 10551fda5690SFjodor Schelichow iface_desc->desc.bNumEndpoints); 105681f6075eSEvgeniy Polyakov err = -EINVAL; 105781f6075eSEvgeniy Polyakov goto err_out_clear; 105881f6075eSEvgeniy Polyakov } 105981f6075eSEvgeniy Polyakov 106081f6075eSEvgeniy Polyakov /* 106181f6075eSEvgeniy Polyakov * This loop doesn'd show control 0 endpoint, 106281f6075eSEvgeniy Polyakov * so we will fill only 1-3 endpoints entry. 106381f6075eSEvgeniy Polyakov */ 106481f6075eSEvgeniy Polyakov for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { 106581f6075eSEvgeniy Polyakov endpoint = &iface_desc->endpoint[i].desc; 106681f6075eSEvgeniy Polyakov 106781f6075eSEvgeniy Polyakov dev->ep[i+1] = endpoint->bEndpointAddress; 106881f6075eSEvgeniy Polyakov #if 0 106981f6075eSEvgeniy Polyakov printk("%d: addr=%x, size=%d, dir=%s, type=%x\n", 107081f6075eSEvgeniy Polyakov i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize), 107181f6075eSEvgeniy Polyakov (endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT", 107281f6075eSEvgeniy Polyakov endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); 107381f6075eSEvgeniy Polyakov #endif 107481f6075eSEvgeniy Polyakov } 107581f6075eSEvgeniy Polyakov 107681f6075eSEvgeniy Polyakov err = ds_w1_init(dev); 107781f6075eSEvgeniy Polyakov if (err) 107881f6075eSEvgeniy Polyakov goto err_out_clear; 107981f6075eSEvgeniy Polyakov 1080abd52a13SEvgeniy Polyakov mutex_lock(&ds_mutex); 108181f6075eSEvgeniy Polyakov list_add_tail(&dev->ds_entry, &ds_devices); 1082abd52a13SEvgeniy Polyakov mutex_unlock(&ds_mutex); 108381f6075eSEvgeniy Polyakov 108481f6075eSEvgeniy Polyakov return 0; 108581f6075eSEvgeniy Polyakov 108681f6075eSEvgeniy Polyakov err_out_clear: 108781f6075eSEvgeniy Polyakov usb_set_intfdata(intf, NULL); 108881f6075eSEvgeniy Polyakov usb_put_dev(dev->udev); 108981f6075eSEvgeniy Polyakov err_out_free: 109081f6075eSEvgeniy Polyakov kfree(dev); 109181f6075eSEvgeniy Polyakov return err; 109281f6075eSEvgeniy Polyakov } 109381f6075eSEvgeniy Polyakov 109481f6075eSEvgeniy Polyakov static void ds_disconnect(struct usb_interface *intf) 109581f6075eSEvgeniy Polyakov { 109681f6075eSEvgeniy Polyakov struct ds_device *dev; 109781f6075eSEvgeniy Polyakov 109881f6075eSEvgeniy Polyakov dev = usb_get_intfdata(intf); 109981f6075eSEvgeniy Polyakov if (!dev) 110081f6075eSEvgeniy Polyakov return; 110181f6075eSEvgeniy Polyakov 1102abd52a13SEvgeniy Polyakov mutex_lock(&ds_mutex); 110381f6075eSEvgeniy Polyakov list_del(&dev->ds_entry); 1104abd52a13SEvgeniy Polyakov mutex_unlock(&ds_mutex); 110581f6075eSEvgeniy Polyakov 110681f6075eSEvgeniy Polyakov ds_w1_fini(dev); 110781f6075eSEvgeniy Polyakov 110881f6075eSEvgeniy Polyakov usb_set_intfdata(intf, NULL); 110981f6075eSEvgeniy Polyakov 111081f6075eSEvgeniy Polyakov usb_put_dev(dev->udev); 111181f6075eSEvgeniy Polyakov kfree(dev); 111281f6075eSEvgeniy Polyakov } 111381f6075eSEvgeniy Polyakov 1114d7b3cf89SArvind Yadav static const struct usb_device_id ds_id_table[] = { 111550fa2951SAndrew F. Davis { USB_DEVICE(0x04fa, 0x2490) }, 111650fa2951SAndrew F. Davis { }, 111750fa2951SAndrew F. Davis }; 111850fa2951SAndrew F. Davis MODULE_DEVICE_TABLE(usb, ds_id_table); 111950fa2951SAndrew F. Davis 112050fa2951SAndrew F. Davis static struct usb_driver ds_driver = { 112150fa2951SAndrew F. Davis .name = "DS9490R", 112250fa2951SAndrew F. Davis .probe = ds_probe, 112350fa2951SAndrew F. Davis .disconnect = ds_disconnect, 112450fa2951SAndrew F. Davis .id_table = ds_id_table, 112550fa2951SAndrew F. Davis }; 1126fe748483SGreg Kroah-Hartman module_usb_driver(ds_driver); 112781f6075eSEvgeniy Polyakov 1128a8018766SEvgeniy Polyakov MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); 112981f6075eSEvgeniy Polyakov MODULE_DESCRIPTION("DS2490 USB <-> W1 bus master driver (DS9490*)"); 113050fa2951SAndrew F. Davis MODULE_LICENSE("GPL"); 1131