Lines Matching +full:4 +full:- +full:data
1 // SPDX-License-Identifier: GPL-2.0
3 // Register map access API - SPI AVMM support
5 // Copyright (C) 2018-2020 Intel Corporation. All rights reserved.
17 * The "SPI slave to Avalon Master Bridge" (spi-avmm) IP should be integrated
34 * Chapter "Avalon-ST Bytes to Packets and Packets to Bytes Converter Cores"
37 * Chapter "Avalon-ST Serial Peripheral Interface Core" describes the
47 * The spi-avmm IP on the slave chip decodes the byte stream and initiates
52 * and finally gets the response value (read out data for register read,
73 #define SPI_AVMM_REG_SIZE 4UL
75 #define SPI_AVMM_VAL_SIZE 4UL
102 * the write request format is: Transaction request header + data
105 * the read response format is: pure data, no Transaction response header
128 * This macro defines the max possible length of the phy data. In the worst
129 * case, all transaction layer bytes need to be escaped (so the data length
130 * doubles), plus 4 special chars (SOP, CHANNEL, CHANNEL_NUM, EOP). Finally
133 #define PHY_TX_MAX ALIGN(2 * TRANS_TX_MAX + 4, 4)
144 * struct spi_avmm_bridge - SPI slave to AVMM bus master bridge
148 * @trans_len: length of valid data in trans_buf.
149 * @phy_len: length of valid data in phy_buf.
150 * @trans_buf: the bridge buffer for transaction layer data.
151 * @phy_buf: the bridge buffer for physical layer data.
152 * @swap_words: the word swapping cb for phy data. NULL if not needed.
171 swab32_array(buf, len / 4); in br_swap_words_32()
175 * Format transaction layer data in br->trans_buf according to the register
176 * access request, Store valid transaction layer data length in br->trans_len.
184 __le32 *data; in br_trans_tx_prepare() local
199 header = (struct trans_req_header *)br->trans_buf; in br_trans_tx_prepare()
200 header->code = code; in br_trans_tx_prepare()
201 header->rsvd = 0; in br_trans_tx_prepare()
202 header->size = cpu_to_be16((u16)count * SPI_AVMM_VAL_SIZE); in br_trans_tx_prepare()
203 header->addr = cpu_to_be32(reg); in br_trans_tx_prepare()
209 if (trans_len > sizeof(br->trans_buf)) in br_trans_tx_prepare()
210 return -ENOMEM; in br_trans_tx_prepare()
212 data = (__le32 *)(br->trans_buf + TRANS_REQ_HD_SIZE); in br_trans_tx_prepare()
215 *data++ = cpu_to_le32(*wr_val++); in br_trans_tx_prepare()
218 /* Store valid trans data length for next layer */ in br_trans_tx_prepare()
219 br->trans_len = trans_len; in br_trans_tx_prepare()
225 * Convert transaction layer data (in br->trans_buf) to phy layer data, store
226 * them in br->phy_buf. Pad the phy_buf aligned with SPI's BPW. Store valid phy
227 * layer data length in br->phy_len.
232 * The driver will not simply pad 4a at the tail. The concern is that driver
233 * will not store MISO data during tx phase, if the driver pads 4a at the tail,
237 * MOSI ...|7a|7c|00|10| |00|00|04|02| |4b|7d|5a|7b| |40|4a|4a|4a| |XX|XX|...
238 * MISO ...|4a|4a|4a|4a| |4a|4a|4a|4a| |4a|4a|4a|4a| |4a|7a|7c|00| |78|56|...
242 * before pad ...|7a|7c|00|10| |00|00|04|02| |4b|7d|5a|7b| |40|
243 * after pad ...|7a|7c|00|10| |00|00|04|02| |4b|7d|5a|4a| |4a|4a|7b|40|
253 tb = br->trans_buf; in br_pkt_phy_tx_prepare()
254 tb_end = tb + br->trans_len; in br_pkt_phy_tx_prepare()
255 pb = br->phy_buf; in br_pkt_phy_tx_prepare()
256 pb_limit = pb + ARRAY_SIZE(br->phy_buf); in br_pkt_phy_tx_prepare()
275 if (tb == tb_end - 1 && !pb_eop) { in br_pkt_phy_tx_prepare()
282 * insert an ESCAPE char if the data value equals any special in br_pkt_phy_tx_prepare()
304 /* The phy buffer is used out but transaction layer data remains */ in br_pkt_phy_tx_prepare()
306 return -ENOMEM; in br_pkt_phy_tx_prepare()
308 /* Store valid phy data length for spi transfer */ in br_pkt_phy_tx_prepare()
309 br->phy_len = pb - br->phy_buf; in br_pkt_phy_tx_prepare()
311 if (br->word_len == 1) in br_pkt_phy_tx_prepare()
315 aligned_phy_len = ALIGN(br->phy_len, br->word_len); in br_pkt_phy_tx_prepare()
316 if (aligned_phy_len > sizeof(br->phy_buf)) in br_pkt_phy_tx_prepare()
317 return -ENOMEM; in br_pkt_phy_tx_prepare()
319 if (aligned_phy_len == br->phy_len) in br_pkt_phy_tx_prepare()
323 move_size = pb - pb_eop; in br_pkt_phy_tx_prepare()
324 memmove(&br->phy_buf[aligned_phy_len - move_size], pb_eop, move_size); in br_pkt_phy_tx_prepare()
327 memset(pb_eop, PHY_IDLE, aligned_phy_len - br->phy_len); in br_pkt_phy_tx_prepare()
329 /* update the phy data length */ in br_pkt_phy_tx_prepare()
330 br->phy_len = aligned_phy_len; in br_pkt_phy_tx_prepare()
342 if (br->swap_words) in br_do_tx()
343 br->swap_words(br->phy_buf, br->phy_len); in br_do_tx()
345 /* send all data in phy_buf */ in br_do_tx()
346 return spi_write(br->spi, br->phy_buf, br->phy_len); in br_do_tx()
351 * them to transaction layer data in br->trans_buf. It also stores the length
352 * of rx transaction layer data in br->trans_len
355 * prepare a fixed length buffer to receive all of the rx data in a batch. We
356 * have to read word by word and convert them to transaction layer data at
363 struct device *dev = &br->spi->dev; in br_do_rx_and_pkt_phy_parse()
368 tb_limit = br->trans_buf + ARRAY_SIZE(br->trans_buf); in br_do_rx_and_pkt_phy_parse()
369 pb = br->phy_buf; in br_do_rx_and_pkt_phy_parse()
372 ret = spi_read(br->spi, pb, br->word_len); in br_do_rx_and_pkt_phy_parse()
377 if (br->swap_words) in br_do_rx_and_pkt_phy_parse()
378 br->swap_words(pb, br->word_len); in br_do_rx_and_pkt_phy_parse()
381 for (i = 0; i < br->word_len; i++) { in br_do_rx_and_pkt_phy_parse()
394 * a non-zero channel number is found. in br_do_rx_and_pkt_phy_parse()
400 return -EFAULT; in br_do_rx_and_pkt_phy_parse()
412 tb = br->trans_buf; in br_do_rx_and_pkt_phy_parse()
426 return -EFAULT; in br_do_rx_and_pkt_phy_parse()
432 return -EFAULT; in br_do_rx_and_pkt_phy_parse()
439 return -EFAULT; in br_do_rx_and_pkt_phy_parse()
458 br->trans_len = tb - br->trans_buf; in br_do_rx_and_pkt_phy_parse()
479 return -ETIMEDOUT; in br_do_rx_and_pkt_phy_parse()
493 return -EFAULT; in br_do_rx_and_pkt_phy_parse()
503 unsigned int i, trans_len = br->trans_len; in br_rd_trans_rx_parse()
504 __le32 *data; in br_rd_trans_rx_parse() local
507 return -EFAULT; in br_rd_trans_rx_parse()
509 data = (__le32 *)br->trans_buf; in br_rd_trans_rx_parse()
511 *val++ = le32_to_cpu(*data++); in br_rd_trans_rx_parse()
523 unsigned int trans_len = br->trans_len; in br_wr_trans_rx_parse()
529 return -EFAULT; in br_wr_trans_rx_parse()
531 resp = (struct trans_resp_header *)br->trans_buf; in br_wr_trans_rx_parse()
533 code = resp->r_code ^ 0x80; in br_wr_trans_rx_parse()
534 val_len = be16_to_cpu(resp->size); in br_wr_trans_rx_parse()
536 return -EFAULT; in br_wr_trans_rx_parse()
541 return -EFAULT; in br_wr_trans_rx_parse()
553 br->trans_len = 0; in do_reg_access()
554 br->phy_len = 0; in do_reg_access()
583 return -EINVAL; in regmap_spi_avmm_gather_write()
586 return -EINVAL; in regmap_spi_avmm_gather_write()
592 static int regmap_spi_avmm_write(void *context, const void *data, size_t bytes) in regmap_spi_avmm_write() argument
595 return -EINVAL; in regmap_spi_avmm_write()
597 return regmap_spi_avmm_gather_write(context, data, SPI_AVMM_REG_SIZE, in regmap_spi_avmm_write()
598 data + SPI_AVMM_REG_SIZE, in regmap_spi_avmm_write()
599 bytes - SPI_AVMM_REG_SIZE); in regmap_spi_avmm_write()
607 return -EINVAL; in regmap_spi_avmm_read()
610 return -EINVAL; in regmap_spi_avmm_read()
622 return ERR_PTR(-ENODEV); in spi_avmm_bridge_ctx_gen()
625 spi->mode = SPI_MODE_1; in spi_avmm_bridge_ctx_gen()
626 spi->bits_per_word = 32; in spi_avmm_bridge_ctx_gen()
628 spi->bits_per_word = 8; in spi_avmm_bridge_ctx_gen()
630 return ERR_PTR(-EINVAL); in spi_avmm_bridge_ctx_gen()
635 return ERR_PTR(-ENOMEM); in spi_avmm_bridge_ctx_gen()
637 br->spi = spi; in spi_avmm_bridge_ctx_gen()
638 br->word_len = spi->bits_per_word / 8; in spi_avmm_bridge_ctx_gen()
639 if (br->word_len == 4) { in spi_avmm_bridge_ctx_gen()
645 br->swap_words = br_swap_words_32; in spi_avmm_bridge_ctx_gen()
679 map = __regmap_init(&spi->dev, ®map_spi_avmm_bus, in __regmap_init_spi_avmm()
702 map = __devm_regmap_init(&spi->dev, ®map_spi_avmm_bus, in __devm_regmap_init_spi_avmm()
713 MODULE_DESCRIPTION("Register map access API - SPI AVMM support");