Ejemplo n.º 1
0
static int __must_check wl12xx_sdio_raw_read(struct device *child, int addr,
					     void *buf, size_t len, bool fixed)
{
	int ret;
	struct wl12xx_sdio_glue *glue = dev_get_drvdata(child->parent);
	struct sdio_func *func = dev_to_sdio_func(glue->dev);

	sdio_claim_host(func);

	if (unlikely(dump)) {
		printk(KERN_DEBUG "wlcore_sdio: READ from 0x%04x\n", addr);
		print_hex_dump(KERN_DEBUG, "wlcore_sdio: READ ",
				DUMP_PREFIX_OFFSET, 16, 1,
				buf, len, false);
	}

	if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG)) {
		((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret);
		dev_dbg(child->parent, "sdio read 52 addr 0x%x, byte 0x%02x\n",
			addr, ((u8 *)buf)[0]);
	} else {
		if (fixed)
			ret = sdio_readsb(func, buf, addr, len);
		else
			ret = sdio_memcpy_fromio(func, buf, addr, len);

		dev_dbg(child->parent, "sdio read 53 addr 0x%x, %zu bytes\n",
			addr, len);
	}

	sdio_release_host(func);

	if (WARN_ON(ret))
		dev_err(child->parent, "sdio read failed (%d)\n", ret);

	return ret;
}
static int msdc_ettagent_read(struct msdc_host *host, unsigned int u4Addr, unsigned int u4Func, void *pBuffer, unsigned int u4Len, unsigned int u4Cmd)
{
    int ret = 0;
    u8 *value = (u8 *) pBuffer;
    struct sdio_func *sdioFunc;

    if((pBuffer==NULL) || (host==NULL))
    {
        printk("[%s] pBuffer = %p, host = %p\n", __func__, pBuffer, host);
        return -1;
    }
        
    if( ((u4Cmd == 53) && (u4Len < 4)) ||
        ((u4Cmd == 52) && (u4Len > 1)) )
    {
        printk("[%s] u4Cmd = %d, u4Len = %d\n", __func__, u4Cmd, u4Len);
        return -1;
    }

    sdioFunc = host->mmc->card->sdio_func[u4Func - 1];

    //sdio_claim_host(sdioFunc);
    if(u4Cmd == 53)
        ret = sdio_readsb(sdioFunc, pBuffer, u4Addr, u4Len);
    else if(u4Cmd == 52)
        *value = sdio_readb(sdioFunc, u4Addr, &ret);
    else
    {
        printk("[%s] Doesn't support u4Cmd = %d\n", __func__, u4Cmd);
        ret = -1;
    }
    //sdio_release_host(sdioFunc);
    
//    printk("Isaac: host->error = %d\n", host->error);

    return ret;
}
Ejemplo n.º 3
0
static void wl1271_sdio_raw_read(struct wl1271 *wl, int addr, void *buf,
				 size_t len, bool fixed)
{
	int ret;
	struct sdio_func *func = wl_to_func(wl);

	if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
		((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret);
		wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x",
			     addr, ((u8 *)buf)[0]);
	} else {
		if (fixed)
			ret = sdio_readsb(func, buf, addr, len);
		else
			ret = sdio_memcpy_fromio(func, buf, addr, len);

		wl1271_debug(DEBUG_SDIO, "sdio read 53 addr 0x%x, %zu bytes",
			     addr, len);
		wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len);
	}

	if (ret)
		wl1271_error("sdio read failed (%d)", ret);
}
Ejemplo n.º 4
0
/*
 * This function reads multiple data from SDIO card memory.
 */
