162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * ds2490.c USB to one wire bridge 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (c) 2004 Evgeniy Polyakov <zbr@ioremap.net> 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include <linux/module.h> 962306a36Sopenharmony_ci#include <linux/kernel.h> 1062306a36Sopenharmony_ci#include <linux/mod_devicetable.h> 1162306a36Sopenharmony_ci#include <linux/usb.h> 1262306a36Sopenharmony_ci#include <linux/slab.h> 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#include <linux/w1.h> 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/* USB Standard */ 1762306a36Sopenharmony_ci/* USB Control request vendor type */ 1862306a36Sopenharmony_ci#define VENDOR 0x40 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci/* COMMAND TYPE CODES */ 2162306a36Sopenharmony_ci#define CONTROL_CMD 0x00 2262306a36Sopenharmony_ci#define COMM_CMD 0x01 2362306a36Sopenharmony_ci#define MODE_CMD 0x02 2462306a36Sopenharmony_ci 2562306a36Sopenharmony_ci/* CONTROL COMMAND CODES */ 2662306a36Sopenharmony_ci#define CTL_RESET_DEVICE 0x0000 2762306a36Sopenharmony_ci#define CTL_START_EXE 0x0001 2862306a36Sopenharmony_ci#define CTL_RESUME_EXE 0x0002 2962306a36Sopenharmony_ci#define CTL_HALT_EXE_IDLE 0x0003 3062306a36Sopenharmony_ci#define CTL_HALT_EXE_DONE 0x0004 3162306a36Sopenharmony_ci#define CTL_FLUSH_COMM_CMDS 0x0007 3262306a36Sopenharmony_ci#define CTL_FLUSH_RCV_BUFFER 0x0008 3362306a36Sopenharmony_ci#define CTL_FLUSH_XMT_BUFFER 0x0009 3462306a36Sopenharmony_ci#define CTL_GET_COMM_CMDS 0x000A 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_ci/* MODE COMMAND CODES */ 3762306a36Sopenharmony_ci#define MOD_PULSE_EN 0x0000 3862306a36Sopenharmony_ci#define MOD_SPEED_CHANGE_EN 0x0001 3962306a36Sopenharmony_ci#define MOD_1WIRE_SPEED 0x0002 4062306a36Sopenharmony_ci#define MOD_STRONG_PU_DURATION 0x0003 4162306a36Sopenharmony_ci#define MOD_PULLDOWN_SLEWRATE 0x0004 4262306a36Sopenharmony_ci#define MOD_PROG_PULSE_DURATION 0x0005 4362306a36Sopenharmony_ci#define MOD_WRITE1_LOWTIME 0x0006 4462306a36Sopenharmony_ci#define MOD_DSOW0_TREC 0x0007 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* COMMUNICATION COMMAND CODES */ 4762306a36Sopenharmony_ci#define COMM_ERROR_ESCAPE 0x0601 4862306a36Sopenharmony_ci#define COMM_SET_DURATION 0x0012 4962306a36Sopenharmony_ci#define COMM_BIT_IO 0x0020 5062306a36Sopenharmony_ci#define COMM_PULSE 0x0030 5162306a36Sopenharmony_ci#define COMM_1_WIRE_RESET 0x0042 5262306a36Sopenharmony_ci#define COMM_BYTE_IO 0x0052 5362306a36Sopenharmony_ci#define COMM_MATCH_ACCESS 0x0064 5462306a36Sopenharmony_ci#define COMM_BLOCK_IO 0x0074 5562306a36Sopenharmony_ci#define COMM_READ_STRAIGHT 0x0080 5662306a36Sopenharmony_ci#define COMM_DO_RELEASE 0x6092 5762306a36Sopenharmony_ci#define COMM_SET_PATH 0x00A2 5862306a36Sopenharmony_ci#define COMM_WRITE_SRAM_PAGE 0x00B2 5962306a36Sopenharmony_ci#define COMM_WRITE_EPROM 0x00C4 6062306a36Sopenharmony_ci#define COMM_READ_CRC_PROT_PAGE 0x00D4 6162306a36Sopenharmony_ci#define COMM_READ_REDIRECT_PAGE_CRC 0x21E4 6262306a36Sopenharmony_ci#define COMM_SEARCH_ACCESS 0x00F4 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci/* Communication command bits */ 6562306a36Sopenharmony_ci#define COMM_TYPE 0x0008 6662306a36Sopenharmony_ci#define COMM_SE 0x0008 6762306a36Sopenharmony_ci#define COMM_D 0x0008 6862306a36Sopenharmony_ci#define COMM_Z 0x0008 6962306a36Sopenharmony_ci#define COMM_CH 0x0008 7062306a36Sopenharmony_ci#define COMM_SM 0x0008 7162306a36Sopenharmony_ci#define COMM_R 0x0008 7262306a36Sopenharmony_ci#define COMM_IM 0x0001 7362306a36Sopenharmony_ci 7462306a36Sopenharmony_ci#define COMM_PS 0x4000 7562306a36Sopenharmony_ci#define COMM_PST 0x4000 7662306a36Sopenharmony_ci#define COMM_CIB 0x4000 7762306a36Sopenharmony_ci#define COMM_RTS 0x4000 7862306a36Sopenharmony_ci#define COMM_DT 0x2000 7962306a36Sopenharmony_ci#define COMM_SPU 0x1000 8062306a36Sopenharmony_ci#define COMM_F 0x0800 8162306a36Sopenharmony_ci#define COMM_NTF 0x0400 8262306a36Sopenharmony_ci#define COMM_ICP 0x0200 8362306a36Sopenharmony_ci#define COMM_RST 0x0100 8462306a36Sopenharmony_ci 8562306a36Sopenharmony_ci#define PULSE_PROG 0x01 8662306a36Sopenharmony_ci#define PULSE_SPUE 0x02 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci#define BRANCH_MAIN 0xCC 8962306a36Sopenharmony_ci#define BRANCH_AUX 0x33 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci/* Status flags */ 9262306a36Sopenharmony_ci#define ST_SPUA 0x01 /* Strong Pull-up is active */ 9362306a36Sopenharmony_ci#define ST_PRGA 0x02 /* 12V programming pulse is being generated */ 9462306a36Sopenharmony_ci#define ST_12VP 0x04 /* external 12V programming voltage is present */ 9562306a36Sopenharmony_ci#define ST_PMOD 0x08 /* DS2490 powered from USB and external sources */ 9662306a36Sopenharmony_ci#define ST_HALT 0x10 /* DS2490 is currently halted */ 9762306a36Sopenharmony_ci#define ST_IDLE 0x20 /* DS2490 is currently idle */ 9862306a36Sopenharmony_ci#define ST_EPOF 0x80 9962306a36Sopenharmony_ci/* Status transfer size, 16 bytes status, 16 byte result flags */ 10062306a36Sopenharmony_ci#define ST_SIZE 0x20 10162306a36Sopenharmony_ci 10262306a36Sopenharmony_ci/* Result Register flags */ 10362306a36Sopenharmony_ci#define RR_DETECT 0xA5 /* New device detected */ 10462306a36Sopenharmony_ci#define RR_NRS 0x01 /* Reset no presence or ... */ 10562306a36Sopenharmony_ci#define RR_SH 0x02 /* short on reset or set path */ 10662306a36Sopenharmony_ci#define RR_APP 0x04 /* alarming presence on reset */ 10762306a36Sopenharmony_ci#define RR_VPP 0x08 /* 12V expected not seen */ 10862306a36Sopenharmony_ci#define RR_CMP 0x10 /* compare error */ 10962306a36Sopenharmony_ci#define RR_CRC 0x20 /* CRC error detected */ 11062306a36Sopenharmony_ci#define RR_RDP 0x40 /* redirected page */ 11162306a36Sopenharmony_ci#define RR_EOS 0x80 /* end of search error */ 11262306a36Sopenharmony_ci 11362306a36Sopenharmony_ci#define SPEED_NORMAL 0x00 11462306a36Sopenharmony_ci#define SPEED_FLEXIBLE 0x01 11562306a36Sopenharmony_ci#define SPEED_OVERDRIVE 0x02 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci#define NUM_EP 4 11862306a36Sopenharmony_ci#define EP_CONTROL 0 11962306a36Sopenharmony_ci#define EP_STATUS 1 12062306a36Sopenharmony_ci#define EP_DATA_OUT 2 12162306a36Sopenharmony_ci#define EP_DATA_IN 3 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_cistruct ds_device { 12462306a36Sopenharmony_ci struct list_head ds_entry; 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci struct usb_device *udev; 12762306a36Sopenharmony_ci struct usb_interface *intf; 12862306a36Sopenharmony_ci 12962306a36Sopenharmony_ci int ep[NUM_EP]; 13062306a36Sopenharmony_ci 13162306a36Sopenharmony_ci /* Strong PullUp 13262306a36Sopenharmony_ci * 0: pullup not active, else duration in milliseconds 13362306a36Sopenharmony_ci */ 13462306a36Sopenharmony_ci int spu_sleep; 13562306a36Sopenharmony_ci /* spu_bit contains COMM_SPU or 0 depending on if the strong pullup 13662306a36Sopenharmony_ci * should be active or not for writes. 13762306a36Sopenharmony_ci */ 13862306a36Sopenharmony_ci u16 spu_bit; 13962306a36Sopenharmony_ci 14062306a36Sopenharmony_ci u8 st_buf[ST_SIZE]; 14162306a36Sopenharmony_ci u8 byte_buf; 14262306a36Sopenharmony_ci 14362306a36Sopenharmony_ci struct w1_bus_master master; 14462306a36Sopenharmony_ci}; 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_cistruct ds_status { 14762306a36Sopenharmony_ci u8 enable; 14862306a36Sopenharmony_ci u8 speed; 14962306a36Sopenharmony_ci u8 pullup_dur; 15062306a36Sopenharmony_ci u8 ppuls_dur; 15162306a36Sopenharmony_ci u8 pulldown_slew; 15262306a36Sopenharmony_ci u8 write1_time; 15362306a36Sopenharmony_ci u8 write0_time; 15462306a36Sopenharmony_ci u8 reserved0; 15562306a36Sopenharmony_ci u8 status; 15662306a36Sopenharmony_ci u8 command0; 15762306a36Sopenharmony_ci u8 command1; 15862306a36Sopenharmony_ci u8 command_buffer_status; 15962306a36Sopenharmony_ci u8 data_out_buffer_status; 16062306a36Sopenharmony_ci u8 data_in_buffer_status; 16162306a36Sopenharmony_ci u8 reserved1; 16262306a36Sopenharmony_ci u8 reserved2; 16362306a36Sopenharmony_ci}; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_cistatic LIST_HEAD(ds_devices); 16662306a36Sopenharmony_cistatic DEFINE_MUTEX(ds_mutex); 16762306a36Sopenharmony_ci 16862306a36Sopenharmony_cistatic int ds_send_control_cmd(struct ds_device *dev, u16 value, u16 index) 16962306a36Sopenharmony_ci{ 17062306a36Sopenharmony_ci int err; 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 17362306a36Sopenharmony_ci CONTROL_CMD, VENDOR, value, index, NULL, 0, 1000); 17462306a36Sopenharmony_ci if (err < 0) { 17562306a36Sopenharmony_ci dev_err(&dev->udev->dev, 17662306a36Sopenharmony_ci "Failed to send command control message %x.%x: err=%d.\n", 17762306a36Sopenharmony_ci value, index, err); 17862306a36Sopenharmony_ci return err; 17962306a36Sopenharmony_ci } 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_ci return err; 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_cistatic int ds_send_control_mode(struct ds_device *dev, u16 value, u16 index) 18562306a36Sopenharmony_ci{ 18662306a36Sopenharmony_ci int err; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 18962306a36Sopenharmony_ci MODE_CMD, VENDOR, value, index, NULL, 0, 1000); 19062306a36Sopenharmony_ci if (err < 0) { 19162306a36Sopenharmony_ci dev_err(&dev->udev->dev, 19262306a36Sopenharmony_ci "Failed to send mode control message %x.%x: err=%d.\n", 19362306a36Sopenharmony_ci value, index, err); 19462306a36Sopenharmony_ci return err; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci return err; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_cistatic int ds_send_control(struct ds_device *dev, u16 value, u16 index) 20162306a36Sopenharmony_ci{ 20262306a36Sopenharmony_ci int err; 20362306a36Sopenharmony_ci 20462306a36Sopenharmony_ci err = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, dev->ep[EP_CONTROL]), 20562306a36Sopenharmony_ci COMM_CMD, VENDOR, value, index, NULL, 0, 1000); 20662306a36Sopenharmony_ci if (err < 0) { 20762306a36Sopenharmony_ci dev_err(&dev->udev->dev, 20862306a36Sopenharmony_ci "Failed to send control message %x.%x: err=%d.\n", 20962306a36Sopenharmony_ci value, index, err); 21062306a36Sopenharmony_ci return err; 21162306a36Sopenharmony_ci } 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_ci return err; 21462306a36Sopenharmony_ci} 21562306a36Sopenharmony_ci 21662306a36Sopenharmony_cistatic void ds_dump_status(struct ds_device *ds_dev, unsigned char *buf, int count) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci struct device *dev = &ds_dev->udev->dev; 21962306a36Sopenharmony_ci int i; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci dev_info(dev, "ep_status=0x%x, count=%d, status=%*phC", 22262306a36Sopenharmony_ci ds_dev->ep[EP_STATUS], count, count, buf); 22362306a36Sopenharmony_ci 22462306a36Sopenharmony_ci if (count >= 16) { 22562306a36Sopenharmony_ci dev_dbg(dev, "enable flag: 0x%02x", buf[0]); 22662306a36Sopenharmony_ci dev_dbg(dev, "1-wire speed: 0x%02x", buf[1]); 22762306a36Sopenharmony_ci dev_dbg(dev, "strong pullup duration: 0x%02x", buf[2]); 22862306a36Sopenharmony_ci dev_dbg(dev, "programming pulse duration: 0x%02x", buf[3]); 22962306a36Sopenharmony_ci dev_dbg(dev, "pulldown slew rate control: 0x%02x", buf[4]); 23062306a36Sopenharmony_ci dev_dbg(dev, "write-1 low time: 0x%02x", buf[5]); 23162306a36Sopenharmony_ci dev_dbg(dev, "data sample offset/write-0 recovery time: 0x%02x", buf[6]); 23262306a36Sopenharmony_ci dev_dbg(dev, "reserved (test register): 0x%02x", buf[7]); 23362306a36Sopenharmony_ci dev_dbg(dev, "device status flags: 0x%02x", buf[8]); 23462306a36Sopenharmony_ci dev_dbg(dev, "communication command byte 1: 0x%02x", buf[9]); 23562306a36Sopenharmony_ci dev_dbg(dev, "communication command byte 2: 0x%02x", buf[10]); 23662306a36Sopenharmony_ci dev_dbg(dev, "communication command buffer status: 0x%02x", buf[11]); 23762306a36Sopenharmony_ci dev_dbg(dev, "1-wire data output buffer status: 0x%02x", buf[12]); 23862306a36Sopenharmony_ci dev_dbg(dev, "1-wire data input buffer status: 0x%02x", buf[13]); 23962306a36Sopenharmony_ci dev_dbg(dev, "reserved: 0x%02x", buf[14]); 24062306a36Sopenharmony_ci dev_dbg(dev, "reserved: 0x%02x", buf[15]); 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci for (i = 16; i < count; ++i) { 24462306a36Sopenharmony_ci if (buf[i] == RR_DETECT) { 24562306a36Sopenharmony_ci dev_dbg(dev, "New device detect.\n"); 24662306a36Sopenharmony_ci continue; 24762306a36Sopenharmony_ci } 24862306a36Sopenharmony_ci dev_dbg(dev, "Result Register Value: 0x%02x", buf[i]); 24962306a36Sopenharmony_ci if (buf[i] & RR_NRS) 25062306a36Sopenharmony_ci dev_dbg(dev, "NRS: Reset no presence or ...\n"); 25162306a36Sopenharmony_ci if (buf[i] & RR_SH) 25262306a36Sopenharmony_ci dev_dbg(dev, "SH: short on reset or set path\n"); 25362306a36Sopenharmony_ci if (buf[i] & RR_APP) 25462306a36Sopenharmony_ci dev_dbg(dev, "APP: alarming presence on reset\n"); 25562306a36Sopenharmony_ci if (buf[i] & RR_VPP) 25662306a36Sopenharmony_ci dev_dbg(dev, "VPP: 12V expected not seen\n"); 25762306a36Sopenharmony_ci if (buf[i] & RR_CMP) 25862306a36Sopenharmony_ci dev_dbg(dev, "CMP: compare error\n"); 25962306a36Sopenharmony_ci if (buf[i] & RR_CRC) 26062306a36Sopenharmony_ci dev_dbg(dev, "CRC: CRC error detected\n"); 26162306a36Sopenharmony_ci if (buf[i] & RR_RDP) 26262306a36Sopenharmony_ci dev_dbg(dev, "RDP: redirected page\n"); 26362306a36Sopenharmony_ci if (buf[i] & RR_EOS) 26462306a36Sopenharmony_ci dev_dbg(dev, "EOS: end of search error\n"); 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci} 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_cistatic int ds_recv_status(struct ds_device *dev, struct ds_status *st) 26962306a36Sopenharmony_ci{ 27062306a36Sopenharmony_ci int count, err; 27162306a36Sopenharmony_ci 27262306a36Sopenharmony_ci if (st) 27362306a36Sopenharmony_ci memset(st, 0, sizeof(*st)); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ci count = 0; 27662306a36Sopenharmony_ci err = usb_interrupt_msg(dev->udev, 27762306a36Sopenharmony_ci usb_rcvintpipe(dev->udev, 27862306a36Sopenharmony_ci dev->ep[EP_STATUS]), 27962306a36Sopenharmony_ci dev->st_buf, sizeof(dev->st_buf), 28062306a36Sopenharmony_ci &count, 1000); 28162306a36Sopenharmony_ci if (err < 0) { 28262306a36Sopenharmony_ci dev_err(&dev->udev->dev, 28362306a36Sopenharmony_ci "Failed to read 1-wire data from 0x%x: err=%d.\n", 28462306a36Sopenharmony_ci dev->ep[EP_STATUS], err); 28562306a36Sopenharmony_ci return err; 28662306a36Sopenharmony_ci } 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci if (st && count >= sizeof(*st)) 28962306a36Sopenharmony_ci memcpy(st, dev->st_buf, sizeof(*st)); 29062306a36Sopenharmony_ci 29162306a36Sopenharmony_ci return count; 29262306a36Sopenharmony_ci} 29362306a36Sopenharmony_ci 29462306a36Sopenharmony_cistatic void ds_reset_device(struct ds_device *dev) 29562306a36Sopenharmony_ci{ 29662306a36Sopenharmony_ci ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); 29762306a36Sopenharmony_ci /* Always allow strong pullup which allow individual writes to use 29862306a36Sopenharmony_ci * the strong pullup. 29962306a36Sopenharmony_ci */ 30062306a36Sopenharmony_ci if (ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_SPUE)) 30162306a36Sopenharmony_ci dev_err(&dev->udev->dev, 30262306a36Sopenharmony_ci "%s: Error allowing strong pullup\n", __func__); 30362306a36Sopenharmony_ci /* Chip strong pullup time was cleared. */ 30462306a36Sopenharmony_ci if (dev->spu_sleep) { 30562306a36Sopenharmony_ci /* lower 4 bits are 0, see ds_set_pullup */ 30662306a36Sopenharmony_ci u8 del = dev->spu_sleep>>4; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci if (ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del)) 30962306a36Sopenharmony_ci dev_err(&dev->udev->dev, 31062306a36Sopenharmony_ci "%s: Error setting duration\n", __func__); 31162306a36Sopenharmony_ci } 31262306a36Sopenharmony_ci} 31362306a36Sopenharmony_ci 31462306a36Sopenharmony_cistatic int ds_recv_data(struct ds_device *dev, unsigned char *buf, int size) 31562306a36Sopenharmony_ci{ 31662306a36Sopenharmony_ci int count, err; 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_ci /* Careful on size. If size is less than what is available in 31962306a36Sopenharmony_ci * the input buffer, the device fails the bulk transfer and 32062306a36Sopenharmony_ci * clears the input buffer. It could read the maximum size of 32162306a36Sopenharmony_ci * the data buffer, but then do you return the first, last, or 32262306a36Sopenharmony_ci * some set of the middle size bytes? As long as the rest of 32362306a36Sopenharmony_ci * the code is correct there will be size bytes waiting. A 32462306a36Sopenharmony_ci * call to ds_wait_status will wait until the device is idle 32562306a36Sopenharmony_ci * and any data to be received would have been available. 32662306a36Sopenharmony_ci */ 32762306a36Sopenharmony_ci count = 0; 32862306a36Sopenharmony_ci err = usb_bulk_msg(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN]), 32962306a36Sopenharmony_ci buf, size, &count, 1000); 33062306a36Sopenharmony_ci if (err < 0) { 33162306a36Sopenharmony_ci int recv_len; 33262306a36Sopenharmony_ci 33362306a36Sopenharmony_ci dev_info(&dev->udev->dev, "Clearing ep0x%x.\n", dev->ep[EP_DATA_IN]); 33462306a36Sopenharmony_ci usb_clear_halt(dev->udev, usb_rcvbulkpipe(dev->udev, dev->ep[EP_DATA_IN])); 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci /* status might tell us why endpoint is stuck? */ 33762306a36Sopenharmony_ci recv_len = ds_recv_status(dev, NULL); 33862306a36Sopenharmony_ci if (recv_len >= 0) 33962306a36Sopenharmony_ci ds_dump_status(dev, dev->st_buf, recv_len); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci return err; 34262306a36Sopenharmony_ci } 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci#if 0 34562306a36Sopenharmony_ci { 34662306a36Sopenharmony_ci int i; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci printk("%s: count=%d: ", __func__, count); 34962306a36Sopenharmony_ci for (i = 0; i < count; ++i) 35062306a36Sopenharmony_ci printk("%02x ", buf[i]); 35162306a36Sopenharmony_ci printk("\n"); 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci#endif 35462306a36Sopenharmony_ci return count; 35562306a36Sopenharmony_ci} 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_cistatic int ds_send_data(struct ds_device *dev, unsigned char *buf, int len) 35862306a36Sopenharmony_ci{ 35962306a36Sopenharmony_ci int count, err; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_ci count = 0; 36262306a36Sopenharmony_ci err = usb_bulk_msg(dev->udev, usb_sndbulkpipe(dev->udev, dev->ep[EP_DATA_OUT]), buf, len, &count, 1000); 36362306a36Sopenharmony_ci if (err < 0) { 36462306a36Sopenharmony_ci dev_err(&dev->udev->dev, "Failed to write 1-wire data to ep0x%x: " 36562306a36Sopenharmony_ci "err=%d.\n", dev->ep[EP_DATA_OUT], err); 36662306a36Sopenharmony_ci return err; 36762306a36Sopenharmony_ci } 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci return err; 37062306a36Sopenharmony_ci} 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci#if 0 37362306a36Sopenharmony_ci 37462306a36Sopenharmony_ciint ds_stop_pulse(struct ds_device *dev, int limit) 37562306a36Sopenharmony_ci{ 37662306a36Sopenharmony_ci struct ds_status st; 37762306a36Sopenharmony_ci int count = 0, err = 0; 37862306a36Sopenharmony_ci 37962306a36Sopenharmony_ci do { 38062306a36Sopenharmony_ci err = ds_send_control(dev, CTL_HALT_EXE_IDLE, 0); 38162306a36Sopenharmony_ci if (err) 38262306a36Sopenharmony_ci break; 38362306a36Sopenharmony_ci err = ds_send_control(dev, CTL_RESUME_EXE, 0); 38462306a36Sopenharmony_ci if (err) 38562306a36Sopenharmony_ci break; 38662306a36Sopenharmony_ci err = ds_recv_status(dev, &st); 38762306a36Sopenharmony_ci if (err) 38862306a36Sopenharmony_ci break; 38962306a36Sopenharmony_ci 39062306a36Sopenharmony_ci if ((st.status & ST_SPUA) == 0) { 39162306a36Sopenharmony_ci err = ds_send_control_mode(dev, MOD_PULSE_EN, 0); 39262306a36Sopenharmony_ci if (err) 39362306a36Sopenharmony_ci break; 39462306a36Sopenharmony_ci } 39562306a36Sopenharmony_ci } while (++count < limit); 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci return err; 39862306a36Sopenharmony_ci} 39962306a36Sopenharmony_ci 40062306a36Sopenharmony_ciint ds_detect(struct ds_device *dev, struct ds_status *st) 40162306a36Sopenharmony_ci{ 40262306a36Sopenharmony_ci int err; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci err = ds_send_control_cmd(dev, CTL_RESET_DEVICE, 0); 40562306a36Sopenharmony_ci if (err) 40662306a36Sopenharmony_ci return err; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, 0); 40962306a36Sopenharmony_ci if (err) 41062306a36Sopenharmony_ci return err; 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM | COMM_TYPE, 0x40); 41362306a36Sopenharmony_ci if (err) 41462306a36Sopenharmony_ci return err; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci err = ds_send_control_mode(dev, MOD_PULSE_EN, PULSE_PROG); 41762306a36Sopenharmony_ci if (err) 41862306a36Sopenharmony_ci return err; 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_ci err = ds_dump_status(dev, st); 42162306a36Sopenharmony_ci 42262306a36Sopenharmony_ci return err; 42362306a36Sopenharmony_ci} 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci#endif /* 0 */ 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_cistatic int ds_wait_status(struct ds_device *dev, struct ds_status *st) 42862306a36Sopenharmony_ci{ 42962306a36Sopenharmony_ci int err, count = 0; 43062306a36Sopenharmony_ci 43162306a36Sopenharmony_ci do { 43262306a36Sopenharmony_ci st->status = 0; 43362306a36Sopenharmony_ci err = ds_recv_status(dev, st); 43462306a36Sopenharmony_ci#if 0 43562306a36Sopenharmony_ci if (err >= 0) { 43662306a36Sopenharmony_ci int i; 43762306a36Sopenharmony_ci printk("0x%x: count=%d, status: ", dev->ep[EP_STATUS], err); 43862306a36Sopenharmony_ci for (i = 0; i < err; ++i) 43962306a36Sopenharmony_ci printk("%02x ", dev->st_buf[i]); 44062306a36Sopenharmony_ci printk("\n"); 44162306a36Sopenharmony_ci } 44262306a36Sopenharmony_ci#endif 44362306a36Sopenharmony_ci } while (!(st->status & ST_IDLE) && !(err < 0) && ++count < 100); 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci if (err >= 16 && st->status & ST_EPOF) { 44662306a36Sopenharmony_ci dev_info(&dev->udev->dev, "Resetting device after ST_EPOF.\n"); 44762306a36Sopenharmony_ci ds_reset_device(dev); 44862306a36Sopenharmony_ci /* Always dump the device status. */ 44962306a36Sopenharmony_ci count = 101; 45062306a36Sopenharmony_ci } 45162306a36Sopenharmony_ci 45262306a36Sopenharmony_ci /* Dump the status for errors or if there is extended return data. 45362306a36Sopenharmony_ci * The extended status includes new device detection (maybe someone 45462306a36Sopenharmony_ci * can do something with it). 45562306a36Sopenharmony_ci */ 45662306a36Sopenharmony_ci if (err > 16 || count >= 100 || err < 0) 45762306a36Sopenharmony_ci ds_dump_status(dev, dev->st_buf, err); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci /* Extended data isn't an error. Well, a short is, but the dump 46062306a36Sopenharmony_ci * would have already told the user that and we can't do anything 46162306a36Sopenharmony_ci * about it in software anyway. 46262306a36Sopenharmony_ci */ 46362306a36Sopenharmony_ci if (count >= 100 || err < 0) 46462306a36Sopenharmony_ci return -1; 46562306a36Sopenharmony_ci else 46662306a36Sopenharmony_ci return 0; 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_cistatic int ds_reset(struct ds_device *dev) 47062306a36Sopenharmony_ci{ 47162306a36Sopenharmony_ci int err; 47262306a36Sopenharmony_ci 47362306a36Sopenharmony_ci /* Other potentionally interesting flags for reset. 47462306a36Sopenharmony_ci * 47562306a36Sopenharmony_ci * COMM_NTF: Return result register feedback. This could be used to 47662306a36Sopenharmony_ci * detect some conditions such as short, alarming presence, or 47762306a36Sopenharmony_ci * detect if a new device was detected. 47862306a36Sopenharmony_ci * 47962306a36Sopenharmony_ci * COMM_SE which allows SPEED_NORMAL, SPEED_FLEXIBLE, SPEED_OVERDRIVE: 48062306a36Sopenharmony_ci * Select the data transfer rate. 48162306a36Sopenharmony_ci */ 48262306a36Sopenharmony_ci err = ds_send_control(dev, COMM_1_WIRE_RESET | COMM_IM, SPEED_NORMAL); 48362306a36Sopenharmony_ci if (err) 48462306a36Sopenharmony_ci return err; 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci return 0; 48762306a36Sopenharmony_ci} 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci#if 0 49062306a36Sopenharmony_cistatic int ds_set_speed(struct ds_device *dev, int speed) 49162306a36Sopenharmony_ci{ 49262306a36Sopenharmony_ci int err; 49362306a36Sopenharmony_ci 49462306a36Sopenharmony_ci if (speed != SPEED_NORMAL && speed != SPEED_FLEXIBLE && speed != SPEED_OVERDRIVE) 49562306a36Sopenharmony_ci return -EINVAL; 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci if (speed != SPEED_OVERDRIVE) 49862306a36Sopenharmony_ci speed = SPEED_FLEXIBLE; 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci speed &= 0xff; 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci err = ds_send_control_mode(dev, MOD_1WIRE_SPEED, speed); 50362306a36Sopenharmony_ci if (err) 50462306a36Sopenharmony_ci return err; 50562306a36Sopenharmony_ci 50662306a36Sopenharmony_ci return err; 50762306a36Sopenharmony_ci} 50862306a36Sopenharmony_ci#endif /* 0 */ 50962306a36Sopenharmony_ci 51062306a36Sopenharmony_cistatic int ds_set_pullup(struct ds_device *dev, int delay) 51162306a36Sopenharmony_ci{ 51262306a36Sopenharmony_ci int err = 0; 51362306a36Sopenharmony_ci u8 del = 1 + (u8)(delay >> 4); 51462306a36Sopenharmony_ci /* Just storing delay would not get the trunication and roundup. */ 51562306a36Sopenharmony_ci int ms = del<<4; 51662306a36Sopenharmony_ci 51762306a36Sopenharmony_ci /* Enable spu_bit if a delay is set. */ 51862306a36Sopenharmony_ci dev->spu_bit = delay ? COMM_SPU : 0; 51962306a36Sopenharmony_ci /* If delay is zero, it has already been disabled, if the time is 52062306a36Sopenharmony_ci * the same as the hardware was last programmed to, there is also 52162306a36Sopenharmony_ci * nothing more to do. Compare with the recalculated value ms 52262306a36Sopenharmony_ci * rather than del or delay which can have a different value. 52362306a36Sopenharmony_ci */ 52462306a36Sopenharmony_ci if (delay == 0 || ms == dev->spu_sleep) 52562306a36Sopenharmony_ci return err; 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci err = ds_send_control(dev, COMM_SET_DURATION | COMM_IM, del); 52862306a36Sopenharmony_ci if (err) 52962306a36Sopenharmony_ci return err; 53062306a36Sopenharmony_ci 53162306a36Sopenharmony_ci dev->spu_sleep = ms; 53262306a36Sopenharmony_ci 53362306a36Sopenharmony_ci return err; 53462306a36Sopenharmony_ci} 53562306a36Sopenharmony_ci 53662306a36Sopenharmony_cistatic int ds_touch_bit(struct ds_device *dev, u8 bit, u8 *tbit) 53762306a36Sopenharmony_ci{ 53862306a36Sopenharmony_ci int err; 53962306a36Sopenharmony_ci struct ds_status st; 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_ci err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | (bit ? COMM_D : 0), 54262306a36Sopenharmony_ci 0); 54362306a36Sopenharmony_ci if (err) 54462306a36Sopenharmony_ci return err; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci ds_wait_status(dev, &st); 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci err = ds_recv_data(dev, tbit, sizeof(*tbit)); 54962306a36Sopenharmony_ci if (err < 0) 55062306a36Sopenharmony_ci return err; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci return 0; 55362306a36Sopenharmony_ci} 55462306a36Sopenharmony_ci 55562306a36Sopenharmony_ci#if 0 55662306a36Sopenharmony_cistatic int ds_write_bit(struct ds_device *dev, u8 bit) 55762306a36Sopenharmony_ci{ 55862306a36Sopenharmony_ci int err; 55962306a36Sopenharmony_ci struct ds_status st; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci /* Set COMM_ICP to write without a readback. Note, this will 56262306a36Sopenharmony_ci * produce one time slot, a down followed by an up with COMM_D 56362306a36Sopenharmony_ci * only determing the timing. 56462306a36Sopenharmony_ci */ 56562306a36Sopenharmony_ci err = ds_send_control(dev, COMM_BIT_IO | COMM_IM | COMM_ICP | 56662306a36Sopenharmony_ci (bit ? COMM_D : 0), 0); 56762306a36Sopenharmony_ci if (err) 56862306a36Sopenharmony_ci return err; 56962306a36Sopenharmony_ci 57062306a36Sopenharmony_ci ds_wait_status(dev, &st); 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_ci return 0; 57362306a36Sopenharmony_ci} 57462306a36Sopenharmony_ci#endif 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_cistatic int ds_write_byte(struct ds_device *dev, u8 byte) 57762306a36Sopenharmony_ci{ 57862306a36Sopenharmony_ci int err; 57962306a36Sopenharmony_ci struct ds_status st; 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_ci err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM | dev->spu_bit, byte); 58262306a36Sopenharmony_ci if (err) 58362306a36Sopenharmony_ci return err; 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci if (dev->spu_bit) 58662306a36Sopenharmony_ci msleep(dev->spu_sleep); 58762306a36Sopenharmony_ci 58862306a36Sopenharmony_ci err = ds_wait_status(dev, &st); 58962306a36Sopenharmony_ci if (err) 59062306a36Sopenharmony_ci return err; 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci err = ds_recv_data(dev, &dev->byte_buf, 1); 59362306a36Sopenharmony_ci if (err < 0) 59462306a36Sopenharmony_ci return err; 59562306a36Sopenharmony_ci 59662306a36Sopenharmony_ci return !(byte == dev->byte_buf); 59762306a36Sopenharmony_ci} 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_cistatic int ds_read_byte(struct ds_device *dev, u8 *byte) 60062306a36Sopenharmony_ci{ 60162306a36Sopenharmony_ci int err; 60262306a36Sopenharmony_ci struct ds_status st; 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci err = ds_send_control(dev, COMM_BYTE_IO | COMM_IM, 0xff); 60562306a36Sopenharmony_ci if (err) 60662306a36Sopenharmony_ci return err; 60762306a36Sopenharmony_ci 60862306a36Sopenharmony_ci ds_wait_status(dev, &st); 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci err = ds_recv_data(dev, byte, sizeof(*byte)); 61162306a36Sopenharmony_ci if (err < 0) 61262306a36Sopenharmony_ci return err; 61362306a36Sopenharmony_ci 61462306a36Sopenharmony_ci return 0; 61562306a36Sopenharmony_ci} 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_cistatic int ds_read_block(struct ds_device *dev, u8 *buf, int len) 61862306a36Sopenharmony_ci{ 61962306a36Sopenharmony_ci struct ds_status st; 62062306a36Sopenharmony_ci int err; 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_ci if (len > 64*1024) 62362306a36Sopenharmony_ci return -E2BIG; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci memset(buf, 0xFF, len); 62662306a36Sopenharmony_ci 62762306a36Sopenharmony_ci err = ds_send_data(dev, buf, len); 62862306a36Sopenharmony_ci if (err < 0) 62962306a36Sopenharmony_ci return err; 63062306a36Sopenharmony_ci 63162306a36Sopenharmony_ci err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM, len); 63262306a36Sopenharmony_ci if (err) 63362306a36Sopenharmony_ci return err; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci ds_wait_status(dev, &st); 63662306a36Sopenharmony_ci 63762306a36Sopenharmony_ci memset(buf, 0x00, len); 63862306a36Sopenharmony_ci err = ds_recv_data(dev, buf, len); 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci return err; 64162306a36Sopenharmony_ci} 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_cistatic int ds_write_block(struct ds_device *dev, u8 *buf, int len) 64462306a36Sopenharmony_ci{ 64562306a36Sopenharmony_ci int err; 64662306a36Sopenharmony_ci struct ds_status st; 64762306a36Sopenharmony_ci 64862306a36Sopenharmony_ci err = ds_send_data(dev, buf, len); 64962306a36Sopenharmony_ci if (err < 0) 65062306a36Sopenharmony_ci return err; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci err = ds_send_control(dev, COMM_BLOCK_IO | COMM_IM | dev->spu_bit, len); 65362306a36Sopenharmony_ci if (err) 65462306a36Sopenharmony_ci return err; 65562306a36Sopenharmony_ci 65662306a36Sopenharmony_ci if (dev->spu_bit) 65762306a36Sopenharmony_ci msleep(dev->spu_sleep); 65862306a36Sopenharmony_ci 65962306a36Sopenharmony_ci ds_wait_status(dev, &st); 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci err = ds_recv_data(dev, buf, len); 66262306a36Sopenharmony_ci if (err < 0) 66362306a36Sopenharmony_ci return err; 66462306a36Sopenharmony_ci 66562306a36Sopenharmony_ci return !(err == len); 66662306a36Sopenharmony_ci} 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_cistatic void ds9490r_search(void *data, struct w1_master *master, 66962306a36Sopenharmony_ci u8 search_type, w1_slave_found_callback callback) 67062306a36Sopenharmony_ci{ 67162306a36Sopenharmony_ci /* When starting with an existing id, the first id returned will 67262306a36Sopenharmony_ci * be that device (if it is still on the bus most likely). 67362306a36Sopenharmony_ci * 67462306a36Sopenharmony_ci * If the number of devices found is less than or equal to the 67562306a36Sopenharmony_ci * search_limit, that number of IDs will be returned. If there are 67662306a36Sopenharmony_ci * more, search_limit IDs will be returned followed by a non-zero 67762306a36Sopenharmony_ci * discrepency value. 67862306a36Sopenharmony_ci */ 67962306a36Sopenharmony_ci struct ds_device *dev = data; 68062306a36Sopenharmony_ci int err; 68162306a36Sopenharmony_ci u16 value, index; 68262306a36Sopenharmony_ci struct ds_status st; 68362306a36Sopenharmony_ci int search_limit; 68462306a36Sopenharmony_ci int found = 0; 68562306a36Sopenharmony_ci int i; 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci /* DS18b20 spec, 13.16 ms per device, 75 per second, sleep for 68862306a36Sopenharmony_ci * discovering 8 devices (1 bulk transfer and 1/2 FIFO size) at a time. 68962306a36Sopenharmony_ci */ 69062306a36Sopenharmony_ci const unsigned long jtime = msecs_to_jiffies(1000*8/75); 69162306a36Sopenharmony_ci /* FIFO 128 bytes, bulk packet size 64, read a multiple of the 69262306a36Sopenharmony_ci * packet size. 69362306a36Sopenharmony_ci */ 69462306a36Sopenharmony_ci const size_t bufsize = 2 * 64; 69562306a36Sopenharmony_ci u64 *buf, *found_ids; 69662306a36Sopenharmony_ci 69762306a36Sopenharmony_ci buf = kmalloc(bufsize, GFP_KERNEL); 69862306a36Sopenharmony_ci if (!buf) 69962306a36Sopenharmony_ci return; 70062306a36Sopenharmony_ci 70162306a36Sopenharmony_ci /* 70262306a36Sopenharmony_ci * We are holding the bus mutex during the scan, but adding devices via the 70362306a36Sopenharmony_ci * callback needs the bus to be unlocked. So we queue up found ids here. 70462306a36Sopenharmony_ci */ 70562306a36Sopenharmony_ci found_ids = kmalloc_array(master->max_slave_count, sizeof(u64), GFP_KERNEL); 70662306a36Sopenharmony_ci if (!found_ids) { 70762306a36Sopenharmony_ci kfree(buf); 70862306a36Sopenharmony_ci return; 70962306a36Sopenharmony_ci } 71062306a36Sopenharmony_ci 71162306a36Sopenharmony_ci mutex_lock(&master->bus_mutex); 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_ci /* address to start searching at */ 71462306a36Sopenharmony_ci if (ds_send_data(dev, (u8 *)&master->search_id, 8) < 0) 71562306a36Sopenharmony_ci goto search_out; 71662306a36Sopenharmony_ci master->search_id = 0; 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci value = COMM_SEARCH_ACCESS | COMM_IM | COMM_RST | COMM_SM | COMM_F | 71962306a36Sopenharmony_ci COMM_RTS; 72062306a36Sopenharmony_ci search_limit = master->max_slave_count; 72162306a36Sopenharmony_ci if (search_limit > 255) 72262306a36Sopenharmony_ci search_limit = 0; 72362306a36Sopenharmony_ci index = search_type | (search_limit << 8); 72462306a36Sopenharmony_ci if (ds_send_control(dev, value, index) < 0) 72562306a36Sopenharmony_ci goto search_out; 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci do { 72862306a36Sopenharmony_ci schedule_timeout(jtime); 72962306a36Sopenharmony_ci 73062306a36Sopenharmony_ci err = ds_recv_status(dev, &st); 73162306a36Sopenharmony_ci if (err < 0 || err < sizeof(st)) 73262306a36Sopenharmony_ci break; 73362306a36Sopenharmony_ci 73462306a36Sopenharmony_ci if (st.data_in_buffer_status) { 73562306a36Sopenharmony_ci /* 73662306a36Sopenharmony_ci * Bulk in can receive partial ids, but when it does 73762306a36Sopenharmony_ci * they fail crc and will be discarded anyway. 73862306a36Sopenharmony_ci * That has only been seen when status in buffer 73962306a36Sopenharmony_ci * is 0 and bulk is read anyway, so don't read 74062306a36Sopenharmony_ci * bulk without first checking if status says there 74162306a36Sopenharmony_ci * is data to read. 74262306a36Sopenharmony_ci */ 74362306a36Sopenharmony_ci err = ds_recv_data(dev, (u8 *)buf, bufsize); 74462306a36Sopenharmony_ci if (err < 0) 74562306a36Sopenharmony_ci break; 74662306a36Sopenharmony_ci for (i = 0; i < err/8; ++i) { 74762306a36Sopenharmony_ci found_ids[found++] = buf[i]; 74862306a36Sopenharmony_ci /* 74962306a36Sopenharmony_ci * can't know if there will be a discrepancy 75062306a36Sopenharmony_ci * value after until the next id 75162306a36Sopenharmony_ci */ 75262306a36Sopenharmony_ci if (found == search_limit) { 75362306a36Sopenharmony_ci master->search_id = buf[i]; 75462306a36Sopenharmony_ci break; 75562306a36Sopenharmony_ci } 75662306a36Sopenharmony_ci } 75762306a36Sopenharmony_ci } 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci if (test_bit(W1_ABORT_SEARCH, &master->flags)) 76062306a36Sopenharmony_ci break; 76162306a36Sopenharmony_ci } while (!(st.status & (ST_IDLE | ST_HALT))); 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci /* only continue the search if some weren't found */ 76462306a36Sopenharmony_ci if (found <= search_limit) { 76562306a36Sopenharmony_ci master->search_id = 0; 76662306a36Sopenharmony_ci } else if (!test_bit(W1_WARN_MAX_COUNT, &master->flags)) { 76762306a36Sopenharmony_ci /* 76862306a36Sopenharmony_ci * Only max_slave_count will be scanned in a search, 76962306a36Sopenharmony_ci * but it will start where it left off next search 77062306a36Sopenharmony_ci * until all ids are identified and then it will start 77162306a36Sopenharmony_ci * over. A continued search will report the previous 77262306a36Sopenharmony_ci * last id as the first id (provided it is still on the 77362306a36Sopenharmony_ci * bus). 77462306a36Sopenharmony_ci */ 77562306a36Sopenharmony_ci dev_info(&dev->udev->dev, "%s: max_slave_count %d reached, " 77662306a36Sopenharmony_ci "will continue next search.\n", __func__, 77762306a36Sopenharmony_ci master->max_slave_count); 77862306a36Sopenharmony_ci set_bit(W1_WARN_MAX_COUNT, &master->flags); 77962306a36Sopenharmony_ci } 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_cisearch_out: 78262306a36Sopenharmony_ci mutex_unlock(&master->bus_mutex); 78362306a36Sopenharmony_ci kfree(buf); 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci for (i = 0; i < found; i++) /* run callback for all queued up IDs */ 78662306a36Sopenharmony_ci callback(master, found_ids[i]); 78762306a36Sopenharmony_ci kfree(found_ids); 78862306a36Sopenharmony_ci} 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci#if 0 79162306a36Sopenharmony_ci/* 79262306a36Sopenharmony_ci * FIXME: if this disabled code is ever used in the future all ds_send_data() 79362306a36Sopenharmony_ci * calls must be changed to use a DMAable buffer. 79462306a36Sopenharmony_ci */ 79562306a36Sopenharmony_cistatic int ds_match_access(struct ds_device *dev, u64 init) 79662306a36Sopenharmony_ci{ 79762306a36Sopenharmony_ci int err; 79862306a36Sopenharmony_ci struct ds_status st; 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci err = ds_send_data(dev, (unsigned char *)&init, sizeof(init)); 80162306a36Sopenharmony_ci if (err) 80262306a36Sopenharmony_ci return err; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci ds_wait_status(dev, &st); 80562306a36Sopenharmony_ci 80662306a36Sopenharmony_ci err = ds_send_control(dev, COMM_MATCH_ACCESS | COMM_IM | COMM_RST, 0x0055); 80762306a36Sopenharmony_ci if (err) 80862306a36Sopenharmony_ci return err; 80962306a36Sopenharmony_ci 81062306a36Sopenharmony_ci ds_wait_status(dev, &st); 81162306a36Sopenharmony_ci 81262306a36Sopenharmony_ci return 0; 81362306a36Sopenharmony_ci} 81462306a36Sopenharmony_ci 81562306a36Sopenharmony_cistatic int ds_set_path(struct ds_device *dev, u64 init) 81662306a36Sopenharmony_ci{ 81762306a36Sopenharmony_ci int err; 81862306a36Sopenharmony_ci struct ds_status st; 81962306a36Sopenharmony_ci u8 buf[9]; 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci memcpy(buf, &init, 8); 82262306a36Sopenharmony_ci buf[8] = BRANCH_MAIN; 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci err = ds_send_data(dev, buf, sizeof(buf)); 82562306a36Sopenharmony_ci if (err) 82662306a36Sopenharmony_ci return err; 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci ds_wait_status(dev, &st); 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci err = ds_send_control(dev, COMM_SET_PATH | COMM_IM | COMM_RST, 0); 83162306a36Sopenharmony_ci if (err) 83262306a36Sopenharmony_ci return err; 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci ds_wait_status(dev, &st); 83562306a36Sopenharmony_ci 83662306a36Sopenharmony_ci return 0; 83762306a36Sopenharmony_ci} 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_ci#endif /* 0 */ 84062306a36Sopenharmony_ci 84162306a36Sopenharmony_cistatic u8 ds9490r_touch_bit(void *data, u8 bit) 84262306a36Sopenharmony_ci{ 84362306a36Sopenharmony_ci struct ds_device *dev = data; 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci if (ds_touch_bit(dev, bit, &dev->byte_buf)) 84662306a36Sopenharmony_ci return 0; 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci return dev->byte_buf; 84962306a36Sopenharmony_ci} 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci#if 0 85262306a36Sopenharmony_cistatic void ds9490r_write_bit(void *data, u8 bit) 85362306a36Sopenharmony_ci{ 85462306a36Sopenharmony_ci struct ds_device *dev = data; 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci ds_write_bit(dev, bit); 85762306a36Sopenharmony_ci} 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_cistatic u8 ds9490r_read_bit(void *data) 86062306a36Sopenharmony_ci{ 86162306a36Sopenharmony_ci struct ds_device *dev = data; 86262306a36Sopenharmony_ci int err; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci err = ds_touch_bit(dev, 1, &dev->byte_buf); 86562306a36Sopenharmony_ci if (err) 86662306a36Sopenharmony_ci return 0; 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci return dev->byte_buf & 1; 86962306a36Sopenharmony_ci} 87062306a36Sopenharmony_ci#endif 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_cistatic void ds9490r_write_byte(void *data, u8 byte) 87362306a36Sopenharmony_ci{ 87462306a36Sopenharmony_ci struct ds_device *dev = data; 87562306a36Sopenharmony_ci 87662306a36Sopenharmony_ci ds_write_byte(dev, byte); 87762306a36Sopenharmony_ci} 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_cistatic u8 ds9490r_read_byte(void *data) 88062306a36Sopenharmony_ci{ 88162306a36Sopenharmony_ci struct ds_device *dev = data; 88262306a36Sopenharmony_ci int err; 88362306a36Sopenharmony_ci 88462306a36Sopenharmony_ci err = ds_read_byte(dev, &dev->byte_buf); 88562306a36Sopenharmony_ci if (err) 88662306a36Sopenharmony_ci return 0; 88762306a36Sopenharmony_ci 88862306a36Sopenharmony_ci return dev->byte_buf; 88962306a36Sopenharmony_ci} 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_cistatic void ds9490r_write_block(void *data, const u8 *buf, int len) 89262306a36Sopenharmony_ci{ 89362306a36Sopenharmony_ci struct ds_device *dev = data; 89462306a36Sopenharmony_ci u8 *tbuf; 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci if (len <= 0) 89762306a36Sopenharmony_ci return; 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci tbuf = kmemdup(buf, len, GFP_KERNEL); 90062306a36Sopenharmony_ci if (!tbuf) 90162306a36Sopenharmony_ci return; 90262306a36Sopenharmony_ci 90362306a36Sopenharmony_ci ds_write_block(dev, tbuf, len); 90462306a36Sopenharmony_ci 90562306a36Sopenharmony_ci kfree(tbuf); 90662306a36Sopenharmony_ci} 90762306a36Sopenharmony_ci 90862306a36Sopenharmony_cistatic u8 ds9490r_read_block(void *data, u8 *buf, int len) 90962306a36Sopenharmony_ci{ 91062306a36Sopenharmony_ci struct ds_device *dev = data; 91162306a36Sopenharmony_ci int err; 91262306a36Sopenharmony_ci u8 *tbuf; 91362306a36Sopenharmony_ci 91462306a36Sopenharmony_ci if (len <= 0) 91562306a36Sopenharmony_ci return 0; 91662306a36Sopenharmony_ci 91762306a36Sopenharmony_ci tbuf = kmalloc(len, GFP_KERNEL); 91862306a36Sopenharmony_ci if (!tbuf) 91962306a36Sopenharmony_ci return 0; 92062306a36Sopenharmony_ci 92162306a36Sopenharmony_ci err = ds_read_block(dev, tbuf, len); 92262306a36Sopenharmony_ci if (err >= 0) 92362306a36Sopenharmony_ci memcpy(buf, tbuf, len); 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci kfree(tbuf); 92662306a36Sopenharmony_ci 92762306a36Sopenharmony_ci return err >= 0 ? len : 0; 92862306a36Sopenharmony_ci} 92962306a36Sopenharmony_ci 93062306a36Sopenharmony_cistatic u8 ds9490r_reset(void *data) 93162306a36Sopenharmony_ci{ 93262306a36Sopenharmony_ci struct ds_device *dev = data; 93362306a36Sopenharmony_ci int err; 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci err = ds_reset(dev); 93662306a36Sopenharmony_ci if (err) 93762306a36Sopenharmony_ci return 1; 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci return 0; 94062306a36Sopenharmony_ci} 94162306a36Sopenharmony_ci 94262306a36Sopenharmony_cistatic u8 ds9490r_set_pullup(void *data, int delay) 94362306a36Sopenharmony_ci{ 94462306a36Sopenharmony_ci struct ds_device *dev = data; 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_ci if (ds_set_pullup(dev, delay)) 94762306a36Sopenharmony_ci return 1; 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci return 0; 95062306a36Sopenharmony_ci} 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_cistatic int ds_w1_init(struct ds_device *dev) 95362306a36Sopenharmony_ci{ 95462306a36Sopenharmony_ci memset(&dev->master, 0, sizeof(struct w1_bus_master)); 95562306a36Sopenharmony_ci 95662306a36Sopenharmony_ci /* Reset the device as it can be in a bad state. 95762306a36Sopenharmony_ci * This is necessary because a block write will wait for data 95862306a36Sopenharmony_ci * to be placed in the output buffer and block any later 95962306a36Sopenharmony_ci * commands which will keep accumulating and the device will 96062306a36Sopenharmony_ci * not be idle. Another case is removing the ds2490 module 96162306a36Sopenharmony_ci * while a bus search is in progress, somehow a few commands 96262306a36Sopenharmony_ci * get through, but the input transfers fail leaving data in 96362306a36Sopenharmony_ci * the input buffer. This will cause the next read to fail 96462306a36Sopenharmony_ci * see the note in ds_recv_data. 96562306a36Sopenharmony_ci */ 96662306a36Sopenharmony_ci ds_reset_device(dev); 96762306a36Sopenharmony_ci 96862306a36Sopenharmony_ci dev->master.data = dev; 96962306a36Sopenharmony_ci dev->master.touch_bit = &ds9490r_touch_bit; 97062306a36Sopenharmony_ci /* read_bit and write_bit in w1_bus_master are expected to set and 97162306a36Sopenharmony_ci * sample the line level. For write_bit that means it is expected to 97262306a36Sopenharmony_ci * set it to that value and leave it there. ds2490 only supports an 97362306a36Sopenharmony_ci * individual time slot at the lowest level. The requirement from 97462306a36Sopenharmony_ci * pulling the bus state down to reading the state is 15us, something 97562306a36Sopenharmony_ci * that isn't realistic on the USB bus anyway. 97662306a36Sopenharmony_ci dev->master.read_bit = &ds9490r_read_bit; 97762306a36Sopenharmony_ci dev->master.write_bit = &ds9490r_write_bit; 97862306a36Sopenharmony_ci */ 97962306a36Sopenharmony_ci dev->master.read_byte = &ds9490r_read_byte; 98062306a36Sopenharmony_ci dev->master.write_byte = &ds9490r_write_byte; 98162306a36Sopenharmony_ci dev->master.read_block = &ds9490r_read_block; 98262306a36Sopenharmony_ci dev->master.write_block = &ds9490r_write_block; 98362306a36Sopenharmony_ci dev->master.reset_bus = &ds9490r_reset; 98462306a36Sopenharmony_ci dev->master.set_pullup = &ds9490r_set_pullup; 98562306a36Sopenharmony_ci dev->master.search = &ds9490r_search; 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci return w1_add_master_device(&dev->master); 98862306a36Sopenharmony_ci} 98962306a36Sopenharmony_ci 99062306a36Sopenharmony_cistatic void ds_w1_fini(struct ds_device *dev) 99162306a36Sopenharmony_ci{ 99262306a36Sopenharmony_ci w1_remove_master_device(&dev->master); 99362306a36Sopenharmony_ci} 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_cistatic int ds_probe(struct usb_interface *intf, 99662306a36Sopenharmony_ci const struct usb_device_id *udev_id) 99762306a36Sopenharmony_ci{ 99862306a36Sopenharmony_ci struct usb_device *udev = interface_to_usbdev(intf); 99962306a36Sopenharmony_ci struct usb_endpoint_descriptor *endpoint; 100062306a36Sopenharmony_ci struct usb_host_interface *iface_desc; 100162306a36Sopenharmony_ci struct ds_device *dev; 100262306a36Sopenharmony_ci int i, err, alt; 100362306a36Sopenharmony_ci 100462306a36Sopenharmony_ci dev = kzalloc(sizeof(struct ds_device), GFP_KERNEL); 100562306a36Sopenharmony_ci if (!dev) 100662306a36Sopenharmony_ci return -ENOMEM; 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci dev->udev = usb_get_dev(udev); 100962306a36Sopenharmony_ci if (!dev->udev) { 101062306a36Sopenharmony_ci err = -ENOMEM; 101162306a36Sopenharmony_ci goto err_out_free; 101262306a36Sopenharmony_ci } 101362306a36Sopenharmony_ci memset(dev->ep, 0, sizeof(dev->ep)); 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci usb_set_intfdata(intf, dev); 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci err = usb_reset_configuration(dev->udev); 101862306a36Sopenharmony_ci if (err) { 101962306a36Sopenharmony_ci dev_err(&dev->udev->dev, 102062306a36Sopenharmony_ci "Failed to reset configuration: err=%d.\n", err); 102162306a36Sopenharmony_ci goto err_out_clear; 102262306a36Sopenharmony_ci } 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci /* alternative 3, 1ms interrupt (greatly speeds search), 64 byte bulk */ 102562306a36Sopenharmony_ci alt = 3; 102662306a36Sopenharmony_ci err = usb_set_interface(dev->udev, 102762306a36Sopenharmony_ci intf->cur_altsetting->desc.bInterfaceNumber, alt); 102862306a36Sopenharmony_ci if (err) { 102962306a36Sopenharmony_ci dev_err(&dev->udev->dev, "Failed to set alternative setting %d " 103062306a36Sopenharmony_ci "for %d interface: err=%d.\n", alt, 103162306a36Sopenharmony_ci intf->cur_altsetting->desc.bInterfaceNumber, err); 103262306a36Sopenharmony_ci goto err_out_clear; 103362306a36Sopenharmony_ci } 103462306a36Sopenharmony_ci 103562306a36Sopenharmony_ci iface_desc = intf->cur_altsetting; 103662306a36Sopenharmony_ci if (iface_desc->desc.bNumEndpoints != NUM_EP-1) { 103762306a36Sopenharmony_ci dev_err(&dev->udev->dev, "Num endpoints=%d. It is not DS9490R.\n", 103862306a36Sopenharmony_ci iface_desc->desc.bNumEndpoints); 103962306a36Sopenharmony_ci err = -EINVAL; 104062306a36Sopenharmony_ci goto err_out_clear; 104162306a36Sopenharmony_ci } 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci /* 104462306a36Sopenharmony_ci * This loop doesn'd show control 0 endpoint, 104562306a36Sopenharmony_ci * so we will fill only 1-3 endpoints entry. 104662306a36Sopenharmony_ci */ 104762306a36Sopenharmony_ci for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { 104862306a36Sopenharmony_ci endpoint = &iface_desc->endpoint[i].desc; 104962306a36Sopenharmony_ci 105062306a36Sopenharmony_ci dev->ep[i+1] = endpoint->bEndpointAddress; 105162306a36Sopenharmony_ci#if 0 105262306a36Sopenharmony_ci printk("%d: addr=%x, size=%d, dir=%s, type=%x\n", 105362306a36Sopenharmony_ci i, endpoint->bEndpointAddress, le16_to_cpu(endpoint->wMaxPacketSize), 105462306a36Sopenharmony_ci (endpoint->bEndpointAddress & USB_DIR_IN)?"IN":"OUT", 105562306a36Sopenharmony_ci endpoint->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK); 105662306a36Sopenharmony_ci#endif 105762306a36Sopenharmony_ci } 105862306a36Sopenharmony_ci 105962306a36Sopenharmony_ci err = ds_w1_init(dev); 106062306a36Sopenharmony_ci if (err) 106162306a36Sopenharmony_ci goto err_out_clear; 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci mutex_lock(&ds_mutex); 106462306a36Sopenharmony_ci list_add_tail(&dev->ds_entry, &ds_devices); 106562306a36Sopenharmony_ci mutex_unlock(&ds_mutex); 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci return 0; 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_cierr_out_clear: 107062306a36Sopenharmony_ci usb_set_intfdata(intf, NULL); 107162306a36Sopenharmony_ci usb_put_dev(dev->udev); 107262306a36Sopenharmony_cierr_out_free: 107362306a36Sopenharmony_ci kfree(dev); 107462306a36Sopenharmony_ci return err; 107562306a36Sopenharmony_ci} 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_cistatic void ds_disconnect(struct usb_interface *intf) 107862306a36Sopenharmony_ci{ 107962306a36Sopenharmony_ci struct ds_device *dev; 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ci dev = usb_get_intfdata(intf); 108262306a36Sopenharmony_ci if (!dev) 108362306a36Sopenharmony_ci return; 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci mutex_lock(&ds_mutex); 108662306a36Sopenharmony_ci list_del(&dev->ds_entry); 108762306a36Sopenharmony_ci mutex_unlock(&ds_mutex); 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_ci ds_w1_fini(dev); 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci usb_set_intfdata(intf, NULL); 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci usb_put_dev(dev->udev); 109462306a36Sopenharmony_ci kfree(dev); 109562306a36Sopenharmony_ci} 109662306a36Sopenharmony_ci 109762306a36Sopenharmony_cistatic const struct usb_device_id ds_id_table[] = { 109862306a36Sopenharmony_ci { USB_DEVICE(0x04fa, 0x2490) }, 109962306a36Sopenharmony_ci { }, 110062306a36Sopenharmony_ci}; 110162306a36Sopenharmony_ciMODULE_DEVICE_TABLE(usb, ds_id_table); 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_cistatic struct usb_driver ds_driver = { 110462306a36Sopenharmony_ci .name = "DS9490R", 110562306a36Sopenharmony_ci .probe = ds_probe, 110662306a36Sopenharmony_ci .disconnect = ds_disconnect, 110762306a36Sopenharmony_ci .id_table = ds_id_table, 110862306a36Sopenharmony_ci}; 110962306a36Sopenharmony_cimodule_usb_driver(ds_driver); 111062306a36Sopenharmony_ci 111162306a36Sopenharmony_ciMODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); 111262306a36Sopenharmony_ciMODULE_DESCRIPTION("DS2490 USB <-> W1 bus master driver (DS9490*)"); 111362306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1114