Lines Matching +full:flow +full:- +full:controller

1 // SPDX-License-Identifier: GPL-2.0-only
8 * Christophe Ricard <christophe-h.ricard@st.com>
10 * Maintained by: <tpmdd-devel@lists.sourceforge.net>
42 * TCG SPI flow control is documented in section 6.4 of the spec[1]. In short,
46 * [1] https://trustedcomputinggroup.org/resource/pc-client-platform-tpm-profile-ptp-specification/
54 if ((phy->iobuf[3] & 0x01) == 0) { in tpm_tis_spi_flow_control()
57 spi_xfer->len = 1; in tpm_tis_spi_flow_control()
60 ret = spi_sync_locked(phy->spi_device, &m); in tpm_tis_spi_flow_control()
63 if (phy->iobuf[0] & 0x01) in tpm_tis_spi_flow_control()
68 return -ETIMEDOUT; in tpm_tis_spi_flow_control()
75 * Half duplex controller with support for TPM wait state detection like
76 * Tegra QSPI need CMD, ADDR & DATA sent in single message to manage HW flow
77 * control. Each phase sent in different transfer for controller to idenity
93 phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1); in tpm_tis_spi_transfer_half()
94 phy->iobuf[1] = 0xd4; in tpm_tis_spi_transfer_half()
95 phy->iobuf[2] = addr >> 8; in tpm_tis_spi_transfer_half()
96 phy->iobuf[3] = addr; in tpm_tis_spi_transfer_half()
100 spi_xfer[0].tx_buf = phy->iobuf; in tpm_tis_spi_transfer_half()
104 spi_xfer[1].tx_buf = phy->iobuf + 1; in tpm_tis_spi_transfer_half()
109 spi_xfer[2].tx_buf = &phy->iobuf[4]; in tpm_tis_spi_transfer_half()
111 memcpy(&phy->iobuf[4], out, transfer_len); in tpm_tis_spi_transfer_half()
117 spi_xfer[2].rx_buf = &phy->iobuf[4]; in tpm_tis_spi_transfer_half()
123 reinit_completion(&phy->ready); in tpm_tis_spi_transfer_half()
125 ret = spi_sync(phy->spi_device, &m); in tpm_tis_spi_transfer_half()
130 memcpy(in, &phy->iobuf[4], transfer_len); in tpm_tis_spi_transfer_half()
134 len -= transfer_len; in tpm_tis_spi_transfer_half()
149 spi_bus_lock(phy->spi_device->master); in tpm_tis_spi_transfer_full()
154 phy->iobuf[0] = (in ? 0x80 : 0) | (transfer_len - 1); in tpm_tis_spi_transfer_full()
155 phy->iobuf[1] = 0xd4; in tpm_tis_spi_transfer_full()
156 phy->iobuf[2] = addr >> 8; in tpm_tis_spi_transfer_full()
157 phy->iobuf[3] = addr; in tpm_tis_spi_transfer_full()
160 spi_xfer.tx_buf = phy->iobuf; in tpm_tis_spi_transfer_full()
161 spi_xfer.rx_buf = phy->iobuf; in tpm_tis_spi_transfer_full()
167 ret = spi_sync_locked(phy->spi_device, &m); in tpm_tis_spi_transfer_full()
171 /* Flow control transfers are receive only */ in tpm_tis_spi_transfer_full()
173 ret = phy->flow_control(phy, &spi_xfer); in tpm_tis_spi_transfer_full()
183 spi_xfer.tx_buf = phy->iobuf; in tpm_tis_spi_transfer_full()
185 memcpy(phy->iobuf, out, transfer_len); in tpm_tis_spi_transfer_full()
191 reinit_completion(&phy->ready); in tpm_tis_spi_transfer_full()
192 ret = spi_sync_locked(phy->spi_device, &m); in tpm_tis_spi_transfer_full()
197 memcpy(in, phy->iobuf, transfer_len); in tpm_tis_spi_transfer_full()
201 len -= transfer_len; in tpm_tis_spi_transfer_full()
210 spi_sync_locked(phy->spi_device, &m); in tpm_tis_spi_transfer_full()
213 spi_bus_unlock(phy->spi_device->master); in tpm_tis_spi_transfer_full()
221 struct spi_controller *ctlr = phy->spi_device->controller; in tpm_tis_spi_transfer()
224 * TPM flow control over SPI requires full duplex support. in tpm_tis_spi_transfer()
225 * Send entire message to a half duplex controller to handle in tpm_tis_spi_transfer()
226 * wait polling in controller. in tpm_tis_spi_transfer()
227 * Set TPM HW flow control flag.. in tpm_tis_spi_transfer()
229 if (ctlr->flags & SPI_CONTROLLER_HALF_DUPLEX) in tpm_tis_spi_transfer()
250 phy->iobuf = devm_kmalloc(&spi->dev, MAX_SPI_FRAMESIZE, GFP_KERNEL); in tpm_tis_spi_init()
251 if (!phy->iobuf) in tpm_tis_spi_init()
252 return -ENOMEM; in tpm_tis_spi_init()
254 phy->spi_device = spi; in tpm_tis_spi_init()
256 return tpm_tis_core_init(&spi->dev, &phy->priv, irq, phy_ops, NULL); in tpm_tis_spi_init()
269 phy = devm_kzalloc(&dev->dev, sizeof(struct tpm_tis_spi_phy), in tpm_tis_spi_probe()
272 return -ENOMEM; in tpm_tis_spi_probe()
274 phy->flow_control = tpm_tis_spi_flow_control; in tpm_tis_spi_probe()
276 if (dev->controller->flags & SPI_CONTROLLER_HALF_DUPLEX) in tpm_tis_spi_probe()
277 dev->mode |= SPI_TPM_HW_FLOW; in tpm_tis_spi_probe()
280 if (dev->irq > 0) in tpm_tis_spi_probe()
281 irq = dev->irq; in tpm_tis_spi_probe()
283 irq = -1; in tpm_tis_spi_probe()
285 init_completion(&phy->ready); in tpm_tis_spi_probe()
296 probe_func = of_device_get_match_data(&spi->dev); in tpm_tis_spi_driver_probe()
299 probe_func = (tpm_tis_spi_probe_func)spi_dev_id->driver_data; in tpm_tis_spi_driver_probe()
301 return -ENODEV; in tpm_tis_spi_driver_probe()
320 { "st33htpm-spi", (unsigned long)tpm_tis_spi_probe },
323 { "tpm_tis-spi", (unsigned long)tpm_tis_spi_probe },
330 { .compatible = "st,st33htpm-spi", .data = tpm_tis_spi_probe },
332 { .compatible = "tcg,tpm_tis-spi", .data = tpm_tis_spi_probe },