static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *buffer,
				  u32 len, u32 port, u8 claim)
{
	struct sdio_mmc_card *card = adapter->card;
	int ret = -1;
	u8 blk_mode =
		(port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE;
	u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1;
	u32 blk_cnt =
		(blk_mode ==
		 BLOCK_MODE) ? (len / MWIFIEX_SDIO_BLOCK_SIZE) : len;
	u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK);

	if (claim)
		sdio_claim_host(card->func);

	if (!sdio_readsb(card->func, buffer, ioport, blk_cnt * blk_size))
		ret = 0;

	if (claim)
		sdio_release_host(card->func);

	return ret;
}
Ejemplo n.º 5
0
static A_STATUS
__HIFReadWrite(HIF_DEVICE *device,
             A_UINT32 address,
             A_UCHAR *buffer,
             A_UINT32 length,
             A_UINT32 request,
             void *context)
{
    A_UINT8 opcode;
    A_STATUS    status = A_OK;
    int     ret;
    A_UINT8 *tbuffer;
    A_BOOL   bounced = FALSE;

    AR_DEBUG_ASSERT(device != NULL);
    AR_DEBUG_ASSERT(device->func != NULL);

    AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device: 0x%p, buffer:0x%p (addr:0x%X)\n", 
                    device, buffer, address));

    do {
        if (request & HIF_EXTENDED_IO) {
            //AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Command type: CMD53\n"));
        } else {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
                            ("AR6000: Invalid command type: 0x%08x\n", request));
            status = A_EINVAL;
            break;
        }

        if (request & HIF_BLOCK_BASIS) {
            /* round to whole block length size */
            length = (length / HIF_MBOX_BLOCK_SIZE) * HIF_MBOX_BLOCK_SIZE;
            AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
                            ("AR6000: Block mode (BlockLen: %d)\n",
                            length));
        } else if (request & HIF_BYTE_BASIS) {
            AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
                            ("AR6000: Byte mode (BlockLen: %d)\n",
                            length));
        } else {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
                            ("AR6000: Invalid data mode: 0x%08x\n", request));
            status = A_EINVAL;
            break;
        }

#if 0
        /* useful for checking register accesses */
        if (length & 0x3) {
            A_PRINTF(KERN_ALERT"AR6000: HIF (%s) is not a multiple of 4 bytes, addr:0x%X, len:%d\n",
                                request & HIF_WRITE ? "write":"read", address, length);
        }
#endif

        if (request & HIF_WRITE) {
            if ((address >= HIF_MBOX_START_ADDR(0)) &&
                (address <= HIF_MBOX_END_ADDR(3)))
            {
    
                AR_DEBUG_ASSERT(length <= HIF_MBOX_WIDTH);
    
                /*
                 * Mailbox write. Adjust the address so that the last byte
                 * falls on the EOM address.
                 */
                address += (HIF_MBOX_WIDTH - length);
            }
        }

        if (request & HIF_FIXED_ADDRESS) {
            opcode = CMD53_FIXED_ADDRESS;
            AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Fixed 0x%X\n", address));
        } else if (request & HIF_INCREMENTAL_ADDRESS) {
            opcode = CMD53_INCR_ADDRESS;
            AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Address mode: Incremental 0x%X\n", address));
        } else {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
                            ("AR6000: Invalid address mode: 0x%08x\n", request));
            status = A_EINVAL;
            break;
        }

        if (request & HIF_WRITE) {
#if HIF_USE_DMA_BOUNCE_BUFFER
            if (BUFFER_NEEDS_BOUNCE(buffer)) {
                AR_DEBUG_ASSERT(device->dma_buffer != NULL);
                tbuffer = device->dma_buffer;
                    /* copy the write data to the dma buffer */
                AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE);
                memcpy(tbuffer, buffer, length);
                bounced = TRUE;
            } else {
                tbuffer = buffer;    
            }
#else
	        tbuffer = buffer;
#endif
            if (opcode == CMD53_FIXED_ADDRESS) {
                ret = sdio_writesb(device->func, address, tbuffer, length);
                AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writesb ret=%d address: 0x%X, len: %d, 0x%X\n",
						  ret, address, length, *(int *)tbuffer));
            } else {
                ret = sdio_memcpy_toio(device->func, address, tbuffer, length);
                AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: writeio ret=%d address: 0x%X, len: %d, 0x%X\n",
						  ret, address, length, *(int *)tbuffer));
            }
        } else if (request & HIF_READ) {
#if HIF_USE_DMA_BOUNCE_BUFFER
            if (BUFFER_NEEDS_BOUNCE(buffer)) {
                AR_DEBUG_ASSERT(device->dma_buffer != NULL);
                AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE);
                tbuffer = device->dma_buffer;
                bounced = TRUE;
            } else {
                tbuffer = buffer;    
            }
#else
            tbuffer = buffer;
#endif
            if (opcode == CMD53_FIXED_ADDRESS) {
                ret = sdio_readsb(device->func, tbuffer, address, length);
                AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readsb ret=%d address: 0x%X, len: %d, 0x%X\n",
						  ret, address, length, *(int *)tbuffer));
            } else {
                ret = sdio_memcpy_fromio(device->func, tbuffer, address, length);
                AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: readio ret=%d address: 0x%X, len: %d, 0x%X\n",
						  ret, address, length, *(int *)tbuffer));
            }
#if HIF_USE_DMA_BOUNCE_BUFFER
            if (bounced) {
    	           /* copy the read data from the dma buffer */
                memcpy(buffer, tbuffer, length);
            }
