Lines Matching +full:1 +full:br +full:- +full:10

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
79 * it is proper that we limit 1KB xfer at max.
82 #define MAX_WRITE_CNT 1UL
144 * struct spi_avmm_bridge - SPI slave to AVMM bus master bridge
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.
178 static int br_trans_tx_prepare(struct spi_avmm_bridge *br, bool is_read, u32 reg, in br_trans_tx_prepare() argument
188 if (count == 1) in br_trans_tx_prepare()
193 if (count == 1) in br_trans_tx_prepare()
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()
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.
237 * MOSI ...|7a|7c|00|10| |00|00|04|02| |4b|7d|5a|7b| |40|4a|4a|4a| |XX|XX|...
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|
247 static int br_pkt_phy_tx_prepare(struct spi_avmm_bridge *br) in br_pkt_phy_tx_prepare() argument
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()
306 return -ENOMEM; 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()
314 /* Do phy buf padding if word_len > 1 byte. */ 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()
330 br->phy_len = aligned_phy_len; in br_pkt_phy_tx_prepare()
339 static int br_do_tx(struct spi_avmm_bridge *br) in br_do_tx() argument
342 if (br->swap_words) in br_do_tx()
343 br->swap_words(br->phy_buf, br->phy_len); 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
359 static int br_do_rx_and_pkt_phy_parse(struct spi_avmm_bridge *br) in br_do_rx_and_pkt_phy_parse() argument
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()
500 static int br_rd_trans_rx_parse(struct spi_avmm_bridge *br, in br_rd_trans_rx_parse() argument
503 unsigned int i, trans_len = br->trans_len; in br_rd_trans_rx_parse()
507 return -EFAULT; in br_rd_trans_rx_parse()
509 data = (__le32 *)br->trans_buf; in br_rd_trans_rx_parse()
520 static int br_wr_trans_rx_parse(struct spi_avmm_bridge *br, in br_wr_trans_rx_parse() argument
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()
549 struct spi_avmm_bridge *br = context; in do_reg_access() local
553 br->trans_len = 0; in do_reg_access()
554 br->phy_len = 0; in do_reg_access()
556 ret = br_trans_tx_prepare(br, is_read, reg, value, count); in do_reg_access()
560 ret = br_pkt_phy_tx_prepare(br); in do_reg_access()
564 ret = br_do_tx(br); in do_reg_access()
568 ret = br_do_rx_and_pkt_phy_parse(br); in do_reg_access()
573 return br_rd_trans_rx_parse(br, value, count); in do_reg_access()
575 return br_wr_trans_rx_parse(br, count); in do_reg_access()
583 return -EINVAL; in regmap_spi_avmm_gather_write()
586 return -EINVAL; in regmap_spi_avmm_gather_write()
595 return -EINVAL; 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()
619 struct spi_avmm_bridge *br; in spi_avmm_bridge_ctx_gen() local
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()
633 br = kzalloc(sizeof(*br), GFP_KERNEL); in spi_avmm_bridge_ctx_gen()
634 if (!br) 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()
643 * if word length > 1. in spi_avmm_bridge_ctx_gen()
645 br->swap_words = br_swap_words_32; in spi_avmm_bridge_ctx_gen()
648 return br; in spi_avmm_bridge_ctx_gen()
679 map = __regmap_init(&spi->dev, &regmap_spi_avmm_bus, in __regmap_init_spi_avmm()
702 map = __devm_regmap_init(&spi->dev, &regmap_spi_avmm_bus, in __devm_regmap_init_spi_avmm()
713 MODULE_DESCRIPTION("Register map access API - SPI AVMM support");