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