#endif
        } else {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
                            ("AR6000: Invalid direction: 0x%08x\n", request));
            status = A_EINVAL;
            break;
        }

        if (ret) {
            AR_DEBUG_PRINTF(ATH_DEBUG_ERROR,
                            ("AR6000: SDIO bus operation failed! MMC stack returned : %d \n", ret));
            status = A_ERROR;
        }
    } while (FALSE);

    return status;
}
/** 
 *  @brief This function reads data from the card.
 *  
 *  @param priv    	A pointer to bt_private structure
 *  @return 	   	BT_STATUS_SUCCESS or BT_STATUS_FAILURE
 */
static int
sd_card_to_host(bt_private * priv)
{
    int ret = BT_STATUS_SUCCESS;
    u16 buf_len = 0;
    int buf_block_len;
    int blksz;
    struct sk_buff *skb = NULL;
    u32 type;
    u8 *payload = NULL;
    struct hci_dev *hdev = priv->bt_dev.hcidev;
    struct sdio_mmc_card *card = priv->bt_dev.card;

    ENTER();

    if (!card || !card->func) {
        PRINTM(ERROR, "card or function is NULL!\n");
        ret = BT_STATUS_FAILURE;
        goto exit;
    }

    /* Read the length of data to be transferred */
    ret = sd_read_rx_len(priv, &buf_len);
    if (ret < 0) {
        PRINTM(ERROR, "card_to_host, read scratch reg failed\n");
        ret = BT_STATUS_FAILURE;
        goto exit;
    }

    /* Allocate buffer */
    blksz = SD_BLOCK_SIZE;
    buf_block_len = (buf_len + blksz - 1) / blksz;
    if (buf_len <= BT_HEADER_LEN || (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
        PRINTM(ERROR, "card_to_host, invalid packet length: %d\n", buf_len);
        ret = BT_STATUS_FAILURE;
        goto exit;
    }
    skb =
        bt_skb_alloc(buf_block_len * blksz + PXA3XX_DMA_ALIGNMENT, GFP_ATOMIC);
    if (skb == NULL) {
        PRINTM(WARN, "No free skb\n");
        goto exit;
    }
    if ((u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1)) {
        skb_put(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1));
        skb_pull(skb, (u32) skb->data & (PXA3XX_DMA_ALIGNMENT - 1));
    }

    payload = skb->tail;
    ret = sdio_readsb(card->func, payload, priv->bt_dev.ioport,
                      buf_block_len * blksz);
    if (ret < 0) {
        PRINTM(ERROR, "card_to_host, read iomem failed: %d\n", ret);
        ret = BT_STATUS_FAILURE;
        goto exit;
    }
    DBG_HEXDUMP(DAT_D, "SDIO Blk Rd", payload, blksz * buf_block_len);
    /* This is SDIO specific header length: byte[2][1][0], type: byte[3]
       (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor) */
    buf_len = payload[0];
    buf_len |= (u16) payload[1] << 8;
    type = payload[3];
    PRINTM(DATA, "SDIO Blk Rd dev%d: len=%d type=%d\n", hdev->id, buf_len,
           type);
    switch (type) {
    case HCI_ACLDATA_PKT:
    case HCI_SCODATA_PKT:
    case HCI_EVENT_PKT:
        bt_cb(skb)->pkt_type = type;
        skb->dev = (void *) hdev;
        skb_put(skb, buf_len);
        skb_pull(skb, BT_HEADER_LEN);
        if (type == HCI_EVENT_PKT)
            check_evtpkt(priv, skb);
        hci_recv_frame(skb);
        hdev->stat.byte_rx += buf_len;
        break;
    case MRVL_VENDOR_PKT:
        bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
        skb->dev = (void *) hdev;
        skb_put(skb, buf_len);
        skb_pull(skb, BT_HEADER_LEN);
        if (BT_STATUS_SUCCESS != bt_process_event(priv, skb))
            hci_recv_frame(skb);
        hdev->stat.byte_rx += buf_len;
        break;
    default:
        /* Driver specified event and command resp should be handle here */
        PRINTM(INFO, "Unknow PKT type:%d\n", type);
        kfree_skb(skb);
        skb = NULL;
        break;
    }
  exit:
    if (ret) {
        hdev->stat.err_rx++;
        if (skb)
            kfree_skb(skb);
    }

    LEAVE();
    return ret;
}
Ejemplo n.º 7
0
int bcmsdio_cmd53(unsigned int offset, int rw, int func, int blk_mode, int opcode, int buflen, char *buff)
{
	struct sdio_func *function = func_data[BCM_SDIO_FN1]->func;
	int ret = -1;
	int count = 0;

	if (function == NULL) {
		BCM_DEBUG_PRINT(ERROR_LEVEL, KERN_ALERT " ***Error: %s %d ***\n", __func__, __LINE__);
		return -ENON_INTF_ERR;
	}

	sdio_claim_host(function);
	if(func_data[BCM_SDIO_FN1]->bremoved) {
		ret = -ENON_INTF_ERR;
		BCM_DEBUG_PRINT(ERROR_LEVEL, KERN_ALERT "Error :%s,%d removed flag var is non-zero :%d \n", __func__, __LINE__,func_data[BCM_SDIO_FN1]->bremoved);
		goto rel_host;
	}

	/* NOTE: blk_mode is not used here. If buflen exceeds corresponding 
	 * block size then SDIO stack will internally convert the request to 
	 * block req
	 * */
	if(buflen%4) {
		int i;
		
		/* Some SDIO controllers don't like CMD53 for 
 		 * request len not-multiple of 4. */
		ret = 0;
		for(i=0; i<buflen; i++) {

			buff[i] = bcmsdio_cmd52_nolock(buff[i], offset, rw, func,&ret);
			if(ret) {
				BCM_DEBUG_PRINT(debuglevel, "FAILED IN INDEX: %d for CMD52 %d rw: %x addr: %x\n", i, ret, rw, offset);
				goto rel_host;
			} else {
				if(opcode) 
					offset++;
			}
		}
	}
	else 
	{
		while( count < SDIO_CMD_RETRIES )
		{
			if(func != BCM_SDIO_FN0)
			{
				if (rw) {
					if (opcode)
						ret = sdio_memcpy_toio(function, offset, buff, buflen);
					else
						ret = sdio_writesb(function, offset, buff, buflen);
				} else {
					if (opcode)
						ret = sdio_memcpy_fromio(function, buff, offset, buflen);
					else
						ret = sdio_readsb(function, buff, offset, buflen);
				}
			}
			else
			{
				ret = bcm_sdio_cmd53(function,rw,offset,opcode,buff,buflen,BCM_SDIO_FN0_BLK_SIZE);
			}

			if(!ret)
				break;
			
			count++;
		}
		
		if(count)
			BCM_DEBUG_PRINT(debuglevel, "Count is higher than 0 for cmd53: %x\n", count);
		
		if(ret)
			BCM_DEBUG_PRINT(debuglevel, "FAILED IN CMD53 %d rw: %x addr: %x count: %x\n", ret, rw, offset, count);
	}
	//BCM_DEBUG_PRINT(debuglevel, KERN_ALERT "cmd53-fn-%d-%d: addr:x%x w:x%x sz:x%x ret:x%x\n", func, function->num, offset, rw, buflen, ret);
rel_host:
	sdio_release_host(function);

	return ret;
}
Ejemplo n.º 8
0
/*----------------------------------------------------------------------------*/
BOOL
kalDevPortRead(IN P_GLUE_INFO_T prGlueInfo,
	       IN UINT_16 u2Port,
	       IN UINT_32 u4Len, OUT PUINT_8 pucBuf, IN UINT_32 u4ValidOutBufSize)
{
	P_GL_HIF_INFO_T prHifInfo = NULL;
	PUINT_8 pucDst = NULL;
	int count = u4Len;
	int ret = 0;
	int bNum = 0;

#if (MTK_WCN_HIF_SDIO == 0)
	struct sdio_func *prSdioFunc = NULL;
#endif

#if DBG
	/* printk(KERN_INFO DRV_NAME"++kalDevPortRead++ buf:0x%p, port:0x%x, length:%d\n", pucBuf, u2Port, u4Len); */
#endif

	ASSERT(prGlueInfo);
	prHifInfo = &prGlueInfo->rHifInfo;

	ASSERT(pucBuf);
	pucDst = pucBuf;

	ASSERT(u4Len <= u4ValidOutBufSize);

#if (MTK_WCN_HIF_SDIO == 0)
	prSdioFunc = prHifInfo->func;

	ASSERT(prSdioFunc->cur_blksize > 0);

	if (!in_interrupt) {
		sdio_claim_host(prSdioFunc);
	}

	/* Split buffer into multiple single block to workaround hifsys */
	while (count >= prSdioFunc->cur_blksize) {
		count -= prSdioFunc->cur_blksize;
		bNum++;
	}
	if (count > 0 && bNum > 0) {
		bNum++;
	}

	if (bNum > 0) {
		ret = sdio_readsb(prSdioFunc, pucDst, u2Port, prSdioFunc->cur_blksize * bNum);

#ifdef CONFIG_X86
		/* ENE workaround */
		{
			int tmp;
			sdio_writel(prSdioFunc, 0x0, SDIO_X86_WORKAROUND_WRITE_MCR, &tmp);
		}
#endif

	} else {
		ret = sdio_readsb(prSdioFunc, pucDst, u2Port, count);
	}

	if (!in_interrupt) {
		sdio_release_host(prSdioFunc);
	}
#else

	/* Split buffer into multiple single block to workaround hifsys */
	while (count >= (prGlueInfo->rHifInfo).prFuncInfo->blk_sz) {
		count -= ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz);
		bNum++;
	}
	if (count > 0 && bNum > 0) {
		bNum++;
	}

	if (bNum > 0) {
		ret =
		    mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucDst,
					      ((prGlueInfo->rHifInfo).prFuncInfo->blk_sz) * bNum);
	} else {
		ret =
		    mtk_wcn_hif_sdio_read_buf(prGlueInfo->rHifInfo.cltCtx, u2Port, (PUINT32) pucDst,
					      count);
	}
