18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2012 Intel Corporation. All rights reserved. 38c2ecf20Sopenharmony_ci * Copyright (c) 2006 - 2012 QLogic Corporation. All rights reserved. 48c2ecf20Sopenharmony_ci * Copyright (c) 2003, 2004, 2005, 2006 PathScale, Inc. All rights reserved. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * This software is available to you under a choice of one of two 78c2ecf20Sopenharmony_ci * licenses. You may choose to be licensed under the terms of the GNU 88c2ecf20Sopenharmony_ci * General Public License (GPL) Version 2, available from the file 98c2ecf20Sopenharmony_ci * COPYING in the main directory of this source tree, or the 108c2ecf20Sopenharmony_ci * OpenIB.org BSD license below: 118c2ecf20Sopenharmony_ci * 128c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or 138c2ecf20Sopenharmony_ci * without modification, are permitted provided that the following 148c2ecf20Sopenharmony_ci * conditions are met: 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * - Redistributions of source code must retain the above 178c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 188c2ecf20Sopenharmony_ci * disclaimer. 198c2ecf20Sopenharmony_ci * 208c2ecf20Sopenharmony_ci * - Redistributions in binary form must reproduce the above 218c2ecf20Sopenharmony_ci * copyright notice, this list of conditions and the following 228c2ecf20Sopenharmony_ci * disclaimer in the documentation and/or other materials 238c2ecf20Sopenharmony_ci * provided with the distribution. 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 268c2ecf20Sopenharmony_ci * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 278c2ecf20Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 288c2ecf20Sopenharmony_ci * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 298c2ecf20Sopenharmony_ci * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 308c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 318c2ecf20Sopenharmony_ci * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 328c2ecf20Sopenharmony_ci * SOFTWARE. 338c2ecf20Sopenharmony_ci */ 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#include <linux/delay.h> 368c2ecf20Sopenharmony_ci#include <linux/pci.h> 378c2ecf20Sopenharmony_ci#include <linux/vmalloc.h> 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci#include "qib.h" 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci/* 428c2ecf20Sopenharmony_ci * QLogic_IB "Two Wire Serial Interface" driver. 438c2ecf20Sopenharmony_ci * Originally written for a not-quite-i2c serial eeprom, which is 448c2ecf20Sopenharmony_ci * still used on some supported boards. Later boards have added a 458c2ecf20Sopenharmony_ci * variety of other uses, most board-specific, so the bit-boffing 468c2ecf20Sopenharmony_ci * part has been split off to this file, while the other parts 478c2ecf20Sopenharmony_ci * have been moved to chip-specific files. 488c2ecf20Sopenharmony_ci * 498c2ecf20Sopenharmony_ci * We have also dropped all pretense of fully generic (e.g. pretend 508c2ecf20Sopenharmony_ci * we don't know whether '1' is the higher voltage) interface, as 518c2ecf20Sopenharmony_ci * the restrictions of the generic i2c interface (e.g. no access from 528c2ecf20Sopenharmony_ci * driver itself) make it unsuitable for this use. 538c2ecf20Sopenharmony_ci */ 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci#define READ_CMD 1 568c2ecf20Sopenharmony_ci#define WRITE_CMD 0 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci/** 598c2ecf20Sopenharmony_ci * i2c_wait_for_writes - wait for a write 608c2ecf20Sopenharmony_ci * @dd: the qlogic_ib device 618c2ecf20Sopenharmony_ci * 628c2ecf20Sopenharmony_ci * We use this instead of udelay directly, so we can make sure 638c2ecf20Sopenharmony_ci * that previous register writes have been flushed all the way 648c2ecf20Sopenharmony_ci * to the chip. Since we are delaying anyway, the cost doesn't 658c2ecf20Sopenharmony_ci * hurt, and makes the bit twiddling more regular 668c2ecf20Sopenharmony_ci */ 678c2ecf20Sopenharmony_cistatic void i2c_wait_for_writes(struct qib_devdata *dd) 688c2ecf20Sopenharmony_ci{ 698c2ecf20Sopenharmony_ci /* 708c2ecf20Sopenharmony_ci * implicit read of EXTStatus is as good as explicit 718c2ecf20Sopenharmony_ci * read of scratch, if all we want to do is flush 728c2ecf20Sopenharmony_ci * writes. 738c2ecf20Sopenharmony_ci */ 748c2ecf20Sopenharmony_ci dd->f_gpio_mod(dd, 0, 0, 0); 758c2ecf20Sopenharmony_ci rmb(); /* inlined, so prevent compiler reordering */ 768c2ecf20Sopenharmony_ci} 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci/* 798c2ecf20Sopenharmony_ci * QSFP modules are allowed to hold SCL low for 500uSec. Allow twice that 808c2ecf20Sopenharmony_ci * for "almost compliant" modules 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_ci#define SCL_WAIT_USEC 1000 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci/* BUF_WAIT is time bus must be free between STOP or ACK and to next START. 858c2ecf20Sopenharmony_ci * Should be 20, but some chips need more. 868c2ecf20Sopenharmony_ci */ 878c2ecf20Sopenharmony_ci#define TWSI_BUF_WAIT_USEC 60 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_cistatic void scl_out(struct qib_devdata *dd, u8 bit) 908c2ecf20Sopenharmony_ci{ 918c2ecf20Sopenharmony_ci u32 mask; 928c2ecf20Sopenharmony_ci 938c2ecf20Sopenharmony_ci udelay(1); 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci mask = 1UL << dd->gpio_scl_num; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci /* SCL is meant to be bare-drain, so never set "OUT", just DIR */ 988c2ecf20Sopenharmony_ci dd->f_gpio_mod(dd, 0, bit ? 0 : mask, mask); 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci /* 1018c2ecf20Sopenharmony_ci * Allow for slow slaves by simple 1028c2ecf20Sopenharmony_ci * delay for falling edge, sampling on rise. 1038c2ecf20Sopenharmony_ci */ 1048c2ecf20Sopenharmony_ci if (!bit) 1058c2ecf20Sopenharmony_ci udelay(2); 1068c2ecf20Sopenharmony_ci else { 1078c2ecf20Sopenharmony_ci int rise_usec; 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_ci for (rise_usec = SCL_WAIT_USEC; rise_usec > 0; rise_usec -= 2) { 1108c2ecf20Sopenharmony_ci if (mask & dd->f_gpio_mod(dd, 0, 0, 0)) 1118c2ecf20Sopenharmony_ci break; 1128c2ecf20Sopenharmony_ci udelay(2); 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci if (rise_usec <= 0) 1158c2ecf20Sopenharmony_ci qib_dev_err(dd, "SCL interface stuck low > %d uSec\n", 1168c2ecf20Sopenharmony_ci SCL_WAIT_USEC); 1178c2ecf20Sopenharmony_ci } 1188c2ecf20Sopenharmony_ci i2c_wait_for_writes(dd); 1198c2ecf20Sopenharmony_ci} 1208c2ecf20Sopenharmony_ci 1218c2ecf20Sopenharmony_cistatic void sda_out(struct qib_devdata *dd, u8 bit) 1228c2ecf20Sopenharmony_ci{ 1238c2ecf20Sopenharmony_ci u32 mask; 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci mask = 1UL << dd->gpio_sda_num; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_ci /* SDA is meant to be bare-drain, so never set "OUT", just DIR */ 1288c2ecf20Sopenharmony_ci dd->f_gpio_mod(dd, 0, bit ? 0 : mask, mask); 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci i2c_wait_for_writes(dd); 1318c2ecf20Sopenharmony_ci udelay(2); 1328c2ecf20Sopenharmony_ci} 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_cistatic u8 sda_in(struct qib_devdata *dd, int wait) 1358c2ecf20Sopenharmony_ci{ 1368c2ecf20Sopenharmony_ci int bnum; 1378c2ecf20Sopenharmony_ci u32 read_val, mask; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci bnum = dd->gpio_sda_num; 1408c2ecf20Sopenharmony_ci mask = (1UL << bnum); 1418c2ecf20Sopenharmony_ci /* SDA is meant to be bare-drain, so never set "OUT", just DIR */ 1428c2ecf20Sopenharmony_ci dd->f_gpio_mod(dd, 0, 0, mask); 1438c2ecf20Sopenharmony_ci read_val = dd->f_gpio_mod(dd, 0, 0, 0); 1448c2ecf20Sopenharmony_ci if (wait) 1458c2ecf20Sopenharmony_ci i2c_wait_for_writes(dd); 1468c2ecf20Sopenharmony_ci return (read_val & mask) >> bnum; 1478c2ecf20Sopenharmony_ci} 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci/** 1508c2ecf20Sopenharmony_ci * i2c_ackrcv - see if ack following write is true 1518c2ecf20Sopenharmony_ci * @dd: the qlogic_ib device 1528c2ecf20Sopenharmony_ci */ 1538c2ecf20Sopenharmony_cistatic int i2c_ackrcv(struct qib_devdata *dd) 1548c2ecf20Sopenharmony_ci{ 1558c2ecf20Sopenharmony_ci u8 ack_received; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci /* AT ENTRY SCL = LOW */ 1588c2ecf20Sopenharmony_ci /* change direction, ignore data */ 1598c2ecf20Sopenharmony_ci ack_received = sda_in(dd, 1); 1608c2ecf20Sopenharmony_ci scl_out(dd, 1); 1618c2ecf20Sopenharmony_ci ack_received = sda_in(dd, 1) == 0; 1628c2ecf20Sopenharmony_ci scl_out(dd, 0); 1638c2ecf20Sopenharmony_ci return ack_received; 1648c2ecf20Sopenharmony_ci} 1658c2ecf20Sopenharmony_ci 1668c2ecf20Sopenharmony_cistatic void stop_cmd(struct qib_devdata *dd); 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci/** 1698c2ecf20Sopenharmony_ci * rd_byte - read a byte, sending STOP on last, else ACK 1708c2ecf20Sopenharmony_ci * @dd: the qlogic_ib device 1718c2ecf20Sopenharmony_ci * 1728c2ecf20Sopenharmony_ci * Returns byte shifted out of device 1738c2ecf20Sopenharmony_ci */ 1748c2ecf20Sopenharmony_cistatic int rd_byte(struct qib_devdata *dd, int last) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci int bit_cntr, data; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci data = 0; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci for (bit_cntr = 7; bit_cntr >= 0; --bit_cntr) { 1818c2ecf20Sopenharmony_ci data <<= 1; 1828c2ecf20Sopenharmony_ci scl_out(dd, 1); 1838c2ecf20Sopenharmony_ci data |= sda_in(dd, 0); 1848c2ecf20Sopenharmony_ci scl_out(dd, 0); 1858c2ecf20Sopenharmony_ci } 1868c2ecf20Sopenharmony_ci if (last) { 1878c2ecf20Sopenharmony_ci scl_out(dd, 1); 1888c2ecf20Sopenharmony_ci stop_cmd(dd); 1898c2ecf20Sopenharmony_ci } else { 1908c2ecf20Sopenharmony_ci sda_out(dd, 0); 1918c2ecf20Sopenharmony_ci scl_out(dd, 1); 1928c2ecf20Sopenharmony_ci scl_out(dd, 0); 1938c2ecf20Sopenharmony_ci sda_out(dd, 1); 1948c2ecf20Sopenharmony_ci } 1958c2ecf20Sopenharmony_ci return data; 1968c2ecf20Sopenharmony_ci} 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci/** 1998c2ecf20Sopenharmony_ci * wr_byte - write a byte, one bit at a time 2008c2ecf20Sopenharmony_ci * @dd: the qlogic_ib device 2018c2ecf20Sopenharmony_ci * @data: the byte to write 2028c2ecf20Sopenharmony_ci * 2038c2ecf20Sopenharmony_ci * Returns 0 if we got the following ack, otherwise 1 2048c2ecf20Sopenharmony_ci */ 2058c2ecf20Sopenharmony_cistatic int wr_byte(struct qib_devdata *dd, u8 data) 2068c2ecf20Sopenharmony_ci{ 2078c2ecf20Sopenharmony_ci int bit_cntr; 2088c2ecf20Sopenharmony_ci u8 bit; 2098c2ecf20Sopenharmony_ci 2108c2ecf20Sopenharmony_ci for (bit_cntr = 7; bit_cntr >= 0; bit_cntr--) { 2118c2ecf20Sopenharmony_ci bit = (data >> bit_cntr) & 1; 2128c2ecf20Sopenharmony_ci sda_out(dd, bit); 2138c2ecf20Sopenharmony_ci scl_out(dd, 1); 2148c2ecf20Sopenharmony_ci scl_out(dd, 0); 2158c2ecf20Sopenharmony_ci } 2168c2ecf20Sopenharmony_ci return (!i2c_ackrcv(dd)) ? 1 : 0; 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci/* 2208c2ecf20Sopenharmony_ci * issue TWSI start sequence: 2218c2ecf20Sopenharmony_ci * (both clock/data high, clock high, data low while clock is high) 2228c2ecf20Sopenharmony_ci */ 2238c2ecf20Sopenharmony_cistatic void start_seq(struct qib_devdata *dd) 2248c2ecf20Sopenharmony_ci{ 2258c2ecf20Sopenharmony_ci sda_out(dd, 1); 2268c2ecf20Sopenharmony_ci scl_out(dd, 1); 2278c2ecf20Sopenharmony_ci sda_out(dd, 0); 2288c2ecf20Sopenharmony_ci udelay(1); 2298c2ecf20Sopenharmony_ci scl_out(dd, 0); 2308c2ecf20Sopenharmony_ci} 2318c2ecf20Sopenharmony_ci 2328c2ecf20Sopenharmony_ci/** 2338c2ecf20Sopenharmony_ci * stop_seq - transmit the stop sequence 2348c2ecf20Sopenharmony_ci * @dd: the qlogic_ib device 2358c2ecf20Sopenharmony_ci * 2368c2ecf20Sopenharmony_ci * (both clock/data low, clock high, data high while clock is high) 2378c2ecf20Sopenharmony_ci */ 2388c2ecf20Sopenharmony_cistatic void stop_seq(struct qib_devdata *dd) 2398c2ecf20Sopenharmony_ci{ 2408c2ecf20Sopenharmony_ci scl_out(dd, 0); 2418c2ecf20Sopenharmony_ci sda_out(dd, 0); 2428c2ecf20Sopenharmony_ci scl_out(dd, 1); 2438c2ecf20Sopenharmony_ci sda_out(dd, 1); 2448c2ecf20Sopenharmony_ci} 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci/** 2478c2ecf20Sopenharmony_ci * stop_cmd - transmit the stop condition 2488c2ecf20Sopenharmony_ci * @dd: the qlogic_ib device 2498c2ecf20Sopenharmony_ci * 2508c2ecf20Sopenharmony_ci * (both clock/data low, clock high, data high while clock is high) 2518c2ecf20Sopenharmony_ci */ 2528c2ecf20Sopenharmony_cistatic void stop_cmd(struct qib_devdata *dd) 2538c2ecf20Sopenharmony_ci{ 2548c2ecf20Sopenharmony_ci stop_seq(dd); 2558c2ecf20Sopenharmony_ci udelay(TWSI_BUF_WAIT_USEC); 2568c2ecf20Sopenharmony_ci} 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci/** 2598c2ecf20Sopenharmony_ci * qib_twsi_reset - reset I2C communication 2608c2ecf20Sopenharmony_ci * @dd: the qlogic_ib device 2618c2ecf20Sopenharmony_ci */ 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ciint qib_twsi_reset(struct qib_devdata *dd) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci int clock_cycles_left = 9; 2668c2ecf20Sopenharmony_ci int was_high = 0; 2678c2ecf20Sopenharmony_ci u32 pins, mask; 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci /* Both SCL and SDA should be high. If not, there 2708c2ecf20Sopenharmony_ci * is something wrong. 2718c2ecf20Sopenharmony_ci */ 2728c2ecf20Sopenharmony_ci mask = (1UL << dd->gpio_scl_num) | (1UL << dd->gpio_sda_num); 2738c2ecf20Sopenharmony_ci 2748c2ecf20Sopenharmony_ci /* 2758c2ecf20Sopenharmony_ci * Force pins to desired innocuous state. 2768c2ecf20Sopenharmony_ci * This is the default power-on state with out=0 and dir=0, 2778c2ecf20Sopenharmony_ci * So tri-stated and should be floating high (barring HW problems) 2788c2ecf20Sopenharmony_ci */ 2798c2ecf20Sopenharmony_ci dd->f_gpio_mod(dd, 0, 0, mask); 2808c2ecf20Sopenharmony_ci 2818c2ecf20Sopenharmony_ci /* 2828c2ecf20Sopenharmony_ci * Clock nine times to get all listeners into a sane state. 2838c2ecf20Sopenharmony_ci * If SDA does not go high at any point, we are wedged. 2848c2ecf20Sopenharmony_ci * One vendor recommends then issuing START followed by STOP. 2858c2ecf20Sopenharmony_ci * we cannot use our "normal" functions to do that, because 2868c2ecf20Sopenharmony_ci * if SCL drops between them, another vendor's part will 2878c2ecf20Sopenharmony_ci * wedge, dropping SDA and keeping it low forever, at the end of 2888c2ecf20Sopenharmony_ci * the next transaction (even if it was not the device addressed). 2898c2ecf20Sopenharmony_ci * So our START and STOP take place with SCL held high. 2908c2ecf20Sopenharmony_ci */ 2918c2ecf20Sopenharmony_ci while (clock_cycles_left--) { 2928c2ecf20Sopenharmony_ci scl_out(dd, 0); 2938c2ecf20Sopenharmony_ci scl_out(dd, 1); 2948c2ecf20Sopenharmony_ci /* Note if SDA is high, but keep clocking to sync slave */ 2958c2ecf20Sopenharmony_ci was_high |= sda_in(dd, 0); 2968c2ecf20Sopenharmony_ci } 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci if (was_high) { 2998c2ecf20Sopenharmony_ci /* 3008c2ecf20Sopenharmony_ci * We saw a high, which we hope means the slave is sync'd. 3018c2ecf20Sopenharmony_ci * Issue START, STOP, pause for T_BUF. 3028c2ecf20Sopenharmony_ci */ 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ci pins = dd->f_gpio_mod(dd, 0, 0, 0); 3058c2ecf20Sopenharmony_ci if ((pins & mask) != mask) 3068c2ecf20Sopenharmony_ci qib_dev_err(dd, "GPIO pins not at rest: %d\n", 3078c2ecf20Sopenharmony_ci pins & mask); 3088c2ecf20Sopenharmony_ci /* Drop SDA to issue START */ 3098c2ecf20Sopenharmony_ci udelay(1); /* Guarantee .6 uSec setup */ 3108c2ecf20Sopenharmony_ci sda_out(dd, 0); 3118c2ecf20Sopenharmony_ci udelay(1); /* Guarantee .6 uSec hold */ 3128c2ecf20Sopenharmony_ci /* At this point, SCL is high, SDA low. Raise SDA for STOP */ 3138c2ecf20Sopenharmony_ci sda_out(dd, 1); 3148c2ecf20Sopenharmony_ci udelay(TWSI_BUF_WAIT_USEC); 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci return !was_high; 3188c2ecf20Sopenharmony_ci} 3198c2ecf20Sopenharmony_ci 3208c2ecf20Sopenharmony_ci#define QIB_TWSI_START 0x100 3218c2ecf20Sopenharmony_ci#define QIB_TWSI_STOP 0x200 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci/* Write byte to TWSI, optionally prefixed with START or suffixed with 3248c2ecf20Sopenharmony_ci * STOP. 3258c2ecf20Sopenharmony_ci * returns 0 if OK (ACK received), else != 0 3268c2ecf20Sopenharmony_ci */ 3278c2ecf20Sopenharmony_cistatic int qib_twsi_wr(struct qib_devdata *dd, int data, int flags) 3288c2ecf20Sopenharmony_ci{ 3298c2ecf20Sopenharmony_ci int ret = 1; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci if (flags & QIB_TWSI_START) 3328c2ecf20Sopenharmony_ci start_seq(dd); 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci ret = wr_byte(dd, data); /* Leaves SCL low (from i2c_ackrcv()) */ 3358c2ecf20Sopenharmony_ci 3368c2ecf20Sopenharmony_ci if (flags & QIB_TWSI_STOP) 3378c2ecf20Sopenharmony_ci stop_cmd(dd); 3388c2ecf20Sopenharmony_ci return ret; 3398c2ecf20Sopenharmony_ci} 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_ci/* Added functionality for IBA7220-based cards */ 3428c2ecf20Sopenharmony_ci#define QIB_TEMP_DEV 0x98 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci/* 3458c2ecf20Sopenharmony_ci * qib_twsi_blk_rd 3468c2ecf20Sopenharmony_ci * Formerly called qib_eeprom_internal_read, and only used for eeprom, 3478c2ecf20Sopenharmony_ci * but now the general interface for data transfer from twsi devices. 3488c2ecf20Sopenharmony_ci * One vestige of its former role is that it recognizes a device 3498c2ecf20Sopenharmony_ci * QIB_TWSI_NO_DEV and does the correct operation for the legacy part, 3508c2ecf20Sopenharmony_ci * which responded to all TWSI device codes, interpreting them as 3518c2ecf20Sopenharmony_ci * address within device. On all other devices found on board handled by 3528c2ecf20Sopenharmony_ci * this driver, the device is followed by a one-byte "address" which selects 3538c2ecf20Sopenharmony_ci * the "register" or "offset" within the device from which data should 3548c2ecf20Sopenharmony_ci * be read. 3558c2ecf20Sopenharmony_ci */ 3568c2ecf20Sopenharmony_ciint qib_twsi_blk_rd(struct qib_devdata *dd, int dev, int addr, 3578c2ecf20Sopenharmony_ci void *buffer, int len) 3588c2ecf20Sopenharmony_ci{ 3598c2ecf20Sopenharmony_ci int ret; 3608c2ecf20Sopenharmony_ci u8 *bp = buffer; 3618c2ecf20Sopenharmony_ci 3628c2ecf20Sopenharmony_ci ret = 1; 3638c2ecf20Sopenharmony_ci 3648c2ecf20Sopenharmony_ci if (dev == QIB_TWSI_NO_DEV) { 3658c2ecf20Sopenharmony_ci /* legacy not-really-I2C */ 3668c2ecf20Sopenharmony_ci addr = (addr << 1) | READ_CMD; 3678c2ecf20Sopenharmony_ci ret = qib_twsi_wr(dd, addr, QIB_TWSI_START); 3688c2ecf20Sopenharmony_ci } else { 3698c2ecf20Sopenharmony_ci /* Actual I2C */ 3708c2ecf20Sopenharmony_ci ret = qib_twsi_wr(dd, dev | WRITE_CMD, QIB_TWSI_START); 3718c2ecf20Sopenharmony_ci if (ret) { 3728c2ecf20Sopenharmony_ci stop_cmd(dd); 3738c2ecf20Sopenharmony_ci ret = 1; 3748c2ecf20Sopenharmony_ci goto bail; 3758c2ecf20Sopenharmony_ci } 3768c2ecf20Sopenharmony_ci /* 3778c2ecf20Sopenharmony_ci * SFF spec claims we do _not_ stop after the addr 3788c2ecf20Sopenharmony_ci * but simply issue a start with the "read" dev-addr. 3798c2ecf20Sopenharmony_ci * Since we are implicitely waiting for ACK here, 3808c2ecf20Sopenharmony_ci * we need t_buf (nominally 20uSec) before that start, 3818c2ecf20Sopenharmony_ci * and cannot rely on the delay built in to the STOP 3828c2ecf20Sopenharmony_ci */ 3838c2ecf20Sopenharmony_ci ret = qib_twsi_wr(dd, addr, 0); 3848c2ecf20Sopenharmony_ci udelay(TWSI_BUF_WAIT_USEC); 3858c2ecf20Sopenharmony_ci 3868c2ecf20Sopenharmony_ci if (ret) { 3878c2ecf20Sopenharmony_ci qib_dev_err(dd, 3888c2ecf20Sopenharmony_ci "Failed to write interface read addr %02X\n", 3898c2ecf20Sopenharmony_ci addr); 3908c2ecf20Sopenharmony_ci ret = 1; 3918c2ecf20Sopenharmony_ci goto bail; 3928c2ecf20Sopenharmony_ci } 3938c2ecf20Sopenharmony_ci ret = qib_twsi_wr(dd, dev | READ_CMD, QIB_TWSI_START); 3948c2ecf20Sopenharmony_ci } 3958c2ecf20Sopenharmony_ci if (ret) { 3968c2ecf20Sopenharmony_ci stop_cmd(dd); 3978c2ecf20Sopenharmony_ci ret = 1; 3988c2ecf20Sopenharmony_ci goto bail; 3998c2ecf20Sopenharmony_ci } 4008c2ecf20Sopenharmony_ci 4018c2ecf20Sopenharmony_ci /* 4028c2ecf20Sopenharmony_ci * block devices keeps clocking data out as long as we ack, 4038c2ecf20Sopenharmony_ci * automatically incrementing the address. Some have "pages" 4048c2ecf20Sopenharmony_ci * whose boundaries will not be crossed, but the handling 4058c2ecf20Sopenharmony_ci * of these is left to the caller, who is in a better 4068c2ecf20Sopenharmony_ci * position to know. 4078c2ecf20Sopenharmony_ci */ 4088c2ecf20Sopenharmony_ci while (len-- > 0) { 4098c2ecf20Sopenharmony_ci /* 4108c2ecf20Sopenharmony_ci * Get and store data, sending ACK if length remaining, 4118c2ecf20Sopenharmony_ci * else STOP 4128c2ecf20Sopenharmony_ci */ 4138c2ecf20Sopenharmony_ci *bp++ = rd_byte(dd, !len); 4148c2ecf20Sopenharmony_ci } 4158c2ecf20Sopenharmony_ci 4168c2ecf20Sopenharmony_ci ret = 0; 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_cibail: 4198c2ecf20Sopenharmony_ci return ret; 4208c2ecf20Sopenharmony_ci} 4218c2ecf20Sopenharmony_ci 4228c2ecf20Sopenharmony_ci/* 4238c2ecf20Sopenharmony_ci * qib_twsi_blk_wr 4248c2ecf20Sopenharmony_ci * Formerly called qib_eeprom_internal_write, and only used for eeprom, 4258c2ecf20Sopenharmony_ci * but now the general interface for data transfer to twsi devices. 4268c2ecf20Sopenharmony_ci * One vestige of its former role is that it recognizes a device 4278c2ecf20Sopenharmony_ci * QIB_TWSI_NO_DEV and does the correct operation for the legacy part, 4288c2ecf20Sopenharmony_ci * which responded to all TWSI device codes, interpreting them as 4298c2ecf20Sopenharmony_ci * address within device. On all other devices found on board handled by 4308c2ecf20Sopenharmony_ci * this driver, the device is followed by a one-byte "address" which selects 4318c2ecf20Sopenharmony_ci * the "register" or "offset" within the device to which data should 4328c2ecf20Sopenharmony_ci * be written. 4338c2ecf20Sopenharmony_ci */ 4348c2ecf20Sopenharmony_ciint qib_twsi_blk_wr(struct qib_devdata *dd, int dev, int addr, 4358c2ecf20Sopenharmony_ci const void *buffer, int len) 4368c2ecf20Sopenharmony_ci{ 4378c2ecf20Sopenharmony_ci int sub_len; 4388c2ecf20Sopenharmony_ci const u8 *bp = buffer; 4398c2ecf20Sopenharmony_ci int max_wait_time, i; 4408c2ecf20Sopenharmony_ci int ret = 1; 4418c2ecf20Sopenharmony_ci 4428c2ecf20Sopenharmony_ci while (len > 0) { 4438c2ecf20Sopenharmony_ci if (dev == QIB_TWSI_NO_DEV) { 4448c2ecf20Sopenharmony_ci if (qib_twsi_wr(dd, (addr << 1) | WRITE_CMD, 4458c2ecf20Sopenharmony_ci QIB_TWSI_START)) { 4468c2ecf20Sopenharmony_ci goto failed_write; 4478c2ecf20Sopenharmony_ci } 4488c2ecf20Sopenharmony_ci } else { 4498c2ecf20Sopenharmony_ci /* Real I2C */ 4508c2ecf20Sopenharmony_ci if (qib_twsi_wr(dd, dev | WRITE_CMD, QIB_TWSI_START)) 4518c2ecf20Sopenharmony_ci goto failed_write; 4528c2ecf20Sopenharmony_ci ret = qib_twsi_wr(dd, addr, 0); 4538c2ecf20Sopenharmony_ci if (ret) { 4548c2ecf20Sopenharmony_ci qib_dev_err(dd, 4558c2ecf20Sopenharmony_ci "Failed to write interface write addr %02X\n", 4568c2ecf20Sopenharmony_ci addr); 4578c2ecf20Sopenharmony_ci goto failed_write; 4588c2ecf20Sopenharmony_ci } 4598c2ecf20Sopenharmony_ci } 4608c2ecf20Sopenharmony_ci 4618c2ecf20Sopenharmony_ci sub_len = min(len, 4); 4628c2ecf20Sopenharmony_ci addr += sub_len; 4638c2ecf20Sopenharmony_ci len -= sub_len; 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci for (i = 0; i < sub_len; i++) 4668c2ecf20Sopenharmony_ci if (qib_twsi_wr(dd, *bp++, 0)) 4678c2ecf20Sopenharmony_ci goto failed_write; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci stop_cmd(dd); 4708c2ecf20Sopenharmony_ci 4718c2ecf20Sopenharmony_ci /* 4728c2ecf20Sopenharmony_ci * Wait for write complete by waiting for a successful 4738c2ecf20Sopenharmony_ci * read (the chip replies with a zero after the write 4748c2ecf20Sopenharmony_ci * cmd completes, and before it writes to the eeprom. 4758c2ecf20Sopenharmony_ci * The startcmd for the read will fail the ack until 4768c2ecf20Sopenharmony_ci * the writes have completed. We do this inline to avoid 4778c2ecf20Sopenharmony_ci * the debug prints that are in the real read routine 4788c2ecf20Sopenharmony_ci * if the startcmd fails. 4798c2ecf20Sopenharmony_ci * We also use the proper device address, so it doesn't matter 4808c2ecf20Sopenharmony_ci * whether we have real eeprom_dev. Legacy likes any address. 4818c2ecf20Sopenharmony_ci */ 4828c2ecf20Sopenharmony_ci max_wait_time = 100; 4838c2ecf20Sopenharmony_ci while (qib_twsi_wr(dd, dev | READ_CMD, QIB_TWSI_START)) { 4848c2ecf20Sopenharmony_ci stop_cmd(dd); 4858c2ecf20Sopenharmony_ci if (!--max_wait_time) 4868c2ecf20Sopenharmony_ci goto failed_write; 4878c2ecf20Sopenharmony_ci } 4888c2ecf20Sopenharmony_ci /* now read (and ignore) the resulting byte */ 4898c2ecf20Sopenharmony_ci rd_byte(dd, 1); 4908c2ecf20Sopenharmony_ci } 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci ret = 0; 4938c2ecf20Sopenharmony_ci goto bail; 4948c2ecf20Sopenharmony_ci 4958c2ecf20Sopenharmony_cifailed_write: 4968c2ecf20Sopenharmony_ci stop_cmd(dd); 4978c2ecf20Sopenharmony_ci ret = 1; 4988c2ecf20Sopenharmony_ci 4998c2ecf20Sopenharmony_cibail: 5008c2ecf20Sopenharmony_ci return ret; 5018c2ecf20Sopenharmony_ci} 502