Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cfe3e656 authored by Dean Luick's avatar Dean Luick Committed by Doug Ledford
Browse files

staging/rdma/hfi1: Correct TWSI reset



Change the TWSI reset function so it will stop the reset
once the lines are in an expected state.

Reviewed-by: default avatarEaswar Hariharan <easwar.hariharan@intel.com>
Reviewed-by: default avatarDean Luick <dean.luick@intel.com>
Signed-off-by: default avatarPablo Cacho <pablo.cacho@intel.com>
Signed-off-by: default avatarJubin John <jubin.john@intel.com>
Signed-off-by: default avatarDoug Ledford <dledford@redhat.com>
parent 0096765b
Loading
Loading
Loading
Loading
+4 −6
Original line number Original line Diff line number Diff line
@@ -5,7 +5,7 @@
 *
 *
 * GPL LICENSE SUMMARY
 * GPL LICENSE SUMMARY
 *
 *
 * Copyright(c) 2015 Intel Corporation.
 * Copyright(c) 2015, 2016 Intel Corporation.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * it under the terms of version 2 of the GNU General Public License as
@@ -18,7 +18,7 @@
 *
 *
 * BSD LICENSE
 * BSD LICENSE
 *
 *
 * Copyright(c) 2015 Intel Corporation.
 * Copyright(c) 2015, 2016 Intel Corporation.
 *
 *
 * Redistribution and use in source and binary forms, with or without
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * modification, are permitted provided that the following conditions
@@ -106,7 +106,6 @@ int i2c_write(struct hfi1_pportdata *ppd, u32 target, int i2c_addr, int offset,
	if (ret) {
	if (ret) {
		hfi1_dev_porterr(ppd->dd, ppd->port,
		hfi1_dev_porterr(ppd->dd, ppd->port,
				 "I2C write interface reset failed\n");
				 "I2C write interface reset failed\n");
		ret = -EIO;
		goto done;
		goto done;
	}
	}


@@ -179,7 +178,6 @@ int i2c_read(struct hfi1_pportdata *ppd, u32 target, int i2c_addr, int offset,
	if (ret) {
	if (ret) {
		hfi1_dev_porterr(ppd->dd, ppd->port,
		hfi1_dev_porterr(ppd->dd, ppd->port,
				 "I2C read interface reset failed\n");
				 "I2C read interface reset failed\n");
		ret = -EIO;
		goto done;
		goto done;
	}
	}


@@ -213,7 +211,7 @@ int qsfp_write(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
		hfi1_dev_porterr(ppd->dd, ppd->port,
		hfi1_dev_porterr(ppd->dd, ppd->port,
				 "QSFP write interface reset failed\n");
				 "QSFP write interface reset failed\n");
		mutex_unlock(&ppd->dd->qsfp_i2c_mutex);
		mutex_unlock(&ppd->dd->qsfp_i2c_mutex);
		return -EIO;
		return ret;
	}
	}


	while (count < len) {
	while (count < len) {
@@ -279,7 +277,7 @@ int qsfp_read(struct hfi1_pportdata *ppd, u32 target, int addr, void *bp,
		hfi1_dev_porterr(ppd->dd, ppd->port,
		hfi1_dev_porterr(ppd->dd, ppd->port,
				 "QSFP read interface reset failed\n");
				 "QSFP read interface reset failed\n");
		mutex_unlock(&ppd->dd->qsfp_i2c_mutex);
		mutex_unlock(&ppd->dd->qsfp_i2c_mutex);
		return -EIO;
		return ret;
	}
	}


	while (count < len) {
	while (count < len) {
+28 −36
Original line number Original line Diff line number Diff line
@@ -5,7 +5,7 @@
 *
 *
 * GPL LICENSE SUMMARY
 * GPL LICENSE SUMMARY
 *
 *
 * Copyright(c) 2015 Intel Corporation.
 * Copyright(c) 2015, 2016 Intel Corporation.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * it under the terms of version 2 of the GNU General Public License as
@@ -18,7 +18,7 @@
 *
 *
 * BSD LICENSE
 * BSD LICENSE
 *
 *
 * Copyright(c) 2015 Intel Corporation.
 * Copyright(c) 2015, 2016 Intel Corporation.
 *
 *
 * Redistribution and use in source and binary forms, with or without
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * modification, are permitted provided that the following conditions
@@ -136,6 +136,19 @@ static void scl_out(struct hfi1_devdata *dd, u32 target, u8 bit)
	i2c_wait_for_writes(dd, target);
	i2c_wait_for_writes(dd, target);
}
}


static u8 scl_in(struct hfi1_devdata *dd, u32 target, int wait)
{
	u32 read_val, mask;

	mask = QSFP_HFI0_I2CCLK;
	/* SCL is meant to be bare-drain, so never set "OUT", just DIR */
	hfi1_gpio_mod(dd, target, 0, 0, mask);
	read_val = hfi1_gpio_mod(dd, target, 0, 0, 0);
	if (wait)
		i2c_wait_for_writes(dd, target);
	return (read_val & mask) >> GPIO_SCL_NUM;
}

static void sda_out(struct hfi1_devdata *dd, u32 target, u8 bit)
static void sda_out(struct hfi1_devdata *dd, u32 target, u8 bit)
{
{
	u32 mask;
	u32 mask;
@@ -274,13 +287,12 @@ static void stop_cmd(struct hfi1_devdata *dd, u32 target)
/**
/**
 * hfi1_twsi_reset - reset I2C communication
 * hfi1_twsi_reset - reset I2C communication
 * @dd: the hfi1_ib device
 * @dd: the hfi1_ib device
 * returns 0 if ok, -EIO on error
 */
 */

int hfi1_twsi_reset(struct hfi1_devdata *dd, u32 target)
int hfi1_twsi_reset(struct hfi1_devdata *dd, u32 target)
{
{
	int clock_cycles_left = 9;
	int clock_cycles_left = 9;
	int was_high = 0;
	u32 mask;
	u32 pins, mask;


	/* Both SCL and SDA should be high. If not, there
	/* Both SCL and SDA should be high. If not, there
	 * is something wrong.
	 * is something wrong.
@@ -294,43 +306,23 @@ int hfi1_twsi_reset(struct hfi1_devdata *dd, u32 target)
	 */
	 */
	hfi1_gpio_mod(dd, target, 0, 0, mask);
	hfi1_gpio_mod(dd, target, 0, 0, mask);


	/*
	/* Check if SCL is low, if it is low then we have a slave device
	 * Clock nine times to get all listeners into a sane state.
	 * misbehaving and there is not much we can do.
	 * If SDA does not go high at any point, we are wedged.
	 */
	 * One vendor recommends then issuing START followed by STOP.
	if (!scl_in(dd, target, 0))
	 * we cannot use our "normal" functions to do that, because
		return -EIO;
	 * if SCL drops between them, another vendor's part will

	 * wedge, dropping SDA and keeping it low forever, at the end of
	/* Check if SDA is low, if it is low then we have to clock SDA
	 * the next transaction (even if it was not the device addressed).
	 * up to 9 times for the device to release the bus
	 * So our START and STOP take place with SCL held high.
	 */
	 */
	while (clock_cycles_left--) {
	while (clock_cycles_left--) {
		if (sda_in(dd, target, 0))
			return 0;
		scl_out(dd, target, 0);
		scl_out(dd, target, 0);
		scl_out(dd, target, 1);
		scl_out(dd, target, 1);
		/* Note if SDA is high, but keep clocking to sync slave */
		was_high |= sda_in(dd, target, 0);
	}

	if (was_high) {
		/*
		 * We saw a high, which we hope means the slave is sync'd.
		 * Issue START, STOP, pause for T_BUF.
		 */

		pins = hfi1_gpio_mod(dd, target, 0, 0, 0);
		if ((pins & mask) != mask)
			dd_dev_err(dd, "GPIO pins not at rest: %d\n",
				    pins & mask);
		/* Drop SDA to issue START */
		udelay(1); /* Guarantee .6 uSec setup */
		sda_out(dd, target, 0);
		udelay(1); /* Guarantee .6 uSec hold */
		/* At this point, SCL is high, SDA low. Raise SDA for STOP */
		sda_out(dd, target, 1);
		udelay(TWSI_BUF_WAIT_USEC);
	}
	}


	return !was_high;
	return -EIO;
}
}


#define HFI1_TWSI_START 0x100
#define HFI1_TWSI_START 0x100
+4 −3
Original line number Original line Diff line number Diff line
@@ -7,7 +7,7 @@
 *
 *
 * GPL LICENSE SUMMARY
 * GPL LICENSE SUMMARY
 *
 *
 * Copyright(c) 2015 Intel Corporation.
 * Copyright(c) 2015, 2016 Intel Corporation.
 *
 *
 * This program is free software; you can redistribute it and/or modify
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of version 2 of the GNU General Public License as
 * it under the terms of version 2 of the GNU General Public License as
@@ -20,7 +20,7 @@
 *
 *
 * BSD LICENSE
 * BSD LICENSE
 *
 *
 * Copyright(c) 2015 Intel Corporation.
 * Copyright(c) 2015, 2016 Intel Corporation.
 *
 *
 * Redistribution and use in source and binary forms, with or without
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * modification, are permitted provided that the following conditions
@@ -54,8 +54,9 @@


struct hfi1_devdata;
struct hfi1_devdata;


/* Bit position of SDA pin in ASIC_QSFP* registers  */
/* Bit position of SDA/SCL pins in ASIC_QSFP* registers  */
#define  GPIO_SDA_NUM 1
#define  GPIO_SDA_NUM 1
#define  GPIO_SCL_NUM 0


/* these functions must be called with qsfp_lock held */
/* these functions must be called with qsfp_lock held */
int hfi1_twsi_reset(struct hfi1_devdata *dd, u32 target);
int hfi1_twsi_reset(struct hfi1_devdata *dd, u32 target);