#endif

	if (ret) {
		kalSendAeeWarning(HIF_SDIO_ERR_TITLE_STR,
				  HIF_SDIO_ERR_DESC_STR "sdio_readsb() reports error: %x", ret);
		DBGLOG(HAL, ERROR, ("sdio_readsb() reports error: %x", ret));
	}

	return (ret) ? FALSE : TRUE;
}				/* end of kalDevPortRead() */
Ejemplo n.º 9
0
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;
}
Ejemplo n.º 10
0
static int write_data(struct sdio_func *func, u32 addr, void *data
	, u32 size, u32 access_size)
{
	int rv = 0;
	struct sqn_sdio_card *sqn_card = sdio_get_drvdata(func);

	sqn_pr_enter();
	sdio_claim_host(func);

	if (is_good_ahb_address(addr, sqn_card->version)
		&& 0 == (size % 4) && 4 == access_size)
	{
		/* write data using AHB */

		u8 *data_cp = 0;
#ifdef DEBUG
		u8 *read_data  = 0;
#endif

		sqn_pr_dbg("write data using AHB\n");
		sdio_writel(func, addr, SQN_SDIO_ADA_ADDR, &rv);
		if (rv) {
			sqn_pr_dbg("can't set SQN_SDIO_ADA_ADDR register\n");
			goto out;
		}
		sqn_pr_dbg("after SQN_SDIO_ADA_ADDR\n");

		data_cp = kmalloc(size, GFP_KERNEL | GFP_DMA);
		memcpy(data_cp, data, size);
		rv = sdio_writesb(func, SQN_SDIO_ADA_RDWR, data_cp, size);
		if (rv) {
			sqn_pr_dbg("can't write to SQN_SDIO_ADA_RDWR register\n");
			goto out;
		}
		kfree(data_cp);

		/*
		 * Workaround when sdio_writesb doesn't work because DMA
		 * alignment
		 */
		/*
		int i = 0;
		for (; i < size/4; ++i) {
			sdio_writel(func, *((u32*)data + i), SQN_SDIO_ADA_RDWR, &rv);
			if (rv) {
				sqn_pr_dbg("can't write to SQN_SDIO_ADA_RDWR register\n");
				goto out;
			}
		}
		*/

		sqn_pr_dbg("after SQN_SDIO_ADA_RDWR\n");

		/* ******** only for debugging ******** */
		/* validate written data */
/* #ifdef DEBUG */
#if 0
		sqn_pr_dbg("reading data using AHB\n");
		sdio_writel(func, addr, SQN_SDIO_ADA_ADDR, &rv);
		if (rv) {
			sqn_pr_dbg("can't set SQN_SDIO_ADA_ADDR register\n");
			goto out;
		}
		sqn_pr_dbg("after SQN_SDIO_ADA_ADDR\n");

		read_data = kmalloc(size, GFP_KERNEL);
		rv = sdio_readsb(func, read_data, SQN_SDIO_ADA_RDWR, size);
		if (rv) {
			sqn_pr_dbg("can't read from SQN_SDIO_ADA_RDWR register\n");
			kfree(read_data);
			goto out;
		}

		if (memcmp(data, read_data, size))
			sqn_pr_dbg("WARNING: written data are __not__ equal\n");
		else
			sqn_pr_dbg("OK: written data are equal\n");

		kfree(read_data);
#endif /* DEBUG */
		/* ******** only for debugging ******** */

	} else if (4 == access_size && size >= 4) {
		/* write data using CMD53 */
		sqn_pr_dbg("write data using CMD53\n");
		rv = sdio_memcpy_toio(func, addr, data , size);
	} else {
		/* write data using CMD52 */
		/* not implemented yet, so we use CMD53 */
		/* rv = sdio_memcpy_toio(func, addr, data , size); */
		int i = 0;
		sqn_pr_dbg("write data using CMD52\n");
		for (i = 0; i < size; ++i) {
			sdio_writeb(func, *((u8*)data + i), addr + i, &rv);
			if (rv) {
				sqn_pr_dbg("can't write 1 byte to %xh addr using CMD52\n"
					, addr + i);
				goto out;
			}
		}
	}

out:
	sdio_release_host(func);
	sqn_pr_leave();
	return rv;
}
Ejemplo n.º 11
0
/**
 *  @brief This function reads data from the card.
 *
 *  @param priv     A pointer to bt_private structure
 *  @return         BT_STATUS_SUCCESS or BT_STATUS_FAILURE
 */
