int brcmf_sdioh_request_byte(struct brcmf_sdio_dev *sdiodev, uint rw, uint func,
			     uint regaddr, u8 *byte)
{
	int err_ret;

	brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x\n", rw, func, regaddr);

	brcmf_pm_resume_wait(sdiodev, &sdiodev->request_byte_wait);
	if (brcmf_pm_resume_error(sdiodev))
		return -EIO;

	if (rw && func == 0) {
		/* handle F0 separately */
		err_ret = brcmf_sdioh_f0_write_byte(sdiodev, regaddr, byte);
	} else {
		sdio_claim_host(sdiodev->func[func]);
		if (rw) /* CMD52 Write */
			sdio_writeb(sdiodev->func[func], *byte, regaddr,
				    &err_ret);
		else if (func == 0) {
			*byte = sdio_f0_readb(sdiodev->func[func], regaddr,
					      &err_ret);
		} else {
			*byte = sdio_readb(sdiodev->func[func], regaddr,
					   &err_ret);
		}
		sdio_release_host(sdiodev->func[func]);
	}

	if (err_ret)
		brcmf_dbg(ERROR, "Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n",
			  rw ? "write" : "read", func, regaddr, *byte, err_ret);

	return err_ret;
}
int brcmf_sdioh_request_word(struct brcmf_sdio_dev *sdiodev,
			     uint rw, uint func, uint addr, u32 *word,
			     uint nbytes)
{
	int err_ret = -EIO;

	if (func == 0) {
		brcmf_dbg(ERROR, "Only CMD52 allowed to F0\n");
		return -EINVAL;
	}

	brcmf_dbg(INFO, "rw=%d, func=%d, addr=0x%05x, nbytes=%d\n",
		  rw, func, addr, nbytes);

	brcmf_pm_resume_wait(sdiodev, &sdiodev->request_word_wait);
	if (brcmf_pm_resume_error(sdiodev))
		return -EIO;
	/* Claim host controller */
	sdio_claim_host(sdiodev->func[func]);

	if (rw) {		/* CMD52 Write */
		if (nbytes == 4)
			sdio_writel(sdiodev->func[func], *word, addr,
				    &err_ret);
		else if (nbytes == 2)
			sdio_writew(sdiodev->func[func], (*word & 0xFFFF),
				    addr, &err_ret);
		else
			brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes);
	} else {		/* CMD52 Read */
		if (nbytes == 4)
			*word = sdio_readl(sdiodev->func[func], addr, &err_ret);
		else if (nbytes == 2)
			*word = sdio_readw(sdiodev->func[func], addr,
					   &err_ret) & 0xFFFF;
		else
			brcmf_dbg(ERROR, "Invalid nbytes: %d\n", nbytes);
	}

	/* Release host controller */
	sdio_release_host(sdiodev->func[func]);

	if (err_ret)
		brcmf_dbg(ERROR, "Failed to %s word, Err: 0x%08x\n",
			  rw ? "write" : "read", err_ret);

	return err_ret;
}
/*
 * This function takes a queue of packets. The packets on the queue
 * are assumed to be properly aligned by the caller.
 */
int
brcmf_sdioh_request_chain(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
			  uint write, uint func, uint addr,
			  struct sk_buff_head *pktq)
{
	bool fifo = (fix_inc == SDIOH_DATA_FIX);
	u32 SGCount = 0;
	int err_ret = 0;

	struct sk_buff *pkt;

	brcmf_dbg(TRACE, "Enter\n");

	brcmf_pm_resume_wait(sdiodev, &sdiodev->request_chain_wait);
	if (brcmf_pm_resume_error(sdiodev))
		return -EIO;

	/* Claim host controller */
	sdio_claim_host(sdiodev->func[func]);

	skb_queue_walk(pktq, pkt) {
		uint pkt_len = pkt->len;
		pkt_len += 3;
		pkt_len &= 0xFFFFFFFC;

		err_ret = brcmf_sdioh_request_data(sdiodev, write, fifo, func,
						   addr, pkt, pkt_len);
		if (err_ret) {
			brcmf_dbg(ERROR, "%s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
				  write ? "TX" : "RX", pkt, SGCount, addr,
				  pkt_len, err_ret);
		} else {
			brcmf_dbg(TRACE, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n",
				  write ? "TX" : "RX", pkt, SGCount, addr,
				  pkt_len);
		}
		if (!fifo)
			addr += pkt_len;

		SGCount++;
	}
/*
 * This function takes a buffer or packet, and fixes everything up
 * so that in the end, a DMA-able packet is created.
 *
 * A buffer does not have an associated packet pointer,
 * and may or may not be aligned.
 * A packet may consist of a single packet, or a packet chain.
 * If it is a packet chain, then all the packets in the chain
 * must be properly aligned.
 *
 * If the packet data is not aligned, then there may only be
 * one packet, and in this case,  it is copied to a new
 * aligned packet.
 *
 */
int brcmf_sdioh_request_buffer(struct brcmf_sdio_dev *sdiodev,
			       uint fix_inc, uint write, uint func, uint addr,
			       uint reg_width, uint buflen_u, u8 *buffer,
			       struct sk_buff *pkt)
{
	int Status;
	struct sk_buff *mypkt = NULL;

