From 8a6460473f0a31c528617ffde51aa88985725c7a Mon Sep 17 00:00:00 2001 From: asterix Date: Tue, 2 Aug 2011 17:21:18 +0000 Subject: [PATCH] Add first implementation of hsmci controller for sam3x. git-svn-id: https://src.develer.com/svnoss/bertos/trunk@4987 38d2e660-2303-0410-9eaa-f027e97ec537 --- bertos/cpu/cortex-m3/drv/hsmci_sam3.c | 147 ++++++++++++++++++++++++++ bertos/cpu/cortex-m3/drv/hsmci_sam3.h | 78 ++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 bertos/cpu/cortex-m3/drv/hsmci_sam3.c create mode 100644 bertos/cpu/cortex-m3/drv/hsmci_sam3.h diff --git a/bertos/cpu/cortex-m3/drv/hsmci_sam3.c b/bertos/cpu/cortex-m3/drv/hsmci_sam3.c new file mode 100644 index 00000000..13b2f136 --- /dev/null +++ b/bertos/cpu/cortex-m3/drv/hsmci_sam3.c @@ -0,0 +1,147 @@ +/** + * \file + * + * + * \brief HSMCI driver implementation. + * + * \author Daniele Basile + */ + + +#include "hsmci_sam3.h" + +#include +#include +#include + +#include + + + +#define HSMCI_INIT_SPEED 400000 +#define HSMCI_CLK_DIV ((CPU_FREQ / (HSMCI_INIT_SPEED << 1)) - 1) + +#define HSMCI_ERROR_MASK (BV(HSMCI_SR_RINDE) | \ + BV(HSMCI_SR_RDIRE) | \ + BV(HSMCI_SR_RCRCE) | \ + BV(HSMCI_SR_RENDE) | \ + BV(HSMCI_SR_RTOE) | \ + BV(HSMCI_SR_DCRCE) | \ + BV(HSMCI_SR_DTOE) | \ + BV(HSMCI_SR_CSTOE) | \ + BV(HSMCI_SR_BLKOVRE) | \ + BV(HSMCI_SR_ACKRCVE)) + + +#define HSMCI_RESP_ERROR_MASK (BV(HSMCI_SR_RINDE) | BV(HSMCI_SR_RDIRE) \ + | BV(HSMCI_SR_RCRCE)| BV(HSMCI_SR_RENDE)| BV(HSMCI_SR_RTOE)) + + +#define HSMCI_WAIT()\ + do { \ + cpu_relax(); \ + } while (!(HSMCI_SR & (BV(HSMCI_SR_CMDRDY) | BV(HSMCI_SR_NOTBUSY) | BV(HSMCI_SR_XFRDONE)))) + +#define HSMCI_ERROR() (HSMCI_SR & HSMCI_ERROR_MASK) + +#define HSMCI_HW_INIT() \ +do { \ + PIOA_PDR = BV(19) | BV(20) | BV(21) | BV(22) | BV(23) | BV(24); \ + PIO_PERIPH_SEL(PIOA_BASE, BV(19) | BV(20) | BV(21) | BV(22) | BV(23) | BV(24), PIO_PERIPH_A); \ +} while (0) + + +#define STROBE_ON() PIOB_SODR = BV(13) +#define STROBE_OFF() PIOB_CODR = BV(13) +#define STROBE_INIT() \ + do { \ + PIOB_OER = BV(13); \ + PIOB_PER = BV(13); \ + } while(0) + +static DECLARE_ISR(hsmci_irq) +{ + kprintf("irq stato %lx\n", HSMCI_SR); +} + +void hsmci_readResp(void *resp, size_t len) +{ + ASSERT(resp); + uint32_t *r = (uint32_t *)resp; + + kprintf("size %d %d\n",(len / sizeof(HSMCI_RSPR)), sizeof(HSMCI_RSPR)); + for (size_t i = 0; i < (len / sizeof(HSMCI_RSPR)); i++) + r[i] = HSMCI_RSPR; +} + +bool hsmci_sendCmd(uint8_t index, uint32_t argument, uint32_t reply_type) +{ + STROBE_ON(); + HSMCI_WAIT(); + + HSMCI_ARGR = argument; + HSMCI_CMDR = index | reply_type | BV(HSMCI_CMDR_OPDCMD); + + uint32_t status; + do { + status = HSMCI_SR; + if (status & HSMCI_RESP_ERROR_MASK) + return status; + + cpu_relax(); + } while (!(status & (BV(HSMCI_SR_CMDRDY) | BV(HSMCI_SR_NOTBUSY) | BV(HSMCI_SR_XFRDONE)))); + + timer_delay(1); + STROBE_OFF(); + return 0; +} + +void hsmci_init(Hsmci *hsmci) +{ + (void)hsmci; + + HSMCI_HW_INIT(); + STROBE_INIT(); + + pmc_periphEnable(HSMCI_ID); + HSMCI_CR = BV(HSMCI_CR_SWRST); + HSMCI_CR = BV(HSMCI_CR_PWSDIS) | BV(HSMCI_CR_MCIDIS); + HSMCI_IDR = 0xFFFFFFFF; + + HSMCI_DTOR = 0xFF | HSMCI_DTOR_DTOMUL_1048576; + HSMCI_CSTOR = 0xFF | HSMCI_CSTOR_CSTOMUL_1048576; + HSMCI_MR = HSMCI_CLK_DIV | ((0x7u << HSMCI_MR_PWSDIV_SHIFT) & HSMCI_MR_PWSDIV_MASK); + HSMCI_SDCR = 0; + HSMCI_CFG = BV(HSMCI_CFG_FIFOMODE) | BV(HSMCI_CFG_FERRCTRL); + + sysirq_setHandler(INT_HSMCI, hsmci_irq); + HSMCI_CR = BV(HSMCI_CR_MCIEN); + +} diff --git a/bertos/cpu/cortex-m3/drv/hsmci_sam3.h b/bertos/cpu/cortex-m3/drv/hsmci_sam3.h new file mode 100644 index 00000000..4f27843d --- /dev/null +++ b/bertos/cpu/cortex-m3/drv/hsmci_sam3.h @@ -0,0 +1,78 @@ +/** + * \file + * + * + * \brief HSMCI driver functions. + * + * \author Daniele Basile + */ + +#ifndef DRV_HSMCI_SAM3_H +#define DRV_HSMCI_SAM3_H + +#include +#include + +#define CMD8_V_RANGE_CHECK_PAT 0xAA +#define CMD8_V_RANGE_27V_36V (0x100 | CMD8_V_RANGE_CHECK_PAT) +#define CMD8_V_RANGE_LOW (0x1000 | CMD8_V_RANGE_CHECK_PAT) +#define CMD8_V_ECHO_REPLY 0xFF +#define CMD8_SUPP_V_RANGE_REPLY 0xFF00 + + +#define SD_OCR_CCS BV(30) /**< SD Card Capacity Status (CCS) */ +#define SD_OCR_BUSY BV(31) /**< SD/MMC Card power up status bit (busy) */ + +#define SD_OCR_VDD_27_28 BV(15) +#define SD_OCR_VDD_28_29 BV(16) +#define SD_OCR_VDD_29_30 BV(17) +#define SD_OCR_VDD_30_31 BV(18) +#define SD_OCR_VDD_31_32 BV(19) +#define SD_OCR_VDD_32_33 BV(20) + + +#define SD_HOST_VOLTAGE_RANGE (SD_OCR_VDD_27_28 | \ + SD_OCR_VDD_28_29 | \ + SD_OCR_VDD_29_30 | \ + SD_OCR_VDD_30_31 | \ + SD_OCR_VDD_31_32 | \ + SD_OCR_VDD_32_33) + +typedef struct Hsmci +{ +} Hsmci; + +void hsmci_readResp(void *resp, size_t len); +bool hsmci_sendCmd(uint8_t index, uint32_t argument, uint32_t reply_type); + +void hsmci_init(Hsmci *hsmci); + +#endif /* DRV_HSMCI_SAM3_H */ -- 2.25.1