diff options
author | Peter Huewe <peter.huewe@infineon.com> | 2017-03-02 08:03:11 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-05-25 09:44:31 -0400 |
commit | aad1e5c81cbb0617ef544f65d2e4b41fed05484f (patch) | |
tree | 5a84c693806a19218d5a6b37b2b1281a09b88007 | |
parent | cc0f994c205df817b9ed4a29fd712fa0da82c68b (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.c | 87 |
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 | ||
55 | static inline struct tpm_tis_spi_phy *to_tpm_tis_spi_phy(struct tpm_tis_data *data) | 55 | static 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 | ||
60 | static int tpm_tis_spi_read_bytes(struct tpm_tis_data *data, u32 addr, | 60 | static 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 | ||
125 | static 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 | |||
118 | static int tpm_tis_spi_write_bytes(struct tpm_tis_data *data, u32 addr, | 131 | static 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 | |||
171 | exit: | ||
172 | spi_bus_unlock(phy->spi_device->master); | ||
173 | return ret; | ||
174 | } | 135 | } |
175 | 136 | ||
176 | static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result) | 137 | static int tpm_tis_spi_read16(struct tpm_tis_data *data, u32 addr, u16 *result) |