aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Huewe <peter.huewe@infineon.com>2017-03-02 08:03:11 -0500
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-05-25 09:44:31 -0400
commitaad1e5c81cbb0617ef544f65d2e4b41fed05484f (patch)
tree5a84c693806a19218d5a6b37b2b1281a09b88007
parentcc0f994c205df817b9ed4a29fd712fa0da82c68b (diff)
tpm_tis_spi: Use single function to transfer data
commit f848f2143ae42dc0918400039257a893835254d1 upstream. The algorithm for sending data to the TPM is mostly identical to the algorithm for receiving data from the TPM, so a single function is sufficient to handle both cases. This is a prequisite for all the other fixes, so we don't have to fix everything twice (send/receive) v2: u16 instead of u8 for the length. Fixes: 0edbfea537d1 ("tpm/tpm_tis_spi: Add support for spi phy") Signed-off-by: Alexander Steffen <Alexander.Steffen@infineon.com> Signed-off-by: Peter Huewe <peter.huewe@infineon.com> Reviewed-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Tested-by: Benoit Houyere <benoit.houyere@st.com> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/char/tpm/tpm_tis_spi.c87
1 files changed, 24 insertions, 63 deletions
diff --git a/drivers/char/tpm/tpm_tis_spi.c b/drivers/char/tpm/tpm_tis_spi.c
index dbaad9c681e3..8341d5f2792c 100644
--- a/drivers/char/tpm/tpm_tis_spi.c
+++ b/drivers/char/tpm/tpm_tis_spi.c
@@ -48,8 +48,8 @@ struct tpm_tis_spi_phy {
48 struct tpm_tis_data priv; 48 struct tpm_tis_data priv;
49 struct spi_device *spi_device; 49 struct spi_device *spi_device;
50 50
51 u8 tx_buf[MAX_SPI_FRAMESIZE + 4]; 51 u8 tx_buf[4];
52 u8 rx_buf[MAX_SPI_FRAMESIZE + 4]; 52 u8 rx_buf[4];
53}; 53};
54 54
55static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data) 55static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data)
@@ -57,8 +57,8 @@ static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *da
57 return container_of(data, struct tpm_tis_spi_phy, priv); 57 return container_of(data, struct tpm_tis_spi_phy, priv);
58} 58}
59 59
60static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr, 60static int tpm_tis_spi_transfer(struct tpm_tis_data *data, u32 addr, u16 len,
61 u16 len, u8 *result) 61 u8 *buffer, u8 direction)
62{ 62{
63 struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); 63 struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data);
64 int ret, i; 64 int ret, i;
@@ -67,17 +67,17 @@ static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
67 .tx_buf = phy->tx_buf, 67 .tx_buf = phy->tx_buf,
68 .rx_buf = phy->rx_buf, 68 .rx_buf = phy->rx_buf,
69 .len = 4, 69 .len = 4,
70 .cs_change = 1,
70 }; 71 };
71 72
72 if (len > MAX_SPI_FRAMESIZE) 73 if (len > MAX_SPI_FRAMESIZE)
73 return -ENOMEM; 74 return -ENOMEM;
74 75
75 phy->tx_buf[0] = 0x80 | (len - 1); 76 phy->tx_buf[0] = direction | (len - 1);
76 phy->tx_buf[1] = 0xd4; 77 phy->tx_buf[1] = 0xd4;
77 phy->tx_buf[2] = (addr >> 8) & 0xFF; 78 phy->tx_buf[2] = addr >> 8;
78 phy->tx_buf[3] = addr & 0xFF; 79 phy->tx_buf[3] = addr;
79 80
80 spi_xfer.cs_change = 1;
81 spi_message_init(&m); 81 spi_message_init(&m);
82 spi_message_add_tail(&spi_xfer, &m); 82 spi_message_add_tail(&spi_xfer, &m);
83 83
@@ -86,7 +86,7 @@ static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
86 if (ret < 0) 86 if (ret < 0)
87 goto exit; 87 goto exit;
88 88
89 memset(phy->tx_buf, 0, len); 89 phy->tx_buf[0] = 0;
90 90
91 /* According to TCG PTP specification, if there is no TPM present at 91 /* According to TCG PTP specification, if there is no TPM present at
92 * all, then the design has a weak pull-up on MISO. If a TPM is not 92 * all, then the design has a weak pull-up on MISO. If a TPM is not
@@ -104,7 +104,14 @@ static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
104 104
105 spi_xfer.cs_change = 0; 105 spi_xfer.cs_change = 0;
106 spi_xfer.len = len; 106 spi_xfer.len = len;
107 spi_xfer.rx_buf = result; 107
108 if (direction) {
109 spi_xfer.tx_buf = NULL;
110 spi_xfer.rx_buf = buffer;
111 } else {
112 spi_xfer.tx_buf = buffer;
113 spi_xfer.rx_buf = NULL;
114 }
108 115
109 spi_message_init(&m); 116 spi_message_init(&m);
110 spi_message_add_tail(&spi_xfer, &m); 117 spi_message_add_tail(&spi_xfer, &m);
@@ -115,62 +122,16 @@ exit:
115 return ret; 122 return ret;
116} 123}
117 124
125static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr,
126 u16 len, u8 *result)
127{
128 return tpm_tis_spi_transfer(data, addr, len, result, 0x80);
129}
130
118static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr, 131static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr,
119 u16 len, u8 *value) 132 u16 len, u8 *value)
120{ 133{
121 struct tpm_tis_spi_phy *phy = to_tpm_tis_spi_phy(data); 134 return tpm_tis_spi_transfer(data, addr, len, value, 0);
122 int ret, i;
123 struct spi_message m;
124 struct spi_transfer spi_xfer = {
125 .tx_buf = phy->tx_buf,
126 .rx_buf = phy->rx_buf,
127 .len = 4,
128 };
129
130 if (len > MAX_SPI_FRAMESIZE)
131 return -ENOMEM;
132
133 phy->tx_buf[0] = len - 1;
134 phy->tx_buf[1] = 0xd4;
135 phy->tx_buf[2] = (addr >> 8) & 0xFF;
136 phy->tx_buf[3] = addr & 0xFF;
137
138 spi_xfer.cs_change = 1;
139 spi_message_init(&m);
140 spi_message_add_tail(&spi_xfer, &m);
141
142 spi_bus_lock(phy->spi_device->master);
143 ret = spi_sync_locked(phy->spi_device, &m);
144 if (ret < 0)
145 goto exit;
146
147 memset(phy->tx_buf, 0, len);
148
149 /* According to TCG PTP specification, if there is no TPM present at
150 * all, then the design has a weak pull-up on MISO. If a TPM is not
151 * present, a pull-up on MISO means that the SB controller sees a 1,
152 * and will latch in 0xFF on the read.
153 */
154 for (i = 0; (phy->rx_buf[0] & 0x01) == 0 && i < TPM_RETRY; i++) {
155 spi_xfer.len = 1;
156 spi_message_init(&m);
157 spi_message_add_tail(&spi_xfer, &m);
158 ret = spi_sync_locked(phy->spi_device, &m);
159 if (ret < 0)
160 goto exit;
161 }
162
163 spi_xfer.len = len;
164 spi_xfer.tx_buf = value;
165 spi_xfer.cs_change = 0;
166 spi_xfer.tx_buf = value;
167 spi_message_init(&m);
168 spi_message_add_tail(&spi_xfer, &m);
169 ret = spi_sync_locked(phy->spi_device, &m);
170
171exit:
172 spi_bus_unlock(phy->spi_device->master);
173 return ret;
174} 135}
175 136
176static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result) 137static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result)