	brcmf_dbg(TRACE, "Enter\n");

	brcmf_pm_resume_wait(sdiodev, &sdiodev->request_buffer_wait);
	if (brcmf_pm_resume_error(sdiodev))
		return -EIO;
	/* Case 1: we don't have a packet. */
	if (pkt == NULL) {
		brcmf_dbg(DATA, "Creating new %s Packet, len=%d\n",
			  write ? "TX" : "RX", buflen_u);
		mypkt = brcmu_pkt_buf_get_skb(buflen_u);
		if (!mypkt) {
			brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n",
				  buflen_u);
			return -EIO;
		}

		/* For a write, copy the buffer data into the packet. */
		if (write)
			memcpy(mypkt->data, buffer, buflen_u);

		Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write,
						    func, addr, mypkt);

		/* For a read, copy the packet data back to the buffer. */
		if (!write)
			memcpy(buffer, mypkt->data, buflen_u);

		brcmu_pkt_buf_free_skb(mypkt);
	} else if (((ulong) (pkt->data) & DMA_ALIGN_MASK) != 0) {
		/*
		 * Case 2: We have a packet, but it is unaligned.
		 * In this case, we cannot have a chain (pkt->next == NULL)
		 */
		brcmf_dbg(DATA, "Creating aligned %s Packet, len=%d\n",
			  write ? "TX" : "RX", pkt->len);
		mypkt = brcmu_pkt_buf_get_skb(pkt->len);
		if (!mypkt) {
			brcmf_dbg(ERROR, "brcmu_pkt_buf_get_skb failed: len %d\n",
				  pkt->len);
			return -EIO;
		}

		/* For a write, copy the buffer data into the packet. */
		if (write)
			memcpy(mypkt->data, pkt->data, pkt->len);

		Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write,
						    func, addr, mypkt);

		/* For a read, copy the packet data back to the buffer. */
		if (!write)
			memcpy(pkt->data, mypkt->data, mypkt->len);

		brcmu_pkt_buf_free_skb(mypkt);
	} else {		/* case 3: We have a packet and
				 it is aligned. */
		brcmf_dbg(DATA, "Aligned %s Packet, direct DMA\n",
			  write ? "Tx" : "Rx");
		Status = brcmf_sdioh_request_packet(sdiodev, fix_inc, write,
						    func, addr, pkt);
	}

	return Status;
}
static int
brcmf_sdioh_request_packet(struct brcmf_sdio_dev *sdiodev, uint fix_inc,
			   uint write, uint func, uint addr,
			   struct sk_buff *pkt)
{
	bool fifo = (fix_inc == SDIOH_DATA_FIX);
	u32 SGCount = 0;
	int err_ret = 0;

	struct sk_buff *pnext;

	brcmf_dbg(TRACE, "Enter\n");

	brcmf_pm_resume_wait(sdiodev, &sdiodev->request_packet_wait);
	if (brcmf_pm_resume_error(sdiodev))
		return -EIO;

	/* Claim host controller */
	sdio_claim_host(sdiodev->func[func]);
	for (pnext = pkt; pnext; pnext = pnext->next) {
		uint pkt_len = pnext->len;
		pkt_len += 3;
		pkt_len &= 0xFFFFFFFC;

		if ((write) && (!fifo)) {
			err_ret = sdio_memcpy_toio(sdiodev->func[func], addr,
						   ((u8 *) (pnext->data)),
						   pkt_len);
		} else if (write) {
			err_ret = sdio_memcpy_toio(sdiodev->func[func], addr,
						   ((u8 *) (pnext->data)),
						   pkt_len);
		} else if (fifo) {
			err_ret = sdio_readsb(sdiodev->func[func],
					      ((u8 *) (pnext->data)),
					      addr, pkt_len);
		} else {
			err_ret = sdio_memcpy_fromio(sdiodev->func[func],
						     ((u8 *) (pnext->data)),
						     addr, pkt_len);
		}

		if (err_ret) {
			brcmf_dbg(ERROR, "%s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=0x%08x\n",
				  write ? "TX" : "RX", pnext, SGCount, addr,
				  pkt_len, err_ret);
		} else {
			brcmf_dbg(TRACE, "%s xfr'd %p[%d], addr=0x%05x, len=%d\n",
				  write ? "TX" : "RX", pnext, SGCount, addr,
				  pkt_len);
		}

		if (!fifo)
			addr += pkt_len;
		SGCount++;

	}

	/* Release host controller */
	sdio_release_host(sdiodev->func[func]);

	brcmf_dbg(TRACE, "Exit\n");
	return err_ret;
}