static int
sd_card_to_host(bt_private *priv)
{
	int ret = BT_STATUS_SUCCESS;
	u16 buf_len = 0;
	int buf_block_len;
	int blksz;
	struct sk_buff *skb = NULL;
	u32 type;
	u8 *payload = NULL;
	struct mbt_dev *mbt_dev = NULL;
	struct m_dev *mdev_bt = &(priv->bt_dev.m_dev[BT_SEQ]);
	struct m_dev *mdev_fm = &(priv->bt_dev.m_dev[FM_SEQ]);
	struct m_dev *mdev_nfc = &(priv->bt_dev.m_dev[NFC_SEQ]);
	struct nfc_dev *nfc_dev =
		(struct nfc_dev *)priv->bt_dev.m_dev[NFC_SEQ].dev_pointer;
	struct fm_dev *fm_dev =
		(struct fm_dev *)priv->bt_dev.m_dev[FM_SEQ].dev_pointer;
	struct m_dev *mdev_debug = &(priv->bt_dev.m_dev[DEBUG_SEQ]);
	struct debug_dev *debug_dev =
		(struct debug_dev *)priv->bt_dev.m_dev[DEBUG_SEQ].dev_pointer;
	struct sdio_mmc_card *card = priv->bt_dev.card;

	ENTER();
	if (priv->bt_dev.m_dev[BT_SEQ].spec_type != BLUEZ_SPEC)
		mbt_dev = (struct mbt_dev *)priv->bt_dev.m_dev[BT_SEQ].dev_pointer;
	if (!card || !card->func) {
		PRINTM(ERROR, "BT: card or function is NULL!\n");
		ret = BT_STATUS_FAILURE;
		goto exit;
	}

	/* Read the length of data to be transferred */
	ret = sd_read_rx_len(priv, &buf_len);
	if (ret < 0) {
		PRINTM(ERROR, "BT: card_to_host, read scratch reg failed\n");
		ret = BT_STATUS_FAILURE;
		goto exit;
	}

	/* Allocate buffer */
	blksz = SD_BLOCK_SIZE;
	buf_block_len = (buf_len + blksz - 1) / blksz;
	if (buf_len <= BT_HEADER_LEN ||
	    (buf_block_len * blksz) > ALLOC_BUF_SIZE) {
		PRINTM(ERROR, "BT: card_to_host, invalid packet length: %d\n",
		       buf_len);
		ret = BT_STATUS_FAILURE;
		goto exit;
	}
	skb = bt_skb_alloc(buf_block_len * blksz + DMA_ALIGNMENT, GFP_ATOMIC);
	if (skb == NULL) {
		PRINTM(WARN, "BT: No free skb\n");
		goto exit;
	}
	if ((t_ptr)skb->data & (DMA_ALIGNMENT - 1)) {
		skb_put(skb,
			DMA_ALIGNMENT -
			((t_ptr)skb->data & (DMA_ALIGNMENT - 1)));
		skb_pull(skb,
			 DMA_ALIGNMENT -
			 ((t_ptr)skb->data & (DMA_ALIGNMENT - 1)));
	}

	payload = skb->data;
	ret = sdio_readsb(card->func, payload, priv->bt_dev.ioport,
			  buf_block_len * blksz);
	if (ret < 0) {
		PRINTM(ERROR, "BT: card_to_host, read iomem failed: %d\n", ret);
		kfree_skb(skb);
		skb = NULL;
		ret = BT_STATUS_FAILURE;
		goto exit;
	}
	/* This is SDIO specific header length: byte[2][1][0], * type: byte[3]
	   (HCI_COMMAND = 1, ACL_DATA = 2, SCO_DATA = 3, 0xFE = Vendor) */
	buf_len = payload[0];
	buf_len |= (u16) payload[1] << 8;
	type = payload[3];
	PRINTM(DATA, "BT: SDIO Blk Rd %s: len=%d type=%d\n", mbt_dev->name,
	       buf_len, type);
	if (buf_len > buf_block_len * blksz) {
		PRINTM(ERROR,
		       "BT: Drop invalid rx pkt, len in hdr=%d, cmd53 length=%d\n",
		       buf_len, buf_block_len * blksz);
		ret = BT_STATUS_FAILURE;
		kfree_skb(skb);
		skb = NULL;
		goto exit;
	}
	DBG_HEXDUMP(DAT_D, "BT: SDIO Blk Rd", payload, buf_len);
	switch (type) {
	case HCI_ACLDATA_PKT:
		bt_cb(skb)->pkt_type = type;
		skb_put(skb, buf_len);
		skb_pull(skb, BT_HEADER_LEN);
		if (mbt_dev) {
			skb->dev = (void *)mdev_bt;
			mdev_recv_frame(skb);
			mdev_bt->stat.byte_rx += buf_len;
		}
		break;
	case HCI_SCODATA_PKT:
		bt_cb(skb)->pkt_type = type;
		skb_put(skb, buf_len);
		skb_pull(skb, BT_HEADER_LEN);
		if (mbt_dev) {
			skb->dev = (void *)mdev_bt;
			mdev_recv_frame(skb);
			mdev_bt->stat.byte_rx += buf_len;
		}
		break;
	case HCI_EVENT_PKT:
		/** add EVT Demux */
		bt_cb(skb)->pkt_type = type;
		skb_put(skb, buf_len);
		skb_pull(skb, BT_HEADER_LEN);
		if (BT_STATUS_SUCCESS == check_evtpkt(priv, skb))
			break;
		switch (skb->data[0]) {
		case 0x0E:
			/** cmd complete */
			if (priv->debug_device_pending) {
				if (priv->debug_ocf_ogf[0] == skb->data[3] &&
				    priv->debug_ocf_ogf[1] == skb->data[4]) {
					priv->debug_device_pending = 0;
					priv->debug_ocf_ogf[0] = 0;
					priv->debug_ocf_ogf[1] = 0;
					/** debug cmd complete */
					if (debug_dev) {
						skb->dev = (void *)mdev_debug;
						mdev_recv_frame(skb);
						mdev_debug->stat.byte_rx +=
							buf_len;
					}
					break;
				}
			}
			if (skb->data[3] == 0x80 && skb->data[4] == 0xFE) {
				/** FM cmd complete */
				if (fm_dev) {
					skb->dev = (void *)mdev_fm;
					mdev_recv_frame(skb);
					mdev_fm->stat.byte_rx += buf_len;
				}
			} else if (skb->data[3] == 0x81 && skb->data[4] == 0xFE) {
				/** NFC cmd complete */
				if (nfc_dev) {
					skb->dev = (void *)mdev_nfc;
					mdev_recv_frame(skb);
					mdev_nfc->stat.byte_rx += buf_len;
				}
			} else {
				if (mbt_dev) {
					skb->dev = (void *)mdev_bt;
					mdev_recv_frame(skb);
					mdev_bt->stat.byte_rx += buf_len;
				}
			}
			break;
		case 0x0F:
			/** cmd status */
			if (skb->data[4] == 0x80 && skb->data[5] == 0xFE) {
				/** FM cmd ststus */
				if (fm_dev) {
					skb->dev = (void *)mdev_fm;
					mdev_recv_frame(skb);
					mdev_fm->stat.byte_rx += buf_len;
				}
			} else if (skb->data[4] == 0x81 && skb->data[5] == 0xFE) {
				/** NFC cmd ststus */
				if (nfc_dev) {
					skb->dev = (void *)mdev_nfc;
					mdev_recv_frame(skb);
					mdev_nfc->stat.byte_rx += buf_len;
				}
			} else {
				/** BT cmd status */
				if (mbt_dev) {
					skb->dev = (void *)mdev_bt;
					mdev_recv_frame(skb);
					mdev_bt->stat.byte_rx += buf_len;
				}
			}
			break;
		case 0xFF:
			/** Vendor specific pkt */
			if (skb->data[2] == 0xC0) {
				/** NFC EVT */
				if (nfc_dev) {
					skb->dev = (void *)mdev_nfc;
					mdev_recv_frame(skb);
					mdev_nfc->stat.byte_rx += buf_len;
				}
			} else if (skb->data[2] >= 0x80 && skb->data[2] <= 0xAF) {
				/** FM EVT */
				if (fm_dev) {
					skb->dev = (void *)mdev_fm;
					mdev_recv_frame(skb);
					mdev_fm->stat.byte_rx += buf_len;
				}
			} else {
				/** BT EVT */
				if (mbt_dev) {
					skb->dev = (void *)mdev_bt;
					mdev_recv_frame(skb);
					mdev_bt->stat.byte_rx += buf_len;
				}
			}
			break;
		default:
			/** BT EVT */
			if (mbt_dev) {
				skb->dev = (void *)mdev_bt;
				mdev_recv_frame(skb);
				mdev_bt->stat.byte_rx += buf_len;
			}
			break;
		}
		break;
	case MRVL_VENDOR_PKT:
		/* Just think here need to back compatible FM */
		bt_cb(skb)->pkt_type = HCI_VENDOR_PKT;
		skb_put(skb, buf_len);
		skb_pull(skb, BT_HEADER_LEN);
		if (mbt_dev) {
			if (BT_STATUS_SUCCESS != bt_process_event(priv, skb)) {
				skb->dev = (void *)mdev_bt;
				mdev_recv_frame(skb);
				mdev_bt->stat.byte_rx += buf_len;
			}
		}

		break;
	default:
		/* Driver specified event and command resp should be handle
		   here */
		PRINTM(INFO, "BT: Unknown PKT type:%d\n", type);
		kfree_skb(skb);
		skb = NULL;
		break;
	}
exit:
	if (ret) {
		if (mbt_dev)
			mdev_bt->stat.err_rx++;
		PRINTM(ERROR, "error when recv pkt!\n");
	}

	LEAVE();
	return ret;
}
Ejemplo n.º 12
0
int sif_io_sync(struct esp_pub *epub, u32 addr, u8 *buf, u32 len, u32 flag)
{
        int err = 0;
        u8 * ibuf = NULL;
        bool need_ibuf = false;
        struct esp_sdio_ctrl *sctrl = NULL;
        struct sdio_func *func = NULL;

	if (epub == NULL || buf == NULL) {
        	ESSERT(0);
		err = -EINVAL;
		goto _exit;
	}

        sctrl = (struct esp_sdio_ctrl *)epub->sif;
        func = sctrl->func;
	if (func == NULL) {
		ESSERT(0);	
		err = -EINVAL;
		goto _exit;
	}

        if (bad_buf(buf)) {
                esp_dbg(ESP_DBG_TRACE, "%s dst 0x%08x, len %d badbuf\n", __func__, addr, len);
                need_ibuf = true;
                ibuf = sctrl->dma_buffer;
        } else {
                ibuf = buf;
        }

        if (flag & SIF_BLOCK_BASIS) {
                /* round up for block data transcation */
        }

        if (flag & SIF_TO_DEVICE) {

                esp_dbg(ESP_DBG_TRACE, "%s to addr 0x%08x, len %d \n", __func__, addr, len);
                if (need_ibuf)
                        memcpy(ibuf, buf, len);

                sdio_claim_host(func);

                if (flag & SIF_FIXED_ADDR)
                        err = sdio_writesb(func, addr, ibuf, len);
                else if (flag & SIF_INC_ADDR) {
                        err = sdio_memcpy_toio(func, addr, ibuf, len);
                }
                sif_platform_check_r1_ready(epub);
                sdio_release_host(func);
        } else if (flag & SIF_FROM_DEVICE) {

                esp_dbg(ESP_DBG_TRACE, "%s from addr 0x%08x, len %d \n", __func__, addr, len);

                sdio_claim_host(func);

                if (flag & SIF_FIXED_ADDR)
                        err = sdio_readsb(func, ibuf, addr, len);
                else if (flag & SIF_INC_ADDR) {
                        err = sdio_memcpy_fromio(func, ibuf, addr, len);
                }

                sdio_release_host(func);

                if (!err && need_ibuf)
                        memcpy(buf, ibuf, len);
        }

_exit:
        return err;
}