mirror of
https://github.com/apache/nuttx.git
synced 2026-06-06 00:14:22 +08:00
Add missing HSCMI configuration options; Make HSMCI configuration naming more compatible; Fix HSCMI clocking to use the CLKODD bit
This commit is contained in:
@@ -7027,3 +7027,7 @@
|
|||||||
Manuel Stühn (2014-3-24).
|
Manuel Stühn (2014-3-24).
|
||||||
* net/netdev_ioctl.c and uip/uip_input.c: IGMP-related bug fixes
|
* net/netdev_ioctl.c and uip/uip_input.c: IGMP-related bug fixes
|
||||||
from Manuel Stühn (2014-3-24).
|
from Manuel Stühn (2014-3-24).
|
||||||
|
* arch/arm/src/sam34: Add missing HSCMI configuration settings to
|
||||||
|
Kconfig; update naming to include SAM34_ (2014-3-24).
|
||||||
|
* configs/sam4e-ek/include/board.h: Update HSMCI timing to use the
|
||||||
|
CLKODD bit (2014-3-24).
|
||||||
|
|||||||
@@ -1131,6 +1131,52 @@ config SAM34_EMAC_ISETH0
|
|||||||
endmenu # EMAC device driver options
|
endmenu # EMAC device driver options
|
||||||
endif # SAM34_EMAC
|
endif # SAM34_EMAC
|
||||||
|
|
||||||
|
if SAM34_HSMCI
|
||||||
|
menu "AT91SAM3/4 HSMCI device driver options"
|
||||||
|
|
||||||
|
config SAM34_HSMCI_RDPROOF
|
||||||
|
bool "Read Proof Enable"
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
Enabling Read Proof allows to stop the HSMCI Clock during read
|
||||||
|
access if the internal FIFO is full. This will guarantee data
|
||||||
|
integrity, not bandwidth.
|
||||||
|
|
||||||
|
config SAM34_HSMCI_WRPROOF
|
||||||
|
bool "Write Proof Enable"
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
Enabling Write Proof allows to stop the HSMCI Clock during write
|
||||||
|
access if the internal FIFO is full. This will guarantee data
|
||||||
|
integrity, not bandwidth.
|
||||||
|
|
||||||
|
config SAM34_HSMCI_XFRDEBUG
|
||||||
|
bool "HSMCI transfer debug"
|
||||||
|
depends on DEBUG_FS && DEBUG_VERBOSE
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
Enable special debug instrumentation analyze HSMCI data transfers.
|
||||||
|
This logic is as non-invasive as possible: It samples HSMCI
|
||||||
|
registers at key points in the data transfer and then dumps all of
|
||||||
|
the registers at the end of the transfer. If DEBUG_DMA is also
|
||||||
|
enabled, then DMA register will be collected as well. Requires also
|
||||||
|
DEBUG_FS and DEBUG_VERBOSE.
|
||||||
|
|
||||||
|
config SAM34_HSMCI_CMDDEBUG
|
||||||
|
bool "HSMCI command debug"
|
||||||
|
depends on DEBUG_FS && DEBUG_VERBOSE
|
||||||
|
default n
|
||||||
|
---help---
|
||||||
|
Enable special debug instrumentation analyze HSMCI commands. This
|
||||||
|
logic is as non-invasive as possible: It samples HSMCI registers at
|
||||||
|
key points in the data transfer and then dumps all of the registers
|
||||||
|
at the end of the transfer. If DEBUG_DMA is also enabled, then DMA
|
||||||
|
register will be collected as well. Requires also DEBUG_FS and
|
||||||
|
DEBUG_VERBOSE.
|
||||||
|
|
||||||
|
endmenu # HSMCI device driver options
|
||||||
|
endif # SAM34_HSMCI
|
||||||
|
|
||||||
if SAM34_UDP
|
if SAM34_UDP
|
||||||
menu "AT91SAM3/4 USB Full Speed Device Controller driver (DCD) options"
|
menu "AT91SAM3/4 USB Full Speed Device Controller driver (DCD) options"
|
||||||
|
|
||||||
|
|||||||
@@ -1216,52 +1216,46 @@ static void sam_req_wrsetup(struct sam_usbdev_s *priv,
|
|||||||
|
|
||||||
/* Get the number of bytes remaining to be sent. */
|
/* Get the number of bytes remaining to be sent. */
|
||||||
|
|
||||||
|
DEBUGASSERT(privreq->req.xfrd < privreq->req.len);
|
||||||
nbytes = privreq->req.len - privreq->req.xfrd;
|
nbytes = privreq->req.len - privreq->req.xfrd;
|
||||||
|
|
||||||
/* If we are not sending a zero length packet, then clip the size to
|
/* Either send the maxpacketsize or all of the remaining data in
|
||||||
* maxpacket and check if we need to send a following zero length packet.
|
* the request.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (nbytes > 0)
|
if (nbytes >= privep->ep.maxpacket)
|
||||||
{
|
{
|
||||||
/* Either send the maxpacketsize or all of the remaining data in
|
nbytes = privep->ep.maxpacket;
|
||||||
* the request.
|
|
||||||
*/
|
|
||||||
|
|
||||||
if (nbytes >= privep->ep.maxpacket)
|
|
||||||
{
|
|
||||||
nbytes = privep->ep.maxpacket;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* This is the new number of bytes "in-flight" */
|
|
||||||
|
|
||||||
privreq->inflight = nbytes;
|
|
||||||
usbtrace(TRACE_WRITE(USB_EPNO(privep->ep.eplog)), nbytes);
|
|
||||||
|
|
||||||
/* The new buffer pointer is the started of the buffer plus the number
|
|
||||||
* of bytes successfully transfered plus the number of bytes previously
|
|
||||||
* "in-flight".
|
|
||||||
*/
|
|
||||||
|
|
||||||
buf = privreq->req.buf + privreq->req.xfrd;
|
|
||||||
|
|
||||||
/* Write packet in the FIFO buffer */
|
|
||||||
|
|
||||||
fifo = (uint8_t *)
|
|
||||||
((uint32_t *)SAM_UDPHSRAM_VSECTION + (EPT_VIRTUAL_SIZE * epno));
|
|
||||||
|
|
||||||
for (; nbytes; nbytes--)
|
|
||||||
{
|
|
||||||
*fifo++ = *buf++;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Indicate that there is data in the TX packet memory. This will
|
|
||||||
* be cleared when the next data out interrupt is received.
|
|
||||||
*/
|
|
||||||
|
|
||||||
privep->epstate = UDPHS_EPSTATE_SENDING;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This is the new number of bytes "in-flight" */
|
||||||
|
|
||||||
|
privreq->inflight = nbytes;
|
||||||
|
usbtrace(TRACE_WRITE(USB_EPNO(privep->ep.eplog)), nbytes);
|
||||||
|
|
||||||
|
/* The new buffer pointer is the started of the buffer plus the number
|
||||||
|
* of bytes successfully transfered plus the number of bytes previously
|
||||||
|
* "in-flight".
|
||||||
|
*/
|
||||||
|
|
||||||
|
buf = privreq->req.buf + privreq->req.xfrd;
|
||||||
|
|
||||||
|
/* Write packet in the FIFO buffer */
|
||||||
|
|
||||||
|
fifo = (uint8_t *)
|
||||||
|
((uint32_t *)SAM_UDPHSRAM_VSECTION + (EPT_VIRTUAL_SIZE * epno));
|
||||||
|
|
||||||
|
for (; nbytes; nbytes--)
|
||||||
|
{
|
||||||
|
*fifo++ = *buf++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Indicate that there is data in the TX packet memory. This will
|
||||||
|
* be cleared when the next data out interrupt is received.
|
||||||
|
*/
|
||||||
|
|
||||||
|
privep->epstate = UDPHS_EPSTATE_SENDING;
|
||||||
|
|
||||||
/* Initiate the transfer and configure to receive the transfer complete
|
/* Initiate the transfer and configure to receive the transfer complete
|
||||||
* interrupt.
|
* interrupt.
|
||||||
*/
|
*/
|
||||||
@@ -1379,7 +1373,8 @@ static int sam_req_write(struct sam_usbdev_s *priv, struct sam_ep_s *privep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* The way that we handle the transfer is going to depend on
|
/* The way that we handle the transfer is going to depend on
|
||||||
* whether or not this endpoint supports DMA.
|
* whether or not this endpoint supports DMA. In either case
|
||||||
|
* the endpoint state will transition to SENDING.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ((SAM_EPSET_DMA & SAM_EP_BIT(epno)) != 0)
|
if ((SAM_EPSET_DMA & SAM_EP_BIT(epno)) != 0)
|
||||||
@@ -1424,21 +1419,22 @@ static int sam_req_write(struct sam_usbdev_s *priv, struct sam_ep_s *privep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* If all of the bytes were sent (including any final zero length
|
/* If all of the bytes were sent (including any final zero length
|
||||||
* packet) then we are finished with the request buffer), then we can
|
* packet) then we are finished with the request buffer and we can
|
||||||
* return the request buffer to the class driver. The transfer is not
|
* return the request buffer to the class driver. The state will
|
||||||
* finished yet, however. There are still bytes in flight. The
|
* remain IDLE only if nothing else was put in flight.
|
||||||
* transfer is truly finished when we are called again and the
|
*
|
||||||
* request buffer is empty.
|
* Note that we will then loop to check to check the next queued
|
||||||
|
* write request.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (privreq->req.len >= privreq->req.xfrd &&
|
if (privep->epstate == UDPHS_EPSTATE_IDLE)
|
||||||
privep->epstate == UDPHS_EPSTATE_IDLE)
|
|
||||||
{
|
{
|
||||||
/* Return the write request to the class driver */
|
/* Return the write request to the class driver */
|
||||||
|
|
||||||
usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)),
|
usbtrace(TRACE_COMPLETE(USB_EPNO(privep->ep.eplog)),
|
||||||
privreq->req.xfrd);
|
privreq->req.xfrd);
|
||||||
|
|
||||||
|
DEBUGASSERT(privreq->req.len == privreq->req.xfrd);
|
||||||
sam_req_complete(privep, OK);
|
sam_req_complete(privep, OK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3577,9 +3573,6 @@ static int sam_ep_submit(struct usbdev_ep_s *ep, struct usbdev_req_s *req)
|
|||||||
epno = USB_EPNO(ep->eplog);
|
epno = USB_EPNO(ep->eplog);
|
||||||
req->result = -EINPROGRESS;
|
req->result = -EINPROGRESS;
|
||||||
req->xfrd = 0;
|
req->xfrd = 0;
|
||||||
privreq->inflight = 0;
|
|
||||||
privep->zlpneeded = false;
|
|
||||||
privep->zlpsent = false;
|
|
||||||
flags = irqsave();
|
flags = irqsave();
|
||||||
|
|
||||||
/* Handle IN (device-to-host) requests. NOTE: If the class device is
|
/* Handle IN (device-to-host) requests. NOTE: If the class device is
|
||||||
|
|||||||
@@ -146,28 +146,28 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef CONFIG_SAM4EEK_120MHZ
|
#ifdef CONFIG_SAM4EEK_120MHZ
|
||||||
/* MCK = 120MHz, CLKDIV = 149, MCI_SPEED = 120MHz / 2 * (149+1) = 400 KHz */
|
/* MCK = 120MHz, CLKDIV = 149 w/o CLKODD, MCI_SPEED = 120MHz / (2*149 + 0 + 2) = 400 KHz */
|
||||||
|
|
||||||
# define HSMCI_INIT_CLKDIV (149 << HSMCI_MR_CLKDIV_SHIFT)
|
# define HSMCI_INIT_CLKDIV (149 << HSMCI_MR_CLKDIV_SHIFT)
|
||||||
|
|
||||||
/* MCK = 120MHz, CLKDIV = 2, MCI_SPEED = 120MHz / 2 * (2+1) = 20 MHz */
|
/* MCK = 120MHz, CLKDIV = 2 w/o CLKODD, MCI_SPEED = 120MHz / (2*2 + 0 + 2) = 20 MHz */
|
||||||
|
|
||||||
# define HSMCI_MMCXFR_CLKDIV (3 << HSMCI_MR_CLKDIV_SHIFT)
|
# define HSMCI_MMCXFR_CLKDIV (3 << HSMCI_MR_CLKDIV_SHIFT)
|
||||||
|
|
||||||
/* MCK = 120MHz, CLKDIV = 2, MCI_SPEED = 120MHz / 2 * (2+1) = 20 MHz */
|
/* MCK = 120MHz, CLKDIV = 1 w/ CLKODD, MCI_SPEED = 120MHz / (2*1 + 1 + 2) = 24 MHz */
|
||||||
|
|
||||||
# define HSMCI_SDXFR_CLKDIV (1 << HSMCI_MR_CLKDIV_SHIFT)
|
# define HSMCI_SDXFR_CLKDIV ((1 << HSMCI_MR_CLKDIV_SHIFT) | HSMCI_MR_CLKODD)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
/* MCK = 96MHz, CLKDIV = 119, MCI_SPEED = 96MHz / 2 * (119+1) = 400 KHz */
|
/* MCK = 96MHz, CLKDIV = 119, w/o CLKODD, MCI_SPEED = 96MHz / (2 * 119 + 0 + 2) = 400 KHz */
|
||||||
|
|
||||||
# define HSMCI_INIT_CLKDIV (119 << HSMCI_MR_CLKDIV_SHIFT)
|
# define HSMCI_INIT_CLKDIV (119 << HSMCI_MR_CLKDIV_SHIFT)
|
||||||
|
|
||||||
/* MCK = 96MHz, CLKDIV = 3, MCI_SPEED = 96MHz / 2 * (3+1) = 12 MHz */
|
/* MCK = 96MHz, CLKDIV = 1 w/ CLKODD, MCI_SPEED = 96MHz / (2*1 + 1 + 2) = 19.2 MHz */
|
||||||
|
|
||||||
# define HSMCI_MMCXFR_CLKDIV (3 << HSMCI_MR_CLKDIV_SHIFT)
|
# define HSMCI_MMCXFR_CLKDIV ((3 << HSMCI_MR_CLKDIV_SHIFT) | HSMCI_MR_CLKODD)
|
||||||
|
|
||||||
/* MCK = 96MHz, CLKDIV = 1, MCI_SPEED = 96MHz / 2 * (1+1) = 24 MHz */
|
/* MCK = 96MHz, CLKDIV = 1 w/o CLKODD, MCI_SPEED = 96MHz / (2*1 + 0 + 2) = 24 MHz */
|
||||||
|
|
||||||
# define HSMCI_SDXFR_CLKDIV (1 << HSMCI_MR_CLKDIV_SHIFT)
|
# define HSMCI_SDXFR_CLKDIV (1 << HSMCI_MR_CLKDIV_SHIFT)
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user